Changeset 94402 in vbox for trunk/src/VBox/VMM/testcase
- Timestamp:
- Mar 30, 2022 11:06:33 PM (3 years ago)
- Location:
- trunk/src/VBox/VMM/testcase
- Files:
-
- 1 added
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/testcase/tstIEMAImpl.cpp
r94398 r94402 3451 3451 3452 3452 3453 3454 /* 3455 * Other FPU stuff. 3456 */ 3457 3458 typedef struct FPU_BINARY_R80_TEST_T 3459 { 3460 uint16_t fFcw; 3461 uint16_t fFswIn; 3462 uint16_t fFswOut; 3463 RTFLOAT80U InVal1; 3464 RTFLOAT80U InVal2; 3465 RTFLOAT80U OutVal; 3466 } FPU_BINARY_R80_TEST_T; 3467 3468 typedef struct FPU_BINARY_R64_TEST_T 3469 { 3470 uint16_t fFcw; 3471 uint16_t fFswIn; 3472 uint16_t fFswOut; 3473 RTFLOAT80U InVal1; 3474 RTFLOAT64U InVal2; 3475 RTFLOAT80U OutVal; 3476 } FPU_BINARY_R64_TEST_T; 3477 3478 typedef struct FPU_BINARY_R32_TEST_T 3479 { 3480 uint16_t fFcw; 3481 uint16_t fFswIn; 3482 uint16_t fFswOut; 3483 RTFLOAT80U InVal1; 3484 RTFLOAT32U InVal2; 3485 RTFLOAT80U OutVal; 3486 } FPU_BINARY_R32_TEST_T; 3487 3488 typedef struct FPU_BINARY_EFL_R80_TEST_T 3489 { 3490 uint16_t fFcw; 3491 uint16_t fFswIn; 3492 uint16_t fFswOut; 3493 RTFLOAT80U InVal1; 3494 RTFLOAT80U InVal2; 3495 uint32_t fEflOut; 3496 } FPU_BINARY_EFL_R80_TEST_T; 3497 3498 #include "tstIEMAImplDataFpuBinary.h" 3499 3500 3501 /* 3502 * Binary FPU operations on two 80-bit floating point values. 3503 */ 3504 3505 #ifndef HAVE_FPU_BINARY_R80 3506 static FPU_BINARY_R80_TEST_T const g_aTests_fadd_r80_by_r80[] = { {0} }; 3507 static FPU_BINARY_R80_TEST_T const g_aTests_fsub_r80_by_r80[] = { {0} }; 3508 static FPU_BINARY_R80_TEST_T const g_aTests_fsubr_r80_by_r80[] = { {0} }; 3509 static FPU_BINARY_R80_TEST_T const g_aTests_fmul_r80_by_r80[] = { {0} }; 3510 static FPU_BINARY_R80_TEST_T const g_aTests_fdiv_r80_by_r80[] = { {0} }; 3511 static FPU_BINARY_R80_TEST_T const g_aTests_fdivr_r80_by_r80[] = { {0} }; 3512 static FPU_BINARY_R80_TEST_T const g_aTests_fprem_r80_by_r80[] = { {0} }; 3513 static FPU_BINARY_R80_TEST_T const g_aTests_fprem1_r80_by_r80[] = { {0} }; 3514 static FPU_BINARY_R80_TEST_T const g_aTests_fscale_r80_by_r80[] = { {0} }; 3515 static FPU_BINARY_R80_TEST_T const g_aTests_fpatan_r80_by_r80[] = { {0} }; 3516 static FPU_BINARY_R80_TEST_T const g_aTests_fyl2x_r80_by_r80[] = { {0} }; 3517 static FPU_BINARY_R80_TEST_T const g_aTests_fyl2xp1_r80_by_r80[] = { {0} }; 3518 #endif 3519 3520 typedef struct FPU_BINARY_R80_T 3521 { 3522 const char *pszName; 3523 PFNIEMAIMPLFPUR80 pfn, pfnNative; 3524 FPU_BINARY_R80_TEST_T const *paTests; 3525 uint32_t cTests; 3526 uint32_t uExtra; 3527 uint8_t idxCpuEflFlavour; 3528 } FPU_BINARY_R80_T; 3529 3530 static const FPU_BINARY_R80_T g_aFpuBinaryR80[] = 3531 { 3532 ENTRY(fadd_r80_by_r80), 3533 ENTRY(fsub_r80_by_r80), 3534 ENTRY(fsubr_r80_by_r80), 3535 ENTRY(fmul_r80_by_r80), 3536 ENTRY(fdiv_r80_by_r80), 3537 ENTRY(fdivr_r80_by_r80), 3538 ENTRY(fprem_r80_by_r80), 3539 ENTRY(fprem1_r80_by_r80), 3540 ENTRY(fscale_r80_by_r80), 3541 ENTRY(fpatan_r80_by_r80), 3542 ENTRY(fyl2x_r80_by_r80), 3543 ENTRY(fyl2xp1_r80_by_r80), 3544 }; 3545 3546 #ifdef TSTIEMAIMPL_WITH_GENERATOR 3547 static void FpuBinaryR80Generate(PRTSTREAM pOut, uint32_t cTests) 3548 { 3549 static struct { RTFLOAT80U Val1, Val2; } const s_aSpecials[] = 3550 { 3551 { RTFLOAT80U_INIT_C(0, 0xffffeeeeddddcccc, RTFLOAT80U_EXP_BIAS), 3552 RTFLOAT80U_INIT_C(0, 0xffffeeeeddddcccc, RTFLOAT80U_EXP_BIAS) }, /* whatever */ 3553 }; 3554 3555 RTStrmPrintf(pOut, "\n\n#define HAVE_FPU_BINARY_R80\n"); 3556 X86FXSTATE State; 3557 RT_ZERO(State); 3558 uint32_t cMinNormalPairs = cTests / 4; 3559 for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aFpuBinaryR80); iFn++) 3560 { 3561 RTStrmPrintf(pOut, "static const FPU_BINARY_R80_TEST_T g_aTests_%s[] =\n{\n", g_aFpuBinaryR80[iFn].pszName); 3562 uint32_t cNormalInputPairs = 0; 3563 for (uint32_t iTest = 0; iTest < cTests + RT_ELEMENTS(s_aSpecials); iTest += 1) 3564 { 3565 RTFLOAT80U const InVal1 = iTest < cTests ? RandR80Ex() : s_aSpecials[iTest - cTests].Val1; 3566 RTFLOAT80U const InVal2 = iTest < cTests ? RandR80Ex() : s_aSpecials[iTest - cTests].Val2; 3567 if (RTFLOAT80U_IS_NORMAL(&InVal1) && RTFLOAT80U_IS_NORMAL(&InVal2)) 3568 cNormalInputPairs++; 3569 else if (cNormalInputPairs < cMinNormalPairs && iTest + cMinNormalPairs >= cTests && iTest < cTests) 3570 { 3571 iTest -= 1; 3572 continue; 3573 } 3574 3575 uint16_t const fFcw = RandFcw(); 3576 State.FSW = RandFsw(); 3577 3578 for (uint16_t iRounding = 0; iRounding < 4; iRounding++) 3579 { 3580 for (uint16_t iPrecision = 0; iPrecision < 4; iPrecision++) 3581 { 3582 for (uint16_t iMask = 0; iMask <= X86_FCW_MASK_ALL; iMask += X86_FCW_MASK_ALL) 3583 { 3584 State.FCW = (fFcw & ~(X86_FCW_RC_MASK | X86_FCW_PC_MASK | X86_FCW_MASK_ALL)) 3585 | (iRounding << X86_FCW_RC_SHIFT) 3586 | (iPrecision << X86_FCW_PC_SHIFT) 3587 | iMask; 3588 IEMFPURESULT Res = { RTFLOAT80U_INIT(0, 0, 0), 0 }; 3589 g_aFpuBinaryR80[iFn].pfn(&State, &Res, &InVal1, &InVal2); 3590 RTStrmPrintf(pOut, " { %#06x, %#06x, %#06x, %s, %s, %s }, /* #%u/%u/%u/%c */\n", 3591 State.FCW, State.FSW, Res.FSW, GenFormatR80(&InVal1), GenFormatR80(&InVal2), 3592 GenFormatR80(&Res.r80Result), iTest, iRounding, iPrecision, iMask ? 'c' : 'u'); 3593 } 3594 } 3595 } 3596 } 3597 RTStrmPrintf(pOut, "};\n"); 3598 } 3599 } 3600 #endif 3601 3602 3603 static void FpuBinaryR80Test(void) 3604 { 3605 X86FXSTATE State; 3606 RT_ZERO(State); 3607 for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aFpuBinaryR80); iFn++) 3608 { 3609 RTTestSub(g_hTest, g_aFpuBinaryR80[iFn].pszName); 3610 3611 uint32_t const cTests = g_aFpuBinaryR80[iFn].cTests; 3612 FPU_BINARY_R80_TEST_T const * const paTests = g_aFpuBinaryR80[iFn].paTests; 3613 PFNIEMAIMPLFPUR80 pfn = g_aFpuBinaryR80[iFn].pfn; 3614 uint32_t const cVars = 1 + (g_aFpuBinaryR80[iFn].idxCpuEflFlavour == g_idxCpuEflFlavour && g_aFpuBinaryR80[iFn].pfnNative); 3615 for (uint32_t iVar = 0; iVar < cVars; iVar++) 3616 { 3617 for (uint32_t iTest = 0; iTest < cTests; iTest++) 3618 { 3619 RTFLOAT80U const InVal1 = paTests[iTest].InVal1; 3620 RTFLOAT80U const InVal2 = paTests[iTest].InVal2; 3621 IEMFPURESULT Res = { RTFLOAT80U_INIT(0, 0, 0), 0 }; 3622 State.FCW = paTests[iTest].fFcw; 3623 State.FSW = paTests[iTest].fFswIn; 3624 pfn(&State, &Res, &InVal1, &InVal2); 3625 if ( Res.FSW != paTests[iTest].fFswOut 3626 || !RTFLOAT80U_ARE_IDENTICAL(&Res.r80Result, &paTests[iTest].OutVal)) 3627 RTTestFailed(g_hTest, "#%04u%s: fcw=%#06x fsw=%#06x in1=%s in2=%s\n" 3628 "%s -> fsw=%#06x %s\n" 3629 "%s expected %#06x %s%s%s (%s)\n", 3630 iTest, iVar ? "/n" : "", paTests[iTest].fFcw, paTests[iTest].fFswIn, 3631 FormatR80(&paTests[iTest].InVal1), FormatR80(&paTests[iTest].InVal2), 3632 iVar ? " " : "", Res.FSW, FormatR80(&Res.r80Result), 3633 iVar ? " " : "", paTests[iTest].fFswOut, FormatR80(&paTests[iTest].OutVal), 3634 FswDiff(Res.FSW, paTests[iTest].fFswOut), 3635 RTFLOAT80U_ARE_IDENTICAL(&Res.r80Result, &paTests[iTest].OutVal) ? " - val" : "", 3636 FormatFcw(paTests[iTest].fFcw) ); 3637 } 3638 pfn = g_aFpuBinaryR80[iFn].pfnNative; 3639 } 3640 } 3641 } 3642 3643 3644 /* 3645 * Binary FPU operations on one 80-bit floating point value and one 64-bit or 32-bit one. 3646 */ 3647 3648 #ifndef HAVE_FPU_BINARY_R64 3649 static FPU_BINARY_R64_TEST_T const g_aTests_fadd_r80_by_r64[] = { {0} }; 3650 static FPU_BINARY_R64_TEST_T const g_aTests_fmul_r80_by_r64[] = { {0} }; 3651 static FPU_BINARY_R64_TEST_T const g_aTests_fsub_r80_by_r64[] = { {0} }; 3652 static FPU_BINARY_R64_TEST_T const g_aTests_fsubr_r80_by_r64[] = { {0} }; 3653 static FPU_BINARY_R64_TEST_T const g_aTests_fdiv_r80_by_r64[] = { {0} }; 3654 static FPU_BINARY_R64_TEST_T const g_aTests_fdivr_r80_by_r64[] = { {0} }; 3655 #endif 3656 #ifndef HAVE_FPU_BINARY_R32 3657 static FPU_BINARY_R32_TEST_T const g_aTests_fadd_r80_by_r32[] = { {0} }; 3658 static FPU_BINARY_R32_TEST_T const g_aTests_fmul_r80_by_r32[] = { {0} }; 3659 static FPU_BINARY_R32_TEST_T const g_aTests_fsub_r80_by_r32[] = { {0} }; 3660 static FPU_BINARY_R32_TEST_T const g_aTests_fsubr_r80_by_r32[] = { {0} }; 3661 static FPU_BINARY_R32_TEST_T const g_aTests_fdiv_r80_by_r32[] = { {0} }; 3662 static FPU_BINARY_R32_TEST_T const g_aTests_fdivr_r80_by_r32[] = { {0} }; 3663 #endif 3664 3665 #ifdef TSTIEMAIMPL_WITH_GENERATOR 3666 static struct { RTFLOAT80U Val1; RTFLOAT64U Val2; } const s_aFpuBinaryR64Specials[] = 3667 { 3668 { RTFLOAT80U_INIT_C(0, 0xffffeeeeddddcccc, RTFLOAT80U_EXP_BIAS), 3669 RTFLOAT64U_INIT_C(0, 0xfeeeeddddcccc, RTFLOAT64U_EXP_BIAS) }, /* whatever */ 3670 }; 3671 static struct { RTFLOAT80U Val1; RTFLOAT32U Val2; } const s_aFpuBinaryR32Specials[] = 3672 { 3673 { RTFLOAT80U_INIT_C(0, 0xffffeeeeddddcccc, RTFLOAT80U_EXP_BIAS), 3674 RTFLOAT32U_INIT_C(0, 0x7fffee, RTFLOAT32U_EXP_BIAS) }, /* whatever */ 3675 }; 3676 3677 # define GEN_FPU_BINARY_SMALL(a_cBits, a_rdType, a_aSubTests, a_TestType) \ 3678 static void FpuBinaryR ## a_cBits ## Generate(PRTSTREAM pOut, uint32_t cTests) \ 3679 { \ 3680 RTStrmPrintf(pOut, "\n\n#define HAVE_FPU_BINARY_R" #a_cBits "\n"); \ 3681 X86FXSTATE State; \ 3682 RT_ZERO(State); \ 3683 uint32_t cMinNormalPairs = cTests / 4; \ 3684 for (size_t iFn = 0; iFn < RT_ELEMENTS(a_aSubTests); iFn++) \ 3685 { \ 3686 RTStrmPrintf(pOut, "static const " #a_TestType " g_aTests_%s[] =\n{\n", a_aSubTests[iFn].pszName); \ 3687 uint32_t cNormalInputPairs = 0; \ 3688 for (uint32_t iTest = 0; iTest < cTests + RT_ELEMENTS(s_aFpuBinaryR ## a_cBits ## Specials); iTest += 1) \ 3689 { \ 3690 RTFLOAT80U const InVal1 = iTest < cTests ? RandR80Ex() \ 3691 : s_aFpuBinaryR ## a_cBits ## Specials[iTest - cTests].Val1; \ 3692 a_rdType const InVal2 = iTest < cTests ? RandR ## a_cBits ## Src(a_cBits) \ 3693 : s_aFpuBinaryR ## a_cBits ## Specials[iTest - cTests].Val2; \ 3694 if (RTFLOAT80U_IS_NORMAL(&InVal1) && a_rdType ## _IS_NORMAL(&InVal2)) \ 3695 cNormalInputPairs++; \ 3696 else if (cNormalInputPairs < cMinNormalPairs && iTest + cMinNormalPairs >= cTests && iTest < cTests) \ 3697 { \ 3698 iTest -= 1; \ 3699 continue; \ 3700 } \ 3701 \ 3702 uint16_t const fFcw = RandFcw(); \ 3703 State.FSW = RandFsw(); \ 3704 \ 3705 for (uint16_t iRounding = 0; iRounding < 4; iRounding++) \ 3706 { \ 3707 for (uint16_t iPrecision = 0; iPrecision < 4; iPrecision++) \ 3708 { \ 3709 for (uint16_t iMask = 0; iMask <= X86_FCW_MASK_ALL; iMask += X86_FCW_MASK_ALL) \ 3710 { \ 3711 State.FCW = (fFcw & ~(X86_FCW_RC_MASK | X86_FCW_PC_MASK | X86_FCW_MASK_ALL)) \ 3712 | (iRounding << X86_FCW_RC_SHIFT) \ 3713 | (iPrecision << X86_FCW_PC_SHIFT) \ 3714 | iMask; \ 3715 IEMFPURESULT Res = { RTFLOAT80U_INIT(0, 0, 0), 0 }; \ 3716 a_aSubTests[iFn].pfn(&State, &Res, &InVal1, &InVal2); \ 3717 RTStrmPrintf(pOut, " { %#06x, %#06x, %#06x, %s, %s, %s }, /* #%u/%u/%u/%c */\n", \ 3718 State.FCW, State.FSW, Res.FSW, GenFormatR80(&InVal1), GenFormatR ## a_cBits(&InVal2), \ 3719 GenFormatR80(&Res.r80Result), iTest, iRounding, iPrecision, iMask ? 'c' : 'u'); \ 3720 } \ 3721 } \ 3722 } \ 3723 } \ 3724 RTStrmPrintf(pOut, "};\n"); \ 3725 } \ 3726 } 3727 #else 3728 # define GEN_FPU_BINARY_SMALL(a_cBits, a_rdType, a_aSubTests, a_TestType) 3729 #endif 3730 3731 #define TEST_FPU_BINARY_SMALL(a_cBits, a_rdType, a_SubTestType, a_aSubTests, a_TestType) \ 3732 typedef struct a_SubTestType \ 3733 { \ 3734 const char *pszName; \ 3735 PFNIEMAIMPLFPUR ## a_cBits pfn, pfnNative; \ 3736 a_TestType const *paTests; \ 3737 uint32_t cTests; \ 3738 uint32_t uExtra; \ 3739 uint8_t idxCpuEflFlavour; \ 3740 } a_SubTestType; \ 3741 \ 3742 static const a_SubTestType a_aSubTests[] = \ 3743 { \ 3744 ENTRY(RT_CONCAT(fadd_r80_by_r, a_cBits)), \ 3745 ENTRY(RT_CONCAT(fmul_r80_by_r, a_cBits)), \ 3746 ENTRY(RT_CONCAT(fsub_r80_by_r, a_cBits)), \ 3747 ENTRY(RT_CONCAT(fsubr_r80_by_r, a_cBits)), \ 3748 ENTRY(RT_CONCAT(fdiv_r80_by_r, a_cBits)), \ 3749 ENTRY(RT_CONCAT(fdivr_r80_by_r, a_cBits)), \ 3750 }; \ 3751 \ 3752 GEN_FPU_BINARY_SMALL(a_cBits, a_rdType, a_aSubTests, a_TestType) \ 3753 \ 3754 static void FpuBinaryR ## a_cBits ##Test(void) \ 3755 { \ 3756 X86FXSTATE State; \ 3757 RT_ZERO(State); \ 3758 for (size_t iFn = 0; iFn < RT_ELEMENTS(a_aSubTests); iFn++) \ 3759 { \ 3760 RTTestSub(g_hTest, a_aSubTests[iFn].pszName); \ 3761 \ 3762 uint32_t const cTests = a_aSubTests[iFn].cTests; \ 3763 a_TestType const * const paTests = a_aSubTests[iFn].paTests; \ 3764 PFNIEMAIMPLFPUR ## a_cBits pfn = a_aSubTests[iFn].pfn; \ 3765 uint32_t const cVars = 1 + (a_aSubTests[iFn].idxCpuEflFlavour == g_idxCpuEflFlavour && a_aSubTests[iFn].pfnNative); \ 3766 for (uint32_t iVar = 0; iVar < cVars; iVar++) \ 3767 { \ 3768 for (uint32_t iTest = 0; iTest < cTests; iTest++) \ 3769 { \ 3770 RTFLOAT80U const InVal1 = paTests[iTest].InVal1; \ 3771 a_rdType const InVal2 = paTests[iTest].InVal2; \ 3772 IEMFPURESULT Res = { RTFLOAT80U_INIT(0, 0, 0), 0 }; \ 3773 State.FCW = paTests[iTest].fFcw; \ 3774 State.FSW = paTests[iTest].fFswIn; \ 3775 pfn(&State, &Res, &InVal1, &InVal2); \ 3776 if ( Res.FSW != paTests[iTest].fFswOut \ 3777 || !RTFLOAT80U_ARE_IDENTICAL(&Res.r80Result, &paTests[iTest].OutVal)) \ 3778 RTTestFailed(g_hTest, "#%04u%s: fcw=%#06x fsw=%#06x in1=%s in2=%s\n" \ 3779 "%s -> fsw=%#06x %s\n" \ 3780 "%s expected %#06x %s%s%s (%s)\n", \ 3781 iTest, iVar ? "/n" : "", paTests[iTest].fFcw, paTests[iTest].fFswIn, \ 3782 FormatR80(&paTests[iTest].InVal1), FormatR ## a_cBits(&paTests[iTest].InVal2), \ 3783 iVar ? " " : "", Res.FSW, FormatR80(&Res.r80Result), \ 3784 iVar ? " " : "", paTests[iTest].fFswOut, FormatR80(&paTests[iTest].OutVal), \ 3785 FswDiff(Res.FSW, paTests[iTest].fFswOut), \ 3786 RTFLOAT80U_ARE_IDENTICAL(&Res.r80Result, &paTests[iTest].OutVal) ? " - val" : "", \ 3787 FormatFcw(paTests[iTest].fFcw) ); \ 3788 } \ 3789 pfn = a_aSubTests[iFn].pfnNative; \ 3790 } \ 3791 } \ 3792 } 3793 3794 TEST_FPU_BINARY_SMALL(64, RTFLOAT64U, FPU_BINARY_R64_T, g_aFpuBinaryR64, FPU_BINARY_R64_TEST_T) 3795 TEST_FPU_BINARY_SMALL(32, RTFLOAT32U, FPU_BINARY_R32_T, g_aFpuBinaryR32, FPU_BINARY_R32_TEST_T) 3796 3797 3798 /* 3799 * Binary operations on 80-, 64- and 32-bit floating point only affecting FSW. 3800 */ 3801 #ifndef HAVE_FPU_BINARY_FSW_R80 3802 static FPU_BINARY_R80_TEST_T const g_aTests_fcom_r80_by_r80[] = { {0} }; 3803 static FPU_BINARY_R80_TEST_T const g_aTests_fucom_r80_by_r80[] = { {0} }; 3804 #endif 3805 #ifndef HAVE_FPU_BINARY_FSW_R64 3806 static FPU_BINARY_R64_TEST_T const g_aTests_fcom_r80_by_r64[] = { {0} }; 3807 #endif 3808 #ifndef HAVE_FPU_BINARY_FSW_R32 3809 static FPU_BINARY_R32_TEST_T const g_aTests_fcom_r80_by_r32[] = { {0} }; 3810 #endif 3811 3812 #ifdef TSTIEMAIMPL_WITH_GENERATOR 3813 static struct { RTFLOAT80U Val1, Val2; } const s_aFpuBinaryFswR80Specials[] = 3814 { 3815 { RTFLOAT80U_INIT_C(0, 0xffffeeeeddddcccc, RTFLOAT80U_EXP_BIAS), 3816 RTFLOAT80U_INIT_C(0, 0xffffeeeeddddcccc, RTFLOAT80U_EXP_BIAS) }, /* whatever */ 3817 }; 3818 static struct { RTFLOAT80U Val1; RTFLOAT64U Val2; } const s_aFpuBinaryFswR64Specials[] = 3819 { 3820 { RTFLOAT80U_INIT_C(0, 0xffffeeeeddddcccc, RTFLOAT80U_EXP_BIAS), 3821 RTFLOAT64U_INIT_C(0, 0xfeeeeddddcccc, RTFLOAT64U_EXP_BIAS) }, /* whatever */ 3822 }; 3823 static struct { RTFLOAT80U Val1; RTFLOAT32U Val2; } const s_aFpuBinaryFswR32Specials[] = 3824 { 3825 { RTFLOAT80U_INIT_C(0, 0xffffeeeeddddcccc, RTFLOAT80U_EXP_BIAS), 3826 RTFLOAT32U_INIT_C(0, 0x7fffee, RTFLOAT32U_EXP_BIAS) }, /* whatever */ 3827 }; 3828 3829 # define GEN_FPU_BINARY_FSW(a_cBits, a_rdType, a_aSubTests, a_TestType) \ 3830 static void FpuBinaryFswR ## a_cBits ## Generate(PRTSTREAM pOut, uint32_t cTests) \ 3831 { \ 3832 RTStrmPrintf(pOut, "\n\n#define HAVE_FPU_BINARY_FSW_R" #a_cBits "\n"); \ 3833 X86FXSTATE State; \ 3834 RT_ZERO(State); \ 3835 uint32_t cMinNormalPairs = cTests / 4; \ 3836 for (size_t iFn = 0; iFn < RT_ELEMENTS(a_aSubTests); iFn++) \ 3837 { \ 3838 RTStrmPrintf(pOut, "static const " #a_TestType " g_aTests_%s[] =\n{\n", a_aSubTests[iFn].pszName); \ 3839 uint32_t cNormalInputPairs = 0; \ 3840 for (uint32_t iTest = 0; iTest < cTests + RT_ELEMENTS(s_aFpuBinaryFswR ## a_cBits ## Specials); iTest += 1) \ 3841 { \ 3842 RTFLOAT80U const InVal1 = iTest < cTests ? RandR80Ex() \ 3843 : s_aFpuBinaryFswR ## a_cBits ## Specials[iTest - cTests].Val1; \ 3844 a_rdType const InVal2 = iTest < cTests ? RandR ## a_cBits ## Src(a_cBits) \ 3845 : s_aFpuBinaryFswR ## a_cBits ## Specials[iTest - cTests].Val2; \ 3846 if (RTFLOAT80U_IS_NORMAL(&InVal1) && a_rdType ## _IS_NORMAL(&InVal2)) \ 3847 cNormalInputPairs++; \ 3848 else if (cNormalInputPairs < cMinNormalPairs && iTest + cMinNormalPairs >= cTests && iTest < cTests) \ 3849 { \ 3850 iTest -= 1; \ 3851 continue; \ 3852 } \ 3853 \ 3854 uint16_t const fFcw = RandFcw(); \ 3855 State.FSW = RandFsw(); \ 3856 \ 3857 /* Guess these aren't affected by precision or rounding, so just flip the exception mask. */ \ 3858 for (uint16_t iMask = 0; iMask <= X86_FCW_MASK_ALL; iMask += X86_FCW_MASK_ALL) \ 3859 { \ 3860 State.FCW = (fFcw & ~(X86_FCW_MASK_ALL)) | iMask; \ 3861 uint16_t uFswOut = 0; \ 3862 a_aSubTests[iFn].pfn(&State, &uFswOut, &InVal1, &InVal2); \ 3863 RTStrmPrintf(pOut, " { %#06x, %#06x, %#06x, %s, %s }, /* #%u/%c */\n", \ 3864 State.FCW, State.FSW, uFswOut, GenFormatR80(&InVal1), GenFormatR ## a_cBits(&InVal2), \ 3865 iTest, iMask ? 'c' : 'u'); \ 3866 } \ 3867 } \ 3868 RTStrmPrintf(pOut, "};\n"); \ 3869 } \ 3870 } 3871 #else 3872 # define GEN_FPU_BINARY_FSW(a_cBits, a_rdType, a_aSubTests, a_TestType) 3873 #endif 3874 3875 #define TEST_FPU_BINARY_FSW(a_cBits, a_rdType, a_SubTestType, a_aSubTests, a_TestType, ...) \ 3876 typedef struct a_SubTestType \ 3877 { \ 3878 const char *pszName; \ 3879 PFNIEMAIMPLFPUR ## a_cBits ## FSW pfn, pfnNative; \ 3880 a_TestType const *paTests; \ 3881 uint32_t cTests; \ 3882 uint32_t uExtra; \ 3883 uint8_t idxCpuEflFlavour; \ 3884 } a_SubTestType; \ 3885 \ 3886 static const a_SubTestType a_aSubTests[] = \ 3887 { \ 3888 ENTRY(RT_CONCAT(fcom_r80_by_r, a_cBits)), \ 3889 __VA_ARGS__\ 3890 }; \ 3891 \ 3892 GEN_FPU_BINARY_FSW(a_cBits, a_rdType, a_aSubTests, a_TestType) \ 3893 \ 3894 static void FpuBinaryFswR ## a_cBits ##Test(void) \ 3895 { \ 3896 X86FXSTATE State; \ 3897 RT_ZERO(State); \ 3898 for (size_t iFn = 0; iFn < RT_ELEMENTS(a_aSubTests); iFn++) \ 3899 { \ 3900 RTTestSub(g_hTest, a_aSubTests[iFn].pszName); \ 3901 \ 3902 uint32_t const cTests = a_aSubTests[iFn].cTests; \ 3903 a_TestType const * const paTests = a_aSubTests[iFn].paTests; \ 3904 PFNIEMAIMPLFPUR ## a_cBits ## FSW pfn = a_aSubTests[iFn].pfn; \ 3905 uint32_t const cVars = 1 + (a_aSubTests[iFn].idxCpuEflFlavour == g_idxCpuEflFlavour && a_aSubTests[iFn].pfnNative); \ 3906 for (uint32_t iVar = 0; iVar < cVars; iVar++) \ 3907 { \ 3908 for (uint32_t iTest = 0; iTest < cTests; iTest++) \ 3909 { \ 3910 RTFLOAT80U const InVal1 = paTests[iTest].InVal1; \ 3911 a_rdType const InVal2 = paTests[iTest].InVal2; \ 3912 State.FCW = paTests[iTest].fFcw; \ 3913 State.FSW = paTests[iTest].fFswIn; \ 3914 uint16_t uFswOut = 0; \ 3915 pfn(&State, &uFswOut, &InVal1, &InVal2); \ 3916 if (uFswOut != paTests[iTest].fFswOut) \ 3917 RTTestFailed(g_hTest, "#%04u%s: fcw=%#06x fsw=%#06x in1=%s in2=%s\n" \ 3918 "%s -> fsw=%#06x\n" \ 3919 "%s expected %#06x %s (%s)\n", \ 3920 iTest, iVar ? "/n" : "", paTests[iTest].fFcw, paTests[iTest].fFswIn, \ 3921 FormatR80(&paTests[iTest].InVal1), FormatR ## a_cBits(&paTests[iTest].InVal2), \ 3922 iVar ? " " : "", uFswOut, \ 3923 iVar ? " " : "", paTests[iTest].fFswOut, \ 3924 FswDiff(uFswOut, paTests[iTest].fFswOut), FormatFcw(paTests[iTest].fFcw) ); \ 3925 } \ 3926 pfn = a_aSubTests[iFn].pfnNative; \ 3927 } \ 3928 } \ 3929 } 3930 3931 TEST_FPU_BINARY_FSW(80, RTFLOAT80U, FPU_BINARY_FSW_R80_T, g_aFpuBinaryFswR80, FPU_BINARY_R80_TEST_T, ENTRY(fucom_r80_by_r80)) 3932 TEST_FPU_BINARY_FSW(64, RTFLOAT64U, FPU_BINARY_FSW_R64_T, g_aFpuBinaryFswR64, FPU_BINARY_R64_TEST_T, RT_NOTHING) 3933 TEST_FPU_BINARY_FSW(32, RTFLOAT32U, FPU_BINARY_FSW_R32_T, g_aFpuBinaryFswR32, FPU_BINARY_R32_TEST_T, RT_NOTHING) 3934 3935 3936 /* 3937 * Binary operations on 80-bit floating point that effects only EFLAGS and possibly FSW. 3938 */ 3939 #ifndef HAVE_FPU_BINARY_EFL_R80 3940 static FPU_BINARY_EFL_R80_TEST_T const g_aTests_fcomi_r80_by_r80[] = { {0} }; 3941 static FPU_BINARY_EFL_R80_TEST_T const g_aTests_fucomi_r80_by_r80[] = { {0} }; 3942 #endif 3943 3944 typedef struct FPU_BINARY_EFL_R80_T 3945 { 3946 const char *pszName; 3947 PFNIEMAIMPLFPUR80EFL pfn, pfnNative; 3948 FPU_BINARY_EFL_R80_TEST_T const *paTests; 3949 uint32_t cTests; 3950 uint32_t uExtra; 3951 uint8_t idxCpuEflFlavour; 3952 } FPU_BINARY_EFL_R80_T; 3953 3954 static const FPU_BINARY_EFL_R80_T g_aFpuBinaryEflR80[] = 3955 { 3956 ENTRY(fcomi_r80_by_r80), 3957 ENTRY(fucomi_r80_by_r80), 3958 }; 3959 3960 #ifdef TSTIEMAIMPL_WITH_GENERATOR 3961 static struct { RTFLOAT80U Val1, Val2; } const s_aFpuBinaryEflR80Specials[] = 3962 { 3963 { RTFLOAT80U_INIT_C(0, 0xffffeeeeddddcccc, RTFLOAT80U_EXP_BIAS), 3964 RTFLOAT80U_INIT_C(0, 0xffffeeeeddddcccc, RTFLOAT80U_EXP_BIAS) }, /* whatever */ 3965 }; 3966 3967 static void FpuBinaryEflR80Generate(PRTSTREAM pOut, uint32_t cTests) 3968 { 3969 RTStrmPrintf(pOut, "\n\n#define HAVE_FPU_BINARY_EFL_R80\n"); 3970 X86FXSTATE State; 3971 RT_ZERO(State); 3972 uint32_t cMinNormalPairs = cTests / 4; 3973 for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aFpuBinaryEflR80); iFn++) 3974 { 3975 RTStrmPrintf(pOut, "static const FPU_BINARY_EFL_R80_TEST_T g_aTests_%s[] =\n{\n", g_aFpuBinaryEflR80[iFn].pszName); 3976 uint32_t cNormalInputPairs = 0; 3977 for (uint32_t iTest = 0; iTest < cTests + RT_ELEMENTS(s_aFpuBinaryEflR80Specials); iTest += 1) 3978 { 3979 RTFLOAT80U const InVal1 = iTest < cTests ? RandR80Ex() : s_aFpuBinaryEflR80Specials[iTest - cTests].Val1; 3980 RTFLOAT80U const InVal2 = iTest < cTests ? RandR80Ex() : s_aFpuBinaryEflR80Specials[iTest - cTests].Val2; 3981 if (RTFLOAT80U_IS_NORMAL(&InVal1) && RTFLOAT80U_IS_NORMAL(&InVal2)) 3982 cNormalInputPairs++; 3983 else if (cNormalInputPairs < cMinNormalPairs && iTest + cMinNormalPairs >= cTests && iTest < cTests) 3984 { 3985 iTest -= 1; 3986 continue; 3987 } 3988 3989 uint16_t const fFcw = RandFcw(); 3990 State.FSW = RandFsw(); 3991 3992 /* Guess these aren't affected by precision or rounding, so just flip the exception mask. */ 3993 for (uint16_t iMask = 0; iMask <= X86_FCW_MASK_ALL; iMask += X86_FCW_MASK_ALL) 3994 { 3995 State.FCW = (fFcw & ~(X86_FCW_MASK_ALL)) | iMask; 3996 uint16_t uFswOut = 0; 3997 uint32_t fEflOut = g_aFpuBinaryEflR80[iFn].pfn(&State, &uFswOut, &InVal1, &InVal2); 3998 RTStrmPrintf(pOut, " { %#06x, %#06x, %#06x, %s, %s, %#08x }, /* #%u/%c */\n", 3999 State.FCW, State.FSW, uFswOut, GenFormatR80(&InVal1), GenFormatR80(&InVal2), fEflOut, 4000 iTest, iMask ? 'c' : 'u'); 4001 } 4002 } 4003 RTStrmPrintf(pOut, "};\n"); 4004 } 4005 } 4006 #endif /*TSTIEMAIMPL_WITH_GENERATOR*/ 4007 4008 static void FpuBinaryEflR80Test(void) 4009 { 4010 X86FXSTATE State; 4011 RT_ZERO(State); 4012 for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aFpuBinaryEflR80); iFn++) 4013 { 4014 RTTestSub(g_hTest, g_aFpuBinaryEflR80[iFn].pszName); 4015 4016 uint32_t const cTests = g_aFpuBinaryEflR80[iFn].cTests; 4017 FPU_BINARY_EFL_R80_TEST_T const * const paTests = g_aFpuBinaryEflR80[iFn].paTests; 4018 PFNIEMAIMPLFPUR80EFL pfn = g_aFpuBinaryEflR80[iFn].pfn; 4019 uint32_t const cVars = 1 + (g_aFpuBinaryEflR80[iFn].idxCpuEflFlavour == g_idxCpuEflFlavour && g_aFpuBinaryEflR80[iFn].pfnNative); 4020 for (uint32_t iVar = 0; iVar < cVars; iVar++) 4021 { 4022 for (uint32_t iTest = 0; iTest < cTests; iTest++) 4023 { 4024 RTFLOAT80U const InVal1 = paTests[iTest].InVal1; 4025 RTFLOAT80U const InVal2 = paTests[iTest].InVal2; 4026 State.FCW = paTests[iTest].fFcw; 4027 State.FSW = paTests[iTest].fFswIn; 4028 uint16_t uFswOut = 0; 4029 uint32_t fEflOut = pfn(&State, &uFswOut, &InVal1, &InVal2); 4030 if ( uFswOut != paTests[iTest].fFswOut 4031 || fEflOut != paTests[iTest].fEflOut) 4032 RTTestFailed(g_hTest, "#%04u%s: fcw=%#06x fsw=%#06x in1=%s in2=%s\n" 4033 "%s -> fsw=%#06x efl=%#08x\n" 4034 "%s expected %#06x %#08x %s (%s)\n", 4035 iTest, iVar ? "/n" : "", paTests[iTest].fFcw, paTests[iTest].fFswIn, 4036 FormatR80(&paTests[iTest].InVal1), FormatR80(&paTests[iTest].InVal2), 4037 iVar ? " " : "", uFswOut, fEflOut, 4038 iVar ? " " : "", paTests[iTest].fFswOut, paTests[iTest].fEflOut, 4039 EFlagsDiff(fEflOut, paTests[iTest].fEflOut), FormatFcw(paTests[iTest].fFcw)); 4040 } 4041 pfn = g_aFpuBinaryEflR80[iFn].pfnNative; 4042 } 4043 } 4044 } 4045 4046 4047 3453 4048 int main(int argc, char **argv) 3454 4049 { … … 3476 4071 bool fInt = true; 3477 4072 bool fFpuLdSt = true; 4073 bool fFpuBinary = true; 3478 4074 bool fFpuOther = true; 3479 4075 bool fCpuData = true; … … 3490 4086 { "--none", 'z', RTGETOPT_REQ_NOTHING }, 3491 4087 { "--zap", 'z', RTGETOPT_REQ_NOTHING }, 3492 { "--fpu-ld-st", 'f', RTGETOPT_REQ_NOTHING }, 3493 { "--fpu-load-store", 'f', RTGETOPT_REQ_NOTHING }, 3494 { "--fpu-other", 'F', RTGETOPT_REQ_NOTHING }, 4088 { "--fpu-ld-st", 'F', RTGETOPT_REQ_NOTHING }, /* FPU stuff is upper case */ 4089 { "--fpu-load-store", 'F', RTGETOPT_REQ_NOTHING }, 4090 { "--fpu-binary", 'B', RTGETOPT_REQ_NOTHING }, 4091 { "--fpu-other", 'O', RTGETOPT_REQ_NOTHING }, 3495 4092 { "--int", 'i', RTGETOPT_REQ_NOTHING }, 3496 4093 // generation parameters … … 3520 4117 fInt = true; 3521 4118 fFpuLdSt = true; 4119 fFpuBinary = true; 3522 4120 fFpuOther = true; 3523 4121 break; … … 3527 4125 fInt = false; 3528 4126 fFpuLdSt = false; 4127 fFpuBinary = false; 3529 4128 fFpuOther = false; 3530 4129 break; 3531 case ' f':4130 case 'F': 3532 4131 fFpuLdSt = true; 3533 4132 break; 3534 case ' F':4133 case 'O': 3535 4134 fFpuOther = true; 4135 break; 4136 case 'B': 4137 fFpuBinary = true; 3536 4138 break; 3537 4139 case 'i': … … 3563 4165 " -i, --int\n" 3564 4166 " Enable non-FPU tests.\n" 3565 " - f, --fpu-ld-st\n"4167 " -F, --fpu-ld-st\n" 3566 4168 " Enable FPU load and store tests.\n" 3567 " -f, --fpu-other\n" 4169 " -B, --fpu-binary\n" 4170 " Enable FPU binary 80, 64 and 32-bit FP tests.\n" 4171 " -O, --fpu-other\n" 3568 4172 " Enable other FPU tests.\n" 3569 4173 "\n" … … 3674 4278 } 3675 4279 4280 if (fFpuBinary) 4281 { 4282 const char *pszFileInfix = "FpuBinary"; 4283 const char *pszDataFile = fCommonData ? "tstIEMAImplDataFpuBinary.h" : pszBitBucket; 4284 PRTSTREAM pStrmData = NULL; 4285 rc = RTStrmOpen(pszDataFile, "w", &pStrmData); 4286 if (!pStrmData) 4287 return RTMsgErrorExitFailure("Failed to open %s for writing: %Rrc", pszDataFile, rc); 4288 4289 const char *pszDataCpuFile = !fCpuData ? pszBitBucket : g_idxCpuEflFlavour == IEMTARGETCPU_EFL_BEHAVIOR_AMD 4290 ? "tstIEMAImplDataFpuBinary-Amd.h" : "tstIEMAImplDataFpuBinary-Intel.h"; 4291 PRTSTREAM pStrmDataCpu = NULL; 4292 rc = RTStrmOpen(pszDataCpuFile, "w", &pStrmDataCpu); 4293 if (!pStrmData) 4294 return RTMsgErrorExitFailure("Failed to open %s for writing: %Rrc", pszDataCpuFile, rc); 4295 4296 GenerateHeader(pStrmData, pszFileInfix, szCpuDesc, NULL, ""); 4297 GenerateHeader(pStrmDataCpu, pszFileInfix, szCpuDesc, pszCpuType, pszCpuSuff); 4298 4299 FpuBinaryR80Generate(pStrmData, cTests); 4300 FpuBinaryR64Generate(pStrmData, cTests); 4301 FpuBinaryR32Generate(pStrmData, cTests); 4302 FpuBinaryFswR80Generate(pStrmData, cTests); 4303 FpuBinaryFswR64Generate(pStrmData, cTests); 4304 FpuBinaryFswR32Generate(pStrmData, cTests); 4305 FpuBinaryEflR80Generate(pStrmData, cTests); 4306 4307 RTEXITCODE rcExit = GenerateFooterAndClose(pStrmDataCpu, pszDataCpuFile, pszFileInfix, pszCpuSuff, 4308 GenerateFooterAndClose(pStrmData, pszDataFile, pszFileInfix, "", 4309 RTEXITCODE_SUCCESS)); 4310 if (rcExit != RTEXITCODE_SUCCESS) 4311 return rcExit; 4312 } 4313 4314 # if 0 3676 4315 if (fFpuOther) 3677 4316 { 3678 # if 03679 4317 const char *pszFileInfix = "FpuOther"; 3680 4318 const char *pszDataFile = fCommonData ? "tstIEMAImplDataFpuOther.h" : pszBitBucket; … … 3701 4339 if (rcExit != RTEXITCODE_SUCCESS) 3702 4340 return rcExit; 4341 } 3703 4342 # endif 3704 }3705 4343 3706 4344 return RTEXITCODE_SUCCESS; … … 3766 4404 FpuStD80Test(); 3767 4405 } 4406 4407 if (fFpuBinary) 4408 { 4409 FpuBinaryR80Test(); 4410 FpuBinaryR64Test(); 4411 FpuBinaryR32Test(); 4412 FpuBinaryFswR80Test(); 4413 FpuBinaryFswR64Test(); 4414 FpuBinaryFswR32Test(); 4415 FpuBinaryEflR80Test(); 4416 } 3768 4417 } 3769 4418 return RTTestSummaryAndDestroy(g_hTest);
Note:
See TracChangeset
for help on using the changeset viewer.