]> git.lizzy.rs Git - rust.git/blob - src/rt/arch/x86_64/morestack.S
auto merge of #5649 : thestinger/rust/lib, r=brson
[rust.git] / src / rt / arch / x86_64 / morestack.S
1 // Mark stack as non-executable
2 #if defined(__linux__) && defined(__ELF__)
3 .section        .note.GNU-stack, "", @progbits
4 #endif
5
6 /*
7         __morestack
8
9         See i386/morestack.S for the lengthy, general explanation.
10 */
11
12 .text
13
14 #if defined(__APPLE__) || defined(_WIN32)
15 #define UPCALL_NEW_STACK        _upcall_new_stack
16 #define UPCALL_DEL_STACK        _upcall_del_stack
17 #define MORESTACK               ___morestack
18 #else
19 #define UPCALL_NEW_STACK        upcall_new_stack
20 #define UPCALL_DEL_STACK        upcall_del_stack
21 #define MORESTACK               __morestack
22 #endif
23
24 .globl UPCALL_NEW_STACK
25 .globl UPCALL_DEL_STACK
26 .globl MORESTACK
27
28 #if defined(__linux__) || defined(__FreeBSD__)
29         .hidden MORESTACK
30 #else
31 #if defined(__APPLE__)
32         .private_extern MORESTACK
33 #endif
34 #endif
35
36 #ifdef __ELF__
37         .type MORESTACK,@function
38 #endif
39
40
41 #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
42 MORESTACK:
43         .cfi_startproc
44
45         pushq %rbp
46         // The CFA is 24 bytes above the register that it will
47         // be associated with for this frame (%rbp). That is 8
48         // bytes greater than a normal frame, to allow the unwinder
49         // to skip the partial frame of the original function.
50         .cfi_def_cfa_offset 24
51         // %rbp is -24 bytes from the CFA
52         .cfi_offset %rbp, -24
53         movq %rsp, %rbp
54         // Calculate the CFA as on offset from %ebp
55         .cfi_def_cfa_register %rbp
56
57         subq $184, %rsp
58
59         // Save argument registers of the original function
60         movq %rdi,       (%rsp)
61         movq %rsi,      8(%rsp)
62         movq %rdx,     16(%rsp)
63         movq %rcx,     24(%rsp)
64         movq %r8,      32(%rsp)
65         movq %r9,      40(%rsp)
66         movdqa %xmm0,  48(%rsp)
67         movdqa %xmm1,  64(%rsp)
68         movdqa %xmm2,  80(%rsp)
69         movdqa %xmm3,  96(%rsp)
70         movdqa %xmm4, 112(%rsp)
71         movdqa %xmm5, 128(%rsp)
72         movdqa %xmm6, 144(%rsp)
73         movdqa %xmm7, 160(%rsp)
74
75         // Calculate the address of the stack arguments.
76         // We have the base pointer, __morestack's return address,
77         // and __morestack's caller's return address to skip
78         movq %rbp, %rax
79         addq $24, %rax  // Base pointer, return address x2
80
81         // The arguments to __morestack are passed in %r10 & %r11
82
83         movq %r11, %rdx // Size of stack arguments
84         movq %rax, %rsi // Address of stack arguments
85         movq %r10, %rdi // The amount of stack needed
86
87 #ifdef __APPLE__
88         call UPCALL_NEW_STACK
89 #endif
90 #ifdef __linux__
91         call UPCALL_NEW_STACK@PLT
92 #endif
93 #ifdef __FreeBSD__
94         call UPCALL_NEW_STACK@PLT
95 #endif
96
97         // Pop the saved arguments
98         movq      (%rsp), %rdi
99         movq     8(%rsp), %rsi
100         movq    16(%rsp), %rdx
101         movq    24(%rsp), %rcx
102         movq    32(%rsp), %r8
103         movq    40(%rsp), %r9
104         movdqa  48(%rsp), %xmm0
105         movdqa  64(%rsp), %xmm1
106         movdqa  80(%rsp), %xmm2
107         movdqa  96(%rsp), %xmm3
108         movdqa 112(%rsp), %xmm4
109         movdqa 128(%rsp), %xmm5
110         movdqa 144(%rsp), %xmm6
111         movdqa 160(%rsp), %xmm7
112
113         addq $184, %rsp
114
115         movq 8(%rbp),%r10       // Grab the return pointer.
116         incq %r10               // Skip past the `ret` in our parent frame
117         movq %rax,%rsp          // Switch to the new stack.
118
119         call *%r10              // Reenter the caller function
120
121         // Switch back to the rust stack
122         movq %rbp, %rsp
123
124         // Save the return value
125         pushq %rax
126
127 #ifdef __APPLE__
128         call UPCALL_DEL_STACK
129 #endif
130 #ifdef __linux__
131         call UPCALL_DEL_STACK@PLT
132 #endif
133 #ifdef __FreeBSD__
134         call UPCALL_DEL_STACK@PLT
135 #endif
136
137         popq %rax // Restore the return value
138         popq %rbp
139         ret
140
141         .cfi_endproc
142
143 #else
144 MORESTACK:
145         ret
146 #endif