]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Implement fcsel d_d, s_s. Fixes #340856.
authorJulian Seward <jseward@acm.org>
Sat, 15 Nov 2014 16:07:14 +0000 (16:07 +0000)
committerJulian Seward <jseward@acm.org>
Sat, 15 Nov 2014 16:07:14 +0000 (16:07 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@2991

VEX/priv/guest_arm64_toIR.c
VEX/priv/host_arm64_defs.c
VEX/priv/host_arm64_defs.h
VEX/priv/host_arm64_isel.c

index 1426d003cdd250f06c2bab60df37aae75ef3b587..eb13f383fde118754daee76c74533f72b1642083 100644 (file)
@@ -11844,7 +11844,40 @@ Bool dis_AdvSIMD_fp_conditional_compare(/*MB_OUT*/DisResult* dres, UInt insn)
 static
 Bool dis_AdvSIMD_fp_conditional_select(/*MB_OUT*/DisResult* dres, UInt insn)
 {
+   /* 31        23 21 20 15   11 9 5
+      000 11110 ty 1  m  cond 11 n d
+      The first 3 bits are really "M 0 S", but M and S are always zero.
+      Decode fields: ty  
+   */
 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn, (_bMax), (_bMin))
+   if (INSN(31,24) != BITS8(0,0,0,1,1,1,1,0) || INSN(21,21) != 1
+       || INSN(11,10) != BITS2(1,1)) {
+      return False;
+   }
+   UInt ty   = INSN(23,22);
+   UInt mm   = INSN(20,16);
+   UInt cond = INSN(15,12);
+   UInt nn   = INSN(9,5);
+   UInt dd   = INSN(4,0);
+   if (ty <= X01) {
+      /* -------- 00: FCSEL s_s -------- */
+      /* -------- 00: FCSEL d_d -------- */
+      IRType ity = ty == X01 ? Ity_F64 : Ity_F32;
+      IRTemp srcT = newTemp(ity);
+      IRTemp srcF = newTemp(ity);
+      IRTemp res  = newTemp(ity);
+      assign(srcT, getQRegLO(nn, ity));
+      assign(srcF, getQRegLO(mm, ity));
+      assign(res, IRExpr_ITE(
+                     unop(Iop_64to1, mk_arm64g_calculate_condition(cond)),
+                     mkexpr(srcT), mkexpr(srcF)));
+      putQReg128(dd, mkV128(0x0000));
+      putQRegLO(dd, mkexpr(res));
+      DIP("fcsel %s, %s, %s, %s\n",
+          nameQRegLO(dd, ity), nameQRegLO(nn, ity), nameQRegLO(mm, ity),
+          nameCC(cond));
+      return True;
+   }
    return False;
 #  undef INSN
 }
index 62db9921bba380d9f94f790cd0ed8aff99bc651b..e18c5a576039a3393cb3540b25b91891f816449a 100644 (file)
@@ -1112,6 +1112,17 @@ ARM64Instr* ARM64Instr_VCmpS ( HReg argL, HReg argR ) {
    i->ARM64in.VCmpS.argR = argR;
    return i;
 }
+ARM64Instr* ARM64Instr_VFCSel ( HReg dst, HReg argL, HReg argR,
+                                ARM64CondCode cond, Bool isD ) {
+   ARM64Instr* i          = LibVEX_Alloc(sizeof(ARM64Instr));
+   i->tag                 = ARM64in_VFCSel;
+   i->ARM64in.VFCSel.dst  = dst;
+   i->ARM64in.VFCSel.argL = argL;
+   i->ARM64in.VFCSel.argR = argR;
+   i->ARM64in.VFCSel.cond = cond;
+   i->ARM64in.VFCSel.isD  = isD;
+   return i;
+}
 ARM64Instr* ARM64Instr_FPCR ( Bool toFPCR, HReg iReg ) {
    ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
    i->tag                 = ARM64in_FPCR;
@@ -1646,6 +1657,18 @@ void ppARM64Instr ( const ARM64Instr* i ) {
          vex_printf(", ");
          ppHRegARM64asSreg(i->ARM64in.VCmpS.argR);
          return;
+      case ARM64in_VFCSel: {
+         void (*ppHRegARM64fp)(HReg)
+            = (i->ARM64in.VFCSel.isD ? ppHRegARM64 : ppHRegARM64asSreg);
+         vex_printf("fcsel  ");
+         ppHRegARM64fp(i->ARM64in.VFCSel.dst);
+         vex_printf(", ");
+         ppHRegARM64fp(i->ARM64in.VFCSel.argL);
+         vex_printf(", ");
+         ppHRegARM64fp(i->ARM64in.VFCSel.argR);
+         vex_printf(", %s", showARM64CondCode(i->ARM64in.VFCSel.cond));
+         return;
+      }
       case ARM64in_FPCR:
          if (i->ARM64in.FPCR.toFPCR) {
             vex_printf("msr    fpcr, ");
@@ -2028,6 +2051,11 @@ void getRegUsage_ARM64Instr ( HRegUsage* u, const ARM64Instr* i, Bool mode64 )
          addHRegUse(u, HRmRead, i->ARM64in.VCmpS.argL);
          addHRegUse(u, HRmRead, i->ARM64in.VCmpS.argR);
          return;
+      case ARM64in_VFCSel:
+         addHRegUse(u, HRmRead, i->ARM64in.VFCSel.argL);
+         addHRegUse(u, HRmRead, i->ARM64in.VFCSel.argR);
+         addHRegUse(u, HRmWrite, i->ARM64in.VFCSel.dst);
+         return;
       case ARM64in_FPCR:
          if (i->ARM64in.FPCR.toFPCR)
             addHRegUse(u, HRmRead, i->ARM64in.FPCR.iReg);
@@ -2256,6 +2284,11 @@ void mapRegs_ARM64Instr ( HRegRemap* m, ARM64Instr* i, Bool mode64 )
          i->ARM64in.VCmpS.argL = lookupHRegRemap(m, i->ARM64in.VCmpS.argL);
          i->ARM64in.VCmpS.argR = lookupHRegRemap(m, i->ARM64in.VCmpS.argR);
          return;
+      case ARM64in_VFCSel:
+         i->ARM64in.VFCSel.argL = lookupHRegRemap(m, i->ARM64in.VFCSel.argL);
+         i->ARM64in.VFCSel.argR = lookupHRegRemap(m, i->ARM64in.VFCSel.argR);
+         i->ARM64in.VFCSel.dst  = lookupHRegRemap(m, i->ARM64in.VFCSel.dst);
+         return;
       case ARM64in_FPCR:
          i->ARM64in.FPCR.iReg = lookupHRegRemap(m, i->ARM64in.FPCR.iReg);
          return;
@@ -3958,6 +3991,21 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
          *p++ = X_3_8_5_6_5_5(X000, X11110001, sM, X001000, sN, X00000);
          goto done;
       }
+      case ARM64in_VFCSel: {
+         /* 31        23 21 20 15   11 9 5
+            000 11110 00 1  m  cond 11 n d  FCSEL Sd,Sn,Sm,cond
+            000 11110 01 1  m  cond 11 n d  FCSEL Dd,Dn,Dm,cond
+         */
+         Bool isD  = i->ARM64in.VFCSel.isD;
+         UInt dd   = dregNo(i->ARM64in.VFCSel.dst);
+         UInt nn   = dregNo(i->ARM64in.VFCSel.argL);
+         UInt mm   = dregNo(i->ARM64in.VFCSel.argR);
+         UInt cond = (UInt)i->ARM64in.VFCSel.cond;
+         vassert(cond < 16);
+         *p++ = X_3_8_5_6_5_5(X000, isD ? X11110011 : X11110001,
+                              mm, (cond << 2) | X000011, nn, dd);
+         goto done; 
+      }
       case ARM64in_FPCR: {
          Bool toFPCR = i->ARM64in.FPCR.toFPCR;
          UInt iReg   = iregNo(i->ARM64in.FPCR.iReg);
index 9420eb650bedcdc58dbbee2971fcbe7651b602d6..05615ea8ca2c94903098df7bfabe0d49b3f14671 100644 (file)
@@ -491,6 +491,7 @@ typedef
       ARM64in_VBinS,
       ARM64in_VCmpD,
       ARM64in_VCmpS,
+      ARM64in_VFCSel,
       ARM64in_FPCR,
       ARM64in_FPSR,
       /* ARM64in_V*V: vector ops on vector registers */
@@ -743,6 +744,15 @@ typedef
             HReg argL;
             HReg argR;
          } VCmpS;
+         /* 32- or 64-bit FP conditional select */
+         struct {
+            HReg          dst;
+            HReg          argL;
+            HReg          argR;
+            ARM64CondCode cond;
+            Bool          isD;
+         }
+         VFCSel;
          /* Move a 32-bit value to/from the FPCR */
          struct {
             Bool toFPCR;
@@ -889,6 +899,8 @@ extern ARM64Instr* ARM64Instr_VBinD   ( ARM64FpBinOp op, HReg, HReg, HReg );
 extern ARM64Instr* ARM64Instr_VBinS   ( ARM64FpBinOp op, HReg, HReg, HReg );
 extern ARM64Instr* ARM64Instr_VCmpD   ( HReg argL, HReg argR );
 extern ARM64Instr* ARM64Instr_VCmpS   ( HReg argL, HReg argR );
+extern ARM64Instr* ARM64Instr_VFCSel  ( HReg dst, HReg argL, HReg argR,
+                                        ARM64CondCode cond, Bool isD );
 extern ARM64Instr* ARM64Instr_FPCR    ( Bool toFPCR, HReg iReg );
 extern ARM64Instr* ARM64Instr_FPSR    ( Bool toFPSR, HReg iReg );
 extern ARM64Instr* ARM64Instr_VBinV   ( ARM64VecBinOp op, HReg, HReg, HReg );
index f11e0b358fe444c2dc467287a7464c81fb99de52..f0879f6a8ef0b1ff2637882a66a1ab84122857f2 100644 (file)
@@ -3067,6 +3067,17 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
       }
    }
 
+   if (e->tag == Iex_ITE) {
+      /* ITE(ccexpr, iftrue, iffalse) */
+      ARM64CondCode cc;
+      HReg r1  = iselDblExpr(env, e->Iex.ITE.iftrue);
+      HReg r0  = iselDblExpr(env, e->Iex.ITE.iffalse);
+      HReg dst = newVRegD(env);
+      cc = iselCondCode(env, e->Iex.ITE.cond);
+      addInstr(env, ARM64Instr_VFCSel(dst, r1, r0, cc, True/*64-bit*/));
+      return dst;
+   }
+
    ppIRExpr(e);
    vpanic("iselDblExpr_wrk");
 }
@@ -3222,6 +3233,17 @@ static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
       }
    }
 
+   if (e->tag == Iex_ITE) {
+      /* ITE(ccexpr, iftrue, iffalse) */
+      ARM64CondCode cc;
+      HReg r1  = iselFltExpr(env, e->Iex.ITE.iftrue);
+      HReg r0  = iselFltExpr(env, e->Iex.ITE.iffalse);
+      HReg dst = newVRegD(env);
+      cc = iselCondCode(env, e->Iex.ITE.cond);
+      addInstr(env, ARM64Instr_VFCSel(dst, r1, r0, cc, False/*!64-bit*/));
+      return dst;
+   }
+
    ppIRExpr(e);
    vpanic("iselFltExpr_wrk");
 }