Quantcast

vex: r3293 - in /trunk: priv/guest_arm_toIR.c priv/host_arm_defs.c priv/host_arm_defs.h priv/host_arm_isel.c priv/ir_defs.c pub/libvex_ir.h

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

vex: r3293 - in /trunk: priv/guest_arm_toIR.c priv/host_arm_defs.c priv/host_arm_defs.h priv/host_arm_isel.c priv/ir_defs.c pub/libvex_ir.h

svn-2
Author: sewardj
Date: Fri Jan 13 17:58:57 2017
New Revision: 3293

Log:
Implement
  V{MIN,MAX}NM.F64 Dd, Dn, Dm
  V{MIN,MAX}NM.F32 Sd, Sn, Sm

Modified:
    trunk/priv/guest_arm_toIR.c
    trunk/priv/host_arm_defs.c
    trunk/priv/host_arm_defs.h
    trunk/priv/host_arm_isel.c
    trunk/priv/ir_defs.c
    trunk/pub/libvex_ir.h

Modified: trunk/priv/guest_arm_toIR.c
==============================================================================
--- trunk/priv/guest_arm_toIR.c (original)
+++ trunk/priv/guest_arm_toIR.c Fri Jan 13 17:58:57 2017
@@ -13665,6 +13665,50 @@
       return True;
    }
 
+   /* ----------- V{MAX,MIN}NM{.F64 d_d_d, .F32 s_s_s} ----------- */
+   /* 31   27    22 21 19 15 11  8 7 6  5 4 3
+      1111 11101 D  00 Vn Vd 101 1 N op M 0 Vm  V{MIN,MAX}NM.F64 Dd, Dn, Dm
+      1111 11101 D  00 Vn Vd 101 0 N op M 0 Vm  V{MIN,MAX}NM.F32 Sd, Sn, Sm
+
+      ARM encoding is in NV space.
+      In Thumb mode, we must not be in an IT block.
+   */
+   if (INSN(31,23) == BITS9(1,1,1,1,1,1,1,0,1) && INSN(21,20) == BITS2(0,0)
+       && INSN(11,9) == BITS3(1,0,1) && INSN(4,4) == 0) {
+      UInt bit_D  = INSN(22,22);
+      UInt fld_Vn = INSN(19,16);
+      UInt fld_Vd = INSN(15,12);
+      Bool isF64  = INSN(8,8) == 1;
+      UInt bit_N  = INSN(7,7);
+      Bool isMAX  = INSN(6,6) == 0;
+      UInt bit_M  = INSN(5,5);
+      UInt fld_Vm = INSN(3,0);
+
+      UInt dd = isF64 ? ((bit_D << 4) | fld_Vd) : ((fld_Vd << 1) | bit_D);
+      UInt nn = isF64 ? ((bit_N << 4) | fld_Vn) : ((fld_Vn << 1) | bit_N);
+      UInt mm = isF64 ? ((bit_M << 4) | fld_Vm) : ((fld_Vm << 1) | bit_M);
+
+      if (isT) {
+         gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
+      }
+      /* In ARM mode, this is statically unconditional.  In Thumb mode,
+         this must be dynamically unconditional, and we've SIGILLd if not.
+         In either case we can create unconditional IR. */
+
+      IROp op = isF64 ? (isMAX ? Iop_MaxNumF64 : Iop_MinNumF64)
+                      : (isMAX ? Iop_MaxNumF32 : Iop_MinNumF32);
+      IRExpr* srcN = (isF64 ? llGetDReg : llGetFReg)(nn);
+      IRExpr* srcM = (isF64 ? llGetDReg : llGetFReg)(mm);
+      IRExpr* res  = binop(op, srcN, srcM);
+      (isF64 ? llPutDReg : llPutFReg)(dd, res);
+
+      UChar rch = isF64 ? 'd' : 'f';
+      DIP("v%snm.%s %c%u, %c%u, %c%u\n",
+          isMAX ? "max" : "min", isF64 ? "f64" : "f32",
+          rch, dd, rch, nn, rch, mm);
+      return True;
+   }
+
    /* ---------- Doesn't match anything. ---------- */
    return False;
 

Modified: trunk/priv/host_arm_defs.c
==============================================================================
--- trunk/priv/host_arm_defs.c (original)
+++ trunk/priv/host_arm_defs.c Fri Jan 13 17:58:57 2017
@@ -1374,6 +1374,18 @@
    i->ARMin.VRIntR.src   = src;
    return i;
 }
+ARMInstr* ARMInstr_VMinMaxNum ( Bool isF64, Bool isMax,
+                                HReg dst, HReg srcL, HReg srcR )
+{
+   ARMInstr* i = LibVEX_Alloc_inline(sizeof(ARMInstr));
+   i->tag = ARMin_VMinMaxNum;
+   i->ARMin.VMinMaxNum.isF64 = isF64;
+   i->ARMin.VMinMaxNum.isMax = isMax;
+   i->ARMin.VMinMaxNum.dst   = dst ;
+   i->ARMin.VMinMaxNum.srcL  = srcL;
+   i->ARMin.VMinMaxNum.srcR  = srcR;
+   return i;
+}
 ARMInstr* ARMInstr_FPSCR ( Bool toFPSCR, HReg iReg ) {
    ARMInstr* i = LibVEX_Alloc_inline(sizeof(ARMInstr));
    i->tag                 = ARMin_FPSCR;
@@ -1890,6 +1902,17 @@
          ppHRegARM(i->ARMin.VRIntR.src);
          return;
       }
+      case ARMin_VMinMaxNum: {
+         const HChar* sz = i->ARMin.VMinMaxNum.isF64 ? "f64" : "f32";
+         const HChar* nm = i->ARMin.VMinMaxNum.isMax ? "vmaxnm" : "vminnm";
+         vex_printf("%s.%s ", nm, sz);
+         ppHRegARM(i->ARMin.VMinMaxNum.dst);
+         vex_printf(", ");
+         ppHRegARM(i->ARMin.VMinMaxNum.srcL);
+         vex_printf(", ");
+         ppHRegARM(i->ARMin.VMinMaxNum.srcR);
+         return;
+      }
       case ARMin_FPSCR:
          if (i->ARMin.FPSCR.toFPSCR) {
             vex_printf("fmxr  fpscr, ");
@@ -2289,6 +2312,11 @@
          addHRegUse(u, HRmWrite, i->ARMin.VRIntR.dst);
          addHRegUse(u, HRmRead,  i->ARMin.VRIntR.src);
          return;
+      case ARMin_VMinMaxNum:
+         addHRegUse(u, HRmWrite, i->ARMin.VMinMaxNum.dst);
+         addHRegUse(u, HRmRead,  i->ARMin.VMinMaxNum.srcL);
+         addHRegUse(u, HRmRead,  i->ARMin.VMinMaxNum.srcR);
+         return;
       case ARMin_FPSCR:
          if (i->ARMin.FPSCR.toFPSCR)
             addHRegUse(u, HRmRead, i->ARMin.FPSCR.iReg);
@@ -2508,6 +2536,14 @@
          i->ARMin.VRIntR.dst = lookupHRegRemap(m, i->ARMin.VRIntR.dst);
          i->ARMin.VRIntR.src = lookupHRegRemap(m, i->ARMin.VRIntR.src);
          return;
+      case ARMin_VMinMaxNum:
+         i->ARMin.VMinMaxNum.dst
+            = lookupHRegRemap(m, i->ARMin.VMinMaxNum.dst);
+         i->ARMin.VMinMaxNum.srcL
+            = lookupHRegRemap(m, i->ARMin.VMinMaxNum.srcL);
+         i->ARMin.VMinMaxNum.srcR
+            = lookupHRegRemap(m, i->ARMin.VMinMaxNum.srcR);
+         return;
       case ARMin_FPSCR:
          i->ARMin.FPSCR.iReg = lookupHRegRemap(m, i->ARMin.FPSCR.iReg);
          return;
@@ -3900,6 +3936,38 @@
                          isF64 ? X1011 : X1010, X0100 | (M << 1), Vm);
          goto done;
       }
+      case ARMin_VMinMaxNum: {
+         Bool isF64 = i->ARMin.VMinMaxNum.isF64;
+         Bool isMax = i->ARMin.VMinMaxNum.isMax;
+         UInt rDst  = (isF64 ? dregEnc : fregEnc)(i->ARMin.VMinMaxNum.dst);
+         UInt rSrcL = (isF64 ? dregEnc : fregEnc)(i->ARMin.VMinMaxNum.srcL);
+         UInt rSrcR = (isF64 ? dregEnc : fregEnc)(i->ARMin.VMinMaxNum.srcR);
+         /* The encoding of registers here differs strangely for the
+            F32 and F64 cases. */
+         UInt D, Vd, N, Vn, M, Vm;
+         if (isF64) {
+            D  = (rDst >> 4) & 1;
+            Vd = rDst & 0xF;
+            N  = (rSrcL >> 4) & 1;
+            Vn = rSrcL & 0xF;
+            M  = (rSrcR >> 4) & 1;
+            Vm = rSrcR & 0xF;
+         } else {
+            Vd = (rDst >> 1) & 0xF;
+            D  = rDst & 1;
+            Vn = (rSrcL >> 1) & 0xF;
+            N  = rSrcL & 1;
+            Vm = (rSrcR >> 1) & 0xF;
+            M  = rSrcR & 1;
+         }
+         vassert(D <= 1 && Vd <= 15 && M <= 1 && Vm <= 15 && N <= 1
+                 && Vn <= 15);
+         *p++ = XXXXXXXX(X1111,X1110, X1000 | (D << 2), Vn, Vd,
+                         X1010 | (isF64 ? 1 : 0),
+                         (N << 3) | ((isMax ? 0 : 1) << 2) | (M << 1) | 0,
+                         Vm);
+         goto done;
+      }
       case ARMin_FPSCR: {
          Bool toFPSCR = i->ARMin.FPSCR.toFPSCR;
          UInt iReg    = iregEnc(i->ARMin.FPSCR.iReg);

Modified: trunk/priv/host_arm_defs.h
==============================================================================
--- trunk/priv/host_arm_defs.h (original)
+++ trunk/priv/host_arm_defs.h Fri Jan 13 17:58:57 2017
@@ -596,6 +596,7 @@
       ARMin_VXferS,
       ARMin_VCvtID,
       ARMin_VRIntR,
+      ARMin_VMinMaxNum,
       ARMin_FPSCR,
       ARMin_MFence,
       ARMin_CLREX,
@@ -861,6 +862,15 @@
             HReg dst;
             HReg src;
          } VRIntR;
+         /* Do Min/Max of F32 or F64 values, propagating the numerical arg
+            if the other is a qNaN.  For ARM >= V8 hosts only. */
+         struct {
+            Bool isF64;
+            Bool isMax;
+            HReg dst;
+            HReg srcL;
+            HReg srcR;
+         } VMinMaxNum;
          /* Move a 32-bit value to/from the FPSCR (FMXR, FMRX) */
          struct {
             Bool toFPSCR;
@@ -1016,6 +1026,8 @@
 extern ARMInstr* ARMInstr_VCvtID   ( Bool iToD, Bool syned,
                                      HReg dst, HReg src );
 extern ARMInstr* ARMInstr_VRIntR   ( Bool isF64, HReg dst, HReg src );
+extern ARMInstr* ARMInstr_VMinMaxNum ( Bool isF64, Bool isMax,
+                                       HReg dst, HReg srcL, HReg srcR );
 extern ARMInstr* ARMInstr_FPSCR    ( Bool toFPSCR, HReg iReg );
 extern ARMInstr* ARMInstr_MFence   ( void );
 extern ARMInstr* ARMInstr_CLREX    ( void );

Modified: trunk/priv/host_arm_isel.c
==============================================================================
--- trunk/priv/host_arm_isel.c (original)
+++ trunk/priv/host_arm_isel.c Fri Jan 13 17:58:57 2017
@@ -5618,6 +5618,21 @@
             /* not a V8 target, so we can't select insns for this. */
             break;
          }
+         case Iop_MaxNumF64:
+         case Iop_MinNumF64: {
+            /* Same comments regarding V8 support as for Iop_RoundF64toInt. */
+            if (VEX_ARM_ARCHLEVEL(env->hwcaps) >= 8) {
+               HReg srcL  = iselDblExpr(env, e->Iex.Binop.arg1);
+               HReg srcR  = iselDblExpr(env, e->Iex.Binop.arg2);
+               HReg dst   = newVRegD(env);
+               Bool isMax = e->Iex.Binop.op == Iop_MaxNumF64;
+               addInstr(env, ARMInstr_VMinMaxNum(
+                                True/*isF64*/, isMax, dst, srcL, srcR));
+               return dst;
+            }
+            /* not a V8 target, so we can't select insns for this. */
+            break;
+         }
          default:
             break;
       }
@@ -5775,6 +5790,21 @@
             /* not a V8 target, so we can't select insns for this. */
             break;
          }
+         case Iop_MaxNumF32:
+         case Iop_MinNumF32: {
+            /* Same comments regarding V8 support as for Iop_RoundF32toInt. */
+            if (VEX_ARM_ARCHLEVEL(env->hwcaps) >= 8) {
+               HReg srcL  = iselFltExpr(env, e->Iex.Binop.arg1);
+               HReg srcR  = iselFltExpr(env, e->Iex.Binop.arg2);
+               HReg dst   = newVRegF(env);
+               Bool isMax = e->Iex.Binop.op == Iop_MaxNumF32;
+               addInstr(env, ARMInstr_VMinMaxNum(
+                                False/*!isF64*/, isMax, dst, srcL, srcR));
+               return dst;
+            }
+            /* not a V8 target, so we can't select insns for this. */
+            break;
+         }
          default:
             break;
       }

Modified: trunk/priv/ir_defs.c
==============================================================================
--- trunk/priv/ir_defs.c (original)
+++ trunk/priv/ir_defs.c Fri Jan 13 17:58:57 2017
@@ -354,6 +354,11 @@
       case Iop_RecpExpF64: vex_printf("RecpExpF64"); return;
       case Iop_RecpExpF32: vex_printf("RecpExpF32"); return;
 
+      case Iop_MaxNumF64: vex_printf("MaxNumF64"); return;
+      case Iop_MinNumF64: vex_printf("MinNumF64"); return;
+      case Iop_MaxNumF32: vex_printf("MaxNumF32"); return;
+      case Iop_MinNumF32: vex_printf("MinNumF32"); return;
+
       case Iop_F16toF64: vex_printf("F16toF64"); return;
       case Iop_F64toF16: vex_printf("F64toF16"); return;
       case Iop_F16toF32: vex_printf("F16toF32"); return;
@@ -2838,7 +2843,13 @@
       case Iop_RecpExpF32:
          BINARY(ity_RMode,Ity_F32, Ity_F32);
 
-      case Iop_CmpF32:
+      case Iop_MaxNumF64: case Iop_MinNumF64:
+         BINARY(Ity_F64,Ity_F64, Ity_F64);
+
+      case Iop_MaxNumF32: case Iop_MinNumF32:
+         BINARY(Ity_F32,Ity_F32, Ity_F32);
+
+     case Iop_CmpF32:
          BINARY(Ity_F32,Ity_F32, Ity_I32);
 
       case Iop_CmpF64:

Modified: trunk/pub/libvex_ir.h
==============================================================================
--- trunk/pub/libvex_ir.h (original)
+++ trunk/pub/libvex_ir.h Fri Jan 13 17:58:57 2017
@@ -776,6 +776,13 @@
       Iop_RecpExpF64,  /* FRECPX d  :: IRRoundingMode(I32) x F64 -> F64 */
       Iop_RecpExpF32,  /* FRECPX s  :: IRRoundingMode(I32) x F32 -> F32 */
 
+      /* --------- Possibly required by IEEE 754-2008. --------- */
+
+      Iop_MaxNumF64,  /* max, F64, numerical operand if other is a qNaN */
+      Iop_MinNumF64,  /* min, F64, ditto */
+      Iop_MaxNumF32,  /* max, F32, ditto */
+      Iop_MinNumF32,  /* min, F32, ditto */
+
       /* ------------------ 16-bit scalar FP ------------------ */
 
       Iop_F16toF64,  /*                       F16 -> F64 */


------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today. http://sdm.link/xeonphi
_______________________________________________
Valgrind-developers mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/valgrind-developers
Loading...