Fix atomic operations on PA-RISC 2.0 processors.
[official-gcc.git] / libgcc / config / s390 / morestack.S
blobdb50e60fca303ce03e4fc047b211313222b43403
1 # s390 support for -fsplit-stack.
2 # Copyright (C) 2015-2022 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
10 # version.
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
15 # for more details.
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.
35         .global __morestack
36         .hidden __morestack
38         .type   __morestack,@function
40 __morestack:
41 .LFB1:
42         .cfi_startproc
45 #ifndef __s390x__
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.
52 #ifndef __PIC__
53         .cfi_personality 0,__gcc_personality_v0
54         .cfi_lsda 0,.LLSDA1
55 #else
56         .cfi_personality 0x9b,DW.ref.__gcc_personality_v0
57         .cfi_lsda 0x1b,.LLSDA1
58 #endif
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
90         # the below use.
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.
105 .LEHB0:
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
114         # block.
115         a       %r10, 0x8(%r10)
117         # Leave vararg pointer in %r1, in case function uses it
118         la      %r1, 0x60(%r11)
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
138         # save actual fprs).
139         la      %r2, 0x40(%r11)
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.
145 .LEHE0:
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.
152         lr      %r15, %r11
153         ahi     %r15, -0x60
155         brasl   %r14, __morestack_unblock_signals
157         lm      %r2, %r15, 0x8(%r11)    # Restore all registers.
158         .cfi_remember_state
159         .cfi_restore %r15
160         .cfi_restore %r14
161         .cfi_restore %r13
162         .cfi_restore %r12
163         .cfi_restore %r11
164         .cfi_restore %r10
165         .cfi_restore %r9
166         .cfi_restore %r8
167         .cfi_restore %r7
168         .cfi_restore %r6
169         .cfi_def_cfa_register %r15
170         br      %r14                    # Return to caller's caller.
172 # Executed if no new stack allocation is needed.
174 .Lnoalloc:
175         .cfi_restore_state
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.
184 .Lcopy:
185         mvcle   %r8, %r12, 0            # Copy.
186         jo      .Lcopy
188 .Lnostackparm:
189         # Third parameter is address of function meat - address of parameter
190         # block.
191         a       %r10, 0x8(%r10)
193         # Leave vararg pointer in %r1, in case function uses it
194         la      %r1, 0x60(%r11)
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.
202         .cfi_remember_state
203         .cfi_restore %r15
204         .cfi_restore %r14
205         .cfi_restore %r13
206         .cfi_restore %r12
207         .cfi_restore %r11
208         .cfi_restore %r10
209         .cfi_restore %r9
210         .cfi_restore %r8
211         .cfi_restore %r7
212         .cfi_restore %r6
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.
219 .L1:
220         .cfi_restore_state
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.
232 #ifdef __PIC__
233         brasl   %r14, _Unwind_Resume@PLT
234 #else
235         brasl   %r14, _Unwind_Resume
236 #endif
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.
245 #ifndef __PIC__
246         .cfi_personality 0x3,__gcc_personality_v0
247         .cfi_lsda 0x3,.LLSDA1
248 #else
249         .cfi_personality 0x9b,DW.ref.__gcc_personality_v0
250         .cfi_lsda 0x1b,.LLSDA1
251 #endif
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
272         ear     %r1, %a0
273         sllg    %r1, %r1, 32
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
285         # the below use.
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.
299         ear     %r1, %a0
300         sllg    %r1, %r1, 32
301         ear     %r1, %a1                # Extract thread pointer.
302 .LEHB0:
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
311         # block.
312         ag      %r10, 0x10(%r10)
314         # Leave vararg pointer in %r1, in case function uses it
315         la      %r1, 0xa0(%r11)
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
335         # save actual fprs).
336         la      %r2, 0x80(%r11)
337         brasl   %r14, __generic_releasestack
339         sg      %r2, 0x80(%r11)         # Subtract available space.
340         aghi    %r2, BACKOFF            # Back off a bit.
341         ear     %r1, %a0
342         sllg    %r1, %r1, 32
343         ear     %r1, %a1                # Extract thread pointer.
344 .LEHE0:
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.
351         lgr     %r15, %r11
352         aghi    %r15, -0xa0
354         brasl   %r14, __morestack_unblock_signals
356         lmg     %r2, %r15, 0x10(%r11)   # Restore all registers.
357         .cfi_remember_state
358         .cfi_restore %r15
359         .cfi_restore %r14
360         .cfi_restore %r13
361         .cfi_restore %r12
362         .cfi_restore %r11
363         .cfi_restore %r10
364         .cfi_restore %r9
365         .cfi_restore %r8
366         .cfi_restore %r7
367         .cfi_restore %r6
368         .cfi_def_cfa_register %r15
369         br      %r14                    # Return to caller's caller.
371 # Executed if no new stack allocation is needed.
373 .Lnoalloc:
374         .cfi_restore_state
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.
383 .Lcopy:
384         mvcle   %r8, %r12, 0            # Copy.
385         jo      .Lcopy
387 .Lnostackparm:
388         # Third parameter is address of function meat - address of parameter
389         # block.
390         ag      %r10, 0x10(%r10)
392         # Leave vararg pointer in %r1, in case function uses it
393         la      %r1, 0xa0(%r11)
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.
401         .cfi_remember_state
402         .cfi_restore %r15
403         .cfi_restore %r14
404         .cfi_restore %r13
405         .cfi_restore %r12
406         .cfi_restore %r11
407         .cfi_restore %r10
408         .cfi_restore %r9
409         .cfi_restore %r8
410         .cfi_restore %r7
411         .cfi_restore %r6
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.
418 .L1:
419         .cfi_restore_state
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.
425         ear     %r1, %a0
426         sllg    %r1, %r1, 32
427         ear     %r1, %a1                # Extract thread pointer.
428         stg     %r3, 0x38(%r1)  # Save the new stack boundary.
430         lgr     %r2, %r6                # Exception header.
431 #ifdef __PIC__
432         brasl   %r14, _Unwind_Resume@PLT
433 #else
434         brasl   %r14, _Unwind_Resume
435 #endif
437 #endif /* defined(__s390x__) */
439         .cfi_endproc
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
447         .align  4
448 .LLSDA1:
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
453 .LLSDACSB1:
454         .uleb128 .LEHB0-.LFB1   # region 0 start
455         .uleb128 .LEHE0-.LEHB0  # length
456         .uleb128 .L1-.LFB1      # landing pad
457         .uleb128 0              # action
458 .LLSDACSE1:
461         .global __gcc_personality_v0
462 #ifdef __PIC__
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:
470 #ifndef __LP64__
471         .align 4
472         .size   DW.ref.__gcc_personality_v0, 4
473         .long   __gcc_personality_v0
474 #else
475         .align 8
476         .size   DW.ref.__gcc_personality_v0, 8
477         .quad   __gcc_personality_v0
478 #endif
479 #endif
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.
487         .text
488         .global __stack_split_initialize
489         .hidden __stack_split_initialize
491         .type   __stack_split_initialize, @function
493 __stack_split_initialize:
495 #ifndef __s390x__
497         ear     %r1, %a0
498         lr      %r0, %r15
499         ahi     %r0, -0x4000    # We should have at least 16K.
500         st      %r0, 0x20(%r1)
502         lr      %r2, %r15
503         lhi     %r3, 0x4000
504 #ifdef __PIC__
505         jg      __generic_morestack_set_initial_sp@PLT  # Tail call
506 #else
507         jg      __generic_morestack_set_initial_sp      # Tail call
508 #endif
510 #else /* defined(__s390x__) */
512         ear     %r1, %a0
513         sllg    %r1, %r1, 32
514         ear     %r1, %a1
515         lgr     %r0, %r15
516         aghi    %r0, -0x4000    # We should have at least 16K.
517         stg     %r0, 0x38(%r1)
519         lgr     %r2, %r15
520         lghi    %r3, 0x4000
521 #ifdef __PIC__
522         jg      __generic_morestack_set_initial_sp@PLT  # Tail call
523 #else
524         jg      __generic_morestack_set_initial_sp      # Tail call
525 #endif
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.
535         .text
536         .global __morestack_get_guard
537         .hidden __morestack_get_guard
539         .type   __morestack_get_guard,@function
541 __morestack_get_guard:
543 #ifndef __s390x__
544         ear     %r1, %a0
545         l       %r2, 0x20(%r1)
546 #else
547         ear     %r1, %a0
548         sllg    %r1, %r1, 32
549         ear     %r1, %a1
550         lg      %r2, 0x38(%r1)
551 #endif
552         br %r14
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:
564 #ifndef __s390x__
565         ear     %r1, %a0
566         st      %r2, 0x20(%r1)
567 #else
568         ear     %r1, %a0
569         sllg    %r1, %r1, 32
570         ear     %r1, %a1
571         stg     %r2, 0x38(%r1)
572 #endif
573         br      %r14
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:
586 #ifndef __s390x__
587         sr      %r2, %r3
588         ahi     %r2, BACKOFF
589 #else
590         sgr     %r2, %r3
591         aghi    %r2, BACKOFF
592 #endif
593         br      %r14
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
601 #else
602         .section .ctors.65535,"aw",@progbits
603 #endif
605 #ifndef __LP64__
606         .align  4
607         .long   __stack_split_initialize
608         .long   __morestack_load_mmap
609 #else
610         .align  8
611         .quad   __stack_split_initialize
612         .quad   __morestack_load_mmap
613 #endif
615         .section        .note.GNU-stack,"",@progbits
616         .section        .note.GNU-split-stack,"",@progbits
617         .section        .note.GNU-no-split-stack,"",@progbits