From 2830b0b8655f0d1a62b416af8ade31f5b96f0ffb Mon Sep 17 00:00:00 2001
From: Georg-Johann Lay <avr@gjlay.de>
Date: Fri, 14 Jun 2024 18:24:13 +0200
Subject: [PATCH] AVR: target/115419 - Tie breaks are rounded-to-even.

libgcc/config/avr/libf7/
	PR target/115419
	* libf7.c (f7_get_double): Round tie breaks to even LSB.
---
 libgcc/config/avr/libf7/libf7.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/libgcc/config/avr/libf7/libf7.c b/libgcc/config/avr/libf7/libf7.c
index 375becb854c1..6fae4fc1a2de 100644
--- a/libgcc/config/avr/libf7/libf7.c
+++ b/libgcc/config/avr/libf7/libf7.c
@@ -440,11 +440,21 @@ f7_double_t f7_get_double (const f7_t *aa)
 
   mant &= 0x00ffffffffffffff;
 
-  // FIXME: For subnormals, rounding is premature and should be
-  //	    done *after* the mantissa has been shifted into place
-  //	    (or the round value be shifted left accordingly).
-  // Round.
-  mant += 1u << (F7_MANT_BITS - (1 + DBL_DIG_MANT) - 1);
+  // PR115419: The least significant nibble tells how to round:
+  // Tie breaks are rounded to even (Banker's rounding).
+  uint8_t lsn = mant & 0xff;
+  lsn &= 0xf;
+  // The LSB of the outgoing double is at bit 3.
+  if (lsn & (1 << 3))
+    ++lsn;
+  if (lsn > (1 << 2))
+    {
+      // FIXME: For subnormals, rounding is premature and should be
+      //        done *after* the mantissa has been shifted into place
+      //        (or the round value be shifted left accordingly).
+      // Round.
+      mant += 1u << (F7_MANT_BITS - (1 + DBL_DIG_MANT) - 1);
+    }
 
   uint8_t dex;
   register uint64_t r18 __asm ("r18") = mant;
-- 
GitLab