|
From: <sv...@va...> - 2005-06-13 12:17:35
|
Author: sewardj
Date: 2005-06-13 13:17:27 +0100 (Mon, 13 Jun 2005)
New Revision: 1206
Log:
Implement fldenv/fstenv on amd64.
Modified:
trunk/priv/guest-amd64/gdefs.h
trunk/priv/guest-amd64/ghelpers.c
trunk/priv/guest-amd64/toIR.c
trunk/priv/guest-generic/g_generic_x87.h
trunk/priv/guest-x86/ghelpers.c
trunk/priv/guest-x86/toIR.c
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-06-10 11:04:52 UTC (rev 1205)
+++ trunk/priv/guest-amd64/gdefs.h 2005-06-13 12:17:27 UTC (rev 1206)
@@ -105,6 +105,10 @@
=20
extern ULong amd64g_create_mxcsr ( ULong sseround );
=20
+extern VexEmWarn amd64g_dirtyhelper_FLDENV ( VexGuestAMD64State*, HWord =
);
+
+extern void amd64g_dirtyhelper_FSTENV ( VexGuestAMD64State*, HWord );
+
/* Translate a guest virtual_addr into a guest linear address by
consulting the supplied LDT/GDT structures. Their representation
must be as specified in pub/libvex_guest_amd64.h. To indicate a
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-06-10 11:04:52 UTC (rev 1205)
+++ trunk/priv/guest-amd64/ghelpers.c 2005-06-13 12:17:27 UTC (rev 1206)
@@ -1308,6 +1308,98 @@
}
=20
=20
+/* This is used to implement 'fldenv'. =20
+ Reads 28 bytes at x87_state[0 .. 27]. */
+/* CALLED FROM GENERATED CODE */
+/* DIRTY HELPER */
+VexEmWarn amd64g_dirtyhelper_FLDENV ( /*OUT*/VexGuestAMD64State* vex_sta=
te,
+ /*IN*/HWord x87_state)
+{
+ Int stno, preg;
+ UInt tag;
+ UChar* vexTags =3D (UChar*)(&vex_state->guest_FPTAG[0]);
+ Fpu_State* x87 =3D (Fpu_State*)x87_state;
+ UInt ftop =3D (x87->env[FP_ENV_STAT] >> 11) & 7;
+ UInt tagw =3D x87->env[FP_ENV_TAG];
+ UInt fpucw =3D x87->env[FP_ENV_CTRL];
+ ULong c3210 =3D x87->env[FP_ENV_STAT] & 0x4700;
+ VexEmWarn ew;
+ ULong fpround;
+ ULong pair;
+
+ /* Copy tags */
+ for (stno =3D 0; stno < 8; stno++) {
+ preg =3D (stno + ftop) & 7;
+ tag =3D (tagw >> (2*preg)) & 3;
+ if (tag =3D=3D 3) {
+ /* register is empty */
+ vexTags[preg] =3D 0;
+ } else {
+ /* register is non-empty */
+ vexTags[preg] =3D 1;
+ }
+ }
+
+ /* stack pointer */
+ vex_state->guest_FTOP =3D ftop;
+
+ /* status word */
+ vex_state->guest_FC3210 =3D c3210;
+
+ /* handle the control word, setting FPROUND and detecting any
+ emulation warnings. */
+ pair =3D amd64g_check_fldcw ( (ULong)fpucw );
+ fpround =3D pair & 0xFFFFFFFFULL;
+ ew =3D (VexEmWarn)(pair >> 32);
+ =20
+ vex_state->guest_FPROUND =3D fpround & 3;
+
+ /* emulation warnings --> caller */
+ return ew;
+}
+
+
+/* CALLED FROM GENERATED CODE */
+/* DIRTY HELPER */
+/* Create an x87 FPU env from the guest state, as close as we can
+ approximate it. Writes 28 bytes at x87_state[0..27]. */
+void amd64g_dirtyhelper_FSTENV ( /*IN*/VexGuestAMD64State* vex_state,
+ /*OUT*/HWord x87_state )
+{
+ Int i, stno, preg;
+ UInt tagw;
+ UChar* vexTags =3D (UChar*)(&vex_state->guest_FPTAG[0]);
+ Fpu_State* x87 =3D (Fpu_State*)x87_state;
+ UInt ftop =3D vex_state->guest_FTOP;
+ ULong c3210 =3D vex_state->guest_FC3210;
+
+ for (i =3D 0; i < 14; i++)
+ x87->env[i] =3D 0;
+
+ x87->env[1] =3D x87->env[3] =3D x87->env[5] =3D x87->env[13] =3D 0xFF=
FF;
+ x87->env[FP_ENV_STAT]=20
+ =3D toUShort(((ftop & 7) << 11) | (c3210 & 0x4700));
+ x87->env[FP_ENV_CTRL]=20
+ =3D toUShort(amd64g_create_fpucw( vex_state->guest_FPROUND ));
+
+ /* Compute the x87 tag word. */
+ tagw =3D 0;
+ for (stno =3D 0; stno < 8; stno++) {
+ preg =3D (stno + ftop) & 7;
+ if (vexTags[preg] =3D=3D 0) {
+ /* register is empty */
+ tagw |=3D (3 << (2*preg));
+ } else {
+ /* register is full. */
+ tagw |=3D (0 << (2*preg));
+ }
+ }
+ x87->env[FP_ENV_TAG] =3D toUShort(tagw);
+
+ /* We don't dump the x87 registers, tho. */
+}
+
+
/*---------------------------------------------------------------*/
/*--- 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-06-10 11:04:52 UTC (rev 1205)
+++ trunk/priv/guest-amd64/toIR.c 2005-06-13 12:17:27 UTC (rev 1206)
@@ -4596,65 +4596,63 @@
fp_pop();
break;
=20
-//.. case 4: { /* FLDENV m108 */
-//.. /* Uses dirty helper:=20
-//.. VexEmWarn x86g_do_FLDENV ( VexGuestX86State*, =
Addr32 ) */
-//.. IRTemp ew =3D newTemp(Ity_I32);
-//.. IRDirty* d =3D unsafeIRDirty_0_N (=20
-//.. 0/*regparms*/,=20
-//.. "x86g_dirtyhelper_FLDENV",=20
-//.. &x86g_dirtyhelper_FLDENV,
-//.. mkIRExprVec_1( mkexpr(addr) )
-//.. );
-//.. d->needsBBP =3D True;
-//.. d->tmp =3D ew;
-//.. /* declare we're reading memory */
-//.. d->mFx =3D Ifx_Read;
-//.. d->mAddr =3D mkexpr(addr);
-//.. d->mSize =3D 28;
-//..=20
-//.. /* declare we're writing guest state */
-//.. d->nFxState =3D 5;
-//..=20
-//.. d->fxState[0].fx =3D Ifx_Write;
-//.. d->fxState[0].offset =3D OFFB_FTOP;
-//.. d->fxState[0].size =3D sizeof(UInt);
-//..=20
-//.. d->fxState[1].fx =3D Ifx_Write;
-//.. d->fxState[1].offset =3D OFFB_FPREGS;
-//.. d->fxState[1].size =3D 8 * sizeof(ULong);
-//..=20
-//.. d->fxState[2].fx =3D Ifx_Write;
-//.. d->fxState[2].offset =3D OFFB_FPTAGS;
-//.. d->fxState[2].size =3D 8 * sizeof(UChar);
-//..=20
-//.. d->fxState[3].fx =3D Ifx_Write;
-//.. d->fxState[3].offset =3D OFFB_FPROUND;
-//.. d->fxState[3].size =3D sizeof(UInt);
-//..=20
-//.. d->fxState[4].fx =3D Ifx_Write;
-//.. d->fxState[4].offset =3D OFFB_FC3210;
-//.. d->fxState[4].size =3D sizeof(UInt);
-//..=20
-//.. stmt( IRStmt_Dirty(d) );
-//..=20
-//.. /* ew contains any emulation warning we may need to
-//.. issue. If needed, side-exit to the next insn,
-//.. reporting the warning, so that Valgrind's dispatc=
her
-//.. sees the warning. */
-//.. put_emwarn( mkexpr(ew) );
-//.. stmt(=20
-//.. IRStmt_Exit(
-//.. binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
-//.. Ijk_EmWarn,
-//.. IRConst_U32( ((Addr32)guest_eip_bbstart)+delta=
)
-//.. )
-//.. );
-//..=20
-//.. DIP("fldenv %s\n", dis_buf);
-//.. break;
-//.. }
+ case 4: { /* FLDENV m28 */
+ /* Uses dirty helper:=20
+ VexEmWarn amd64g_do_FLDENV ( VexGuestX86State*, HWo=
rd ) */
+ IRTemp ew =3D newTemp(Ity_I32);
+ IRTemp w64 =3D newTemp(Ity_I64);
+ IRDirty* d =3D unsafeIRDirty_0_N (=20
+ 0/*regparms*/,=20
+ "amd64g_dirtyhelper_FLDENV",=20
+ &amd64g_dirtyhelper_FLDENV,
+ mkIRExprVec_1( mkexpr(addr) )
+ );
+ d->needsBBP =3D True;
+ d->tmp =3D w64;
+ /* declare we're reading memory */
+ d->mFx =3D Ifx_Read;
+ d->mAddr =3D mkexpr(addr);
+ d->mSize =3D 28;
=20
+ /* declare we're writing guest state */
+ d->nFxState =3D 4;
+
+ d->fxState[0].fx =3D Ifx_Write;
+ d->fxState[0].offset =3D OFFB_FTOP;
+ d->fxState[0].size =3D sizeof(UInt);
+
+ d->fxState[1].fx =3D Ifx_Write;
+ d->fxState[1].offset =3D OFFB_FPTAGS;
+ d->fxState[1].size =3D 8 * sizeof(UChar);
+
+ d->fxState[2].fx =3D Ifx_Write;
+ d->fxState[2].offset =3D OFFB_FPROUND;
+ d->fxState[2].size =3D sizeof(ULong);
+
+ d->fxState[3].fx =3D Ifx_Write;
+ d->fxState[3].offset =3D OFFB_FC3210;
+ d->fxState[3].size =3D sizeof(ULong);
+
+ stmt( IRStmt_Dirty(d) );
+
+ /* ew contains any emulation warning we may need to
+ issue. If needed, side-exit to the next insn,
+ reporting the warning, so that Valgrind's dispatcher
+ sees the warning. */
+ assign(ew, unop(Iop_64to32,mkexpr(w64)) );
+ put_emwarn( mkexpr(ew) );
+ stmt(=20
+ IRStmt_Exit(
+ binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
+ Ijk_EmWarn,
+ IRConst_U64( guest_rip_bbstart+delta )
+ )
+ );
+
+ DIP("fldenv %s\n", dis_buf);
+ break;
+ }
+
case 5: {/* FLDCW */
/* The only thing we observe in the control word is the
rounding mode. Therefore, pass the 16-bit value
@@ -4695,51 +4693,51 @@
break;
}
=20
-//.. case 6: { /* FNSTENV m28 */
-//.. /* Uses dirty helper:=20
-//.. void x86g_do_FSTENV ( VexGuestX86State*, UInt =
) */
-//.. IRDirty* d =3D unsafeIRDirty_0_N (=20
-//.. 0/*regparms*/,=20
-//.. "x86g_dirtyhelper_FSTENV",=20
-//.. &x86g_dirtyhelper_FSTENV,
-//.. mkIRExprVec_1( mkexpr(addr) )
-//.. );
-//.. d->needsBBP =3D True;
-//.. /* declare we're writing memory */
-//.. d->mFx =3D Ifx_Write;
-//.. d->mAddr =3D mkexpr(addr);
-//.. d->mSize =3D 28;
-//..=20
-//.. /* declare we're reading guest state */
-//.. d->nFxState =3D 4;
-//..=20
-//.. d->fxState[0].fx =3D Ifx_Read;
-//.. d->fxState[0].offset =3D OFFB_FTOP;
-//.. d->fxState[0].size =3D sizeof(UInt);
-//..=20
-//.. d->fxState[1].fx =3D Ifx_Read;
-//.. d->fxState[1].offset =3D OFFB_FPTAGS;
-//.. d->fxState[1].size =3D 8 * sizeof(UChar);
-//..=20
-//.. d->fxState[2].fx =3D Ifx_Read;
-//.. d->fxState[2].offset =3D OFFB_FPROUND;
-//.. d->fxState[2].size =3D sizeof(UInt);
-//..=20
-//.. d->fxState[3].fx =3D Ifx_Read;
-//.. d->fxState[3].offset =3D OFFB_FC3210;
-//.. d->fxState[3].size =3D sizeof(UInt);
-//..=20
-//.. stmt( IRStmt_Dirty(d) );
-//..=20
-//.. DIP("fnstenv %s\n", dis_buf);
-//.. break;
-//.. }
+ case 6: { /* FNSTENV m28 */
+ /* Uses dirty helper:=20
+ void amd64g_do_FSTENV ( VexGuestAMD64State*, HWord =
) */
+ IRDirty* d =3D unsafeIRDirty_0_N (=20
+ 0/*regparms*/,=20
+ "amd64g_dirtyhelper_FSTENV",=20
+ &amd64g_dirtyhelper_FSTENV,
+ mkIRExprVec_1( mkexpr(addr) )
+ );
+ d->needsBBP =3D True;
+ /* declare we're writing memory */
+ d->mFx =3D Ifx_Write;
+ d->mAddr =3D mkexpr(addr);
+ d->mSize =3D 28;
=20
+ /* declare we're reading guest state */
+ d->nFxState =3D 4;
+
+ d->fxState[0].fx =3D Ifx_Read;
+ d->fxState[0].offset =3D OFFB_FTOP;
+ d->fxState[0].size =3D sizeof(UInt);
+
+ d->fxState[1].fx =3D Ifx_Read;
+ d->fxState[1].offset =3D OFFB_FPTAGS;
+ d->fxState[1].size =3D 8 * sizeof(UChar);
+
+ d->fxState[2].fx =3D Ifx_Read;
+ d->fxState[2].offset =3D OFFB_FPROUND;
+ d->fxState[2].size =3D sizeof(ULong);
+
+ d->fxState[3].fx =3D Ifx_Read;
+ d->fxState[3].offset =3D OFFB_FC3210;
+ d->fxState[3].size =3D sizeof(ULong);
+
+ stmt( IRStmt_Dirty(d) );
+
+ DIP("fnstenv %s\n", dis_buf);
+ break;
+ }
+
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 ) */
+ /* ULong amd64g_create_fpucw ( ULong fpround ) */
DIP("fnstcw %s\n", dis_buf);
storeLE(
mkexpr(addr),=20
Modified: trunk/priv/guest-generic/g_generic_x87.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-generic/g_generic_x87.h 2005-06-10 11:04:52 UTC (rev=
1205)
+++ trunk/priv/guest-generic/g_generic_x87.h 2005-06-13 12:17:27 UTC (rev=
1206)
@@ -75,6 +75,26 @@
void convert_f80le_to_f64le ( /*IN*/UChar* f80, /*OUT*/UChar* f64 );
=20
=20
+/* Layout of the real x87 state. */
+typedef
+ struct {
+ UShort env[14];
+ UChar reg[80];
+ }
+ Fpu_State;
+
+/* Offsets, in 16-bit ints, into the FPU environment (env) area. */
+#define FP_ENV_CTRL 0
+#define FP_ENV_STAT 2
+#define FP_ENV_TAG 4
+#define FP_ENV_IP 6 /* and 7 */
+#define FP_ENV_CS 8
+#define FP_ENV_OPOFF 10 /* and 11 */
+#define FP_ENV_OPSEL 12
+#define FP_REG(ii) (10*(7-(ii)))
+
+
+
#endif /* ndef __G_GENERIC_X87_H */
=20
/*---------------------------------------------------------------*/
Modified: trunk/priv/guest-x86/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-x86/ghelpers.c 2005-06-10 11:04:52 UTC (rev 1205)
+++ trunk/priv/guest-x86/ghelpers.c 2005-06-13 12:17:27 UTC (rev 1206)
@@ -1234,25 +1234,10 @@
/*----------------------------------------------*/
=20
/* Layout of the real x87 state. */
+/* 13 June 05: Fpu_State and auxiliary constants was moved to
+ g_generic_x87.h */
=20
-typedef
- struct {
- UShort env[14];
- UChar reg[80];
- }
- Fpu_State;
=20
-/* Offsets, in 16-bit ints, into the FPU environment (env) area. */
-#define FP_ENV_CTRL 0
-#define FP_ENV_STAT 2
-#define FP_ENV_TAG 4
-#define FP_ENV_IP 6 /* and 7 */
-#define FP_ENV_CS 8
-#define FP_ENV_OPOFF 10 /* and 11 */
-#define FP_ENV_OPSEL 12
-#define FP_REG(ii) (10*(7-(ii)))
-
-
/* CLEAN HELPER */
/* fpucw[15:0] contains a x87 native format FPU control word.
Extract from it the required FPROUND value and any resulting
Modified: trunk/priv/guest-x86/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-x86/toIR.c 2005-06-10 11:04:52 UTC (rev 1205)
+++ trunk/priv/guest-x86/toIR.c 2005-06-13 12:17:27 UTC (rev 1206)
@@ -3733,7 +3733,7 @@
=20
case 4: { /* FLDENV m28 */
/* Uses dirty helper:=20
- VexEmWarn x86g_do_FLDENV ( VexGuestX86State*, Addr3=
2 ) */
+ VexEmWarn x86g_do_FLDENV ( VexGuestX86State*, HWord=
) */
IRTemp ew =3D newTemp(Ity_I32);
IRDirty* d =3D unsafeIRDirty_0_N (=20
0/*regparms*/,=20
@@ -3832,7 +3832,7 @@
=20
case 6: { /* FNSTENV m28 */
/* Uses dirty helper:=20
- void x86g_do_FSTENV ( VexGuestX86State*, UInt ) */
+ void x86g_do_FSTENV ( VexGuestX86State*, HWord ) */
IRDirty* d =3D unsafeIRDirty_0_N (=20
0/*regparms*/,=20
"x86g_dirtyhelper_FSTENV",=20
|