|
From: <sv...@va...> - 2005-05-09 02:57:13
|
Author: sewardj
Date: 2005-05-09 03:57:08 +0100 (Mon, 09 May 2005)
New Revision: 1171
Modified:
trunk/priv/guest-amd64/gdefs.h
trunk/priv/guest-amd64/ghelpers.c
trunk/priv/guest-amd64/toIR.c
trunk/priv/host-amd64/hdefs.c
trunk/priv/host-amd64/hdefs.h
trunk/priv/host-amd64/isel.c
Log:
Even more x87 instructions.
Modified: trunk/priv/guest-amd64/gdefs.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/priv/guest-amd64/gdefs.h 2005-05-08 23:03:48 UTC (rev 1170)
+++ trunk/priv/guest-amd64/gdefs.h 2005-05-09 02:57:08 UTC (rev 1171)
@@ -97,9 +97,9 @@
// UInt arg, UInt rot_amt, UInt eflags_in, UInt sz=20
// );
=20
-//extern ULong amd64g_check_fldcw ( ULong fpucw );
+extern ULong amd64g_check_fldcw ( ULong fpucw );
=20
-//extern ULong amd64g_create_fpucw ( ULong fpround );
+extern ULong amd64g_create_fpucw ( ULong fpround );
=20
extern ULong amd64g_check_ldmxcsr ( ULong mxcsr );
=20
Modified: trunk/priv/guest-amd64/ghelpers.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/priv/guest-amd64/ghelpers.c 2005-05-08 23:03:48 UTC (rev 1170)
+++ trunk/priv/guest-amd64/ghelpers.c 2005-05-09 02:57:08 UTC (rev 1171)
@@ -1268,7 +1268,44 @@
}
=20
=20
+/* CLEAN HELPER */
+/* fpucw[15:0] contains a x87 native format FPU control word.
+ Extract from it the required FPROUND value and any resulting
+ emulation warning, and return (warn << 32) | fpround value.
+*/
+ULong amd64g_check_fldcw ( ULong fpucw )
+{
+ /* Decide on a rounding mode. fpucw[11:10] holds it. */
+ /* NOTE, encoded exactly as per enum IRRoundingMode. */
+ ULong rmode =3D (fpucw >> 10) & 3;
=20
+ /* Detect any required emulation warnings. */
+ VexEmWarn ew =3D EmWarn_NONE;
+
+ if ((fpucw & 0x3F) !=3D 0x3F) {
+ /* unmasked exceptions! */
+ ew =3D EmWarn_X86_x87exns;
+ }
+ else
+ if (((fpucw >> 8) & 3) !=3D 3) {
+ /* unsupported precision */
+ ew =3D EmWarn_X86_x87precision;
+ }
+
+ return (((ULong)ew) << 32) | ((ULong)rmode);
+}
+
+
+/* CLEAN HELPER */
+/* Given fpround as an IRRoundingMode value, create a suitable x87
+ native format FPU control word. */
+ULong amd64g_create_fpucw ( ULong fpround )
+{
+ fpround &=3D 3;
+ return 0x037F | (fpround << 10);
+}
+
+
/*---------------------------------------------------------------*/
/*--- Misc integer helpers, including rotates and CPUID. ---*/
/*---------------------------------------------------------------*/
Modified: trunk/priv/guest-amd64/toIR.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/priv/guest-amd64/toIR.c 2005-05-08 23:03:48 UTC (rev 1170)
+++ trunk/priv/guest-amd64/toIR.c 2005-05-09 02:57:08 UTC (rev 1171)
@@ -4143,11 +4143,11 @@
return unop(Iop_64to32, IRExpr_Get( OFFB_FPROUND, Ity_I64 ));
}
=20
-//.. static void put_fpround ( IRExpr* /* :: Ity_I32 */ e )
-//.. {
-//.. vassert(typeOfIRExpr(irbb->tyenv, e) =3D=3D Ity_I32);
-//.. stmt( IRStmt_Put( OFFB_FPROUND, unop(Iop_32Uto64,e) ) );
-//.. }
+static void put_fpround ( IRExpr* /* :: Ity_I32 */ e )
+{
+ vassert(typeOfIRExpr(irbb->tyenv, e) =3D=3D Ity_I32);
+ stmt( IRStmt_Put( OFFB_FPROUND, unop(Iop_32Uto64,e) ) );
+}
=20
=20
/* --------- Synthesise a 2-bit FPU rounding mode. --------- */
@@ -4617,47 +4617,47 @@
//.. DIP("fldenv %s\n", dis_buf);
//.. break;
//.. }
-//..=20
-//.. case 5: {/* FLDCW */
-//.. /* The only thing we observe in the control word is =
the
-//.. rounding mode. Therefore, pass the 16-bit value
-//.. (x87 native-format control word) to a clean helpe=
r,
-//.. getting back a 64-bit value, the lower half of wh=
ich
-//.. is the FPROUND value to store, and the upper half=
of
-//.. which is the emulation-warning token which may be
-//.. generated.
-//.. */
-//.. /* ULong x86h_check_fldcw ( UInt ); */
-//.. IRTemp t64 =3D newTemp(Ity_I64);
-//.. IRTemp ew =3D newTemp(Ity_I32);
-//.. DIP("fldcw %s\n", dis_buf);
-//.. assign( t64, mkIRExprCCall(
-//.. Ity_I64, 0/*regparms*/,=20
-//.. "x86g_check_fldcw",
-//.. &x86g_check_fldcw,=20
-//.. mkIRExprVec_1(=20
-//.. unop( Iop_16Uto32,=20
-//.. loadLE(Ity_I16, mkexpr(addr=
)))
-//.. )
-//.. )
-//.. );
-//..=20
-//.. put_fpround( unop(Iop_64to32, mkexpr(t64)) );
-//.. assign( ew, unop(Iop_64HIto32, mkexpr(t64) ) );
-//.. put_emwarn( mkexpr(ew) );
-//.. /* Finally, if an emulation warning was reported,
-//.. side-exit to the next insn, reporting the warning=
,
-//.. so that Valgrind's dispatcher sees the warning. *=
/
-//.. stmt(=20
-//.. IRStmt_Exit(
-//.. binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
-//.. Ijk_EmWarn,
-//.. IRConst_U32( ((Addr32)guest_eip_bbstart)+delta=
)
-//.. )
-//.. );
-//.. break;
-//.. }
-//..=20
+
+ case 5: {/* FLDCW */
+ /* The only thing we observe in the control word is the
+ rounding mode. Therefore, pass the 16-bit value
+ (x87 native-format control word) to a clean helper,
+ getting back a 64-bit value, the lower half of which
+ is the FPROUND value to store, and the upper half of
+ which is the emulation-warning token which may be
+ generated.
+ */
+ /* ULong amd64h_check_fldcw ( ULong ); */
+ IRTemp t64 =3D newTemp(Ity_I64);
+ IRTemp ew =3D newTemp(Ity_I32);
+ DIP("fldcw %s\n", dis_buf);
+ assign( t64, mkIRExprCCall(
+ Ity_I64, 0/*regparms*/,=20
+ "amd64g_check_fldcw",
+ &amd64g_check_fldcw,=20
+ mkIRExprVec_1(=20
+ unop( Iop_16Uto64,=20
+ loadLE(Ity_I16, mkexpr(addr)))
+ )
+ )
+ );
+
+ put_fpround( unop(Iop_64to32, mkexpr(t64)) );
+ assign( ew, unop(Iop_64HIto32, mkexpr(t64) ) );
+ put_emwarn( mkexpr(ew) );
+ /* Finally, if an emulation warning was reported,
+ side-exit to the next insn, reporting the warning,
+ so that Valgrind's dispatcher sees the warning. */
+ stmt(=20
+ IRStmt_Exit(
+ binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
+ Ijk_EmWarn,
+ IRConst_U64( guest_rip_bbstart+delta )
+ )
+ );
+ break;
+ }
+
//.. case 6: { /* FNSTENV m28 */
//.. /* Uses dirty helper:=20
//.. void x86g_do_FSTENV ( VexGuestX86State*, UInt =
) */
@@ -4697,25 +4697,25 @@
//.. DIP("fnstenv %s\n", dis_buf);
//.. break;
//.. }
-//..=20
-//.. case 7: /* FNSTCW */
-//.. /* Fake up a native x87 FPU control word. The only
-//.. thing it depends on is FPROUND[1:0], so call a cle=
an
-//.. helper to cook it up. */
-//.. /* UInt x86h_create_fpucw ( UInt fpround ) */
-//.. DIP("fnstcw %s\n", dis_buf);
-//.. storeLE(
-//.. mkexpr(addr),=20
-//.. unop( Iop_32to16,=20
-//.. mkIRExprCCall(
-//.. Ity_I32, 0/*regp*/,
-//.. "x86g_create_fpucw", &x86g_create_fpucw,=
=20
-//.. mkIRExprVec_1( get_fpround() )=20
-//.. )=20
-//.. )=20
-//.. );
-//.. break;
=20
+ case 7: /* FNSTCW */
+ /* Fake up a native x87 FPU control word. The only
+ thing it depends on is FPROUND[1:0], so call a clean
+ helper to cook it up. */
+ /* ULong x86h_create_fpucw ( ULong fpround ) */
+ DIP("fnstcw %s\n", dis_buf);
+ storeLE(
+ mkexpr(addr),=20
+ unop( Iop_64to16,=20
+ mkIRExprCCall(
+ Ity_I64, 0/*regp*/,
+ "amd64g_create_fpucw", &amd64g_create_fpucw,=20
+ mkIRExprVec_1( unop(Iop_32Uto64, get_fpround(=
)) )=20
+ )=20
+ )=20
+ );
+ break;
+
default:
vex_printf("unhandled opc_aux =3D 0x%2x\n", gregLO3ofRM(m=
odrm));
vex_printf("first_opcode =3D=3D 0xD9\n");
@@ -4837,13 +4837,13 @@
fp_pop();
break;
=20
-//.. case 0xF2: /* FPTAN */
-//.. DIP("ftan\n");
-//.. put_ST_UNCHECKED(0, unop(Iop_TanF64, get_ST(0)));
-//.. fp_push();
-//.. put_ST(0, IRExpr_Const(IRConst_F64(1.0)));
-//.. clear_C2(); /* HACK */
-//.. break;
+ case 0xF2: /* FPTAN */
+ DIP("ftan\n");
+ put_ST_UNCHECKED(0, unop(Iop_TanF64, get_ST(0)));
+ fp_push();
+ put_ST(0, IRExpr_Const(IRConst_F64(1.0)));
+ clear_C2(); /* HACK */
+ break;
=20
case 0xF3: /* FPATAN */
DIP("fpatan\n");
@@ -4885,12 +4885,12 @@
//.. break;
//.. }
//..=20
-//.. case 0xF9: /* FYL2XP1 */
-//.. DIP("fyl2xp1\n");
-//.. put_ST_UNCHECKED(1, binop(Iop_Yl2xp1F64,
-//.. get_ST(1), get_ST(0)));
-//.. fp_pop();
-//.. break;
+ case 0xF9: /* FYL2XP1 */
+ DIP("fyl2xp1\n");
+ put_ST_UNCHECKED(1, binop(Iop_Yl2xp1F64,
+ get_ST(1), get_ST(0)));
+ fp_pop();
+ break;
=20
case 0xFA: /* FSQRT */
DIP("fsqrt\n");
Modified: trunk/priv/host-amd64/hdefs.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/priv/host-amd64/hdefs.c 2005-05-08 23:03:48 UTC (rev 1170)
+++ trunk/priv/host-amd64/hdefs.c 2005-05-09 02:57:08 UTC (rev 1171)
@@ -567,7 +567,7 @@
case Afp_SCALE: return "scale";
case Afp_ATAN: return "atan";
case Afp_YL2X: return "yl2x";
-//.. case Xfp_YL2XP1: return "yl2xp1";
+ case Afp_YL2XP1: return "yl2xp1";
//.. case Xfp_PREM: return "prem";
//.. case Xfp_PREM1: return "prem1";
case Afp_SQRT: return "sqrt";
@@ -576,7 +576,7 @@
//.. case Xfp_MOV: return "mov";
case Afp_SIN: return "sin";
case Afp_COS: return "cos";
-//.. case Xfp_TAN: return "tan";
+ case Afp_TAN: return "tan";
case Afp_ROUND: return "round";
case Afp_2XM1: return "2xm1";
default: vpanic("showA87FpOp");
@@ -2836,14 +2836,16 @@
=20
case Ain_A87FpOp:
switch (i->Ain.A87FpOp.op) {
- case Afp_SQRT: *p++ =3D 0xD9; *p++ =3D 0xFA; break;
- case Afp_SIN: *p++ =3D 0xD9; *p++ =3D 0xFE; break;
- case Afp_COS: *p++ =3D 0xD9; *p++ =3D 0xFF; break;
- case Afp_ROUND: *p++ =3D 0xD9; *p++ =3D 0xFC; break;
- case Afp_2XM1: *p++ =3D 0xD9; *p++ =3D 0xF0; break;
- case Afp_SCALE: *p++ =3D 0xD9; *p++ =3D 0xFD; break;
- case Afp_ATAN: *p++ =3D 0xD9; *p++ =3D 0xF3; break;
- case Afp_YL2X: *p++ =3D 0xD9; *p++ =3D 0xF1; break;
+ case Afp_SQRT: *p++ =3D 0xD9; *p++ =3D 0xFA; break;
+ case Afp_SIN: *p++ =3D 0xD9; *p++ =3D 0xFE; break;
+ case Afp_COS: *p++ =3D 0xD9; *p++ =3D 0xFF; break;
+ case Afp_TAN: *p++ =3D 0xD9; *p++ =3D 0xF2; break;
+ case Afp_ROUND: *p++ =3D 0xD9; *p++ =3D 0xFC; break;
+ case Afp_2XM1: *p++ =3D 0xD9; *p++ =3D 0xF0; break;
+ case Afp_SCALE: *p++ =3D 0xD9; *p++ =3D 0xFD; break;
+ case Afp_ATAN: *p++ =3D 0xD9; *p++ =3D 0xF3; break;
+ case Afp_YL2X: *p++ =3D 0xD9; *p++ =3D 0xF1; break;
+ case Afp_YL2XP1: *p++ =3D 0xD9; *p++ =3D 0xF9; break;
default: goto bad;
}
goto done;
Modified: trunk/priv/host-amd64/hdefs.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/priv/host-amd64/hdefs.h 2005-05-08 23:03:48 UTC (rev 1170)
+++ trunk/priv/host-amd64/hdefs.h 2005-05-09 02:57:08 UTC (rev 1171)
@@ -297,10 +297,10 @@
Afp_INVALID,
/* Binary */
//.. Xfp_ADD, Xfp_SUB, Xfp_MUL, Xfp_DIV,=20
- Afp_SCALE, Afp_ATAN, Afp_YL2X, //Xfp_YL2XP1, Xfp_PREM, Xfp_PREM1,
+ Afp_SCALE, Afp_ATAN, Afp_YL2X, Afp_YL2XP1, //Xfp_PREM, Xfp_PREM1,
/* Unary */
Afp_SQRT, //Xfp_ABS, Xfp_NEG, Xfp_MOV,=20
- Afp_SIN, Afp_COS, //Xfp_TAN,
+ Afp_SIN, Afp_COS, Afp_TAN,
Afp_ROUND, Afp_2XM1
}
A87FpOp;
Modified: trunk/priv/host-amd64/isel.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/priv/host-amd64/isel.c 2005-05-08 23:03:48 UTC (rev 1170)
+++ trunk/priv/host-amd64/isel.c 2005-05-09 02:57:08 UTC (rev 1171)
@@ -2838,7 +2838,8 @@
if (e->tag =3D=3D Iex_Binop=20
&& (e->Iex.Binop.op =3D=3D Iop_ScaleF64
|| e->Iex.Binop.op =3D=3D Iop_AtanF64
- || e->Iex.Binop.op =3D=3D Iop_Yl2xF64)
+ || e->Iex.Binop.op =3D=3D Iop_Yl2xF64
+ || e->Iex.Binop.op =3D=3D Iop_Yl2xp1F64)
) {
AMD64AMode* m8_rsp =3D AMD64AMode_IR(-8, hregAMD64_RSP());
HReg arg1 =3D iselDblExpr(env, e->Iex.Binop.arg1);
@@ -2868,6 +2869,9 @@
case Iop_Yl2xF64:=20
addInstr(env, AMD64Instr_A87FpOp(Afp_YL2X));
break;
+ case Iop_Yl2xp1F64:=20
+ addInstr(env, AMD64Instr_A87FpOp(Afp_YL2XP1));
+ break;
default:=20
vassert(0);
}
@@ -2927,9 +2931,9 @@
//.. case Iop_NegF64: fpop =3D Xfp_NEG; break;
//.. case Iop_AbsF64: fpop =3D Xfp_ABS; break;
case Iop_SqrtF64: fpop =3D Afp_SQRT; break;
- case Iop_SinF64: fpop =3D Afp_SIN; break;
- case Iop_CosF64: fpop =3D Afp_COS; break;
-//.. case Iop_TanF64: fpop =3D Xfp_TAN; break;
+ case Iop_SinF64: fpop =3D Afp_SIN; break;
+ case Iop_CosF64: fpop =3D Afp_COS; break;
+ case Iop_TanF64: fpop =3D Afp_TAN; break;
case Iop_2xm1F64: fpop =3D Afp_2XM1; break;
default: break;
}
@@ -2937,10 +2941,15 @@
AMD64AMode* m8_rsp =3D AMD64AMode_IR(-8, hregAMD64_RSP());
HReg arg =3D iselDblExpr(env, e->Iex.Unop.arg);
HReg dst =3D newVRegV(env);
+ Int nNeeded =3D e->Iex.Unop.op=3D=3DIop_TanF64 ? 2 : 1;
addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 8, arg, m8_rsp=
));
- addInstr(env, AMD64Instr_A87Free(1));
+ addInstr(env, AMD64Instr_A87Free(nNeeded));
addInstr(env, AMD64Instr_A87PushPop(m8_rsp, True/*push*/));
addInstr(env, AMD64Instr_A87FpOp(fpop));
+ if (e->Iex.Unop.op=3D=3DIop_TanF64) {
+ /* get rid of the extra 1.0 that fptan pushes */
+ addInstr(env, AMD64Instr_A87PushPop(m8_rsp, False/*pop*/));
+ }
addInstr(env, AMD64Instr_A87PushPop(m8_rsp, False/*pop*/));
addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 8, dst, m8_rsp))=
;
return dst;
|