1# x86/x86_64 support for -fsplit-stack.
2# Copyright (C) 2009-2019 Free Software Foundation, Inc.
3# Contributed by Ian Lance Taylor <iant@google.com>.
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
27# Support for allocating more stack space when using -fsplit-stack.
28# When a function discovers that it needs more stack space, it will
29# call __morestack with the size of the stack frame and the size of
30# the parameters to copy from the old stack frame to the new one.
31# The __morestack function preserves the parameter registers and
32# calls __generic_morestack to actually allocate the stack space.
33
34# When this is called stack space is very low, but we ensure that
35# there is enough space to push the parameter registers and to call
36# __generic_morestack.
37
38# When calling __generic_morestack, FRAME_SIZE points to the size of
39# the desired frame when the function is called, and the function
40# sets it to the size of the allocated stack.  OLD_STACK points to
41# the parameters on the old stack and PARAM_SIZE is the number of
42# bytes of parameters to copy to the new stack.  These are the
43# parameters of the function that called __morestack.  The
44# __generic_morestack function returns the new stack pointer,
45# pointing to the address of the first copied parameter.  The return
46# value minus the returned *FRAME_SIZE will be the first address on
47# the stack which we should not use.
48
49# void *__generic_morestack (size_t *frame_size, void *old_stack,
50#			     size_t param_size);
51
52# The __morestack routine has to arrange for the caller to return to a
53# stub on the new stack.  The stub is responsible for restoring the
54# old stack pointer and returning to the caller's caller.  This calls
55# __generic_releasestack to retrieve the old stack pointer and release
56# the newly allocated stack.
57
58# void *__generic_releasestack (size_t *available);
59
60# We do a little dance so that the processor's call/return return
61# address prediction works out.  The compiler arranges for the caller
62# to look like this:
63#   call __generic_morestack
64#   ret
65#  L:
66#   // carry on with function
67# After we allocate more stack, we call L, which is in our caller.
68# When that returns (to the predicted instruction), we release the
69# stack segment and reset the stack pointer.  We then return to the
70# predicted instruction, namely the ret instruction immediately after
71# the call to __generic_morestack.  That then returns to the caller of
72# the original caller.
73
74
75# The amount of extra space we ask for.  In general this has to be
76# enough for the dynamic loader to find a symbol and for a signal
77# handler to run.
78
79#ifndef __x86_64__
80#define BACKOFF (1024)
81#else
82#define BACKOFF (1536)
83#endif
84
85
86# The amount of space we ask for when calling non-split-stack code.
87#define NON_SPLIT_STACK 0x100000
88
89# This entry point is for split-stack code which calls non-split-stack
90# code.  When the linker sees this case, it converts the call to
91# __morestack to call __morestack_non_split instead.  We just bump the
92# requested stack space by 16K.
93
94#include <cet.h>
95
96	.global __morestack_non_split
97	.hidden	__morestack_non_split
98
99#ifdef __ELF__
100       .type	__morestack_non_split,@function
101#endif
102
103__morestack_non_split:
104	.cfi_startproc
105
106#ifndef __x86_64__
107
108	# See below for an extended explanation of this.
109	.cfi_def_cfa %esp,16
110
111	pushl	%eax			# Save %eax in case it is a parameter.
112
113	.cfi_adjust_cfa_offset 4	# Account for pushed register.
114
115	movl	%esp,%eax		# Current stack,
116	subl	8(%esp),%eax		# less required stack frame size,
117	subl	$NON_SPLIT_STACK,%eax	# less space for non-split code.
118	cmpl	%gs:0x30,%eax		# See if we have enough space.
119	jb	2f			# Get more space if we need it.
120
121	# Here the stack is
122	#	%esp + 20:	stack pointer after two returns
123	#	%esp + 16:	return address of morestack caller's caller
124	#	%esp + 12:	size of parameters
125	#	%esp + 8:	new stack frame size
126	#	%esp + 4:	return address of this function
127	#	%esp:		saved %eax
128	#
129	# Since we aren't doing a full split stack, we don't need to
130	# do anything when our caller returns.  So we return to our
131	# caller rather than calling it, and let it return as usual.
132	# To make that work we adjust the return address.
133
134	# This breaks call/return address prediction for the call to
135	# this function.  I can't figure out a way to make it work
136	# short of copying the parameters down the stack, which will
137	# probably take more clock cycles than we will lose breaking
138	# call/return address prediction.  We will only break
139	# prediction for this call, not for our caller.
140
141	movl	4(%esp),%eax		# Increment the return address
142	cmpb	$0xc3,(%eax)		# to skip the ret instruction;
143	je	1f			# see above.
144	addl	$2,%eax
1451:	inc	%eax
146
147	# If the instruction that we return to is
148	#   leal  20(%ebp),{%eax,%ecx,%edx}
149	# then we have been called by a varargs function that expects
150	# %ebp to hold a real value.  That can only work if we do the
151	# full stack split routine.  FIXME: This is fragile.
152	cmpb	$0x8d,(%eax)
153	jne	3f
154	cmpb	$0x14,2(%eax)
155	jne	3f
156	cmpb	$0x45,1(%eax)
157	je	2f
158	cmpb	$0x4d,1(%eax)
159	je	2f
160	cmpb	$0x55,1(%eax)
161	je	2f
162
1633:
164	movl	%eax,4(%esp)		# Update return address.
165
166	popl	%eax			# Restore %eax and stack.
167
168	.cfi_adjust_cfa_offset -4	# Account for popped register.
169
170	ret	$8			# Return to caller, popping args.
171
1722:
173	.cfi_adjust_cfa_offset 4	# Back to where we were.
174
175	popl	%eax			# Restore %eax and stack.
176
177	.cfi_adjust_cfa_offset -4	# Account for popped register.
178
179	# Increment space we request.
180	addl	$NON_SPLIT_STACK+0x1000+BACKOFF,4(%esp)
181
182	# Fall through into morestack.
183
184#else
185
186	# See below for an extended explanation of this.
187	.cfi_def_cfa %rsp,16
188
189	pushq	%rax			# Save %rax in case caller is using
190					# it to preserve original %r10.
191	.cfi_adjust_cfa_offset 8	# Adjust for pushed register.
192
193	movq	%rsp,%rax		# Current stack,
194	subq	%r10,%rax		# less required stack frame size,
195	subq	$NON_SPLIT_STACK,%rax	# less space for non-split code.
196
197#ifdef __LP64__
198	cmpq	%fs:0x70,%rax		# See if we have enough space.
199#else
200	cmpl	%fs:0x40,%eax
201#endif
202
203	jb	2f			# Get more space if we need it.
204
205	# If the instruction that we return to is
206	#   leaq  24(%rbp), %r11n
207	# then we have been called by a varargs function that expects
208	# %ebp to hold a real value.  That can only work if we do the
209	# full stack split routine.  FIXME: This is fragile.
210	movq	8(%rsp),%rax
211	incq	%rax			# Skip ret instruction in caller.
212	cmpl	$0x185d8d4c,(%rax)
213	je	2f
214
215	# This breaks call/return prediction, as described above.
216	incq	8(%rsp)			# Increment the return address.
217
218	popq	%rax			# Restore register.
219
220	.cfi_adjust_cfa_offset -8	# Adjust for popped register.
221
222	ret				# Return to caller.
223
2242:
225	popq	%rax			# Restore register.
226
227	.cfi_adjust_cfa_offset -8	# Adjust for popped register.
228
229	# Increment space we request.
230	addq	$NON_SPLIT_STACK+0x1000+BACKOFF,%r10
231
232	# Fall through into morestack.
233
234#endif
235
236	.cfi_endproc
237#ifdef __ELF__
238	.size	__morestack_non_split, . - __morestack_non_split
239#endif
240
241# __morestack_non_split falls through into __morestack.
242
243
244# The __morestack function.
245
246	.global	__morestack
247	.hidden	__morestack
248
249#ifdef __ELF__
250	.type	__morestack,@function
251#endif
252
253__morestack:
254.LFB1:
255	.cfi_startproc
256
257
258#ifndef __x86_64__
259
260
261# The 32-bit __morestack function.
262
263	# We use a cleanup to restore the stack guard if an exception
264	# is thrown through this code.
265#ifndef __PIC__
266	.cfi_personality 0,__gcc_personality_v0
267	.cfi_lsda 0,.LLSDA1
268#else
269	.cfi_personality 0x9b,DW.ref.__gcc_personality_v0
270	.cfi_lsda 0x1b,.LLSDA1
271#endif
272
273	# We return below with a ret $8.  We will return to a single
274	# return instruction, which will return to the caller of our
275	# caller.  We let the unwinder skip that single return
276	# instruction, and just return to the real caller.
277
278	# Here CFA points just past the return address on the stack,
279	# e.g., on function entry it is %esp + 4.  The stack looks
280	# like this:
281	#	CFA + 12:	stack pointer after two returns
282	#	CFA + 8:	return address of morestack caller's caller
283	#	CFA + 4:	size of parameters
284	#	CFA:		new stack frame size
285	#	CFA - 4:	return address of this function
286	#	CFA - 8:	previous value of %ebp; %ebp points here
287	# Setting the new CFA to be the current CFA + 12 (i.e., %esp +
288	# 16) will make the unwinder pick up the right return address.
289
290	.cfi_def_cfa %esp,16
291
292	pushl	%ebp
293	.cfi_adjust_cfa_offset 4
294	.cfi_offset %ebp, -20
295	movl	%esp,%ebp
296	.cfi_def_cfa_register %ebp
297
298	# In 32-bit mode the parameters are pushed on the stack.  The
299	# argument size is pushed then the new stack frame size is
300	# pushed.
301
302	# In the body of a non-leaf function, the stack pointer will
303	# be aligned to a 16-byte boundary.  That is CFA + 12 in the
304	# stack picture above: (CFA + 12) % 16 == 0.  At this point we
305	# have %esp == CFA - 8, so %esp % 16 == 12.  We need some
306	# space for saving registers and passing parameters, and we
307	# need to wind up with %esp % 16 == 0.
308	subl	$44,%esp
309
310	# Because our cleanup code may need to clobber %ebx, we need
311	# to save it here so the unwinder can restore the value used
312	# by the caller.  Note that we don't have to restore the
313	# register, since we don't change it, we just have to save it
314	# for the unwinder.
315	movl	%ebx,-4(%ebp)
316	.cfi_offset %ebx, -24
317
318	# In 32-bit mode the registers %eax, %edx, and %ecx may be
319	# used for parameters, depending on the regparm and fastcall
320	# attributes.
321
322	movl	%eax,-8(%ebp)
323	movl	%edx,-12(%ebp)
324	movl	%ecx,-16(%ebp)
325
326	call	__morestack_block_signals
327
328	movl	12(%ebp),%eax		# The size of the parameters.
329	movl	%eax,8(%esp)
330	leal	20(%ebp),%eax		# Address of caller's parameters.
331	movl	%eax,4(%esp)
332	addl	$BACKOFF,8(%ebp)	# Ask for backoff bytes.
333	leal	8(%ebp),%eax		# The address of the new frame size.
334	movl	%eax,(%esp)
335
336	call	__generic_morestack
337
338	movl	%eax,%esp		# Switch to the new stack.
339	subl	8(%ebp),%eax		# The end of the stack space.
340	addl	$BACKOFF,%eax		# Back off 512 bytes.
341
342.LEHB0:
343	# FIXME: The offset must match
344	# TARGET_THREAD_SPLIT_STACK_OFFSET in
345	# gcc/config/i386/linux.h.
346	movl	%eax,%gs:0x30		# Save the new stack boundary.
347
348	call	__morestack_unblock_signals
349
350	movl	-12(%ebp),%edx		# Restore registers.
351	movl	-16(%ebp),%ecx
352
353	movl	4(%ebp),%eax		# Increment the return address
354	cmpb	$0xc3,(%eax)		# to skip the ret instruction;
355	je	1f			# see above.
356	addl	$2,%eax
3571:	inc	%eax
358
359	movl	%eax,-12(%ebp)		# Store return address in an
360					# unused slot.
361
362	movl	-8(%ebp),%eax		# Restore the last register.
363
364	call	*-12(%ebp)		# Call our caller!
365
366	# The caller will return here, as predicted.
367
368	# Save the registers which may hold a return value.  We
369	# assume that __generic_releasestack does not touch any
370	# floating point or vector registers.
371	pushl	%eax
372	pushl	%edx
373
374	# Push the arguments to __generic_releasestack now so that the
375	# stack is at a 16-byte boundary for
376	# __morestack_block_signals.
377	pushl	$0			# Where the available space is returned.
378	leal	0(%esp),%eax		# Push its address.
379	push	%eax
380
381	call	__morestack_block_signals
382
383	call	__generic_releasestack
384
385	subl	4(%esp),%eax		# Subtract available space.
386	addl	$BACKOFF,%eax		# Back off 512 bytes.
387.LEHE0:
388	movl	%eax,%gs:0x30		# Save the new stack boundary.
389
390	addl	$8,%esp			# Remove values from stack.
391
392	# We need to restore the old stack pointer, which is in %rbp,
393	# before we unblock signals.  We also need to restore %eax and
394	# %edx after we unblock signals but before we return.  Do this
395	# by moving %eax and %edx from the current stack to the old
396	# stack.
397
398	popl	%edx			# Pop return value from current stack.
399	popl	%eax
400
401	movl	%ebp,%esp		# Restore stack pointer.
402
403	# As before, we now have %esp % 16 == 12.
404
405	pushl	%eax			# Push return value on old stack.
406	pushl	%edx
407	subl	$4,%esp			# Align stack to 16-byte boundary.
408
409	call	__morestack_unblock_signals
410
411	addl	$4,%esp
412	popl	%edx			# Restore return value.
413	popl	%eax
414
415	.cfi_remember_state
416
417	# We never changed %ebx, so we don't have to actually restore it.
418	.cfi_restore %ebx
419
420	popl	%ebp
421	.cfi_restore %ebp
422	.cfi_def_cfa %esp, 16
423	ret	$8			# Return to caller, which will
424					# immediately return.  Pop
425					# arguments as we go.
426
427# This is the cleanup code called by the stack unwinder when unwinding
428# through the code between .LEHB0 and .LEHE0 above.
429
430.L1:
431	.cfi_restore_state
432	subl	$16,%esp		# Maintain 16 byte alignment.
433	movl	%eax,4(%esp)		# Save exception header.
434	movl	%ebp,(%esp)		# Stack pointer after resume.
435	call	__generic_findstack
436	movl	%ebp,%ecx		# Get the stack pointer.
437	subl	%eax,%ecx		# Subtract available space.
438	addl	$BACKOFF,%ecx		# Back off 512 bytes.
439	movl	%ecx,%gs:0x30		# Save new stack boundary.
440	movl	4(%esp),%eax		# Function argument.
441	movl	%eax,(%esp)
442#ifdef __PIC__
443	call	__x86.get_pc_thunk.bx	# %ebx may not be set up for us.
444	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
445	call	_Unwind_Resume@PLT	# Resume unwinding.
446#else
447	call	_Unwind_Resume
448#endif
449
450#else /* defined(__x86_64__) */
451
452
453# The 64-bit __morestack function.
454
455	# We use a cleanup to restore the stack guard if an exception
456	# is thrown through this code.
457#ifndef __PIC__
458	.cfi_personality 0x3,__gcc_personality_v0
459	.cfi_lsda 0x3,.LLSDA1
460#else
461	.cfi_personality 0x9b,DW.ref.__gcc_personality_v0
462	.cfi_lsda 0x1b,.LLSDA1
463#endif
464
465	# We will return a single return instruction, which will
466	# return to the caller of our caller.  Let the unwinder skip
467	# that single return instruction, and just return to the real
468	# caller.
469	.cfi_def_cfa %rsp,16
470
471	# Set up a normal backtrace.
472	pushq	%rbp
473	.cfi_adjust_cfa_offset 8
474	.cfi_offset %rbp, -24
475	movq	%rsp, %rbp
476	.cfi_def_cfa_register %rbp
477
478	# In 64-bit mode the new stack frame size is passed in r10
479        # and the argument size is passed in r11.
480
481	addq	$BACKOFF,%r10		# Ask for backoff bytes.
482	pushq	%r10			# Save new frame size.
483
484	# In 64-bit mode the registers %rdi, %rsi, %rdx, %rcx, %r8,
485	# and %r9 may be used for parameters.  We also preserve %rax
486	# which the caller may use to hold %r10.
487
488	pushq	%rax
489	pushq	%rdi
490	pushq	%rsi
491	pushq	%rdx
492	pushq	%rcx
493	pushq	%r8
494	pushq	%r9
495
496	pushq	%r11
497
498	# We entered morestack with the stack pointer aligned to a
499	# 16-byte boundary (the call to morestack's caller used 8
500	# bytes, and the call to morestack used 8 bytes).  We have now
501	# pushed 10 registers, so we are still aligned to a 16-byte
502	# boundary.
503
504	call	__morestack_block_signals
505
506	leaq	-8(%rbp),%rdi		# Address of new frame size.
507	leaq	24(%rbp),%rsi		# The caller's parameters.
508	popq	%rdx			# The size of the parameters.
509
510	subq	$8,%rsp			# Align stack.
511
512	call	__generic_morestack
513
514	movq	-8(%rbp),%r10		# Reload modified frame size
515	movq	%rax,%rsp		# Switch to the new stack.
516	subq	%r10,%rax		# The end of the stack space.
517	addq	$BACKOFF,%rax		# Back off 1024 bytes.
518
519.LEHB0:
520	# FIXME: The offset must match
521	# TARGET_THREAD_SPLIT_STACK_OFFSET in
522	# gcc/config/i386/linux64.h.
523	# Macro to save the new stack boundary.
524#ifdef __LP64__
525#define X86_64_SAVE_NEW_STACK_BOUNDARY(reg)	movq	%r##reg,%fs:0x70
526#else
527#define X86_64_SAVE_NEW_STACK_BOUNDARY(reg)	movl	%e##reg,%fs:0x40
528#endif
529	X86_64_SAVE_NEW_STACK_BOUNDARY (ax)
530
531	call	__morestack_unblock_signals
532
533	movq	-24(%rbp),%rdi		# Restore registers.
534	movq	-32(%rbp),%rsi
535	movq	-40(%rbp),%rdx
536	movq	-48(%rbp),%rcx
537	movq	-56(%rbp),%r8
538	movq	-64(%rbp),%r9
539
540	movq	8(%rbp),%r10		# Increment the return address
541	incq	%r10			# to skip the ret instruction;
542					# see above.
543
544	movq	-16(%rbp),%rax		# Restore caller's %rax.
545
546	call	*%r10			# Call our caller!
547
548	# The caller will return here, as predicted.
549
550	# Save the registers which may hold a return value.  We
551	# assume that __generic_releasestack does not touch any
552	# floating point or vector registers.
553	pushq	%rax
554	pushq	%rdx
555
556	call	__morestack_block_signals
557
558	pushq	$0			# For alignment.
559	pushq	$0			# Where the available space is returned.
560	leaq	0(%rsp),%rdi		# Pass its address.
561
562	call	__generic_releasestack
563
564	subq	0(%rsp),%rax		# Subtract available space.
565	addq	$BACKOFF,%rax		# Back off 1024 bytes.
566.LEHE0:
567	X86_64_SAVE_NEW_STACK_BOUNDARY (ax)
568
569	addq	$16,%rsp		# Remove values from stack.
570
571	# We need to restore the old stack pointer, which is in %rbp,
572	# before we unblock signals.  We also need to restore %rax and
573	# %rdx after we unblock signals but before we return.  Do this
574	# by moving %rax and %rdx from the current stack to the old
575	# stack.
576
577	popq	%rdx			# Pop return value from current stack.
578	popq	%rax
579
580	movq	%rbp,%rsp		# Restore stack pointer.
581
582	# Now (%rsp & 16) == 8.
583
584	subq	$8,%rsp			# For alignment.
585	pushq	%rax			# Push return value on old stack.
586	pushq	%rdx
587
588	call	__morestack_unblock_signals
589
590	popq	%rdx			# Restore return value.
591	popq	%rax
592	addq	$8,%rsp
593
594	.cfi_remember_state
595	popq	%rbp
596	.cfi_restore %rbp
597	.cfi_def_cfa %rsp, 16
598	ret				# Return to caller, which will
599					# immediately return.
600
601# This is the cleanup code called by the stack unwinder when unwinding
602# through the code between .LEHB0 and .LEHE0 above.
603
604.L1:
605	.cfi_restore_state
606	subq	$16,%rsp		# Maintain 16 byte alignment.
607	movq	%rax,(%rsp)		# Save exception header.
608	movq	%rbp,%rdi		# Stack pointer after resume.
609	call	__generic_findstack
610	movq	%rbp,%rcx		# Get the stack pointer.
611	subq	%rax,%rcx		# Subtract available space.
612	addq	$BACKOFF,%rcx		# Back off 1024 bytes.
613	X86_64_SAVE_NEW_STACK_BOUNDARY (cx)
614	movq	(%rsp),%rdi		# Restore exception data for call.
615#ifdef __PIC__
616	call	_Unwind_Resume@PLT	# Resume unwinding.
617#else
618	call	_Unwind_Resume		# Resume unwinding.
619#endif
620
621#endif /* defined(__x86_64__) */
622
623	.cfi_endproc
624#ifdef __ELF__
625	.size	__morestack, . - __morestack
626#endif
627
628#if !defined(__x86_64__) && defined(__PIC__)
629# Output the thunk to get PC into bx, since we use it above.
630	.section	.text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
631	.globl	__x86.get_pc_thunk.bx
632	.hidden	__x86.get_pc_thunk.bx
633#ifdef __ELF__
634	.type	__x86.get_pc_thunk.bx, @function
635#endif
636__x86.get_pc_thunk.bx:
637	.cfi_startproc
638	movl	(%esp), %ebx
639	ret
640	.cfi_endproc
641#ifdef __ELF__
642	.size	__x86.get_pc_thunk.bx, . - __x86.get_pc_thunk.bx
643#endif
644#endif
645
646# The exception table.  This tells the personality routine to execute
647# the exception handler.
648
649	.section	.gcc_except_table,"a",@progbits
650	.align	4
651.LLSDA1:
652	.byte	0xff	# @LPStart format (omit)
653	.byte	0xff	# @TType format (omit)
654	.byte	0x1	# call-site format (uleb128)
655	.uleb128 .LLSDACSE1-.LLSDACSB1	# Call-site table length
656.LLSDACSB1:
657	.uleb128 .LEHB0-.LFB1	# region 0 start
658	.uleb128 .LEHE0-.LEHB0	# length
659	.uleb128 .L1-.LFB1	# landing pad
660	.uleb128 0		# action
661.LLSDACSE1:
662
663
664	.global __gcc_personality_v0
665#ifdef __PIC__
666	# Build a position independent reference to the basic
667        # personality function.
668	.hidden DW.ref.__gcc_personality_v0
669	.weak   DW.ref.__gcc_personality_v0
670	.section .data.DW.ref.__gcc_personality_v0,"awG",@progbits,DW.ref.__gcc_personality_v0,comdat
671	.type	DW.ref.__gcc_personality_v0, @object
672DW.ref.__gcc_personality_v0:
673#ifndef __LP64__
674	.align 4
675	.size	DW.ref.__gcc_personality_v0, 4
676	.long	__gcc_personality_v0
677#else
678	.align 8
679	.size	DW.ref.__gcc_personality_v0, 8
680	.quad	__gcc_personality_v0
681#endif
682#endif
683
684#if defined __x86_64__ && defined __LP64__
685
686# This entry point is used for the large model.  With this entry point
687# the upper 32 bits of %r10 hold the argument size and the lower 32
688# bits hold the new stack frame size.  There doesn't seem to be a way
689# to know in the assembler code that we are assembling for the large
690# model, and there doesn't seem to be a large model multilib anyhow.
691# If one is developed, then the non-PIC code is probably OK since we
692# will probably be close to the morestack code, but the PIC code
693# almost certainly needs to be changed.  FIXME.
694
695	.text
696	.global	__morestack_large_model
697	.hidden	__morestack_large_model
698
699#ifdef __ELF__
700	.type	__morestack_large_model,@function
701#endif
702
703__morestack_large_model:
704
705	.cfi_startproc
706	_CET_ENDBR
707
708	movq	%r10, %r11
709	andl	$0xffffffff, %r10d
710	sarq	$32, %r11
711	jmp	__morestack
712
713	.cfi_endproc
714#ifdef __ELF__
715       .size	__morestack_large_model, . - __morestack_large_model
716#endif
717
718#endif /* __x86_64__ && __LP64__ */
719
720# Initialize the stack test value when the program starts or when a
721# new thread starts.  We don't know how large the main stack is, so we
722# guess conservatively.  We might be able to use getrlimit here.
723
724	.text
725	.global	__stack_split_initialize
726	.hidden	__stack_split_initialize
727
728#ifdef __ELF__
729	.type	__stack_split_initialize, @function
730#endif
731
732__stack_split_initialize:
733	_CET_ENDBR
734
735#ifndef __x86_64__
736
737	leal	-16000(%esp),%eax	# We should have at least 16K.
738	movl	%eax,%gs:0x30
739	subl	$4,%esp			# Align stack.
740	pushl	$16000
741	pushl	%esp
742#ifdef __PIC__
743	call	__generic_morestack_set_initial_sp@PLT
744#else
745	call	__generic_morestack_set_initial_sp
746#endif
747	addl	$12,%esp
748	ret
749
750#else /* defined(__x86_64__) */
751
752	leaq	-16000(%rsp),%rax	# We should have at least 16K.
753	X86_64_SAVE_NEW_STACK_BOUNDARY (ax)
754	subq	$8,%rsp			# Align stack.
755	movq	%rsp,%rdi
756	movq	$16000,%rsi
757#ifdef __PIC__
758	call	__generic_morestack_set_initial_sp@PLT
759#else
760	call	__generic_morestack_set_initial_sp
761#endif
762	addq	$8,%rsp
763	ret
764
765#endif /* defined(__x86_64__) */
766
767#ifdef __ELF__
768	.size	__stack_split_initialize, . - __stack_split_initialize
769#endif
770
771# Routines to get and set the guard, for __splitstack_getcontext,
772# __splitstack_setcontext, and __splitstack_makecontext.
773
774# void *__morestack_get_guard (void) returns the current stack guard.
775	.text
776	.global	__morestack_get_guard
777	.hidden	__morestack_get_guard
778
779#ifdef __ELF__
780	.type	__morestack_get_guard,@function
781#endif
782
783__morestack_get_guard:
784
785#ifndef __x86_64__
786	movl	%gs:0x30,%eax
787#else
788#ifdef __LP64__
789	movq	%fs:0x70,%rax
790#else
791	movl	%fs:0x40,%eax
792#endif
793#endif
794	ret
795
796#ifdef __ELF__
797	.size	__morestack_get_guard, . - __morestack_get_guard
798#endif
799
800# void __morestack_set_guard (void *) sets the stack guard.
801	.global	__morestack_set_guard
802	.hidden	__morestack_set_guard
803
804#ifdef __ELF__
805	.type	__morestack_set_guard,@function
806#endif
807
808__morestack_set_guard:
809
810#ifndef __x86_64__
811	movl	4(%esp),%eax
812	movl	%eax,%gs:0x30
813#else
814	X86_64_SAVE_NEW_STACK_BOUNDARY (di)
815#endif
816	ret
817
818#ifdef __ELF__
819	.size	__morestack_set_guard, . - __morestack_set_guard
820#endif
821
822# void *__morestack_make_guard (void *, size_t) returns the stack
823# guard value for a stack.
824	.global	__morestack_make_guard
825	.hidden	__morestack_make_guard
826
827#ifdef __ELF__
828	.type	__morestack_make_guard,@function
829#endif
830
831__morestack_make_guard:
832
833#ifndef __x86_64__
834	movl	4(%esp),%eax
835	subl	8(%esp),%eax
836	addl	$BACKOFF,%eax
837#else
838	subq	%rsi,%rdi
839	addq	$BACKOFF,%rdi
840	movq	%rdi,%rax
841#endif
842	ret
843
844#ifdef __ELF__
845	.size	__morestack_make_guard, . - __morestack_make_guard
846#endif
847
848# Make __stack_split_initialize a high priority constructor.  FIXME:
849# This is ELF specific.
850
851	.section	.ctors.65535,"aw",@progbits
852
853#ifndef __LP64__
854	.align	4
855	.long	__stack_split_initialize
856	.long	__morestack_load_mmap
857#else
858	.align	8
859	.quad	__stack_split_initialize
860	.quad	__morestack_load_mmap
861#endif
862
863#ifdef __ELF__
864	.section	.note.GNU-stack,"",@progbits
865	.section	.note.GNU-split-stack,"",@progbits
866	.section	.note.GNU-no-split-stack,"",@progbits
867#endif
868