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.12 by gbeauche, 2002-05-16T15:48:06Z vs.
Revision 1.13 by gbeauche, 2002-05-19T21:58:42Z

# Line 79 | Line 79 | static bool sigsegv_do_install_handler(i
79   #if (defined(powerpc) || defined(__powerpc__))
80   #include <sys/ucontext.h>
81   #define SIGSEGV_FAULT_INSTRUCTION               (((ucontext_t *)scp)->uc_mcontext.regs->nip)
82 + #define SIGSEGV_REGISTER_FILE                   (unsigned long *)(((ucontext_t *)scp)->uc_mcontext.regs)
83 + #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
84   #endif
85   #endif
86   #endif
# Line 105 | Line 107 | static bool sigsegv_do_install_handler(i
107   #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, struct sigcontext *scp
108   #define SIGSEGV_FAULT_ADDRESS                   scp->regs->dar
109   #define SIGSEGV_FAULT_INSTRUCTION               scp->regs->nip
110 + #define SIGSEGV_REGISTER_FILE                   (unsigned long *)(scp->regs)
111 + #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
112   #endif
113   #if (defined(alpha) || defined(__alpha__))
114   #include <asm/sigcontext.h>
# Line 445 | Line 449 | static bool ix86_skip_instruction(sigseg
449          }
450  
451   #if DEBUG
452 <        printf("%08x: %s %s access", regs[X86_REG_EIP],
452 >        printf("%08x: %s %s access", fault_instruction,
453                     transfer_size == SIZE_BYTE ? "byte" : transfer_size == SIZE_WORD ? "word" : "long",
454                     transfer_type == TYPE_LOAD ? "read" : "write");
455          
# Line 463 | Line 467 | static bool ix86_skip_instruction(sigseg
467          return true;
468   }
469   #endif
470 + // Decode and skip PPC instruction
471 + #if (defined(powerpc) || defined(__powerpc__))
472 + #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)
479 + {
480 +        // Get opcode and divide into fields
481 +        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 +        }
571 +        
572 +        // 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) {
594 +                // Unknown machine code, let it crash. Then patch the decoder
595 +                return false;
596 +        }
597 +
598 + #if DEBUG
599 +        printf("%08x: %s %s access", fault_instruction,
600 +                   transfer_size == SIZE_BYTE ? "byte" : transfer_size == SIZE_HALFWORD ? "word" : "long",
601 +                   transfer_type == TYPE_LOAD ? "read" : "write");
602 +        
603 +        if (addr_mode == MODE_U || addr_mode == MODE_UX)
604 +                printf(" r%d (ra = %08x)\n", ra, addr);
605 +        if (transfer_type == TYPE_LOAD)
606 +                printf(" r%d (rd = 0)\n", rd);
607 + #endif
608 +        
609 +        if (addr_mode == MODE_U || addr_mode == MODE_UX)
610 +                regs[POWERPC_REG_GPR + ra] = addr;
611 +        if (transfer_type == TYPE_LOAD)
612 +                regs[POWERPC_REG_GPR + rd] = 0;
613 +        
614 +        regs[POWERPC_REG_NIP] += 4;
615 +        return true;
616 + }
617 + #endif
618   #endif
619  
620   // Fallbacks

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines