From 7d918c0ad8c564c1eb487bd8fa6eb750ffbc7caa Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 25 Mar 2015 22:59:12 +0100 Subject: [PATCH] ARM64: Just some disasm improvements --- Core/Util/DisArm64.cpp | 28 +++++++++++++++++++++++++++- unittest/TestArm64Emitter.cpp | 11 ++++++++--- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Core/Util/DisArm64.cpp b/Core/Util/DisArm64.cpp index dcd89c3068..af9a9031f3 100644 --- a/Core/Util/DisArm64.cpp +++ b/Core/Util/DisArm64.cpp @@ -82,6 +82,15 @@ int HighestSetBit(int value) { return highest; } +int LowestSetBit(int value, int maximum = 32) { + int lowest = 0; + for (int i = 0; i < maximum; i++) { + if (value & (1 << i)) + return i; + } + return maximum; +} + static uint64_t Ones(int len) { if (len == 0x40) { return 0xFFFFFFFFFFFFFFFF; @@ -354,6 +363,9 @@ static void DataProcessingRegister(uint32_t w, uint64_t addr, Instruction *instr if (Rd == 31 && opc == 3) { // It's a CMP snprintf(instr->text, sizeof(instr->text), "%s %c%d, %c%d", "cmp", r, Rn, r, Rm); + } else if (Rn == 31 && opc == 2) { + // It's a NEG + snprintf(instr->text, sizeof(instr->text), "%s %c%d, %c%d", "neg", r, Rd, r, Rm); } else { snprintf(instr->text, sizeof(instr->text), "%s %c%d, %c%d, %c%d", opnames[opc], r, Rd, r, Rn, r, Rm); } @@ -413,6 +425,7 @@ const char *GetArrangement(bool Q, bool sz) { else if (Q == 1 && sz == 1) return "2d"; else return "ERROR"; } + // (w >> 25) & 0xF == 7 static void FPandASIMD1(uint32_t w, uint64_t addr, Instruction *instr) { int Rd = w & 0x1f; @@ -438,7 +451,20 @@ static void FPandASIMD1(uint32_t w, uint64_t addr, Instruction *instr) { } } else if (((w >> 21) & 0x4F9) == 0x70) { if (((w >> 10) & 0x21) == 1) { - snprintf(instr->text, sizeof(instr->text), "(asimd copy %08x)", w); + if (((w >> 11) & 3) == 3) { + // From GPR + snprintf(instr->text, sizeof(instr->text), "(asimd copy gpr %08x)", w); + } else { + int imm5 = (w >> 16) & 0x1F; + int size = LowestSetBit(imm5, 5); + 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); + } } } else if (((w >> 21) & 0x4F8) == 0x78) { if ((w >> 10) & 1) { diff --git a/unittest/TestArm64Emitter.cpp b/unittest/TestArm64Emitter.cpp index 54a19da436..89c75aad6d 100644 --- a/unittest/TestArm64Emitter.cpp +++ b/unittest/TestArm64Emitter.cpp @@ -39,15 +39,20 @@ bool TestArm64Emitter() { ARM64XEmitter emitter((u8 *)code); ARM64FloatEmitter fp(&emitter); + + fp.INS(32, Q3, 1, Q12, 3); + RET(CheckLast(emitter, "6e0c6583 ins q3.d[1], q12.d[3]")); + fp.INS(8, D4, 5, D11, 2); + RET(CheckLast(emitter, "6e0b1564 ins d4.b[5], d11.b[2]")); emitter.NEG(X1, X2); - RET(CheckLast(emitter, "8b030c41 neg x1, x2")); // A real disasm says fmla v0.2s, v1.2s, v2.s[1] but I think our way is more readable + RET(CheckLast(emitter, "cb0203e1 neg x1, x2")); emitter.ADD(X1, X2, X3, ArithOption(X1, ST_LSL, 3)); - RET(CheckLast(emitter, "8b030c41 add x1, x2, x3, lsl #3")); // A real disasm says fmla v0.2s, v1.2s, v2.s[1] but I think our way is more readable + RET(CheckLast(emitter, "8b030c41 add x1, x2, x3, lsl #3")); //emitter.EXTR(W1, W3, 0, 7); //RET(CheckLast(emitter, "53033061 extr w1, w3, w7")); //fp.FCVTL(32, Q6, D25); - //RET(CheckLast(emitter, "4fa29820 fcvtl q6, d25")); // A real disasm says fmla v0.2s, v1.2s, v2.s[1] but I think our way is more readable + //RET(CheckLast(emitter, "4fa29820 fcvtl q6, d25")); fp.FMUL(32, Q0, Q1, Q2, 3); RET(CheckLast(emitter, "4fa29820 fmul q0, q1, q2.4s[3]")); // A real disasm says fmla v0.2s, v1.2s, v2.s[1] but I think our way is more readable fp.FMLA(32, D0, D1, D2, 1);