1
// Copyright 2013 Dolphin Emulator Project
2
// Licensed under GPLv2
3
// Refer to the license.txt file included.
6
#include "../HW/Memmap.h"
8
#include "JitCommon/JitBase.h"
9
#include "JitCommon/JitCache.h"
10
#include "JitInterface.h"
15
const u32 plru_mask[8] = {11,11,19,19,37,37,69,69};
16
const u32 plru_value[8] = {11,3,17,1,36,4,64,0};
18
InstructionCache::InstructionCache()
20
for (u32 m = 0; m < 0xff; m++)
23
while (m & (1<<w)) w++;
24
way_from_valid[m] = w;
27
for (u32 m = 0; m < 128; m++)
30
for (int i = 0; i < 7; i++) b[i] = m & (1<<i);
58
void InstructionCache::Reset()
60
memset(valid, 0, sizeof(valid));
61
memset(plru, 0, sizeof(plru));
63
memset(lookup_table, 0xff, sizeof(lookup_table));
64
memset(lookup_table_ex, 0xff, sizeof(lookup_table_ex));
65
memset(lookup_table_vmem, 0xff, sizeof(lookup_table_vmem));
67
JitInterface::ClearSafe();
70
void InstructionCache::Init()
72
memset(data, 0, sizeof(data));
73
memset(tags, 0, sizeof(tags));
74
memset(way_from_valid, 0, sizeof(way_from_valid));
75
memset(way_from_plru, 0, sizeof(way_from_plru));
80
void InstructionCache::Invalidate(u32 addr)
84
// invalidates the whole set
85
u32 set = (addr >> 5) & 0x7f;
87
for (int i = 0; i < 8; i++)
88
if (valid[set] & (1<<i))
90
if (tags[set][i] & (ICACHE_VMEM_BIT >> 12))
91
lookup_table_vmem[((tags[set][i] << 7) | set) & 0xfffff] = 0xff;
92
else if (tags[set][i] & (ICACHE_EXRAM_BIT >> 12))
93
lookup_table_ex[((tags[set][i] << 7) | set) & 0x1fffff] = 0xff;
95
lookup_table[((tags[set][i] << 7) | set) & 0xfffff] = 0xff;
99
JitInterface::InvalidateICache(addr & ~0x1f, 32);
102
u32 InstructionCache::ReadInstruction(u32 addr)
104
if (!HID0.ICE) // instruction cache is disabled
105
return Memory::ReadUnchecked_U32(addr);
106
u32 set = (addr >> 5) & 0x7f;
107
u32 tag = addr >> 12;
110
if (addr & ICACHE_VMEM_BIT)
112
t = lookup_table_vmem[(addr>>5) & 0xfffff];
114
else if (addr & ICACHE_EXRAM_BIT)
116
t = lookup_table_ex[(addr>>5) & 0x1fffff];
120
t = lookup_table[(addr>>5) & 0xfffff];
124
for (u32 i = 0; i < 8; i++)
125
if (tags[set][i] == tag && (valid[set] & (1<<i)))
131
if (t == 0xff) // load to the cache
133
if (HID0.ILOCK) // instruction cache is locked
134
return Memory::ReadUnchecked_U32(addr);
136
if (valid[set] != 0xff)
137
t = way_from_valid[valid[set]];
139
t = way_from_plru[plru[set]];
141
u8 *p = Memory::GetPointer(addr & ~0x1f);
142
memcpy(data[set][t], p, 32);
144
if (valid[set] & (1<<t))
146
if (tags[set][t] & (ICACHE_VMEM_BIT >> 12))
147
lookup_table_vmem[((tags[set][t] << 7) | set) & 0xfffff] = 0xff;
148
else if (tags[set][t] & (ICACHE_EXRAM_BIT >> 12))
149
lookup_table_ex[((tags[set][t] << 7) | set) & 0x1fffff] = 0xff;
151
lookup_table[((tags[set][t] << 7) | set) & 0xfffff] = 0xff;
154
if (addr & ICACHE_VMEM_BIT)
155
lookup_table_vmem[(addr>>5) & 0xfffff] = t;
156
else if (addr & ICACHE_EXRAM_BIT)
157
lookup_table_ex[(addr>>5) & 0x1fffff] = t;
159
lookup_table[(addr>>5) & 0xfffff] = t;
165
plru[set] = (plru[set] & ~plru_mask[t]) | plru_value[t];
166
u32 res = Common::swap32(data[set][t][(addr>>2)&7]);