qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

softfloat: Support float_round_to_odd more places

Previously this was only supported for roundAndPackFloat64.

New support in round_canonical, round_to_int, float128_round_to_int,
roundAndPackFloat32, roundAndPackInt32, roundAndPackInt64,
roundAndPackUint64. This does not include any of the floatx80 routines,
as we do not have users for that rounding mode there.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20190215170225.15537-1-richard.henderson@linaro.org>
Tested-by: David Hildenbrand <david@redhat.com>
[AJB: add missing break]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

authored by

Richard Henderson and committed by
Alex Bennée
5d64abb3 dc3f8a9d

+94 -14
+60 -5
fpu/softfloat.c
··· 696 696 static FloatParts round_canonical(FloatParts p, float_status *s, 697 697 const FloatFmt *parm) 698 698 { 699 + const uint64_t frac_lsb = parm->frac_lsb; 699 700 const uint64_t frac_lsbm1 = parm->frac_lsbm1; 700 701 const uint64_t round_mask = parm->round_mask; 701 702 const uint64_t roundeven_mask = parm->roundeven_mask; ··· 730 731 case float_round_down: 731 732 inc = p.sign ? round_mask : 0; 732 733 overflow_norm = !p.sign; 734 + break; 735 + case float_round_to_odd: 736 + overflow_norm = true; 737 + inc = frac & frac_lsb ? 0 : round_mask; 733 738 break; 734 739 default: 735 740 g_assert_not_reached(); ··· 778 783 shift64RightJamming(frac, 1 - exp, &frac); 779 784 if (frac & round_mask) { 780 785 /* Need to recompute round-to-even. */ 781 - if (s->float_rounding_mode == float_round_nearest_even) { 786 + switch (s->float_rounding_mode) { 787 + case float_round_nearest_even: 782 788 inc = ((frac & roundeven_mask) != frac_lsbm1 783 789 ? frac_lsbm1 : 0); 790 + break; 791 + case float_round_to_odd: 792 + inc = frac & frac_lsb ? 0 : round_mask; 793 + break; 784 794 } 785 795 flags |= float_flag_inexact; 786 796 frac += inc; ··· 1988 1998 case float_round_down: 1989 1999 one = a.sign; 1990 2000 break; 2001 + case float_round_to_odd: 2002 + one = true; 2003 + break; 1991 2004 default: 1992 2005 g_assert_not_reached(); 1993 2006 } ··· 2020 2033 break; 2021 2034 case float_round_down: 2022 2035 inc = a.sign ? rnd_mask : 0; 2036 + break; 2037 + case float_round_to_odd: 2038 + inc = a.frac & frac_lsb ? 0 : rnd_mask; 2023 2039 break; 2024 2040 default: 2025 2041 g_assert_not_reached(); ··· 3313 3329 break; 3314 3330 case float_round_down: 3315 3331 roundIncrement = zSign ? 0x7f : 0; 3332 + break; 3333 + case float_round_to_odd: 3334 + roundIncrement = absZ & 0x80 ? 0 : 0x7f; 3316 3335 break; 3317 3336 default: 3318 3337 abort(); ··· 3368 3387 case float_round_down: 3369 3388 increment = zSign && absZ1; 3370 3389 break; 3390 + case float_round_to_odd: 3391 + increment = !(absZ0 & 1) && absZ1; 3392 + break; 3371 3393 default: 3372 3394 abort(); 3373 3395 } ··· 3423 3445 break; 3424 3446 case float_round_down: 3425 3447 increment = zSign && absZ1; 3448 + break; 3449 + case float_round_to_odd: 3450 + increment = !(absZ0 & 1) && absZ1; 3426 3451 break; 3427 3452 default: 3428 3453 abort(); ··· 3526 3551 case float_round_down: 3527 3552 roundIncrement = zSign ? 0x7f : 0; 3528 3553 break; 3554 + case float_round_to_odd: 3555 + roundIncrement = zSig & 0x80 ? 0 : 0x7f; 3556 + break; 3529 3557 default: 3530 3558 abort(); 3531 3559 break; ··· 3536 3564 || ( ( zExp == 0xFD ) 3537 3565 && ( (int32_t) ( zSig + roundIncrement ) < 0 ) ) 3538 3566 ) { 3567 + bool overflow_to_inf = roundingMode != float_round_to_odd && 3568 + roundIncrement != 0; 3539 3569 float_raise(float_flag_overflow | float_flag_inexact, status); 3540 - return packFloat32( zSign, 0xFF, - ( roundIncrement == 0 )); 3570 + return packFloat32(zSign, 0xFF, -!overflow_to_inf); 3541 3571 } 3542 3572 if ( zExp < 0 ) { 3543 3573 if (status->flush_to_zero) { ··· 3554 3584 roundBits = zSig & 0x7F; 3555 3585 if (isTiny && roundBits) { 3556 3586 float_raise(float_flag_underflow, status); 3587 + } 3588 + if (roundingMode == float_round_to_odd) { 3589 + /* 3590 + * For round-to-odd case, the roundIncrement depends on 3591 + * zSig which just changed. 3592 + */ 3593 + roundIncrement = zSig & 0x80 ? 0 : 0x7f; 3557 3594 } 3558 3595 } 3559 3596 } ··· 6987 7024 add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low); 6988 7025 } 6989 7026 break; 7027 + case float_round_to_odd: 7028 + /* 7029 + * Note that if lastBitMask == 0, the last bit is the lsb 7030 + * of high, and roundBitsMask == -1. 7031 + */ 7032 + if ((lastBitMask ? z.low & lastBitMask : z.high & 1) == 0) { 7033 + add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low); 7034 + } 7035 + break; 6990 7036 default: 6991 7037 abort(); 6992 7038 } ··· 6998 7044 status->float_exception_flags |= float_flag_inexact; 6999 7045 aSign = extractFloat128Sign( a ); 7000 7046 switch (status->float_rounding_mode) { 7001 - case float_round_nearest_even: 7047 + case float_round_nearest_even: 7002 7048 if ( ( aExp == 0x3FFE ) 7003 7049 && ( extractFloat128Frac0( a ) 7004 7050 | extractFloat128Frac1( a ) ) ··· 7011 7057 return packFloat128(aSign, 0x3FFF, 0, 0); 7012 7058 } 7013 7059 break; 7014 - case float_round_down: 7060 + case float_round_down: 7015 7061 return 7016 7062 aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) 7017 7063 : packFloat128( 0, 0, 0, 0 ); 7018 - case float_round_up: 7064 + case float_round_up: 7019 7065 return 7020 7066 aSign ? packFloat128( 1, 0, 0, 0 ) 7021 7067 : packFloat128( 0, 0x3FFF, 0, 0 ); 7068 + 7069 + case float_round_to_odd: 7070 + return packFloat128(aSign, 0x3FFF, 0, 0); 7022 7071 } 7023 7072 return packFloat128( aSign, 0, 0, 0 ); 7024 7073 } ··· 7047 7096 break; 7048 7097 case float_round_down: 7049 7098 if (extractFloat128Sign(z)) { 7099 + z.high |= (a.low != 0); 7100 + z.high += roundBitsMask; 7101 + } 7102 + break; 7103 + case float_round_to_odd: 7104 + if ((z.high & lastBitMask) == 0) { 7050 7105 z.high |= (a.low != 0); 7051 7106 z.high += roundBitsMask; 7052 7107 }
+34 -9
tests/fp/fp-test.c
··· 125 125 126 126 static bool blacklisted(unsigned op, int rmode) 127 127 { 128 - /* odd has only been implemented for a few 128-bit ops */ 128 + /* odd has not been implemented for any 80-bit ops */ 129 129 if (rmode == softfloat_round_odd) { 130 130 switch (op) { 131 - case F128_ADD: 132 - case F128_SUB: 133 - case F128_MUL: 134 - case F128_DIV: 135 - case F128_TO_F64: 136 - case F128_SQRT: 137 - return false; 138 - default: 131 + case EXTF80_TO_UI32: 132 + case EXTF80_TO_UI64: 133 + case EXTF80_TO_I32: 134 + case EXTF80_TO_I64: 135 + case EXTF80_TO_UI32_R_MINMAG: 136 + case EXTF80_TO_UI64_R_MINMAG: 137 + case EXTF80_TO_I32_R_MINMAG: 138 + case EXTF80_TO_I64_R_MINMAG: 139 + case EXTF80_TO_F16: 140 + case EXTF80_TO_F32: 141 + case EXTF80_TO_F64: 142 + case EXTF80_TO_F128: 143 + case EXTF80_ROUNDTOINT: 144 + case EXTF80_ADD: 145 + case EXTF80_SUB: 146 + case EXTF80_MUL: 147 + case EXTF80_DIV: 148 + case EXTF80_REM: 149 + case EXTF80_SQRT: 150 + case EXTF80_EQ: 151 + case EXTF80_LE: 152 + case EXTF80_LT: 153 + case EXTF80_EQ_SIGNALING: 154 + case EXTF80_LE_QUIET: 155 + case EXTF80_LT_QUIET: 156 + case UI32_TO_EXTF80: 157 + case UI64_TO_EXTF80: 158 + case I32_TO_EXTF80: 159 + case I64_TO_EXTF80: 160 + case F16_TO_EXTF80: 161 + case F32_TO_EXTF80: 162 + case F64_TO_EXTF80: 163 + case F128_TO_EXTF80: 139 164 return true; 140 165 } 141 166 }