[gcc]
[official-gcc.git] / libgcc / config / rs6000 / morestack.S
bloba0fee4037e4e47a937812576f633ab8bdc573d17
1 #ifdef __powerpc64__
2 # PowerPC64 support for -fsplit-stack.
3 # Copyright (C) 2009-2018 Free Software Foundation, Inc.
4 # Contributed by Alan Modra <amodra@gmail.com>.
6 # This file is part of GCC.
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.
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.
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.
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/>.
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
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
48 #if _CALL_ELF == 2
50 #define BODY_LABEL(name) name
52 #define ENTRY0(name)                                    \
53         .global name;                                   \
54         .hidden name;                                   \
55         .type name,@function;                           \
56 name##:
58 #define ENTRY(name)                                     \
59         ENTRY0(name);                                   \
60 0:      addis %r2,%r12,.TOC.-0b@ha;                     \
61         addi %r2,%r2,.TOC.-0b@l;                        \
62         .localentry name, .-name
64 #else
66 #define BODY_LABEL(name) .L.##name
68 #define ENTRY0(name)                                    \
69         .global name;                                   \
70         .hidden name;                                   \
71         .type name,@function;                           \
72         .pushsection ".opd","aw";                       \
73         .p2align 3;                                     \
74 name##: .quad BODY_LABEL (name), .TOC.@tocbase, 0;      \
75         .popsection;                                    \
76 BODY_LABEL(name)##:
78 #define ENTRY(name) ENTRY0(name)
80 #endif
82 #define SIZE(name) .size name, .-BODY_LABEL(name)
85         .text
86 # Just like __morestack, but with larger excess allocation
87 ENTRY0(__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
104         addis %r12,%r12,-NON_SPLIT_STACK@h
105         SIZE (__morestack_non_split)
106 # Fall through into __morestack
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
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.
135 ENTRY0(__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)
158         # void __morestack_block_signals (void)
159         bl __morestack_block_signals
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
169 # Start using new stack
170         stdu %r29,-32(%r3)              # back-chain
171         mr %r1,%r3
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
185         # void __morestack_unblock_signals (void)
186         bl __morestack_unblock_signals
188 # Set up for a call to the target function, located 3
189 # instructions after __morestack's return address.
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!
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
221         bl __morestack_block_signals
223         # void *__generic_releasestack (size_t *pavailable)
224         addi %r3,%r29,NEWSTACKSIZE_SAVE
225         bl __generic_releasestack
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
234         bl __morestack_unblock_signals
236 # Use old stack again.
237         mr %r1,%r29
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
256 # This is the cleanup code called by the stack unwinder when
257 # unwinding through code between .LEHB0 and .LEHE0 above.
258 cleanup:
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)
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:
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
295 DW.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
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)
306 ENTRY(__stack_split_initialize)
307         addi %r3,%r1,-0x4000            # We should have at least 16K.
308         std %r3,-0x7000-64(%r13)        # tcbhead_t.__private_ss
309         # void __generic_morestack_set_initial_sp (void *sp, size_t len)
310         mr %r3,%r1
311         li %r4, 0x4000
312         b __generic_morestack_set_initial_sp
313         SIZE (__stack_split_initialize)
316 # Return current __private_ss
317 # void *__morestack_get_guard (void)
318 ENTRY0(__morestack_get_guard)
319         ld %r3,-0x7000-64(%r13)         # tcbhead_t.__private_ss
320         blr
321         SIZE (__morestack_get_guard)
324 # Set __private_ss
325 # void __morestack_set_guard (void *ptr)
326 ENTRY0(__morestack_set_guard)
327         std %r3,-0x7000-64(%r13)        # tcbhead_t.__private_ss
328         blr
329         SIZE (__morestack_set_guard)
332 # Return the stack guard value for given stack
333 # void *__morestack_make_guard (void *stack, size_t size)
334 ENTRY0(__morestack_make_guard)
335         sub %r3,%r3,%r4
336         addi %r3,%r3,BACKOFF
337         blr
338         SIZE (__morestack_make_guard)
341 # Make __stack_split_initialize a high priority constructor.
342         .section .ctors.65535,"aw",@progbits
343         .p2align 3
344         .quad __stack_split_initialize
345         .quad __morestack_load_mmap
347         .section .note.GNU-stack,"",@progbits
348         .section .note.GNU-split-stack,"",@progbits
349         .section .note.GNU-no-split-stack,"",@progbits
350 #endif /* __powerpc64__ */