]>
Commit | Line | Data |
---|---|---|
f5c64a69 DS |
1 | /* stuff needed for libgcc on win32. |
2 | * | |
d652f226 | 3 | * Copyright (C) 1996, 1998, 2001, 2003, 2008, 2009, 2010 |
174425ad | 4 | * Free Software Foundation, Inc. |
f5c64a69 DS |
5 | * Written By Steve Chamberlain |
6 | * | |
7 | * This file is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License as published by the | |
748086b7 | 9 | * Free Software Foundation; either version 3, or (at your option) any |
f5c64a69 DS |
10 | * later version. |
11 | * | |
f5c64a69 DS |
12 | * This file is distributed in the hope that it will be useful, but |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
748086b7 JJ |
17 | * Under Section 7 of GPL version 3, you are granted additional |
18 | * permissions described in the GCC Runtime Library Exception, version | |
19 | * 3.1, as published by the Free Software Foundation. | |
f5c64a69 | 20 | * |
748086b7 JJ |
21 | * You should have received a copy of the GNU General Public License and |
22 | * a copy of the GCC Runtime Library Exception along with this program; | |
23 | * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
24 | * <http://www.gnu.org/licenses/>. | |
f5c64a69 | 25 | */ |
3a2c1cd8 | 26 | |
174425ad KT |
27 | #include "auto-host.h" |
28 | ||
29 | #ifdef HAVE_GAS_CFI_SECTIONS_DIRECTIVE | |
30 | .cfi_sections .debug_frame | |
31 | # define cfi_startproc() .cfi_startproc | |
32 | # define cfi_endproc() .cfi_endproc | |
33 | # define cfi_adjust_cfa_offset(X) .cfi_adjust_cfa_offset X | |
34 | # define cfi_def_cfa_register(X) .cfi_def_cfa_register X | |
35 | # define cfi_register(D,S) .cfi_register D, S | |
36 | # ifdef _WIN64 | |
37 | # define cfi_push(X) .cfi_adjust_cfa_offset 8; .cfi_rel_offset X, 0 | |
38 | # define cfi_pop(X) .cfi_adjust_cfa_offset -8; .cfi_restore X | |
39 | # else | |
40 | # define cfi_push(X) .cfi_adjust_cfa_offset 4; .cfi_rel_offset X, 0 | |
41 | # define cfi_pop(X) .cfi_adjust_cfa_offset -4; .cfi_restore X | |
42 | # endif | |
43 | #else | |
44 | # define cfi_startproc() | |
45 | # define cfi_endproc() | |
46 | # define cfi_adjust_cfa_offset(X) | |
47 | # define cfi_def_cfa_register(X) | |
48 | # define cfi_register(D,S) | |
49 | # define cfi_push(X) | |
50 | # define cfi_pop(X) | |
51 | #endif /* HAVE_GAS_CFI_SECTIONS_DIRECTIVE */ | |
3a2c1cd8 | 52 | |
174425ad KT |
53 | #ifdef L_chkstk |
54 | /* Function prologue calls __chkstk to probe the stack when allocating more | |
f5c64a69 DS |
55 | than CHECK_STACK_LIMIT bytes in one go. Touching the stack at 4K |
56 | increments is necessary to ensure that the guard pages used | |
57 | by the OS virtual memory manger are allocated in correct sequence. */ | |
58 | ||
3a2c1cd8 MM |
59 | .global ___chkstk |
60 | .global __alloca | |
174425ad KT |
61 | #ifdef _WIN64 |
62 | /* __alloca is a normal function call, which uses %rcx as the argument. */ | |
63 | cfi_startproc() | |
3a2c1cd8 | 64 | __alloca: |
174425ad KT |
65 | movq %rcx, %rax |
66 | /* FALLTHRU */ | |
3a2c1cd8 | 67 | |
174425ad KT |
68 | /* ___chkstk is a *special* function call, which uses %rax as the argument. |
69 | We avoid clobbering the 4 integer argument registers, %rcx, %rdx, | |
70 | %r8 and %r9, which leaves us with %rax, %r10, and %r11 to use. */ | |
71 | .align 4 | |
72 | ___chkstk: | |
73 | popq %r11 /* pop return address */ | |
74 | cfi_adjust_cfa_offset(-8) /* indicate return address in r11 */ | |
75 | cfi_register(%rip, %r11) | |
76 | movq %rsp, %r10 | |
77 | cmpq $0x1000, %rax /* > 4k ?*/ | |
78 | jb 2f | |
3a2c1cd8 | 79 | |
174425ad KT |
80 | 1: subq $0x1000, %r10 /* yes, move pointer down 4k*/ |
81 | orl $0x0, (%r10) /* probe there */ | |
82 | subq $0x1000, %rax /* decrement count */ | |
83 | cmpq $0x1000, %rax | |
84 | ja 1b /* and do it again */ | |
3a2c1cd8 | 85 | |
174425ad KT |
86 | 2: subq %rax, %r10 |
87 | movq %rsp, %rax /* hold CFA until return */ | |
88 | cfi_def_cfa_register(%rax) | |
89 | orl $0x0, (%r10) /* less than 4k, just peek here */ | |
90 | movq %r10, %rsp /* decrement stack */ | |
3a2c1cd8 | 91 | |
ccf8e764 | 92 | /* Push the return value back. Doing this instead of just |
174425ad | 93 | jumping to %r11 preserves the cached call-return stack |
ccf8e764 | 94 | used by most modern processors. */ |
174425ad | 95 | pushq %r11 |
ccf8e764 | 96 | ret |
174425ad | 97 | cfi_endproc() |
ccf8e764 | 98 | #else |
174425ad KT |
99 | cfi_startproc() |
100 | ___chkstk: | |
ccf8e764 | 101 | __alloca: |
174425ad KT |
102 | pushl %ecx /* save temp */ |
103 | cfi_push(%eax) | |
104 | leal 8(%esp), %ecx /* point past return addr */ | |
105 | cmpl $0x1000, %eax /* > 4k ?*/ | |
106 | jb 2f | |
107 | ||
108 | 1: subl $0x1000, %ecx /* yes, move pointer down 4k*/ | |
109 | orl $0x0, (%ecx) /* probe there */ | |
110 | subl $0x1000, %eax /* decrement count */ | |
111 | cmpl $0x1000, %eax | |
112 | ja 1b /* and do it again */ | |
35b35fd0 | 113 | |
174425ad KT |
114 | 2: subl %eax, %ecx |
115 | orl $0x0, (%ecx) /* less than 4k, just peek here */ | |
116 | movl %esp, %eax /* save current stack pointer */ | |
117 | cfi_def_cfa_register(%eax) | |
118 | movl %ecx, %esp /* decrement stack */ | |
119 | movl (%eax), %ecx /* recover saved temp */ | |
35b35fd0 | 120 | |
174425ad KT |
121 | /* Copy the return register. Doing this instead of just jumping to |
122 | the address preserves the cached call-return stack used by most | |
123 | modern processors. */ | |
124 | pushl 4(%eax) | |
35b35fd0 | 125 | ret |
174425ad KT |
126 | cfi_endproc() |
127 | #endif /* _WIN64 */ | |
128 | #endif /* L_chkstk */ | |
ccf8e764 | 129 | |
174425ad KT |
130 | #ifdef L_chkstk_ms |
131 | /* ___chkstk_ms is a *special* function call, which uses %rax as the argument. | |
132 | We avoid clobbering any registers. Unlike ___chkstk, it just probes the | |
133 | stack and does no stack allocation. */ | |
134 | .global ___chkstk_ms | |
135 | #ifdef _WIN64 | |
136 | cfi_startproc() | |
137 | ___chkstk_ms: | |
138 | pushq %rcx /* save temps */ | |
139 | cfi_push(%rcx) | |
140 | pushq %rax | |
141 | cfi_push(%rax) | |
142 | cmpq $0x1000, %rax /* > 4k ?*/ | |
143 | leaq 24(%rsp), %rcx /* point past return addr */ | |
144 | jb 2f | |
145 | ||
146 | 1: subq $0x1000, %rcx /* yes, move pointer down 4k */ | |
147 | orq $0x0, (%rcx) /* probe there */ | |
ccf8e764 RH |
148 | subq $0x1000, %rax /* decrement count */ |
149 | cmpq $0x1000, %rax | |
174425ad | 150 | ja 1b /* and do it again */ |
ccf8e764 | 151 | |
174425ad KT |
152 | 2: subq %rax, %rcx |
153 | orq $0x0, (%rcx) /* less than 4k, just peek here */ | |
ccf8e764 | 154 | |
174425ad KT |
155 | popq %rax |
156 | cfi_pop(%rax) | |
157 | popq %rcx | |
158 | cfi_pop(%rcx) | |
159 | ret | |
160 | cfi_endproc() | |
161 | #else | |
162 | cfi_startproc() | |
163 | ___chkstk_ms: | |
164 | pushl %ecx /* save temp */ | |
165 | cfi_push(%ecx) | |
166 | pushl %eax | |
167 | cfi_push(%eax) | |
168 | cmpl $0x1000, %eax /* > 4k ?*/ | |
169 | leal 12(%esp), %ecx /* point past return addr */ | |
170 | jb 2f | |
171 | ||
172 | 1: subl $0x1000, %ecx /* yes, move pointer down 4k*/ | |
173 | orl $0x0, (%ecx) /* probe there */ | |
174 | subl $0x1000, %eax /* decrement count */ | |
175 | cmpl $0x1000, %eax | |
176 | ja 1b /* and do it again */ | |
177 | ||
178 | 2: subl %eax, %ecx | |
179 | orl $0x0, (%ecx) /* less than 4k, just peek here */ | |
180 | ||
181 | popl %eax | |
182 | cfi_pop(%eax) | |
183 | popl %ecx | |
184 | cfi_pop(%ecx) | |
ccf8e764 | 185 | ret |
174425ad KT |
186 | cfi_endproc() |
187 | #endif /* _WIN64 */ | |
188 | #endif /* L_chkstk_ms */ |