gen/
.clang-format
570 B
.gitignore
30 B
.gitsigners
112 B
LICENSE
1.1 KiB
Makefile
911 B
README
1.8 KiB
ast.c
5.0 KiB
ast.h
15.1 KiB
desugar.c
23.1 KiB
desugar.h
286 B
gen.c
108.5 KiB
gen.h
4.9 KiB
io.c
1.1 KiB
io.h
444 B
limits.h
1.3 KiB
module.c
10.0 KiB
module.h
2.2 KiB
options.c
1.4 KiB
options.h
472 B
parser.c
68.3 KiB
parser.h
942 B
radiance.c
3.7 KiB
ralloc.c
2.0 KiB
ralloc.h
1.1 KiB
resolver.c
109.7 KiB
resolver.h
5.6 KiB
riscv.c
12.0 KiB
riscv.h
12.0 KiB
scanner.c
10.2 KiB
scanner.h
3.2 KiB
strings.c
2.6 KiB
strings.h
407 B
symtab.c
5.7 KiB
symtab.h
4.6 KiB
types.h
1.0 KiB
util.h
1.5 KiB
riscv.h
raw
| 1 | #ifndef OP_H |
| 2 | #define OP_H |
| 3 | |
| 4 | #include "types.h" |
| 5 | |
| 6 | /* Total number of registers. */ |
| 7 | #define REGISTERS 32 |
| 8 | /* Word size of target architecture (RISCV64). */ |
| 9 | #define WORD_SIZE 8 |
| 10 | /* Tag size for optional/union discriminants. */ |
| 11 | #define TAG_SIZE 1 |
| 12 | /* Instruction size in bytes (always 32-bit, even on RV64). */ |
| 13 | #define INSTR_SIZE 4 |
| 14 | /* Stack alignment requirement. */ |
| 15 | #define STACK_ALIGNMENT 16 |
| 16 | /* The frame pointer register is set as an alias of `S0`. */ |
| 17 | #define FP S0 |
| 18 | |
| 19 | /* Convenient macro wrappers for `instr`. |
| 20 | * Some of these, such as BLE and BGT are implemented by swapping the operands |
| 21 | * of other instructions. */ |
| 22 | #define ADDI(rd, rs1, imm) __instr(I_ADDI, rd, rs1, 0, imm) |
| 23 | #define SLTI(rd, rs1, imm) __instr(I_SLTI, rd, rs1, 0, imm) |
| 24 | #define SLTIU(rd, rs1, imm) __instr(I_SLTIU, rd, rs1, 0, imm) |
| 25 | #define XORI(rd, rs1, imm) __instr(I_XORI, rd, rs1, 0, imm) |
| 26 | #define ORI(rd, rs1, imm) __instr(I_ORI, rd, rs1, 0, imm) |
| 27 | #define ANDI(rd, rs1, imm) __instr(I_ANDI, rd, rs1, 0, imm) |
| 28 | #define SLLI(rd, rs1, imm) __instr(I_SLLI, rd, rs1, 0, imm) |
| 29 | #define SRLI(rd, rs1, imm) __instr(I_SRLI, rd, rs1, 0, imm) |
| 30 | #define SRAI(rd, rs1, imm) __instr(I_SRAI, rd, rs1, 0, imm) |
| 31 | #define JALR(rd, rs1, imm) __instr(I_JALR, rd, rs1, 0, imm) |
| 32 | #define LB(rd, rs1, imm) __instr(I_LB, rd, rs1, 0, imm) |
| 33 | #define LH(rd, rs1, imm) __instr(I_LH, rd, rs1, 0, imm) |
| 34 | #define LW(rd, rs1, imm) __instr(I_LW, rd, rs1, 0, imm) |
| 35 | #define LWU(rd, rs1, imm) __instr(I_LWU, rd, rs1, 0, imm) |
| 36 | #define LD(rd, rs1, imm) __instr(I_LD, rd, rs1, 0, imm) |
| 37 | #define LBU(rd, rs1, imm) __instr(I_LBU, rd, rs1, 0, imm) |
| 38 | #define LHU(rd, rs1, imm) __instr(I_LHU, rd, rs1, 0, imm) |
| 39 | #define SB(rs2, rs1, imm) __instr(I_SB, 0, rs1, rs2, imm) |
| 40 | #define SH(rs2, rs1, imm) __instr(I_SH, 0, rs1, rs2, imm) |
| 41 | #define SW(rs2, rs1, imm) __instr(I_SW, 0, rs1, rs2, imm) |
| 42 | #define SD(rs2, rs1, imm) __instr(I_SD, 0, rs1, rs2, imm) |
| 43 | #define BEQ(rs1, rs2, imm) __instr(I_BEQ, 0, rs1, rs2, imm) |
| 44 | #define BNE(rs1, rs2, imm) __instr(I_BNE, 0, rs1, rs2, imm) |
| 45 | #define BLT(rs1, rs2, imm) __instr(I_BLT, 0, rs1, rs2, imm) |
| 46 | #define BGE(rs1, rs2, imm) __instr(I_BGE, 0, rs1, rs2, imm) |
| 47 | #define BLTU(rs1, rs2, imm) __instr(I_BLTU, 0, rs1, rs2, imm) |
| 48 | #define BGEU(rs1, rs2, imm) __instr(I_BGEU, 0, rs1, rs2, imm) |
| 49 | #define BLE(rs1, rs2, imm) __instr(I_BGE, 0, rs2, rs1, imm) |
| 50 | #define BGT(rs1, rs2, imm) __instr(I_BLT, 0, rs2, rs1, imm) |
| 51 | #define ADD(rd, rs1, rs2) __instr(I_ADD, rd, rs1, rs2, 0) |
| 52 | #define SUB(rd, rs1, rs2) __instr(I_SUB, rd, rs1, rs2, 0) |
| 53 | #define DIV(rd, rs1, rs2) __instr(I_DIV, rd, rs1, rs2, 0) |
| 54 | #define DIVU(rd, rs1, rs2) __instr(I_DIVU, rd, rs1, rs2, 0) |
| 55 | #define REM(rd, rs1, rs2) __instr(I_REM, rd, rs1, rs2, 0) |
| 56 | #define REMU(rd, rs1, rs2) __instr(I_REMU, rd, rs1, rs2, 0) |
| 57 | #define MUL(rd, rs1, rs2) __instr(I_MUL, rd, rs1, rs2, 0) |
| 58 | #define SLL(rd, rs1, rs2) __instr(I_SLL, rd, rs1, rs2, 0) |
| 59 | #define SLT(rd, rs1, rs2) __instr(I_SLT, rd, rs1, rs2, 0) |
| 60 | #define SLTU(rd, rs1, rs2) __instr(I_SLTU, rd, rs1, rs2, 0) |
| 61 | #define XOR(rd, rs1, rs2) __instr(I_XOR, rd, rs1, rs2, 0) |
| 62 | #define SRL(rd, rs1, rs2) __instr(I_SRL, rd, rs1, rs2, 0) |
| 63 | #define AND(rd, rs1, rs2) __instr(I_AND, rd, rs1, rs2, 0) |
| 64 | #define OR(rd, rs1, rs2) __instr(I_OR, rd, rs1, rs2, 0) |
| 65 | #define LUI(rd, imm) __instr(I_LUI, rd, 0, 0, imm) |
| 66 | #define AUIPC(rd, imm) __instr(I_AUIPC, rd, 0, 0, imm) |
| 67 | #define JAL(rd, imm) __instr(I_JAL, rd, 0, 0, imm) |
| 68 | #define JMP(imm) __instr(I_JMP, 0, 0, 0, imm) |
| 69 | #define MV(rd, rs1) __instr(I_MV, rd, rs1, 0, 0) |
| 70 | #define NOT(rd, rs1) __instr(I_NOT, rd, rs1, 0, 0) |
| 71 | #define NEG(rd, rs1) __instr(I_NEG, rd, rs1, 0, 0) |
| 72 | #define NOP __instr(I_NOP, 0, 0, 0, 0) |
| 73 | #define RET __instr(I_JALR, ZERO, RA, 0, 0) |
| 74 | #define EBREAK __instr(I_EBREAK, 0, 0, 0, 0) |
| 75 | #define ECALL __instr(I_ECALL, 0, 0, 0, 0) |
| 76 | /* RV64I word-width (32-bit) operations */ |
| 77 | #define ADDIW(rd, rs1, imm) __instr(I_ADDIW, rd, rs1, 0, imm) |
| 78 | #define ADDW(rd, rs1, rs2) __instr(I_ADDW, rd, rs1, rs2, 0) |
| 79 | #define SUBW(rd, rs1, rs2) __instr(I_SUBW, rd, rs1, rs2, 0) |
| 80 | #define MULW(rd, rs1, rs2) __instr(I_MULW, rd, rs1, rs2, 0) |
| 81 | #define DIVW(rd, rs1, rs2) __instr(I_DIVW, rd, rs1, rs2, 0) |
| 82 | #define DIVUW(rd, rs1, rs2) __instr(I_DIVUW, rd, rs1, rs2, 0) |
| 83 | #define REMW(rd, rs1, rs2) __instr(I_REMW, rd, rs1, rs2, 0) |
| 84 | #define REMUW(rd, rs1, rs2) __instr(I_REMUW, rd, rs1, rs2, 0) |
| 85 | #define SLLIW(rd, rs1, imm) __instr(I_SLLIW, rd, rs1, 0, imm) |
| 86 | #define SRLIW(rd, rs1, imm) __instr(I_SRLIW, rd, rs1, 0, imm) |
| 87 | #define SRAIW(rd, rs1, imm) __instr(I_SRAIW, rd, rs1, 0, imm) |
| 88 | #define SLLW(rd, rs1, rs2) __instr(I_SLLW, rd, rs1, rs2, 0) |
| 89 | #define SRLW(rd, rs1, rs2) __instr(I_SRLW, rd, rs1, rs2, 0) |
| 90 | #define SRAW(rd, rs1, rs2) __instr(I_SRAW, rd, rs1, rs2, 0) |
| 91 | /* F Extension - Floating-point instructions */ |
| 92 | #define FADD_S(rd, rs1, rs2) __instr(I_FADD_S, rd, rs1, rs2, 0) |
| 93 | #define FSUB_S(rd, rs1, rs2) __instr(I_FSUB_S, rd, rs1, rs2, 0) |
| 94 | #define FMUL_S(rd, rs1, rs2) __instr(I_FMUL_S, rd, rs1, rs2, 0) |
| 95 | #define FDIV_S(rd, rs1, rs2) __instr(I_FDIV_S, rd, rs1, rs2, 0) |
| 96 | #define FEQ_S(rd, rs1, rs2) __instr(I_FEQ_S, rd, rs1, rs2, 0) |
| 97 | #define FLT_S(rd, rs1, rs2) __instr(I_FLT_S, rd, rs1, rs2, 0) |
| 98 | #define FLE_S(rd, rs1, rs2) __instr(I_FLE_S, rd, rs1, rs2, 0) |
| 99 | #define FLW(rd, rs1, imm) __instr(I_FLW, rd, rs1, 0, imm) |
| 100 | #define FSW(rs2, rs1, imm) __instr(I_FSW, 0, rs1, rs2, imm) |
| 101 | |
| 102 | /* String representations of register names. */ |
| 103 | extern const char *reg_names[]; |
| 104 | |
| 105 | /* Boolean map of caller-saved registers. |
| 106 | * True for registers that need to be saved by the caller |
| 107 | * before a function call. */ |
| 108 | extern const bool caller_saved_registers[REGISTERS]; |
| 109 | |
| 110 | /* RISC-V register names. */ |
| 111 | typedef enum { |
| 112 | ZERO = 0, /* Hard-wired zero */ |
| 113 | RA = 1, /* Return address */ |
| 114 | SP = 2, /* Stack pointer */ |
| 115 | GP = 3, /* Global pointer */ |
| 116 | TP = 4, /* Thread pointer */ |
| 117 | T0 = 5, /* Temporary/alternate link register */ |
| 118 | T1 = 6, /* Temporary */ |
| 119 | T2 = 7, /* Temporary */ |
| 120 | S0 = 8, /* Saved register/frame pointer */ |
| 121 | S1 = 9, /* Saved register */ |
| 122 | A0 = 10, /* Function arguments/returns */ |
| 123 | A1 = 11, |
| 124 | A2 = 12, /* Function arguments */ |
| 125 | A3 = 13, |
| 126 | A4 = 14, |
| 127 | A5 = 15, |
| 128 | A6 = 16, |
| 129 | A7 = 17, |
| 130 | S2 = 18, /* Saved registers */ |
| 131 | S3 = 19, |
| 132 | S4 = 20, |
| 133 | S5 = 21, |
| 134 | S6 = 22, |
| 135 | S7 = 23, |
| 136 | S8 = 24, |
| 137 | S9 = 25, |
| 138 | S10 = 26, |
| 139 | S11 = 27, |
| 140 | T3 = 28, /* Temporaries */ |
| 141 | T4 = 29, |
| 142 | T5 = 30, |
| 143 | T6 = 31 |
| 144 | } reg_t; |
| 145 | |
| 146 | /* Temporary registers (T1-T6) */ |
| 147 | extern const reg_t temp_registers[6]; |
| 148 | |
| 149 | /* Opcodes for RISC-V base instruction set */ |
| 150 | typedef enum { |
| 151 | OP_LOAD = 0x03, |
| 152 | OP_STORE = 0x23, |
| 153 | OP_BRANCH = 0x63, |
| 154 | OP_JALR = 0x67, |
| 155 | OP_JAL = 0x6F, |
| 156 | OP_OP = 0x33, |
| 157 | OP_IMM = 0x13, |
| 158 | OP_AUIPC = 0x17, |
| 159 | OP_IMM_32 = 0x1B, /* RV64I: ADDIW, SLLIW, SRLIW, SRAIW */ |
| 160 | OP_OP_32 = 0x3B, /* RV64I: ADDW, SUBW, SLLW, SRLW, SRAW, MULW, DIVW, REMW */ |
| 161 | OP_LUI = 0x37, |
| 162 | OP_SYSTEM = 0x73, |
| 163 | OP_FENCE = 0x0F, |
| 164 | /* F Extension opcodes */ |
| 165 | OP_LOAD_FP = 0x07, |
| 166 | OP_STORE_FP = 0x27, |
| 167 | OP_OP_FP = 0x53 |
| 168 | } opcode_t; |
| 169 | |
| 170 | /* Function3 values */ |
| 171 | typedef enum { |
| 172 | /* Memory operations */ |
| 173 | FUNCT3_BYTE = 0x0, /* LB/SB - Load/Store Byte */ |
| 174 | FUNCT3_HALF = 0x1, /* LH/SH - Load/Store Halfword */ |
| 175 | FUNCT3_WORD = 0x2, /* LW/SW - Load/Store Word */ |
| 176 | FUNCT3_DOUBLE = 0x3, /* LD/SD - Load/Store Doubleword */ |
| 177 | FUNCT3_BYTE_U = 0x4, /* LBU - Load Byte Unsigned */ |
| 178 | FUNCT3_HALF_U = 0x5, /* LHU - Load Halfword Unsigned */ |
| 179 | FUNCT3_WORD_U = 0x6, /* LWU - Load Word Unsigned */ |
| 180 | |
| 181 | /* ALU operations */ |
| 182 | FUNCT3_ADD = 0x0, /* ADD/SUB/ADDI */ |
| 183 | FUNCT3_SLL = 0x1, /* SLL/SLLI */ |
| 184 | FUNCT3_SLT = 0x2, /* SLT/SLTI */ |
| 185 | FUNCT3_SLTU = 0x3, /* SLTU/SLTIU */ |
| 186 | FUNCT3_XOR = 0x4, /* XOR/XORI */ |
| 187 | FUNCT3_SRL = 0x5, /* SRL/SRA/SRLI/SRAI */ |
| 188 | FUNCT3_OR = 0x6, /* OR/ORI */ |
| 189 | FUNCT3_AND = 0x7, /* AND/ANDI */ |
| 190 | /* F Extension function3 codes */ |
| 191 | FUNCT3_WORD_FP = 0x2, /* FLW/FSW - Load/Store Single */ |
| 192 | FUNCT3_FEQ = 0x2, /* FEQ.S */ |
| 193 | FUNCT3_FLT = 0x1, /* FLT.S */ |
| 194 | FUNCT3_FLE = 0x0 /* FLE.S */ |
| 195 | } funct3_t; |
| 196 | |
| 197 | /* Function7 values */ |
| 198 | typedef enum { |
| 199 | FUNCT7_NORMAL = 0x00, |
| 200 | FUNCT7_SUB = 0x20, |
| 201 | FUNCT7_SRA = 0x20, |
| 202 | FUNCT7_MUL = 0x01, |
| 203 | /* F Extension function codes */ |
| 204 | FUNCT7_FADD_S = 0x00, |
| 205 | FUNCT7_FSUB_S = 0x04, |
| 206 | FUNCT7_FMUL_S = 0x08, |
| 207 | FUNCT7_FDIV_S = 0x0C, |
| 208 | FUNCT7_FEQ_S = 0x50, |
| 209 | FUNCT7_FLT_S = 0x50, |
| 210 | FUNCT7_FLE_S = 0x50 |
| 211 | } funct7_t; |
| 212 | |
| 213 | /* Represents a RISC-V instruction in its various formats */ |
| 214 | typedef union { |
| 215 | struct { |
| 216 | u32 opcode : 7; |
| 217 | u32 rd : 5; |
| 218 | u32 funct3 : 3; |
| 219 | u32 rs1 : 5; |
| 220 | u32 rs2 : 5; |
| 221 | u32 funct7 : 7; |
| 222 | } r; /* Register format */ |
| 223 | |
| 224 | struct { |
| 225 | u32 opcode : 7; |
| 226 | u32 rd : 5; |
| 227 | u32 funct3 : 3; |
| 228 | u32 rs1 : 5; |
| 229 | u32 imm_11_0 : 12; |
| 230 | } i; /* Immediate format */ |
| 231 | |
| 232 | struct { |
| 233 | u32 opcode : 7; |
| 234 | u32 imm_4_0 : 5; |
| 235 | u32 funct3 : 3; |
| 236 | u32 rs1 : 5; |
| 237 | u32 rs2 : 5; |
| 238 | u32 imm_11_5 : 7; |
| 239 | } s; /* Store format */ |
| 240 | |
| 241 | struct { |
| 242 | u32 opcode : 7; |
| 243 | u32 imm_11 : 1; |
| 244 | u32 imm_4_1 : 4; |
| 245 | u32 funct3 : 3; |
| 246 | u32 rs1 : 5; |
| 247 | u32 rs2 : 5; |
| 248 | u32 imm_10_5 : 6; |
| 249 | u32 imm_12 : 1; |
| 250 | } b; /* Branch format */ |
| 251 | |
| 252 | struct { |
| 253 | u32 opcode : 7; |
| 254 | u32 rd : 5; |
| 255 | u32 imm_31_12 : 20; |
| 256 | } u; /* Upper immediate format */ |
| 257 | |
| 258 | struct { |
| 259 | u32 opcode : 7; |
| 260 | u32 rd : 5; |
| 261 | u32 imm_19_12 : 8; |
| 262 | u32 imm_11 : 1; |
| 263 | u32 imm_10_1 : 10; |
| 264 | u32 imm_20 : 1; |
| 265 | } j; /* Jump format */ |
| 266 | |
| 267 | u32 raw; /* Raw 32-bit instruction */ |
| 268 | } instr_t; |
| 269 | |
| 270 | /* Instruction type. */ |
| 271 | typedef enum { |
| 272 | IFMT_I, /* I-type (immediate) */ |
| 273 | IFMT_R, /* R-type (register) */ |
| 274 | IFMT_S, /* S-type (store) */ |
| 275 | IFMT_B, /* B-type (branch) */ |
| 276 | IFMT_U, /* U-type (upper immediate) */ |
| 277 | IFMT_J, /* J-type (jump) */ |
| 278 | } ifmt_t; |
| 279 | |
| 280 | /* RISC-V instruction name. */ |
| 281 | typedef enum { |
| 282 | I_LUI, |
| 283 | I_AUIPC, |
| 284 | I_JAL, |
| 285 | I_JALR, |
| 286 | I_BEQ, |
| 287 | I_BNE, |
| 288 | I_BLT, |
| 289 | I_BGE, |
| 290 | I_BLTU, |
| 291 | I_BGEU, |
| 292 | I_LB, |
| 293 | I_LH, |
| 294 | I_LW, |
| 295 | I_LBU, |
| 296 | I_LHU, |
| 297 | I_SB, |
| 298 | I_SH, |
| 299 | I_SW, |
| 300 | I_ADDI, |
| 301 | I_SLTI, |
| 302 | I_SLTIU, |
| 303 | I_XORI, |
| 304 | I_ORI, |
| 305 | I_ANDI, |
| 306 | I_SLLI, |
| 307 | I_SRLI, |
| 308 | I_SRAI, |
| 309 | I_ADD, |
| 310 | I_SUB, |
| 311 | I_SLL, |
| 312 | I_SLT, |
| 313 | I_SLTU, |
| 314 | I_XOR, |
| 315 | I_SRL, |
| 316 | I_SRA, |
| 317 | I_OR, |
| 318 | I_AND, |
| 319 | I_MUL, |
| 320 | I_MULH, |
| 321 | I_MULHSU, |
| 322 | I_MULHU, |
| 323 | I_DIV, |
| 324 | I_DIVU, |
| 325 | I_REM, |
| 326 | I_REMU, |
| 327 | I_MV, |
| 328 | I_JMP, |
| 329 | I_NOP, |
| 330 | I_NOT, |
| 331 | I_NEG, |
| 332 | I_EBREAK, |
| 333 | I_ECALL, |
| 334 | /* F Extension - Floating-point instructions */ |
| 335 | I_FADD_S, |
| 336 | I_FSUB_S, |
| 337 | I_FMUL_S, |
| 338 | I_FDIV_S, |
| 339 | I_FEQ_S, |
| 340 | I_FLT_S, |
| 341 | I_FLE_S, |
| 342 | I_FLW, |
| 343 | I_FSW, |
| 344 | /* RV64I extensions */ |
| 345 | I_LWU, |
| 346 | I_LD, |
| 347 | I_SD, |
| 348 | I_ADDIW, |
| 349 | I_SLLIW, |
| 350 | I_SRLIW, |
| 351 | I_SRAIW, |
| 352 | I_ADDW, |
| 353 | I_SUBW, |
| 354 | I_SLLW, |
| 355 | I_SRLW, |
| 356 | I_SRAW, |
| 357 | I_MULW, |
| 358 | I_DIVW, |
| 359 | I_DIVUW, |
| 360 | I_REMW, |
| 361 | I_REMUW |
| 362 | } iname_t; |
| 363 | |
| 364 | /* Returns a RISC-V instruction based on the instruction type. */ |
| 365 | instr_t instr(iname_t op, reg_t rd, reg_t rs1, reg_t rs2, i32 imm); |
| 366 | |
| 367 | static inline instr_t __instr( |
| 368 | iname_t op, reg_t rd, reg_t rs1, reg_t rs2, i32 imm |
| 369 | ) { |
| 370 | return instr(op, rd, rs1, rs2, imm); |
| 371 | } |
| 372 | |
| 373 | /* Return true when a signed 12-bit immediate can encode `value`. */ |
| 374 | static inline bool is_small(i32 value) { |
| 375 | return value >= -2048 && value <= 2047; |
| 376 | } |
| 377 | |
| 378 | static inline bool is_branch_imm(i32 value) { |
| 379 | return value >= -(1 << 12) && value <= ((1 << 12) - 2) && !(value & 1); |
| 380 | } |
| 381 | |
| 382 | static inline bool is_jump_imm(i32 value) { |
| 383 | return value >= -(1 << 20) && value <= ((1 << 20) - 2) && !(value & 1); |
| 384 | } |
| 385 | |
| 386 | /* Helper function to sign-extend a value. */ |
| 387 | i32 sign_extend(u32 value, int bit_width); |
| 388 | /* Aligns a size to the specified alignment boundary. */ |
| 389 | i32 align(i32 size, i32 alignment); |
| 390 | /* Functions to get immediates out of instruction. */ |
| 391 | i32 get_i_imm(instr_t instr); |
| 392 | i32 get_s_imm(instr_t instr); |
| 393 | i32 get_b_imm(instr_t instr); |
| 394 | i32 get_j_imm(instr_t instr); |
| 395 | |
| 396 | #endif |