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