1 # s390 support for -fsplit-stack.
2 # Copyright (C) 2015-2023 Free Software Foundation, Inc.
3 # Contributed by Marcin KoĆcielnicki <koriakin@0x04.net>.
5 # This file is part of GCC.
7 # GCC is free software; you can redistribute it and/or modify it under
8 # the terms of the GNU General Public License as published by the Free
9 # Software Foundation; either version 3, or (at your option) any later
12 # GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
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.
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/>.
26 # Excess space needed to call ld.so resolver for lazy plt
27 # resolution. Go uses sigaltstack so this doesn't need to
28 # also cover signal frame size.
29 #define BACKOFF 0x1000
31 #include <auto-host.h>
33 # The __morestack function.
38 .type __morestack,@function
48 # The 31-bit __morestack function.
50 # We use a cleanup to restore the stack guard if an exception
51 # is thrown through this code.
53 .cfi_personality 0,__gcc_personality_v0
56 .cfi_personality 0x9b,DW.ref.__gcc_personality_v0
57 .cfi_lsda 0x1b,.LLSDA1
60 stm %r2, %r15, 0x8(%r15) # Save %r2-%r15.
61 .cfi_offset %r6, -0x48
62 .cfi_offset %r7, -0x44
63 .cfi_offset %r8, -0x40
64 .cfi_offset %r9, -0x3c
65 .cfi_offset %r10, -0x38
66 .cfi_offset %r11, -0x34
67 .cfi_offset %r12, -0x30
68 .cfi_offset %r13, -0x2c
69 .cfi_offset %r14, -0x28
70 .cfi_offset %r15, -0x24
71 lr %r11, %r15 # Make frame pointer for vararg.
72 .cfi_def_cfa_register %r11
73 ahi %r15, -0x60 # 0x60 for standard frame.
74 st %r11, 0(%r15) # Save back chain.
75 lr %r8, %r0 # Save %r0 (static chain).
76 lr %r10, %r1 # Save %r1 (address of parameter block).
78 l %r7, 0(%r10) # Required frame size to %r7
79 ear %r1, %a0 # Extract thread pointer.
80 l %r1, 0x20(%r1) # Get stack bounduary
81 ar %r1, %r7 # Stack bounduary + frame size
82 a %r1, 4(%r10) # + stack param size
83 clr %r1, %r15 # Compare with current stack pointer
84 jle .Lnoalloc # guard > sp - frame-size: need alloc
86 brasl %r14, __morestack_block_signals
88 # We abuse one of caller's fpr save slots (which we don't use for fprs)
89 # as a local variable. Not needed here, but done to be consistent with
91 ahi %r7, BACKOFF # Bump requested size a bit.
92 st %r7, 0x40(%r11) # Stuff frame size on stack.
93 la %r2, 0x40(%r11) # Pass its address as parameter.
94 la %r3, 0x60(%r11) # Caller's stack parameters.
95 l %r4, 4(%r10) # Size of stack parameters.
96 brasl %r14, __generic_morestack
98 lr %r15, %r2 # Switch to the new stack.
99 ahi %r15, -0x60 # Make a stack frame on it.
100 st %r11, 0(%r15) # Save back chain.
102 s %r2, 0x40(%r11) # The end of stack space.
103 ahi %r2, BACKOFF # Back off a bit.
104 ear %r1, %a0 # Extract thread pointer.
106 st %r2, 0x20(%r1) # Save the new stack boundary.
108 brasl %r14, __morestack_unblock_signals
110 lr %r0, %r8 # Static chain.
111 lm %r2, %r6, 0x8(%r11) # Paremeter registers.
113 # Third parameter is address of function meat - address of parameter
117 # Leave vararg pointer in %r1, in case function uses it
120 # State of registers:
121 # %r0: Static chain from entry.
122 # %r1: Vararg pointer.
123 # %r2-%r6: Parameters from entry.
124 # %r7-%r10: Indeterminate.
125 # %r11: Frame pointer (%r15 from entry).
126 # %r12-%r13: Indeterminate.
127 # %r14: Return address.
128 # %r15: Stack pointer.
129 basr %r14, %r10 # Call our caller.
131 stm %r2, %r3, 0x8(%r11) # Save return registers.
133 brasl %r14, __morestack_block_signals
135 # We need a stack slot now, but have no good way to get it - the frame
136 # on new stack had to be exactly 0x60 bytes, or stack parameters would
137 # be passed wrong. Abuse fpr save area in caller's frame (we don't
140 brasl %r14, __generic_releasestack
142 s %r2, 0x40(%r11) # Subtract available space.
143 ahi %r2, BACKOFF # Back off a bit.
144 ear %r1, %a0 # Extract thread pointer.
146 st %r2, 0x20(%r1) # Save the new stack boundary.
148 # We need to restore the old stack pointer before unblocking signals.
149 # We also need 0x60 bytes for a stack frame. Since we had a stack
150 # frame at this place before the stack switch, there's no need to
151 # write the back chain again.
155 brasl %r14, __morestack_unblock_signals
157 lm %r2, %r15, 0x8(%r11) # Restore all registers.
169 .cfi_def_cfa_register %r15
170 br %r14 # Return to caller's caller.
172 # Executed if no new stack allocation is needed.
176 # We may need to copy stack parameters.
177 l %r9, 0x4(%r10) # Load stack parameter size.
178 ltr %r9, %r9 # And check if it's 0.
179 je .Lnostackparm # Skip the copy if not needed.
180 sr %r15, %r9 # Make space on the stack.
181 la %r8, 0x60(%r15) # Destination.
182 la %r12, 0x60(%r11) # Source.
183 lr %r13, %r9 # Source size.
185 mvcle %r8, %r12, 0 # Copy.
189 # Third parameter is address of function meat - address of parameter
193 # Leave vararg pointer in %r1, in case function uses it
196 # OK, no stack allocation needed. We still follow the protocol and
197 # call our caller - it doesn't cost much and makes sure vararg works.
198 # No need to set any registers here - %r0 and %r2-%r6 weren't modified.
199 basr %r14, %r10 # Call our caller.
201 lm %r6, %r15, 0x18(%r11) # Restore all callee-saved registers.
213 .cfi_def_cfa_register %r15
214 br %r14 # Return to caller's caller.
216 # This is the cleanup code called by the stack unwinder when unwinding
217 # through the code between .LEHB0 and .LEHE0 above.
221 lr %r2, %r11 # Stack pointer after resume.
222 brasl %r14, __generic_findstack
223 lr %r3, %r11 # Get the stack pointer.
224 sr %r3, %r2 # Subtract available space.
225 ahi %r3, BACKOFF # Back off a bit.
226 ear %r1, %a0 # Extract thread pointer.
227 st %r3, 0x20(%r1) # Save the new stack boundary.
229 # We need GOT pointer in %r12 for PLT entry.
230 larl %r12,_GLOBAL_OFFSET_TABLE_
231 lr %r2, %r6 # Exception header.
233 brasl %r14, _Unwind_Resume@PLT
235 brasl %r14, _Unwind_Resume
238 #else /* defined(__s390x__) */
241 # The 64-bit __morestack function.
243 # We use a cleanup to restore the stack guard if an exception
244 # is thrown through this code.
246 .cfi_personality 0x3,__gcc_personality_v0
247 .cfi_lsda 0x3,.LLSDA1
249 .cfi_personality 0x9b,DW.ref.__gcc_personality_v0
250 .cfi_lsda 0x1b,.LLSDA1
253 stmg %r2, %r15, 0x10(%r15) # Save %r2-%r15.
254 .cfi_offset %r6, -0x70
255 .cfi_offset %r7, -0x68
256 .cfi_offset %r8, -0x60
257 .cfi_offset %r9, -0x58
258 .cfi_offset %r10, -0x50
259 .cfi_offset %r11, -0x48
260 .cfi_offset %r12, -0x40
261 .cfi_offset %r13, -0x38
262 .cfi_offset %r14, -0x30
263 .cfi_offset %r15, -0x28
264 lgr %r11, %r15 # Make frame pointer for vararg.
265 .cfi_def_cfa_register %r11
266 aghi %r15, -0xa0 # 0xa0 for standard frame.
267 stg %r11, 0(%r15) # Save back chain.
268 lgr %r8, %r0 # Save %r0 (static chain).
269 lgr %r10, %r1 # Save %r1 (address of parameter block).
271 lg %r7, 0(%r10) # Required frame size to %r7
274 ear %r1, %a1 # Extract thread pointer.
275 lg %r1, 0x38(%r1) # Get stack bounduary
276 agr %r1, %r7 # Stack bounduary + frame size
277 ag %r1, 8(%r10) # + stack param size
278 clgr %r1, %r15 # Compare with current stack pointer
279 jle .Lnoalloc # guard > sp - frame-size: need alloc
281 brasl %r14, __morestack_block_signals
283 # We abuse one of caller's fpr save slots (which we don't use for fprs)
284 # as a local variable. Not needed here, but done to be consistent with
286 aghi %r7, BACKOFF # Bump requested size a bit.
287 stg %r7, 0x80(%r11) # Stuff frame size on stack.
288 la %r2, 0x80(%r11) # Pass its address as parameter.
289 la %r3, 0xa0(%r11) # Caller's stack parameters.
290 lg %r4, 8(%r10) # Size of stack parameters.
291 brasl %r14, __generic_morestack
293 lgr %r15, %r2 # Switch to the new stack.
294 aghi %r15, -0xa0 # Make a stack frame on it.
295 stg %r11, 0(%r15) # Save back chain.
297 sg %r2, 0x80(%r11) # The end of stack space.
298 aghi %r2, BACKOFF # Back off a bit.
301 ear %r1, %a1 # Extract thread pointer.
303 stg %r2, 0x38(%r1) # Save the new stack boundary.
305 brasl %r14, __morestack_unblock_signals
307 lgr %r0, %r8 # Static chain.
308 lmg %r2, %r6, 0x10(%r11) # Paremeter registers.
310 # Third parameter is address of function meat - address of parameter
314 # Leave vararg pointer in %r1, in case function uses it
317 # State of registers:
318 # %r0: Static chain from entry.
319 # %r1: Vararg pointer.
320 # %r2-%r6: Parameters from entry.
321 # %r7-%r10: Indeterminate.
322 # %r11: Frame pointer (%r15 from entry).
323 # %r12-%r13: Indeterminate.
324 # %r14: Return address.
325 # %r15: Stack pointer.
326 basr %r14, %r10 # Call our caller.
328 stg %r2, 0x10(%r11) # Save return register.
330 brasl %r14, __morestack_block_signals
332 # We need a stack slot now, but have no good way to get it - the frame
333 # on new stack had to be exactly 0xa0 bytes, or stack parameters would
334 # be passed wrong. Abuse fpr save area in caller's frame (we don't
337 brasl %r14, __generic_releasestack
339 sg %r2, 0x80(%r11) # Subtract available space.
340 aghi %r2, BACKOFF # Back off a bit.
343 ear %r1, %a1 # Extract thread pointer.
345 stg %r2, 0x38(%r1) # Save the new stack boundary.
347 # We need to restore the old stack pointer before unblocking signals.
348 # We also need 0xa0 bytes for a stack frame. Since we had a stack
349 # frame at this place before the stack switch, there's no need to
350 # write the back chain again.
354 brasl %r14, __morestack_unblock_signals
356 lmg %r2, %r15, 0x10(%r11) # Restore all registers.
368 .cfi_def_cfa_register %r15
369 br %r14 # Return to caller's caller.
371 # Executed if no new stack allocation is needed.
375 # We may need to copy stack parameters.
376 lg %r9, 0x8(%r10) # Load stack parameter size.
377 ltgr %r9, %r9 # Check if it's 0.
378 je .Lnostackparm # Skip the copy if not needed.
379 sgr %r15, %r9 # Make space on the stack.
380 la %r8, 0xa0(%r15) # Destination.
381 la %r12, 0xa0(%r11) # Source.
382 lgr %r13, %r9 # Source size.
384 mvcle %r8, %r12, 0 # Copy.
388 # Third parameter is address of function meat - address of parameter
392 # Leave vararg pointer in %r1, in case function uses it
395 # OK, no stack allocation needed. We still follow the protocol and
396 # call our caller - it doesn't cost much and makes sure vararg works.
397 # No need to set any registers here - %r0 and %r2-%r6 weren't modified.
398 basr %r14, %r10 # Call our caller.
400 lmg %r6, %r15, 0x30(%r11) # Restore all callee-saved registers.
412 .cfi_def_cfa_register %r15
413 br %r14 # Return to caller's caller.
415 # This is the cleanup code called by the stack unwinder when unwinding
416 # through the code between .LEHB0 and .LEHE0 above.
420 lgr %r2, %r11 # Stack pointer after resume.
421 brasl %r14, __generic_findstack
422 lgr %r3, %r11 # Get the stack pointer.
423 sgr %r3, %r2 # Subtract available space.
424 aghi %r3, BACKOFF # Back off a bit.
427 ear %r1, %a1 # Extract thread pointer.
428 stg %r3, 0x38(%r1) # Save the new stack boundary.
430 lgr %r2, %r6 # Exception header.
432 brasl %r14, _Unwind_Resume@PLT
434 brasl %r14, _Unwind_Resume
437 #endif /* defined(__s390x__) */
440 .size __morestack, . - __morestack
443 # The exception table. This tells the personality routine to execute
444 # the exception handler.
446 .section .gcc_except_table,"a",@progbits
449 .byte 0xff # @LPStart format (omit)
450 .byte 0xff # @TType format (omit)
451 .byte 0x1 # call-site format (uleb128)
452 .uleb128 .LLSDACSE1-.LLSDACSB1 # Call-site table length
454 .uleb128 .LEHB0-.LFB1 # region 0 start
455 .uleb128 .LEHE0-.LEHB0 # length
456 .uleb128 .L1-.LFB1 # landing pad
461 .global __gcc_personality_v0
463 # Build a position independent reference to the basic
464 # personality function.
465 .hidden DW.ref.__gcc_personality_v0
466 .weak DW.ref.__gcc_personality_v0
467 .section .data.DW.ref.__gcc_personality_v0,"awG",@progbits,DW.ref.__gcc_personality_v0,comdat
468 .type DW.ref.__gcc_personality_v0, @object
469 DW.ref.__gcc_personality_v0:
472 .size DW.ref.__gcc_personality_v0, 4
473 .long __gcc_personality_v0
476 .size DW.ref.__gcc_personality_v0, 8
477 .quad __gcc_personality_v0
483 # Initialize the stack test value when the program starts or when a
484 # new thread starts. We don't know how large the main stack is, so we
485 # guess conservatively. We might be able to use getrlimit here.
488 .global __stack_split_initialize
489 .hidden __stack_split_initialize
491 .type __stack_split_initialize, @function
493 __stack_split_initialize:
499 ahi %r0, -0x4000 # We should have at least 16K.
505 jg __generic_morestack_set_initial_sp@PLT # Tail call
507 jg __generic_morestack_set_initial_sp # Tail call
510 #else /* defined(__s390x__) */
516 aghi %r0, -0x4000 # We should have at least 16K.
522 jg __generic_morestack_set_initial_sp@PLT # Tail call
524 jg __generic_morestack_set_initial_sp # Tail call
527 #endif /* defined(__s390x__) */
529 .size __stack_split_initialize, . - __stack_split_initialize
531 # Routines to get and set the guard, for __splitstack_getcontext,
532 # __splitstack_setcontext, and __splitstack_makecontext.
534 # void *__morestack_get_guard (void) returns the current stack guard.
536 .global __morestack_get_guard
537 .hidden __morestack_get_guard
539 .type __morestack_get_guard,@function
541 __morestack_get_guard:
554 .size __morestack_get_guard, . - __morestack_get_guard
556 # void __morestack_set_guard (void *) sets the stack guard.
557 .global __morestack_set_guard
558 .hidden __morestack_set_guard
560 .type __morestack_set_guard,@function
562 __morestack_set_guard:
575 .size __morestack_set_guard, . - __morestack_set_guard
577 # void *__morestack_make_guard (void *, size_t) returns the stack
578 # guard value for a stack.
579 .global __morestack_make_guard
580 .hidden __morestack_make_guard
582 .type __morestack_make_guard,@function
584 __morestack_make_guard:
595 .size __morestack_make_guard, . - __morestack_make_guard
597 # Make __stack_split_initialize a high priority constructor.
599 #if HAVE_INITFINI_ARRAY_SUPPORT
600 .section .init_array.00000,"aw",@progbits
602 .section .ctors.65535,"aw",@progbits
607 .long __stack_split_initialize
608 .long __morestack_load_mmap
611 .quad __stack_split_initialize
612 .quad __morestack_load_mmap
615 .section .note.GNU-stack,"",@progbits
616 .section .note.GNU-split-stack,"",@progbits
617 .section .note.GNU-no-split-stack,"",@progbits