- Timestamp:
- Apr 14, 2022 1:49:03 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp
r94570 r94607 4356 4356 AssertCompileSize(RTFLOAT32U, 4); 4357 4357 4358 /** 4359 * Normalizes a possible pseudo-normal value. 4360 * 4361 * Psuedo-normal values are some oddities from the 8087 & 287 days. They are 4362 * denormals with the J-bit set, so they can simply be rewritten as 2**-16382, 4363 * i.e. changing uExponent from 0 to 1. 4364 * 4365 * This macro will declare a RTFLOAT80U with the name given by 4366 * @a a_r80ValNormalized and update the @a a_pr80Val variable to point to it if 4367 * a normalization was performed. 4368 * 4369 * @note This must be applied before calling SoftFloat with a value that couldbe 4370 * a pseudo-denormal, as SoftFloat doesn't handle pseudo-denormals 4371 * correctly. 4372 */ 4373 #define IEM_NORMALIZE_PSEUDO_DENORMAL(a_pr80Val, a_r80ValNormalized) \ 4374 RTFLOAT80U a_r80ValNormalized; \ 4375 if (RTFLOAT80U_IS_PSEUDO_DENORMAL(a_pr80Val)) \ 4376 { \ 4377 a_r80ValNormalized = *a_pr80Val; \ 4378 a_r80ValNormalized.s.uExponent = 1; \ 4379 a_pr80Val = &a_r80ValNormalized; \ 4380 } else do {} while (0) 4381 4358 4382 #ifdef IEM_WITH_FLOAT128_FOR_FPU 4359 4383 … … 4473 4497 : (uint8_t)softfloat_round_minMag, \ 4474 4498 0, \ 4499 (uint8_t)((a_fFcw) & X86_FCW_XCPT_MASK), \ 4475 4500 ((a_fFcw) & X86_FCW_PC_MASK) == X86_FCW_PC_53 ? (uint8_t)64 \ 4476 4501 : ((a_fFcw) & X86_FCW_PC_MASK) == X86_FCW_PC_24 ? (uint8_t)32 : (uint8_t)80 \ … … 4480 4505 # define IEM_SOFTFLOAT_STATE_TO_FSW(a_fFsw, a_pSoftState, a_fFcw) \ 4481 4506 ( (a_fFsw) \ 4482 | (uint16_t)(( a_pSoftState)->exceptionFlags & softfloat_flag_c1) << (2) \4507 | (uint16_t)(((a_pSoftState)->exceptionFlags & softfloat_flag_c1) << 2) \ 4483 4508 | ((a_pSoftState)->exceptionFlags & X86_FSW_XCPT_MASK) \ 4484 4509 | ( ((a_pSoftState)->exceptionFlags & X86_FSW_XCPT_MASK) & (~(a_fFcw) & X86_FSW_XCPT_MASK) \ … … 4644 4669 pr80Dst->s.uMantissa = 0; 4645 4670 } 4671 return fFsw; 4672 } 4673 4674 4675 /** 4676 * Helper for transfering exception and C1 to FSW and setting the result value 4677 * accordingly. 4678 * 4679 * @returns Updated FSW. 4680 * @param pSoftState The SoftFloat state following the operation. 4681 * @param r80XResult The result of the SoftFloat operation. 4682 * @param pr80Result Where to store the result for IEM. 4683 * @param fFcw The FPU control word. 4684 * @param fFsw The FSW before the operation, with necessary bits 4685 * cleared and such. 4686 * @param pr80XcptResult Alternative return value for use an unmasked \#IE is 4687 * raised. 4688 */ 4689 DECLINLINE(uint16_t) iemFpuSoftStateAndF80ToFswAndIprtResult(softfloat_state_t const *pSoftState, extFloat80_t r80XResult, 4690 PRTFLOAT80U pr80Result, uint16_t fFcw, uint16_t fFsw, 4691 PCRTFLOAT80U pr80XcptResult) 4692 { 4693 fFsw |= (pSoftState->exceptionFlags & X86_FSW_XCPT_MASK) 4694 | (uint16_t)((pSoftState->exceptionFlags & softfloat_flag_c1) << 2); 4695 if (fFsw & ~fFcw & X86_FSW_XCPT_MASK) 4696 fFsw |= X86_FSW_ES | X86_FSW_B; 4697 4698 if (!(fFsw & ~fFcw & X86_FSW_IE)) 4699 iemFpuSoftF80ToIprt(pr80Result, r80XResult); 4700 else 4701 *pr80Result = *pr80XcptResult; 4646 4702 return fFsw; 4647 4703 } … … 4959 5015 4960 5016 5017 /** Worker for iemAImpl_fadd_r80_by_r80. */ 5018 static uint16_t iemAImpl_fadd_f80_r80_worker(PCRTFLOAT80U pr80Val1, PCRTFLOAT80U pr80Val2, PRTFLOAT80U pr80Result, 5019 uint16_t fFcw, uint16_t fFsw, PCRTFLOAT80U pr80Val1Org) 5020 { 5021 softfloat_state_t SoftState = IEM_SOFTFLOAT_STATE_INITIALIZER_FROM_FCW(fFcw); 5022 extFloat80_t r80XResult = extF80_add(iemFpuSoftF80FromIprt(pr80Val1), iemFpuSoftF80FromIprt(pr80Val2), &SoftState); 5023 return iemFpuSoftStateAndF80ToFswAndIprtResult(&SoftState, r80XResult, pr80Result, fFcw, fFsw, pr80Val1Org); 5024 } 5025 5026 4961 5027 IEM_DECL_IMPL_DEF(void, iemAImpl_fadd_r80_by_r80,(PCX86FXSTATE pFpuState, PIEMFPURESULT pFpuRes, 4962 5028 PCRTFLOAT80U pr80Val1, PCRTFLOAT80U pr80Val2)) 4963 5029 { 4964 RT_NOREF(pFpuState, pFpuRes, pr80Val1, pr80Val2); 4965 AssertReleaseFailed(); 5030 uint16_t const fFcw = pFpuState->FCW; 5031 uint16_t fFsw = (pFpuState->FSW & (X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3)) | (6 << X86_FSW_TOP_SHIFT); 5032 5033 /* SoftFloat does not check for Pseudo-Infinity, Pseudo-Nan and Unnormals. */ 5034 if (RTFLOAT80U_IS_387_INVALID(pr80Val1) || RTFLOAT80U_IS_387_INVALID(pr80Val2)) 5035 { 5036 if (fFcw & X86_FCW_IM) 5037 pFpuRes->r80Result = g_r80Indefinite; 5038 else 5039 { 5040 pFpuRes->r80Result = *pr80Val1; 5041 fFsw |= X86_FSW_ES | X86_FSW_B; 5042 } 5043 fFsw |= X86_FSW_IE; 5044 } 5045 /* SoftFloat does not check for denormals and certainly not report them to us. NaNs trumps denormals. */ 5046 else if ( (RTFLOAT80U_IS_DENORMAL_OR_PSEUDO_DENORMAL(pr80Val1) && !RTFLOAT80U_IS_NAN(pr80Val2)) 5047 || (RTFLOAT80U_IS_DENORMAL_OR_PSEUDO_DENORMAL(pr80Val2) && !RTFLOAT80U_IS_NAN(pr80Val1)) ) 5048 { 5049 if (fFcw & X86_FCW_DM) 5050 { 5051 PCRTFLOAT80U const pr80Val1Org = pr80Val1; 5052 IEM_NORMALIZE_PSEUDO_DENORMAL(pr80Val1, r80Val1Normalized); 5053 IEM_NORMALIZE_PSEUDO_DENORMAL(pr80Val2, r80Val2Normalized); 5054 fFsw = iemAImpl_fadd_f80_r80_worker(pr80Val1, pr80Val2, &pFpuRes->r80Result, fFcw, fFsw, pr80Val1Org); 5055 } 5056 else 5057 { 5058 pFpuRes->r80Result = *pr80Val1; 5059 fFsw |= X86_FSW_ES | X86_FSW_B; 5060 } 5061 fFsw |= X86_FSW_DE; 5062 } 5063 /* SoftFloat can handle the rest: */ 5064 else 5065 fFsw = iemAImpl_fadd_f80_r80_worker(pr80Val1, pr80Val2, &pFpuRes->r80Result, fFcw, fFsw, pr80Val1); 5066 5067 pFpuRes->FSW = fFsw; 4966 5068 } 4967 5069
Note:
See TracChangeset
for help on using the changeset viewer.