From 0049ef3a2a879d785872b02c87ef8fc740974a63 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 12 Jun 2018 13:22:49 -0400 Subject: [PATCH] Gekko: Centralize bitmasking of the FPSCR within UReg_FPSCR Rather than introduce this handling in every system instruction that modifies the FPSCR directly, we can instead just handle it within the data structure instead, which avoids duplicating mask handling across instructions. This also allows handling proper masking from the debugger register windows themselves without duplicating masking behavior there either. --- Source/Core/Core/PowerPC/Gekko.h | 31 +++++++++++++++++- .../Interpreter_SystemRegisters.cpp | 32 ++++++------------- .../DolphinQt2/Debugger/RegisterWidget.cpp | 2 +- .../Core/DolphinWX/Debugger/RegisterView.cpp | 2 +- 4 files changed, 41 insertions(+), 26 deletions(-) diff --git a/Source/Core/Core/PowerPC/Gekko.h b/Source/Core/Core/PowerPC/Gekko.h index a47f26f08f..fda28b1fbc 100644 --- a/Source/Core/Core/PowerPC/Gekko.h +++ b/Source/Core/Core/PowerPC/Gekko.h @@ -474,8 +474,37 @@ union UReg_FPSCR }; u32 Hex = 0; + // The FPSCR's 20th bit (11th from a little endian perspective) + // is defined as reserved and set to zero. Attempts to modify it + // are ignored by hardware, so we do the same. + static constexpr u32 mask = 0xFFFFF7FF; + UReg_FPSCR() = default; - explicit UReg_FPSCR(u32 hex_) : Hex{hex_} {} + explicit UReg_FPSCR(u32 hex_) : Hex{hex_ & mask} {} + + UReg_FPSCR& operator=(u32 value) + { + Hex = value & mask; + return *this; + } + + UReg_FPSCR& operator|=(u32 value) + { + Hex |= value & mask; + return *this; + } + + UReg_FPSCR& operator&=(u32 value) + { + Hex &= value; + return *this; + } + + UReg_FPSCR& operator^=(u32 value) + { + Hex ^= value & mask; + return *this; + } void ClearFIFR() { diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp index 5772b3c732..57942be5e8 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp @@ -62,20 +62,14 @@ void Interpreter::mtfsb0x(UGeckoInstruction inst) void Interpreter::mtfsb1x(UGeckoInstruction inst) { const u32 bit = inst.CRBD; + const u32 b = 0x80000000 >> bit; - // Bit 20 in the FPSCR is reserved and defined as zero, - // so we ensure that we don't set it. - if (bit != 20) - { - const u32 b = 0x80000000 >> bit; + if (b & FPSCR_ANY_X) + SetFPException(b); + else + FPSCR |= b; - if (b & FPSCR_ANY_X) - SetFPException(b); - else - FPSCR.Hex |= b; - - FPSCRtoFPUSettings(FPSCR); - } + FPSCRtoFPUSettings(FPSCR); if (inst.Rc) Helper_UpdateCR1(); @@ -83,14 +77,12 @@ void Interpreter::mtfsb1x(UGeckoInstruction inst) void Interpreter::mtfsfix(UGeckoInstruction inst) { - // Bit 20 of the FPSCR is reserved and defined as zero on hardware, - // so ensure that we don't set it. const u32 field = inst.CRFD; - const u32 pre_shifted_mask = field == 4 ? 0x70000000 : 0xF0000000; + const u32 pre_shifted_mask = 0xF0000000; const u32 mask = (pre_shifted_mask >> (4 * field)); const u32 imm = (inst.hex << 16) & pre_shifted_mask; - FPSCR.Hex = (FPSCR.Hex & ~mask) | (imm >> (4 * field)); + FPSCR = (FPSCR.Hex & ~mask) | (imm >> (4 * field)); FPSCRtoFPUSettings(FPSCR); @@ -108,13 +100,7 @@ void Interpreter::mtfsfx(UGeckoInstruction inst) m |= (0xFU << (i * 4)); } - // Bit 20 of the FPSCR is defined as always being zero - // (bit 11 in a little endian context), so ensure that - // we don't actually set that bit. - if ((fm & 0b100) != 0) - m &= 0xFFFFF7FF; - - FPSCR.Hex = (FPSCR.Hex & ~m) | (static_cast(riPS0(inst.FB)) & m); + FPSCR = (FPSCR.Hex & ~m) | (static_cast(riPS0(inst.FB)) & m); FPSCRtoFPUSettings(FPSCR); if (inst.Rc) diff --git a/Source/Core/DolphinQt2/Debugger/RegisterWidget.cpp b/Source/Core/DolphinQt2/Debugger/RegisterWidget.cpp index 98db9f671f..2a2fff7aa2 100644 --- a/Source/Core/DolphinQt2/Debugger/RegisterWidget.cpp +++ b/Source/Core/DolphinQt2/Debugger/RegisterWidget.cpp @@ -290,7 +290,7 @@ void RegisterWidget::PopulateTable() // FPSCR AddRegister(22, 5, RegisterType::fpscr, "FPSCR", [] { return PowerPC::ppcState.fpscr.Hex; }, - [](u64 value) { PowerPC::ppcState.fpscr.Hex = value; }); + [](u64 value) { PowerPC::ppcState.fpscr = static_cast(value); }); // MSR AddRegister(23, 5, RegisterType::msr, "MSR", [] { return PowerPC::ppcState.msr.Hex; }, diff --git a/Source/Core/DolphinWX/Debugger/RegisterView.cpp b/Source/Core/DolphinWX/Debugger/RegisterView.cpp index 6d62ca6b5e..0e392d829d 100644 --- a/Source/Core/DolphinWX/Debugger/RegisterView.cpp +++ b/Source/Core/DolphinWX/Debugger/RegisterView.cpp @@ -124,7 +124,7 @@ void SetSpecialRegValue(int reg, u32 value) PowerPC::SetXER(UReg_XER(value)); break; case 5: - PowerPC::ppcState.fpscr.Hex = value; + PowerPC::ppcState.fpscr = value; break; case 6: PowerPC::ppcState.msr.Hex = value;