]> git.lizzy.rs Git - rust.git/blob - src/rt/arch/x86_64/morestack.S
Merge pull request #1392 from Lenny222/list
[rust.git] / src / rt / arch / x86_64 / morestack.S
1 /*
2         __morestack
3
4         See i386/morestack.S for the lengthy, general explanation.
5 */
6
7 .text
8
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
13 #else
14 #define UPCALL_NEW_STACK        upcall_new_stack
15 #define UPCALL_DEL_STACK        upcall_del_stack
16 #define MORESTACK               __morestack
17 #endif
18
19 .globl UPCALL_NEW_STACK
20 .globl UPCALL_DEL_STACK
21 .globl MORESTACK
22
23 #if defined(__linux__) || defined(__FreeBSD__)
24         .hidden MORESTACK
25 #else
26 #if defined(__APPLE__)
27         .private_extern MORESTACK
28 #endif
29 #endif
30
31 #ifdef __ELF__
32         .type MORESTACK,@function
33 #endif
34
35
36 #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
37 MORESTACK:
38         .cfi_startproc
39
40         pushq %rbp
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
47         .cfi_offset %rbp, -24
48         movq %rsp, %rbp
49         // Calculate the CFA as on offset from %ebp
50         .cfi_def_cfa_register %rbp
51
52         pushq $0 // Alignment
53
54         // FIXME: libgcc also saves rax. not sure if we need to
55
56         // Save argument registers of the original function
57         pushq   %rdi
58         pushq   %rsi
59         pushq   %rdx
60         pushq   %rcx
61         pushq   %r8
62         pushq   %r9
63
64         pushq $0 // Alignment
65         pushq $0 // Alignment
66
67         subq $128, %rsp
68         movdqa %xmm0,    (%rsp)
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)
76
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
80         movq %rbp, %rax
81         addq $24, %rax  // Base pointer, return address x2
82
83         // The arguments to __morestack are passed in %r10 & %r11
84
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
88         
89 #ifdef __APPLE__
90         call UPCALL_NEW_STACK
91 #endif
92 #ifdef __linux__
93         call UPCALL_NEW_STACK@PLT
94 #endif
95 #ifdef __FreeBSD__
96         call UPCALL_NEW_STACK@PLT
97 #endif
98
99         // Pop the saved arguments
100         movdqa    (%rsp), %xmm0
101         movdqa  16(%rsp), %xmm1
102         movdqa  32(%rsp), %xmm2
103         movdqa  48(%rsp), %xmm3
104         movdqa  64(%rsp), %xmm4
105         movdqa  80(%rsp), %xmm5
106         movdqa  96(%rsp), %xmm6
107         movdqa 112(%rsp), %xmm7
108         addq $128, %rsp
109
110         popq %r9 // Alignment
111         popq %r9 // Alignment
112
113         popq %r9
114         popq %r8
115         popq %rcx
116         popq %rdx
117         popq %rsi
118         popq %rdi
119
120         // Pop the unwinding %rsp
121         addq $8, %rsp
122
123         movq 8(%rbp),%r10       // Grab the return pointer.
124         incq %r10               // Skip past the `ret` in our parent frame
125         movq %rax,%rsp          // Switch to the new stack.
126
127         call *%r10              // Reenter the caller function
128
129         // Switch back to the rust stack
130         movq %rbp, %rsp
131
132         // Save the return value
133         pushq %rax
134
135 #ifdef __APPLE__
136         call UPCALL_DEL_STACK
137 #endif
138 #ifdef __linux__
139         call UPCALL_DEL_STACK@PLT
140 #endif
141 #ifdef __FreeBSD__
142         call UPCALL_DEL_STACK@PLT
143 #endif
144
145         popq %rax // Restore the return value
146         popq %rbp
147         // FIXME: I don't think these rules are necessary
148         // since the unwinder should never encounter an instruction
149         // pointer pointing here.
150         .cfi_restore %rbp
151         .cfi_def_cfa %rsp, 16
152         ret
153         
154         .cfi_endproc
155
156 #else
157 MORESTACK:
158         ret
159 #endif