]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Followup to r1562: fixes for x86
authorJulian Seward <jseward@acm.org>
Fri, 3 Feb 2006 22:54:17 +0000 (22:54 +0000)
committerJulian Seward <jseward@acm.org>
Fri, 3 Feb 2006 22:54:17 +0000 (22:54 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@1564

VEX/priv/guest-x86/toIR.c
VEX/priv/host-x86/isel.c
VEX/pub/libvex_ir.h

index 2a0c20918aa84e2bc10e0d722498ec3fc22f6fd6..d9aa5cb2a8e7e3875fb9c087b0e3b670e7d20557 100644 (file)
@@ -630,6 +630,11 @@ static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
    return IRExpr_Binop(op, a1, a2);
 }
 
+static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
+{
+   return IRExpr_Triop(op, a1, a2, a3);
+}
+
 static IRExpr* mkexpr ( IRTemp tmp )
 {
    return IRExpr_Tmp(tmp);
@@ -3181,6 +3186,11 @@ static IRExpr* /* :: Ity_I32 */ get_roundingmode ( void )
    return binop( Iop_And32, get_fpround(), mkU32(3) );
 }
 
+static IRExpr* /* :: Ity_I32 */ get_FAKE_roundingmode ( void )
+{
+   return mkU32(Irrm_NEAREST);
+}
+
 
 /* --------- Get/set FP register tag bytes. --------- */
 
@@ -3317,13 +3327,15 @@ void fp_do_op_mem_ST_0 ( IRTemp addr, HChar* op_txt, HChar* dis_buf,
    DIP("f%s%c %s\n", op_txt, dbl?'l':'s', dis_buf);
    if (dbl) {
       put_ST_UNCHECKED(0, 
-         binop( op, 
+         triop( op, 
+                get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
                 get_ST(0), 
                 loadLE(Ity_F64,mkexpr(addr))
          ));
    } else {
       put_ST_UNCHECKED(0, 
-         binop( op, 
+         triop( op, 
+                get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
                 get_ST(0), 
                 unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr)))
          ));
@@ -3341,13 +3353,15 @@ void fp_do_oprev_mem_ST_0 ( IRTemp addr, HChar* op_txt, HChar* dis_buf,
    DIP("f%s%c %s\n", op_txt, dbl?'l':'s', dis_buf);
    if (dbl) {
       put_ST_UNCHECKED(0, 
-         binop( op, 
+         triop( op, 
+                get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
                 loadLE(Ity_F64,mkexpr(addr)),
                 get_ST(0)
          ));
    } else {
       put_ST_UNCHECKED(0, 
-         binop( op, 
+         triop( op, 
+                get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
                 unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr))),
                 get_ST(0)
          ));
@@ -3366,7 +3380,10 @@ void fp_do_op_ST_ST ( HChar* op_txt, IROp op, UInt st_src, UInt st_dst,
                                  (Int)st_src, (Int)st_dst );
    put_ST_UNCHECKED( 
       st_dst, 
-      binop(op, get_ST(st_dst), get_ST(st_src) ) 
+      triop( op, 
+             get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+             get_ST(st_dst), 
+             get_ST(st_src) ) 
    );
    if (pop_after)
       fp_pop();
@@ -3383,7 +3400,10 @@ void fp_do_oprev_ST_ST ( HChar* op_txt, IROp op, UInt st_src, UInt st_dst,
                                  (Int)st_src, (Int)st_dst );
    put_ST_UNCHECKED( 
       st_dst, 
-      binop(op, get_ST(st_src), get_ST(st_dst) ) 
+      triop( op, 
+             get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+             get_ST(st_src), 
+             get_ST(st_dst) ) 
    );
    if (pop_after)
       fp_pop();
@@ -3876,19 +3896,28 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta )
 
             case 0xF0: /* F2XM1 */
                DIP("f2xm1\n");
-               put_ST_UNCHECKED(0, unop(Iop_2xm1F64, get_ST(0)));
+               put_ST_UNCHECKED(0, 
+                  binop(Iop_2xm1F64, 
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+                        get_ST(0)));
                break;
 
             case 0xF1: /* FYL2X */
                DIP("fyl2x\n");
-               put_ST_UNCHECKED(1, binop(Iop_Yl2xF64,
-                                         get_ST(1), get_ST(0)));
+               put_ST_UNCHECKED(1, 
+                  triop(Iop_Yl2xF64,
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+                        get_ST(1), 
+                        get_ST(0)));
                fp_pop();
                break;
 
             case 0xF2: /* FPTAN */
                DIP("ftan\n");
-               put_ST_UNCHECKED(0, unop(Iop_TanF64, get_ST(0)));
+               put_ST_UNCHECKED(0, 
+                  binop(Iop_TanF64, 
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+                        get_ST(0)));
                fp_push();
                put_ST(0, IRExpr_Const(IRConst_F64(1.0)));
                clear_C2(); /* HACK */
@@ -3896,12 +3925,15 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta )
 
             case 0xF3: /* FPATAN */
                DIP("fpatan\n");
-               put_ST_UNCHECKED(1, binop(Iop_AtanF64,
-                                         get_ST(1), get_ST(0)));
+               put_ST_UNCHECKED(1, 
+                  triop(Iop_AtanF64,
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+                        get_ST(1), 
+                        get_ST(0)));
                fp_pop();
                break;
 
-            case 0xF4: {
+            case 0xF4: { /* FXTRACT */
                IRTemp argF = newTemp(Ity_F64);
                IRTemp sigF = newTemp(Ity_F64);
                IRTemp expF = newTemp(Ity_F64);
@@ -3968,23 +4000,35 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta )
 
             case 0xF9: /* FYL2XP1 */
                DIP("fyl2xp1\n");
-               put_ST_UNCHECKED(1, binop(Iop_Yl2xp1F64,
-                                         get_ST(1), get_ST(0)));
+               put_ST_UNCHECKED(1, 
+                  triop(Iop_Yl2xp1F64,
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+                        get_ST(1), 
+                        get_ST(0)));
                fp_pop();
                break;
 
             case 0xFA: /* FSQRT */
                DIP("fsqrt\n");
-               put_ST_UNCHECKED(0, unop(Iop_SqrtF64, get_ST(0)));
+               put_ST_UNCHECKED(0, 
+                  binop(Iop_SqrtF64, 
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+                        get_ST(0)));
                break;
 
             case 0xFB: { /* FSINCOS */
                IRTemp a1 = newTemp(Ity_F64);
                assign( a1, get_ST(0) );
                DIP("fsincos\n");
-               put_ST_UNCHECKED(0, unop(Iop_SinF64, mkexpr(a1)));
+               put_ST_UNCHECKED(0, 
+                  binop(Iop_SinF64, 
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+                        mkexpr(a1)));
                fp_push();
-               put_ST(0, unop(Iop_CosF64, mkexpr(a1)));
+               put_ST(0, 
+                  binop(Iop_CosF64,
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+                        mkexpr(a1)));
                clear_C2(); /* HACK */
                break;
             }
@@ -3997,19 +4041,28 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta )
 
             case 0xFD: /* FSCALE */
                DIP("fscale\n");
-               put_ST_UNCHECKED(0, binop(Iop_ScaleF64,
-                                         get_ST(0), get_ST(1)));
+               put_ST_UNCHECKED(0, 
+                  triop(Iop_ScaleF64,
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+                        get_ST(0), 
+                        get_ST(1)));
                break;
 
             case 0xFE: /* FSIN */
                DIP("fsin\n");
-               put_ST_UNCHECKED(0, unop(Iop_SinF64, get_ST(0)));
+               put_ST_UNCHECKED(0, 
+                  binop(Iop_SinF64, 
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+                        get_ST(0)));
                clear_C2(); /* HACK */
                break;
 
             case 0xFF: /* FCOS */
                DIP("fcos\n");
-               put_ST_UNCHECKED(0, unop(Iop_CosF64, get_ST(0)));
+               put_ST_UNCHECKED(0, 
+                  binop(Iop_CosF64, 
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+                        get_ST(0)));
                clear_C2(); /* HACK */
                break;
 
@@ -4095,7 +4148,8 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta )
 
             do_fop_m32:
                put_ST_UNCHECKED(0, 
-                  binop(fop, 
+                  triop(fop, 
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
                         get_ST(0),
                         unop(Iop_I32toF64,
                              loadLE(Ity_I32, mkexpr(addr)))));
@@ -4103,7 +4157,8 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta )
 
             do_foprev_m32:
                put_ST_UNCHECKED(0, 
-                  binop(fop, 
+                  triop(fop, 
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
                         unop(Iop_I32toF64,
                              loadLE(Ity_I32, mkexpr(addr))),
                         get_ST(0)));
@@ -4741,7 +4796,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta )
                                       get_ST(0),
                                       unop(Iop_I32toF64, 
                                          unop(Iop_16Sto32,
-                                           loadLE(Ity_I16,mkexpr(addr))))),
+                                              loadLE(Ity_I16,mkexpr(addr))))),
                                 mkU8(8)),
                           mkU32(0x4500)
                    ));
@@ -4770,7 +4825,8 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta )
 
             do_fop_m16:
                put_ST_UNCHECKED(0, 
-                  binop(fop, 
+                  triop(fop, 
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
                         get_ST(0),
                         unop(Iop_I32toF64,
                              unop(Iop_16Sto32, 
@@ -4779,7 +4835,8 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta )
 
             do_foprev_m16:
                put_ST_UNCHECKED(0, 
-                  binop(fop, 
+                  triop(fop, 
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
                         unop(Iop_I32toF64,
                              unop(Iop_16Sto32, 
                                   loadLE(Ity_I16, mkexpr(addr)))),
index 6240ae8fa01cb4f411879b86f7874117c10edff6..b30a215b35711a42cde4ecff051002d954fedc0f 100644 (file)
@@ -661,14 +661,14 @@ void set_FPU_rounding_mode ( ISelEnv* env, IRExpr* mode )
 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. */
+   /* Set dst to zero.  If dst contains a NaN then all hell might
+      break loose after the comparison.  So, first zero it. */
    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));
+   /* Doesn't that just totally suck? */
    return dst;
 }
 
@@ -2604,17 +2604,36 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
       return res;
    }
 
-   if (e->tag == Iex_Binop) {
+   if (e->tag == Iex_Triop) {
       X86FpOp fpop = Xfp_INVALID;
-      switch (e->Iex.Binop.op) {
+      switch (e->Iex.Triop.op) {
          case Iop_AddF64:    fpop = Xfp_ADD; break;
          case Iop_SubF64:    fpop = Xfp_SUB; break;
          case Iop_MulF64:    fpop = Xfp_MUL; break;
          case Iop_DivF64:    fpop = Xfp_DIV; break;
          case Iop_ScaleF64:  fpop = Xfp_SCALE; break;
-         case Iop_AtanF64:   fpop = Xfp_ATAN; break;
          case Iop_Yl2xF64:   fpop = Xfp_YL2X; break;
          case Iop_Yl2xp1F64: fpop = Xfp_YL2XP1; break;
+         case Iop_AtanF64:   fpop = Xfp_ATAN; break;
+         default: break;
+      }
+      if (fpop != Xfp_INVALID) {
+         HReg res  = newVRegF(env);
+         HReg srcL = iselDblExpr(env, e->Iex.Triop.arg2);
+         HReg srcR = iselDblExpr(env, e->Iex.Triop.arg3);
+         /* XXXROUNDINGFIXME */
+         /* set roundingmode here */
+         addInstr(env, X86Instr_FpBinary(fpop,srcL,srcR,res));
+        if (fpop != Xfp_ADD && fpop != Xfp_SUB 
+            && fpop != Xfp_MUL && fpop != Xfp_DIV)
+            roundToF64(env, res);
+         return res;
+      }
+   }
+
+   if (e->tag == Iex_Binop) {
+      X86FpOp fpop = Xfp_INVALID;
+      switch (e->Iex.Binop.op) {
          case Iop_PRemF64:   fpop = Xfp_PREM; break;
          case Iop_PRem1F64:  fpop = Xfp_PREM1; break;
          default: break;
@@ -2671,21 +2690,21 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
       return dst;
    }
 
-   if (e->tag == Iex_Unop) {
+   if (e->tag == Iex_Binop) {
       X86FpOp fpop = Xfp_INVALID;
-      switch (e->Iex.Unop.op) {
-         case Iop_NegF64:  fpop = Xfp_NEG; break;
-         case Iop_AbsF64:  fpop = Xfp_ABS; break;
-         case Iop_SqrtF64: fpop = Xfp_SQRT; break;
+      switch (e->Iex.Binop.op) {
          case Iop_SinF64:  fpop = Xfp_SIN; break;
          case Iop_CosF64:  fpop = Xfp_COS; break;
          case Iop_TanF64:  fpop = Xfp_TAN; break;
          case Iop_2xm1F64: fpop = Xfp_2XM1; break;
+         case Iop_SqrtF64: fpop = Xfp_SQRT; break;
          default: break;
       }
       if (fpop != Xfp_INVALID) {
          HReg res = newVRegF(env);
-         HReg src = iselDblExpr(env, e->Iex.Unop.arg);
+         HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
+         /* XXXROUNDINGFIXME */
+         /* set roundingmode here */
          addInstr(env, X86Instr_FpUnary(fpop,src,res));
         if (fpop != Xfp_SQRT
              && fpop != Xfp_NEG && fpop != Xfp_ABS)
@@ -2694,6 +2713,23 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
       }
    }
 
+   if (e->tag == Iex_Unop) {
+      X86FpOp fpop = Xfp_INVALID;
+      switch (e->Iex.Unop.op) {
+         case Iop_NegF64:  fpop = Xfp_NEG; break;
+         case Iop_AbsF64:  fpop = Xfp_ABS; break;
+         default: break;
+      }
+      if (fpop != Xfp_INVALID) {
+         HReg res = newVRegF(env);
+         HReg src = iselDblExpr(env, e->Iex.Unop.arg);
+         addInstr(env, X86Instr_FpUnary(fpop,src,res));
+        if (fpop != Xfp_NEG && fpop != Xfp_ABS)
+            roundToF64(env, res);
+         return res;
+      }
+   }
+
    if (e->tag == Iex_Unop) {
       switch (e->Iex.Unop.op) {
          case Iop_I32toF64: {
index aa879a571589b178fa756079727249f6640f3f98..27f92c599b4b571e479a05d3b88c03482ebd3337 100644 (file)
@@ -658,9 +658,16 @@ extern void ppIROp ( IROp );
 
 
 /* Encoding of IEEE754-specified rounding modes.  This is the same as
-   the encoding used by Intel IA32 to indicate x87 rounding mode. */
+   the encoding used by Intel IA32 to indicate x87 rounding mode.
+   Note, various front and back ends rely on the actual numerical
+   values of these, so do not change them. */
 typedef
-   enum { Irrm_NEAREST=0, Irrm_NegINF=1, Irrm_PosINF=2, Irrm_ZERO=3 }
+   enum { 
+      Irrm_NEAREST = 0, 
+      Irrm_NegINF  = 1, 
+      Irrm_PosINF  = 2, 
+      Irrm_ZERO    = 3 
+   }
    IRRoundingMode;
 
 /* Floating point comparison result values, as created by Iop_CmpF64.