From e2fb4b40c321668ff5efe3fc8b1eae3fbd1728ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 8 Mar 2018 12:20:35 -0500 Subject: [PATCH] fpu/softfloat: re-factor compare The compare function was already expanded from a macro. I keep the macro expansion but move most of the logic into a compare_decomposed. Backports commit 0c4c90929143a530730e2879204a55a30bf63758 from qemu --- qemu/aarch64.h | 2 + qemu/aarch64eb.h | 2 + qemu/arm.h | 2 + qemu/armeb.h | 2 + qemu/fpu/softfloat.c | 133 +++++++++++++++++++++-------------- qemu/header_gen.py | 2 + qemu/include/fpu/softfloat.h | 2 + qemu/m68k.h | 2 + qemu/mips.h | 2 + qemu/mips64.h | 2 + qemu/mips64el.h | 2 + qemu/mipsel.h | 2 + qemu/powerpc.h | 2 + qemu/sparc.h | 2 + qemu/sparc64.h | 2 + qemu/x86_64.h | 2 + 16 files changed, 110 insertions(+), 53 deletions(-) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 17095299..4533d4fb 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -488,6 +488,8 @@ #define float128_unordered_quiet float128_unordered_quiet_aarch64 #define float16ToCommonNaN float16ToCommonNaN_aarch64 #define float16_add float16_add_aarch64 +#define float16_compare float16_compare_aarch64 +#define float16_compare_quiet float16_compare_quiet_aarch64 #define float16_default_nan float16_default_nan_aarch64 #define float16_div float16_div_aarch64 #define float16_is_quiet_nan float16_is_quiet_nan_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index 455074fd..935a4e9e 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -488,6 +488,8 @@ #define float128_unordered_quiet float128_unordered_quiet_aarch64eb #define float16ToCommonNaN float16ToCommonNaN_aarch64eb #define float16_add float16_add_aarch64eb +#define float16_compare float16_compare_aarch64eb +#define float16_compare_quiet float16_compare_quiet_aarch64eb #define float16_default_nan float16_default_nan_aarch64eb #define float16_div float16_div_aarch64eb #define float16_is_quiet_nan float16_is_quiet_nan_aarch64eb diff --git a/qemu/arm.h b/qemu/arm.h index 063ab518..6dd8359a 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -488,6 +488,8 @@ #define float128_unordered_quiet float128_unordered_quiet_arm #define float16ToCommonNaN float16ToCommonNaN_arm #define float16_add float16_add_arm +#define float16_compare float16_compare_arm +#define float16_compare_quiet float16_compare_quiet_arm #define float16_default_nan float16_default_nan_arm #define float16_div float16_div_arm #define float16_is_quiet_nan float16_is_quiet_nan_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index 219f388f..8ade8111 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -488,6 +488,8 @@ #define float128_unordered_quiet float128_unordered_quiet_armeb #define float16ToCommonNaN float16ToCommonNaN_armeb #define float16_add float16_add_armeb +#define float16_compare float16_compare_armeb +#define float16_compare_quiet float16_compare_quiet_armeb #define float16_default_nan float16_default_nan_armeb #define float16_div float16_div_armeb #define float16_is_quiet_nan float16_is_quiet_nan_armeb diff --git a/qemu/fpu/softfloat.c b/qemu/fpu/softfloat.c index b09bb75e..29b0b1ab 100644 --- a/qemu/fpu/softfloat.c +++ b/qemu/fpu/softfloat.c @@ -1664,6 +1664,86 @@ float64 uint16_to_float64(uint16_t a, float_status *status) return uint64_to_float64(a, status); } +/* Floating point compare */ +static int compare_floats(FloatParts a, FloatParts b, bool is_quiet, + float_status *s) +{ + if (is_nan(a.cls) || is_nan(b.cls)) { + if (!is_quiet || + a.cls == float_class_snan || + b.cls == float_class_snan) { + s->float_exception_flags |= float_flag_invalid; + } + return float_relation_unordered; + } + + if (a.cls == float_class_zero) { + if (b.cls == float_class_zero) { + return float_relation_equal; + } + return b.sign ? float_relation_greater : float_relation_less; + } else if (b.cls == float_class_zero) { + return a.sign ? float_relation_less : float_relation_greater; + } + + /* The only really important thing about infinity is its sign. If + * both are infinities the sign marks the smallest of the two. + */ + if (a.cls == float_class_inf) { + if ((b.cls == float_class_inf) && (a.sign == b.sign)) { + return float_relation_equal; + } + return a.sign ? float_relation_less : float_relation_greater; + } else if (b.cls == float_class_inf) { + return b.sign ? float_relation_greater : float_relation_less; + } + + if (a.sign != b.sign) { + return a.sign ? float_relation_less : float_relation_greater; + } + + if (a.exp == b.exp) { + if (a.frac == b.frac) { + return float_relation_equal; + } + if (a.sign) { + return a.frac > b.frac ? + float_relation_less : float_relation_greater; + } else { + return a.frac > b.frac ? + float_relation_greater : float_relation_less; + } + } else { + if (a.sign) { + return a.exp > b.exp ? float_relation_less : float_relation_greater; + } else { + return a.exp > b.exp ? float_relation_greater : float_relation_less; + } + } +} + +#define COMPARE(sz) \ +int float ## sz ## _compare(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); \ + return compare_floats(pa, pb, false, s); \ +} \ +int float ## sz ## _compare_quiet(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); \ + return compare_floats(pa, pb, true, s); \ +} + +COMPARE(16) +COMPARE(32) +COMPARE(64) + +#undef COMPARE + /* Multiply A by 2 raised to the power N. */ static FloatParts scalbn_decomposed(FloatParts a, int n, float_status *s) { @@ -6812,59 +6892,6 @@ int float128_unordered_quiet(float128 a, float128 b, float_status *status) return 0; } -#define COMPARE(s, nan_exp) \ -static inline int float ## s ## _compare_internal(float ## s a, float ## s b, \ - int is_quiet, float_status *status) \ -{ \ - flag aSign, bSign; \ - uint ## s ## _t av, bv; \ - a = float ## s ## _squash_input_denormal(a, status); \ - b = float ## s ## _squash_input_denormal(b, status); \ - \ - if (( ( extractFloat ## s ## Exp( a ) == nan_exp ) && \ - extractFloat ## s ## Frac( a ) ) || \ - ( ( extractFloat ## s ## Exp( b ) == nan_exp ) && \ - extractFloat ## s ## Frac( b ) )) { \ - if (!is_quiet || \ - float ## s ## _is_signaling_nan(a, status) || \ - float ## s ## _is_signaling_nan(b, status)) { \ - float_raise(float_flag_invalid, status); \ - } \ - return float_relation_unordered; \ - } \ - aSign = extractFloat ## s ## Sign( a ); \ - bSign = extractFloat ## s ## Sign( b ); \ - av = float ## s ## _val(a); \ - bv = float ## s ## _val(b); \ - if ( aSign != bSign ) { \ - if ( (uint ## s ## _t) ( ( av | bv )<<1 ) == 0 ) { \ - /* zero case */ \ - return float_relation_equal; \ - } else { \ - return 1 - (2 * aSign); \ - } \ - } else { \ - if (av == bv) { \ - return float_relation_equal; \ - } else { \ - return 1 - 2 * (aSign ^ ( av < bv )); \ - } \ - } \ -} \ - \ -int float ## s ## _compare(float ## s a, float ## s b, float_status *status) \ -{ \ - return float ## s ## _compare_internal(a, b, 0, status); \ -} \ - \ -int float ## s ## _compare_quiet(float ## s a, float ## s b, float_status *status) \ -{ \ - return float ## s ## _compare_internal(a, b, 1, status); \ -} - -COMPARE(32, 0xff) -COMPARE(64, 0x7ff) - static inline int floatx80_compare_internal(floatx80 a, floatx80 b, int is_quiet, float_status *status) { diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 7b13bd5f..c5cac451 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -494,6 +494,8 @@ symbols = ( 'float128_unordered_quiet', 'float16ToCommonNaN', 'float16_add', + 'float16_compare', + 'float16_compare_quiet', 'float16_default_nan', 'float16_div', 'float16_is_quiet_nan', diff --git a/qemu/include/fpu/softfloat.h b/qemu/include/fpu/softfloat.h index 574b9403..f210bc6f 100644 --- a/qemu/include/fpu/softfloat.h +++ b/qemu/include/fpu/softfloat.h @@ -258,6 +258,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); +int float16_compare(float16, float16, float_status *status); +int float16_compare_quiet(float16, float16, float_status *status); int float16_is_quiet_nan(float16, float_status *status); int float16_is_signaling_nan(float16, float_status *status); diff --git a/qemu/m68k.h b/qemu/m68k.h index 23d5a5d7..fb8a5327 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -488,6 +488,8 @@ #define float128_unordered_quiet float128_unordered_quiet_m68k #define float16ToCommonNaN float16ToCommonNaN_m68k #define float16_add float16_add_m68k +#define float16_compare float16_compare_m68k +#define float16_compare_quiet float16_compare_quiet_m68k #define float16_default_nan float16_default_nan_m68k #define float16_div float16_div_m68k #define float16_is_quiet_nan float16_is_quiet_nan_m68k diff --git a/qemu/mips.h b/qemu/mips.h index b7de7269..e38d932e 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -488,6 +488,8 @@ #define float128_unordered_quiet float128_unordered_quiet_mips #define float16ToCommonNaN float16ToCommonNaN_mips #define float16_add float16_add_mips +#define float16_compare float16_compare_mips +#define float16_compare_quiet float16_compare_quiet_mips #define float16_default_nan float16_default_nan_mips #define float16_div float16_div_mips #define float16_is_quiet_nan float16_is_quiet_nan_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 5e7c30ab..2e4cf338 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -488,6 +488,8 @@ #define float128_unordered_quiet float128_unordered_quiet_mips64 #define float16ToCommonNaN float16ToCommonNaN_mips64 #define float16_add float16_add_mips64 +#define float16_compare float16_compare_mips64 +#define float16_compare_quiet float16_compare_quiet_mips64 #define float16_default_nan float16_default_nan_mips64 #define float16_div float16_div_mips64 #define float16_is_quiet_nan float16_is_quiet_nan_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 850dfad4..620e93cd 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -488,6 +488,8 @@ #define float128_unordered_quiet float128_unordered_quiet_mips64el #define float16ToCommonNaN float16ToCommonNaN_mips64el #define float16_add float16_add_mips64el +#define float16_compare float16_compare_mips64el +#define float16_compare_quiet float16_compare_quiet_mips64el #define float16_default_nan float16_default_nan_mips64el #define float16_div float16_div_mips64el #define float16_is_quiet_nan float16_is_quiet_nan_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 5c53eb7b..98ef126e 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -488,6 +488,8 @@ #define float128_unordered_quiet float128_unordered_quiet_mipsel #define float16ToCommonNaN float16ToCommonNaN_mipsel #define float16_add float16_add_mipsel +#define float16_compare float16_compare_mipsel +#define float16_compare_quiet float16_compare_quiet_mipsel #define float16_default_nan float16_default_nan_mipsel #define float16_div float16_div_mipsel #define float16_is_quiet_nan float16_is_quiet_nan_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index 1e38dcf6..4d514c5d 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -488,6 +488,8 @@ #define float128_unordered_quiet float128_unordered_quiet_powerpc #define float16ToCommonNaN float16ToCommonNaN_powerpc #define float16_add float16_add_powerpc +#define float16_compare float16_compare_powerpc +#define float16_compare_quiet float16_compare_quiet_powerpc #define float16_default_nan float16_default_nan_powerpc #define float16_div float16_div_powerpc #define float16_is_quiet_nan float16_is_quiet_nan_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index fd863c07..f260903f 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -488,6 +488,8 @@ #define float128_unordered_quiet float128_unordered_quiet_sparc #define float16ToCommonNaN float16ToCommonNaN_sparc #define float16_add float16_add_sparc +#define float16_compare float16_compare_sparc +#define float16_compare_quiet float16_compare_quiet_sparc #define float16_default_nan float16_default_nan_sparc #define float16_div float16_div_sparc #define float16_is_quiet_nan float16_is_quiet_nan_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 80d940dd..f3ceb164 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -488,6 +488,8 @@ #define float128_unordered_quiet float128_unordered_quiet_sparc64 #define float16ToCommonNaN float16ToCommonNaN_sparc64 #define float16_add float16_add_sparc64 +#define float16_compare float16_compare_sparc64 +#define float16_compare_quiet float16_compare_quiet_sparc64 #define float16_default_nan float16_default_nan_sparc64 #define float16_div float16_div_sparc64 #define float16_is_quiet_nan float16_is_quiet_nan_sparc64 diff --git a/qemu/x86_64.h b/qemu/x86_64.h index e00cb274..5298e8ab 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -488,6 +488,8 @@ #define float128_unordered_quiet float128_unordered_quiet_x86_64 #define float16ToCommonNaN float16ToCommonNaN_x86_64 #define float16_add float16_add_x86_64 +#define float16_compare float16_compare_x86_64 +#define float16_compare_quiet float16_compare_quiet_x86_64 #define float16_default_nan float16_default_nan_x86_64 #define float16_div float16_div_x86_64 #define float16_is_quiet_nan float16_is_quiet_nan_x86_64