diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc index bbeadaa189..a9f268fcab 100644 --- a/fpu/softfloat-parts.c.inc +++ b/fpu/softfloat-parts.c.inc @@ -214,18 +214,35 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s, p->frac_lo &= ~round_mask; } } else if (unlikely(exp >= exp_max)) { - flags |= float_flag_overflow | float_flag_inexact; - if (overflow_norm) { + flags |= float_flag_overflow; + if (s->rebias_overflow) { + exp -= fmt->exp_re_bias; + } else if (overflow_norm) { + flags |= float_flag_inexact; exp = exp_max - 1; frac_allones(p); p->frac_lo &= ~round_mask; } else { + flags |= float_flag_inexact; p->cls = float_class_inf; exp = exp_max; frac_clear(p); } } frac_shr(p, frac_shift); + } else if (unlikely(s->rebias_underflow)) { + flags |= float_flag_underflow; + exp += fmt->exp_re_bias; + if (p->frac_lo & round_mask) { + flags |= float_flag_inexact; + if (frac_addi(p, p, inc)) { + frac_shr(p, 1); + p->frac_hi |= DECOMPOSED_IMPLICIT_BIT; + exp++; + } + p->frac_lo &= ~round_mask; + } + frac_shr(p, frac_shift); } else if (s->flush_to_zero) { flags |= float_flag_output_denormal; p->cls = float_class_zero; diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 4a871ef2a1..c7454c3eb1 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -521,6 +521,7 @@ typedef struct { typedef struct { int exp_size; int exp_bias; + int exp_re_bias; int exp_max; int frac_size; int frac_shift; @@ -532,6 +533,7 @@ typedef struct { #define FLOAT_PARAMS_(E) \ .exp_size = E, \ .exp_bias = ((1 << E) - 1) >> 1, \ + .exp_re_bias = (1 << (E - 1)) + (1 << (E - 2)), \ .exp_max = (1 << E) - 1 #define FLOAT_PARAMS(E, F) \ diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h index 7a6ea881d8..0884ec4ef7 100644 --- a/include/fpu/softfloat-types.h +++ b/include/fpu/softfloat-types.h @@ -195,6 +195,10 @@ typedef struct float_status { bool snan_bit_is_one; bool use_first_nan; bool no_signaling_nans; + /* should overflowed results subtract re_bias to its exponent? */ + bool rebias_overflow; + /* should underflowed results add re_bias to its exponent? */ + bool rebias_underflow; } float_status; #endif /* SOFTFLOAT_TYPES_H */