summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2011-05-06 15:50:07 -0700
committerRichard Henderson <rth@twiddle.net>2011-05-06 15:50:07 -0700
commit45a30cd864c313b353f47c8186b2b932069af4a1 (patch)
tree8eb31dfd2bf4c7fbc4f613dcf604eb636c167ff8
parent87fb8be28570645cd42f940ebdaed4ee1d7724cf (diff)
downloadqemu-palcode-45a30cd864c313b353f47c8186b2b932069af4a1.tar.gz
Handle padding in printf numerical output.
-rw-r--r--printf.c85
-rw-r--r--protos.h1
-rw-r--r--strlen.S59
3 files changed, 119 insertions, 26 deletions
diff --git a/printf.c b/printf.c
index f5c7545..469b82c 100644
--- a/printf.c
+++ b/printf.c
@@ -20,14 +20,38 @@
#include <stdarg.h>
#include <stdbool.h>
-#include "uart.h"
+#include <string.h>
+#include "console.h"
-static int print_decimal(unsigned long val)
+static int print_buf_pad(char *buf, int buflen, char *p, int width, int pad)
+{
+ int len = buf + buflen - p;
+ int r = 0;
+
+ if (width > len)
+ {
+ *--p = pad;
+ len++;
+
+ while (width > buflen)
+ {
+ crb_puts(0, p, 1);
+ width--;
+ r++;
+ }
+ while (width > len)
+ *--p = pad, len++;
+ }
+
+ crb_puts(0, p, len);
+ return r + len;
+}
+
+static int print_decimal(unsigned long val, int width, int pad)
{
char buf[32];
- char *p = buf+31;
+ char *p = buf + sizeof(buf);
- *p = 0;
if (val == 0)
*--p = '0';
else
@@ -48,16 +72,14 @@ static int print_decimal(unsigned long val)
while (val);
}
- uart_puts(COM1, p+1);
- return sizeof(buf) - (p - buf);
+ return print_buf_pad(buf, sizeof(buf), p, width, pad);
}
-static int print_hex(unsigned long val)
+static int print_hex(unsigned long val, int width, char pad)
{
char buf[32];
- char *p = buf+31;
+ char *p = buf + sizeof(buf);
- *p = 0;
if (val == 0)
*--p = '0';
else
@@ -71,8 +93,7 @@ static int print_hex(unsigned long val)
while (val);
}
- uart_puts(COM1, p+1);
- return sizeof(buf) - (p - buf);
+ return print_buf_pad(buf, sizeof(buf), p, width, pad);
}
int printf(const char *fmt, ...)
@@ -86,18 +107,21 @@ int printf(const char *fmt, ...)
for (; *fmt ; fmt++)
if (*fmt != '%')
{
- uart_putchar(COM1, *fmt);
+ crb_puts(0, fmt, 1);
r++;
}
else
{
+ const char *percent = fmt;
bool is_long = false;
+ char pad = ' ';
+ int width = 0;
restart:
switch (*++fmt)
{
case '%':
- uart_putchar(COM1, '%');
+ crb_puts(0, "%", 1);
r++;
break;
@@ -111,7 +135,7 @@ int printf(const char *fmt, ...)
long d = va_arg (args, long);
if (d < 0)
{
- uart_putchar(COM1, '-');
+ crb_puts(0, "-", 1);
d = -d;
}
val = d;
@@ -121,7 +145,7 @@ int printf(const char *fmt, ...)
int d = va_arg (args, int);
if (d < 0)
{
- uart_putchar(COM1, '-');
+ crb_puts(0, "-", 1);
d = -d;
r++;
}
@@ -136,7 +160,7 @@ int printf(const char *fmt, ...)
val = va_arg (args, unsigned int);
do_unsigned:
- r += print_decimal (val);
+ r += print_decimal (val, width, pad);
break;
case 'x':
@@ -144,23 +168,32 @@ int printf(const char *fmt, ...)
val = va_arg (args, unsigned long);
else
val = va_arg (args, unsigned int);
- r += print_hex (val);
+ r += print_hex (val, width, pad);
+ break;
case 's':
{
const char *s = va_arg (args, const char *);
- while (*s)
- {
- uart_putchar(COM1, *s++);
- r++;
- }
- break;
+ int len = strlen(s);
+ crb_puts(0, s, len);
+ r += len;
}
+ break;
+
+ case '0':
+ pad = '0';
+ case '1' ... '9':
+ width = *fmt - '0';
+ while (fmt[1] >= '0' && fmt[1] <= '9')
+ width = width * 10 + *++fmt - '0';
+ goto restart;
default:
- uart_putchar(COM1, '%');
- uart_putchar(COM1, *fmt);
- r += 2;
+ {
+ int len = fmt - percent;
+ crb_puts(0, percent, len);
+ r += len;
+ }
break;
}
}
diff --git a/protos.h b/protos.h
index b765083..bebd50a 100644
--- a/protos.h
+++ b/protos.h
@@ -176,6 +176,7 @@ extern void entInt(void);
* Utils
*/
+extern int printf(const char *, ...);
extern void ndelay(unsigned long nsec);
static inline void udelay(unsigned long msec)
diff --git a/strlen.S b/strlen.S
new file mode 100644
index 0000000..5a77d72
--- /dev/null
+++ b/strlen.S
@@ -0,0 +1,59 @@
+/*
+ * strlen.S (c) 1995 David Mosberger (davidm@cs.arizona.edu)
+ *
+ * Finds length of a 0-terminated string. Optimized for the
+ * Alpha architecture:
+ *
+ * - memory accessed as aligned quadwords only
+ * - uses bcmpge to compare 8 bytes in parallel
+ * - does binary search to find 0 byte in last
+ * quadword (HAKMEM needed 12 instructions to
+ * do this instead of the 9 instructions that
+ * binary search needs).
+ */
+
+ .set noreorder
+ .set noat
+
+ .align 3
+
+ .globl strlen
+ .ent strlen
+strlen:
+ .frame $sp, 0, $26, 0
+ .prologue 0
+
+ ldq_u $1, 0($16) # load first quadword ($16 may be misaligned)
+ lda $2, -1($31)
+ insqh $2, $16, $2
+ andnot $16, 7, $0
+ or $2, $1, $1
+ cmpbge $31, $1, $2 # $2 <- bitmask: bit i == 1 <==> i-th byte == 0
+ bne $2, found
+
+loop: ldq $1, 8($0)
+ addq $0, 8, $0 # addr += 8
+ nop # helps dual issue last two insns
+ cmpbge $31, $1, $2
+ beq $2, loop
+
+found: blbs $2, done # make aligned case fast
+ negq $2, $3
+ and $2, $3, $2
+
+ and $2, 0x0f, $1
+ addq $0, 4, $3
+ cmoveq $1, $3, $0
+
+ and $2, 0x33, $1
+ addq $0, 2, $3
+ cmoveq $1, $3, $0
+
+ and $2, 0x55, $1
+ addq $0, 1, $3
+ cmoveq $1, $3, $0
+
+done: subq $0, $16, $0
+ ret $31, ($26)
+
+ .end strlen