maybe we need to use the physical address??
This commit is contained in:
+2
-1
@@ -27,4 +27,5 @@ compile_commands.json
|
|||||||
*.diagsession
|
*.diagsession
|
||||||
tests/
|
tests/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
resources/version.hpp
|
resources/version.hpp
|
||||||
|
__cmake_systeminformation/CMakeFiles/
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ void DataCache::WriteBack<false>(u64 vaddr, u32 paddr) {
|
|||||||
|
|
||||||
u32 origPhysAddr = (line.ptag << 12) | (paddr & 0xfff);
|
u32 origPhysAddr = (line.ptag << 12) | (paddr & 0xfff);
|
||||||
u32 lineStart = GetDCacheLineStart(origPhysAddr);
|
u32 lineStart = GetDCacheLineStart(origPhysAddr);
|
||||||
|
Core::GetInstance().interpreter.EvictCachedBlock(vaddr);
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
mmio.rdp.WriteRDRAM(lineStart + i, line.data[i]);
|
mmio.rdp.WriteRDRAM(lineStart + i, line.data[i]);
|
||||||
}
|
}
|
||||||
@@ -86,6 +87,7 @@ void InstructionCache::WriteBack(u64 vaddr, u32 paddr, u32 ptag) {
|
|||||||
if (line.ptag == ptag && line.valid) {
|
if (line.ptag == ptag && line.valid) {
|
||||||
u32 origPhysAddr = (line.ptag << 12) | (paddr & 0xfff);
|
u32 origPhysAddr = (line.ptag << 12) | (paddr & 0xfff);
|
||||||
u32 lineStart = GetICacheLineStart(origPhysAddr);
|
u32 lineStart = GetICacheLineStart(origPhysAddr);
|
||||||
|
Core::GetInstance().interpreter.EvictCachedBlock(vaddr);
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
mmio.rdp.WriteRDRAM(lineStart + i, line.data[i]);
|
mmio.rdp.WriteRDRAM(lineStart + i, line.data[i]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,26 +96,6 @@ u32 Interpreter::Step() {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CachedLine &CachedState::GetLine(u64 addr) {
|
|
||||||
u32 offset;
|
|
||||||
u32 page = DivideAddr(addr, offset);
|
|
||||||
return blocks[page].lines[offset];
|
|
||||||
}
|
|
||||||
|
|
||||||
void CachedState::InsertLine(u64 addr, const CachedLine &line) {
|
|
||||||
u32 offset;
|
|
||||||
u32 page = DivideAddr(addr, offset);
|
|
||||||
|
|
||||||
blocks[page].lines[offset] = line;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CachedState::EvictLine(u64 addr) {
|
|
||||||
u32 offset;
|
|
||||||
u32 page = DivideAddr(addr, offset);
|
|
||||||
|
|
||||||
blocks[page].lines[offset] = CachedLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 Interpreter::ExecuteCached() {
|
u32 Interpreter::ExecuteCached() {
|
||||||
auto addr = regs.pc;
|
auto addr = regs.pc;
|
||||||
auto blockAddr = addr;
|
auto blockAddr = addr;
|
||||||
@@ -123,46 +103,38 @@ u32 Interpreter::ExecuteCached() {
|
|||||||
auto offset = addr & 0xfff;
|
auto offset = addr & 0xfff;
|
||||||
auto &blocks = cachedState.blocks;
|
auto &blocks = cachedState.blocks;
|
||||||
|
|
||||||
if (page >= blocks.size())
|
if (blocks[page].code.size() >= offset) {
|
||||||
blocks.push_back();
|
|
||||||
|
|
||||||
if (page < blocks.size()) {
|
|
||||||
const auto &block = blocks[page];
|
const auto &block = blocks[page];
|
||||||
if (blocks[page].len > 0) {
|
for (u32 i = 0; i < block.code.size(); i++) {
|
||||||
for (u32 i = 0; i < block.len; i++) {
|
if (!MaybeAdvance())
|
||||||
if (!MaybeAdvance())
|
return i + 1;
|
||||||
return i + 1;
|
|
||||||
|
|
||||||
Instruction instr = block.code[i];
|
Instruction instr = block.code[i];
|
||||||
DecodeExecute(instr);
|
DecodeExecute(instr);
|
||||||
|
|
||||||
// Branch likely with false condition, it wasn't taken so don't execute the delay slot
|
// Branch likely with false condition, it wasn't taken so don't execute the delay slot
|
||||||
if (IsBranchLikely(instr) && !regs.delaySlot)
|
if (IsBranchLikely(instr) && !regs.delaySlot)
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (block.cycles == 0)
|
|
||||||
Scheduler::GetInstance().SkipToNext();
|
|
||||||
|
|
||||||
return block.cycles;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (block.cycles == 0)
|
||||||
|
Scheduler::GetInstance().SkipToNext();
|
||||||
|
|
||||||
|
return block.cycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line.code.size() > 0) {
|
auto &block = blocks[page];
|
||||||
}
|
block.code.resize(MAX_INSTRUCTION_PER_BLOCK);
|
||||||
|
|
||||||
std::vector<Instruction> code;
|
|
||||||
code.resize(MAX_INSTRUCTION_PER_LINE);
|
|
||||||
|
|
||||||
u32 i;
|
u32 i;
|
||||||
bool fetchDelaySlot = false;
|
bool fetchDelaySlot = false;
|
||||||
for (i = 0; i < MAX_INSTRUCTION_PER_LINE; i++) {
|
for (i = 0; i < MAX_INSTRUCTION_PER_BLOCK; i++) {
|
||||||
Instruction instr;
|
Instruction instr;
|
||||||
if (!Fetch(instr, addr))
|
if (!Fetch(instr, addr))
|
||||||
return i + 1;
|
return i + 1;
|
||||||
|
|
||||||
addr += 4;
|
addr += 4;
|
||||||
code[i] = instr;
|
block.code[i] = instr;
|
||||||
|
|
||||||
if (fetchDelaySlot) {
|
if (fetchDelaySlot) {
|
||||||
i++;
|
i++;
|
||||||
@@ -178,7 +150,8 @@ u32 Interpreter::ExecuteCached() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cachedState.InsertLine(blockAddr, {code, i, i});
|
blocks[page].cycles = i;
|
||||||
|
blocks[page].len = i;
|
||||||
|
|
||||||
return ExecuteCached();
|
return ExecuteCached();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,27 +5,25 @@
|
|||||||
namespace n64 {
|
namespace n64 {
|
||||||
struct Core;
|
struct Core;
|
||||||
|
|
||||||
|
static constexpr u32 MAX_BLOCKS = 1 << 20;
|
||||||
static constexpr u32 MAX_INSTRUCTION_PER_BLOCK = 1 << 12;
|
static constexpr u32 MAX_INSTRUCTION_PER_BLOCK = 1 << 12;
|
||||||
|
|
||||||
struct CachedBlock {
|
struct CachedBlock {
|
||||||
std::array<Instruction, MAX_INSTRUCTION_PER_BLOCK> code = {};
|
std::vector<Instruction> code = {};
|
||||||
u32 cycles = 0;
|
|
||||||
u32 len = 0;
|
u32 len = 0;
|
||||||
};
|
u32 cycles = 0;
|
||||||
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
struct CachedState {
|
struct CachedState {
|
||||||
CachedState() {}
|
CachedState() { blocks.resize(MAX_BLOCKS); }
|
||||||
std::vector<CachedBlock> blocks = {};
|
std::vector<CachedBlock> blocks = {};
|
||||||
bool exception = false;
|
bool exception = false;
|
||||||
|
|
||||||
void Reset() {
|
void Reset() {
|
||||||
blocks = {};
|
blocks = {};
|
||||||
|
blocks.resize(MAX_BLOCKS);
|
||||||
exception = false;
|
exception = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CachedLine &GetLine(u64);
|
|
||||||
void InsertLine(u64, const CachedLine &);
|
|
||||||
void EvictLine(u64);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Interpreter final {
|
struct Interpreter final {
|
||||||
@@ -36,6 +34,8 @@ struct Interpreter final {
|
|||||||
bool FetchThenMaybeAdvance(Instruction &);
|
bool FetchThenMaybeAdvance(Instruction &);
|
||||||
bool MaybeAdvance();
|
bool MaybeAdvance();
|
||||||
|
|
||||||
|
void EvictCachedBlock(u64 addr) { cachedState.blocks[(addr >> 12) & 0xfffff] = {}; }
|
||||||
|
|
||||||
void Reset() {
|
void Reset() {
|
||||||
cop2Latch = {};
|
cop2Latch = {};
|
||||||
cachedState.Reset();
|
cachedState.Reset();
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ template <>
|
|||||||
void RDP::WriteRDRAM<u8>(const size_t idx, const u8 v) {
|
void RDP::WriteRDRAM<u8>(const size_t idx, const u8 v) {
|
||||||
if (const size_t real = BYTE_ADDRESS(idx); real < RDRAM_SIZE) [[likely]] {
|
if (const size_t real = BYTE_ADDRESS(idx); real < RDRAM_SIZE) [[likely]] {
|
||||||
rdram[real] = v;
|
rdram[real] = v;
|
||||||
Core::GetInstance().interpreter.cachedState.EvictLine(idx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +26,6 @@ template <>
|
|||||||
void RDP::WriteRDRAM<u16>(const size_t idx, const u16 v) {
|
void RDP::WriteRDRAM<u16>(const size_t idx, const u16 v) {
|
||||||
if (const size_t real = HALF_ADDRESS(idx); real < RDRAM_SIZE) [[likely]] {
|
if (const size_t real = HALF_ADDRESS(idx); real < RDRAM_SIZE) [[likely]] {
|
||||||
ircolib::WriteAccess<u16>(rdram, real, v);
|
ircolib::WriteAccess<u16>(rdram, real, v);
|
||||||
Core::GetInstance().interpreter.cachedState.EvictLine(idx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +33,6 @@ template <>
|
|||||||
void RDP::WriteRDRAM<u32>(const size_t idx, const u32 v) {
|
void RDP::WriteRDRAM<u32>(const size_t idx, const u32 v) {
|
||||||
if (idx < RDRAM_SIZE) [[likely]] {
|
if (idx < RDRAM_SIZE) [[likely]] {
|
||||||
ircolib::WriteAccess<u32>(rdram, idx, v);
|
ircolib::WriteAccess<u32>(rdram, idx, v);
|
||||||
Core::GetInstance().interpreter.cachedState.EvictLine(idx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +40,6 @@ template <>
|
|||||||
void RDP::WriteRDRAM<u64>(const size_t idx, const u64 v) {
|
void RDP::WriteRDRAM<u64>(const size_t idx, const u64 v) {
|
||||||
if (idx < RDRAM_SIZE) [[likely]] {
|
if (idx < RDRAM_SIZE) [[likely]] {
|
||||||
ircolib::WriteAccess<u64>(rdram, idx, v);
|
ircolib::WriteAccess<u64>(rdram, idx, v);
|
||||||
Core::GetInstance().interpreter.cachedState.EvictLine(idx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1310,8 +1310,8 @@ void Cop1::swc1(const Instruction instr) {
|
|||||||
regs.cop0.HandleTLBException(addr);
|
regs.cop0.HandleTLBException(addr);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
} else {
|
} else {
|
||||||
|
Core::GetInstance().interpreter.EvictCachedBlock(addr);
|
||||||
mem.Write<u32>(physical, FGR_T<u32>(regs.cop0.status, instr.ft()));
|
mem.Write<u32>(physical, FGR_T<u32>(regs.cop0.status, instr.ft()));
|
||||||
Core::GetInstance().interpreter.cachedState.EvictLine(addr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1338,8 +1338,8 @@ void Cop1::sdc1(const Instruction instr) {
|
|||||||
regs.cop0.HandleTLBException(addr);
|
regs.cop0.HandleTLBException(addr);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
} else {
|
} else {
|
||||||
|
Core::GetInstance().interpreter.EvictCachedBlock(addr);
|
||||||
mem.Write(physical, FGR_T<u64>(regs.cop0.status, instr.ft()));
|
mem.Write(physical, FGR_T<u64>(regs.cop0.status, instr.ft()));
|
||||||
Core::GetInstance().interpreter.cachedState.EvictLine(addr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -407,7 +407,7 @@ void Interpreter::sb(const Instruction instr) {
|
|||||||
regs.cop0.HandleTLBException(address);
|
regs.cop0.HandleTLBException(address);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
} else {
|
} else {
|
||||||
cachedState.EvictLine(address);
|
EvictCachedBlock(address);
|
||||||
mem.Write<u8>(paddr, regs.Read<s64>(instr.rt()));
|
mem.Write<u8>(paddr, regs.Read<s64>(instr.rt()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -431,7 +431,7 @@ void Interpreter::sc(const Instruction instr) {
|
|||||||
regs.cop0.HandleTLBException(address);
|
regs.cop0.HandleTLBException(address);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
} else {
|
} else {
|
||||||
cachedState.EvictLine(address);
|
EvictCachedBlock(address);
|
||||||
mem.Write<u32>(paddr, regs.Read<s64>(instr.rt()));
|
mem.Write<u32>(paddr, regs.Read<s64>(instr.rt()));
|
||||||
regs.Write(instr.rt(), 1);
|
regs.Write(instr.rt(), 1);
|
||||||
}
|
}
|
||||||
@@ -464,7 +464,7 @@ void Interpreter::scd(const Instruction instr) {
|
|||||||
regs.cop0.HandleTLBException(address);
|
regs.cop0.HandleTLBException(address);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
} else {
|
} else {
|
||||||
cachedState.EvictLine(address);
|
EvictCachedBlock(address);
|
||||||
mem.Write<u32>(paddr, regs.Read<s64>(instr.rt()));
|
mem.Write<u32>(paddr, regs.Read<s64>(instr.rt()));
|
||||||
regs.Write(instr.rt(), 1);
|
regs.Write(instr.rt(), 1);
|
||||||
}
|
}
|
||||||
@@ -481,7 +481,7 @@ void Interpreter::sh(const Instruction instr) {
|
|||||||
regs.cop0.HandleTLBException(address);
|
regs.cop0.HandleTLBException(address);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
} else {
|
} else {
|
||||||
cachedState.EvictLine(address);
|
EvictCachedBlock(address);
|
||||||
mem.Write<u16>(physical, regs.Read<s64>(instr.rt()));
|
mem.Write<u16>(physical, regs.Read<s64>(instr.rt()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -500,7 +500,7 @@ void Interpreter::sw(const Instruction instr) {
|
|||||||
regs.cop0.HandleTLBException(address);
|
regs.cop0.HandleTLBException(address);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
} else {
|
} else {
|
||||||
cachedState.EvictLine(address);
|
EvictCachedBlock(address);
|
||||||
mem.Write<u32>(physical, regs.Read<s64>(instr.rt()));
|
mem.Write<u32>(physical, regs.Read<s64>(instr.rt()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -518,7 +518,7 @@ void Interpreter::sd(const Instruction instr) {
|
|||||||
regs.cop0.HandleTLBException(address);
|
regs.cop0.HandleTLBException(address);
|
||||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
|
||||||
} else {
|
} else {
|
||||||
cachedState.EvictLine(address);
|
EvictCachedBlock(address);
|
||||||
mem.Write(physical, regs.Read<s64>(instr.rt()));
|
mem.Write(physical, regs.Read<s64>(instr.rt()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -534,8 +534,8 @@ void Interpreter::sdl(const Instruction instr) {
|
|||||||
const u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
|
const u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
|
||||||
const u64 data = mem.Read<u64>(paddr & ~7);
|
const u64 data = mem.Read<u64>(paddr & ~7);
|
||||||
const u64 rt = regs.Read<s64>(instr.rt());
|
const u64 rt = regs.Read<s64>(instr.rt());
|
||||||
|
EvictCachedBlock(address);
|
||||||
mem.Write(paddr & ~7, (data & ~mask) | (rt >> shift));
|
mem.Write(paddr & ~7, (data & ~mask) | (rt >> shift));
|
||||||
cachedState.EvictLine(address);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,8 +550,8 @@ void Interpreter::sdr(const Instruction instr) {
|
|||||||
const u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
|
const u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
|
||||||
const u64 data = mem.Read<u64>(paddr & ~7);
|
const u64 data = mem.Read<u64>(paddr & ~7);
|
||||||
const u64 rt = regs.Read<s64>(instr.rt());
|
const u64 rt = regs.Read<s64>(instr.rt());
|
||||||
|
EvictCachedBlock(address);
|
||||||
mem.Write(paddr & ~7, (data & ~mask) | (rt << shift));
|
mem.Write(paddr & ~7, (data & ~mask) | (rt << shift));
|
||||||
cachedState.EvictLine(address);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,8 +566,8 @@ void Interpreter::swl(const Instruction instr) {
|
|||||||
const u32 mask = 0xFFFFFFFF >> shift;
|
const u32 mask = 0xFFFFFFFF >> shift;
|
||||||
const u32 data = mem.Read<u32>(paddr & ~3);
|
const u32 data = mem.Read<u32>(paddr & ~3);
|
||||||
const u32 rt = regs.Read<s64>(instr.rt());
|
const u32 rt = regs.Read<s64>(instr.rt());
|
||||||
|
EvictCachedBlock(address);
|
||||||
mem.Write<u32>(paddr & ~3, (data & ~mask) | (rt >> shift));
|
mem.Write<u32>(paddr & ~3, (data & ~mask) | (rt >> shift));
|
||||||
cachedState.EvictLine(address);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,8 +582,8 @@ void Interpreter::swr(const Instruction instr) {
|
|||||||
const u32 mask = 0xFFFFFFFF << shift;
|
const u32 mask = 0xFFFFFFFF << shift;
|
||||||
const u32 data = mem.Read<u32>(paddr & ~3);
|
const u32 data = mem.Read<u32>(paddr & ~3);
|
||||||
const u32 rt = regs.Read<s64>(instr.rt());
|
const u32 rt = regs.Read<s64>(instr.rt());
|
||||||
|
EvictCachedBlock(address);
|
||||||
mem.Write<u32>(paddr & ~3, (data & ~mask) | (rt << shift));
|
mem.Write<u32>(paddr & ~3, (data & ~mask) | (rt << shift));
|
||||||
cachedState.EvictLine(address);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user