From b6af5f3a74d9ed8d78e2467a895d5ae0b732f114 Mon Sep 17 00:00:00 2001 From: Faraz Shahbazker Date: Wed, 2 Feb 2022 11:17:23 +0100 Subject: [PATCH] sim: Factor out NaN handling in floating point operations 2022-02-01 Faraz Shahbazker sim/common/ChangeLog: * sim-fpu.c (sim_fpu_op_nan): New. (sim_fpu_add): Factor out NaN operand handling with a call to sim_fpu_op_nan. (sim_fpu_sub, sim_fpu_mul, sim_fpu_div): Likewise. (sim_fpu_rem, sim_fpu_max, sim_fpu_min): Likewise. * sim-fpu.h (sim_fpu_op_nan): New declaration. --- sim/common/sim-fpu.c | 189 +++++++------------------------------------ sim/common/sim-fpu.h | 10 +++ 2 files changed, 41 insertions(+), 158 deletions(-) diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c index 276ad234174..9174eaf17b4 100644 --- a/sim/common/sim-fpu.c +++ b/sim/common/sim-fpu.c @@ -986,7 +986,24 @@ sim_fpu_round_64 (sim_fpu *f, return do_round (f, 1, round, denorm); } +/* NaN handling for binary operations. */ +INLINE_SIM_FPU (int) +sim_fpu_op_nan (sim_fpu *f, const sim_fpu *l, const sim_fpu *r) +{ + if (sim_fpu_is_snan (l) || sim_fpu_is_snan (r)) + { + *f = sim_fpu_is_snan (l) ? *l : *r; + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + } + ASSERT (sim_fpu_is_nan (l) || sim_fpu_is_nan (r)); + if (sim_fpu_is_qnan (l)) + *f = *l; + else /* if (sim_fpu_is_qnan (r)) */ + *f = *r; + return 0; +} /* Arithmetic ops */ @@ -995,28 +1012,8 @@ sim_fpu_add (sim_fpu *f, const sim_fpu *l, const sim_fpu *r) { - if (sim_fpu_is_snan (l)) - { - *f = *l; - f->class = sim_fpu_class_qnan; - return sim_fpu_status_invalid_snan; - } - if (sim_fpu_is_snan (r)) - { - *f = *r; - f->class = sim_fpu_class_qnan; - return sim_fpu_status_invalid_snan; - } - if (sim_fpu_is_qnan (l)) - { - *f = *l; - return 0; - } - if (sim_fpu_is_qnan (r)) - { - *f = *r; - return 0; - } + if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r)) + return sim_fpu_op_nan (f, l, r); if (sim_fpu_is_infinity (l)) { if (sim_fpu_is_infinity (r) @@ -1144,28 +1141,8 @@ sim_fpu_sub (sim_fpu *f, const sim_fpu *l, const sim_fpu *r) { - if (sim_fpu_is_snan (l)) - { - *f = *l; - f->class = sim_fpu_class_qnan; - return sim_fpu_status_invalid_snan; - } - if (sim_fpu_is_snan (r)) - { - *f = *r; - f->class = sim_fpu_class_qnan; - return sim_fpu_status_invalid_snan; - } - if (sim_fpu_is_qnan (l)) - { - *f = *l; - return 0; - } - if (sim_fpu_is_qnan (r)) - { - *f = *r; - return 0; - } + if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r)) + return sim_fpu_op_nan (f, l, r); if (sim_fpu_is_infinity (l)) { if (sim_fpu_is_infinity (r) @@ -1298,28 +1275,8 @@ sim_fpu_mul (sim_fpu *f, const sim_fpu *l, const sim_fpu *r) { - if (sim_fpu_is_snan (l)) - { - *f = *l; - f->class = sim_fpu_class_qnan; - return sim_fpu_status_invalid_snan; - } - if (sim_fpu_is_snan (r)) - { - *f = *r; - f->class = sim_fpu_class_qnan; - return sim_fpu_status_invalid_snan; - } - if (sim_fpu_is_qnan (l)) - { - *f = *l; - return 0; - } - if (sim_fpu_is_qnan (r)) - { - *f = *r; - return 0; - } + if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r)) + return sim_fpu_op_nan (f, l, r); if (sim_fpu_is_infinity (l)) { if (sim_fpu_is_zero (r)) @@ -1423,30 +1380,8 @@ sim_fpu_div (sim_fpu *f, const sim_fpu *l, const sim_fpu *r) { - if (sim_fpu_is_snan (l)) - { - *f = *l; - f->class = sim_fpu_class_qnan; - return sim_fpu_status_invalid_snan; - } - if (sim_fpu_is_snan (r)) - { - *f = *r; - f->class = sim_fpu_class_qnan; - return sim_fpu_status_invalid_snan; - } - if (sim_fpu_is_qnan (l)) - { - *f = *l; - f->class = sim_fpu_class_qnan; - return 0; - } - if (sim_fpu_is_qnan (r)) - { - *f = *r; - f->class = sim_fpu_class_qnan; - return 0; - } + if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r)) + return sim_fpu_op_nan (f, l, r); if (sim_fpu_is_infinity (l)) { if (sim_fpu_is_infinity (r)) @@ -1556,30 +1491,8 @@ sim_fpu_rem (sim_fpu *f, const sim_fpu *l, const sim_fpu *r) { - if (sim_fpu_is_snan (l)) - { - *f = *l; - f->class = sim_fpu_class_qnan; - return sim_fpu_status_invalid_snan; - } - if (sim_fpu_is_snan (r)) - { - *f = *r; - f->class = sim_fpu_class_qnan; - return sim_fpu_status_invalid_snan; - } - if (sim_fpu_is_qnan (l)) - { - *f = *l; - f->class = sim_fpu_class_qnan; - return 0; - } - if (sim_fpu_is_qnan (r)) - { - *f = *r; - f->class = sim_fpu_class_qnan; - return 0; - } + if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r)) + return sim_fpu_op_nan (f, l, r); if (sim_fpu_is_infinity (l)) { *f = sim_fpu_qnan; @@ -1639,28 +1552,8 @@ sim_fpu_max (sim_fpu *f, const sim_fpu *l, const sim_fpu *r) { - if (sim_fpu_is_snan (l)) - { - *f = *l; - f->class = sim_fpu_class_qnan; - return sim_fpu_status_invalid_snan; - } - if (sim_fpu_is_snan (r)) - { - *f = *r; - f->class = sim_fpu_class_qnan; - return sim_fpu_status_invalid_snan; - } - if (sim_fpu_is_qnan (l)) - { - *f = *l; - return 0; - } - if (sim_fpu_is_qnan (r)) - { - *f = *r; - return 0; - } + if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r)) + return sim_fpu_op_nan (f, l, r); if (sim_fpu_is_infinity (l)) { if (sim_fpu_is_infinity (r) @@ -1722,28 +1615,8 @@ sim_fpu_min (sim_fpu *f, const sim_fpu *l, const sim_fpu *r) { - if (sim_fpu_is_snan (l)) - { - *f = *l; - f->class = sim_fpu_class_qnan; - return sim_fpu_status_invalid_snan; - } - if (sim_fpu_is_snan (r)) - { - *f = *r; - f->class = sim_fpu_class_qnan; - return sim_fpu_status_invalid_snan; - } - if (sim_fpu_is_qnan (l)) - { - *f = *l; - return 0; - } - if (sim_fpu_is_qnan (r)) - { - *f = *r; - return 0; - } + if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r)) + return sim_fpu_op_nan (f, l, r); if (sim_fpu_is_infinity (l)) { if (sim_fpu_is_infinity (r) diff --git a/sim/common/sim-fpu.h b/sim/common/sim-fpu.h index b0b318cb283..2a141981687 100644 --- a/sim/common/sim-fpu.h +++ b/sim/common/sim-fpu.h @@ -261,6 +261,16 @@ INLINE_SIM_FPU (int) sim_fpu_sqrt (sim_fpu *f, +/* NaN handling. + + Assuming that at least one of the inputs is NAN choose the correct + NAN result for the binary operation. */ + +INLINE_SIM_FPU (int) sim_fpu_op_nan (sim_fpu *f, + const sim_fpu *l, const sim_fpu *r); + + + /* Conversion of integer <-> floating point. */ INLINE_SIM_FPU (int) sim_fpu_i32to (sim_fpu *f, int32_t i, -- 2.30.2