Improve NetBSD support: Allow VMA determination with fewer system calls.
[libsigsegv/ericb.git] / src / fault-macosdarwin7-powerpc.c
blob6769441e5ceca0f1527d8550c6deb331d773884a
1 /* Fault handler information subroutine. MacOSX/Darwin7/PowerPC version.
2 * Taken from gcc-3.2/boehm-gc/os_dep.c.
4 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
5 * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
6 * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
7 * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
9 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
10 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
12 * Permission is hereby granted to use or copy this program
13 * for any purpose, provided the above notices are retained on all copies.
14 * Permission to modify the code and to distribute modified code is granted,
15 * provided the above notices are retained, and a notice that the code was
16 * modified is included with the above copyright notice.
19 #include <ucontext.h>
21 /* Decodes the machine instruction which was responsible for the sending of the
22 SIGBUS signal. Sadly this is the only way to find the faulting address
23 because the signal handler doesn't get it directly from the kernel (although
24 it is available on the Mach level, but dropped by the BSD personality before
25 it calls our signal handler...)
26 This code should be able to deal correctly with all PPCs starting from the
27 601 up to and including the G4s (including Velocity Engine). */
28 #define EXTRACT_OP1(iw) (((iw) & 0xFC000000) >> 26)
29 #define EXTRACT_OP2(iw) (((iw) & 0x000007FE) >> 1)
30 #define EXTRACT_REGA(iw) (((iw) & 0x001F0000) >> 16)
31 #define EXTRACT_REGB(iw) (((iw) & 0x03E00000) >> 21)
32 #define EXTRACT_REGC(iw) (((iw) & 0x0000F800) >> 11)
33 #define EXTRACT_DISP(iw) ((short *) &(iw))[1]
35 static void *
36 get_fault_addr (siginfo_t *sip, ucontext_t *ucp)
38 unsigned int instr = *(unsigned int *) sip->si_addr;
39 unsigned int *regs =
40 #if __DARWIN_UNIX03
41 &ucp->uc_mcontext->ss.__r0; /* r0..r31 */
42 #else
43 &ucp->uc_mcontext->ss.r0; /* r0..r31 */
44 #endif
45 int disp = 0;
46 int tmp;
47 unsigned int baseA = 0;
48 unsigned int baseB = 0;
49 unsigned int addr;
50 unsigned int alignmask = 0xFFFFFFFF;
52 switch (EXTRACT_OP1 (instr))
54 case 38: /* stb */
55 case 39: /* stbu */
56 case 54: /* stfd */
57 case 55: /* stfdu */
58 case 52: /* stfs */
59 case 53: /* stfsu */
60 case 44: /* sth */
61 case 45: /* sthu */
62 case 47: /* stmw */
63 case 36: /* stw */
64 case 37: /* stwu */
65 tmp = EXTRACT_REGA (instr);
66 if (tmp > 0)
67 baseA = regs[tmp];
68 disp = EXTRACT_DISP (instr);
69 break;
70 case 31:
71 switch (EXTRACT_OP2 (instr))
73 case 86: /* dcbf */
74 case 54: /* dcbst */
75 case 1014: /* dcbz */
76 case 247: /* stbux */
77 case 215: /* stbx */
78 case 759: /* stfdux */
79 case 727: /* stfdx */
80 case 983: /* stfiwx */
81 case 695: /* stfsux */
82 case 663: /* stfsx */
83 case 918: /* sthbrx */
84 case 439: /* sthux */
85 case 407: /* sthx */
86 case 661: /* stswx */
87 case 662: /* stwbrx */
88 case 150: /* stwcx. */
89 case 183: /* stwux */
90 case 151: /* stwx */
91 case 135: /* stvebx */
92 case 167: /* stvehx */
93 case 199: /* stvewx */
94 case 231: /* stvx */
95 case 487: /* stvxl */
96 tmp = EXTRACT_REGA (instr);
97 if (tmp > 0)
98 baseA = regs[tmp];
99 baseB = regs[EXTRACT_REGC (instr)];
100 /* Determine Altivec alignment mask. */
101 switch (EXTRACT_OP2 (instr))
103 case 167: /* stvehx */
104 alignmask = 0xFFFFFFFE;
105 break;
106 case 199: /* stvewx */
107 alignmask = 0xFFFFFFFC;
108 break;
109 case 231: /* stvx */
110 case 487: /* stvxl */
111 alignmask = 0xFFFFFFF0;
112 break;
114 break;
115 case 725: /* stswi */
116 tmp = EXTRACT_REGA (instr);
117 if (tmp > 0)
118 baseA = regs[tmp];
119 break;
120 default: /* ignore instruction */
121 return (void *) 0;
123 break;
124 default: /* ignore instruction */
125 return (void *) 0;
128 addr = (baseA + baseB) + disp;
129 addr &= alignmask;
130 return (void *) addr;