Added ability to merge traces cross JCC branch instructions
Makes traces longer -> emulation faster in average
This commit is contained in:
parent
db69a25c36
commit
d9a59c7a1f
@ -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;len<max_length;len++)
|
||||
for (unsigned len=0;len<max_length;len++,i++)
|
||||
{
|
||||
#if BX_SUPPORT_X86_64
|
||||
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64)
|
||||
@ -157,25 +157,33 @@ bxICacheEntry_c* BX_CPU_C::fetchInstructionTrace(bxInstruction_c *iStorage, bx_a
|
||||
}
|
||||
// First instruction is boundary fetch, return iStorage and leave
|
||||
// the trace cache entry invalid (do not cache the instruction)
|
||||
trace->writeStamp = 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).
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 },
|
||||
|
@ -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());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user