aboutsummaryrefslogtreecommitdiff
path: root/fpu/softfloat.c
diff options
context:
space:
mode:
authorChih-Min Chao <chihmin.chao@sifive.com>2021-10-22 00:08:45 +0800
committerAlistair Francis <alistair.francis@wdc.com>2021-10-29 16:55:45 +1000
commit0e9030376e1a8eb6d15cb5e69dffa09a6ff16b92 (patch)
tree62971887576fbe63cded429e387ce35127ffa79b /fpu/softfloat.c
parent50d160876414e91e51ac718ac6edea6dbadf4694 (diff)
downloadqemu-0e9030376e1a8eb6d15cb5e69dffa09a6ff16b92.zip
qemu-0e9030376e1a8eb6d15cb5e69dffa09a6ff16b92.tar.gz
qemu-0e9030376e1a8eb6d15cb5e69dffa09a6ff16b92.tar.bz2
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>
Diffstat (limited to 'fpu/softfloat.c')
-rw-r--r--fpu/softfloat.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 6e769f9..9a28720 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -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)