]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Frontend:
authorCerion Armour-Brown <cerion@valgrind.org>
Tue, 8 Nov 2005 16:23:07 +0000 (16:23 +0000)
committerCerion Armour-Brown <cerion@valgrind.org>
Tue, 8 Nov 2005 16:23:07 +0000 (16:23 +0000)
 added remaining integer altivec insns (phew!)
  - vsum4ubs, vsum4sbs, vsum4shs, vsum2sws, vsumsws
  - vmsummbm, vmsumuhs, vmsumshs

 various helpers to construct IR
  - expand8x16*:      sign/zero-extend V128_8x16 lanes => 2x V128_16x8
  - breakV128to4x64*: break V128 to 4xI32's, sign/zero-extend to I64's
  - mkQNarrow64to32*: un/signed saturating narrow 64 to 32
  - mkV128from4x64*:  narrow 4xI64's to 4xI32's, combine to V128_34x4

Backend:
 Iop_Add64
   - added PPC32Instr_AddSubC32: 32-bit add/sub read/write carry
 64-bit Iex_Const
 Iop_32Sto64

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

VEX/priv/guest-ppc32/toIR.c
VEX/priv/host-ppc32/hdefs.c
VEX/priv/host-ppc32/hdefs.h
VEX/priv/host-ppc32/isel.c

index 8601452cf0b669f8ed262a3e09be44b591019de0..e4a75036a012018cf9d4f12e854b87db5b50ca0e 100644 (file)
@@ -414,6 +414,11 @@ static IRExpr* mkU32 ( UInt i )
    return IRExpr_Const(IRConst_U32(i));
 }
 
+static IRExpr* mkU64 ( ULong i )
+{
+   return IRExpr_Const(IRConst_U64(i));
+}
+
 static IRExpr* loadBE ( IRType ty, IRExpr* data )
 {
    return IRExpr_Load(Iend_BE,ty,data);
@@ -437,6 +442,206 @@ static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
                                        unop(Iop_1Uto32, arg2)));
 }
 
+/* expand V128_8Ux16 to 2x V128_16Ux8's */
+static void expand8Ux16( IRExpr* vIn, /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
+{
+   IRTemp ones8x16 = newTemp(Ity_V128);
+
+   vassert(typeOfIRExpr(irbb->tyenv, vIn) == Ity_V128);
+   vassert(vEvn && *vEvn == IRTemp_INVALID);
+   vassert(vOdd && *vOdd == IRTemp_INVALID);
+   *vEvn = newTemp(Ity_V128);
+   *vOdd = newTemp(Ity_V128);
+
+   assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
+   assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
+   assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), 
+                        binop(Iop_ShlV128, vIn, mkU8(8))) );
+}
+
+/* expand V128_8Sx16 to 2x V128_16Sx8's */
+static void expand8Sx16( IRExpr* vIn, /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
+{
+   IRTemp ones8x16 = newTemp(Ity_V128);
+
+   vassert(typeOfIRExpr(irbb->tyenv, vIn) == Ity_V128);
+   vassert(vEvn && *vEvn == IRTemp_INVALID);
+   vassert(vOdd && *vOdd == IRTemp_INVALID);
+   *vEvn = newTemp(Ity_V128);
+   *vOdd = newTemp(Ity_V128);
+
+   assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
+   assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
+   assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), 
+                        binop(Iop_ShlV128, vIn, mkU8(8))) );
+}
+
+/* expand V128_16Uto8 to 2x V128_32Ux4's */
+static void expand16Ux8( IRExpr* vIn, /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
+{
+   IRTemp ones16x8 = newTemp(Ity_V128);
+
+   vassert(typeOfIRExpr(irbb->tyenv, vIn) == Ity_V128);
+   vassert(vEvn && *vEvn == IRTemp_INVALID);
+   vassert(vOdd && *vOdd == IRTemp_INVALID);
+   *vEvn = newTemp(Ity_V128);
+   *vOdd = newTemp(Ity_V128);
+
+   assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
+   assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
+   assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), 
+                       binop(Iop_ShlV128, vIn, mkU8(16))) );
+}
+
+/* expand V128_16Sto8 to 2x V128_32Sx4's */
+static void expand16Sx8( IRExpr* vIn, /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
+{
+   IRTemp ones16x8 = newTemp(Ity_V128);
+
+   vassert(typeOfIRExpr(irbb->tyenv, vIn) == Ity_V128);
+   vassert(vEvn && *vEvn == IRTemp_INVALID);
+   vassert(vOdd && *vOdd == IRTemp_INVALID);
+   *vEvn = newTemp(Ity_V128);
+   *vOdd = newTemp(Ity_V128);
+
+   assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
+   assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
+   assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), 
+                       binop(Iop_ShlV128, vIn, mkU8(16))) );
+}
+
+/* break V128 to 4xI32's, then sign-extend to I64's */
+static void breakV128to4x64S( IRExpr* t128,
+                              /*OUTs*/
+                              IRTemp* t3, IRTemp* t2,
+                              IRTemp* t1, IRTemp* t0 )
+{
+   IRTemp hi64 = newTemp(Ity_I64);
+   IRTemp lo64 = newTemp(Ity_I64);
+
+   vassert(typeOfIRExpr(irbb->tyenv, t128) == Ity_V128);
+   vassert(t0 && *t0 == IRTemp_INVALID);
+   vassert(t1 && *t1 == IRTemp_INVALID);
+   vassert(t2 && *t2 == IRTemp_INVALID);
+   vassert(t3 && *t3 == IRTemp_INVALID);
+   *t0 = newTemp(Ity_I64);
+   *t1 = newTemp(Ity_I64);
+   *t2 = newTemp(Ity_I64);
+   *t3 = newTemp(Ity_I64);
+
+   assign( hi64, unop(Iop_V128HIto64, t128) );
+   assign( lo64, unop(Iop_V128to64,   t128) );
+   assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
+   assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
+   assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
+   assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
+}
+
+/* break V128 to 4xI32's, then zero-extend to I64's */
+static void breakV128to4x64U ( IRExpr* t128,
+                               /*OUTs*/
+                               IRTemp* t3, IRTemp* t2,
+                               IRTemp* t1, IRTemp* t0 )
+{
+   IRTemp hi64 = newTemp(Ity_I64);
+   IRTemp lo64 = newTemp(Ity_I64);
+
+   vassert(typeOfIRExpr(irbb->tyenv, t128) == Ity_V128);
+   vassert(t0 && *t0 == IRTemp_INVALID);
+   vassert(t1 && *t1 == IRTemp_INVALID);
+   vassert(t2 && *t2 == IRTemp_INVALID);
+   vassert(t3 && *t3 == IRTemp_INVALID);
+   *t0 = newTemp(Ity_I64);
+   *t1 = newTemp(Ity_I64);
+   *t2 = newTemp(Ity_I64);
+   *t3 = newTemp(Ity_I64);
+
+   assign( hi64, unop(Iop_V128HIto64, t128) );
+   assign( lo64, unop(Iop_V128to64,   t128) );
+   assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
+   assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
+   assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
+   assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
+}
+
+/* Signed saturating narrow 64S to 32 */
+static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
+{
+   IRTemp hi32 = newTemp(Ity_I32);
+   IRTemp lo32 = newTemp(Ity_I32);
+
+   vassert(typeOfIRExpr(irbb->tyenv, t64) == Ity_I64);
+
+   assign( hi32, unop(Iop_64HIto32, t64));
+   assign( lo32, unop(Iop_64to32,   t64));
+
+   return IRExpr_Mux0X(
+             /* if (hi32 == (lo32 >>s 31)) */
+             unop(Iop_1Uto8,
+                  binop(Iop_CmpEQ32, mkexpr(hi32),
+                        binop( Iop_Sar32, mkexpr(lo32), mkU8(31)))),
+             /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
+             binop(Iop_Add32, mkU32(0x7FFFFFFF),
+                   binop(Iop_Shr32, mkexpr(hi32), mkU8(31))),
+             /* then: within signed-32 range: lo half good enough */
+             mkexpr(lo32) );
+}
+
+/* Unsigned saturating narrow 64S to 32 */
+static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
+{
+   IRTemp hi32 = newTemp(Ity_I32);
+   IRTemp lo32 = newTemp(Ity_I32);
+
+   vassert(typeOfIRExpr(irbb->tyenv, t64) == Ity_I64);
+
+   assign( hi32, unop(Iop_64HIto32, t64));
+   assign( lo32, unop(Iop_64to32,   t64));
+
+   return IRExpr_Mux0X(
+            /* if (top 32 bits of t64 are 0) */
+            unop(Iop_1Uto8, binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0))),
+            /* else: positive saturate -> 0xFFFFFFFF */
+            mkU32(0xFFFFFFFF),
+            /* then: within unsigned-32 range: lo half good enough */
+            mkexpr(lo32) );
+}
+
+/* Signed saturate narrow 64->32, combining to V128 */
+static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
+                                 IRExpr* t1, IRExpr* t0 )
+{
+   vassert(typeOfIRExpr(irbb->tyenv, t3) == Ity_I64);
+   vassert(typeOfIRExpr(irbb->tyenv, t2) == Ity_I64);
+   vassert(typeOfIRExpr(irbb->tyenv, t1) == Ity_I64);
+   vassert(typeOfIRExpr(irbb->tyenv, t0) == Ity_I64);
+   return binop(Iop_64HLtoV128,
+                binop(Iop_32HLto64,
+                      mkQNarrow64Sto32( t3 ),
+                      mkQNarrow64Sto32( t2 )),
+                binop(Iop_32HLto64,
+                      mkQNarrow64Sto32( t1 ),
+                      mkQNarrow64Sto32( t0 )));
+}
+
+/* Unsigned saturate narrow 64->32, combining to V128 */
+static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
+                                 IRExpr* t1, IRExpr* t0 )
+{
+   vassert(typeOfIRExpr(irbb->tyenv, t3) == Ity_I64);
+   vassert(typeOfIRExpr(irbb->tyenv, t2) == Ity_I64);
+   vassert(typeOfIRExpr(irbb->tyenv, t1) == Ity_I64);
+   vassert(typeOfIRExpr(irbb->tyenv, t0) == Ity_I64);
+   return binop(Iop_64HLtoV128,
+                binop(Iop_32HLto64,
+                      mkQNarrow64Uto32( t3 ),
+                      mkQNarrow64Uto32( t2 )),
+                binop(Iop_32HLto64,
+                      mkQNarrow64Uto32( t1 ),
+                      mkQNarrow64Uto32( t0 )));
+}
+
+
 static Int integerGuestRegOffset ( UInt archreg )
 {
    vassert(archreg < 32);
@@ -5155,6 +5360,20 @@ static Bool dis_av_arith ( UInt theInstr )
 
    IRTemp vA = newTemp(Ity_V128);
    IRTemp vB = newTemp(Ity_V128);
+   IRTemp z3 = newTemp(Ity_I64);
+   IRTemp z2 = newTemp(Ity_I64);
+   IRTemp z1 = newTemp(Ity_I64);
+   IRTemp z0 = newTemp(Ity_I64);
+   IRTemp aEvn, aOdd;
+   IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
+   IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
+   IRTemp b3, b2, b1, b0;
+
+   aEvn = aOdd = IRTemp_INVALID;
+   a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
+   a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
+   b3 = b2 = b1 = b0 = IRTemp_INVALID;
+
    assign( vA, getVReg(vA_addr));
    assign( vB, getVReg(vB_addr));
 
@@ -5436,31 +5655,148 @@ static Bool dis_av_arith ( UInt theInstr )
 
 
    /* Sum Across Partial */
-   case 0x608: // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
+   case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
+      IRTemp aEE, aEO, aOE, aOO;
+      aEE = aEO = aOE = aOO = IRTemp_INVALID;
       DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
-      DIP(" => not implemented\n");
-      return False;
 
-   case 0x708: // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
+      /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
+      expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
+      expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
+      expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
+
+      /* break V128 to 4xI32's, zero-extending to I64's */
+      breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
+      breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
+      breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
+      breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
+      breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
+
+      /* add lanes */
+      assign( z3, binop(Iop_Add64, mkexpr(b3),
+                        binop(Iop_Add64,
+                              binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
+                              binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
+      assign( z2, binop(Iop_Add64, mkexpr(b2),
+                        binop(Iop_Add64,
+                              binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
+                              binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
+      assign( z1, binop(Iop_Add64, mkexpr(b1),
+                        binop(Iop_Add64,
+                              binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
+                              binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
+      assign( z0, binop(Iop_Add64, mkexpr(b0),
+                        binop(Iop_Add64,
+                              binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
+                              binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
+      
+      /* saturate-narrow to 32bit, and combine to V128 */
+      putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
+                                         mkexpr(z1), mkexpr(z0)) );
+      break;
+   }
+   case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
+      IRTemp aEE, aEO, aOE, aOO;
+      aEE = aEO = aOE = aOO = IRTemp_INVALID;
       DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
-      DIP(" => not implemented\n");
-      return False;
 
-   case 0x648: // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
+      /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
+      expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
+      expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
+      expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
+
+      /* break V128 to 4xI32's, sign-extending to I64's */
+      breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
+      breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
+      breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
+      breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
+      breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
+
+      /* add lanes */
+      assign( z3, binop(Iop_Add64, mkexpr(b3),
+                        binop(Iop_Add64,
+                              binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
+                              binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
+      assign( z2, binop(Iop_Add64, mkexpr(b2),
+                        binop(Iop_Add64,
+                              binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
+                              binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
+      assign( z1, binop(Iop_Add64, mkexpr(b1),
+                        binop(Iop_Add64,
+                              binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
+                              binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
+      assign( z0, binop(Iop_Add64, mkexpr(b0),
+                        binop(Iop_Add64,
+                              binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
+                              binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
+      
+      /* saturate-narrow to 32bit, and combine to V128 */
+      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
+                                         mkexpr(z1), mkexpr(z0)) );
+      break;
+   }
+   case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
       DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
-      DIP(" => not implemented\n");
-      return False;
 
-   case 0x688: // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
+      /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
+      expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
+
+      /* break V128 to 4xI32's, sign-extending to I64's */
+      breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
+      breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
+      breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
+
+      /* add lanes */
+      assign( z3, binop(Iop_Add64, mkexpr(b3),
+                        binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
+      assign( z2, binop(Iop_Add64, mkexpr(b2),
+                        binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
+      assign( z1, binop(Iop_Add64, mkexpr(b1),
+                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
+      assign( z0, binop(Iop_Add64, mkexpr(b0),
+                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
+
+      /* saturate-narrow to 32bit, and combine to V128 */
+      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
+                                         mkexpr(z1), mkexpr(z0)) );
+      break;
+   }
+   case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
       DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
-      DIP(" => not implemented\n");
-      return False;
 
-   case 0x788: // vsumsws  (Sum SW Saturate, AV p271)
+      /* break V128 to 4xI32's, sign-extending to I64's */
+      breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
+      breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
+
+      /* add lanes */
+      assign( z2, binop(Iop_Add64, mkexpr(b2),
+                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
+      assign( z0, binop(Iop_Add64, mkexpr(b0),
+                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
+
+      /* saturate-narrow to 32bit, and combine to V128 */
+      putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
+                                         mkU64(0), mkexpr(z0)) );
+      break;
+   }
+   case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
       DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
-      DIP(" => not implemented\n");
-      return False;
 
+      /* break V128 to 4xI32's, sign-extending to I64's */
+      breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
+      breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
+
+      /* add lanes */
+      assign( z0, binop(Iop_Add64, mkexpr(b0),
+                        binop(Iop_Add64,
+                              binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
+                              binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
+
+      /* saturate-narrow to 32bit, and combine to V128 */
+      putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
+                                         mkU64(0), mkexpr(z0)) );
+      break;
+   }
    default:
       vex_printf("dis_av_arith(PPC32)(opc2=0x%x)\n", opc2);
       return False;
@@ -5618,32 +5954,43 @@ static Bool dis_av_multarith ( UInt theInstr )
    UChar vC_addr  = toUChar((theInstr >>  6) & 0x1F); /* theInstr[6:10]  */
    UChar opc2     = toUChar((theInstr >>  0) & 0x3F); /* theInstr[0:5]   */
 
+   IRTemp vA    = newTemp(Ity_V128);
+   IRTemp vB    = newTemp(Ity_V128);
+   IRTemp vC    = newTemp(Ity_V128);
    IRTemp zeros = newTemp(Ity_V128);
-   IRTemp vA = newTemp(Ity_V128);
-   IRTemp vB = newTemp(Ity_V128);
-   IRTemp vC = newTemp(Ity_V128);
+   IRTemp aLo   = newTemp(Ity_V128);
+   IRTemp bLo   = newTemp(Ity_V128);
+   IRTemp cLo   = newTemp(Ity_V128);
+   IRTemp zLo   = newTemp(Ity_V128);
+   IRTemp aHi   = newTemp(Ity_V128);
+   IRTemp bHi   = newTemp(Ity_V128);
+   IRTemp cHi   = newTemp(Ity_V128);
+   IRTemp zHi   = newTemp(Ity_V128);
+   IRTemp abEvn = newTemp(Ity_V128);
+   IRTemp abOdd = newTemp(Ity_V128);
+   IRTemp z3    = newTemp(Ity_I64);
+   IRTemp z2    = newTemp(Ity_I64);
+   IRTemp z1    = newTemp(Ity_I64);
+   IRTemp z0    = newTemp(Ity_I64);
+   IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
+   IRTemp c3, c2, c1, c0;
+
+   ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
+   c3 = c2 = c1 = c0 = IRTemp_INVALID;
+
    assign( vA, getVReg(vA_addr));
    assign( vB, getVReg(vB_addr));
    assign( vC, getVReg(vC_addr));
+   assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
 
    if (opc1 != 0x4) {
       vex_printf("dis_av_multarith(PPC32)(instr)\n");
       return False;
    }
 
-   assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
-
    switch (opc2) {
    /* Multiply-Add */
    case 0x20: { // vmhaddshs (Multiply High, Add Signed HW Saturate, AV p185)
-      IRTemp aLo = newTemp(Ity_V128);
-      IRTemp bLo = newTemp(Ity_V128);
-      IRTemp cLo = newTemp(Ity_V128);
-      IRTemp zLo = newTemp(Ity_V128);
-      IRTemp aHi = newTemp(Ity_V128);
-      IRTemp bHi = newTemp(Ity_V128);
-      IRTemp cHi = newTemp(Ity_V128);
-      IRTemp zHi = newTemp(Ity_V128);
       IRTemp cSigns = newTemp(Ity_V128);
       DIP("vmhaddshs v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
       assign( cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
@@ -5675,14 +6022,6 @@ static Bool dis_av_multarith ( UInt theInstr )
    }
    case 0x21: { // vmhraddshs (Multiply High Round, Add Signed HW Saturate, AV p186)
       IRTemp zKonst = newTemp(Ity_V128);
-      IRTemp aLo = newTemp(Ity_V128);
-      IRTemp bLo = newTemp(Ity_V128);
-      IRTemp cLo = newTemp(Ity_V128);
-      IRTemp zLo = newTemp(Ity_V128);
-      IRTemp aHi = newTemp(Ity_V128);
-      IRTemp bHi = newTemp(Ity_V128);
-      IRTemp cHi = newTemp(Ity_V128);
-      IRTemp zHi = newTemp(Ity_V128);
       IRTemp cSigns = newTemp(Ity_V128);
       DIP("vmhraddshs v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
       assign( cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
@@ -5694,8 +6033,8 @@ static Bool dis_av_multarith ( UInt theInstr )
       assign( cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns), mkexpr(vC)) );
 
       /* shifting our const avoids store/load version of Dup */
-      assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4,
-                                               mkU32(0x1)), mkU8(14)) );
+      assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
+                            mkU8(14)) );
 
       assign( zLo, binop(Iop_Add32x4,
                          binop(Iop_SarN32x4,
@@ -5719,14 +6058,6 @@ static Bool dis_av_multarith ( UInt theInstr )
       break;
    }
    case 0x22: { // vmladduhm (Multiply Low, Add Unsigned HW Modulo, AV p194)
-      IRTemp aLo = newTemp(Ity_V128);
-      IRTemp bLo = newTemp(Ity_V128);
-      IRTemp cLo = newTemp(Ity_V128);
-      IRTemp zLo = newTemp(Ity_V128);
-      IRTemp aHi = newTemp(Ity_V128);
-      IRTemp bHi = newTemp(Ity_V128);
-      IRTemp cHi = newTemp(Ity_V128);
-      IRTemp zHi = newTemp(Ity_V128);
       DIP("vmladduhm v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
       assign( aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)) );
       assign( bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)) );
@@ -5751,78 +6082,138 @@ static Bool dis_av_multarith ( UInt theInstr )
 
    /* Multiply-Sum */
    case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
-      IRTemp zKonst = newTemp(Ity_V128);
-      IRTemp odd = newTemp(Ity_V128);
-      IRTemp even = newTemp(Ity_V128);
-      IRTemp odd_odd = newTemp(Ity_V128);
-      IRTemp odd_even = newTemp(Ity_V128);
-      IRTemp even_odd = newTemp(Ity_V128);
-      IRTemp even_even = newTemp(Ity_V128);
+      IRTemp abEE, abEO, abOE, abOO;
+      abEE = abEO = abOE = abOO = IRTemp_INVALID;
       DIP("vmsumubm v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
-      assign( odd,  binop(Iop_MullEven8Ux16,
-                          binop(Iop_ShlV128, mkexpr(vA), mkU8(8)),
-                          binop(Iop_ShlV128, mkexpr(vB), mkU8(8)) ));
-      assign( even, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
-      /* zKonst just used to separate the lanes out */
-      assign( zKonst, unop(Iop_Dup16x8, mkU16(0x1)) );
-
-      assign( odd_odd,   binop(Iop_MullEven16Ux8,
-                               binop(Iop_ShlV128, mkexpr(odd), mkU8(16)),
-                               binop(Iop_ShlV128, mkexpr(zKonst), mkU8(16)) ));
-      assign( odd_even,  binop(Iop_MullEven16Ux8, mkexpr(odd),  mkexpr(zKonst)) );
-      assign( even_odd,  binop(Iop_MullEven16Ux8,
-                               binop(Iop_ShlV128, mkexpr(even), mkU8(16)),
-                               binop(Iop_ShlV128, mkexpr(zKonst), mkU8(16)) ));
-      assign( even_even, binop(Iop_MullEven16Ux8, mkexpr(even), mkexpr(zKonst)) );
 
+      /* multiply vA,vB (unsigned, widening) */
+      assign( abEvn, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
+      assign( abOdd, binop(Iop_MullEven8Ux16,
+                           binop(Iop_ShlV128, mkexpr(vA), mkU8(8)),
+                           binop(Iop_ShlV128, mkexpr(vB), mkU8(8)) ));
+      
+      /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
+      expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
+      expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
+      
       putVReg( vD_addr,
                binop(Iop_Add32x4, mkexpr(vC),
                      binop(Iop_Add32x4,
-                           binop(Iop_Add32x4, mkexpr(odd_even), mkexpr(odd_odd)),
-                           binop(Iop_Add32x4, mkexpr(even_even), mkexpr(even_odd)))) );
+                           binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
+                           binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
       break;
    }
-   case 0x25: // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
+   case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
+      IRTemp aEvn, aOdd, bEvn, bOdd;
+      IRTemp abEE = newTemp(Ity_V128);
+      IRTemp abEO = newTemp(Ity_V128);
+      IRTemp abOE = newTemp(Ity_V128);
+      IRTemp abOO = newTemp(Ity_V128);
+      aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
       DIP("vmsummbm v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
-      DIP(" => not implemented\n");
-      return False;
 
+      /* sign-extend vA, zero-extend vB, for mixed-sign multiply
+         (separating out adjacent lanes to different vectors) */
+      expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
+      expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
+
+      /* multiply vA, vB, again separating adjacent lanes */
+      assign( abEE, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn) ));
+      assign( abEO, binop(Iop_MullEven16Sx8,
+                          binop(Iop_ShlV128, mkexpr(aEvn), mkU8(16)),
+                          binop(Iop_ShlV128, mkexpr(bEvn), mkU8(16)) ));
+      assign( abOE, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd) ));
+      assign( abOO, binop(Iop_MullEven16Sx8,
+                          binop(Iop_ShlV128, mkexpr(aOdd), mkU8(16)),
+                          binop(Iop_ShlV128, mkexpr(bOdd), mkU8(16)) ));
+
+      /* add results together, + vC */
+      putVReg( vD_addr,
+               binop(Iop_QAdd32Sx4, mkexpr(vC),
+                     binop(Iop_QAdd32Sx4,
+                           binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
+                           binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)) )));
+      break;
+   }
    case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
-      IRTemp odd = newTemp(Ity_V128);
-      IRTemp even = newTemp(Ity_V128);
       DIP("vmsumuhm v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
-      assign( odd,  binop(Iop_MullEven16Ux8,
-                          binop(Iop_ShlV128, mkexpr(vA), mkU8(16)),
-                          binop(Iop_ShlV128, mkexpr(vB), mkU8(16)) ));
-      assign( even, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
+      assign( abEvn, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
+      assign( abOdd, binop(Iop_MullEven16Ux8,
+                           binop(Iop_ShlV128, mkexpr(vA), mkU8(16)),
+                           binop(Iop_ShlV128, mkexpr(vB), mkU8(16)) ));
       putVReg( vD_addr,
                binop(Iop_Add32x4, mkexpr(vC),
-                     binop(Iop_Add32x4, mkexpr(odd), mkexpr(even))) );
+                     binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
       break;
    }
-   case 0x27: // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
+   case 0x27: // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
       DIP("vmsumuhs v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
-      DIP(" => not implemented\n");
-      return False;
+      /* widening multiply, separating lanes */
+      assign( abEvn, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
+      assign( abOdd, binop(Iop_MullEven16Ux8,
+                           binop(Iop_ShlV128, mkexpr(vA), mkU8(16)),
+                           binop(Iop_ShlV128, mkexpr(vB), mkU8(16))) );
+
+      /* break V128 to 4xI32's, zero-extending to I64's */
+      breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
+      breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
+      breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
+
+      /* add lanes */
+      assign( z3, binop(Iop_Add64, mkexpr(c3),
+                        binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
+      assign( z2, binop(Iop_Add64, mkexpr(c2),
+                        binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
+      assign( z1, binop(Iop_Add64, mkexpr(c1),
+                        binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
+      assign( z0, binop(Iop_Add64, mkexpr(c0),
+                        binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
 
+      /* saturate-narrow to 32bit, and combine to V128 */
+      putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
+                                         mkexpr(z1), mkexpr(z0)) );
+
+      break;
+   }
    case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
-      IRTemp odd = newTemp(Ity_V128);
-      IRTemp even = newTemp(Ity_V128);
       DIP("vmsumshm v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
-      assign( odd,  binop(Iop_MullEven16Sx8,
-                          binop(Iop_ShlV128, mkexpr(vA), mkU8(16)),
-                          binop(Iop_ShlV128, mkexpr(vB), mkU8(16)) ));
-      assign( even, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
+      assign( abEvn, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
+      assign( abOdd, binop(Iop_MullEven16Sx8,
+                           binop(Iop_ShlV128, mkexpr(vA), mkU8(16)),
+                           binop(Iop_ShlV128, mkexpr(vB), mkU8(16)) ));
       putVReg( vD_addr,
                binop(Iop_Add32x4, mkexpr(vC),
-                     binop(Iop_Add32x4, mkexpr(odd), mkexpr(even))) );
+                     binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
       break;
    }
-   case 0x29: // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
+   case 0x29: // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
       DIP("vmsumshs v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
-      DIP(" => not implemented\n");
-      return False;
-
+      /* widening multiply, separating lanes */
+      assign( abEvn, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
+      assign( abOdd, binop(Iop_MullEven16Sx8,
+                           binop(Iop_ShlV128, mkexpr(vA), mkU8(16)),
+                           binop(Iop_ShlV128, mkexpr(vB), mkU8(16))) );
+
+      /* break V128 to 4xI32's, sign-extending to I64's */
+      breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
+      breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
+      breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
+
+      /* add lanes */
+      assign( z3, binop(Iop_Add64, mkexpr(c3),
+                        binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
+      assign( z2, binop(Iop_Add64, mkexpr(c2),
+                        binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
+      assign( z1, binop(Iop_Add64, mkexpr(c1),
+                        binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
+      assign( z0, binop(Iop_Add64, mkexpr(c0),
+                        binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
+
+      /* saturate-narrow to 32bit, and combine to V128 */
+      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
+                                         mkexpr(z1), mkexpr(z0)) );
+      break;
+   }
    default:
       vex_printf("dis_av_multarith(PPC32)(opc2)\n");
       return False;
index f357c97b3136dfaf449a750f1999bbe91ccfee18..1775f88a0fc90e309af858e9e77cacdba87194b7 100644 (file)
@@ -721,6 +721,17 @@ PPC32Instr* PPC32Instr_Alu32 ( PPC32AluOp op, HReg dst,
    i->Pin.Alu32.srcR = srcR;
    return i;
 }
+PPC32Instr* PPC32Instr_AddSubC32 ( Bool isAdd, Bool setC,
+                                   HReg dst, HReg srcL, HReg srcR ) {
+   PPC32Instr* i          = LibVEX_Alloc(sizeof(PPC32Instr));
+   i->tag                 = Pin_AddSubC32;
+   i->Pin.AddSubC32.isAdd = isAdd;
+   i->Pin.AddSubC32.setC  = setC;
+   i->Pin.AddSubC32.dst   = dst;
+   i->Pin.AddSubC32.srcL  = srcL;
+   i->Pin.AddSubC32.srcR  = srcR;
+   return i;
+}
 PPC32Instr* PPC32Instr_Cmp32 ( Bool syned, UInt crfD, 
                                HReg srcL, PPC32RH* srcR ) {
    PPC32Instr* i      = LibVEX_Alloc(sizeof(PPC32Instr));
@@ -1080,6 +1091,16 @@ void ppPPC32Instr ( PPC32Instr* i )
          ppPPC32RH(i->Pin.Alu32.srcR);
       }
       return;
+   case Pin_AddSubC32:
+      vex_printf("%s%s ",
+                 i->Pin.AddSubC32.isAdd ? "add" : "sub",
+                 i->Pin.AddSubC32.setC ? "c" : "e");
+      ppHRegPPC32(i->Pin.AddSubC32.dst);
+      vex_printf(",");
+      ppHRegPPC32(i->Pin.AddSubC32.srcL);
+      vex_printf(",");
+      ppHRegPPC32(i->Pin.AddSubC32.srcR);
+      return;
    case Pin_Cmp32:
       vex_printf("%s%s %%cr%u,",
                  i->Pin.Cmp32.syned ? "cmp" : "cmpl",
@@ -1469,6 +1490,11 @@ void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i )
       addRegUsage_PPC32RH(u, i->Pin.Alu32.srcR);
       addHRegUse(u, HRmWrite, i->Pin.Alu32.dst);
       return;
+   case Pin_AddSubC32:
+      addHRegUse(u, HRmWrite, i->Pin.AddSubC32.dst);
+      addHRegUse(u, HRmRead, i->Pin.AddSubC32.srcL);
+      addHRegUse(u, HRmRead, i->Pin.AddSubC32.srcR);
+      return;
    case Pin_Cmp32:
       addHRegUse(u, HRmRead, i->Pin.Cmp32.srcL);
       addRegUsage_PPC32RH(u, i->Pin.Cmp32.srcR);
@@ -1694,6 +1720,11 @@ void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i)
       mapReg(m, &i->Pin.Alu32.srcL);
       mapRegs_PPC32RH(m, i->Pin.Alu32.srcR);
       return;
+   case Pin_AddSubC32:
+      mapReg(m, &i->Pin.AddSubC32.dst);
+      mapReg(m, &i->Pin.AddSubC32.srcL);
+      mapReg(m, &i->Pin.AddSubC32.srcR);
+      return;
    case Pin_Cmp32:
       mapReg(m, &i->Pin.Cmp32.srcL);
       mapRegs_PPC32RH(m, i->Pin.Cmp32.srcR);
@@ -2346,6 +2377,28 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
       goto done;
    }
 
+   case Pin_AddSubC32: {
+      Bool isAdd    = i->Pin.AddSubC32.isAdd;
+      Bool setC = i->Pin.AddSubC32.setC;
+      UInt r_srcL   = iregNo(i->Pin.AddSubC32.srcL);
+      UInt r_srcR   = iregNo(i->Pin.AddSubC32.srcR);
+      UInt r_dst    = iregNo(i->Pin.AddSubC32.dst);
+      
+      if (isAdd) {
+         if (setC) /* addc (PPC32 p348) */
+            p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 10, 0);
+         else          /* adde (PPC32 p349) */
+            p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 138, 0);
+      } else {
+         /* subfX, with args the "wrong" way round */
+         if (setC) /* subfc (PPC32 p538) */
+            p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 8, 0);
+         else          /* subfe (PPC32 p539) */
+            p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 136, 0);
+      }
+      goto done;
+   }
+
    case Pin_Cmp32: {
       Bool syned  = i->Pin.Cmp32.syned;
       UInt fld1   = i->Pin.Cmp32.crfD << 2;
index e95c07fc3b6d5facf61f53612835636c9a6b2ee0..a2c2ba4073ceb0d13162e116746c2d6d6e7391b7 100644 (file)
@@ -419,6 +419,7 @@ typedef
    enum {
       Pin_LI32,       /* load 32-bit immediate (fake insn) */
       Pin_Alu32,      /* 32-bit add/sub/and/or/xor/shl/shr/sar */
+      Pin_AddSubC32,  /* 32-bit add/sub with read/write carry */
       Pin_Cmp32,      /* 32-bit compare */
       Pin_Unary32,    /* 32-bit not, neg, clz */
       Pin_MulL,       /* widening multiply */
@@ -491,6 +492,14 @@ typedef
             HReg       srcL;
             PPC32RH*   srcR;
          } Alu32;
+         /*  */
+         struct {
+            Bool isAdd;  /* else sub */
+            Bool setC;   /* else read carry */
+            HReg dst;
+            HReg srcL;
+            HReg srcR;
+         } AddSubC32;
          /* If signed, the immediate, if it exists, is a signed 16,
             else it is an unsigned 16. */
          struct {
@@ -710,6 +719,7 @@ typedef
 
 extern PPC32Instr* PPC32Instr_LI32       ( HReg, UInt );
 extern PPC32Instr* PPC32Instr_Alu32      ( PPC32AluOp, HReg, HReg, PPC32RH* );
+extern PPC32Instr* PPC32Instr_AddSubC32  ( Bool, Bool, HReg, HReg, HReg );
 extern PPC32Instr* PPC32Instr_Cmp32      ( Bool,       UInt, HReg, PPC32RH* );
 extern PPC32Instr* PPC32Instr_Unary32    ( PPC32UnaryOp op, HReg dst, HReg src );
 extern PPC32Instr* PPC32Instr_MulL       ( Bool syned, Bool hi32, HReg, HReg, HReg );
index 00864ce26d5528d710f582245379538f0ea8465a..001766c0d33ed6da23f89d24f216a87a766259d4 100644 (file)
@@ -1926,20 +1926,20 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e )
    vassert(e);
    vassert(typeOfIRExpr(env->type_env,e) == Ity_I64);
 
-//..    /* 64-bit literal */
-//..    if (e->tag == Iex_Const) {
-//..       ULong w64 = e->Iex.Const.con->Ico.U64;
-//..       UInt  wHi = ((UInt)(w64 >> 32)) & 0xFFFFFFFF;
-//..       UInt  wLo = ((UInt)w64) & 0xFFFFFFFF;
-//..       HReg  tLo = newVRegI(env);
-//..       HReg  tHi = newVRegI(env);
-//..       vassert(e->Iex.Const.con->tag == Ico_U64);
-//..       addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(wHi), tHi));
-//..       addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(wLo), tLo));
-//..       *rHi = tHi;
-//..       *rLo = tLo;
-//..       return;
-//..    }
+   /* 64-bit literal */
+   if (e->tag == Iex_Const) {
+      ULong w64 = e->Iex.Const.con->Ico.U64;
+      UInt  wHi = ((UInt)(w64 >> 32)) & 0xFFFFFFFF;
+      UInt  wLo = ((UInt)w64) & 0xFFFFFFFF;
+      HReg  tLo = newVRegI(env);
+      HReg  tHi = newVRegI(env);
+      vassert(e->Iex.Const.con->tag == Ico_U64);
+      addInstr(env, PPC32Instr_LI32(tHi, wHi));
+      addInstr(env, PPC32Instr_LI32(tLo, wLo));
+      *rHi = tHi;
+      *rLo = tLo;
+      return;
+   }
 
    /* read 64-bit IRTemp */
    if (e->tag == Iex_Tmp) {
@@ -2070,38 +2070,33 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e )
                             : e->Iex.Binop.op==Iop_And64 ? Palu_AND
                             : Palu_XOR;
             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
-            addInstr(env, mk_iMOVds_RR(tHi, xHi));
-            addInstr(env, mk_iMOVds_RR(tLo, xLo));
             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
-            addInstr(env, PPC32Instr_Alu32(op, tHi, tHi, PPC32RH_Reg(yHi)));
-            addInstr(env, PPC32Instr_Alu32(op, tLo, tHi, PPC32RH_Reg(yLo)));
+            addInstr(env, PPC32Instr_Alu32(op, tHi, xHi, PPC32RH_Reg(yHi)));
+            addInstr(env, PPC32Instr_Alu32(op, tLo, xLo, PPC32RH_Reg(yLo)));
             *rHi = tHi;
             *rLo = tLo;
             return;
          }
 
-//..          /* Add64/Sub64 */
-//..          case Iop_Add64:
+         /* Add64/Sub64 */
+         case Iop_Add64: {
 //..          case Iop_Sub64: {
-//..             HReg xLo, xHi, yLo, yHi;
-//..             HReg tLo = newVRegI(env);
-//..             HReg tHi = newVRegI(env);
-//..             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
-//..             addInstr(env, mk_iMOVsd_RR(xHi, tHi));
-//..             addInstr(env, mk_iMOVsd_RR(xLo, tLo));
-//..             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
+            HReg xLo, xHi, yLo, yHi;
+            HReg tLo = newVRegI(env);
+            HReg tHi = newVRegI(env);
+            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
+            iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
 //..             if (e->Iex.Binop.op==Iop_Add64) {
-//..                addInstr(env, X86Instr_Alu32R(Xalu_ADD, X86RMI_Reg(yLo), tLo));
-//..                addInstr(env, X86Instr_Alu32R(Xalu_ADC, X86RMI_Reg(yHi), tHi));
-//..             } else {
-//..                addInstr(env, X86Instr_Alu32R(Xalu_SUB, X86RMI_Reg(yLo), tLo));
-//..                addInstr(env, X86Instr_Alu32R(Xalu_SBB, X86RMI_Reg(yHi), tHi));
+            addInstr(env, PPC32Instr_AddSubC32( True/*add*/, True /*set carry*/,
+                                                tLo, xLo, yLo));
+            addInstr(env, PPC32Instr_AddSubC32( True/*add*/, False/*read carry*/,
+                                                tHi, xHi, yHi));
+//..             } else { // Sub64
 //..             }
-//..             *rHi = tHi;
-//..             *rLo = tLo;
-//..             return;
-//..          }
-
+            *rHi = tHi;
+            *rLo = tLo;
+            return;
+         }
 
          /* 32HLto64(e1,e2) */
          case Iop_32HLto64:
@@ -2401,18 +2396,15 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e )
    if (e->tag == Iex_Unop) {
       switch (e->Iex.Unop.op) {
 
-//..          /* 32Sto64(e) */
-//..          case Iop_32Sto64: {
-//..             HReg tLo = newVRegI(env);
-//..             HReg tHi = newVRegI(env);
-//..             HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-//..             addInstr(env, mk_iMOVsd_RR(src,tHi));
-//..             addInstr(env, mk_iMOVsd_RR(src,tLo));
-//..             addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, X86RM_Reg(tHi)));
-//..             *rHi = tHi;
-//..             *rLo = tLo;
-//..             return;
-//..          }
+         /* 32Sto64(e) */
+         case Iop_32Sto64: {
+            HReg tHi = newVRegI(env);
+            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
+            addInstr(env, PPC32Instr_Alu32(Palu_SAR, tHi, src, PPC32RH_Imm(False,31)));
+            *rHi = tHi;
+            *rLo = src;
+            return;
+         }
 
          /* 32Uto64(e) */
          case Iop_32Uto64: {