diff options
Diffstat (limited to 'benchmarks/common/syscalls.c')
-rw-r--r-- | benchmarks/common/syscalls.c | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/benchmarks/common/syscalls.c b/benchmarks/common/syscalls.c new file mode 100644 index 0000000..f95dde4 --- /dev/null +++ b/benchmarks/common/syscalls.c @@ -0,0 +1,265 @@ +#include <stdint.h> +#include <string.h> +#include <stdarg.h> +#include "pcr.h" + +void exit(int code) +{ + volatile uint64_t magic_mem[8] = {0}; + magic_mem[0] = 1; + magic_mem[1] = code; + __sync_synchronize(); + mtpcr(PCR_TOHOST, (long)magic_mem); + while(1); +} + +void printstr(const char* s) +{ + volatile uint64_t magic_mem[8] = {0}; + magic_mem[0] = 4; + magic_mem[1] = 1; + magic_mem[2] = (unsigned long)s; + magic_mem[3] = strlen(s); + __sync_synchronize(); + mtpcr(PCR_TOHOST, (long)magic_mem); + while(mtpcr(PCR_FROMHOST, 0) == 0); +} + +int putchar(int ch) +{ + #define buffered_putch_bufsize 64 + static char buf[buffered_putch_bufsize]; + static int buflen = 0; + + if(ch != -1) + buf[buflen++] = ch; + + if(ch == -1 || buflen == buffered_putch_bufsize) + { + volatile uint64_t magic_mem[8] = {0}; + magic_mem[0] = 4; + magic_mem[1] = 1; + magic_mem[2] = (long)buf; + magic_mem[3] = buflen; + __sync_synchronize(); + mtpcr(PCR_TOHOST, (long)magic_mem); + while(mtpcr(PCR_FROMHOST, 0) == 0); + + buflen = 0; + } + + return 0; +} + +void printhex(uint64_t x) +{ + char str[17]; + int i; + for (i = 0; i < 16; i++) + { + str[15-i] = (x & 0xF) + ((x & 0xF) < 10 ? '0' : 'a'-10); + x >>= 4; + } + str[16] = 0; + + printstr(str); +} + +static void printnum(void (*putch)(int, void**), void **putdat, + unsigned long long num, unsigned base, int width, int padc) +{ + if (num >= base) + printnum(putch, putdat, num / base, base, width - 1, padc); + else while (--width > 0) + putch(padc, putdat); + + putch("0123456789abcdef"[num % base], putdat); +} + +static unsigned long long getuint(va_list *ap, int lflag) +{ + if (lflag >= 2) + return va_arg(*ap, unsigned long long); + else if (lflag) + return va_arg(*ap, unsigned long); + else + return va_arg(*ap, unsigned int); +} + +static long long getint(va_list *ap, int lflag) +{ + if (lflag >= 2) + return va_arg(*ap, long long); + else if (lflag) + return va_arg(*ap, long); + else + return va_arg(*ap, int); +} + +void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_list ap) +{ + register const char* p; + const char* last_fmt; + register int ch, err; + unsigned long long num; + int base, lflag, width, precision, altflag; + char padc; + + while (1) { + while ((ch = *(unsigned char *) fmt) != '%') { + if (ch == '\0') + return; + fmt++; + putch(ch, putdat); + } + fmt++; + + // Process a %-escape sequence + last_fmt = fmt; + padc = ' '; + width = -1; + precision = -1; + lflag = 0; + altflag = 0; + reswitch: + switch (ch = *(unsigned char *) fmt++) { + + // flag to pad on the right + case '-': + padc = '-'; + goto reswitch; + + // flag to pad with 0's instead of spaces + case '0': + padc = '0'; + goto reswitch; + + // width field + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + for (precision = 0; ; ++fmt) { + precision = precision * 10 + ch - '0'; + ch = *fmt; + if (ch < '0' || ch > '9') + break; + } + goto process_precision; + + case '*': + precision = va_arg(ap, int); + goto process_precision; + + case '.': + if (width < 0) + width = 0; + goto reswitch; + + case '#': + altflag = 1; + goto reswitch; + + process_precision: + if (width < 0) + width = precision, precision = -1; + goto reswitch; + + // long flag (doubled for long long) + case 'l': + lflag++; + goto reswitch; + + // character + case 'c': + putch(va_arg(ap, int), putdat); + break; + + // string + case 's': + if ((p = va_arg(ap, char *)) == NULL) + p = "(null)"; + if (width > 0 && padc != '-') + for (width -= strnlen(p, precision); width > 0; width--) + putch(padc, putdat); + for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) { + if (altflag && (ch < ' ' || ch > '~')) + putch('?', putdat); + else + putch(ch, putdat); + p++; + } + for (; width > 0; width--) + putch(' ', putdat); + break; + + // (signed) decimal + case 'd': + num = getint(&ap, lflag); + if ((long long) num < 0) { + putch('-', putdat); + num = -(long long) num; + } + base = 10; + goto number; + + // unsigned decimal + case 'u': + num = getuint(&ap, lflag); + base = 10; + goto number; + + // (unsigned) octal + case 'o': + // should do something with padding so it's always 3 octits + num = getuint(&ap, lflag); + base = 8; + goto number; + + // pointer + case 'p': + putch('0', putdat); + putch('x', putdat); + num = (unsigned long long) + (uintptr_t) va_arg(ap, void *); + base = 16; + goto number; + + // (unsigned) hexadecimal + case 'x': + num = getuint(&ap, lflag); + base = 16; + number: + printnum(putch, putdat, num, base, width, padc); + break; + + // escaped '%' character + case '%': + putch(ch, putdat); + break; + + // unrecognized escape sequence - just print it literally + default: + putch('%', putdat); + fmt = last_fmt; + break; + } + } +} + +int printf(const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + vprintfmt((void*)putchar, 0, fmt, ap); + putchar(-1); + + va_end(ap); + return 0; // incorrect return value, but who cares, anyway? +} |