diff --git a/bochs/cpu/cpu.cc b/bochs/cpu/cpu.cc index 0c8be2789..89d840f07 100644 --- a/bochs/cpu/cpu.cc +++ b/bochs/cpu/cpu.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: cpu.cc,v 1.189 2007-12-14 11:27:44 sshwarts Exp $ +// $Id: cpu.cc,v 1.190 2007-12-14 20:41:09 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -65,7 +65,7 @@ static Bit32u iCacheMisses=0; static Bit32u iCacheMergeTraces=0; static Bit32u iCacheTraceLengh[BX_MAX_TRACE_LENGTH]; -#define InstrICache_StatsMask 0xfffffff +#define InstrICache_StatsMask 0x3ffffff #define InstrICache_Stats() {\ if ((iCacheLookups & InstrICache_StatsMask) == 0) { \ @@ -120,7 +120,7 @@ bxICacheEntry_c* BX_CPU_C::fetchInstructionTrace(bxInstruction_c *iStorage, bx_a // We are not so lucky, but let's be optimistic - try to build trace from // incoming instruction bytes stream ! trace->pAddr = pAddr; - trace->writeStamp = ICacheWriteStampInvalid; + trace->writeStamp = pageWriteStamp; trace->ilen = 0; InstrICache_Increment(iCacheMisses); @@ -138,7 +138,7 @@ bxICacheEntry_c* BX_CPU_C::fetchInstructionTrace(bxInstruction_c *iStorage, bx_a bxInstruction_c *i = trace->i; - for (unsigned len=0;lenwriteStamp = ICacheWriteStampInvalid; boundaryFetch(fetchPtr, remainingInPage, iStorage); return 0; } // add instruction to the trace ... unsigned iLen = i->ilen(); - trace->writeStamp = pageWriteStamp; trace->ilen++; - if (i->getStopTraceAttr()) break; // ... and continue to the next instruction remainingInPage -= iLen; if (remainingInPage == 0) break; if (remainingInPage < 15) maxFetch = remainingInPage; - fetchPtr += iLen; pAddr += iLen; - i++; + fetchPtr += iLen; - if (mergeTraces(trace, i, pAddr)) break; + if (i->getStopTraceAttr()) { + unsigned b1 = i->b1() & 0x1f0; + if (b1 == 0x70 || b1 == 0x180) { // JCC instruction + // try cross JCC branch merge of traces + mergeTraces(trace, i+1, pAddr); + } + break; + } + + // try to find a trace starting from current pAddr and merge + if (mergeTraces(trace, i+1, pAddr)) break; } return trace; @@ -369,6 +377,11 @@ void BX_CPU_C::cpu_loop(Bit32u max_instr_count) while (1) { +#if BX_SUPPORT_TRACE_CACHE + // clear stop trace magic indication that probably was set by branch32/64 + BX_CPU_THIS_PTR async_event &= ~BX_ASYNC_EVENT_STOP_TRACE; +#endif + // First check on events which occurred for previous instructions // (traps) and ones which are asynchronous to the CPU // (hardware interrupts). diff --git a/bochs/cpu/cpu.h b/bochs/cpu/cpu.h index 9c9825c4a..dd2fa7639 100644 --- a/bochs/cpu/cpu.h +++ b/bochs/cpu/cpu.h @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: cpu.h,v 1.387 2007-12-14 11:27:44 sshwarts Exp $ +// $Id: cpu.h,v 1.388 2007-12-14 20:41:09 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -1199,7 +1199,10 @@ public: // for now... #define BX_DEBUG_TRAP_SPECIAL (0xf8000000) Bit32u debug_trap; // holds DR6 value (16bit) to be set as well - volatile bx_bool async_event; + volatile Bit32u async_event; + +#define BX_ASYNC_EVENT_STOP_TRACE (0x80000000) + volatile bx_bool INTR; volatile bx_bool smi_pending; volatile bx_bool nmi_pending; diff --git a/bochs/cpu/ctrl_xfer_pro.cc b/bochs/cpu/ctrl_xfer_pro.cc index 73fd7a1de..8b7836575 100644 --- a/bochs/cpu/ctrl_xfer_pro.cc +++ b/bochs/cpu/ctrl_xfer_pro.cc @@ -1,5 +1,5 @@ //////////////////////////////////////////////////////////////////////// -// $Id: ctrl_xfer_pro.cc,v 1.63 2007-12-10 23:04:18 sshwarts Exp $ +// $Id: ctrl_xfer_pro.cc,v 1.64 2007-12-14 20:41:09 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -139,6 +139,12 @@ BX_CPU_C::branch_near32(Bit32u new_EIP) BX_ERROR(("branch_near: offset outside of CS limits")); exception(BX_GP_EXCEPTION, 0, 0); } + +#if BX_SUPPORT_TRACE_CACHE + // assert magic async_event to stop trace execution + BX_CPU_THIS_PTR async_event |= BX_ASYNC_EVENT_STOP_TRACE; +#endif + EIP = new_EIP; } @@ -170,6 +176,11 @@ BX_CPU_C::branch_near64(bxInstruction_c *i) exception(BX_GP_EXCEPTION, 0, 0); } +#if BX_SUPPORT_TRACE_CACHE + // assert magic async_event to stop trace execution + BX_CPU_THIS_PTR async_event |= BX_ASYNC_EVENT_STOP_TRACE; +#endif + RIP = new_RIP; } #endif diff --git a/bochs/cpu/fetchdecode.cc b/bochs/cpu/fetchdecode.cc index 78a61033b..f33fa0cd9 100644 --- a/bochs/cpu/fetchdecode.cc +++ b/bochs/cpu/fetchdecode.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: fetchdecode.cc,v 1.147 2007-12-13 18:42:31 sshwarts Exp $ +// $Id: fetchdecode.cc,v 1.148 2007-12-14 20:41:09 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -1514,7 +1514,7 @@ static const BxOpcodeInfo_t BxOpcodeInfo32M[512*2] = { /* C0 /wm */ { BxGroup2 | BxImmediate_Ib, NULL, BxOpcodeInfoG2Eb }, /* C1 /wm */ { BxGroup2 | BxImmediate_Ib, NULL, BxOpcodeInfoG2Ew }, /* C2 /wm */ { BxImmediate_Iw | BxTraceEnd, &BX_CPU_C::RETnear16_Iw }, - /* C3 /wm */ { BxTraceEnd, &BX_CPU_C::RETnear16 }, + /* C3 /wm */ { BxTraceEnd, &BX_CPU_C::RETnear16 }, /* C4 /wm */ { 0, &BX_CPU_C::LES_GwMp }, /* C5 /wm */ { 0, &BX_CPU_C::LDS_GwMp }, /* C6 /wm */ { BxImmediate_Ib, &BX_CPU_C::MOV_EbIbM }, diff --git a/bochs/cpu/proc_ctrl.cc b/bochs/cpu/proc_ctrl.cc index 2fae1995a..bc5da1e64 100644 --- a/bochs/cpu/proc_ctrl.cc +++ b/bochs/cpu/proc_ctrl.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: proc_ctrl.cc,v 1.188 2007-12-14 11:27:44 sshwarts Exp $ +// $Id: proc_ctrl.cc,v 1.189 2007-12-14 20:41:09 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -136,14 +136,16 @@ void BX_CPU_C::CLTS(bxInstruction_c *i) void BX_CPU_C::INVD(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 4 - invalidate_prefetch_q(); - if (!real_mode() && CPL!=0) { BX_ERROR(("INVD: priveledge check failed, generate #GP(0)")); exception(BX_GP_EXCEPTION, 0, 0); } + invalidate_prefetch_q(); + BX_DEBUG(("INVD: Flush internal caches !")); + BX_INSTR_CACHE_CNTRL(BX_CPU_ID, BX_INSTR_INVD); + #if BX_SUPPORT_ICACHE flushICaches(); #endif @@ -157,14 +159,16 @@ void BX_CPU_C::INVD(bxInstruction_c *i) void BX_CPU_C::WBINVD(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 4 - invalidate_prefetch_q(); - if (!real_mode() && CPL!=0) { BX_ERROR(("WBINVD: priveledge check failed, generate #GP(0)")); exception(BX_GP_EXCEPTION, 0, 0); } + invalidate_prefetch_q(); + BX_DEBUG(("WBINVD: Flush internal caches !")); + BX_INSTR_CACHE_CNTRL(BX_CPU_ID, BX_INSTR_WBINVD); + #if BX_SUPPORT_ICACHE flushICaches(); #endif @@ -178,8 +182,11 @@ void BX_CPU_C::WBINVD(bxInstruction_c *i) void BX_CPU_C::CLFLUSH(bxInstruction_c *i) { #if BX_SUPPORT_CLFLUSH + bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[i->seg()]; // check if we could access the memory - execute_virtual_checks(&BX_CPU_THIS_PTR sregs[i->seg()], RMAddr(i), 1); + if ((seg->cache.valid & SegAccessROK4G) != SegAccessROK4G) { + execute_virtual_checks(seg, RMAddr(i), 1); + } #else BX_INFO(("CLFLUSH: not supported, enable with SSE2")); UndefinedOpcode(i); @@ -587,9 +594,8 @@ void BX_CPU_C::MOV_CdRd(bxInstruction_c *i) case 0: // CR0 (MSW) SetCR0(val_32); break; - case 1: /* CR1 */ - BX_PANIC(("MOV_CdRd: CR1 not implemented yet")); + BX_PANIC(("MOV_CdRd:CR1 not implemented yet")); break; case 2: /* CR2 */ BX_DEBUG(("MOV_CdRd:CR2 = %08x", (unsigned) val_32)); @@ -819,13 +825,13 @@ void BX_CPU_C::LMSW_Ew(bxInstruction_c *i) Bit16u msw; Bit32u cr0; - invalidate_prefetch_q(); - if (!real_mode() && CPL!=0) { BX_ERROR(("LMSW: CPL!=0 not in real mode")); exception(BX_GP_EXCEPTION, 0, 0); } + invalidate_prefetch_q(); + if (i->modC0()) { msw = BX_READ_16BIT_REG(i->rm()); }