@samitouri / QOSamiQemu / commits / 1f5d3cebf0

fpu: Split scalbn from partsN(muladd_scalbn)

Handle the scaling separately with parts64_scalbn. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Richard Henderson committed Apr 28, 2026 at 08:01 UTC 1f5d3cebf0d5131e4dada5c07d778b00eb9ce2e2
2 files changed +34 -23
fpu/softfloat-parts.c.inc
+10 -10
@@ -669,17 +669,19 @@ static FloatPartsN *partsN(mul)(FloatPartsN *a, FloatPartsN *b,
669 * `b' then adding 'c', with no intermediate rounding step after the
670 * multiplication. The operation is performed according to the
671 * IEC/IEEE Standard for Binary Floating-Point Arithmetic 754-2008.
672 - * The flags argument allows the caller to select negation of the
673 - * addend, the intermediate product, or the final result. (The
674 - * difference between this and having the caller do a separate
675 - * negation is that negating externally will flip the sign bit on NaNs.)
672 + * The flags argument allows the caller to select negation of the addend
673 + * or the intermediate product. (The difference between this and having
674 + * the caller do a separate negation is that negating externally will
675 + * flip the sign bit on NaNs.) Note that float_muladd_negate_result
676 + * is not applied here, and should be handled separately after rounding
677 + * chooses the final sign of 0.0.
678 *
679 * Requires A and C extracted into a double-sized structure to provide the
680 * extra space for the widening multiply.
681 */
680 -static FloatPartsN *partsN(muladd_scalbn)(FloatPartsN *a, FloatPartsN *b,
681 - FloatPartsN *c, int scale,
682 - int flags, float_status *s)
682 +static FloatPartsN *partsN(muladd)(FloatPartsN *a, FloatPartsN *b,
683 + FloatPartsN *c,
684 + int flags, float_status *s)
685 {
686 int ab_mask, abc_mask;
687 FloatPartsW p_widen, c_widen;
@@ -725,7 +727,7 @@ static FloatPartsN *partsN(muladd_scalbn)(FloatPartsN *a, FloatPartsN *b,
727 g_assert(ab_mask & float_cmask_zero);
728 if (is_anynorm(c->cls)) {
729 *a = *c;
728 - goto return_normal;
730 + goto finish_sign;
731 }
732 if (c->cls == float_class_zero) {
733 if (flags & float_muladd_suppress_add_product_zero) {
@@ -770,8 +772,6 @@ static FloatPartsN *partsN(muladd_scalbn)(FloatPartsN *a, FloatPartsN *b,
772 a->sign = p_widen.sign;
773 a->exp = p_widen.exp;
774
773 - return_normal:
774 - a->exp += scale;
775 finish_sign:
776 /*
777 * All result types except for "return the default NaN
fpu/softfloat.c
+24 -13
@@ -1907,11 +1907,14 @@ float16_muladd_scalbn(float16 a, float16 b, float16 c,
1907 FloatParts64 pa = float16_unpack_canonical(a, status);
1908 FloatParts64 pb = float16_unpack_canonical(b, status);
1909 FloatParts64 pc = float16_unpack_canonical(c, status);
1910 - FloatParts64 *pr =
1911 - parts64_muladd_scalbn(&pa, &pb, &pc, scale, flags, status);
1910 + FloatParts64 *pr = parts64_muladd(&pa, &pb, &pc, flags, status);
1911
1913 - /* Round before applying negate result. */
1912 + /* Before rounding, scale. */
1913 + if (scale) {
1914 + parts64_scalbn(pr, scale, status);
1915 + }
1916 parts64_uncanon(pr, status, &float16_params, false);
1917 + /* After rounding, apply negate result, especially for -0.0. */
1918 if ((flags & float_muladd_negate_result) && !is_nan(pr->cls)) {
1919 pr->sign ^= 1;
1920 }
@@ -1931,10 +1934,14 @@ float32_muladd_scalbn(float32 a, float32 b, float32 c,
1934 FloatParts64 pa = float32_unpack_canonical(a, status);
1935 FloatParts64 pb = float32_unpack_canonical(b, status);
1936 FloatParts64 pc = float32_unpack_canonical(c, status);
1934 - FloatParts64 *pr = parts64_muladd_scalbn(&pa, &pb, &pc, scale, flags, status);
1937 + FloatParts64 *pr = parts64_muladd(&pa, &pb, &pc, flags, status);
1938
1936 - /* Round before applying negate result. */
1939 + /* Before rounding, scale. */
1940 + if (scale) {
1941 + parts64_scalbn(pr, scale, status);
1942 + }
1943 parts64_uncanon(pr, status, &float32_params, false);
1944 + /* After rounding, apply negate result, especially for -0.0. */
1945 if ((flags & float_muladd_negate_result) && !is_nan(pr->cls)) {
1946 pr->sign ^= 1;
1947 }
@@ -1948,10 +1955,14 @@ float64_muladd_scalbn(float64 a, float64 b, float64 c,
1955 FloatParts64 pa = float64_unpack_canonical(a, status);
1956 FloatParts64 pb = float64_unpack_canonical(b, status);
1957 FloatParts64 pc = float64_unpack_canonical(c, status);
1951 - FloatParts64 *pr = parts64_muladd_scalbn(&pa, &pb, &pc, scale, flags, status);
1958 + FloatParts64 *pr = parts64_muladd(&pa, &pb, &pc, flags, status);
1959
1953 - /* Round before applying negate result. */
1960 + /* Before rounding, scale. */
1961 + if (scale) {
1962 + parts64_scalbn(pr, scale, status);
1963 + }
1964 parts64_uncanon(pr, status, &float64_params, false);
1965 + /* After rounding, apply negate result, especially for -0.0. */
1966 if ((flags & float_muladd_negate_result) && !is_nan(pr->cls)) {
1967 pr->sign ^= 1;
1968 }
@@ -2105,7 +2116,7 @@ float64 float64r32_muladd(float64 a, float64 b, float64 c,
2116 FloatParts64 pa = float64_unpack_canonical(a, status);
2117 FloatParts64 pb = float64_unpack_canonical(b, status);
2118 FloatParts64 pc = float64_unpack_canonical(c, status);
2108 - FloatParts64 *pr = parts64_muladd_scalbn(&pa, &pb, &pc, 0, flags, status);
2119 + FloatParts64 *pr = parts64_muladd(&pa, &pb, &pc, flags, status);
2120
2121 /* Round before applying negate result. */
2122 parts64_uncanon(pr, status, &float32_params, false);
@@ -2121,7 +2132,7 @@ bfloat16 QEMU_FLATTEN bfloat16_muladd(bfloat16 a, bfloat16 b, bfloat16 c,
2132 FloatParts64 pa = bfloat16_unpack_canonical(a, status);
2133 FloatParts64 pb = bfloat16_unpack_canonical(b, status);
2134 FloatParts64 pc = bfloat16_unpack_canonical(c, status);
2124 - FloatParts64 *pr = parts64_muladd_scalbn(&pa, &pb, &pc, 0, flags, status);
2135 + FloatParts64 *pr = parts64_muladd(&pa, &pb, &pc, flags, status);
2136
2137 /* Round before applying negate result. */
2138 parts64_uncanon(pr, status, &bfloat16_params, false);
@@ -2137,7 +2148,7 @@ float128 QEMU_FLATTEN float128_muladd(float128 a, float128 b, float128 c,
2148 FloatParts128 pa = float128_unpack_canonical(a, status);
2149 FloatParts128 pb = float128_unpack_canonical(b, status);
2150 FloatParts128 pc = float128_unpack_canonical(c, status);
2140 - FloatParts128 *pr = parts128_muladd_scalbn(&pa, &pb, &pc, 0, flags, status);
2151 + FloatParts128 *pr = parts128_muladd(&pa, &pb, &pc, flags, status);
2152
2153 /* Round before applying negate result. */
2154 parts128_uncanon(pr, status, &float128_params, false);
@@ -5116,7 +5127,7 @@ float32 float32_exp2(float32 a, float_status *status)
5127 rp = float64_unpack_canonical(float64_one, status);
5128 for (int i = 0; i < 15; i++) {
5129 tp = float64_unpack_canonical(float32_exp2_coefficients[i], status);
5119 - rp = *parts64_muladd_scalbn(&tp, &xnp, &rp, 0, 0, status);
5130 + rp = *parts64_muladd(&tp, &xnp, &rp, 0, status);
5131 xnp = *parts64_mul(&xnp, &xp, status);
5132 }
5133
@@ -5196,8 +5207,8 @@ static void parts_s390_divide_to_integer(FloatParts64 *a, FloatParts64 *b,
5207
5208 /* Compute precise remainder */
5209 r_precise_buf = *b;
5199 - r_precise = parts64_muladd_scalbn(&r_precise_buf, n, a, 0,
5200 - float_muladd_negate_product, status);
5210 + r_precise = parts64_muladd(&r_precise_buf, n, a,
5211 + float_muladd_negate_product, status);
5212
5213 /* Round remainder to the target format */
5214 *r = *r_precise;