aboutsummaryrefslogtreecommitdiff
path: root/libgcc/config
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2015-05-20 10:56:28 +0930
committerAlan Modra <amodra@gcc.gnu.org>2015-05-20 10:56:28 +0930
commit0f0fd745255adf8b2904b0acaf1c3b66ec93ddb2 (patch)
tree25d754bde890f2750c3489f49713ea0123e09339 /libgcc/config
parent8a03f86937467dcfe401b4f369307faf2593e97a (diff)
downloadgcc-0f0fd745255adf8b2904b0acaf1c3b66ec93ddb2.zip
gcc-0f0fd745255adf8b2904b0acaf1c3b66ec93ddb2.tar.gz
gcc-0f0fd745255adf8b2904b0acaf1c3b66ec93ddb2.tar.bz2
rs6000-common.c (TARGET_SUPPORTS_SPLIT_STACK): Define.
gcc/ * common/config/rs6000/rs6000-common.c (TARGET_SUPPORTS_SPLIT_STACK): Define. (rs6000_supports_split_stack): New function. * gcc/config/rs6000/rs6000.c (machine_function): Add split_stack_arg_pointer. (TARGET_EXTRA_LIVE_ON_ENTRY, TARGET_INTERNAL_ARG_POINTER): Define. (setup_incoming_varargs): Use crtl->args.internal_arg_pointer rather than virtual_incoming_args_rtx. (rs6000_va_start): Likewise. (split_stack_arg_pointer_used_p): New function. (rs6000_emit_prologue): Set up arg pointer for -fsplit-stack. (morestack_ref): New var. (gen_add3_const, rs6000_expand_split_stack_prologue, rs6000_internal_arg_pointer, rs6000_live_on_entry, rs6000_split_stack_space_check): New functions. (rs6000_elf_file_end): Call file_end_indicate_split_stack. * gcc/config/rs6000/rs6000.md (UNSPEC_STACK_CHECK): Define. (UNSPECV_SPLIT_STACK_RETURN): Define. (split_stack_prologue, load_split_stack_limit, load_split_stack_limit_di, load_split_stack_limit_si, split_stack_return, split_stack_space_check): New expands and insns. * gcc/config/rs6000/rs6000-protos.h (rs6000_expand_split_stack_prologue): Declare. (rs6000_split_stack_space_check): Declare. libgcc/ * config/rs6000/morestack.S: New. * config/rs6000/t-stack-rs6000: New. * config.host (powerpc*-*-linux*): Add t-stack and t-stack-rs6000 to tmake_file. * generic-morestack.c: Don't build for powerpc 32-bit. From-SVN: r223426
Diffstat (limited to 'libgcc/config')
-rw-r--r--libgcc/config/rs6000/morestack.S351
-rw-r--r--libgcc/config/rs6000/t-stack-rs60002
2 files changed, 353 insertions, 0 deletions
diff --git a/libgcc/config/rs6000/morestack.S b/libgcc/config/rs6000/morestack.S
new file mode 100644
index 0000000..ecd1bf4
--- /dev/null
+++ b/libgcc/config/rs6000/morestack.S
@@ -0,0 +1,351 @@
+#ifdef __powerpc64__
+# PowerPC64 support for -fsplit-stack.
+# Copyright (C) 2009-2015 Free Software Foundation, Inc.
+# Contributed by Alan Modra <amodra@gmail.com>.
+
+# This file is part of GCC.
+
+# GCC is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 3, or (at your option) any later
+# version.
+
+# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+
+#if _CALL_ELF == 2
+ .abiversion 2
+#define PARAMS 32
+#else
+ .abiversion 1
+#define PARAMS 48
+#endif
+#define MORESTACK_FRAMESIZE (PARAMS+96)
+#define PARAMREG_SAVE -MORESTACK_FRAMESIZE+PARAMS+0
+#define STATIC_CHAIN_SAVE -MORESTACK_FRAMESIZE+PARAMS+64
+#define R29_SAVE -MORESTACK_FRAMESIZE+PARAMS+72
+#define LINKREG_SAVE -MORESTACK_FRAMESIZE+PARAMS+80
+#define NEWSTACKSIZE_SAVE -MORESTACK_FRAMESIZE+PARAMS+88
+
+# Excess space needed to call ld.so resolver for lazy plt
+# resolution. Go uses sigaltstack so this doesn't need to
+# also cover signal frame size.
+#define BACKOFF 4096
+# Large excess allocated when calling non-split-stack code.
+#define NON_SPLIT_STACK 0x100000
+
+
+#if _CALL_ELF == 2
+
+#define BODY_LABEL(name) name
+
+#define ENTRY0(name) \
+ .global name; \
+ .hidden name; \
+ .type name,@function; \
+name##:
+
+#define ENTRY(name) \
+ ENTRY0(name); \
+0: addis %r2,%r12,.TOC.-0b@ha; \
+ addi %r2,%r2,.TOC.-0b@l; \
+ .localentry name, .-name
+
+#else
+
+#define BODY_LABEL(name) .L.##name
+
+#define ENTRY0(name) \
+ .global name; \
+ .hidden name; \
+ .type name,@function; \
+ .pushsection ".opd","aw"; \
+ .p2align 3; \
+name##: .quad BODY_LABEL (name), .TOC.@tocbase, 0; \
+ .popsection; \
+BODY_LABEL(name)##:
+
+#define ENTRY(name) ENTRY0(name)
+
+#endif
+
+#define SIZE(name) .size name, .-BODY_LABEL(name)
+
+
+ .text
+# Just like __morestack, but with larger excess allocation
+ENTRY0(__morestack_non_split)
+.LFB1:
+ .cfi_startproc
+# We use a cleanup to restore the tcbhead_t.__private_ss if
+# an exception is thrown through this code.
+#ifdef __PIC__
+ .cfi_personality 0x9b,DW.ref.__gcc_personality_v0
+ .cfi_lsda 0x1b,.LLSDA1
+#else
+ .cfi_personality 0x3,__gcc_personality_v0
+ .cfi_lsda 0x3,.LLSDA1
+#endif
+# LR is already saved by the split-stack prologue code.
+# We may as well have the unwinder skip over the call in the
+# prologue too.
+ .cfi_offset %lr,16
+
+ addis %r12,%r12,-NON_SPLIT_STACK@h
+ SIZE (__morestack_non_split)
+# Fall through into __morestack
+
+
+# This function is called with non-standard calling conventions.
+# On entry, r12 is the requested stack pointer. One version of the
+# split-stack prologue that calls __morestack looks like
+# ld %r0,-0x7000-64(%r13)
+# addis %r12,%r1,-allocate@ha
+# addi %r12,%r12,-allocate@l
+# cmpld %r12,%r0
+# bge+ enough
+# mflr %r0
+# std %r0,16(%r1)
+# bl __morestack
+# ld %r0,16(%r1)
+# mtlr %r0
+# blr
+# enough:
+# The normal function prologue follows here, with a small addition at
+# the end to set up the arg pointer. The arg pointer is set up with:
+# addi %r12,%r1,offset
+# bge %cr7,.+8
+# mr %r12,%r29
+#
+# Note that the lr save slot 16(%r1) has already been used.
+# r3 thru r11 possibly contain arguments and a static chain
+# pointer for the function we're calling, so must be preserved.
+# cr7 must also be preserved.
+
+ENTRY0(__morestack)
+# Save parameter passing registers, our arguments, lr, r29
+# and use r29 as a frame pointer.
+ std %r3,PARAMREG_SAVE+0(%r1)
+ sub %r3,%r1,%r12 # calculate requested stack size
+ mflr %r12
+ std %r4,PARAMREG_SAVE+8(%r1)
+ std %r5,PARAMREG_SAVE+16(%r1)
+ std %r6,PARAMREG_SAVE+24(%r1)
+ std %r7,PARAMREG_SAVE+32(%r1)
+ addi %r3,%r3,BACKOFF
+ std %r8,PARAMREG_SAVE+40(%r1)
+ std %r9,PARAMREG_SAVE+48(%r1)
+ std %r10,PARAMREG_SAVE+56(%r1)
+ std %r11,STATIC_CHAIN_SAVE(%r1)
+ std %r29,R29_SAVE(%r1)
+ std %r12,LINKREG_SAVE(%r1)
+ std %r3,NEWSTACKSIZE_SAVE(%r1) # new stack size
+ mr %r29,%r1
+ .cfi_offset %r29,R29_SAVE
+ .cfi_def_cfa_register %r29
+ stdu %r1,-MORESTACK_FRAMESIZE(%r1)
+
+ # void __morestack_block_signals (void)
+ bl __morestack_block_signals
+
+ # void *__generic_morestack (size_t *pframe_size,
+ # void *old_stack,
+ # size_t param_size)
+ addi %r3,%r29,NEWSTACKSIZE_SAVE
+ mr %r4,%r29
+ li %r5,0 # no copying from old stack
+ bl __generic_morestack
+
+# Start using new stack
+ stdu %r29,-32(%r3) # back-chain
+ mr %r1,%r3
+
+# Set __private_ss stack guard for the new stack.
+ ld %r12,NEWSTACKSIZE_SAVE(%r29) # modified size
+ addi %r3,%r3,BACKOFF-32
+ sub %r3,%r3,%r12
+# Note that a signal frame has $pc pointing at the instruction
+# where the signal occurred. For something like a timer
+# interrupt this means the instruction has already executed,
+# thus the region starts at the instruction modifying
+# __private_ss, not one instruction after.
+.LEHB0:
+ std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss
+
+ # void __morestack_unblock_signals (void)
+ bl __morestack_unblock_signals
+
+# Set up for a call to the target function, located 3
+# instructions after __morestack's return address.
+#
+ ld %r12,LINKREG_SAVE(%r29)
+ ld %r3,PARAMREG_SAVE+0(%r29) # restore arg regs
+ ld %r4,PARAMREG_SAVE+8(%r29)
+ ld %r5,PARAMREG_SAVE+16(%r29)
+ ld %r6,PARAMREG_SAVE+24(%r29)
+ ld %r7,PARAMREG_SAVE+32(%r29)
+ ld %r8,PARAMREG_SAVE+40(%r29)
+ ld %r9,PARAMREG_SAVE+48(%r29)
+ addi %r0,%r12,12 # add 3 instructions
+ ld %r10,PARAMREG_SAVE+56(%r29)
+ ld %r11,STATIC_CHAIN_SAVE(%r29)
+ cmpld %cr7,%r12,%r0 # indicate we were called
+ mtctr %r0
+ bctrl # call caller!
+
+# On return, save regs possibly used to return a value, and
+# possibly trashed by calls to __morestack_block_signals,
+# __generic_releasestack and __morestack_unblock_signals.
+# Assume those calls don't use vector or floating point regs.
+ std %r3,PARAMREG_SAVE+0(%r29)
+ std %r4,PARAMREG_SAVE+8(%r29)
+ std %r5,PARAMREG_SAVE+16(%r29)
+ std %r6,PARAMREG_SAVE+24(%r29)
+#if _CALL_ELF == 2
+ std %r7,PARAMREG_SAVE+32(%r29)
+ std %r8,PARAMREG_SAVE+40(%r29)
+ std %r9,PARAMREG_SAVE+48(%r29)
+ std %r10,PARAMREG_SAVE+56(%r29)
+#endif
+
+ bl __morestack_block_signals
+
+ # void *__generic_releasestack (size_t *pavailable)
+ addi %r3,%r29,NEWSTACKSIZE_SAVE
+ bl __generic_releasestack
+
+# Reset __private_ss stack guard to value for old stack
+ ld %r12,NEWSTACKSIZE_SAVE(%r29)
+ addi %r3,%r3,BACKOFF
+ sub %r3,%r3,%r12
+.LEHE0:
+ std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss
+
+ bl __morestack_unblock_signals
+
+# Use old stack again.
+ mr %r1,%r29
+
+# Restore return value regs, and return.
+ ld %r0,LINKREG_SAVE(%r29)
+ mtlr %r0
+ ld %r3,PARAMREG_SAVE+0(%r29)
+ ld %r4,PARAMREG_SAVE+8(%r29)
+ ld %r5,PARAMREG_SAVE+16(%r29)
+ ld %r6,PARAMREG_SAVE+24(%r29)
+#if _CALL_ELF == 2
+ ld %r7,PARAMREG_SAVE+32(%r29)
+ ld %r8,PARAMREG_SAVE+40(%r29)
+ ld %r9,PARAMREG_SAVE+48(%r29)
+ ld %r10,PARAMREG_SAVE+56(%r29)
+#endif
+ ld %r29,R29_SAVE(%r29)
+ .cfi_def_cfa_register %r1
+ blr
+
+# This is the cleanup code called by the stack unwinder when
+# unwinding through code between .LEHB0 and .LEHE0 above.
+cleanup:
+ .cfi_def_cfa_register %r29
+ std %r3,PARAMREG_SAVE(%r29) # Save exception header
+ # size_t __generic_findstack (void *stack)
+ mr %r3,%r29
+ bl __generic_findstack
+ sub %r3,%r29,%r3
+ addi %r3,%r3,BACKOFF
+ std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss
+ ld %r3,PARAMREG_SAVE(%r29)
+ bl _Unwind_Resume
+ nop
+ .cfi_endproc
+ SIZE (__morestack)
+
+
+ .section .gcc_except_table,"a",@progbits
+ .p2align 2
+.LLSDA1:
+ .byte 0xff # @LPStart format (omit)
+ .byte 0xff # @TType format (omit)
+ .byte 0x1 # call-site format (uleb128)
+ .uleb128 .LLSDACSE1-.LLSDACSB1 # Call-site table length
+.LLSDACSB1:
+ .uleb128 .LEHB0-.LFB1 # region 0 start
+ .uleb128 .LEHE0-.LEHB0 # length
+ .uleb128 cleanup-.LFB1 # landing pad
+ .uleb128 0 # no action, ie. a cleanup
+.LLSDACSE1:
+
+
+#ifdef __PIC__
+# Build a position independent reference to the personality function.
+ .hidden DW.ref.__gcc_personality_v0
+ .weak DW.ref.__gcc_personality_v0
+ .section .data.DW.ref.__gcc_personality_v0,"awG",@progbits,DW.ref.__gcc_personality_v0,comdat
+ .p2align 3
+DW.ref.__gcc_personality_v0:
+ .quad __gcc_personality_v0
+ .type DW.ref.__gcc_personality_v0, @object
+ .size DW.ref.__gcc_personality_v0, 8
+#endif
+
+
+ .text
+# Initialize the stack guard when the program starts or when a
+# new thread starts. This is called from a constructor.
+# void __stack_split_initialize (void)
+ENTRY(__stack_split_initialize)
+ addi %r3,%r1,-0x4000 # We should have at least 16K.
+ std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss
+ # void __generic_morestack_set_initial_sp (void *sp, size_t len)
+ mr %r3,%r1
+ li %r4, 0x4000
+ b __generic_morestack_set_initial_sp
+ SIZE (__stack_split_initialize)
+
+
+# Return current __private_ss
+# void *__morestack_get_guard (void)
+ENTRY0(__morestack_get_guard)
+ ld %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss
+ blr
+ SIZE (__morestack_get_guard)
+
+
+# Set __private_ss
+# void __morestack_set_guard (void *ptr)
+ENTRY0(__morestack_set_guard)
+ std %r3,-0x7000-64(%r13) # tcbhead_t.__private_ss
+ blr
+ SIZE (__morestack_set_guard)
+
+
+# Return the stack guard value for given stack
+# void *__morestack_make_guard (void *stack, size_t size)
+ENTRY0(__morestack_make_guard)
+ sub %r3,%r3,%r4
+ addi %r3,%r3,BACKOFF
+ blr
+ SIZE (__morestack_make_guard)
+
+
+# Make __stack_split_initialize a high priority constructor.
+ .section .ctors.65535,"aw",@progbits
+ .p2align 3
+ .quad __stack_split_initialize
+ .quad __morestack_load_mmap
+
+ .section .note.GNU-stack,"",@progbits
+ .section .note.GNU-split-stack,"",@progbits
+ .section .note.GNU-no-split-stack,"",@progbits
+#endif /* __powerpc64__ */
diff --git a/libgcc/config/rs6000/t-stack-rs6000 b/libgcc/config/rs6000/t-stack-rs6000
new file mode 100644
index 0000000..0690622
--- /dev/null
+++ b/libgcc/config/rs6000/t-stack-rs6000
@@ -0,0 +1,2 @@
+# Makefile fragment to support -fsplit-stack for powerpc.
+LIB2ADD_ST += $(srcdir)/config/rs6000/morestack.S