Changeset 94162 in vbox for trunk/src/VBox/VMM/VMMAll
- Timestamp:
- Mar 10, 2022 10:29:05 PM (3 years ago)
- Location:
- trunk/src/VBox/VMM/VMMAll
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r94156 r94162 1135 1135 1136 1136 1137 /** Function table for the SHLD instruction */1137 /** Function table for the SHLD instruction. */ 1138 1138 IEM_STATIC const IEMOPSHIFTDBLSIZES g_iemAImpl_shld = 1139 1139 { … … 1143 1143 }; 1144 1144 1145 /** Function table for the SHRD instruction */ 1145 /** Function table for the SHLD instruction, AMD EFLAGS variation. */ 1146 IEM_STATIC const IEMOPSHIFTDBLSIZES g_iemAImpl_shld_amd = 1147 { 1148 iemAImpl_shld_u16_amd, 1149 iemAImpl_shld_u32_amd, 1150 iemAImpl_shld_u64_amd 1151 }; 1152 1153 /** Function table for the SHLD instruction, Intel EFLAGS variation. */ 1154 IEM_STATIC const IEMOPSHIFTDBLSIZES g_iemAImpl_shld_intel = 1155 { 1156 iemAImpl_shld_u16_intel, 1157 iemAImpl_shld_u32_intel, 1158 iemAImpl_shld_u64_intel 1159 }; 1160 1161 /** EFLAGS variation selection table for the SHLD instruction. */ 1162 IEM_STATIC const IEMOPSHIFTDBLSIZES * const g_iemAImpl_shld_eflags[] = 1163 { 1164 &g_iemAImpl_shld, 1165 &g_iemAImpl_shld_intel, 1166 &g_iemAImpl_shld_amd, 1167 &g_iemAImpl_shld 1168 }; 1169 1170 /** Function table for the SHRD instruction. */ 1146 1171 IEM_STATIC const IEMOPSHIFTDBLSIZES g_iemAImpl_shrd = 1147 1172 { 1148 1173 iemAImpl_shrd_u16, 1149 1174 iemAImpl_shrd_u32, 1150 iemAImpl_shrd_u64, 1175 iemAImpl_shrd_u64 1176 }; 1177 1178 /** Function table for the SHRD instruction, AMD EFLAGS variation. */ 1179 IEM_STATIC const IEMOPSHIFTDBLSIZES g_iemAImpl_shrd_amd = 1180 { 1181 iemAImpl_shrd_u16_amd, 1182 iemAImpl_shrd_u32_amd, 1183 iemAImpl_shrd_u64_amd 1184 }; 1185 1186 /** Function table for the SHRD instruction, Intel EFLAGS variation. */ 1187 IEM_STATIC const IEMOPSHIFTDBLSIZES g_iemAImpl_shrd_intel = 1188 { 1189 iemAImpl_shrd_u16_intel, 1190 iemAImpl_shrd_u32_intel, 1191 iemAImpl_shrd_u64_intel 1192 }; 1193 1194 /** EFLAGS variation selection table for the SHRD instruction. */ 1195 IEM_STATIC const IEMOPSHIFTDBLSIZES * const g_iemAImpl_shrd_eflags[] = 1196 { 1197 &g_iemAImpl_shrd, 1198 &g_iemAImpl_shrd_intel, 1199 &g_iemAImpl_shrd_amd, 1200 &g_iemAImpl_shrd 1151 1201 }; 1152 1202 -
trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm
r94156 r94162 1413 1413 %macro IEMIMPL_SHIFT_DBL_OP 3 1414 1414 BEGINCODE 1415 BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16_intel, 16 1416 BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16_amd, 16 1415 1417 BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u16, 16 1416 1418 PROLOGUE_4_ARGS … … 1428 1430 ENDPROC iemAImpl_ %+ %1 %+ _u16 1429 1431 1432 BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32_intel, 16 1433 BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32_amd, 16 1430 1434 BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u32, 16 1431 1435 PROLOGUE_4_ARGS … … 1444 1448 1445 1449 %ifdef RT_ARCH_AMD64 1450 BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_intel, 20 1451 BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64_amd, 20 1446 1452 BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _u64, 20 1447 1453 PROLOGUE_4_ARGS -
trunk/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp
r94156 r94162 2678 2678 /* 2679 2679 * SHLD 2680 * 2681 * - CF is the last bit shifted out of puDst. 2682 * - AF is always cleared by Intel 10980XE. 2683 * - AF is always set by AMD 3990X. 2684 * - OF is set according to the first shift on Intel 10980XE, it seems. 2685 * - OF is set according to the last sub-shift on AMD 3990X. 2686 * - ZF, SF and PF are calculated according to the result by both vendors. 2680 2687 */ 2681 2688 #define EMIT_SHLD(a_cBitsWidth) \ … … 2683 2690 uint ## a_cBitsWidth ## _t uSrc, uint8_t cShift, uint32_t *pfEFlags)) \ 2684 2691 { \ 2692 /** @todo this ain't right for 16-bit. Apparently it should use 0x1f instead \ 2693 * of 0xf for masking and use uSrc in repetitive fashion... */ \ 2685 2694 cShift &= a_cBitsWidth - 1; \ 2686 2695 if (cShift) \ 2687 2696 { \ 2688 uint ## a_cBitsWidth ## _t const uDst = *puDst; \2697 uint ## a_cBitsWidth ## _t const uDst = *puDst; \ 2689 2698 uint ## a_cBitsWidth ## _t uResult = uDst << cShift; \ 2690 2699 uResult |= uSrc >> (a_cBitsWidth - cShift); \ 2691 2700 *puDst = uResult; \ 2692 2701 \ 2693 /* Calc EFLAGS. CF is the last bit shifted out of puDst. The OF flag \2694 indicates a sign change for a single shift, whereas intel documents \2695 setting it to zero for higher shift counts and AMD just says it's \2696 undefined, however AMD x3990 sets it according to the last sub-shift. \2697 On AMD x3990 the AF flag is always set. */ \2698 2702 uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS; \ 2699 if (true /*AMD*/) \ 2700 { \ 2701 fEfl |= X86_EFL_GET_OF_ ## a_cBitsWidth((uDst << (cShift - 1)) ^ uResult); /* Set according to last shift. */ \ 2702 fEfl |= X86_EFL_AF; \ 2703 } \ 2704 else \ 2705 { \ 2706 if (cShift == 1) \ 2707 fEfl |= X86_EFL_GET_OF_ ## a_cBitsWidth((uDst ^ uResult)); \ 2708 fEfl |= X86_EFL_AF; /* ? */ \ 2709 } \ 2703 AssertCompile(X86_EFL_CF_BIT == 0); \ 2704 fEfl |= X86_EFL_GET_OF_ ## a_cBitsWidth(uDst ^ (uDst << 1)); /* Set according to the first shift. */ \ 2705 fEfl |= (uDst >> (a_cBitsWidth - cShift)) & X86_EFL_CF; /* CF = last bit shifted out */ \ 2706 fEfl |= g_afParity[uResult & 0xff]; \ 2707 fEfl |= X86_EFL_CALC_SF(uResult, a_cBitsWidth); \ 2708 fEfl |= X86_EFL_CALC_ZF(uResult); \ 2709 *pfEFlags = fEfl; \ 2710 } \ 2711 }\ 2712 \ 2713 IEM_DECL_IMPL_DEF(void, iemAImpl_shld_u ## a_cBitsWidth ## _intel,(uint ## a_cBitsWidth ## _t *puDst, \ 2714 uint ## a_cBitsWidth ## _t uSrc, uint8_t cShift, \ 2715 uint32_t *pfEFlags)) \ 2716 { \ 2717 iemAImpl_shld_u ## a_cBitsWidth(puDst, uSrc, cShift, pfEFlags); \ 2718 } \ 2719 \ 2720 IEM_DECL_IMPL_DEF(void, iemAImpl_shld_u ## a_cBitsWidth ## _amd,(uint ## a_cBitsWidth ## _t *puDst, \ 2721 uint ## a_cBitsWidth ## _t uSrc, uint8_t cShift, \ 2722 uint32_t *pfEFlags)) \ 2723 { \ 2724 cShift &= a_cBitsWidth - 1; \ 2725 if (cShift) \ 2726 { \ 2727 uint ## a_cBitsWidth ## _t const uDst = *puDst; \ 2728 uint ## a_cBitsWidth ## _t uResult = uDst << cShift; \ 2729 uResult |= uSrc >> (a_cBitsWidth - cShift); \ 2730 *puDst = uResult; \ 2731 \ 2732 uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS; \ 2733 fEfl |= X86_EFL_GET_OF_ ## a_cBitsWidth((uDst << (cShift - 1)) ^ uResult); /* Set according to last shift. */ \ 2734 fEfl |= X86_EFL_AF; \ 2710 2735 AssertCompile(X86_EFL_CF_BIT == 0); \ 2711 2736 fEfl |= (uDst >> (a_cBitsWidth - cShift)) & X86_EFL_CF; /* CF = last bit shifted out */ \ … … 2716 2741 } \ 2717 2742 } 2743 2718 2744 EMIT_SHLD(64) 2719 2745 # if !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) … … 2725 2751 /* 2726 2752 * SHRD 2753 * 2754 * EFLAGS behaviour seems to be the same as with SHLD: 2755 * - CF is the last bit shifted out of puDst. 2756 * - AF is always cleared by Intel 10980XE. 2757 * - AF is always set by AMD 3990X. 2758 * - OF is set according to the first shift on Intel 10980XE, it seems. 2759 * - OF is set according to the last sub-shift on AMD 3990X. 2760 * - ZF, SF and PF are calculated according to the result by both vendors. 2727 2761 */ 2728 2762 #define EMIT_SHRD(a_cBitsWidth) \ 2729 2763 IEM_DECL_IMPL_DEF(void, iemAImpl_shrd_u ## a_cBitsWidth,(uint ## a_cBitsWidth ## _t *puDst, \ 2730 2764 uint ## a_cBitsWidth ## _t uSrc, uint8_t cShift, uint32_t *pfEFlags)) \ 2765 { \ 2766 /** @todo this is wrong for 16-bit, where it should be 0x1f not 0xf and \ 2767 * source used twice or something like that. */ \ 2768 cShift &= a_cBitsWidth - 1; \ 2769 if (cShift) \ 2770 { \ 2771 uint ## a_cBitsWidth ## _t const uDst = *puDst; \ 2772 uint ## a_cBitsWidth ## _t uResult = uDst >> cShift; \ 2773 uResult |= uSrc << (a_cBitsWidth - cShift); \ 2774 *puDst = uResult; \ 2775 \ 2776 uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS; \ 2777 fEfl |= X86_EFL_GET_OF_ ## a_cBitsWidth(uDst ^ (uSrc << (a_cBitsWidth - 1))); \ 2778 AssertCompile(X86_EFL_CF_BIT == 0); \ 2779 fEfl |= (uDst >> (cShift - 1)) & X86_EFL_CF; \ 2780 fEfl |= X86_EFL_CALC_SF(uResult, a_cBitsWidth); \ 2781 fEfl |= X86_EFL_CALC_ZF(uResult); \ 2782 fEfl |= g_afParity[uResult & 0xff]; \ 2783 *pfEFlags = fEfl; \ 2784 } \ 2785 } \ 2786 \ 2787 IEM_DECL_IMPL_DEF(void, iemAImpl_shrd_u ## a_cBitsWidth ## _intel,(uint ## a_cBitsWidth ## _t *puDst, \ 2788 uint ## a_cBitsWidth ## _t uSrc, uint8_t cShift, \ 2789 uint32_t *pfEFlags)) \ 2790 { \ 2791 iemAImpl_shrd_u ## a_cBitsWidth(puDst, uSrc, cShift, pfEFlags); \ 2792 } \ 2793 \ 2794 IEM_DECL_IMPL_DEF(void, iemAImpl_shrd_u ## a_cBitsWidth ## _amd,(uint ## a_cBitsWidth ## _t *puDst, \ 2795 uint ## a_cBitsWidth ## _t uSrc, uint8_t cShift, \ 2796 uint32_t *pfEFlags)) \ 2731 2797 { \ 2732 2798 cShift &= a_cBitsWidth - 1; \ … … 2738 2804 *puDst = uResult; \ 2739 2805 \ 2740 /* Calc EFLAGS. CF is the last bit shifted out of puDst. The OF flag \2741 indicates a sign change for a single shift, whereas intel documents \2742 setting it to zero for higher shift counts and AMD just says it's \2743 undefined, however AMD x3990 sets it according to the last sub-shift. \2744 On AMD x3990 the AF flag is always set. */ \2745 2806 uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS; \ 2746 if (true /*AMD*/) \ 2747 { \ 2748 if (cShift > 1) /* Set according to last shift. */ \ 2749 fEfl |= X86_EFL_GET_OF_ ## a_cBitsWidth((uSrc << (a_cBitsWidth - cShift + 1)) ^ uResult); \ 2750 else \ 2751 fEfl |= X86_EFL_GET_OF_ ## a_cBitsWidth(uDst ^ uResult); \ 2752 fEfl |= X86_EFL_AF; \ 2753 } \ 2807 if (cShift > 1) /* Set according to last shift. */ \ 2808 fEfl |= X86_EFL_GET_OF_ ## a_cBitsWidth((uSrc << (a_cBitsWidth - cShift + 1)) ^ uResult); \ 2754 2809 else \ 2755 { \ 2756 if (cShift == 1) \ 2757 fEfl |= X86_EFL_GET_OF_ ## a_cBitsWidth((uDst >> (a_cBitsWidth - 1)) ^ (uint32_t)(uResult >> (a_cBitsWidth - 1))); \ 2758 fEfl |= X86_EFL_AF; /* ? */ \ 2759 } \ 2810 fEfl |= X86_EFL_GET_OF_ ## a_cBitsWidth(uDst ^ uResult); \ 2811 fEfl |= X86_EFL_AF; \ 2760 2812 AssertCompile(X86_EFL_CF_BIT == 0); \ 2761 2813 fEfl |= (uDst >> (cShift - 1)) & X86_EFL_CF; \ -
trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsTwoByte0f.cpp.h
r94156 r94162 6726 6726 IEMOP_MNEMONIC(shld_Ev_Gv_Ib, "shld Ev,Gv,Ib"); 6727 6727 IEMOP_HLP_MIN_386(); 6728 return FNIEMOP_CALL_1(iemOpCommonShldShrd_Ib, &g_iemAImpl_shld);6728 return FNIEMOP_CALL_1(iemOpCommonShldShrd_Ib, IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_shld_eflags)); 6729 6729 } 6730 6730 … … 6735 6735 IEMOP_MNEMONIC(shld_Ev_Gv_CL, "shld Ev,Gv,CL"); 6736 6736 IEMOP_HLP_MIN_386(); 6737 return FNIEMOP_CALL_1(iemOpCommonShldShrd_CL, &g_iemAImpl_shld);6737 return FNIEMOP_CALL_1(iemOpCommonShldShrd_CL, IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_shld_eflags)); 6738 6738 } 6739 6739 … … 6784 6784 IEMOP_MNEMONIC(shrd_Ev_Gv_Ib, "shrd Ev,Gv,Ib"); 6785 6785 IEMOP_HLP_MIN_386(); 6786 return FNIEMOP_CALL_1(iemOpCommonShldShrd_Ib, &g_iemAImpl_shrd);6786 return FNIEMOP_CALL_1(iemOpCommonShldShrd_Ib, IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_shrd_eflags)); 6787 6787 } 6788 6788 … … 6793 6793 IEMOP_MNEMONIC(shrd_Ev_Gv_CL, "shrd Ev,Gv,CL"); 6794 6794 IEMOP_HLP_MIN_386(); 6795 return FNIEMOP_CALL_1(iemOpCommonShldShrd_CL, &g_iemAImpl_shrd);6795 return FNIEMOP_CALL_1(iemOpCommonShldShrd_CL, IEMTARGETCPU_EFL_BEHAVIOR_SELECT(g_iemAImpl_shrd_eflags)); 6796 6796 } 6797 6797
Note:
See TracChangeset
for help on using the changeset viewer.