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