Skip to content

Commit dd8da21

Browse files
committed
---
yaml --- r: 6212 b: refs/heads/master c: b30a76e h: refs/heads/master v: v3
1 parent 83f8578 commit dd8da21

File tree

5 files changed

+108
-67
lines changed

5 files changed

+108
-67
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: a8c0c2b871a9a0c39a1294327490700104cd0918
2+
refs/heads/master: b30a76ed1b5f5d35560d00a621bf91d6024c478e

trunk/src/rt/arch/x86_64/_context.S

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
.text
1+
#include "x86_64_regs.h"
2+
3+
.text
24

35
/*
46
According to ABI documentation found at
@@ -46,54 +48,68 @@ First four arguments:
4648
.globl swap_registers
4749
swap_registers:
4850
// n.b. when we enter, the return address is at the top of
49-
// the stack (i.e., 0(%RSP)). We
51+
// the stack (i.e., 0(%RSP)) and the argument is in
52+
// RUSTRT_ARG0_S. We
5053
// simply save all NV registers into oregs.
5154
// We then restore all NV registers from regs. This restores
5255
// the old stack pointer, which should include the proper
5356
// return address. We can therefore just return normally to
5457
// jump back into the old code.
58+
59+
# if defined(RUSTRT_ARG0_S)
60+
mov RUSTRT_ARG0_S, %rdi
61+
mov RUSTRT_ARG1_S, %rsi
62+
# endif
5563

5664
// Save instruction pointer:
5765
pop %rax
58-
mov %rax, 56(%rdi)
66+
mov %rax, (RUSTRT_IP*8)(%rdi)
5967

6068
// Save non-volatile integer registers:
6169
// (including RSP)
62-
mov %rbx, 0(%rdi)
63-
mov %rsp, 8(%rdi)
64-
mov %rbp, 16(%rdi)
65-
mov %r12, 24(%rdi)
66-
mov %r13, 32(%rdi)
67-
mov %r14, 40(%rdi)
68-
mov %r15, 48(%rdi)
70+
mov %rbx, (RUSTRT_RBX*8)(%rdi)
71+
mov %rsp, (RUSTRT_RSP*8)(%rdi)
72+
mov %rbp, (RUSTRT_RBP*8)(%rdi)
73+
mov %r12, (RUSTRT_R12*8)(%rdi)
74+
mov %r13, (RUSTRT_R13*8)(%rdi)
75+
mov %r14, (RUSTRT_R14*8)(%rdi)
76+
mov %r15, (RUSTRT_R15*8)(%rdi)
77+
78+
// Save relevant argument registers:
79+
mov %rcx, (RUSTRT_RCX*8)(%rdi)
80+
mov %rdi, (RUSTRT_RDI*8)(%rdi)
6981

7082
// Save non-volatile XMM registers:
71-
movapd %xmm0, 64(%rdi)
72-
movapd %xmm1, 80(%rdi)
73-
movapd %xmm2, 96(%rdi)
74-
movapd %xmm3, 112(%rdi)
75-
movapd %xmm4, 128(%rdi)
76-
movapd %xmm5, 144(%rdi)
83+
movapd %xmm0, (RUSTRT_XMM0*8)(%rdi)
84+
movapd %xmm1, (RUSTRT_XMM1*8)(%rdi)
85+
movapd %xmm2, (RUSTRT_XMM2*8)(%rdi)
86+
movapd %xmm3, (RUSTRT_XMM3*8)(%rdi)
87+
movapd %xmm4, (RUSTRT_XMM4*8)(%rdi)
88+
movapd %xmm5, (RUSTRT_XMM5*8)(%rdi)
7789

7890
// Restore non-volatile integer registers:
7991
// (including RSP)
80-
mov 0(%rsi), %rbx
81-
mov 8(%rsi), %rsp
82-
mov 16(%rsi), %rbp
83-
mov 24(%rsi), %r12
84-
mov 32(%rsi), %r13
85-
mov 40(%rsi), %r14
86-
mov 48(%rsi), %r15
92+
mov (RUSTRT_RBX*8)(%rsi), %rbx
93+
mov (RUSTRT_RSP*8)(%rsi), %rsp
94+
mov (RUSTRT_RBP*8)(%rsi), %rbp
95+
mov (RUSTRT_R12*8)(%rsi), %r12
96+
mov (RUSTRT_R13*8)(%rsi), %r13
97+
mov (RUSTRT_R14*8)(%rsi), %r14
98+
mov (RUSTRT_R15*8)(%rsi), %r15
99+
100+
// Restore relevant argument registers:
101+
mov (RUSTRT_RCX*8)(%rdi), %rcx
102+
mov (RUSTRT_RDI*8)(%rdi), %rdi
87103

88104
// Restore non-volatile XMM registers:
89-
movapd 64(%rsi), %xmm0
90-
movapd 80(%rsi), %xmm1
91-
movapd 96(%rsi), %xmm2
92-
movapd 112(%rsi), %xmm3
93-
movapd 128(%rsi), %xmm4
94-
movapd 144(%rsi), %xmm5
105+
movapd (RUSTRT_XMM0*8)(%rsi), %xmm0
106+
movapd (RUSTRT_XMM1*8)(%rsi), %xmm1
107+
movapd (RUSTRT_XMM2*8)(%rsi), %xmm2
108+
movapd (RUSTRT_XMM3*8)(%rsi), %xmm3
109+
movapd (RUSTRT_XMM4*8)(%rsi), %xmm4
110+
movapd (RUSTRT_XMM5*8)(%rsi), %xmm5
95111

96112
// Jump to the instruction pointer
97113
// found in regs:
98-
jmp *56(%rsi)
114+
jmp *(RUSTRT_IP*8)(%rsi)
99115

trunk/src/rt/arch/x86_64/context.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,11 @@ void context::call(void *f, void *arg, void *stack) {
2525
// given function.
2626
swap(*this);
2727

28-
// set up the trampoline frame
29-
uint64_t *sp = (uint64_t *)stack;
28+
// set up the stack
29+
uint32_t *sp = (uint32_t *)stack;
30+
sp = align_down(sp);
3031

31-
// Shift the stack pointer so the alignment works out right.
32-
sp = align_down(sp) - 3;
33-
*--sp = (uint64_t)arg;
34-
*--sp = 0xdeadbeef;
35-
36-
regs.regs[RSP] = (uint64_t)sp;
37-
regs.ip = (uint64_t)f;
32+
regs.data[RUSTRT_ARG0] = (uint64_t)arg;
33+
regs.data[RUSTRT_RSP] = (uint64_t)sp;
34+
regs.data[RUSTRT_IP] = (uint64_t)f;
3835
}

trunk/src/rt/arch/x86_64/context.h

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,42 +20,41 @@ T align_down(T sp)
2020
return (T)((uint64_t)sp & ~(16 - 1));
2121
}
2222

23+
// The struct in which we store the saved data. This is mostly the
24+
// volatile registers and instruction pointer, but it also includes
25+
// RCX/RDI which are used to pass arguments. The indices for each
26+
// register are found in <x86_64_regs.h>:
27+
#include "x86_64_regs.h"
2328
struct registers_t {
24-
uint64_t regs[7]; // Space for the volatile regs: rbx, rsp, rbp, r12:r15
25-
uint64_t ip;
26-
27-
// n.b.: These must be 16-byte aligned or movapd is unhappy.
28-
__m128 xmms[6]; // Space for the volatile regs: xmm0:xmm5
29+
uint64_t data[RUSTRT_MAX];
2930
};
3031

3132
class context {
3233
public:
33-
static const int RSP = 1;
34-
35-
registers_t regs;
36-
37-
context();
38-
39-
context *next;
40-
41-
void swap(context &out);
42-
void call(void *f, void *arg, void *sp);
43-
void call(void *f, void *sp);
44-
45-
// Note that this doesn't actually adjust esp. Instead, we adjust esp when
46-
// we actually do the call. This is needed for exception safety -- if the
47-
// function being called causes the task to fail, then we have to avoid
48-
// leaking space on the C stack.
49-
inline void *alloc_stack(size_t nbytes) {
50-
uint32_t bot = regs.regs[RSP];
51-
uint32_t top = align_down(bot - nbytes);
34+
registers_t regs;
35+
36+
context();
37+
38+
context *next;
39+
40+
void swap(context &out);
41+
void call(void *f, void *arg, void *sp);
42+
void call(void *f, void *sp);
43+
44+
// Note that this doesn't actually adjust esp. Instead, we adjust esp when
45+
// we actually do the call. This is needed for exception safety -- if the
46+
// function being called causes the task to fail, then we have to avoid
47+
// leaking space on the C stack.
48+
inline void *alloc_stack(size_t nbytes) {
49+
uint32_t bot = regs.data[RUSTRT_RSP];
50+
uint32_t top = align_down(bot - nbytes);
5251

5352
#ifdef HAVE_VALGRIND
54-
(void)VALGRIND_MAKE_MEM_UNDEFINED(top - 4, bot - top + 4);
53+
(void)VALGRIND_MAKE_MEM_UNDEFINED(top - 4, bot - top + 4);
5554
#endif
5655

57-
return reinterpret_cast<void *>(top);
58-
}
56+
return reinterpret_cast<void *>(top);
57+
}
5958
};
6059

6160
#endif
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#define RUSTRT_RBX 0
2+
#define RUSTRT_RSP 1
3+
#define RUSTRT_RBP 2
4+
#define RUSTRT_RDI 3
5+
#define RUSTRT_RCX 4
6+
#define RUSTRT_R12 5
7+
#define RUSTRT_R13 6
8+
#define RUSTRT_R14 7
9+
#define RUSTRT_R15 8
10+
#define RUSTRT_IP 9
11+
#define RUSTRT_XMM0 10
12+
#define RUSTRT_XMM1 12
13+
#define RUSTRT_XMM2 14
14+
#define RUSTRT_XMM3 16
15+
#define RUSTRT_XMM4 18
16+
#define RUSTRT_XMM5 20
17+
#define RUSTRT_MAX 22
18+
19+
// ARG0 is the register in which the first argument goes.
20+
// Naturally this depends on your operating system.
21+
#if defined(__MINGW32__) || defined(_WINDOWS)
22+
# define RUSTRT_ARG0 RUSTRT_RCX
23+
# define RUSTRT_ARG0_S %rcx
24+
# define RUSTRT_ARG1_S %rdx
25+
#else
26+
# define RUSTRT_ARG0 RUSTRT_RDI
27+
#endif
28+
29+

0 commit comments

Comments
 (0)