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;
void CheckCompareInterrupt();
void cop2Decode(u32);
void cop2Decode(Instruction);
void special(Instruction);
void regimm(Instruction);
void Exec(Instruction);

View File

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

View File

@@ -127,22 +127,22 @@ void JIT::special(const Instruction instr) {
dsubu(instr);
break;
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;
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;
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;
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;
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;
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;
case Instruction::DSLL:
dsll(instr);
@@ -184,22 +184,22 @@ void JIT::regimm(const Instruction instr) {
bgezl(instr);
break;
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;
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;
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;
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;
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;
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;
case Instruction::BLTZAL:
bltzal(instr);

View File

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

View File

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

View File

@@ -16,6 +16,11 @@ struct Instruction {
inline u8 ft() const { return rt(); }
inline u8 fd() const { return sa(); }
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 u32 target() const { return instr.jtype.target; }
inline u8 opcode() const { return instr.opcode.op; }