[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 41/46] softfloat: Introduce sh[lr]_double primitives
From: |
Richard Henderson |
Subject: |
[PULL 41/46] softfloat: Introduce sh[lr]_double primitives |
Date: |
Sun, 16 May 2021 07:34:26 -0500 |
Have x86_64 assembly for them, with a fallback.
This avoids shuffling values through %cl in the x86 case.
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/fpu/softfloat-macros.h | 36 ++++++++++++
fpu/softfloat.c | 102 +++++++++++++++++++++++++--------
2 files changed, 115 insertions(+), 23 deletions(-)
diff --git a/include/fpu/softfloat-macros.h b/include/fpu/softfloat-macros.h
index 672c1db555..ec4e27a595 100644
--- a/include/fpu/softfloat-macros.h
+++ b/include/fpu/softfloat-macros.h
@@ -85,6 +85,42 @@ this code that are retained.
#include "fpu/softfloat-types.h"
#include "qemu/host-utils.h"
+/**
+ * shl_double: double-word merging left shift
+ * @l: left or most-significant word
+ * @r: right or least-significant word
+ * @c: shift count
+ *
+ * Shift @l left by @c bits, shifting in bits from @r.
+ */
+static inline uint64_t shl_double(uint64_t l, uint64_t r, int c)
+{
+#if defined(__x86_64__)
+ asm("shld %b2, %1, %0" : "+r"(l) : "r"(r), "ci"(c));
+ return l;
+#else
+ return c ? (l << c) | (r >> (64 - c)) : l;
+#endif
+}
+
+/**
+ * shr_double: double-word merging right shift
+ * @l: left or most-significant word
+ * @r: right or least-significant word
+ * @c: shift count
+ *
+ * Shift @r right by @c bits, shifting in bits from @l.
+ */
+static inline uint64_t shr_double(uint64_t l, uint64_t r, int c)
+{
+#if defined(__x86_64__)
+ asm("shrd %b2, %1, %0" : "+r"(r) : "r"(l), "ci"(c));
+ return r;
+#else
+ return c ? (r >> c) | (l << (64 - c)) : r;
+#endif
+}
+
/*----------------------------------------------------------------------------
| Shifts `a' right by the number of bits given in `count'. If any nonzero
| bits are shifted off, they are ``jammed'' into the least significant bit of
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 571309e74f..34689959a9 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -957,15 +957,12 @@ static int frac128_normalize(FloatParts128 *a)
{
if (a->frac_hi) {
int shl = clz64(a->frac_hi);
- if (shl) {
- int shr = 64 - shl;
- a->frac_hi = (a->frac_hi << shl) | (a->frac_lo >> shr);
- a->frac_lo = (a->frac_lo << shl);
- }
+ a->frac_hi = shl_double(a->frac_hi, a->frac_lo, shl);
+ a->frac_lo <<= shl;
return shl;
} else if (a->frac_lo) {
int shl = clz64(a->frac_lo);
- a->frac_hi = (a->frac_lo << shl);
+ a->frac_hi = a->frac_lo << shl;
a->frac_lo = 0;
return shl + 64;
}
@@ -976,7 +973,7 @@ static int frac256_normalize(FloatParts256 *a)
{
uint64_t a0 = a->frac_hi, a1 = a->frac_hm;
uint64_t a2 = a->frac_lm, a3 = a->frac_lo;
- int ret, shl, shr;
+ int ret, shl;
if (likely(a0)) {
shl = clz64(a0);
@@ -1006,11 +1003,10 @@ static int frac256_normalize(FloatParts256 *a)
ret += shl;
}
- shr = -shl & 63;
- a0 = (a0 << shl) | (a1 >> shr);
- a1 = (a1 << shl) | (a2 >> shr);
- a2 = (a2 << shl) | (a3 >> shr);
- a3 = (a3 << shl);
+ a0 = shl_double(a0, a1, shl);
+ a1 = shl_double(a1, a2, shl);
+ a2 = shl_double(a2, a3, shl);
+ a3 <<= shl;
done:
a->frac_hi = a0;
@@ -1029,7 +1025,20 @@ static void frac64_shl(FloatParts64 *a, int c)
static void frac128_shl(FloatParts128 *a, int c)
{
- shift128Left(a->frac_hi, a->frac_lo, c, &a->frac_hi, &a->frac_lo);
+ uint64_t a0 = a->frac_hi, a1 = a->frac_lo;
+
+ if (c & 64) {
+ a0 = a1, a1 = 0;
+ }
+
+ c &= 63;
+ if (c) {
+ a0 = shl_double(a0, a1, c);
+ a1 = a1 << c;
+ }
+
+ a->frac_hi = a0;
+ a->frac_lo = a1;
}
#define frac_shl(A, C) FRAC_GENERIC_64_128(shl, A)(A, C)
@@ -1041,19 +1050,68 @@ static void frac64_shr(FloatParts64 *a, int c)
static void frac128_shr(FloatParts128 *a, int c)
{
- shift128Right(a->frac_hi, a->frac_lo, c, &a->frac_hi, &a->frac_lo);
+ uint64_t a0 = a->frac_hi, a1 = a->frac_lo;
+
+ if (c & 64) {
+ a1 = a0, a0 = 0;
+ }
+
+ c &= 63;
+ if (c) {
+ a1 = shr_double(a0, a1, c);
+ a0 = a0 >> c;
+ }
+
+ a->frac_hi = a0;
+ a->frac_lo = a1;
}
#define frac_shr(A, C) FRAC_GENERIC_64_128(shr, A)(A, C)
static void frac64_shrjam(FloatParts64 *a, int c)
{
- shift64RightJamming(a->frac, c, &a->frac);
+ uint64_t a0 = a->frac;
+
+ if (likely(c != 0)) {
+ if (likely(c < 64)) {
+ a0 = (a0 >> c) | (shr_double(a0, 0, c) != 0);
+ } else {
+ a0 = a0 != 0;
+ }
+ a->frac = a0;
+ }
}
static void frac128_shrjam(FloatParts128 *a, int c)
{
- shift128RightJamming(a->frac_hi, a->frac_lo, c, &a->frac_hi, &a->frac_lo);
+ uint64_t a0 = a->frac_hi, a1 = a->frac_lo;
+ uint64_t sticky = 0;
+
+ if (unlikely(c == 0)) {
+ return;
+ } else if (likely(c < 64)) {
+ /* nothing */
+ } else if (likely(c < 128)) {
+ sticky = a1;
+ a1 = a0;
+ a0 = 0;
+ c &= 63;
+ if (c == 0) {
+ goto done;
+ }
+ } else {
+ sticky = a0 | a1;
+ a0 = a1 = 0;
+ goto done;
+ }
+
+ sticky |= shr_double(a1, 0, c);
+ a1 = shr_double(a0, a1, c);
+ a0 = a0 >> c;
+
+ done:
+ a->frac_lo = a1 | (sticky != 0);
+ a->frac_hi = a0;
}
static void frac256_shrjam(FloatParts256 *a, int c)
@@ -1061,7 +1119,6 @@ static void frac256_shrjam(FloatParts256 *a, int c)
uint64_t a0 = a->frac_hi, a1 = a->frac_hm;
uint64_t a2 = a->frac_lm, a3 = a->frac_lo;
uint64_t sticky = 0;
- int invc;
if (unlikely(c == 0)) {
return;
@@ -1086,12 +1143,11 @@ static void frac256_shrjam(FloatParts256 *a, int c)
goto done;
}
- invc = -c & 63;
- sticky |= a3 << invc;
- a3 = (a3 >> c) | (a2 << invc);
- a2 = (a2 >> c) | (a1 << invc);
- a1 = (a1 >> c) | (a0 << invc);
- a0 = (a0 >> c);
+ sticky |= shr_double(a3, 0, c);
+ a3 = shr_double(a2, a3, c);
+ a2 = shr_double(a1, a2, c);
+ a1 = shr_double(a0, a1, c);
+ a0 = a0 >> c;
done:
a->frac_lo = a3 | (sticky != 0);
--
2.25.1
- [PULL 21/46] softfloat: Use pointers with ftype_pack_raw, (continued)
- [PULL 21/46] softfloat: Use pointers with ftype_pack_raw, Richard Henderson, 2021/05/16
- [PULL 30/46] softfloat: Move pick_nan_muladd to softfloat-parts.c.inc, Richard Henderson, 2021/05/16
- [PULL 34/46] softfloat: Move addsub_floats to softfloat-parts.c.inc, Richard Henderson, 2021/05/16
- [PULL 38/46] softfloat: Use mulu64 for mul64To128, Richard Henderson, 2021/05/16
- [PULL 27/46] softfloat: Convert float128_default_nan to parts, Richard Henderson, 2021/05/16
- [PULL 35/46] softfloat: Implement float128_add/sub via parts, Richard Henderson, 2021/05/16
- [PULL 37/46] softfloat: Move muladd_floats to softfloat-parts.c.inc, Richard Henderson, 2021/05/16
- [PULL 32/46] softfloat: Move round_canonical to softfloat-parts.c.inc, Richard Henderson, 2021/05/16
- [PULL 39/46] softfloat: Use add192 in mul128To256, Richard Henderson, 2021/05/16
- [PULL 36/46] softfloat: Move mul_floats to softfloat-parts.c.inc, Richard Henderson, 2021/05/16
- [PULL 41/46] softfloat: Introduce sh[lr]_double primitives,
Richard Henderson <=
- [PULL 40/46] softfloat: Tidy mul128By64To192, Richard Henderson, 2021/05/16
- [PULL 42/46] softfloat: Move div_floats to softfloat-parts.c.inc, Richard Henderson, 2021/05/16
- [PULL 45/46] softfloat: Move round_to_int to softfloat-parts.c.inc, Richard Henderson, 2021/05/16
- [PULL 44/46] softfloat: Convert float-to-float conversions with float128, Richard Henderson, 2021/05/16
- [PULL 43/46] softfloat: Split float_to_float, Richard Henderson, 2021/05/16
- [PULL 46/46] softfloat: Move round_to_int_and_pack to softfloat-parts.c.inc, Richard Henderson, 2021/05/16
- Re: [PULL 00/46] softfloat: Convert float128 to FloatParts (part 1), no-reply, 2021/05/16