|
|
| version 1.5, 2004/01/15 15:50:33 | version 1.21, 2005/02/04 05:32:24 |
|---|---|
| Line 28 | Line 28 |
| */ | */ |
| #include "compiler.h" | #include "compiler.h" |
| #include "dosio.h" | |
| #include "cpu.h" | #include "cpu.h" |
| #include "ia32.mcr" | #include "ia32.mcr" |
| #include "inst_table.h" | #include "inst_table.h" |
| #if defined(IA32_PROFILE_INSTRUCTION) | |
| UINT32 inst_1byte_count[2][256]; | |
| UINT32 inst_2byte_count[2][256]; | |
| UINT32 ea16_count[24]; | |
| UINT32 ea32_count[24]; | |
| UINT32 sib0_count[256]; | |
| UINT32 sib1_count[256]; | |
| UINT32 sib2_count[256]; | |
| static const char *ea16_str[24] = { | |
| "BX + SI", "BX + SI + DISP8", "BX + SI + DISP16", | |
| "BX + DI", "BX + DI + DISP8", "BX + DI + DISP16", | |
| "BP + SI", "BP + SI + DISP8", "BP + SI + DISP16", | |
| "BP + DI", "BP + DI + DISP8", "BP + DI + DISP16", | |
| "SI", "SI + DISP8", "SI + DISP16", | |
| "DI", "DI + DISP8", "DI + DISP16", | |
| "DISP16", "BP + DISP8", "BP + DISP16", | |
| "BX", "BX + DISP8", "BX + DISP16", | |
| }; | |
| static const char *ea32_str[24] = { | |
| "EAX", "ECX", "EDX", "EBX", "SIB", "DISP32", "ESI", "EDI", | |
| "EAX + DISP8", "ECX + DISP8", "EDX + DISP8", "EBX + DISP8", | |
| "SIB + DISP8", "EBP + DISP8", "ESI + DISP8", "EDI + DISP8", | |
| "EAX + DISP32", "ECX + DISP32", "EDX + DISP32", "EBX + DISP32", | |
| "SIB + DISP32", "EBP + DISP32", "ESI + DISP32", "EDI + DISP32", | |
| }; | |
| static const char *sib0_base_str[8] = { | |
| "EAX", "ECX", "EDX", "EBX", "ESP", "DISP32", "ESI", "EDI", | |
| }; | |
| static const char *sib1_base_str[8] = { | |
| "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", | |
| }; | |
| static const char *sib_index_str[8] = { | |
| "EAX", "ECX", "EDX", "EBX", "", "EBP", "ESI", "EDI", | |
| }; | |
| static const char *sib_scale_str[4] = { | |
| "", "2", "4", "8", | |
| }; | |
| void | sigjmp_buf exec_1step_jmpbuf; |
| clear_profile_inst(void) | |
| { | |
| memset(inst_1byte_count, 0, sizeof(inst_1byte_count)); | #if defined(IA32_INSTRUCTION_TRACE) |
| memset(inst_2byte_count, 0, sizeof(inst_2byte_count)); | typedef struct { |
| memset(ea16_count, 0, sizeof(ea16_count)); | CPU_REGS regs; |
| memset(ea32_count, 0, sizeof(ea32_count)); | disasm_context_t disasm; |
| memset(sib0_count, 0, sizeof(sib0_count)); | |
| memset(sib1_count, 0, sizeof(sib1_count)); | |
| memset(sib2_count, 0, sizeof(sib2_count)); | |
| } | |
| void | BYTE op[MAX_PREFIX + 2]; |
| show_profile_inst(void) | int opbytes; |
| { | } ia32_context_t; |
| int i; | |
| printf("instruction (16bit)\n"); | #define NCTX 1024 |
| for (i = 0; i < 256; i++) { | |
| if (inst_1byte_count[0][i] != 0) { | |
| printf("0x%02x: %d\n", i, inst_1byte_count[0][i]); | |
| } | |
| } | |
| for (i = 0; i < 256; i++) { | |
| if (inst_2byte_count[0][i] != 0) { | |
| printf("0x0f%02x: %d\n", i, inst_2byte_count[0][i]); | |
| } | |
| } | |
| printf("instruction (32bit)\n"); | ia32_context_t ctx[NCTX]; |
| for (i = 0; i < 256; i++) { | int ctx_index = 0; |
| if (inst_1byte_count[1][i] != 0) { | |
| printf("0x%02x: %d\n", i, inst_1byte_count[1][i]); | |
| } | |
| } | |
| for (i = 0; i < 256; i++) { | |
| if (inst_2byte_count[1][i] != 0) { | |
| printf("0x0f%02x: %d\n", i, inst_2byte_count[1][i]); | |
| } | |
| } | |
| } | |
| void | int cpu_inst_trace = 0; |
| show_profile_ea(void) | |
| { | |
| char buf[80]; | |
| char tmp[80]; | |
| int i; | |
| int t; | |
| printf("EA16\n"); | |
| for (i = 0; i < NELEMENTS(ea16_count); i++) { | |
| if (ea16_count[i] != 0) { | |
| printf("%s: %d\n", ea16_str[i], ea16_count[i]); | |
| } | |
| } | |
| printf("EA32\n"); | |
| for (i = 0; i < NELEMENTS(ea32_count); i++) { | |
| if (ea32_count[i] != 0) { | |
| printf("%s: %d\n", ea32_str[i], ea32_count[i]); | |
| } | |
| } | |
| printf("SIB0\n"); | |
| for (i = 0; i < NELEMENTS(sib0_count); i++) { | |
| if (sib0_count[i] != 0) { | |
| sprintf(tmp, "%s", sib0_base_str[i & 7]); | |
| strcpy(buf, tmp); | |
| t = (i >> 3) & 7; | |
| if (t != 4) { | |
| sprintf(tmp, " + %s", sib_index_str[t]); | |
| strcat(buf, tmp); | |
| } | |
| t = (i >> 6) & 3; | |
| if (t != 0) { | |
| sprintf(tmp, " * %s", sib_scale_str[t]); | |
| strcat(buf, tmp); | |
| } | |
| printf("%s: %d\n", buf, sib0_count[i]); | |
| } | |
| } | |
| printf("SIB1\n"); | |
| for (i = 0; i < NELEMENTS(sib1_count); i++) { | |
| if (sib1_count[i] != 0) { | |
| sprintf(tmp, "%s", sib1_base_str[i & 7]); | |
| strcpy(buf, tmp); | |
| t = (i >> 3) & 7; | |
| if (t != 4) { | |
| sprintf(tmp, " + %s", sib_index_str[t]); | |
| strcat(buf, tmp); | |
| } | |
| t = (i >> 6) & 3; | |
| if (t != 0) { | |
| sprintf(tmp, " * %s", sib_scale_str[t]); | |
| strcat(buf, tmp); | |
| } | |
| printf("%s + DISP8: %d\n", buf, sib1_count[i]); | |
| } | |
| } | |
| printf("SIB2\n"); | |
| for (i = 0; i < NELEMENTS(sib2_count); i++) { | |
| if (sib2_count[i] != 0) { | |
| sprintf(tmp, "%s", sib1_base_str[i & 7]); | |
| strcpy(buf, tmp); | |
| t = (i >> 3) & 7; | |
| if (t != 4) { | |
| sprintf(tmp, " + %s", sib_index_str[t]); | |
| strcat(buf, tmp); | |
| } | |
| t = (i >> 6) & 3; | |
| if (t != 0) { | |
| sprintf(tmp, " * %s", sib_scale_str[t]); | |
| strcat(buf, tmp); | |
| } | |
| printf("%s + DISP32: %d\n", buf, sib2_count[i]); | |
| } | |
| } | |
| } | |
| #endif | #endif |
| #ifdef IA32_INSTRUCTION_TRACE | |
| static FILE *fp = NULL; | |
| BOOL cpu_inst_trace = FALSE; | |
| static const char *opcode_1byte[2][256] = { | // #define IPTRACE (1 << 14) |
| /* 16bit */ | |
| { | |
| /*00*/ "addb", "addw", "addb", "addw", "addb", "addw", "push", "pop", | |
| "orb", "orw", "orb", "orw", "orb", "orw", "push", NULL, | |
| /*10*/ "adcb", "adcw", "adcb", "adcw", "adcb", "adcw", "push", "pop", | |
| "sbbb", "sbbw", "sbbb", "sbbw", "sbbb", "sbbw", "push", "pop", | |
| /*20*/ "andb", "andw", "andb", "andw", "andb", "andw", "es:", "daa", | |
| "subb", "subw", "subb", "subw", "subb", "subw", "cs:", "das", | |
| /*30*/ "xorb", "xorw", "xorb", "xorw", "xorb", "xorw", "ss:", "aaa", | |
| "cmpb", "cmpw", "cmpb", "cmpw", "cmpb", "cmpw", "ds:", "aas", | |
| /*40*/ "incw", "incw", "incw", "incw", "incw", "incw", "incw", "incw", | |
| "decw", "decw", "decw", "decw", "decw", "decw", "decw", "decw", | |
| /*50*/ "push", "push", "push", "push", "push", "push", "push", "push", | |
| "pop", "pop", "pop", "pop", "pop", "pop", "pop", "pop", | |
| /*60*/ "pusha", "popa", "bound", "arpl", "fs:", "gs:", NULL, NULL, | |
| "push", "imul", "push", "imul", "insb", "insw", "outsb", "outsw", | |
| /*70*/ "jo", "jno", "jc", "jnc", "jz", "jnz", "jna", "ja", | |
| "js", "jns", "jp", "jnp", "jl", "jnl", "jle", "jnle", | |
| /*80*/ NULL, NULL, NULL, NULL, "testb", "testw", "xchgb", "xchgw", | |
| "movb", "movw", "movb", "movw", "movw", "lea", "movw", "pop", | |
| /*90*/ "nop", "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", | |
| "cbw", "cwd", "callf", "fwait", "pushf", "popf", "sahf", "lahf", | |
| /*a0*/ "movb", "movw", "movb", "movw", "movsb", "movsw", "cmpsb", "cmpsw", | |
| "testb", "testw", "stosb", "stosw", "lodsb", "lodsw", "scasb", "scasw", | |
| /*b0*/ "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", | |
| "movw", "movw", "movw", "movw", "movw", "movw", "movw", "movw", | |
| /*c0*/ NULL, NULL, "ret", "ret", "les", "lds", "movb", "movw", | |
| "enter", "leave", "retf", "retf", "int3", "int", "into", "iret", | |
| /*d0*/ NULL, NULL, NULL, NULL, "aam", "aad", "salc", "xlat", | |
| "esc0", "esc1", "esc2", "esc3", "esc4", "esc5", "esc6", "esc7", | |
| /*e0*/ "loopne","loope", "loop", "jcxz", "inb", "inw", "outb", "outw", | |
| "call", "jmp", "jmpf", "jmp", "inb", "inw", "outb", "outw", | |
| /*f0*/ "lock:", "int1", "repne", "repe", "hlt", "cmc", NULL, NULL, | |
| "clc", "stc", "cli", "sti", "cld", "std", NULL, NULL, | |
| }, | |
| /* 32bit */ | |
| { | |
| /*00*/ "addb", "addl", "addb", "addl", "addb", "addl", "pushl", "popl", | |
| "orb", "orl", "orb", "orl", "orb", "orl", "pushl", NULL, | |
| /*10*/ "adcb", "adcl", "adcb", "adcl", "adcb", "adcl", "pushl", "popl", | |
| "sbbb", "sbbl", "sbbb", "sbbl", "sbbb", "sbbl", "pushl", "popl", | |
| /*20*/ "andb", "andl", "andb", "andl", "andb", "andl", "es:", "daa", | |
| "subb", "subl", "subb", "subl", "subb", "subl", "cs:", "das", | |
| /*30*/ "xorb", "xorl", "xorb", "xorl", "xorb", "xorl", "ss:", "aaa", | |
| "cmpb", "cmpl", "cmpb", "cmpl", "cmpb", "cmpl", "ds:", "aas", | |
| /*40*/ "incl", "incl", "incl", "incl", "incl", "incl", "incl", "incl", | |
| "decl", "decl", "decl", "decl", "decl", "decl", "decl", "decl", | |
| /*50*/ "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", | |
| "popl", "popl", "popl", "popl", "popl", "popl", "popl", "pop", | |
| /*60*/ "pushal","popal", "bound", "arpl", "fs:", "gs:", NULL, NULL, | |
| "pushl", "imul", "pushl", "imul", "insb", "insl", "outsb", "outsl", | |
| /*70*/ "jo", "jno", "jc", "jnc", "jz", "jnz", "jna", "ja", | |
| "js", "jns", "jp", "jnp", "jl", "jnl", "jle", "jnle", | |
| /*80*/ NULL, NULL, NULL, NULL, "testb", "testl", "xchgb", "xchgl", | |
| "movb", "movl", "movb", "movl", "movl", "lea", "movl", "popl", | |
| /*90*/ "nop", "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", | |
| "cwde", "cdq", "callfl","fwait", "pushfd","popfd", "sahf", "lahf", | |
| /*a0*/ "movb", "movl", "movb", "movl", "movsb", "movsd", "cmpsb", "cmpsd", | |
| "testb", "testl", "stosb", "stosd", "lodsb", "lodsd", "scasb", "scasd", | |
| /*b0*/ "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", | |
| "movl", "movl", "movl", "movl", "movl", "movl", "movl", "movl", | |
| /*c0*/ NULL, NULL, "ret", "ret", "les", "lds", "movb", "movl", | |
| "enter", "leave", "retfd", "retfd", "int3", "int", "into", "iret", | |
| /*d0*/ NULL, NULL, NULL, NULL, "aam", "aad", "salc", "xlat", | |
| "esc0", "esc1", "esc2", "esc3", "esc4", "esc5", "esc6", "esc7", | |
| /*e0*/ "loopne","loope", "loop", "jecxz", "inb", "inl", "outb", "outl", | |
| "call", "jmp", "jmpf", "jmp", "inb", "inl", "outb", "outl", | |
| /*f0*/ "lock:", "int1", "repne", "repe", "hlt", "cmc", NULL, NULL, | |
| "clc", "stc", "cli", "sti", "cld", "std", NULL, NULL, | |
| } | |
| }; | |
| static const char *opcode_2byte[2][256] = { | #if defined(TRACE) && IPTRACE |
| /* 16bit */ | static UINT trpos = 0; |
| { | static UINT32 trcs[IPTRACE]; |
| /*00*/ NULL, NULL, "lar", "lsl", | static UINT32 treip[IPTRACE]; |
| NULL, "loadall", "clts", NULL, | |
| "invd", "wbinvd", NULL, "UD2", | void iptrace_out(void) { |
| NULL, NULL, NULL, NULL, | |
| /*10*/ NULL, NULL, NULL, NULL, | FILEH fh; |
| NULL, NULL, NULL, NULL, | UINT s; |
| NULL, NULL, NULL, NULL, | UINT32 cs; |
| NULL, NULL, NULL, NULL, | UINT32 eip; |
| /*20*/ "movl", "movl", "movl", "movl", | char buf[32]; |
| "movl", NULL, "movl", NULL, | |
| NULL, NULL, NULL, NULL, | s = trpos; |
| NULL, NULL, NULL, NULL, | if (s > IPTRACE) { |
| /*30*/ "wrmsr", "rdtsc", "rdmsr", NULL, | s -= IPTRACE; |
| NULL, NULL, NULL, NULL, | } |
| NULL, NULL, NULL, NULL, | else { |
| NULL, NULL, NULL, NULL, | s = 0; |
| /*40*/ "cmovo", "cmovno", "cmovc", "cmovnc", | } |
| "cmovz", "cmovnz", "cmovna", "cmova", | fh = file_create_c("his.txt"); |
| "cmovs", "cmovns", "cmovp", "cmovnp", | while(s < trpos) { |
| "cmovl", "cmovnl", "cmovle", "cmovnle", | cs = trcs[s & (IPTRACE - 1)]; |
| /*50*/ NULL, NULL, NULL, NULL, | eip = treip[s & (IPTRACE - 1)]; |
| NULL, NULL, NULL, NULL, | s++; |
| NULL, NULL, NULL, NULL, | SPRINTF(buf, "%.4x:%.8x\r\n", cs, eip); |
| NULL, NULL, NULL, NULL, | file_write(fh, buf, strlen(buf)); |
| /*60*/ NULL, NULL, NULL, NULL, | } |
| NULL, NULL, NULL, NULL, | file_close(fh); |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| /*70*/ NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| /*80*/ "jo", "jno", "jc", "jnc", | |
| "jz", "jnz", "jna", "ja", | |
| "js", "jns", "jp", "jnp", | |
| "jl", "jnl", "jle", "jnle", | |
| /*90*/ "seto", "setno", "setc", "setnc", | |
| "setz", "setnz", "setna", "seta", | |
| "sets", "setns", "setp", "setnp", | |
| "setl", "setnl", "setle", "setnle", | |
| /*a0*/ "push", "pop", "cpuid", "bt", | |
| "shldb", "shldw", "cmpxchgb","cmpxchgw", | |
| "push", "pop", "rsm", "bts", | |
| "shrdb", "shrdw", NULL, "imul", | |
| /*b0*/ "cmpxchgb","cmpxchgw","lss", "btr", | |
| "lfs", "lgs", "movzb", "movzw", | |
| NULL, "UD2", NULL, "btc", | |
| "bsf", "bsr", "movsb", "movsw", | |
| /*c0*/ "xaddb", "xaddw", NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| "bswap", "bswap", "bswap", "bswap", | |
| "bswap", "bswap", "bswap", "bswap", | |
| /*d0*/ NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| /*e0*/ NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| /*f0*/ NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| }, | |
| /* 32bit */ | |
| { | |
| /*00*/ NULL, NULL, "lar", "lsl", | |
| NULL, "loadall", "clts", NULL, | |
| "invd", "wbinvd", NULL, "UD2", | |
| NULL, NULL, NULL, NULL, | |
| /*10*/ NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| /*20*/ "movl", "movl", "movl", "movl", | |
| "movl", NULL, "movl", NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| /*30*/ "wrmsr", "rdtsc", "rdmsr", NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| /*40*/ "cmovo", "cmovno", "cmovc", "cmovnc", | |
| "cmovz", "cmovnz", "cmovna", "cmova", | |
| "cmovs", "cmovns", "cmovp", "cmovnp", | |
| "cmovl", "cmovnl", "cmovle", "cmovnle", | |
| /*50*/ NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| /*60*/ NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| /*70*/ NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| /*80*/ "jo", "jno", "jc", "jnc", | |
| "jz", "jnz", "jna", "ja", | |
| "js", "jns", "jp", "jnp", | |
| "jl", "jnl", "jle", "jnle", | |
| /*90*/ "seto", "setno", "setc", "setnc", | |
| "setz", "setnz", "setna", "seta", | |
| "sets", "setns", "setp", "setnp", | |
| "setl", "setnl", "setle", "setnle", | |
| /*a0*/ "push", "pop", "cpuid", "bt", | |
| "shldb", "shldl", "cmpxchgb","cmpxchgl", | |
| "push", "pop", "rsm", "bts", | |
| "shrdb", "shrdl", NULL, "imul", | |
| /*b0*/ "cmpxchgb","cmpxchgd","lss", "btr", | |
| "lfs", "lgs", "movzbl", "movzwl", | |
| NULL, "UD2", NULL, "btc", | |
| "bsf", "bsr", "movsbl", "movswl", | |
| /*c0*/ "xaddb", "xaddl", NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| "bswapl", "bswapl", "bswapl", "bswapl", | |
| "bswapl", "bswapl", "bswapl", "bswapl", | |
| /*d0*/ NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| /*e0*/ NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| /*f0*/ NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| NULL, NULL, NULL, NULL, | |
| } | } |
| }; | #endif |
| static const char *opcode_0x8x[2][2][8] = { | |
| /* 16bit */ | |
| { | |
| { "addb", "orb", "adcb", "sbbb", "andb", "subb", "xorb", "cmpb" }, | |
| { "addw", "orw", "adcw", "sbbw", "andw", "subw", "xorw", "cmpw" } | |
| }, | |
| /* 32bit */ | |
| { | |
| { "addb", "orb", "adcb", "sbbb", "andb", "subb", "xorb", "cmpb" }, | |
| { "addl", "orl", "adcl", "sbbl", "andl", "subl", "xorl", "cmpl" } | |
| } | |
| }; | |
| static const char *opcode_shift[2][2][8] = { | void |
| /* 16bit */ | exec_1step(void) |
| { | |
| { "rolb", "rorb", "rclb", "rcrb", "shlb", "shrb", "shlb", "sarb" }, | |
| { "rolw", "rorw", "rclw", "rcrw", "shlw", "shrw", "shlw", "sarw" } | |
| }, | |
| /* 32bit */ | |
| { | { |
| { "rolb", "rorb", "rclb", "rcrb", "shlb", "shrb", "shlb", "sarb" }, | int prefix; |
| { "roll", "rorl", "rcll", "rcrl", "shll", "shrl", "shll", "sarl" } | UINT32 op; |
| }, | |
| }; | |
| static const char *opcode_0xf6[2][2][8] = { | CPU_PREV_EIP = CPU_EIP; |
| /* 16bit */ | CPU_STATSAVE.cpu_inst = CPU_STATSAVE.cpu_inst_default; |
| { | |
| { "testb", "testb", "notb", "negb", "mul", "imul", "div", "idiv" }, | |
| { "testw", "testw", "notw", "negw", "mulw", "imulw", "divw", "idivw" } | |
| }, | |
| /* 32bit */ | |
| { | |
| { "testb", "testb", "notb", "negb", "mul", "imul", "div", "idiv" }, | |
| { "testl", "testl", "notl", "negl", "mull", "imull", "divl", "idivl" } | |
| }, | |
| }; | |
| static const char *opcode_0xfe[2][2][8] = { | #if defined(TRACE) && IPTRACE |
| /* 16bit */ | if (CPU_CS == 0x000c) { |
| { | trcs[trpos & (IPTRACE - 1)] = CPU_CS; |
| { "incb", "decb", NULL, NULL, NULL, NULL, NULL, NULL }, | treip[trpos & (IPTRACE - 1)] = CPU_EIP; |
| { "incw", "decw", "call", "callf", "jmp", "jmpf", "push", NULL } | trpos++; |
| }, | |
| /* 32bit */ | |
| { | |
| { "incb", "decb", NULL, NULL, NULL, NULL, NULL, NULL }, | |
| { "incl", "decl", "call", "callf", "jmp", "jmpf", "pushl", NULL } | |
| } | } |
| }; | #endif |
| static const char *opcode2_g6[8] = { | |
| "sldt", "str", "lldt", "ltr", "verr", "verw", NULL, NULL | |
| }; | |
| static const char *opcode2_g7[8] = { | |
| "sgdt", "sidt", "lgdt", "lidt", "smsw", NULL, "lmsw", "invlpg" | |
| }; | |
| static const char *opcode2_g8[8] = { | |
| NULL, NULL, NULL, NULL, "bt", "bts", "btr", "btc" | |
| }; | |
| static const char *opcode2_g9[8] = { | |
| NULL, "cmpxchg8b", NULL, NULL, NULL, NULL, NULL, NULL | |
| }; | |
| static const char *reg8[8] = { | |
| "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" | |
| }; | |
| static const char *reg16[8] = { | |
| "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" | |
| }; | |
| static const char *reg32[8] = { | |
| "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" | |
| }; | |
| static DWORD | |
| ea(DWORD eip, DWORD op) | |
| { | |
| static const char *ea16[8] = { | |
| "bx + si", "bx + di", "bp + si", "bp + di", | |
| "si", "di", "bp", "bx" | |
| }; | |
| char buf[256]; | |
| DWORD mod = (op >> 6) & 3; | |
| DWORD rm = op & 7; | |
| DWORD val; | |
| __ASSERT(mod != 3); | |
| buf[0] = '\0'; | |
| if (!CPU_INST_AS32) { | |
| if (mod == 0) { | |
| if (rm == 6) { | |
| /* disp16 */ | |
| val = cpu_codefetch_w(eip); | |
| eip += 2; | |
| SPRINTF(buf, "0x%04x", val); | |
| } else { | |
| SPRINTF(buf, "%s", ea16[rm]); | |
| } | |
| } else { | |
| if (mod == 1) { | |
| /* disp8 */ | |
| val = cpu_codefetch(eip); | |
| if (val & 0x80) { | |
| val |= 0xff00; | |
| } | |
| eip++; | |
| } else { | |
| /* disp16 */ | |
| val = cpu_codefetch_w(eip); | |
| eip += 2; | |
| } | |
| SPRINTF(buf, "%s + 0x%04x", ea16[rm], val); | |
| } | |
| } else { | |
| char tmp[32]; | |
| BYTE count[9]; | |
| int n; | |
| int i; | |
| ZeroMemory(count, sizeof(count)); | |
| if (rm == 5) { | |
| DWORD sib; | |
| DWORD scale; | |
| DWORD idx; | |
| DWORD base; | |
| sib = cpu_codefetch(eip); | |
| eip++; | |
| scale = (sib >> 6) & 3; | |
| idx = (sib >> 3) & 7; | |
| base = sib & 7; | |
| if (base == 5 && mod == 0) { | |
| val = cpu_codefetch_d(eip); | |
| eip += 4; | |
| count[8] += val; | |
| } else { | |
| count[base]++; | |
| } | |
| if (idx != 4) { | |
| count[idx] += 1 << scale; | |
| } | |
| } | |
| if (rm == 6 && mod == 0) { | #if defined(IA32_INSTRUCTION_TRACE) |
| /* disp32 */ | ctx[ctx_index].regs = CPU_STATSAVE.cpu_regs; |
| val = cpu_codefetch_d(eip); | if (cpu_inst_trace) { |
| eip += 4; | disasm_context_t *d = &ctx[ctx_index].disasm; |
| count[8] += val; | UINT32 eip = CPU_EIP; |
| } else { | int rv; |
| if (mod == 1) { | |
| /* disp8 */ | rv = disasm(&eip, d); |
| val = cpu_codefetch(eip); | if (rv == 0) { |
| eip++; | char buf[256]; |
| if (val & 0x80) { | char tmp[32]; |
| val |= 0xffffff00; | int len = d->nopbytes > 8 ? 8 : d->nopbytes; |
| } | int i; |
| count[8] += val; | |
| } else if (mod == 2) { | buf[0] = '\0'; |
| /* disp32 */ | for (i = 0; i < len; i++) { |
| val = cpu_codefetch_d(eip); | snprintf(tmp, sizeof(tmp), "%02x ", d->opcode[i]); |
| eip += 4; | milstr_ncat(buf, tmp, sizeof(buf)); |
| count[8] += val; | |
| } | } |
| if (rm != 5) { | for (; i < 8; i++) { |
| count[rm]++; | milstr_ncat(buf, " ", sizeof(buf)); |
| } | } |
| } | VERBOSE(("%04x:%08x: %s%s", CPU_CS, CPU_EIP, buf, d->str)); |
| n = 0; | buf[0] = '\0'; |
| for (i = 0; i < 8; i++) { | for (; i < d->nopbytes; i++) { |
| if (count[i] != 0) { | snprintf(tmp, sizeof(tmp), "%02x ", d->opcode[i]); |
| if (n > 0) { | |
| milstr_ncat(buf, " + ", sizeof(buf)); | |
| } | |
| if (count[i] > 1) { | |
| SPRINTF(tmp, "%s * %d", | |
| reg32[i], count[i]); | |
| } else { | |
| milstr_ncpy(tmp, reg32[i], sizeof(tmp)); | |
| } | |
| milstr_ncat(buf, tmp, sizeof(buf)); | milstr_ncat(buf, tmp, sizeof(buf)); |
| n++; | if ((i % 8) == 7) { |
| VERBOSE((" : %s", buf)); | |
| buf[0] = '\0'; | |
| } | |
| } | } |
| } | if ((i % 8) != 0) { |
| if (count[8] != 0) { | VERBOSE((" : %s", buf)); |
| if (n > 0) { | |
| milstr_ncat(buf, " + ", sizeof(buf)); | |
| } | } |
| SPRINTF(tmp, "0x%08x", count[8]); | |
| milstr_ncat(buf, tmp, sizeof(buf)); | |
| } | } |
| } | } |
| fprintf(fp, "[%s]", buf); | ctx[ctx_index].opbytes = 0; |
| return eip; | |
| } | |
| void | |
| close_instruction_trace(void) | |
| { | |
| if (fp) { | |
| fclose(fp); | |
| fp = NULL; | |
| } | |
| } | |
| #endif | #endif |
| #define MAX_PREFIX 8 | #if defined(IA32_SUPPORT_DEBUG_REGISTER) |
| if (CPU_STAT_BP && !(CPU_EFLAG & RF_FLAG)) { | |
| jmp_buf exec_1step_jmpbuf; | int i; |
| for (i = 0; i < CPU_DEBUG_REG_INDEX_NUM; i++) { | |
| void | if ((CPU_STAT_BP & (1 << i)) |
| exec_1step(void) | && (CPU_DR7_GET_RW(i) == CPU_DR7_RW_CODE) |
| { | && (CPU_DR(i) == CPU_EIP) |
| int prefix; | && (CPU_DR7_GET_LEN(i) == 0)) { |
| BYTE op; | CPU_DR6 |= CPU_DR6_B(i); |
| EXCEPTION(DB_EXCEPTION, 0); | |
| CPU_PREV_EIP = CPU_EIP; | } |
| } | |
| CPU_STATSAVE.cpu_inst = CPU_STATSAVE.cpu_inst_default; | |
| #ifdef IA32_INSTRUCTION_TRACE | |
| { | |
| BYTE opcode[MAX_PREFIX + 1]; | |
| DWORD eip = CPU_EIP; | |
| int num = 0; | |
| int i; | |
| BOOL t = cpu_inst_trace; | |
| if ((CPU_CS == 0x0018) && (eip >= 0x0000b42c) && (eip <= 0x0000b435)) { | |
| t = FALSE; | |
| } | |
| if ((fp == NULL) && t) { | |
| fp = fopen("ia32trace.txt", "a"); | |
| } | |
| if (fp && t) { | |
| fprintf(fp, "%04x:%08x:", CPU_CS, eip); | |
| } | } |
| #endif | #endif /* IA32_SUPPORT_DEBUG_REGISTER */ |
| for (prefix = 0; prefix < MAX_PREFIX; prefix++) { | for (prefix = 0; prefix < MAX_PREFIX; prefix++) { |
| GET_PCBYTE(op); | GET_PCBYTE(op); |
| #if defined(IA32_INSTRUCTION_TRACE) | |
| #ifdef IA32_INSTRUCTION_TRACE | ctx[ctx_index].op[prefix] = op; |
| eip++; | ctx[ctx_index].opbytes++; |
| if (fp && t) { | |
| opcode[num++] = op; | |
| fprintf(fp, " %02x", op); | |
| } | |
| #endif | #endif |
| /* prefix */ | /* prefix */ |
| if (insttable_info[op] & INST_PREFIX) { | if (insttable_info[op] & INST_PREFIX) { |
| PROFILE_INC_INST_1BYTE(op); | |
| (*insttable_1byte[0][op])(); | (*insttable_1byte[0][op])(); |
| continue; | continue; |
| } | } |
| Line 687 exec_1step(void) | Line 180 exec_1step(void) |
| if (prefix == MAX_PREFIX) { | if (prefix == MAX_PREFIX) { |
| EXCEPTION(UD_EXCEPTION, 0); | EXCEPTION(UD_EXCEPTION, 0); |
| } | } |
| PROFILE_INC_INST_1BYTE(op); | |
| #ifdef IA32_INSTRUCTION_TRACE | |
| if (fp && t) { | |
| BYTE op2 = 0; | |
| if ((op == 0x0f) | |
| || (op >= 0x80 && op <= 0x83) | |
| || (op >= 0xc0 && op <= 0xc1) | |
| || (op >= 0xd0 && op <= 0xd3) | |
| || (op >= 0xf6 && op <= 0xf7) | |
| || (op >= 0xfe /* && op <= 0xff */) | |
| ) { | |
| op2 = cpu_codefetch(eip); | |
| eip++; | |
| fprintf(fp, " %02x", op2); | |
| } | |
| fprintf(fp, "\t\t"); | #if defined(IA32_INSTRUCTION_TRACE) |
| for (i = 0; i < num; i++) { | if (op == 0x0f) { |
| BYTE c = opcode[i]; | BYTE op2; |
| const char *p = opcode_1byte[CPU_INST_OP32][c]; | op2 = cpu_codefetch(CPU_EIP); |
| if (p) { | ctx[ctx_index].op[prefix + 1] = op2; |
| fprintf(fp, "%s ", p); | ctx[ctx_index].opbytes++; |
| } else { | |
| BYTE t = (op2 >> 3) & 7; | |
| switch (c) { | |
| case 0x80: case 0x81: case 0x82: case 0x83: | |
| p = opcode_0x8x[CPU_INST_OP32][c&1][t]; | |
| break; | |
| case 0xc0: case 0xc1: | |
| case 0xd0: case 0xd1: case 0xd2: case 0xd3: | |
| p = opcode_shift[CPU_INST_OP32][c&1][t]; | |
| break; | |
| case 0xf6: | |
| case 0xf7: | |
| p = opcode_0xf6[CPU_INST_OP32][c&1][t]; | |
| break; | |
| case 0xfe: | |
| case 0xff: | |
| p = opcode_0xfe[CPU_INST_OP32][c&1][t]; | |
| break; | |
| } | |
| if (p) { | |
| fprintf(fp, "%s ", p); | |
| } | |
| } | |
| } | |
| if (op == 0x0f) { | |
| const char *p = opcode_2byte[CPU_INST_OP32][op2]; | |
| if (p) { | |
| fprintf(fp, "%s ", p); | |
| } else { | |
| BYTE t; | |
| t = cpu_codefetch(eip); | |
| eip++; | |
| t = (t >> 3) & 7; | |
| switch (op2) { | |
| case 0x00: | |
| p = opcode2_g6[t]; | |
| break; | |
| case 0x01: | |
| p = opcode2_g7[t]; | |
| break; | |
| case 0xba: | |
| p = opcode2_g8[t]; | |
| break; | |
| case 0xc7: | |
| p = opcode2_g9[t]; | |
| break; | |
| } | |
| if (p) { | |
| fprintf(fp, "%s ", p); | |
| } | |
| } | |
| } | |
| fprintf(fp, "\n"); | |
| } | |
| #if 0 | |
| if (fp) { | |
| fclose(fp); | |
| fp = NULL; | |
| } | } |
| #endif | ctx_index = (ctx_index + 1) % NELEMENTS(ctx); |
| } | |
| #endif | #endif |
| /* normal / rep, but not use */ | /* normal / rep, but not use */ |
| if (!(insttable_info[op] & INST_STRING) || !CPU_INST_REPUSE) { | if (!(insttable_info[op] & INST_STRING) || !CPU_INST_REPUSE) { |
| (*insttable_1byte[CPU_INST_OP32][op])(); | (*insttable_1byte[CPU_INST_OP32][op])(); |
| #if defined(IA32_SUPPORT_DEBUG_REGISTER) | |
| goto check_break_point; | |
| #else | |
| return; | return; |
| #endif | |
| } | } |
| /* rep */ | /* rep */ |
| Line 794 exec_1step(void) | Line 207 exec_1step(void) |
| if (CPU_CX != 0) { | if (CPU_CX != 0) { |
| if (!(insttable_info[op] & REP_CHECKZF)) { | if (!(insttable_info[op] & REP_CHECKZF)) { |
| /* rep */ | /* rep */ |
| do { | for (;;) { |
| (*insttable_1byte[CPU_INST_OP32][op])(); | (*insttable_1byte[CPU_INST_OP32][op])(); |
| } while (--CPU_CX); | if (--CPU_CX == 0) |
| break; | |
| if (CPU_REMCLOCK <= 0) { | |
| CPU_EIP = CPU_PREV_EIP; | |
| break; | |
| } | |
| } | |
| } else if (CPU_INST_REPUSE != 0xf2) { | } else if (CPU_INST_REPUSE != 0xf2) { |
| /* repe */ | /* repe */ |
| do { | for (;;) { |
| (*insttable_1byte[CPU_INST_OP32][op])(); | (*insttable_1byte[CPU_INST_OP32][op])(); |
| } while (--CPU_CX && (CPU_FLAGL & Z_FLAG)); | if (--CPU_CX == 0 || CC_NZ) |
| break; | |
| if (CPU_REMCLOCK <= 0) { | |
| CPU_EIP = CPU_PREV_EIP; | |
| break; | |
| } | |
| } | |
| } else { | } else { |
| /* repne */ | /* repne */ |
| do { | for (;;) { |
| (*insttable_1byte[CPU_INST_OP32][op])(); | (*insttable_1byte[CPU_INST_OP32][op])(); |
| } while (--CPU_CX && !(CPU_FLAGL & Z_FLAG)); | if (--CPU_CX == 0 || CC_Z) |
| break; | |
| if (CPU_REMCLOCK <= 0) { | |
| CPU_EIP = CPU_PREV_EIP; | |
| break; | |
| } | |
| } | |
| } | } |
| } | } |
| } else { | } else { |
| if (CPU_ECX != 0) { | if (CPU_ECX != 0) { |
| if (!(insttable_info[op] & REP_CHECKZF)) { | if (!(insttable_info[op] & REP_CHECKZF)) { |
| /* rep */ | /* rep */ |
| do { | for (;;) { |
| (*insttable_1byte[CPU_INST_OP32][op])(); | (*insttable_1byte[CPU_INST_OP32][op])(); |
| } while (--CPU_ECX); | if (--CPU_ECX == 0) |
| break; | |
| if (CPU_REMCLOCK <= 0) { | |
| CPU_EIP = CPU_PREV_EIP; | |
| break; | |
| } | |
| } | |
| } else if (CPU_INST_REPUSE != 0xf2) { | } else if (CPU_INST_REPUSE != 0xf2) { |
| /* repe */ | /* repe */ |
| do { | for (;;) { |
| (*insttable_1byte[CPU_INST_OP32][op])(); | (*insttable_1byte[CPU_INST_OP32][op])(); |
| } while (--CPU_ECX && (CPU_FLAGL & Z_FLAG)); | if (--CPU_ECX == 0 || CC_NZ) |
| break; | |
| if (CPU_REMCLOCK <= 0) { | |
| CPU_EIP = CPU_PREV_EIP; | |
| break; | |
| } | |
| } | |
| } else { | } else { |
| /* repne */ | /* repne */ |
| do { | for (;;) { |
| (*insttable_1byte[CPU_INST_OP32][op])(); | (*insttable_1byte[CPU_INST_OP32][op])(); |
| } while (--CPU_ECX && !(CPU_FLAGL & Z_FLAG)); | if (--CPU_ECX == 0 || CC_Z) |
| break; | |
| if (CPU_REMCLOCK <= 0) { | |
| CPU_EIP = CPU_PREV_EIP; | |
| break; | |
| } | |
| } | |
| } | } |
| } | } |
| } | } |
| #if defined(IA32_SUPPORT_DEBUG_REGISTER) | |
| check_break_point: | |
| if (CPU_TRAP || (CPU_STAT_BP_EVENT & ~CPU_STAT_BP_EVENT_RF)) { | |
| UINT8 orig = CPU_STAT_BP_EVENT & ~CPU_STAT_BP_EVENT_RF; | |
| CPU_STAT_BP_EVENT &= CPU_STAT_BP_EVENT_RF; | |
| CPU_DR6 |= (orig & 0xf); | |
| if (orig & CPU_STAT_BP_EVENT_TASK) { | |
| CPU_DR6 |= CPU_DR6_BT; | |
| } | |
| if (CPU_TRAP) { | |
| CPU_DR6 |= CPU_DR6_BS; | |
| } | |
| INTERRUPT(DB_EXCEPTION, TRUE, FALSE, 0); | |
| } | |
| if (CPU_EFLAG & RF_FLAG) { | |
| if (CPU_STAT_BP_EVENT & CPU_STAT_BP_EVENT_RF) { | |
| /* after IRETD or task switch */ | |
| CPU_STAT_BP_EVENT &= ~CPU_STAT_BP_EVENT_RF; | |
| } else { | |
| CPU_EFLAG &= ~RF_FLAG; | |
| } | |
| } | |
| #endif /* IA32_SUPPORT_DEBUG_REGISTER */ | |
| } | } |