Cop0's Index as a union

This commit is contained in:
SimoneN64
2023-08-28 15:58:18 +02:00
parent 1a338de8b9
commit 367a82c11d
3 changed files with 34 additions and 24 deletions

View File

@@ -19,13 +19,13 @@ void Cop0::Reset() {
EPC = 0xFFFFFFFFFFFFFFFFll; EPC = 0xFFFFFFFFFFFFFFFFll;
ErrorEPC = 0xFFFFFFFFFFFFFFFFll; ErrorEPC = 0xFFFFFFFFFFFFFFFFll;
wired = 0; wired = 0;
index = 63; index.raw = 63;
badVaddr = 0xFFFFFFFFFFFFFFFF; badVaddr = 0xFFFFFFFFFFFFFFFF;
} }
u32 Cop0::GetReg32(u8 addr) { u32 Cop0::GetReg32(u8 addr) {
switch(addr) { switch(addr) {
case COP0_REG_INDEX: return index & 0x8000003F; case COP0_REG_INDEX: return index.raw & INDEX_MASK;
case COP0_REG_RANDOM: return GetRandom(); case COP0_REG_RANDOM: return GetRandom();
case COP0_REG_ENTRYLO0: return entryLo0.raw; case COP0_REG_ENTRYLO0: return entryLo0.raw;
case COP0_REG_ENTRYLO1: return entryLo1.raw; case COP0_REG_ENTRYLO1: return entryLo1.raw;
@@ -54,7 +54,7 @@ u32 Cop0::GetReg32(u8 addr) {
case 23: case 24: case 25: case 23: case 24: case 25:
case 31: return openbus; case 31: return openbus;
default: default:
Util::panic("Unsupported word read from COP0 register {}", index); Util::panic("Unsupported word read from COP0 register {}", addr);
} }
} }
@@ -75,14 +75,14 @@ u64 Cop0::GetReg64(u8 addr) const {
case 23: case 24: case 25: case 23: case 24: case 25:
case 31: return openbus; case 31: return openbus;
default: default:
Util::panic("Unsupported dword read from COP0 register {}", index); Util::panic("Unsupported dword read from COP0 register {}", addr);
} }
} }
void Cop0::SetReg32(u8 addr, u32 value) { void Cop0::SetReg32(u8 addr, u32 value) {
openbus = value & 0xFFFFFFFF; openbus = value & 0xFFFFFFFF;
switch(addr) { switch(addr) {
case COP0_REG_INDEX: index = value; break; case COP0_REG_INDEX: index.raw = value & INDEX_MASK; break;
case COP0_REG_RANDOM: break; case COP0_REG_RANDOM: break;
case COP0_REG_ENTRYLO0: case COP0_REG_ENTRYLO0:
entryLo0.raw = value & ENTRY_LO_MASK; entryLo0.raw = value & ENTRY_LO_MASK;
@@ -137,7 +137,7 @@ void Cop0::SetReg32(u8 addr, u32 value) {
case 23: case 24: case 25: case 23: case 24: case 25:
case 31: break; case 31: break;
default: default:
Util::panic("Unsupported word write from COP0 register {}", index); Util::panic("Unsupported word write from COP0 register {}", addr);
} }
} }
@@ -352,7 +352,7 @@ void Cop0::decodeInterp(Registers& regs, u32 instr) {
case 0x10 ... 0x1F: case 0x10 ... 0x1F:
switch(mask_cop2) { switch(mask_cop2) {
case 0x01: tlbr(); break; case 0x01: tlbr(); break;
case 0x02: tlbw(index & 0x3F); break; case 0x02: tlbw(index.i); break;
case 0x06: tlbw(GetRandom()); break; case 0x06: tlbw(GetRandom()); break;
case 0x08: tlbp(regs); break; case 0x08: tlbp(regs); break;
case 0x18: eret(regs); break; case 0x18: eret(regs); break;

View File

@@ -5,6 +5,7 @@
namespace n64 { namespace n64 {
#define STATUS_MASK 0xFF57FFFF #define STATUS_MASK 0xFF57FFFF
#define CONFIG_MASK 0x0F00800F #define CONFIG_MASK 0x0F00800F
#define INDEX_MASK 0x8000003F
#define COP0_REG_INDEX 0 #define COP0_REG_INDEX 0
#define COP0_REG_RANDOM 1 #define COP0_REG_RANDOM 1
#define COP0_REG_ENTRYLO0 2 #define COP0_REG_ENTRYLO0 2
@@ -133,6 +134,15 @@ union PageMask {
}; };
}; };
union Index {
u32 raw;
struct {
unsigned i:6;
unsigned:25;
unsigned p:1;
};
};
struct TLBEntry { struct TLBEntry {
bool initialized; bool initialized;
union { union {
@@ -220,7 +230,7 @@ struct Cop0 {
PageMask pageMask{}; PageMask pageMask{};
EntryHi entryHi{}; EntryHi entryHi{};
EntryLo entryLo0{}, entryLo1{}; EntryLo entryLo0{}, entryLo1{};
u32 index{}; Index index{};
Cop0Context context{}; Cop0Context context{};
u32 wired{}, r7{}; u32 wired{}, r7{};
u64 badVaddr{}, count{}; u64 badVaddr{}, count{};

View File

@@ -32,12 +32,11 @@ void Cop0::eret(Registers& regs) {
void Cop0::tlbr() { void Cop0::tlbr() {
u8 Index = index & 0b111111; if (index.i >= 32) {
if (Index >= 32) { Util::panic("TLBR with TLB index {}", index.i);
Util::panic("TLBR with TLB index {}", index);
} }
TLBEntry entry = tlb[Index]; TLBEntry entry = tlb[index.i];
entryHi.raw = entry.entryHi.raw; entryHi.raw = entry.entryHi.raw;
entryLo0.raw = entry.entryLo0.raw & 0x3FFFFFFF; entryLo0.raw = entry.entryLo0.raw & 0x3FFFFFFF;
@@ -48,34 +47,35 @@ void Cop0::tlbr() {
pageMask.raw = entry.pageMask.raw; pageMask.raw = entry.pageMask.raw;
} }
void Cop0::tlbw(int index) { void Cop0::tlbw(int index_) {
PageMask page_mask{}; PageMask page_mask{};
page_mask = pageMask; page_mask = pageMask;
u32 top = page_mask.mask & 0xAAA; u32 top = page_mask.mask & 0xAAA;
page_mask.mask = top | (top >> 1); page_mask.mask = top | (top >> 1);
if(index >= 32) { if(index_ >= 32) {
Util::panic("TLBWI with TLB index {}", index); Util::panic("TLBWI with TLB index {}", index_);
} }
tlb[index].entryHi.raw = entryHi.raw; tlb[index_].entryHi.raw = entryHi.raw;
tlb[index].entryHi.vpn2 &= ~page_mask.mask; tlb[index_].entryHi.vpn2 &= ~page_mask.mask;
tlb[index].entryLo0.raw = entryLo0.raw & 0x03FFFFFE; tlb[index_].entryLo0.raw = entryLo0.raw & 0x03FFFFFE;
tlb[index].entryLo1.raw = entryLo1.raw & 0x03FFFFFE; tlb[index_].entryLo1.raw = entryLo1.raw & 0x03FFFFFE;
tlb[index].pageMask.raw = page_mask.raw; tlb[index_].pageMask.raw = page_mask.raw;
tlb[index].global = entryLo0.g && entryLo1.g; tlb[index_].global = entryLo0.g && entryLo1.g;
tlb[index].initialized = true; tlb[index_].initialized = true;
} }
void Cop0::tlbp(Registers& regs) { void Cop0::tlbp(Registers& regs) {
int match = -1; int match = -1;
TLBEntry* entry = TLBTryMatch(regs, entryHi.raw, &match); TLBEntry* entry = TLBTryMatch(regs, entryHi.raw, &match);
if(entry && match >= 0) { if(entry && match >= 0) {
index = match; index.i = match;
index.p = 0;
} else { } else {
index = 0x80000000; index.p = 1;
} }
} }