1 /**
2  * @file
3  * @brief RISCV-Specific constants for ELF binaries.
4  *
5  * References can be found here:
6  * https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc
7  */
8 /*
9  * Copyright (c) 2024 CISPA Helmholtz Center for Information Security gGmbH
10  *
11  * SPDX-License-Identifier: Apache-2.0
12  */
13 #ifndef ZEPHYR_ARCH_RISCV_ELF_H
14 #define ZEPHYR_ARCH_RISCV_ELF_H
15 
16 #include <stdint.h>
17 #include <zephyr/sys/util_macro.h>
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 
23 /**
24  * Relocation names for RISCV-specific relocations
25  * @cond ignore
26  */
27 
28 #define R_RISCV_NONE              0
29 #define R_RISCV_32                1
30 #define R_RISCV_64                2
31 #define R_RISCV_RELATIVE          3
32 #define R_RISCV_COPY              4
33 #define R_RISCV_JUMP_SLOT         5
34 #define R_RISCV_TLS_DTPMOD32      6
35 #define R_RISCV_TLS_DTPMOD64      7
36 #define R_RISCV_TLS_DTPREL32      8
37 #define R_RISCV_TLS_DTPREL64      9
38 #define R_RISCV_TLS_TPREL32       10
39 #define R_RISCV_TLS_TPREL64       11
40 #define R_RISCV_TLSDESC           12
41 /* 13-15 reserved */
42 #define R_RISCV_BRANCH            16
43 #define R_RISCV_JAL               17
44 #define R_RISCV_CALL              18
45 #define R_RISCV_CALL_PLT          19
46 #define R_RISCV_GOT_HI20          20
47 #define R_RISCV_TLS_GOT_HI20      21
48 #define R_RISCV_TLS_GD_HI20       22
49 #define R_RISCV_PCREL_HI20        23
50 #define R_RISCV_PCREL_LO12_I      24
51 #define R_RISCV_PCREL_LO12_S      25
52 #define R_RISCV_HI20              26
53 #define R_RISCV_LO12_I            27
54 #define R_RISCV_LO12_S            28
55 #define R_RISCV_TPREL_HI20        29
56 #define R_RISCV_TPREL_LO12_I      30
57 #define R_RISCV_TPREL_LO12_S      31
58 #define R_RISCV_TPREL_ADD         32
59 #define R_RISCV_ADD8              33
60 #define R_RISCV_ADD16             34
61 #define R_RISCV_ADD32             35
62 #define R_RISCV_ADD64             36
63 #define R_RISCV_SUB8              37
64 #define R_RISCV_SUB16             38
65 #define R_RISCV_SUB32             39
66 #define R_RISCV_SUB64             40
67 #define R_RISCV_GOT32_PCREL       41
68 /* 42 reserved */
69 #define R_RISCV_ALIGN             43
70 /* next two refer to compressed instructions */
71 #define R_RISCV_RVC_BRANCH        44
72 #define R_RISCV_RVC_JUMP          45
73 /* 46-50 reserved */
74 #define R_RISCV_RELAX             51
75 #define R_RISCV_SUB6              52
76 #define R_RISCV_SET6              53
77 #define R_RISCV_SET8              54
78 #define R_RISCV_SET16             55
79 #define R_RISCV_SET32             56
80 #define R_RISCV_32_PCREL          57
81 #define R_RISCV_IRELATIVE         58
82 #define R_RISCV_PLT32             59
83 #define R_RISCV_SET_ULEB128       60
84 #define R_RISCV_SUB_ULEB128       61
85 #define R_RISCV_TLSDESC_HI20      62
86 #define R_RISCV_TLSDESC_LOAD_LO12 63
87 #define R_RISCV_TLSDESC_ADD_LO12  64
88 #define R_RISCV_TLSDESC_CALL      65
89 /* 66-190 reserved */
90 #define R_RISCV_VENDOR            191
91 /* 192-255 reserved */
92 /** @endcond */
93 
94 /**
95  * "wordclass" from RISC-V specification
96  * @cond ignore
97  */
98 #if defined(CONFIG_64BIT)
99 typedef uint64_t r_riscv_wordclass_t;
100 #else
101 typedef uint32_t r_riscv_wordclass_t;
102 #endif
103 /** @endcond */
104 
105 /** @brief  Extract bit from immediate
106  *
107  * @param imm8 immediate value (usually upper 20 or lower 12 bit)
108  * @param bit which bit to extract
109  */
110 #define R_RISCV_IMM8_GET_BIT(imm8, bit) (((imm8) & BIT(bit)) >> (bit))
111 
112 /** @brief  Generate mask for immediate in B-type RISC-V instruction
113  *
114  * @param imm8 immediate value, lower 12 bits used;
115  *             due to alignment requirements, imm8[0] is implicitly 0
116  *
117  */
118 #define R_RISCV_BTYPE_IMM8_MASK(imm8)                                                              \
119 	((R_RISCV_IMM8_GET_BIT(imm8, 12) << 31) | (R_RISCV_IMM8_GET_BIT(imm8, 10) << 30) |         \
120 	 (R_RISCV_IMM8_GET_BIT(imm8, 9) << 29) | (R_RISCV_IMM8_GET_BIT(imm8, 8) << 28) |           \
121 	 (R_RISCV_IMM8_GET_BIT(imm8, 7) << 27) | (R_RISCV_IMM8_GET_BIT(imm8, 6) << 26) |           \
122 	 (R_RISCV_IMM8_GET_BIT(imm8, 5) << 25) | (R_RISCV_IMM8_GET_BIT(imm8, 4) << 11) |           \
123 	 (R_RISCV_IMM8_GET_BIT(imm8, 3) << 10) | (R_RISCV_IMM8_GET_BIT(imm8, 2) << 9) |            \
124 	 (R_RISCV_IMM8_GET_BIT(imm8, 1) << 8) | (R_RISCV_IMM8_GET_BIT(imm8, 11) << 7))
125 
126 /** @brief  Generate mask for immediate in J-type RISC-V instruction
127  *
128  * @param imm8 immediate value, lower 21 bits used;
129  *             due to alignment requirements, imm8[0] is implicitly 0
130  *
131  */
132 #define R_RISCV_JTYPE_IMM8_MASK(imm8)                                                              \
133 	((R_RISCV_IMM8_GET_BIT(imm8, 20) << 31) | (R_RISCV_IMM8_GET_BIT(imm8, 10) << 30) |         \
134 	 (R_RISCV_IMM8_GET_BIT(imm8, 9) << 29) | (R_RISCV_IMM8_GET_BIT(imm8, 8) << 28) |           \
135 	 (R_RISCV_IMM8_GET_BIT(imm8, 7) << 27) | (R_RISCV_IMM8_GET_BIT(imm8, 6) << 26) |           \
136 	 (R_RISCV_IMM8_GET_BIT(imm8, 5) << 25) | (R_RISCV_IMM8_GET_BIT(imm8, 4) << 24) |           \
137 	 (R_RISCV_IMM8_GET_BIT(imm8, 3) << 23) | (R_RISCV_IMM8_GET_BIT(imm8, 2) << 22) |           \
138 	 (R_RISCV_IMM8_GET_BIT(imm8, 1) << 21) | (R_RISCV_IMM8_GET_BIT(imm8, 11) << 20) |          \
139 	 (R_RISCV_IMM8_GET_BIT(imm8, 19) << 19) | (R_RISCV_IMM8_GET_BIT(imm8, 18) << 18) |         \
140 	 (R_RISCV_IMM8_GET_BIT(imm8, 17) << 17) | (R_RISCV_IMM8_GET_BIT(imm8, 16) << 16) |         \
141 	 (R_RISCV_IMM8_GET_BIT(imm8, 15) << 15) | (R_RISCV_IMM8_GET_BIT(imm8, 14) << 14) |         \
142 	 (R_RISCV_IMM8_GET_BIT(imm8, 13) << 13) | (R_RISCV_IMM8_GET_BIT(imm8, 12) << 12))
143 
144 /** @brief  Generate mask for immediate in S-type RISC-V instruction
145  *
146  * @param imm8 immediate value, lower 12 bits used
147  *
148  */
149 #define R_RISCV_STYPE_IMM8_MASK(imm8)                                                              \
150 	((R_RISCV_IMM8_GET_BIT(imm8, 11) << 31) | (R_RISCV_IMM8_GET_BIT(imm8, 10) << 30) |         \
151 	 (R_RISCV_IMM8_GET_BIT(imm8, 9) << 29) | (R_RISCV_IMM8_GET_BIT(imm8, 8) << 28) |           \
152 	 (R_RISCV_IMM8_GET_BIT(imm8, 7) << 27) | (R_RISCV_IMM8_GET_BIT(imm8, 6) << 26) |           \
153 	 (R_RISCV_IMM8_GET_BIT(imm8, 5) << 25) | (R_RISCV_IMM8_GET_BIT(imm8, 4) << 11) |           \
154 	 (R_RISCV_IMM8_GET_BIT(imm8, 3) << 10) | (R_RISCV_IMM8_GET_BIT(imm8, 2) << 9) |            \
155 	 (R_RISCV_IMM8_GET_BIT(imm8, 1) << 8) | (R_RISCV_IMM8_GET_BIT(imm8, 0) << 7))
156 
157 /** @brief  Generate mask for immediate in compressed J-type RISC-V instruction
158  *
159  * @param imm8 immediate value, lower 12 bits used;
160  *             due to alignment requirements, imm8[0] is implicitly 0
161  *
162  */
163 #define R_RISCV_CJTYPE_IMM8_MASK(imm8)                                                             \
164 	((R_RISCV_IMM8_GET_BIT(imm8, 11) << 12) | (R_RISCV_IMM8_GET_BIT(imm8, 4) << 11) |          \
165 	 (R_RISCV_IMM8_GET_BIT(imm8, 9) << 10) | (R_RISCV_IMM8_GET_BIT(imm8, 8) << 9) |            \
166 	 (R_RISCV_IMM8_GET_BIT(imm8, 10) << 8) | (R_RISCV_IMM8_GET_BIT(imm8, 6) << 7) |            \
167 	 (R_RISCV_IMM8_GET_BIT(imm8, 7) << 6) | (R_RISCV_IMM8_GET_BIT(imm8, 3) << 5) |             \
168 	 (R_RISCV_IMM8_GET_BIT(imm8, 2) << 4) | (R_RISCV_IMM8_GET_BIT(imm8, 1) << 3) |             \
169 	 (R_RISCV_IMM8_GET_BIT(imm8, 5) << 2))
170 
171 /** @brief  Generate mask for immediate in compressed B-type RISC-V instruction
172  *
173  * @param imm8 immediate value, lower 9 bits used;
174  *             due to alignment requirements, imm8[0] is implicitly 0
175  *
176  */
177 #define R_RISCV_CBTYPE_IMM8_MASK(imm8)                                                             \
178 	((R_RISCV_IMM8_GET_BIT(imm8, 8) << 12) | (R_RISCV_IMM8_GET_BIT(imm8, 4) << 11) |           \
179 	 (R_RISCV_IMM8_GET_BIT(imm8, 3) << 10) | (R_RISCV_IMM8_GET_BIT(imm8, 7) << 6) |            \
180 	 (R_RISCV_IMM8_GET_BIT(imm8, 6) << 5) | (R_RISCV_IMM8_GET_BIT(imm8, 2) << 4) |             \
181 	 (R_RISCV_IMM8_GET_BIT(imm8, 1) << 3) | (R_RISCV_IMM8_GET_BIT(imm8, 5) << 2))
182 
183 /** @brief Clear immediate bits in B-type instruction.
184  *
185  * @param operand Address of RISC-V instruction, B-type
186  *
187  */
188 #define R_RISCV_CLEAR_BTYPE_IMM8(operand) ((operand) & ~R_RISCV_BTYPE_IMM8_MASK((uint32_t) -1))
189 
190 /** @brief Overwrite immediate in B-type instruction
191  *
192  * @param operand Address of RISC-V instruction, B-type
193  * @param imm8    New immediate
194  *
195  */
196 #define R_RISCV_SET_BTYPE_IMM8(operand, imm8)                                                      \
197 	((R_RISCV_CLEAR_BTYPE_IMM8(operand)) | R_RISCV_BTYPE_IMM8_MASK(imm8))
198 
199 /** @brief Clear immediate bits in J-type instruction.
200  *
201  * @param operand Address of RISC-V instruction, J-type
202  *
203  */
204 #define R_RISCV_CLEAR_JTYPE_IMM8(operand) ((operand) & ~R_RISCV_JTYPE_IMM8_MASK((uint32_t) -1))
205 
206 /** @brief Overwrite immediate in J-type instruction
207  *
208  * @param operand Address of RISC-V instruction, J-type
209  * @param imm8    New immediate
210  *
211  */
212 #define R_RISCV_SET_JTYPE_IMM8(operand, imm8)                                                      \
213 	((R_RISCV_CLEAR_JTYPE_IMM8(operand)) | R_RISCV_JTYPE_IMM8_MASK(imm8))
214 
215 /** @brief Clear immediate bits in S-type instruction.
216  *
217  * @param operand Address of RISC-V instruction, S-type
218  *
219  */
220 #define R_RISCV_CLEAR_STYPE_IMM8(operand) ((operand) & ~R_RISCV_STYPE_IMM8_MASK((uint32_t) -1))
221 
222 /** @brief Overwrite immediate in S-type instruction
223  *
224  * @param operand Address of RISC-V instruction, S-type
225  * @param imm8    New immediate
226  *
227  */
228 #define R_RISCV_SET_STYPE_IMM8(operand, imm8)                                                      \
229 	((R_RISCV_CLEAR_STYPE_IMM8(operand)) | R_RISCV_STYPE_IMM8_MASK(imm8))
230 
231 /** @brief Clear immediate bits in compressed J-type instruction.
232  *
233  * @param operand Address of RISC-V instruction, compressed-J-type
234  *
235  */
236 #define R_RISCV_CLEAR_CJTYPE_IMM8(operand) ((operand) & ~R_RISCV_CJTYPE_IMM8_MASK((uint32_t) -1))
237 
238 /** @brief Overwrite immediate in compressed J-type instruction
239  *
240  * @param operand Address of RISC-V instruction, compressed-J-type
241  * @param imm8    New immediate
242  *
243  */
244 #define R_RISCV_SET_CJTYPE_IMM8(operand, imm8)                                                     \
245 	((R_RISCV_CLEAR_CJTYPE_IMM8(operand)) | R_RISCV_CJTYPE_IMM8_MASK(imm8))
246 
247 /** @brief Clear immediate bits in compressed B-type instruction.
248  *
249  * @param operand Address of RISC-V instruction, compressed-B-type
250  *
251  */
252 #define R_RISCV_CLEAR_CBTYPE_IMM8(operand) ((operand) & ~R_RISCV_CBTYPE_IMM8_MASK((uint32_t) -1))
253 
254 /** @brief Overwrite immediate in compressed B-type instruction
255  *
256  * @param operand Address of RISC-V instruction, compressed-B-type
257  * @param imm8    New immediate
258  *
259  */
260 #define R_RISCV_SET_CBTYPE_IMM8(operand, imm8)                                                     \
261 	((R_RISCV_CLEAR_CBTYPE_IMM8(operand)) | R_RISCV_CBTYPE_IMM8_MASK(imm8))
262 
263 /** @brief Clear immediate bits in U-type instruction.
264  *
265  * @param operand Address of RISC-V instruction, U-type
266  *
267  */
268 #define R_RISCV_CLEAR_UTYPE_IMM8(operand) ((operand) & ~(0xFFFFF000))
269 
270 /** @brief Overwrite immediate in U-type instruction
271  *
272  * @param operand Address of RISC-V instruction, U-type
273  * @param imm8    New immediate
274  *
275  */
276 #define R_RISCV_SET_UTYPE_IMM8(operand, imm8)                                                      \
277 	((R_RISCV_CLEAR_UTYPE_IMM8(operand)) | ((imm8) & 0xFFFFF000))
278 
279 /** @brief Clear immediate bits in I-type instruction.
280  *
281  * @param operand Address of RISC-V instruction, I-type
282  *
283  */
284 #define R_RISCV_CLEAR_ITYPE_IMM8(operand) ((operand) & ~(0xFFF00000))
285 
286 /** @brief Overwrite immediate in I-type instruction
287  *
288  * @param operand Address of RISC-V instruction, I-type
289  * @param imm8    New immediate
290  *
291  */
292 #define R_RISCV_SET_ITYPE_IMM8(operand, imm8) ((R_RISCV_CLEAR_ITYPE_IMM8(operand)) | ((imm8) << 20))
293 
294 #ifdef __cplusplus
295 }
296 #endif
297 
298 #endif /* ZEPHYR_ARCH_RISCV_ELF_H */
299