4 See i386/morestack.S for the lengthy, general explanation.
9 #if defined(__APPLE__) || defined(_WIN32)
10 #define UPCALL_NEW_STACK _upcall_new_stack
11 #define UPCALL_DEL_STACK _upcall_del_stack
12 #define MORESTACK ___morestack
14 #define UPCALL_NEW_STACK upcall_new_stack
15 #define UPCALL_DEL_STACK upcall_del_stack
16 #define MORESTACK __morestack
19 .globl UPCALL_NEW_STACK
20 .globl UPCALL_DEL_STACK
23 #if defined(__linux__)
26 #if defined(__APPLE__)
27 .private_extern MORESTACK
32 .type MORESTACK,@function
36 #if defined(__linux__) || defined(__APPLE__)
41 // The CFA is 24 bytes above the register that it will
42 // be associated with for this frame (%rbp). That is 8
43 // bytes greater than a normal frame, to allow the unwinder
44 // to skip the partial frame of the original function.
45 .cfi_def_cfa_offset 24
46 // %rbp is -24 bytes from the CFA
49 // Calculate the CFA as on offset from %ebp
50 .cfi_def_cfa_register %rbp
54 // FIXME: libgcc also saves rax. not sure if we need to
56 // Save argument registers of the original function
69 movdqa %xmm1, 16(%rsp)
70 movdqa %xmm2, 32(%rsp)
71 movdqa %xmm3, 48(%rsp)
72 movdqa %xmm4, 64(%rsp)
73 movdqa %xmm5, 80(%rsp)
74 movdqa %xmm6, 96(%rsp)
75 movdqa %xmm7, 112(%rsp)
77 // Calculate the address of the stack arguments.
78 // We have the base pointer, __morestack's return address,
79 // and __morestack's caller's return address to skip
81 addq $24, %rax // Base pointer, return address x2
83 // The arguments to __morestack are passed in %r10 & %r11
85 movq %r11, %rdx // Size of stack arguments
86 movq %rax, %rsi // Address of stack arguments
87 movq %r10, %rdi // The amount of stack needed
93 call UPCALL_NEW_STACK@PLT
96 // Pop the saved arguments
98 movdqa 16(%rsp), %xmm1
99 movdqa 32(%rsp), %xmm2
100 movdqa 48(%rsp), %xmm3
101 movdqa 64(%rsp), %xmm4
102 movdqa 80(%rsp), %xmm5
103 movdqa 96(%rsp), %xmm6
104 movdqa 112(%rsp), %xmm7
107 popq %r9 // Alignment
108 popq %r9 // Alignment
117 // Pop the unwinding %rsp
120 movq 8(%rbp),%r10 // Grab the return pointer.
121 incq %r10 // Skip past the `ret` in our parent frame
122 movq %rax,%rsp // Switch to the new stack.
124 call *%r10 // Reenter the caller function
126 // Switch back to the rust stack
129 // Save the return value
133 call UPCALL_DEL_STACK
136 call UPCALL_DEL_STACK@PLT
139 popq %rax // Restore the return value
141 // FIXME: I don't think these rules are necessary
142 // since the unwinder should never encounter an instruction
143 // pointer pointing here.
145 .cfi_def_cfa %rsp, 16