Annotation of lucent/sys/src/libmach/8db.c, revision 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.