1 // See LICENSE for license details.
8 #include <sys/signal.h>
15 extern volatile uint64_t tohost
;
16 extern volatile uint64_t fromhost
;
18 static uintptr_t syscall(uintptr_t which
, uint64_t arg0
, uint64_t arg1
, uint64_t arg2
)
20 volatile uint64_t magic_mem
[8] __attribute__((aligned(64)));
27 tohost
= (uintptr_t)magic_mem
;
36 #define NUM_COUNTERS 2
37 static uintptr_t counters
[NUM_COUNTERS
];
38 static char* counter_names
[NUM_COUNTERS
];
40 void setStats(int enable
)
43 #define READ_CTR(name) do { \
44 while (i >= NUM_COUNTERS) ; \
45 uintptr_t csr = read_csr(name); \
46 if (!enable) { csr -= counters[i]; counter_names[i] = #name; } \
47 counters[i++] = csr; \
56 void __attribute__((noreturn
)) tohost_exit(uintptr_t code
)
58 tohost
= (code
<< 1) | 1;
62 uintptr_t __attribute__((weak
)) handle_trap(uintptr_t cause
, uintptr_t epc
, uintptr_t regs
[32])
77 void printstr(const char* s
)
79 syscall(SYS_write
, 1, (uintptr_t)s
, strlen(s
));
82 void __attribute__((weak
)) thread_entry(int cid
, int nc
)
84 // multi-threaded programs override this function.
85 // for the case of single-threaded programs, only let core 0 proceed.
89 int __attribute__((weak
)) main(int argc
, char** argv
)
91 // single-threaded programs override this function.
92 printstr("Implement main(), foo!\n");
96 static void init_tls()
98 register void* thread_pointer
asm("tp");
99 extern char _tls_data
;
100 extern __thread
char _tdata_begin
, _tdata_end
, _tbss_end
;
101 size_t tdata_size
= &_tdata_end
- &_tdata_begin
;
102 memcpy(thread_pointer
, &_tls_data
, tdata_size
);
103 size_t tbss_size
= &_tbss_end
- &_tdata_end
;
104 memset(thread_pointer
+ tdata_size
, 0, tbss_size
);
107 void _init(int cid
, int nc
)
110 thread_entry(cid
, nc
);
112 // only single-threaded programs should ever get here.
113 int ret
= main(0, 0);
115 char buf
[NUM_COUNTERS
* 32] __attribute__((aligned(64)));
117 for (int i
= 0; i
< NUM_COUNTERS
; i
++)
119 pbuf
+= sprintf(pbuf
, "%s = %d\n", counter_names
[i
], counters
[i
]);
129 static __thread
char buf
[64] __attribute__((aligned(64)));
130 static __thread
int buflen
= 0;
134 if (ch
== '\n' || buflen
== sizeof(buf
))
136 syscall(SYS_write
, 1, (uintptr_t)buf
, buflen
);
143 void printhex(uint64_t x
)
147 for (i
= 0; i
< 16; i
++)
149 str
[15-i
] = (x
& 0xF) + ((x
& 0xF) < 10 ? '0' : 'a'-10);
157 static inline void printnum(void (*putch
)(int, void**), void **putdat
,
158 unsigned long long num
, unsigned base
, int width
, int padc
)
160 unsigned digs
[sizeof(num
)*CHAR_BIT
];
165 digs
[pos
++] = num
% base
;
171 while (width
-- > pos
)
175 putch(digs
[pos
] + (digs
[pos
] >= 10 ? 'a' - 10 : '0'), putdat
);
178 static unsigned long long getuint(va_list *ap
, int lflag
)
181 return va_arg(*ap
, unsigned long long);
183 return va_arg(*ap
, unsigned long);
185 return va_arg(*ap
, unsigned int);
188 static long long getint(va_list *ap
, int lflag
)
191 return va_arg(*ap
, long long);
193 return va_arg(*ap
, long);
195 return va_arg(*ap
, int);
198 static void vprintfmt(void (*putch
)(int, void**), void **putdat
, const char *fmt
, va_list ap
)
200 register const char* p
;
201 const char* last_fmt
;
202 register int ch
, err
;
203 unsigned long long num
;
204 int base
, lflag
, width
, precision
, altflag
;
208 while ((ch
= *(unsigned char *) fmt
) != '%') {
216 // Process a %-escape sequence
224 switch (ch
= *(unsigned char *) fmt
++) {
226 // flag to pad on the right
231 // flag to pad with 0's instead of spaces
246 for (precision
= 0; ; ++fmt
) {
247 precision
= precision
* 10 + ch
- '0';
249 if (ch
< '0' || ch
> '9')
252 goto process_precision
;
255 precision
= va_arg(ap
, int);
256 goto process_precision
;
269 width
= precision
, precision
= -1;
272 // long flag (doubled for long long)
279 putch(va_arg(ap
, int), putdat
);
284 if ((p
= va_arg(ap
, char *)) == NULL
)
286 if (width
> 0 && padc
!= '-')
287 for (width
-= strnlen(p
, precision
); width
> 0; width
--)
289 for (; (ch
= *p
) != '\0' && (precision
< 0 || --precision
>= 0); width
--) {
293 for (; width
> 0; width
--)
299 num
= getint(&ap
, lflag
);
300 if ((long long) num
< 0) {
302 num
= -(long long) num
;
310 goto unsigned_number
;
314 // should do something with padding so it's always 3 octits
316 goto unsigned_number
;
320 static_assert(sizeof(long) == sizeof(void*));
324 /* fall through to 'x' */
326 // (unsigned) hexadecimal
330 num
= getuint(&ap
, lflag
);
332 printnum(putch
, putdat
, num
, base
, width
, padc
);
335 // escaped '%' character
340 // unrecognized escape sequence - just print it literally
349 int printf(const char* fmt
, ...)
354 vprintfmt((void*)putchar
, 0, fmt
, ap
);
357 return 0; // incorrect return value, but who cares, anyway?
360 int sprintf(char* str
, const char* fmt
, ...)
366 void sprintf_putch(int ch
, void** data
)
368 char** pstr
= (char**)data
;
373 vprintfmt(sprintf_putch
, (void**)&str
, fmt
, ap
);
380 void* memcpy(void* dest
, const void* src
, size_t len
)
382 if ((((uintptr_t)dest
| (uintptr_t)src
| len
) & (sizeof(uintptr_t)-1)) == 0) {
383 const uintptr_t* s
= src
;
385 while (d
< (uintptr_t*)(dest
+ len
))
390 while (d
< (char*)(dest
+ len
))
396 void* memset(void* dest
, int byte
, size_t len
)
398 if ((((uintptr_t)dest
| len
) & (sizeof(uintptr_t)-1)) == 0) {
399 uintptr_t word
= byte
& 0xFF;
402 word
|= word
<< 16 << 16;
405 while (d
< (uintptr_t*)(dest
+ len
))
409 while (d
< (char*)(dest
+ len
))
415 size_t strlen(const char *s
)
423 size_t strnlen(const char *s
, size_t n
)
431 int strcmp(const char* s1
, const char* s2
)
433 unsigned char c1
, c2
;
438 } while (c1
!= 0 && c1
== c2
);
443 char* strcpy(char* dest
, const char* src
)
446 while ((*d
++ = *src
++))
451 long atol(const char* str
)
459 if (*str
== '-' || *str
== '+') {
469 return sign
? -res
: res
;