VirtualBox

Changeset 98812 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Mar 1, 2023 7:55:18 PM (2 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
156132
Message:

VMM/IEM: Completely untested emulations for pcmp{i,e}str{i,m}, bugref:9898

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

Legend:

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

    r98781 r98812  
    1646916469 * [V]PCMPISTRI
    1647016470 */
     16471
     16472/**
     16473 * Does the comparisons based on the mode and source input format.
     16474 */
     16475static void iemAImpl_pcmpxstrx_cmp(bool afCmpRes[16][16], PCRTUINT128U puSrc1, PCRTUINT128U puSrc2, uint8_t bImm)
     16476{
     16477#define PCMPXSTRX_CMP_CASE(a_fCmpRes, a_puSrc1, a_puSrc2, a_SrcMember, a_bAggOp) \
     16478    do \
     16479    { \
     16480        for (uint8_t idxSrc2 = 0; idxSrc2 < RT_ELEMENTS((a_puSrc2)->a_SrcMember); idxSrc2++) \
     16481            for (uint8_t idxSrc1 = 0; idxSrc1 < RT_ELEMENTS((a_puSrc1)->a_SrcMember); idxSrc1 += 2) \
     16482            { \
     16483                switch (a_bAggOp) \
     16484                { \
     16485                    case 0: \
     16486                    case 2: \
     16487                    case 3: \
     16488                        afCmpRes[idxSrc2][idxSrc1]     = (a_puSrc1)->a_SrcMember[idxSrc1]     == (a_puSrc2)->a_SrcMember[idxSrc2]; \
     16489                        afCmpRes[idxSrc2][idxSrc1 + 1] = (a_puSrc1)->a_SrcMember[idxSrc1 + 1] == (a_puSrc2)->a_SrcMember[idxSrc2 + 1]; \
     16490                        break; \
     16491                    case 1: \
     16492                        afCmpRes[idxSrc2][idxSrc1]     = (a_puSrc1)->a_SrcMember[idxSrc1]     >= (a_puSrc2)->a_SrcMember[idxSrc2]; \
     16493                        afCmpRes[idxSrc2][idxSrc1 + 1] = (a_puSrc1)->a_SrcMember[idxSrc1 + 1] <= (a_puSrc2)->a_SrcMember[idxSrc2 + 1]; \
     16494                        break; \
     16495                    default: \
     16496                        AssertReleaseFailed(); \
     16497                } \
     16498            } \
     16499    } while(0)
     16500
     16501    uint8_t bAggOp = (bImm >> 2) & 0x3;
     16502    switch (bImm & 0x3)
     16503    {
     16504        case 0:
     16505            PCMPXSTRX_CMP_CASE(afCmpRes, puSrc1, puSrc2, au8, bAggOp);
     16506            break;
     16507        case 1:
     16508            PCMPXSTRX_CMP_CASE(afCmpRes, puSrc1, puSrc2, au16, bAggOp);
     16509            break;
     16510        case 2:
     16511            PCMPXSTRX_CMP_CASE(afCmpRes, puSrc1, puSrc2, ai8, bAggOp);
     16512            break;
     16513        case 3:
     16514            PCMPXSTRX_CMP_CASE(afCmpRes, puSrc1, puSrc2, ai16, bAggOp);
     16515            break;
     16516        default:
     16517            AssertReleaseFailed();
     16518    }
     16519#undef PCMPXSTRX_CMP_CASE
     16520}
     16521
     16522static uint8_t iemAImpl_pcmpistrx_get_str_len_implicit(PCRTUINT128U puSrc, uint8_t bImm)
     16523{
     16524    if (bImm & 0x1)
     16525    {
     16526        /* Words -> 8 elements. */
     16527        for (uint8_t i = 0; i < RT_ELEMENTS(puSrc->au16); i++)
     16528            if (puSrc->au16[i] == 0)
     16529                return i;
     16530
     16531        return 8;
     16532    }
     16533    else
     16534    {
     16535        /* Bytes -> 16 elements. */
     16536        for (uint8_t i = 0; i < RT_ELEMENTS(puSrc->au8); i++)
     16537            if (puSrc->au8[i] == 0)
     16538                return i;
     16539
     16540        return 16;
     16541    }
     16542}
     16543
     16544static uint8_t iemAImpl_pcmpistrx_get_str_len_explicit(int64_t i64Len, uint8_t bImm)
     16545{
     16546    if (bImm & 0x1)
     16547    {
     16548        if (i64Len > -8 && i64Len < 8)
     16549            return RT_ABS(i64Len);
     16550
     16551        return 8;
     16552    }
     16553    else
     16554    {
     16555        if (i64Len > -16 && i64Len < 16)
     16556            return RT_ABS(i64Len);
     16557
     16558        return 16;
     16559    }
     16560}
     16561
     16562/**
     16563 * Valid/Invalid override of comparisons (Table 4-7 from 4.1.6 of SDM).
     16564 */
     16565static const bool g_afCmpOverride[4][3] =
     16566{
     16567    /*  xmm1 AND xmm2/m128 invalid      xmm1 invalid, xmm2/m128 valid       xmm1 valid, xmm2/m128 invalid */
     16568    {                        false,                             false,                                 false }, /* Imm8[3:2] = 00b (equal any)     */
     16569    {                        false,                             false,                                 false }, /* Imm8[3:2] = 01b (ranges)        */
     16570    {                        true,                              false,                                 false }, /* Imm8[3:2] = 10b (equal each)    */
     16571    {                        true,                              true,                                  false }, /* Imm8[3:2] = 11b (equal ordered) */
     16572};
     16573
     16574DECL_FORCE_INLINE(bool) iemAImpl_pcmpxstrx_cmp_override_if_invalid(bool fCmpRes, bool fSrc1Valid, bool fSrc2Valid, uint8_t bAggOp)
     16575{
     16576    if (fSrc1Valid && fSrc2Valid)
     16577        return fCmpRes;
     16578
     16579    uint8_t bSrc1Valid = fSrc1Valid ? 2 : 0;
     16580    uint8_t bSrc2Valid = fSrc2Valid ? 1 : 0;
     16581    return g_afCmpOverride[bAggOp][bSrc1Valid + bSrc2Valid];
     16582}
     16583
     16584static uint16_t iemAImpl_pcmpxstrx_cmp_aggregate(bool afCmpRes[16][16], uint8_t idxLen1, uint8_t idxLen2, uint8_t bImm)
     16585{
     16586    uint8_t cElems = (bImm & 0x1) ? 8 : 16;
     16587    uint8_t bAggOp = (bImm >> 2) & 0x3;
     16588    uint16_t u16Result = 0;
     16589
     16590    switch (bAggOp)
     16591    {
     16592        case 0: /* Equal any */
     16593            for (uint8_t idxSrc2 = 0; idxSrc2 < cElems; idxSrc2++)
     16594            {
     16595                uint16_t u16Res = 0;
     16596                for (uint8_t idxSrc1 = 0; idxSrc1 < cElems; idxSrc1++)
     16597                {
     16598                    if (iemAImpl_pcmpxstrx_cmp_override_if_invalid(afCmpRes[idxSrc2][idxSrc1],
     16599                                                                   idxSrc1 < idxLen1,
     16600                                                                   idxSrc2 < idxLen2,
     16601                                                                   bAggOp))
     16602                    {
     16603                        u16Res = RT_BIT(idxSrc2);
     16604                        break;
     16605                    }
     16606                }
     16607
     16608                u16Result |= u16Res;
     16609            }
     16610            break;
     16611
     16612        case 1: /* Ranges */
     16613            for (uint8_t idxSrc2 = 0; idxSrc2 < cElems; idxSrc2++)
     16614            {
     16615                uint16_t u16Res = 0;
     16616                for (uint8_t idxSrc1 = 0; idxSrc1 < cElems; idxSrc1 += 2)
     16617                {
     16618                    if (   iemAImpl_pcmpxstrx_cmp_override_if_invalid(afCmpRes[idxSrc2][idxSrc1],
     16619                                                                      idxSrc1 < idxLen1,
     16620                                                                      idxSrc2 < idxLen2,
     16621                                                                      bAggOp)
     16622                        && iemAImpl_pcmpxstrx_cmp_override_if_invalid(afCmpRes[idxSrc2][idxSrc1 + 1],
     16623                                                                      (idxSrc1 + 1) < idxLen1,
     16624                                                                      idxSrc2 < idxLen2,
     16625                                                                      bAggOp))
     16626                    {
     16627                        u16Res = RT_BIT(idxSrc2);
     16628                        break;
     16629                    }
     16630                }
     16631
     16632                u16Result |= u16Res;
     16633            }
     16634            break;
     16635
     16636        case 2: /* Equal each */
     16637            for (uint8_t i = 0; i < cElems; i++)
     16638            {
     16639                if (iemAImpl_pcmpxstrx_cmp_override_if_invalid(afCmpRes[i][i],
     16640                                                               i < idxLen1,
     16641                                                               i < idxLen2,
     16642                                                               bAggOp))
     16643                    u16Result |= RT_BIT(i);
     16644            }
     16645            break;
     16646
     16647        case 3: /* Equal ordered */
     16648            u16Result = cElems == 8 ? 0xff : 0xffff;
     16649            for (uint8_t idxSrc2 = 0; idxSrc2 < cElems; idxSrc2++)
     16650            {
     16651                uint16_t u16Res = 0;
     16652                for (uint8_t idxSrc1 = 0, k = idxSrc2; (idxSrc1 < cElems - idxSrc2) && (k < cElems); idxSrc1++, k++)
     16653                {
     16654                    if (iemAImpl_pcmpxstrx_cmp_override_if_invalid(afCmpRes[k][idxSrc1],
     16655                                                                   idxSrc1 < idxLen1,
     16656                                                                   k < idxLen2,
     16657                                                                   bAggOp))
     16658                    {
     16659                        u16Res = RT_BIT(idxSrc2);
     16660                        break;
     16661                    }
     16662                }
     16663
     16664                u16Result &= ~u16Res;
     16665            }
     16666            break;
     16667    }
     16668
     16669    /* Polarity selection. */
     16670    switch ((bImm >> 4) & 0x3)
     16671    {
     16672        case 0:
     16673        case 2:
     16674            /* Nothing to do. */
     16675            break;
     16676        case 1:
     16677            u16Result = (cElems == 8 ? 0xff : 0xffff) ^ u16Result;
     16678            break;
     16679        case 3:
     16680            for (uint8_t i = 0; i < cElems; i++)
     16681                if (i < idxLen2)
     16682                    u16Result ^= RT_BIT(i);
     16683            break;
     16684        default:
     16685            AssertReleaseFailed();
     16686    }
     16687
     16688    return u16Result;
     16689}
     16690
     16691DECL_FORCE_INLINE(void) iemAImpl_pcmpxstrx_set_eflags(uint32_t *pfEFlags, uint16_t u16Result, uint8_t cLen1, uint8_t cLen2, uint8_t cElems)
     16692{
     16693    uint32_t fEFlags = 0;
     16694
     16695    if (u16Result)
     16696        fEFlags |= X86_EFL_CF;
     16697    if (cLen2 < cElems)
     16698        fEFlags |= X86_EFL_ZF;
     16699    if (cLen1 < cElems)
     16700        fEFlags |= X86_EFL_SF;
     16701    if (u16Result & 0x1)
     16702        fEFlags |= X86_EFL_OF;
     16703    *pfEFlags = (*pfEFlags & ~X86_EFL_STATUS_BITS) | fEFlags;
     16704}
     16705
    1647116706IEM_DECL_IMPL_DEF(void, iemAImpl_pcmpistri_u128_fallback,(uint32_t *pu32Ecx, uint32_t *pEFlags, PCIEMPCMPISTRXSRC pSrc, uint8_t bEvil))
    1647216707{
    16473     RT_NOREF(pu32Ecx, pEFlags, pSrc, bEvil);
    16474     AssertReleaseFailed();
     16708    bool afCmpRes[16][16];
     16709    uint8_t cElems = (bEvil & RT_BIT(0)) ? 8 : 16;
     16710    iemAImpl_pcmpxstrx_cmp(afCmpRes, &pSrc->uSrc1, &pSrc->uSrc2, bEvil);
     16711    uint8_t cLen1 = iemAImpl_pcmpistrx_get_str_len_implicit(&pSrc->uSrc1, bEvil);
     16712    uint8_t cLen2 = iemAImpl_pcmpistrx_get_str_len_implicit(&pSrc->uSrc2, bEvil);
     16713
     16714    uint16_t u16Result = iemAImpl_pcmpxstrx_cmp_aggregate(afCmpRes, cLen1, cLen2, bEvil);
     16715    if (bEvil & RT_BIT(6))
     16716    {
     16717        /* Index for MSB set. */
     16718        uint32_t idxMsb = ASMBitLastSetU16(u16Result);
     16719        if (idxMsb)
     16720            *pu32Ecx = idxMsb;
     16721        else
     16722            *pu32Ecx = cElems;
     16723    }
     16724    else
     16725    {
     16726        /* Index for LSB set. */
     16727        uint32_t idxLsb = ASMBitFirstSetU16(u16Result);
     16728        if (idxLsb)
     16729            *pu32Ecx = idxLsb;
     16730        else
     16731            *pu32Ecx = cElems;
     16732    }
     16733
     16734    iemAImpl_pcmpxstrx_set_eflags(pEFlags, u16Result, cLen1, cLen2, cElems);
    1647516735}
    1647616736
     
    1648116741IEM_DECL_IMPL_DEF(void, iemAImpl_pcmpestri_u128_fallback,(uint32_t *pu32Ecx, uint32_t *pEFlags, PCIEMPCMPESTRXSRC pSrc, uint8_t bEvil))
    1648216742{
    16483     RT_NOREF(pu32Ecx, pEFlags, pSrc, bEvil);
    16484     AssertReleaseFailed();
     16743    bool afCmpRes[16][16];
     16744    uint8_t cElems = (bEvil & RT_BIT(0)) ? 8 : 16;
     16745    iemAImpl_pcmpxstrx_cmp(afCmpRes, &pSrc->uSrc1, &pSrc->uSrc2, bEvil);
     16746    uint8_t cLen1 = iemAImpl_pcmpistrx_get_str_len_explicit((int64_t)pSrc->u64Rax, bEvil);
     16747    uint8_t cLen2 = iemAImpl_pcmpistrx_get_str_len_explicit((int64_t)pSrc->u64Rdx, bEvil);
     16748
     16749    uint16_t u16Result = iemAImpl_pcmpxstrx_cmp_aggregate(afCmpRes, cLen1, cLen2, bEvil);
     16750    if (bEvil & RT_BIT(6))
     16751    {
     16752        /* Index for MSB set. */
     16753        uint32_t idxMsb = ASMBitLastSetU16(u16Result);
     16754        if (idxMsb)
     16755            *pu32Ecx = idxMsb;
     16756        else
     16757            *pu32Ecx = cElems;
     16758    }
     16759    else
     16760    {
     16761        /* Index for LSB set. */
     16762        uint32_t idxLsb = ASMBitFirstSetU16(u16Result);
     16763        if (idxLsb)
     16764            *pu32Ecx = idxLsb;
     16765        else
     16766            *pu32Ecx = cElems;
     16767    }
     16768
     16769    iemAImpl_pcmpxstrx_set_eflags(pEFlags, u16Result, cLen1, cLen2, cElems);
    1648516770}
    1648616771
     
    1649116776IEM_DECL_IMPL_DEF(void, iemAImpl_pcmpistrm_u128_fallback,(PRTUINT128U puDst, uint32_t *pEFlags, PCIEMPCMPISTRXSRC pSrc, uint8_t bEvil))
    1649216777{
    16493     RT_NOREF(puDst, pEFlags, pSrc, bEvil);
    16494     AssertReleaseFailed();
     16778    bool afCmpRes[16][16];
     16779    uint8_t cElems = (bEvil & RT_BIT(0)) ? 8 : 16;
     16780    iemAImpl_pcmpxstrx_cmp(afCmpRes, &pSrc->uSrc1, &pSrc->uSrc2, bEvil);
     16781    uint8_t cLen1 = iemAImpl_pcmpistrx_get_str_len_implicit(&pSrc->uSrc1, bEvil);
     16782    uint8_t cLen2 = iemAImpl_pcmpistrx_get_str_len_implicit(&pSrc->uSrc2, bEvil);
     16783
     16784    uint16_t u16Result = iemAImpl_pcmpxstrx_cmp_aggregate(afCmpRes, cLen1, cLen2, bEvil);
     16785    if (bEvil & RT_BIT(6))
     16786    {
     16787        /* Generate a mask. */
     16788        if (cElems == 8)
     16789        {
     16790            for (uint8_t i = 0; i < RT_ELEMENTS(puDst->au16); i++)
     16791                if (u16Result & RT_BIT(i))
     16792                    puDst->au16[i] = 0xffff;
     16793                else
     16794                    puDst->au16[i] = 0;
     16795        }
     16796        else
     16797        {
     16798            for (uint8_t i = 0; i < RT_ELEMENTS(puDst->au8); i++)
     16799                if (u16Result & RT_BIT(i))
     16800                    puDst->au8[i] = 0xff;
     16801                else
     16802                    puDst->au8[i] = 0;
     16803        }
     16804    }
     16805    else
     16806    {
     16807        /* Store the result. */
     16808        puDst->au64[0] = u16Result;
     16809        puDst->au64[1] = 0;
     16810    }
     16811
     16812    iemAImpl_pcmpxstrx_set_eflags(pEFlags, u16Result, cLen1, cLen2, cElems);
    1649516813}
    1649616814
     
    1650116819IEM_DECL_IMPL_DEF(void, iemAImpl_pcmpestrm_u128_fallback,(PRTUINT128U puDst, uint32_t *pEFlags, PCIEMPCMPESTRXSRC pSrc, uint8_t bEvil))
    1650216820{
    16503     RT_NOREF(puDst, pEFlags, pSrc, bEvil);
    16504     AssertReleaseFailed();
     16821    bool afCmpRes[16][16];
     16822    uint8_t cElems = (bEvil & RT_BIT(0)) ? 8 : 16;
     16823    iemAImpl_pcmpxstrx_cmp(afCmpRes, &pSrc->uSrc1, &pSrc->uSrc2, bEvil);
     16824    uint8_t cLen1 = iemAImpl_pcmpistrx_get_str_len_explicit((int64_t)pSrc->u64Rax, bEvil);
     16825    uint8_t cLen2 = iemAImpl_pcmpistrx_get_str_len_explicit((int64_t)pSrc->u64Rdx, bEvil);
     16826
     16827    uint16_t u16Result = iemAImpl_pcmpxstrx_cmp_aggregate(afCmpRes, cLen1, cLen2, bEvil);
     16828    if (bEvil & RT_BIT(6))
     16829    {
     16830        /* Generate a mask. */
     16831        if (cElems == 8)
     16832        {
     16833            for (uint8_t i = 0; i < RT_ELEMENTS(puDst->au16); i++)
     16834                if (u16Result & RT_BIT(i))
     16835                    puDst->au16[i] = 0xffff;
     16836                else
     16837                    puDst->au16[i] = 0;
     16838        }
     16839        else
     16840        {
     16841            for (uint8_t i = 0; i < RT_ELEMENTS(puDst->au8); i++)
     16842                if (u16Result & RT_BIT(i))
     16843                    puDst->au8[i] = 0xff;
     16844                else
     16845                    puDst->au8[i] = 0;
     16846        }
     16847    }
     16848    else
     16849    {
     16850        /* Store the result. */
     16851        puDst->au64[0] = u16Result;
     16852        puDst->au64[1] = 0;
     16853    }
     16854
     16855    iemAImpl_pcmpxstrx_set_eflags(pEFlags, u16Result, cLen1, cLen2, cElems);
    1650516856}
    1650616857
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsThree0f3a.cpp.h

    r98781 r98812  
    12171217            IEM_MC_FETCH_XREG_U128(Src.uSrc1, IEM_GET_MODRM_REG(pVCpu, bRm));
    12181218            IEM_MC_FETCH_XREG_U128(Src.uSrc2, IEM_GET_MODRM_RM(pVCpu, bRm));
    1219             IEM_MC_FETCH_GREG_U32_ZX_U64(Src.u64Rax, X86_GREG_xAX);
    1220             IEM_MC_FETCH_GREG_U32_ZX_U64(Src.u64Rdx, X86_GREG_xDX);
     1219            IEM_MC_FETCH_GREG_U32_SX_U64(Src.u64Rax, X86_GREG_xAX);
     1220            IEM_MC_FETCH_GREG_U32_SX_U64(Src.u64Rdx, X86_GREG_xDX);
    12211221            IEM_MC_REF_XREG_U128(puDst, 0 /*xmm0*/);
    12221222            IEM_MC_REF_EFLAGS(pEFlags);
     
    12501250            IEM_MC_REF_GREG_U32(pu32Ecx, X86_GREG_xCX);
    12511251            IEM_MC_FETCH_XREG_U128(Src.uSrc1, IEM_GET_MODRM_REG(pVCpu, bRm));
    1252             IEM_MC_FETCH_GREG_U32_ZX_U64(Src.u64Rax, X86_GREG_xAX);
    1253             IEM_MC_FETCH_GREG_U32_ZX_U64(Src.u64Rdx, X86_GREG_xDX);
     1252            IEM_MC_FETCH_GREG_U32_SX_U64(Src.u64Rax, X86_GREG_xAX);
     1253            IEM_MC_FETCH_GREG_U32_SX_U64(Src.u64Rdx, X86_GREG_xDX);
    12541254            IEM_MC_REF_EFLAGS(pEFlags);
    12551255            IEM_MC_CALL_VOID_AIMPL_4(IEM_SELECT_HOST_OR_FALLBACK(fSse42,
     
    13551355            IEM_MC_FETCH_XREG_U128(Src.uSrc1, IEM_GET_MODRM_REG(pVCpu, bRm));
    13561356            IEM_MC_FETCH_XREG_U128(Src.uSrc2, IEM_GET_MODRM_RM(pVCpu, bRm));
    1357             IEM_MC_FETCH_GREG_U32_ZX_U64(Src.u64Rax, X86_GREG_xAX);
    1358             IEM_MC_FETCH_GREG_U32_ZX_U64(Src.u64Rdx, X86_GREG_xDX);
     1357            IEM_MC_FETCH_GREG_U32_SX_U64(Src.u64Rax, X86_GREG_xAX);
     1358            IEM_MC_FETCH_GREG_U32_SX_U64(Src.u64Rdx, X86_GREG_xDX);
    13591359            IEM_MC_REF_EFLAGS(pEFlags);
    13601360            IEM_MC_CALL_VOID_AIMPL_4(IEM_SELECT_HOST_OR_FALLBACK(fSse42,
     
    13881388            IEM_MC_REF_GREG_U32(pu32Ecx, X86_GREG_xCX);
    13891389            IEM_MC_FETCH_XREG_U128(Src.uSrc1, IEM_GET_MODRM_REG(pVCpu, bRm));
    1390             IEM_MC_FETCH_GREG_U32_ZX_U64(Src.u64Rax, X86_GREG_xAX);
    1391             IEM_MC_FETCH_GREG_U32_ZX_U64(Src.u64Rdx, X86_GREG_xDX);
     1390            IEM_MC_FETCH_GREG_U32_SX_U64(Src.u64Rax, X86_GREG_xAX);
     1391            IEM_MC_FETCH_GREG_U32_SX_U64(Src.u64Rdx, X86_GREG_xDX);
    13921392            IEM_MC_REF_EFLAGS(pEFlags);
    13931393            IEM_MC_CALL_VOID_AIMPL_4(IEM_SELECT_HOST_OR_FALLBACK(fSse42,
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