]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Implement yet more x86 FP transcendental instructions.
authorJulian Seward <jseward@acm.org>
Sun, 12 Sep 2004 12:07:34 +0000 (12:07 +0000)
committerJulian Seward <jseward@acm.org>
Sun, 12 Sep 2004 12:07:34 +0000 (12:07 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@263

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

index bb0825e069c038fc80d8e6454d1dfc09fa3c3fb8..a5eec44e3cc92bfb49cf49427f6068085b47eec7 100644 (file)
@@ -3610,6 +3610,11 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
                put_ST(0, IRExpr_Const(IRConst_F64(0.0)));
                break;
 
+            case 0xF0: /* F2XM1 */
+               DIP("f2xm1\n");
+               put_ST_UNCHECKED(0, unop(Iop_2xm1F64, get_ST(0)));
+               break;
+
             case 0xF1: /* FYL2X */
                DIP("fyl2x\n");
                put_ST_UNCHECKED(1, binop(Iop_Yl2xF64,
@@ -3656,6 +3661,12 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
                   binop(Iop_RoundF64, get_roundingmode(), get_ST(0)) );
                break;
 
+            case 0xFD: /* FSCALE */
+               DIP("fscale\n");
+               put_ST_UNCHECKED(0, binop(Iop_ScaleF64,
+                                         get_ST(0), get_ST(1)));
+               break;
+
             case 0xFE: /* FSIN */
                DIP("fsin\n");
                put_ST_UNCHECKED(0, unop(Iop_SinF64, get_ST(0)));
@@ -3948,6 +3959,15 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
          delta++;
          switch (modrm) {
 
+            case 0xD0 ... 0xD7: /* FST %st(0),%st(?) */
+               r_dst = (UInt)modrm - 0xD0;
+               DIP("fst %%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));
+               break;
+
             case 0xD8 ... 0xDF: /* FSTP %st(0),%st(?) */
                r_dst = (UInt)modrm - 0xD8;
                DIP("fstp %%st(0),%%st(%d)\n", r_dst);
index 2da13506a169f323b6290674781e3ee3a3394510..73db178a2a93b291633bb4d12e4cd7ec5b95fed8 100644 (file)
@@ -420,6 +420,7 @@ Char* showX86FpOp ( X86FpOp op ) {
       case Xfp_MOV:    return "mov";
       case Xfp_SIN:    return "sin";
       case Xfp_COS:    return "cos";
+      case Xfp_2XM1:   return "2xm1";
       default: vpanic("showX86FpOp");
    }
 }
@@ -1279,6 +1280,7 @@ static UChar* do_fop1_st ( UChar* p, X86FpOp op )
       case Xfp_ROUND:  *p++ = 0xD9; *p++ = 0xFC; break;
       case Xfp_SIN:    *p++ = 0xD9; *p++ = 0xFE; break;
       case Xfp_COS:    *p++ = 0xD9; *p++ = 0xFF; break;
+      case Xfp_2XM1:   *p++ = 0xD9; *p++ = 0xF0; break;
       default: vpanic("do_fop1_st: unknown op");
    }
    return p;
@@ -1834,15 +1836,17 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
       goto done;
 
    case Xin_FpBinary:
-      if (i->Xin.FpBinary.op == Xfp_YL2X) {
+      if (i->Xin.FpBinary.op == Xfp_YL2X
+          || i->Xin.FpBinary.op == Xfp_YL2XP1) {
          /* Have to do this specially. */
          /* ffree %st7 ; fld %st(srcL) ; 
-            ffree %st7 ; fld %st(srcR+1) ; fyl2x ; fstp(1+dst) */
+            ffree %st7 ; fld %st(srcR+1) ; fyl2x{p1} ; fstp(1+dst) */
          p = do_ffree_st7(p);
          p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
          p = do_ffree_st7(p);
          p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcR));
-         *p++ = 0xD9; *p++ = 0xF1;
+         *p++ = 0xD9; 
+         *p++ = i->Xin.FpBinary.op==Xfp_YL2X ? 0xF1 : 0xF9;
          p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
          goto done;
       }
@@ -1858,16 +1862,18 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
          p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
          goto done;
       }
-      if (i->Xin.FpBinary.op == Xfp_PREM) {
+      if (i->Xin.FpBinary.op == Xfp_PREM
+          || i->Xin.FpBinary.op == Xfp_SCALE) {
          /* Have to do this specially. */
          /* ffree %st7 ; fld %st(srcR) ; 
-            ffree %st7 ; fld %st(srcL+1) ; fprem ; fstp(2+dst) ; 
+            ffree %st7 ; fld %st(srcL+1) ; fprem/fscale ; fstp(2+dst) ; 
             fincstp ; ffree %st7 */
          p = do_ffree_st7(p);
          p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcR));
          p = do_ffree_st7(p);
          p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcL));
-         *p++ = 0xD9; *p++ = 0xF8;
+         *p++ = 0xD9; 
+         *p++ = i->Xin.FpBinary.op==Xfp_PREM ? 0xF8 : 0xFD;
          p = do_fstp_st(p, 2+hregNumber(i->Xin.FpBinary.dst));
          *p++ = 0xD9; *p++ = 0xF7;
          p = do_ffree_st7(p);
index aa5061e7d9160bfe710f1ab56701cf7eca641d02..f4a25cd18d8c318817e41cee42a5e5b2e76876eb 100644 (file)
@@ -248,10 +248,10 @@ typedef
       Xfp_INVALID,
       /* Binary */
       Xfp_ADD, Xfp_SUB, Xfp_MUL, Xfp_DIV, 
-      Xfp_ATAN, Xfp_YL2X, Xfp_PREM,
+      Xfp_SCALE, Xfp_ATAN, Xfp_YL2X, Xfp_YL2XP1, Xfp_PREM,
       /* Unary */
       Xfp_SQRT, Xfp_ABS, Xfp_NEG, Xfp_MOV, Xfp_SIN, Xfp_COS,
-      Xfp_ROUND
+      Xfp_ROUND, Xfp_2XM1
    }
    X86FpOp;
 
index 00a53f69632b7877c707ab3256bbda94be0b5eca..f3c0dc4714d1cfe5ebed231e0a07935a58e72718 100644 (file)
@@ -1626,13 +1626,15 @@ static HReg iselDblExpr ( ISelEnv* env, IRExpr* e )
    if (e->tag == Iex_Binop) {
       X86FpOp fpop = Xfp_INVALID;
       switch (e->Iex.Binop.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_AtanF64: fpop = Xfp_ATAN; break;
-         case Iop_Yl2xF64: fpop = Xfp_YL2X; break;
-         case Iop_PRemF64: fpop = Xfp_PREM; break;
+         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_PRemF64:   fpop = Xfp_PREM; break;
          default: break;
       }
       if (fpop != Xfp_INVALID) {
@@ -1703,6 +1705,7 @@ static HReg iselDblExpr ( ISelEnv* env, IRExpr* e )
          case Iop_SqrtF64: fpop = Xfp_SQRT; break;
          case Iop_SinF64:  fpop = Xfp_SIN; break;
          case Iop_CosF64:  fpop = Xfp_COS; break;
+         case Iop_2xm1F64: fpop = Xfp_2XM1; break;
          default: break;
       }
       if (fpop != Xfp_INVALID) {
index dc1e76193bdd1ff64e1c53f64fbc717df66ae64a..3dd9740dfdf7101881932fb7edfd2cab2d3bf0cc 100644 (file)
@@ -135,6 +135,7 @@ void ppIROp ( IROp op )
       case Iop_MulF64:    vex_printf("MulF64"); return;
       case Iop_DivF64:    vex_printf("DivF64"); return;
 
+      case Iop_ScaleF64:     vex_printf("ScaleF64"); return;
       case Iop_AtanF64:      vex_printf("AtanF64"); return;
       case Iop_Yl2xF64:      vex_printf("Yl2xF64"); return;
       case Iop_Yl2xp1F64:    vex_printf("Yl2xp1F64"); return;
@@ -146,6 +147,7 @@ void ppIROp ( IROp op )
       case Iop_AbsF64:    vex_printf("AbsF64"); return;
       case Iop_SinF64:    vex_printf("SinF64"); return;
       case Iop_CosF64:    vex_printf("CosF64"); return;
+      case Iop_2xm1F64:   vex_printf("2xm1F64"); return;
 
       case Iop_CmpF64:    vex_printf("CmpF64"); return;
 
@@ -641,6 +643,7 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 )
       case Iop_32Uto64: UNARY(Ity_I64,Ity_I32);
       case Iop_32to8:   UNARY(Ity_I8,Ity_I32);
 
+      case Iop_ScaleF64:
       case Iop_PRemF64:
       case Iop_AtanF64:
       case Iop_Yl2xF64:
@@ -652,7 +655,7 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 )
       case Iop_CmpF64:
          BINARY(Ity_I32,Ity_F64,Ity_F64);
       case Iop_NegF64: case Iop_AbsF64: case Iop_SqrtF64:
-      case Iop_SinF64: case Iop_CosF64:
+      case Iop_SinF64: case Iop_CosF64: case Iop_2xm1F64:
          UNARY(Ity_F64,Ity_F64);
 
       case Iop_I32toF64: UNARY(Ity_F64,Ity_I32);
index c14c60046222947a5af938b3db73b269f7db3b09..cf4b58439178e4ddabdc8ad26e89ee80903fd432 100644 (file)
@@ -168,6 +168,7 @@ typedef
       Iop_Yl2xp1F64,    /* FYL2XP1, arg1 * log2(arg2+1.0)   */
       Iop_PRemF64,      /* FPREM,   remainder(arg1/arg2)    */
       Iop_PRemC3210F64, /* C3210 flags resulting from FPREM, :: I32 */
+      Iop_ScaleF64,     /* FSCALE,  arg1 * (2^RoundTowardsZero(arg2)) */
 
       /* Unary operations mandated by IEEE754. */
       Iop_NegF64, Iop_SqrtF64, 
@@ -176,6 +177,7 @@ typedef
       Iop_AbsF64,    /* FABS */
       Iop_SinF64,    /* FSIN */
       Iop_CosF64,    /* FCOS */
+      Iop_2xm1F64,   /* (2^arg - 1.0) */
 
       /* Comparison, yielding GT/LT/EQ/UN(ordered), as per the following:
             0x45 Unordered