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:
Chih-Min Chao 2021-10-22 00:08:45 +08:00 committed by Alistair Francis
parent 50d1608764
commit 0e9030376e
3 changed files with 46 additions and 8 deletions

View file

@ -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)