From b3a4a302cbf69681773e1faa0e50575fe8d516bf Mon Sep 17 00:00:00 2001 From: SimoneN64 Date: Tue, 27 Aug 2024 21:18:10 +0200 Subject: [PATCH] Finally clangformat --- .clang-format | 52 ++ src/backend/core/BaseCPU.hpp | 10 +- src/backend/core/CpuDefinitions.hpp | 249 +++---- src/backend/core/Interpreter.cpp | 19 +- src/backend/core/Interpreter.hpp | 22 +- src/backend/core/JIT.cpp | 30 +- src/backend/core/JIT.hpp | 22 +- src/backend/core/MMIO.cpp | 83 ++- src/backend/core/Mem.cpp | 650 +++++++++-------- src/backend/core/Mem.hpp | 57 +- src/backend/core/jit/instructions.cpp | 877 +++++++++++------------ src/backend/core/registers/Registers.cpp | 92 ++- src/backend/core/registers/Registers.hpp | 19 +- src/frontend/KaizenQt.cpp | 39 +- 14 files changed, 1141 insertions(+), 1080 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..1802970d --- /dev/null +++ b/.clang-format @@ -0,0 +1,52 @@ +--- +Language: Cpp +BasedOnStyle: LLVM +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignOperands: false +AlignTrailingComments: false +AlwaysBreakTemplateDeclarations: Yes +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: true + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: true + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakConstructorInitializers: AfterColon +BreakConstructorInitializersBeforeComma: false +ColumnLimit: 120 +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ContinuationIndentWidth: 2 +IncludeCategories: + - Regex: '^<.*' + Priority: 1 + - Regex: '^".*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IncludeIsMainRegex: '([-_](test|unittest))?$' +IndentCaseBlocks: true +InsertNewlineAtEOF: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: Inner +SpaceInEmptyParentheses: false +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +TabWidth: 2 +... diff --git a/src/backend/core/BaseCPU.hpp b/src/backend/core/BaseCPU.hpp index 88d6a46c..7ec4239d 100644 --- a/src/backend/core/BaseCPU.hpp +++ b/src/backend/core/BaseCPU.hpp @@ -1,6 +1,6 @@ #pragma once -#include #include +#include namespace n64 { struct BaseCPU { @@ -10,8 +10,8 @@ struct BaseCPU { virtual bool ShouldServiceInterrupt() = 0; virtual void CheckCompareInterrupt() = 0; virtual std::vector Serialize() = 0; - virtual void Deserialize(const std::vector&) = 0; - virtual Mem& GetMem() = 0; - virtual Registers& GetRegs() = 0; + virtual void Deserialize(const std::vector &) = 0; + virtual Mem &GetMem() = 0; + virtual Registers &GetRegs() = 0; }; -} \ No newline at end of file +} // namespace n64 diff --git a/src/backend/core/CpuDefinitions.hpp b/src/backend/core/CpuDefinitions.hpp index 0741168a..9d89e82c 100644 --- a/src/backend/core/CpuDefinitions.hpp +++ b/src/backend/core/CpuDefinitions.hpp @@ -1,129 +1,130 @@ #pragma once #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; +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; +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; -} \ No newline at end of file +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.cpp b/src/backend/core/Interpreter.cpp index 675ee6b4..b89ebd95 100644 --- a/src/backend/core/Interpreter.cpp +++ b/src/backend/core/Interpreter.cpp @@ -1,7 +1,7 @@ #include namespace n64 { -Interpreter::Interpreter(ParallelRDP& parallel) : mem(regs, parallel) { } +Interpreter::Interpreter(ParallelRDP ¶llel) : mem(regs, parallel) {} bool Interpreter::ShouldServiceInterrupt() { bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0; @@ -9,14 +9,13 @@ bool Interpreter::ShouldServiceInterrupt() { bool currently_handling_exception = regs.cop0.status.exl == 1; bool currently_handling_error = regs.cop0.status.erl == 1; - return interrupts_pending && interrupts_enabled && - !currently_handling_exception && !currently_handling_error; + return interrupts_pending && interrupts_enabled && !currently_handling_exception && !currently_handling_error; } void Interpreter::CheckCompareInterrupt() { regs.cop0.count++; regs.cop0.count &= 0x1FFFFFFFF; - if(regs.cop0.count == (u64)regs.cop0.compare << 1) { + if (regs.cop0.count == (u64)regs.cop0.compare << 1) { regs.cop0.cause.ip7 = 1; mem.mmio.mi.UpdateInterrupt(); } @@ -28,14 +27,14 @@ int Interpreter::Step() { regs.prevDelaySlot = regs.delaySlot; regs.delaySlot = false; - if(check_address_error(0b11, u64(regs.pc))) [[unlikely]] { + if (check_address_error(0b11, u64(regs.pc))) [[unlikely]] { regs.cop0.HandleTLBException(regs.pc); regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, regs.pc); return 1; } u32 paddr = 0; - if(!regs.cop0.MapVAddr(Cop0::LOAD, regs.pc, paddr)) { + if (!regs.cop0.MapVAddr(Cop0::LOAD, regs.pc, paddr)) { regs.cop0.HandleTLBException(regs.pc); regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.pc); return 1; @@ -43,7 +42,7 @@ int Interpreter::Step() { u32 instruction = mem.Read(regs, paddr); - if(ShouldServiceInterrupt()) { + if (ShouldServiceInterrupt()) { regs.cop0.FireException(ExceptionCode::Interrupt, 0, regs.pc); return 1; } @@ -67,7 +66,5 @@ std::vector Interpreter::Serialize() { return res; } -void Interpreter::Deserialize(const std::vector &data) { - memcpy(®s, data.data(), sizeof(Registers)); -} -} \ No newline at end of file +void Interpreter::Deserialize(const std::vector &data) { memcpy(®s, data.data(), sizeof(Registers)); } +} // namespace n64 diff --git a/src/backend/core/Interpreter.hpp b/src/backend/core/Interpreter.hpp index daf4218b..c121f23b 100644 --- a/src/backend/core/Interpreter.hpp +++ b/src/backend/core/Interpreter.hpp @@ -1,37 +1,37 @@ #pragma once +#include #include #include -#include namespace n64 { struct Core; + struct Interpreter : BaseCPU { - explicit Interpreter(ParallelRDP&); + explicit Interpreter(ParallelRDP &); ~Interpreter() override = default; int Step() override; + void Reset() override { regs.Reset(); mem.Reset(); cop2Latch = {}; } - Mem& GetMem() override { - return mem; - } + Mem &GetMem() override { return mem; } + + Registers &GetRegs() override { return regs; } - Registers& GetRegs() override { - return regs; - } private: Registers regs; Mem mem; u64 cop2Latch{}; friend struct Cop1; -#define check_address_error(mask, vaddr) (((!regs.cop0.is64BitAddressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0)) +#define check_address_error(mask, vaddr) \ + (((!regs.cop0.is64BitAddressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0)) bool ShouldServiceInterrupt() override; void CheckCompareInterrupt() override; std::vector Serialize() override; - void Deserialize(const std::vector&) override; + void Deserialize(const std::vector &) override; void cop2Decode(u32); void special(u32); @@ -130,4 +130,4 @@ private: void ctc2(u32); void cfc2(u32); }; -} +} // namespace n64 diff --git a/src/backend/core/JIT.cpp b/src/backend/core/JIT.cpp index 1f888df9..ee3b34fd 100644 --- a/src/backend/core/JIT.cpp +++ b/src/backend/core/JIT.cpp @@ -2,10 +2,7 @@ #include namespace n64 { -JIT::JIT(ParallelRDP& parallel) : mem(regs, parallel) { - regs.gpr[0] = 0; - regs.gprIsConstant[0] = true; -} +JIT::JIT(ParallelRDP ¶llel) : mem(regs, parallel) {} bool JIT::ShouldServiceInterrupt() { bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0; @@ -13,14 +10,13 @@ bool JIT::ShouldServiceInterrupt() { bool currently_handling_exception = regs.cop0.status.exl == 1; bool currently_handling_error = regs.cop0.status.erl == 1; - return interrupts_pending && interrupts_enabled && - !currently_handling_exception && !currently_handling_error; + return interrupts_pending && interrupts_enabled && !currently_handling_exception && !currently_handling_error; } void JIT::CheckCompareInterrupt() { regs.cop0.count++; regs.cop0.count &= 0x1FFFFFFFF; - if(regs.cop0.count == (u64)regs.cop0.compare << 1) { + if (regs.cop0.count == (u64)regs.cop0.compare << 1) { regs.cop0.cause.ip7 = 1; mem.mmio.mi.UpdateInterrupt(); } @@ -31,10 +27,10 @@ int JIT::Step() { s64 pc = regs.pc; do { - //CheckCompareInterrupt(); + // CheckCompareInterrupt(); - //regs.prevDelaySlot = regs.delaySlot; - //regs.delaySlot = false; + // regs.prevDelaySlot = regs.delaySlot; + // regs.delaySlot = false; /*if (check_address_error(0b11, u64(pc))) [[unlikely]] { regs.cop0.HandleTLBException(pc); @@ -47,7 +43,8 @@ int JIT::Step() { /*regs.cop0.HandleTLBException(pc); regs.cop0.FireException(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, pc); return 1;*/ - Util::panic("[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address!", static_cast(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD))); + Util::panic("[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address!", + static_cast(regs.cop0.GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD))); } instruction = mem.Read(regs, paddr); @@ -59,8 +56,9 @@ int JIT::Step() { pc += 4; - //Exec(instruction); - } while (!InstrEndsBlock(instruction)); + // Exec(instruction); + } + while (!InstrEndsBlock(instruction)); return 1; } @@ -75,7 +73,5 @@ std::vector JIT::Serialize() { return res; } -void JIT::Deserialize(const std::vector &data) { - memcpy(®s, data.data(), sizeof(Registers)); -} -} \ No newline at end of file +void JIT::Deserialize(const std::vector &data) { memcpy(®s, data.data(), sizeof(Registers)); } +} // namespace n64 diff --git a/src/backend/core/JIT.hpp b/src/backend/core/JIT.hpp index 2cabc48a..2d2e60bf 100644 --- a/src/backend/core/JIT.hpp +++ b/src/backend/core/JIT.hpp @@ -1,36 +1,36 @@ #pragma once +#include #include #include -#include namespace n64 { struct Core; + struct JIT : BaseCPU { - explicit JIT(ParallelRDP&); + explicit JIT(ParallelRDP &); ~JIT() override = default; int Step() override; + void Reset() override { regs.Reset(); mem.Reset(); } - Mem& GetMem() override { - return mem; - } + Mem &GetMem() override { return mem; } + + Registers &GetRegs() override { return regs; } - Registers& GetRegs() override { - return regs; - } private: Registers regs; Mem mem; u64 cop2Latch{}; friend struct Cop1; -#define check_address_error(mask, vaddr) (((!regs.cop0.is64BitAddressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0)) +#define check_address_error(mask, vaddr) \ + (((!regs.cop0.is64BitAddressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0)) bool ShouldServiceInterrupt() override; void CheckCompareInterrupt() override; std::vector Serialize() override; - void Deserialize(const std::vector&) override; + void Deserialize(const std::vector &) override; void Emit(u32); void cop2Decode(u32); @@ -129,4 +129,4 @@ private: void ctc2(u32); void cfc2(u32); }; -} +} // namespace n64 diff --git a/src/backend/core/MMIO.cpp b/src/backend/core/MMIO.cpp index 31fa7a28..7356c061 100644 --- a/src/backend/core/MMIO.cpp +++ b/src/backend/core/MMIO.cpp @@ -15,31 +15,55 @@ void MMIO::Reset() { u32 MMIO::Read(u32 addr) { switch (addr) { - case RSP_REGION: return rsp.Read(addr); - case RDP_REGION: return rdp.Read(addr); - case MI_REGION: return mi.Read(addr); - case VI_REGION: return vi.Read(addr); - case AI_REGION: return ai.Read(addr); - case PI_REGION: return pi.Read(addr); - case RI_REGION: return ri.Read(addr); - case SI_REGION: return si.Read(addr); - default: - Util::panic("Unhandled mmio read at addr {:08X}", addr); + case RSP_REGION: + return rsp.Read(addr); + case RDP_REGION: + return rdp.Read(addr); + case MI_REGION: + return mi.Read(addr); + case VI_REGION: + return vi.Read(addr); + case AI_REGION: + return ai.Read(addr); + case PI_REGION: + return pi.Read(addr); + case RI_REGION: + return ri.Read(addr); + case SI_REGION: + return si.Read(addr); + default: + Util::panic("Unhandled mmio read at addr {:08X}", addr); } } void MMIO::Write(u32 addr, u32 val) { switch (addr) { - case RSP_REGION: rsp.Write(addr, val); break; - case RDP_REGION: rdp.Write(addr, val); break; - case MI_REGION: mi.Write(addr, val); break; - case VI_REGION: vi.Write(addr, val); break; - case AI_REGION: ai.Write(addr, val); break; - case PI_REGION: pi.Write(addr, val); break; - case RI_REGION: ri.Write(addr, val); break; - case SI_REGION: si.Write(addr, val); break; - default: - Util::panic("Unhandled mmio write at addr {:08X} with val {:08X}", addr, val); + case RSP_REGION: + rsp.Write(addr, val); + break; + case RDP_REGION: + rdp.Write(addr, val); + break; + case MI_REGION: + mi.Write(addr, val); + break; + case VI_REGION: + vi.Write(addr, val); + break; + case AI_REGION: + ai.Write(addr, val); + break; + case PI_REGION: + pi.Write(addr, val); + break; + case RI_REGION: + ri.Write(addr, val); + break; + case SI_REGION: + si.Write(addr, val); + break; + default: + Util::panic("Unhandled mmio write at addr {:08X} with val {:08X}", addr, val); } } @@ -47,20 +71,9 @@ std::vector MMIO::Serialize() { std::vector res{}; auto sPIF = si.pif.Serialize(); - constexpr u32 rdpSize = sizeof(DPC) + - 0xFFFFF + - RDRAM_SIZE; - res.resize( - rdpSize + - sizeof(RSP) + - sizeof(MI) + - sizeof(VI) + - sizeof(SI) + - sizeof(PI) + - sizeof(RI) + - sizeof(AI) + - sizeof(u32)*2 + - sizeof(SIStatus)); + constexpr u32 rdpSize = sizeof(DPC) + 0xFFFFF + RDRAM_SIZE; + res.resize(rdpSize + sizeof(RSP) + sizeof(MI) + sizeof(VI) + sizeof(SI) + sizeof(PI) + sizeof(RI) + sizeof(AI) + + sizeof(u32) * 2 + sizeof(SIStatus)); u32 index = 0; memcpy(res.data(), &rsp, sizeof(RSP)); @@ -118,4 +131,4 @@ void MMIO::Deserialize(const std::vector &data) { index += sizeof(u32); memcpy(&si.status, data.data() + index, sizeof(SIStatus)); } -} +} // namespace n64 diff --git a/src/backend/core/Mem.cpp b/src/backend/core/Mem.cpp index 2c0c21c1..8d983115 100644 --- a/src/backend/core/Mem.cpp +++ b/src/backend/core/Mem.cpp @@ -1,14 +1,14 @@ -#include -#include -#include -#include -#include #include -#include +#include +#include #include +#include +#include +#include +#include namespace n64 { -Mem::Mem(Registers& regs, ParallelRDP& parallel) : flash(saveData), mmio(*this, regs, parallel) { +Mem::Mem(Registers ®s, ParallelRDP ¶llel) : flash(saveData), mmio(*this, regs, parallel) { rom.cart.resize(CART_SIZE); std::fill(rom.cart.begin(), rom.cart.end(), 0); } @@ -19,27 +19,31 @@ void Mem::Reset() { if (saveData.is_mapped()) { std::error_code error; saveData.sync(error); - if (error) { Util::panic("Could not sync save data"); } + if (error) { + Util::panic("Could not sync save data"); + } saveData.unmap(); } mmio.Reset(); } void Mem::LoadSRAM(SaveType save_type, fs::path path) { - if(save_type == SAVE_SRAM_256k) { + if (save_type == SAVE_SRAM_256k) { std::error_code error; if (!savePath.empty()) { path = savePath / path.filename(); } sramPath = path.replace_extension(".sram").string(); - if(saveData.is_mapped()) { + if (saveData.is_mapped()) { saveData.sync(error); - if(error) { Util::panic("Could not sync {}", sramPath); } + if (error) { + Util::panic("Could not sync {}", sramPath); + } saveData.unmap(); } auto sramVec = Util::ReadFileBinary(sramPath); - if(sramVec.empty()) { + if (sramVec.empty()) { Util::WriteFileBinary(std::array{}, sramPath); sramVec = Util::ReadFileBinary(sramPath); } @@ -48,56 +52,70 @@ void Mem::LoadSRAM(SaveType save_type, fs::path path) { Util::panic("Corrupt SRAM!"); } - saveData = mio::make_mmap_sink( - sramPath, 0, mio::map_entire_file, error); - if (error) { Util::panic("Could not mmap {}", sramPath); } + saveData = mio::make_mmap_sink(sramPath, 0, mio::map_entire_file, error); + if (error) { + Util::panic("Could not mmap {}", sramPath); + } } } -FORCE_INLINE void SetROMCIC(u32 checksum, ROM& rom) { +FORCE_INLINE void SetROMCIC(u32 checksum, ROM &rom) { switch (checksum) { - case 0xEC8B1325: rom.cicType = CIC_NUS_7102; break; // 7102 - case 0x1DEB51A9: rom.cicType = CIC_NUS_6101; break; // 6101 - case 0xC08E5BD6: rom.cicType = CIC_NUS_6102_7101; break; - case 0x03B8376A: rom.cicType = CIC_NUS_6103_7103; break; - case 0xCF7F41DC: rom.cicType = CIC_NUS_6105_7105; break; - case 0xD1059C6A: rom.cicType = CIC_NUS_6106_7106; break; - default: - Util::warn("Could not determine CIC TYPE! Checksum: 0x{:08X} is unknown!", checksum); - rom.cicType = UNKNOWN_CIC_TYPE; - break; + case 0xEC8B1325: + rom.cicType = CIC_NUS_7102; + break; // 7102 + case 0x1DEB51A9: + rom.cicType = CIC_NUS_6101; + break; // 6101 + case 0xC08E5BD6: + rom.cicType = CIC_NUS_6102_7101; + break; + case 0x03B8376A: + rom.cicType = CIC_NUS_6103_7103; + break; + case 0xCF7F41DC: + rom.cicType = CIC_NUS_6105_7105; + break; + case 0xD1059C6A: + rom.cicType = CIC_NUS_6106_7106; + break; + default: + Util::warn("Could not determine CIC TYPE! Checksum: 0x{:08X} is unknown!", checksum); + rom.cicType = UNKNOWN_CIC_TYPE; + break; } } -std::vector Mem::OpenArchive(const std::string &path, size_t& sizeAdjusted) { +std::vector Mem::OpenArchive(const std::string &path, size_t &sizeAdjusted) { auto stream = ar_open_file(fs::path(path).u8string().c_str()); - if(!stream) { + if (!stream) { Util::panic("Could not open archive! Are you sure it's an archive?"); } - ar_archive* archive = ar_open_zip_archive(stream, false); + ar_archive *archive = ar_open_zip_archive(stream, false); - if(!archive) archive = ar_open_rar_archive(stream); - if(!archive) archive = ar_open_7z_archive(stream); - if(!archive) archive = ar_open_tar_archive(stream); + if (!archive) + archive = ar_open_rar_archive(stream); + if (!archive) + archive = ar_open_7z_archive(stream); + if (!archive) + archive = ar_open_tar_archive(stream); - if(!archive) { + if (!archive) { ar_close(stream); Util::panic("Could not open archive! Are you sure it's a supported archive? (7z, zip, rar and tar are supported)"); } std::vector buf{}; - std::vector rom_exts{".n64",".z64",".v64",".N64",".Z64",".V64"}; + std::vector rom_exts{".n64", ".z64", ".v64", ".N64", ".Z64", ".V64"}; - while(ar_parse_entry(archive)) { + while (ar_parse_entry(archive)) { auto filename = ar_entry_get_name(archive); auto extension = fs::path(filename).extension(); - if(std::any_of(rom_exts.begin(), rom_exts.end(), [&](auto x) { - return extension == x; - })) { + if (std::any_of(rom_exts.begin(), rom_exts.end(), [&](auto x) { return extension == x; })) { auto size = ar_entry_get_size(archive); sizeAdjusted = Util::NextPow2(size); buf.resize(sizeAdjusted); @@ -115,13 +133,13 @@ std::vector Mem::OpenArchive(const std::string &path, size_t& sizeAdjusted) return buf; } -std::vector Mem::OpenROM(const std::string& filename, size_t& sizeAdjusted) { +std::vector Mem::OpenROM(const std::string &filename, size_t &sizeAdjusted) { auto buf = Util::ReadFileBinary(filename); sizeAdjusted = Util::NextPow2(buf.size()); return buf; } -void Mem::LoadROM(bool isArchive, const std::string& filename) { +void Mem::LoadROM(bool isArchive, const std::string &filename) { size_t sizeAdjusted; u32 endianness; { @@ -132,7 +150,7 @@ void Mem::LoadROM(bool isArchive, const std::string& filename) { buf = OpenROM(filename, sizeAdjusted); } - endianness = be32toh(*reinterpret_cast(buf.data())); + endianness = be32toh(*reinterpret_cast(buf.data())); Util::SwapN64Rom(buf, endianness); std::copy(buf.begin(), buf.end(), rom.cart.begin()); @@ -162,289 +180,322 @@ void Mem::LoadROM(bool isArchive, const std::string& filename) { u32 checksum = Util::crc32(0, &rom.cart[0x40], 0x9c0); SetROMCIC(checksum, rom); - endianness = be32toh(*reinterpret_cast(rom.cart.data())); + endianness = be32toh(*reinterpret_cast(rom.cart.data())); Util::SwapN64Rom(rom.cart, endianness); rom.pal = IsROMPAL(); } -template<> u8 Mem::Read(n64::Registers ®s, u32 paddr) { - SI& si = mmio.si; +template <> +u8 Mem::Read(n64::Registers ®s, u32 paddr) { + SI &si = mmio.si; switch (paddr) { - case RDRAM_REGION: - return mmio.rdp.ReadRDRAM(paddr); - case RSP_MEM_REGION: { - auto& src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; + case RDRAM_REGION: + return mmio.rdp.ReadRDRAM(paddr); + case RSP_MEM_REGION: + { + auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; return src[BYTE_ADDRESS(paddr & 0xfff)]; } - case REGION_CART: - return mmio.pi.BusRead(paddr); - case 0x04040000 ... 0x040FFFFF: - case 0x04100000 ... 0x041FFFFF: - case 0x04600000 ... 0x048FFFFF: - case 0x04300000 ... 0x044FFFFF: - Util::panic("MMIO Read!\n"); - case AI_REGION: { + case REGION_CART: + return mmio.pi.BusRead(paddr); + case 0x04040000 ... 0x040FFFFF: + case 0x04100000 ... 0x041FFFFF: + case 0x04600000 ... 0x048FFFFF: + case 0x04300000 ... 0x044FFFFF: + Util::panic("MMIO Read!\n"); + case AI_REGION: + { u32 w = mmio.ai.Read(paddr & ~3); int offs = 3 - (paddr & 3); return (w >> (offs * 8)) & 0xff; } - case PIF_ROM_REGION: - return si.pif.bootrom[BYTE_ADDRESS(paddr) - PIF_ROM_REGION_START]; - case PIF_RAM_REGION: - return si.pif.ram[paddr - PIF_RAM_REGION_START]; - case 0x00800000 ... 0x03EFFFFF: // unused - case 0x04200000 ... 0x042FFFFF: // unused - case 0x04900000 ... 0x04FFFFFF: // unused - case 0x1FC00800 ... 0xFFFFFFFF: // unused - return 0; - default: - Util::panic("Unimplemented 8-bit read at address {:08X} (PC = {:016X})", paddr, (u64) regs.pc); + case PIF_ROM_REGION: + return si.pif.bootrom[BYTE_ADDRESS(paddr) - PIF_ROM_REGION_START]; + case PIF_RAM_REGION: + return si.pif.ram[paddr - PIF_RAM_REGION_START]; + case 0x00800000 ... 0x03EFFFFF: // unused + case 0x04200000 ... 0x042FFFFF: // unused + case 0x04900000 ... 0x04FFFFFF: // unused + case 0x1FC00800 ... 0xFFFFFFFF: // unused + return 0; + default: + Util::panic("Unimplemented 8-bit read at address {:08X} (PC = {:016X})", paddr, (u64)regs.pc); } } -template<> u16 Mem::Read(n64::Registers ®s, u32 paddr) { - SI& si = mmio.si; +template <> +u16 Mem::Read(n64::Registers ®s, u32 paddr) { + SI &si = mmio.si; switch (paddr) { - case RDRAM_REGION: - return mmio.rdp.ReadRDRAM(paddr); - case RSP_MEM_REGION: { - auto& src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; + case RDRAM_REGION: + return mmio.rdp.ReadRDRAM(paddr); + case RSP_MEM_REGION: + { + auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; return Util::ReadAccess(src, HALF_ADDRESS(paddr & 0xfff)); } - case MMIO_REGION: - return mmio.Read(paddr); - case REGION_CART: - return mmio.pi.BusRead(paddr); - case PIF_ROM_REGION: - return Util::ReadAccess(si.pif.bootrom, HALF_ADDRESS(paddr) - PIF_ROM_REGION_START); - case PIF_RAM_REGION: - return be16toh(Util::ReadAccess(si.pif.ram, paddr - PIF_RAM_REGION_START)); - case 0x00800000 ... 0x03EFFFFF: - case 0x04200000 ... 0x042FFFFF: - case 0x04900000 ... 0x04FFFFFF: - case 0x1FC00800 ... 0xFFFFFFFF: - return 0; - default: - Util::panic("Unimplemented 16-bit read at address {:08X} (PC = {:016X})", paddr, (u64) regs.pc); + case MMIO_REGION: + return mmio.Read(paddr); + case REGION_CART: + return mmio.pi.BusRead(paddr); + case PIF_ROM_REGION: + return Util::ReadAccess(si.pif.bootrom, HALF_ADDRESS(paddr) - PIF_ROM_REGION_START); + case PIF_RAM_REGION: + return be16toh(Util::ReadAccess(si.pif.ram, paddr - PIF_RAM_REGION_START)); + case 0x00800000 ... 0x03EFFFFF: + case 0x04200000 ... 0x042FFFFF: + case 0x04900000 ... 0x04FFFFFF: + case 0x1FC00800 ... 0xFFFFFFFF: + return 0; + default: + Util::panic("Unimplemented 16-bit read at address {:08X} (PC = {:016X})", paddr, (u64)regs.pc); } } -template<> u32 Mem::Read(n64::Registers ®s, u32 paddr) { - SI& si = mmio.si; +template <> +u32 Mem::Read(n64::Registers ®s, u32 paddr) { + SI &si = mmio.si; - switch(paddr) { - case RDRAM_REGION: - return mmio.rdp.ReadRDRAM(paddr); - case RSP_MEM_REGION: { - auto& src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; + switch (paddr) { + case RDRAM_REGION: + return mmio.rdp.ReadRDRAM(paddr); + case RSP_MEM_REGION: + { + auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; return Util::ReadAccess(src, paddr & 0xfff); } - case MMIO_REGION: - return mmio.Read(paddr); - case REGION_CART: - return mmio.pi.BusRead(paddr); - case PIF_ROM_REGION: - return Util::ReadAccess(si.pif.bootrom, paddr - PIF_ROM_REGION_START); - case PIF_RAM_REGION: - return be32toh(Util::ReadAccess(si.pif.ram, paddr - PIF_RAM_REGION_START)); - case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF: - case 0x04900000 ... 0x04FFFFFF: case 0x1FC00800 ... 0xFFFFFFFF: return 0; - default: - Util::panic("Unimplemented 32-bit read at address {:08X} (PC = {:016X})", paddr, (u64) regs.pc); + case MMIO_REGION: + return mmio.Read(paddr); + case REGION_CART: + return mmio.pi.BusRead(paddr); + case PIF_ROM_REGION: + return Util::ReadAccess(si.pif.bootrom, paddr - PIF_ROM_REGION_START); + case PIF_RAM_REGION: + return be32toh(Util::ReadAccess(si.pif.ram, paddr - PIF_RAM_REGION_START)); + case 0x00800000 ... 0x03FFFFFF: + case 0x04200000 ... 0x042FFFFF: + case 0x04900000 ... 0x04FFFFFF: + case 0x1FC00800 ... 0xFFFFFFFF: + return 0; + default: + Util::panic("Unimplemented 32-bit read at address {:08X} (PC = {:016X})", paddr, (u64)regs.pc); } } -template<> u64 Mem::Read(n64::Registers ®s, u32 paddr) { - SI& si = mmio.si; +template <> +u64 Mem::Read(n64::Registers ®s, u32 paddr) { + SI &si = mmio.si; switch (paddr) { - case RDRAM_REGION: - return mmio.rdp.ReadRDRAM(paddr); - case RSP_MEM_REGION: { - auto& src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; + case RDRAM_REGION: + return mmio.rdp.ReadRDRAM(paddr); + case RSP_MEM_REGION: + { + auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; return Util::ReadAccess(src, paddr & 0xfff); } - case MMIO_REGION: - return mmio.Read(paddr); - case REGION_CART: - return mmio.pi.BusRead(paddr); - case PIF_ROM_REGION: - return Util::ReadAccess(si.pif.bootrom, paddr - PIF_ROM_REGION_START); - case PIF_RAM_REGION: - return be64toh(Util::ReadAccess(si.pif.ram, paddr - PIF_RAM_REGION_START)); - case 0x00800000 ... 0x03EFFFFF: - case 0x04200000 ... 0x042FFFFF: - case 0x04900000 ... 0x04FFFFFF: - case 0x1FC00800 ... 0xFFFFFFFF: - return 0; - default: - Util::panic("Unimplemented 32-bit read at address {:08X} (PC = {:016X})", paddr, (u64) regs.pc); + case MMIO_REGION: + return mmio.Read(paddr); + case REGION_CART: + return mmio.pi.BusRead(paddr); + case PIF_ROM_REGION: + return Util::ReadAccess(si.pif.bootrom, paddr - PIF_ROM_REGION_START); + case PIF_RAM_REGION: + return be64toh(Util::ReadAccess(si.pif.ram, paddr - PIF_RAM_REGION_START)); + case 0x00800000 ... 0x03EFFFFF: + case 0x04200000 ... 0x042FFFFF: + case 0x04900000 ... 0x04FFFFFF: + case 0x1FC00800 ... 0xFFFFFFFF: + return 0; + default: + Util::panic("Unimplemented 32-bit read at address {:08X} (PC = {:016X})", paddr, (u64)regs.pc); } } -template<> void Mem::Write(Registers& regs, u32 paddr, u32 val) { - SI& si = mmio.si; +template <> +void Mem::Write(Registers ®s, u32 paddr, u32 val) { + SI &si = mmio.si; switch (paddr) { - case RDRAM_REGION: - mmio.rdp.WriteRDRAM(paddr, val); - break; - case RSP_MEM_REGION: { + case RDRAM_REGION: + mmio.rdp.WriteRDRAM(paddr, val); + break; + case RSP_MEM_REGION: + { val = val << (8 * (3 - (paddr & 3))); - auto& dest = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; + auto &dest = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; paddr = (paddr & 0xFFF) & ~3; Util::WriteAccess(dest, paddr, val); - } break; - case REGION_CART: - Util::trace("BusWrite @ {:08X} = {:02X}", paddr, val); - mmio.pi.BusWrite(paddr, val); - break; - case MMIO_REGION: - Util::panic("MMIO Write!"); - case PIF_RAM_REGION: - val = val << (8 * (3 - (paddr & 3))); - paddr = (paddr - PIF_RAM_REGION_START) & ~3; - Util::WriteAccess(si.pif.ram, paddr, htobe32(val)); - si.pif.ProcessCommands(*this); - break; - case 0x00800000 ... 0x03EFFFFF: - case 0x04200000 ... 0x042FFFFF: - case 0x04900000 ... 0x04FFFFFF: - case PIF_ROM_REGION: - case 0x1FC00800 ... 0x7FFFFFFF: - case 0x80000000 ... 0xFFFFFFFF: - break; - default: - Util::panic("Unimplemented 8-bit write at address {:08X} with value {:02X} (PC = {:016X})", paddr, val, - (u64) regs.pc); + } + break; + case REGION_CART: + Util::trace("BusWrite @ {:08X} = {:02X}", paddr, val); + mmio.pi.BusWrite(paddr, val); + break; + case MMIO_REGION: + Util::panic("MMIO Write!"); + case PIF_RAM_REGION: + val = val << (8 * (3 - (paddr & 3))); + paddr = (paddr - PIF_RAM_REGION_START) & ~3; + Util::WriteAccess(si.pif.ram, paddr, htobe32(val)); + si.pif.ProcessCommands(*this); + break; + case 0x00800000 ... 0x03EFFFFF: + case 0x04200000 ... 0x042FFFFF: + case 0x04900000 ... 0x04FFFFFF: + case PIF_ROM_REGION: + case 0x1FC00800 ... 0x7FFFFFFF: + case 0x80000000 ... 0xFFFFFFFF: + break; + default: + Util::panic("Unimplemented 8-bit write at address {:08X} with value {:02X} (PC = {:016X})", paddr, val, + (u64)regs.pc); } } -template<> void Mem::Write(Registers& regs, u32 paddr, u32 val) { - SI& si = mmio.si; +template <> +void Mem::Write(Registers ®s, u32 paddr, u32 val) { + SI &si = mmio.si; switch (paddr) { - case RDRAM_REGION: - mmio.rdp.WriteRDRAM(paddr, val); - break; - case RSP_MEM_REGION: { + case RDRAM_REGION: + mmio.rdp.WriteRDRAM(paddr, val); + break; + case RSP_MEM_REGION: + { val = val << (16 * !(paddr & 2)); - auto& dest = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; + auto &dest = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; paddr = (paddr & 0xFFF) & ~3; Util::WriteAccess(dest, paddr, val); - } break; - case REGION_CART: - Util::trace("BusWrite @ {:08X} = {:04X}", paddr, val); - mmio.pi.BusWrite(paddr, val); - break; - case MMIO_REGION: - Util::panic("MMIO Write!"); - case PIF_RAM_REGION: - val = val << (16 * !(paddr & 2)); - paddr &= ~3; - Util::WriteAccess(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe32(val)); - si.pif.ProcessCommands(*this); - break; - case 0x00800000 ... 0x03EFFFFF: - case 0x04200000 ... 0x042FFFFF: - case 0x04900000 ... 0x04FFFFFF: - case PIF_ROM_REGION: - case 0x1FC00800 ... 0x7FFFFFFF: - case 0x80000000 ... 0xFFFFFFFF: - break; - default: - Util::panic("Unimplemented 16-bit write at address {:08X} with value {:04X} (PC = {:016X})", paddr, val, - (u64) regs.pc); + } + break; + case REGION_CART: + Util::trace("BusWrite @ {:08X} = {:04X}", paddr, val); + mmio.pi.BusWrite(paddr, val); + break; + case MMIO_REGION: + Util::panic("MMIO Write!"); + case PIF_RAM_REGION: + val = val << (16 * !(paddr & 2)); + paddr &= ~3; + Util::WriteAccess(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe32(val)); + si.pif.ProcessCommands(*this); + break; + case 0x00800000 ... 0x03EFFFFF: + case 0x04200000 ... 0x042FFFFF: + case 0x04900000 ... 0x04FFFFFF: + case PIF_ROM_REGION: + case 0x1FC00800 ... 0x7FFFFFFF: + case 0x80000000 ... 0xFFFFFFFF: + break; + default: + Util::panic("Unimplemented 16-bit write at address {:08X} with value {:04X} (PC = {:016X})", paddr, val, + (u64)regs.pc); } } -template<> void Mem::Write(Registers& regs, u32 paddr, u32 val) { - SI& si = mmio.si; +template <> +void Mem::Write(Registers ®s, u32 paddr, u32 val) { + SI &si = mmio.si; - switch(paddr) { - case RDRAM_REGION: - mmio.rdp.WriteRDRAM(paddr, val); - break; - case RSP_MEM_REGION: { - auto& dest = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; + switch (paddr) { + case RDRAM_REGION: + mmio.rdp.WriteRDRAM(paddr, val); + break; + case RSP_MEM_REGION: + { + auto &dest = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; Util::WriteAccess(dest, paddr & 0xfff, val); - } break; - case REGION_CART: - Util::trace("BusWrite @ {:08X} = {:08X}", paddr, val); - mmio.pi.BusWrite(paddr, val); - break; - case MMIO_REGION: - mmio.Write(paddr, val); - break; - case PIF_RAM_REGION: - Util::WriteAccess(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe32(val)); - si.pif.ProcessCommands(*this); - break; - case 0x00800000 ... 0x03EFFFFF: - case 0x04200000 ... 0x042FFFFF: - case 0x04900000 ... 0x04FFFFFF: - case PIF_ROM_REGION: - case 0x1FC00800 ... 0x7FFFFFFF: - case 0x80000000 ... 0xFFFFFFFF: break; - default: Util::panic("Unimplemented 32-bit write at address {:08X} with value {:0X} (PC = {:016X})", paddr, val, (u64)regs.pc); + } + break; + case REGION_CART: + Util::trace("BusWrite @ {:08X} = {:08X}", paddr, val); + mmio.pi.BusWrite(paddr, val); + break; + case MMIO_REGION: + mmio.Write(paddr, val); + break; + case PIF_RAM_REGION: + Util::WriteAccess(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe32(val)); + si.pif.ProcessCommands(*this); + break; + case 0x00800000 ... 0x03EFFFFF: + case 0x04200000 ... 0x042FFFFF: + case 0x04900000 ... 0x04FFFFFF: + case PIF_ROM_REGION: + case 0x1FC00800 ... 0x7FFFFFFF: + case 0x80000000 ... 0xFFFFFFFF: + break; + default: + Util::panic("Unimplemented 32-bit write at address {:08X} with value {:0X} (PC = {:016X})", paddr, val, + (u64)regs.pc); } } -void Mem::Write(Registers& regs, u32 paddr, u64 val) { - SI& si = mmio.si; +void Mem::Write(Registers ®s, u32 paddr, u64 val) { + SI &si = mmio.si; switch (paddr) { - case RDRAM_REGION: - mmio.rdp.WriteRDRAM(paddr, val); - break; - case RSP_MEM_REGION: { - auto& dest = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; + case RDRAM_REGION: + mmio.rdp.WriteRDRAM(paddr, val); + break; + case RSP_MEM_REGION: + { + auto &dest = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; val >>= 32; Util::WriteAccess(dest, paddr & 0xfff, val); - } break; - case REGION_CART: - Util::trace("BusWrite @ {:08X} = {:016X}", paddr, val); - mmio.pi.BusWrite(paddr, val); - break; - case MMIO_REGION: - Util::panic("MMIO Write!"); - case PIF_RAM_REGION: - Util::WriteAccess(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe64(val)); - si.pif.ProcessCommands(*this); - break; - case 0x00800000 ... 0x03EFFFFF: - case 0x04200000 ... 0x042FFFFF: - case 0x04900000 ... 0x04FFFFFF: - case 0x1FC00000 ... 0x1FC007BF: - case 0x1FC00800 ... 0x7FFFFFFF: - case 0x80000000 ... 0xFFFFFFFF: break; - default: - Util::panic("Unimplemented 64-bit write at address {:08X} with value {:0X} (PC = {:016X})", paddr, val, - (u64) regs.pc); + } + break; + case REGION_CART: + Util::trace("BusWrite @ {:08X} = {:016X}", paddr, val); + mmio.pi.BusWrite(paddr, val); + break; + case MMIO_REGION: + Util::panic("MMIO Write!"); + case PIF_RAM_REGION: + Util::WriteAccess(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe64(val)); + si.pif.ProcessCommands(*this); + break; + case 0x00800000 ... 0x03EFFFFF: + case 0x04200000 ... 0x042FFFFF: + case 0x04900000 ... 0x04FFFFFF: + case 0x1FC00000 ... 0x1FC007BF: + case 0x1FC00800 ... 0x7FFFFFFF: + case 0x80000000 ... 0xFFFFFFFF: + break; + default: + Util::panic("Unimplemented 64-bit write at address {:08X} with value {:0X} (PC = {:016X})", paddr, val, + (u64)regs.pc); } } -template <> u32 Mem::BackupRead(u32 addr) { - switch(saveType) { - case SAVE_NONE: return 0; - case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: - Util::warn("Accessing cartridge backup type SAVE_EEPROM, returning 0 for word read"); - return 0; - case SAVE_FLASH_1m: - return flash.Read(addr); - case SAVE_SRAM_256k: - return 0xFFFFFFFF; - default: - Util::panic("Backup read word with unknown save type"); - } -} - -template <> u8 Mem::BackupRead(u32 addr) { +template <> +u32 Mem::BackupRead(u32 addr) { switch (saveType) { - case SAVE_NONE: return 0; - case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: + case SAVE_NONE: + return 0; + case SAVE_EEPROM_4k: + case SAVE_EEPROM_16k: + Util::warn("Accessing cartridge backup type SAVE_EEPROM, returning 0 for word read"); + return 0; + case SAVE_FLASH_1m: + return flash.Read(addr); + case SAVE_SRAM_256k: + return 0xFFFFFFFF; + default: + Util::panic("Backup read word with unknown save type"); + } +} + +template <> +u8 Mem::BackupRead(u32 addr) { + switch (saveType) { + case SAVE_NONE: + return 0; + case SAVE_EEPROM_4k: + case SAVE_EEPROM_16k: Util::warn("Accessing cartridge backup type SAVE_EEPROM, returning 0 for word read"); return 0; case SAVE_FLASH_1m: @@ -453,8 +504,7 @@ template <> u8 Mem::BackupRead(u32 addr) { if (saveData.is_mapped()) { assert(addr < saveData.size()); return saveData[addr]; - } - else { + } else { Util::panic("Invalid backup Read if save data is not initialized"); } default: @@ -462,43 +512,47 @@ template <> u8 Mem::BackupRead(u32 addr) { } } -template <> void Mem::BackupWrite(u32 addr, u32 val) { - switch(saveType) { - case SAVE_NONE: - Util::warn("Accessing cartridge with save type SAVE_NONE in write word"); - break; - case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: - Util::panic("Accessing cartridge with save type SAVE_EEPROM in write word"); - case SAVE_FLASH_1m: - flash.Write(addr, val); - break; - case SAVE_SRAM_256k: - break; - default: - Util::panic("Backup read word with unknown save type"); +template <> +void Mem::BackupWrite(u32 addr, u32 val) { + switch (saveType) { + case SAVE_NONE: + Util::warn("Accessing cartridge with save type SAVE_NONE in write word"); + break; + case SAVE_EEPROM_4k: + case SAVE_EEPROM_16k: + Util::panic("Accessing cartridge with save type SAVE_EEPROM in write word"); + case SAVE_FLASH_1m: + flash.Write(addr, val); + break; + case SAVE_SRAM_256k: + break; + default: + Util::panic("Backup read word with unknown save type"); } } -template <> void Mem::BackupWrite(u32 addr, u8 val) { - switch(saveType) { - case SAVE_NONE: - Util::warn("Accessing cartridge with save type SAVE_NONE in write word"); - break; - case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: - Util::panic("Accessing cartridge with save type SAVE_EEPROM in write word"); - case SAVE_FLASH_1m: - flash.Write(addr, val); - break; - case SAVE_SRAM_256k: - if(saveData.is_mapped()) { - assert(addr < saveData.size()); - saveData[addr] = val; - } else { - Util::panic("Invalid backup Write if save data is not initialized"); - } - break; - default: - Util::panic("Backup read word with unknown save type"); +template <> +void Mem::BackupWrite(u32 addr, u8 val) { + switch (saveType) { + case SAVE_NONE: + Util::warn("Accessing cartridge with save type SAVE_NONE in write word"); + break; + case SAVE_EEPROM_4k: + case SAVE_EEPROM_16k: + Util::panic("Accessing cartridge with save type SAVE_EEPROM in write word"); + case SAVE_FLASH_1m: + flash.Write(addr, val); + break; + case SAVE_SRAM_256k: + if (saveData.is_mapped()) { + assert(addr < saveData.size()); + saveData[addr] = val; + } else { + Util::panic("Invalid backup Write if save data is not initialized"); + } + break; + default: + Util::panic("Backup read word with unknown save type"); } } @@ -517,9 +571,9 @@ std::vector Mem::Serialize() { return res; } -void Mem::Deserialize(const std::vector& data) { +void Mem::Deserialize(const std::vector &data) { mmio.Deserialize(std::vector(data.begin(), data.begin() + mmioSize)); flash.Deserialize(std::vector(data.begin() + mmioSize, data.begin() + mmioSize + flashSize)); memcpy(saveData.data(), data.data() + mmioSize + flashSize, saveData.size()); } -} \ No newline at end of file +} // namespace n64 diff --git a/src/backend/core/Mem.hpp b/src/backend/core/Mem.hpp index 6acbf691..e0320707 100644 --- a/src/backend/core/Mem.hpp +++ b/src/backend/core/Mem.hpp @@ -1,13 +1,13 @@ #pragma once -#include -#include -#include -#include -#include +#include +#include #include #include -#include -#include +#include +#include +#include +#include +#include namespace n64 { struct ROMHeader { @@ -37,22 +37,20 @@ struct ROM { bool pal; }; -enum class FlashState : u8 { - Idle, Erase, Write, Read, Status -}; +enum class FlashState : u8 { Idle, Erase, Write, Read, Status }; struct Flash { - explicit Flash(mio::mmap_sink&); + explicit Flash(mio::mmap_sink &); ~Flash() = default; void Reset(); - void Load(SaveType, const std::string&); + void Load(SaveType, const std::string &); FlashState state{}; u64 status{}; size_t eraseOffs{}; size_t writeOffs{}; std::array writeBuf{}; std::string flashPath{}; - mio::mmap_sink& saveData; + mio::mmap_sink &saveData; enum FlashCommands : u8 { FLASH_COMMAND_EXECUTE = 0xD2, @@ -72,7 +70,7 @@ struct Flash { void CommandWrite(); void CommandRead(); std::vector Serialize(); - void Deserialize(const std::vector& data); + void Deserialize(const std::vector &data); template void Write(u32 index, T val); template @@ -81,28 +79,24 @@ struct Flash { struct Mem { ~Mem() = default; - Mem(Registers&, ParallelRDP&); + Mem(Registers &, ParallelRDP &); void Reset(); void LoadSRAM(SaveType, fs::path); - static std::vector OpenROM(const std::string&, size_t&); - static std::vector OpenArchive(const std::string&, size_t&); - void LoadROM(bool, const std::string&); - [[nodiscard]] auto GetRDRAMPtr() -> u8* { - return mmio.rdp.rdram.data(); - } + static std::vector OpenROM(const std::string &, size_t &); + static std::vector OpenArchive(const std::string &, size_t &); + void LoadROM(bool, const std::string &); + [[nodiscard]] auto GetRDRAMPtr() -> u8 * { return mmio.rdp.rdram.data(); } - [[nodiscard]] auto GetRDRAM() -> std::vector& { - return mmio.rdp.rdram; - } + [[nodiscard]] auto GetRDRAM() -> std::vector & { return mmio.rdp.rdram; } std::vector Serialize(); - void Deserialize(const std::vector&); + void Deserialize(const std::vector &); template - T Read(Registers&, u32); + T Read(Registers &, u32); template - void Write(Registers&, u32, u32); - void Write(Registers&, u32, u64); + void Write(Registers &, u32, u32); + void Write(Registers &, u32, u64); template T BackupRead(u32); @@ -135,6 +129,7 @@ struct Mem { ROM rom; SaveType saveType = SAVE_NONE; Flash flash; + private: friend struct SI; friend struct PI; @@ -148,9 +143,7 @@ private: FORCE_INLINE bool IsROMPAL() { static const char pal_codes[] = {'D', 'F', 'I', 'P', 'S', 'U', 'X', 'Y'}; - return std::any_of(std::begin(pal_codes), std::end(pal_codes), [this](char a) { - return rom.cart[0x3d] == a; - }); + return std::any_of(std::begin(pal_codes), std::end(pal_codes), [this](char a) { return rom.cart[0x3d] == a; }); } }; -} +} // namespace n64 diff --git a/src/backend/core/jit/instructions.cpp b/src/backend/core/jit/instructions.cpp index 1c48f269..35187f8c 100644 --- a/src/backend/core/jit/instructions.cpp +++ b/src/backend/core/jit/instructions.cpp @@ -3,618 +3,541 @@ #define check_signed_overflow(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 { -void JIT::lui(u32 instr) { - u64 val = s64((s16)instr); - val <<= 16; - if (RT(instr) != 0) [[likely]] { +namespace n64 +{ + void JIT::lui(u32 instr) { + u64 val = s64((s16)instr); + val <<= 16; regs.Write(RT(instr), val); - regs.gprIsConstant[RT(instr)] = true; } -} -void JIT::add(u32 instr) { - if(regs.IsRegConstant(RS(instr), RT(instr))) { - u32 rs = regs.Read(RS(instr)); - u32 rt = regs.Read(RT(instr)); - u32 result = rs + rt; - if(check_signed_overflow(rs, rt, result)) { - //regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC); - Util::panic("[JIT]: Unhandled Overflow exception in ADD!"); - } - - if (RD(instr) != 0) [[likely]] { - regs.Write(RD(instr), s32(result)); - regs.gprIsConstant[RD(instr)] = true; - } - } else { - Util::panic("[JIT]: Implement non constant ADD"); - } -} - -void JIT::addu(u32 instr) { - if(regs.IsRegConstant(RS(instr), RT(instr))) { - s32 rs = regs.Read(RS(instr)); - s32 rt = regs.Read(RT(instr)); - s32 result = rs + rt; - - if (RD(instr) != 0) [[likely]] { - regs.Write(RD(instr), result); - regs.gprIsConstant[RD(instr)] = true; - } - } else { - Util::panic("[JIT]: Implement non constant ADDI"); - } -} - -void JIT::addi(u32 instr) { - if(regs.IsRegConstant(RS(instr))) { - auto rs = regs.Read(RS(instr)); - u32 imm = s32(s16(instr)); - u32 result = rs + imm; - if(check_signed_overflow(rs, imm, result)) { - Util::panic("[JIT]: Unhandled Overflow exception in ADDI!"); - } else { - if (RT(instr) != 0) [[likely]] { - regs.Write(RT(instr), s32(result)); - regs.gprIsConstant[RT(instr)] = true; + void JIT::add(u32 instr) { + if (regs.IsRegConstant(RS(instr), RT(instr))) { + u32 rs = regs.Read(RS(instr)); + u32 rt = regs.Read(RT(instr)); + u32 result = rs + rt; + if (check_signed_overflow(rs, rt, result)) { + //regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC); + Util::panic("[JIT]: Unhandled Overflow exception in ADD!"); } + regs.Write(RD(instr), s32(result)); + } else { + Util::panic("[JIT]: Implement non constant ADD"); } - } else { - Util::panic("[JIT]: Implement non constant ADDI!"); } -} -void JIT::addiu(u32 instr) { - if(regs.IsRegConstant(RS(instr))) { - auto rs = regs.Read(RS(instr)); - u32 imm = s32(s16(instr)); - u32 result = rs + imm; - - if (RT(instr) != 0) [[likely]] { - regs.Write(RT(instr), s32(result)); - regs.gprIsConstant[RT(instr)] = true; - } - } else { - Util::panic("[JIT]: Implement non constant ADDIU!"); - } -} - -void JIT::andi(u32 instr) { - s64 imm = (u16)instr; - if(regs.IsRegConstant(RS(instr))) { - if (RT(instr) != 0) [[likely]] { - regs.Write(RT(instr), regs.Read(RS(instr)) & imm); - regs.gprIsConstant[RT(instr)] = true; - } - } else { - Util::panic("[JIT]: Implement non constant ANDI!"); - } -} - -void JIT::and_(u32 instr) { - if(regs.IsRegConstant(RS(instr), RT(instr))) { - if (RD(instr) != 0) [[likely]] { - regs.Write(RD(instr), regs.Read(RS(instr)) & regs.Read(RT(instr))); - regs.gprIsConstant[RD(instr)] = true; - } - } else { - Util::panic("[JIT]: Implement non constant AND!"); - } -} - -void JIT::dadd(u32 instr) { - if(regs.IsRegConstant(RS(instr), RT(instr))) { - auto rs = regs.Read(RS(instr)); - auto rt = regs.Read(RT(instr)); - u64 result = rt + rs; - if (check_signed_overflow(rs, rt, result)) { - //regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC); - Util::panic("[JIT]: Unhandled Overflow exception in DADD!"); - } - - if (RD(instr) != 0) [[likely]] { + void JIT::addu(u32 instr) { + if (regs.IsRegConstant(RS(instr), RT(instr))) { + s32 rs = regs.Read(RS(instr)); + s32 rt = regs.Read(RT(instr)); + s32 result = rs + rt; regs.Write(RD(instr), result); - regs.gprIsConstant[RD(instr)] = true; + } else { + Util::panic("[JIT]: Implement non constant ADDI"); } - } else { - Util::panic("[JIT]: Implement non constant DADD!"); } -} -void JIT::daddu(u32 instr) { - if(regs.IsRegConstant(RS(instr), RT(instr))) { - if (RD(instr) != 0) [[likely]] { + void JIT::addi(u32 instr) { + if (regs.IsRegConstant(RS(instr))) { + auto rs = regs.Read(RS(instr)); + u32 imm = s32(s16(instr)); + u32 result = rs + imm; + if (check_signed_overflow(rs, imm, result)) { + Util::panic("[JIT]: Unhandled Overflow exception in ADDI!"); + } else { + regs.Write(RT(instr), s32(result)); + } + } else { + Util::panic("[JIT]: Implement non constant ADDI!"); + } + } + + void JIT::addiu(u32 instr) { + if (regs.IsRegConstant(RS(instr))) { + auto rs = regs.Read(RS(instr)); + u32 imm = s32(s16(instr)); + u32 result = rs + imm; + regs.Write(RT(instr), s32(result)); + } else { + Util::panic("[JIT]: Implement non constant ADDIU!"); + } + } + + void JIT::andi(u32 instr) { + s64 imm = (u16)instr; + if (regs.IsRegConstant(RS(instr))) { + regs.Write(RT(instr), regs.Read(RS(instr)) & imm); + } else { + Util::panic("[JIT]: Implement non constant ANDI!"); + } + } + + void JIT::and_(u32 instr) { + if (regs.IsRegConstant(RS(instr), RT(instr))) { + regs.Write(RD(instr), regs.Read(RS(instr)) & regs.Read(RT(instr))); + } else { + Util::panic("[JIT]: Implement non constant AND!"); + } + } + + void JIT::dadd(u32 instr) { + if (regs.IsRegConstant(RS(instr), RT(instr))) { + auto rs = regs.Read(RS(instr)); + auto rt = regs.Read(RT(instr)); + u64 result = rt + rs; + if (check_signed_overflow(rs, rt, result)) { + //regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC); + Util::panic("[JIT]: Unhandled Overflow exception in DADD!"); + } + regs.Write(RD(instr), result); + } else { + Util::panic("[JIT]: Implement non constant DADD!"); + } + } + + void JIT::daddu(u32 instr) { + if (regs.IsRegConstant(RS(instr), RT(instr))) { auto rs = regs.Read(RS(instr)); auto rt = regs.Read(RT(instr)); - regs.Write(RD(instr), rt + rs); - regs.gprIsConstant[RD(instr)] = true; + regs.Write(RD(instr), rt + rs); + } else { + Util::panic("[JIT]: Implement non constant DADD!"); } - } else { - Util::panic("[JIT]: Implement non constant DADD!"); } -} -void JIT::daddi(u32 instr) { - if(regs.IsRegConstant(RS(instr))) { - u64 imm = s64(s16(instr)); - auto rs = regs.Read(RS(instr)); - u64 result = imm + rs; - if (check_signed_overflow(rs, imm, result)) { - //regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC); - Util::panic("[JIT]: Unhandled Overflow exception in DADDI!"); - } - - if (RT(instr) != 0) [[likely]] { + void JIT::daddi(u32 instr) { + if (regs.IsRegConstant(RS(instr))) { + u64 imm = s64(s16(instr)); + auto rs = regs.Read(RS(instr)); + u64 result = imm + rs; + if (check_signed_overflow(rs, imm, result)) { + //regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC); + Util::panic("[JIT]: Unhandled Overflow exception in DADDI!"); + } regs.Write(RT(instr), result); - regs.gprIsConstant[RT(instr)] = true; + } else { + Util::panic("[JIT]: Implement non constant DADDI!"); } - } else { - Util::panic("[JIT]: Implement non constant DADDI!"); } -} -void JIT::daddiu(u32 instr) { - if(regs.IsRegConstant(RS(instr))) { - if (RT(instr) != 0) [[likely]] { + void JIT::daddiu(u32 instr) { + if (regs.IsRegConstant(RS(instr))) { s16 imm = s16(instr); auto rs = regs.Read(RS(instr)); - regs.Write(RT(instr), imm + rs); - regs.gprIsConstant[RT(instr)] = true; + regs.Write(RT(instr), imm + rs); + } else { + Util::panic("[JIT]: Implement non constant DADDI!"); } - } else { - Util::panic("[JIT]: Implement non constant DADDI!"); } -} -void JIT::ddiv(u32 instr) { - if(regs.IsRegConstant(RS(instr), RT(instr))) { - auto dividend = regs.Read(RS(instr)); - auto divisor = regs.Read(RT(instr)); - if (dividend == 0x8000000000000000 && divisor == 0xFFFFFFFFFFFFFFFF) { - regs.lo = dividend; - regs.hi = 0; - } else if(divisor == 0) { - regs.hi = dividend; - if(dividend >= 0) { + void JIT::ddiv(u32 instr) { + if (regs.IsRegConstant(RS(instr), RT(instr))) { + auto dividend = regs.Read(RS(instr)); + auto divisor = regs.Read(RT(instr)); + if (dividend == 0x8000000000000000 && divisor == 0xFFFFFFFFFFFFFFFF) { + regs.lo = dividend; + regs.hi = 0; + } else if (divisor == 0) { + regs.hi = dividend; + if (dividend >= 0) { + regs.lo = -1; + } else { + regs.lo = 1; + } + } else { + s64 quotient = dividend / divisor; + s64 remainder = dividend % divisor; + regs.lo = quotient; + regs.hi = remainder; + } + + regs.loIsConstant = true; + regs.hiIsConstant = true; + } else { + Util::panic("[JIT]: Implement non constant DDIV!"); + } + } + + void JIT::ddivu(u32 instr) { + if (regs.IsRegConstant(RS(instr), RT(instr))) { + auto dividend = regs.Read(RS(instr)); + auto divisor = regs.Read(RT(instr)); + if (divisor == 0) { regs.lo = -1; + regs.hi = (s64)dividend; } else { - regs.lo = 1; + u64 quotient = dividend / divisor; + u64 remainder = dividend % divisor; + regs.lo = (s64)quotient; + regs.hi = (s64)remainder; } + + regs.loIsConstant = true; + regs.hiIsConstant = true; } else { - s64 quotient = dividend / divisor; - s64 remainder = dividend % divisor; - regs.lo = quotient; - regs.hi = remainder; + Util::panic("[JIT]: Implement non constant DDIVU!"); } - - regs.loIsConstant = true; - regs.hiIsConstant = true; - } else { - Util::panic("[JIT]: Implement non constant DDIV!"); } -} -void JIT::ddivu(u32 instr) { - if(regs.IsRegConstant(RS(instr), RT(instr))) { - auto dividend = regs.Read(RS(instr)); - auto divisor = regs.Read(RT(instr)); - if (divisor == 0) { - regs.lo = -1; - regs.hi = (s64) dividend; - } else { - u64 quotient = dividend / divisor; - u64 remainder = dividend % divisor; - regs.lo = (s64) quotient; - regs.hi = (s64) remainder; - } + void JIT::div(u32 instr) { + if (regs.IsRegConstant(RS(instr), RT(instr))) { + s64 dividend = regs.Read(RS(instr)); + s64 divisor = regs.Read(RT(instr)); - regs.loIsConstant = true; - regs.hiIsConstant = true; - } else { - Util::panic("[JIT]: Implement non constant DDIVU!"); - } -} - -void JIT::div(u32 instr) { - if(regs.IsRegConstant(RS(instr), RT(instr))) { - s64 dividend = regs.Read(RS(instr)); - s64 divisor = regs.Read(RT(instr)); - - if (divisor == 0) { - regs.hi = dividend; - if (dividend >= 0) { - regs.lo = s64(-1); + if (divisor == 0) { + regs.hi = dividend; + if (dividend >= 0) { + regs.lo = s64(-1); + } else { + regs.lo = s64(1); + } } else { - regs.lo = s64(1); + s32 quotient = dividend / divisor; + s32 remainder = dividend % divisor; + regs.lo = quotient; + regs.hi = remainder; } + + regs.loIsConstant = true; + regs.hiIsConstant = true; } else { - s32 quotient = dividend / divisor; - s32 remainder = dividend % divisor; - regs.lo = quotient; - regs.hi = remainder; + Util::panic("[JIT]: Implement non constant DIV!"); } - - regs.loIsConstant = true; - regs.hiIsConstant = true; - } else { - Util::panic("[JIT]: Implement non constant DIV!"); } -} -void JIT::divu(u32 instr) { - if(regs.IsRegConstant(RS(instr), RT(instr))) { - auto dividend = regs.Read(RS(instr)); - auto divisor = regs.Read(RT(instr)); - if (divisor == 0) { - regs.lo = -1; - regs.hi = (s32) dividend; + void JIT::divu(u32 instr) { + if (regs.IsRegConstant(RS(instr), RT(instr))) { + auto dividend = regs.Read(RS(instr)); + auto divisor = regs.Read(RT(instr)); + if (divisor == 0) { + regs.lo = -1; + regs.hi = (s32)dividend; + } else { + s32 quotient = (s32)(dividend / divisor); + s32 remainder = (s32)(dividend % divisor); + regs.lo = quotient; + regs.hi = remainder; + } + + regs.loIsConstant = true; + regs.hiIsConstant = true; } else { - s32 quotient = (s32) (dividend / divisor); - s32 remainder = (s32) (dividend % divisor); - regs.lo = quotient; - regs.hi = remainder; + Util::panic("[JIT]: Implement non constant DIVU!"); } - - regs.loIsConstant = true; - regs.hiIsConstant = true; - } else { - Util::panic("[JIT]: Implement non constant DIVU!"); } -} -void JIT::dmult(u32 instr) { - if(regs.IsRegConstant(RT(instr), RS(instr))) { - auto rt = regs.Read(RT(instr)); - auto rs = regs.Read(RS(instr)); - s128 result = (s128)rt * (s128)rs; - regs.lo = result & 0xFFFFFFFFFFFFFFFF; - regs.hi = result >> 64; - regs.hiIsConstant = true; - regs.loIsConstant = true; - } else { - Util::panic("[JIT]: Implement non constant DMULT!"); + void JIT::dmult(u32 instr) { + if (regs.IsRegConstant(RT(instr), RS(instr))) { + auto rt = regs.Read(RT(instr)); + auto rs = regs.Read(RS(instr)); + s128 result = (s128)rt * (s128)rs; + regs.lo = result & 0xFFFFFFFFFFFFFFFF; + regs.hi = result >> 64; + regs.hiIsConstant = true; + regs.loIsConstant = true; + } else { + Util::panic("[JIT]: Implement non constant DMULT!"); + } } -} -void JIT::dmultu(u32 instr) { - if(regs.IsRegConstant(RT(instr), RS(instr))) { - auto rt = regs.Read(RT(instr)); - auto rs = regs.Read(RS(instr)); - u128 result = (u128)rt * (u128)rs; - regs.lo = s64(result & 0xFFFFFFFFFFFFFFFF); - regs.hi = s64(result >> 64); - regs.hiIsConstant = true; - regs.loIsConstant = true; - } else { - Util::panic("[JIT]: Implement non constant DMULT!"); + void JIT::dmultu(u32 instr) { + if (regs.IsRegConstant(RT(instr), RS(instr))) { + auto rt = regs.Read(RT(instr)); + auto rs = regs.Read(RS(instr)); + u128 result = (u128)rt * (u128)rs; + regs.lo = s64(result & 0xFFFFFFFFFFFFFFFF); + regs.hi = s64(result >> 64); + regs.hiIsConstant = true; + regs.loIsConstant = true; + } else { + Util::panic("[JIT]: Implement non constant DMULT!"); + } } -} -void JIT::dsll(u32 instr) { - if(regs.IsRegConstant(RT(instr))) { - if (RD(instr) != 0) [[likely]] { + void JIT::dsll(u32 instr) { + if (regs.IsRegConstant(RT(instr))) { u8 sa = ((instr >> 6) & 0x1f); auto result = regs.Read(RT(instr)) << sa; - regs.Write(RD(instr), result); - regs.gprIsConstant[RD(instr)] = true; + regs.Write(RD(instr), result); + } else { + Util::panic("[JIT]: Implement non constant DSLL!"); } - } else { - Util::panic("[JIT]: Implement non constant DSLL!"); } -} -void JIT::dsllv(u32 instr) { - if(regs.IsRegConstant(RT(instr), RS(instr))) { - if (RD(instr) != 0) [[likely]] { + void JIT::dsllv(u32 instr) { + if (regs.IsRegConstant(RT(instr), RS(instr))) { auto sa = regs.Read(RS(instr)) & 63; auto result = regs.Read(RT(instr)) << sa; - regs.Write(RD(instr), result); - regs.gprIsConstant[RD(instr)] = true; + regs.Write(RD(instr), result); + } else { + Util::panic("[JIT]: Implement non constant DSLLV!"); } - } else { - Util::panic("[JIT]: Implement non constant DSLLV!"); } -} -void JIT::dsll32(u32 instr) { - if(regs.IsRegConstant(RT(instr))) { - if (RD(instr) != 0) [[likely]] { + void JIT::dsll32(u32 instr) { + if (regs.IsRegConstant(RT(instr))) { u8 sa = ((instr >> 6) & 0x1f); auto result = regs.Read(RT(instr)) << (sa + 32); - regs.Write(RD(instr), result); - regs.gprIsConstant[RD(instr)] = true; + regs.Write(RD(instr), result); + } else { + Util::panic("[JIT]: Implement non constant DSLL32!"); } - } else { - Util::panic("[JIT]: Implement non constant DSLL32!"); } -} -void JIT::dsra(u32 instr) { - if(regs.IsRegConstant(RT(instr))) { - if (RD(instr) != 0) [[likely]] { + void JIT::dsra(u32 instr) { + if (regs.IsRegConstant(RT(instr))) { auto rt = regs.Read(RT(instr)); u8 sa = ((instr >> 6) & 0x1f); s64 result = rt >> sa; - regs.Write(RD(instr), result); - regs.gprIsConstant[RD(instr)] = true; + regs.Write(RD(instr), result); + } else { + Util::panic("[JIT]: Implement non constant DSRA!"); } - } else { - Util::panic("[JIT]: Implement non constant DSRA!"); } -} -void JIT::dsrav(u32 instr) { - if(regs.IsRegConstant(RT(instr), RS(instr))) { - if (RD(instr) != 0) [[likely]] { + void JIT::dsrav(u32 instr) { + if (regs.IsRegConstant(RT(instr), RS(instr))) { auto rt = regs.Read(RT(instr)); auto rs = regs.Read(RS(instr)); s64 sa = rs & 63; s64 result = rt >> sa; - regs.Write(RD(instr), result); - regs.gprIsConstant[RD(instr)] = true; + regs.Write(RD(instr), result); + } else { + Util::panic("[JIT]: Implement non constant DSRAV!"); } - } else { - Util::panic("[JIT]: Implement non constant DSRAV!"); } -} -void JIT::dsra32(u32 instr) { - if(regs.IsRegConstant(RT(instr))) { - if (RD(instr) != 0) [[likely]] { + void JIT::dsra32(u32 instr) { + if (regs.IsRegConstant(RT(instr))) { auto rt = regs.Read(RT(instr)); u8 sa = ((instr >> 6) & 0x1f); s64 result = rt >> (sa + 32); - regs.Write(RD(instr), result); - regs.gprIsConstant[RD(instr)] = true; + regs.Write(RD(instr), result); + } else { + Util::panic("[JIT]: Implement non constant DSRA32!"); } - } else { - Util::panic("[JIT]: Implement non constant DSRA32!"); } -} -void JIT::dsrl(u32 instr) { - if(regs.IsRegConstant(RT(instr))) { - if (RD(instr) != 0) [[likely]] { + void JIT::dsrl(u32 instr) { + if (regs.IsRegConstant(RT(instr))) { auto rt = regs.Read(RT(instr)); u8 sa = ((instr >> 6) & 0x1f); u64 result = rt >> sa; - regs.Write(RD(instr), s64(result)); - regs.gprIsConstant[RD(instr)] = true; + regs.Write(RD(instr), s64(result)); + } else { + Util::panic("[JIT]: Implement non constant DSRL!"); } - } else { - Util::panic("[JIT]: Implement non constant DSRL!"); } -} -void JIT::dsrlv(u32 instr) { - if(regs.IsRegConstant(RT(instr), RS(instr))) { - if (RD(instr) != 0) [[likely]] { + void JIT::dsrlv(u32 instr) { + if (regs.IsRegConstant(RT(instr), RS(instr))) { u8 amount = regs.Read(RS(instr)) & 63; auto rt = regs.Read(RT(instr)); u64 result = rt >> amount; - regs.Write(RD(instr), s64(result)); - regs.gprIsConstant[RD(instr)] = true; + regs.Write(RD(instr), s64(result)); + } else { + Util::panic("[JIT]: Implement non constant DSRLV!"); } - } else { - Util::panic("[JIT]: Implement non constant DSRLV!"); } -} -void JIT::dsrl32(u32 instr) { - if(regs.IsRegConstant(RT(instr))) { - if (RD(instr) != 0) [[likely]] { + void JIT::dsrl32(u32 instr) { + if (regs.IsRegConstant(RT(instr))) { auto rt = regs.Read(RT(instr)); u8 sa = ((instr >> 6) & 0x1f); u64 result = rt >> (sa + 32); - regs.Write(RD(instr), s64(result)); - regs.gprIsConstant[RD(instr)] = true; - } - } else { - Util::panic("[JIT]: Implement non constant DSRL32!"); - } -} - -void JIT::dsub(u32 instr) { - if(regs.IsRegConstant(RT(instr), RS(instr))) { - auto rt = regs.Read(RT(instr)); - auto rs = regs.Read(RS(instr)); - s64 result = rs - rt; - if (check_signed_underflow(rs, rt, result)) { - // regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC); - Util::panic("[JIT]: Unhandled Overflow exception in DSUB!"); + regs.Write(RD(instr), s64(result)); } else { - if (RD(instr) != 0) [[likely]] { + Util::panic("[JIT]: Implement non constant DSRL32!"); + } + } + + void JIT::dsub(u32 instr) { + if (regs.IsRegConstant(RT(instr), RS(instr))) { + auto rt = regs.Read(RT(instr)); + auto rs = regs.Read(RS(instr)); + s64 result = rs - rt; + if (check_signed_underflow(rs, rt, result)) { + // regs.cop0.FireException(ExceptionCode::Overflow, 0, regs.oldPC); + Util::panic("[JIT]: Unhandled Overflow exception in DSUB!"); + } else { regs.Write(RD(instr), result); - regs.gprIsConstant[RD(instr)] = true; } + } else { + Util::panic("[JIT]: Implement non constant DSUB!"); } - } else { - Util::panic("[JIT]: Implement non constant DSUB!"); } -} -void JIT::dsubu(u32 instr) { - if(regs.IsRegConstant(RT(instr), RS(instr))) { - auto rt = regs.Read(RT(instr)); - auto rs = regs.Read(RS(instr)); - s64 result = rs - rt; - - if (RD(instr) != 0) [[likely]] { + void JIT::dsubu(u32 instr) { + if (regs.IsRegConstant(RT(instr), RS(instr))) { + auto rt = regs.Read(RT(instr)); + auto rs = regs.Read(RS(instr)); + s64 result = rs - rt; regs.Write(RD(instr), result); - regs.gprIsConstant[RD(instr)] = true; + } else { + Util::panic("[JIT]: Implement non constant DSUBU!"); } - } else { - Util::panic("[JIT]: Implement non constant DSUBU!"); } -} -void JIT::mfhi(u32 instr) { - if(regs.hiIsConstant) { - regs.Write(RD(instr), regs.hi); - regs.gprIsConstant[RD(instr)] = true; - } else { - Util::panic("[JIT]: Implement non constant MFHI!"); + void JIT::mfhi(u32 instr) { + if (regs.hiIsConstant) { + regs.Write(RD(instr), regs.hi); + } else { + Util::panic("[JIT]: Implement non constant MFHI!"); + } } -} -void JIT::mflo(u32 instr) { - if(regs.loIsConstant) { - regs.Write(RD(instr), regs.lo); - regs.gprIsConstant[RD(instr)] = true; - } else { - Util::panic("[JIT]: Implement non constant MFLO!"); + void JIT::mflo(u32 instr) { + if (regs.loIsConstant) { + regs.Write(RD(instr), regs.lo); + } else { + Util::panic("[JIT]: Implement non constant MFLO!"); + } } -} -void JIT::mult(u32 instr) { - if(regs.IsRegConstant(RT(instr), RS(instr))) { - auto rt = regs.Read(RT(instr)); - auto rs = regs.Read(RS(instr)); - s64 result = (s64) rt * (s64) rs; - regs.lo = (s64) ((s32) result); - regs.loIsConstant = true; - regs.hi = (s64) ((s32) (result >> 32)); - regs.hiIsConstant = true; - } else { - Util::panic("[JIT]: Implement non constant MULT!"); + void JIT::mult(u32 instr) { + if (regs.IsRegConstant(RT(instr), RS(instr))) { + auto rt = regs.Read(RT(instr)); + auto rs = regs.Read(RS(instr)); + s64 result = (s64)rt * (s64)rs; + regs.lo = (s64)((s32)result); + regs.loIsConstant = true; + regs.hi = (s64)((s32)(result >> 32)); + regs.hiIsConstant = true; + } else { + Util::panic("[JIT]: Implement non constant MULT!"); + } } -} -void JIT::multu(u32 instr) { - if(regs.IsRegConstant(RT(instr), RS(instr))) { - auto rt = regs.Read(RT(instr)); - auto rs = regs.Read(RS(instr)); - u64 result = (u64)rt * (u64)rs; - regs.lo = (s64)((s32)result); - regs.loIsConstant = true; - regs.hi = (s64)((s32)(result >> 32)); - regs.hiIsConstant = true; - } else { - Util::panic("[JIT]: Implement non constant MULTU!"); + void JIT::multu(u32 instr) { + if (regs.IsRegConstant(RT(instr), RS(instr))) { + auto rt = regs.Read(RT(instr)); + auto rs = regs.Read(RS(instr)); + u64 result = (u64)rt * (u64)rs; + regs.lo = (s64)((s32)result); + regs.loIsConstant = true; + regs.hi = (s64)((s32)(result >> 32)); + regs.hiIsConstant = true; + } else { + Util::panic("[JIT]: Implement non constant MULTU!"); + } } -} -void JIT::mthi(u32 instr) { - if(regs.IsRegConstant(RS(instr))) { - regs.hi = regs.Read(RS(instr)); - regs.hiIsConstant = true; - } else { - Util::panic("[JIT]: Implement non constant MTHI!"); + void JIT::mthi(u32 instr) { + if (regs.IsRegConstant(RS(instr))) { + regs.hi = regs.Read(RS(instr)); + regs.hiIsConstant = true; + } else { + Util::panic("[JIT]: Implement non constant MTHI!"); + } } -} -void JIT::mtlo(u32 instr) { - if(regs.IsRegConstant(RS(instr))) { - regs.lo = regs.Read(RS(instr)); - regs.loIsConstant = true; - } else { - Util::panic("[JIT]: Implement non constant MTLO!"); + void JIT::mtlo(u32 instr) { + if (regs.IsRegConstant(RS(instr))) { + regs.lo = regs.Read(RS(instr)); + regs.loIsConstant = true; + } else { + Util::panic("[JIT]: Implement non constant MTLO!"); + } } -} -void JIT::nor(u32 instr) { - if(regs.IsRegConstant(RS(instr), RT(instr))) { - if (RD(instr) != 0) [[likely]] { + void JIT::nor(u32 instr) { + if (regs.IsRegConstant(RS(instr), RT(instr))) { regs.Write(RD(instr), ~(regs.Read(RS(instr)) | regs.Read(RT(instr)))); - regs.gprIsConstant[RD(instr)] = true; + } else { + Util::panic("[JIT]: Implement non constant NOR!"); } - } else { - Util::panic("[JIT]: Implement non constant NOR!"); } -} -void JIT::slti(u32 instr) { - if(regs.IsRegConstant(RS(instr))) { - s16 imm = instr; - if (RT(instr) != 0) [[likely]] { + void JIT::slti(u32 instr) { + if (regs.IsRegConstant(RS(instr))) { + s16 imm = instr; regs.Write(RT(instr), regs.Read(RS(instr)) < imm); - regs.gprIsConstant[RT(instr)] = true; + } else { + Util::panic("[JIT]: Implement non constant SLTI!"); } - } else { - Util::panic("[JIT]: Implement non constant SLTI!"); } -} -void JIT::sltiu(u32 instr) { - if(regs.IsRegConstant(RS(instr))) { - s16 imm = instr; - if (RT(instr) != 0) [[likely]] { + void JIT::sltiu(u32 instr) { + if (regs.IsRegConstant(RS(instr))) { + s16 imm = instr; regs.Write(RT(instr), regs.Read(RS(instr)) < imm); - regs.gprIsConstant[RT(instr)] = true; + } else { + Util::panic("[JIT]: Implement non constant SLTIU!"); } - } else { - Util::panic("[JIT]: Implement non constant SLTIU!"); } -} -void JIT::slt(u32 instr) { - if(regs.IsRegConstant(RS(instr), RT(instr))) { - if (RD(instr) != 0) [[likely]] { + void JIT::slt(u32 instr) { + if (regs.IsRegConstant(RS(instr), RT(instr))) { regs.Write(RD(instr), regs.Read(RS(instr)) < regs.Read(RT(instr))); - regs.gprIsConstant[RD(instr)] = true; + } else { + Util::panic("[JIT]: Implement non constant SLT!"); } - } else { - Util::panic("[JIT]: Implement non constant SLT!"); } -} -void JIT::sltu(u32 instr) { - if(regs.IsRegConstant(RS(instr), RT(instr))) { - if (RD(instr) != 0) [[likely]] { + void JIT::sltu(u32 instr) { + if (regs.IsRegConstant(RS(instr), RT(instr))) { regs.Write(RD(instr), regs.Read(RS(instr)) < regs.Read(RT(instr))); - regs.gprIsConstant[RD(instr)] = true; + } else { + Util::panic("[JIT]: Implement non constant SLT!"); } - } else { - Util::panic("[JIT]: Implement non constant SLT!"); + } + + void JIT::sll(u32 instr) { + if (regs.IsRegConstant(RT(instr))) { + u8 sa = ((instr >> 6) & 0x1f); + s32 result = regs.Read(RT(instr)) << sa; + regs.Write(RD(instr), (s64)result); + } else { + Util::panic("[JIT]: Implement non constant SLL!"); + } + } + + void JIT::sllv(u32 instr) { + if (regs.IsRegConstant(RS(instr), RT(instr))) { + u8 sa = (regs.Read(RS(instr))) & 0x1F; + u32 rt = regs.Read(RT(instr)); + s32 result = rt << sa; + regs.Write(RD(instr), (s64)result); + } + } + + void JIT::sub(u32) { + + } + + void JIT::subu(u32) { + + } + + void JIT::sra(u32) { + + } + + void JIT::srav(u32) { + + } + + void JIT::srl(u32) { + + } + + void JIT::srlv(u32) { + + } + + void JIT::or_(u32) { + + } + + void JIT::ori(u32) { + + } + + void JIT::xor_(u32) { + + } + + void JIT::xori(u32) { + } } - -void JIT::sll(u32) { - -} - -void JIT::sllv(u32) { - -} - -void JIT::sub(u32) { - -} - -void JIT::subu(u32) { - -} - -void JIT::sra(u32) { - -} - -void JIT::srav(u32) { - -} - -void JIT::srl(u32) { - -} - -void JIT::srlv(u32) { - -} - -void JIT::or_(u32) { - -} - -void JIT::ori(u32) { - -} - -void JIT::xor_(u32) { - -} - -void JIT::xori(u32) { - -} -} \ No newline at end of file diff --git a/src/backend/core/registers/Registers.cpp b/src/backend/core/registers/Registers.cpp index ea168393..cc7fcc85 100644 --- a/src/backend/core/registers/Registers.cpp +++ b/src/backend/core/registers/Registers.cpp @@ -1,16 +1,15 @@ #include namespace n64 { -Registers::Registers() : cop0(*this), cop1(*this) { - Reset(); -} +Registers::Registers() : cop0(*this), cop1(*this) { Reset(); } void Registers::Reset() { hi = 0; lo = 0; delaySlot = false; prevDelaySlot = false; - memset(gpr, 0, 32*sizeof(s64)); + gpr.fill(0); + gprIsConstant.fill(false); cop0.Reset(); cop1.Reset(); @@ -31,79 +30,112 @@ void Registers::SetPC32(s32 val) { nextPC = pc + 4; } -template <> u64 Registers::Read(size_t idx) { +template <> +u64 Registers::Read(size_t idx) { return idx == 0 ? 0 : gpr[idx]; } -template <> s64 Registers::Read(size_t idx) { +template <> +s64 Registers::Read(size_t idx) { return s64(Read(idx)); } -template <> u32 Registers::Read(size_t idx) { +template <> +u32 Registers::Read(size_t idx) { return idx == 0 ? 0 : gpr[idx]; } -template <> s32 Registers::Read(size_t idx) { +template <> +s32 Registers::Read(size_t idx) { return s32(Read(idx)); } -template <> u16 Registers::Read(size_t idx) { +template <> +u16 Registers::Read(size_t idx) { return idx == 0 ? 0 : gpr[idx]; } -template <> s16 Registers::Read(size_t idx) { +template <> +s16 Registers::Read(size_t idx) { return s16(Read(idx)); } -template <> u8 Registers::Read(size_t idx) { +template <> +u8 Registers::Read(size_t idx) { return idx == 0 ? 0 : gpr[idx]; } -template <> s8 Registers::Read(size_t idx) { +template <> +s8 Registers::Read(size_t idx) { return s8(Read(idx)); } -template <> void Registers::Write(size_t idx, bool v) { - if(idx == 0) return; +template <> +void Registers::Write(size_t idx, bool v) { + if (idx == 0) + return; gpr[idx] = v; + gprIsConstant[idx] = true; } -template <> void Registers::Write(size_t idx, u64 v) { - if(idx == 0) return; +template <> +void Registers::Write(size_t idx, u64 v) { + if (idx == 0) + return; gpr[idx] = v; + gprIsConstant[idx] = true; } -template <> void Registers::Write(size_t idx, s64 v) { +template <> +void Registers::Write(size_t idx, s64 v) { Write(idx, v); } -template <> void Registers::Write(size_t idx, u32 v) { - if(idx == 0) return; +template <> +void Registers::Write(size_t idx, u32 v) { + if (idx == 0) + return; gpr[idx] = (u32)v; + gprIsConstant[idx] = true; } -template <> void Registers::Write(size_t idx, s32 v) { - if(idx == 0) return; +template <> +void Registers::Write(size_t idx, s32 v) { + if (idx == 0) + return; gpr[idx] = v; + gprIsConstant[idx] = true; } -template <> void Registers::Write(size_t idx, u16 v) { - if(idx == 0) return; +template <> +void Registers::Write(size_t idx, u16 v) { + if (idx == 0) + return; gpr[idx] = (u16)v; + gprIsConstant[idx] = true; } -template <> void Registers::Write(size_t idx, s16 v) { - if(idx == 0) return; +template <> +void Registers::Write(size_t idx, s16 v) { + if (idx == 0) + return; gpr[idx] = v; + gprIsConstant[idx] = true; } -template <> void Registers::Write(size_t idx, u8 v) { - if(idx == 0) return; +template <> +void Registers::Write(size_t idx, u8 v) { + if (idx == 0) + return; gpr[idx] = (u8)v; + gprIsConstant[idx] = true; } -template <> void Registers::Write(size_t idx, s8 v) { - if(idx == 0) return; +template <> +void Registers::Write(size_t idx, s8 v) { + if (idx == 0) + return; gpr[idx] = v; + gprIsConstant[idx] = true; } -} +} // namespace n64 diff --git a/src/backend/core/registers/Registers.hpp b/src/backend/core/registers/Registers.hpp index c15701a9..c3b9572f 100644 --- a/src/backend/core/registers/Registers.hpp +++ b/src/backend/core/registers/Registers.hpp @@ -1,4 +1,5 @@ #pragma once +#include #include namespace n64 { @@ -9,15 +10,14 @@ struct Registers { void SetPC32(s32); bool IsRegConstant(u32 index) { - if(index == 0) return true; + if (index == 0) + return true; return gprIsConstant[index]; } - bool IsRegConstant(u32 first, u32 second) { - return IsRegConstant(first) && IsRegConstant(second); - } + bool IsRegConstant(u32 first, u32 second) { return IsRegConstant(first) && IsRegConstant(second); } - bool gprIsConstant[32]{}; + std::array gprIsConstant{}; bool loIsConstant = false, hiIsConstant = false; Cop0 cop0; Cop1 cop1; @@ -27,9 +27,7 @@ struct Registers { u32 steps = 0; u32 extraCycles = 0; - void CpuStall(u32 cycles) { - extraCycles += cycles; - } + void CpuStall(u32 cycles) { extraCycles += cycles; } u32 PopStalledCycles() { u32 ret = extraCycles; @@ -41,7 +39,8 @@ struct Registers { T Read(size_t); template void Write(size_t, T); + private: - s64 gpr[32]{}; + std::array gpr{}; }; -} +} // namespace n64 diff --git a/src/frontend/KaizenQt.cpp b/src/frontend/KaizenQt.cpp index 332fac16..f18e9064 100644 --- a/src/frontend/KaizenQt.cpp +++ b/src/frontend/KaizenQt.cpp @@ -7,14 +7,15 @@ namespace fs = std::filesystem; -KaizenQt::KaizenQt() noexcept : QWidget(nullptr) { +KaizenQt::KaizenQt() noexcept : + QWidget(nullptr) { mainWindow = std::make_unique(); settingsWindow = std::make_unique(); emuThread = std::make_unique( - std::move(mainWindow->view.vulkanWidget->instance), - std::move(mainWindow->view.vulkanWidget->wsiPlatform), - std::move(mainWindow->view.vulkanWidget->windowInfo), - *settingsWindow); + std::move(mainWindow->view.vulkanWidget->instance), + std::move(mainWindow->view.vulkanWidget->wsiPlatform), + std::move(mainWindow->view.vulkanWidget->windowInfo), + *settingsWindow); ConnectMainWindowSignalsToSlots(); @@ -43,18 +44,18 @@ void KaizenQt::ConnectMainWindowSignalsToSlots() noexcept { connect(mainWindow.get(), &MainWindowController::Pause, emuThread.get(), &EmuThread::TogglePause); } -void KaizenQt::dragEnterEvent(QDragEnterEvent* event) { +void KaizenQt::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasUrls()) { event->acceptProposedAction(); } } -void KaizenQt::dropEvent(QDropEvent* event) { +void KaizenQt::dropEvent(QDropEvent *event) { auto path = event->mimeData()->urls()[0].toLocalFile(); LoadROM(path); } -void KaizenQt::LoadROM(const QString& fileName) noexcept { +void KaizenQt::LoadROM(const QString &fileName) noexcept { mainWindow->view.actionPause->setEnabled(true); mainWindow->view.actionReset->setEnabled(true); mainWindow->view.actionStop->setEnabled(true); @@ -64,25 +65,25 @@ void KaizenQt::LoadROM(const QString& fileName) noexcept { } void KaizenQt::Quit() noexcept { - if(emuThread) { + if (emuThread) { emuThread->SetRender(false); emuThread->Stop(); } QApplication::quit(); } -void KaizenQt::LoadTAS(const QString& fileName) const noexcept { +void KaizenQt::LoadTAS(const QString &fileName) const noexcept { emuThread->core.LoadTAS(fs::path(fileName.toStdString())); } void KaizenQt::keyPressEvent(QKeyEvent *e) { emuThread->core.pause = true; - n64::Mem& mem = emuThread->core.cpu->GetMem(); - n64::PIF& pif = mem.mmio.si.pif; + n64::Mem &mem = emuThread->core.cpu->GetMem(); + n64::PIF &pif = mem.mmio.si.pif; auto k = static_cast(e->key()); - for(int i = 0; i < 14; i++) { - if(k == settingsWindow->keyMap[i]) + for (int i = 0; i < 14; i++) { + if (k == settingsWindow->keyMap[i]) pif.UpdateButton(0, static_cast(i), true); } @@ -101,12 +102,12 @@ void KaizenQt::keyPressEvent(QKeyEvent *e) { void KaizenQt::keyReleaseEvent(QKeyEvent *e) { emuThread->core.pause = true; - n64::Mem& mem = emuThread->core.cpu->GetMem(); - n64::PIF& pif = mem.mmio.si.pif; + n64::Mem &mem = emuThread->core.cpu->GetMem(); + n64::PIF &pif = mem.mmio.si.pif; auto k = static_cast(e->key()); - for(int i = 0; i < 14; i++) { - if(k == settingsWindow->keyMap[i]) + for (int i = 0; i < 14; i++) { + if (k == settingsWindow->keyMap[i]) pif.UpdateButton(0, static_cast(i), false); } @@ -121,4 +122,4 @@ void KaizenQt::keyReleaseEvent(QKeyEvent *e) { emuThread->core.pause = false; QWidget::keyReleaseEvent(e); -} \ No newline at end of file +}