summaryrefslogtreecommitdiff
path: root/riscv/riscv-probe/libfemto/drivers/semihost.c
diff options
context:
space:
mode:
authorCarlos Maiolino <[email protected]>2025-07-10 22:18:39 +0200
committerCarlos Maiolino <[email protected]>2025-07-10 22:18:39 +0200
commit8c6fc0c15415b32080a848bbde640e104098cf13 (patch)
tree04a21bd28f9dc82c8e216390d6208ed93b9bcd11 /riscv/riscv-probe/libfemto/drivers/semihost.c
Initial drop
Add some riscv code Signed-off-by: Carlos Maiolino <[email protected]>
Diffstat (limited to 'riscv/riscv-probe/libfemto/drivers/semihost.c')
-rw-r--r--riscv/riscv-probe/libfemto/drivers/semihost.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/riscv/riscv-probe/libfemto/drivers/semihost.c b/riscv/riscv-probe/libfemto/drivers/semihost.c
new file mode 100644
index 0000000..9f47834
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/drivers/semihost.c
@@ -0,0 +1,60 @@
+// See LICENSE for license details.
+
+#ifdef __riscv
+
+#include "femto.h"
+
+enum {
+ SBI_CONSOLE_PUTCHAR = 1,
+ SBI_CONSOLE_GETCHAR = 2,
+ SBI_SHUTDOWN = 8
+};
+
+#define __syscall(...) \
+ asm volatile ("ecall\n\t" : "+r"(a0) : __VA_ARGS__ : "memory")
+
+static inline long semihost_call0(long n)
+{
+ register long a7 __asm__("a7") = n;
+ register long a0 __asm__("a0");
+ __syscall("r"(a7));
+ return a0;
+}
+
+static inline long semihost_call1(long n, long a)
+{
+ register long a7 __asm__("a7") = n;
+ register long a0 __asm__("a0") = a;
+ __syscall("r"(a7), "0"(a0));
+ return a0;
+}
+
+static int semihost_getchar()
+{
+ semihost_call0(SBI_CONSOLE_GETCHAR);
+}
+
+static int semihost_putchar(int ch)
+{
+ semihost_call1(SBI_CONSOLE_PUTCHAR, ch);
+}
+
+static void semihost_poweroff(int status)
+{
+ semihost_call0(SBI_SHUTDOWN);
+ __builtin_unreachable();
+}
+
+console_device_t console_semihost = {
+ NULL,
+ semihost_getchar,
+ semihost_putchar
+};
+
+
+poweroff_device_t poweroff_semihost = {
+ NULL,
+ semihost_poweroff
+};
+
+#endif \ No newline at end of file