Skip to content

Commit 020cd36

Browse files
nikomatsakisbrson
authored andcommitted
modify x64 assembly and so forth
1 parent d3e8654 commit 020cd36

File tree

4 files changed

+93
-112
lines changed

4 files changed

+93
-112
lines changed

src/rt/arch/x64/_context.S

Lines changed: 76 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,39 @@
11
.text
22

33
/*
4+
According to ABI documentation found at
5+
http://www.x86-64.org/documentation.html
6+
and Microsoft discussion at
7+
http://msdn.microsoft.com/en-US/library/9z1stfyw%28v=VS.80%29.aspx.
8+
9+
BOTH CALLING CONVENTIONS
10+
411
Callee save registers:
5-
ebp, ebx, esi, edi
12+
R12--R15, RDI, RSI, RBX, RBP, RSP
13+
XMM0--XMM5
614
715
Caller save registers:
8-
eax, ecx, edx
16+
RAX, RCX, RDX, R8--R11
17+
XMM6--XMM15
18+
Floating point stack
19+
20+
MAC/AMD CALLING CONVENTIONS
21+
22+
Integer arguments go in registers:
23+
rdi, rsi, rdx, rcx, r8, r9
24+
25+
User flags have no specified role and are not preserved
26+
across calls, with the exception of DF in %rFLAGS,
27+
which must be clear (set to "forward" direction)
28+
on function entry and return.
29+
30+
MICROSOFT CALLING CONVENTIONS
31+
32+
Return value: RAX
33+
34+
First four arguments:
35+
RCX, RDX, R8, R9
36+
XMM0, XMM1, XMM2, XMM3
937
*/
1038

1139
/*
@@ -17,60 +45,55 @@ Caller save registers:
1745
// swap_registers(registers_t *oregs, registers_t *regs)
1846
.globl swap_registers
1947
swap_registers:
20-
// save the old context
21-
movl 4(%esp), %eax
22-
//movl %eax, 0(%eax)
23-
movl %ebx, 4(%eax)
24-
movl %ecx, 8(%eax)
25-
movl %edx, 12(%eax)
26-
movl %ebp, 16(%eax)
27-
movl %esi, 20(%eax)
28-
movl %edi, 24(%eax)
29-
//movl %cs, 32(%eax)
30-
//movl %ds, 34(%eax)
31-
//movl %ss, 36(%eax)
32-
//movl %es, 38(%eax)
33-
//movl %fs, 40(%eax)
34-
//movl %gs, 42(%eax)
35-
36-
// save the flags
37-
pushf
38-
popl %ecx
39-
movl %ecx, 44(%eax)
48+
// n.b. when we enter, the return address is at the top of
49+
// the stack (i.e., 0(%RSP)). We
50+
// simply save all NV registers into oregs.
51+
// We then restore all NV registers from regs. This restores
52+
// the old stack pointer, which should include the proper
53+
// return address. We can therefore just return normally to
54+
// jump back into the old code.
55+
56+
// Save instruction pointer:
57+
popl %rax
58+
movl %rax, 104(%rdi)
4059

41-
// save the return address as the instruction pointer
42-
// and save the stack pointer of the caller
43-
popl %ecx
44-
movl %esp, 28(%eax)
45-
movl %ecx, 48(%eax)
60+
// Save non-volatile integer registers:
61+
// (including RSP)
62+
movl %rbx, 0(%rdi)
63+
movl %rsp, 8(%rdi)
64+
movl %rbp, 16(%rdi)
65+
movl %r12, 24(%rdi)
66+
movl %r13, 32(%rdi)
67+
movl %r14, 40(%rdi)
68+
movl %r15, 48(%rdi)
4669

47-
// restore the new context
48-
movl 4(%esp), %eax
70+
// Save non-volatile XMM registers:
71+
movl %xmm0, 56(%rdi)
72+
movl %xmm1, 64(%rdi)
73+
movl %xmm2, 72(%rdi)
74+
movl %xmm3, 80(%rdi)
75+
movl %xmm4, 88(%rdi)
76+
movl %xmm5, 96(%rdi)
4977

50-
movl 4(%eax), %ebx
51-
// save ecx for later...
52-
movl 12(%eax), %edx
53-
movl 16(%eax), %ebp
54-
movl 20(%eax), %esi
55-
movl 24(%eax), %edi
56-
movl 28(%eax), %esp
57-
// We can't actually change this...
58-
//movl 32(%eax), %cs
59-
//movl 34(%eax), %ds
60-
//movl 36(%eax), %ss
61-
//movl 38(%eax), %es
62-
//movl 40(%eax), %fs
63-
//movl 42(%eax), %gs
78+
// Restore non-volatile integer registers:
79+
// (including RSP)
80+
movl 0(%rsi), %rbx
81+
movl 8(%rsi), %rsp
82+
movl 16(%rsi), %rbp
83+
movl 24(%rsi), %r12
84+
movl 32(%rsi), %r13
85+
movl 40(%rsi), %r14
86+
movl 48(%rsi), %r15
6487

65-
// restore the flags
66-
movl 44(%eax), %ecx
67-
push %ecx
68-
popf
69-
70-
// ok, now we can restore ecx
71-
movl 8(%eax), %ecx
72-
73-
// Return!
74-
jmp *48(%eax)
88+
// Restore non-volatile XMM registers:
89+
movl 56(%rsi), %xmm0
90+
movl 64(%rsi), %xmm1
91+
movl 72(%rsi), %xmm2
92+
movl 80(%rsi), %xmm3
93+
movl 88(%rsi), %xmm4
94+
movl 96(%rsi), %xmm5
7595

96+
// Jump to the instruction pointer
97+
// found in regs:
98+
jmp *104(%rsi)
7699

src/rt/arch/x64/ccall.S

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@ _upcall_call_c_stack:
1111
.globl upcall_call_c_stack
1212
upcall_call_c_stack:
1313
#endif
14-
pushl %ebp
15-
movl %esp,%ebp // save esp
16-
movl 8(%esp),%eax // eax = callee
17-
movl 12(%esp),%esp // switch stack
18-
calll *%eax
19-
movl %ebp,%esp // would like to use "leave" but it's slower
20-
popl %ebp
14+
pushl %rbp
15+
movl %rsp,%rbp // save rsp
16+
movl %rsi,%rsp // switch stack
17+
calll *%rdi
18+
movl %rbp,%rsp // would like to use "leave" but it's slower
19+
popl %rbp
2120
ret
2221

src/rt/arch/x64/context.cpp

Lines changed: 7 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
#include <stdlib.h>
77
#include <assert.h>
88

9-
extern "C" uint32_t CDECL swap_registers(registers_t *oregs,
10-
registers_t *regs)
11-
asm ("swap_registers");
9+
extern "C" void CDECL swap_registers(registers_t *oregs,
10+
registers_t *regs)
11+
asm ("swap_registers");
1212

1313
context::context()
1414
{
@@ -26,48 +26,13 @@ void context::call(void *f, void *arg, void *stack) {
2626
swap(*this);
2727

2828
// set up the trampoline frame
29-
uint32_t *sp = (uint32_t *)stack;
29+
uint64_t *sp = (uint64_t *)stack;
3030

3131
// Shift the stack pointer so the alignment works out right.
3232
sp = align_down(sp) - 3;
33-
*--sp = (uint32_t)arg;
33+
*--sp = (uint64_t)arg;
3434
*--sp = 0xdeadbeef;
3535

36-
regs.esp = (uint32_t)sp;
37-
regs.eip = (uint32_t)f;
36+
regs.regs[1] = (uint64_t)sp;
37+
regs.ip = (uint64_t)f;
3838
}
39-
40-
#if 0
41-
// This is some useful code to check how the registers struct got
42-
// layed out in memory.
43-
int main() {
44-
registers_t regs;
45-
46-
printf("Register offsets\n");
47-
48-
#define REG(r) \
49-
printf(" %6s: +%ld\n", #r, (intptr_t)&regs.r - (intptr_t)&regs);
50-
51-
REG(eax);
52-
REG(ebx);
53-
REG(ecx);
54-
REG(edx);
55-
REG(ebp);
56-
REG(esi);
57-
REG(edi);
58-
REG(esp);
59-
60-
REG(cs);
61-
REG(ds);
62-
REG(ss);
63-
REG(es);
64-
REG(fs);
65-
REG(gs);
66-
67-
REG(eflags);
68-
69-
REG(eip);
70-
71-
return 0;
72-
}
73-
#endif

src/rt/arch/x64/context.h

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,13 @@ T align_down(T sp)
1616
{
1717
// There is no platform we care about that needs more than a
1818
// 16-byte alignment.
19-
return (T)((uint32_t)sp & ~(16 - 1));
19+
return (T)((uint64_t)sp & ~(16 - 1));
2020
}
2121

2222
struct registers_t {
23-
// general purpose registers
24-
uint32_t eax, ebx, ecx, edx, ebp, esi, edi, esp;
25-
26-
// segment registers
27-
uint16_t cs, ds, ss, es, fs, gs;
28-
29-
uint32_t eflags;
30-
31-
uint32_t eip;
23+
uint64_t regs[7]; // Space for the volatile regs: rbx, rsp, rbp, r12:r15
24+
uint64_t xmms[6]; // Space for the volatile regs: xmm0:xmm5
25+
uint64_t ip;
3226
};
3327

3428
class context {

0 commit comments

Comments
 (0)