1a533497752000608ca816df80090e8784a26bde
6 #include <machine/syscall.h>
9 #define static_assert(cond) switch(0) { case 0: case !!(long)(cond): ; }
11 void syscall(long which
, long arg0
, long arg1
, long arg2
)
13 volatile uint64_t magic_mem
[8] __attribute__((aligned(64)));
19 write_csr(tohost
, (long)magic_mem
);
20 while (swap_csr(fromhost
, 0) == 0);
25 write_csr(tohost
, (code
<< 1) | 1);
29 void printstr(const char* s
)
31 syscall(SYS_write
, 1, (long)s
, strlen(s
));
34 // In setStats, we might trap reading uarch-specific counters.
35 // The trap handler will skip over the instruction, but we want
36 // to pretend as though we read the value 0 in this case.
37 #define read_csr_safe(reg) ({ long __tmp = 0; \
38 asm volatile ("csrr %0, " #reg : "+r"(__tmp)); \
41 #define NUM_COUNTERS 18
42 static long counters
[NUM_COUNTERS
];
43 static char* counter_names
[NUM_COUNTERS
];
44 void setStats(int enable
)
47 #define READ_CTR(name) do { \
48 if (i >= NUM_COUNTERS) exit(-1); \
49 long csr = read_csr_safe(name); \
50 if (!enable) { csr -= counters[i]; counter_names[i] = #name; } \
51 counters[i++] = csr; \
53 READ_CTR(cycle
); READ_CTR(instret
);
54 READ_CTR(uarch0
); READ_CTR(uarch1
); READ_CTR(uarch2
); READ_CTR(uarch3
);
55 READ_CTR(uarch4
); READ_CTR(uarch5
); READ_CTR(uarch6
); READ_CTR(uarch7
);
56 READ_CTR(uarch8
); READ_CTR(uarch9
); READ_CTR(uarch10
); READ_CTR(uarch11
);
57 READ_CTR(uarch12
); READ_CTR(uarch13
); READ_CTR(uarch14
); READ_CTR(uarch15
);
61 void __attribute__((weak
)) thread_entry(int cid
, int nc
)
63 // multi-threaded programs override this function.
64 // for the case of single-threaded programs, only let core 0 proceed.
68 int __attribute__((weak
)) main(int argc
, char** argv
)
70 // single-threaded programs override this function.
71 printstr("Implement main(), foo!\n");
75 void _init(int cid
, int nc
)
77 thread_entry(cid
, nc
);
79 // only single-threaded programs should ever get here.
82 char buf
[NUM_COUNTERS
* 32] __attribute__((aligned(64)));
84 for (int i
= 0; i
< NUM_COUNTERS
; i
++)
86 pbuf
+= sprintf(pbuf
, "%s = %d\n", counter_names
[i
], counters
[i
]);
96 static char buf
[64] __attribute__((aligned(64)));
97 static int buflen
= 0;
101 if (ch
== '\n' || buflen
== sizeof(buf
))
103 syscall(SYS_write
, 1, (long)buf
, buflen
);
110 void printhex(uint64_t x
)
114 for (i
= 0; i
< 16; i
++)
116 str
[15-i
] = (x
& 0xF) + ((x
& 0xF) < 10 ? '0' : 'a'-10);
124 static inline void printnum(void (*putch
)(int, void**), void **putdat
,
125 unsigned long long num
, unsigned base
, int width
, int padc
)
127 unsigned digs
[sizeof(num
)*CHAR_BIT
];
132 digs
[pos
++] = num
% base
;
138 while (width
-- > pos
)
142 putch(digs
[pos
] + (digs
[pos
] >= 10 ? 'a' - 10 : '0'), putdat
);
145 static unsigned long long getuint(va_list *ap
, int lflag
)
148 return va_arg(*ap
, unsigned long long);
150 return va_arg(*ap
, unsigned long);
152 return va_arg(*ap
, unsigned int);
155 static long long getint(va_list *ap
, int lflag
)
158 return va_arg(*ap
, long long);
160 return va_arg(*ap
, long);
162 return va_arg(*ap
, int);
165 static void vprintfmt(void (*putch
)(int, void**), void **putdat
, const char *fmt
, va_list ap
)
167 register const char* p
;
168 const char* last_fmt
;
169 register int ch
, err
;
170 unsigned long long num
;
171 int base
, lflag
, width
, precision
, altflag
;
175 while ((ch
= *(unsigned char *) fmt
) != '%') {
183 // Process a %-escape sequence
191 switch (ch
= *(unsigned char *) fmt
++) {
193 // flag to pad on the right
198 // flag to pad with 0's instead of spaces
213 for (precision
= 0; ; ++fmt
) {
214 precision
= precision
* 10 + ch
- '0';
216 if (ch
< '0' || ch
> '9')
219 goto process_precision
;
222 precision
= va_arg(ap
, int);
223 goto process_precision
;
236 width
= precision
, precision
= -1;
239 // long flag (doubled for long long)
246 putch(va_arg(ap
, int), putdat
);
251 if ((p
= va_arg(ap
, char *)) == NULL
)
253 if (width
> 0 && padc
!= '-')
254 for (width
-= strnlen(p
, precision
); width
> 0; width
--)
256 for (; (ch
= *p
) != '\0' && (precision
< 0 || --precision
>= 0); width
--) {
260 for (; width
> 0; width
--)
266 num
= getint(&ap
, lflag
);
267 if ((long long) num
< 0) {
269 num
= -(long long) num
;
277 goto unsigned_number
;
281 // should do something with padding so it's always 3 octits
283 goto unsigned_number
;
287 static_assert(sizeof(long) == sizeof(void*));
291 /* fall through to 'x' */
293 // (unsigned) hexadecimal
297 num
= getuint(&ap
, lflag
);
299 printnum(putch
, putdat
, num
, base
, width
, padc
);
302 // escaped '%' character
307 // unrecognized escape sequence - just print it literally
316 int printf(const char* fmt
, ...)
321 vprintfmt((void*)putchar
, 0, fmt
, ap
);
324 return 0; // incorrect return value, but who cares, anyway?
327 int sprintf(char* str
, const char* fmt
, ...)
333 void sprintf_putch(int ch
, void** data
)
335 char** pstr
= (char**)data
;
340 vprintfmt(sprintf_putch
, (void**)&str
, fmt
, ap
);