]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
x86 guest/host: fix enough 128-bit vector stuff that memcheck works for
authorJulian Seward <jseward@acm.org>
Sun, 12 Dec 2004 16:46:47 +0000 (16:46 +0000)
committerJulian Seward <jseward@acm.org>
Sun, 12 Dec 2004 16:46:47 +0000 (16:46 +0000)
SSE2.  Added a new Iop_Not128 bit primop and generate at least tolerable
SSE code for it.

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

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

index 7a337517ba3db457bf7392b7b5dd95d6697dcf8c..a67c8d3355d4c5f6afa8576e40cc9985cecdddaa 100644 (file)
@@ -6283,9 +6283,7 @@ static UInt dis_SSE_E_to_G_all_wrk (
    IRTemp  addr;
    UChar   rm = getIByte(delta);
    IRExpr* gpart
-      = invertG ? binop( Iop_Xor128, 
-                         getXMMReg(gregOfRM(rm)), 
-                         mkV128(0xFFFF) )
+      = invertG ? unop(Iop_Not128, getXMMReg(gregOfRM(rm)))
                 : getXMMReg(gregOfRM(rm));
    if (epartIsReg(rm)) {
       putXMMReg( gregOfRM(rm), 
@@ -6638,14 +6636,20 @@ static UInt dis_SSEcmp_E_to_G ( UChar sorb, UInt delta,
                             nameXMMReg(gregOfRM(rm)) );
    }
 
-   if (needNot && all_lanes)
-      mask = 0xFFFF;
-   if (needNot && !all_lanes)
+   if (needNot && all_lanes) {
+      putXMMReg( gregOfRM(rm), 
+                 unop(Iop_Not128, mkexpr(plain)) );
+   }
+   else
+   if (needNot && !all_lanes) {
       mask = sz==4 ? 0x000F : 0x00FF;
+      putXMMReg( gregOfRM(rm), 
+                 binop(Iop_Xor128, mkexpr(plain), mkV128(mask)) );
+   }
+   else {
+      putXMMReg( gregOfRM(rm), mkexpr(plain) );
+   }
 
-   putXMMReg( gregOfRM(rm), 
-              needNot ? binop(Iop_Xor128, mkexpr(plain), mkV128(mask))
-                      : mkexpr(plain) );
    return delta;
 }
 
index cdc6287b879eb56b73a3d062ed938bcb96d0e183..f7445c3560428c5662873876aee663ae9df42735 100644 (file)
@@ -698,6 +698,25 @@ void set_FPU_rounding_mode ( ISelEnv* env, IRExpr* mode )
 }
 
 
+/* Generate !src into a new vector register, and be sure that the code
+   is SSE1 compatible.  Amazing that Intel doesn't offer a less crappy
+   way to do this. 
+*/
+static HReg do_sse_Not128 ( ISelEnv* env, HReg src )
+{
+   HReg dst = newVRegV(env);
+   /* Set dst to zero.  Not strictly necessary, but the idea of doing
+      a FP comparison on whatever junk happens to be floating around
+      in it is just too scary. */
+   addInstr(env, X86Instr_SseReRg(Xsse_XOR, dst, dst));
+   /* And now make it all 1s ... */
+   addInstr(env, X86Instr_Sse32Fx4(Xsse_CMPEQF, dst, dst));
+   /* Finally, xor 'src' into it. */
+   addInstr(env, X86Instr_SseReRg(Xsse_XOR, src, dst));
+   return dst;
+}
+
+
 /*---------------------------------------------------------*/
 /*--- ISEL: Integer expressions (32/16/8 bit)           ---*/
 /*---------------------------------------------------------*/
@@ -2461,8 +2480,13 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
    if (e->tag == Iex_Unop) {
    switch (e->Iex.Unop.op) {
 
+      case Iop_Not128: {
+         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
+         return do_sse_Not128(env, arg);
+      }
+
       case Iop_CmpNEZ64x2: {
-         /* only needed for sse2, so can use sse2 code */
+         /* We can use SSE2 instructions for this. */
          /* Ideally, we want to do a 64Ix2 comparison against zero of
             the operand.  Problem is no such insn exists.  Solution
             therefore is to do a 32Ix4 comparison instead, and bitwise-
@@ -2477,29 +2501,20 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
             literal value is 0xB1, that is, 
             (2 << 6) | (3 << 4) | (0 << 2) | (1 << 0) 
          */
-         X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg);
          HReg tmp  = newVRegV(env);
          HReg dst  = newVRegV(env);
-         HReg ones = newVRegV(env);
-         HReg r32  = newVRegI(env);
-         addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0xFFFFFFFF), r32));
-         addInstr(env, X86Instr_Push(X86RMI_Reg(r32)));
-         addInstr(env, X86Instr_Push(X86RMI_Reg(r32)));
-         addInstr(env, X86Instr_Push(X86RMI_Reg(r32)));
-         addInstr(env, X86Instr_Push(X86RMI_Reg(r32)));
-         addInstr(env, X86Instr_SseLdSt(True/*load*/, ones, esp0));
-         add_to_esp(env, 16);
          addInstr(env, X86Instr_SseReRg(Xsse_XOR, tmp, tmp));
          addInstr(env, X86Instr_SseReRg(Xsse_CMPEQ32, arg, tmp));
-         addInstr(env, X86Instr_SseReRg(Xsse_XOR, ones, tmp));
+         tmp = do_sse_Not128(env, tmp);
          addInstr(env, X86Instr_SseShuf(0xB1, tmp, dst));
          addInstr(env, X86Instr_SseReRg(Xsse_OR, tmp, dst));
          return dst;
       }
 
       case Iop_CmpNEZ32x4: {
-         /* sigh, we have to generate crappy code for SSE1 */
+         /* Sigh, we have to generate lousy code since this has to
+            work on SSE1 hosts */
          /* basically, the idea is: for each lane:
                movl lane, %r ; negl %r   (now CF = lane==0 ? 0 : 1)
                sbbl %r, %r               (now %r = 1Sto32(CF))
@@ -2525,6 +2540,31 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
          return dst;
       }
 
+      case Iop_CmpNEZ8x16:
+      case Iop_CmpNEZ16x8: {
+         /* We can use SSE2 instructions for this. */
+         HReg arg;
+         HReg vec0 = newVRegV(env);
+         HReg vec1 = newVRegV(env);
+         HReg dst  = newVRegV(env);
+         X86SseOp cmpOp 
+            = e->Iex.Unop.op==Iop_CmpNEZ16x8 ? Xsse_CMPEQ16
+                                             : Xsse_CMPEQ8;
+         addInstr(env, X86Instr_SseReRg(Xsse_XOR, vec0, vec0));
+         addInstr(env, mk_vMOVsd_RR(vec0, vec1));
+         addInstr(env, X86Instr_Sse32Fx4(Xsse_CMPEQF, vec1, vec1));
+         /* defer arg computation to here so as to give CMPEQF as long
+            as possible to complete */
+         arg = iselVecExpr(env, e->Iex.Unop.arg);
+         /* vec0 is all 0s; vec1 is all 1s */
+         addInstr(env, mk_vMOVsd_RR(arg, dst));
+         /* 16x8 or 8x16 comparison == */
+         addInstr(env, X86Instr_SseReRg(cmpOp, vec0, dst));
+         /* invert result */
+         addInstr(env, X86Instr_SseReRg(Xsse_XOR, vec1, dst));
+         return dst;
+      }
+
       case Iop_Recip32Fx4: op = Xsse_RCPF;   goto do_32Fx4_unary;
       case Iop_RSqrt32Fx4: op = Xsse_RSQRTF; goto do_32Fx4_unary;
       case Iop_Sqrt32Fx4:  op = Xsse_SQRTF;  goto do_32Fx4_unary;
index 52482043cf58601458d8fca3207a09750c897764..a71a27cd51286ec7a94e7e5cec9440134bd3f08d 100644 (file)
@@ -297,9 +297,12 @@ void ppIROp ( IROp op )
       case Iop_128to32:    vex_printf("128to32"); return;
       case Iop_Set128lo32: vex_printf("Set128lo32"); return;
 
+      case Iop_Not128:     vex_printf("Not128"); return;
       case Iop_And128:     vex_printf("And128"); return;
       case Iop_Or128:      vex_printf("Or128");  return;
       case Iop_Xor128:     vex_printf("Xor128"); return;
+      case Iop_CmpNEZ8x16: vex_printf("CmpNEZ8x16"); return;
+      case Iop_CmpNEZ16x8: vex_printf("CmpNEZ16x8"); return;
       case Iop_CmpNEZ32x4: vex_printf("CmpNEZ32x4"); return;
       case Iop_CmpNEZ64x2: vex_printf("CmpNEZ64x2"); return;
 
@@ -1274,12 +1277,14 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 )
       case Iop_InterleaveLO32x4: case Iop_InterleaveLO64x2:
          BINARY(Ity_V128, Ity_V128,Ity_V128);
 
+      case Iop_Not128:
       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:
+      case Iop_CmpNEZ8x16: case Iop_CmpNEZ16x8:
       case Iop_CmpNEZ32x4: case Iop_CmpNEZ64x2:
          UNARY(Ity_V128, Ity_V128);
 
index 11d1699ac96a3a5ef7e35d2a92436d3759971bc3..8d1f8b2ccea2fa1f9152c4b33089dc081d4e8629 100644 (file)
@@ -393,10 +393,11 @@ typedef
       /* ------------------ 128-bit SIMD Integer. ------------------ */
 
       /* BITWISE OPS */
+      Iop_Not128,
       Iop_And128, Iop_Or128, Iop_Xor128, 
 
-      /* MISC (32x4 integer cmp != 0) */
-      Iop_CmpNEZ32x4, Iop_CmpNEZ64x2,
+      /* MISC (vector integer cmp != 0) */
+      Iop_CmpNEZ8x16, Iop_CmpNEZ16x8, Iop_CmpNEZ32x4, Iop_CmpNEZ64x2,
 
       /* ADDITION (normal / unsigned sat / signed sat) */
       Iop_Add8x16,   Iop_Add16x8,   Iop_Add32x4,  Iop_Add64x2,