about summary refs log tree commit diff
path: root/src/rt/arch/x86_64
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2011-11-09 11:01:12 -0800
committerNiko Matsakis <niko@alum.mit.edu>2011-11-09 20:05:49 -0800
commit7baf68b0bdf38baeba482075b12fc50f9ff51d13 (patch)
treeffae4e33bb1abf753c14a3a20081bbb50a56f382 /src/rt/arch/x86_64
parentfc064f441026f2f34417925a26c1f6d73a7faf2c (diff)
downloadrust-7baf68b0bdf38baeba482075b12fc50f9ff51d13.tar.gz
rust-7baf68b0bdf38baeba482075b12fc50f9ff51d13.zip
hack around the problem that x86_64 expects first few args in regs.
call on c-stack expects all data to be delivered on the stack.
Diffstat (limited to 'src/rt/arch/x86_64')
-rw-r--r--src/rt/arch/x86_64/ccall.S35
-rw-r--r--src/rt/arch/x86_64/regs.h6
2 files changed, 38 insertions, 3 deletions
diff --git a/src/rt/arch/x86_64/ccall.S b/src/rt/arch/x86_64/ccall.S
index 428ac7437c1..d9221067175 100644
--- a/src/rt/arch/x86_64/ccall.S
+++ b/src/rt/arch/x86_64/ccall.S
@@ -1,4 +1,9 @@
-    .text
+#include "regs.h"
+
+#define ARG0 RUSTRT_ARG0_S
+#define ARG1 RUSTRT_ARG1_S
+        
+        .text
 
 // upcall_call_c_stack(void (*fn)(), void *new_esp)
 //
@@ -21,8 +26,32 @@ upcall_call_c_stack_float:
 #endif
     push %rbp
     mov %rsp,%rbp          // save rsp
-    mov %rsi,%rsp          // switch stack
-    call *%rdi
+    mov ARG1,%rsp          // switch stack
+
+    // Hack: the arguments to the function are sitting
+    // on the stack right now, as in i386 calling
+    // convention.  We need them in registers.
+    // For now, we just load them into registers.
+    //
+    // This is a total hack because it does not consider
+    // the actual arguments of the target function.
+    // It fails if there are non-INTEGER class arguments,
+    // which would get pushed on the stack, or if there are
+    // additional arguments beyond those that will get
+    // passed in registers.
+    mov ARG0,%r11     // Remember target address
+    mov  0(%rsp),RUSTRT_ARG0_S
+    mov  8(%rsp),RUSTRT_ARG1_S
+    mov 16(%rsp),RUSTRT_ARG2_S
+    mov 24(%rsp),RUSTRT_ARG3_S
+#   ifdef RUSTRT_ARG4_S        
+    mov 32(%rsp),RUSTRT_ARG4_S
+#   endif
+#   ifdef RUSTRT_ARG5_S        
+    mov 40(%rsp),RUSTRT_ARG5_S
+#   endif
+        
+    call *%r11
     mov %rbp,%rsp          // would like to use "leave" but it's slower
     pop %rbp
     ret
diff --git a/src/rt/arch/x86_64/regs.h b/src/rt/arch/x86_64/regs.h
index 7d090ff5b27..5ebcdf7429b 100644
--- a/src/rt/arch/x86_64/regs.h
+++ b/src/rt/arch/x86_64/regs.h
@@ -21,9 +21,15 @@
 #if defined(__MINGW32__) || defined(_WINDOWS)
 #   define RUSTRT_ARG0_S %rcx
 #   define RUSTRT_ARG1_S %rdx
+#   define RUSTRT_ARG2_S %r8
+#   define RUSTRT_ARG3_S %r9
 #else
 #   define RUSTRT_ARG0_S %rdi
 #   define RUSTRT_ARG1_S %rsi
+#   define RUSTRT_ARG2_S %rdx
+#   define RUSTRT_ARG3_S %rcx
+#   define RUSTRT_ARG4_S %r8
+#   define RUSTRT_ARG5_S %r9
 #endif