|
From: <sv...@va...> - 2005-10-03 01:02:46
|
Author: sewardj
Date: 2005-10-03 02:02:40 +0100 (Mon, 03 Oct 2005)
New Revision: 1405
Log:
x86 front end: implement FXTRACT. I knew there was a reason I'd been
avoiding this ...
Modified:
trunk/priv/guest-x86/gdefs.h
trunk/priv/guest-x86/ghelpers.c
trunk/priv/guest-x86/toIR.c
Modified: trunk/priv/guest-x86/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-x86/gdefs.h 2005-09-16 16:02:11 UTC (rev 1404)
+++ trunk/priv/guest-x86/gdefs.h 2005-10-03 01:02:40 UTC (rev 1405)
@@ -119,6 +119,9 @@
=20
extern UInt x86g_create_mxcsr ( UInt sseround );
=20
+extern ULong x86g_calculate_FXTRACT ( ULong arg, UInt getExp );
+
+
/* 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_x86.h. To indicate a
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-09-16 16:02:11 UTC (rev 1404)
+++ trunk/priv/guest-x86/ghelpers.c 2005-10-03 01:02:40 UTC (rev 1405)
@@ -1243,6 +1243,90 @@
}
=20
=20
+/* CALLED FROM GENERATED CODE: CLEAN HELPER */
+/* Extract the signed significand or exponent component as per
+ fxtract. Arg and result are doubles travelling under the guise of
+ ULongs. Returns significand when getExp is zero and exponent
+ otherwise. */
+ULong x86g_calculate_FXTRACT ( ULong arg, UInt getExp )
+{
+ ULong uSig;
+ Long sSig;
+ Double dSig, dExp;
+ Int sExp, i;
+ UInt sign;
+
+ /*
+ S 7FF 0------0 infinity
+ S 7FF 0X-----X snan
+ S 7FF 1X-----X qnan
+ */
+ const ULong posInf =3D 0x7FF0000000000000ULL;
+ const ULong negInf =3D 0xFFF0000000000000ULL;
+ const ULong nanMask =3D 0x7FF0000000000000ULL;
+ const ULong qNan =3D 0x7FF8000000000000ULL;
+ const ULong posZero =3D 0x0000000000000000ULL;
+ const ULong negZero =3D 0x8000000000000000ULL;
+ const ULong bit51 =3D 1ULL << 51;
+ const ULong bit52 =3D 1ULL << 52;
+
+ /* Mimic PIII behaviour for special cases. */
+ if (arg =3D=3D posInf)
+ return getExp ? posInf : posInf;
+ if (arg =3D=3D negInf)
+ return getExp ? posInf : negInf;
+ if ((arg & nanMask) =3D=3D nanMask)
+ return qNan;
+ if (arg =3D=3D posZero)
+ return getExp ? negInf : posZero;
+ if (arg =3D=3D negZero)
+ return getExp ? negInf : negZero;
+
+ /* Split into sign, exponent and significand. */
+ sign =3D ((UInt)(arg >> 63)) & 1;
+
+ /* Mask off exponent & sign. uSig is in range 0 .. 2^52-1. */
+ uSig =3D arg & (bit52 - 1);
+
+ /* Get the exponent. */
+ sExp =3D ((Int)(arg >> 52)) & 0x7FF;
+
+ /* Deal with denormals: if the exponent is zero, then the
+ significand cannot possibly be zero (negZero/posZero are handled
+ above). Shift the significand left until bit 51 of it becomes
+ 1, and decrease the exponent accordingly.
+ */
+ if (sExp =3D=3D 0) {
+ for (i =3D 0; i < 52; i++) {
+ if (uSig & bit51)
+ break;
+ uSig <<=3D 1;
+ sExp--;
+ }
+ uSig <<=3D 1;
+ } else {
+ /* Add the implied leading-1 in the significand. */
+ uSig |=3D bit52;
+ }
+
+ /* Roll in the sign. */
+ sSig =3D uSig;
+ if (sign) sSig =3D- sSig;
+
+ /* Convert sig into a double. This should be an exact conversion.
+ Then divide by 2^52, which should give a value in the range 1.0
+ to 2.0-epsilon, at least for normalised args. */
+ dSig =3D (Double)sSig;
+ dSig /=3D 67108864.0; /* 2^26 */
+ dSig /=3D 67108864.0; /* 2^26 */
+
+ /* Convert exp into a double. Also an exact conversion. */
+ dExp =3D (Double)(sExp - 1023);
+
+ return *(ULong*)(getExp ? &dExp : &dSig);
+}
+
+
/*----------------------------------------------*/
/*--- The exported fns .. ---*/
/*----------------------------------------------*/
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-09-16 16:02:11 UTC (rev 1404)
+++ trunk/priv/guest-x86/toIR.c 2005-10-03 01:02:40 UTC (rev 1405)
@@ -3863,6 +3863,38 @@
fp_pop();
break;
=20
+ case 0xF4: {
+ IRTemp argF =3D newTemp(Ity_F64);
+ IRTemp sigF =3D newTemp(Ity_F64);
+ IRTemp expF =3D newTemp(Ity_F64);
+ IRTemp argI =3D newTemp(Ity_I64);
+ IRTemp sigI =3D newTemp(Ity_I64);
+ IRTemp expI =3D newTemp(Ity_I64);
+ DIP("fxtract\n");
+ assign( argF, get_ST(0) );
+ assign( argI, unop(Iop_ReinterpF64asI64, mkexpr(argF)));
+ assign( sigI,=20
+ mkIRExprCCall(Ity_I64, 0/*regparms*/,=20
+ "x86g_calculate_FXTRACT",=20
+ &x86g_calculate_FXTRACT,=20
+ mkIRExprVec_2( mkexpr(argI),=20
+ mkU32(0)/*sig*/ )) )=
;
+ assign( expI,=20
+ mkIRExprCCall(Ity_I64, 0/*regparms*/,=20
+ "x86g_calculate_FXTRACT",=20
+ &x86g_calculate_FXTRACT,=20
+ mkIRExprVec_2( mkexpr(argI),=20
+ mkU32(1)/*exp*/ )) )=
;
+ assign( sigF, unop(Iop_ReinterpI64asF64, mkexpr(sigI)) );
+ assign( expF, unop(Iop_ReinterpI64asF64, mkexpr(expI)) );
+ /* exponent */
+ put_ST_UNCHECKED(0, mkexpr(expF) );
+ fp_push();
+ /* significand */
+ put_ST(0, mkexpr(sigF) );
+ break;
+ }
+
case 0xF5: { /* FPREM1 -- IEEE compliant */
IRTemp a1 =3D newTemp(Ity_F64);
IRTemp a2 =3D newTemp(Ity_F64);
|