- added instructions how to update the online documentation
[bochs-mirror.git] / cpu / icache.cc
blob815f96679afa6b31449193ff4e1c59c831f91c46
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: icache.cc,v 1.20 2008/11/13 22:58:54 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (c) 2007 Stanislav Shwartsman
6 // Written by Stanislav Shwartsman [sshwarts at sourceforge net]
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 /////////////////////////////////////////////////////////////////////////
24 #define NEED_CPU_REG_SHORTCUTS 1
25 #include "bochs.h"
26 #include "cpu.h"
27 #define LOG_THIS BX_CPU_THIS_PTR
29 bx_bool BX_CPU_C::fetchInstruction(bxInstruction_c *iStorage, Bit32u eipBiased)
31 unsigned remainingInPage = BX_CPU_THIS_PTR eipPageWindowSize - eipBiased;
32 const Bit8u *fetchPtr = BX_CPU_THIS_PTR eipFetchPtr + eipBiased;
33 unsigned ret;
35 #if BX_SUPPORT_X86_64
36 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64)
37 ret = fetchDecode64(fetchPtr, iStorage, remainingInPage);
38 else
39 #endif
40 ret = fetchDecode32(fetchPtr, iStorage, remainingInPage);
42 if (ret==0) {
43 // handle instrumentation callback inside boundaryFetch
44 boundaryFetch(fetchPtr, remainingInPage, iStorage);
45 return 0;
48 #if BX_INSTRUMENTATION
49 BX_INSTR_OPCODE(BX_CPU_ID, fetchPtr, iStorage->ilen(),
50 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b, Is64BitMode());
51 #endif
53 return 1;
56 #if BX_SUPPORT_ICACHE
58 bxPageWriteStampTable pageWriteStampTable;
60 void flushICaches(void)
62 for (unsigned i=0; i<BX_SMP_PROCESSORS; i++) {
63 BX_CPU(i)->iCache.flushICacheEntries();
64 BX_CPU(i)->invalidate_prefetch_q();
65 BX_CPU(i)->async_event |= BX_ASYNC_EVENT_STOP_TRACE;
68 pageWriteStampTable.resetWriteStamps();
71 void purgeICaches(void)
73 flushICaches();
76 #if BX_SUPPORT_TRACE_CACHE
78 void handleSMC(void)
80 for (unsigned i=0; i<BX_SMP_PROCESSORS; i++)
81 BX_CPU(i)->async_event |= BX_ASYNC_EVENT_STOP_TRACE;
84 void BX_CPU_C::serveICacheMiss(bxICacheEntry_c *cache_entry, Bit32u eipBiased, bx_phy_address pAddr)
86 BX_CPU_THIS_PTR iCache.alloc_trace(cache_entry);
88 // Cache miss. We weren't so lucky, but let's be optimistic - try to build
89 // trace from incoming instruction bytes stream !
90 cache_entry->pAddr = pAddr;
91 cache_entry->writeStamp = *(BX_CPU_THIS_PTR currPageWriteStampPtr);
93 unsigned remainingInPage = BX_CPU_THIS_PTR eipPageWindowSize - eipBiased;
94 const Bit8u *fetchPtr = BX_CPU_THIS_PTR eipFetchPtr + eipBiased;
95 unsigned ret;
97 bxInstruction_c *i = cache_entry->i;
99 for (unsigned n=0;n<BX_MAX_TRACE_LENGTH;n++)
101 #if BX_SUPPORT_X86_64
102 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64)
103 ret = fetchDecode64(fetchPtr, i, remainingInPage);
104 else
105 #endif
106 ret = fetchDecode32(fetchPtr, i, remainingInPage);
108 if (ret==0) {
109 // Fetching instruction on segment/page boundary
110 if (n > 0) {
111 // The trace is already valid, it has several instructions inside,
112 // in this case just drop the boundary instruction and stop
113 // tracing.
114 break;
116 // First instruction is boundary fetch, leave the trace cache entry
117 // invalid and do not cache the instruction.
118 cache_entry->writeStamp = ICacheWriteStampInvalid;
119 cache_entry->ilen = 1;
120 boundaryFetch(fetchPtr, remainingInPage, i);
121 return;
124 // add instruction to the trace
125 unsigned iLen = i->ilen();
126 cache_entry->ilen++;
128 // continue to the next instruction
129 remainingInPage -= iLen;
130 if (i->getStopTraceAttr() || remainingInPage == 0) break;
131 pAddr += iLen;
132 fetchPtr += iLen;
133 i++;
135 // try to find a trace starting from current pAddr and merge
136 if (mergeTraces(cache_entry, i, pAddr)) break;
139 BX_CPU_THIS_PTR iCache.commit_trace(cache_entry->ilen);
142 bx_bool BX_CPU_C::mergeTraces(bxICacheEntry_c *entry, bxInstruction_c *i, bx_phy_address pAddr)
144 bxICacheEntry_c *e = BX_CPU_THIS_PTR iCache.get_entry(pAddr);
146 if ((e->pAddr == pAddr) && (e->writeStamp == entry->writeStamp))
148 // determine max amount of instruction to take from another entry
149 unsigned max_length = e->ilen;
150 if (max_length + entry->ilen > BX_MAX_TRACE_LENGTH)
151 max_length = BX_MAX_TRACE_LENGTH - entry->ilen;
152 if(max_length == 0) return 0;
154 memcpy(i, e->i, sizeof(bxInstruction_c)*max_length);
155 entry->ilen += max_length;
156 BX_ASSERT(entry->ilen <= BX_MAX_TRACE_LENGTH);
158 return 1;
161 return 0;
164 #else // BX_SUPPORT_TRACE_CACHE == 0
166 void BX_CPU_C::serveICacheMiss(bxICacheEntry_c *cache_entry, Bit32u eipBiased, bx_phy_address pAddr)
168 // The entry will be marked valid if fetchdecode will succeed
169 cache_entry->writeStamp = ICacheWriteStampInvalid;
171 if (fetchInstruction(cache_entry->i, eipBiased)) {
172 cache_entry->pAddr = pAddr;
173 cache_entry->writeStamp = *(BX_CPU_THIS_PTR currPageWriteStampPtr);
177 #endif
179 #endif // BX_SUPPORT_ICACHE