#include <u.h>#include <libc.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 INTSYM[] = "forkret"; static char *excname[] ={[0] "divide error",[1] "debug exception",[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",[16] "math coprocessor error",[17] "alignment check",[18] "machine check",[19] "floating-point exception",[24] "clock",[25] "keyboard",[27] "modem status",[28] "serial line status",[30] "floppy disk",[36] "mouse",[37] "math coprocessor",[38] "hard disk",[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, /* disassembler */ i386instlen, /* instruction size calculation */}; static char*i386excep(Map *map, Rgetter rget){ ulong c; uvlong pc; static char buf[24]; 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; Symbol s, f; USED(link); i = 0; while(findsym(pc, CTEXT, &s)) { if(!map->kernel) 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; }else if(map->kernel && strcmp(s.name, INTSYM) == 0) sp += 15 * mach->szaddr; /* pop interrupt frame */ if (geta(map, sp, &pc) < 0) break; if(pc == 0) break; (*trace)(map, pc, sp, &s); sp += mach->szaddr; if(map->kernel && strcmp(s.name, INTSYM) == 0) sp += 2 * mach->szaddr; /* pop iret cs, eflags */ 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(!map->kernel) 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; }else if(map->kernel && strcmp(s.name, INTSYM) == 0) sp += 15 * mach->szaddr; /* pop interrupt frame */ if (s.value == addr) return sp; if (geta(map, sp, &pc) < 0) break; if(pc == 0) break; sp += mach->szaddr; if(map->kernel && strcmp(s.name, INTSYM) == 0) sp += 2 * mach->szaddr; /* pop iret cs, eflags */ } 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{ 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",[0x2F] RM,0, "COMISS %x,%X",[0x30] 0,0, "WRMSR",[0x31] 0,0, "RDTSC",[0x32] 0,0, "RDMSR",[0x33] 0,0, "RDPMC",Lines 1–500 of 2187. Load more
#include <u.h> #include <libc.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 INTSYM[] = "forkret"; static char *excname[] = { [0] "divide error", [1] "debug exception", [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", [16] "math coprocessor error", [17] "alignment check", [18] "machine check", [19] "floating-point exception", [24] "clock", [25] "keyboard", [27] "modem status", [28] "serial line status", [30] "floppy disk", [36] "mouse", [37] "math coprocessor", [38] "hard disk", [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, /* disassembler */ i386instlen, /* instruction size calculation */ }; static char* i386excep(Map *map, Rgetter rget) { ulong c; uvlong pc; static char buf[24]; 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; Symbol s, f; USED(link); i = 0; while(findsym(pc, CTEXT, &s)) { if(!map->kernel) 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; }else if(map->kernel && strcmp(s.name, INTSYM) == 0) sp += 15 * mach->szaddr; /* pop interrupt frame */ if (geta(map, sp, &pc) < 0) break; if(pc == 0) break; (*trace)(map, pc, sp, &s); sp += mach->szaddr; if(map->kernel && strcmp(s.name, INTSYM) == 0) sp += 2 * mach->szaddr; /* pop iret cs, eflags */ 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(!map->kernel) 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; }else if(map->kernel && strcmp(s.name, INTSYM) == 0) sp += 15 * mach->szaddr; /* pop interrupt frame */ if (s.value == addr) return sp; if (geta(map, sp, &pc) < 0) break; if(pc == 0) break; sp += mach->szaddr; if(map->kernel && strcmp(s.name, INTSYM) == 0) sp += 2 * mach->szaddr; /* pop iret cs, eflags */ } 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 { 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", [0x2F] RM,0, "COMISS %x,%X", [0x30] 0,0, "WRMSR", [0x31] 0,0, "RDTSC", [0x32] 0,0, "RDMSR", [0x33] 0,0, "RDPMC",