#include #include #include #include #include #include "semihosting.h" #define SEMIHOSTING_SYS_OPEN 0x01 #define SEMIHOSTING_SYS_CLOSE 0x02 #define SEMIHOSTING_SYS_WRITEC 0x03 #define SEMIHOSTING_SYS_WRITE0 0x04 #define SEMIHOSTING_SYS_WRITE 0x05 #define SEMIHOSTING_SYS_READ 0x06 #define SEMIHOSTING_SYS_READC 0x07 #define SEMIHOSTING_SYS_ISERROR 0x08 #define SEMIHOSTING_SYS_ISTTY 0x09 #define SEMIHOSTING_SYS_SEEK 0x0A #define SEMIHOSTING_SYS_FLEN 0x0C #define SEMIHOSTING_SYS_TMPNAM 0x0D #define SEMIHOSTING_SYS_REMOVE 0x0E #define SEMIHOSTING_SYS_RENAME 0x0F #define SEMIHOSTING_SYS_CLOCK 0x10 #define SEMIHOSTING_SYS_TIME 0x11 #define SEMIHOSTING_SYS_SYSTEM 0x12 #define SEMIHOSTING_SYS_ERRNO 0x13 #define SEMIHOSTING_SYS_GET_CMDLINE 0x15 #define SEMIHOSTING_SYS_HEAPINFO 0x16 #define SEMIHOSTING_EnterSVC 0x17 #define SEMIHOSTING_SYS_EXIT 0x18 #define SEMIHOSTING_SYS_EXIT_EXTENDED 0x20 #define SEMIHOSTING_SYS_ELAPSED 0x30 #define SEMIHOSTING_SYS_TICKFREQ 0x31 #define RISCV_SEMIHOSTING_CALL_NUMBER 7 typedef struct { char* str; int mode; size_t length; } OpenVector; typedef struct { char* old; int old_len; char* new; int new_len; } RenameVector; typedef struct { char* path; size_t len; } RemoveVector; typedef struct{ int fd; off_t pos; } SeekVector; static inline int __attribute__ ((always_inline)) call_host(int reason, void* arg) { #if 1 // This must always be set back to 0 to cover the case where a host wasn't // initially present, but only connected while the program was already up and // running. In that case, trap() suddenly won't be called anymore, so we have to // clear this variable *before* EBREAK is called. sh_missing_host = 0; register int value asm ("a0") = reason; register void* ptr asm ("a1") = arg; asm volatile ( // Workaround for RISC-V lack of multiple EBREAKs. " .option push \n" " .option norvc \n" // Force 16-byte alignment to make sure that the 3 instruction fall // within the same virtual page. If you the instruction straddle a page boundary // the debugger fetching the instructions could lead to a page fault. // Note: align 4 means, align by 2 to the power of 4! " .align 4 \n" " slli x0, x0, 0x1f \n" " ebreak \n" " srai x0, x0, 0x07 \n" " .option pop \n" : "=r" (value) /* Outputs */ : "0" (value), "r" (ptr), [swi] "i" (RISCV_SEMIHOSTING_CALL_NUMBER) /* Inputs */ : "memory" /* Clobbers */ ); return value; #else return 0; #endif } int sh_errno(void) { return call_host(SEMIHOSTING_SYS_ERRNO, (void*)NULL); } int sh_time(void) { return call_host(SEMIHOSTING_SYS_TIME, (void*)NULL); } int sh_remove(char* path) { size_t len = strlen(path); RemoveVector vec = {path, len}; return call_host(SEMIHOSTING_SYS_REMOVE, &vec); } void sh_seek(int file_handle, off_t pos) { SeekVector vec = {file_handle, pos}; call_host(SEMIHOSTING_SYS_SEEK, &vec); return; } void sh_write(char* str, int file_handle) { size_t length = strlen(str); OpenVector vec = {str, file_handle, length}; call_host(SEMIHOSTING_SYS_WRITE, &vec); return; } int sh_close(int file_handle) { return call_host(SEMIHOSTING_SYS_CLOSE, file_handle); } void sh_exit(void) { call_host(SEMIHOSTING_SYS_EXIT, (void*)NULL); return; } void sh_exit_extended(void) { call_host(SEMIHOSTING_SYS_EXIT_EXTENDED, (void*)NULL); return; } int sh_flen(int file_handle) { return call_host(SEMIHOSTING_SYS_FLEN, file_handle); } int sh_iserror(int num) { return call_host(SEMIHOSTING_SYS_ISERROR, num); } int sh_istty(int file_handle) { return call_host(SEMIHOSTING_SYS_ISTTY, file_handle); } /* int sh_remove(char* path) { size_t len = strlen(path); RemoveVector vec = {path, len}; return call_host(SEMIHOSTING_SYS_REMOVE, &vec); }*/ void sh_rename(char* old, char* new) { int old_len = strlen(old); int new_len = strlen(new); RenameVector vec = {old, old_len, new, new_len}; call_host(SEMIHOSTING_SYS_RENAME, &vec); return; } void sh_write0(const char* buf) { // Print zero-terminated string call_host(SEMIHOSTING_SYS_WRITE0, (void*) buf); } void sh_writec(char c) { // Print single character call_host(SEMIHOSTING_SYS_WRITEC, (void*)&c); } char sh_readc(void) { // Read character from keyboard. (Blocking operation!) char c = call_host(SEMIHOSTING_SYS_READC, (void*)NULL); return c; } int sh_open(char* str, int mode) { //mode = 0; //int length = 44; size_t length = strlen(str); OpenVector vec = {str, mode, length}; return call_host(SEMIHOSTING_SYS_OPEN, &vec); } void sh_read(char* buf, int file_handle, size_t length) { OpenVector vec = {buf, file_handle, length}; int i = call_host(SEMIHOSTING_SYS_READ, &vec); return i; } int sh_clock(void) { int clock = call_host(SEMIHOSTING_SYS_CLOCK, (void*)NULL); return clock; } /* void sh_write(char* str, int file_handle) { return; }*/