aboutsummaryrefslogtreecommitdiff
path: root/benchmarks/common/syscalls.c
diff options
context:
space:
mode:
Diffstat (limited to 'benchmarks/common/syscalls.c')
-rw-r--r--benchmarks/common/syscalls.c265
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?
+}