correct stack alignment

This commit is contained in:
Niko Matsakis 2011-11-08 17:07:11 -08:00
parent 2edd3135ad
commit ff5b319ce5
6 changed files with 60 additions and 58 deletions

View File

@ -106,7 +106,8 @@ RUNTIME_HDR_$(1) := rt/globals.h \
rt/test/rust_test_harness.h \
rt/test/rust_test_runtime.h \
rt/test/rust_test_util.h \
rt/arch/$$(HOST_$(1))/context.h
rt/arch/$$(HOST_$(1))/context.h \
rt/arch/$$(HOST_$(1))/regs.h
ifeq ($$(HOST_$(1)), i386)
LIBUV_ARCH_$(1) := ia32

2
src/rt/arch/i386/regs.h Normal file
View File

@ -0,0 +1,2 @@
// This file is not used by i386, but we keep it here so all
// architectures have the same set of header files.

View File

@ -1,5 +1,7 @@
#include "x86_64_regs.h"
#include "regs.h"
#define ARG0 RUSTRT_ARG0_S
#define ARG1 RUSTRT_ARG1_S
.text
/*
@ -41,7 +43,10 @@ First four arguments:
/*
Stores current registers into arg0/RCX and restores
registers found in arg1/RDX. This is used by our
implementation of getcontext.
implementation of getcontext. Only saves/restores nonvolatile
registers and the register used for the first argument.
Volatile registers in general ought to be saved by the caller
anyhow.
*/
// swap_registers(registers_t *oregs, registers_t *regs)
@ -56,60 +61,53 @@ swap_registers:
// return address. We can therefore just return normally to
// jump back into the old code.
# if defined(RUSTRT_ARG0_S)
mov RUSTRT_ARG0_S, %rdi
mov RUSTRT_ARG1_S, %rsi
# endif
// Save instruction pointer:
pop %rax
mov %rax, (RUSTRT_IP*8)(%rdi)
mov %rax, (RUSTRT_IP*8)(RUSTRT_ARG0_S)
// Save non-volatile integer registers:
// (including RSP)
mov %rbx, (RUSTRT_RBX*8)(%rdi)
mov %rsp, (RUSTRT_RSP*8)(%rdi)
mov %rbp, (RUSTRT_RBP*8)(%rdi)
mov %r12, (RUSTRT_R12*8)(%rdi)
mov %r13, (RUSTRT_R13*8)(%rdi)
mov %r14, (RUSTRT_R14*8)(%rdi)
mov %r15, (RUSTRT_R15*8)(%rdi)
mov %rbx, (RUSTRT_RBX*8)(ARG0)
mov %rsp, (RUSTRT_RSP*8)(ARG0)
mov %rbp, (RUSTRT_RBP*8)(ARG0)
mov %r12, (RUSTRT_R12*8)(ARG0)
mov %r13, (RUSTRT_R13*8)(ARG0)
mov %r14, (RUSTRT_R14*8)(ARG0)
mov %r15, (RUSTRT_R15*8)(ARG0)
// Save relevant argument registers:
mov %rcx, (RUSTRT_RCX*8)(%rdi)
mov %rdi, (RUSTRT_RDI*8)(%rdi)
// Save 0th argument register:
mov ARG0, (RUSTRT_ARG0*8)(ARG0)
// Save non-volatile XMM registers:
movapd %xmm0, (RUSTRT_XMM0*8)(%rdi)
movapd %xmm1, (RUSTRT_XMM1*8)(%rdi)
movapd %xmm2, (RUSTRT_XMM2*8)(%rdi)
movapd %xmm3, (RUSTRT_XMM3*8)(%rdi)
movapd %xmm4, (RUSTRT_XMM4*8)(%rdi)
movapd %xmm5, (RUSTRT_XMM5*8)(%rdi)
movapd %xmm0, (RUSTRT_XMM0*8)(ARG0)
movapd %xmm1, (RUSTRT_XMM1*8)(ARG0)
movapd %xmm2, (RUSTRT_XMM2*8)(ARG0)
movapd %xmm3, (RUSTRT_XMM3*8)(ARG0)
movapd %xmm4, (RUSTRT_XMM4*8)(ARG0)
movapd %xmm5, (RUSTRT_XMM5*8)(ARG0)
// Restore non-volatile integer registers:
// (including RSP)
mov (RUSTRT_RBX*8)(%rsi), %rbx
mov (RUSTRT_RSP*8)(%rsi), %rsp
mov (RUSTRT_RBP*8)(%rsi), %rbp
mov (RUSTRT_R12*8)(%rsi), %r12
mov (RUSTRT_R13*8)(%rsi), %r13
mov (RUSTRT_R14*8)(%rsi), %r14
mov (RUSTRT_R15*8)(%rsi), %r15
mov (RUSTRT_RBX*8)(ARG1), %rbx
mov (RUSTRT_RSP*8)(ARG1), %rsp
mov (RUSTRT_RBP*8)(ARG1), %rbp
mov (RUSTRT_R12*8)(ARG1), %r12
mov (RUSTRT_R13*8)(ARG1), %r13
mov (RUSTRT_R14*8)(ARG1), %r14
mov (RUSTRT_R15*8)(ARG1), %r15
// Restore relevant argument registers:
mov (RUSTRT_RCX*8)(%rsi), %rcx
mov (RUSTRT_RDI*8)(%rsi), %rdi
// Restore 0th argument register:
mov (RUSTRT_ARG0*8)(ARG1), ARG0
// Restore non-volatile XMM registers:
movapd (RUSTRT_XMM0*8)(%rsi), %xmm0
movapd (RUSTRT_XMM1*8)(%rsi), %xmm1
movapd (RUSTRT_XMM2*8)(%rsi), %xmm2
movapd (RUSTRT_XMM3*8)(%rsi), %xmm3
movapd (RUSTRT_XMM4*8)(%rsi), %xmm4
movapd (RUSTRT_XMM5*8)(%rsi), %xmm5
movapd (RUSTRT_XMM0*8)(ARG1), %xmm0
movapd (RUSTRT_XMM1*8)(ARG1), %xmm1
movapd (RUSTRT_XMM2*8)(ARG1), %xmm2
movapd (RUSTRT_XMM3*8)(ARG1), %xmm3
movapd (RUSTRT_XMM4*8)(ARG1), %xmm4
movapd (RUSTRT_XMM5*8)(ARG1), %xmm5
// Jump to the instruction pointer
// found in regs:
jmp *(RUSTRT_IP*8)(%rsi)
jmp *(RUSTRT_IP*8)(ARG1)

View File

@ -26,8 +26,9 @@ void context::call(void *f, void *arg, void *stack) {
swap(*this);
// set up the stack
uint32_t *sp = (uint32_t *)stack;
uint64_t *sp = (uint64_t *)stack;
sp = align_down(sp);
*--sp = 0xdeadbeef; // takes place of ret. addr.
regs.data[RUSTRT_ARG0] = (uint64_t)arg;
regs.data[RUSTRT_RSP] = (uint64_t)sp;

View File

@ -23,8 +23,8 @@ T align_down(T sp)
// The struct in which we store the saved data. This is mostly the
// volatile registers and instruction pointer, but it also includes
// RCX/RDI which are used to pass arguments. The indices for each
// register are found in <x86_64_regs.h>:
#include "x86_64_regs.h"
// register are found in "regs.h":
#include "regs.h"
struct registers_t {
uint64_t data[RUSTRT_MAX];
};

View File

@ -1,13 +1,13 @@
#define RUSTRT_RBX 0
#define RUSTRT_RSP 1
#define RUSTRT_RBP 2
#define RUSTRT_RDI 3
#define RUSTRT_RCX 4
#define RUSTRT_R12 5
#define RUSTRT_R13 6
#define RUSTRT_R14 7
#define RUSTRT_R15 8
#define RUSTRT_IP 9
#define RUSTRT_RBX 0
#define RUSTRT_RSP 1
#define RUSTRT_RBP 2
#define RUSTRT_ARG0 3 // RCX on Windows, RDI elsewhere
#define RUSTRT_R12 4
#define RUSTRT_R13 5
#define RUSTRT_R14 6
#define RUSTRT_R15 7
#define RUSTRT_IP 8
#define RUSTRT_XXX 9 // Not used, just padding
#define RUSTRT_XMM0 10
#define RUSTRT_XMM1 12
#define RUSTRT_XMM2 14
@ -19,11 +19,11 @@
// ARG0 is the register in which the first argument goes.
// Naturally this depends on your operating system.
#if defined(__MINGW32__) || defined(_WINDOWS)
# define RUSTRT_ARG0 RUSTRT_RCX
# define RUSTRT_ARG0_S %rcx
# define RUSTRT_ARG1_S %rdx
#else
# define RUSTRT_ARG0 RUSTRT_RDI
# define RUSTRT_ARG0_S %rdi
# define RUSTRT_ARG1_S %rsi
#endif