1 /* 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2019 Western Digital Corporation or its affiliates. 5 * 6 * Authors: 7 * Anup Patel <anup.patel@wdc.com> 8 */ 9 10 #ifndef __RISCV_ASM_H__ 11 #define __RISCV_ASM_H__ 12 13 #include <sbi/riscv_encoding.h> 14 15 /* clang-format off */ 16 17 #ifdef __ASSEMBLY__ 18 #define __ASM_STR(x) x 19 #else 20 #define __ASM_STR(x) #x 21 #endif 22 23 #if __riscv_xlen == 64 24 #define __REG_SEL(a, b) __ASM_STR(a) 25 #elif __riscv_xlen == 32 26 #define __REG_SEL(a, b) __ASM_STR(b) 27 #else 28 #error "Unexpected __riscv_xlen" 29 #endif 30 31 #define PAGE_SHIFT (12) 32 #define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) 33 #define PAGE_MASK (~(PAGE_SIZE - 1)) 34 35 #define REG_L __REG_SEL(ld, lw) 36 #define REG_S __REG_SEL(sd, sw) 37 #define SZREG __REG_SEL(8, 4) 38 #define LGREG __REG_SEL(3, 2) 39 40 #if __SIZEOF_POINTER__ == 8 41 #ifdef __ASSEMBLY__ 42 #define RISCV_PTR .dword 43 #define RISCV_SZPTR 8 44 #define RISCV_LGPTR 3 45 #else 46 #define RISCV_PTR ".dword" 47 #define RISCV_SZPTR "8" 48 #define RISCV_LGPTR "3" 49 #endif 50 #elif __SIZEOF_POINTER__ == 4 51 #ifdef __ASSEMBLY__ 52 #define RISCV_PTR .word 53 #define RISCV_SZPTR 4 54 #define RISCV_LGPTR 2 55 #else 56 #define RISCV_PTR ".word" 57 #define RISCV_SZPTR "4" 58 #define RISCV_LGPTR "2" 59 #endif 60 #else 61 #error "Unexpected __SIZEOF_POINTER__" 62 #endif 63 64 #if (__SIZEOF_INT__ == 4) 65 #define RISCV_INT __ASM_STR(.word) 66 #define RISCV_SZINT __ASM_STR(4) 67 #define RISCV_LGINT __ASM_STR(2) 68 #else 69 #error "Unexpected __SIZEOF_INT__" 70 #endif 71 72 #if (__SIZEOF_SHORT__ == 2) 73 #define RISCV_SHORT __ASM_STR(.half) 74 #define RISCV_SZSHORT __ASM_STR(2) 75 #define RISCV_LGSHORT __ASM_STR(1) 76 #else 77 #error "Unexpected __SIZEOF_SHORT__" 78 #endif 79 80 /* clang-format on */ 81 82 #ifndef __ASSEMBLY__ 83 84 #define csr_swap(csr, val) \ 85 ({ \ 86 unsigned long __v = (unsigned long)(val); \ 87 __asm__ __volatile__("csrrw %0, " __ASM_STR(csr) ", %1" \ 88 : "=r"(__v) \ 89 : "rK"(__v) \ 90 : "memory"); \ 91 __v; \ 92 }) 93 94 #define csr_read(csr) \ 95 ({ \ 96 register unsigned long __v; \ 97 __asm__ __volatile__("csrr %0, " __ASM_STR(csr) \ 98 : "=r"(__v) \ 99 : \ 100 : "memory"); \ 101 __v; \ 102 }) 103 104 #define csr_write(csr, val) \ 105 ({ \ 106 unsigned long __v = (unsigned long)(val); \ 107 __asm__ __volatile__("csrw " __ASM_STR(csr) ", %0" \ 108 : \ 109 : "rK"(__v) \ 110 : "memory"); \ 111 }) 112 113 #define csr_read_set(csr, val) \ 114 ({ \ 115 unsigned long __v = (unsigned long)(val); \ 116 __asm__ __volatile__("csrrs %0, " __ASM_STR(csr) ", %1" \ 117 : "=r"(__v) \ 118 : "rK"(__v) \ 119 : "memory"); \ 120 __v; \ 121 }) 122 123 #define csr_set(csr, val) \ 124 ({ \ 125 unsigned long __v = (unsigned long)(val); \ 126 __asm__ __volatile__("csrs " __ASM_STR(csr) ", %0" \ 127 : \ 128 : "rK"(__v) \ 129 : "memory"); \ 130 }) 131 132 #define csr_read_clear(csr, val) \ 133 ({ \ 134 unsigned long __v = (unsigned long)(val); \ 135 __asm__ __volatile__("csrrc %0, " __ASM_STR(csr) ", %1" \ 136 : "=r"(__v) \ 137 : "rK"(__v) \ 138 : "memory"); \ 139 __v; \ 140 }) 141 142 #define csr_clear(csr, val) \ 143 ({ \ 144 unsigned long __v = (unsigned long)(val); \ 145 __asm__ __volatile__("csrc " __ASM_STR(csr) ", %0" \ 146 : \ 147 : "rK"(__v) \ 148 : "memory"); \ 149 }) 150 151 unsigned long csr_read_num(int csr_num); 152 153 void csr_write_num(int csr_num, unsigned long val); 154 155 #define wfi() \ 156 do { \ 157 __asm__ __volatile__("wfi" ::: "memory"); \ 158 } while (0) 159 160 /* Get current HART id */ 161 #define current_hartid() ((unsigned int)csr_read(CSR_MHARTID)) 162 163 /* determine CPU extension, return non-zero support */ 164 int misa_extension_imp(char ext); 165 166 #define misa_extension(c)\ 167 ({\ 168 _Static_assert(((c >= 'A') && (c <= 'Z')),\ 169 "The parameter of misa_extension must be [A-Z]");\ 170 misa_extension_imp(c);\ 171 }) 172 173 /* Get MXL field of misa, return -1 on error */ 174 int misa_xlen(void); 175 176 /* Get RISC-V ISA string representation */ 177 void misa_string(int xlen, char *out, unsigned int out_sz); 178 179 int pmp_set(unsigned int n, unsigned long prot, unsigned long addr, 180 unsigned long log2len); 181 182 int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out, 183 unsigned long *log2len); 184 185 #endif /* !__ASSEMBLY__ */ 186 187 #endif 188