From: Julian Seward Date: Sat, 11 Oct 2008 10:07:55 +0000 (+0000) Subject: Support FPREM1 on amd64. Fixes #172563. X-Git-Tag: svn/VALGRIND_3_4_1^2~15 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=723e4de0a86793d92eea7add2fd0859cb002d87d;p=thirdparty%2Fvalgrind.git Support FPREM1 on amd64. Fixes #172563. git-svn-id: svn://svn.valgrind.org/vex/trunk@1865 --- diff --git a/VEX/priv/guest-amd64/toIR.c b/VEX/priv/guest-amd64/toIR.c index 0e644ccbeb..1a578f6f03 100644 --- a/VEX/priv/guest-amd64/toIR.c +++ b/VEX/priv/guest-amd64/toIR.c @@ -4937,19 +4937,27 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok, break; } -//.. case 0xF5: { /* FPREM1 -- IEEE compliant */ -//.. IRTemp a1 = newTemp(Ity_F64); -//.. IRTemp a2 = newTemp(Ity_F64); -//.. DIP("fprem1\n"); -//.. /* Do FPREM1 twice, once to get the remainder, and once -//.. to get the C3210 flag values. */ -//.. assign( a1, get_ST(0) ); -//.. assign( a2, get_ST(1) ); -//.. put_ST_UNCHECKED(0, binop(Iop_PRem1F64, -//.. mkexpr(a1), mkexpr(a2))); -//.. put_C3210( binop(Iop_PRem1C3210F64, mkexpr(a1), mkexpr(a2)) ); -//.. break; -//.. } + case 0xF5: { /* FPREM1 -- IEEE compliant */ + IRTemp a1 = newTemp(Ity_F64); + IRTemp a2 = newTemp(Ity_F64); + DIP("fprem1\n"); + /* Do FPREM1 twice, once to get the remainder, and once + to get the C3210 flag values. */ + assign( a1, get_ST(0) ); + assign( a2, get_ST(1) ); + put_ST_UNCHECKED(0, + triop(Iop_PRem1F64, + get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */ + mkexpr(a1), + mkexpr(a2))); + put_C3210( + unop(Iop_32Uto64, + triop(Iop_PRem1C3210F64, + get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */ + mkexpr(a1), + mkexpr(a2)) )); + break; + } case 0xF7: /* FINCSTP */ DIP("fincstp\n"); diff --git a/VEX/priv/host-amd64/hdefs.c b/VEX/priv/host-amd64/hdefs.c index c5327aa0ad..55707c8818 100644 --- a/VEX/priv/host-amd64/hdefs.c +++ b/VEX/priv/host-amd64/hdefs.c @@ -549,7 +549,7 @@ HChar* showA87FpOp ( A87FpOp op ) { case Afp_YL2X: return "yl2x"; case Afp_YL2XP1: return "yl2xp1"; case Afp_PREM: return "prem"; -//.. case Xfp_PREM1: return "prem1"; + case Afp_PREM1: return "prem1"; case Afp_SQRT: return "sqrt"; //.. case Xfp_ABS: return "abs"; //.. case Xfp_NEG: return "chs"; @@ -2885,6 +2885,7 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i, case Afp_YL2X: *p++ = 0xD9; *p++ = 0xF1; break; case Afp_YL2XP1: *p++ = 0xD9; *p++ = 0xF9; break; case Afp_PREM: *p++ = 0xD9; *p++ = 0xF8; break; + case Afp_PREM1: *p++ = 0xD9; *p++ = 0xF5; break; default: goto bad; } goto done; diff --git a/VEX/priv/host-amd64/hdefs.h b/VEX/priv/host-amd64/hdefs.h index bc88687b5e..eace7b3d59 100644 --- a/VEX/priv/host-amd64/hdefs.h +++ b/VEX/priv/host-amd64/hdefs.h @@ -307,7 +307,7 @@ typedef enum { Afp_INVALID, /* Binary */ - Afp_SCALE, Afp_ATAN, Afp_YL2X, Afp_YL2XP1, Afp_PREM, + Afp_SCALE, Afp_ATAN, Afp_YL2X, Afp_YL2XP1, Afp_PREM, Afp_PREM1, /* Unary */ Afp_SQRT, Afp_SIN, Afp_COS, Afp_TAN, diff --git a/VEX/priv/host-amd64/isel.c b/VEX/priv/host-amd64/isel.c index 26af4935ba..88777b8823 100644 --- a/VEX/priv/host-amd64/isel.c +++ b/VEX/priv/host-amd64/isel.c @@ -1761,7 +1761,8 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) case Iex_Triop: { /* C3210 flags following FPU partial remainder (fprem), both IEEE compliant (PREM1) and non-IEEE compliant (PREM). */ - if (e->Iex.Triop.op == Iop_PRemC3210F64) { + if (e->Iex.Triop.op == Iop_PRemC3210F64 + || e->Iex.Triop.op == Iop_PRem1C3210F64) { AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP()); HReg arg1 = iselDblExpr(env, e->Iex.Triop.arg2); HReg arg2 = iselDblExpr(env, e->Iex.Triop.arg3); @@ -1780,6 +1781,9 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) case Iop_PRemC3210F64: addInstr(env, AMD64Instr_A87FpOp(Afp_PREM)); break; + case Iop_PRem1C3210F64: + addInstr(env, AMD64Instr_A87FpOp(Afp_PREM1)); + break; default: vassert(0); } @@ -2936,14 +2940,16 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e ) || e->Iex.Triop.op == Iop_AtanF64 || e->Iex.Triop.op == Iop_Yl2xF64 || e->Iex.Triop.op == Iop_Yl2xp1F64 - || e->Iex.Triop.op == Iop_PRemF64) + || e->Iex.Triop.op == Iop_PRemF64 + || e->Iex.Triop.op == Iop_PRem1F64) ) { AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP()); HReg arg1 = iselDblExpr(env, e->Iex.Triop.arg2); HReg arg2 = iselDblExpr(env, e->Iex.Triop.arg3); HReg dst = newVRegV(env); Bool arg2first = toBool(e->Iex.Triop.op == Iop_ScaleF64 - || e->Iex.Triop.op == Iop_PRemF64); + || e->Iex.Triop.op == Iop_PRemF64 + || e->Iex.Triop.op == Iop_PRem1F64); addInstr(env, AMD64Instr_A87Free(2)); /* one arg -> top of x87 stack */ @@ -2975,6 +2981,9 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e ) case Iop_PRemF64: addInstr(env, AMD64Instr_A87FpOp(Afp_PREM)); break; + case Iop_PRem1F64: + addInstr(env, AMD64Instr_A87FpOp(Afp_PREM1)); + break; default: vassert(0); }