return floatx80_round_pack_canonical(&p, status);
}
-static void parts_s390_divide_to_integer(FloatParts64 *a, FloatParts64 *b,
- int final_quotient_rounding_mode,
- bool mask_underflow, bool mask_inexact,
- 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 = parts64_pick_nan(a, b, status);
- *n = *r;
- *cc = 1;
- } else if (a->cls == float_class_inf || b->cls == float_class_zero) {
- *r = parts64_default_nan(status);
- *n = *r;
- *cc = 1;
- status->float_exception_flags |= float_flag_invalid;
- } else if (b->cls == float_class_inf) {
- *r = *a;
- n->cls = float_class_zero;
- n->sign = a->sign ^ b->sign;
- *cc = 0;
- } else {
- FloatParts64 *q, q_buf, r_precise;
- int float_exception_flags = 0;
- bool is_q_smallish;
- uint32_t r_flags;
-
- /* Compute precise quotient */
- q_buf = parts64_div(a, b, status);
- q = &q_buf;
-
- /*
- * Check whether two closest integers can be precisely represented,
- * i.e., all their bits fit into the fractional part.
- */
- is_q_smallish = 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 = parts64_round_to_int(q,
- is_q_smallish
- ? final_quotient_rounding_mode
- : float_round_to_zero,
- 0, status, fmt);
-
- /* Compute precise remainder */
- r_precise = parts64_muladd(b, n, a,
- float_muladd_negate_product, status);
-
- /* Round remainder to the target format */
- *r = r_precise;
- status->float_exception_flags = 0;
- *r = parts64_round_to_fmt(r, status, fmt);
- r_flags = status->float_exception_flags;
-
- /* POp table "Results: DIVIDE TO INTEGER (Part 2 of 2)" */
- if (is_q_smallish) {
- if (r->cls != float_class_zero) {
- if (r->exp < 2 - (1 << (fmt->exp_size - 1))) {
- if (mask_underflow) {
- float_exception_flags |= float_flag_underflow;
- *dxc = 0x10;
- r->exp += fmt->exp_re_bias;
- }
- } else if (r_flags & float_flag_inexact) {
- float_exception_flags |= 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 = r->sign;
- saved_r_precise_sign = r_precise.sign;
- r->sign = false;
- r_precise.sign = false;
- if (parts64_compare(r, &r_precise, status, true) <
- float_relation_equal) {
- *dxc = 0x8;
- } else {
- *dxc = 0xc;
- }
- r->sign = saved_r_sign;
- r_precise.sign = saved_r_precise_sign;
- }
- }
- }
- *cc = 0;
- } else if (n->exp > (1 << (fmt->exp_size - 1)) - 1) {
- n->exp -= fmt->exp_re_bias;
- *cc = r->cls == float_class_zero ? 1 : 3;
- } else {
- *cc = r->cls == float_class_zero ? 0 : 2;
- }
-
- /* Adjust signs of zero results */
- if (r->cls == float_class_zero) {
- r->sign = a->sign;
- }
- if (n->cls == float_class_zero) {
- n->sign = a->sign ^ b->sign;
- }
-
- status->float_exception_flags = 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_inexact, \
- floatN *r, floatN *n, \
- uint32_t *cc, int *dxc, \
- float_status *status) \
-{ \
- FloatParts64 pa = floatN ## _unpack_canonical(a, status); \
- FloatParts64 pb = 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 = floatN ## _round_pack_canonical(&pr, status); \
- *n = 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;
*----------------------------------------------------------------------------*/
float128 float128_default_nan(float_status *status);
-#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_inexact, \
- 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 */
#include "tcg_s390x.h"
#include "exec/helper-proto.h"
#include "fpu/softfloat.h"
+#include "fpu/softfloat-parts.h"
/* #define DEBUG_HELPER */
#ifdef DEBUG_HELPER
return RET128(ret);
}
+static void parts_s390_divide_to_integer(FloatParts64 *a, FloatParts64 *b,
+ int final_quotient_rounding_mode,
+ bool mask_underflow, bool mask_inexact,
+ 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 = parts64_pick_nan(a, b, status);
+ *n = *r;
+ *cc = 1;
+ } else if (a->cls == float_class_inf || b->cls == float_class_zero) {
+ *r = parts64_default_nan(status);
+ *n = *r;
+ *cc = 1;
+ status->float_exception_flags |= float_flag_invalid;
+ } else if (b->cls == float_class_inf) {
+ *r = *a;
+ n->cls = float_class_zero;
+ n->sign = a->sign ^ b->sign;
+ *cc = 0;
+ } else {
+ FloatParts64 *q, q_buf, r_precise;
+ int float_exception_flags = 0;
+ bool is_q_smallish;
+ uint32_t r_flags;
+
+ /* Compute precise quotient */
+ q_buf = parts64_div(a, b, status);
+ q = &q_buf;
+
+ /*
+ * Check whether two closest integers can be precisely represented,
+ * i.e., all their bits fit into the fractional part.
+ */
+ is_q_smallish = 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 = parts64_round_to_int(q,
+ is_q_smallish
+ ? final_quotient_rounding_mode
+ : float_round_to_zero,
+ 0, status, fmt);
+
+ /* Compute precise remainder */
+ r_precise = parts64_muladd(b, n, a,
+ float_muladd_negate_product, status);
+
+ /* Round remainder to the target format */
+ *r = r_precise;
+ status->float_exception_flags = 0;
+ *r = parts64_round_to_fmt(r, status, fmt);
+ r_flags = status->float_exception_flags;
+
+ /* POp table "Results: DIVIDE TO INTEGER (Part 2 of 2)" */
+ if (is_q_smallish) {
+ if (r->cls != float_class_zero) {
+ if (r->exp < 2 - (1 << (fmt->exp_size - 1))) {
+ if (mask_underflow) {
+ float_exception_flags |= float_flag_underflow;
+ *dxc = 0x10;
+ r->exp += fmt->exp_re_bias;
+ }
+ } else if (r_flags & float_flag_inexact) {
+ float_exception_flags |= 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 = r->sign;
+ saved_r_precise_sign = r_precise.sign;
+ r->sign = false;
+ r_precise.sign = false;
+ if (parts64_compare(r, &r_precise, status, true) <
+ float_relation_equal) {
+ *dxc = 0x8;
+ } else {
+ *dxc = 0xc;
+ }
+ r->sign = saved_r_sign;
+ r_precise.sign = saved_r_precise_sign;
+ }
+ }
+ }
+ *cc = 0;
+ } else if (n->exp > (1 << (fmt->exp_size - 1)) - 1) {
+ n->exp -= fmt->exp_re_bias;
+ *cc = r->cls == float_class_zero ? 1 : 3;
+ } else {
+ *cc = r->cls == float_class_zero ? 0 : 2;
+ }
+
+ /* Adjust signs of zero results */
+ if (r->cls == float_class_zero) {
+ r->sign = a->sign;
+ }
+ if (n->cls == float_class_zero) {
+ n->sign = a->sign ^ b->sign;
+ }
+
+ status->float_exception_flags = 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_inexact, \
+ floatN *r, floatN *n, uint32_t *cc, int *dxc, float_status *status) \
+{ \
+ FloatParts64 pa = floatN ## _unpack_canonical(a, status); \
+ FloatParts64 pb = 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 = floatN ## _round_pack_canonical(&pr, status); \
+ *n = 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)
{