Cop0's Index as a union
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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{};
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user