VirtualBox

Changeset 96247 in vbox


Ignore:
Timestamp:
Aug 17, 2022 9:08:30 AM (2 years ago)
Author:
vboxsync
Message:

VMM/IEM: Start implementing floating point SSE instructions using addps, added some new infrastructure bits (mostly untested), bugref:9898

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

Legend:

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

    r95575 r96247  
    41754175
    41764176
     4177/** \#XF(0)/\#XM(0) - 19.   */
     4178VBOXSTRICTRC iemRaiseSimdFpException(PVMCPUCC pVCpu) RT_NOEXCEPT
     4179{
     4180    return iemRaiseXcptOrInt(pVCpu, 0, X86_XCPT_XF, IEM_XCPT_FLAGS_T_CPU_XCPT, 0, 0);
     4181}
     4182
     4183
    41774184/** Accessed via IEMOP_RAISE_DIVIDE_ERROR.   */
    41784185IEM_CIMPL_DEF_0(iemCImplRaiseDivideError)
     
    51275134    iemFpuUpdateOpcodeAndIpWorker(pVCpu, pFpuCtx);
    51285135    iemFpuStackPushOverflowOnly(pVCpu, pFpuCtx);
     5136}
     5137
     5138/** @}  */
     5139
     5140
     5141/** @name   SSE+AVX SIMD access and helpers.
     5142 *
     5143 * @{
     5144 */
     5145/**
     5146 * Stores a result in a SIMD XMM register, updates the MXCSR.
     5147 *
     5148 * @param   pVCpu               The cross context virtual CPU structure of the calling thread.
     5149 * @param   pResult             The result to store.
     5150 * @param   iXmmReg             Which SIMD XMM register to store the result in.
     5151 */
     5152void iemSseStoreResult(PVMCPUCC pVCpu, PCIEMSSERESULT pResult, uint8_t iXmmReg) RT_NOEXCEPT
     5153{
     5154    PX86FXSTATE pFpuCtx = &pVCpu->cpum.GstCtx.XState.x87;
     5155    pFpuCtx->MXCSR |= pResult->MXCSR & X86_MXCSR_XCPT_FLAGS;
     5156    pVCpu->cpum.GstCtx.XState.x87.aXMM[iXmmReg] = pResult->uResult;
    51295157}
    51305158
  • trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm

    r96130 r96247  
    44044404IEMIMPL_V_PMOV_SZ_X pmovzxdq
    44054405
     4406
     4407;;
     4408; Need to move this as well somewhere better?
     4409;
     4410struc IEMSSERESULT
     4411    .uResult      resd 4
     4412    .MXCSR        resd 1
     4413endstruc
     4414
     4415
     4416;;
     4417; Need to move this as well somewhere better?
     4418;
     4419struc IEMAVX128RESULT
     4420    .uResult      resd 4
     4421    .MXCSR        resd 1
     4422endstruc
     4423
     4424
     4425;;
     4426; Need to move this as well somewhere better?
     4427;
     4428struc IEMAVX256RESULT
     4429    .uResult      resd 8
     4430    .MXCSR        resd 1
     4431endstruc
     4432
     4433
     4434;;
     4435; Initialize the SSE MXCSR register using the guest value partially to
     4436; account for rounding mode.
     4437;
     4438; @uses     4 bytes of stack to save the original value, T0.
     4439; @param    1       Expression giving the address of the FXSTATE of the guest.
     4440;
     4441%macro SSE_LD_FXSTATE_MXCSR 1
     4442        sub     xSP, 4
     4443
     4444        stmxcsr [xSP]
     4445        mov     T0_32, [%1 + X86FXSTATE.MXCSR]
     4446        and     T0_32, X86_MXCSR_FZ | X86_MXCSR_RC_MASK | X86_MXCSR_DAZ
     4447        or      T0_32, X86_MXCSR_XCPT_MASK
     4448        sub     xSP, 4
     4449        mov     [xSP], T0_32
     4450        ldmxcsr [xSP]
     4451        add     xSP, 4
     4452%endmacro
     4453
     4454
     4455;;
     4456; Restores the SSE MXCSR register with the original value.
     4457;
     4458; @uses     4 bytes of stack to save the content of MXCSR value, T0, T1.
     4459; @param    1       Expression giving the address where to return the MXCSR value.
     4460; @param    2       Expression giving the address of the FXSTATE of the guest.
     4461;
     4462; @note Restores the stack pointer.
     4463;
     4464%macro SSE_ST_FXSTATE_MXCSR 2
     4465        sub     xSP, 4
     4466        stmxcsr [xSP]
     4467        mov     T0_32, [xSP]
     4468        add     xSP, 4
     4469        ; Merge the status bits into the original MXCSR value.
     4470        mov     T1_32, [%2 + X86FXSTATE.MXCSR]
     4471        and     T0_32, X86_MXCSR_XCPT_FLAGS
     4472        or      T0_32, T1_32
     4473        mov     [%1 + IEMSSERESULT.MXCSR], T0_32
     4474
     4475        ldmxcsr [xSP]
     4476        add     xSP, 4
     4477%endmacro
     4478
     4479
     4480;;
     4481; Initialize the SSE MXCSR register using the guest value partially to
     4482; account for rounding mode.
     4483;
     4484; @uses     4 bytes of stack to save the original value.
     4485; @param    1       Expression giving the address of the FXSTATE of the guest.
     4486;
     4487%macro AVX_LD_XSAVEAREA_MXCSR 1
     4488        sub     xSP, 4
     4489
     4490        stmxcsr [xSP]
     4491        mov     T0_32, [%1 + X86FXSTATE.MXCSR]
     4492        and     T0_32, X86_MXCSR_FZ | X86_MXCSR_RC_MASK | X86_MXCSR_DAZ
     4493        sub     xSP, 4
     4494        mov     [xSP], T0_32
     4495        ldmxcsr [xSP]
     4496        add     xSP, 4
     4497%endmacro
     4498
     4499
     4500;;
     4501; Restores the AVX128 MXCSR register with the original value.
     4502;
     4503; @param    1       Expression giving the address where to return the MXCSR value.
     4504;
     4505; @note Restores the stack pointer.
     4506;
     4507%macro AVX128_ST_XSAVEAREA_MXCSR 1
     4508        stmxcsr [%1 + IEMAVX128RESULT.MXCSR]
     4509
     4510        ldmxcsr [xSP]
     4511        add     xSP, 4
     4512%endmacro
     4513
     4514
     4515;;
     4516; Restores the AVX256 MXCSR register with the original value.
     4517;
     4518; @param    1       Expression giving the address where to return the MXCSR value.
     4519;
     4520; @note Restores the stack pointer.
     4521;
     4522%macro AVX256_ST_XSAVEAREA_MXCSR 1
     4523        stmxcsr [%1 + IEMAVX256RESULT.MXCSR]
     4524
     4525        ldmxcsr [xSP]
     4526        add     xSP, 4
     4527%endmacro
     4528
     4529
     4530;;
     4531; Floating point instruction working on two full sized registers.
     4532;
     4533; @param    1       The instruction
     4534;
     4535; @param    A0      FPU context (FXSTATE or XSAVEAREA).
     4536; @param    A1      Where to return the result including the MXCSR value.
     4537; @param    A2      Pointer to the first media register size operand (input/output).
     4538; @param    A3      Pointer to the second media register size operand (input).
     4539;
     4540%macro IEMIMPL_FP_F2 1
     4541BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u128, 12
     4542        PROLOGUE_4_ARGS
     4543        IEMIMPL_SSE_PROLOGUE
     4544        SSE_LD_FXSTATE_MXCSR A0
     4545
     4546        movdqu   xmm0, [A2]
     4547        movdqu   xmm1, [A3]
     4548        %1       xmm0, xmm1
     4549        movdqu   [A1 + IEMSSERESULT.uResult], xmm0
     4550
     4551        SSE_ST_FXSTATE_MXCSR A1, A0
     4552        IEMIMPL_SSE_PROLOGUE
     4553        EPILOGUE_4_ARGS
     4554ENDPROC iemAImpl_ %+ %1 %+ _u128
     4555
     4556BEGINPROC_FASTCALL iemAImpl_v %+ %1 %+ _u128, 12
     4557        PROLOGUE_4_ARGS
     4558        IEMIMPL_AVX_PROLOGUE
     4559        AVX_LD_XSAVEAREA_MXCSR A0
     4560
     4561        vmovdqu  xmm0, [A2]
     4562        vmovdqu  xmm1, [A3]
     4563        v %+ %1  xmm0, xmm0, xmm1
     4564        vmovdqu  [A1 + IEMAVX128RESULT.uResult], xmm0
     4565
     4566        AVX128_ST_XSAVEAREA_MXCSR A1
     4567        IEMIMPL_AVX_PROLOGUE
     4568        EPILOGUE_4_ARGS
     4569ENDPROC iemAImpl_v %+ %1 %+ _u128
     4570
     4571BEGINPROC_FASTCALL iemAImpl_v %+ %1 %+ _u256, 12
     4572        PROLOGUE_4_ARGS
     4573        IEMIMPL_AVX_PROLOGUE
     4574        AVX_LD_XSAVEAREA_MXCSR A0
     4575
     4576        vmovdqu  ymm0, [A2]
     4577        vmovdqu  ymm1, [A3]
     4578        v %+ %1  ymm0, ymm0, ymm1
     4579        vmovdqu  [A1 + IEMAVX256RESULT.uResult], ymm0
     4580
     4581        AVX256_ST_XSAVEAREA_MXCSR A1
     4582        IEMIMPL_AVX_PROLOGUE
     4583        EPILOGUE_4_ARGS
     4584ENDPROC iemAImpl_v %+ %1 %+ _u256
     4585%endmacro
     4586
     4587IEMIMPL_FP_F2 addps
  • trunk/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp

    r96115 r96247  
    1378213782}
    1378313783
     13784
     13785/**
     13786 * Converts from the packed IPRT 32-bit (single precision) floating point format to
     13787 * the SoftFloat 32-bit floating point format (float32_t).
     13788 *
     13789 * This is only a structure format conversion, nothing else.
     13790 */
     13791DECLINLINE(float32_t) iemFpSoftF32FromIprt(PCRTFLOAT32U pr32Val)
     13792{
     13793    float32_t Tmp;
     13794    Tmp.v = pr32Val->u;
     13795    return Tmp;
     13796}
     13797
     13798
     13799/**
     13800 * Converts from SoftFloat 32-bit floating point format (float32_t)
     13801 * to the packed IPRT 32-bit floating point (RTFLOAT32U) format.
     13802 *
     13803 * This is only a structure format conversion, nothing else.
     13804 */
     13805DECLINLINE(PRTFLOAT32U) iemFpSoftF32ToIprt(PRTFLOAT32U pr32Dst, float32_t const r32XSrc)
     13806{
     13807    pr32Dst->u = r32XSrc.v;
     13808    return pr32Dst;
     13809}
     13810
     13811
     13812/**
     13813 * Converts from the packed IPRT 64-bit (single precision) floating point format to
     13814 * the SoftFloat 64-bit floating point format (float64_t).
     13815 *
     13816 * This is only a structure format conversion, nothing else.
     13817 */
     13818DECLINLINE(float64_t) iemFpSoftF64FromIprt(PCRTFLOAT64U pr64Val)
     13819{
     13820    float64_t Tmp;
     13821    Tmp.v = pr64Val->u;
     13822    return Tmp;
     13823}
     13824
     13825
     13826/**
     13827 * Converts from SoftFloat 64-bit floating point format (float64_t)
     13828 * to the packed IPRT 64-bit floating point (RTFLOAT64U) format.
     13829 *
     13830 * This is only a structure format conversion, nothing else.
     13831 */
     13832DECLINLINE(PRTFLOAT64U) iemFpSoftF64ToIprt(PRTFLOAT64U pr64Dst, float64_t const r64XSrc)
     13833{
     13834    pr64Dst->u = r64XSrc.v;
     13835    return pr64Dst;
     13836}
     13837
     13838
     13839/** Initializer for the SoftFloat state structure. */
     13840# define IEM_SOFTFLOAT_STATE_INITIALIZER_FROM_MXCSR(a_Mxcsr) \
     13841    { \
     13842        softfloat_tininess_afterRounding, \
     13843          ((a_Mxcsr) & X86_MXCSR_RC_MASK) == X86_MXCSR_RC_NEAREST ? (uint8_t)softfloat_round_near_even \
     13844        : ((a_Mxcsr) & X86_MXCSR_RC_MASK) == X86_MXCSR_RC_UP      ? (uint8_t)softfloat_round_max \
     13845        : ((a_Mxcsr) & X86_MXCSR_RC_MASK) == X86_MXCSR_RC_DOWN    ? (uint8_t)softfloat_round_min \
     13846        :                                                           (uint8_t)softfloat_round_minMag, \
     13847        0, \
     13848        (uint8_t)(((a_Mxcsr) & X86_MXCSR_XCPT_MASK) >> X86_MXCSR_XCPT_MASK_SHIFT), /* Matches X86_FSW_?E */\
     13849        32 /* Rounding precision, not relevant for SIMD. */ \
     13850    }
     13851
     13852
     13853/**
     13854 * Helper for transfering exception to MXCSR and setting the result value
     13855 * accordingly.
     13856 *
     13857 * @returns Updated MXCSR.
     13858 * @param   pSoftState      The SoftFloat state following the operation.
     13859 * @param   r32Result       The result of the SoftFloat operation.
     13860 * @param   pr32Result      Where to store the result for IEM.
     13861 * @param   fMxcsr          The original MXCSR value.
     13862 * @param   pr32Src1        The first source operand (for setting #DE under certain circumstances).
     13863 * @param   pr32Src2        The second source operand (for setting #DE under certain circumstances).
     13864 */
     13865DECLINLINE(uint32_t) iemSseSoftStateAndR32ToMxcsrAndIprtResult(softfloat_state_t const *pSoftState, float32_t r32Result,
     13866                                                               PRTFLOAT32U pr32Result, uint32_t fMxcsr,
     13867                                                               PCRTFLOAT32U pr32Src1, PCRTFLOAT32U pr32Src2)
     13868{
     13869    uint8_t fXcpt = pSoftState->exceptionFlags;
     13870    if (   (fMxcsr & X86_MXCSR_FZ)
     13871        && RTFLOAT32U_IS_SUBNORMAL((PRTFLOAT32U)&r32Result))
     13872    {
     13873        /* Underflow masked and flush to zero is set. */
     13874        iemFpSoftF32ToIprt(pr32Result, r32Result);
     13875        pr32Result->s.uFraction = 0;
     13876        pr32Result->s.uExponent = 0;
     13877        fXcpt |= X86_MXCSR_UE | X86_MXCSR_PE;
     13878    }
     13879    else
     13880        iemFpSoftF32ToIprt(pr32Result, r32Result);
     13881
     13882    /* If DAZ is set \#DE is never set. */
     13883    if (fMxcsr & X86_MXCSR_DAZ)
     13884        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)
     13888                    || RTFLOAT32U_IS_SUBNORMAL(pr32Src2))
     13889                 ? X86_MXCSR_DE
     13890                 : 0;
     13891
     13892    return fMxcsr | (fXcpt & X86_MXCSR_XCPT_FLAGS);
     13893}
     13894
     13895
     13896#ifdef IEM_WITHOUT_ASSEMBLY
     13897/**
     13898 * Sets the given floating point input value to the given output taking the Denormals-as-zero flag
     13899 * in MXCSR into account.
     13900 *
     13901 * @returns nothing.
     13902 * @param   pr32Val         Where to store the result.
     13903 * @param   fMxcsr          The input MXCSR value.
     13904 * @param   pr32Src         The value to use.
     13905 */
     13906DECLINLINE(void) iemSsePrepareValueR32(PRTFLOAT32U pr32Val, uint32_t fMxcsr, PCRTFLOAT32U pr32Src)
     13907{
     13908    /* De-normals are changed to 0. */
     13909    if (   fMxcsr & X86_MXCSR_DAZ
     13910        && RTFLOAT32U_IS_SUBNORMAL(pr32Src))
     13911    {
     13912        pr32Val->s.fSign     = pr32Src->s.fSign;
     13913        pr32Val->s.uFraction = 0;
     13914        pr32Val->s.uExponent = 0;
     13915    }
     13916    else
     13917        *pr32Val = *pr32Src;
     13918}
     13919
     13920
     13921/**
     13922 * Validates the given input operands returning whether the operation can continue or whether one
     13923 * of the source operands contains a NaN value, setting the output accordingly.
     13924 *
     13925 * @returns Flag whether the operation can continue (true) or whether a NaN value was detected in one of the operands (false).
     13926 * @param   pr32Res         Where to store the result in case the operation can't continue.
     13927 * @param   pr32Val1        The first input operand.
     13928 * @param   pr32Val2        The second input operand.
     13929 * @param   pfMxcsr         Where to return the modified MXCSR state when false is returned.
     13930 */
     13931DECLINLINE(bool) iemSseCheckInputBinaryR32(PRTFLOAT32U pr32Res, PCRTFLOAT32U pr32Val1, PCRTFLOAT32U pr32Val2, uint32_t *pfMxcsr)
     13932{
     13933    uint8_t cQNan = RTFLOAT32U_IS_QUIET_NAN(pr32Val1) + RTFLOAT32U_IS_QUIET_NAN(pr32Val2);
     13934    uint8_t cSNan = RTFLOAT32U_IS_SIGNALLING_NAN(pr32Val1) + RTFLOAT32U_IS_SIGNALLING_NAN(pr32Val2);
     13935    if (cSNan + cQNan == 2)
     13936    {
     13937        /* Both values are either SNan or QNan, first operand is placed into the result and converted to a QNan. */
     13938        *pr32Res = *pr32Val1;
     13939        pr32Res->s.uFraction |= RT_BIT_32(RTFLOAT32U_FRACTION_BITS - 1);
     13940        *pfMxcsr |= (cSNan ? X86_MXCSR_IE : 0);
     13941        return false;
     13942    }
     13943    else if (cSNan)
     13944    {
     13945        /* One operand is an SNan and placed into the result, converting it to a QNan. */
     13946        *pr32Res = RTFLOAT32U_IS_SIGNALLING_NAN(pr32Val1) ? *pr32Val1 : *pr32Val2;
     13947        pr32Res->s.uFraction |= RT_BIT_32(RTFLOAT32U_FRACTION_BITS - 1);
     13948        *pfMxcsr |= X86_MXCSR_IE;
     13949        return false;
     13950    }
     13951    else if (cQNan)
     13952    {
     13953        /* The QNan operand is placed into the result. */
     13954        *pr32Res = RTFLOAT32U_IS_QUIET_NAN(pr32Val1) ? *pr32Val1 : *pr32Val2;
     13955        return false;
     13956    }
     13957
     13958    Assert(!cQNan && !cSNan);
     13959    return true;
     13960}
     13961#endif
     13962
     13963
     13964/**
     13965 * ADDPS
     13966 */
     13967#ifdef IEM_WITHOUT_ASSEMBLY
     13968static uint32_t iemAImpl_addps_u128_worker(PRTFLOAT32U pr32Res, uint32_t fMxcsr, PCRTFLOAT32U pr32Val1, PCRTFLOAT32U pr32Val2)
     13969{
     13970    if (!iemSseCheckInputBinaryR32(pr32Res, pr32Val1, pr32Val2, &fMxcsr))
     13971        return fMxcsr;
     13972
     13973    RTFLOAT32U r32Src1, r32Src2;
     13974    iemSsePrepareValueR32(&r32Src1, fMxcsr, pr32Val1);
     13975    iemSsePrepareValueR32(&r32Src2, fMxcsr, pr32Val2);
     13976    softfloat_state_t SoftState = IEM_SOFTFLOAT_STATE_INITIALIZER_FROM_MXCSR(fMxcsr);
     13977    float32_t r32Result = f32_add(iemFpSoftF32FromIprt(&r32Src1), iemFpSoftF32FromIprt(&r32Src2), &SoftState);
     13978    return iemSseSoftStateAndR32ToMxcsrAndIprtResult(&SoftState, r32Result, pr32Res, fMxcsr, &r32Src1, &r32Src2);
     13979}
     13980
     13981
     13982IEM_DECL_IMPL_DEF(void, iemAImpl_addps_u128,(PX86FXSTATE pFpuState, PIEMSSERESULT pResult, PCX86XMMREG puSrc1, PCX86XMMREG puSrc2))
     13983{
     13984    pResult->MXCSR |= iemAImpl_addps_u128_worker(&pResult->uResult.ar32[0], pFpuState->MXCSR, &puSrc1->ar32[0], &puSrc2->ar32[0]);
     13985    pResult->MXCSR |= iemAImpl_addps_u128_worker(&pResult->uResult.ar32[1], pFpuState->MXCSR, &puSrc1->ar32[1], &puSrc2->ar32[1]);
     13986    pResult->MXCSR |= iemAImpl_addps_u128_worker(&pResult->uResult.ar32[2], pFpuState->MXCSR, &puSrc1->ar32[2], &puSrc2->ar32[2]);
     13987    pResult->MXCSR |= iemAImpl_addps_u128_worker(&pResult->uResult.ar32[3], pFpuState->MXCSR, &puSrc1->ar32[3], &puSrc2->ar32[3]);
     13988}
     13989#endif
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsTwoByte0f.cpp.h

    r96109 r96247  
    728728        IEM_MC_REF_XREG_U128(puDst, IEM_GET_MODRM_REG(pVCpu, bRm));
    729729        IEM_MC_CALL_VOID_AIMPL_2(pfnU128, puDst, puSrc);
     730
     731        IEM_MC_ADVANCE_RIP();
     732        IEM_MC_END();
     733    }
     734    return VINF_SUCCESS;
     735}
     736
     737
     738/**
     739 * Common worker for SSE instructions on the forms:
     740 *      pxx{s,d}    xmm1, xmm2/mem128
     741 *
     742 * Proper alignment of the 128-bit operand is enforced.
     743 * Exceptions type 2. SSE cpuid checks.
     744 *
     745 * @sa iemOpCommonSse41_FullFull_To_Full, iemOpCommonSse2_FullFull_To_Full
     746 */
     747FNIEMOP_DEF_1(iemOpCommonSseFp_FullFull_To_Full, PFNIEMAIMPLFPSSEF2U128, pfnU128)
     748{
     749    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
     750    if (IEM_IS_MODRM_REG_MODE(bRm))
     751    {
     752        /*
     753         * Register, register.
     754         */
     755        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
     756        IEM_MC_BEGIN(3, 1);
     757        IEM_MC_LOCAL(IEMSSERESULT,          SseRes);
     758        IEM_MC_ARG_LOCAL_REF(PIEMSSERESULT, pSseRes,        SseRes,     0);
     759        IEM_MC_ARG(PCX86XMMREG,             pSrc1,                      1);
     760        IEM_MC_ARG(PCX86XMMREG,             pSrc2,                      2);
     761        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
     762        IEM_MC_PREPARE_SSE_USAGE();
     763        IEM_MC_REF_XREG_XMM_CONST(pSrc1, IEM_GET_MODRM_REG(pVCpu, bRm));
     764        IEM_MC_REF_XREG_XMM_CONST(pSrc2, IEM_GET_MODRM_RM(pVCpu, bRm));
     765        IEM_MC_CALL_SSE_AIMPL_3(pfnU128, pSseRes, pSrc1, pSrc2);
     766        IEM_MC_STORE_SSE_RESULT(SseRes, IEM_GET_MODRM_REG(pVCpu, bRm));
     767        IEM_MC_MAYBE_RAISE_SSE_AVX_SIMD_FP_OR_UD_XCPT();
     768
     769        IEM_MC_ADVANCE_RIP();
     770        IEM_MC_END();
     771    }
     772    else
     773    {
     774        /*
     775         * Register, memory.
     776         */
     777        IEM_MC_BEGIN(3, 2);
     778        IEM_MC_LOCAL(IEMSSERESULT,          SseRes);
     779        IEM_MC_LOCAL(X86XMMREG,             uSrc2);
     780        IEM_MC_ARG_LOCAL_REF(PIEMSSERESULT, pSseRes,        SseRes,     0);
     781        IEM_MC_ARG(PCX86XMMREG,             pSrc1,                      1);
     782        IEM_MC_ARG_LOCAL_REF(PCX86XMMREG,   pSrc2, uSrc2,               2);
     783        IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc);
     784
     785        IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
     786        IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
     787        IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT();
     788        IEM_MC_FETCH_MEM_XMM_ALIGN_SSE(uSrc2, pVCpu->iem.s.iEffSeg, GCPtrEffSrc);
     789
     790        IEM_MC_PREPARE_SSE_USAGE();
     791        IEM_MC_REF_XREG_XMM_CONST(pSrc1, IEM_GET_MODRM_REG(pVCpu, bRm));
     792        IEM_MC_CALL_SSE_AIMPL_3(pfnU128, pSseRes, pSrc1, pSrc2);
     793        IEM_MC_STORE_SSE_RESULT(SseRes, IEM_GET_MODRM_REG(pVCpu, bRm));
     794        IEM_MC_MAYBE_RAISE_SSE_AVX_SIMD_FP_OR_UD_XCPT();
    730795
    731796        IEM_MC_ADVANCE_RIP();
     
    37943859
    37953860/** Opcode      0x0f 0x58 - addps Vps, Wps */
    3796 FNIEMOP_STUB(iemOp_addps_Vps_Wps);
     3861FNIEMOP_DEF(iemOp_addps_Vps_Wps)
     3862{
     3863    IEMOP_MNEMONIC2(RM, ADDPS, addps, Vps, Wps, DISOPTYPE_HARMLESS, 0);
     3864    return FNIEMOP_CALL_1(iemOpCommonSseFp_FullFull_To_Full, iemAImpl_addps_u128);
     3865}
     3866
     3867
    37973868/** Opcode 0x66 0x0f 0x58 - addpd Vpd, Wpd */
    37983869FNIEMOP_STUB(iemOp_addpd_Vpd_Wpd);
  • trunk/src/VBox/VMM/include/IEMInternal.h

    r96115 r96247  
    23562356
    23572357
     2358/** @name SSE/AVX single/double precision floating point operations.
     2359 * @{ */
     2360/**
     2361 * A SSE result.
     2362 */
     2363typedef struct IEMSSERESULT
     2364{
     2365    /** The output value. */
     2366    X86XMMREG       uResult;
     2367    /** The output status. */
     2368    uint32_t        MXCSR;
     2369} IEMSSERESULT;
     2370AssertCompileMemberOffset(IEMSSERESULT, MXCSR, 128 / 8);
     2371/** Pointer to a SSE result. */
     2372typedef IEMSSERESULT *PIEMSSERESULT;
     2373/** Pointer to a const SSE result. */
     2374typedef IEMSSERESULT const *PCIEMSSERESULT;
     2375
     2376
     2377/**
     2378 * A AVX128 result.
     2379 */
     2380typedef struct IEMAVX128RESULT
     2381{
     2382    /** The output value. */
     2383    X86XMMREG       uResult;
     2384    /** The output status. */
     2385    uint32_t        MXCSR;
     2386} IEMAVX128RESULT;
     2387AssertCompileMemberOffset(IEMAVX128RESULT, MXCSR, 128 / 8);
     2388/** Pointer to a AVX128 result. */
     2389typedef IEMAVX128RESULT *PIEMAVX128RESULT;
     2390/** Pointer to a const AVX128 result. */
     2391typedef IEMAVX128RESULT const *PCIEMAVX128RESULT;
     2392
     2393
     2394/**
     2395 * A AVX256 result.
     2396 */
     2397typedef struct IEMAVX256RESULT
     2398{
     2399    /** The output value. */
     2400    X86YMMREG       uResult;
     2401    /** The output status. */
     2402    uint32_t        MXCSR;
     2403} IEMAVX256RESULT;
     2404AssertCompileMemberOffset(IEMAVX256RESULT, MXCSR, 256 / 8);
     2405/** Pointer to a AVX256 result. */
     2406typedef IEMAVX256RESULT *PIEMAVX256RESULT;
     2407/** Pointer to a const AVX256 result. */
     2408typedef IEMAVX256RESULT const *PCIEMAVX256RESULT;
     2409
     2410
     2411typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLFPSSEF2U128,(PX86FXSTATE pFpuState, PIEMSSERESULT pResult, PCX86XMMREG puSrc1, PCX86XMMREG puSrc2));
     2412typedef FNIEMAIMPLFPSSEF2U128  *PFNIEMAIMPLFPSSEF2U128;
     2413typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLFPAVXF3U128,(PX86XSAVEAREA pExtState, PIEMAVX128RESULT pResult, PCX86XMMREG puSrc1, PCX86XMMREG puSrc2));
     2414typedef FNIEMAIMPLFPAVXF3U128  *PFNIEMAIMPLFPAVXF3U128;
     2415typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLFPAVXF3U256,(PX86XSAVEAREA pExtState, PIEMAVX256RESULT pResult, PCX86YMMREG puSrc1, PCX86YMMREG puSrc2));
     2416typedef FNIEMAIMPLFPAVXF3U256  *PFNIEMAIMPLFPAVXF3U256;
     2417
     2418FNIEMAIMPLFPSSEF2U128 iemAImpl_addps_u128;
     2419
     2420FNIEMAIMPLFPAVXF3U128 iemAImpl_vaddps_u128, iemAImpl_vaddps_u128_fallback;
     2421
     2422FNIEMAIMPLFPAVXF3U256 iemAImpl_vaddps_u256, iemAImpl_vaddps_u256_fallback;
     2423/** @} */
     2424
    23582425/** @name C instruction implementations for anything slightly complicated.
    23592426 * @{ */
     
    31813248DECL_NO_RETURN(void)    iemRaiseAlignmentCheckExceptionJmp(PVMCPUCC pVCpu)  RT_NOEXCEPT;
    31823249#endif
     3250VBOXSTRICTRC            iemRaiseSimdFpException(PVMCPUCC pVCpu) RT_NOEXCEPT;
    31833251
    31843252IEM_CIMPL_DEF_0(iemCImplRaiseDivideError);
     
    32513319void            iemFpuStackPushOverflow(PVMCPUCC pVCpu) RT_NOEXCEPT;
    32523320void            iemFpuStackPushOverflowWithMemOp(PVMCPUCC pVCpu, uint8_t iEffSeg, RTGCPTR GCPtrEff) RT_NOEXCEPT;
     3321/** @} */
     3322
     3323/** @name SSE+AVX SIMD access and helpers.
     3324 * @{ */
     3325void            iemSseStoreResult(PVMCPUCC pVCpu, PCIEMSSERESULT pResult, uint8_t iXmmReg) RT_NOEXCEPT;
    32533326/** @} */
    32543327
  • trunk/src/VBox/VMM/include/IEMMc.h

    r95540 r96247  
    192192        if (!IEM_IS_CANONICAL(a_u64Addr)) \
    193193            return iemRaiseGeneralProtectionFault0(pVCpu); \
     194    } while (0)
     195#define IEM_MC_MAYBE_RAISE_SSE_AVX_SIMD_FP_OR_UD_XCPT() \
     196    do { \
     197        if ((  ((pVCpu->cpum.GstCtx.XState.x87.MXCSR & X86_MXCSR_XCPT_MASK) >> X86_MXCSR_XCPT_MASK_SHIFT) \
     198             & (pVCpu->cpum.GstCtx.XState.x87.MXCSR & X86_MXCSR_XCPT_FLAGS)) != 0) \
     199        { \
     200            if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_OSXMMEEXCPT)\
     201                return iemRaiseSimdFpException(pVCpu); \
     202            else \
     203                return iemRaiseUndefinedOpcode(pVCpu); \
     204        } \
    194205    } while (0)
    195206
     
    436447#define IEM_MC_REF_XREG_U128_CONST(a_pu128Dst, a_iXReg) \
    437448    (a_pu128Dst) = ((PCRTUINT128U)&pVCpu->cpum.GstCtx.XState.x87.aXMM[(a_iXReg)].uXmm)
     449#define IEM_MC_REF_XREG_XMM_CONST(a_pXmmDst, a_iXReg) \
     450    (a_pXmmDst) = (&pVCpu->cpum.GstCtx.XState.x87.aXMM[(a_iXReg)])
    438451#define IEM_MC_REF_XREG_U64_CONST(a_pu64Dst, a_iXReg) \
    439452    (a_pu64Dst) = ((uint64_t const *)&pVCpu->cpum.GstCtx.XState.x87.aXMM[(a_iXReg)].au64[0])
     
    706719# define IEM_MC_FETCH_MEM_U128_ALIGN_SSE(a_u128Dst, a_iSeg, a_GCPtrMem) \
    707720    IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU128AlignedSse(pVCpu, &(a_u128Dst), (a_iSeg), (a_GCPtrMem)))
     721
     722# define IEM_MC_FETCH_MEM_XMM(a_XmmDst, a_iSeg, a_GCPtrMem) \
     723    IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU128(pVCpu, &(a_XmmDst).uXmm, (a_iSeg), (a_GCPtrMem)))
     724# define IEM_MC_FETCH_MEM_XMM_NO_AC(a_XmmDst, a_iSeg, a_GCPtrMem) \
     725    IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU128(pVCpu, &(a_XmmDst).uXmm, (a_iSeg), (a_GCPtrMem)))
     726# define IEM_MC_FETCH_MEM_XMM_ALIGN_SSE(a_XmmDst, a_iSeg, a_GCPtrMem) \
     727    IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU128AlignedSse(pVCpu, &(a_XmmDst).uXmm, (a_iSeg), (a_GCPtrMem)))
    708728#else
    709729# define IEM_MC_FETCH_MEM_U128(a_u128Dst, a_iSeg, a_GCPtrMem) \
     
    713733# define IEM_MC_FETCH_MEM_U128_ALIGN_SSE(a_u128Dst, a_iSeg, a_GCPtrMem) \
    714734    iemMemFetchDataU128AlignedSseJmp(pVCpu, &(a_u128Dst), (a_iSeg), (a_GCPtrMem))
     735
     736# define IEM_MC_FETCH_MEM_XMM(a_XmmDst, a_iSeg, a_GCPtrMem) \
     737    iemMemFetchDataU128Jmp(pVCpu, &(a_XmmDst).uXmm, (a_iSeg), (a_GCPtrMem))
     738# define IEM_MC_FETCH_MEM_XMM_NO_AC(a_XmmDst, a_iSeg, a_GCPtrMem) \
     739    iemMemFetchDataU128Jmp(pVCpu, &(a_XmmDst).uXmm, (a_iSeg), (a_GCPtrMem))
     740# define IEM_MC_FETCH_MEM_XMM_ALIGN_SSE(a_XmmDst, a_iSeg, a_GCPtrMem) \
     741    iemMemFetchDataU128AlignedSseJmp(pVCpu, &(a_XmmDst).uXmm, (a_iSeg), (a_GCPtrMem))
    715742#endif
    716743
     
    722749# define IEM_MC_FETCH_MEM_U256_ALIGN_AVX(a_u256Dst, a_iSeg, a_GCPtrMem) \
    723750    IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU256AlignedSse(pVCpu, &(a_u256Dst), (a_iSeg), (a_GCPtrMem)))
     751
     752# define IEM_MC_FETCH_MEM_YMM(a_YmmDst, a_iSeg, a_GCPtrMem) \
     753    IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU256(pVCpu, &(a_YmmDst).ymm, (a_iSeg), (a_GCPtrMem)))
     754# define IEM_MC_FETCH_MEM_YMM_NO_AC(a_YmmDst, a_iSeg, a_GCPtrMem) \
     755    IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU256(pVCpu, &(a_YmmDst).ymm, (a_iSeg), (a_GCPtrMem)))
     756# define IEM_MC_FETCH_MEM_YMM_ALIGN_AVX(a_YmmDst, a_iSeg, a_GCPtrMem) \
     757    IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU256AlignedSse(pVCpu, &(a_YmmDst).ymm, (a_iSeg), (a_GCPtrMem)))
    724758#else
    725759# define IEM_MC_FETCH_MEM_U256(a_u256Dst, a_iSeg, a_GCPtrMem) \
     
    729763# define IEM_MC_FETCH_MEM_U256_ALIGN_AVX(a_u256Dst, a_iSeg, a_GCPtrMem) \
    730764    iemMemFetchDataU256AlignedSseJmp(pVCpu, &(a_u256Dst), (a_iSeg), (a_GCPtrMem))
     765
     766# define IEM_MC_FETCH_MEM_YMM(a_YmmDst, a_iSeg, a_GCPtrMem) \
     767    iemMemFetchDataU256Jmp(pVCpu, &(a_YmmDst).ymm, (a_iSeg), (a_GCPtrMem))
     768# define IEM_MC_FETCH_MEM_YMM_NO_AC(a_YmmDst, a_iSeg, a_GCPtrMem) \
     769    iemMemFetchDataU256Jmp(pVCpu, &(a_YmmDst).ymm, (a_iSeg), (a_GCPtrMem))
     770# define IEM_MC_FETCH_MEM_YMM_ALIGN_AVX(a_YmmDst, a_iSeg, a_GCPtrMem) \
     771    iemMemFetchDataU256AlignedSseJmp(pVCpu, &(a_YmmDst).ymm, (a_iSeg), (a_GCPtrMem))
    731772#endif
    732773
     
    12471288#define IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE() iemFpuActualizeStateForChange(pVCpu)
    12481289
     1290/** Stores SSE SIMD result in a stack register. */
     1291#define IEM_MC_STORE_SSE_RESULT(a_SseData, a_iXmmReg) \
     1292    iemSseStoreResult(pVCpu, &a_SseData, a_iXmmReg)
    12491293/** Prepares for using the SSE state.
    12501294 * Ensures that we can use the host SSE/FPU in the current context (RC+R0.
  • trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp

    r96109 r96247  
    462462#define iemAImpl_unpckhpd_u128          NULL
    463463
     464#define iemAImpl_addps_u128             NULL
     465
    464466/** @}  */
    465467
     
    522524#define IEM_MC_MAYBE_RAISE_FSGSBASE_XCPT()              do { (void)fMcBegin; } while (0)
    523525#define IEM_MC_MAYBE_RAISE_NON_CANONICAL_ADDR_GP0(a_u64Addr) do { (void)fMcBegin; } while (0)
     526#define IEM_MC_MAYBE_RAISE_SSE_AVX_SIMD_FP_OR_UD_XCPT() do { (void)fMcBegin; } while (0)
    524527
    525528#define IEM_MC_LOCAL(a_Type, a_Name) (void)fMcBegin; \
     
    684687#define IEM_MC_REF_XREG_U128_CONST(a_pu128Dst, a_iXReg)     do { (a_pu128Dst) = (PCRTUINT128U)((uintptr_t)0);       CHK_PTYPE(PCRTUINT128U, a_pu128Dst);    (void)fSseWrite; (void)fMcBegin; } while (0)
    685688#define IEM_MC_REF_XREG_U64_CONST(a_pu64Dst, a_iXReg)       do { (a_pu64Dst)  = (uint64_t const *)((uintptr_t)0);   CHK_PTYPE(uint64_t const *, a_pu64Dst); (void)fSseWrite; (void)fMcBegin; } while (0)
     689#define IEM_MC_REF_XREG_XMM_CONST(a_pXmmDst, a_iXReg)       do { (a_pXmmDst) = (PCX86XMMREG)((uintptr_t)0);         CHK_PTYPE(PCX86XMMREG, a_pXmmDst);      (void)fSseWrite; (void)fMcBegin; } while (0)
    686690#define IEM_MC_COPY_XREG_U128(a_iXRegDst, a_iXRegSrc)       do { (void)fSseWrite; (void)fMcBegin; } while (0)
    687691
     
    749753#define IEM_MC_FETCH_MEM_U128_NO_AC(a_u128Dst, a_iSeg, a_GCPtrMem)      do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(RTUINT128U, a_u128Dst); (void)fMcBegin; } while (0)
    750754#define IEM_MC_FETCH_MEM_U128_ALIGN_SSE(a_u128Dst, a_iSeg, a_GCPtrMem)  do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(RTUINT128U, a_u128Dst); (void)fMcBegin; } while (0)
     755#define IEM_MC_FETCH_MEM_XMM(a_XmmDst, a_iSeg, a_GCPtrMem)              do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(X86XMMREG, a_XmmDst); (void)fMcBegin; } while (0)
     756#define IEM_MC_FETCH_MEM_XMM_NO_AC(a_XmmDst, a_iSeg, a_GCPtrMem)        do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(X86XMMREG, a_XmmDst); (void)fMcBegin; } while (0)
     757#define IEM_MC_FETCH_MEM_XMM_ALIGN_SSE(a_XmmDst, a_iSeg, a_GCPtrMem)    do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(X86XMMREG, a_XmmDst); (void)fMcBegin; } while (0)
    751758#define IEM_MC_FETCH_MEM_U256(a_u256Dst, a_iSeg, a_GCPtrMem)            do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(RTUINT256U, a_u256Dst); (void)fMcBegin; } while (0)
    752759#define IEM_MC_FETCH_MEM_U256_NO_AC(a_u256Dst, a_iSeg, a_GCPtrMem)      do { CHK_GCPTR(a_GCPtrMem); CHK_TYPE(RTUINT256U, a_u256Dst); (void)fMcBegin; } while (0)
     
    852859#define IEM_MC_ACTUALIZE_FPU_STATE_FOR_READ()   (void)fMcBegin; const int fFpuRead = 1, fSseRead = 1
    853860#define IEM_MC_ACTUALIZE_FPU_STATE_FOR_CHANGE() (void)fMcBegin; const int fFpuRead = 1, fFpuWrite = 1, fSseRead = 1, fSseWrite = 1
     861#define IEM_MC_STORE_SSE_RESULT(a_SseData, a_iXmmReg)                                           do { (void)fSseWrite; (void)fMcBegin; } while (0)
    854862#define IEM_MC_PREPARE_SSE_USAGE()              (void)fMcBegin; const int fSseRead = 1, fSseWrite = 1, fSseHost = 1
    855863#define IEM_MC_ACTUALIZE_SSE_STATE_FOR_READ()   (void)fMcBegin; const int fSseRead = 1
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