]> git.gag.com Git - fw/sdcc/blob - device/lib/z80/printf.c
* Got dhrystone working - 83/s on a 4MHz Z80!
[fw/sdcc] / device / lib / z80 / printf.c
1 /** Simple printf implementation
2     Again a stub - will use the std one later...
3 */
4
5 #define NULL 0
6
7 /* A hack because I dont understand how va_arg works...
8    sdcc pushes right to left with the real sizes, not cast up
9    to an int.
10    so printf(int, char, long)
11    results in push long, push char, push int
12    On the z80 the stack grows down, so the things seem to be in
13    the correct order.
14  */
15
16 typedef char * va_list;
17 #define va_start(list, last)    list = (char *)&last + sizeof(last)
18 #define va_arg(list, type)      *(type *)list; list += sizeof(type);
19
20 typedef void EMIT(char c, void *pData);
21
22
23 static void _printn(unsigned u, unsigned base, char issigned, EMIT *emitter, void *pData)
24 {
25     const char *_hex = "0123456789ABCDEF";
26     if (issigned && ((int)u < 0)) {
27         (*emitter)('-', pData);
28         u = (unsigned)-((int)u);
29     }
30     if (u >= base)
31         _printn(u/base, base, 0, emitter, pData);
32     (*emitter)(_hex[u%base], pData);
33 }
34
35 static void _printf(const char *format, EMIT *emitter, void *pData, va_list va)
36 {
37     while (*format) {
38         if (*format == '%') {
39             switch (*++format) {
40             case 'c': {
41                 char c = va_arg(va, char);
42                 (*emitter)(c, pData);
43                 break;
44             }
45             case 'u':
46                 {
47                     unsigned u = va_arg(va, unsigned);
48                     _printn(u, 10, 0, emitter, pData);
49                     break;
50                 }
51             case 'd':
52                 {
53                     unsigned u = va_arg(va, unsigned);
54                     _printn(u, 10, 1, emitter, pData);
55                     break;
56                 }
57             case 'x':
58                 {
59                     unsigned u = va_arg(va, unsigned);
60                     _printn(u, 16, 0, emitter, pData);
61                     break;
62                 }
63             case 's': 
64                 {
65                     char *s = va_arg(va, char *);
66                     while (*s) {
67                         (*emitter)(*s, pData);
68                         s++;
69                     }
70                 }
71             }
72         }
73         else {
74             (*emitter)(*format, pData);
75         }
76         format++;
77     }
78 }
79
80 void putchar(char c);
81
82 static void _char_emitter(char c, void *pData)
83 {
84     putchar(c);
85 }
86
87 void printf(const char *format, ...)
88 {
89     va_list va;
90     va_start(va, format);
91
92     _printf(format, _char_emitter, NULL, va);
93 }