|
|
| version 1.2, 2003/12/22 18:00:31 | version 1.28, 2012/01/08 11:36:05 |
|---|---|
| Line 1 | Line 1 |
| /* $Id$ */ | |
| /* | /* |
| * Copyright (c) 2002-2003 NONAKA Kimihiro | * Copyright (c) 2002-2003 NONAKA Kimihiro |
| * All rights reserved. | * All rights reserved. |
| Line 12 | Line 10 |
| * 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the | * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. | * documentation and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products | |
| * derived from this software without specific prior written permission. | |
| * | * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| Line 28 | Line 24 |
| */ | */ |
| #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) | #if defined(ENABLE_TRAP) |
| UINT32 inst_1byte_count[2][256]; | #include "steptrap.h" |
| UINT32 inst_2byte_count[2][256]; | #endif |
| 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 | |
| clear_profile_inst(void) | |
| { | |
| memset(inst_1byte_count, 0, sizeof(inst_1byte_count)); | sigjmp_buf exec_1step_jmpbuf; |
| memset(inst_2byte_count, 0, sizeof(inst_2byte_count)); | |
| memset(ea16_count, 0, sizeof(ea16_count)); | |
| memset(ea32_count, 0, sizeof(ea32_count)); | |
| memset(sib0_count, 0, sizeof(sib0_count)); | |
| memset(sib1_count, 0, sizeof(sib1_count)); | |
| memset(sib2_count, 0, sizeof(sib2_count)); | |
| } | |
| void | #if defined(IA32_INSTRUCTION_TRACE) |
| show_profile_inst(void) | typedef struct { |
| { | CPU_REGS regs; |
| int i; | disasm_context_t disasm; |
| printf("instruction (16bit)\n"); | BYTE op[MAX_PREFIX + 2]; |
| for (i = 0; i < 256; i++) { | int opbytes; |
| if (inst_1byte_count[0][i] != 0) { | } ia32_context_t; |
| 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"); | #define NCTX 1024 |
| for (i = 0; i < 256; i++) { | |
| 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 | ia32_context_t ctx[NCTX]; |
| show_profile_ea(void) | int ctx_index = 0; |
| { | |
| char buf[80]; | int cpu_inst_trace = 0; |
| 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 |
| #define MAX_PREFIX 8 | #if defined(DEBUG) |
| int cpu_debug_rep_cont = 0; | |
| CPU_REGS cpu_debug_rep_regs; | |
| #endif | |
| jmp_buf exec_1step_jmpbuf; | |
| void | void |
| exec_1step(void) | exec_1step(void) |
| { | { |
| BYTE op; | int prefix; |
| BYTE prefix; | UINT32 op; |
| CPU_PREV_EIP = CPU_EIP; | CPU_PREV_EIP = CPU_EIP; |
| CPU_STATSAVE.cpu_inst = CPU_STATSAVE.cpu_inst_default; | CPU_STATSAVE.cpu_inst = CPU_STATSAVE.cpu_inst_default; |
| #if defined(ENABLE_TRAP) | |
| steptrap(CPU_CS, CPU_EIP); | |
| #endif | |
| #if defined(IA32_INSTRUCTION_TRACE) | |
| ctx[ctx_index].regs = CPU_STATSAVE.cpu_regs; | |
| if (cpu_inst_trace) { | |
| disasm_context_t *d = &ctx[ctx_index].disasm; | |
| UINT32 eip = CPU_EIP; | |
| int rv; | |
| rv = disasm(&eip, d); | |
| if (rv == 0) { | |
| char buf[256]; | |
| char tmp[32]; | |
| int len = d->nopbytes > 8 ? 8 : d->nopbytes; | |
| int i; | |
| buf[0] = '\0'; | |
| for (i = 0; i < len; i++) { | |
| snprintf(tmp, sizeof(tmp), "%02x ", d->opbyte[i]); | |
| milstr_ncat(buf, tmp, sizeof(buf)); | |
| } | |
| for (; i < 8; i++) { | |
| milstr_ncat(buf, " ", sizeof(buf)); | |
| } | |
| VERBOSE(("%04x:%08x: %s%s", CPU_CS, CPU_EIP, buf, d->str)); | |
| buf[0] = '\0'; | |
| for (; i < d->nopbytes; i++) { | |
| snprintf(tmp, sizeof(tmp), "%02x ", d->opbyte[i]); | |
| milstr_ncat(buf, tmp, sizeof(buf)); | |
| if ((i % 8) == 7) { | |
| VERBOSE((" : %s", buf)); | |
| buf[0] = '\0'; | |
| } | |
| } | |
| if ((i % 8) != 0) { | |
| VERBOSE((" : %s", buf)); | |
| } | |
| } | |
| } | |
| ctx[ctx_index].opbytes = 0; | |
| #endif | |
| 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) | |
| ctx[ctx_index].op[prefix] = op; | |
| ctx[ctx_index].opbytes++; | |
| #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 225 exec_1step(void) | Line 131 exec_1step(void) |
| if (prefix == MAX_PREFIX) { | if (prefix == MAX_PREFIX) { |
| EXCEPTION(UD_EXCEPTION, 0); | EXCEPTION(UD_EXCEPTION, 0); |
| } | } |
| PROFILE_INC_INST_1BYTE(op); | |
| #if defined(IA32_INSTRUCTION_TRACE) | |
| if (op == 0x0f) { | |
| BYTE op2; | |
| op2 = cpu_codefetch(CPU_EIP); | |
| ctx[ctx_index].op[prefix + 1] = op2; | |
| ctx[ctx_index].opbytes++; | |
| } | |
| ctx_index = (ctx_index + 1) % NELEMENTS(ctx); | |
| #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) { |
| #if defined(DEBUG) | |
| cpu_debug_rep_cont = 0; | |
| #endif | |
| (*insttable_1byte[CPU_INST_OP32][op])(); | (*insttable_1byte[CPU_INST_OP32][op])(); |
| return; | return; |
| } | } |
| /* rep */ | /* rep */ |
| CPU_WORKCLOCK(5); | CPU_WORKCLOCK(5); |
| #if defined(DEBUG) | |
| if (!cpu_debug_rep_cont) { | |
| cpu_debug_rep_cont = 1; | |
| cpu_debug_rep_regs = CPU_STATSAVE.cpu_regs; | |
| } | |
| #endif | |
| if (!CPU_INST_AS32) { | if (!CPU_INST_AS32) { |
| 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) { |
| #if defined(DEBUG) | |
| cpu_debug_rep_cont = 0; | |
| #endif | |
| 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) { |
| #if defined(DEBUG) | |
| cpu_debug_rep_cont = 0; | |
| #endif | |
| 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) { |
| #if defined(DEBUG) | |
| cpu_debug_rep_cont = 0; | |
| #endif | |
| 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) { |
| #if defined(DEBUG) | |
| cpu_debug_rep_cont = 0; | |
| #endif | |
| 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) { |
| #if defined(DEBUG) | |
| cpu_debug_rep_cont = 0; | |
| #endif | |
| 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) { |
| #if defined(DEBUG) | |
| cpu_debug_rep_cont = 0; | |
| #endif | |
| break; | |
| } | |
| if (CPU_REMCLOCK <= 0) { | |
| CPU_EIP = CPU_PREV_EIP; | |
| break; | |
| } | |
| } | |
| } | } |
| } | } |
| } | } |