Skip to content
Permalink
Browse files
Merge pull request #9396 from lioncash/arm
JitArm64_RegCache: Interface cleanup
  • Loading branch information
leoetlino committed Jan 1, 2021
2 parents f59ee87 + fabf79e commit 344a74a
Show file tree
Hide file tree
Showing 9 changed files with 319 additions and 285 deletions.
@@ -144,8 +144,8 @@ void JitArm64::Shutdown()
void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
{
FlushCarry();
gpr.Flush(FlushMode::FLUSH_ALL, js.op);
fpr.Flush(FlushMode::FLUSH_ALL, js.op);
gpr.Flush(FlushMode::All, js.op);
fpr.Flush(FlushMode::All, js.op);

if (js.op->opinfo->flags & FL_ENDBLOCK)
{
@@ -198,8 +198,8 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
SwitchToFarCode();
SetJumpTarget(handleException);

gpr.Flush(FLUSH_MAINTAIN_STATE);
fpr.Flush(FLUSH_MAINTAIN_STATE);
gpr.Flush(FlushMode::MaintainState);
fpr.Flush(FlushMode::MaintainState);

WriteExceptionExit(js.compilerPC);

@@ -212,8 +212,8 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
void JitArm64::HLEFunction(u32 hook_index)
{
FlushCarry();
gpr.Flush(FlushMode::FLUSH_ALL);
fpr.Flush(FlushMode::FLUSH_ALL);
gpr.Flush(FlushMode::All);
fpr.Flush(FlushMode::All);

MOVI2R(W0, js.compilerPC);
MOVI2R(W1, hook_index);
@@ -731,8 +731,8 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
TST(W30, 23, 2);
B(CC_EQ, done_here);

gpr.Flush(FLUSH_MAINTAIN_STATE);
fpr.Flush(FLUSH_MAINTAIN_STATE);
gpr.Flush(FlushMode::MaintainState);
fpr.Flush(FlushMode::MaintainState);
WriteExceptionExit(js.compilerPC, true);
SwitchToNearCode();
SetJumpTarget(exit);
@@ -763,8 +763,8 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
B(CC_EQ, done_here);
gpr.Unlock(WA);

gpr.Flush(FLUSH_MAINTAIN_STATE);
fpr.Flush(FLUSH_MAINTAIN_STATE);
gpr.Flush(FlushMode::MaintainState);
fpr.Flush(FlushMode::MaintainState);
WriteExceptionExit(js.compilerPC, true);
SwitchToNearCode();
SetJumpTarget(NoExtException);
@@ -787,8 +787,8 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
SwitchToFarCode();
SetJumpTarget(far_addr);

gpr.Flush(FLUSH_MAINTAIN_STATE);
fpr.Flush(FLUSH_MAINTAIN_STATE);
gpr.Flush(FlushMode::MaintainState);
fpr.Flush(FlushMode::MaintainState);

LDR(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
ORR(WA, WA, 26, 0); // EXCEPTION_FPU_UNAVAILABLE
@@ -807,8 +807,8 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)

if (SConfig::GetInstance().bJITRegisterCacheOff)
{
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
gpr.Flush(FlushMode::All);
fpr.Flush(FlushMode::All);
FlushCarry();
}

@@ -833,8 +833,8 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)

if (code_block.m_broken)
{
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
gpr.Flush(FlushMode::All);
fpr.Flush(FlushMode::All);
WriteExit(nextPC);
}

@@ -19,8 +19,8 @@ void JitArm64::sc(UGeckoInstruction inst)
INSTRUCTION_START
JITDISABLE(bJITBranchOff);

gpr.Flush(FlushMode::FLUSH_ALL);
fpr.Flush(FlushMode::FLUSH_ALL);
gpr.Flush(FlushMode::All);
fpr.Flush(FlushMode::All);

ARM64Reg WA = gpr.GetReg();

@@ -38,8 +38,8 @@ void JitArm64::rfi(UGeckoInstruction inst)
INSTRUCTION_START
JITDISABLE(bJITBranchOff);

gpr.Flush(FlushMode::FLUSH_ALL);
fpr.Flush(FlushMode::FLUSH_ALL);
gpr.Flush(FlushMode::All);
fpr.Flush(FlushMode::All);

// See Interpreter rfi for details
const u32 mask = 0x87C0FFFF;
@@ -96,8 +96,8 @@ void JitArm64::bx(UGeckoInstruction inst)
return;
}

gpr.Flush(FlushMode::FLUSH_ALL);
fpr.Flush(FlushMode::FLUSH_ALL);
gpr.Flush(FlushMode::All);
fpr.Flush(FlushMode::All);

if (js.op->branchIsIdleLoop)
{
@@ -154,8 +154,8 @@ void JitArm64::bcx(UGeckoInstruction inst)
}
gpr.Unlock(WA);

gpr.Flush(FlushMode::FLUSH_MAINTAIN_STATE);
fpr.Flush(FlushMode::FLUSH_MAINTAIN_STATE);
gpr.Flush(FlushMode::MaintainState);
fpr.Flush(FlushMode::MaintainState);

if (js.op->branchIsIdleLoop)
{
@@ -183,8 +183,8 @@ void JitArm64::bcx(UGeckoInstruction inst)

if (!analyzer.HasOption(PPCAnalyst::PPCAnalyzer::OPTION_CONDITIONAL_CONTINUE))
{
gpr.Flush(FlushMode::FLUSH_ALL);
fpr.Flush(FlushMode::FLUSH_ALL);
gpr.Flush(FlushMode::All);
fpr.Flush(FlushMode::All);
WriteExit(js.compilerPC + 4);
}
}
@@ -206,8 +206,8 @@ void JitArm64::bcctrx(UGeckoInstruction inst)
// BO_2 == 1z1zz -> b always

// NPC = CTR & 0xfffffffc;
gpr.Flush(FlushMode::FLUSH_ALL);
fpr.Flush(FlushMode::FLUSH_ALL);
gpr.Flush(FlushMode::All);
fpr.Flush(FlushMode::All);

if (inst.LK_3)
{
@@ -275,8 +275,8 @@ void JitArm64::bclrx(UGeckoInstruction inst)
gpr.Unlock(WB);
}

gpr.Flush(conditional ? FlushMode::FLUSH_MAINTAIN_STATE : FlushMode::FLUSH_ALL);
fpr.Flush(conditional ? FlushMode::FLUSH_MAINTAIN_STATE : FlushMode::FLUSH_ALL);
gpr.Flush(conditional ? FlushMode::MaintainState : FlushMode::All);
fpr.Flush(conditional ? FlushMode::MaintainState : FlushMode::All);

if (js.op->branchIsIdleLoop)
{
@@ -305,8 +305,8 @@ void JitArm64::bclrx(UGeckoInstruction inst)

if (!analyzer.HasOption(PPCAnalyst::PPCAnalyzer::OPTION_CONDITIONAL_CONTINUE))
{
gpr.Flush(FlushMode::FLUSH_ALL);
fpr.Flush(FlushMode::FLUSH_ALL);
gpr.Flush(FlushMode::All);
fpr.Flush(FlushMode::All);
WriteExit(js.compilerPC + 4);
}
}
@@ -39,9 +39,9 @@ void JitArm64::fp_arith(UGeckoInstruction inst)

if (packed)
{
RegType type = inputs_are_singles ? REG_REG_SINGLE : REG_REG;
u8 size = inputs_are_singles ? 32 : 64;
ARM64Reg (*reg_encoder)(ARM64Reg) = inputs_are_singles ? EncodeRegToDouble : EncodeRegToQuad;
const RegType type = inputs_are_singles ? RegType::Single : RegType::Register;
const u8 size = inputs_are_singles ? 32 : 64;
const auto reg_encoder = inputs_are_singles ? EncodeRegToDouble : EncodeRegToQuad;

VA = reg_encoder(fpr.R(a, type));
if (use_b)
@@ -71,10 +71,12 @@ void JitArm64::fp_arith(UGeckoInstruction inst)
}
else
{
RegType type = (inputs_are_singles && single) ? REG_LOWER_PAIR_SINGLE : REG_LOWER_PAIR;
RegType type_out = single ? (inputs_are_singles ? REG_DUP_SINGLE : REG_DUP) : REG_LOWER_PAIR;
ARM64Reg (*reg_encoder)(ARM64Reg) =
(inputs_are_singles && single) ? EncodeRegToSingle : EncodeRegToDouble;
const RegType type =
(inputs_are_singles && single) ? RegType::LowerPairSingle : RegType::LowerPair;
const RegType type_out =
single ? (inputs_are_singles ? RegType::DuplicatedSingle : RegType::Duplicated) :
RegType::LowerPair;
const auto reg_encoder = (inputs_are_singles && single) ? EncodeRegToSingle : EncodeRegToDouble;

VA = reg_encoder(fpr.R(a, type));
if (use_b)
@@ -125,25 +127,26 @@ void JitArm64::fp_logic(UGeckoInstruction inst)
JITDISABLE(bJITFloatingPointOff);
FALLBACK_IF(inst.Rc);

u32 b = inst.FB, d = inst.FD;
u32 op10 = inst.SUBOP10;
const u32 b = inst.FB;
const u32 d = inst.FD;
const u32 op10 = inst.SUBOP10;

bool packed = inst.OPCD == 4;

// MR with source === dest => no-op
if (op10 == 72 && b == d)
return;

bool single = fpr.IsSingle(b, !packed);
u8 size = single ? 32 : 64;
const bool single = fpr.IsSingle(b, !packed);
const u8 size = single ? 32 : 64;

if (packed)
{
RegType type = single ? REG_REG_SINGLE : REG_REG;
ARM64Reg (*reg_encoder)(ARM64Reg) = single ? EncodeRegToDouble : EncodeRegToQuad;
const RegType type = single ? RegType::Single : RegType::Register;
const auto reg_encoder = single ? EncodeRegToDouble : EncodeRegToQuad;

ARM64Reg VB = reg_encoder(fpr.R(b, type));
ARM64Reg VD = reg_encoder(fpr.RW(d, type));
const ARM64Reg VB = reg_encoder(fpr.R(b, type));
const ARM64Reg VD = reg_encoder(fpr.RW(d, type));

switch (op10)
{
@@ -167,11 +170,11 @@ void JitArm64::fp_logic(UGeckoInstruction inst)
}
else
{
RegType type = single ? REG_LOWER_PAIR_SINGLE : REG_LOWER_PAIR;
ARM64Reg (*reg_encoder)(ARM64Reg) = single ? EncodeRegToSingle : EncodeRegToDouble;
const RegType type = single ? RegType::LowerPairSingle : RegType::LowerPair;
const auto reg_encoder = single ? EncodeRegToSingle : EncodeRegToDouble;

ARM64Reg VB = fpr.R(b, type);
ARM64Reg VD = fpr.RW(d, type);
const ARM64Reg VB = fpr.R(b, type);
const ARM64Reg VD = fpr.RW(d, type);

switch (op10)
{
@@ -201,26 +204,29 @@ void JitArm64::fselx(UGeckoInstruction inst)
JITDISABLE(bJITFloatingPointOff);
FALLBACK_IF(inst.Rc);

u32 a = inst.FA, b = inst.FB, c = inst.FC, d = inst.FD;
const u32 a = inst.FA;
const u32 b = inst.FB;
const u32 c = inst.FC;
const u32 d = inst.FD;

if (fpr.IsSingle(a, true))
{
ARM64Reg VA = fpr.R(a, REG_LOWER_PAIR_SINGLE);
const ARM64Reg VA = fpr.R(a, RegType::LowerPairSingle);
m_float_emit.FCMPE(EncodeRegToSingle(VA));
}
else
{
ARM64Reg VA = fpr.R(a, REG_LOWER_PAIR);
const ARM64Reg VA = fpr.R(a, RegType::LowerPair);
m_float_emit.FCMPE(EncodeRegToDouble(VA));
}

bool single = fpr.IsSingle(b, true) && fpr.IsSingle(c, true);
RegType type = single ? REG_LOWER_PAIR_SINGLE : REG_LOWER_PAIR;
ARM64Reg (*reg_encoder)(ARM64Reg) = single ? EncodeRegToSingle : EncodeRegToDouble;
const bool single = fpr.IsSingle(b, true) && fpr.IsSingle(c, true);
const RegType type = single ? RegType::LowerPairSingle : RegType::LowerPair;
const auto reg_encoder = single ? EncodeRegToSingle : EncodeRegToDouble;

ARM64Reg VB = fpr.R(b, type);
ARM64Reg VC = fpr.R(c, type);
ARM64Reg VD = fpr.RW(d, type);
const ARM64Reg VB = fpr.R(b, type);
const ARM64Reg VC = fpr.R(c, type);
const ARM64Reg VD = fpr.RW(d, type);

m_float_emit.FCSEL(reg_encoder(VD), reg_encoder(VC), reg_encoder(VB), CC_GE);
}
@@ -232,21 +238,22 @@ void JitArm64::frspx(UGeckoInstruction inst)
FALLBACK_IF(inst.Rc);
FALLBACK_IF(SConfig::GetInstance().bFPRF && js.op->wantsFPRF);

u32 b = inst.FB, d = inst.FD;
const u32 b = inst.FB;
const u32 d = inst.FD;

if (fpr.IsSingle(b, true))
{
// Source is already in single precision, so no need to do anything but to copy to PSR1.
ARM64Reg VB = fpr.R(b, REG_LOWER_PAIR_SINGLE);
ARM64Reg VD = fpr.RW(d, REG_DUP_SINGLE);
const ARM64Reg VB = fpr.R(b, RegType::LowerPairSingle);
const ARM64Reg VD = fpr.RW(d, RegType::DuplicatedSingle);

if (b != d)
m_float_emit.FMOV(EncodeRegToSingle(VD), EncodeRegToSingle(VB));
}
else
{
ARM64Reg VB = fpr.R(b, REG_LOWER_PAIR);
ARM64Reg VD = fpr.RW(d, REG_DUP_SINGLE);
const ARM64Reg VB = fpr.R(b, RegType::LowerPair);
const ARM64Reg VD = fpr.RW(d, RegType::DuplicatedSingle);

m_float_emit.FCVT(32, 64, EncodeRegToDouble(VD), EncodeRegToDouble(VB));
}
@@ -258,18 +265,19 @@ void JitArm64::fcmpX(UGeckoInstruction inst)
JITDISABLE(bJITFloatingPointOff);
FALLBACK_IF(SConfig::GetInstance().bFPRF && js.op->wantsFPRF);

u32 a = inst.FA, b = inst.FB;
int crf = inst.CRFD;
const u32 a = inst.FA;
const u32 b = inst.FB;
const int crf = inst.CRFD;

bool singles = fpr.IsSingle(a, true) && fpr.IsSingle(b, true);
RegType type = singles ? REG_LOWER_PAIR_SINGLE : REG_LOWER_PAIR;
ARM64Reg (*reg_encoder)(ARM64Reg) = singles ? EncodeRegToSingle : EncodeRegToDouble;
const bool singles = fpr.IsSingle(a, true) && fpr.IsSingle(b, true);
const RegType type = singles ? RegType::LowerPairSingle : RegType::LowerPair;
const auto reg_encoder = singles ? EncodeRegToSingle : EncodeRegToDouble;

ARM64Reg VA = reg_encoder(fpr.R(a, type));
ARM64Reg VB = reg_encoder(fpr.R(b, type));
const ARM64Reg VA = reg_encoder(fpr.R(a, type));
const ARM64Reg VB = reg_encoder(fpr.R(b, type));

gpr.BindCRToRegister(crf, false);
ARM64Reg XA = gpr.CR(crf);
const ARM64Reg XA = gpr.CR(crf);

FixupBranch pNaN, pLesser, pGreater;
FixupBranch continue1, continue2, continue3;
@@ -320,14 +328,15 @@ void JitArm64::fctiwzx(UGeckoInstruction inst)
JITDISABLE(bJITFloatingPointOff);
FALLBACK_IF(inst.Rc);

u32 b = inst.FB, d = inst.FD;
const u32 b = inst.FB;
const u32 d = inst.FD;

bool single = fpr.IsSingle(b, true);
const bool single = fpr.IsSingle(b, true);

ARM64Reg VB = fpr.R(b, single ? REG_LOWER_PAIR_SINGLE : REG_LOWER_PAIR);
ARM64Reg VD = fpr.RW(d);
const ARM64Reg VB = fpr.R(b, single ? RegType::LowerPairSingle : RegType::LowerPair);
const ARM64Reg VD = fpr.RW(d);

ARM64Reg V0 = fpr.GetReg();
const ARM64Reg V0 = fpr.GetReg();

// Generate 0xFFF8000000000000ULL
m_float_emit.MOVI(64, EncodeRegToDouble(V0), 0xFFFF000000000000ULL);
@@ -339,7 +348,7 @@ void JitArm64::fctiwzx(UGeckoInstruction inst)
}
else
{
ARM64Reg V1 = gpr.GetReg();
const ARM64Reg V1 = gpr.GetReg();

m_float_emit.FCVTS(V1, EncodeRegToDouble(VB), RoundingMode::Z);
m_float_emit.FMOV(EncodeRegToSingle(VD), V1);

0 comments on commit 344a74a

Please sign in to comment.