Skip to content

Commit

Permalink
softfloat: Move addsub_floats to softfloat-parts.c.inc
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Richard Henderson <[email protected]>
  • Loading branch information
rth7680 committed May 16, 2021
1 parent cb3ad03 commit da10a90
Show file tree
Hide file tree
Showing 3 changed files with 255 additions and 141 deletions.
62 changes: 62 additions & 0 deletions fpu/softfloat-parts-addsub.c.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Floating point arithmetic implementation
*
* The code in this source file is derived from release 2a of the SoftFloat
* IEC/IEEE Floating-point Arithmetic Package. Those parts of the code (and
* some later contributions) are provided under that license, as detailed below.
* It has subsequently been modified by contributors to the QEMU Project,
* so some portions are provided under:
* the SoftFloat-2a license
* the BSD license
* GPL-v2-or-later
*
* Any future contributions to this file after December 1st 2014 will be
* taken to be licensed under the Softfloat-2a license unless specifically
* indicated otherwise.
*/

static void partsN(add_normal)(FloatPartsN *a, FloatPartsN *b)
{
int exp_diff = a->exp - b->exp;

if (exp_diff > 0) {
frac_shrjam(b, exp_diff);
} else if (exp_diff < 0) {
frac_shrjam(a, -exp_diff);
a->exp = b->exp;
}

if (frac_add(a, a, b)) {
frac_shrjam(a, 1);
a->frac_hi |= DECOMPOSED_IMPLICIT_BIT;
a->exp += 1;
}
}

static bool partsN(sub_normal)(FloatPartsN *a, FloatPartsN *b)
{
int exp_diff = a->exp - b->exp;
int shift;

if (exp_diff > 0) {
frac_shrjam(b, exp_diff);
frac_sub(a, a, b);
} else if (exp_diff < 0) {
a->exp = b->exp;
a->sign ^= 1;
frac_shrjam(a, -exp_diff);
frac_sub(a, b, a);
} else if (frac_sub(a, a, b)) {
/* Overflow means that A was less than B. */
frac_neg(a);
a->sign ^= 1;
}

shift = frac_normalize(a);
if (likely(shift < N)) {
a->exp -= shift;
return true;
}
a->cls = float_class_zero;
return false;
}
81 changes: 81 additions & 0 deletions fpu/softfloat-parts.c.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Loading

0 comments on commit da10a90

Please sign in to comment.