0c1bc7f6fc9e403ae0c40b0aea41992e16f2e9de
[riscv-tests.git] / benchmarks / common / syscalls.c
1 #include <stdint.h>
2 #include <string.h>
3 #include <stdarg.h>
4 #include <machine/syscall.h>
5 #include "pcr.h"
6
7 void exit(int code)
8 {
9 volatile uint64_t magic_mem[8] = {0};
10 magic_mem[0] = SYS_exit;
11 magic_mem[1] = code;
12 __sync_synchronize();
13 mtpcr(PCR_TOHOST, (long)magic_mem);
14 while(1);
15 }
16
17 void printstr(const char* s)
18 {
19 volatile uint64_t magic_mem[8] = {0};
20 magic_mem[0] = SYS_write;
21 magic_mem[1] = 1;
22 magic_mem[2] = (unsigned long)s;
23 magic_mem[3] = strlen(s);
24 __sync_synchronize();
25 mtpcr(PCR_TOHOST, (long)magic_mem);
26 while(mtpcr(PCR_FROMHOST, 0) == 0);
27 }
28
29 int putchar(int ch)
30 {
31 static char buf[64];
32 static int buflen = 0;
33
34 if(ch != -1)
35 buf[buflen++] = ch;
36
37 if(ch == -1 || buflen == sizeof(buf))
38 {
39 volatile uint64_t magic_mem[8] = {0};
40 magic_mem[0] = SYS_write;
41 magic_mem[1] = 1;
42 magic_mem[2] = (long)buf;
43 magic_mem[3] = buflen;
44 __sync_synchronize();
45 mtpcr(PCR_TOHOST, (long)magic_mem);
46 while(mtpcr(PCR_FROMHOST, 0) == 0);
47
48 buflen = 0;
49 }
50
51 return 0;
52 }
53
54 void printhex(uint64_t x)
55 {
56 char str[17];
57 int i;
58 for (i = 0; i < 16; i++)
59 {
60 str[15-i] = (x & 0xF) + ((x & 0xF) < 10 ? '0' : 'a'-10);
61 x >>= 4;
62 }
63 str[16] = 0;
64
65 printstr(str);
66 }
67
68 static void printnum(void (*putch)(int, void**), void **putdat,
69 unsigned long long num, unsigned base, int width, int padc)
70 {
71 if (num >= base)
72 printnum(putch, putdat, num / base, base, width - 1, padc);
73 else while (--width > 0)
74 putch(padc, putdat);
75
76 putch("0123456789abcdef"[num % base], putdat);
77 }
78
79 static unsigned long long getuint(va_list *ap, int lflag)
80 {
81 if (lflag >= 2)
82 return va_arg(*ap, unsigned long long);
83 else if (lflag)
84 return va_arg(*ap, unsigned long);
85 else
86 return va_arg(*ap, unsigned int);
87 }
88
89 static long long getint(va_list *ap, int lflag)
90 {
91 if (lflag >= 2)
92 return va_arg(*ap, long long);
93 else if (lflag)
94 return va_arg(*ap, long);
95 else
96 return va_arg(*ap, int);
97 }
98
99 void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_list ap)
100 {
101 register const char* p;
102 const char* last_fmt;
103 register int ch, err;
104 unsigned long long num;
105 int base, lflag, width, precision, altflag;
106 char padc;
107
108 while (1) {
109 while ((ch = *(unsigned char *) fmt) != '%') {
110 if (ch == '\0')
111 return;
112 fmt++;
113 putch(ch, putdat);
114 }
115 fmt++;
116
117 // Process a %-escape sequence
118 last_fmt = fmt;
119 padc = ' ';
120 width = -1;
121 precision = -1;
122 lflag = 0;
123 altflag = 0;
124 reswitch:
125 switch (ch = *(unsigned char *) fmt++) {
126
127 // flag to pad on the right
128 case '-':
129 padc = '-';
130 goto reswitch;
131
132 // flag to pad with 0's instead of spaces
133 case '0':
134 padc = '0';
135 goto reswitch;
136
137 // width field
138 case '1':
139 case '2':
140 case '3':
141 case '4':
142 case '5':
143 case '6':
144 case '7':
145 case '8':
146 case '9':
147 for (precision = 0; ; ++fmt) {
148 precision = precision * 10 + ch - '0';
149 ch = *fmt;
150 if (ch < '0' || ch > '9')
151 break;
152 }
153 goto process_precision;
154
155 case '*':
156 precision = va_arg(ap, int);
157 goto process_precision;
158
159 case '.':
160 if (width < 0)
161 width = 0;
162 goto reswitch;
163
164 case '#':
165 altflag = 1;
166 goto reswitch;
167
168 process_precision:
169 if (width < 0)
170 width = precision, precision = -1;
171 goto reswitch;
172
173 // long flag (doubled for long long)
174 case 'l':
175 lflag++;
176 goto reswitch;
177
178 // character
179 case 'c':
180 putch(va_arg(ap, int), putdat);
181 break;
182
183 // string
184 case 's':
185 if ((p = va_arg(ap, char *)) == NULL)
186 p = "(null)";
187 if (width > 0 && padc != '-')
188 for (width -= strnlen(p, precision); width > 0; width--)
189 putch(padc, putdat);
190 for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) {
191 if (altflag && (ch < ' ' || ch > '~'))
192 putch('?', putdat);
193 else
194 putch(ch, putdat);
195 p++;
196 }
197 for (; width > 0; width--)
198 putch(' ', putdat);
199 break;
200
201 // (signed) decimal
202 case 'd':
203 num = getint(&ap, lflag);
204 if ((long long) num < 0) {
205 putch('-', putdat);
206 num = -(long long) num;
207 }
208 base = 10;
209 goto number;
210
211 // unsigned decimal
212 case 'u':
213 num = getuint(&ap, lflag);
214 base = 10;
215 goto number;
216
217 // (unsigned) octal
218 case 'o':
219 // should do something with padding so it's always 3 octits
220 num = getuint(&ap, lflag);
221 base = 8;
222 goto number;
223
224 // pointer
225 case 'p':
226 putch('0', putdat);
227 putch('x', putdat);
228 num = (unsigned long long)
229 (uintptr_t) va_arg(ap, void *);
230 base = 16;
231 goto number;
232
233 // (unsigned) hexadecimal
234 case 'x':
235 num = getuint(&ap, lflag);
236 base = 16;
237 number:
238 printnum(putch, putdat, num, base, width, padc);
239 break;
240
241 // escaped '%' character
242 case '%':
243 putch(ch, putdat);
244 break;
245
246 // unrecognized escape sequence - just print it literally
247 default:
248 putch('%', putdat);
249 fmt = last_fmt;
250 break;
251 }
252 }
253 }
254
255 int printf(const char* fmt, ...)
256 {
257 va_list ap;
258 va_start(ap, fmt);
259
260 vprintfmt((void*)putchar, 0, fmt, ap);
261 putchar(-1);
262
263 va_end(ap);
264 return 0; // incorrect return value, but who cares, anyway?
265 }