diff options
author | Alan Modra <amodra@gmail.com> | 2015-05-20 10:56:28 +0930 |
---|---|---|
committer | Alan Modra <amodra@gcc.gnu.org> | 2015-05-20 10:56:28 +0930 |
commit | 0f0fd745255adf8b2904b0acaf1c3b66ec93ddb2 (patch) | |
tree | 25d754bde890f2750c3489f49713ea0123e09339 /libgcc | |
parent | 8a03f86937467dcfe401b4f369307faf2593e97a (diff) | |
download | gcc-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')
-rw-r--r-- | libgcc/ChangeLog | 8 | ||||
-rw-r--r-- | libgcc/config.host | 1 | ||||
-rw-r--r-- | libgcc/config/rs6000/morestack.S | 351 | ||||
-rw-r--r-- | libgcc/config/rs6000/t-stack-rs6000 | 2 | ||||
-rw-r--r-- | libgcc/generic-morestack.c | 5 |
5 files changed, 367 insertions, 0 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 51b6cf2..c4e716e 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,11 @@ +2015-05-20 Alan Modra <amodra@gmail.com> + + * 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. + 2015-05-19 Eric Botcazou <ebotcazou@adacore.com> * Makefile.in (LIBUNWIND): Move dependency for shared libgcc. diff --git a/libgcc/config.host b/libgcc/config.host index d624221..8d82680 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -1027,6 +1027,7 @@ powerpc-*-rtems*) ;; powerpc*-*-linux*) tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-savresfgpr rs6000/t-crtstuff rs6000/t-linux t-dfprules rs6000/t-ppc64-fp t-slibgcc-libgcc" + tmake_file="${tmake_file} t-stack rs6000/t-stack-rs6000" case $ppc_fp_type in 64) ;; 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 diff --git a/libgcc/generic-morestack.c b/libgcc/generic-morestack.c index 76f94d2..a10559b 100644 --- a/libgcc/generic-morestack.c +++ b/libgcc/generic-morestack.c @@ -23,6 +23,9 @@ 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/>. */ +/* powerpc 32-bit not supported. */ +#if !defined __powerpc__ || defined __powerpc64__ + #include "tconfig.h" #include "tsystem.h" #include "coretypes.h" @@ -935,6 +938,7 @@ __splitstack_find (void *segment_arg, void *sp, size_t *len, nsp -= 12 * sizeof (void *); #elif defined (__i386__) nsp -= 6 * sizeof (void *); +#elif defined __powerpc64__ #else #error "unrecognized target" #endif @@ -1170,3 +1174,4 @@ __splitstack_find_context (void *context[NUMBER_OFFSETS], size_t *stack_size, } #endif /* !defined (inhibit_libc) */ +#endif /* not powerpc 32-bit */ |