Cached interpreter plays Mario 64. Start looking into RSP as well

This commit is contained in:
2026-05-22 16:46:29 +02:00
parent c9a0307878
commit 4f42a673a3
23 changed files with 1161 additions and 845 deletions
@@ -1310,6 +1310,7 @@ void Cop1::swc1(const Instruction instr) {
regs.cop0.HandleTLBException(addr);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else {
Core::GetInstance().interpreter.EvictCachedBlock(addr);
mem.Write<u32>(physical, FGR_T<u32>(regs.cop0.status, instr.ft()));
}
}
@@ -1337,6 +1338,7 @@ void Cop1::sdc1(const Instruction instr) {
regs.cop0.HandleTLBException(addr);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else {
Core::GetInstance().interpreter.EvictCachedBlock(addr);
mem.Write(physical, FGR_T<u64>(regs.cop0.status, instr.ft()));
}
}
+1 -1
View File
@@ -249,7 +249,7 @@ void Interpreter::cop2Decode(const Instruction instr) {
}
}
void Interpreter::Exec(const Instruction instr) {
void Interpreter::DecodeExecute(const Instruction instr) {
// 00rr_rccc
switch (instr.opcode()) {
case Instruction::SPECIAL:
+25 -17
View File
@@ -140,7 +140,6 @@ void Interpreter::branch(const bool cond, const s64 address) {
regs.delaySlot = true;
if (cond) {
regs.nextPC = address;
Core::MaybeIdleSkip();
}
}
@@ -148,7 +147,6 @@ void Interpreter::branch_likely(const bool cond, const s64 address) {
if (cond) {
regs.delaySlot = true;
regs.nextPC = address;
Core::MaybeIdleSkip();
} else {
regs.SetPC64(regs.nextPC);
}
@@ -202,7 +200,7 @@ void Interpreter::lb(const Instruction instr) {
void Interpreter::lh(const Instruction instr) {
const u64 address = regs.Read<s64>(instr.rs()) + (s16)instr;
if (check_address_error(0b1, address)) {
if (Core::IsAddressError(0b1, address)) {
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return;
@@ -220,7 +218,7 @@ void Interpreter::lh(const Instruction instr) {
void Interpreter::lw(const Instruction instr) {
const s16 offset = instr;
const u64 address = regs.Read<s64>(instr.rs()) + offset;
if (check_address_error(0b11, address)) {
if (Core::IsAddressError(0b11, address)) {
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return;
@@ -243,7 +241,7 @@ void Interpreter::ll(const Instruction instr) {
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC);
} else {
const s32 result = mem.Read<u32>(physical);
if (check_address_error(0b11, address)) {
if (Core::IsAddressError(0b11, address)) {
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return;
}
@@ -287,7 +285,7 @@ void Interpreter::lwr(const Instruction instr) {
void Interpreter::ld(const Instruction instr) {
const s64 address = regs.Read<s64>(instr.rs()) + (s16)instr;
if (check_address_error(0b111, address)) {
if (Core::IsAddressError(0b111, address)) {
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return;
@@ -315,7 +313,7 @@ void Interpreter::lld(const Instruction instr) {
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC);
} else {
if (check_address_error(0b111, address)) {
if (Core::IsAddressError(0b111, address)) {
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
} else {
regs.Write(instr.rt(), mem.Read<u64>(paddr));
@@ -369,7 +367,7 @@ void Interpreter::lbu(const Instruction instr) {
void Interpreter::lhu(const Instruction instr) {
const s64 address = regs.Read<s64>(instr.rs()) + (s16)instr;
if (check_address_error(0b1, address)) {
if (Core::IsAddressError(0b1, address)) {
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return;
@@ -386,7 +384,7 @@ void Interpreter::lhu(const Instruction instr) {
void Interpreter::lwu(const Instruction instr) {
const s64 address = regs.Read<s64>(instr.rs()) + (s16)instr;
if (check_address_error(0b11, address)) {
if (Core::IsAddressError(0b11, address)) {
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
return;
@@ -409,6 +407,7 @@ void Interpreter::sb(const Instruction instr) {
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else {
EvictCachedBlock(address);
mem.Write<u8>(paddr, regs.Read<s64>(instr.rt()));
}
}
@@ -419,7 +418,7 @@ void Interpreter::sc(const Instruction instr) {
if (regs.cop0.llbit) {
regs.cop0.llbit = false;
if (check_address_error(0b11, address)) {
if (Core::IsAddressError(0b11, address)) {
regs.Write(instr.rt(), 0);
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorStore, 0, regs.oldPC);
@@ -432,6 +431,7 @@ void Interpreter::sc(const Instruction instr) {
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else {
EvictCachedBlock(address);
mem.Write<u32>(paddr, regs.Read<s64>(instr.rt()));
regs.Write(instr.rt(), 1);
}
@@ -451,7 +451,7 @@ void Interpreter::scd(const Instruction instr) {
if (regs.cop0.llbit) {
regs.cop0.llbit = false;
if (check_address_error(0b111, address)) {
if (Core::IsAddressError(0b111, address)) {
regs.Write(instr.rt(), 0);
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorStore, 0, regs.oldPC);
@@ -464,6 +464,7 @@ void Interpreter::scd(const Instruction instr) {
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else {
EvictCachedBlock(address);
mem.Write<u32>(paddr, regs.Read<s64>(instr.rt()));
regs.Write(instr.rt(), 1);
}
@@ -480,6 +481,7 @@ void Interpreter::sh(const Instruction instr) {
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else {
EvictCachedBlock(address);
mem.Write<u16>(physical, regs.Read<s64>(instr.rt()));
}
}
@@ -487,7 +489,7 @@ void Interpreter::sh(const Instruction instr) {
void Interpreter::sw(const Instruction instr) {
const s16 offset = instr;
const u64 address = regs.Read<s64>(instr.rs()) + offset;
if (check_address_error(0b11, address)) {
if (Core::IsAddressError(0b11, address)) {
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorStore, 0, regs.oldPC);
return;
@@ -498,13 +500,14 @@ void Interpreter::sw(const Instruction instr) {
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else {
EvictCachedBlock(address);
mem.Write<u32>(physical, regs.Read<s64>(instr.rt()));
}
}
void Interpreter::sd(const Instruction instr) {
const s64 address = regs.Read<s64>(instr.rs()) + (s16)instr;
if (check_address_error(0b111, address)) {
if (Core::IsAddressError(0b111, address)) {
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorStore, 0, regs.oldPC);
return;
@@ -515,6 +518,7 @@ void Interpreter::sd(const Instruction instr) {
regs.cop0.HandleTLBException(address);
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC);
} else {
EvictCachedBlock(address);
mem.Write(physical, regs.Read<s64>(instr.rt()));
}
}
@@ -530,6 +534,7 @@ void Interpreter::sdl(const Instruction instr) {
const u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
const u64 data = mem.Read<u64>(paddr & ~7);
const u64 rt = regs.Read<s64>(instr.rt());
EvictCachedBlock(address);
mem.Write(paddr & ~7, (data & ~mask) | (rt >> shift));
}
}
@@ -545,6 +550,7 @@ void Interpreter::sdr(const Instruction instr) {
const u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
const u64 data = mem.Read<u64>(paddr & ~7);
const u64 rt = regs.Read<s64>(instr.rt());
EvictCachedBlock(address);
mem.Write(paddr & ~7, (data & ~mask) | (rt << shift));
}
}
@@ -560,6 +566,7 @@ void Interpreter::swl(const Instruction instr) {
const u32 mask = 0xFFFFFFFF >> shift;
const u32 data = mem.Read<u32>(paddr & ~3);
const u32 rt = regs.Read<s64>(instr.rt());
EvictCachedBlock(address);
mem.Write<u32>(paddr & ~3, (data & ~mask) | (rt >> shift));
}
}
@@ -575,6 +582,7 @@ void Interpreter::swr(const Instruction instr) {
const u32 mask = 0xFFFFFFFF << shift;
const u32 data = mem.Read<u32>(paddr & ~3);
const u32 rt = regs.Read<s64>(instr.rt());
EvictCachedBlock(address);
mem.Write<u32>(paddr & ~3, (data & ~mask) | (rt << shift));
}
}
@@ -869,12 +877,12 @@ void Interpreter::cache(const Instruction instr) {
panic("Unknown cache type {}", type);
if (type == 0)
return cache_type_instruction(op, vaddr, paddr, ptag);
return CacheTypeInstruction(op, vaddr, paddr, ptag);
return cache_type_data(op, vaddr, paddr, ptag);
return CacheTypeData(op, vaddr, paddr, ptag);
}
void Interpreter::cache_type_instruction(const u8 op, const u64 vaddr, const u32 paddr, const u32 ptag) {
void Interpreter::CacheTypeInstruction(const u8 op, const u64 vaddr, const u32 paddr, const u32 ptag) {
switch (op) {
case 0:
icache.InvalidateIndex(vaddr);
@@ -899,7 +907,7 @@ void Interpreter::cache_type_instruction(const u8 op, const u64 vaddr, const u32
}
}
void Interpreter::cache_type_data(const u8 op, const u64 vaddr, const u32 paddr, const u32 ptag) {
void Interpreter::CacheTypeData(const u8 op, const u64 vaddr, const u32 paddr, const u32 ptag) {
switch (op) {
case 0:
dcache.WriteBack<true>(vaddr, paddr);