diff options
author | Richard Henderson | 2020-11-11 21:50:44 +0100 |
---|---|---|
committer | Richard Henderson | 2021-05-16 14:13:51 +0200 |
commit | ec961b81b40a70ff9352f3a1ecc43db610afd2aa (patch) | |
tree | d285c042a1bf85e30d9e7c4d74a5aade2b1d5eec /fpu/softfloat-parts.c.inc | |
parent | softfloat: Introduce sh[lr]_double primitives (diff) | |
download | qemu-ec961b81b40a70ff9352f3a1ecc43db610afd2aa.tar.gz qemu-ec961b81b40a70ff9352f3a1ecc43db610afd2aa.tar.xz qemu-ec961b81b40a70ff9352f3a1ecc43db610afd2aa.zip |
softfloat: Move div_floats to softfloat-parts.c.inc
Rename to parts$N_div.
Implement float128_div with FloatParts128.
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'fpu/softfloat-parts.c.inc')
-rw-r--r-- | fpu/softfloat-parts.c.inc | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc index a203811299..f8165d92f9 100644 --- a/fpu/softfloat-parts.c.inc +++ b/fpu/softfloat-parts.c.inc @@ -539,3 +539,58 @@ static FloatPartsN *partsN(muladd)(FloatPartsN *a, FloatPartsN *b, parts_default_nan(a, s); return a; } + +/* + * Returns the result of dividing the floating-point value `a' by the + * corresponding value `b'. The operation is performed according to + * the IEC/IEEE Standard for Binary Floating-Point Arithmetic. + */ +static FloatPartsN *partsN(div)(FloatPartsN *a, FloatPartsN *b, + float_status *s) +{ + int ab_mask = float_cmask(a->cls) | float_cmask(b->cls); + bool sign = a->sign ^ b->sign; + + if (likely(ab_mask == float_cmask_normal)) { + a->sign = sign; + a->exp -= b->exp + frac_div(a, b); + return a; + } + + /* 0/0 or Inf/Inf => NaN */ + if (unlikely(ab_mask == float_cmask_zero) || + unlikely(ab_mask == float_cmask_inf)) { + float_raise(float_flag_invalid, s); + parts_default_nan(a, s); + return a; + } + + /* All the NaN cases */ + if (unlikely(ab_mask & float_cmask_anynan)) { + return parts_pick_nan(a, b, s); + } + + a->sign = sign; + + /* Inf / X */ + if (a->cls == float_class_inf) { + return a; + } + + /* 0 / X */ + if (a->cls == float_class_zero) { + return a; + } + + /* X / Inf */ + if (b->cls == float_class_inf) { + a->cls = float_class_zero; + return a; + } + + /* X / 0 => Inf */ + g_assert(b->cls == float_class_zero); + float_raise(float_flag_divbyzero, s); + a->cls = float_class_inf; + return a; +} |