From 013bbc71af60af4db1e783dad30bb3e8889daea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 4 Apr 2015 22:15:58 +0200 Subject: [PATCH] ARM64: Fix DUP disasm, INS disasm --- Common/Arm64Emitter.cpp | 8 ++++++++ Common/Arm64Emitter.h | 1 + Core/Util/DisArm64.cpp | 16 ++++++++++++---- unittest/TestArm64Emitter.cpp | 4 +++- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Common/Arm64Emitter.cpp b/Common/Arm64Emitter.cpp index 129c13f9de..5fcbdfbc59 100644 --- a/Common/Arm64Emitter.cpp +++ b/Common/Arm64Emitter.cpp @@ -3518,6 +3518,14 @@ void ARM64FloatEmitter::MOVI2F(ARM64Reg Rd, float value, ARM64Reg scratch, bool } } +// TODO: Quite a few values could be generated easily using the MOVI instruction and friends. +void ARM64FloatEmitter::MOVI2FDUP(ARM64Reg Rd, float value, ARM64Reg scratch) { + // TODO: Make it work with more element sizes + // TODO: Optimize - there are shorter solution for many values + MOVI2F(Rd, value, scratch); + DUP(32, Rd, Rd, 0); +} + void ARM64XEmitter::SUBSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) { u32 val; bool shift; diff --git a/Common/Arm64Emitter.h b/Common/Arm64Emitter.h index 889d392efb..2740ab3d3b 100644 --- a/Common/Arm64Emitter.h +++ b/Common/Arm64Emitter.h @@ -883,6 +883,7 @@ public: void FMLA(u8 esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u8 index); void MOVI2F(ARM64Reg Rd, float value, ARM64Reg scratch = INVALID_REG, bool negate = false); + void MOVI2FDUP(ARM64Reg Rd, float value, ARM64Reg scratch = INVALID_REG); // ABI related void ABI_PushRegisters(BitSet32 registers); diff --git a/Core/Util/DisArm64.cpp b/Core/Util/DisArm64.cpp index d0e9d3e275..78ab7cc039 100644 --- a/Core/Util/DisArm64.cpp +++ b/Core/Util/DisArm64.cpp @@ -533,10 +533,18 @@ static void FPandASIMD1(uint32_t w, uint64_t addr, Instruction *instr) { int imm4 = (w >> 11) & 0xF; int dst_index = imm5 >> (size + 1); int src_index = imm4 >> size; - int idxdsize = (imm4 & 8) ? 128 : 64; - char s = "bhdx"[size]; - char r = "dq"[idxdsize == 128]; - snprintf(instr->text, sizeof(instr->text), "ins %c%d.%c[%d], %c%d.%c[%d]", r, Rd, s, dst_index, r, Rn, s, src_index); + int op = (w >> 29) & 1; + char s = "bhsd"[size]; + if (op == 0 && imm4 == 0) { + // DUP (element) + int idxdsize = (imm5 & 8) ? 128 : 64; + char r = "dq"[idxdsize == 128]; + snprintf(instr->text, sizeof(instr->text), "dup %c%d, %c%d.%c[%d]", r, Rd, r, Rn, s, dst_index); + } else { + int idxdsize = (imm4 & 8) ? 128 : 64; + char r = "dq"[idxdsize == 128]; + snprintf(instr->text, sizeof(instr->text), "ins %c%d.%c[%d], %c%d.%c[%d]", r, Rd, s, dst_index, r, Rn, s, src_index); + } } } } else if (((w >> 21) & 0x4F8) == 0x78) { diff --git a/unittest/TestArm64Emitter.cpp b/unittest/TestArm64Emitter.cpp index 6987ef0007..c456326913 100644 --- a/unittest/TestArm64Emitter.cpp +++ b/unittest/TestArm64Emitter.cpp @@ -39,6 +39,8 @@ bool TestArm64Emitter() { ARM64XEmitter emitter((u8 *)code); ARM64FloatEmitter fp(&emitter); + fp.DUP(32, Q1, Q30, 3); + RET(CheckLast(emitter, "4e1c07c1 dup q1, q30.s[3]")); fp.UXTL(8, Q1, D8); RET(CheckLast(emitter, "2f08a501 uxtl.16.8 q1, d8")); fp.LDR(16, INDEX_UNSIGNED, Q1, X1, 64); @@ -52,7 +54,7 @@ bool TestArm64Emitter() { fp.FMUL(32, D1, D13, D21); RET(CheckLast(emitter, "2e35dda1 fmul.32 d1, d13, d21")); fp.INS(32, Q3, 1, Q12, 3); - RET(CheckLast(emitter, "6e0c6583 ins q3.d[1], q12.d[3]")); + RET(CheckLast(emitter, "6e0c6583 ins q3.s[1], q12.s[3]")); fp.INS(8, D4, 5, D11, 2); RET(CheckLast(emitter, "6e0b1564 ins d4.b[5], d11.b[2]")); emitter.NEG(X1, X2);