diff options
Diffstat (limited to 'gcc/config/rs6000')
-rw-r--r-- | gcc/config/rs6000/aix.h | 34 | ||||
-rw-r--r-- | gcc/config/rs6000/darwin-fallback.c | 487 | ||||
-rw-r--r-- | gcc/config/rs6000/t-darwin | 4 |
3 files changed, 1 insertions, 524 deletions
diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h index 13d317f508a..2c678a3a247 100644 --- a/gcc/config/rs6000/aix.h +++ b/gcc/config/rs6000/aix.h @@ -209,40 +209,6 @@ /* And similarly for general purpose registers. */ #define GP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 32) -/* If the current unwind info (FS) does not contain explicit info - saving R2, then we have to do a minor amount of code reading to - figure out if it was saved. The big problem here is that the - code that does the save/restore is generated by the linker, so - we have no good way to determine at compile time what to do. */ - -#define R_LR 65 - -#ifdef __64BIT__ -#define MD_FROB_UPDATE_CONTEXT(CTX, FS) \ - do { \ - if ((FS)->regs.reg[2].how == REG_UNSAVED) \ - { \ - unsigned int *insn \ - = (unsigned int *) \ - _Unwind_GetGR ((CTX), R_LR); \ - if (*insn == 0xE8410028) \ - _Unwind_SetGRPtr ((CTX), 2, (CTX)->cfa + 40); \ - } \ - } while (0) -#else -#define MD_FROB_UPDATE_CONTEXT(CTX, FS) \ - do { \ - if ((FS)->regs.reg[2].how == REG_UNSAVED) \ - { \ - unsigned int *insn \ - = (unsigned int *) \ - _Unwind_GetGR ((CTX), R_LR); \ - if (*insn == 0x80410014) \ - _Unwind_SetGRPtr ((CTX), 2, (CTX)->cfa + 20); \ - } \ - } while (0) -#endif - #define PROFILE_HOOK(LABEL) output_profile_hook (LABEL) /* No version of AIX fully supports AltiVec or 64-bit instructions in diff --git a/gcc/config/rs6000/darwin-fallback.c b/gcc/config/rs6000/darwin-fallback.c deleted file mode 100644 index 4591071ea74..00000000000 --- a/gcc/config/rs6000/darwin-fallback.c +++ /dev/null @@ -1,487 +0,0 @@ -/* Fallback frame-state unwinder for Darwin. - Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. - - 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/>. */ - -#ifdef __ppc__ - -#include "tconfig.h" -#include "tsystem.h" -#include "coretypes.h" -#include "tm.h" -#include "dwarf2.h" -#include "unwind.h" -#include "unwind-dw2.h" -#include <stdint.h> -#include <stdbool.h> -#include <sys/types.h> -#include <signal.h> - -#define R_LR 65 -#define R_CTR 66 -#define R_CR2 70 -#define R_XER 76 -#define R_VR0 77 -#define R_VRSAVE 109 -#define R_VSCR 110 -#define R_SPEFSCR 112 - -typedef unsigned long reg_unit; - -/* Place in GPRS the parameters to the first 'sc' instruction that would - have been executed if we were returning from this CONTEXT, or - return false if an unexpected instruction is encountered. */ - -static bool -interpret_libc (reg_unit gprs[32], struct _Unwind_Context *context) -{ - uint32_t *pc = (uint32_t *)_Unwind_GetIP (context); - uint32_t cr; - reg_unit lr = (reg_unit) pc; - reg_unit ctr = 0; - uint32_t *invalid_address = NULL; - - int i; - - for (i = 0; i < 13; i++) - gprs[i] = 1; - gprs[1] = _Unwind_GetCFA (context); - for (; i < 32; i++) - gprs[i] = _Unwind_GetGR (context, i); - cr = _Unwind_GetGR (context, R_CR2); - - /* For each supported Libc, we have to track the code flow - all the way back into the kernel. - - This code is believed to support all released Libc/Libsystem builds since - Jaguar 6C115, including all the security updates. To be precise, - - Libc Libsystem Build(s) - 262~1 60~37 6C115 - 262~1 60.2~4 6D52 - 262~1 61~3 6F21-6F22 - 262~1 63~24 6G30-6G37 - 262~1 63~32 6I34-6I35 - 262~1 63~64 6L29-6L60 - 262.4.1~1 63~84 6L123-6R172 - - 320~1 71~101 7B85-7D28 - 320~1 71~266 7F54-7F56 - 320~1 71~288 7F112 - 320~1 71~289 7F113 - 320.1.3~1 71.1.1~29 7H60-7H105 - 320.1.3~1 71.1.1~30 7H110-7H113 - 320.1.3~1 71.1.1~31 7H114 - - That's a big table! It would be insane to try to keep track of - every little detail, so we just read the code itself and do what - it would do. - */ - - for (;;) - { - uint32_t ins = *pc++; - - if ((ins & 0xFC000003) == 0x48000000) /* b instruction */ - { - pc += ((((int32_t) ins & 0x3FFFFFC) ^ 0x2000000) - 0x2000004) / 4; - continue; - } - if ((ins & 0xFC600000) == 0x2C000000) /* cmpwi */ - { - int32_t val1 = (int16_t) ins; - int32_t val2 = gprs[ins >> 16 & 0x1F]; - /* Only beq and bne instructions are supported, so we only - need to set the EQ bit. */ - uint32_t mask = 0xF << ((ins >> 21 & 0x1C) ^ 0x1C); - if (val1 == val2) - cr |= mask; - else - cr &= ~mask; - continue; - } - if ((ins & 0xFEC38003) == 0x40820000) /* forwards beq/bne */ - { - if ((cr >> ((ins >> 16 & 0x1F) ^ 0x1F) & 1) == (ins >> 24 & 1)) - pc += (ins & 0x7FFC) / 4 - 1; - continue; - } - if ((ins & 0xFC0007FF) == 0x7C000378) /* or, including mr */ - { - gprs [ins >> 16 & 0x1F] = (gprs [ins >> 11 & 0x1F] - | gprs [ins >> 21 & 0x1F]); - continue; - } - if (ins >> 26 == 0x0E) /* addi, including li */ - { - reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F]; - gprs [ins >> 21 & 0x1F] = src + (int16_t) ins; - continue; - } - if (ins >> 26 == 0x0F) /* addis, including lis */ - { - reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F]; - gprs [ins >> 21 & 0x1F] = src + ((int16_t) ins << 16); - continue; - } - if (ins >> 26 == 0x20) /* lwz */ - { - reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F]; - uint32_t *p = (uint32_t *)(src + (int16_t) ins); - if (p == invalid_address) - return false; - gprs [ins >> 21 & 0x1F] = *p; - continue; - } - if (ins >> 26 == 0x21) /* lwzu */ - { - uint32_t *p = (uint32_t *)(gprs [ins >> 16 & 0x1F] += (int16_t) ins); - if (p == invalid_address) - return false; - gprs [ins >> 21 & 0x1F] = *p; - continue; - } - if (ins >> 26 == 0x24) /* stw */ - /* What we hope this is doing is '--in_sigtramp'. We don't want - to actually store to memory, so just make a note of the - address and refuse to load from it. */ - { - reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F]; - uint32_t *p = (uint32_t *)(src + (int16_t) ins); - if (p == NULL || invalid_address != NULL) - return false; - invalid_address = p; - continue; - } - if (ins >> 26 == 0x2E) /* lmw */ - { - reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F]; - uint32_t *p = (uint32_t *)(src + (int16_t) ins); - int i; - - for (i = (ins >> 21 & 0x1F); i < 32; i++) - { - if (p == invalid_address) - return false; - gprs[i] = *p++; - } - continue; - } - if ((ins & 0xFC1FFFFF) == 0x7c0803a6) /* mtlr */ - { - lr = gprs [ins >> 21 & 0x1F]; - continue; - } - if ((ins & 0xFC1FFFFF) == 0x7c0802a6) /* mflr */ - { - gprs [ins >> 21 & 0x1F] = lr; - continue; - } - if ((ins & 0xFC1FFFFF) == 0x7c0903a6) /* mtctr */ - { - ctr = gprs [ins >> 21 & 0x1F]; - continue; - } - /* The PowerPC User's Manual says that bit 11 of the mtcrf - instruction is reserved and should be set to zero, but it - looks like the Darwin assembler doesn't do that... */ - if ((ins & 0xFC000FFF) == 0x7c000120) /* mtcrf */ - { - int i; - uint32_t mask = 0; - for (i = 0; i < 8; i++) - mask |= ((-(ins >> (12 + i) & 1)) & 0xF) << 4 * i; - cr = (cr & ~mask) | (gprs [ins >> 21 & 0x1F] & mask); - continue; - } - if (ins == 0x429f0005) /* bcl- 20,4*cr7+so,.+4, loads pc into LR */ - { - lr = (reg_unit) pc; - continue; - } - if (ins == 0x4e800420) /* bctr */ - { - pc = (uint32_t *) ctr; - continue; - } - if (ins == 0x44000002) /* sc */ - return true; - - return false; - } -} - -/* We used to include <ucontext.h> and <mach/thread_status.h>, - but they change so much between different Darwin system versions - that it's much easier to just write the structures involved here - directly. */ - -/* These defines are from the kernel's bsd/dev/ppc/unix_signal.c. */ -#define UC_TRAD 1 -#define UC_TRAD_VEC 6 -#define UC_TRAD64 20 -#define UC_TRAD64_VEC 25 -#define UC_FLAVOR 30 -#define UC_FLAVOR_VEC 35 -#define UC_FLAVOR64 40 -#define UC_FLAVOR64_VEC 45 -#define UC_DUAL 50 -#define UC_DUAL_VEC 55 - -struct gcc_ucontext -{ - int onstack; - sigset_t sigmask; - void * stack_sp; - size_t stack_sz; - int stack_flags; - struct gcc_ucontext *link; - size_t mcsize; - struct gcc_mcontext32 *mcontext; -}; - -struct gcc_float_vector_state -{ - double fpregs[32]; - uint32_t fpscr_pad; - uint32_t fpscr; - uint32_t save_vr[32][4]; - uint32_t save_vscr[4]; -}; - -struct gcc_mcontext32 { - uint32_t dar; - uint32_t dsisr; - uint32_t exception; - uint32_t padding1[5]; - uint32_t srr0; - uint32_t srr1; - uint32_t gpr[32]; - uint32_t cr; - uint32_t xer; - uint32_t lr; - uint32_t ctr; - uint32_t mq; - uint32_t vrsave; - struct gcc_float_vector_state fvs; -}; - -/* These are based on /usr/include/ppc/ucontext.h and - /usr/include/mach/ppc/thread_status.h, but rewritten to be more - convenient, to compile on Jaguar, and to work around Radar 3712064 - on Panther, which is that the 'es' field of 'struct mcontext64' has - the wrong type (doh!). */ - -struct gcc_mcontext64 { - uint64_t dar; - uint32_t dsisr; - uint32_t exception; - uint32_t padding1[4]; - uint64_t srr0; - uint64_t srr1; - uint32_t gpr[32][2]; - uint32_t cr; - uint32_t xer[2]; /* These are arrays because the original structure has them misaligned. */ - uint32_t lr[2]; - uint32_t ctr[2]; - uint32_t vrsave; - struct gcc_float_vector_state fvs; -}; - -#define UC_FLAVOR_SIZE \ - (sizeof (struct gcc_mcontext32) - 33*16) - -#define UC_FLAVOR_VEC_SIZE (sizeof (struct gcc_mcontext32)) - -#define UC_FLAVOR64_SIZE \ - (sizeof (struct gcc_mcontext64) - 33*16) - -#define UC_FLAVOR64_VEC_SIZE (sizeof (struct gcc_mcontext64)) - -/* Given GPRS as input to a 'sc' instruction, and OLD_CFA, update FS - to represent the execution of a signal return; or, if not a signal - return, return false. */ - -static bool -handle_syscall (_Unwind_FrameState *fs, const reg_unit gprs[32], - _Unwind_Ptr old_cfa) -{ - struct gcc_ucontext *uctx; - bool is_64, is_vector; - struct gcc_float_vector_state * float_vector_state; - _Unwind_Ptr new_cfa; - int i; - static _Unwind_Ptr return_addr; - - /* Yay! We're in a Libc that we understand, and it's made a - system call. In Jaguar, this is a direct system call with value 103; - in Panther and Tiger it is a SYS_syscall call for system call number 184, - and in Leopard it is a direct syscall with number 184. */ - - if (gprs[0] == 0x67 /* SYS_SIGRETURN */) - { - uctx = (struct gcc_ucontext *) gprs[3]; - is_vector = (uctx->mcsize == UC_FLAVOR64_VEC_SIZE - || uctx->mcsize == UC_FLAVOR_VEC_SIZE); - is_64 = (uctx->mcsize == UC_FLAVOR64_VEC_SIZE - || uctx->mcsize == UC_FLAVOR64_SIZE); - } - else if (gprs[0] == 0 /* SYS_syscall */ && gprs[3] == 184) - { - int ctxstyle = gprs[5]; - uctx = (struct gcc_ucontext *) gprs[4]; - is_vector = (ctxstyle == UC_FLAVOR_VEC || ctxstyle == UC_FLAVOR64_VEC - || ctxstyle == UC_TRAD_VEC || ctxstyle == UC_TRAD64_VEC); - is_64 = (ctxstyle == UC_FLAVOR64_VEC || ctxstyle == UC_TRAD64_VEC - || ctxstyle == UC_FLAVOR64 || ctxstyle == UC_TRAD64); - } - else if (gprs[0] == 184 /* SYS_sigreturn */) - { - int ctxstyle = gprs[4]; - uctx = (struct gcc_ucontext *) gprs[3]; - is_vector = (ctxstyle == UC_FLAVOR_VEC || ctxstyle == UC_FLAVOR64_VEC - || ctxstyle == UC_TRAD_VEC || ctxstyle == UC_TRAD64_VEC); - is_64 = (ctxstyle == UC_FLAVOR64_VEC || ctxstyle == UC_TRAD64_VEC - || ctxstyle == UC_FLAVOR64 || ctxstyle == UC_TRAD64); - } - else - return false; - -#define set_offset(r, addr) \ - (fs->regs.reg[r].how = REG_SAVED_OFFSET, \ - fs->regs.reg[r].loc.offset = (_Unwind_Ptr)(addr) - new_cfa) - - /* Restore even the registers that are not call-saved, since they - might be being used in the prologue to save other registers, - for instance GPR0 is sometimes used to save LR. */ - - /* Handle the GPRs, and produce the information needed to do the rest. */ - if (is_64) - { - /* The context is 64-bit, but it doesn't carry any extra information - for us because only the low 32 bits of the registers are - call-saved. */ - struct gcc_mcontext64 *m64 = (struct gcc_mcontext64 *)uctx->mcontext; - int i; - - float_vector_state = &m64->fvs; - - new_cfa = m64->gpr[1][1]; - - set_offset (R_CR2, &m64->cr); - for (i = 0; i < 32; i++) - set_offset (i, m64->gpr[i] + 1); - set_offset (R_XER, m64->xer + 1); - set_offset (R_LR, m64->lr + 1); - set_offset (R_CTR, m64->ctr + 1); - if (is_vector) - set_offset (R_VRSAVE, &m64->vrsave); - - /* Sometimes, srr0 points to the instruction that caused the exception, - and sometimes to the next instruction to be executed; we want - the latter. */ - if (m64->exception == 3 || m64->exception == 4 - || m64->exception == 6 - || (m64->exception == 7 && !(m64->srr1 & 0x10000))) - return_addr = m64->srr0 + 4; - else - return_addr = m64->srr0; - } - else - { - struct gcc_mcontext32 *m = uctx->mcontext; - int i; - - float_vector_state = &m->fvs; - - new_cfa = m->gpr[1]; - - set_offset (R_CR2, &m->cr); - for (i = 0; i < 32; i++) - set_offset (i, m->gpr + i); - set_offset (R_XER, &m->xer); - set_offset (R_LR, &m->lr); - set_offset (R_CTR, &m->ctr); - - if (is_vector) - set_offset (R_VRSAVE, &m->vrsave); - - /* Sometimes, srr0 points to the instruction that caused the exception, - and sometimes to the next instruction to be executed; we want - the latter. */ - if (m->exception == 3 || m->exception == 4 - || m->exception == 6 - || (m->exception == 7 && !(m->srr1 & 0x10000))) - return_addr = m->srr0 + 4; - else - return_addr = m->srr0; - } - - fs->regs.cfa_how = CFA_REG_OFFSET; - fs->regs.cfa_reg = STACK_POINTER_REGNUM; - fs->regs.cfa_offset = new_cfa - old_cfa;; - - /* The choice of column for the return address is somewhat tricky. - Fortunately, the actual choice is private to this file, and - the space it's reserved from is the GCC register space, not the - DWARF2 numbering. So any free element of the right size is an OK - choice. Thus: */ - fs->retaddr_column = ARG_POINTER_REGNUM; - /* FIXME: this should really be done using a DWARF2 location expression, - not using a static variable. In fact, this entire file should - be implemented in DWARF2 expressions. */ - set_offset (ARG_POINTER_REGNUM, &return_addr); - - for (i = 0; i < 32; i++) - set_offset (32 + i, float_vector_state->fpregs + i); - set_offset (R_SPEFSCR, &float_vector_state->fpscr); - - if (is_vector) - { - for (i = 0; i < 32; i++) - set_offset (R_VR0 + i, float_vector_state->save_vr + i); - set_offset (R_VSCR, float_vector_state->save_vscr); - } - - return true; -} - -/* This is also prototyped in rs6000/darwin.h, inside the - MD_FALLBACK_FRAME_STATE_FOR macro. */ -extern bool _Unwind_fallback_frame_state_for (struct _Unwind_Context *context, - _Unwind_FrameState *fs); - -/* Implement the MD_FALLBACK_FRAME_STATE_FOR macro, - returning true iff the frame was a sigreturn() frame that we - can understand. */ - -bool -_Unwind_fallback_frame_state_for (struct _Unwind_Context *context, - _Unwind_FrameState *fs) -{ - reg_unit gprs[32]; - - if (!interpret_libc (gprs, context)) - return false; - return handle_syscall (fs, gprs, _Unwind_GetCFA (context)); -} -#endif diff --git a/gcc/config/rs6000/t-darwin b/gcc/config/rs6000/t-darwin index 8113b9ecbcb..27fc07b69b3 100644 --- a/gcc/config/rs6000/t-darwin +++ b/gcc/config/rs6000/t-darwin @@ -1,5 +1,5 @@ # Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, -# 2007 Free Software Foundation, Inc. +# 2007, 2011 Free Software Foundation, Inc. # # This file is part of GCC. # @@ -40,7 +40,5 @@ TARGET_LIBGCC2_CFLAGS = -Wa,-force_cpusubtype_ALL -pipe -mmacosx-version-min=10. # Export the _xlq* symbols from darwin-ldouble.c. SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-ppc64.ver -LIB2ADDEH += $(srcdir)/config/rs6000/darwin-fallback.c - darwin-fpsave.o: $(srcdir)/config/rs6000/darwin-asm.h darwin-tramp.o: $(srcdir)/config/rs6000/darwin-asm.h |