aboutsummaryrefslogtreecommitdiff
path: root/machine/unprivileged_memory.h
diff options
context:
space:
mode:
Diffstat (limited to 'machine/unprivileged_memory.h')
-rw-r--r--machine/unprivileged_memory.h79
1 files changed, 79 insertions, 0 deletions
diff --git a/machine/unprivileged_memory.h b/machine/unprivileged_memory.h
new file mode 100644
index 0000000..d03cc5e
--- /dev/null
+++ b/machine/unprivileged_memory.h
@@ -0,0 +1,79 @@
+#ifndef _RISCV_MISALIGNED_H
+#define _RISCV_MISALIGNED_H
+
+#include "encoding.h"
+#include <stdint.h>
+
+#define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type, insn) \
+ static inline type load_##type(const type* addr, uintptr_t mepc) \
+ { \
+ register uintptr_t __mepc asm ("a2") = mepc; \
+ register uintptr_t __mstatus asm ("a3"); \
+ type val; \
+ asm ("csrrs %0, mstatus, %3\n" \
+ #insn " %1, %2\n" \
+ "csrw mstatus, %0" \
+ : "+&r" (__mstatus), "=&r" (val) \
+ : "m" (*addr), "r" (MSTATUS_MPRV), "r" (__mepc)); \
+ return val; \
+ }
+
+#define DECLARE_UNPRIVILEGED_STORE_FUNCTION(type, insn) \
+ static inline void store_##type(type* addr, type val, uintptr_t mepc) \
+ { \
+ register uintptr_t __mepc asm ("a2") = mepc; \
+ register uintptr_t __mstatus asm ("a3"); \
+ asm volatile ("csrrs %0, mstatus, %3\n" \
+ #insn " %1, %2\n" \
+ "csrw mstatus, %0" \
+ : "+&r" (__mstatus) \
+ : "r" (val), "m" (*addr), "r" (MSTATUS_MPRV), \
+ "r" (__mepc)); \
+ }
+
+DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint8_t, lbu)
+DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint16_t, lhu)
+DECLARE_UNPRIVILEGED_LOAD_FUNCTION(int8_t, lb)
+DECLARE_UNPRIVILEGED_LOAD_FUNCTION(int16_t, lh)
+DECLARE_UNPRIVILEGED_LOAD_FUNCTION(int32_t, lw)
+DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint8_t, sb)
+DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint16_t, sh)
+DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint32_t, sw)
+#ifdef __riscv64
+DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint32_t, lwu)
+DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint64_t, ld)
+DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint64_t, sd)
+#else
+DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint32_t, lw)
+#endif
+
+static uint32_t __attribute__((always_inline)) get_insn(uintptr_t mepc, uintptr_t* mstatus)
+{
+ register uintptr_t __mepc asm ("a2") = mepc;
+ register uintptr_t __mstatus asm ("a3");
+ uint32_t val;
+#ifndef __riscv_compressed
+ asm ("csrrs %[mstatus], mstatus, %[mprv]\n"
+ "lw %[insn], (%[addr])\n"
+ "csrw mstatus, %[mstatus]"
+ : [mstatus] "+&r" (__mstatus), [insn] "=&r" (val)
+ : [mprv] "r" (MSTATUS_MPRV), [addr] "r" (__mepc));
+#else
+ uintptr_t rvc_mask = 3, tmp;
+ asm ("csrrs %[mstatus], mstatus, %[mprv]\n"
+ "lhu %[insn], (%[addr])\n"
+ "and %[tmp], %[insn], %[rvc_mask]\n"
+ "bne %[tmp], %[rvc_mask], 1f\n"
+ "lh %[tmp], 2(%[addr])\n"
+ "sll %[tmp], %[tmp], 16\n"
+ "add %[insn], %[insn], %[tmp]\n"
+ "1: csrw mstatus, %[mstatus]"
+ : [mstatus] "+&r" (__mstatus), [insn] "=&r" (val), [tmp] "=&r" (tmp)
+ : [mprv] "r" (MSTATUS_MPRV), [addr] "r" (__mepc),
+ [rvc_mask] "r" (rvc_mask));
+#endif
+ *mstatus = __mstatus;
+ return val;
+}
+
+#endif