Changeset 106269 in vbox for trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-instr-4.c32
- Timestamp:
- Oct 10, 2024 4:37:43 AM (7 weeks ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-instr-4.c32
r106268 r106269 2612 2612 uExpectedMxCsr = ((uExpectedMxCsr & ~BS3_MXCSR_FIXED_MASK) | uForceOnMask) & ~uForceOffMask; 2613 2613 2614 /*2615 * The test value tables give us the exceptions expected when run fully2616 * masked. Here we try the instruction under multiple mask schemes: as2617 * requested by the value table; as implied by the stated resulting2618 * exceptions; fully masked; fully unmasked; and possibly some2619 * combinations.2620 *2621 * This is WORK IN PROGRESS code, and unclear whether it will be2622 * completed or will turn out to have been a bad idea. The idea is to2623 * convert the existing instruction test functions one by one to use2624 * this. Tables need updating because (1) some output rows are wrong2625 * for instructions which always raise an exception fgiven the stated2626 * mask; (2) output exceptions may be wrong for instructions which2627 * always raise an early DE exception, but would return a late exception2628 * (PE, OE, UE) if DE were masked; (3) entries which specify any or all2629 * exceptions already on in MXCSR must be modified to only show output2630 * exceptions which will be *newly* raised by the instruction itself.2631 *2632 * Code indentation is being retained the same as the parent Worker12633 * functions for now, to facilitate co-fixing of any other issues found2634 * while this is under development. Indentation will be fixed if/when2635 * this becomes the replacement Worker1.2636 */2637 2614 uExpectedMxCsr_orig = uExpectedMxCsr; 2638 2615 uInitialExceptions = pValues->uMxCsr & X86_MXCSR_XCPT_FLAGS; 2639 2616 uExpectedMask = uExpectedMxCsr_orig & X86_MXCSR_XCPT_MASK; 2640 2617 2641 /* Debug code to help convert the value tables; eventually replace with an assert */ 2642 if (!sfMismatchShown && (uSpecifiedMask != uExpectedMask)) 2643 { 2644 Bs3TestFailedF("UNEXPECTED: specified mask %#RX32 != expected mask %#RX32 [only flagging 1st instance]\n", uExpectedMask, uSpecifiedMask); 2645 sfMismatchShown = true; 2646 } 2618 /* 2619 * The worker no longer insists that uSpecifiedMask == uExpectedMask. While 2620 * this is the usual state of affairs, a particular value entry could give 2621 * different input and output masks to intentionally force extra testing of 2622 * specific mask values. This shouldn't actually provide any benefit since 2623 * random masks will eventually (quickly -- in microseconds) hit all possible 2624 * combinations; but perhaps there is some reason to do it in some cases? 2625 * But in most cases, uSpecifiedMask, uExpectedMask, uImpliedMask, and 2626 * uCombinedMask will be identical; duplicates will be filtered out by the 2627 * uSeenMasks test. 2628 */ 2647 2629 uImpliedMask = (uExpectedMxCsr_orig & X86_MXCSR_XCPT_FLAGS) << X86_MXCSR_XCPT_MASK_SHIFT; 2648 2630 uCombinedMask = uSpecifiedMask | uImpliedMask; … … 2650 2632 uUnmaskedMask = 0; 2651 2633 2652 for (iMaskType = 0; iMaskType <= 6; iMaskType++) 2653 { 2654 if (BS3_SKIPIT(0, 0, 0, pTestCtx->iVal, iMaskType)) 2655 continue; 2656 2657 switch (iMaskType) 2658 { 2659 case 0: 2660 uThisMask = uSpecifiedMask; 2661 break; 2662 case 1: 2663 uThisMask = uExpectedMask; 2664 break; 2665 case 2: 2666 uThisMask = uImpliedMask; 2667 break; 2668 case 3: 2669 uThisMask = uCombinedMask; 2670 break; 2671 case 4: 2672 uThisMask = uMaskedMask; 2673 break; 2674 case 5: 2675 uThisMask = uUnmaskedMask; 2676 break; 2677 case 6: 2678 /* This case must be last, as it trashes uSeenMasks & uInitialExceptions */ 2679 uRandTmp = bs3CpuInstrX_SimpleRand(); 2680 switch (uRandTmp & X86_MXCSR_RC_MASK) 2634 /* 2635 * The test value tables give us the exceptions expected when run fully 2636 * masked. Here we try the instruction under multiple mask schemes: 2637 * as requested by the value table; as implied by the stated resulting 2638 * exceptions; fully masked; fully unmasked; with a random mask; with 2639 * random exceptions already turned on; both random mask & exceptions. 2640 */ 2641 for (iMaskType = 0; iMaskType <= RT_ELEMENTS(s_apszMaskType); iMaskType++) 2642 { 2643 if (BS3_SKIPIT(0, 0, 0, pTestCtx->iVal, iMaskType)) 2644 continue; 2645 2646 switch (iMaskType) 2647 { 2648 case 0: 2649 uThisMask = uSpecifiedMask; 2650 break; 2651 case 1: 2652 uThisMask = uExpectedMask; 2653 break; 2654 case 2: 2655 uThisMask = uImpliedMask; 2656 break; 2657 case 3: 2658 uThisMask = uCombinedMask; 2659 break; 2660 case 4: 2661 uThisMask = uMaskedMask; 2662 break; 2663 case 5: 2664 uThisMask = uUnmaskedMask; 2665 break; 2666 case 6: 2667 /* This case must be last, as it trashes uSeenMasks & uInitialExceptions */ 2668 /* Also confirm 1:1 cases implemented :: mask type descriptions */ 2669 BS3_ASSERT(iMaskType == RT_ELEMENTS(s_apszMaskType)); 2670 2671 uRandTmp = bs3CpuInstrX_SimpleRand(); 2672 uThisMask = uRandTmp & X86_MXCSR_XCPT_MASK; 2673 switch (uRandTmp & X86_MXCSR_RC_MASK) 2674 { 2675 case X86_MXCSR_RC_ZERO: 2676 case X86_MXCSR_RC_NEAREST: /* Random mask */ 2677 break; 2678 case X86_MXCSR_RC_UP: /* Random initial exceptions */ 2679 uThisMask = uSpecifiedMask; 2680 RT_FALL_THRU(); 2681 case X86_MXCSR_RC_DOWN: /* Random mask & initial exceptions */ 2682 uSeenMasks = 0; /* Don't skip for same-mask */ 2683 uInitialExceptions = uRandTmp & X86_MXCSR_XCPT_FLAGS; 2684 break; 2685 default: 2686 BS3_ASSERT(0); 2687 } 2688 break; 2689 default: 2690 BS3_ASSERT(0); 2691 } 2692 /* No matter what was chosen, honor FIXED mask bits */ 2693 uThisMask = (uThisMask | uForceOnMask) & ~uForceOffMask; 2694 2695 /* Skip millions of redundant tests imposed by the mask twiddling scheme */ 2696 if (uSeenMasks & (RT_BIT_64(uThisMask >> X86_MXCSR_XCPT_MASK_SHIFT))) continue; 2697 uSeenMasks |= RT_BIT_64(uThisMask >> X86_MXCSR_XCPT_MASK_SHIFT); 2698 2699 /* This is the input MXCSR value we'll be sending */ 2700 uMxCsr = (pValues->uMxCsr & ~(X86_MXCSR_XCPT_MASK | X86_MXCSR_XCPT_FLAGS)) | uThisMask | uInitialExceptions; 2701 2702 /* What exceptions does this test value claim to raise? Only actual raises, not initially-on exceptions */ 2703 uExpectedExceptions = uExpectedMxCsr_orig & X86_MXCSR_XCPT_FLAGS; 2704 uExpectedUnmaskedExceptions = uExpectedExceptions & ~(uThisMask >> X86_MXCSR_XCPT_MASK_SHIFT); 2705 2706 /* This is the output MXCSR value we will expect */ 2707 uExpectedMxCsr = (uExpectedMxCsr_orig & ~(X86_MXCSR_XCPT_MASK)) | uThisMask; 2708 2709 /* If we hit an unmasked early exception, late exceptions won't be raised. */ 2710 if (uExpectedUnmaskedExceptions & (X86_MXCSR_DE | X86_MXCSR_IE | X86_MXCSR_ZE)) 2711 uExpectedMxCsr &= ~(X86_MXCSR_OE | X86_MXCSR_PE | X86_MXCSR_UE); 2712 2713 /* However, all exceptions which are on before the instruction will still be on. */ 2714 uExpectedMxCsr |= uInitialExceptions; 2715 2716 /* A fault is raised only by unmasked exceptions which were caused by the instruction itself. */ 2717 fFpXcptExpected = (uExpectedUnmaskedExceptions != 0); 2718 2719 /* 2720 * Set up the context and some expectations. 2721 */ 2722 /* Destination. */ 2723 Bs3MemZero(&MemOpExpect, sizeof(MemOpExpect)); 2724 if (pTest->iRegDst == UINT8_MAX) 2725 { 2726 BS3_ASSERT(pTest->enmRm >= RM_MEM); 2727 Bs3MemSet(puMemOpAlias, 0xcc, cbMemOp); 2728 if (bXcptExpect == X86_XCPT_DB) 2729 MemOpExpect.ymm = pValues->uDstOut.ymm; 2730 else 2731 Bs3MemSet(&MemOpExpect, 0xcc, sizeof(MemOpExpect)); 2732 } 2733 2734 /* Source #1 (/ destination for SSE). */ 2735 if (pTest->iRegSrc1 == UINT8_MAX) 2736 { 2737 BS3_ASSERT(pTest->enmRm >= RM_MEM); 2738 Bs3MemCpy(puMemOpAlias, &pValues->uSrc1, cbMemOp); 2739 if (pTest->iRegDst == UINT8_MAX) 2740 BS3_ASSERT(fSseInstr); 2741 else 2742 MemOpExpect.ymm = pValues->uSrc1.ymm; 2743 } 2744 else if (fSseInstr) 2745 Bs3ExtCtxSetXmm(pExtCtx, pTest->iRegSrc1, &pValues->uSrc1.ymm.DQWords.dqw0); 2746 else 2747 Bs3ExtCtxSetYmm(pExtCtx, pTest->iRegSrc1, &pValues->uSrc1.ymm, 32); 2748 2749 /* Source #2. */ 2750 if (pTest->iRegSrc2 == UINT8_MAX) 2751 { 2752 BS3_ASSERT(pTest->enmRm >= RM_MEM); 2753 BS3_ASSERT(pTest->iRegDst != UINT8_MAX && pTest->iRegSrc1 != UINT8_MAX); 2754 Bs3MemCpy(puMemOpAlias, &pValues->uSrc2, cbMemOp); 2755 MemOpExpect.ymm = pValues->uSrc2.ymm; 2756 } 2757 else if (fSseInstr) 2758 Bs3ExtCtxSetXmm(pExtCtx, pTest->iRegSrc2, &pValues->uSrc2.ymm.DQWords.dqw0); 2759 else 2760 Bs3ExtCtxSetYmm(pExtCtx, pTest->iRegSrc2, &pValues->uSrc2.ymm, 32); 2761 2762 /* Memory pointer. */ 2763 if (pTest->enmRm >= RM_MEM) 2764 { 2765 BS3_ASSERT( pTest->iRegDst == UINT8_MAX 2766 || pTest->iRegSrc1 == UINT8_MAX 2767 || pTest->iRegSrc2 == UINT8_MAX); 2768 Bs3RegCtxSetGrpSegFromCurPtr(pCtx, &pCtx->rbx, &pCtx->fs, puMemOp); 2769 } 2770 2771 /* Setup MXCSR for the current test. */ 2772 uMxCsr |= (pSavedCfg->uMxCsr & X86_MXCSR_MM); 2773 BS3_ASSERT(!(uMxCsr & X86_MXCSR_MM)); 2774 BS3_ASSERT(!(uMxCsr & X86_MXCSR_DAZ) || g_fMxCsrDazSupported); 2775 Bs3ExtCtxSetMxCsr(pExtCtx, uMxCsr); 2776 2777 /* 2778 * Prepare globals and execute. 2779 */ 2780 g_uBs3TrapEipHint = pCtx->rip.u32; 2781 if ( bXcptExpect == X86_XCPT_DB 2782 && !fFpXcptExpected) 2783 g_uBs3TrapEipHint += cbInstr + 1; 2784 Bs3TrapSetJmpAndRestoreWithExtCtxAndRm(pCtx, pExtCtx, pTrapFrame, pExtCtxOut); 2785 2786 /* 2787 * Check the result. 2788 * 2789 * If a floating-point exception is expected, the destination is not updated by the instruction. 2790 * In the case of SSE instructions, updating the destination here will work because it is the same 2791 * as the source, but for AVX++ it won't because the destination is different and would contain 0s. 2792 */ 2793 cErrors = Bs3TestSubErrorCount(); 2794 if ( bXcptExpect == X86_XCPT_DB 2795 && !fFpXcptExpected 2796 && pTest->iRegDst != UINT8_MAX) 2797 { 2798 if (fSseInstr) 2799 Bs3ExtCtxSetXmm(pExtCtx, pTest->iRegDst, &pValues->uDstOut.ymm.DQWords.dqw0); 2800 else 2801 Bs3ExtCtxSetYmm(pExtCtx, pTest->iRegDst, &pValues->uDstOut.ymm, cbOperand); 2802 } 2803 #if defined(DEBUG_aeichner) /** @todo Necessary kludge on a i7-1068NG7. */ 2804 if ( pExtCtx->enmMethod == BS3EXTCTXMETHOD_XSAVE 2805 && pExtCtx->Ctx.x.Hdr.bmXState == 0x7 2806 && pExtCtxOut->Ctx.x.Hdr.bmXState == 0x3) 2807 pExtCtxOut->Ctx.x.Hdr.bmXState = 0x7; 2808 #endif 2809 2810 if (bXcptExpect == X86_XCPT_DB) 2811 { 2812 if (fFuzzyPE) 2681 2813 { 2682 case X86_MXCSR_RC_ZERO: 2683 case X86_MXCSR_RC_NEAREST: /* Random mask */ 2684 uThisMask = uRandTmp & X86_MXCSR_XCPT_MASK; 2685 break; 2686 case X86_MXCSR_RC_UP: /* Random initial exceptions */ 2687 uThisMask = uSpecifiedMask; 2688 uInitialExceptions = uRandTmp & X86_MXCSR_XCPT_FLAGS; 2689 uSeenMasks = 0; /* Don't skip for same-mask */ 2690 break; 2691 case X86_MXCSR_RC_DOWN: /* Random mask & initial exceptions */ 2692 uThisMask = uRandTmp & X86_MXCSR_XCPT_MASK; 2693 uInitialExceptions = uRandTmp & X86_MXCSR_XCPT_FLAGS; 2694 uSeenMasks = 0; /* Don't skip for same-mask */ 2695 break; 2696 default: 2697 BS3_ASSERT(0); 2814 uint32_t const uGotMxCsr = Bs3ExtCtxGetMxCsr(pExtCtxOut); 2815 uExpectedMxCsr = (uExpectedMxCsr & ~X86_MXCSR_PE) | (uGotMxCsr & X86_MXCSR_PE); 2698 2816 } 2699 break; 2700 default: 2701 BS3_ASSERT(0); 2702 } 2703 /* No matter what was chosen, honor FIXED mask bits */ 2704 uThisMask = (uThisMask | uForceOnMask) & ~uForceOffMask; 2705 2706 /* Skip millions of redundant tests imposed by the mask twiddling scheme */ 2707 if (uSeenMasks & (RT_BIT_64(uThisMask >> X86_MXCSR_XCPT_MASK_SHIFT))) continue; 2708 uSeenMasks |= RT_BIT_64(uThisMask >> X86_MXCSR_XCPT_MASK_SHIFT); 2709 2710 /* This is the input MXCSR value we'll be sending */ 2711 uMxCsr = (pValues->uMxCsr & ~(X86_MXCSR_XCPT_MASK | X86_MXCSR_XCPT_FLAGS)) | uThisMask | uInitialExceptions; 2712 2713 /* What exceptions does this test value claim to raise? Only actual raises, not initially-on exceptions */ 2714 uExpectedExceptions = uExpectedMxCsr_orig & X86_MXCSR_XCPT_FLAGS; 2715 uExpectedUnmaskedExceptions = uExpectedExceptions & ~(uThisMask >> X86_MXCSR_XCPT_MASK_SHIFT); 2716 2717 /* This is the output MXCSR value we will expect */ 2718 uExpectedMxCsr = (uExpectedMxCsr_orig & ~(X86_MXCSR_XCPT_MASK)) | uThisMask; 2719 2720 /* If we hit an unmasked early exception, late exceptions won't be raised. */ 2721 if (uExpectedUnmaskedExceptions & (X86_MXCSR_DE | X86_MXCSR_IE | X86_MXCSR_ZE)) 2722 uExpectedMxCsr &= ~(X86_MXCSR_OE | X86_MXCSR_PE | X86_MXCSR_UE); 2723 2724 /* However, all exceptions which are on before the instruction will still be on. */ 2725 uExpectedMxCsr |= uInitialExceptions; 2726 2727 /* A fault is raised only by unmasked exceptions which were caused by the instruction itself. */ 2728 fFpXcptExpected = (uExpectedUnmaskedExceptions != 0); 2729 2730 /* 2731 * Set up the context and some expectations. 2732 */ 2733 /* Destination. */ 2734 Bs3MemZero(&MemOpExpect, sizeof(MemOpExpect)); 2735 if (pTest->iRegDst == UINT8_MAX) 2736 { 2737 BS3_ASSERT(pTest->enmRm >= RM_MEM); 2738 Bs3MemSet(puMemOpAlias, 0xcc, cbMemOp); 2817 Bs3ExtCtxSetMxCsr(pExtCtx, uExpectedMxCsr | (pSavedCfg->uMxCsr & X86_MXCSR_MM)); 2818 } 2819 2820 Bs3TestCheckExtCtx(pExtCtxOut, pExtCtx, 0 /*fFlags*/, pTestCtx->pszMode, pTestCtx->idTestStep); 2821 2739 2822 if (bXcptExpect == X86_XCPT_DB) 2740 MemOpExpect.ymm = pValues->uDstOut.ymm;2741 else2742 Bs3MemSet(&MemOpExpect, 0xcc, sizeof(MemOpExpect));2743 }2744 2745 /* Source #1 (/ destination for SSE). */2746 if (pTest->iRegSrc1 == UINT8_MAX)2747 {2748 BS3_ASSERT(pTest->enmRm >= RM_MEM);2749 Bs3MemCpy(puMemOpAlias, &pValues->uSrc1, cbMemOp);2750 if (pTest->iRegDst == UINT8_MAX)2751 BS3_ASSERT(fSseInstr);2752 else2753 MemOpExpect.ymm = pValues->uSrc1.ymm;2754 }2755 else if (fSseInstr)2756 Bs3ExtCtxSetXmm(pExtCtx, pTest->iRegSrc1, &pValues->uSrc1.ymm.DQWords.dqw0);2757 else2758 Bs3ExtCtxSetYmm(pExtCtx, pTest->iRegSrc1, &pValues->uSrc1.ymm, 32);2759 2760 /* Source #2. */2761 if (pTest->iRegSrc2 == UINT8_MAX)2762 {2763 BS3_ASSERT(pTest->enmRm >= RM_MEM);2764 BS3_ASSERT(pTest->iRegDst != UINT8_MAX && pTest->iRegSrc1 != UINT8_MAX);2765 Bs3MemCpy(puMemOpAlias, &pValues->uSrc2, cbMemOp);2766 MemOpExpect.ymm = pValues->uSrc2.ymm;2767 }2768 else if (fSseInstr)2769 Bs3ExtCtxSetXmm(pExtCtx, pTest->iRegSrc2, &pValues->uSrc2.ymm.DQWords.dqw0);2770 else2771 Bs3ExtCtxSetYmm(pExtCtx, pTest->iRegSrc2, &pValues->uSrc2.ymm, 32);2772 2773 /* Memory pointer. */2774 if (pTest->enmRm >= RM_MEM)2775 {2776 BS3_ASSERT( pTest->iRegDst == UINT8_MAX2777 || pTest->iRegSrc1 == UINT8_MAX2778 || pTest->iRegSrc2 == UINT8_MAX);2779 Bs3RegCtxSetGrpSegFromCurPtr(pCtx, &pCtx->rbx, &pCtx->fs, puMemOp);2780 }2781 2782 /* Setup MXCSR for the current test. */2783 uMxCsr |= (pSavedCfg->uMxCsr & X86_MXCSR_MM);2784 BS3_ASSERT(!(uMxCsr & X86_MXCSR_MM));2785 BS3_ASSERT(!(uMxCsr & X86_MXCSR_DAZ) || g_fMxCsrDazSupported);2786 Bs3ExtCtxSetMxCsr(pExtCtx, uMxCsr);2787 2788 /*2789 * Prepare globals and execute.2790 */2791 g_uBs3TrapEipHint = pCtx->rip.u32;2792 if ( bXcptExpect == X86_XCPT_DB2793 && !fFpXcptExpected)2794 g_uBs3TrapEipHint += cbInstr + 1;2795 Bs3TrapSetJmpAndRestoreWithExtCtxAndRm(pCtx, pExtCtx, pTrapFrame, pExtCtxOut);2796 2797 /*2798 * Check the result.2799 *2800 * If a floating-point exception is expected, the destination is not updated by the instruction.2801 * In the case of SSE instructions, updating the destination here will work because it is the same2802 * as the source, but for AVX++ it won't because the destination is different and would contain 0s.2803 */2804 cErrors = Bs3TestSubErrorCount();2805 if ( bXcptExpect == X86_XCPT_DB2806 && !fFpXcptExpected2807 && pTest->iRegDst != UINT8_MAX)2808 {2809 if (fSseInstr)2810 Bs3ExtCtxSetXmm(pExtCtx, pTest->iRegDst, &pValues->uDstOut.ymm.DQWords.dqw0);2811 else2812 Bs3ExtCtxSetYmm(pExtCtx, pTest->iRegDst, &pValues->uDstOut.ymm, cbOperand);2813 }2814 #if defined(DEBUG_aeichner) /** @todo Necessary kludge on a i7-1068NG7. */2815 if ( pExtCtx->enmMethod == BS3EXTCTXMETHOD_XSAVE2816 && pExtCtx->Ctx.x.Hdr.bmXState == 0x72817 && pExtCtxOut->Ctx.x.Hdr.bmXState == 0x3)2818 pExtCtxOut->Ctx.x.Hdr.bmXState = 0x7;2819 #endif2820 2821 if (bXcptExpect == X86_XCPT_DB)2822 {2823 if (fFuzzyPE)2824 2823 { 2825 uint32_t const uGotMxCsr = Bs3ExtCtxGetMxCsr(pExtCtxOut); 2826 uExpectedMxCsr = (uExpectedMxCsr & ~X86_MXCSR_PE) | (uGotMxCsr & X86_MXCSR_PE); 2827 } 2828 Bs3ExtCtxSetMxCsr(pExtCtx, uExpectedMxCsr | (pSavedCfg->uMxCsr & X86_MXCSR_MM)); 2829 } 2830 2831 Bs3TestCheckExtCtx(pExtCtxOut, pExtCtx, 0 /*fFlags*/, pTestCtx->pszMode, pTestCtx->idTestStep); 2832 2833 if (bXcptExpect == X86_XCPT_DB) 2834 { 2835 uint32_t const uGotMxCsr = Bs3ExtCtxGetMxCsr(pExtCtxOut) & ~X86_MXCSR_MM; 2836 2837 /* Check if the SIMD FP exception flags and mask (or lack of) are as expected. */ 2838 if (uGotMxCsr != uExpectedMxCsr) 2839 { 2840 char szExpectFlags[FP_XCPT_FLAGS_NAMES_MAXLEN]; 2841 char szExpectMasks[FP_XCPT_MASKS_NAMES_MAXLEN]; 2842 char szExpectOthers[FP_XCPT_OTHERS_NAMES_MAXLEN]; 2843 char szGotFlags[FP_XCPT_FLAGS_NAMES_MAXLEN]; 2844 char szGotMasks[FP_XCPT_MASKS_NAMES_MAXLEN]; 2845 char szGotOthers[FP_XCPT_OTHERS_NAMES_MAXLEN]; 2846 bs3CpuInstr4GetXcptFlags(&szExpectFlags[0], sizeof(szExpectFlags), uExpectedMxCsr); 2847 bs3CpuInstr4GetXcptMasks(&szExpectMasks[0], sizeof(szExpectMasks), uExpectedMxCsr); 2848 bs3CpuInstr4GetXcptOthers(&szExpectOthers[0], sizeof(szExpectOthers), uExpectedMxCsr); 2849 bs3CpuInstr4GetXcptFlags(&szGotFlags[0], sizeof(szGotFlags), uGotMxCsr); 2850 bs3CpuInstr4GetXcptMasks(&szGotMasks[0], sizeof(szGotMasks), uGotMxCsr); 2851 bs3CpuInstr4GetXcptOthers(&szGotOthers[0], sizeof(szGotOthers), uGotMxCsr); 2852 Bs3TestFailedF("Expected MXCSR %#RX32 (%s%s%s ) got MXCSR %#RX32 (%s%s%s )", uExpectedMxCsr, 2853 szExpectFlags, szExpectMasks, szExpectOthers, uGotMxCsr, szGotFlags, szGotMasks, szGotOthers); 2854 } 2855 2856 /* Check if the SIMD FP exception (or lack of) is as expected. */ 2857 if (fFpXcptExpected) 2858 { 2859 if (pTrapFrame->bXcpt == bFpXcpt) 2824 uint32_t const uGotMxCsr = Bs3ExtCtxGetMxCsr(pExtCtxOut) & ~X86_MXCSR_MM; 2825 2826 /* Check if the SIMD FP exception flags and mask (or lack of) are as expected. */ 2827 if (uGotMxCsr != uExpectedMxCsr) 2828 { 2829 char szExpectFlags[FP_XCPT_FLAGS_NAMES_MAXLEN]; 2830 char szExpectMasks[FP_XCPT_MASKS_NAMES_MAXLEN]; 2831 char szExpectOthers[FP_XCPT_OTHERS_NAMES_MAXLEN]; 2832 char szGotFlags[FP_XCPT_FLAGS_NAMES_MAXLEN]; 2833 char szGotMasks[FP_XCPT_MASKS_NAMES_MAXLEN]; 2834 char szGotOthers[FP_XCPT_OTHERS_NAMES_MAXLEN]; 2835 bs3CpuInstr4GetXcptFlags(&szExpectFlags[0], sizeof(szExpectFlags), uExpectedMxCsr); 2836 bs3CpuInstr4GetXcptMasks(&szExpectMasks[0], sizeof(szExpectMasks), uExpectedMxCsr); 2837 bs3CpuInstr4GetXcptOthers(&szExpectOthers[0], sizeof(szExpectOthers), uExpectedMxCsr); 2838 bs3CpuInstr4GetXcptFlags(&szGotFlags[0], sizeof(szGotFlags), uGotMxCsr); 2839 bs3CpuInstr4GetXcptMasks(&szGotMasks[0], sizeof(szGotMasks), uGotMxCsr); 2840 bs3CpuInstr4GetXcptOthers(&szGotOthers[0], sizeof(szGotOthers), uGotMxCsr); 2841 Bs3TestFailedF("Expected MXCSR %#RX32 (%s%s%s ) got MXCSR %#RX32 (%s%s%s )", uExpectedMxCsr, 2842 szExpectFlags, szExpectMasks, szExpectOthers, uGotMxCsr, szGotFlags, szGotMasks, szGotOthers); 2843 } 2844 2845 /* Check if the SIMD FP exception (or lack of) is as expected. */ 2846 if (fFpXcptExpected) 2847 { 2848 if (pTrapFrame->bXcpt == bFpXcpt) 2849 { /* likely */ } 2850 else 2851 Bs3TestFailedF("Expected floating-point xcpt %s, got %s", bs3CpuInstr4XcptName(bFpXcpt), 2852 bs3CpuInstr4XcptName(pTrapFrame->bXcpt)); 2853 } 2854 else if (pTrapFrame->bXcpt == X86_XCPT_DB) 2860 2855 { /* likely */ } 2861 2856 else 2862 Bs3TestFailedF("Expected floating-point xcpt %s, got %s", bs3CpuInstr4XcptName(bFpXcpt), 2863 bs3CpuInstr4XcptName(pTrapFrame->bXcpt)); 2857 Bs3TestFailedF("Expected no xcpt, got %s", bs3CpuInstr4XcptName(pTrapFrame->bXcpt)); 2864 2858 } 2865 else if (pTrapFrame->bXcpt == X86_XCPT_DB) 2866 { /* likely */ } 2867 else 2868 Bs3TestFailedF("Expected no xcpt, got %s", bs3CpuInstr4XcptName(pTrapFrame->bXcpt)); 2859 /* Check if non-FP exception is as expected. */ 2860 else if (pTrapFrame->bXcpt != bXcptExpect) 2861 Bs3TestFailedF("Expected xcpt %s, got %s", bs3CpuInstr4XcptName(bXcptExpect), bs3CpuInstr4XcptName(pTrapFrame->bXcpt)); 2862 2863 /* Kludge! Looks like EFLAGS.AC is cleared when raising #GP in real mode on the 10980XE. WEIRD! */ 2864 if (bMode == BS3_MODE_RM && (pCtx->rflags.u32 & X86_EFL_AC)) 2865 { 2866 if (pTrapFrame->Ctx.rflags.u32 & X86_EFL_AC) 2867 Bs3TestFailedF("Expected EFLAGS.AC to be cleared (bXcpt=%d)", pTrapFrame->bXcpt); 2868 pTrapFrame->Ctx.rflags.u32 |= X86_EFL_AC; 2869 } 2870 if (bXcptExpect == X86_XCPT_PF) 2871 pCtx->cr2.u = (uintptr_t)puMemOp; 2872 Bs3TestCheckRegCtxEx(&pTrapFrame->Ctx, pCtx, bXcptExpect == X86_XCPT_DB && !fFpXcptExpected ? cbInstr + 1 : 0, 0 /*cbSpAdjust*/, 2873 (bXcptExpect == X86_XCPT_DB && !fFpXcptExpected) || BS3_MODE_IS_16BIT_SYS(bMode) ? 0 : X86_EFL_RF, 2874 pTestCtx->pszMode, pTestCtx->idTestStep); 2875 pCtx->cr2.u = 0; 2876 2877 if ( pTest->enmRm >= RM_MEM 2878 && Bs3MemCmp(puMemOpAlias, &MemOpExpect, cbMemOp) != 0) 2879 Bs3TestFailedF("Expected uMemOp %.*Rhxs, got %.*Rhxs", cbMemOp, &MemOpExpect, cbMemOp, puMemOpAlias); 2880 2881 if (cErrors != Bs3TestSubErrorCount()) 2882 Bs3TestFailedF("Mask mode %s, mask=%#RX32, in-exceptions=%#RX32, in-MxCsr=%#RX32, expect-MxCsr=%#RX32", s_apszMaskType[iMaskType], uThisMask, uInitialExceptions, uMxCsr, uExpectedMxCsr); 2869 2883 } 2870 /* Check if non-FP exception is as expected. */2871 else if (pTrapFrame->bXcpt != bXcptExpect)2872 Bs3TestFailedF("Expected xcpt %s, got %s", bs3CpuInstr4XcptName(bXcptExpect), bs3CpuInstr4XcptName(pTrapFrame->bXcpt));2873 2874 /* Kludge! Looks like EFLAGS.AC is cleared when raising #GP in real mode on the 10980XE. WEIRD! */2875 if (bMode == BS3_MODE_RM && (pCtx->rflags.u32 & X86_EFL_AC))2876 {2877 if (pTrapFrame->Ctx.rflags.u32 & X86_EFL_AC)2878 Bs3TestFailedF("Expected EFLAGS.AC to be cleared (bXcpt=%d)", pTrapFrame->bXcpt);2879 pTrapFrame->Ctx.rflags.u32 |= X86_EFL_AC;2880 }2881 if (bXcptExpect == X86_XCPT_PF)2882 pCtx->cr2.u = (uintptr_t)puMemOp;2883 Bs3TestCheckRegCtxEx(&pTrapFrame->Ctx, pCtx, bXcptExpect == X86_XCPT_DB && !fFpXcptExpected ? cbInstr + 1 : 0, 0 /*cbSpAdjust*/,2884 (bXcptExpect == X86_XCPT_DB && !fFpXcptExpected) || BS3_MODE_IS_16BIT_SYS(bMode) ? 0 : X86_EFL_RF,2885 pTestCtx->pszMode, pTestCtx->idTestStep);2886 pCtx->cr2.u = 0;2887 2888 if ( pTest->enmRm >= RM_MEM2889 && Bs3MemCmp(puMemOpAlias, &MemOpExpect, cbMemOp) != 0)2890 Bs3TestFailedF("Expected uMemOp %.*Rhxs, got %.*Rhxs", cbMemOp, &MemOpExpect, cbMemOp, puMemOpAlias);2891 2892 if (cErrors != Bs3TestSubErrorCount())2893 Bs3TestFailedF("Mask mode %s, mask=%#RX32, in-exceptions=%#RX32, in-MxCsr=%#RX32, expect-MxCsr=%#RX32", s_apszMaskType[iMaskType], uThisMask, uInitialExceptions, uMxCsr, uExpectedMxCsr);2894 }2895 2884 2896 2885 return cErrorsInit;
Note:
See TracChangeset
for help on using the changeset viewer.