diff options
Diffstat (limited to 'libsigsegv/src/fault-macosdarwin7-powerpc.c')
-rw-r--r-- | libsigsegv/src/fault-macosdarwin7-powerpc.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/libsigsegv/src/fault-macosdarwin7-powerpc.c b/libsigsegv/src/fault-macosdarwin7-powerpc.c new file mode 100644 index 00000000..e8e9337a --- /dev/null +++ b/libsigsegv/src/fault-macosdarwin7-powerpc.c @@ -0,0 +1,131 @@ +/* Fault handler information subroutine. MacOSX/Darwin7/PowerPC version. + * Taken from gcc-3.2/boehm-gc/os_dep.c. + * + * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers + * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. + * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. + * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved. + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + */ + +#include <ucontext.h> + +/* Decodes the machine instruction which was responsible for the sending of the + SIGBUS signal. Sadly this is the only way to find the faulting address + because the signal handler doesn't get it directly from the kernel (although + it is available on the Mach level, but dropped by the BSD personality before + it calls our signal handler...) + This code should be able to deal correctly with all PPCs starting from the + 601 up to and including the G4s (including Velocity Engine). */ +#define EXTRACT_OP1(iw) (((iw) & 0xFC000000) >> 26) +#define EXTRACT_OP2(iw) (((iw) & 0x000007FE) >> 1) +#define EXTRACT_REGA(iw) (((iw) & 0x001F0000) >> 16) +#define EXTRACT_REGB(iw) (((iw) & 0x03E00000) >> 21) +#define EXTRACT_REGC(iw) (((iw) & 0x0000F800) >> 11) +#define EXTRACT_DISP(iw) ((short *) &(iw))[1] + +static void * +get_fault_addr (siginfo_t *sip, ucontext_t *ucp) +{ + unsigned int instr = *(unsigned int *) sip->si_addr; + unsigned int *regs = +#if __DARWIN_UNIX03 + &ucp->uc_mcontext->ss.__r0; /* r0..r31 */ +#else + &ucp->uc_mcontext->ss.r0; /* r0..r31 */ +#endif + int disp = 0; + int tmp; + unsigned int baseA = 0; + unsigned int baseB = 0; + unsigned int addr; + unsigned int alignmask = 0xFFFFFFFF; + + switch (EXTRACT_OP1 (instr)) + { + case 38: /* stb */ + case 39: /* stbu */ + case 54: /* stfd */ + case 55: /* stfdu */ + case 52: /* stfs */ + case 53: /* stfsu */ + case 44: /* sth */ + case 45: /* sthu */ + case 47: /* stmw */ + case 36: /* stw */ + case 37: /* stwu */ + tmp = EXTRACT_REGA (instr); + if (tmp > 0) + baseA = regs[tmp]; + disp = EXTRACT_DISP (instr); + break; + case 31: + switch (EXTRACT_OP2 (instr)) + { + case 86: /* dcbf */ + case 54: /* dcbst */ + case 1014: /* dcbz */ + case 247: /* stbux */ + case 215: /* stbx */ + case 759: /* stfdux */ + case 727: /* stfdx */ + case 983: /* stfiwx */ + case 695: /* stfsux */ + case 663: /* stfsx */ + case 918: /* sthbrx */ + case 439: /* sthux */ + case 407: /* sthx */ + case 661: /* stswx */ + case 662: /* stwbrx */ + case 150: /* stwcx. */ + case 183: /* stwux */ + case 151: /* stwx */ + case 135: /* stvebx */ + case 167: /* stvehx */ + case 199: /* stvewx */ + case 231: /* stvx */ + case 487: /* stvxl */ + tmp = EXTRACT_REGA (instr); + if (tmp > 0) + baseA = regs[tmp]; + baseB = regs[EXTRACT_REGC (instr)]; + /* Determine Altivec alignment mask. */ + switch (EXTRACT_OP2 (instr)) + { + case 167: /* stvehx */ + alignmask = 0xFFFFFFFE; + break; + case 199: /* stvewx */ + alignmask = 0xFFFFFFFC; + break; + case 231: /* stvx */ + case 487: /* stvxl */ + alignmask = 0xFFFFFFF0; + break; + } + break; + case 725: /* stswi */ + tmp = EXTRACT_REGA (instr); + if (tmp > 0) + baseA = regs[tmp]; + break; + default: /* ignore instruction */ + return (void *) 0; + } + break; + default: /* ignore instruction */ + return (void *) 0; + } + + addr = (baseA + baseB) + disp; + addr &= alignmask; + return (void *) addr; +} |