mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 00:03:54 -06:00
softfloat: add APIs to handle alternative sNaN propagation for fmax/fmin
For "fmax/fmin ft0, ft1, ft2" and if one of the inputs is sNaN, The original logic: Return NaN and set invalid flag if ft1 == sNaN || ft2 == sNan. The alternative path: Set invalid flag if ft1 == sNaN || ft2 == sNaN. Return NaN only if ft1 == NaN && ft2 == NaN. The IEEE 754 spec allows both implementation and some architecture such as riscv choose different defintions in two spec versions. (riscv-spec-v2.2 use original version, riscv-spec-20191213 changes to alternative) Signed-off-by: Chih-Min Chao <chihmin.chao@sifive.com> Signed-off-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20211021160847.2748577-2-frank.chang@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
50d1608764
commit
0e9030376e
3 changed files with 46 additions and 8 deletions
|
@ -1219,14 +1219,35 @@ static FloatPartsN *partsN(minmax)(FloatPartsN *a, FloatPartsN *b,
|
|||
|
||||
if (unlikely(ab_mask & float_cmask_anynan)) {
|
||||
/*
|
||||
* For minnum/maxnum, if one operand is a QNaN, and the other
|
||||
* For minNum/maxNum (IEEE 754-2008)
|
||||
* or minimumNumber/maximumNumber (IEEE 754-2019),
|
||||
* if one operand is a QNaN, and the other
|
||||
* operand is numerical, then return numerical argument.
|
||||
*/
|
||||
if ((flags & minmax_isnum)
|
||||
if ((flags & (minmax_isnum | minmax_isnumber))
|
||||
&& !(ab_mask & float_cmask_snan)
|
||||
&& (ab_mask & ~float_cmask_qnan)) {
|
||||
return is_nan(a->cls) ? b : a;
|
||||
}
|
||||
|
||||
/*
|
||||
* In IEEE 754-2019, minNum, maxNum, minNumMag and maxNumMag
|
||||
* are removed and replaced with minimum, minimumNumber, maximum
|
||||
* and maximumNumber.
|
||||
* minimumNumber/maximumNumber behavior for SNaN is changed to:
|
||||
* If both operands are NaNs, a QNaN is returned.
|
||||
* If either operand is a SNaN,
|
||||
* an invalid operation exception is signaled,
|
||||
* but unless both operands are NaNs,
|
||||
* the SNaN is otherwise ignored and not converted to a QNaN.
|
||||
*/
|
||||
if ((flags & minmax_isnumber)
|
||||
&& (ab_mask & float_cmask_snan)
|
||||
&& (ab_mask & ~float_cmask_anynan)) {
|
||||
float_raise(float_flag_invalid, s);
|
||||
return is_nan(a->cls) ? b : a;
|
||||
}
|
||||
|
||||
return parts_pick_nan(a, b, s);
|
||||
}
|
||||
|
||||
|
|
|
@ -436,6 +436,11 @@ enum {
|
|||
minmax_isnum = 2,
|
||||
/* Set for the IEEE 754-2008 minNumMag() and minNumMag() operations. */
|
||||
minmax_ismag = 4,
|
||||
/*
|
||||
* Set for the IEEE 754-2019 minimumNumber() and maximumNumber()
|
||||
* operations.
|
||||
*/
|
||||
minmax_isnumber = 8,
|
||||
};
|
||||
|
||||
/* Simple helpers for checking if, or what kind of, NaN we have */
|
||||
|
@ -3927,12 +3932,14 @@ static float128 float128_minmax(float128 a, float128 b,
|
|||
{ return type##_minmax(a, b, s, flags); }
|
||||
|
||||
#define MINMAX_2(type) \
|
||||
MINMAX_1(type, max, 0) \
|
||||
MINMAX_1(type, maxnum, minmax_isnum) \
|
||||
MINMAX_1(type, maxnummag, minmax_isnum | minmax_ismag) \
|
||||
MINMAX_1(type, min, minmax_ismin) \
|
||||
MINMAX_1(type, minnum, minmax_ismin | minmax_isnum) \
|
||||
MINMAX_1(type, minnummag, minmax_ismin | minmax_isnum | minmax_ismag)
|
||||
MINMAX_1(type, max, 0) \
|
||||
MINMAX_1(type, maxnum, minmax_isnum) \
|
||||
MINMAX_1(type, maxnummag, minmax_isnum | minmax_ismag) \
|
||||
MINMAX_1(type, maximum_number, minmax_isnumber) \
|
||||
MINMAX_1(type, min, minmax_ismin) \
|
||||
MINMAX_1(type, minnum, minmax_ismin | minmax_isnum) \
|
||||
MINMAX_1(type, minnummag, minmax_ismin | minmax_isnum | minmax_ismag) \
|
||||
MINMAX_1(type, minimum_number, minmax_ismin | minmax_isnumber) \
|
||||
|
||||
MINMAX_2(float16)
|
||||
MINMAX_2(bfloat16)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue