Skip to content
Permalink
Browse files
Merge pull request #9593 from JosJuice/jitarm64-constant-carry
JitArm64: Constant carry flag optimizations
  • Loading branch information
degasus committed Mar 19, 2021
2 parents 3b9ae81 + 4c2cdb6 commit bcd572a
Show file tree
Hide file tree
Showing 7 changed files with 262 additions and 103 deletions.
@@ -673,6 +673,7 @@ class ARM64XEmitter
CSINV(Rd, zr, zr, (CCFlags)((u32)cond ^ 1));
}
void NEG(ARM64Reg Rd, ARM64Reg Rs) { SUB(Rd, Is64Bit(Rd) ? ARM64Reg::ZR : ARM64Reg::WZR, Rs); }
void NEGS(ARM64Reg Rd, ARM64Reg Rs) { SUBS(Rd, Is64Bit(Rd) ? ARM64Reg::ZR : ARM64Reg::WZR, Rs); }
// Data-Processing 1 source
void RBIT(ARM64Reg Rd, ARM64Reg Rn);
void REV16(ARM64Reg Rd, ARM64Reg Rn);
@@ -926,8 +926,7 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)

js.downcountAmount = 0;
js.skipInstructions = 0;
js.carryFlagSet = false;
js.carryFlagInverted = false;
js.carryFlag = CarryFlag::InPPCState;
js.constantGqr.clear();

// Assume that GQR values don't change often at runtime. Many paired-heavy games use largely float
@@ -63,26 +63,29 @@ void Jit64::GenerateOverflow()

void Jit64::FinalizeCarry(CCFlags cond)
{
js.carryFlagSet = false;
js.carryFlagInverted = false;
js.carryFlag = CarryFlag::InPPCState;
if (js.op->wantsCA)
{
// Not actually merging instructions, but the effect is equivalent (we can't have
// breakpoints/etc in between).
if (CanMergeNextInstructions(1) && js.op[1].wantsCAInFlags)
{
if (cond == CC_C || cond == CC_NC)
if (cond == CC_C)
{
js.carryFlagInverted = cond == CC_NC;
js.carryFlag = CarryFlag::InHostCarry;
}
else if (cond == CC_NC)
{
js.carryFlag = CarryFlag::InHostCarryInverted;
}
else
{
// convert the condition to a carry flag (is there a better way?)
SETcc(cond, R(RSCRATCH));
SHR(8, R(RSCRATCH), Imm8(1));
js.carryFlag = CarryFlag::InHostCarry;
}
LockFlags();
js.carryFlagSet = true;
}
else
{
@@ -94,8 +97,7 @@ void Jit64::FinalizeCarry(CCFlags cond)
// Unconditional version
void Jit64::FinalizeCarry(bool ca)
{
js.carryFlagSet = false;
js.carryFlagInverted = false;
js.carryFlag = CarryFlag::InPPCState;
if (js.op->wantsCA)
{
if (CanMergeNextInstructions(1) && js.op[1].wantsCAInFlags)
@@ -105,7 +107,7 @@ void Jit64::FinalizeCarry(bool ca)
else
CLC();
LockFlags();
js.carryFlagSet = true;
js.carryFlag = CarryFlag::InHostCarry;
}
else if (ca)
{
@@ -1475,7 +1477,7 @@ void Jit64::arithXex(UGeckoInstruction inst)
int d = inst.RD;
bool same_input_sub = !add && regsource && a == b;

if (!js.carryFlagSet)
if (js.carryFlag == CarryFlag::InPPCState)
JitGetAndClearCAOV(inst.OE);
else
UnlockFlags();
@@ -1488,7 +1490,7 @@ void Jit64::arithXex(UGeckoInstruction inst)
RegCache::Realize(Rd);

// Convert carry to borrow
if (!js.carryFlagInverted)
if (js.carryFlag != CarryFlag::InHostCarryInverted)
CMC();
SBB(32, Rd, Rd);
invertedCarry = true;
@@ -1499,7 +1501,7 @@ void Jit64::arithXex(UGeckoInstruction inst)
RCX64Reg Rd = gpr.Bind(d, RCMode::ReadWrite);
RegCache::Realize(Ra, Rd);

if (!js.carryFlagInverted)
if (js.carryFlag != CarryFlag::InHostCarryInverted)
CMC();
SBB(32, Rd, Ra);
invertedCarry = true;
@@ -1519,14 +1521,14 @@ void Jit64::arithXex(UGeckoInstruction inst)
NOT(32, Rd);
// if the source is an immediate, we can invert carry by going from add -> sub and doing src =
// -1 - src
if (js.carryFlagInverted && source.IsImm())
if (js.carryFlag == CarryFlag::InHostCarryInverted && source.IsImm())
{
SBB(32, Rd, Imm32(-1 - source.SImm32()));
invertedCarry = true;
}
else
{
if (js.carryFlagInverted)
if (js.carryFlag == CarryFlag::InHostCarryInverted)
CMC();
ADC(32, Rd, source);
}
@@ -638,7 +638,7 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
js.downcountAmount = 0;
js.skipInstructions = 0;
js.curBlock = b;
js.carryFlagSet = false;
js.carryFlag = CarryFlag::InPPCState;
js.numLoadStoreInst = 0;
js.numFloatingPointInst = 0;

@@ -233,7 +233,7 @@ class JitArm64 : public JitBase, public Arm64Gen::ARM64CodeBlock, public CommonA
void ComputeRC0(Arm64Gen::ARM64Reg reg);
void ComputeRC0(u64 imm);
void ComputeCarry(Arm64Gen::ARM64Reg reg); // reg must contain 0 or 1
void ComputeCarry(bool Carry);
void ComputeCarry(bool carry);
void ComputeCarry();
void FlushCarry();

0 comments on commit bcd572a

Please sign in to comment.