From 79306b851c78f9f0e3eee5b3a2ee1ef93ffd1142 Mon Sep 17 00:00:00 2001 From: Stanislav Shwartsman Date: Thu, 23 Feb 2006 18:23:31 +0000 Subject: [PATCH] Separate fetch/decode instruction block to stand-alone method. The method could be reused when building instruction trace for DT --- bochs/cpu/cpu.cc | 176 +++++++++++++++++++++++++---------------------- bochs/cpu/cpu.h | 7 +- bochs/main.cc | 7 +- 3 files changed, 101 insertions(+), 89 deletions(-) diff --git a/bochs/cpu/cpu.cc b/bochs/cpu/cpu.cc index 0fcde6e1a..f3b016a03 100644 --- a/bochs/cpu/cpu.cc +++ b/bochs/cpu/cpu.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: cpu.cc,v 1.131 2006-02-14 20:03:14 sshwarts Exp $ +// $Id: cpu.cc,v 1.132 2006-02-23 18:23:31 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -122,9 +122,7 @@ static unsigned iCacheMisses=0; void BX_CPU_C::cpu_loop(Bit32s max_instr_count) { - unsigned ret; bxInstruction_c iStorage BX_CPP_AlignN(32); - bxInstruction_c *i = &iStorage; #if BX_DEBUGGER BX_CPU_THIS_PTR break_point = 0; @@ -205,86 +203,8 @@ void BX_CPU_C::cpu_loop(Bit32s max_instr_count) eipBiased = RIP + BX_CPU_THIS_PTR eipPageBias; } -#if BX_SUPPORT_ICACHE - Bit32u 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); - - Bit32u pageWriteStamp = *(BX_CPU_THIS_PTR currPageWriteStampPtr); - -#if BX_SUPPORT_ICACHE - InstrICache_Increment(iCacheLookups); - InstrICache_Stats(); -#endif - - if ((cache_entry->pAddr == pAddr) && - (cache_entry->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 - } - else -#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. :^) - bx_address remainingInPage; - remainingInPage = (BX_CPU_THIS_PTR eipPageWindowSize - eipBiased); - unsigned maxFetch = 15; - if (remainingInPage < 15) maxFetch = remainingInPage; - Bit8u *fetchPtr = BX_CPU_THIS_PTR eipFetchPtr + eipBiased; - -#if BX_SUPPORT_ICACHE - // The entry will be marked valid if fetchdecode will succeed - cache_entry->writeStamp = ICacheWriteStampInvalid; - InstrICache_Increment(iCacheMisses); -#endif - -#if BX_SUPPORT_X86_64 - if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) - ret = fetchDecode64(fetchPtr, i, maxFetch); - else -#endif - ret = fetchDecode(fetchPtr, i, maxFetch); - - if (ret==0) { -#if BX_SUPPORT_ICACHE - i = &iStorage; // Leave entry invalid -#endif - boundaryFetch(fetchPtr, remainingInPage, i); - } - else - { -#if BX_SUPPORT_ICACHE - // In the case where the page is marked ICacheWriteStampInvalid, all - // counter bits will be high, being eqivalent to ICacheWriteStampMax. - // In the case where the page is marked as possibly having associated - // iCache entries, we need to leave the counter as-is, unless we're - // willing to dump all iCache entries which can hash to this page. - // Therefore, in either case, we can keep the counter as-is and - // replace the fetch mode bits. - Bit32u fetchModeMask = BX_CPU_THIS_PTR iCache.fetchModeMask; - pageWriteStamp &= ICacheWriteStampMask; // Clear out old fetch mode bits. - pageWriteStamp |= fetchModeMask; // Add in new ones. - pageWriteStampTable.setPageWriteStamp(pAddr, pageWriteStamp); - 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 - } - } + // fetch and decode next instruction + bxInstruction_c *i = fetchInstruction(&iStorage, eipBiased); bx_address next_RIP = RIP + i->ilen(); if (! Is64BitMode()) { @@ -497,6 +417,93 @@ debugger_check: } // while (1) } +bxInstruction_c* BX_CPU_C::fetchInstruction(bxInstruction_c *iStorage, bx_address eipBiased) +{ + unsigned ret; + bxInstruction_c *i = iStorage; + +#if BX_SUPPORT_ICACHE + 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); + + Bit32u pageWriteStamp = *(BX_CPU_THIS_PTR currPageWriteStampPtr); + + InstrICache_Increment(iCacheLookups); + InstrICache_Stats(); + + if ((cache_entry->pAddr == pAddr) && + (cache_entry->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 + } + else +#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. :^) + bx_address remainingInPage; + remainingInPage = (BX_CPU_THIS_PTR eipPageWindowSize - eipBiased); + unsigned maxFetch = 15; + if (remainingInPage < 15) maxFetch = remainingInPage; + Bit8u *fetchPtr = BX_CPU_THIS_PTR eipFetchPtr + eipBiased; + +#if BX_SUPPORT_ICACHE + // The entry will be marked valid if fetchdecode will succeed + cache_entry->writeStamp = ICacheWriteStampInvalid; + InstrICache_Increment(iCacheMisses); +#endif + +#if BX_SUPPORT_X86_64 + if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) + ret = fetchDecode64(fetchPtr, i, maxFetch); + else +#endif + ret = fetchDecode(fetchPtr, i, maxFetch); + + if (ret==0) { +#if BX_SUPPORT_ICACHE + i = iStorage; // Leave entry invalid +#endif + boundaryFetch(fetchPtr, remainingInPage, i); + } + else + { +#if BX_SUPPORT_ICACHE + // In the case where the page is marked ICacheWriteStampInvalid, all + // counter bits will be high, being eqivalent to ICacheWriteStampMax. + // In the case where the page is marked as possibly having associated + // iCache entries, we need to leave the counter as-is, unless we're + // willing to dump all iCache entries which can hash to this page. + // Therefore, in either case, we can keep the counter as-is and + // replace the fetch mode bits. + Bit32u fetchModeMask = BX_CPU_THIS_PTR iCache.fetchModeMask; + pageWriteStamp &= ICacheWriteStampMask; // Clear out old fetch mode bits. + pageWriteStamp |= fetchModeMask; // Add in new ones. + pageWriteStampTable.setPageWriteStamp(pAddr, pageWriteStamp); + 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 + } + } + + return i; +} + unsigned BX_CPU_C::handleAsyncEvent(void) { // @@ -727,8 +734,9 @@ unsigned BX_CPU_C::handleAsyncEvent(void) void BX_CPU_C::prefetch(void) { + bx_phy_address pAddr; + // prefetch QSIZE byte quantity aligned on corresponding boundary - Bit32u pAddr; bx_address laddrPageOffset0, eipPageOffset0; bx_address temp_rip = RIP; diff --git a/bochs/cpu/cpu.h b/bochs/cpu/cpu.h index 945868b25..5d71b9bad 100644 --- a/bochs/cpu/cpu.h +++ b/bochs/cpu/cpu.h @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: cpu.h,v 1.261 2006-02-17 13:34:30 sshwarts Exp $ +// $Id: cpu.h,v 1.262 2006-02-23 18:23:31 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -1166,8 +1166,8 @@ public: // for now... bx_address eipPageBias; bx_address eipPageWindowSize; Bit8u *eipFetchPtr; - Bit32u pAddrA20Page; // Guest physical address of current instruction - // page with A20() already applied. + bx_phy_address pAddrA20Page; // Guest physical address of current instruction + // page with A20() already applied. #if BX_SUPPORT_ICACHE const Bit32u *currPageWriteStampPtr; #endif @@ -2469,6 +2469,7 @@ public: // for now... #if BX_SUPPORT_X86_64 BX_SMF unsigned fetchDecode64(Bit8u *, bxInstruction_c *, unsigned); #endif + BX_SMF bxInstruction_c* fetchInstruction(bxInstruction_c *, bx_address); BX_SMF void UndefinedOpcode(bxInstruction_c *); BX_SMF void BxError(bxInstruction_c *i); diff --git a/bochs/main.cc b/bochs/main.cc index 4ac3ac6d4..391cb6f8e 100644 --- a/bochs/main.cc +++ b/bochs/main.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: main.cc,v 1.315 2006-02-22 19:18:28 vruppert Exp $ +// $Id: main.cc,v 1.316 2006-02-23 18:23:30 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002 MandrakeSoft S.A. @@ -868,7 +868,10 @@ int bx_init_hardware() BX_INFO((" fpu support: %s",BX_SUPPORT_FPU?"yes":"no")); BX_INFO((" paging support: %s, tlb enabled: %s",BX_SUPPORT_PAGING?"yes":"no",BX_USE_TLB?"yes":"no")); BX_INFO((" mmx support: %s",BX_SUPPORT_MMX?"yes":"no")); - BX_INFO((" sse support: %s",BX_SUPPORT_SSE==2?"2":BX_SUPPORT_SSE==1?"1":"no")); + if (BX_SUPPORT_SSE == 0) + BX_INFO((" sse support: no")); + else + BX_INFO((" sse support: %d",BX_SUPPORT_SSE)); BX_INFO((" v8086 mode support: %s",BX_SUPPORT_V8086_MODE?"yes":"no")); BX_INFO((" VME support: %s",BX_SUPPORT_VME?"yes":"no")); BX_INFO((" 3dnow! support: %s",BX_SUPPORT_3DNOW?"yes":"no"));