From a8be9781542807c13d09f125b142220f4c285dd4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 18 Mar 2015 23:58:34 +0100 Subject: [PATCH] ARM64 emitter: Add fixed point versions of SCVTF and UCVTF --- Common/Arm64Emitter.cpp | 31 +++++++++++++++++++++++++++++++ Common/Arm64Emitter.h | 5 +++++ 2 files changed, 36 insertions(+) diff --git a/Common/Arm64Emitter.cpp b/Common/Arm64Emitter.cpp index 7cfbbc836b..a6f2806978 100644 --- a/Common/Arm64Emitter.cpp +++ b/Common/Arm64Emitter.cpp @@ -2134,6 +2134,16 @@ void ARM64FloatEmitter::EmitConversion(bool sf, bool S, u32 type, u32 rmode, u32 (opcode << 16) | (Rn << 5) | Rd); } +void ARM64FloatEmitter::EmitConversion2(bool sf, bool S, u32 type, u32 rmode, u32 opcode, int scale, ARM64Reg Rd, ARM64Reg Rn) +{ + _assert_msg_(DYNA_REC, Rn <= SP, "%s only supports GPR as source!", __FUNCTION__); + Rd = DecodeReg(Rd); + Rn = DecodeReg(Rn); + + Write32((sf << 31) | (S << 29) | (0xF0 << 21) | (type << 22) | (rmode << 19) | \ + (opcode << 16) | (scale << 10) | (Rn << 5) | Rd); +} + void ARM64FloatEmitter::EmitCompare(bool M, bool S, u32 op, u32 opcode2, ARM64Reg Rn, ARM64Reg Rm) { _assert_msg_(DYNA_REC, !IsQuad(Rn), "%s doesn't support vector!", __FUNCTION__); @@ -2733,6 +2743,7 @@ void ARM64FloatEmitter::UCVTF(u8 size, ARM64Reg Rd, ARM64Reg Rn) { Emit2RegMisc(1, size >> 6, 0x1D, Rd, Rn); } + void ARM64FloatEmitter::XTN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn) { Emit2RegMisc(0, dest_size >> 4, 0x12, Rd, Rn); @@ -2930,6 +2941,26 @@ void ARM64FloatEmitter::UCVTF(ARM64Reg Rd, ARM64Reg Rn) EmitConversion(sf, 0, type, 0, 3, Rd, Rn); } +void ARM64FloatEmitter::SCVTF(ARM64Reg Rd, ARM64Reg Rn, int scale) +{ + bool sf = Is64Bit(Rn); + u32 type = 0; + if (IsDouble(Rd)) + type = 1; + + EmitConversion2(sf, 0, type, 0, 2, 64 - scale, Rd, Rn); +} + +void ARM64FloatEmitter::UCVTF(ARM64Reg Rd, ARM64Reg Rn, int scale) +{ + bool sf = Is64Bit(Rn); + u32 type = 0; + if (IsDouble(Rd)) + type = 1; + + EmitConversion2(sf, 0, type, 0, 3, 64 - scale, Rd, Rn); +} + void ARM64FloatEmitter::FCMP(ARM64Reg Rn, ARM64Reg Rm) { EmitCompare(0, 0, 0, 0, Rn, Rm); diff --git a/Common/Arm64Emitter.h b/Common/Arm64Emitter.h index 7e5605d3db..b29ecd47d1 100644 --- a/Common/Arm64Emitter.h +++ b/Common/Arm64Emitter.h @@ -787,6 +787,10 @@ public: void SCVTF(ARM64Reg Rd, ARM64Reg Rn); void UCVTF(ARM64Reg Rd, ARM64Reg Rn); + // Fixed point to float. scale is the number of fractional bits. + void SCVTF(ARM64Reg Rd, ARM64Reg Rn, int scale); + void UCVTF(ARM64Reg Rd, ARM64Reg Rn, int scale); + // Float comparison void FCMP(ARM64Reg Rn, ARM64Reg Rm); void FCMP(ARM64Reg Rn); @@ -840,6 +844,7 @@ private: void EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size, ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm); void Emit1Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd, ARM64Reg Rn); void EmitConversion(bool sf, bool S, u32 type, u32 rmode, u32 opcode, ARM64Reg Rd, ARM64Reg Rn); + void EmitConversion2(bool sf, bool S, u32 type, u32 rmode, u32 opcode, int scale, ARM64Reg Rd, ARM64Reg Rn); void EmitCompare(bool M, bool S, u32 op, u32 opcode2, ARM64Reg Rn, ARM64Reg Rm); void EmitCondSelect(bool M, bool S, CCFlags cond, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm); void EmitPermute(u32 size, u32 op, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);