about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2011-11-08 14:25:41 -0800
committerNiko Matsakis <niko@alum.mit.edu>2011-11-08 21:14:09 -0800
commitb30a76ed1b5f5d35560d00a621bf91d6024c478e (patch)
tree4d579053bc54119090560172ca775dcbd3b03b4f /src
parenta8c0c2b871a9a0c39a1294327490700104cd0918 (diff)
downloadrust-b30a76ed1b5f5d35560d00a621bf91d6024c478e.tar.gz
rust-b30a76ed1b5f5d35560d00a621bf91d6024c478e.zip
correct calling convention for x86_64
Diffstat (limited to 'src')
-rw-r--r--src/rt/arch/x86_64/_context.S76
-rw-r--r--src/rt/arch/x86_64/context.cpp15
-rw-r--r--src/rt/arch/x86_64/context.h53
-rw-r--r--src/rt/arch/x86_64/x86_64_regs.h29
4 files changed, 107 insertions, 66 deletions
diff --git a/src/rt/arch/x86_64/_context.S b/src/rt/arch/x86_64/_context.S
index 2eba7296df2..5632df932f3 100644
--- a/src/rt/arch/x86_64/_context.S
+++ b/src/rt/arch/x86_64/_context.S
@@ -1,4 +1,6 @@
-	.text
+#include "x86_64_regs.h"
+
+        .text
 
 /*
 According to ABI documentation found at
@@ -46,54 +48,68 @@ First four arguments:
 .globl swap_registers
 swap_registers:
         // n.b. when we enter, the return address is at the top of
-        // the stack (i.e., 0(%RSP)).  We
+        // the stack (i.e., 0(%RSP)) and the argument is in
+        // RUSTRT_ARG0_S.  We
         // simply save all NV registers into oregs.
         // We then restore all NV registers from regs.  This restores
         // the old stack pointer, which should include the proper
         // 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, 56(%rdi)
+        mov %rax, (RUSTRT_IP*8)(%rdi)
 
         // Save non-volatile integer registers:
         //   (including RSP)
-        mov %rbx,   0(%rdi)
-        mov %rsp,   8(%rdi)
-        mov %rbp,  16(%rdi)
-        mov %r12,  24(%rdi)
-        mov %r13,  32(%rdi)
-        mov %r14,  40(%rdi)
-        mov %r15,  48(%rdi)
+        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)
+
+        // Save relevant argument registers:
+        mov %rcx, (RUSTRT_RCX*8)(%rdi)
+        mov %rdi, (RUSTRT_RDI*8)(%rdi)
 
         // Save non-volatile XMM registers:
-        movapd %xmm0,  64(%rdi)
-        movapd %xmm1,  80(%rdi)
-        movapd %xmm2,  96(%rdi)
-        movapd %xmm3, 112(%rdi)
-        movapd %xmm4, 128(%rdi)
-        movapd %xmm5, 144(%rdi)
+        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)
 
         // Restore non-volatile integer registers:
         //   (including RSP)
-        mov  0(%rsi), %rbx
-        mov  8(%rsi), %rsp
-        mov 16(%rsi), %rbp
-        mov 24(%rsi), %r12
-        mov 32(%rsi), %r13
-        mov 40(%rsi), %r14
-        mov 48(%rsi), %r15
+        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
+
+        // Restore relevant argument registers:
+        mov (RUSTRT_RCX*8)(%rdi), %rcx
+        mov (RUSTRT_RDI*8)(%rdi), %rdi
 
         // Restore non-volatile XMM registers:
-        movapd  64(%rsi), %xmm0
-        movapd  80(%rsi), %xmm1
-        movapd  96(%rsi), %xmm2
-        movapd 112(%rsi), %xmm3
-        movapd 128(%rsi), %xmm4
-        movapd 144(%rsi), %xmm5
+        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
 
         // Jump to the instruction pointer
         // found in regs:
-        jmp *56(%rsi)
+        jmp *(RUSTRT_IP*8)(%rsi)
 
diff --git a/src/rt/arch/x86_64/context.cpp b/src/rt/arch/x86_64/context.cpp
index edfae486b4f..09577dbd151 100644
--- a/src/rt/arch/x86_64/context.cpp
+++ b/src/rt/arch/x86_64/context.cpp
@@ -25,14 +25,11 @@ void context::call(void *f, void *arg, void *stack) {
   // given function.
   swap(*this);
 
-  // set up the trampoline frame
-  uint64_t *sp = (uint64_t *)stack;
+  // set up the stack
+  uint32_t *sp = (uint32_t *)stack;
+  sp = align_down(sp);
 
-  // Shift the stack pointer so the alignment works out right.
-  sp = align_down(sp) - 3;
-  *--sp = (uint64_t)arg;
-  *--sp = 0xdeadbeef;
-
-  regs.regs[RSP] = (uint64_t)sp;
-  regs.ip = (uint64_t)f;
+  regs.data[RUSTRT_ARG0] = (uint64_t)arg;
+  regs.data[RUSTRT_RSP] = (uint64_t)sp;
+  regs.data[RUSTRT_IP] = (uint64_t)f;
 }
diff --git a/src/rt/arch/x86_64/context.h b/src/rt/arch/x86_64/context.h
index 305298093cc..5d764cfdb0a 100644
--- a/src/rt/arch/x86_64/context.h
+++ b/src/rt/arch/x86_64/context.h
@@ -20,42 +20,41 @@ T align_down(T sp)
     return (T)((uint64_t)sp & ~(16 - 1));
 }
 
+// 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"
 struct registers_t {
-    uint64_t regs[7];  // Space for the volatile regs: rbx, rsp, rbp, r12:r15
-    uint64_t ip;
-
-    // n.b.: These must be 16-byte aligned or movapd is unhappy.
-    __m128 xmms[6]; // Space for the volatile regs: xmm0:xmm5
+    uint64_t data[RUSTRT_MAX];
 };
 
 class context {
 public:
-  static const int RSP = 1;
-
-  registers_t regs;
-
-  context();
-
-  context *next;
-
-  void swap(context &out);
-  void call(void *f, void *arg, void *sp);
-  void call(void *f, void *sp);
-
-  // Note that this doesn't actually adjust esp. Instead, we adjust esp when
-  // we actually do the call. This is needed for exception safety -- if the
-  // function being called causes the task to fail, then we have to avoid
-  // leaking space on the C stack.
-  inline void *alloc_stack(size_t nbytes) {
-    uint32_t bot = regs.regs[RSP];
-    uint32_t top = align_down(bot - nbytes);
+    registers_t regs;
+    
+    context();
+    
+    context *next;
+    
+    void swap(context &out);
+    void call(void *f, void *arg, void *sp);
+    void call(void *f, void *sp);
+    
+    // Note that this doesn't actually adjust esp. Instead, we adjust esp when
+    // we actually do the call. This is needed for exception safety -- if the
+    // function being called causes the task to fail, then we have to avoid
+    // leaking space on the C stack.
+    inline void *alloc_stack(size_t nbytes) {
+        uint32_t bot = regs.data[RUSTRT_RSP];
+        uint32_t top = align_down(bot - nbytes);
 
 #ifdef HAVE_VALGRIND
-    (void)VALGRIND_MAKE_MEM_UNDEFINED(top - 4, bot - top + 4);
+        (void)VALGRIND_MAKE_MEM_UNDEFINED(top - 4, bot - top + 4);
 #endif
 
-    return reinterpret_cast<void *>(top);
-  }
+        return reinterpret_cast<void *>(top);
+    }
 };
 
 #endif
diff --git a/src/rt/arch/x86_64/x86_64_regs.h b/src/rt/arch/x86_64/x86_64_regs.h
new file mode 100644
index 00000000000..084ab03fdc4
--- /dev/null
+++ b/src/rt/arch/x86_64/x86_64_regs.h
@@ -0,0 +1,29 @@
+#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_XMM0 10
+#define RUSTRT_XMM1 12
+#define RUSTRT_XMM2 14
+#define RUSTRT_XMM3 16
+#define RUSTRT_XMM4 18
+#define RUSTRT_XMM5 20
+#define RUSTRT_MAX  22
+
+// 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  
+#endif
+
+