ipl: Avoid usage of __umoddi3 and __udivdi3 when printing numbers

At palo boot time we don't have an exception handler installed yet.
So we must avoid using __umoddi3 and __udivdi3 (which use floating point
instructions).

This is a trivial work-around to simply output all integer values
which are bigger than 32-bit as hex-values only. For hex-printing
we can use bitshifts which don't need to be emulated.

Signed-off-by: Helge Deller <deller@gmx.de>
diff --git a/ipl/vsprintf.c b/ipl/vsprintf.c
index 4a7a060..052511a 100644
--- a/ipl/vsprintf.c
+++ b/ipl/vsprintf.c
@@ -36,10 +36,17 @@
 #define SPECIAL	32		/* 0x */
 #define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
 
-#define do_div(n,base) ({ \
+/* inline on "unsigned long", not "long long" to avoid using __umoddi3 and __udivdi3 */
+#define do_div_long(n,base) ({ \
 int __res; \
-__res = ((unsigned long long) n) % (unsigned) base; \
-n = ((unsigned long long) n) / (unsigned) base; \
+__res = ((unsigned long) n) % (unsigned) base; \
+n = ((unsigned long) n) / (unsigned) base; \
+__res; })
+
+#define do_div_hex(n) ({ \
+unsigned long __res; \
+__res = ((unsigned long) n) & 0x0f; \
+n >>= 4; \
 __res; })
 
 static char * number(char * str, unsigned long long num, int base, int size, int precision
@@ -79,8 +86,12 @@
 	i = 0;
 	if (num == 0)
 		tmp[i++]='0';
-	else while (num != 0)
-		tmp[i++] = digits[do_div(num,base)];
+	else while (num != 0) {
+		if (base == 16)
+			tmp[i++] = digits[do_div_hex(num)];
+		else
+			tmp[i++] = digits[do_div_long(num,base)];
+	}
 	if (i > precision)
 		precision = i;
 	size -= precision;
@@ -277,6 +288,14 @@
 			num = va_arg(args, int);
 		else
 			num = va_arg(args, unsigned int);
+		/* workaround to output all integers > 32bit as hex. Avoids millicode routines */
+		if (num >> 32) {
+			if (base != 16) { // append hex symbol "0x"
+				*str++ = '0';
+				*str++ = 'x';
+			}
+			base = 16;
+		}
 		str = number(str, num, base, field_width, precision, flags);
 	}
 	*str = '\0';