@samitouri / QOSamiQemu / commits / f0eb9fe01b

target/s390x: Move float{32,64}_s390_divide_to_integer

Now that we've exposed enough infrastructure, this can be implemented in the backend that needs it. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Richard Henderson committed Apr 26, 2026 at 12:37 UTC f0eb9fe01ba11fc069deff636576eab941d5daca
3 files changed +135 -148
fpu/softfloat.c
-137
@@ -5151,143 +5151,6 @@ floatx80 floatx80_round(floatx80 a, float_status *status)
5151 return floatx80_round_pack_canonical(&p, status);
5152 }
5153
5154 -static void parts_s390_divide_to_integer(FloatParts64 *a, FloatParts64 *b,
5155 - int final_quotient_rounding_mode,
5156 - bool mask_underflow, bool mask_inexact,
5157 - const FloatFmt *fmt,
5158 - FloatParts64 *r, FloatParts64 *n,
5159 - uint32_t *cc, int *dxc,
5160 - float_status *status)
5161 -{
5162 - /* POp table "Results: DIVIDE TO INTEGER (Part 1 of 2)" */
5163 - if ((float_cmask(a->cls) | float_cmask(b->cls)) & float_cmask_anynan) {
5164 - *r = parts64_pick_nan(a, b, status);
5165 - *n = *r;
5166 - *cc = 1;
5167 - } else if (a->cls == float_class_inf || b->cls == float_class_zero) {
5168 - *r = parts64_default_nan(status);
5169 - *n = *r;
5170 - *cc = 1;
5171 - status->float_exception_flags |= float_flag_invalid;
5172 - } else if (b->cls == float_class_inf) {
5173 - *r = *a;
5174 - n->cls = float_class_zero;
5175 - n->sign = a->sign ^ b->sign;
5176 - *cc = 0;
5177 - } else {
5178 - FloatParts64 *q, q_buf, r_precise;
5179 - int float_exception_flags = 0;
5180 - bool is_q_smallish;
5181 - uint32_t r_flags;
5182 -
5183 - /* Compute precise quotient */
5184 - q_buf = parts64_div(a, b, status);
5185 - q = &q_buf;
5186 -
5187 - /*
5188 - * Check whether two closest integers can be precisely represented,
5189 - * i.e., all their bits fit into the fractional part.
5190 - */
5191 - is_q_smallish = q->exp < (fmt->frac_size + 1);
5192 -
5193 - /*
5194 - * Final quotient is rounded using final-quotient-rounding method, and
5195 - * partial quotient is rounded toward zero.
5196 - *
5197 - * Rounding of partial quotient may be inexact. This is the whole point
5198 - * of distinguishing partial quotients, so ignore the exception.
5199 - */
5200 - *n = parts64_round_to_int(q,
5201 - is_q_smallish
5202 - ? final_quotient_rounding_mode
5203 - : float_round_to_zero,
5204 - 0, status, fmt);
5205 -
5206 - /* Compute precise remainder */
5207 - r_precise = parts64_muladd(b, n, a,
5208 - float_muladd_negate_product, status);
5209 -
5210 - /* Round remainder to the target format */
5211 - *r = r_precise;
5212 - status->float_exception_flags = 0;
5213 - *r = parts64_round_to_fmt(r, status, fmt);
5214 - r_flags = status->float_exception_flags;
5215 -
5216 - /* POp table "Results: DIVIDE TO INTEGER (Part 2 of 2)" */
5217 - if (is_q_smallish) {
5218 - if (r->cls != float_class_zero) {
5219 - if (r->exp < 2 - (1 << (fmt->exp_size - 1))) {
5220 - if (mask_underflow) {
5221 - float_exception_flags |= float_flag_underflow;
5222 - *dxc = 0x10;
5223 - r->exp += fmt->exp_re_bias;
5224 - }
5225 - } else if (r_flags & float_flag_inexact) {
5226 - float_exception_flags |= float_flag_inexact;
5227 - if (mask_inexact) {
5228 - bool saved_r_sign, saved_r_precise_sign;
5229 -
5230 - /*
5231 - * Check whether remainder was truncated (rounded
5232 - * toward zero) or incremented.
5233 - */
5234 - saved_r_sign = r->sign;
5235 - saved_r_precise_sign = r_precise.sign;
5236 - r->sign = false;
5237 - r_precise.sign = false;
5238 - if (parts64_compare(r, &r_precise, status, true) <
5239 - float_relation_equal) {
5240 - *dxc = 0x8;
5241 - } else {
5242 - *dxc = 0xc;
5243 - }
5244 - r->sign = saved_r_sign;
5245 - r_precise.sign = saved_r_precise_sign;
5246 - }
5247 - }
5248 - }
5249 - *cc = 0;
5250 - } else if (n->exp > (1 << (fmt->exp_size - 1)) - 1) {
5251 - n->exp -= fmt->exp_re_bias;
5252 - *cc = r->cls == float_class_zero ? 1 : 3;
5253 - } else {
5254 - *cc = r->cls == float_class_zero ? 0 : 2;
5255 - }
5256 -
5257 - /* Adjust signs of zero results */
5258 - if (r->cls == float_class_zero) {
5259 - r->sign = a->sign;
5260 - }
5261 - if (n->cls == float_class_zero) {
5262 - n->sign = a->sign ^ b->sign;
5263 - }
5264 -
5265 - status->float_exception_flags = float_exception_flags;
5266 - }
5267 -}
5268 -
5269 -#define DEFINE_S390_DIVIDE_TO_INTEGER(floatN) \
5270 -void floatN ## _s390_divide_to_integer(floatN a, floatN b, \
5271 - int final_quotient_rounding_mode, \
5272 - bool mask_underflow, bool mask_inexact, \
5273 - floatN *r, floatN *n, \
5274 - uint32_t *cc, int *dxc, \
5275 - float_status *status) \
5276 -{ \
5277 - FloatParts64 pa = floatN ## _unpack_canonical(a, status); \
5278 - FloatParts64 pb = floatN ## _unpack_canonical(b, status); \
5279 - FloatParts64 pr, pn; \
5280 - parts_s390_divide_to_integer(&pa, &pb, final_quotient_rounding_mode, \
5281 - mask_underflow, mask_inexact, \
5282 - &floatN ## _params, \
5283 - &pr, &pn, cc, dxc, status); \
5284 - *r = floatN ## _round_pack_canonical(&pr, status); \
5285 - *n = floatN ## _round_pack_canonical(&pn, status); \
5286 -}
5287 -
5288 -DEFINE_S390_DIVIDE_TO_INTEGER(float32)
5289 -DEFINE_S390_DIVIDE_TO_INTEGER(float64)
5290 -
5154 static void __attribute__((constructor)) softfloat_init(void)
5155 {
5156 union_float64 ua, ub, uc, ur;
include/fpu/softfloat.h
-11
@@ -1386,15 +1386,4 @@ static inline bool float128_unordered_quiet(float128 a, float128 b,
1386 *----------------------------------------------------------------------------*/
1387 float128 float128_default_nan(float_status *status);
1388
1389 -#define DECLARE_S390_DIVIDE_TO_INTEGER(floatN) \
1390 -void floatN ## _s390_divide_to_integer(floatN a, floatN b, \
1391 - int final_quotient_rounding_mode, \
1392 - bool mask_underflow, bool mask_inexact, \
1393 - floatN *r, floatN *n, \
1394 - uint32_t *cc, int *dxc, \
1395 - float_status *status)
1396 -DECLARE_S390_DIVIDE_TO_INTEGER(float32);
1397 -DECLARE_S390_DIVIDE_TO_INTEGER(float64);
1398 -
1399 -
1389 #endif /* SOFTFLOAT_H */
target/s390x/tcg/fpu_helper.c
+135
@@ -24,6 +24,7 @@
24 #include "tcg_s390x.h"
25 #include "exec/helper-proto.h"
26 #include "fpu/softfloat.h"
27 +#include "fpu/softfloat-parts.h"
28
29 /* #define DEBUG_HELPER */
30 #ifdef DEBUG_HELPER
@@ -315,6 +316,140 @@ Int128 HELPER(dxb)(CPUS390XState *env, Int128 a, Int128 b)
316 return RET128(ret);
317 }
318
319 +static void parts_s390_divide_to_integer(FloatParts64 *a, FloatParts64 *b,
320 + int final_quotient_rounding_mode,
321 + bool mask_underflow, bool mask_inexact,
322 + const FloatFmt *fmt,
323 + FloatParts64 *r, FloatParts64 *n,
324 + uint32_t *cc, int *dxc,
325 + float_status *status)
326 +{
327 + /* POp table "Results: DIVIDE TO INTEGER (Part 1 of 2)" */
328 + if ((float_cmask(a->cls) | float_cmask(b->cls)) & float_cmask_anynan) {
329 + *r = parts64_pick_nan(a, b, status);
330 + *n = *r;
331 + *cc = 1;
332 + } else if (a->cls == float_class_inf || b->cls == float_class_zero) {
333 + *r = parts64_default_nan(status);
334 + *n = *r;
335 + *cc = 1;
336 + status->float_exception_flags |= float_flag_invalid;
337 + } else if (b->cls == float_class_inf) {
338 + *r = *a;
339 + n->cls = float_class_zero;
340 + n->sign = a->sign ^ b->sign;
341 + *cc = 0;
342 + } else {
343 + FloatParts64 *q, q_buf, r_precise;
344 + int float_exception_flags = 0;
345 + bool is_q_smallish;
346 + uint32_t r_flags;
347 +
348 + /* Compute precise quotient */
349 + q_buf = parts64_div(a, b, status);
350 + q = &q_buf;
351 +
352 + /*
353 + * Check whether two closest integers can be precisely represented,
354 + * i.e., all their bits fit into the fractional part.
355 + */
356 + is_q_smallish = q->exp < (fmt->frac_size + 1);
357 +
358 + /*
359 + * Final quotient is rounded using final-quotient-rounding method, and
360 + * partial quotient is rounded toward zero.
361 + *
362 + * Rounding of partial quotient may be inexact. This is the whole point
363 + * of distinguishing partial quotients, so ignore the exception.
364 + */
365 + *n = parts64_round_to_int(q,
366 + is_q_smallish
367 + ? final_quotient_rounding_mode
368 + : float_round_to_zero,
369 + 0, status, fmt);
370 +
371 + /* Compute precise remainder */
372 + r_precise = parts64_muladd(b, n, a,
373 + float_muladd_negate_product, status);
374 +
375 + /* Round remainder to the target format */
376 + *r = r_precise;
377 + status->float_exception_flags = 0;
378 + *r = parts64_round_to_fmt(r, status, fmt);
379 + r_flags = status->float_exception_flags;
380 +
381 + /* POp table "Results: DIVIDE TO INTEGER (Part 2 of 2)" */
382 + if (is_q_smallish) {
383 + if (r->cls != float_class_zero) {
384 + if (r->exp < 2 - (1 << (fmt->exp_size - 1))) {
385 + if (mask_underflow) {
386 + float_exception_flags |= float_flag_underflow;
387 + *dxc = 0x10;
388 + r->exp += fmt->exp_re_bias;
389 + }
390 + } else if (r_flags & float_flag_inexact) {
391 + float_exception_flags |= float_flag_inexact;
392 + if (mask_inexact) {
393 + bool saved_r_sign, saved_r_precise_sign;
394 +
395 + /*
396 + * Check whether remainder was truncated (rounded
397 + * toward zero) or incremented.
398 + */
399 + saved_r_sign = r->sign;
400 + saved_r_precise_sign = r_precise.sign;
401 + r->sign = false;
402 + r_precise.sign = false;
403 + if (parts64_compare(r, &r_precise, status, true) <
404 + float_relation_equal) {
405 + *dxc = 0x8;
406 + } else {
407 + *dxc = 0xc;
408 + }
409 + r->sign = saved_r_sign;
410 + r_precise.sign = saved_r_precise_sign;
411 + }
412 + }
413 + }
414 + *cc = 0;
415 + } else if (n->exp > (1 << (fmt->exp_size - 1)) - 1) {
416 + n->exp -= fmt->exp_re_bias;
417 + *cc = r->cls == float_class_zero ? 1 : 3;
418 + } else {
419 + *cc = r->cls == float_class_zero ? 0 : 2;
420 + }
421 +
422 + /* Adjust signs of zero results */
423 + if (r->cls == float_class_zero) {
424 + r->sign = a->sign;
425 + }
426 + if (n->cls == float_class_zero) {
427 + n->sign = a->sign ^ b->sign;
428 + }
429 +
430 + status->float_exception_flags = float_exception_flags;
431 + }
432 +}
433 +
434 +#define DEFINE_S390_DIVIDE_TO_INTEGER(floatN) \
435 +static void floatN ## _s390_divide_to_integer(floatN a, floatN b, \
436 + int final_quotient_rounding_mode, bool mask_underflow, bool mask_inexact, \
437 + floatN *r, floatN *n, uint32_t *cc, int *dxc, float_status *status) \
438 +{ \
439 + FloatParts64 pa = floatN ## _unpack_canonical(a, status); \
440 + FloatParts64 pb = floatN ## _unpack_canonical(b, status); \
441 + FloatParts64 pr, pn; \
442 + parts_s390_divide_to_integer(&pa, &pb, final_quotient_rounding_mode, \
443 + mask_underflow, mask_inexact, \
444 + &floatN ## _params, \
445 + &pr, &pn, cc, dxc, status); \
446 + *r = floatN ## _round_pack_canonical(&pr, status); \
447 + *n = floatN ## _round_pack_canonical(&pn, status); \
448 +}
449 +
450 +DEFINE_S390_DIVIDE_TO_INTEGER(float32)
451 +DEFINE_S390_DIVIDE_TO_INTEGER(float64)
452 +
453 void HELPER(dib)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3,
454 uint32_t m4, uint32_t bits)
455 {