Instruction struct rewrite in RSP too now

This commit is contained in:
irisz64
2025-09-01 09:47:07 +02:00
parent e795c256f2
commit 5444df993c
9 changed files with 578 additions and 585 deletions

View File

@@ -25,7 +25,7 @@ private:
bool ShouldServiceInterrupt() const; bool ShouldServiceInterrupt() const;
void CheckCompareInterrupt(); void CheckCompareInterrupt();
void cop2Decode(u32); void cop2Decode(Instruction);
void special(Instruction); void special(Instruction);
void regimm(Instruction); void regimm(Instruction);
void Exec(Instruction); void Exec(Instruction);

View File

@@ -4,6 +4,7 @@
#include <array> #include <array>
#include <core/RDP.hpp> #include <core/RDP.hpp>
#include <core/mmio/MI.hpp> #include <core/mmio/MI.hpp>
#include <Instruction.hpp>
#define RSP_BYTE(addr) (dmem[BYTE_ADDRESS(addr) & 0xFFF]) #define RSP_BYTE(addr) (dmem[BYTE_ADDRESS(addr) & 0xFFF])
#define GET_RSP_HALF(addr) ((RSP_BYTE(addr) << 8) | RSP_BYTE((addr) + 1)) #define GET_RSP_HALF(addr) ((RSP_BYTE(addr) << 8) | RSP_BYTE((addr) + 1))
@@ -134,7 +135,7 @@ struct RSP {
void SetVTE(const VPR &vt, u8 e); void SetVTE(const VPR &vt, u8 e);
auto Read(u32 addr) -> u32; auto Read(u32 addr) -> u32;
void Write(u32 addr, u32 val); void Write(u32 addr, u32 val);
void Exec(u32 instr); void Exec(const Instruction instr);
SPStatus spStatus{}; SPStatus spStatus{};
u16 oldPC{}, pc{}, nextPC{}; u16 oldPC{}, pc{}, nextPC{};
SPDMASPAddr spDMASPAddr{}; SPDMASPAddr spDMASPAddr{};
@@ -256,120 +257,120 @@ struct RSP {
FORCE_INLINE void ReleaseSemaphore() { semaphore = false; } FORCE_INLINE void ReleaseSemaphore() { semaphore = false; }
void special(const u32 instr); void special(const Instruction instr);
void regimm(const u32 instr); void regimm(const Instruction instr);
void lwc2(const u32 instr); void lwc2(const Instruction instr);
void swc2(const u32 instr); void swc2(const Instruction instr);
void cop2(const u32 instr); void cop2(const Instruction instr);
void cop0(const u32 instr); void cop0(const Instruction instr);
void add(u32 instr); void add(Instruction instr);
void addi(u32 instr); void addi(Instruction instr);
void and_(u32 instr); void and_(Instruction instr);
void andi(u32 instr); void andi(Instruction instr);
void b(u32 instr, bool cond); void b(Instruction instr, bool cond);
void blink(u32 instr, bool cond); void blink(Instruction instr, bool cond);
void cfc2(u32 instr); void cfc2(Instruction instr);
void ctc2(u32 instr); void ctc2(Instruction instr);
void lb(u32 instr); void lb(Instruction instr);
void lh(u32 instr); void lh(Instruction instr);
void lw(u32 instr); void lw(Instruction instr);
void lbu(u32 instr); void lbu(Instruction instr);
void lhu(u32 instr); void lhu(Instruction instr);
void lui(u32 instr); void lui(Instruction instr);
void luv(u32 instr); void luv(Instruction instr);
void lbv(u32 instr); void lbv(Instruction instr);
void ldv(u32 instr); void ldv(Instruction instr);
void lsv(u32 instr); void lsv(Instruction instr);
void llv(u32 instr); void llv(Instruction instr);
void lrv(u32 instr); void lrv(Instruction instr);
void lqv(u32 instr); void lqv(Instruction instr);
void lfv(u32 instr); void lfv(Instruction instr);
void lhv(u32 instr); void lhv(Instruction instr);
void ltv(u32 instr); void ltv(Instruction instr);
void lpv(u32 instr); void lpv(Instruction instr);
void j(u32 instr); void j(Instruction instr);
void jal(u32 instr); void jal(Instruction instr);
void jr(u32 instr); void jr(Instruction instr);
void jalr(u32 instr); void jalr(Instruction instr);
void nor(u32 instr); void nor(Instruction instr);
void or_(u32 instr); void or_(Instruction instr);
void ori(u32 instr); void ori(Instruction instr);
void xor_(u32 instr); void xor_(Instruction instr);
void xori(u32 instr); void xori(Instruction instr);
void sb(u32 instr); void sb(Instruction instr);
void sh(u32 instr); void sh(Instruction instr);
void sw(u32 instr); void sw(Instruction instr);
void swv(u32 instr); void swv(Instruction instr);
void sub(u32 instr); void sub(Instruction instr);
void sbv(u32 instr); void sbv(Instruction instr);
void sdv(u32 instr); void sdv(Instruction instr);
void stv(u32 instr); void stv(Instruction instr);
void sqv(u32 instr); void sqv(Instruction instr);
void ssv(u32 instr); void ssv(Instruction instr);
void suv(u32 instr); void suv(Instruction instr);
void slv(u32 instr); void slv(Instruction instr);
void shv(u32 instr); void shv(Instruction instr);
void sfv(u32 instr); void sfv(Instruction instr);
void srv(u32 instr); void srv(Instruction instr);
void spv(u32 instr); void spv(Instruction instr);
void sllv(u32 instr); void sllv(Instruction instr);
void srlv(u32 instr); void srlv(Instruction instr);
void srav(u32 instr); void srav(Instruction instr);
void sll(u32 instr); void sll(Instruction instr);
void srl(u32 instr); void srl(Instruction instr);
void sra(u32 instr); void sra(Instruction instr);
void slt(u32 instr); void slt(Instruction instr);
void sltu(u32 instr); void sltu(Instruction instr);
void slti(u32 instr); void slti(Instruction instr);
void sltiu(u32 instr); void sltiu(Instruction instr);
void vabs(u32 instr); void vabs(Instruction instr);
void vadd(u32 instr); void vadd(Instruction instr);
void vaddc(u32 instr); void vaddc(Instruction instr);
void vand(u32 instr); void vand(Instruction instr);
void vnand(u32 instr); void vnand(Instruction instr);
void vch(u32 instr); void vch(Instruction instr);
void vcr(u32 instr); void vcr(Instruction instr);
void vcl(u32 instr); void vcl(Instruction instr);
void vmacf(u32 instr); void vmacf(Instruction instr);
void vmacu(u32 instr); void vmacu(Instruction instr);
void vmacq(u32 instr); void vmacq(Instruction instr);
void vmadh(u32 instr); void vmadh(Instruction instr);
void vmadl(u32 instr); void vmadl(Instruction instr);
void vmadm(u32 instr); void vmadm(Instruction instr);
void vmadn(u32 instr); void vmadn(Instruction instr);
void vmov(u32 instr); void vmov(Instruction instr);
void vmulf(u32 instr); void vmulf(Instruction instr);
void vmulu(u32 instr); void vmulu(Instruction instr);
void vmulq(u32 instr); void vmulq(Instruction instr);
void vmudl(u32 instr); void vmudl(Instruction instr);
void vmudh(u32 instr); void vmudh(Instruction instr);
void vmudm(u32 instr); void vmudm(Instruction instr);
void vmudn(u32 instr); void vmudn(Instruction instr);
void vmrg(u32 instr); void vmrg(Instruction instr);
void vlt(u32 instr); void vlt(Instruction instr);
void veq(u32 instr); void veq(Instruction instr);
void vne(u32 instr); void vne(Instruction instr);
void vge(u32 instr); void vge(Instruction instr);
void vrcp(u32 instr); void vrcp(Instruction instr);
void vrsq(u32 instr); void vrsq(Instruction instr);
void vrcpl(u32 instr); void vrcpl(Instruction instr);
void vrsql(u32 instr); void vrsql(Instruction instr);
void vrndp(u32 instr); void vrndp(Instruction instr);
void vrndn(u32 instr); void vrndn(Instruction instr);
void vrcph(u32 instr); void vrcph(Instruction instr);
void vsar(u32 instr); void vsar(Instruction instr);
void vsub(u32 instr); void vsub(Instruction instr);
void vsubc(u32 instr); void vsubc(Instruction instr);
void vxor(u32 instr); void vxor(Instruction instr);
void vnxor(u32 instr); void vnxor(Instruction instr);
void vor(u32 instr); void vor(Instruction instr);
void vnor(u32 instr); void vnor(Instruction instr);
void vzero(u32 instr); void vzero(Instruction instr);
void mfc0(const RDP &rdp, u32 instr); void mfc0(const RDP &rdp, Instruction instr);
void mtc0(u32 instr) const; void mtc0(Instruction instr) const;
void mfc2(u32 instr); void mfc2(Instruction instr);
void mtc2(u32 instr); void mtc2(Instruction instr);
template <bool toRdram> template <bool toRdram>
void DMA(); void DMA();

View File

@@ -220,12 +220,12 @@ void Interpreter::regimm(const Instruction instr) {
} }
} }
void Interpreter::cop2Decode(const u32 instr) { void Interpreter::cop2Decode(const Instruction instr) {
if (!regs.cop0.status.cu2) { if (!regs.cop0.status.cu2) {
regs.cop0.FireException(ExceptionCode::CoprocessorUnusable, 2, regs.oldPC); regs.cop0.FireException(ExceptionCode::CoprocessorUnusable, 2, regs.oldPC);
return; return;
} }
switch (RS(instr)) { switch (instr.rs()) {
case 0x00: case 0x00:
mfc2(instr); mfc2(instr);
break; break;

View File

@@ -127,22 +127,22 @@ void JIT::special(const Instruction instr) {
dsubu(instr); dsubu(instr);
break; break;
case Instruction::TGE: case Instruction::TGE:
trap(regs.Read<s64>(RS(instr)) >= regs.Read<s64>(RT(instr))); trap(regs.Read<s64>(instr.rs()) >= regs.Read<s64>(instr.rt()));
break; break;
case Instruction::TGEU: case Instruction::TGEU:
trap(regs.Read<u64>(RS(instr)) >= regs.Read<u64>(RT(instr))); trap(regs.Read<u64>(instr.rs()) >= regs.Read<u64>(instr.rt()));
break; break;
case Instruction::TLT: case Instruction::TLT:
trap(regs.Read<s64>(RS(instr)) < regs.Read<s64>(RT(instr))); trap(regs.Read<s64>(instr.rs()) < regs.Read<s64>(instr.rt()));
break; break;
case Instruction::TLTU: case Instruction::TLTU:
trap(regs.Read<u64>(RS(instr)) < regs.Read<u64>(RT(instr))); trap(regs.Read<u64>(instr.rs()) < regs.Read<u64>(instr.rt()));
break; break;
case Instruction::TEQ: case Instruction::TEQ:
trap(regs.Read<s64>(RS(instr)) == regs.Read<s64>(RT(instr))); trap(regs.Read<s64>(instr.rs()) == regs.Read<s64>(instr.rt()));
break; break;
case Instruction::TNE: case Instruction::TNE:
trap(regs.Read<s64>(RS(instr)) != regs.Read<s64>(RT(instr))); trap(regs.Read<s64>(instr.rs()) != regs.Read<s64>(instr.rt()));
break; break;
case Instruction::DSLL: case Instruction::DSLL:
dsll(instr); dsll(instr);
@@ -184,22 +184,22 @@ void JIT::regimm(const Instruction instr) {
bgezl(instr); bgezl(instr);
break; break;
case Instruction::TGEI: case Instruction::TGEI:
trap(regs.Read<s64>(RS(instr)) >= static_cast<s64>(static_cast<s16>(instr))); trap(regs.Read<s64>(instr.rs()) >= static_cast<s64>(static_cast<s16>(instr)));
break; break;
case Instruction::TGEIU: case Instruction::TGEIU:
trap(regs.Read<u64>(RS(instr)) >= static_cast<u64>(static_cast<s64>(static_cast<s16>(instr)))); trap(regs.Read<u64>(instr.rs()) >= static_cast<u64>(static_cast<s64>(static_cast<s16>(instr))));
break; break;
case Instruction::TLTI: case Instruction::TLTI:
trap(regs.Read<s64>(RS(instr)) < static_cast<s64>(static_cast<s16>(instr))); trap(regs.Read<s64>(instr.rs()) < static_cast<s64>(static_cast<s16>(instr)));
break; break;
case Instruction::TLTIU: case Instruction::TLTIU:
trap(regs.Read<u64>(RS(instr)) < static_cast<u64>(static_cast<s64>(static_cast<s16>(instr)))); trap(regs.Read<u64>(instr.rs()) < static_cast<u64>(static_cast<s64>(static_cast<s16>(instr))));
break; break;
case Instruction::TEQI: case Instruction::TEQI:
trap(regs.Read<s64>(RS(instr)) == static_cast<s64>(static_cast<s16>(instr))); trap(regs.Read<s64>(instr.rs()) == static_cast<s64>(static_cast<s16>(instr)));
break; break;
case Instruction::TNEI: case Instruction::TNEI:
trap(regs.Read<s64>(RS(instr)) != static_cast<s64>(static_cast<s16>(instr))); trap(regs.Read<s64>(instr.rs()) != static_cast<s64>(static_cast<s16>(instr)));
break; break;
case Instruction::BLTZAL: case Instruction::BLTZAL:
bltzal(instr); bltzal(instr);

View File

@@ -949,8 +949,8 @@ void JIT::ld(const Instruction instr) {
} }
void JIT::ldc1(const Instruction instr) { void JIT::ldc1(const Instruction instr) {
if (regs.IsRegConstant(BASE(instr))) { if (regs.IsRegConstant(instr.base())) {
const u64 addr = static_cast<s64>(static_cast<s16>(instr)) + regs.Read<s64>(BASE(instr)); const u64 addr = static_cast<s64>(static_cast<s16>(instr)) + regs.Read<s64>(instr.base());
if (u32 physical; !regs.cop0.MapVAddr(Cop0::LOAD, addr, physical)) { if (u32 physical; !regs.cop0.MapVAddr(Cop0::LOAD, addr, physical)) {
// regs.cop0.HandleTLBException(addr); // regs.cop0.HandleTLBException(addr);
@@ -958,8 +958,8 @@ void JIT::ldc1(const Instruction instr) {
panic("[JIT]: Unhandled TLBL exception in LD1!"); panic("[JIT]: Unhandled TLBL exception in LD1!");
} else { } else {
const u64 data = mem.Read<u64>(physical); const u64 data = mem.Read<u64>(physical);
regs.cop1.FGR_T<u64>(regs.cop0.status, FT(instr)) = data; regs.cop1.FGR_T<u64>(regs.cop0.status, instr.ft()) = data;
regs.cop1.fgrIsConstant[FT(instr)] = true; regs.cop1.fgrIsConstant[instr.ft()] = true;
} }
} else { } else {
panic("[JIT]: Implement non constant LD1!"); panic("[JIT]: Implement non constant LD1!");

View File

@@ -2,9 +2,9 @@
#include <log.hpp> #include <log.hpp>
namespace n64 { namespace n64 {
void RSP::special(const u32 instr) { void RSP::special(const Instruction instr) {
MI& mi = Core::GetMem().mmio.mi; MI& mi = Core::GetMem().mmio.mi;
switch (const u8 mask = instr & 0x3f) { switch (instr.cop_funct()) {
case 0x00: case 0x00:
if (instr != 0) { if (instr != 0) {
sll(instr); sll(instr);
@@ -66,31 +66,31 @@ void RSP::special(const u32 instr) {
sltu(instr); sltu(instr);
break; break;
default: default:
panic("Unhandled RSP special instruction ({:06b})", mask); panic("Unhandled RSP special instruction ({:06b})", instr.cop_funct());
} }
} }
void RSP::regimm(const u32 instr) { void RSP::regimm(const Instruction instr) {
switch (const u8 mask = instr >> 16 & 0x1F) { switch (instr.cop_rt()) {
case 0x00: case 0x00:
b(instr, gpr[RS(instr)] < 0); b(instr, gpr[instr.rs()] < 0);
break; break;
case 0x01: case 0x01:
b(instr, gpr[RS(instr)] >= 0); b(instr, gpr[instr.rs()] >= 0);
break; break;
case 0x10: case 0x10:
blink(instr, gpr[RS(instr)] < 0); blink(instr, gpr[instr.rs()] < 0);
break; break;
case 0x11: case 0x11:
blink(instr, gpr[RS(instr)] >= 0); blink(instr, gpr[instr.rs()] >= 0);
break; break;
default: default:
panic("Unhandled RSP regimm instruction ({:05b})", mask); panic("Unhandled RSP regimm instruction ({:05b})", instr.cop_rt());
} }
} }
void RSP::lwc2(const u32 instr) { void RSP::lwc2(const Instruction instr) {
switch (const u8 mask = instr >> 11 & 0x1F) { switch (instr.rd()) {
case 0x00: case 0x00:
lbv(instr); lbv(instr);
break; break;
@@ -127,12 +127,12 @@ void RSP::lwc2(const u32 instr) {
ltv(instr); ltv(instr);
break; break;
default: default:
panic("Unhandled RSP LWC2 {:05b}", mask); panic("Unhandled RSP LWC2 {:05b}", instr.rd());
} }
} }
void RSP::swc2(const u32 instr) { void RSP::swc2(const Instruction instr) {
switch (const u8 mask = instr >> 11 & 0x1F) { switch (instr.rd()) {
case 0x00: case 0x00:
sbv(instr); sbv(instr);
break; break;
@@ -170,18 +170,17 @@ void RSP::swc2(const u32 instr) {
stv(instr); stv(instr);
break; break;
default: default:
panic("Unhandled RSP SWC2 {:05b}", mask); panic("Unhandled RSP SWC2 {:05b}", instr.rd());
} }
} }
void RSP::cop2(const u32 instr) { void RSP::cop2(const Instruction instr) {
const u8 mask_sub = instr >> 21 & 0x1F; switch (instr.cop_funct()) {
switch (const u8 mask = instr & 0x3F) {
case 0x00: case 0x00:
if (instr >> 25 & 1) { if (instr >> 25 & 1) {
vmulf(instr); vmulf(instr);
} else { } else {
switch (mask_sub) { switch (instr.cop_rs()) {
case 0x00: case 0x00:
mfc2(instr); mfc2(instr);
break; break;
@@ -195,7 +194,7 @@ void RSP::cop2(const u32 instr) {
ctc2(instr); ctc2(instr);
break; break;
default: default:
panic("Unhandled RSP COP2 sub ({:05b})", mask_sub); panic("Unhandled RSP COP2 sub ({:05b})", instr.cop_rs());
} }
} }
break; break;
@@ -340,13 +339,13 @@ void RSP::cop2(const u32 instr) {
case 0x3F: case 0x3F:
break; break;
default: default:
panic("Unhandled RSP COP2 ({:06b})", mask); panic("Unhandled RSP COP2 ({:06b})", instr.cop_funct());
} }
} }
void RSP::cop0(const u32 instr) { void RSP::cop0(const Instruction instr) {
if ((instr & 0x7FF) == 0) { if ((instr & 0x7FF) == 0) {
switch (const u8 mask = instr >> 21 & 0x1F) { switch (instr.cop_rs()) {
case 0x00: case 0x00:
mfc0(Core::GetMem().mmio.rdp, instr); mfc0(Core::GetMem().mmio.rdp, instr);
break; break;
@@ -354,18 +353,18 @@ void RSP::cop0(const u32 instr) {
mtc0(instr); mtc0(instr);
break; break;
default: default:
panic("Unhandled RSP COP0 ({:05b})", mask); panic("Unhandled RSP COP0 ({:05b})", instr.cop_rs());
} }
} else { } else {
panic("RSP COP0 unknown {:08X}", instr); panic("RSP COP0 unknown {:08X}", u32(instr));
} }
} }
void RSP::Exec(const u32 instr) { void RSP::Exec(const Instruction instr) {
Mem& mem = Core::GetMem(); Mem& mem = Core::GetMem();
MMIO &mmio = mem.mmio; MMIO &mmio = mem.mmio;
MI &mi = mmio.mi; MI &mi = mmio.mi;
switch (const u8 mask = instr >> 26 & 0x3F) { switch (instr.opcode()) {
case 0x00: case 0x00:
special(instr); special(instr);
break; break;
@@ -379,16 +378,16 @@ void RSP::Exec(const u32 instr) {
jal(instr); jal(instr);
break; break;
case 0x04: case 0x04:
b(instr, gpr[RT(instr)] == gpr[RS(instr)]); b(instr, gpr[instr.rt()] == gpr[instr.rs()]);
break; break;
case 0x05: case 0x05:
b(instr, gpr[RT(instr)] != gpr[RS(instr)]); b(instr, gpr[instr.rt()] != gpr[instr.rs()]);
break; break;
case 0x06: case 0x06:
b(instr, gpr[RS(instr)] <= 0); b(instr, gpr[instr.rs()] <= 0);
break; break;
case 0x07: case 0x07:
b(instr, gpr[RS(instr)] > 0); b(instr, gpr[instr.rs()] > 0);
break; break;
case 0x08: case 0x08:
case 0x09: case 0x09:
@@ -451,7 +450,7 @@ void RSP::Exec(const u32 instr) {
break; break;
default: default:
mem.DumpIMEM(); mem.DumpIMEM();
panic("Unhandled RSP instruction ({:06b}, {:04X})", mask, oldPC); panic("Unhandled RSP instruction ({:06b}, {:04X})", instr.opcode(), oldPC);
} }
} }
} // namespace n64 } // namespace n64

File diff suppressed because it is too large Load Diff

View File

@@ -27,18 +27,6 @@ static FORCE_INLINE constexpr u32 GetVideoFrequency(bool pal) {
#define HALF_ADDRESS(addr) ((addr) ^ 2) #define HALF_ADDRESS(addr) ((addr) ^ 2)
#define BYTE_ADDRESS(addr) ((addr) ^ 3) #define BYTE_ADDRESS(addr) ((addr) ^ 3)
#define RD(x) (((x) >> 11) & 0x1F)
#define RT(x) (((x) >> 16) & 0x1F)
#define RS(x) (((x) >> 21) & 0x1F)
#define FD(x) (((x) >> 6) & 0x1F)
#define FT(x) RT(x)
#define FS(x) RD(x)
#define BASE(x) RS(x)
#define VT(x) (((x) >> 16) & 0x1F)
#define VS(x) (((x) >> 11) & 0x1F)
#define VD(x) (((x) >> 6) & 0x1F)
#define E1(x) (((x) >> 7) & 0x0F)
#define E2(x) (((x) >> 21) & 0x0F)
#define ELEMENT_INDEX(i) (7 - (i)) #define ELEMENT_INDEX(i) (7 - (i))
#define BYTE_INDEX(i) (15 - (i)) #define BYTE_INDEX(i) (15 - (i))

View File

@@ -16,6 +16,11 @@ struct Instruction {
inline u8 ft() const { return rt(); } inline u8 ft() const { return rt(); }
inline u8 fd() const { return sa(); } inline u8 fd() const { return sa(); }
inline u8 base() const { return rs(); } inline u8 base() const { return rs(); }
inline u8 vt() const { return rt(); }
inline u8 vs() const { return rd(); }
inline u8 vd() const { return fd(); }
inline u8 e1() const { return (instr.raw >> 7) & 0x0f; }
inline u8 e2() const { return rs() & 0x0f; }
inline u16 imm() const { return instr.itype.imm; } inline u16 imm() const { return instr.itype.imm; }
inline u32 target() const { return instr.jtype.target; } inline u32 target() const { return instr.jtype.target; }
inline u8 opcode() const { return instr.opcode.op; } inline u8 opcode() const { return instr.opcode.op; }