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