Changeset 101626 in vbox for trunk/src/VBox/VMM/include
- Timestamp:
- Oct 27, 2023 1:50:02 PM (15 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/include/IEMN8veRecompiler.h
r101584 r101626 264 264 kIemNativeLabelType_Invalid = 0, 265 265 kIemNativeLabelType_Return, 266 kIemNativeLabelType_ReturnBreak, 266 267 kIemNativeLabelType_If, 267 268 kIemNativeLabelType_Else, … … 1734 1735 1735 1736 /** 1737 * Emits code for AND'ing an 32-bit GPRs with a constant. 1738 */ 1739 DECLINLINE(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 /** 1736 1795 * Emits code for XOR'ing two 64-bit GPRs. 1737 1796 */ … … 2013 2072 # error "Port me!" 2014 2073 #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 */ 2082 DECLINLINE(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 */ 2160 DECLINLINE(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); 2015 2218 return off; 2016 2219 } … … 2649 2852 */ 2650 2853 DECLINLINE(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) 2652 2856 { 2653 2857 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmLabelType, UINT32_MAX /*offWhere*/, uData); … … 2657 2861 2658 2862 2863 /** 2864 * Emits code that jumps to the given label if @a iGprLeft and @a iGprRight 2865 * differs. 2866 */ 2867 DECLINLINE(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 */ 2879 DECLINLINE(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 */ 2892 DECLINLINE(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 */ 2904 DECLINLINE(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 */ 2918 DECLINLINE(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 */ 2931 DECLINLINE(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 2659 2941 2660 2942 /**
Note:
See TracChangeset
for help on using the changeset viewer.