VirtualBox

Ignore:
Timestamp:
Mar 3, 2024 2:20:46 AM (14 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
162008
Message:

VMM/IEM: Implemented iemNativeEmit_test_r_r_efl and enabled it for AMD64 hosts. bugref:10376

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/target-x86/IEMAllN8veEmit-x86.h

    r103646 r103648  
    129129{
    130130    /*
    131      * The AND instruction will clear OF, CF and AF (latter is off undefined),
     131     * The AND instruction will clear OF, CF and AF (latter is undefined),
    132132     * so we don't need the initial destination value.
    133133     *
     
    191191                           uint8_t idxVarDst, uint8_t idxVarSrc, uint8_t idxVarEfl, uint8_t cOpBits)
    192192{
    193     RT_NOREF(idxVarDst, idxVarSrc, idxVarEfl, cOpBits);
    194     AssertFailed();
    195     return iemNativeEmitBrk(pReNative, off, 0x666);
     193    /*
     194     * The TESTS instruction will clear OF, CF and AF (latter is undefined),
     195     * so we don't need the initial destination value.
     196     *
     197     * On AMD64 we use the matching native instruction.
     198     *
     199     * On ARM64 we need a real register for the AND result so we can calculate
     200     * PF correctly for it.  This means that we have to use a three operand
     201     * AND variant, which makes the code widely different from AMD64.
     202     */
     203    /** @todo we could use ANDS on ARM64 and get the ZF for free for all
     204     *        variants, and SF for 32-bit and 64-bit.  */
     205    uint8_t const         idxRegDst    = iemNativeVarRegisterAcquire(pReNative, idxVarDst, &off, true /*fInitialized*/);
     206    uint8_t const         idxRegSrc    = iemNativeVarRegisterAcquire(pReNative, idxVarSrc, &off, true /*fInitialized*/);
     207#ifndef RT_ARCH_AMD64
     208    uint8_t const         idxRegResult = iemNativeRegAllocTmp(pReNative, &off);
     209#endif
     210//    off = iemNativeEmitBrk(pReNative, off, 0x2222);
     211    PIEMNATIVEINSTR const pCodeBuf     = iemNativeInstrBufEnsure(pReNative, off, RT_ARCH_VAL == RT_ARCH_VAL_AMD64 ? 4 : 1);
     212#ifdef RT_ARCH_ARM64
     213    pCodeBuf[off++] = Armv8A64MkInstrAnd(idxRegResult, idxRegDst, idxRegSrc, cOpBits > 32 /*f64Bit*/);
     214
     215#elif defined(RT_ARCH_AMD64)
     216    switch (cOpBits)
     217    {
     218        case 16:
     219            pCodeBuf[off++] = X86_OP_PRF_SIZE_OP;
     220            RT_FALL_THRU();
     221        case 32:
     222            if (idxRegDst >= 8 || idxRegSrc >= 8)
     223                pCodeBuf[off++] = (idxRegDst >= 8 ? X86_OP_REX_B : 0) | (idxRegSrc >= 8 ? X86_OP_REX_R : 0);
     224            pCodeBuf[off++] = 0x85;
     225            break;
     226
     227        default: AssertFailed(); RT_FALL_THRU();
     228        case 64:
     229            pCodeBuf[off++] = X86_OP_REX_W | (idxRegDst >= 8 ? X86_OP_REX_B : 0) | (idxRegSrc >= 8 ? X86_OP_REX_R : 0);
     230            pCodeBuf[off++] = 0x85;
     231            break;
     232
     233        case 8:
     234            if (idxRegDst >= 8 || idxRegSrc >= 8)
     235                pCodeBuf[off++] = (idxRegDst >= 8 ? X86_OP_REX_B : 0) | (idxRegSrc >= 8 ? X86_OP_REX_R : 0);
     236            else if (idxRegDst >= 4 || idxRegSrc >= 4)
     237                pCodeBuf[off++] = X86_OP_REX;
     238            pCodeBuf[off++] = 0x84;
     239            break;
     240    }
     241    pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, idxRegSrc & 7, idxRegDst & 7);
     242#else
     243# error "port me"
     244#endif
     245    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     246    iemNativeVarRegisterRelease(pReNative, idxVarSrc);
     247    iemNativeVarRegisterRelease(pReNative, idxVarDst);
     248
     249#ifdef RT_ARCH_AMD64
     250    off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl, cOpBits, UINT8_MAX);
     251#else
     252    off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl, cOpBits, idxRegResult);
     253    iemNativeRegFreeTmp(pReNative, idxRegResult);
     254#endif
     255    return off;
    196256}
    197257
     
    202262{
    203263    /*
    204      * The OR instruction will clear OF, CF and AF (latter is off undefined),
     264     * The OR instruction will clear OF, CF and AF (latter is undefined),
    205265     * so we don't need the initial destination value.
    206266     *
     
    263323{
    264324    /*
    265      * The XOR instruction will clear OF, CF and AF (latter is off undefined),
     325     * The XOR instruction will clear OF, CF and AF (latter is undefined),
    266326     * so we don't need the initial destination value.
    267327     *
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