--- np2/i386c/ia32/cpu.c 2003/12/08 00:55:31 1.1 +++ np2/i386c/ia32/cpu.c 2005/03/12 12:32:54 1.24 @@ -1,4 +1,4 @@ -/* $Id: cpu.c,v 1.1 2003/12/08 00:55:31 yui Exp $ */ +/* $Id: cpu.c,v 1.24 2005/03/12 12:32:54 monaka Exp $ */ /* * Copyright (c) 2002-2003 NONAKA Kimihiro @@ -12,8 +12,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,24 +26,112 @@ */ #include "compiler.h" +#include "dosio.h" #include "cpu.h" #include "ia32.mcr" #include "inst_table.h" -jmp_buf exec_1step_jmpbuf; +#if defined(ENABLE_TRAP) +#include "steptrap.h" +#endif + + +sigjmp_buf exec_1step_jmpbuf; + +#if defined(IA32_INSTRUCTION_TRACE) +typedef struct { + CPU_REGS regs; + disasm_context_t disasm; + + BYTE op[MAX_PREFIX + 2]; + int opbytes; +} ia32_context_t; + +#define NCTX 1024 + +ia32_context_t ctx[NCTX]; +int ctx_index = 0; + +int cpu_inst_trace = 0; +#endif + void exec_1step(void) { - BYTE op; + 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->opcode[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->opcode[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 - cpu_inst = cpu_inst_default; +#if defined(IA32_SUPPORT_DEBUG_REGISTER) + if (CPU_STAT_BP && !(CPU_EFLAG & RF_FLAG)) { + int i; + for (i = 0; i < CPU_DEBUG_REG_INDEX_NUM; i++) { + if ((CPU_STAT_BP & (1 << i)) + && (CPU_DR7_GET_RW(i) == CPU_DR7_RW_CODE) + && (CPU_DR(i) == CPU_EIP) + && (CPU_DR7_GET_LEN(i) == 0)) { + CPU_DR6 |= CPU_DR6_B(i); + EXCEPTION(DB_EXCEPTION, 0); + } + } + } +#endif /* IA32_SUPPORT_DEBUG_REGISTER */ - for (;;) { + 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) { @@ -54,11 +140,28 @@ exec_1step(void) } break; } + if (prefix == MAX_PREFIX) { + EXCEPTION(UD_EXCEPTION, 0); + } + +#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) { (*insttable_1byte[CPU_INST_OP32][op])(); +#if defined(IA32_SUPPORT_DEBUG_REGISTER) + goto check_break_point; +#else return; +#endif } /* rep */ @@ -67,39 +170,101 @@ exec_1step(void) 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) + 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) + 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) + 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) + 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) + 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) + 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 */ }