123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- From 7616e27c73841ac1e8fa031d843bde1325307bab Mon Sep 17 00:00:00 2001
- From: Chih-Min Chao <chihmin.chao@sifive.com>
- Date: Thu, 30 Jul 2020 02:52:23 -0700
- Subject: [PATCH 001/107] softfloat: add APIs to handle alternative sNaN
- propagation
- 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 if ft1 == sNaN && ft2 == sNaN
- The ieee754 spec allows both implementation and some architecture such
- as riscv choose differenct defintion 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>
- Message-Id: <1596102747-20226-3-git-send-email-chihmin.chao@sifive.com>
- ---
- fpu/softfloat.c | 92 +++++++++++++++++++++++++----------------
- include/fpu/softfloat.h | 6 +++
- 2 files changed, 63 insertions(+), 35 deletions(-)
- diff --git a/fpu/softfloat.c b/fpu/softfloat.c
- index 67cfa0fd82..edaa760310 100644
- --- a/fpu/softfloat.c
- +++ b/fpu/softfloat.c
- @@ -894,11 +894,16 @@ static FloatParts return_nan(FloatParts a, float_status *s)
- return a;
- }
-
- -static FloatParts pick_nan(FloatParts a, FloatParts b, float_status *s)
- +static void set_snan_flag(FloatParts a, FloatParts b, float_status *s)
- {
- if (is_snan(a.cls) || is_snan(b.cls)) {
- s->float_exception_flags |= float_flag_invalid;
- }
- +}
- +
- +static FloatParts pick_nan(FloatParts a, FloatParts b, float_status *s)
- +{
- + set_snan_flag(a, b, s);
-
- if (s->default_nan_mode) {
- return parts_default_nan(s);
- @@ -3091,23 +3096,32 @@ bfloat16 uint16_to_bfloat16(uint16_t a, float_status *status)
- * and minNumMag() from the IEEE-754 2008.
- */
- static FloatParts minmax_floats(FloatParts a, FloatParts b, bool ismin,
- - bool ieee, bool ismag, float_status *s)
- + bool ieee, bool ismag, bool issnan_prop,
- + float_status *s)
- {
- if (unlikely(is_nan(a.cls) || is_nan(b.cls))) {
- if (ieee) {
- /* Takes two floating-point values `a' and `b', one of
- * which is a NaN, and returns the appropriate NaN
- * result. If either `a' or `b' is a signaling NaN,
- - * the invalid exception is raised.
- + * the invalid exception is raised but the NaN
- + * propagation is 'shall'.
- */
- if (is_snan(a.cls) || is_snan(b.cls)) {
- - return pick_nan(a, b, s);
- - } else if (is_nan(a.cls) && !is_nan(b.cls)) {
- + if (issnan_prop) {
- + return pick_nan(a, b, s);
- + } else {
- + set_snan_flag(a, b, s);
- + }
- + }
- +
- + if (is_nan(a.cls) && !is_nan(b.cls)) {
- return b;
- } else if (is_nan(b.cls) && !is_nan(a.cls)) {
- return a;
- }
- }
- +
- return pick_nan(a, b, s);
- } else {
- int a_exp, b_exp;
- @@ -3161,56 +3175,64 @@ static FloatParts minmax_floats(FloatParts a, FloatParts b, bool ismin,
- }
- }
-
- -#define MINMAX(sz, name, ismin, isiee, ismag) \
- +#define MINMAX(sz, name, ismin, isiee, ismag, issnan_prop) \
- float ## sz float ## sz ## _ ## name(float ## sz a, float ## sz b, \
- float_status *s) \
- { \
- FloatParts pa = float ## sz ## _unpack_canonical(a, s); \
- FloatParts pb = float ## sz ## _unpack_canonical(b, s); \
- - FloatParts pr = minmax_floats(pa, pb, ismin, isiee, ismag, s); \
- + FloatParts pr = minmax_floats(pa, pb, ismin, isiee, ismag, \
- + issnan_prop, s); \
- \
- return float ## sz ## _round_pack_canonical(pr, s); \
- }
-
- -MINMAX(16, min, true, false, false)
- -MINMAX(16, minnum, true, true, false)
- -MINMAX(16, minnummag, true, true, true)
- -MINMAX(16, max, false, false, false)
- -MINMAX(16, maxnum, false, true, false)
- -MINMAX(16, maxnummag, false, true, true)
- -
- -MINMAX(32, min, true, false, false)
- -MINMAX(32, minnum, true, true, false)
- -MINMAX(32, minnummag, true, true, true)
- -MINMAX(32, max, false, false, false)
- -MINMAX(32, maxnum, false, true, false)
- -MINMAX(32, maxnummag, false, true, true)
- -
- -MINMAX(64, min, true, false, false)
- -MINMAX(64, minnum, true, true, false)
- -MINMAX(64, minnummag, true, true, true)
- -MINMAX(64, max, false, false, false)
- -MINMAX(64, maxnum, false, true, false)
- -MINMAX(64, maxnummag, false, true, true)
- +MINMAX(16, min, true, false, false, true)
- +MINMAX(16, minnum, true, true, false, true)
- +MINMAX(16, minnum_noprop, true, true, false, false)
- +MINMAX(16, minnummag, true, true, true, true)
- +MINMAX(16, max, false, false, false, true)
- +MINMAX(16, maxnum, false, true, false, true)
- +MINMAX(16, maxnum_noprop, false, true, false, false)
- +MINMAX(16, maxnummag, false, true, true, true)
- +
- +MINMAX(32, min, true, false, false, true)
- +MINMAX(32, minnum, true, true, false, true)
- +MINMAX(32, minnum_noprop, true, true, false, false)
- +MINMAX(32, minnummag, true, true, true, true)
- +MINMAX(32, max, false, false, false, true)
- +MINMAX(32, maxnum, false, true, false, true)
- +MINMAX(32, maxnum_noprop, false, true, false, false)
- +MINMAX(32, maxnummag, false, true, true, true)
- +
- +MINMAX(64, min, true, false, false, true)
- +MINMAX(64, minnum, true, true, false, true)
- +MINMAX(64, minnum_noprop, true, true, false, false)
- +MINMAX(64, minnummag, true, true, true, true)
- +MINMAX(64, max, false, false, false, true)
- +MINMAX(64, maxnum, false, true, false, true)
- +MINMAX(64, maxnum_noprop, false, true, false, false)
- +MINMAX(64, maxnummag, false, true, true, true)
-
- #undef MINMAX
-
- -#define BF16_MINMAX(name, ismin, isiee, ismag) \
- +#define BF16_MINMAX(name, ismin, isiee, ismag, issnan_prop) \
- bfloat16 bfloat16_ ## name(bfloat16 a, bfloat16 b, float_status *s) \
- { \
- FloatParts pa = bfloat16_unpack_canonical(a, s); \
- FloatParts pb = bfloat16_unpack_canonical(b, s); \
- - FloatParts pr = minmax_floats(pa, pb, ismin, isiee, ismag, s); \
- + FloatParts pr = minmax_floats(pa, pb, ismin, isiee, ismag, \
- + issnan_prop, s); \
- \
- return bfloat16_round_pack_canonical(pr, s); \
- }
-
- -BF16_MINMAX(min, true, false, false)
- -BF16_MINMAX(minnum, true, true, false)
- -BF16_MINMAX(minnummag, true, true, true)
- -BF16_MINMAX(max, false, false, false)
- -BF16_MINMAX(maxnum, false, true, false)
- -BF16_MINMAX(maxnummag, false, true, true)
- +BF16_MINMAX(min, true, false, false, true)
- +BF16_MINMAX(minnum, true, true, false, true)
- +BF16_MINMAX(minnummag, true, true, true, true)
- +BF16_MINMAX(max, false, false, false, true)
- +BF16_MINMAX(maxnum, false, true, false, true)
- +BF16_MINMAX(maxnummag, false, true, true, true)
-
- #undef BF16_MINMAX
-
- diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
- index 78ad5ca738..5cd7d44bc9 100644
- --- a/include/fpu/softfloat.h
- +++ b/include/fpu/softfloat.h
- @@ -240,6 +240,8 @@ float16 float16_minnum(float16, float16, float_status *status);
- float16 float16_maxnum(float16, float16, float_status *status);
- float16 float16_minnummag(float16, float16, float_status *status);
- float16 float16_maxnummag(float16, float16, float_status *status);
- +float16 float16_minnum_noprop(float16, float16, float_status *status);
- +float16 float16_maxnum_noprop(float16, float16, float_status *status);
- float16 float16_sqrt(float16, float_status *status);
- FloatRelation float16_compare(float16, float16, float_status *status);
- FloatRelation float16_compare_quiet(float16, float16, float_status *status);
- @@ -586,6 +588,8 @@ float32 float32_minnum(float32, float32, float_status *status);
- float32 float32_maxnum(float32, float32, float_status *status);
- float32 float32_minnummag(float32, float32, float_status *status);
- float32 float32_maxnummag(float32, float32, float_status *status);
- +float32 float32_minnum_noprop(float32, float32, float_status *status);
- +float32 float32_maxnum_noprop(float32, float32, float_status *status);
- bool float32_is_quiet_nan(float32, float_status *status);
- bool float32_is_signaling_nan(float32, float_status *status);
- float32 float32_silence_nan(float32, float_status *status);
- @@ -775,6 +779,8 @@ float64 float64_minnum(float64, float64, float_status *status);
- float64 float64_maxnum(float64, float64, float_status *status);
- float64 float64_minnummag(float64, float64, float_status *status);
- float64 float64_maxnummag(float64, float64, float_status *status);
- +float64 float64_minnum_noprop(float64, float64, float_status *status);
- +float64 float64_maxnum_noprop(float64, float64, float_status *status);
- bool float64_is_quiet_nan(float64 a, float_status *status);
- bool float64_is_signaling_nan(float64, float_status *status);
- float64 float64_silence_nan(float64, float_status *status);
- --
- 2.33.1
|