URI:
       tmach386.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tmach386.c (62651B)
       ---
            1 /*
            2  * 386 definition
            3  */
            4 #include <u.h>
            5 #include <libc.h>
            6 #include <bio.h>
            7 #include <mach.h>
            8 #include "ureg386.h"
            9 
           10 #define        REGOFF(x)        (ulong)(&((struct Ureg *) 0)->x)
           11 
           12 #define        REGSIZE                sizeof(struct Ureg)
           13 #define        FP_CTL(x)                (REGSIZE+4*(x))
           14 #define        FP_REG(x)                (FP_CTL(7)+10*(x))
           15 #define        FPREGSIZE        (6*4+8*10)
           16 
           17 /*
           18  * i386-specific debugger interface
           19  */
           20 
           21         char        *i386excep(Map*, Regs*);
           22 
           23 /*
           24 static        int        i386trace(Map*, ulong, ulong, ulong, Tracer);
           25 static        ulong        i386frame(Map*, ulong, ulong, ulong, ulong);
           26 */
           27         int        i386foll(Map*, Regs*, u64int, u64int*);
           28         int        i386hexinst(Map*, u64int, char*, int);
           29         int        i386das(Map*, u64int, char, char*, int);
           30         int        i386instlen(Map*, u64int);
           31         int        i386unwind(Map*, Regs*, u64int*, Symbol*);
           32 
           33 static char *i386windregs[] = {
           34         "PC",
           35         "SP",
           36         "BP",
           37         "AX",
           38         "CX",
           39         "DX",
           40         "BX",
           41         "SI",
           42         "DI",
           43         0,
           44 };
           45 
           46 static        Regdesc i386reglist[] = {
           47         {"DI",                REGOFF(di),        RINT, 'X'},
           48         {"SI",                REGOFF(si),        RINT, 'X'},
           49         {"BP",                REGOFF(bp),        RINT, 'X'},
           50         {"BX",                REGOFF(bx),        RINT, 'X'},
           51         {"DX",                REGOFF(dx),        RINT, 'X'},
           52         {"CX",                REGOFF(cx),        RINT, 'X'},
           53         {"AX",                REGOFF(ax),        RINT, 'X'},
           54         {"GS",                REGOFF(gs),        RINT, 'X'},
           55         {"FS",                REGOFF(fs),        RINT, 'X'},
           56         {"ES",                REGOFF(es),        RINT, 'X'},
           57         {"DS",                REGOFF(ds),        RINT, 'X'},
           58         {"TRAP",        REGOFF(trap),         RINT, 'X'},
           59         {"ECODE",        REGOFF(ecode),        RINT, 'X'},
           60         {"PC",                REGOFF(pc),                RINT, 'X'},
           61         {"CS",                REGOFF(cs),        RINT, 'X'},
           62         {"EFLAGS",        REGOFF(flags),        RINT, 'X'},
           63         {"SP",                REGOFF(sp),                RINT, 'X'},
           64         {"SS",                REGOFF(ss),        RINT, 'X'},
           65 
           66         {"E0",                FP_CTL(0),        RFLT, 'X'},
           67         {"E1",                FP_CTL(1),        RFLT, 'X'},
           68         {"E2",                FP_CTL(2),        RFLT, 'X'},
           69         {"E3",                FP_CTL(3),        RFLT, 'X'},
           70         {"E4",                FP_CTL(4),        RFLT, 'X'},
           71         {"E5",                FP_CTL(5),        RFLT, 'X'},
           72         {"E6",                FP_CTL(6),        RFLT, 'X'},
           73         {"F0",                FP_REG(7),        RFLT, '3'},
           74         {"F1",                FP_REG(6),        RFLT, '3'},
           75         {"F2",                FP_REG(5),        RFLT, '3'},
           76         {"F3",                FP_REG(4),        RFLT, '3'},
           77         {"F4",                FP_REG(3),        RFLT, '3'},
           78         {"F5",                FP_REG(2),        RFLT, '3'},
           79         {"F6",                FP_REG(1),        RFLT, '3'},
           80         {"F7",                FP_REG(0),        RFLT, '3'},
           81         {  0 }
           82 };
           83 
           84 Mach mach386 =
           85 {
           86         "386",
           87         M386,                /* machine type */
           88         i386reglist,        /* register list */
           89         REGSIZE,        /* size of registers in bytes */
           90         FPREGSIZE,        /* size of fp registers in bytes */
           91         "PC",                /* name of PC */
           92         "SP",                /* name of SP */
           93         "BP",                /* name of FP */
           94         0,                /* link register */
           95         "setSB",        /* static base register name (bogus anyways) */
           96         0,                /* static base register value */
           97         0x1000,                /* page size */
           98         0x80100000,        /* kernel base */
           99         0,                /* kernel text mask */
          100         1,                /* quantization of pc */
          101         4,                /* szaddr */
          102         4,                /* szreg */
          103         4,                /* szfloat */
          104         8,                /* szdouble */
          105 
          106         i386windregs,        /* locations unwound in stack trace */
          107         9,
          108 
          109         {0xCC, 0, 0, 0},        /* break point: INT 3 */
          110         1,                        /* break point size */
          111 
          112         i386foll,                /* following addresses */
          113         i386excep,                /* print exception */
          114         i386unwind,                /* stack unwind */
          115 
          116         leswap2,                        /* convert short to local byte order */
          117         leswap4,                        /* convert long to local byte order */
          118         leswap8,                        /* convert vlong to local byte order */
          119         leieeeftoa32,                /* single precision float pointer */
          120         leieeeftoa64,                /* double precision float pointer */
          121         leieeeftoa80,                /* long double precision floating point */
          122 
          123         i386das,                /* dissembler */
          124         i386das,                /* plan9-format disassembler */
          125         0,                        /* commercial disassembler */
          126         i386hexinst,                /* print instruction */
          127         i386instlen,                /* instruction size calculation */
          128 };
          129 
          130 /*
          131  * The wrapper code around Linux system calls
          132  * saves AX on the stack before calling some calls
          133  * (at least, __libc_nanosleep), when running in
          134  * threaded programs.
          135  */
          136 static void
          137 syscallhack(Map *map, Regs *regs, int *spoff)
          138 {
          139         u64int pc;
          140         char buf[60];
          141 
          142         rget(regs, "PC", &pc);
          143         if(i386das(map, pc-2, 0, buf, sizeof buf) != 2 || strncmp(buf, "INTB\t$", 6) != 0)
          144                 return;
          145         if(i386das(map, pc, 0, buf, sizeof buf) != 2 || strcmp(buf, "MOVL\tDX,BX") != 0)
          146                 return;
          147         if(i386das(map, pc+2, 0, buf, sizeof buf) != 3 || strcmp(buf, "XCHGL\tAX,0(SP)") != 0)
          148                 return;
          149         *spoff += 4;
          150 }
          151 
          152 int
          153 i386unwind(Map *map, Regs *regs, u64int *next, Symbol *sym)
          154 {
          155         int i, isp, ipc, ibp, havebp, n, spoff, off[9];
          156         ulong pc;
          157         u32int v;
          158         char buf[60], *p;
          159 
          160 /*print("i386unwind %s\n", sym ? sym->name : nil); */
          161         isp = windindex("SP");
          162         ipc = windindex("PC");
          163         ibp = windindex("BP");
          164         if(isp < 0 || ipc < 0 || ibp < 0){
          165                 werrstr("i386unwind: cannot happen");
          166                 return -1;
          167         }
          168 
          169         /*
          170          * Disassemble entry to figure out
          171          * where values have been saved.
          172          * Perhaps should disassemble exit path
          173          * instead -- a random walk on the code
          174          * should suffice to get us to a RET.
          175          */
          176         if(sym){
          177                 pc = sym->loc.addr;
          178 /*print("startpc %lux\n", pc); */
          179                 memset(off, 0xff, sizeof off);
          180                 spoff = 0;
          181                 havebp = 0;
          182                 for(;;){
          183                         if((n = i386das(map, pc, 0, buf, sizeof buf)) < 0)
          184                                 break;
          185 /*print("%s\n", buf); */
          186                         pc += n;
          187                         if(strncmp(buf, "PUSHL\t", 6) == 0){
          188                                 spoff += 4;
          189                                 if((i = windindex(buf+6)) >= 0)
          190                                         off[i] = spoff;
          191                         }else if(strcmp(buf, "MOVL\tSP,BP") == 0 && spoff == 4 && off[ibp] == 4){
          192                                 havebp = 1;
          193                         }else if(strncmp(buf, "SUBL\t$", 6) == 0){
          194                                 if((p = strrchr(buf, ',')) && strcmp(p, ",SP") == 0){
          195 /*print("spoff %s\n", buf+6); */
          196                                         spoff += strtol(buf+6, 0, 16);
          197                                 }
          198                                 break;
          199                         }else if(strncmp(buf, "XORL\t", 5) == 0 || strncmp(buf, "MOVL\t", 5) == 0){
          200                                 /*
          201                                  * Hope these are rescheduled non-prologue instructions
          202                                  * like XORL AX, AX or MOVL $0x3, AX and thus ignorable.
          203                                  */
          204                         }else
          205                                 break;
          206                 }
          207 
          208                 syscallhack(map, regs, &spoff);
          209 
          210                 if(havebp){
          211 /*print("havebp\n"); */
          212                         rget(regs, "BP", &next[isp]);
          213                         get4(map, next[isp], &v);
          214                         next[ibp] = v;
          215                         next[isp] += 4;
          216                 }else{
          217                         rget(regs, "SP", &next[isp]);
          218 /*print("old sp %lux + %d\n", next[isp], spoff); */
          219                         next[isp] += spoff;
          220                 }
          221                 for(i=0; i<nelem(off); i++)
          222                         if(off[i] != -1){
          223                                 get4(map, next[isp]-off[i], &v);
          224                                 next[i] = v;
          225                         }
          226 
          227                 if(get4(map, next[isp], &v) < 0)
          228                         return -1;
          229 /*print("new pc %lux => %lux\n", next[isp], v); */
          230                 next[ipc] = v;
          231                 next[isp] += 4;
          232                 return 0;
          233         }
          234 
          235         /*
          236          * Rely on bp chaining
          237          */
          238         if(rget(regs, "BP", &next[isp]) < 0
          239         || get4(map, next[isp], &v) < 0)
          240                 return -1;
          241         next[ibp] = v;
          242         next[isp] += 4;
          243         if(get4(map, next[isp], &v) < 0)
          244                 return -1;
          245         next[ipc] = v;
          246         next[isp] += 4;
          247         return 0;
          248 }
          249 
          250 /*static        char        STARTSYM[] =        "_main"; */
          251 /*static        char        PROFSYM[] =        "_mainp"; */
          252 static        char        FRAMENAME[] =        ".frame";
          253 static char *excname[] =
          254 {
          255         "divide error",                        /* 0 */
          256         "debug exception",                /* 1 */
          257         0,0,                                /* 2, 3 */
          258         "overflow",                        /* 4 */
          259         "bounds check",                        /* 5 */
          260         "invalid opcode",                /* 6 */
          261         "math coprocessor emulation",        /* 7 */
          262         "double fault",                        /* 8 */
          263         "math coprocessor overrun",        /* 9 */
          264         "invalid TSS",                        /* 10 */
          265         "segment not present",                /* 11 */
          266         "stack exception",                /* 12 */
          267         "general protection violation",        /* 13 */
          268         "page fault",                        /* 14 */
          269         0,                                /* 15 */
          270         "math coprocessor error",        /* 16 */
          271         0,0,0,0,0,0,0,                        /* 17-23 */
          272         "clock",                        /* 24 */
          273         "keyboard",                        /* 25 */
          274         0,                                /* 26 */
          275         "modem status",                        /* 27 */
          276         "serial line status",                /* 28 */
          277         0,                                /* 29 */
          278         "floppy disk",                        /* 30 */
          279         0,0,0,0,0,                        /* 31-35 */
          280         "mouse",                        /* 36 */
          281         "math coprocessor",                /* 37 */
          282         "hard disk",                        /* 38 */
          283         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,/* 39-54 */
          284         0,0,0,0,0,0,0,0,0,                /* 55-63 */
          285         "system call",                        /* 64 */
          286 };
          287 
          288 char*
          289 i386excep(Map *map, Regs *regs)
          290 {
          291         u64int c;
          292         u64int pc;
          293         static char buf[16];
          294 
          295         if(rget(regs, "TRAP", &c) < 0)
          296                 return "no trap register";
          297 
          298         if(c > 64 || excname[c] == 0) {
          299                 if (c == 3) {
          300                         if (rget(regs, "PC", &pc) >= 0)
          301                         if (get1(map, pc, (uchar*)buf, mach->bpsize) > 0)
          302                         if (memcmp(buf, mach->bpinst, mach->bpsize) == 0)
          303                                 return "breakpoint";
          304                 }
          305                 sprint(buf, "exception %ld", c);
          306                 return buf;
          307         } else
          308                 return excname[c];
          309 }
          310 
          311         /* I386/486 - Disassembler and related functions */
          312 
          313 /*
          314  *  an instruction
          315  */
          316 typedef struct Instr Instr;
          317 struct        Instr
          318 {
          319         uchar        mem[1+1+1+1+2+1+1+4+4];                /* raw instruction */
          320         uvlong        addr;                /* address of start of instruction */
          321         int        n;                /* number of bytes in instruction */
          322         char        *prefix;        /* instr prefix */
          323         char        *segment;        /* segment override */
          324         uchar        jumptype;        /* set to the operand type for jump/ret/call */
          325         uchar        amd64;
          326         uchar        rex;                /* REX prefix (or zero) */
          327         char        osize;                /* 'W' or 'L' (or 'Q' on amd64) */
          328         char        asize;                /* address size 'W' or 'L' (or 'Q' or amd64) */
          329         uchar        mod;                /* bits 6-7 of mod r/m field */
          330         uchar        reg;                /* bits 3-5 of mod r/m field */
          331         char        ss;                /* bits 6-7 of SIB */
          332         schar        index;                /* bits 3-5 of SIB */
          333         schar        base;                /* bits 0-2 of SIB */
          334         char        rip;                /* RIP-relative in amd64 mode */
          335         uchar        opre;                /* f2/f3 could introduce media */
          336         short        seg;                /* segment of far address */
          337         uint32        disp;                /* displacement */
          338         uint32         imm;                /* immediate */
          339         uint32         imm2;                /* second immediate operand */
          340         uvlong        imm64;                /* big immediate */
          341         char        *curr;                /* fill level in output buffer */
          342         char        *end;                /* end of output buffer */
          343         char        *err;                /* error message */
          344 };
          345 
          346         /* 386 register (ha!) set */
          347 enum{
          348         AX=0,
          349         CX,
          350         DX,
          351         BX,
          352         SP,
          353         BP,
          354         SI,
          355         DI,
          356 
          357         /* amd64 */
          358         /* be careful: some unix system headers #define R8, R9, etc */
          359         AMD64_R8,
          360         AMD64_R9,
          361         AMD64_R10,
          362         AMD64_R11,
          363         AMD64_R12,
          364         AMD64_R13,
          365         AMD64_R14,
          366         AMD64_R15
          367 };
          368 
          369         /* amd64 rex extension byte */
          370 enum{
          371         REXW                = 1<<3,        /* =1, 64-bit operand size */
          372         REXR                = 1<<2,        /* extend modrm reg */
          373         REXX                = 1<<1,        /* extend sib index */
          374         REXB                = 1<<0        /* extend modrm r/m, sib base, or opcode reg */
          375 };
          376 
          377         /* Operand Format codes */
          378 /*
          379 %A        -        address size register modifier (!asize -> 'E')
          380 %C        -        Control register CR0/CR1/CR2
          381 %D        -        Debug register DR0/DR1/DR2/DR3/DR6/DR7
          382 %I        -        second immediate operand
          383 %O        -        Operand size register modifier (!osize -> 'E')
          384 %T        -        Test register TR6/TR7
          385 %S        -        size code ('W' or 'L')
          386 %W        -        Weird opcode: OSIZE == 'W' => "CBW"; else => "CWDE"
          387 %d        -        displacement 16-32 bits
          388 %e        -        effective address - Mod R/M value
          389 %f        -        floating point register F0-F7 - from Mod R/M register
          390 %g        -        segment register
          391 %i        -        immediate operand 8-32 bits
          392 %p        -        PC-relative - signed displacement in immediate field
          393 %r        -        Reg from Mod R/M
          394 %w        -        Weird opcode: OSIZE == 'W' => "CWD"; else => "CDQ"
          395 */
          396 
          397 typedef struct Optable Optable;
          398 struct Optable
          399 {
          400         char        operand[2];
          401         void        *proto;                /* actually either (char*) or (Optable*) */
          402 };
          403         /* Operand decoding codes */
          404 enum {
          405         Ib = 1,                        /* 8-bit immediate - (no sign extension)*/
          406         Ibs,                        /* 8-bit immediate (sign extended) */
          407         Jbs,                        /* 8-bit sign-extended immediate in jump or call */
          408         Iw,                        /* 16-bit immediate -> imm */
          409         Iw2,                        /* 16-bit immediate -> imm2 */
          410         Iwd,                        /* Operand-sized immediate (no sign extension)*/
          411         Iwdq,                        /* Operand-sized immediate, possibly 64 bits */
          412         Awd,                        /* Address offset */
          413         Iwds,                        /* Operand-sized immediate (sign extended) */
          414         RM,                        /* Word or int32 R/M field with register (/r) */
          415         RMB,                        /* Byte R/M field with register (/r) */
          416         RMOP,                        /* Word or int32 R/M field with op code (/digit) */
          417         RMOPB,                        /* Byte R/M field with op code (/digit) */
          418         RMR,                        /* R/M register only (mod = 11) */
          419         RMM,                        /* R/M memory only (mod = 0/1/2) */
          420         Op_R0,                        /* Base reg of Mod R/M is literal 0x00 */
          421         Op_R1,                        /* Base reg of Mod R/M is literal 0x01 */
          422         FRMOP,                        /* Floating point R/M field with opcode */
          423         FRMEX,                        /* Extended floating point R/M field with opcode */
          424         JUMP,                        /* Jump or Call flag - no operand */
          425         RET,                        /* Return flag - no operand */
          426         OA,                        /* literal 0x0a byte */
          427         PTR,                        /* Seg:Displacement addr (ptr16:16 or ptr16:32) */
          428         AUX,                        /* Multi-byte op code - Auxiliary table */
          429         AUXMM,                        /* multi-byte op code - auxiliary table chosen by prefix */
          430         PRE,                        /* Instr Prefix */
          431         OPRE,                        /* Instr Prefix or media op extension */
          432         SEG,                        /* Segment Prefix */
          433         OPOVER,                        /* Operand size override */
          434         ADDOVER,                /* Address size override */
          435 };
          436 
          437 static Optable optab0F00[8]=
          438 {
          439 [0x00] =        { 0,0,                "MOVW        LDT,%e" },
          440 [0x01] =        { 0,0,                "MOVW        TR,%e" },
          441 [0x02] =        { 0,0,                "MOVW        %e,LDT" },
          442 [0x03] =        { 0,0,                "MOVW        %e,TR" },
          443 [0x04] =        { 0,0,                "VERR        %e" },
          444 [0x05] =        { 0,0,                "VERW        %e" },
          445 };
          446 
          447 static Optable optab0F01[8]=
          448 {
          449 [0x00] =        { 0,0,                "MOVL        GDTR,%e" },
          450 [0x01] =        { 0,0,                "MOVL        IDTR,%e" },
          451 [0x02] =        { 0,0,                "MOVL        %e,GDTR" },
          452 [0x03] =        { 0,0,                "MOVL        %e,IDTR" },
          453 [0x04] =        { 0,0,                "MOVW        MSW,%e" },        /* word */
          454 [0x06] =        { 0,0,                "MOVW        %e,MSW" },        /* word */
          455 [0x07] =        { 0,0,                "INVLPG        %e" },                /* or SWAPGS */
          456 };
          457 
          458 static Optable optab0F01F8[1]=
          459 {
          460 [0x00] =        { 0,0,                "SWAPGS" },
          461 };
          462 
          463 /* 0F71 */
          464 /* 0F72 */
          465 /* 0F73 */
          466 
          467 static Optable optab0FAE[8]=
          468 {
          469 [0x00] =        { 0,0,                "FXSAVE        %e" },
          470 [0x01] =        { 0,0,                "FXRSTOR        %e" },
          471 [0x02] =        { 0,0,                "LDMXCSR        %e" },
          472 [0x03] =        { 0,0,                "STMXCSR        %e" },
          473 [0x05] =        { 0,0,                "LFENCE" },
          474 [0x06] =        { 0,0,                "MFENCE" },
          475 [0x07] =        { 0,0,                "SFENCE" },
          476 };
          477 
          478 /* 0F18 */
          479 /* 0F0D */
          480 
          481 static Optable optab0FBA[8]=
          482 {
          483 [0x04] =        { Ib,0,                "BT%S        %i,%e" },
          484 [0x05] =        { Ib,0,                "BTS%S        %i,%e" },
          485 [0x06] =        { Ib,0,                "BTR%S        %i,%e" },
          486 [0x07] =        { Ib,0,                "BTC%S        %i,%e" },
          487 };
          488 
          489 static Optable optab0F0F[256]=
          490 {
          491 [0x0c] =        { 0,0,                "PI2FW        %m,%M" },
          492 [0x0d] =        { 0,0,                "PI2L        %m,%M" },
          493 [0x1c] =        { 0,0,                "PF2IW        %m,%M" },
          494 [0x1d] =        { 0,0,                "PF2IL        %m,%M" },
          495 [0x8a] =        { 0,0,                "PFNACC        %m,%M" },
          496 [0x8e] =        { 0,0,                "PFPNACC        %m,%M" },
          497 [0x90] =        { 0,0,                "PFCMPGE        %m,%M" },
          498 [0x94] =        { 0,0,                "PFMIN        %m,%M" },
          499 [0x96] =        { 0,0,                "PFRCP        %m,%M" },
          500 [0x97] =        { 0,0,                "PFRSQRT        %m,%M" },
          501 [0x9a] =        { 0,0,                "PFSUB        %m,%M" },
          502 [0x9e] =        { 0,0,                "PFADD        %m,%M" },
          503 [0xa0] =        { 0,0,                "PFCMPGT        %m,%M" },
          504 [0xa4] =        { 0,0,                "PFMAX        %m,%M" },
          505 [0xa6] =        { 0,0,                "PFRCPIT1        %m,%M" },
          506 [0xa7] =        { 0,0,                "PFRSQIT1        %m,%M" },
          507 [0xaa] =        { 0,0,                "PFSUBR        %m,%M" },
          508 [0xae] =        { 0,0,                "PFACC        %m,%M" },
          509 [0xb0] =        { 0,0,                "PFCMPEQ        %m,%M" },
          510 [0xb4] =        { 0,0,                "PFMUL        %m,%M" },
          511 [0xb6] =        { 0,0,                "PFRCPI2T        %m,%M" },
          512 [0xb7] =        { 0,0,                "PMULHRW        %m,%M" },
          513 [0xbb] =        { 0,0,                "PSWAPL        %m,%M" },
          514 };
          515 
          516 static Optable optab0FC7[8]=
          517 {
          518 [0x01] =        { 0,0,                "CMPXCHG8B        %e" },
          519 };
          520 
          521 static Optable optab660F71[8]=
          522 {
          523 [0x02] =        { Ib,0,                "PSRLW        %i,%X" },
          524 [0x04] =        { Ib,0,                "PSRAW        %i,%X" },
          525 [0x06] =        { Ib,0,                "PSLLW        %i,%X" },
          526 };
          527 
          528 static Optable optab660F72[8]=
          529 {
          530 [0x02] =        { Ib,0,                "PSRLL        %i,%X" },
          531 [0x04] =        { Ib,0,                "PSRAL        %i,%X" },
          532 [0x06] =        { Ib,0,                "PSLLL        %i,%X" },
          533 };
          534 
          535 static Optable optab660F73[8]=
          536 {
          537 [0x02] =        { Ib,0,                "PSRLQ        %i,%X" },
          538 [0x03] =        { Ib,0,                "PSRLO        %i,%X" },
          539 [0x06] =        { Ib,0,                "PSLLQ        %i,%X" },
          540 [0x07] =        { Ib,0,                "PSLLO        %i,%X" },
          541 };
          542 
          543 static Optable optab660F[256]=
          544 {
          545 [0x2B] =        { RM,0,                "MOVNTPD        %x,%e" },
          546 [0x2E] =        { RM,0,                "UCOMISD        %x,%X" },
          547 [0x2F] =        { RM,0,                "COMISD        %x,%X" },
          548 [0x5A] =        { RM,0,                "CVTPD2PS        %x,%X" },
          549 [0x5B] =        { RM,0,                "CVTPS2PL        %x,%X" },
          550 [0x6A] =        { RM,0,                "PUNPCKHLQ %x,%X" },
          551 [0x6B] =        { RM,0,                "PACKSSLW %x,%X" },
          552 [0x6C] =        { RM,0,                "PUNPCKLQDQ %x,%X" },
          553 [0x6D] =        { RM,0,                "PUNPCKHQDQ %x,%X" },
          554 [0x6E] =        { RM,0,                "MOV%S        %e,%X" },
          555 [0x6F] =        { RM,0,                "MOVO        %x,%X" },                /* MOVDQA */
          556 [0x70] =        { RM,Ib,                "PSHUFL        %i,%x,%X" },
          557 [0x71] =        { RMOP,0,                optab660F71 },
          558 [0x72] =        { RMOP,0,                optab660F72 },
          559 [0x73] =        { RMOP,0,                optab660F73 },
          560 [0x7E] =        { RM,0,                "MOV%S        %X,%e" },
          561 [0x7F] =        { RM,0,                "MOVO        %X,%x" },
          562 [0xC4] =        { RM,Ib,                "PINSRW        %i,%e,%X" },
          563 [0xC5] =        { RMR,Ib,                "PEXTRW        %i,%X,%e" },
          564 [0xD4] =        { RM,0,                "PADDQ        %x,%X" },
          565 [0xD5] =        { RM,0,                "PMULLW        %x,%X" },
          566 [0xD6] =        { RM,0,                "MOVQ        %X,%x" },
          567 [0xE6] =        { RM,0,                "CVTTPD2PL        %x,%X" },
          568 [0xE7] =        { RM,0,                "MOVNTO        %X,%e" },
          569 [0xF7] =        { RM,0,                "MASKMOVOU        %x,%X" },
          570 };
          571 
          572 static Optable optabF20F[256]=
          573 {
          574 [0x10] =        { RM,0,                "MOVSD        %x,%X" },
          575 [0x11] =        { RM,0,                "MOVSD        %X,%x" },
          576 [0x2A] =        { RM,0,                "CVTS%S2SD        %e,%X" },
          577 [0x2C] =        { RM,0,                "CVTTSD2S%S        %x,%r" },
          578 [0x2D] =        { RM,0,                "CVTSD2S%S        %x,%r" },
          579 [0x5A] =        { RM,0,                "CVTSD2SS        %x,%X" },
          580 [0x6F] =        { RM,0,                "MOVOU        %x,%X" },
          581 [0x70] =        { RM,Ib,                "PSHUFLW        %i,%x,%X" },
          582 [0x7F] =        { RM,0,                "MOVOU        %X,%x" },
          583 [0xD6] =        { RM,0,                "MOVQOZX        %M,%X" },
          584 [0xE6] =        { RM,0,                "CVTPD2PL        %x,%X" },
          585 };
          586 
          587 static Optable optabF30F[256]=
          588 {
          589 [0x10] =        { RM,0,                "MOVSS        %x,%X" },
          590 [0x11] =        { RM,0,                "MOVSS        %X,%x" },
          591 [0x2A] =        { RM,0,                "CVTS%S2SS        %e,%X" },
          592 [0x2C] =        { RM,0,                "CVTTSS2S%S        %x,%r" },
          593 [0x2D] =        { RM,0,                "CVTSS2S%S        %x,%r" },
          594 [0x5A] =        { RM,0,                "CVTSS2SD        %x,%X" },
          595 [0x5B] =        { RM,0,                "CVTTPS2PL        %x,%X" },
          596 [0x6F] =        { RM,0,                "MOVOU        %x,%X" },
          597 [0x70] =        { RM,Ib,                "PSHUFHW        %i,%x,%X" },
          598 [0x7E] =        { RM,0,                "MOVQOZX        %x,%X" },
          599 [0x7F] =        { RM,0,                "MOVOU        %X,%x" },
          600 [0xD6] =        { RM,0,                "MOVQOZX        %m*,%X" },
          601 [0xE6] =        { RM,0,                "CVTPL2PD        %x,%X" },
          602 };
          603 
          604 static Optable optab0F[256]=
          605 {
          606 [0x00] =        { RMOP,0,                optab0F00 },
          607 [0x01] =        { RMOP,0,                optab0F01 },
          608 [0x02] =        { RM,0,                "LAR        %e,%r" },
          609 [0x03] =        { RM,0,                "LSL        %e,%r" },
          610 [0x05] =        { 0,0,                "SYSCALL" },
          611 [0x06] =        { 0,0,                "CLTS" },
          612 [0x07] =        { 0,0,                "SYSRET" },
          613 [0x08] =        { 0,0,                "INVD" },
          614 [0x09] =        { 0,0,                "WBINVD" },
          615 [0x0B] =        { 0,0,                "UD2" },
          616 [0x0F] =        { RM,AUX,                optab0F0F },                /* 3DNow! */
          617 [0x10] =        { RM,0,                "MOVU%s        %x,%X" },
          618 [0x11] =        { RM,0,                "MOVU%s        %X,%x" },
          619 [0x12] =        { RM,0,                "MOV[H]L%s        %x,%X" },        /* TO DO: H if source is XMM */
          620 [0x13] =        { RM,0,                "MOVL%s        %X,%e" },
          621 [0x14] =        { RM,0,                "UNPCKL%s        %x,%X" },
          622 [0x15] =        { RM,0,                "UNPCKH%s        %x,%X" },
          623 [0x16] =        { RM,0,                "MOV[L]H%s        %x,%X" },        /* TO DO: L if source is XMM */
          624 [0x17] =        { RM,0,                "MOVH%s        %X,%x" },
          625 [0x20] =        { RMR,0,                "MOVL        %C,%e" },
          626 [0x21] =        { RMR,0,                "MOVL        %D,%e" },
          627 [0x22] =        { RMR,0,                "MOVL        %e,%C" },
          628 [0x23] =        { RMR,0,                "MOVL        %e,%D" },
          629 [0x24] =        { RMR,0,                "MOVL        %T,%e" },
          630 [0x26] =        { RMR,0,                "MOVL        %e,%T" },
          631 [0x28] =        { RM,0,                "MOVA%s        %x,%X" },
          632 [0x29] =        { RM,0,                "MOVA%s        %X,%x" },
          633 [0x2A] =        { RM,0,                "CVTPL2%s        %m*,%X" },
          634 [0x2B] =        { RM,0,                "MOVNT%s        %X,%e" },
          635 [0x2C] =        { RM,0,                "CVTT%s2PL        %x,%M" },
          636 [0x2D] =        { RM,0,                "CVT%s2PL        %x,%M" },
          637 [0x2E] =        { RM,0,                "UCOMISS        %x,%X" },
          638 [0x2F] =        { RM,0,                "COMISS        %x,%X" },
          639 [0x30] =        { 0,0,                "WRMSR" },
          640 [0x31] =        { 0,0,                "RDTSC" },
          641 [0x32] =        { 0,0,                "RDMSR" },
          642 [0x33] =        { 0,0,                "RDPMC" },
          643 [0x42] =        { RM,0,                "CMOVC        %e,%r" },                /* CF */
          644 [0x43] =        { RM,0,                "CMOVNC        %e,%r" },                /* ¬ CF */
          645 [0x44] =        { RM,0,                "CMOVZ        %e,%r" },                /* ZF */
          646 [0x45] =        { RM,0,                "CMOVNZ        %e,%r" },                /* ¬ ZF */
          647 [0x46] =        { RM,0,                "CMOVBE        %e,%r" },                /* CF ∨ ZF */
          648 [0x47] =        { RM,0,                "CMOVA        %e,%r" },                /* ¬CF ∧ ¬ZF */
          649 [0x48] =        { RM,0,                "CMOVS        %e,%r" },                /* SF */
          650 [0x49] =        { RM,0,                "CMOVNS        %e,%r" },                /* ¬ SF */
          651 [0x4A] =        { RM,0,                "CMOVP        %e,%r" },                /* PF */
          652 [0x4B] =        { RM,0,                "CMOVNP        %e,%r" },                /* ¬ PF */
          653 [0x4C] =        { RM,0,                "CMOVLT        %e,%r" },                /* LT ≡ OF ≠ SF */
          654 [0x4D] =        { RM,0,                "CMOVGE        %e,%r" },                /* GE ≡ ZF ∨ SF */
          655 [0x4E] =        { RM,0,                "CMOVLE        %e,%r" },                /* LE ≡ ZF ∨ LT */
          656 [0x4F] =        { RM,0,                "CMOVGT        %e,%r" },                /* GT ≡ ¬ZF ∧ GE */
          657 [0x50] =        { RM,0,                "MOVMSK%s        %X,%r" },        /* TO DO: check */
          658 [0x51] =        { RM,0,                "SQRT%s        %x,%X" },
          659 [0x52] =        { RM,0,                "RSQRT%s        %x,%X" },
          660 [0x53] =        { RM,0,                "RCP%s        %x,%X" },
          661 [0x54] =        { RM,0,                "AND%s        %x,%X" },
          662 [0x55] =        { RM,0,                "ANDN%s        %x,%X" },
          663 [0x56] =        { RM,0,                "OR%s        %x,%X" },                /* TO DO: S/D */
          664 [0x57] =        { RM,0,                "XOR%s        %x,%X" },                /* S/D */
          665 [0x58] =        { RM,0,                "ADD%s        %x,%X" },                /* S/P S/D */
          666 [0x59] =        { RM,0,                "MUL%s        %x,%X" },
          667 [0x5A] =        { RM,0,                "CVTPS2PD        %x,%X" },
          668 [0x5B] =        { RM,0,                "CVTPL2PS        %x,%X" },
          669 [0x5C] =        { RM,0,                "SUB%s        %x,%X" },
          670 [0x5D] =        { RM,0,                "MIN%s        %x,%X" },
          671 [0x5E] =        { RM,0,                "DIV%s        %x,%X" },                /* TO DO: S/P S/D */
          672 [0x5F] =        { RM,0,                "MAX%s        %x,%X" },
          673 [0x60] =        { RM,0,                "PUNPCKLBW %m,%M" },
          674 [0x61] =        { RM,0,                "PUNPCKLWL %m,%M" },
          675 [0x62] =        { RM,0,                "PUNPCKLLQ %m,%M" },
          676 [0x63] =        { RM,0,                "PACKSSWB %m,%M" },
          677 [0x64] =        { RM,0,                "PCMPGTB %m,%M" },
          678 [0x65] =        { RM,0,                "PCMPGTW %m,%M" },
          679 [0x66] =        { RM,0,                "PCMPGTL %m,%M" },
          680 [0x67] =        { RM,0,                "PACKUSWB %m,%M" },
          681 [0x68] =        { RM,0,                "PUNPCKHBW %m,%M" },
          682 [0x69] =        { RM,0,                "PUNPCKHWL %m,%M" },
          683 [0x6A] =        { RM,0,                "PUNPCKHLQ %m,%M" },
          684 [0x6B] =        { RM,0,                "PACKSSLW %m,%M" },
          685 [0x6E] =        { RM,0,                "MOV%S %e,%M" },
          686 [0x6F] =        { RM,0,                "MOVQ %m,%M" },
          687 [0x70] =        { RM,Ib,                "PSHUFW        %i,%m,%M" },
          688 [0x74] =        { RM,0,                "PCMPEQB %m,%M" },
          689 [0x75] =        { RM,0,                "PCMPEQW %m,%M" },
          690 [0x76] =        { RM,0,                "PCMPEQL %m,%M" },
          691 [0x77] =        { 0,0,                "EMMS" },
          692 [0x7E] =        { RM,0,                "MOV%S %M,%e" },
          693 [0x7F] =        { RM,0,                "MOVQ %M,%m" },
          694 [0xAE] =        { RMOP,0,                optab0FAE },
          695 [0xAA] =        { 0,0,                "RSM" },
          696 [0xB0] =        { RM,0,                "CMPXCHGB        %r,%e" },
          697 [0xB1] =        { RM,0,                "CMPXCHG%S        %r,%e" },
          698 [0xC0] =        { RMB,0,                "XADDB        %r,%e" },
          699 [0xC1] =        { RM,0,                "XADD%S        %r,%e" },
          700 [0xC2] =        { RM,Ib,                "CMP%s        %x,%X,%#i" },
          701 [0xC3] =        { RM,0,                "MOVNTI%S        %r,%e" },
          702 [0xC6] =        { RM,Ib,                "SHUF%s        %i,%x,%X" },
          703 [0xC8] =        { 0,0,                "BSWAP        AX" },
          704 [0xC9] =        { 0,0,                "BSWAP        CX" },
          705 [0xCA] =        { 0,0,                "BSWAP        DX" },
          706 [0xCB] =        { 0,0,                "BSWAP        BX" },
          707 [0xCC] =        { 0,0,                "BSWAP        SP" },
          708 [0xCD] =        { 0,0,                "BSWAP        BP" },
          709 [0xCE] =        { 0,0,                "BSWAP        SI" },
          710 [0xCF] =        { 0,0,                "BSWAP        DI" },
          711 [0xD1] =        { RM,0,                "PSRLW %m,%M" },
          712 [0xD2] =        { RM,0,                "PSRLL %m,%M" },
          713 [0xD3] =        { RM,0,                "PSRLQ %m,%M" },
          714 [0xD5] =        { RM,0,                "PMULLW %m,%M" },
          715 [0xD6] =        { RM,0,                "MOVQOZX        %m*,%X" },
          716 [0xD7] =        { RM,0,                "PMOVMSKB %m,%r" },
          717 [0xD8] =        { RM,0,                "PSUBUSB %m,%M" },
          718 [0xD9] =        { RM,0,                "PSUBUSW %m,%M" },
          719 [0xDA] =        { RM,0,                "PMINUB %m,%M" },
          720 [0xDB] =        { RM,0,                "PAND %m,%M" },
          721 [0xDC] =        { RM,0,                "PADDUSB %m,%M" },
          722 [0xDD] =        { RM,0,                "PADDUSW %m,%M" },
          723 [0xDE] =        { RM,0,                "PMAXUB %m,%M" },
          724 [0xDF] =        { RM,0,                "PANDN %m,%M" },
          725 [0xE0] =        { RM,0,                "PAVGB %m,%M" },
          726 [0xE1] =        { RM,0,                "PSRAW %m,%M" },
          727 [0xE2] =        { RM,0,                "PSRAL %m,%M" },
          728 [0xE3] =        { RM,0,                "PAVGW %m,%M" },
          729 [0xE4] =        { RM,0,                "PMULHUW %m,%M" },
          730 [0xE5] =        { RM,0,                "PMULHW %m,%M" },
          731 [0xE7] =        { RM,0,                "MOVNTQ        %M,%e" },
          732 [0xE8] =        { RM,0,                "PSUBSB %m,%M" },
          733 [0xE9] =        { RM,0,                "PSUBSW %m,%M" },
          734 [0xEA] =        { RM,0,                "PMINSW %m,%M" },
          735 [0xEB] =        { RM,0,                "POR %m,%M" },
          736 [0xEC] =        { RM,0,                "PADDSB %m,%M" },
          737 [0xED] =        { RM,0,                "PADDSW %m,%M" },
          738 [0xEE] =        { RM,0,                "PMAXSW %m,%M" },
          739 [0xEF] =        { RM,0,                "PXOR %m,%M" },
          740 [0xF1] =        { RM,0,                "PSLLW %m,%M" },
          741 [0xF2] =        { RM,0,                "PSLLL %m,%M" },
          742 [0xF3] =        { RM,0,                "PSLLQ %m,%M" },
          743 [0xF4] =        { RM,0,                "PMULULQ        %m,%M" },
          744 [0xF5] =        { RM,0,                "PMADDWL %m,%M" },
          745 [0xF6] =        { RM,0,                "PSADBW %m,%M" },
          746 [0xF7] =        { RMR,0,                "MASKMOVQ        %m,%M" },
          747 [0xF8] =        { RM,0,                "PSUBB %m,%M" },
          748 [0xF9] =        { RM,0,                "PSUBW %m,%M" },
          749 [0xFA] =        { RM,0,                "PSUBL %m,%M" },
          750 [0xFC] =        { RM,0,                "PADDB %m,%M" },
          751 [0xFD] =        { RM,0,                "PADDW %m,%M" },
          752 [0xFE] =        { RM,0,                "PADDL %m,%M" },
          753 
          754 [0x80] =        { Iwds,0,                "JOS        %p" },
          755 [0x81] =        { Iwds,0,                "JOC        %p" },
          756 [0x82] =        { Iwds,0,                "JCS        %p" },
          757 [0x83] =        { Iwds,0,                "JCC        %p" },
          758 [0x84] =        { Iwds,0,                "JEQ        %p" },
          759 [0x85] =        { Iwds,0,                "JNE        %p" },
          760 [0x86] =        { Iwds,0,                "JLS        %p" },
          761 [0x87] =        { Iwds,0,                "JHI        %p" },
          762 [0x88] =        { Iwds,0,                "JMI        %p" },
          763 [0x89] =        { Iwds,0,                "JPL        %p" },
          764 [0x8a] =        { Iwds,0,                "JPS        %p" },
          765 [0x8b] =        { Iwds,0,                "JPC        %p" },
          766 [0x8c] =        { Iwds,0,                "JLT        %p" },
          767 [0x8d] =        { Iwds,0,                "JGE        %p" },
          768 [0x8e] =        { Iwds,0,                "JLE        %p" },
          769 [0x8f] =        { Iwds,0,                "JGT        %p" },
          770 [0x90] =        { RMB,0,                "SETOS        %e" },
          771 [0x91] =        { RMB,0,                "SETOC        %e" },
          772 [0x92] =        { RMB,0,                "SETCS        %e" },
          773 [0x93] =        { RMB,0,                "SETCC        %e" },
          774 [0x94] =        { RMB,0,                "SETEQ        %e" },
          775 [0x95] =        { RMB,0,                "SETNE        %e" },
          776 [0x96] =        { RMB,0,                "SETLS        %e" },
          777 [0x97] =        { RMB,0,                "SETHI        %e" },
          778 [0x98] =        { RMB,0,                "SETMI        %e" },
          779 [0x99] =        { RMB,0,                "SETPL        %e" },
          780 [0x9a] =        { RMB,0,                "SETPS        %e" },
          781 [0x9b] =        { RMB,0,                "SETPC        %e" },
          782 [0x9c] =        { RMB,0,                "SETLT        %e" },
          783 [0x9d] =        { RMB,0,                "SETGE        %e" },
          784 [0x9e] =        { RMB,0,                "SETLE        %e" },
          785 [0x9f] =        { RMB,0,                "SETGT        %e" },
          786 [0xa0] =        { 0,0,                "PUSHL        FS" },
          787 [0xa1] =        { 0,0,                "POPL        FS" },
          788 [0xa2] =        { 0,0,                "CPUID" },
          789 [0xa3] =        { RM,0,                "BT%S        %r,%e" },
          790 [0xa4] =        { RM,Ib,                "SHLD%S        %r,%i,%e" },
          791 [0xa5] =        { RM,0,                "SHLD%S        %r,CL,%e" },
          792 [0xa8] =        { 0,0,                "PUSHL        GS" },
          793 [0xa9] =        { 0,0,                "POPL        GS" },
          794 [0xab] =        { RM,0,                "BTS%S        %r,%e" },
          795 [0xac] =        { RM,Ib,                "SHRD%S        %r,%i,%e" },
          796 [0xad] =        { RM,0,                "SHRD%S        %r,CL,%e" },
          797 [0xaf] =        { RM,0,                "IMUL%S        %e,%r" },
          798 [0xb2] =        { RMM,0,                "LSS        %e,%r" },
          799 [0xb3] =        { RM,0,                "BTR%S        %r,%e" },
          800 [0xb4] =        { RMM,0,                "LFS        %e,%r" },
          801 [0xb5] =        { RMM,0,                "LGS        %e,%r" },
          802 [0xb6] =        { RMB,0,                "MOVBZX        %e,%R" },
          803 [0xb7] =        { RM,0,                "MOVWZX        %e,%R" },
          804 [0xba] =        { RMOP,0,                optab0FBA },
          805 [0xbb] =        { RM,0,                "BTC%S        %e,%r" },
          806 [0xbc] =        { RM,0,                "BSF%S        %e,%r" },
          807 [0xbd] =        { RM,0,                "BSR%S        %e,%r" },
          808 [0xbe] =        { RMB,0,                "MOVBSX        %e,%R" },
          809 [0xbf] =        { RM,0,                "MOVWSX        %e,%R" },
          810 [0xc7] =        { RMOP,0,                optab0FC7 },
          811 };
          812 
          813 static Optable optab80[8]=
          814 {
          815 [0x00] =        { Ib,0,                "ADDB        %i,%e" },
          816 [0x01] =        { Ib,0,                "ORB        %i,%e" },
          817 [0x02] =        { Ib,0,                "ADCB        %i,%e" },
          818 [0x03] =        { Ib,0,                "SBBB        %i,%e" },
          819 [0x04] =        { Ib,0,                "ANDB        %i,%e" },
          820 [0x05] =        { Ib,0,                "SUBB        %i,%e" },
          821 [0x06] =        { Ib,0,                "XORB        %i,%e" },
          822 [0x07] =        { Ib,0,                "CMPB        %e,%i" },
          823 };
          824 
          825 static Optable optab81[8]=
          826 {
          827 [0x00] =        { Iwd,0,                "ADD%S        %i,%e" },
          828 [0x01] =        { Iwd,0,                "OR%S        %i,%e" },
          829 [0x02] =        { Iwd,0,                "ADC%S        %i,%e" },
          830 [0x03] =        { Iwd,0,                "SBB%S        %i,%e" },
          831 [0x04] =        { Iwd,0,                "AND%S        %i,%e" },
          832 [0x05] =        { Iwd,0,                "SUB%S        %i,%e" },
          833 [0x06] =        { Iwd,0,                "XOR%S        %i,%e" },
          834 [0x07] =        { Iwd,0,                "CMP%S        %e,%i" },
          835 };
          836 
          837 static Optable optab83[8]=
          838 {
          839 [0x00] =        { Ibs,0,                "ADD%S        %i,%e" },
          840 [0x01] =        { Ibs,0,                "OR%S        %i,%e" },
          841 [0x02] =        { Ibs,0,                "ADC%S        %i,%e" },
          842 [0x03] =        { Ibs,0,                "SBB%S        %i,%e" },
          843 [0x04] =        { Ibs,0,                "AND%S        %i,%e" },
          844 [0x05] =        { Ibs,0,                "SUB%S        %i,%e" },
          845 [0x06] =        { Ibs,0,                "XOR%S        %i,%e" },
          846 [0x07] =        { Ibs,0,                "CMP%S        %e,%i" },
          847 };
          848 
          849 static Optable optabC0[8] =
          850 {
          851 [0x00] =        { Ib,0,                "ROLB        %i,%e" },
          852 [0x01] =        { Ib,0,                "RORB        %i,%e" },
          853 [0x02] =        { Ib,0,                "RCLB        %i,%e" },
          854 [0x03] =        { Ib,0,                "RCRB        %i,%e" },
          855 [0x04] =        { Ib,0,                "SHLB        %i,%e" },
          856 [0x05] =        { Ib,0,                "SHRB        %i,%e" },
          857 [0x07] =        { Ib,0,                "SARB        %i,%e" },
          858 };
          859 
          860 static Optable optabC1[8] =
          861 {
          862 [0x00] =        { Ib,0,                "ROL%S        %i,%e" },
          863 [0x01] =        { Ib,0,                "ROR%S        %i,%e" },
          864 [0x02] =        { Ib,0,                "RCL%S        %i,%e" },
          865 [0x03] =        { Ib,0,                "RCR%S        %i,%e" },
          866 [0x04] =        { Ib,0,                "SHL%S        %i,%e" },
          867 [0x05] =        { Ib,0,                "SHR%S        %i,%e" },
          868 [0x07] =        { Ib,0,                "SAR%S        %i,%e" },
          869 };
          870 
          871 static Optable optabD0[8] =
          872 {
          873 [0x00] =        { 0,0,                "ROLB        %e" },
          874 [0x01] =        { 0,0,                "RORB        %e" },
          875 [0x02] =        { 0,0,                "RCLB        %e" },
          876 [0x03] =        { 0,0,                "RCRB        %e" },
          877 [0x04] =        { 0,0,                "SHLB        %e" },
          878 [0x05] =        { 0,0,                "SHRB        %e" },
          879 [0x07] =        { 0,0,                "SARB        %e" },
          880 };
          881 
          882 static Optable optabD1[8] =
          883 {
          884 [0x00] =        { 0,0,                "ROL%S        %e" },
          885 [0x01] =        { 0,0,                "ROR%S        %e" },
          886 [0x02] =        { 0,0,                "RCL%S        %e" },
          887 [0x03] =        { 0,0,                "RCR%S        %e" },
          888 [0x04] =        { 0,0,                "SHL%S        %e" },
          889 [0x05] =        { 0,0,                "SHR%S        %e" },
          890 [0x07] =        { 0,0,                "SAR%S        %e" },
          891 };
          892 
          893 static Optable optabD2[8] =
          894 {
          895 [0x00] =        { 0,0,                "ROLB        CL,%e" },
          896 [0x01] =        { 0,0,                "RORB        CL,%e" },
          897 [0x02] =        { 0,0,                "RCLB        CL,%e" },
          898 [0x03] =        { 0,0,                "RCRB        CL,%e" },
          899 [0x04] =        { 0,0,                "SHLB        CL,%e" },
          900 [0x05] =        { 0,0,                "SHRB        CL,%e" },
          901 [0x07] =        { 0,0,                "SARB        CL,%e" },
          902 };
          903 
          904 static Optable optabD3[8] =
          905 {
          906 [0x00] =        { 0,0,                "ROL%S        CL,%e" },
          907 [0x01] =        { 0,0,                "ROR%S        CL,%e" },
          908 [0x02] =        { 0,0,                "RCL%S        CL,%e" },
          909 [0x03] =        { 0,0,                "RCR%S        CL,%e" },
          910 [0x04] =        { 0,0,                "SHL%S        CL,%e" },
          911 [0x05] =        { 0,0,                "SHR%S        CL,%e" },
          912 [0x07] =        { 0,0,                "SAR%S        CL,%e" },
          913 };
          914 
          915 static Optable optabD8[8+8] =
          916 {
          917 [0x00] =        { 0,0,                "FADDF        %e,F0" },
          918 [0x01] =        { 0,0,                "FMULF        %e,F0" },
          919 [0x02] =        { 0,0,                "FCOMF        %e,F0" },
          920 [0x03] =        { 0,0,                "FCOMFP        %e,F0" },
          921 [0x04] =        { 0,0,                "FSUBF        %e,F0" },
          922 [0x05] =        { 0,0,                "FSUBRF        %e,F0" },
          923 [0x06] =        { 0,0,                "FDIVF        %e,F0" },
          924 [0x07] =        { 0,0,                "FDIVRF        %e,F0" },
          925 [0x08] =        { 0,0,                "FADDD        %f,F0" },
          926 [0x09] =        { 0,0,                "FMULD        %f,F0" },
          927 [0x0a] =        { 0,0,                "FCOMD        %f,F0" },
          928 [0x0b] =        { 0,0,                "FCOMPD        %f,F0" },
          929 [0x0c] =        { 0,0,                "FSUBD        %f,F0" },
          930 [0x0d] =        { 0,0,                "FSUBRD        %f,F0" },
          931 [0x0e] =        { 0,0,                "FDIVD        %f,F0" },
          932 [0x0f] =        { 0,0,                "FDIVRD        %f,F0" },
          933 };
          934 /*
          935  *        optabD9 and optabDB use the following encoding:
          936  *        if (0 <= modrm <= 2) instruction = optabDx[modrm&0x07];
          937  *        else instruction = optabDx[(modrm&0x3f)+8];
          938  *
          939  *        the instructions for MOD == 3, follow the 8 instructions
          940  *        for the other MOD values stored at the front of the table.
          941  */
          942 static Optable optabD9[64+8] =
          943 {
          944 [0x00] =        { 0,0,                "FMOVF        %e,F0" },
          945 [0x02] =        { 0,0,                "FMOVF        F0,%e" },
          946 [0x03] =        { 0,0,                "FMOVFP        F0,%e" },
          947 [0x04] =        { 0,0,                "FLDENV%S %e" },
          948 [0x05] =        { 0,0,                "FLDCW        %e" },
          949 [0x06] =        { 0,0,                "FSTENV%S %e" },
          950 [0x07] =        { 0,0,                "FSTCW        %e" },
          951 [0x08] =        { 0,0,                "FMOVD        F0,F0" },                /* Mod R/M = 11xx xxxx*/
          952 [0x09] =        { 0,0,                "FMOVD        F1,F0" },
          953 [0x0a] =        { 0,0,                "FMOVD        F2,F0" },
          954 [0x0b] =        { 0,0,                "FMOVD        F3,F0" },
          955 [0x0c] =        { 0,0,                "FMOVD        F4,F0" },
          956 [0x0d] =        { 0,0,                "FMOVD        F5,F0" },
          957 [0x0e] =        { 0,0,                "FMOVD        F6,F0" },
          958 [0x0f] =        { 0,0,                "FMOVD        F7,F0" },
          959 [0x10] =        { 0,0,                "FXCHD        F0,F0" },
          960 [0x11] =        { 0,0,                "FXCHD        F1,F0" },
          961 [0x12] =        { 0,0,                "FXCHD        F2,F0" },
          962 [0x13] =        { 0,0,                "FXCHD        F3,F0" },
          963 [0x14] =        { 0,0,                "FXCHD        F4,F0" },
          964 [0x15] =        { 0,0,                "FXCHD        F5,F0" },
          965 [0x16] =        { 0,0,                "FXCHD        F6,F0" },
          966 [0x17] =        { 0,0,                "FXCHD        F7,F0" },
          967 [0x18] =        { 0,0,                "FNOP" },
          968 [0x28] =        { 0,0,                "FCHS" },
          969 [0x29] =        { 0,0,                "FABS" },
          970 [0x2c] =        { 0,0,                "FTST" },
          971 [0x2d] =        { 0,0,                "FXAM" },
          972 [0x30] =        { 0,0,                "FLD1" },
          973 [0x31] =        { 0,0,                "FLDL2T" },
          974 [0x32] =        { 0,0,                "FLDL2E" },
          975 [0x33] =        { 0,0,                "FLDPI" },
          976 [0x34] =        { 0,0,                "FLDLG2" },
          977 [0x35] =        { 0,0,                "FLDLN2" },
          978 [0x36] =        { 0,0,                "FLDZ" },
          979 [0x38] =        { 0,0,                "F2XM1" },
          980 [0x39] =        { 0,0,                "FYL2X" },
          981 [0x3a] =        { 0,0,                "FPTAN" },
          982 [0x3b] =        { 0,0,                "FPATAN" },
          983 [0x3c] =        { 0,0,                "FXTRACT" },
          984 [0x3d] =        { 0,0,                "FPREM1" },
          985 [0x3e] =        { 0,0,                "FDECSTP" },
          986 [0x3f] =        { 0,0,                "FNCSTP" },
          987 [0x40] =        { 0,0,                "FPREM" },
          988 [0x41] =        { 0,0,                "FYL2XP1" },
          989 [0x42] =        { 0,0,                "FSQRT" },
          990 [0x43] =        { 0,0,                "FSINCOS" },
          991 [0x44] =        { 0,0,                "FRNDINT" },
          992 [0x45] =        { 0,0,                "FSCALE" },
          993 [0x46] =        { 0,0,                "FSIN" },
          994 [0x47] =        { 0,0,                "FCOS" },
          995 };
          996 
          997 static Optable optabDA[8+8] =
          998 {
          999 [0x00] =        { 0,0,                "FADDL        %e,F0" },
         1000 [0x01] =        { 0,0,                "FMULL        %e,F0" },
         1001 [0x02] =        { 0,0,                "FCOML        %e,F0" },
         1002 [0x03] =        { 0,0,                "FCOMLP        %e,F0" },
         1003 [0x04] =        { 0,0,                "FSUBL        %e,F0" },
         1004 [0x05] =        { 0,0,                "FSUBRL        %e,F0" },
         1005 [0x06] =        { 0,0,                "FDIVL        %e,F0" },
         1006 [0x07] =        { 0,0,                "FDIVRL        %e,F0" },
         1007 [0x08] =        { 0,0,                "FCMOVCS        %f,F0" },
         1008 [0x09] =        { 0,0,                "FCMOVEQ        %f,F0" },
         1009 [0x0a] =        { 0,0,                "FCMOVLS        %f,F0" },
         1010 [0x0b] =        { 0,0,                "FCMOVUN        %f,F0" },
         1011 [0x0d] =        { Op_R1,0,                "FUCOMPP" },
         1012 };
         1013 
         1014 static Optable optabDB[8+64] =
         1015 {
         1016 [0x00] =        { 0,0,                "FMOVL        %e,F0" },
         1017 [0x02] =        { 0,0,                "FMOVL        F0,%e" },
         1018 [0x03] =        { 0,0,                "FMOVLP        F0,%e" },
         1019 [0x05] =        { 0,0,                "FMOVX        %e,F0" },
         1020 [0x07] =        { 0,0,                "FMOVXP        F0,%e" },
         1021 [0x08] =        { 0,0,                "FCMOVCC        F0,F0" },        /* Mod R/M = 11xx xxxx*/
         1022 [0x09] =        { 0,0,                "FCMOVCC        F1,F0" },
         1023 [0x0a] =        { 0,0,                "FCMOVCC        F2,F0" },
         1024 [0x0b] =        { 0,0,                "FCMOVCC        F3,F0" },
         1025 [0x0c] =        { 0,0,                "FCMOVCC        F4,F0" },
         1026 [0x0d] =        { 0,0,                "FCMOVCC        F5,F0" },
         1027 [0x0e] =        { 0,0,                "FCMOVCC        F6,F0" },
         1028 [0x0f] =        { 0,0,                "FCMOVCC        F7,F0" },
         1029 [0x10] =        { 0,0,                "FCMOVNE        F0,F0" },
         1030 [0x11] =        { 0,0,                "FCMOVNE        F1,F0" },
         1031 [0x12] =        { 0,0,                "FCMOVNE        F2,F0" },
         1032 [0x13] =        { 0,0,                "FCMOVNE        F3,F0" },
         1033 [0x14] =        { 0,0,                "FCMOVNE        F4,F0" },
         1034 [0x15] =        { 0,0,                "FCMOVNE        F5,F0" },
         1035 [0x16] =        { 0,0,                "FCMOVNE        F6,F0" },
         1036 [0x17] =        { 0,0,                "FCMOVNE        F7,F0" },
         1037 [0x18] =        { 0,0,                "FCMOVHI        F0,F0" },
         1038 [0x19] =        { 0,0,                "FCMOVHI        F1,F0" },
         1039 [0x1a] =        { 0,0,                "FCMOVHI        F2,F0" },
         1040 [0x1b] =        { 0,0,                "FCMOVHI        F3,F0" },
         1041 [0x1c] =        { 0,0,                "FCMOVHI        F4,F0" },
         1042 [0x1d] =        { 0,0,                "FCMOVHI        F5,F0" },
         1043 [0x1e] =        { 0,0,                "FCMOVHI        F6,F0" },
         1044 [0x1f] =        { 0,0,                "FCMOVHI        F7,F0" },
         1045 [0x20] =        { 0,0,                "FCMOVNU        F0,F0" },
         1046 [0x21] =        { 0,0,                "FCMOVNU        F1,F0" },
         1047 [0x22] =        { 0,0,                "FCMOVNU        F2,F0" },
         1048 [0x23] =        { 0,0,                "FCMOVNU        F3,F0" },
         1049 [0x24] =        { 0,0,                "FCMOVNU        F4,F0" },
         1050 [0x25] =        { 0,0,                "FCMOVNU        F5,F0" },
         1051 [0x26] =        { 0,0,                "FCMOVNU        F6,F0" },
         1052 [0x27] =        { 0,0,                "FCMOVNU        F7,F0" },
         1053 [0x2a] =        { 0,0,                "FCLEX" },
         1054 [0x2b] =        { 0,0,                "FINIT" },
         1055 [0x30] =        { 0,0,                "FUCOMI        F0,F0" },
         1056 [0x31] =        { 0,0,                "FUCOMI        F1,F0" },
         1057 [0x32] =        { 0,0,                "FUCOMI        F2,F0" },
         1058 [0x33] =        { 0,0,                "FUCOMI        F3,F0" },
         1059 [0x34] =        { 0,0,                "FUCOMI        F4,F0" },
         1060 [0x35] =        { 0,0,                "FUCOMI        F5,F0" },
         1061 [0x36] =        { 0,0,                "FUCOMI        F6,F0" },
         1062 [0x37] =        { 0,0,                "FUCOMI        F7,F0" },
         1063 [0x38] =        { 0,0,                "FCOMI        F0,F0" },
         1064 [0x39] =        { 0,0,                "FCOMI        F1,F0" },
         1065 [0x3a] =        { 0,0,                "FCOMI        F2,F0" },
         1066 [0x3b] =        { 0,0,                "FCOMI        F3,F0" },
         1067 [0x3c] =        { 0,0,                "FCOMI        F4,F0" },
         1068 [0x3d] =        { 0,0,                "FCOMI        F5,F0" },
         1069 [0x3e] =        { 0,0,                "FCOMI        F6,F0" },
         1070 [0x3f] =        { 0,0,                "FCOMI        F7,F0" },
         1071 };
         1072 
         1073 static Optable optabDC[8+8] =
         1074 {
         1075 [0x00] =        { 0,0,                "FADDD        %e,F0" },
         1076 [0x01] =        { 0,0,                "FMULD        %e,F0" },
         1077 [0x02] =        { 0,0,                "FCOMD        %e,F0" },
         1078 [0x03] =        { 0,0,                "FCOMDP        %e,F0" },
         1079 [0x04] =        { 0,0,                "FSUBD        %e,F0" },
         1080 [0x05] =        { 0,0,                "FSUBRD        %e,F0" },
         1081 [0x06] =        { 0,0,                "FDIVD        %e,F0" },
         1082 [0x07] =        { 0,0,                "FDIVRD        %e,F0" },
         1083 [0x08] =        { 0,0,                "FADDD        F0,%f" },
         1084 [0x09] =        { 0,0,                "FMULD        F0,%f" },
         1085 [0x0c] =        { 0,0,                "FSUBRD        F0,%f" },
         1086 [0x0d] =        { 0,0,                "FSUBD        F0,%f" },
         1087 [0x0e] =        { 0,0,                "FDIVRD        F0,%f" },
         1088 [0x0f] =        { 0,0,                "FDIVD        F0,%f" },
         1089 };
         1090 
         1091 static Optable optabDD[8+8] =
         1092 {
         1093 [0x00] =        { 0,0,                "FMOVD        %e,F0" },
         1094 [0x02] =        { 0,0,                "FMOVD        F0,%e" },
         1095 [0x03] =        { 0,0,                "FMOVDP        F0,%e" },
         1096 [0x04] =        { 0,0,                "FRSTOR%S %e" },
         1097 [0x06] =        { 0,0,                "FSAVE%S %e" },
         1098 [0x07] =        { 0,0,                "FSTSW        %e" },
         1099 [0x08] =        { 0,0,                "FFREED        %f" },
         1100 [0x0a] =        { 0,0,                "FMOVD        %f,F0" },
         1101 [0x0b] =        { 0,0,                "FMOVDP        %f,F0" },
         1102 [0x0c] =        { 0,0,                "FUCOMD        %f,F0" },
         1103 [0x0d] =        { 0,0,                "FUCOMDP %f,F0" },
         1104 };
         1105 
         1106 static Optable optabDE[8+8] =
         1107 {
         1108 [0x00] =        { 0,0,                "FADDW        %e,F0" },
         1109 [0x01] =        { 0,0,                "FMULW        %e,F0" },
         1110 [0x02] =        { 0,0,                "FCOMW        %e,F0" },
         1111 [0x03] =        { 0,0,                "FCOMWP        %e,F0" },
         1112 [0x04] =        { 0,0,                "FSUBW        %e,F0" },
         1113 [0x05] =        { 0,0,                "FSUBRW        %e,F0" },
         1114 [0x06] =        { 0,0,                "FDIVW        %e,F0" },
         1115 [0x07] =        { 0,0,                "FDIVRW        %e,F0" },
         1116 [0x08] =        { 0,0,                "FADDDP        F0,%f" },
         1117 [0x09] =        { 0,0,                "FMULDP        F0,%f" },
         1118 [0x0b] =        { Op_R1,0,                "FCOMPDP" },
         1119 [0x0c] =        { 0,0,                "FSUBRDP F0,%f" },
         1120 [0x0d] =        { 0,0,                "FSUBDP        F0,%f" },
         1121 [0x0e] =        { 0,0,                "FDIVRDP F0,%f" },
         1122 [0x0f] =        { 0,0,                "FDIVDP        F0,%f" },
         1123 };
         1124 
         1125 static Optable optabDF[8+8] =
         1126 {
         1127 [0x00] =        { 0,0,                "FMOVW        %e,F0" },
         1128 [0x02] =        { 0,0,                "FMOVW        F0,%e" },
         1129 [0x03] =        { 0,0,                "FMOVWP        F0,%e" },
         1130 [0x04] =        { 0,0,                "FBLD        %e" },
         1131 [0x05] =        { 0,0,                "FMOVL        %e,F0" },
         1132 [0x06] =        { 0,0,                "FBSTP        %e" },
         1133 [0x07] =        { 0,0,                "FMOVLP        F0,%e" },
         1134 [0x0c] =        { Op_R0,0,                "FSTSW        %OAX" },
         1135 [0x0d] =        { 0,0,                "FUCOMIP        F0,%f" },
         1136 [0x0e] =        { 0,0,                "FCOMIP        F0,%f" },
         1137 };
         1138 
         1139 static Optable optabF6[8] =
         1140 {
         1141 [0x00] =        { Ib,0,                "TESTB        %i,%e" },
         1142 [0x02] =        { 0,0,                "NOTB        %e" },
         1143 [0x03] =        { 0,0,                "NEGB        %e" },
         1144 [0x04] =        { 0,0,                "MULB        AL,%e" },
         1145 [0x05] =        { 0,0,                "IMULB        AL,%e" },
         1146 [0x06] =        { 0,0,                "DIVB        AL,%e" },
         1147 [0x07] =        { 0,0,                "IDIVB        AL,%e" },
         1148 };
         1149 
         1150 static Optable optabF7[8] =
         1151 {
         1152 [0x00] =        { Iwd,0,                "TEST%S        %i,%e" },
         1153 [0x02] =        { 0,0,                "NOT%S        %e" },
         1154 [0x03] =        { 0,0,                "NEG%S        %e" },
         1155 [0x04] =        { 0,0,                "MUL%S        %OAX,%e" },
         1156 [0x05] =        { 0,0,                "IMUL%S        %OAX,%e" },
         1157 [0x06] =        { 0,0,                "DIV%S        %OAX,%e" },
         1158 [0x07] =        { 0,0,                "IDIV%S        %OAX,%e" },
         1159 };
         1160 
         1161 static Optable optabFE[8] =
         1162 {
         1163 [0x00] =        { 0,0,                "INCB        %e" },
         1164 [0x01] =        { 0,0,                "DECB        %e" },
         1165 };
         1166 
         1167 static Optable optabFF[8] =
         1168 {
         1169 [0x00] =        { 0,0,                "INC%S        %e" },
         1170 [0x01] =        { 0,0,                "DEC%S        %e" },
         1171 [0x02] =        { JUMP,0,                "CALL*        %e" },
         1172 [0x03] =        { JUMP,0,                "CALLF*        %e" },
         1173 [0x04] =        { JUMP,0,                "JMP*        %e" },
         1174 [0x05] =        { JUMP,0,                "JMPF*        %e" },
         1175 [0x06] =        { 0,0,                "PUSHL        %e" },
         1176 };
         1177 
         1178 static Optable optable[256+2] =
         1179 {
         1180 [0x00] =        { RMB,0,                "ADDB        %r,%e" },
         1181 [0x01] =        { RM,0,                "ADD%S        %r,%e" },
         1182 [0x02] =        { RMB,0,                "ADDB        %e,%r" },
         1183 [0x03] =        { RM,0,                "ADD%S        %e,%r" },
         1184 [0x04] =        { Ib,0,                "ADDB        %i,AL" },
         1185 [0x05] =        { Iwd,0,                "ADD%S        %i,%OAX" },
         1186 [0x06] =        { 0,0,                "PUSHL        ES" },
         1187 [0x07] =        { 0,0,                "POPL        ES" },
         1188 [0x08] =        { RMB,0,                "ORB        %r,%e" },
         1189 [0x09] =        { RM,0,                "OR%S        %r,%e" },
         1190 [0x0a] =        { RMB,0,                "ORB        %e,%r" },
         1191 [0x0b] =        { RM,0,                "OR%S        %e,%r" },
         1192 [0x0c] =        { Ib,0,                "ORB        %i,AL" },
         1193 [0x0d] =        { Iwd,0,                "OR%S        %i,%OAX" },
         1194 [0x0e] =        { 0,0,                "PUSHL        CS" },
         1195 [0x0f] =        { AUXMM,0,        optab0F },
         1196 [0x10] =        { RMB,0,                "ADCB        %r,%e" },
         1197 [0x11] =        { RM,0,                "ADC%S        %r,%e" },
         1198 [0x12] =        { RMB,0,                "ADCB        %e,%r" },
         1199 [0x13] =        { RM,0,                "ADC%S        %e,%r" },
         1200 [0x14] =        { Ib,0,                "ADCB        %i,AL" },
         1201 [0x15] =        { Iwd,0,                "ADC%S        %i,%OAX" },
         1202 [0x16] =        { 0,0,                "PUSHL        SS" },
         1203 [0x17] =        { 0,0,                "POPL        SS" },
         1204 [0x18] =        { RMB,0,                "SBBB        %r,%e" },
         1205 [0x19] =        { RM,0,                "SBB%S        %r,%e" },
         1206 [0x1a] =        { RMB,0,                "SBBB        %e,%r" },
         1207 [0x1b] =        { RM,0,                "SBB%S        %e,%r" },
         1208 [0x1c] =        { Ib,0,                "SBBB        %i,AL" },
         1209 [0x1d] =        { Iwd,0,                "SBB%S        %i,%OAX" },
         1210 [0x1e] =        { 0,0,                "PUSHL        DS" },
         1211 [0x1f] =        { 0,0,                "POPL        DS" },
         1212 [0x20] =        { RMB,0,                "ANDB        %r,%e" },
         1213 [0x21] =        { RM,0,                "AND%S        %r,%e" },
         1214 [0x22] =        { RMB,0,                "ANDB        %e,%r" },
         1215 [0x23] =        { RM,0,                "AND%S        %e,%r" },
         1216 [0x24] =        { Ib,0,                "ANDB        %i,AL" },
         1217 [0x25] =        { Iwd,0,                "AND%S        %i,%OAX" },
         1218 [0x26] =        { SEG,0,                "ES:" },
         1219 [0x27] =        { 0,0,                "DAA" },
         1220 [0x28] =        { RMB,0,                "SUBB        %r,%e" },
         1221 [0x29] =        { RM,0,                "SUB%S        %r,%e" },
         1222 [0x2a] =        { RMB,0,                "SUBB        %e,%r" },
         1223 [0x2b] =        { RM,0,                "SUB%S        %e,%r" },
         1224 [0x2c] =        { Ib,0,                "SUBB        %i,AL" },
         1225 [0x2d] =        { Iwd,0,                "SUB%S        %i,%OAX" },
         1226 [0x2e] =        { SEG,0,                "CS:" },
         1227 [0x2f] =        { 0,0,                "DAS" },
         1228 [0x30] =        { RMB,0,                "XORB        %r,%e" },
         1229 [0x31] =        { RM,0,                "XOR%S        %r,%e" },
         1230 [0x32] =        { RMB,0,                "XORB        %e,%r" },
         1231 [0x33] =        { RM,0,                "XOR%S        %e,%r" },
         1232 [0x34] =        { Ib,0,                "XORB        %i,AL" },
         1233 [0x35] =        { Iwd,0,                "XOR%S        %i,%OAX" },
         1234 [0x36] =        { SEG,0,                "SS:" },
         1235 [0x37] =        { 0,0,                "AAA" },
         1236 [0x38] =        { RMB,0,                "CMPB        %r,%e" },
         1237 [0x39] =        { RM,0,                "CMP%S        %r,%e" },
         1238 [0x3a] =        { RMB,0,                "CMPB        %e,%r" },
         1239 [0x3b] =        { RM,0,                "CMP%S        %e,%r" },
         1240 [0x3c] =        { Ib,0,                "CMPB        %i,AL" },
         1241 [0x3d] =        { Iwd,0,                "CMP%S        %i,%OAX" },
         1242 [0x3e] =        { SEG,0,                "DS:" },
         1243 [0x3f] =        { 0,0,                "AAS" },
         1244 [0x40] =        { 0,0,                "INC%S        %OAX" },
         1245 [0x41] =        { 0,0,                "INC%S        %OCX" },
         1246 [0x42] =        { 0,0,                "INC%S        %ODX" },
         1247 [0x43] =        { 0,0,                "INC%S        %OBX" },
         1248 [0x44] =        { 0,0,                "INC%S        %OSP" },
         1249 [0x45] =        { 0,0,                "INC%S        %OBP" },
         1250 [0x46] =        { 0,0,                "INC%S        %OSI" },
         1251 [0x47] =        { 0,0,                "INC%S        %ODI" },
         1252 [0x48] =        { 0,0,                "DEC%S        %OAX" },
         1253 [0x49] =        { 0,0,                "DEC%S        %OCX" },
         1254 [0x4a] =        { 0,0,                "DEC%S        %ODX" },
         1255 [0x4b] =        { 0,0,                "DEC%S        %OBX" },
         1256 [0x4c] =        { 0,0,                "DEC%S        %OSP" },
         1257 [0x4d] =        { 0,0,                "DEC%S        %OBP" },
         1258 [0x4e] =        { 0,0,                "DEC%S        %OSI" },
         1259 [0x4f] =        { 0,0,                "DEC%S        %ODI" },
         1260 [0x50] =        { 0,0,                "PUSH%S        %OAX" },
         1261 [0x51] =        { 0,0,                "PUSH%S        %OCX" },
         1262 [0x52] =        { 0,0,                "PUSH%S        %ODX" },
         1263 [0x53] =        { 0,0,                "PUSH%S        %OBX" },
         1264 [0x54] =        { 0,0,                "PUSH%S        %OSP" },
         1265 [0x55] =        { 0,0,                "PUSH%S        %OBP" },
         1266 [0x56] =        { 0,0,                "PUSH%S        %OSI" },
         1267 [0x57] =        { 0,0,                "PUSH%S        %ODI" },
         1268 [0x58] =        { 0,0,                "POP%S        %OAX" },
         1269 [0x59] =        { 0,0,                "POP%S        %OCX" },
         1270 [0x5a] =        { 0,0,                "POP%S        %ODX" },
         1271 [0x5b] =        { 0,0,                "POP%S        %OBX" },
         1272 [0x5c] =        { 0,0,                "POP%S        %OSP" },
         1273 [0x5d] =        { 0,0,                "POP%S        %OBP" },
         1274 [0x5e] =        { 0,0,                "POP%S        %OSI" },
         1275 [0x5f] =        { 0,0,                "POP%S        %ODI" },
         1276 [0x60] =        { 0,0,                "PUSHA%S" },
         1277 [0x61] =        { 0,0,                "POPA%S" },
         1278 [0x62] =        { RMM,0,                "BOUND        %e,%r" },
         1279 [0x63] =        { RM,0,                "ARPL        %r,%e" },
         1280 [0x64] =        { SEG,0,                "FS:" },
         1281 [0x65] =        { SEG,0,                "GS:" },
         1282 [0x66] =        { OPOVER,0,        "" },
         1283 [0x67] =        { ADDOVER,0,        "" },
         1284 [0x68] =        { Iwd,0,                "PUSH%S        %i" },
         1285 [0x69] =        { RM,Iwd,                "IMUL%S        %e,%i,%r" },
         1286 [0x6a] =        { Ib,0,                "PUSH%S        %i" },
         1287 [0x6b] =        { RM,Ibs,                "IMUL%S        %e,%i,%r" },
         1288 [0x6c] =        { 0,0,                "INSB        DX,(%ODI)" },
         1289 [0x6d] =        { 0,0,                "INS%S        DX,(%ODI)" },
         1290 [0x6e] =        { 0,0,                "OUTSB        (%ASI),DX" },
         1291 [0x6f] =        { 0,0,                "OUTS%S        (%ASI),DX" },
         1292 [0x70] =        { Jbs,0,                "JOS        %p" },
         1293 [0x71] =        { Jbs,0,                "JOC        %p" },
         1294 [0x72] =        { Jbs,0,                "JCS        %p" },
         1295 [0x73] =        { Jbs,0,                "JCC        %p" },
         1296 [0x74] =        { Jbs,0,                "JEQ        %p" },
         1297 [0x75] =        { Jbs,0,                "JNE        %p" },
         1298 [0x76] =        { Jbs,0,                "JLS        %p" },
         1299 [0x77] =        { Jbs,0,                "JHI        %p" },
         1300 [0x78] =        { Jbs,0,                "JMI        %p" },
         1301 [0x79] =        { Jbs,0,                "JPL        %p" },
         1302 [0x7a] =        { Jbs,0,                "JPS        %p" },
         1303 [0x7b] =        { Jbs,0,                "JPC        %p" },
         1304 [0x7c] =        { Jbs,0,                "JLT        %p" },
         1305 [0x7d] =        { Jbs,0,                "JGE        %p" },
         1306 [0x7e] =        { Jbs,0,                "JLE        %p" },
         1307 [0x7f] =        { Jbs,0,                "JGT        %p" },
         1308 [0x80] =        { RMOPB,0,        optab80 },
         1309 [0x81] =        { RMOP,0,                optab81 },
         1310 [0x83] =        { RMOP,0,                optab83 },
         1311 [0x84] =        { RMB,0,                "TESTB        %r,%e" },
         1312 [0x85] =        { RM,0,                "TEST%S        %r,%e" },
         1313 [0x86] =        { RMB,0,                "XCHGB        %r,%e" },
         1314 [0x87] =        { RM,0,                "XCHG%S        %r,%e" },
         1315 [0x88] =        { RMB,0,                "MOVB        %r,%e" },
         1316 [0x89] =        { RM,0,                "MOV%S        %r,%e" },
         1317 [0x8a] =        { RMB,0,                "MOVB        %e,%r" },
         1318 [0x8b] =        { RM,0,                "MOV%S        %e,%r" },
         1319 [0x8c] =        { RM,0,                "MOVW        %g,%e" },
         1320 [0x8d] =        { RM,0,                "LEA%S        %e,%r" },
         1321 [0x8e] =        { RM,0,                "MOVW        %e,%g" },
         1322 [0x8f] =        { RM,0,                "POP%S        %e" },
         1323 [0x90] =        { 0,0,                "NOP" },
         1324 [0x91] =        { 0,0,                "XCHG        %OCX,%OAX" },
         1325 [0x92] =        { 0,0,                "XCHG        %ODX,%OAX" },
         1326 [0x93] =        { 0,0,                "XCHG        %OBX,%OAX" },
         1327 [0x94] =        { 0,0,                "XCHG        %OSP,%OAX" },
         1328 [0x95] =        { 0,0,                "XCHG        %OBP,%OAX" },
         1329 [0x96] =        { 0,0,                "XCHG        %OSI,%OAX" },
         1330 [0x97] =        { 0,0,                "XCHG        %ODI,%OAX" },
         1331 [0x98] =        { 0,0,                "%W" },                        /* miserable CBW or CWDE */
         1332 [0x99] =        { 0,0,                "%w" },                        /* idiotic CWD or CDQ */
         1333 [0x9a] =        { PTR,0,                "CALL%S        %d" },
         1334 [0x9b] =        { 0,0,                "WAIT" },
         1335 [0x9c] =        { 0,0,                "PUSHF" },
         1336 [0x9d] =        { 0,0,                "POPF" },
         1337 [0x9e] =        { 0,0,                "SAHF" },
         1338 [0x9f] =        { 0,0,                "LAHF" },
         1339 [0xa0] =        { Awd,0,                "MOVB        %i,AL" },
         1340 [0xa1] =        { Awd,0,                "MOV%S        %i,%OAX" },
         1341 [0xa2] =        { Awd,0,                "MOVB        AL,%i" },
         1342 [0xa3] =        { Awd,0,                "MOV%S        %OAX,%i" },
         1343 [0xa4] =        { 0,0,                "MOVSB        (%ASI),(%ADI)" },
         1344 [0xa5] =        { 0,0,                "MOVS%S        (%ASI),(%ADI)" },
         1345 [0xa6] =        { 0,0,                "CMPSB        (%ASI),(%ADI)" },
         1346 [0xa7] =        { 0,0,                "CMPS%S        (%ASI),(%ADI)" },
         1347 [0xa8] =        { Ib,0,                "TESTB        %i,AL" },
         1348 [0xa9] =        { Iwd,0,                "TEST%S        %i,%OAX" },
         1349 [0xaa] =        { 0,0,                "STOSB        AL,(%ADI)" },
         1350 [0xab] =        { 0,0,                "STOS%S        %OAX,(%ADI)" },
         1351 [0xac] =        { 0,0,                "LODSB        (%ASI),AL" },
         1352 [0xad] =        { 0,0,                "LODS%S        (%ASI),%OAX" },
         1353 [0xae] =        { 0,0,                "SCASB        (%ADI),AL" },
         1354 [0xaf] =        { 0,0,                "SCAS%S        (%ADI),%OAX" },
         1355 [0xb0] =        { Ib,0,                "MOVB        %i,AL" },
         1356 [0xb1] =        { Ib,0,                "MOVB        %i,CL" },
         1357 [0xb2] =        { Ib,0,                "MOVB        %i,DL" },
         1358 [0xb3] =        { Ib,0,                "MOVB        %i,BL" },
         1359 [0xb4] =        { Ib,0,                "MOVB        %i,AH" },
         1360 [0xb5] =        { Ib,0,                "MOVB        %i,CH" },
         1361 [0xb6] =        { Ib,0,                "MOVB        %i,DH" },
         1362 [0xb7] =        { Ib,0,                "MOVB        %i,BH" },
         1363 [0xb8] =        { Iwdq,0,                "MOV%S        %i,%OAX" },
         1364 [0xb9] =        { Iwdq,0,                "MOV%S        %i,%OCX" },
         1365 [0xba] =        { Iwdq,0,                "MOV%S        %i,%ODX" },
         1366 [0xbb] =        { Iwdq,0,                "MOV%S        %i,%OBX" },
         1367 [0xbc] =        { Iwdq,0,                "MOV%S        %i,%OSP" },
         1368 [0xbd] =        { Iwdq,0,                "MOV%S        %i,%OBP" },
         1369 [0xbe] =        { Iwdq,0,                "MOV%S        %i,%OSI" },
         1370 [0xbf] =        { Iwdq,0,                "MOV%S        %i,%ODI" },
         1371 [0xc0] =        { RMOPB,0,        optabC0 },
         1372 [0xc1] =        { RMOP,0,                optabC1 },
         1373 [0xc2] =        { Iw,0,                "RET        %i" },
         1374 [0xc3] =        { RET,0,                "RET" },
         1375 [0xc4] =        { RM,0,                "LES        %e,%r" },
         1376 [0xc5] =        { RM,0,                "LDS        %e,%r" },
         1377 [0xc6] =        { RMB,Ib,                "MOVB        %i,%e" },
         1378 [0xc7] =        { RM,Iwd,                "MOV%S        %i,%e" },
         1379 [0xc8] =        { Iw2,Ib,                "ENTER        %i,%I" },                /* loony ENTER */
         1380 [0xc9] =        { RET,0,                "LEAVE" },                /* bizarre LEAVE */
         1381 [0xca] =        { Iw,0,                "RETF        %i" },
         1382 [0xcb] =        { RET,0,                "RETF" },
         1383 [0xcc] =        { 0,0,                "INT        3" },
         1384 [0xcd] =        { Ib,0,                "INTB        %i" },
         1385 [0xce] =        { 0,0,                "INTO" },
         1386 [0xcf] =        { 0,0,                "IRET" },
         1387 [0xd0] =        { RMOPB,0,        optabD0 },
         1388 [0xd1] =        { RMOP,0,                optabD1 },
         1389 [0xd2] =        { RMOPB,0,        optabD2 },
         1390 [0xd3] =        { RMOP,0,                optabD3 },
         1391 [0xd4] =        { OA,0,                "AAM" },
         1392 [0xd5] =        { OA,0,                "AAD" },
         1393 [0xd7] =        { 0,0,                "XLAT" },
         1394 [0xd8] =        { FRMOP,0,        optabD8 },
         1395 [0xd9] =        { FRMEX,0,        optabD9 },
         1396 [0xda] =        { FRMOP,0,        optabDA },
         1397 [0xdb] =        { FRMEX,0,        optabDB },
         1398 [0xdc] =        { FRMOP,0,        optabDC },
         1399 [0xdd] =        { FRMOP,0,        optabDD },
         1400 [0xde] =        { FRMOP,0,        optabDE },
         1401 [0xdf] =        { FRMOP,0,        optabDF },
         1402 [0xe0] =        { Jbs,0,                "LOOPNE        %p" },
         1403 [0xe1] =        { Jbs,0,                "LOOPE        %p" },
         1404 [0xe2] =        { Jbs,0,                "LOOP        %p" },
         1405 [0xe3] =        { Jbs,0,                "JCXZ        %p" },
         1406 [0xe4] =        { Ib,0,                "INB        %i,AL" },
         1407 [0xe5] =        { Ib,0,                "IN%S        %i,%OAX" },
         1408 [0xe6] =        { Ib,0,                "OUTB        AL,%i" },
         1409 [0xe7] =        { Ib,0,                "OUT%S        %OAX,%i" },
         1410 [0xe8] =        { Iwds,0,                "CALL        %p" },
         1411 [0xe9] =        { Iwds,0,                "JMP        %p" },
         1412 [0xea] =        { PTR,0,                "JMP        %d" },
         1413 [0xeb] =        { Jbs,0,                "JMP        %p" },
         1414 [0xec] =        { 0,0,                "INB        DX,AL" },
         1415 [0xed] =        { 0,0,                "IN%S        DX,%OAX" },
         1416 [0xee] =        { 0,0,                "OUTB        AL,DX" },
         1417 [0xef] =        { 0,0,                "OUT%S        %OAX,DX" },
         1418 [0xf0] =        { PRE,0,                "LOCK" },
         1419 [0xf2] =        { OPRE,0,                "REPNE" },
         1420 [0xf3] =        { OPRE,0,                "REP" },
         1421 [0xf4] =        { 0,0,                "HLT" },
         1422 [0xf5] =        { 0,0,                "CMC" },
         1423 [0xf6] =        { RMOPB,0,        optabF6 },
         1424 [0xf7] =        { RMOP,0,                optabF7 },
         1425 [0xf8] =        { 0,0,                "CLC" },
         1426 [0xf9] =        { 0,0,                "STC" },
         1427 [0xfa] =        { 0,0,                "CLI" },
         1428 [0xfb] =        { 0,0,                "STI" },
         1429 [0xfc] =        { 0,0,                "CLD" },
         1430 [0xfd] =        { 0,0,                "STD" },
         1431 [0xfe] =        { RMOPB,0,        optabFE },
         1432 [0xff] =        { RMOP,0,                optabFF },
         1433 [0x100] =        { RM,0,                "MOVLQSX        %e,%r" },
         1434 [0x101] =        { RM,0,                "MOVLQZX        %e,%r" },
         1435 };
         1436 
         1437 /*
         1438  *  get a byte of the instruction
         1439  */
         1440 static int
         1441 igetc(Map *map, Instr *ip, uchar *c)
         1442 {
         1443         if(ip->n+1 > sizeof(ip->mem)){
         1444                 werrstr("instruction too long");
         1445                 return -1;
         1446         }
         1447         if (get1(map, ip->addr+ip->n, c, 1) < 0) {
         1448                 werrstr("can't read instruction: %r");
         1449                 return -1;
         1450         }
         1451         ip->mem[ip->n++] = *c;
         1452         return 1;
         1453 }
         1454 
         1455 /*
         1456  *  get two bytes of the instruction
         1457  */
         1458 static int
         1459 igets(Map *map, Instr *ip, ushort *sp)
         1460 {
         1461         uchar c;
         1462         ushort s;
         1463 
         1464         if (igetc(map, ip, &c) < 0)
         1465                 return -1;
         1466         s = c;
         1467         if (igetc(map, ip, &c) < 0)
         1468                 return -1;
         1469         s |= (c<<8);
         1470         *sp = s;
         1471         return 1;
         1472 }
         1473 
         1474 /*
         1475  *  get 4 bytes of the instruction
         1476  */
         1477 static int
         1478 igetl(Map *map, Instr *ip, uint32 *lp)
         1479 {
         1480         ushort s;
         1481         int32        l;
         1482 
         1483         if (igets(map, ip, &s) < 0)
         1484                 return -1;
         1485         l = s;
         1486         if (igets(map, ip, &s) < 0)
         1487                 return -1;
         1488         l |= (s<<16);
         1489         *lp = l;
         1490         return 1;
         1491 }
         1492 
         1493 /*
         1494  *  get 8 bytes of the instruction
         1495  *
         1496 static int
         1497 igetq(Map *map, Instr *ip, vlong *qp)
         1498 {
         1499         uint32        l;
         1500         uvlong q;
         1501 
         1502         if (igetl(map, ip, &l) < 0)
         1503                 return -1;
         1504         q = l;
         1505         if (igetl(map, ip, &l) < 0)
         1506                 return -1;
         1507         q |= ((uvlong)l<<32);
         1508         *qp = q;
         1509         return 1;
         1510 }
         1511  */
         1512 
         1513 static int
         1514 getdisp(Map *map, Instr *ip, int mod, int rm, int code, int pcrel)
         1515 {
         1516         uchar c;
         1517         ushort s;
         1518 
         1519         if (mod > 2)
         1520                 return 1;
         1521         if (mod == 1) {
         1522                 if (igetc(map, ip, &c) < 0)
         1523                         return -1;
         1524                 if (c&0x80)
         1525                         ip->disp = c|0xffffff00;
         1526                 else
         1527                         ip->disp = c&0xff;
         1528         } else if (mod == 2 || rm == code) {
         1529                 if (ip->asize == 'E') {
         1530                         if (igetl(map, ip, &ip->disp) < 0)
         1531                                 return -1;
         1532                         if (mod == 0)
         1533                                 ip->rip = pcrel;
         1534                 } else {
         1535                         if (igets(map, ip, &s) < 0)
         1536                                 return -1;
         1537                         if (s&0x8000)
         1538                                 ip->disp = s|0xffff0000;
         1539                         else
         1540                                 ip->disp = s;
         1541                 }
         1542                 if (mod == 0)
         1543                         ip->base = -1;
         1544         }
         1545         return 1;
         1546 }
         1547 
         1548 static int
         1549 modrm(Map *map, Instr *ip, uchar c)
         1550 {
         1551         uchar rm, mod;
         1552 
         1553         mod = (c>>6)&3;
         1554         rm = c&7;
         1555         ip->mod = mod;
         1556         ip->base = rm;
         1557         ip->reg = (c>>3)&7;
         1558         ip->rip = 0;
         1559         if (mod == 3)                        /* register */
         1560                 return 1;
         1561         if (ip->asize == 0) {                /* 16-bit mode */
         1562                 switch(rm) {
         1563                 case 0:
         1564                         ip->base = BX; ip->index = SI;
         1565                         break;
         1566                 case 1:
         1567                         ip->base = BX; ip->index = DI;
         1568                         break;
         1569                 case 2:
         1570                         ip->base = BP; ip->index = SI;
         1571                         break;
         1572                 case 3:
         1573                         ip->base = BP; ip->index = DI;
         1574                         break;
         1575                 case 4:
         1576                         ip->base = SI;
         1577                         break;
         1578                 case 5:
         1579                         ip->base = DI;
         1580                         break;
         1581                 case 6:
         1582                         ip->base = BP;
         1583                         break;
         1584                 case 7:
         1585                         ip->base = BX;
         1586                         break;
         1587                 default:
         1588                         break;
         1589                 }
         1590                 return getdisp(map, ip, mod, rm, 6, 0);
         1591         }
         1592         if (rm == 4) {        /* scummy sib byte */
         1593                 if (igetc(map, ip, &c) < 0)
         1594                         return -1;
         1595                 ip->ss = (c>>6)&0x03;
         1596                 ip->index = (c>>3)&0x07;
         1597                 if (ip->index == 4)
         1598                         ip->index = -1;
         1599                 ip->base = c&0x07;
         1600                 return getdisp(map, ip, mod, ip->base, 5, 0);
         1601         }
         1602         return getdisp(map, ip, mod, rm, 5, ip->amd64);
         1603 }
         1604 
         1605 static Optable *
         1606 mkinstr(Map *map, Instr *ip, uvlong pc)
         1607 {
         1608         int i, n, norex;
         1609         uchar c;
         1610         ushort s;
         1611         Optable *op, *obase;
         1612         char buf[128];
         1613 
         1614         memset(ip, 0, sizeof(*ip));
         1615         norex = 1;
         1616         ip->base = -1;
         1617         ip->index = -1;
         1618 //        if(asstype == AI8086)
         1619 //                ip->osize = 'W';
         1620 //        else {
         1621                 ip->osize = 'L';
         1622                 ip->asize = 'E';
         1623                 ip->amd64 = (machcpu == &machamd64);
         1624                 norex = 0;
         1625 //        }
         1626         ip->addr = pc;
         1627         if (igetc(map, ip, &c) < 0)
         1628                 return 0;
         1629         obase = optable;
         1630 newop:
         1631         if(ip->amd64 && !norex){
         1632                 if(c >= 0x40 && c <= 0x4f) {
         1633                         ip->rex = c;
         1634                         if(igetc(map, ip, &c) < 0)
         1635                                 return 0;
         1636                 }
         1637                 if(c == 0x63){
         1638                         if(ip->rex&REXW)
         1639                                 op = &obase[0x100];        /* MOVLQSX */
         1640                         else
         1641                                 op = &obase[0x101];        /* MOVLQZX */
         1642                         goto hack;
         1643                 }
         1644         }
         1645         op = &obase[c];
         1646 hack:
         1647         if (op->proto == 0) {
         1648 badop:
         1649                 n = snprint(buf, sizeof(buf), "opcode: ??");
         1650                 for (i = 0; i < ip->n && n < sizeof(buf)-3; i++, n+=2)
         1651                         _hexify(buf+n, ip->mem[i], 1);
         1652                 strcpy(buf+n, "??");
         1653                 werrstr(buf);
         1654                 return 0;
         1655         }
         1656         for(i = 0; i < 2 && op->operand[i]; i++) {
         1657                 switch(op->operand[i]) {
         1658                 case Ib:        /* 8-bit immediate - (no sign extension)*/
         1659                         if (igetc(map, ip, &c) < 0)
         1660                                 return 0;
         1661                         ip->imm = c&0xff;
         1662                         ip->imm64 = ip->imm;
         1663                         break;
         1664                 case Jbs:        /* 8-bit jump immediate (sign extended) */
         1665                         if (igetc(map, ip, &c) < 0)
         1666                                 return 0;
         1667                         if (c&0x80)
         1668                                 ip->imm = c|0xffffff00;
         1669                         else
         1670                                 ip->imm = c&0xff;
         1671                         ip->imm64 = (int32)ip->imm;
         1672                         ip->jumptype = Jbs;
         1673                         break;
         1674                 case Ibs:        /* 8-bit immediate (sign extended) */
         1675                         if (igetc(map, ip, &c) < 0)
         1676                                 return 0;
         1677                         if (c&0x80)
         1678                                 if (ip->osize == 'L')
         1679                                         ip->imm = c|0xffffff00;
         1680                                 else
         1681                                         ip->imm = c|0xff00;
         1682                         else
         1683                                 ip->imm = c&0xff;
         1684                         ip->imm64 = (int32)ip->imm;
         1685                         break;
         1686                 case Iw:        /* 16-bit immediate -> imm */
         1687                         if (igets(map, ip, &s) < 0)
         1688                                 return 0;
         1689                         ip->imm = s&0xffff;
         1690                         ip->imm64 = ip->imm;
         1691                         ip->jumptype = Iw;
         1692                         break;
         1693                 case Iw2:        /* 16-bit immediate -> in imm2*/
         1694                         if (igets(map, ip, &s) < 0)
         1695                                 return 0;
         1696                         ip->imm2 = s&0xffff;
         1697                         break;
         1698                 case Iwd:        /* Operand-sized immediate (no sign extension unless 64 bits)*/
         1699                         if (ip->osize == 'L') {
         1700                                 if (igetl(map, ip, &ip->imm) < 0)
         1701                                         return 0;
         1702                                 ip->imm64 = ip->imm;
         1703                                 if(ip->rex&REXW && (ip->imm & (1<<31)) != 0)
         1704                                         ip->imm64 |= (vlong)(~0ULL << 32);
         1705                         } else {
         1706                                 if (igets(map, ip, &s)< 0)
         1707                                         return 0;
         1708                                 ip->imm = s&0xffff;
         1709                                 ip->imm64 = ip->imm;
         1710                         }
         1711                         break;
         1712                 case Iwdq:        /* Operand-sized immediate, possibly big */
         1713                         if (ip->osize == 'L') {
         1714                                 if (igetl(map, ip, &ip->imm) < 0)
         1715                                         return 0;
         1716                                 ip->imm64 = ip->imm;
         1717                                 if (ip->rex & REXW) {
         1718                                         uint32 l;
         1719                                         if (igetl(map, ip, &l) < 0)
         1720                                                 return 0;
         1721                                         ip->imm64 |= (uvlong)l << 32;
         1722                                 }
         1723                         } else {
         1724                                 if (igets(map, ip, &s)< 0)
         1725                                         return 0;
         1726                                 ip->imm = s&0xffff;
         1727                         }
         1728                         break;
         1729                 case Awd:        /* Address-sized immediate (no sign extension)*/
         1730                         if (ip->asize == 'E') {
         1731                                 if (igetl(map, ip, &ip->imm) < 0)
         1732                                         return 0;
         1733                                 /* TO DO: REX */
         1734                         } else {
         1735                                 if (igets(map, ip, &s)< 0)
         1736                                         return 0;
         1737                                 ip->imm = s&0xffff;
         1738                         }
         1739                         break;
         1740                 case Iwds:        /* Operand-sized immediate (sign extended) */
         1741                         if (ip->osize == 'L') {
         1742                                 if (igetl(map, ip, &ip->imm) < 0)
         1743                                         return 0;
         1744                         } else {
         1745                                 if (igets(map, ip, &s)< 0)
         1746                                         return 0;
         1747                                 if (s&0x8000)
         1748                                         ip->imm = s|0xffff0000;
         1749                                 else
         1750                                         ip->imm = s&0xffff;
         1751                         }
         1752                         ip->jumptype = Iwds;
         1753                         break;
         1754                 case OA:        /* literal 0x0a byte */
         1755                         if (igetc(map, ip, &c) < 0)
         1756                                 return 0;
         1757                         if (c != 0x0a)
         1758                                 goto badop;
         1759                         break;
         1760                 case Op_R0:        /* base register must be R0 */
         1761                         if (ip->base != 0)
         1762                                 goto badop;
         1763                         break;
         1764                 case Op_R1:        /* base register must be R1 */
         1765                         if (ip->base != 1)
         1766                                 goto badop;
         1767                         break;
         1768                 case RMB:        /* R/M field with byte register (/r)*/
         1769                         if (igetc(map, ip, &c) < 0)
         1770                                 return 0;
         1771                         if (modrm(map, ip, c) < 0)
         1772                                 return 0;
         1773                         ip->osize = 'B';
         1774                         break;
         1775                 case RM:        /* R/M field with register (/r) */
         1776                         if (igetc(map, ip, &c) < 0)
         1777                                 return 0;
         1778                         if (modrm(map, ip, c) < 0)
         1779                                 return 0;
         1780                         break;
         1781                 case RMOPB:        /* R/M field with op code (/digit) */
         1782                         if (igetc(map, ip, &c) < 0)
         1783                                 return 0;
         1784                         if (modrm(map, ip, c) < 0)
         1785                                 return 0;
         1786                         c = ip->reg;                /* secondary op code */
         1787                         obase = (Optable*)op->proto;
         1788                         ip->osize = 'B';
         1789                         goto newop;
         1790                 case RMOP:        /* R/M field with op code (/digit) */
         1791                         if (igetc(map, ip, &c) < 0)
         1792                                 return 0;
         1793                         if (modrm(map, ip, c) < 0)
         1794                                 return 0;
         1795                         obase = (Optable*)op->proto;
         1796                         if(ip->amd64 && obase == optab0F01 && c == 0xF8)
         1797                                 return optab0F01F8;
         1798                         c = ip->reg;
         1799                         goto newop;
         1800                 case FRMOP:        /* FP R/M field with op code (/digit) */
         1801                         if (igetc(map, ip, &c) < 0)
         1802                                 return 0;
         1803                         if (modrm(map, ip, c) < 0)
         1804                                 return 0;
         1805                         if ((c&0xc0) == 0xc0)
         1806                                 c = ip->reg+8;                /* 16 entry table */
         1807                         else
         1808                                 c = ip->reg;
         1809                         obase = (Optable*)op->proto;
         1810                         goto newop;
         1811                 case FRMEX:        /* Extended FP R/M field with op code (/digit) */
         1812                         if (igetc(map, ip, &c) < 0)
         1813                                 return 0;
         1814                         if (modrm(map, ip, c) < 0)
         1815                                 return 0;
         1816                         if ((c&0xc0) == 0xc0)
         1817                                 c = (c&0x3f)+8;                /* 64-entry table */
         1818                         else
         1819                                 c = ip->reg;
         1820                         obase = (Optable*)op->proto;
         1821                         goto newop;
         1822                 case RMR:        /* R/M register only (mod = 11) */
         1823                         if (igetc(map, ip, &c) < 0)
         1824                                 return 0;
         1825                         if ((c&0xc0) != 0xc0) {
         1826                                 werrstr("invalid R/M register: %x", c);
         1827                                 return 0;
         1828                         }
         1829                         if (modrm(map, ip, c) < 0)
         1830                                 return 0;
         1831                         break;
         1832                 case RMM:        /* R/M register only (mod = 11) */
         1833                         if (igetc(map, ip, &c) < 0)
         1834                                 return 0;
         1835                         if ((c&0xc0) == 0xc0) {
         1836                                 werrstr("invalid R/M memory mode: %x", c);
         1837                                 return 0;
         1838                         }
         1839                         if (modrm(map, ip, c) < 0)
         1840                                 return 0;
         1841                         break;
         1842                 case PTR:        /* Seg:Displacement addr (ptr16:16 or ptr16:32) */
         1843                         if (ip->osize == 'L') {
         1844                                 if (igetl(map, ip, &ip->disp) < 0)
         1845                                         return 0;
         1846                         } else {
         1847                                 if (igets(map, ip, &s)< 0)
         1848                                         return 0;
         1849                                 ip->disp = s&0xffff;
         1850                         }
         1851                         if (igets(map, ip, (ushort*)&ip->seg) < 0)
         1852                                 return 0;
         1853                         ip->jumptype = PTR;
         1854                         break;
         1855                 case AUXMM:        /* Multi-byte op code; prefix determines table selection */
         1856                         if (igetc(map, ip, &c) < 0)
         1857                                 return 0;
         1858                         obase = (Optable*)op->proto;
         1859                         switch (ip->opre) {
         1860                         case 0x66:        op = optab660F; break;
         1861                         case 0xF2:        op = optabF20F; break;
         1862                         case 0xF3:        op = optabF30F; break;
         1863                         default:        op = nil; break;
         1864                         }
         1865                         if(op != nil && op[c].proto != nil)
         1866                                 obase = op;
         1867                         norex = 1;        /* no more rex prefixes */
         1868                         /* otherwise the optab entry captures it */
         1869                         goto newop;
         1870                 case AUX:        /* Multi-byte op code - Auxiliary table */
         1871                         obase = (Optable*)op->proto;
         1872                         if (igetc(map, ip, &c) < 0)
         1873                                 return 0;
         1874                         goto newop;
         1875                 case OPRE:        /* Instr Prefix or media op */
         1876                         ip->opre = c;
         1877                         /* fall through */
         1878                 case PRE:        /* Instr Prefix */
         1879                         ip->prefix = (char*)op->proto;
         1880                         if (igetc(map, ip, &c) < 0)
         1881                                 return 0;
         1882                         if (ip->opre && c == 0x0F)
         1883                                 ip->prefix = 0;
         1884                         goto newop;
         1885                 case SEG:        /* Segment Prefix */
         1886                         ip->segment = (char*)op->proto;
         1887                         if (igetc(map, ip, &c) < 0)
         1888                                 return 0;
         1889                         goto newop;
         1890                 case OPOVER:        /* Operand size override */
         1891                         ip->opre = c;
         1892                         ip->osize = 'W';
         1893                         if (igetc(map, ip, &c) < 0)
         1894                                 return 0;
         1895                         if (c == 0x0F)
         1896                                 ip->osize = 'L';
         1897                         else if (ip->amd64 && (c&0xF0) == 0x40)
         1898                                 ip->osize = 'Q';
         1899                         goto newop;
         1900                 case ADDOVER:        /* Address size override */
         1901                         ip->asize = 0;
         1902                         if (igetc(map, ip, &c) < 0)
         1903                                 return 0;
         1904                         goto newop;
         1905                 case JUMP:        /* mark instruction as JUMP or RET */
         1906                 case RET:
         1907                         ip->jumptype = op->operand[i];
         1908                         break;
         1909                 default:
         1910                         werrstr("bad operand type %d", op->operand[i]);
         1911                         return 0;
         1912                 }
         1913         }
         1914         return op;
         1915 }
         1916 
         1917 #pragma        varargck        argpos        bprint                2
         1918 
         1919 static void
         1920 bprint(Instr *ip, char *fmt, ...)
         1921 {
         1922         va_list arg;
         1923 
         1924         va_start(arg, fmt);
         1925         ip->curr = vseprint(ip->curr, ip->end, fmt, arg);
         1926         va_end(arg);
         1927 }
         1928 
         1929 /*
         1930  *  if we want to call 16 bit regs AX,BX,CX,...
         1931  *  and 32 bit regs EAX,EBX,ECX,... then
         1932  *  change the defs of ANAME and ONAME to:
         1933  *  #define        ANAME(ip)        ((ip->asize == 'E' ? "E" : "")
         1934  *  #define        ONAME(ip)        ((ip)->osize == 'L' ? "E" : "")
         1935  */
         1936 #define        ANAME(ip)        ""
         1937 #define        ONAME(ip)        ""
         1938 
         1939 static char *reg[] =  {
         1940 [AX] =        "AX",
         1941 [CX] =        "CX",
         1942 [DX] =        "DX",
         1943 [BX] =        "BX",
         1944 [SP] =        "SP",
         1945 [BP] =        "BP",
         1946 [SI] =        "SI",
         1947 [DI] =        "DI",
         1948 
         1949         /* amd64 */
         1950 [AMD64_R8] =        "R8",
         1951 [AMD64_R9] =        "R9",
         1952 [AMD64_R10] =        "R10",
         1953 [AMD64_R11] =        "R11",
         1954 [AMD64_R12] =        "R12",
         1955 [AMD64_R13] =        "R13",
         1956 [AMD64_R14] =        "R14",
         1957 [AMD64_R15] =        "R15",
         1958 };
         1959 
         1960 static char *breg[] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" };
         1961 static char *breg64[] = { "AL", "CL", "DL", "BL", "SPB", "BPB", "SIB", "DIB",
         1962         "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B" };
         1963 static char *sreg[] = { "ES", "CS", "SS", "DS", "FS", "GS" };
         1964 
         1965 static void
         1966 plocal(Instr *ip)
         1967 {
         1968         Symbol s;
         1969         char *name;
         1970         Loc l, li;
         1971 
         1972         l.type = LOFFSET;
         1973         l.offset = ip->disp;
         1974         if(ip->base == SP)
         1975                 l.reg = "SP";
         1976         else
         1977                 l.reg = "BP";
         1978 
         1979         li.type = LADDR;
         1980         li.addr = ip->addr;
         1981         if(findsym(li, CTEXT, &s) < 0)
         1982                 goto raw;
         1983 
         1984         name = nil;
         1985         if(ip->base==SP && lookuplsym(&s, FRAMENAME, &s) >= 0) {
         1986                 /* translate stack offset to offset from plan 9 frame pointer*/
         1987                 /* XXX not sure how to do this */
         1988         }
         1989 
         1990         if(name==nil && findlsym(&s, l, &s) >= 0)
         1991                 name = s.name;
         1992 
         1993         if(name)
         1994                 bprint(ip, "%s+", name);
         1995 
         1996 raw:
         1997         bprint(ip, "%#lx(%s)", l.offset, l.reg);
         1998 /*
         1999         if (s.value > ip->disp) {
         2000                 ret = getauto(&s, s.value-ip->disp-mach->szaddr, CAUTO, &s);
         2001                 reg = "(SP)";
         2002         } else {
         2003                 offset -= s.value;
         2004                 ret = getauto(&s, offset, CPARAM, &s);
         2005                 reg = "(FP)";
         2006         }
         2007         if (ret)
         2008                 bprint(ip, "%s+", s.name);
         2009         else
         2010                 offset = ip->disp;
         2011         bprint(ip, "%ux%s", offset, reg);
         2012 */
         2013 }
         2014 
         2015 static int
         2016 isjmp(Instr *ip)
         2017 {
         2018         switch(ip->jumptype){
         2019         case Iwds:
         2020         case Jbs:
         2021         case JUMP:
         2022                 return 1;
         2023         default:
         2024                 return 0;
         2025         }
         2026 }
         2027 
         2028 /*
         2029  * This is too smart for its own good, but it really is nice
         2030  * to have accurate translations when debugging, and it
         2031  * helps us identify which code is different in binaries that
         2032  * are changed on sources.
         2033  */
         2034 static int
         2035 issymref(Instr *ip, Symbol *s, int32 w, int32 val)
         2036 {
         2037         Symbol next, tmp;
         2038         int32 isstring, size;
         2039 
         2040         if (isjmp(ip))
         2041                 return 1;
         2042         if (s->class==CTEXT && w==0)
         2043                 return 1;
         2044         if (s->class==CDATA) {
         2045                 /* use first bss symbol (or "end") rather than edata */
         2046                 if (s->name[0]=='e' && strcmp(s->name, "edata") == 0){
         2047                         if((indexsym(s->index+1, &tmp) && loccmp(&tmp.loc, &s->loc) == 0)
         2048                         || (indexsym(s->index-1, &tmp) && loccmp(&tmp.loc, &s->loc) == 0))
         2049                                 *s = tmp;
         2050                 }
         2051                 if (w == 0)
         2052                         return 1;
         2053                 for (next=*s; next.loc.addr==s->loc.addr; next=tmp)
         2054                         if (!indexsym(next.index+1, &tmp))
         2055                                 break;
         2056                 size = next.loc.addr - s->loc.addr;
         2057                 if (w >= size)
         2058                         return 0;
         2059                 if (w > size-w)
         2060                         w = size-w;
         2061                 /* huge distances are usually wrong except in .string */
         2062                 isstring = (s->name[0]=='.' && strcmp(s->name, ".string") == 0);
         2063                 if (w > 8192 && !isstring)
         2064                         return 0;
         2065                 /* medium distances are tricky - look for constants */
         2066                 /* near powers of two */
         2067                 if ((val&(val-1)) == 0 || (val&(val+1)) == 0)
         2068                         return 0;
         2069                 return 1;
         2070         }
         2071         return 0;
         2072 }
         2073 
         2074 static void
         2075 immediate(Instr *ip, vlong val)
         2076 {
         2077         Symbol s;
         2078         long w;
         2079         Loc l;
         2080 
         2081         l.type = LADDR;
         2082         l.addr = val;
         2083         if (findsym(l, CANY, &s) >= 0) {                /* TO DO */
         2084                 w = val - s.loc.addr;
         2085                 if (w < 0)
         2086                         w = -w;
         2087                 if (issymref(ip, &s, w, val)) {
         2088                         if (w)
         2089                                 bprint(ip, "%s+%#lux(SB)", s.name, w);
         2090                         else
         2091                                 bprint(ip, "%s(SB)", s.name);
         2092                         return;
         2093                 }
         2094 /*
         2095                 if (s.class==CDATA && globalsym(&s, s.index+1)) {
         2096                         w = s.value - val;
         2097                         if (w < 0)
         2098                                 w = -w;
         2099                         if (w < 4096) {
         2100                                 bprint(ip, "%s-%#lux(SB)", s.name, w);
         2101                                 return;
         2102                         }
         2103                 }
         2104 */
         2105         }
         2106         if((ip->rex & REXW) == 0)
         2107                 bprint(ip, "%lux", (long)val);
         2108         else
         2109                 bprint(ip, "%llux", val);
         2110 }
         2111 
         2112 static void
         2113 pea(Instr *ip)
         2114 {
         2115         if (ip->mod == 3) {
         2116                 if (ip->osize == 'B')
         2117                         bprint(ip, (ip->rex & REXB? breg64: breg)[(uchar)ip->base]);
         2118                 else if(ip->rex & REXB)
         2119                         bprint(ip, "%s%s", ANAME(ip), reg[ip->base+8]);
         2120                 else
         2121                         bprint(ip, "%s%s", ANAME(ip), reg[(uchar)ip->base]);
         2122                 return;
         2123         }
         2124         if (ip->segment)
         2125                 bprint(ip, ip->segment);
         2126         if (ip->asize == 'E' && ip->base == SP)
         2127                 plocal(ip);
         2128         else {
         2129                 if (ip->base < 0)
         2130                         immediate(ip, ip->disp);
         2131                 else {
         2132                         bprint(ip, "%ux", ip->disp);
         2133                         if(ip->rip)
         2134                                 bprint(ip, "(RIP)");
         2135                         bprint(ip,"(%s%s)", ANAME(ip), reg[ip->rex&REXB? ip->base+8: ip->base]);
         2136                 }
         2137         }
         2138         if (ip->index >= 0)
         2139                 bprint(ip,"(%s%s*%d)", ANAME(ip), reg[ip->rex&REXX? ip->index+8: ip->index], 1<<ip->ss);
         2140 }
         2141 
         2142 static void
         2143 prinstr(Instr *ip, char *fmt)
         2144 {
         2145         int sharp;
         2146         vlong v;
         2147 
         2148         if (ip->prefix)
         2149                 bprint(ip, "%s ", ip->prefix);
         2150         for (; *fmt && ip->curr < ip->end; fmt++) {
         2151                 if (*fmt != '%'){
         2152                         *ip->curr++ = *fmt;
         2153                         continue;
         2154                 }
         2155                 sharp = 0;
         2156                 if(*++fmt == '#') {
         2157                         sharp = 1;
         2158                         ++fmt;
         2159                 }
         2160                 switch(*fmt){
         2161                 case '%':
         2162                         *ip->curr++ = '%';
         2163                         break;
         2164                 case 'A':
         2165                         bprint(ip, "%s", ANAME(ip));
         2166                         break;
         2167                 case 'C':
         2168                         bprint(ip, "CR%d", ip->reg);
         2169                         break;
         2170                 case 'D':
         2171                         if (ip->reg < 4 || ip->reg == 6 || ip->reg == 7)
         2172                                 bprint(ip, "DR%d",ip->reg);
         2173                         else
         2174                                 bprint(ip, "???");
         2175                         break;
         2176                 case 'I':
         2177                         bprint(ip, "$");
         2178                         immediate(ip, ip->imm2);
         2179                         break;
         2180                 case 'O':
         2181                         bprint(ip,"%s", ONAME(ip));
         2182                         break;
         2183                 case 'i':
         2184                         if(!sharp)
         2185                                 bprint(ip, "$");
         2186                         v = ip->imm;
         2187                         if(ip->rex & REXW)
         2188                                 v = ip->imm64;
         2189                         immediate(ip, v);
         2190                         break;
         2191                 case 'R':
         2192                         bprint(ip, "%s%s", ONAME(ip), reg[ip->rex&REXR? ip->reg+8: ip->reg]);
         2193                         break;
         2194                 case 'S':
         2195                         if(ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW)
         2196                                 bprint(ip, "Q");
         2197                         else
         2198                                 bprint(ip, "%c", ip->osize);
         2199                         break;
         2200                 case 's':
         2201                         if(ip->opre == 0 || ip->opre == 0x66)
         2202                                 bprint(ip, "P");
         2203                         else
         2204                                 bprint(ip, "S");
         2205                         if(ip->opre == 0xf2 || ip->opre == 0x66)
         2206                                 bprint(ip, "D");
         2207                         else
         2208                                 bprint(ip, "S");
         2209                         break;
         2210                 case 'T':
         2211                         if (ip->reg == 6 || ip->reg == 7)
         2212                                 bprint(ip, "TR%d",ip->reg);
         2213                         else
         2214                                 bprint(ip, "???");
         2215                         break;
         2216                 case 'W':
         2217                         if (ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW)
         2218                                 bprint(ip, "CDQE");
         2219                         else if (ip->osize == 'L')
         2220                                 bprint(ip,"CWDE");
         2221                         else
         2222                                 bprint(ip, "CBW");
         2223                         break;
         2224                 case 'd':
         2225                         bprint(ip,"%ux:%ux", ip->seg, ip->disp);
         2226                         break;
         2227                 case 'm':
         2228                         if (ip->mod == 3 && ip->osize != 'B') {
         2229                                 if(fmt[1] != '*'){
         2230                                         if(ip->opre != 0) {
         2231                                                 bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base);
         2232                                                 break;
         2233                                         }
         2234                                 } else
         2235                                         fmt++;
         2236                                 bprint(ip, "M%d", ip->base);
         2237                                 break;
         2238                         }
         2239                         pea(ip);
         2240                         break;
         2241                 case 'e':
         2242                         pea(ip);
         2243                         break;
         2244                 case 'f':
         2245                         bprint(ip, "F%d", ip->base);
         2246                         break;
         2247                 case 'g':
         2248                         if (ip->reg < 6)
         2249                                 bprint(ip,"%s",sreg[ip->reg]);
         2250                         else
         2251                                 bprint(ip,"???");
         2252                         break;
         2253                 case 'p':
         2254                         /*
         2255                          * signed immediate in the uint32 ip->imm.
         2256                          */
         2257                         v = (int32)ip->imm;
         2258                         immediate(ip, v+ip->addr+ip->n);
         2259                         break;
         2260                 case 'r':
         2261                         if (ip->osize == 'B')
         2262                                 bprint(ip,"%s", (ip->rex? breg64: breg)[ip->rex&REXR? ip->reg+8: ip->reg]);
         2263                         else
         2264                                 bprint(ip, reg[ip->rex&REXR? ip->reg+8: ip->reg]);
         2265                         break;
         2266                 case 'w':
         2267                         if (ip->osize == 'Q' || ip->rex & REXW)
         2268                                 bprint(ip, "CQO");
         2269                         else if (ip->osize == 'L')
         2270                                 bprint(ip,"CDQ");
         2271                         else
         2272                                 bprint(ip, "CWD");
         2273                         break;
         2274                 case 'M':
         2275                         if(ip->opre != 0)
         2276                                 bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg);
         2277                         else
         2278                                 bprint(ip, "M%d", ip->reg);
         2279                         break;
         2280                 case 'x':
         2281                         if (ip->mod == 3 && ip->osize != 'B') {
         2282                                 bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base);
         2283                                 break;
         2284                         }
         2285                         pea(ip);
         2286                         break;
         2287                 case 'X':
         2288                         bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg);
         2289                         break;
         2290                 default:
         2291                         bprint(ip, "%%%c", *fmt);
         2292                         break;
         2293                 }
         2294         }
         2295         *ip->curr = 0;                /* there's always room for 1 byte */
         2296 }
         2297 
         2298 int
         2299 i386das(Map *map, uvlong pc, char modifier, char *buf, int n)
         2300 {
         2301         Instr instr;
         2302         Optable *op;
         2303 
         2304         USED(modifier);
         2305         op = mkinstr(map, &instr, pc);
         2306         if (op == 0) {
         2307                 errstr(buf, n);
         2308                 return -1;
         2309         }
         2310         instr.curr = buf;
         2311         instr.end = buf+n-1;
         2312         prinstr(&instr, op->proto);
         2313         return instr.n;
         2314 }
         2315 
         2316 int
         2317 i386hexinst(Map *map, u64int pc, char *buf, int n)
         2318 {
         2319         Instr instr;
         2320         int i;
         2321 
         2322         if (mkinstr(map, &instr, pc) == 0) {
         2323                 errstr(buf, n);
         2324                 return -1;
         2325         }
         2326         for(i = 0; i < instr.n && n > 2; i++) {
         2327                 _hexify(buf, instr.mem[i], 1);
         2328                 buf += 2;
         2329                 n -= 2;
         2330         }
         2331         *buf = 0;
         2332         return instr.n;
         2333 }
         2334 
         2335 int
         2336 i386instlen(Map *map, u64int pc)
         2337 {
         2338         Instr i;
         2339 
         2340         if (mkinstr(map, &i, pc))
         2341                 return i.n;
         2342         return -1;
         2343 }
         2344 
         2345 int
         2346 i386foll(Map *map, Regs *regs, u64int pc, u64int *foll)
         2347 {
         2348         Instr i;
         2349         Optable *op;
         2350         ushort s;
         2351         u64int l, addr;
         2352         vlong v;
         2353         int n;
         2354 
         2355         op = mkinstr(map, &i, pc);
         2356         if (!op)
         2357                 return -1;
         2358 
         2359         n = 0;
         2360 
         2361         switch(i.jumptype) {
         2362         case RET:                /* RETURN or LEAVE */
         2363         case Iw:                /* RETURN */
         2364                 if (strcmp(op->proto, "LEAVE") == 0) {
         2365                         if (lgeta(map, regs, locindir("BP", 0), &l) < 0)
         2366                                 return -1;
         2367                 } else if (lgeta(map, regs, locindir(mach->sp, 0), &l) < 0)
         2368                         return -1;
         2369                 foll[0] = l;
         2370                 return 1;
         2371         case Iwds:                /* pc relative JUMP or CALL*/
         2372         case Jbs:                /* pc relative JUMP or CALL */
         2373                 v = (int32)i.imm;
         2374                 foll[0] = pc+v+i.n;
         2375                 n = 1;
         2376                 break;
         2377         case PTR:                /* seg:displacement JUMP or CALL */
         2378                 foll[0] = (i.seg<<4)+i.disp;
         2379                 return 1;
         2380         case JUMP:                /* JUMP or CALL EA */
         2381 
         2382                 if(i.mod == 3) {
         2383                         if (rget(regs, reg[i.rex&REXB? i.base+8: i.base], &foll[0]) < 0)
         2384                                 return -1;
         2385                         return 1;
         2386                 }
         2387                         /* calculate the effective address */
         2388                 addr = i.disp;
         2389                 if (i.base >= 0) {
         2390                         if (lgeta(map, regs, locindir(reg[i.rex&REXB? i.base+8: i.base], 0), &l) < 0)
         2391                                 return -1;
         2392                         addr += l;
         2393                 }
         2394                 if (i.index >= 0) {
         2395                         if (lgeta(map, regs, locindir(reg[i.rex&REXX? i.index+8: i.index], 0), &l) < 0)
         2396                                 return -1;
         2397                         addr += l*(1<<i.ss);
         2398                 }
         2399                         /* now retrieve a seg:disp value at that address */
         2400                 if (get2(map, addr, &s) < 0)                        /* seg */
         2401                         return -1;
         2402                 foll[0] = s<<4;
         2403                 addr += 2;
         2404                 if (i.asize == 'L') {
         2405                         if (geta(map, addr, &l) < 0)                /* disp32 */
         2406                                 return -1;
         2407                         foll[0] += l;
         2408                 } else {                                        /* disp16 */
         2409                         if (get2(map, addr, &s) < 0)
         2410                                 return -1;
         2411                         foll[0] += s;
         2412                 }
         2413                 return 1;
         2414         default:
         2415                 break;
         2416         }
         2417         if (strncmp(op->proto,"JMP", 3) == 0 || strncmp(op->proto,"CALL", 4) == 0)
         2418                 return 1;
         2419         foll[n++] = pc+i.n;
         2420         return n;
         2421 }