#include <lib9.h>#include <bio.h>#include "mach.h" /* * i386-specific debugger interface * also amd64 extensions */ static char *i386excep(Map*, Rgetter); static int i386trace(Map*, uvlong, uvlong, uvlong, Tracer);static uvlong i386frame(Map*, uvlong, uvlong, uvlong, uvlong);static int i386foll(Map*, uvlong, Rgetter, uvlong*);static int i386inst(Map*, uvlong, char, char*, int);static int i386das(Map*, uvlong, char*, int);static int i386instlen(Map*, uvlong); static char STARTSYM[] = "_main";static char PROFSYM[] = "_mainp";static char FRAMENAME[] = ".frame";static char *excname[65] ={/*[0]*/ "divide error",/*[1]*/ "debug exception",/*[2]*/ nil,/*[3]*/ nil,/*[4]*/ "overflow",/*[5]*/ "bounds check",/*[6]*/ "invalid opcode",/*[7]*/ "math coprocessor emulation",/*[8]*/ "double fault",/*[9]*/ "math coprocessor overrun",/*[10]*/ "invalid TSS",/*[11]*/ "segment not present",/*[12]*/ "stack exception",/*[13]*/ "general protection violation",/*[14]*/ "page fault",/*[15]*/ nil,/*[16]*/ "math coprocessor error",/*[17]*/ "alignment check",/*[18]*/ "machine check",/*[19]*/ "floating-point exception",/*[20]*/ nil,/*[21]*/ nil,/*[22]*/ nil,/*[23]*/ nil,/*[24]*/ "clock",/*[25]*/ "keyboard",/*[26]*/ nil,/*[27]*/ "modem status",/*[28]*/ "serial line status",/*[29]*/ nil,/*[30]*/ "floppy disk",/*[31]*/ nil,/*[32]*/ nil,/*[33]*/ nil,/*[34]*/ nil,/*[35]*/ nil,/*[36]*/ "mouse",/*[37]*/ "math coprocessor",/*[38]*/ "hard disk", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,/* 39-54 */ 0,0,0,0,0,0,0,0,0, /* 55-63 *//*[64]*/ "system call",}; Machdata i386mach ={ {0xCC, 0, 0, 0}, /* break point: INT 3 */ 1, /* break point size */ leswab, /* convert short to local byte order */ leswal, /* convert long to local byte order */ leswav, /* convert vlong to local byte order */ i386trace, /* C traceback */ i386frame, /* frame finder */ i386excep, /* print exception */ 0, /* breakpoint fixup */ leieeesftos, /* single precision float printer */ leieeedftos, /* double precision float printer */ i386foll, /* following addresses */ i386inst, /* print instruction */ i386das, /* dissembler */ i386instlen, /* instruction size calculation */}; static char*i386excep(Map *map, Rgetter rget){ ulong c; uvlong pc; static char buf[16]; c = (*rget)(map, "TRAP"); if(c > 64 || excname[c] == 0) { if (c == 3) { pc = (*rget)(map, "PC"); if (get1(map, pc, (uchar*)buf, machdata->bpsize) > 0) if (memcmp(buf, machdata->bpinst, machdata->bpsize) == 0) return "breakpoint"; } snprint(buf, sizeof(buf), "exception %ld", c); return buf; } else return excname[c];} static inti386trace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace){ int i; uvlong osp; Symbol s, f; USED(link); i = 0; osp = 0; while(findsym(pc, CTEXT, &s)) { if (osp == sp) break; osp = sp; if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0) break; if(pc != s.value) { /* not at first instruction */ if(findlocal(&s, FRAMENAME, &f) == 0) break; sp += f.value-mach->szaddr; } if (geta(map, sp, &pc) < 0) break; if(pc == 0) break; (*trace)(map, pc, sp, &s); sp += mach->szaddr; if(++i > 1000) break; } return i;} static uvlongi386frame(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link){ Symbol s, f; USED(link); while (findsym(pc, CTEXT, &s)) { if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0) break; if(pc != s.value) { /* not first instruction */ if(findlocal(&s, FRAMENAME, &f) == 0) break; sp += f.value-mach->szaddr; } if (s.value == addr) return sp; if (geta(map, sp, &pc) < 0) break; sp += mach->szaddr; } return 0;} /* I386/486 - Disassembler and related functions */ /* * an instruction */typedef struct Instr Instr;struct Instr{ uchar mem[1+1+1+1+2+1+1+4+4]; /* raw instruction */ uvlong addr; /* address of start of instruction */ int n; /* number of bytes in instruction */ char *prefix; /* instr prefix */ char *segment; /* segment override */ uchar jumptype; /* set to the operand type for jump/ret/call */ uchar amd64; uchar rex; /* REX prefix (or zero) */ char osize; /* 'W' or 'L' (or 'Q' on amd64) */ char asize; /* address size 'W' or 'L' (or 'Q' or amd64) */ uchar mod; /* bits 6-7 of mod r/m field */ uchar reg; /* bits 3-5 of mod r/m field */ char ss; /* bits 6-7 of SIB */ char index; /* bits 3-5 of SIB */ char base; /* bits 0-2 of SIB */ char rip; /* RIP-relative in amd64 mode */ uchar opre; /* f2/f3 could introduce media */ short seg; /* segment of far address */ ulong disp; /* displacement */ ulong imm; /* immediate */ ulong imm2; /* second immediate operand */ uvlong imm64; /* big immediate */ char *curr; /* fill level in output buffer */ char *end; /* end of output buffer */ char *err; /* error message */}; /* 386 register (ha!) set */enum{ AX=0, CX, DX, BX, SP, BP, SI, DI, /* amd64 */ R8, R9, R10, R11, R12, R13, R14, R15}; /* amd64 rex extension byte */enum{ REXW = 1<<3, /* =1, 64-bit operand size */ REXR = 1<<2, /* extend modrm reg */ REXX = 1<<1, /* extend sib index */ REXB = 1<<0 /* extend modrm r/m, sib base, or opcode reg */}; /* Operand Format codes *//*%A - address size register modifier (!asize -> 'E')%C - Control register CR0/CR1/CR2%D - Debug register DR0/DR1/DR2/DR3/DR6/DR7%I - second immediate operand%O - Operand size register modifier (!osize -> 'E')%T - Test register TR6/TR7%S - size code ('W' or 'L')%W - Weird opcode: OSIZE == 'W' => "CBW"; else => "CWDE"%d - displacement 16-32 bits%e - effective address - Mod R/M value%f - floating point register F0-F7 - from Mod R/M register%g - segment register%i - immediate operand 8-32 bits%p - PC-relative - signed displacement in immediate field%r - Reg from Mod R/M%w - Weird opcode: OSIZE == 'W' => "CWD"; else => "CDQ"*/ typedef struct Optable Optable;struct Optable{ int x; char operand[2]; void *proto; /* actually either (char*) or (Optable*) */}; /* Operand decoding codes */enum { Ib = 1, /* 8-bit immediate - (no sign extension)*/ Ibs, /* 8-bit immediate (sign extended) */ Jbs, /* 8-bit sign-extended immediate in jump or call */ Iw, /* 16-bit immediate -> imm */ Iw2, /* 16-bit immediate -> imm2 */ Iwd, /* Operand-sized immediate (no sign extension)*/ Iwdq, /* Operand-sized immediate, possibly 64 bits */ Awd, /* Address offset */ Iwds, /* Operand-sized immediate (sign extended) */ RM, /* Word or long R/M field with register (/r) */ RMB, /* Byte R/M field with register (/r) */ RMOP, /* Word or long R/M field with op code (/digit) */ RMOPB, /* Byte R/M field with op code (/digit) */ RMR, /* R/M register only (mod = 11) */ RMM, /* R/M memory only (mod = 0/1/2) */ R0, /* Base reg of Mod R/M is literal 0x00 */ R1, /* Base reg of Mod R/M is literal 0x01 */ FRMOP, /* Floating point R/M field with opcode */ FRMEX, /* Extended floating point R/M field with opcode */ JUMP, /* Jump or Call flag - no operand */ RET, /* Return flag - no operand */ OA, /* literal 0x0a byte */ PTR, /* Seg:Displacement addr (ptr16:16 or ptr16:32) */ AUX, /* Multi-byte op code - Auxiliary table */ AUXMM, /* multi-byte op code - auxiliary table chosen by prefix */ PRE, /* Instr Prefix */ OPRE, /* Instr Prefix or media op extension */ SEG, /* Segment Prefix */ OPOVER, /* Operand size override */ ADDOVER, /* Address size override */}; static Optable optab0F00[8]={0x00, 0,0, "MOVW LDT,%e",0x01, 0,0, "MOVW TR,%e",0x02, 0,0, "MOVW %e,LDT",0x03, 0,0, "MOVW %e,TR",0x04, 0,0, "VERR %e",0x05, 0,0, "VERW %e",}; static Optable optab0F01[8]={0x00, 0,0, "MOVL GDTR,%e",0x01, 0,0, "MOVL IDTR,%e",0x02, 0,0, "MOVL %e,GDTR",0x03, 0,0, "MOVL %e,IDTR",0x04, 0,0, "MOVW MSW,%e", /* word */0x06, 0,0, "MOVW %e,MSW", /* word */0x07, 0,0, "INVLPG %e", /* or SWAPGS */}; static Optable optab0F01F8[1]={0x00, 0,0, "SWAPGS",}; /* 0F71 *//* 0F72 *//* 0F73 */ static Optable optab0FAE[8]={0x00, 0,0, "FXSAVE %e",0x01, 0,0, "FXRSTOR %e",0x02, 0,0, "LDMXCSR %e",0x03, 0,0, "STMXCSR %e",0x05, 0,0, "LFENCE",0x06, 0,0, "MFENCE",0x07, 0,0, "SFENCE",}; /* 0F18 *//* 0F0D */ static Optable optab0FBA[8]={0x04, Ib,0, "BT%S %i,%e",0x05, Ib,0, "BTS%S %i,%e",0x06, Ib,0, "BTR%S %i,%e",0x07, Ib,0, "BTC%S %i,%e",}; static Optable optab0F0F[256]={0x0c, 0,0, "PI2FW %m,%M",0x0d, 0,0, "PI2L %m,%M",0x1c, 0,0, "PF2IW %m,%M",0x1d, 0,0, "PF2IL %m,%M",0x8a, 0,0, "PFNACC %m,%M",0x8e, 0,0, "PFPNACC %m,%M",0x90, 0,0, "PFCMPGE %m,%M",0x94, 0,0, "PFMIN %m,%M",0x96, 0,0, "PFRCP %m,%M",0x97, 0,0, "PFRSQRT %m,%M",0x9a, 0,0, "PFSUB %m,%M",0x9e, 0,0, "PFADD %m,%M",0xa0, 0,0, "PFCMPGT %m,%M",0xa4, 0,0, "PFMAX %m,%M",0xa6, 0,0, "PFRCPIT1 %m,%M",0xa7, 0,0, "PFRSQIT1 %m,%M",0xaa, 0,0, "PFSUBR %m,%M",0xae, 0,0, "PFACC %m,%M",0xb0, 0,0, "PFCMPEQ %m,%M",0xb4, 0,0, "PFMUL %m,%M",0xb6, 0,0, "PFRCPI2T %m,%M",0xb7, 0,0, "PMULHRW %m,%M",0xbb, 0,0, "PSWAPL %m,%M",}; static Optable optab0FC7[8]={0x01, 0,0, "CMPXCHG8B %e",}; static Optable optab660F71[8]={0x02, Ib,0, "PSRLW %i,%X",0x04, Ib,0, "PSRAW %i,%X",0x06, Ib,0, "PSLLW %i,%X",}; static Optable optab660F72[8]={0x02, Ib,0, "PSRLL %i,%X",0x04, Ib,0, "PSRAL %i,%X",0x06, Ib,0, "PSLLL %i,%X",}; static Optable optab660F73[8]={0x02, Ib,0, "PSRLQ %i,%X",0x03, Ib,0, "PSRLO %i,%X",0x06, Ib,0, "PSLLQ %i,%X",0x07, Ib,0, "PSLLO %i,%X",}; static Optable optab660F[256]={0x2B, RM,0, "MOVNTPD %x,%e",0x2E, RM,0, "UCOMISD %x,%X",0x2F, RM,0, "COMISD %x,%X",0x5A, RM,0, "CVTPD2PS %x,%X",0x5B, RM,0, "CVTPS2PL %x,%X",0x6A, RM,0, "PUNPCKHLQ %x,%X",0x6B, RM,0, "PACKSSLW %x,%X",0x6C, RM,0, "PUNPCKLQDQ %x,%X",0x6D, RM,0, "PUNPCKHQDQ %x,%X",0x6E, RM,0, "MOV%S %e,%X",0x6F, RM,0, "MOVO %x,%X", /* MOVDQA */0x70, RM,Ib, "PSHUFL %i,%x,%X",0x71, RMOP,0, optab660F71,0x72, RMOP,0, optab660F72,0x73, RMOP,0, optab660F73,0x7E, RM,0, "MOV%S %X,%e",0x7F, RM,0, "MOVO %X,%x",0xC4, RM,Ib, "PINSRW %i,%e,%X",0xC5, RMR,Ib, "PEXTRW %i,%X,%e",0xD4, RM,0, "PADDQ %x,%X",0xD5, RM,0, "PMULLW %x,%X",0xD6, RM,0, "MOVQ %X,%x",0xE6, RM,0, "CVTTPD2PL %x,%X",0xE7, RM,0, "MOVNTO %X,%e",0xF7, RM,0, "MASKMOVOU %x,%X",}; static Optable optabF20F[256]={0x10, RM,0, "MOVSD %x,%X",0x11, RM,0, "MOVSD %X,%x",0x2A, RM,0, "CVTS%S2SD %e,%X",0x2C, RM,0, "CVTTSD2S%S %x,%r",0x2D, RM,0, "CVTSD2S%S %x,%r",0x5A, RM,0, "CVTSD2SS %x,%X",0x6F, RM,0, "MOVOU %x,%X",0x70, RM,Ib, "PSHUFLW %i,%x,%X",0x7F, RM,0, "MOVOU %X,%x",0xD6, RM,0, "MOVQOZX %M,%X",0xE6, RM,0, "CVTPD2PL %x,%X",}; static Optable optabF30F[256]={0x10, RM,0, "MOVSS %x,%X",0x11, RM,0, "MOVSS %X,%x",0x2A, RM,0, "CVTS%S2SS %e,%X",0x2C, RM,0, "CVTTSS2S%S %x,%r",0x2D, RM,0, "CVTSS2S%S %x,%r",0x5A, RM,0, "CVTSS2SD %x,%X",0x5B, RM,0, "CVTTPS2PL %x,%X",0x6F, RM,0, "MOVOU %x,%X",0x70, RM,Ib, "PSHUFHW %i,%x,%X",0x7E, RM,0, "MOVQOZX %x,%X",0x7F, RM,0, "MOVOU %X,%x",0xD6, RM,0, "MOVQOZX %m*,%X",0xE6, RM,0, "CVTPL2PD %x,%X",}; static Optable optab0F[256]={0x00, RMOP,0, optab0F00,0x01, RMOP,0, optab0F01,0x02, RM,0, "LAR %e,%r",0x03, RM,0, "LSL %e,%r",0x05, 0,0, "SYSCALL",0x06, 0,0, "CLTS",0x07, 0,0, "SYSRET",0x08, 0,0, "INVD",0x09, 0,0, "WBINVD",0x0B, 0,0, "UD2",0x0F, RM,AUX, optab0F0F, /* 3DNow! */0x10, RM,0, "MOVU%s %x,%X",0x11, RM,0, "MOVU%s %X,%x",0x12, RM,0, "MOV[H]L%s %x,%X", /* TO DO: H if source is XMM */0x13, RM,0, "MOVL%s %X,%e",0x14, RM,0, "UNPCKL%s %x,%X",0x15, RM,0, "UNPCKH%s %x,%X",0x16, RM,0, "MOV[L]H%s %x,%X", /* TO DO: L if source is XMM */0x17, RM,0, "MOVH%s %X,%x",0x20, RMR,0, "MOVL %C,%e",0x21, RMR,0, "MOVL %D,%e",0x22, RMR,0, "MOVL %e,%C",0x23, RMR,0, "MOVL %e,%D",0x24, RMR,0, "MOVL %T,%e",0x26, RMR,0, "MOVL %e,%T",0x28, RM,0, "MOVA%s %x,%X",0x29, RM,0, "MOVA%s %X,%x",0x2A, RM,0, "CVTPL2%s %m*,%X",0x2B, RM,0, "MOVNT%s %X,%e",0x2C, RM,0, "CVTT%s2PL %x,%M",0x2D, RM,0, "CVT%s2PL %x,%M",0x2E, RM,0, "UCOMISS %x,%X",Lines 1–500 of 2266. Load more
#include <lib9.h> #include <bio.h> #include "mach.h" /* * i386-specific debugger interface * also amd64 extensions */ static char *i386excep(Map*, Rgetter); static int i386trace(Map*, uvlong, uvlong, uvlong, Tracer); static uvlong i386frame(Map*, uvlong, uvlong, uvlong, uvlong); static int i386foll(Map*, uvlong, Rgetter, uvlong*); static int i386inst(Map*, uvlong, char, char*, int); static int i386das(Map*, uvlong, char*, int); static int i386instlen(Map*, uvlong); static char STARTSYM[] = "_main"; static char PROFSYM[] = "_mainp"; static char FRAMENAME[] = ".frame"; static char *excname[65] = { /*[0]*/ "divide error", /*[1]*/ "debug exception", /*[2]*/ nil, /*[3]*/ nil, /*[4]*/ "overflow", /*[5]*/ "bounds check", /*[6]*/ "invalid opcode", /*[7]*/ "math coprocessor emulation", /*[8]*/ "double fault", /*[9]*/ "math coprocessor overrun", /*[10]*/ "invalid TSS", /*[11]*/ "segment not present", /*[12]*/ "stack exception", /*[13]*/ "general protection violation", /*[14]*/ "page fault", /*[15]*/ nil, /*[16]*/ "math coprocessor error", /*[17]*/ "alignment check", /*[18]*/ "machine check", /*[19]*/ "floating-point exception", /*[20]*/ nil, /*[21]*/ nil, /*[22]*/ nil, /*[23]*/ nil, /*[24]*/ "clock", /*[25]*/ "keyboard", /*[26]*/ nil, /*[27]*/ "modem status", /*[28]*/ "serial line status", /*[29]*/ nil, /*[30]*/ "floppy disk", /*[31]*/ nil, /*[32]*/ nil, /*[33]*/ nil, /*[34]*/ nil, /*[35]*/ nil, /*[36]*/ "mouse", /*[37]*/ "math coprocessor", /*[38]*/ "hard disk", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,/* 39-54 */ 0,0,0,0,0,0,0,0,0, /* 55-63 */ /*[64]*/ "system call", }; Machdata i386mach = { {0xCC, 0, 0, 0}, /* break point: INT 3 */ 1, /* break point size */ leswab, /* convert short to local byte order */ leswal, /* convert long to local byte order */ leswav, /* convert vlong to local byte order */ i386trace, /* C traceback */ i386frame, /* frame finder */ i386excep, /* print exception */ 0, /* breakpoint fixup */ leieeesftos, /* single precision float printer */ leieeedftos, /* double precision float printer */ i386foll, /* following addresses */ i386inst, /* print instruction */ i386das, /* dissembler */ i386instlen, /* instruction size calculation */ }; static char* i386excep(Map *map, Rgetter rget) { ulong c; uvlong pc; static char buf[16]; c = (*rget)(map, "TRAP"); if(c > 64 || excname[c] == 0) { if (c == 3) { pc = (*rget)(map, "PC"); if (get1(map, pc, (uchar*)buf, machdata->bpsize) > 0) if (memcmp(buf, machdata->bpinst, machdata->bpsize) == 0) return "breakpoint"; } snprint(buf, sizeof(buf), "exception %ld", c); return buf; } else return excname[c]; } static int i386trace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace) { int i; uvlong osp; Symbol s, f; USED(link); i = 0; osp = 0; while(findsym(pc, CTEXT, &s)) { if (osp == sp) break; osp = sp; if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0) break; if(pc != s.value) { /* not at first instruction */ if(findlocal(&s, FRAMENAME, &f) == 0) break; sp += f.value-mach->szaddr; } if (geta(map, sp, &pc) < 0) break; if(pc == 0) break; (*trace)(map, pc, sp, &s); sp += mach->szaddr; if(++i > 1000) break; } return i; } static uvlong i386frame(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link) { Symbol s, f; USED(link); while (findsym(pc, CTEXT, &s)) { if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0) break; if(pc != s.value) { /* not first instruction */ if(findlocal(&s, FRAMENAME, &f) == 0) break; sp += f.value-mach->szaddr; } if (s.value == addr) return sp; if (geta(map, sp, &pc) < 0) break; sp += mach->szaddr; } return 0; } /* I386/486 - Disassembler and related functions */ /* * an instruction */ typedef struct Instr Instr; struct Instr { uchar mem[1+1+1+1+2+1+1+4+4]; /* raw instruction */ uvlong addr; /* address of start of instruction */ int n; /* number of bytes in instruction */ char *prefix; /* instr prefix */ char *segment; /* segment override */ uchar jumptype; /* set to the operand type for jump/ret/call */ uchar amd64; uchar rex; /* REX prefix (or zero) */ char osize; /* 'W' or 'L' (or 'Q' on amd64) */ char asize; /* address size 'W' or 'L' (or 'Q' or amd64) */ uchar mod; /* bits 6-7 of mod r/m field */ uchar reg; /* bits 3-5 of mod r/m field */ char ss; /* bits 6-7 of SIB */ char index; /* bits 3-5 of SIB */ char base; /* bits 0-2 of SIB */ char rip; /* RIP-relative in amd64 mode */ uchar opre; /* f2/f3 could introduce media */ short seg; /* segment of far address */ ulong disp; /* displacement */ ulong imm; /* immediate */ ulong imm2; /* second immediate operand */ uvlong imm64; /* big immediate */ char *curr; /* fill level in output buffer */ char *end; /* end of output buffer */ char *err; /* error message */ }; /* 386 register (ha!) set */ enum{ AX=0, CX, DX, BX, SP, BP, SI, DI, /* amd64 */ R8, R9, R10, R11, R12, R13, R14, R15 }; /* amd64 rex extension byte */ enum{ REXW = 1<<3, /* =1, 64-bit operand size */ REXR = 1<<2, /* extend modrm reg */ REXX = 1<<1, /* extend sib index */ REXB = 1<<0 /* extend modrm r/m, sib base, or opcode reg */ }; /* Operand Format codes */ /* %A - address size register modifier (!asize -> 'E') %C - Control register CR0/CR1/CR2 %D - Debug register DR0/DR1/DR2/DR3/DR6/DR7 %I - second immediate operand %O - Operand size register modifier (!osize -> 'E') %T - Test register TR6/TR7 %S - size code ('W' or 'L') %W - Weird opcode: OSIZE == 'W' => "CBW"; else => "CWDE" %d - displacement 16-32 bits %e - effective address - Mod R/M value %f - floating point register F0-F7 - from Mod R/M register %g - segment register %i - immediate operand 8-32 bits %p - PC-relative - signed displacement in immediate field %r - Reg from Mod R/M %w - Weird opcode: OSIZE == 'W' => "CWD"; else => "CDQ" */ typedef struct Optable Optable; struct Optable { int x; char operand[2]; void *proto; /* actually either (char*) or (Optable*) */ }; /* Operand decoding codes */ enum { Ib = 1, /* 8-bit immediate - (no sign extension)*/ Ibs, /* 8-bit immediate (sign extended) */ Jbs, /* 8-bit sign-extended immediate in jump or call */ Iw, /* 16-bit immediate -> imm */ Iw2, /* 16-bit immediate -> imm2 */ Iwd, /* Operand-sized immediate (no sign extension)*/ Iwdq, /* Operand-sized immediate, possibly 64 bits */ Awd, /* Address offset */ Iwds, /* Operand-sized immediate (sign extended) */ RM, /* Word or long R/M field with register (/r) */ RMB, /* Byte R/M field with register (/r) */ RMOP, /* Word or long R/M field with op code (/digit) */ RMOPB, /* Byte R/M field with op code (/digit) */ RMR, /* R/M register only (mod = 11) */ RMM, /* R/M memory only (mod = 0/1/2) */ R0, /* Base reg of Mod R/M is literal 0x00 */ R1, /* Base reg of Mod R/M is literal 0x01 */ FRMOP, /* Floating point R/M field with opcode */ FRMEX, /* Extended floating point R/M field with opcode */ JUMP, /* Jump or Call flag - no operand */ RET, /* Return flag - no operand */ OA, /* literal 0x0a byte */ PTR, /* Seg:Displacement addr (ptr16:16 or ptr16:32) */ AUX, /* Multi-byte op code - Auxiliary table */ AUXMM, /* multi-byte op code - auxiliary table chosen by prefix */ PRE, /* Instr Prefix */ OPRE, /* Instr Prefix or media op extension */ SEG, /* Segment Prefix */ OPOVER, /* Operand size override */ ADDOVER, /* Address size override */ }; static Optable optab0F00[8]= { 0x00, 0,0, "MOVW LDT,%e", 0x01, 0,0, "MOVW TR,%e", 0x02, 0,0, "MOVW %e,LDT", 0x03, 0,0, "MOVW %e,TR", 0x04, 0,0, "VERR %e", 0x05, 0,0, "VERW %e", }; static Optable optab0F01[8]= { 0x00, 0,0, "MOVL GDTR,%e", 0x01, 0,0, "MOVL IDTR,%e", 0x02, 0,0, "MOVL %e,GDTR", 0x03, 0,0, "MOVL %e,IDTR", 0x04, 0,0, "MOVW MSW,%e", /* word */ 0x06, 0,0, "MOVW %e,MSW", /* word */ 0x07, 0,0, "INVLPG %e", /* or SWAPGS */ }; static Optable optab0F01F8[1]= { 0x00, 0,0, "SWAPGS", }; /* 0F71 */ /* 0F72 */ /* 0F73 */ static Optable optab0FAE[8]= { 0x00, 0,0, "FXSAVE %e", 0x01, 0,0, "FXRSTOR %e", 0x02, 0,0, "LDMXCSR %e", 0x03, 0,0, "STMXCSR %e", 0x05, 0,0, "LFENCE", 0x06, 0,0, "MFENCE", 0x07, 0,0, "SFENCE", }; /* 0F18 */ /* 0F0D */ static Optable optab0FBA[8]= { 0x04, Ib,0, "BT%S %i,%e", 0x05, Ib,0, "BTS%S %i,%e", 0x06, Ib,0, "BTR%S %i,%e", 0x07, Ib,0, "BTC%S %i,%e", }; static Optable optab0F0F[256]= { 0x0c, 0,0, "PI2FW %m,%M", 0x0d, 0,0, "PI2L %m,%M", 0x1c, 0,0, "PF2IW %m,%M", 0x1d, 0,0, "PF2IL %m,%M", 0x8a, 0,0, "PFNACC %m,%M", 0x8e, 0,0, "PFPNACC %m,%M", 0x90, 0,0, "PFCMPGE %m,%M", 0x94, 0,0, "PFMIN %m,%M", 0x96, 0,0, "PFRCP %m,%M", 0x97, 0,0, "PFRSQRT %m,%M", 0x9a, 0,0, "PFSUB %m,%M", 0x9e, 0,0, "PFADD %m,%M", 0xa0, 0,0, "PFCMPGT %m,%M", 0xa4, 0,0, "PFMAX %m,%M", 0xa6, 0,0, "PFRCPIT1 %m,%M", 0xa7, 0,0, "PFRSQIT1 %m,%M", 0xaa, 0,0, "PFSUBR %m,%M", 0xae, 0,0, "PFACC %m,%M", 0xb0, 0,0, "PFCMPEQ %m,%M", 0xb4, 0,0, "PFMUL %m,%M", 0xb6, 0,0, "PFRCPI2T %m,%M", 0xb7, 0,0, "PMULHRW %m,%M", 0xbb, 0,0, "PSWAPL %m,%M", }; static Optable optab0FC7[8]= { 0x01, 0,0, "CMPXCHG8B %e", }; static Optable optab660F71[8]= { 0x02, Ib,0, "PSRLW %i,%X", 0x04, Ib,0, "PSRAW %i,%X", 0x06, Ib,0, "PSLLW %i,%X", }; static Optable optab660F72[8]= { 0x02, Ib,0, "PSRLL %i,%X", 0x04, Ib,0, "PSRAL %i,%X", 0x06, Ib,0, "PSLLL %i,%X", }; static Optable optab660F73[8]= { 0x02, Ib,0, "PSRLQ %i,%X", 0x03, Ib,0, "PSRLO %i,%X", 0x06, Ib,0, "PSLLQ %i,%X", 0x07, Ib,0, "PSLLO %i,%X", }; static Optable optab660F[256]= { 0x2B, RM,0, "MOVNTPD %x,%e", 0x2E, RM,0, "UCOMISD %x,%X", 0x2F, RM,0, "COMISD %x,%X", 0x5A, RM,0, "CVTPD2PS %x,%X", 0x5B, RM,0, "CVTPS2PL %x,%X", 0x6A, RM,0, "PUNPCKHLQ %x,%X", 0x6B, RM,0, "PACKSSLW %x,%X", 0x6C, RM,0, "PUNPCKLQDQ %x,%X", 0x6D, RM,0, "PUNPCKHQDQ %x,%X", 0x6E, RM,0, "MOV%S %e,%X", 0x6F, RM,0, "MOVO %x,%X", /* MOVDQA */ 0x70, RM,Ib, "PSHUFL %i,%x,%X", 0x71, RMOP,0, optab660F71, 0x72, RMOP,0, optab660F72, 0x73, RMOP,0, optab660F73, 0x7E, RM,0, "MOV%S %X,%e", 0x7F, RM,0, "MOVO %X,%x", 0xC4, RM,Ib, "PINSRW %i,%e,%X", 0xC5, RMR,Ib, "PEXTRW %i,%X,%e", 0xD4, RM,0, "PADDQ %x,%X", 0xD5, RM,0, "PMULLW %x,%X", 0xD6, RM,0, "MOVQ %X,%x", 0xE6, RM,0, "CVTTPD2PL %x,%X", 0xE7, RM,0, "MOVNTO %X,%e", 0xF7, RM,0, "MASKMOVOU %x,%X", }; static Optable optabF20F[256]= { 0x10, RM,0, "MOVSD %x,%X", 0x11, RM,0, "MOVSD %X,%x", 0x2A, RM,0, "CVTS%S2SD %e,%X", 0x2C, RM,0, "CVTTSD2S%S %x,%r", 0x2D, RM,0, "CVTSD2S%S %x,%r", 0x5A, RM,0, "CVTSD2SS %x,%X", 0x6F, RM,0, "MOVOU %x,%X", 0x70, RM,Ib, "PSHUFLW %i,%x,%X", 0x7F, RM,0, "MOVOU %X,%x", 0xD6, RM,0, "MOVQOZX %M,%X", 0xE6, RM,0, "CVTPD2PL %x,%X", }; static Optable optabF30F[256]= { 0x10, RM,0, "MOVSS %x,%X", 0x11, RM,0, "MOVSS %X,%x", 0x2A, RM,0, "CVTS%S2SS %e,%X", 0x2C, RM,0, "CVTTSS2S%S %x,%r", 0x2D, RM,0, "CVTSS2S%S %x,%r", 0x5A, RM,0, "CVTSS2SD %x,%X", 0x5B, RM,0, "CVTTPS2PL %x,%X", 0x6F, RM,0, "MOVOU %x,%X", 0x70, RM,Ib, "PSHUFHW %i,%x,%X", 0x7E, RM,0, "MOVQOZX %x,%X", 0x7F, RM,0, "MOVOU %X,%x", 0xD6, RM,0, "MOVQOZX %m*,%X", 0xE6, RM,0, "CVTPL2PD %x,%X", }; static Optable optab0F[256]= { 0x00, RMOP,0, optab0F00, 0x01, RMOP,0, optab0F01, 0x02, RM,0, "LAR %e,%r", 0x03, RM,0, "LSL %e,%r", 0x05, 0,0, "SYSCALL", 0x06, 0,0, "CLTS", 0x07, 0,0, "SYSRET", 0x08, 0,0, "INVD", 0x09, 0,0, "WBINVD", 0x0B, 0,0, "UD2", 0x0F, RM,AUX, optab0F0F, /* 3DNow! */ 0x10, RM,0, "MOVU%s %x,%X", 0x11, RM,0, "MOVU%s %X,%x", 0x12, RM,0, "MOV[H]L%s %x,%X", /* TO DO: H if source is XMM */ 0x13, RM,0, "MOVL%s %X,%e", 0x14, RM,0, "UNPCKL%s %x,%X", 0x15, RM,0, "UNPCKH%s %x,%X", 0x16, RM,0, "MOV[L]H%s %x,%X", /* TO DO: L if source is XMM */ 0x17, RM,0, "MOVH%s %X,%x", 0x20, RMR,0, "MOVL %C,%e", 0x21, RMR,0, "MOVL %D,%e", 0x22, RMR,0, "MOVL %e,%C", 0x23, RMR,0, "MOVL %e,%D", 0x24, RMR,0, "MOVL %T,%e", 0x26, RMR,0, "MOVL %e,%T", 0x28, RM,0, "MOVA%s %x,%X", 0x29, RM,0, "MOVA%s %X,%x", 0x2A, RM,0, "CVTPL2%s %m*,%X", 0x2B, RM,0, "MOVNT%s %X,%e", 0x2C, RM,0, "CVTT%s2PL %x,%M", 0x2D, RM,0, "CVT%s2PL %x,%M", 0x2E, RM,0, "UCOMISS %x,%X",