]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
arm64: implement FSQRT 2d_2d, 4s_4s, 2s_2s
authorJulian Seward <jseward@acm.org>
Mon, 6 Apr 2015 19:34:03 +0000 (19:34 +0000)
committerJulian Seward <jseward@acm.org>
Mon, 6 Apr 2015 19:34:03 +0000 (19:34 +0000)
AFAICS this completes the AArch64 SIMD implementation, except for the
crypto instructions.

This changes the type of Iop_Sqrt64x2 and Iop_Sqrt32x4 so as to take a
rounding mode argument.  This will (temporarily, of course) break all
of the other targets that implement vector fsqrt.

git-svn-id: svn://svn.valgrind.org/vex/trunk@3120

VEX/priv/guest_arm64_toIR.c
VEX/priv/host_arm64_defs.c
VEX/priv/host_arm64_defs.h
VEX/priv/host_arm64_isel.c
VEX/priv/ir_defs.c
VEX/pub/libvex_ir.h

index a5b7d2137c77a8bbf9da51f6641b38f7cc380309..14c27f1abf9a2bbca6e0a6ff0775c1b308a2ce52 100644 (file)
@@ -12437,6 +12437,21 @@ Bool dis_AdvSIMD_two_reg_misc(/*MB_OUT*/DisResult* dres, UInt insn)
       return True;
    }
 
+   if (bitU == 1 && size >= X10 && opcode == BITS5(1,1,1,1,1)) {
+      /* -------- 1,1x,11111: FSQRT 2d_2d, 4s_4s, 2s_2s -------- */
+      Bool isD = (size & 1) == 1;
+      IROp op  = isD ? Iop_Sqrt64Fx2 : Iop_Sqrt32Fx4;
+      if (bitQ == 0 && isD) return False; // implied 1d case
+      IRTemp resV = newTempV128();
+      assign(resV, binop(op, mkexpr(mk_get_IR_rounding_mode()),
+                             getQReg128(nn)));
+      putQReg128(dd, math_MAYBE_ZERO_HI64(bitQ, resV));
+      const HChar* arr = bitQ == 0 ? "2s" : (size == X11 ? "2d" : "4s");
+      DIP("%s %s.%s, %s.%s\n", "fsqrt",
+          nameQReg128(dd), arr, nameQReg128(nn), arr);
+      return True;
+   }
+
    return False;
 #  undef INSN
 }
index fc0984a9d5bbe33b52c736b76f3123f9cc315c90..b886e81cc2c6a8a7b6d3e2b713e3ba352222d642 100644 (file)
@@ -749,6 +749,8 @@ static void showARM64VecUnaryOp(/*OUT*/const HChar** nm,
       case ARM64vecu_FRECPE32x4:  *nm = "frecpe";  *ar = "4s";  return;
       case ARM64vecu_FRSQRTE64x2: *nm = "frsqrte"; *ar = "2d";  return;
       case ARM64vecu_FRSQRTE32x4: *nm = "frsqrte"; *ar = "4s";  return;
+      case ARM64vecu_FSQRT64x2:   *nm = "fsqrt";   *ar = "2d";  return;
+      case ARM64vecu_FSQRT32x4:   *nm = "fsqrt";   *ar = "4s";  return;
       default: vpanic("showARM64VecUnaryOp");
    }
 }
@@ -4869,6 +4871,9 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
 
             011 01110 11 1 00001 110110 n d  FRECPE Vd.2d, Vn.2d
             011 01110 10 1 00001 110110 n d  FRECPE Vd.4s, Vn.4s
+
+            011 01110 11 1 00001 111110 n d  FSQRT Vd.2d, Vn.2d
+            011 01110 10 1 00001 111110 n d  FSQRT Vd.4s, Vn.4s
          */
          UInt vD = qregEnc(i->ARM64in.VUnaryV.dst);
          UInt vN = qregEnc(i->ARM64in.VUnaryV.arg);
@@ -4960,6 +4965,12 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             case ARM64vecu_FRSQRTE32x4:
                *p++ = X_3_8_5_6_5_5(X011, X01110101, X00001, X110110, vN, vD);
                break;
+            case ARM64vecu_FSQRT64x2:
+               *p++ = X_3_8_5_6_5_5(X011, X01110111, X00001, X111110, vN, vD);
+               break;
+            case ARM64vecu_FSQRT32x4:
+               *p++ = X_3_8_5_6_5_5(X011, X01110101, X00001, X111110, vN, vD);
+               break;
             default:
                goto bad;
          }
index fce9f834226fd18b75c030c357fb703931256523..039fce1682be497177c6ee789a5b1404c37484d4 100644 (file)
@@ -414,6 +414,7 @@ typedef
       ARM64vecu_URSQRTE32x4,
       ARM64vecu_FRECPE64x2,   ARM64vecu_FRECPE32x4,
       ARM64vecu_FRSQRTE64x2,  ARM64vecu_FRSQRTE32x4,
+      ARM64vecu_FSQRT64x2,    ARM64vecu_FSQRT32x4,
       ARM64vecu_INVALID
    }
    ARM64VecUnaryOp;
index a6e507d050ffaa0a407056f0d76cd853682aa2f9..b6e42f1a79bc401d95f90884b29da806f5641558 100644 (file)
@@ -2363,6 +2363,17 @@ static HReg iselV128Expr_wrk ( ISelEnv* env, IRExpr* e )
 
    if (e->tag == Iex_Binop) {
       switch (e->Iex.Binop.op) {
+         case Iop_Sqrt32Fx4:
+         case Iop_Sqrt64Fx2: {
+            HReg arg = iselV128Expr(env, e->Iex.Binop.arg2);
+            HReg res = newVRegV(env);
+            set_FPCR_rounding_mode(env, e->Iex.Binop.arg1);
+            ARM64VecUnaryOp op 
+               = e->Iex.Binop.op == Iop_Sqrt32Fx4
+                    ? ARM64vecu_FSQRT32x4 : ARM64vecu_FSQRT64x2;
+            addInstr(env, ARM64Instr_VUnaryV(op, res, arg));
+            return res;
+         }
          case Iop_64HLtoV128: {
             HReg res  = newVRegV(env);
             HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1);
index 0b70f39fc2e35fe3610c04063b9b76411bfb7aae..596379e4b082d22f48e7e5394110230a7f369b7a 100644 (file)
@@ -2859,6 +2859,10 @@ void typeOfPrimop ( IROp op,
       case Iop_RSqrtEst32Ux4:
          UNARY(Ity_V128, Ity_V128);
 
+      case Iop_Sqrt64Fx2:
+      case Iop_Sqrt32Fx4:
+         BINARY(ity_RMode,Ity_V128, Ity_V128);
+
       case Iop_64HLtoV128:
          BINARY(Ity_I64,Ity_I64, Ity_V128);
 
@@ -3019,8 +3023,8 @@ void typeOfPrimop ( IROp op,
       case Iop_RecipEst64Fx2: case Iop_RSqrtEst64Fx2:
       case Iop_RecipEst32Ux4:
       case Iop_RSqrtEst32F0x4:
-      case Iop_Sqrt32Fx4:  case Iop_Sqrt32F0x4:
-      case Iop_Sqrt64Fx2:  case Iop_Sqrt64F0x2:
+      case Iop_Sqrt32F0x4:
+      case Iop_Sqrt64F0x2:
       case Iop_CmpNEZ8x16: case Iop_CmpNEZ16x8:
       case Iop_CmpNEZ32x4: case Iop_CmpNEZ64x2:
       case Iop_Cnt8x16:
index 7178c7e2e1dc2f282f28ca74e49dc440f925126c..145caa481cf8e1cd7591406fdfa74b6683cdd0d3 100644 (file)
@@ -1294,9 +1294,11 @@ typedef
 
       /* unary */
       Iop_Abs32Fx4,
-      Iop_Sqrt32Fx4,
       Iop_Neg32Fx4,
 
+      /* binary :: IRRoundingMode(I32) x V128 -> V128 */
+      Iop_Sqrt32Fx4,
+
       /* Vector Reciprocal Estimate finds an approximate reciprocal of each
          element in the operand vector, and places the results in the
          destination vector.  */
@@ -1359,9 +1361,11 @@ typedef
 
       /* unary */
       Iop_Abs64Fx2,
-      Iop_Sqrt64Fx2,
       Iop_Neg64Fx2,
 
+      /* binary :: IRRoundingMode(I32) x V128 -> V128 */
+      Iop_Sqrt64Fx2,
+
       /* see 32Fx4 variants for description */
       Iop_RecipEst64Fx2,    // unary
       Iop_RecipStep64Fx2,   // binary