From nobody Tue Jul 28 17:56:26 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1778977629300836.1463317527484; Sat, 16 May 2026 17:27:09 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wOPKq-0001iP-O5; Sat, 16 May 2026 20:26:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wOPKY-0001eh-Vo for qemu-devel@nongnu.org; Sat, 16 May 2026 20:26:07 -0400 Received: from mail-pf1-x431.google.com ([2607:f8b0:4864:20::431]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wOPKW-0002aW-MF for qemu-devel@nongnu.org; Sat, 16 May 2026 20:26:06 -0400 Received: by mail-pf1-x431.google.com with SMTP id d2e1a72fcca58-8353fd1cb5fso443273b3a.0 for ; Sat, 16 May 2026 17:26:03 -0700 (PDT) Received: from stoup.. ([71.212.142.33]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-83f19c5be71sm9670317b3a.39.2026.05.16.17.26.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 16 May 2026 17:26:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1778977562; x=1779582362; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fCZyoqgqjVXJJtjxCkZlZshfx8C6L5WwhqI7H2CZ8tM=; b=njz/VanvoGCWA5zisIK/6GTHXB3y0sP5kazmOay6fWCE7fssXl6EteTIMbsMSGkjwH 1D9MJyBB4LDC0ayKzhzzMPZoRXCoAZj90ZRaxN1Od1+DtBHOkNKiRdWcIMIAgiBZdUTN 8hPbna1Iwn7n4CP6GqiFkna00F9WYUqTLU4UboU56spB2bO6+zy/29lC0BqqzCsRVUbW ic4XTbuPjoc8B8G7y1Q4aMYVLjFWjQ2gBjao9AdF6XrQ4a8MMJ9WTU94sTEk0w7sb6FK uu9QBLRLk0+Vs2Kaje31RUv0Nuv+mUCXGrJw6quf3mzDIdlti7RYXkME4x8qDktenPT+ sJHQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778977562; x=1779582362; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=fCZyoqgqjVXJJtjxCkZlZshfx8C6L5WwhqI7H2CZ8tM=; b=WfEdJhKyoZPwCUvDAZS+3Q0vb+zpX4xkf2okfkW+nwWmeg3DpHkW8VtOu+ax7t1UMf PXLKsW/1U+MYpoCzereCDsHO7JMhw2Qws5DwvqjcG8vre/tnH2FqGqBfs0FvknTnkV7b ziD5l1yWwTyL050Z/7M5TGkIcGojpapiJoyLQzoAzEGfe1+tgPM3kNvkZuoUAM0sdQ+o PRdhoNINd5SQZmy3qTtP6fvkmIFrBlbCKTFZO4TTKQ4aCtuzo4IDD4/W0yNq9OVuT6Ds QwrRmAzxnZVktx0b1vHSZYiiNmcOtBdP9RQHBCJ0iwV31bXA0Ni0OYMRqQsjMqH0RNwj wTnQ== X-Gm-Message-State: AOJu0YzmFg1PQPj2QVCQyXyYPWDycUr1rnTOupLlKiJjTl7YgG8h2GN4 PdYlPhizkzrmlC3RFLqciXNKi6fFfhRphkleKiJ+EGIac4MqZahzYl8JPb9Qs4H58AKeqpZswju O7/WZ X-Gm-Gg: Acq92OFez5f4i2X1MBCJ4pSltHy2eRfke8LmZqdzLkUUsTvpiJfGBcL5SA7/G5Em+Xv d0MapdKSkCNd9T4Rp34167tfvRPCUuboL4DJvwwpnItz+u5XqZ1JFhnzebown+Fjbxo3lF+1nJe qzljlQ9waM7k9RbYTZ2XQdFNT7zOcNOLiiwS97sqTRgJK0A+/25R3Q7WNFF40GywOLi7opDg8Z3 i3ySw/WfrjGr5czFjrzfmIbACBPWAdRZ67ZEc1az1lU9cvM2SUnX+BhNi5i5RwVmane61M7oZS1 wA9pxW+v5EBYHIhLNjKnRxXgTWy0UPA5skJn2agRXYR9oFlyBzLSjRAYwIDkCUd7BErWMqu883z X6S++a1oZAqF36FEhhXDwRTiaVQr9IMP2SzlJjyfbA+cKFx2UNzyNh1rxFvzjrVQVgBsaqNJm+7 i+1uQg3/8vPNQjUgni/R1w++gi49AaHO9T1l6eCvtJjDFvpau41g== X-Received: by 2002:a05:6a00:1405:b0:82c:1cd0:2f7e with SMTP id d2e1a72fcca58-83f33c93b19mr7002752b3a.20.1778977562185; Sat, 16 May 2026 17:26:02 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Ilya Leoshkevich Subject: [PATCH v4 07/12] target/s390x: Move float{32, 64}_s390_divide_to_integer Date: Sat, 16 May 2026 17:25:44 -0700 Message-ID: <20260517002550.321291-8-richard.henderson@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260517002550.321291-1-richard.henderson@linaro.org> References: <20260517002550.321291-1-richard.henderson@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::431; envelope-from=richard.henderson@linaro.org; helo=mail-pf1-x431.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1778977631033158500 Now that we've exposed enough infrastructure, this can be implemented in the backend that needs it. Reviewed-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- include/fpu/softfloat.h | 11 --- fpu/softfloat.c | 137 ---------------------------------- target/s390x/tcg/fpu_helper.c | 135 +++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 148 deletions(-) diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 8389a07b04..1580d956d5 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -1386,15 +1386,4 @@ static inline bool float128_unordered_quiet(float128= a, float128 b, *-------------------------------------------------------------------------= ---*/ float128 float128_default_nan(float_status *status); =20 -#define DECLARE_S390_DIVIDE_TO_INTEGER(floatN) = \ -void floatN ## _s390_divide_to_integer(floatN a, floatN b, = \ - int final_quotient_rounding_mode, = \ - bool mask_underflow, bool mask_inex= act, \ - floatN *r, floatN *n, = \ - uint32_t *cc, int *dxc, = \ - float_status *status) -DECLARE_S390_DIVIDE_TO_INTEGER(float32); -DECLARE_S390_DIVIDE_TO_INTEGER(float64); - - #endif /* SOFTFLOAT_H */ diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 08ea56a71d..a762f4b43a 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -5151,143 +5151,6 @@ floatx80 floatx80_round(floatx80 a, float_status *s= tatus) return floatx80_round_pack_canonical(&p, status); } =20 -static void parts_s390_divide_to_integer(FloatParts64 *a, FloatParts64 *b, - int final_quotient_rounding_mode, - bool mask_underflow, bool mask_in= exact, - const FloatFmt *fmt, - FloatParts64 *r, FloatParts64 *n, - uint32_t *cc, int *dxc, - float_status *status) -{ - /* POp table "Results: DIVIDE TO INTEGER (Part 1 of 2)" */ - if ((float_cmask(a->cls) | float_cmask(b->cls)) & float_cmask_anynan) { - *r =3D parts64_pick_nan(a, b, status); - *n =3D *r; - *cc =3D 1; - } else if (a->cls =3D=3D float_class_inf || b->cls =3D=3D float_class_= zero) { - *r =3D parts64_default_nan(status); - *n =3D *r; - *cc =3D 1; - status->float_exception_flags |=3D float_flag_invalid; - } else if (b->cls =3D=3D float_class_inf) { - *r =3D *a; - n->cls =3D float_class_zero; - n->sign =3D a->sign ^ b->sign; - *cc =3D 0; - } else { - FloatParts64 *q, q_buf, r_precise; - int float_exception_flags =3D 0; - bool is_q_smallish; - uint32_t r_flags; - - /* Compute precise quotient */ - q_buf =3D parts64_div(a, b, status); - q =3D &q_buf; - - /* - * Check whether two closest integers can be precisely represented, - * i.e., all their bits fit into the fractional part. - */ - is_q_smallish =3D q->exp < (fmt->frac_size + 1); - - /* - * Final quotient is rounded using final-quotient-rounding method,= and - * partial quotient is rounded toward zero. - * - * Rounding of partial quotient may be inexact. This is the whole = point - * of distinguishing partial quotients, so ignore the exception. - */ - *n =3D parts64_round_to_int(q, - is_q_smallish - ? final_quotient_rounding_mode - : float_round_to_zero, - 0, status, fmt); - - /* Compute precise remainder */ - r_precise =3D parts64_muladd(b, n, a, - float_muladd_negate_product, status); - - /* Round remainder to the target format */ - *r =3D r_precise; - status->float_exception_flags =3D 0; - *r =3D parts64_round_to_fmt(r, status, fmt); - r_flags =3D status->float_exception_flags; - - /* POp table "Results: DIVIDE TO INTEGER (Part 2 of 2)" */ - if (is_q_smallish) { - if (r->cls !=3D float_class_zero) { - if (r->exp < 2 - (1 << (fmt->exp_size - 1))) { - if (mask_underflow) { - float_exception_flags |=3D float_flag_underflow; - *dxc =3D 0x10; - r->exp +=3D fmt->exp_re_bias; - } - } else if (r_flags & float_flag_inexact) { - float_exception_flags |=3D float_flag_inexact; - if (mask_inexact) { - bool saved_r_sign, saved_r_precise_sign; - - /* - * Check whether remainder was truncated (rounded - * toward zero) or incremented. - */ - saved_r_sign =3D r->sign; - saved_r_precise_sign =3D r_precise.sign; - r->sign =3D false; - r_precise.sign =3D false; - if (parts64_compare(r, &r_precise, status, true) < - float_relation_equal) { - *dxc =3D 0x8; - } else { - *dxc =3D 0xc; - } - r->sign =3D saved_r_sign; - r_precise.sign =3D saved_r_precise_sign; - } - } - } - *cc =3D 0; - } else if (n->exp > (1 << (fmt->exp_size - 1)) - 1) { - n->exp -=3D fmt->exp_re_bias; - *cc =3D r->cls =3D=3D float_class_zero ? 1 : 3; - } else { - *cc =3D r->cls =3D=3D float_class_zero ? 0 : 2; - } - - /* Adjust signs of zero results */ - if (r->cls =3D=3D float_class_zero) { - r->sign =3D a->sign; - } - if (n->cls =3D=3D float_class_zero) { - n->sign =3D a->sign ^ b->sign; - } - - status->float_exception_flags =3D float_exception_flags; - } -} - -#define DEFINE_S390_DIVIDE_TO_INTEGER(floatN) = \ -void floatN ## _s390_divide_to_integer(floatN a, floatN b, = \ - int final_quotient_rounding_mode, = \ - bool mask_underflow, bool mask_inex= act, \ - floatN *r, floatN *n, = \ - uint32_t *cc, int *dxc, = \ - float_status *status) = \ -{ = \ - FloatParts64 pa =3D floatN ## _unpack_canonical(a, status); = \ - FloatParts64 pb =3D floatN ## _unpack_canonical(b, status); = \ - FloatParts64 pr, pn; = \ - parts_s390_divide_to_integer(&pa, &pb, final_quotient_rounding_mode, = \ - mask_underflow, mask_inexact, = \ - &floatN ## _params, = \ - &pr, &pn, cc, dxc, status); = \ - *r =3D floatN ## _round_pack_canonical(&pr, status); = \ - *n =3D floatN ## _round_pack_canonical(&pn, status); = \ -} - -DEFINE_S390_DIVIDE_TO_INTEGER(float32) -DEFINE_S390_DIVIDE_TO_INTEGER(float64) - static void __attribute__((constructor)) softfloat_init(void) { union_float64 ua, ub, uc, ur; diff --git a/target/s390x/tcg/fpu_helper.c b/target/s390x/tcg/fpu_helper.c index 122994960a..33e0f6100d 100644 --- a/target/s390x/tcg/fpu_helper.c +++ b/target/s390x/tcg/fpu_helper.c @@ -24,6 +24,7 @@ #include "tcg_s390x.h" #include "exec/helper-proto.h" #include "fpu/softfloat.h" +#include "fpu/softfloat-parts.h" =20 /* #define DEBUG_HELPER */ #ifdef DEBUG_HELPER @@ -315,6 +316,140 @@ Int128 HELPER(dxb)(CPUS390XState *env, Int128 a, Int1= 28 b) return RET128(ret); } =20 +static void parts_s390_divide_to_integer(FloatParts64 *a, FloatParts64 *b, + int final_quotient_rounding_mode, + bool mask_underflow, bool mask_in= exact, + const FloatFmt *fmt, + FloatParts64 *r, FloatParts64 *n, + uint32_t *cc, int *dxc, + float_status *status) +{ + /* POp table "Results: DIVIDE TO INTEGER (Part 1 of 2)" */ + if ((float_cmask(a->cls) | float_cmask(b->cls)) & float_cmask_anynan) { + *r =3D parts64_pick_nan(a, b, status); + *n =3D *r; + *cc =3D 1; + } else if (a->cls =3D=3D float_class_inf || b->cls =3D=3D float_class_= zero) { + *r =3D parts64_default_nan(status); + *n =3D *r; + *cc =3D 1; + status->float_exception_flags |=3D float_flag_invalid; + } else if (b->cls =3D=3D float_class_inf) { + *r =3D *a; + n->cls =3D float_class_zero; + n->sign =3D a->sign ^ b->sign; + *cc =3D 0; + } else { + FloatParts64 *q, q_buf, r_precise; + int float_exception_flags =3D 0; + bool is_q_smallish; + uint32_t r_flags; + + /* Compute precise quotient */ + q_buf =3D parts64_div(a, b, status); + q =3D &q_buf; + + /* + * Check whether two closest integers can be precisely represented, + * i.e., all their bits fit into the fractional part. + */ + is_q_smallish =3D q->exp < (fmt->frac_size + 1); + + /* + * Final quotient is rounded using final-quotient-rounding method,= and + * partial quotient is rounded toward zero. + * + * Rounding of partial quotient may be inexact. This is the whole = point + * of distinguishing partial quotients, so ignore the exception. + */ + *n =3D parts64_round_to_int(q, + is_q_smallish + ? final_quotient_rounding_mode + : float_round_to_zero, + 0, status, fmt); + + /* Compute precise remainder */ + r_precise =3D parts64_muladd(b, n, a, + float_muladd_negate_product, status); + + /* Round remainder to the target format */ + *r =3D r_precise; + status->float_exception_flags =3D 0; + *r =3D parts64_round_to_fmt(r, status, fmt); + r_flags =3D status->float_exception_flags; + + /* POp table "Results: DIVIDE TO INTEGER (Part 2 of 2)" */ + if (is_q_smallish) { + if (r->cls !=3D float_class_zero) { + if (r->exp < 2 - (1 << (fmt->exp_size - 1))) { + if (mask_underflow) { + float_exception_flags |=3D float_flag_underflow; + *dxc =3D 0x10; + r->exp +=3D fmt->exp_re_bias; + } + } else if (r_flags & float_flag_inexact) { + float_exception_flags |=3D float_flag_inexact; + if (mask_inexact) { + bool saved_r_sign, saved_r_precise_sign; + + /* + * Check whether remainder was truncated (rounded + * toward zero) or incremented. + */ + saved_r_sign =3D r->sign; + saved_r_precise_sign =3D r_precise.sign; + r->sign =3D false; + r_precise.sign =3D false; + if (parts64_compare(r, &r_precise, status, true) < + float_relation_equal) { + *dxc =3D 0x8; + } else { + *dxc =3D 0xc; + } + r->sign =3D saved_r_sign; + r_precise.sign =3D saved_r_precise_sign; + } + } + } + *cc =3D 0; + } else if (n->exp > (1 << (fmt->exp_size - 1)) - 1) { + n->exp -=3D fmt->exp_re_bias; + *cc =3D r->cls =3D=3D float_class_zero ? 1 : 3; + } else { + *cc =3D r->cls =3D=3D float_class_zero ? 0 : 2; + } + + /* Adjust signs of zero results */ + if (r->cls =3D=3D float_class_zero) { + r->sign =3D a->sign; + } + if (n->cls =3D=3D float_class_zero) { + n->sign =3D a->sign ^ b->sign; + } + + status->float_exception_flags =3D float_exception_flags; + } +} + +#define DEFINE_S390_DIVIDE_TO_INTEGER(floatN) = \ +static void floatN ## _s390_divide_to_integer(floatN a, floatN b, = \ + int final_quotient_rounding_mode, bool mask_underflow, bool mask_inexa= ct, \ + floatN *r, floatN *n, uint32_t *cc, int *dxc, float_status *status) = \ +{ = \ + FloatParts64 pa =3D floatN ## _unpack_canonical(a, status); = \ + FloatParts64 pb =3D floatN ## _unpack_canonical(b, status); = \ + FloatParts64 pr, pn; = \ + parts_s390_divide_to_integer(&pa, &pb, final_quotient_rounding_mode, = \ + mask_underflow, mask_inexact, = \ + &floatN ## _params, = \ + &pr, &pn, cc, dxc, status); = \ + *r =3D floatN ## _round_pack_canonical(&pr, status); = \ + *n =3D floatN ## _round_pack_canonical(&pn, status); = \ +} + +DEFINE_S390_DIVIDE_TO_INTEGER(float32) +DEFINE_S390_DIVIDE_TO_INTEGER(float64) + void HELPER(dib)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3, uint32_t m4, uint32_t bits) { --=20 2.43.0