https://gcc.gnu.org/g:e6f2daff77ee1f709105cb9f8e3e92f04c179431

commit r16-2173-ge6f2daff77ee1f709105cb9f8e3e92f04c179431
Author: Jan Dubiec <j...@o2.pl>
Date:   Thu Jul 10 07:41:08 2025 -0600

    [PATCH] libgcc: PR target/116363 Fix SFtype to UDWtype conversion
    
    This patch fixes SFtype to UDWtype (aka float to unsigned long long)
    conversion on targets without DFmode like e.g. H8/300H. It solely relies
    on SFtype->UWtype and UWtype->UDWtype conversions/casts. The existing code
    in line 2218 (counter = a) assigns/casts a float which is *always* not 
lesser
    than Wtype_MAXp1_F to an UWtype int which of course does not have enough
    capacity.
    
            PR target/116363
    
    libgcc/ChangeLog:
    
            * libgcc2.c (__fixunssfDI): Fix SFtype to UDWtype conversion for 
targets
            without LIBGCC2_HAS_DF_MODE defined

Diff:
---
 libgcc/libgcc2.c | 41 +++++++++++++----------------------------
 1 file changed, 13 insertions(+), 28 deletions(-)

diff --git a/libgcc/libgcc2.c b/libgcc/libgcc2.c
index faefff3730ca..df99c78eb204 100644
--- a/libgcc/libgcc2.c
+++ b/libgcc/libgcc2.c
@@ -2187,36 +2187,21 @@ __fixunssfDI (SFtype a)
   if (a < 1)
     return 0;
   if (a < Wtype_MAXp1_F)
-    return (UWtype)a;
+    return (UWtype) a;
   if (a < Wtype_MAXp1_F * Wtype_MAXp1_F)
     {
-      /* Since we know that there are fewer significant bits in the SFmode
-        quantity than in a word, we know that we can convert out all the
-        significant bits in one step, and thus avoid losing bits.  */
-
-      /* ??? This following loop essentially performs frexpf.  If we could
-        use the real libm function, or poke at the actual bits of the fp
-        format, it would be significantly faster.  */
-
-      UWtype shift = 0, counter;
-      SFtype msb;
-
-      a /= Wtype_MAXp1_F;
-      for (counter = W_TYPE_SIZE / 2; counter != 0; counter >>= 1)
-       {
-         SFtype counterf = (UWtype)1 << counter;
-         if (a >= counterf)
-           {
-             shift |= counter;
-             a /= counterf;
-           }
-       }
-
-      /* Rescale into the range of one word, extract the bits of that
-        one word, and shift the result into position.  */
-      a *= Wtype_MAXp1_F;
-      counter = a;
-      return (DWtype)counter << shift;
+      /* We assume that SFtype -> UWtype and UWtype -> UDWtype casts work
+         properly. Obviously, we *cannot* assume that SFtype -> UDWtype
+         works as expected.  */
+      SFtype a_hi, a_lo;
+
+      a_hi = a / Wtype_MAXp1_F;
+      a_lo = a - a_hi * Wtype_MAXp1_F;
+
+      /* A lot of parentheses. This is to make it very clear what is
+         the sequence of operations.  */
+      return ((UDWtype) ((UWtype) a_hi)) << W_TYPE_SIZE
+            | (UDWtype) ((UWtype) a_lo);
     }
   return -1;
 #else

Reply via email to