VirtualBox

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


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

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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