VirtualBox

Changeset 103682 in vbox


Ignore:
Timestamp:
Mar 5, 2024 2:23:15 PM (13 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
162047
Message:

VMM/IEM: Cleaning up IEMAllN8veEmit-x86.h a little. bugref:10376

File:
1 edited

Legend:

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

    r103677 r103682  
    273273
    274274
     275/**
     276 * The AND instruction will clear OF, CF and AF (latter is undefined) and
     277 * set the other flags according to the result.
     278 */
    275279DECL_INLINE_THROW(uint32_t)
    276280iemNativeEmit_and_r_r_efl(PIEMRECOMPILERSTATE pReNative, uint32_t off,
    277281                          uint8_t idxVarDst, uint8_t idxVarSrc, uint8_t idxVarEfl, uint8_t cOpBits)
    278282{
    279     /*
    280      * The AND instruction will clear OF, CF and AF (latter is undefined),
    281      * so we don't need the initial destination value.
    282      *
    283      * On AMD64 we must use the correctly sized AND instructions to get the
    284      * right EFLAGS.SF value, while the rest will just lump 16-bit and 8-bit
    285      * in the 32-bit ones.
    286      */
    287     /** @todo we could use ANDS on ARM64 and get the ZF for free for all
    288      *        variants, and SF for 32-bit and 64-bit.  */
    289283    uint8_t const idxRegDst = iemNativeVarRegisterAcquire(pReNative, idxVarDst, &off, true /*fInitialized*/);
    290284    uint8_t const idxRegSrc = iemNativeVarRegisterAcquire(pReNative, idxVarSrc, &off, true /*fInitialized*/);
    291     //off = iemNativeEmitBrk(pReNative, off, 0x2222);
    292     switch (cOpBits)
    293     {
    294         case 32:
    295 #ifndef RT_ARCH_AMD64
    296         case 16:
    297         case 8:
    298 #endif
    299             off = iemNativeEmitAndGpr32ByGpr32(pReNative, off, idxRegDst, idxRegSrc);
    300             break;
    301 
    302         default: AssertFailed(); RT_FALL_THRU();
    303         case 64:
    304             off = iemNativeEmitAndGprByGpr(pReNative, off, idxRegDst, idxRegSrc);
    305             break;
    306 
    307 #ifdef RT_ARCH_AMD64
    308         case 16:
    309         {
    310             PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
    311             pCodeBuf[off++] = X86_OP_PRF_SIZE_OP;
    312             off = iemNativeEmitAndGpr32ByGpr32(pReNative, off, idxRegDst, idxRegSrc);
    313             break;
    314         }
    315 
    316         case 8:
    317         {
    318             PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 3);
    319             if (idxRegDst >= 8 || idxRegSrc >= 8)
    320                 pCodeBuf[off++] = (idxRegDst >= 8 ? X86_OP_REX_R : 0) | (idxRegSrc >= 8 ? X86_OP_REX_B : 0);
    321             else if (idxRegDst >= 4 || idxRegSrc >= 4)
    322                 pCodeBuf[off++] = X86_OP_REX;
    323             pCodeBuf[off++] = 0x22;
    324             pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, idxRegDst & 7, idxRegSrc & 7);
    325             IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    326             break;
    327         }
    328 #endif
    329     }
     285#ifdef RT_ARCH_AMD64
     286    /* On AMD64 we just use the correctly size AND instruction harvest the EFLAGS. */
     287    off = iemNativeEmitAmd64ModRmInstrRREx(iemNativeInstrBufEnsure(pReNative, off, 4), off,
     288                                           0x22, 0x23, cOpBits, idxRegDst, idxRegSrc);
     289    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     290
     291#elif defined(RT_ARCH_ARM64)
     292    /* On ARM64 we use 32-bit AND for the 8-bit and 16-bit bit ones. */
     293    /** @todo we should use ANDS on ARM64 and get the ZF for free for all
     294     *        variants, and SF for 32-bit and 64-bit.  */
     295    PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     296    pCodeBuf[off++] = Armv8A64MkInstrAnd(idxRegDst, idxRegDst, idxRegSrc, cOpBits > 32 /*f64Bit*/);
     297    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     298
     299#else
     300# error "Port me"
     301#endif
    330302    iemNativeVarRegisterRelease(pReNative, idxVarSrc);
    331303
     
    336308
    337309
     310/**
     311 * The TEST instruction will clear OF, CF and AF (latter is undefined) and
     312 * set the other flags according to the result.
     313 */
    338314DECL_INLINE_THROW(uint32_t)
    339315iemNativeEmit_test_r_r_efl(PIEMRECOMPILERSTATE pReNative, uint32_t off,
    340316                           uint8_t idxVarDst, uint8_t idxVarSrc, uint8_t idxVarEfl, uint8_t cOpBits)
    341317{
    342     /*
    343      * The TESTS instruction will clear OF, CF and AF (latter is undefined),
    344      * so we don't need the initial destination value.
    345      *
    346      * On AMD64 we use the matching native instruction.
    347      *
    348      * On ARM64 we need a real register for the AND result so we can calculate
    349      * PF correctly for it.  This means that we have to use a three operand
    350      * AND variant, which makes the code widely different from AMD64.
    351      */
    352     /** @todo we could use ANDS on ARM64 and get the ZF for free for all
    353      *        variants, and SF for 32-bit and 64-bit.  */
    354318    uint8_t const         idxRegDst    = iemNativeVarRegisterAcquire(pReNative, idxVarDst, &off, true /*fInitialized*/);
    355319    uint8_t const         idxRegSrc    = idxVarSrc == idxVarDst ? idxRegDst /* special case of 'test samereg,samereg' */
    356320                                       : iemNativeVarRegisterAcquire(pReNative, idxVarSrc, &off, true /*fInitialized*/);
    357 #ifndef RT_ARCH_AMD64
     321#ifdef RT_ARCH_AMD64
     322    /* On AMD64 we just use the correctly size TEST instruction harvest the EFLAGS. */
     323    off = iemNativeEmitAmd64ModRmInstrRREx(iemNativeInstrBufEnsure(pReNative, off, 4), off,
     324                                           0x84, 0x85, cOpBits, idxRegSrc, idxRegDst);
     325    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     326
     327#elif defined(RT_ARCH_ARM64)
     328    /* On ARM64 we use 32-bit AND for the 8-bit and 16-bit bit ones.  We also
     329       need to keep the result in order to calculate the flags. */
     330    /** @todo we should use ANDS on ARM64 and get the ZF for free for all
     331     *        variants, and SF for 32-bit and 64-bit.  */
    358332    uint8_t const         idxRegResult = iemNativeRegAllocTmp(pReNative, &off);
    359 #endif
    360 //    off = iemNativeEmitBrk(pReNative, off, 0x2222);
    361     PIEMNATIVEINSTR const pCodeBuf     = iemNativeInstrBufEnsure(pReNative, off, RT_ARCH_VAL == RT_ARCH_VAL_AMD64 ? 4 : 1);
    362 #ifdef RT_ARCH_ARM64
     333    PIEMNATIVEINSTR const pCodeBuf     = iemNativeInstrBufEnsure(pReNative, off, 1);
    363334    pCodeBuf[off++] = Armv8A64MkInstrAnd(idxRegResult, idxRegDst, idxRegSrc, cOpBits > 32 /*f64Bit*/);
    364 
    365 #elif defined(RT_ARCH_AMD64)
    366     switch (cOpBits)
    367     {
    368         case 16:
    369             pCodeBuf[off++] = X86_OP_PRF_SIZE_OP;
    370             RT_FALL_THRU();
    371         case 32:
    372             if (idxRegDst >= 8 || idxRegSrc >= 8)
    373                 pCodeBuf[off++] = (idxRegDst >= 8 ? X86_OP_REX_B : 0) | (idxRegSrc >= 8 ? X86_OP_REX_R : 0);
    374             pCodeBuf[off++] = 0x85;
    375             break;
    376 
    377         default: AssertFailed(); RT_FALL_THRU();
    378         case 64:
    379             pCodeBuf[off++] = X86_OP_REX_W | (idxRegDst >= 8 ? X86_OP_REX_B : 0) | (idxRegSrc >= 8 ? X86_OP_REX_R : 0);
    380             pCodeBuf[off++] = 0x85;
    381             break;
    382 
    383         case 8:
    384             if (idxRegDst >= 8 || idxRegSrc >= 8)
    385                 pCodeBuf[off++] = (idxRegDst >= 8 ? X86_OP_REX_B : 0) | (idxRegSrc >= 8 ? X86_OP_REX_R : 0);
    386             else if (idxRegDst >= 4 || idxRegSrc >= 4)
    387                 pCodeBuf[off++] = X86_OP_REX;
    388             pCodeBuf[off++] = 0x84;
    389             break;
    390     }
    391     pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, idxRegSrc & 7, idxRegDst & 7);
    392 #else
    393 # error "port me"
    394 #endif
    395     IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     335    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     336
     337#else
     338# error "Port me"
     339#endif
    396340    if (idxVarSrc != idxVarDst)
    397341        iemNativeVarRegisterRelease(pReNative, idxVarSrc);
     
    408352
    409353
     354/**
     355 * The OR instruction will clear OF, CF and AF (latter is undefined) and
     356 * set the other flags according to the result.
     357 */
    410358DECL_INLINE_THROW(uint32_t)
    411359iemNativeEmit_or_r_r_efl(PIEMRECOMPILERSTATE pReNative, uint32_t off,
    412360                         uint8_t idxVarDst, uint8_t idxVarSrc, uint8_t idxVarEfl, uint8_t cOpBits)
    413361{
    414     /*
    415      * The OR instruction will clear OF, CF and AF (latter is undefined),
    416      * so we don't need the initial destination value.
    417      *
    418      * On AMD64 we must use the correctly sized OR instructions to get the
    419      * right EFLAGS.SF value, while the rest will just lump 16-bit and 8-bit
    420      * in the 32-bit ones.
    421      */
    422362    uint8_t const idxRegDst = iemNativeVarRegisterAcquire(pReNative, idxVarDst, &off, true /*fInitialized*/);
    423363    uint8_t const idxRegSrc = iemNativeVarRegisterAcquire(pReNative, idxVarSrc, &off, true /*fInitialized*/);
    424     //off = iemNativeEmitBrk(pReNative, off, 0x2222);
    425     switch (cOpBits)
    426     {
    427         case 32:
    428 #ifndef RT_ARCH_AMD64
    429         case 16:
    430         case 8:
    431 #endif
    432             off = iemNativeEmitOrGpr32ByGpr(pReNative, off, idxRegDst, idxRegSrc);
    433             break;
    434 
    435         default: AssertFailed(); RT_FALL_THRU();
    436         case 64:
    437             off = iemNativeEmitOrGprByGpr(pReNative, off, idxRegDst, idxRegSrc);
    438             break;
    439 
    440 #ifdef RT_ARCH_AMD64
    441         case 16:
    442         {
    443             PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
    444             pCodeBuf[off++] = X86_OP_PRF_SIZE_OP;
    445             off = iemNativeEmitOrGpr32ByGpr(pReNative, off, idxRegDst, idxRegSrc);
    446             break;
    447         }
    448 
    449         case 8:
    450         {
    451             PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 3);
    452             if (idxRegDst >= 8 || idxRegSrc >= 8)
    453                 pCodeBuf[off++] = (idxRegDst >= 8 ? X86_OP_REX_R : 0) | (idxRegSrc >= 8 ? X86_OP_REX_B : 0);
    454             else if (idxRegDst >= 4 || idxRegSrc >= 4)
    455                 pCodeBuf[off++] = X86_OP_REX;
    456             pCodeBuf[off++] = 0x0a;
    457             pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, idxRegDst & 7, idxRegSrc & 7);
    458             IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    459             break;
    460         }
    461 #endif
    462     }
     364#ifdef RT_ARCH_AMD64
     365    /* On AMD64 we just use the correctly size OR instruction harvest the EFLAGS. */
     366    off = iemNativeEmitAmd64ModRmInstrRREx(iemNativeInstrBufEnsure(pReNative, off, 4), off,
     367                                           0x0a, 0x0b, cOpBits, idxRegDst, idxRegSrc);
     368    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     369
     370#elif defined(RT_ARCH_ARM64)
     371    /* On ARM64 we use 32-bit OR for the 8-bit and 16-bit bit ones. */
     372    PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     373    pCodeBuf[off++] = Armv8A64MkInstrOrr(idxRegDst, idxRegDst, idxRegSrc, cOpBits > 32 /*f64Bit*/);
     374    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     375
     376#else
     377# error "Port me"
     378#endif
    463379    iemNativeVarRegisterRelease(pReNative, idxVarSrc);
    464380
     
    469385
    470386
     387/**
     388 * The XOR instruction will clear OF, CF and AF (latter is undefined) and
     389 * set the other flags according to the result.
     390 */
    471391DECL_INLINE_THROW(uint32_t)
    472392iemNativeEmit_xor_r_r_efl(PIEMRECOMPILERSTATE pReNative, uint32_t off,
    473393                          uint8_t idxVarDst, uint8_t idxVarSrc, uint8_t idxVarEfl, uint8_t cOpBits)
    474394{
    475     /*
    476      * The XOR instruction will clear OF, CF and AF (latter is undefined),
    477      * so we don't need the initial destination value.
    478      *
    479      * On AMD64 we must use the correctly sizeed XOR instructions to get the
    480      * right EFLAGS.SF value, while the rest will just lump 16-bit and 8-bit
    481      * in the 32-bit ones.
    482      */
    483395    uint8_t const idxRegDst = iemNativeVarRegisterAcquire(pReNative, idxVarDst, &off, true /*fInitialized*/);
    484396    uint8_t const idxRegSrc = iemNativeVarRegisterAcquire(pReNative, idxVarSrc, &off, true /*fInitialized*/);
    485     //off = iemNativeEmitBrk(pReNative, off, 0x2222);
    486     switch (cOpBits)
    487     {
    488         case 32:
    489 #ifndef RT_ARCH_AMD64
    490         case 16:
    491         case 8:
    492 #endif
    493             off = iemNativeEmitXorGpr32ByGpr32(pReNative, off, idxRegDst, idxRegSrc);
    494             break;
    495 
    496         default: AssertFailed(); RT_FALL_THRU();
    497         case 64:
    498             off = iemNativeEmitXorGprByGpr(pReNative, off, idxRegDst, idxRegSrc);
    499             break;
    500 
    501 #ifdef RT_ARCH_AMD64
    502         case 16:
    503         {
    504             PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
    505             pCodeBuf[off++] = X86_OP_PRF_SIZE_OP;
    506             off = iemNativeEmitXorGpr32ByGpr32(pReNative, off, idxRegDst, idxRegSrc);
    507             break;
    508         }
    509 
    510         case 8:
    511         {
    512             PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 3);
    513             if (idxRegDst >= 8 || idxRegSrc >= 8)
    514                 pCodeBuf[off++] = (idxRegDst >= 8 ? X86_OP_REX_R : 0) | (idxRegSrc >= 8 ? X86_OP_REX_B : 0);
    515             else if (idxRegDst >= 4 || idxRegSrc >= 4)
    516                 pCodeBuf[off++] = X86_OP_REX;
    517             pCodeBuf[off++] = 0x32;
    518             pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, idxRegDst & 7, idxRegSrc & 7);
    519             IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    520             break;
    521         }
    522 #endif
    523     }
     397#ifdef RT_ARCH_AMD64
     398    /* On AMD64 we just use the correctly size OR instruction harvest the EFLAGS. */
     399    off = iemNativeEmitAmd64ModRmInstrRREx(iemNativeInstrBufEnsure(pReNative, off, 4), off,
     400                                           0x32, 0x33, cOpBits, idxRegDst, idxRegSrc);
     401    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     402
     403#elif defined(RT_ARCH_ARM64)
     404    /* On ARM64 we use 32-bit OR for the 8-bit and 16-bit bit ones. */
     405    PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     406    pCodeBuf[off++] = Armv8A64MkInstrEor(idxRegDst, idxRegDst, idxRegSrc, cOpBits > 32 /*f64Bit*/);
     407    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     408
     409#else
     410# error "Port me"
     411#endif
    524412    iemNativeVarRegisterRelease(pReNative, idxVarSrc);
    525413
     
    560448    uint8_t const idxRegSrc = iemNativeVarRegisterAcquire(pReNative, idxVarSrc, &off, true /*fInitialized*/);
    561449
    562 #ifdef RT_ARCH_ARM64
     450#ifdef RT_ARCH_AMD64
     451    /* On AMD64 we just use the correctly sized SUB instruction to get the right EFLAGS.SF value. */
     452    off = iemNativeEmitAmd64ModRmInstrRREx(iemNativeInstrBufEnsure(pReNative, off, 4), off,
     453                                           0x2a, 0x2b, cOpBits, idxRegDst, idxRegSrc);
     454    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     455
     456    iemNativeVarRegisterRelease(pReNative, idxVarSrc);
     457    iemNativeVarRegisterRelease(pReNative, idxVarDst);
     458
     459    off = iemNativeEmitEFlagsForArithmetic(pReNative, off, idxVarEfl);
     460
     461#elif defined(RT_ARCH_ARM64)
    563462    /* On ARM64 we'll need the two input operands as well as the result in order
    564463       to calculate the right flags, even if we use SUBS and translates NZCV into
    565464       OF, CF, ZF and SF. */
    566 
    567465    uint8_t const         idxRegDstIn = iemNativeRegAllocTmp(pReNative, &off);
    568466    PIEMNATIVEINSTR const pCodeBuf    = iemNativeInstrBufEnsure(pReNative, off, 4);
     
    592490    iemNativeVarRegisterRelease(pReNative, idxVarDst);
    593491
    594 #elif defined(RT_ARCH_AMD64)
    595     /* On AMD64 we just use the correctly sized SUB instruction to get the right EFLAGS.SF value. */
    596     off = iemNativeEmitAmd64ModRmInstrRREx(iemNativeInstrBufEnsure(pReNative, off, 4), off,
    597                                            0x2a, 0x2b, cOpBits, idxRegDst, idxRegSrc);
    598     IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    599 
    600     iemNativeVarRegisterRelease(pReNative, idxVarSrc);
    601     iemNativeVarRegisterRelease(pReNative, idxVarDst);
    602 
    603     off = iemNativeEmitEFlagsForArithmetic(pReNative, off, idxVarEfl);
    604 
    605492#else
    606493# error "port me"
     
    620507    uint8_t const idxRegSrc = iemNativeVarRegisterAcquire(pReNative, idxVarSrc, &off, true /*fInitialized*/);
    621508
    622 #ifdef RT_ARCH_ARM64
     509#ifdef RT_ARCH_AMD64
     510    /* On AMD64 we just use the correctly sized CMP instruction to get the right EFLAGS.SF value. */
     511    off = iemNativeEmitAmd64ModRmInstrRREx(iemNativeInstrBufEnsure(pReNative, off, 4), off,
     512                                           0x3a, 0x3b, cOpBits, idxRegDst, idxRegSrc);
     513    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     514
     515    iemNativeVarRegisterRelease(pReNative, idxVarSrc);
     516    iemNativeVarRegisterRelease(pReNative, idxVarDst);
     517
     518    off = iemNativeEmitEFlagsForArithmetic(pReNative, off, idxVarEfl);
     519
     520#elif defined(RT_ARCH_ARM64)
    623521    /* On ARM64 we'll need the actual result as well as both input operands in order
    624522       to calculate the right flags, even if we use SUBS and translates NZCV into
    625523       OF, CF, ZF and SF. */
    626 
    627524    uint8_t const         idxRegResult = iemNativeRegAllocTmp(pReNative, &off);
    628525    PIEMNATIVEINSTR const pCodeBuf     = iemNativeInstrBufEnsure(pReNative, off, 3);
     
    648545    iemNativeVarRegisterRelease(pReNative, idxVarDst);
    649546
    650 #elif defined(RT_ARCH_AMD64)
    651     /* On AMD64 we just use the correctly sized CMP instruction to get the right EFLAGS.SF value. */
    652     off = iemNativeEmitAmd64ModRmInstrRREx(iemNativeInstrBufEnsure(pReNative, off, 4), off,
    653                                            0x3a, 0x3b, cOpBits, idxRegDst, idxRegSrc);
    654     IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    655 
    656     iemNativeVarRegisterRelease(pReNative, idxVarSrc);
    657     iemNativeVarRegisterRelease(pReNative, idxVarDst);
    658 
    659     off = iemNativeEmitEFlagsForArithmetic(pReNative, off, idxVarEfl);
    660 
    661547#else
    662548# error "port me"
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