mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-04-24 22:34:54 +00:00
JitArm64: Optimize ConvertSingleToDouble, part 1
This commit is contained in:
parent
28e4869c43
commit
018e247624
4 changed files with 54 additions and 9 deletions
|
@ -221,6 +221,7 @@ private:
|
||||||
void GenerateAsm();
|
void GenerateAsm();
|
||||||
void GenerateCommonAsm();
|
void GenerateCommonAsm();
|
||||||
void GenerateConvertDoubleToSingle();
|
void GenerateConvertDoubleToSingle();
|
||||||
|
void GenerateConvertSingleToDouble();
|
||||||
void GenerateQuantizedLoadStores();
|
void GenerateQuantizedLoadStores();
|
||||||
|
|
||||||
// Profiling
|
// Profiling
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
#include "Core/CoreTiming.h"
|
#include "Core/CoreTiming.h"
|
||||||
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
|
|
||||||
#include "Core/PowerPC/JitArm64/Jit.h"
|
#include "Core/PowerPC/JitArm64/Jit.h"
|
||||||
#include "Core/PowerPC/JitArm64/JitArm64_RegCache.h"
|
#include "Core/PowerPC/JitArm64/JitArm64_RegCache.h"
|
||||||
#include "Core/PowerPC/PPCTables.h"
|
#include "Core/PowerPC/PPCTables.h"
|
||||||
|
@ -390,9 +389,6 @@ void JitArm64::fctiwzx(UGeckoInstruction inst)
|
||||||
// instructions, they must convert floats bitexact and never flush denormals to zero or turn SNaNs
|
// instructions, they must convert floats bitexact and never flush denormals to zero or turn SNaNs
|
||||||
// into QNaNs. This means we can't just use FCVT/FCVTL/FCVTN.
|
// into QNaNs. This means we can't just use FCVT/FCVTL/FCVTN.
|
||||||
|
|
||||||
// When calling the conversion functions, we are cheating a little and not
|
|
||||||
// saving the FPRs since we know the functions happen to not use them.
|
|
||||||
|
|
||||||
void JitArm64::ConvertDoubleToSingleLower(ARM64Reg dest_reg, ARM64Reg src_reg)
|
void JitArm64::ConvertDoubleToSingleLower(ARM64Reg dest_reg, ARM64Reg src_reg)
|
||||||
{
|
{
|
||||||
FlushCarry();
|
FlushCarry();
|
||||||
|
@ -429,11 +425,11 @@ void JitArm64::ConvertSingleToDoubleLower(ARM64Reg dest_reg, ARM64Reg src_reg)
|
||||||
{
|
{
|
||||||
FlushCarry();
|
FlushCarry();
|
||||||
|
|
||||||
const BitSet32 gpr_saved = gpr.GetCallerSavedUsed();
|
const BitSet32 gpr_saved = gpr.GetCallerSavedUsed() & BitSet32{0, 1, 2, 3, 4, 30};
|
||||||
ABI_PushRegisters(gpr_saved);
|
ABI_PushRegisters(gpr_saved);
|
||||||
|
|
||||||
m_float_emit.UMOV(32, ARM64Reg::W0, src_reg, 0);
|
m_float_emit.UMOV(32, ARM64Reg::W0, src_reg, 0);
|
||||||
QuickCallFunction(ARM64Reg::X1, &ConvertToDouble);
|
BL(cstd);
|
||||||
m_float_emit.INS(64, dest_reg, 0, ARM64Reg::X0);
|
m_float_emit.INS(64, dest_reg, 0, ARM64Reg::X0);
|
||||||
|
|
||||||
ABI_PopRegisters(gpr_saved);
|
ABI_PopRegisters(gpr_saved);
|
||||||
|
@ -443,15 +439,16 @@ void JitArm64::ConvertSingleToDoublePair(ARM64Reg dest_reg, ARM64Reg src_reg)
|
||||||
{
|
{
|
||||||
FlushCarry();
|
FlushCarry();
|
||||||
|
|
||||||
const BitSet32 gpr_saved = gpr.GetCallerSavedUsed();
|
// Save X0-X4 and X30 if they're in use
|
||||||
|
const BitSet32 gpr_saved = gpr.GetCallerSavedUsed() & BitSet32{0, 1, 2, 3, 4, 30};
|
||||||
ABI_PushRegisters(gpr_saved);
|
ABI_PushRegisters(gpr_saved);
|
||||||
|
|
||||||
m_float_emit.UMOV(32, ARM64Reg::W0, src_reg, 1);
|
m_float_emit.UMOV(32, ARM64Reg::W0, src_reg, 1);
|
||||||
QuickCallFunction(ARM64Reg::X1, &ConvertToDouble);
|
BL(cstd);
|
||||||
m_float_emit.INS(64, dest_reg, 1, ARM64Reg::X0);
|
m_float_emit.INS(64, dest_reg, 1, ARM64Reg::X0);
|
||||||
|
|
||||||
m_float_emit.UMOV(32, ARM64Reg::W0, src_reg, 0);
|
m_float_emit.UMOV(32, ARM64Reg::W0, src_reg, 0);
|
||||||
QuickCallFunction(ARM64Reg::X1, &ConvertToDouble);
|
BL(cstd);
|
||||||
m_float_emit.INS(64, dest_reg, 0, ARM64Reg::X0);
|
m_float_emit.INS(64, dest_reg, 0, ARM64Reg::X0);
|
||||||
|
|
||||||
ABI_PopRegisters(gpr_saved);
|
ABI_PopRegisters(gpr_saved);
|
||||||
|
|
|
@ -199,6 +199,10 @@ void JitArm64::GenerateCommonAsm()
|
||||||
GenerateConvertDoubleToSingle();
|
GenerateConvertDoubleToSingle();
|
||||||
JitRegister::Register(GetAsmRoutines()->cdts, GetCodePtr(), "JIT_cdts");
|
JitRegister::Register(GetAsmRoutines()->cdts, GetCodePtr(), "JIT_cdts");
|
||||||
|
|
||||||
|
GetAsmRoutines()->cstd = GetCodePtr();
|
||||||
|
GenerateConvertSingleToDouble();
|
||||||
|
JitRegister::Register(GetAsmRoutines()->cdts, GetCodePtr(), "JIT_cstd");
|
||||||
|
|
||||||
GenerateQuantizedLoadStores();
|
GenerateQuantizedLoadStores();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,6 +230,48 @@ void JitArm64::GenerateConvertDoubleToSingle()
|
||||||
RET();
|
RET();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Input in W0, output in X0, clobbers X0-X4 and flags.
|
||||||
|
void JitArm64::GenerateConvertSingleToDouble()
|
||||||
|
{
|
||||||
|
UBFX(ARM64Reg::W1, ARM64Reg::W0, 23, 8);
|
||||||
|
FixupBranch normal_or_nan = CBNZ(ARM64Reg::W1);
|
||||||
|
|
||||||
|
ANDI2R(ARM64Reg::W1, ARM64Reg::W0, 0x007fffff);
|
||||||
|
FixupBranch denormal = CBNZ(ARM64Reg::W1);
|
||||||
|
|
||||||
|
// Zero
|
||||||
|
LSL(ARM64Reg::X0, ARM64Reg::X0, 32);
|
||||||
|
RET();
|
||||||
|
|
||||||
|
SetJumpTarget(denormal);
|
||||||
|
ANDI2R(ARM64Reg::W2, ARM64Reg::W0, 0x80000000);
|
||||||
|
CLZ(ARM64Reg::X3, ARM64Reg::X1);
|
||||||
|
LSL(ARM64Reg::X2, ARM64Reg::X2, 32);
|
||||||
|
ORRI2R(ARM64Reg::X4, ARM64Reg::X3, 0xffffffffffffffc0);
|
||||||
|
SUB(ARM64Reg::X2, ARM64Reg::X2, ARM64Reg::X3, ArithOption(ARM64Reg::X3, ShiftType::LSL, 52));
|
||||||
|
ADD(ARM64Reg::X3, ARM64Reg::X4, 23);
|
||||||
|
LSLV(ARM64Reg::X1, ARM64Reg::X1, ARM64Reg::X3);
|
||||||
|
BFI(ARM64Reg::X2, ARM64Reg::X1, 30, 22);
|
||||||
|
MOVI2R(ARM64Reg::X1, 0x3a90000000000000);
|
||||||
|
ADD(ARM64Reg::X0, ARM64Reg::X2, ARM64Reg::X1);
|
||||||
|
RET();
|
||||||
|
|
||||||
|
SetJumpTarget(normal_or_nan);
|
||||||
|
CMP(ARM64Reg::W1, 0xff);
|
||||||
|
ANDI2R(ARM64Reg::W2, ARM64Reg::W0, 0x40000000);
|
||||||
|
CSET(ARM64Reg::W4, CCFlags::CC_NEQ);
|
||||||
|
ANDI2R(ARM64Reg::W3, ARM64Reg::W0, 0xc0000000);
|
||||||
|
EOR(ARM64Reg::W2, ARM64Reg::W4, ARM64Reg::W2, ArithOption(ARM64Reg::W2, ShiftType::LSR, 30));
|
||||||
|
MOVI2R(ARM64Reg::X1, 0x3800000000000000);
|
||||||
|
ANDI2R(ARM64Reg::W4, ARM64Reg::W0, 0x3fffffff);
|
||||||
|
LSL(ARM64Reg::X3, ARM64Reg::X3, 32);
|
||||||
|
CMP(ARM64Reg::W2, 0);
|
||||||
|
CSEL(ARM64Reg::X1, ARM64Reg::X1, ARM64Reg::ZR, CCFlags::CC_NEQ);
|
||||||
|
BFI(ARM64Reg::X3, ARM64Reg::X4, 29, 30);
|
||||||
|
ORR(ARM64Reg::X0, ARM64Reg::X3, ARM64Reg::X1);
|
||||||
|
RET();
|
||||||
|
}
|
||||||
|
|
||||||
void JitArm64::GenerateQuantizedLoadStores()
|
void JitArm64::GenerateQuantizedLoadStores()
|
||||||
{
|
{
|
||||||
// X0 is the scale
|
// X0 is the scale
|
||||||
|
|
|
@ -26,6 +26,7 @@ struct CommonAsmRoutinesBase
|
||||||
const u8* fres;
|
const u8* fres;
|
||||||
const u8* mfcr;
|
const u8* mfcr;
|
||||||
const u8* cdts;
|
const u8* cdts;
|
||||||
|
const u8* cstd;
|
||||||
|
|
||||||
// In: array index: GQR to use.
|
// In: array index: GQR to use.
|
||||||
// In: ECX: Address to read from.
|
// In: ECX: Address to read from.
|
||||||
|
|
Loading…
Add table
Reference in a new issue