From: Julian Seward Date: Thu, 9 Sep 2004 22:43:51 +0000 (+0000) Subject: Various more x86 FP cases. X-Git-Tag: svn/VALGRIND_3_0_1^2~1086 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=43428ac1441b8233b27cfed9f77c834c5f0cc0d5;p=thirdparty%2Fvalgrind.git Various more x86 FP cases. git-svn-id: svn://svn.valgrind.org/vex/trunk@248 --- diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index 1b8fb64cb4..b11605f86a 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -3283,7 +3283,7 @@ static void fp_pop ( void ) and describe FP instructions. */ -/* ST(0) = ST(0) `op` mem64(addr) (when dbl==True) +/* ST(0) = ST(0) `op` mem64/32(addr) Need to check ST(0)'s tag on read, but not on write. */ static @@ -3292,10 +3292,41 @@ void fp_do_op_mem_ST_0 ( IRTemp addr, UChar* op_txt, UChar* dis_buf, { DIP("f%s%c %s", op_txt, dbl?'l':'s', dis_buf); if (dbl) { - put_ST_UNCHECKED(0, binop(op, get_ST(0), loadLE(Ity_F64,mkexpr(addr)))); + put_ST_UNCHECKED(0, + binop( op, + get_ST(0), + loadLE(Ity_F64,mkexpr(addr)) + )); } else { - put_ST_UNCHECKED(0, binop(op, get_ST(0), - unop(Iop_F32toF64,loadLE(Ity_F32,mkexpr(addr))))); + put_ST_UNCHECKED(0, + binop( op, + get_ST(0), + unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr))) + )); + } +} + + +/* ST(0) = mem64/32(addr) `op` ST(0) + Need to check ST(0)'s tag on read, but not on write. +*/ +static +void fp_do_oprev_mem_ST_0 ( IRTemp addr, UChar* op_txt, UChar* dis_buf, + IROp op, Bool dbl ) +{ + DIP("f%s%c %s", op_txt, dbl?'l':'s', dis_buf); + if (dbl) { + put_ST_UNCHECKED(0, + binop( op, + loadLE(Ity_F64,mkexpr(addr)), + get_ST(0) + )); + } else { + put_ST_UNCHECKED(0, + binop( op, + unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr))), + get_ST(0) + )); } } @@ -3358,6 +3389,10 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) switch (gregOfRM(modrm)) { + case 0: /* FADD single-real */ + fp_do_op_mem_ST_0 ( addr, "add", dis_buf, Iop_AddF64, False ); + break; + case 1: /* FMUL single-real */ fp_do_op_mem_ST_0 ( addr, "mul", dis_buf, Iop_MulF64, False ); break; @@ -3379,10 +3414,22 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) fp_do_op_ST_ST ( "add", Iop_AddF64, modrm - 0xC0, 0, False ); break; + case 0xC8 ... 0xCF: /* FMUL %st(?),%st(0) */ + fp_do_op_ST_ST ( "mul", Iop_MulF64, modrm - 0xC8, 0, False ); + break; + case 0xE0 ... 0xE7: /* FSUB %st(?),%st(0) */ fp_do_op_ST_ST ( "sub", Iop_SubF64, modrm - 0xE0, 0, False ); break; + case 0xF0 ... 0xF7: /* FDIV %st(?),%st(0) */ + fp_do_op_ST_ST ( "div", Iop_DivF64, modrm - 0xF0, 0, False ); + break; + + case 0xF8 ... 0xFF: /* FDIVR %st(?),%st(0) */ + fp_do_oprev_ST_ST ( "divr", Iop_DivF64, modrm - 0xF8, 0, False ); + break; + default: goto decode_fail; } @@ -3557,6 +3604,15 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) delta++; switch (modrm) { + case 0xC8 ... 0xCF: /* FCMOVE(Z) ST(i), ST(0) */ + r_src = (UInt)modrm - 0xC8; + DIP("fcmovz %%st(%d), %%st(0)", r_src); + put_ST_UNCHECKED(0, + IRExpr_Mux0X( + unop(Iop_1Uto8,calculate_condition(CondZ)), + get_ST(0), get_ST(r_src)) ); + break; + case 0xE9: /* FUCOMPP %st(0),%st(1) */ DIP("fucompp %%st(0),%%st(1)\n"); put_C320( binop(Iop_Shl32, @@ -3640,6 +3696,10 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) fp_do_op_mem_ST_0 ( addr, "sub", dis_buf, Iop_SubF64, True ); break; + case 5: /* FSUBR double-real */ + fp_do_oprev_mem_ST_0 ( addr, "subr", dis_buf, Iop_SubF64, True ); + break; + case 6: /* FDIV double-real */ fp_do_op_mem_ST_0 ( addr, "div", dis_buf, Iop_DivF64, True ); break; @@ -3655,6 +3715,10 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) delta++; switch (modrm) { + case 0xC0 ... 0xC7: /* FADD %st(0),%st(?) */ + fp_do_op_ST_ST ( "add", Iop_AddF64, 0, modrm - 0xC0, False ); + break; + case 0xC8 ... 0xCF: /* FMUL %st(0),%st(?) */ fp_do_op_ST_ST ( "mul", Iop_MulF64, 0, modrm - 0xC8, False ); break; @@ -3770,6 +3834,10 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) fp_do_oprev_ST_ST ( "subr", Iop_SubF64, 0, modrm - 0xE0, True ); break; + case 0xE8 ... 0xEF: /* FSUBP %st(0),%st(?) */ + fp_do_op_ST_ST ( "sub", Iop_SubF64, 0, modrm - 0xE8, True ); + break; + case 0xF0 ... 0xF7: /* FDIVRP %st(0),%st(?) */ fp_do_oprev_ST_ST ( "divr", Iop_DivF64, 0, modrm - 0xF0, True ); break;