]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Make a whole bunch of mmx instructions work.
authorJulian Seward <jseward@acm.org>
Mon, 9 May 2005 17:52:56 +0000 (17:52 +0000)
committerJulian Seward <jseward@acm.org>
Mon, 9 May 2005 17:52:56 +0000 (17:52 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@1173

VEX/priv/guest-amd64/ghelpers.c
VEX/priv/guest-amd64/toIR.c
VEX/priv/host-amd64/isel.c

index 4685e78a22f2eb563f7b010a56a7fb078c9a1568..c03c5d67e8edae271421ec8370a9fac871496ee8 100644 (file)
@@ -1383,6 +1383,43 @@ void amd64g_dirtyhelper_CPUID ( VexGuestAMD64State* st )
 }
 
 
+/*---------------------------------------------------------------*/
+/*--- Helpers for MMX/SSE/SSE2.                               ---*/
+/*---------------------------------------------------------------*/
+
+static inline ULong mk32x2 ( UInt w1, UInt w0 ) {
+   return (((ULong)w1) << 32) | ((ULong)w0);
+}
+
+static inline UShort sel16x4_3 ( ULong w64 ) {
+   UInt hi32 = toUInt(w64 >> 32);
+   return toUShort(hi32 >> 16);
+}
+static inline UShort sel16x4_2 ( ULong w64 ) {
+   UInt hi32 = toUInt(w64 >> 32);
+   return toUShort(hi32);
+}
+static inline UShort sel16x4_1 ( ULong w64 ) {
+   UInt lo32 = toUInt(w64);
+   return toUShort(lo32 >> 16);
+}
+static inline UShort sel16x4_0 ( ULong w64 ) {
+   UInt lo32 = toUInt(w64);
+   return toUShort(lo32);
+}
+
+/* CALLED FROM GENERATED CODE: CLEAN HELPER */
+ULong amd64g_calculate_mmx_pmaddwd ( ULong xx, ULong yy )
+{
+   return
+      mk32x2(
+         (((Int)(Short)sel16x4_3(xx)) * ((Int)(Short)sel16x4_3(yy)))
+            + (((Int)(Short)sel16x4_2(xx)) * ((Int)(Short)sel16x4_2(yy))),
+         (((Int)(Short)sel16x4_1(xx)) * ((Int)(Short)sel16x4_1(yy)))
+            + (((Int)(Short)sel16x4_0(xx)) * ((Int)(Short)sel16x4_0(yy)))
+      );
+}
+
 
 /*---------------------------------------------------------------*/
 /*--- Helpers for dealing with, and describing,               ---*/
index a51bcce102226ba39fceaf494f93ada18aa51f49..bf8c729bb75be75c94da785f953fde6710120338 100644 (file)
@@ -667,6 +667,13 @@ static Int gregLO3ofRM ( UChar mod_reg_rm )
    return (Int)( (mod_reg_rm >> 3) & 7 );
 }
 
+/* Ditto the 'e' field of a modRM byte. */
+inline
+static Int eregLO3ofRM ( UChar mod_reg_rm )
+{
+   return (Int)(mod_reg_rm & 0x7);
+}
+
 /* Get a 8/16/32-bit unsigned value out of the insn stream. */
 
 static UChar getUChar ( ULong delta )
@@ -881,6 +888,12 @@ static Bool haveNo66noF2noF3 ( Prefix pfx )
      toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == 0);
 }
 
+/* Return True iff pfx has any of 66, F2 and F3 set */
+static Bool have66orF2orF3 ( Prefix pfx )
+{
+  return ! haveNo66noF2noF3(pfx);
+}
+
 /* Clear all the segment-override bits in a prefix. */
 static Prefix clearSegBits ( Prefix p )
 {
@@ -1968,14 +1981,14 @@ static HChar* nameGrp8 ( Int opc_aux )
 //..       default: vpanic("nameSReg(x86)");
 //..    }
 //.. }
-//.. 
-//.. static HChar* nameMMXReg ( Int mmxreg )
-//.. {
-//..    static HChar* mmx_names[8] 
-//..      = { "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" };
-//..    if (mmxreg < 0 || mmxreg > 7) vpanic("nameMMXReg(x86,guest)");
-//..    return mmx_names[mmxreg];
-//.. }
+
+static HChar* nameMMXReg ( Int mmxreg )
+{
+   static HChar* mmx_names[8] 
+     = { "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" };
+   if (mmxreg < 0 || mmxreg > 7) vpanic("nameMMXReg(amd64,guest)");
+   return mmx_names[mmxreg];
+}
 
 static HChar* nameXMMReg ( Int xmmreg )
 {
@@ -1988,16 +2001,16 @@ static HChar* nameXMMReg ( Int xmmreg )
    return xmm_names[xmmreg];
 }
  
-//.. static Char* nameMMXGran ( UChar gran )
-//.. {
-//..    switch (gran) {
-//..       case 0: return "b";
-//..       case 1: return "w";
-//..       case 2: return "d";
-//..       case 3: return "q";
-//..       default: vpanic("nameMMXGran(x86,guest)");
-//..    }
-//.. }
+static HChar* nameMMXGran ( UChar gran )
+{
+   switch (gran) {
+      case 0: return "b";
+      case 1: return "w";
+      case 2: return "d";
+      case 3: return "q";
+      default: vpanic("nameMMXGran(amd64,guest)");
+   }
+}
 
 static HChar nameISize ( Int size )
 {
@@ -5790,288 +5803,288 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
 }
 
 
-//.. /*------------------------------------------------------------*/
-//.. /*---                                                      ---*/
-//.. /*--- MMX INSTRUCTIONS                                     ---*/
-//.. /*---                                                      ---*/
-//.. /*------------------------------------------------------------*/
-//.. 
-//.. /* Effect of MMX insns on x87 FPU state (table 11-2 of 
-//..    IA32 arch manual, volume 3):
-//.. 
-//..    Read from, or write to MMX register (viz, any insn except EMMS):
-//..    * All tags set to Valid (non-empty) -- FPTAGS[i] := nonzero
-//..    * FP stack pointer set to zero
-//.. 
-//..    EMMS:
-//..    * All tags set to Invalid (empty) -- FPTAGS[i] := zero
-//..    * FP stack pointer set to zero
-//.. */
-//.. 
-//.. static void do_MMX_preamble ( void )
-//.. {
-//..    Int      i;
-//..    IRArray* descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
-//..    IRExpr*  zero  = mkU32(0);
-//..    IRExpr*  tag1  = mkU8(1);
-//..    put_ftop(zero);
-//..    for (i = 0; i < 8; i++)
-//..       stmt( IRStmt_PutI( descr, zero, i, tag1 ) );
-//.. }
-//.. 
-//.. static void do_EMMS_preamble ( void )
-//.. {
-//..    Int      i;
-//..    IRArray* descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
-//..    IRExpr*  zero  = mkU32(0);
-//..    IRExpr*  tag0  = mkU8(0);
-//..    put_ftop(zero);
-//..    for (i = 0; i < 8; i++)
-//..       stmt( IRStmt_PutI( descr, zero, i, tag0 ) );
-//.. }
-//.. 
-//.. 
-//.. static IRExpr* getMMXReg ( UInt archreg )
-//.. {
-//..    vassert(archreg < 8);
-//..    return IRExpr_Get( OFFB_FPREGS + 8 * archreg, Ity_I64 );
-//.. }
-//.. 
-//.. 
-//.. static void putMMXReg ( UInt archreg, IRExpr* e )
-//.. {
-//..    vassert(archreg < 8);
-//..    vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_I64);
-//..    stmt( IRStmt_Put( OFFB_FPREGS + 8 * archreg, e ) );
-//.. }
-//.. 
-//.. 
-//.. /* Helper for non-shift MMX insns.  Note this is incomplete in the
-//..    sense that it does not first call do_MMX_preamble() -- that is the
-//..    responsibility of its caller. */
-//.. 
-//.. static 
-//.. UInt dis_MMXop_regmem_to_reg ( UChar sorb,
-//..                                UInt  delta,
-//..                                UChar opc,
-//..                                Char* name,
-//..                                Bool  show_granularity )
-//.. {
-//..    HChar   dis_buf[50];
-//..    UChar   modrm = getUChar(delta);
-//..    Bool    isReg = epartIsReg(modrm);
-//..    IRExpr* argL  = NULL;
-//..    IRExpr* argR  = NULL;
-//..    IRExpr* argG  = NULL;
-//..    IRExpr* argE  = NULL;
-//..    IRTemp  res   = newTemp(Ity_I64);
-//.. 
-//..    Bool    invG  = False;
-//..    IROp    op    = Iop_INVALID;
-//..    void*   hAddr = NULL;
-//..    Char*   hName = NULL;
-//..    Bool    eLeft = False;
-//.. 
-//.. #  define XXX(_name) do { hAddr = &_name; hName = #_name; } while (0)
-//.. 
-//..    switch (opc) {
-//..       /* Original MMX ones */
-//..       case 0xFC: op = Iop_Add8x8; break;
-//..       case 0xFD: op = Iop_Add16x4; break;
-//..       case 0xFE: op = Iop_Add32x2; break;
-//.. 
-//..       case 0xEC: op = Iop_QAdd8Sx8; break;
-//..       case 0xED: op = Iop_QAdd16Sx4; break;
-//.. 
-//..       case 0xDC: op = Iop_QAdd8Ux8; break;
-//..       case 0xDD: op = Iop_QAdd16Ux4; break;
-//.. 
-//..       case 0xF8: op = Iop_Sub8x8;  break;
-//..       case 0xF9: op = Iop_Sub16x4; break;
-//..       case 0xFA: op = Iop_Sub32x2; break;
-//.. 
-//..       case 0xE8: op = Iop_QSub8Sx8; break;
-//..       case 0xE9: op = Iop_QSub16Sx4; break;
-//.. 
-//..       case 0xD8: op = Iop_QSub8Ux8; break;
-//..       case 0xD9: op = Iop_QSub16Ux4; break;
-//.. 
-//..       case 0xE5: op = Iop_MulHi16Sx4; break;
-//..       case 0xD5: op = Iop_Mul16x4; break;
-//..       case 0xF5: XXX(x86g_calculate_mmx_pmaddwd); break;
-//.. 
-//..       case 0x74: op = Iop_CmpEQ8x8; break;
-//..       case 0x75: op = Iop_CmpEQ16x4; break;
-//..       case 0x76: op = Iop_CmpEQ32x2; break;
-//.. 
-//..       case 0x64: op = Iop_CmpGT8Sx8; break;
-//..       case 0x65: op = Iop_CmpGT16Sx4; break;
-//..       case 0x66: op = Iop_CmpGT32Sx2; break;
-//.. 
-//..       case 0x6B: op = Iop_QNarrow32Sx2; eLeft = True; break;
-//..       case 0x63: op = Iop_QNarrow16Sx4; eLeft = True; break;
-//..       case 0x67: op = Iop_QNarrow16Ux4; eLeft = True; break;
-//.. 
-//..       case 0x68: op = Iop_InterleaveHI8x8;  eLeft = True; break;
-//..       case 0x69: op = Iop_InterleaveHI16x4; eLeft = True; break;
-//..       case 0x6A: op = Iop_InterleaveHI32x2; eLeft = True; break;
-//.. 
-//..       case 0x60: op = Iop_InterleaveLO8x8;  eLeft = True; break;
-//..       case 0x61: op = Iop_InterleaveLO16x4; eLeft = True; break;
-//..       case 0x62: op = Iop_InterleaveLO32x2; eLeft = True; break;
-//.. 
-//..       case 0xDB: op = Iop_And64; break;
-//..       case 0xDF: op = Iop_And64; invG = True; break;
-//..       case 0xEB: op = Iop_Or64; break;
-//..       case 0xEF: /* Possibly do better here if argL and argR are the
-//..                     same reg */
-//..                  op = Iop_Xor64; break;
-//.. 
-//..       /* Introduced in SSE1 */
-//..       case 0xE0: op = Iop_Avg8Ux8;    break;
-//..       case 0xE3: op = Iop_Avg16Ux4;   break;
-//..       case 0xEE: op = Iop_Max16Sx4;   break;
-//..       case 0xDE: op = Iop_Max8Ux8;    break;
-//..       case 0xEA: op = Iop_Min16Sx4;   break;
-//..       case 0xDA: op = Iop_Min8Ux8;    break;
-//..       case 0xE4: op = Iop_MulHi16Ux4; break;
-//..       case 0xF6: XXX(x86g_calculate_mmx_psadbw); break;
-//.. 
-//..       /* Introduced in SSE2 */
-//..       case 0xD4: op = Iop_Add64; break;
-//..       case 0xFB: op = Iop_Sub64; break;
-//.. 
-//..       default: 
-//..          vex_printf("\n0x%x\n", (Int)opc);
-//..          vpanic("dis_MMXop_regmem_to_reg");
-//..    }
-//.. 
-//.. #  undef XXX
-//.. 
-//..    argG = getMMXReg(gregOfRM(modrm));
-//..    if (invG)
-//..       argG = unop(Iop_Not64, argG);
-//.. 
-//..    if (isReg) {
-//..       delta++;
-//..       argE = getMMXReg(eregOfRM(modrm));
-//..    } else {
-//..       Int    len;
-//..       IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
-//..       delta += len;
-//..       argE = loadLE(Ity_I64, mkexpr(addr));
-//..    }
-//.. 
-//..    if (eLeft) {
-//..       argL = argE;
-//..       argR = argG;
-//..    } else {
-//..       argL = argG;
-//..       argR = argE;
-//..    }
-//.. 
-//..    if (op != Iop_INVALID) {
-//..       vassert(hName == NULL);
-//..       vassert(hAddr == NULL);
-//..       assign(res, binop(op, argL, argR));
-//..    } else {
-//..       vassert(hName != NULL);
-//..       vassert(hAddr != NULL);
-//..       assign( res, 
-//..               mkIRExprCCall(
-//..                  Ity_I64, 
-//..                  0/*regparms*/, hName, hAddr,
-//..                  mkIRExprVec_2( argL, argR )
-//..               ) 
-//..             );
-//..    }
-//.. 
-//..    putMMXReg( gregOfRM(modrm), mkexpr(res) );
-//.. 
-//..    DIP("%s%s %s, %s\n", 
-//..        name, show_granularity ? nameMMXGran(opc & 3) : (Char*)"",
-//..        ( isReg ? nameMMXReg(eregOfRM(modrm)) : dis_buf ),
-//..        nameMMXReg(gregOfRM(modrm)) );
-//.. 
-//..    return delta;
-//.. }
-//.. 
-//.. 
-//.. /* Vector by scalar shift of G by the amount specified at the bottom
-//..    of E.  This is a straight copy of dis_SSE_shiftG_byE. */
-//.. 
-//.. static UInt dis_MMX_shiftG_byE ( UChar sorb, ULong delta, 
-//..                                  HChar* opname, IROp op )
-//.. {
-//..    HChar   dis_buf[50];
-//..    Int     alen, size;
-//..    IRTemp  addr;
-//..    Bool    shl, shr, sar;
-//..    UChar   rm   = getUChar(delta);
-//..    IRTemp  g0   = newTemp(Ity_I64);
-//..    IRTemp  g1   = newTemp(Ity_I64);
-//..    IRTemp  amt  = newTemp(Ity_I32);
-//..    IRTemp  amt8 = newTemp(Ity_I8);
-//.. 
-//..    if (epartIsReg(rm)) {
-//..       assign( amt, unop(Iop_64to32, getMMXReg(eregOfRM(rm))) );
-//..       DIP("%s %s,%s\n", opname,
-//..                         nameMMXReg(eregOfRM(rm)),
-//..                         nameMMXReg(gregOfRM(rm)) );
-//..       delta++;
-//..    } else {
-//..       addr = disAMode ( &alen, sorb, delta, dis_buf );
-//..       assign( amt, loadLE(Ity_I32, mkexpr(addr)) );
-//..       DIP("%s %s,%s\n", opname,
-//..                         dis_buf,
-//..                         nameMMXReg(gregOfRM(rm)) );
-//..       delta += alen;
-//..    }
-//..    assign( g0,   getMMXReg(gregOfRM(rm)) );
-//..    assign( amt8, unop(Iop_32to8, mkexpr(amt)) );
-//.. 
-//..    shl = shr = sar = False;
-//..    size = 0;
-//..    switch (op) {
-//..       case Iop_ShlN16x4: shl = True; size = 32; break;
-//..       case Iop_ShlN32x2: shl = True; size = 32; break;
-//..       case Iop_Shl64:    shl = True; size = 64; break;
-//..       case Iop_ShrN16x4: shr = True; size = 16; break;
-//..       case Iop_ShrN32x2: shr = True; size = 32; break;
-//..       case Iop_Shr64:    shr = True; size = 64; break;
-//..       case Iop_SarN16x4: sar = True; size = 16; break;
-//..       case Iop_SarN32x2: sar = True; size = 32; break;
-//..       default: vassert(0);
-//..    }
-//.. 
-//..    if (shl || shr) {
-//..      assign( 
-//..         g1,
-//..         IRExpr_Mux0X(
-//..            unop(Iop_1Uto8,binop(Iop_CmpLT32U,mkexpr(amt),mkU32(size))),
-//..            mkU64(0),
-//..            binop(op, mkexpr(g0), mkexpr(amt8))
-//..         )
-//..      );
-//..    } else 
-//..    if (sar) {
-//..      assign( 
-//..         g1,
-//..         IRExpr_Mux0X(
-//..            unop(Iop_1Uto8,binop(Iop_CmpLT32U,mkexpr(amt),mkU32(size))),
-//..            binop(op, mkexpr(g0), mkU8(size-1)),
-//..            binop(op, mkexpr(g0), mkexpr(amt8))
-//..         )
-//..      );
-//..    } else {
-//..       vassert(0);
-//..    }
-//.. 
-//..    putMMXReg( gregOfRM(rm), mkexpr(g1) );
-//..    return delta;
-//.. }
-//.. 
-//.. 
+/*------------------------------------------------------------*/
+/*---                                                      ---*/
+/*--- MMX INSTRUCTIONS                                     ---*/
+/*---                                                      ---*/
+/*------------------------------------------------------------*/
+
+/* Effect of MMX insns on x87 FPU state (table 11-2 of 
+   IA32 arch manual, volume 3):
+
+   Read from, or write to MMX register (viz, any insn except EMMS):
+   * All tags set to Valid (non-empty) -- FPTAGS[i] := nonzero
+   * FP stack pointer set to zero
+
+   EMMS:
+   * All tags set to Invalid (empty) -- FPTAGS[i] := zero
+   * FP stack pointer set to zero
+*/
+
+static void do_MMX_preamble ( void )
+{
+   Int      i;
+   IRArray* descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
+   IRExpr*  zero  = mkU32(0);
+   IRExpr*  tag1  = mkU8(1);
+   put_ftop(zero);
+   for (i = 0; i < 8; i++)
+      stmt( IRStmt_PutI( descr, zero, i, tag1 ) );
+}
+
+static void do_EMMS_preamble ( void )
+{
+   Int      i;
+   IRArray* descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
+   IRExpr*  zero  = mkU32(0);
+   IRExpr*  tag0  = mkU8(0);
+   put_ftop(zero);
+   for (i = 0; i < 8; i++)
+      stmt( IRStmt_PutI( descr, zero, i, tag0 ) );
+}
+
+
+static IRExpr* getMMXReg ( UInt archreg )
+{
+   vassert(archreg < 8);
+   return IRExpr_Get( OFFB_FPREGS + 8 * archreg, Ity_I64 );
+}
+
+
+static void putMMXReg ( UInt archreg, IRExpr* e )
+{
+   vassert(archreg < 8);
+   vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_I64);
+   stmt( IRStmt_Put( OFFB_FPREGS + 8 * archreg, e ) );
+}
+
+
+/* Helper for non-shift MMX insns.  Note this is incomplete in the
+   sense that it does not first call do_MMX_preamble() -- that is the
+   responsibility of its caller. */
+
+static 
+ULong dis_MMXop_regmem_to_reg ( Prefix pfx,
+                                ULong  delta,
+                                UChar  opc,
+                                Char*  name,
+                                Bool   show_granularity )
+{
+   HChar   dis_buf[50];
+   UChar   modrm = getUChar(delta);
+   Bool    isReg = epartIsReg(modrm);
+   IRExpr* argL  = NULL;
+   IRExpr* argR  = NULL;
+   IRExpr* argG  = NULL;
+   IRExpr* argE  = NULL;
+   IRTemp  res   = newTemp(Ity_I64);
+
+   Bool    invG  = False;
+   IROp    op    = Iop_INVALID;
+   void*   hAddr = NULL;
+   Char*   hName = NULL;
+   Bool    eLeft = False;
+
+#  define XXX(_name) do { hAddr = &_name; hName = #_name; } while (0)
+
+   switch (opc) {
+      /* Original MMX ones */
+      case 0xFC: op = Iop_Add8x8; break;
+      case 0xFD: op = Iop_Add16x4; break;
+      case 0xFE: op = Iop_Add32x2; break;
+
+      case 0xEC: op = Iop_QAdd8Sx8; break;
+      case 0xED: op = Iop_QAdd16Sx4; break;
+
+      case 0xDC: op = Iop_QAdd8Ux8; break;
+      case 0xDD: op = Iop_QAdd16Ux4; break;
+
+      case 0xF8: op = Iop_Sub8x8;  break;
+      case 0xF9: op = Iop_Sub16x4; break;
+      case 0xFA: op = Iop_Sub32x2; break;
+
+      case 0xE8: op = Iop_QSub8Sx8; break;
+      case 0xE9: op = Iop_QSub16Sx4; break;
+
+      case 0xD8: op = Iop_QSub8Ux8; break;
+      case 0xD9: op = Iop_QSub16Ux4; break;
+
+      case 0xE5: op = Iop_MulHi16Sx4; break;
+      case 0xD5: op = Iop_Mul16x4; break;
+      case 0xF5: XXX(amd64g_calculate_mmx_pmaddwd); break;
+
+      case 0x74: op = Iop_CmpEQ8x8; break;
+      case 0x75: op = Iop_CmpEQ16x4; break;
+      case 0x76: op = Iop_CmpEQ32x2; break;
+
+      case 0x64: op = Iop_CmpGT8Sx8; break;
+      case 0x65: op = Iop_CmpGT16Sx4; break;
+      case 0x66: op = Iop_CmpGT32Sx2; break;
+
+      case 0x6B: op = Iop_QNarrow32Sx2; eLeft = True; break;
+      case 0x63: op = Iop_QNarrow16Sx4; eLeft = True; break;
+      case 0x67: op = Iop_QNarrow16Ux4; eLeft = True; break;
+
+      case 0x68: op = Iop_InterleaveHI8x8;  eLeft = True; break;
+      case 0x69: op = Iop_InterleaveHI16x4; eLeft = True; break;
+      case 0x6A: op = Iop_InterleaveHI32x2; eLeft = True; break;
+
+      case 0x60: op = Iop_InterleaveLO8x8;  eLeft = True; break;
+      case 0x61: op = Iop_InterleaveLO16x4; eLeft = True; break;
+      case 0x62: op = Iop_InterleaveLO32x2; eLeft = True; break;
+
+      case 0xDB: op = Iop_And64; break;
+      case 0xDF: op = Iop_And64; invG = True; break;
+      case 0xEB: op = Iop_Or64; break;
+      case 0xEF: /* Possibly do better here if argL and argR are the
+                    same reg */
+                 op = Iop_Xor64; break;
+
+      /* Introduced in SSE1 */
+      case 0xE0: op = Iop_Avg8Ux8;    break;
+      case 0xE3: op = Iop_Avg16Ux4;   break;
+      case 0xEE: op = Iop_Max16Sx4;   break;
+      case 0xDE: op = Iop_Max8Ux8;    break;
+      case 0xEA: op = Iop_Min16Sx4;   break;
+      case 0xDA: op = Iop_Min8Ux8;    break;
+      case 0xE4: op = Iop_MulHi16Ux4; break;
+       //      case 0xF6: XXX(x86g_calculate_mmx_psadbw); break;
+
+      /* Introduced in SSE2 */
+      case 0xD4: op = Iop_Add64; break;
+      case 0xFB: op = Iop_Sub64; break;
+
+      default: 
+         vex_printf("\n0x%x\n", (Int)opc);
+         vpanic("dis_MMXop_regmem_to_reg");
+   }
+
+#  undef XXX
+
+   argG = getMMXReg(gregLO3ofRM(modrm));
+   if (invG)
+      argG = unop(Iop_Not64, argG);
+
+   if (isReg) {
+      delta++;
+      argE = getMMXReg(eregLO3ofRM(modrm));
+   } else {
+      Int    len;
+      IRTemp addr = disAMode( &len, pfx, delta, dis_buf, 0 );
+      delta += len;
+      argE = loadLE(Ity_I64, mkexpr(addr));
+   }
+
+   if (eLeft) {
+      argL = argE;
+      argR = argG;
+   } else {
+      argL = argG;
+      argR = argE;
+   }
+
+   if (op != Iop_INVALID) {
+      vassert(hName == NULL);
+      vassert(hAddr == NULL);
+      assign(res, binop(op, argL, argR));
+   } else {
+      vassert(hName != NULL);
+      vassert(hAddr != NULL);
+      assign( res, 
+              mkIRExprCCall(
+                 Ity_I64, 
+                 0/*regparms*/, hName, hAddr,
+                 mkIRExprVec_2( argL, argR )
+              ) 
+            );
+   }
+
+   putMMXReg( gregLO3ofRM(modrm), mkexpr(res) );
+
+   DIP("%s%s %s, %s\n", 
+       name, show_granularity ? nameMMXGran(opc & 3) : "",
+       ( isReg ? nameMMXReg(eregLO3ofRM(modrm)) : dis_buf ),
+       nameMMXReg(gregLO3ofRM(modrm)) );
+
+   return delta;
+}
+
+
+/* Vector by scalar shift of G by the amount specified at the bottom
+   of E.  This is a straight copy of dis_SSE_shiftG_byE. */
+
+static ULong dis_MMX_shiftG_byE ( Prefix pfx, ULong delta, 
+                                  HChar* opname, IROp op )
+{
+   HChar   dis_buf[50];
+   Int     alen, size;
+   IRTemp  addr;
+   Bool    shl, shr, sar;
+   UChar   rm   = getUChar(delta);
+   IRTemp  g0   = newTemp(Ity_I64);
+   IRTemp  g1   = newTemp(Ity_I64);
+   IRTemp  amt  = newTemp(Ity_I64);
+   IRTemp  amt8 = newTemp(Ity_I8);
+
+   if (epartIsReg(rm)) {
+      assign( amt, getMMXReg(eregLO3ofRM(rm)) );
+      DIP("%s %s,%s\n", opname,
+                        nameMMXReg(eregLO3ofRM(rm)),
+                        nameMMXReg(gregLO3ofRM(rm)) );
+      delta++;
+   } else {
+      addr = disAMode ( &alen, pfx, delta, dis_buf, 0 );
+      assign( amt, loadLE(Ity_I64, mkexpr(addr)) );
+      DIP("%s %s,%s\n", opname,
+                        dis_buf,
+                        nameMMXReg(gregLO3ofRM(rm)) );
+      delta += alen;
+   }
+   assign( g0,   getMMXReg(gregLO3ofRM(rm)) );
+   assign( amt8, unop(Iop_64to8, mkexpr(amt)) );
+
+   shl = shr = sar = False;
+   size = 0;
+   switch (op) {
+      case Iop_ShlN16x4: shl = True; size = 32; break;
+      case Iop_ShlN32x2: shl = True; size = 32; break;
+      case Iop_Shl64:    shl = True; size = 64; break;
+      case Iop_ShrN16x4: shr = True; size = 16; break;
+      case Iop_ShrN32x2: shr = True; size = 32; break;
+      case Iop_Shr64:    shr = True; size = 64; break;
+      case Iop_SarN16x4: sar = True; size = 16; break;
+      case Iop_SarN32x2: sar = True; size = 32; break;
+      default: vassert(0);
+   }
+
+   if (shl || shr) {
+     assign( 
+        g1,
+        IRExpr_Mux0X(
+           unop(Iop_1Uto8,binop(Iop_CmpLT64U,mkexpr(amt),mkU64(size))),
+           mkU64(0),
+           binop(op, mkexpr(g0), mkexpr(amt8))
+        )
+     );
+   } else 
+   if (sar) {
+     assign( 
+        g1,
+        IRExpr_Mux0X(
+           unop(Iop_1Uto8,binop(Iop_CmpLT64U,mkexpr(amt),mkU64(size))),
+           binop(op, mkexpr(g0), mkU8(size-1)),
+           binop(op, mkexpr(g0), mkexpr(amt8))
+        )
+     );
+   } else {
+      vassert(0);
+   }
+
+   putMMXReg( gregLO3ofRM(rm), mkexpr(g1) );
+   return delta;
+}
+
+
 //.. /* Vector by scalar shift of E by an immediate byte.  This is a
 //..    straight copy of dis_SSE_shiftE_imm. */
 //.. 
@@ -6126,24 +6139,24 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
 //..    putMMXReg( eregOfRM(rm), mkexpr(e1) );
 //..    return delta;
 //.. }
-//.. 
-//.. 
-//.. /* Completely handle all MMX instructions except emms. */
-//.. 
-//.. static
-//.. UInt dis_MMX ( Bool* decode_ok, UChar sorb, Int sz, ULong delta )
-//.. {
-//..    Int   len;
-//..    UChar modrm;
-//..    HChar dis_buf[50];
-//..    UChar opc = getUChar(delta);
-//..    delta++;
-//.. 
-//..    /* dis_MMX handles all insns except emms. */
-//..    do_MMX_preamble();
-//.. 
-//..    switch (opc) {
-//.. 
+
+
+/* Completely handle all MMX instructions except emms. */
+
+static
+ULong dis_MMX ( Bool* decode_ok, Prefix pfx, Int sz, ULong delta )
+{
+   Int   len;
+   UChar modrm;
+   HChar dis_buf[50];
+   UChar opc = getUChar(delta);
+   delta++;
+
+   /* dis_MMX handles all insns except emms. */
+   do_MMX_preamble();
+
+   switch (opc) {
+
 //..       case 0x6E: 
 //..          /* MOVD (src)ireg-or-mem (E), (dst)mmxreg (G)*/
 //..          if (sz != 4) 
@@ -6188,200 +6201,199 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
 //..             DIP("movd %s, %s\n", nameMMXReg(gregOfRM(modrm)), dis_buf);
 //..          }
 //..          break;
-//.. 
-//..       case 0x6F:
-//..          /* MOVQ (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          modrm = getUChar(delta);
-//..          if (epartIsReg(modrm)) {
-//..             delta++;
-//..             putMMXReg( gregOfRM(modrm), getMMXReg(eregOfRM(modrm)) );
-//..             DIP("movq %s, %s\n", 
-//..                 nameMMXReg(eregOfRM(modrm)), nameMMXReg(gregOfRM(modrm)));
-//..          } else {
-//..             IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
-//..             delta += len;
-//..             putMMXReg( gregOfRM(modrm), loadLE(Ity_I64, mkexpr(addr)) );
-//..             DIP("movq %s, %s\n", 
-//..                 dis_buf, nameMMXReg(gregOfRM(modrm)));
-//..          }
-//..          break;
-//.. 
-//..       case 0x7F:
-//..          /* MOVQ (src)mmxreg, (dst)mmxreg-or-mem */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          modrm = getUChar(delta);
-//..          if (epartIsReg(modrm)) {
-//..             /* Fall through.  The assembler doesn't appear to generate
-//..                these. */
-//..             goto mmx_decode_failure;
-//..          } else {
-//..             IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
-//..             delta += len;
-//..             storeLE( mkexpr(addr), getMMXReg(gregOfRM(modrm)) );
-//..             DIP("mov(nt)q %s, %s\n", 
-//..                 nameMMXReg(gregOfRM(modrm)), dis_buf);
-//..          }
-//..          break;
-//.. 
-//..       case 0xFC: 
-//..       case 0xFD: 
-//..       case 0xFE: /* PADDgg (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "padd", True );
-//..          break;
-//.. 
-//..       case 0xEC: 
-//..       case 0xED: /* PADDSgg (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "padds", True );
-//..          break;
-//.. 
-//..       case 0xDC: 
-//..       case 0xDD: /* PADDUSgg (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "paddus", True );
-//..          break;
-//.. 
-//..       case 0xF8: 
-//..       case 0xF9: 
-//..       case 0xFA: /* PSUBgg (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "psub", True );
-//..          break;
-//.. 
-//..       case 0xE8: 
-//..       case 0xE9: /* PSUBSgg (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "psubs", True );
-//..          break;
-//.. 
-//..       case 0xD8: 
-//..       case 0xD9: /* PSUBUSgg (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "psubus", True );
-//..          break;
-//.. 
-//..       case 0xE5: /* PMULHW (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pmulhw", False );
-//..          break;
-//.. 
-//..       case 0xD5: /* PMULLW (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pmullw", False );
-//..          break;
-//.. 
-//..       case 0xF5: /* PMADDWD (src)mmxreg-or-mem, (dst)mmxreg */
-//..          vassert(sz == 4);
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pmaddwd", False );
-//..          break;
-//.. 
-//..       case 0x74: 
-//..       case 0x75: 
-//..       case 0x76: /* PCMPEQgg (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pcmpeq", True );
-//..          break;
-//.. 
-//..       case 0x64: 
-//..       case 0x65: 
-//..       case 0x66: /* PCMPGTgg (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pcmpgt", True );
-//..          break;
-//.. 
-//..       case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "packssdw", False );
-//..          break;
-//.. 
-//..       case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "packsswb", False );
-//..          break;
-//.. 
-//..       case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "packuswb", False );
-//..          break;
-//.. 
-//..       case 0x68: 
-//..       case 0x69: 
-//..       case 0x6A: /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "punpckh", True );
-//..          break;
-//.. 
-//..       case 0x60: 
-//..       case 0x61: 
-//..       case 0x62: /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "punpckl", True );
-//..          break;
-//.. 
-//..       case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pand", False );
-//..          break;
-//.. 
-//..       case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pandn", False );
-//..          break;
-//.. 
-//..       case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "por", False );
-//..          break;
-//.. 
-//..       case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
-//..          if (sz != 4) 
-//..             goto mmx_decode_failure;
-//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pxor", False );
-//..          break; 
-//.. 
-#if 0 /* stop gcc multi-line comment warning */
-/.. #     define SHIFT_BY_REG(_name,_op)                                 \
-/..                 delta = dis_MMX_shiftG_byE(sorb, delta, _name, _op); \
-/..                 break;
-#endif /* stop gcc multi-line comment warning */
-//.. 
-//..       /* PSLLgg (src)mmxreg-or-mem, (dst)mmxreg */
-//..       case 0xF1: SHIFT_BY_REG("psllw", Iop_ShlN16x4);
-//..       case 0xF2: SHIFT_BY_REG("pslld", Iop_ShlN32x2);
-//..       case 0xF3: SHIFT_BY_REG("psllq", Iop_Shl64);
-//.. 
-//..       /* PSRLgg (src)mmxreg-or-mem, (dst)mmxreg */
-//..       case 0xD1: SHIFT_BY_REG("psrlw", Iop_ShrN16x4);
-//..       case 0xD2: SHIFT_BY_REG("psrld", Iop_ShrN32x2);
-//..       case 0xD3: SHIFT_BY_REG("psrlq", Iop_Shr64);
-//.. 
-//..       /* PSRAgg (src)mmxreg-or-mem, (dst)mmxreg */
-//..       case 0xE1: SHIFT_BY_REG("psraw", Iop_SarN16x4);
-//..       case 0xE2: SHIFT_BY_REG("psrad", Iop_SarN32x2);
-//.. 
-//.. #     undef SHIFT_BY_REG
+
+      case 0x6F:
+         /* MOVQ (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         modrm = getUChar(delta);
+         if (epartIsReg(modrm)) {
+            delta++;
+            putMMXReg( gregLO3ofRM(modrm), getMMXReg(eregLO3ofRM(modrm)) );
+            DIP("movq %s, %s\n", 
+                nameMMXReg(eregLO3ofRM(modrm)), 
+                nameMMXReg(gregLO3ofRM(modrm)));
+         } else {
+            IRTemp addr = disAMode( &len, pfx, delta, dis_buf, 0 );
+            delta += len;
+            putMMXReg( gregLO3ofRM(modrm), loadLE(Ity_I64, mkexpr(addr)) );
+            DIP("movq %s, %s\n", 
+                dis_buf, nameMMXReg(gregLO3ofRM(modrm)));
+         }
+         break;
+
+      case 0x7F:
+         /* MOVQ (src)mmxreg, (dst)mmxreg-or-mem */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         modrm = getUChar(delta);
+         if (epartIsReg(modrm)) {
+            /* Fall through.  The assembler doesn't appear to generate
+               these. */
+            goto mmx_decode_failure;
+         } else {
+            IRTemp addr = disAMode( &len, pfx, delta, dis_buf, 0 );
+            delta += len;
+            storeLE( mkexpr(addr), getMMXReg(gregLO3ofRM(modrm)) );
+            DIP("mov(nt)q %s, %s\n", 
+                nameMMXReg(gregLO3ofRM(modrm)), dis_buf);
+         }
+         break;
+
+      case 0xFC: 
+      case 0xFD: 
+      case 0xFE: /* PADDgg (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "padd", True );
+         break;
+
+      case 0xEC: 
+      case 0xED: /* PADDSgg (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "padds", True );
+         break;
+
+      case 0xDC: 
+      case 0xDD: /* PADDUSgg (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "paddus", True );
+         break;
+
+      case 0xF8: 
+      case 0xF9: 
+      case 0xFA: /* PSUBgg (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "psub", True );
+         break;
+
+      case 0xE8: 
+      case 0xE9: /* PSUBSgg (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "psubs", True );
+         break;
+
+      case 0xD8: 
+      case 0xD9: /* PSUBUSgg (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "psubus", True );
+         break;
+
+      case 0xE5: /* PMULHW (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "pmulhw", False );
+         break;
+
+      case 0xD5: /* PMULLW (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "pmullw", False );
+         break;
+
+      case 0xF5: /* PMADDWD (src)mmxreg-or-mem, (dst)mmxreg */
+         vassert(sz == 4);
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "pmaddwd", False );
+         break;
+
+      case 0x74: 
+      case 0x75: 
+      case 0x76: /* PCMPEQgg (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "pcmpeq", True );
+         break;
+
+      case 0x64: 
+      case 0x65: 
+      case 0x66: /* PCMPGTgg (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "pcmpgt", True );
+         break;
+
+      case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "packssdw", False );
+         break;
+
+      case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "packsswb", False );
+         break;
+
+      case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "packuswb", False );
+         break;
+
+      case 0x68: 
+      case 0x69: 
+      case 0x6A: /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "punpckh", True );
+         break;
+
+      case 0x60: 
+      case 0x61: 
+      case 0x62: /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "punpckl", True );
+         break;
+
+      case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "pand", False );
+         break;
+
+      case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "pandn", False );
+         break;
+
+      case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "por", False );
+         break;
+
+      case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
+         if (sz != 4) 
+            goto mmx_decode_failure;
+         delta = dis_MMXop_regmem_to_reg ( pfx, delta, opc, "pxor", False );
+         break; 
+
+#     define SHIFT_BY_REG(_name,_op)                                \
+                delta = dis_MMX_shiftG_byE(pfx, delta, _name, _op); \
+                break;
+
+      /* PSLLgg (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0xF1: SHIFT_BY_REG("psllw", Iop_ShlN16x4);
+      case 0xF2: SHIFT_BY_REG("pslld", Iop_ShlN32x2);
+      case 0xF3: SHIFT_BY_REG("psllq", Iop_Shl64);
+
+      /* PSRLgg (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0xD1: SHIFT_BY_REG("psrlw", Iop_ShrN16x4);
+      case 0xD2: SHIFT_BY_REG("psrld", Iop_ShrN32x2);
+      case 0xD3: SHIFT_BY_REG("psrlq", Iop_Shr64);
+
+      /* PSRAgg (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0xE1: SHIFT_BY_REG("psraw", Iop_SarN16x4);
+      case 0xE2: SHIFT_BY_REG("psrad", Iop_SarN32x2);
+
+#     undef SHIFT_BY_REG
 //.. 
 //..       case 0x71: 
 //..       case 0x72: 
@@ -6429,20 +6441,20 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
 //.. #        undef SHIFT_BY_IMM
 //..          break;
 //..       }
-//.. 
-//..       /* --- MMX decode failure --- */
-//..       default:
-//..       mmx_decode_failure:
-//..          *decode_ok = False;
-//..          return delta; /* ignored */
-//.. 
-//..    }
-//.. 
-//..    *decode_ok = True;
-//..    return delta;
-//.. }
-//.. 
-//.. 
+
+      /* --- MMX decode failure --- */
+      default:
+      mmx_decode_failure:
+         *decode_ok = False;
+         return delta; /* ignored */
+
+   }
+
+   *decode_ok = True;
+   return delta;
+}
+
+
 //.. /*------------------------------------------------------------*/
 //.. /*--- More misc arithmetic and other obscure insns.        ---*/
 //.. /*------------------------------------------------------------*/
@@ -10498,17 +10510,18 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
 //..                                  "paddd", Iop_Add32x4, False );
 //..       goto decode_success;
-//..    }
-//.. 
-//..    /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
-//..    /* 0F D4 = PADDQ -- add 64x1 */
-//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xD4) {
-//..       do_MMX_preamble();
-//..       delta = dis_MMXop_regmem_to_reg ( 
-//..                 sorb, delta+2, insn[1], "paddq", False );
-//..       goto decode_success;
 //..    }
 
+   /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
+   /* 0F D4 = PADDQ -- add 64x1 */
+   if (haveNo66noF2noF3(pfx) && sz == 4 
+       && insn[0] == 0x0F && insn[1] == 0xD4) {
+      do_MMX_preamble();
+      delta = dis_MMXop_regmem_to_reg ( 
+                pfx, delta+2, insn[1], "paddq", False );
+      goto decode_success;
+   }
+
    /* 66 0F D4 = PADDQ */
    if (have66noF2noF3(pfx) && sz == 2 
        && insn[0] == 0x0F && insn[1] == 0xD4) {
@@ -11201,15 +11214,16 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..                                  "psubd", Iop_Sub32x4, False );
 //..       goto decode_success;
 //..    }
-//.. 
-//..    /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
-//..    /* 0F FB = PSUBQ -- sub 64x1 */
-//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xFB) {
-//..       do_MMX_preamble();
-//..       delta = dis_MMXop_regmem_to_reg ( 
-//..                 sorb, delta+2, insn[1], "psubq", False );
-//..       goto decode_success;
-//..    }
+
+   /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
+   /* 0F FB = PSUBQ -- sub 64x1 */
+   if (haveNo66noF2noF3(pfx) && sz == 4 
+       && insn[0] == 0x0F && insn[1] == 0xFB) {
+      do_MMX_preamble();
+      delta = dis_MMXop_regmem_to_reg ( 
+                pfx, delta+2, insn[1], "psubq", False );
+      goto decode_success;
+   }
 
    /* 66 0F FB = PSUBQ */
    if (have66noF2noF3(pfx) && sz == 2 
@@ -11583,46 +11597,6 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
          goto decode_failure;
       }
 
-//..    /* ------------------------ INC & DEC ------------------ */
-//.. 
-//..    case 0x40: /* INC eAX */
-//..    case 0x41: /* INC eCX */
-//..    case 0x42: /* INC eDX */
-//..    case 0x43: /* INC eBX */
-//..    case 0x44: /* INC eSP */
-//..    case 0x45: /* INC eBP */
-//..    case 0x46: /* INC eSI */
-//..    case 0x47: /* INC eDI */
-//..       vassert(sz == 2 || sz == 4);
-//..       ty = szToITy(sz);
-//..       t1 = newTemp(ty);
-//..       assign( t1, binop(mkSizedOp(ty,Iop_Add8),
-//..                         getIReg(sz, (UInt)(opc - 0x40)),
-//..                         mkU(ty,1)) );
-//..       setFlags_INC_DEC( True, t1, ty );
-//..       putIReg(sz, (UInt)(opc - 0x40), mkexpr(t1));
-//..       DIP("inc%c %s\n", nameISize(sz), nameIReg(sz,opc-0x40));
-//..       break;
-//.. 
-//..    case 0x48: /* DEC eAX */
-//..    case 0x49: /* DEC eCX */
-//..    case 0x4A: /* DEC eDX */
-//..    case 0x4B: /* DEC eBX */
-//..    case 0x4C: /* DEC eSP */
-//..    case 0x4D: /* DEC eBP */
-//..    case 0x4E: /* DEC eSI */
-//..    case 0x4F: /* DEC eDI */
-//..       vassert(sz == 2 || sz == 4);
-//..       ty = szToITy(sz);
-//..       t1 = newTemp(ty);
-//..       assign( t1, binop(mkSizedOp(ty,Iop_Sub8),
-//..                         getIReg(sz, (UInt)(opc - 0x48)),
-//..                         mkU(ty,1)) );
-//..       setFlags_INC_DEC( False, t1, ty );
-//..       putIReg(sz, (UInt)(opc - 0x48), mkexpr(t1));
-//..       DIP("dec%c %s\n", nameISize(sz), nameIReg(sz,opc-0x48));
-//..       break;
-
    /* ------------------------ Jcond, byte offset --------- */
 
    case 0xEB: /* Jb (jump, byte offset) */
@@ -11813,7 +11787,7 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..                                 sorbTxt(sorb), d32);
 //..       break;
 
-/* XXXX be careful here with moves to AH/BH/CH/DH */
+   /* XXXX be careful here with moves to AH/BH/CH/DH */
    case 0xB0: /* MOV imm,AL */
    case 0xB1: /* MOV imm,CL */
    case 0xB2: /* MOV imm,DL */
@@ -13301,100 +13275,102 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
          break;
       }
 
-//..       /* =-=-=-=-=-=-=-=-=- MMXery =-=-=-=-=-=-=-=-=-=-= */
-//.. 
+      /* =-=-=-=-=-=-=-=-=- MMXery =-=-=-=-=-=-=-=-=-=-= */
+
 //..       case 0x71: 
 //..       case 0x72: 
 //..       case 0x73: /* PSLLgg/PSRAgg/PSRLgg mmxreg by imm8 */
 //.. 
 //..       case 0x6E: /* MOVD (src)ireg-or-mem, (dst)mmxreg */
 //..       case 0x7E: /* MOVD (src)mmxreg, (dst)ireg-or-mem */
-//..       case 0x7F: /* MOVQ (src)mmxreg, (dst)mmxreg-or-mem */
-//..       case 0x6F: /* MOVQ (src)mmxreg-or-mem, (dst)mmxreg */
-//.. 
-//..       case 0xFC: 
-//..       case 0xFD: 
-//..       case 0xFE: /* PADDgg (src)mmxreg-or-mem, (dst)mmxreg */
-//.. 
-//..       case 0xEC: 
-//..       case 0xED: /* PADDSgg (src)mmxreg-or-mem, (dst)mmxreg */
-//.. 
-//..       case 0xDC:
-//..       case 0xDD: /* PADDUSgg (src)mmxreg-or-mem, (dst)mmxreg */
-//.. 
-//..       case 0xF8: 
-//..       case 0xF9: 
-//..       case 0xFA: /* PSUBgg (src)mmxreg-or-mem, (dst)mmxreg */
-//.. 
-//..       case 0xE8: 
-//..       case 0xE9: /* PSUBSgg (src)mmxreg-or-mem, (dst)mmxreg */
-//.. 
-//..       case 0xD8: 
-//..       case 0xD9: /* PSUBUSgg (src)mmxreg-or-mem, (dst)mmxreg */
-//.. 
-//..       case 0xE5: /* PMULHW (src)mmxreg-or-mem, (dst)mmxreg */
-//..       case 0xD5: /* PMULLW (src)mmxreg-or-mem, (dst)mmxreg */
-//.. 
-//..       case 0xF5: /* PMADDWD (src)mmxreg-or-mem, (dst)mmxreg */
-//.. 
-//..       case 0x74: 
-//..       case 0x75: 
-//..       case 0x76: /* PCMPEQgg (src)mmxreg-or-mem, (dst)mmxreg */
-//.. 
-//..       case 0x64: 
-//..       case 0x65: 
-//..       case 0x66: /* PCMPGTgg (src)mmxreg-or-mem, (dst)mmxreg */
-//.. 
-//..       case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
-//..       case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
-//..       case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
-//.. 
-//..       case 0x68: 
-//..       case 0x69: 
-//..       case 0x6A: /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
-//.. 
-//..       case 0x60: 
-//..       case 0x61: 
-//..       case 0x62: /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
-//.. 
-//..       case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
-//..       case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
-//..       case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
-//..       case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
-//.. 
-//..       case 0xF1: /* PSLLgg (src)mmxreg-or-mem, (dst)mmxreg */
-//..       case 0xF2: 
-//..       case 0xF3: 
-//.. 
-//..       case 0xD1: /* PSRLgg (src)mmxreg-or-mem, (dst)mmxreg */
-//..       case 0xD2: 
-//..       case 0xD3: 
-//.. 
-//..       case 0xE1: /* PSRAgg (src)mmxreg-or-mem, (dst)mmxreg */
-//..       case 0xE2: 
-//..       {
-//..          ULong delta0    = delta-1;
-//..          Bool decode_OK = False;
-//.. 
-//..          /* If sz==2 this is SSE, and we assume sse idec has
-//..             already spotted those cases by now. */
-//..          if (sz != 4)
-//..             goto decode_failure;
-//.. 
-//..          delta = dis_MMX ( &decode_OK, sorb, sz, delta-1 );
-//..          if (!decode_OK) {
-//..             delta = delta0;
-//..             goto decode_failure;
-//..          }
-//..          break;
-//..       }
-//.. 
-//..       case 0x77: /* EMMS */
-//..          if (sz != 4)
-//..             goto decode_failure;
-//..          do_EMMS_preamble();
-//..          DIP("emms\n");
-//..          break;
+      case 0x7F: /* MOVQ (src)mmxreg, (dst)mmxreg-or-mem */
+      case 0x6F: /* MOVQ (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0xFC: 
+      case 0xFD: 
+      case 0xFE: /* PADDgg (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0xEC: 
+      case 0xED: /* PADDSgg (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0xDC:
+      case 0xDD: /* PADDUSgg (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0xF8: 
+      case 0xF9: 
+      case 0xFA: /* PSUBgg (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0xE8: 
+      case 0xE9: /* PSUBSgg (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0xD8: 
+      case 0xD9: /* PSUBUSgg (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0xE5: /* PMULHW (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0xD5: /* PMULLW (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0xF5: /* PMADDWD (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0x74: 
+      case 0x75: 
+      case 0x76: /* PCMPEQgg (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0x64: 
+      case 0x65: 
+      case 0x66: /* PCMPGTgg (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0x68: 
+      case 0x69: 
+      case 0x6A: /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0x60: 
+      case 0x61: 
+      case 0x62: /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0xF1: /* PSLLgg (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0xF2: 
+      case 0xF3: 
+
+      case 0xD1: /* PSRLgg (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0xD2: 
+      case 0xD3: 
+
+      case 0xE1: /* PSRAgg (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0xE2: 
+      {
+         ULong delta0    = delta-1;
+         Bool decode_OK = False;
+
+         /* If sz==2 this is SSE, and we assume sse idec has
+            already spotted those cases by now. */
+         if (sz != 4)
+            goto decode_failure;
+         if (have66orF2orF3(pfx))
+            goto decode_failure;
+
+         delta = dis_MMX ( &decode_OK, pfx, sz, delta-1 );
+         if (!decode_OK) {
+            delta = delta0;
+            goto decode_failure;
+         }
+         break;
+      }
+
+      case 0x77: /* EMMS */
+         if (sz != 4)
+            goto decode_failure;
+         do_EMMS_preamble();
+         DIP("emms\n");
+         break;
 
       /* =-=-=-=-=-=-=-=-=- unimp2 =-=-=-=-=-=-=-=-=-=-= */
 
index ccf3b41c49a192b76aef847449772bc57e3c3dec..32958de41967953664df21e39bc431920fb4cd13 100644 (file)
@@ -41,7 +41,7 @@
 #include "main/vex_util.h"
 #include "main/vex_globals.h"
 #include "host-generic/h_generic_regs.h"
-//.. #include "host-generic/h_generic_simd64.h"
+#include "host-generic/h_generic_simd64.h"
 #include "host-amd64/hdefs.h"
 
 
@@ -764,6 +764,7 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
 /* DO NOT CALL THIS DIRECTLY ! */
 static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
 {
+   Bool second_is_UInt;
    MatchInfo mi;
    DECLARE_PATTERN(p_8Uto64);
    DECLARE_PATTERN(p_1Uto8_64to1);
@@ -806,6 +807,8 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
    case Iex_Binop: {
       AMD64AluOp   aluOp;
       AMD64ShiftOp shOp;
+      HWord fn = 0; /* helper fn for most SIMD64 stuff */
+
 //.. 
 //..       /* Pattern: Sub32(0,x) */
 //..       if (e->Iex.Binop.op == Iop_Sub32 && isZero32(e->Iex.Binop.arg1)) {
@@ -919,6 +922,141 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
          return dst;
       }
 
+      /* Deal with 64-bit SIMD binary ops */
+      second_is_UInt = False;
+      switch (e->Iex.Binop.op) {
+         case Iop_Add8x8:
+            fn = (HWord)h_generic_calc_Add8x8; break;
+         case Iop_Add16x4:
+            fn = (HWord)h_generic_calc_Add16x4; break;
+         case Iop_Add32x2:
+            fn = (HWord)h_generic_calc_Add32x2; break;
+//.. 
+//..          case Iop_Avg8Ux8:
+//..             fn = (HWord)h_generic_calc_Avg8Ux8; break;
+//..          case Iop_Avg16Ux4:
+//..             fn = (HWord)h_generic_calc_Avg16Ux4; break;
+
+         case Iop_CmpEQ8x8:
+            fn = (HWord)h_generic_calc_CmpEQ8x8; break;
+         case Iop_CmpEQ16x4:
+            fn = (HWord)h_generic_calc_CmpEQ16x4; break;
+         case Iop_CmpEQ32x2:
+            fn = (HWord)h_generic_calc_CmpEQ32x2; break;
+
+         case Iop_CmpGT8Sx8:
+            fn = (HWord)h_generic_calc_CmpGT8Sx8; break;
+         case Iop_CmpGT16Sx4:
+            fn = (HWord)h_generic_calc_CmpGT16Sx4; break;
+         case Iop_CmpGT32Sx2:
+            fn = (HWord)h_generic_calc_CmpGT32Sx2; break;
+
+         case Iop_InterleaveHI8x8:
+            fn = (HWord)h_generic_calc_InterleaveHI8x8; break;
+         case Iop_InterleaveLO8x8:
+            fn = (HWord)h_generic_calc_InterleaveLO8x8; break;
+         case Iop_InterleaveHI16x4:
+            fn = (HWord)h_generic_calc_InterleaveHI16x4; break;
+         case Iop_InterleaveLO16x4:
+            fn = (HWord)h_generic_calc_InterleaveLO16x4; break;
+         case Iop_InterleaveHI32x2:
+            fn = (HWord)h_generic_calc_InterleaveHI32x2; break;
+         case Iop_InterleaveLO32x2:
+            fn = (HWord)h_generic_calc_InterleaveLO32x2; break;
+
+//..          case Iop_Max8Ux8:
+//..             fn = (HWord)h_generic_calc_Max8Ux8; break;
+//..          case Iop_Max16Sx4:
+//..             fn = (HWord)h_generic_calc_Max16Sx4; break;
+//..          case Iop_Min8Ux8:
+//..             fn = (HWord)h_generic_calc_Min8Ux8; break;
+//..          case Iop_Min16Sx4:
+//..             fn = (HWord)h_generic_calc_Min16Sx4; break;
+
+         case Iop_Mul16x4:
+            fn = (HWord)h_generic_calc_Mul16x4; break;
+         case Iop_MulHi16Sx4:
+            fn = (HWord)h_generic_calc_MulHi16Sx4; break;
+//..          case Iop_MulHi16Ux4:
+//..             fn = (HWord)h_generic_calc_MulHi16Ux4; break;
+//.. 
+         case Iop_QAdd8Sx8:
+            fn = (HWord)h_generic_calc_QAdd8Sx8; break;
+         case Iop_QAdd16Sx4:
+            fn = (HWord)h_generic_calc_QAdd16Sx4; break;
+         case Iop_QAdd8Ux8:
+            fn = (HWord)h_generic_calc_QAdd8Ux8; break;
+         case Iop_QAdd16Ux4:
+            fn = (HWord)h_generic_calc_QAdd16Ux4; break;
+
+         case Iop_QNarrow32Sx2:
+            fn = (HWord)h_generic_calc_QNarrow32Sx2; break;
+         case Iop_QNarrow16Sx4:
+            fn = (HWord)h_generic_calc_QNarrow16Sx4; break;
+         case Iop_QNarrow16Ux4:
+            fn = (HWord)h_generic_calc_QNarrow16Ux4; break;
+
+         case Iop_QSub8Sx8:
+            fn = (HWord)h_generic_calc_QSub8Sx8; break;
+         case Iop_QSub16Sx4:
+            fn = (HWord)h_generic_calc_QSub16Sx4; break;
+         case Iop_QSub8Ux8:
+            fn = (HWord)h_generic_calc_QSub8Ux8; break;
+         case Iop_QSub16Ux4:
+            fn = (HWord)h_generic_calc_QSub16Ux4; break;
+
+         case Iop_Sub8x8:
+            fn = (HWord)h_generic_calc_Sub8x8; break;
+         case Iop_Sub16x4:
+            fn = (HWord)h_generic_calc_Sub16x4; break;
+         case Iop_Sub32x2:
+            fn = (HWord)h_generic_calc_Sub32x2; break;
+
+         case Iop_ShlN32x2:
+            fn = (HWord)h_generic_calc_ShlN32x2; 
+            second_is_UInt = True;
+            break;
+         case Iop_ShlN16x4:
+            fn = (HWord)h_generic_calc_ShlN16x4;
+            second_is_UInt = True;
+            break;
+         case Iop_ShrN32x2:
+            fn = (HWord)h_generic_calc_ShrN32x2; 
+            second_is_UInt = True; 
+            break;
+         case Iop_ShrN16x4:
+            fn = (HWord)h_generic_calc_ShrN16x4;
+            second_is_UInt = True; 
+            break;
+         case Iop_SarN32x2:
+            fn = (HWord)h_generic_calc_SarN32x2;
+            second_is_UInt = True; 
+            break;
+         case Iop_SarN16x4:
+            fn = (HWord)h_generic_calc_SarN16x4;
+            second_is_UInt = True; 
+            break;
+
+         default:
+            fn = (HWord)0; break;
+      }
+      if (fn != (HWord)0) {
+         /* Note: the following assumes all helpers are of signature 
+               ULong fn ( ULong, ULong ), and they are
+            not marked as regparm functions. 
+         */
+         HReg dst  = newVRegI(env);
+         HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1);
+         HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2);
+         if (second_is_UInt)
+            addInstr(env, AMD64Instr_MovZLQ(argR, argR));
+         addInstr(env, mk_iMOVsd_RR(argL, hregAMD64_RDI()) );
+         addInstr(env, mk_iMOVsd_RR(argR, hregAMD64_RSI()) );
+         addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn, 2 ));
+         addInstr(env, mk_iMOVsd_RR(hregAMD64_RAX(), dst));
+         return dst;
+      }
+
       /* Handle misc other ops. */
 
       if (e->Iex.Binop.op == Iop_DivModS64to32
@@ -2320,152 +2458,6 @@ static void iselInt128Expr_wrk ( HReg* rHi, HReg* rLo,
 //..             return;
 //..          }
 //.. 
-//..          case Iop_Add8x8:
-//..             fn = (HWord)h_generic_calc_Add8x8; goto binnish;
-//..          case Iop_Add16x4:
-//..             fn = (HWord)h_generic_calc_Add16x4; goto binnish;
-//..          case Iop_Add32x2:
-//..             fn = (HWord)h_generic_calc_Add32x2; goto binnish;
-//.. 
-//..          case Iop_Avg8Ux8:
-//..             fn = (HWord)h_generic_calc_Avg8Ux8; goto binnish;
-//..          case Iop_Avg16Ux4:
-//..             fn = (HWord)h_generic_calc_Avg16Ux4; goto binnish;
-//.. 
-//..          case Iop_CmpEQ8x8:
-//..             fn = (HWord)h_generic_calc_CmpEQ8x8; goto binnish;
-//..          case Iop_CmpEQ16x4:
-//..             fn = (HWord)h_generic_calc_CmpEQ16x4; goto binnish;
-//..          case Iop_CmpEQ32x2:
-//..             fn = (HWord)h_generic_calc_CmpEQ32x2; goto binnish;
-//.. 
-//..          case Iop_CmpGT8Sx8:
-//..             fn = (HWord)h_generic_calc_CmpGT8Sx8; goto binnish;
-//..          case Iop_CmpGT16Sx4:
-//..             fn = (HWord)h_generic_calc_CmpGT16Sx4; goto binnish;
-//..          case Iop_CmpGT32Sx2:
-//..             fn = (HWord)h_generic_calc_CmpGT32Sx2; goto binnish;
-//.. 
-//..          case Iop_InterleaveHI8x8:
-//..             fn = (HWord)h_generic_calc_InterleaveHI8x8; goto binnish;
-//..          case Iop_InterleaveLO8x8:
-//..             fn = (HWord)h_generic_calc_InterleaveLO8x8; goto binnish;
-//..          case Iop_InterleaveHI16x4:
-//..             fn = (HWord)h_generic_calc_InterleaveHI16x4; goto binnish;
-//..          case Iop_InterleaveLO16x4:
-//..             fn = (HWord)h_generic_calc_InterleaveLO16x4; goto binnish;
-//..          case Iop_InterleaveHI32x2:
-//..             fn = (HWord)h_generic_calc_InterleaveHI32x2; goto binnish;
-//..          case Iop_InterleaveLO32x2:
-//..             fn = (HWord)h_generic_calc_InterleaveLO32x2; goto binnish;
-//.. 
-//..          case Iop_Max8Ux8:
-//..             fn = (HWord)h_generic_calc_Max8Ux8; goto binnish;
-//..          case Iop_Max16Sx4:
-//..             fn = (HWord)h_generic_calc_Max16Sx4; goto binnish;
-//..          case Iop_Min8Ux8:
-//..             fn = (HWord)h_generic_calc_Min8Ux8; goto binnish;
-//..          case Iop_Min16Sx4:
-//..             fn = (HWord)h_generic_calc_Min16Sx4; goto binnish;
-//.. 
-//..          case Iop_Mul16x4:
-//..             fn = (HWord)h_generic_calc_Mul16x4; goto binnish;
-//..          case Iop_MulHi16Sx4:
-//..             fn = (HWord)h_generic_calc_MulHi16Sx4; goto binnish;
-//..          case Iop_MulHi16Ux4:
-//..             fn = (HWord)h_generic_calc_MulHi16Ux4; goto binnish;
-//.. 
-//..          case Iop_QAdd8Sx8:
-//..             fn = (HWord)h_generic_calc_QAdd8Sx8; goto binnish;
-//..          case Iop_QAdd16Sx4:
-//..             fn = (HWord)h_generic_calc_QAdd16Sx4; goto binnish;
-//..          case Iop_QAdd8Ux8:
-//..             fn = (HWord)h_generic_calc_QAdd8Ux8; goto binnish;
-//..          case Iop_QAdd16Ux4:
-//..             fn = (HWord)h_generic_calc_QAdd16Ux4; goto binnish;
-//.. 
-//..          case Iop_QNarrow32Sx2:
-//..             fn = (HWord)h_generic_calc_QNarrow32Sx2; goto binnish;
-//..          case Iop_QNarrow16Sx4:
-//..             fn = (HWord)h_generic_calc_QNarrow16Sx4; goto binnish;
-//..          case Iop_QNarrow16Ux4:
-//..             fn = (HWord)h_generic_calc_QNarrow16Ux4; goto binnish;
-//.. 
-//..          case Iop_QSub8Sx8:
-//..             fn = (HWord)h_generic_calc_QSub8Sx8; goto binnish;
-//..          case Iop_QSub16Sx4:
-//..             fn = (HWord)h_generic_calc_QSub16Sx4; goto binnish;
-//..          case Iop_QSub8Ux8:
-//..             fn = (HWord)h_generic_calc_QSub8Ux8; goto binnish;
-//..          case Iop_QSub16Ux4:
-//..             fn = (HWord)h_generic_calc_QSub16Ux4; goto binnish;
-//.. 
-//..          case Iop_Sub8x8:
-//..             fn = (HWord)h_generic_calc_Sub8x8; goto binnish;
-//..          case Iop_Sub16x4:
-//..             fn = (HWord)h_generic_calc_Sub16x4; goto binnish;
-//..          case Iop_Sub32x2:
-//..             fn = (HWord)h_generic_calc_Sub32x2; goto binnish;
-//.. 
-//..          binnish: {
-//..             /* Note: the following assumes all helpers are of
-//..                signature 
-//..                   ULong fn ( ULong, ULong ), and they are
-//..                not marked as regparm functions. 
-//..             */
-//..             HReg xLo, xHi, yLo, yHi;
-//..             HReg tLo = newVRegI(env);
-//..             HReg tHi = newVRegI(env);
-//..             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
-//..             addInstr(env, X86Instr_Push(X86RMI_Reg(yHi)));
-//..             addInstr(env, X86Instr_Push(X86RMI_Reg(yLo)));
-//..             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
-//..             addInstr(env, X86Instr_Push(X86RMI_Reg(xHi)));
-//..             addInstr(env, X86Instr_Push(X86RMI_Reg(xLo)));
-//..             addInstr(env, X86Instr_Call( Xcc_ALWAYS, (UInt)fn, 0 ));
-//..             add_to_esp(env, 4*4);
-//..             addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
-//..             addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
-//..             *rHi = tHi;
-//..             *rLo = tLo;
-//..             return;
-//..          }
-//.. 
-//..          case Iop_ShlN32x2:
-//..             fn = (HWord)h_generic_calc_ShlN32x2; goto shifty;
-//..          case Iop_ShlN16x4:
-//..             fn = (HWord)h_generic_calc_ShlN16x4; goto shifty;
-//..          case Iop_ShrN32x2:
-//..             fn = (HWord)h_generic_calc_ShrN32x2; goto shifty;
-//..          case Iop_ShrN16x4:
-//..             fn = (HWord)h_generic_calc_ShrN16x4; goto shifty;
-//..          case Iop_SarN32x2:
-//..             fn = (HWord)h_generic_calc_SarN32x2; goto shifty;
-//..          case Iop_SarN16x4:
-//..             fn = (HWord)h_generic_calc_SarN16x4; goto shifty;
-//..          shifty: {
-//..             /* Note: the following assumes all helpers are of
-//..                signature 
-//..                   ULong fn ( ULong, UInt ), and they are
-//..                not marked as regparm functions. 
-//..             */
-//..             HReg xLo, xHi;
-//..             HReg tLo = newVRegI(env);
-//..             HReg tHi = newVRegI(env);
-//..             X86RMI* y = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
-//..             addInstr(env, X86Instr_Push(y));
-//..             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
-//..             addInstr(env, X86Instr_Push(X86RMI_Reg(xHi)));
-//..             addInstr(env, X86Instr_Push(X86RMI_Reg(xLo)));
-//..             addInstr(env, X86Instr_Call( Xcc_ALWAYS, (UInt)fn, 0 ));
-//..             add_to_esp(env, 3*4);
-//..             addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
-//..             addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
-//..             *rHi = tHi;
-//..             *rLo = tLo;
-//..             return;
-//..          }
-
          default: 
             break;
       }