VirtualBox

Changeset 96286 in vbox


Ignore:
Timestamp:
Aug 18, 2022 8:11:28 AM (2 years ago)
Author:
vboxsync
Message:

VMM/IEM: Implement mulps/mulpd instructions, bugref:9898

Location:
trunk/src/VBox/VMM
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm

    r96253 r96286  
    45874587IEMIMPL_FP_F2 addps
    45884588IEMIMPL_FP_F2 addpd
     4589IEMIMPL_FP_F2 mulps
     4590IEMIMPL_FP_F2 mulpd
  • trunk/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp

    r96264 r96286  
    1388113881
    1388213882    /* If DAZ is set \#DE is never set. */
    13883     if (fMxcsr & X86_MXCSR_DAZ)
     13883    if (   fMxcsr & X86_MXCSR_DAZ
     13884        || (   (fXcpt & X86_MXCSR_DE) /* Softfloat sets DE for sub-normal values. */
     13885            && (RTFLOAT32U_IS_SUBNORMAL(pr32Result))))
    1388413886        fXcpt &= ~X86_MXCSR_DE;
    13885     else /* Need to set \#DE when either the result or one of the source operands is a De-normal (softfloat doesn't do this always). */
    13886         fXcpt |=   (   RTFLOAT32U_IS_SUBNORMAL(pr32Result)
    13887                     || RTFLOAT32U_IS_SUBNORMAL(pr32Src1)
     13887    else /* Need to set \#DE when one of the source operands is a De-normal. */
     13888        fXcpt |=   (   RTFLOAT32U_IS_SUBNORMAL(pr32Src1)
    1388813889                    || RTFLOAT32U_IS_SUBNORMAL(pr32Src2))
    1388913890                 ? X86_MXCSR_DE
     
    1392413925
    1392513926    /* If DAZ is set \#DE is never set. */
    13926     if (fMxcsr & X86_MXCSR_DAZ)
     13927    if (   fMxcsr & X86_MXCSR_DAZ
     13928        || (   (fXcpt & X86_MXCSR_DE) /* Softfloat sets DE for sub-normal values. */
     13929            && (RTFLOAT64U_IS_SUBNORMAL(pr64Result))))
    1392713930        fXcpt &= ~X86_MXCSR_DE;
    13928     else /* Need to set \#DE when either the result or one of the source operands is a De-normal (softfloat doesn't do this always). */
    13929         fXcpt |=   (   RTFLOAT64U_IS_SUBNORMAL(pr64Result)
    13930                     || RTFLOAT64U_IS_SUBNORMAL(pr64Src1)
     13931    else /* Need to set \#DE when one of the source operands is a De-normal. */
     13932        fXcpt |=   (   RTFLOAT64U_IS_SUBNORMAL(pr64Src1)
    1393113933                    || RTFLOAT64U_IS_SUBNORMAL(pr64Src2))
    1393213934                 ? X86_MXCSR_DE
     
    1398913991 * of the source operands contains a NaN value, setting the output accordingly.
    1399013992 *
    13991  * @returns Flag whether the operation can continue (true) or whether a NaN value was detected in one of the operands (false).
     13993 * @returns Flag whether the operation can continue (false) or whether a NaN value was detected in one of the operands (true).
    1399213994 * @param   pr32Res         Where to store the result in case the operation can't continue.
    1399313995 * @param   pr32Val1        The first input operand.
     
    1400514007        pr32Res->s.uFraction |= RT_BIT_32(RTFLOAT32U_FRACTION_BITS - 1);
    1400614008        *pfMxcsr |= (cSNan ? X86_MXCSR_IE : 0);
    14007         return false;
     14009        return true;
    1400814010    }
    1400914011    else if (cSNan)
     
    1401314015        pr32Res->s.uFraction |= RT_BIT_32(RTFLOAT32U_FRACTION_BITS - 1);
    1401414016        *pfMxcsr |= X86_MXCSR_IE;
    14015         return false;
     14017        return true;
    1401614018    }
    1401714019    else if (cQNan)
     
    1401914021        /* The QNan operand is placed into the result. */
    1402014022        *pr32Res = RTFLOAT32U_IS_QUIET_NAN(pr32Val1) ? *pr32Val1 : *pr32Val2;
    14021         return false;
     14023        return true;
    1402214024    }
    1402314025
    1402414026    Assert(!cQNan && !cSNan);
    14025     return true;
     14027    return false;
     14028}
     14029
     14030
     14031/**
     14032 * Checks all input values for valid inputs returning whether the operation can continue.
     14033 *
     14034 * @returns Flag whether the operation can continue (true) or whether a NaN value was detected in one of the operands (false).
     14035 * @param   pResult         Where to store the result in case the operation can't continue.
     14036 * @param   puSrc1          The first input operand.
     14037 * @param   puSrc2          The second input operand.
     14038 * @param   fMxcsr          The MXCSR flags.
     14039 */
     14040static bool iemSseCheckXmmInputBinaryR32(PIEMSSERESULT pResult, PCX86XMMREG puSrc1, PCX86XMMREG puSrc2, uint32_t fMxcsr)
     14041{
     14042    bool fNan = iemSseCheckInputBinaryR32(&pResult->uResult.ar32[0], &puSrc1->ar32[0], &puSrc2->ar32[0], &fMxcsr);
     14043    fNan     |= iemSseCheckInputBinaryR32(&pResult->uResult.ar32[1], &puSrc1->ar32[1], &puSrc2->ar32[1], &fMxcsr);
     14044    fNan     |= iemSseCheckInputBinaryR32(&pResult->uResult.ar32[2], &puSrc1->ar32[3], &puSrc2->ar32[2], &fMxcsr);
     14045    fNan     |= iemSseCheckInputBinaryR32(&pResult->uResult.ar32[3], &puSrc1->ar32[2], &puSrc2->ar32[3], &fMxcsr);
     14046    if (fNan)
     14047        pResult->MXCSR = fMxcsr;
     14048
     14049    return !fNan;
    1402614050}
    1402714051
     
    1403114055 * of the source operands contains a NaN value, setting the output accordingly.
    1403214056 *
    14033  * @returns Flag whether the operation can continue (true) or whether a NaN value was detected in one of the operands (false).
     14057 * @returns Flag whether the operation can continue (false) or whether a NaN value was detected in one of the operands (true).
    1403414058 * @param   pr64Res         Where to store the result in case the operation can't continue.
    1403514059 * @param   pr64Val1        The first input operand.
     
    1404714071        pr64Res->s64.uFraction |= RT_BIT_64(RTFLOAT64U_FRACTION_BITS - 1);
    1404814072        *pfMxcsr |= (cSNan ? X86_MXCSR_IE : 0);
    14049         return false;
     14073        return true;
    1405014074    }
    1405114075    else if (cSNan)
     
    1405514079        pr64Res->s64.uFraction |= RT_BIT_64(RTFLOAT64U_FRACTION_BITS - 1);
    1405614080        *pfMxcsr |= X86_MXCSR_IE;
    14057         return false;
     14081        return true;
    1405814082    }
    1405914083    else if (cQNan)
     
    1406114085        /* The QNan operand is placed into the result. */
    1406214086        *pr64Res = RTFLOAT64U_IS_QUIET_NAN(pr64Val1) ? *pr64Val1 : *pr64Val2;
    14063         return false;
     14087        return true;
    1406414088    }
    1406514089
    1406614090    Assert(!cQNan && !cSNan);
    14067     return true;
    14068 }
     14091    return false;
     14092}
     14093
     14094
     14095/**
     14096 * Checks all input values for valid inputs returning whether the operation can continue.
     14097 *
     14098 * @returns Flag whether the operation can continue (true) or whether a NaN value was detected in one of the operands (false).
     14099 * @param   pResult         Where to store the result in case the operation can't continue.
     14100 * @param   puSrc1          The first input operand.
     14101 * @param   puSrc2          The second input operand.
     14102 * @param   fMxcsr          The MXCSR flags.
     14103 */
     14104static bool iemSseCheckXmmInputBinaryR64(PIEMSSERESULT pResult, PCX86XMMREG puSrc1, PCX86XMMREG puSrc2, uint32_t fMxcsr)
     14105{
     14106    bool fNan = iemSseCheckInputBinaryR64(&pResult->uResult.ar64[0], &puSrc1->ar64[0], &puSrc2->ar64[0], &fMxcsr);
     14107    fNan     |= iemSseCheckInputBinaryR64(&pResult->uResult.ar64[1], &puSrc1->ar64[1], &puSrc2->ar64[1], &fMxcsr);
     14108    if (fNan)
     14109        pResult->MXCSR = fMxcsr;
     14110
     14111    return !fNan;
     14112}
     14113
    1406914114#endif
    1407014115
     
    1407614121static uint32_t iemAImpl_addps_u128_worker(PRTFLOAT32U pr32Res, uint32_t fMxcsr, PCRTFLOAT32U pr32Val1, PCRTFLOAT32U pr32Val2)
    1407714122{
    14078     if (!iemSseCheckInputBinaryR32(pr32Res, pr32Val1, pr32Val2, &fMxcsr))
    14079         return fMxcsr;
    14080 
    1408114123    RTFLOAT32U r32Src1, r32Src2;
    1408214124    iemSsePrepareValueR32(&r32Src1, fMxcsr, pr32Val1);
     
    1409014132IEM_DECL_IMPL_DEF(void, iemAImpl_addps_u128,(PX86FXSTATE pFpuState, PIEMSSERESULT pResult, PCX86XMMREG puSrc1, PCX86XMMREG puSrc2))
    1409114133{
    14092     pResult->MXCSR |= iemAImpl_addps_u128_worker(&pResult->uResult.ar32[0], pFpuState->MXCSR, &puSrc1->ar32[0], &puSrc2->ar32[0]);
    14093     pResult->MXCSR |= iemAImpl_addps_u128_worker(&pResult->uResult.ar32[1], pFpuState->MXCSR, &puSrc1->ar32[1], &puSrc2->ar32[1]);
    14094     pResult->MXCSR |= iemAImpl_addps_u128_worker(&pResult->uResult.ar32[2], pFpuState->MXCSR, &puSrc1->ar32[2], &puSrc2->ar32[2]);
    14095     pResult->MXCSR |= iemAImpl_addps_u128_worker(&pResult->uResult.ar32[3], pFpuState->MXCSR, &puSrc1->ar32[3], &puSrc2->ar32[3]);
     14134    if (iemSseCheckXmmInputBinaryR32(pResult, puSrc1, puSrc2, pFpuState->MXCSR))
     14135    {
     14136        pResult->MXCSR |= iemAImpl_addps_u128_worker(&pResult->uResult.ar32[0], pFpuState->MXCSR, &puSrc1->ar32[0], &puSrc2->ar32[0]);
     14137        pResult->MXCSR |= iemAImpl_addps_u128_worker(&pResult->uResult.ar32[1], pFpuState->MXCSR, &puSrc1->ar32[1], &puSrc2->ar32[1]);
     14138        pResult->MXCSR |= iemAImpl_addps_u128_worker(&pResult->uResult.ar32[2], pFpuState->MXCSR, &puSrc1->ar32[2], &puSrc2->ar32[2]);
     14139        pResult->MXCSR |= iemAImpl_addps_u128_worker(&pResult->uResult.ar32[3], pFpuState->MXCSR, &puSrc1->ar32[3], &puSrc2->ar32[3]);
     14140    }
    1409614141}
    1409714142#endif
     
    1410414149static uint32_t iemAImpl_addpd_u128_worker(PRTFLOAT64U pr64Res, uint32_t fMxcsr, PCRTFLOAT64U pr64Val1, PCRTFLOAT64U pr64Val2)
    1410514150{
    14106     if (!iemSseCheckInputBinaryR64(pr64Res, pr64Val1, pr64Val2, &fMxcsr))
    14107         return fMxcsr;
    14108 
    1410914151    RTFLOAT64U r64Src1, r64Src2;
    1411014152    iemSsePrepareValueR64(&r64Src1, fMxcsr, pr64Val1);
     
    1411814160IEM_DECL_IMPL_DEF(void, iemAImpl_addpd_u128,(PX86FXSTATE pFpuState, PIEMSSERESULT pResult, PCX86XMMREG puSrc1, PCX86XMMREG puSrc2))
    1411914161{
    14120     pResult->MXCSR |= iemAImpl_addpd_u128_worker(&pResult->uResult.ar64[0], pFpuState->MXCSR, &puSrc1->ar64[0], &puSrc2->ar64[0]);
    14121     pResult->MXCSR |= iemAImpl_addpd_u128_worker(&pResult->uResult.ar64[1], pFpuState->MXCSR, &puSrc1->ar64[1], &puSrc2->ar64[1]);
     14162    if (iemSseCheckXmmInputBinaryR64(pResult, puSrc1, puSrc2, pFpuState->MXCSR))
     14163    {
     14164        pResult->MXCSR |= iemAImpl_addpd_u128_worker(&pResult->uResult.ar64[0], pFpuState->MXCSR, &puSrc1->ar64[0], &puSrc2->ar64[0]);
     14165        pResult->MXCSR |= iemAImpl_addpd_u128_worker(&pResult->uResult.ar64[1], pFpuState->MXCSR, &puSrc1->ar64[1], &puSrc2->ar64[1]);
     14166    }
    1412214167}
    1412314168#endif
     14169
     14170
     14171/**
     14172 * MULPS
     14173 */
     14174#ifdef IEM_WITHOUT_ASSEMBLY
     14175static uint32_t iemAImpl_mulps_u128_worker(PRTFLOAT32U pr32Res, uint32_t fMxcsr, PCRTFLOAT32U pr32Val1, PCRTFLOAT32U pr32Val2)
     14176{
     14177    RTFLOAT32U r32Src1, r32Src2;
     14178    iemSsePrepareValueR32(&r32Src1, fMxcsr, pr32Val1);
     14179    iemSsePrepareValueR32(&r32Src2, fMxcsr, pr32Val2);
     14180    softfloat_state_t SoftState = IEM_SOFTFLOAT_STATE_INITIALIZER_FROM_MXCSR(fMxcsr);
     14181    float32_t r32Result = f32_mul(iemFpSoftF32FromIprt(&r32Src1), iemFpSoftF32FromIprt(&r32Src2), &SoftState);
     14182    return iemSseSoftStateAndR32ToMxcsrAndIprtResult(&SoftState, r32Result, pr32Res, fMxcsr, &r32Src1, &r32Src2);
     14183}
     14184
     14185
     14186IEM_DECL_IMPL_DEF(void, iemAImpl_mulps_u128,(PX86FXSTATE pFpuState, PIEMSSERESULT pResult, PCX86XMMREG puSrc1, PCX86XMMREG puSrc2))
     14187{
     14188    if (iemSseCheckXmmInputBinaryR32(pResult, puSrc1, puSrc2, pFpuState->MXCSR))
     14189    {
     14190        pResult->MXCSR |= iemAImpl_mulps_u128_worker(&pResult->uResult.ar32[0], pFpuState->MXCSR, &puSrc1->ar32[0], &puSrc2->ar32[0]);
     14191        pResult->MXCSR |= iemAImpl_mulps_u128_worker(&pResult->uResult.ar32[1], pFpuState->MXCSR, &puSrc1->ar32[1], &puSrc2->ar32[1]);
     14192        pResult->MXCSR |= iemAImpl_mulps_u128_worker(&pResult->uResult.ar32[2], pFpuState->MXCSR, &puSrc1->ar32[2], &puSrc2->ar32[2]);
     14193        pResult->MXCSR |= iemAImpl_mulps_u128_worker(&pResult->uResult.ar32[3], pFpuState->MXCSR, &puSrc1->ar32[3], &puSrc2->ar32[3]);
     14194    }
     14195}
     14196#endif
     14197
     14198
     14199/**
     14200 * MULPD
     14201 */
     14202#ifdef IEM_WITHOUT_ASSEMBLY
     14203static uint32_t iemAImpl_mulpd_u128_worker(PRTFLOAT64U pr64Res, uint32_t fMxcsr, PCRTFLOAT64U pr64Val1, PCRTFLOAT64U pr64Val2)
     14204{
     14205    RTFLOAT64U r64Src1, r64Src2;
     14206    iemSsePrepareValueR64(&r64Src1, fMxcsr, pr64Val1);
     14207    iemSsePrepareValueR64(&r64Src2, fMxcsr, pr64Val2);
     14208    softfloat_state_t SoftState = IEM_SOFTFLOAT_STATE_INITIALIZER_FROM_MXCSR(fMxcsr);
     14209    float64_t r64Result = f64_mul(iemFpSoftF64FromIprt(&r64Src1), iemFpSoftF64FromIprt(&r64Src2), &SoftState);
     14210    return iemSseSoftStateAndR64ToMxcsrAndIprtResult(&SoftState, r64Result, pr64Res, fMxcsr, &r64Src1, &r64Src2);
     14211}
     14212
     14213
     14214IEM_DECL_IMPL_DEF(void, iemAImpl_mulpd_u128,(PX86FXSTATE pFpuState, PIEMSSERESULT pResult, PCX86XMMREG puSrc1, PCX86XMMREG puSrc2))
     14215{
     14216    if (iemSseCheckXmmInputBinaryR64(pResult, puSrc1, puSrc2, pFpuState->MXCSR))
     14217    {
     14218        pResult->MXCSR |= iemAImpl_mulpd_u128_worker(&pResult->uResult.ar64[0], pFpuState->MXCSR, &puSrc1->ar64[0], &puSrc2->ar64[0]);
     14219        pResult->MXCSR |= iemAImpl_mulpd_u128_worker(&pResult->uResult.ar64[1], pFpuState->MXCSR, &puSrc1->ar64[1], &puSrc2->ar64[1]);
     14220    }
     14221}
     14222#endif
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsTwoByte0f.cpp.h

    r96253 r96286  
    38793879FNIEMOP_STUB(iemOp_addsd_Vsd_Wsd);
    38803880
     3881
    38813882/** Opcode      0x0f 0x59 - mulps Vps, Wps */
    3882 FNIEMOP_STUB(iemOp_mulps_Vps_Wps);
     3883FNIEMOP_DEF(iemOp_mulps_Vps_Wps)
     3884{
     3885    IEMOP_MNEMONIC2(RM, MULPS, mulps, Vps, Wps, DISOPTYPE_HARMLESS, 0);
     3886    return FNIEMOP_CALL_1(iemOpCommonSseFp_FullFull_To_Full, iemAImpl_mulps_u128);
     3887}
     3888
     3889
    38833890/** Opcode 0x66 0x0f 0x59 - mulpd Vpd, Wpd */
    3884 FNIEMOP_STUB(iemOp_mulpd_Vpd_Wpd);
     3891FNIEMOP_DEF(iemOp_mulpd_Vpd_Wpd)
     3892{
     3893    IEMOP_MNEMONIC2(RM, MULPD, mulpd, Vpd, Wpd, DISOPTYPE_HARMLESS, 0);
     3894    return FNIEMOP_CALL_1(iemOpCommonSseFp_FullFull_To_Full, iemAImpl_mulpd_u128);
     3895}
     3896
     3897
    38853898/** Opcode 0xf3 0x0f 0x59 - mulss Vss, Wss */
    38863899FNIEMOP_STUB(iemOp_mulss_Vss_Wss);
  • trunk/src/VBox/VMM/include/IEMInternal.h

    r96253 r96286  
    24182418FNIEMAIMPLFPSSEF2U128 iemAImpl_addps_u128;
    24192419FNIEMAIMPLFPSSEF2U128 iemAImpl_addpd_u128;
     2420FNIEMAIMPLFPSSEF2U128 iemAImpl_mulps_u128;
     2421FNIEMAIMPLFPSSEF2U128 iemAImpl_mulpd_u128;
    24202422
    24212423FNIEMAIMPLFPAVXF3U128 iemAImpl_vaddps_u128, iemAImpl_vaddps_u128_fallback;
    24222424FNIEMAIMPLFPAVXF3U128 iemAImpl_vaddpd_u128, iemAImpl_vaddpd_u128_fallback;
     2425FNIEMAIMPLFPAVXF3U128 iemAImpl_vmulps_u128, iemAImpl_vmulps_u128_fallback;
     2426FNIEMAIMPLFPAVXF3U128 iemAImpl_vmulpd_u128, iemAImpl_vmulpd_u128_fallback;
    24232427
    24242428FNIEMAIMPLFPAVXF3U256 iemAImpl_vaddps_u256, iemAImpl_vaddps_u256_fallback;
    24252429FNIEMAIMPLFPAVXF3U256 iemAImpl_vaddpd_u256, iemAImpl_vaddpd_u256_fallback;
     2430FNIEMAIMPLFPAVXF3U256 iemAImpl_vmulps_u256, iemAImpl_vmulps_u256_fallback;
     2431FNIEMAIMPLFPAVXF3U256 iemAImpl_vmulpd_u256, iemAImpl_vmulpd_u256_fallback;
    24262432/** @} */
    24272433
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