gimplify: Handle void expression as asm input [PR100501, PR100792]
[gcc.git] / libgcc / config / rs6000 / morestack.S
blob49e2fb5280ac9e75bfb70a2502a88229cf261c70
1 #ifdef __powerpc64__
2 # PowerPC64 support for -fsplit-stack.
3 # Copyright (C) 2009-2024 Free Software Foundation, Inc.
4 # Contributed by Alan Modra <amodra@gmail.com>.
6 # This file is part of GCC.
8 # GCC is free software; you can redistribute it and/or modify it under
9 # the terms of the GNU General Public License as published by the Free
10 # Software Foundation; either version 3, or (at your option) any later
11 # version.
13 # GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 # WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 # for more details.
18 # Under Section 7 of GPL version 3, you are granted additional
19 # permissions described in the GCC Runtime Library Exception, version
20 # 3.1, as published by the Free Software Foundation.
22 # You should have received a copy of the GNU General Public License and
23 # a copy of the GCC Runtime Library Exception along with this program;
24 # see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25 # <http://www.gnu.org/licenses/>.
27 #include <auto-host.h>
29 #if _CALL_ELF == 2
30         .abiversion 2
31 #define PARAMS 32
32 #else
33 #define PARAMS 48
34 #endif
35 #define MORESTACK_FRAMESIZE     (PARAMS+96)
36 #define R2_SAVE                 -MORESTACK_FRAMESIZE+PARAMS-8
37 #define PARAMREG_SAVE           -MORESTACK_FRAMESIZE+PARAMS+0
38 #define STATIC_CHAIN_SAVE       -MORESTACK_FRAMESIZE+PARAMS+64
39 #define R29_SAVE                -MORESTACK_FRAMESIZE+PARAMS+72
40 #define LINKREG_SAVE            -MORESTACK_FRAMESIZE+PARAMS+80
41 #define NEWSTACKSIZE_SAVE       -MORESTACK_FRAMESIZE+PARAMS+88
43 # Excess space needed to call ld.so resolver for lazy plt
44 # resolution.  Go uses sigaltstack so this doesn't need to
45 # also cover signal frame size.
46 #define BACKOFF 4096
47 # Large excess allocated when calling non-split-stack code.
48 #define NON_SPLIT_STACK 0x100000
51 #if _CALL_ELF == 2
53 #define BODY_LABEL(name) name
55 #define ENTRY0(name)                                    \
56         .global name;                                   \
57         .hidden name;                                   \
58         .type name,@function;                           \
59 name##:
61 #ifdef __PCREL__
62 #define ENTRY(name)                                     \
63         ENTRY0(name);                                   \
64         .localentry name, 1
65 #define JUMP_TARGET(name) name##@notoc
66 #else
67 #define ENTRY(name)                                     \
68         ENTRY0(name);                                   \
69 0:      addis %r2,%r12,.TOC.-0b@ha;                     \
70         addi %r2,%r2,.TOC.-0b@l;                        \
71         .localentry name, .-name
72 #endif
74 #else
76 #define BODY_LABEL(name) .L.##name
78 #define ENTRY0(name)                                    \
79         .global name;                                   \
80         .hidden name;                                   \
81         .type name,@function;                           \
82         .pushsection ".opd","aw";                       \
83         .p2align 3;                                     \
84 name##: .quad BODY_LABEL (name), .TOC.@tocbase, 0;      \
85         .popsection;                                    \
86 BODY_LABEL(name)##:
88 #define ENTRY(name) ENTRY0(name)
90 #endif
92 #define SIZE(name) .size name, .-BODY_LABEL(name)
94 #ifndef JUMP_TARGET
95 #define JUMP_TARGET(name) name
96 #endif
98         .text
99 # Just like __morestack, but with larger excess allocation
100 ENTRY0(__morestack_non_split)
101 .LFB1:
102         .cfi_startproc
103 # We use a cleanup to restore the tcbhead_t.__private_ss if
104 # an exception is thrown through this code.
105 #ifdef __PIC__
106         .cfi_personality 0x9b,DW.ref.__gcc_personality_v0
107         .cfi_lsda 0x1b,.LLSDA1
108 #else
109         .cfi_personality 0x3,__gcc_personality_v0
110         .cfi_lsda 0x3,.LLSDA1
111 #endif
112 # LR is already saved by the split-stack prologue code.
113 # We may as well have the unwinder skip over the call in the
114 # prologue too.
115         .cfi_offset %lr,16
117         addis %r12,%r12,-NON_SPLIT_STACK@h
118         SIZE (__morestack_non_split)
119 # Fall through into __morestack
122 # This function is called with non-standard calling conventions.
123 # On entry, r12 is the requested stack pointer.  One version of the
124 # split-stack prologue that calls __morestack looks like
125 #       ld %r0,-0x7000-64(%r13)
126 #       addis %r12,%r1,-allocate@ha
127 #       addi %r12,%r12,-allocate@l
128 #       cmpld %r12,%r0
129 #       bge+ enough
130 #       mflr %r0
131 #       std %r0,16(%r1)
132 #       bl __morestack
133 #       ld %r0,16(%r1)
134 #       mtlr %r0
135 #       blr
136 # enough:
137 # The normal function prologue follows here, with a small addition at
138 # the end to set up the arg pointer.  The arg pointer is set up with:
139 #       addi %r12,%r1,offset
140 #       bge %cr7,.+8
141 #       mr %r12,%r29
143 # Note that the lr save slot 16(%r1) has already been used.
144 # r3 thru r11 possibly contain arguments and a static chain
145 # pointer for the function we're calling, so must be preserved.
146 # cr7 must also be preserved.
148 ENTRY0(__morestack)
150 #if _CALL_ELF == 2
151 # Functions with localentry bits of zero cannot make calls if those
152 # calls might change r2.  This is true generally, and also true for
153 # __morestack with its special calling convention.  When __morestack's
154 # caller is non-pcrel but libgcc is pcrel, the functions called here
155 # might modify r2.  r2 must be preserved on exit, and also restored
156 # for the call back to our caller.
157         std %r2,R2_SAVE(%r1)
158 #endif
160 # Save parameter passing registers, our arguments, lr, r29
161 # and use r29 as a frame pointer.
162         std %r3,PARAMREG_SAVE+0(%r1)
163         sub %r3,%r1,%r12                # calculate requested stack size
164         mflr %r12
165         std %r4,PARAMREG_SAVE+8(%r1)
166         std %r5,PARAMREG_SAVE+16(%r1)
167         std %r6,PARAMREG_SAVE+24(%r1)
168         std %r7,PARAMREG_SAVE+32(%r1)
169         addi %r3,%r3,BACKOFF
170         std %r8,PARAMREG_SAVE+40(%r1)
171         std %r9,PARAMREG_SAVE+48(%r1)
172         std %r10,PARAMREG_SAVE+56(%r1)
173         std %r11,STATIC_CHAIN_SAVE(%r1)
174         std %r29,R29_SAVE(%r1)
175         std %r12,LINKREG_SAVE(%r1)
176         std %r3,NEWSTACKSIZE_SAVE(%r1)  # new stack size
177         mr %r29,%r1
178 #if _CALL_ELF == 2
179         .cfi_offset %r2,R2_SAVE
180 #endif
181         .cfi_offset %r29,R29_SAVE
182         .cfi_def_cfa_register %r29
183         stdu %r1,-MORESTACK_FRAMESIZE(%r1)
185 #if _CALL_ELF == 2 && !defined __PCREL__
186 # If this isn't a pcrel libgcc then the functions we call here will
187 # require r2 to be valid.  If __morestack is called from pcrel code r2
188 # won't be valid.  Set it up.
189         bcl 20,31,1f
191         mflr %r12
192         addis %r2,%r12,.TOC.-1b@ha
193         addi %r2,%r2,.TOC.-1b@l
194 #endif
196         # void __morestack_block_signals (void)
197         bl JUMP_TARGET(__morestack_block_signals)
199         # void *__generic_morestack (size_t *pframe_size,
200         #                            void *old_stack,
201         #                            size_t param_size)
202         addi %r3,%r29,NEWSTACKSIZE_SAVE
203         mr %r4,%r29
204         li %r5,0                        # no copying from old stack
205         bl JUMP_TARGET(__generic_morestack)
207 # Start using new stack
208         stdu %r29,-PARAMS(%r3)          # back-chain
209         mr %r1,%r3
211 # Set __private_ss stack guard for the new stack.
212         ld %r12,NEWSTACKSIZE_SAVE(%r29) # modified size
213         addi %r3,%r3,BACKOFF-PARAMS
214         sub %r3,%r3,%r12
215 # Note that a signal frame has $pc pointing at the instruction
216 # where the signal occurred.  For something like a timer
217 # interrupt this means the instruction has already executed,
218 # thus the region starts at the instruction modifying
219 # __private_ss, not one instruction after.
220 .LEHB0:
221         std %r3,-0x7000-64(%r13)        # tcbhead_t.__private_ss
223         # void __morestack_unblock_signals (void)
224         bl JUMP_TARGET(__morestack_unblock_signals)
226 # Set up for a call to the target function, located 3
227 # instructions after __morestack's return address.
229         ld %r12,LINKREG_SAVE(%r29)
230 #if _CALL_ELF == 2
231         ld %r2,R2_SAVE(%r29)
232 #endif
233         ld %r3,PARAMREG_SAVE+0(%r29)    # restore arg regs
234         ld %r4,PARAMREG_SAVE+8(%r29)
235         ld %r5,PARAMREG_SAVE+16(%r29)
236         ld %r6,PARAMREG_SAVE+24(%r29)
237         ld %r7,PARAMREG_SAVE+32(%r29)
238         ld %r8,PARAMREG_SAVE+40(%r29)
239         ld %r9,PARAMREG_SAVE+48(%r29)
240         addi %r0,%r12,12                # add 3 instructions
241         ld %r10,PARAMREG_SAVE+56(%r29)
242         ld %r11,STATIC_CHAIN_SAVE(%r29)
243         cmpld %cr7,%r12,%r0             # indicate we were called
244         mtctr %r0
245         bctrl                           # call caller!
247 # On return, save regs possibly used to return a value, and
248 # possibly trashed by calls to __morestack_block_signals,
249 # __generic_releasestack and __morestack_unblock_signals.
250 # Assume those calls don't use vector or floating point regs.
251         std %r3,PARAMREG_SAVE+0(%r29)
252         std %r4,PARAMREG_SAVE+8(%r29)
253         std %r5,PARAMREG_SAVE+16(%r29)
254         std %r6,PARAMREG_SAVE+24(%r29)
255 #if _CALL_ELF == 2
256         std %r7,PARAMREG_SAVE+32(%r29)
257         std %r8,PARAMREG_SAVE+40(%r29)
258         std %r9,PARAMREG_SAVE+48(%r29)
259         std %r10,PARAMREG_SAVE+56(%r29)
260 #endif
262 #if _CALL_ELF == 2 && !defined __PCREL__
263 # r2 was restored for calling back into our caller.  Set it up again.
264         bcl 20,31,1f
266         mflr %r12
267         addis %r2,%r12,.TOC.-1b@ha
268         addi %r2,%r2,.TOC.-1b@l
269 #endif
271         bl JUMP_TARGET(__morestack_block_signals)
273         # void *__generic_releasestack (size_t *pavailable)
274         addi %r3,%r29,NEWSTACKSIZE_SAVE
275         bl JUMP_TARGET(__generic_releasestack)
277 # Reset __private_ss stack guard to value for old stack
278         ld %r12,NEWSTACKSIZE_SAVE(%r29)
279         addi %r3,%r3,BACKOFF
280         sub %r3,%r3,%r12
281 .LEHE0:
282         std %r3,-0x7000-64(%r13)        # tcbhead_t.__private_ss
284         bl JUMP_TARGET(__morestack_unblock_signals)
286 # Use old stack again.
287         mr %r1,%r29
289 # Restore return value regs, and return.
290         ld %r0,LINKREG_SAVE(%r29)
291         mtlr %r0
292 #if _CALL_ELF == 2
293         ld %r2,R2_SAVE(%r29)
294 #endif
295         ld %r3,PARAMREG_SAVE+0(%r29)
296         ld %r4,PARAMREG_SAVE+8(%r29)
297         ld %r5,PARAMREG_SAVE+16(%r29)
298         ld %r6,PARAMREG_SAVE+24(%r29)
299 #if _CALL_ELF == 2
300         ld %r7,PARAMREG_SAVE+32(%r29)
301         ld %r8,PARAMREG_SAVE+40(%r29)
302         ld %r9,PARAMREG_SAVE+48(%r29)
303         ld %r10,PARAMREG_SAVE+56(%r29)
304 #endif
305         ld %r29,R29_SAVE(%r29)
306         .cfi_def_cfa_register %r1
307         blr
309 # This is the cleanup code called by the stack unwinder when
310 # unwinding through code between .LEHB0 and .LEHE0 above.
311 cleanup:
312         .cfi_def_cfa_register %r29
313         std %r3,PARAMREG_SAVE(%r29)     # Save exception header
314         # size_t __generic_findstack (void *stack)
315         mr %r3,%r29
316         bl JUMP_TARGET(__generic_findstack)
317         sub %r3,%r29,%r3
318         addi %r3,%r3,BACKOFF
319         std %r3,-0x7000-64(%r13)        # tcbhead_t.__private_ss
320         ld %r3,PARAMREG_SAVE(%r29)
321         bl JUMP_TARGET(_Unwind_Resume)
322 #ifndef __PCREL__
323         nop
324 #endif
325         .cfi_endproc
326         SIZE (__morestack)
329         .section .gcc_except_table,"a",@progbits
330         .p2align 2
331 .LLSDA1:
332         .byte   0xff    # @LPStart format (omit)
333         .byte   0xff    # @TType format (omit)
334         .byte   0x1     # call-site format (uleb128)
335         .uleb128 .LLSDACSE1-.LLSDACSB1  # Call-site table length
336 .LLSDACSB1:
337         .uleb128 .LEHB0-.LFB1   # region 0 start
338         .uleb128 .LEHE0-.LEHB0  # length
339         .uleb128 cleanup-.LFB1  # landing pad
340         .uleb128 0              # no action, ie. a cleanup
341 .LLSDACSE1:
344 #ifdef __PIC__
345 # Build a position independent reference to the personality function.
346         .hidden DW.ref.__gcc_personality_v0
347         .weak DW.ref.__gcc_personality_v0
348         .section .data.DW.ref.__gcc_personality_v0,"awG",@progbits,DW.ref.__gcc_personality_v0,comdat
349         .p2align 3
350 DW.ref.__gcc_personality_v0:
351         .quad __gcc_personality_v0
352         .type DW.ref.__gcc_personality_v0, @object
353         .size DW.ref.__gcc_personality_v0, 8
354 #endif
357         .text
358 # Initialize the stack guard when the program starts or when a
359 # new thread starts.  This is called from a constructor.
360 # void __stack_split_initialize (void)
361 ENTRY(__stack_split_initialize)
362         .cfi_startproc
363         addi %r3,%r1,-0x4000            # We should have at least 16K.
364         std %r3,-0x7000-64(%r13)        # tcbhead_t.__private_ss
365         # void __generic_morestack_set_initial_sp (void *sp, size_t len)
366         mr %r3,%r1
367         li %r4, 0x4000
368         b JUMP_TARGET(__generic_morestack_set_initial_sp)
369 # The lack of .cfi_endproc here is deliberate.  This function and the
370 # following ones can all use the default FDE.
371         SIZE (__stack_split_initialize)
374 # Return current __private_ss
375 # void *__morestack_get_guard (void)
376 ENTRY0(__morestack_get_guard)
377         ld %r3,-0x7000-64(%r13)         # tcbhead_t.__private_ss
378         blr
379         SIZE (__morestack_get_guard)
382 # Set __private_ss
383 # void __morestack_set_guard (void *ptr)
384 ENTRY0(__morestack_set_guard)
385         std %r3,-0x7000-64(%r13)        # tcbhead_t.__private_ss
386         blr
387         SIZE (__morestack_set_guard)
390 # Return the stack guard value for given stack
391 # void *__morestack_make_guard (void *stack, size_t size)
392 ENTRY0(__morestack_make_guard)
393         sub %r3,%r3,%r4
394         addi %r3,%r3,BACKOFF
395         blr
396         .cfi_endproc
397         SIZE (__morestack_make_guard)
400 # Make __stack_split_initialize a high priority constructor.
401 #if HAVE_INITFINI_ARRAY_SUPPORT
402         .section .init_array.00000,"aw",@init_array
403 #else
404         .section .ctors.65535,"aw",@progbits
405 #endif
406         .p2align 3
407         .quad __stack_split_initialize
408         .quad __morestack_load_mmap
410         .section .note.GNU-stack,"",@progbits
411         .section .note.GNU-split-stack,"",@progbits
412         .section .note.GNU-no-split-stack,"",@progbits
413 #endif /* __powerpc64__ */