From 68620ce893a018c5c7d8f734f4e8eca08a367895 Mon Sep 17 00:00:00 2001 From: SimoZ64 Date: Sat, 16 Aug 2025 22:00:01 +0200 Subject: [PATCH] start implementing instruction union for cleaner switches and stuff --- src/backend/core/CpuDefinitions.hpp | 126 +------------------- src/backend/core/interpreter/decode.cpp | 108 +++++++++--------- src/utils/Instruction.hpp | 145 ++++++++++++++++++++++++ 3 files changed, 201 insertions(+), 178 deletions(-) create mode 100644 src/utils/Instruction.hpp diff --git a/src/backend/core/CpuDefinitions.hpp b/src/backend/core/CpuDefinitions.hpp index 9d89e82c..59777073 100644 --- a/src/backend/core/CpuDefinitions.hpp +++ b/src/backend/core/CpuDefinitions.hpp @@ -2,129 +2,5 @@ #include namespace n64 { -constexpr u8 SPECIAL = 0b000000; -constexpr u8 REGIMM = 0b000001; -constexpr u8 J = 0b000010; -constexpr u8 JAL = 0b000011; -constexpr u8 BEQ = 0b000100; -constexpr u8 BNE = 0b000101; -constexpr u8 BLEZ = 0b000110; -constexpr u8 BGTZ = 0b000111; -constexpr u8 ADDI = 0b001000; -constexpr u8 ADDIU = 0b001001; -constexpr u8 SLTI = 0b001010; -constexpr u8 SLTIU = 0b001011; -constexpr u8 ANDI = 0b001100; -constexpr u8 ORI = 0b001101; -constexpr u8 XORI = 0b001110; -constexpr u8 LUI = 0b001111; -constexpr u8 COP0 = 0b010000; -constexpr u8 COP1 = 0b010001; -constexpr u8 COP2 = 0b010010; -constexpr u8 BEQL = 0b010100; -constexpr u8 BNEL = 0b010101; -constexpr u8 BLEZL = 0b010110; -constexpr u8 BGTZL = 0b010111; -constexpr u8 DADDI = 0b011000; -constexpr u8 DADDIU = 0b011001; -constexpr u8 LDL = 0b011010; -constexpr u8 LDR = 0b011011; -constexpr u8 LB = 0b100000; -constexpr u8 LH = 0b100001; -constexpr u8 LWL = 0b100010; -constexpr u8 LW = 0b100011; -constexpr u8 LBU = 0b100100; -constexpr u8 LHU = 0b100101; -constexpr u8 LWR = 0b100110; -constexpr u8 LWU = 0b100111; -constexpr u8 SB = 0b101000; -constexpr u8 SH = 0b101001; -constexpr u8 SWL = 0b101010; -constexpr u8 SW = 0b101011; -constexpr u8 SDL = 0b101100; -constexpr u8 SDR = 0b101101; -constexpr u8 SWR = 0b101110; -constexpr u8 CACHE = 0b101111; -constexpr u8 LL = 0b110000; -constexpr u8 LWC1 = 0b110001; -constexpr u8 LWC2 = 0b110010; -constexpr u8 LLD = 0b110100; -constexpr u8 LDC1 = 0b110101; -constexpr u8 LDC2 = 0b110110; -constexpr u8 LD = 0b110111; -constexpr u8 SC = 0b111000; -constexpr u8 SWC1 = 0b111001; -constexpr u8 SWC2 = 0b111010; -constexpr u8 SCD = 0b111100; -constexpr u8 SDC1 = 0b111101; -constexpr u8 SDC2 = 0b111110; -constexpr u8 SD = 0b111111; -// special -constexpr u8 SLL = 0b000000; -constexpr u8 SRL = 0b000010; -constexpr u8 SRA = 0b000011; -constexpr u8 SLLV = 0b000100; -constexpr u8 SRLV = 0b000110; -constexpr u8 SRAV = 0b000111; -constexpr u8 JR = 0b001000; -constexpr u8 JALR = 0b001001; -constexpr u8 SYSCALL = 0b001100; -constexpr u8 BREAK = 0b001101; -constexpr u8 SYNC = 0b001111; -constexpr u8 MFHI = 0b010000; -constexpr u8 MTHI = 0b010001; -constexpr u8 MFLO = 0b010010; -constexpr u8 MTLO = 0b010011; -constexpr u8 DSLLV = 0b010100; -constexpr u8 DSRLV = 0b010110; -constexpr u8 DSRAV = 0b010111; -constexpr u8 MULT = 0b011000; -constexpr u8 MULTU = 0b011001; -constexpr u8 DIV = 0b011010; -constexpr u8 DIVU = 0b011011; -constexpr u8 DMULT = 0b011100; -constexpr u8 DMULTU = 0b011101; -constexpr u8 DDIV = 0b011110; -constexpr u8 DDIVU = 0b011111; -constexpr u8 ADD = 0b100000; -constexpr u8 ADDU = 0b100001; -constexpr u8 SUB = 0b100010; -constexpr u8 SUBU = 0b100011; -constexpr u8 AND = 0b100100; -constexpr u8 OR = 0b100101; -constexpr u8 XOR = 0b100110; -constexpr u8 NOR = 0b100111; -constexpr u8 SLT = 0b101010; -constexpr u8 SLTU = 0b101011; -constexpr u8 DADD = 0b101100; -constexpr u8 DADDU = 0b101101; -constexpr u8 DSUB = 0b101110; -constexpr u8 DSUBU = 0b101111; -constexpr u8 TGE = 0b110000; -constexpr u8 TGEU = 0b110001; -constexpr u8 TLT = 0b110010; -constexpr u8 TLTU = 0b110011; -constexpr u8 TEQ = 0b110100; -constexpr u8 TNE = 0b110110; -constexpr u8 DSLL = 0b111000; -constexpr u8 DSRL = 0b111010; -constexpr u8 DSRA = 0b111011; -constexpr u8 DSLL32 = 0b111100; -constexpr u8 DSRL32 = 0b111110; -constexpr u8 DSRA32 = 0b111111; -// regimm -constexpr u8 BLTZ = 0b00000; -constexpr u8 BGEZ = 0b00001; -constexpr u8 BLTZL = 0b00010; -constexpr u8 BGEZL = 0b00011; -constexpr u8 TGEI = 0b01000; -constexpr u8 TGEIU = 0b01001; -constexpr u8 TLTI = 0b01010; -constexpr u8 TLTIU = 0b01011; -constexpr u8 TEQI = 0b01100; -constexpr u8 TNEI = 0b01110; -constexpr u8 BLTZAL = 0b10000; -constexpr u8 BGEZAL = 0b10001; -constexpr u8 BLTZALL = 0b10010; -constexpr u8 BGEZALL = 0b10011; + } // namespace n64 diff --git a/src/backend/core/interpreter/decode.cpp b/src/backend/core/interpreter/decode.cpp index 910341ff..08cd85db 100644 --- a/src/backend/core/interpreter/decode.cpp +++ b/src/backend/core/interpreter/decode.cpp @@ -1,166 +1,168 @@ #include #include #include +#include namespace n64 { void Interpreter::special(const u32 instr) { + Instruction helper(instr); // 00rr_rccc - switch (const u8 mask = instr & 0x3F) { - case SLL: + switch (helper.special()) { + case Instruction::SLL: if (instr != 0) { sll(instr); } break; - case SRL: + case Instruction::SRL: srl(instr); break; - case SRA: + case Instruction::SRA: sra(instr); break; - case SLLV: + case Instruction::SLLV: sllv(instr); break; - case SRLV: + case Instruction::SRLV: srlv(instr); break; - case SRAV: + case Instruction::SRAV: srav(instr); break; - case JR: + case Instruction::JR: jr(instr); break; - case JALR: + case Instruction::JALR: jalr(instr); break; - case SYSCALL: + case Instruction::SYSCALL: regs.cop0.FireException(ExceptionCode::Syscall, 0, regs.oldPC); break; - case BREAK: + case Instruction::BREAK: regs.cop0.FireException(ExceptionCode::Breakpoint, 0, regs.oldPC); break; - case SYNC: + case Instruction::SYNC: break; // SYNC - case MFHI: + case Instruction::MFHI: mfhi(instr); break; - case MTHI: + case Instruction::MTHI: mthi(instr); break; - case MFLO: + case Instruction::MFLO: mflo(instr); break; - case MTLO: + case Instruction::MTLO: mtlo(instr); break; - case DSLLV: + case Instruction::DSLLV: dsllv(instr); break; - case DSRLV: + case Instruction::DSRLV: dsrlv(instr); break; - case DSRAV: + case Instruction::DSRAV: dsrav(instr); break; - case MULT: + case Instruction::MULT: mult(instr); break; - case MULTU: + case Instruction::MULTU: multu(instr); break; - case DIV: + case Instruction::DIV: div(instr); break; - case DIVU: + case Instruction::DIVU: divu(instr); break; - case DMULT: + case Instruction::DMULT: dmult(instr); break; - case DMULTU: + case Instruction::DMULTU: dmultu(instr); break; - case DDIV: + case Instruction::DDIV: ddiv(instr); break; - case DDIVU: + case Instruction::DDIVU: ddivu(instr); break; - case ADD: + case Instruction::ADD: add(instr); break; - case ADDU: + case Instruction::ADDU: addu(instr); break; - case SUB: + case Instruction::SUB: sub(instr); break; - case SUBU: + case Instruction::SUBU: subu(instr); break; - case AND: + case Instruction::AND: and_(instr); break; - case OR: + case Instruction::OR: or_(instr); break; - case XOR: + case Instruction::XOR: xor_(instr); break; - case NOR: + case Instruction::NOR: nor(instr); break; - case SLT: + case Instruction::SLT: slt(instr); break; - case SLTU: + case Instruction::SLTU: sltu(instr); break; - case DADD: + case Instruction::DADD: dadd(instr); break; - case DADDU: + case Instruction::DADDU: daddu(instr); break; - case DSUB: + case Instruction::DSUB: dsub(instr); break; - case DSUBU: + case Instruction::DSUBU: dsubu(instr); break; - case TGE: + case Instruction::TGE: trap(regs.Read(RS(instr)) >= regs.Read(RT(instr))); break; - case TGEU: + case Instruction::TGEU: trap(regs.Read(RS(instr)) >= regs.Read(RT(instr))); break; - case TLT: + case Instruction::TLT: trap(regs.Read(RS(instr)) < regs.Read(RT(instr))); break; - case TLTU: + case Instruction::TLTU: trap(regs.Read(RS(instr)) < regs.Read(RT(instr))); break; - case TEQ: + case Instruction::TEQ: trap(regs.Read(RS(instr)) == regs.Read(RT(instr))); break; - case TNE: + case Instruction::TNE: trap(regs.Read(RS(instr)) != regs.Read(RT(instr))); break; - case DSLL: + case Instruction::DSLL: dsll(instr); break; - case DSRL: + case Instruction::DSRL: dsrl(instr); break; - case DSRA: + case Instruction::DSRA: dsra(instr); break; - case DSLL32: + case Instruction::DSLL32: dsll32(instr); break; - case DSRL32: + case Instruction::DSRL32: dsrl32(instr); break; - case DSRA32: + case Instruction::DSRA32: dsra32(instr); break; default: diff --git a/src/utils/Instruction.hpp b/src/utils/Instruction.hpp new file mode 100644 index 00000000..fc95cd02 --- /dev/null +++ b/src/utils/Instruction.hpp @@ -0,0 +1,145 @@ +#pragma once +#include +#include + +namespace n64 { +struct Instruction { + Instruction(u32 v) : raw(v) {} + void operator=(u32 v) { raw = v; } + + u32 raw; + + 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; } + + static constexpr u8 SPECIAL = 0b000000; + static constexpr u8 REGIMM = 0b000001; + static constexpr u8 J = 0b000010; + static constexpr u8 JAL = 0b000011; + static constexpr u8 BEQ = 0b000100; + static constexpr u8 BNE = 0b000101; + static constexpr u8 BLEZ = 0b000110; + static constexpr u8 BGTZ = 0b000111; + static constexpr u8 ADDI = 0b001000; + static constexpr u8 ADDIU = 0b001001; + static constexpr u8 SLTI = 0b001010; + static constexpr u8 SLTIU = 0b001011; + static constexpr u8 ANDI = 0b001100; + static constexpr u8 ORI = 0b001101; + static constexpr u8 XORI = 0b001110; + static constexpr u8 LUI = 0b001111; + static constexpr u8 COP0 = 0b010000; + static constexpr u8 COP1 = 0b010001; + static constexpr u8 COP2 = 0b010010; + static constexpr u8 BEQL = 0b010100; + static constexpr u8 BNEL = 0b010101; + static constexpr u8 BLEZL = 0b010110; + static constexpr u8 BGTZL = 0b010111; + static constexpr u8 DADDI = 0b011000; + static constexpr u8 DADDIU = 0b011001; + static constexpr u8 LDL = 0b011010; + static constexpr u8 LDR = 0b011011; + static constexpr u8 LB = 0b100000; + static constexpr u8 LH = 0b100001; + static constexpr u8 LWL = 0b100010; + static constexpr u8 LW = 0b100011; + static constexpr u8 LBU = 0b100100; + static constexpr u8 LHU = 0b100101; + static constexpr u8 LWR = 0b100110; + static constexpr u8 LWU = 0b100111; + static constexpr u8 SB = 0b101000; + static constexpr u8 SH = 0b101001; + static constexpr u8 SWL = 0b101010; + static constexpr u8 SW = 0b101011; + static constexpr u8 SDL = 0b101100; + static constexpr u8 SDR = 0b101101; + static constexpr u8 SWR = 0b101110; + static constexpr u8 CACHE = 0b101111; + static constexpr u8 LL = 0b110000; + static constexpr u8 LWC1 = 0b110001; + static constexpr u8 LWC2 = 0b110010; + static constexpr u8 LLD = 0b110100; + static constexpr u8 LDC1 = 0b110101; + static constexpr u8 LDC2 = 0b110110; + static constexpr u8 LD = 0b110111; + static constexpr u8 SC = 0b111000; + static constexpr u8 SWC1 = 0b111001; + static constexpr u8 SWC2 = 0b111010; + static constexpr u8 SCD = 0b111100; + static constexpr u8 SDC1 = 0b111101; + static constexpr u8 SDC2 = 0b111110; + static constexpr u8 SD = 0b111111; + // special + static constexpr u8 SLL = 0b000000; + static constexpr u8 SRL = 0b000010; + static constexpr u8 SRA = 0b000011; + static constexpr u8 SLLV = 0b000100; + static constexpr u8 SRLV = 0b000110; + static constexpr u8 SRAV = 0b000111; + static constexpr u8 JR = 0b001000; + static constexpr u8 JALR = 0b001001; + static constexpr u8 SYSCALL = 0b001100; + static constexpr u8 BREAK = 0b001101; + static constexpr u8 SYNC = 0b001111; + static constexpr u8 MFHI = 0b010000; + static constexpr u8 MTHI = 0b010001; + static constexpr u8 MFLO = 0b010010; + static constexpr u8 MTLO = 0b010011; + static constexpr u8 DSLLV = 0b010100; + static constexpr u8 DSRLV = 0b010110; + static constexpr u8 DSRAV = 0b010111; + static constexpr u8 MULT = 0b011000; + static constexpr u8 MULTU = 0b011001; + static constexpr u8 DIV = 0b011010; + static constexpr u8 DIVU = 0b011011; + static constexpr u8 DMULT = 0b011100; + static constexpr u8 DMULTU = 0b011101; + static constexpr u8 DDIV = 0b011110; + static constexpr u8 DDIVU = 0b011111; + static constexpr u8 ADD = 0b100000; + static constexpr u8 ADDU = 0b100001; + static constexpr u8 SUB = 0b100010; + static constexpr u8 SUBU = 0b100011; + static constexpr u8 AND = 0b100100; + static constexpr u8 OR = 0b100101; + static constexpr u8 XOR = 0b100110; + static constexpr u8 NOR = 0b100111; + static constexpr u8 SLT = 0b101010; + static constexpr u8 SLTU = 0b101011; + static constexpr u8 DADD = 0b101100; + static constexpr u8 DADDU = 0b101101; + static constexpr u8 DSUB = 0b101110; + static constexpr u8 DSUBU = 0b101111; + static constexpr u8 TGE = 0b110000; + static constexpr u8 TGEU = 0b110001; + static constexpr u8 TLT = 0b110010; + static constexpr u8 TLTU = 0b110011; + static constexpr u8 TEQ = 0b110100; + static constexpr u8 TNE = 0b110110; + static constexpr u8 DSLL = 0b111000; + static constexpr u8 DSRL = 0b111010; + static constexpr u8 DSRA = 0b111011; + static constexpr u8 DSLL32 = 0b111100; + static constexpr u8 DSRL32 = 0b111110; + static constexpr u8 DSRA32 = 0b111111; + // regimm + static constexpr u8 BLTZ = 0b00000; + static constexpr u8 BGEZ = 0b00001; + static constexpr u8 BLTZL = 0b00010; + static constexpr u8 BGEZL = 0b00011; + static constexpr u8 TGEI = 0b01000; + static constexpr u8 TGEIU = 0b01001; + static constexpr u8 TLTI = 0b01010; + static constexpr u8 TLTIU = 0b01011; + static constexpr u8 TEQI = 0b01100; + static constexpr u8 TNEI = 0b01110; + static constexpr u8 BLTZAL = 0b10000; + static constexpr u8 BGEZAL = 0b10001; + static constexpr u8 BLTZALL = 0b10010; + static constexpr u8 BGEZALL = 0b10011; +}; +} \ No newline at end of file