Commit d2a727e347 for qemu.org
commit d2a727e34732e57fb40d9f42d0c09a6d3a6c6ddf
Author: Richard Henderson <richard.henderson@linaro.org>
Date: Sun Apr 26 20:40:42 2026 +1000
fpu: Drop parts_log2
Use parts64_log2 at each call site.
That leaves parts128_log2 unused, so move the whole function back
to softfloat.c and specialize for FloatParts64.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 8405cf29cd..5f27efd288 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -1671,134 +1671,3 @@ static void partsN(scalbn)(FloatPartsN *a, int n, float_status *s)
g_assert_not_reached();
}
}
-
-/*
- * Return log2(A)
- */
-static void partsN(log2)(FloatPartsN *a, float_status *s, const FloatFmt *fmt)
-{
- uint64_t a0, a1, r, t, ign;
- FloatPartsN f;
- int i, n, a_exp, f_exp;
-
- if (unlikely(a->cls != float_class_normal)) {
- switch (a->cls) {
- case float_class_denormal:
- if (!a->sign) {
- /* -ve denormal will be InvalidOperation */
- float_raise(float_flag_input_denormal_used, s);
- }
- break;
- case float_class_snan:
- case float_class_qnan:
- partsN(return_nan)(a, s);
- return;
- case float_class_zero:
- float_raise(float_flag_divbyzero, s);
- /* log2(0) = -inf */
- a->cls = float_class_inf;
- a->sign = 1;
- return;
- case float_class_inf:
- if (unlikely(a->sign)) {
- goto d_nan;
- }
- return;
- default:
- g_assert_not_reached();
- }
- }
- if (unlikely(a->sign)) {
- goto d_nan;
- }
-
- /* TODO: This algorithm looses bits too quickly for float128. */
- g_assert(N == 64);
-
- a_exp = a->exp;
- f_exp = -1;
-
- r = 0;
- t = DECOMPOSED_IMPLICIT_BIT;
- a0 = a->frac_hi;
- a1 = 0;
-
- n = fmt->frac_size + 2;
- if (unlikely(a_exp == -1)) {
- /*
- * When a_exp == -1, we're computing the log2 of a value [0.5,1.0).
- * When the value is very close to 1.0, there are lots of 1's in
- * the msb parts of the fraction. At the end, when we subtract
- * this value from -1.0, we can see a catastrophic loss of precision,
- * as 0x800..000 - 0x7ff..ffx becomes 0x000..00y, leaving only the
- * bits of y in the final result. To minimize this, compute as many
- * digits as we can.
- * ??? This case needs another algorithm to avoid this.
- */
- n = fmt->frac_size * 2 + 2;
- /* Don't compute a value overlapping the sticky bit */
- n = MIN(n, 62);
- }
-
- for (i = 0; i < n; i++) {
- if (a1) {
- mul128To256(a0, a1, a0, a1, &a0, &a1, &ign, &ign);
- } else if (a0 & 0xffffffffull) {
- mul64To128(a0, a0, &a0, &a1);
- } else if (a0 & ~DECOMPOSED_IMPLICIT_BIT) {
- a0 >>= 32;
- a0 *= a0;
- } else {
- goto exact;
- }
-
- if (a0 & DECOMPOSED_IMPLICIT_BIT) {
- if (unlikely(a_exp == 0 && r == 0)) {
- /*
- * When a_exp == 0, we're computing the log2 of a value
- * [1.0,2.0). When the value is very close to 1.0, there
- * are lots of 0's in the msb parts of the fraction.
- * We need to compute more digits to produce a correct
- * result -- restart at the top of the fraction.
- * ??? This is likely to lose precision quickly, as for
- * float128; we may need another method.
- */
- f_exp -= i;
- t = r = DECOMPOSED_IMPLICIT_BIT;
- i = 0;
- } else {
- r |= t;
- }
- } else {
- add128(a0, a1, a0, a1, &a0, &a1);
- }
- t >>= 1;
- }
-
- /* Set sticky for inexact. */
- r |= (a1 || a0 & ~DECOMPOSED_IMPLICIT_BIT);
-
- exact:
- partsN(sint_to_float)(a, a_exp, 0, s);
- if (r == 0) {
- return;
- }
-
- memset(&f, 0, sizeof(f));
- f.cls = float_class_normal;
- f.frac_hi = r;
- f.exp = f_exp - frac_normalize(&f);
-
- if (a_exp < 0) {
- partsN(sub_normal)(a, &f);
- } else if (a_exp > 0) {
- partsN(add_normal)(a, &f);
- } else {
- *a = f;
- }
- return;
-
- d_nan:
- float_raise(float_flag_invalid, s);
- partsN(default_nan)(a, s);
-}
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 3e6f2a152a..6a38d161f7 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -779,12 +779,6 @@ static float128 QEMU_FLATTEN float128_pack_raw(const FloatParts128 *p)
FloatParts128 *: parts128_##NAME, \
FloatParts256 *: parts256_##NAME)
-static void parts64_log2(FloatParts64 *a, float_status *s, const FloatFmt *f);
-static void parts128_log2(FloatParts128 *a, float_status *s, const FloatFmt *f);
-
-#define parts_log2(A, S, F) \
- PARTS_GENERIC_64_128(log2, A)(A, S, F)
-
/*
* Helper functions for softfloat-parts.c.inc, per-size operations.
*/
@@ -4851,12 +4845,135 @@ floatx80 floatx80_sqrt(floatx80 a, float_status *s)
/*
* log2
*/
+
+static void parts64_log2(FloatParts64 *a, float_status *s, const FloatFmt *fmt)
+{
+ uint64_t a0, a1, r, t, ign;
+ int i, n, a_exp, f_exp;
+
+ if (unlikely(a->cls != float_class_normal)) {
+ switch (a->cls) {
+ case float_class_denormal:
+ if (!a->sign) {
+ /* -ve denormal will be InvalidOperation */
+ float_raise(float_flag_input_denormal_used, s);
+ }
+ break;
+ case float_class_snan:
+ case float_class_qnan:
+ parts64_return_nan(a, s);
+ return;
+ case float_class_zero:
+ float_raise(float_flag_divbyzero, s);
+ /* log2(0) = -inf */
+ a->cls = float_class_inf;
+ a->sign = 1;
+ return;
+ case float_class_inf:
+ if (unlikely(a->sign)) {
+ goto d_nan;
+ }
+ return;
+ default:
+ g_assert_not_reached();
+ }
+ }
+ if (unlikely(a->sign)) {
+ goto d_nan;
+ }
+
+ a_exp = a->exp;
+ f_exp = -1;
+
+ r = 0;
+ t = DECOMPOSED_IMPLICIT_BIT;
+ a0 = a->frac_hi;
+ a1 = 0;
+
+ n = fmt->frac_size + 2;
+ if (unlikely(a_exp == -1)) {
+ /*
+ * When a_exp == -1, we're computing the log2 of a value [0.5,1.0).
+ * When the value is very close to 1.0, there are lots of 1's in
+ * the msb parts of the fraction. At the end, when we subtract
+ * this value from -1.0, we can see a catastrophic loss of precision,
+ * as 0x800..000 - 0x7ff..ffx becomes 0x000..00y, leaving only the
+ * bits of y in the final result. To minimize this, compute as many
+ * digits as we can.
+ * ??? This case needs another algorithm to avoid this.
+ */
+ n = fmt->frac_size * 2 + 2;
+ /* Don't compute a value overlapping the sticky bit */
+ n = MIN(n, 62);
+ }
+
+ for (i = 0; i < n; i++) {
+ if (a1) {
+ mul128To256(a0, a1, a0, a1, &a0, &a1, &ign, &ign);
+ } else if (a0 & 0xffffffffull) {
+ mul64To128(a0, a0, &a0, &a1);
+ } else if (a0 & ~DECOMPOSED_IMPLICIT_BIT) {
+ a0 >>= 32;
+ a0 *= a0;
+ } else {
+ goto exact;
+ }
+
+ if (a0 & DECOMPOSED_IMPLICIT_BIT) {
+ if (unlikely(a_exp == 0 && r == 0)) {
+ /*
+ * When a_exp == 0, we're computing the log2 of a value
+ * [1.0,2.0). When the value is very close to 1.0, there
+ * are lots of 0's in the msb parts of the fraction.
+ * We need to compute more digits to produce a correct
+ * result -- restart at the top of the fraction.
+ * ??? This is likely to lose precision quickly, as for
+ * float128; we may need another method.
+ */
+ f_exp -= i;
+ t = r = DECOMPOSED_IMPLICIT_BIT;
+ i = 0;
+ } else {
+ r |= t;
+ }
+ } else {
+ add128(a0, a1, a0, a1, &a0, &a1);
+ }
+ t >>= 1;
+ }
+
+ /* Set sticky for inexact. */
+ r |= (a1 || a0 & ~DECOMPOSED_IMPLICIT_BIT);
+
+ exact:
+ parts64_sint_to_float(a, a_exp, 0, s);
+ if (r != 0) {
+ FloatParts64 f = {
+ .cls = float_class_normal, .frac = r
+ };
+ f.exp = f_exp - frac_normalize(&f);
+
+ if (a_exp < 0) {
+ parts64_sub_normal(a, &f);
+ } else if (a_exp > 0) {
+ parts64_add_normal(a, &f);
+ } else {
+ *a = f;
+ }
+ }
+ return;
+
+ d_nan:
+ float_raise(float_flag_invalid, s);
+ parts64_default_nan(a, s);
+}
+
float32 float32_log2(float32 a, float_status *status)
{
FloatParts64 p;
float32_unpack_canonical(&p, a, status);
- parts_log2(&p, status, &float32_params);
+ parts64_log2(&p, status, &float32_params);
return float32_round_pack_canonical(&p, status);
}
@@ -4865,7 +4982,7 @@ float64 float64_log2(float64 a, float_status *status)
FloatParts64 p;
float64_unpack_canonical(&p, a, status);
- parts_log2(&p, status, &float64_params);
+ parts64_log2(&p, status, &float64_params);
return float64_round_pack_canonical(&p, status);
}