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