diff options
author | Helge Deller <deller@gmx.de> | 2022-08-05 09:03:43 +0200 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2022-08-05 10:43:48 +0200 |
commit | 05ab9d3921cd267bdc61f4517e954e05620c98e1 (patch) | |
tree | 030bcb079038f55f3209c16b90d2f1b2396299ed | |
parent | dc64a651f6bd83ca22b6c7a90ac486cb853f0356 (diff) | |
download | palo-05ab9d3921cd267bdc61f4517e954e05620c98e1.tar.gz |
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>
-rw-r--r-- | ipl/vsprintf.c | 29 |
1 files changed, 24 insertions, 5 deletions
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 @@ static int skip_atoi(const char **s) #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 @@ static char * number(char * str, unsigned long long num, int base, int size, int 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 @@ again: 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'; |