Cache instructions implemented but broken lmao. Commented out for now
This commit is contained in:
@@ -4,90 +4,90 @@
|
||||
|
||||
namespace n64 {
|
||||
void Cop0::mtc0(const Instruction instr) {
|
||||
Registers& regs = Core::GetRegs();
|
||||
SetReg32(instr.rd(), regs.Read<u32>(instr.rt()));
|
||||
Registers ®s = Core::GetRegs();
|
||||
SetReg32(instr.rd(), regs.Read<u32>(instr.rt()));
|
||||
}
|
||||
|
||||
void Cop0::dmtc0(const Instruction instr) {
|
||||
Registers& regs = Core::GetRegs();
|
||||
SetReg64(instr.rd(), regs.Read<u64>(instr.rt()));
|
||||
void Cop0::dmtc0(const Instruction instr) {
|
||||
Registers ®s = Core::GetRegs();
|
||||
SetReg64(instr.rd(), regs.Read<u64>(instr.rt()));
|
||||
}
|
||||
|
||||
void Cop0::mfc0(const Instruction instr) {
|
||||
Registers& regs = Core::GetRegs();
|
||||
regs.Write(instr.rt(), s32(GetReg32(instr.rd())));
|
||||
void Cop0::mfc0(const Instruction instr) {
|
||||
Registers ®s = Core::GetRegs();
|
||||
regs.Write(instr.rt(), s32(GetReg32(instr.rd())));
|
||||
}
|
||||
|
||||
void Cop0::dmfc0(const Instruction instr) const {
|
||||
Registers& regs = Core::GetRegs();
|
||||
regs.Write(instr.rt(), s64(GetReg64(instr.rd())));
|
||||
void Cop0::dmfc0(const Instruction instr) const {
|
||||
Registers ®s = Core::GetRegs();
|
||||
regs.Write(instr.rt(), s64(GetReg64(instr.rd())));
|
||||
}
|
||||
|
||||
void Cop0::eret() {
|
||||
Registers& regs = Core::GetRegs();
|
||||
if (!regs.cop0.kernelMode) {
|
||||
FireException(ExceptionCode::CoprocessorUnusable, 0, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
if (status.erl) {
|
||||
regs.SetPC64(ErrorEPC);
|
||||
status.erl = false;
|
||||
} else {
|
||||
regs.SetPC64(EPC);
|
||||
status.exl = false;
|
||||
}
|
||||
regs.cop0.Update();
|
||||
llbit = false;
|
||||
Registers ®s = Core::GetRegs();
|
||||
if (!regs.cop0.kernelMode) {
|
||||
FireException(Cop0::ExceptionCode::CoprocessorUnusable, 0, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
if (status.erl) {
|
||||
regs.SetPC64(ErrorEPC);
|
||||
status.erl = false;
|
||||
} else {
|
||||
regs.SetPC64(EPC);
|
||||
status.exl = false;
|
||||
}
|
||||
regs.cop0.Update();
|
||||
llbit = false;
|
||||
}
|
||||
|
||||
|
||||
void Cop0::tlbr() {
|
||||
if (index.i >= 32) {
|
||||
panic("TLBR with TLB index {}", index.i);
|
||||
}
|
||||
if (index.i >= 32) {
|
||||
panic("TLBR with TLB index {}", index.i);
|
||||
}
|
||||
|
||||
const TLBEntry entry = tlb[index.i];
|
||||
const TLBEntry entry = tlb[index.i];
|
||||
|
||||
entryHi.raw = entry.entryHi.raw;
|
||||
entryLo0.raw = entry.entryLo0.raw & 0x3FFFFFFF;
|
||||
entryLo1.raw = entry.entryLo1.raw & 0x3FFFFFFF;
|
||||
entryHi.raw = entry.entryHi.raw;
|
||||
entryLo0.raw = entry.entryLo0.raw & 0x3FFFFFFF;
|
||||
entryLo1.raw = entry.entryLo1.raw & 0x3FFFFFFF;
|
||||
|
||||
entryLo0.g = entry.global;
|
||||
entryLo1.g = entry.global;
|
||||
pageMask.raw = entry.pageMask.raw;
|
||||
entryLo0.g = entry.global;
|
||||
entryLo1.g = entry.global;
|
||||
pageMask.raw = entry.pageMask.raw;
|
||||
}
|
||||
|
||||
void Cop0::tlbw(const int index_) {
|
||||
PageMask page_mask{};
|
||||
page_mask = pageMask;
|
||||
const u32 top = page_mask.mask & 0xAAA;
|
||||
page_mask.mask = top | (top >> 1);
|
||||
PageMask page_mask{};
|
||||
page_mask = pageMask;
|
||||
const u32 top = page_mask.mask & 0xAAA;
|
||||
page_mask.mask = top | (top >> 1);
|
||||
|
||||
if (index_ >= 32) {
|
||||
panic("TLBWI with TLB index {}", index_);
|
||||
}
|
||||
if (index_ >= 32) {
|
||||
panic("TLBWI with TLB index {}", index_);
|
||||
}
|
||||
|
||||
tlb[index_].entryHi.raw = entryHi.raw;
|
||||
tlb[index_].entryHi.vpn2 &= ~page_mask.mask;
|
||||
tlb[index_].entryHi.raw = entryHi.raw;
|
||||
tlb[index_].entryHi.vpn2 &= ~page_mask.mask;
|
||||
|
||||
tlb[index_].entryLo0.raw = entryLo0.raw & 0x03FFFFFE;
|
||||
tlb[index_].entryLo1.raw = entryLo1.raw & 0x03FFFFFE;
|
||||
tlb[index_].pageMask.raw = page_mask.raw;
|
||||
tlb[index_].entryLo0.raw = entryLo0.raw & 0x03FFFFFE;
|
||||
tlb[index_].entryLo1.raw = entryLo1.raw & 0x03FFFFFE;
|
||||
tlb[index_].pageMask.raw = page_mask.raw;
|
||||
|
||||
tlb[index_].global = entryLo0.g && entryLo1.g;
|
||||
tlb[index_].initialized = true;
|
||||
tlb[index_].global = entryLo0.g && entryLo1.g;
|
||||
tlb[index_].initialized = true;
|
||||
}
|
||||
|
||||
void Cop0::tlbp() {
|
||||
int match = -1;
|
||||
const TLBEntry *entry = TLBTryMatch(entryHi.raw, match);
|
||||
if (match >= 0) {
|
||||
index.raw = match;
|
||||
return;
|
||||
}
|
||||
int match = -1;
|
||||
const TLBEntry *entry = TLBTryMatch(entryHi.raw, match);
|
||||
if (match >= 0) {
|
||||
index.raw = match;
|
||||
return;
|
||||
}
|
||||
|
||||
index.raw = 0;
|
||||
index.p = 1;
|
||||
index.raw = 0;
|
||||
index.p = 1;
|
||||
}
|
||||
|
||||
} // namespace n64
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -33,10 +33,10 @@ void Interpreter::special(const Instruction instr) {
|
||||
jalr(instr);
|
||||
break;
|
||||
case Instruction::SYSCALL:
|
||||
regs.cop0.FireException(ExceptionCode::Syscall, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::Syscall, 0, regs.oldPC);
|
||||
break;
|
||||
case Instruction::BREAK:
|
||||
regs.cop0.FireException(ExceptionCode::Breakpoint, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::Breakpoint, 0, regs.oldPC);
|
||||
break;
|
||||
case Instruction::SYNC:
|
||||
break; // SYNC
|
||||
@@ -222,7 +222,7 @@ void Interpreter::regimm(const Instruction instr) {
|
||||
|
||||
void Interpreter::cop2Decode(const Instruction instr) {
|
||||
if (!regs.cop0.status.cu2) {
|
||||
regs.cop0.FireException(ExceptionCode::CoprocessorUnusable, 2, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::CoprocessorUnusable, 2, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
switch (instr.rs()) {
|
||||
@@ -245,7 +245,7 @@ void Interpreter::cop2Decode(const Instruction instr) {
|
||||
ctc2(instr);
|
||||
break;
|
||||
default:
|
||||
regs.cop0.FireException(ExceptionCode::ReservedInstruction, 2, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::ReservedInstruction, 2, regs.oldPC);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,7 +361,7 @@ void Interpreter::Exec(const Instruction instr) {
|
||||
ldr(instr);
|
||||
break;
|
||||
case 0x1F:
|
||||
regs.cop0.FireException(ExceptionCode::ReservedInstruction, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::ReservedInstruction, 0, regs.oldPC);
|
||||
break;
|
||||
case Instruction::LB:
|
||||
lb(instr);
|
||||
@@ -409,10 +409,7 @@ void Interpreter::Exec(const Instruction instr) {
|
||||
swr(instr);
|
||||
break;
|
||||
case Instruction::CACHE:
|
||||
{
|
||||
panic("CACHE 0b{:05b}, 0x{:04X}({}/r{} = 0x{:08X})", instr.op(), instr.offset(),
|
||||
Registers::regNames[instr.base()], instr.base(), regs.Read<u64>(instr.base()));
|
||||
}
|
||||
// cache(instr);
|
||||
break;
|
||||
case Instruction::LL:
|
||||
ll(instr);
|
||||
|
||||
@@ -8,7 +8,7 @@ void Interpreter::add(const Instruction instr) {
|
||||
const u32 rs = regs.Read<s32>(instr.rs());
|
||||
const u32 rt = regs.Read<s32>(instr.rt());
|
||||
if (const u32 result = rs + rt; check_signed_overflow(rs, rt, result)) {
|
||||
regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::Overflow, 0, regs.oldPC);
|
||||
} else {
|
||||
regs.Write(instr.rd(), static_cast<s32>(result));
|
||||
}
|
||||
@@ -25,7 +25,7 @@ void Interpreter::addi(const Instruction instr) {
|
||||
const u32 rs = regs.Read<s64>(instr.rs());
|
||||
const u32 imm = static_cast<s32>(static_cast<s16>(instr));
|
||||
if (const u32 result = rs + imm; check_signed_overflow(rs, imm, result)) {
|
||||
regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::Overflow, 0, regs.oldPC);
|
||||
} else {
|
||||
regs.Write(instr.rt(), static_cast<s32>(result));
|
||||
}
|
||||
@@ -42,7 +42,7 @@ void Interpreter::dadd(const Instruction instr) {
|
||||
const u64 rs = regs.Read<s64>(instr.rs());
|
||||
const u64 rt = regs.Read<s64>(instr.rt());
|
||||
if (const u64 result = rt + rs; check_signed_overflow(rs, rt, result)) {
|
||||
regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::Overflow, 0, regs.oldPC);
|
||||
} else {
|
||||
regs.Write(instr.rd(), result);
|
||||
}
|
||||
@@ -58,7 +58,7 @@ void Interpreter::daddi(const Instruction instr) {
|
||||
const u64 imm = s64(s16(instr));
|
||||
const u64 rs = regs.Read<s64>(instr.rs());
|
||||
if (const u64 result = imm + rs; check_signed_overflow(rs, imm, result)) {
|
||||
regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::Overflow, 0, regs.oldPC);
|
||||
} else {
|
||||
regs.Write(instr.rt(), result);
|
||||
}
|
||||
@@ -202,7 +202,7 @@ void Interpreter::lh(const Instruction instr) {
|
||||
const u64 address = regs.Read<s64>(instr.rs()) + (s16)instr;
|
||||
if (check_address_error(0b1, address)) {
|
||||
regs.cop0.HandleTLBException(address);
|
||||
regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ void Interpreter::lw(const Instruction instr) {
|
||||
const u64 address = regs.Read<s64>(instr.rs()) + offset;
|
||||
if (check_address_error(0b11, address)) {
|
||||
regs.cop0.HandleTLBException(address);
|
||||
regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ void Interpreter::ll(const Instruction instr) {
|
||||
} else {
|
||||
const s32 result = mem.Read<u32>(physical);
|
||||
if (check_address_error(0b11, address)) {
|
||||
regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ void Interpreter::ld(const Instruction instr) {
|
||||
const s64 address = regs.Read<s64>(instr.rs()) + (s16)instr;
|
||||
if (check_address_error(0b111, address)) {
|
||||
regs.cop0.HandleTLBException(address);
|
||||
regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ void Interpreter::ld(const Instruction instr) {
|
||||
|
||||
void Interpreter::lld(const Instruction instr) {
|
||||
if (!regs.cop0.is64BitAddressing && !regs.cop0.kernelMode) {
|
||||
regs.cop0.FireException(ExceptionCode::ReservedInstruction, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::ReservedInstruction, 0, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ void Interpreter::lld(const Instruction instr) {
|
||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC);
|
||||
} else {
|
||||
if (check_address_error(0b111, address)) {
|
||||
regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||
} else {
|
||||
regs.Write(instr.rt(), mem.Read<u64>(paddr));
|
||||
regs.cop0.llbit = true;
|
||||
@@ -369,7 +369,7 @@ void Interpreter::lhu(const Instruction instr) {
|
||||
const s64 address = regs.Read<s64>(instr.rs()) + (s16)instr;
|
||||
if (check_address_error(0b1, address)) {
|
||||
regs.cop0.HandleTLBException(address);
|
||||
regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
u32 paddr;
|
||||
@@ -386,7 +386,7 @@ void Interpreter::lwu(const Instruction instr) {
|
||||
const s64 address = regs.Read<s64>(instr.rs()) + (s16)instr;
|
||||
if (check_address_error(0b11, address)) {
|
||||
regs.cop0.HandleTLBException(address);
|
||||
regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -420,7 +420,7 @@ void Interpreter::sc(const Instruction instr) {
|
||||
if (check_address_error(0b11, address)) {
|
||||
regs.Write(instr.rt(), 0);
|
||||
regs.cop0.HandleTLBException(address);
|
||||
regs.cop0.FireException(ExceptionCode::AddressErrorStore, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorStore, 0, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -440,7 +440,7 @@ void Interpreter::sc(const Instruction instr) {
|
||||
|
||||
void Interpreter::scd(const Instruction instr) {
|
||||
if (!regs.cop0.is64BitAddressing && !regs.cop0.kernelMode) {
|
||||
regs.cop0.FireException(ExceptionCode::ReservedInstruction, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::ReservedInstruction, 0, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -452,7 +452,7 @@ void Interpreter::scd(const Instruction instr) {
|
||||
if (check_address_error(0b111, address)) {
|
||||
regs.Write(instr.rt(), 0);
|
||||
regs.cop0.HandleTLBException(address);
|
||||
regs.cop0.FireException(ExceptionCode::AddressErrorStore, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorStore, 0, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -487,7 +487,7 @@ void Interpreter::sw(const Instruction instr) {
|
||||
const u64 address = regs.Read<s64>(instr.rs()) + offset;
|
||||
if (check_address_error(0b11, address)) {
|
||||
regs.cop0.HandleTLBException(address);
|
||||
regs.cop0.FireException(ExceptionCode::AddressErrorStore, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorStore, 0, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -504,7 +504,7 @@ void Interpreter::sd(const Instruction instr) {
|
||||
const s64 address = regs.Read<s64>(instr.rs()) + (s16)instr;
|
||||
if (check_address_error(0b111, address)) {
|
||||
regs.cop0.HandleTLBException(address);
|
||||
regs.cop0.FireException(ExceptionCode::AddressErrorStore, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::AddressErrorStore, 0, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -757,7 +757,7 @@ void Interpreter::dsub(const Instruction instr) {
|
||||
const s64 rt = regs.Read<s64>(instr.rt());
|
||||
const s64 rs = regs.Read<s64>(instr.rs());
|
||||
if (const s64 result = rs - rt; check_signed_underflow(rs, rt, result)) {
|
||||
regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::Overflow, 0, regs.oldPC);
|
||||
} else {
|
||||
regs.Write(instr.rd(), result);
|
||||
}
|
||||
@@ -775,7 +775,7 @@ void Interpreter::sub(const Instruction instr) {
|
||||
const s32 rs = regs.Read<s64>(instr.rs());
|
||||
const s32 result = rs - rt;
|
||||
if (check_signed_underflow(rs, rt, result)) {
|
||||
regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC);
|
||||
regs.cop0.FireException(Cop0::ExceptionCode::Overflow, 0, regs.oldPC);
|
||||
} else {
|
||||
regs.Write(instr.rd(), result);
|
||||
}
|
||||
@@ -831,7 +831,7 @@ void Interpreter::mthi(const Instruction instr) { regs.hi = regs.Read<s64>(instr
|
||||
void Interpreter::trap(const bool cond) const {
|
||||
Cop0 &cop0 = Core::GetRegs().cop0;
|
||||
if (cond) {
|
||||
cop0.FireException(ExceptionCode::Trap, 0, regs.oldPC);
|
||||
cop0.FireException(Cop0::ExceptionCode::Trap, 0, regs.oldPC);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -852,21 +852,84 @@ void Interpreter::cfc2(const Instruction) {}
|
||||
|
||||
void Interpreter::cache(const Instruction instr) {
|
||||
u8 type = instr.op() & 3;
|
||||
u8 op = (instr.op() >> 2) & 7;
|
||||
const u8 op = (instr.op() >> 2) & 7;
|
||||
u64 vaddr = regs.Read<u64>(instr.rs()) + (s16)instr.offset();
|
||||
u32 paddr;
|
||||
if (!regs.cop0.MapVAddr(Cop0::LOAD, vaddr, paddr)) {
|
||||
regs.cop0.HandleTLBException(vaddr);
|
||||
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.oldPC);
|
||||
return;
|
||||
}
|
||||
|
||||
u32 ptag = GetPhysicalAddressPTag(paddr);
|
||||
|
||||
if (type > 1)
|
||||
panic("Unknown cache type {}", type);
|
||||
|
||||
if (type == 0)
|
||||
return cache_type_instruction(op);
|
||||
return cache_type_instruction(op, vaddr, paddr, ptag);
|
||||
|
||||
if (type == 1)
|
||||
return cache_type_data(op);
|
||||
return cache_type_data(op, vaddr, paddr, ptag);
|
||||
}
|
||||
|
||||
void Interpreter::cache_type_instruction(const u8 op) {
|
||||
void Interpreter::cache_type_instruction(const u8 op, const u64 vaddr, const u32 paddr, const u32 ptag) {
|
||||
switch (op) {
|
||||
case 0:
|
||||
icache.
|
||||
icache.InvalidateIndex(vaddr);
|
||||
break;
|
||||
case 1:
|
||||
icache.LoadTag(vaddr);
|
||||
break;
|
||||
case 2:
|
||||
icache.StoreTag(vaddr, regs.cop0.tagLo.ptaglo, regs.cop0);
|
||||
break;
|
||||
case 4:
|
||||
icache.InvalidateIndex(vaddr, ptag);
|
||||
break;
|
||||
case 5:
|
||||
icache.FillLine(vaddr, paddr);
|
||||
break;
|
||||
case 6:
|
||||
icache.WriteBack(vaddr, paddr, ptag);
|
||||
break;
|
||||
default:
|
||||
panic("Unimplemented icache op 0b{:03b}", op);
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::cache_type_data(const u8 op, const u64 vaddr, const u32 paddr, const u32 ptag) {
|
||||
switch (op) {
|
||||
case 0:
|
||||
dcache.WriteBack<true>(vaddr, paddr);
|
||||
break;
|
||||
case 1:
|
||||
dcache.LoadTag(vaddr);
|
||||
break;
|
||||
case 2:
|
||||
dcache.StoreTag(vaddr, regs.cop0.tagLo.ptaglo, regs.cop0);
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
auto &line = dcache.lines[GetDCacheLineIndex(vaddr)];
|
||||
if ((line.ptag != ptag || !line.valid) && line.dirty)
|
||||
dcache.WriteBack(vaddr, paddr);
|
||||
|
||||
line.ptag = ptag;
|
||||
line.valid = true;
|
||||
line.dirty = true;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
dcache.InvalidateIndex(vaddr, ptag);
|
||||
break;
|
||||
case 5:
|
||||
dcache.WriteBack<true>(vaddr, paddr, ptag);
|
||||
break;
|
||||
case 6:
|
||||
dcache.WriteBack(vaddr, paddr, ptag);
|
||||
break;
|
||||
default:
|
||||
panic("Unimplemented dcache op 0b{:03b}", op);
|
||||
}
|
||||
}
|
||||
} // namespace n64
|
||||
|
||||
Reference in New Issue
Block a user