Improve how our printk calls do_div by using constants.

The do_div code has a nice optimization in it when it is called with
constants. The current highly generalized use of it defeats those
optimizations and causes trouble on ARM, resulting in a complex and
buggy code path.

Since we only need to print in bases 8, 10, and 16, do a minor
restructuring of the code so that we call do_div with constants.
If you need base 2, print in base 16 and do it in your head. :-)

This fixes an ongoing problem with ARM, will not harm X86, and will
help PPC should we ever want to support it again.
Plus, I don't have to ever try to understand the div64 assembly and where
it's going wrong :-)

Change-Id: I6a480011916eb0834e05c5bb10909d83330fe797
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Reviewed-on: http://review.coreboot.org/2235
Tested-by: build bot (Jenkins)
Reviewed-by: David Hendricks <dhendrix@chromium.org>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Ronald G. Minnich 2013-01-30 14:29:34 -08:00 committed by David Hendricks
parent bc3abbbaf0
commit 79e36d9060
1 changed files with 16 additions and 2 deletions

View File

@ -69,8 +69,22 @@ static int number(void (*tx_byte)(unsigned char byte),
i = 0; i = 0;
if (num == 0) if (num == 0)
tmp[i++]='0'; tmp[i++]='0';
else while (num != 0) else while (num != 0){
tmp[i++] = digits[do_div(num,base)]; /* there are some nice optimizations in the
* Macros-From-Hell that form the div64 code
* *IF* you call it with a constant.
* We're firmware, we only do bases
* 8, 10, and 16. Let's be smart.
* This greatly helps ARM, reduces the
* code footprint at compile time, and does not hurt x86.
*/
if (base == 10)
tmp[i++] = digits[do_div(num,10)];
else if (base == 8)
tmp[i++] = digits[do_div(num,8)];
else /* sorry, you're out of choices */
tmp[i++] = digits[do_div(num,16)];
}
if (i > precision) if (i > precision)
precision = i; precision = i;
size -= precision; size -= precision;