VirtualBox

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


Ignore:
Timestamp:
Oct 27, 2023 1:50:02 PM (16 months ago)
Author:
vboxsync
Message:

VMM/IEM: Native implementation of BltIn_CheckMode. bugref:10371

Location:
trunk/src/VBox/VMM
Files:
3 edited

Legend:

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

    r101589 r101626  
    35253525 * Emits the code at the RaiseGP0 label.
    35263526 */
    3527 static uint32_t iemNativeEmitRaiseGp0(PIEMRECOMPILERSTATE pReNative, uint32_t off)
     3527static uint32_t iemNativeEmitRaiseGp0(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t idxReturnLabel)
    35283528{
    35293529    uint32_t const idxLabel = iemNativeLabelFind(pReNative, kIemNativeLabelType_RaiseGp0);
     
    35403540
    35413541        /* jump back to the return sequence. */
    3542         off = iemNativeEmitJmpToLabel(pReNative, off, iemNativeLabelFind(pReNative, kIemNativeLabelType_Return));
     3542        off = iemNativeEmitJmpToLabel(pReNative, off, idxReturnLabel);
     3543    }
     3544    return off;
     3545}
     3546
     3547
     3548/**
     3549 * Emits the code at the ReturnBreak label (returns VINF_IEM_REEXEC_BREAK).
     3550 */
     3551static uint32_t iemNativeEmitReturnBreak(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t idxReturnLabel)
     3552{
     3553    uint32_t const idxLabel = iemNativeLabelFind(pReNative, kIemNativeLabelType_ReturnBreak);
     3554    if (idxLabel != UINT32_MAX)
     3555    {
     3556        iemNativeLabelDefine(pReNative, idxLabel, off);
     3557
     3558        off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_CALL_RET_GREG, VINF_IEM_REEXEC_BREAK);
     3559
     3560        /* jump back to the return sequence. */
     3561        off = iemNativeEmitJmpToLabel(pReNative, off, idxReturnLabel);
    35433562    }
    35443563    return off;
     
    35943613 * Emits a standard epilog.
    35953614 */
    3596 static uint32_t iemNativeEmitEpilog(PIEMRECOMPILERSTATE pReNative, uint32_t off)
    3597 {
     3615static uint32_t iemNativeEmitEpilog(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t *pidxReturnLabel)
     3616{
     3617    *pidxReturnLabel = UINT32_MAX;
     3618
    35983619    /*
    35993620     * Successful return, so clear the return register (eax, w0).
     
    36073628    uint32_t const idxReturn = iemNativeLabelCreate(pReNative, kIemNativeLabelType_Return, off);
    36083629    AssertReturn(idxReturn != UINT32_MAX, UINT32_MAX);
     3630    *pidxReturnLabel = idxReturn;
    36093631
    36103632    /*
     
    48574879    uint8_t const      cbInstr  = (uint8_t)pCallEntry->auParams[1];
    48584880    return iemNativeEmitCImplCall(pReNative, off, pCallEntry->idxInstr, (uintptr_t)pfnCImpl, cbInstr, 0, 0, 0, 0);
     4881}
     4882
     4883
     4884/**
     4885 * Built-in function checks if IEMCPU::fExec has the expected value.
     4886 */
     4887static IEM_DECL_IEMNATIVERECOMPFUNC_DEF(iemNativeRecompFunc_BltIn_CheckMode)
     4888{
     4889    uint32_t const fExpectedExec = (uint32_t)pCallEntry->auParams[0];
     4890
     4891    uint8_t idxTmpReg = iemNativeRegAllocTmp(pReNative, &off);
     4892    AssertReturn(idxTmpReg < RT_ELEMENTS(pReNative->Core.aHstRegs), UINT32_MAX);
     4893    off = iemNativeEmitLoadGprFromVCpuU32(pReNative, off, idxTmpReg, RT_UOFFSETOF(VMCPUCC, iem.s.fExec));
     4894    off = iemNativeEmitAndGpr32ByImm(pReNative, off, idxTmpReg, IEMTB_F_KEY_MASK);
     4895    off = iemNativeEmitTestIfGpr32NotEqualImmAndJmpToNewLabel(pReNative, off, idxTmpReg, fExpectedExec & IEMTB_F_KEY_MASK,
     4896                                                              kIemNativeLabelType_ReturnBreak);
     4897    iemNativeRegFreeTmp(pReNative, idxTmpReg);
     4898    return off;
    48594899}
    48604900
     
    51605200                                case kIemNativeLabelType_Return:
    51615201                                    pszName = "Return";
     5202                                    break;
     5203                                case kIemNativeLabelType_ReturnBreak:
     5204                                    pszName = "ReturnBreak";
    51625205                                    break;
    51635206                                case kIemNativeLabelType_If:
     
    54285471     * Emit the epilog code.
    54295472     */
    5430     off = iemNativeEmitEpilog(pReNative, off);
     5473    uint32_t idxReturnLabel;
     5474    off = iemNativeEmitEpilog(pReNative, off, &idxReturnLabel);
    54315475    AssertReturn(off != UINT32_MAX, pTb);
    54325476
     
    54345478     * Generate special jump labels.
    54355479     */
     5480    if (pReNative->bmLabelTypes & RT_BIT_64(kIemNativeLabelType_ReturnBreak))
     5481    {
     5482        off = iemNativeEmitReturnBreak(pReNative, off, idxReturnLabel);
     5483        AssertReturn(off != UINT32_MAX, pTb);
     5484    }
    54365485    if (pReNative->bmLabelTypes & RT_BIT_64(kIemNativeLabelType_RaiseGp0))
    54375486    {
    5438         off = iemNativeEmitRaiseGp0(pReNative, off);
     5487        off = iemNativeEmitRaiseGp0(pReNative, off, idxReturnLabel);
    54395488        AssertReturn(off != UINT32_MAX, pTb);
    54405489    }
  • trunk/src/VBox/VMM/VMMAll/IEMAllThrdPython.py

    r101557 r101626  
    18781878        ( 'DeferToCImpl0',                                      2, True  ),
    18791879        ( 'CheckIrq',                                           0, False ),
    1880         ( 'CheckMode',                                          1, False ),
     1880        ( 'CheckMode',                                          1, True ),
    18811881        ( 'CheckHwInstrBps',                                    0, False ),
    18821882        ( 'CheckCsLim',                                         1, False ),
  • trunk/src/VBox/VMM/include/IEMN8veRecompiler.h

    r101584 r101626  
    264264    kIemNativeLabelType_Invalid = 0,
    265265    kIemNativeLabelType_Return,
     266    kIemNativeLabelType_ReturnBreak,
    266267    kIemNativeLabelType_If,
    267268    kIemNativeLabelType_Else,
     
    17341735
    17351736/**
     1737 * Emits code for AND'ing an 32-bit GPRs with a constant.
     1738 */
     1739DECLINLINE(uint32_t ) iemNativeEmitAndGpr32ByImm(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprDst, uint32_t uImm)
     1740{
     1741#if defined(RT_ARCH_AMD64)
     1742    /* and Ev, imm */
     1743    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 7);
     1744    AssertReturn(pbCodeBuf, UINT32_MAX);
     1745    if (iGprDst >= 8)
     1746        pbCodeBuf[off++] = X86_OP_REX_R;
     1747    if (uImm < 128)
     1748    {
     1749        pbCodeBuf[off++] = 0x83;
     1750        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4, iGprDst & 7);
     1751        pbCodeBuf[off++] = (uint8_t)uImm;
     1752    }
     1753    else
     1754    {
     1755        pbCodeBuf[off++] = 0x81;
     1756        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4, iGprDst & 7);
     1757        pbCodeBuf[off++] = RT_BYTE1(uImm);
     1758        pbCodeBuf[off++] = RT_BYTE2(uImm);
     1759        pbCodeBuf[off++] = RT_BYTE3(uImm);
     1760        pbCodeBuf[off++] = RT_BYTE4(uImm);
     1761    }
     1762
     1763#elif defined(RT_ARCH_ARM64)
     1764    uint32_t uImmR     = 0;
     1765    uint32_t uImmNandS = 0;
     1766    if (Armv8A64ConvertMaskToImmRImmS(uImm, &uImmNandS, &uImmR))
     1767    {
     1768        uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     1769        AssertReturn(pu32CodeBuf, UINT32_MAX);
     1770        pu32CodeBuf[off++] = Armv8A64MkInstrAndImm(iGprDst, iGprDst, uImmNandS, uImmR, false /*f64Bit*/);
     1771    }
     1772    else
     1773    {
     1774        /* Use temporary register for the immediate. */
     1775        uint8_t iTmpReg = iemNativeRegAllocTmpImm(pReNative, &off, uImm);
     1776        AssertReturn(iTmpReg < RT_ELEMENTS(pReNative->Core.aHstRegs), UINT32_MAX);
     1777
     1778        /* and gprdst, gprdst, tmpreg */
     1779        uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     1780        AssertReturn(pu32CodeBuf, UINT32_MAX);
     1781        pu32CodeBuf[off++] = Armv8A64MkInstrAnd(iGprDst, iGprDst, iTmpReg, false /*f64Bit*/);
     1782
     1783        iemNativeRegFreeTmpImm(pReNative, iTmpReg);
     1784    }
     1785
     1786#else
     1787# error "Port me"
     1788#endif
     1789    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     1790    return off;
     1791}
     1792
     1793
     1794/**
    17361795 * Emits code for XOR'ing two 64-bit GPRs.
    17371796 */
     
    20132072# error "Port me!"
    20142073#endif
     2074    return off;
     2075}
     2076
     2077
     2078/**
     2079 * Emits a compare of a 64-bit GPR with a constant value, settings status
     2080 * flags/whatever for use with conditional instruction.
     2081 */
     2082DECLINLINE(uint32_t) iemNativeEmitCmpGprWithImm(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprLeft, uint64_t uImm)
     2083{
     2084#ifdef RT_ARCH_AMD64
     2085    if (uImm <= UINT32_C(0xff))
     2086    {
     2087        /* cmp Ev, Ib */
     2088        uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 4);
     2089        AssertReturn(pbCodeBuf, UINT32_MAX);
     2090        pbCodeBuf[off++] = X86_OP_REX_W | (iGprLeft >= 8 ? X86_OP_REX_B : 0);
     2091        pbCodeBuf[off++] = 0x83;
     2092        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 7, iGprLeft & 7);
     2093        pbCodeBuf[off++] = (uint8_t)uImm;
     2094    }
     2095    else if ((int64_t)uImm == (int32_t)uImm)
     2096    {
     2097        /* cmp Ev, imm */
     2098        uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 7);
     2099        AssertReturn(pbCodeBuf, UINT32_MAX);
     2100        pbCodeBuf[off++] = X86_OP_REX_W | (iGprLeft >= 8 ? X86_OP_REX_B : 0);
     2101        pbCodeBuf[off++] = 0x81;
     2102        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 7, iGprLeft & 7);
     2103        IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     2104        pbCodeBuf[off++] = RT_BYTE1(uImm);
     2105        pbCodeBuf[off++] = RT_BYTE2(uImm);
     2106        pbCodeBuf[off++] = RT_BYTE3(uImm);
     2107        pbCodeBuf[off++] = RT_BYTE4(uImm);
     2108    }
     2109    else
     2110    {
     2111        /* Use temporary register for the immediate. */
     2112        uint8_t iTmpReg = iemNativeRegAllocTmpImm(pReNative, &off, uImm);
     2113        AssertReturn(iTmpReg < RT_ELEMENTS(pReNative->Core.aHstRegs), UINT32_MAX);
     2114
     2115        off = iemNativeEmitCmpGprWithGpr(pReNative, off, iGprLeft, iTmpReg);
     2116
     2117        iemNativeRegFreeTmpImm(pReNative, iTmpReg);
     2118    }
     2119
     2120#elif defined(RT_ARCH_ARM64)
     2121    /** @todo guess there are clevere things we can do here...   */
     2122    if (uImm < _4K)
     2123    {
     2124        uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     2125        AssertReturn(pu32CodeBuf, UINT32_MAX);
     2126        pu32CodeBuf[off++] = Armv8A64MkInstrAddSubUImm12(true /*fSub*/, ARMV8_A64_REG_XZR, iGprLeft, (uint32_t)uImm,
     2127                                                         true /*64Bit*/, true /*fSetFlags*/);
     2128    }
     2129    else if (uImm < RT_BIT_32(12+12) && (uImm & (_4K - 1)) == 0)
     2130    {
     2131        uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     2132        AssertReturn(pu32CodeBuf, UINT32_MAX);
     2133        pu32CodeBuf[off++] = Armv8A64MkInstrAddSubUImm12(true /*fSub*/, ARMV8_A64_REG_XZR, iGprLeft, (uint32_t)uImm,
     2134                                                         true /*64Bit*/, true /*fSetFlags*/, true /*fShift12*/);
     2135    }
     2136    else
     2137    {
     2138        /* Use temporary register for the immediate. */
     2139        uint8_t iTmpReg = iemNativeRegAllocTmpImm(pReNative, &off, uImm);
     2140        AssertReturn(iTmpReg < RT_ELEMENTS(pReNative->Core.aHstRegs), UINT32_MAX);
     2141
     2142        off = iemNativeEmitCmpGprWithGpr(pReNative, off, iGprLeft, iTmpReg);
     2143
     2144        iemNativeRegFreeTmpImm(pReNative, iTmpReg);
     2145    }
     2146
     2147#else
     2148# error "Port me!"
     2149#endif
     2150
     2151    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     2152    return off;
     2153}
     2154
     2155
     2156/**
     2157 * Emits a compare of a 32-bit GPR with a constant value, settings status
     2158 * flags/whatever for use with conditional instruction.
     2159 */
     2160DECLINLINE(uint32_t) iemNativeEmitCmpGpr32WithImm(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprLeft, uint32_t uImm)
     2161{
     2162#ifdef RT_ARCH_AMD64
     2163    uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 7);
     2164    AssertReturn(pbCodeBuf, UINT32_MAX);
     2165    if (iGprLeft >= 8)
     2166        pbCodeBuf[off++] = X86_OP_REX_B;
     2167    if (uImm <= UINT32_C(0xff))
     2168    {
     2169        /* cmp Ev, Ib */
     2170        pbCodeBuf[off++] = 0x83;
     2171        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 7, iGprLeft & 7);
     2172        pbCodeBuf[off++] = (uint8_t)uImm;
     2173    }
     2174    else
     2175    {
     2176        /* cmp Ev, imm */
     2177        pbCodeBuf[off++] = 0x81;
     2178        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 7, iGprLeft & 7);
     2179        IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     2180        pbCodeBuf[off++] = RT_BYTE1(uImm);
     2181        pbCodeBuf[off++] = RT_BYTE2(uImm);
     2182        pbCodeBuf[off++] = RT_BYTE3(uImm);
     2183        pbCodeBuf[off++] = RT_BYTE4(uImm);
     2184    }
     2185
     2186#elif defined(RT_ARCH_ARM64)
     2187    /** @todo guess there are clevere things we can do here...   */
     2188    if (uImm < _4K)
     2189    {
     2190        uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     2191        AssertReturn(pu32CodeBuf, UINT32_MAX);
     2192        pu32CodeBuf[off++] = Armv8A64MkInstrAddSubUImm12(true /*fSub*/, ARMV8_A64_REG_XZR, iGprLeft, (uint32_t)uImm,
     2193                                                         false /*64Bit*/, true /*fSetFlags*/);
     2194    }
     2195    else if (uImm < RT_BIT_32(12+12) && (uImm & (_4K - 1)) == 0)
     2196    {
     2197        uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     2198        AssertReturn(pu32CodeBuf, UINT32_MAX);
     2199        pu32CodeBuf[off++] = Armv8A64MkInstrAddSubUImm12(true /*fSub*/, ARMV8_A64_REG_XZR, iGprLeft, (uint32_t)uImm,
     2200                                                         false /*64Bit*/, true /*fSetFlags*/, true /*fShift12*/);
     2201    }
     2202    else
     2203    {
     2204        /* Use temporary register for the immediate. */
     2205        uint8_t iTmpReg = iemNativeRegAllocTmpImm(pReNative, &off, uImm);
     2206        AssertReturn(iTmpReg < RT_ELEMENTS(pReNative->Core.aHstRegs), UINT32_MAX);
     2207
     2208        off = iemNativeEmitCmpGpr32WithGpr(pReNative, off, iGprLeft, iTmpReg);
     2209
     2210        iemNativeRegFreeTmpImm(pReNative, iTmpReg);
     2211    }
     2212
     2213#else
     2214# error "Port me!"
     2215#endif
     2216
     2217    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    20152218    return off;
    20162219}
     
    26492852 */
    26502853DECLINLINE(uint32_t) iemNativeEmitTestIfGprIsZeroAndJmpToNewLabel(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprSrc,
    2651                                                                   bool f64Bit, IEMNATIVELABELTYPE enmLabelType, uint16_t uData)
     2854                                                                  bool f64Bit, IEMNATIVELABELTYPE enmLabelType,
     2855                                                                  uint16_t uData = 0)
    26522856{
    26532857    uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmLabelType, UINT32_MAX /*offWhere*/, uData);
     
    26572861
    26582862
     2863/**
     2864 * Emits code that jumps to the given label if @a iGprLeft and @a iGprRight
     2865 * differs.
     2866 */
     2867DECLINLINE(uint32_t) iemNativeEmitTestIfGprNotEqualGprAndJmpToLabel(PIEMRECOMPILERSTATE pReNative, uint32_t off,
     2868                                                                     uint8_t iGprLeft, uint8_t iGprRight, uint32_t idxLabel)
     2869{
     2870    off = iemNativeEmitCmpGprWithGpr(pReNative, off, iGprLeft, iGprRight);
     2871    off = iemNativeEmitJnzToLabel(pReNative, off, idxLabel);
     2872    return off;
     2873}
     2874
     2875
     2876/**
     2877 * Emits code that jumps to a new label if @a iGprLeft and @a iGprRight differs.
     2878 */
     2879DECLINLINE(uint32_t) iemNativeEmitTestIfGprNotEqualGprAndJmpToNewLabel(PIEMRECOMPILERSTATE pReNative, uint32_t off,
     2880                                                                       uint8_t iGprLeft, uint8_t iGprRight,
     2881                                                                       IEMNATIVELABELTYPE enmLabelType, uint16_t uData = 0)
     2882{
     2883    uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmLabelType, UINT32_MAX /*offWhere*/, uData);
     2884    AssertReturn(idxLabel != UINT32_MAX, UINT32_MAX);
     2885    return iemNativeEmitTestIfGprNotEqualGprAndJmpToLabel(pReNative, off, iGprLeft, iGprRight, idxLabel);
     2886}
     2887
     2888
     2889/**
     2890 * Emits code that jumps to the given label if @a iGprSrc differs from @a uImm.
     2891 */
     2892DECLINLINE(uint32_t) iemNativeEmitTestIfGprNotEqualImmAndJmpToLabel(PIEMRECOMPILERSTATE pReNative, uint32_t off,
     2893                                                                    uint8_t iGprSrc, uint64_t uImm, uint32_t idxLabel)
     2894{
     2895    off = iemNativeEmitCmpGprWithImm(pReNative, off, iGprSrc, uImm);
     2896    off = iemNativeEmitJnzToLabel(pReNative, off, idxLabel);
     2897    return off;
     2898}
     2899
     2900
     2901/**
     2902 * Emits code that jumps to a new label if @a iGprSrc differs from @a uImm.
     2903 */
     2904DECLINLINE(uint32_t) iemNativeEmitTestIfGprNotEqualImmAndJmpToNewLabel(PIEMRECOMPILERSTATE pReNative, uint32_t off,
     2905                                                                       uint8_t iGprSrc, uint64_t uImm,
     2906                                                                       IEMNATIVELABELTYPE enmLabelType, uint16_t uData = 0)
     2907{
     2908    uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmLabelType, UINT32_MAX /*offWhere*/, uData);
     2909    AssertReturn(idxLabel != UINT32_MAX, UINT32_MAX);
     2910    return iemNativeEmitTestIfGprNotEqualImmAndJmpToLabel(pReNative, off, iGprSrc, uImm, idxLabel);
     2911}
     2912
     2913
     2914/**
     2915 * Emits code that jumps to the given label if 32-bit @a iGprSrc differs from
     2916 * @a uImm.
     2917 */
     2918DECLINLINE(uint32_t) iemNativeEmitTestIfGpr32NotEqualImmAndJmpToLabel(PIEMRECOMPILERSTATE pReNative, uint32_t off,
     2919                                                                      uint8_t iGprSrc, uint32_t uImm, uint32_t idxLabel)
     2920{
     2921    off = iemNativeEmitCmpGpr32WithImm(pReNative, off, iGprSrc, uImm);
     2922    off = iemNativeEmitJnzToLabel(pReNative, off, idxLabel);
     2923    return off;
     2924}
     2925
     2926
     2927/**
     2928 * Emits code that jumps to a new label if 32-bit @a iGprSrc differs from
     2929 * @a uImm.
     2930 */
     2931DECLINLINE(uint32_t) iemNativeEmitTestIfGpr32NotEqualImmAndJmpToNewLabel(PIEMRECOMPILERSTATE pReNative, uint32_t off,
     2932                                                                         uint8_t iGprSrc, uint32_t uImm,
     2933                                                                         IEMNATIVELABELTYPE enmLabelType, uint16_t uData = 0)
     2934{
     2935    uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmLabelType, UINT32_MAX /*offWhere*/, uData);
     2936    AssertReturn(idxLabel != UINT32_MAX, UINT32_MAX);
     2937    return iemNativeEmitTestIfGpr32NotEqualImmAndJmpToLabel(pReNative, off, iGprSrc, uImm, idxLabel);
     2938}
     2939
     2940
    26592941
    26602942/**
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