softfloat: Move minmax_flags to softfloat-parts.c.inc

Rename to parts$N_minmax.  Combine 3 bool arguments to a bitmask.
Introduce ftype_minmax functions as a common optimization point.
Fold bfloat16 expansions into the same macro as the other types.

Reviewed-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2020-11-14 16:52:38 -08:00
parent 37c954a1b9
commit e1c4667a9b
2 changed files with 152 additions and 126 deletions

View file

@ -938,3 +938,83 @@ static void partsN(uint_to_float)(FloatPartsN *p, uint64_t a,
p->frac_hi = a << shift;
}
}
/*
* Float min/max.
*/
static FloatPartsN *partsN(minmax)(FloatPartsN *a, FloatPartsN *b,
float_status *s, int flags)
{
int ab_mask = float_cmask(a->cls) | float_cmask(b->cls);
int a_exp, b_exp, cmp;
if (unlikely(ab_mask & float_cmask_anynan)) {
/*
* For minnum/maxnum, if one operand is a QNaN, and the other
* operand is numerical, then return numerical argument.
*/
if ((flags & minmax_isnum)
&& !(ab_mask & float_cmask_snan)
&& (ab_mask & ~float_cmask_qnan)) {
return is_nan(a->cls) ? b : a;
}
return parts_pick_nan(a, b, s);
}
a_exp = a->exp;
b_exp = b->exp;
if (unlikely(ab_mask != float_cmask_normal)) {
switch (a->cls) {
case float_class_normal:
break;
case float_class_inf:
a_exp = INT16_MAX;
break;
case float_class_zero:
a_exp = INT16_MIN;
break;
default:
g_assert_not_reached();
break;
}
switch (b->cls) {
case float_class_normal:
break;
case float_class_inf:
b_exp = INT16_MAX;
break;
case float_class_zero:
b_exp = INT16_MIN;
break;
default:
g_assert_not_reached();
break;
}
}
/* Compare magnitudes. */
cmp = a_exp - b_exp;
if (cmp == 0) {
cmp = frac_cmp(a, b);
}
/*
* Take the sign into account.
* For ismag, only do this if the magnitudes are equal.
*/
if (!(flags & minmax_ismag) || cmp == 0) {
if (a->sign != b->sign) {
/* For differing signs, the negative operand is less. */
cmp = a->sign ? -1 : 1;
} else if (a->sign) {
/* For two negative operands, invert the magnitude comparison. */
cmp = -cmp;
}
}
if (flags & minmax_ismin) {
cmp = -cmp;
}
return cmp < 0 ? b : a;
}