Annotation of lucent/sys/src/libmach/8db.c, revision 1.1.1.1

1.1       root        1: #include <u.h>
                      2: #include <libc.h>
                      3: #include <bio.h>
                      4: #include <mach.h>
                      5: 
                      6: /*
                      7:  * i386-specific debugger interface
                      8:  */
                      9: 
                     10: static char    *i386excep(Map*, Rgetter);
                     11: 
                     12: static int     i386trace(Map*, ulong, ulong, ulong, Tracer);
                     13: static ulong   i386frame(Map*, ulong, ulong, ulong, ulong);
                     14: static int     i386foll(Map*, ulong, Rgetter, ulong*);
                     15: static int     i386inst(Map*, ulong, char, char*, int);
                     16: static int     i386das(Map*, ulong, char*, int);
                     17: static int     i386instlen(Map*, ulong);
                     18: 
                     19: static char    STARTSYM[] =    "_main";
                     20: static char    PROFSYM[] =     "_mainp";
                     21: static char    FRAMENAME[] =   ".frame";
                     22: static char *excname[] =
                     23: {
                     24: [0]    "divide error",
                     25: [1]    "debug exception",
                     26: [4]    "overflow",
                     27: [5]    "bounds check",
                     28: [6]    "invalid opcode",
                     29: [7]    "math coprocessor emulation",
                     30: [8]    "double fault",
                     31: [9]    "math coprocessor overrun",
                     32: [10]   "invalid TSS",
                     33: [11]   "segment not present",
                     34: [12]   "stack exception",
                     35: [13]   "general protection violation",
                     36: [14]   "page fault",
                     37: [16]   "math coprocessor error",
                     38: [24]   "clock",
                     39: [25]   "keyboard",
                     40: [27]   "modem status",
                     41: [28]   "serial line status",
                     42: [30]   "floppy disk",
                     43: [36]   "mouse",
                     44: [37]   "math coprocessor",
                     45: [38]   "hard disk",
                     46: [64]   "system call",
                     47: };
                     48: 
                     49: Machdata i386mach =
                     50: {
                     51:        {0xCC, 0, 0, 0},        /* break point: INT 3 */
                     52:        1,                      /* break point size */
                     53: 
                     54:        leswab,                 /* convert short to local byte order */
                     55:        leswal,                 /* convert long to local byte order */
                     56:        i386trace,              /* C traceback */
                     57:        i386frame,              /* frame finder */
                     58:        0,                      /* ublock fixup */
                     59:        i386excep,              /* print exception */
                     60:        0,                      /* breakpoint fixup */
                     61:        leieeesftos,            /* single precision float printer */
                     62:        leieeedftos,            /* double precision float printer */
                     63:        i386foll,               /* following addresses */
                     64:        i386inst,               /* print instruction */
                     65:        i386das,                /* dissembler */
                     66:        i386instlen,            /* instruction size calculation */
                     67: };
                     68: 
                     69: static char*
                     70: i386excep(Map *map, Rgetter rget)
                     71: {
                     72:        ulong c;
                     73:        ulong pc;
                     74:        static char buf[16];
                     75: 
                     76:        c = (*rget)(map, "TRAP");
                     77:        if(c > 64 || excname[c] == 0) {
                     78:                if (c == 3) {
                     79:                        pc = (*rget)(map, "PC");
                     80:                        if (get1(map, pc, (uchar*)buf, machdata->bpsize) > 0)
                     81:                        if (memcmp(buf, machdata->bpinst, machdata->bpsize) == 0)
                     82:                                return "breakpoint";
                     83:                }
                     84:                sprint(buf, "exception %d", c);
                     85:                return buf;
                     86:        } else
                     87:                return excname[c];
                     88: }
                     89: 
                     90: static int
                     91: i386trace(Map *map, ulong pc, ulong sp, ulong link, Tracer trace)
                     92: {
                     93:        int i;
                     94:        Symbol s, f;
                     95:        ulong osp;
                     96: 
                     97:        USED(link);
                     98:        i = 0;
                     99:        osp = 0;
                    100:        while(findsym(pc, CTEXT, &s)) {
                    101:                if(osp == sp)
                    102:                        break;
                    103:                osp = sp;
                    104:                if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
                    105:                        break;
                    106: 
                    107:                if(pc != s.value) {     /* not at first instruction */
                    108:                        if(findlocal(&s, FRAMENAME, &f) == 0)
                    109:                                break;
                    110:                        sp += f.value-mach->szaddr;
                    111:                }
                    112: 
                    113:                if (get4(map, sp, (long *) &pc) < 0)
                    114:                        break;
                    115: 
                    116:                if(pc == 0)
                    117:                        break;
                    118: 
                    119:                (*trace)(map, pc, sp, &s);
                    120:                sp += mach->szaddr;
                    121: 
                    122:                if(++i > 40)
                    123:                        break;
                    124:        }
                    125:        return i;
                    126: }
                    127: 
                    128: static ulong
                    129: i386frame(Map *map, ulong addr, ulong pc, ulong sp, ulong link)
                    130: {
                    131:        Symbol s, f;
                    132: 
                    133:        USED(link);
                    134:        while (findsym(pc, CTEXT, &s)) {
                    135:                if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
                    136:                        break;
                    137: 
                    138:                if(pc != s.value) {     /* not first instruction */
                    139:                        if(findlocal(&s, FRAMENAME, &f) == 0)
                    140:                                break;
                    141:                        sp += f.value-mach->szaddr;
                    142:                }
                    143: 
                    144:                if (s.value == addr)
                    145:                        return sp;
                    146: 
                    147:                if (get4(map, sp, (long *)&pc) < 0)
                    148:                        break;
                    149:                sp += mach->szaddr;
                    150:        }
                    151:        return 0;
                    152: }
                    153: 
                    154:        /* I386/486 - Disassembler and related functions */
                    155: 
                    156: /*
                    157:  *  an instruction
                    158:  */
                    159: typedef struct Instr Instr;
                    160: struct Instr
                    161: {
                    162:        uchar   mem[1+1+1+1+2+1+1+4+4];         /* raw instruction */
                    163:        ulong   addr;           /* address of start of instruction */
                    164:        int     n;              /* number of bytes in instruction */
                    165:        char    *prefix;        /* instr prefix */
                    166:        char    *segment;       /* segment override */
                    167:        uchar   jumptype;       /* set to the operand type for jump/ret/call */
                    168:        char    osize;          /* 'W' or 'L' */
                    169:        char    asize;          /* address size 'W' or 'L' */
                    170:        uchar   mod;            /* bits 6-7 of mod r/m field */
                    171:        uchar   reg;            /* bits 3-5 of mod r/m field */
                    172:        char    ss;             /* bits 6-7 of SIB */
                    173:        char    index;          /* bits 3-5 of SIB */
                    174:        char    base;           /* bits 0-2 of SIB */
                    175:        short   seg;            /* segment of far address */
                    176:        ulong   disp;           /* displacement */
                    177:        ulong   imm;            /* immediate */
                    178:        ulong   imm2;           /* second immediate operand */
                    179:        char    *curr;          /* fill level in output buffer */
                    180:        char    *end;           /* end of output buffer */
                    181:        char    *err;           /* error message */
                    182: };
                    183: 
                    184:        /* 386 register (ha!) set */
                    185: enum{
                    186:        AX=0,
                    187:        CX,
                    188:        DX,
                    189:        BX,
                    190:        SP,
                    191:        BP,
                    192:        SI,
                    193:        DI,
                    194: };
                    195:        /* Operand Format codes */
                    196: /*
                    197: %A     -       address size register modifier (!asize -> 'E')
                    198: %C     -       Control register CR0/CR1/CR2
                    199: %D     -       Debug register DR0/DR1/DR2/DR3/DR6/DR7
                    200: %I     -       second immediate operand
                    201: %O     -       Operand size register modifier (!osize -> 'E')
                    202: %T     -       Test register TR6/TR7
                    203: %S     -       size code ('W' or 'L')
                    204: %X     -       Weird opcode: OSIZE == 'W' => "CBW"; else => "CWDE"
                    205: %d     -       displacement 16-32 bits
                    206: %e     -       effective address - Mod R/M value
                    207: %f     -       floating point register F0-F7 - from Mod R/M register
                    208: %g     -       segment register
                    209: %i     -       immediate operand 8-32 bits
                    210: %p     -       PC-relative - signed displacement in immediate field
                    211: %r     -       Reg from Mod R/M
                    212: %x     -       Weird opcode: OSIZE == 'W' => "CWD"; else => "CDQ"
                    213: */
                    214: 
                    215: typedef struct Optable Optable;
                    216: struct Optable
                    217: {
                    218:        char    operand[2];
                    219:        void    *proto;         /* actually either (char*) or (Optable*) */
                    220: };
                    221:        /* Operand decoding codes */
                    222: enum {
                    223:        Ib = 1,                 /* 8-bit immediate - (no sign extension)*/
                    224:        Ibs,                    /* 8-bit immediate (sign extended) */
                    225:        Jbs,                    /* 8-bit sign-extended immediate in jump or call */
                    226:        Iw,                     /* 16-bit immediate -> imm */
                    227:        Iw2,                    /* 16-bit immediate -> imm2 */
                    228:        Iwd,                    /* Operand-sized immediate (no sign extension)*/
                    229:        Awd,                    /* Address offset */
                    230:        Iwds,                   /* Operand-sized immediate (sign extended) */
                    231:        RM,                     /* Word or long R/M field with register (/r) */
                    232:        RMB,                    /* Byte R/M field with register (/r) */
                    233:        RMOP,                   /* Word or long R/M field with op code (/digit) */
                    234:        RMOPB,                  /* Byte R/M field with op code (/digit) */
                    235:        RMR,                    /* R/M register only (mod = 11) */
                    236:        RMM,                    /* R/M memory only (mod = 0/1/2) */
                    237:        R0,                     /* Base reg of Mod R/M is literal 0x00 */
                    238:        R1,                     /* Base reg of Mod R/M is literal 0x01 */
                    239:        FRMOP,                  /* Floating point R/M field with opcode */
                    240:        FRMEX,                  /* Extended floating point R/M field with opcode */
                    241:        JUMP,                   /* Jump or Call flag - no operand */
                    242:        RET,                    /* Return flag - no operand */
                    243:        OA,                     /* literal 0x0a byte */
                    244:        PTR,                    /* Seg:Displacement addr (ptr16:16 or ptr16:32) */
                    245:        AUX,                    /* Multi-byte op code - Auxiliary table */
                    246:        PRE,                    /* Instr Prefix */
                    247:        SEG,                    /* Segment Prefix */
                    248:        OPOVER,                 /* Operand size override */
                    249:        ADDOVER,                /* Address size override */
                    250: };
                    251:        
                    252: static Optable optab0F00[8]=
                    253: {
                    254: [0x00] 0,0,            "MOVW   LDT,%e",
                    255: [0x01] 0,0,            "MOVW   TR,%e",
                    256: [0x02] 0,0,            "MOVW   %e,LDT",
                    257: [0x03] 0,0,            "MOVW   %e,TR",
                    258: [0x04] 0,0,            "VERR   %e",
                    259: [0x05] 0,0,            "VERW   %e",
                    260: };
                    261: 
                    262: static Optable optab0F01[8]=
                    263: {
                    264: [0x00] 0,0,            "MOVL   GDTR,%e",
                    265: [0x01] 0,0,            "MOVL   IDTR,%e",
                    266: [0x02] 0,0,            "MOVL   %e,GDTR",
                    267: [0x03] 0,0,            "MOVL   %e,IDTR",
                    268: [0x04] 0,0,            "MOVW   MSW,%e",        /* word */
                    269: [0x06] 0,0,            "MOVW   %e,MSW",        /* word */
                    270: };
                    271: 
                    272: static Optable optab0FBA[8]=
                    273: {
                    274: [0x04] Ib,0,           "BT%S   %i,%e",
                    275: [0x05] Ib,0,           "BTS%S  %i,%e",
                    276: [0x06] Ib,0,           "BTR%S  %i,%e",
                    277: [0x07] Ib,0,           "BTC%S  %i,%e",
                    278: };
                    279: 
                    280: static Optable optab0F[256]=
                    281: {
                    282: [0x00] RMOP,0,         optab0F00,
                    283: [0x01] RMOP,0,         optab0F01,
                    284: [0x02] RM,0,           "LAR    %e,%r",
                    285: [0x03] RM,0,           "LSL    %e,%r",
                    286: [0x06] 0,0,            "CLTS",
                    287: [0x08] 0,0,            "INVD",
                    288: [0x09] 0,0,            "WBINVD",
                    289: [0x20] RMR,0,          "MOVL   %C,%e",
                    290: [0x21] RMR,0,          "MOVL   %D,%e",
                    291: [0x22] RMR,0,          "MOVL   %e,%C",
                    292: [0x23] RMR,0,          "MOVL   %e,%D",
                    293: [0x24] RMR,0,          "MOVL   %T,%e",
                    294: [0x26] RMR,0,          "MOVL   %e,%T",
                    295: [0x30] 0,0,            "WRMSR",
                    296: [0x31] 0,0,            "RDTSC",
                    297: [0x32] 0,0,            "RDMSR",
                    298: [0x80] Iwds,0,         "JOS    %p",
                    299: [0x81] Iwds,0,         "JOC    %p",
                    300: [0x82] Iwds,0,         "JCS    %p",
                    301: [0x83] Iwds,0,         "JCC    %p",
                    302: [0x84] Iwds,0,         "JEQ    %p",
                    303: [0x85] Iwds,0,         "JNE    %p",
                    304: [0x86] Iwds,0,         "JLS    %p",
                    305: [0x87] Iwds,0,         "JHI    %p",
                    306: [0x88] Iwds,0,         "JMI    %p",
                    307: [0x89] Iwds,0,         "JPL    %p",
                    308: [0x8a] Iwds,0,         "JPS    %p",
                    309: [0x8b] Iwds,0,         "JPC    %p",
                    310: [0x8c] Iwds,0,         "JLT    %p",
                    311: [0x8d] Iwds,0,         "JGE    %p",
                    312: [0x8e] Iwds,0,         "JLE    %p",
                    313: [0x8f] Iwds,0,         "JGT    %p",
                    314: [0x90] RMB,0,          "SETOS  %e",
                    315: [0x91] RMB,0,          "SETOC  %e",
                    316: [0x92] RMB,0,          "SETCS  %e",
                    317: [0x93] RMB,0,          "SETCC  %e",
                    318: [0x94] RMB,0,          "SETEQ  %e",
                    319: [0x95] RMB,0,          "SETNE  %e",
                    320: [0x96] RMB,0,          "SETLS  %e",
                    321: [0x97] RMB,0,          "SETHI  %e",
                    322: [0x98] RMB,0,          "SETMI  %e",
                    323: [0x99] RMB,0,          "SETPL  %e",
                    324: [0x9a] RMB,0,          "SETPS  %e",
                    325: [0x9b] RMB,0,          "SETPC  %e",
                    326: [0x9c] RMB,0,          "SETLT  %e",
                    327: [0x9d] RMB,0,          "SETGE  %e",
                    328: [0x9e] RMB,0,          "SETLE  %e",
                    329: [0x9f] RMB,0,          "SETGT  %e",
                    330: [0xa0] 0,0,            "PUSHL  FS",
                    331: [0xa1] 0,0,            "POPL   FS",
                    332: [0xa2] 0,0,            "CPUID",
                    333: [0xa3] RM,0,           "BT%S   %r,%e",
                    334: [0xa4] RM,Ib,          "SHLD%S %r,%i,%e",
                    335: [0xa5] RM,0,           "SHLD%S %r,CL,%e",
                    336: [0xa8] 0,0,            "PUSHL  GS",
                    337: [0xa9] 0,0,            "POPL   GS",
                    338: [0xab] RM,0,           "BTS%S  %r,%e",
                    339: [0xac] RM,Ib,          "SHRD%S %r,%i,%e",
                    340: [0xad] RM,0,           "SHRD%S %r,CL,%e",
                    341: [0xaf] RM,0,           "IMUL%S %e,%r",
                    342: [0xb2] RMM,0,          "LSS    %e,%r",
                    343: [0xb3] RM,0,           "BTR%S  %r,%e",
                    344: [0xb4] RMM,0,          "LFS    %e,%r",
                    345: [0xb5] RMM,0,          "LGS    %e,%r",
                    346: [0xb6] RMB,0,          "MOVBZX %e,%R",
                    347: [0xb7] RM,0,           "MOVWZX %e,%R",
                    348: [0xba] RMOP,0,         optab0FBA,
                    349: [0xbb] RM,0,           "BTC%S  %e,%r",
                    350: [0xbc] RM,0,           "BSF%S  %e,%r",
                    351: [0xbd] RM,0,           "BSR%S  %e,%r",
                    352: [0xbe] RMB,0,          "MOVBSX %e,%R",
                    353: [0xbf] RM,0,           "MOVWSX %e,%R",
                    354: };
                    355: 
                    356: static Optable optab80[8]=
                    357: {
                    358: [0x00] Ib,0,           "ADDB   %i,%e",
                    359: [0x01] Ib,0,           "ORB    %i,%e",
                    360: [0x02] Ib,0,           "ADCB   %i,%e",
                    361: [0x03] Ib,0,           "SBBB   %i,%e",
                    362: [0x04] Ib,0,           "ANDB   %i,%e",
                    363: [0x05] Ib,0,           "SUBB   %i,%e",
                    364: [0x06] Ib,0,           "XORB   %i,%e",
                    365: [0x07] Ib,0,           "CMPB   %e,%i",
                    366: };
                    367: 
                    368: static Optable optab81[8]=
                    369: {
                    370: [0x00] Iwd,0,          "ADD%S  %i,%e",
                    371: [0x01] Iwd,0,          "OR%S   %i,%e",
                    372: [0x02] Iwd,0,          "ADC%S  %i,%e",
                    373: [0x03] Iwd,0,          "SBB%S  %i,%e",
                    374: [0x04] Iwd,0,          "AND%S  %i,%e",
                    375: [0x05] Iwd,0,          "SUB%S  %i,%e",
                    376: [0x06] Iwd,0,          "XOR%S  %i,%e",
                    377: [0x07] Iwd,0,          "CMP%S  %e,%i",
                    378: };
                    379: 
                    380: static Optable optab83[8]=
                    381: {
                    382: [0x00] Ibs,0,          "ADD%S  %i,%e",
                    383: [0x01] Ibs,0,          "OR%S   %i,%e",
                    384: [0x02] Ibs,0,          "ADC%S  %i,%e",
                    385: [0x03] Ibs,0,          "SBB%S  %i,%e",
                    386: [0x04] Ibs,0,          "AND%S  %i,%e",
                    387: [0x05] Ibs,0,          "SUB%S  %i,%e",
                    388: [0x06] Ibs,0,          "XOR%S  %i,%e",
                    389: [0x07] Ibs,0,          "CMP%S  %e,%i",
                    390: };
                    391: 
                    392: static Optable optabC0[8] =
                    393: {
                    394: [0x00] Ib,0,           "ROLB   %i,%e",
                    395: [0x01] Ib,0,           "RORB   %i,%e",
                    396: [0x02] Ib,0,           "RCLB   %i,%e",
                    397: [0x03] Ib,0,           "RCRB   %i,%e",
                    398: [0x04] Ib,0,           "SHLB   %i,%e",
                    399: [0x05] Ib,0,           "SHRB   %i,%e",
                    400: [0x07] Ib,0,           "SARB   %i,%e",
                    401: };
                    402: 
                    403: static Optable optabC1[8] =
                    404: {
                    405: [0x00] Ib,0,           "ROL%S  %i,%e",
                    406: [0x01] Ib,0,           "ROR%S  %i,%e",
                    407: [0x02] Ib,0,           "RCL%S  %i,%e",
                    408: [0x03] Ib,0,           "RCR%S  %i,%e",
                    409: [0x04] Ib,0,           "SHL%S  %i,%e",
                    410: [0x05] Ib,0,           "SHR%S  %i,%e",
                    411: [0x07] Ib,0,           "SAR%S  %i,%e",
                    412: };
                    413: 
                    414: static Optable optabD0[8] =
                    415: {
                    416: [0x00] 0,0,            "ROLB   %e",
                    417: [0x01] 0,0,            "RORB   %e",
                    418: [0x02] 0,0,            "RCLB   %e",
                    419: [0x03] 0,0,            "RCRB   %e",
                    420: [0x04] 0,0,            "SHLB   %e",
                    421: [0x05] 0,0,            "SHRB   %e",
                    422: [0x07] 0,0,            "SARB   %e",
                    423: };
                    424: 
                    425: static Optable optabD1[8] =
                    426: {
                    427: [0x00] 0,0,            "ROL%S  %e",
                    428: [0x01] 0,0,            "ROR%S  %e",
                    429: [0x02] 0,0,            "RCL%S  %e",
                    430: [0x03] 0,0,            "RCR%S  %e",
                    431: [0x04] 0,0,            "SHL%S  %e",
                    432: [0x05] 0,0,            "SHR%S  %e",
                    433: [0x07] 0,0,            "SAR%S  %e",
                    434: };
                    435: 
                    436: static Optable optabD2[8] =
                    437: {
                    438: [0x00] 0,0,            "ROLB   CL,%e",
                    439: [0x01] 0,0,            "RORB   CL,%e",
                    440: [0x02] 0,0,            "RCLB   CL,%e",
                    441: [0x03] 0,0,            "RCRB   CL,%e",
                    442: [0x04] 0,0,            "SHLB   CL,%e",
                    443: [0x05] 0,0,            "SHRB   CL,%e",
                    444: [0x07] 0,0,            "SARB   CL,%e",
                    445: };
                    446: 
                    447: static Optable optabD3[8] =
                    448: {
                    449: [0x00] 0,0,            "ROL%S  CL,%e",
                    450: [0x01] 0,0,            "ROR%S  CL,%e",
                    451: [0x02] 0,0,            "RCL%S  CL,%e",
                    452: [0x03] 0,0,            "RCR%S  CL,%e",
                    453: [0x04] 0,0,            "SHL%S  CL,%e",
                    454: [0x05] 0,0,            "SHR%S  CL,%e",
                    455: [0x07] 0,0,            "SAR%S  CL,%e",
                    456: };
                    457: 
                    458: static Optable optabD8[8+8] =
                    459: {
                    460: [0x00] 0,0,            "FADDF  %e,F0",
                    461: [0x01] 0,0,            "FMULF  %e,F0",
                    462: [0x02] 0,0,            "FCOMF  %e,F0",
                    463: [0x03] 0,0,            "FCOMFP %e,F0",
                    464: [0x04] 0,0,            "FSUBF  %e,F0",
                    465: [0x05] 0,0,            "FSUBRF %e,F0",
                    466: [0x06] 0,0,            "FDIVF  %e,F0",
                    467: [0x07] 0,0,            "FDIVRF %e,F0",
                    468: [0x08] 0,0,            "FADDD  %f,F0",
                    469: [0x09] 0,0,            "FMULD  %f,F0",
                    470: [0x0a] 0,0,            "FCOMD  %f,F0",
                    471: [0x0b] 0,0,            "FCOMPD %f,F0",
                    472: [0x0c] 0,0,            "FSUBD  %f,F0",
                    473: [0x0d] 0,0,            "FSUBRD %f,F0",
                    474: [0x0e] 0,0,            "FDIVD  %f,F0",
                    475: [0x0f] 0,0,            "FDIVRD %f,F0",
                    476: };
                    477: /*
                    478:  *     optabD9 and optabDB use the following encoding: 
                    479:  *     if (0 <= modrm <= 2) instruction = optabDx[modrm&0x07];
                    480:  *     else instruction = optabDx[(modrm&0x3f)+8];
                    481:  *
                    482:  *     the instructions for MOD == 3, follow the 8 instructions
                    483:  *     for the other MOD values stored at the front of the table.
                    484:  */
                    485: static Optable optabD9[64+8] =
                    486: {
                    487: [0x00] 0,0,            "FMOVF  %e,F0",
                    488: [0x02] 0,0,            "FMOVF  F0,%e",
                    489: [0x03] 0,0,            "FMOVFP F0,%e",
                    490: [0x04] 0,0,            "FLDENV%S %e",
                    491: [0x05] 0,0,            "FLDCW  %e",
                    492: [0x06] 0,0,            "FSTENV%S %e",
                    493: [0x07] 0,0,            "FSTCW  %e",
                    494: [0x08] 0,0,            "FMOVD  F0,F0",         /* Mod R/M = 11xx xxxx*/
                    495: [0x09] 0,0,            "FMOVD  F1,F0",
                    496: [0x0a] 0,0,            "FMOVD  F2,F0",
                    497: [0x0b] 0,0,            "FMOVD  F3,F0",
                    498: [0x0c] 0,0,            "FMOVD  F4,F0",
                    499: [0x0d] 0,0,            "FMOVD  F5,F0",
                    500: [0x0e] 0,0,            "FMOVD  F6,F0",
                    501: [0x0f] 0,0,            "FMOVD  F7,F0",
                    502: [0x10] 0,0,            "FXCHD  F0,F0",
                    503: [0x11] 0,0,            "FXCHD  F1,F0",
                    504: [0x12] 0,0,            "FXCHD  F2,F0",
                    505: [0x13] 0,0,            "FXCHD  F3,F0",
                    506: [0x14] 0,0,            "FXCHD  F4,F0",
                    507: [0x15] 0,0,            "FXCHD  F5,F0",
                    508: [0x16] 0,0,            "FXCHD  F6,F0",
                    509: [0x17] 0,0,            "FXCHD  F7,F0",
                    510: [0x18] 0,0,            "FNOP",
                    511: [0x28] 0,0,            "FCHS",
                    512: [0x29] 0,0,            "FABS",
                    513: [0x2c] 0,0,            "FTST",
                    514: [0x2d] 0,0,            "FXAM",
                    515: [0x30] 0,0,            "FLD1",
                    516: [0x31] 0,0,            "FLDL2T",
                    517: [0x32] 0,0,            "FLDL2E",
                    518: [0x33] 0,0,            "FLDPI",
                    519: [0x34] 0,0,            "FLDLG2",
                    520: [0x35] 0,0,            "FLDLN2",
                    521: [0x36] 0,0,            "FLDZ",
                    522: [0x38] 0,0,            "F2XM1",
                    523: [0x39] 0,0,            "FYL2X",
                    524: [0x3a] 0,0,            "FPTAN",
                    525: [0x3b] 0,0,            "FPATAN",
                    526: [0x3c] 0,0,            "FXTRACT",
                    527: [0x3d] 0,0,            "FPREM1",
                    528: [0x3e] 0,0,            "FDECSTP",
                    529: [0x3f] 0,0,            "FNCSTP",
                    530: [0x40] 0,0,            "FPREM",
                    531: [0x41] 0,0,            "FYL2XP1",
                    532: [0x42] 0,0,            "FSQRT",
                    533: [0x43] 0,0,            "FSINCOS",
                    534: [0x44] 0,0,            "FRNDINT",
                    535: [0x45] 0,0,            "FSCALE",
                    536: [0x46] 0,0,            "FSIN",
                    537: [0x47] 0,0,            "FCOS",
                    538: };
                    539: 
                    540: static Optable optabDA[8+8] =
                    541: {
                    542: [0x00] 0,0,            "FADDL  %e,F0",
                    543: [0x01] 0,0,            "FMULL  %e,F0",
                    544: [0x02] 0,0,            "FCOML  %e,F0",
                    545: [0x03] 0,0,            "FCOMLP %e,F0",
                    546: [0x04] 0,0,            "FSUBL  %e,F0",
                    547: [0x05] 0,0,            "FSUBRL %e,F0",
                    548: [0x06] 0,0,            "FDIVL  %e,F0",
                    549: [0x07] 0,0,            "FDIVRL %e,F0",
                    550: [0x0d] R1,0,           "FUCOMPP",
                    551: };
                    552: 
                    553: static Optable optabDB[8+64] =
                    554: {
                    555: [0x00] 0,0,            "FMOVL  %e,F0",
                    556: [0x02] 0,0,            "FMOVL  F0,%e",
                    557: [0x03] 0,0,            "FMOVLP F0,%e",
                    558: [0x05] 0,0,            "FMOVX  %e,F0",
                    559: [0x07] 0,0,            "FMOVXP F0,%e",
                    560: [0x2a] 0,0,            "FCLEX",
                    561: [0x2b] 0,0,            "FINIT",
                    562: };
                    563: 
                    564: static Optable optabDC[8+8] =
                    565: {
                    566: [0x00] 0,0,            "FADDD  %e,F0",
                    567: [0x01] 0,0,            "FMULD  %e,F0",
                    568: [0x02] 0,0,            "FCOMD  %e,F0",
                    569: [0x03] 0,0,            "FCOMDP %e,F0",
                    570: [0x04] 0,0,            "FSUBD  %e,F0",
                    571: [0x05] 0,0,            "FSUBRD %e,F0",
                    572: [0x06] 0,0,            "FDIVD  %e,F0",
                    573: [0x07] 0,0,            "FDIVRD %e,F0",
                    574: [0x08] 0,0,            "FADDD  F0,%f",
                    575: [0x09] 0,0,            "FMULD  F0,%f",
                    576: [0x0c] 0,0,            "FSUBRD F0,%f",
                    577: [0x0d] 0,0,            "FSUBD  F0,%f",
                    578: [0x0e] 0,0,            "FDIVRD F0,%f",
                    579: [0x0f] 0,0,            "FDIVD  F0,%f",
                    580: };
                    581: 
                    582: static Optable optabDD[8+8] =
                    583: {
                    584: [0x00] 0,0,            "FMOVD  %e,F0",
                    585: [0x02] 0,0,            "FMOVD  F0,%e",
                    586: [0x03] 0,0,            "FMOVDP F0,%e",
                    587: [0x04] 0,0,            "FRSTOR%S %e",
                    588: [0x06] 0,0,            "FSAVE%S %e",
                    589: [0x07] 0,0,            "FSTSW  %e",
                    590: [0x08] 0,0,            "FFREED %f",
                    591: [0x0a] 0,0,            "FMOVD  %f,F0",
                    592: [0x0b] 0,0,            "FMOVDP %f,F0",
                    593: [0x0c] 0,0,            "FUCOMD %f,F0",
                    594: [0x0d] 0,0,            "FUCOMDP %f,F0",
                    595: };
                    596: 
                    597: static Optable optabDE[8+8] =
                    598: {
                    599: [0x00] 0,0,            "FADDW  %e,F0",
                    600: [0x01] 0,0,            "FMULW  %e,F0",
                    601: [0x02] 0,0,            "FCOMW  %e,F0",
                    602: [0x03] 0,0,            "FCOMWP %e,F0",
                    603: [0x04] 0,0,            "FSUBW  %e,F0",
                    604: [0x05] 0,0,            "FSUBRW %e,F0",
                    605: [0x06] 0,0,            "FDIVW  %e,F0",
                    606: [0x07] 0,0,            "FDIVRW %e,F0",
                    607: [0x08] 0,0,            "FADDDP F0,%f",
                    608: [0x09] 0,0,            "FMULDP F0,%f",
                    609: [0x0b] R1,0,           "FCOMPDP",
                    610: [0x0c] 0,0,            "FSUBRDP F0,%f",
                    611: [0x0d] 0,0,            "FSUBDP F0,%f",
                    612: [0x0e] 0,0,            "FDIVRDP F0,%f",
                    613: [0x0f] 0,0,            "FDIVDP F0,%f",
                    614: };
                    615: 
                    616: static Optable optabDF[8+8] =
                    617: {
                    618: [0x00] 0,0,            "FMOVW  %e,F0",
                    619: [0x02] 0,0,            "FMOVW  F0,%e",
                    620: [0x03] 0,0,            "FMOVWP F0,%e",
                    621: [0x04] 0,0,            "FBLD   %e",
                    622: [0x05] 0,0,            "FMOVL  %e,F0",
                    623: [0x06] 0,0,            "FBSTP  %e",
                    624: [0x07] 0,0,            "FMOVLP F0,%e",
                    625: [0x0c] R0,0,           "FSTSW  %OAX",
                    626: };
                    627: 
                    628: static Optable optabF6[8] =
                    629: {
                    630: [0x00] Ib,0,           "TESTB  %i,%e",
                    631: [0x02] 0,0,            "NOTB   %e",
                    632: [0x03] 0,0,            "NEGB   %e",
                    633: [0x04] 0,0,            "MULB   AL,%e",
                    634: [0x05] 0,0,            "IMULB  AL,%e",
                    635: [0x06] 0,0,            "DIVB   AL,%e",
                    636: [0x07] 0,0,            "IDIVB  AL,%e",
                    637: };
                    638: 
                    639: static Optable optabF7[8] =
                    640: {
                    641: [0x00] Iwd,0,          "TEST%S %i,%e",
                    642: [0x02] 0,0,            "NOT%S  %e",
                    643: [0x03] 0,0,            "NEG%S  %e",
                    644: [0x04] 0,0,            "MUL%S  %OAX,%e",
                    645: [0x05] 0,0,            "IMUL%S %OAX,%e",
                    646: [0x06] 0,0,            "DIV%S  %OAX,%e",
                    647: [0x07] 0,0,            "IDIV%S %OAX,%e",
                    648: };
                    649: 
                    650: static Optable optabFE[8] =
                    651: {
                    652: [0x00] 0,0,            "INCB   %e",
                    653: [0x01] 0,0,            "DECB   %e",
                    654: };
                    655: 
                    656: static Optable optabFF[8] =
                    657: {
                    658: [0x00] 0,0,            "INC%S  %e",
                    659: [0x01] 0,0,            "DEC%S  %e",
                    660: [0x02] JUMP,0,         "CALL*%S %e",
                    661: [0x03] JUMP,0,         "CALLF*%S %e",
                    662: [0x04] JUMP,0,         "JMP*%S %e",
                    663: [0x05] JUMP,0,         "JMPF*%S %e",
                    664: [0x06] 0,0,            "PUSHL  %e",
                    665: };
                    666: 
                    667: static Optable optable[256] =
                    668: {
                    669: [0x00] RMB,0,          "ADDB   %r,%e",
                    670: [0x01] RM,0,           "ADD%S  %r,%e",
                    671: [0x02] RMB,0,          "ADDB   %e,%r",
                    672: [0x03] RM,0,           "ADD%S  %e,%r",
                    673: [0x04] Ib,0,           "ADDB   %i,AL",
                    674: [0x05] Iwd,0,          "ADD%S  %i,%OAX",
                    675: [0x06] 0,0,            "PUSHL  ES",
                    676: [0x07] 0,0,            "POPL   ES",
                    677: [0x08] RMB,0,          "ORB    %r,%e",
                    678: [0x09] RM,0,           "OR%S   %r,%e",
                    679: [0x0a] RMB,0,          "ORB    %e,%r",
                    680: [0x0b] RM,0,           "OR%S   %e,%r",
                    681: [0x0c] Ib,0,           "ORB    %i,AL",
                    682: [0x0d] Iwd,0,          "OR%S   %i,%OAX",
                    683: [0x0e] 0,0,            "PUSHL  CS",
                    684: [0x0f] AUX,0,          optab0F,
                    685: [0x10] RMB,0,          "ADCB   %r,%e",
                    686: [0x11] RM,0,           "ADC%S  %r,%e",
                    687: [0x12] RMB,0,          "ADCB   %e,%r",
                    688: [0x13] RM,0,           "ADC%S  %e,%r",
                    689: [0x14] Ib,0,           "ADCB   %i,AL",
                    690: [0x15] Iwd,0,          "ADC%S  %i,%OAX",
                    691: [0x16] 0,0,            "PUSHL  SS",
                    692: [0x17] 0,0,            "POPL   SS",
                    693: [0x18] RMB,0,          "SBBB   %r,%e",
                    694: [0x19] RM,0,           "SBB%S  %r,%e",
                    695: [0x1a] RMB,0,          "SBBB   %e,%r",
                    696: [0x1b] RM,0,           "SBB%S  %e,%r",
                    697: [0x1c] Ib,0,           "SBBB   %i,AL",
                    698: [0x1d] Iwd,0,          "SBB%S  %i,%OAX",
                    699: [0x1e] 0,0,            "PUSHL  DS",
                    700: [0x1f] 0,0,            "POPL   DS",
                    701: [0x20] RMB,0,          "ANDB   %r,%e",
                    702: [0x21] RM,0,           "AND%S  %r,%e",
                    703: [0x22] RMB,0,          "ANDB   %e,%r",
                    704: [0x23] RM,0,           "AND%S  %e,%r",
                    705: [0x24] Ib,0,           "ANDB   %i,AL",
                    706: [0x25] Iwd,0,          "AND%S  %i,%OAX",
                    707: [0x26] SEG,0,          "ES:",
                    708: [0x27] 0,0,            "DAA",
                    709: [0x28] RMB,0,          "SUBB   %r,%e",
                    710: [0x29] RM,0,           "SUB%S  %r,%e",
                    711: [0x2a] RMB,0,          "SUBB   %e,%r",
                    712: [0x2b] RM,0,           "SUB%S  %e,%r",
                    713: [0x2c] Ib,0,           "SUBB   %i,AL",
                    714: [0x2d] Iwd,0,          "SUB%S  %i,%OAX",
                    715: [0x2e] SEG,0,          "CS:",
                    716: [0x2f] 0,0,            "DAS",
                    717: [0x30] RMB,0,          "XORB   %r,%e",
                    718: [0x31] RM,0,           "XOR%S  %r,%e",
                    719: [0x32] RMB,0,          "XORB   %e,%r",
                    720: [0x33] RM,0,           "XOR%S  %e,%r",
                    721: [0x34] Ib,0,           "XORB   %i,AL",
                    722: [0x35] Iwd,0,          "XOR%S  %i,%OAX",
                    723: [0x36] SEG,0,          "SS:",
                    724: [0x37] 0,0,            "AAA",
                    725: [0x38] RMB,0,          "CMPB   %r,%e",
                    726: [0x39] RM,0,           "CMP%S  %r,%e",
                    727: [0x3a] RMB,0,          "CMPB   %e,%r",
                    728: [0x3b] RM,0,           "CMP%S  %e,%r",
                    729: [0x3c] Ib,0,           "CMPB   %i,AL",
                    730: [0x3d] Iwd,0,          "CMP%S  %i,%OAX",
                    731: [0x3e] SEG,0,          "DS:",
                    732: [0x3f] 0,0,            "AAS",
                    733: [0x40] 0,0,            "INC%S  %OAX",
                    734: [0x41] 0,0,            "INC%S  %OCX",
                    735: [0x42] 0,0,            "INC%S  %ODX",
                    736: [0x43] 0,0,            "INC%S  %OBX",
                    737: [0x44] 0,0,            "INC%S  %OSP",
                    738: [0x45] 0,0,            "INC%S  %OBP",
                    739: [0x46] 0,0,            "INC%S  %OSI",
                    740: [0x47] 0,0,            "INC%S  %ODI",
                    741: [0x48] 0,0,            "DEC%S  %OAX",
                    742: [0x49] 0,0,            "DEC%S  %OCX",
                    743: [0x4a] 0,0,            "DEC%S  %ODX",
                    744: [0x4b] 0,0,            "DEC%S  %OBX",
                    745: [0x4c] 0,0,            "DEC%S  %OSP",
                    746: [0x4d] 0,0,            "DEC%S  %OBP",
                    747: [0x4e] 0,0,            "DEC%S  %OSI",
                    748: [0x4f] 0,0,            "DEC%S  %ODI",
                    749: [0x50] 0,0,            "PUSH%S %OAX",
                    750: [0x51] 0,0,            "PUSH%S %OCX",
                    751: [0x52] 0,0,            "PUSH%S %ODX",
                    752: [0x53] 0,0,            "PUSH%S %OBX",
                    753: [0x54] 0,0,            "PUSH%S %OSP",
                    754: [0x55] 0,0,            "PUSH%S %OBP",
                    755: [0x56] 0,0,            "PUSH%S %OSI",
                    756: [0x57] 0,0,            "PUSH%S %ODI",
                    757: [0x58] 0,0,            "POP%S  %OAX",
                    758: [0x59] 0,0,            "POP%S  %OCX",
                    759: [0x5a] 0,0,            "POP%S  %ODX",
                    760: [0x5b] 0,0,            "POP%S  %OBX",
                    761: [0x5c] 0,0,            "POP%S  %OSP",
                    762: [0x5d] 0,0,            "POP%S  %OBP",
                    763: [0x5e] 0,0,            "POP%S  %OSI",
                    764: [0x5f] 0,0,            "POP%S  %ODI",
                    765: [0x60] 0,0,            "PUSHA%S",
                    766: [0x61] 0,0,            "POPA%S",
                    767: [0x62] RMM,0,          "BOUND  %e,%r",
                    768: [0x63] RM,0,           "ARPL   %r,%e",
                    769: [0x64] SEG,0,          "FS:",
                    770: [0x65] SEG,0,          "GS:",
                    771: [0x66] OPOVER,0,       "",
                    772: [0x67] ADDOVER,0,      "",
                    773: [0x68] Iwd,0,          "PUSH%S %i",
                    774: [0x69] RM,Iwd,         "IMUL%S %e,%i,%r",
                    775: [0x6a] Ib,0,           "PUSH%S %i",
                    776: [0x6b] RM,Ibs,         "IMUL%S %e,%i,%r",
                    777: [0x6c] 0,0,            "INSB   DX,(%ODI)",
                    778: [0x6d] 0,0,            "INS%S  DX,(%ODI)",
                    779: [0x6e] 0,0,            "OUTSB  (%ASI),DX",
                    780: [0x6f] 0,0,            "OUTS%S (%ASI),DX",
                    781: [0x70] Jbs,0,          "JOS    %p",
                    782: [0x71] Jbs,0,          "JOC    %p",
                    783: [0x72] Jbs,0,          "JCS    %p",
                    784: [0x73] Jbs,0,          "JCC    %p",
                    785: [0x74] Jbs,0,          "JEQ    %p",
                    786: [0x75] Jbs,0,          "JNE    %p",
                    787: [0x76] Jbs,0,          "JLS    %p",
                    788: [0x77] Jbs,0,          "JHI    %p",
                    789: [0x78] Jbs,0,          "JMI    %p",
                    790: [0x79] Jbs,0,          "JPL    %p",
                    791: [0x7a] Jbs,0,          "JPS    %p",
                    792: [0x7b] Jbs,0,          "JPC    %p",
                    793: [0x7c] Jbs,0,          "JLT    %p",
                    794: [0x7d] Jbs,0,          "JGE    %p",
                    795: [0x7e] Jbs,0,          "JLE    %p",
                    796: [0x7f] Jbs,0,          "JGT    %p",
                    797: [0x80] RMOPB,0,        optab80,
                    798: [0x81] RMOP,0,         optab81,
                    799: [0x83] RMOP,0,         optab83,
                    800: [0x84] RMB,0,          "TESTB  %r,%e",
                    801: [0x85] RM,0,           "TEST%S %r,%e",
                    802: [0x86] RMB,0,          "XCHGB  %r,%e",
                    803: [0x87] RM,0,           "XCHG%S %r,%e",
                    804: [0x88] RMB,0,          "MOVB   %r,%e",
                    805: [0x89] RM,0,           "MOV%S  %r,%e",
                    806: [0x8a] RMB,0,          "MOVB   %e,%r",
                    807: [0x8b] RM,0,           "MOV%S  %e,%r",
                    808: [0x8c] RM,0,           "MOVW   %g,%e",
                    809: [0x8d] RM,0,           "LEA    %e,%r",
                    810: [0x8e] RM,0,           "MOVW   %e,%g",
                    811: [0x8f] RM,0,           "POP%S  %e",
                    812: [0x90] 0,0,            "NOP",
                    813: [0x91] 0,0,            "XCHG   %OCX,%OAX",
                    814: [0x92] 0,0,            "XCHG   %OCX,%OAX",
                    815: [0x93] 0,0,            "XCHG   %OCX,%OAX",
                    816: [0x94] 0,0,            "XCHG   %OSP,%OAX",
                    817: [0x95] 0,0,            "XCHG   %OBP,%OAX",
                    818: [0x96] 0,0,            "XCHG   %OSI,%OAX",
                    819: [0x97] 0,0,            "XCHG   %ODI,%OAX",
                    820: [0x98] 0,0,            "%X",                   /* miserable CBW or CWDE */
                    821: [0x99] 0,0,            "%x",                   /* idiotic CWD or CDQ */
                    822: [0x9a] PTR,0,          "CALL%S %d",
                    823: [0x9b] 0,0,            "WAIT",
                    824: [0x9c] 0,0,            "PUSH   FLAGS",
                    825: [0x9d] 0,0,            "POP    FLAGS",
                    826: [0x9f] 0,0,            "LAHF",
                    827: [0xa0] Awd,0,          "MOVB   %i,AL",
                    828: [0xa1] Awd,0,          "MOV%S  %i,%OAX",
                    829: [0xa2] Awd,0,          "MOVB   AL,%i",
                    830: [0xa3] Awd,0,          "MOV%S  %OAX,%i",
                    831: [0xa4] 0,0,            "MOVSB  (%ASI),(%ADI)",
                    832: [0xa5] 0,0,            "MOVS%S (%ASI),(%ADI)",
                    833: [0xa6] 0,0,            "CMPSB  (%ASI),(%ADI)",
                    834: [0xa7] 0,0,            "CMPS%S (%ASI),(%ADI)",
                    835: [0xa8] Ib,0,           "TESTB  %i,AL",
                    836: [0xa9] Iwd,0,          "TEST%S %i,%OAX",
                    837: [0xaa] 0,0,            "STOSB  AL,(%ADI)",
                    838: [0xab] 0,0,            "STOS%S %OAX,(%ADI)",
                    839: [0xac] 0,0,            "LODSB  (%ASI),AL",
                    840: [0xad] 0,0,            "LODS%S (%ASI),%OAX",
                    841: [0xae] 0,0,            "SCASB  (%ADI),AL",
                    842: [0xaf] 0,0,            "SCAS%S (%ADI),%OAX",
                    843: [0xb0] Ib,0,           "MOVB   %i,AL",
                    844: [0xb1] Ib,0,           "MOVB   %i,CL",
                    845: [0xb2] Ib,0,           "MOVB   %i,DL",
                    846: [0xb3] Ib,0,           "MOVB   %i,BL",
                    847: [0xb4] Ib,0,           "MOVB   %i,AH",
                    848: [0xb5] Ib,0,           "MOVB   %i,CH",
                    849: [0xb6] Ib,0,           "MOVB   %i,DH",
                    850: [0xb7] Ib,0,           "MOVB   %i,BH",
                    851: [0xb8] Iwd,0,          "MOV%S  %i,%OAX",
                    852: [0xb9] Iwd,0,          "MOV%S  %i,%OCX",
                    853: [0xba] Iwd,0,          "MOV%S  %i,%ODX",
                    854: [0xbb] Iwd,0,          "MOV%S  %i,%OBX",
                    855: [0xbc] Iwd,0,          "MOV%S  %i,%OSP",
                    856: [0xbd] Iwd,0,          "MOV%S  %i,%OBP",
                    857: [0xbe] Iwd,0,          "MOV%S  %i,%OSI",
                    858: [0xbf] Iwd,0,          "MOV%S  %i,%ODI",
                    859: [0xc0] RMOPB,0,        optabC0,
                    860: [0xc1] RMOP,0,         optabC1,
                    861: [0xc2] Iw,0,           "RET    %i",
                    862: [0xc3] RET,0,          "RET",
                    863: [0xc4] RM,0,           "LES    %e,%r",
                    864: [0xc5] RM,0,           "LDS    %e,%r",
                    865: [0xc6] RMB,Ib,         "MOVB   %i,%e",
                    866: [0xc7] RM,Iwd,         "MOV%S  %i,%e",
                    867: [0xc8] Iw2,Ib,         "ENTER  %i,%I",         /* loony ENTER */
                    868: [0xc9] RET,0,          "LEAVE",                /* bizarre LEAVE */
                    869: [0xca] Iw,0,           "RETF   %i",
                    870: [0xcb] RET,0,          "RETF",
                    871: [0xcc] 0,0,            "INT    3",
                    872: [0xcd] Ib,0,           "INTB   %i",
                    873: [0xce] 0,0,            "INTO",
                    874: [0xcf] 0,0,            "IRET",
                    875: [0xd0] RMOPB,0,        optabD0,
                    876: [0xd1] RMOP,0,         optabD1,
                    877: [0xd2] RMOPB,0,        optabD2,
                    878: [0xd3] RMOP,0,         optabD3,
                    879: [0xd4] OA,0,           "AAM",
                    880: [0xd5] OA,0,           "AAD",
                    881: [0xd7] 0,0,            "XLAT",
                    882: [0xd8] FRMOP,0,        optabD8,
                    883: [0xd9] FRMEX,0,        optabD9,
                    884: [0xda] FRMOP,0,        optabDA,
                    885: [0xdb] FRMEX,0,        optabDB,
                    886: [0xdc] FRMOP,0,        optabDC,
                    887: [0xdd] FRMOP,0,        optabDD,
                    888: [0xde] FRMOP,0,        optabDE,
                    889: [0xdf] FRMOP,0,        optabDF,
                    890: [0xe0] Jbs,0,          "LOOPNE %p",
                    891: [0xe1] Jbs,0,          "LOOPE  %p",
                    892: [0xe2] Jbs,0,          "LOOP   %p",
                    893: [0xe3] Jbs,0,          "JCXZ   %p",
                    894: [0xe4] Ib,0,           "INB    %i,AL",
                    895: [0xe5] Ib,0,           "IN%S   %i,%OAX",
                    896: [0xe6] Ib,0,           "OUTB   AL,%i",
                    897: [0xe7] Ib,0,           "OUT%S  %OAX,%i",
                    898: [0xe8] Iwds,0,         "CALL   %p",
                    899: [0xe9] Iwds,0,         "JMP    %p",
                    900: [0xea] PTR,0,          "JMP    %d",
                    901: [0xeb] Jbs,0,          "JMP    %p",
                    902: [0xec] 0,0,            "INB    DX,AL",
                    903: [0xed] 0,0,            "IN%S   DX,%OAX",
                    904: [0xee] 0,0,            "OUTB   AL,DX",
                    905: [0xef] 0,0,            "OUT%S  %OAX,DX",
                    906: [0xf0] PRE,0,          "LOCK",
                    907: [0xf2] PRE,0,          "REPNE",
                    908: [0xf3] PRE,0,          "REP",
                    909: [0xf4] 0,0,            "HALT",
                    910: [0xf5] 0,0,            "CMC",
                    911: [0xf6] RMOPB,0,        optabF6,
                    912: [0xf7] RMOP,0,         optabF7,
                    913: [0xf8] 0,0,            "CLC",
                    914: [0xf9] 0,0,            "STC",
                    915: [0xfa] 0,0,            "CLI",
                    916: [0xfb] 0,0,            "STI",
                    917: [0xfc] 0,0,            "CLD",
                    918: [0xfd] 0,0,            "STD",
                    919: [0xfe] RMOPB,0,        optabFE,
                    920: [0xff] RMOP,0,         optabFF,
                    921: };
                    922: 
                    923: /*
                    924:  *  get a byte of the instruction
                    925:  */
                    926: static int
                    927: igetc(Map * map, Instr *ip, uchar *c)
                    928: {
                    929:        if(ip->n+1 > sizeof(ip->mem)){
                    930:                werrstr("instruction too long");
                    931:                return -1;
                    932:        }
                    933:        if (get1(map, ip->addr+ip->n, c, 1) < 0) {
                    934:                werrstr("can't read instruction: %r");
                    935:                return -1;
                    936:        }
                    937:        ip->mem[ip->n++] = *c;
                    938:        return 1;
                    939: }
                    940: 
                    941: /*
                    942:  *  get two bytes of the instruction
                    943:  */
                    944: static int
                    945: igets(Map *map, Instr *ip, ushort *sp)
                    946: {
                    947:        uchar   c;
                    948:        ushort s;
                    949: 
                    950:        if (igetc(map, ip, &c) < 0)
                    951:                return -1;
                    952:        s = c;
                    953:        if (igetc(map, ip, &c) < 0)
                    954:                return -1;
                    955:        s |= (c<<8);
                    956:        *sp = s;
                    957:        return 1;
                    958: }
                    959: 
                    960: /*
                    961:  *  get 4 bytes of the instruction
                    962:  */
                    963: static int
                    964: igetl(Map *map, Instr *ip, ulong *lp)
                    965: {
                    966:        ushort s;
                    967:        long    l;
                    968: 
                    969:        if (igets(map, ip, &s) < 0)
                    970:                return -1;
                    971:        l = s;
                    972:        if (igets(map, ip, &s) < 0)
                    973:                return -1;
                    974:        l |= (s<<16);
                    975:        *lp = l;
                    976:        return 1;
                    977: }
                    978: 
                    979: static int
                    980: getdisp(Map *map, Instr *ip, int mod, int rm, int code)
                    981: {
                    982:        uchar c;
                    983:        ushort s;
                    984: 
                    985:        if (mod > 2)
                    986:                return 1;
                    987:        if (mod == 1) {
                    988:                if (igetc(map, ip, &c) < 0)
                    989:                        return -1;
                    990:                if (c&0x80)
                    991:                        ip->disp = c|0xffffff00;
                    992:                else
                    993:                        ip->disp = c&0xff;
                    994:        } else if (mod == 2 || rm == code) {
                    995:                if (ip->asize == 'E') {
                    996:                        if (igetl(map, ip, &ip->disp) < 0)
                    997:                                return -1;
                    998:                } else {
                    999:                        if (igets(map, ip, &s) < 0)
                   1000:                                return -1;
                   1001:                        if (s&0x8000)
                   1002:                                ip->disp = s|0xffff0000;
                   1003:                        else
                   1004:                                ip->disp = s;
                   1005:                }
                   1006:                if (mod == 0)
                   1007:                        ip->base = -1;
                   1008:        }
                   1009:        return 1;
                   1010: }
                   1011: 
                   1012: static int
                   1013: modrm(Map *map, Instr *ip, uchar c)
                   1014: {
                   1015:        uchar rm, mod;
                   1016: 
                   1017:        mod = (c>>6)&3;
                   1018:        rm = c&7;
                   1019:        ip->mod = mod;
                   1020:        ip->base = rm;
                   1021:        ip->reg = (c>>3)&7;
                   1022:        if (mod == 3)                   /* register */
                   1023:                return 1;
                   1024:        if (ip->asize == 0) {           /* 16-bit mode */
                   1025:                switch(rm)
                   1026:                {
                   1027:                case 0:
                   1028:                        ip->base = BX; ip->index = SI;
                   1029:                        break;
                   1030:                case 1:
                   1031:                        ip->base = BX; ip->index = DI;
                   1032:                        break;
                   1033:                case 2:
                   1034:                        ip->base = BP; ip->index = SI;
                   1035:                        break;
                   1036:                case 3:
                   1037:                        ip->base = BP; ip->index = DI;
                   1038:                        break;
                   1039:                case 4:
                   1040:                        ip->base = SI;
                   1041:                        break;
                   1042:                case 5:
                   1043:                        ip->base = DI;
                   1044:                        break;
                   1045:                case 6:
                   1046:                        ip->base = BP;
                   1047:                        break;
                   1048:                case 7:
                   1049:                        ip->base = BX;
                   1050:                        break;
                   1051:                default:
                   1052:                        break;
                   1053:                }
                   1054:                return getdisp(map, ip, mod, rm, 6);
                   1055:        }
                   1056:        if (rm == 4) {  /* scummy sib byte */
                   1057:                if (igetc(map, ip, &c) < 0)
                   1058:                        return -1;
                   1059:                ip->ss = (c>>6)&0x03;
                   1060:                ip->index = (c>>3)&0x07;
                   1061:                if (ip->index == 4)
                   1062:                        ip->index = -1;
                   1063:                ip->base = c&0x07;
                   1064:                return getdisp(map, ip, mod, ip->base, 5);
                   1065:        }
                   1066:        return getdisp(map, ip, mod, rm, 5);
                   1067: }
                   1068: 
                   1069: static Optable *
                   1070: mkinstr(Map *map, Instr *ip, ulong pc)
                   1071: {
                   1072:        int i, n;
                   1073:        uchar c;
                   1074:        ushort s;
                   1075:        Optable *op, *obase;
                   1076:        char buf[128];
                   1077: 
                   1078:        memset(ip, 0, sizeof(*ip));
                   1079:        ip->base = -1;
                   1080:        ip->index = -1;
                   1081:        if(asstype == AI8086)
                   1082:                ip->osize = 'W';
                   1083:        else {
                   1084:                ip->osize = 'L';
                   1085:                ip->asize = 'E';
                   1086:        }
                   1087:        ip->addr = pc;
                   1088:        if (igetc(map, ip, &c) < 0)
                   1089:                return 0;
                   1090:        obase = optable;
                   1091: newop:
                   1092:        op = &obase[c];
                   1093:        if (op->proto == 0) {
                   1094: badop:
                   1095:                n = snprint(buf, sizeof(buf), "opcode: ??");
                   1096:                for (i = 0; i < ip->n && n < sizeof(buf)-3; i++, n+=2)
                   1097:                        _hexify(buf+n, ip->mem[i], 1);
                   1098:                strcpy(buf+n, "??");
                   1099:                werrstr(buf);
                   1100:                return 0;
                   1101:        }
                   1102:        for(i = 0; i < 2 && op->operand[i]; i++) {
                   1103:                switch(op->operand[i])
                   1104:                {
                   1105:                case Ib:        /* 8-bit immediate - (no sign extension)*/
                   1106:                        if (igetc(map, ip, &c) < 0)
                   1107:                                return 0;
                   1108:                        ip->imm = c&0xff;
                   1109:                        break;
                   1110:                case Jbs:       /* 8-bit jump immediate (sign extended) */
                   1111:                        if (igetc(map, ip, &c) < 0)
                   1112:                                return 0;
                   1113:                        if (c&0x80)
                   1114:                                ip->imm = c|0xffffff00;
                   1115:                        else
                   1116:                                ip->imm = c&0xff;
                   1117:                        ip->jumptype = Jbs;
                   1118:                        break;
                   1119:                case Ibs:       /* 8-bit immediate (sign extended) */
                   1120:                        if (igetc(map, ip, &c) < 0)
                   1121:                                return 0;
                   1122:                        if (c&0x80)
                   1123:                                if (ip->osize == 'L')
                   1124:                                        ip->imm = c|0xffffff00;
                   1125:                                else
                   1126:                                        ip->imm = c|0xff00;
                   1127:                        else
                   1128:                                ip->imm = c&0xff;
                   1129:                        break;
                   1130:                case Iw:        /* 16-bit immediate -> imm */
                   1131:                        if (igets(map, ip, &s) < 0)
                   1132:                                return 0;
                   1133:                        ip->imm = s&0xffff;
                   1134:                        ip->jumptype = Iw;
                   1135:                        break;
                   1136:                case Iw2:       /* 16-bit immediate -> in imm2*/
                   1137:                        if (igets(map, ip, &s) < 0)
                   1138:                                return 0;
                   1139:                        ip->imm2 = s&0xffff;
                   1140:                        break;
                   1141:                case Iwd:       /* Operand-sized immediate (no sign extension)*/
                   1142:                        if (ip->osize == 'L') {
                   1143:                                if (igetl(map, ip, &ip->imm) < 0)
                   1144:                                        return 0;
                   1145:                        } else {
                   1146:                                if (igets(map, ip, &s)< 0)
                   1147:                                        return 0;
                   1148:                                ip->imm = s&0xffff;
                   1149:                        }
                   1150:                        break;
                   1151:                case Awd:       /* Address-sized immediate (no sign extension)*/
                   1152:                        if (ip->asize == 'E') {
                   1153:                                if (igetl(map, ip, &ip->imm) < 0)
                   1154:                                        return 0;
                   1155:                        } else {
                   1156:                                if (igets(map, ip, &s)< 0)
                   1157:                                        return 0;
                   1158:                                ip->imm = s&0xffff;
                   1159:                        }
                   1160:                        break;
                   1161:                case Iwds:      /* Operand-sized immediate (sign extended) */
                   1162:                        if (ip->osize == 'L') {
                   1163:                                if (igetl(map, ip, &ip->imm) < 0)
                   1164:                                        return 0;
                   1165:                        } else {
                   1166:                                if (igets(map, ip, &s)< 0)
                   1167:                                        return 0;
                   1168:                                if (s&0x8000)
                   1169:                                        ip->imm = s|0xffff0000;
                   1170:                                else
                   1171:                                        ip->imm = s&0xffff;
                   1172:                        }
                   1173:                        ip->jumptype = Iwds;
                   1174:                        break;
                   1175:                case OA:        /* literal 0x0a byte */
                   1176:                        if (igetc(map, ip, &c) < 0)
                   1177:                                return 0;
                   1178:                        if (c != 0x0a)
                   1179:                                goto badop;
                   1180:                        break;
                   1181:                case R0:        /* base register must be R0 */
                   1182:                        if (ip->base != 0)
                   1183:                                goto badop;
                   1184:                        break;
                   1185:                case R1:        /* base register must be R1 */
                   1186:                        if (ip->base != 1)
                   1187:                                goto badop;
                   1188:                        break;
                   1189:                case RMB:       /* R/M field with byte register (/r)*/
                   1190:                        if (igetc(map, ip, &c) < 0)
                   1191:                                return 0;
                   1192:                        if (modrm(map, ip, c) < 0)
                   1193:                                return 0;
                   1194:                        ip->osize = 'B';
                   1195:                        break;
                   1196:                case RM:        /* R/M field with register (/r) */
                   1197:                        if (igetc(map, ip, &c) < 0)
                   1198:                                return 0;
                   1199:                        if (modrm(map, ip, c) < 0)
                   1200:                                return 0;
                   1201:                        break;
                   1202:                case RMOPB:     /* R/M field with op code (/digit) */
                   1203:                        if (igetc(map, ip, &c) < 0)
                   1204:                                return 0;
                   1205:                        if (modrm(map, ip, c) < 0)
                   1206:                                return 0;
                   1207:                        c = ip->reg;            /* secondary op code */
                   1208:                        obase = (Optable*)op->proto;
                   1209:                        ip->osize = 'B';
                   1210:                        goto newop;
                   1211:                case RMOP:      /* R/M field with op code (/digit) */
                   1212:                        if (igetc(map, ip, &c) < 0)
                   1213:                                return 0;
                   1214:                        if (modrm(map, ip, c) < 0)
                   1215:                                return 0;
                   1216:                        c = ip->reg;
                   1217:                        obase = (Optable*)op->proto;
                   1218:                        goto newop;
                   1219:                case FRMOP:     /* FP R/M field with op code (/digit) */
                   1220:                        if (igetc(map, ip, &c) < 0)
                   1221:                                return 0;
                   1222:                        if (modrm(map, ip, c) < 0)
                   1223:                                return 0;
                   1224:                        if ((c&0xc0) == 0xc0)
                   1225:                                c = ip->reg+8;          /* 16 entry table */
                   1226:                        else
                   1227:                                c = ip->reg;
                   1228:                        obase = (Optable*)op->proto;
                   1229:                        goto newop;
                   1230:                case FRMEX:     /* Extended FP R/M field with op code (/digit) */
                   1231:                        if (igetc(map, ip, &c) < 0)
                   1232:                                return 0;
                   1233:                        if (modrm(map, ip, c) < 0)
                   1234:                                return 0;
                   1235:                        if ((c&0xc0) == 0xc0)
                   1236:                                c = (c&0x3f)+8;         /* 64-entry table */
                   1237:                        else
                   1238:                                c = ip->reg;
                   1239:                        obase = (Optable*)op->proto;
                   1240:                        goto newop;
                   1241:                case RMR:       /* R/M register only (mod = 11) */
                   1242:                        if (igetc(map, ip, &c) < 0)
                   1243:                                return 0;
                   1244:                        if ((c&0xc0) != 0xc0) {
                   1245:                                werrstr("invalid R/M register: %x", c);
                   1246:                                return 0;
                   1247:                        }
                   1248:                        if (modrm(map, ip, c) < 0)
                   1249:                                return 0;
                   1250:                        break;
                   1251:                case RMM:       /* R/M register only (mod = 11) */
                   1252:                        if (igetc(map, ip, &c) < 0)
                   1253:                                return 0;
                   1254:                        if ((c&0xc0) == 0xc0) {
                   1255:                                werrstr("invalid R/M memory mode: %x", c);
                   1256:                                return 0;
                   1257:                        }
                   1258:                        if (modrm(map, ip, c) < 0)
                   1259:                                return 0;
                   1260:                        break;
                   1261:                case PTR:       /* Seg:Displacement addr (ptr16:16 or ptr16:32) */
                   1262:                        if (igets(map, ip, (ushort*)&ip->seg) < 0)
                   1263:                                return 0;
                   1264:                        if (ip->osize == 'L') {
                   1265:                                if (igetl(map, ip, &ip->disp) < 0)
                   1266:                                        return 0;
                   1267:                        } else {
                   1268:                                if (igets(map, ip, &s)< 0)
                   1269:                                        return 0;
                   1270:                                ip->disp = s&0xffff;
                   1271:                        }
                   1272:                        ip->jumptype = PTR;
                   1273:                        break;
                   1274:                case AUX:       /* Multi-byte op code - Auxiliary table */
                   1275:                        obase = (Optable*)op->proto;
                   1276:                        if (igetc(map, ip, &c) < 0)
                   1277:                                return 0;
                   1278:                        goto newop;
                   1279:                case PRE:       /* Instr Prefix */
                   1280:                        ip->prefix = (char*)op->proto;
                   1281:                        if (igetc(map, ip, &c) < 0)
                   1282:                                return 0;
                   1283:                        goto newop;
                   1284:                case SEG:       /* Segment Prefix */
                   1285:                        ip->segment = (char*)op->proto;
                   1286:                        if (igetc(map, ip, &c) < 0)
                   1287:                                return 0;
                   1288:                        goto newop;
                   1289:                case OPOVER:    /* Operand size override */
                   1290:                        ip->osize = 'W';
                   1291:                        if (igetc(map, ip, &c) < 0)
                   1292:                                return 0;
                   1293:                        goto newop;
                   1294:                case ADDOVER:   /* Address size override */
                   1295:                        ip->asize = 0;
                   1296:                        if (igetc(map, ip, &c) < 0)
                   1297:                                return 0;
                   1298:                        goto newop;
                   1299:                case JUMP:      /* mark instruction as JUMP or RET */
                   1300:                case RET:
                   1301:                        ip->jumptype = op->operand[i];
                   1302:                        break;
                   1303:                default:
                   1304:                        werrstr("bad operand type %d", op->operand[i]);
                   1305:                        return 0;
                   1306:                }
                   1307:        }
                   1308:        return op;
                   1309: }
                   1310: 
                   1311: static void
                   1312: bprint(Instr *ip, char *fmt, ...)
                   1313: {
                   1314:        ip->curr = doprint(ip->curr, ip->end, fmt, (&fmt+1));
                   1315: }
                   1316: 
                   1317: /*
                   1318:  *     if 32-bit registers are to be named E<rr>, macro ANAME should
                   1319:  *     always return ip->asize and ONAME should return a 'E' when
                   1320:  *     when ip->osize == 'L'.  The macros should return a null character
                   1321:  *     when 32-bit registers are ddesignated by <rr>.
                   1322:  */
                   1323: #define        ANAME(ip)       0
                   1324: #define        ONAME(ip)       ((ip)->osize == 'L' ? 0 : 0)
                   1325: 
                   1326: static char *reg[] =  {
                   1327: [AX]   "AX",
                   1328: [CX]   "CX",
                   1329: [DX]   "DX",
                   1330: [BX]   "BX",
                   1331: [SP]   "SP",
                   1332: [BP]   "BP",
                   1333: [SI]   "SI",
                   1334: [DI]   "DI",
                   1335: };
                   1336: 
                   1337: static char *breg[] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" };
                   1338: static char *sreg[] = { "ES", "CS", "SS", "DS", "FS", "GS" };
                   1339: 
                   1340: static void
                   1341: plocal(Instr *ip)
                   1342: {
                   1343:        int ret, offset;
                   1344:        Symbol s;
                   1345:        char *reg;
                   1346: 
                   1347:        offset = ip->disp;
                   1348:        if (!findsym(ip->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) {
                   1349:                bprint(ip, "%lux(SP)", offset);
                   1350:                return;
                   1351:        }
                   1352: 
                   1353:        if (s.value > ip->disp) {
                   1354:                ret = getauto(&s, s.value-ip->disp-mach->szaddr, CAUTO, &s);
                   1355:                reg = "(SP)";
                   1356:        } else {
                   1357:                offset -= s.value;
                   1358:                ret = getauto(&s, offset, CPARAM, &s);
                   1359:                reg = "(FP)";
                   1360:        }
                   1361:        if (ret)
                   1362:                bprint(ip, "%s+", s.name);
                   1363:        else
                   1364:                offset = ip->disp;
                   1365:        bprint(ip, "%lux%s", offset, reg);
                   1366: }
                   1367: 
                   1368: static void
                   1369: pea(Instr *ip)
                   1370: {
                   1371:        if (ip->mod == 3) {
                   1372:                if (ip->osize == 'B')
                   1373:                        bprint(ip, breg[ip->base]);
                   1374:                else
                   1375:                        bprint(ip, "%c%s", ANAME(ip), reg[ip->base]);
                   1376:                return;
                   1377:        }
                   1378:        if (ip->segment)
                   1379:                bprint(ip, ip->segment);
                   1380:        if (ip->asize == 'E' && ip->base == SP)
                   1381:                plocal(ip);
                   1382:        else {
                   1383:                bprint(ip,"%lux", ip->disp);
                   1384:                if (ip->base >= 0)
                   1385:                        bprint(ip,"(%c%s)", ANAME(ip), reg[ip->base]);
                   1386:        }
                   1387:        if (ip->index >= 0)
                   1388:                bprint(ip,"(%c%s*%d)", ANAME(ip), reg[ip->index], 1<<ip->ss);
                   1389: }
                   1390: 
                   1391: static void
                   1392: immediate(Instr *ip, long val)
                   1393: {
                   1394:        Symbol s;
                   1395:        long w;
                   1396: 
                   1397:        if (findsym(val, CANY, &s)) {
                   1398:                w = val - s.value;
                   1399:                if (w < 0)
                   1400:                        w = -w;
                   1401:                if (w < 4096) {
                   1402:                        if (w)
                   1403:                                bprint(ip, "%s+%lux(SB)", s.name, w);
                   1404:                        else
                   1405:                                bprint(ip, "%s(SB)", s.name);
                   1406:                        return;
                   1407:                }
                   1408:        }
                   1409:        bprint(ip, "%lux", val);
                   1410: }
                   1411: 
                   1412: static void
                   1413: prinstr(Instr *ip, char *fmt)
                   1414: {
                   1415:        if (ip->prefix)
                   1416:                bprint(ip, "%s ", ip->prefix);
                   1417:        for (; *fmt && ip->curr < ip->end; fmt++) {
                   1418:                if (*fmt != '%')
                   1419:                        *ip->curr++ = *fmt;
                   1420:                else switch(*++fmt)
                   1421:                {
                   1422:                case '%':
                   1423:                        *ip->curr++ = '%';
                   1424:                        break;
                   1425:                case 'A':
                   1426:                        bprint(ip, "%c", ANAME(ip));
                   1427:                        break;
                   1428:                case 'C':
                   1429:                        bprint(ip, "CR%d", ip->reg);
                   1430:                        break;
                   1431:                case 'D':
                   1432:                        if (ip->reg < 4 || ip->reg == 6 || ip->reg == 7)
                   1433:                                bprint(ip, "DR%d",ip->reg);
                   1434:                        else
                   1435:                                bprint(ip, "???");
                   1436:                        break;
                   1437:                case 'I':
                   1438:                        bprint(ip, "$");
                   1439:                        immediate(ip, ip->imm2);
                   1440:                        break;
                   1441:                case 'O':
                   1442:                        bprint(ip,"%c", ONAME(ip));
                   1443:                        break;
                   1444:                case 'i':
                   1445:                        bprint(ip, "$");
                   1446:                        immediate(ip,ip->imm);
                   1447:                        break;
                   1448:                case 'R':
                   1449:                        bprint(ip, "%c%s", ONAME(ip), reg[ip->reg]);
                   1450:                        break;
                   1451:                case 'S':
                   1452:                        bprint(ip, "%c", ip->osize);
                   1453:                        break;
                   1454:                case 'T':
                   1455:                        if (ip->reg == 6 || ip->reg == 7)
                   1456:                                bprint(ip, "TR%d",ip->reg);
                   1457:                        else
                   1458:                                bprint(ip, "???");
                   1459:                        break;
                   1460:                case 'X':
                   1461:                        if (ip->osize == 'L')
                   1462:                                bprint(ip,"CWDE");
                   1463:                        else
                   1464:                                bprint(ip, "CBW");
                   1465:                        break;
                   1466:                case 'd':
                   1467:                        bprint(ip,"%lux:%lux",ip->seg,ip->disp);
                   1468:                        break;
                   1469:                case 'e':
                   1470:                        pea(ip);
                   1471:                        break;
                   1472:                case 'f':
                   1473:                        bprint(ip, "F%d", ip->base);
                   1474:                        break;
                   1475:                case 'g':
                   1476:                        if (ip->reg < 6)
                   1477:                                bprint(ip,"%s",sreg[ip->reg]);
                   1478:                        else
                   1479:                                bprint(ip,"???");
                   1480:                        break;
                   1481:                case 'p':
                   1482:                        immediate(ip, ip->imm+ip->addr+ip->n);
                   1483:                        break;
                   1484:                case 'r':
                   1485:                        if (ip->osize == 'B')
                   1486:                                bprint(ip,"%s",breg[ip->reg]);
                   1487:                        else
                   1488:                                bprint(ip, reg[ip->reg]);
                   1489:                        break;
                   1490:                case 'x':
                   1491:                        if (ip->osize == 'L')
                   1492:                                bprint(ip,"CDQ");
                   1493:                        else
                   1494:                                bprint(ip, "CWD");
                   1495:                        break;
                   1496:                default:
                   1497:                        bprint(ip, "%%%c", *fmt);
                   1498:                        break;
                   1499:                }
                   1500:        }
                   1501:        *ip->curr = 0;          /* there's always room for 1 byte */
                   1502: }
                   1503: 
                   1504: static int
                   1505: i386inst(Map *map, ulong pc, char modifier, char *buf, int n)
                   1506: {
                   1507:        Instr   instr;
                   1508:        Optable *op;
                   1509: 
                   1510:        USED(modifier);
                   1511:        op = mkinstr(map, &instr, pc);
                   1512:        if (op == 0) {
                   1513:                if (n >= ERRLEN)
                   1514:                        errstr(buf);
                   1515:                else
                   1516:                        snprint(buf,n,"%r");
                   1517:                return -1;
                   1518:        }
                   1519:        instr.curr = buf;
                   1520:        instr.end = buf+n-1;
                   1521:        prinstr(&instr, op->proto);
                   1522:        return instr.n;
                   1523: }
                   1524: 
                   1525: static int
                   1526: i386das(Map *map, ulong pc, char *buf, int n)
                   1527: {
                   1528:        Instr   instr;
                   1529:        int i;
                   1530: 
                   1531:        if (mkinstr(map, &instr, pc) == 0) {
                   1532:                if (n >= ERRLEN)
                   1533:                        errstr(buf);
                   1534:                else
                   1535:                        snprint(buf,n,"%r");
                   1536:                return -1;
                   1537:        }
                   1538:        for(i = 0; i < instr.n && n > 2; i++) {
                   1539:                _hexify(buf, instr.mem[i], 1);
                   1540:                buf += 2;
                   1541:                n -= 2;
                   1542:        }
                   1543:        *buf = 0;
                   1544:        return instr.n;
                   1545: }
                   1546: 
                   1547: static int
                   1548: i386instlen(Map *map, ulong pc)
                   1549: {
                   1550:        Instr i;
                   1551: 
                   1552:        if (mkinstr(map, &i, pc))
                   1553:                return i.n;
                   1554:        return -1;
                   1555: }
                   1556: 
                   1557: static int
                   1558: i386foll(Map *map, ulong pc, Rgetter rget, ulong *foll)
                   1559: {
                   1560:        Instr i;
                   1561:        Optable *op;
                   1562:        ushort s;
                   1563:        ulong l, addr;
                   1564:        int n;
                   1565: 
                   1566:        op = mkinstr(map, &i, pc);
                   1567:        if (!op)
                   1568:                return -1;
                   1569: 
                   1570:        n = 0;
                   1571:        switch(i.jumptype)
                   1572:        {
                   1573:        case RET:               /* RETURN or LEAVE */
                   1574:        case Iw:                /* RETURN */
                   1575:                if (strcmp(op->proto, "LEAVE") == 0) {
                   1576:                        if (get4(map, (*rget)(map, "BP"), (long*)&l) < 0)
                   1577:                                return -1;
                   1578:                } else if (get4(map, (*rget)(map, mach->sp), (long*)&l) < 0)
                   1579:                        return -1;
                   1580:                foll[0] = l;
                   1581:                return 1;
                   1582:        case Iwds:              /* pc relative JUMP or CALL*/
                   1583:        case Jbs:               /* pc relative JUMP or CALL */
                   1584:                foll[0] = pc+i.imm+i.n;
                   1585:                n = 1;
                   1586:                break;
                   1587:        case PTR:               /* seg:displacement JUMP or CALL */
                   1588:                foll[0] = (i.seg<<4)+i.disp;
                   1589:                return 1;
                   1590:        case JUMP:              /* JUMP or CALL EA */
                   1591:                        /* calculate the effective address */
                   1592:                addr = i.disp;
                   1593:                if (i.base >= 0) {
                   1594:                        if (get4(map, (*rget)(map, reg[i.base]), (long*)&l) < 0)
                   1595:                                return -1;
                   1596:                        addr += l;
                   1597:                }
                   1598:                if (i.index >= 0) {
                   1599:                        if (get4(map, (*rget)(map, reg[i.index]), (long*)&l) < 0)
                   1600:                                return -1;
                   1601:                        addr += l*(1<<i.ss);
                   1602:                }
                   1603:                        /* now retrieve a seg:disp value at that address */
                   1604:                if (get2(map, addr, &s) < 0)            /* seg */
                   1605:                        return -1;
                   1606:                foll[0] = s<<4;
                   1607:                addr += 2;
                   1608:                if (i.asize == 'L') {
                   1609:                        if (get4(map, addr, (long*)&l) < 0)     /* disp32 */
                   1610:                                return -1;
                   1611:                        foll[0] += l;
                   1612:                } else {                                        /* disp16 */
                   1613:                        if (get2(map, addr, &s) < 0)
                   1614:                                return -1;
                   1615:                        foll[0] += s;
                   1616:                }
                   1617:                return 1;
                   1618:        default:
                   1619:                break;
                   1620:        }               
                   1621:        if (strncmp(op->proto,"JMP", 3) == 0 || strncmp(op->proto,"CALL", 4) == 0)
                   1622:                return 1;
                   1623:        foll[n++] = pc+i.n;
                   1624:        return n;
                   1625: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.