From: Julian Seward Date: Thu, 26 Jun 2014 12:39:05 +0000 (+0000) Subject: arm64: implement: rbit 16b,8b, rev16 16b,8b X-Git-Tag: svn/VALGRIND_3_10_1^2~80 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=32c4e9152c952fa3b99bafb6324f730c1ddc5591;p=thirdparty%2Fvalgrind.git arm64: implement: rbit 16b,8b, rev16 16b,8b git-svn-id: svn://svn.valgrind.org/vex/trunk@2891 --- diff --git a/VEX/priv/guest_arm64_toIR.c b/VEX/priv/guest_arm64_toIR.c index 48851aa247..1bc824af40 100644 --- a/VEX/priv/guest_arm64_toIR.c +++ b/VEX/priv/guest_arm64_toIR.c @@ -5657,6 +5657,16 @@ void putLO64andZUorPutHI64 ( Bool is2, UInt dd, IRTemp new64 ) } +/* |fullWidth| is a full V128 width result. Depending on bitQ, + zero out the upper half. */ +static IRExpr* math_MAYBE_ZERO_HI64 ( UInt bitQ, IRTemp fullWidth ) +{ + if (bitQ == 1) return mkexpr(fullWidth); + if (bitQ == 0) return unop(Iop_ZeroHI64ofV128, mkexpr(fullWidth)); + vassert(0); +} + + static Bool dis_AdvSIMD_EXT(/*MB_OUT*/DisResult* dres, UInt insn) { @@ -7464,6 +7474,17 @@ Bool dis_AdvSIMD_two_reg_misc(/*MB_OUT*/DisResult* dres, UInt insn) UInt dd = INSN(4,0); vassert(size < 4); + if (bitU == 0 && size == X00 && opcode == BITS5(0,0,0,0,1)) { + /* -------- 0,00,00001: REV16 16b_16b, 8b_8b -------- */ + IRTemp res = newTemp(Ity_V128); + assign(res, unop(Iop_Reverse8sIn16_x8, getQReg128(nn))); + putQReg128(dd, math_MAYBE_ZERO_HI64(bitQ, res)); + const HChar* arr = nameArr_Q_SZ(bitQ, 0); + DIP("%s %s.%s, %s.%s\n", "rev16", + nameQReg128(dd), arr, nameQReg128(nn), arr); + return True; + } + if (opcode == BITS5(0,0,1,0,0)) { /* -------- 0,xx,00100: CLS std6_std6 -------- */ /* -------- 1,xx,00100: CLZ std6_std6 -------- */ @@ -7489,12 +7510,24 @@ Bool dis_AdvSIMD_two_reg_misc(/*MB_OUT*/DisResult* dres, UInt insn) assign(res, unop(bitU == 0 ? Iop_Cnt8x16 : Iop_NotV128, getQReg128(nn))); putQReg128(dd, bitQ == 0 ? unop(Iop_ZeroHI64ofV128, mkexpr(res)) : mkexpr(res)); - const HChar* arr = nameArr_Q_SZ(bitQ, size); + const HChar* arr = nameArr_Q_SZ(bitQ, 0); DIP("%s %s.%s, %s.%s\n", bitU == 0 ? "cnt" : "not", nameQReg128(dd), arr, nameQReg128(nn), arr); return True; } + if (bitU == 1 && size == X01 && opcode == BITS5(0,0,1,0,1)) { + /* -------- 1,01,00101 RBIT 16b_16b, 8b_8b -------- */ + IRTemp res = newTemp(Ity_V128); + assign(res, unop(Iop_Reverse1sIn8_x16, getQReg128(nn))); + putQReg128(dd, bitQ == 0 ? unop(Iop_ZeroHI64ofV128, mkexpr(res)) + : mkexpr(res)); + const HChar* arr = nameArr_Q_SZ(bitQ, 0); + DIP("%s %s.%s, %s.%s\n", "rbit", + nameQReg128(dd), arr, nameQReg128(nn), arr); + return True; + } + if (opcode == BITS5(0,1,0,0,0)) { /* -------- 0,xx,01000: CMGT std7_std7_#0 -------- */ // >s 0 /* -------- 1,xx,01000: CMGE std7_std7_#0 -------- */ // >=s 0 diff --git a/VEX/priv/host_arm64_defs.c b/VEX/priv/host_arm64_defs.c index dbb485d6d5..041309deb7 100644 --- a/VEX/priv/host_arm64_defs.c +++ b/VEX/priv/host_arm64_defs.c @@ -947,6 +947,8 @@ static void showARM64VecUnaryOp(/*OUT*/const HChar** nm, case ARM64vecu_CLZ16x8: *nm = "clz "; *ar = "8h"; return; case ARM64vecu_CLZ8x16: *nm = "clz "; *ar = "16b"; return; case ARM64vecu_CNT8x16: *nm = "cnt "; *ar = "16b"; return; + case ARM64vecu_RBIT: *nm = "rbit "; *ar = "16b"; return; + case ARM64vecu_REV1616B: *nm = "rev16"; *ar = "16b"; return; default: vpanic("showARM64VecUnaryOp"); } } @@ -5387,6 +5389,10 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc, 011 01110 00 1 00000 010010 n d CLZ Vd.16b, Vn.16b 010 01110 00 1 00000 010110 n d CNT Vd.16b, Vn.16b + + 011 01110 01 1 00000 010110 n d RBIT Vd.16b, Vn.16b + + 010 01110 00 1 00000 000110 n d REV16 Vd.16b, Vn.16b */ UInt vD = qregNo(i->ARM64in.VUnaryV.dst); UInt vN = qregNo(i->ARM64in.VUnaryV.arg); @@ -5439,6 +5445,12 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc, case ARM64vecu_CNT8x16: *p++ = X_3_8_5_6_5_5(X010, X01110001, X00000, X010110, vN, vD); break; + case ARM64vecu_RBIT: + *p++ = X_3_8_5_6_5_5(X011, X01110011, X00000, X010110, vN, vD); + break; + case ARM64vecu_REV1616B: + *p++ = X_3_8_5_6_5_5(X010, X01110001, X00000, X000110, vN, vD); + break; default: goto bad; } diff --git a/VEX/priv/host_arm64_defs.h b/VEX/priv/host_arm64_defs.h index 12b098095e..7c1a233b10 100644 --- a/VEX/priv/host_arm64_defs.h +++ b/VEX/priv/host_arm64_defs.h @@ -360,6 +360,8 @@ typedef ARM64vecu_CLS32x4, ARM64vecu_CLS16x8, ARM64vecu_CLS8x16, ARM64vecu_CLZ32x4, ARM64vecu_CLZ16x8, ARM64vecu_CLZ8x16, ARM64vecu_CNT8x16, + ARM64vecu_RBIT, + ARM64vecu_REV1616B, ARM64vecu_INVALID } ARM64VecUnaryOp; diff --git a/VEX/priv/host_arm64_isel.c b/VEX/priv/host_arm64_isel.c index 35bebfaad2..60c351cfef 100644 --- a/VEX/priv/host_arm64_isel.c +++ b/VEX/priv/host_arm64_isel.c @@ -4417,6 +4417,8 @@ static HReg iselV128Expr_wrk ( ISelEnv* env, IRExpr* e ) case Iop_Cls32x4: case Iop_Cls16x8: case Iop_Cls8x16: case Iop_Clz32x4: case Iop_Clz16x8: case Iop_Clz8x16: case Iop_Cnt8x16: + case Iop_Reverse1sIn8_x16: + case Iop_Reverse8sIn16_x8: { HReg res = newVRegV(env); HReg arg = iselV128Expr(env, e->Iex.Unop.arg); @@ -4438,6 +4440,8 @@ static HReg iselV128Expr_wrk ( ISelEnv* env, IRExpr* e ) case Iop_Clz16x8: op = ARM64vecu_CLZ16x8; break; case Iop_Clz8x16: op = ARM64vecu_CLZ8x16; break; case Iop_Cnt8x16: op = ARM64vecu_CNT8x16; break; + case Iop_Reverse1sIn8_x16: op = ARM64vecu_RBIT; break; + case Iop_Reverse8sIn16_x8: op = ARM64vecu_REV1616B; break; default: vassert(0); } addInstr(env, ARM64Instr_VUnaryV(op, res, arg)); diff --git a/VEX/priv/ir_defs.c b/VEX/priv/ir_defs.c index df26947b73..b81a96e30d 100644 --- a/VEX/priv/ir_defs.c +++ b/VEX/priv/ir_defs.c @@ -976,6 +976,7 @@ void ppIROp ( IROp op ) case Iop_Reverse8sIn64_x2: vex_printf("Reverse8sIn64_x2"); return; case Iop_Reverse16sIn64_x2: vex_printf("Reverse16sIn64_x2"); return; case Iop_Reverse32sIn64_x2: vex_printf("Reverse32sIn64_x2"); return; + case Iop_Reverse1sIn8_x16: vex_printf("Reverse1sIn8_x16"); return; case Iop_F32ToFixed32Ux4_RZ: vex_printf("F32ToFixed32Ux4_RZ"); return; case Iop_F32ToFixed32Sx4_RZ: vex_printf("F32ToFixed32Sx4_RZ"); return; @@ -2912,6 +2913,7 @@ void typeOfPrimop ( IROp op, case Iop_Reverse32sIn64_x2: case Iop_Reverse8sIn32_x4: case Iop_Reverse16sIn32_x4: case Iop_Reverse8sIn16_x8: + case Iop_Reverse1sIn8_x16: case Iop_Neg64Fx2: case Iop_Neg32Fx4: case Iop_Abs8x16: case Iop_Abs16x8: case Iop_Abs32x4: case Iop_Abs64x2: case Iop_CipherSV128: diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index c9a49bb01e..78128470c7 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -1598,6 +1598,7 @@ typedef Iop_Reverse8sIn16_x8, Iop_Reverse8sIn32_x4, Iop_Reverse16sIn32_x4, Iop_Reverse8sIn64_x2, Iop_Reverse16sIn64_x2, Iop_Reverse32sIn64_x2, + Iop_Reverse1sIn8_x16, /* Reverse bits in each byte lane. */ /* PERMUTING -- copy src bytes to dst, as indexed by control vector bytes: