mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-28 15:13:31 +08:00
tiny-printf: Adjust to avoid using data section
We can pass all the variables down to the functions that need them, and then everything is on the stack. This is safer than using the data section. At least on firefly-rk3288, the code size is the same and the data size is 12 bytes smaller: before: 18865 2636 40 21541 5425 b/firefly-rk3288/spl/u-boot-spl after: 18865 2624 40 21529 5419 b/firefly-rk3288/spl/u-boot-spl Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Tom Rini <trini@konsulko.com> Reviewed-by: Stefan Roese <sr@denx.de>
This commit is contained in:
parent
43caa9a879
commit
45313e83b8
@ -13,29 +13,33 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <serial.h>
|
#include <serial.h>
|
||||||
|
|
||||||
/*
|
struct printf_info {
|
||||||
* This code in here may execute before the DRAM is initialised, so
|
char *bf; /* Digit buffer */
|
||||||
* we should make sure that it doesn't touch BSS, which some boards
|
char zs; /* non-zero if a digit has been written */
|
||||||
* put in DRAM.
|
char *outstr; /* Next output position for sprintf() */
|
||||||
*/
|
|
||||||
static char *bf __attribute__ ((section(".data")));
|
|
||||||
static char zs __attribute__ ((section(".data")));
|
|
||||||
|
|
||||||
/* Current position in sprintf() output string */
|
/* Output a character */
|
||||||
static char *outstr __attribute__ ((section(".data")));
|
void (*putc)(struct printf_info *info, char ch);
|
||||||
|
};
|
||||||
|
|
||||||
static void out(char c)
|
void putc_normal(struct printf_info *info, char ch)
|
||||||
{
|
{
|
||||||
*bf++ = c;
|
putc(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void out_dgt(char dgt)
|
static void out(struct printf_info *info, char c)
|
||||||
{
|
{
|
||||||
out(dgt + (dgt < 10 ? '0' : 'a' - 10));
|
*info->bf++ = c;
|
||||||
zs = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void div_out(unsigned int *num, unsigned int div)
|
static void out_dgt(struct printf_info *info, char dgt)
|
||||||
|
{
|
||||||
|
out(info, dgt + (dgt < 10 ? '0' : 'a' - 10));
|
||||||
|
info->zs = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void div_out(struct printf_info *info, unsigned int *num,
|
||||||
|
unsigned int div)
|
||||||
{
|
{
|
||||||
unsigned char dgt = 0;
|
unsigned char dgt = 0;
|
||||||
|
|
||||||
@ -44,11 +48,11 @@ static void div_out(unsigned int *num, unsigned int div)
|
|||||||
dgt++;
|
dgt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zs || dgt > 0)
|
if (info->zs || dgt > 0)
|
||||||
out_dgt(dgt);
|
out_dgt(info, dgt);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _vprintf(const char *fmt, va_list va, void (*putc)(const char ch))
|
int _vprintf(struct printf_info *info, const char *fmt, va_list va)
|
||||||
{
|
{
|
||||||
char ch;
|
char ch;
|
||||||
char *p;
|
char *p;
|
||||||
@ -58,7 +62,7 @@ int _vprintf(const char *fmt, va_list va, void (*putc)(const char ch))
|
|||||||
|
|
||||||
while ((ch = *(fmt++))) {
|
while ((ch = *(fmt++))) {
|
||||||
if (ch != '%') {
|
if (ch != '%') {
|
||||||
putc(ch);
|
info->putc(info, ch);
|
||||||
} else {
|
} else {
|
||||||
bool lz = false;
|
bool lz = false;
|
||||||
int width = 0;
|
int width = 0;
|
||||||
@ -76,9 +80,9 @@ int _vprintf(const char *fmt, va_list va, void (*putc)(const char ch))
|
|||||||
ch = *fmt++;
|
ch = *fmt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bf = buf;
|
info->bf = buf;
|
||||||
p = bf;
|
p = info->bf;
|
||||||
zs = 0;
|
info->zs = 0;
|
||||||
|
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case '\0':
|
case '\0':
|
||||||
@ -88,45 +92,45 @@ int _vprintf(const char *fmt, va_list va, void (*putc)(const char ch))
|
|||||||
num = va_arg(va, unsigned int);
|
num = va_arg(va, unsigned int);
|
||||||
if (ch == 'd' && (int)num < 0) {
|
if (ch == 'd' && (int)num < 0) {
|
||||||
num = -(int)num;
|
num = -(int)num;
|
||||||
out('-');
|
out(info, '-');
|
||||||
}
|
}
|
||||||
if (!num) {
|
if (!num) {
|
||||||
out_dgt(0);
|
out_dgt(info, 0);
|
||||||
} else {
|
} else {
|
||||||
for (div = 1000000000; div; div /= 10)
|
for (div = 1000000000; div; div /= 10)
|
||||||
div_out(&num, div);
|
div_out(info, &num, div);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
num = va_arg(va, unsigned int);
|
num = va_arg(va, unsigned int);
|
||||||
if (!num) {
|
if (!num) {
|
||||||
out_dgt(0);
|
out_dgt(info, 0);
|
||||||
} else {
|
} else {
|
||||||
for (div = 0x10000000; div; div /= 0x10)
|
for (div = 0x10000000; div; div /= 0x10)
|
||||||
div_out(&num, div);
|
div_out(info, &num, div);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
out((char)(va_arg(va, int)));
|
out(info, (char)(va_arg(va, int)));
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
p = va_arg(va, char*);
|
p = va_arg(va, char*);
|
||||||
break;
|
break;
|
||||||
case '%':
|
case '%':
|
||||||
out('%');
|
out(info, '%');
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*bf = 0;
|
*info->bf = 0;
|
||||||
bf = p;
|
info->bf = p;
|
||||||
while (*bf++ && width > 0)
|
while (*info->bf++ && width > 0)
|
||||||
width--;
|
width--;
|
||||||
while (width-- > 0)
|
while (width-- > 0)
|
||||||
putc(lz ? '0' : ' ');
|
info->putc(info, lz ? '0' : ' ');
|
||||||
if (p) {
|
if (p) {
|
||||||
while ((ch = *p++))
|
while ((ch = *p++))
|
||||||
putc(ch);
|
info->putc(info, ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,36 +141,44 @@ abort:
|
|||||||
|
|
||||||
int vprintf(const char *fmt, va_list va)
|
int vprintf(const char *fmt, va_list va)
|
||||||
{
|
{
|
||||||
return _vprintf(fmt, va, putc);
|
struct printf_info info;
|
||||||
|
|
||||||
|
info.putc = putc_normal;
|
||||||
|
return _vprintf(&info, fmt, va);
|
||||||
}
|
}
|
||||||
|
|
||||||
int printf(const char *fmt, ...)
|
int printf(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
struct printf_info info;
|
||||||
|
|
||||||
va_list va;
|
va_list va;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
info.putc = putc_normal;
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
ret = _vprintf(fmt, va, putc);
|
ret = _vprintf(&info, fmt, va);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void putc_outstr(char ch)
|
static void putc_outstr(struct printf_info *info, char ch)
|
||||||
{
|
{
|
||||||
*outstr++ = ch;
|
*info->outstr++ = ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sprintf(char *buf, const char *fmt, ...)
|
int sprintf(char *buf, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
struct printf_info info;
|
||||||
va_list va;
|
va_list va;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
outstr = buf;
|
info.outstr = buf;
|
||||||
ret = _vprintf(fmt, va, putc_outstr);
|
info.putc = putc_outstr;
|
||||||
|
ret = _vprintf(&info, fmt, va);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
*outstr = '\0';
|
*info.outstr = '\0';
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -174,14 +186,16 @@ int sprintf(char *buf, const char *fmt, ...)
|
|||||||
/* Note that size is ignored */
|
/* Note that size is ignored */
|
||||||
int snprintf(char *buf, size_t size, const char *fmt, ...)
|
int snprintf(char *buf, size_t size, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
struct printf_info info;
|
||||||
va_list va;
|
va_list va;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
outstr = buf;
|
info.outstr = buf;
|
||||||
ret = _vprintf(fmt, va, putc_outstr);
|
info.putc = putc_outstr;
|
||||||
|
ret = _vprintf(&info, fmt, va);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
*outstr = '\0';
|
*info.outstr = '\0';
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user