VirtualBox

Changeset 94606 in vbox


Ignore:
Timestamp:
Apr 14, 2022 1:48:52 PM (2 years ago)
Author:
vboxsync
Message:

VMM/IEM,libs/softfloat,tstIEMAImpl: C implementation of fadd helper and related rounding tweaks for SoftFloat. Improved floating point test value generation to make sure we cover all types of input before we go full random. This means increasing the minimum number of tests to 160 for the binary floating point instructions, to cover all basic combinations. bugref:9898

Location:
trunk/src
Files:
3 edited

Legend:

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

    r94571 r94606  
    218218
    219219
    220 static int16_t  RandI16Src(uint32_t iTest)
    221 {
    222     RT_NOREF(iTest);
     220/** 2nd operand for and FPU instruction, pairing with RandR80Src1. */
     221static int16_t  RandI16Src2(uint32_t iTest)
     222{
     223    if (iTest < 18 * 4)
     224        switch (iTest % 4)
     225        {
     226            case 0: return 0;
     227            case 1: return INT16_MAX;
     228            case 2: return INT16_MIN;
     229            case 3: break;
     230        }
    223231    return (int16_t)RandU16();
    224232}
    225233
    226234
    227 static int32_t  RandI32Src(uint32_t iTest)
    228 {
    229     RT_NOREF(iTest);
     235/** 2nd operand for and FPU instruction, pairing with RandR80Src1. */
     236static int32_t  RandI32Src2(uint32_t iTest)
     237{
     238    if (iTest < 18 * 4)
     239        switch (iTest % 4)
     240        {
     241            case 0: return 0;
     242            case 1: return INT32_MAX;
     243            case 2: return INT32_MIN;
     244            case 3: break;
     245        }
    230246    return (int32_t)RandU32();
    231247}
     
    263279
    264280
    265 static RTFLOAT80U RandR80Ex(unsigned cTarget = 80, bool fIntTarget = false)
     281
     282static RTFLOAT80U RandR80Ex(uint8_t bType, unsigned cTarget = 80, bool fIntTarget = false)
    266283{
    267284    Assert(cTarget == (!fIntTarget ? 80U : 16U) || cTarget == 64U || cTarget == 32U || (cTarget == 59U && fIntTarget));
     
    272289
    273290    /*
    274      * Make it more likely that we get a good selection of special values.
     291     * Adjust the random stuff according to bType.
    275292     */
    276     uint8_t bType = RandU8() & 0x1f;
     293    bType &= 0x1f;
    277294    if (bType == 0 || bType == 1 || bType == 2 || bType == 3)
    278295    {
     
    283300        AssertMsg(bType != 0 || RTFLOAT80U_IS_ZERO(&r80),       ("%s\n", FormatR80(&r80)));
    284301        AssertMsg(bType != 1 || RTFLOAT80U_IS_PSEUDO_INF(&r80), ("%s\n", FormatR80(&r80)));
     302        Assert(   bType != 1 || RTFLOAT80U_IS_387_INVALID(&r80));
    285303        AssertMsg(bType != 2 || RTFLOAT80U_IS_INF(&r80),        ("%s\n", FormatR80(&r80)));
    286304        AssertMsg(bType != 3 || RTFLOAT80U_IS_INDEFINITE(&r80), ("%s\n", FormatR80(&r80)));
     
    313331        AssertMsg(RTFLOAT80U_IS_PSEUDO_NAN(&r80), ("%s bType=%#x\n", FormatR80(&r80), bType));
    314332        AssertMsg(RTFLOAT80U_IS_NAN(&r80),        ("%s bType=%#x\n", FormatR80(&r80), bType));
    315     }
    316     else if (bType == 10 || bType == 11)
    317     {
    318         /* Quiet and signalling NaNs (using fInteger to pick which). */
     333        Assert(RTFLOAT80U_IS_387_INVALID(&r80));
     334    }
     335    else if (bType == 10 || bType == 11 || bType == 12 || bType == 13)
     336    {
     337        /* Quiet and signalling NaNs. */
    319338        if (bType & 1)
    320339            SafeR80FractionShift(&r80, r80.sj64.uExponent % 62);
     
    322341            r80.sj64.uFraction = RTRandU64Ex(1, RT_BIT_64(RTFLOAT80U_FRACTION_BITS) - 1);
    323342        r80.sj64.uExponent = 0x7fff;
    324         if (r80.sj64.fInteger)
    325             r80.sj64.uFraction |= RT_BIT_64(62);
     343        if (bType < 12)
     344            r80.sj64.uFraction |= RT_BIT_64(62);  /* quiet */
    326345        else
    327             r80.sj64.uFraction &= ~RT_BIT_64(62);
     346            r80.sj64.uFraction &= ~RT_BIT_64(62); /* signaling */
    328347        r80.sj64.fInteger  = 1;
     348        AssertMsg(bType >= 12 || RTFLOAT80U_IS_QUIET_NAN(&r80), ("%s\n", FormatR80(&r80)));
     349        AssertMsg(bType <  12 || RTFLOAT80U_IS_SIGNALLING_NAN(&r80), ("%s\n", FormatR80(&r80)));
    329350        AssertMsg(RTFLOAT80U_IS_SIGNALLING_NAN(&r80) || RTFLOAT80U_IS_QUIET_NAN(&r80), ("%s\n", FormatR80(&r80)));
    330351        AssertMsg(RTFLOAT80U_IS_QUIET_OR_SIGNALLING_NAN(&r80), ("%s\n", FormatR80(&r80)));
    331352        AssertMsg(RTFLOAT80U_IS_NAN(&r80), ("%s\n", FormatR80(&r80)));
    332353    }
    333     else if (bType == 12 || bType == 13)
     354    else if (bType == 14 || bType == 15)
    334355    {
    335356        /* Unnormals */
     
    340361            r80.sj64.uExponent = (uint16_t)RTRandU32Ex(1, RTFLOAT80U_EXP_MAX - 1);
    341362        AssertMsg(RTFLOAT80U_IS_UNNORMAL(&r80), ("%s\n", FormatR80(&r80)));
    342     }
    343     else if (bType < 24)
     363        Assert(RTFLOAT80U_IS_387_INVALID(&r80));
     364    }
     365    else if (bType < 26)
    344366    {
    345367        /* Make sure we have lots of normalized values. */
     
    356378                r80.sj64.uExponent = uMaxExp - 1;
    357379
    358             if (bType == 14)
     380            if (bType == 16)
    359381            {   /* All 1s is useful to testing rounding. Also try trigger special
    360382                   behaviour by sometimes rounding out of range, while we're at it. */
     
    380402                r80.sj64.uExponent = uMaxExp;
    381403
    382             if (bType == 14)
     404            if (bType == 16)
    383405            {   /* All 1s is useful to testing rounding. Also try trigger special
    384406                   behaviour by sometimes rounding out of range, while we're at it. */
     
    398420
    399421
    400 static RTFLOAT80U RandR80Src(uint32_t iTest)
    401 {
    402     RT_NOREF(iTest);
    403     return RandR80Ex();
     422static RTFLOAT80U RandR80(unsigned cTarget = 80, bool fIntTarget = false)
     423{
     424    /*
     425     * Make it more likely that we get a good selection of special values.
     426     */
     427    return RandR80Ex(RandU8(), cTarget, fIntTarget);
     428
     429}
     430
     431
     432static RTFLOAT80U RandR80Src(uint32_t iTest, unsigned cTarget = 80, bool fIntTarget = false)
     433{
     434    /* Make sure we cover all the basic types first before going for random selection: */
     435    if (iTest <= 18)
     436        return RandR80Ex(18 - iTest, cTarget, fIntTarget); /* Starting with 3 normals. */
     437    return RandR80(cTarget, fIntTarget);
     438}
     439
     440
     441/**
     442 * Helper for RandR80Src1 and RandR80Src2 that converts bType from a 0..11 range
     443 * to a 0..17, covering all basic value types.
     444 */
     445static uint8_t RandR80Src12RemapType(uint8_t bType)
     446{
     447    switch (bType)
     448    {
     449        case 0:  return 18; /* normal */
     450        case 1:  return 16; /* normal extreme rounding */
     451        case 2:  return 14; /* unnormal */
     452        case 3:  return 12; /* Signalling NaN */
     453        case 4:  return 10; /* Quiet NaN */
     454        case 5:  return 8;  /* PseudoNaN */
     455        case 6:  return 6;  /* Pseudo Denormal */
     456        case 7:  return 4;  /* Denormal */
     457        case 8:  return 3;  /* Indefinite */
     458        case 9:  return 2;  /* Infinity */
     459        case 10: return 1;  /* Pseudo-Infinity */
     460        case 11: return 0;  /* Zero */
     461        default: AssertFailedReturn(18);
     462    }
     463}
     464
     465
     466/**
     467 * This works in tandem with RandR80Src2 to make sure we cover all operand
     468 * type mixes first before we venture into regular random testing.
     469 *
     470 * There are 11 basic variations, when we leave out the five odd ones using
     471 * SafeR80FractionShift. Because of the special normalized value targetting at
     472 * rounding, we make it an even 12.  So 144 combinations for two operands.
     473 */
     474static RTFLOAT80U RandR80Src1(uint32_t iTest, unsigned cPartnerBits = 80, bool fPartnerInt = false)
     475{
     476    if (cPartnerBits == 80)
     477    {
     478        Assert(!fPartnerInt);
     479        if (iTest < 12 * 12)
     480            return RandR80Ex(RandR80Src12RemapType(iTest / 12));
     481    }
     482    else if ((cPartnerBits == 64 || cPartnerBits == 32) && !fPartnerInt)
     483    {
     484        if (iTest < 12 * 10)
     485            return RandR80Ex(RandR80Src12RemapType(iTest / 10));
     486    }
     487    else if (iTest < 18 * 4 && fPartnerInt)
     488        return RandR80Ex(iTest / 4);
     489    return RandR80();
     490}
     491
     492
     493/** Partner to RandR80Src1. */
     494static RTFLOAT80U RandR80Src2(uint32_t iTest)
     495{
     496    if (iTest < 12 * 12)
     497        return RandR80Ex(RandR80Src12RemapType(iTest % 12));
     498    return RandR80();
    404499}
    405500
     
    414509
    415510
    416 static RTFLOAT64U RandR64Src(uint32_t iTest)
    417 {
    418     RT_NOREF(iTest);
    419 
     511static RTFLOAT64U RandR64Ex(uint8_t bType)
     512{
    420513    RTFLOAT64U r64;
    421514    r64.u = RandU64();
     
    425518     * On average 6 out of 16 calls should return a special value.
    426519     */
    427     uint8_t bType = RandU8() & 0xf;
     520    bType &= 0xf;
    428521    if (bType == 0 || bType == 1)
    429522    {
     
    445538        AssertMsg(RTFLOAT64U_IS_SUBNORMAL(&r64), ("%s bType=%#x\n", FormatR64(&r64), bType));
    446539    }
    447     else if (bType == 4 || bType == 5)
     540    else if (bType == 4 || bType == 5 || bType == 6 || bType == 7)
    448541    {
    449542        /* NaNs */
    450         if (bType == 5)
     543        if (bType & 1)
    451544            SafeR64FractionShift(&r64, r64.s64.uExponent % 51);
    452545        else if (r64.s64.uFraction == 0)
    453546            r64.s64.uFraction = RTRandU64Ex(1, RT_BIT_64(RTFLOAT64U_FRACTION_BITS) - 1);
    454547        r64.s64.uExponent = 0x7ff;
     548        if (bType < 6)
     549            r64.s64.uFraction |= RT_BIT_64(RTFLOAT64U_FRACTION_BITS - 1); /* quiet */
     550        else
     551            r64.s64.uFraction &= ~RT_BIT_64(RTFLOAT64U_FRACTION_BITS - 1); /* signalling */
     552        AssertMsg(bType >= 6 || RTFLOAT64U_IS_QUIET_NAN(&r64),      ("%s bType=%#x\n", FormatR64(&r64), bType));
     553        AssertMsg(bType <  6 || RTFLOAT64U_IS_SIGNALLING_NAN(&r64), ("%s bType=%#x\n", FormatR64(&r64), bType));
    455554        AssertMsg(RTFLOAT64U_IS_NAN(&r64), ("%s bType=%#x\n", FormatR64(&r64), bType));
    456555    }
     
    468567
    469568
     569static RTFLOAT64U RandR64Src(uint32_t iTest)
     570{
     571    if (iTest < 16)
     572        return RandR64Ex(iTest);
     573    return RandR64Ex(RandU8());
     574}
     575
     576
     577/** Pairing with a 80-bit floating point arg. */
     578static RTFLOAT64U RandR64Src2(uint32_t iTest)
     579{
     580    if (iTest < 12 * 10)
     581        return RandR64Ex(9 - iTest % 10); /* start with normal values */
     582    return RandR64Ex(RandU8());
     583}
     584
     585
    470586static void SafeR32FractionShift(PRTFLOAT32U pr32, uint8_t cShift)
    471587{
     
    477593
    478594
    479 static RTFLOAT32U RandR32Src(uint32_t iTest)
    480 {
    481     RT_NOREF(iTest);
    482 
     595static RTFLOAT32U RandR32Ex(uint8_t bType)
     596{
    483597    RTFLOAT32U r32;
    484598    r32.u = RandU32();
     
    488602     * On average 6 out of 16 calls should return a special value.
    489603     */
    490     uint8_t bType = RandU8() & 0xf;
     604    bType &= 0xf;
    491605    if (bType == 0 || bType == 1)
    492606    {
     
    507621        AssertMsg(RTFLOAT32U_IS_SUBNORMAL(&r32), ("%s bType=%#x\n", FormatR32(&r32), bType));
    508622    }
    509     else if (bType == 4 || bType == 5)
     623    else if (bType == 4 || bType == 5 || bType == 6 || bType == 7)
    510624    {
    511625        /* NaNs */
    512         if (bType == 5)
     626        if (bType & 1)
    513627            SafeR32FractionShift(&r32, r32.s.uExponent % 22);
    514628        else if (r32.s.uFraction == 0)
    515629            r32.s.uFraction = RTRandU32Ex(1, RT_BIT_32(RTFLOAT32U_FRACTION_BITS) - 1);
    516630        r32.s.uExponent = 0xff;
     631        if (bType < 6)
     632            r32.s.uFraction |= RT_BIT_32(RTFLOAT32U_FRACTION_BITS - 1);  /* quiet */
     633        else
     634            r32.s.uFraction &= ~RT_BIT_32(RTFLOAT32U_FRACTION_BITS - 1); /* signalling */
     635        AssertMsg(bType >= 6 || RTFLOAT32U_IS_QUIET_NAN(&r32),      ("%s bType=%#x\n", FormatR32(&r32), bType));
     636        AssertMsg(bType <  6 || RTFLOAT32U_IS_SIGNALLING_NAN(&r32), ("%s bType=%#x\n", FormatR32(&r32), bType));
    517637        AssertMsg(RTFLOAT32U_IS_NAN(&r32), ("%s bType=%#x\n", FormatR32(&r32), bType));
    518638    }
     
    527647    }
    528648    return r32;
     649}
     650
     651
     652static RTFLOAT32U RandR32Src(uint32_t iTest)
     653{
     654    if (iTest < 16)
     655        return RandR32Ex(iTest);
     656    return RandR32Ex(RandU8());
     657}
     658
     659
     660/** Pairing with a 80-bit floating point arg. */
     661static RTFLOAT32U RandR32Src2(uint32_t iTest)
     662{
     663    if (iTest < 12 * 10)
     664        return RandR32Ex(9 - iTest % 10); /* start with normal values */
     665    return RandR32Ex(RandU8());
    529666}
    530667
     
    25622699            uint16_t const fFcw = RandFcw(); \
    25632700            State.FSW = RandFsw(); \
    2564             RTFLOAT80U const InVal = iTest < cTests ? RandR80Src(iTest) : g_aFpuStR ## a_cBits ## Specials[iTest - cTests]; \
     2701            RTFLOAT80U const InVal = iTest < cTests ? RandR80Src(iTest, a_cBits) \
     2702                                   : g_aFpuStR ## a_cBits ## Specials[iTest - cTests]; \
    25652703            \
    25662704            for (uint16_t iRounding = 0; iRounding < 4; iRounding++) \
     
    28062944            uint16_t const fFcw = RandFcw(); \
    28072945            State.FSW = RandFsw(); \
    2808             RTFLOAT80U const InVal = iTest < cTests ? RandR80Ex(a_cBits, true) \
     2946            RTFLOAT80U const InVal = iTest < cTests ? RandR80Src(iTest, a_cBits, true) \
    28092947                                   : g_aFpuStI ## a_cBits ## Specials[iTest - cTests]; \
    28102948            \
     
    29413079            uint16_t const fFcw = RandFcw();
    29423080            State.FSW = RandFsw();
    2943             RTFLOAT80U const InVal = iTest < cTests ? RandR80Ex(59, true) : s_aSpecials[iTest - cTests];
     3081            RTFLOAT80U const InVal = iTest < cTests ? RandR80Src(iTest, 59, true) : s_aSpecials[iTest - cTests];
    29443082
    29453083            for (uint16_t iRounding = 0; iRounding < 4; iRounding++)
     
    30433181static void FpuBinaryR80Generate(PRTSTREAM pOut, PRTSTREAM pOutCpu, uint32_t cTests)
    30443182{
     3183    cTests = RT_MAX(160, cTests); /* there are 144 standard input variations */
     3184
    30453185    static struct { RTFLOAT80U Val1, Val2; } const s_aSpecials[] =
    30463186    {
    3047         {   RTFLOAT80U_INIT_C(0, 0xffffeeeeddddcccc, RTFLOAT80U_EXP_BIAS),
    3048             RTFLOAT80U_INIT_C(0, 0xffffeeeeddddcccc, RTFLOAT80U_EXP_BIAS)   }, /* whatever */
     3187        {   RTFLOAT80U_INIT_C(1, 0xdd762f07f2e80eef, 30142),    /* causes weird overflows with DOWN and NEAR rounding. */
     3188            RTFLOAT80U_INIT_C(1, 0xffffffffffffffff, RTFLOAT80U_EXP_MAX - 1) },
     3189        {   RTFLOAT80U_INIT_ZERO(0),    /* causes weird overflows with UP and NEAR rounding when precision is lower than 64. */
     3190            RTFLOAT80U_INIT_C(0, 0xffffffffffffffff, RTFLOAT80U_EXP_MAX - 1) },
     3191        {   RTFLOAT80U_INIT_ZERO(0),    /* minus variant */
     3192            RTFLOAT80U_INIT_C(1, 0xffffffffffffffff, RTFLOAT80U_EXP_MAX - 1) },
    30493193    };
    30503194
    30513195    X86FXSTATE State;
    30523196    RT_ZERO(State);
    3053     uint32_t cMinNormalPairs = cTests / 4;
     3197    uint32_t cMinNormalPairs = (cTests - 144) / 4;
    30543198    for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aFpuBinaryR80); iFn++)
    30553199    {
     
    30643208
    30653209        GenerateArrayStart(pOutFn, g_aFpuBinaryR80[iFn].pszName, "FPU_BINARY_R80_TEST_T");
     3210        uint32_t iTestOutput       = 0;
    30663211        uint32_t cNormalInputPairs = 0;
    30673212        for (uint32_t iTest = 0; iTest < cTests + RT_ELEMENTS(s_aSpecials); iTest += 1)
    30683213        {
    3069             RTFLOAT80U const InVal1 = iTest < cTests ? RandR80Ex() : s_aSpecials[iTest - cTests].Val1;
    3070             RTFLOAT80U const InVal2 = iTest < cTests ? RandR80Ex() : s_aSpecials[iTest - cTests].Val2;
     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;
    30713216            if (RTFLOAT80U_IS_NORMAL(&InVal1) && RTFLOAT80U_IS_NORMAL(&InVal2))
    30723217                cNormalInputPairs++;
     
    30773222            }
    30783223
     3224            uint16_t const fFcwExtra = 0;
    30793225            uint16_t const fFcw = RandFcw();
    30803226            State.FSW = RandFsw();
    30813227
    30823228            for (uint16_t iRounding = 0; iRounding < 4; iRounding++)
    3083             {
    30843229                for (uint16_t iPrecision = 0; iPrecision < 4; iPrecision++)
    30853230                {
    3086                     for (uint16_t iMask = 0; iMask <= X86_FCW_MASK_ALL; iMask += X86_FCW_MASK_ALL)
     3231                    State.FCW = (fFcw & ~(X86_FCW_RC_MASK | X86_FCW_PC_MASK | X86_FCW_MASK_ALL))
     3232                              | (iRounding  << X86_FCW_RC_SHIFT)
     3233                              | (iPrecision << X86_FCW_PC_SHIFT)
     3234                              | X86_FCW_MASK_ALL;
     3235                    IEMFPURESULT ResM = { RTFLOAT80U_INIT(0, 0, 0), 0 };
     3236                    pfn(&State, &ResM, &InVal1, &InVal2);
     3237                    RTStrmPrintf(pOutFn, "    { %#06x, %#06x, %#06x, %s, %s, %s }, /* #%u/%u/%u/m = #%u */\n",
     3238                                 State.FCW | fFcwExtra, State.FSW, ResM.FSW, GenFormatR80(&InVal1), GenFormatR80(&InVal2),
     3239                                 GenFormatR80(&ResM.r80Result), iTest, iRounding, iPrecision, iTestOutput++);
     3240
     3241                    State.FCW = State.FCW & ~X86_FCW_MASK_ALL;
     3242                    IEMFPURESULT ResU = { RTFLOAT80U_INIT(0, 0, 0), 0 };
     3243                    pfn(&State, &ResU, &InVal1, &InVal2);
     3244                    RTStrmPrintf(pOutFn, "    { %#06x, %#06x, %#06x, %s, %s, %s }, /* #%u/%u/%u/u = #%u */\n",
     3245                                 State.FCW | fFcwExtra, State.FSW, ResU.FSW, GenFormatR80(&InVal1), GenFormatR80(&InVal2),
     3246                                 GenFormatR80(&ResU.r80Result), iTest, iRounding, iPrecision, iTestOutput++);
     3247
     3248                    uint16_t fXcpt = (ResM.FSW | ResU.FSW) & X86_FSW_XCPT_MASK & ~X86_FSW_SF;
     3249                    if (fXcpt)
    30873250                    {
    3088                         State.FCW = (fFcw & ~(X86_FCW_RC_MASK | X86_FCW_PC_MASK | X86_FCW_MASK_ALL))
    3089                                   | (iRounding  << X86_FCW_RC_SHIFT)
    3090                                   | (iPrecision << X86_FCW_PC_SHIFT)
    3091                                   | iMask;
    3092                         IEMFPURESULT Res = { RTFLOAT80U_INIT(0, 0, 0), 0 };
    3093                         pfn(&State, &Res, &InVal1, &InVal2);
    3094                         RTStrmPrintf(pOutFn, "    { %#06x, %#06x, %#06x, %s, %s, %s }, /* #%u/%u/%u/%c */\n",
    3095                                      State.FCW, State.FSW, Res.FSW, GenFormatR80(&InVal1), GenFormatR80(&InVal2),
    3096                                      GenFormatR80(&Res.r80Result), iTest, iRounding, iPrecision, iMask ? 'c' : 'u');
     3251                        State.FCW = (State.FCW & ~X86_FCW_MASK_ALL) | fXcpt;
     3252                        IEMFPURESULT Res1 = { RTFLOAT80U_INIT(0, 0, 0), 0 };
     3253                        pfn(&State, &Res1, &InVal1, &InVal2);
     3254                        RTStrmPrintf(pOutFn, "    { %#06x, %#06x, %#06x, %s, %s, %s }, /* #%u/%u/%u/%#x = #%u */\n",
     3255                                     State.FCW | fFcwExtra, State.FSW, Res1.FSW, GenFormatR80(&InVal1), GenFormatR80(&InVal2),
     3256                                     GenFormatR80(&Res1.r80Result), iTest, iRounding, iPrecision, fXcpt, iTestOutput++);
     3257                        if (((Res1.FSW & X86_FSW_XCPT_MASK) & fXcpt) != (Res1.FSW & X86_FSW_XCPT_MASK))
     3258                        {
     3259                            fXcpt |= Res1.FSW & X86_FSW_XCPT_MASK;
     3260                            State.FCW = (State.FCW & ~X86_FCW_MASK_ALL) | fXcpt;
     3261                            IEMFPURESULT Res2 = { RTFLOAT80U_INIT(0, 0, 0), 0 };
     3262                            pfn(&State, &Res2, &InVal1, &InVal2);
     3263                            RTStrmPrintf(pOutFn, "    { %#06x, %#06x, %#06x, %s, %s, %s }, /* #%u/%u/%u/%#x[!] = #%u */\n",
     3264                                         State.FCW | fFcwExtra, State.FSW, Res2.FSW, GenFormatR80(&InVal1), GenFormatR80(&InVal2),
     3265                                         GenFormatR80(&Res2.r80Result), iTest, iRounding, iPrecision, fXcpt, iTestOutput++);
     3266                        }
     3267                        if (!RT_IS_POWER_OF_TWO(fXcpt))
     3268                            for (uint16_t fUnmasked = 1; fUnmasked <= X86_FCW_PM; fUnmasked <<= 1)
     3269                                if (fUnmasked & fXcpt)
     3270                                {
     3271                                    State.FCW = (State.FCW & ~X86_FCW_MASK_ALL) | (fXcpt & ~fUnmasked);
     3272                                    IEMFPURESULT Res3 = { RTFLOAT80U_INIT(0, 0, 0), 0 };
     3273                                    pfn(&State, &Res3, &InVal1, &InVal2);
     3274                                    RTStrmPrintf(pOutFn, "    { %#06x, %#06x, %#06x, %s, %s, %s }, /* #%u/%u/%u/u%#x = #%u */\n",
     3275                                                 State.FCW | fFcwExtra, State.FSW, Res3.FSW, GenFormatR80(&InVal1), GenFormatR80(&InVal2),
     3276                                                 GenFormatR80(&Res3.r80Result), iTest, iRounding, iPrecision, fUnmasked, iTestOutput++);
     3277                                }
    30973278                    }
    30983279                }
    3099             }
    31003280        }
    31013281        GenerateArrayEnd(pOutFn, g_aFpuBinaryR80[iFn].pszName);
     
    31753355};
    31763356
    3177 # define GEN_FPU_BINARY_SMALL(a_cBits, a_LoBits, a_UpBits, a_Type2, a_aSubTests, a_TestType) \
     3357# define GEN_FPU_BINARY_SMALL(a_fIntType, a_cBits, a_LoBits, a_UpBits, a_Type2, a_aSubTests, a_TestType) \
    31783358static void FpuBinary ## a_UpBits ## Generate(PRTSTREAM pOut, uint32_t cTests) \
    31793359{ \
     3360    cTests = RT_MAX(160, cTests); /* there are 144 standard input variations for r80 by r80 */ \
     3361    \
    31803362    X86FXSTATE State; \
    31813363    RT_ZERO(State); \
    3182     uint32_t cMinNormalPairs = cTests / 4; \
     3364    uint32_t cMinNormalPairs = (cTests - 144) / 4; \
    31833365    for (size_t iFn = 0; iFn < RT_ELEMENTS(a_aSubTests); iFn++) \
    31843366    { \
     
    31873369        for (uint32_t iTest = 0; iTest < cTests + RT_ELEMENTS(s_aFpuBinary ## a_UpBits ## Specials); iTest += 1) \
    31883370        { \
    3189             RTFLOAT80U const InVal1 = iTest < cTests ? RandR80Ex() \
     3371            RTFLOAT80U const InVal1 = iTest < cTests ? RandR80Src1(iTest, a_cBits, a_fIntType) \
    31903372                                    : s_aFpuBinary ## a_UpBits ## Specials[iTest - cTests].Val1; \
    3191             a_Type2    const InVal2 = iTest < cTests ? Rand ## a_UpBits ## Src(a_cBits) \
     3373            a_Type2    const InVal2 = iTest < cTests ? Rand ## a_UpBits ## Src2(iTest) \
    31923374                                    : s_aFpuBinary ## a_UpBits ## Specials[iTest - cTests].Val2; \
    31933375            if (RTFLOAT80U_IS_NORMAL(&InVal1) && a_Type2 ## _IS_NORMAL(&InVal2)) \
     
    32253407}
    32263408#else
    3227 # define GEN_FPU_BINARY_SMALL(a_cBits, a_LoBits, a_UpBits, a_Type2, a_aSubTests, a_TestType)
     3409# define GEN_FPU_BINARY_SMALL(a_fIntType, a_cBits, a_LoBits, a_UpBits, a_Type2, a_aSubTests, a_TestType)
    32283410#endif
    32293411
    3230 #define TEST_FPU_BINARY_SMALL(a_cBits, a_LoBits, a_UpBits, a_I, a_Type2, a_SubTestType, a_aSubTests, a_TestType) \
     3412#define TEST_FPU_BINARY_SMALL(a_fIntType, a_cBits, a_LoBits, a_UpBits, a_I, a_Type2, a_SubTestType, a_aSubTests, a_TestType) \
    32313413TYPEDEF_SUBTEST_TYPE(a_SubTestType, a_TestType, PFNIEMAIMPLFPU ## a_UpBits); \
    32323414\
     
    32413423}; \
    32423424\
    3243 GEN_FPU_BINARY_SMALL(a_cBits, a_LoBits, a_UpBits, a_Type2, a_aSubTests, a_TestType) \
     3425GEN_FPU_BINARY_SMALL(a_fIntType, a_cBits, a_LoBits, a_UpBits, a_Type2, a_aSubTests, a_TestType) \
    32443426\
    32453427static void FpuBinary ## a_UpBits ## Test(void) \
     
    32843466}
    32853467
    3286 TEST_FPU_BINARY_SMALL(64, r64, R64, RT_NOTHING, RTFLOAT64U, FPU_BINARY_R64_T, g_aFpuBinaryR64, FPU_BINARY_R64_TEST_T)
    3287 TEST_FPU_BINARY_SMALL(32, r32, R32, RT_NOTHING, RTFLOAT32U, FPU_BINARY_R32_T, g_aFpuBinaryR32, FPU_BINARY_R32_TEST_T)
    3288 TEST_FPU_BINARY_SMALL(32, i32, I32, i,          int32_t,    FPU_BINARY_I32_T, g_aFpuBinaryI32, FPU_BINARY_I32_TEST_T)
    3289 TEST_FPU_BINARY_SMALL(16, i16, I16, i,          int16_t,    FPU_BINARY_I16_T, g_aFpuBinaryI16, FPU_BINARY_I16_TEST_T)
     3468TEST_FPU_BINARY_SMALL(0, 64, r64, R64, RT_NOTHING, RTFLOAT64U, FPU_BINARY_R64_T, g_aFpuBinaryR64, FPU_BINARY_R64_TEST_T)
     3469TEST_FPU_BINARY_SMALL(0, 32, r32, R32, RT_NOTHING, RTFLOAT32U, FPU_BINARY_R32_T, g_aFpuBinaryR32, FPU_BINARY_R32_TEST_T)
     3470TEST_FPU_BINARY_SMALL(1, 32, i32, I32, i,          int32_t,    FPU_BINARY_I32_T, g_aFpuBinaryI32, FPU_BINARY_I32_TEST_T)
     3471TEST_FPU_BINARY_SMALL(1, 16, i16, I16, i,          int16_t,    FPU_BINARY_I16_T, g_aFpuBinaryI16, FPU_BINARY_I16_TEST_T)
    32903472
    32913473
     
    33183500};
    33193501
    3320 # define GEN_FPU_BINARY_FSW(a_cBits, a_UpBits, a_Type2, a_aSubTests, a_TestType) \
     3502# define GEN_FPU_BINARY_FSW(a_fIntType, a_cBits, a_UpBits, a_Type2, a_aSubTests, a_TestType) \
    33213503static void FpuBinaryFsw ## a_UpBits ## Generate(PRTSTREAM pOut, uint32_t cTests) \
    33223504{ \
     3505    cTests = RT_MAX(160, cTests); /* there are 144 standard input variations for r80 by r80 */ \
     3506    \
    33233507    X86FXSTATE State; \
    33243508    RT_ZERO(State); \
    3325     uint32_t cMinNormalPairs = cTests / 4; \
     3509    uint32_t cMinNormalPairs = (cTests - 144) / 4; \
    33263510    for (size_t iFn = 0; iFn < RT_ELEMENTS(a_aSubTests); iFn++) \
    33273511    { \
     
    33303514        for (uint32_t iTest = 0; iTest < cTests + RT_ELEMENTS(s_aFpuBinaryFsw ## a_UpBits ## Specials); iTest += 1) \
    33313515        { \
    3332             RTFLOAT80U const InVal1 = iTest < cTests ? RandR80Ex() \
     3516            RTFLOAT80U const InVal1 = iTest < cTests ? RandR80Src1(iTest, a_cBits, a_fIntType) \
    33333517                                    : s_aFpuBinaryFsw ## a_UpBits ## Specials[iTest - cTests].Val1; \
    3334             a_Type2    const InVal2 = iTest < cTests ? Rand ## a_UpBits ## Src(a_cBits) \
     3518            a_Type2    const InVal2 = iTest < cTests ? Rand ## a_UpBits ## Src2(iTest) \
    33353519                                    : s_aFpuBinaryFsw ## a_UpBits ## Specials[iTest - cTests].Val2; \
    33363520            if (RTFLOAT80U_IS_NORMAL(&InVal1) && a_Type2 ## _IS_NORMAL(&InVal2)) \
     
    33603544}
    33613545#else
    3362 # define GEN_FPU_BINARY_FSW(a_cBits, a_UpBits, a_Type2, a_aSubTests, a_TestType)
     3546# define GEN_FPU_BINARY_FSW(a_fIntType, a_cBits, a_UpBits, a_Type2, a_aSubTests, a_TestType)
    33633547#endif
    33643548
    3365 #define TEST_FPU_BINARY_FSW(a_cBits, a_UpBits, a_Type2, a_SubTestType, a_aSubTests, a_TestType, ...) \
     3549#define TEST_FPU_BINARY_FSW(a_fIntType, a_cBits, a_UpBits, a_Type2, a_SubTestType, a_aSubTests, a_TestType, ...) \
    33663550TYPEDEF_SUBTEST_TYPE(a_SubTestType, a_TestType, PFNIEMAIMPLFPU ## a_UpBits ## FSW); \
    33673551\
     
    33713555}; \
    33723556\
    3373 GEN_FPU_BINARY_FSW(a_cBits, a_UpBits, a_Type2, a_aSubTests, a_TestType) \
     3557GEN_FPU_BINARY_FSW(a_fIntType, a_cBits, a_UpBits, a_Type2, a_aSubTests, a_TestType) \
    33743558\
    33753559static void FpuBinaryFsw ## a_UpBits ## Test(void) \
     
    34113595}
    34123596
    3413 TEST_FPU_BINARY_FSW(80, R80, RTFLOAT80U, FPU_BINARY_FSW_R80_T, g_aFpuBinaryFswR80, FPU_BINARY_R80_TEST_T, ENTRY(fcom_r80_by_r80), ENTRY(fucom_r80_by_r80))
    3414 TEST_FPU_BINARY_FSW(64, R64, RTFLOAT64U, FPU_BINARY_FSW_R64_T, g_aFpuBinaryFswR64, FPU_BINARY_R64_TEST_T, ENTRY(fcom_r80_by_r64))
    3415 TEST_FPU_BINARY_FSW(32, R32, RTFLOAT32U, FPU_BINARY_FSW_R32_T, g_aFpuBinaryFswR32, FPU_BINARY_R32_TEST_T, ENTRY(fcom_r80_by_r32))
    3416 TEST_FPU_BINARY_FSW(32, I32, int32_t,    FPU_BINARY_FSW_I32_T, g_aFpuBinaryFswI32, FPU_BINARY_I32_TEST_T, ENTRY(ficom_r80_by_i32))
    3417 TEST_FPU_BINARY_FSW(16, I16, int16_t,    FPU_BINARY_FSW_I16_T, g_aFpuBinaryFswI16, FPU_BINARY_I16_TEST_T, ENTRY(ficom_r80_by_i16))
     3597TEST_FPU_BINARY_FSW(0, 80, R80, RTFLOAT80U, FPU_BINARY_FSW_R80_T, g_aFpuBinaryFswR80, FPU_BINARY_R80_TEST_T, ENTRY(fcom_r80_by_r80), ENTRY(fucom_r80_by_r80))
     3598TEST_FPU_BINARY_FSW(0, 64, R64, RTFLOAT64U, FPU_BINARY_FSW_R64_T, g_aFpuBinaryFswR64, FPU_BINARY_R64_TEST_T, ENTRY(fcom_r80_by_r64))
     3599TEST_FPU_BINARY_FSW(0, 32, R32, RTFLOAT32U, FPU_BINARY_FSW_R32_T, g_aFpuBinaryFswR32, FPU_BINARY_R32_TEST_T, ENTRY(fcom_r80_by_r32))
     3600TEST_FPU_BINARY_FSW(1, 32, I32, int32_t,    FPU_BINARY_FSW_I32_T, g_aFpuBinaryFswI32, FPU_BINARY_I32_TEST_T, ENTRY(ficom_r80_by_i32))
     3601TEST_FPU_BINARY_FSW(1, 16, I16, int16_t,    FPU_BINARY_FSW_I16_T, g_aFpuBinaryFswI16, FPU_BINARY_I16_TEST_T, ENTRY(ficom_r80_by_i16))
    34183602
    34193603
     
    34383622static void FpuBinaryEflR80Generate(PRTSTREAM pOut, uint32_t cTests)
    34393623{
     3624    cTests = RT_MAX(160, cTests); /* there are 144 standard input variations */
     3625
    34403626    X86FXSTATE State;
    34413627    RT_ZERO(State);
    3442     uint32_t cMinNormalPairs = cTests / 4;
     3628    uint32_t cMinNormalPairs = (cTests - 144) / 4;
    34433629    for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aFpuBinaryEflR80); iFn++)
    34443630    {
     
    34473633        for (uint32_t iTest = 0; iTest < cTests + RT_ELEMENTS(s_aFpuBinaryEflR80Specials); iTest += 1)
    34483634        {
    3449             RTFLOAT80U const InVal1 = iTest < cTests ? RandR80Ex() : s_aFpuBinaryEflR80Specials[iTest - cTests].Val1;
    3450             RTFLOAT80U const InVal2 = iTest < cTests ? RandR80Ex() : s_aFpuBinaryEflR80Specials[iTest - cTests].Val2;
     3635            RTFLOAT80U const InVal1 = iTest < cTests ? RandR80Src1(iTest) : s_aFpuBinaryEflR80Specials[iTest - cTests].Val1;
     3636            RTFLOAT80U const InVal2 = iTest < cTests ? RandR80Src2(iTest) : s_aFpuBinaryEflR80Specials[iTest - cTests].Val2;
    34513637            if (RTFLOAT80U_IS_NORMAL(&InVal1) && RTFLOAT80U_IS_NORMAL(&InVal2))
    34523638                cNormalInputPairs++;
     
    35913777        for (uint32_t iTest = 0; iTest < cTests + RT_ELEMENTS(s_aSpecials); iTest += 1)
    35923778        {
    3593             RTFLOAT80U InVal = iTest < cTests ? RandR80Ex() : s_aSpecials[iTest - cTests];
     3779            RTFLOAT80U InVal = iTest < cTests ? RandR80Src(iTest) : s_aSpecials[iTest - cTests];
    35943780            if (RTFLOAT80U_IS_NORMAL(&InVal))
    35953781            {
     
    38063992        for (uint32_t iTest = 0; iTest < cTests + RT_ELEMENTS(s_aSpecials); iTest += 1)
    38073993        {
    3808             RTFLOAT80U const InVal = iTest < cTests ? RandR80Ex() : s_aSpecials[iTest - cTests];
     3994            RTFLOAT80U const InVal = iTest < cTests ? RandR80Src(iTest) : s_aSpecials[iTest - cTests];
    38093995            if (RTFLOAT80U_IS_NORMAL(&InVal))
    38103996                cNormalInputs++;
     
    39374123        for (uint32_t iTest = 0; iTest < cTests + RT_ELEMENTS(s_aSpecials); iTest += 1)
    39384124        {
    3939             RTFLOAT80U InVal = iTest < cTests ? RandR80Ex() : s_aSpecials[iTest - cTests];
     4125            RTFLOAT80U InVal = iTest < cTests ? RandR80Src(iTest) : s_aSpecials[iTest - cTests];
    39404126            if (RTFLOAT80U_IS_NORMAL(&InVal))
    39414127            {
  • trunk/src/libs/softfloat-3e/source/include/softfloat_types.h

    r94558 r94606  
    9696    /* softfloat_flag_inexact and friends. */
    9797    uint8_t exceptionFlags;
     98    /** Masked exceptions (only underflow is relevant). */
     99    uint8_t exceptionMask;
    98100    /* extF80: rounding precsision: 32, 64 or 80 */
    99101    uint8_t roundingPrecision;
    100102} softfloat_state_t;
    101 # define SOFTFLOAT_STATE_INIT_DEFAULTS() { softfloat_round_near_even, softfloat_tininess_afterRounding, 0, 80 }
     103# define SOFTFLOAT_STATE_INIT_DEFAULTS() { softfloat_round_near_even, softfloat_tininess_afterRounding, 0, 0x3f, 80 }
    102104#else
    103105# undef  VBOX_WITHOUT_SOFTFLOAT_GLOBALS
  • trunk/src/libs/softfloat-3e/source/s_roundPackToExtF80.c

    r94564 r94606  
    4040#include "internals.h"
    4141#include "softfloat.h"
     42#include <iprt/types.h> /* VBox: RTFLOAT80U_EXP_BIAS_UNDERFLOW_ADJUST */
     43//#include <iprt/assert.h>
    4244
    4345extFloat80_t
     
    5759    struct uint64_extra sig64Extra;
    5860    union { struct extFloat80M s; extFloat80_t f; } uZ;
     61    //RTAssertMsg2("softfloat_roundPackToExtF80: exp=%d sig=%RX64 sigExtra=%RX64 rp=%d\n", exp, sig, sigExtra, roundingPrecision);
    5962
    6063    /*------------------------------------------------------------------------
     
    8790            /*----------------------------------------------------------------
    8891            *----------------------------------------------------------------*/
     92            bool fUnmaskedUnderflow = false;                                                /* VBox: unmasked underflow bias */
    8993            isTiny =
    9094                   (softfloat_detectTininess
     
    9296                || (exp < 0)
    9397                || (sig <= (uint64_t) (sig + roundIncrement));
    94             sig = softfloat_shiftRightJam64( sig, 1 - exp );
     98            if (    (pState->exceptionMask & softfloat_flag_underflow)                      /* VBox: unmasked underflow bias */
     99                 || (exp == -63 && sig == 0 && sigExtra == 0) /* zero */ ) {                /* VBox: unmasked underflow bias */
     100                sig = softfloat_shiftRightJam64(sig, 1 - exp);
     101            } else {                                                                        /* VBox: unmasked underflow bias */
     102                //RTAssertMsg2("softfloat_roundPackToExtF80: #UE - bias adj: %d -> %d; sig=%#RX64\n", exp, exp + RTFLOAT80U_EXP_BIAS_UNDERFLOW_ADJUST, sig); /* VBox: unmasked underflow bias */
     103                softfloat_raiseFlags( softfloat_flag_underflow SOFTFLOAT_STATE_ARG_COMMA ); /* VBox: unmasked underflow bias */
     104                exp += RTFLOAT80U_EXP_BIAS_UNDERFLOW_ADJUST;                                /* VBox: unmasked underflow bias */
     105                fUnmaskedUnderflow = true;                                                  /* VBox: unmasked underflow bias */
     106            }                                                                               /* VBox: unmasked underflow bias */
     107            uint64_t const uOldSig = sig; /* VBox */
    95108            roundBits = sig & roundMask;
    96109            if ( roundBits ) {
    97110                if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow SOFTFLOAT_STATE_ARG_COMMA );
    98111                softfloat_exceptionFlags |= softfloat_flag_inexact;
    99                 if ( roundIncrement ) softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox */
    100112#ifdef SOFTFLOAT_ROUND_ODD
    101113                if ( roundingMode == softfloat_round_odd ) {
     
    105117            }
    106118            sig += roundIncrement;
    107             exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0);
     119            if ( !fUnmaskedUnderflow ) {                                /* VBox: unmasked underflow bias */
     120                exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0);
     121            }                                                           /* VBox: unmasked underflow bias */
    108122            roundIncrement = roundMask + 1;
    109123            if ( roundNearEven && (roundBits<<1 == roundIncrement) ) {
     
    111125            }
    112126            sig &= ~roundMask;
     127            if ( sig > uOldSig ) {                                      /* VBox: C1 */
     128                softfloat_exceptionFlags |= softfloat_flag_c1;          /* VBox: C1 */
     129                //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #1\n"); /* VBox: C1 */
     130            }                                                           /* VBox: C1 */
    113131            goto packReturn;
    114132        }
     
    122140    /*------------------------------------------------------------------------
    123141    *------------------------------------------------------------------------*/
    124     { /* VBox*/
    125     uint64_t const uOldSig = sig; /* VBox */
     142    {                                                                   /* VBox: C1 */
     143    uint64_t const uOldSig = sig;                                       /* VBox: C1 */
    126144    if ( roundBits ) {
    127145        softfloat_exceptionFlags |= softfloat_flag_inexact;
     
    129147        if ( roundingMode == softfloat_round_odd ) {
    130148            sig = (sig & ~roundMask) | (roundMask + 1);
    131             if ( sig > uOldSig ) softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox */
     149            if ( sig > uOldSig ) {                                      /* VBox: C1 */
     150                softfloat_exceptionFlags |= softfloat_flag_c1;          /* VBox: C1 */
     151                //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #2\n"); /* VBox: C1 */
     152            }                                                           /* VBox: C1 */
    132153            goto packReturn;
    133154        }
     
    138159        ++exp;
    139160        sig = UINT64_C( 0x8000000000000000 );
    140         softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox */
     161        softfloat_exceptionFlags |= softfloat_flag_c1;                  /* VBox: C1 */
     162        //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #3\n");         /* VBox: C1 */
    141163    }
    142164    roundIncrement = roundMask + 1;
     
    145167    }
    146168    sig &= ~roundMask;
    147     if ( sig > uOldSig ) softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox */
     169    if ( sig > uOldSig ) {                                              /* VBox: C1 */
     170        softfloat_exceptionFlags |= softfloat_flag_c1;                  /* VBox: C1 */
     171        //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #4\n");         /* VBox: C1 */
     172    }                                                                   /* VBox: C1 */
    148173    goto packReturn;
    149     } /* VBox */
     174    }                                                                   /* VBox: C1 */
    150175    /*------------------------------------------------------------------------
    151176    *------------------------------------------------------------------------*/
     
    164189            /*----------------------------------------------------------------
    165190            *----------------------------------------------------------------*/
     191            bool fUnmaskedUnderflow = false;                                                /* VBox: unmasked underflow bias */
    166192            isTiny =
    167193                   (softfloat_detectTininess
     
    170196                || ! doIncrement
    171197                || (sig < UINT64_C( 0xFFFFFFFFFFFFFFFF ));
    172             sig64Extra =
    173                 softfloat_shiftRightJam64Extra( sig, sigExtra, 1 - exp );
    174             exp = 0;
    175             sig = sig64Extra.v;
    176             sigExtra = sig64Extra.extra;
     198            if (    (pState->exceptionMask & softfloat_flag_underflow)                      /* VBox: unmasked underflow bias */
     199                 || (exp == -63 && sig == 0 && sigExtra == 0) /* zero */ ) {                /* VBox: unmasked underflow bias */
     200                sig64Extra =
     201                    softfloat_shiftRightJam64Extra( sig, sigExtra, 1 - exp );
     202                exp = 0;
     203                sig = sig64Extra.v;
     204                sigExtra = sig64Extra.extra;
     205            } else {                                                                        /* VBox: unmasked underflow bias */
     206                //RTAssertMsg2("softfloat_roundPackToExtF80: #UE/80 - bias adj: %d -> %d; sig=%#RX64'%016RX64\n", exp, exp + RTFLOAT80U_EXP_BIAS_UNDERFLOW_ADJUST, sig, sigExtra); /* VBox: unmasked underflow bias */
     207                softfloat_raiseFlags( softfloat_flag_underflow SOFTFLOAT_STATE_ARG_COMMA ); /* VBox: unmasked underflow bias */
     208                exp += RTFLOAT80U_EXP_BIAS_UNDERFLOW_ADJUST;                                /* VBox: unmasked underflow bias */
     209                fUnmaskedUnderflow = true;                                                  /* VBox: unmasked underflow bias */
     210            }                                                                               /* VBox: unmasked underflow bias */
    177211            if ( sigExtra ) {
    178212                if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow SOFTFLOAT_STATE_ARG_COMMA );
     
    195229            }
    196230            if ( doIncrement ) {
    197                 softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox */
     231                softfloat_exceptionFlags |= softfloat_flag_c1;              /* VBox: C1 */
     232                //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #5\n");     /* VBox: C1 */
    198233                ++sig;
    199234                sig &=
     
    201236                         (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
    202237                              & roundNearEven);
    203                 exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0);
     238                if ( fUnmaskedUnderflow ) {                                 /* VBox: unmasked underflow bias */
     239                    exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0);
     240                } else if ((sig & UINT64_C( 0x8000000000000000 )) != 0) {   /* VBox: unmasked underflow bias */
     241                    exp++;                                                  /* VBox: unmasked underflow bias */
     242                }                                                           /* VBox: unmasked underflow bias */
    204243            }
    205244            goto packReturn;
     
    225264                exp = 0x7FFF;
    226265                sig = UINT64_C( 0x8000000000000000 );
     266                softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox: C1 - Returning infinity means we've rounded up. */
     267                //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #6\n");
     268
     269                /* VBox: HACK ALERT! Some utterly weird behaviour, found with 'fadd 0,max', precision < 64 and rounding away from 0. */
     270                if ( !(pState->exceptionMask & softfloat_flag_overflow) ) /* VBox */
     271                    exp = 8191; /* => -8192 */                            /* VBox */
    227272            } else {
    228273                exp = 0x7FFE;
     
    249294            ++exp;
    250295            sig = UINT64_C( 0x8000000000000000 );
    251             softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox */
     296            softfloat_exceptionFlags |= softfloat_flag_c1;              /* VBox: C1 */
     297            //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #7\n");     /* VBox: C1 */
    252298        } else {
    253299            sig &=
     
    255301                     (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
    256302                          & roundNearEven);
    257             if ( sig > uOldSig ) softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox */
     303            if ( sig > uOldSig ) {                                      /* VBox: C1 */
     304                softfloat_exceptionFlags |= softfloat_flag_c1;          /* VBox: C1 */
     305                //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #8\n"); /* VBox: C1 */
     306            }
    258307        }
    259308    }
Note: See TracChangeset for help on using the changeset viewer.

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