1#ifdef __powerpc64__
2# PowerPC64 support for -fsplit-stack.
3# Copyright (C) 2009-2020 Free Software Foundation, Inc.
4# Contributed by Alan Modra <amodra@gmail.com>.
5
6# This file is part of GCC.
7
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.
12
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.
17
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.
21
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/>.
26
27#if _CALL_ELF == 2
28	.abiversion 2
29#define PARAMS 32
30#else
31#define PARAMS 48
32#endif
33#define MORESTACK_FRAMESIZE	(PARAMS+96)
34#define PARAMREG_SAVE		-MORESTACK_FRAMESIZE+PARAMS+0
35#define STATIC_CHAIN_SAVE	-MORESTACK_FRAMESIZE+PARAMS+64
36#define R29_SAVE		-MORESTACK_FRAMESIZE+PARAMS+72
37#define LINKREG_SAVE		-MORESTACK_FRAMESIZE+PARAMS+80
38#define NEWSTACKSIZE_SAVE	-MORESTACK_FRAMESIZE+PARAMS+88
39
40# Excess space needed to call ld.so resolver for lazy plt
41# resolution.  Go uses sigaltstack so this doesn't need to
42# also cover signal frame size.
43#define BACKOFF 4096
44# Large excess allocated when calling non-split-stack code.
45#define NON_SPLIT_STACK 0x100000
46
47
48#if _CALL_ELF == 2
49
50#define BODY_LABEL(name) name
51
52#define ENTRY0(name)					\
53	.global name;					\
54	.hidden	name;					\
55	.type name,@function;				\
56name##:
57
58#define ENTRY(name)					\
59	ENTRY0(name);					\
600:	addis %r2,%r12,.TOC.-0b@ha;			\
61        addi %r2,%r2,.TOC.-0b@l;			\
62	.localentry name, .-name
63
64#else
65
66#define BODY_LABEL(name) .L.##name
67
68#define ENTRY0(name)					\
69	.global name;					\
70	.hidden	name;					\
71	.type name,@function;				\
72	.pushsection ".opd","aw";			\
73	.p2align 3;					\
74name##: .quad BODY_LABEL (name), .TOC.@tocbase, 0;	\
75	.popsection;					\
76BODY_LABEL(name)##:
77
78#define ENTRY(name) ENTRY0(name)
79
80#endif
81
82#define SIZE(name) .size name, .-BODY_LABEL(name)
83
84
85	.text
86# Just like __morestack, but with larger excess allocation
87ENTRY0(__morestack_non_split)
88.LFB1:
89	.cfi_startproc
90# We use a cleanup to restore the tcbhead_t.__private_ss if
91# an exception is thrown through this code.
92#ifdef __PIC__
93	.cfi_personality 0x9b,DW.ref.__gcc_personality_v0
94	.cfi_lsda 0x1b,.LLSDA1
95#else
96	.cfi_personality 0x3,__gcc_personality_v0
97	.cfi_lsda 0x3,.LLSDA1
98#endif
99# LR is already saved by the split-stack prologue code.
100# We may as well have the unwinder skip over the call in the
101# prologue too.
102	.cfi_offset %lr,16
103
104	addis %r12,%r12,-NON_SPLIT_STACK@h
105	SIZE (__morestack_non_split)
106# Fall through into __morestack
107
108
109# This function is called with non-standard calling conventions.
110# On entry, r12 is the requested stack pointer.  One version of the
111# split-stack prologue that calls __morestack looks like
112#	ld %r0,-0x7000-64(%r13)
113#	addis %r12,%r1,-allocate@ha
114#	addi %r12,%r12,-allocate@l
115#	cmpld %r12,%r0
116#	bge+ enough
117#	mflr %r0
118#	std %r0,16(%r1)
119#	bl __morestack
120#	ld %r0,16(%r1)
121#	mtlr %r0
122#	blr
123# enough:
124# The normal function prologue follows here, with a small addition at
125# the end to set up the arg pointer.  The arg pointer is set up with:
126#	addi %r12,%r1,offset
127#	bge %cr7,.+8
128#	mr %r12,%r29
129#
130# Note that the lr save slot 16(%r1) has already been used.
131# r3 thru r11 possibly contain arguments and a static chain
132# pointer for the function we're calling, so must be preserved.
133# cr7 must also be preserved.
134
135ENTRY0(__morestack)
136# Save parameter passing registers, our arguments, lr, r29
137# and use r29 as a frame pointer.
138	std %r3,PARAMREG_SAVE+0(%r1)
139	sub %r3,%r1,%r12		# calculate requested stack size
140	mflr %r12
141	std %r4,PARAMREG_SAVE+8(%r1)
142	std %r5,PARAMREG_SAVE+16(%r1)
143	std %r6,PARAMREG_SAVE+24(%r1)
144	std %r7,PARAMREG_SAVE+32(%r1)
145	addi %r3,%r3,BACKOFF
146	std %r8,PARAMREG_SAVE+40(%r1)
147	std %r9,PARAMREG_SAVE+48(%r1)
148	std %r10,PARAMREG_SAVE+56(%r1)
149	std %r11,STATIC_CHAIN_SAVE(%r1)
150	std %r29,R29_SAVE(%r1)
151	std %r12,LINKREG_SAVE(%r1)
152	std %r3,NEWSTACKSIZE_SAVE(%r1)	# new stack size
153	mr %r29,%r1
154	.cfi_offset %r29,R29_SAVE
155	.cfi_def_cfa_register %r29
156	stdu %r1,-MORESTACK_FRAMESIZE(%r1)
157
158	# void __morestack_block_signals (void)
159	bl __morestack_block_signals
160
161	# void *__generic_morestack (size_t *pframe_size,
162	#			     void *old_stack,
163	#			     size_t param_size)
164	addi %r3,%r29,NEWSTACKSIZE_SAVE
165	mr %r4,%r29
166	li %r5,0			# no copying from old stack
167	bl __generic_morestack
168
169# Start using new stack
170	stdu %r29,-32(%r3)		# back-chain
171	mr %r1,%r3
172
173# Set __private_ss stack guard for the new stack.
174	ld %r12,NEWSTACKSIZE_SAVE(%r29)	# modified size
175	addi %r3,%r3,BACKOFF-32
176	sub %r3,%r3,%r12
177# Note that a signal frame has $pc pointing at the instruction
178# where the signal occurred.  For something like a timer
179# interrupt this means the instruction has already executed,
180# thus the region starts at the instruction modifying
181# __private_ss, not one instruction after.
182.LEHB0:
183	std %r3,-0x7000-64(%r13)	# tcbhead_t.__private_ss
184
185	# void __morestack_unblock_signals (void)
186	bl __morestack_unblock_signals
187
188# Set up for a call to the target function, located 3
189# instructions after __morestack's return address.
190#
191	ld %r12,LINKREG_SAVE(%r29)
192	ld %r3,PARAMREG_SAVE+0(%r29)	# restore arg regs
193	ld %r4,PARAMREG_SAVE+8(%r29)
194	ld %r5,PARAMREG_SAVE+16(%r29)
195	ld %r6,PARAMREG_SAVE+24(%r29)
196	ld %r7,PARAMREG_SAVE+32(%r29)
197	ld %r8,PARAMREG_SAVE+40(%r29)
198	ld %r9,PARAMREG_SAVE+48(%r29)
199	addi %r0,%r12,12		# add 3 instructions
200	ld %r10,PARAMREG_SAVE+56(%r29)
201	ld %r11,STATIC_CHAIN_SAVE(%r29)
202	cmpld %cr7,%r12,%r0		# indicate we were called
203	mtctr %r0
204	bctrl				# call caller!
205
206# On return, save regs possibly used to return a value, and
207# possibly trashed by calls to __morestack_block_signals,
208# __generic_releasestack and __morestack_unblock_signals.
209# Assume those calls don't use vector or floating point regs.
210	std %r3,PARAMREG_SAVE+0(%r29)
211	std %r4,PARAMREG_SAVE+8(%r29)
212	std %r5,PARAMREG_SAVE+16(%r29)
213	std %r6,PARAMREG_SAVE+24(%r29)
214#if _CALL_ELF == 2
215	std %r7,PARAMREG_SAVE+32(%r29)
216	std %r8,PARAMREG_SAVE+40(%r29)
217	std %r9,PARAMREG_SAVE+48(%r29)
218	std %r10,PARAMREG_SAVE+56(%r29)
219#endif
220
221	bl __morestack_block_signals
222
223	# void *__generic_releasestack (size_t *pavailable)
224	addi %r3,%r29,NEWSTACKSIZE_SAVE
225	bl __generic_releasestack
226
227# Reset __private_ss stack guard to value for old stack
228	ld %r12,NEWSTACKSIZE_SAVE(%r29)
229	addi %r3,%r3,BACKOFF
230	sub %r3,%r3,%r12
231.LEHE0:
232	std %r3,-0x7000-64(%r13)	# tcbhead_t.__private_ss
233
234	bl __morestack_unblock_signals
235
236# Use old stack again.
237	mr %r1,%r29
238
239# Restore return value regs, and return.
240	ld %r0,LINKREG_SAVE(%r29)
241	mtlr %r0
242	ld %r3,PARAMREG_SAVE+0(%r29)
243	ld %r4,PARAMREG_SAVE+8(%r29)
244	ld %r5,PARAMREG_SAVE+16(%r29)
245	ld %r6,PARAMREG_SAVE+24(%r29)
246#if _CALL_ELF == 2
247	ld %r7,PARAMREG_SAVE+32(%r29)
248	ld %r8,PARAMREG_SAVE+40(%r29)
249	ld %r9,PARAMREG_SAVE+48(%r29)
250	ld %r10,PARAMREG_SAVE+56(%r29)
251#endif
252	ld %r29,R29_SAVE(%r29)
253	.cfi_def_cfa_register %r1
254	blr
255
256# This is the cleanup code called by the stack unwinder when
257# unwinding through code between .LEHB0 and .LEHE0 above.
258cleanup:
259	.cfi_def_cfa_register %r29
260	std %r3,PARAMREG_SAVE(%r29)	# Save exception header
261	# size_t __generic_findstack (void *stack)
262	mr %r3,%r29
263	bl __generic_findstack
264	sub %r3,%r29,%r3
265	addi %r3,%r3,BACKOFF
266	std %r3,-0x7000-64(%r13)	# tcbhead_t.__private_ss
267	ld %r3,PARAMREG_SAVE(%r29)
268	bl _Unwind_Resume
269	nop
270	.cfi_endproc
271	SIZE (__morestack)
272
273
274	.section .gcc_except_table,"a",@progbits
275	.p2align 2
276.LLSDA1:
277	.byte	0xff	# @LPStart format (omit)
278	.byte	0xff	# @TType format (omit)
279	.byte	0x1	# call-site format (uleb128)
280	.uleb128 .LLSDACSE1-.LLSDACSB1	# Call-site table length
281.LLSDACSB1:
282	.uleb128 .LEHB0-.LFB1	# region 0 start
283	.uleb128 .LEHE0-.LEHB0	# length
284	.uleb128 cleanup-.LFB1	# landing pad
285	.uleb128 0		# no action, ie. a cleanup
286.LLSDACSE1:
287
288
289#ifdef __PIC__
290# Build a position independent reference to the personality function.
291	.hidden DW.ref.__gcc_personality_v0
292	.weak DW.ref.__gcc_personality_v0
293	.section .data.DW.ref.__gcc_personality_v0,"awG",@progbits,DW.ref.__gcc_personality_v0,comdat
294	.p2align 3
295DW.ref.__gcc_personality_v0:
296	.quad __gcc_personality_v0
297	.type DW.ref.__gcc_personality_v0, @object
298	.size DW.ref.__gcc_personality_v0, 8
299#endif
300
301
302	.text
303# Initialize the stack guard when the program starts or when a
304# new thread starts.  This is called from a constructor.
305# void __stack_split_initialize (void)
306ENTRY(__stack_split_initialize)
307	.cfi_startproc
308	addi %r3,%r1,-0x4000		# We should have at least 16K.
309	std %r3,-0x7000-64(%r13)	# tcbhead_t.__private_ss
310	# void __generic_morestack_set_initial_sp (void *sp, size_t len)
311	mr %r3,%r1
312	li %r4, 0x4000
313	b __generic_morestack_set_initial_sp
314# The lack of .cfi_endproc here is deliberate.  This function and the
315# following ones can all use the default FDE.
316	SIZE (__stack_split_initialize)
317
318
319# Return current __private_ss
320# void *__morestack_get_guard (void)
321ENTRY0(__morestack_get_guard)
322	ld %r3,-0x7000-64(%r13)		# tcbhead_t.__private_ss
323	blr
324	SIZE (__morestack_get_guard)
325
326
327# Set __private_ss
328# void __morestack_set_guard (void *ptr)
329ENTRY0(__morestack_set_guard)
330	std %r3,-0x7000-64(%r13)	# tcbhead_t.__private_ss
331	blr
332	SIZE (__morestack_set_guard)
333
334
335# Return the stack guard value for given stack
336# void *__morestack_make_guard (void *stack, size_t size)
337ENTRY0(__morestack_make_guard)
338	sub %r3,%r3,%r4
339	addi %r3,%r3,BACKOFF
340	blr
341	.cfi_endproc
342	SIZE (__morestack_make_guard)
343
344
345# Make __stack_split_initialize a high priority constructor.
346	.section .ctors.65535,"aw",@progbits
347	.p2align 3
348	.quad __stack_split_initialize
349	.quad __morestack_load_mmap
350
351	.section .note.GNU-stack,"",@progbits
352	.section .note.GNU-split-stack,"",@progbits
353	.section .note.GNU-no-split-stack,"",@progbits
354#endif /* __powerpc64__ */
355