]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add some 32-bit SIMD integer primops, and use these to shorten up the
authorJulian Seward <jseward@acm.org>
Wed, 22 Sep 2010 00:56:37 +0000 (00:56 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 22 Sep 2010 00:56:37 +0000 (00:56 +0000)
implementation of some ARM media v6 instructions.

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

VEX/priv/guest_arm_toIR.c
VEX/priv/host_arm_isel.c
VEX/priv/host_generic_simd64.c
VEX/priv/host_generic_simd64.h
VEX/priv/ir_defs.c
VEX/pub/libvex_ir.h

index 225a5c87ca7220ac6c9e5c9eab72457ec9e549e0..ac705bde15e6c05219ebb9a338e9af55f0cdf7e1 100644 (file)
@@ -966,6 +966,41 @@ static IRExpr* get_GEFLAG32( Int flagNo /* 0, 1, 2, 3 */ )
    }
 }
 
+/* Set all 4 GE flags from the given 32-bit value as follows: GE 3 and
+   2 are set from bit 31 of the value, and GE 1 and 0 are set from bit
+   15 of the value.  All other bits are ignored. */
+static void set_GE_32_10_from_bits_31_15 ( IRTemp t32, IRTemp condT )
+{
+   IRTemp ge10 = newTemp(Ity_I32);
+   IRTemp ge32 = newTemp(Ity_I32);
+   assign(ge10, binop(Iop_And32, mkexpr(t32), mkU32(0x00008000)));
+   assign(ge32, binop(Iop_And32, mkexpr(t32), mkU32(0x80000000)));
+   put_GEFLAG32( 0, 0, mkexpr(ge10), condT );
+   put_GEFLAG32( 1, 0, mkexpr(ge10), condT );
+   put_GEFLAG32( 2, 0, mkexpr(ge32), condT );
+   put_GEFLAG32( 3, 0, mkexpr(ge32), condT );
+}
+
+
+/* Set all 4 GE flags from the given 32-bit value as follows: GE 3
+   from bit 31, GE 2 from bit 23, GE 1 from bit 15, and GE0 from
+   bit 7.  All other bits are ignored. */
+static void set_GE_3_2_1_0_from_bits_31_23_15_7 ( IRTemp t32, IRTemp condT )
+{
+   IRTemp ge0 = newTemp(Ity_I32);
+   IRTemp ge1 = newTemp(Ity_I32);
+   IRTemp ge2 = newTemp(Ity_I32);
+   IRTemp ge3 = newTemp(Ity_I32);
+   assign(ge0, binop(Iop_And32, mkexpr(t32), mkU32(0x00000080)));
+   assign(ge1, binop(Iop_And32, mkexpr(t32), mkU32(0x00008000)));
+   assign(ge2, binop(Iop_And32, mkexpr(t32), mkU32(0x00800000)));
+   assign(ge3, binop(Iop_And32, mkexpr(t32), mkU32(0x80000000)));
+   put_GEFLAG32( 0, 0, mkexpr(ge0), condT );
+   put_GEFLAG32( 1, 0, mkexpr(ge1), condT );
+   put_GEFLAG32( 2, 0, mkexpr(ge2), condT );
+   put_GEFLAG32( 3, 0, mkexpr(ge3), condT );
+}
+
 
 /* ---------------- FPSCR stuff ---------------- */
 
@@ -8623,37 +8658,22 @@ static Bool decode_V6MEDIA_instruction (
      }
 
      if (gate) {
-        IRTemp irt_regN   = newTemp(Ity_I32);
-        IRTemp irt_regM   = newTemp(Ity_I32);
-        IRTemp irt_sum_lo = newTemp(Ity_I32);
-        IRTemp irt_sum_hi = newTemp(Ity_I32);
-
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
-
-        assign( irt_sum_lo, 
-                binop(Iop_Add32, 
-                      binop(Iop_And32, mkexpr(irt_regN), mkU32(0xFFFF)), 
-                      binop(Iop_And32, mkexpr(irt_regM), mkU32(0xFFFF))) );
-        assign( irt_sum_hi, 
-                binop(Iop_Add32, 
-                      binop(Iop_Shr32, mkexpr(irt_regN), mkU8(16)), 
-                      binop(Iop_Shr32, mkexpr(irt_regM), mkU8(16))) );
-
-        put_GEFLAG32( 0, 16, mkexpr(irt_sum_lo), condT );
-        put_GEFLAG32( 1, 16, mkexpr(irt_sum_lo), condT );
-        put_GEFLAG32( 2, 16, mkexpr(irt_sum_hi), condT );
-        put_GEFLAG32( 3, 16, mkexpr(irt_sum_hi), condT );
+        IRTemp rNt  = newTemp(Ity_I32);
+        IRTemp rMt  = newTemp(Ity_I32);
+        IRTemp res  = newTemp(Ity_I32);
+        IRTemp reso = newTemp(Ity_I32);
 
-        IRExpr* ire_result 
-          = binop( Iop_Or32, 
-                   binop(Iop_And32, mkexpr(irt_sum_lo), mkU32(0xFFFF)), 
-                   binop(Iop_Shl32, mkexpr(irt_sum_hi), mkU8(16)) );
+        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
 
+        assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt)));
         if (isT)
-           putIRegT( regD, ire_result, condT );
+           putIRegT( regD, mkexpr(res), condT );
         else
-           putIRegA( regD, ire_result, condT, Ijk_Boring );
+           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
+
+        assign(reso, binop(Iop_HAdd16Ux2, mkexpr(rNt), mkexpr(rMt)));
+        set_GE_32_10_from_bits_31_15(reso, condT);
 
         DIP("uadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
         return True;
@@ -8687,46 +8707,23 @@ static Bool decode_V6MEDIA_instruction (
      }
 
      if (gate) {
-        IRTemp irt_regN   = newTemp(Ity_I32);
-        IRTemp irt_regM   = newTemp(Ity_I32);
-        IRTemp irt_sum_lo = newTemp(Ity_I32);
-        IRTemp irt_sum_hi = newTemp(Ity_I32);
-
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
-
-        assign( irt_sum_lo, 
-                binop(Iop_Add32, 
-                      binop(Iop_Sar32,
-                            binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)),
-                            mkU8(16)), 
-                      binop(Iop_Sar32,
-                            binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)),
-                            mkU8(16)) ));
-        assign( irt_sum_hi, 
-                binop(Iop_Add32, 
-                      binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)), 
-                      binop(Iop_Sar32, mkexpr(irt_regM), mkU8(16))) );
-
-        IRTemp not_sum_lo = newTemp(Ity_I32);
-        assign(not_sum_lo, unop(Iop_Not32, mkexpr(irt_sum_lo)));
-        put_GEFLAG32( 0, 31, mkexpr(not_sum_lo), condT );
-        put_GEFLAG32( 1, 31, mkexpr(not_sum_lo), condT );
-
-        IRTemp not_sum_hi = newTemp(Ity_I32);
-        assign(not_sum_hi, unop(Iop_Not32, mkexpr(irt_sum_hi)));
-        put_GEFLAG32( 2, 31, mkexpr(not_sum_hi), condT );
-        put_GEFLAG32( 3, 31, mkexpr(not_sum_hi), condT );
+        IRTemp rNt  = newTemp(Ity_I32);
+        IRTemp rMt  = newTemp(Ity_I32);
+        IRTemp res  = newTemp(Ity_I32);
+        IRTemp reso = newTemp(Ity_I32);
 
-        IRExpr* ire_result 
-          = binop( Iop_Or32, 
-                   binop(Iop_And32, mkexpr(irt_sum_lo), mkU32(0xFFFF)), 
-                   binop(Iop_Shl32, mkexpr(irt_sum_hi), mkU8(16)) );
+        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
 
+        assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt)));
         if (isT)
-           putIRegT( regD, ire_result, condT );
+           putIRegT( regD, mkexpr(res), condT );
         else
-           putIRegA( regD, ire_result, condT, Ijk_Boring );
+           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
+
+        assign(reso, unop(Iop_Not32,
+                          binop(Iop_HAdd16Sx2, mkexpr(rNt), mkexpr(rMt))));
+        set_GE_32_10_from_bits_31_15(reso, condT);
 
         DIP("sadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
         return True;
@@ -8760,45 +8757,25 @@ static Bool decode_V6MEDIA_instruction (
      }
 
      if (gate) {
-        IRTemp irt_regN       = newTemp(Ity_I32);
-        IRTemp irt_regM       = newTemp(Ity_I32);
-        IRTemp irt_res_lo     = newTemp(Ity_I32);
-        IRTemp irt_res_hi     = newTemp(Ity_I32);
-        IRTemp irt_res_lo_not = newTemp(Ity_I32);
-        IRTemp irt_res_hi_not = newTemp(Ity_I32);
-
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
-
-        assign( irt_res_lo, 
-                binop( Iop_Sub32, 
-                       binop(Iop_And32, mkexpr(irt_regN), mkU32(0xFFFF)),
-                       binop(Iop_And32, mkexpr(irt_regM), mkU32(0xFFFF)) ) );
-        assign( irt_res_hi, 
-                binop( Iop_Sub32, 
-                       binop(Iop_Shr32, mkexpr(irt_regN), mkU8(16)), 
-                       binop(Iop_Shr32, mkexpr(irt_regM), mkU8(16)) ) );
-
-        assign( irt_res_lo_not, 
-                unop(Iop_Not32, binop(Iop_Sar32, mkexpr(irt_res_lo), mkU8(31))) );
-        assign( irt_res_hi_not, 
-                unop(Iop_Not32, binop(Iop_Sar32, mkexpr(irt_res_hi), mkU8(31))) );
-        put_GEFLAG32( 0, 0, mkexpr(irt_res_lo_not), condT );
-        put_GEFLAG32( 1, 0, mkexpr(irt_res_lo_not), condT );
-        put_GEFLAG32( 2, 0, mkexpr(irt_res_hi_not), condT );
-        put_GEFLAG32( 3, 0, mkexpr(irt_res_hi_not), condT );
+        IRTemp rNt  = newTemp(Ity_I32);
+        IRTemp rMt  = newTemp(Ity_I32);
+        IRTemp res  = newTemp(Ity_I32);
+        IRTemp reso = newTemp(Ity_I32);
 
-        IRExpr* ire_result 
-          = binop( Iop_Or32, 
-                   binop(Iop_And32, mkexpr(irt_res_lo), mkU32(0xFFFF)),
-                   binop(Iop_Shl32, mkexpr(irt_res_hi), mkU8(16)) );
+        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
 
+        assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt)));
         if (isT)
-           putIRegT( regD, ire_result, condT );
+           putIRegT( regD, mkexpr(res), condT );
         else
-           putIRegA( regD, ire_result, condT, Ijk_Boring );
+           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
 
-        DIP("usub16 %s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
+        assign(reso, unop(Iop_Not32,
+                          binop(Iop_HSub16Ux2, mkexpr(rNt), mkexpr(rMt))));
+        set_GE_32_10_from_bits_31_15(reso, condT);
+
+        DIP("usub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
         return True;
      }
      /* fall through */
@@ -8830,46 +8807,23 @@ static Bool decode_V6MEDIA_instruction (
      }
 
      if (gate) {
-        IRTemp irt_regN   = newTemp(Ity_I32);
-        IRTemp irt_regM   = newTemp(Ity_I32);
-        IRTemp irt_sum_lo = newTemp(Ity_I32);
-        IRTemp irt_sum_hi = newTemp(Ity_I32);
-
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
-
-        assign( irt_sum_lo, 
-                binop(Iop_Sub32, 
-                      binop(Iop_Sar32,
-                            binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)),
-                            mkU8(16)), 
-                      binop(Iop_Sar32,
-                            binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)),
-                            mkU8(16)) ));
-        assign( irt_sum_hi, 
-                binop(Iop_Sub32, 
-                      binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)), 
-                      binop(Iop_Sar32, mkexpr(irt_regM), mkU8(16))) );
-
-        IRTemp not_sum_lo = newTemp(Ity_I32);
-        assign(not_sum_lo, unop(Iop_Not32, mkexpr(irt_sum_lo)));
-        put_GEFLAG32( 0, 31, mkexpr(not_sum_lo), condT );
-        put_GEFLAG32( 1, 31, mkexpr(not_sum_lo), condT );
-
-        IRTemp not_sum_hi = newTemp(Ity_I32);
-        assign(not_sum_hi, unop(Iop_Not32, mkexpr(irt_sum_hi)));
-        put_GEFLAG32( 2, 31, mkexpr(not_sum_hi), condT );
-        put_GEFLAG32( 3, 31, mkexpr(not_sum_hi), condT );
+        IRTemp rNt  = newTemp(Ity_I32);
+        IRTemp rMt  = newTemp(Ity_I32);
+        IRTemp res  = newTemp(Ity_I32);
+        IRTemp reso = newTemp(Ity_I32);
 
-        IRExpr* ire_result 
-          = binop( Iop_Or32, 
-                   binop(Iop_And32, mkexpr(irt_sum_lo), mkU32(0xFFFF)), 
-                   binop(Iop_Shl32, mkexpr(irt_sum_hi), mkU8(16)) );
+        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
 
+        assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt)));
         if (isT)
-           putIRegT( regD, ire_result, condT );
+           putIRegT( regD, mkexpr(res), condT );
         else
-           putIRegA( regD, ire_result, condT, Ijk_Boring );
+           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
+
+        assign(reso, unop(Iop_Not32,
+                          binop(Iop_HSub16Sx2, mkexpr(rNt), mkexpr(rMt))));
+        set_GE_32_10_from_bits_31_15(reso, condT);
 
         DIP("ssub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
         return True;
@@ -8903,86 +8857,36 @@ static Bool decode_V6MEDIA_instruction (
      }
 
      if (gate) {
-        IRTemp irt_regN   = newTemp(Ity_I32);
-        IRTemp irt_regM   = newTemp(Ity_I32);
-        IRTemp irt_sum_l0 = newTemp(Ity_I32);
-        IRTemp irt_sum_l1 = newTemp(Ity_I32);
-        IRTemp irt_sum_l2 = newTemp(Ity_I32);
-        IRTemp irt_sum_l3 = newTemp(Ity_I32);
-
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
+        IRTemp rNt  = newTemp(Ity_I32);
+        IRTemp rMt  = newTemp(Ity_I32);
+        IRTemp res  = newTemp(Ity_I32);
+        IRTemp reso = newTemp(Ity_I32);
 
-        IRExpr* ire_regN_l0 = binop( Iop_And32, mkexpr(irt_regN), mkU32(0xff) );
-
-        IRExpr* ire_regN_l1 = binop(Iop_And32, 
-                                    binop(Iop_Shr32, mkexpr(irt_regN), mkU8(8)),
-                                    mkU32(0xff) );
-        IRExpr* ire_regN_l2 = binop(Iop_And32, 
-                                    binop(Iop_Shr32, mkexpr(irt_regN), mkU8(16)),
-                                    mkU32(0xff) );
-        IRExpr* ire_regN_l3 = binop(Iop_And32, 
-                                    binop(Iop_Shr32, mkexpr(irt_regN), mkU8(24)),
-                                    mkU32(0xff) );
-
-        IRExpr* ire_regM_l0 = binop( Iop_And32, mkexpr(irt_regM), mkU32(0xff) );
-        IRExpr* ire_regM_l1 = binop(Iop_And32, 
-                                    binop(Iop_Shr32, mkexpr(irt_regM), mkU8(8)),
-                                    mkU32(0xff) );
-        IRExpr* ire_regM_l2 = binop(Iop_And32, 
-                                    binop(Iop_Shr32, mkexpr(irt_regM), mkU8(16)),
-                                    mkU32(0xff) );
-        IRExpr* ire_regM_l3 = binop(Iop_And32, 
-                                    binop(Iop_Shr32, mkexpr(irt_regM), mkU8(24)),
-                                    mkU32(0xff) );
-
-        assign(irt_sum_l0, binop(Iop_Add32, ire_regN_l0, ire_regM_l0));
-        assign(irt_sum_l1, binop(Iop_Add32, ire_regN_l1, ire_regM_l1));
-        assign(irt_sum_l2, binop(Iop_Add32, ire_regN_l2, ire_regM_l2));
-        assign(irt_sum_l3, binop(Iop_Add32, ire_regN_l3, ire_regM_l3));
-
-        put_GEFLAG32( 0, 8, mkexpr(irt_sum_l0), condT );
-        put_GEFLAG32( 1, 8, mkexpr(irt_sum_l1), condT );
-        put_GEFLAG32( 2, 8, mkexpr(irt_sum_l2), condT );
-        put_GEFLAG32( 3, 8, mkexpr(irt_sum_l3), condT );
-
-        IRExpr* ire_res_a 
-          = binop( Iop_Or32, 
-                   binop( Iop_And32, mkexpr(irt_sum_l0), mkU32(0xff) ), 
-                   binop( Iop_Shl32, 
-                          binop( Iop_And32, mkexpr(irt_sum_l1), mkU32(0xff) ), 
-                          mkU8(8) ) );
-        IRExpr* ire_res_b  
-          = binop( Iop_Or32, 
-                   binop( Iop_Shl32, 
-                          binop( Iop_And32, mkexpr(irt_sum_l2), mkU32(0xff) ), 
-                          mkU8(16) ), 
-                   ire_res_a );
-        IRExpr* ire_result 
-          = binop( Iop_Or32, 
-                   binop( Iop_Shl32, 
-                          binop( Iop_And32, mkexpr(irt_sum_l3), mkU32(0xff) ), 
-                          mkU8(24) ), 
-                   ire_res_b );
+        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
 
+        assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt)));
         if (isT)
-           putIRegT( regD, ire_result, condT );
+           putIRegT( regD, mkexpr(res), condT );
         else
-           putIRegA( regD, ire_result, condT, Ijk_Boring );
+           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
 
-        DIP("uadd8%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM);
+        assign(reso, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
+        set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
+
+        DIP("uadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
         return True;
      }
      /* fall through */
    }
 
-   /* ------------------- usub8<c> <Rd>,<Rn>,<Rm> ------------------ */
+   /* ------------------- sadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
    {
      UInt regD = 99, regN = 99, regM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
+        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
@@ -8990,106 +8894,49 @@ static Bool decode_V6MEDIA_instruction (
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
+        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
             INSNA(11,8)  == BITS4(1,1,1,1)         &&
-            (INSNA(7,4)  == BITS4(1,1,1,1))) {
+            (INSNA(7,4)  == BITS4(1,0,0,1))) {
            regD = INSNA(15,12);
            regN = INSNA(19,16);
            regM = INSNA(3,0);
            if (regD != 15 && regN != 15 && regM != 15)
-             gate = True;
+              gate = True;
         }
      }
 
      if (gate) {
-        IRTemp irt_regN    = newTemp(Ity_I32);
-        IRTemp irt_regM    = newTemp(Ity_I32);
-        IRTemp irt_diff_l0 = newTemp(Ity_I32);
-        IRTemp irt_diff_l1 = newTemp(Ity_I32);
-        IRTemp irt_diff_l2 = newTemp(Ity_I32);
-        IRTemp irt_diff_l3 = newTemp(Ity_I32);
-
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
+        IRTemp rNt  = newTemp(Ity_I32);
+        IRTemp rMt  = newTemp(Ity_I32);
+        IRTemp res  = newTemp(Ity_I32);
+        IRTemp reso = newTemp(Ity_I32);
 
-        IRExpr* ire_regN_l0 = binop( Iop_And32, mkexpr(irt_regN), mkU32(0xff) );
-        IRExpr* ire_regN_l1 = binop(Iop_And32, 
-                                    binop(Iop_Shr32, mkexpr(irt_regN), mkU8(8)),
-                                    mkU32(0xff));
-        IRExpr* ire_regN_l2 = binop(Iop_And32, 
-                                    binop(Iop_Shr32, mkexpr(irt_regN), mkU8(16)),
-                                    mkU32(0xff));
-        IRExpr* ire_regN_l3 = binop(Iop_And32, 
-                                    binop(Iop_Shr32, mkexpr(irt_regN), mkU8(24)),
-                                    mkU32(0xff));
-
-        IRExpr* ire_regM_l0  = binop(Iop_And32, mkexpr(irt_regM), mkU32(0xff) );
-        IRExpr* ire_regM_l1  = binop(Iop_And32, 
-                                     binop(Iop_Shr32, mkexpr(irt_regM), mkU8(8)),
-                                     mkU32(0xff));
-        IRExpr* ire_regM_l2 = binop(Iop_And32, 
-                                    binop(Iop_Shr32, mkexpr(irt_regM), mkU8(16)),
-                                    mkU32(0xff));
-        IRExpr* ire_regM_l3 = binop(Iop_And32, 
-                                    binop(Iop_Shr32, mkexpr(irt_regM), mkU8(24)),
-                                    mkU32(0xff));
-
-        assign( irt_diff_l0, binop(Iop_Sub32, ire_regN_l0, ire_regM_l0) );
-        assign( irt_diff_l1, binop(Iop_Sub32, ire_regN_l1, ire_regM_l1) );
-        assign( irt_diff_l2, binop(Iop_Sub32, ire_regN_l2, ire_regM_l2) );
-        assign( irt_diff_l3, binop(Iop_Sub32, ire_regN_l3, ire_regM_l3) );
-
-        IRExpr* ire_not_l0 = unop(Iop_Not32,
-                                  binop(Iop_Sar32, mkexpr(irt_diff_l0), mkU8(31)));
-        IRExpr* ire_not_l1 = unop(Iop_Not32,
-                                  binop(Iop_Sar32, mkexpr(irt_diff_l1), mkU8(31)));
-        IRExpr* ire_not_l2 = unop(Iop_Not32,
-                                  binop(Iop_Sar32, mkexpr(irt_diff_l2), mkU8(31)));
-        IRExpr* ire_not_l3 = unop(Iop_Not32,
-                                  binop(Iop_Sar32, mkexpr(irt_diff_l3), mkU8(31)));
-
-        put_GEFLAG32( 0, 0, ire_not_l0, condT );
-        put_GEFLAG32( 1, 0, ire_not_l1, condT );
-        put_GEFLAG32( 2, 0, ire_not_l2, condT );
-        put_GEFLAG32( 3, 0, ire_not_l3, condT );
-
-        IRExpr* ire_res_a
-          = binop( Iop_Or32, 
-                   binop( Iop_And32, mkexpr(irt_diff_l0), mkU32(0xff) ), 
-                   binop( Iop_Shl32, 
-                          binop( Iop_And32, mkexpr(irt_diff_l1), mkU32(0xff) ),
-                          mkU8(8) ) );
-        IRExpr* ire_res_b
-          = binop( Iop_Or32, 
-                   binop( Iop_Shl32, 
-                          binop( Iop_And32, mkexpr(irt_diff_l2), mkU32(0xff) ), 
-                          mkU8(16) ), 
-                   ire_res_a );
-        IRExpr* ire_result
-          = binop( Iop_Or32, 
-                   binop( Iop_Shl32, 
-                          binop( Iop_And32, mkexpr(irt_diff_l3), mkU32(0xff) ), 
-                          mkU8(24) ), 
-                   ire_res_b );
+        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
 
+        assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt)));
         if (isT)
-           putIRegT( regD, ire_result, condT );
+           putIRegT( regD, mkexpr(res), condT );
         else
-           putIRegA( regD, ire_result, condT, Ijk_Boring );
+           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
 
-        DIP("usub8%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM);
+        assign(reso, unop(Iop_Not32,
+                          binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt))));
+        set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
+
+        DIP("sadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
         return True;
      }
      /* fall through */
    }
 
-   /* ------------------ qadd16<c> <Rd>,<Rn>,<Rm> ------------------ */
+   /* ------------------- usub8<c> <Rd>,<Rn>,<Rm> ------------------ */
    {
      UInt regD = 99, regN = 99, regM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
+        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
@@ -9097,66 +8944,49 @@ static Bool decode_V6MEDIA_instruction (
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
+        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
             INSNA(11,8)  == BITS4(1,1,1,1)         &&
-            INSNA(7,4)   == BITS4(0,0,0,1)) {
+            (INSNA(7,4)  == BITS4(1,1,1,1))) {
            regD = INSNA(15,12);
            regN = INSNA(19,16);
            regM = INSNA(3,0);
            if (regD != 15 && regN != 15 && regM != 15)
-              gate = True;
+             gate = True;
         }
      }
 
      if (gate) {
-        IRTemp irt_regN   = newTemp(Ity_I32);
-        IRTemp irt_regM   = newTemp(Ity_I32);
-        IRTemp irt_sum_lo = newTemp(Ity_I32);
-        IRTemp irt_sum_hi = newTemp(Ity_I32);
-        IRTemp irt_res_lo = newTemp(Ity_I32);
-        IRTemp irt_res_hi = newTemp(Ity_I32);
-
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
-
-        assign( irt_sum_lo, 
-                binop(Iop_Add32, 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)), 
-                            mkU8(16)), 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 
-                            mkU8(16))) );
-
-        assign( irt_sum_hi, binop(Iop_Add32, 
-                                  binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)), 
-                                  binop(Iop_Sar32, mkexpr(irt_regM), mkU8(16))) );
-
-        armSignedSatQ( irt_sum_lo, 0x10, &irt_res_lo, NULL );
-        armSignedSatQ( irt_sum_hi, 0x10, &irt_res_hi, NULL );
+        IRTemp rNt  = newTemp(Ity_I32);
+        IRTemp rMt  = newTemp(Ity_I32);
+        IRTemp res  = newTemp(Ity_I32);
+        IRTemp reso = newTemp(Ity_I32);
 
-        IRExpr* ire_result 
-          = binop( Iop_Or32, binop(Iop_Shl32, mkexpr(irt_res_hi), mkU8(16)), 
-                   binop(Iop_And32, mkexpr(irt_res_lo), mkU32(0xFFFF)) );
+        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
 
+        assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt)));
         if (isT)
-           putIRegT( regD, ire_result, condT );
+           putIRegT( regD, mkexpr(res), condT );
         else
-           putIRegA( regD, ire_result, condT, Ijk_Boring );
+           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
+
+        assign(reso, unop(Iop_Not32,
+                          binop(Iop_HSub8Ux4, mkexpr(rNt), mkexpr(rMt))));
+        set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
 
-        DIP( "qadd16%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
+        DIP("usub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
         return True;
      }
      /* fall through */
    }
 
-   /* ------------------ qsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
+   /* ------------------- ssub8<c> <Rd>,<Rn>,<Rm> ------------------ */
    {
      UInt regD = 99, regN = 99, regM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
+        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
@@ -9164,68 +8994,49 @@ static Bool decode_V6MEDIA_instruction (
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
+        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
             INSNA(11,8)  == BITS4(1,1,1,1)         &&
-            INSNA(7,4)   == BITS4(0,1,1,1)) {
+            INSNA(7,4)   == BITS4(1,1,1,1)) {
            regD = INSNA(15,12);
            regN = INSNA(19,16);
            regM = INSNA(3,0);
            if (regD != 15 && regN != 15 && regM != 15)
-             gate = True;
+              gate = True;
         }
      }
 
      if (gate) {
-        IRTemp irt_regN    = newTemp(Ity_I32);
-        IRTemp irt_regM    = newTemp(Ity_I32);
-        IRTemp irt_diff_lo = newTemp(Ity_I32);
-        IRTemp irt_diff_hi = newTemp(Ity_I32);
-        IRTemp irt_res_lo  = newTemp(Ity_I32);
-        IRTemp irt_res_hi  = newTemp(Ity_I32);
-
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
-
-        assign( irt_diff_lo, 
-                binop( Iop_Sub32, 
-                       binop(Iop_Sar32, 
-                             binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)), 
-                             mkU8(16)), 
-                       binop(Iop_Sar32, 
-                             binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 
-                             mkU8(16))) );
-
-        assign( irt_diff_hi, binop( Iop_Sub32, 
-                                    binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)), 
-                                    binop(Iop_Sar32, mkexpr(irt_regM), mkU8(16))) );
-
-        armSignedSatQ( irt_diff_lo, 0x10, &irt_res_lo, NULL );
-        armSignedSatQ( irt_diff_hi, 0x10, &irt_res_hi, NULL );
+        IRTemp rNt  = newTemp(Ity_I32);
+        IRTemp rMt  = newTemp(Ity_I32);
+        IRTemp res  = newTemp(Ity_I32);
+        IRTemp reso = newTemp(Ity_I32);
 
-        IRExpr* ire_result 
-          = binop( Iop_Or32, binop(Iop_Shl32, mkexpr(irt_res_hi), mkU8(16)), 
-                   binop(Iop_And32, mkexpr(irt_res_lo), mkU32(0xFFFF)) );
+        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
 
+        assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt)));
         if (isT)
-           putIRegT( regD, ire_result, condT );
+           putIRegT( regD, mkexpr(res), condT );
         else
-           putIRegA( regD, ire_result, condT, Ijk_Boring );
+           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
+
+        assign(reso, unop(Iop_Not32,
+                          binop(Iop_HSub8Sx4, mkexpr(rNt), mkexpr(rMt))));
+        set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
 
-        DIP( "qsub16%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
+        DIP("ssub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
         return True;
      }
      /* fall through */
    }
 
-   /* ------------------- qsax<c> <Rd>,<Rn>,<Rm> ------------------- */
-   /* note: the hardware seems to construct the result differently
-      from wot the manual says. */
+   /* ------------------ qadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
    {
      UInt regD = 99, regN = 99, regM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
+        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
@@ -9235,7 +9046,7 @@ static Bool decode_V6MEDIA_instruction (
      } else {
         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
             INSNA(11,8)  == BITS4(1,1,1,1)         &&
-            INSNA(7,4)   == BITS4(0,1,0,1)) {
+            INSNA(7,4)   == BITS4(1,0,0,1)) {
            regD = INSNA(15,12);
            regN = INSNA(19,16);
            regM = INSNA(3,0);
@@ -9245,56 +9056,32 @@ static Bool decode_V6MEDIA_instruction (
      }
 
      if (gate) {
-        IRTemp irt_regN     = newTemp(Ity_I32);
-        IRTemp irt_regM     = newTemp(Ity_I32);
-        IRTemp irt_sum      = newTemp(Ity_I32);
-        IRTemp irt_diff     = newTemp(Ity_I32);
-        IRTemp irt_sum_res  = newTemp(Ity_I32);
-        IRTemp irt_diff_res = newTemp(Ity_I32);
-
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
-
-        assign( irt_diff, 
-                binop( Iop_Sub32, 
-                       binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
-                       binop( Iop_Sar32, 
-                              binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 
-                              mkU8(16) ) ) );
-        armSignedSatQ( irt_diff, 0x10, &irt_diff_res, NULL);
-
-        assign( irt_sum, 
-                binop( Iop_Add32, 
-                       binop( Iop_Sar32, 
-                              binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 
-                              mkU8(16) ), 
-                       binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) )) );
-        armSignedSatQ( irt_sum, 0x10, &irt_sum_res, NULL );
+        IRTemp rNt   = newTemp(Ity_I32);
+        IRTemp rMt   = newTemp(Ity_I32);
+        IRTemp res_q = newTemp(Ity_I32);
 
-        IRExpr* ire_result = binop( Iop_Or32, 
-                                    binop( Iop_Shl32, mkexpr(irt_diff_res), 
-                                           mkU8(16) ), 
-                                    binop( Iop_And32, mkexpr(irt_sum_res), 
-                                           mkU32(0xFFFF)) );
+        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
 
-        if (isT) 
-           putIRegT( regD, ire_result, condT );
+        assign(res_q, binop(Iop_QAdd8Sx4, mkexpr(rNt), mkexpr(rMt)));
+        if (isT)
+           putIRegT( regD, mkexpr(res_q), condT );
         else
-           putIRegA( regD, ire_result, condT, Ijk_Boring );
+           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
 
-        DIP( "qsax%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
+        DIP("qadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
         return True;
      }
      /* fall through */
    }
 
-   /* ------------------- qasx<c> <Rd>,<Rn>,<Rm> ------------------- */
+   /* ------------------ qsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
    {
      UInt regD = 99, regN = 99, regM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
+        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
@@ -9304,7 +9091,7 @@ static Bool decode_V6MEDIA_instruction (
      } else {
         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
             INSNA(11,8)  == BITS4(1,1,1,1)         &&
-            INSNA(7,4)   == BITS4(0,0,1,1)) {
+            INSNA(7,4)   == BITS4(1,1,1,1)) {
            regD = INSNA(15,12);
            regN = INSNA(19,16);
            regM = INSNA(3,0);
@@ -9314,55 +9101,32 @@ static Bool decode_V6MEDIA_instruction (
      }
 
      if (gate) {
-        IRTemp irt_regN     = newTemp(Ity_I32);
-        IRTemp irt_regM     = newTemp(Ity_I32);
-        IRTemp irt_sum      = newTemp(Ity_I32);
-        IRTemp irt_diff     = newTemp(Ity_I32);
-        IRTemp irt_res_sum  = newTemp(Ity_I32);
-        IRTemp irt_res_diff = newTemp(Ity_I32);
-
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
-
-        assign( irt_diff,  
-                binop( Iop_Sub32, 
-                       binop( Iop_Sar32, 
-                              binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 
-                              mkU8(16) ), 
-                       binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
-        armSignedSatQ( irt_diff, 0x10, &irt_res_diff, NULL );
+        IRTemp rNt   = newTemp(Ity_I32);
+        IRTemp rMt   = newTemp(Ity_I32);
+        IRTemp res_q = newTemp(Ity_I32);
 
-        assign( irt_sum, 
-                binop( Iop_Add32, 
-                       binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ), 
-                       binop( Iop_Sar32, 
-                              binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ), 
-                              mkU8(16) ) ) );
-        armSignedSatQ( irt_sum, 0x10, &irt_res_sum, NULL );
-       
-        IRExpr* ire_result 
-          = binop( Iop_Or32, 
-                   binop( Iop_Shl32, mkexpr(irt_res_sum), mkU8(16) ), 
-                   binop( Iop_And32, mkexpr(irt_res_diff), mkU32(0xFFFF) ) );
+        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
 
+        assign(res_q, binop(Iop_QSub8Sx4, mkexpr(rNt), mkexpr(rMt)));
         if (isT)
-           putIRegT( regD, ire_result, condT );
+           putIRegT( regD, mkexpr(res_q), condT );
         else
-           putIRegA( regD, ire_result, condT, Ijk_Boring );
+           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
 
-        DIP( "qasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
+        DIP("qsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
         return True;
      }
      /* fall through */
    }
 
-   /* ------------------- sasx<c> <Rd>,<Rn>,<Rm> ------------------- */
+   /* ------------------ uqadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
    {
      UInt regD = 99, regN = 99, regM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
+        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
@@ -9370,9 +9134,9 @@ static Bool decode_V6MEDIA_instruction (
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
+        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
             INSNA(11,8)  == BITS4(1,1,1,1)         &&
-            INSNA(7,4)   == BITS4(0,0,1,1)) {
+            (INSNA(7,4)  == BITS4(1,0,0,1))) {
            regD = INSNA(15,12);
            regN = INSNA(19,16);
            regM = INSNA(3,0);
@@ -9382,371 +9146,212 @@ static Bool decode_V6MEDIA_instruction (
      }
 
      if (gate) {
-        IRTemp irt_regN = newTemp(Ity_I32);
-        IRTemp irt_regM = newTemp(Ity_I32);
-        IRTemp irt_sum  = newTemp(Ity_I32);
-        IRTemp irt_diff = newTemp(Ity_I32);
-
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
+        IRTemp rNt   = newTemp(Ity_I32);
+        IRTemp rMt   = newTemp(Ity_I32);
+        IRTemp res_q = newTemp(Ity_I32);
 
-        assign( irt_diff,  
-                binop( Iop_Sub32, 
-                       binop( Iop_Sar32, 
-                              binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 
-                              mkU8(16) ), 
-                       binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
-
-        assign( irt_sum, 
-                binop( Iop_Add32, 
-                       binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ), 
-                       binop( Iop_Sar32, 
-                              binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ), 
-                              mkU8(16) ) ) );
-       
-        IRExpr* ire_result 
-          = binop( Iop_Or32, 
-                   binop( Iop_Shl32, mkexpr(irt_sum), mkU8(16) ), 
-                   binop( Iop_And32, mkexpr(irt_diff), mkU32(0xFFFF) ) );
-
-        IRTemp ge10 = newTemp(Ity_I32);
-        assign(ge10, unop(Iop_Not32, mkexpr(irt_diff)));
-        put_GEFLAG32( 0, 31, mkexpr(ge10), condT );
-        put_GEFLAG32( 1, 31, mkexpr(ge10), condT );
-
-        IRTemp ge32 = newTemp(Ity_I32);
-        assign(ge32, unop(Iop_Not32, mkexpr(irt_sum)));
-        put_GEFLAG32( 2, 31, mkexpr(ge32), condT );
-        put_GEFLAG32( 3, 31, mkexpr(ge32), condT );
+        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
 
+        assign(res_q, binop(Iop_QAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
         if (isT)
-           putIRegT( regD, ire_result, condT );
+           putIRegT( regD, mkexpr(res_q), condT );
         else
-           putIRegA( regD, ire_result, condT, Ijk_Boring );
+           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
 
-        DIP( "sasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
+        DIP("uqadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
         return True;
      }
      /* fall through */
    }
 
-   /* --------------- smuad, smuadx<c><Rd>,<Rn>,<Rm> --------------- */
+   /* ------------------ uqsub8<c> <Rd>,<Rn>,<Rm> ------------------ */
    {
-     UInt regD = 99, regN = 99, regM = 99, bitM = 99;
+     UInt regD = 99, regN = 99, regM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFB2 && (INSNT1(15,0) & 0xF0E0) == 0xF000) {
+        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
-           bitM = INSNT1(4,4);
            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
-            INSNA(15,12) == BITS4(1,1,1,1)         &&
-            (INSNA(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1) ) {
-           regD = INSNA(19,16);
-           regN = INSNA(3,0);
-           regM = INSNA(11,8);
-           bitM = INSNA(5,5);
+        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
+            INSNA(11,8)  == BITS4(1,1,1,1)         &&
+            (INSNA(7,4)  == BITS4(1,1,1,1))) {
+           regD = INSNA(15,12);
+           regN = INSNA(19,16);
+           regM = INSNA(3,0);
            if (regD != 15 && regN != 15 && regM != 15)
-              gate = True;
+             gate = True;
         }
      }
 
      if (gate) {
-        IRTemp irt_regN    = newTemp(Ity_I32);
-        IRTemp irt_regM    = newTemp(Ity_I32);
-        IRTemp irt_prod_lo = newTemp(Ity_I32);
-        IRTemp irt_prod_hi = newTemp(Ity_I32);
-        IRTemp tmpM        = newTemp(Ity_I32);
-
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
+        IRTemp rNt   = newTemp(Ity_I32);
+        IRTemp rMt   = newTemp(Ity_I32);
+        IRTemp res_q = newTemp(Ity_I32);
 
-        assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
-        assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
-
-        assign( irt_prod_lo, 
-                binop( Iop_Mul32, 
-                       binop( Iop_Sar32, 
-                              binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)), 
-                              mkU8(16) ), 
-                       binop( Iop_Sar32, 
-                              binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 
-                              mkU8(16) ) ) );
-        assign( irt_prod_hi, binop(Iop_Mul32, 
-                                   binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)), 
-                                   binop(Iop_Sar32, mkexpr(irt_regM), mkU8(16))) );
-        IRExpr* ire_result 
-           = binop( Iop_Add32, mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) );
+        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
 
+        assign(res_q, binop(Iop_QSub8Ux4, mkexpr(rNt), mkexpr(rMt)));
         if (isT)
-           putIRegT( regD, ire_result, condT );
+           putIRegT( regD, mkexpr(res_q), condT );
         else
-           putIRegA( regD, ire_result, condT, Ijk_Boring );
+           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
 
-        or_into_QFLAG32( binop( Iop_Shr32, 
-                                binop( Iop_And32,
-                                       binop( Iop_Xor32, ire_result, 
-                                              mkexpr(irt_prod_hi) ),
-                                       binop( Iop_Xor32, ire_result, 
-                                              mkexpr(irt_prod_lo) ) ), 
-                                mkU8(31)), condT );
-
-        DIP("smuad%s%s r%u, r%u, r%u\n",
-            bitM ? "x" : "", nCC(conq), regD, regN, regM);
+        DIP("uqsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
         return True;
      }
      /* fall through */
    }
 
-   /* --------------- smlad{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
+   /* ----------------- uhadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
    {
-     UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
+     UInt regD = 99, regN = 99, regM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFB2 && INSNT1(7,5) == BITS3(0,0,0)) {
+        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
-           regA = INSNT1(15,12);
-           bitM = INSNT1(4,4);
-           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
-               && !isBadRegT(regA))
+           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
-            (INSNA(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
-           regD = INSNA(19,16);
-           regA = INSNA(15,12);
-           regN = INSNA(3,0);
-           regM = INSNA(11,8);
-           bitM = INSNA(5,5);
-           if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
+        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
+            INSNA(11,8)  == BITS4(1,1,1,1)         &&
+            INSNA(7,4)   == BITS4(1,0,0,1)) {
+           regD = INSNA(15,12);
+           regN = INSNA(19,16);
+           regM = INSNA(3,0);
+           if (regD != 15 && regN != 15 && regM != 15)
               gate = True;
         }
      }
 
      if (gate) {
-        IRTemp irt_regN    = newTemp(Ity_I32);
-        IRTemp irt_regM    = newTemp(Ity_I32);
-        IRTemp irt_regA    = newTemp(Ity_I32);
-        IRTemp irt_prod_lo = newTemp(Ity_I32);
-        IRTemp irt_prod_hi = newTemp(Ity_I32);
-        IRTemp irt_sum     = newTemp(Ity_I32);
-        IRTemp tmpM        = newTemp(Ity_I32);
-
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
+        IRTemp rNt   = newTemp(Ity_I32);
+        IRTemp rMt   = newTemp(Ity_I32);
+        IRTemp res_q = newTemp(Ity_I32);
 
-        assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
-        assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
-
-        assign( irt_prod_lo, 
-                binop(Iop_Mul32, 
-                      binop(Iop_Sar32, 
-                            binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 
-                            mkU8(16)), 
-                      binop(Iop_Sar32, 
-                            binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ), 
-                            mkU8(16))) );
-        assign( irt_prod_hi, 
-                binop( Iop_Mul32, 
-                       binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ), 
-                       binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
-        assign( irt_sum, binop( Iop_Add32, 
-                                mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) ) );
-
-        IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_sum), mkexpr(irt_regA));
+        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
 
+        assign(res_q, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
         if (isT)
-           putIRegT( regD, ire_result, condT );
+           putIRegT( regD, mkexpr(res_q), condT );
         else
-           putIRegA( regD, ire_result, condT, Ijk_Boring );
+           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
 
-        or_into_QFLAG32( binop( Iop_Shr32, 
-                                binop( Iop_And32,
-                                       binop( Iop_Xor32, mkexpr(irt_sum), 
-                                              mkexpr(irt_prod_lo) ),
-                                       binop( Iop_Xor32, mkexpr(irt_sum), 
-                                              mkexpr(irt_prod_hi) ) ), 
-                                mkU8(31)), condT );
-        or_into_QFLAG32( binop( Iop_Shr32, 
-                                binop( Iop_And32,
-                                       binop( Iop_Xor32, ire_result, 
-                                              mkexpr(irt_sum) ),
-                                       binop( Iop_Xor32, ire_result, 
-                                              mkexpr(irt_regA) ) ), 
-                                mkU8(31)), condT );
-
-        DIP("smlad%s%s r%u, r%u, r%u, r%u\n",
-            bitM ? "x" : "", nCC(conq), regD, regN, regM, regA);
+        DIP("uhadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
         return True;
      }
      /* fall through */
    }
 
-   /* ----- smlabb, smlabt, smlatb, smlatt <Rd>,<Rn>,<Rm>,<Ra> ----- */
+   /* ----------------- shadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
    {
-     UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99, bitN = 99;
+     UInt regD = 99, regN = 99, regM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFB1 && INSNT1(7,6) == BITS2(0,0)) {
+        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
-           regA = INSNT1(15,12);
-           bitM = INSNT1(4,4);
-           bitN = INSNT1(5,5);
-           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
-               && !isBadRegT(regA))
+           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) &&
-            (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(1,0,0,0)) {
-           regD = INSNA(19,16);
-           regN = INSNA(3,0);
-           regM = INSNA(11,8);
-           regA = INSNA(15,12);
-           bitM = INSNA(6,6);
-           bitN = INSNA(5,5);
-           if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
+        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
+            INSNA(11,8)  == BITS4(1,1,1,1)         &&
+            INSNA(7,4)   == BITS4(1,0,0,1)) {
+           regD = INSNA(15,12);
+           regN = INSNA(19,16);
+           regM = INSNA(3,0);
+           if (regD != 15 && regN != 15 && regM != 15)
               gate = True;
         }
      }
 
      if (gate) {
-        IRTemp irt_regA = newTemp(Ity_I32);
-        IRTemp irt_prod = newTemp(Ity_I32);
+        IRTemp rNt   = newTemp(Ity_I32);
+        IRTemp rMt   = newTemp(Ity_I32);
+        IRTemp res_q = newTemp(Ity_I32);
 
-        assign( irt_prod, 
-                binop(Iop_Mul32, 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32,
-                                  isT ? getIRegT(regN) : getIRegA(regN),
-                                  mkU8(bitN ? 0 : 16)),
-                            mkU8(16)), 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32,
-                                  isT ? getIRegT(regM) : getIRegA(regM),
-                                  mkU8(bitM ? 0 : 16)), 
-                            mkU8(16))) );
-
-        assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
-
-        IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_prod), mkexpr(irt_regA));
+        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
 
+        assign(res_q, binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt)));
         if (isT)
-           putIRegT( regD, ire_result, condT );
+           putIRegT( regD, mkexpr(res_q), condT );
         else
-           putIRegA( regD, ire_result, condT, Ijk_Boring );
+           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
 
-        or_into_QFLAG32( binop( Iop_Shr32, 
-                                binop( Iop_And32,
-                                       binop(Iop_Xor32, 
-                                             ire_result, mkexpr(irt_prod)),
-                                       binop(Iop_Xor32, 
-                                             ire_result, mkexpr(irt_regA)) ), 
-                                mkU8(31)), 
-                         condT );
-
-        DIP( "smla%c%c%s r%u, r%u, r%u, r%u\n", 
-             bitN ? 't' : 'b', bitM ? 't' : 'b', 
-             nCC(conq), regD, regN, regM, regA );
+        DIP("shadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
         return True;
      }
      /* fall through */
    }
 
-   /* ----- smlawb, smlawt <Rd>,<Rn>,<Rm>,<Ra> ----- */
+   /* ------------------ qadd16<c> <Rd>,<Rn>,<Rm> ------------------ */
    {
-     UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
+     UInt regD = 99, regN = 99, regM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFB3 && INSNT1(7,5) == BITS3(0,0,0)) {
+        if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
-           regA = INSNT1(15,12);
-           bitM = INSNT1(4,4);
-           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
-               && !isBadRegT(regA))
+           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
-            (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,0,0)) {
-           regD = INSNA(19,16);
-           regN = INSNA(3,0);
-           regM = INSNA(11,8);
-           regA = INSNA(15,12);
-           bitM = INSNA(6,6);
-           if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
+        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
+            INSNA(11,8)  == BITS4(1,1,1,1)         &&
+            INSNA(7,4)   == BITS4(0,0,0,1)) {
+           regD = INSNA(15,12);
+           regN = INSNA(19,16);
+           regM = INSNA(3,0);
+           if (regD != 15 && regN != 15 && regM != 15)
               gate = True;
         }
      }
 
      if (gate) {
-        IRTemp irt_regA = newTemp(Ity_I32);
-        IRTemp irt_prod = newTemp(Ity_I64);
+        IRTemp rNt   = newTemp(Ity_I32);
+        IRTemp rMt   = newTemp(Ity_I32);
+        IRTemp res_q = newTemp(Ity_I32);
 
-        assign( irt_prod, 
-                binop(Iop_MullS32, 
-                      isT ? getIRegT(regN) : getIRegA(regN),
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32,
-                                  isT ? getIRegT(regM) : getIRegA(regM),
-                                  mkU8(bitM ? 0 : 16)), 
-                            mkU8(16))) );
-
-        assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
-
-        IRTemp prod32 = newTemp(Ity_I32);
-        assign(prod32,
-               binop(Iop_Or32,
-                     binop(Iop_Shl32, unop(Iop_64HIto32, mkexpr(irt_prod)), mkU8(16)),
-                     binop(Iop_Shr32, unop(Iop_64to32, mkexpr(irt_prod)), mkU8(16))
-        ));
-
-        IRExpr* ire_result = binop(Iop_Add32, mkexpr(prod32), mkexpr(irt_regA));
+        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
 
+        assign(res_q, binop(Iop_QAdd16Sx2, mkexpr(rNt), mkexpr(rMt)));
         if (isT)
-           putIRegT( regD, ire_result, condT );
+           putIRegT( regD, mkexpr(res_q), condT );
         else
-           putIRegA( regD, ire_result, condT, Ijk_Boring );
+           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
 
-        or_into_QFLAG32( binop( Iop_Shr32, 
-                                binop( Iop_And32,
-                                       binop(Iop_Xor32, 
-                                             ire_result, mkexpr(prod32)),
-                                       binop(Iop_Xor32, 
-                                             ire_result, mkexpr(irt_regA)) ), 
-                                mkU8(31)), 
-                         condT );
-
-        DIP( "smlaw%c%s r%u, r%u, r%u, r%u\n", 
-             bitM ? 't' : 'b', 
-             nCC(conq), regD, regN, regM, regA );
+        DIP("qadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
         return True;
      }
      /* fall through */
    }
 
-   /* ------------------ uqsub8<c> <Rd>,<Rn>,<Rm> ------------------ */
+   /* ------------------ qsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
    {
      UInt regD = 99, regN = 99, regM = 99;
      Bool gate = False;
 
-     if (isT) {
-        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
+      if (isT) {
+        if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
@@ -9754,9 +9359,9 @@ static Bool decode_V6MEDIA_instruction (
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
+        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
             INSNA(11,8)  == BITS4(1,1,1,1)         &&
-            (INSNA(7,4)  == BITS4(1,1,1,1))) {
+            INSNA(7,4)   == BITS4(0,1,1,1)) {
            regD = INSNA(15,12);
            regN = INSNA(19,16);
            regM = INSNA(3,0);
@@ -9766,81 +9371,40 @@ static Bool decode_V6MEDIA_instruction (
      }
 
      if (gate) {
-        IRTemp irt_regN    = newTemp(Ity_I32);
-        IRTemp irt_regM    = newTemp(Ity_I32);
-        IRTemp irt_diff_l0 = newTemp(Ity_I32);
-        IRTemp irt_diff_l1 = newTemp(Ity_I32);
-        IRTemp irt_diff_l2 = newTemp(Ity_I32);
-        IRTemp irt_diff_l3 = newTemp(Ity_I32);
-        IRTemp irt_sat_l0  = newTemp(Ity_I32);
-        IRTemp irt_sat_l1  = newTemp(Ity_I32);
-        IRTemp irt_sat_l2  = newTemp(Ity_I32);
-        IRTemp irt_sat_l3  = newTemp(Ity_I32);
-
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
+        IRTemp rNt   = newTemp(Ity_I32);
+        IRTemp rMt   = newTemp(Ity_I32);
+        IRTemp res_q = newTemp(Ity_I32);
 
-        assign( irt_diff_l0, 
-                binop(Iop_Sub32, 
-                      binop(Iop_And32, mkexpr(irt_regN), mkU32(0xff)),  
-                      binop(Iop_And32, mkexpr(irt_regM), mkU32(0xff))) );
-        assign( irt_diff_l1, 
-                binop(Iop_Sub32, 
-                      binop(Iop_And32, 
-                            binop(Iop_Shr32, mkexpr(irt_regN), mkU8(8)),
-                            mkU32(0xff)), 
-                      binop(Iop_And32, 
-                            binop(Iop_Shr32, mkexpr(irt_regM), mkU8(8)),
-                            mkU32(0xff))) );
-        assign( irt_diff_l2, 
-                binop(Iop_Sub32, 
-                      binop(Iop_And32, 
-                            binop(Iop_Shr32, mkexpr(irt_regN), mkU8(16)),
-                            mkU32(0xff)),
-                      binop(Iop_And32, 
-                            binop(Iop_Shr32, mkexpr(irt_regM), mkU8(16)), 
-                            mkU32(0xff))) );
-        assign( irt_diff_l3,
-                binop(Iop_Sub32, 
-                      binop(Iop_And32, 
-                            binop(Iop_Shr32, mkexpr(irt_regN), mkU8(24)),
-                            mkU32(0xff)), 
-                      binop(Iop_And32, 
-                            binop(Iop_Shr32, mkexpr(irt_regM), mkU8(24)),
-                            mkU32(0xff) )) );
-
-        armUnsignedSatQ( &irt_sat_l0, NULL, irt_diff_l0, 0x8 );
-        armUnsignedSatQ( &irt_sat_l1, NULL, irt_diff_l1, 0x8 );
-        armUnsignedSatQ( &irt_sat_l2, NULL, irt_diff_l2, 0x8 );
-        armUnsignedSatQ( &irt_sat_l3, NULL, irt_diff_l3, 0x8 );
-
-        IRExpr* ire_res_a = binop(Iop_Or32, mkexpr(irt_sat_l0), 
-                                  binop(Iop_Shl32, mkexpr(irt_sat_l1), mkU8(8)));
-        IRExpr* ire_res_b = binop(Iop_Or32, 
-                                  binop(Iop_Shl32, mkexpr(irt_sat_l2), mkU8(16)),
-                                  ire_res_a);
-        IRExpr* ire_result = binop(Iop_Or32, 
-                                   binop(Iop_Shl32, mkexpr(irt_sat_l3), mkU8(24)),
-                                   ire_res_b);
+        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
 
+        assign(res_q, binop(Iop_QSub16Sx2, mkexpr(rNt), mkexpr(rMt)));
         if (isT)
-           putIRegT( regD, ire_result, condT );
+           putIRegT( regD, mkexpr(res_q), condT );
         else
-           putIRegA( regD, ire_result, condT, Ijk_Boring );
+           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
 
-        DIP("uqsub8%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM);
+        DIP("qsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
         return True;
      }
      /* fall through */
    }
 
-   /* ------------------ uqadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
+   /////////////////////////////////////////////////////////////////
+   /////////////////////////////////////////////////////////////////
+   /////////////////////////////////////////////////////////////////
+   /////////////////////////////////////////////////////////////////
+   /////////////////////////////////////////////////////////////////
+
+   /* ------------------- qsax<c> <Rd>,<Rn>,<Rm> ------------------- */
+   /* note: the hardware seems to construct the result differently
+      from wot the manual says. */
    {
      UInt regD = 99, regN = 99, regM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
+        if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
@@ -9848,9 +9412,9 @@ static Bool decode_V6MEDIA_instruction (
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
+        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
             INSNA(11,8)  == BITS4(1,1,1,1)         &&
-            (INSNA(7,4)  == BITS4(1,0,0,1))) {
+            INSNA(7,4)   == BITS4(0,1,0,1)) {
            regD = INSNA(15,12);
            regN = INSNA(19,16);
            regM = INSNA(3,0);
@@ -9860,83 +9424,56 @@ static Bool decode_V6MEDIA_instruction (
      }
 
      if (gate) {
-        IRTemp irt_regN   = newTemp(Ity_I32);
-        IRTemp irt_regM   = newTemp(Ity_I32);
-        IRTemp irt_sum_l0 = newTemp(Ity_I32);
-        IRTemp irt_sum_l1 = newTemp(Ity_I32);
-        IRTemp irt_sum_l2 = newTemp(Ity_I32);
-        IRTemp irt_sum_l3 = newTemp(Ity_I32);
-        IRTemp irt_sat_l0 = newTemp(Ity_I32);
-        IRTemp irt_sat_l1 = newTemp(Ity_I32);
-        IRTemp irt_sat_l2 = newTemp(Ity_I32);
-        IRTemp irt_sat_l3 = newTemp(Ity_I32);
+        IRTemp irt_regN     = newTemp(Ity_I32);
+        IRTemp irt_regM     = newTemp(Ity_I32);
+        IRTemp irt_sum      = newTemp(Ity_I32);
+        IRTemp irt_diff     = newTemp(Ity_I32);
+        IRTemp irt_sum_res  = newTemp(Ity_I32);
+        IRTemp irt_diff_res = newTemp(Ity_I32);
 
         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
 
-        assign( irt_sum_l0,
-                binop(Iop_Add32, 
-                      binop(Iop_And32, mkexpr(irt_regN), mkU32(0xff)),
-                      binop(Iop_And32, mkexpr(irt_regM), mkU32(0xff))) );
-        assign( irt_sum_l1,
-                binop(Iop_Add32, 
-                      binop(Iop_And32, 
-                            binop(Iop_Shr32, mkexpr(irt_regN), mkU8(8)), 
-                            mkU32(0xff)), 
-                      binop(Iop_And32, 
-                            binop(Iop_Shr32, mkexpr(irt_regM), mkU8(8)), 
-                            mkU32(0xff))) );
-        assign( irt_sum_l2,
-                binop(Iop_Add32, 
-                      binop(Iop_And32, 
-                            binop(Iop_Shr32, mkexpr(irt_regN), mkU8(16)), 
-                            mkU32(0xff)), 
-                      binop(Iop_And32, 
-                            binop(Iop_Shr32, mkexpr(irt_regM), mkU8(16)), 
-                            mkU32(0xff))) );
-        assign( irt_sum_l3, 
-                binop(Iop_Add32, 
-                      binop(Iop_And32, 
-                            binop(Iop_Shr32, mkexpr(irt_regN), mkU8(24)), 
-                            mkU32(0xff)), 
-                      binop(Iop_And32, 
-                            binop(Iop_Shr32, mkexpr(irt_regM), mkU8(24)), 
-                            mkU32(0xff))) );
-
-        armUnsignedSatQ( &irt_sat_l0, NULL, irt_sum_l0, 0x8 );
-        armUnsignedSatQ( &irt_sat_l1, NULL, irt_sum_l1, 0x8 );
-        armUnsignedSatQ( &irt_sat_l2, NULL, irt_sum_l2, 0x8 );
-        armUnsignedSatQ( &irt_sat_l3, NULL, irt_sum_l3, 0x8 );
-
-        IRExpr* ire_res_a  = binop(Iop_Or32, mkexpr(irt_sat_l0), 
-                                   binop(Iop_Shl32, mkexpr(irt_sat_l1), mkU8(8)));
-        IRExpr* ire_res_b  = binop(Iop_Or32, 
-                                   binop(Iop_Shl32, mkexpr(irt_sat_l2), mkU8(16)),
-                                   ire_res_a);
-        IRExpr* ire_result = binop(Iop_Or32, 
-                                   binop(Iop_Shl32, mkexpr(irt_sat_l3), mkU8(24)),
-                                   ire_res_b);
+        assign( irt_diff, 
+                binop( Iop_Sub32, 
+                       binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
+                       binop( Iop_Sar32, 
+                              binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 
+                              mkU8(16) ) ) );
+        armSignedSatQ( irt_diff, 0x10, &irt_diff_res, NULL);
 
-        if (isT)
+        assign( irt_sum, 
+                binop( Iop_Add32, 
+                       binop( Iop_Sar32, 
+                              binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 
+                              mkU8(16) ), 
+                       binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) )) );
+        armSignedSatQ( irt_sum, 0x10, &irt_sum_res, NULL );
+
+        IRExpr* ire_result = binop( Iop_Or32, 
+                                    binop( Iop_Shl32, mkexpr(irt_diff_res), 
+                                           mkU8(16) ), 
+                                    binop( Iop_And32, mkexpr(irt_sum_res), 
+                                           mkU32(0xFFFF)) );
+
+        if (isT) 
            putIRegT( regD, ire_result, condT );
         else
            putIRegA( regD, ire_result, condT, Ijk_Boring );
 
-        DIP("uqadd8%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM);
+        DIP( "qsax%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
         return True;
      }
      /* fall through */
    }
 
-   /* ------------------- sel<c> <Rd>,<Rn>,<Rm> -------------------- */
-   /* fixme: fix up the test in v6media.c so that we can pass the ge
-      flags as part of the test. */
+   /* ------------------- qasx<c> <Rd>,<Rn>,<Rm> ------------------- */
    {
      UInt regD = 99, regN = 99, regM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF080) {
+        if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
@@ -9944,9 +9481,9 @@ static Bool decode_V6MEDIA_instruction (
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
+        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
             INSNA(11,8)  == BITS4(1,1,1,1)         &&
-            INSNA(7,4)   == BITS4(1,0,1,1)) {
+            INSNA(7,4)   == BITS4(0,0,1,1)) {
            regD = INSNA(15,12);
            regN = INSNA(19,16);
            regM = INSNA(3,0);
@@ -9956,73 +9493,55 @@ static Bool decode_V6MEDIA_instruction (
      }
 
      if (gate) {
-        IRTemp irt_ge_flag0 = newTemp(Ity_I32);
-        IRTemp irt_ge_flag1 = newTemp(Ity_I32);
-        IRTemp irt_ge_flag2 = newTemp(Ity_I32);
-        IRTemp irt_ge_flag3 = newTemp(Ity_I32);
-
-        assign( irt_ge_flag0, get_GEFLAG32(0) );
-        assign( irt_ge_flag1, get_GEFLAG32(1) );
-        assign( irt_ge_flag2, get_GEFLAG32(2) );
-        assign( irt_ge_flag3, get_GEFLAG32(3) );
+        IRTemp irt_regN     = newTemp(Ity_I32);
+        IRTemp irt_regM     = newTemp(Ity_I32);
+        IRTemp irt_sum      = newTemp(Ity_I32);
+        IRTemp irt_diff     = newTemp(Ity_I32);
+        IRTemp irt_res_sum  = newTemp(Ity_I32);
+        IRTemp irt_res_diff = newTemp(Ity_I32);
 
-        IRExpr* ire_ge_flag0_or 
-          = binop(Iop_Or32, mkexpr(irt_ge_flag0), 
-                  binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag0)));
-        IRExpr* ire_ge_flag1_or 
-          = binop(Iop_Or32, mkexpr(irt_ge_flag1), 
-                  binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag1)));
-        IRExpr* ire_ge_flag2_or 
-          = binop(Iop_Or32, mkexpr(irt_ge_flag2), 
-                  binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag2)));
-        IRExpr* ire_ge_flag3_or 
-          = binop(Iop_Or32, mkexpr(irt_ge_flag3), 
-                  binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag3)));
+        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
+        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
 
-        IRExpr* ire_ge_flags 
-          = binop( Iop_Or32, 
-                   binop(Iop_Or32, 
-                         binop(Iop_And32, 
-                               binop(Iop_Sar32, ire_ge_flag0_or, mkU8(31)), 
-                               mkU32(0x000000ff)), 
-                         binop(Iop_And32, 
-                               binop(Iop_Sar32, ire_ge_flag1_or, mkU8(31)), 
-                               mkU32(0x0000ff00))), 
-                   binop(Iop_Or32, 
-                         binop(Iop_And32, 
-                               binop(Iop_Sar32, ire_ge_flag2_or, mkU8(31)), 
-                               mkU32(0x00ff0000)), 
-                         binop(Iop_And32, 
-                               binop(Iop_Sar32, ire_ge_flag3_or, mkU8(31)), 
-                               mkU32(0xff000000))) );
+        assign( irt_diff,  
+                binop( Iop_Sub32, 
+                       binop( Iop_Sar32, 
+                              binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 
+                              mkU8(16) ), 
+                       binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
+        armSignedSatQ( irt_diff, 0x10, &irt_res_diff, NULL );
 
+        assign( irt_sum, 
+                binop( Iop_Add32, 
+                       binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ), 
+                       binop( Iop_Sar32, 
+                              binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ), 
+                              mkU8(16) ) ) );
+        armSignedSatQ( irt_sum, 0x10, &irt_res_sum, NULL );
+       
         IRExpr* ire_result 
-          = binop(Iop_Or32, 
-                  binop(Iop_And32,
-                        isT ? getIRegT(regN) : getIRegA(regN),
-                        ire_ge_flags ), 
-                  binop(Iop_And32,
-                        isT ? getIRegT(regM) : getIRegA(regM),
-                        unop(Iop_Not32, ire_ge_flags)));
+          = binop( Iop_Or32, 
+                   binop( Iop_Shl32, mkexpr(irt_res_sum), mkU8(16) ), 
+                   binop( Iop_And32, mkexpr(irt_res_diff), mkU32(0xFFFF) ) );
 
         if (isT)
            putIRegT( regD, ire_result, condT );
         else
            putIRegA( regD, ire_result, condT, Ijk_Boring );
 
-        DIP("sel%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
+        DIP( "qasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
         return True;
      }
      /* fall through */
    }
 
-   /* ------------------ qsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
+   /* ------------------- sasx<c> <Rd>,<Rn>,<Rm> ------------------- */
    {
      UInt regD = 99, regN = 99, regM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
+        if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
@@ -10030,9 +9549,9 @@ static Bool decode_V6MEDIA_instruction (
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
+        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
             INSNA(11,8)  == BITS4(1,1,1,1)         &&
-            INSNA(7,4)   == BITS4(1,1,1,1)) {
+            INSNA(7,4)   == BITS4(0,0,1,1)) {
            regD = INSNA(15,12);
            regN = INSNA(19,16);
            regM = INSNA(3,0);
@@ -10042,459 +9561,373 @@ static Bool decode_V6MEDIA_instruction (
      }
 
      if (gate) {
-        IRTemp irt_regN      = newTemp(Ity_I32);
-        IRTemp irt_regM      = newTemp(Ity_I32);
-        IRTemp irt_diff1     = newTemp(Ity_I32);
-        IRTemp irt_diff2     = newTemp(Ity_I32);
-        IRTemp irt_diff3     = newTemp(Ity_I32);
-        IRTemp irt_diff4     = newTemp(Ity_I32);
-        IRTemp irt_diff1_sat = newTemp(Ity_I32);
-        IRTemp irt_diff2_sat = newTemp(Ity_I32);
-        IRTemp irt_diff3_sat = newTemp(Ity_I32);
-        IRTemp irt_diff4_sat = newTemp(Ity_I32);
+        IRTemp irt_regN = newTemp(Ity_I32);
+        IRTemp irt_regM = newTemp(Ity_I32);
+        IRTemp irt_sum  = newTemp(Ity_I32);
+        IRTemp irt_diff = newTemp(Ity_I32);
 
         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
 
-        assign( irt_diff1, 
-                binop(Iop_Sub32, 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regN), mkU8(24)), 
-                            mkU8(24)), 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regM), mkU8(24)), 
-                            mkU8(24))) );
-        assign( irt_diff2, 
-                binop(Iop_Sub32, 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)), 
-                            mkU8(24)), 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 
-                            mkU8(24))) );
-        assign( irt_diff3,
-                binop(Iop_Sub32, 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regN), mkU8(8)), 
-                            mkU8(24)), 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regM), mkU8(8)), 
-                            mkU8(24))) );
-        assign( irt_diff4, binop(Iop_Sub32, 
-                                 binop(Iop_Sar32, mkexpr(irt_regN), mkU8(24)), 
-                                 binop(Iop_Sar32, mkexpr(irt_regM), mkU8(24))) );
-
-        armSignedSatQ( irt_diff1, 0x8, &irt_diff1_sat, NULL );
-        armSignedSatQ( irt_diff2, 0x8, &irt_diff2_sat, NULL );
-        armSignedSatQ( irt_diff3, 0x8, &irt_diff3_sat, NULL );
-        armSignedSatQ( irt_diff4, 0x8, &irt_diff4_sat, NULL );
+        assign( irt_diff,  
+                binop( Iop_Sub32, 
+                       binop( Iop_Sar32, 
+                              binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 
+                              mkU8(16) ), 
+                       binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
 
+        assign( irt_sum, 
+                binop( Iop_Add32, 
+                       binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ), 
+                       binop( Iop_Sar32, 
+                              binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ), 
+                              mkU8(16) ) ) );
+       
         IRExpr* ire_result 
           = binop( Iop_Or32, 
-                   binop(Iop_Or32, 
-                         binop(Iop_And32, mkexpr(irt_diff1_sat), mkU32(0x000000ff)),
-                         binop(Iop_And32, 
-                               binop(Iop_Shl32, mkexpr(irt_diff2_sat), mkU8(8)),
-                               mkU32(0x0000ff00))), 
-                   binop(Iop_Or32,
-                         binop(Iop_And32,
-                               binop(Iop_Shl32, mkexpr(irt_diff3_sat), mkU8(16)),
-                               mkU32(0x00ff0000)),
-                         binop(Iop_Shl32, mkexpr(irt_diff4_sat), mkU8(24))) );
+                   binop( Iop_Shl32, mkexpr(irt_sum), mkU8(16) ), 
+                   binop( Iop_And32, mkexpr(irt_diff), mkU32(0xFFFF) ) );
+
+        IRTemp ge10 = newTemp(Ity_I32);
+        assign(ge10, unop(Iop_Not32, mkexpr(irt_diff)));
+        put_GEFLAG32( 0, 31, mkexpr(ge10), condT );
+        put_GEFLAG32( 1, 31, mkexpr(ge10), condT );
+
+        IRTemp ge32 = newTemp(Ity_I32);
+        assign(ge32, unop(Iop_Not32, mkexpr(irt_sum)));
+        put_GEFLAG32( 2, 31, mkexpr(ge32), condT );
+        put_GEFLAG32( 3, 31, mkexpr(ge32), condT );
 
         if (isT)
            putIRegT( regD, ire_result, condT );
         else
            putIRegA( regD, ire_result, condT, Ijk_Boring );
 
-        DIP( "qsub8%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
+        DIP( "sasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
         return True;
      }
      /* fall through */
    }
 
-   /* ------------------ qadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
+   /* --------------- smuad, smuadx<c><Rd>,<Rn>,<Rm> --------------- */
    {
-     UInt regD = 99, regN = 99, regM = 99;
+     UInt regD = 99, regN = 99, regM = 99, bitM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
+        if (INSNT0(15,4) == 0xFB2 && (INSNT1(15,0) & 0xF0E0) == 0xF000) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
+           bitM = INSNT1(4,4);
            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
-            INSNA(11,8)  == BITS4(1,1,1,1)         &&
-            INSNA(7,4)   == BITS4(1,0,0,1)) {
-           regD = INSNA(15,12);
-           regN = INSNA(19,16);
-           regM = INSNA(3,0);
+        if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
+            INSNA(15,12) == BITS4(1,1,1,1)         &&
+            (INSNA(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1) ) {
+           regD = INSNA(19,16);
+           regN = INSNA(3,0);
+           regM = INSNA(11,8);
+           bitM = INSNA(5,5);
            if (regD != 15 && regN != 15 && regM != 15)
               gate = True;
         }
      }
 
      if (gate) {
-        IRTemp irt_regN     = newTemp(Ity_I32);
-        IRTemp irt_regM     = newTemp(Ity_I32);
-        IRTemp irt_sum1     = newTemp(Ity_I32);
-        IRTemp irt_sum2     = newTemp(Ity_I32);
-        IRTemp irt_sum3     = newTemp(Ity_I32);
-        IRTemp irt_sum4     = newTemp(Ity_I32);
-        IRTemp irt_sum1_sat = newTemp(Ity_I32);
-        IRTemp irt_sum2_sat = newTemp(Ity_I32);
-        IRTemp irt_sum3_sat = newTemp(Ity_I32);
-        IRTemp irt_sum4_sat = newTemp(Ity_I32);
+        IRTemp irt_regN    = newTemp(Ity_I32);
+        IRTemp irt_regM    = newTemp(Ity_I32);
+        IRTemp irt_prod_lo = newTemp(Ity_I32);
+        IRTemp irt_prod_hi = newTemp(Ity_I32);
+        IRTemp tmpM        = newTemp(Ity_I32);
+
         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
 
-        assign( irt_sum1, 
-                binop(Iop_Add32, 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regN), mkU8(24)), 
-                            mkU8(24)), 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regM), mkU8(24)), 
-                            mkU8(24))) );
-        assign( irt_sum2, 
-                binop(Iop_Add32, 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)), 
-                            mkU8(24)), 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 
-                            mkU8(24))) );
-        assign( irt_sum3, 
-                binop(Iop_Add32, 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regN), mkU8(8)), 
-                            mkU8(24)), 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regM), mkU8(8)), 
-                            mkU8(24))) );
-        assign( irt_sum4, 
-                binop(Iop_Add32, 
-                      binop(Iop_Sar32, mkexpr(irt_regN), mkU8(24)), 
-                      binop(Iop_Sar32, mkexpr(irt_regM), mkU8(24))) );
-
-        armSignedSatQ( irt_sum1, 0x8,&irt_sum1_sat, NULL );
-        armSignedSatQ( irt_sum2, 0x8, &irt_sum2_sat, NULL );
-        armSignedSatQ( irt_sum3, 0x8, &irt_sum3_sat, NULL );
-        armSignedSatQ( irt_sum4, 0x8, &irt_sum4_sat, NULL );
+        assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
+        assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
 
+        assign( irt_prod_lo, 
+                binop( Iop_Mul32, 
+                       binop( Iop_Sar32, 
+                              binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)), 
+                              mkU8(16) ), 
+                       binop( Iop_Sar32, 
+                              binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 
+                              mkU8(16) ) ) );
+        assign( irt_prod_hi, binop(Iop_Mul32, 
+                                   binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)), 
+                                   binop(Iop_Sar32, mkexpr(irt_regM), mkU8(16))) );
         IRExpr* ire_result 
-          = binop( Iop_Or32, 
-                   binop(Iop_Or32, 
-                         binop(Iop_And32, mkexpr(irt_sum1_sat), mkU32(0x000000ff)), 
-                         binop(Iop_And32, 
-                               binop(Iop_Shl32, mkexpr(irt_sum2_sat), mkU8(8)), 
-                               mkU32(0x0000ff00))), 
-                   binop(Iop_Or32, 
-                         binop(Iop_And32, 
-                               binop(Iop_Shl32, mkexpr(irt_sum3_sat), mkU8(16)),
-                               mkU32(0x00ff0000)), 
-                         binop(Iop_Shl32, mkexpr(irt_sum4_sat), mkU8(24))) );
+           = binop( Iop_Add32, mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) );
 
         if (isT)
            putIRegT( regD, ire_result, condT );
         else
            putIRegA( regD, ire_result, condT, Ijk_Boring );
 
-        DIP( "qadd8%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
+        or_into_QFLAG32( binop( Iop_Shr32, 
+                                binop( Iop_And32,
+                                       binop( Iop_Xor32, ire_result, 
+                                              mkexpr(irt_prod_hi) ),
+                                       binop( Iop_Xor32, ire_result, 
+                                              mkexpr(irt_prod_lo) ) ), 
+                                mkU8(31)), condT );
+
+        DIP("smuad%s%s r%u, r%u, r%u\n",
+            bitM ? "x" : "", nCC(conq), regD, regN, regM);
         return True;
      }
      /* fall through */
    }
 
-   /* ----------------- shadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
+   /* --------------- smlad{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
    {
-     UInt regD = 99, regN = 99, regM = 99;
+     UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
+        if (INSNT0(15,4) == 0xFB2 && INSNT1(7,5) == BITS3(0,0,0)) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
-           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
+           regA = INSNT1(15,12);
+           bitM = INSNT1(4,4);
+           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
+               && !isBadRegT(regA))
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
-            INSNA(11,8)  == BITS4(1,1,1,1)         &&
-            INSNA(7,4)   == BITS4(1,0,0,1)) {
-           regD = INSNA(15,12);
-           regN = INSNA(19,16);
-           regM = INSNA(3,0);
-           if (regD != 15 && regN != 15 && regM != 15)
+        if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
+            (INSNA(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
+           regD = INSNA(19,16);
+           regA = INSNA(15,12);
+           regN = INSNA(3,0);
+           regM = INSNA(11,8);
+           bitM = INSNA(5,5);
+           if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
               gate = True;
         }
      }
 
      if (gate) {
-        IRTemp irt_regN = newTemp(Ity_I32);
-        IRTemp irt_regM = newTemp(Ity_I32);
+        IRTemp irt_regN    = newTemp(Ity_I32);
+        IRTemp irt_regM    = newTemp(Ity_I32);
+        IRTemp irt_regA    = newTemp(Ity_I32);
+        IRTemp irt_prod_lo = newTemp(Ity_I32);
+        IRTemp irt_prod_hi = newTemp(Ity_I32);
+        IRTemp irt_sum     = newTemp(Ity_I32);
+        IRTemp tmpM        = newTemp(Ity_I32);
 
         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
+        assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
 
-        IRExpr* ire_sum1 
-                   = binop( Iop_Add32, 
-                            binop(Iop_Sar32, 
-                                  binop(Iop_Shl32, mkexpr(irt_regN), mkU8(24)), 
-                                  mkU8(24)), 
-                            binop(Iop_Sar32, 
-                                  binop(Iop_Shl32, mkexpr(irt_regM), mkU8(24)), 
-                                  mkU8(24)) );
-        IRExpr* ire_sum2 
-                   = binop(Iop_Add32, 
-                           binop(Iop_Sar32, 
-                                 binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)), 
-                                 mkU8(24)), 
-                           binop(Iop_Sar32, 
-                                 binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 
-                                 mkU8(24)));
-        IRExpr* ire_sum3 
-                   = binop(Iop_Add32, 
-                           binop(Iop_Sar32, 
-                                 binop(Iop_Shl32, mkexpr(irt_regN), mkU8(8)), 
-                                 mkU8(24)), 
-                           binop(Iop_Sar32, 
-                                 binop(Iop_Shl32, mkexpr(irt_regM), mkU8(8)), 
-                                 mkU8(24)));
-        IRExpr* ire_sum4 
-                   = binop( Iop_Add32, 
-                            binop(Iop_Sar32, mkexpr(irt_regN), mkU8(24)), 
-                            binop(Iop_Sar32, mkexpr(irt_regM), mkU8(24)) );
+        assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
+        assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
 
-        IRExpr* ire_result 
-                   = binop( Iop_Or32,
-                            binop(Iop_Or32, 
-                                  binop(Iop_And32
-                                        binop(Iop_Sar32, ire_sum1, mkU8(1)),
-                                        mkU32(0x000000ff))
-                                  binop(Iop_And32
-                                        binop(Iop_Shl32, ire_sum2, mkU8(7)), 
-                                        mkU32(0x0000ff00)))
-                            binop(Iop_Or32, 
-                                  binop(Iop_And32
-                                        binop(Iop_Shl32, ire_sum3, mkU8(15)), 
-                                        mkU32(0x00ff0000))
-                                  binop(Iop_And32, 
-                                        binop(Iop_Shl32, ire_sum4, mkU8(23)), 
-                                        mkU32(0xff000000))) );
+        assign( irt_prod_lo, 
+                binop(Iop_Mul32, 
+                      binop(Iop_Sar32, 
+                            binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) )
+                            mkU8(16)), 
+                      binop(Iop_Sar32
+                            binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) )
+                            mkU8(16))) );
+        assign( irt_prod_hi
+                binop( Iop_Mul32, 
+                       binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) )
+                       binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
+        assign( irt_sum, binop( Iop_Add32
+                                mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) ) );
+
+        IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_sum), mkexpr(irt_regA));
 
         if (isT)
            putIRegT( regD, ire_result, condT );
         else
            putIRegA( regD, ire_result, condT, Ijk_Boring );
 
-        DIP( "shadd8%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
+        or_into_QFLAG32( binop( Iop_Shr32, 
+                                binop( Iop_And32,
+                                       binop( Iop_Xor32, mkexpr(irt_sum), 
+                                              mkexpr(irt_prod_lo) ),
+                                       binop( Iop_Xor32, mkexpr(irt_sum), 
+                                              mkexpr(irt_prod_hi) ) ), 
+                                mkU8(31)), condT );
+        or_into_QFLAG32( binop( Iop_Shr32, 
+                                binop( Iop_And32,
+                                       binop( Iop_Xor32, ire_result, 
+                                              mkexpr(irt_sum) ),
+                                       binop( Iop_Xor32, ire_result, 
+                                              mkexpr(irt_regA) ) ), 
+                                mkU8(31)), condT );
+
+        DIP("smlad%s%s r%u, r%u, r%u, r%u\n",
+            bitM ? "x" : "", nCC(conq), regD, regN, regM, regA);
         return True;
      }
      /* fall through */
    }
 
-   /* ----------------- uhadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
-   // merge with shadd8
+   /* ----- smlabb, smlabt, smlatb, smlatt <Rd>,<Rn>,<Rm>,<Ra> ----- */
    {
-     UInt regD = 99, regN = 99, regM = 99;
+     UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99, bitN = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
+        if (INSNT0(15,4) == 0xFB1 && INSNT1(7,6) == BITS2(0,0)) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
-           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
+           regA = INSNT1(15,12);
+           bitM = INSNT1(4,4);
+           bitN = INSNT1(5,5);
+           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
+               && !isBadRegT(regA))
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
-            INSNA(11,8)  == BITS4(1,1,1,1)         &&
-            INSNA(7,4)   == BITS4(1,0,0,1)) {
-           regD = INSNA(15,12);
-           regN = INSNA(19,16);
-           regM = INSNA(3,0);
-           if (regD != 15 && regN != 15 && regM != 15)
+        if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) &&
+            (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(1,0,0,0)) {
+           regD = INSNA(19,16);
+           regN = INSNA(3,0);
+           regM = INSNA(11,8);
+           regA = INSNA(15,12);
+           bitM = INSNA(6,6);
+           bitN = INSNA(5,5);
+           if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
               gate = True;
         }
      }
 
      if (gate) {
-        IRTemp irt_regN = newTemp(Ity_I32);
-        IRTemp irt_regM = newTemp(Ity_I32);
+        IRTemp irt_regA = newTemp(Ity_I32);
+        IRTemp irt_prod = newTemp(Ity_I32);
 
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
+        assign( irt_prod, 
+                binop(Iop_Mul32, 
+                      binop(Iop_Sar32, 
+                            binop(Iop_Shl32,
+                                  isT ? getIRegT(regN) : getIRegA(regN),
+                                  mkU8(bitN ? 0 : 16)),
+                            mkU8(16)), 
+                      binop(Iop_Sar32, 
+                            binop(Iop_Shl32,
+                                  isT ? getIRegT(regM) : getIRegA(regM),
+                                  mkU8(bitM ? 0 : 16)), 
+                            mkU8(16))) );
 
-        IRExpr* ire_sum1 
-                   = binop( Iop_Add32, 
-                            binop(Iop_Shr32, 
-                                  binop(Iop_Shl32, mkexpr(irt_regN), mkU8(24)), 
-                                  mkU8(24)), 
-                            binop(Iop_Shr32, 
-                                  binop(Iop_Shl32, mkexpr(irt_regM), mkU8(24)), 
-                                  mkU8(24)) );
-        IRExpr* ire_sum2 
-                   = binop(Iop_Add32, 
-                           binop(Iop_Shr32, 
-                                 binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)), 
-                                 mkU8(24)), 
-                           binop(Iop_Shr32, 
-                                 binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 
-                                 mkU8(24)));
-        IRExpr* ire_sum3 
-                   = binop(Iop_Add32, 
-                           binop(Iop_Shr32, 
-                                 binop(Iop_Shl32, mkexpr(irt_regN), mkU8(8)), 
-                                 mkU8(24)), 
-                           binop(Iop_Shr32, 
-                                 binop(Iop_Shl32, mkexpr(irt_regM), mkU8(8)), 
-                                 mkU8(24)));
-        IRExpr* ire_sum4 
-                   = binop( Iop_Add32, 
-                            binop(Iop_Shr32, mkexpr(irt_regN), mkU8(24)), 
-                            binop(Iop_Shr32, mkexpr(irt_regM), mkU8(24)) );
+        assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
 
-        IRExpr* ire_result 
-                   = binop( Iop_Or32,
-                            binop(Iop_Or32, 
-                                  binop(Iop_And32, 
-                                        binop(Iop_Sar32, ire_sum1, mkU8(1)),
-                                        mkU32(0x000000ff)), 
-                                  binop(Iop_And32, 
-                                        binop(Iop_Shl32, ire_sum2, mkU8(7)), 
-                                        mkU32(0x0000ff00))), 
-                            binop(Iop_Or32, 
-                                  binop(Iop_And32, 
-                                        binop(Iop_Shl32, ire_sum3, mkU8(15)), 
-                                        mkU32(0x00ff0000)), 
-                                  binop(Iop_And32, 
-                                        binop(Iop_Shl32, ire_sum4, mkU8(23)), 
-                                        mkU32(0xff000000))) );
+        IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_prod), mkexpr(irt_regA));
 
         if (isT)
            putIRegT( regD, ire_result, condT );
         else
            putIRegA( regD, ire_result, condT, Ijk_Boring );
 
-        DIP( "uhadd8%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
+        or_into_QFLAG32( binop( Iop_Shr32, 
+                                binop( Iop_And32,
+                                       binop(Iop_Xor32, 
+                                             ire_result, mkexpr(irt_prod)),
+                                       binop(Iop_Xor32, 
+                                             ire_result, mkexpr(irt_regA)) ), 
+                                mkU8(31)), 
+                         condT );
+
+        DIP( "smla%c%c%s r%u, r%u, r%u, r%u\n", 
+             bitN ? 't' : 'b', bitM ? 't' : 'b', 
+             nCC(conq), regD, regN, regM, regA );
         return True;
      }
      /* fall through */
    }
 
-   /* ------------------- sadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
+   /* ----- smlawb, smlawt <Rd>,<Rn>,<Rm>,<Ra> ----- */
    {
-     UInt regD = 99, regN = 99, regM = 99;
+     UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
+        if (INSNT0(15,4) == 0xFB3 && INSNT1(7,5) == BITS3(0,0,0)) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
-           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
+           regA = INSNT1(15,12);
+           bitM = INSNT1(4,4);
+           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
+               && !isBadRegT(regA))
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
-            INSNA(11,8)  == BITS4(1,1,1,1)         &&
-            (INSNA(7,4)  == BITS4(1,0,0,1))) {
-           regD = INSNA(15,12);
-           regN = INSNA(19,16);
-           regM = INSNA(3,0);
-           if (regD != 15 && regN != 15 && regM != 15)
+        if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
+            (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,0,0)) {
+           regD = INSNA(19,16);
+           regN = INSNA(3,0);
+           regM = INSNA(11,8);
+           regA = INSNA(15,12);
+           bitM = INSNA(6,6);
+           if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
               gate = True;
         }
      }
 
      if (gate) {
-        IRTemp irt_regN = newTemp(Ity_I32);
-        IRTemp irt_regM = newTemp(Ity_I32);
+        IRTemp irt_regA = newTemp(Ity_I32);
+        IRTemp irt_prod = newTemp(Ity_I64);
 
-        IRTemp irt_sum_l0 = newTemp(Ity_I32);
-        IRTemp irt_sum_l1 = newTemp(Ity_I32);
-        IRTemp irt_sum_l2 = newTemp(Ity_I32);
-        IRTemp irt_sum_l3 = newTemp(Ity_I32);
+        assign( irt_prod, 
+                binop(Iop_MullS32, 
+                      isT ? getIRegT(regN) : getIRegA(regN),
+                      binop(Iop_Sar32, 
+                            binop(Iop_Shl32,
+                                  isT ? getIRegT(regM) : getIRegA(regM),
+                                  mkU8(bitM ? 0 : 16)), 
+                            mkU8(16))) );
 
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
+        assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
 
-        assign( irt_sum_l0, 
-                binop(Iop_Add32, 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regN), mkU8(24)), 
-                            mkU8(24)),
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regM), mkU8(24)), 
-                            mkU8(24))) );
-        assign( irt_sum_l1, 
-                binop(Iop_Add32, 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)), 
-                            mkU8(24)), 
-                      binop(Iop_Sar32,
-                            binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 
-                            mkU8(24))) );
-        assign( irt_sum_l2, 
-                binop(Iop_Add32, 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regN), mkU8(8)), 
-                            mkU8(24)), 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regM), mkU8(8)), 
-                            mkU8(24))) );
-        assign( irt_sum_l3, 
-                binop(Iop_Add32, 
-                      binop(Iop_Sar32, mkexpr(irt_regN), mkU8(24)), 
-                      binop(Iop_Sar32, mkexpr(irt_regM), mkU8(24))) );
-
-        put_GEFLAG32( 0, 31, unop(Iop_Not32, mkexpr(irt_sum_l0)), condT );
-        put_GEFLAG32( 1, 31, unop(Iop_Not32, mkexpr(irt_sum_l1)), condT );
-        put_GEFLAG32( 2, 31, unop(Iop_Not32, mkexpr(irt_sum_l2)), condT );
-        put_GEFLAG32( 3, 31, unop(Iop_Not32, mkexpr(irt_sum_l3)), condT );
+        IRTemp prod32 = newTemp(Ity_I32);
+        assign(prod32,
+               binop(Iop_Or32,
+                     binop(Iop_Shl32, unop(Iop_64HIto32, mkexpr(irt_prod)), mkU8(16)),
+                     binop(Iop_Shr32, unop(Iop_64to32, mkexpr(irt_prod)), mkU8(16))
+        ));
 
-        IRExpr* ire_result 
-          = binop( Iop_Or32,
-                   binop(Iop_Shl32, 
-                         binop(Iop_And32, mkexpr(irt_sum_l3), mkU32(0xff)),
-                         mkU8(24)), 
-                   binop(Iop_Or32, 
-                         binop(Iop_Shl32, 
-                               binop(Iop_And32, mkexpr(irt_sum_l2), mkU32(0xff)),
-                               mkU8(16)),  
-                         binop(Iop_Or32, 
-                               binop(Iop_And32, mkexpr(irt_sum_l0), mkU32(0xff)), 
-                               binop(Iop_Shl32, 
-                                     binop(Iop_And32, 
-                                           mkexpr(irt_sum_l1), mkU32(0xff)),  
-                                     mkU8(8)))) );
+        IRExpr* ire_result = binop(Iop_Add32, mkexpr(prod32), mkexpr(irt_regA));
 
         if (isT)
            putIRegT( regD, ire_result, condT );
         else
            putIRegA( regD, ire_result, condT, Ijk_Boring );
 
-        DIP("sadd8%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM);
+        or_into_QFLAG32( binop( Iop_Shr32, 
+                                binop( Iop_And32,
+                                       binop(Iop_Xor32, 
+                                             ire_result, mkexpr(prod32)),
+                                       binop(Iop_Xor32, 
+                                             ire_result, mkexpr(irt_regA)) ), 
+                                mkU8(31)), 
+                         condT );
+
+        DIP( "smlaw%c%s r%u, r%u, r%u, r%u\n", 
+             bitM ? 't' : 'b', 
+             nCC(conq), regD, regN, regM, regA );
         return True;
      }
      /* fall through */
    }
 
-   /* ------------------- ssub8<c> <Rd>,<Rn>,<Rm> ------------------ */
-   // merge with sadd8
+   /* ------------------- sel<c> <Rd>,<Rn>,<Rm> -------------------- */
+   /* fixme: fix up the test in v6media.c so that we can pass the ge
+      flags as part of the test. */
    {
      UInt regD = 99, regN = 99, regM = 99;
      Bool gate = False;
 
      if (isT) {
-        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
+        if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF080) {
            regN = INSNT0(3,0);
            regD = INSNT1(11,8);
            regM = INSNT1(3,0);
@@ -10502,9 +9935,9 @@ static Bool decode_V6MEDIA_instruction (
               gate = True;
         }
      } else {
-        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
+        if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
             INSNA(11,8)  == BITS4(1,1,1,1)         &&
-            INSNA(7,4)   == BITS4(1,1,1,1)) {
+            INSNA(7,4)   == BITS4(1,0,1,1)) {
            regD = INSNA(15,12);
            regN = INSNA(19,16);
            regM = INSNA(3,0);
@@ -10514,73 +9947,61 @@ static Bool decode_V6MEDIA_instruction (
      }
 
      if (gate) {
-        IRTemp irt_regN = newTemp(Ity_I32);
-        IRTemp irt_regM = newTemp(Ity_I32);
+        IRTemp irt_ge_flag0 = newTemp(Ity_I32);
+        IRTemp irt_ge_flag1 = newTemp(Ity_I32);
+        IRTemp irt_ge_flag2 = newTemp(Ity_I32);
+        IRTemp irt_ge_flag3 = newTemp(Ity_I32);
 
-        IRTemp irt_sum_l0 = newTemp(Ity_I32);
-        IRTemp irt_sum_l1 = newTemp(Ity_I32);
-        IRTemp irt_sum_l2 = newTemp(Ity_I32);
-        IRTemp irt_sum_l3 = newTemp(Ity_I32);
+        assign( irt_ge_flag0, get_GEFLAG32(0) );
+        assign( irt_ge_flag1, get_GEFLAG32(1) );
+        assign( irt_ge_flag2, get_GEFLAG32(2) );
+        assign( irt_ge_flag3, get_GEFLAG32(3) );
 
-        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
-        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
+        IRExpr* ire_ge_flag0_or 
+          = binop(Iop_Or32, mkexpr(irt_ge_flag0), 
+                  binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag0)));
+        IRExpr* ire_ge_flag1_or 
+          = binop(Iop_Or32, mkexpr(irt_ge_flag1), 
+                  binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag1)));
+        IRExpr* ire_ge_flag2_or 
+          = binop(Iop_Or32, mkexpr(irt_ge_flag2), 
+                  binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag2)));
+        IRExpr* ire_ge_flag3_or 
+          = binop(Iop_Or32, mkexpr(irt_ge_flag3), 
+                  binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag3)));
 
-        assign( irt_sum_l0, 
-                binop(Iop_Sub32, 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regN), mkU8(24)), 
-                            mkU8(24)),
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regM), mkU8(24)), 
-                            mkU8(24))) );
-        assign( irt_sum_l1, 
-                binop(Iop_Sub32, 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)), 
-                            mkU8(24)), 
-                      binop(Iop_Sar32,
-                            binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 
-                            mkU8(24))) );
-        assign( irt_sum_l2, 
-                binop(Iop_Sub32, 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regN), mkU8(8)), 
-                            mkU8(24)), 
-                      binop(Iop_Sar32, 
-                            binop(Iop_Shl32, mkexpr(irt_regM), mkU8(8)), 
-                            mkU8(24))) );
-        assign( irt_sum_l3, 
-                binop(Iop_Sub32, 
-                      binop(Iop_Sar32, mkexpr(irt_regN), mkU8(24)), 
-                      binop(Iop_Sar32, mkexpr(irt_regM), mkU8(24))) );
-
-        put_GEFLAG32( 0, 31, unop(Iop_Not32, mkexpr(irt_sum_l0)), condT );
-        put_GEFLAG32( 1, 31, unop(Iop_Not32, mkexpr(irt_sum_l1)), condT );
-        put_GEFLAG32( 2, 31, unop(Iop_Not32, mkexpr(irt_sum_l2)), condT );
-        put_GEFLAG32( 3, 31, unop(Iop_Not32, mkexpr(irt_sum_l3)), condT );
+        IRExpr* ire_ge_flags 
+          = binop( Iop_Or32, 
+                   binop(Iop_Or32, 
+                         binop(Iop_And32, 
+                               binop(Iop_Sar32, ire_ge_flag0_or, mkU8(31)), 
+                               mkU32(0x000000ff)), 
+                         binop(Iop_And32, 
+                               binop(Iop_Sar32, ire_ge_flag1_or, mkU8(31)), 
+                               mkU32(0x0000ff00))), 
+                   binop(Iop_Or32, 
+                         binop(Iop_And32, 
+                               binop(Iop_Sar32, ire_ge_flag2_or, mkU8(31)), 
+                               mkU32(0x00ff0000)), 
+                         binop(Iop_And32, 
+                               binop(Iop_Sar32, ire_ge_flag3_or, mkU8(31)), 
+                               mkU32(0xff000000))) );
 
         IRExpr* ire_result 
-          = binop( Iop_Or32,
-                   binop(Iop_Shl32, 
-                         binop(Iop_And32, mkexpr(irt_sum_l3), mkU32(0xff)),
-                         mkU8(24)), 
-                   binop(Iop_Or32, 
-                         binop(Iop_Shl32, 
-                               binop(Iop_And32, mkexpr(irt_sum_l2), mkU32(0xff)),
-                               mkU8(16)),  
-                         binop(Iop_Or32, 
-                               binop(Iop_And32, mkexpr(irt_sum_l0), mkU32(0xff)), 
-                               binop(Iop_Shl32, 
-                                     binop(Iop_And32, 
-                                           mkexpr(irt_sum_l1), mkU32(0xff)),  
-                                     mkU8(8)))) );
+          = binop(Iop_Or32, 
+                  binop(Iop_And32,
+                        isT ? getIRegT(regN) : getIRegA(regN),
+                        ire_ge_flags ), 
+                  binop(Iop_And32,
+                        isT ? getIRegT(regM) : getIRegA(regM),
+                        unop(Iop_Not32, ire_ge_flags)));
 
         if (isT)
            putIRegT( regD, ire_result, condT );
         else
            putIRegA( regD, ire_result, condT, Ijk_Boring );
 
-        DIP("ssub8%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM);
+        DIP("sel%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
         return True;
      }
      /* fall through */
index 28dfc684f9b532f429e8b56576e4e3ac12fb902d..cc2b01cc4e576918bea2f9e9496c92ec58a5859d 100644 (file)
@@ -38,6 +38,7 @@
 #include "main_util.h"
 #include "main_globals.h"
 #include "host_generic_regs.h"
+#include "host_generic_simd64.h"  // for 32-bit SIMD helpers
 #include "host_arm_defs.h"
 
 
@@ -1304,6 +1305,60 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
          return res;
       }
 
+      /* All cases involving host-side helper calls. */
+      void* fn = NULL;
+      switch (e->Iex.Binop.op) {
+         case Iop_Add16x2:
+            fn = &h_generic_calc_Add16x2; break;
+         case Iop_Sub16x2:
+            fn = &h_generic_calc_Sub16x2; break;
+         case Iop_HAdd16Ux2:
+            fn = &h_generic_calc_HAdd16Ux2; break;
+         case Iop_HAdd16Sx2:
+            fn = &h_generic_calc_HAdd16Sx2; break;
+         case Iop_HSub16Ux2:
+            fn = &h_generic_calc_HSub16Ux2; break;
+         case Iop_HSub16Sx2:
+            fn = &h_generic_calc_HSub16Sx2; break;
+         case Iop_QAdd16Sx2:
+            fn = &h_generic_calc_QAdd16Sx2; break;
+         case Iop_QSub16Sx2:
+            fn = &h_generic_calc_QSub16Sx2; break;
+         case Iop_Add8x4:
+            fn = &h_generic_calc_Add8x4; break;
+         case Iop_Sub8x4:
+            fn = &h_generic_calc_Sub8x4; break;
+         case Iop_HAdd8Ux4:
+            fn = &h_generic_calc_HAdd8Ux4; break;
+         case Iop_HAdd8Sx4:
+            fn = &h_generic_calc_HAdd8Sx4; break;
+         case Iop_HSub8Ux4:
+            fn = &h_generic_calc_HSub8Ux4; break;
+         case Iop_HSub8Sx4:
+            fn = &h_generic_calc_HSub8Sx4; break;
+         case Iop_QAdd8Sx4:
+            fn = &h_generic_calc_QAdd8Sx4; break;
+         case Iop_QAdd8Ux4:
+            fn = &h_generic_calc_QAdd8Ux4; break;
+         case Iop_QSub8Sx4:
+            fn = &h_generic_calc_QSub8Sx4; break;
+         case Iop_QSub8Ux4:
+            fn = &h_generic_calc_QSub8Ux4; break;
+         default:
+            break;
+      }
+
+      if (fn) {
+         HReg regL = iselIntExpr_R(env, e->Iex.Binop.arg1);
+         HReg regR = iselIntExpr_R(env, e->Iex.Binop.arg2);
+         HReg res  = newVRegI(env);
+         addInstr(env, mk_iMOVds_RR(hregARM_R0(), regL));
+         addInstr(env, mk_iMOVds_RR(hregARM_R1(), regR));
+         addInstr(env, ARMInstr_Call( ARMcc_AL, (HWord)Ptr_to_ULong(fn), 2 ));
+         addInstr(env, mk_iMOVds_RR(res, hregARM_R0()));
+         return res;
+      }
+
       break;
    }
 
@@ -1570,6 +1625,27 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
          default:
             break;
       }
+
+      /* All Unop cases involving host-side helper calls. */
+      void* fn = NULL;
+      switch (e->Iex.Unop.op) {
+         case Iop_CmpNEZ16x2:
+            fn = &h_generic_calc_CmpNEZ16x2; break;
+         case Iop_CmpNEZ8x4:
+            fn = &h_generic_calc_CmpNEZ8x4; break;
+         default:
+            break;
+      }
+
+      if (fn) {
+         HReg arg = iselIntExpr_R(env, e->Iex.Unop.arg);
+         HReg res = newVRegI(env);
+         addInstr(env, mk_iMOVds_RR(hregARM_R0(), arg));
+         addInstr(env, ARMInstr_Call( ARMcc_AL, (HWord)Ptr_to_ULong(fn), 1 ));
+         addInstr(env, mk_iMOVds_RR(res, hregARM_R0()));
+         return res;
+      }
+
       break;
    }
 
index 39aace9ac1688086752788b9e97e8a2569e326ba..e685ad6a3d48708e717909c286d180036bb48a53 100644 (file)
@@ -90,7 +90,7 @@ static inline UShort sel16x4_0 ( ULong w64 ) {
 static inline ULong mk8x8 ( UChar w7, UChar w6,
                             UChar w5, UChar w4,
                             UChar w3, UChar w2,
-                           UChar w1, UChar w0 ) {
+                            UChar w1, UChar w0 ) {
    UInt hi32 =   (((UInt)w7) << 24) | (((UInt)w6) << 16)
                | (((UInt)w5) << 8)  | (((UInt)w4) << 0);
    UInt lo32 =   (((UInt)w3) << 24) | (((UInt)w2) << 16)
@@ -375,6 +375,71 @@ static inline UChar min8U ( UChar xx, UChar yy )
    return toUChar((xx < yy) ? xx : yy);
 }
 
+static inline UShort hadd16U ( UShort xx, UShort yy )
+{
+   UInt xxi = (UInt)xx;
+   UInt yyi = (UInt)yy;
+   UInt r   = (xxi + yyi) >> 1;
+   return (UShort)r;
+}
+
+static inline Short hadd16S ( Short xx, Short yy )
+{
+   Int xxi = (Int)xx;
+   Int yyi = (Int)yy;
+   Int r   = (xxi + yyi) >> 1;
+   return (Short)r;
+}
+
+static inline UShort hsub16U ( UShort xx, UShort yy )
+{
+   UInt xxi = (UInt)xx;
+   UInt yyi = (UInt)yy;
+   UInt r   = (xxi - yyi) >> 1;
+   return (UShort)r;
+}
+
+static inline Short hsub16S ( Short xx, Short yy )
+{
+   Int xxi = (Int)xx;
+   Int yyi = (Int)yy;
+   Int r   = (xxi - yyi) >> 1;
+   return (Short)r;
+}
+
+static inline UChar hadd8U ( UChar xx, UChar yy )
+{
+   UInt xxi = (UInt)xx;
+   UInt yyi = (UInt)yy;
+   UInt r   = (xxi + yyi) >> 1;
+   return (UChar)r;
+}
+
+static inline Char hadd8S ( Char xx, Char yy )
+{
+   Int xxi = (Int)xx;
+   Int yyi = (Int)yy;
+   Int r   = (xxi + yyi) >> 1;
+   return (Char)r;
+}
+
+static inline UChar hsub8U ( UChar xx, UChar yy )
+{
+   UInt xxi = (UInt)xx;
+   UInt yyi = (UInt)yy;
+   UInt r   = (xxi - yyi) >> 1;
+   return (UChar)r;
+}
+
+static inline Char hsub8S ( Char xx, Char yy )
+{
+   Int xxi = (Int)xx;
+   Int yyi = (Int)yy;
+   Int r   = (xxi - yyi) >> 1;
+   return (Char)r;
+}
+
+
 /* ----------------------------------------------------- */
 /* Start of the externally visible functions.  These simply
    implement the corresponding IR primops. */
@@ -1030,6 +1095,227 @@ ULong h_generic_calc_Min8Ux8 ( ULong xx, ULong yy )
           );
 }
 
+/* ------------ SOME 32-bit SIMD HELPERS TOO ------------ */
+
+/* Tuple/select functions for 16x2 vectors. */
+static inline UInt mk16x2 ( UShort w1, UShort w2 ) {
+   return (((UInt)w1) << 16) | ((UInt)w2);
+}
+
+static inline UShort sel16x2_1 ( UInt w32 ) {
+   return 0xFFFF & (UShort)(w32 >> 16);
+}
+static inline UShort sel16x2_0 ( UInt w32 ) {
+   return 0xFFFF & (UShort)(w32);
+}
+
+static inline UInt mk8x4 ( UChar w3, UChar w2,
+                           UChar w1, UChar w0 ) {
+   UInt w32 =   (((UInt)w3) << 24) | (((UInt)w2) << 16)
+              | (((UInt)w1) << 8)  | (((UInt)w0) << 0);
+   return w32;
+}
+
+static inline UChar sel8x4_3 ( UInt w32 ) {
+   return toUChar(0xFF & (w32 >> 24));
+}
+static inline UChar sel8x4_2 ( UInt w32 ) {
+   return toUChar(0xFF & (w32 >> 16));
+}
+static inline UChar sel8x4_1 ( UInt w32 ) {
+   return toUChar(0xFF & (w32 >> 8));
+}
+static inline UChar sel8x4_0 ( UInt w32 ) {
+   return toUChar(0xFF & (w32 >> 0));
+}
+
+
+/* ----------------------------------------------------- */
+/* More externally visible functions.  These simply
+   implement the corresponding IR primops. */
+/* ----------------------------------------------------- */
+
+/* ------ 16x2 ------ */
+
+UInt h_generic_calc_Add16x2 ( UInt xx, UInt yy )
+{
+   return mk16x2( sel16x2_1(xx) + sel16x2_1(yy),
+                  sel16x2_0(xx) + sel16x2_0(yy) );
+}
+
+UInt h_generic_calc_Sub16x2 ( UInt xx, UInt yy )
+{
+   return mk16x2( sel16x2_1(xx) - sel16x2_1(yy),
+                  sel16x2_0(xx) - sel16x2_0(yy) );
+}
+
+UInt h_generic_calc_HAdd16Ux2 ( UInt xx, UInt yy )
+{
+   return mk16x2( hadd16U( sel16x2_1(xx), sel16x2_1(yy) ),
+                  hadd16U( sel16x2_0(xx), sel16x2_0(yy) ) );
+}
+
+UInt h_generic_calc_HAdd16Sx2 ( UInt xx, UInt yy )
+{
+   return mk16x2( hadd16S( sel16x2_1(xx), sel16x2_1(yy) ),
+                  hadd16S( sel16x2_0(xx), sel16x2_0(yy) ) );
+}
+
+UInt h_generic_calc_HSub16Ux2 ( UInt xx, UInt yy )
+{
+   return mk16x2( hsub16U( sel16x2_1(xx), sel16x2_1(yy) ),
+                  hsub16U( sel16x2_0(xx), sel16x2_0(yy) ) );
+}
+
+UInt h_generic_calc_HSub16Sx2 ( UInt xx, UInt yy )
+{
+   return mk16x2( hsub16S( sel16x2_1(xx), sel16x2_1(yy) ),
+                  hsub16S( sel16x2_0(xx), sel16x2_0(yy) ) );
+}
+
+UInt h_generic_calc_QAdd16Ux2 ( UInt xx, UInt yy )
+{
+   return mk16x2( qadd16U( sel16x2_1(xx), sel16x2_1(yy) ),
+                  qadd16U( sel16x2_0(xx), sel16x2_0(yy) ) );
+}
+
+UInt h_generic_calc_QAdd16Sx2 ( UInt xx, UInt yy )
+{
+   return mk16x2( qadd16S( sel16x2_1(xx), sel16x2_1(yy) ),
+                  qadd16S( sel16x2_0(xx), sel16x2_0(yy) ) );
+}
+
+UInt h_generic_calc_QSub16Ux2 ( UInt xx, UInt yy )
+{
+   return mk16x2( qsub16U( sel16x2_1(xx), sel16x2_1(yy) ),
+                  qsub16U( sel16x2_0(xx), sel16x2_0(yy) ) );
+}
+
+UInt h_generic_calc_QSub16Sx2 ( UInt xx, UInt yy )
+{
+   return mk16x2( qsub16S( sel16x2_1(xx), sel16x2_1(yy) ),
+                  qsub16S( sel16x2_0(xx), sel16x2_0(yy) ) );
+}
+
+/* ------ 8x4 ------ */
+
+UInt h_generic_calc_Add8x4 ( UInt xx, UInt yy )
+{
+   return mk8x4(
+             sel8x4_3(xx) + sel8x4_3(yy),
+             sel8x4_2(xx) + sel8x4_2(yy),
+             sel8x4_1(xx) + sel8x4_1(yy),
+             sel8x4_0(xx) + sel8x4_0(yy)
+          );
+}
+
+UInt h_generic_calc_Sub8x4 ( UInt xx, UInt yy )
+{
+   return mk8x4(
+             sel8x4_3(xx) - sel8x4_3(yy),
+             sel8x4_2(xx) - sel8x4_2(yy),
+             sel8x4_1(xx) - sel8x4_1(yy),
+             sel8x4_0(xx) - sel8x4_0(yy)
+          );
+}
+
+UInt h_generic_calc_HAdd8Ux4 ( UInt xx, UInt yy )
+{
+   return mk8x4(
+             hadd8U( sel8x4_3(xx), sel8x4_3(yy) ),
+             hadd8U( sel8x4_2(xx), sel8x4_2(yy) ),
+             hadd8U( sel8x4_1(xx), sel8x4_1(yy) ),
+             hadd8U( sel8x4_0(xx), sel8x4_0(yy) )
+          );
+}
+
+UInt h_generic_calc_HAdd8Sx4 ( UInt xx, UInt yy )
+{
+   return mk8x4(
+             hadd8S( sel8x4_3(xx), sel8x4_3(yy) ),
+             hadd8S( sel8x4_2(xx), sel8x4_2(yy) ),
+             hadd8S( sel8x4_1(xx), sel8x4_1(yy) ),
+             hadd8S( sel8x4_0(xx), sel8x4_0(yy) )
+          );
+}
+
+UInt h_generic_calc_HSub8Ux4 ( UInt xx, UInt yy )
+{
+   return mk8x4(
+             hsub8U( sel8x4_3(xx), sel8x4_3(yy) ),
+             hsub8U( sel8x4_2(xx), sel8x4_2(yy) ),
+             hsub8U( sel8x4_1(xx), sel8x4_1(yy) ),
+             hsub8U( sel8x4_0(xx), sel8x4_0(yy) )
+          );
+}
+
+UInt h_generic_calc_HSub8Sx4 ( UInt xx, UInt yy )
+{
+   return mk8x4(
+             hsub8S( sel8x4_3(xx), sel8x4_3(yy) ),
+             hsub8S( sel8x4_2(xx), sel8x4_2(yy) ),
+             hsub8S( sel8x4_1(xx), sel8x4_1(yy) ),
+             hsub8S( sel8x4_0(xx), sel8x4_0(yy) )
+          );
+}
+
+UInt h_generic_calc_QAdd8Ux4 ( UInt xx, UInt yy )
+{
+   return mk8x4(
+             qadd8U( sel8x4_3(xx), sel8x4_3(yy) ),
+             qadd8U( sel8x4_2(xx), sel8x4_2(yy) ),
+             qadd8U( sel8x4_1(xx), sel8x4_1(yy) ),
+             qadd8U( sel8x4_0(xx), sel8x4_0(yy) )
+          );
+}
+
+UInt h_generic_calc_QAdd8Sx4 ( UInt xx, UInt yy )
+{
+   return mk8x4(
+             qadd8S( sel8x4_3(xx), sel8x4_3(yy) ),
+             qadd8S( sel8x4_2(xx), sel8x4_2(yy) ),
+             qadd8S( sel8x4_1(xx), sel8x4_1(yy) ),
+             qadd8S( sel8x4_0(xx), sel8x4_0(yy) )
+          );
+}
+
+UInt h_generic_calc_QSub8Ux4 ( UInt xx, UInt yy )
+{
+   return mk8x4(
+             qsub8U( sel8x4_3(xx), sel8x4_3(yy) ),
+             qsub8U( sel8x4_2(xx), sel8x4_2(yy) ),
+             qsub8U( sel8x4_1(xx), sel8x4_1(yy) ),
+             qsub8U( sel8x4_0(xx), sel8x4_0(yy) )
+          );
+}
+
+UInt h_generic_calc_QSub8Sx4 ( UInt xx, UInt yy )
+{
+   return mk8x4(
+             qsub8S( sel8x4_3(xx), sel8x4_3(yy) ),
+             qsub8S( sel8x4_2(xx), sel8x4_2(yy) ),
+             qsub8S( sel8x4_1(xx), sel8x4_1(yy) ),
+             qsub8S( sel8x4_0(xx), sel8x4_0(yy) )
+          );
+}
+
+UInt h_generic_calc_CmpNEZ16x2 ( UInt xx )
+{
+   return mk16x2(
+             cmpnez16( sel16x2_1(xx) ),
+             cmpnez16( sel16x2_0(xx) )
+          );
+}
+
+UInt h_generic_calc_CmpNEZ8x4 ( UInt xx )
+{
+   return mk8x4(
+             cmpnez8( sel8x4_3(xx) ),
+             cmpnez8( sel8x4_2(xx) ),
+             cmpnez8( sel8x4_1(xx) ),
+             cmpnez8( sel8x4_0(xx) )
+          );
+}
 
 /*---------------------------------------------------------------*/
 /*--- end                               host_generic_simd64.c ---*/
index 18687d5daa3c8ffcead517b558cba090b185416d..c29fbf6b2f37be77309ee146a4e8a199af0e0a4d 100644 (file)
@@ -121,6 +121,36 @@ extern ULong h_generic_calc_Max8Ux8  ( ULong, ULong );
 extern ULong h_generic_calc_Min16Sx4 ( ULong, ULong );
 extern ULong h_generic_calc_Min8Ux8  ( ULong, ULong );
 
+/* 32-bit SIMD HELPERS */
+
+extern UInt h_generic_calc_Add16x2   ( UInt, UInt );
+extern UInt h_generic_calc_Sub16x2   ( UInt, UInt );
+
+extern UInt h_generic_calc_HAdd16Ux2 ( UInt, UInt );
+extern UInt h_generic_calc_HAdd16Sx2 ( UInt, UInt );
+extern UInt h_generic_calc_HSub16Ux2 ( UInt, UInt );
+extern UInt h_generic_calc_HSub16Sx2 ( UInt, UInt );
+
+extern UInt h_generic_calc_QAdd16Ux2 ( UInt, UInt );
+extern UInt h_generic_calc_QAdd16Sx2 ( UInt, UInt );
+extern UInt h_generic_calc_QSub16Ux2 ( UInt, UInt );
+extern UInt h_generic_calc_QSub16Sx2 ( UInt, UInt );
+
+extern UInt h_generic_calc_Add8x4   ( UInt, UInt );
+extern UInt h_generic_calc_Sub8x4   ( UInt, UInt );
+
+extern UInt h_generic_calc_HAdd8Ux4 ( UInt, UInt );
+extern UInt h_generic_calc_HAdd8Sx4 ( UInt, UInt );
+extern UInt h_generic_calc_HSub8Ux4 ( UInt, UInt );
+extern UInt h_generic_calc_HSub8Sx4 ( UInt, UInt );
+
+extern UInt h_generic_calc_QAdd8Ux4 ( UInt, UInt );
+extern UInt h_generic_calc_QAdd8Sx4 ( UInt, UInt );
+extern UInt h_generic_calc_QSub8Ux4 ( UInt, UInt );
+extern UInt h_generic_calc_QSub8Sx4 ( UInt, UInt );
+
+extern UInt h_generic_calc_CmpNEZ16x2 ( UInt );
+extern UInt h_generic_calc_CmpNEZ8x4  ( UInt );
 
 #endif /* ndef __VEX_HOST_GENERIC_SIMD64_H */
 
index 48519e40fadcc3c0949216c255d3b4d6b7ea996c..b73348785ca982e66ffeaae13f33294eb2cda49f 100644 (file)
@@ -284,6 +284,31 @@ void ppIROp ( IROp op )
       case Iop_TruncF64asF32: vex_printf("TruncF64asF32"); return;
       case Iop_CalcFPRF:      vex_printf("CalcFPRF"); return;
 
+      case Iop_Add16x2:   vex_printf("Add16x2"); return;
+      case Iop_Sub16x2:   vex_printf("Sub16x2"); return;
+      case Iop_QAdd16Sx2: vex_printf("QAdd16Sx2"); return;
+      case Iop_QAdd16Ux2: vex_printf("QAdd16Ux2"); return;
+      case Iop_QSub16Sx2: vex_printf("QSub16Sx2"); return;
+      case Iop_QSub16Ux2: vex_printf("QSub16Ux2"); return;
+      case Iop_HAdd16Ux2: vex_printf("HAdd16Ux2"); return;
+      case Iop_HAdd16Sx2: vex_printf("HAdd16Sx2"); return;
+      case Iop_HSub16Ux2: vex_printf("HSub16Ux2"); return;
+      case Iop_HSub16Sx2: vex_printf("HSub16Sx2"); return;
+
+      case Iop_Add8x4:   vex_printf("Add8x4"); return;
+      case Iop_Sub8x4:   vex_printf("Sub8x4"); return;
+      case Iop_QAdd8Sx4: vex_printf("QAdd8Sx4"); return;
+      case Iop_QAdd8Ux4: vex_printf("QAdd8Ux4"); return;
+      case Iop_QSub8Sx4: vex_printf("QSub8Sx4"); return;
+      case Iop_QSub8Ux4: vex_printf("QSub8Ux4"); return;
+      case Iop_HAdd8Ux4: vex_printf("HAdd8Ux4"); return;
+      case Iop_HAdd8Sx4: vex_printf("HAdd8Sx4"); return;
+      case Iop_HSub8Ux4: vex_printf("HSub8Ux4"); return;
+      case Iop_HSub8Sx4: vex_printf("HSub8Sx4"); return;
+
+      case Iop_CmpNEZ16x2: vex_printf("CmpNEZ16x2"); return;
+      case Iop_CmpNEZ8x4:  vex_printf("CmpNEZ8x4"); return;
+
       case Iop_CmpF64:    vex_printf("CmpF64"); return;
 
       case Iop_F64toI16S: vex_printf("F64toI16S"); return;
@@ -1909,6 +1934,16 @@ void typeOfPrimop ( IROp op,
       case Iop_Add32: case Iop_Sub32: case Iop_Mul32:
       case Iop_Or32:  case Iop_And32: case Iop_Xor32:
       case Iop_Max32U:
+      case Iop_Add16x2: case Iop_Sub16x2:
+      case Iop_QAdd16Sx2: case Iop_QAdd16Ux2:
+      case Iop_QSub16Sx2: case Iop_QSub16Ux2:
+      case Iop_HAdd16Ux2: case Iop_HAdd16Sx2:
+      case Iop_HSub16Ux2: case Iop_HSub16Sx2:
+      case Iop_Add8x4: case Iop_Sub8x4:
+      case Iop_QAdd8Sx4: case Iop_QAdd8Ux4:
+      case Iop_QSub8Sx4: case Iop_QSub8Ux4:
+      case Iop_HAdd8Ux4: case Iop_HAdd8Sx4:
+      case Iop_HSub8Ux4: case Iop_HSub8Sx4:
          BINARY(Ity_I32,Ity_I32, Ity_I32);
 
       case Iop_Add64: case Iop_Sub64: case Iop_Mul64:
@@ -1994,6 +2029,7 @@ void typeOfPrimop ( IROp op,
       case Iop_Not16:
          UNARY(Ity_I16, Ity_I16);
       case Iop_Not32:
+      case Iop_CmpNEZ16x2: case Iop_CmpNEZ8x4:
          UNARY(Ity_I32, Ity_I32);
 
       case Iop_Not64:
index ee4df18685d8de0de525818021404f710558bc55..b3d78b6b067158fd34cea41d46bc659b28675784 100644 (file)
@@ -675,6 +675,33 @@ typedef
       Iop_CalcFPRF, /* Calc 5 fpscr[FPRF] bits (Class, <, =, >, Unord)
                        from FP result */
 
+      /* ------------------ 32-bit SIMD Integer ------------------ */
+
+      /* 16x2 add/sub, also signed/unsigned saturating variants */
+      Iop_Add16x2, Iop_Sub16x2,
+      Iop_QAdd16Sx2, Iop_QAdd16Ux2,
+      Iop_QSub16Sx2, Iop_QSub16Ux2,
+
+      /* 16x2 signed/unsigned halving add/sub.  For each lane, these
+         compute bits 16:1 of (eg) sx(argL) + sx(argR),
+         or zx(argL) - zx(argR) etc. */
+      Iop_HAdd16Ux2, Iop_HAdd16Sx2,
+      Iop_HSub16Ux2, Iop_HSub16Sx2,
+
+      /* 8x4 add/sub, also signed/unsigned saturating variants */
+      Iop_Add8x4, Iop_Sub8x4,
+      Iop_QAdd8Sx4, Iop_QAdd8Ux4,
+      Iop_QSub8Sx4, Iop_QSub8Ux4,
+
+      /* 8x4 signed/unsigned halving add/sub.  For each lane, these
+         compute bits 8:1 of (eg) sx(argL) + sx(argR),
+         or zx(argL) - zx(argR) etc. */
+      Iop_HAdd8Ux4, Iop_HAdd8Sx4,
+      Iop_HSub8Ux4, Iop_HSub8Sx4,
+
+      /* MISC (vector integer cmp != 0) */
+      Iop_CmpNEZ16x2, Iop_CmpNEZ8x4,
+
       /* ------------------ 64-bit SIMD FP ------------------------ */
 
       /* Convertion to/from int */
@@ -717,7 +744,6 @@ typedef
       /* Unary */
       Iop_Neg32Fx2, Iop_Abs32Fx2,
 
-
       /* ------------------ 64-bit SIMD Integer. ------------------ */
 
       /* MISC (vector integer cmp != 0) */