Mem and Regs not part of cpu anymore.

This commit is contained in:
SimoZ64
2025-08-01 21:05:11 +02:00
parent 812b905bdf
commit 010bb5e0bb
35 changed files with 246 additions and 250 deletions

View File

@@ -193,7 +193,7 @@ void ParallelRDP::UpdateScreen(Util::IntrusivePtr<Image> image) const {
void ParallelRDP::UpdateScreen(bool playing) const {
if(playing) {
n64::Core& core = n64::Core::GetInstance();
n64::VI& vi = core.GetVI();
n64::VI& vi = core.GetMem().mmio.vi;
command_processor->set_vi_register(VIRegister::Control, vi.status.raw);
command_processor->set_vi_register(VIRegister::Origin, vi.origin);
command_processor->set_vi_register(VIRegister::Width, vi.width);

View File

@@ -7,10 +7,10 @@ namespace n64 {
Core::Core() {
auto cpuType = Options::GetInstance().GetValue<std::string>("cpu", "type");
if (cpuType == "interpreter") {
cpu = std::make_unique<Interpreter>(parallel);
cpu = std::make_unique<Interpreter>(parallel, *mem, regs);
} else if(cpuType == "jit") {
#ifndef __aarch64__
cpu = std::make_unique<JIT>(parallel);
cpu = std::make_unique<JIT>(parallel, *mem, regs);
#else
panic("JIT currently unsupported on aarch64");
#endif
@@ -26,11 +26,13 @@ void Core::Stop() {
}
void Core::Reset() {
regs.Reset();
mem->Reset();
cpu->Reset();
cpu->GetMem().mmio.si.pif.Execute();
mem->mmio.si.pif.Execute();
}
bool Core::LoadTAS(const fs::path &path) const { return cpu->GetMem().mmio.si.pif.movie.Load(path); }
bool Core::LoadTAS(const fs::path &path) const { return mem->mmio.si.pif.movie.Load(path); }
void Core::LoadROM(const std::string &rom_) {
Stop();
@@ -41,26 +43,24 @@ void Core::LoadROM(const std::string &rom_) {
auto extension = fs::path(rom).extension().string();
const bool isArchive = std::ranges::any_of(archive_types, [&extension](const auto &e) { return e == extension; });
cpu->GetMem().LoadROM(isArchive, rom);
mem->LoadROM(isArchive, rom);
GameDB::match();
if (cpu->GetMem().rom.gameNameDB.empty()) {
cpu->GetMem().rom.gameNameDB = fs::path(rom).stem().string();
if (mem->rom.gameNameDB.empty()) {
mem->rom.gameNameDB = fs::path(rom).stem().string();
}
cpu->GetMem().mmio.vi.isPal = cpu->GetMem().IsROMPAL();
cpu->GetMem().mmio.si.pif.InitDevices(cpu->GetMem().saveType);
cpu->GetMem().mmio.si.pif.mempakPath = rom;
cpu->GetMem().mmio.si.pif.LoadEeprom(cpu->GetMem().saveType, rom);
cpu->GetMem().flash.Load(cpu->GetMem().saveType, rom);
cpu->GetMem().LoadSRAM(cpu->GetMem().saveType, rom);
cpu->GetMem().mmio.si.pif.Execute();
mem->mmio.vi.isPal = mem->IsROMPAL();
mem->mmio.si.pif.InitDevices(mem->saveType);
mem->mmio.si.pif.mempakPath = rom;
mem->mmio.si.pif.LoadEeprom(mem->saveType, rom);
mem->flash.Load(mem->saveType, rom);
mem->LoadSRAM(mem->saveType, rom);
mem->mmio.si.pif.Execute();
pause = false;
romLoaded = true;
}
void Core::Run(float volumeL, float volumeR) {
Mem &mem = cpu->GetMem();
MMIO &mmio = mem.mmio;
Registers &regs = cpu->GetRegs();
MMIO &mmio = mem->mmio;
for (int field = 0; field < mmio.vi.numFields; field++) {
u32 frameCycles = 0;
@@ -71,7 +71,7 @@ void Core::Run(float volumeL, float volumeR) {
mmio.mi.InterruptRaise(MI::Interrupt::VI);
}
for (; cycles < mem.mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) {
for (; cycles < mem->mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) {
u32 taken = cpu->Step();
taken += regs.PopStalledCycles();

View File

@@ -20,13 +20,20 @@ struct Core {
return instance;
}
static Registers& GetRegs() {
return GetInstance().regs;
}
static Mem& GetMem() {
return *GetInstance().mem;
}
void Stop();
void Reset();
void LoadROM(const std::string &);
[[nodiscard]] bool LoadTAS(const fs::path &) const;
void Run(float volumeL, float volumeR);
void TogglePause() { pause = !pause; }
[[nodiscard]] VI &GetVI() const { return cpu->GetMem().mmio.vi; }
inline void ToggleBreakpoint(s64 addr) {
if(breakpoints.contains(addr)){
breakpoints.erase(addr);
@@ -42,6 +49,8 @@ struct Core {
u32 cycles = 0;
bool romLoaded = false;
std::string rom;
Registers regs;
std::unique_ptr<Mem> mem = std::make_unique<Mem>();
std::unique_ptr<BaseCPU> cpu;
size_t memSize{}, cpuSize{}, verSize{};
int slot = 0;

View File

@@ -3,7 +3,7 @@
namespace n64 {
void GameDB::match() {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
const ROM &rom = mem.rom;
for (const auto &[code, regions, saveType, name] : gamedb) {
const bool matches_code = code == rom.code;

View File

@@ -19,8 +19,7 @@ u64 Scheduler::Remove(const EventType eventType) const {
}
void Scheduler::Tick(const u64 t) {
n64::Core& core = n64::Core::GetInstance();
n64::Mem& mem = core.cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
ticks += t;
n64::MI &mi = mem.mmio.mi;
n64::SI &si = mem.mmio.si;

View File

@@ -8,7 +8,5 @@ struct BaseCPU {
virtual ~BaseCPU() = default;
virtual int Step() = 0;
virtual void Reset() = 0;
virtual Mem &GetMem() = 0;
virtual Registers &GetRegs() = 0;
};
} // namespace n64

View File

@@ -4,7 +4,7 @@
template <>
std::optional<u64> Disassembler::CapstoneToRegValue(mips_reg reg) const {
n64::Registers& regs = n64::Core::GetInstance().cpu->GetRegs();
n64::Registers& regs = n64::Core::GetRegs();
u64 val = 0;
switch(reg) {
case MIPS_REG_ZERO: case MIPS_REG_ZERO_64: case MIPS_REG_ZERO_NM:
@@ -109,7 +109,7 @@ std::optional<u64> Disassembler::CapstoneToRegValue(mips_reg reg) const {
template <>
std::string Disassembler::CapstoneToRegValue(mips_reg reg) const {
n64::Registers& regs = n64::Core::GetInstance().cpu->GetRegs();
n64::Registers& regs = n64::Core::GetRegs();
auto val = CapstoneToRegValue<std::optional<u64>>(reg);
return std::format("{}", val.has_value() ? std::format("{} (= 0x{:016X})", cs_reg_name(handle, reg), val.value()) : "! Unknown !");
@@ -131,13 +131,11 @@ Disassembler::DisassemblyResult Disassembler::DisassembleSimple(const u32 addres
}
[[nodiscard]] Disassembler::DisassemblyResult Disassembler::Disassemble(const u32 address) const {
n64::Core& core = n64::Core::GetInstance();
n64::Mem& mem = core.cpu->GetMem();
u32 paddr;
if(!core.cpu->GetRegs().cop0.MapVAddr(n64::Cop0::TLBAccessType::LOAD, address, paddr))
if(!n64::Core::GetRegs().cop0.MapVAddr(n64::Cop0::TLBAccessType::LOAD, address, paddr))
return DisassemblyResult{false, ""};
u32 instruction = mem.Read<u32>(paddr);
u32 instruction = n64::Core::GetMem().Read<u32>(paddr);
return details ? DisassembleDetailed(address, instruction) : DisassembleSimple(address, instruction);
}

View File

@@ -1,7 +1,7 @@
#include <Core.hpp>
namespace n64 {
Interpreter::Interpreter(ParallelRDP &parallel) {}
Interpreter::Interpreter(ParallelRDP& parallel, Mem& mem, Registers& regs) : mem(mem), regs(regs) {}
bool Interpreter::ShouldServiceInterrupt() const {
const bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0;

View File

@@ -7,22 +7,17 @@ namespace n64 {
struct Core;
struct Interpreter : BaseCPU {
explicit Interpreter(ParallelRDP &);
explicit Interpreter(ParallelRDP&, Mem&, Registers&);
~Interpreter() override = default;
int Step() override;
void Reset() override {
regs.Reset();
mem.Reset();
cop2Latch = {};
}
Mem &GetMem() override { return mem; }
Registers &GetRegs() override { return regs; }
private:
Registers regs;
Mem mem;
Registers& regs;
Mem& mem;
u64 cop2Latch{};
friend struct Cop1;
#define check_address_error(mask, vaddr) \

View File

@@ -3,7 +3,8 @@
namespace n64 {
#ifndef __aarch64__
JIT::JIT(ParallelRDP &parallel) : regs(this), mem(this) {
JIT::JIT(ParallelRDP& parallel, Mem& mem, Registers& regs) : mem(mem), regs(regs) {
regs.SetJIT(this);
blockCache.resize(kUpperSize);
if (cs_open(CS_ARCH_MIPS, static_cast<cs_mode>(CS_MODE_MIPS64 | CS_MODE_BIG_ENDIAN), &disassemblerMips) !=
CS_ERR_OK) {
@@ -29,7 +30,7 @@ void JIT::CheckCompareInterrupt() {
regs.cop0.count &= 0x1FFFFFFFF;
if (regs.cop0.count == static_cast<u64>(regs.cop0.compare) << 1) {
regs.cop0.cause.ip7 = 1;
mem.mmio.mi.UpdateInterrupt();
Core::GetMem().mmio.mi.UpdateInterrupt();
}
}
@@ -58,7 +59,42 @@ u32 JIT::FetchInstruction() {
static_cast<int>(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)), static_cast<u64>(blockPC));
}
return mem.Read<u32>(paddr);
return Core::GetMem().Read<u32>(paddr);
}
void JIT::SetPC32(s32 val) {
code.mov(code.SCR1, REG(qword, pc));
code.mov(REG(qword, oldPC), code.SCR1);
code.mov(code.SCR1, s64(val));
code.mov(REG(qword, pc), code.SCR1);
code.mov(code.SCR1, s64(val) + 4);
code.mov(REG(qword, nextPC), code.SCR1);
}
void JIT::SetPC64(s64 val) {
code.mov(code.SCR1, REG(qword, pc));
code.mov(REG(qword, oldPC), code.SCR1);
code.mov(code.SCR1, val);
code.mov(REG(qword, pc), code.SCR1);
code.mov(code.SCR1, val + 4);
code.mov(REG(qword, nextPC), code.SCR1);
}
void JIT::SetPC32(const Xbyak::Reg32& val) {
code.mov(code.SCR1, REG(qword, pc));
code.mov(REG(qword, oldPC), code.SCR1);
code.movsxd(val.cvt64(), val);
code.mov(REG(qword, pc), val);
code.add(val, 4);
code.mov(REG(qword, nextPC), val);
}
void JIT::SetPC64(const Xbyak::Reg64& val) {
code.mov(code.SCR1, REG(qword, pc));
code.mov(REG(qword, oldPC), code.SCR1);
code.mov(REG(qword, pc), val);
code.add(val, 4);
code.mov(REG(qword, nextPC), val);
}
int JIT::Step() {
@@ -126,7 +162,7 @@ int JIT::Step() {
static_cast<int>(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)), static_cast<u64>(blockPC));
}
instruction = mem.Read<u32>(paddr);
instruction = Core::GetMem().Read<u32>(paddr);
instructionsInBlock++;
blockOldPC = blockPC;

View File

@@ -22,27 +22,21 @@ static constexpr u32 kCodeCacheAllocSize = kCodeCacheSize + 4_kb;
struct JIT : BaseCPU {};
#else
struct JIT : BaseCPU {
explicit JIT(ParallelRDP &);
explicit JIT(ParallelRDP&, Mem&, Registers&);
~JIT() override = default;
int Step() override;
void Reset() override {
regs.Reset();
mem.Reset();
code.reset();
blockCache = {};
blockCache.resize(kUpperSize);
}
void InvalidateBlock(u32);
Mem &GetMem() override { return mem; }
Registers &GetRegs() override { return regs; }
private:
Registers& regs;
Mem& mem;
Xbyak::CodeGenerator code{kCodeCacheAllocSize};
Registers regs;
Mem mem;
u64 cop2Latch{};
u64 blockOldPC = 0, blockPC = 0, blockNextPC = 0;
friend struct Cop1;
@@ -69,6 +63,7 @@ private:
return Xbyak::Address{0};
}
// Thanks to https://github.com/grumpycoders/pcsx-redux
// Load a pointer to the JIT object in "reg"
template <typename T>
@@ -96,41 +91,10 @@ private:
code.add(code.rsp, 8);
}
void SetPC32(s32 val) {
code.mov(code.SCR1, REG(qword, pc));
code.mov(REG(qword, oldPC), code.SCR1);
code.mov(code.SCR1, s64(val));
code.mov(REG(qword, pc), code.SCR1);
code.mov(code.SCR1, s64(val) + 4);
code.mov(REG(qword, nextPC), code.SCR1);
}
void SetPC64(s64 val) {
code.mov(code.SCR1, REG(qword, pc));
code.mov(REG(qword, oldPC), code.SCR1);
code.mov(code.SCR1, val);
code.mov(REG(qword, pc), code.SCR1);
code.mov(code.SCR1, val + 4);
code.mov(REG(qword, nextPC), code.SCR1);
}
void SetPC32(const Xbyak::Reg32& val) {
code.mov(code.SCR1, REG(qword, pc));
code.mov(REG(qword, oldPC), code.SCR1);
code.movsxd(val.cvt64(), val);
code.mov(REG(qword, pc), val);
code.add(val, 4);
code.mov(REG(qword, nextPC), val);
}
void SetPC64(const Xbyak::Reg64& val) {
code.mov(code.SCR1, REG(qword, pc));
code.mov(REG(qword, oldPC), code.SCR1);
code.mov(REG(qword, pc), val);
code.add(val, 4);
code.mov(REG(qword, nextPC), val);
}
void SetPC32(s32 val);
void SetPC64(s64 val);
void SetPC32(const Xbyak::Reg32& val);
void SetPC64(const Xbyak::Reg64& val);
void BranchNotTaken();
void BranchTaken(s64 offs);
void BranchTaken(const Xbyak::Reg64 &offs);

View File

@@ -133,7 +133,7 @@ void Mem::LoadROM(const bool isArchive, const std::string &filename) {
template <>
u8 Mem::Read(const u32 paddr) {
n64::Registers& regs = n64::Core::GetInstance().cpu->GetRegs();
n64::Registers& regs = n64::Core::GetRegs();
const SI &si = mmio.si;
if(Util::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) return mmio.rdp.ReadRDRAM<u8>(paddr);
@@ -165,7 +165,7 @@ u8 Mem::Read(const u32 paddr) {
template <>
u16 Mem::Read(const u32 paddr) {
n64::Registers& regs = n64::Core::GetInstance().cpu->GetRegs();
n64::Registers& regs = n64::Core::GetRegs();
const SI &si = mmio.si;
if(Util::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) return mmio.rdp.ReadRDRAM<u16>(paddr);
@@ -190,7 +190,7 @@ u16 Mem::Read(const u32 paddr) {
template <>
u32 Mem::Read(const u32 paddr) {
n64::Registers& regs = n64::Core::GetInstance().cpu->GetRegs();
n64::Registers& regs = n64::Core::GetRegs();
const SI &si = mmio.si;
if(Util::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) return mmio.rdp.ReadRDRAM<u32>(paddr);
@@ -216,7 +216,7 @@ u32 Mem::Read(const u32 paddr) {
template <>
u64 Mem::Read(const u32 paddr) {
n64::Registers& regs = n64::Core::GetInstance().cpu->GetRegs();
n64::Registers& regs = n64::Core::GetRegs();
const SI &si = mmio.si;
if(Util::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) return mmio.rdp.ReadRDRAM<u64>(paddr);
@@ -242,7 +242,7 @@ u64 Mem::Read(const u32 paddr) {
template <>
void Mem::WriteInterpreter<u8>(u32 paddr, u32 val) {
n64::Registers& regs = n64::Core::GetInstance().cpu->GetRegs();
n64::Registers& regs = n64::Core::GetRegs();
SI &si = mmio.si;
if(Util::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { mmio.rdp.WriteRDRAM<u8>(paddr, val); return; }
@@ -296,7 +296,7 @@ void Mem::Write<u8>(const u32 paddr, const u32 val) {
template <>
void Mem::WriteInterpreter<u16>(u32 paddr, u32 val) {
n64::Registers& regs = n64::Core::GetInstance().cpu->GetRegs();
n64::Registers& regs = n64::Core::GetRegs();
SI &si = mmio.si;
if(Util::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { mmio.rdp.WriteRDRAM<u16>(paddr, val); return; }
@@ -350,7 +350,7 @@ void Mem::Write<u16>(const u32 paddr, const u32 val) {
template <>
void Mem::WriteInterpreter<u32>(const u32 paddr, const u32 val) {
n64::Registers& regs = n64::Core::GetInstance().cpu->GetRegs();
n64::Registers& regs = n64::Core::GetRegs();
SI &si = mmio.si;
if(Util::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { mmio.rdp.WriteRDRAM<u32>(paddr, val); return; }
@@ -409,7 +409,7 @@ void Mem::WriteJIT(const u32 paddr, const u64 val) {
void Mem::Write(const u32 paddr, const u64 val) { WriteInterpreter(paddr, val); }
void Mem::WriteInterpreter(const u32 paddr, u64 val) {
n64::Registers& regs = n64::Core::GetInstance().cpu->GetRegs();
n64::Registers& regs = n64::Core::GetRegs();
SI &si = mmio.si;
if(Util::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { mmio.rdp.WriteRDRAM<u64>(paddr, val); return; }

View File

@@ -23,7 +23,6 @@ struct ROMHeader {
u32 manufacturerId;
u16 cartridgeId;
char countryCode[2];
u8 bootCode[4032];
};
struct ROM {

View File

@@ -197,7 +197,7 @@ FORCE_INLINE void logCommand(u8 cmd) {
*/
void RDP::RunCommand() {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
ParallelRDP& parallel = n64::Core::GetInstance().parallel;
if (dpc.status.freeze) {
return;
@@ -285,7 +285,7 @@ void RDP::RunCommand() {
}
void RDP::OnFullSync() {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
ParallelRDP& parallel = n64::Core::GetInstance().parallel;
parallel.OnFullSync();

View File

@@ -88,8 +88,8 @@ auto RSP::Read(const u32 addr) -> u32 {
}
void RSP::WriteStatus(const u32 value) {
Mem& mem = Core::GetInstance().cpu->GetMem();
Registers& regs = Core::GetInstance().cpu->GetRegs();
Mem& mem = Core::GetMem();
Registers& regs = Core::GetRegs();
MI &mi = mem.mmio.mi;
const auto write = SPStatusWrite{.raw = value};
if (write.clearHalt && !write.setHalt) {
@@ -130,7 +130,7 @@ void RSP::WriteStatus(const u32 value) {
template <>
void RSP::DMA<true>() {
Mem& mem = Core::GetInstance().cpu->GetMem();
Mem& mem = Core::GetMem();
u32 length = spDMALen.len + 1;
length = (length + 0x7) & ~0x7;
@@ -163,7 +163,7 @@ void RSP::DMA<true>() {
template <>
void RSP::DMA<false>() {
Mem& mem = Core::GetInstance().cpu->GetMem();
Mem& mem = Core::GetMem();
u32 length = spDMALen.len + 1;
length = (length + 0x7) & ~0x7;

View File

@@ -4,27 +4,27 @@
namespace n64 {
void Cop0::mtc0(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
SetReg32(RD(instr), regs.Read<u32>(RT(instr)));
}
void Cop0::dmtc0(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
SetReg64(RD(instr), regs.Read<u64>(RT(instr)));
}
void Cop0::mfc0(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
regs.Write(RT(instr), s32(GetReg32(RD(instr))));
}
void Cop0::dmfc0(const u32 instr) const {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
regs.Write(RT(instr), s64(GetReg64(RD(instr))));
}
void Cop0::eret() {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (status.erl) {
regs.SetPC64(ErrorEPC);
status.erl = false;

View File

@@ -132,7 +132,7 @@ bool Cop1::isqnan<double>(const double f) {
template <>
bool Cop1::CheckCVTArg<s32>(const float f) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
switch (std::fpclassify(f)) {
case FP_SUBNORMAL:
case FP_INFINITE:
@@ -153,7 +153,7 @@ bool Cop1::CheckCVTArg<s32>(const float f) {
template <>
bool Cop1::CheckCVTArg<s32>(const double f) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
switch (std::fpclassify(f)) {
case FP_SUBNORMAL:
case FP_INFINITE:
@@ -174,7 +174,7 @@ bool Cop1::CheckCVTArg<s32>(const double f) {
template <>
bool Cop1::CheckCVTArg<s64>(const float f) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
switch (std::fpclassify(f)) {
case FP_SUBNORMAL:
case FP_INFINITE:
@@ -195,7 +195,7 @@ bool Cop1::CheckCVTArg<s64>(const float f) {
template <>
bool Cop1::CheckCVTArg<s64>(const double f) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
switch (std::fpclassify(f)) {
case FP_SUBNORMAL:
case FP_INFINITE:
@@ -216,7 +216,7 @@ bool Cop1::CheckCVTArg<s64>(const double f) {
template <typename T>
bool Cop1::CheckArg(const T f) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
switch (std::fpclassify(f)) {
case FP_SUBNORMAL:
SetCauseUnimplemented();
@@ -234,7 +234,7 @@ bool Cop1::CheckArg(const T f) {
template <typename T>
bool Cop1::CheckArgs(const T f1, const T f2) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
auto class1 = std::fpclassify(f1), class2 = std::fpclassify(f2);
if ((class1 == FP_NAN && !isqnan(f1)) || (class2 == FP_NAN && !isqnan(f2))) {
SetCauseUnimplemented();
@@ -260,7 +260,7 @@ bool Cop1::CheckArgs(const T f1, const T f2) {
template <bool preserveCause>
bool Cop1::CheckFPUUsable() {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if constexpr (preserveCause) {
if (!regs.cop0.status.cu1) {
regs.cop0.FireException(ExceptionCode::CoprocessorUnusable, 1, regs.oldPC);
@@ -295,7 +295,7 @@ FORCE_INLINE T FlushResult(T f, const u32 round) {
template <>
bool Cop1::CheckResult<float>(float &f) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
switch (std::fpclassify(f)) {
case FP_SUBNORMAL:
if (!fcr31.fs || fcr31.enable.underflow || fcr31.enable.inexact_operation) {
@@ -318,7 +318,7 @@ bool Cop1::CheckResult<float>(float &f) {
template <>
bool Cop1::CheckResult<double>(double &f) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
switch (std::fpclassify(f)) {
case FP_SUBNORMAL:
if (!fcr31.fs || fcr31.enable.underflow || fcr31.enable.inexact_operation) {
@@ -341,7 +341,7 @@ bool Cop1::CheckResult<double>(double &f) {
template <bool cvt>
bool Cop1::TestExceptions() {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
const u32 exc = std::fetestexcept(FE_ALL_EXCEPT);
if (!exc)
@@ -445,7 +445,7 @@ bool Cop1::SetCauseInvalid() {
#define CHECK_FPE_CONV_CONST(type, res, operation) CHECK_FPE_IMPL_CONST(type, res, operation, true)
void Cop1::absd(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -458,7 +458,7 @@ void Cop1::absd(const u32 instr) {
}
void Cop1::abss(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -471,7 +471,7 @@ void Cop1::abss(const u32 instr) {
}
void Cop1::adds(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -485,7 +485,7 @@ void Cop1::adds(const u32 instr) {
}
void Cop1::addd(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -499,7 +499,7 @@ void Cop1::addd(const u32 instr) {
}
void Cop1::ceills(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -510,7 +510,7 @@ void Cop1::ceills(const u32 instr) {
}
void Cop1::ceilld(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -521,7 +521,7 @@ void Cop1::ceilld(const u32 instr) {
}
void Cop1::ceilws(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -532,7 +532,7 @@ void Cop1::ceilws(const u32 instr) {
}
void Cop1::ceilwd(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -543,7 +543,7 @@ void Cop1::ceilwd(const u32 instr) {
}
void Cop1::cfc1(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable<true>())
return;
const u8 fd = RD(instr);
@@ -562,7 +562,7 @@ void Cop1::cfc1(const u32 instr) {
}
void Cop1::ctc1(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable<true>())
return;
const u8 fs = RD(instr);
@@ -610,7 +610,7 @@ void Cop1::ctc1(const u32 instr) {
}
void Cop1::cvtds(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -623,7 +623,7 @@ void Cop1::cvtds(const u32 instr) {
}
void Cop1::cvtsd(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -636,7 +636,7 @@ void Cop1::cvtsd(const u32 instr) {
}
void Cop1::cvtsw(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<s32>(regs.cop0.status, FS(instr));
@@ -647,7 +647,7 @@ void Cop1::cvtsw(const u32 instr) {
}
void Cop1::cvtsl(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<s64>(regs.cop0.status, FS(instr));
@@ -663,7 +663,7 @@ void Cop1::cvtsl(const u32 instr) {
}
void Cop1::cvtwd(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -674,7 +674,7 @@ void Cop1::cvtwd(const u32 instr) {
}
void Cop1::cvtws(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -685,7 +685,7 @@ void Cop1::cvtws(const u32 instr) {
}
void Cop1::cvtls(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -696,7 +696,7 @@ void Cop1::cvtls(const u32 instr) {
}
void Cop1::cvtdw(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<s32>(regs.cop0.status, FS(instr));
@@ -707,7 +707,7 @@ void Cop1::cvtdw(const u32 instr) {
}
void Cop1::cvtdl(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
@@ -725,7 +725,7 @@ void Cop1::cvtdl(const u32 instr) {
}
void Cop1::cvtld(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -737,7 +737,7 @@ void Cop1::cvtld(const u32 instr) {
template <typename T, bool quiet, bool cf>
bool Cop1::XORDERED(const T fs, const T ft) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (std::isnan(fs) || std::isnan(ft)) {
if (std::isnan(fs) && (!quiet || isqnan(fs)) && SetCauseInvalid()) {
regs.cop0.FireException(ExceptionCode::FloatingPointError, 0, regs.oldPC);
@@ -759,7 +759,7 @@ bool Cop1::XORDERED(const T fs, const T ft) {
template <typename T>
void Cop1::cf(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
@@ -771,7 +771,7 @@ void Cop1::cf(const u32 instr) {
template <typename T>
void Cop1::cun(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const T fs = FGR_S<T>(regs.cop0.status, FS(instr));
@@ -782,7 +782,7 @@ void Cop1::cun(const u32 instr) {
template <typename T>
void Cop1::ceq(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const T fs = FGR_S<T>(regs.cop0.status, FS(instr));
@@ -794,7 +794,7 @@ void Cop1::ceq(const u32 instr) {
template <typename T>
void Cop1::cueq(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const T fs = FGR_S<T>(regs.cop0.status, FS(instr));
@@ -806,7 +806,7 @@ void Cop1::cueq(const u32 instr) {
template <typename T>
void Cop1::colt(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const T fs = FGR_S<T>(regs.cop0.status, FS(instr));
@@ -818,7 +818,7 @@ void Cop1::colt(const u32 instr) {
template <typename T>
void Cop1::cult(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const T fs = FGR_S<T>(regs.cop0.status, FS(instr));
@@ -830,7 +830,7 @@ void Cop1::cult(const u32 instr) {
template <typename T>
void Cop1::cole(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const T fs = FGR_S<T>(regs.cop0.status, FS(instr));
@@ -842,7 +842,7 @@ void Cop1::cole(const u32 instr) {
template <typename T>
void Cop1::cule(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const T fs = FGR_S<T>(regs.cop0.status, FS(instr));
@@ -854,7 +854,7 @@ void Cop1::cule(const u32 instr) {
template <typename T>
void Cop1::csf(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const T fs = FGR_S<T>(regs.cop0.status, FS(instr));
@@ -865,7 +865,7 @@ void Cop1::csf(const u32 instr) {
template <typename T>
void Cop1::cngle(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const T fs = FGR_S<T>(regs.cop0.status, FS(instr));
@@ -876,7 +876,7 @@ void Cop1::cngle(const u32 instr) {
template <typename T>
void Cop1::cseq(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const T fs = FGR_S<T>(regs.cop0.status, FS(instr));
@@ -888,7 +888,7 @@ void Cop1::cseq(const u32 instr) {
template <typename T>
void Cop1::cngl(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const T fs = FGR_S<T>(regs.cop0.status, FS(instr));
@@ -900,7 +900,7 @@ void Cop1::cngl(const u32 instr) {
template <typename T>
void Cop1::clt(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const T fs = FGR_S<T>(regs.cop0.status, FS(instr));
@@ -912,7 +912,7 @@ void Cop1::clt(const u32 instr) {
template <typename T>
void Cop1::cnge(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const T fs = FGR_S<T>(regs.cop0.status, FS(instr));
@@ -924,7 +924,7 @@ void Cop1::cnge(const u32 instr) {
template <typename T>
void Cop1::cle(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const T fs = FGR_S<T>(regs.cop0.status, FS(instr));
@@ -936,7 +936,7 @@ void Cop1::cle(const u32 instr) {
template <typename T>
void Cop1::cngt(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const T fs = FGR_S<T>(regs.cop0.status, FS(instr));
@@ -980,7 +980,7 @@ template void Cop1::cle<double>(u32 instr);
template void Cop1::cngt<double>(u32 instr);
void Cop1::divs(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -994,7 +994,7 @@ void Cop1::divs(const u32 instr) {
}
void Cop1::divd(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -1008,7 +1008,7 @@ void Cop1::divd(const u32 instr) {
}
void Cop1::muls(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -1022,7 +1022,7 @@ void Cop1::muls(const u32 instr) {
}
void Cop1::muld(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -1036,7 +1036,7 @@ void Cop1::muld(const u32 instr) {
}
void Cop1::subs(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -1050,7 +1050,7 @@ void Cop1::subs(const u32 instr) {
}
void Cop1::subd(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -1066,14 +1066,14 @@ void Cop1::subd(const u32 instr) {
void Cop1::movs(const u32 instr) { movd(instr); }
void Cop1::movd(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable<true>())
return;
FGR_D<double>(regs.cop0.status, FD(instr)) = FGR_S<double>(regs.cop0.status, FS(instr));
}
void Cop1::negs(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -1086,7 +1086,7 @@ void Cop1::negs(const u32 instr) {
}
void Cop1::negd(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -1099,7 +1099,7 @@ void Cop1::negd(const u32 instr) {
}
void Cop1::sqrts(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -1112,7 +1112,7 @@ void Cop1::sqrts(const u32 instr) {
}
void Cop1::sqrtd(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -1125,7 +1125,7 @@ void Cop1::sqrtd(const u32 instr) {
}
void Cop1::roundls(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -1140,7 +1140,7 @@ void Cop1::roundls(const u32 instr) {
}
void Cop1::roundld(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -1155,7 +1155,7 @@ void Cop1::roundld(const u32 instr) {
}
void Cop1::roundws(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -1170,7 +1170,7 @@ void Cop1::roundws(const u32 instr) {
}
void Cop1::roundwd(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -1185,7 +1185,7 @@ void Cop1::roundwd(const u32 instr) {
}
void Cop1::floorls(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -1196,7 +1196,7 @@ void Cop1::floorls(const u32 instr) {
}
void Cop1::floorld(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -1207,7 +1207,7 @@ void Cop1::floorld(const u32 instr) {
}
void Cop1::floorws(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -1218,7 +1218,7 @@ void Cop1::floorws(const u32 instr) {
}
void Cop1::floorwd(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -1229,7 +1229,7 @@ void Cop1::floorwd(const u32 instr) {
}
void Cop1::truncws(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -1244,7 +1244,7 @@ void Cop1::truncws(const u32 instr) {
}
void Cop1::truncwd(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -1259,7 +1259,7 @@ void Cop1::truncwd(const u32 instr) {
}
void Cop1::truncls(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<float>(regs.cop0.status, FS(instr));
@@ -1274,7 +1274,7 @@ void Cop1::truncls(const u32 instr) {
}
void Cop1::truncld(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
const auto fs = FGR_S<double>(regs.cop0.status, FS(instr));
@@ -1289,8 +1289,8 @@ void Cop1::truncld(const u32 instr) {
}
void Cop1::lwc1(u32 instr) {
Mem& mem = Core::GetInstance().cpu->GetMem();
Registers& regs = Core::GetInstance().cpu->GetRegs();
Mem& mem = Core::GetMem();
Registers& regs = Core::GetRegs();
const u64 addr = static_cast<s64>(static_cast<s16>(instr)) + regs.Read<s64>(BASE(instr));
if (u32 physical; !regs.cop0.MapVAddr(Cop0::LOAD, addr, physical)) {
@@ -1303,8 +1303,8 @@ void Cop1::lwc1(u32 instr) {
}
void Cop1::swc1(u32 instr) {
Mem& mem = Core::GetInstance().cpu->GetMem();
Registers& regs = Core::GetInstance().cpu->GetRegs();
Mem& mem = Core::GetMem();
Registers& regs = Core::GetRegs();
const u64 addr = static_cast<s64>(static_cast<s16>(instr)) + regs.Read<s64>(BASE(instr));
if (u32 physical; !regs.cop0.MapVAddr(Cop0::STORE, addr, physical)) {
@@ -1316,8 +1316,8 @@ void Cop1::swc1(u32 instr) {
}
void Cop1::ldc1(u32 instr) {
Mem& mem = Core::GetInstance().cpu->GetMem();
Registers& regs = Core::GetInstance().cpu->GetRegs();
Mem& mem = Core::GetMem();
Registers& regs = Core::GetRegs();
const u64 addr = static_cast<s64>(static_cast<s16>(instr)) + regs.Read<s64>(BASE(instr));
if (u32 physical; !regs.cop0.MapVAddr(Cop0::LOAD, addr, physical)) {
@@ -1330,8 +1330,8 @@ void Cop1::ldc1(u32 instr) {
}
void Cop1::sdc1(u32 instr) {
Mem& mem = Core::GetInstance().cpu->GetMem();
Registers& regs = Core::GetInstance().cpu->GetRegs();
Mem& mem = Core::GetMem();
Registers& regs = Core::GetRegs();
const u64 addr = static_cast<s64>(static_cast<s16>(instr)) + regs.Read<s64>(BASE(instr));
if (u32 physical; !regs.cop0.MapVAddr(Cop0::STORE, addr, physical)) {
@@ -1343,7 +1343,7 @@ void Cop1::sdc1(u32 instr) {
}
void Cop1::unimplemented() {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable())
return;
SetCauseUnimplemented();
@@ -1351,28 +1351,28 @@ void Cop1::unimplemented() {
}
void Cop1::mfc1(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable<true>())
return;
regs.Write(RT(instr), FGR_T<s32>(regs.cop0.status, FS(instr)));
}
void Cop1::dmfc1(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable<true>())
return;
regs.Write(RT(instr), FGR_S<s64>(regs.cop0.status, FS(instr)));
}
void Cop1::mtc1(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable<true>())
return;
FGR_T<s32>(regs.cop0.status, FS(instr)) = regs.Read<s64>(RT(instr));
}
void Cop1::dmtc1(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
if (!CheckFPUUsable<true>())
return;
FGR_S<u64>(regs.cop0.status, FS(instr)) = regs.Read<s64>(RT(instr));

View File

@@ -1,5 +1,5 @@
#include <Core.hpp>
#include <CpuDefinitions.hpp>
#include <core/Interpreter.hpp>
#include <log.hpp>
namespace n64 {

View File

@@ -824,7 +824,7 @@ void Interpreter::mtlo(const u32 instr) { regs.lo = regs.Read<s64>(RS(instr)); }
void Interpreter::mthi(const u32 instr) { regs.hi = regs.Read<s64>(RS(instr)); }
void Interpreter::trap(const bool cond) const {
Cop0& cop0 = Core::GetInstance().cpu->GetRegs().cop0;
Cop0& cop0 = Core::GetRegs().cop0;
if (cond) {
cop0.FireException(ExceptionCode::Trap, 0, regs.oldPC);
}

View File

@@ -1,5 +1,4 @@
#include <JIT.hpp>
#include <jit/helpers.hpp>
#include <Core.hpp>
#define check_signed_overflow(op1, op2, res) (((~((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1)
#define check_signed_underflow(op1, op2, res) (((((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1)

View File

@@ -35,7 +35,7 @@ auto AI::Read(const u32 addr) const -> u32 {
}
void AI::Write(const u32 addr, const u32 val) {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
switch (addr) {
case 0x04500000:
if (dmaCount < 2) {
@@ -80,7 +80,7 @@ void AI::Write(const u32 addr, const u32 val) {
}
void AI::Step(const u32 cpuCycles, const float volumeL, const float volumeR) {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
cycles += cpuCycles;
while (cycles > dac.period) {
if (dmaCount == 0) {

View File

@@ -52,7 +52,7 @@ void MI::InterruptLower(const Interrupt intr) {
}
void MI::UpdateInterrupt() const {
n64::Registers& regs = n64::Core::GetInstance().cpu->GetRegs();
n64::Registers& regs = n64::Core::GetRegs();
const bool interrupt = miIntr.raw & miIntrMask.raw;
regs.cop0.cause.ip2 = interrupt;
}

View File

@@ -37,7 +37,7 @@ bool PI::WriteLatch(u32 value) {
}
bool PI::ReadLatch() {
n64::Registers& regs = n64::Core::GetInstance().cpu->GetRegs();
n64::Registers& regs = n64::Core::GetRegs();
if (ioBusy) [[unlikely]] {
ioBusy = false;
regs.CpuStall(Scheduler::GetInstance().Remove(PI_BUS_WRITE_COMPLETE));
@@ -48,7 +48,7 @@ bool PI::ReadLatch() {
template <>
auto PI::BusRead<u8, true>(u32 addr) -> u8 {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
switch (addr) {
case REGION_PI_UNKNOWN:
panic("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, "
@@ -83,7 +83,7 @@ auto PI::BusRead<u8, true>(u32 addr) -> u8 {
template <>
auto PI::BusRead<u8, false>(u32 addr) -> u8 {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
if (!ReadLatch()) [[unlikely]] {
return latch >> 24;
}
@@ -123,7 +123,7 @@ auto PI::BusRead<u8, false>(u32 addr) -> u8 {
template <>
void PI::BusWrite<u8, true>(u32 addr, u32 val) {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
switch (addr) {
case REGION_PI_UNKNOWN:
panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
@@ -161,7 +161,7 @@ void PI::BusWrite<u8, false>(u32 addr, u32 val) {
template <>
auto PI::BusRead<u16, false>(u32 addr) -> u16 {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
if (!ReadLatch()) [[unlikely]] {
return latch >> 16;
}
@@ -231,7 +231,7 @@ void PI::BusWrite<u16, true>(u32 addr, u32 val) {
template <>
auto PI::BusRead<u32, false>(u32 addr) -> u32 {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
if (!ReadLatch()) [[unlikely]] {
return latch;
}
@@ -284,7 +284,7 @@ auto PI::BusRead<u32, true>(u32 addr) -> u32 {
template <>
void PI::BusWrite<u32, false>(u32 addr, u32 val) {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
switch (addr) {
case REGION_PI_UNKNOWN:
if (!WriteLatch(val)) [[unlikely]] {
@@ -348,7 +348,7 @@ void PI::BusWrite<u32, true>(u32 addr, u32 val) {
template <>
auto PI::BusRead<u64, false>(u32 addr) -> u64 {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
if (!ReadLatch()) [[unlikely]] {
return static_cast<u64>(latch) << 32;
}
@@ -409,7 +409,7 @@ void PI::BusWrite<true>(u32 addr, u64 val) {
}
auto PI::Read(u32 addr) const -> u32 {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
switch (addr) {
case 0x04600000:
return dramAddr & 0x00FFFFFE;
@@ -498,7 +498,7 @@ u32 PI::AccessTiming(const u8 domain, const u32 length) const {
// rdram -> cart
template <>
void PI::DMA<false>() {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
const s32 len = rdLen + 1;
trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr);
@@ -522,7 +522,7 @@ void PI::DMA<false>() {
// cart -> rdram
template <>
void PI::DMA<true>() {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
const s32 len = wrLen + 1;
trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr);
@@ -544,7 +544,7 @@ void PI::DMA<true>() {
}
void PI::Write(u32 addr, u32 val) {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
MI &mi = mem.mmio.mi;
switch (addr) {
case 0x04600000:

View File

@@ -166,7 +166,7 @@ FORCE_INLINE u8 DataCRC(const u8 *data) {
#define BCD_DECODE(x) (((x) >> 4) * 10 + ((x) & 15))
void PIF::ConfigureJoyBusFrame() {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
channel = 0;
int i = 0;
while (i < 63) {
@@ -332,7 +332,7 @@ void PIF::MempakWrite(u8 *cmd, u8 *res) {
}
void PIF::EepromRead(const u8 *cmd, u8 *res) const {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
assert(mem.saveType == SAVE_EEPROM_4k || mem.saveType == SAVE_EEPROM_16k);
if (channel == 4) {
const u8 offset = cmd[3];
@@ -347,7 +347,7 @@ void PIF::EepromRead(const u8 *cmd, u8 *res) const {
}
void PIF::EepromWrite(const u8 *cmd, u8 *res) {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
assert(mem.saveType == SAVE_EEPROM_4k || mem.saveType == SAVE_EEPROM_16k);
if (channel == 4) {
const u8 offset = cmd[3];
@@ -364,8 +364,8 @@ void PIF::EepromWrite(const u8 *cmd, u8 *res) {
}
void PIF::HLE(const bool pal, const CICType cicType) const {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Registers& regs = n64::Core::GetInstance().cpu->GetRegs();
n64::Mem& mem = n64::Core::GetMem();
n64::Registers& regs = n64::Core::GetRegs();
mem.Write<u32>(PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]);
switch (cicType) {
@@ -631,7 +631,7 @@ void PIF::HLE(const bool pal, const CICType cicType) const {
}
void PIF::Execute() const {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
const CICType cicType = mem.rom.cicType;
const bool pal = mem.rom.pal;
mem.Write<u32>(PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]);

View File

@@ -13,7 +13,7 @@ void SI::Reset() {
}
auto SI::Read(u32 addr) const -> u32 {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
switch (addr) {
case 0x04800000:
return dramAddr;
@@ -39,7 +39,7 @@ auto SI::Read(u32 addr) const -> u32 {
// pif -> rdram
template <>
void SI::DMA<true>() {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
pif.ProcessCommands();
for (int i = 0; i < 64; i++) {
mem.mmio.rdp.WriteRDRAM<u8>(dramAddr + i, pif.Read(pifAddr + i));
@@ -50,7 +50,7 @@ void SI::DMA<true>() {
// rdram -> pif
template <>
void SI::DMA<false>() {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
for (int i = 0; i < 64; i++) {
pif.Write(pifAddr + i, mem.mmio.rdp.ReadRDRAM<u8>(dramAddr + i));
}
@@ -58,7 +58,7 @@ void SI::DMA<false>() {
}
void SI::DMA() {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
status.dmaBusy = false;
if (toDram)
DMA<true>();
@@ -68,7 +68,7 @@ void SI::DMA() {
}
void SI::Write(u32 addr, u32 val) {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
switch (addr) {
case 0x04800000:
dramAddr = val & RDRAM_DSIZE;

View File

@@ -62,7 +62,7 @@ u32 VI::Read(const u32 paddr) const {
}
void VI::Write(const u32 paddr, const u32 val) {
n64::Mem& mem = n64::Core::GetInstance().cpu->GetMem();
n64::Mem& mem = n64::Core::GetMem();
switch (paddr) {
case 0x04400000:
status.raw = val;

View File

@@ -370,7 +370,7 @@ FORCE_INLINE bool Is64BitAddressing(const Cop0 &cp0, const u64 addr) {
}
void Cop0::FireException(const ExceptionCode code, const int cop, s64 pc) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
const bool old_exl = status.exl;
if (!status.exl) {
@@ -452,7 +452,7 @@ ExceptionCode Cop0::GetTLBExceptionCode(const TLBError error, const TLBAccessTyp
}
void Cop0::decode(const u32 instr) {
Registers& regs = Core::GetInstance().cpu->GetRegs();
Registers& regs = Core::GetRegs();
const u8 mask_cop = instr >> 21 & 0x1F;
const u8 mask_cop2 = instr & 0x3F;
switch (mask_cop) {

View File

@@ -3,7 +3,7 @@
#include <core/JIT.hpp>
namespace n64 {
Registers::Registers(JIT *jit) : jit(jit) { Reset(); }
Registers::Registers() { Reset(); }
void Registers::Reset() {
hi = 0;

View File

@@ -4,12 +4,12 @@
#include <backend/core/registers/Cop1.hpp>
namespace n64 {
struct JIT;
struct Registers {
Registers(JIT *jit = nullptr);
Registers();
void Reset();
void SetPC64(s64);
void SetPC32(s32);
void SetJIT(JIT* jit) { this->jit = jit; }
[[nodiscard]] bool IsRegConstant(const u32 index) const {
if (index == 0)

View File

@@ -365,7 +365,7 @@ FORCE_INLINE void cop0(Mem &mem, const u32 instr) {
}
void RSP::Exec(const u32 instr) {
Mem& mem = Core::GetInstance().cpu->GetMem();
Mem& mem = Core::GetMem();
MMIO &mmio = mem.mmio;
MI &mi = mmio.mi;
switch (const u8 mask = instr >> 26 & 0x3F) {

View File

@@ -1802,7 +1802,7 @@ void RSP::vzero(const u32 instr) {
void RSP::mfc0(const RDP &rdp, const u32 instr) { gpr[RT(instr)] = GetCop0Reg(*this, rdp, RD(instr)); }
void RSP::mtc0(const u32 instr) const {
Mem& mem = Core::GetInstance().cpu->GetMem();
Mem& mem = Core::GetMem();
SetCop0Reg(mem, RD(instr), gpr[RT(instr)]);
}

View File

@@ -58,8 +58,6 @@ void InstructionFunc(s64, s64, Disassembler::DisassemblyResult& disasm) {
void CommentFunc(s64, s64, Disassembler::DisassemblyResult& disasm) {
n64::Core& core = n64::Core::GetInstance();
n64::Mem& mem = core.cpu->GetMem();
n64::Registers& regs = core.cpu->GetRegs();
if(!disasm.success) {
ImGui::TextColored(ImColor(0xff71efe5), "");
@@ -92,10 +90,10 @@ void CommentFunc(s64, s64, Disassembler::DisassemblyResult& disasm) {
ImGui::TableNextRow();
for(u32 col = 0; col < 16; col+=4) {
u32 paddr;
if(!regs.cop0.MapVAddr(n64::Cop0::LOAD, vaddr+row*0x10+col, paddr))
if(!n64::Core::GetRegs().cop0.MapVAddr(n64::Cop0::LOAD, vaddr+row*0x10+col, paddr))
continue;
u32 val = mem.Read<u32>(paddr);
u32 val = n64::Core::GetMem().Read<u32>(paddr);
ImGui::TableSetColumnIndex(col+0);
ImGui::Text("%02X", (val >> 24) & 0xff);
@@ -114,7 +112,7 @@ void CommentFunc(s64, s64, Disassembler::DisassemblyResult& disasm) {
bool Debugger::render() {
n64::Core& core = n64::Core::GetInstance();
n64::Registers& regs = core.cpu->GetRegs();
n64::Registers& regs = core.GetRegs();
if(!enabled)
return false;

View File

@@ -35,7 +35,7 @@ void KaizenGui::QueryDevices(SDL_Event event) {
void KaizenGui::HandleInput(SDL_Event event) {
n64::Core& core = n64::Core::GetInstance();
n64::PIF &pif = core.cpu->GetMem().mmio.si.pif;
n64::PIF &pif = core.GetMem().mmio.si.pif;
switch(event.type) {
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
if(!gamepad)
@@ -261,7 +261,8 @@ void KaizenGui::RenderUI() {
void KaizenGui::LoadROM(const std::string &path) noexcept {
n64::Core& core = n64::Core::GetInstance();
core.LoadROM(path);
const auto gameNameDB = core.cpu->GetMem().rom.gameNameDB;
const auto gameNameDB = core.GetMem().rom.gameNameDB;
SDL_SetWindowTitle(window.getHandle(), ("Kaizen - " + gameNameDB).c_str());
}
void KaizenGui::run() {
@@ -291,12 +292,7 @@ void KaizenGui::run() {
}
void KaizenGui::LoadTAS(const std::string &path) const noexcept {
n64::Core& core = n64::Core::GetInstance();
if (core.LoadTAS(fs::path(path))) {
const auto gameNameDB = core.cpu->GetMem().rom.gameNameDB;
const auto movieName = fs::path(path).stem().string();
return;
if (!n64::Core::GetInstance().LoadTAS(fs::path(path))) {
panic("Could not load TAS movie {}!", path);
}
panic("Could not load TAS movie {}!", path);
}

View File

@@ -8,5 +8,5 @@ RenderWidget::RenderWidget(SDL_Window* window) {
wsiPlatform = std::make_shared<SDLWSIPlatform>(window);
windowInfo = std::make_shared<SDLParallelRdpWindowInfo>(window);
n64::Core& core = n64::Core::GetInstance();
core.parallel.Init(wsiPlatform, windowInfo, core.cpu->GetMem().GetRDRAMPtr());
core.parallel.Init(wsiPlatform, windowInfo, core.GetMem().GetRDRAMPtr());
}

View File

@@ -54,11 +54,11 @@ struct Error {
};
template <class... Args>
std::string Format(Severity severity,
std::optional<u64> lastPC,
std::optional<MemoryAccess> memoryAccess,
std::optional<Type> type,
const std::format_string<Args...> fmt, Args... args) {
void Throw (Severity severity,
Type type,
std::optional<u64> lastPC,
std::optional<MemoryAccess> memoryAccess,
const std::format_string<Args...> fmt, Args... args) {
this->severity = severity;
this->lastPC = lastPC;
this->memoryAccess = memoryAccess;
@@ -74,11 +74,16 @@ struct Error {
return severity == NONE;
}
static Error& Get() {
static Error& GetInstance() {
static Error instance;
return instance;
}
static std::string Get() {
return GetInstance().err;
}
private:
std::string err;
Severity severity = NONE;
Type type = {};
std::optional<u64> lastPC = {};