VirtualBox

Changeset 94680 in vbox


Ignore:
Timestamp:
Apr 22, 2022 7:37:55 AM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
151047
Message:

tstIEMAImpl: fprem, fprem1 & fscale adjustments. bugref:9898

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/testcase/tstIEMAImpl.cpp

    r94606 r94680  
    10081008        cch += RTStrPrintf(&pszBuf[cch], sizeof(g_aszBuf[0]) - cch, "/TOP%u!%u",
    10091009                           X86_FSW_TOP_GET(fActual), X86_FSW_TOP_GET(fExpected));
     1010#if 0 /* For debugging fprem & fprem1 */
     1011    cch += RTStrPrintf(&pszBuf[cch], sizeof(g_aszBuf[0]) - cch, " - Q=%d (vs %d)",
     1012                       X86_FSW_CX_TO_QUOTIENT(fActual), X86_FSW_CX_TO_QUOTIENT(fExpected));
     1013#endif
    10101014    RTStrPrintf(&pszBuf[cch], sizeof(g_aszBuf[0]) - cch, "");
    10111015    return pszBuf;
     
    31583162 */
    31593163TYPEDEF_SUBTEST_TYPE(FPU_BINARY_R80_T, FPU_BINARY_R80_TEST_T, PFNIEMAIMPLFPUR80);
     3164enum { kFpuBinaryHint_fprem = 1, };
    31603165
    31613166static const FPU_BINARY_R80_T g_aFpuBinaryR80[] =
     
    31673172    ENTRY(fdiv_r80_by_r80),
    31683173    ENTRY(fdivr_r80_by_r80),
    3169     ENTRY(fprem_r80_by_r80),
    3170     ENTRY(fprem1_r80_by_r80),
     3174    ENTRY_EX(fprem_r80_by_r80,  kFpuBinaryHint_fprem),
     3175    ENTRY_EX(fprem1_r80_by_r80, kFpuBinaryHint_fprem),
    31713176    ENTRY(fscale_r80_by_r80),
    31723177    ENTRY_AMD(  fpatan_r80_by_r80,  0),  // C1 and rounding differs on AMD
     
    31813186static void FpuBinaryR80Generate(PRTSTREAM pOut, PRTSTREAM pOutCpu, uint32_t cTests)
    31823187{
    3183     cTests = RT_MAX(160, cTests); /* there are 144 standard input variations */
     3188    cTests = RT_MAX(192, cTests); /* there are 144 standard input variations */
    31843189
    31853190    static struct { RTFLOAT80U Val1, Val2; } const s_aSpecials[] =
     
    31913196        {   RTFLOAT80U_INIT_ZERO(0),    /* minus variant */
    31923197            RTFLOAT80U_INIT_C(1, 0xffffffffffffffff, RTFLOAT80U_EXP_MAX - 1) },
     3198        {   RTFLOAT80U_INIT_C(0, 0xcef238bb9a0afd86, 577 + RTFLOAT80U_EXP_BIAS),    /* for fprem and fprem1, max sequence length */
     3199            RTFLOAT80U_INIT_C(0, 0xf11684ec0beaad94,   1 + RTFLOAT80U_EXP_BIAS) },
     3200        {   RTFLOAT80U_INIT_C(0, 0xffffffffffffffff, -13396 + RTFLOAT80U_EXP_BIAS), /* for fdiv. We missed PE. */
     3201            RTFLOAT80U_INIT_C(1, 0xffffffffffffffff,  16383 + RTFLOAT80U_EXP_BIAS) },
     3202        {   RTFLOAT80U_INIT_C(0, 0x8000000000000000,   1 + RTFLOAT80U_EXP_BIAS),    /* for fprem/fprem1 */
     3203            RTFLOAT80U_INIT_C(0, 0xe000000000000000,   0 + RTFLOAT80U_EXP_BIAS) },
     3204        {   RTFLOAT80U_INIT_C(0, 0x8000000000000000,   1 + RTFLOAT80U_EXP_BIAS),    /* for fprem/fprem1 */
     3205            RTFLOAT80U_INIT_C(0, 0x8000000000000000,   0 + RTFLOAT80U_EXP_BIAS) },
     3206        /* fscale: This may seriously increase the exponent, and it turns out overflow and underflow behaviour changes
     3207                   once RTFLOAT80U_EXP_BIAS_ADJUST is exceeded. */
     3208        {   RTFLOAT80U_INIT_C(0, 0xffffffffffffffff,   RTFLOAT80U_EXP_MAX - 1),     /* for fscale: max * 2^1 */
     3209            RTFLOAT80U_INIT_C(0, 0x8000000000000000,   0 + RTFLOAT80U_EXP_BIAS) },
     3210        {   RTFLOAT80U_INIT_C(0, 0xffffffffffffffff,   RTFLOAT80U_EXP_MAX - 1),     /* for fscale: max * 2^64 */
     3211            RTFLOAT80U_INIT_C(0, 0x8000000000000000,   6 + RTFLOAT80U_EXP_BIAS) },
     3212        {   RTFLOAT80U_INIT_C(0, 0xffffffffffffffff,   RTFLOAT80U_EXP_MAX - 1),     /* for fscale: max * 2^1024 */
     3213            RTFLOAT80U_INIT_C(0, 0x8000000000000000,   10 + RTFLOAT80U_EXP_BIAS) },
     3214        {   RTFLOAT80U_INIT_C(0, 0xffffffffffffffff,   RTFLOAT80U_EXP_MAX - 1),     /* for fscale: max * 2^4096 */
     3215            RTFLOAT80U_INIT_C(0, 0x8000000000000000,   12 + RTFLOAT80U_EXP_BIAS) },
     3216        {   RTFLOAT80U_INIT_C(0, 0xffffffffffffffff,   RTFLOAT80U_EXP_MAX - 1),     /* for fscale: max * 2^16384 */
     3217            RTFLOAT80U_INIT_C(0, 0x8000000000000000,   14 + RTFLOAT80U_EXP_BIAS) }, /* resulting exponent: 49150 */
     3218        {   RTFLOAT80U_INIT_C(0, 0xffffffffffffffff,   RTFLOAT80U_EXP_MAX - 1),     /* for fscale: max * 2^24576 (RTFLOAT80U_EXP_BIAS_ADJUST) */
     3219            RTFLOAT80U_INIT_C(0, 0xc000000000000000,   14 + RTFLOAT80U_EXP_BIAS) }, /* resulting exponent: 57342 - within 10980XE range */
     3220        {   RTFLOAT80U_INIT_C(0, 0xffffffffffffffff,   RTFLOAT80U_EXP_MAX - 1),     /* for fscale: max * 2^24577 */
     3221            RTFLOAT80U_INIT_C(0, 0xc002000000000000,   14 + RTFLOAT80U_EXP_BIAS) }, /* resulting exponent: 57343 - outside 10980XE range, behaviour changes! */
     3222        {   RTFLOAT80U_INIT_C(0, 0xffffffffffffffff,   RTFLOAT80U_EXP_MAX - 1),     /* for fscale: max * 2^32768 - result is within range on 10980XE */
     3223            RTFLOAT80U_INIT_C(0, 0x8000000000000000,   15 + RTFLOAT80U_EXP_BIAS) }, /* resulting exponent: 65534 */
     3224        {   RTFLOAT80U_INIT_C(0, 0xffffffffffffffff,   RTFLOAT80U_EXP_MAX - 1),     /* for fscale: max * 2^65536 */
     3225            RTFLOAT80U_INIT_C(0, 0x8000000000000000,   16 + RTFLOAT80U_EXP_BIAS) },
     3226        {   RTFLOAT80U_INIT_C(0, 0xffffffffffffffff,   RTFLOAT80U_EXP_MAX - 1),     /* for fscale: max * 2^1048576 */
     3227            RTFLOAT80U_INIT_C(0, 0x8000000000000000,   20 + RTFLOAT80U_EXP_BIAS) },
     3228        {   RTFLOAT80U_INIT_C(0, 0xffffffffffffffff,   RTFLOAT80U_EXP_MAX - 1),     /* for fscale: max * 2^16777216 */
     3229            RTFLOAT80U_INIT_C(0, 0x8000000000000000,   24 + RTFLOAT80U_EXP_BIAS) },
     3230        {   RTFLOAT80U_INIT_C(0, 0x8000000000000000,   1),                          /* for fscale: min * 2^-24576 (RTFLOAT80U_EXP_BIAS_ADJUST) */
     3231            RTFLOAT80U_INIT_C(1, 0xc000000000000000,   14 + RTFLOAT80U_EXP_BIAS) }, /* resulting exponent: -24575 - within 10980XE range */
     3232        {   RTFLOAT80U_INIT_C(0, 0x8000000000000000,   1),                          /* for fscale: max * 2^-24577 (RTFLOAT80U_EXP_BIAS_ADJUST) */
     3233            RTFLOAT80U_INIT_C(1, 0xc002000000000000,   14 + RTFLOAT80U_EXP_BIAS) }, /* resulting exponent: -24576 - outside 10980XE range, behaviour changes! */
     3234        /* fscale: Negative variants for the essentials of the above. */
     3235        {   RTFLOAT80U_INIT_C(1, 0xffffffffffffffff,   RTFLOAT80U_EXP_MAX - 1),     /* for fscale: max * 2^24576 (RTFLOAT80U_EXP_BIAS_ADJUST) */
     3236            RTFLOAT80U_INIT_C(0, 0xc000000000000000,   14 + RTFLOAT80U_EXP_BIAS) }, /* resulting exponent: 57342 - within 10980XE range */
     3237        {   RTFLOAT80U_INIT_C(1, 0xffffffffffffffff,   RTFLOAT80U_EXP_MAX - 1),     /* for fscale: max * 2^24577 */
     3238            RTFLOAT80U_INIT_C(0, 0xc002000000000000,   14 + RTFLOAT80U_EXP_BIAS) }, /* resulting exponent: 57343 - outside 10980XE range, behaviour changes! */
     3239        {   RTFLOAT80U_INIT_C(1, 0x8000000000000000,   1),                          /* for fscale: min * 2^-24576 (RTFLOAT80U_EXP_BIAS_ADJUST) */
     3240            RTFLOAT80U_INIT_C(1, 0xc000000000000000,   14 + RTFLOAT80U_EXP_BIAS) }, /* resulting exponent: -57342 - within 10980XE range */
     3241        {   RTFLOAT80U_INIT_C(1, 0x8000000000000000,   1),                          /* for fscale: max * 2^-24576 (RTFLOAT80U_EXP_BIAS_ADJUST) */
     3242            RTFLOAT80U_INIT_C(1, 0xc002000000000000,   14 + RTFLOAT80U_EXP_BIAS) }, /* resulting exponent: -57343 - outside 10980XE range, behaviour changes! */
     3243        /* fscale: Some fun with denormals and pseudo-denormals. */
     3244        {   RTFLOAT80U_INIT_C(0, 0x0800000000000000,   0),                          /* for fscale: max * 2^-4 */
     3245            RTFLOAT80U_INIT_C(1, 0x8000000000000000,   2 + RTFLOAT80U_EXP_BIAS) },
     3246        {   RTFLOAT80U_INIT_C(0, 0x0800000000000000,   0),                          /* for fscale: max * 2^+1 */
     3247            RTFLOAT80U_INIT_C(0, 0x8000000000000000,   0 + RTFLOAT80U_EXP_BIAS) },
     3248        {   RTFLOAT80U_INIT_C(0, 0x0800000000000000,   0), RTFLOAT80U_INIT_ZERO(0) }, /* for fscale: max * 2^+0 */
     3249        {   RTFLOAT80U_INIT_C(0, 0x0000000000000008,   0),                          /* for fscale: max * 2^-4 => underflow */
     3250            RTFLOAT80U_INIT_C(1, 0x8000000000000000,   2 + RTFLOAT80U_EXP_BIAS) },
     3251        {   RTFLOAT80U_INIT_C(0, 0x8005000300020001,   0), RTFLOAT80U_INIT_ZERO(0) }, /* pseudo-normal number * 2^+0. */
     3252        {   RTFLOAT80U_INIT_C(1, 0x8005000300020001,   0), RTFLOAT80U_INIT_ZERO(0) }, /* pseudo-normal number * 2^+0. */
     3253        {   RTFLOAT80U_INIT_C(0, 0x8005000300020001,   0),                          /* pseudo-normal number * 2^-4 */
     3254            RTFLOAT80U_INIT_C(1, 0x8000000000000000,   2 + RTFLOAT80U_EXP_BIAS) },
     3255        {   RTFLOAT80U_INIT_C(0, 0x8005000300020001,   0),                          /* pseudo-normal number * 2^+0 */
     3256            RTFLOAT80U_INIT_C(0, 0x8000000000000000,   0 + RTFLOAT80U_EXP_BIAS) },
     3257        {   RTFLOAT80U_INIT_C(0, 0x8005000300020001,   0),                          /* pseudo-normal number * 2^+1 */
     3258            RTFLOAT80U_INIT_C(0, 0x8000000000000000,   1 + RTFLOAT80U_EXP_BIAS) },
    31933259    };
    31943260
    31953261    X86FXSTATE State;
    31963262    RT_ZERO(State);
    3197     uint32_t cMinNormalPairs = (cTests - 144) / 4;
     3263    uint32_t cMinNormalPairs       = (cTests - 144) / 4;
     3264    uint32_t cMinTargetRangeInputs = cMinNormalPairs / 2;
    31983265    for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aFpuBinaryR80); iFn++)
    31993266    {
     
    32083275
    32093276        GenerateArrayStart(pOutFn, g_aFpuBinaryR80[iFn].pszName, "FPU_BINARY_R80_TEST_T");
    3210         uint32_t iTestOutput       = 0;
    3211         uint32_t cNormalInputPairs = 0;
     3277        uint32_t iTestOutput        = 0;
     3278        uint32_t cNormalInputPairs  = 0;
     3279        uint32_t cTargetRangeInputs = 0;
    32123280        for (uint32_t iTest = 0; iTest < cTests + RT_ELEMENTS(s_aSpecials); iTest += 1)
    32133281        {
    3214             RTFLOAT80U const InVal1 = iTest < cTests ? RandR80Src1(iTest) : s_aSpecials[iTest - cTests].Val1;
    3215             RTFLOAT80U const InVal2 = iTest < cTests ? RandR80Src2(iTest) : s_aSpecials[iTest - cTests].Val2;
     3282            RTFLOAT80U InVal1 = iTest < cTests ? RandR80Src1(iTest) : s_aSpecials[iTest - cTests].Val1;
     3283            RTFLOAT80U InVal2 = iTest < cTests ? RandR80Src2(iTest) : s_aSpecials[iTest - cTests].Val2;
     3284            bool fTargetRange = false;
    32163285            if (RTFLOAT80U_IS_NORMAL(&InVal1) && RTFLOAT80U_IS_NORMAL(&InVal2))
     3286            {
    32173287                cNormalInputPairs++;
     3288                if (   g_aFpuBinaryR80[iFn].uExtra == kFpuBinaryHint_fprem
     3289                    && (uint32_t)InVal1.s.uExponent - (uint32_t)InVal2.s.uExponent - (uint32_t)64 <= (uint32_t)512)
     3290                    cTargetRangeInputs += fTargetRange = true;
     3291                else if (cTargetRangeInputs < cMinTargetRangeInputs && iTest < cTests)
     3292                    if (g_aFpuBinaryR80[iFn].uExtra == kFpuBinaryHint_fprem)
     3293                    {   /* The aim is two values with an exponent difference between 64 and 640 so we can do the whole sequence. */
     3294                        InVal2.s.uExponent = RTRandU32Ex(1, RTFLOAT80U_EXP_MAX - 66);
     3295                        InVal1.s.uExponent = RTRandU32Ex(InVal2.s.uExponent + 64, RT_MIN(InVal2.s.uExponent + 512, RTFLOAT80U_EXP_MAX - 1));
     3296                        cTargetRangeInputs += fTargetRange = true;
     3297                    }
     3298            }
    32183299            else if (cNormalInputPairs < cMinNormalPairs && iTest + cMinNormalPairs >= cTests && iTest < cTests)
    32193300            {
     
    32763357                                                 GenFormatR80(&Res3.r80Result), iTest, iRounding, iPrecision, fUnmasked, iTestOutput++);
    32773358                                }
     3359                    }
     3360
     3361                    /* If the values are in range and caused no exceptions, do the whole series of
     3362                       partial reminders till we get the non-partial one or run into an exception. */
     3363                    if (fTargetRange && fXcpt == 0 && g_aFpuBinaryR80[iFn].uExtra == kFpuBinaryHint_fprem)
     3364                    {
     3365                        IEMFPURESULT ResPrev = ResM;
     3366                        for (unsigned i = 0; i < 32 && (ResPrev.FSW & (X86_FSW_C2 | X86_FSW_XCPT_MASK)) == X86_FSW_C2; i++)
     3367                        {
     3368                            State.FCW = State.FCW | X86_FCW_MASK_ALL;
     3369                            State.FSW = ResPrev.FSW;
     3370                            IEMFPURESULT ResSeq = { RTFLOAT80U_INIT(0, 0, 0), 0 };
     3371                            pfn(&State, &ResSeq, &ResPrev.r80Result, &InVal2);
     3372                            RTStrmPrintf(pOutFn, "    { %#06x, %#06x, %#06x, %s, %s, %s }, /* #%u/%u/%u/seq%u = #%u */\n",
     3373                                         State.FCW | fFcwExtra, State.FSW, ResSeq.FSW, GenFormatR80(&ResPrev.r80Result),
     3374                                         GenFormatR80(&InVal2), GenFormatR80(&ResSeq.r80Result),
     3375                                         iTest, iRounding, iPrecision, i + 1, iTestOutput++);
     3376                            ResPrev = ResSeq;
     3377                        }
    32783378                    }
    32793379                }
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette