]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Implement VCVT.{S,U}32.F64 D[d], D[d], #frac_bits. Fixes #315738.
authorJulian Seward <jseward@acm.org>
Wed, 6 Mar 2013 08:34:04 +0000 (08:34 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 6 Mar 2013 08:34:04 +0000 (08:34 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@2695

VEX/priv/guest_arm_toIR.c
VEX/priv/host_arm_isel.c

index 3bd873a9ef648d18a8de35c511bfa4327ea5a089..574b69b014a909d6c9faca05d2a17701adfaf229 100644 (file)
@@ -12486,8 +12486,6 @@ static Bool decode_CP10_CP11_instruction (
          /* VCVT.F64.{S,U}32 D[d], D[d], #frac_bits */
          /* This generates really horrible code.  We could potentially
             do much better. */
-         IRTemp rmode = newTemp(Ity_I32);
-         assign(rmode, mkU32(Irrm_NEAREST)); // per the spec
          IRTemp src32 = newTemp(Ity_I32);
          assign(src32,  unop(Iop_ReinterpF32asI32, getFReg(2*d)));
          IRExpr* as_F64 = unop( unsyned ? Iop_I32UtoF64 : Iop_I32StoF64,
@@ -12504,6 +12502,28 @@ static Bool decode_CP10_CP11_instruction (
              unsyned ? 'u' : 's', d, d, frac_bits);
          goto decode_success_vfp;
       }
+      if (frac_bits >= 1 && frac_bits <= 32 && to_fixed && dp_op
+                                            && size == 32) {
+         /* VCVT.{S,U}32.F64 D[d], D[d], #frac_bits */
+         IRTemp srcF64 = newTemp(Ity_F64);
+         assign(srcF64, getDReg(d));
+         IRTemp scale = newTemp(Ity_F64);
+         assign(scale, unop(Iop_I32UtoF64, mkU32( 1 << (frac_bits-1) )));
+         IRTemp scaledF64 = newTemp(Ity_F64);
+         IRExpr* rm = mkU32(Irrm_NEAREST);
+         assign(scaledF64, triop(Iop_MulF64,
+                                 rm, mkexpr(srcF64),
+                                 triop(Iop_AddF64, rm, mkexpr(scale),
+                                                       mkexpr(scale))));
+         IRTemp rmode = newTemp(Ity_I32);
+         assign(rmode, mkU32(Irrm_ZERO)); // as per the spec
+         IRTemp asI32 = newTemp(Ity_I32);
+         assign(asI32, binop(unsyned ? Iop_F64toI32U : Iop_F64toI32S,
+                             mkexpr(rmode), mkexpr(scaledF64)));
+         putDRegI64(d, unop(unsyned ? Iop_32Uto64 : Iop_32Sto64,
+                            mkexpr(asI32)), condT);
+         goto decode_success_vfp;
+      }
       /* fall through */
    }
 
index 84d856bb358aa512072a8606063d842c65467938..095fc9cdf26a3c618d9f80f986f246c026db3609 100644 (file)
@@ -3087,12 +3087,23 @@ static HReg iselNeon64Expr_wrk ( ISelEnv* env, IRExpr* e )
             return res;
          }
 
+         /* 32Sto64 */
+         case Iop_32Sto64: {
+            HReg rLo = iselIntExpr_R(env, e->Iex.Unop.arg);
+            HReg rHi = newVRegI(env);
+            addInstr(env, mk_iMOVds_RR(rHi, rLo));
+            addInstr(env, ARMInstr_Shift(ARMsh_SAR, rHi, rHi, ARMRI5_I5(31)));
+            HReg res = newVRegD(env);
+            addInstr(env, ARMInstr_VXferD(True/*toD*/, res, rHi, rLo));
+            return res;
+         }
+
+         /* The next 3 are pass-throughs */
          /* ReinterpF64asI64 */
          case Iop_ReinterpF64asI64:
          /* Left64(e) */
          case Iop_Left64:
          /* CmpwNEZ64(e) */
-         //case Iop_CmpwNEZ64:
          case Iop_1Sto64: {
             HReg rLo, rHi;
             HReg res = newVRegD(env);
@@ -3100,6 +3111,7 @@ static HReg iselNeon64Expr_wrk ( ISelEnv* env, IRExpr* e )
             addInstr(env, ARMInstr_VXferD(True/*toD*/, res, rHi, rLo));
             return res;
          }
+
          case Iop_Not64: {
             DECLARE_PATTERN(p_veqz_8x8);
             DECLARE_PATTERN(p_veqz_16x4);