tools/nolibc/stdlib: avoid a 64-bit shift in u64toh_r()
authorWilly Tarreau <w@1wt.eu>
Mon, 7 Feb 2022 16:23:37 +0000 (17:23 +0100)
committerPaul E. McKenney <paulmck@kernel.org>
Thu, 21 Apr 2022 00:05:44 +0000 (17:05 -0700)
The build of printf() on mips requires libgcc for functions __ashldi3 and
__lshrdi3 due to 64-bit shifts when scanning the input number. These are
not really needed in fact since we scan the number 4 bits at a time. Let's
arrange the loop to perform two 32-bit shifts instead on 32-bit platforms.

Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
tools/include/nolibc/stdlib.h

index 82a4cf6..db47362 100644 (file)
@@ -200,14 +200,18 @@ int u64toh_r(uint64_t in, char *buffer)
        int dig;
 
        do {
-               dig = in >> pos;
-               in -= (uint64_t)dig << pos;
+               if (sizeof(long) >= 8) {
+                       dig = (in >> pos) & 0xF;
+               } else {
+                       /* 32-bit platforms: avoid a 64-bit shift */
+                       uint32_t d = (pos >= 32) ? (in >> 32) : in;
+                       dig = (d >> (pos & 31)) & 0xF;
+               }
+               if (dig > 9)
+                       dig += 'a' - '0' - 10;
                pos -= 4;
-               if (dig || digits || pos < 0) {
-                       if (dig > 9)
-                               dig += 'a' - '0' - 10;
+               if (dig || digits || pos < 0)
                        buffer[digits++] = '0' + dig;
-               }
        } while (pos >= 0);
 
        buffer[digits] = 0;