VirtualBox

Changeset 104129 in vbox for trunk/src/VBox/VMM/include


Ignore:
Timestamp:
Apr 2, 2024 12:37:36 PM (10 months ago)
Author:
vboxsync
Message:

VMM/IEM: Rework MXCSR handling for SSE instructions, bugref:10641

The old approach by referencing the X86FXSTATE and accessing the MXCSR value there
prevents us from keeping the MXCSR shadowed in a host register for SIMD guest code
causing unecessary memory accesses. It also prevents avoiding skipping dirty guest registers
because the instruction helpers would have access the to CPUMCTX structure.

The new approach passes the guest MXCSR as the first argument of the helper callback and
the helper returns the MXCSR with the new exception flags being set as a return value.
With this the helpers only work on arguments supplied and don't access anything in CPUMCTX
directly which allows the recompiler to avoid flushing pending register writes unless they get
used.

As a bonus this also gets rid of the IEMSSERESULT struct which was required because the helpers
are restricted to 4 arguments due to restrictions on x86 for the assembly helpers in IEMAllAImpl.asm

Location:
trunk/src/VBox/VMM/include
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/include/IEMInternal.h

    r104115 r104129  
    55
    66/*
    7  * Copyright (C) 2011-2023 Oracle and/or its affiliates.
     7 * Copyright (C) 2011-2024 Oracle and/or its affiliates.
    88 *
    99 * This file is part of VirtualBox base platform packages, as
     
    38503850FNIEMAIMPLF2EFL256 iemAImpl_vptest_u256, iemAImpl_vptest_u256_fallback;
    38513851
    3852 typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLSSEF2I32U64,(PCX86FXSTATE pFpuState, uint32_t *pfMxcsr, int32_t *pi32Dst, const uint64_t *pu64Src)); /* pu64Src is a double precision floating point. */
     3852typedef IEM_DECL_IMPL_TYPE(uint32_t, FNIEMAIMPLSSEF2I32U64,(uint32_t uMxCsrIn, int32_t *pi32Dst, const uint64_t *pu64Src)); /* pu64Src is a double precision floating point. */
    38533853typedef FNIEMAIMPLSSEF2I32U64 *PFNIEMAIMPLSSEF2I32U64;
    3854 typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLSSEF2I64U64,(PCX86FXSTATE pFpuState, uint32_t *pfMxcsr, int64_t *pi64Dst, const uint64_t *pu64Src)); /* pu64Src is a double precision floating point. */
     3854typedef IEM_DECL_IMPL_TYPE(uint32_t, FNIEMAIMPLSSEF2I64U64,(uint32_t uMxCsrIn, int64_t *pi64Dst, const uint64_t *pu64Src)); /* pu64Src is a double precision floating point. */
    38553855typedef FNIEMAIMPLSSEF2I64U64 *PFNIEMAIMPLSSEF2I64U64;
    3856 typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLSSEF2I32U32,(PCX86FXSTATE pFpuState, uint32_t *pfMxcsr, int32_t *pi32Dst, const uint32_t *pu32Src)); /* pu32Src is a single precision floating point. */
     3856typedef IEM_DECL_IMPL_TYPE(uint32_t, FNIEMAIMPLSSEF2I32U32,(uint32_t uMxCsrIn, int32_t *pi32Dst, const uint32_t *pu32Src)); /* pu32Src is a single precision floating point. */
    38573857typedef FNIEMAIMPLSSEF2I32U32 *PFNIEMAIMPLSSEF2I32U32;
    3858 typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLSSEF2I64U32,(PCX86FXSTATE pFpuState, uint32_t *pfMxcsr, int64_t *pi64Dst, const uint32_t *pu32Src)); /* pu32Src is a single precision floating point. */
     3858typedef IEM_DECL_IMPL_TYPE(uint32_t, FNIEMAIMPLSSEF2I64U32,(uint32_t uMxCsrIn, int64_t *pi64Dst, const uint32_t *pu32Src)); /* pu32Src is a single precision floating point. */
    38593859typedef FNIEMAIMPLSSEF2I64U32 *PFNIEMAIMPLSSEF2I64U32;
    38603860
     
    38713871FNIEMAIMPLSSEF2I64U32 iemAImpl_cvtss2si_i64_r32;
    38723872
    3873 typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLSSEF2R32I32,(PCX86FXSTATE pFpuState, uint32_t *pfMxcsr, PRTFLOAT32U pr32Dst, const int32_t *pi32Src));
     3873typedef IEM_DECL_IMPL_TYPE(uint32_t, FNIEMAIMPLSSEF2R32I32,(uint32_t uMxCsrIn, PRTFLOAT32U pr32Dst, const int32_t *pi32Src));
    38743874typedef FNIEMAIMPLSSEF2R32I32 *PFNIEMAIMPLSSEF2R32I32;
    3875 typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLSSEF2R32I64,(PCX86FXSTATE pFpuState, uint32_t *pfMxcsr, PRTFLOAT32U pr32Dst, const int64_t *pi64Src));
     3875typedef IEM_DECL_IMPL_TYPE(uint32_t, FNIEMAIMPLSSEF2R32I64,(uint32_t uMxCsrIn, PRTFLOAT32U pr32Dst, const int64_t *pi64Src));
    38763876typedef FNIEMAIMPLSSEF2R32I64 *PFNIEMAIMPLSSEF2R32I64;
    38773877
     
    38793879FNIEMAIMPLSSEF2R32I64 iemAImpl_cvtsi2ss_r32_i64;
    38803880
    3881 typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLSSEF2R64I32,(PCX86FXSTATE pFpuState, uint32_t *pfMxcsr, PRTFLOAT64U pr64Dst, const int32_t *pi32Src));
     3881typedef IEM_DECL_IMPL_TYPE(uint32_t, FNIEMAIMPLSSEF2R64I32,(uint32_t uMxCsrIn, PRTFLOAT64U pr64Dst, const int32_t *pi32Src));
    38823882typedef FNIEMAIMPLSSEF2R64I32 *PFNIEMAIMPLSSEF2R64I32;
    3883 typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLSSEF2R64I64,(PCX86FXSTATE pFpuState, uint32_t *pfMxcsr, PRTFLOAT64U pr64Dst, const int64_t *pi64Src));
     3883typedef IEM_DECL_IMPL_TYPE(uint32_t, FNIEMAIMPLSSEF2R64I64,(uint32_t uMxCsrIn, PRTFLOAT64U pr64Dst, const int64_t *pi64Src));
    38843884typedef FNIEMAIMPLSSEF2R64I64 *PFNIEMAIMPLSSEF2R64I64;
    38853885
     
    38883888
    38893889
    3890 typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLF2EFLMXCSR128,(uint32_t *pfMxcsr, uint32_t *pfEFlags, PCX86XMMREG puSrc1, PCX86XMMREG puSrc2));
     3890typedef IEM_DECL_IMPL_TYPE(uint32_t, FNIEMAIMPLF2EFLMXCSR128,(uint32_t uMxCsrIn, uint32_t *pfEFlags, PCX86XMMREG puSrc1, PCX86XMMREG puSrc2));
    38913891typedef FNIEMAIMPLF2EFLMXCSR128 *PFNIEMAIMPLF2EFLMXCSR128;
    38923892
     
    42474247 * @{ */
    42484248/**
    4249  * A SSE result.
    4250  */
    4251 typedef struct IEMSSERESULT
    4252 {
    4253     /** The output value. */
    4254     X86XMMREG       uResult;
    4255     /** The output status. */
    4256     uint32_t        MXCSR;
    4257 } IEMSSERESULT;
    4258 AssertCompileMemberOffset(IEMSSERESULT, MXCSR, 128 / 8);
    4259 /** Pointer to a SSE result. */
    4260 typedef IEMSSERESULT *PIEMSSERESULT;
    4261 /** Pointer to a const SSE result. */
    4262 typedef IEMSSERESULT const *PCIEMSSERESULT;
    4263 
    4264 
    4265 /**
    42664249 * A AVX128 result.
    42674250 */
     
    42974280
    42984281
    4299 typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLFPSSEF2U128,(PX86FXSTATE pFpuState, PIEMSSERESULT pResult, PCX86XMMREG puSrc1, PCX86XMMREG puSrc2));
     4282typedef IEM_DECL_IMPL_TYPE(uint32_t, FNIEMAIMPLFPSSEF2U128,(uint32_t uMxCsrIn, PX86XMMREG pResult, PCX86XMMREG puSrc1, PCX86XMMREG puSrc2));
    43004283typedef FNIEMAIMPLFPSSEF2U128  *PFNIEMAIMPLFPSSEF2U128;
    4301 typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLFPSSEF2U128R32,(PX86FXSTATE pFpuState, PIEMSSERESULT pResult, PCX86XMMREG puSrc1, PCRTFLOAT32U pr32Src2));
     4284typedef IEM_DECL_IMPL_TYPE(uint32_t, FNIEMAIMPLFPSSEF2U128R32,(uint32_t uMxCsrIn, PX86XMMREG Result, PCX86XMMREG puSrc1, PCRTFLOAT32U pr32Src2));
    43024285typedef FNIEMAIMPLFPSSEF2U128R32  *PFNIEMAIMPLFPSSEF2U128R32;
    4303 typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLFPSSEF2U128R64,(PX86FXSTATE pFpuState, PIEMSSERESULT pResult, PCX86XMMREG puSrc1, PCRTFLOAT64U pr64Src2));
     4286typedef IEM_DECL_IMPL_TYPE(uint32_t, FNIEMAIMPLFPSSEF2U128R64,(uint32_t uMxCsrIn, PX86XMMREG pResult, PCX86XMMREG puSrc1, PCRTFLOAT64U pr64Src2));
    43044287typedef FNIEMAIMPLFPSSEF2U128R64  *PFNIEMAIMPLFPSSEF2U128R64;
    43054288
     
    54795462/** @name SSE+AVX SIMD access and helpers.
    54805463 * @{ */
    5481 void            iemSseStoreResult(PVMCPUCC pVCpu, PCIEMSSERESULT pResult, uint8_t iXmmReg) RT_NOEXCEPT;
    54825464void            iemSseUpdateMxcsr(PVMCPUCC pVCpu, uint32_t fMxcsr) RT_NOEXCEPT;
    54835465/** @} */
  • trunk/src/VBox/VMM/include/IEMMc.h

    r104099 r104129  
    29602960
    29612961/** Stores SSE SIMD result updating MXCSR. */
    2962 #define IEM_MC_STORE_SSE_RESULT(a_SseData, a_iXmmReg) \
    2963     iemSseStoreResult(pVCpu, &a_SseData, a_iXmmReg)
    2964 /** Updates MXCSR. */
    2965 #define IEM_MC_SSE_UPDATE_MXCSR(a_fMxcsr) \
    2966     iemSseUpdateMxcsr(pVCpu, a_fMxcsr)
     2962#define IEM_MC_STORE_SSE_RESULT(a_Res, a_iXmmReg) \
     2963    do { \
     2964        PCX86FXSTATE pFpuCtx = &pVCpu->cpum.GstCtx.XState.x87; \
     2965        if ((  ~((pFpuCtx->MXCSR & X86_MXCSR_XCPT_MASK) >> X86_MXCSR_XCPT_MASK_SHIFT) \
     2966             & (pFpuCtx->MXCSR & X86_MXCSR_XCPT_FLAGS)) == 0) \
     2967            pVCpu->cpum.GstCtx.XState.x87.aXMM[(a_iXmmReg)] = (a_Res); \
     2968    } while (0)
    29672969
    29682970/** Prepares for using the SSE state.
     
    30243026    do { \
    30253027        IEM_MC_PREPARE_SSE_USAGE(); \
    3026         a_pfnAImpl(&pVCpu->cpum.GstCtx.XState.x87, (a0), (a1)); \
     3028        pVCpu->cpum.GstCtx.XState.x87.MXCSR = a_pfnAImpl(pVCpu->cpum.GstCtx.XState.x87.MXCSR & ~X86_MXCSR_XCPT_FLAGS, \
     3029                                                        (a0), (a1)); \
    30273030    } while (0)
    30283031
     
    30383041    do { \
    30393042        IEM_MC_PREPARE_SSE_USAGE(); \
    3040         a_pfnAImpl(&pVCpu->cpum.GstCtx.XState.x87, (a0), (a1), (a2)); \
     3043        pVCpu->cpum.GstCtx.XState.x87.MXCSR = a_pfnAImpl(pVCpu->cpum.GstCtx.XState.x87.MXCSR & ~X86_MXCSR_XCPT_FLAGS, \
     3044                                                         (a0), (a1), (a2)); \
    30413045    } while (0)
    30423046
     
    30713075        IEM_MC_PREPARE_AVX_USAGE(); \
    30723076        a_pfnAImpl(&pVCpu->cpum.GstCtx.XState, (a1), (a2), (a3)); \
     3077    } while (0)
     3078
     3079/**
     3080 * Calls a AVX assembly implementation taking three visible arguments.
     3081 *
     3082 * @param   a_pfnAImpl      Pointer to the assembly SSE routine.
     3083 * @param   a0              The first extra argument.
     3084 * @param   a1              The second extra argument.
     3085 * @param   a2              The third extra argument.
     3086 *
     3087 * @note The and'ing with X86_MXCSR_XCPT_FLAGS is just a precaution as
     3088 *       the called helper should return an MXCSR with only new exception flags
     3089 *       added.
     3090 * @note This is temporarily required for the v(u)comis* stuff because
     3091 *       tstIEMAImpl will not compile otherwise, will be removed once the AVX
     3092 *       stuff is reworked, see @bugref{10641}
     3093 */
     3094#define IEM_MC_CALL_AVX_AIMPL_NEW_3(a_pfnAImpl, a0, a1, a2) \
     3095    do { \
     3096        IEM_MC_PREPARE_SSE_USAGE(); \
     3097        pVCpu->cpum.GstCtx.XState.x87.MXCSR |=   a_pfnAImpl(pVCpu->cpum.GstCtx.XState.x87.MXCSR, (a0), (a1), (a2)) \
     3098                                               & X86_MXCSR_XCPT_FLAGS; \
    30733099    } while (0)
    30743100
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