diff options
Diffstat (limited to 'gcc-4.9/gcc/ada/sigtramp-ppcvxw.c')
-rw-r--r-- | gcc-4.9/gcc/ada/sigtramp-ppcvxw.c | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/gcc-4.9/gcc/ada/sigtramp-ppcvxw.c b/gcc-4.9/gcc/ada/sigtramp-ppcvxw.c new file mode 100644 index 000000000..0432b0831 --- /dev/null +++ b/gcc-4.9/gcc/ada/sigtramp-ppcvxw.c @@ -0,0 +1,293 @@ +/**************************************************************************** + * * + * GNAT COMPILER COMPONENTS * + * * + * S I G T R A M P * + * * + * Asm Implementation File * + * * + * Copyright (C) 2011-2013, Free Software Foundation, Inc. * + * * + * GNAT is free software; you can redistribute it and/or modify it under * + * terms of the GNU General Public License as published by the Free Soft- * + * ware Foundation; either version 3, or (at your option) any later ver- * + * sion. GNAT is distributed in the hope that it will be useful, but WITH- * + * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. * + * * + * As a special exception 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/>. * + * * + * GNAT was originally developed by the GNAT team at New York University. * + * Extensive contributions were provided by Ada Core Technologies Inc. * + * * + ****************************************************************************/ + +/********************************************************** + * PowerPC-VxWorks version of the __gnat_sigtramp service * + **********************************************************/ + +#include "sigtramp.h" +/* See sigtramp.h for a general explanation of functionality. */ + +#include <vxWorks.h> +#include <arch/../regs.h> +#include <sigLib.h> + +/* ---------------------- + -- General comments -- + ---------------------- + + Stubs are generated from toplevel asms and .cfi directives, much simpler + to use and check for correctness than manual encodings of CFI byte + sequences. The general idea is to establish CFA as sigcontext->sc_pregs + and state where to find the registers as offsets from there. + + As of today, we support a single stub, providing CFI info for common + registers (GPRs, LR, ...). We might need variants with support for floating + point or altivec registers as well at some point. + + Checking which variant should apply and getting at sc_pregs is simpler + to express in C (we can't use offsetof in toplevel asms and hardcoding + constants is not workable with the flurry of VxWorks variants), so this + is the choice for our toplevel interface. + + Note that the registers we "restore" here are those to which we have + direct access through the system sigcontext structure, which includes + only a partial set of the non-volatiles ABI-wise. */ + +/* ----------------------------------------- + -- Protypes for our internal asm stubs -- + ----------------------------------------- + + SC_PREGS is always expected to be SIGCONTEXT->sc_pregs. Eventhough our + symbols will remain local, the prototype claims "extern" and not + "static" to prevent compiler complaints about a symbol used but never + defined. */ + +/* sigtramp stub providing CFI info for common registers. */ + +extern void __gnat_sigtramp_common +(int signo, void *siginfo, void *sigcontext, + sighandler_t * handler, void * sc_pregs); + + +/* ------------------------------------- + -- Common interface implementation -- + ------------------------------------- + + We enforce optimization to minimize the overhead of the extra layer. */ + +void __gnat_sigtramp (int signo, void *si, void *sc, + sighandler_t * handler) + __attribute__((optimize(2))); + +void __gnat_sigtramp (int signo, void *si, void *sc, + sighandler_t * handler) +{ + struct sigcontext * sctx = (struct sigcontext *) sc; + + __gnat_sigtramp_common (signo, si, sctx, handler, sctx->sc_pregs); +} + + +/* --------------------------- + -- And now the asm stubs -- + --------------------------- + + They all have a common structure with blocks of asm sequences queued one + after the others. Typically: + + SYMBOL_START + + CFI_DIRECTIVES + CFI_DEF_CFA, + CFI_COMMON_REGISTERS, + ... + + STUB_BODY + asm code to establish frame, setup the cfa reg value, + call the real signal handler, ... + + SYMBOL_END +*/ + +/*-------------------------------- + -- Misc constants and helpers -- + -------------------------------- */ + +/* REGNO constants, dwarf column numbers for registers of interest. */ + +#define REGNO_LR 65 +#define REGNO_CTR 66 +#define REGNO_CR 70 +#define REGNO_XER 76 +#define REGNO_GR(N) (N) + +#define REGNO_PC 67 /* ARG_POINTER_REGNUM */ + +/* asm string construction helpers. */ + +#define STR(TEXT) #TEXT +/* stringify expanded TEXT, surrounding it with double quotes. */ + +#define S(E) STR(E) +/* stringify E, which will resolve as text but may contain macros + still to be expanded. */ + +/* asm (TEXT) outputs <tab>TEXT. These facilitate the output of + multine contents: */ +#define TAB(S) "\t" S +#define CR(S) S "\n" + +#undef TCR +#define TCR(S) TAB(CR(S)) + +/*------------------------------ + -- Stub construction blocks -- + ------------------------------ */ + +/* CFA setup block + --------------- + Only non-volatile registers are suitable for a CFA base. These are the + only ones we can expect to be able retrieve from the unwinding context + while walking up the chain, saved by at least the bottom-most exception + propagation services. We use r15 here and set it to the value we need + in stub body that follows. Note that r14 is inappropriate here, even + though it is non-volatile according to the ABI, because GCC uses it as + an extra SCRATCH on SPE targets. */ + +#define CFA_REG 15 + +#define CFI_DEF_CFA \ +CR(".cfi_def_cfa " S(CFA_REG) ", 0") + +/* Register location blocks + ------------------------ + Rules to find registers of interest from the CFA. This should comprise + all the non-volatile registers relevant to the interrupted context. + + Note that we include r1 in this set, unlike the libgcc unwinding + fallbacks. This is useful for fallbacks to allow the use of r1 in CFI + expressions and the absence of rule for r1 gets compensated by using the + target CFA instead. We don't need the expression facility here and + setup a fake CFA to allow very simple offset expressions, so having a + rule for r1 is the proper thing to do. We for sure have observed + crashes in some cases without it. */ + +#define COMMON_CFI(REG) \ + ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG) + +#define CFI_COMMON_REGS \ +CR("# CFI for common registers\n") \ +TCR(COMMON_CFI(GR(0))) \ +TCR(COMMON_CFI(GR(1))) \ +TCR(COMMON_CFI(GR(2))) \ +TCR(COMMON_CFI(GR(3))) \ +TCR(COMMON_CFI(GR(4))) \ +TCR(COMMON_CFI(GR(5))) \ +TCR(COMMON_CFI(GR(6))) \ +TCR(COMMON_CFI(GR(7))) \ +TCR(COMMON_CFI(GR(8))) \ +TCR(COMMON_CFI(GR(9))) \ +TCR(COMMON_CFI(GR(10))) \ +TCR(COMMON_CFI(GR(11))) \ +TCR(COMMON_CFI(GR(12))) \ +TCR(COMMON_CFI(GR(13))) \ +TCR(COMMON_CFI(GR(14))) \ +TCR(COMMON_CFI(GR(15))) \ +TCR(COMMON_CFI(GR(16))) \ +TCR(COMMON_CFI(GR(17))) \ +TCR(COMMON_CFI(GR(18))) \ +TCR(COMMON_CFI(GR(19))) \ +TCR(COMMON_CFI(GR(20))) \ +TCR(COMMON_CFI(GR(21))) \ +TCR(COMMON_CFI(GR(22))) \ +TCR(COMMON_CFI(GR(23))) \ +TCR(COMMON_CFI(GR(24))) \ +TCR(COMMON_CFI(GR(25))) \ +TCR(COMMON_CFI(GR(26))) \ +TCR(COMMON_CFI(GR(27))) \ +TCR(COMMON_CFI(GR(28))) \ +TCR(COMMON_CFI(GR(29))) \ +TCR(COMMON_CFI(GR(30))) \ +TCR(COMMON_CFI(GR(31))) \ +TCR(COMMON_CFI(LR)) \ +TCR(COMMON_CFI(CR)) \ +TCR(COMMON_CFI(CTR)) \ +TCR(COMMON_CFI(XER)) \ +TCR(COMMON_CFI(PC)) \ +TCR(".cfi_return_column " S(REGNO_PC)) + +/* Trampoline body block + --------------------- */ + +#define SIGTRAMP_BODY \ +CR("") \ +TCR("# Allocate frame and save the non-volatile") \ +TCR("# registers we're going to modify") \ +TCR("stwu %r1,-16(%r1)") \ +TCR("mflr %r0") \ +TCR("stw %r0,20(%r1)") \ +TCR("stw %r" S(CFA_REG) ",8(%r1)") \ +TCR("") \ +TCR("# Setup CFA_REG = sc_pregs, that we'll retrieve as our CFA value") \ +TCR("mr %r" S(CFA_REG) ", %r7") \ +TCR("") \ +TCR("# Call the real handler. The signo, siginfo and sigcontext") \ +TCR("# arguments are the same as those we received in r3, r4 and r5") \ +TCR("mtctr %r6") \ +TCR("bctrl") \ +TCR("") \ +TCR("# Restore our callee-saved items, release our frame and return") \ +TCR("lwz %r" S(CFA_REG) ",8(%r1)") \ +TCR("lwz %r0,20(%r1)") \ +TCR("mtlr %r0") \ +TCR("") \ +TCR("addi %r1,%r1,16") \ +TCR("blr") + +/* Symbol definition block + ----------------------- */ + +#define SIGTRAMP_START(SYM) \ +CR("# " S(SYM) " cfi trampoline") \ +TCR(".type " S(SYM) ", @function") \ +CR("") \ +CR(S(SYM) ":") \ +TCR(".cfi_startproc") \ +TCR(".cfi_signal_frame") + +/* Symbol termination block + ------------------------ */ + +#define SIGTRAMP_END(SYM) \ +CR(".cfi_endproc") \ +TCR(".size " S(SYM) ", .-" S(SYM)) + +/*---------------------------- + -- And now, the real code -- + ---------------------------- */ + +/* Text section start. The compiler isn't aware of that switch. */ + +asm (".text\n" + TCR(".align 2")); + +/* sigtramp stub for common registers. */ + +#define TRAMP_COMMON __gnat_sigtramp_common + +asm (SIGTRAMP_START(TRAMP_COMMON)); +asm (CFI_DEF_CFA); +asm (CFI_COMMON_REGS); +asm (SIGTRAMP_BODY); +asm (SIGTRAMP_END(TRAMP_COMMON)); + + |