VirtualBox

Changeset 94692 in vbox


Ignore:
Timestamp:
Apr 22, 2022 9:38:41 PM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
151065
Message:

VMM/IEM: Implemented C version of f*com* instruction helpers. bugref:9898

File:
1 edited

Legend:

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

    r94683 r94692  
    57015701
    57025702
    5703 IEM_DECL_IMPL_DEF(void, iemAImpl_fcom_r80_by_r32,(PCX86FXSTATE pFpuState, uint16_t *pFSW,
     5703/**
     5704 * Worker for fcom, fucom, and friends.
     5705 */
     5706static uint16_t iemAImpl_fcom_r80_by_r80_worker(PCRTFLOAT80U pr80Val1, PCRTFLOAT80U pr80Val2,
     5707                                                uint16_t fFcw, uint16_t fFsw, bool fIeOnAllNaNs)
     5708{
     5709    /*
     5710     * Unpack the values.
     5711     */
     5712    bool const fSign1      = pr80Val1->s.fSign;
     5713    int32_t    iExponent1  = pr80Val1->s.uExponent;
     5714    uint64_t   uMantissa1  = pr80Val1->s.uMantissa;
     5715
     5716    bool const fSign2      = pr80Val2->s.fSign;
     5717    int32_t    iExponent2  = pr80Val2->s.uExponent;
     5718    uint64_t   uMantissa2  = pr80Val2->s.uMantissa;
     5719
     5720    /*
     5721     * Check for invalid inputs.
     5722     */
     5723    if (   RTFLOAT80U_IS_387_INVALID_EX(uMantissa1, iExponent1)
     5724        || RTFLOAT80U_IS_387_INVALID_EX(uMantissa2, iExponent2))
     5725    {
     5726         if (!(fFcw & X86_FCW_IM))
     5727             fFsw |= X86_FSW_ES | X86_FSW_B;
     5728         return fFsw | X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3 | X86_FSW_IE;
     5729    }
     5730
     5731    /*
     5732     * Check for NaNs and indefinites, they are all unordered and trumps #DE.
     5733     */
     5734    if (   RTFLOAT80U_IS_INDEFINITE_OR_QUIET_OR_SIGNALLING_NAN_EX(uMantissa1, iExponent1)
     5735        || RTFLOAT80U_IS_INDEFINITE_OR_QUIET_OR_SIGNALLING_NAN_EX(uMantissa2, iExponent2))
     5736    {
     5737        if (   fIeOnAllNaNs
     5738            || RTFLOAT80U_IS_SIGNALLING_NAN_EX(uMantissa1, iExponent1)
     5739            || RTFLOAT80U_IS_SIGNALLING_NAN_EX(uMantissa2, iExponent2))
     5740        {
     5741            fFsw |= X86_FSW_IE;
     5742            if (!(fFcw & X86_FCW_IM))
     5743                fFsw |= X86_FSW_ES | X86_FSW_B;
     5744        }
     5745        return fFsw | X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3;
     5746    }
     5747
     5748    /*
     5749     * Normalize the values.
     5750     */
     5751    if (RTFLOAT80U_IS_DENORMAL_OR_PSEUDO_DENORMAL_EX(uMantissa1, iExponent1))
     5752    {
     5753        if (RTFLOAT80U_IS_PSEUDO_DENORMAL_EX(uMantissa1, iExponent1))
     5754            iExponent1 = 1;
     5755        else
     5756        {
     5757            iExponent1 = 64 - ASMBitLastSetU64(uMantissa1);
     5758            uMantissa1 <<= iExponent1;
     5759            iExponent1 = 1 - iExponent1;
     5760        }
     5761        fFsw |= X86_FSW_DE;
     5762        if (!(fFcw & X86_FCW_DM))
     5763            fFsw |= X86_FSW_ES | X86_FSW_B;
     5764    }
     5765
     5766    if (RTFLOAT80U_IS_DENORMAL_OR_PSEUDO_DENORMAL_EX(uMantissa2, iExponent2))
     5767    {
     5768        if (RTFLOAT80U_IS_PSEUDO_DENORMAL_EX(uMantissa2, iExponent2))
     5769            iExponent2 = 1;
     5770        else
     5771        {
     5772            iExponent2 = 64 - ASMBitLastSetU64(uMantissa2);
     5773            uMantissa2 <<= iExponent2;
     5774            iExponent2 = 1 - iExponent2;
     5775        }
     5776        fFsw |= X86_FSW_DE;
     5777        if (!(fFcw & X86_FCW_DM))
     5778            fFsw |= X86_FSW_ES | X86_FSW_B;
     5779    }
     5780
     5781    /*
     5782     * Test if equal (val1 == val2):
     5783     */
     5784    if (   uMantissa1 == uMantissa2
     5785        && iExponent1 == iExponent2
     5786        && (   fSign1 == fSign2
     5787            || (uMantissa1 == 0 && iExponent1 == 0) /* ignore sign for zero */ ) )
     5788        fFsw |= X86_FSW_C3;
     5789    /*
     5790     * Test if less than (val1 < val2):
     5791     */
     5792    else if (fSign1 && !fSign2)
     5793        fFsw |= X86_FSW_C0;
     5794    else if (fSign1 == fSign2)
     5795    {
     5796        /* Zeros are problematic, however at the most one can be zero here. */
     5797        if (RTFLOAT80U_IS_ZERO_EX(uMantissa1, iExponent1))
     5798            return !fSign1 ? fFsw | X86_FSW_C0 : fFsw;
     5799        if (RTFLOAT80U_IS_ZERO_EX(uMantissa2, iExponent2))
     5800            return fSign1  ? fFsw | X86_FSW_C0 : fFsw;
     5801
     5802        if (  fSign1
     5803            ^ (   iExponent1 < iExponent2
     5804               || (   iExponent1 == iExponent2
     5805                   && uMantissa1 < uMantissa2 ) ) )
     5806        fFsw |= X86_FSW_C0;
     5807    }
     5808    /* else: No flags set if greater. */
     5809
     5810    return fFsw;
     5811}
     5812
     5813
     5814IEM_DECL_IMPL_DEF(void, iemAImpl_fcom_r80_by_r80,(PCX86FXSTATE pFpuState, uint16_t *pfFsw,
     5815                                                  PCRTFLOAT80U pr80Val1, PCRTFLOAT80U pr80Val2))
     5816{
     5817    *pfFsw = iemAImpl_fcom_r80_by_r80_worker(pr80Val1, pr80Val2, pFpuState->FCW, 6 << X86_FSW_TOP_SHIFT, true /*fIeOnAllNaNs*/);
     5818}
     5819
     5820
     5821
     5822
     5823IEM_DECL_IMPL_DEF(void, iemAImpl_fucom_r80_by_r80,(PCX86FXSTATE pFpuState, uint16_t *pfFsw,
     5824                                                   PCRTFLOAT80U pr80Val1, PCRTFLOAT80U pr80Val2))
     5825{
     5826    *pfFsw = iemAImpl_fcom_r80_by_r80_worker(pr80Val1, pr80Val2, pFpuState->FCW, 6 << X86_FSW_TOP_SHIFT, false /*fIeOnAllNaNs*/);
     5827}
     5828
     5829
     5830IEM_DECL_IMPL_DEF(void, iemAImpl_fcom_r80_by_r64,(PCX86FXSTATE pFpuState, uint16_t *pfFsw,
     5831                                                  PCRTFLOAT80U pr80Val1, PCRTFLOAT64U pr64Val2))
     5832{
     5833    RTFLOAT80U r80Val2;
     5834    uint16_t   fFsw = iemAImplConvertR64ToR80(pr64Val2, &r80Val2);
     5835    Assert(!fFsw || fFsw == X86_FSW_DE);
     5836    *pfFsw = iemAImpl_fcom_r80_by_r80_worker(pr80Val1, &r80Val2, pFpuState->FCW, 7 << X86_FSW_TOP_SHIFT, true /*fIeOnAllNaNs*/);
     5837    if (fFsw != 0 && !(*pfFsw & X86_FSW_IE))
     5838    {
     5839        if (!(pFpuState->FCW & X86_FCW_DM))
     5840            fFsw |= X86_FSW_ES | X86_FSW_B;
     5841        *pfFsw |= fFsw;
     5842    }
     5843}
     5844
     5845
     5846IEM_DECL_IMPL_DEF(void, iemAImpl_fcom_r80_by_r32,(PCX86FXSTATE pFpuState, uint16_t *pfFsw,
    57045847                                                  PCRTFLOAT80U pr80Val1, PCRTFLOAT32U pr32Val2))
    57055848{
    5706     RT_NOREF(pFpuState, pFSW, pr80Val1, pr32Val2);
    5707     AssertReleaseFailed();
    5708 }
    5709 
    5710 
    5711 IEM_DECL_IMPL_DEF(void, iemAImpl_fcom_r80_by_r64,(PCX86FXSTATE pFpuState, uint16_t *pFSW,
    5712                                                   PCRTFLOAT80U pr80Val1, PCRTFLOAT64U pr64Val2))
    5713 {
    5714     RT_NOREF(pFpuState, pFSW, pr80Val1, pr64Val2);
    5715     AssertReleaseFailed();
    5716 }
    5717 
    5718 
    5719 IEM_DECL_IMPL_DEF(void, iemAImpl_fcom_r80_by_r80,(PCX86FXSTATE pFpuState, uint16_t *pFSW,
    5720                                                   PCRTFLOAT80U pr80Val1, PCRTFLOAT80U pr80Val2))
    5721 {
    5722     RT_NOREF(pFpuState, pFSW, pr80Val1, pr80Val2);
    5723     AssertReleaseFailed();
    5724 }
    5725 
    5726 
    5727 IEM_DECL_IMPL_DEF(uint32_t, iemAImpl_fcomi_r80_by_r80,(PCX86FXSTATE pFpuState, uint16_t *pFSW,
     5849    RTFLOAT80U r80Val2;
     5850    uint16_t   fFsw = iemAImplConvertR32ToR80(pr32Val2, &r80Val2);
     5851    Assert(!fFsw || fFsw == X86_FSW_DE);
     5852    *pfFsw = iemAImpl_fcom_r80_by_r80_worker(pr80Val1, &r80Val2, pFpuState->FCW, 7 << X86_FSW_TOP_SHIFT, true /*fIeOnAllNaNs*/);
     5853    if (fFsw != 0 && !(*pfFsw & X86_FSW_IE))
     5854    {
     5855        if (!(pFpuState->FCW & X86_FCW_DM))
     5856            fFsw |= X86_FSW_ES | X86_FSW_B;
     5857        *pfFsw |= fFsw;
     5858    }
     5859}
     5860
     5861
     5862IEM_DECL_IMPL_DEF(void, iemAImpl_ficom_r80_by_i32,(PCX86FXSTATE pFpuState, uint16_t *pfFsw,
     5863                                                   PCRTFLOAT80U pr80Val1, int32_t const *pi32Val2))
     5864{
     5865    RTFLOAT80U r80Val2;
     5866    iemAImpl_fcom_r80_by_r80(pFpuState, pfFsw, pr80Val1, iemAImplConvertI32ToR80(*pi32Val2, &r80Val2));
     5867    *pfFsw = (*pfFsw & ~X86_FSW_TOP_MASK) | (7 << X86_FSW_TOP_SHIFT);
     5868}
     5869
     5870
     5871IEM_DECL_IMPL_DEF(void, iemAImpl_ficom_r80_by_i16,(PCX86FXSTATE pFpuState, uint16_t *pfFsw,
     5872                                                   PCRTFLOAT80U pr80Val1, int16_t const *pi16Val2))
     5873{
     5874    RTFLOAT80U r80Val2;
     5875    iemAImpl_fcom_r80_by_r80(pFpuState, pfFsw, pr80Val1, iemAImplConvertI16ToR80(*pi16Val2, &r80Val2));
     5876    *pfFsw = (*pfFsw & ~X86_FSW_TOP_MASK) | (7 << X86_FSW_TOP_SHIFT);
     5877}
     5878
     5879
     5880/**
     5881 * Worker for fcomi & fucomi.
     5882 */
     5883static uint32_t iemAImpl_fcomi_r80_by_r80_worker(PCRTFLOAT80U pr80Val1, PCRTFLOAT80U pr80Val2,
     5884                                                 uint16_t fFcw, uint16_t fFswIn, bool fIeOnAllNaNs, uint16_t *pfFsw)
     5885{
     5886    uint16_t fFsw    = iemAImpl_fcom_r80_by_r80_worker(pr80Val1, pr80Val2, fFcw, 6 << X86_FSW_TOP_SHIFT, fIeOnAllNaNs);
     5887    uint32_t fEflags = ((fFsw & X86_FSW_C3) >> (X86_FSW_C3_BIT - X86_EFL_ZF_BIT))
     5888                     | ((fFsw & X86_FSW_C2) >> (X86_FSW_C2_BIT - X86_EFL_PF_BIT))
     5889                     | ((fFsw & X86_FSW_C0) >> (X86_FSW_C0_BIT - X86_EFL_CF_BIT));
     5890
     5891    /* Note! C1 is not cleared as per docs! Everything is preserved. */
     5892    *pfFsw = (fFsw & ~X86_FSW_C_MASK) | (fFswIn & X86_FSW_C_MASK);
     5893    return fEflags | X86_EFL_IF | X86_EFL_RA1_MASK;
     5894}
     5895
     5896
     5897IEM_DECL_IMPL_DEF(uint32_t, iemAImpl_fcomi_r80_by_r80,(PCX86FXSTATE pFpuState, uint16_t *pfFsw,
    57285898                                                       PCRTFLOAT80U pr80Val1, PCRTFLOAT80U pr80Val2))
    57295899{
    5730     RT_NOREF(pFpuState, pFSW, pr80Val1, pr80Val2);
    5731     AssertReleaseFailed();
    5732     return 0;
    5733 }
    5734 
    5735 
    5736 IEM_DECL_IMPL_DEF(void, iemAImpl_fucom_r80_by_r80,(PCX86FXSTATE pFpuState, uint16_t *pFSW,
    5737                                                    PCRTFLOAT80U pr80Val1, PCRTFLOAT80U pr80Val2))
    5738 {
    5739     RT_NOREF(pFpuState, pFSW, pr80Val1, pr80Val2);
    5740     AssertReleaseFailed();
    5741 }
    5742 
    5743 
    5744 IEM_DECL_IMPL_DEF(uint32_t, iemAImpl_fucomi_r80_by_r80,(PCX86FXSTATE pFpuState, uint16_t *pu16Fsw,
     5900    return iemAImpl_fcomi_r80_by_r80_worker(pr80Val1, pr80Val2, pFpuState->FCW, pFpuState->FSW, true /*fIeOnAllNaNs*/, pfFsw);
     5901}
     5902
     5903
     5904IEM_DECL_IMPL_DEF(uint32_t, iemAImpl_fucomi_r80_by_r80,(PCX86FXSTATE pFpuState, uint16_t *pfFsw,
    57455905                                                        PCRTFLOAT80U pr80Val1, PCRTFLOAT80U pr80Val2))
    57465906{
    5747     RT_NOREF(pFpuState, pu16Fsw, pr80Val1, pr80Val2);
    5748     AssertReleaseFailed();
    5749     return 0;
    5750 }
    5751 
    5752 
    5753 IEM_DECL_IMPL_DEF(void, iemAImpl_ficom_r80_by_i16,(PCX86FXSTATE pFpuState, uint16_t *pu16Fsw,
    5754                                                    PCRTFLOAT80U pr80Val1, int16_t const *pi16Val2))
    5755 {
    5756     RT_NOREF(pFpuState, pu16Fsw, pr80Val1, pi16Val2);
    5757     AssertReleaseFailed();
    5758 }
    5759 
    5760 
    5761 IEM_DECL_IMPL_DEF(void, iemAImpl_ficom_r80_by_i32,(PCX86FXSTATE pFpuState, uint16_t *pu16Fsw,
    5762                                                    PCRTFLOAT80U pr80Val1, int32_t const *pi32Val2))
    5763 {
    5764     RT_NOREF(pFpuState, pu16Fsw, pr80Val1, pi32Val2);
    5765     AssertReleaseFailed();
     5907    return iemAImpl_fcomi_r80_by_r80_worker(pr80Val1, pr80Val2, pFpuState->FCW, pFpuState->FSW, false /*fIeOnAllNaNs*/, pfFsw);
    57665908}
    57675909
Note: See TracChangeset for help on using the changeset viewer.

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