Home | History | Annotate | Line # | Download | only in rs6000
morestack.S revision 1.1
      1 #ifdef __powerpc64__
      2 # PowerPC64 support for -fsplit-stack.
      3 # Copyright (C) 2009-2016 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;				\
     56 name##:
     57 
     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
     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;					\
     74 name##: .quad BODY_LABEL (name), .TOC.@tocbase, 0;	\
     75 	.popsection;					\
     76 BODY_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
     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
    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 
    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)
    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.
    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)
    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
    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
    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)
    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)
    314 
    315 
    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)
    322 
    323 
    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)
    330 
    331 
    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)
    339 
    340 
    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
    346 
    347 	.section .note.GNU-stack,"",@progbits
    348 	.section .note.GNU-split-stack,"",@progbits
    349 	.section .note.GNU-no-split-stack,"",@progbits
    350 #endif /* __powerpc64__ */
    351