VirtualBox

Changeset 103991 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Mar 21, 2024 2:30:04 PM (11 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
162376
Message:

VMM/IEM: Fix IEM_MC_COPY_XREG_U128(), IEM_MC_COPY_YREG_U128_ZX_VLMAX() and IEM_MC_COPY_YREG_U256_ZX_VLMAX() for the case when source register == destination register, , bugref:10614

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompFuncs.h

    r103990 r103991  
    71997199iemNativeEmitSimdCopyXregU128(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iXRegDst, uint8_t iXRegSrc)
    72007200{
    7201     /*
    7202      * Allocate destination and source register.
    7203      *
    7204      * @note The order is important here when iXRegSrc == iXRegDst, because if iXRegDst gets allocated first for the full write
    7205      *       it won't load the actual value from CPUMCTX. When allocating iXRegSrc afterwards it will get duplicated from the already
    7206      *       allocated host register for iXRegDst containing garbage. This will be catched by the guest register value checking.
    7207      */
    7208     uint8_t const idxSimdRegSrc = iemNativeSimdRegAllocTmpForGuestSimdReg(pReNative, &off, IEMNATIVEGSTSIMDREG_SIMD(iXRegSrc),
    7209                                                                           kIemNativeGstSimdRegLdStSz_Low128, kIemNativeGstRegUse_ReadOnly);
    7210     uint8_t const idxSimdRegDst = iemNativeSimdRegAllocTmpForGuestSimdReg(pReNative, &off, IEMNATIVEGSTSIMDREG_SIMD(iXRegDst),
    7211                                                                           kIemNativeGstSimdRegLdStSz_Low128, kIemNativeGstRegUse_ForFullWrite);
    7212 
    7213     off = iemNativeEmitSimdLoadVecRegFromVecRegU128(pReNative, off, idxSimdRegDst, idxSimdRegSrc);
    7214     IEMNATIVE_SIMD_REG_STATE_SET_DIRTY_LO_U128(pReNative, iXRegDst);
    7215     /* We don't need to write everything back here as the destination is marked as dirty and will be flushed automatically. */
    7216 
    7217     /* Free but don't flush the source and destination register. */
    7218     iemNativeSimdRegFreeTmp(pReNative, idxSimdRegDst);
    7219     iemNativeSimdRegFreeTmp(pReNative, idxSimdRegSrc);
     7201    /* This is a nop if the source and destination register are the same. */
     7202    if (iXRegDst != iXRegSrc)
     7203    {
     7204        /* Allocate destination and source register. */
     7205        uint8_t const idxSimdRegDst = iemNativeSimdRegAllocTmpForGuestSimdReg(pReNative, &off, IEMNATIVEGSTSIMDREG_SIMD(iXRegDst),
     7206                                                                              kIemNativeGstSimdRegLdStSz_Low128, kIemNativeGstRegUse_ForFullWrite);
     7207        uint8_t const idxSimdRegSrc = iemNativeSimdRegAllocTmpForGuestSimdReg(pReNative, &off, IEMNATIVEGSTSIMDREG_SIMD(iXRegSrc),
     7208                                                                              kIemNativeGstSimdRegLdStSz_Low128, kIemNativeGstRegUse_ReadOnly);
     7209
     7210        off = iemNativeEmitSimdLoadVecRegFromVecRegU128(pReNative, off, idxSimdRegDst, idxSimdRegSrc);
     7211        IEMNATIVE_SIMD_REG_STATE_SET_DIRTY_LO_U128(pReNative, iXRegDst);
     7212        /* We don't need to write everything back here as the destination is marked as dirty and will be flushed automatically. */
     7213
     7214        /* Free but don't flush the source and destination register. */
     7215        iemNativeSimdRegFreeTmp(pReNative, idxSimdRegDst);
     7216        iemNativeSimdRegFreeTmp(pReNative, idxSimdRegSrc);
     7217    }
    72207218
    72217219    return off;
     
    75217519{
    75227520    /*
    7523      * Allocate destination and source register.
    7524      *
    7525      * @note The order is important here when iYRegSrc == iYRegDst, because if iYRegDst gets allocated first for the full write
    7526      *       it won't load the actual value from CPUMCTX. When allocating iYRegSrc afterwards it will get duplicated from the already
    7527      *       allocated host register for iYRegDst containing garbage. This will be catched by the guest register value checking.
     7521     * The iYRegSrc == iYRegDst case needs to be treated differently here, because if iYRegDst gets allocated first for the full write
     7522     * it won't load the actual value from CPUMCTX. When allocating iYRegSrc afterwards it will get duplicated from the already
     7523     * allocated host register for iYRegDst containing garbage. This will be catched by the guest register value checking in debug builds.
    75287524     */
    7529     uint8_t const idxSimdRegSrc = iemNativeSimdRegAllocTmpForGuestSimdReg(pReNative, &off, IEMNATIVEGSTSIMDREG_SIMD(iYRegSrc),
    7530                                                                           kIemNativeGstSimdRegLdStSz_Low128, kIemNativeGstRegUse_ReadOnly);
    7531     uint8_t const idxSimdRegDst = iemNativeSimdRegAllocTmpForGuestSimdReg(pReNative, &off, IEMNATIVEGSTSIMDREG_SIMD(iYRegDst),
    7532                                                                           kIemNativeGstSimdRegLdStSz_256, kIemNativeGstRegUse_ForFullWrite);
    7533 
    7534     off = iemNativeEmitSimdLoadVecRegFromVecRegU128(pReNative, off, idxSimdRegDst, idxSimdRegSrc);
    7535     off = iemNativeEmitSimdZeroVecRegHighU128(pReNative, off, idxSimdRegDst);
    7536     IEMNATIVE_SIMD_REG_STATE_SET_DIRTY_LO_U128(pReNative, iYRegDst);
    7537     IEMNATIVE_SIMD_REG_STATE_SET_DIRTY_HI_U128(pReNative, iYRegDst);
    7538 
    7539     /* Free but don't flush the source and destination register. */
    7540     iemNativeSimdRegFreeTmp(pReNative, idxSimdRegDst);
    7541     iemNativeSimdRegFreeTmp(pReNative, idxSimdRegSrc);
     7525    if (iYRegDst != iYRegSrc)
     7526    {
     7527        /* Allocate destination and source register. */
     7528        uint8_t const idxSimdRegDst = iemNativeSimdRegAllocTmpForGuestSimdReg(pReNative, &off, IEMNATIVEGSTSIMDREG_SIMD(iYRegDst),
     7529                                                                              kIemNativeGstSimdRegLdStSz_256, kIemNativeGstRegUse_ForFullWrite);
     7530        uint8_t const idxSimdRegSrc =  iemNativeSimdRegAllocTmpForGuestSimdReg(pReNative, &off, IEMNATIVEGSTSIMDREG_SIMD(iYRegSrc),
     7531                                                                               kIemNativeGstSimdRegLdStSz_Low128, kIemNativeGstRegUse_ReadOnly);
     7532
     7533        off = iemNativeEmitSimdLoadVecRegFromVecRegU128(pReNative, off, idxSimdRegDst, idxSimdRegSrc);
     7534        off = iemNativeEmitSimdZeroVecRegHighU128(pReNative, off, idxSimdRegDst);
     7535        IEMNATIVE_SIMD_REG_STATE_SET_DIRTY_LO_U128(pReNative, iYRegDst);
     7536        IEMNATIVE_SIMD_REG_STATE_SET_DIRTY_HI_U128(pReNative, iYRegDst);
     7537
     7538        /* Free but don't flush the source and destination register. */
     7539        iemNativeSimdRegFreeTmp(pReNative, idxSimdRegDst);
     7540        iemNativeSimdRegFreeTmp(pReNative, idxSimdRegSrc);
     7541    }
     7542    else
     7543    {
     7544        /* This effectively only clears the upper 128-bits of the register. */
     7545        uint8_t const idxSimdReg = iemNativeSimdRegAllocTmpForGuestSimdReg(pReNative, &off, IEMNATIVEGSTSIMDREG_SIMD(iYRegDst),
     7546                                                                           kIemNativeGstSimdRegLdStSz_High128, kIemNativeGstRegUse_ForFullWrite);
     7547
     7548        off = iemNativeEmitSimdZeroVecRegHighU128(pReNative, off, idxSimdReg);
     7549        IEMNATIVE_SIMD_REG_STATE_SET_DIRTY_HI_U128(pReNative, iYRegDst);
     7550
     7551        /* Free but don't flush the destination register. */
     7552        iemNativeSimdRegFreeTmp(pReNative, idxSimdReg);
     7553    }
    75427554
    75437555    return off;
     
    75537565{
    75547566    /*
    7555      * Allocate destination and source register.
    7556      *
    7557      * @note The order is important here when iYRegSrc == iYRegDst, because if iYRegDst gets allocated first for the full write
    7558      *       it won't load the actual value from CPUMCTX. When allocating iYRegSrc afterwards it will get duplicated from the already
    7559      *       allocated host register for iYRegDst containing garbage. This will be catched by the guest register value checking.
     7567     * The iYRegSrc == iYRegDst case needs to be treated differently here, because if iYRegDst gets allocated first for the full write
     7568     * it won't load the actual value from CPUMCTX. When allocating iYRegSrc afterwards it will get duplicated from the already
     7569     * allocated host register for iYRegDst containing garbage. This will be catched by the guest register value checking in debug builds.
     7570     * iYRegSrc == iYRegDst would effectively only clear any upper 256-bits for a zmm register we don't support yet, so this is just a nop.
    75607571     */
    7561     uint8_t const idxSimdRegSrc = iemNativeSimdRegAllocTmpForGuestSimdReg(pReNative, &off, IEMNATIVEGSTSIMDREG_SIMD(iYRegSrc),
    7562                                                                           kIemNativeGstSimdRegLdStSz_256, kIemNativeGstRegUse_ReadOnly);
    7563     uint8_t const idxSimdRegDst = iemNativeSimdRegAllocTmpForGuestSimdReg(pReNative, &off, IEMNATIVEGSTSIMDREG_SIMD(iYRegDst),
    7564                                                                           kIemNativeGstSimdRegLdStSz_256, kIemNativeGstRegUse_ForFullWrite);
    7565 
    7566     off = iemNativeEmitSimdLoadVecRegFromVecRegU256(pReNative, off, idxSimdRegDst, idxSimdRegSrc);
    7567     IEMNATIVE_SIMD_REG_STATE_SET_DIRTY_LO_U128(pReNative, iYRegDst);
    7568     IEMNATIVE_SIMD_REG_STATE_SET_DIRTY_HI_U128(pReNative, iYRegDst);
    7569 
    7570     /* Free but don't flush the source and destination register. */
    7571     iemNativeSimdRegFreeTmp(pReNative, idxSimdRegDst);
    7572     iemNativeSimdRegFreeTmp(pReNative, idxSimdRegSrc);
     7572    if (iYRegDst != iYRegSrc)
     7573    {
     7574        /* Allocate destination and source register. */
     7575        uint8_t const idxSimdRegSrc = iemNativeSimdRegAllocTmpForGuestSimdReg(pReNative, &off, IEMNATIVEGSTSIMDREG_SIMD(iYRegSrc),
     7576                                                                              kIemNativeGstSimdRegLdStSz_256, kIemNativeGstRegUse_ReadOnly);
     7577        uint8_t const idxSimdRegDst = iemNativeSimdRegAllocTmpForGuestSimdReg(pReNative, &off, IEMNATIVEGSTSIMDREG_SIMD(iYRegDst),
     7578                                                                              kIemNativeGstSimdRegLdStSz_256, kIemNativeGstRegUse_ForFullWrite);
     7579
     7580        off = iemNativeEmitSimdLoadVecRegFromVecRegU256(pReNative, off, idxSimdRegDst, idxSimdRegSrc);
     7581        IEMNATIVE_SIMD_REG_STATE_SET_DIRTY_LO_U128(pReNative, iYRegDst);
     7582        IEMNATIVE_SIMD_REG_STATE_SET_DIRTY_HI_U128(pReNative, iYRegDst);
     7583
     7584        /* Free but don't flush the source and destination register. */
     7585        iemNativeSimdRegFreeTmp(pReNative, idxSimdRegDst);
     7586        iemNativeSimdRegFreeTmp(pReNative, idxSimdRegSrc);
     7587    }
    75737588
    75747589    return off;
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