Share registers between both cores
This commit is contained in:
@@ -25,7 +25,7 @@ CartInfo Core::LoadROM(const std::string& rom_) {
|
|||||||
romLoaded = true;
|
romLoaded = true;
|
||||||
|
|
||||||
CartInfo cartInfo = mem.LoadROM(rom);
|
CartInfo cartInfo = mem.LoadROM(rom);
|
||||||
DoPIFHLE(mem, CpuGetRegs(), cartInfo);
|
DoPIFHLE(mem, regs, cartInfo);
|
||||||
|
|
||||||
return cartInfo;
|
return cartInfo;
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,6 @@ CartInfo Core::LoadROM(const std::string& rom_) {
|
|||||||
void Core::Run(Window& window, float volumeL, float volumeR) {
|
void Core::Run(Window& window, float volumeL, float volumeR) {
|
||||||
MMIO& mmio = mem.mmio;
|
MMIO& mmio = mem.mmio;
|
||||||
Controller& controller = mmio.si.controller;
|
Controller& controller = mmio.si.controller;
|
||||||
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;
|
||||||
@@ -46,7 +45,7 @@ void Core::Run(Window& window, float volumeL, float volumeR) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(;cycles <= mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) {
|
for(;cycles <= mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) {
|
||||||
CpuStep(mem);
|
CpuStep();
|
||||||
if(!mmio.rsp.spStatus.halt) {
|
if(!mmio.rsp.spStatus.halt) {
|
||||||
regs.steps++;
|
regs.steps++;
|
||||||
if(regs.steps > 2) {
|
if(regs.steps > 2) {
|
||||||
@@ -74,7 +73,7 @@ void Core::Run(Window& window, float volumeL, float volumeR) {
|
|||||||
UpdateScreenParallelRdp(*this, window, GetVI());
|
UpdateScreenParallelRdp(*this, window, GetVI());
|
||||||
|
|
||||||
int missedCycles = N64_CYCLES_PER_FRAME - frameCycles;
|
int missedCycles = N64_CYCLES_PER_FRAME - frameCycles;
|
||||||
mmio.ai.Step(mem, CpuGetRegs(), missedCycles, volumeL, volumeR);
|
mmio.ai.Step(mem, 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) {
|
||||||
|
|||||||
@@ -24,22 +24,15 @@ struct Core {
|
|||||||
|
|
||||||
void CpuReset() {
|
void CpuReset() {
|
||||||
switch(cpuType) {
|
switch(cpuType) {
|
||||||
case CpuType::Dynarec: cpuDynarec.Reset(); break;
|
case CpuType::Dynarec: break;
|
||||||
case CpuType::Interpreter: cpuInterp.Reset(); break;
|
case CpuType::Interpreter: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CpuStep(Mem& mem) {
|
void CpuStep() {
|
||||||
switch(cpuType) {
|
switch(cpuType) {
|
||||||
case CpuType::Dynarec: cpuDynarec.Step(mem); break;
|
case CpuType::Dynarec: cpuDynarec.Step(mem, regs); break;
|
||||||
case CpuType::Interpreter: cpuInterp.Step(mem); break;
|
case CpuType::Interpreter: cpuInterp.Step(regs, mem); break;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Registers& CpuGetRegs() {
|
|
||||||
switch(cpuType) {
|
|
||||||
case CpuType::Dynarec: return cpuDynarec.regs;
|
|
||||||
case CpuType::Interpreter: return cpuInterp.regs;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,5 +49,6 @@ struct Core {
|
|||||||
CpuType cpuType = CpuType::Dynarec;
|
CpuType cpuType = CpuType::Dynarec;
|
||||||
Interpreter cpuInterp;
|
Interpreter cpuInterp;
|
||||||
Dynarec cpuDynarec;
|
Dynarec cpuDynarec;
|
||||||
|
Registers regs;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ void Dynarec::Reset() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dynarec::Step(Mem &mem) {
|
void Dynarec::Step(Mem &mem, Registers& regs) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
struct Dynarec {
|
struct Dynarec {
|
||||||
void Step(Mem& mem);
|
void Step(Mem& mem, Registers& regs);
|
||||||
void Reset();
|
void Reset();
|
||||||
Registers regs;
|
Registers regs;
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -2,10 +2,6 @@
|
|||||||
#include <log.hpp>
|
#include <log.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
void Interpreter::Reset() {
|
|
||||||
regs.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool ShouldServiceInterrupt(Registers& regs) {
|
inline bool ShouldServiceInterrupt(Registers& regs) {
|
||||||
bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0;
|
bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0;
|
||||||
bool interrupts_enabled = regs.cop0.status.ie == 1;
|
bool interrupts_enabled = regs.cop0.status.ie == 1;
|
||||||
@@ -25,7 +21,7 @@ inline void CheckCompareInterrupt(MI& mi, Registers& regs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::Step(Mem& mem) {
|
void Interpreter::Step(Registers& regs, Mem& mem) {
|
||||||
regs.gpr[0] = 0;
|
regs.gpr[0] = 0;
|
||||||
|
|
||||||
CheckCompareInterrupt(mem.mmio.mi, regs);
|
CheckCompareInterrupt(mem.mmio.mi, regs);
|
||||||
@@ -44,6 +40,6 @@ void Interpreter::Step(Mem& mem) {
|
|||||||
regs.pc = regs.nextPC;
|
regs.pc = regs.nextPC;
|
||||||
regs.nextPC += 4;
|
regs.nextPC += 4;
|
||||||
|
|
||||||
Exec(mem, instruction);
|
Exec(regs, mem, instruction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,113 +5,108 @@
|
|||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
struct Interpreter {
|
struct Interpreter {
|
||||||
Interpreter() {
|
Interpreter() = default;
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
~Interpreter() = default;
|
~Interpreter() = default;
|
||||||
void Reset();
|
void Step(Registers& regs, Mem&);
|
||||||
void Step(Mem&);
|
|
||||||
Registers regs;
|
|
||||||
private:
|
private:
|
||||||
u64 cop2Latch{};
|
u64 cop2Latch{};
|
||||||
friend struct Cop1;
|
friend struct Cop1;
|
||||||
|
|
||||||
void cop2Decode(u32);
|
void cop2Decode(Registers&, u32);
|
||||||
void special(Mem&, u32);
|
void special(Registers&, Mem&, u32);
|
||||||
void regimm(u32);
|
void regimm(Registers&, u32);
|
||||||
void Exec(Mem&, u32);
|
void Exec(Registers&, Mem&, u32);
|
||||||
void add(u32);
|
void add(Registers&, u32);
|
||||||
void addu(u32);
|
void addu(Registers&, u32);
|
||||||
void addi(u32);
|
void addi(Registers&, u32);
|
||||||
void addiu(u32);
|
void addiu(Registers&, u32);
|
||||||
void andi(u32);
|
void andi(Registers&, u32);
|
||||||
void and_(u32);
|
void and_(Registers&, u32);
|
||||||
void branch(bool, s64);
|
void branch(Registers&, bool, s64);
|
||||||
void branch_likely(bool, s64);
|
void branch_likely(Registers&, bool, s64);
|
||||||
void b(u32, bool);
|
void b(Registers&, u32, bool);
|
||||||
void blink(u32, bool);
|
void blink(Registers&, u32, bool);
|
||||||
void bl(u32, bool);
|
void bl(Registers&, u32, bool);
|
||||||
void bllink(u32, bool);
|
void bllink(Registers&, u32, bool);
|
||||||
void dadd(u32);
|
void dadd(Registers&, u32);
|
||||||
void daddu(u32);
|
void daddu(Registers&, u32);
|
||||||
void daddi(u32);
|
void daddi(Registers&, u32);
|
||||||
void daddiu(u32);
|
void daddiu(Registers&, u32);
|
||||||
void ddiv(u32);
|
void ddiv(Registers&, u32);
|
||||||
void ddivu(u32);
|
void ddivu(Registers&, u32);
|
||||||
void div(u32);
|
void div(Registers&, u32);
|
||||||
void divu(u32);
|
void divu(Registers&, u32);
|
||||||
void dmult(u32);
|
void dmult(Registers&, u32);
|
||||||
void dmultu(u32);
|
void dmultu(Registers&, u32);
|
||||||
void dsll(u32);
|
void dsll(Registers&, u32);
|
||||||
void dsllv(u32);
|
void dsllv(Registers&, u32);
|
||||||
void dsll32(u32);
|
void dsll32(Registers&, u32);
|
||||||
void dsra(u32);
|
void dsra(Registers&, u32);
|
||||||
void dsrav(u32);
|
void dsrav(Registers&, u32);
|
||||||
void dsra32(u32);
|
void dsra32(Registers&, u32);
|
||||||
void dsrl(u32);
|
void dsrl(Registers&, u32);
|
||||||
void dsrlv(u32);
|
void dsrlv(Registers&, u32);
|
||||||
void dsrl32(u32);
|
void dsrl32(Registers&, u32);
|
||||||
void dsub(u32);
|
void dsub(Registers&, u32);
|
||||||
void dsubu(u32);
|
void dsubu(Registers&, u32);
|
||||||
void j(u32);
|
void j(Registers&, u32);
|
||||||
void jr(u32);
|
void jr(Registers&, u32);
|
||||||
void jal(u32);
|
void jal(Registers&, u32);
|
||||||
void jalr(u32);
|
void jalr(Registers&, u32);
|
||||||
void lui(u32);
|
void lui(Registers&, u32);
|
||||||
void lbu(Mem&, u32);
|
void lbu(Registers&, Mem&, u32);
|
||||||
void lb(Mem&, u32);
|
void lb(Registers&, Mem&, u32);
|
||||||
void ld(Mem&, u32);
|
void ld(Registers&, Mem&, u32);
|
||||||
void ldl(Mem&, u32);
|
void ldl(Registers&, Mem&, u32);
|
||||||
void ldr(Mem&, u32);
|
void ldr(Registers&, Mem&, u32);
|
||||||
void lh(Mem&, u32);
|
void lh(Registers&, Mem&, u32);
|
||||||
void lhu(Mem&, u32);
|
void lhu(Registers&, Mem&, u32);
|
||||||
void ll(Mem&, u32);
|
void ll(Registers&, Mem&, u32);
|
||||||
void lld(Mem&, u32);
|
void lld(Registers&, Mem&, u32);
|
||||||
void lw(Mem&, u32);
|
void lw(Registers&, Mem&, u32);
|
||||||
void lwl(Mem&, u32);
|
void lwl(Registers&, Mem&, u32);
|
||||||
void lwu(Mem&, u32);
|
void lwu(Registers&, Mem&, u32);
|
||||||
void lwr(Mem&, u32);
|
void lwr(Registers&, Mem&, u32);
|
||||||
void mfhi(u32);
|
void mfhi(Registers&, u32);
|
||||||
void mflo(u32);
|
void mflo(Registers&, u32);
|
||||||
void mult(u32);
|
void mult(Registers&, u32);
|
||||||
void multu(u32);
|
void multu(Registers&, u32);
|
||||||
void mthi(u32);
|
void mthi(Registers&, u32);
|
||||||
void mtlo(u32);
|
void mtlo(Registers&, u32);
|
||||||
void nor(u32);
|
void nor(Registers&, u32);
|
||||||
void sb(Mem&, u32);
|
void sb(Registers&, Mem&, u32);
|
||||||
void sc(Mem&, u32);
|
void sc(Registers&, Mem&, u32);
|
||||||
void scd(Mem&, u32);
|
void scd(Registers&, Mem&, u32);
|
||||||
void sd(Mem&, u32);
|
void sd(Registers&, Mem&, u32);
|
||||||
void sdl(Mem&, u32);
|
void sdl(Registers&, Mem&, u32);
|
||||||
void sdr(Mem&, u32);
|
void sdr(Registers&, Mem&, u32);
|
||||||
void sh(Mem&, u32);
|
void sh(Registers&, Mem&, u32);
|
||||||
void sw(Mem&, u32);
|
void sw(Registers&, Mem&, u32);
|
||||||
void swl(Mem&, u32);
|
void swl(Registers&, Mem&, u32);
|
||||||
void swr(Mem&, u32);
|
void swr(Registers&, Mem&, u32);
|
||||||
void slti(u32);
|
void slti(Registers&, u32);
|
||||||
void sltiu(u32);
|
void sltiu(Registers&, u32);
|
||||||
void slt(u32);
|
void slt(Registers&, u32);
|
||||||
void sltu(u32);
|
void sltu(Registers&, u32);
|
||||||
void sll(u32);
|
void sll(Registers&, u32);
|
||||||
void sllv(u32);
|
void sllv(Registers&, u32);
|
||||||
void sub(u32);
|
void sub(Registers&, u32);
|
||||||
void subu(u32);
|
void subu(Registers&, u32);
|
||||||
void sra(u32);
|
void sra(Registers&, u32);
|
||||||
void srav(u32);
|
void srav(Registers&, u32);
|
||||||
void srl(u32);
|
void srl(Registers&, u32);
|
||||||
void srlv(u32);
|
void srlv(Registers&, u32);
|
||||||
void trap(bool);
|
void trap(Registers&, bool);
|
||||||
void or_(u32);
|
void or_(Registers&, u32);
|
||||||
void ori(u32);
|
void ori(Registers&, u32);
|
||||||
void xor_(u32);
|
void xor_(Registers&, u32);
|
||||||
void xori(u32);
|
void xori(Registers&, u32);
|
||||||
|
|
||||||
void mtc2(u32);
|
void mtc2(Registers&, u32);
|
||||||
void mfc2(u32);
|
void mfc2(Registers&, u32);
|
||||||
void dmtc2(u32);
|
void dmtc2(Registers&, u32);
|
||||||
void dmfc2(u32);
|
void dmfc2(Registers&, u32);
|
||||||
void ctc2(u32);
|
void ctc2(Registers&, u32);
|
||||||
void cfc2(u32);
|
void cfc2(Registers&, u32);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,172 +2,172 @@
|
|||||||
#include <log.hpp>
|
#include <log.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
void Interpreter::special(Mem& mem, u32 instr) {
|
void Interpreter::special(Registers& regs, Mem& mem, u32 instr) {
|
||||||
u8 mask = (instr & 0x3F);
|
u8 mask = (instr & 0x3F);
|
||||||
// 00rr_rccc
|
// 00rr_rccc
|
||||||
switch (mask) { // TODO: named constants for clearer code
|
switch (mask) { // TODO: named constants for clearer code
|
||||||
case 0:
|
case 0:
|
||||||
if (instr != 0) {
|
if (instr != 0) {
|
||||||
sll(instr);
|
sll(regs, instr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x02: srl(instr); break;
|
case 0x02: srl(regs, instr); break;
|
||||||
case 0x03: sra(instr); break;
|
case 0x03: sra(regs, instr); break;
|
||||||
case 0x04: sllv(instr); break;
|
case 0x04: sllv(regs, instr); break;
|
||||||
case 0x06: srlv(instr); break;
|
case 0x06: srlv(regs, instr); break;
|
||||||
case 0x07: srav(instr); break;
|
case 0x07: srav(regs, instr); break;
|
||||||
case 0x08: jr(instr); break;
|
case 0x08: jr(regs, instr); break;
|
||||||
case 0x09: jalr(instr); break;
|
case 0x09: jalr(regs, instr); break;
|
||||||
case 0x0C: FireException(regs, ExceptionCode::Syscall, 0, regs.oldPC); break;
|
case 0x0C: FireException(regs, ExceptionCode::Syscall, 0, regs.oldPC); break;
|
||||||
case 0x0D: FireException(regs, ExceptionCode::Breakpoint, 0, regs.oldPC); break;
|
case 0x0D: FireException(regs, ExceptionCode::Breakpoint, 0, regs.oldPC); break;
|
||||||
case 0x0F: break; // SYNC
|
case 0x0F: break; // SYNC
|
||||||
case 0x10: mfhi(instr); break;
|
case 0x10: mfhi(regs, instr); break;
|
||||||
case 0x11: mthi(instr); break;
|
case 0x11: mthi(regs, instr); break;
|
||||||
case 0x12: mflo(instr); break;
|
case 0x12: mflo(regs, instr); break;
|
||||||
case 0x13: mtlo(instr); break;
|
case 0x13: mtlo(regs, instr); break;
|
||||||
case 0x14: dsllv(instr); break;
|
case 0x14: dsllv(regs, instr); break;
|
||||||
case 0x16: dsrlv(instr); break;
|
case 0x16: dsrlv(regs, instr); break;
|
||||||
case 0x17: dsrav(instr); break;
|
case 0x17: dsrav(regs, instr); break;
|
||||||
case 0x18: mult(instr); break;
|
case 0x18: mult(regs, instr); break;
|
||||||
case 0x19: multu(instr); break;
|
case 0x19: multu(regs, instr); break;
|
||||||
case 0x1A: div(instr); break;
|
case 0x1A: div(regs, instr); break;
|
||||||
case 0x1B: divu(instr); break;
|
case 0x1B: divu(regs, instr); break;
|
||||||
case 0x1C: dmult(instr); break;
|
case 0x1C: dmult(regs, instr); break;
|
||||||
case 0x1D: dmultu(instr); break;
|
case 0x1D: dmultu(regs, instr); break;
|
||||||
case 0x1E: ddiv(instr); break;
|
case 0x1E: ddiv(regs, instr); break;
|
||||||
case 0x1F: ddivu(instr); break;
|
case 0x1F: ddivu(regs, instr); break;
|
||||||
case 0x20: add(instr); break;
|
case 0x20: add(regs, instr); break;
|
||||||
case 0x21: addu(instr); break;
|
case 0x21: addu(regs, instr); break;
|
||||||
case 0x22: sub(instr); break;
|
case 0x22: sub(regs, instr); break;
|
||||||
case 0x23: subu(instr); break;
|
case 0x23: subu(regs, instr); break;
|
||||||
case 0x24: and_(instr); break;
|
case 0x24: and_(regs, instr); break;
|
||||||
case 0x25: or_(instr); break;
|
case 0x25: or_(regs, instr); break;
|
||||||
case 0x26: xor_(instr); break;
|
case 0x26: xor_(regs, instr); break;
|
||||||
case 0x27: nor(instr); break;
|
case 0x27: nor(regs, instr); break;
|
||||||
case 0x2A: slt(instr); break;
|
case 0x2A: slt(regs, instr); break;
|
||||||
case 0x2B: sltu(instr); break;
|
case 0x2B: sltu(regs, instr); break;
|
||||||
case 0x2C: dadd(instr); break;
|
case 0x2C: dadd(regs, instr); break;
|
||||||
case 0x2D: daddu(instr); break;
|
case 0x2D: daddu(regs, instr); break;
|
||||||
case 0x2E: dsub(instr); break;
|
case 0x2E: dsub(regs, instr); break;
|
||||||
case 0x2F: dsubu(instr); break;
|
case 0x2F: dsubu(regs, instr); break;
|
||||||
case 0x30: trap(regs.gpr[RS(instr)] >= regs.gpr[RT(instr)]); break;
|
case 0x30: trap(regs, regs.gpr[RS(instr)] >= regs.gpr[RT(instr)]); break;
|
||||||
case 0x31: trap((u64)regs.gpr[RS(instr)] >= (u64)regs.gpr[RT(instr)]); break;
|
case 0x31: trap(regs, (u64)regs.gpr[RS(instr)] >= (u64)regs.gpr[RT(instr)]); break;
|
||||||
case 0x32: trap(regs.gpr[RS(instr)] < regs.gpr[RT(instr)]); break;
|
case 0x32: trap(regs, regs.gpr[RS(instr)] < regs.gpr[RT(instr)]); break;
|
||||||
case 0x33: trap((u64)regs.gpr[RS(instr)] < (u64)regs.gpr[RT(instr)]); break;
|
case 0x33: trap(regs, (u64)regs.gpr[RS(instr)] < (u64)regs.gpr[RT(instr)]); break;
|
||||||
case 0x34: trap(regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
|
case 0x34: trap(regs, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
|
||||||
case 0x36: trap(regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break;
|
case 0x36: trap(regs, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break;
|
||||||
case 0x38: dsll(instr); break;
|
case 0x38: dsll(regs, instr); break;
|
||||||
case 0x3A: dsrl(instr); break;
|
case 0x3A: dsrl(regs, instr); break;
|
||||||
case 0x3B: dsra(instr); break;
|
case 0x3B: dsra(regs, instr); break;
|
||||||
case 0x3C: dsll32(instr); break;
|
case 0x3C: dsll32(regs, instr); break;
|
||||||
case 0x3E: dsrl32(instr); break;
|
case 0x3E: dsrl32(regs, instr); break;
|
||||||
case 0x3F: dsra32(instr); break;
|
case 0x3F: dsra32(regs, instr); break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 7, mask & 7, instr, (u64)regs.oldPC);
|
util::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 7, mask & 7, instr, (u64)regs.oldPC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::regimm(u32 instr) {
|
void Interpreter::regimm(Registers& regs, u32 instr) {
|
||||||
u8 mask = ((instr >> 16) & 0x1F);
|
u8 mask = ((instr >> 16) & 0x1F);
|
||||||
// 000r_rccc
|
// 000r_rccc
|
||||||
switch (mask) { // TODO: named constants for clearer code
|
switch (mask) { // TODO: named constants for clearer code
|
||||||
case 0x00: b(instr, regs.gpr[RS(instr)] < 0); break;
|
case 0x00: b(regs, instr, regs.gpr[RS(instr)] < 0); break;
|
||||||
case 0x01: b(instr, regs.gpr[RS(instr)] >= 0); break;
|
case 0x01: b(regs, instr, regs.gpr[RS(instr)] >= 0); break;
|
||||||
case 0x02: bl(instr, regs.gpr[RS(instr)] < 0); break;
|
case 0x02: bl(regs, instr, regs.gpr[RS(instr)] < 0); break;
|
||||||
case 0x03: bl(instr, regs.gpr[RS(instr)] >= 0); break;
|
case 0x03: bl(regs, instr, regs.gpr[RS(instr)] >= 0); break;
|
||||||
case 0x08: trap(regs.gpr[RS(instr)] >= s64(s16(instr))); break;
|
case 0x08: trap(regs, regs.gpr[RS(instr)] >= s64(s16(instr))); break;
|
||||||
case 0x09: trap(u64(regs.gpr[RS(instr)]) >= u64(s64(s16(instr)))); break;
|
case 0x09: trap(regs, u64(regs.gpr[RS(instr)]) >= u64(s64(s16(instr)))); break;
|
||||||
case 0x0A: trap(regs.gpr[RS(instr)] < s64(s16(instr))); break;
|
case 0x0A: trap(regs, regs.gpr[RS(instr)] < s64(s16(instr))); break;
|
||||||
case 0x0B: trap(u64(regs.gpr[RS(instr)]) < u64(s64(s16(instr)))); break;
|
case 0x0B: trap(regs, u64(regs.gpr[RS(instr)]) < u64(s64(s16(instr)))); break;
|
||||||
case 0x0C: trap(regs.gpr[RS(instr)] == s64(s16(instr))); break;
|
case 0x0C: trap(regs, regs.gpr[RS(instr)] == s64(s16(instr))); break;
|
||||||
case 0x0E: trap(regs.gpr[RS(instr)] != s64(s16(instr))); break;
|
case 0x0E: trap(regs, regs.gpr[RS(instr)] != s64(s16(instr))); break;
|
||||||
case 0x10: blink(instr, regs.gpr[RS(instr)] < 0); break;
|
case 0x10: blink(regs, instr, regs.gpr[RS(instr)] < 0); break;
|
||||||
case 0x11: blink(instr, regs.gpr[RS(instr)] >= 0); break;
|
case 0x11: blink(regs, instr, regs.gpr[RS(instr)] >= 0); break;
|
||||||
case 0x12: bllink(instr, regs.gpr[RS(instr)] < 0); break;
|
case 0x12: bllink(regs, instr, regs.gpr[RS(instr)] < 0); break;
|
||||||
case 0x13: bllink(instr, regs.gpr[RS(instr)] >= 0); break;
|
case 0x13: bllink(regs, instr, regs.gpr[RS(instr)] >= 0); break;
|
||||||
default:
|
default:
|
||||||
util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 3, mask & 7, instr, (u64)regs.oldPC);
|
util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 3, mask & 7, instr, (u64)regs.oldPC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::cop2Decode(u32 instr) {
|
void Interpreter::cop2Decode(Registers& regs, u32 instr) {
|
||||||
if(!regs.cop0.status.cu2) {
|
if(!regs.cop0.status.cu2) {
|
||||||
FireException(regs, ExceptionCode::CoprocessorUnusable, 2, regs.oldPC);
|
FireException(regs, ExceptionCode::CoprocessorUnusable, 2, regs.oldPC);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch(RS(instr)) {
|
switch(RS(instr)) {
|
||||||
case 0x00: mfc2(instr); break;
|
case 0x00: mfc2(regs, instr); break;
|
||||||
case 0x01: dmfc2(instr); break;
|
case 0x01: dmfc2(regs, instr); break;
|
||||||
case 0x02: cfc2(instr); break;
|
case 0x02: cfc2(regs, instr); break;
|
||||||
case 0x04: mtc2(instr); break;
|
case 0x04: mtc2(regs, instr); break;
|
||||||
case 0x05: dmtc2(instr); break;
|
case 0x05: dmtc2(regs, instr); break;
|
||||||
case 0x06: ctc2(instr); break;
|
case 0x06: ctc2(regs, instr); break;
|
||||||
default:
|
default:
|
||||||
FireException(regs, ExceptionCode::ReservedInstruction, 2, regs.oldPC);
|
FireException(regs, ExceptionCode::ReservedInstruction, 2, regs.oldPC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::Exec(Mem& mem, u32 instr) {
|
void Interpreter::Exec(Registers& regs, Mem& mem, 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
|
||||||
case 0x00: special(mem, instr); break;
|
case 0x00: special(regs, mem, instr); break;
|
||||||
case 0x01: regimm(instr); break;
|
case 0x01: regimm(regs, instr); break;
|
||||||
case 0x02: j(instr); break;
|
case 0x02: j(regs, instr); break;
|
||||||
case 0x03: jal(instr); break;
|
case 0x03: jal(regs, instr); break;
|
||||||
case 0x04: b(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
|
case 0x04: b(regs, instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
|
||||||
case 0x05: {
|
case 0x05: {
|
||||||
//fmt::print("RS: {:016X}, RT: {:016X}\n", (u64)regs.gpr[RS(instr)], (u64)regs.gpr[RT(instr)]);
|
//fmt::print("RS: {:016X}, RT: {:016X}\n", (u64)regs.gpr[RS(instr)], (u64)regs.gpr[RT(instr)]);
|
||||||
b(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]);
|
b(regs, instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]);
|
||||||
} break;
|
} break;
|
||||||
case 0x06: b(instr, regs.gpr[RS(instr)] <= 0); break;
|
case 0x06: b(regs, instr, regs.gpr[RS(instr)] <= 0); break;
|
||||||
case 0x07: b(instr, regs.gpr[RS(instr)] > 0); break;
|
case 0x07: b(regs, instr, regs.gpr[RS(instr)] > 0); break;
|
||||||
case 0x08: addi(instr); break;
|
case 0x08: addi(regs, instr); break;
|
||||||
case 0x09: addiu(instr); break;
|
case 0x09: addiu(regs, instr); break;
|
||||||
case 0x0A: slti(instr); break;
|
case 0x0A: slti(regs, instr); break;
|
||||||
case 0x0B: sltiu(instr); break;
|
case 0x0B: sltiu(regs, instr); break;
|
||||||
case 0x0C: andi(instr); break;
|
case 0x0C: andi(regs, instr); break;
|
||||||
case 0x0D: ori(instr); break;
|
case 0x0D: ori(regs, instr); break;
|
||||||
case 0x0E: xori(instr); break;
|
case 0x0E: xori(regs, instr); break;
|
||||||
case 0x0F: lui(instr); break;
|
case 0x0F: lui(regs, instr); break;
|
||||||
case 0x10: regs.cop0.decode(regs, mem, instr); break;
|
case 0x10: regs.cop0.decode(regs, mem, instr); break;
|
||||||
case 0x11: regs.cop1.decode(*this, instr); break;
|
case 0x11: regs.cop1.decode(regs, *this, instr); break;
|
||||||
case 0x12: cop2Decode(instr); break;
|
case 0x12: cop2Decode(regs, instr); break;
|
||||||
case 0x14: bl(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
|
case 0x14: bl(regs, instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
|
||||||
case 0x15: bl(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break;
|
case 0x15: bl(regs, instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break;
|
||||||
case 0x16: bl(instr, regs.gpr[RS(instr)] <= 0); break;
|
case 0x16: bl(regs, instr, regs.gpr[RS(instr)] <= 0); break;
|
||||||
case 0x17: bl(instr, regs.gpr[RS(instr)] > 0); break;
|
case 0x17: bl(regs, instr, regs.gpr[RS(instr)] > 0); break;
|
||||||
case 0x18: daddi(instr); break;
|
case 0x18: daddi(regs, instr); break;
|
||||||
case 0x19: daddiu(instr); break;
|
case 0x19: daddiu(regs, instr); break;
|
||||||
case 0x1A: ldl(mem, instr); break;
|
case 0x1A: ldl(regs, mem, instr); break;
|
||||||
case 0x1B: ldr(mem, instr); break;
|
case 0x1B: ldr(regs, mem, instr); break;
|
||||||
case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, regs.oldPC); break;
|
case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, regs.oldPC); break;
|
||||||
case 0x20: lb(mem, instr); break;
|
case 0x20: lb(regs, mem, instr); break;
|
||||||
case 0x21: lh(mem, instr); break;
|
case 0x21: lh(regs, mem, instr); break;
|
||||||
case 0x22: lwl(mem, instr); break;
|
case 0x22: lwl(regs, mem, instr); break;
|
||||||
case 0x23: lw(mem, instr); break;
|
case 0x23: lw(regs, mem, instr); break;
|
||||||
case 0x24: lbu(mem, instr); break;
|
case 0x24: lbu(regs, mem, instr); break;
|
||||||
case 0x25: lhu(mem, instr); break;
|
case 0x25: lhu(regs, mem, instr); break;
|
||||||
case 0x26: lwr(mem, instr); break;
|
case 0x26: lwr(regs, mem, instr); break;
|
||||||
case 0x27: lwu(mem, instr); break;
|
case 0x27: lwu(regs, mem, instr); break;
|
||||||
case 0x28: sb(mem, instr); break;
|
case 0x28: sb(regs, mem, instr); break;
|
||||||
case 0x29: sh(mem, instr); break;
|
case 0x29: sh(regs, mem, instr); break;
|
||||||
case 0x2A: swl(mem, instr); break;
|
case 0x2A: swl(regs, mem, instr); break;
|
||||||
case 0x2B: sw(mem, instr); break;
|
case 0x2B: sw(regs, mem, instr); break;
|
||||||
case 0x2C: sdl(mem, instr); break;
|
case 0x2C: sdl(regs, mem, instr); break;
|
||||||
case 0x2D: sdr(mem, instr); break;
|
case 0x2D: sdr(regs, mem, instr); break;
|
||||||
case 0x2E: swr(mem, instr); break;
|
case 0x2E: swr(regs, mem, instr); break;
|
||||||
case 0x2F: break; // CACHE
|
case 0x2F: break; // CACHE
|
||||||
case 0x30: ll(mem, instr); break;
|
case 0x30: ll(regs, mem, 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(regs, mem, 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(regs, mem, instr); break;
|
||||||
case 0x38: sc(mem, instr); break;
|
case 0x38: sc(regs, mem, 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(regs, mem, 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(regs, mem, 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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#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 {
|
namespace n64 {
|
||||||
void Interpreter::add(u32 instr) {
|
void Interpreter::add(Registers& regs, u32 instr) {
|
||||||
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;
|
||||||
@@ -17,14 +17,14 @@ void Interpreter::add(u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::addu(u32 instr) {
|
void Interpreter::addu(Registers& regs, u32 instr) {
|
||||||
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)];
|
||||||
s32 result = rs + rt;
|
s32 result = rs + rt;
|
||||||
regs.gpr[RD(instr)] = result;
|
regs.gpr[RD(instr)] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::addi(u32 instr) {
|
void Interpreter::addi(Registers& regs, u32 instr) {
|
||||||
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;
|
||||||
@@ -35,14 +35,14 @@ void Interpreter::addi(u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::addiu(u32 instr) {
|
void Interpreter::addiu(Registers& regs, u32 instr) {
|
||||||
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 Interpreter::dadd(u32 instr) {
|
void Interpreter::dadd(Registers& regs, u32 instr) {
|
||||||
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;
|
||||||
@@ -53,13 +53,13 @@ void Interpreter::dadd(u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::daddu(u32 instr) {
|
void Interpreter::daddu(Registers& regs, u32 instr) {
|
||||||
s64 rs = regs.gpr[RS(instr)];
|
s64 rs = regs.gpr[RS(instr)];
|
||||||
s64 rt = regs.gpr[RT(instr)];
|
s64 rt = regs.gpr[RT(instr)];
|
||||||
regs.gpr[RD(instr)] = rs + rt;
|
regs.gpr[RD(instr)] = rs + rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::daddi(u32 instr) {
|
void Interpreter::daddi(Registers& regs, u32 instr) {
|
||||||
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;
|
||||||
@@ -70,13 +70,13 @@ void Interpreter::daddi(u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::daddiu(u32 instr) {
|
void Interpreter::daddiu(Registers& regs, u32 instr) {
|
||||||
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 Interpreter::div(u32 instr) {
|
void Interpreter::div(Registers& regs, u32 instr) {
|
||||||
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)];
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ void Interpreter::div(u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::divu(u32 instr) {
|
void Interpreter::divu(Registers& regs, u32 instr) {
|
||||||
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) {
|
||||||
@@ -109,7 +109,7 @@ void Interpreter::divu(u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ddiv(u32 instr) {
|
void Interpreter::ddiv(Registers& regs, u32 instr) {
|
||||||
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) {
|
||||||
@@ -130,7 +130,7 @@ void Interpreter::ddiv(u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ddivu(u32 instr) {
|
void Interpreter::ddivu(Registers& regs, u32 instr) {
|
||||||
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) {
|
||||||
@@ -144,14 +144,14 @@ void Interpreter::ddivu(u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::branch(bool cond, s64 address) {
|
void Interpreter::branch(Registers& regs, bool cond, s64 address) {
|
||||||
regs.delaySlot = true;
|
regs.delaySlot = true;
|
||||||
if (cond) {
|
if (cond) {
|
||||||
regs.nextPC = address;
|
regs.nextPC = address;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::branch_likely(bool cond, s64 address) {
|
void Interpreter::branch_likely(Registers& regs, bool cond, s64 address) {
|
||||||
regs.delaySlot = true;
|
regs.delaySlot = true;
|
||||||
if (cond) {
|
if (cond) {
|
||||||
regs.nextPC = address;
|
regs.nextPC = address;
|
||||||
@@ -160,44 +160,44 @@ void Interpreter::branch_likely(bool cond, s64 address) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::b(u32 instr, bool cond) {
|
void Interpreter::b(Registers& regs, u32 instr, bool cond) {
|
||||||
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(cond, address);
|
branch(regs, cond, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::blink(u32 instr, bool cond) {
|
void Interpreter::blink(Registers& regs, u32 instr, bool cond) {
|
||||||
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(cond, address);
|
branch(regs, cond, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::bl(u32 instr, bool cond) {
|
void Interpreter::bl(Registers& regs, u32 instr, bool cond) {
|
||||||
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(cond, address);
|
branch_likely(regs, cond, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::bllink(u32 instr, bool cond) {
|
void Interpreter::bllink(Registers& regs, u32 instr, bool cond) {
|
||||||
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(cond, address);
|
branch_likely(regs, cond, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::lui(u32 instr) {
|
void Interpreter::lui(Registers& regs, u32 instr) {
|
||||||
s64 val = (s16)instr;
|
s64 val = (s16)instr;
|
||||||
val <<= 16;
|
val <<= 16;
|
||||||
regs.gpr[RT(instr)] = val;
|
regs.gpr[RT(instr)] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::lb(Mem& mem, u32 instr) {
|
void Interpreter::lb(Registers& regs, Mem& mem, u32 instr) {
|
||||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
regs.gpr[RT(instr)] = (s8)mem.Read8(regs, address, regs.oldPC);
|
regs.gpr[RT(instr)] = (s8)mem.Read8(regs, address, regs.oldPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::lh(Mem& mem, u32 instr) {
|
void Interpreter::lh(Registers& regs, Mem& mem, u32 instr) {
|
||||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
u64 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);
|
||||||
@@ -208,7 +208,7 @@ void Interpreter::lh(Mem& mem, u32 instr) {
|
|||||||
regs.gpr[RT(instr)] = (s16)mem.Read16(regs, address, regs.oldPC);
|
regs.gpr[RT(instr)] = (s16)mem.Read16(regs, address, regs.oldPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::lw(Mem& mem, u32 instr) {
|
void Interpreter::lw(Registers& regs, Mem& mem, 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(address, 0b11)) {
|
if (check_address_error(address, 0b11)) {
|
||||||
@@ -226,7 +226,7 @@ void Interpreter::lw(Mem& mem, u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ll(Mem& mem, u32 instr) {
|
void Interpreter::ll(Registers& regs, Mem& mem, u32 instr) {
|
||||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
u32 physical;
|
u32 physical;
|
||||||
if (!MapVAddr(regs, LOAD, address, physical)) {
|
if (!MapVAddr(regs, LOAD, address, physical)) {
|
||||||
@@ -240,7 +240,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(Registers& regs, Mem& mem, 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)) {
|
||||||
@@ -255,7 +255,7 @@ void Interpreter::lwl(Mem& mem, u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::lwr(Mem& mem, u32 instr) {
|
void Interpreter::lwr(Registers& regs, Mem& mem, 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)) {
|
||||||
@@ -270,7 +270,7 @@ void Interpreter::lwr(Mem& mem, u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ld(Mem& mem, u32 instr) {
|
void Interpreter::ld(Registers& regs, Mem& mem, u32 instr) {
|
||||||
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);
|
||||||
@@ -282,7 +282,7 @@ void Interpreter::ld(Mem& mem, u32 instr) {
|
|||||||
regs.gpr[RT(instr)] = value;
|
regs.gpr[RT(instr)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::lld(Mem& mem, u32 instr) {
|
void Interpreter::lld(Registers& regs, Mem& mem, u32 instr) {
|
||||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
u32 paddr;
|
u32 paddr;
|
||||||
if (!MapVAddr(regs, LOAD, address, paddr)) {
|
if (!MapVAddr(regs, LOAD, address, paddr)) {
|
||||||
@@ -296,7 +296,7 @@ void Interpreter::lld(Mem& mem, u32 instr) {
|
|||||||
regs.cop0.LLAddr = paddr >> 4;
|
regs.cop0.LLAddr = paddr >> 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ldl(Mem& mem, u32 instr) {
|
void Interpreter::ldl(Registers& regs, Mem& mem, 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)) {
|
||||||
@@ -311,7 +311,7 @@ void Interpreter::ldl(Mem& mem, u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ldr(Mem& mem, u32 instr) {
|
void Interpreter::ldr(Registers& regs, Mem& mem, 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)) {
|
||||||
@@ -326,13 +326,13 @@ void Interpreter::ldr(Mem& mem, u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::lbu(Mem& mem, u32 instr) {
|
void Interpreter::lbu(Registers& regs, Mem& mem, u32 instr) {
|
||||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
u8 value = mem.Read8(regs, address, regs.oldPC);
|
u8 value = mem.Read8(regs, address, regs.oldPC);
|
||||||
regs.gpr[RT(instr)] = value;
|
regs.gpr[RT(instr)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::lhu(Mem& mem, u32 instr) {
|
void Interpreter::lhu(Registers& regs, Mem& mem, u32 instr) {
|
||||||
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);
|
||||||
@@ -344,7 +344,7 @@ void Interpreter::lhu(Mem& mem, u32 instr) {
|
|||||||
regs.gpr[RT(instr)] = value;
|
regs.gpr[RT(instr)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::lwu(Mem& mem, u32 instr) {
|
void Interpreter::lwu(Registers& regs, Mem& mem, u32 instr) {
|
||||||
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);
|
||||||
@@ -356,12 +356,12 @@ void Interpreter::lwu(Mem& mem, u32 instr) {
|
|||||||
regs.gpr[RT(instr)] = value;
|
regs.gpr[RT(instr)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sb(Mem& mem, u32 instr) {
|
void Interpreter::sb(Registers& regs, Mem& mem, u32 instr) {
|
||||||
u32 address = regs.gpr[RS(instr)] + (s16)instr;
|
u32 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
mem.Write8(regs, address, regs.gpr[RT(instr)], regs.oldPC);
|
mem.Write8(regs, address, regs.gpr[RT(instr)], regs.oldPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sc(Mem& mem, u32 instr) {
|
void Interpreter::sc(Registers& regs, Mem& mem, u32 instr) {
|
||||||
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);
|
||||||
@@ -376,7 +376,7 @@ void Interpreter::sc(Mem& mem, u32 instr) {
|
|||||||
regs.cop0.llbit = false;
|
regs.cop0.llbit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::scd(Mem& mem, u32 instr) {
|
void Interpreter::scd(Registers& regs, Mem& mem, u32 instr) {
|
||||||
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);
|
||||||
@@ -392,7 +392,7 @@ void Interpreter::scd(Mem& mem, u32 instr) {
|
|||||||
regs.cop0.llbit = false;
|
regs.cop0.llbit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sh(Mem& mem, u32 instr) {
|
void Interpreter::sh(Registers& regs, Mem& mem, u32 instr) {
|
||||||
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);
|
||||||
@@ -409,7 +409,7 @@ void Interpreter::sh(Mem& mem, u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sw(Mem& mem, u32 instr) {
|
void Interpreter::sw(Registers& regs, Mem& mem, 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(address, 0b11)) {
|
if (check_address_error(address, 0b11)) {
|
||||||
@@ -427,7 +427,7 @@ void Interpreter::sw(Mem& mem, u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sd(Mem& mem, u32 instr) {
|
void Interpreter::sd(Registers& regs, Mem& mem, u32 instr) {
|
||||||
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);
|
||||||
@@ -445,7 +445,7 @@ void Interpreter::sd(Mem& mem, u32 instr) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sdl(Mem& mem, u32 instr) {
|
void Interpreter::sdl(Registers& regs, Mem& mem, 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)) {
|
||||||
@@ -460,7 +460,7 @@ void Interpreter::sdl(Mem& mem, u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sdr(Mem& mem, u32 instr) {
|
void Interpreter::sdr(Registers& regs, Mem& mem, 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)) {
|
||||||
@@ -475,7 +475,7 @@ void Interpreter::sdr(Mem& mem, u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::swl(Mem& mem, u32 instr) {
|
void Interpreter::swl(Registers& regs, Mem& mem, 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)) {
|
||||||
@@ -490,7 +490,7 @@ void Interpreter::swl(Mem& mem, u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::swr(Mem& mem, u32 instr) {
|
void Interpreter::swr(Registers& regs, Mem& mem, 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)) {
|
||||||
@@ -505,21 +505,21 @@ void Interpreter::swr(Mem& mem, u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ori(u32 instr) {
|
void Interpreter::ori(Registers& regs, u32 instr) {
|
||||||
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 Interpreter::or_(u32 instr) {
|
void Interpreter::or_(Registers& regs, u32 instr) {
|
||||||
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 Interpreter::nor(u32 instr) {
|
void Interpreter::nor(Registers& regs, u32 instr) {
|
||||||
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 Interpreter::j(u32 instr) {
|
void Interpreter::j(Registers& regs, u32 instr) {
|
||||||
s32 target = (instr & 0x3ffffff) << 2;
|
s32 target = (instr & 0x3ffffff) << 2;
|
||||||
s64 address = (regs.oldPC & ~0xfffffff) | target;
|
s64 address = (regs.oldPC & ~0xfffffff) | target;
|
||||||
if (check_address_error(address, 0b11)) {
|
if (check_address_error(address, 0b11)) {
|
||||||
@@ -527,127 +527,127 @@ void Interpreter::j(u32 instr) {
|
|||||||
FireException(regs, ExceptionCode::DataBusError, 0, regs.oldPC);
|
FireException(regs, ExceptionCode::DataBusError, 0, regs.oldPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
branch(true, address);
|
branch(regs, true, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::jal(u32 instr) {
|
void Interpreter::jal(Registers& regs, u32 instr) {
|
||||||
regs.gpr[31] = regs.nextPC;
|
regs.gpr[31] = regs.nextPC;
|
||||||
j(instr);
|
j(regs, instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::jalr(u32 instr) {
|
void Interpreter::jalr(Registers& regs, u32 instr) {
|
||||||
branch(true, regs.gpr[RS(instr)]);
|
branch(regs, true, regs.gpr[RS(instr)]);
|
||||||
regs.gpr[RD(instr)] = regs.pc + 4;
|
regs.gpr[RD(instr)] = regs.pc + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::slti(u32 instr) {
|
void Interpreter::slti(Registers& regs, u32 instr) {
|
||||||
regs.gpr[RT(instr)] = regs.gpr[RS(instr)] < se_imm(instr);
|
regs.gpr[RT(instr)] = regs.gpr[RS(instr)] < se_imm(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sltiu(u32 instr) {
|
void Interpreter::sltiu(Registers& regs, u32 instr) {
|
||||||
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 Interpreter::slt(u32 instr) {
|
void Interpreter::slt(Registers& regs, u32 instr) {
|
||||||
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 Interpreter::sltu(u32 instr) {
|
void Interpreter::sltu(Registers& regs, u32 instr) {
|
||||||
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 Interpreter::xori(u32 instr) {
|
void Interpreter::xori(Registers& regs, u32 instr) {
|
||||||
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 Interpreter::xor_(u32 instr) {
|
void Interpreter::xor_(Registers& regs, u32 instr) {
|
||||||
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 Interpreter::andi(u32 instr) {
|
void Interpreter::andi(Registers& regs, u32 instr) {
|
||||||
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 Interpreter::and_(u32 instr) {
|
void Interpreter::and_(Registers& regs, u32 instr) {
|
||||||
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 Interpreter::sll(u32 instr) {
|
void Interpreter::sll(Registers& regs, u32 instr) {
|
||||||
u8 sa = ((instr >> 6) & 0x1f);
|
u8 sa = ((instr >> 6) & 0x1f);
|
||||||
s32 result = regs.gpr[RT(instr)] << sa;
|
s32 result = regs.gpr[RT(instr)] << sa;
|
||||||
regs.gpr[RD(instr)] = (s64)result;
|
regs.gpr[RD(instr)] = (s64)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sllv(u32 instr) {
|
void Interpreter::sllv(Registers& regs, u32 instr) {
|
||||||
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)];
|
||||||
s32 result = rt << sa;
|
s32 result = rt << sa;
|
||||||
regs.gpr[RD(instr)] = (s64)result;
|
regs.gpr[RD(instr)] = (s64)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dsll32(u32 instr) {
|
void Interpreter::dsll32(Registers& regs, u32 instr) {
|
||||||
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);
|
||||||
regs.gpr[RD(instr)] = result;
|
regs.gpr[RD(instr)] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dsll(u32 instr) {
|
void Interpreter::dsll(Registers& regs, u32 instr) {
|
||||||
u8 sa = ((instr >> 6) & 0x1f);
|
u8 sa = ((instr >> 6) & 0x1f);
|
||||||
s64 result = regs.gpr[RT(instr)] << sa;
|
s64 result = regs.gpr[RT(instr)] << sa;
|
||||||
regs.gpr[RD(instr)] = result;
|
regs.gpr[RD(instr)] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dsllv(u32 instr) {
|
void Interpreter::dsllv(Registers& regs, u32 instr) {
|
||||||
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;
|
||||||
regs.gpr[RD(instr)] = result;
|
regs.gpr[RD(instr)] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::srl(u32 instr) {
|
void Interpreter::srl(Registers& regs, u32 instr) {
|
||||||
u32 rt = regs.gpr[RT(instr)];
|
u32 rt = regs.gpr[RT(instr)];
|
||||||
u8 sa = ((instr >> 6) & 0x1f);
|
u8 sa = ((instr >> 6) & 0x1f);
|
||||||
u32 result = rt >> sa;
|
u32 result = rt >> sa;
|
||||||
regs.gpr[RD(instr)] = (s32)result;
|
regs.gpr[RD(instr)] = (s32)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::srlv(u32 instr) {
|
void Interpreter::srlv(Registers& regs, u32 instr) {
|
||||||
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)];
|
||||||
s32 result = rt >> sa;
|
s32 result = rt >> sa;
|
||||||
regs.gpr[RD(instr)] = (s64)result;
|
regs.gpr[RD(instr)] = (s64)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dsrl(u32 instr) {
|
void Interpreter::dsrl(Registers& regs, u32 instr) {
|
||||||
u64 rt = regs.gpr[RT(instr)];
|
u64 rt = regs.gpr[RT(instr)];
|
||||||
u8 sa = ((instr >> 6) & 0x1f);
|
u8 sa = ((instr >> 6) & 0x1f);
|
||||||
u64 result = rt >> sa;
|
u64 result = rt >> sa;
|
||||||
regs.gpr[RD(instr)] = s64(result);
|
regs.gpr[RD(instr)] = s64(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dsrlv(u32 instr) {
|
void Interpreter::dsrlv(Registers& regs, u32 instr) {
|
||||||
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)];
|
||||||
u64 result = rt >> amount;
|
u64 result = rt >> amount;
|
||||||
regs.gpr[RD(instr)] = s64(result);
|
regs.gpr[RD(instr)] = s64(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dsrl32(u32 instr) {
|
void Interpreter::dsrl32(Registers& regs, u32 instr) {
|
||||||
u64 rt = regs.gpr[RT(instr)];
|
u64 rt = regs.gpr[RT(instr)];
|
||||||
u8 sa = ((instr >> 6) & 0x1f);
|
u8 sa = ((instr >> 6) & 0x1f);
|
||||||
u64 result = rt >> (sa + 32);
|
u64 result = rt >> (sa + 32);
|
||||||
regs.gpr[RD(instr)] = s64(result);
|
regs.gpr[RD(instr)] = s64(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sra(u32 instr) {
|
void Interpreter::sra(Registers& regs, u32 instr) {
|
||||||
s64 rt = regs.gpr[RT(instr)];
|
s64 rt = regs.gpr[RT(instr)];
|
||||||
u8 sa = ((instr >> 6) & 0x1f);
|
u8 sa = ((instr >> 6) & 0x1f);
|
||||||
s32 result = rt >> sa;
|
s32 result = rt >> sa;
|
||||||
regs.gpr[RD(instr)] = result;
|
regs.gpr[RD(instr)] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::srav(u32 instr) {
|
void Interpreter::srav(Registers& regs, u32 instr) {
|
||||||
s64 rt = regs.gpr[RT(instr)];
|
s64 rt = regs.gpr[RT(instr)];
|
||||||
s64 rs = regs.gpr[RS(instr)];
|
s64 rs = regs.gpr[RS(instr)];
|
||||||
u8 sa = rs & 0x1f;
|
u8 sa = rs & 0x1f;
|
||||||
@@ -655,14 +655,14 @@ void Interpreter::srav(u32 instr) {
|
|||||||
regs.gpr[RD(instr)] = result;
|
regs.gpr[RD(instr)] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dsra(u32 instr) {
|
void Interpreter::dsra(Registers& regs, u32 instr) {
|
||||||
s64 rt = regs.gpr[RT(instr)];
|
s64 rt = regs.gpr[RT(instr)];
|
||||||
u8 sa = ((instr >> 6) & 0x1f);
|
u8 sa = ((instr >> 6) & 0x1f);
|
||||||
s64 result = rt >> sa;
|
s64 result = rt >> sa;
|
||||||
regs.gpr[RD(instr)] = result;
|
regs.gpr[RD(instr)] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dsrav(u32 instr) {
|
void Interpreter::dsrav(Registers& regs, u32 instr) {
|
||||||
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 sa = rs & 63;
|
s64 sa = rs & 63;
|
||||||
@@ -670,24 +670,24 @@ void Interpreter::dsrav(u32 instr) {
|
|||||||
regs.gpr[RD(instr)] = result;
|
regs.gpr[RD(instr)] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dsra32(u32 instr) {
|
void Interpreter::dsra32(Registers& regs, u32 instr) {
|
||||||
s64 rt = regs.gpr[RT(instr)];
|
s64 rt = regs.gpr[RT(instr)];
|
||||||
u8 sa = ((instr >> 6) & 0x1f);
|
u8 sa = ((instr >> 6) & 0x1f);
|
||||||
s64 result = rt >> (sa + 32);
|
s64 result = rt >> (sa + 32);
|
||||||
regs.gpr[RD(instr)] = result;
|
regs.gpr[RD(instr)] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::jr(u32 instr) {
|
void Interpreter::jr(Registers& regs, u32 instr) {
|
||||||
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, regs.oldPC);
|
FireException(regs, ExceptionCode::DataBusError, 0, regs.oldPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
branch(true, address);
|
branch(regs, true, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dsub(u32 instr) {
|
void Interpreter::dsub(Registers& regs, u32 instr) {
|
||||||
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;
|
||||||
@@ -698,14 +698,14 @@ void Interpreter::dsub(u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dsubu(u32 instr) {
|
void Interpreter::dsubu(Registers& regs, u32 instr) {
|
||||||
u64 rt = regs.gpr[RT(instr)];
|
u64 rt = regs.gpr[RT(instr)];
|
||||||
u64 rs = regs.gpr[RS(instr)];
|
u64 rs = regs.gpr[RS(instr)];
|
||||||
u64 result = rs - rt;
|
u64 result = rs - rt;
|
||||||
regs.gpr[RD(instr)] = s64(result);
|
regs.gpr[RD(instr)] = s64(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::sub(u32 instr) {
|
void Interpreter::sub(Registers& regs, u32 instr) {
|
||||||
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;
|
||||||
@@ -716,14 +716,14 @@ void Interpreter::sub(u32 instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::subu(u32 instr) {
|
void Interpreter::subu(Registers& regs, u32 instr) {
|
||||||
u32 rt = regs.gpr[RT(instr)];
|
u32 rt = regs.gpr[RT(instr)];
|
||||||
u32 rs = regs.gpr[RS(instr)];
|
u32 rs = regs.gpr[RS(instr)];
|
||||||
u32 result = rs - rt;
|
u32 result = rs - rt;
|
||||||
regs.gpr[RD(instr)] = (s64)((s32)result);
|
regs.gpr[RD(instr)] = (s64)((s32)result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dmultu(u32 instr) {
|
void Interpreter::dmultu(Registers& regs, u32 instr) {
|
||||||
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;
|
||||||
@@ -731,7 +731,7 @@ void Interpreter::dmultu(u32 instr) {
|
|||||||
regs.hi = (s64)(result >> 64);
|
regs.hi = (s64)(result >> 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dmult(u32 instr) {
|
void Interpreter::dmult(Registers& regs, u32 instr) {
|
||||||
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;
|
||||||
@@ -739,7 +739,7 @@ void Interpreter::dmult(u32 instr) {
|
|||||||
regs.hi = result >> 64;
|
regs.hi = result >> 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::multu(u32 instr) {
|
void Interpreter::multu(Registers& regs, u32 instr) {
|
||||||
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;
|
||||||
@@ -747,7 +747,7 @@ void Interpreter::multu(u32 instr) {
|
|||||||
regs.hi = (s64)((s32)(result >> 32));
|
regs.hi = (s64)((s32)(result >> 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::mult(u32 instr) {
|
void Interpreter::mult(Registers& regs, u32 instr) {
|
||||||
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;
|
||||||
@@ -755,50 +755,50 @@ void Interpreter::mult(u32 instr) {
|
|||||||
regs.hi = (s64)((s32)(result >> 32));
|
regs.hi = (s64)((s32)(result >> 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::mflo(u32 instr) {
|
void Interpreter::mflo(Registers& regs, u32 instr) {
|
||||||
regs.gpr[RD(instr)] = regs.lo;
|
regs.gpr[RD(instr)] = regs.lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::mfhi(u32 instr) {
|
void Interpreter::mfhi(Registers& regs, u32 instr) {
|
||||||
regs.gpr[RD(instr)] = regs.hi;
|
regs.gpr[RD(instr)] = regs.hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::mtlo(u32 instr) {
|
void Interpreter::mtlo(Registers& regs, u32 instr) {
|
||||||
regs.lo = regs.gpr[RS(instr)];
|
regs.lo = regs.gpr[RS(instr)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::mthi(u32 instr) {
|
void Interpreter::mthi(Registers& regs, u32 instr) {
|
||||||
regs.hi = regs.gpr[RS(instr)];
|
regs.hi = regs.gpr[RS(instr)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::trap(bool cond) {
|
void Interpreter::trap(Registers& regs, bool cond) {
|
||||||
if(cond) {
|
if(cond) {
|
||||||
FireException(regs, ExceptionCode::Trap, 0, regs.oldPC);
|
FireException(regs, ExceptionCode::Trap, 0, regs.oldPC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::mtc2(u32 instr) {
|
void Interpreter::mtc2(Registers& regs, u32 instr) {
|
||||||
cop2Latch = regs.gpr[RT(instr)];
|
cop2Latch = regs.gpr[RT(instr)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::mfc2(u32 instr) {
|
void Interpreter::mfc2(Registers& regs, u32 instr) {
|
||||||
s32 value = cop2Latch;
|
s32 value = cop2Latch;
|
||||||
regs.gpr[RT(instr)] = value;
|
regs.gpr[RT(instr)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dmtc2(u32 instr) {
|
void Interpreter::dmtc2(Registers& regs, u32 instr) {
|
||||||
cop2Latch = regs.gpr[RT(instr)];
|
cop2Latch = regs.gpr[RT(instr)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::dmfc2(u32 instr) {
|
void Interpreter::dmfc2(Registers& regs, u32 instr) {
|
||||||
regs.gpr[RT(instr)] = cop2Latch;
|
regs.gpr[RT(instr)] = cop2Latch;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::ctc2(u32) {
|
void Interpreter::ctc2(Registers& regs, u32) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::cfc2(u32) {
|
void Interpreter::cfc2(Registers& regs, u32) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,7 @@ void Cop1::Reset() {
|
|||||||
memset(fgr, 0, 32 * sizeof(FGR));
|
memset(fgr, 0, 32 * sizeof(FGR));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cop1::decode(Interpreter& cpu, u32 instr) {
|
void Cop1::decode(Registers& regs, Interpreter& cpu, u32 instr) {
|
||||||
Registers& regs = cpu.regs;
|
|
||||||
if(!regs.cop0.status.cu1) {
|
if(!regs.cop0.status.cu1) {
|
||||||
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, regs.oldPC);
|
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, regs.oldPC);
|
||||||
return;
|
return;
|
||||||
@@ -36,10 +35,10 @@ void Cop1::decode(Interpreter& cpu, u32 instr) {
|
|||||||
case 0x07: FireException(regs, ExceptionCode::ReservedInstruction, 1, regs.oldPC); break;
|
case 0x07: FireException(regs, ExceptionCode::ReservedInstruction, 1, regs.oldPC); break;
|
||||||
case 0x08:
|
case 0x08:
|
||||||
switch(mask_branch) {
|
switch(mask_branch) {
|
||||||
case 0: cpu.b(instr, !regs.cop1.fcr31.compare); break;
|
case 0: cpu.b(regs, instr, !regs.cop1.fcr31.compare); break;
|
||||||
case 1: cpu.b(instr, regs.cop1.fcr31.compare); break;
|
case 1: cpu.b(regs, instr, regs.cop1.fcr31.compare); break;
|
||||||
case 2: cpu.bl(instr, !regs.cop1.fcr31.compare); break;
|
case 2: cpu.bl(regs, instr, !regs.cop1.fcr31.compare); break;
|
||||||
case 3: cpu.bl(instr, regs.cop1.fcr31.compare); break;
|
case 3: cpu.bl(regs, instr, regs.cop1.fcr31.compare); break;
|
||||||
default: util::panic("Undefined BC COP1 {:02X}\n", mask_branch);
|
default: util::panic("Undefined BC COP1 {:02X}\n", mask_branch);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ struct Cop1 {
|
|||||||
FCR31 fcr31{};
|
FCR31 fcr31{};
|
||||||
FGR fgr[32]{};
|
FGR fgr[32]{};
|
||||||
void Reset();
|
void Reset();
|
||||||
void decode(Interpreter&, u32);
|
void decode(Registers&, Interpreter&, u32);
|
||||||
friend struct Interpreter;
|
friend struct Interpreter;
|
||||||
private:
|
private:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
Reference in New Issue
Block a user