--- np2/i386c/ia32/cpu.c 2003/12/22 18:00:31 1.2 +++ np2/i386c/ia32/cpu.c 2012/01/08 11:36:05 1.28 @@ -1,5 +1,3 @@ -/* $Id: cpu.c,v 1.2 2003/12/22 18:00:31 monaka Exp $ */ - /* * Copyright (c) 2002-2003 NONAKA Kimihiro * All rights reserved. @@ -12,8 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * 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 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -28,195 +24,105 @@ */ #include "compiler.h" +#include "dosio.h" #include "cpu.h" #include "ia32.mcr" #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", -}; +#if defined(ENABLE_TRAP) +#include "steptrap.h" +#endif -void -clear_profile_inst(void) -{ - memset(inst_1byte_count, 0, sizeof(inst_1byte_count)); - 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)); -} +sigjmp_buf exec_1step_jmpbuf; -void -show_profile_inst(void) -{ - int i; +#if defined(IA32_INSTRUCTION_TRACE) +typedef struct { + CPU_REGS regs; + disasm_context_t disasm; - printf("instruction (16bit)\n"); - 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]); - } - } + BYTE op[MAX_PREFIX + 2]; + int opbytes; +} ia32_context_t; - printf("instruction (32bit)\n"); - 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]); - } - } -} +#define NCTX 1024 -void -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]); - } - } -} +ia32_context_t ctx[NCTX]; +int ctx_index = 0; + +int cpu_inst_trace = 0; #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 exec_1step(void) { - BYTE op; - BYTE prefix; + int prefix; + UINT32 op; CPU_PREV_EIP = CPU_EIP; - 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++) { GET_PCBYTE(op); +#if defined(IA32_INSTRUCTION_TRACE) + ctx[ctx_index].op[prefix] = op; + ctx[ctx_index].opbytes++; +#endif /* prefix */ if (insttable_info[op] & INST_PREFIX) { - PROFILE_INC_INST_1BYTE(op); (*insttable_1byte[0][op])(); continue; } @@ -225,52 +131,130 @@ exec_1step(void) if (prefix == MAX_PREFIX) { 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 */ if (!(insttable_info[op] & INST_STRING) || !CPU_INST_REPUSE) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif (*insttable_1byte[CPU_INST_OP32][op])(); return; } /* rep */ 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_CX != 0) { if (!(insttable_info[op] & REP_CHECKZF)) { /* rep */ - do { + for (;;) { (*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) { /* repe */ - do { + for (;;) { (*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 { /* repne */ - do { + for (;;) { (*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 { if (CPU_ECX != 0) { if (!(insttable_info[op] & REP_CHECKZF)) { /* rep */ - do { + for (;;) { (*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) { /* repe */ - do { + for (;;) { (*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 { /* repne */ - do { + for (;;) { (*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; + } + } } } }