From dd98e19c9555112030a3a7f7be744729891517b4 Mon Sep 17 00:00:00 2001 From: irisz64 Date: Thu, 28 Aug 2025 09:25:22 +0200 Subject: [PATCH] Continue big Instruction struct rewrite --- src/backend/Core.cpp | 2 + src/backend/Core.hpp | 16 +- src/backend/core/Interpreter.hpp | 182 +++++++++--------- src/backend/core/interpreter/decode.cpp | 246 +++++++++++------------- src/backend/core/registers/Cop0.cpp | 18 +- src/backend/core/registers/Cop0.hpp | 3 +- src/backend/core/registers/Cop1.cpp | 44 ++++- src/backend/core/registers/Cop1.hpp | 131 ++++++------- src/utils/Instruction.hpp | 83 +++++++- 9 files changed, 399 insertions(+), 326 deletions(-) diff --git a/src/backend/Core.cpp b/src/backend/Core.cpp index a2395639..f1369229 100644 --- a/src/backend/Core.cpp +++ b/src/backend/Core.cpp @@ -7,9 +7,11 @@ namespace n64 { Core::Core() { auto cpuType = Options::GetInstance().GetValue("cpu", "type"); if (cpuType == "interpreter") { + cpuType = Interpreted; cpu = std::make_unique(parallel, *mem, regs); } else if(cpuType == "jit") { #ifndef __aarch64__ + cpuType = DynamicRecompiler; cpu = std::make_unique(parallel, *mem, regs); #else panic("JIT currently unsupported on aarch64"); diff --git a/src/backend/Core.hpp b/src/backend/Core.hpp index 87ca650c..2588ba82 100644 --- a/src/backend/Core.hpp +++ b/src/backend/Core.hpp @@ -11,7 +11,7 @@ struct Core { Interpreted, DynamicRecompiler, CachedInterpreter - }; + } cpuType = Interpreted; explicit Core(); @@ -28,6 +28,20 @@ struct Core { return *GetInstance().mem; } + static Interpreter& GetInterpreter() { + if(GetInstance().cpuType == Interpreted) + return *dynamic_cast(GetInstance().cpu.get()); + + panic("Tried to get interpreter when other cpu type is used."); + } + + static JIT& GetDynamicRecompiler() { + if(GetInstance().cpuType == DynamicRecompiler) + return *dynamic_cast(GetInstance().cpu.get()); + + panic("Tried to get interpreter when other cpu type is used."); + } + int StepCPU(); void StepRSP(int cpuCycles); void Stop(); diff --git a/src/backend/core/Interpreter.hpp b/src/backend/core/Interpreter.hpp index c6aae436..02a2bb63 100644 --- a/src/backend/core/Interpreter.hpp +++ b/src/backend/core/Interpreter.hpp @@ -26,100 +26,100 @@ private: void CheckCompareInterrupt(); void cop2Decode(u32); - void special(u32); - void regimm(u32); - void Exec(u32); - void add(u32); - void addu(u32); - void addi(u32); - void addiu(u32); - void andi(u32); - void and_(u32); + void special(Instruction); + void regimm(Instruction); + void Exec(Instruction); + void add(Instruction); + void addu(Instruction); + void addi(Instruction); + void addiu(Instruction); + void andi(Instruction); + void and_(Instruction); void branch(bool, s64); void branch_likely(bool, s64); - void b(u32, bool); - void blink(u32, bool); - void bl(u32, bool); - void bllink(u32, bool); - void dadd(u32); - void daddu(u32); - void daddi(u32); - void daddiu(u32); - void ddiv(u32); - void ddivu(u32); - void div(u32); - void divu(u32); - void dmult(u32); - void dmultu(u32); - void dsll(u32); - void dsllv(u32); - void dsll32(u32); - void dsra(u32); - void dsrav(u32); - void dsra32(u32); - void dsrl(u32); - void dsrlv(u32); - void dsrl32(u32); - void dsub(u32); - void dsubu(u32); - void j(u32); - void jr(u32); - void jal(u32); - void jalr(u32); - void lui(u32); - void lbu(u32); - void lb(u32); - void ld(u32); - void ldl(u32); - void ldr(u32); - void lh(u32); - void lhu(u32); - void ll(u32); - void lld(u32); - void lw(u32); - void lwl(u32); - void lwu(u32); - void lwr(u32); - void mfhi(u32); - void mflo(u32); - void mult(u32); - void multu(u32); - void mthi(u32); - void mtlo(u32); - void nor(u32); - void sb(u32); - void sc(u32); - void scd(u32); - void sd(u32); - void sdl(u32); - void sdr(u32); - void sh(u32); - void sw(u32); - void swl(u32); - void swr(u32); - void slti(u32); - void sltiu(u32); - void slt(u32); - void sltu(u32); - void sll(u32); - void sllv(u32); - void sub(u32); - void subu(u32); - void sra(u32); - void srav(u32); - void srl(u32); - void srlv(u32); + void b(Instruction, bool); + void blink(Instruction, bool); + void bl(Instruction, bool); + void bllink(Instruction, bool); + void dadd(Instruction); + void daddu(Instruction); + void daddi(Instruction); + void daddiu(Instruction); + void ddiv(Instruction); + void ddivu(Instruction); + void div(Instruction); + void divu(Instruction); + void dmult(Instruction); + void dmultu(Instruction); + void dsll(Instruction); + void dsllv(Instruction); + void dsll32(Instruction); + void dsra(Instruction); + void dsrav(Instruction); + void dsra32(Instruction); + void dsrl(Instruction); + void dsrlv(Instruction); + void dsrl32(Instruction); + void dsub(Instruction); + void dsubu(Instruction); + void j(Instruction); + void jr(Instruction); + void jal(Instruction); + void jalr(Instruction); + void lui(Instruction); + void lbu(Instruction); + void lb(Instruction); + void ld(Instruction); + void ldl(Instruction); + void ldr(Instruction); + void lh(Instruction); + void lhu(Instruction); + void ll(Instruction); + void lld(Instruction); + void lw(Instruction); + void lwl(Instruction); + void lwu(Instruction); + void lwr(Instruction); + void mfhi(Instruction); + void mflo(Instruction); + void mult(Instruction); + void multu(Instruction); + void mthi(Instruction); + void mtlo(Instruction); + void nor(Instruction); + void sb(Instruction); + void sc(Instruction); + void scd(Instruction); + void sd(Instruction); + void sdl(Instruction); + void sdr(Instruction); + void sh(Instruction); + void sw(Instruction); + void swl(Instruction); + void swr(Instruction); + void slti(Instruction); + void sltiu(Instruction); + void slt(Instruction); + void sltu(Instruction); + void sll(Instruction); + void sllv(Instruction); + void sub(Instruction); + void subu(Instruction); + void sra(Instruction); + void srav(Instruction); + void srl(Instruction); + void srlv(Instruction); void trap(bool) const; - void or_(u32); - void ori(u32); - void xor_(u32); - void xori(u32); + void or_(Instruction); + void ori(Instruction); + void xor_(Instruction); + void xori(Instruction); - void mtc2(u32); - void mfc2(u32); - void dmtc2(u32); - void dmfc2(u32); - void ctc2(u32); - void cfc2(u32); + void mtc2(Instruction); + void mfc2(Instruction); + void dmtc2(Instruction); + void dmfc2(Instruction); + void ctc2(Instruction); + void cfc2(Instruction); }; } // namespace n64 diff --git a/src/backend/core/interpreter/decode.cpp b/src/backend/core/interpreter/decode.cpp index 08cd85db..3aa84433 100644 --- a/src/backend/core/interpreter/decode.cpp +++ b/src/backend/core/interpreter/decode.cpp @@ -4,12 +4,11 @@ #include namespace n64 { -void Interpreter::special(const u32 instr) { - Instruction helper(instr); +void Interpreter::special(const Instruction instr) { // 00rr_rccc - switch (helper.special()) { + switch (instr.instr.opcode.special) { case Instruction::SLL: - if (instr != 0) { + if (instr.instr.raw != 0) { sll(instr); } break; @@ -130,22 +129,22 @@ void Interpreter::special(const u32 instr) { dsubu(instr); break; case Instruction::TGE: - trap(regs.Read(RS(instr)) >= regs.Read(RT(instr))); + trap(regs.Read(instr.rs()) >= regs.Read(instr.rt())); break; case Instruction::TGEU: - trap(regs.Read(RS(instr)) >= regs.Read(RT(instr))); + trap(regs.Read(instr.rs()) >= regs.Read(instr.rt())); break; case Instruction::TLT: - trap(regs.Read(RS(instr)) < regs.Read(RT(instr))); + trap(regs.Read(instr.rs()) < regs.Read(instr.rt())); break; case Instruction::TLTU: - trap(regs.Read(RS(instr)) < regs.Read(RT(instr))); + trap(regs.Read(instr.rs()) < regs.Read(instr.rt())); break; case Instruction::TEQ: - trap(regs.Read(RS(instr)) == regs.Read(RT(instr))); + trap(regs.Read(instr.rs()) == regs.Read(instr.rt())); break; case Instruction::TNE: - trap(regs.Read(RS(instr)) != regs.Read(RT(instr))); + trap(regs.Read(instr.rs()) != regs.Read(instr.rt())); break; case Instruction::DSLL: dsll(instr); @@ -166,59 +165,59 @@ void Interpreter::special(const u32 instr) { dsra32(instr); break; default: - panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})", (mask >> 3) & 7, mask & 7, instr, + panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})", instr.instr.opcode.special_hi, instr.instr.opcode.special_lo, instr.instr.raw, static_cast(regs.oldPC)); } } -void Interpreter::regimm(const u32 instr) { +void Interpreter::regimm(const Instruction instr) { // 000r_rccc - switch (const u8 mask = instr >> 16 & 0x1F) { - case BLTZ: - b(instr, regs.Read(RS(instr)) < 0); + switch (instr.instr.opcode.regimm) { + case Instruction::BLTZ: + b(instr, regs.Read(instr.rs()) < 0); break; - case BGEZ: - b(instr, regs.Read(RS(instr)) >= 0); + case Instruction::BGEZ: + b(instr, regs.Read(instr.rs()) >= 0); break; - case BLTZL: - bl(instr, regs.Read(RS(instr)) < 0); + case Instruction::BLTZL: + bl(instr, regs.Read(instr.rs()) < 0); break; - case BGEZL: - bl(instr, regs.Read(RS(instr)) >= 0); + case Instruction::BGEZL: + bl(instr, regs.Read(instr.rs()) >= 0); break; - case TGEI: - trap(regs.Read(RS(instr)) >= static_cast(static_cast(instr))); + case Instruction::TGEI: + trap(regs.Read(instr.rs()) >= static_cast(static_cast(instr.instr.itype.imm))); break; - case TGEIU: - trap(regs.Read(RS(instr)) >= static_cast(static_cast(static_cast(instr)))); + case Instruction::TGEIU: + trap(regs.Read(instr.rs()) >= static_cast(static_cast(static_cast(instr.instr.itype.imm)))); break; - case TLTI: - trap(regs.Read(RS(instr)) < static_cast(static_cast(instr))); + case Instruction::TLTI: + trap(regs.Read(instr.rs()) < static_cast(static_cast(instr.instr.itype.imm))); break; - case TLTIU: - trap(regs.Read(RS(instr)) < static_cast(static_cast(static_cast(instr)))); + case Instruction::TLTIU: + trap(regs.Read(instr.rs()) < static_cast(static_cast(static_cast(instr.instr.itype.imm)))); break; - case TEQI: - trap(regs.Read(RS(instr)) == static_cast(static_cast(instr))); + case Instruction::TEQI: + trap(regs.Read(instr.rs()) == static_cast(static_cast(instr.instr.itype.imm))); break; - case TNEI: - trap(regs.Read(RS(instr)) != static_cast(static_cast(instr))); + case Instruction::TNEI: + trap(regs.Read(instr.rs()) != static_cast(static_cast(instr.instr.itype.imm))); break; - case BLTZAL: - blink(instr, regs.Read(RS(instr)) < 0); + case Instruction::BLTZAL: + blink(instr, regs.Read(instr.rs()) < 0); break; - case BGEZAL: - blink(instr, regs.Read(RS(instr)) >= 0); + case Instruction::BGEZAL: + blink(instr, regs.Read(instr.rs()) >= 0); break; - case BLTZALL: - bllink(instr, regs.Read(RS(instr)) < 0); + case Instruction::BLTZALL: + bllink(instr, regs.Read(instr.rs()) < 0); break; - case BGEZALL: - bllink(instr, regs.Read(RS(instr)) >= 0); + case Instruction::BGEZALL: + bllink(instr, regs.Read(instr.rs()) >= 0); break; default: - panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", (mask >> 3) & 3, mask & 7, instr, - static_cast(regs.oldPC)); + panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", instr.instr.opcode.regimm_hi, + instr.instr.opcode.regimm_lo, instr, static_cast(regs.oldPC)); } } @@ -251,203 +250,172 @@ void Interpreter::cop2Decode(const u32 instr) { } } -void Interpreter::Exec(const u32 instr) { +void Interpreter::Exec(const Instruction instr) { // 00rr_rccc - switch (const u8 mask = instr >> 26 & 0x3f) { - case SPECIAL: + switch (instr.instr.opcode.op) { + case Instruction::SPECIAL: special(instr); break; - case REGIMM: + case Instruction::REGIMM: regimm(instr); break; - case J: + case Instruction::J: j(instr); break; - case JAL: + case Instruction::JAL: jal(instr); break; - case BEQ: - b(instr, regs.Read(RS(instr)) == regs.Read(RT(instr))); + case Instruction::BEQ: + b(instr, regs.Read(instr.rs()) == regs.Read(instr.rt())); break; - case BNE: - b(instr, regs.Read(RS(instr)) != regs.Read(RT(instr))); + case Instruction::BNE: + b(instr, regs.Read(instr.rs()) != regs.Read(instr.rt())); break; - case BLEZ: - b(instr, regs.Read(RS(instr)) <= 0); + case Instruction::BLEZ: + b(instr, regs.Read(instr.rs()) <= 0); break; - case BGTZ: - b(instr, regs.Read(RS(instr)) > 0); + case Instruction::BGTZ: + b(instr, regs.Read(instr.rs()) > 0); break; - case ADDI: + case Instruction::ADDI: addi(instr); break; - case ADDIU: + case Instruction::ADDIU: addiu(instr); break; - case SLTI: + case Instruction::SLTI: slti(instr); break; - case SLTIU: + case Instruction::SLTIU: sltiu(instr); break; - case ANDI: + case Instruction::ANDI: andi(instr); break; - case ORI: + case Instruction::ORI: ori(instr); break; - case XORI: + case Instruction::XORI: xori(instr); break; - case LUI: + case Instruction::LUI: lui(instr); break; - case COP0: + case Instruction::COP0: regs.cop0.decode(instr); break; - case COP1: - { - const u8 mask_sub = (instr >> 21) & 0x1F; - const u8 mask_branch = (instr >> 16) & 0x1F; - if (mask_sub == 0x08) { - switch (mask_branch) { - case 0: - if (!regs.cop1.CheckFPUUsable()) - return; - b(instr, !regs.cop1.fcr31.compare); - break; - case 1: - if (!regs.cop1.CheckFPUUsable()) - return; - b(instr, regs.cop1.fcr31.compare); - break; - case 2: - if (!regs.cop1.CheckFPUUsable()) - return; - bl(instr, !regs.cop1.fcr31.compare); - break; - case 3: - if (!regs.cop1.CheckFPUUsable()) - return; - bl(instr, regs.cop1.fcr31.compare); - break; - default: - panic("Undefined BC COP1 {:02X}", mask_branch); - } - break; - } - regs.cop1.decode(instr); - } + case Instruction::COP1: + regs.cop1.decode(instr); break; - case COP2: + case Instruction::COP2: cop2Decode(instr); break; - case BEQL: - bl(instr, regs.Read(RS(instr)) == regs.Read(RT(instr))); + case Instruction::BEQL: + bl(instr, regs.Read(instr.rs()) == regs.Read(instr.rt())); break; - case BNEL: - bl(instr, regs.Read(RS(instr)) != regs.Read(RT(instr))); + case Instruction::BNEL: + bl(instr, regs.Read(instr.rs()) != regs.Read(instr.rt())); break; - case BLEZL: - bl(instr, regs.Read(RS(instr)) <= 0); + case Instruction::BLEZL: + bl(instr, regs.Read(instr.rs()) <= 0); break; - case BGTZL: - bl(instr, regs.Read(RS(instr)) > 0); + case Instruction::BGTZL: + bl(instr, regs.Read(instr.rs()) > 0); break; - case DADDI: + case Instruction::DADDI: daddi(instr); break; - case DADDIU: + case Instruction::DADDIU: daddiu(instr); break; - case LDL: + case Instruction::LDL: ldl(instr); break; - case LDR: + case Instruction::LDR: ldr(instr); break; case 0x1F: regs.cop0.FireException(ExceptionCode::ReservedInstruction, 0, regs.oldPC); break; - case LB: + case Instruction::LB: lb(instr); break; - case LH: + case Instruction::LH: lh(instr); break; - case LWL: + case Instruction::LWL: lwl(instr); break; - case LW: + case Instruction::LW: lw(instr); break; - case LBU: + case Instruction::LBU: lbu(instr); break; - case LHU: + case Instruction::LHU: lhu(instr); break; - case LWR: + case Instruction::LWR: lwr(instr); break; - case LWU: + case Instruction::LWU: lwu(instr); break; - case SB: + case Instruction::SB: sb(instr); break; - case SH: + case Instruction::SH: sh(instr); break; - case SWL: + case Instruction::SWL: swl(instr); break; - case SW: + case Instruction::SW: sw(instr); break; - case SDL: + case Instruction::SDL: sdl(instr); break; - case SDR: + case Instruction::SDR: sdr(instr); break; - case SWR: + case Instruction::SWR: swr(instr); break; - case CACHE: + case Instruction::CACHE: break; // CACHE - case LL: + case Instruction::LL: ll(instr); break; - case LWC1: + case Instruction::LWC1: regs.cop1.lwc1(instr); break; - case LLD: + case Instruction::LLD: lld(instr); break; - case LDC1: + case Instruction::LDC1: regs.cop1.ldc1(instr); break; - case LD: + case Instruction::LD: ld(instr); break; - case SC: + case Instruction::SC: sc(instr); break; - case SWC1: + case Instruction::SWC1: regs.cop1.swc1(instr); break; - case SCD: + case Instruction::SCD: scd(instr); break; - case SDC1: + case Instruction::SDC1: regs.cop1.sdc1(instr); break; - case SD: + case Instruction::SD: sd(instr); break; default: - panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", mask, instr, static_cast(regs.oldPC)); + panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", instr.instr.opcode.op, u32(instr), static_cast(regs.oldPC)); } } } // namespace n64 diff --git a/src/backend/core/registers/Cop0.cpp b/src/backend/core/registers/Cop0.cpp index 700491f3..330c7537 100644 --- a/src/backend/core/registers/Cop0.cpp +++ b/src/backend/core/registers/Cop0.cpp @@ -451,25 +451,23 @@ ExceptionCode Cop0::GetTLBExceptionCode(const TLBError error, const TLBAccessTyp } } -void Cop0::decode(const u32 instr) { +void Cop0::decode(const Instruction instr) { Registers& regs = Core::GetRegs(); - const u8 mask_cop = instr >> 21 & 0x1F; - const u8 mask_cop2 = instr & 0x3F; - switch (mask_cop) { + switch (instr.cop_rs()) { case 0x00: - mfc0(instr); + mfc0(u32(instr)); break; case 0x01: - dmfc0(instr); + dmfc0(u32(instr)); break; case 0x04: - mtc0(instr); + mtc0(u32(instr)); break; case 0x05: - dmtc0(instr); + dmtc0(u32(instr)); break; case 0x10 ... 0x1F: - switch (mask_cop2) { + switch (instr.cop_funct()) { case 0x01: tlbr(); break; @@ -486,7 +484,7 @@ void Cop0::decode(const u32 instr) { eret(); break; default: - panic("Unimplemented COP0 function {} {} ({:08X}) ({:016X})", mask_cop2 >> 3, mask_cop2 & 7, instr, + panic("Unimplemented COP0 function {} ({:08X}) ({:016X})", instr.cop_funct(), u32(instr), regs.oldPC); } break; diff --git a/src/backend/core/registers/Cop0.hpp b/src/backend/core/registers/Cop0.hpp index bf1b5bc1..0bbd5c42 100644 --- a/src/backend/core/registers/Cop0.hpp +++ b/src/backend/core/registers/Cop0.hpp @@ -2,6 +2,7 @@ #include #include #include +#include namespace n64 { #define STATUS_MASK 0xFF57FFFF @@ -264,7 +265,7 @@ struct Cop0 { TLBEntry *TLBTryMatch(u64 vaddr); void HandleTLBException(u64 vaddr); static ExceptionCode GetTLBExceptionCode(TLBError error, TLBAccessType accessType); - void decode(u32); + void decode(const Instruction); private: [[nodiscard]] FORCE_INLINE u32 GetWired() const { return wired & 0x3F; } diff --git a/src/backend/core/registers/Cop1.cpp b/src/backend/core/registers/Cop1.cpp index 8f9a3144..b2d12a96 100644 --- a/src/backend/core/registers/Cop1.cpp +++ b/src/backend/core/registers/Cop1.cpp @@ -10,11 +10,9 @@ void Cop1::Reset() { memset(fgr, 0, 32 * sizeof(FloatingPointReg)); } -void Cop1::decode(const u32 instr) { - const u8 mask_sub = (instr >> 21) & 0x1F; - const u8 mask_fun = instr & 0x3F; - const u8 mask_branch = (instr >> 16) & 0x1F; - switch (mask_sub) { +void Cop1::decode(const Instruction instr) { + auto cpu = Core::GetInstance().cpuType == Core::Interpreted ? Core::GetInterpreter() : Core::GetDynamicRecompiler(); + switch (instr.cop_rs()) { // 000r_rccc case 0x00: mfc1(instr); @@ -40,8 +38,34 @@ void Cop1::decode(const u32 instr) { case 0x07: unimplemented(); break; + case 0x08: + switch (instr.cop_rt()) { + case 0: + if (!regs.cop1.CheckFPUUsable()) + return; + cpu.b(instr, !regs.cop1.fcr31.compare); + break; + case 1: + if (!regs.cop1.CheckFPUUsable()) + return; + cpu.b(instr, regs.cop1.fcr31.compare); + break; + case 2: + if (!regs.cop1.CheckFPUUsable()) + return; + cpu.bl(instr, !regs.cop1.fcr31.compare); + break; + case 3: + if (!regs.cop1.CheckFPUUsable()) + return; + cpu.bl(instr, regs.cop1.fcr31.compare); + break; + default: + panic("Undefined BC COP1 {:02X}", instr.cop_rt()); + } + break; case 0x10: // s - switch (mask_fun) { + switch (instr.cop_funct()) { case 0x00: adds(instr); break; @@ -152,7 +176,7 @@ void Cop1::decode(const u32 instr) { } break; case 0x11: // d - switch (mask_fun) { + switch (instr.cop_funct()) { case 0x00: addd(instr); break; @@ -263,7 +287,7 @@ void Cop1::decode(const u32 instr) { } break; case 0x14: // w - switch (mask_fun) { + switch (instr.cop_funct()) { case 0x20: cvtsw(instr); break; @@ -275,7 +299,7 @@ void Cop1::decode(const u32 instr) { } break; case 0x15: // l - switch (mask_fun) { + switch (instr.cop_funct()) { case 0x20: cvtsl(instr); break; @@ -287,7 +311,7 @@ void Cop1::decode(const u32 instr) { } break; default: - panic("Unimplemented COP1 instruction {} {}", mask_sub >> 3, mask_sub & 7); + panic("Unimplemented COP1 instruction {}", instr.cop_rs()); } } } // namespace n64 diff --git a/src/backend/core/registers/Cop1.hpp b/src/backend/core/registers/Cop1.hpp index 7cce78c5..e6da8259 100644 --- a/src/backend/core/registers/Cop1.hpp +++ b/src/backend/core/registers/Cop1.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#include namespace n64 { struct Cop1; @@ -117,7 +118,7 @@ struct Cop1 { bool fgrIsConstant[32]{}; void Reset(); - void decode(u32); + void decode(const Instruction); friend struct Interpreter; friend struct JIT; @@ -156,91 +157,91 @@ private: auto FGR_S(const Cop0Status &, u32) -> T &; template auto FGR_D(const Cop0Status &, u32) -> T &; - void absd(u32 instr); - void abss(u32 instr); - void adds(u32 instr); - void addd(u32 instr); - void subs(u32 instr); - void subd(u32 instr); - void ceills(u32 instr); - void ceilws(u32 instr); - void ceilld(u32 instr); - void ceilwd(u32 instr); - void cfc1(u32 instr); - void ctc1(u32 instr); + void absd(const Instruction instr); + void abss(const Instruction instr); + void adds(const Instruction instr); + void addd(const Instruction instr); + void subs(const Instruction instr); + void subd(const Instruction instr); + void ceills(const Instruction instr); + void ceilws(const Instruction instr); + void ceilld(const Instruction instr); + void ceilwd(const Instruction instr); + void cfc1(const Instruction instr); + void ctc1(const Instruction instr); void unimplemented(); - void roundls(u32 instr); - void roundld(u32 instr); - void roundws(u32 instr); - void roundwd(u32 instr); - void floorls(u32 instr); - void floorld(u32 instr); - void floorws(u32 instr); - void floorwd(u32 instr); - void cvtls(u32 instr); - void cvtws(u32 instr); - void cvtds(u32 instr); - void cvtsw(u32 instr); - void cvtdw(u32 instr); - void cvtsd(u32 instr); - void cvtwd(u32 instr); - void cvtld(u32 instr); - void cvtdl(u32 instr); - void cvtsl(u32 instr); + void roundls(const Instruction instr); + void roundld(const Instruction instr); + void roundws(const Instruction instr); + void roundwd(const Instruction instr); + void floorls(const Instruction instr); + void floorld(const Instruction instr); + void floorws(const Instruction instr); + void floorwd(const Instruction instr); + void cvtls(const Instruction instr); + void cvtws(const Instruction instr); + void cvtds(const Instruction instr); + void cvtsw(const Instruction instr); + void cvtdw(const Instruction instr); + void cvtsd(const Instruction instr); + void cvtwd(const Instruction instr); + void cvtld(const Instruction instr); + void cvtdl(const Instruction instr); + void cvtsl(const Instruction instr); template - void cf(u32 instr); + void cf(const Instruction instr); template - void cun(u32 instr); + void cun(const Instruction instr); template - void ceq(u32 instr); + void ceq(const Instruction instr); template - void cueq(u32 instr); + void cueq(const Instruction instr); template - void colt(u32 instr); + void colt(const Instruction instr); template - void cult(u32 instr); + void cult(const Instruction instr); template - void cole(u32 instr); + void cole(const Instruction instr); template - void cule(u32 instr); + void cule(const Instruction instr); template - void csf(u32 instr); + void csf(const Instruction instr); template - void cngle(u32 instr); + void cngle(const Instruction instr); template - void cseq(u32 instr); + void cseq(const Instruction instr); template - void cngl(u32 instr); + void cngl(const Instruction instr); template - void clt(u32 instr); + void clt(const Instruction instr); template - void cnge(u32 instr); + void cnge(const Instruction instr); template - void cle(u32 instr); + void cle(const Instruction instr); template - void cngt(u32 instr); - void divs(u32 instr); - void divd(u32 instr); - void muls(u32 instr); - void muld(u32 instr); - void movs(u32 instr); - void movd(u32 instr); - void negs(u32 instr); - void negd(u32 instr); - void sqrts(u32 instr); - void sqrtd(u32 instr); + void cngt(const Instruction instr); + void divs(const Instruction instr); + void divd(const Instruction instr); + void muls(const Instruction instr); + void muld(const Instruction instr); + void movs(const Instruction instr); + void movd(const Instruction instr); + void negs(const Instruction instr); + void negd(const Instruction instr); + void sqrts(const Instruction instr); + void sqrtd(const Instruction instr); void lwc1(u32); void swc1(u32); void ldc1(u32); void sdc1(u32); - void mfc1(u32 instr); - void dmfc1(u32 instr); - void mtc1(u32 instr); - void dmtc1(u32 instr); - void truncws(u32 instr); - void truncwd(u32 instr); - void truncls(u32 instr); - void truncld(u32 instr); + void mfc1(const Instruction instr); + void dmfc1(const Instruction instr); + void mtc1(const Instruction instr); + void dmtc1(const Instruction instr); + void truncws(const Instruction instr); + void truncwd(const Instruction instr); + void truncls(const Instruction instr); + void truncld(const Instruction instr); }; } // namespace n64 diff --git a/src/utils/Instruction.hpp b/src/utils/Instruction.hpp index fc95cd02..df8a355d 100644 --- a/src/utils/Instruction.hpp +++ b/src/utils/Instruction.hpp @@ -4,17 +4,82 @@ namespace n64 { struct Instruction { - Instruction(u32 v) : raw(v) {} - void operator=(u32 v) { raw = v; } + Instruction(u32 v) { instr.raw = v; } + void operator=(u32 v) { instr.raw = v; } + auto operator u32() { return instr.raw; } + + inline u8 rs() const { return instr.rtype.rs; } + inline u8 rt() const { return instr.rtype.rt; } + inline u8 rd() const { return instr.rtype.rd; } + inline u8 sa() const { return instr.rtype.sa; } + inline u16 imm() const { return instr.itype.imm; } + inline u32 target() const { return instr.jtype.target; } + inline u8 cop_rs() const { return instr.opcode.cop_rs; } + inline u8 cop_rt() const { return instr.opcode.cop_rt; } + inline u8 cop_funct() const { return instr.opcode.funct; } - u32 raw; + union { + struct { + unsigned imm:16; + unsigned rt:5; + unsigned rs:5; + unsigned op:6; + } itype; - FORCE_INLINE u8 special() const { return raw & 0x3F; } - FORCE_INLINE u8 cop_funct() const { return special(); } - FORCE_INLINE u8 regimm() const { return (raw >> 16) & 0x1F; } - FORCE_INLINE u8 branch() const { return regimm(); } - FORCE_INLINE u8 decode() const { return (raw >> 26) & 0x3F; } - FORCE_INLINE u8 cop() const { return (raw >> 21) & 0x1F; } + struct { + unsigned target:26; + unsigned op:6; + } jtype; + + struct { + unsigned funct:6; + unsigned sa:5; + unsigned rd:5; + unsigned rt:5; + unsigned rs:5; + unsigned op:6; + } rtype; + + union { + struct { + unsigned special_lo:3; + unsigned special_hi:3; + unsigned:26; + }; + + struct { + unsigned special:6; + unsigned:26; + }; + struct { + unsigned:16; + unsigned regimm_lo:3; + unsigned regimm_hi:2; + unsigned:11; + }; + + struct { + unsigned:16; + unsigned regimm:5; + unsigned:11; + }; + + struct { + unsigned:26; + unsigned op:6; + }; + + struct { + unsigned funct:6; + unsigned:10; + unsigned cop_rt:5; + unsigned cop_rs:5; + unsigned:6; + }; + } opcode; + + u32 raw; + } instr{}; static constexpr u8 SPECIAL = 0b000000; static constexpr u8 REGIMM = 0b000001;