diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 433aeb9d15..4468f7c57d 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -215,6 +215,7 @@ add_library(core PowerPC/JitInterface.cpp PowerPC/CachedInterpreter/CachedInterpreter.cpp PowerPC/CachedInterpreter/InterpreterBlockCache.cpp + PowerPC/ConditionRegister.cpp PowerPC/Interpreter/Interpreter_Branch.cpp PowerPC/Interpreter/Interpreter.cpp PowerPC/Interpreter/Interpreter_FloatingPoint.cpp diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index bff81652df..8a6b08adfc 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -257,6 +257,7 @@ + @@ -520,6 +521,7 @@ + diff --git a/Source/Core/Core/GeckoCode.cpp b/Source/Core/Core/GeckoCode.cpp index ae3d0f66f5..35f4f11f84 100644 --- a/Source/Core/Core/GeckoCode.cpp +++ b/Source/Core/Core/GeckoCode.cpp @@ -268,7 +268,7 @@ void RunCodeHandler() PowerPC::HostWrite_U32(SFP, SP + 8); // Real stack frame PowerPC::HostWrite_U32(PC, SP + 12); PowerPC::HostWrite_U32(LR, SP + 16); - PowerPC::HostWrite_U32(PowerPC::CompactCR(), SP + 20); + PowerPC::HostWrite_U32(PowerPC::ppcState.cr.Get(), SP + 20); // Registers FPR0->13 are volatile for (int i = 0; i < 14; ++i) { diff --git a/Source/Core/Core/HLE/HLE_Misc.cpp b/Source/Core/Core/HLE/HLE_Misc.cpp index 27cb3012a7..5893c3f4a8 100644 --- a/Source/Core/Core/HLE/HLE_Misc.cpp +++ b/Source/Core/Core/HLE/HLE_Misc.cpp @@ -61,7 +61,7 @@ void GeckoReturnTrampoline() GPR(1) = PowerPC::HostRead_U32(SP + 8); NPC = PowerPC::HostRead_U32(SP + 12); LR = PowerPC::HostRead_U32(SP + 16); - PowerPC::ExpandCR(PowerPC::HostRead_U32(SP + 20)); + PowerPC::ppcState.cr.Set(PowerPC::HostRead_U32(SP + 20)); for (int i = 0; i < 14; ++i) { rPS(i).SetBoth(PowerPC::HostRead_U64(SP + 24 + 2 * i * sizeof(u64)), diff --git a/Source/Core/Core/HLE/HLE_VarArgs.cpp b/Source/Core/Core/HLE/HLE_VarArgs.cpp index e7e6a9099e..d96e5bebdd 100644 --- a/Source/Core/Core/HLE/HLE_VarArgs.cpp +++ b/Source/Core/Core/HLE/HLE_VarArgs.cpp @@ -21,7 +21,7 @@ double HLE::SystemVABI::VAList::GetFPR(u32 fpr) const HLE::SystemVABI::VAListStruct::VAListStruct(u32 address) : VAList(0), m_va_list{PowerPC::HostRead_U8(address), PowerPC::HostRead_U8(address + 1), PowerPC::HostRead_U32(address + 4), PowerPC::HostRead_U32(address + 8)}, - m_address(address), m_has_fpr_area(PowerPC::GetCRBit(6) == 1) + m_address(address), m_has_fpr_area(PowerPC::ppcState.cr.GetBit(6) == 1) { m_stack = m_va_list.overflow_arg_area; m_gpr += m_va_list.gpr; diff --git a/Source/Core/Core/PowerPC/ConditionRegister.cpp b/Source/Core/Core/PowerPC/ConditionRegister.cpp new file mode 100644 index 0000000000..f024f12a02 --- /dev/null +++ b/Source/Core/Core/PowerPC/ConditionRegister.cpp @@ -0,0 +1,46 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Core/PowerPC/ConditionRegister.h" + +namespace PowerPC +{ +const std::array ConditionRegister::s_crTable = {{ + ConditionRegister::PPCToInternal(0x0), + ConditionRegister::PPCToInternal(0x1), + ConditionRegister::PPCToInternal(0x2), + ConditionRegister::PPCToInternal(0x3), + ConditionRegister::PPCToInternal(0x4), + ConditionRegister::PPCToInternal(0x5), + ConditionRegister::PPCToInternal(0x6), + ConditionRegister::PPCToInternal(0x7), + ConditionRegister::PPCToInternal(0x8), + ConditionRegister::PPCToInternal(0x9), + ConditionRegister::PPCToInternal(0xA), + ConditionRegister::PPCToInternal(0xB), + ConditionRegister::PPCToInternal(0xC), + ConditionRegister::PPCToInternal(0xD), + ConditionRegister::PPCToInternal(0xE), + ConditionRegister::PPCToInternal(0xF), +}}; + +u32 ConditionRegister::Get() const +{ + u32 new_cr = 0; + for (u32 i = 0; i < 8; i++) + { + new_cr |= GetField(i) << (28 - i * 4); + } + return new_cr; +} + +void ConditionRegister::Set(u32 cr) +{ + for (u32 i = 0; i < 8; i++) + { + SetField(i, (cr >> (28 - i * 4)) & 0xF); + } +} + +} // namespace PowerPC diff --git a/Source/Core/Core/PowerPC/ConditionRegister.h b/Source/Core/Core/PowerPC/ConditionRegister.h new file mode 100644 index 0000000000..f1897e9086 --- /dev/null +++ b/Source/Core/Core/PowerPC/ConditionRegister.h @@ -0,0 +1,93 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include "Common/CommonTypes.h" + +namespace PowerPC +{ +enum CRBits +{ + CR_SO = 1, + CR_EQ = 2, + CR_GT = 4, + CR_LT = 8, + + CR_SO_BIT = 0, + CR_EQ_BIT = 1, + CR_GT_BIT = 2, + CR_LT_BIT = 3, +}; + +// Optimized CR implementation. Instead of storing CR in its PowerPC format +// (4 bit value, SO/EQ/LT/GT), we store instead a 64 bit value for each of +// the 8 CR register parts. This 64 bit value follows this format: +// - SO iff. bit 61 is set +// - EQ iff. lower 32 bits == 0 +// - GT iff. (s64)cr_val > 0 +// - LT iff. bit 62 is set +// +// This has the interesting property that sign-extending the result of an +// operation from 32 to 64 bits results in a 64 bit value that works as a +// CR value. Checking each part of CR is also fast, as it is equivalent to +// testing one bit or the low 32 bit part of a register. And CR can still +// be manipulated bit by bit fairly easily. +struct ConditionRegister +{ + // convert flags into 64-bit CR values with a lookup table + static const std::array s_crTable; + + u64 fields[8]; + + // Convert between PPC and internal representation of CR. + static u64 PPCToInternal(u8 value) + { + u64 cr_val = 0x100000000; + cr_val |= (u64) !!(value & CR_SO) << 61; + cr_val |= (u64) !(value & CR_EQ); + cr_val |= (u64) !(value & CR_GT) << 63; + cr_val |= (u64) !!(value & CR_LT) << 62; + + return cr_val; + } + + // Warning: these CR operations are fairly slow since they need to convert from + // PowerPC format (4 bit) to our internal 64 bit format. + void SetField(u32 cr_field, u32 value) { fields[cr_field] = s_crTable[value]; } + + u32 GetField(u32 cr_field) const + { + const u64 cr_val = fields[cr_field]; + u32 ppc_cr = 0; + + // SO + ppc_cr |= !!(cr_val & (1ull << 61)); + // EQ + ppc_cr |= ((cr_val & 0xFFFFFFFF) == 0) << 1; + // GT + ppc_cr |= (static_cast(cr_val) > 0) << 2; + // LT + ppc_cr |= !!(cr_val & (1ull << 62)) << 3; + + return ppc_cr; + } + + u32 GetBit(u32 bit) const { return (GetField(bit >> 2) >> (3 - (bit & 3))) & 1; } + + void SetBit(u32 bit, u32 value) + { + if (value & 1) + SetField(bit >> 2, GetField(bit >> 2) | (0x8 >> (bit & 3))); + else + SetField(bit >> 2, GetField(bit >> 2) & ~(0x8 >> (bit & 3))); + } + + // Set and Get are fairly slow. Should be avoided if possible. + void Set(u32 new_cr); + u32 Get() const; +}; + +} // namespace PowerPC diff --git a/Source/Core/Core/PowerPC/GDBStub.cpp b/Source/Core/Core/PowerPC/GDBStub.cpp index af203cb63d..10d5fd91fd 100644 --- a/Source/Core/Core/PowerPC/GDBStub.cpp +++ b/Source/Core/Core/PowerPC/GDBStub.cpp @@ -449,7 +449,7 @@ static void gdb_read_register() wbe32hex(reply, MSR.Hex); break; case 66: - wbe32hex(reply, PowerPC::GetCR()); + wbe32hex(reply, PowerPC::ppcState.cr.Get()); break; case 67: wbe32hex(reply, LR); @@ -534,7 +534,7 @@ static void gdb_write_register() MSR.Hex = re32hex(bufptr); break; case 66: - PowerPC::SetCR(re32hex(bufptr)); + PowerPC::ppcState.cr.Set(re32hex(bufptr)); break; case 67: LR = re32hex(bufptr); diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp index 945588b51e..14602f7b00 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp @@ -135,7 +135,7 @@ static void Trace(UGeckoInstruction& inst) DEBUG_LOG(POWERPC, "INTER PC: %08x SRR0: %08x SRR1: %08x CRval: %016" PRIx64 " FPSCR: %08x MSR: %08x LR: " "%08x %s %08x %s", - PC, SRR0, SRR1, PowerPC::ppcState.cr_val[0], FPSCR.Hex, MSR.Hex, + PC, SRR0, SRR1, PowerPC::ppcState.cr.fields[0], FPSCR.Hex, MSR.Hex, PowerPC::ppcState.spr[8], regs.c_str(), inst.hex, ppc_inst.c_str()); } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp index 0d07309cd7..a1920b3eef 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp @@ -41,7 +41,8 @@ void Interpreter::bcx(UGeckoInstruction inst) const bool only_condition_check = ((inst.BO >> 2) & 1); const u32 ctr_check = ((CTR != 0) ^ (inst.BO >> 1)) & 1; const bool counter = only_condition_check || ctr_check; - const bool condition = only_counter_check || (PowerPC::GetCRBit(inst.BI) == u32(true_false)); + const bool condition = + only_counter_check || (PowerPC::ppcState.cr.GetBit(inst.BI) == u32(true_false)); if (counter && condition) { @@ -81,7 +82,7 @@ void Interpreter::bcctrx(UGeckoInstruction inst) "bcctrx with decrement and test CTR option is invalid!"); const u32 condition = - ((inst.BO_2 >> 4) | (PowerPC::GetCRBit(inst.BI_2) == ((inst.BO_2 >> 3) & 1))) & 1; + ((inst.BO_2 >> 4) | (PowerPC::ppcState.cr.GetBit(inst.BI_2) == ((inst.BO_2 >> 3) & 1))) & 1; if (condition) { @@ -100,7 +101,7 @@ void Interpreter::bclrx(UGeckoInstruction inst) const u32 counter = ((inst.BO_2 >> 2) | ((CTR != 0) ^ (inst.BO_2 >> 1))) & 1; const u32 condition = - ((inst.BO_2 >> 4) | (PowerPC::GetCRBit(inst.BI_2) == ((inst.BO_2 >> 3) & 1))) & 1; + ((inst.BO_2 >> 4) | (PowerPC::ppcState.cr.GetBit(inst.BI_2) == ((inst.BO_2 >> 3) & 1))) & 1; if (counter & condition) { diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index 296b85959c..3254ce1a64 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -54,7 +54,7 @@ inline void UpdateFPSCR() inline void Helper_UpdateCR1() { - PowerPC::SetCRField(1, (FPSCR.FX << 3) | (FPSCR.FEX << 2) | (FPSCR.VX << 1) | FPSCR.OX); + PowerPC::ppcState.cr.SetField(1, (FPSCR.FX << 3) | (FPSCR.FEX << 2) | (FPSCR.VX << 1) | FPSCR.OX); } inline double ForceSingle(double value) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp index e39c39e1fa..7a3e8b6aa4 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -161,7 +161,7 @@ void Interpreter::Helper_FloatCompareOrdered(UGeckoInstruction inst, double fa, // Clear and set the FPCC bits accordingly. FPSCR.FPRF = (FPSCR.FPRF & ~0xF) | compare_value; - PowerPC::SetCRField(inst.CRFD, compare_value); + PowerPC::ppcState.cr.SetField(inst.CRFD, compare_value); } void Interpreter::Helper_FloatCompareUnordered(UGeckoInstruction inst, double fa, double fb) @@ -195,7 +195,7 @@ void Interpreter::Helper_FloatCompareUnordered(UGeckoInstruction inst, double fa // Clear and set the FPCC bits accordingly. FPSCR.FPRF = (FPSCR.FPRF & ~0xF) | compare_value; - PowerPC::SetCRField(inst.CRFD, compare_value); + PowerPC::ppcState.cr.SetField(inst.CRFD, compare_value); } void Interpreter::fcmpo(UGeckoInstruction inst) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp index d851e451fe..e7cbd06b30 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp @@ -15,7 +15,7 @@ void Interpreter::Helper_UpdateCR0(u32 value) u64 cr_val = (u64)sign_extended; cr_val = (cr_val & ~(1ull << 61)) | ((u64)PowerPC::GetXER_SO() << 61); - PowerPC::ppcState.cr_val[0] = cr_val; + PowerPC::ppcState.cr.fields[0] = cr_val; } u32 Interpreter::Helper_Carry(u32 value1, u32 value2) @@ -82,7 +82,7 @@ void Interpreter::cmpi(UGeckoInstruction inst) if (PowerPC::GetXER_SO()) f |= 0x1; - PowerPC::SetCRField(inst.CRFD, f); + PowerPC::ppcState.cr.SetField(inst.CRFD, f); } void Interpreter::cmpli(UGeckoInstruction inst) @@ -101,7 +101,7 @@ void Interpreter::cmpli(UGeckoInstruction inst) if (PowerPC::GetXER_SO()) f |= 0x1; - PowerPC::SetCRField(inst.CRFD, f); + PowerPC::ppcState.cr.SetField(inst.CRFD, f); } void Interpreter::mulli(UGeckoInstruction inst) @@ -212,7 +212,7 @@ void Interpreter::cmp(UGeckoInstruction inst) if (PowerPC::GetXER_SO()) temp |= 0x1; - PowerPC::SetCRField(inst.CRFD, temp); + PowerPC::ppcState.cr.SetField(inst.CRFD, temp); } void Interpreter::cmpl(UGeckoInstruction inst) @@ -231,7 +231,7 @@ void Interpreter::cmpl(UGeckoInstruction inst) if (PowerPC::GetXER_SO()) temp |= 0x1; - PowerPC::SetCRField(inst.CRFD, temp); + PowerPC::ppcState.cr.SetField(inst.CRFD, temp); } void Interpreter::cntlzwx(UGeckoInstruction inst) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp index 8e270dfc9f..a4a1475c5f 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp @@ -1017,13 +1017,13 @@ void Interpreter::stwcxd(UGeckoInstruction inst) if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) { m_reserve = false; - PowerPC::SetCRField(0, 2 | PowerPC::GetXER_SO()); + PowerPC::ppcState.cr.SetField(0, 2 | PowerPC::GetXER_SO()); return; } } } - PowerPC::SetCRField(0, PowerPC::GetXER_SO()); + PowerPC::ppcState.cr.SetField(0, PowerPC::GetXER_SO()); } void Interpreter::stwux(UGeckoInstruction inst) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp index 84174fe288..b7d9c55001 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp @@ -107,14 +107,14 @@ void Interpreter::mtfsfx(UGeckoInstruction inst) void Interpreter::mcrxr(UGeckoInstruction inst) { - PowerPC::SetCRField(inst.CRFD, PowerPC::GetXER().Hex >> 28); + PowerPC::ppcState.cr.SetField(inst.CRFD, PowerPC::GetXER().Hex >> 28); PowerPC::ppcState.xer_ca = 0; PowerPC::ppcState.xer_so_ov = 0; } void Interpreter::mfcr(UGeckoInstruction inst) { - rGPR[inst.RD] = PowerPC::GetCR(); + rGPR[inst.RD] = PowerPC::ppcState.cr.Get(); } void Interpreter::mtcrf(UGeckoInstruction inst) @@ -122,7 +122,7 @@ void Interpreter::mtcrf(UGeckoInstruction inst) const u32 crm = inst.CRM; if (crm == 0xFF) { - PowerPC::SetCR(rGPR[inst.RS]); + PowerPC::ppcState.cr.Set(rGPR[inst.RS]); } else { @@ -134,7 +134,7 @@ void Interpreter::mtcrf(UGeckoInstruction inst) mask |= 0xFU << (i * 4); } - PowerPC::SetCR((PowerPC::GetCR() & ~mask) | (rGPR[inst.RS] & mask)); + PowerPC::ppcState.cr.Set((PowerPC::ppcState.cr.Get() & ~mask) | (rGPR[inst.RS] & mask)); } } @@ -464,48 +464,56 @@ void Interpreter::mtspr(UGeckoInstruction inst) void Interpreter::crand(UGeckoInstruction inst) { - PowerPC::SetCRBit(inst.CRBD, PowerPC::GetCRBit(inst.CRBA) & PowerPC::GetCRBit(inst.CRBB)); + PowerPC::ppcState.cr.SetBit(inst.CRBD, PowerPC::ppcState.cr.GetBit(inst.CRBA) & + PowerPC::ppcState.cr.GetBit(inst.CRBB)); } void Interpreter::crandc(UGeckoInstruction inst) { - PowerPC::SetCRBit(inst.CRBD, PowerPC::GetCRBit(inst.CRBA) & (1 ^ PowerPC::GetCRBit(inst.CRBB))); + PowerPC::ppcState.cr.SetBit(inst.CRBD, PowerPC::ppcState.cr.GetBit(inst.CRBA) & + (1 ^ PowerPC::ppcState.cr.GetBit(inst.CRBB))); } void Interpreter::creqv(UGeckoInstruction inst) { - PowerPC::SetCRBit(inst.CRBD, 1 ^ (PowerPC::GetCRBit(inst.CRBA) ^ PowerPC::GetCRBit(inst.CRBB))); + PowerPC::ppcState.cr.SetBit(inst.CRBD, 1 ^ (PowerPC::ppcState.cr.GetBit(inst.CRBA) ^ + PowerPC::ppcState.cr.GetBit(inst.CRBB))); } void Interpreter::crnand(UGeckoInstruction inst) { - PowerPC::SetCRBit(inst.CRBD, 1 ^ (PowerPC::GetCRBit(inst.CRBA) & PowerPC::GetCRBit(inst.CRBB))); + PowerPC::ppcState.cr.SetBit(inst.CRBD, 1 ^ (PowerPC::ppcState.cr.GetBit(inst.CRBA) & + PowerPC::ppcState.cr.GetBit(inst.CRBB))); } void Interpreter::crnor(UGeckoInstruction inst) { - PowerPC::SetCRBit(inst.CRBD, 1 ^ (PowerPC::GetCRBit(inst.CRBA) | PowerPC::GetCRBit(inst.CRBB))); + PowerPC::ppcState.cr.SetBit(inst.CRBD, 1 ^ (PowerPC::ppcState.cr.GetBit(inst.CRBA) | + PowerPC::ppcState.cr.GetBit(inst.CRBB))); } void Interpreter::cror(UGeckoInstruction inst) { - PowerPC::SetCRBit(inst.CRBD, (PowerPC::GetCRBit(inst.CRBA) | PowerPC::GetCRBit(inst.CRBB))); + PowerPC::ppcState.cr.SetBit( + inst.CRBD, (PowerPC::ppcState.cr.GetBit(inst.CRBA) | PowerPC::ppcState.cr.GetBit(inst.CRBB))); } void Interpreter::crorc(UGeckoInstruction inst) { - PowerPC::SetCRBit(inst.CRBD, (PowerPC::GetCRBit(inst.CRBA) | (1 ^ PowerPC::GetCRBit(inst.CRBB)))); + PowerPC::ppcState.cr.SetBit(inst.CRBD, (PowerPC::ppcState.cr.GetBit(inst.CRBA) | + (1 ^ PowerPC::ppcState.cr.GetBit(inst.CRBB)))); } void Interpreter::crxor(UGeckoInstruction inst) { - PowerPC::SetCRBit(inst.CRBD, (PowerPC::GetCRBit(inst.CRBA) ^ PowerPC::GetCRBit(inst.CRBB))); + PowerPC::ppcState.cr.SetBit( + inst.CRBD, (PowerPC::ppcState.cr.GetBit(inst.CRBA) ^ PowerPC::ppcState.cr.GetBit(inst.CRBB))); } void Interpreter::mcrf(UGeckoInstruction inst) { - const u32 cr_f = PowerPC::GetCRField(inst.CRFS); - PowerPC::SetCRField(inst.CRFD, cr_f); + const u32 cr_f = PowerPC::ppcState.cr.GetField(inst.CRFS); + PowerPC::ppcState.cr.SetField(inst.CRFD, cr_f); } void Interpreter::isync(UGeckoInstruction inst) @@ -546,7 +554,7 @@ void Interpreter::mcrfs(UGeckoInstruction inst) FPSCR.VXCVI = 0; break; } - PowerPC::SetCRField(inst.CRFD, fpflags); + PowerPC::ppcState.cr.SetField(inst.CRFD, fpflags); } void Interpreter::mffsx(UGeckoInstruction inst) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp index fcf65ee9b8..dd41561944 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp @@ -550,14 +550,16 @@ void Jit64::FloatCompare(UGeckoInstruction inst, bool upper) pGreater = J_CC(CC_B); } - MOV(64, R(RSCRATCH), Imm64(PowerPC::PPCCRToInternal(output[PowerPC::CR_EQ_BIT]))); + MOV(64, R(RSCRATCH), + Imm64(PowerPC::ConditionRegister::PPCToInternal(output[PowerPC::CR_EQ_BIT]))); if (fprf) OR(32, PPCSTATE(fpscr), Imm32(PowerPC::CR_EQ << FPRF_SHIFT)); continue1 = J(); SetJumpTarget(pNaN); - MOV(64, R(RSCRATCH), Imm64(PowerPC::PPCCRToInternal(output[PowerPC::CR_SO_BIT]))); + MOV(64, R(RSCRATCH), + Imm64(PowerPC::ConditionRegister::PPCToInternal(output[PowerPC::CR_SO_BIT]))); if (fprf) OR(32, PPCSTATE(fpscr), Imm32(PowerPC::CR_SO << FPRF_SHIFT)); @@ -566,13 +568,15 @@ void Jit64::FloatCompare(UGeckoInstruction inst, bool upper) continue2 = J(); SetJumpTarget(pGreater); - MOV(64, R(RSCRATCH), Imm64(PowerPC::PPCCRToInternal(output[PowerPC::CR_GT_BIT]))); + MOV(64, R(RSCRATCH), + Imm64(PowerPC::ConditionRegister::PPCToInternal(output[PowerPC::CR_GT_BIT]))); if (fprf) OR(32, PPCSTATE(fpscr), Imm32(PowerPC::CR_GT << FPRF_SHIFT)); continue3 = J(); SetJumpTarget(pLesser); - MOV(64, R(RSCRATCH), Imm64(PowerPC::PPCCRToInternal(output[PowerPC::CR_LT_BIT]))); + MOV(64, R(RSCRATCH), + Imm64(PowerPC::ConditionRegister::PPCToInternal(output[PowerPC::CR_LT_BIT]))); if (fprf) OR(32, PPCSTATE(fpscr), Imm32(PowerPC::CR_LT << FPRF_SHIFT)); } @@ -584,7 +588,7 @@ void Jit64::FloatCompare(UGeckoInstruction inst, bool upper) SetJumpTarget(continue3); } - MOV(64, PPCSTATE(cr_val[crf]), R(RSCRATCH)); + MOV(64, PPCSTATE(cr.fields[crf]), R(RSCRATCH)); } void Jit64::fcmpX(UGeckoInstruction inst) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index f132959dcb..a4ae501936 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -148,16 +148,16 @@ void Jit64::ComputeRC(preg_t preg, bool needs_test, bool needs_sext) if (arg.IsImm()) { - MOV(64, PPCSTATE(cr_val[0]), Imm32(arg.SImm32())); + MOV(64, PPCSTATE(cr.fields[0]), Imm32(arg.SImm32())); } else if (needs_sext) { MOVSX(64, 32, RSCRATCH, arg); - MOV(64, PPCSTATE(cr_val[0]), R(RSCRATCH)); + MOV(64, PPCSTATE(cr.fields[0]), R(RSCRATCH)); } else { - MOV(64, PPCSTATE(cr_val[0]), arg); + MOV(64, PPCSTATE(cr.fields[0]), arg); } if (CheckMergedBranch(0)) @@ -517,12 +517,12 @@ void Jit64::cmpXX(UGeckoInstruction inst) (u64)gpr.Imm32(a) - (u64)comparand.Imm32(); if (compareResult == (s32)compareResult) { - MOV(64, PPCSTATE(cr_val[crf]), Imm32((u32)compareResult)); + MOV(64, PPCSTATE(cr.fields[crf]), Imm32((u32)compareResult)); } else { MOV(64, R(RSCRATCH), Imm64(compareResult)); - MOV(64, PPCSTATE(cr_val[crf]), R(RSCRATCH)); + MOV(64, PPCSTATE(cr.fields[crf]), R(RSCRATCH)); } if (merge_branch) @@ -539,7 +539,7 @@ void Jit64::cmpXX(UGeckoInstruction inst) RCX64Reg Ra = gpr.Bind(a, RCMode::Read); RegCache::Realize(Ra); - MOV(64, PPCSTATE(cr_val[crf]), Ra); + MOV(64, PPCSTATE(cr.fields[crf]), Ra); if (merge_branch) { TEST(64, Ra, Ra); @@ -587,7 +587,7 @@ void Jit64::cmpXX(UGeckoInstruction inst) if (comparand.IsImm() && comparand.Imm32() == 0) { - MOV(64, PPCSTATE(cr_val[crf]), R(input)); + MOV(64, PPCSTATE(cr.fields[crf]), R(input)); // Place the comparison next to the branch for macro-op fusion if (merge_branch) TEST(64, R(input), R(input)); @@ -595,7 +595,7 @@ void Jit64::cmpXX(UGeckoInstruction inst) else { SUB(64, R(input), comparand); - MOV(64, PPCSTATE(cr_val[crf]), R(input)); + MOV(64, PPCSTATE(cr.fields[crf]), R(input)); } if (merge_branch) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp index f14cd38994..6a5d7bb360 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp @@ -15,27 +15,32 @@ using namespace Gen; +static OpArg CROffset(int field) +{ + return PPCSTATE(cr.fields[field]); +} + void Jit64::GetCRFieldBit(int field, int bit, X64Reg out, bool negate) { switch (bit) { case PowerPC::CR_SO_BIT: // check bit 61 set - BT(64, PPCSTATE(cr_val[field]), Imm8(61)); + BT(64, CROffset(field), Imm8(61)); SETcc(negate ? CC_NC : CC_C, R(out)); break; case PowerPC::CR_EQ_BIT: // check bits 31-0 == 0 - CMP(32, PPCSTATE(cr_val[field]), Imm8(0)); + CMP(32, CROffset(field), Imm8(0)); SETcc(negate ? CC_NZ : CC_Z, R(out)); break; case PowerPC::CR_GT_BIT: // check val > 0 - CMP(64, PPCSTATE(cr_val[field]), Imm8(0)); + CMP(64, CROffset(field), Imm8(0)); SETcc(negate ? CC_NG : CC_G, R(out)); break; case PowerPC::CR_LT_BIT: // check bit 62 set - BT(64, PPCSTATE(cr_val[field]), Imm8(62)); + BT(64, CROffset(field), Imm8(62)); SETcc(negate ? CC_NC : CC_C, R(out)); break; @@ -46,7 +51,7 @@ void Jit64::GetCRFieldBit(int field, int bit, X64Reg out, bool negate) void Jit64::SetCRFieldBit(int field, int bit, X64Reg in) { - MOV(64, R(RSCRATCH2), PPCSTATE(cr_val[field])); + MOV(64, R(RSCRATCH2), CROffset(field)); MOVZX(32, 8, in, R(in)); // Gross but necessary; if the input is totally zero and we set SO or LT, @@ -90,7 +95,7 @@ void Jit64::SetCRFieldBit(int field, int bit, X64Reg in) } BTS(64, R(RSCRATCH2), Imm8(32)); - MOV(64, PPCSTATE(cr_val[field]), R(RSCRATCH2)); + MOV(64, CROffset(field), R(RSCRATCH2)); } void Jit64::ClearCRFieldBit(int field, int bit) @@ -98,19 +103,19 @@ void Jit64::ClearCRFieldBit(int field, int bit) switch (bit) { case PowerPC::CR_SO_BIT: - BTR(64, PPCSTATE(cr_val[field]), Imm8(61)); + BTR(64, CROffset(field), Imm8(61)); break; case PowerPC::CR_EQ_BIT: - OR(64, PPCSTATE(cr_val[field]), Imm8(1)); + OR(64, CROffset(field), Imm8(1)); break; case PowerPC::CR_GT_BIT: - BTS(64, PPCSTATE(cr_val[field]), Imm8(63)); + BTS(64, CROffset(field), Imm8(63)); break; case PowerPC::CR_LT_BIT: - BTR(64, PPCSTATE(cr_val[field]), Imm8(62)); + BTR(64, CROffset(field), Imm8(62)); break; } // We don't need to set bit 32; the cases where that's needed only come up when setting bits, not @@ -119,7 +124,7 @@ void Jit64::ClearCRFieldBit(int field, int bit) void Jit64::SetCRFieldBit(int field, int bit) { - MOV(64, R(RSCRATCH), PPCSTATE(cr_val[field])); + MOV(64, R(RSCRATCH), CROffset(field)); if (bit != PowerPC::CR_GT_BIT) { TEST(64, R(RSCRATCH), R(RSCRATCH)); @@ -149,7 +154,7 @@ void Jit64::SetCRFieldBit(int field, int bit) } BTS(64, R(RSCRATCH), Imm8(32)); - MOV(64, PPCSTATE(cr_val[field]), R(RSCRATCH)); + MOV(64, CROffset(field), R(RSCRATCH)); } FixupBranch Jit64::JumpIfCRFieldBit(int field, int bit, bool jump_if_set) @@ -157,19 +162,19 @@ FixupBranch Jit64::JumpIfCRFieldBit(int field, int bit, bool jump_if_set) switch (bit) { case PowerPC::CR_SO_BIT: // check bit 61 set - BT(64, PPCSTATE(cr_val[field]), Imm8(61)); + BT(64, CROffset(field), Imm8(61)); return J_CC(jump_if_set ? CC_C : CC_NC, true); case PowerPC::CR_EQ_BIT: // check bits 31-0 == 0 - CMP(32, PPCSTATE(cr_val[field]), Imm8(0)); + CMP(32, CROffset(field), Imm8(0)); return J_CC(jump_if_set ? CC_Z : CC_NZ, true); case PowerPC::CR_GT_BIT: // check val > 0 - CMP(64, PPCSTATE(cr_val[field]), Imm8(0)); + CMP(64, CROffset(field), Imm8(0)); return J_CC(jump_if_set ? CC_G : CC_LE, true); case PowerPC::CR_LT_BIT: // check bit 62 set - BT(64, PPCSTATE(cr_val[field]), Imm8(62)); + BT(64, CROffset(field), Imm8(62)); return J_CC(jump_if_set ? CC_C : CC_NC, true); default: @@ -476,22 +481,22 @@ void Jit64::mtcrf(UGeckoInstruction inst) if ((crm & (0x80 >> i)) != 0) { u8 newcr = (gpr.Imm32(inst.RS) >> (28 - (i * 4))) & 0xF; - u64 newcrval = PowerPC::PPCCRToInternal(newcr); + u64 newcrval = PowerPC::ConditionRegister::PPCToInternal(newcr); if ((s64)newcrval == (s32)newcrval) { - MOV(64, PPCSTATE(cr_val[i]), Imm32((s32)newcrval)); + MOV(64, CROffset(i), Imm32((s32)newcrval)); } else { MOV(64, R(RSCRATCH), Imm64(newcrval)); - MOV(64, PPCSTATE(cr_val[i]), R(RSCRATCH)); + MOV(64, CROffset(i), R(RSCRATCH)); } } } } else { - MOV(64, R(RSCRATCH2), ImmPtr(PowerPC::m_crTable.data())); + MOV(64, R(RSCRATCH2), ImmPtr(PowerPC::ConditionRegister::s_crTable.data())); RCX64Reg Rs = gpr.Bind(inst.RS, RCMode::Read); RegCache::Realize(Rs); for (int i = 0; i < 8; i++) @@ -504,7 +509,7 @@ void Jit64::mtcrf(UGeckoInstruction inst) if (i != 0) AND(32, R(RSCRATCH), Imm8(0xF)); MOV(64, R(RSCRATCH), MComplex(RSCRATCH2, RSCRATCH, SCALE_8, 0)); - MOV(64, PPCSTATE(cr_val[i]), R(RSCRATCH)); + MOV(64, CROffset(i), R(RSCRATCH)); } } } @@ -519,8 +524,8 @@ void Jit64::mcrf(UGeckoInstruction inst) // USES_CR if (inst.CRFS != inst.CRFD) { - MOV(64, R(RSCRATCH), PPCSTATE(cr_val[inst.CRFS])); - MOV(64, PPCSTATE(cr_val[inst.CRFD]), R(RSCRATCH)); + MOV(64, R(RSCRATCH), CROffset(inst.CRFS)); + MOV(64, CROffset(inst.CRFD), R(RSCRATCH)); } } @@ -537,9 +542,9 @@ void Jit64::mcrxr(UGeckoInstruction inst) // [SO OV CA 0] << 3 SHL(32, R(RSCRATCH), Imm8(4)); - MOV(64, R(RSCRATCH2), ImmPtr(PowerPC::m_crTable.data())); + MOV(64, R(RSCRATCH2), ImmPtr(PowerPC::ConditionRegister::s_crTable.data())); MOV(64, R(RSCRATCH), MRegSum(RSCRATCH, RSCRATCH2)); - MOV(64, PPCSTATE(cr_val[inst.CRFD]), R(RSCRATCH)); + MOV(64, CROffset(inst.CRFD), R(RSCRATCH)); // Clear XER[0-3] MOV(8, PPCSTATE(xer_ca), Imm8(0)); @@ -646,9 +651,9 @@ void Jit64::mcrfs(UGeckoInstruction inst) } AND(32, R(RSCRATCH), Imm32(mask)); MOV(32, PPCSTATE(fpscr), R(RSCRATCH)); - LEA(64, RSCRATCH, MConst(PowerPC::m_crTable)); + LEA(64, RSCRATCH, MConst(PowerPC::ConditionRegister::s_crTable)); MOV(64, R(RSCRATCH), MComplex(RSCRATCH, RSCRATCH2, SCALE_8, 0)); - MOV(64, PPCSTATE(cr_val[inst.CRFD]), R(RSCRATCH)); + MOV(64, CROffset(inst.CRFD), R(RSCRATCH)); } void Jit64::mffsx(UGeckoInstruction inst) diff --git a/Source/Core/Core/PowerPC/Jit64Common/Jit64AsmCommon.cpp b/Source/Core/Core/PowerPC/Jit64Common/Jit64AsmCommon.cpp index ff3a99a797..81b4b27204 100644 --- a/Source/Core/Core/PowerPC/Jit64Common/Jit64AsmCommon.cpp +++ b/Source/Core/Core/PowerPC/Jit64Common/Jit64AsmCommon.cpp @@ -216,7 +216,7 @@ void CommonAsmRoutines::GenMfcr() if (i != 0) SHL(32, R(dst), Imm8(4)); - MOV(64, R(cr_val), PPCSTATE(cr_val[i])); + MOV(64, R(cr_val), PPCSTATE(cr.fields[i])); // Upper bits of tmp need to be zeroed. // Note: tmp is used later for address calculations and thus diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp index a72f7ec4ce..459d3d259e 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp @@ -293,7 +293,7 @@ void JitArm64::fcmpX(UGeckoInstruction inst) SetJumpTarget(pNaN); - MOVI2R(XA, PowerPC::PPCCRToInternal(PowerPC::CR_SO)); + MOVI2R(XA, PowerPC::ConditionRegister::PPCToInternal(PowerPC::CR_SO)); if (a != b) { diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.cpp index 78fd2633d9..b97ac69180 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.cpp @@ -139,7 +139,7 @@ Arm64GPRCache::GuestRegInfo Arm64GPRCache::GetGuestGPR(size_t preg) Arm64GPRCache::GuestRegInfo Arm64GPRCache::GetGuestCR(size_t preg) { ASSERT(preg < GUEST_CR_COUNT); - return {64, PPCSTATE_OFF(cr_val[preg]), m_guest_registers[GUEST_CR_OFFSET + preg]}; + return {64, PPCSTATE_OFF(cr.fields[preg]), m_guest_registers[GUEST_CR_OFFSET + preg]}; } Arm64GPRCache::GuestRegInfo Arm64GPRCache::GetGuestByIndex(size_t index) diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp index a922e7aafd..7f567eca4d 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp @@ -94,7 +94,7 @@ void JitArm64::mcrxr(UGeckoInstruction inst) // [SO OV CA 0] << 3 LSL(WA, WA, 4); - MOVP2R(XB, PowerPC::m_crTable.data()); + MOVP2R(XB, PowerPC::ConditionRegister::s_crTable.data()); LDR(XB, XB, XA); // Clear XER[0-3] @@ -664,7 +664,7 @@ void JitArm64::mtcrf(UGeckoInstruction inst) ARM64Reg RS = gpr.R(inst.RS); ARM64Reg WB = gpr.GetReg(); ARM64Reg XB = EncodeRegTo64(WB); - MOVP2R(XB, PowerPC::m_crTable.data()); + MOVP2R(XB, PowerPC::ConditionRegister::s_crTable.data()); for (int i = 0; i < 8; ++i) { if ((crm & (0x80 >> i)) != 0) diff --git a/Source/Core/Core/PowerPC/PPCTables.cpp b/Source/Core/Core/PowerPC/PPCTables.cpp index e8cb5ad2d6..f559e0f59b 100644 --- a/Source/Core/Core/PowerPC/PPCTables.cpp +++ b/Source/Core/Core/PowerPC/PPCTables.cpp @@ -31,28 +31,6 @@ std::array m_infoTable63; std::array m_allInstructions; size_t m_numInstructions; -namespace PowerPC -{ -const std::array m_crTable = {{ - PPCCRToInternal(0x0), - PPCCRToInternal(0x1), - PPCCRToInternal(0x2), - PPCCRToInternal(0x3), - PPCCRToInternal(0x4), - PPCCRToInternal(0x5), - PPCCRToInternal(0x6), - PPCCRToInternal(0x7), - PPCCRToInternal(0x8), - PPCCRToInternal(0x9), - PPCCRToInternal(0xA), - PPCCRToInternal(0xB), - PPCCRToInternal(0xC), - PPCCRToInternal(0xD), - PPCCRToInternal(0xE), - PPCCRToInternal(0xF), -}}; -} // namespace PowerPC - namespace PPCTables { GekkoOPInfo* GetOpInfo(UGeckoInstruction inst) diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index 52d19543a3..b8a7e94981 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -94,24 +94,6 @@ std::ostream& operator<<(std::ostream& os, CPUCore core) return os; } -u32 CompactCR() -{ - u32 new_cr = 0; - for (u32 i = 0; i < 8; i++) - { - new_cr |= GetCRField(i) << (28 - i * 4); - } - return new_cr; -} - -void ExpandCR(u32 cr) -{ - for (u32 i = 0; i < 8; i++) - { - SetCRField(i, (cr >> (28 - i * 4)) & 0xF); - } -} - void DoState(PointerWrap& p) { // some of this code has been disabled, because @@ -127,7 +109,7 @@ void DoState(PointerWrap& p) p.DoArray(ppcState.gpr); p.Do(ppcState.pc); p.Do(ppcState.npc); - p.DoArray(ppcState.cr_val); + p.DoArray(ppcState.cr.fields); p.Do(ppcState.msr); p.Do(ppcState.fpscr); p.Do(ppcState.Exceptions); @@ -183,8 +165,10 @@ static void ResetRegisters() ppcState.pc = 0; ppcState.npc = 0; ppcState.Exceptions = 0; - for (auto& v : ppcState.cr_val) + for (auto& v : ppcState.cr.fields) + { v = 0x8000000000000001; + } DBATUpdated(); IBATUpdated(); diff --git a/Source/Core/Core/PowerPC/PowerPC.h b/Source/Core/Core/PowerPC/PowerPC.h index 2c43bca14f..b8128a8594 100644 --- a/Source/Core/Core/PowerPC/PowerPC.h +++ b/Source/Core/Core/PowerPC/PowerPC.h @@ -4,7 +4,6 @@ #pragma once -#include #include #include #include @@ -15,6 +14,7 @@ #include "Core/Debugger/PPCDebugInterface.h" #include "Core/PowerPC/BreakPoints.h" +#include "Core/PowerPC/ConditionRegister.h" #include "Core/PowerPC/Gekko.h" #include "Core/PowerPC/PPCCache.h" @@ -103,20 +103,7 @@ struct PowerPCState u32 pc; // program counter u32 npc; - // Optimized CR implementation. Instead of storing CR in its PowerPC format - // (4 bit value, SO/EQ/LT/GT), we store instead a 64 bit value for each of - // the 8 CR register parts. This 64 bit value follows this format: - // - SO iff. bit 61 is set - // - EQ iff. lower 32 bits == 0 - // - GT iff. (s64)cr_val > 0 - // - LT iff. bit 62 is set - // - // This has the interesting property that sign-extending the result of an - // operation from 32 to 64 bits results in a 64 bit value that works as a - // CR value. Checking each part of CR is also fast, as it is equivalent to - // testing one bit or the low 32 bit part of a register. And CR can still - // be manipulated bit by bit fairly easily. - u64 cr_val[8]; + ConditionRegister cr; UReg_MSR msr; // machine state register UReg_FPSCR fpscr; // floating point flags/status bits @@ -213,9 +200,6 @@ void CheckExternalExceptions(); void CheckBreakPoints(); void RunLoop(); -u32 CompactCR(); -void ExpandCR(u32 cr); - u64 ReadFullTimeBaseValue(); void WriteFullTimeBaseValue(u64 value); @@ -252,83 +236,6 @@ void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst); #define rPS(i) (PowerPC::ppcState.ps[(i)]) -enum CRBits -{ - CR_SO = 1, - CR_EQ = 2, - CR_GT = 4, - CR_LT = 8, - - CR_SO_BIT = 0, - CR_EQ_BIT = 1, - CR_GT_BIT = 2, - CR_LT_BIT = 3, -}; - -// Convert between PPC and internal representation of CR. -inline u64 PPCCRToInternal(u8 value) -{ - u64 cr_val = 0x100000000; - cr_val |= (u64) !!(value & CR_SO) << 61; - cr_val |= (u64) !(value & CR_EQ); - cr_val |= (u64) !(value & CR_GT) << 63; - cr_val |= (u64) !!(value & CR_LT) << 62; - - return cr_val; -} - -// convert flags into 64-bit CR values with a lookup table -extern const std::array m_crTable; - -// Warning: these CR operations are fairly slow since they need to convert from -// PowerPC format (4 bit) to our internal 64 bit format. See the definition of -// ppcState.cr_val for more explanations. -inline void SetCRField(u32 cr_field, u32 value) -{ - PowerPC::ppcState.cr_val[cr_field] = m_crTable[value]; -} - -inline u32 GetCRField(u32 cr_field) -{ - const u64 cr_val = PowerPC::ppcState.cr_val[cr_field]; - u32 ppc_cr = 0; - - // SO - ppc_cr |= !!(cr_val & (1ull << 61)); - // EQ - ppc_cr |= ((cr_val & 0xFFFFFFFF) == 0) << 1; - // GT - ppc_cr |= (static_cast(cr_val) > 0) << 2; - // LT - ppc_cr |= !!(cr_val & (1ull << 62)) << 3; - - return ppc_cr; -} - -inline u32 GetCRBit(u32 bit) -{ - return (GetCRField(bit >> 2) >> (3 - (bit & 3))) & 1; -} - -inline void SetCRBit(u32 bit, u32 value) -{ - if (value & 1) - SetCRField(bit >> 2, GetCRField(bit >> 2) | (0x8 >> (bit & 3))); - else - SetCRField(bit >> 2, GetCRField(bit >> 2) & ~(0x8 >> (bit & 3))); -} - -// SetCR and GetCR are fairly slow. Should be avoided if possible. -inline void SetCR(u32 new_cr) -{ - PowerPC::ExpandCR(new_cr); -} - -inline u32 GetCR() -{ - return PowerPC::CompactCR(); -} - inline void SetCarry(u32 ca) { PowerPC::ppcState.xer_ca = ca; diff --git a/Source/Core/DolphinQt/Debugger/CodeWidget.cpp b/Source/Core/DolphinQt/Debugger/CodeWidget.cpp index a37881e03f..af13edfb3c 100644 --- a/Source/Core/DolphinQt/Debugger/CodeWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/CodeWidget.cpp @@ -416,7 +416,8 @@ static bool WillInstructionReturn(UGeckoInstruction inst) if (inst.hex == 0x4C000064u) return true; bool counter = (inst.BO_2 >> 2 & 1) != 0 || (CTR != 0) != ((inst.BO_2 >> 1 & 1) != 0); - bool condition = inst.BO_2 >> 4 != 0 || PowerPC::GetCRBit(inst.BI_2) == (inst.BO_2 >> 3 & 1); + bool condition = + inst.BO_2 >> 4 != 0 || PowerPC::ppcState.cr.GetBit(inst.BI_2) == (inst.BO_2 >> 3 & 1); bool isBclr = inst.OPCD_7 == 0b010011 && (inst.hex >> 1 & 0b10000) != 0; return isBclr && counter && condition && !inst.LK_3; } diff --git a/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp b/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp index 93bc112f67..ffe776e19f 100644 --- a/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp @@ -280,8 +280,8 @@ void RegisterWidget::PopulateTable() [](u64 value) { PowerPC::ppcState.spr[SPR_CTR] = value; }); // CR - AddRegister(20, 5, RegisterType::cr, "CR", [] { return PowerPC::GetCR(); }, - [](u64 value) { PowerPC::SetCR(value); }); + AddRegister(20, 5, RegisterType::cr, "CR", [] { return PowerPC::ppcState.cr.Get(); }, + [](u64 value) { PowerPC::ppcState.cr.Set(value); }); // XER AddRegister(21, 5, RegisterType::xer, "XER", [] { return PowerPC::GetXER().Hex; },