Bochs/bochs/patches/patch.fetchdecode-cache

287 lines
8.9 KiB
Plaintext
Raw Normal View History

----------------------------------------------------------------------
Patch name: patche-fetchdecode-cache
Author: tld
Date: May, 29th 2002
Detailed description:
I somehow managed to implement the fetchdecode caching system I wrote
about last night (and to which I didn't get any answer)
I couldn't benchmark it as I wanted (mainly, I lack the tools) so I
don't really know what performance change it brought.
It has issues with code morphing (and some other things I can't
recognize in the code), but if the cache is "small enough" it works.
For those interested, I left the source code on
http://tld.digitalcurse.com/bochs/cpu.cc which is meant to
replace the
file cpu/cpu.cc in the CVS snapshot 20020527 which you can find at
http://tld.digitalcurse.com/bochs/bochs-20020527.tar.bz2 if
2002-05-30 01:52:36 +04:00
you don't have CVS access.
I'd like to hear comments on this.
PS. Of course, my code does NOT follow bochs' code standard which is not
intended to be inserted into the release. This is just intended as a
prototype did in 2 hours (of which, 1.5 for understanding the
surrounding code...)
Patch was created with:
cvs diff -u
Apply patch to what version:
cvs checked out on May, 29th 2002
Instructions:
To patch, go to main bochs directory.
Type "patch -p0 < THIS_PATCH_FILE".
----------------------------------------------------------------------
2002-05-30 01:52:36 +04:00
Index: config.h.in
===================================================================
RCS file: /cvsroot/bochs/bochs/config.h.in,v
retrieving revision 1.48
diff -u -r1.48 config.h.in
--- config.h.in 18 Apr 2002 01:00:53 -0000 1.48
+++ config.h.in 29 May 2002 21:46:52 -0000
@@ -189,6 +189,14 @@
#define BX_SUPPORT_V8086_MODE 1
+
+// Use fetchdecode cache
+// 1 = use the cache
+// 0 = don't use the cache
+
+#define BX_FETCHDECODE_CACHE 01
+
+
// Support shadowing of ROM from C0000 to FFFFF.
// This allows that region to be written to.
#define BX_SHADOW_RAM 0
Index: cpu/cpu.cc
===================================================================
RCS file: /cvsroot/bochs/bochs/cpu/cpu.cc,v
retrieving revision 1.28
diff -u -r1.28 cpu.cc
--- cpu/cpu.cc 18 Apr 2002 00:22:19 -0000 1.28
2002-05-30 01:52:36 +04:00
+++ cpu/cpu.cc 29 May 2002 21:46:53 -0000
@@ -26,7 +26,6 @@
#define BX_INSTR_SPY 0
-
#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#define LOG_THIS BX_CPU_THIS_PTR
@@ -37,6 +36,35 @@
//unsigned counter[2] = { 0, 0 };
2002-05-30 01:52:36 +04:00
+#if BX_FETCHDECODE_CACHE
+ // The number of entries. MUST be a power of 2
+ #define BX_FDCACHE_SIZE 0x0100
+ #define BX_FDCACHE_MASK (BX_FDCACHE_SIZE-1)
+
+ // To get information about hit ratio every so operations
+ #define BX_FDCACHE_STATS 0x100000
+
+ // The following stuff must be added to the processor's data (or else... poor MP!)
+ // note from cb : still to do
+
2002-05-30 01:52:36 +04:00
+ Bit32u fdcache_eip[BX_FDCACHE_SIZE]; // will store operation's IP
+
2002-05-30 01:52:36 +04:00
+ // NOTE: This struct should really be aligned!
+ BxInstruction_t fdcache_i[BX_FDCACHE_SIZE]; // stores decoded instruction
+
2002-05-30 01:52:36 +04:00
+ Bit32u fdcache_cs; // the last used CS
+ Bit32u fdcache_32; // was the segment 32bit?
+
2002-05-30 01:52:36 +04:00
+ // End of stuff to insert
+
+ unsigned long bx_fdcache_sel,
+ bx_fdcache_eip;
+
+ #if BX_FDCACHE_STATS
+ int bx_fdcache_hit = 0; // cache hits
+ int bx_fdcache_acc = BX_FDCACHE_STATS; // total accesses (countdown)
+ #endif // BX_FDCACHE_STATS
+#endif // BX_FETCHDECODE_CACHE
#if BX_SIM_ID == 0 // only need to define once
2002-05-30 01:52:36 +04:00
@@ -106,11 +134,13 @@
BX_CPU_C::cpu_loop(Bit32s max_instr_count)
{
unsigned ret;
- BxInstruction_t i;
+ BxInstruction_t bxinstruction_dummy, *i = &bxinstruction_dummy;
unsigned maxisize;
Bit8u *fetch_ptr;
Boolean is_32;
2002-05-30 01:52:36 +04:00
+printf("sizeof(BxInstruction_t) = %i\n", sizeof(BxInstruction_t));
+
#if BX_DEBUGGER
BX_CPU_THIS_PTR break_point = 0;
#ifdef MAGIC_BREAKPOINT
@@ -217,15 +247,67 @@
maxisize = 16;
if (BX_CPU_THIS_PTR bytesleft < 16)
maxisize = BX_CPU_THIS_PTR bytesleft;
- ret = FetchDecode(fetch_ptr, &i, maxisize, is_32);
+
2002-05-30 01:52:36 +04:00
+#if BX_FETCHDECODE_CACHE
+ bx_fdcache_eip = EIP;
+ bx_fdcache_sel = bx_fdcache_eip & BX_FDCACHE_MASK;
+
2002-05-30 01:52:36 +04:00
+ i = &fdcache_i[bx_fdcache_sel];
+
+ // NOTE: I'm not sure this is the correct value to check for (I don't know bochs)
+ // Maybe I should also check for other things?
+ if (fdcache_cs != BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base || fdcache_32 != is_32) {
+ // Clear the EIP values
+ for (int tmp = BX_FDCACHE_SIZE-1; tmp >= 0; --tmp) {
+ fdcache_eip[tmp] = 0xFFFFFFFF; // do NOT fill with 0s!
+ }
2002-05-30 01:52:36 +04:00
+ fdcache_cs = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base;
+ fdcache_32 = is_32;
+ }
2002-05-30 01:52:36 +04:00
+
+ if (fdcache_eip[bx_fdcache_sel] == bx_fdcache_eip) {
+ // HIT! :-)
+ #if BX_FDCACHE_STATS
+ ++bx_fdcache_hit;
+ #endif
+
2002-05-30 01:52:36 +04:00
+ // (debugging stuff)
+ // printf("%8.8x:%8.8x !\n", BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base, EIP);
+
+ ret = 1; // success!
+ } else {
2002-05-30 01:52:36 +04:00
+ // MISS :'(
+ ret = FetchDecode(fetch_ptr, i, maxisize, is_32);
+
2002-05-30 01:52:36 +04:00
+ // (debugging stuff)
+ // printf("%8.8x:%8.8x\n", BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base, EIP);
+
2002-05-30 01:52:36 +04:00
+ // NOTE: I don't know what ret is for. This way is safer, I guess...
+ if (ret) {
2002-05-30 01:52:36 +04:00
+ fdcache_eip[bx_fdcache_sel] = bx_fdcache_eip; // store the computed value
+ } else {
2002-05-30 01:52:36 +04:00
+ fdcache_eip[bx_fdcache_sel] = 0xFFFFFFFF;
+ }
+ }
+
2002-05-30 01:52:36 +04:00
+ #if BX_FDCACHE_STATS
+ if (!--bx_fdcache_acc) {
+ bx_fdcache_acc = BX_FDCACHE_STATS;
+ printf("%6.6x\n", bx_fdcache_hit);
+ bx_fdcache_hit = 0;
+ }
2002-05-30 01:52:36 +04:00
+ #endif // BX_FDCACHE_STATS
+#else // #if BX_FETCHDECODE_CACHE
+ ret = FetchDecode(fetch_ptr, i, maxisize, is_32);
2002-05-30 01:52:36 +04:00
+#endif // BX_FETCHDECODE_CACHE
if (ret) {
- if (i.ResolveModrm) {
+ if (i->ResolveModrm) {
// call method on BX_CPU_C object
- BX_CPU_CALL_METHOD(i.ResolveModrm, (&i));
+ BX_CPU_CALL_METHOD(i->ResolveModrm, (i));
}
- BX_CPU_THIS_PTR fetch_ptr += i.ilen;
- BX_CPU_THIS_PTR bytesleft -= i.ilen;
+ BX_CPU_THIS_PTR fetch_ptr += i->ilen;
+ BX_CPU_THIS_PTR bytesleft -= i->ilen;
fetch_decode_OK:
#if BX_DEBUGGER
2002-05-30 01:52:36 +04:00
@@ -239,34 +321,34 @@
}
#endif
- if (i.rep_used && (i.attr & BxRepeatable)) {
+ if (i->rep_used && (i->attr & BxRepeatable)) {
repeat_loop:
- if (i.attr & BxRepeatableZF) {
- if (i.as_32) {
+ if (i->attr & BxRepeatableZF) {
+ if (i->as_32) {
if (ECX != 0) {
- BX_CPU_CALL_METHOD(i.execute, (&i));
+ BX_CPU_CALL_METHOD(i->execute, (i));
ECX -= 1;
}
- if ((i.rep_used==0xf3) && (get_ZF()==0)) goto repeat_done;
- if ((i.rep_used==0xf2) && (get_ZF()!=0)) goto repeat_done;
+ if ((i->rep_used==0xf3) && (get_ZF()==0)) goto repeat_done;
+ if ((i->rep_used==0xf2) && (get_ZF()!=0)) goto repeat_done;
if (ECX == 0) goto repeat_done;
goto repeat_not_done;
}
else {
if (CX != 0) {
- BX_CPU_CALL_METHOD(i.execute, (&i));
+ BX_CPU_CALL_METHOD(i->execute, (i));
CX -= 1;
}
- if ((i.rep_used==0xf3) && (get_ZF()==0)) goto repeat_done;
- if ((i.rep_used==0xf2) && (get_ZF()!=0)) goto repeat_done;
+ if ((i->rep_used==0xf3) && (get_ZF()==0)) goto repeat_done;
+ if ((i->rep_used==0xf2) && (get_ZF()!=0)) goto repeat_done;
if (CX == 0) goto repeat_done;
goto repeat_not_done;
}
}
else { // normal repeat, no concern for ZF
- if (i.as_32) {
+ if (i->as_32) {
if (ECX != 0) {
- BX_CPU_CALL_METHOD(i.execute, (&i));
+ BX_CPU_CALL_METHOD(i->execute, (i));
ECX -= 1;
}
if (ECX == 0) goto repeat_done;
2002-05-30 01:52:36 +04:00
@@ -274,7 +356,7 @@
}
else { // 16bit addrsize
if (CX != 0) {
- BX_CPU_CALL_METHOD(i.execute, (&i));
+ BX_CPU_CALL_METHOD(i->execute, (i));
CX -= 1;
}
if (CX == 0) goto repeat_done;
2002-05-30 01:52:36 +04:00
@@ -302,12 +384,12 @@
repeat_done:
- BX_CPU_THIS_PTR eip += i.ilen;
+ BX_CPU_THIS_PTR eip += i->ilen;
}
else {
// non repeating instruction
- BX_CPU_THIS_PTR eip += i.ilen;
- BX_CPU_CALL_METHOD(i.execute, (&i));
+ BX_CPU_THIS_PTR eip += i->ilen;
+ BX_CPU_CALL_METHOD(i->execute, (i));
}
BX_CPU_THIS_PTR prev_eip = EIP; // commit new EIP
2002-05-30 01:52:36 +04:00
@@ -410,13 +492,13 @@
for (; j<16; j++) {
FetchBuffer[j] = *temp_ptr++;
}
- ret = FetchDecode(FetchBuffer, &i, 16, is_32);
+ ret = FetchDecode(FetchBuffer, i, 16, is_32);
if (ret==0)
BX_PANIC(("fetchdecode: cross boundary: ret==0"));
- if (i.ResolveModrm) {
- BX_CPU_CALL_METHOD(i.ResolveModrm, (&i));
+ if (i->ResolveModrm) {
+ BX_CPU_CALL_METHOD(i->ResolveModrm, (i));
}
- remain = i.ilen - remain;
+ remain = i->ilen - remain;
// note: eip has already been advanced to beginning of page
BX_CPU_THIS_PTR fetch_ptr = fetch_ptr + remain;