1// See LICENSE for license details. 2 3#ifndef _RISCV_MISALIGNED_H 4#define _RISCV_MISALIGNED_H 5 6#include "encoding.h" 7#include "bits.h" 8#include <stdint.h> 9 10#define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type, insn) \ 11 static inline type load_##type(const type* addr, uintptr_t mepc) \ 12 { \ 13 register uintptr_t __mepc asm ("a2") = mepc; \ 14 register uintptr_t __mstatus asm ("a3"); \ 15 type val; \ 16 asm ("csrrs %0, mstatus, %3\n" \ 17 #insn " %1, %2\n" \ 18 "csrw mstatus, %0" \ 19 : "+&r" (__mstatus), "=&r" (val) \ 20 : "m" (*addr), "r" (MSTATUS_MPRV), "r" (__mepc)); \ 21 return val; \ 22 } 23 24#define DECLARE_UNPRIVILEGED_STORE_FUNCTION(type, insn) \ 25 static inline void store_##type(type* addr, type val, uintptr_t mepc) \ 26 { \ 27 register uintptr_t __mepc asm ("a2") = mepc; \ 28 register uintptr_t __mstatus asm ("a3"); \ 29 asm volatile ("csrrs %0, mstatus, %3\n" \ 30 #insn " %1, %2\n" \ 31 "csrw mstatus, %0" \ 32 : "+&r" (__mstatus) \ 33 : "r" (val), "m" (*addr), "r" (MSTATUS_MPRV), \ 34 "r" (__mepc)); \ 35 } 36 37DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint8_t, lbu) 38DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint16_t, lhu) 39DECLARE_UNPRIVILEGED_LOAD_FUNCTION(int8_t, lb) 40DECLARE_UNPRIVILEGED_LOAD_FUNCTION(int16_t, lh) 41DECLARE_UNPRIVILEGED_LOAD_FUNCTION(int32_t, lw) 42DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint8_t, sb) 43DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint16_t, sh) 44DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint32_t, sw) 45#if __riscv_xlen == 64 46DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint32_t, lwu) 47DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint64_t, ld) 48DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint64_t, sd) 49DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uintptr_t, ld) 50#else 51DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint32_t, lw) 52DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uintptr_t, lw) 53 54static inline uint64_t load_uint64_t(const uint64_t* addr, uintptr_t mepc) 55{ 56 return load_uint32_t((uint32_t*)addr, mepc) 57 + ((uint64_t)load_uint32_t((uint32_t*)addr + 1, mepc) << 32); 58} 59 60static inline void store_uint64_t(uint64_t* addr, uint64_t val, uintptr_t mepc) 61{ 62 store_uint32_t((uint32_t*)addr, val, mepc); 63 store_uint32_t((uint32_t*)addr + 1, val >> 32, mepc); 64} 65#endif 66 67static uintptr_t __attribute__((always_inline)) get_insn(uintptr_t mepc, uintptr_t* mstatus) 68{ 69 register uintptr_t __mepc asm ("a2") = mepc; 70 register uintptr_t __mstatus asm ("a3"); 71 uintptr_t val; 72#ifndef __riscv_compressed 73 asm ("csrrs %[mstatus], mstatus, %[mprv]\n" 74 STR(LWU) " %[insn], (%[addr])\n" 75 "csrw mstatus, %[mstatus]" 76 : [mstatus] "+&r" (__mstatus), [insn] "=&r" (val) 77 : [mprv] "r" (MSTATUS_MPRV | MSTATUS_MXR), [addr] "r" (__mepc)); 78#else 79 uintptr_t rvc_mask = 3, tmp; 80 asm ("csrrs %[mstatus], mstatus, %[mprv]\n" 81 "and %[tmp], %[addr], 2\n" 82 "bnez %[tmp], 1f\n" 83 STR(LWU) " %[insn], (%[addr])\n" 84 "and %[tmp], %[insn], %[rvc_mask]\n" 85 "beq %[tmp], %[rvc_mask], 2f\n" 86 "sll %[insn], %[insn], %[xlen_minus_16]\n" 87 "srl %[insn], %[insn], %[xlen_minus_16]\n" 88 "j 2f\n" 89 "1:\n" 90 "lhu %[insn], (%[addr])\n" 91 "and %[tmp], %[insn], %[rvc_mask]\n" 92 "bne %[tmp], %[rvc_mask], 2f\n" 93 "lhu %[tmp], 2(%[addr])\n" 94 "sll %[tmp], %[tmp], 16\n" 95 "add %[insn], %[insn], %[tmp]\n" 96 "2: csrw mstatus, %[mstatus]" 97 : [mstatus] "+&r" (__mstatus), [insn] "=&r" (val), [tmp] "=&r" (tmp) 98 : [mprv] "r" (MSTATUS_MPRV | MSTATUS_MXR), [addr] "r" (__mepc), 99 [rvc_mask] "r" (rvc_mask), [xlen_minus_16] "i" (__riscv_xlen - 16)); 100#endif 101 *mstatus = __mstatus; 102 return val; 103} 104 105#endif 106