ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/sigsegv.cpp (file contents):
Revision 1.13 by gbeauche, 2002-05-19T21:58:42Z vs.
Revision 1.14 by gbeauche, 2002-05-20T15:56:13Z

# Line 54 | Line 54 | static bool sigsegv_do_install_handler(i
54  
55  
56   /*
57 + *  Instruction decoding aids
58 + */
59 +
60 + // Transfer type
61 + enum transfer_type_t {
62 +        TYPE_UNKNOWN,
63 +        TYPE_LOAD,
64 +        TYPE_STORE
65 + };
66 +
67 + // Transfer size
68 + enum transfer_size_t {
69 +        SIZE_UNKNOWN,
70 +        SIZE_BYTE,
71 +        SIZE_WORD,
72 +        SIZE_LONG
73 + };
74 +
75 + #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
76 + // Addressing mode
77 + enum addressing_mode_t {
78 +        MODE_UNKNOWN,
79 +        MODE_NORM,
80 +        MODE_U,
81 +        MODE_X,
82 +        MODE_UX
83 + };
84 +
85 + // Decoded instruction
86 + struct instruction_t {
87 +        transfer_type_t         transfer_type;
88 +        transfer_size_t         transfer_size;
89 +        addressing_mode_t       addr_mode;
90 +        unsigned int            addr;
91 +        char                            ra, rd;
92 + };
93 +
94 + static void powerpc_decode_instruction(instruction_t *instruction, unsigned int nip, unsigned int * gpr)
95 + {
96 +        // Get opcode and divide into fields
97 +        unsigned int opcode = *((unsigned int *)nip);
98 +        unsigned int primop = opcode >> 26;
99 +        unsigned int exop = (opcode >> 1) & 0x3ff;
100 +        unsigned int ra = (opcode >> 16) & 0x1f;
101 +        unsigned int rb = (opcode >> 11) & 0x1f;
102 +        unsigned int rd = (opcode >> 21) & 0x1f;
103 +        signed int imm = (signed short)(opcode & 0xffff);
104 +        
105 +        // Analyze opcode
106 +        transfer_type_t transfer_type = TYPE_UNKNOWN;
107 +        transfer_size_t transfer_size = SIZE_UNKNOWN;
108 +        addressing_mode_t addr_mode = MODE_UNKNOWN;
109 +        switch (primop) {
110 +        case 31:
111 +                switch (exop) {
112 +                case 23:        // lwzx
113 +                        transfer_type = TYPE_LOAD; transfer_size = SIZE_LONG; addr_mode = MODE_X; break;
114 +                case 55:        // lwzux
115 +                        transfer_type = TYPE_LOAD; transfer_size = SIZE_LONG; addr_mode = MODE_UX; break;
116 +                case 87:        // lbzx
117 +                        transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
118 +                case 119:       // lbzux
119 +                        transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
120 +                case 151:       // stwx
121 +                        transfer_type = TYPE_STORE; transfer_size = SIZE_LONG; addr_mode = MODE_X; break;
122 +                case 183:       // stwux
123 +                        transfer_type = TYPE_STORE; transfer_size = SIZE_LONG; addr_mode = MODE_UX; break;
124 +                case 215:       // stbx
125 +                        transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
126 +                case 247:       // stbux
127 +                        transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
128 +                case 279:       // lhzx
129 +                        transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
130 +                case 311:       // lhzux
131 +                        transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
132 +                case 343:       // lhax
133 +                        transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
134 +                case 375:       // lhaux
135 +                        transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
136 +                case 407:       // sthx
137 +                        transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
138 +                case 439:       // sthux
139 +                        transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
140 +                }
141 +                break;
142 +        
143 +        case 32:        // lwz
144 +                transfer_type = TYPE_LOAD; transfer_size = SIZE_LONG; addr_mode = MODE_NORM; break;
145 +        case 33:        // lwzu
146 +                transfer_type = TYPE_LOAD; transfer_size = SIZE_LONG; addr_mode = MODE_U; break;
147 +        case 34:        // lbz
148 +                transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
149 +        case 35:        // lbzu
150 +                transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
151 +        case 36:        // stw
152 +                transfer_type = TYPE_STORE; transfer_size = SIZE_LONG; addr_mode = MODE_NORM; break;
153 +        case 37:        // stwu
154 +                transfer_type = TYPE_STORE; transfer_size = SIZE_LONG; addr_mode = MODE_U; break;
155 +        case 38:        // stb
156 +                transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
157 +        case 39:        // stbu
158 +                transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
159 +        case 40:        // lhz
160 +                transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
161 +        case 41:        // lhzu
162 +                transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
163 +        case 42:        // lha
164 +                transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
165 +        case 43:        // lhau
166 +                transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
167 +        case 44:        // sth
168 +                transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
169 +        case 45:        // sthu
170 +                transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
171 +        }
172 +        
173 +        // Calculate effective address
174 +        unsigned int addr = 0;
175 +        switch (addr_mode) {
176 +        case MODE_X:
177 +        case MODE_UX:
178 +                if (ra == 0)
179 +                        addr = gpr[rb];
180 +                else
181 +                        addr = gpr[ra] + gpr[rb];
182 +                break;
183 +        case MODE_NORM:
184 +        case MODE_U:
185 +                if (ra == 0)
186 +                        addr = (signed int)(signed short)imm;
187 +                else
188 +                        addr = gpr[ra] + (signed int)(signed short)imm;
189 +                break;
190 +        default:
191 +                break;
192 +        }
193 +        
194 +        // Commit decoded instruction
195 +        instruction->addr = addr;
196 +        instruction->addr_mode = addr_mode;
197 +        instruction->transfer_type = transfer_type;
198 +        instruction->transfer_size = transfer_size;
199 +        instruction->ra = ra;
200 +        instruction->rd = rd;
201 + }
202 + #endif
203 +
204 +
205 + /*
206   *  OS-dependant SIGSEGV signals support section
207   */
208  
# Line 69 | Line 218 | static bool sigsegv_do_install_handler(i
218   #if defined(__linux__)
219   #if (defined(i386) || defined(__i386__))
220   #include <sys/ucontext.h>
221 < #define SIGSEGV_FAULT_INSTRUCTION               (((ucontext_t *)scp)->uc_mcontext.gregs[14]) /* should use REG_EIP instead */
222 < #define SIGSEGV_REGISTER_FILE                   (unsigned long *)(((ucontext_t *)scp)->uc_mcontext.gregs)
221 > #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
222 > #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[14] /* should use REG_EIP instead */
223 > #define SIGSEGV_REGISTER_FILE                   (unsigned int *)SIGSEGV_CONTEXT_REGS
224   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
225   #endif
226   #if (defined(ia64) || defined(__ia64__))
# Line 78 | Line 228 | static bool sigsegv_do_install_handler(i
228   #endif
229   #if (defined(powerpc) || defined(__powerpc__))
230   #include <sys/ucontext.h>
231 < #define SIGSEGV_FAULT_INSTRUCTION               (((ucontext_t *)scp)->uc_mcontext.regs->nip)
232 < #define SIGSEGV_REGISTER_FILE                   (unsigned long *)(((ucontext_t *)scp)->uc_mcontext.regs)
231 > #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.regs)
232 > #define SIGSEGV_FAULT_INSTRUCTION               (SIGSEGV_CONTEXT_REGS->nip)
233 > #define SIGSEGV_REGISTER_FILE                   (unsigned int *)&SIGSEGV_CONTEXT_REGS->nip, (unsigned int *)(SIGSEGV_CONTEXT_REGS->gpr)
234   #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
235   #endif
236   #endif
# Line 107 | Line 258 | static bool sigsegv_do_install_handler(i
258   #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, struct sigcontext *scp
259   #define SIGSEGV_FAULT_ADDRESS                   scp->regs->dar
260   #define SIGSEGV_FAULT_INSTRUCTION               scp->regs->nip
261 < #define SIGSEGV_REGISTER_FILE                   (unsigned long *)(scp->regs)
261 > #define SIGSEGV_REGISTER_FILE                   (unsigned int *)&scp->regs->nip, (unsigned int *)(scp->regs->gpr)
262   #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
263   #endif
264   #if (defined(alpha) || defined(__alpha__))
# Line 162 | Line 313 | static sigsegv_address_t get_fault_addre
313   #if (defined(m68k) || defined(__m68k__))
314   #include <m68k/frame.h>
315   #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, int code, struct sigcontext *scp
316 < #define SIGSEGV_FAULT_ADDRESS                   ({                                                                                                                              \
166 <        struct sigstate {                                                                                                                                                                       \
167 <                int ss_flags;                                                                                                                                                                   \
168 <                struct frame ss_frame;                                                                                                                                                  \
169 <        };                                                                                                                                                                                                      \
170 <        struct sigstate *state = (struct sigstate *)scp->sc_ap;                                                                                         \
171 <        char *fault_addr;                                                                                                                                                                       \
172 <        switch (state->ss_frame.f_format) {                                                                                                                                     \
173 <        case 7:         /* 68040 access error */                                                                                                                                \
174 <                /* "code" is sometimes unreliable (i.e. contains NULL or a bogus address), reason unknown */    \
175 <                fault_addr = state->ss_frame.f_fmt7.f_fa;                                                                                                               \
176 <                break;                                                                                                                                                                                  \
177 <        default:                                                                                                                                                                                        \
178 <                fault_addr = (char *)code;                                                                                                                                              \
179 <                break;                                                                                                                                                                                  \
180 <        }                                                                                                                                                                                                       \
181 <        fault_addr;                                                                                                                                                                                     \
182 < })
316 > #define SIGSEGV_FAULT_ADDRESS                   get_fault_address(scp)
317   #define SIGSEGV_ALL_SIGNALS                             FAULT_HANDLER(SIGSEGV)
318 +
319 + // Use decoding scheme from BasiliskII/m68k native
320 + static sigsegv_address_t get_fault_address(struct sigcontext *scp)
321 + {
322 +        struct sigstate {
323 +                int ss_flags;
324 +                struct frame ss_frame;
325 +        };
326 +        struct sigstate *state = (struct sigstate *)scp->sc_ap;
327 +        char *fault_addr;
328 +        switch (state->ss_frame.f_format) {
329 +        case 7:         /* 68040 access error */
330 +                /* "code" is sometimes unreliable (i.e. contains NULL or a bogus address), reason unknown */
331 +                fault_addr = state->ss_frame.f_fmt7.f_fa;
332 +                break;
333 +        default:
334 +                fault_addr = (char *)code;
335 +                break;
336 +        }
337 +        return (sigsegv_address_t)fault_addr;
338 + }
339   #else
340   #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, int code, void *scp, char *addr
341   #define SIGSEGV_FAULT_ADDRESS                   addr
# Line 195 | Line 350 | static sigsegv_address_t get_fault_addre
350   #define SIGSEGV_FAULT_ADDRESS                   get_fault_address(scp)
351   #define SIGSEGV_FAULT_INSTRUCTION               scp->sc_ir
352   #define SIGSEGV_ALL_SIGNALS                             FAULT_HANDLER(SIGBUS)
353 + #define SIGSEGV_REGISTER_FILE                   (unsigned int *)&scp->sc_ir, &((unsigned int *) scp->sc_regs)[2]
354 + #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
355  
356 < // From Boehm's GC 6.0alpha8
200 < #define EXTRACT_OP1(iw)     (((iw) & 0xFC000000) >> 26)
201 < #define EXTRACT_OP2(iw)     (((iw) & 0x000007FE) >> 1)
202 < #define EXTRACT_REGA(iw)    (((iw) & 0x001F0000) >> 16)
203 < #define EXTRACT_REGB(iw)    (((iw) & 0x03E00000) >> 21)
204 < #define EXTRACT_REGC(iw)    (((iw) & 0x0000F800) >> 11)
205 < #define EXTRACT_DISP(iw)    ((short *) &(iw))[1]
206 <
356 > // Use decoding scheme from SheepShaver
357   static sigsegv_address_t get_fault_address(struct sigcontext *scp)
358   {
359 <        unsigned int   instr = *((unsigned int *) scp->sc_ir);
360 <        unsigned int * regs = &((unsigned int *) scp->sc_regs)[2];
361 <        int            disp = 0, tmp;
362 <        unsigned int   baseA = 0, baseB = 0;
363 <        unsigned int   addr, alignmask = 0xFFFFFFFF;
364 <
215 <        switch(EXTRACT_OP1(instr)) {
216 <        case 38:   /* stb */
217 <        case 39:   /* stbu */
218 <        case 54:   /* stfd */
219 <        case 55:   /* stfdu */
220 <        case 52:   /* stfs */
221 <        case 53:   /* stfsu */
222 <        case 44:   /* sth */
223 <        case 45:   /* sthu */
224 <        case 47:   /* stmw */
225 <        case 36:   /* stw */
226 <        case 37:   /* stwu */
227 <                tmp = EXTRACT_REGA(instr);
228 <                if(tmp > 0)
229 <                        baseA = regs[tmp];
230 <                disp = EXTRACT_DISP(instr);
231 <                break;
232 <        case 31:
233 <                switch(EXTRACT_OP2(instr)) {
234 <                case 86:    /* dcbf */
235 <                case 54:    /* dcbst */
236 <                case 1014:  /* dcbz */
237 <                case 247:   /* stbux */
238 <                case 215:   /* stbx */
239 <                case 759:   /* stfdux */
240 <                case 727:   /* stfdx */
241 <                case 983:   /* stfiwx */
242 <                case 695:   /* stfsux */
243 <                case 663:   /* stfsx */
244 <                case 918:   /* sthbrx */
245 <                case 439:   /* sthux */
246 <                case 407:   /* sthx */
247 <                case 661:   /* stswx */
248 <                case 662:   /* stwbrx */
249 <                case 150:   /* stwcx. */
250 <                case 183:   /* stwux */
251 <                case 151:   /* stwx */
252 <                case 135:   /* stvebx */
253 <                case 167:   /* stvehx */
254 <                case 199:   /* stvewx */
255 <                case 231:   /* stvx */
256 <                case 487:   /* stvxl */
257 <                        tmp = EXTRACT_REGA(instr);
258 <                        if(tmp > 0)
259 <                                baseA = regs[tmp];
260 <                        baseB = regs[EXTRACT_REGC(instr)];
261 <                        /* determine Altivec alignment mask */
262 <                        switch(EXTRACT_OP2(instr)) {
263 <                        case 167:   /* stvehx */
264 <                                alignmask = 0xFFFFFFFE;
265 <                                break;
266 <                        case 199:   /* stvewx */
267 <                                alignmask = 0xFFFFFFFC;
268 <                                break;
269 <                        case 231:   /* stvx */
270 <                                alignmask = 0xFFFFFFF0;
271 <                                break;
272 <                        case 487:  /* stvxl */
273 <                                alignmask = 0xFFFFFFF0;
274 <                                break;
275 <                        }
276 <                        break;
277 <                case 725:   /* stswi */
278 <                        tmp = EXTRACT_REGA(instr);
279 <                        if(tmp > 0)
280 <                                baseA = regs[tmp];
281 <                        break;
282 <                default:   /* ignore instruction */
283 <                        return 0;
284 <                        break;
285 <                }
286 <                break;
287 <        default:   /* ignore instruction */
288 <                return 0;
289 <                break;
290 <        }
291 <        
292 <        addr = (baseA + baseB) + disp;
293 <        addr &= alignmask;
294 <        return (sigsegv_address_t)addr;
359 >        unsigned int   nip = (unsigned int) scp->sc_ir;
360 >        unsigned int * gpr = &((unsigned int *) scp->sc_regs)[2];
361 >        instruction_t  instr;
362 >
363 >        powerpc_decode_instruction(&instr, nip, gpr);
364 >        return (sigsegv_address_t)instr.addr;
365   }
366   #endif
367   #endif
368   #endif
369  
370 +
371 + /*
372 + *  Instruction skipping
373 + */
374 +
375   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
376   // Decode and skip X86 instruction
377   #if (defined(i386) || defined(__i386__))
# Line 347 | Line 422 | static inline int ix86_step_over_modrm(u
422          return offset;
423   }
424  
425 < static bool ix86_skip_instruction(sigsegv_address_t fault_instruction, unsigned long * regs)
425 > static bool ix86_skip_instruction(unsigned int * regs)
426   {
427 <        unsigned char * eip = (unsigned char *)fault_instruction;
427 >        unsigned char * eip = (unsigned char *)regs[X86_REG_EIP];
428  
429          if (eip == 0)
430                  return false;
431          
432 <        // Transfer type
433 <        enum {
359 <                TYPE_UNKNOWN,
360 <                TYPE_LOAD,
361 <                TYPE_STORE
362 <        } transfer_type = TYPE_UNKNOWN;
363 <        
364 <        // Transfer size
365 <        enum {
366 <                SIZE_BYTE,
367 <                SIZE_WORD,
368 <                SIZE_LONG
369 <        } transfer_size = SIZE_LONG;
432 >        transfer_type_t transfer_type = TYPE_UNKNOWN;
433 >        transfer_size_t transfer_size = SIZE_LONG;
434          
435          int reg = -1;
436          int len = 0;
# Line 467 | Line 531 | static bool ix86_skip_instruction(sigseg
531          return true;
532   }
533   #endif
534 +
535   // Decode and skip PPC instruction
536 < #if (defined(powerpc) || defined(__powerpc__))
537 < #if defined(__linux__)
473 < enum {
474 <        POWERPC_REG_GPR = 0,
475 <        POWERPC_REG_NIP = 32
476 < };
477 < #endif
478 < static bool powerpc_skip_instruction(sigsegv_address_t fault_instruction, unsigned long * regs)
536 > #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
537 > static bool powerpc_skip_instruction(unsigned int * nip_p, unsigned int * regs)
538   {
539 <        // Get opcode and divide into fields
540 <        unsigned int opcode = *((unsigned int *)fault_instruction);
482 <        unsigned int primop = opcode >> 26;
483 <        unsigned int exop = (opcode >> 1) & 0x3ff;
484 <        unsigned int ra = (opcode >> 16) & 0x1f;
485 <        unsigned int rb = (opcode >> 11) & 0x1f;
486 <        unsigned int rd = (opcode >> 21) & 0x1f;
487 <        signed int imm = (signed short)(opcode & 0xffff);
488 <        
489 <        // Analyze opcode
490 <        enum {
491 <                TYPE_UNKNOWN,
492 <                TYPE_LOAD,
493 <                TYPE_STORE
494 <        } transfer_type = TYPE_UNKNOWN;
495 <        enum {
496 <                SIZE_UNKNOWN,
497 <                SIZE_BYTE,
498 <                SIZE_HALFWORD,
499 <                SIZE_WORD
500 <        } transfer_size = SIZE_UNKNOWN;
501 <        enum {
502 <                MODE_UNKNOWN,
503 <                MODE_NORM,
504 <                MODE_U,
505 <                MODE_X,
506 <                MODE_UX
507 <        } addr_mode = MODE_UNKNOWN;
508 <        switch (primop) {
509 <        case 31:
510 <                switch (exop) {
511 <                case 23:        // lwzx
512 <                        transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
513 <                case 55:        // lwzux
514 <                        transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
515 <                case 87:        // lbzx
516 <                        transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
517 <                case 119:       // lbzux
518 <                        transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
519 <                case 151:       // stwx
520 <                        transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
521 <                case 183:       // stwux
522 <                        transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
523 <                case 215:       // stbx
524 <                        transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
525 <                case 247:       // stbux
526 <                        transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
527 <                case 279:       // lhzx
528 <                        transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
529 <                case 311:       // lhzux
530 <                        transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
531 <                case 343:       // lhax
532 <                        transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
533 <                case 375:       // lhaux
534 <                        transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
535 <                case 407:       // sthx
536 <                        transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
537 <                case 439:       // sthux
538 <                        transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
539 <                }
540 <                break;
541 <        
542 <        case 32:        // lwz
543 <                transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
544 <        case 33:        // lwzu
545 <                transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
546 <        case 34:        // lbz
547 <                transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
548 <        case 35:        // lbzu
549 <                transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
550 <        case 36:        // stw
551 <                transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
552 <        case 37:        // stwu
553 <                transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
554 <        case 38:        // stb
555 <                transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
556 <        case 39:        // stbu
557 <                transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
558 <        case 40:        // lhz
559 <                transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
560 <        case 41:        // lhzu
561 <                transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
562 <        case 42:        // lha
563 <                transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
564 <        case 43:        // lhau
565 <                transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
566 <        case 44:        // sth
567 <                transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
568 <        case 45:        // sthu
569 <                transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
570 <        }
539 >        instruction_t instr;
540 >        powerpc_decode_instruction(&instr, *nip_p, regs);
541          
542 <        // Calculate effective address
573 <        unsigned int addr = 0;
574 <        switch (addr_mode) {
575 <        case MODE_X:
576 <        case MODE_UX:
577 <                if (ra == 0)
578 <                        addr = regs[POWERPC_REG_GPR + rb];
579 <                else
580 <                        addr = regs[POWERPC_REG_GPR + ra] + regs[POWERPC_REG_GPR + rb];
581 <                break;
582 <        case MODE_NORM:
583 <        case MODE_U:
584 <                if (ra == 0)
585 <                        addr = (signed int)(signed short)imm;
586 <                else
587 <                        addr = regs[POWERPC_REG_GPR + ra] + (signed int)(signed short)imm;
588 <                break;
589 <        default:
590 <                break;
591 <        }
592 <        
593 <        if (transfer_type == TYPE_UNKNOWN) {
542 >        if (instr.transfer_type == TYPE_UNKNOWN) {
543                  // Unknown machine code, let it crash. Then patch the decoder
544                  return false;
545          }
546  
547   #if DEBUG
548 <        printf("%08x: %s %s access", fault_instruction,
549 <                   transfer_size == SIZE_BYTE ? "byte" : transfer_size == SIZE_HALFWORD ? "word" : "long",
550 <                   transfer_type == TYPE_LOAD ? "read" : "write");
551 <        
552 <        if (addr_mode == MODE_U || addr_mode == MODE_UX)
553 <                printf(" r%d (ra = %08x)\n", ra, addr);
554 <        if (transfer_type == TYPE_LOAD)
555 <                printf(" r%d (rd = 0)\n", rd);
556 < #endif
557 <        
558 <        if (addr_mode == MODE_U || addr_mode == MODE_UX)
559 <                regs[POWERPC_REG_GPR + ra] = addr;
560 <        if (transfer_type == TYPE_LOAD)
561 <                regs[POWERPC_REG_GPR + rd] = 0;
548 >        printf("%08x: %s %s access", *nip_p,
549 >                   instr.transfer_size == SIZE_BYTE ? "byte" : instr.transfer_size == SIZE_WORD ? "word" : "long",
550 >                   instr.transfer_type == TYPE_LOAD ? "read" : "write");
551 >        
552 >        if (instr.addr_mode == MODE_U || instr.addr_mode == MODE_UX)
553 >                printf(" r%d (ra = %08x)\n", instr.ra, instr.addr);
554 >        if (instr.transfer_type == TYPE_LOAD)
555 >                printf(" r%d (rd = 0)\n", instr.rd);
556 > #endif
557 >        
558 >        if (instr.addr_mode == MODE_U || instr.addr_mode == MODE_UX)
559 >                regs[instr.ra] = instr.addr;
560 >        if (instr.transfer_type == TYPE_LOAD)
561 >                regs[instr.rd] = 0;
562          
563 <        regs[POWERPC_REG_NIP] += 4;
563 >        *nip_p += 4;
564          return true;
565   }
566   #endif
# Line 649 | Line 598 | static void sigsegv_handler(SIGSEGV_FAUL
598   #if HAVE_SIGSEGV_SKIP_INSTRUCTION
599          else if (sigsegv_ignore_fault) {
600                  // Call the instruction skipper with the register file available
601 <                if (SIGSEGV_SKIP_INSTRUCTION(fault_instruction, SIGSEGV_REGISTER_FILE))
601 >                if (SIGSEGV_SKIP_INSTRUCTION(SIGSEGV_REGISTER_FILE))
602                          fault_recovered = true;
603          }
604   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines