From: Julian Seward Date: Sun, 12 Sep 2004 12:07:34 +0000 (+0000) Subject: Implement yet more x86 FP transcendental instructions. X-Git-Tag: svn/VALGRIND_3_0_1^2~1071 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=88b58c8d70e7dcae8cf0f04b96e72e87d6646bc9;p=thirdparty%2Fvalgrind.git Implement yet more x86 FP transcendental instructions. git-svn-id: svn://svn.valgrind.org/vex/trunk@263 --- diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index bb0825e069..a5eec44e3c 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -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); diff --git a/VEX/priv/host-x86/hdefs.c b/VEX/priv/host-x86/hdefs.c index 2da13506a1..73db178a2a 100644 --- a/VEX/priv/host-x86/hdefs.c +++ b/VEX/priv/host-x86/hdefs.c @@ -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); diff --git a/VEX/priv/host-x86/hdefs.h b/VEX/priv/host-x86/hdefs.h index aa5061e7d9..f4a25cd18d 100644 --- a/VEX/priv/host-x86/hdefs.h +++ b/VEX/priv/host-x86/hdefs.h @@ -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; diff --git a/VEX/priv/host-x86/isel.c b/VEX/priv/host-x86/isel.c index 00a53f6963..f3c0dc4714 100644 --- a/VEX/priv/host-x86/isel.c +++ b/VEX/priv/host-x86/isel.c @@ -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) { diff --git a/VEX/priv/ir/irdefs.c b/VEX/priv/ir/irdefs.c index dc1e76193b..3dd9740dfd 100644 --- a/VEX/priv/ir/irdefs.c +++ b/VEX/priv/ir/irdefs.c @@ -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); diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index c14c600462..cf4b584391 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -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