#include <u.h>#include <libc.h>#include <bio.h>#include <mach.h> /* * i386-specific debugger interface */ static char *i386excep(Map*, Rgetter); static int i386trace(Map*, ulong, ulong, ulong, Tracer);static ulong i386frame(Map*, ulong, ulong, ulong, ulong);static int i386foll(Map*, ulong, Rgetter, ulong*);static int i386inst(Map*, ulong, char, char*, int);static int i386das(Map*, ulong, char*, int);static int i386instlen(Map*, ulong); static char STARTSYM[] = "_main";static char PROFSYM[] = "_mainp";static char FRAMENAME[] = ".frame";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",[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, /* dissembler */ i386instlen, /* instruction size calculation */}; static char*i386excep(Map *map, Rgetter rget){ ulong c; ulong 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"; } sprint(buf, "exception %ld", c); return buf; } else return excname[c];} static inti386trace(Map *map, ulong pc, ulong sp, ulong link, Tracer trace){ int i; ulong 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 (get4(map, sp, (long *) &pc) < 0) break; if(pc == 0) break; (*trace)(map, pc, sp, &s); sp += mach->szaddr; if(++i > 1000) break; } return i;} static ulongi386frame(Map *map, ulong addr, ulong pc, ulong sp, ulong 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 (get4(map, sp, (long *)&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 */ ulong 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 */ char osize; /* 'W' or 'L' */ char asize; /* address size 'W' or 'L' */ 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 */ short seg; /* segment of far address */ ulong disp; /* displacement */ ulong imm; /* immediate */ ulong imm2; /* second immediate operand */ 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,}; /* 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')%X - 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%x - 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)*/ 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 */ PRE, /* Instr Prefix */ 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 */}; 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 optab0F[256]={[0x00] RMOP,0, optab0F00,[0x01] RMOP,0, optab0F01,[0x02] RM,0, "LAR %e,%r",[0x03] RM,0, "LSL %e,%r",[0x06] 0,0, "CLTS",[0x08] 0,0, "INVD",[0x09] 0,0, "WBINVD",[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",[0x30] 0,0, "WRMSR",[0x31] 0,0, "RDTSC",[0x32] 0,0, "RDMSR",[0x42] RM,0, "CMOVC %e,%r", /* CF */[0x43] RM,0, "CMOVNC %e,%r", /* ¬ CF */[0x44] RM,0, "CMOVZ %e,%r", /* ZF */[0x45] RM,0, "CMOVNZ %e,%r", /* ¬ ZF */[0x46] RM,0, "CMOVBE %e,%r", /* CF ∨ ZF */[0x47] RM,0, "CMOVA %e,%r", /* ¬CF ∧ ¬ZF */[0x48] RM,0, "CMOVS %e,%r", /* SF */[0x49] RM,0, "CMOVNS %e,%r", /* ¬ SF */[0x4A] RM,0, "CMOVP %e,%r", /* PF */[0x4B] RM,0, "CMOVNP %e,%r", /* ¬ PF */[0x4C] RM,0, "CMOVLT %e,%r", /* LT ≡ OF ≠ SF */[0x4D] RM,0, "CMOVGE %e,%r", /* GE ≡ ZF ∨ SF */[0x4E] RM,0, "CMOVLE %e,%r", /* LE ≡ ZF ∨ LT */[0x4F] RM,0, "CMOVGT %e,%r", /* GT ≡ ¬ZF ∧ GE */[0x80] Iwds,0, "JOS %p",[0x81] Iwds,0, "JOC %p",[0x82] Iwds,0, "JCS %p",[0x83] Iwds,0, "JCC %p",[0x84] Iwds,0, "JEQ %p",[0x85] Iwds,0, "JNE %p",[0x86] Iwds,0, "JLS %p",[0x87] Iwds,0, "JHI %p",[0x88] Iwds,0, "JMI %p",[0x89] Iwds,0, "JPL %p",[0x8a] Iwds,0, "JPS %p",[0x8b] Iwds,0, "JPC %p",[0x8c] Iwds,0, "JLT %p",[0x8d] Iwds,0, "JGE %p",[0x8e] Iwds,0, "JLE %p",[0x8f] Iwds,0, "JGT %p",[0x90] RMB,0, "SETOS %e",[0x91] RMB,0, "SETOC %e",[0x92] RMB,0, "SETCS %e",[0x93] RMB,0, "SETCC %e",[0x94] RMB,0, "SETEQ %e",[0x95] RMB,0, "SETNE %e",[0x96] RMB,0, "SETLS %e",[0x97] RMB,0, "SETHI %e",[0x98] RMB,0, "SETMI %e",[0x99] RMB,0, "SETPL %e",[0x9a] RMB,0, "SETPS %e",[0x9b] RMB,0, "SETPC %e",[0x9c] RMB,0, "SETLT %e",[0x9d] RMB,0, "SETGE %e",[0x9e] RMB,0, "SETLE %e",[0x9f] RMB,0, "SETGT %e",[0xa0] 0,0, "PUSHL FS",[0xa1] 0,0, "POPL FS",[0xa2] 0,0, "CPUID",[0xa3] RM,0, "BT%S %r,%e",[0xa4] RM,Ib, "SHLD%S %r,%i,%e",[0xa5] RM,0, "SHLD%S %r,CL,%e",[0xa8] 0,0, "PUSHL GS",[0xa9] 0,0, "POPL GS",[0xab] RM,0, "BTS%S %r,%e",[0xac] RM,Ib, "SHRD%S %r,%i,%e",[0xad] RM,0, "SHRD%S %r,CL,%e",[0xaf] RM,0, "IMUL%S %e,%r",[0xb2] RMM,0, "LSS %e,%r",[0xb3] RM,0, "BTR%S %r,%e",[0xb4] RMM,0, "LFS %e,%r",[0xb5] RMM,0, "LGS %e,%r",[0xb6] RMB,0, "MOVBZX %e,%R",[0xb7] RM,0, "MOVWZX %e,%R",[0xba] RMOP,0, optab0FBA,[0xbb] RM,0, "BTC%S %e,%r",[0xbc] RM,0, "BSF%S %e,%r",[0xbd] RM,0, "BSR%S %e,%r",[0xbe] RMB,0, "MOVBSX %e,%R",[0xbf] RM,0, "MOVWSX %e,%R",}; static Optable optab80[8]={[0x00] Ib,0, "ADDB %i,%e",[0x01] Ib,0, "ORB %i,%e",[0x02] Ib,0, "ADCB %i,%e",[0x03] Ib,0, "SBBB %i,%e",[0x04] Ib,0, "ANDB %i,%e",[0x05] Ib,0, "SUBB %i,%e",[0x06] Ib,0, "XORB %i,%e",[0x07] Ib,0, "CMPB %e,%i",}; static Optable optab81[8]={[0x00] Iwd,0, "ADD%S %i,%e",[0x01] Iwd,0, "OR%S %i,%e",[0x02] Iwd,0, "ADC%S %i,%e",[0x03] Iwd,0, "SBB%S %i,%e",[0x04] Iwd,0, "AND%S %i,%e",[0x05] Iwd,0, "SUB%S %i,%e",[0x06] Iwd,0, "XOR%S %i,%e",[0x07] Iwd,0, "CMP%S %e,%i",}; static Optable optab83[8]={[0x00] Ibs,0, "ADD%S %i,%e",[0x01] Ibs,0, "OR%S %i,%e",[0x02] Ibs,0, "ADC%S %i,%e",[0x03] Ibs,0, "SBB%S %i,%e",[0x04] Ibs,0, "AND%S %i,%e",[0x05] Ibs,0, "SUB%S %i,%e",[0x06] Ibs,0, "XOR%S %i,%e",[0x07] Ibs,0, "CMP%S %e,%i",}; static Optable optabC0[8] ={[0x00] Ib,0, "ROLB %i,%e",[0x01] Ib,0, "RORB %i,%e",[0x02] Ib,0, "RCLB %i,%e",[0x03] Ib,0, "RCRB %i,%e",[0x04] Ib,0, "SHLB %i,%e",[0x05] Ib,0, "SHRB %i,%e",[0x07] Ib,0, "SARB %i,%e",}; static Optable optabC1[8] ={[0x00] Ib,0, "ROL%S %i,%e",[0x01] Ib,0, "ROR%S %i,%e",[0x02] Ib,0, "RCL%S %i,%e",[0x03] Ib,0, "RCR%S %i,%e",[0x04] Ib,0, "SHL%S %i,%e",[0x05] Ib,0, "SHR%S %i,%e",[0x07] Ib,0, "SAR%S %i,%e",}; static Optable optabD0[8] ={[0x00] 0,0, "ROLB %e",[0x01] 0,0, "RORB %e",[0x02] 0,0, "RCLB %e",[0x03] 0,0, "RCRB %e",[0x04] 0,0, "SHLB %e",[0x05] 0,0, "SHRB %e",[0x07] 0,0, "SARB %e",}; static Optable optabD1[8] ={[0x00] 0,0, "ROL%S %e",[0x01] 0,0, "ROR%S %e",[0x02] 0,0, "RCL%S %e",[0x03] 0,0, "RCR%S %e",[0x04] 0,0, "SHL%S %e",[0x05] 0,0, "SHR%S %e",[0x07] 0,0, "SAR%S %e",}; static Optable optabD2[8] ={[0x00] 0,0, "ROLB CL,%e",[0x01] 0,0, "RORB CL,%e",[0x02] 0,0, "RCLB CL,%e",[0x03] 0,0, "RCRB CL,%e",[0x04] 0,0, "SHLB CL,%e",[0x05] 0,0, "SHRB CL,%e",[0x07] 0,0, "SARB CL,%e",}; static Optable optabD3[8] ={[0x00] 0,0, "ROL%S CL,%e",[0x01] 0,0, "ROR%S CL,%e",[0x02] 0,0, "RCL%S CL,%e",[0x03] 0,0, "RCR%S CL,%e",[0x04] 0,0, "SHL%S CL,%e",[0x05] 0,0, "SHR%S CL,%e",[0x07] 0,0, "SAR%S CL,%e",}; static Optable optabD8[8+8] ={[0x00] 0,0, "FADDF %e,F0",[0x01] 0,0, "FMULF %e,F0",[0x02] 0,0, "FCOMF %e,F0",[0x03] 0,0, "FCOMFP %e,F0",[0x04] 0,0, "FSUBF %e,F0",[0x05] 0,0, "FSUBRF %e,F0",[0x06] 0,0, "FDIVF %e,F0",[0x07] 0,0, "FDIVRF %e,F0",[0x08] 0,0, "FADDD %f,F0",[0x09] 0,0, "FMULD %f,F0",[0x0a] 0,0, "FCOMD %f,F0",[0x0b] 0,0, "FCOMPD %f,F0",[0x0c] 0,0, "FSUBD %f,F0",[0x0d] 0,0, "FSUBRD %f,F0",[0x0e] 0,0, "FDIVD %f,F0",[0x0f] 0,0, "FDIVRD %f,F0",};/* * optabD9 and optabDB use the following encoding: * if (0 <= modrm <= 2) instruction = optabDx[modrm&0x07]; * else instruction = optabDx[(modrm&0x3f)+8]; * * the instructions for MOD == 3, follow the 8 instructions * for the other MOD values stored at the front of the table. */static Optable optabD9[64+8] =Lines 1–500 of 1645. Load more
#include <u.h> #include <libc.h> #include <bio.h> #include <mach.h> /* * i386-specific debugger interface */ static char *i386excep(Map*, Rgetter); static int i386trace(Map*, ulong, ulong, ulong, Tracer); static ulong i386frame(Map*, ulong, ulong, ulong, ulong); static int i386foll(Map*, ulong, Rgetter, ulong*); static int i386inst(Map*, ulong, char, char*, int); static int i386das(Map*, ulong, char*, int); static int i386instlen(Map*, ulong); static char STARTSYM[] = "_main"; static char PROFSYM[] = "_mainp"; static char FRAMENAME[] = ".frame"; 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", [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, /* dissembler */ i386instlen, /* instruction size calculation */ }; static char* i386excep(Map *map, Rgetter rget) { ulong c; ulong 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"; } sprint(buf, "exception %ld", c); return buf; } else return excname[c]; } static int i386trace(Map *map, ulong pc, ulong sp, ulong link, Tracer trace) { int i; ulong 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 (get4(map, sp, (long *) &pc) < 0) break; if(pc == 0) break; (*trace)(map, pc, sp, &s); sp += mach->szaddr; if(++i > 1000) break; } return i; } static ulong i386frame(Map *map, ulong addr, ulong pc, ulong sp, ulong 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 (get4(map, sp, (long *)&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 */ ulong 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 */ char osize; /* 'W' or 'L' */ char asize; /* address size 'W' or 'L' */ 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 */ short seg; /* segment of far address */ ulong disp; /* displacement */ ulong imm; /* immediate */ ulong imm2; /* second immediate operand */ 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, }; /* 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') %X - 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 %x - 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)*/ 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 */ PRE, /* Instr Prefix */ 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 */ }; 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 optab0F[256]= { [0x00] RMOP,0, optab0F00, [0x01] RMOP,0, optab0F01, [0x02] RM,0, "LAR %e,%r", [0x03] RM,0, "LSL %e,%r", [0x06] 0,0, "CLTS", [0x08] 0,0, "INVD", [0x09] 0,0, "WBINVD", [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", [0x30] 0,0, "WRMSR", [0x31] 0,0, "RDTSC", [0x32] 0,0, "RDMSR", [0x42] RM,0, "CMOVC %e,%r", /* CF */ [0x43] RM,0, "CMOVNC %e,%r", /* ¬ CF */ [0x44] RM,0, "CMOVZ %e,%r", /* ZF */ [0x45] RM,0, "CMOVNZ %e,%r", /* ¬ ZF */ [0x46] RM,0, "CMOVBE %e,%r", /* CF ∨ ZF */ [0x47] RM,0, "CMOVA %e,%r", /* ¬CF ∧ ¬ZF */ [0x48] RM,0, "CMOVS %e,%r", /* SF */ [0x49] RM,0, "CMOVNS %e,%r", /* ¬ SF */ [0x4A] RM,0, "CMOVP %e,%r", /* PF */ [0x4B] RM,0, "CMOVNP %e,%r", /* ¬ PF */ [0x4C] RM,0, "CMOVLT %e,%r", /* LT ≡ OF ≠ SF */ [0x4D] RM,0, "CMOVGE %e,%r", /* GE ≡ ZF ∨ SF */ [0x4E] RM,0, "CMOVLE %e,%r", /* LE ≡ ZF ∨ LT */ [0x4F] RM,0, "CMOVGT %e,%r", /* GT ≡ ¬ZF ∧ GE */ [0x80] Iwds,0, "JOS %p", [0x81] Iwds,0, "JOC %p", [0x82] Iwds,0, "JCS %p", [0x83] Iwds,0, "JCC %p", [0x84] Iwds,0, "JEQ %p", [0x85] Iwds,0, "JNE %p", [0x86] Iwds,0, "JLS %p", [0x87] Iwds,0, "JHI %p", [0x88] Iwds,0, "JMI %p", [0x89] Iwds,0, "JPL %p", [0x8a] Iwds,0, "JPS %p", [0x8b] Iwds,0, "JPC %p", [0x8c] Iwds,0, "JLT %p", [0x8d] Iwds,0, "JGE %p", [0x8e] Iwds,0, "JLE %p", [0x8f] Iwds,0, "JGT %p", [0x90] RMB,0, "SETOS %e", [0x91] RMB,0, "SETOC %e", [0x92] RMB,0, "SETCS %e", [0x93] RMB,0, "SETCC %e", [0x94] RMB,0, "SETEQ %e", [0x95] RMB,0, "SETNE %e", [0x96] RMB,0, "SETLS %e", [0x97] RMB,0, "SETHI %e", [0x98] RMB,0, "SETMI %e", [0x99] RMB,0, "SETPL %e", [0x9a] RMB,0, "SETPS %e", [0x9b] RMB,0, "SETPC %e", [0x9c] RMB,0, "SETLT %e", [0x9d] RMB,0, "SETGE %e", [0x9e] RMB,0, "SETLE %e", [0x9f] RMB,0, "SETGT %e", [0xa0] 0,0, "PUSHL FS", [0xa1] 0,0, "POPL FS", [0xa2] 0,0, "CPUID", [0xa3] RM,0, "BT%S %r,%e", [0xa4] RM,Ib, "SHLD%S %r,%i,%e", [0xa5] RM,0, "SHLD%S %r,CL,%e", [0xa8] 0,0, "PUSHL GS", [0xa9] 0,0, "POPL GS", [0xab] RM,0, "BTS%S %r,%e", [0xac] RM,Ib, "SHRD%S %r,%i,%e", [0xad] RM,0, "SHRD%S %r,CL,%e", [0xaf] RM,0, "IMUL%S %e,%r", [0xb2] RMM,0, "LSS %e,%r", [0xb3] RM,0, "BTR%S %r,%e", [0xb4] RMM,0, "LFS %e,%r", [0xb5] RMM,0, "LGS %e,%r", [0xb6] RMB,0, "MOVBZX %e,%R", [0xb7] RM,0, "MOVWZX %e,%R", [0xba] RMOP,0, optab0FBA, [0xbb] RM,0, "BTC%S %e,%r", [0xbc] RM,0, "BSF%S %e,%r", [0xbd] RM,0, "BSR%S %e,%r", [0xbe] RMB,0, "MOVBSX %e,%R", [0xbf] RM,0, "MOVWSX %e,%R", }; static Optable optab80[8]= { [0x00] Ib,0, "ADDB %i,%e", [0x01] Ib,0, "ORB %i,%e", [0x02] Ib,0, "ADCB %i,%e", [0x03] Ib,0, "SBBB %i,%e", [0x04] Ib,0, "ANDB %i,%e", [0x05] Ib,0, "SUBB %i,%e", [0x06] Ib,0, "XORB %i,%e", [0x07] Ib,0, "CMPB %e,%i", }; static Optable optab81[8]= { [0x00] Iwd,0, "ADD%S %i,%e", [0x01] Iwd,0, "OR%S %i,%e", [0x02] Iwd,0, "ADC%S %i,%e", [0x03] Iwd,0, "SBB%S %i,%e", [0x04] Iwd,0, "AND%S %i,%e", [0x05] Iwd,0, "SUB%S %i,%e", [0x06] Iwd,0, "XOR%S %i,%e", [0x07] Iwd,0, "CMP%S %e,%i", }; static Optable optab83[8]= { [0x00] Ibs,0, "ADD%S %i,%e", [0x01] Ibs,0, "OR%S %i,%e", [0x02] Ibs,0, "ADC%S %i,%e", [0x03] Ibs,0, "SBB%S %i,%e", [0x04] Ibs,0, "AND%S %i,%e", [0x05] Ibs,0, "SUB%S %i,%e", [0x06] Ibs,0, "XOR%S %i,%e", [0x07] Ibs,0, "CMP%S %e,%i", }; static Optable optabC0[8] = { [0x00] Ib,0, "ROLB %i,%e", [0x01] Ib,0, "RORB %i,%e", [0x02] Ib,0, "RCLB %i,%e", [0x03] Ib,0, "RCRB %i,%e", [0x04] Ib,0, "SHLB %i,%e", [0x05] Ib,0, "SHRB %i,%e", [0x07] Ib,0, "SARB %i,%e", }; static Optable optabC1[8] = { [0x00] Ib,0, "ROL%S %i,%e", [0x01] Ib,0, "ROR%S %i,%e", [0x02] Ib,0, "RCL%S %i,%e", [0x03] Ib,0, "RCR%S %i,%e", [0x04] Ib,0, "SHL%S %i,%e", [0x05] Ib,0, "SHR%S %i,%e", [0x07] Ib,0, "SAR%S %i,%e", }; static Optable optabD0[8] = { [0x00] 0,0, "ROLB %e", [0x01] 0,0, "RORB %e", [0x02] 0,0, "RCLB %e", [0x03] 0,0, "RCRB %e", [0x04] 0,0, "SHLB %e", [0x05] 0,0, "SHRB %e", [0x07] 0,0, "SARB %e", }; static Optable optabD1[8] = { [0x00] 0,0, "ROL%S %e", [0x01] 0,0, "ROR%S %e", [0x02] 0,0, "RCL%S %e", [0x03] 0,0, "RCR%S %e", [0x04] 0,0, "SHL%S %e", [0x05] 0,0, "SHR%S %e", [0x07] 0,0, "SAR%S %e", }; static Optable optabD2[8] = { [0x00] 0,0, "ROLB CL,%e", [0x01] 0,0, "RORB CL,%e", [0x02] 0,0, "RCLB CL,%e", [0x03] 0,0, "RCRB CL,%e", [0x04] 0,0, "SHLB CL,%e", [0x05] 0,0, "SHRB CL,%e", [0x07] 0,0, "SARB CL,%e", }; static Optable optabD3[8] = { [0x00] 0,0, "ROL%S CL,%e", [0x01] 0,0, "ROR%S CL,%e", [0x02] 0,0, "RCL%S CL,%e", [0x03] 0,0, "RCR%S CL,%e", [0x04] 0,0, "SHL%S CL,%e", [0x05] 0,0, "SHR%S CL,%e", [0x07] 0,0, "SAR%S CL,%e", }; static Optable optabD8[8+8] = { [0x00] 0,0, "FADDF %e,F0", [0x01] 0,0, "FMULF %e,F0", [0x02] 0,0, "FCOMF %e,F0", [0x03] 0,0, "FCOMFP %e,F0", [0x04] 0,0, "FSUBF %e,F0", [0x05] 0,0, "FSUBRF %e,F0", [0x06] 0,0, "FDIVF %e,F0", [0x07] 0,0, "FDIVRF %e,F0", [0x08] 0,0, "FADDD %f,F0", [0x09] 0,0, "FMULD %f,F0", [0x0a] 0,0, "FCOMD %f,F0", [0x0b] 0,0, "FCOMPD %f,F0", [0x0c] 0,0, "FSUBD %f,F0", [0x0d] 0,0, "FSUBRD %f,F0", [0x0e] 0,0, "FDIVD %f,F0", [0x0f] 0,0, "FDIVRD %f,F0", }; /* * optabD9 and optabDB use the following encoding: * if (0 <= modrm <= 2) instruction = optabDx[modrm&0x07]; * else instruction = optabDx[(modrm&0x3f)+8]; * * the instructions for MOD == 3, follow the 8 instructions * for the other MOD values stored at the front of the table. */ static Optable optabD9[64+8] =