summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorFiora <fioraaeterna@gmail.com>2014-08-21 13:56:18 -0700
committerFiora <fioraaeterna@gmail.com>2014-09-13 13:47:43 -0700
commitbea2504a5111b00a0ce618f28c0777fb299307f3 (patch)
tree1d7404b7e6400fddfe43de02b0ce7aa8ecfacd84 /Source/Core
parenta6c9515b00de392e3075d01287dd5ab38cab0bad (diff)
JIT64: optimize carry calculations
Omit carry calculations that get overwritten later in the block before they're used. Very common in the case of srawix and friends.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/PowerPC/Interpreter/Interpreter_Tables.cpp8
-rw-r--r--Source/Core/Core/PowerPC/Jit64/Jit.h2
-rw-r--r--Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp4
-rw-r--r--Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp123
-rw-r--r--Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp2
-rw-r--r--Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp10
-rw-r--r--Source/Core/Core/PowerPC/JitCommon/Jit_Util.h2
-rw-r--r--Source/Core/Core/PowerPC/PPCAnalyst.cpp44
-rw-r--r--Source/Core/Core/PowerPC/PPCAnalyst.h4
9 files changed, 116 insertions, 83 deletions
diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Tables.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Tables.cpp
index 2bf66ae99b..317132266d 100644
--- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Tables.cpp
+++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Tables.cpp
@@ -34,7 +34,7 @@ static GekkoOPTemplate primarytable[] =
{10, Interpreter::cmpli, {"cmpli", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn, 1, 0, 0, 0}},
{11, Interpreter::cmpi, {"cmpi", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn, 1, 0, 0, 0}},
{12, Interpreter::addic, {"addic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA, 1, 0, 0, 0}},
- {13, Interpreter::addic_rc, {"addic_rc", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CR0, 1, 0, 0, 0}},
+ {13, Interpreter::addic_rc, {"addic_rc", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA | FL_SET_CR0, 1, 0, 0, 0}},
{14, Interpreter::addi, {"addi", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0, 1, 0, 0, 0}},
{15, Interpreter::addis, {"addis", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0, 1, 0, 0, 0}},
@@ -180,8 +180,8 @@ static GekkoOPTemplate table31[] =
{922, Interpreter::extshx, {"extshx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT, 1, 0, 0, 0}},
{954, Interpreter::extsbx, {"extsbx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT, 1, 0, 0, 0}},
{536, Interpreter::srwx, {"srwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT, 1, 0, 0, 0}},
- {792, Interpreter::srawx, {"srawx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT, 1, 0, 0, 0}},
- {824, Interpreter::srawix, {"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT, 1, 0, 0, 0}},
+ {792, Interpreter::srawx, {"srawx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
+ {824, Interpreter::srawix, {"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
{24, Interpreter::slwx, {"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT, 1, 0, 0, 0}},
{54, Interpreter::dcbst, {"dcbst", OPTYPE_DCACHE, 0, 5, 0, 0, 0}},
@@ -260,7 +260,7 @@ static GekkoOPTemplate table31[] =
{339, Interpreter::mfspr, {"mfspr", OPTYPE_SPR, FL_OUT_D, 1, 0, 0, 0}},
{467, Interpreter::mtspr, {"mtspr", OPTYPE_SPR, 0, 2, 0, 0, 0}},
{371, Interpreter::mftb, {"mftb", OPTYPE_SYSTEM, FL_OUT_D | FL_TIMER, 1, 0, 0, 0}},
- {512, Interpreter::mcrxr, {"mcrxr", OPTYPE_SYSTEM, 0, 1, 0, 0, 0}},
+ {512, Interpreter::mcrxr, {"mcrxr", OPTYPE_SYSTEM, FL_READ_CA | FL_SET_CA, 1, 0, 0, 0}},
{595, Interpreter::mfsr, {"mfsr", OPTYPE_SYSTEM, FL_OUT_D, 3, 0, 0, 0}},
{659, Interpreter::mfsrin, {"mfsrin", OPTYPE_SYSTEM, FL_OUT_D, 3, 0, 0, 0}},
diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.h b/Source/Core/Core/PowerPC/Jit64/Jit.h
index dd5af56673..498d833dd7 100644
--- a/Source/Core/Core/PowerPC/Jit64/Jit.h
+++ b/Source/Core/Core/PowerPC/Jit64/Jit.h
@@ -100,7 +100,7 @@ public:
void GenerateConstantOverflow(bool overflow);
void GenerateConstantOverflow(s64 val);
void GenerateOverflow();
- void FinalizeCarryOverflow(bool oe, bool inv = false);
+ void FinalizeCarryOverflow(bool ca, bool oe, bool inv = false);
void ComputeRC(const Gen::OpArg & arg);
// Use to extract bytes from a register using the regcache. offset is in bytes.
diff --git a/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp b/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp
index 98c986a2f0..f9e0ac97d5 100644
--- a/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp
+++ b/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp
@@ -193,8 +193,8 @@ static GekkoOPTemplate table31[] =
{922, &Jit64::extsXx}, //"extshx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{954, &Jit64::extsXx}, //"extsbx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{536, &Jit64::srwx}, //"srwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
- {792, &Jit64::srawx}, //"srawx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
- {824, &Jit64::srawix}, //"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
+ {792, &Jit64::srawx}, //"srawx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_SET_CA | FL_RC_BIT}},
+ {824, &Jit64::srawix}, //"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_SET_CA | FL_RC_BIT}},
{24, &Jit64::slwx}, //"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{54, &Jit64::dcbst}, //"dcbst", OPTYPE_DCACHE, 0, 4}},
diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp
index 0b6f0dac4f..974ae1569d 100644
--- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp
+++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp
@@ -45,7 +45,7 @@ void Jit64::GenerateOverflow()
}
// Assumes CA,OV are clear
-void Jit64::FinalizeCarryOverflow(bool oe, bool inv)
+void Jit64::FinalizeCarryOverflow(bool ca, bool oe, bool inv)
{
// USES_XER
if (oe)
@@ -53,15 +53,17 @@ void Jit64::FinalizeCarryOverflow(bool oe, bool inv)
// this is slightly messy because JitSetCAIf modifies x86 flags, so we have to do it in both
// sides of the branch.
FixupBranch jno = J_CC(CC_NO);
- JitSetCAIf(inv ? CC_NC : CC_C);
+ if (ca)
+ JitSetCAIf(inv ? CC_NC : CC_C);
//XER[OV/SO] = 1
OR(32, PPCSTATE(spr[SPR_XER]), Imm32(XER_SO_MASK | XER_OV_MASK));
FixupBranch exit = J();
SetJumpTarget(jno);
- JitSetCAIf(inv ? CC_NC : CC_C);
+ if (ca)
+ JitSetCAIf(inv ? CC_NC : CC_C);
SetJumpTarget(exit);
}
- else
+ else if (ca)
{
// Do carry
JitSetCAIf(inv ? CC_NC : CC_C);
@@ -129,10 +131,11 @@ static u32 Xor(u32 a, u32 b)
void Jit64::regimmop(int d, int a, bool binary, u32 value, Operation doop, void (XEmitter::*op)(int, const Gen::OpArg&, const Gen::OpArg&), bool Rc, bool carry)
{
gpr.Lock(d, a);
- if (a || binary || carry) // yeh nasty special case addic
+ // Be careful; addic treats r0 as r0, but addi treats r0 as zero.
+ if (a || binary || carry)
{
- if (carry)
- JitClearCAOV(false);
+ carry &= js.op->wantsCA;
+ JitClearCAOV(carry, false);
if (gpr.R(a).IsImm() && !carry)
{
gpr.SetImmediate32(d, doop((u32)gpr.R(a).offset, value));
@@ -717,41 +720,43 @@ void Jit64::subfic(UGeckoInstruction inst)
{
if (imm == 0)
{
- JitClearCAOV(false);
+ JitClearCAOV(js.op->wantsCA, false);
// Flags act exactly like subtracting from 0
NEG(32, gpr.R(d));
// Output carry is inverted
- JitSetCAIf(CC_NC);
+ if (js.op->wantsCA)
+ JitSetCAIf(CC_NC);
}
else if (imm == -1)
{
// CA is always set in this case
- JitSetCA();
+ if (js.op->wantsCA)
+ JitSetCA();
NOT(32, gpr.R(d));
}
else
{
- JitClearCAOV(false);
+ JitClearCAOV(js.op->wantsCA, false);
NOT(32, gpr.R(d));
ADD(32, gpr.R(d), Imm32(imm+1));
// Output carry is normal
- JitSetCAIf(CC_C);
+ if (js.op->wantsCA)
+ JitSetCAIf(CC_C);
}
}
else
{
- JitClearCAOV(false);
+ JitClearCAOV(js.op->wantsCA, false);
MOV(32, gpr.R(d), Imm32(imm));
SUB(32, gpr.R(d), gpr.R(a));
// Output carry is inverted
- JitSetCAIf(CC_NC);
+ if (js.op->wantsCA)
+ JitSetCAIf(CC_NC);
}
gpr.UnlockAll();
// This instruction has no RC flag
}
-
-
void Jit64::subfx(UGeckoInstruction inst)
{
INSTRUCTION_START
@@ -1250,7 +1255,7 @@ void Jit64::arithXex(UGeckoInstruction inst)
NOT(32, gpr.R(d));
ADC(32, gpr.R(d), source);
}
- FinalizeCarryOverflow(inst.OE, invertedCarry);
+ FinalizeCarryOverflow(js.op->wantsCA, inst.OE, invertedCarry);
if (inst.Rc)
ComputeRC(gpr.R(d));
gpr.UnlockAll();
@@ -1264,7 +1269,7 @@ void Jit64::arithcx(UGeckoInstruction inst)
int a = inst.RA, b = inst.RB, d = inst.RD;
gpr.Lock(a, b, d);
gpr.BindToRegister(d, d == a || d == b, true);
- JitClearCAOV(inst.OE);
+ JitClearCAOV(js.op->wantsCA, inst.OE);
if (d == a && d != b)
{
@@ -1290,7 +1295,7 @@ void Jit64::arithcx(UGeckoInstruction inst)
SUB(32, gpr.R(d), gpr.R(a));
}
- FinalizeCarryOverflow(inst.OE, !add);
+ FinalizeCarryOverflow(js.op->wantsCA, inst.OE, !add);
if (inst.Rc)
ComputeRC(gpr.R(d));
gpr.UnlockAll();
@@ -1683,16 +1688,23 @@ void Jit64::srawx(UGeckoInstruction inst)
gpr.FlushLockX(ECX);
gpr.Lock(a, s, b);
gpr.BindToRegister(a, (a == s || a == b), true);
- JitClearCAOV(false);
+ JitClearCAOV(js.op->wantsCA, false);
MOV(32, R(ECX), gpr.R(b));
if (a != s)
MOV(32, gpr.R(a), gpr.R(s));
SHL(64, gpr.R(a), Imm8(32));
SAR(64, gpr.R(a), R(ECX));
- MOV(32, R(RSCRATCH), gpr.R(a));
- SHR(64, gpr.R(a), Imm8(32));
- TEST(32, gpr.R(a), R(RSCRATCH));
- JitSetCAIf(CC_NZ);
+ if (js.op->wantsCA)
+ {
+ MOV(32, R(RSCRATCH), gpr.R(a));
+ SHR(64, gpr.R(a), Imm8(32));
+ TEST(32, gpr.R(a), R(RSCRATCH));
+ JitSetCAIf(CC_NZ);
+ }
+ else
+ {
+ SHR(64, gpr.R(a), Imm8(32));
+ }
gpr.UnlockAll();
gpr.UnlockAllX();
if (inst.Rc)
@@ -1710,41 +1722,50 @@ void Jit64::srawix(UGeckoInstruction inst)
{
gpr.Lock(a, s);
gpr.BindToRegister(a, a == s, true);
- MOV(32, R(RSCRATCH), gpr.R(s));
- if (a != s)
- MOV(32, gpr.R(a), R(RSCRATCH));
- // some optimized common cases that can be done in slightly fewer ops
- if (amount == 31)
- {
- JitSetCA();
- SAR(32, gpr.R(a), Imm8(31));
- NEG(32, R(RSCRATCH)); // RSCRATCH = input == INT_MIN ? INT_MIN : -input;
- AND(32, R(RSCRATCH), Imm32(0x80000000)); // RSCRATCH = input < 0 && input != INT_MIN ? 0 : 0x80000000
- SHR(32, R(RSCRATCH), Imm8(31 - XER_CA_SHIFT));
- XOR(32, PPCSTATE(spr[SPR_XER]), R(RSCRATCH)); // XER.CA = (input < 0 && input != INT_MIN)
- }
- else if (amount == 1)
- {
- JitClearCAOV(false);
- SHR(32, R(RSCRATCH), Imm8(31)); // sign
- AND(32, R(RSCRATCH), gpr.R(a)); // (sign && carry)
- SAR(32, gpr.R(a), Imm8(1));
- SHL(32, R(RSCRATCH), Imm8(XER_CA_SHIFT));
- OR(32, PPCSTATE(spr[SPR_XER]), R(RSCRATCH)); // XER.CA = sign && carry, aka (input&0x80000001) == 0x80000001
+ if (!js.op->wantsCA)
+ {
+ if (a != s)
+ MOV(32, gpr.R(a), gpr.R(s));
+ SAR(32, gpr.R(a), Imm8(amount));
}
else
{
- JitClearCAOV(false);
- SAR(32, gpr.R(a), Imm8(amount));
- SHL(32, R(RSCRATCH), Imm8(32 - amount));
- TEST(32, R(RSCRATCH), gpr.R(a));
- JitSetCAIf(CC_NZ);
+ MOV(32, R(RSCRATCH), gpr.R(s));
+ if (a != s)
+ MOV(32, gpr.R(a), R(RSCRATCH));
+ // some optimized common cases that can be done in slightly fewer ops
+ if (amount == 31)
+ {
+ JitSetCA();
+ SAR(32, gpr.R(a), Imm8(31));
+ NEG(32, R(RSCRATCH)); // RSCRATCH = input == INT_MIN ? INT_MIN : -input;
+ AND(32, R(RSCRATCH), Imm32(0x80000000)); // RSCRATCH = input < 0 && input != INT_MIN ? 0 : 0x80000000
+ SHR(32, R(RSCRATCH), Imm8(31 - XER_CA_SHIFT));
+ XOR(32, PPCSTATE(spr[SPR_XER]), R(RSCRATCH)); // XER.CA = (input < 0 && input != INT_MIN)
+ }
+ else if (amount == 1)
+ {
+ JitClearCAOV(true, false);
+ SHR(32, R(RSCRATCH), Imm8(31)); // sign
+ AND(32, R(RSCRATCH), gpr.R(a)); // (sign && carry)
+ SAR(32, gpr.R(a), Imm8(1));
+ SHL(32, R(RSCRATCH), Imm8(XER_CA_SHIFT));
+ OR(32, PPCSTATE(spr[SPR_XER]), R(RSCRATCH)); // XER.CA = sign && carry, aka (input&0x80000001) == 0x80000001
+ }
+ else
+ {
+ JitClearCAOV(true, false);
+ SAR(32, gpr.R(a), Imm8(amount));
+ SHL(32, R(RSCRATCH), Imm8(32 - amount));
+ TEST(32, R(RSCRATCH), gpr.R(a));
+ JitSetCAIf(CC_NZ);
+ }
}
}
else
{
gpr.Lock(a, s);
- JitClearCAOV(false);
+ JitClearCAOV(js.op->wantsCA, false);
gpr.BindToRegister(a, a == s, true);
if (a != s)
diff --git a/Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp b/Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp
index 695dab795e..0305e22ac5 100644
--- a/Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp
+++ b/Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp
@@ -1106,7 +1106,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
Jit->JitSetCA();
FixupBranch cont = Jit->J();
Jit->SetJumpTarget(nocarry);
- Jit->JitClearCAOV(false);
+ Jit->JitClearCAOV(true, false);
Jit->SetJumpTarget(cont);
regNormalRegClear(RI, I);
break;
diff --git a/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp b/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp
index c12b9fedcf..2b1a0ef7c1 100644
--- a/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp
+++ b/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp
@@ -825,10 +825,10 @@ void EmuCodeBlock::JitSetCAIf(CCFlags conditionCode)
OR(32, PPCSTATE(spr[SPR_XER]), R(RSCRATCH)); //XER.CA = 1
}
-void EmuCodeBlock::JitClearCAOV(bool oe)
+void EmuCodeBlock::JitClearCAOV(bool ca, bool oe)
{
- if (oe)
- AND(32, PPCSTATE(spr[SPR_XER]), Imm32(~XER_CA_MASK & ~XER_OV_MASK)); //XER.CA, XER.OV = 0
- else
- AND(32, PPCSTATE(spr[SPR_XER]), Imm32(~XER_CA_MASK)); //XER.CA = 0
+ u32 mask = (ca ? ~XER_CA_MASK : 0xFFFFFFFF) & (oe ? ~XER_OV_MASK : 0xFFFFFFFF);
+ if (mask == 0xFFFFFFFF)
+ return;
+ AND(32, PPCSTATE(spr[SPR_XER]), Imm32(mask));
}
diff --git a/Source/Core/Core/PowerPC/JitCommon/Jit_Util.h b/Source/Core/Core/PowerPC/JitCommon/Jit_Util.h
index e50eedf08f..221ce455ab 100644
--- a/Source/Core/Core/PowerPC/JitCommon/Jit_Util.h
+++ b/Source/Core/Core/PowerPC/JitCommon/Jit_Util.h
@@ -74,7 +74,7 @@ public:
void JitGetAndClearCAOV(bool oe);
void JitSetCA();
void JitSetCAIf(Gen::CCFlags conditionCode);
- void JitClearCAOV(bool oe);
+ void JitClearCAOV(bool ca, bool oe);
void ForceSinglePrecisionS(Gen::X64Reg xmm);
void ForceSinglePrecisionP(Gen::X64Reg xmm);
diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/PowerPC/PPCAnalyst.cpp
index 55adc3f172..e7c06a2009 100644
--- a/Source/Core/Core/PowerPC/PPCAnalyst.cpp
+++ b/Source/Core/Core/PowerPC/PPCAnalyst.cpp
@@ -430,7 +430,6 @@ void PPCAnalyzer::SetInstructionStats(CodeBlock *block, CodeOp *code, GekkoOPInf
{
code->wantsCR0 = false;
code->wantsCR1 = false;
- code->wantsPS1 = false;
if (opinfo->flags & FL_USE_FPU)
block->m_fpa->any = true;
@@ -458,6 +457,15 @@ void PPCAnalyzer::SetInstructionStats(CodeBlock *block, CodeOp *code, GekkoOPInf
code->outputFPRF = (opinfo->flags & FL_SET_FPRF) ? true : false;
code->canEndBlock = (opinfo->flags & FL_ENDBLOCK) ? true : false;
+ code->wantsCA = (opinfo->flags & FL_READ_CA) ? true : false;
+ code->outputCA = (opinfo->flags & FL_SET_CA) ? true : false;
+
+ // mfspr/mtspr can affect/use XER, so be super careful here
+ if (code->inst.OPCD == 31 && code->inst.SUBOP10 == 339) // mfspr
+ code->wantsCA = ((code->inst.SPRU << 5) | (code->inst.SPRL & 0x1F)) == SPR_XER;
+ if (code->inst.OPCD == 31 && code->inst.SUBOP10 == 467) // mtspr
+ code->outputCA = ((code->inst.SPRU << 5) | (code->inst.SPRL & 0x1F)) == SPR_XER;
+
int numOut = 0;
int numIn = 0;
if (opinfo->flags & FL_OUT_A)
@@ -715,26 +723,30 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock *block, CodeBuffer *buffer, u32
block->m_broken = true;
}
- // Scan for CR0 dependency
- // assume next block wants flags to be safe
+ // Scan for flag dependencies; assume the next block (or any branch that can leave the block)
+ // wants flags, to be safe.
bool wantsCR0 = true;
bool wantsCR1 = true;
- bool wantsPS1 = true;
bool wantsFPRF = true;
+ bool wantsCA = true;
for (int i = block->m_num_instructions - 1; i >= 0; i--)
{
- wantsCR0 |= code[i].wantsCR0 || code[i].canEndBlock;
- wantsCR1 |= code[i].wantsCR1 || code[i].canEndBlock;
- wantsPS1 |= code[i].wantsPS1 || code[i].canEndBlock;
- wantsFPRF |= code[i].wantsFPRF || code[i].canEndBlock;
- code[i].wantsCR0 = wantsCR0;
- code[i].wantsCR1 = wantsCR1;
- code[i].wantsPS1 = wantsPS1;
- code[i].wantsFPRF = wantsFPRF;
- wantsCR0 &= !code[i].outputCR0;
- wantsCR1 &= !code[i].outputCR1;
- wantsPS1 &= !code[i].outputPS1;
- wantsFPRF &= !code[i].outputFPRF;
+ bool opWantsCR0 = code[i].wantsCR0;
+ bool opWantsCR1 = code[i].wantsCR1;
+ bool opWantsFPRF = code[i].wantsFPRF;
+ bool opWantsCA = code[i].wantsCA;
+ code[i].wantsCR0 = wantsCR0 || code[i].canEndBlock;
+ code[i].wantsCR1 = wantsCR1 || code[i].canEndBlock;
+ code[i].wantsFPRF = wantsFPRF || code[i].canEndBlock;
+ code[i].wantsCA = wantsCA || code[i].canEndBlock;
+ wantsCR0 |= opWantsCR0 || code[i].canEndBlock;
+ wantsCR1 |= opWantsCR1 || code[i].canEndBlock;
+ wantsFPRF |= opWantsFPRF || code[i].canEndBlock;
+ wantsCA |= opWantsCA || code[i].canEndBlock;
+ wantsCR0 &= !code[i].outputCR0 || opWantsCR0;
+ wantsCR1 &= !code[i].outputCR1 || opWantsCR1;
+ wantsFPRF &= !code[i].outputFPRF || opWantsFPRF;
+ wantsCA &= !code[i].outputCA || opWantsCA;
}
return address;
}
diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.h b/Source/Core/Core/PowerPC/PPCAnalyst.h
index 4a9058112a..774129a5d0 100644
--- a/Source/Core/Core/PowerPC/PPCAnalyst.h
+++ b/Source/Core/Core/PowerPC/PPCAnalyst.h
@@ -33,12 +33,12 @@ struct CodeOp //16B
bool isBranchTarget;
bool wantsCR0;
bool wantsCR1;
- bool wantsPS1;
bool wantsFPRF;
+ bool wantsCA;
bool outputCR0;
bool outputCR1;
- bool outputPS1;
bool outputFPRF;
+ bool outputCA;
bool canEndBlock;
bool skip; // followed BL-s for example
};