Changeset 93792 in vbox for trunk/src/VBox
- Timestamp:
- Feb 16, 2022 1:30:16 PM (3 years ago)
- Location:
- trunk/src/VBox/VMM/VMMAll
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm
r93115 r93792 1102 1102 1103 1103 1104 ;; 1105 ; Macro for implementing memory fence operation. 1106 ; 1107 ; No return value, no operands or anything. 1108 ; 1109 ; @param 1 The instruction. 1110 ; 1111 %macro IEMIMPL_MEM_FENCE 1 1112 BEGINCODE 1113 BEGINPROC_FASTCALL iemAImpl_ %+ %1, 0 1114 %1 1115 ret 1116 ENDPROC iemAImpl_ %+ %1 1117 %endmacro 1118 1119 IEMIMPL_MEM_FENCE lfence 1120 IEMIMPL_MEM_FENCE sfence 1121 IEMIMPL_MEM_FENCE mfence 1122 1123 ;; 1124 ; Alternative for non-SSE2 host. 1125 ; 1126 BEGINPROC_FASTCALL iemAImpl_alt_mem_fence, 0 1127 push xAX 1128 xchg xAX, [xSP] 1129 add xSP, xCB 1130 ret 1131 ENDPROC iemAImpl_alt_mem_fence 1132 1104 ; 1105 ; BSWAP. No flag changes. 1106 ; 1107 ; Each function takes one argument, pointer to the value to bswap 1108 ; (input/output). They all return void. 1109 ; 1110 BEGINPROC_FASTCALL iemAImpl_bswap_u16, 4 1111 PROLOGUE_1_ARGS 1112 mov T0_32, [A0] ; just in case any of the upper bits are used. 1113 db 66h 1114 bswap T0_32 1115 mov [A0], T0_32 1116 EPILOGUE_1_ARGS 1117 ENDPROC iemAImpl_bswap_u16 1118 1119 BEGINPROC_FASTCALL iemAImpl_bswap_u32, 4 1120 PROLOGUE_1_ARGS 1121 mov T0_32, [A0] 1122 bswap T0_32 1123 mov [A0], T0_32 1124 EPILOGUE_1_ARGS 1125 ENDPROC iemAImpl_bswap_u32 1126 1127 BEGINPROC_FASTCALL iemAImpl_bswap_u64, 4 1128 %ifdef RT_ARCH_AMD64 1129 PROLOGUE_1_ARGS 1130 mov T0, [A0] 1131 bswap T0 1132 mov [A0], T0 1133 EPILOGUE_1_ARGS 1134 %else 1135 PROLOGUE_1_ARGS 1136 mov T0, [A0] 1137 mov T1, [A0 + 4] 1138 bswap T0 1139 bswap T1 1140 mov [A0 + 4], T0 1141 mov [A0], T1 1142 EPILOGUE_1_ARGS 1143 %endif 1144 ENDPROC iemAImpl_bswap_u64 1133 1145 1134 1146 … … 1744 1756 1745 1757 1746 ; 1747 ; BSWAP. No flag changes. 1748 ; 1749 ; Each function takes one argument, pointer to the value to bswap 1750 ; (input/output). They all return void. 1751 ; 1752 BEGINPROC_FASTCALL iemAImpl_bswap_u16, 4 1753 PROLOGUE_1_ARGS 1754 mov T0_32, [A0] ; just in case any of the upper bits are used. 1755 db 66h 1756 bswap T0_32 1757 mov [A0], T0_32 1758 EPILOGUE_1_ARGS 1759 ENDPROC iemAImpl_bswap_u16 1760 1761 BEGINPROC_FASTCALL iemAImpl_bswap_u32, 4 1762 PROLOGUE_1_ARGS 1763 mov T0_32, [A0] 1764 bswap T0_32 1765 mov [A0], T0_32 1766 EPILOGUE_1_ARGS 1767 ENDPROC iemAImpl_bswap_u32 1768 1769 BEGINPROC_FASTCALL iemAImpl_bswap_u64, 4 1770 %ifdef RT_ARCH_AMD64 1771 PROLOGUE_1_ARGS 1772 mov T0, [A0] 1773 bswap T0 1774 mov [A0], T0 1775 EPILOGUE_1_ARGS 1776 %else 1777 PROLOGUE_1_ARGS 1778 mov T0, [A0] 1779 mov T1, [A0 + 4] 1780 bswap T0 1781 bswap T1 1782 mov [A0 + 4], T0 1783 mov [A0], T1 1784 EPILOGUE_1_ARGS 1785 %endif 1786 ENDPROC iemAImpl_bswap_u64 1758 ;; 1759 ; Macro for implementing memory fence operation. 1760 ; 1761 ; No return value, no operands or anything. 1762 ; 1763 ; @param 1 The instruction. 1764 ; 1765 %macro IEMIMPL_MEM_FENCE 1 1766 BEGINCODE 1767 BEGINPROC_FASTCALL iemAImpl_ %+ %1, 0 1768 %1 1769 ret 1770 ENDPROC iemAImpl_ %+ %1 1771 %endmacro 1772 1773 IEMIMPL_MEM_FENCE lfence 1774 IEMIMPL_MEM_FENCE sfence 1775 IEMIMPL_MEM_FENCE mfence 1776 1777 ;; 1778 ; Alternative for non-SSE2 host. 1779 ; 1780 BEGINPROC_FASTCALL iemAImpl_alt_mem_fence, 0 1781 push xAX 1782 xchg xAX, [xSP] 1783 add xSP, xCB 1784 ret 1785 ENDPROC iemAImpl_alt_mem_fence 1787 1786 1788 1787 -
trunk/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp
r93786 r93792 2281 2281 *********************************************************************************************************************************/ 2282 2282 2283 /* 2284 * ROL 2285 */ 2286 2287 /** 2288 * Updates the status bits (OF and CF) for an ROL instruction. 2289 * 2290 * @returns Status bits. 2291 * @param a_pfEFlags Pointer to the 32-bit EFLAGS value to update. 2292 * @param a_uResult Unsigned result value. 2293 * @param a_cBitsWidth The width of the result (8, 16, 32, 64). 2294 */ 2295 #define IEM_EFL_UPDATE_STATUS_BITS_FOR_ROL(a_pfEFlags, a_uResult, a_cBitsWidth) do { \ 2296 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement \ 2297 it the same way as for 1 bit shifts. */ \ 2298 AssertCompile(X86_EFL_CF_BIT == 0); \ 2299 uint32_t fEflTmp = *(a_pfEFlags); \ 2300 fEflTmp &= ~(X86_EFL_CF | X86_EFL_OF); \ 2301 uint32_t const fCarry = ((a_uResult) & X86_EFL_CF); \ 2302 fEflTmp |= fCarry; \ 2303 fEflTmp |= (((a_uResult) >> (a_cBitsWidth - 1)) ^ fCarry) << X86_EFL_OF_BIT; \ 2304 *(a_pfEFlags) = fEflTmp; \ 2305 } while (0) 2306 2283 2307 IEM_DECL_IMPL_DEF(void, iemAImpl_rol_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags)) 2284 2308 { … … 2286 2310 if (cShift) 2287 2311 { 2288 uint64_t uDst = *puDst; 2289 uint64_t uResult; 2290 uResult = uDst << cShift; 2291 uResult |= uDst >> (64 - cShift); 2312 uint64_t uResult = ASMRotateLeftU64(*puDst, cShift); 2292 2313 *puDst = uResult; 2293 2294 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement 2295 it the same way as for 1 bit shifts. */ 2296 AssertCompile(X86_EFL_CF_BIT == 0); 2297 uint32_t fEfl = *pfEFlags & ~(X86_EFL_CF | X86_EFL_OF); 2298 uint32_t fCarry = (uResult & 1); 2299 fEfl |= fCarry; 2300 fEfl |= ((uResult >> 63) ^ fCarry) << X86_EFL_OF_BIT; 2301 *pfEFlags = fEfl; 2302 } 2303 } 2304 2314 IEM_EFL_UPDATE_STATUS_BITS_FOR_ROL(pfEFlags, uResult, 64); 2315 } 2316 } 2317 2318 # if !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) 2319 2320 IEM_DECL_IMPL_DEF(void, iemAImpl_rol_u32,(uint32_t *puDst, uint8_t cShift, uint32_t *pfEFlags)) 2321 { 2322 cShift &= 31; 2323 if (cShift) 2324 { 2325 uint32_t uResult = ASMRotateLeftU32(*puDst, cShift); 2326 *puDst = uResult; 2327 IEM_EFL_UPDATE_STATUS_BITS_FOR_ROL(pfEFlags, uResult, 32); 2328 } 2329 } 2330 2331 2332 IEM_DECL_IMPL_DEF(void, iemAImpl_rol_u16,(uint16_t *puDst, uint8_t cShift, uint32_t *pfEFlags)) 2333 { 2334 cShift &= 15; 2335 if (cShift) 2336 { 2337 uint16_t uDst = *puDst; 2338 uint16_t uResult = (uDst << cShift) | (uDst >> (16 - cShift)); 2339 *puDst = uResult; 2340 IEM_EFL_UPDATE_STATUS_BITS_FOR_ROL(pfEFlags, uResult, 16); 2341 } 2342 } 2343 2344 2345 IEM_DECL_IMPL_DEF(void, iemAImpl_rol_u8,(uint8_t *puDst, uint8_t cShift, uint32_t *pfEFlags)) 2346 { 2347 cShift &= 7; 2348 if (cShift) 2349 { 2350 uint8_t uDst = *puDst; 2351 uint8_t uResult = (uDst << cShift) | (uDst >> (8 - cShift)); 2352 *puDst = uResult; 2353 IEM_EFL_UPDATE_STATUS_BITS_FOR_ROL(pfEFlags, uResult, 8); 2354 } 2355 } 2356 2357 # endif /* !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) */ 2358 2359 2360 /* 2361 * ROR 2362 */ 2363 2364 /** 2365 * Updates the status bits (OF and CF) for an ROL instruction. 2366 * 2367 * @returns Status bits. 2368 * @param a_pfEFlags Pointer to the 32-bit EFLAGS value to update. 2369 * @param a_uResult Unsigned result value. 2370 * @param a_cBitsWidth The width of the result (8, 16, 32, 64). 2371 */ 2372 #define IEM_EFL_UPDATE_STATUS_BITS_FOR_ROR(a_pfEFlags, a_uResult, a_cBitsWidth) do { \ 2373 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement \ 2374 it the same way as for 1 bit shifts. */ \ 2375 AssertCompile(X86_EFL_CF_BIT == 0); \ 2376 uint32_t fEflTmp = *(a_pfEFlags); \ 2377 fEflTmp &= ~(X86_EFL_CF | X86_EFL_OF); \ 2378 uint32_t const fCarry = ((a_uResult) >> ((a_cBitsWidth) - 1)) & X86_EFL_CF; \ 2379 fEflTmp |= fCarry; \ 2380 fEflTmp |= (((a_uResult) >> ((a_cBitsWidth) - 2)) ^ fCarry) << X86_EFL_OF_BIT; \ 2381 *(a_pfEFlags) = fEflTmp; \ 2382 } while (0) 2305 2383 2306 2384 IEM_DECL_IMPL_DEF(void, iemAImpl_ror_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags)) … … 2309 2387 if (cShift) 2310 2388 { 2311 uint64_t uDst = *puDst; 2312 uint64_t uResult; 2389 uint64_t const uResult = ASMRotateRightU64(*puDst, cShift); 2390 *puDst = uResult; 2391 IEM_EFL_UPDATE_STATUS_BITS_FOR_ROR(pfEFlags, uResult, 64); 2392 } 2393 } 2394 2395 # if !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) 2396 2397 IEM_DECL_IMPL_DEF(void, iemAImpl_ror_u32,(uint32_t *puDst, uint8_t cShift, uint32_t *pfEFlags)) 2398 { 2399 cShift &= 31; 2400 if (cShift) 2401 { 2402 uint64_t const uResult = ASMRotateRightU32(*puDst, cShift); 2403 *puDst = uResult; 2404 IEM_EFL_UPDATE_STATUS_BITS_FOR_ROR(pfEFlags, uResult, 32); 2405 } 2406 } 2407 2408 2409 IEM_DECL_IMPL_DEF(void, iemAImpl_ror_u16,(uint16_t *puDst, uint8_t cShift, uint32_t *pfEFlags)) 2410 { 2411 cShift &= 15; 2412 if (cShift) 2413 { 2414 uint16_t uDst = *puDst; 2415 uint16_t uResult; 2313 2416 uResult = uDst >> cShift; 2314 uResult |= uDst << ( 64- cShift);2417 uResult |= uDst << (16 - cShift); 2315 2418 *puDst = uResult; 2316 2317 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement 2318 it the same way as for 1 bit shifts (OF = OF XOR New-CF). */ 2319 AssertCompile(X86_EFL_CF_BIT == 0); 2320 uint32_t fEfl = *pfEFlags & ~(X86_EFL_CF | X86_EFL_OF); 2321 uint32_t fCarry = (uResult >> 63) & X86_EFL_CF; 2322 fEfl |= fCarry; 2323 fEfl |= (((uResult >> 62) ^ fCarry) << X86_EFL_OF_BIT) & X86_EFL_OF; 2324 *pfEFlags = fEfl; 2325 } 2326 } 2327 2328 2329 IEM_DECL_IMPL_DEF(void, iemAImpl_rcl_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags)) 2330 { 2331 cShift &= 63; 2419 IEM_EFL_UPDATE_STATUS_BITS_FOR_ROR(pfEFlags, uResult, 16); 2420 } 2421 } 2422 2423 2424 IEM_DECL_IMPL_DEF(void, iemAImpl_ror_u8,(uint8_t *puDst, uint8_t cShift, uint32_t *pfEFlags)) 2425 { 2426 cShift &= 7; 2332 2427 if (cShift) 2333 2428 { 2334 uint32_t fEfl = *pfEFlags; 2335 uint64_t uDst = *puDst; 2336 uint64_t uResult; 2337 uResult = uDst << cShift; 2338 AssertCompile(X86_EFL_CF_BIT == 0); 2339 if (cShift > 1) 2340 uResult |= uDst >> (65 - cShift); 2341 uResult |= (uint64_t)(fEfl & X86_EFL_CF) << (cShift - 1); 2429 uint8_t uDst = *puDst; 2430 uint8_t uResult; 2431 uResult = uDst >> cShift; 2432 uResult |= uDst << (8 - cShift); 2342 2433 *puDst = uResult; 2343 2344 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement 2345 it the same way as for 1 bit shifts. */ 2346 uint32_t fCarry = (uDst >> (64 - cShift)) & X86_EFL_CF; 2347 fEfl &= ~(X86_EFL_CF | X86_EFL_OF); 2348 fEfl |= fCarry; 2349 fEfl |= ((uResult >> 63) ^ fCarry) << X86_EFL_OF_BIT; 2350 *pfEFlags = fEfl; 2351 } 2352 } 2353 2354 2355 IEM_DECL_IMPL_DEF(void, iemAImpl_rcr_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags)) 2356 { 2357 cShift &= 63; 2358 if (cShift) 2359 { 2360 uint32_t fEfl = *pfEFlags; 2361 uint64_t uDst = *puDst; 2362 uint64_t uResult; 2363 uResult = uDst >> cShift; 2364 AssertCompile(X86_EFL_CF_BIT == 0); 2365 if (cShift > 1) 2366 uResult |= uDst << (65 - cShift); 2367 uResult |= (uint64_t)(fEfl & X86_EFL_CF) << (64 - cShift); 2368 *puDst = uResult; 2369 2370 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement 2371 it the same way as for 1 bit shifts. */ 2372 uint32_t fCarry = (uDst >> (cShift - 1)) & X86_EFL_CF; 2373 fEfl &= ~(X86_EFL_CF | X86_EFL_OF); 2374 fEfl |= fCarry; 2375 fEfl |= ((uResult >> 63) ^ fCarry) << X86_EFL_OF_BIT; 2376 *pfEFlags = fEfl; 2377 } 2378 } 2379 2380 2381 IEM_DECL_IMPL_DEF(void, iemAImpl_shl_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags)) 2382 { 2383 cShift &= 63; 2384 if (cShift) 2385 { 2386 uint64_t uDst = *puDst; 2387 uint64_t uResult = uDst << cShift; 2388 *puDst = uResult; 2389 2390 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement 2391 it the same way as for 1 bit shifts. The AF bit is undefined, we 2392 always set it to zero atm. */ 2393 AssertCompile(X86_EFL_CF_BIT == 0); 2394 uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS; 2395 uint32_t fCarry = (uDst >> (64 - cShift)) & X86_EFL_CF; 2396 fEfl |= fCarry; 2397 fEfl |= ((uResult >> 63) ^ fCarry) << X86_EFL_OF_BIT; 2398 fEfl |= X86_EFL_CALC_SF(uResult, 64); 2399 fEfl |= X86_EFL_CALC_ZF(uResult); 2400 fEfl |= g_afParity[uResult & 0xff]; 2401 *pfEFlags = fEfl; 2402 } 2403 } 2404 2405 2406 IEM_DECL_IMPL_DEF(void, iemAImpl_shr_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags)) 2407 { 2408 cShift &= 63; 2409 if (cShift) 2410 { 2411 uint64_t uDst = *puDst; 2412 uint64_t uResult = uDst >> cShift; 2413 *puDst = uResult; 2414 2415 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement 2416 it the same way as for 1 bit shifts. The AF bit is undefined, we 2417 always set it to zero atm. */ 2418 AssertCompile(X86_EFL_CF_BIT == 0); 2419 uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS; 2420 fEfl |= (uDst >> (cShift - 1)) & X86_EFL_CF; 2421 fEfl |= (uDst >> 63) << X86_EFL_OF_BIT; 2422 fEfl |= X86_EFL_CALC_SF(uResult, 64); 2423 fEfl |= X86_EFL_CALC_ZF(uResult); 2424 fEfl |= g_afParity[uResult & 0xff]; 2425 *pfEFlags = fEfl; 2426 } 2427 } 2428 2429 2430 IEM_DECL_IMPL_DEF(void, iemAImpl_sar_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags)) 2431 { 2432 cShift &= 63; 2433 if (cShift) 2434 { 2435 uint64_t uDst = *puDst; 2436 uint64_t uResult = (int64_t)uDst >> cShift; 2437 *puDst = uResult; 2438 2439 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement 2440 it the same way as for 1 bit shifts (0). The AF bit is undefined, 2441 we always set it to zero atm. */ 2442 AssertCompile(X86_EFL_CF_BIT == 0); 2443 uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS; 2444 fEfl |= (uDst >> (cShift - 1)) & X86_EFL_CF; 2445 fEfl |= X86_EFL_CALC_SF(uResult, 64); 2446 fEfl |= X86_EFL_CALC_ZF(uResult); 2447 fEfl |= g_afParity[uResult & 0xff]; 2448 *pfEFlags = fEfl; 2449 } 2450 } 2451 2452 2453 IEM_DECL_IMPL_DEF(void, iemAImpl_shld_u64,(uint64_t *puDst, uint64_t uSrc, uint8_t cShift, uint32_t *pfEFlags)) 2454 { 2455 cShift &= 63; 2456 if (cShift) 2457 { 2458 uint64_t uDst = *puDst; 2459 uint64_t uResult; 2460 uResult = uDst << cShift; 2461 uResult |= uSrc >> (64 - cShift); 2462 *puDst = uResult; 2463 2464 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement 2465 it the same way as for 1 bit shifts. The AF bit is undefined, 2466 we always set it to zero atm. */ 2467 AssertCompile(X86_EFL_CF_BIT == 0); 2468 uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS; 2469 fEfl |= (uDst >> (64 - cShift)) & X86_EFL_CF; 2470 fEfl |= (uint32_t)((uDst >> 63) ^ (uint32_t)(uResult >> 63)) << X86_EFL_OF_BIT; 2471 fEfl |= X86_EFL_CALC_SF(uResult, 64); 2472 fEfl |= X86_EFL_CALC_ZF(uResult); 2473 fEfl |= g_afParity[uResult & 0xff]; 2474 *pfEFlags = fEfl; 2475 } 2476 } 2477 2478 2479 IEM_DECL_IMPL_DEF(void, iemAImpl_shrd_u64,(uint64_t *puDst, uint64_t uSrc, uint8_t cShift, uint32_t *pfEFlags)) 2480 { 2481 cShift &= 63; 2482 if (cShift) 2483 { 2484 uint64_t uDst = *puDst; 2485 uint64_t uResult; 2486 uResult = uDst >> cShift; 2487 uResult |= uSrc << (64 - cShift); 2488 *puDst = uResult; 2489 2490 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement 2491 it the same way as for 1 bit shifts. The AF bit is undefined, 2492 we always set it to zero atm. */ 2493 AssertCompile(X86_EFL_CF_BIT == 0); 2494 uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS; 2495 fEfl |= (uDst >> (cShift - 1)) & X86_EFL_CF; 2496 fEfl |= (uint32_t)((uDst >> 63) ^ (uint32_t)(uResult >> 63)) << X86_EFL_OF_BIT; 2497 fEfl |= X86_EFL_CALC_SF(uResult, 64); 2498 fEfl |= X86_EFL_CALC_ZF(uResult); 2499 fEfl |= g_afParity[uResult & 0xff]; 2500 *pfEFlags = fEfl; 2501 } 2502 } 2434 IEM_EFL_UPDATE_STATUS_BITS_FOR_ROR(pfEFlags, uResult, 8); 2435 } 2436 } 2437 2438 # endif /* !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) */ 2439 2440 2441 /* 2442 * RCL 2443 */ 2444 #define EMIT_RCL(a_cBitsWidth) \ 2445 IEM_DECL_IMPL_DEF(void, iemAImpl_rcl_u ## a_cBitsWidth,(uint ## a_cBitsWidth ## _t *puDst, uint8_t cShift, uint32_t *pfEFlags)) \ 2446 { \ 2447 cShift &= a_cBitsWidth - 1; \ 2448 if (cShift) \ 2449 { \ 2450 uint ## a_cBitsWidth ## _t const uDst = *puDst; \ 2451 uint ## a_cBitsWidth ## _t uResult = uDst << cShift; \ 2452 if (cShift > 1) \ 2453 uResult |= uDst >> (a_cBitsWidth + 1 - cShift); \ 2454 \ 2455 uint32_t fEfl = *pfEFlags; \ 2456 AssertCompile(X86_EFL_CF_BIT == 0); \ 2457 uResult |= (uint ## a_cBitsWidth ## _t)(fEfl & X86_EFL_CF) << (cShift - 1); \ 2458 \ 2459 *puDst = uResult; \ 2460 \ 2461 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement \ 2462 it the same way as for 1 bit shifts. */ \ 2463 fEfl &= ~(X86_EFL_CF | X86_EFL_OF); \ 2464 uint32_t const fCarry = (uDst >> (a_cBitsWidth - cShift)) & X86_EFL_CF; \ 2465 fEfl |= fCarry; \ 2466 fEfl |= ((uResult >> (a_cBitsWidth - 1)) ^ fCarry) << X86_EFL_OF_BIT; \ 2467 *pfEFlags = fEfl; \ 2468 } \ 2469 } 2470 EMIT_RCL(64); 2471 # if !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) 2472 EMIT_RCL(32); 2473 EMIT_RCL(16); 2474 EMIT_RCL(8); 2475 # endif 2476 2477 2478 /* 2479 * RCR 2480 */ 2481 #define EMIT_RCR(a_cBitsWidth) \ 2482 IEM_DECL_IMPL_DEF(void, iemAImpl_rcr_u ## a_cBitsWidth,(uint ## a_cBitsWidth ##_t *puDst, uint8_t cShift, uint32_t *pfEFlags)) \ 2483 { \ 2484 cShift &= a_cBitsWidth - 1; \ 2485 if (cShift) \ 2486 { \ 2487 uint ## a_cBitsWidth ## _t const uDst = *puDst; \ 2488 uint ## a_cBitsWidth ## _t uResult = uDst >> cShift; \ 2489 if (cShift > 1) \ 2490 uResult |= uDst << (a_cBitsWidth + 1 - cShift); \ 2491 \ 2492 AssertCompile(X86_EFL_CF_BIT == 0); \ 2493 uint32_t fEfl = *pfEFlags; \ 2494 uResult |= (uint ## a_cBitsWidth ## _t)(fEfl & X86_EFL_CF) << (a_cBitsWidth - cShift); \ 2495 *puDst = uResult; \ 2496 \ 2497 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement \ 2498 it the same way as for 1 bit shifts. */ \ 2499 fEfl &= ~(X86_EFL_CF | X86_EFL_OF); \ 2500 uint32_t const fCarry = (uDst >> (cShift - 1)) & X86_EFL_CF; \ 2501 fEfl |= fCarry; \ 2502 fEfl |= ((uResult >> (a_cBitsWidth - 1)) ^ fCarry) << X86_EFL_OF_BIT; \ 2503 *pfEFlags = fEfl; \ 2504 } \ 2505 } 2506 EMIT_RCR(64); 2507 # if !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) 2508 EMIT_RCR(32); 2509 EMIT_RCR(16); 2510 EMIT_RCR(8); 2511 # endif 2512 2513 2514 /* 2515 * SHL 2516 */ 2517 #define EMIT_SHL(a_cBitsWidth) \ 2518 IEM_DECL_IMPL_DEF(void, iemAImpl_shl_u ## a_cBitsWidth,(uint ## a_cBitsWidth ## _t *puDst, uint8_t cShift, uint32_t *pfEFlags)) \ 2519 { \ 2520 cShift &= a_cBitsWidth - 1; \ 2521 if (cShift) \ 2522 { \ 2523 uint ## a_cBitsWidth ##_t const uDst = *puDst; \ 2524 uint ## a_cBitsWidth ##_t uResult = uDst << cShift; \ 2525 *puDst = uResult; \ 2526 \ 2527 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement \ 2528 it the same way as for 1 bit shifts. The AF bit is undefined, we \ 2529 always set it to zero atm. */ \ 2530 AssertCompile(X86_EFL_CF_BIT == 0); \ 2531 uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS; \ 2532 uint32_t fCarry = (uDst >> (a_cBitsWidth - cShift)) & X86_EFL_CF; \ 2533 fEfl |= fCarry; \ 2534 fEfl |= ((uResult >> (a_cBitsWidth - 1)) ^ fCarry) << X86_EFL_OF_BIT; \ 2535 fEfl |= X86_EFL_CALC_SF(uResult, a_cBitsWidth); \ 2536 fEfl |= X86_EFL_CALC_ZF(uResult); \ 2537 fEfl |= g_afParity[uResult & 0xff]; \ 2538 *pfEFlags = fEfl; \ 2539 } \ 2540 } 2541 EMIT_SHL(64) 2542 # if !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) 2543 EMIT_SHL(32) 2544 EMIT_SHL(16) 2545 EMIT_SHL(8) 2546 # endif 2547 2548 2549 /* 2550 * SHR 2551 */ 2552 #define EMIT_SHR(a_cBitsWidth) \ 2553 IEM_DECL_IMPL_DEF(void, iemAImpl_shr_u ## a_cBitsWidth,(uint ## a_cBitsWidth ## _t *puDst, uint8_t cShift, uint32_t *pfEFlags)) \ 2554 { \ 2555 cShift &= a_cBitsWidth - 1; \ 2556 if (cShift) \ 2557 { \ 2558 uint ## a_cBitsWidth ## _t const uDst = *puDst; \ 2559 uint ## a_cBitsWidth ## _t uResult = uDst >> cShift; \ 2560 *puDst = uResult; \ 2561 \ 2562 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement \ 2563 it the same way as for 1 bit shifts. The AF bit is undefined, we \ 2564 always set it to zero atm. */ \ 2565 AssertCompile(X86_EFL_CF_BIT == 0); \ 2566 uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS; \ 2567 fEfl |= (uDst >> (cShift - 1)) & X86_EFL_CF; \ 2568 fEfl |= (uDst >> (a_cBitsWidth - 1)) << X86_EFL_OF_BIT; \ 2569 fEfl |= X86_EFL_CALC_SF(uResult, a_cBitsWidth); \ 2570 fEfl |= X86_EFL_CALC_ZF(uResult); \ 2571 fEfl |= g_afParity[uResult & 0xff]; \ 2572 *pfEFlags = fEfl; \ 2573 } \ 2574 } 2575 EMIT_SHR(64) 2576 # if !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) 2577 EMIT_SHR(32) 2578 EMIT_SHR(16) 2579 EMIT_SHR(8) 2580 # endif 2581 2582 2583 /* 2584 * SAR 2585 */ 2586 #define EMIT_SAR(a_cBitsWidth) \ 2587 IEM_DECL_IMPL_DEF(void, iemAImpl_sar_u ## a_cBitsWidth,(uint ## a_cBitsWidth ## _t *puDst, uint8_t cShift, uint32_t *pfEFlags)) \ 2588 { \ 2589 cShift &= a_cBitsWidth - 1; \ 2590 if (cShift) \ 2591 { \ 2592 uint ## a_cBitsWidth ## _t const uDst = *puDst; \ 2593 uint ## a_cBitsWidth ## _t uResult = (int ## a_cBitsWidth ## _t)uDst >> cShift; \ 2594 *puDst = uResult; \ 2595 \ 2596 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement \ 2597 it the same way as for 1 bit shifts (0). The AF bit is undefined, \ 2598 we always set it to zero atm. */ \ 2599 AssertCompile(X86_EFL_CF_BIT == 0); \ 2600 uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS; \ 2601 fEfl |= (uDst >> (cShift - 1)) & X86_EFL_CF; \ 2602 fEfl |= X86_EFL_CALC_SF(uResult, a_cBitsWidth); \ 2603 fEfl |= X86_EFL_CALC_ZF(uResult); \ 2604 fEfl |= g_afParity[uResult & 0xff]; \ 2605 *pfEFlags = fEfl; \ 2606 } \ 2607 } 2608 EMIT_SAR(64) 2609 # if !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) 2610 EMIT_SAR(32) 2611 EMIT_SAR(16) 2612 EMIT_SAR(8) 2613 # endif 2614 2615 2616 /* 2617 * SHLD 2618 */ 2619 #define EMIT_SHLD(a_cBitsWidth) \ 2620 IEM_DECL_IMPL_DEF(void, iemAImpl_shld_u ## a_cBitsWidth,(uint ## a_cBitsWidth ## _t *puDst, \ 2621 uint ## a_cBitsWidth ## _t uSrc, uint8_t cShift, uint32_t *pfEFlags)) \ 2622 { \ 2623 cShift &= a_cBitsWidth - 1; \ 2624 if (cShift) \ 2625 { \ 2626 uint ## a_cBitsWidth ## _t const uDst = *puDst; \ 2627 uint ## a_cBitsWidth ## _t uResult = uDst << cShift; \ 2628 uResult |= uSrc >> (a_cBitsWidth - cShift); \ 2629 *puDst = uResult; \ 2630 \ 2631 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement \ 2632 it the same way as for 1 bit shifts. The AF bit is undefined, \ 2633 we always set it to zero atm. */ \ 2634 AssertCompile(X86_EFL_CF_BIT == 0); \ 2635 uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS; \ 2636 fEfl |= (uDst >> (a_cBitsWidth - cShift)) & X86_EFL_CF; \ 2637 fEfl |= (uint32_t)((uDst >> (a_cBitsWidth - 1)) ^ (uint32_t)(uResult >> (a_cBitsWidth - 1))) << X86_EFL_OF_BIT; \ 2638 fEfl |= X86_EFL_CALC_SF(uResult, a_cBitsWidth); \ 2639 fEfl |= X86_EFL_CALC_ZF(uResult); \ 2640 fEfl |= g_afParity[uResult & 0xff]; \ 2641 *pfEFlags = fEfl; \ 2642 } \ 2643 } 2644 EMIT_SHLD(64) 2645 # if !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) 2646 EMIT_SHLD(32) 2647 EMIT_SHLD(16) 2648 EMIT_SHLD(8) 2649 # endif 2650 2651 2652 /* 2653 * SHRD 2654 */ 2655 #define EMIT_SHRD(a_cBitsWidth) \ 2656 IEM_DECL_IMPL_DEF(void, iemAImpl_shrd_u ## a_cBitsWidth,(uint ## a_cBitsWidth ## _t *puDst, \ 2657 uint ## a_cBitsWidth ## _t uSrc, uint8_t cShift, uint32_t *pfEFlags)) \ 2658 { \ 2659 cShift &= a_cBitsWidth - 1; \ 2660 if (cShift) \ 2661 { \ 2662 uint ## a_cBitsWidth ## _t const uDst = *puDst; \ 2663 uint ## a_cBitsWidth ## _t uResult = uDst >> cShift; \ 2664 uResult |= uSrc << (a_cBitsWidth - cShift); \ 2665 *puDst = uResult; \ 2666 \ 2667 /* Calc EFLAGS. The OF bit is undefined if cShift > 1, we implement \ 2668 it the same way as for 1 bit shifts. The AF bit is undefined, \ 2669 we always set it to zero atm. */ \ 2670 AssertCompile(X86_EFL_CF_BIT == 0); \ 2671 uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS; \ 2672 fEfl |= (uDst >> (cShift - 1)) & X86_EFL_CF; \ 2673 fEfl |= (uint32_t)((uDst >> (a_cBitsWidth - 1)) ^ (uint32_t)(uResult >> (a_cBitsWidth - 1))) << X86_EFL_OF_BIT; \ 2674 fEfl |= X86_EFL_CALC_SF(uResult, a_cBitsWidth); \ 2675 fEfl |= X86_EFL_CALC_ZF(uResult); \ 2676 fEfl |= g_afParity[uResult & 0xff]; \ 2677 *pfEFlags = fEfl; \ 2678 } \ 2679 } 2680 EMIT_SHRD(64) 2681 # if !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) 2682 EMIT_SHRD(32) 2683 EMIT_SHRD(16) 2684 EMIT_SHRD(8) 2685 # endif 2503 2686 2504 2687
Note:
See TracChangeset
for help on using the changeset viewer.