Changeset 94397 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Mar 30, 2022 1:53:25 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp
r94387 r94397 3333 3333 * Normal or subnormal number. 3334 3334 */ 3335 /* Do rounding. */ 3336 uint64_t uMantissaOut = uMantissaIn + uRoundingAdd; 3337 if (uMantissaOut < uMantissaIn) 3338 { 3339 uMantissaOut >>= 1; 3340 iExponentOut++; 3341 Assert(iExponentOut < RTFLOAT32U_EXP_MAX); /* checked above */ 3342 fFsw |= X86_FSW_C1; 3343 } 3344 /** @todo not sure if this is applied correctly, with the above carry check. */ 3345 else if ( (fFcw & X86_FCW_RC_MASK) == X86_FCW_RC_NEAREST 3346 && !(fRoundedOff & RT_BIT_64(RTFLOAT80U_FRACTION_BITS - RTFLOAT32U_FRACTION_BITS - 1))) 3347 uMantissaOut &= ~(uint64_t)1; 3348 3349 /* Truncat the mantissa and set the return value. */ 3335 /* Do rounding - just truncate in near mode when midway on an even outcome. */ 3336 uint64_t uMantissaOut = uMantissaIn; 3337 if ( (fFcw & X86_FCW_RC_MASK) != X86_FCW_RC_NEAREST 3338 || (uMantissaIn & RT_BIT_64(RTFLOAT80U_FRACTION_BITS - RTFLOAT32U_FRACTION_BITS)) 3339 || fRoundedOff != uRoundingAdd) 3340 { 3341 uMantissaOut = uMantissaIn + uRoundingAdd; 3342 if (uMantissaOut >= uMantissaIn) 3343 { /* likely */ } 3344 else 3345 { 3346 uMantissaOut >>= 1; /* (We don't need to add bit 63 here (the integer bit), as it will be chopped off below.) */ 3347 iExponentOut++; 3348 Assert(iExponentOut < RTFLOAT32U_EXP_MAX); /* checked above */ 3349 fFsw |= X86_FSW_C1; 3350 } 3351 } 3352 else 3353 uMantissaOut = uMantissaIn; 3354 3355 /* Truncate the mantissa and set the return value. */ 3350 3356 uMantissaOut >>= RTFLOAT80U_FRACTION_BITS - RTFLOAT32U_FRACTION_BITS; 3351 3357 … … 3507 3513 if (iExponentOut <= 0) 3508 3514 { 3509 uMantissaIn = iExponentOut <= -633510 ? uMantissaIn != 03511 : (uMantissaIn >> (-iExponentOut + 1)) | ((uMantissaIn & (RT_BIT_64(-iExponentOut + 1) - 1)) != 0);3512 fRoundedOff = uMantissaIn & fRoundingOffMask;3515 uMantissaIn = iExponentOut <= -63 3516 ? uMantissaIn != 0 3517 : (uMantissaIn >> (-iExponentOut + 1)) | ((uMantissaIn & (RT_BIT_64(-iExponentOut + 1) - 1)) != 0); 3518 fRoundedOff = uMantissaIn & fRoundingOffMask; 3513 3519 if (fRoundedOff && fIsTiny) 3514 fFsw |= X86_FSW_UE;3515 iExponentOut 3520 fFsw |= X86_FSW_UE; 3521 iExponentOut = 0; 3516 3522 } 3517 3523 } … … 3551 3557 * Normal or subnormal number. 3552 3558 */ 3553 /* Do rounding. */ 3554 uint64_t uMantissaOut = uMantissaIn + uRoundingAdd; 3555 if (uMantissaOut < uMantissaIn) 3556 { 3557 uMantissaOut >>= 1; 3558 iExponentOut++; 3559 Assert(iExponentOut < RTFLOAT64U_EXP_MAX); /* checked above */ 3560 fFsw |= X86_FSW_C1; 3561 } 3562 /** @todo not sure if this is applied correctly, with the above carry check. */ 3563 else if ( (fFcw & X86_FCW_RC_MASK) == X86_FCW_RC_NEAREST 3564 && !(fRoundedOff & RT_BIT_32(RTFLOAT80U_FRACTION_BITS - RTFLOAT64U_FRACTION_BITS - 1))) 3565 uMantissaOut &= ~(uint64_t)1; 3566 3567 /* Truncat the mantissa and set the return value. */ 3559 /* Do rounding - just truncate in near mode when midway on an even outcome. */ 3560 uint64_t uMantissaOut = uMantissaIn; 3561 if ( (fFcw & X86_FCW_RC_MASK) != X86_FCW_RC_NEAREST 3562 || (uMantissaIn & RT_BIT_32(RTFLOAT80U_FRACTION_BITS - RTFLOAT64U_FRACTION_BITS)) 3563 || fRoundedOff != uRoundingAdd) 3564 { 3565 uMantissaOut = uMantissaIn + uRoundingAdd; 3566 if (uMantissaOut >= uMantissaIn) 3567 { /* likely */ } 3568 else 3569 { 3570 uMantissaOut >>= 1; /* (We don't need to add bit 63 here (the integer bit), as it will be chopped off below.) */ 3571 iExponentOut++; 3572 Assert(iExponentOut < RTFLOAT64U_EXP_MAX); /* checked above */ 3573 fFsw |= X86_FSW_C1; 3574 } 3575 } 3576 else 3577 uMantissaOut = uMantissaIn; 3578 3579 /* Truncate the mantissa and set the return value. */ 3568 3580 uMantissaOut >>= RTFLOAT80U_FRACTION_BITS - RTFLOAT64U_FRACTION_BITS; 3569 3581 … … 3704 3716 * where we'll drop off all but bit 63. 3705 3717 */ 3706 #define EMIT_FIST(a_cBits, a_iType, a_iTypeMin, a_iType Max, a_iTypeIndefinite) \3718 #define EMIT_FIST(a_cBits, a_iType, a_iTypeMin, a_iTypeIndefinite) \ 3707 3719 IEM_DECL_IMPL_DEF(void, iemAImpl_fist_r80_to_i ## a_cBits,(PCX86FXSTATE pFpuState, uint16_t *pu16FSW, \ 3708 3720 a_iType *piDst, PCRTFLOAT80U pr80Val)) \ … … 3754 3766 else \ 3755 3767 { \ 3756 AssertMsg(iExponent == a_cBits - 2, \ 3768 /* overflowed after rounding. */ \ 3769 AssertMsg(iExponent == a_cBits - 2 && uMantissa == RT_BIT_64(a_cBits - 1), \ 3757 3770 ("e=%d m=%#RX64 (org %#RX64) s=%d; shift=%d ro=%#RX64 rm=%#RX64 ra=%#RX64\n", iExponent, uMantissa, \ 3758 3771 pr80Val->s.uMantissa, fSignIn, cShiftOff, fRoundedOff, fRoundingOffMask, uRoundingAdd)); \ 3759 3772 \ 3760 3773 /* Special case for the integer minimum value. */ \ 3761 if (fSignIn && uMantissa == RT_BIT_64(a_cBits - 1)) \3774 if (fSignIn) \ 3762 3775 { \ 3763 3776 *piDst = a_iTypeMin; \ … … 3768 3781 else \ 3769 3782 { \ 3770 /* overflowed after rounding. */ \3771 3783 fFsw |= X86_FSW_IE; \ 3772 3784 if (fFcw & X86_FCW_IM) \ 3773 { \ 3774 if ( (fSignIn && (fFcw & X86_FCW_RC_MASK) != X86_FCW_RC_DOWN) \ 3775 || (!fSignIn && uMantissa == RT_BIT_64(a_cBits - 1)) ) \ 3776 *piDst = a_iTypeMin; \ 3777 else if (!fSignIn && (fFcw & X86_FCW_RC_MASK) != X86_FCW_RC_UP) \ 3778 *piDst = a_iTypeMax; \ 3779 else \ 3780 { \ 3781 *piDst = 0; \ 3782 fFsw |= X86_FSW_C1; \ 3783 } \ 3784 } \ 3785 *piDst = a_iTypeMin; \ 3785 3786 else \ 3786 3787 fFsw |= X86_FSW_ES | X86_FSW_B | (7 << X86_FSW_TOP_SHIFT); \ … … 3819 3820 if (!(fFcw & X86_FCW_PM)) \ 3820 3821 fFsw |= X86_FSW_ES | X86_FSW_B; \ 3822 } \ 3823 /* \ 3824 * Special MIN case. \ 3825 */ \ 3826 else if ( fSignIn && iExponent == a_cBits - 1 \ 3827 && ( a_cBits < 64 && (fFcw & X86_FCW_RC_MASK) != X86_FCW_RC_DOWN \ 3828 ? uMantissa < (RT_BIT_64(63) | RT_BIT_64(65 - a_cBits)) \ 3829 : uMantissa == RT_BIT_64(63))) \ 3830 { \ 3831 *piDst = a_iTypeMin; \ 3832 if (uMantissa & (RT_BIT_64(64 - a_cBits + 1) - 1)) \ 3833 { \ 3834 fFsw |= X86_FSW_PE; \ 3835 if (!(fFcw & X86_FCW_PM)) \ 3836 fFsw |= X86_FSW_ES | X86_FSW_B; \ 3837 } \ 3821 3838 } \ 3822 3839 /* \ … … 3868 3885 *pu16FSW = fFsw; \ 3869 3886 } 3870 EMIT_FIST(64, int64_t, INT64_MIN, INT64_MAX, X86_FPU_INT64_INDEFINITE) 3871 EMIT_FIST(32, int32_t, INT32_MIN, INT32_MAX, X86_FPU_INT32_INDEFINITE) 3872 EMIT_FIST(16, int16_t, INT16_MIN, INT16_MAX, X86_FPU_INT16_INDEFINITE) 3873 3874 3875 #define EMIT_FISTT(a_cBits, a_iType, a_iTypeMin, a_iTypeMax, a_iTypeIndefinite) \ 3887 EMIT_FIST(64, int64_t, INT64_MIN, X86_FPU_INT64_INDEFINITE) 3888 EMIT_FIST(32, int32_t, INT32_MIN, X86_FPU_INT32_INDEFINITE) 3889 EMIT_FIST(16, int16_t, INT16_MIN, X86_FPU_INT16_INDEFINITE) 3890 3891 3892 /* 3893 * The FISTT instruction was added with SSE3 and are a lot simpler than FIST. 3894 * 3895 * The 16-bit version is a bit peculiar, though, as it seems to be raising IE 3896 * as if it was the 32-bit version (i.e. starting with exp 31 instead of 15), 3897 * thus the @a a_cBitsIn. 3898 */ 3899 #define EMIT_FISTT(a_cBits, a_cBitsIn, a_iType, a_iTypeMin, a_iTypeMax, a_iTypeIndefinite) \ 3876 3900 IEM_DECL_IMPL_DEF(void, iemAImpl_fistt_r80_to_i ## a_cBits,(PCX86FXSTATE pFpuState, uint16_t *pu16FSW, \ 3877 3901 a_iType *piDst, PCRTFLOAT80U pr80Val)) \ … … 3889 3913 int32_t iExponent = (int32_t)pr80Val->s.uExponent - RTFLOAT80U_EXP_BIAS; \ 3890 3914 \ 3891 if ((uint32_t)iExponent <= a_cBits - 2) \3915 if ((uint32_t)iExponent <= a_cBitsIn - 2) \ 3892 3916 { \ 3893 3917 unsigned const cShiftOff = 63 - iExponent; \ … … 3895 3919 uint64_t const fRoundedOff = uMantissa & fRoundingOffMask; \ 3896 3920 uMantissa >>= cShiftOff; \ 3897 Assert(!(uMantissa & RT_BIT_64(a_cBits - 1)));\3921 /*Assert(!(uMantissa & RT_BIT_64(a_cBits - 1)));*/ \ 3898 3922 if (!fSignIn) \ 3899 3923 *piDst = (a_iType)uMantissa; \ … … 3917 3941 if (!(fFcw & X86_FCW_PM)) \ 3918 3942 fFsw |= X86_FSW_ES | X86_FSW_B; \ 3943 } \ 3944 /* \ 3945 * Special MIN case. \ 3946 */ \ 3947 else if ( fSignIn && iExponent == a_cBits - 1 \ 3948 && (a_cBits < 64 \ 3949 ? uMantissa < (RT_BIT_64(63) | RT_BIT_64(65 - a_cBits)) \ 3950 : uMantissa == RT_BIT_64(63)) ) \ 3951 { \ 3952 *piDst = a_iTypeMin; \ 3953 if (uMantissa & (RT_BIT_64(64 - a_cBits + 1) - 1)) \ 3954 { \ 3955 fFsw |= X86_FSW_PE; \ 3956 if (!(fFcw & X86_FCW_PM)) \ 3957 fFsw |= X86_FSW_ES | X86_FSW_B; \ 3958 } \ 3959 } \ 3960 /* \ 3961 * Figure this weirdness. \ 3962 */ \ 3963 else if (a_cBits == 16 && fSignIn && iExponent == 31 && uMantissa < UINT64_C(0x8000100000000000) ) \ 3964 { \ 3965 *piDst = 0; \ 3966 if (uMantissa & (RT_BIT_64(64 - a_cBits + 1) - 1)) \ 3967 { \ 3968 fFsw |= X86_FSW_PE; \ 3969 if (!(fFcw & X86_FCW_PM)) \ 3970 fFsw |= X86_FSW_ES | X86_FSW_B; \ 3971 } \ 3919 3972 } \ 3920 3973 /* \ … … 3959 4012 *pu16FSW = fFsw; \ 3960 4013 } 3961 EMIT_FISTT(64, int64_t, INT64_MIN, INT64_MAX, X86_FPU_INT64_INDEFINITE)3962 EMIT_FISTT(32, int32_t, INT32_MIN, INT32_MAX, X86_FPU_INT32_INDEFINITE)3963 EMIT_FISTT(16, int16_t, INT16_MIN, INT16_MAX, 0 /* X86_FPU_INT16_INDEFINITE - weird weird weird! */)4014 EMIT_FISTT(64, 64, int64_t, INT64_MIN, INT64_MAX, X86_FPU_INT64_INDEFINITE) 4015 EMIT_FISTT(32, 32, int32_t, INT32_MIN, INT32_MAX, X86_FPU_INT32_INDEFINITE) 4016 EMIT_FISTT(16, 32, int16_t, INT16_MIN, INT16_MAX, 0 /* X86_FPU_INT16_INDEFINITE - weird weird weird! */) 3964 4017 3965 4018 … … 3967 4020 PRTPBCD80U pd80Dst, PCRTFLOAT80U pr80Src)) 3968 4021 { 3969 RT_NOREF(pFpuState, pu16FSW, pd80Dst, pr80Src); 3970 AssertReleaseFailed(); 4022 /*static RTPBCD80U const s_ad80MaxMin[2] = { RTPBCD80U_INIT_MAX(), RTPBCD80U_INIT_MIN() };*/ 4023 static RTPBCD80U const s_ad80Zeros[2] = { RTPBCD80U_INIT_ZERO(0), RTPBCD80U_INIT_ZERO(1) }; 4024 static RTPBCD80U const s_ad80One[2] = { RTPBCD80U_INIT_C(0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,1), 4025 RTPBCD80U_INIT_C(1, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,1) }; 4026 static RTPBCD80U const s_d80Indefinite = RTPBCD80U_INIT_INDEFINITE(); 4027 4028 uint16_t const fFcw = pFpuState->FCW; 4029 uint16_t fFsw = (pFpuState->FSW & (X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3)); 4030 bool const fSignIn = pr80Src->s.fSign; 4031 4032 /* 4033 * Deal with normal numbers first. 4034 */ 4035 if (RTFLOAT80U_IS_NORMAL(pr80Src)) 4036 { 4037 uint64_t uMantissa = pr80Src->s.uMantissa; 4038 int32_t iExponent = (int32_t)pr80Src->s.uExponent - RTFLOAT80U_EXP_BIAS; 4039 if ( (uint32_t)iExponent <= 58 4040 || ((uint32_t)iExponent == 59 && uMantissa <= UINT64_C(0xde0b6b3a763fffff)) ) 4041 { 4042 unsigned const cShiftOff = 63 - iExponent; 4043 uint64_t const fRoundingOffMask = RT_BIT_64(cShiftOff) - 1; 4044 uint64_t const uRoundingAdd = (fFcw & X86_FCW_RC_MASK) == X86_FCW_RC_NEAREST 4045 ? RT_BIT_64(cShiftOff - 1) 4046 : (fFcw & X86_FCW_RC_MASK) == (fSignIn ? X86_FCW_RC_DOWN : X86_FCW_RC_UP) 4047 ? fRoundingOffMask 4048 : 0; 4049 uint64_t fRoundedOff = uMantissa & fRoundingOffMask; 4050 4051 uMantissa >>= cShiftOff; 4052 uint64_t const uRounding = (fRoundedOff + uRoundingAdd) >> cShiftOff; 4053 uMantissa += uRounding; 4054 if (uMantissa <= (uint64_t)RTPBCD80U_MAX) 4055 { 4056 if (fRoundedOff) 4057 { 4058 if ((uMantissa & 1) && (fFcw & X86_FCW_RC_MASK) == X86_FCW_RC_NEAREST && fRoundedOff == uRoundingAdd) 4059 uMantissa &= ~(uint64_t)1; /* round to even number if equal distance between up/down. */ 4060 else if (uRounding) 4061 fFsw |= X86_FSW_C1; 4062 fFsw |= X86_FSW_PE; 4063 if (!(fFcw & X86_FCW_PM)) 4064 fFsw |= X86_FSW_ES | X86_FSW_B; 4065 } 4066 4067 pd80Dst->s.fSign = fSignIn; 4068 pd80Dst->s.uPad = 0; 4069 for (size_t iPair = 0; iPair < RT_ELEMENTS(pd80Dst->s.abPairs); iPair++) 4070 { 4071 unsigned const uDigits = uMantissa % 100; 4072 uMantissa /= 100; 4073 uint8_t const bLo = uDigits % 10; 4074 uint8_t const bHi = uDigits / 10; 4075 pd80Dst->s.abPairs[iPair] = RTPBCD80U_MAKE_PAIR(bHi, bLo); 4076 } 4077 } 4078 else 4079 { 4080 /* overflowed after rounding. */ 4081 fFsw |= X86_FSW_IE; 4082 if (fFcw & X86_FCW_IM) 4083 *pd80Dst = s_d80Indefinite; 4084 else 4085 fFsw |= X86_FSW_ES | X86_FSW_B | (7 << X86_FSW_TOP_SHIFT); 4086 } 4087 } 4088 /* 4089 * Tiny sub-zero numbers. 4090 */ 4091 else if (iExponent < 0) 4092 { 4093 if (!fSignIn) 4094 { 4095 if ( (fFcw & X86_FCW_RC_MASK) == X86_FCW_RC_UP 4096 || (iExponent == -1 && (fFcw & X86_FCW_RC_MASK) == X86_FCW_RC_NEAREST)) 4097 { 4098 *pd80Dst = s_ad80One[fSignIn]; 4099 fFsw |= X86_FSW_C1; 4100 } 4101 else 4102 *pd80Dst = s_ad80Zeros[fSignIn]; 4103 } 4104 else 4105 { 4106 if ( (fFcw & X86_FCW_RC_MASK) == X86_FCW_RC_UP 4107 || (fFcw & X86_FCW_RC_MASK) == X86_FCW_RC_ZERO 4108 || (iExponent < -1 && (fFcw & X86_FCW_RC_MASK) == X86_FCW_RC_NEAREST)) 4109 *pd80Dst = s_ad80Zeros[fSignIn]; 4110 else 4111 { 4112 *pd80Dst = s_ad80One[fSignIn]; 4113 fFsw |= X86_FSW_C1; 4114 } 4115 } 4116 fFsw |= X86_FSW_PE; 4117 if (!(fFcw & X86_FCW_PM)) 4118 fFsw |= X86_FSW_ES | X86_FSW_B; 4119 } 4120 /* 4121 * Too large/small number outside the target integer range. 4122 */ 4123 else 4124 { 4125 fFsw |= X86_FSW_IE; 4126 if (fFcw & X86_FCW_IM) 4127 *pd80Dst = s_d80Indefinite; 4128 else 4129 fFsw |= X86_FSW_ES | X86_FSW_B | (7 << X86_FSW_TOP_SHIFT); 4130 } 4131 } 4132 /* 4133 * Map both +0 and -0 to integer zero (signless/+). 4134 */ 4135 else if (RTFLOAT80U_IS_ZERO(pr80Src)) 4136 *pd80Dst = s_ad80Zeros[fSignIn]; 4137 /* 4138 * Denormals are just really tiny sub-zero numbers that are either rounded 4139 * to zero, 1 or -1 depending on sign and rounding control. 4140 */ 4141 else if (RTFLOAT80U_IS_PSEUDO_DENORMAL(pr80Src) || RTFLOAT80U_IS_DENORMAL(pr80Src)) 4142 { 4143 if ((fFcw & X86_FCW_RC_MASK) != (fSignIn ? X86_FCW_RC_DOWN : X86_FCW_RC_UP)) 4144 *pd80Dst = s_ad80Zeros[fSignIn]; 4145 else 4146 { 4147 *pd80Dst = s_ad80One[fSignIn]; 4148 fFsw |= X86_FSW_C1; 4149 } 4150 fFsw |= X86_FSW_PE; 4151 if (!(fFcw & X86_FCW_PM)) 4152 fFsw |= X86_FSW_ES | X86_FSW_B; 4153 } 4154 /* 4155 * All other special values are considered invalid arguments and result 4156 * in an IE exception and indefinite value if masked. 4157 */ 4158 else 4159 { 4160 fFsw |= X86_FSW_IE; 4161 if (fFcw & X86_FCW_IM) 4162 *pd80Dst = s_d80Indefinite; 4163 else 4164 fFsw |= X86_FSW_ES | X86_FSW_B | (7 << X86_FSW_TOP_SHIFT); 4165 } 4166 *pu16FSW = fFsw; 3971 4167 } 3972 4168
Note:
See TracChangeset
for help on using the changeset viewer.