JitArm64: Factor out single/double conversion code to functions

Preparation for following commits.

This commit intentionally doesn't touch paired stores,
since paired stores are supposed to flush to zero.
(Consistent with Jit64.)
This commit is contained in:
JosJuice 2021-01-21 19:11:06 +01:00
parent fdf7744a53
commit 949686bbe7
5 changed files with 41 additions and 11 deletions

View File

@ -152,6 +152,11 @@ public:
void psq_l(UGeckoInstruction inst);
void psq_st(UGeckoInstruction inst);
void ConvertDoubleToSingleLower(Arm64Gen::ARM64Reg dest_reg, Arm64Gen::ARM64Reg src_reg);
void ConvertDoubleToSinglePair(Arm64Gen::ARM64Reg dest_reg, Arm64Gen::ARM64Reg src_reg);
void ConvertSingleToDoubleLower(Arm64Gen::ARM64Reg dest_reg, Arm64Gen::ARM64Reg src_reg);
void ConvertSingleToDoublePair(Arm64Gen::ARM64Reg dest_reg, Arm64Gen::ARM64Reg src_reg);
private:
struct SlowmemHandler
{

View File

@ -386,3 +386,23 @@ void JitArm64::fctiwzx(UGeckoInstruction inst)
ASSERT_MSG(DYNA_REC, b == d || single == fpr.IsSingle(b, true),
"Register allocation turned singles into doubles in the middle of fctiwzx");
}
void JitArm64::ConvertDoubleToSingleLower(ARM64Reg dest_reg, ARM64Reg src_reg)
{
m_float_emit.FCVT(32, 64, EncodeRegToDouble(dest_reg), EncodeRegToDouble(src_reg));
}
void JitArm64::ConvertDoubleToSinglePair(ARM64Reg dest_reg, ARM64Reg src_reg)
{
m_float_emit.FCVTN(32, EncodeRegToDouble(dest_reg), EncodeRegToDouble(src_reg));
}
void JitArm64::ConvertSingleToDoubleLower(ARM64Reg dest_reg, ARM64Reg src_reg)
{
m_float_emit.FCVT(64, 32, EncodeRegToDouble(dest_reg), EncodeRegToDouble(src_reg));
}
void JitArm64::ConvertSingleToDoublePair(ARM64Reg dest_reg, ARM64Reg src_reg)
{
m_float_emit.FCVTL(64, EncodeRegToDouble(dest_reg), EncodeRegToDouble(src_reg));
}

View File

@ -258,7 +258,7 @@ void JitArm64::stfXX(UGeckoInstruction inst)
if (want_single && !have_single)
{
const ARM64Reg single_reg = fpr.GetReg();
m_float_emit.FCVT(32, 64, EncodeRegToDouble(single_reg), EncodeRegToDouble(V0));
ConvertDoubleToSingleLower(single_reg, V0);
V0 = single_reg;
}

View File

@ -17,9 +17,10 @@
using namespace Arm64Gen;
void Arm64RegCache::Init(ARM64XEmitter* emitter)
void Arm64RegCache::Init(JitArm64* jit)
{
m_emit = emitter;
m_jit = jit;
m_emit = jit;
m_float_emit.reset(new ARM64FloatEmitter(m_emit));
GetAllocationOrder();
}
@ -467,7 +468,7 @@ ARM64Reg Arm64FPRCache::R(size_t preg, RegType type)
return host_reg;
// Else convert this register back to doubles.
m_float_emit->FCVTL(64, EncodeRegToDouble(host_reg), EncodeRegToDouble(host_reg));
m_jit->ConvertSingleToDoublePair(host_reg, host_reg);
reg.Load(host_reg, RegType::Register);
[[fallthrough]];
}
@ -482,7 +483,7 @@ ARM64Reg Arm64FPRCache::R(size_t preg, RegType type)
return host_reg;
// Else convert this register back to a double.
m_float_emit->FCVT(64, 32, EncodeRegToDouble(host_reg), EncodeRegToDouble(host_reg));
m_jit->ConvertSingleToDoubleLower(host_reg, host_reg);
reg.Load(host_reg, RegType::LowerPair);
[[fallthrough]];
}
@ -516,7 +517,7 @@ ARM64Reg Arm64FPRCache::R(size_t preg, RegType type)
return host_reg;
}
m_float_emit->FCVT(64, 32, EncodeRegToDouble(host_reg), EncodeRegToDouble(host_reg));
m_jit->ConvertSingleToDoubleLower(host_reg, host_reg);
reg.Load(host_reg, RegType::Duplicated);
[[fallthrough]];
}
@ -593,7 +594,7 @@ ARM64Reg Arm64FPRCache::RW(size_t preg, RegType type)
{
case RegType::Single:
flush_reg = GetReg();
m_float_emit->FCVTL(64, EncodeRegToDouble(flush_reg), EncodeRegToDouble(host_reg));
m_jit->ConvertSingleToDoublePair(flush_reg, host_reg);
[[fallthrough]];
case RegType::Register:
// We are doing a full 128bit store because it takes 2 cycles on a Cortex-A57 to do a 128bit
@ -604,7 +605,7 @@ ARM64Reg Arm64FPRCache::RW(size_t preg, RegType type)
break;
case RegType::DuplicatedSingle:
flush_reg = GetReg();
m_float_emit->FCVT(64, 32, EncodeRegToDouble(flush_reg), EncodeRegToDouble(host_reg));
m_jit->ConvertSingleToDoubleLower(flush_reg, host_reg);
[[fallthrough]];
case RegType::Duplicated:
// Store PSR1 (which is equal to PSR0) in memory.
@ -712,13 +713,13 @@ void Arm64FPRCache::FlushRegister(size_t preg, bool maintain_state)
if (type == RegType::Single)
{
if (dirty)
m_float_emit->FCVTL(64, EncodeRegToDouble(host_reg), EncodeRegToDouble(host_reg));
m_jit->ConvertSingleToDoublePair(host_reg, host_reg);
type = RegType::Register;
}
if (type == RegType::DuplicatedSingle || type == RegType::LowerPairSingle)
{
if (dirty)
m_float_emit->FCVT(64, 32, EncodeRegToDouble(host_reg), EncodeRegToDouble(host_reg));
m_jit->ConvertSingleToDoubleLower(host_reg, host_reg);
if (type == RegType::DuplicatedSingle)
type = RegType::Duplicated;

View File

@ -15,6 +15,8 @@
#include "Core/PowerPC/PPCAnalyst.h"
#include "Core/PowerPC/PowerPC.h"
class JitArm64;
// Dedicated host registers
// memory base register
@ -150,7 +152,7 @@ public:
explicit Arm64RegCache(size_t guest_reg_count) : m_guest_registers(guest_reg_count) {}
virtual ~Arm64RegCache() = default;
void Init(Arm64Gen::ARM64XEmitter* emitter);
void Init(JitArm64* jit);
virtual void Start(PPCAnalyst::BlockRegStats& stats) {}
void DiscardRegisters(BitSet32 regs);
@ -218,6 +220,8 @@ protected:
reg.IncrementLastUsed();
}
JitArm64* m_jit = nullptr;
// Code emitter
Arm64Gen::ARM64XEmitter* m_emit = nullptr;