From: Jim Wilson Date: Wed, 21 Dec 2016 20:33:12 +0000 (-0800) Subject: Fix bugs with float compare and Inf operands. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=87903eafb083abbf330c22fbf941fcbad700c098;p=binutils-gdb.git Fix bugs with float compare and Inf operands. sim/aarch64/ * simulator.c (set_flags_for_float_compare): Add code to handle Inf. Add comment to document NaN issue. (set_flags_for_double_compare): Likewise. sim/testsuite/sim/aarch64/ * fcmp.s: New. --- diff --git a/sim/aarch64/ChangeLog b/sim/aarch64/ChangeLog index 2346a499adc..b1baf26d9bf 100644 --- a/sim/aarch64/ChangeLog +++ b/sim/aarch64/ChangeLog @@ -1,3 +1,9 @@ +2016-12-21 Jim Wilson + + * simulator.c (set_flags_for_float_compare): Add code to handle Inf. + Add comment to document NaN issue. + (set_flags_for_double_compare): Likewise. + 2016-12-13 Jim Wilson * simulator.c (NEG, POS): Move before set_flags_for_add64. diff --git a/sim/aarch64/simulator.c b/sim/aarch64/simulator.c index e6406dcfc7b..be3d6c7e52b 100644 --- a/sim/aarch64/simulator.c +++ b/sim/aarch64/simulator.c @@ -8468,8 +8468,22 @@ set_flags_for_float_compare (sim_cpu *cpu, float fvalue1, float fvalue2) { uint32_t flags; + /* FIXME: Add exception raising. */ if (isnan (fvalue1) || isnan (fvalue2)) flags = C|V; + else if (isinf (fvalue1) && isinf (fvalue2)) + { + /* Subtracting two infinities may give a NaN. We only need to compare + the signs, which we can get from isinf. */ + int result = isinf (fvalue1) - isinf (fvalue2); + + if (result == 0) + flags = Z|C; + else if (result < 0) + flags = N; + else /* (result > 0). */ + flags = C; + } else { float result = fvalue1 - fvalue2; @@ -8540,8 +8554,22 @@ set_flags_for_double_compare (sim_cpu *cpu, double dval1, double dval2) { uint32_t flags; + /* FIXME: Add exception raising. */ if (isnan (dval1) || isnan (dval2)) flags = C|V; + else if (isinf (dval1) && isinf (dval2)) + { + /* Subtracting two infinities may give a NaN. We only need to compare + the signs, which we can get from isinf. */ + int result = isinf (dval1) - isinf (dval2); + + if (result == 0) + flags = Z|C; + else if (result < 0) + flags = N; + else /* (result > 0). */ + flags = C; + } else { double result = dval1 - dval2; diff --git a/sim/testsuite/sim/aarch64/ChangeLog b/sim/testsuite/sim/aarch64/ChangeLog index ff047e3973a..a130a975b9b 100644 --- a/sim/testsuite/sim/aarch64/ChangeLog +++ b/sim/testsuite/sim/aarch64/ChangeLog @@ -1,3 +1,7 @@ +2016-12-21 Jim Wilson + + * fcmp.s: New. + 2016-12-13 Jim Wilson * testutils.inc (pass): Move .Lpass to start. diff --git a/sim/testsuite/sim/aarch64/fcmp.s b/sim/testsuite/sim/aarch64/fcmp.s new file mode 100644 index 00000000000..fd826c4873d --- /dev/null +++ b/sim/testsuite/sim/aarch64/fcmp.s @@ -0,0 +1,146 @@ +# mach: aarch64 + +# Check the FP compare instructions: fcmps, fcmpzs, fcmpes, fcmpzes, fcmpd, +# fcmpzd, fcmped, fcmpzed. +# For 1 operand compares, check 0, 1, -1, +Inf, -Inf. +# For 2 operand compares, check 1/1, 1/-2, -1/2, +Inf/+Inf, +Inf/-Inf. +# FIXME: Check for qNaN and sNaN when exception raising support added. + +.include "testutils.inc" + + start + fmov s0, wzr + fcmp s0, #0.0 + bne .Lfailure + fcmpe s0, #0.0 + bne .Lfailure + fmov d0, xzr + fcmp d0, #0.0 + bne .Lfailure + fcmpe d0, #0.0 + bne .Lfailure + + fmov s0, #1.0 + fcmp s0, #0.0 + blo .Lfailure + fcmpe s0, #0.0 + blo .Lfailure + fmov d0, #1.0 + fcmp d0, #0.0 + blo .Lfailure + fcmpe d0, #0.0 + blo .Lfailure + + fmov s0, #-1.0 + fcmp s0, #0.0 + bpl .Lfailure + fcmpe s0, #0.0 + bpl .Lfailure + fmov d0, #-1.0 + fcmp d0, #0.0 + bpl .Lfailure + fcmpe d0, #0.0 + bpl .Lfailure + + fmov s0, #1.0 + fmov s1, wzr + fdiv s0, s0, s1 + fcmp s0, #0.0 + blo .Lfailure + fcmpe s0, #0.0 + blo .Lfailure + fmov d0, #1.0 + fmov d1, xzr + fdiv d0, d0, d1 + fcmp d0, #0.0 + blo .Lfailure + fcmpe d0, #0.0 + blo .Lfailure + + fmov s0, #-1.0 + fmov s1, wzr + fdiv s0, s0, s1 + fcmp s0, #0.0 + bpl .Lfailure + fcmpe s0, #0.0 + bpl .Lfailure + fmov d0, #-1.0 + fmov d1, xzr + fdiv d0, d0, d1 + fcmp d0, #0.0 + bpl .Lfailure + fcmpe d0, #0.0 + bpl .Lfailure + + fmov s0, #1.0 + fmov s1, #1.0 + fcmp s0, s1 + bne .Lfailure + fcmpe s0, s1 + bne .Lfailure + fmov d0, #1.0 + fmov d1, #1.0 + fcmp d0, d1 + bne .Lfailure + fcmpe d0, d1 + bne .Lfailure + + fmov s0, #1.0 + fmov s1, #-2.0 + fcmp s0, s1 + blo .Lfailure + fcmpe s0, s1 + blo .Lfailure + fmov d0, #1.0 + fmov d1, #-2.0 + fcmp d0, d1 + blo .Lfailure + fcmpe d0, d1 + blo .Lfailure + + fmov s0, #-1.0 + fmov s1, #2.0 + fcmp s0, s1 + bpl .Lfailure + fcmpe s0, s1 + bpl .Lfailure + fmov d0, #-1.0 + fmov d1, #2.0 + fcmp d0, d1 + bpl .Lfailure + fcmpe d0, d1 + bpl .Lfailure + + fmov s0, #1.0 + fmov s1, wzr + fdiv s0, s0, s1 + fcmp s0, s0 + bne .Lfailure + fcmpe s0, s0 + bne .Lfailure + fmov s1, #-1.0 + fmov s2, wzr + fdiv s1, s1, s2 + fcmp s0, s1 + blo .Lfailure + fcmpe s0, s1 + blo .Lfailure + + fmov d0, #1.0 + fmov d1, xzr + fdiv d0, d0, d1 + fcmp d0, d0 + bne .Lfailure + fcmpe d0, d0 + bne .Lfailure + fmov d1, #-1.0 + fmov d2, xzr + fdiv d1, d1, d2 + fcmp d0, d1 + blo .Lfailure + fcmpe d0, d1 + blo .Lfailure + + pass +.Lfailure: + fail