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; },