Back to index

plt-scheme  4.2.1
osx_addr.inc
Go to the documentation of this file.
00001 
00002 /* This code comes from the conservative collector, ../gc/os_dep.c */
00003 
00004 /* Decodes the machine instruction which was responsible for the sending of the
00005    SIGBUS signal. Sadly this is the only way to find the faulting address because
00006    the signal handler doesn't get it directly from the kernel (although it is
00007    available on the Mach level, but droppped by the BSD personality before it
00008    calls our signal handler...)
00009    This code should be able to deal correctly with all PPCs starting from the
00010    601 up to and including the G4s (including Velocity Engine). */
00011 #define EXTRACT_OP1(iw)     (((iw) & 0xFC000000) >> 26)
00012 #define EXTRACT_OP2(iw)     (((iw) & 0x000007FE) >> 1)
00013 #define EXTRACT_REGA(iw)    (((iw) & 0x001F0000) >> 16)
00014 #define EXTRACT_REGB(iw)    (((iw) & 0x03E00000) >> 21)
00015 #define EXTRACT_REGC(iw)    (((iw) & 0x0000F800) >> 11)
00016 #define EXTRACT_DISP(iw)    ((short *) &(iw))[1]
00017 
00018 static char *get_fault_addr(unsigned int instr, unsigned int * regs)
00019 {
00020    int            disp = 0, tmp;
00021    unsigned int   baseA = 0, baseB = 0;
00022    unsigned int   addr, alignmask = 0xFFFFFFFF;
00023 
00024    switch(EXTRACT_OP1(instr)) {
00025       case 38:   /* stb */
00026       case 39:   /* stbu */
00027       case 54:   /* stfd */
00028       case 55:   /* stfdu */
00029       case 52:   /* stfs */
00030       case 53:   /* stfsu */
00031       case 44:   /* sth */
00032       case 45:   /* sthu */
00033       case 47:   /* stmw */
00034       case 36:   /* stw */
00035       case 37:   /* stwu */
00036             tmp = EXTRACT_REGA(instr);
00037             if(tmp > 0)
00038                baseA = regs[tmp];
00039             disp = EXTRACT_DISP(instr);
00040             break;
00041       case 31:
00042             switch(EXTRACT_OP2(instr)) {
00043                case 86:    /* dcbf */
00044                case 54:    /* dcbst */
00045                case 1014:  /* dcbz */
00046                case 247:   /* stbux */
00047                case 215:   /* stbx */
00048                case 759:   /* stfdux */
00049                case 727:   /* stfdx */
00050                case 983:   /* stfiwx */
00051                case 695:   /* stfsux */
00052                case 663:   /* stfsx */
00053                case 918:   /* sthbrx */
00054                case 439:   /* sthux */
00055                case 407:   /* sthx */
00056                case 661:   /* stswx */
00057                case 662:   /* stwbrx */
00058                case 150:   /* stwcx. */
00059                case 183:   /* stwux */
00060                case 151:   /* stwx */
00061                case 135:   /* stvebx */
00062                case 167:   /* stvehx */
00063                case 199:   /* stvewx */
00064                case 231:   /* stvx */
00065                case 487:   /* stvxl */
00066                      tmp = EXTRACT_REGA(instr);
00067                      if(tmp > 0)
00068                         baseA = regs[tmp];
00069                         baseB = regs[EXTRACT_REGC(instr)];
00070                         /* determine Altivec alignment mask */
00071                         switch(EXTRACT_OP2(instr)) {
00072                            case 167:   /* stvehx */
00073                                  alignmask = 0xFFFFFFFE;
00074                                  break;
00075                            case 199:   /* stvewx */
00076                                  alignmask = 0xFFFFFFFC;
00077                                  break;
00078                            case 231:   /* stvx */
00079                                  alignmask = 0xFFFFFFF0;
00080                                  break;
00081                            case 487:  /* stvxl */
00082                                  alignmask = 0xFFFFFFF0;
00083                                  break;
00084                         }
00085                         break;
00086                case 725:   /* stswi */
00087                      tmp = EXTRACT_REGA(instr);
00088                      if(tmp > 0)
00089                         baseA = regs[tmp];
00090                         break;
00091                default:   /* ignore instruction */
00092                      return NULL;
00093                     break;
00094             }
00095             break;
00096       default:   /* ignore instruction */
00097             return NULL;
00098             break;
00099    }
00100        
00101    addr = (baseA + baseB) + disp;
00102    addr &= alignmask;
00103    return (char *)addr;
00104 }