]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fill in a huge number of amd64 floating point cases, and start to
authorJulian Seward <jseward@acm.org>
Fri, 25 Feb 2005 02:48:47 +0000 (02:48 +0000)
committerJulian Seward <jseward@acm.org>
Fri, 25 Feb 2005 02:48:47 +0000 (02:48 +0000)
reinstate the old x87 instruction decoder.

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

VEX/priv/guest-amd64/ghelpers.c
VEX/priv/guest-amd64/toIR.c
VEX/priv/host-amd64/hdefs.c
VEX/priv/host-amd64/hdefs.h
VEX/priv/host-amd64/isel.c
VEX/pub/libvex_guest_amd64.h

index 26934d7a30404c6ebf63c24bd1af1ee2ec7e9b08..3008fff3fcad1785710473cdedaadc0f85aa93c3 100644 (file)
@@ -1141,6 +1141,26 @@ IRExpr* guest_amd64_spechelper ( HChar* function_name,
 }
 
 
+/*---------------------------------------------------------------*/
+/*--- Supporting functions for x87 FPU activities.            ---*/
+/*---------------------------------------------------------------*/
+
+// MAYBE NOT TRUE: /* CALLED FROM GENERATED CODE */
+// MAYBE NOT TRUE: /* DIRTY HELPER (writes guest state) */
+/* Initialise the x87 FPU state as per 'finit'. */
+static
+void amd64g_dirtyhelper_FINIT ( VexGuestAMD64State* gst )
+{
+   Int i;
+   gst->guest_FTOP = 0;
+   for (i = 0; i < 8; i++) {
+      gst->guest_FPTAG[i] = 0; /* empty */
+      gst->guest_FPREG[i] = 0; /* IEEE754 64-bit zero */
+   }
+   gst->guest_FPROUND = (ULong)Irrm_NEAREST;
+   gst->guest_FC3210  = 0;
+}
+
 
 /*---------------------------------------------------------------*/
 /*--- Misc integer helpers, including rotates and CPUID.      ---*/
@@ -1262,6 +1282,9 @@ void LibVEX_GuestAMD64_initialise ( /*OUT*/VexGuestAMD64State* vex_state )
 
    vex_state->guest_RIP = 0;
 
+   /* Initialise the simulated FPU */
+   amd64g_dirtyhelper_FINIT( vex_state );
+
    /* Initialise the SSE state. */
 #  define SSEZERO(_xmm) _xmm[0]=_xmm[1]=_xmm[2]=_xmm[3] = 0;
 
@@ -1339,7 +1362,7 @@ VexGuestLayout
 
           /* Describe any sections to be regarded by Memcheck as
              'always-defined'. */
-          .n_alwaysDefd = 7,
+          .n_alwaysDefd = 11,
 
           /* flags thunk: OP and NDEP are always defd, whereas DEP1
              and DEP2 have to be tracked.  See detailed comment in
@@ -1351,10 +1374,10 @@ VexGuestLayout
                  /*  3 */ ALWAYSDEFD(guest_IDFLAG),
                  /*  4 */ ALWAYSDEFD(guest_RIP),
                  /*  5 */ ALWAYSDEFD(guest_FS_ZERO),
-                 // /* */ ALWAYSDEFD(guest_FTOP),
-                 // /* */ ALWAYSDEFD(guest_FPTAG),
-                 // /* */ ALWAYSDEFD(guest_FPROUND),
-                 // /* */ ALWAYSDEFD(guest_FC3210),
+                 /*  6 */ ALWAYSDEFD(guest_FTOP),
+                 /*  7 */ ALWAYSDEFD(guest_FPTAG),
+                 /*  8 */ ALWAYSDEFD(guest_FPROUND),
+                 /*  9 */ ALWAYSDEFD(guest_FC3210),
                  // /* */ ALWAYSDEFD(guest_CS),
                  // /* */ ALWAYSDEFD(guest_DS),
                  // /* */ ALWAYSDEFD(guest_ES),
index 6295f9a5ab5430aaded40bf2c59a743446dde379..4f1518b5bff706d1d9634b3394e4e605bb7c2d11 100644 (file)
@@ -339,11 +339,11 @@ static void unimplemented ( HChar* str )
 #define OFFB_CC_DEP2   offsetof(VexGuestAMD64State,guest_CC_DEP2)
 #define OFFB_CC_NDEP   offsetof(VexGuestAMD64State,guest_CC_NDEP)
 
-//.. #define OFFB_FPREGS    offsetof(VexGuestX86State,guest_FPREG[0])
-//.. #define OFFB_FPTAGS    offsetof(VexGuestX86State,guest_FPTAG[0])
+#define OFFB_FPREGS    offsetof(VexGuestAMD64State,guest_FPREG[0])
+#define OFFB_FPTAGS    offsetof(VexGuestAMD64State,guest_FPTAG[0])
 #define OFFB_DFLAG     offsetof(VexGuestAMD64State,guest_DFLAG)
 #define OFFB_IDFLAG    offsetof(VexGuestAMD64State,guest_IDFLAG)
-//.. #define OFFB_FTOP      offsetof(VexGuestX86State,guest_FTOP)
+#define OFFB_FTOP      offsetof(VexGuestAMD64State,guest_FTOP)
 //.. #define OFFB_FC3210    offsetof(VexGuestX86State,guest_FC3210)
 //.. #define OFFB_FPROUND   offsetof(VexGuestX86State,guest_FPROUND)
 //.. 
@@ -818,21 +818,28 @@ static Bool haveF3 ( Prefix pfx ) {
 static Bool have66noF2noF3 ( Prefix pfx )
 {
   return 
-     toBool(((pfx & PFX_66) | ((~pfx) & (PFX_F2|PFX_F3))) > 0);
+     toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == PFX_66);
 }
 
 /* Return True iff pfx has F2 set and 66 and F3 clear */
 static Bool haveF2no66noF3 ( Prefix pfx )
 {
   return 
-     toBool(((pfx & PFX_F2) | ((~pfx) & (PFX_66|PFX_F3))) > 0);
+     toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == PFX_F2);
+}
+
+/* Return True iff pfx has F3 set and 66 and F2 clear */
+static Bool haveF3no66noF2 ( Prefix pfx )
+{
+  return 
+     toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == PFX_F3);
 }
 
 /* Return True iff pfx has 66, F2 and F3 clear */
 static Bool haveNo66noF2noF3 ( Prefix pfx )
 {
   return 
-     toBool((((~pfx) & (PFX_66|PFX_F2|PFX_F3))) > 0);
+     toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == 0);
 }
 
 /* Clear all the segment-override bits in a prefix. */
@@ -1159,14 +1166,14 @@ static Int xmmGuestRegOffset ( UInt xmmreg )
 //..    vassert(laneno >= 0 && laneno < 8);
 //..    return xmmGuestRegOffset( xmmreg ) + 2 * laneno;
 //.. }
-//.. 
-//.. static Int xmmGuestRegLane32offset ( UInt xmmreg, Int laneno )
-//.. {
-//..    /* Correct for little-endian host only. */
-//..    vassert(!host_is_bigendian);
-//..    vassert(laneno >= 0 && laneno < 4);
-//..    return xmmGuestRegOffset( xmmreg ) + 4 * laneno;
-//.. }
+
+static Int xmmGuestRegLane32offset ( UInt xmmreg, Int laneno )
+{
+   /* Correct for little-endian host only. */
+   vassert(!host_is_bigendian);
+   vassert(laneno >= 0 && laneno < 4);
+   return xmmGuestRegOffset( xmmreg ) + 4 * laneno;
+}
 
 static Int xmmGuestRegLane64offset ( UInt xmmreg, Int laneno )
 {
@@ -1202,11 +1209,11 @@ static IRExpr* getXMMRegLane64F ( UInt xmmreg, Int laneno )
    return IRExpr_Get( xmmGuestRegLane64offset(xmmreg,laneno), Ity_F64 );
 }
 
-//.. static IRExpr* getXMMRegLane32 ( UInt xmmreg, Int laneno )
-//.. {
-//..    return IRExpr_Get( xmmGuestRegLane32offset(xmmreg,laneno), Ity_I32 );
-//.. }
-//.. 
+static IRExpr* getXMMRegLane32 ( UInt xmmreg, Int laneno )
+{
+   return IRExpr_Get( xmmGuestRegLane32offset(xmmreg,laneno), Ity_I32 );
+}
+
 //.. static IRExpr* getXMMRegLane32F ( UInt xmmreg, Int laneno )
 //.. {
 //..    return IRExpr_Get( xmmGuestRegLane32offset(xmmreg,laneno), Ity_F32 );
@@ -1230,18 +1237,18 @@ static void putXMMRegLane64F ( UInt xmmreg, Int laneno, IRExpr* e )
    stmt( IRStmt_Put( xmmGuestRegLane64offset(xmmreg,laneno), e ) );
 }
 
-//.. static void putXMMRegLane32F ( UInt xmmreg, Int laneno, IRExpr* e )
-//.. {
-//..    vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_F32);
-//..    stmt( IRStmt_Put( xmmGuestRegLane32offset(xmmreg,laneno), e ) );
-//.. }
-//.. 
-//.. static void putXMMRegLane32 ( UInt xmmreg, Int laneno, IRExpr* e )
-//.. {
-//..    vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_I32);
-//..    stmt( IRStmt_Put( xmmGuestRegLane32offset(xmmreg,laneno), e ) );
-//.. }
-//.. 
+static void putXMMRegLane32F ( UInt xmmreg, Int laneno, IRExpr* e )
+{
+   vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_F32);
+   stmt( IRStmt_Put( xmmGuestRegLane32offset(xmmreg,laneno), e ) );
+}
+
+static void putXMMRegLane32 ( UInt xmmreg, Int laneno, IRExpr* e )
+{
+   vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_I32);
+   stmt( IRStmt_Put( xmmGuestRegLane32offset(xmmreg,laneno), e ) );
+}
+
 //.. static void putXMMRegLane16 ( UInt xmmreg, Int laneno, IRExpr* e )
 //.. {
 //..    vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_I16);
@@ -3896,30 +3903,31 @@ ULong dis_imul_I_E_G ( Prefix      pfx,
 //.. {
 //..    stmt( IRStmt_Put( OFFB_EMWARN, e ) );
 //.. }
-//.. 
-//.. /* --- Produce an IRExpr* denoting a 64-bit QNaN. --- */
-//.. 
-//.. static IRExpr* mkQNaN64 ( void )
-//.. {
-//..   /* QNaN is 0 2047 1 0(51times) 
-//..      == 0b 11111111111b 1 0(51times)
-//..      == 0x7FF8 0000 0000 0000
-//..    */
-//..    return IRExpr_Const(IRConst_F64i(0x7FF8000000000000ULL));
-//.. }
-//.. 
-//.. /* --------- Get/put the top-of-stack pointer. --------- */
-//.. 
-//.. static IRExpr* get_ftop ( void )
-//.. {
-//..    return IRExpr_Get( OFFB_FTOP, Ity_I32 );
-//.. }
-//.. 
-//.. static void put_ftop ( IRExpr* e )
-//.. {
-//..    stmt( IRStmt_Put( OFFB_FTOP, e ) );
-//.. }
-//.. 
+
+/* --- Produce an IRExpr* denoting a 64-bit QNaN. --- */
+
+static IRExpr* mkQNaN64 ( void )
+{
+  /* QNaN is 0 2047 1 0(51times) 
+     == 0b 11111111111b 1 0(51times)
+     == 0x7FF8 0000 0000 0000
+   */
+   return IRExpr_Const(IRConst_F64i(0x7FF8000000000000ULL));
+}
+
+/* --------- Get/put the top-of-stack pointer :: Ity_I32 --------- */
+
+static IRExpr* get_ftop ( void )
+{
+   return IRExpr_Get( OFFB_FTOP, Ity_I32 );
+}
+
+static void put_ftop ( IRExpr* e )
+{
+   vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I32);
+   stmt( IRStmt_Put( OFFB_FTOP, e ) );
+}
+
 //.. /* --------- Get/put the C3210 bits. --------- */
 //.. 
 //.. static IRExpr* get_C3210 ( void )
@@ -3954,104 +3962,104 @@ ULong dis_imul_I_E_G ( Prefix      pfx,
 //.. {
 //..    return binop( Iop_And32, get_fpround(), mkU32(3) );
 //.. }
-//.. 
-//.. 
-//.. /* --------- Get/set FP register tag bytes. --------- */
-//.. 
-//.. /* Given i, and some expression e, generate 'ST_TAG(i) = e'. */
-//.. 
-//.. static void put_ST_TAG ( Int i, IRExpr* value )
-//.. {
-//..    IRArray* descr;
-//..    vassert(typeOfIRExpr(irbb->tyenv, value) == Ity_I8);
-//..    descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
-//..    stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
-//.. }
-//.. 
-//.. /* Given i, generate an expression yielding 'ST_TAG(i)'.  This will be
-//..    zero to indicate "Empty" and nonzero to indicate "NonEmpty".  */
-//.. 
-//.. static IRExpr* get_ST_TAG ( Int i )
-//.. {
-//..    IRArray* descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
-//..    return IRExpr_GetI( descr, get_ftop(), i );
-//.. }
-//.. 
-//.. 
-//.. /* --------- Get/set FP registers. --------- */
-//.. 
-//.. /* Given i, and some expression e, emit 'ST(i) = e' and set the
-//..    register's tag to indicate the register is full.  The previous
-//..    state of the register is not checked. */
-//.. 
-//.. static void put_ST_UNCHECKED ( Int i, IRExpr* value )
-//.. {
-//..    IRArray* descr;
-//..    vassert(typeOfIRExpr(irbb->tyenv, value) == Ity_F64);
-//..    descr = mkIRArray( OFFB_FPREGS, Ity_F64, 8 );
-//..    stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
-//..    /* Mark the register as in-use. */
-//..    put_ST_TAG(i, mkU8(1));
-//.. }
-//.. 
-//.. /* Given i, and some expression e, emit
-//..       ST(i) = is_full(i) ? NaN : e
-//..    and set the tag accordingly.
-//.. */
-//.. 
-//.. static void put_ST ( Int i, IRExpr* value )
-//.. {
-//..    put_ST_UNCHECKED( i,
-//..                      IRExpr_Mux0X( get_ST_TAG(i),
-//..                                    /* 0 means empty */
-//..                                    value,
-//..                                    /* non-0 means full */
-//..                                    mkQNaN64()
-//..                    )
-//..    );
-//.. }
-//.. 
-//.. 
-//.. /* Given i, generate an expression yielding 'ST(i)'. */
-//.. 
-//.. static IRExpr* get_ST_UNCHECKED ( Int i )
-//.. {
-//..    IRArray* descr = mkIRArray( OFFB_FPREGS, Ity_F64, 8 );
-//..    return IRExpr_GetI( descr, get_ftop(), i );
-//.. }
-//.. 
-//.. 
-//.. /* Given i, generate an expression yielding 
-//..   is_full(i) ? ST(i) : NaN
-//.. */
-//.. 
-//.. static IRExpr* get_ST ( Int i )
-//.. {
-//..    return
-//..       IRExpr_Mux0X( get_ST_TAG(i),
-//..                     /* 0 means empty */
-//..                     mkQNaN64(),
-//..                     /* non-0 means full */
-//..                     get_ST_UNCHECKED(i));
-//.. }
-//.. 
-//.. 
-//.. /* Adjust FTOP downwards by one register. */
-//.. 
-//.. static void fp_push ( void )
-//.. {
-//..    put_ftop( binop(Iop_Sub32, get_ftop(), mkU32(1)) );
-//.. }
-//.. 
-//.. /* Adjust FTOP upwards by one register, and mark the vacated register
-//..    as empty.  */
-//.. 
-//.. static void fp_pop ( void )
-//.. {
-//..    put_ST_TAG(0, mkU8(0));
-//..    put_ftop( binop(Iop_Add32, get_ftop(), mkU32(1)) );
-//.. }
-//.. 
+
+
+/* --------- Get/set FP register tag bytes. --------- */
+
+/* Given i, and some expression e, generate 'ST_TAG(i) = e'. */
+
+static void put_ST_TAG ( Int i, IRExpr* value )
+{
+   IRArray* descr;
+   vassert(typeOfIRExpr(irbb->tyenv, value) == Ity_I8);
+   descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
+   stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
+}
+
+/* Given i, generate an expression yielding 'ST_TAG(i)'.  This will be
+   zero to indicate "Empty" and nonzero to indicate "NonEmpty".  */
+
+static IRExpr* get_ST_TAG ( Int i )
+{
+   IRArray* descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
+   return IRExpr_GetI( descr, get_ftop(), i );
+}
+
+
+/* --------- Get/set FP registers. --------- */
+
+/* Given i, and some expression e, emit 'ST(i) = e' and set the
+   register's tag to indicate the register is full.  The previous
+   state of the register is not checked. */
+
+static void put_ST_UNCHECKED ( Int i, IRExpr* value )
+{
+   IRArray* descr;
+   vassert(typeOfIRExpr(irbb->tyenv, value) == Ity_F64);
+   descr = mkIRArray( OFFB_FPREGS, Ity_F64, 8 );
+   stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
+   /* Mark the register as in-use. */
+   put_ST_TAG(i, mkU8(1));
+}
+
+/* Given i, and some expression e, emit
+      ST(i) = is_full(i) ? NaN : e
+   and set the tag accordingly.
+*/
+
+static void put_ST ( Int i, IRExpr* value )
+{
+   put_ST_UNCHECKED( i,
+                     IRExpr_Mux0X( get_ST_TAG(i),
+                                   /* 0 means empty */
+                                   value,
+                                   /* non-0 means full */
+                                   mkQNaN64()
+                   )
+   );
+}
+
+
+/* Given i, generate an expression yielding 'ST(i)'. */
+
+static IRExpr* get_ST_UNCHECKED ( Int i )
+{
+   IRArray* descr = mkIRArray( OFFB_FPREGS, Ity_F64, 8 );
+   return IRExpr_GetI( descr, get_ftop(), i );
+}
+
+
+/* Given i, generate an expression yielding 
+  is_full(i) ? ST(i) : NaN
+*/
+
+static IRExpr* get_ST ( Int i )
+{
+   return
+      IRExpr_Mux0X( get_ST_TAG(i),
+                    /* 0 means empty */
+                    mkQNaN64(),
+                    /* non-0 means full */
+                    get_ST_UNCHECKED(i));
+}
+
+
+/* Adjust FTOP downwards by one register. */
+
+static void fp_push ( void )
+{
+   put_ftop( binop(Iop_Sub32, get_ftop(), mkU32(1)) );
+}
+
+/* Adjust FTOP upwards by one register, and mark the vacated register
+   as empty.  */
+
+static void fp_pop ( void )
+{
+   put_ST_TAG(0, mkU8(0));
+   put_ftop( binop(Iop_Add32, get_ftop(), mkU32(1)) );
+}
+
 //.. /* Clear the C2 bit of the FPU status register, for
 //..    sin/cos/tan/sincos. */
 //.. 
@@ -4166,21 +4174,21 @@ ULong dis_imul_I_E_G ( Prefix      pfx,
 //..    if (pop_after)
 //..       fp_pop();
 //.. }
-//.. 
-//.. 
-//.. static
-//.. UInt dis_FPU ( Bool* decode_ok, UChar sorb, ULong delta )
-//.. {
-//..    Int    len;
-//..    UInt   r_src, r_dst;
-//..    HChar  dis_buf[50];
-//..    IRTemp t1, t2;
-//.. 
-//..    /* On entry, delta points at the second byte of the insn (the modrm
-//..       byte).*/
-//..    UChar first_opcode = getUChar(delta-1);
-//..    UChar modrm        = getUChar(delta+0);
-//.. 
+
+
+static
+ULong dis_FPU ( Bool* decode_ok, Prefix pfx, ULong delta )
+{
+   Int    len;
+   UInt   r_src, r_dst;
+   HChar  dis_buf[50];
+   IRTemp t1, t2;
+
+   /* On entry, delta points at the second byte of the insn (the modrm
+      byte).*/
+   UChar first_opcode = getUChar(delta-1);
+   UChar modrm        = getUChar(delta+0);
+
 //..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD8 opcodes +-+-+-+-+-+-+-+ */
 //.. 
 //..    if (first_opcode == 0xD8) {
@@ -4317,19 +4325,19 @@ ULong dis_imul_I_E_G ( Prefix      pfx,
 //..          }
 //..       }
 //..    }
-//.. 
-//..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD9 opcodes +-+-+-+-+-+-+-+ */
+
+   /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD9 opcodes +-+-+-+-+-+-+-+ */
 //..    else
-//..    if (first_opcode == 0xD9) {
-//..       if (modrm < 0xC0) {
-//.. 
-//..          /* bits 5,4,3 are an opcode extension, and the modRM also
-//..             specifies an address. */
-//..          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
-//..          delta += len;
-//.. 
-//..          switch (gregOfRM(modrm)) {
-//.. 
+   if (first_opcode == 0xD9) {
+      if (modrm < 0xC0) {
+
+         /* bits 5,4,3 are an opcode extension, and the modRM also
+            specifies an address. */
+         IRTemp addr = disAMode( &len, pfx, delta, dis_buf, 0 );
+         delta += len;
+
+         switch (gregOfRM(modrm)) {
+
 //..             case 0: /* FLD single-real */
 //..                DIP("flds %s\n", dis_buf);
 //..                fp_push();
@@ -4506,17 +4514,17 @@ ULong dis_imul_I_E_G ( Prefix      pfx,
 //..                   ) 
 //..                );
 //..                break;
-//.. 
-//..             default:
-//..                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
-//..                vex_printf("first_opcode == 0xD9\n");
-//..                goto decode_fail;
-//..          }
-//.. 
-//..       } else {
-//..          delta++;
-//..          switch (modrm) {
-//.. 
+
+            default:
+               vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+               vex_printf("first_opcode == 0xD9\n");
+               goto decode_fail;
+         }
+
+      } else {
+         delta++;
+         switch (modrm) {
+
 //..             case 0xC0 ... 0xC7: /* FLD %st(?) */
 //..                r_src = (UInt)modrm - 0xC0;
 //..                DIP("fld %%st(%d)\n", r_src);
@@ -4525,23 +4533,23 @@ ULong dis_imul_I_E_G ( Prefix      pfx,
 //..                fp_push();
 //..                put_ST(0, mkexpr(t1));
 //..                break;
-//.. 
-//..             case 0xC8 ... 0xCF: /* FXCH %st(?) */
-//..                r_src = (UInt)modrm - 0xC8;
-//..                DIP("fxch %%st(%d)\n", r_src);
-//..                t1 = newTemp(Ity_F64);
-//..                t2 = newTemp(Ity_F64);
-//..                assign(t1, get_ST(0));
-//..                assign(t2, get_ST(r_src));
-//..                put_ST_UNCHECKED(0, mkexpr(t2));
-//..                put_ST_UNCHECKED(r_src, mkexpr(t1));
-//..                break;
-//.. 
-//..             case 0xE0: /* FCHS */
-//..                DIP("fchs\n");
-//..                put_ST_UNCHECKED(0, unop(Iop_NegF64, get_ST(0)));
-//..                break;
-//.. 
+
+            case 0xC8 ... 0xCF: /* FXCH %st(?) */
+               r_src = (UInt)modrm - 0xC8;
+               DIP("fxch %%st(%d)\n", r_src);
+               t1 = newTemp(Ity_F64);
+               t2 = newTemp(Ity_F64);
+               assign(t1, get_ST(0));
+               assign(t2, get_ST(r_src));
+               put_ST_UNCHECKED(0, mkexpr(t2));
+               put_ST_UNCHECKED(r_src, mkexpr(t1));
+               break;
+
+            case 0xE0: /* FCHS */
+               DIP("fchs\n");
+               put_ST_UNCHECKED(0, unop(Iop_NegF64, get_ST(0)));
+               break;
+
 //..             case 0xE1: /* FABS */
 //..                DIP("fabs\n");
 //..                put_ST_UNCHECKED(0, unop(Iop_AbsF64, get_ST(0)));
@@ -4721,26 +4729,26 @@ ULong dis_imul_I_E_G ( Prefix      pfx,
 //..                put_ST_UNCHECKED(0, unop(Iop_CosF64, get_ST(0)));
 //..                clear_C2(); /* HACK */
 //..                break;
-//.. 
-//..             default:
-//..                goto decode_fail;
-//..          }
-//..       }
-//..    }
-//.. 
-//..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDA opcodes +-+-+-+-+-+-+-+ */
-//..    else
-//..    if (first_opcode == 0xDA) {
-//.. 
-//..       if (modrm < 0xC0) {
-//.. 
-//..          /* bits 5,4,3 are an opcode extension, and the modRM also
-//..             specifies an address. */
-//..          IROp   fop;
-//..          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
-//..          delta += len;
-//..          switch (gregOfRM(modrm)) {
-//.. 
+
+            default:
+               goto decode_fail;
+         }
+      }
+   }
+
+   /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDA opcodes +-+-+-+-+-+-+-+ */
+   else
+   if (first_opcode == 0xDA) {
+
+      if (modrm < 0xC0) {
+
+         /* bits 5,4,3 are an opcode extension, and the modRM also
+            specifies an address. */
+         IROp   fop;
+         IRTemp addr = disAMode( &len, pfx, delta, dis_buf, 0 );
+         delta += len;
+         switch (gregOfRM(modrm)) {
+
 //..             case 0: /* FIADD m32int */ /* ST(0) += m32int */
 //..                DIP("fiaddl %s\n", dis_buf);
 //..                fop = Iop_AddF64;
@@ -4786,18 +4794,18 @@ ULong dis_imul_I_E_G ( Prefix      pfx,
 //..                              loadLE(Ity_I32, mkexpr(addr))),
 //..                         get_ST(0)));
 //..                break;
-//.. 
-//..             default:
-//..                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
-//..                vex_printf("first_opcode == 0xDA\n");
-//..                goto decode_fail;
-//..          }
-//.. 
-//..       } else {
-//.. 
-//..          delta++;
-//..          switch (modrm) {
-//.. 
+
+            default:
+               vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+               vex_printf("first_opcode == 0xDA\n");
+               goto decode_fail;
+         }
+
+      } else {
+
+         delta++;
+         switch (modrm) {
+
 //..             case 0xC0 ... 0xC7: /* FCMOVB ST(i), ST(0) */
 //..                r_src = (UInt)modrm - 0xC0;
 //..                DIP("fcmovb %%st(%d), %%st(0)\n", r_src);
@@ -4807,17 +4815,17 @@ ULong dis_imul_I_E_G ( Prefix      pfx,
 //..                                          mk_x86g_calculate_condition(X86CondB)), 
 //..                                     get_ST(0), get_ST(r_src)) );
 //..                break;
-//.. 
-//..             case 0xC8 ... 0xCF: /* FCMOVE(Z) ST(i), ST(0) */
-//..                r_src = (UInt)modrm - 0xC8;
-//..                DIP("fcmovz %%st(%d), %%st(0)\n", r_src);
-//..                put_ST_UNCHECKED(0, 
-//..                                 IRExpr_Mux0X( 
-//..                                     unop(Iop_1Uto8,
-//..                                          mk_x86g_calculate_condition(X86CondZ)), 
-//..                                     get_ST(0), get_ST(r_src)) );
-//..                break;
-//.. 
+
+            case 0xC8 ... 0xCF: /* FCMOVE(Z) ST(i), ST(0) */
+               r_src = (UInt)modrm - 0xC8;
+               DIP("fcmovz %%st(%d), %%st(0)\n", r_src);
+               put_ST_UNCHECKED(0, 
+                                IRExpr_Mux0X( 
+                                    unop(Iop_1Uto8,
+                                         mk_amd64g_calculate_condition(AMD64CondZ)), 
+                                    get_ST(0), get_ST(r_src)) );
+               break;
+
 //..             case 0xD0 ... 0xD7: /* FCMOVBE ST(i), ST(0) */
 //..                r_src = (UInt)modrm - 0xD0;
 //..                DIP("fcmovbe %%st(%d), %%st(0)\n", r_src);
@@ -4841,14 +4849,14 @@ ULong dis_imul_I_E_G ( Prefix      pfx,
 //..                fp_pop();
 //..                fp_pop();
 //..                break;
-//.. 
-//..             default:
-//..                goto decode_fail;
-//..          }
-//.. 
-//..       }
-//..    }
-//.. 
+
+            default:
+               goto decode_fail;
+         }
+
+      }
+   }
+
 //..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDB opcodes +-+-+-+-+-+-+-+ */
 //..    else
 //..    if (first_opcode == 0xDB) {
@@ -5138,37 +5146,37 @@ ULong dis_imul_I_E_G ( Prefix      pfx,
 //.. 
 //..       }
 //..    }
-//.. 
-//..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDD opcodes +-+-+-+-+-+-+-+ */
-//..    else
-//..    if (first_opcode == 0xDD) {
-//.. 
-//..       if (modrm < 0xC0) {
-//.. 
-//..          /* bits 5,4,3 are an opcode extension, and the modRM also
-//..             specifies an address. */
-//..          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
-//..          delta += len;
-//.. 
-//..          switch (gregOfRM(modrm)) {
-//.. 
-//..             case 0: /* FLD double-real */
-//..                DIP("fldl %s\n", dis_buf);
-//..                fp_push();
-//..                put_ST(0, IRExpr_LDle(Ity_F64, mkexpr(addr)));
-//..                break;
-//.. 
+
+   /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDD opcodes +-+-+-+-+-+-+-+ */
+   else
+   if (first_opcode == 0xDD) {
+
+      if (modrm < 0xC0) {
+
+         /* bits 5,4,3 are an opcode extension, and the modRM also
+            specifies an address. */
+         IRTemp addr = disAMode( &len, pfx, delta, dis_buf, 0 );
+         delta += len;
+
+         switch (gregOfRM(modrm)) {
+
+            case 0: /* FLD double-real */
+               DIP("fldl %s\n", dis_buf);
+               fp_push();
+               put_ST(0, IRExpr_LDle(Ity_F64, mkexpr(addr)));
+               break;
+
 //..             case 2: /* FST double-real */
 //..                DIP("fstl %s\n", dis_buf);
 //..                storeLE(mkexpr(addr), get_ST(0));
 //..                break;
-//.. 
-//..             case 3: /* FSTP double-real */
-//..                DIP("fstpl %s\n", dis_buf);
-//..                storeLE(mkexpr(addr), get_ST(0));
-//..                fp_pop();
-//..                break;
-//.. 
+
+            case 3: /* FSTP double-real */
+               DIP("fstpl %s\n", dis_buf);
+               storeLE(mkexpr(addr), get_ST(0));
+               fp_pop();
+               break;
+
 //..             case 4: { /* FRSTOR m108 */
 //..                /* Uses dirty helper: 
 //..                      VexEmWarn x86g_do_FRSTOR ( VexGuestX86State*, Addr32 ) */
@@ -5271,16 +5279,16 @@ ULong dis_imul_I_E_G ( Prefix      pfx,
 //..                DIP("fnsave %s\n", dis_buf);
 //..                break;
 //..             }
-//.. 
-//..             default:
-//..                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
-//..                vex_printf("first_opcode == 0xDD\n");
-//..                goto decode_fail;
-//..          }
-//..       } else {
-//..          delta++;
-//..          switch (modrm) {
-//.. 
+
+            default:
+               vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+               vex_printf("first_opcode == 0xDD\n");
+               goto decode_fail;
+         }
+      } else {
+         delta++;
+         switch (modrm) {
+
 //..             case 0xD0 ... 0xD7: /* FST %st(0),%st(?) */
 //..                r_dst = (UInt)modrm - 0xD0;
 //..                DIP("fst %%st(0),%%st(%d)\n", r_dst);
@@ -5289,17 +5297,17 @@ ULong dis_imul_I_E_G ( Prefix      pfx,
 //..                   is not generated.  Hence put_ST_UNCHECKED. */
 //..                put_ST_UNCHECKED(r_dst, get_ST(0));
 //..                break;
-//.. 
-//..             case 0xD8 ... 0xDF: /* FSTP %st(0),%st(?) */
-//..                r_dst = (UInt)modrm - 0xD8;
-//..                DIP("fstp %%st(0),%%st(%d)\n", r_dst);
-//..                /* P4 manual says: "If the destination operand is a
-//..                   non-empty register, the invalid-operation exception
-//..                   is not generated.  Hence put_ST_UNCHECKED. */
-//..                put_ST_UNCHECKED(r_dst, get_ST(0));
-//..                fp_pop();
-//..                break;
-//.. 
+
+            case 0xD8 ... 0xDF: /* FSTP %st(0),%st(?) */
+               r_dst = (UInt)modrm - 0xD8;
+               DIP("fstp %%st(0),%%st(%d)\n", r_dst);
+               /* P4 manual says: "If the destination operand is a
+                  non-empty register, the invalid-operation exception
+                  is not generated.  Hence put_ST_UNCHECKED. */
+               put_ST_UNCHECKED(r_dst, get_ST(0));
+               fp_pop();
+               break;
+
 //..             case 0xE0 ... 0xE7: /* FUCOM %st(0),%st(?) */
 //..                r_dst = (UInt)modrm - 0xE0;
 //..                DIP("fucom %%st(0),%%st(%d)\n", r_dst);
@@ -5326,13 +5334,13 @@ ULong dis_imul_I_E_G ( Prefix      pfx,
 //..                    ));
 //..                fp_pop();
 //..                break;
-//.. 
-//..             default:
-//..                goto decode_fail;
-//..          }
-//..       }
-//..    }
-//.. 
+
+            default:
+               goto decode_fail;
+         }
+      }
+   }
+
 //..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDE opcodes +-+-+-+-+-+-+-+ */
 //..    else
 //..    if (first_opcode == 0xDE) {
@@ -5542,19 +5550,19 @@ ULong dis_imul_I_E_G ( Prefix      pfx,
 //..       }
 //.. 
 //..    }
-//.. 
-//..    else
-//..    vpanic("dis_FPU(x86): invalid primary opcode");
-//.. 
-//..    *decode_ok = True;
-//..    return delta;
-//.. 
-//..   decode_fail:
-//..    *decode_ok = False;
-//..    return delta;
-//.. }
-//.. 
-//.. 
+
+   else
+      goto decode_fail; //vpanic("dis_FPU(amd64): invalid primary opcode");
+
+   *decode_ok = True;
+   return delta;
+
+  decode_fail:
+   *decode_ok = False;
+   return delta;
+}
+
+
 //.. /*------------------------------------------------------------*/
 //.. /*---                                                      ---*/
 //.. /*--- MMX INSTRUCTIONS                                     ---*/
@@ -6976,11 +6984,11 @@ void dis_ret ( ULong d64 )
    Handles full width G = G `op` E   and   G = (not G) `op` E.
 */
 
-static UInt dis_SSE_E_to_G_all_wrk ( 
-               Prefix pfx, ULong delta, 
-               HChar* opname, IROp op,
-               Bool   invertG
-            )
+static ULong dis_SSE_E_to_G_all_wrk ( 
+                Prefix pfx, ULong delta, 
+                HChar* opname, IROp op,
+                Bool   invertG
+             )
 {
    HChar   dis_buf[50];
    Int     alen;
@@ -7013,60 +7021,61 @@ static UInt dis_SSE_E_to_G_all_wrk (
 /* All lanes SSE binary operation, G = G `op` E. */
 
 static
-UInt dis_SSE_E_to_G_all ( Prefix pfx, ULong delta, HChar* opname, IROp op )
+ULong dis_SSE_E_to_G_all ( Prefix pfx, ULong delta, 
+                           HChar* opname, IROp op )
 {
    return dis_SSE_E_to_G_all_wrk( pfx, delta, opname, op, False );
 }
 
-//.. /* All lanes SSE binary operation, G = (not G) `op` E. */
-//.. 
-//.. static
-//.. UInt dis_SSE_E_to_G_all_invG ( UChar sorb, ULong delta, 
-//..                                HChar* opname, IROp op )
-//.. {
-//..    return dis_SSE_E_to_G_all_wrk( sorb, delta, opname, op, True );
-//.. }
-//.. 
-//.. 
-//.. /* Lowest 32-bit lane only SSE binary operation, G = G `op` E. */
-//.. 
-//.. static UInt dis_SSE_E_to_G_lo32 ( UChar sorb, ULong delta, 
-//..                                   HChar* opname, IROp op )
-//.. {
-//..    HChar   dis_buf[50];
-//..    Int     alen;
-//..    IRTemp  addr;
-//..    UChar   rm = getUChar(delta);
-//..    IRExpr* gpart = getXMMReg(gregOfRM(rm));
-//..    if (epartIsReg(rm)) {
-//..       putXMMReg( gregOfRM(rm), 
-//..                  binop(op, gpart,
-//..                            getXMMReg(eregOfRM(rm))) );
-//..       DIP("%s %s,%s\n", opname,
-//..                         nameXMMReg(eregOfRM(rm)),
-//..                         nameXMMReg(gregOfRM(rm)) );
-//..       return delta+1;
-//..    } else {
-//..       /* We can only do a 32-bit memory read, so the upper 3/4 of the
-//..          E operand needs to be made simply of zeroes. */
-//..       IRTemp epart = newTemp(Ity_V128);
-//..       addr = disAMode ( &alen, sorb, delta, dis_buf );
-//..       assign( epart, unop( Iop_32Uto128,
-//..                            loadLE(Ity_I32, mkexpr(addr))) );
-//..       putXMMReg( gregOfRM(rm), 
-//..                  binop(op, gpart, mkexpr(epart)) );
-//..       DIP("%s %s,%s\n", opname,
-//..                         dis_buf,
-//..                         nameXMMReg(gregOfRM(rm)) );
-//..       return delta+alen;
-//..    }
-//.. }
+/* All lanes SSE binary operation, G = (not G) `op` E. */
+
+static
+ULong dis_SSE_E_to_G_all_invG ( Prefix pfx, ULong delta, 
+                                HChar* opname, IROp op )
+{
+   return dis_SSE_E_to_G_all_wrk( pfx, delta, opname, op, True );
+}
+
+
+/* Lowest 32-bit lane only SSE binary operation, G = G `op` E. */
+
+static ULong dis_SSE_E_to_G_lo32 ( Prefix pfx, ULong delta, 
+                                   HChar* opname, IROp op )
+{
+   HChar   dis_buf[50];
+   Int     alen;
+   IRTemp  addr;
+   UChar   rm = getUChar(delta);
+   IRExpr* gpart = getXMMReg(gregOfRM(rm));
+   if (epartIsReg(rm)) {
+      putXMMReg( gregOfRM(rm), 
+                 binop(op, gpart,
+                           getXMMReg(eregOfRexRM(pfx,rm))) );
+      DIP("%s %s,%s\n", opname,
+                        nameXMMReg(eregOfRexRM(pfx,rm)),
+                        nameXMMReg(gregOfRexRM(pfx,rm)) );
+      return delta+1;
+   } else {
+      /* We can only do a 32-bit memory read, so the upper 3/4 of the
+         E operand needs to be made simply of zeroes. */
+      IRTemp epart = newTemp(Ity_V128);
+      addr = disAMode ( &alen, pfx, delta, dis_buf, 0 );
+      assign( epart, unop( Iop_32UtoV128,
+                           loadLE(Ity_I32, mkexpr(addr))) );
+      putXMMReg( gregOfRexRM(pfx,rm), 
+                 binop(op, gpart, mkexpr(epart)) );
+      DIP("%s %s,%s\n", opname,
+                        dis_buf,
+                        nameXMMReg(gregOfRexRM(pfx,rm)) );
+      return delta+alen;
+   }
+}
 
 
 /* Lower 64-bit lane only SSE binary operation, G = G `op` E. */
 
-static UInt dis_SSE_E_to_G_lo64 ( Prefix pfx, ULong delta, 
-                                  HChar* opname, IROp op )
+static ULong dis_SSE_E_to_G_lo64 ( Prefix pfx, ULong delta, 
+                                   HChar* opname, IROp op )
 {
    HChar   dis_buf[50];
    Int     alen;
@@ -7173,10 +7182,10 @@ static UInt dis_SSE_E_to_G_lo64 ( Prefix pfx, ULong delta,
 
 /* Lowest 64-bit lane only unary SSE operation, G = op(E). */
 
-static UInt dis_SSE_E_to_G_unary_lo64 ( 
-               Prefix pfx, ULong delta, 
-               HChar* opname, IROp op
-            )
+static ULong dis_SSE_E_to_G_unary_lo64 ( 
+                Prefix pfx, ULong delta, 
+                HChar* opname, IROp op
+             )
 {
    /* First we need to get the old G value and patch the low 64 bits
       of the E operand into it.  Then apply op and write back to G. */
@@ -7249,115 +7258,115 @@ static UInt dis_SSE_E_to_G_unary_lo64 (
 //..               : binop(op, gpart, epart) );
 //..    return delta;
 //.. }
-//.. 
-//.. 
-//.. /* Helper for doing SSE FP comparisons. */
-//.. 
-//.. static void findSSECmpOp ( Bool* needNot, IROp* op, 
-//..                            Int imm8, Bool all_lanes, Int sz )
-//.. {
-//..    imm8 &= 7;
-//..    *needNot = False;
-//..    *op      = Iop_INVALID;
-//..    if (imm8 >= 4) {
-//..       *needNot = True;
-//..       imm8 -= 4;
-//..    }
-//.. 
-//..    if (sz == 4 && all_lanes) {
-//..       switch (imm8) {
-//..          case 0: *op = Iop_CmpEQ32Fx4; return;
-//..          case 1: *op = Iop_CmpLT32Fx4; return;
-//..          case 2: *op = Iop_CmpLE32Fx4; return;
-//..          case 3: *op = Iop_CmpUN32Fx4; return;
-//..          default: break;
-//..       }
-//..    }
-//..    if (sz == 4 && !all_lanes) {
-//..       switch (imm8) {
-//..          case 0: *op = Iop_CmpEQ32F0x4; return;
-//..          case 1: *op = Iop_CmpLT32F0x4; return;
-//..          case 2: *op = Iop_CmpLE32F0x4; return;
-//..          case 3: *op = Iop_CmpUN32F0x4; return;
-//..          default: break;
-//..       }
-//..    }
-//..    if (sz == 8 && all_lanes) {
-//..       switch (imm8) {
-//..          case 0: *op = Iop_CmpEQ64Fx2; return;
-//..          case 1: *op = Iop_CmpLT64Fx2; return;
-//..          case 2: *op = Iop_CmpLE64Fx2; return;
-//..          case 3: *op = Iop_CmpUN64Fx2; return;
-//..          default: break;
-//..       }
-//..    }
-//..    if (sz == 8 && !all_lanes) {
-//..       switch (imm8) {
-//..          case 0: *op = Iop_CmpEQ64F0x2; return;
-//..          case 1: *op = Iop_CmpLT64F0x2; return;
-//..          case 2: *op = Iop_CmpLE64F0x2; return;
-//..          case 3: *op = Iop_CmpUN64F0x2; return;
-//..          default: break;
-//..       }
-//..    }
-//..    vpanic("findSSECmpOp(x86,guest)");
-//.. }
-//.. 
-//.. /* Handles SSE 32F comparisons. */
-//.. 
-//.. static UInt dis_SSEcmp_E_to_G ( UChar sorb, ULong delta, 
-//..                           HChar* opname, Bool all_lanes, Int sz )
-//.. {
-//..    HChar   dis_buf[50];
-//..    Int     alen, imm8;
-//..    IRTemp  addr;
-//..    Bool    needNot = False;
-//..    IROp    op      = Iop_INVALID;
-//..    IRTemp  plain   = newTemp(Ity_V128);
-//..    UChar   rm      = getUChar(delta);
-//..    UShort  mask    = 0;
-//..    vassert(sz == 4 || sz == 8);
-//..    if (epartIsReg(rm)) {
-//..       imm8 = getUChar(delta+1);
-//..       findSSECmpOp(&needNot, &op, imm8, all_lanes, sz);
-//..       assign( plain, binop(op, getXMMReg(gregOfRM(rm)), 
-//..                                getXMMReg(eregOfRM(rm))) );
-//..       delta += 2;
-//..       DIP("%s $%d,%s,%s\n", opname,
-//..                             (Int)imm8,
-//..                             nameXMMReg(eregOfRM(rm)),
-//..                             nameXMMReg(gregOfRM(rm)) );
-//..    } else {
-//..       addr = disAMode ( &alen, sorb, delta, dis_buf );
-//..       imm8 = getUChar(delta+alen);
-//..       findSSECmpOp(&needNot, &op, imm8, all_lanes, sz);
-//..       assign( plain, binop(op, getXMMReg(gregOfRM(rm)), 
-//..                                loadLE(Ity_V128, mkexpr(addr))) );
-//..       delta += alen+1;
-//..       DIP("%s $%d,%s,%s\n", opname,
-//..                             (Int)imm8,
-//..                             dis_buf,
-//..                             nameXMMReg(gregOfRM(rm)) );
-//..    }
-//.. 
-//..    if (needNot && all_lanes) {
-//..       putXMMReg( gregOfRM(rm), 
-//..                  unop(Iop_Not128, mkexpr(plain)) );
-//..    }
-//..    else
-//..    if (needNot && !all_lanes) {
-//..       mask = sz==4 ? 0x000F : 0x00FF;
-//..       putXMMReg( gregOfRM(rm), 
-//..                  binop(Iop_Xor128, mkexpr(plain), mkV128(mask)) );
-//..    }
-//..    else {
-//..       putXMMReg( gregOfRM(rm), mkexpr(plain) );
-//..    }
-//.. 
-//..    return delta;
-//.. }
-//.. 
-//.. 
+
+
+/* Helper for doing SSE FP comparisons. */
+
+static void findSSECmpOp ( Bool* needNot, IROp* op, 
+                           Int imm8, Bool all_lanes, Int sz )
+{
+   imm8 &= 7;
+   *needNot = False;
+   *op      = Iop_INVALID;
+   if (imm8 >= 4) {
+      *needNot = True;
+      imm8 -= 4;
+   }
+
+   if (sz == 4 && all_lanes) {
+      switch (imm8) {
+         case 0: *op = Iop_CmpEQ32Fx4; return;
+         case 1: *op = Iop_CmpLT32Fx4; return;
+         case 2: *op = Iop_CmpLE32Fx4; return;
+         case 3: *op = Iop_CmpUN32Fx4; return;
+         default: break;
+      }
+   }
+   if (sz == 4 && !all_lanes) {
+      switch (imm8) {
+         case 0: *op = Iop_CmpEQ32F0x4; return;
+         case 1: *op = Iop_CmpLT32F0x4; return;
+         case 2: *op = Iop_CmpLE32F0x4; return;
+         case 3: *op = Iop_CmpUN32F0x4; return;
+         default: break;
+      }
+   }
+   if (sz == 8 && all_lanes) {
+      switch (imm8) {
+         case 0: *op = Iop_CmpEQ64Fx2; return;
+         case 1: *op = Iop_CmpLT64Fx2; return;
+         case 2: *op = Iop_CmpLE64Fx2; return;
+         case 3: *op = Iop_CmpUN64Fx2; return;
+         default: break;
+      }
+   }
+   if (sz == 8 && !all_lanes) {
+      switch (imm8) {
+         case 0: *op = Iop_CmpEQ64F0x2; return;
+         case 1: *op = Iop_CmpLT64F0x2; return;
+         case 2: *op = Iop_CmpLE64F0x2; return;
+         case 3: *op = Iop_CmpUN64F0x2; return;
+         default: break;
+      }
+   }
+   vpanic("findSSECmpOp(amd64,guest)");
+}
+
+/* Handles SSE 32F comparisons. */
+
+static ULong dis_SSEcmp_E_to_G ( Prefix pfx, ULong delta, 
+                                 HChar* opname, Bool all_lanes, Int sz )
+{
+   HChar   dis_buf[50];
+   Int     alen, imm8;
+   IRTemp  addr;
+   Bool    needNot = False;
+   IROp    op      = Iop_INVALID;
+   IRTemp  plain   = newTemp(Ity_V128);
+   UChar   rm      = getUChar(delta);
+   UShort  mask    = 0;
+   vassert(sz == 4 || sz == 8);
+   if (epartIsReg(rm)) {
+      imm8 = getUChar(delta+1);
+      findSSECmpOp(&needNot, &op, imm8, all_lanes, sz);
+      assign( plain, binop(op, getXMMReg(gregOfRexRM(pfx,rm)), 
+                               getXMMReg(eregOfRexRM(pfx,rm))) );
+      delta += 2;
+      DIP("%s $%d,%s,%s\n", opname,
+                            (Int)imm8,
+                            nameXMMReg(eregOfRexRM(pfx,rm)),
+                            nameXMMReg(gregOfRexRM(pfx,rm)) );
+   } else {
+      addr = disAMode ( &alen, pfx, delta, dis_buf, 1 );
+      imm8 = getUChar(delta+alen);
+      findSSECmpOp(&needNot, &op, imm8, all_lanes, sz);
+      assign( plain, binop(op, getXMMReg(gregOfRexRM(pfx,rm)), 
+                               loadLE(Ity_V128, mkexpr(addr))) );
+      delta += alen+1;
+      DIP("%s $%d,%s,%s\n", opname,
+                            (Int)imm8,
+                            dis_buf,
+                            nameXMMReg(gregOfRexRM(pfx,rm)) );
+   }
+
+   if (needNot && all_lanes) {
+      putXMMReg( gregOfRM(rm), 
+                 unop(Iop_NotV128, mkexpr(plain)) );
+   }
+   else
+   if (needNot && !all_lanes) {
+      mask = sz==4 ? 0x000F : 0x00FF;
+      putXMMReg( gregOfRexRM(pfx,rm), 
+                 binop(Iop_XorV128, mkexpr(plain), mkV128(mask)) );
+   }
+   else {
+      putXMMReg( gregOfRexRM(pfx,rm), mkexpr(plain) );
+   }
+
+   return delta;
+}
+
+
 //.. /* Vector by scalar shift of G by the amount specified at the bottom
 //..    of E. */
 //.. 
@@ -7895,14 +7904,14 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "addps", Iop_Add32Fx4 );
 //..       goto decode_success;
 //..    }
-//.. 
-//..    /* F3 0F 58 = ADDSS -- add 32F0x4 from R/M to R */
-//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x58) {
-//..       vassert(sz == 4);
-//..       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "addss", Iop_Add32F0x4 );
-//..       goto decode_success;
-//..    }
-//.. 
+
+   /* F3 0F 58 = ADDSS -- add 32F0x4 from R/M to R */
+   if (haveF3no66noF2(pfx) && sz == 4
+       && insn[0] == 0x0F && insn[1] == 0x58) {
+      delta = dis_SSE_E_to_G_lo32( pfx, delta+2, "addss", Iop_Add32F0x4 );
+      goto decode_success;
+   }
+
 //..    /* 0F 55 = ANDNPS -- G = (not G) and E */
 //..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x55) {
 //..       delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "andnps", Iop_And128 );
@@ -7978,7 +7987,7 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..                                  nameXMMReg(gregOfRM(modrm)));
 //..       } else {
 //..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
-//..    assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
+//..          assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
 //..          delta += 2+alen;
 //..          DIP("cvtpi2ps %s,%s\n", dis_buf,
 //..                                  nameXMMReg(gregOfRM(modrm)) );
@@ -7994,47 +8003,67 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..                     unop(Iop_64to32, mkexpr(arg64)) )) );
 //.. 
 //..       putXMMRegLane32F(
-//..          gregOfRM(modrm), 1, 
-//..          binop(Iop_F64toF32, 
-//..                mkexpr(rmode),
-//..                unop(Iop_I32toF64,
-//..                     unop(Iop_64HIto32, mkexpr(arg64)) )) );
-//.. 
-//..       goto decode_success;
-//..    }
-//.. 
-//..    /* F3 0F 2A = CVTSI2SS -- convert I32 in mem/ireg to F32 in low
-//..       quarter xmm */
-//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x2A) {
-//..       IRTemp arg32 = newTemp(Ity_I32);
-//..       IRTemp rmode = newTemp(Ity_I32);
-//..       vassert(sz == 4);
-//.. 
-//..       modrm = getUChar(delta+3);
-//..       if (epartIsReg(modrm)) {
-//..          assign( arg32, getIReg(4, eregOfRM(modrm)) );
-//..          delta += 3+1;
-//..          DIP("cvtsi2ss %s,%s\n", nameIReg(4, eregOfRM(modrm)),
-//..                                  nameXMMReg(gregOfRM(modrm)));
-//..       } else {
-//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
-//..    assign( arg32, loadLE(Ity_I32, mkexpr(addr)) );
-//..          delta += 3+alen;
-//..          DIP("cvtsi2ss %s,%s\n", dis_buf,
-//..                                  nameXMMReg(gregOfRM(modrm)) );
-//..       }
-//.. 
-//..       assign( rmode, get_sse_roundingmode() );
-//.. 
-//..       putXMMRegLane32F( 
-//..          gregOfRM(modrm), 0,
-//..          binop(Iop_F64toF32,
+//..          gregOfRM(modrm), 1, 
+//..          binop(Iop_F64toF32, 
 //..                mkexpr(rmode),
-//..                unop(Iop_I32toF64, mkexpr(arg32)) ) );
+//..                unop(Iop_I32toF64,
+//..                     unop(Iop_64HIto32, mkexpr(arg64)) )) );
 //.. 
 //..       goto decode_success;
 //..    }
-//.. 
+
+   /* F3 0F 2A = CVTSI2SS 
+      -- sz==4: convert I32 in mem/ireg to F32 in low quarter xmm
+      -- sz==8: convert I64 in mem/ireg to F32 in low quarter xmm */
+   if (haveF3no66noF2(pfx) && (sz == 4 || sz == 8)
+       && insn[0] == 0x0F && insn[1] == 0x2A) {
+
+      IRTemp rmode = newTemp(Ity_I32);
+      assign( rmode, get_sse_roundingmode() );
+      modrm = getUChar(delta+2);
+
+      if (sz == 4) {
+         IRTemp arg32 = newTemp(Ity_I32);
+         if (epartIsReg(modrm)) {
+            goto decode_failure; /* awaiting test case */
+            assign( arg32, getIRegB(pfx, 4, eregOfRM(modrm)) );
+            delta += 2+1;
+            DIP("cvtsi2ss %s,%s\n", nameIRegB(pfx, 4, eregOfRM(modrm)),
+                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
+         } else {
+            goto decode_failure; /* awaiting test case */
+            addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
+            assign( arg32, loadLE(Ity_I32, mkexpr(addr)) );
+            delta += 2+alen;
+            DIP("cvtsi2ss %s,%s\n", dis_buf,
+                                    nameXMMReg(gregOfRexRM(pfx,modrm)) );
+         }
+         putXMMRegLane32F( 
+            gregOfRexRM(pfx,modrm), 0,
+            binop(Iop_F64toF32,
+                  mkexpr(rmode),
+                  unop(Iop_I32toF64, mkexpr(arg32)) ) );
+      } else {
+         /* sz == 8 */
+         IRTemp arg64 = newTemp(Ity_I64);
+         if (epartIsReg(modrm)) {
+            assign( arg64, getIRegB(pfx, 8, eregOfRM(modrm)) );
+            delta += 2+1;
+            DIP("cvtsi2ssq %s,%s\n", nameIRegB(pfx, 8, eregOfRM(modrm)),
+                                     nameXMMReg(gregOfRexRM(pfx,modrm)));
+         } else {
+            goto decode_failure; /* awaiting test case */
+         }
+         putXMMRegLane32F( 
+            gregOfRexRM(pfx,modrm), 0,
+            binop(Iop_F64toF32,
+                  mkexpr(rmode),
+                  binop(Iop_I64toF64, mkexpr(rmode), mkexpr(arg64)) ) );
+      }
+
+      goto decode_success;
+   }
+
 //..    /* 0F 2D = CVTPS2PI -- convert 2 x F32 in mem/low half xmm to 2 x
 //..       I32 in mmx, according to prevailing SSE rounding mode */
 //..    /* 0F 2C = CVTTPS2PI -- convert 2 x F32 in mem/low half xmm to 2 x
@@ -8217,30 +8246,32 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "minss", Iop_Min32F0x4 );
 //..       goto decode_success;
 //..    }
-//.. 
-//..    /* 0F 28 = MOVAPS -- move from E (mem or xmm) to G (xmm). */
-//..    /* 0F 10 = MOVUPS -- move from E (mem or xmm) to G (xmm). */
-//..    if (sz == 4 && insn[0] == 0x0F && (insn[1] == 0x28 || insn[1] == 0x10)) {
-//..       modrm = getUChar(delta+2);
-//..       if (epartIsReg(modrm)) {
-//..          putXMMReg( gregOfRM(modrm), 
-//..                     getXMMReg( eregOfRM(modrm) ));
-//..          DIP("mov[ua]ps %s,%s\n", nameXMMReg(eregOfRM(modrm)),
-//..                                   nameXMMReg(gregOfRM(modrm)));
-//..          delta += 2+1;
-//..       } else {
-//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
-//..          putXMMReg( gregOfRM(modrm), 
-//..                     loadLE(Ity_V128, mkexpr(addr)) );
-//..          DIP("mov[ua]ps %s,%s\n", dis_buf,
-//..                                   nameXMMReg(gregOfRM(modrm)));
-//..          delta += 2+alen;
-//..       }
-//..       goto decode_success;
-//..    }
+
+   /* 0F 28 = MOVAPS -- move from E (mem or xmm) to G (xmm). */
+   /* 0F 10 = MOVUPS -- move from E (mem or xmm) to G (xmm). */
+   if (haveNo66noF2noF3(pfx) && sz == 4
+       && insn[0] == 0x0F && (insn[1] == 0x28 || insn[1] == 0x10)) {
+      modrm = getUChar(delta+2);
+      if (epartIsReg(modrm)) {
+         putXMMReg( gregOfRexRM(pfx,modrm), 
+                    getXMMReg( eregOfRexRM(pfx,modrm) ));
+         DIP("mov[ua]ps %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
+                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
+         delta += 2+1;
+      } else {
+         addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
+         putXMMReg( gregOfRexRM(pfx,modrm), 
+                    loadLE(Ity_V128, mkexpr(addr)) );
+         DIP("mov[ua]ps %s,%s\n", dis_buf,
+                                  nameXMMReg(gregOfRexRM(pfx,modrm)));
+         delta += 2+alen;
+      }
+      goto decode_success;
+   }
 
    /* 0F 29 = MOVAPS -- move from G (xmm) to E (mem or xmm). */
-   if (haveNo66noF2noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x29) {
+   if (haveNo66noF2noF3(pfx) && sz == 4
+       && insn[0] == 0x0F && insn[1] == 0x29) {
       modrm = getUChar(delta+2);
       if (epartIsReg(modrm)) {
          /* fall through; awaiting test case */
@@ -8399,61 +8430,61 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..       }
 //..       /* else fall through */
 //..    }
-//.. 
-//..    /* F3 0F 10 = MOVSS -- move 32 bits from E (mem or lo 1/4 xmm) to G
-//..       (lo 1/4 xmm).  If E is mem, upper 3/4 of G is zeroed out. */
-//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x10) {
-//..       vassert(sz == 4);
-//..       modrm = getUChar(delta+3);
-//..       if (epartIsReg(modrm)) {
-//..          putXMMRegLane32( gregOfRM(modrm), 0,
-//..                           getXMMRegLane32( eregOfRM(modrm), 0 ));
-//..          DIP("movss %s,%s\n", nameXMMReg(eregOfRM(modrm)),
-//..                               nameXMMReg(gregOfRM(modrm)));
-//..          delta += 3+1;
-//..       } else {
-//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
-//..          putXMMReg( gregOfRM(modrm), mkV128(0) );
-//..          putXMMRegLane32( gregOfRM(modrm), 0,
-//..                           loadLE(Ity_I32, mkexpr(addr)) );
-//..          DIP("movss %s,%s\n", dis_buf,
-//..                               nameXMMReg(gregOfRM(modrm)));
-//..          delta += 3+alen;
-//..       }
-//..       goto decode_success;
-//..    }
-//.. 
-//..    /* F3 0F 11 = MOVSS -- move 32 bits from G (lo 1/4 xmm) to E (mem
-//..       or lo 1/4 xmm). */
-//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x11) {
-//..       vassert(sz == 4);
-//..       modrm = getUChar(delta+3);
-//..       if (epartIsReg(modrm)) {
-//..          /* fall through, we don't yet have a test case */
-//..       } else {
-//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
-//..          storeLE( mkexpr(addr),
-//..                   getXMMRegLane32(gregOfRM(modrm), 0) );
-//..          DIP("movss %s,%s\n", nameXMMReg(gregOfRM(modrm)),
-//..                               dis_buf);
-//..          delta += 3+alen;
-//..          goto decode_success;
-//..       }
-//..    }
-//.. 
+
+   /* F3 0F 10 = MOVSS -- move 32 bits from E (mem or lo 1/4 xmm) to G
+      (lo 1/4 xmm).  If E is mem, upper 3/4 of G is zeroed out. */
+   if (haveF3no66noF2(pfx) && sz == 4
+       && insn[0] == 0x0F && insn[1] == 0x10) {
+      modrm = getUChar(delta+2);
+      if (epartIsReg(modrm)) {
+         putXMMRegLane32( gregOfRexRM(pfx,modrm), 0,
+                          getXMMRegLane32( eregOfRexRM(pfx,modrm), 0 ));
+         DIP("movss %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
+                              nameXMMReg(gregOfRexRM(pfx,modrm)));
+         delta += 2+1;
+      } else {
+         addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
+         putXMMReg( gregOfRexRM(pfx,modrm), mkV128(0) );
+         putXMMRegLane32( gregOfRexRM(pfx,modrm), 0,
+                          loadLE(Ity_I32, mkexpr(addr)) );
+         DIP("movss %s,%s\n", dis_buf,
+                              nameXMMReg(gregOfRexRM(pfx,modrm)));
+         delta += 2+alen;
+      }
+      goto decode_success;
+   }
+
+   /* F3 0F 11 = MOVSS -- move 32 bits from G (lo 1/4 xmm) to E (mem
+      or lo 1/4 xmm). */
+   if (haveF3no66noF2(pfx) && sz == 4
+       && insn[0] == 0x0F && insn[1] == 0x11) {
+      modrm = getUChar(delta+2);
+      if (epartIsReg(modrm)) {
+         /* fall through, we don't yet have a test case */
+      } else {
+         addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
+         storeLE( mkexpr(addr),
+                  getXMMRegLane32(gregOfRexRM(pfx,modrm), 0) );
+         DIP("movss %s,%s\n", nameXMMReg(gregOfRexRM(pfx,modrm)),
+                              dis_buf);
+         delta += 2+alen;
+         goto decode_success;
+      }
+   }
+
 //..    /* 0F 59 = MULPS -- mul 32Fx4 from R/M to R */
 //..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x59) {
 //..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "mulps", Iop_Mul32Fx4 );
 //..       goto decode_success;
 //..    }
-//.. 
-//..    /* F3 0F 59 = MULSS -- mul 32F0x4 from R/M to R */
-//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x59) {
-//..       vassert(sz == 4);
-//..       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "mulss", Iop_Mul32F0x4 );
-//..       goto decode_success;
-//..    }
-//.. 
+
+   /* F3 0F 59 = MULSS -- mul 32F0x4 from R/M to R */
+   if (haveF3no66noF2(pfx) && sz == 4
+       && insn[0] == 0x0F && insn[1] == 0x59) {
+      delta = dis_SSE_E_to_G_lo32( pfx, delta+2, "mulss", Iop_Mul32F0x4 );
+      goto decode_success;
+   }
+
 //..    /* 0F 56 = ORPS -- G = G and E */
 //..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x56) {
 //..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "orps", Iop_Or128 );
@@ -8674,7 +8705,7 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..       } else {
 //..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
 //..          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
-//..    order = (Int)insn[2+alen];
+//..          order = (Int)insn[2+alen];
 //..          delta += 3+alen;
 //..          DIP("pshufw $%d,%s,%s\n", order, 
 //..                                    dis_buf,
@@ -8828,14 +8859,14 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "subps", Iop_Sub32Fx4 );
 //..       goto decode_success;
 //..    }
-//.. 
-//..    /* F3 0F 5C = SUBSS -- sub 32F0x4 from R/M to R */
-//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5C) {
-//..       vassert(sz == 4);
-//..       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "subss", Iop_Sub32F0x4 );
-//..       goto decode_success;
-//..    }
-//.. 
+
+   /* F3 0F 5C = SUBSS -- sub 32F0x4 from R/M to R */
+   if (haveF3no66noF2(pfx) && sz == 4
+       && insn[0] == 0x0F && insn[1] == 0x5C) {
+      delta = dis_SSE_E_to_G_lo32( pfx, delta+2, "subss", Iop_Sub32F0x4 );
+      goto decode_success;
+   }
+
 //..    /* 0F 15 = UNPCKHPS -- unpack and interleave high part F32s */
 //..    /* 0F 14 = UNPCKLPS -- unpack and interleave low part F32s */
 //..    /* These just appear to be special cases of SHUFPS */
@@ -8875,13 +8906,14 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //.. 
 //..       goto decode_success;
 //..    }
-//.. 
-//..    /* 0F 57 = XORPS -- G = G and E */
-//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x57) {
-//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "xorps", Iop_Xor128 );
-//..       goto decode_success;
-//..    }
-//.. 
+
+   /* 0F 57 = XORPS -- G = G and E */
+   if (haveNo66noF2noF3(pfx) && sz == 4 
+       && insn[0] == 0x0F && insn[1] == 0x57) {
+      delta = dis_SSE_E_to_G_all( pfx, delta+2, "xorps", Iop_XorV128 );
+      goto decode_success;
+   }
+
 //..    /* ---------------------------------------------------- */
 //..    /* --- end of the SSE decoder.                      --- */
 //..    /* ---------------------------------------------------- */
@@ -8910,11 +8942,12 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
       goto decode_success;
    }
 
-//..    /* 66 0F 55 = ANDNPD -- G = (not G) and E */
-//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x55) {
-//..       delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "andnpd", Iop_And128 );
-//..       goto decode_success;
-//..    }
+   /* 66 0F 55 = ANDNPD -- G = (not G) and E */
+   if (have66noF2noF3(pfx) && sz == 2 
+       && insn[0] == 0x0F && insn[1] == 0x55) {
+      delta = dis_SSE_E_to_G_all_invG( pfx, delta+2, "andnpd", Iop_AndV128 );
+      goto decode_success;
+   }
 
    /* 66 0F 54 = ANDPD -- G = G and E */
    if (have66noF2noF3(pfx) && sz == 2 
@@ -8928,13 +8961,13 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..       delta = dis_SSEcmp_E_to_G( sorb, delta+2, "cmppd", True, 8 );
 //..       goto decode_success;
 //..    }
-//.. 
-//..    /* F2 0F C2 = CMPSD -- 64F0x2 comparison from R/M to R */
-//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xC2) {
-//..       vassert(sz == 4);
-//..       delta = dis_SSEcmp_E_to_G( sorb, delta+3, "cmpsd", False, 8 );
-//..       goto decode_success;
-//..    }
+
+   /* F2 0F C2 = CMPSD -- 64F0x2 comparison from R/M to R */
+   if (haveF2no66noF3(pfx) && sz == 4
+       && insn[0] == 0x0F && insn[1] == 0xC2) {
+      delta = dis_SSEcmp_E_to_G( pfx, delta+2, "cmpsd", False, 8 );
+      goto decode_success;
+   }
 
    /* 66 0F 2F = COMISD  -- 64F0x2 comparison G,E, and set ZCP */
    /* 66 0F 2E = UCOMISD -- 64F0x2 comparison G,E, and set ZCP */
@@ -8988,7 +9021,7 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..                                  nameXMMReg(gregOfRM(modrm)));
 //..       } else {
 //..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
-//..    assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
+//..          assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
 //..          delta += 3+alen;
 //..          DIP("cvtdq2pd %s,%s\n", dis_buf,
 //..                                  nameXMMReg(gregOfRM(modrm)) );
@@ -9338,42 +9371,43 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
       goto decode_success;
    }
 
-//..    /* F2 0F 5A = CVTSD2SS -- convert F64 in mem/low half xmm to F32 in
-//..       low 1/4 xmm(G), according to prevailing SSE rounding mode */
-//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5A) {
-//..       IRTemp rmode = newTemp(Ity_I32);
-//..       IRTemp f64lo = newTemp(Ity_F64);
-//..       vassert(sz == 4);
-//.. 
-//..       modrm = getUChar(delta+3);
-//..       if (epartIsReg(modrm)) {
-//..          delta += 3+1;
-//..          assign(f64lo, getXMMRegLane64F(eregOfRM(modrm), 0));
-//..          DIP("cvtsd2ss %s,%s\n", nameXMMReg(eregOfRM(modrm)),
-//..                                  nameXMMReg(gregOfRM(modrm)));
-//..       } else {
-//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
-//..          assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
-//..          delta += 3+alen;
-//..          DIP("cvtsd2ss %s,%s\n", dis_buf,
-//..                                  nameXMMReg(gregOfRM(modrm)));
-//..       }
-//.. 
-//..       assign( rmode, get_sse_roundingmode() );
-//..       putXMMRegLane32F( 
-//..          gregOfRM(modrm), 0, 
-//..          binop( Iop_F64toF32, mkexpr(rmode), mkexpr(f64lo) )
-//..       );
-//.. 
-//..       goto decode_success;
-//..    }
+   /* F2 0F 5A = CVTSD2SS -- convert F64 in mem/low half xmm to F32 in
+      low 1/4 xmm(G), according to prevailing SSE rounding mode */
+   if (haveF2no66noF3(pfx) && sz == 4
+       && insn[0] == 0x0F && insn[1] == 0x5A) {
+      IRTemp rmode = newTemp(Ity_I32);
+      IRTemp f64lo = newTemp(Ity_F64);
+      vassert(sz == 4);
+
+      modrm = getUChar(delta+2);
+      if (epartIsReg(modrm)) {
+         delta += 2+1;
+         assign(f64lo, getXMMRegLane64F(eregOfRexRM(pfx,modrm), 0));
+         DIP("cvtsd2ss %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
+                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
+      } else {
+         addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
+         assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
+         delta += 2+alen;
+         DIP("cvtsd2ss %s,%s\n", dis_buf,
+                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
+      }
+
+      assign( rmode, get_sse_roundingmode() );
+      putXMMRegLane32F( 
+         gregOfRexRM(pfx,modrm), 0, 
+         binop( Iop_F64toF32, mkexpr(rmode), mkexpr(f64lo) )
+      );
+
+      goto decode_success;
+   }
 
    /* F2 0F 2A = CVTSI2SD 
       when sz==4 -- convert I32 in mem/ireg to F64 in low half xmm
       when sz==8 -- convert I64 in mem/ireg to F64 in low half xmm
    */
-   if (haveF2no66noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x2A) {
-      vassert(sz == 4 || sz == 8);
+   if (haveF2no66noF3(pfx) && (sz == 4 || sz == 8)
+       && insn[0] == 0x0F && insn[1] == 0x2A) {
       modrm = getUChar(delta+2);
 
       if (sz == 4) {
@@ -9399,14 +9433,14 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
          if (epartIsReg(modrm)) {
             assign( arg64, getIRegB(pfx, 8, eregOfRM(modrm)) );
             delta += 2+1;
-            DIP("cvtsi2sd %s,%s\n", nameIRegB(pfx, 8, eregOfRM(modrm)),
-                                    nameXMMReg(gregOfRexRM(pfx,modrm)));
+            DIP("cvtsi2sdq %s,%s\n", nameIRegB(pfx, 8, eregOfRM(modrm)),
+                                     nameXMMReg(gregOfRexRM(pfx,modrm)));
          } else {
             addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
             assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
             delta += 2+alen;
-            DIP("cvtsi2sd %s,%s\n", dis_buf,
-                                    nameXMMReg(gregOfRexRM(pfx,modrm)) );
+            DIP("cvtsi2sdq %s,%s\n", dis_buf,
+                                     nameXMMReg(gregOfRexRM(pfx,modrm)) );
          }
          putXMMRegLane64F( 
             gregOfRexRM(pfx,modrm), 
@@ -9585,32 +9619,33 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "minsd", Iop_Min64F0x2 );
 //..       goto decode_success;
 //..    }
-//.. 
-//..    /* 66 0F 28 = MOVAPD -- move from E (mem or xmm) to G (xmm). */
-//..    /* 66 0F 10 = MOVUPD -- move from E (mem or xmm) to G (xmm). */
-//..    /* 66 0F 6F = MOVDQA -- move from E (mem or xmm) to G (xmm). */
-//..    if (sz == 2 && insn[0] == 0x0F 
-//..        && (insn[1] == 0x28 || insn[1] == 0x10 || insn[1] == 0x6F)) {
-//..       HChar* wot = insn[1]==0x28 ? "apd" :
-//..                    insn[1]==0x10 ? "upd" : "dqa";
-//..       modrm = getUChar(delta+2);
-//..       if (epartIsReg(modrm)) {
-//..          putXMMReg( gregOfRM(modrm), 
-//..                     getXMMReg( eregOfRM(modrm) ));
-//..          DIP("mov%s %s,%s\n", wot, nameXMMReg(eregOfRM(modrm)),
-//..                                    nameXMMReg(gregOfRM(modrm)));
-//..          delta += 2+1;
-//..       } else {
-//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
-//..          putXMMReg( gregOfRM(modrm), 
-//..                     loadLE(Ity_V128, mkexpr(addr)) );
-//..          DIP("mov%s %s,%s\n", wot, dis_buf,
-//..                                    nameXMMReg(gregOfRM(modrm)));
-//..          delta += 2+alen;
-//..       }
-//..       goto decode_success;
-//..    }
-//.. 
+
+   /* 66 0F 28 = MOVAPD -- move from E (mem or xmm) to G (xmm). */
+   /* 66 0F 10 = MOVUPD -- move from E (mem or xmm) to G (xmm). */
+   /* 66 0F 6F = MOVDQA -- move from E (mem or xmm) to G (xmm). */
+   if (have66noF2noF3(pfx) && sz == 2 
+       && insn[0] == 0x0F 
+       && (insn[1] == 0x28 || insn[1] == 0x10 || insn[1] == 0x6F)) {
+      HChar* wot = insn[1]==0x28 ? "apd" :
+                   insn[1]==0x10 ? "upd" : "dqa";
+      modrm = getUChar(delta+2);
+      if (epartIsReg(modrm)) {
+         putXMMReg( gregOfRexRM(pfx,modrm), 
+                    getXMMReg( eregOfRexRM(pfx,modrm) ));
+         DIP("mov%s %s,%s\n", wot, nameXMMReg(eregOfRexRM(pfx,modrm)),
+                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
+         delta += 2+1;
+      } else {
+         addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
+         putXMMReg( gregOfRexRM(pfx,modrm), 
+                    loadLE(Ity_V128, mkexpr(addr)) );
+         DIP("mov%s %s,%s\n", wot, dis_buf,
+                                   nameXMMReg(gregOfRexRM(pfx,modrm)));
+         delta += 2+alen;
+      }
+      goto decode_success;
+   }
+
 //..    /* 66 0F 29 = MOVAPD -- move from G (xmm) to E (mem or xmm). */
 //..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x29) {
 //..       modrm = getUChar(delta+2);
@@ -9936,8 +9971,8 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 
    /* F2 0F 11 = MOVSD -- move 64 bits from G (lo half xmm) to E (mem
       or lo half xmm). */
-   if (haveF2no66noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x11) {
-      vassert(sz == 4);
+   if (haveF2no66noF3(pfx) && sz == 4
+       && insn[0] == 0x0F && insn[1] == 0x11) {
       modrm = getUChar(delta+2);
       if (epartIsReg(modrm)) {
          /* fall through, we don't yet have a test case */
@@ -9959,18 +9994,19 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..    }
 
    /* F2 0F 59 = MULSD -- mul 64F0x2 from R/M to R */
-   if (haveF2no66noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x59) {
-      vassert(sz == 4);
+   if (haveF2no66noF3(pfx) && sz == 4
+       && insn[0] == 0x0F && insn[1] == 0x59) {
       delta = dis_SSE_E_to_G_lo64( pfx, delta+2, "mulsd", Iop_Mul64F0x2 );
       goto decode_success;
    }
 
-//..    /* 66 0F 56 = ORPD -- G = G and E */
-//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x56) {
-//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "orpd", Iop_Or128 );
-//..       goto decode_success;
-//..    }
-//.. 
+   /* 66 0F 56 = ORPD -- G = G and E */
+   if (have66noF2noF3(pfx) && sz == 2 
+       && insn[0] == 0x0F && insn[1] == 0x56) {
+      delta = dis_SSE_E_to_G_all( pfx, delta+2, "orpd", Iop_OrV128 );
+      goto decode_success;
+   }
+
 //..    /* 66 0F C6 /r ib = SHUFPD -- shuffle packed F64s */
 //..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xC6) {
 //..       Int    select;
@@ -11173,8 +11209,8 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
                      : "cqo\n"));
       break;
 
-//..    /* ------------------------ FPU ops -------------------- */
-//.. 
+   /* ------------------------ FPU ops -------------------- */
+
 //..    case 0x9E: /* SAHF */
 //..       codegen_SAHF();
 //..       DIP("sahf\n");
@@ -11189,25 +11225,28 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..       /* ignore? */
 //..       DIP("fwait\n");
 //..       break;
-//.. 
-//..    case 0xD8:
-//..    case 0xD9:
-//..    case 0xDA:
-//..    case 0xDB:
-//..    case 0xDC:
-//..    case 0xDD:
-//..    case 0xDE:
-//..    case 0xDF: {
-//..       ULong delta0    = delta;
-//..       Bool decode_OK = False;
-//..       delta = dis_FPU ( &decode_OK, sorb, delta );
-//..       if (!decode_OK) {
-//..          delta = delta0;
-//..          goto decode_failure;
-//..       }
-//..       break;
-//..    }
-//.. 
+
+   case 0xD8:
+   case 0xD9:
+   case 0xDA:
+   case 0xDB:
+   case 0xDC:
+   case 0xDD:
+   case 0xDE:
+   case 0xDF:
+      if (sz == 4 && haveNo66noF2noF3(pfx)) {
+         ULong delta0    = delta;
+         Bool  decode_OK = False;
+         delta = dis_FPU ( &decode_OK, pfx, delta );
+         if (!decode_OK) {
+            delta = delta0;
+            goto decode_failure;
+         }
+         break;
+      } else {
+         goto decode_failure;
+      }
+
 //..    /* ------------------------ INC & DEC ------------------ */
 //.. 
 //..    case 0x40: /* INC eAX */
@@ -12295,11 +12334,8 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 
    case 0x90: /* XCHG eAX,eAX */
       if (haveF2orF3(pfx)) goto decode_failure;
-      if (sz == 2 || sz == 4 || sz == 8) {
-         DIP("nop\n");
-         break;
-      }
-      /* else fall through */
+      DIP("nop\n");
+      break;
    case 0x91: /* XCHG rAX,rCX */
    case 0x92: /* XCHG rAX,rDX */
    case 0x93: /* XCHG rAX,rBX */
index 79a3c0c06b803e9f60ddb0ff6e5a7df24b8c1316..d3e8c46639bfd9b61a129a171fd7e5e056fd66bd 100644 (file)
@@ -574,10 +574,10 @@ HChar* showAMD64SseOp ( AMD64SseOp op ) {
       case Asse_DIVF:     return "div";
       case Asse_MAXF:     return "max";
       case Asse_MINF:     return "min";
-//..       case Xsse_CMPEQF:   return "cmpFeq";
-//..       case Xsse_CMPLTF:   return "cmpFlt";
-//..       case Xsse_CMPLEF:   return "cmpFle";
-//..       case Xsse_CMPUNF:   return "cmpFun";
+      case Asse_CMPEQF:   return "cmpFeq";
+      case Asse_CMPLTF:   return "cmpFlt";
+      case Asse_CMPLEF:   return "cmpFle";
+      case Asse_CMPUNF:   return "cmpFun";
 //..       case Xsse_RCPF:     return "rcp";
 //..       case Xsse_RSQRTF:   return "rsqrt";
       case Asse_SQRTF:    return "sqrt";
@@ -891,6 +891,16 @@ AMD64Instr* AMD64Instr_SseSF2SI ( Int szS, Int szD, HReg src, HReg dst ) {
    vassert(szD == 4 || szD == 8);
    return i;
 }
+AMD64Instr* AMD64Instr_SseSDSS   ( Bool from64, HReg src, HReg dst )
+{
+   AMD64Instr* i         = LibVEX_Alloc(sizeof(AMD64Instr));
+   i->tag                = Ain_SseSDSS;
+   i->Ain.SseSDSS.from64 = from64;
+   i->Ain.SseSDSS.src    = src;
+   i->Ain.SseSDSS.dst    = dst;
+   return i;
+}
+
 //.. AMD64Instr* AMD64Instr_SseConst ( UShort con, HReg dst ) {
 //..    AMD64Instr* i            = LibVEX_Alloc(sizeof(AMD64Instr));
 //..    i->tag                 = Xin_SseConst;
@@ -920,24 +930,24 @@ AMD64Instr* AMD64Instr_SseLdzLO  ( Int sz, HReg reg, AMD64AMode* addr )
    vassert(sz == 4 || sz == 8);
    return i;
 }
-//.. AMD64Instr* AMD64Instr_Sse32Fx4 ( AMD64SseOp op, HReg src, HReg dst ) {
-//..    AMD64Instr* i         = LibVEX_Alloc(sizeof(AMD64Instr));
-//..    i->tag              = Xin_Sse32Fx4;
-//..    i->Xin.Sse32Fx4.op  = op;
-//..    i->Xin.Sse32Fx4.src = src;
-//..    i->Xin.Sse32Fx4.dst = dst;
-//..    vassert(op != Xsse_MOV);
-//..    return i;
-//.. }
-//.. AMD64Instr* AMD64Instr_Sse32FLo ( AMD64SseOp op, HReg src, HReg dst ) {
-//..    AMD64Instr* i         = LibVEX_Alloc(sizeof(AMD64Instr));
-//..    i->tag              = Xin_Sse32FLo;
-//..    i->Xin.Sse32FLo.op  = op;
-//..    i->Xin.Sse32FLo.src = src;
-//..    i->Xin.Sse32FLo.dst = dst;
-//..    vassert(op != Xsse_MOV);
-//..    return i;
-//.. }
+AMD64Instr* AMD64Instr_Sse32Fx4 ( AMD64SseOp op, HReg src, HReg dst ) {
+   AMD64Instr* i       = LibVEX_Alloc(sizeof(AMD64Instr));
+   i->tag              = Ain_Sse32Fx4;
+   i->Ain.Sse32Fx4.op  = op;
+   i->Ain.Sse32Fx4.src = src;
+   i->Ain.Sse32Fx4.dst = dst;
+   vassert(op != Asse_MOV);
+   return i;
+}
+AMD64Instr* AMD64Instr_Sse32FLo ( AMD64SseOp op, HReg src, HReg dst ) {
+   AMD64Instr* i       = LibVEX_Alloc(sizeof(AMD64Instr));
+   i->tag              = Ain_Sse32FLo;
+   i->Ain.Sse32FLo.op  = op;
+   i->Ain.Sse32FLo.src = src;
+   i->Ain.Sse32FLo.dst = dst;
+   vassert(op != Asse_MOV);
+   return i;
+}
 //.. AMD64Instr* AMD64Instr_Sse64Fx2 ( AMD64SseOp op, HReg src, HReg dst ) {
 //..    AMD64Instr* i         = LibVEX_Alloc(sizeof(AMD64Instr));
 //..    i->tag              = Xin_Sse64Fx2;
@@ -964,15 +974,15 @@ AMD64Instr* AMD64Instr_SseReRg ( AMD64SseOp op, HReg re, HReg rg ) {
    i->Ain.SseReRg.dst = rg;
    return i;
 }
-//.. AMD64Instr* AMD64Instr_SseCMov ( AMD64CondCode cond, HReg src, HReg dst ) {
-//..    AMD64Instr* i         = LibVEX_Alloc(sizeof(AMD64Instr));
-//..    i->tag              = Xin_SseCMov;
-//..    i->Xin.SseCMov.cond = cond;
-//..    i->Xin.SseCMov.src  = src;
-//..    i->Xin.SseCMov.dst  = dst;
-//..    vassert(cond != Xcc_ALWAYS);
-//..    return i;
-//.. }
+AMD64Instr* AMD64Instr_SseCMov ( AMD64CondCode cond, HReg src, HReg dst ) {
+   AMD64Instr* i       = LibVEX_Alloc(sizeof(AMD64Instr));
+   i->tag              = Ain_SseCMov;
+   i->Ain.SseCMov.cond = cond;
+   i->Ain.SseCMov.src  = src;
+   i->Ain.SseCMov.dst  = dst;
+   vassert(cond != Acc_ALWAYS);
+   return i;
+}
 //.. AMD64Instr* AMD64Instr_SseShuf ( Int order, HReg src, HReg dst ) {
 //..    AMD64Instr* i          = LibVEX_Alloc(sizeof(AMD64Instr));
 //..    i->tag               = Xin_SseShuf;
@@ -1206,6 +1216,12 @@ void ppAMD64Instr ( AMD64Instr* i )
          (i->Ain.SseSF2SI.szD==4 ? ppHRegAMD64_lo32 : ppHRegAMD64)
             (i->Ain.SseSF2SI.dst);
          break;
+      case Ain_SseSDSS:
+         vex_printf(i->Ain.SseSDSS.from64 ? "cvtsd2ss " : "cvtss2sd ");
+         ppHRegAMD64(i->Ain.SseSDSS.src);
+         vex_printf(",");
+         ppHRegAMD64(i->Ain.SseSDSS.dst);
+         break;
 //..       case Xin_SseConst:
 //..          vex_printf("const $0x%04x,", (Int)i->Xin.SseConst.con);
 //..          ppHRegAMD64(i->Xin.SseConst.dst);
@@ -1233,18 +1249,18 @@ void ppAMD64Instr ( AMD64Instr* i )
          vex_printf(",");
          ppHRegAMD64(i->Ain.SseLdzLO.reg);
          return;
-//..       case Xin_Sse32Fx4:
-//..          vex_printf("%sps ", showAMD64SseOp(i->Xin.Sse32Fx4.op));
-//..          ppHRegAMD64(i->Xin.Sse32Fx4.src);
-//..          vex_printf(",");
-//..          ppHRegAMD64(i->Xin.Sse32Fx4.dst);
-//..          return;
-//..       case Xin_Sse32FLo:
-//..          vex_printf("%sss ", showAMD64SseOp(i->Xin.Sse32FLo.op));
-//..          ppHRegAMD64(i->Xin.Sse32FLo.src);
-//..          vex_printf(",");
-//..          ppHRegAMD64(i->Xin.Sse32FLo.dst);
-//..          return;
+      case Ain_Sse32Fx4:
+         vex_printf("%sps ", showAMD64SseOp(i->Ain.Sse32Fx4.op));
+         ppHRegAMD64(i->Ain.Sse32Fx4.src);
+         vex_printf(",");
+         ppHRegAMD64(i->Ain.Sse32Fx4.dst);
+         return;
+      case Ain_Sse32FLo:
+         vex_printf("%sss ", showAMD64SseOp(i->Ain.Sse32FLo.op));
+         ppHRegAMD64(i->Ain.Sse32FLo.src);
+         vex_printf(",");
+         ppHRegAMD64(i->Ain.Sse32FLo.dst);
+         return;
 //..       case Xin_Sse64Fx2:
 //..          vex_printf("%spd ", showAMD64SseOp(i->Xin.Sse64Fx2.op));
 //..          ppHRegAMD64(i->Xin.Sse64Fx2.src);
@@ -1263,12 +1279,12 @@ void ppAMD64Instr ( AMD64Instr* i )
          vex_printf(",");
          ppHRegAMD64(i->Ain.SseReRg.dst);
          return;
-//..       case Xin_SseCMov:
-//..          vex_printf("cmov%s ", showAMD64CondCode(i->Xin.SseCMov.cond));
-//..          ppHRegAMD64(i->Xin.SseCMov.src);
-//..          vex_printf(",");
-//..          ppHRegAMD64(i->Xin.SseCMov.dst);
-//..          return;
+      case Ain_SseCMov:
+         vex_printf("cmov%s ", showAMD64CondCode(i->Ain.SseCMov.cond));
+         ppHRegAMD64(i->Ain.SseCMov.src);
+         vex_printf(",");
+         ppHRegAMD64(i->Ain.SseCMov.dst);
+         return;
 //..       case Xin_SseShuf:
 //..          vex_printf("pshufd $0x%x,", i->Xin.SseShuf.order);
 //..          ppHRegAMD64(i->Xin.SseShuf.src);
@@ -1469,6 +1485,10 @@ void getRegUsage_AMD64Instr ( HRegUsage* u, AMD64Instr* i )
          addHRegUse(u, HRmRead,  i->Ain.SseSF2SI.src);
          addHRegUse(u, HRmWrite, i->Ain.SseSF2SI.dst);
          return;
+      case Ain_SseSDSS:
+         addHRegUse(u, HRmRead,  i->Ain.SseSDSS.src);
+         addHRegUse(u, HRmWrite, i->Ain.SseSDSS.dst);
+         return;
       case Ain_SseLdSt:
          addRegUsage_AMD64AMode(u, i->Ain.SseLdSt.addr);
          addHRegUse(u, i->Ain.SseLdSt.isLoad ? HRmWrite : HRmRead,
@@ -1481,24 +1501,24 @@ void getRegUsage_AMD64Instr ( HRegUsage* u, AMD64Instr* i )
 //..       case Xin_SseConst:
 //..          addHRegUse(u, HRmWrite, i->Xin.SseConst.dst);
 //..          return;
-//..       case Xin_Sse32Fx4:
-//..          vassert(i->Xin.Sse32Fx4.op != Xsse_MOV);
-//..          unary = i->Xin.Sse32Fx4.op == Xsse_RCPF
-//..                  || i->Xin.Sse32Fx4.op == Xsse_RSQRTF
-//..                  || i->Xin.Sse32Fx4.op == Xsse_SQRTF;
-//..          addHRegUse(u, HRmRead, i->Xin.Sse32Fx4.src);
-//..          addHRegUse(u, unary ? HRmWrite : HRmModify, 
-//..                        i->Xin.Sse32Fx4.dst);
-//..          return;
-//..       case Xin_Sse32FLo:
-//..          vassert(i->Xin.Sse32FLo.op != Xsse_MOV);
-//..          unary = i->Xin.Sse32FLo.op == Xsse_RCPF
-//..                  || i->Xin.Sse32FLo.op == Xsse_RSQRTF
-//..                  || i->Xin.Sse32FLo.op == Xsse_SQRTF;
-//..          addHRegUse(u, HRmRead, i->Xin.Sse32FLo.src);
-//..          addHRegUse(u, unary ? HRmWrite : HRmModify, 
-//..                        i->Xin.Sse32FLo.dst);
-//..          return;
+      case Ain_Sse32Fx4:
+         vassert(i->Ain.Sse32Fx4.op != Asse_MOV);
+         unary = i->Ain.Sse32Fx4.op == Asse_RCPF
+                 || i->Ain.Sse32Fx4.op == Asse_RSQRTF
+                 || i->Ain.Sse32Fx4.op == Asse_SQRTF;
+         addHRegUse(u, HRmRead, i->Ain.Sse32Fx4.src);
+         addHRegUse(u, unary ? HRmWrite : HRmModify, 
+                       i->Ain.Sse32Fx4.dst);
+         return;
+      case Ain_Sse32FLo:
+         vassert(i->Ain.Sse32FLo.op != Asse_MOV);
+         unary = i->Ain.Sse32FLo.op == Asse_RCPF
+                 || i->Ain.Sse32FLo.op == Asse_RSQRTF
+                 || i->Ain.Sse32FLo.op == Asse_SQRTF;
+         addHRegUse(u, HRmRead, i->Ain.Sse32FLo.src);
+         addHRegUse(u, unary ? HRmWrite : HRmModify, 
+                       i->Ain.Sse32FLo.dst);
+         return;
 //..       case Xin_Sse64Fx2:
 //..          vassert(i->Xin.Sse64Fx2.op != Xsse_MOV);
 //..          unary = i->Xin.Sse64Fx2.op == Xsse_RCPF
@@ -1530,10 +1550,10 @@ void getRegUsage_AMD64Instr ( HRegUsage* u, AMD64Instr* i )
                           i->Ain.SseReRg.dst);
          }
          return;
-//..       case Xin_SseCMov:
-//..          addHRegUse(u, HRmRead,   i->Xin.SseCMov.src);
-//..          addHRegUse(u, HRmModify, i->Xin.SseCMov.dst);
-//..          return;
+      case Ain_SseCMov:
+         addHRegUse(u, HRmRead,   i->Ain.SseCMov.src);
+         addHRegUse(u, HRmModify, i->Ain.SseCMov.dst);
+         return;
 //..       case Xin_SseShuf:
 //..          addHRegUse(u, HRmRead,  i->Xin.SseShuf.src);
 //..          addHRegUse(u, HRmWrite, i->Xin.SseShuf.dst);
@@ -1660,6 +1680,10 @@ void mapRegs_AMD64Instr ( HRegRemap* m, AMD64Instr* i )
          mapReg(m, &i->Ain.SseSF2SI.src);
          mapReg(m, &i->Ain.SseSF2SI.dst);
          return;
+      case Ain_SseSDSS:
+         mapReg(m, &i->Ain.SseSDSS.src);
+         mapReg(m, &i->Ain.SseSDSS.dst);
+         return;
 //..       case Xin_SseConst:
 //..          mapReg(m, &i->Xin.SseConst.dst);
 //..          return;
@@ -1671,14 +1695,14 @@ void mapRegs_AMD64Instr ( HRegRemap* m, AMD64Instr* i )
          mapReg(m, &i->Ain.SseLdzLO.reg);
          mapRegs_AMD64AMode(m, i->Ain.SseLdzLO.addr);
          break;
-//..       case Xin_Sse32Fx4:
-//..          mapReg(m, &i->Xin.Sse32Fx4.src);
-//..          mapReg(m, &i->Xin.Sse32Fx4.dst);
-//..          return;
-//..       case Xin_Sse32FLo:
-//..          mapReg(m, &i->Xin.Sse32FLo.src);
-//..          mapReg(m, &i->Xin.Sse32FLo.dst);
-//..          return;
+      case Ain_Sse32Fx4:
+         mapReg(m, &i->Ain.Sse32Fx4.src);
+         mapReg(m, &i->Ain.Sse32Fx4.dst);
+         return;
+      case Ain_Sse32FLo:
+         mapReg(m, &i->Ain.Sse32FLo.src);
+         mapReg(m, &i->Ain.Sse32FLo.dst);
+         return;
 //..       case Xin_Sse64Fx2:
 //..          mapReg(m, &i->Xin.Sse64Fx2.src);
 //..          mapReg(m, &i->Xin.Sse64Fx2.dst);
@@ -1691,10 +1715,10 @@ void mapRegs_AMD64Instr ( HRegRemap* m, AMD64Instr* i )
          mapReg(m, &i->Ain.SseReRg.src);
          mapReg(m, &i->Ain.SseReRg.dst);
          return;
-//..       case Xin_SseCMov:
-//..          mapReg(m, &i->Xin.SseCMov.src);
-//..          mapReg(m, &i->Xin.SseCMov.dst);
-//..          return;
+      case Ain_SseCMov:
+         mapReg(m, &i->Ain.SseCMov.src);
+         mapReg(m, &i->Ain.SseCMov.dst);
+         return;
 //..       case Xin_SseShuf:
 //..          mapReg(m, &i->Xin.SseShuf.src);
 //..          mapReg(m, &i->Xin.SseShuf.dst);
@@ -2934,6 +2958,18 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i )
                         vreg2ireg(i->Ain.SseSF2SI.src) );
       goto done;
 
+   case Ain_SseSDSS:
+      /* cvtsd2ss/cvtss2sd %src, %dst */
+      *p++ = i->Ain.SseSDSS.from64 ? 0xF2 : 0xF3;
+      *p++ = clearWBit(
+              rexAMode_R( vreg2ireg(i->Ain.SseSDSS.dst),
+                          vreg2ireg(i->Ain.SseSDSS.src) ));
+      *p++ = 0x0F;
+      *p++ = 0x5A;
+      p = doAMode_R( p, vreg2ireg(i->Ain.SseSDSS.dst),
+                        vreg2ireg(i->Ain.SseSDSS.src) );
+      goto done;
+
 //.. 
 //..    case Xin_FpCmp:
 //..       /* gcmp %fL, %fR, %dst
@@ -2978,7 +3014,6 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i )
          *p++ = 0xF2;
       } else
       if (i->Ain.SseLdSt.sz == 4) {
-         goto bad; /* awaiting test case */
          *p++ = 0xF3;
       } else
       if (i->Ain.SseLdSt.sz != 16) {
@@ -3004,30 +3039,33 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i )
                        i->Ain.SseLdzLO.addr);
       goto done;
 
-//..    case Xin_Sse32Fx4:
-//..       xtra = 0;
-//..       *p++ = 0x0F;
-//..       switch (i->Xin.Sse32Fx4.op) {
-//..          case Xsse_ADDF:   *p++ = 0x58; break;
-//..          case Xsse_DIVF:   *p++ = 0x5E; break;
-//..          case Xsse_MAXF:   *p++ = 0x5F; break;
-//..          case Xsse_MINF:   *p++ = 0x5D; break;
-//..          case Xsse_MULF:   *p++ = 0x59; break;
-//..          case Xsse_RCPF:   *p++ = 0x53; break;
-//..          case Xsse_RSQRTF: *p++ = 0x52; break;
-//..          case Xsse_SQRTF:  *p++ = 0x51; break;
-//..          case Xsse_SUBF:   *p++ = 0x5C; break;
-//..          case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
-//..          case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
-//..          case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
-//..          default: goto bad;
-//..       }
-//..       p = doAMode_R(p, fake(vregNo(i->Xin.Sse32Fx4.dst)),
-//..                        fake(vregNo(i->Xin.Sse32Fx4.src)) );
-//..       if (xtra & 0x100)
-//..          *p++ = (UChar)(xtra & 0xFF);
-//..       goto done;
-//.. 
+   case Ain_Sse32Fx4:
+      xtra = 0;
+      *p++ = clearWBit(
+             rexAMode_R( vreg2ireg(i->Ain.Sse32Fx4.dst),
+                         vreg2ireg(i->Ain.Sse32Fx4.src) ));
+      *p++ = 0x0F;
+      switch (i->Ain.Sse32Fx4.op) {
+       //case Asse_ADDF:   *p++ = 0x58; break;
+       //case Asse_DIVF:   *p++ = 0x5E; break;
+       //case Asse_MAXF:   *p++ = 0x5F; break;
+        //case Asse_MINF:   *p++ = 0x5D; break;
+       //case Asse_MULF:   *p++ = 0x59; break;
+        //case Asse_RCPF:   *p++ = 0x53; break;
+       //case Asse_RSQRTF: *p++ = 0x52; break;
+       //case Asse_SQRTF:  *p++ = 0x51; break;
+       //case Asse_SUBF:   *p++ = 0x5C; break;
+         case Asse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
+       //case Asse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
+       //case Asse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
+         default: goto bad;
+      }
+      p = doAMode_R(p, vreg2ireg(i->Ain.Sse32Fx4.dst),
+                       vreg2ireg(i->Ain.Sse32Fx4.src) );
+      if (xtra & 0x100)
+         *p++ = (UChar)(xtra & 0xFF);
+      goto done;
+
 //..    case Xin_Sse64Fx2:
 //..       xtra = 0;
 //..       *p++ = 0x66;
@@ -3052,31 +3090,34 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i )
 //..       if (xtra & 0x100)
 //..          *p++ = (UChar)(xtra & 0xFF);
 //..       goto done;
-//.. 
-//..    case Xin_Sse32FLo:
-//..       xtra = 0;
-//..       *p++ = 0xF3;
-//..       *p++ = 0x0F;
-//..       switch (i->Xin.Sse32FLo.op) {
-//..          case Xsse_ADDF:   *p++ = 0x58; break;
+
+   case Ain_Sse32FLo:
+      xtra = 0;
+      *p++ = 0xF3;
+      *p++ = clearWBit(
+             rexAMode_R( vreg2ireg(i->Ain.Sse32FLo.dst),
+                         vreg2ireg(i->Ain.Sse32FLo.src) ));
+      *p++ = 0x0F;
+      switch (i->Ain.Sse32FLo.op) {
+         case Asse_ADDF:   *p++ = 0x58; break;
 //..          case Xsse_DIVF:   *p++ = 0x5E; break;
 //..          case Xsse_MAXF:   *p++ = 0x5F; break;
 //..          case Xsse_MINF:   *p++ = 0x5D; break;
-//..          case Xsse_MULF:   *p++ = 0x59; break;
+         case Asse_MULF:   *p++ = 0x59; break;
 //..          case Xsse_RCPF:   *p++ = 0x53; break;
 //..          case Xsse_RSQRTF: *p++ = 0x52; break;
 //..          case Xsse_SQRTF:  *p++ = 0x51; break;
-//..          case Xsse_SUBF:   *p++ = 0x5C; break;
+         case Asse_SUBF:   *p++ = 0x5C; break;
 //..          case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
 //..          case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
 //..          case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
-//..          default: goto bad;
-//..       }
-//..       p = doAMode_R(p, fake(vregNo(i->Xin.Sse32FLo.dst)),
-//..                        fake(vregNo(i->Xin.Sse32FLo.src)) );
-//..       if (xtra & 0x100)
-//..          *p++ = (UChar)(xtra & 0xFF);
-//..       goto done;
+         default: goto bad;
+      }
+      p = doAMode_R(p, vreg2ireg(i->Ain.Sse32FLo.dst),
+                       vreg2ireg(i->Ain.Sse32FLo.src) );
+      if (xtra & 0x100)
+         *p++ = (UChar)(xtra & 0xFF);
+      goto done;
 
    case Ain_Sse64FLo:
       xtra = 0;
@@ -3096,7 +3137,7 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i )
          case Asse_SQRTF:  *p++ = 0x51; break;
          case Asse_SUBF:   *p++ = 0x5C; break;
 //..          case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
-//..          case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
+         case Asse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
 //..          case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
          default: goto bad;
       }
@@ -3115,7 +3156,7 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i )
 
       switch (i->Ain.SseReRg.op) {
          case Asse_MOV:     /*movups*/ XX(rex); XX(0x0F); XX(0x10); break;
-//..          case Xsse_OR:                 XX(rex); XX(0x0F); XX(0x56); break;
+         case Asse_OR:                 XX(rex); XX(0x0F); XX(0x56); break;
          case Asse_XOR:                XX(rex); XX(0x0F); XX(0x57); break;
          case Asse_AND:                XX(rex); XX(0x0F); XX(0x54); break;
 //..          case Xsse_PACKSSD:  XX(0x66); XX(rex); XX(0x0F); XX(0x6B); break;
@@ -3175,22 +3216,25 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i )
 #     undef XX
       goto done;
 
-//..    case Xin_SseCMov:
-//..       /* jmp fwds if !condition */
-//..       *p++ = 0x70 + (i->Xin.SseCMov.cond ^ 1);
-//..       *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
-//..       ptmp = p;
-//.. 
-//..       /* movaps %src, %dst */
-//..       *p++ = 0x0F; 
-//..       *p++ = 0x28; 
-//..       p = doAMode_R(p, fake(vregNo(i->Xin.SseCMov.dst)),
-//..                        fake(vregNo(i->Xin.SseCMov.src)) );
-//.. 
-//..       /* Fill in the jump offset. */
-//..       *(ptmp-1) = p - ptmp;
-//..       goto done;
-//.. 
+   case Ain_SseCMov:
+      /* jmp fwds if !condition */
+      *p++ = 0x70 + (i->Ain.SseCMov.cond ^ 1);
+      *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
+      ptmp = p;
+
+      /* movaps %src, %dst */
+      *p++ = clearWBit(
+             rexAMode_R( vreg2ireg(i->Ain.SseCMov.dst),
+                         vreg2ireg(i->Ain.SseCMov.src) ));
+      *p++ = 0x0F; 
+      *p++ = 0x28; 
+      p = doAMode_R(p, vreg2ireg(i->Ain.SseCMov.dst),
+                       vreg2ireg(i->Ain.SseCMov.src) );
+
+      /* Fill in the jump offset. */
+      *(ptmp-1) = p - ptmp;
+      goto done;
+
 //..    case Xin_SseShuf:
 //..       *p++ = 0x66; 
 //..       *p++ = 0x0F; 
index 587cac3ce24022a7f3fc092eb9742243d27e2c03..cf1b006eee78e2fc0da0d0abd089649de0a58249 100644 (file)
@@ -316,7 +316,7 @@ typedef
       /* Floating point binary */
       Asse_ADDF, Asse_SUBF, Asse_MULF, Asse_DIVF,
       Asse_MAXF, Asse_MINF,
-//..       Xsse_CMPEQF, Xsse_CMPLTF, Xsse_CMPLEF, Xsse_CMPUNF,
+      Asse_CMPEQF, Asse_CMPLTF, Asse_CMPLEF, Asse_CMPUNF,
       /* Floating point unary */
       Asse_RCPF, Asse_RSQRTF, Asse_SQRTF, 
       /* Bitwise */
@@ -385,17 +385,18 @@ typedef
                         register */
       Ain_SseSI2SF,  /* scalar 32/64 int to 32/64 float conversion */
       Ain_SseSF2SI,  /* scalar 32/64 float to 32/64 int conversion */
+      Ain_SseSDSS,   /* scalar float32 to/from float64 */
 //.. 
 //..       Xin_SseConst,  /* Generate restricted SSE literal */
       Ain_SseLdSt,   /* SSE load/store 32/64/128 bits, no alignment
                         constraints, upper 96/64/0 bits arbitrary */
       Ain_SseLdzLO,  /* SSE load low 32/64 bits, zero remainder of reg */
-//..       Xin_Sse32Fx4,  /* SSE binary, 32Fx4 */
-//..       Xin_Sse32FLo,  /* SSE binary, 32F in lowest lane only */
+      Ain_Sse32Fx4,  /* SSE binary, 32Fx4 */
+      Ain_Sse32FLo,  /* SSE binary, 32F in lowest lane only */
 //..       Xin_Sse64Fx2,  /* SSE binary, 64Fx2 */
       Ain_Sse64FLo,  /* SSE binary, 64F in lowest lane only */
       Ain_SseReRg,   /* SSE binary general reg-reg, Re, Rg */
-//..       Xin_SseCMov,   /* SSE conditional move */
+      Ain_SseCMov,   /* SSE conditional move */
 //..       Xin_SseShuf    /* SSE2 shuffle (pshufd) */
    }
    AMD64InstrTag;
@@ -586,6 +587,12 @@ typedef
             HReg  src; /* v class */
             HReg  dst; /* i class */
          } SseSF2SI;
+         /* scalar float32 to/from float64 */
+         struct {
+            Bool from64; /* True: 64->32; False: 32->64 */
+            HReg src;
+            HReg dst;
+         } SseSDSS;
 //.. 
 //..          /* Simplistic SSE[123] */
 //..          struct {
@@ -603,16 +610,16 @@ typedef
             HReg        reg;
             AMD64AMode* addr;
          } SseLdzLO;
-//..          struct {
-//..             X86SseOp op;
-//..             HReg     src;
-//..             HReg     dst;
-//..          } Sse32Fx4;
-//..          struct {
-//..             X86SseOp op;
-//..             HReg     src;
-//..             HReg     dst;
-//..          } Sse32FLo;
+         struct {
+            AMD64SseOp op;
+            HReg       src;
+            HReg       dst;
+         } Sse32Fx4;
+         struct {
+            AMD64SseOp op;
+            HReg       src;
+            HReg       dst;
+         } Sse32FLo;
 //..          struct {
 //..             X86SseOp op;
 //..             HReg     src;
@@ -628,13 +635,13 @@ typedef
             HReg       src;
             HReg       dst;
          } SseReRg;
-//..          /* Mov src to dst on the given condition, which may not
-//..             be the bogus Xcc_ALWAYS. */
-//..          struct {
-//..             X86CondCode cond;
-//..             HReg        src;
-//..             HReg        dst;
-//..          } SseCMov;
+         /* Mov src to dst on the given condition, which may not
+            be the bogus Xcc_ALWAYS. */
+         struct {
+            AMD64CondCode cond;
+            HReg          src;
+            HReg          dst;
+         } SseCMov;
 //..          struct {
 //..             Int    order; /* 0 <= order <= 0xFF */
 //..             HReg   src;
@@ -677,16 +684,17 @@ extern AMD64Instr* AMD64Instr_LdMXCSR   ( AMD64AMode* );
 extern AMD64Instr* AMD64Instr_SseUComIS ( Int sz, HReg srcL, HReg srcR, HReg dst );
 extern AMD64Instr* AMD64Instr_SseSI2SF  ( Int szS, Int szD, HReg src, HReg dst );
 extern AMD64Instr* AMD64Instr_SseSF2SI  ( Int szS, Int szD, HReg src, HReg dst );
+extern AMD64Instr* AMD64Instr_SseSDSS   ( Bool from64, HReg src, HReg dst );
 //.. 
 //.. extern AMD64Instr* AMD64Instr_SseConst  ( UShort con, HReg dst );
 extern AMD64Instr* AMD64Instr_SseLdSt   ( Bool isLoad, Int sz, HReg, AMD64AMode* );
 extern AMD64Instr* AMD64Instr_SseLdzLO  ( Int sz, HReg, AMD64AMode* );
-//.. extern AMD64Instr* AMD64Instr_Sse32Fx4  ( AMD64SseOp, HReg, HReg );
-//.. extern AMD64Instr* AMD64Instr_Sse32FLo  ( AMD64SseOp, HReg, HReg );
+extern AMD64Instr* AMD64Instr_Sse32Fx4  ( AMD64SseOp, HReg, HReg );
+extern AMD64Instr* AMD64Instr_Sse32FLo  ( AMD64SseOp, HReg, HReg );
 //.. extern AMD64Instr* AMD64Instr_Sse64Fx2  ( AMD64SseOp, HReg, HReg );
 extern AMD64Instr* AMD64Instr_Sse64FLo  ( AMD64SseOp, HReg, HReg );
 extern AMD64Instr* AMD64Instr_SseReRg   ( AMD64SseOp, HReg, HReg );
-//.. extern AMD64Instr* AMD64Instr_SseCMov   ( AMD64CondCode, HReg src, HReg dst );
+extern AMD64Instr* AMD64Instr_SseCMov   ( AMD64CondCode, HReg src, HReg dst );
 //.. extern AMD64Instr* AMD64Instr_SseShuf   ( Int order, HReg src, HReg dst );
 
 
index 7159afd7acb165fe5dfb62cc260eb909fae042c5..01718ddec3c0ba68bc45c05bbfa8c1cf5ceae8d7 100644 (file)
@@ -233,8 +233,8 @@ static AMD64CondCode iselCondCode        ( ISelEnv* env, IRExpr* e );
 static HReg          iselDblExpr_wrk     ( ISelEnv* env, IRExpr* e );
 static HReg          iselDblExpr         ( ISelEnv* env, IRExpr* e );
 
-//static HReg          iselFltExpr_wrk     ( ISelEnv* env, IRExpr* e );
-//static HReg          iselFltExpr         ( ISelEnv* env, IRExpr* e );
+static HReg          iselFltExpr_wrk     ( ISelEnv* env, IRExpr* e );
+static HReg          iselFltExpr         ( ISelEnv* env, IRExpr* e );
 
 static HReg          iselVecExpr_wrk     ( ISelEnv* env, IRExpr* e );
 static HReg          iselVecExpr         ( ISelEnv* env, IRExpr* e );
@@ -567,48 +567,50 @@ void doHelperCall ( ISelEnv* env,
 }
 
 
-//.. /* Given a guest-state array descriptor, an index expression and a
-//..    bias, generate an X86AMode holding the relevant guest state
-//..    offset. */
-//.. 
-//.. static
-//.. X86AMode* genGuestArrayOffset ( ISelEnv* env, IRArray* descr, 
-//..                                 IRExpr* off, Int bias )
-//.. {
-//..    HReg tmp, roff;
-//..    Int  elemSz = sizeofIRType(descr->elemTy);
-//..    Int  nElems = descr->nElems;
-//.. 
-//..    /* throw out any cases not generated by an x86 front end.  In
-//..       theory there might be a day where we need to handle them -- if
-//..       we ever run non-x86-guest on x86 host. */
-//.. 
-//..    if (nElems != 8 || (elemSz != 1 && elemSz != 8))
-//..       vpanic("genGuestArrayOffset(x86 host)");
-//.. 
-//..    /* Compute off into a reg, %off.  Then return:
-//.. 
-//..          movl %off, %tmp
-//..          addl $bias, %tmp  (if bias != 0)
-//..          andl %tmp, 7
-//..          ... base(%ebp, %tmp, shift) ...
-//..    */
-//..    tmp  = newVRegI(env);
-//..    roff = iselIntExpr_R(env, off);
-//..    addInstr(env, mk_iMOVsd_RR(roff, tmp));
-//..    if (bias != 0) {
-//..       addInstr(env, 
-//..                X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(bias), tmp));
-//..    }
-//..    addInstr(env, 
-//..             X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(7), tmp));
-//..    vassert(elemSz == 1 || elemSz == 8);
-//..    return
-//..       X86AMode_IRRS( descr->base, hregX86_EBP(), tmp,
-//..                                   elemSz==8 ? 3 : 0);
-//.. }
-//.. 
-//.. 
+/* Given a guest-state array descriptor, an index expression and a
+   bias, generate an AMD64AMode holding the relevant guest state
+   offset. */
+
+static
+AMD64AMode* genGuestArrayOffset ( ISelEnv* env, IRArray* descr, 
+                                  IRExpr* off, Int bias )
+{
+   HReg tmp, roff;
+   Int  elemSz = sizeofIRType(descr->elemTy);
+   Int  nElems = descr->nElems;
+
+   /* Throw out any cases not generated by an amd64 front end.  In
+      theory there might be a day where we need to handle them -- if
+      we ever run non-amd64-guest on amd64 host. */
+
+   if (nElems != 8 || (elemSz != 1 && elemSz != 8))
+      vpanic("genGuestArrayOffset(amd64 host)");
+
+   /* Compute off into a reg, %off.  Then return:
+
+         movq %off, %tmp
+         addq $bias, %tmp  (if bias != 0)
+         andq %tmp, 7
+         ... base(%rbp, %tmp, shift) ...
+   */
+   tmp  = newVRegI(env);
+   roff = iselIntExpr_R(env, off);
+   addInstr(env, mk_iMOVsd_RR(roff, tmp));
+   if (bias != 0) {
+      /* Make sure the bias is sane, in the sense that there are
+         no significant bits above bit 30 in it. */
+      vassert(-10000 < bias && bias < 10000);
+      addInstr(env, 
+               AMD64Instr_Alu64R(Aalu_ADD, AMD64RMI_Imm(bias), tmp));
+   }
+   addInstr(env, 
+            AMD64Instr_Alu64R(Aalu_AND, AMD64RMI_Imm(7), tmp));
+   vassert(elemSz == 1 || elemSz == 8);
+   return
+      AMD64AMode_IRRS( descr->base, hregAMD64_RBP(), tmp,
+                                    elemSz==8 ? 3 : 0);
+}
+
 
 /* Set the SSE unit's rounding mode to default (%mxcsr = 0x1F80) */
 static
@@ -703,27 +705,27 @@ void set_SSE_rounding_mode ( ISelEnv* env, IRExpr* mode )
 //..    addInstr(env, X86Instr_FpLdStCW(True/*load*/, zero_esp));
 //..    add_to_esp(env, 4);
 //.. }
-//.. 
-//.. 
-//.. /* Generate !src into a new vector register, and be sure that the code
-//..    is SSE1 compatible.  Amazing that Intel doesn't offer a less crappy
-//..    way to do this. 
-//.. */
-//.. static HReg do_sse_Not128 ( ISelEnv* env, HReg src )
-//.. {
-//..    HReg dst = newVRegV(env);
-//..    /* Set dst to zero.  Not strictly necessary, but the idea of doing
-//..       a FP comparison on whatever junk happens to be floating around
-//..       in it is just too scary. */
-//..    addInstr(env, X86Instr_SseReRg(Xsse_XOR, dst, dst));
-//..    /* And now make it all 1s ... */
-//..    addInstr(env, X86Instr_Sse32Fx4(Xsse_CMPEQF, dst, dst));
-//..    /* Finally, xor 'src' into it. */
-//..    addInstr(env, X86Instr_SseReRg(Xsse_XOR, src, dst));
-//..    return dst;
-//.. }
-//.. 
-//.. 
+
+
+/* Generate !src into a new vector register, and be sure that the code
+   is SSE1 compatible.  Amazing that Intel doesn't offer a less crappy
+   way to do this. 
+*/
+static HReg do_sse_NotV128 ( ISelEnv* env, HReg src )
+{
+   HReg dst = newVRegV(env);
+   /* Set dst to zero.  Not strictly necessary, but the idea of doing
+      a FP comparison on whatever junk happens to be floating around
+      in it is just too scary. */
+   addInstr(env, AMD64Instr_SseReRg(Asse_XOR, dst, dst));
+   /* And now make it all 1s ... */
+   addInstr(env, AMD64Instr_Sse32Fx4(Asse_CMPEQF, dst, dst));
+   /* Finally, xor 'src' into it. */
+   addInstr(env, AMD64Instr_SseReRg(Asse_XOR, src, dst));
+   return dst;
+}
+
+
 //.. /* Round an x87 FPU value to 53-bit-mantissa precision, to be used
 //..    after most non-simple FPU operations (simple = +, -, *, / and
 //..    sqrt).
@@ -1374,18 +1376,18 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
       break;
    }
 
-//..    case Iex_GetI: {
-//..       X86AMode* am 
-//..          = genGuestArrayOffset(
-//..               env, e->Iex.GetI.descr, 
-//..                    e->Iex.GetI.ix, e->Iex.GetI.bias );
-//..       HReg dst = newVRegI(env);
-//..       if (ty == Ity_I8) {
-//..          addInstr(env, X86Instr_LoadEX( 1, False, am, dst ));
-//..          return dst;
-//..       }
-//..       break;
-//..    }
+   case Iex_GetI: {
+      AMD64AMode* am 
+         = genGuestArrayOffset(
+              env, e->Iex.GetI.descr, 
+                   e->Iex.GetI.ix, e->Iex.GetI.bias );
+      HReg dst = newVRegI(env);
+      if (ty == Ity_I8) {
+         addInstr(env, AMD64Instr_LoadEX( 1, False, am, dst ));
+         return dst;
+      }
+      break;
+   }
 
    /* --------- CCALL --------- */
    case Iex_CCall: {
@@ -2549,30 +2551,30 @@ static void iselInt128Expr_wrk ( HReg* rHi, HReg* rLo,
 }
 
 
-//.. /*---------------------------------------------------------*/
-//.. /*--- ISEL: Floating point expressions (32 bit)         ---*/
-//.. /*---------------------------------------------------------*/
-//.. 
-//.. /* Nothing interesting here; really just wrappers for
-//..    64-bit stuff. */
-//.. 
-//.. static HReg iselFltExpr ( ISelEnv* env, IRExpr* e )
-//.. {
-//..    HReg r = iselFltExpr_wrk( env, e );
-//.. #  if 0
-//..    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
-//.. #  endif
-//..    vassert(hregClass(r) == HRcFlt64); /* yes, really Flt64 */
-//..    vassert(hregIsVirtual(r));
-//..    return r;
-//.. }
-//.. 
-//.. /* DO NOT CALL THIS DIRECTLY */
-//.. static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
-//.. {
-//..    IRType ty = typeOfIRExpr(env->type_env,e);
-//..    vassert(ty == Ity_F32);
-//.. 
+/*---------------------------------------------------------*/
+/*--- ISEL: Floating point expressions (32 bit)         ---*/
+/*---------------------------------------------------------*/
+
+/* Nothing interesting here; really just wrappers for
+   64-bit stuff. */
+
+static HReg iselFltExpr ( ISelEnv* env, IRExpr* e )
+{
+   HReg r = iselFltExpr_wrk( env, e );
+#  if 0
+   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
+#  endif
+   vassert(hregClass(r) == HRcVec128);
+   vassert(hregIsVirtual(r));
+   return r;
+}
+
+/* DO NOT CALL THIS DIRECTLY */
+static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
+{
+   IRType ty = typeOfIRExpr(env->type_env,e);
+   vassert(ty == Ity_F32);
+
 //..    if (e->tag == Iex_Tmp) {
 //..       return lookupIRTemp(env, e->Iex.Tmp.tmp);
 //..    }
@@ -2585,20 +2587,20 @@ static void iselInt128Expr_wrk ( HReg* rHi, HReg* rLo,
 //..       addInstr(env, X86Instr_FpLdSt(True/*load*/, 4, res, am));
 //..       return res;
 //..    }
-//.. 
-//..    if (e->tag == Iex_Binop
-//..        && e->Iex.Binop.op == Iop_F64toF32) {
-//..       /* Although the result is still held in a standard FPU register,
-//..          we need to round it to reflect the loss of accuracy/range
-//..          entailed in casting it to a 32-bit float. */
-//..       HReg dst = newVRegF(env);
-//..       HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
-//..       set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
-//..       addInstr(env, X86Instr_Fp64to32(src,dst));
-//..       set_FPU_rounding_default( env );
-//..       return dst;
-//..    }
-//.. 
+
+   if (e->tag == Iex_Binop
+       && e->Iex.Binop.op == Iop_F64toF32) {
+      /* Although the result is still held in a standard SSE register,
+         we need to round it to reflect the loss of accuracy/range
+         entailed in casting it to a 32-bit float. */
+      HReg dst = newVRegV(env);
+      HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
+      set_SSE_rounding_mode( env, e->Iex.Binop.arg1 );
+      addInstr(env, AMD64Instr_SseSDSS(True/*D->S*/,src,dst));
+      set_SSE_rounding_default( env );
+      return dst;
+   }
+
 //..    if (e->tag == Iex_Get) {
 //..       X86AMode* am = X86AMode_IR( e->Iex.Get.offset,
 //..                                   hregX86_EBP() );
@@ -2621,10 +2623,10 @@ static void iselInt128Expr_wrk ( HReg* rHi, HReg* rLo,
 //..       add_to_esp(env, 4);
 //..       return dst;
 //..    }
-//.. 
-//..    ppIRExpr(e);
-//..    vpanic("iselFltExpr_wrk");
-//.. }
+
+   ppIRExpr(e);
+   vpanic("iselFltExpr_wrk");
+}
 
 
 /*---------------------------------------------------------*/
@@ -2677,30 +2679,32 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
       return lookupIRTemp(env, e->Iex.Tmp.tmp);
    }
 
-//..    if (e->tag == Iex_Const) {
-//..       union { UInt u32x2[2]; ULong u64; Double f64; } u;
-//..       HReg freg = newVRegF(env);
-//..       vassert(sizeof(u) == 8);
-//..       vassert(sizeof(u.u64) == 8);
-//..       vassert(sizeof(u.f64) == 8);
-//..       vassert(sizeof(u.u32x2) == 8);
-//.. 
-//..       if (e->Iex.Const.con->tag == Ico_F64) {
-//..          u.f64 = e->Iex.Const.con->Ico.F64;
-//..       }
-//..       else if (e->Iex.Const.con->tag == Ico_F64i) {
-//..          u.u64 = e->Iex.Const.con->Ico.F64i;
-//..       }
-//..       else
-//..          vpanic("iselDblExpr(x86): const");
-//.. 
-//..       addInstr(env, X86Instr_Push(X86RMI_Imm(u.u32x2[1])));
-//..       addInstr(env, X86Instr_Push(X86RMI_Imm(u.u32x2[0])));
-//..       addInstr(env, X86Instr_FpLdSt(True/*load*/, 8, freg, 
-//..                                     X86AMode_IR(0, hregX86_ESP())));
-//..       add_to_esp(env, 8);
-//..       return freg;
-//..    }
+   if (e->tag == Iex_Const) {
+      union { ULong u64; Double f64; } u;
+      HReg res = newVRegV(env);
+      HReg tmp = newVRegI(env);
+      vassert(sizeof(u) == 8);
+      vassert(sizeof(u.u64) == 8);
+      vassert(sizeof(u.f64) == 8);
+
+      if (e->Iex.Const.con->tag == Ico_F64) {
+         u.f64 = e->Iex.Const.con->Ico.F64;
+      }
+      else if (e->Iex.Const.con->tag == Ico_F64i) {
+         u.u64 = e->Iex.Const.con->Ico.F64i;
+      }
+      else
+         vpanic("iselDblExpr(amd64): const");
+
+      addInstr(env, AMD64Instr_Imm64(u.u64, tmp));
+      addInstr(env, AMD64Instr_Push(AMD64RMI_Reg(tmp)));
+      addInstr(env, AMD64Instr_SseLdSt(
+                       True/*load*/, 8, res, 
+                       AMD64AMode_IR(0, hregAMD64_RSP())
+              ));
+      add_to_rsp(env, 8);
+      return res;
+   }
 
    if (e->tag == Iex_LDle) {
       AMD64AMode* am;
@@ -2719,16 +2723,16 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
       return res;
    }
 
-//..    if (e->tag == Iex_GetI) {
-//..       X86AMode* am 
-//..          = genGuestArrayOffset(
-//..               env, e->Iex.GetI.descr, 
-//..                    e->Iex.GetI.ix, e->Iex.GetI.bias );
-//..       HReg res = newVRegF(env);
-//..       addInstr(env, X86Instr_FpLdSt( True/*load*/, 8, res, am ));
-//..       return res;
-//..    }
-//.. 
+   if (e->tag == Iex_GetI) {
+      AMD64AMode* am 
+         = genGuestArrayOffset(
+              env, e->Iex.GetI.descr, 
+                   e->Iex.GetI.ix, e->Iex.GetI.bias );
+      HReg res = newVRegV(env);
+      addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 8, res, am ));
+      return res;
+   }
+
 //..    if (e->tag == Iex_Binop) {
 //..       X86FpOp fpop = Xfp_INVALID;
 //..       switch (e->Iex.Binop.op) {
@@ -2792,6 +2796,23 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
       return dst;
    }
 
+   if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_NegF64) {
+      /* Sigh ... very rough code.  Could do much better. */
+      HReg r1  = newVRegI(env);
+      HReg dst = newVRegV(env);
+      HReg tv  = newVRegV(env);
+      HReg src = iselDblExpr(env, e->Iex.Unop.arg);
+      AMD64AMode* rsp0 = AMD64AMode_IR(0, hregAMD64_RSP());
+      addInstr(env, mk_vMOVsd_RR(src,dst));
+      addInstr(env, AMD64Instr_Push(AMD64RMI_Imm(0)));
+      addInstr(env, AMD64Instr_Imm64( 1ULL<<63, r1 ));
+      addInstr(env, AMD64Instr_Push(AMD64RMI_Reg(r1)));
+      addInstr(env, AMD64Instr_SseLdSt(True, 16, tv, rsp0));
+      addInstr(env, AMD64Instr_SseReRg(Asse_XOR, tv, dst));
+      add_to_rsp(env, 16);
+      return dst;
+   }
+
 //..    if (e->tag == Iex_Unop) {
 //..       X86FpOp fpop = Xfp_INVALID;
 //..       switch (e->Iex.Unop.op) {
@@ -2853,21 +2874,21 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
 //..             break;
 //..       }
 //..    }
-//.. 
-//..    /* --------- MULTIPLEX --------- */
-//..    if (e->tag == Iex_Mux0X) {
-//..      if (ty == Ity_F64
-//..          && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
-//..         HReg r8  = iselIntExpr_R(env, e->Iex.Mux0X.cond);
-//..         HReg rX  = iselDblExpr(env, e->Iex.Mux0X.exprX);
-//..         HReg r0  = iselDblExpr(env, e->Iex.Mux0X.expr0);
-//..         HReg dst = newVRegF(env);
-//..         addInstr(env, X86Instr_FpUnary(Xfp_MOV,rX,dst));
-//..         addInstr(env, X86Instr_Test32(X86RI_Imm(0xFF), X86RM_Reg(r8)));
-//..         addInstr(env, X86Instr_FpCMov(Xcc_Z,r0,dst));
-//..         return dst;
-//..       }
-//..    }
+
+   /* --------- MULTIPLEX --------- */
+   if (e->tag == Iex_Mux0X) {
+      HReg r8, rX, r0, dst;
+      vassert(ty == Ity_F64);
+      vassert(typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8);
+      r8  = iselIntExpr_R(env, e->Iex.Mux0X.cond);
+      rX  = iselDblExpr(env, e->Iex.Mux0X.exprX);
+      r0  = iselDblExpr(env, e->Iex.Mux0X.expr0);
+      dst = newVRegV(env);
+      addInstr(env, mk_vMOVsd_RR(rX,dst));
+      addInstr(env, AMD64Instr_Test64(AMD64RI_Imm(0xFF), AMD64RM_Reg(r8)));
+      addInstr(env, AMD64Instr_SseCMov(Acc_Z,r0,dst));
+      return dst;
+   }
 
    ppIRExpr(e);
    vpanic("iselDblExpr_wrk");
@@ -2925,26 +2946,35 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
    if (e->tag == Iex_Const) {
       HReg dst = newVRegV(env);
       vassert(e->Iex.Const.con->tag == Ico_V128);
-      if (e->Iex.Const.con->Ico.V128 == 0) {
+      if (e->Iex.Const.con->Ico.V128 == 0x0000) {
          addInstr(env, AMD64Instr_SseReRg(Asse_XOR, dst, dst));
          return dst;
+      } else
+      if (e->Iex.Const.con->Ico.V128 == 0x00FF) {
+         AMD64AMode* rsp0 = AMD64AMode_IR(0, hregAMD64_RSP());
+         /* Both of these literals are sign-extended to 64 bits. */
+         addInstr(env, AMD64Instr_Push(AMD64RMI_Imm(0)));
+         addInstr(env, AMD64Instr_Push(AMD64RMI_Imm(0xFFFFFFFF)));
+         addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 16, dst, rsp0 ));
+         add_to_rsp(env, 16);
+         return dst;
       } else {
          goto vec_fail;
-#if 0
-      addInstr(env, X86Instr_SseConst(e->Iex.Const.con->Ico.V128, dst));
-      return dst;
-#endif
+#        if 0
+         addInstr(env, X86Instr_SseConst(e->Iex.Const.con->Ico.V128, dst));
+         return dst;
+#        endif
       }
    }
 
    if (e->tag == Iex_Unop) {
    switch (e->Iex.Unop.op) {
 
-//..       case Iop_Not128: {
-//..          HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
-//..          return do_sse_Not128(env, arg);
-//..       }
-//.. 
+      case Iop_NotV128: {
+         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
+         return do_sse_NotV128(env, arg);
+      }
+
 //..       case Iop_CmpNEZ64x2: {
 //..          /* We can use SSE2 instructions for this. */
 //..          /* Ideally, we want to do a 64Ix2 comparison against zero of
@@ -3086,15 +3116,14 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
          return dst;
       }
 
-//..       case Iop_32Uto128: {
-//..          HReg      dst  = newVRegV(env);
-//..          X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
-//..          X86RMI*   rmi  = iselIntExpr_RMI(env, e->Iex.Unop.arg);
-//..          addInstr(env, X86Instr_Push(rmi));
-//..          addInstr(env, X86Instr_SseLdzLO(4, dst, esp0));
-//..          add_to_esp(env, 4);
-//..          return dst;
-//..       }
+      case Iop_32UtoV128: {
+         HReg        dst     = newVRegV(env);
+         AMD64AMode* rsp_m32 = AMD64AMode_IR(-32, hregAMD64_RSP());
+         AMD64RI*    ri      = iselIntExpr_RI(env, e->Iex.Unop.arg);
+         addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, ri, rsp_m32));
+         addInstr(env, AMD64Instr_SseLdzLO(4, dst, rsp_m32));
+         return dst;
+      }
 
       case Iop_64UtoV128: {
          HReg        dst  = newVRegV(env);
@@ -3189,27 +3218,27 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
 //..          addInstr(env, X86Instr_Sse64Fx2(op, argR, dst));
 //..          return dst;
 //..       }
-//.. 
+
 //..       case Iop_CmpEQ32F0x4: op = Xsse_CMPEQF; goto do_32F0x4;
 //..       case Iop_CmpLT32F0x4: op = Xsse_CMPLTF; goto do_32F0x4;
 //..       case Iop_CmpLE32F0x4: op = Xsse_CMPLEF; goto do_32F0x4;
-//..       case Iop_Add32F0x4:   op = Xsse_ADDF;   goto do_32F0x4;
+      case Iop_Add32F0x4:   op = Asse_ADDF;   goto do_32F0x4;
 //..       case Iop_Div32F0x4:   op = Xsse_DIVF;   goto do_32F0x4;
 //..       case Iop_Max32F0x4:   op = Xsse_MAXF;   goto do_32F0x4;
 //..       case Iop_Min32F0x4:   op = Xsse_MINF;   goto do_32F0x4;
-//..       case Iop_Mul32F0x4:   op = Xsse_MULF;   goto do_32F0x4;
-//..       case Iop_Sub32F0x4:   op = Xsse_SUBF;   goto do_32F0x4;
-//..       do_32F0x4: {
-//..          HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
-//..          HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
-//..          HReg dst = newVRegV(env);
-//..          addInstr(env, mk_vMOVsd_RR(argL, dst));
-//..          addInstr(env, X86Instr_Sse32FLo(op, argR, dst));
-//..          return dst;
-//..       }
-//.. 
+      case Iop_Mul32F0x4:   op = Asse_MULF;   goto do_32F0x4;
+      case Iop_Sub32F0x4:   op = Asse_SUBF;   goto do_32F0x4;
+      do_32F0x4: {
+         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
+         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
+         HReg dst = newVRegV(env);
+         addInstr(env, mk_vMOVsd_RR(argL, dst));
+         addInstr(env, AMD64Instr_Sse32FLo(op, argR, dst));
+         return dst;
+      }
+
 //..       case Iop_CmpEQ64F0x2: op = Xsse_CMPEQF; goto do_64F0x2;
-//..       case Iop_CmpLT64F0x2: op = Xsse_CMPLTF; goto do_64F0x2;
+      case Iop_CmpLT64F0x2: op = Asse_CMPLTF; goto do_64F0x2;
 //..       case Iop_CmpLE64F0x2: op = Xsse_CMPLEF; goto do_64F0x2;
       case Iop_Add64F0x2:   op = Asse_ADDF;   goto do_64F0x2;
       case Iop_Div64F0x2:   op = Asse_DIVF;   goto do_64F0x2;
@@ -3252,7 +3281,7 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
 //..          op = Xsse_UNPCKLQ; arg1isEReg = True; goto do_SseReRg;
 //.. 
       case Iop_AndV128:    op = Asse_AND;      goto do_SseReRg;
-//..       case Iop_Or128:      op = Xsse_OR;       goto do_SseReRg;
+      case Iop_OrV128:     op = Asse_OR;       goto do_SseReRg;
       case Iop_XorV128:    op = Asse_XOR;      goto do_SseReRg;
 //..       case Iop_Add8x16:    op = Xsse_ADD8;     goto do_SseReRg;
 //..       case Iop_Add16x8:    op = Xsse_ADD16;    goto do_SseReRg;
@@ -3382,11 +3411,11 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
                                         r,am));
          return;
       }
-//..       if (tyd == Ity_F64) {
-//..          HReg r = iselDblExpr(env, stmt->Ist.STle.data);
-//..          addInstr(env, X86Instr_FpLdSt(False/*store*/, 8, r, am));
-//..          return;
-//..       }
+      if (tyd == Ity_F64) {
+         HReg r = iselDblExpr(env, stmt->Ist.STle.data);
+         addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 8, r, am));
+         return;
+      }
 //..       if (tyd == Ity_F32) {
 //..          HReg r = iselFltExpr(env, stmt->Ist.STle.data);
 //..          addInstr(env, X86Instr_FpLdSt(False/*store*/, 4, r, am));
@@ -3442,13 +3471,13 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
          addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, vec, am));
          return;
       }
-//..       if (ty == Ity_F32) {
-//..          HReg f32 = iselFltExpr(env, stmt->Ist.Put.data);
-//..          X86AMode* am  = X86AMode_IR(stmt->Ist.Put.offset, hregX86_EBP());
-//..          set_FPU_rounding_default(env); /* paranoia */
-//..          addInstr(env, X86Instr_FpLdSt( False/*store*/, 4, f32, am ));
-//..          return;
-//..       }
+      if (ty == Ity_F32) {
+         HReg f32 = iselFltExpr(env, stmt->Ist.Put.data);
+         AMD64AMode* am = AMD64AMode_IR(stmt->Ist.Put.offset, hregAMD64_RBP());
+         set_SSE_rounding_default(env); /* paranoia */
+         addInstr(env, AMD64Instr_SseLdSt( False/*store*/, 4, f32, am ));
+         return;
+      }
       if (ty == Ity_F64) {
          HReg f64 = iselDblExpr(env, stmt->Ist.Put.data);
          AMD64AMode* am = AMD64AMode_IR( stmt->Ist.Put.offset, 
@@ -3459,24 +3488,24 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
       break;
    }
 
-//..    /* --------- Indexed PUT --------- */
-//..    case Ist_PutI: {
-//..       X86AMode* am 
-//..          = genGuestArrayOffset(
-//..               env, stmt->Ist.PutI.descr, 
-//..                    stmt->Ist.PutI.ix, stmt->Ist.PutI.bias );
-//.. 
-//..       IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data);
-//..       if (ty == Ity_F64) {
-//..          HReg val = iselDblExpr(env, stmt->Ist.PutI.data);
-//..          addInstr(env, X86Instr_FpLdSt( False/*store*/, 8, val, am ));
-//..          return;
-//..       }
-//..       if (ty == Ity_I8) {
-//..          HReg r = iselIntExpr_R(env, stmt->Ist.PutI.data);
-//..          addInstr(env, X86Instr_Store( 1, r, am ));
-//..          return;
-//..       }
+   /* --------- Indexed PUT --------- */
+   case Ist_PutI: {
+      AMD64AMode* am 
+         = genGuestArrayOffset(
+              env, stmt->Ist.PutI.descr, 
+                   stmt->Ist.PutI.ix, stmt->Ist.PutI.bias );
+
+      IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data);
+      if (ty == Ity_F64) {
+         HReg val = iselDblExpr(env, stmt->Ist.PutI.data);
+         addInstr(env, AMD64Instr_SseLdSt( False/*store*/, 8, val, am ));
+         return;
+      }
+      if (ty == Ity_I8) {
+         HReg r = iselIntExpr_R(env, stmt->Ist.PutI.data);
+         addInstr(env, AMD64Instr_Store( 1, r, am ));
+         return;
+      }
 //..       if (ty == Ity_I64) {
 //..          HReg rHi, rLo;
 //..          X86AMode* am4 = advance4(am);
@@ -3485,8 +3514,8 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
 //..          addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(rHi), am4 ));
 //..          return;
 //..       }
-//..       break;
-//..    }
+      break;
+   }
 
    /* --------- TMP --------- */
    case Ist_Tmp: {
index a5d4c5b41544813f958ae0d54da06aee63f7eaf5..8d30985977df02a00cb2703b5631da6591cf2866 100644 (file)
 /*---------------------------------------------------------------*/
 
 /* See detailed comments at the top of libvex_guest_x86.h for
-   further info.  This representation pretty closely mimics the
+   further info.  This representation closely follows the
    x86 representation.
-
-   SSEROUND[1:0] is the SSE unit's notional rounding mode, encoded as
-   per the IRRoundingMode type.
 */
 
 
@@ -114,6 +111,16 @@ typedef
       U128  guest_XMM14;
       U128  guest_XMM15;
 
+      /* FPU */
+      /* Note.  Setting guest_FTOP to be ULong messes up the
+         delicately-balanced PutI/GetI optimisation machinery.
+         Therefore best to leave it as a UInt. */
+      UInt  guest_FTOP;
+      ULong guest_FPREG[8];
+      UChar guest_FPTAG[8];
+      ULong guest_FPROUND;
+      ULong guest_FC3210;
+
       /* Emulation warnings */
       UInt   guest_EMWARN;
       /* Padding to make it have an 8-aligned size */