]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fill in a bunch more amd64 floating point cases. Some non-trivial
authorJulian Seward <jseward@acm.org>
Fri, 25 Feb 2005 13:03:03 +0000 (13:03 +0000)
committerJulian Seward <jseward@acm.org>
Fri, 25 Feb 2005 13:03:03 +0000 (13:03 +0000)
FP programs are beginning to work now.

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

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

index 4f1518b5bff706d1d9634b3394e4e605bb7c2d11..2962f929e8b12b101db8cb8e78a39347dc8b057e 100644 (file)
@@ -345,7 +345,7 @@ static void unimplemented ( HChar* str )
 #define OFFB_IDFLAG    offsetof(VexGuestAMD64State,guest_IDFLAG)
 #define OFFB_FTOP      offsetof(VexGuestAMD64State,guest_FTOP)
 //.. #define OFFB_FC3210    offsetof(VexGuestX86State,guest_FC3210)
-//.. #define OFFB_FPROUND   offsetof(VexGuestX86State,guest_FPROUND)
+#define OFFB_FPROUND   offsetof(VexGuestAMD64State,guest_FPROUND)
 //.. 
 //.. #define OFFB_CS        offsetof(VexGuestX86State,guest_CS)
 //.. #define OFFB_DS        offsetof(VexGuestX86State,guest_DS)
@@ -1214,10 +1214,10 @@ 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 );
-//.. }
+static IRExpr* getXMMRegLane32F ( UInt xmmreg, Int laneno )
+{
+   return IRExpr_Get( xmmGuestRegLane32offset(xmmreg,laneno), Ity_F32 );
+}
 
 static void putXMMReg ( UInt xmmreg, IRExpr* e )
 {
@@ -3939,31 +3939,32 @@ static void put_ftop ( IRExpr* e )
 //.. {
 //..    stmt( IRStmt_Put( OFFB_FC3210, e ) );
 //.. }
-//.. 
-//.. /* --------- Get/put the FPU rounding mode. --------- */
-//.. static IRExpr* /* :: Ity_I32 */ get_fpround ( void )
-//.. {
-//..    return IRExpr_Get( OFFB_FPROUND, Ity_I32 );
-//.. }
-//.. 
+
+/* --------- Get/put the FPU rounding mode. --------- */
+static IRExpr* /* :: Ity_I32 */ get_fpround ( void )
+{
+   return unop(Iop_64to32, IRExpr_Get( OFFB_FPROUND, Ity_I64 ));
+}
+
 //.. static void put_fpround ( IRExpr* /* :: Ity_I32 */ e )
 //.. {
-//..    stmt( IRStmt_Put( OFFB_FPROUND, e ) );
-//.. }
-//.. 
-//.. 
-//.. /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
-//.. /* Produces a value in 0 .. 3, which is encoded as per the type
-//..    IRRoundingMode.  Since the guest_FPROUND value is also encoded as
-//..    per IRRoundingMode, we merely need to get it and mask it for
-//..    safety.
-//.. */
-//.. static IRExpr* /* :: Ity_I32 */ get_roundingmode ( void )
-//.. {
-//..    return binop( Iop_And32, get_fpround(), mkU32(3) );
+//..    vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I32);
+//..    stmt( IRStmt_Put( OFFB_FPROUND, unop(Iop_32Uto64,e) ) );
 //.. }
 
 
+/* --------- Synthesise a 2-bit FPU rounding mode. --------- */
+/* Produces a value in 0 .. 3, which is encoded as per the type
+   IRRoundingMode.  Since the guest_FPROUND value is also encoded as
+   per IRRoundingMode, we merely need to get it and mask it for
+   safety.
+*/
+static IRExpr* /* :: Ity_I32 */ get_roundingmode ( void )
+{
+   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'. */
@@ -4153,27 +4154,29 @@ static void fp_pop ( void )
 //..    if (pop_after)
 //..       fp_pop();
 //.. }
-//.. 
-//.. /* %eflags(Z,P,C) = UCOMI( st(0), st(i) ) */
-//.. static void fp_do_ucomi_ST0_STi ( UInt i, Bool pop_after )
-//.. {
-//..    DIP("fucomi%s %%st(0),%%st(%d)\n", pop_after ? "p" : "", i);
-//..    /* This is a bit of a hack (and isn't really right).  It sets
-//..       Z,P,C,O correctly, but forces A and S to zero, whereas the Intel
-//..       documentation implies A and S are unchanged. 
-//..    */
-//..    /* It's also fishy in that it is used both for COMIP and
-//..       UCOMIP, and they aren't the same (although similar). */
-//..    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
-//..    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
-//..    stmt( IRStmt_Put( OFFB_CC_DEP1,
-//..                      binop( Iop_And32,
-//..                             binop(Iop_CmpF64, get_ST(0), get_ST(i)),
-//..                             mkU32(0x45)
-//..        )));
-//..    if (pop_after)
-//..       fp_pop();
-//.. }
+
+/* %rflags(Z,P,C) = UCOMI( st(0), st(i) ) */
+static void fp_do_ucomi_ST0_STi ( UInt i, Bool pop_after )
+{
+   DIP("fucomi%s %%st(0),%%st(%d)\n", pop_after ? "p" : "", i);
+   /* This is a bit of a hack (and isn't really right).  It sets
+      Z,P,C,O correctly, but forces A and S to zero, whereas the Intel
+      documentation implies A and S are unchanged. 
+   */
+   /* It's also fishy in that it is used both for COMIP and
+      UCOMIP, and they aren't the same (although similar). */
+   stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
+   stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
+   stmt( IRStmt_Put( 
+            OFFB_CC_DEP1,
+            binop( Iop_And64,
+                   unop( Iop_32Uto64,
+                         binop(Iop_CmpF64, get_ST(0), get_ST(i))),
+                   mkU64(0x45)
+        )));
+   if (pop_after)
+      fp_pop();
+}
 
 
 static
@@ -4338,26 +4341,26 @@ ULong dis_FPU ( Bool* decode_ok, Prefix pfx, ULong delta )
 
          switch (gregOfRM(modrm)) {
 
-//..             case 0: /* FLD single-real */
-//..                DIP("flds %s\n", dis_buf);
-//..                fp_push();
-//..                put_ST(0, unop(Iop_F32toF64,
-//..                               loadLE(Ity_F32, mkexpr(addr))));
-//..                break;
-//.. 
-//..             case 2: /* FST single-real */
-//..                DIP("fsts %s\n", dis_buf);
-//..                storeLE(mkexpr(addr),
-//..                        binop(Iop_F64toF32, get_roundingmode(), get_ST(0)));
-//..                break;
-//.. 
-//..             case 3: /* FSTP single-real */
-//..                DIP("fstps %s\n", dis_buf);
-//..                storeLE(mkexpr(addr), 
-//..                        binop(Iop_F64toF32, get_roundingmode(), get_ST(0)));
-//..                fp_pop();
-//..                break;
-//.. 
+            case 0: /* FLD single-real */
+               DIP("flds %s\n", dis_buf);
+               fp_push();
+               put_ST(0, unop(Iop_F32toF64,
+                              loadLE(Ity_F32, mkexpr(addr))));
+               break;
+
+            case 2: /* FST single-real */
+               DIP("fsts %s\n", dis_buf);
+               storeLE(mkexpr(addr),
+                       binop(Iop_F64toF32, get_roundingmode(), get_ST(0)));
+               break;
+
+            case 3: /* FSTP single-real */
+               DIP("fstps %s\n", dis_buf);
+               storeLE(mkexpr(addr), 
+                       binop(Iop_F64toF32, get_roundingmode(), get_ST(0)));
+               fp_pop();
+               break;
+
 //..             case 4: { /* FLDENV m108 */
 //..                /* Uses dirty helper: 
 //..                      VexEmWarn x86g_do_FLDENV ( VexGuestX86State*, Addr32 ) */
@@ -4525,14 +4528,14 @@ ULong dis_FPU ( Bool* decode_ok, Prefix pfx, ULong delta )
          delta++;
          switch (modrm) {
 
-//..             case 0xC0 ... 0xC7: /* FLD %st(?) */
-//..                r_src = (UInt)modrm - 0xC0;
-//..                DIP("fld %%st(%d)\n", r_src);
-//..                t1 = newTemp(Ity_F64);
-//..                assign(t1, get_ST(r_src));
-//..                fp_push();
-//..                put_ST(0, mkexpr(t1));
-//..                break;
+            case 0xC0 ... 0xC7: /* FLD %st(?) */
+               r_src = (UInt)modrm - 0xC0;
+               DIP("fld %%st(%d)\n", r_src);
+               t1 = newTemp(Ity_F64);
+               assign(t1, get_ST(r_src));
+               fp_push();
+               put_ST(0, mkexpr(t1));
+               break;
 
             case 0xC8 ... 0xCF: /* FXCH %st(?) */
                r_src = (UInt)modrm - 0xC8;
@@ -4574,14 +4577,14 @@ ULong dis_FPU ( Bool* decode_ok, Prefix pfx, ULong delta )
 //..                DIP("fxam\n");
 //..                break;
 //..             }
-//.. 
-//..             case 0xE8: /* FLD1 */
-//..                DIP("fld1\n");
-//..                fp_push();
-//..                /* put_ST(0, IRExpr_Const(IRConst_F64(1.0))); */
-//..                put_ST(0, IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)));
-//..                break;
-//.. 
+
+            case 0xE8: /* FLD1 */
+               DIP("fld1\n");
+               fp_push();
+               /* put_ST(0, IRExpr_Const(IRConst_F64(1.0))); */
+               put_ST(0, IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)));
+               break;
+
 //..             case 0xE9: /* FLDL2T */
 //..                DIP("fldl2t\n");
 //..                fp_push();
@@ -4616,14 +4619,14 @@ ULong dis_FPU ( Bool* decode_ok, Prefix pfx, ULong delta )
 //..                /* put_ST(0, IRExpr_Const(IRConst_F64(0.69314718055994530942))); */
 //..                put_ST(0, IRExpr_Const(IRConst_F64i(0x3fe62e42fefa39efULL)));
 //..                break;
-//.. 
-//..             case 0xEE: /* FLDZ */
-//..                DIP("fldz\n");
-//..                fp_push();
-//..                /* put_ST(0, IRExpr_Const(IRConst_F64(0.0))); */
-//..                put_ST(0, IRExpr_Const(IRConst_F64i(0x0000000000000000ULL)));
-//..                break;
-//.. 
+
+            case 0xEE: /* FLDZ */
+               DIP("fldz\n");
+               fp_push();
+               /* put_ST(0, IRExpr_Const(IRConst_F64(0.0))); */
+               put_ST(0, IRExpr_Const(IRConst_F64i(0x0000000000000000ULL)));
+               break;
+
 //..             case 0xF0: /* F2XM1 */
 //..                DIP("f2xm1\n");
 //..                put_ST_UNCHECKED(0, unop(Iop_2xm1F64, get_ST(0)));
@@ -4857,18 +4860,18 @@ ULong dis_FPU ( Bool* decode_ok, Prefix pfx, ULong delta )
       }
    }
 
-//..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDB opcodes +-+-+-+-+-+-+-+ */
-//..    else
-//..    if (first_opcode == 0xDB) {
-//..       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)) {
-//.. 
+   /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDB opcodes +-+-+-+-+-+-+-+ */
+   else
+   if (first_opcode == 0xDB) {
+      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: /* FILD m32int */
 //..                DIP("fildl %s\n", dis_buf);
 //..                fp_push();
@@ -4940,18 +4943,18 @@ ULong dis_FPU ( Bool* decode_ok, Prefix pfx, ULong delta )
 //..                DIP("fstpt\n %s", dis_buf);
 //..                break;
 //..             }
-//.. 
-//..             default:
-//..                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
-//..                vex_printf("first_opcode == 0xDB\n");
-//..                goto decode_fail;
-//..          }
-//.. 
-//..       } else {
-//.. 
-//..          delta++;
-//..          switch (modrm) {
-//.. 
+
+            default:
+               vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+               vex_printf("first_opcode == 0xDB\n");
+               goto decode_fail;
+         }
+
+      } else {
+
+         delta++;
+         switch (modrm) {
+
 //..             case 0xC0 ... 0xC7: /* FCMOVNB ST(i), ST(0) */
 //..                r_src = (UInt)modrm - 0xC0;
 //..                DIP("fcmovnb %%st(%d), %%st(0)\n", r_src);
@@ -5025,21 +5028,21 @@ ULong dis_FPU ( Bool* decode_ok, Prefix pfx, ULong delta )
 //..                DIP("fninit\n");
 //..                break;
 //..             }
-//.. 
-//..             case 0xE8 ... 0xEF: /* FUCOMI %st(0),%st(?) */
-//..                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xE8, False );
-//..                break;
-//.. 
+
+            case 0xE8 ... 0xEF: /* FUCOMI %st(0),%st(?) */
+               fp_do_ucomi_ST0_STi( (UInt)modrm - 0xE8, False );
+               break;
+
 //..             case 0xF0 ... 0xF7: /* FCOMI %st(0),%st(?) */
 //..                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xF0, False );
 //..                break;
-//.. 
-//..             default:
-//..                goto decode_fail;
-//..          }
-//..       }
-//..    }
-//.. 
+
+            default:
+               goto decode_fail;
+         }
+      }
+   }
+
 //..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDC opcodes +-+-+-+-+-+-+-+ */
 //..    else
 //..    if (first_opcode == 0xDC) {
@@ -5166,10 +5169,10 @@ ULong dis_FPU ( Bool* decode_ok, Prefix pfx, ULong delta )
                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 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);
@@ -5458,20 +5461,20 @@ ULong dis_FPU ( Bool* decode_ok, Prefix pfx, ULong delta )
 //.. 
 //..       }
 //..    }
-//.. 
-//..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDF opcodes +-+-+-+-+-+-+-+ */
-//..    else
-//..    if (first_opcode == 0xDF) {
-//.. 
-//..       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)) {
-//.. 
+
+   /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDF opcodes +-+-+-+-+-+-+-+ */
+   else
+   if (first_opcode == 0xDF) {
+
+      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: /* FILD m16int */
 //..                DIP("fildw %s\n", dis_buf);
 //..                fp_push();
@@ -5507,18 +5510,24 @@ ULong dis_FPU ( Bool* decode_ok, Prefix pfx, ULong delta )
 //..                         binop(Iop_F64toI64, get_roundingmode(), get_ST(0)) );
 //..                fp_pop();
 //..                break;
-//.. 
-//..             default:
-//..                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
-//..                vex_printf("first_opcode == 0xDF\n");
-//..                goto decode_fail;
-//..          }
-//.. 
-//..       } else {
-//.. 
-//..          delta++;
-//..          switch (modrm) {
-//.. 
+
+            default:
+               vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+               vex_printf("first_opcode == 0xDF\n");
+               goto decode_fail;
+         }
+
+      } else {
+
+         delta++;
+         switch (modrm) {
+
+            case 0xC0: /* FFREEP %st(0) */
+               DIP("ffreep %%st(%d)\n", 0);
+               put_ST_TAG ( 0, mkU8(0) );
+               fp_pop();
+               break;
+
 //..             case 0xE0: /* FNSTSW %ax */
 //..                DIP("fnstsw %%ax\n");
 //..                /* Invent a plausible-looking FPU status word value and
@@ -5543,13 +5552,13 @@ ULong dis_FPU ( Bool* decode_ok, Prefix pfx, ULong delta )
 //..                /* not really right since COMIP != UCOMIP */
 //..                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xF0, True );
 //..                break;
-//.. 
-//..             default: 
-//..                goto decode_fail;
-//..          }
-//..       }
-//.. 
-//..    }
+
+            default: 
+               goto decode_fail;
+         }
+      }
+
+   }
 
    else
       goto decode_fail; //vpanic("dis_FPU(amd64): invalid primary opcode");
@@ -7936,41 +7945,47 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..       delta = dis_SSEcmp_E_to_G( sorb, delta+3, "cmpss", False, 4 );
 //..       goto decode_success;
 //..    }
-//.. 
-//..    /* 0F 2F = COMISS  -- 32F0x4 comparison G,E, and set ZCP */
-//..    /* 0F 2E = UCOMISS -- 32F0x4 comparison G,E, and set ZCP */
-//..    if (sz == 4 && insn[0] == 0x0F && (insn[1] == 0x2F || insn[1] == 0x2E)) {
-//..       IRTemp argL = newTemp(Ity_F32);
-//..       IRTemp argR = newTemp(Ity_F32);
-//..       modrm = getUChar(delta+2);
-//..       if (epartIsReg(modrm)) {
-//..          assign( argR, getXMMRegLane32F( eregOfRM(modrm), 0/*lowest lane*/ ) );
-//..          delta += 2+1;
-//..          DIP("[u]comiss %s,%s\n", nameXMMReg(eregOfRM(modrm)),
-//..                                   nameXMMReg(gregOfRM(modrm)) );
-//..       } else {
-//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
-//..    assign( argR, loadLE(Ity_F32, mkexpr(addr)) );
-//..          delta += 2+alen;
-//..          DIP("[u]comiss %s,%s\n", dis_buf,
-//..                                   nameXMMReg(gregOfRM(modrm)) );
-//..       }
-//..       assign( argL, getXMMRegLane32F( gregOfRM(modrm), 0/*lowest lane*/ ) );
-//.. 
-//..       stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
-//..       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
-//..       stmt( IRStmt_Put( 
-//..                OFFB_CC_DEP1,
-//..                binop( Iop_And32,
-//..                       binop(Iop_CmpF64, 
-//..                             unop(Iop_F32toF64,mkexpr(argL)),
-//..                             unop(Iop_F32toF64,mkexpr(argR))),
-//..                       mkU32(0x45)
-//..           )));
-//.. 
-//..       goto decode_success;
-//..    }
-//.. 
+
+   /* 0F 2F = COMISS  -- 32F0x4 comparison G,E, and set ZCP */
+   /* 0F 2E = UCOMISS -- 32F0x4 comparison G,E, and set ZCP */
+   if (haveNo66noF2noF3(pfx) && sz == 4 
+       && insn[0] == 0x0F && (insn[1] == 0x2F || insn[1] == 0x2E)) {
+      IRTemp argL = newTemp(Ity_F32);
+      IRTemp argR = newTemp(Ity_F32);
+      modrm = getUChar(delta+2);
+      if (epartIsReg(modrm)) {
+         assign( argR, getXMMRegLane32F( eregOfRexRM(pfx,modrm), 
+                                         0/*lowest lane*/ ) );
+         delta += 2+1;
+         DIP("%scomiss %s,%s\n", insn[1]==0x2E ? "u" : "",
+                                 nameXMMReg(eregOfRexRM(pfx,modrm)),
+                                 nameXMMReg(gregOfRexRM(pfx,modrm)) );
+      } else {
+         addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
+        assign( argR, loadLE(Ity_F32, mkexpr(addr)) );
+         delta += 2+alen;
+         DIP("%scomiss %s,%s\n", insn[1]==0x2E ? "u" : "",
+                                 dis_buf,
+                                 nameXMMReg(gregOfRexRM(pfx,modrm)) );
+      }
+      assign( argL, getXMMRegLane32F( gregOfRexRM(pfx,modrm), 
+                                      0/*lowest lane*/ ) );
+
+      stmt( IRStmt_Put( OFFB_CC_OP,   mkU64(AMD64G_CC_OP_COPY) ));
+      stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
+      stmt( IRStmt_Put( 
+               OFFB_CC_DEP1,
+               binop( Iop_And64,
+                      unop( Iop_32Uto64,
+                            binop(Iop_CmpF64, 
+                                  unop(Iop_F32toF64,mkexpr(argL)),
+                                  unop(Iop_F32toF64,mkexpr(argR)))),
+                      mkU64(0x45)
+          )));
+
+      goto decode_success;
+   }
+
 //..    /* 0F 2A = CVTPI2PS -- convert 2 x I32 in mem/mmx to 2 x F32 in low
 //..       half xmm */
 //..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x2A) {
@@ -8031,7 +8046,6 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
             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;
@@ -8166,14 +8180,14 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "divps", Iop_Div32Fx4 );
 //..       goto decode_success;
 //..    }
-//.. 
-//..    /* F3 0F 5E = DIVSS -- div 32F0x4 from R/M to R */
-//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5E) {
-//..       vassert(sz == 4);
-//..       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "divss", Iop_Div32F0x4 );
-//..       goto decode_success;
-//..    }
-//.. 
+
+   /* F3 0F 5E = DIVSS -- div 32F0x4 from R/M to R */
+   if (haveF3no66noF2(pfx) && sz == 4
+       && insn[0] == 0x0F && insn[1] == 0x5E) {
+      delta = dis_SSE_E_to_G_lo32( pfx, delta+2, "divss", Iop_Div32F0x4 );
+      goto decode_success;
+   }
+
 //..    /* 0F AE /2 = LDMXCSR m32 -- load %mxcsr */
 //..    if (insn[0] == 0x0F && insn[1] == 0xAE
 //..        && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 2) {
@@ -8971,7 +8985,7 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 
    /* 66 0F 2F = COMISD  -- 64F0x2 comparison G,E, and set ZCP */
    /* 66 0F 2E = UCOMISD -- 64F0x2 comparison G,E, and set ZCP */
-   if (have66noF2noF3(pfx) 
+   if (have66noF2noF3(pfx) && sz == 2
        && insn[0] == 0x0F && (insn[1] == 0x2F || insn[1] == 0x2E)) {
       IRTemp argL = newTemp(Ity_F64);
       IRTemp argR = newTemp(Ity_F64);
@@ -9456,32 +9470,32 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
       goto decode_success;
    }
 
-//..    /* F3 0F 5A = CVTSS2SD -- convert F32 in mem/low 1/4 xmm to F64 in
-//..       low half xmm(G) */
-//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5A) {
-//..       IRTemp f32lo = newTemp(Ity_F32);
-//..       vassert(sz == 4);
-//.. 
-//..       modrm = getUChar(delta+3);
-//..       if (epartIsReg(modrm)) {
-//..          delta += 3+1;
-//..          assign(f32lo, getXMMRegLane32F(eregOfRM(modrm), 0));
-//..          DIP("cvtss2sd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
-//..                                  nameXMMReg(gregOfRM(modrm)));
-//..       } else {
-//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
-//..          assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
-//..          delta += 3+alen;
-//..          DIP("cvtss2sd %s,%s\n", dis_buf,
-//..                                  nameXMMReg(gregOfRM(modrm)));
-//..       }
-//.. 
-//..       putXMMRegLane64F( gregOfRM(modrm), 0, 
-//..                         unop( Iop_F32toF64, mkexpr(f32lo) ) );
-//.. 
-//..       goto decode_success;
-//..    }
-//.. 
+   /* F3 0F 5A = CVTSS2SD -- convert F32 in mem/low 1/4 xmm to F64 in
+      low half xmm(G) */
+   if (haveF3no66noF2(pfx) && sz == 4
+       && insn[0] == 0x0F && insn[1] == 0x5A) {
+      IRTemp f32lo = newTemp(Ity_F32);
+
+      modrm = getUChar(delta+2);
+      if (epartIsReg(modrm)) {
+         delta += 2+1;
+         assign(f32lo, getXMMRegLane32F(eregOfRexRM(pfx,modrm), 0));
+         DIP("cvtss2sd %s,%s\n", nameXMMReg(eregOfRexRM(pfx,modrm)),
+                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
+      } else {
+         addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 );
+         assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
+         delta += 2+alen;
+         DIP("cvtss2sd %s,%s\n", dis_buf,
+                                 nameXMMReg(gregOfRexRM(pfx,modrm)));
+      }
+
+      putXMMRegLane64F( gregOfRexRM(pfx,modrm), 0, 
+                        unop( Iop_F32toF64, mkexpr(f32lo) ) );
+
+      goto decode_success;
+   }
+
 //..    /* 66 0F E6 = CVTTPD2DQ -- convert 2 x F64 in mem/xmm to 2 x I32 in
 //..       lo half xmm(G), and zero upper half, rounding towards zero */
 //..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE6) {
@@ -9612,13 +9626,13 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "minpd", Iop_Min64Fx2 );
 //..       goto decode_success;
 //..    }
-//.. 
-//..    /* F2 0F 5D = MINSD -- min 64F0x2 from R/M to R */
-//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5D) {
-//..       vassert(sz == 4);
-//..       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "minsd", Iop_Min64F0x2 );
-//..       goto decode_success;
-//..    }
+
+   /* F2 0F 5D = MINSD -- min 64F0x2 from R/M to R */
+   if (haveF2no66noF3(pfx) && sz == 4
+       && insn[0] == 0x0F && insn[1] == 0x5D) {
+      delta = dis_SSE_E_to_G_lo64( pfx, delta+2, "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). */
index d3e8c46639bfd9b61a129a171fd7e5e056fd66bd..ff678e5adc123d75e62d9008765df540f7d6891f 100644 (file)
@@ -3100,7 +3100,7 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i )
       *p++ = 0x0F;
       switch (i->Ain.Sse32FLo.op) {
          case Asse_ADDF:   *p++ = 0x58; break;
-//..          case Xsse_DIVF:   *p++ = 0x5E; break;
+         case Asse_DIVF:   *p++ = 0x5E; break;
 //..          case Xsse_MAXF:   *p++ = 0x5F; break;
 //..          case Xsse_MINF:   *p++ = 0x5D; break;
          case Asse_MULF:   *p++ = 0x59; break;
@@ -3130,7 +3130,7 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i )
          case Asse_ADDF:   *p++ = 0x58; break;
          case Asse_DIVF:   *p++ = 0x5E; break;
          case Asse_MAXF:   *p++ = 0x5F; break;
-//..          case Xsse_MINF:   *p++ = 0x5D; break;
+         case Asse_MINF:   *p++ = 0x5D; break;
          case Asse_MULF:   *p++ = 0x59; break;
 //..          case Xsse_RCPF:   *p++ = 0x53; break;
 //..          case Xsse_RSQRTF: *p++ = 0x52; break;
index 01718ddec3c0ba68bc45c05bbfa8c1cf5ceae8d7..47e3f6759d57ddfcad7c9da72e13c80a9316e9ba 100644 (file)
@@ -2575,18 +2575,18 @@ 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);
-//..    }
-//.. 
-//..    if (e->tag == Iex_LDle) {
-//..       X86AMode* am;
-//..       HReg res = newVRegF(env);
-//..       vassert(e->Iex.LDle.ty == Ity_F32);
-//..       am = iselIntExpr_AMode(env, e->Iex.LDle.addr);
-//..       addInstr(env, X86Instr_FpLdSt(True/*load*/, 4, res, am));
-//..       return res;
-//..    }
+   if (e->tag == Iex_Tmp) {
+      return lookupIRTemp(env, e->Iex.Tmp.tmp);
+   }
+
+   if (e->tag == Iex_LDle) {
+      AMD64AMode* am;
+      HReg res = newVRegV(env);
+      vassert(e->Iex.LDle.ty == Ity_F32);
+      am = iselIntExpr_AMode(env, e->Iex.LDle.addr);
+      addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 4, res, am));
+      return res;
+   }
 
    if (e->tag == Iex_Binop
        && e->Iex.Binop.op == Iop_F64toF32) {
@@ -2601,14 +2601,14 @@ static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
       return dst;
    }
 
-//..    if (e->tag == Iex_Get) {
-//..       X86AMode* am = X86AMode_IR( e->Iex.Get.offset,
-//..                                   hregX86_EBP() );
-//..       HReg res = newVRegF(env);
-//..       addInstr(env, X86Instr_FpLdSt( True/*load*/, 4, res, am ));
-//..       return res;
-//..    }
-//.. 
+   if (e->tag == Iex_Get) {
+      AMD64AMode* am = AMD64AMode_IR( e->Iex.Get.offset,
+                                       hregAMD64_RBP() );
+      HReg res = newVRegV(env);
+      addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 4, res, am ));
+      return res;
+   }
+
 //..    if (e->tag == Iex_Unop
 //..        && e->Iex.Unop.op == Iop_ReinterpI32asF32) {
 //..        /* Given an I32, produce an IEEE754 float with the same bit
@@ -2835,9 +2835,9 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
 //..          return res;
 //..       }
 //..    }
-//.. 
-//..    if (e->tag == Iex_Unop) {
-//..       switch (e->Iex.Unop.op) {
+
+   if (e->tag == Iex_Unop) {
+      switch (e->Iex.Unop.op) {
 //..          case Iop_I32toF64: {
 //..             HReg dst = newVRegF(env);
 //..             HReg ri  = iselIntExpr_R(env, e->Iex.Unop.arg);
@@ -2846,7 +2846,7 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
 //..             addInstr(env, X86Instr_FpLdStI(
 //..                              True/*load*/, 4, dst, 
 //..                              X86AMode_IR(0, hregX86_ESP())));
-//..       add_to_esp(env, 4);
+//..             add_to_esp(env, 4);
 //..             return dst;
 //..          }
 //..          case Iop_ReinterpI64asF64: {
@@ -2854,7 +2854,7 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
 //..                bit pattern. */
 //..             HReg dst = newVRegF(env);
 //..             HReg rHi, rLo;
-//..       iselInt64Expr( &rHi, &rLo, env, e->Iex.Unop.arg);
+//..             iselInt64Expr( &rHi, &rLo, env, e->Iex.Unop.arg);
 //..             /* paranoia */
 //..             set_FPU_rounding_default(env);
 //..             addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));
@@ -2862,18 +2862,21 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
 //..             addInstr(env, X86Instr_FpLdSt(
 //..                              True/*load*/, 8, dst, 
 //..                              X86AMode_IR(0, hregX86_ESP())));
-//..       add_to_esp(env, 8);
+//..             add_to_esp(env, 8);
 //..             return dst;
-//..    }
-//..          case Iop_F32toF64: {
-//..             /* this is a no-op */
-//..             HReg res = iselFltExpr(env, e->Iex.Unop.arg);
-//..             return res;
-//..    }
-//..          default: 
-//..             break;
-//..       }
-//..    }
+//..          }
+         case Iop_F32toF64: {
+            HReg f64 = newVRegV(env);
+            /* this shouldn't be necessary, but be paranoid ... */
+            set_SSE_rounding_default(env);
+            HReg f32 = iselFltExpr(env, e->Iex.Unop.arg);
+            addInstr(env, AMD64Instr_SseSDSS(False/*S->D*/, f32, f64));
+            return f64;
+         }
+         default: 
+            break;
+      }
+   }
 
    /* --------- MULTIPLEX --------- */
    if (e->tag == Iex_Mux0X) {
@@ -3223,7 +3226,7 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
 //..       case Iop_CmpLT32F0x4: op = Xsse_CMPLTF; goto do_32F0x4;
 //..       case Iop_CmpLE32F0x4: op = Xsse_CMPLEF; goto do_32F0x4;
       case Iop_Add32F0x4:   op = Asse_ADDF;   goto do_32F0x4;
-//..       case Iop_Div32F0x4:   op = Xsse_DIVF;   goto do_32F0x4;
+      case Iop_Div32F0x4:   op = Asse_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 = Asse_MULF;   goto do_32F0x4;
@@ -3243,7 +3246,7 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
       case Iop_Add64F0x2:   op = Asse_ADDF;   goto do_64F0x2;
       case Iop_Div64F0x2:   op = Asse_DIVF;   goto do_64F0x2;
       case Iop_Max64F0x2:   op = Asse_MAXF;   goto do_64F0x2;
-//..       case Iop_Min64F0x2:   op = Xsse_MINF;   goto do_64F0x2;
+      case Iop_Min64F0x2:   op = Asse_MINF;   goto do_64F0x2;
       case Iop_Mul64F0x2:   op = Asse_MULF;   goto do_64F0x2;
       case Iop_Sub64F0x2:   op = Asse_SUBF;   goto do_64F0x2;
       do_64F0x2: {
@@ -3416,11 +3419,11 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
          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));
-//..          return;
-//..       }
+      if (tyd == Ity_F32) {
+         HReg r = iselFltExpr(env, stmt->Ist.STle.data);
+         addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 4, r, am));
+         return;
+      }
 //..       if (tyd == Ity_I64) {
 //..          HReg vHi, vLo, rA;
 //..          iselInt64Expr(&vHi, &vLo, env, stmt->Ist.STle.data);
@@ -3548,12 +3551,12 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
          addInstr(env, mk_vMOVsd_RR(src, dst));
          return;
       }
-//..       if (ty == Ity_F32) {
-//..          HReg dst = lookupIRTemp(env, tmp);
-//..          HReg src = iselFltExpr(env, stmt->Ist.Tmp.data);
-//..          addInstr(env, X86Instr_FpUnary(Xfp_MOV,src,dst));
-//..          return;
-//..       }
+      if (ty == Ity_F32) {
+         HReg dst = lookupIRTemp(env, tmp);
+         HReg src = iselFltExpr(env, stmt->Ist.Tmp.data);
+         addInstr(env, mk_vMOVsd_RR(src, dst));
+         return;
+      }
       if (ty == Ity_V128) {
          HReg dst = lookupIRTemp(env, tmp);
          HReg src = iselVecExpr(env, stmt->Ist.Tmp.data);