Use virtual class for different cpu types rather than that hot mess with pointers and shiz

This commit is contained in:
CocoSimone
2023-02-19 22:14:59 +01:00
parent 24eac65357
commit f113db7059
26 changed files with 700 additions and 536 deletions

View File

@@ -9,63 +9,60 @@ Core::Core() {
if(SDL_GameControllerAddMappingsFromFile("resources/gamecontrollerdb.txt") < 0) { if(SDL_GameControllerAddMappingsFromFile("resources/gamecontrollerdb.txt") < 0) {
Util::print("Failed to load game controller DB\n"); Util::print("Failed to load game controller DB\n");
} }
Stop();
} }
void Core::Stop() { void Core::Stop() {
CpuReset(); cpu->Reset();
mem.Reset(); cpu->mem.Reset();
pause = true; pause = true;
romLoaded = false; romLoaded = false;
} }
CartInfo Core::LoadROM(const std::string& rom_) { CartInfo Core::LoadROM(const std::string& rom_) {
rom = rom_; rom = rom_;
CpuReset(); cpu->Reset();
mem.Reset(); cpu->mem.Reset();
pause = false; pause = false;
romLoaded = true; romLoaded = true;
CartInfo cartInfo = mem.LoadROM(rom); CartInfo cartInfo = cpu->mem.LoadROM(rom);
isPAL = cartInfo.isPAL; isPAL = cartInfo.isPAL;
mem.mmio.si.pif.ExecutePIF(mem, CpuGetRegs(), cartInfo); cpu->mem.mmio.si.pif.ExecutePIF(cpu->mem, cpu->regs, cartInfo);
return cartInfo; return cartInfo;
} }
void Core::Run(Window& window, float volumeL, float volumeR) { void Core::Run(Window& window, float volumeL, float volumeR) {
MMIO& mmio = mem.mmio; MMIO& mmio = cpu->mem.mmio;
Registers& regs = CpuGetRegs();
for(int field = 0; field < mmio.vi.numFields; field++) { for (int field = 0; field < mmio.vi.numFields; field++) {
int frameCycles = 0; int frameCycles = 0;
if(!pause && romLoaded) { if (!pause && romLoaded) {
for (int i = 0; i < mmio.vi.numHalflines; i++) { for (int i = 0; i < mmio.vi.numHalflines; i++) {
mmio.vi.current = (i << 1) + field; mmio.vi.current = (i << 1) + field;
if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) { if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) {
InterruptRaise(mmio.mi, regs, Interrupt::VI); InterruptRaise(mmio.mi, cpu->regs, Interrupt::VI);
} }
int cpuCount = CpuStep(*this); int cpuCount = cpu->Run();
frameCycles += cpuCount; frameCycles += cpuCount;
mmio.rsp.Run(cpuCount, cpu->regs, cpu->mem);
mmio.rsp.Run(cpuCount, regs, mem); mmio.ai.Step(cpu->mem, cpu->regs, cpuCount, volumeL, volumeR);
mmio.ai.Step(mem, regs, cpuCount, volumeL, volumeR); scheduler.tick(cpuCount, cpu->mem, cpu->regs);
scheduler.tick(cpuCount, mem, regs);
} }
if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) { if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) {
InterruptRaise(mmio.mi, regs, Interrupt::VI); InterruptRaise(mmio.mi, cpu->regs, Interrupt::VI);
} }
UpdateScreenParallelRdp(*this, window, GetVI()); UpdateScreenParallelRdp(*this, window, GetVI());
int missedCycles = N64_CYCLES_PER_FRAME(isPAL) - frameCycles; int missedCycles = N64_CYCLES_PER_FRAME(isPAL) - frameCycles;
mmio.ai.Step(mem, regs, missedCycles, volumeL, volumeR); mmio.ai.Step(cpu->mem, cpu->regs, missedCycles, volumeL, volumeR);
} else if(pause && romLoaded) { } else if (pause && romLoaded) {
UpdateScreenParallelRdp(*this, window, GetVI()); UpdateScreenParallelRdp(*this, window, GetVI());
} else if(pause && !romLoaded) { } else if (pause && !romLoaded) {
UpdateScreenParallelRdpNoGame(*this, window); UpdateScreenParallelRdpNoGame(*this, window);
} }
} }

View File

@@ -22,34 +22,7 @@ struct Core {
CartInfo LoadROM(const std::string&); CartInfo LoadROM(const std::string&);
void Run(Window&, float volumeL, float volumeR); void Run(Window&, float volumeL, float volumeR);
void TogglePause() { pause = !pause; } void TogglePause() { pause = !pause; }
VI& GetVI() { return mem.mmio.vi; } VI& GetVI() { return cpu->mem.mmio.vi; }
void CpuReset() const {
switch(cpuType) {
case CpuType::Dynarec: cpuDynarec->Reset(); break;
case CpuType::Interpreter: cpuInterp->Reset(); break;
case CpuType::NONE: break;
}
}
[[nodiscard]] Registers& CpuGetRegs() const {
switch(cpuType) {
case CpuType::Dynarec: return cpuDynarec->regs;
case CpuType::Interpreter: return cpuInterp->regs;
case CpuType::NONE:
Util::panic("BRUH\n");
}
}
static int CpuStep(Core& core) {
switch(core.cpuType) {
case CpuType::Dynarec:
return core.cpuDynarec->Step(core.mem);
case CpuType::Interpreter:
return core.cpuInterp->Run(core.mem);
case CpuType::NONE: return 0;
}
}
u32 breakpoint = 0; u32 breakpoint = 0;
@@ -58,10 +31,8 @@ struct Core {
bool romLoaded = false; bool romLoaded = false;
bool done = false; bool done = false;
std::string rom; std::string rom;
Mem mem;
CpuType cpuType = CpuType::NONE; CpuType cpuType = CpuType::NONE;
Interpreter* cpuInterp = nullptr; std::unique_ptr<BaseCPU> cpu;
JIT::Dynarec* cpuDynarec = nullptr;
Debugger debugger{*this}; Debugger debugger{*this};
}; };
} }

View File

@@ -0,0 +1,12 @@
#pragma once
#include <Registers.hpp>
namespace n64 {
struct BaseCPU {
virtual ~BaseCPU() {}
virtual void Reset() {}
virtual int Run() {}
Registers regs;
Mem mem;
};
}

View File

@@ -1,8 +1,10 @@
#include <Dynarec.hpp> #include <Core.hpp>
#include <Registers.hpp> #include <Registers.hpp>
#include <filesystem> #include <filesystem>
#include "Dynarec.hpp"
namespace n64::JIT {
namespace n64 {
namespace fs = std::filesystem; namespace fs = std::filesystem;
Dynarec::~Dynarec() { Dynarec::~Dynarec() {
@@ -97,8 +99,8 @@ void Dynarec::AllocateOuter(u32 pc) {
blockCache[pc >> 20] = (Fn*)bumpAlloc(0x1000 * sizeof(Fn)); blockCache[pc >> 20] = (Fn*)bumpAlloc(0x1000 * sizeof(Fn));
} }
int Dynarec::Step(Mem &mem) { int Dynarec::Run() {
instrInBlock = 0; /*instrInBlock = 0;
regs.gpr[0] = 0; regs.gpr[0] = 0;
regs.prevDelaySlot = regs.delaySlot; regs.prevDelaySlot = regs.delaySlot;
regs.delaySlot = false; regs.delaySlot = false;
@@ -128,6 +130,13 @@ int Dynarec::Step(Mem &mem) {
FireException(regs, ExceptionCode::Interrupt, 0, false); FireException(regs, ExceptionCode::Interrupt, 0, false);
} }
return instrInBlock; return instrInBlock;*/
Util::panic("JIT RECOMPILER NOT YET IMPLEMENTED!\n");
}
void Dynarec::Reset() {
code.reset();
regs.Reset();
InvalidateCache();
} }
} }

View File

@@ -2,11 +2,9 @@
#include <xbyak/xbyak.h> #include <xbyak/xbyak.h>
#include <backend/core/Mem.hpp> #include <backend/core/Mem.hpp>
#include <fstream> #include <fstream>
#include <Registers.hpp> #include <BaseCPU.hpp>
namespace n64 { struct Cop1; } namespace n64 {
namespace n64::JIT {
using namespace Xbyak; using namespace Xbyak;
using namespace Xbyak::util; using namespace Xbyak::util;
using Fn = void (*)(); using Fn = void (*)();
@@ -16,18 +14,13 @@ using Fn = void (*)();
#define CODECACHE_SIZE (2 << 25) #define CODECACHE_SIZE (2 << 25)
#define CODECACHE_OVERHEAD (CODECACHE_SIZE - 1_kb) #define CODECACHE_OVERHEAD (CODECACHE_SIZE - 1_kb)
struct Dynarec { struct Dynarec : BaseCPU {
Dynarec(); Dynarec();
~Dynarec(); ~Dynarec() override;
int Step(Mem&); int Run() override;
void Reset() { void Reset() override;
code.reset();
regs.Reset();
InvalidateCache();
}
u64 cop2Latch{}; u64 cop2Latch{};
CodeGenerator code; CodeGenerator code;
n64::Registers regs;
void InvalidatePage(u32); void InvalidatePage(u32);
void InvalidateCache(); void InvalidateCache();
private: private:

View File

@@ -1,4 +1,4 @@
#include <core/Interpreter.hpp> #include <Core.hpp>
#include <log.hpp> #include <log.hpp>
namespace n64 { namespace n64 {
@@ -21,10 +21,13 @@ inline void CheckCompareInterrupt(MI& mi, Registers& regs) {
} }
} }
int Interpreter::Run(Mem& mem) { void Interpreter::Reset() {
MMIO& mmio = mem.mmio; regs.Reset();
int count = 0; }
for(;count <= mmio.vi.cyclesPerHalfline; count++) {
int Interpreter::Run() {
int cycles = 0;
for(; cycles <= mem.mmio.vi.cyclesPerHalfline; cycles++) {
CheckCompareInterrupt(mem.mmio.mi, regs); CheckCompareInterrupt(mem.mmio.mi, regs);
regs.prevDelaySlot = regs.delaySlot; regs.prevDelaySlot = regs.delaySlot;
@@ -34,23 +37,23 @@ int Interpreter::Run(Mem& mem) {
if(!MapVAddr(regs, LOAD, regs.pc, paddr)) { if(!MapVAddr(regs, LOAD, regs.pc, paddr)) {
HandleTLBException(regs, regs.pc); HandleTLBException(regs, regs.pc);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false);
return count; return cycles;
} }
u32 instruction = mem.Read32(regs, paddr); u32 instruction = mem.Read32(regs, paddr);
if(ShouldServiceInterrupt(regs)) { if(ShouldServiceInterrupt(regs)) {
FireException(regs, ExceptionCode::Interrupt, 0, false); FireException(regs, ExceptionCode::Interrupt, 0, false);
return count; return cycles;
} }
regs.oldPC = regs.pc; regs.oldPC = regs.pc;
regs.pc = regs.nextPC; regs.pc = regs.nextPC;
regs.nextPC += 4; regs.nextPC += 4;
Exec(mem, instruction); Exec(instruction);
} }
return count; return cycles;
} }
} }

View File

@@ -2,16 +2,15 @@
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
#include <Mem.hpp> #include <Mem.hpp>
#include <vector> #include <vector>
#include <BaseCPU.hpp>
namespace n64 { namespace n64 {
struct Interpreter { struct Core;
struct Interpreter : BaseCPU {
Interpreter() = default; Interpreter() = default;
~Interpreter() = default; ~Interpreter() = default;
int Run(Mem&); int Run() override;
void Reset() { void Reset() override;
regs.Reset();
}
Registers regs;
private: private:
u64 cop2Latch{}; u64 cop2Latch{};
friend struct Cop1; friend struct Cop1;
@@ -19,7 +18,7 @@ private:
void cop2Decode(u32); void cop2Decode(u32);
void special(u32); void special(u32);
void regimm(u32); void regimm(u32);
void Exec(Mem&, u32); void Exec(u32);
void add(u32); void add(u32);
void addu(u32); void addu(u32);
void addi(u32); void addi(u32);
@@ -58,19 +57,19 @@ private:
void jal(u32); void jal(u32);
void jalr(u32); void jalr(u32);
void lui(u32); void lui(u32);
void lbu(Mem&, u32); void lbu(u32);
void lb(Mem&, u32); void lb(u32);
void ld(Mem&, u32); void ld(u32);
void ldl(Mem&, u32); void ldl(u32);
void ldr(Mem&, u32); void ldr(u32);
void lh(Mem&, u32); void lh(u32);
void lhu(Mem&, u32); void lhu(u32);
void ll(Mem&, u32); void ll(u32);
void lld(Mem&, u32); void lld(u32);
void lw(Mem&, u32); void lw(u32);
void lwl(Mem&, u32); void lwl(u32);
void lwu(Mem&, u32); void lwu(u32);
void lwr(Mem&, u32); void lwr(u32);
void mfhi(u32); void mfhi(u32);
void mflo(u32); void mflo(u32);
void mult(u32); void mult(u32);
@@ -78,16 +77,16 @@ private:
void mthi(u32); void mthi(u32);
void mtlo(u32); void mtlo(u32);
void nor(u32); void nor(u32);
void sb(Mem&, u32); void sb(u32);
void sc(Mem&, u32); void sc(u32);
void scd(Mem&, u32); void scd(u32);
void sd(Mem&, u32); void sd(u32);
void sdl(Mem&, u32); void sdl(u32);
void sdr(Mem&, u32); void sdr(u32);
void sh(Mem&, u32); void sh(u32);
void sw(Mem&, u32); void sw(u32);
void swl(Mem&, u32); void swl(u32);
void swr(Mem&, u32); void swr(u32);
void slti(u32); void slti(u32);
void sltiu(u32); void sltiu(u32);
void slt(u32); void slt(u32);

View File

@@ -223,22 +223,22 @@ u64 Mem::Read64(n64::Registers &regs, u32 paddr) {
} }
} }
void Mem::Write8(Registers& regs, n64::JIT::Dynarec& dyn, u32 paddr, u32 val) { void Mem::Write8(Registers& regs, n64::Dynarec& dyn, u32 paddr, u32 val) {
dyn.InvalidatePage(BYTE_ADDRESS(paddr)); dyn.InvalidatePage(BYTE_ADDRESS(paddr));
return Write8(regs, paddr, val); return Write8(regs, paddr, val);
} }
void Mem::Write16(Registers& regs, n64::JIT::Dynarec& dyn, u32 paddr, u32 val) { void Mem::Write16(Registers& regs, n64::Dynarec& dyn, u32 paddr, u32 val) {
dyn.InvalidatePage(HALF_ADDRESS(paddr)); dyn.InvalidatePage(HALF_ADDRESS(paddr));
return Write16(regs, paddr, val); return Write16(regs, paddr, val);
} }
void Mem::Write32(Registers& regs, n64::JIT::Dynarec& dyn, u32 paddr, u32 val) { void Mem::Write32(Registers& regs, n64::Dynarec& dyn, u32 paddr, u32 val) {
dyn.InvalidatePage(paddr); dyn.InvalidatePage(paddr);
return Write32(regs, paddr, val); return Write32(regs, paddr, val);
} }
void Mem::Write64(Registers& regs, n64::JIT::Dynarec& dyn, u32 paddr, u64 val) { void Mem::Write64(Registers& regs, n64::Dynarec& dyn, u32 paddr, u64 val) {
dyn.InvalidatePage(paddr); dyn.InvalidatePage(paddr);
return Write64(regs, paddr, val); return Write64(regs, paddr, val);
} }

View File

@@ -15,9 +15,7 @@ struct CartInfo {
u32 crc; u32 crc;
}; };
namespace JIT {
struct Dynarec; struct Dynarec;
}
struct Mem { struct Mem {
~Mem() { ~Mem() {
@@ -34,10 +32,10 @@ struct Mem {
u16 Read16(Registers&, u32); u16 Read16(Registers&, u32);
u32 Read32(Registers&, u32); u32 Read32(Registers&, u32);
u64 Read64(Registers&, u32); u64 Read64(Registers&, u32);
void Write8(Registers&, JIT::Dynarec&, u32, u32); void Write8(Registers&, Dynarec&, u32, u32);
void Write16(Registers&, JIT::Dynarec&, u32, u32); void Write16(Registers&, Dynarec&, u32, u32);
void Write32(Registers&, JIT::Dynarec&, u32, u32); void Write32(Registers&, Dynarec&, u32, u32);
void Write64(Registers&, JIT::Dynarec&, u32, u64); void Write64(Registers&, Dynarec&, u32, u64);
void Write8(Registers&, u32, u32); void Write8(Registers&, u32, u32);
void Write16(Registers&, u32, u32); void Write16(Registers&, u32, u32);
void Write32(Registers&, u32, u32); void Write32(Registers&, u32, u32);

View File

@@ -1,6 +1,6 @@
#include <core/Dynarec.hpp> #include <core/Dynarec.hpp>
namespace n64::JIT { namespace n64 {
void Dynarec::InvalidatePage(u32 paddr) { void Dynarec::InvalidatePage(u32 paddr) {
blockCache[paddr >> 20] = nullptr; blockCache[paddr >> 20] = nullptr;
} }

View File

@@ -2,8 +2,8 @@
#include <Registers.hpp> #include <Registers.hpp>
#include <dynarec/cop/cop0instructions.hpp> #include <dynarec/cop/cop0instructions.hpp>
namespace n64::JIT { namespace n64 {
void cop0Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) { void cop0Decode(Registers& regs, Dynarec& cpu, u32 instr) {
u8 mask_cop = (instr >> 21) & 0x1F; u8 mask_cop = (instr >> 21) & 0x1F;
u8 mask_cop2 = instr & 0x3F; u8 mask_cop2 = instr & 0x3F;
Xbyak::CodeGenerator& code = cpu.code; Xbyak::CodeGenerator& code = cpu.code;
@@ -36,14 +36,13 @@ void cop0Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) {
code.call(code.rax); code.call(code.rax);
break; break;
case 0x02: case 0x02:
code.and_(code.dword[code.rdi + offsetof(n64::Registers, cop0.index)], 0x3F); code.and_(code.dword[code.rdi + offsetof(Registers, cop0.index)], 0x3F);
code.mov(code.rsi, code.dword[code.rdi]); code.mov(code.rsi, code.dword[code.rdi]);
code.mov(code.rax, (u64)tlbw); code.mov(code.rax, (u64)tlbw);
code.call(code.rax); code.call(code.rax);
break; break;
case 0x06: case 0x06:
code.mov(code.rax, (u64)regs.cop0.GetRandom()); code.mov(code.rax, (u64)regs.cop0.GetRandom());
code.call(code.rax);
code.mov(code.rsi, code.rax); code.mov(code.rsi, code.rax);
code.mov(code.rax, (u64)tlbw); code.mov(code.rax, (u64)tlbw);
code.call(code.rax); code.call(code.rax);

View File

@@ -3,8 +3,5 @@
namespace n64 { namespace n64 {
struct Registers; struct Registers;
} void cop0Decode(Registers&, Dynarec& cpu, u32 instr);
namespace n64::JIT {
void cop0Decode(n64::Registers& regs, u32 instr, Dynarec& cpu);
} }

View File

@@ -2,24 +2,29 @@
#include <log.hpp> #include <log.hpp>
#include <Registers.hpp> #include <Registers.hpp>
namespace n64::JIT { namespace n64 {
void mtc0(n64::Registers& regs, u32 instr) { void mtc0(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop0.SetReg32(RD(instr), regs.gpr[RT(instr)]); regs.cop0.SetReg32(RD(instr), regs.gpr[RT(instr)]);
} }
void dmtc0(n64::Registers& regs, u32 instr) { void dmtc0(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop0.SetReg64(RD(instr), regs.gpr[RT(instr)]); regs.cop0.SetReg64(RD(instr), regs.gpr[RT(instr)]);
} }
void mfc0(n64::Registers& regs, u32 instr) { void mfc0(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.gpr[RT(instr)] = s32(regs.cop0.GetReg32(RD(instr))); regs.gpr[RT(instr)] = s32(regs.cop0.GetReg32(RD(instr)));
} }
void dmfc0(n64::Registers& regs, u32 instr) { void dmfc0(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.gpr[RT(instr)] = s64(regs.cop0.GetReg64(RD(instr))); regs.gpr[RT(instr)] = s64(regs.cop0.GetReg64(RD(instr)));
} }
void eret(n64::Registers& regs) { void eret(Dynarec& cpu) {
Registers& regs = cpu.regs;
if(regs.cop0.status.erl) { if(regs.cop0.status.erl) {
regs.SetPC64(regs.cop0.ErrorEPC); regs.SetPC64(regs.cop0.ErrorEPC);
regs.cop0.status.erl = false; regs.cop0.status.erl = false;
@@ -31,7 +36,8 @@ void eret(n64::Registers& regs) {
} }
void tlbr(n64::Registers& regs) { void tlbr(Dynarec& cpu) {
Registers& regs = cpu.regs;
u8 Index = regs.cop0.index & 0b111111; u8 Index = regs.cop0.index & 0b111111;
if (Index >= 32) { if (Index >= 32) {
Util::panic("TLBR with TLB index {}", Index); Util::panic("TLBR with TLB index {}", Index);
@@ -48,7 +54,8 @@ void tlbr(n64::Registers& regs) {
regs.cop0.pageMask.raw = entry.pageMask.raw; regs.cop0.pageMask.raw = entry.pageMask.raw;
} }
void tlbw(n64::Registers& regs, int index_) { void tlbw(Dynarec& cpu, int index_) {
Registers& regs = cpu.regs;
PageMask page_mask = regs.cop0.pageMask; PageMask page_mask = regs.cop0.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);
@@ -68,7 +75,8 @@ void tlbw(n64::Registers& regs, int index_) {
regs.cop0.tlb[index_].initialized = true; regs.cop0.tlb[index_].initialized = true;
} }
void tlbp(n64::Registers& regs) { void tlbp(Dynarec& cpu) {
Registers& regs = cpu.regs;
int match = -1; int match = -1;
TLBEntry* entry = TLBTryMatch(regs, regs.cop0.entryHi.raw, &match); TLBEntry* entry = TLBTryMatch(regs, regs.cop0.entryHi.raw, &match);
if(entry && match >= 0) { if(entry && match >= 0) {

View File

@@ -1,13 +1,13 @@
#pragma once #pragma once
#include <Dynarec.hpp> #include <Dynarec.hpp>
namespace n64::JIT { namespace n64 {
void mtc0(n64::Registers&, u32); void mtc0(Dynarec&, u32);
void dmtc0(n64::Registers&, u32); void dmtc0(Dynarec&, u32);
void mfc0(n64::Registers&, u32); void mfc0(Dynarec&, u32);
void dmfc0(n64::Registers&, u32); void dmfc0(Dynarec&, u32);
void eret(n64::Registers&); void eret(Dynarec&);
void tlbr(n64::Registers&); void tlbr(Dynarec&);
void tlbw(n64::Registers&, int); void tlbw(Dynarec&, int);
void tlbp(n64::Registers&); void tlbp(Dynarec&);
} }

View File

@@ -2,8 +2,8 @@
#include <dynarec/instructions.hpp> #include <dynarec/instructions.hpp>
#include <Registers.hpp> #include <Registers.hpp>
namespace n64::JIT { namespace n64 {
bool cop1Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) { bool cop1Decode(Registers& regs, Dynarec& cpu, u32 instr) {
Xbyak::CodeGenerator& code = cpu.code; Xbyak::CodeGenerator& code = cpu.code;
u8 mask_sub = (instr >> 21) & 0x1F; u8 mask_sub = (instr >> 21) & 0x1F;

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <dynarec/cop/cop1instructions.hpp> #include <dynarec/cop/cop1instructions.hpp>
namespace n64::JIT { namespace n64 {
bool cop1Decode(n64::Registers& regs, u32 instr, Dynarec& cpu); bool cop1Decode(Registers&, Dynarec& cpu, u32 instr);
} }

View File

@@ -4,7 +4,7 @@
#include <Cop1.hpp> #include <Cop1.hpp>
#include <Registers.hpp> #include <Registers.hpp>
namespace n64::JIT { namespace n64 {
inline int PushRoundingMode(const FCR31& fcr31) { inline int PushRoundingMode(const FCR31& fcr31) {
int og = fegetround(); int og = fegetround();
switch(fcr31.rounding_mode) { switch(fcr31.rounding_mode) {
@@ -29,67 +29,78 @@ inline int PushRoundingMode(const FCR31& fcr31) {
} \ } \
} while(0) } while(0)
void absd(n64::Registers& regs, u32 instr) { void absd(Dynarec& cpu, u32 instr) {
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); Registers& regs = cpu.regs;
auto fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), std::abs(fs)); regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), std::abs(fs));
} }
void abss(n64::Registers& regs, u32 instr) { void abss(Dynarec& cpu, u32 instr) {
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); Registers& regs = cpu.regs;
auto fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), std::abs(fs)); regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), std::abs(fs));
} }
void absw(n64::Registers& regs, u32 instr) { void absw(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
s32 fs = regs.cop1.GetReg<s32>(regs.cop0, FS(instr)); s32 fs = regs.cop1.GetReg<s32>(regs.cop0, FS(instr));
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), std::abs(fs)); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), std::abs(fs));
} }
void absl(n64::Registers& regs, u32 instr) { void absl(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
s64 fs = regs.cop1.GetReg<s64>(regs.cop0, FS(instr)); s64 fs = regs.cop1.GetReg<s64>(regs.cop0, FS(instr));
regs.cop1.SetReg(regs.cop0, FD(instr), std::abs(fs)); regs.cop1.SetReg(regs.cop0, FD(instr), std::abs(fs));
} }
void adds(n64::Registers& regs, u32 instr) { void adds(Dynarec& cpu, u32 instr) {
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); Registers& regs = cpu.regs;
float ft = regs.cop1.GetCop1Reg<float>(regs.cop0, FT(instr)); auto fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
auto ft = regs.cop1.GetCop1Reg<float>(regs.cop0, FT(instr));
checknanregs(fs, ft); checknanregs(fs, ft);
float result = fs + ft; float result = fs + ft;
regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), result); regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), result);
} }
void addd(n64::Registers& regs, u32 instr) { void addd(Dynarec& cpu, u32 instr) {
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); Registers& regs = cpu.regs;
double ft = regs.cop1.GetCop1Reg<double>(regs.cop0, FT(instr)); auto fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
auto ft = regs.cop1.GetCop1Reg<double>(regs.cop0, FT(instr));
checknanregs(fs, ft); checknanregs(fs, ft);
double result = fs + ft; double result = fs + ft;
regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), result); regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), result);
} }
void ceills(n64::Registers& regs, u32 instr) { void ceills(Dynarec& cpu, u32 instr) {
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); Registers& regs = cpu.regs;
auto fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
s64 result = std::ceil(fs); s64 result = std::ceil(fs);
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), result); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), result);
} }
void ceilws(n64::Registers& regs, u32 instr) { void ceilws(Dynarec& cpu, u32 instr) {
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); Registers& regs = cpu.regs;
auto fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
s32 result = std::ceil(fs); s32 result = std::ceil(fs);
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), result); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), result);
} }
void ceilld(n64::Registers& regs, u32 instr) { void ceilld(Dynarec& cpu, u32 instr) {
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); Registers& regs = cpu.regs;
auto fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
s64 result = std::ceil(fs); s64 result = std::ceil(fs);
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), result); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), result);
} }
void ceilwd(n64::Registers& regs, u32 instr) { void ceilwd(Dynarec& cpu, u32 instr) {
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); Registers& regs = cpu.regs;
auto fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
s32 result = std::ceil(fs); s32 result = std::ceil(fs);
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), result); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), result);
} }
void cfc1(n64::Registers& regs, u32 instr) { void cfc1(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
u8 fd = RD(instr); u8 fd = RD(instr);
s32 val = 0; s32 val = 0;
switch(fd) { switch(fd) {
@@ -100,7 +111,8 @@ void cfc1(n64::Registers& regs, u32 instr) {
regs.gpr[RT(instr)] = val; regs.gpr[RT(instr)] = val;
} }
void ctc1(n64::Registers& regs, u32 instr) { void ctc1(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
u8 fs = FS(instr); u8 fs = FS(instr);
u32 val = regs.gpr[RT(instr)]; u32 val = regs.gpr[RT(instr)];
switch(fs) { switch(fs) {
@@ -113,7 +125,8 @@ void ctc1(n64::Registers& regs, u32 instr) {
} }
} }
void cvtds(n64::Registers& regs, u32 instr) { void cvtds(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetCop1Reg<double>( regs.cop1.SetCop1Reg<double>(
regs.cop0, regs.cop0,
FD(instr), FD(instr),
@@ -124,7 +137,8 @@ void cvtds(n64::Registers& regs, u32 instr) {
); );
} }
void cvtsd(n64::Registers& regs, u32 instr) { void cvtsd(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetCop1Reg<float>( regs.cop1.SetCop1Reg<float>(
regs.cop0, regs.cop0,
FD(instr), FD(instr),
@@ -135,7 +149,8 @@ void cvtsd(n64::Registers& regs, u32 instr) {
); );
} }
void cvtwd(n64::Registers& regs, u32 instr) { void cvtwd(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetReg<u32>( regs.cop1.SetReg<u32>(
regs.cop0, regs.cop0,
FD(instr), FD(instr),
@@ -146,7 +161,8 @@ void cvtwd(n64::Registers& regs, u32 instr) {
); );
} }
void cvtws(n64::Registers& regs, u32 instr) { void cvtws(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetReg<u32>( regs.cop1.SetReg<u32>(
regs.cop0, regs.cop0,
FD(instr), FD(instr),
@@ -157,7 +173,8 @@ void cvtws(n64::Registers& regs, u32 instr) {
); );
} }
void cvtls(n64::Registers& regs, u32 instr) { void cvtls(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetReg<u64>( regs.cop1.SetReg<u64>(
regs.cop0, regs.cop0,
FD(instr), FD(instr),
@@ -168,7 +185,8 @@ void cvtls(n64::Registers& regs, u32 instr) {
); );
} }
void cvtsl(n64::Registers& regs, u32 instr) { void cvtsl(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetCop1Reg<float>( regs.cop1.SetCop1Reg<float>(
regs.cop0, regs.cop0,
FD(instr), FD(instr),
@@ -179,7 +197,8 @@ void cvtsl(n64::Registers& regs, u32 instr) {
); );
} }
void cvtdw(n64::Registers& regs, u32 instr) { void cvtdw(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetCop1Reg<double>( regs.cop1.SetCop1Reg<double>(
regs.cop0, regs.cop0,
FD(instr), FD(instr),
@@ -190,7 +209,8 @@ void cvtdw(n64::Registers& regs, u32 instr) {
); );
} }
void cvtsw(n64::Registers& regs, u32 instr) { void cvtsw(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetCop1Reg<float>( regs.cop1.SetCop1Reg<float>(
regs.cop0, regs.cop0,
FD(instr), FD(instr),
@@ -201,7 +221,8 @@ void cvtsw(n64::Registers& regs, u32 instr) {
); );
} }
void cvtdl(n64::Registers& regs, u32 instr) { void cvtdl(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetCop1Reg<double>( regs.cop1.SetCop1Reg<double>(
regs.cop0, regs.cop0,
FD(instr), FD(instr),
@@ -212,7 +233,8 @@ void cvtdl(n64::Registers& regs, u32 instr) {
); );
} }
void cvtld(n64::Registers& regs, u32 instr) { void cvtld(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetReg<u64>( regs.cop1.SetReg<u64>(
regs.cop0, regs.cop0,
FD(instr), FD(instr),
@@ -224,7 +246,8 @@ void cvtld(n64::Registers& regs, u32 instr) {
} }
template <typename T> template <typename T>
inline bool CalculateCondition(n64::Registers& regs, T fs, T ft, CompConds cond) { inline bool CalculateCondition(Dynarec& cpu, T fs, T ft, CompConds cond) {
Registers& regs = cpu.regs;
switch(cond) { switch(cond) {
case F: return false; case F: return false;
case UN: return std::isnan(fs) || std::isnan(ft); case UN: return std::isnan(fs) || std::isnan(ft);
@@ -242,82 +265,94 @@ inline bool CalculateCondition(n64::Registers& regs, T fs, T ft, CompConds cond)
return false; return false;
} }
return CalculateCondition(regs, fs, ft, static_cast<CompConds>(cond - 8)); return CalculateCondition(cpu, fs, ft, static_cast<CompConds>(cond - 8));
} }
} }
template <typename T> template <typename T>
void ccond(n64::Registers& regs, u32 instr, CompConds cond) { void ccond(Dynarec& cpu, u32 instr, CompConds cond) {
Registers& regs = cpu.regs;
T fs = regs.cop1.GetCop1Reg<T>(regs.cop0, FS(instr)); T fs = regs.cop1.GetCop1Reg<T>(regs.cop0, FS(instr));
T ft = regs.cop1.GetCop1Reg<T>(regs.cop0, FT(instr)); T ft = regs.cop1.GetCop1Reg<T>(regs.cop0, FT(instr));
regs.cop1.fcr31.compare = CalculateCondition(regs, fs, ft, cond); regs.cop1.fcr31.compare = CalculateCondition(cpu, fs, ft, cond);
} }
template void ccond<float>(n64::Registers& regs, u32 instr, CompConds cond); template void ccond<float>(Dynarec& cpu, u32 instr, CompConds cond);
template void ccond<double>(n64::Registers& regs, u32 instr, CompConds cond); template void ccond<double>(Dynarec& cpu, u32 instr, CompConds cond);
void divs(Registers &regs, u32 instr) { void divs(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
float ft = regs.cop1.GetCop1Reg<float>(regs.cop0, FT(instr)); float ft = regs.cop1.GetCop1Reg<float>(regs.cop0, FT(instr));
regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), fs / ft); regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), fs / ft);
} }
void divd(Registers &regs, u32 instr) { void divd(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
double ft = regs.cop1.GetCop1Reg<double>(regs.cop0, FT(instr)); double ft = regs.cop1.GetCop1Reg<double>(regs.cop0, FT(instr));
regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), fs / ft); regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), fs / ft);
} }
void muls(Registers &regs, u32 instr) { void muls(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
float ft = regs.cop1.GetCop1Reg<float>(regs.cop0, FT(instr)); float ft = regs.cop1.GetCop1Reg<float>(regs.cop0, FT(instr));
regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), fs * ft); regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), fs * ft);
} }
void muld(n64::Registers& regs, u32 instr) { void muld(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
double ft = regs.cop1.GetCop1Reg<double>(regs.cop0, FT(instr)); double ft = regs.cop1.GetCop1Reg<double>(regs.cop0, FT(instr));
regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), fs * ft); regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), fs * ft);
} }
void mulw(Registers &regs, u32 instr) { void mulw(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
u32 fs = regs.cop1.GetReg<u32>(regs.cop0, FS(instr)); u32 fs = regs.cop1.GetReg<u32>(regs.cop0, FS(instr));
u32 ft = regs.cop1.GetReg<u32>(regs.cop0, FT(instr)); u32 ft = regs.cop1.GetReg<u32>(regs.cop0, FT(instr));
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), fs * ft); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), fs * ft);
} }
void mull(Registers &regs, u32 instr) { void mull(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
u64 fs = regs.cop1.GetReg<u64>(regs.cop0, FS(instr)); u64 fs = regs.cop1.GetReg<u64>(regs.cop0, FS(instr));
u64 ft = regs.cop1.GetReg<u64>(regs.cop0, FT(instr)); u64 ft = regs.cop1.GetReg<u64>(regs.cop0, FT(instr));
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), fs * ft); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), fs * ft);
} }
void subs(Registers &regs, u32 instr) { void subs(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
float ft = regs.cop1.GetCop1Reg<float>(regs.cop0, FT(instr)); float ft = regs.cop1.GetCop1Reg<float>(regs.cop0, FT(instr));
regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), fs - ft); regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), fs - ft);
} }
void subd(Registers &regs, u32 instr) { void subd(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
double ft = regs.cop1.GetCop1Reg<double>(regs.cop0, FT(instr)); double ft = regs.cop1.GetCop1Reg<double>(regs.cop0, FT(instr));
regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), fs - ft); regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), fs - ft);
} }
void subw(Registers &regs, u32 instr) { void subw(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
u32 fs = regs.cop1.GetReg<u32>(regs.cop0, FS(instr)); u32 fs = regs.cop1.GetReg<u32>(regs.cop0, FS(instr));
u32 ft = regs.cop1.GetReg<u32>(regs.cop0, FT(instr)); u32 ft = regs.cop1.GetReg<u32>(regs.cop0, FT(instr));
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), fs - ft); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), fs - ft);
} }
void subl(Registers &regs, u32 instr) { void subl(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
u64 fs = regs.cop1.GetReg<u64>(regs.cop0, FS(instr)); u64 fs = regs.cop1.GetReg<u64>(regs.cop0, FS(instr));
u64 ft = regs.cop1.GetReg<u64>(regs.cop0, FT(instr)); u64 ft = regs.cop1.GetReg<u64>(regs.cop0, FT(instr));
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), fs - ft); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), fs - ft);
} }
void movs(n64::Registers& regs, u32 instr) { void movs(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetCop1Reg<float>( regs.cop1.SetCop1Reg<float>(
regs.cop0, regs.cop0,
FD(instr), FD(instr),
@@ -328,7 +363,8 @@ void movs(n64::Registers& regs, u32 instr) {
); );
} }
void movd(n64::Registers& regs, u32 instr) { void movd(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetCop1Reg<double>( regs.cop1.SetCop1Reg<double>(
regs.cop0, regs.cop0,
FD(instr), FD(instr),
@@ -339,7 +375,8 @@ void movd(n64::Registers& regs, u32 instr) {
); );
} }
void movw(n64::Registers& regs, u32 instr) { void movw(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetReg<u32>( regs.cop1.SetReg<u32>(
regs.cop0, regs.cop0,
FD(instr), FD(instr),
@@ -350,7 +387,8 @@ void movw(n64::Registers& regs, u32 instr) {
); );
} }
void movl(n64::Registers& regs, u32 instr) { void movl(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetReg<u64>( regs.cop1.SetReg<u64>(
regs.cop0, regs.cop0,
FD(instr), FD(instr),
@@ -361,7 +399,8 @@ void movl(n64::Registers& regs, u32 instr) {
); );
} }
void negs(Registers &regs, u32 instr) { void negs(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetCop1Reg<float>( regs.cop1.SetCop1Reg<float>(
regs.cop0, regs.cop0,
FD(instr), FD(instr),
@@ -372,7 +411,8 @@ void negs(Registers &regs, u32 instr) {
); );
} }
void negd(Registers &regs, u32 instr) { void negd(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetCop1Reg<double>( regs.cop1.SetCop1Reg<double>(
regs.cop0, regs.cop0,
FD(instr), FD(instr),
@@ -383,65 +423,77 @@ void negd(Registers &regs, u32 instr) {
); );
} }
void sqrts(Registers &regs, u32 instr) { void sqrts(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), std::sqrt(fs)); regs.cop1.SetCop1Reg<float>(regs.cop0, FD(instr), std::sqrt(fs));
} }
void sqrtd(Registers &regs, u32 instr) { void sqrtd(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), std::sqrt(fs)); regs.cop1.SetCop1Reg<double>(regs.cop0, FD(instr), std::sqrt(fs));
} }
void roundls(n64::Registers& regs, u32 instr) { void roundls(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
PUSHROUNDINGMODE; PUSHROUNDINGMODE;
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), (s32)std::nearbyint(fs)); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), (s32)std::nearbyint(fs));
POPROUNDINGMODE; POPROUNDINGMODE;
} }
void roundld(n64::Registers& regs, u32 instr) { void roundld(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
PUSHROUNDINGMODE; PUSHROUNDINGMODE;
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), (s64)std::nearbyint(fs)); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), (s64)std::nearbyint(fs));
POPROUNDINGMODE; POPROUNDINGMODE;
} }
void roundws(n64::Registers& regs, u32 instr) { void roundws(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
PUSHROUNDINGMODE; PUSHROUNDINGMODE;
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), (s32)std::nearbyint(fs)); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), (s32)std::nearbyint(fs));
POPROUNDINGMODE; POPROUNDINGMODE;
} }
void roundwd(n64::Registers& regs, u32 instr) { void roundwd(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
PUSHROUNDINGMODE; PUSHROUNDINGMODE;
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), (s32)std::nearbyint(fs)); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), (s32)std::nearbyint(fs));
POPROUNDINGMODE; POPROUNDINGMODE;
} }
void floorls(n64::Registers& regs, u32 instr) { void floorls(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), (s64)std::floor(fs)); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), (s64)std::floor(fs));
} }
void floorld(n64::Registers& regs, u32 instr) { void floorld(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), (s64)std::floor(fs)); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), (s64)std::floor(fs));
} }
void floorws(n64::Registers& regs, u32 instr) { void floorws(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), (s64)std::floor(fs)); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), (s64)std::floor(fs));
} }
void floorwd(n64::Registers& regs, u32 instr) { void floorwd(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), (s64)std::floor(fs)); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), (s64)std::floor(fs));
} }
void lwc1(n64::Registers& regs, Mem& mem, u32 instr) { void lwc1(Dynarec& cpu, u32 instr) {
Mem& mem = cpu.mem;
Registers& regs = cpu.regs;
if(!regs.cop0.status.cu1) { if(!regs.cop0.status.cu1) {
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true); FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
return; return;
@@ -459,7 +511,9 @@ void lwc1(n64::Registers& regs, Mem& mem, u32 instr) {
} }
} }
void swc1(n64::Registers& regs, Mem& mem, u32 instr) { void swc1(Dynarec& cpu, u32 instr) {
Mem& mem = cpu.mem;
Registers& regs = cpu.regs;
if(!regs.cop0.status.cu1) { if(!regs.cop0.status.cu1) {
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true); FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
return; return;
@@ -476,7 +530,9 @@ void swc1(n64::Registers& regs, Mem& mem, u32 instr) {
} }
} }
void ldc1(n64::Registers& regs, Mem& mem, u32 instr) { void ldc1(Dynarec& cpu, u32 instr) {
Mem& mem = cpu.mem;
Registers& regs = cpu.regs;
if(!regs.cop0.status.cu1) { if(!regs.cop0.status.cu1) {
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true); FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
return; return;
@@ -494,7 +550,9 @@ void ldc1(n64::Registers& regs, Mem& mem, u32 instr) {
} }
} }
void sdc1(n64::Registers& regs, Mem& mem, u32 instr) { void sdc1(Dynarec& cpu, u32 instr) {
Mem& mem = cpu.mem;
Registers& regs = cpu.regs;
if(!regs.cop0.status.cu1) { if(!regs.cop0.status.cu1) {
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true); FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
return; return;
@@ -511,43 +569,51 @@ void sdc1(n64::Registers& regs, Mem& mem, u32 instr) {
} }
} }
void truncws(n64::Registers& regs, u32 instr) { void truncws(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
s32 result = (s32)std::trunc(fs); s32 result = (s32)std::trunc(fs);
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), result); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), result);
} }
void truncwd(n64::Registers& regs, u32 instr) { void truncwd(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
s32 result = (s32)std::trunc(fs); s32 result = (s32)std::trunc(fs);
regs.cop1.SetReg<u32>(regs.cop0, FD(instr), result); regs.cop1.SetReg<u32>(regs.cop0, FD(instr), result);
} }
void truncls(n64::Registers& regs, u32 instr) { void truncls(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr)); float fs = regs.cop1.GetCop1Reg<float>(regs.cop0, FS(instr));
s64 result = (s64)std::trunc(fs); s64 result = (s64)std::trunc(fs);
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), result); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), result);
} }
void truncld(n64::Registers& regs, u32 instr) { void truncld(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr)); double fs = regs.cop1.GetCop1Reg<double>(regs.cop0, FS(instr));
s64 result = (s64)std::trunc(fs); s64 result = (s64)std::trunc(fs);
regs.cop1.SetReg<u64>(regs.cop0, FD(instr), result); regs.cop1.SetReg<u64>(regs.cop0, FD(instr), result);
} }
void mfc1(n64::Registers& regs, u32 instr) { void mfc1(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.gpr[RT(instr)] = (s32)regs.cop1.GetReg<u32>(regs.cop0, FS(instr)); regs.gpr[RT(instr)] = (s32)regs.cop1.GetReg<u32>(regs.cop0, FS(instr));
} }
void dmfc1(n64::Registers& regs, u32 instr) { void dmfc1(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.gpr[RT(instr)] = (s64)regs.cop1.GetReg<u64>(regs.cop0, FS(instr)); regs.gpr[RT(instr)] = (s64)regs.cop1.GetReg<u64>(regs.cop0, FS(instr));
} }
void mtc1(n64::Registers& regs, u32 instr) { void mtc1(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetReg<u32>(regs.cop0, FS(instr), regs.gpr[RT(instr)]); regs.cop1.SetReg<u32>(regs.cop0, FS(instr), regs.gpr[RT(instr)]);
} }
void dmtc1(n64::Registers& regs, u32 instr) { void dmtc1(Dynarec& cpu, u32 instr) {
Registers& regs = cpu.regs;
regs.cop1.SetReg<u64>(regs.cop0, FS(instr), regs.gpr[RT(instr)]); regs.cop1.SetReg<u64>(regs.cop0, FS(instr), regs.gpr[RT(instr)]);
} }
} }

View File

@@ -2,67 +2,67 @@
#include <Dynarec.hpp> #include <Dynarec.hpp>
#include <Cop1.hpp> #include <Cop1.hpp>
namespace n64::JIT { namespace n64 {
void absd(n64::Registers&, u32 instr); void absd(Dynarec&, u32 instr);
void abss(n64::Registers&, u32 instr); void abss(Dynarec&, u32 instr);
void absw(n64::Registers&, u32 instr); void absw(Dynarec&, u32 instr);
void absl(n64::Registers&, u32 instr); void absl(Dynarec&, u32 instr);
void adds(n64::Registers&, u32 instr); void adds(Dynarec&, u32 instr);
void addd(n64::Registers&, u32 instr); void addd(Dynarec&, u32 instr);
void subs(n64::Registers&, u32 instr); void subs(Dynarec&, u32 instr);
void subd(n64::Registers&, u32 instr); void subd(Dynarec&, u32 instr);
void subw(n64::Registers&, u32 instr); void subw(Dynarec&, u32 instr);
void subl(n64::Registers&, u32 instr); void subl(Dynarec&, u32 instr);
void ceills(n64::Registers&, u32 instr); void ceills(Dynarec&, u32 instr);
void ceilws(n64::Registers&, u32 instr); void ceilws(Dynarec&, u32 instr);
void ceilld(n64::Registers&, u32 instr); void ceilld(Dynarec&, u32 instr);
void ceilwd(n64::Registers&, u32 instr); void ceilwd(Dynarec&, u32 instr);
void cfc1(n64::Registers&, u32 instr); void cfc1(Dynarec&, u32 instr);
void ctc1(n64::Registers&, u32 instr); void ctc1(Dynarec&, u32 instr);
void roundls(n64::Registers&, u32 instr); void roundls(Dynarec&, u32 instr);
void roundld(n64::Registers&, u32 instr); void roundld(Dynarec&, u32 instr);
void roundws(n64::Registers&, u32 instr); void roundws(Dynarec&, u32 instr);
void roundwd(n64::Registers&, u32 instr); void roundwd(Dynarec&, u32 instr);
void floorls(n64::Registers&, u32 instr); void floorls(Dynarec&, u32 instr);
void floorld(n64::Registers&, u32 instr); void floorld(Dynarec&, u32 instr);
void floorws(n64::Registers&, u32 instr); void floorws(Dynarec&, u32 instr);
void floorwd(n64::Registers&, u32 instr); void floorwd(Dynarec&, u32 instr);
void cvtls(n64::Registers&, u32 instr); void cvtls(Dynarec&, u32 instr);
void cvtws(n64::Registers&, u32 instr); void cvtws(Dynarec&, u32 instr);
void cvtds(n64::Registers&, u32 instr); void cvtds(Dynarec&, u32 instr);
void cvtsw(n64::Registers&, u32 instr); void cvtsw(Dynarec&, u32 instr);
void cvtdw(n64::Registers&, u32 instr); void cvtdw(Dynarec&, u32 instr);
void cvtsd(n64::Registers&, u32 instr); void cvtsd(Dynarec&, u32 instr);
void cvtwd(n64::Registers&, u32 instr); void cvtwd(Dynarec&, u32 instr);
void cvtld(n64::Registers&, u32 instr); void cvtld(Dynarec&, u32 instr);
void cvtdl(n64::Registers&, u32 instr); void cvtdl(Dynarec&, u32 instr);
void cvtsl(n64::Registers&, u32 instr); void cvtsl(Dynarec&, u32 instr);
template <typename T> template <typename T>
void ccond(n64::Registers&, u32 instr, CompConds); void ccond(Dynarec&, u32 instr, CompConds);
void divs(n64::Registers&, u32 instr); void divs(Dynarec&, u32 instr);
void divd(n64::Registers&, u32 instr); void divd(Dynarec&, u32 instr);
void muls(n64::Registers&, u32 instr); void muls(Dynarec&, u32 instr);
void muld(n64::Registers&, u32 instr); void muld(Dynarec&, u32 instr);
void mulw(n64::Registers&, u32 instr); void mulw(Dynarec&, u32 instr);
void mull(n64::Registers&, u32 instr); void mull(Dynarec&, u32 instr);
void movs(n64::Registers&, u32 instr); void movs(Dynarec&, u32 instr);
void movd(n64::Registers&, u32 instr); void movd(Dynarec&, u32 instr);
void movw(n64::Registers&, u32 instr); void movw(Dynarec&, u32 instr);
void movl(n64::Registers&, u32 instr); void movl(Dynarec&, u32 instr);
void negs(n64::Registers&, u32 instr); void negs(Dynarec&, u32 instr);
void negd(n64::Registers&, u32 instr); void negd(Dynarec&, u32 instr);
void sqrts(n64::Registers&, u32 instr); void sqrts(Dynarec&, u32 instr);
void sqrtd(n64::Registers&, u32 instr); void sqrtd(Dynarec&, u32 instr);
void lwc1(n64::Registers&, Mem&, u32 instr); void lwc1(Dynarec&, u32 instr);
void swc1(n64::Registers&, Mem&, u32 instr); void swc1(Dynarec&, u32 instr);
void ldc1(n64::Registers&, Mem&, u32 instr); void ldc1(Dynarec&, u32 instr);
void mfc1(n64::Registers&, u32 instr); void mfc1(Dynarec&, u32 instr);
void dmfc1(n64::Registers&, u32 instr); void dmfc1(Dynarec&, u32 instr);
void mtc1(n64::Registers&, u32 instr); void mtc1(Dynarec&, u32 instr);
void dmtc1(n64::Registers&, u32 instr); void dmtc1(Dynarec&, u32 instr);
void sdc1(n64::Registers&, Mem&, u32 instr); void sdc1(Dynarec&, u32 instr);
void truncws(n64::Registers&, u32 instr); void truncws(Dynarec&, u32 instr);
void truncwd(n64::Registers&, u32 instr); void truncwd(Dynarec&, u32 instr);
void truncls(n64::Registers&, u32 instr); void truncls(Dynarec&, u32 instr);
void truncld(n64::Registers&, u32 instr); void truncld(Dynarec&, u32 instr);
} }

View File

@@ -3,7 +3,7 @@
#include <dynarec/cop/cop0decode.hpp> #include <dynarec/cop/cop0decode.hpp>
#include <Registers.hpp> #include <Registers.hpp>
namespace n64::JIT { namespace n64 {
void Dynarec::cop2Decode(u32 instr) { void Dynarec::cop2Decode(u32 instr) {
code.mov(rdi, (u64)this); code.mov(rdi, (u64)this);
code.mov(rsi, (u64)&regs); code.mov(rsi, (u64)&regs);
@@ -560,8 +560,8 @@ bool Dynarec::Exec(Mem& mem, u32 instr) {
code.mov(rax, (u64)lui); code.mov(rax, (u64)lui);
code.call(rax); code.call(rax);
break; break;
case 0x10: cop0Decode(regs, instr, *this); break; case 0x10: cop0Decode(regs, *this, instr); break;
case 0x11: res = cop1Decode(regs, instr, *this); break; case 0x11: res = cop1Decode(regs, *this, instr); break;
case 0x12: cop2Decode(instr); break; case 0x12: cop2Decode(instr); break;
case 0x14: case 0x14:
code.mov(rsi, instr); code.mov(rsi, instr);

View File

@@ -5,8 +5,9 @@
#define check_signed_overflow(op1, op2, res) (((~((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1) #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) #define check_signed_underflow(op1, op2, res) (((((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1)
namespace n64::JIT { namespace n64 {
void add(Registers& regs, u32 instr) { void add(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
u32 rs = (s32)regs.gpr[RS(instr)]; u32 rs = (s32)regs.gpr[RS(instr)];
u32 rt = (s32)regs.gpr[RT(instr)]; u32 rt = (s32)regs.gpr[RT(instr)];
u32 result = rs + rt; u32 result = rs + rt;
@@ -19,7 +20,8 @@ void add(Registers& regs, u32 instr) {
} }
} }
void addu(Registers& regs, u32 instr) { void addu(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
s32 rs = (s32)regs.gpr[RS(instr)]; s32 rs = (s32)regs.gpr[RS(instr)];
s32 rt = (s32)regs.gpr[RT(instr)]; s32 rt = (s32)regs.gpr[RT(instr)];
@@ -28,7 +30,8 @@ void addu(Registers& regs, u32 instr) {
} }
} }
void addi(Registers& regs, u32 instr) { void addi(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
u32 rs = regs.gpr[RS(instr)]; u32 rs = regs.gpr[RS(instr)];
u32 imm = s32(s16(instr)); u32 imm = s32(s16(instr));
u32 result = rs + imm; u32 result = rs + imm;
@@ -39,14 +42,16 @@ void addi(Registers& regs, u32 instr) {
} }
} }
void addiu(Registers& regs, u32 instr) { void addiu(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
s32 rs = (s32)regs.gpr[RS(instr)]; s32 rs = (s32)regs.gpr[RS(instr)];
s16 imm = (s16)(instr); s16 imm = (s16)(instr);
s32 result = rs + imm; s32 result = rs + imm;
regs.gpr[RT(instr)] = result; regs.gpr[RT(instr)] = result;
} }
void dadd(Registers& regs, u32 instr) { void dadd(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
u64 rs = regs.gpr[RS(instr)]; u64 rs = regs.gpr[RS(instr)];
u64 rt = regs.gpr[RT(instr)]; u64 rt = regs.gpr[RT(instr)];
u64 result = rt + rs; u64 result = rt + rs;
@@ -59,7 +64,8 @@ void dadd(Registers& regs, u32 instr) {
} }
} }
void daddu(Registers& regs, u32 instr) { void daddu(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
s64 rs = regs.gpr[RS(instr)]; s64 rs = regs.gpr[RS(instr)];
s64 rt = regs.gpr[RT(instr)]; s64 rt = regs.gpr[RT(instr)];
@@ -67,7 +73,8 @@ void daddu(Registers& regs, u32 instr) {
} }
} }
void daddi(Registers& regs, u32 instr) { void daddi(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
u64 imm = s64(s16(instr)); u64 imm = s64(s16(instr));
u64 rs = regs.gpr[RS(instr)]; u64 rs = regs.gpr[RS(instr)];
u64 result = imm + rs; u64 result = imm + rs;
@@ -78,13 +85,15 @@ void daddi(Registers& regs, u32 instr) {
} }
} }
void daddiu(Registers& regs, u32 instr) { void daddiu(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
s16 imm = (s16)(instr); s16 imm = (s16)(instr);
s64 rs = regs.gpr[RS(instr)]; s64 rs = regs.gpr[RS(instr)];
regs.gpr[RT(instr)] = rs + imm; regs.gpr[RT(instr)] = rs + imm;
} }
void div(Registers& regs, u32 instr) { void div(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
s64 dividend = (s32)regs.gpr[RS(instr)]; s64 dividend = (s32)regs.gpr[RS(instr)];
s64 divisor = (s32)regs.gpr[RT(instr)]; s64 divisor = (s32)regs.gpr[RT(instr)];
@@ -103,7 +112,8 @@ void div(Registers& regs, u32 instr) {
} }
} }
void divu(Registers& regs, u32 instr) { void divu(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
u32 dividend = regs.gpr[RS(instr)]; u32 dividend = regs.gpr[RS(instr)];
u32 divisor = regs.gpr[RT(instr)]; u32 divisor = regs.gpr[RT(instr)];
if(divisor == 0) { if(divisor == 0) {
@@ -117,7 +127,8 @@ void divu(Registers& regs, u32 instr) {
} }
} }
void ddiv(Registers& regs, u32 instr) { void ddiv(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
s64 dividend = regs.gpr[RS(instr)]; s64 dividend = regs.gpr[RS(instr)];
s64 divisor = regs.gpr[RT(instr)]; s64 divisor = regs.gpr[RT(instr)];
if (dividend == 0x8000000000000000 && divisor == 0xFFFFFFFFFFFFFFFF) { if (dividend == 0x8000000000000000 && divisor == 0xFFFFFFFFFFFFFFFF) {
@@ -138,7 +149,8 @@ void ddiv(Registers& regs, u32 instr) {
} }
} }
void ddivu(Registers& regs, u32 instr) { void ddivu(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
u64 dividend = regs.gpr[RS(instr)]; u64 dividend = regs.gpr[RS(instr)];
u64 divisor = regs.gpr[RT(instr)]; u64 divisor = regs.gpr[RT(instr)];
if(divisor == 0) { if(divisor == 0) {
@@ -152,14 +164,16 @@ void ddivu(Registers& regs, u32 instr) {
} }
} }
void branch(Registers& regs, bool cond, s64 address) { void branch(Dynarec& dyn, bool cond, s64 address) {
Registers& regs = dyn.regs;
regs.delaySlot = true; regs.delaySlot = true;
if (cond) { if (cond) {
regs.nextPC = address; regs.nextPC = address;
} }
} }
void branch_likely(Registers& regs, bool cond, s64 address) { void branch_likely(Dynarec& dyn, bool cond, s64 address) {
Registers& regs = dyn.regs;
regs.delaySlot = true; regs.delaySlot = true;
if (cond) { if (cond) {
regs.nextPC = address; regs.nextPC = address;
@@ -168,39 +182,46 @@ void branch_likely(Registers& regs, bool cond, s64 address) {
} }
} }
void b(Registers& regs, u32 instr, bool cond) { void b(Dynarec& dyn, u32 instr, bool cond) {
Registers& regs = dyn.regs;
s64 offset = (s64)se_imm(instr) << 2; s64 offset = (s64)se_imm(instr) << 2;
s64 address = regs.pc + offset; s64 address = regs.pc + offset;
branch(regs, cond, address); branch(dyn, cond, address);
} }
void blink(Registers& regs, u32 instr, bool cond) { void blink(Dynarec& dyn, u32 instr, bool cond) {
Registers& regs = dyn.regs;
regs.gpr[31] = regs.nextPC; regs.gpr[31] = regs.nextPC;
s64 offset = (s64)se_imm(instr) << 2; s64 offset = (s64)se_imm(instr) << 2;
s64 address = regs.pc + offset; s64 address = regs.pc + offset;
branch(regs, cond, address); branch(dyn, cond, address);
} }
void bl(Registers& regs, u32 instr, bool cond) { void bl(Dynarec& dyn, u32 instr, bool cond) {
Registers& regs = dyn.regs;
s64 offset = (s64)se_imm(instr) << 2; s64 offset = (s64)se_imm(instr) << 2;
s64 address = regs.pc + offset; s64 address = regs.pc + offset;
branch_likely(regs, cond, address); branch_likely(dyn, cond, address);
} }
void bllink(Registers& regs, u32 instr, bool cond) { void bllink(Dynarec& dyn, u32 instr, bool cond) {
Registers& regs = dyn.regs;
regs.gpr[31] = regs.nextPC; regs.gpr[31] = regs.nextPC;
s64 offset = (s64)se_imm(instr) << 2; s64 offset = (s64)se_imm(instr) << 2;
s64 address = regs.pc + offset; s64 address = regs.pc + offset;
branch_likely(regs, cond, address); branch_likely(dyn, cond, address);
} }
void lui(Registers& regs, u32 instr) { void lui(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
s64 val = (s16)instr; s64 val = (s16)instr;
val <<= 16; val <<= 16;
regs.gpr[RT(instr)] = val; regs.gpr[RT(instr)] = val;
} }
void lb(Registers& regs, Mem& mem, u32 instr) { void lb(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
@@ -211,7 +232,9 @@ void lb(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void lh(Registers& regs, Mem& mem, u32 instr) { void lh(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
if ((address & 0b1) > 0) { if ((address & 0b1) > 0) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -228,7 +251,9 @@ void lh(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void lw(Registers& regs, Mem& mem, u32 instr) { void lw(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
s16 offset = instr; s16 offset = instr;
u64 address = regs.gpr[RS(instr)] + offset; u64 address = regs.gpr[RS(instr)] + offset;
if (check_address_error(address, 0b11)) { if (check_address_error(address, 0b11)) {
@@ -246,7 +271,9 @@ void lw(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void ll(Registers& regs, Mem& mem, u32 instr) { void ll(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 physical; u32 physical;
if (!MapVAddr(regs, LOAD, address, physical)) { if (!MapVAddr(regs, LOAD, address, physical)) {
@@ -265,7 +292,9 @@ void ll(Registers& regs, Mem& mem, u32 instr) {
regs.cop0.LLAddr = physical >> 4; regs.cop0.LLAddr = physical >> 4;
} }
void lwl(Registers& regs, Mem& mem, u32 instr) { void lwl(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
@@ -280,7 +309,9 @@ void lwl(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void lwr(Registers& regs, Mem& mem, u32 instr) { void lwr(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
@@ -295,7 +326,9 @@ void lwr(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void ld(Registers& regs, Mem& mem, u32 instr) { void ld(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b111)) { if (check_address_error(address, 0b111)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -307,7 +340,9 @@ void ld(Registers& regs, Mem& mem, u32 instr) {
regs.gpr[RT(instr)] = value; regs.gpr[RT(instr)] = value;
} }
void lld(Registers& regs, Mem& mem, u32 instr) { void lld(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) { if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) {
FireException(regs, ExceptionCode::ReservedInstruction, 0, true); FireException(regs, ExceptionCode::ReservedInstruction, 0, true);
return; return;
@@ -329,7 +364,9 @@ void lld(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void ldl(Registers& regs, Mem& mem, u32 instr) { void ldl(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr = 0; u32 paddr = 0;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
@@ -344,7 +381,9 @@ void ldl(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void ldr(Registers& regs, Mem& mem, u32 instr) { void ldr(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
@@ -359,13 +398,17 @@ void ldr(Registers& regs, Mem& mem, u32 instr) {
} }
} }
void lbu(Registers& regs, Mem& mem, u32 instr) { void lbu(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u8 value = mem.Read8(regs, address); u8 value = mem.Read8(regs, address);
regs.gpr[RT(instr)] = value; regs.gpr[RT(instr)] = value;
} }
void lhu(Registers& regs, Mem& mem, u32 instr) { void lhu(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b1)) { if (check_address_error(address, 0b1)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -377,7 +420,9 @@ void lhu(Registers& regs, Mem& mem, u32 instr) {
regs.gpr[RT(instr)] = value; regs.gpr[RT(instr)] = value;
} }
void lwu(Registers& regs, Mem& mem, u32 instr) { void lwu(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b11)) { if (check_address_error(address, 0b11)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -389,12 +434,16 @@ void lwu(Registers& regs, Mem& mem, u32 instr) {
regs.gpr[RT(instr)] = value; regs.gpr[RT(instr)] = value;
} }
void sb(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { void sb(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
u32 address = regs.gpr[RS(instr)] + (s16)instr; u32 address = regs.gpr[RS(instr)] + (s16)instr;
mem.Write8(regs, dyn, address, regs.gpr[RT(instr)]); mem.Write8(regs, dyn, address, regs.gpr[RT(instr)]);
} }
void sc(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { void sc(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
if ((address & 0b11) > 0) { if ((address & 0b11) > 0) {
@@ -417,7 +466,9 @@ void sc(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
} }
} }
void scd(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { void scd(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b111)) { if (check_address_error(address, 0b111)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -433,7 +484,9 @@ void scd(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
regs.cop0.llbit = false; regs.cop0.llbit = false;
} }
void sh(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { void sh(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b1)) { if (check_address_error(address, 0b1)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -450,7 +503,9 @@ void sh(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
} }
} }
void sw(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { void sw(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
s16 offset = instr; s16 offset = instr;
u64 address = regs.gpr[RS(instr)] + offset; u64 address = regs.gpr[RS(instr)] + offset;
if (check_address_error(address, 0b11)) { if (check_address_error(address, 0b11)) {
@@ -468,7 +523,9 @@ void sw(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
} }
} }
void sd(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { void sd(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(address, 0b11)) { if (check_address_error(address, 0b11)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -486,7 +543,9 @@ void sd(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
} }
void sdl(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { void sdl(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
@@ -501,7 +560,9 @@ void sdl(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
} }
} }
void sdr(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { void sdr(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
@@ -516,7 +577,9 @@ void sdr(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
} }
} }
void swl(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { void swl(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
@@ -531,7 +594,9 @@ void swl(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
} }
} }
void swr(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { void swr(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
Mem& mem = dyn.mem;
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
@@ -546,86 +611,101 @@ void swr(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
} }
} }
void ori(Registers& regs, u32 instr) { void ori(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
s64 imm = (u16)instr; s64 imm = (u16)instr;
s64 result = imm | regs.gpr[RS(instr)]; s64 result = imm | regs.gpr[RS(instr)];
regs.gpr[RT(instr)] = result; regs.gpr[RT(instr)] = result;
} }
void or_(Registers& regs, u32 instr) { void or_(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
regs.gpr[RD(instr)] = regs.gpr[RS(instr)] | regs.gpr[RT(instr)]; regs.gpr[RD(instr)] = regs.gpr[RS(instr)] | regs.gpr[RT(instr)];
} }
} }
void nor(Registers& regs, u32 instr) { void nor(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
regs.gpr[RD(instr)] = ~(regs.gpr[RS(instr)] | regs.gpr[RT(instr)]); regs.gpr[RD(instr)] = ~(regs.gpr[RS(instr)] | regs.gpr[RT(instr)]);
} }
} }
void j(Registers& regs, u32 instr) { void j(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
u64 target = (instr & 0x3ffffff) << 2; u64 target = (instr & 0x3ffffff) << 2;
u64 address = ((regs.pc - 4) & ~0xfffffff) | target; u64 address = ((regs.pc - 4) & ~0xfffffff) | target;
branch(regs, true, address); branch(dyn, true, address);
} }
void jal(Registers& regs, u32 instr) { void jal(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
regs.gpr[31] = regs.nextPC; regs.gpr[31] = regs.nextPC;
j(regs, instr); j(dyn, instr);
} }
void jalr(Registers& regs, u32 instr) { void jalr(Dynarec& dyn, u32 instr) {
branch(regs, true, regs.gpr[RS(instr)]); Registers& regs = dyn.regs;
branch(dyn, true, regs.gpr[RS(instr)]);
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
regs.gpr[RD(instr)] = regs.pc + 4; regs.gpr[RD(instr)] = regs.pc + 4;
} }
} }
void slti(Registers& regs, u32 instr) { void slti(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
regs.gpr[RT(instr)] = regs.gpr[RS(instr)] < se_imm(instr); regs.gpr[RT(instr)] = regs.gpr[RS(instr)] < se_imm(instr);
} }
void sltiu(Registers& regs, u32 instr) { void sltiu(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
regs.gpr[RT(instr)] = (u64)regs.gpr[RS(instr)] < se_imm(instr); regs.gpr[RT(instr)] = (u64)regs.gpr[RS(instr)] < se_imm(instr);
} }
void slt(Registers& regs, u32 instr) { void slt(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
regs.gpr[RD(instr)] = regs.gpr[RS(instr)] < regs.gpr[RT(instr)]; regs.gpr[RD(instr)] = regs.gpr[RS(instr)] < regs.gpr[RT(instr)];
} }
} }
void sltu(Registers& regs, u32 instr) { void sltu(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
regs.gpr[RD(instr)] = (u64) regs.gpr[RS(instr)] < (u64) regs.gpr[RT(instr)]; regs.gpr[RD(instr)] = (u64) regs.gpr[RS(instr)] < (u64) regs.gpr[RT(instr)];
} }
} }
void xori(Registers& regs, u32 instr) { void xori(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
s64 imm = (u16)instr; s64 imm = (u16)instr;
regs.gpr[RT(instr)] = regs.gpr[RS(instr)] ^ imm; regs.gpr[RT(instr)] = regs.gpr[RS(instr)] ^ imm;
} }
void xor_(Registers& regs, u32 instr) { void xor_(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
regs.gpr[RD(instr)] = regs.gpr[RT(instr)] ^ regs.gpr[RS(instr)]; regs.gpr[RD(instr)] = regs.gpr[RT(instr)] ^ regs.gpr[RS(instr)];
} }
} }
void andi(Registers& regs, u32 instr) { void andi(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
s64 imm = (u16)instr; s64 imm = (u16)instr;
regs.gpr[RT(instr)] = regs.gpr[RS(instr)] & imm; regs.gpr[RT(instr)] = regs.gpr[RS(instr)] & imm;
} }
void and_(Registers& regs, u32 instr) { void and_(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
regs.gpr[RD(instr)] = regs.gpr[RS(instr)] & regs.gpr[RT(instr)]; regs.gpr[RD(instr)] = regs.gpr[RS(instr)] & regs.gpr[RT(instr)];
} }
} }
void sll(Registers& regs, u32 instr) { void sll(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
s32 result = regs.gpr[RT(instr)] << sa; s32 result = regs.gpr[RT(instr)] << sa;
@@ -633,7 +713,8 @@ void sll(Registers& regs, u32 instr) {
} }
} }
void sllv(Registers& regs, u32 instr) { void sllv(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
u8 sa = (regs.gpr[RS(instr)]) & 0x1F; u8 sa = (regs.gpr[RS(instr)]) & 0x1F;
u32 rt = regs.gpr[RT(instr)]; u32 rt = regs.gpr[RT(instr)];
@@ -642,7 +723,8 @@ void sllv(Registers& regs, u32 instr) {
} }
} }
void dsll32(Registers& regs, u32 instr) { void dsll32(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
s64 result = regs.gpr[RT(instr)] << (sa + 32); s64 result = regs.gpr[RT(instr)] << (sa + 32);
@@ -650,7 +732,8 @@ void dsll32(Registers& regs, u32 instr) {
} }
} }
void dsll(Registers& regs, u32 instr) { void dsll(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
s64 result = regs.gpr[RT(instr)] << sa; s64 result = regs.gpr[RT(instr)] << sa;
@@ -658,7 +741,8 @@ void dsll(Registers& regs, u32 instr) {
} }
} }
void dsllv(Registers& regs, u32 instr) { void dsllv(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
s64 sa = regs.gpr[RS(instr)] & 63; s64 sa = regs.gpr[RS(instr)] & 63;
s64 result = regs.gpr[RT(instr)] << sa; s64 result = regs.gpr[RT(instr)] << sa;
@@ -666,7 +750,8 @@ void dsllv(Registers& regs, u32 instr) {
} }
} }
void srl(Registers& regs, u32 instr) { void srl(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
u32 rt = regs.gpr[RT(instr)]; u32 rt = regs.gpr[RT(instr)];
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
@@ -675,7 +760,8 @@ void srl(Registers& regs, u32 instr) {
} }
} }
void srlv(Registers& regs, u32 instr) { void srlv(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
u8 sa = (regs.gpr[RS(instr)] & 0x1F); u8 sa = (regs.gpr[RS(instr)] & 0x1F);
u32 rt = regs.gpr[RT(instr)]; u32 rt = regs.gpr[RT(instr)];
@@ -684,7 +770,8 @@ void srlv(Registers& regs, u32 instr) {
} }
} }
void dsrl(Registers& regs, u32 instr) { void dsrl(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
u64 rt = regs.gpr[RT(instr)]; u64 rt = regs.gpr[RT(instr)];
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
@@ -693,7 +780,8 @@ void dsrl(Registers& regs, u32 instr) {
} }
} }
void dsrlv(Registers& regs, u32 instr) { void dsrlv(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
u8 amount = (regs.gpr[RS(instr)] & 63); u8 amount = (regs.gpr[RS(instr)] & 63);
u64 rt = regs.gpr[RT(instr)]; u64 rt = regs.gpr[RT(instr)];
@@ -702,7 +790,8 @@ void dsrlv(Registers& regs, u32 instr) {
} }
} }
void dsrl32(Registers& regs, u32 instr) { void dsrl32(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
u64 rt = regs.gpr[RT(instr)]; u64 rt = regs.gpr[RT(instr)];
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
@@ -711,7 +800,8 @@ void dsrl32(Registers& regs, u32 instr) {
} }
} }
void sra(Registers& regs, u32 instr) { void sra(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
s64 rt = regs.gpr[RT(instr)]; s64 rt = regs.gpr[RT(instr)];
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
@@ -720,7 +810,8 @@ void sra(Registers& regs, u32 instr) {
} }
} }
void srav(Registers& regs, u32 instr) { void srav(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
s64 rt = regs.gpr[RT(instr)]; s64 rt = regs.gpr[RT(instr)];
s64 rs = regs.gpr[RS(instr)]; s64 rs = regs.gpr[RS(instr)];
@@ -730,7 +821,8 @@ void srav(Registers& regs, u32 instr) {
} }
} }
void dsra(Registers& regs, u32 instr) { void dsra(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
s64 rt = regs.gpr[RT(instr)]; s64 rt = regs.gpr[RT(instr)];
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
@@ -739,7 +831,8 @@ void dsra(Registers& regs, u32 instr) {
} }
} }
void dsrav(Registers& regs, u32 instr) { void dsrav(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
s64 rt = regs.gpr[RT(instr)]; s64 rt = regs.gpr[RT(instr)];
s64 rs = regs.gpr[RS(instr)]; s64 rs = regs.gpr[RS(instr)];
@@ -749,7 +842,8 @@ void dsrav(Registers& regs, u32 instr) {
} }
} }
void dsra32(Registers& regs, u32 instr) { void dsra32(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
s64 rt = regs.gpr[RT(instr)]; s64 rt = regs.gpr[RT(instr)];
u8 sa = ((instr >> 6) & 0x1f); u8 sa = ((instr >> 6) & 0x1f);
@@ -758,17 +852,19 @@ void dsra32(Registers& regs, u32 instr) {
} }
} }
void jr(Registers& regs, u32 instr) { void jr(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
s64 address = regs.gpr[RS(instr)]; s64 address = regs.gpr[RS(instr)];
if (check_address_error(address, 0b11)) { if (check_address_error(address, 0b11)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
FireException(regs, ExceptionCode::DataBusError, 0, true); FireException(regs, ExceptionCode::DataBusError, 0, true);
} }
branch(regs, true, address); branch(dyn, true, address);
} }
void dsub(Registers& regs, u32 instr) { void dsub(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
s64 rt = regs.gpr[RT(instr)]; s64 rt = regs.gpr[RT(instr)];
s64 rs = regs.gpr[RS(instr)]; s64 rs = regs.gpr[RS(instr)];
s64 result = rs - rt; s64 result = rs - rt;
@@ -781,7 +877,8 @@ void dsub(Registers& regs, u32 instr) {
} }
} }
void dsubu(Registers& regs, u32 instr) { void dsubu(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
u64 rt = regs.gpr[RT(instr)]; u64 rt = regs.gpr[RT(instr)];
u64 rs = regs.gpr[RS(instr)]; u64 rs = regs.gpr[RS(instr)];
@@ -790,7 +887,8 @@ void dsubu(Registers& regs, u32 instr) {
} }
} }
void sub(Registers& regs, u32 instr) { void sub(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
s32 rt = regs.gpr[RT(instr)]; s32 rt = regs.gpr[RT(instr)];
s32 rs = regs.gpr[RS(instr)]; s32 rs = regs.gpr[RS(instr)];
s32 result = rs - rt; s32 result = rs - rt;
@@ -803,7 +901,8 @@ void sub(Registers& regs, u32 instr) {
} }
} }
void subu(Registers& regs, u32 instr) { void subu(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
u32 rt = regs.gpr[RT(instr)]; u32 rt = regs.gpr[RT(instr)];
u32 rs = regs.gpr[RS(instr)]; u32 rs = regs.gpr[RS(instr)];
@@ -812,7 +911,8 @@ void subu(Registers& regs, u32 instr) {
} }
} }
void dmultu(Registers& regs, u32 instr) { void dmultu(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
u64 rt = regs.gpr[RT(instr)]; u64 rt = regs.gpr[RT(instr)];
u64 rs = regs.gpr[RS(instr)]; u64 rs = regs.gpr[RS(instr)];
u128 result = (u128)rt * (u128)rs; u128 result = (u128)rt * (u128)rs;
@@ -820,7 +920,8 @@ void dmultu(Registers& regs, u32 instr) {
regs.hi = (s64)(result >> 64); regs.hi = (s64)(result >> 64);
} }
void dmult(Registers& regs, u32 instr) { void dmult(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
s64 rt = regs.gpr[RT(instr)]; s64 rt = regs.gpr[RT(instr)];
s64 rs = regs.gpr[RS(instr)]; s64 rs = regs.gpr[RS(instr)];
s128 result = (s128)rt * (s128)rs; s128 result = (s128)rt * (s128)rs;
@@ -828,7 +929,8 @@ void dmult(Registers& regs, u32 instr) {
regs.hi = result >> 64; regs.hi = result >> 64;
} }
void multu(Registers& regs, u32 instr) { void multu(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
u32 rt = regs.gpr[RT(instr)]; u32 rt = regs.gpr[RT(instr)];
u32 rs = regs.gpr[RS(instr)]; u32 rs = regs.gpr[RS(instr)];
u64 result = (u64)rt * (u64)rs; u64 result = (u64)rt * (u64)rs;
@@ -836,7 +938,8 @@ void multu(Registers& regs, u32 instr) {
regs.hi = (s64)((s32)(result >> 32)); regs.hi = (s64)((s32)(result >> 32));
} }
void mult(Registers& regs, u32 instr) { void mult(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
s32 rt = regs.gpr[RT(instr)]; s32 rt = regs.gpr[RT(instr)];
s32 rs = regs.gpr[RS(instr)]; s32 rs = regs.gpr[RS(instr)];
s64 result = (s64)rt * (s64)rs; s64 result = (s64)rt * (s64)rs;
@@ -844,46 +947,55 @@ void mult(Registers& regs, u32 instr) {
regs.hi = (s64)((s32)(result >> 32)); regs.hi = (s64)((s32)(result >> 32));
} }
void mflo(Registers& regs, u32 instr) { void mflo(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
regs.gpr[RD(instr)] = regs.lo; regs.gpr[RD(instr)] = regs.lo;
} }
} }
void mfhi(Registers& regs, u32 instr) { void mfhi(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
if(likely(RD(instr) != 0)) { if(likely(RD(instr) != 0)) {
regs.gpr[RD(instr)] = regs.hi; regs.gpr[RD(instr)] = regs.hi;
} }
} }
void mtlo(Registers& regs, u32 instr) { void mtlo(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
regs.lo = regs.gpr[RS(instr)]; regs.lo = regs.gpr[RS(instr)];
} }
void mthi(Registers& regs, u32 instr) { void mthi(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
regs.hi = regs.gpr[RS(instr)]; regs.hi = regs.gpr[RS(instr)];
} }
void trap(Registers& regs, bool cond) { void trap(Dynarec& dyn, bool cond) {
Registers& regs = dyn.regs;
if(cond) { if(cond) {
FireException(regs, ExceptionCode::Trap, 0, true); FireException(regs, ExceptionCode::Trap, 0, true);
} }
} }
void mtc2(Dynarec& dyn, Registers& regs, u32 instr) { void mtc2(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
dyn.cop2Latch = regs.gpr[RT(instr)]; dyn.cop2Latch = regs.gpr[RT(instr)];
} }
void mfc2(Dynarec& dyn, Registers& regs, u32 instr) { void mfc2(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
s32 value = dyn.cop2Latch; s32 value = dyn.cop2Latch;
regs.gpr[RT(instr)] = value; regs.gpr[RT(instr)] = value;
} }
void dmtc2(Dynarec& dyn, Registers& regs, u32 instr) { void dmtc2(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
dyn.cop2Latch = regs.gpr[RT(instr)]; dyn.cop2Latch = regs.gpr[RT(instr)];
} }
void dmfc2(Dynarec& dyn, Registers& regs, u32 instr) { void dmfc2(Dynarec& dyn, u32 instr) {
Registers& regs = dyn.regs;
regs.gpr[RT(instr)] = dyn.cop2Latch; regs.gpr[RT(instr)] = dyn.cop2Latch;
} }

View File

@@ -1,94 +1,94 @@
#pragma once #pragma once
#include <Dynarec.hpp> #include <Dynarec.hpp>
namespace n64::JIT { namespace n64 {
void add(Registers&, u32); void add(Dynarec&, u32);
void addu(Registers&, u32); void addu(Dynarec&, u32);
void addi(Registers&, u32); void addi(Dynarec&, u32);
void addiu(Registers&, u32); void addiu(Dynarec&, u32);
void andi(Registers&, u32); void andi(Dynarec&, u32);
void and_(Registers&, u32); void and_(Dynarec&, u32);
void branch(Registers&, bool, s64); void branch(Dynarec&, bool, s64);
void branch_likely(Registers&, bool, s64); void branch_likely(Dynarec&, bool, s64);
void b(Registers&, u32, bool); void b(Dynarec&, u32, bool);
void blink(Registers&, u32, bool); void blink(Dynarec&, u32, bool);
void bl(Registers&, u32, bool); void bl(Dynarec&, u32, bool);
void bllink(Registers&, u32, bool); void bllink(Dynarec&, u32, bool);
void dadd(Registers&, u32); void dadd(Dynarec&, u32);
void daddu(Registers&, u32); void daddu(Dynarec&, u32);
void daddi(Registers&, u32); void daddi(Dynarec&, u32);
void daddiu(Registers&, u32); void daddiu(Dynarec&, u32);
void ddiv(Registers&, u32); void ddiv(Dynarec&, u32);
void ddivu(Registers&, u32); void ddivu(Dynarec&, u32);
void div(Registers&, u32); void div(Dynarec&, u32);
void divu(Registers&, u32); void divu(Dynarec&, u32);
void dmult(Registers&, u32); void dmult(Dynarec&, u32);
void dmultu(Registers&, u32); void dmultu(Dynarec&, u32);
void dsll(Registers&, u32); void dsll(Dynarec&, u32);
void dsllv(Registers&, u32); void dsllv(Dynarec&, u32);
void dsll32(Registers&, u32); void dsll32(Dynarec&, u32);
void dsra(Registers&, u32); void dsra(Dynarec&, u32);
void dsrav(Registers&, u32); void dsrav(Dynarec&, u32);
void dsra32(Registers&, u32); void dsra32(Dynarec&, u32);
void dsrl(Registers&, u32); void dsrl(Dynarec&, u32);
void dsrlv(Registers&, u32); void dsrlv(Dynarec&, u32);
void dsrl32(Registers&, u32); void dsrl32(Dynarec&, u32);
void dsub(Registers&, u32); void dsub(Dynarec&, u32);
void dsubu(Registers&, u32); void dsubu(Dynarec&, u32);
void j(Registers&, u32); void j(Dynarec&, u32);
void jr(Registers&, u32); void jr(Dynarec&, u32);
void jal(Registers&, u32); void jal(Dynarec&, u32);
void jalr(Registers&, u32); void jalr(Dynarec&, u32);
void lui(Registers&, u32); void lui(Dynarec&, u32);
void lbu(Registers&, Mem&, u32); void lbu(Dynarec&, u32);
void lb(Registers&, Mem&, u32); void lb(Dynarec&, u32);
void ld(Registers&, Mem&, u32); void ld(Dynarec&, u32);
void ldl(Registers&, Mem&, u32); void ldl(Dynarec&, u32);
void ldr(Registers&, Mem&, u32); void ldr(Dynarec&, u32);
void lh(Registers&, Mem&, u32); void lh(Dynarec&, u32);
void lhu(Registers&, Mem&, u32); void lhu(Dynarec&, u32);
void ll(Registers&, Mem&, u32); void ll(Dynarec&, u32);
void lld(Registers&, Mem&, u32); void lld(Dynarec&, u32);
void lw(Registers&, Mem&, u32); void lw(Dynarec&, u32);
void lwl(Registers&, Mem&, u32); void lwl(Dynarec&, u32);
void lwu(Registers&, Mem&, u32); void lwu(Dynarec&, u32);
void lwr(Registers&, Mem&, u32); void lwr(Dynarec&, u32);
void mfhi(Registers&, u32); void mfhi(Dynarec&, u32);
void mflo(Registers&, u32); void mflo(Dynarec&, u32);
void mult(Registers&, u32); void mult(Dynarec&, u32);
void multu(Registers&, u32); void multu(Dynarec&, u32);
void mthi(Registers&, u32); void mthi(Dynarec&, u32);
void mtlo(Registers&, u32); void mtlo(Dynarec&, u32);
void nor(Registers&, u32); void nor(Dynarec&, u32);
void sb(Registers&, Mem&, Dynarec&, u32); void sb(Dynarec&, u32);
void sc(Registers&, Mem&, Dynarec&, u32); void sc(Dynarec&, u32);
void scd(Registers&, Mem&, Dynarec&, u32); void scd(Dynarec&, u32);
void sd(Registers&, Mem&, Dynarec&, u32); void sd(Dynarec&, u32);
void sdl(Registers&, Mem&, Dynarec&, u32); void sdl(Dynarec&, u32);
void sdr(Registers&, Mem&, Dynarec&, u32); void sdr(Dynarec&, u32);
void sh(Registers&, Mem&, Dynarec&, u32); void sh(Dynarec&, u32);
void sw(Registers&, Mem&, Dynarec&, u32); void sw(Dynarec&, u32);
void swl(Registers&, Mem&, Dynarec&, u32); void swl(Dynarec&, u32);
void swr(Registers&, Mem&, Dynarec&, u32); void swr(Dynarec&, u32);
void slti(Registers&, u32); void slti(Dynarec&, u32);
void sltiu(Registers&, u32); void sltiu(Dynarec&, u32);
void slt(Registers&, u32); void slt(Dynarec&, u32);
void sltu(Registers&, u32); void sltu(Dynarec&, u32);
void sll(Registers&, u32); void sll(Dynarec&, u32);
void sllv(Registers&, u32); void sllv(Dynarec&, u32);
void sub(Registers&, u32); void sub(Dynarec&, u32);
void subu(Registers&, u32); void subu(Dynarec&, u32);
void sra(Registers&, u32); void sra(Dynarec&, u32);
void srav(Registers&, u32); void srav(Dynarec&, u32);
void srl(Registers&, u32); void srl(Dynarec&, u32);
void srlv(Registers&, u32); void srlv(Dynarec&, u32);
void trap(Registers&, bool); void trap(Dynarec&, bool);
void or_(Registers&, u32); void or_(Dynarec&, u32);
void ori(Registers&, u32); void ori(Dynarec&, u32);
void xor_(Registers&, u32); void xor_(Dynarec&, u32);
void xori(Registers&, u32); void xori(Dynarec&, u32);
void mtc2(Dynarec& dyn, Registers&, u32); void mtc2(Dynarec&, u32);
void mfc2(Dynarec& dyn, Registers&, u32); void mfc2(Dynarec&, u32);
void dmtc2(Dynarec& dyn, Registers&, u32); void dmtc2(Dynarec&, u32);
void dmfc2(Dynarec& dyn, Registers&, u32); void dmfc2(Dynarec&, u32);
} }

View File

@@ -107,7 +107,7 @@ void Interpreter::cop2Decode(u32 instr) {
} }
} }
void Interpreter::Exec(Mem& mem, u32 instr) { void Interpreter::Exec(u32 instr) {
u8 mask = (instr >> 26) & 0x3f; u8 mask = (instr >> 26) & 0x3f;
// 00rr_rccc // 00rr_rccc
switch(mask) { // TODO: named constants for clearer code switch(mask) { // TODO: named constants for clearer code
@@ -139,35 +139,35 @@ void Interpreter::Exec(Mem& mem, u32 instr) {
case 0x17: bl(instr, regs.gpr[RS(instr)] > 0); break; case 0x17: bl(instr, regs.gpr[RS(instr)] > 0); break;
case 0x18: daddi(instr); break; case 0x18: daddi(instr); break;
case 0x19: daddiu(instr); break; case 0x19: daddiu(instr); break;
case 0x1A: ldl(mem, instr); break; case 0x1A: ldl(instr); break;
case 0x1B: ldr(mem, instr); break; case 0x1B: ldr(instr); break;
case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, true); break; case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, true); break;
case 0x20: lb(mem, instr); break; case 0x20: lb(instr); break;
case 0x21: lh(mem, instr); break; case 0x21: lh(instr); break;
case 0x22: lwl(mem, instr); break; case 0x22: lwl(instr); break;
case 0x23: lw(mem, instr); break; case 0x23: lw(instr); break;
case 0x24: lbu(mem, instr); break; case 0x24: lbu(instr); break;
case 0x25: lhu(mem, instr); break; case 0x25: lhu(instr); break;
case 0x26: lwr(mem, instr); break; case 0x26: lwr(instr); break;
case 0x27: lwu(mem, instr); break; case 0x27: lwu(instr); break;
case 0x28: sb(mem, instr); break; case 0x28: sb(instr); break;
case 0x29: sh(mem, instr); break; case 0x29: sh(instr); break;
case 0x2A: swl(mem, instr); break; case 0x2A: swl(instr); break;
case 0x2B: sw(mem, instr); break; case 0x2B: sw(instr); break;
case 0x2C: sdl(mem, instr); break; case 0x2C: sdl(instr); break;
case 0x2D: sdr(mem, instr); break; case 0x2D: sdr(instr); break;
case 0x2E: swr(mem, instr); break; case 0x2E: swr(instr); break;
case 0x2F: break; // CACHE case 0x2F: break; // CACHE
case 0x30: ll(mem, instr); break; case 0x30: ll(instr); break;
case 0x31: regs.cop1.lwc1(regs, mem, instr); break; case 0x31: regs.cop1.lwc1(regs, mem, instr); break;
case 0x34: lld(mem, instr); break; case 0x34: lld(instr); break;
case 0x35: regs.cop1.ldc1(regs, mem, instr); break; case 0x35: regs.cop1.ldc1(regs, mem, instr); break;
case 0x37: ld(mem, instr); break; case 0x37: ld(instr); break;
case 0x38: sc(mem, instr); break; case 0x38: sc(instr); break;
case 0x39: regs.cop1.swc1(regs, mem, instr); break; case 0x39: regs.cop1.swc1(regs, mem, instr); break;
case 0x3C: scd(mem, instr); break; case 0x3C: scd(instr); break;
case 0x3D: regs.cop1.sdc1(regs, mem, instr); break; case 0x3D: regs.cop1.sdc1(regs, mem, instr); break;
case 0x3F: sd(mem, instr); break; case 0x3F: sd(instr); break;
default: default:
Util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})\n", mask, instr, (u64)regs.oldPC); Util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})\n", mask, instr, (u64)regs.oldPC);
} }

View File

@@ -203,7 +203,7 @@ void Interpreter::lui(u32 instr) {
regs.gpr[RT(instr)] = val; regs.gpr[RT(instr)] = val;
} }
void Interpreter::lb(Mem& mem, u32 instr) { void Interpreter::lb(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
@@ -214,7 +214,7 @@ void Interpreter::lb(Mem& mem, u32 instr) {
} }
} }
void Interpreter::lh(Mem& mem, u32 instr) { void Interpreter::lh(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
if ((address & 0b1) > 0) { if ((address & 0b1) > 0) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -231,7 +231,7 @@ void Interpreter::lh(Mem& mem, u32 instr) {
} }
} }
void Interpreter::lw(Mem& mem, u32 instr) { void Interpreter::lw(u32 instr) {
s16 offset = instr; s16 offset = instr;
u64 address = regs.gpr[RS(instr)] + offset; u64 address = regs.gpr[RS(instr)] + offset;
if (check_address_error(0b11, address)) { if (check_address_error(0b11, address)) {
@@ -249,7 +249,7 @@ void Interpreter::lw(Mem& mem, u32 instr) {
} }
} }
void Interpreter::ll(Mem& mem, u32 instr) { void Interpreter::ll(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 physical; u32 physical;
if (!MapVAddr(regs, LOAD, address, physical)) { if (!MapVAddr(regs, LOAD, address, physical)) {
@@ -268,7 +268,7 @@ void Interpreter::ll(Mem& mem, u32 instr) {
regs.cop0.LLAddr = physical >> 4; regs.cop0.LLAddr = physical >> 4;
} }
void Interpreter::lwl(Mem& mem, u32 instr) { void Interpreter::lwl(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
@@ -283,7 +283,7 @@ void Interpreter::lwl(Mem& mem, u32 instr) {
} }
} }
void Interpreter::lwr(Mem& mem, u32 instr) { void Interpreter::lwr(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr = 0; u32 paddr = 0;
if(!MapVAddr(regs, LOAD, address, paddr)) { if(!MapVAddr(regs, LOAD, address, paddr)) {
@@ -298,7 +298,7 @@ void Interpreter::lwr(Mem& mem, u32 instr) {
} }
} }
void Interpreter::ld(Mem& mem, u32 instr) { void Interpreter::ld(u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(0b111, address)) { if (check_address_error(0b111, address)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -316,7 +316,7 @@ void Interpreter::ld(Mem& mem, u32 instr) {
} }
} }
void Interpreter::lld(Mem& mem, u32 instr) { void Interpreter::lld(u32 instr) {
if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) { if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) {
FireException(regs, ExceptionCode::ReservedInstruction, 0, true); FireException(regs, ExceptionCode::ReservedInstruction, 0, true);
return; return;
@@ -338,7 +338,7 @@ void Interpreter::lld(Mem& mem, u32 instr) {
} }
} }
void Interpreter::ldl(Mem& mem, u32 instr) { void Interpreter::ldl(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr = 0; u32 paddr = 0;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
@@ -353,7 +353,7 @@ void Interpreter::ldl(Mem& mem, u32 instr) {
} }
} }
void Interpreter::ldr(Mem& mem, u32 instr) { void Interpreter::ldr(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
@@ -368,7 +368,7 @@ void Interpreter::ldr(Mem& mem, u32 instr) {
} }
} }
void Interpreter::lbu(Mem& mem, u32 instr) { void Interpreter::lbu(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, LOAD, address, paddr)) { if (!MapVAddr(regs, LOAD, address, paddr)) {
@@ -380,7 +380,7 @@ void Interpreter::lbu(Mem& mem, u32 instr) {
} }
} }
void Interpreter::lhu(Mem& mem, u32 instr) { void Interpreter::lhu(u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if ((address & 0b1) > 0) { if ((address & 0b1) > 0) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -397,7 +397,7 @@ void Interpreter::lhu(Mem& mem, u32 instr) {
} }
} }
void Interpreter::lwu(Mem& mem, u32 instr) { void Interpreter::lwu(u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if ((address & 0b11) > 0) { if ((address & 0b11) > 0) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -415,7 +415,7 @@ void Interpreter::lwu(Mem& mem, u32 instr) {
} }
} }
void Interpreter::sb(Mem& mem, u32 instr) { void Interpreter::sb(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
@@ -426,7 +426,7 @@ void Interpreter::sb(Mem& mem, u32 instr) {
} }
} }
void Interpreter::sc(Mem& mem, u32 instr) { void Interpreter::sc(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
if ((address & 0b11) > 0) { if ((address & 0b11) > 0) {
@@ -449,7 +449,7 @@ void Interpreter::sc(Mem& mem, u32 instr) {
} }
} }
void Interpreter::scd(Mem& mem, u32 instr) { void Interpreter::scd(u32 instr) {
if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) { if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) {
FireException(regs, ExceptionCode::ReservedInstruction, 0, true); FireException(regs, ExceptionCode::ReservedInstruction, 0, true);
return; return;
@@ -477,7 +477,7 @@ void Interpreter::scd(Mem& mem, u32 instr) {
} }
} }
void Interpreter::sh(Mem& mem, u32 instr) { void Interpreter::sh(u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 physical; u32 physical;
@@ -489,7 +489,7 @@ void Interpreter::sh(Mem& mem, u32 instr) {
} }
} }
void Interpreter::sw(Mem& mem, u32 instr) { void Interpreter::sw(u32 instr) {
s16 offset = instr; s16 offset = instr;
u64 address = regs.gpr[RS(instr)] + offset; u64 address = regs.gpr[RS(instr)] + offset;
if (check_address_error(0b11, address)) { if (check_address_error(0b11, address)) {
@@ -507,7 +507,7 @@ void Interpreter::sw(Mem& mem, u32 instr) {
} }
} }
void Interpreter::sd(Mem& mem, u32 instr) { void Interpreter::sd(u32 instr) {
s64 address = regs.gpr[RS(instr)] + (s16)instr; s64 address = regs.gpr[RS(instr)] + (s16)instr;
if (check_address_error(0b111, address)) { if (check_address_error(0b111, address)) {
HandleTLBException(regs, address); HandleTLBException(regs, address);
@@ -524,7 +524,7 @@ void Interpreter::sd(Mem& mem, u32 instr) {
} }
} }
void Interpreter::sdl(Mem& mem, u32 instr) { void Interpreter::sdl(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
@@ -539,7 +539,7 @@ void Interpreter::sdl(Mem& mem, u32 instr) {
} }
} }
void Interpreter::sdr(Mem& mem, u32 instr) { void Interpreter::sdr(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
@@ -554,7 +554,7 @@ void Interpreter::sdr(Mem& mem, u32 instr) {
} }
} }
void Interpreter::swl(Mem& mem, u32 instr) { void Interpreter::swl(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {
@@ -569,7 +569,7 @@ void Interpreter::swl(Mem& mem, u32 instr) {
} }
} }
void Interpreter::swr(Mem& mem, u32 instr) { void Interpreter::swr(u32 instr) {
u64 address = regs.gpr[RS(instr)] + (s16)instr; u64 address = regs.gpr[RS(instr)] + (s16)instr;
u32 paddr; u32 paddr;
if (!MapVAddr(regs, STORE, address, paddr)) { if (!MapVAddr(regs, STORE, address, paddr)) {

View File

@@ -9,7 +9,7 @@ App::App() : window(core) {
void App::Run() { void App::Run() {
SDL_EventState(SDL_DROPFILE, SDL_ENABLE); SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
n64::SI& si = core.mem.mmio.si; n64::SI& si = core.cpu->mem.mmio.si;
while (!core.done) { while (!core.done) {
core.Run(window, window.settings.GetVolumeL(), window.settings.GetVolumeL()); core.Run(window, window.settings.GetVolumeL(), window.settings.GetVolumeL());

View File

@@ -65,10 +65,10 @@ Settings::Settings(n64::Core& core) {
switch(core.cpuType) { switch(core.cpuType) {
case n64::CpuType::Interpreter: case n64::CpuType::Interpreter:
core.cpuInterp = new n64::Interpreter; core.cpu = std::make_unique<n64::Interpreter>();
break; break;
case n64::CpuType::Dynarec: case n64::CpuType::Dynarec:
core.cpuDynarec = new n64::JIT::Dynarec; core.cpu = std::make_unique<n64::Dynarec>();
break; break;
case n64::CpuType::NONE: case n64::CpuType::NONE:
Util::panic("BRUH\n"); Util::panic("BRUH\n");

View File

@@ -12,7 +12,7 @@ namespace fs = std::filesystem;
Window::Window(n64::Core& core) : settings(core) { Window::Window(n64::Core& core) : settings(core) {
InitSDL(); InitSDL();
InitParallelRDP(core.mem.GetRDRAM(), window); InitParallelRDP(core.cpu->mem.GetRDRAM(), window);
InitImgui(); InitImgui();
NFD::Init(); NFD::Init();
} }
@@ -199,13 +199,13 @@ void Window::RenderMainMenuBar(n64::Core &core) {
} }
} }
if (ImGui::MenuItem("Dump RDRAM")) { if (ImGui::MenuItem("Dump RDRAM")) {
core.mem.DumpRDRAM(); core.cpu->mem.DumpRDRAM();
} }
if (ImGui::MenuItem("Dump IMEM")) { if (ImGui::MenuItem("Dump IMEM")) {
core.mem.DumpIMEM(); core.cpu->mem.DumpIMEM();
} }
if (ImGui::MenuItem("Dump DMEM")) { if (ImGui::MenuItem("Dump DMEM")) {
core.mem.DumpDMEM(); core.cpu->mem.DumpDMEM();
} }
if (ImGui::MenuItem("Exit")) { if (ImGui::MenuItem("Exit")) {
core.done = true; core.done = true;
@@ -250,8 +250,8 @@ void Window::Render(n64::Core& core) {
static u32 lastFrame = 0; static u32 lastFrame = 0;
if(!core.pause && lastFrame < ticks - 1000) { if(!core.pause && lastFrame < ticks - 1000) {
lastFrame = ticks; lastFrame = ticks;
windowTitle += fmt::format(" | {:02d} VI/s", core.mem.mmio.vi.swaps); windowTitle += fmt::format(" | {:02d} VI/s", core.cpu->mem.mmio.vi.swaps);
core.mem.mmio.vi.swaps = 0; core.cpu->mem.mmio.vi.swaps = 0;
SDL_SetWindowTitle(window, windowTitle.c_str()); SDL_SetWindowTitle(window, windowTitle.c_str());
windowTitle = shadowWindowTitle; windowTitle = shadowWindowTitle;
} }