Huge refactor: Make Core a singleton
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
#include <core/Interpreter.hpp>
|
||||
#include <core/registers/Registers.hpp>
|
||||
#include <Core.hpp>
|
||||
#include <log.hpp>
|
||||
|
||||
namespace n64 {
|
||||
Cop0::Cop0(Registers ®s) : regs(regs) { Reset(); }
|
||||
Cop0::Cop0() { Reset(); }
|
||||
|
||||
void Cop0::Reset() {
|
||||
cause.raw = 0xB000007C;
|
||||
@@ -293,15 +292,15 @@ static FORCE_INLINE u64 getVPN(const u64 addr, const u64 pageMask) {
|
||||
return vpn & ~mask;
|
||||
}
|
||||
|
||||
TLBEntry *Cop0::TLBTryMatch(const u64 vaddr, int &index) const {
|
||||
TLBEntry *Cop0::TLBTryMatch(const u64 vaddr, int &index) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (TLBEntry *entry = ®s.cop0.tlb[i]; entry->initialized) {
|
||||
if (TLBEntry *entry = &tlb[i]; entry->initialized) {
|
||||
const u64 entry_vpn = getVPN(entry->entryHi.raw, entry->pageMask.raw);
|
||||
const u64 vaddr_vpn = getVPN(vaddr, entry->pageMask.raw);
|
||||
|
||||
const bool vpn_match = entry_vpn == vaddr_vpn;
|
||||
|
||||
if (const bool asid_match = entry->global || regs.cop0.entryHi.asid == entry->entryHi.asid;
|
||||
if (const bool asid_match = entry->global || entryHi.asid == entry->entryHi.asid;
|
||||
vpn_match && asid_match) {
|
||||
index = i;
|
||||
return entry;
|
||||
@@ -312,15 +311,15 @@ TLBEntry *Cop0::TLBTryMatch(const u64 vaddr, int &index) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TLBEntry *Cop0::TLBTryMatch(const u64 vaddr) const {
|
||||
for (auto &i : regs.cop0.tlb) {
|
||||
TLBEntry *Cop0::TLBTryMatch(const u64 vaddr) {
|
||||
for (auto &i : tlb) {
|
||||
if (TLBEntry *entry = &i; entry->initialized) {
|
||||
const u64 entry_vpn = getVPN(entry->entryHi.raw, entry->pageMask.raw);
|
||||
const u64 vaddr_vpn = getVPN(vaddr, entry->pageMask.raw);
|
||||
|
||||
const bool vpn_match = entry_vpn == vaddr_vpn;
|
||||
|
||||
if (const bool asid_match = entry->global || regs.cop0.entryHi.asid == entry->entryHi.asid;
|
||||
if (const bool asid_match = entry->global || entryHi.asid == entry->entryHi.asid;
|
||||
vpn_match && asid_match) {
|
||||
return entry;
|
||||
}
|
||||
@@ -330,10 +329,10 @@ TLBEntry *Cop0::TLBTryMatch(const u64 vaddr) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Cop0::ProbeTLB(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) const {
|
||||
bool Cop0::ProbeTLB(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) {
|
||||
const TLBEntry *entry = TLBTryMatch(vaddr);
|
||||
if (!entry) {
|
||||
regs.cop0.tlbError = MISS;
|
||||
tlbError = MISS;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -343,12 +342,12 @@ bool Cop0::ProbeTLB(const TLBAccessType accessType, const u64 vaddr, u32 &paddr)
|
||||
const EntryLo entryLo = odd ? entry->entryLo1 : entry->entryLo0;
|
||||
|
||||
if (!entryLo.v) {
|
||||
regs.cop0.tlbError = INVALID;
|
||||
tlbError = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (accessType == STORE && !entryLo.d) {
|
||||
regs.cop0.tlbError = MODIFICATION;
|
||||
tlbError = MODIFICATION;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -370,22 +369,23 @@ FORCE_INLINE bool Is64BitAddressing(const Cop0 &cp0, const u64 addr) {
|
||||
}
|
||||
}
|
||||
|
||||
void Cop0::FireException(const ExceptionCode code, const int cop, s64 pc) const {
|
||||
const bool old_exl = regs.cop0.status.exl;
|
||||
void Cop0::FireException(const ExceptionCode code, const int cop, s64 pc) {
|
||||
Registers& regs = Core::GetInstance().cpu->GetRegs();
|
||||
const bool old_exl = status.exl;
|
||||
|
||||
if (!regs.cop0.status.exl) {
|
||||
if ((regs.cop0.cause.branchDelay = regs.prevDelaySlot)) {
|
||||
if (!status.exl) {
|
||||
if ((cause.branchDelay = regs.prevDelaySlot)) {
|
||||
pc -= 4;
|
||||
}
|
||||
|
||||
regs.cop0.status.exl = true;
|
||||
regs.cop0.EPC = pc;
|
||||
status.exl = true;
|
||||
EPC = pc;
|
||||
}
|
||||
|
||||
regs.cop0.cause.copError = cop;
|
||||
regs.cop0.cause.exceptionCode = static_cast<u8>(code);
|
||||
cause.copError = cop;
|
||||
cause.exceptionCode = static_cast<u8>(code);
|
||||
|
||||
if (regs.cop0.status.bev) {
|
||||
if (status.bev) {
|
||||
panic("BEV bit set!");
|
||||
} else {
|
||||
switch (code) {
|
||||
@@ -423,15 +423,15 @@ void Cop0::FireException(const ExceptionCode code, const int cop, s64 pc) const
|
||||
regs.cop0.Update();
|
||||
}
|
||||
|
||||
void Cop0::HandleTLBException(const u64 vaddr) const {
|
||||
void Cop0::HandleTLBException(const u64 vaddr) {
|
||||
const u64 vpn2 = vaddr >> 13 & 0x7FFFF;
|
||||
const u64 xvpn2 = vaddr >> 13 & 0x7FFFFFF;
|
||||
regs.cop0.badVaddr = vaddr;
|
||||
regs.cop0.context.badvpn2 = vpn2;
|
||||
regs.cop0.xcontext.badvpn2 = xvpn2;
|
||||
regs.cop0.xcontext.r = vaddr >> 62 & 3;
|
||||
regs.cop0.entryHi.vpn2 = xvpn2;
|
||||
regs.cop0.entryHi.r = vaddr >> 62 & 3;
|
||||
badVaddr = vaddr;
|
||||
context.badvpn2 = vpn2;
|
||||
xcontext.badvpn2 = xvpn2;
|
||||
xcontext.r = vaddr >> 62 & 3;
|
||||
entryHi.vpn2 = xvpn2;
|
||||
entryHi.r = vaddr >> 62 & 3;
|
||||
}
|
||||
|
||||
ExceptionCode Cop0::GetTLBExceptionCode(const TLBError error, const TLBAccessType accessType) {
|
||||
@@ -452,6 +452,7 @@ ExceptionCode Cop0::GetTLBExceptionCode(const TLBError error, const TLBAccessTyp
|
||||
}
|
||||
|
||||
void Cop0::decode(const u32 instr) {
|
||||
Registers& regs = Core::GetInstance().cpu->GetRegs();
|
||||
const u8 mask_cop = instr >> 21 & 0x1F;
|
||||
const u8 mask_cop2 = instr & 0x3F;
|
||||
switch (mask_cop) {
|
||||
@@ -495,30 +496,30 @@ void Cop0::decode(const u32 instr) {
|
||||
}
|
||||
|
||||
bool Cop0::MapVAddr(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) {
|
||||
if (regs.cop0.is64BitAddressing) [[unlikely]] {
|
||||
if (regs.cop0.kernelMode) [[likely]] {
|
||||
if (is64BitAddressing) [[unlikely]] {
|
||||
if (kernelMode) [[likely]] {
|
||||
return MapVAddr64(accessType, vaddr, paddr);
|
||||
}
|
||||
|
||||
if (regs.cop0.userMode) {
|
||||
if (userMode) {
|
||||
return UserMapVAddr64(accessType, vaddr, paddr);
|
||||
}
|
||||
|
||||
if (regs.cop0.supervisorMode) {
|
||||
if (supervisorMode) {
|
||||
panic("Supervisor mode memory access, 64 bit mode");
|
||||
} else {
|
||||
panic("Unknown mode! This should never happen!");
|
||||
}
|
||||
} else {
|
||||
if (regs.cop0.kernelMode) [[likely]] {
|
||||
if (kernelMode) [[likely]] {
|
||||
return MapVAddr32(accessType, vaddr, paddr);
|
||||
}
|
||||
|
||||
if (regs.cop0.userMode) {
|
||||
if (userMode) {
|
||||
return UserMapVAddr32(accessType, vaddr, paddr);
|
||||
}
|
||||
|
||||
if (regs.cop0.supervisorMode) {
|
||||
if (supervisorMode) {
|
||||
panic("Supervisor mode memory access, 32 bit mode");
|
||||
} else {
|
||||
panic("Unknown mode! This should never happen!");
|
||||
@@ -531,7 +532,7 @@ bool Cop0::UserMapVAddr32(const TLBAccessType accessType, const u64 vaddr, u32 &
|
||||
case VREGION_KUSEG:
|
||||
return ProbeTLB(accessType, s64(s32(vaddr)), paddr);
|
||||
default:
|
||||
regs.cop0.tlbError = DISALLOWED_ADDRESS;
|
||||
tlbError = DISALLOWED_ADDRESS;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -558,7 +559,7 @@ bool Cop0::UserMapVAddr64(const TLBAccessType accessType, const u64 vaddr, u32 &
|
||||
case VREGION_XKUSEG:
|
||||
return ProbeTLB(accessType, vaddr, paddr);
|
||||
default:
|
||||
regs.cop0.tlbError = DISALLOWED_ADDRESS;
|
||||
tlbError = DISALLOWED_ADDRESS;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -570,7 +571,7 @@ bool Cop0::MapVAddr64(const TLBAccessType accessType, const u64 vaddr, u32 &padd
|
||||
return ProbeTLB(accessType, vaddr, paddr);
|
||||
case VREGION_XKPHYS:
|
||||
{
|
||||
if (!regs.cop0.kernelMode) {
|
||||
if (!kernelMode) {
|
||||
panic("Access to XKPHYS address 0x{:016X} when outside kernel mode!", vaddr);
|
||||
}
|
||||
if (const u8 high_two_bits = (vaddr >> 62) & 0b11; high_two_bits != 0b10) {
|
||||
@@ -580,7 +581,7 @@ bool Cop0::MapVAddr64(const TLBAccessType accessType, const u64 vaddr, u32 &padd
|
||||
bool cached = subsegment != 2; // do something with this eventually
|
||||
// If any bits in the range of 58:32 are set, the address is invalid.
|
||||
if (const bool valid = (vaddr & 0x07FFFFFF00000000) == 0; !valid) {
|
||||
regs.cop0.tlbError = DISALLOWED_ADDRESS;
|
||||
tlbError = DISALLOWED_ADDRESS;
|
||||
return false;
|
||||
}
|
||||
paddr = vaddr & 0xFFFFFFFF;
|
||||
@@ -607,7 +608,7 @@ bool Cop0::MapVAddr64(const TLBAccessType accessType, const u64 vaddr, u32 &padd
|
||||
case VREGION_XBAD1:
|
||||
case VREGION_XBAD2:
|
||||
case VREGION_XBAD3:
|
||||
regs.cop0.tlbError = DISALLOWED_ADDRESS;
|
||||
tlbError = DISALLOWED_ADDRESS;
|
||||
return false;
|
||||
default:
|
||||
panic("Resolving virtual address 0x{:016X} in 64 bit mode", vaddr);
|
||||
|
||||
Reference in New Issue
Block a user