diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2020-10-22 15:22:55 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2021-05-16 07:13:51 -0500 |
commit | da10a9074a630c1b1cfa9df5f510bbfdd3f7d327 (patch) | |
tree | e73126150dad6c83486acaa1d20383877d94e65b /fpu/softfloat-parts.c.inc | |
parent | cb3ad0365fb17f679c69057f384f1f4928c19647 (diff) | |
download | qemu-da10a9074a630c1b1cfa9df5f510bbfdd3f7d327.zip qemu-da10a9074a630c1b1cfa9df5f510bbfdd3f7d327.tar.gz qemu-da10a9074a630c1b1cfa9df5f510bbfdd3f7d327.tar.bz2 |
softfloat: Move addsub_floats to softfloat-parts.c.inc
In preparation for implementing multiple sizes. Rename to parts_addsub,
split out parts_add/sub_normal for future reuse with muladd.
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 | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc index efdc724..cfce9f6 100644 --- a/fpu/softfloat-parts.c.inc +++ b/fpu/softfloat-parts.c.inc @@ -281,3 +281,84 @@ static void partsN(uncanon)(FloatPartsN *p, float_status *s, p->exp = exp; float_raise(flags, s); } + +/* + * Returns the result of adding or subtracting the values of the + * floating-point values `a' and `b'. The operation is performed + * according to the IEC/IEEE Standard for Binary Floating-Point + * Arithmetic. + */ +static FloatPartsN *partsN(addsub)(FloatPartsN *a, FloatPartsN *b, + float_status *s, bool subtract) +{ + bool b_sign = b->sign ^ subtract; + int ab_mask = float_cmask(a->cls) | float_cmask(b->cls); + + if (a->sign != b_sign) { + /* Subtraction */ + if (likely(ab_mask == float_cmask_normal)) { + if (parts_sub_normal(a, b)) { + return a; + } + /* Subtract was exact, fall through to set sign. */ + ab_mask = float_cmask_zero; + } + + if (ab_mask == float_cmask_zero) { + a->sign = s->float_rounding_mode == float_round_down; + return a; + } + + if (unlikely(ab_mask & float_cmask_anynan)) { + goto p_nan; + } + + if (ab_mask & float_cmask_inf) { + if (a->cls != float_class_inf) { + /* N - Inf */ + goto return_b; + } + if (b->cls != float_class_inf) { + /* Inf - N */ + return a; + } + /* Inf - Inf */ + float_raise(float_flag_invalid, s); + parts_default_nan(a, s); + return a; + } + } else { + /* Addition */ + if (likely(ab_mask == float_cmask_normal)) { + parts_add_normal(a, b); + return a; + } + + if (ab_mask == float_cmask_zero) { + return a; + } + + if (unlikely(ab_mask & float_cmask_anynan)) { + goto p_nan; + } + + if (ab_mask & float_cmask_inf) { + a->cls = float_class_inf; + return a; + } + } + + if (b->cls == float_class_zero) { + g_assert(a->cls == float_class_normal); + return a; + } + + g_assert(a->cls == float_class_zero); + g_assert(b->cls == float_class_normal); + return_b: + b->sign = b_sign; + return b; + + p_nan: + return parts_pick_nan(a, b, s); +} |