xref: /netbsd-src/external/gpl3/gcc/dist/libgcc/config/s390/morestack.S (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1# s390 support for -fsplit-stack.
2# Copyright (C) 2015-2022 Free Software Foundation, Inc.
3# Contributed by Marcin Kościelnicki <koriakin@0x04.net>.
4
5# This file is part of GCC.
6
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.
11
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.
16
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.
20
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/>.
25
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
30
31#include <auto-host.h>
32
33# The __morestack function.
34
35	.global	__morestack
36	.hidden	__morestack
37
38	.type	__morestack,@function
39
40__morestack:
41.LFB1:
42	.cfi_startproc
43
44
45#ifndef __s390x__
46
47
48# The 31-bit __morestack function.
49
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
59
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).
77
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
85
86	brasl	%r14, __morestack_block_signals
87
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
97
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.
101
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.
107
108	brasl	%r14, __morestack_unblock_signals
109
110	lr	%r0, %r8		# Static chain.
111	lm	%r2, %r6, 0x8(%r11)	# Paremeter registers.
112
113	# Third parameter is address of function meat - address of parameter
114	# block.
115	a	%r10, 0x8(%r10)
116
117	# Leave vararg pointer in %r1, in case function uses it
118	la	%r1, 0x60(%r11)
119
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.
130
131	stm	%r2, %r3, 0x8(%r11)	# Save return registers.
132
133	brasl	%r14, __morestack_block_signals
134
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
141
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.
147
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
154
155	brasl	%r14, __morestack_unblock_signals
156
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.
171
172# Executed if no new stack allocation is needed.
173
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
187
188.Lnostackparm:
189	# Third parameter is address of function meat - address of parameter
190	# block.
191	a	%r10, 0x8(%r10)
192
193	# Leave vararg pointer in %r1, in case function uses it
194	la	%r1, 0x60(%r11)
195
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.
200
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.
215
216# This is the cleanup code called by the stack unwinder when unwinding
217# through the code between .LEHB0 and .LEHE0 above.
218
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.
228
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
237
238#else /* defined(__s390x__) */
239
240
241# The 64-bit __morestack function.
242
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
252
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).
270
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
280
281	brasl	%r14, __morestack_block_signals
282
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
292
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.
296
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.
304
305	brasl	%r14, __morestack_unblock_signals
306
307	lgr	%r0, %r8		# Static chain.
308	lmg	%r2, %r6, 0x10(%r11)	# Paremeter registers.
309
310	# Third parameter is address of function meat - address of parameter
311	# block.
312	ag	%r10, 0x10(%r10)
313
314	# Leave vararg pointer in %r1, in case function uses it
315	la	%r1, 0xa0(%r11)
316
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.
327
328	stg	%r2, 0x10(%r11)		# Save return register.
329
330	brasl	%r14, __morestack_block_signals
331
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
338
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.
346
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
353
354	brasl	%r14, __morestack_unblock_signals
355
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.
370
371# Executed if no new stack allocation is needed.
372
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
386
387.Lnostackparm:
388	# Third parameter is address of function meat - address of parameter
389	# block.
390	ag	%r10, 0x10(%r10)
391
392	# Leave vararg pointer in %r1, in case function uses it
393	la	%r1, 0xa0(%r11)
394
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.
399
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.
414
415# This is the cleanup code called by the stack unwinder when unwinding
416# through the code between .LEHB0 and .LEHE0 above.
417
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.
429
430	lgr	%r2, %r6		# Exception header.
431#ifdef __PIC__
432	brasl	%r14, _Unwind_Resume@PLT
433#else
434	brasl	%r14, _Unwind_Resume
435#endif
436
437#endif /* defined(__s390x__) */
438
439	.cfi_endproc
440	.size	__morestack, . - __morestack
441
442
443# The exception table.  This tells the personality routine to execute
444# the exception handler.
445
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:
459
460
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
469DW.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
480
481
482
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.
486
487	.text
488	.global	__stack_split_initialize
489	.hidden	__stack_split_initialize
490
491	.type	__stack_split_initialize, @function
492
493__stack_split_initialize:
494
495#ifndef __s390x__
496
497	ear	%r1, %a0
498	lr	%r0, %r15
499	ahi	%r0, -0x4000	# We should have at least 16K.
500	st	%r0, 0x20(%r1)
501
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
509
510#else /* defined(__s390x__) */
511
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)
518
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
526
527#endif /* defined(__s390x__) */
528
529	.size	__stack_split_initialize, . - __stack_split_initialize
530
531# Routines to get and set the guard, for __splitstack_getcontext,
532# __splitstack_setcontext, and __splitstack_makecontext.
533
534# void *__morestack_get_guard (void) returns the current stack guard.
535	.text
536	.global	__morestack_get_guard
537	.hidden	__morestack_get_guard
538
539	.type	__morestack_get_guard,@function
540
541__morestack_get_guard:
542
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
553
554	.size	__morestack_get_guard, . - __morestack_get_guard
555
556# void __morestack_set_guard (void *) sets the stack guard.
557	.global	__morestack_set_guard
558	.hidden	__morestack_set_guard
559
560	.type	__morestack_set_guard,@function
561
562__morestack_set_guard:
563
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
574
575	.size	__morestack_set_guard, . - __morestack_set_guard
576
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
581
582	.type	__morestack_make_guard,@function
583
584__morestack_make_guard:
585
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
594
595	.size	__morestack_make_guard, . - __morestack_make_guard
596
597# Make __stack_split_initialize a high priority constructor.
598
599#if HAVE_INITFINI_ARRAY_SUPPORT
600	.section .init_array.00000,"aw",@progbits
601#else
602	.section .ctors.65535,"aw",@progbits
603#endif
604
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
614
615	.section	.note.GNU-stack,"",@progbits
616	.section	.note.GNU-split-stack,"",@progbits
617	.section	.note.GNU-no-split-stack,"",@progbits
618