Improved version of trace cache patch:

- configure support
   - ability to configure legacy ICACHE without trace cache
   - only with legacy ICACHE - still support INSTR_OPCODE callback
   - info in main.cc
This commit is contained in:
Stanislav Shwartsman 2007-11-26 18:00:34 +00:00
parent 91add6a05a
commit 06550b3fdd
1 changed files with 159 additions and 126 deletions

View File

@ -1,7 +1,77 @@
diff -ur bochs/config.h.in bochs-trace-cache/config.h.in
--- bochs/config.h.in 2007-11-22 08:28:05.000000000 +0200
+++ bochs-trace-cache/config.h.in 2007-11-26 19:37:19.218750000 +0200
@@ -730,6 +730,11 @@
#define BX_SupportHostAsms 0
#define BX_SUPPORT_ICACHE 0
+#define BX_SUPPORT_TRACE_CACHE 0
+
+#if (BX_SUPPORT_TRACE_CACHE && BX_SUPPORT_ICACHE==0)
+#error Trace cache optimizatin cannot be compiled without iCache!
+#endif
// if 1, don't do gpf on MSRs that we don't implement
#define BX_IGNORE_BAD_MSR 0
diff -ur bochs/configure.in bochs-trace-cache/configure.in
--- bochs/configure.in 2007-11-23 14:47:12.000000000 +0200
+++ bochs-trace-cache/configure.in 2007-11-26 19:39:44.546875000 +0200
@@ -1006,6 +1006,27 @@
]
)
+AC_MSG_CHECKING(for instruction trace cache support)
+AC_ARG_ENABLE(trace-cache,
+ [ --enable-trace-cache support instruction trace cache],
+ [if test "$enableval" = yes; then
+ AC_MSG_RESULT(yes)
+ speedup_TraceCache=1
+ else
+ AC_MSG_RESULT(no)
+ speedup_TraceCache=0
+ fi],
+ [
+ if test "$speedup_TraceCache " = 1; then
+ AC_MSG_RESULT(yes)
+ speedup_TraceCache=1
+ else
+ AC_MSG_RESULT(no)
+ speedup_TraceCache=0
+ fi
+ ]
+ )
+
AC_MSG_CHECKING(for instruction cache support)
AC_ARG_ENABLE(icache,
[ --enable-icache support instruction cache],
@@ -1262,6 +1283,10 @@
speedup_fastcall=1
fi
+if test "$speedup_iCache" = 0 -a "$speedup_TraceCache" = 1; then
+ AC_MSG_ERROR([iCache is require to compile with trace cache optimization])
+fi
+
if test "$speedup_guest2host_tlb" = 1; then
AC_DEFINE(BX_SupportGuest2HostTLB, 1)
else
@@ -1292,6 +1317,12 @@
AC_DEFINE(BX_FAST_FUNC_CALL, 0)
fi
+if test "$speedup_TraceCache" = 1; then
+ AC_DEFINE(BX_SUPPORT_TRACE_CACHE, 1)
+else
+ AC_DEFINE(BX_SUPPORT_TRACE_CACHE, 0)
+fi
+
READLINE_LIB=""
rl_without_curses_ok=no
diff -ur bochs/cpu/cpu.cc bochs-trace-cache/cpu/cpu.cc
--- bochs/cpu/cpu.cc 2007-11-24 16:22:32.000000000 +0200
+++ bochs-trace-cache/cpu/cpu.cc 2007-11-24 16:29:57.078125000 +0200
@@ -62,16 +62,19 @@
+++ bochs-trace-cache/cpu/cpu.cc 2007-11-26 19:32:46.359375000 +0200
@@ -62,16 +62,20 @@
#if InstrumentICACHE
static unsigned iCacheLookups=0;
static unsigned iCacheMisses=0;
@ -20,53 +90,33 @@ diff -ur bochs/cpu/cpu.cc bochs-trace-cache/cpu/cpu.cc
(iCacheLookups-iCacheMisses) * 100.0 / iCacheLookups)); \
- iCacheLookups = iCacheMisses = 0; \
+ iCacheLookups = iCacheMisses = iCacheMergeTraces = 0; \
+ for (int i=0;i<=BX_MAX_TRACE_LENGTH;i++) iCacheLength[i] = 0; \
} \
}
#define InstrICache_Increment(v) (v)++
@@ -90,49 +93,125 @@
@@ -90,7 +94,118 @@
#define RCX ECX
#endif
-BX_CPP_INLINE bxInstruction_c* BX_CPU_C::fetchInstruction(bxInstruction_c *iStorage, bx_address eipBiased)
-{
- unsigned ret;
- bxInstruction_c *i = iStorage;
-
#if BX_SUPPORT_ICACHE
+#if BX_SUPPORT_TRACE_CACHE
+
+bxICacheEntry_c* BX_CPU_C::fetchInstructionTrace(bxInstruction_c *iStorage, bx_address eipBiased)
+{
bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrA20Page + eipBiased;
unsigned iCacheHash = BX_CPU_THIS_PTR iCache.hash(pAddr);
- bxICacheEntry_c *cache_entry = &(BX_CPU_THIS_PTR iCache.entry[iCacheHash]);
- i = &(cache_entry->i);
-
+ bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrA20Page + eipBiased;
+ unsigned iCacheHash = BX_CPU_THIS_PTR iCache.hash(pAddr);
+ bxICacheEntry_c *trace = &(BX_CPU_THIS_PTR iCache.entry[iCacheHash]);
Bit32u pageWriteStamp = *(BX_CPU_THIS_PTR currPageWriteStampPtr);
InstrICache_Increment(iCacheLookups);
InstrICache_Stats();
- if ((cache_entry->pAddr == pAddr) &&
- (cache_entry->writeStamp == pageWriteStamp))
+ Bit32u pageWriteStamp = *(BX_CPU_THIS_PTR currPageWriteStampPtr);
+
+ InstrICache_Increment(iCacheLookups);
+ InstrICache_Stats();
+
+ if ((trace->pAddr == pAddr) &&
+ (trace->writeStamp == pageWriteStamp))
{
- // iCache hit. Instruction is already decoded and stored in the
- // instruction cache.
-#if BX_INSTRUMENTATION
- // An instruction was found in the iCache.
- BX_INSTR_OPCODE(BX_CPU_ID, BX_CPU_THIS_PTR eipFetchPtr + eipBiased,
- i->ilen(), BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b, Is64BitMode());
-#endif
- return i;
+ {
+ return trace; // We are lucky - trace cache hit !
}
-#endif
- // iCache miss. No validated instruction with matching fetch parameters
- // is in the iCache. Or we're not compiling iCache support in, in which
- // case we always have an iCache miss. :^)
+ }
+
+ // We are not so lucky, but let's be optimistic - try to build trace from
+ // incoming instruction bytes stream !
+ trace->pAddr = pAddr;
@ -75,16 +125,12 @@ diff -ur bochs/cpu/cpu.cc bochs-trace-cache/cpu/cpu.cc
+
+ InstrICache_Increment(iCacheMisses);
+
bx_address remainingInPage = (BX_CPU_THIS_PTR eipPageWindowSize - eipBiased);
unsigned maxFetch = 15;
if (remainingInPage < 15) maxFetch = remainingInPage;
Bit8u *fetchPtr = BX_CPU_THIS_PTR eipFetchPtr + eipBiased;
+ bx_address remainingInPage = (BX_CPU_THIS_PTR eipPageWindowSize - eipBiased);
+ unsigned maxFetch = 15;
+ if (remainingInPage < 15) maxFetch = remainingInPage;
+ Bit8u *fetchPtr = BX_CPU_THIS_PTR eipFetchPtr + eipBiased;
+ unsigned ret;
-#if BX_SUPPORT_ICACHE
- // The entry will be marked valid if fetchdecode will succeed
- cache_entry->writeStamp = ICacheWriteStampInvalid;
- InstrICache_Increment(iCacheMisses);
+
+ // We could include in trace maximum BX_MAX_TRACE_LEN instructions
+ unsigned max_length = BX_MAX_TRACE_LENGTH;
+ if ((pageWriteStamp & ICacheWriteStampMask) != ICacheWriteStampStart)
@ -98,7 +144,7 @@ diff -ur bochs/cpu/cpu.cc bochs-trace-cache/cpu/cpu.cc
+ if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64)
+ ret = fetchDecode64(fetchPtr, i, maxFetch);
+ else
#endif
+#endif
+ ret = fetchDecode32(fetchPtr, i, maxFetch);
+
+ if (ret==0) {
@ -164,39 +210,11 @@ diff -ur bochs/cpu/cpu.cc bochs-trace-cache/cpu/cpu.cc
+
+#else
+
+BX_CPP_INLINE bxInstruction_c* BX_CPU_C::fetchInstruction(bxInstruction_c *iStorage, bx_address eipBiased)
+{
+ bxInstruction_c *i = iStorage;
+ bx_address remainingInPage = (BX_CPU_THIS_PTR eipPageWindowSize - eipBiased);
+ unsigned maxFetch = 15;
+ if (remainingInPage < 15) maxFetch = remainingInPage;
+ Bit8u *fetchPtr = BX_CPU_THIS_PTR eipFetchPtr + eipBiased;
+ unsigned ret;
#if BX_SUPPORT_X86_64
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64)
@@ -142,26 +221,14 @@
ret = fetchDecode32(fetchPtr, i, maxFetch);
if (ret==0) {
- // return iStorage and leave icache entry invalid (do not cache instr)
- boundaryFetch(fetchPtr, remainingInPage, iStorage);
- return iStorage;
- }
- else
- {
-#if BX_SUPPORT_ICACHE
- cache_entry->pAddr = pAddr;
- cache_entry->writeStamp = pageWriteStamp;
-#endif
-#if BX_INSTRUMENTATION
- // An instruction was either fetched, or found in the iCache.
- BX_INSTR_OPCODE(BX_CPU_ID, fetchPtr, i->ilen(),
- BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b, Is64BitMode());
-#endif
+ boundaryFetch(fetchPtr, remainingInPage, i);
}
+bxInstruction_c* BX_CPU_C::fetchInstruction(bxInstruction_c *iStorage, bx_address eipBiased)
{
unsigned ret;
bxInstruction_c *i = iStorage;
@@ -162,6 +277,8 @@
return i;
}
@ -205,27 +223,25 @@ diff -ur bochs/cpu/cpu.cc bochs-trace-cache/cpu/cpu.cc
// The CHECK_MAX_INSTRUCTIONS macro allows cpu_loop to execute a few
// instructions and then return so that the other processors have a chance to
// run. This is used by bochs internal debugger or when simulating
@@ -244,47 +309,68 @@
@@ -244,47 +359,67 @@
eipBiased = RIP + BX_CPU_THIS_PTR eipPageBias;
}
- // fetch and decode next instruction
- bxInstruction_c *i = fetchInstruction(&iStorage, eipBiased);
+#if BX_SUPPORT_TRACE_CACHE == 0
+ // fetch and decode single instruction
bxInstruction_c *i = fetchInstruction(&iStorage, eipBiased);
+#else
+ unsigned n, length = 1;
+ bxInstruction_c *i = &iStorage;
+ unsigned length = 1, n;
+
+#if BX_SUPPORT_ICACHE
+ bxICacheEntry_c *trace = fetchInstructionTrace(&iStorage, eipBiased);
+ if (trace) {
+ i = trace->i; // execute from first instruction in trace
+ length = trace->ilen;
+ }
+#else
+ // fetch and decode single instruction
+ i = fetchInstruction(&iStorage, eipBiased);
+#endif
+
+ for (n=0; n < length; n++, i++) {
+#endif
- BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
+ BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
@ -288,19 +304,19 @@ diff -ur bochs/cpu/cpu.cc bochs-trace-cache/cpu/cpu.cc
- CHECK_MAX_INSTRUCTIONS(max_instr_count);
+ CHECK_MAX_INSTRUCTIONS(max_instr_count);
+
+#if BX_SUPPORT_ICACHE
+#if BX_SUPPORT_TRACE_CACHE
+ if (trace && trace->writeStamp != *(BX_CPU_THIS_PTR currPageWriteStampPtr))
+ break; // probably it is self modifying code ...
+#endif
+
+ if (BX_CPU_THIS_PTR async_event) break;
+ }
+#endif
} // while (1)
}
diff -ur bochs/cpu/cpu.h bochs-trace-cache/cpu/cpu.h
--- bochs/cpu/cpu.h 2007-11-24 16:22:32.000000000 +0200
+++ bochs-trace-cache/cpu/cpu.h 2007-11-24 16:27:05.218750000 +0200
--- bochs/cpu/cpu.h 2007-11-25 22:22:06.000000000 +0200
+++ bochs-trace-cache/cpu/cpu.h 2007-11-26 19:30:42.984375000 +0200
@@ -615,9 +615,10 @@
void (BX_CPU_C::*execute)(bxInstruction_c *);
#endif
@ -318,7 +334,7 @@ diff -ur bochs/cpu/cpu.h bochs-trace-cache/cpu/cpu.h
metaInfo3 = (metaInfo3 & ~3) | (value);
}
+#if BX_SUPPORT_ICACHE
+#if BX_SUPPORT_TRACE_CACHE
+ BX_CPP_INLINE void setStopTraceAttr(void) {
+ metaInfo3 |= (1<<3);
+ }
@ -339,11 +355,11 @@ diff -ur bochs/cpu/cpu.h bochs-trace-cache/cpu/cpu.h
}
};
// <TAG-CLASS-INSTRUCTION-END>
@@ -2917,7 +2927,12 @@
@@ -2931,7 +2941,12 @@
#if BX_SUPPORT_X86_64
BX_SMF unsigned fetchDecode64(Bit8u *, bxInstruction_c *, unsigned);
#endif
+#if BX_SUPPORT_ICACHE
+#if BX_SUPPORT_TRACE_CACHE
+ BX_SMF bxICacheEntry_c* fetchInstructionTrace(bxInstruction_c *, bx_address);
+ BX_SMF bx_bool mergeTraces(bxICacheEntry_c *trace, bxInstruction_c *i, bx_phy_address pAddr);
+#else
@ -352,11 +368,11 @@ diff -ur bochs/cpu/cpu.h bochs-trace-cache/cpu/cpu.h
BX_SMF void UndefinedOpcode(bxInstruction_c *);
BX_SMF void BxError(bxInstruction_c *i);
@@ -3742,6 +3757,12 @@
@@ -3756,6 +3771,12 @@
#define BxLockable 0x0100 // bit 8
#define Bx3ByteOpcode 0x0200 // bit 9
+#if BX_SUPPORT_ICACHE
+#if BX_SUPPORT_TRACE_CACHE
+ #define BxTraceEnd 0x2000 // bit 13
+#else
+ #define BxTraceEnd 0
@ -366,8 +382,8 @@ diff -ur bochs/cpu/cpu.h bochs-trace-cache/cpu/cpu.h
#define BxGroup2 BxGroupN
#define BxGroup3 BxGroupN
diff -ur bochs/cpu/fetchdecode.cc bochs-trace-cache/cpu/fetchdecode.cc
--- bochs/cpu/fetchdecode.cc 2007-11-23 18:37:05.000000000 +0200
+++ bochs-trace-cache/cpu/fetchdecode.cc 2007-11-24 16:27:06.890625000 +0200
--- bochs/cpu/fetchdecode.cc 2007-11-25 22:22:06.000000000 +0200
+++ bochs-trace-cache/cpu/fetchdecode.cc 2007-11-26 19:34:29.234375000 +0200
@@ -207,7 +207,7 @@
/* 14 /wr */ { BxImmediate_Ib, &BX_CPU_C::ADC_ALIb },
/* 15 /wr */ { BxImmediate_Iv, &BX_CPU_C::ADC_AXIw },
@ -860,7 +876,7 @@ diff -ur bochs/cpu/fetchdecode.cc bochs-trace-cache/cpu/fetchdecode.cc
/* 0F B8 /dr */ { BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fb8d },
- /* 0F B9 /dr */ { 0, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
+ /* 0F B9 /dr */ { BxTraceEnd, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
/* 0F BA /dr */ { BxGroup8, NULL, BxOpcodeInfoG8EdIb },
/* 0F BA /dr */ { BxGroup8, NULL, BxOpcodeInfoG8EdIbR },
/* 0F BB /dr */ { 0, &BX_CPU_C::BTC_EdGdR },
/* 0F BC /dr */ { 0, &BX_CPU_C::BSF_GdEd },
@@ -1342,7 +1342,7 @@
@ -1112,7 +1128,7 @@ diff -ur bochs/cpu/fetchdecode.cc bochs-trace-cache/cpu/fetchdecode.cc
/* 0F B8 /wm */ { BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fb8w },
- /* 0F B9 /wm */ { 0, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
+ /* 0F B9 /wm */ { BxTraceEnd, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
/* 0F BA /wm */ { BxGroup8, NULL, BxOpcodeInfoG8EwIb },
/* 0F BA /wm */ { BxGroup8, NULL, BxOpcodeInfoG8EwIbM },
/* 0F BB /wm */ { BxLockable, &BX_CPU_C::BTC_EwGwM },
/* 0F BC /wm */ { 0, &BX_CPU_C::BSF_GwEw },
@@ -1906,7 +1906,7 @@
@ -1364,12 +1380,12 @@ diff -ur bochs/cpu/fetchdecode.cc bochs-trace-cache/cpu/fetchdecode.cc
/* 0F B8 /dm */ { BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fb8d },
- /* 0F B9 /dm */ { 0, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
+ /* 0F B9 /dm */ { BxTraceEnd, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
/* 0F BA /dm */ { BxGroup8, NULL, BxOpcodeInfoG8EdIb },
/* 0F BA /dm */ { BxGroup8, NULL, BxOpcodeInfoG8EdIbM },
/* 0F BB /dm */ { BxLockable, &BX_CPU_C::BTC_EdGdM },
/* 0F BC /dm */ { 0, &BX_CPU_C::BSF_GdEd },
@@ -2799,10 +2799,15 @@
// lock prefix not allowed or destination operand is not memory
if ((mod == 0xc0) || !(attr & BxLockable)) {
@@ -2800,10 +2800,15 @@
// mod == 0xc0 can't be BxLockable in fetchdecode tables
if (/*(mod == 0xc0) ||*/ !(attr & BxLockable)) {
BX_INFO(("LOCK prefix unallowed (op1=0x%x, attr=0x%x, mod=0x%x, nnn=%u)", b1, attr, mod, nnn));
- UndefinedOpcode(instruction);
+ // replace execution function with undefined-opcode
@ -1377,18 +1393,18 @@ diff -ur bochs/cpu/fetchdecode.cc bochs-trace-cache/cpu/fetchdecode.cc
}
}
+#if BX_SUPPORT_ICACHE
+#if BX_SUPPORT_TRACE_CACHE
+ if (attr & BxTraceEnd) instruction->setStopTraceAttr();
+#endif
+
imm_mode = attr & BxImmediate;
if (imm_mode) {
switch (imm_mode) {
@@ -2937,8 +2942,16 @@
@@ -2938,8 +2943,16 @@
if (BX_NULL_SEG_REG(instruction->seg()))
instruction->setSeg(BX_SEG_REG_DS);
+#if BX_SUPPORT_ICACHE
+#if BX_SUPPORT_TRACE_CACHE
+ // set stop-trace attribute for invalid instructions
+ if(instruction->execute == &BX_CPU_C::BxError) {
+ instruction->setStopTraceAttr();
@ -1402,8 +1418,8 @@ diff -ur bochs/cpu/fetchdecode.cc bochs-trace-cache/cpu/fetchdecode.cc
}
diff -ur bochs/cpu/fetchdecode.h bochs-trace-cache/cpu/fetchdecode.h
--- bochs/cpu/fetchdecode.h 2007-11-18 01:28:31.000000000 +0200
+++ bochs-trace-cache/cpu/fetchdecode.h 2007-11-23 15:33:02.234375000 +0200
--- bochs/cpu/fetchdecode.h 2007-11-25 22:22:10.000000000 +0200
+++ bochs-trace-cache/cpu/fetchdecode.h 2007-11-26 19:30:46.515625000 +0200
@@ -2869,10 +2869,10 @@
// attributes defined in main area
/* 0 */ { BxLockable, &BX_CPU_C::INC_EwM },
@ -1610,10 +1626,10 @@ diff -ur bochs/cpu/fetchdecode.h bochs-trace-cache/cpu/fetchdecode.h
};
#endif
Files bochs/cpu/fetchdecode.o and bochs-trace-cache/cpu/fetchdecode.o differ
Only in bochs-trace-cache/cpu: fetchdecode.o
diff -ur bochs/cpu/fetchdecode64.cc bochs-trace-cache/cpu/fetchdecode64.cc
--- bochs/cpu/fetchdecode64.cc 2007-11-24 16:22:33.000000000 +0200
+++ bochs-trace-cache/cpu/fetchdecode64.cc 2007-11-24 16:29:38.359375000 +0200
--- bochs/cpu/fetchdecode64.cc 2007-11-25 22:22:10.000000000 +0200
+++ bochs-trace-cache/cpu/fetchdecode64.cc 2007-11-26 19:34:57.875000000 +0200
@@ -285,22 +285,22 @@
/* 6D /wr */ { 0, &BX_CPU_C::REP_INSW_YwDX },
/* 6E /wr */ { 0, &BX_CPU_C::REP_OUTSB_DXXb },
@ -1811,7 +1827,7 @@ diff -ur bochs/cpu/fetchdecode64.cc bochs-trace-cache/cpu/fetchdecode64.cc
/* 0F B8 /wr */ { BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fb8w },
- /* 0F B9 /wr */ { 0, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
+ /* 0F B9 /wr */ { BxTraceEnd, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
/* 0F BA /wr */ { BxGroup8, NULL, BxOpcodeInfoG8EwIb },
/* 0F BA /wr */ { BxGroup8, NULL, BxOpcodeInfoG8EwIbR },
/* 0F BB /wr */ { 0, &BX_CPU_C::BTC_EwGwR },
/* 0F BC /wr */ { 0, &BX_CPU_C::BSF_GwEw },
@@ -814,22 +814,22 @@
@ -2011,7 +2027,7 @@ diff -ur bochs/cpu/fetchdecode64.cc bochs-trace-cache/cpu/fetchdecode64.cc
/* 0F B8 /dr */ { BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fb8d },
- /* 0F B9 /dr */ { 0, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
+ /* 0F B9 /dr */ { BxTraceEnd, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
/* 0F BA /dr */ { BxGroup8, NULL, BxOpcodeInfoG8EdIb },
/* 0F BA /dr */ { BxGroup8, NULL, BxOpcodeInfoG8EdIbR },
/* 0F BB /dr */ { 0, &BX_CPU_C::BTC_EdGdR },
/* 0F BC /dr */ { 0, &BX_CPU_C::BSF_GdEd },
@@ -1343,22 +1343,22 @@
@ -2211,7 +2227,7 @@ diff -ur bochs/cpu/fetchdecode64.cc bochs-trace-cache/cpu/fetchdecode64.cc
/* 0F B8 /qr */ { BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fb8q },
- /* 0F B9 /qr */ { 0, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
+ /* 0F B9 /qr */ { BxTraceEnd, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
/* 0F BA /qr */ { BxGroup8, NULL, BxOpcodeInfo64G8EqIb },
/* 0F BA /qr */ { BxGroup8, NULL, BxOpcodeInfo64G8EqIbR },
/* 0F BB /qr */ { 0, &BX_CPU_C::BTC_EqGqR },
/* 0F BC /qr */ { 0, &BX_CPU_C::BSF_GqEq },
@@ -1878,22 +1878,22 @@
@ -2411,7 +2427,7 @@ diff -ur bochs/cpu/fetchdecode64.cc bochs-trace-cache/cpu/fetchdecode64.cc
/* 0F B8 /wm */ { BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fb8w },
- /* 0F B9 /wm */ { 0, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
+ /* 0F B9 /wm */ { BxTraceEnd, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
/* 0F BA /wm */ { BxGroup8, NULL, BxOpcodeInfoG8EwIb },
/* 0F BA /wm */ { BxGroup8, NULL, BxOpcodeInfoG8EwIbM },
/* 0F BB /wm */ { BxLockable, &BX_CPU_C::BTC_EwGwM },
/* 0F BC /wm */ { 0, &BX_CPU_C::BSF_GwEw },
@@ -2407,22 +2407,22 @@
@ -2611,7 +2627,7 @@ diff -ur bochs/cpu/fetchdecode64.cc bochs-trace-cache/cpu/fetchdecode64.cc
/* 0F B8 /dm */ { BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fb8d },
- /* 0F B9 /dm */ { 0, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
+ /* 0F B9 /dm */ { BxTraceEnd, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
/* 0F BA /dm */ { BxGroup8, NULL, BxOpcodeInfoG8EdIb },
/* 0F BA /dm */ { BxGroup8, NULL, BxOpcodeInfoG8EdIbM },
/* 0F BB /dm */ { BxLockable, &BX_CPU_C::BTC_EdGdM },
/* 0F BC /dm */ { 0, &BX_CPU_C::BSF_GdEd },
@@ -2936,22 +2936,22 @@
@ -2811,12 +2827,12 @@ diff -ur bochs/cpu/fetchdecode64.cc bochs-trace-cache/cpu/fetchdecode64.cc
/* 0F B8 /qm */ { BxPrefixSSE, NULL, BxOpcodeGroupSSE_0fb8q },
- /* 0F B9 /qm */ { 0, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
+ /* 0F B9 /qm */ { BxTraceEnd, &BX_CPU_C::UndefinedOpcode }, // UD2 opcode
/* 0F BA /qm */ { BxGroup8, NULL, BxOpcodeInfo64G8EqIb },
/* 0F BA /qm */ { BxGroup8, NULL, BxOpcodeInfo64G8EqIbM },
/* 0F BB /qm */ { BxLockable, &BX_CPU_C::BTC_EqGqM },
/* 0F BC /qm */ { 0, &BX_CPU_C::BSF_GqEq },
@@ -3767,10 +3767,15 @@
// lock prefix not allowed or destination operand is not memory
if ((mod == 0xc0) || !(attr & BxLockable)) {
@@ -3768,10 +3768,15 @@
// mod == 0xc0 can't be BxLockable in fetchdecode tables
if (/*(mod == 0xc0) ||*/ !(attr & BxLockable)) {
BX_INFO(("LOCK prefix unallowed (op1=0x%x, mod=%u, nnn=%u)", b1, mod, nnn));
- UndefinedOpcode(instruction);
+ // replace execution function with undefined-opcode
@ -2824,18 +2840,18 @@ diff -ur bochs/cpu/fetchdecode64.cc bochs-trace-cache/cpu/fetchdecode64.cc
}
}
+#if BX_SUPPORT_ICACHE
+#if BX_SUPPORT_TRACE_CACHE
+ if (attr & BxTraceEnd) instruction->setStopTraceAttr();
+#endif
+
imm_mode = attr & BxImmediate;
if (imm_mode) {
switch (imm_mode) {
@@ -3889,6 +3894,13 @@
@@ -3890,6 +3895,13 @@
if (BX_NULL_SEG_REG(instruction->seg()))
instruction->setSeg(BX_SEG_REG_DS);
+#if BX_SUPPORT_ICACHE
+#if BX_SUPPORT_TRACE_CACHE
+ // set stop-trace attribute for invalid instructions
+ if(instruction->execute == &BX_CPU_C::BxError) {
+ instruction->setStopTraceAttr();
@ -2847,12 +2863,14 @@ diff -ur bochs/cpu/fetchdecode64.cc bochs-trace-cache/cpu/fetchdecode64.cc
return(1);
diff -ur bochs/cpu/icache.h bochs-trace-cache/cpu/icache.h
--- bochs/cpu/icache.h 2007-11-22 19:32:00.000000000 +0200
+++ bochs-trace-cache/cpu/icache.h 2007-11-23 15:37:53.703125000 +0200
@@ -115,12 +115,15 @@
+++ bochs-trace-cache/cpu/icache.h 2007-11-26 18:03:18.316625600 +0200
@@ -115,12 +115,21 @@
#define BxICacheEntries (64 * 1024) // Must be a power of 2.
+#if BX_SUPPORT_TRACE_CACHE
+#define BX_MAX_TRACE_LENGTH 16
+#endif
+
struct bxICacheEntry_c
{
@ -2860,8 +2878,23 @@ diff -ur bochs/cpu/icache.h bochs-trace-cache/cpu/icache.h
Bit32u writeStamp; // Generation ID. Each write to a physical page
// decrements this value
- bxInstruction_c i; // The instruction decode information
+#if BX_SUPPORT_TRACE_CACHE
+ Bit32u ilen; // Trace length in instructions
+ bxInstruction_c i[BX_MAX_TRACE_LENGTH];
+#else
+ bxInstruction_c i;
+#endif
};
class BOCHSAPI bxICache_c {
diff -ur bochs/main.cc bochs-trace-cache/main.cc
--- bochs/main.cc 2007-11-20 20:36:26.000000000 +0200
+++ bochs-trace-cache/main.cc 2007-11-26 19:41:46.671875000 +0200
@@ -1003,6 +1003,7 @@
BX_INFO((" Guest2HostTLB support: %s",BX_SupportGuest2HostTLB?"yes":"no"));
BX_INFO((" RepeatSpeedups support: %s",BX_SupportRepeatSpeedups?"yes":"no"));
BX_INFO((" Icache support: %s",BX_SUPPORT_ICACHE?"yes":"no"));
+ BX_INFO((" Trace cache support: %s",BX_SUPPORT_TRACE_CACHE?"yes":"no"));
BX_INFO((" Fast function calls: %s",BX_FAST_FUNC_CALL?"yes":"no"));
BX_INFO(("Devices configuration"));
BX_INFO((" ACPI support: %s",BX_SUPPORT_ACPI?"yes":"no"));