VirtualBox

Changeset 94607 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Apr 14, 2022 1:49:03 PM (3 years ago)
Author:
vboxsync
Message:

VMM/IEM,libs/softfloat: C implementation of fadd helper and related rounding tweaks for SoftFloat. bugref:9898

File:
1 edited

Legend:

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

    r94570 r94607  
    43564356AssertCompileSize(RTFLOAT32U,   4);
    43574357
     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
    43584382#ifdef IEM_WITH_FLOAT128_FOR_FPU
    43594383
     
    44734497        :                                                      (uint8_t)softfloat_round_minMag, \
    44744498        0, \
     4499        (uint8_t)((a_fFcw) & X86_FCW_XCPT_MASK), \
    44754500          ((a_fFcw) & X86_FCW_PC_MASK) == X86_FCW_PC_53      ? (uint8_t)64 \
    44764501        : ((a_fFcw) & X86_FCW_PC_MASK) == X86_FCW_PC_24      ? (uint8_t)32 : (uint8_t)80 \
     
    44804505# define IEM_SOFTFLOAT_STATE_TO_FSW(a_fFsw, a_pSoftState, a_fFcw) \
    44814506    (  (a_fFsw) \
    4482      | (uint16_t)((a_pSoftState)->exceptionFlags & softfloat_flag_c1) << (2) \
     4507     | (uint16_t)(((a_pSoftState)->exceptionFlags & softfloat_flag_c1) << 2) \
    44834508     | ((a_pSoftState)->exceptionFlags & X86_FSW_XCPT_MASK) \
    44844509     | (  ((a_pSoftState)->exceptionFlags & X86_FSW_XCPT_MASK) & (~(a_fFcw) & X86_FSW_XCPT_MASK) \
     
    46444669        pr80Dst->s.uMantissa = 0;
    46454670    }
     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 */
     4689DECLINLINE(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;
    46464702    return fFsw;
    46474703}
     
    49595015
    49605016
     5017/** Worker for iemAImpl_fadd_r80_by_r80. */
     5018static 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
    49615027IEM_DECL_IMPL_DEF(void, iemAImpl_fadd_r80_by_r80,(PCX86FXSTATE pFpuState, PIEMFPURESULT pFpuRes,
    49625028                                                  PCRTFLOAT80U pr80Val1, PCRTFLOAT80U pr80Val2))
    49635029{
    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;
    49665068}
    49675069
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