mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-27 12:23:53 -06:00
softfloat: Inline pickNaN
Inline pickNaN into its only caller. This makes one assert redundant with the immediately preceding IF. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-id: 20241203203949.483774-9-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
1b34f934dd
commit
04cbb4acc6
2 changed files with 73 additions and 105 deletions
|
@ -39,25 +39,89 @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
|
||||||
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
|
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
|
||||||
float_status *s)
|
float_status *s)
|
||||||
{
|
{
|
||||||
|
int cmp, which;
|
||||||
|
|
||||||
if (is_snan(a->cls) || is_snan(b->cls)) {
|
if (is_snan(a->cls) || is_snan(b->cls)) {
|
||||||
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
|
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->default_nan_mode) {
|
if (s->default_nan_mode) {
|
||||||
parts_default_nan(a, s);
|
parts_default_nan(a, s);
|
||||||
} else {
|
return a;
|
||||||
int cmp = frac_cmp(a, b);
|
}
|
||||||
|
|
||||||
|
cmp = frac_cmp(a, b);
|
||||||
if (cmp == 0) {
|
if (cmp == 0) {
|
||||||
cmp = a->sign < b->sign;
|
cmp = a->sign < b->sign;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pickNaN(a->cls, b->cls, cmp > 0, s)) {
|
switch (s->float_2nan_prop_rule) {
|
||||||
|
case float_2nan_prop_s_ab:
|
||||||
|
if (is_snan(a->cls)) {
|
||||||
|
which = 0;
|
||||||
|
} else if (is_snan(b->cls)) {
|
||||||
|
which = 1;
|
||||||
|
} else if (is_qnan(a->cls)) {
|
||||||
|
which = 0;
|
||||||
|
} else {
|
||||||
|
which = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case float_2nan_prop_s_ba:
|
||||||
|
if (is_snan(b->cls)) {
|
||||||
|
which = 1;
|
||||||
|
} else if (is_snan(a->cls)) {
|
||||||
|
which = 0;
|
||||||
|
} else if (is_qnan(b->cls)) {
|
||||||
|
which = 1;
|
||||||
|
} else {
|
||||||
|
which = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case float_2nan_prop_ab:
|
||||||
|
which = is_nan(a->cls) ? 0 : 1;
|
||||||
|
break;
|
||||||
|
case float_2nan_prop_ba:
|
||||||
|
which = is_nan(b->cls) ? 1 : 0;
|
||||||
|
break;
|
||||||
|
case float_2nan_prop_x87:
|
||||||
|
/*
|
||||||
|
* This implements x87 NaN propagation rules:
|
||||||
|
* SNaN + QNaN => return the QNaN
|
||||||
|
* two SNaNs => return the one with the larger significand, silenced
|
||||||
|
* two QNaNs => return the one with the larger significand
|
||||||
|
* SNaN and a non-NaN => return the SNaN, silenced
|
||||||
|
* QNaN and a non-NaN => return the QNaN
|
||||||
|
*
|
||||||
|
* If we get down to comparing significands and they are the same,
|
||||||
|
* return the NaN with the positive sign bit (if any).
|
||||||
|
*/
|
||||||
|
if (is_snan(a->cls)) {
|
||||||
|
if (is_snan(b->cls)) {
|
||||||
|
which = cmp > 0 ? 0 : 1;
|
||||||
|
} else {
|
||||||
|
which = is_qnan(b->cls) ? 1 : 0;
|
||||||
|
}
|
||||||
|
} else if (is_qnan(a->cls)) {
|
||||||
|
if (is_snan(b->cls) || !is_qnan(b->cls)) {
|
||||||
|
which = 0;
|
||||||
|
} else {
|
||||||
|
which = cmp > 0 ? 0 : 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
which = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (which) {
|
||||||
a = b;
|
a = b;
|
||||||
}
|
}
|
||||||
if (is_snan(a->cls)) {
|
if (is_snan(a->cls)) {
|
||||||
parts_silence_nan(a, s);
|
parts_silence_nan(a, s);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -352,102 +352,6 @@ bool float32_is_signaling_nan(float32 a_, float_status *status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
|
||||||
| Select which NaN to propagate for a two-input operation.
|
|
||||||
| IEEE754 doesn't specify all the details of this, so the
|
|
||||||
| algorithm is target-specific.
|
|
||||||
| The routine is passed various bits of information about the
|
|
||||||
| two NaNs and should return 0 to select NaN a and 1 for NaN b.
|
|
||||||
| Note that signalling NaNs are always squashed to quiet NaNs
|
|
||||||
| by the caller, by calling floatXX_silence_nan() before
|
|
||||||
| returning them.
|
|
||||||
|
|
|
||||||
| aIsLargerSignificand is only valid if both a and b are NaNs
|
|
||||||
| of some kind, and is true if a has the larger significand,
|
|
||||||
| or if both a and b have the same significand but a is
|
|
||||||
| positive but b is negative. It is only needed for the x87
|
|
||||||
| tie-break rule.
|
|
||||||
*----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static int pickNaN(FloatClass a_cls, FloatClass b_cls,
|
|
||||||
bool aIsLargerSignificand, float_status *status)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* We guarantee not to require the target to tell us how to
|
|
||||||
* pick a NaN if we're always returning the default NaN.
|
|
||||||
* But if we're not in default-NaN mode then the target must
|
|
||||||
* specify via set_float_2nan_prop_rule().
|
|
||||||
*/
|
|
||||||
assert(!status->default_nan_mode);
|
|
||||||
|
|
||||||
switch (status->float_2nan_prop_rule) {
|
|
||||||
case float_2nan_prop_s_ab:
|
|
||||||
if (is_snan(a_cls)) {
|
|
||||||
return 0;
|
|
||||||
} else if (is_snan(b_cls)) {
|
|
||||||
return 1;
|
|
||||||
} else if (is_qnan(a_cls)) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case float_2nan_prop_s_ba:
|
|
||||||
if (is_snan(b_cls)) {
|
|
||||||
return 1;
|
|
||||||
} else if (is_snan(a_cls)) {
|
|
||||||
return 0;
|
|
||||||
} else if (is_qnan(b_cls)) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case float_2nan_prop_ab:
|
|
||||||
if (is_nan(a_cls)) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case float_2nan_prop_ba:
|
|
||||||
if (is_nan(b_cls)) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case float_2nan_prop_x87:
|
|
||||||
/*
|
|
||||||
* This implements x87 NaN propagation rules:
|
|
||||||
* SNaN + QNaN => return the QNaN
|
|
||||||
* two SNaNs => return the one with the larger significand, silenced
|
|
||||||
* two QNaNs => return the one with the larger significand
|
|
||||||
* SNaN and a non-NaN => return the SNaN, silenced
|
|
||||||
* QNaN and a non-NaN => return the QNaN
|
|
||||||
*
|
|
||||||
* If we get down to comparing significands and they are the same,
|
|
||||||
* return the NaN with the positive sign bit (if any).
|
|
||||||
*/
|
|
||||||
if (is_snan(a_cls)) {
|
|
||||||
if (is_snan(b_cls)) {
|
|
||||||
return aIsLargerSignificand ? 0 : 1;
|
|
||||||
}
|
|
||||||
return is_qnan(b_cls) ? 1 : 0;
|
|
||||||
} else if (is_qnan(a_cls)) {
|
|
||||||
if (is_snan(b_cls) || !is_qnan(b_cls)) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return aIsLargerSignificand ? 0 : 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Returns 1 if the double-precision floating-point value `a' is a quiet
|
| Returns 1 if the double-precision floating-point value `a' is a quiet
|
||||||
| NaN; otherwise returns 0.
|
| NaN; otherwise returns 0.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue