From: Julian Seward Date: Tue, 7 Mar 2006 01:40:44 +0000 (+0000) Subject: Merge r1593 (implement amd64 fxtract) X-Git-Tag: svn/VALGRIND_3_1_1^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3f788b4ec51b05a33f9554d6c4af13cf18508328;p=thirdparty%2Fvalgrind.git Merge r1593 (implement amd64 fxtract) git-svn-id: svn://svn.valgrind.org/vex/branches/VEX_3_1_BRANCH@1594 --- diff --git a/VEX/priv/guest-amd64/toIR.c b/VEX/priv/guest-amd64/toIR.c index efa9747370..2de74470c0 100644 --- a/VEX/priv/guest-amd64/toIR.c +++ b/VEX/priv/guest-amd64/toIR.c @@ -132,6 +132,7 @@ #include "main/vex_util.h" #include "main/vex_globals.h" #include "guest-generic/bb_to_IR.h" +#include "guest-generic/g_generic_x87.h" #include "guest-amd64/gdefs.h" @@ -4772,6 +4773,42 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok, fp_pop(); break; + case 0xF4: { /* FXTRACT */ + IRTemp argF = newTemp(Ity_F64); + IRTemp sigF = newTemp(Ity_F64); + IRTemp expF = newTemp(Ity_F64); + IRTemp argI = newTemp(Ity_I64); + IRTemp sigI = newTemp(Ity_I64); + IRTemp expI = newTemp(Ity_I64); + DIP("fxtract\n"); + assign( argF, get_ST(0) ); + assign( argI, unop(Iop_ReinterpF64asI64, mkexpr(argF))); + assign( sigI, + mkIRExprCCall( + Ity_I64, 0/*regparms*/, + "x86amd64g_calculate_FXTRACT", + &x86amd64g_calculate_FXTRACT, + mkIRExprVec_2( mkexpr(argI), + mkIRExpr_HWord(0)/*sig*/ )) + ); + assign( expI, + mkIRExprCCall( + Ity_I64, 0/*regparms*/, + "x86amd64g_calculate_FXTRACT", + &x86amd64g_calculate_FXTRACT, + mkIRExprVec_2( mkexpr(argI), + mkIRExpr_HWord(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 = newTemp(Ity_F64); //.. IRTemp a2 = newTemp(Ity_F64); diff --git a/VEX/priv/guest-generic/g_generic_x87.c b/VEX/priv/guest-generic/g_generic_x87.c index d574905230..01b16b0112 100644 --- a/VEX/priv/guest-generic/g_generic_x87.c +++ b/VEX/priv/guest-generic/g_generic_x87.c @@ -437,6 +437,115 @@ void convert_f80le_to_f64le ( /*IN*/UChar* f80, /*OUT*/UChar* f64 ) } +/* 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 x86amd64g_calculate_FXTRACT ( ULong arg, HWord getExp ) +{ + ULong uSig, uExp; + /* Long sSig; */ + Int sExp, i; + UInt sign, expExp; + + /* + S 7FF 0------0 infinity + S 7FF 0X-----X snan + S 7FF 1X-----X qnan + */ + const ULong posInf = 0x7FF0000000000000ULL; + const ULong negInf = 0xFFF0000000000000ULL; + const ULong nanMask = 0x7FF0000000000000ULL; + const ULong qNan = 0x7FF8000000000000ULL; + const ULong posZero = 0x0000000000000000ULL; + const ULong negZero = 0x8000000000000000ULL; + const ULong bit51 = 1ULL << 51; + const ULong bit52 = 1ULL << 52; + const ULong sigMask = bit52 - 1; + + /* Mimic PIII behaviour for special cases. */ + if (arg == posInf) + return getExp ? posInf : posInf; + if (arg == negInf) + return getExp ? posInf : negInf; + if ((arg & nanMask) == nanMask) + return qNan; + if (arg == posZero) + return getExp ? negInf : posZero; + if (arg == negZero) + return getExp ? negInf : negZero; + + /* Split into sign, exponent and significand. */ + sign = ((UInt)(arg >> 63)) & 1; + + /* Mask off exponent & sign. uSig is in range 0 .. 2^52-1. */ + uSig = arg & sigMask; + + /* Get the exponent. */ + sExp = ((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 == 0) { + for (i = 0; i < 52; i++) { + if (uSig & bit51) + break; + uSig <<= 1; + sExp--; + } + uSig <<= 1; + } else { + /* Add the implied leading-1 in the significand. */ + uSig |= bit52; + } + + /* Roll in the sign. */ + /* sSig = uSig; */ + /* if (sign) sSig =- 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 = (Double)sSig; */ + /* dSig /= 67108864.0; */ /* 2^26 */ + /* dSig /= 67108864.0; */ /* 2^26 */ + uSig &= sigMask; + uSig |= 0x3FF0000000000000ULL; + if (sign) + uSig ^= negZero; + + /* Convert exp into a double. Also an exact conversion. */ + /* dExp = (Double)(sExp - 1023); */ + sExp -= 1023; + if (sExp == 0) { + uExp = 0; + } else { + uExp = sExp < 0 ? -sExp : sExp; + expExp = 0x3FF +52; + /* 1 <= uExp <= 1074 */ + /* Skip first 42 iterations of normalisation loop as we know they + will always happen */ + uExp <<= 42; + expExp -= 42; + for (i = 0; i < 52-42; i++) { + if (uExp & bit52) + break; + uExp <<= 1; + expExp--; + } + uExp &= sigMask; + uExp |= ((ULong)expExp) << 52; + if (sExp < 0) uExp ^= negZero; + } + + return getExp ? uExp : uSig; +} + + /*---------------------------------------------------------------*/ /*--- end guest-generic/h_generic_x87.c ---*/ /*---------------------------------------------------------------*/ diff --git a/VEX/priv/guest-generic/g_generic_x87.h b/VEX/priv/guest-generic/g_generic_x87.h index 5169960646..357b1dee91 100644 --- a/VEX/priv/guest-generic/g_generic_x87.h +++ b/VEX/priv/guest-generic/g_generic_x87.h @@ -105,6 +105,10 @@ typedef #define FP_REG(ii) (10*(7-(ii))) +/* Do the computations for x86/amd64 FXTRACT */ +extern ULong x86amd64g_calculate_FXTRACT ( ULong arg, HWord getExp ); + + #endif /* ndef __G_GENERIC_X87_H */ diff --git a/VEX/priv/guest-x86/gdefs.h b/VEX/priv/guest-x86/gdefs.h index 235befc19b..4e492df744 100644 --- a/VEX/priv/guest-x86/gdefs.h +++ b/VEX/priv/guest-x86/gdefs.h @@ -119,8 +119,6 @@ extern ULong x86g_check_ldmxcsr ( UInt mxcsr ); extern UInt x86g_create_mxcsr ( UInt sseround ); -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 diff --git a/VEX/priv/guest-x86/ghelpers.c b/VEX/priv/guest-x86/ghelpers.c index d515fcaf36..ce56bb3f6f 100644 --- a/VEX/priv/guest-x86/ghelpers.c +++ b/VEX/priv/guest-x86/ghelpers.c @@ -1243,115 +1243,6 @@ void x86g_dirtyhelper_storeF80le ( UInt addrU, ULong f64 ) } -/* 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, uExp; - /* Long sSig; */ - Int sExp, i; - UInt sign, expExp; - - /* - S 7FF 0------0 infinity - S 7FF 0X-----X snan - S 7FF 1X-----X qnan - */ - const ULong posInf = 0x7FF0000000000000ULL; - const ULong negInf = 0xFFF0000000000000ULL; - const ULong nanMask = 0x7FF0000000000000ULL; - const ULong qNan = 0x7FF8000000000000ULL; - const ULong posZero = 0x0000000000000000ULL; - const ULong negZero = 0x8000000000000000ULL; - const ULong bit51 = 1ULL << 51; - const ULong bit52 = 1ULL << 52; - const ULong sigMask = bit52 - 1; - - /* Mimic PIII behaviour for special cases. */ - if (arg == posInf) - return getExp ? posInf : posInf; - if (arg == negInf) - return getExp ? posInf : negInf; - if ((arg & nanMask) == nanMask) - return qNan; - if (arg == posZero) - return getExp ? negInf : posZero; - if (arg == negZero) - return getExp ? negInf : negZero; - - /* Split into sign, exponent and significand. */ - sign = ((UInt)(arg >> 63)) & 1; - - /* Mask off exponent & sign. uSig is in range 0 .. 2^52-1. */ - uSig = arg & sigMask; - - /* Get the exponent. */ - sExp = ((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 == 0) { - for (i = 0; i < 52; i++) { - if (uSig & bit51) - break; - uSig <<= 1; - sExp--; - } - uSig <<= 1; - } else { - /* Add the implied leading-1 in the significand. */ - uSig |= bit52; - } - - /* Roll in the sign. */ - /* sSig = uSig; */ - /* if (sign) sSig =- 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 = (Double)sSig; */ - /* dSig /= 67108864.0; */ /* 2^26 */ - /* dSig /= 67108864.0; */ /* 2^26 */ - uSig &= sigMask; - uSig |= 0x3FF0000000000000ULL; - if (sign) - uSig ^= negZero; - - /* Convert exp into a double. Also an exact conversion. */ - /* dExp = (Double)(sExp - 1023); */ - sExp -= 1023; - if (sExp == 0) { - uExp = 0; - } else { - uExp = sExp < 0 ? -sExp : sExp; - expExp = 0x3FF +52; - /* 1 <= uExp <= 1074 */ - /* Skip first 42 iterations of normalisation loop as we know they - will always happen */ - uExp <<= 42; - expExp -= 42; - for (i = 0; i < 52-42; i++) { - if (uExp & bit52) - break; - uExp <<= 1; - expExp--; - } - uExp &= sigMask; - uExp |= ((ULong)expExp) << 52; - if (sExp < 0) uExp ^= negZero; - } - - return getExp ? uExp : uSig; -} - - /*----------------------------------------------*/ /*--- The exported fns .. ---*/ /*----------------------------------------------*/ diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index 8f759ccd90..b53dba0972 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -132,6 +132,7 @@ #include "main/vex_util.h" #include "main/vex_globals.h" #include "guest-generic/bb_to_IR.h" +#include "guest-generic/g_generic_x87.h" #include "guest-x86/gdefs.h" @@ -3886,17 +3887,21 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta ) assign( argF, get_ST(0) ); assign( argI, unop(Iop_ReinterpF64asI64, mkexpr(argF))); assign( sigI, - mkIRExprCCall(Ity_I64, 0/*regparms*/, - "x86g_calculate_FXTRACT", - &x86g_calculate_FXTRACT, - mkIRExprVec_2( mkexpr(argI), - mkU32(0)/*sig*/ )) ); + mkIRExprCCall( + Ity_I64, 0/*regparms*/, + "x86amd64g_calculate_FXTRACT", + &x86amd64g_calculate_FXTRACT, + mkIRExprVec_2( mkexpr(argI), + mkIRExpr_HWord(0)/*sig*/ )) + ); assign( expI, - mkIRExprCCall(Ity_I64, 0/*regparms*/, - "x86g_calculate_FXTRACT", - &x86g_calculate_FXTRACT, - mkIRExprVec_2( mkexpr(argI), - mkU32(1)/*exp*/ )) ); + mkIRExprCCall( + Ity_I64, 0/*regparms*/, + "x86amd64g_calculate_FXTRACT", + &x86amd64g_calculate_FXTRACT, + mkIRExprVec_2( mkexpr(argI), + mkIRExpr_HWord(1)/*exp*/ )) + ); assign( sigF, unop(Iop_ReinterpI64asF64, mkexpr(sigI)) ); assign( expF, unop(Iop_ReinterpI64asF64, mkexpr(expI)) ); /* exponent */