Check in FETCHDECODE Caching, with changes.

Specific changes from the patch:

1.) renamed fdcache_eip to fdcache_ip, as it is using
the RIP instead of the EIP.

2.) added a Boolean array fdcache_is32 which uses is32
to determine icache hits.  Otherwise we could run 32-bit
code as 16-bit or vice versa.


 Modified Files:
 	config.h.in cpu/cpu.cc cpu/cpu.h memory/memory.cc
This commit is contained in:
Gregory Alexander 2002-06-03 22:39:11 +00:00
parent 75247ef0a4
commit fda1b874e9
4 changed files with 117 additions and 29 deletions

View File

@ -546,6 +546,15 @@ typedef unsigned int Boolean;
#define BX_DYNAMIC_CPU_I386 0 #define BX_DYNAMIC_CPU_I386 0
#define BX_DYNAMIC_CPU_SPARC 0 #define BX_DYNAMIC_CPU_SPARC 0
// caching of fetchdecode() calls
#define BX_FETCHDECODE_CACHE 0
#if BX_FETCHDECODE_CACHE
// The number of entries. MUST be a power of 2
#define BX_FDCACHE_SIZE 0x0800
#define BX_FDCACHE_MASK (BX_FDCACHE_SIZE-1)
#endif // BX_FETCHDECODE_CACHE
#define BX_SUPPORT_FPU 0 #define BX_SUPPORT_FPU 0
#define BX_HAVE_GETENV 0 #define BX_HAVE_GETENV 0

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: cpu.cc,v 1.28 2002-04-18 00:22:19 bdenney Exp $ // $Id: cpu.cc,v 1.29 2002-06-03 22:39:10 yakovlev Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001 MandrakeSoft S.A. // Copyright (C) 2001 MandrakeSoft S.A.
@ -37,7 +37,12 @@
//unsigned counter[2] = { 0, 0 }; //unsigned counter[2] = { 0, 0 };
#if BX_FETCHDECODE_CACHE
static unsigned long bx_fdcache_sel;
static unsigned long bx_fdcache_ip;
static Bit32u new_phy_addr;
#endif // BX_FETCHDECODE_CACHE
#if BX_SIM_ID == 0 // only need to define once #if BX_SIM_ID == 0 // only need to define once
// This array defines a look-up table for the even parity-ness // This array defines a look-up table for the even parity-ness
@ -106,11 +111,16 @@ extern void REGISTER_IADDR(Bit32u addr);
BX_CPU_C::cpu_loop(Bit32s max_instr_count) BX_CPU_C::cpu_loop(Bit32s max_instr_count)
{ {
unsigned ret; unsigned ret;
BxInstruction_t i; BxInstruction_t *i;
unsigned maxisize; unsigned maxisize;
Bit8u *fetch_ptr; Bit8u *fetch_ptr;
Boolean is_32; Boolean is_32;
#if !BX_FETCHDECODE_CACHE
BxInstruction_t bxinstruction_dummy;
i = &bxinstruction_dummy;
#endif // #if BX_FETCHDECODE_CACHE
#if BX_DEBUGGER #if BX_DEBUGGER
BX_CPU_THIS_PTR break_point = 0; BX_CPU_THIS_PTR break_point = 0;
#ifdef MAGIC_BREAKPOINT #ifdef MAGIC_BREAKPOINT
@ -214,18 +224,49 @@ async_events_processed:
} }
fetch_ptr = BX_CPU_THIS_PTR fetch_ptr; fetch_ptr = BX_CPU_THIS_PTR fetch_ptr;
#if BX_FETCHDECODE_CACHE
bx_fdcache_ip = new_phy_addr;
bx_fdcache_sel = bx_fdcache_ip & BX_FDCACHE_MASK;
i = &(BX_CPU_THIS_PTR fdcache_i[bx_fdcache_sel]);
if ((BX_CPU_THIS_PTR fdcache_ip[bx_fdcache_sel] == bx_fdcache_ip) &&
(BX_CPU_THIS_PTR fdcache_is32[bx_fdcache_sel] == is_32)) {
// HIT! ;^)
ret = 1; // success!
new_phy_addr += i->ilen;
} else {
// MISS :'(
#endif // #if BX_FETCHDECODE_CACHE
maxisize = 16; maxisize = 16;
if (BX_CPU_THIS_PTR bytesleft < 16) if (BX_CPU_THIS_PTR bytesleft < 16) {
maxisize = BX_CPU_THIS_PTR bytesleft; maxisize = BX_CPU_THIS_PTR bytesleft;
ret = FetchDecode(fetch_ptr, &i, maxisize, is_32); }
ret = FetchDecode(fetch_ptr, i, maxisize, is_32);
#if BX_FETCHDECODE_CACHE
// The instruction straddles a page boundary.
// Not storing such instructions in the cache is probably the
// easiest way to handle them
if (ret) {
BX_CPU_THIS_PTR fdcache_ip[bx_fdcache_sel] = bx_fdcache_ip;
BX_CPU_THIS_PTR fdcache_is32[bx_fdcache_sel] = is_32;
new_phy_addr += i->ilen;
} else {
// Invalidate cache!
BX_CPU_THIS_PTR fdcache_ip[bx_fdcache_sel] = 0xFFFFFFFF;
}
}
#endif // #if BX_FETCHDECODE_CACHE
if (ret) { if (ret) {
if (i.ResolveModrm) { if (i->ResolveModrm) {
// call method on BX_CPU_C object // 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 fetch_ptr += i->ilen;
BX_CPU_THIS_PTR bytesleft -= i.ilen; BX_CPU_THIS_PTR bytesleft -= i->ilen;
fetch_decode_OK: fetch_decode_OK:
#if BX_DEBUGGER #if BX_DEBUGGER
@ -239,34 +280,34 @@ fetch_decode_OK:
} }
#endif #endif
if (i.rep_used && (i.attr & BxRepeatable)) { if (i->rep_used && (i->attr & BxRepeatable)) {
repeat_loop: repeat_loop:
if (i.attr & BxRepeatableZF) { if (i->attr & BxRepeatableZF) {
if (i.as_32) { if (i->as_32) {
if (ECX != 0) { if (ECX != 0) {
BX_CPU_CALL_METHOD(i.execute, (&i)); BX_CPU_CALL_METHOD(i->execute, (i));
ECX -= 1; ECX -= 1;
} }
if ((i.rep_used==0xf3) && (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 ((i->rep_used==0xf2) && (get_ZF()!=0)) goto repeat_done;
if (ECX == 0) goto repeat_done; if (ECX == 0) goto repeat_done;
goto repeat_not_done; goto repeat_not_done;
} }
else { else {
if (CX != 0) { if (CX != 0) {
BX_CPU_CALL_METHOD(i.execute, (&i)); BX_CPU_CALL_METHOD(i->execute, (i));
CX -= 1; CX -= 1;
} }
if ((i.rep_used==0xf3) && (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 ((i->rep_used==0xf2) && (get_ZF()!=0)) goto repeat_done;
if (CX == 0) goto repeat_done; if (CX == 0) goto repeat_done;
goto repeat_not_done; goto repeat_not_done;
} }
} }
else { // normal repeat, no concern for ZF else { // normal repeat, no concern for ZF
if (i.as_32) { if (i->as_32) {
if (ECX != 0) { if (ECX != 0) {
BX_CPU_CALL_METHOD(i.execute, (&i)); BX_CPU_CALL_METHOD(i->execute, (i));
ECX -= 1; ECX -= 1;
} }
if (ECX == 0) goto repeat_done; if (ECX == 0) goto repeat_done;
@ -274,7 +315,7 @@ repeat_loop:
} }
else { // 16bit addrsize else { // 16bit addrsize
if (CX != 0) { if (CX != 0) {
BX_CPU_CALL_METHOD(i.execute, (&i)); BX_CPU_CALL_METHOD(i->execute, (i));
CX -= 1; CX -= 1;
} }
if (CX == 0) goto repeat_done; if (CX == 0) goto repeat_done;
@ -302,12 +343,12 @@ repeat_not_done:
repeat_done: repeat_done:
BX_CPU_THIS_PTR eip += i.ilen; BX_CPU_THIS_PTR eip += i->ilen;
} }
else { else {
// non repeating instruction // non repeating instruction
BX_CPU_THIS_PTR eip += i.ilen; BX_CPU_THIS_PTR eip += i->ilen;
BX_CPU_CALL_METHOD(i.execute, (&i)); BX_CPU_CALL_METHOD(i->execute, (i));
} }
BX_CPU_THIS_PTR prev_eip = EIP; // commit new EIP BX_CPU_THIS_PTR prev_eip = EIP; // commit new EIP
@ -410,17 +451,22 @@ static Bit8u FetchBuffer[16];
for (; j<16; j++) { for (; j<16; j++) {
FetchBuffer[j] = *temp_ptr++; FetchBuffer[j] = *temp_ptr++;
} }
ret = FetchDecode(FetchBuffer, &i, 16, is_32); ret = FetchDecode(FetchBuffer, i, 16, is_32);
if (ret==0) if (ret==0)
BX_PANIC(("fetchdecode: cross boundary: ret==0")); BX_PANIC(("fetchdecode: cross boundary: ret==0"));
if (i.ResolveModrm) { if (i->ResolveModrm) {
BX_CPU_CALL_METHOD(i.ResolveModrm, (&i)); 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 // note: eip has already been advanced to beginning of page
BX_CPU_THIS_PTR fetch_ptr = fetch_ptr + remain; BX_CPU_THIS_PTR fetch_ptr = fetch_ptr + remain;
BX_CPU_THIS_PTR bytesleft -= remain; BX_CPU_THIS_PTR bytesleft -= remain;
#if BX_FETCHDECODE_CACHE
new_phy_addr += remain;
#endif // BX_FETCHDECODE_CACHE
//BX_CPU_THIS_PTR eip += remain; //BX_CPU_THIS_PTR eip += remain;
BX_CPU_THIS_PTR eip = BX_CPU_THIS_PTR prev_eip; BX_CPU_THIS_PTR eip = BX_CPU_THIS_PTR prev_eip;
goto fetch_decode_OK; goto fetch_decode_OK;
@ -603,7 +649,9 @@ BX_CPU_C::prefetch(void)
// cs:eIP // cs:eIP
// prefetch QSIZE byte quantity aligned on corresponding boundary // prefetch QSIZE byte quantity aligned on corresponding boundary
Bit32u new_linear_addr; Bit32u new_linear_addr;
#if !BX_FETCHDECODE_CACHE
Bit32u new_phy_addr; Bit32u new_phy_addr;
#endif // !BX_FETCHDECODE_CACHE
Bit32u temp_eip, temp_limit; Bit32u temp_eip, temp_limit;
temp_eip = BX_CPU_THIS_PTR eip; temp_eip = BX_CPU_THIS_PTR eip;
@ -664,7 +712,9 @@ BX_CPU_C::prefetch(void)
BX_CPU_C::revalidate_prefetch_q(void) BX_CPU_C::revalidate_prefetch_q(void)
{ {
Bit32u new_linear_addr, new_linear_page, new_linear_offset; Bit32u new_linear_addr, new_linear_page, new_linear_offset;
#if !BX_FETCHDECODE_CACHE
Bit32u new_phy_addr; Bit32u new_phy_addr;
#endif // !BX_FETCHDECODE_CACHE
new_linear_addr = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base + BX_CPU_THIS_PTR eip; new_linear_addr = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base + BX_CPU_THIS_PTR eip;

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.19 2002-04-18 00:22:19 bdenney Exp $ // $Id: cpu.h,v 1.20 2002-06-03 22:39:10 yakovlev Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001 MandrakeSoft S.A. // Copyright (C) 2001 MandrakeSoft S.A.
@ -1582,6 +1582,14 @@ public: // for now...
bx_local_apic_c local_apic; bx_local_apic_c local_apic;
Boolean int_from_local_apic; Boolean int_from_local_apic;
#endif #endif
#if BX_FETCHDECODE_CACHE
Bit32u fdcache_ip[BX_FDCACHE_SIZE]; // will store operation's IP
// NOTE: This struct should really be aligned!
BxInstruction_t fdcache_i[BX_FDCACHE_SIZE]; // stores decoded instruction
Boolean fdcache_is32[BX_FDCACHE_SIZE];
#endif // #if BX_FETCHDECODE_CACHE
}; };

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: memory.cc,v 1.11 2002-04-03 16:48:15 japj Exp $ // $Id: memory.cc,v 1.12 2002-06-03 22:39:11 yakovlev Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001 MandrakeSoft S.A. // Copyright (C) 2001 MandrakeSoft S.A.
@ -49,6 +49,27 @@ BX_MEM_C::write_physical(BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data)
a20addr = A20ADDR(addr); a20addr = A20ADDR(addr);
BX_INSTR_PHY_WRITE(a20addr, len); BX_INSTR_PHY_WRITE(a20addr, len);
#if BX_FETCHDECODE_CACHE
// NOTE: This piece should be put, if possible, where a write to the memory
// takes place.
// Here it trashes cache even for writes that would end up to ROM
// Invalidate instruction cache for written addresses
// Instructions can be up to 16 bytes long, so I have to trash up to 15 bytes
// before write address (costly!)
// I think it would NOT be safe to invalidate up to the last instruction
// before the write because there COULD be programs which use
// jump-in-the-middle-of-an-instruction schemes (esp. copyprotection
// schemes)
unsigned long bx_fdcache_idx = addr - 15;
for (int count = 15+len; count > 0; --count) {
if (cpu->fdcache_ip[bx_fdcache_idx & BX_FDCACHE_MASK] == bx_fdcache_idx) {
cpu->fdcache_ip[bx_fdcache_idx & BX_FDCACHE_MASK] = 0xFFFFFFFF;
}
++bx_fdcache_idx;
}
#endif // #if BX_FETCHDECODE_CACHE
#if BX_DEBUGGER #if BX_DEBUGGER
// (mch) Check for physical write break points, TODO // (mch) Check for physical write break points, TODO
// (bbd) Each breakpoint should have an associated CPU#, TODO // (bbd) Each breakpoint should have an associated CPU#, TODO