VirtualBox

Changeset 94387 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Mar 28, 2022 9:50:41 PM (3 years ago)
Author:
vboxsync
Message:

VMM/IEM: Implemented C version of fistt; fixes to fst and fist. bugref:9898

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp

    r94383 r94387  
    33103310        if (!(fFcw & X86_FCW_OM))
    33113311            return fFsw | X86_FSW_ES | X86_FSW_B;
    3312         if (fRoundedOff)
    3313         {
    3314             fFsw |= X86_FSW_PE;
    3315             if (uRoundingAdd)
    3316                 fFsw |= X86_FSW_C1;
    3317             if (!(fFcw & X86_FCW_PM))
    3318                 fFsw |= X86_FSW_ES | X86_FSW_B;
    3319         }
     3312        fFsw |= X86_FSW_PE;
     3313        if (uRoundingAdd)
     3314            fFsw |= X86_FSW_C1;
     3315        if (!(fFcw & X86_FCW_PM))
     3316            fFsw |= X86_FSW_ES | X86_FSW_B;
    33203317
    33213318        pr32Dst->s.fSign         = fSignIn;
     
    35313528        if (!(fFcw & X86_FCW_OM))
    35323529            return fFsw | X86_FSW_ES | X86_FSW_B;
    3533         if (fRoundedOff)
    3534         {
    3535             fFsw |= X86_FSW_PE;
    3536             if (uRoundingAdd)
    3537                 fFsw |= X86_FSW_C1;
    3538             if (!(fFcw & X86_FCW_PM))
    3539                 fFsw |= X86_FSW_ES | X86_FSW_B;
    3540         }
     3530        fFsw |= X86_FSW_PE;
     3531        if (uRoundingAdd)
     3532            fFsw |= X86_FSW_C1;
     3533        if (!(fFcw & X86_FCW_PM))
     3534            fFsw |= X86_FSW_ES | X86_FSW_B;
    35413535
    35423536        pr64Dst->s64.fSign         = fSignIn;
     
    36993693 *
    37003694 * Mantissa:
     3695 *  63        56        48        40        32        24        16         8         0
     3696 *  v          v         v         v         v         v         v         v         v
    37013697 *  1[.]111 0000 1111 0000 1111 0000 1111 0000 1111 0000 1111 0000 1111 0000 1111 0000
    3702  *  ^          ^         ^         ^         ^         ^         ^         ^         ^
    3703  *  63        56        48        40        32        24        16         8         0
     3698 *      \    \    \    \    \    \    \    \    \    \    \    \    \    \    \    \
     3699 * Exp: 0    4    8    12   16   20   24   28   32   36   40   44   48   52   56   60
    37043700 *
    37053701 * int64_t has the same width, only bit 63 is the sign bit.  So, the max we can map over
     
    37263722        if ((uint32_t)iExponent <= a_cBits - 2) \
    37273723        { \
    3728             unsigned const cShiftOff        = a_cBits - 1 - iExponent; \
     3724            unsigned const cShiftOff        = 63 - iExponent; \
    37293725            uint64_t const fRoundingOffMask = RT_BIT_64(cShiftOff) - 1; \
    37303726            uint64_t const uRoundingAdd     = (fFcw & X86_FCW_RC_MASK) == X86_FCW_RC_NEAREST \
     
    37423738                if (fRoundedOff) \
    37433739                { \
    3744                     if ((uMantissa & 1) && iExponent == a_cBits - 2 && ((fFcw & X86_FCW_RC_MASK) == X86_FCW_RC_NEAREST)) \
    3745                         uMantissa &= ~(uint64_t)1; \
     3740                    if ((uMantissa & 1) && (fFcw & X86_FCW_RC_MASK) == X86_FCW_RC_NEAREST && fRoundedOff == uRoundingAdd) \
     3741                        uMantissa &= ~(uint64_t)1; /* round to even number if equal distance between up/down. */ \
    37463742                    else if (uRounding) \
    37473743                        fFsw |= X86_FSW_C1; \
     
    37583754            else \
    37593755            { \
    3760                 Assert(iExponent == a_cBits - 2); \
     3756                AssertMsg(iExponent == a_cBits - 2, \
     3757                          ("e=%d m=%#RX64 (org %#RX64) s=%d; shift=%d ro=%#RX64 rm=%#RX64 ra=%#RX64\n", iExponent, uMantissa, \
     3758                          pr80Val->s.uMantissa, fSignIn, cShiftOff, fRoundedOff, fRoundingOffMask, uRoundingAdd)); \
     3759                \
    37613760                /* Special case for the integer minimum value. */ \
    37623761                if (fSignIn && uMantissa == RT_BIT_64(a_cBits - 1)) \
     
    38443843    else if (RTFLOAT80U_IS_PSEUDO_DENORMAL(pr80Val) || RTFLOAT80U_IS_DENORMAL(pr80Val)) \
    38453844    { \
    3846         /* Really small numbers that are either rounded to zero, 1 or -1 \
    3847            depending on sign and rounding control. */ \
    38483845        if ((fFcw & X86_FCW_RC_MASK) != (fSignIn ? X86_FCW_RC_DOWN : X86_FCW_RC_UP)) \
    38493846            *piDst = 0; \
     
    38763873
    38773874
    3878 IEM_DECL_IMPL_DEF(void, iemAImpl_fistt_r80_to_i16,(PCX86FXSTATE pFpuState, uint16_t *pu16FSW,
    3879                                                    int16_t *pi16Val, PCRTFLOAT80U pr80Val))
    3880 {
    3881     RT_NOREF(pFpuState, pu16FSW, pi16Val, pr80Val);
    3882     AssertReleaseFailed();
    3883 }
    3884 
    3885 IEM_DECL_IMPL_DEF(void, iemAImpl_fistt_r80_to_i32,(PCX86FXSTATE pFpuState, uint16_t *pu16FSW,
    3886                                                    int32_t *pi32Val, PCRTFLOAT80U pr80Val))
    3887 {
    3888     RT_NOREF(pFpuState, pu16FSW, pi32Val, pr80Val);
    3889     AssertReleaseFailed();
    3890 }
    3891 
    3892 
    3893 IEM_DECL_IMPL_DEF(void, iemAImpl_fistt_r80_to_i64,(PCX86FXSTATE pFpuState, uint16_t *pu16FSW,
    3894                                                    int64_t *pi64Val, PCRTFLOAT80U pr80Val))
    3895 {
    3896     RT_NOREF(pFpuState, pu16FSW, pi64Val, pr80Val);
    3897     AssertReleaseFailed();
    3898 }
     3875#define EMIT_FISTT(a_cBits, a_iType, a_iTypeMin, a_iTypeMax, a_iTypeIndefinite) \
     3876IEM_DECL_IMPL_DEF(void, iemAImpl_fistt_r80_to_i ## a_cBits,(PCX86FXSTATE pFpuState, uint16_t *pu16FSW, \
     3877                                                            a_iType *piDst, PCRTFLOAT80U pr80Val)) \
     3878{ \
     3879    uint16_t const fFcw    = pFpuState->FCW; \
     3880    uint16_t       fFsw    = (pFpuState->FSW & (X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3)); \
     3881    bool const     fSignIn = pr80Val->s.fSign; \
     3882    \
     3883    /* \
     3884     * Deal with normal numbers first. \
     3885     */ \
     3886    if (RTFLOAT80U_IS_NORMAL(pr80Val)) \
     3887    { \
     3888        uint64_t       uMantissa = pr80Val->s.uMantissa; \
     3889        int32_t        iExponent = (int32_t)pr80Val->s.uExponent - RTFLOAT80U_EXP_BIAS; \
     3890        \
     3891        if ((uint32_t)iExponent <= a_cBits - 2) \
     3892        { \
     3893            unsigned const cShiftOff        = 63 - iExponent; \
     3894            uint64_t const fRoundingOffMask = RT_BIT_64(cShiftOff) - 1; \
     3895            uint64_t const fRoundedOff      = uMantissa & fRoundingOffMask; \
     3896            uMantissa >>= cShiftOff; \
     3897            Assert(!(uMantissa & RT_BIT_64(a_cBits - 1))); \
     3898            if (!fSignIn) \
     3899                *piDst = (a_iType)uMantissa; \
     3900            else \
     3901                *piDst = -(a_iType)uMantissa; \
     3902            \
     3903            if (fRoundedOff) \
     3904            { \
     3905                fFsw |= X86_FSW_PE; \
     3906                if (!(fFcw & X86_FCW_PM)) \
     3907                    fFsw |= X86_FSW_ES | X86_FSW_B; \
     3908            } \
     3909        } \
     3910        /* \
     3911         * Tiny sub-zero numbers. \
     3912         */ \
     3913        else if (iExponent < 0) \
     3914        { \
     3915            *piDst = 0; \
     3916            fFsw |= X86_FSW_PE; \
     3917            if (!(fFcw & X86_FCW_PM)) \
     3918                fFsw |= X86_FSW_ES | X86_FSW_B; \
     3919        } \
     3920        /* \
     3921         * Too large/small number outside the target integer range. \
     3922         */ \
     3923        else \
     3924        { \
     3925            fFsw |= X86_FSW_IE; \
     3926            if (fFcw & X86_FCW_IM) \
     3927                *piDst = a_iTypeIndefinite; \
     3928            else \
     3929                fFsw |= X86_FSW_ES | X86_FSW_B | (7 << X86_FSW_TOP_SHIFT); \
     3930        } \
     3931    } \
     3932    /* \
     3933     * Map both +0 and -0 to integer zero (signless/+). \
     3934     */ \
     3935    else if (RTFLOAT80U_IS_ZERO(pr80Val)) \
     3936        *piDst = 0; \
     3937    /* \
     3938     * Denormals are just really tiny sub-zero numbers that are trucated to zero. \
     3939     */ \
     3940    else if (RTFLOAT80U_IS_PSEUDO_DENORMAL(pr80Val) || RTFLOAT80U_IS_DENORMAL(pr80Val)) \
     3941    { \
     3942        *piDst = 0; \
     3943        fFsw |= X86_FSW_PE; \
     3944        if (!(fFcw & X86_FCW_PM)) \
     3945            fFsw |= X86_FSW_ES | X86_FSW_B; \
     3946    } \
     3947    /* \
     3948     * All other special values are considered invalid arguments and result \
     3949     * in an IE exception and indefinite value if masked. \
     3950     */ \
     3951    else \
     3952    { \
     3953        fFsw |= X86_FSW_IE; \
     3954        if (fFcw & X86_FCW_IM) \
     3955            *piDst = a_iTypeIndefinite; \
     3956        else \
     3957            fFsw |= X86_FSW_ES | X86_FSW_B | (7 << X86_FSW_TOP_SHIFT); \
     3958    } \
     3959    *pu16FSW = fFsw; \
     3960}
     3961EMIT_FISTT(64, int64_t, INT64_MIN, INT64_MAX, X86_FPU_INT64_INDEFINITE)
     3962EMIT_FISTT(32, int32_t, INT32_MIN, INT32_MAX, X86_FPU_INT32_INDEFINITE)
     3963EMIT_FISTT(16, int16_t, INT16_MIN, INT16_MAX, 0 /* X86_FPU_INT16_INDEFINITE - weird weird weird! */)
    38993964
    39003965
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette