]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Copy-n-paste 32x4 floating point stuff into 64x2 floating point stuff so
authorJulian Seward <jseward@acm.org>
Tue, 7 Dec 2004 11:16:04 +0000 (11:16 +0000)
committerJulian Seward <jseward@acm.org>
Tue, 7 Dec 2004 11:16:04 +0000 (11:16 +0000)
as to form a basis for SSE2 floating point support.

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

VEX/priv/guest-x86/toIR.c
VEX/priv/host-x86/hdefs.c
VEX/priv/host-x86/hdefs.h
VEX/priv/host-x86/isel.c
VEX/priv/ir/irdefs.c
VEX/pub/libvex_ir.h

index b5b18a5441f0b75fea10d835ccdcaa995ff9bf4c..72c2c99956478b2ce495e18a8430bdf5d970831c 100644 (file)
@@ -6991,6 +6991,40 @@ static UInt dis_SSE_E_to_G_lo32 ( UChar sorb, UInt delta,
    }
 }
 
+/* Lower 64-bit lane only SSE binary operation, G = G `op` E. */
+
+static UInt dis_SSE_E_to_G_lo64 ( UChar sorb, UInt delta, 
+                                  HChar* opname, IROp op )
+{
+   HChar   dis_buf[50];
+   Int     alen;
+   IRTemp  addr;
+   UChar   rm = getIByte(delta);
+   IRExpr* gpart = getXMMReg(gregOfRM(rm));
+   if (epartIsReg(rm)) {
+      putXMMReg( gregOfRM(rm), 
+                 binop(op, gpart,
+                           getXMMReg(eregOfRM(rm))) );
+      DIP("%s %s,%s\n", opname,
+                        nameXMMReg(eregOfRM(rm)),
+                        nameXMMReg(gregOfRM(rm)) );
+      return delta+1;
+   } else {
+      /* We can only do a 64-bit memory read, so the upper half of the
+         E operand needs to be made simply of zeroes. */
+      IRTemp epart = newTemp(Ity_V128);
+      addr = disAMode ( &alen, sorb, delta, dis_buf );
+      assign( epart, unop( Iop_64Uto128,
+                           loadLE(Ity_I64, mkexpr(addr))) );
+      putXMMReg( gregOfRM(rm), 
+                 binop(op, gpart, mkexpr(epart)) );
+      DIP("%s %s,%s\n", opname,
+                        dis_buf,
+                        nameXMMReg(gregOfRM(rm)) );
+      return delta+alen;
+   }
+}
+
 /* All lanes unary SSE operation, G = op(E). */
 
 static UInt dis_SSE_E_to_G_unary_all ( 
@@ -7155,6 +7189,12 @@ static IRExpr* /* :: Ity_I32 */ get_sse_roundingmode ( void )
                  mkU32(3) );
 }
 
+static void put_sse_roundingmode ( IRExpr* sseround )
+{
+   vassert(typeOfIRExpr(irbb->tyenv, sseround) == Ity_I32);
+   stmt( IRStmt_Put( OFFB_SSEROUND, sseround ) );
+}
+
 /* Break a 128-bit value up into four 32-bit ints. */
 
 static void breakup128to32s ( IRTemp t128,
@@ -7326,8 +7366,7 @@ static DisResult disInstr ( /*IN*/  Bool    resteerOK,
    insn = (UChar*)&guest_code[delta];
 
    /* 0F 58 = ADDPS -- add 32Fx4 from R/M to R */
-   if (insn[0] == 0x0F && insn[1] == 0x58) {
-      vassert(sz == 4);
+   if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x58) {
       delta = dis_SSE_E_to_G_all( sorb, delta+2, "addps", Iop_Add32Fx4 );
       goto decode_success;
    }
@@ -7340,22 +7379,19 @@ static DisResult disInstr ( /*IN*/  Bool    resteerOK,
    }
 
    /* 0F 55 = ANDNPS -- G = (not G) and E */
-   if (insn[0] == 0x0F && insn[1] == 0x55) {
-      vassert(sz == 4);
+   if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x55) {
       delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "andnps", Iop_And128 );
       goto decode_success;
    }
 
    /* 0F 54 = ANDPS -- G = G and E */
-   if (insn[0] == 0x0F && insn[1] == 0x54) {
-      vassert(sz == 4);
+   if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x54) {
       delta = dis_SSE_E_to_G_all( sorb, delta+2, "andps", Iop_And128 );
       goto decode_success;
    }
 
    /* 0F C2 = CMPPS -- 32Fx4 comparison from R/M to R */
-   if (insn[0] == 0x0F && insn[1] == 0xC2) {
-      vassert(sz == 4);
+   if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xC2) {
       delta = dis_SSEcmp_E_to_G( sorb, delta+2, "cmpps", True, 4 );
       goto decode_success;
    }
@@ -7621,7 +7657,7 @@ static DisResult disInstr ( /*IN*/  Bool    resteerOK,
                    )
             );
 
-      //put_sseround( unop(Iop_64to32, mkexpr(t64)) );
+      put_sse_roundingmode( unop(Iop_64to32, mkexpr(t64)) );
       assign( ew, unop(Iop_64HIto32, mkexpr(t64) ) );
       put_emwarn( mkexpr(ew) );
       /* Finally, if an emulation warning was reported, side-exit to
@@ -8386,6 +8422,42 @@ static DisResult disInstr ( /*IN*/  Bool    resteerOK,
       goto decode_success;
    }
 
+   /* ---------------------------------------------------- */
+   /* --- end of the SSE decoder.                      --- */
+   /* ---------------------------------------------------- */
+
+   /* ---------------------------------------------------- */
+   /* --- start of the SSE2 decoder.                   --- */
+   /* ---------------------------------------------------- */
+
+   insn = (UChar*)&guest_code[delta];
+
+   /* 66 0F 58 = ADDPD -- add 32Fx4 from R/M to R */
+   if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x58) {
+      delta = dis_SSE_E_to_G_all( sorb, delta+2, "addpd", Iop_Add64Fx2 );
+      goto decode_success;
+   }
+   /* F2 0F 58 = ADDSD -- add 64F0x2 from R/M to R */
+   if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x58) {
+      vassert(sz == 4);
+      delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "addsd", Iop_Add64F0x2 );
+      goto decode_success;
+   }
+
+   /* 66 0F 55 = ANDNPD -- G = (not G) and E */
+   if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x55) {
+      delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "andnpd", Iop_And128 );
+      goto decode_success;
+   }
+
+   /* 66 0F 54 = ANDPD -- G = G and E */
+   if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x54) {
+      delta = dis_SSE_E_to_G_all( sorb, delta+2, "andpd", Iop_And128 );
+      goto decode_success;
+   }
+
+
 //-- 
 //--    /* FXSAVE/FXRSTOR m32 -- load/store the FPU/MMX/SSE state. */
 //--    if (insn[0] == 0x0F && insn[1] == 0xAE 
index c070507d0ab29d9cda75f8579950779c52be697e..380ac563188e8b796cb0b8790f272449aa037a08 100644 (file)
@@ -765,7 +765,7 @@ X86Instr* X86Instr_Sse128 ( X86SseOp op, HReg src, HReg dst ) {
            || op == Xsse_AND || op == Xsse_OR || op == Xsse_XOR);
    return i;
 }
-X86Instr* X86Instr_Sse32Fx4  ( X86SseOp op, HReg src, HReg dst ) {
+X86Instr* X86Instr_Sse32Fx4 ( X86SseOp op, HReg src, HReg dst ) {
    X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
    i->tag              = Xin_Sse32Fx4;
    i->Xin.Sse32Fx4.op  = op;
@@ -773,7 +773,7 @@ X86Instr* X86Instr_Sse32Fx4  ( X86SseOp op, HReg src, HReg dst ) {
    i->Xin.Sse32Fx4.dst = dst;
    return i;
 }
-X86Instr* X86Instr_Sse32FLo  ( X86SseOp op, HReg src, HReg dst ) {
+X86Instr* X86Instr_Sse32FLo ( X86SseOp op, HReg src, HReg dst ) {
    X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
    i->tag              = Xin_Sse32FLo;
    i->Xin.Sse32FLo.op  = op;
@@ -781,6 +781,22 @@ X86Instr* X86Instr_Sse32FLo  ( X86SseOp op, HReg src, HReg dst ) {
    i->Xin.Sse32FLo.dst = dst;
    return i;
 }
+X86Instr* X86Instr_Sse64Fx2 ( X86SseOp op, HReg src, HReg dst ) {
+   X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
+   i->tag              = Xin_Sse64Fx2;
+   i->Xin.Sse64Fx2.op  = op;
+   i->Xin.Sse64Fx2.src = src;
+   i->Xin.Sse64Fx2.dst = dst;
+   return i;
+}
+X86Instr* X86Instr_Sse64FLo ( X86SseOp op, HReg src, HReg dst ) {
+   X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
+   i->tag              = Xin_Sse64FLo;
+   i->Xin.Sse64FLo.op  = op;
+   i->Xin.Sse64FLo.src = src;
+   i->Xin.Sse64FLo.dst = dst;
+   return i;
+}
 
 void ppX86Instr ( X86Instr* i ) {
    switch (i->tag) {
@@ -1007,6 +1023,18 @@ void ppX86Instr ( X86Instr* i ) {
          vex_printf(",");
          ppHRegX86(i->Xin.Sse32FLo.dst);
          return;
+      case Xin_Sse64Fx2:
+         vex_printf("%spd ", showX86SseOp(i->Xin.Sse64Fx2.op));
+         ppHRegX86(i->Xin.Sse64Fx2.src);
+         vex_printf(",");
+         ppHRegX86(i->Xin.Sse64Fx2.dst);
+         return;
+      case Xin_Sse64FLo:
+         vex_printf("%ssd ", showX86SseOp(i->Xin.Sse64FLo.op));
+         ppHRegX86(i->Xin.Sse64FLo.src);
+         vex_printf(",");
+         ppHRegX86(i->Xin.Sse64FLo.dst);
+         return;
 
       default:
          vpanic("ppX86Instr");
@@ -1198,6 +1226,24 @@ void getRegUsage_X86Instr (HRegUsage* u, X86Instr* i)
          addHRegUse(u, unary ? HRmWrite : HRmModify, 
                        i->Xin.Sse32FLo.dst);
          return;
+      case Xin_Sse64Fx2:
+         vassert(i->Xin.Sse64Fx2.op != Xsse_MOV);
+         unary = i->Xin.Sse64Fx2.op == Xsse_RCPF
+                 || i->Xin.Sse64Fx2.op == Xsse_RSQRTF
+                 || i->Xin.Sse64Fx2.op == Xsse_SQRTF;
+         addHRegUse(u, HRmRead, i->Xin.Sse64Fx2.src);
+         addHRegUse(u, unary ? HRmWrite : HRmModify, 
+                       i->Xin.Sse64Fx2.dst);
+         return;
+      case Xin_Sse64FLo:
+         vassert(i->Xin.Sse64FLo.op != Xsse_MOV);
+         unary = i->Xin.Sse64FLo.op == Xsse_RCPF
+                 || i->Xin.Sse64FLo.op == Xsse_RSQRTF
+                 || i->Xin.Sse64FLo.op == Xsse_SQRTF;
+         addHRegUse(u, HRmRead, i->Xin.Sse64FLo.src);
+         addHRegUse(u, unary ? HRmWrite : HRmModify, 
+                       i->Xin.Sse64FLo.dst);
+         return;
       default:
          ppX86Instr(i);
          vpanic("getRegUsage_X86Instr");
@@ -1326,6 +1372,14 @@ void mapRegs_X86Instr (HRegRemap* m, X86Instr* i)
          mapReg(m, &i->Xin.Sse32FLo.src);
          mapReg(m, &i->Xin.Sse32FLo.dst);
          return;
+      case Xin_Sse64Fx2:
+         mapReg(m, &i->Xin.Sse64Fx2.src);
+         mapReg(m, &i->Xin.Sse64Fx2.dst);
+         return;
+      case Xin_Sse64FLo:
+         mapReg(m, &i->Xin.Sse64FLo.src);
+         mapReg(m, &i->Xin.Sse64FLo.dst);
+         return;
       default:
          ppX86Instr(i);
          vpanic("mapRegs_X86Instr");
@@ -2427,16 +2481,14 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
       goto done;
 
    case Xin_SseLdzLO:
-      if (i->Xin.SseLdzLO.sz == 4) {
-         /* movss amode, %xmm-dst */
-         *p++ = 0xF3; 
-         *p++ = 0x0F; 
-         *p++ = 0x10; 
-         p = doAMode_M(p, fake(vregNo(i->Xin.SseLdzLO.reg)), 
-                          i->Xin.SseLdzLO.addr);
-         goto done;
-      }
-      break;
+      vassert(i->Xin.SseLdzLO.sz == 4 || i->Xin.SseLdzLO.sz == 8);
+      /* movs[sd] amode, %xmm-dst */
+      *p++ = i->Xin.SseLdzLO.sz==4 ? 0xF3 : 0xF2;
+      *p++ = 0x0F; 
+      *p++ = 0x10; 
+      p = doAMode_M(p, fake(vregNo(i->Xin.SseLdzLO.reg)), 
+                       i->Xin.SseLdzLO.addr);
+      goto done;
 
    case Xin_Sse128:
       *p++ = 0x0F;
@@ -2475,6 +2527,31 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
          *p++ = (UChar)(xtra & 0xFF);
       goto done;
 
+   case Xin_Sse64Fx2:
+      xtra = 0;
+      *p++ = 0x66;
+      *p++ = 0x0F;
+      switch (i->Xin.Sse64Fx2.op) {
+         case Xsse_ADDF:   *p++ = 0x58; break;
+         case Xsse_DIVF:   *p++ = 0x5E; break;
+         case Xsse_MAXF:   *p++ = 0x5F; break;
+         case Xsse_MINF:   *p++ = 0x5D; break;
+         case Xsse_MULF:   *p++ = 0x59; break;
+         case Xsse_RCPF:   *p++ = 0x53; break;
+         case Xsse_RSQRTF: *p++ = 0x52; break;
+         case Xsse_SQRTF:  *p++ = 0x51; break;
+         case Xsse_SUBF:   *p++ = 0x5C; break;
+         case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
+         case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
+         case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
+         default: goto bad;
+      }
+      p = doAMode_R(p, fake(vregNo(i->Xin.Sse64Fx2.dst)),
+                       fake(vregNo(i->Xin.Sse64Fx2.src)) );
+      if (xtra & 0x100)
+         *p++ = (UChar)(xtra & 0xFF);
+      goto done;
+
    case Xin_Sse32FLo:
       xtra = 0;
       *p++ = 0xF3;
@@ -2500,6 +2577,31 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
          *p++ = (UChar)(xtra & 0xFF);
       goto done;
 
+   case Xin_Sse64FLo:
+      xtra = 0;
+      *p++ = 0xF2;
+      *p++ = 0x0F;
+      switch (i->Xin.Sse64FLo.op) {
+         case Xsse_ADDF:   *p++ = 0x58; break;
+         case Xsse_DIVF:   *p++ = 0x5E; break;
+         case Xsse_MAXF:   *p++ = 0x5F; break;
+         case Xsse_MINF:   *p++ = 0x5D; break;
+         case Xsse_MULF:   *p++ = 0x59; break;
+         case Xsse_RCPF:   *p++ = 0x53; break;
+         case Xsse_RSQRTF: *p++ = 0x52; break;
+         case Xsse_SQRTF:  *p++ = 0x51; break;
+         case Xsse_SUBF:   *p++ = 0x5C; break;
+         case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
+         case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
+         case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
+         default: goto bad;
+      }
+      p = doAMode_R(p, fake(vregNo(i->Xin.Sse64FLo.dst)),
+                       fake(vregNo(i->Xin.Sse64FLo.src)) );
+      if (xtra & 0x100)
+         *p++ = (UChar)(xtra & 0xFF);
+      goto done;
+
    default: 
       goto bad;
    }
index 64d57a40aaf66b7e005261d7ae3e6ec821729c76..7c16b86472cf96fa69388027d5690eb5928d1e54 100644 (file)
@@ -353,9 +353,9 @@ typedef
       Xin_SseLdzLO,  /* SSE load low 32/64 bits, zero remainder of reg */
       Xin_Sse128,    /* SSE binary typeless (and/or/xor/andn) */
       Xin_Sse32Fx4,  /* SSE binary, 32Fx4 */
-      Xin_Sse32FLo   /* SSE binary, 32F in lowest lane only */
-      //      Xin_Sse64Fx2,  /* SSE binary, 64Fx2 */
-      //      Xin_Sse64FLo,  /* SSE binary, 64F in lowest lane only */
+      Xin_Sse32FLo,  /* SSE binary, 32F in lowest lane only */
+      Xin_Sse64Fx2,  /* SSE binary, 64Fx2 */
+      Xin_Sse64FLo   /* SSE binary, 64F in lowest lane only */
       /* Xin_SseUn32Fx4 */
    }
    X86InstrTag;
@@ -551,6 +551,16 @@ typedef
             HReg     src;
             HReg     dst;
          } Sse32FLo;
+         struct {
+            X86SseOp op;
+            HReg     src;
+            HReg     dst;
+         } Sse64Fx2;
+         struct {
+            X86SseOp op;
+            HReg     src;
+            HReg     dst;
+         } Sse64FLo;
 
       } Xin;
    }
@@ -590,6 +600,8 @@ extern X86Instr* X86Instr_SseLdzLO  ( Int sz, HReg, X86AMode* );
 extern X86Instr* X86Instr_Sse128    ( X86SseOp, HReg, HReg );
 extern X86Instr* X86Instr_Sse32Fx4  ( X86SseOp, HReg, HReg );
 extern X86Instr* X86Instr_Sse32FLo  ( X86SseOp, HReg, HReg );
+extern X86Instr* X86Instr_Sse64Fx2  ( X86SseOp, HReg, HReg );
+extern X86Instr* X86Instr_Sse64FLo  ( X86SseOp, HReg, HReg );
 
 
 extern void ppX86Instr ( X86Instr* );
index a617334a6c66e8f9f8d038a7bd55f90e0248495d..94467b3dfaf47b6c3c4b32efdf442c81a08e5976 100644 (file)
@@ -2437,6 +2437,17 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
          return dst;
       }
 
+      case Iop_Recip64Fx2: op = Xsse_RCPF;   goto do_64Fx2_unary;
+      case Iop_RSqrt64Fx2: op = Xsse_RSQRTF; goto do_64Fx2_unary;
+      case Iop_Sqrt64Fx2:  op = Xsse_SQRTF;  goto do_64Fx2_unary;
+      do_64Fx2_unary:
+      {
+         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
+         HReg dst = newVRegV(env);
+         addInstr(env, X86Instr_Sse64Fx2(op, arg, dst));
+         return dst;
+      }
+
       case Iop_Recip32F0x4: op = Xsse_RCPF;   goto do_32F0x4_unary;
       case Iop_RSqrt32F0x4: op = Xsse_RSQRTF; goto do_32F0x4_unary;
       case Iop_Sqrt32F0x4:  op = Xsse_SQRTF;  goto do_32F0x4_unary;
@@ -2455,6 +2466,24 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
          return dst;
       }
 
+      case Iop_Recip64F0x2: op = Xsse_RCPF;   goto do_64F0x2_unary;
+      case Iop_RSqrt64F0x2: op = Xsse_RSQRTF; goto do_64F0x2_unary;
+      case Iop_Sqrt64F0x2:  op = Xsse_SQRTF;  goto do_64F0x2_unary;
+      do_64F0x2_unary:
+      {
+         /* A bit subtle.  We have to copy the arg to the result
+            register first, because actually doing the SSE scalar insn
+            leaves the upper half of the destination register
+            unchanged.  Whereas the required semantics of these
+            primops is that the upper half is simply copied in from the
+            argument. */
+         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
+         HReg dst = newVRegV(env);
+         addInstr(env, mk_vMOVsd_RR(arg, dst));
+         addInstr(env, X86Instr_Sse64FLo(op, arg, dst));
+         return dst;
+      }
+
       case Iop_32Uto128: {
          HReg      dst  = newVRegV(env);
          X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
@@ -2465,6 +2494,18 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
          return dst;
       }
 
+      case Iop_64Uto128: {
+         HReg      rHi, rLo;
+         HReg      dst  = newVRegV(env);
+         X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
+         iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
+         addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));
+         addInstr(env, X86Instr_Push(X86RMI_Reg(rLo)));
+        addInstr(env, X86Instr_SseLdzLO(8, dst, esp0));
+         add_to_esp(env, 8);
+         return dst;
+      }
+
       default:
          break;
    } /* switch (e->Iex.Unop.op) */
@@ -2541,6 +2582,25 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
          return dst;
       }
 
+      case Iop_CmpEQ64Fx2: op = Xsse_CMPEQF; goto do_64Fx2;
+      case Iop_CmpLT64Fx2: op = Xsse_CMPLTF; goto do_64Fx2;
+      case Iop_CmpLE64Fx2: op = Xsse_CMPLEF; goto do_64Fx2;
+      case Iop_Add64Fx2:   op = Xsse_ADDF;   goto do_64Fx2;
+      case Iop_Div64Fx2:   op = Xsse_DIVF;   goto do_64Fx2;
+      case Iop_Max64Fx2:   op = Xsse_MAXF;   goto do_64Fx2;
+      case Iop_Min64Fx2:   op = Xsse_MINF;   goto do_64Fx2;
+      case Iop_Mul64Fx2:   op = Xsse_MULF;   goto do_64Fx2;
+      case Iop_Sub64Fx2:   op = Xsse_SUBF;   goto do_64Fx2;
+      do_64Fx2:
+      {
+         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
+         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
+         HReg dst = newVRegV(env);
+         addInstr(env, mk_vMOVsd_RR(argL, dst));
+         addInstr(env, X86Instr_Sse64Fx2(op, argR, dst));
+         return dst;
+      }
+
       case Iop_CmpEQ32F0x4: op = Xsse_CMPEQF; goto do_32F0x4;
       case Iop_CmpLT32F0x4: op = Xsse_CMPLTF; goto do_32F0x4;
       case Iop_CmpLE32F0x4: op = Xsse_CMPLEF; goto do_32F0x4;
@@ -2559,6 +2619,24 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
          return dst;
       }
 
+      case Iop_CmpEQ64F0x2: op = Xsse_CMPEQF; goto do_64F0x2;
+      case Iop_CmpLT64F0x2: op = Xsse_CMPLTF; goto do_64F0x2;
+      case Iop_CmpLE64F0x2: op = Xsse_CMPLEF; goto do_64F0x2;
+      case Iop_Add64F0x2:   op = Xsse_ADDF;   goto do_64F0x2;
+      case Iop_Div64F0x2:   op = Xsse_DIVF;   goto do_64F0x2;
+      case Iop_Max64F0x2:   op = Xsse_MAXF;   goto do_64F0x2;
+      case Iop_Min64F0x2:   op = Xsse_MINF;   goto do_64F0x2;
+      case Iop_Mul64F0x2:   op = Xsse_MULF;   goto do_64F0x2;
+      case Iop_Sub64F0x2:   op = Xsse_SUBF;   goto do_64F0x2;
+      do_64F0x2: {
+         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
+         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
+         HReg dst = newVRegV(env);
+         addInstr(env, mk_vMOVsd_RR(argL, dst));
+         addInstr(env, X86Instr_Sse64FLo(op, argR, dst));
+         return dst;
+      }
+
       default:
          break;
    } /* switch (e->Iex.Binop.op) */
index 7b90c922fb5158e2a3d218ef553c44d4addd9105..696143d789a1352ec247f79e39a4df3fa4835277 100644 (file)
@@ -227,46 +227,73 @@ void ppIROp ( IROp op )
 
       case Iop_Add32Fx4:  vex_printf("Add32Fx4"); return;
       case Iop_Add32F0x4: vex_printf("Add32F0x4"); return;
+      case Iop_Add64Fx2:  vex_printf("Add64Fx2"); return;
+      case Iop_Add64F0x2: vex_printf("Add64F0x2"); return;
 
       case Iop_Div32Fx4:  vex_printf("Div32Fx4"); return;
       case Iop_Div32F0x4: vex_printf("Div32F0x4"); return;
+      case Iop_Div64Fx2:  vex_printf("Div64Fx2"); return;
+      case Iop_Div64F0x2: vex_printf("Div64F0x2"); return;
 
       case Iop_Max32Fx4:  vex_printf("Max32Fx4"); return;
       case Iop_Max32F0x4: vex_printf("Max32F0x4"); return;
+      case Iop_Max64Fx2:  vex_printf("Max64Fx2"); return;
+      case Iop_Max64F0x2: vex_printf("Max64F0x2"); return;
 
       case Iop_Min32Fx4:  vex_printf("Min32Fx4"); return;
       case Iop_Min32F0x4: vex_printf("Min32F0x4"); return;
+      case Iop_Min64Fx2:  vex_printf("Min64Fx2"); return;
+      case Iop_Min64F0x2: vex_printf("Min64F0x2"); return;
 
       case Iop_Mul32Fx4:  vex_printf("Mul32Fx4"); return;
       case Iop_Mul32F0x4: vex_printf("Mul32F0x4"); return;
+      case Iop_Mul64Fx2:  vex_printf("Mul64Fx2"); return;
+      case Iop_Mul64F0x2: vex_printf("Mul64F0x2"); return;
 
       case Iop_Recip32Fx4:  vex_printf("Recip32Fx4"); return;
       case Iop_Recip32F0x4: vex_printf("Recip32F0x4"); return;
+      case Iop_Recip64Fx2:  vex_printf("Recip64Fx2"); return;
+      case Iop_Recip64F0x2: vex_printf("Recip64F0x2"); return;
 
       case Iop_RSqrt32Fx4:  vex_printf("RSqrt32Fx4"); return;
       case Iop_RSqrt32F0x4: vex_printf("RSqrt32F0x4"); return;
+      case Iop_RSqrt64Fx2:  vex_printf("RSqrt64Fx2"); return;
+      case Iop_RSqrt64F0x2: vex_printf("RSqrt64F0x2"); return;
 
-      case Iop_Sqrt32Fx4:   vex_printf("Sqrt32Fx4"); return;
-      case Iop_Sqrt32F0x4 : vex_printf("Sqrt32F0x4"); return;
+      case Iop_Sqrt32Fx4:  vex_printf("Sqrt32Fx4"); return;
+      case Iop_Sqrt32F0x4: vex_printf("Sqrt32F0x4"); return;
+      case Iop_Sqrt64Fx2:  vex_printf("Sqrt64Fx2"); return;
+      case Iop_Sqrt64F0x2: vex_printf("Sqrt64F0x2"); return;
 
       case Iop_Sub32Fx4:  vex_printf("Sub32Fx4"); return;
       case Iop_Sub32F0x4: vex_printf("Sub32F0x4"); return;
+      case Iop_Sub64Fx2:  vex_printf("Sub64Fx2"); return;
+      case Iop_Sub64F0x2: vex_printf("Sub64F0x2"); return;
 
       case Iop_CmpEQ32Fx4: vex_printf("CmpEQ32Fx4"); return;
       case Iop_CmpLT32Fx4: vex_printf("CmpLT32Fx4"); return;
       case Iop_CmpLE32Fx4: vex_printf("CmpLE32Fx4"); return;
       case Iop_CmpUN32Fx4: vex_printf("CmpUN32Fx4"); return;
+      case Iop_CmpEQ64Fx2: vex_printf("CmpEQ64Fx2"); return;
+      case Iop_CmpLT64Fx2: vex_printf("CmpLT64Fx2"); return;
+      case Iop_CmpLE64Fx2: vex_printf("CmpLE64Fx2"); return;
+      case Iop_CmpUN64Fx2: vex_printf("CmpUN64Fx2"); return;
 
       case Iop_CmpEQ32F0x4: vex_printf("CmpEQ32F0x4"); return;
       case Iop_CmpLT32F0x4: vex_printf("CmpLT32F0x4"); return;
       case Iop_CmpLE32F0x4: vex_printf("CmpLE32F0x4"); return;
       case Iop_CmpUN32F0x4: vex_printf("CmpUN32F0x4"); return;
+      case Iop_CmpEQ64F0x2: vex_printf("CmpEQ64F0x2"); return;
+      case Iop_CmpLT64F0x2: vex_printf("CmpLT64F0x2"); return;
+      case Iop_CmpLE64F0x2: vex_printf("CmpLE64F0x2"); return;
+      case Iop_CmpUN64F0x2: vex_printf("CmpUN64F0x2"); return;
 
       case Iop_64HLto128: vex_printf("64HLto128"); return;
       case Iop_128to64:   vex_printf("128to64");   return;
       case Iop_128HIto64: vex_printf("128HIto64"); return;
 
       case Iop_32Uto128:   vex_printf("32Uto128"); return;
+      case Iop_64Uto128:   vex_printf("64Uto128"); return;
       case Iop_Set128lo32: vex_printf("Set128lo32"); return;
 
       default: vpanic("ppIROp(1)");
@@ -1126,24 +1153,38 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 )
          UNARY(Ity_I64, Ity_V128);
 
       case Iop_32Uto128:   UNARY(Ity_V128, Ity_I32);
+      case Iop_64Uto128:   UNARY(Ity_V128, Ity_I64);
       case Iop_Set128lo32: BINARY(Ity_V128, Ity_V128,Ity_I32);
 
       case Iop_CmpEQ32Fx4: case Iop_CmpLT32Fx4:
+      case Iop_CmpEQ64Fx2: case Iop_CmpLT64Fx2:
       case Iop_CmpLE32Fx4: case Iop_CmpUN32Fx4:
+      case Iop_CmpLE64Fx2: case Iop_CmpUN64Fx2:
       case Iop_CmpEQ32F0x4: case Iop_CmpLT32F0x4:
+      case Iop_CmpEQ64F0x2: case Iop_CmpLT64F0x2:
       case Iop_CmpLE32F0x4: case Iop_CmpUN32F0x4:
+      case Iop_CmpLE64F0x2: case Iop_CmpUN64F0x2:
       case Iop_Add32Fx4: case Iop_Add32F0x4:
+      case Iop_Add64Fx2: case Iop_Add64F0x2:
       case Iop_Div32Fx4: case Iop_Div32F0x4:
+      case Iop_Div64Fx2: case Iop_Div64F0x2:
       case Iop_Max32Fx4: case Iop_Max32F0x4:
+      case Iop_Max64Fx2: case Iop_Max64F0x2:
       case Iop_Min32Fx4: case Iop_Min32F0x4:
+      case Iop_Min64Fx2: case Iop_Min64F0x2:
       case Iop_Mul32Fx4: case Iop_Mul32F0x4:
+      case Iop_Mul64Fx2: case Iop_Mul64F0x2:
       case Iop_Sub32Fx4: case Iop_Sub32F0x4:
+      case Iop_Sub64Fx2: case Iop_Sub64F0x2:
       case Iop_And128: case Iop_Or128: case Iop_Xor128:
          BINARY(Ity_V128, Ity_V128,Ity_V128);
 
       case Iop_Recip32Fx4: case Iop_Recip32F0x4:
+      case Iop_Recip64Fx2: case Iop_Recip64F0x2:
       case Iop_RSqrt32Fx4: case Iop_RSqrt32F0x4:
+      case Iop_RSqrt64Fx2: case Iop_RSqrt64F0x2:
       case Iop_Sqrt32Fx4:  case Iop_Sqrt32F0x4:
+      case Iop_Sqrt64Fx2:  case Iop_Sqrt64F0x2:
          UNARY(Ity_V128, Ity_V128);
 
       default:
index 581ecbcd5934914e123607b39d8f014915af450c..fe3b1b201554b9facf0222b2dfafbbb2a6249d13 100644 (file)
@@ -337,12 +337,9 @@ typedef
       Iop_Add32Fx4, Iop_Sub32Fx4, Iop_Mul32Fx4, Iop_Div32Fx4, 
       Iop_Max32Fx4, Iop_Min32Fx4,
       Iop_CmpEQ32Fx4, Iop_CmpLT32Fx4, Iop_CmpLE32Fx4, Iop_CmpUN32Fx4, 
-      Iop_CmpEQ32F0x4, Iop_CmpLT32F0x4, Iop_CmpLE32F0x4, Iop_CmpUN32F0x4, 
 
       /* unary */
       Iop_Recip32Fx4, Iop_Sqrt32Fx4, Iop_RSqrt32Fx4,
-      //Iop_ItoF32x4, /* first arg is IRRoundingMode (Ity_I32) */
-      //Iop_FtoI32x4, /* first arg is IRRoundingMode (Ity_I32) */
 
       /* --- 32x4 lowest-lane-only scalar FP --- */
 
@@ -352,11 +349,33 @@ typedef
       /* binary */
       Iop_Add32F0x4, Iop_Sub32F0x4, Iop_Mul32F0x4, Iop_Div32F0x4, 
       Iop_Max32F0x4, Iop_Min32F0x4,
+      Iop_CmpEQ32F0x4, Iop_CmpLT32F0x4, Iop_CmpLE32F0x4, Iop_CmpUN32F0x4, 
 
       /* unary */
       Iop_Recip32F0x4, Iop_Sqrt32F0x4, Iop_RSqrt32F0x4,
-      //Iop_ItoF320x4, /* first arg is IRRoundingMode (Ity_I32) */
-      //Iop_FtoI320x4, /* first arg is IRRoundingMode (Ity_I32) */
+
+      /* --- 64x2 vector FP --- */
+
+      /* binary */
+      Iop_Add64Fx2, Iop_Sub64Fx2, Iop_Mul64Fx2, Iop_Div64Fx2, 
+      Iop_Max64Fx2, Iop_Min64Fx2,
+      Iop_CmpEQ64Fx2, Iop_CmpLT64Fx2, Iop_CmpLE64Fx2, Iop_CmpUN64Fx2, 
+
+      /* unary */
+      Iop_Recip64Fx2, Iop_Sqrt64Fx2, Iop_RSqrt64Fx2,
+
+      /* --- 64x2 lowest-lane-only scalar FP --- */
+
+      /* In binary cases, upper half is copied from first operand.  In
+        unary cases, upper half is copied from the operand. */
+
+      /* binary */
+      Iop_Add64F0x2, Iop_Sub64F0x2, Iop_Mul64F0x2, Iop_Div64F0x2, 
+      Iop_Max64F0x2, Iop_Min64F0x2,
+      Iop_CmpEQ64F0x2, Iop_CmpLT64F0x2, Iop_CmpLE64F0x2, Iop_CmpUN64F0x2, 
+
+      /* unary */
+      Iop_Recip64F0x2, Iop_Sqrt64F0x2, Iop_RSqrt64F0x2,
 
       /* --- pack / unpack --- */
 
@@ -366,6 +385,7 @@ typedef
       Iop_64HLto128,   // :: (I64,I64) -> V128
 
       Iop_32Uto128,
+      Iop_64Uto128,
       Iop_Set128lo32,
       /* 128 -> 32 bit unpack */
       //Iop_128W3to32,   // :: V128 -> I32, bits 127-96