1 /////////////////////////////////////////////////////////////////////////
2 // $Id: icache.h,v 1.40 2008/10/14 17:23:53 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (c) 2007 Stanislav Shwartsman
6 // Written by Stanislav Shwartsman [sshwarts at sourceforge net]
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 /////////////////////////////////////////////////////////////////////////
29 // bit31: 1=CS is 32/64-bit, 0=CS is 16-bit.
30 // bit30: 1=Long Mode, 0=not Long Mode.
31 // Combination bit31=1 & bit30=1 is invalid (data page)
32 const Bit32u ICacheWriteStampInvalid
= 0xffffffff;
33 const Bit32u ICacheWriteStampStart
= 0x3fffffff;
34 const Bit32u ICacheWriteStampFetchModeMask
= ~ICacheWriteStampStart
;
36 #if BX_SUPPORT_TRACE_CACHE
37 extern void handleSMC(void);
40 class bxPageWriteStampTable
42 // A table (dynamically allocated) to store write-stamp generation IDs.
43 // Each time a write occurs to a physical page, a generation ID is
44 // decremented. Only iCache entries which have write stamps matching
45 // the physical page write stamp are valid.
46 Bit32u
*pageWriteStampTable
;
48 #define PHY_MEM_PAGES (1024*1024)
51 bxPageWriteStampTable() {
52 pageWriteStampTable
= new Bit32u
[PHY_MEM_PAGES
];
55 ~bxPageWriteStampTable() { delete [] pageWriteStampTable
; }
57 BX_CPP_INLINE Bit32u
getPageWriteStamp(bx_phy_address pAddr
) const
59 return pageWriteStampTable
[pAddr
>>12];
62 BX_CPP_INLINE
const Bit32u
*getPageWriteStampPtr(bx_phy_address pAddr
) const
64 return &pageWriteStampTable
[pAddr
>>12];
67 BX_CPP_INLINE
void setPageWriteStamp(bx_phy_address pAddr
, Bit32u pageWriteStamp
)
69 pageWriteStampTable
[pAddr
>>12] = pageWriteStamp
;
72 BX_CPP_INLINE
void decWriteStamp(bx_phy_address pAddr
)
75 #if BX_SUPPORT_TRACE_CACHE
76 if ((pageWriteStampTable
[pAddr
] & ICacheWriteStampFetchModeMask
) != ICacheWriteStampFetchModeMask
)
78 handleSMC(); // one of the CPUs might be running trace from this page
79 // Decrement page write stamp, so iCache entries with older stamps are
80 // effectively invalidated.
81 pageWriteStampTable
[pAddr
]--;
85 BX_DBG_DIRTY_PAGE(pAddr
);
89 BX_CPP_INLINE
void resetWriteStamps(void);
90 BX_CPP_INLINE
void purgeWriteStamps(void);
93 BX_CPP_INLINE
void bxPageWriteStampTable::resetWriteStamps(void)
95 for (Bit32u i
=0; i
<PHY_MEM_PAGES
; i
++) {
96 pageWriteStampTable
[i
] = ICacheWriteStampInvalid
;
100 BX_CPP_INLINE
void bxPageWriteStampTable::purgeWriteStamps(void)
102 for (Bit32u i
=0; i
<PHY_MEM_PAGES
; i
++) {
103 pageWriteStampTable
[i
] |= ICacheWriteStampStart
;
107 extern bxPageWriteStampTable pageWriteStampTable
;
109 #define BxICacheEntries (64 * 1024) // Must be a power of 2.
110 #define BxICacheMemPool (384 * 1024)
112 #if BX_SUPPORT_TRACE_CACHE
113 #define BX_MAX_TRACE_LENGTH 32
116 struct bxICacheEntry_c
118 bx_phy_address pAddr
; // Physical address of the instruction
119 Bit32u writeStamp
; // Generation ID. Each write to a physical page
120 // decrements this value
121 #if BX_SUPPORT_TRACE_CACHE
122 Bit32u ilen
; // Trace length in instructions
125 // ... define as array of 1 to simplify merge with trace cache code
126 bxInstruction_c i
[1];
130 class BOCHSAPI bxICache_c
{
132 bxICacheEntry_c entry
[BxICacheEntries
];
133 #if BX_SUPPORT_TRACE_CACHE
134 bxInstruction_c pool
[BxICacheMemPool
];
139 bxICache_c() { flushICacheEntries(); }
141 BX_CPP_INLINE
unsigned hash(bx_phy_address pAddr
) const
143 // return (pAddr + (pAddr << 2) + (pAddr>>6)) & (BxICacheEntries-1);
144 return (pAddr
) & (BxICacheEntries
-1);
147 #if BX_SUPPORT_TRACE_CACHE
148 BX_CPP_INLINE
void alloc_trace(bxICacheEntry_c
*e
)
150 if (mempool
+ BX_MAX_TRACE_LENGTH
> BxICacheMemPool
) {
151 flushICacheEntries();
153 e
->i
= &pool
[mempool
];
157 BX_CPP_INLINE
void commit_trace(unsigned len
) { mempool
+= len
; }
160 BX_CPP_INLINE
void purgeICacheEntries(void);
161 BX_CPP_INLINE
void flushICacheEntries(void);
163 BX_CPP_INLINE bxICacheEntry_c
* get_entry(bx_phy_address pAddr
)
165 return &(entry
[hash(pAddr
)]);
170 BX_CPP_INLINE
void bxICache_c::flushICacheEntries(void)
172 bxICacheEntry_c
* e
= entry
;
173 for (unsigned i
=0; i
<BxICacheEntries
; i
++, e
++) {
174 e
->writeStamp
= ICacheWriteStampInvalid
;
176 #if BX_SUPPORT_TRACE_CACHE
181 // Since the write stamps may overflow if we always simply decrese them,
182 // this function has to be called often enough that we can reset them.
183 BX_CPP_INLINE
void bxICache_c::purgeICacheEntries(void)
185 flushICacheEntries();
188 extern void purgeICaches(void);
189 extern void flushICaches(void);
191 #endif // BX_SUPPORT_ICACHE