diff --git a/core/rexcode/isa/riscv/clobber_types.odin b/core/rexcode/isa/riscv/clobber_types.odin new file mode 100644 index 000000000..6d2b37bbd --- /dev/null +++ b/core/rexcode/isa/riscv/clobber_types.odin @@ -0,0 +1,47 @@ +package rexcode_riscv + +// Operand slots (indices into the Encoding operand list) that are read/written. +// Max 4 operands (R4-type FMA: rd, rs1, rs2, rs3). +Operand_Set :: distinct bit_set[0..<4; u8] + +FFlags :: distinct bit_set[FFlag; u8] +// fcsr accrued exception flags. This is the ONLY flag state in RISC-V — there +// are no integer condition codes, so there is no EFLAGS-style triad here. +FFlag :: enum u8 { + NV, // invalid operation + DZ, // divide by zero + OF, // overflow + UF, // underflow + NX, // inexact +} + +Clobber_Regs :: distinct bit_set[Clobber_Reg; u8] +// Implicitly-touched registers that are NOT distinct operands. RISC-V's base +// ISA has almost none of these (unlike x86's RAX/RDX/RSP-heavy encodings) — +// only the compressed link/stack forms. +Clobber_Reg :: enum u8 { + RA, // x1, implicit link on C.JAL / C.JALR + SP, // x2, implicit base on the *SP compressed forms +} + +Side_Effects :: distinct bit_set[Side_Effect; u8] +Side_Effect :: enum u8 { + CONTROL, // writes pc: branches, jumps, and trap redirects + TRAP, // synchronous environment trap (ECALL / EBREAK) + FENCE, // explicit memory-ordering barrier (FENCE) + IFENCE, // instruction-fetch synchronization (FENCE.I) + ATOMIC, // indivisible memory RMW (AMO*, and the LR/SC pair) + RESERVATION, // sets or tests an LR/SC reservation +} + +Clobber :: struct { + written: Operand_Set, // operand slots whose register/CSR is written + read: Operand_Set, // operand slots whose register/CSR/mem-base is read + implicit_wr: Clobber_Regs, // implicit reg writes (ra on C.JAL/C.JALR) + implicit_rd: Clobber_Regs, // implicit reg reads (sp on the *SP forms) + fflags_wr: FFlags, // accrued exception flags this op may raise + reads_frm: bool, // consumes the dynamic rounding mode from fcsr + writes_mem: bool, + reads_mem: bool, + side_effects: Side_Effects, +} \ No newline at end of file diff --git a/core/rexcode/isa/riscv/tablegen/encoding_table.odin b/core/rexcode/isa/riscv/tablegen/encoding_table.odin deleted file mode 100644 index 3aa4433d9..000000000 --- a/core/rexcode/isa/riscv/tablegen/encoding_table.odin +++ /dev/null @@ -1,432 +0,0 @@ -// rexcode · Brendan Punsky (dotbmp@github), original author - -package rexcode_riscv_tablegen - -// ============================================================================= -// RISC-V ENCODING_TABLE -// ============================================================================= -// -// (bits, mask) model -- same shape as MIPS. `bits` carries the static -// opcode/funct3/funct7 pattern; `mask` covers exactly the bits that are -// fixed. Operand-driven fields (rd, rs1, rs2, immediates, rounding mode, -// aq/rl) land in zero positions of `bits` and are ORed in by the encoder. -// -// Sections: -// §1 RV32I + RV64I base -// §2 Zicsr (CSR access) + Zifencei (FENCE.I) -// §3 M extension -// §4 A extension (atomics) -// §5 F extension (single-precision FP) -// §6 D extension (double-precision FP) -@(rodata) -ENCODING_TABLE:= #partial [Mnemonic][]Encoding{ - .INVALID = {}, - - // ========================================================================= - // §1 RV32I / RV64I base - // ========================================================================= - - // ---- Upper-immediate ---------------------------------------------------- - .LUI = { {.LUI, {.GPR,.IMM20,.NONE,.NONE}, {.RD,.IMM_U,.NONE,.NONE}, 0x00000037, MASK_U, .I, {}} }, - .AUIPC = { {.AUIPC, {.GPR,.IMM20,.NONE,.NONE}, {.RD,.IMM_U,.NONE,.NONE}, 0x00000017, MASK_U, .I, {}} }, - - // ---- Jumps -------------------------------------------------------------- - .JAL = { {.JAL, {.GPR,.REL21,.NONE,.NONE}, {.RD,.IMM_J,.NONE,.NONE}, 0x0000006F, MASK_J, .I, {branch=true}} }, - .JALR = { {.JALR, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00000067, MASK_OPCODE | MASK_FUNCT3, .I, {branch=true}} }, - - // ---- Branches (B-type) -------------------------------------------------- - .BEQ = { {.BEQ, {.GPR,.GPR,.REL13,.NONE}, {.RS1,.RS2,.IMM_B,.NONE}, 0x00000063, MASK_B, .I, {branch=true}} }, - .BNE = { {.BNE, {.GPR,.GPR,.REL13,.NONE}, {.RS1,.RS2,.IMM_B,.NONE}, 0x00001063, MASK_B, .I, {branch=true}} }, - .BLT = { {.BLT, {.GPR,.GPR,.REL13,.NONE}, {.RS1,.RS2,.IMM_B,.NONE}, 0x00004063, MASK_B, .I, {branch=true}} }, - .BGE = { {.BGE, {.GPR,.GPR,.REL13,.NONE}, {.RS1,.RS2,.IMM_B,.NONE}, 0x00005063, MASK_B, .I, {branch=true}} }, - .BLTU = { {.BLTU, {.GPR,.GPR,.REL13,.NONE}, {.RS1,.RS2,.IMM_B,.NONE}, 0x00006063, MASK_B, .I, {branch=true}} }, - .BGEU = { {.BGEU, {.GPR,.GPR,.REL13,.NONE}, {.RS1,.RS2,.IMM_B,.NONE}, 0x00007063, MASK_B, .I, {branch=true}} }, - - // ---- Loads (I-type) ----------------------------------------------------- - .LB = { {.LB, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00000003, MASK_I, .I, {}} }, - .LH = { {.LH, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00001003, MASK_I, .I, {}} }, - .LW = { {.LW, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00002003, MASK_I, .I, {}} }, - .LBU = { {.LBU, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00004003, MASK_I, .I, {}} }, - .LHU = { {.LHU, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00005003, MASK_I, .I, {}} }, - .LWU = { {.LWU, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00006003, MASK_I, .I, {rv64_only=true}} }, - .LD = { {.LD, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00003003, MASK_I, .I, {rv64_only=true}} }, - - // ---- Stores (S-type) ---------------------------------------------------- - .SB = { {.SB, {.GPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00000023, MASK_S, .I, {}} }, - .SH = { {.SH, {.GPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00001023, MASK_S, .I, {}} }, - .SW = { {.SW, {.GPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00002023, MASK_S, .I, {}} }, - .SD = { {.SD, {.GPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00003023, MASK_S, .I, {rv64_only=true}} }, - - // ---- Integer reg-imm (I-type ALU) --------------------------------------- - .ADDI = { {.ADDI, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00000013, MASK_I, .I, {}} }, - .SLTI = { {.SLTI, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00002013, MASK_I, .I, {}} }, - .SLTIU = { {.SLTIU, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00003013, MASK_I, .I, {}} }, - .XORI = { {.XORI, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00004013, MASK_I, .I, {}} }, - .ORI = { {.ORI, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00006013, MASK_I, .I, {}} }, - .ANDI = { {.ANDI, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00007013, MASK_I, .I, {}} }, - - // I-type shifts. RV32 uses 5-bit shamt + funct7; RV64 widens to 6-bit - // shamt + funct6. We list the RV64-compatible mask (funct6 fixed, - // shamt[5] operand-driven); on RV32 the user must keep shamt < 32. - .SLLI = { {.SLLI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x00001013, MASK_OPCODE | MASK_FUNCT3 | 0xFC000000, .I, {}} }, - .SRLI = { {.SRLI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x00005013, MASK_OPCODE | MASK_FUNCT3 | 0xFC000000, .I, {}} }, - .SRAI = { {.SRAI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x40005013, MASK_OPCODE | MASK_FUNCT3 | 0xFC000000, .I, {}} }, - - // RV64 OP-IMM-32 (operates on low 32 bits, sign-extends result) - .ADDIW = { {.ADDIW, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x0000001B, MASK_I, .I, {rv64_only=true}} }, - .SLLIW = { {.SLLIW, {.GPR,.GPR,.IMM5,.NONE}, {.RD,.RS1,.SHAMT5,.NONE}, 0x0000101B, MASK_R, .I, {rv64_only=true}} }, - .SRLIW = { {.SRLIW, {.GPR,.GPR,.IMM5,.NONE}, {.RD,.RS1,.SHAMT5,.NONE}, 0x0000501B, MASK_R, .I, {rv64_only=true}} }, - .SRAIW = { {.SRAIW, {.GPR,.GPR,.IMM5,.NONE}, {.RD,.RS1,.SHAMT5,.NONE}, 0x4000501B, MASK_R, .I, {rv64_only=true}} }, - - // ---- Integer reg-reg (R-type) ------------------------------------------- - .ADD = { {.ADD, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00000033, MASK_R, .I, {}} }, - .SUB = { {.SUB, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x40000033, MASK_R, .I, {}} }, - .SLL = { {.SLL, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00001033, MASK_R, .I, {}} }, - .SLT = { {.SLT, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00002033, MASK_R, .I, {}} }, - .SLTU = { {.SLTU, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00003033, MASK_R, .I, {}} }, - .XOR = { {.XOR, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00004033, MASK_R, .I, {}} }, - .SRL = { {.SRL, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00005033, MASK_R, .I, {}} }, - .SRA = { {.SRA, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x40005033, MASK_R, .I, {}} }, - .OR = { {.OR, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00006033, MASK_R, .I, {}} }, - .AND = { {.AND, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00007033, MASK_R, .I, {}} }, - - // RV64 OP-32 - .ADDW = { {.ADDW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0000003B, MASK_R, .I, {rv64_only=true}} }, - .SUBW = { {.SUBW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x4000003B, MASK_R, .I, {rv64_only=true}} }, - .SLLW = { {.SLLW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0000103B, MASK_R, .I, {rv64_only=true}} }, - .SRLW = { {.SRLW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0000503B, MASK_R, .I, {rv64_only=true}} }, - .SRAW = { {.SRAW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x4000503B, MASK_R, .I, {rv64_only=true}} }, - - // ---- Memory ordering ---------------------------------------------------- - // FENCE encodes pred/succ in bits 27-24 / 23-20. The opcode reserves - // these as operand-driven; mask covers opcode + funct3. - .FENCE = { {.FENCE, {.FENCE_FLAGS,.FENCE_FLAGS,.NONE,.NONE}, {.FENCE_PRED,.FENCE_SUCC,.NONE,.NONE}, 0x0000000F, MASK_I, .I, {}} }, - .FENCE_I = { {.FENCE_I, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x0000100F, 0xFFFFFFFF, .ZIFENCEI, {}} }, - - // ---- System ------------------------------------------------------------- - .ECALL = { {.ECALL, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x00000073, 0xFFFFFFFF, .I, {branch=true}} }, - .EBREAK = { {.EBREAK, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x00100073, 0xFFFFFFFF, .I, {branch=true}} }, - - // ========================================================================= - // §2 Zicsr (CSR access) - // ========================================================================= - // CSRRW rd, csr, rs1 - // CSRRWI rd, csr, zimm5 (zimm5 lives in the RS1 field) - - .CSRRW = { {.CSRRW, {.GPR,.CSR,.GPR,.NONE}, {.RD,.CSR_FIELD,.RS1,.NONE}, 0x00001073, MASK_I, .ZICSR, {}} }, - .CSRRS = { {.CSRRS, {.GPR,.CSR,.GPR,.NONE}, {.RD,.CSR_FIELD,.RS1,.NONE}, 0x00002073, MASK_I, .ZICSR, {}} }, - .CSRRC = { {.CSRRC, {.GPR,.CSR,.GPR,.NONE}, {.RD,.CSR_FIELD,.RS1,.NONE}, 0x00003073, MASK_I, .ZICSR, {}} }, - .CSRRWI = { {.CSRRWI, {.GPR,.CSR,.ZIMM5,.NONE}, {.RD,.CSR_FIELD,.ZIMM_FIELD,.NONE}, 0x00005073, MASK_I, .ZICSR, {}} }, - .CSRRSI = { {.CSRRSI, {.GPR,.CSR,.ZIMM5,.NONE}, {.RD,.CSR_FIELD,.ZIMM_FIELD,.NONE}, 0x00006073, MASK_I, .ZICSR, {}} }, - .CSRRCI = { {.CSRRCI, {.GPR,.CSR,.ZIMM5,.NONE}, {.RD,.CSR_FIELD,.ZIMM_FIELD,.NONE}, 0x00007073, MASK_I, .ZICSR, {}} }, - - // ========================================================================= - // §3 M extension (RV32M / RV64M) - // ========================================================================= - // All share opcode 0x33 and funct7 = 0x01. - - .MUL = { {.MUL, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02000033, MASK_R, .M, {}} }, - .MULH = { {.MULH, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02001033, MASK_R, .M, {}} }, - .MULHSU = { {.MULHSU, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02002033, MASK_R, .M, {}} }, - .MULHU = { {.MULHU, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02003033, MASK_R, .M, {}} }, - .DIV = { {.DIV, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02004033, MASK_R, .M, {}} }, - .DIVU = { {.DIVU, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02005033, MASK_R, .M, {}} }, - .REM = { {.REM, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02006033, MASK_R, .M, {}} }, - .REMU = { {.REMU, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02007033, MASK_R, .M, {}} }, - - // RV64 M-32 variants (opcode 0x3B) - .MULW = { {.MULW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0200003B, MASK_R, .M, {rv64_only=true}} }, - .DIVW = { {.DIVW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0200403B, MASK_R, .M, {rv64_only=true}} }, - .DIVUW = { {.DIVUW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0200503B, MASK_R, .M, {rv64_only=true}} }, - .REMW = { {.REMW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0200603B, MASK_R, .M, {rv64_only=true}} }, - .REMUW = { {.REMUW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0200703B, MASK_R, .M, {rv64_only=true}} }, - - // ========================================================================= - // §4 A extension (atomics) - // ========================================================================= - // opcode 0x2F; funct3 = 2 for .W and 3 for .D; funct5 (bits 31-27) - // picks the op; bits 26-25 are aq/rl (operand). Mask = opcode + - // funct3 + funct5 = 0xF800707F. - // - // LR.W/LR.D take only one register addr (rd, rs1); rs2 must be 0 - // and is part of the static mask. - // - // The address operand uses OFFSET_BASE_A (rs1 only; disp must be 0). - - .LR_W = { {.LR_W, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_A,.NONE,.NONE}, 0x1000202F, 0xF9F0707F, .A, {}} }, - .SC_W = { {.SC_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x1800202F, 0xF800707F, .A, {}} }, - .AMOSWAP_W = { {.AMOSWAP_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x0800202F, 0xF800707F, .A, {}} }, - .AMOADD_W = { {.AMOADD_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x0000202F, 0xF800707F, .A, {}} }, - .AMOXOR_W = { {.AMOXOR_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x2000202F, 0xF800707F, .A, {}} }, - .AMOAND_W = { {.AMOAND_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x6000202F, 0xF800707F, .A, {}} }, - .AMOOR_W = { {.AMOOR_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x4000202F, 0xF800707F, .A, {}} }, - .AMOMIN_W = { {.AMOMIN_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x8000202F, 0xF800707F, .A, {}} }, - .AMOMAX_W = { {.AMOMAX_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0xA000202F, 0xF800707F, .A, {}} }, - .AMOMINU_W = { {.AMOMINU_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0xC000202F, 0xF800707F, .A, {}} }, - .AMOMAXU_W = { {.AMOMAXU_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0xE000202F, 0xF800707F, .A, {}} }, - - .LR_D = { {.LR_D, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_A,.NONE,.NONE}, 0x1000302F, 0xF9F0707F, .A, {rv64_only=true}} }, - .SC_D = { {.SC_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x1800302F, 0xF800707F, .A, {rv64_only=true}} }, - .AMOSWAP_D = { {.AMOSWAP_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x0800302F, 0xF800707F, .A, {rv64_only=true}} }, - .AMOADD_D = { {.AMOADD_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x0000302F, 0xF800707F, .A, {rv64_only=true}} }, - .AMOXOR_D = { {.AMOXOR_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x2000302F, 0xF800707F, .A, {rv64_only=true}} }, - .AMOAND_D = { {.AMOAND_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x6000302F, 0xF800707F, .A, {rv64_only=true}} }, - .AMOOR_D = { {.AMOOR_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x4000302F, 0xF800707F, .A, {rv64_only=true}} }, - .AMOMIN_D = { {.AMOMIN_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x8000302F, 0xF800707F, .A, {rv64_only=true}} }, - .AMOMAX_D = { {.AMOMAX_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0xA000302F, 0xF800707F, .A, {rv64_only=true}} }, - .AMOMINU_D = { {.AMOMINU_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0xC000302F, 0xF800707F, .A, {rv64_only=true}} }, - .AMOMAXU_D = { {.AMOMAXU_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0xE000302F, 0xF800707F, .A, {rv64_only=true}} }, - - // ========================================================================= - // §5 F extension (single-precision) - // ========================================================================= - // - // OP-FP opcode = 0x53. funct7 selects op family. funct3 is normally the - // FP rounding mode (operand-driven, fp_round flag) but is fixed for a - // few ops (FMV/FCLASS/FEQ/FLT/FLE/FSGNJ*). - // - // Masks include opcode + funct7 always. funct3 is included only when - // it's a fixed selector rather than a rounding mode. rs2 is included - // when it's a fixed selector (FCVT/FMV/FCLASS/FSQRT). - // - // MASK macros used below: - // M_OP_F7 :: opcode + funct7 - // M_OP_F7_RS2 :: + rs2 - // M_OP_F7_F3 :: + funct3 - // M_OP_F7_F3_RS2 :: + both - - .FLW = { {.FLW, {.FPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00002007, MASK_I, .F, {}} }, - .FSW = { {.FSW, {.FPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00002027, MASK_S, .F, {}} }, - - // R4-type FMA: opcode + fmt (bits 26-25); fmt=00 for .S - .FMADD_S = { {.FMADD_S, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x00000043, 0x0600007F, .F, {fp_round=true}} }, - .FMSUB_S = { {.FMSUB_S, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x00000047, 0x0600007F, .F, {fp_round=true}} }, - .FNMSUB_S = { {.FNMSUB_S, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x0000004B, 0x0600007F, .F, {fp_round=true}} }, - .FNMADD_S = { {.FNMADD_S, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x0000004F, 0x0600007F, .F, {fp_round=true}} }, - - // R-type with rm - .FADD_S = { {.FADD_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00000053, MASK_OPCODE | MASK_FUNCT7, .F, {fp_round=true}} }, - .FSUB_S = { {.FSUB_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x08000053, MASK_OPCODE | MASK_FUNCT7, .F, {fp_round=true}} }, - .FMUL_S = { {.FMUL_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x10000053, MASK_OPCODE | MASK_FUNCT7, .F, {fp_round=true}} }, - .FDIV_S = { {.FDIV_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x18000053, MASK_OPCODE | MASK_FUNCT7, .F, {fp_round=true}} }, - .FSQRT_S = { {.FSQRT_S, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x58000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true}} }, - - // FSGNJ family: funct7 fixed (0x10), funct3 selects sub-op (no rm) - .FSGNJ_S = { {.FSGNJ_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x20000053, MASK_R, .F, {}} }, - .FSGNJN_S = { {.FSGNJN_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x20001053, MASK_R, .F, {}} }, - .FSGNJX_S = { {.FSGNJX_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x20002053, MASK_R, .F, {}} }, - - // FMIN/FMAX: funct7=0x14, funct3 selects min(0)/max(1) - .FMIN_S = { {.FMIN_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x28000053, MASK_R, .F, {}} }, - .FMAX_S = { {.FMAX_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x28001053, MASK_R, .F, {}} }, - - // FP -> int convert: rs2 is the type selector - .FCVT_W_S = { {.FCVT_W_S, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC0000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true}} }, - .FCVT_WU_S = { {.FCVT_WU_S, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC0100053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true}} }, - .FCVT_L_S = { {.FCVT_L_S, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC0200053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true, rv64_only=true}} }, - .FCVT_LU_S = { {.FCVT_LU_S, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC0300053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true, rv64_only=true}} }, - - // FP <- int convert - .FCVT_S_W = { {.FCVT_S_W, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD0000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true}} }, - .FCVT_S_WU = { {.FCVT_S_WU, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD0100053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true}} }, - .FCVT_S_L = { {.FCVT_S_L, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD0200053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true, rv64_only=true}} }, - .FCVT_S_LU = { {.FCVT_S_LU, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD0300053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true, rv64_only=true}} }, - - // FMV / FCLASS: funct3 fixed (000 for FMV, 001 for FCLASS), rs2=0 - .FMV_X_W = { {.FMV_X_W, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xE0000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2 | MASK_FUNCT3, .F, {}} }, - .FMV_W_X = { {.FMV_W_X, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xF0000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2 | MASK_FUNCT3, .F, {}} }, - .FCLASS_S = { {.FCLASS_S, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xE0001053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2 | MASK_FUNCT3, .F, {}} }, - - // FP compare: funct7=0x50, funct3 selects EQ(2)/LT(1)/LE(0) - .FEQ_S = { {.FEQ_S, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA0002053, MASK_R, .F, {}} }, - .FLT_S = { {.FLT_S, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA0001053, MASK_R, .F, {}} }, - .FLE_S = { {.FLE_S, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA0000053, MASK_R, .F, {}} }, - - // ========================================================================= - // §6 D extension (double-precision) - // ========================================================================= - // - // Same pattern as F but funct7 low bit = 1 (fmt=01 = D). - - .FLD = { {.FLD, {.FPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00003007, MASK_I, .D, {}} }, - .FSD = { {.FSD, {.FPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00003027, MASK_S, .D, {}} }, - - .FMADD_D = { {.FMADD_D, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x02000043, 0x0600007F, .D, {fp_round=true}} }, - .FMSUB_D = { {.FMSUB_D, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x02000047, 0x0600007F, .D, {fp_round=true}} }, - .FNMSUB_D = { {.FNMSUB_D, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x0200004B, 0x0600007F, .D, {fp_round=true}} }, - .FNMADD_D = { {.FNMADD_D, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x0200004F, 0x0600007F, .D, {fp_round=true}} }, - - .FADD_D = { {.FADD_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02000053, MASK_OPCODE | MASK_FUNCT7, .D, {fp_round=true}} }, - .FSUB_D = { {.FSUB_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A000053, MASK_OPCODE | MASK_FUNCT7, .D, {fp_round=true}} }, - .FMUL_D = { {.FMUL_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x12000053, MASK_OPCODE | MASK_FUNCT7, .D, {fp_round=true}} }, - .FDIV_D = { {.FDIV_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x1A000053, MASK_OPCODE | MASK_FUNCT7, .D, {fp_round=true}} }, - .FSQRT_D = { {.FSQRT_D, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x5A000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true}} }, - - .FSGNJ_D = { {.FSGNJ_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x22000053, MASK_R, .D, {}} }, - .FSGNJN_D = { {.FSGNJN_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x22001053, MASK_R, .D, {}} }, - .FSGNJX_D = { {.FSGNJX_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x22002053, MASK_R, .D, {}} }, - - .FMIN_D = { {.FMIN_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x2A000053, MASK_R, .D, {}} }, - .FMAX_D = { {.FMAX_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x2A001053, MASK_R, .D, {}} }, - - // FCVT between S and D - .FCVT_S_D = { {.FCVT_S_D, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x40100053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true}} }, - .FCVT_D_S = { {.FCVT_D_S, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x42000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true}} }, - - // FP -> int (double-source) - .FCVT_W_D = { {.FCVT_W_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC2000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true}} }, - .FCVT_WU_D = { {.FCVT_WU_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC2100053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true}} }, - .FCVT_L_D = { {.FCVT_L_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC2200053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true, rv64_only=true}} }, - .FCVT_LU_D = { {.FCVT_LU_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC2300053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true, rv64_only=true}} }, - - // FP <- int - .FCVT_D_W = { {.FCVT_D_W, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD2000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true}} }, - .FCVT_D_WU = { {.FCVT_D_WU, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD2100053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true}} }, - .FCVT_D_L = { {.FCVT_D_L, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD2200053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true, rv64_only=true}} }, - .FCVT_D_LU = { {.FCVT_D_LU, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD2300053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true, rv64_only=true}} }, - - // FMV / FCLASS double - .FMV_X_D = { {.FMV_X_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xE2000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2 | MASK_FUNCT3, .D, {rv64_only=true}} }, - .FMV_D_X = { {.FMV_D_X, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xF2000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2 | MASK_FUNCT3, .D, {rv64_only=true}} }, - .FCLASS_D = { {.FCLASS_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xE2001053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2 | MASK_FUNCT3, .D, {}} }, - - // FP compare double - .FEQ_D = { {.FEQ_D, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA2002053, MASK_R, .D, {}} }, - .FLT_D = { {.FLT_D, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA2001053, MASK_R, .D, {}} }, - .FLE_D = { {.FLE_D, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA2000053, MASK_R, .D, {}} }, - - // ========================================================================= - // C extension (16-bit compressed) - // ========================================================================= - // - // bits/mask use only the low 16 bits; the encoder writes 2 bytes for any - // form whose (bits & 3) != 3. The constant-bit pattern places the C - // dispatch fields (funct + op) in the low half-word. - - // ---- Quadrant 0 (op = 00) ---------------------------------------------- - - // C.ADDI4SPN rd', sp, imm = 000 imm[5:4] imm[9:6] imm[2] imm[3] rd' 00 - // funct3=000, op=00 -> static bits 0x0000, mask covers funct3+op only - // so the imm fields and rd' are operand-driven. - .C_ADDI4SPN = { {.C_ADDI4SPN, {.GPR_C, .GPR_SP, .IMM_C8U, .NONE}, {.C_RD_PRIMED, .NONE, .C_IMM_CIW, .NONE}, 0x0000, 0xE003, .C, {}} }, - - // C.FLD rd', imm(rs1') = 001 imm[5:3] rs1' imm[7:6] rd' 00 (D) - .C_FLD = { {.C_FLD, {.FPR_C, .MEM_C_D, .NONE, .NONE}, {.C_RD_PRIMED, .C_OFFSET_BASE_D, .NONE, .NONE}, 0x2000, 0xE003, .D, {}} }, - - // C.LW rd', imm(rs1') = 010 imm[5:3] rs1' imm[2,6] rd' 00 - .C_LW = { {.C_LW, {.GPR_C, .MEM_C_W, .NONE, .NONE}, {.C_RD_PRIMED, .C_OFFSET_BASE_W, .NONE, .NONE}, 0x4000, 0xE003, .C, {}} }, - - // C.LD rd', imm(rs1') = 011 imm[5:3] rs1' imm[7:6] rd' 00 (RV64-only) - .C_LD = { {.C_LD, {.GPR_C, .MEM_C_D, .NONE, .NONE}, {.C_RD_PRIMED, .C_OFFSET_BASE_D, .NONE, .NONE}, 0x6000, 0xE003, .C, {rv64_only=true}} }, - - // C.FSD rs2', imm(rs1') = 101 imm[5:3] rs1' imm[7:6] rs2' 00 - .C_FSD = { {.C_FSD, {.FPR_C, .MEM_C_D, .NONE, .NONE}, {.C_RS2_PRIMED, .C_OFFSET_BASE_D, .NONE, .NONE}, 0xA000, 0xE003, .D, {}} }, - - // C.SW rs2', imm(rs1') = 110 imm[5:3] rs1' imm[2,6] rs2' 00 - .C_SW = { {.C_SW, {.GPR_C, .MEM_C_W, .NONE, .NONE}, {.C_RS2_PRIMED, .C_OFFSET_BASE_W, .NONE, .NONE}, 0xC000, 0xE003, .C, {}} }, - - // C.SD rs2', imm(rs1') = 111 imm[5:3] rs1' imm[7:6] rs2' 00 (RV64-only) - .C_SD = { {.C_SD, {.GPR_C, .MEM_C_D, .NONE, .NONE}, {.C_RS2_PRIMED, .C_OFFSET_BASE_D, .NONE, .NONE}, 0xE000, 0xE003, .C, {rv64_only=true}} }, - - // C.FLW rd', imm(rs1') = 011 imm[5:3] rs1' imm[2,6] rd' 00 (RV32-only) - .C_FLW = { {.C_FLW, {.FPR_C, .MEM_C_W, .NONE, .NONE}, {.C_RD_PRIMED, .C_OFFSET_BASE_W, .NONE, .NONE}, 0x6000, 0xE003, .F, {rv32_only=true}} }, - - // C.FSW rs2', imm(rs1') = 111 imm[5:3] rs1' imm[2,6] rs2' 00 (RV32-only) - .C_FSW = { {.C_FSW, {.FPR_C, .MEM_C_W, .NONE, .NONE}, {.C_RS2_PRIMED, .C_OFFSET_BASE_W, .NONE, .NONE}, 0xE000, 0xE003, .F, {rv32_only=true}} }, - - // ---- Quadrant 1 (op = 01) ---------------------------------------------- - - // C.NOP = 0x0001 = C.ADDI x0, 0 (fully fixed encoding). - .C_NOP = { {.C_NOP, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x0001, 0xFFFF, .C, {}} }, - - // C.ADDI rd, imm = 000 imm[5] rd!=0 imm[4:0] 01 - .C_ADDI = { {.C_ADDI, {.GPR_NONZERO, .IMM_C6S, .NONE, .NONE}, {.C_RD_RS1, .C_IMM_CI_S, .NONE, .NONE}, 0x0001, 0xE003, .C, {}} }, - - // C.JAL imm = 001 imm[11:1] 01 (RV32-only) - .C_JAL = { {.C_JAL, {.REL12, .NONE, .NONE, .NONE}, {.C_BRANCH12, .NONE, .NONE, .NONE}, 0x2001, 0xE003, .C, {rv32_only=true, branch=true}} }, - - // C.ADDIW rd, imm = 001 imm[5] rd!=0 imm[4:0] 01 (RV64-only) - .C_ADDIW = { {.C_ADDIW, {.GPR_NONZERO, .IMM_C6S, .NONE, .NONE}, {.C_RD_RS1, .C_IMM_CI_S, .NONE, .NONE}, 0x2001, 0xE003, .C, {rv64_only=true}} }, - - // C.LI rd, imm = 010 imm[5] rd!=0 imm[4:0] 01 - .C_LI = { {.C_LI, {.GPR_NONZERO, .IMM_C6S, .NONE, .NONE}, {.C_RD_RS1, .C_IMM_CI_S, .NONE, .NONE}, 0x4001, 0xE003, .C, {}} }, - - // C.ADDI16SP sp, imm = 011 imm[9] 00010 imm[4,6,8:7,5] 01 - // rd is fixed at 2 (sp); ensure the form discriminates by checking rd=2. - .C_ADDI16SP = { {.C_ADDI16SP, {.GPR_SP, .IMM_C10S, .NONE, .NONE}, {.NONE, .C_IMM_ADDI16SP, .NONE, .NONE}, 0x6101, 0xEF83, .C, {}} }, - - // C.LUI rd, imm = 011 imm[17] rd!=0,2 imm[16:12] 01 - .C_LUI = { {.C_LUI, {.GPR_NONZERO, .IMM_C18S, .NONE, .NONE}, {.C_RD_RS1, .C_IMM_LUI, .NONE, .NONE}, 0x6001, 0xE003, .C, {}} }, - - // C.SRLI rd', shamt = 100 shamt[5] 00 rd' shamt[4:0] 01 - .C_SRLI = { {.C_SRLI, {.GPR_C, .IMM_C6U, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_IMM_CI_U, .NONE, .NONE}, 0x8001, 0xEC03, .C, {}} }, - - // C.SRAI rd', shamt = 100 shamt[5] 01 rd' shamt[4:0] 01 - .C_SRAI = { {.C_SRAI, {.GPR_C, .IMM_C6U, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_IMM_CI_U, .NONE, .NONE}, 0x8401, 0xEC03, .C, {}} }, - - // C.ANDI rd', imm = 100 imm[5] 10 rd' imm[4:0] 01 - .C_ANDI = { {.C_ANDI, {.GPR_C, .IMM_C6S, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_IMM_CI_S, .NONE, .NONE}, 0x8801, 0xEC03, .C, {}} }, - - // CA-format reg-reg (op=01, funct6=100011 / 100111 + funct2 picks op): - // C.SUB rd', rs2' = 100011 rd' 00 rs2' 01 - // C.XOR rd', rs2' = 100011 rd' 01 rs2' 01 - // C.OR rd', rs2' = 100011 rd' 10 rs2' 01 - // C.AND rd', rs2' = 100011 rd' 11 rs2' 01 - // C.SUBW rd', rs2' = 100111 rd' 00 rs2' 01 (RV64) - // C.ADDW rd', rs2' = 100111 rd' 01 rs2' 01 (RV64) - .C_SUB = { {.C_SUB, {.GPR_C, .GPR_C, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_RS2_PRIMED, .NONE, .NONE}, 0x8C01, 0xFC63, .C, {}} }, - .C_XOR = { {.C_XOR, {.GPR_C, .GPR_C, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_RS2_PRIMED, .NONE, .NONE}, 0x8C21, 0xFC63, .C, {}} }, - .C_OR = { {.C_OR, {.GPR_C, .GPR_C, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_RS2_PRIMED, .NONE, .NONE}, 0x8C41, 0xFC63, .C, {}} }, - .C_AND = { {.C_AND, {.GPR_C, .GPR_C, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_RS2_PRIMED, .NONE, .NONE}, 0x8C61, 0xFC63, .C, {}} }, - .C_SUBW = { {.C_SUBW, {.GPR_C, .GPR_C, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_RS2_PRIMED, .NONE, .NONE}, 0x9C01, 0xFC63, .C, {rv64_only=true}} }, - .C_ADDW = { {.C_ADDW, {.GPR_C, .GPR_C, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_RS2_PRIMED, .NONE, .NONE}, 0x9C21, 0xFC63, .C, {rv64_only=true}} }, - - // C.J offset = 101 offset[11:1] 01 - .C_J = { {.C_J, {.REL12, .NONE, .NONE, .NONE}, {.C_BRANCH12, .NONE, .NONE, .NONE}, 0xA001, 0xE003, .C, {branch=true}} }, - - // C.BEQZ rs1', offset[8:1] = 110 offset[8,4:3] rs1' offset[7:6,2:1,5] 01 - .C_BEQZ = { {.C_BEQZ, {.GPR_C, .REL9, .NONE, .NONE}, {.C_RS1_PRIMED, .C_BRANCH9, .NONE, .NONE}, 0xC001, 0xE003, .C, {branch=true}} }, - // C.BNEZ rs1', offset[8:1] = 111 offset[8,4:3] rs1' offset[7:6,2:1,5] 01 - .C_BNEZ = { {.C_BNEZ, {.GPR_C, .REL9, .NONE, .NONE}, {.C_RS1_PRIMED, .C_BRANCH9, .NONE, .NONE}, 0xE001, 0xE003, .C, {branch=true}} }, - - // ---- Quadrant 2 (op = 10) ---------------------------------------------- - - // C.SLLI rd, shamt = 000 shamt[5] rd!=0 shamt[4:0] 10 - .C_SLLI = { {.C_SLLI, {.GPR_NONZERO, .IMM_C6U, .NONE, .NONE}, {.C_RD_RS1, .C_IMM_CI_U, .NONE, .NONE}, 0x0002, 0xE003, .C, {}} }, - - // C.FLDSP rd, imm = 001 imm[5] rd imm[4:3,8:6] 10 - .C_FLDSP = { {.C_FLDSP, {.FPR, .MEM_C_SP_D, .NONE, .NONE}, {.C_RD_RS1, .C_SP_OFFSET_D, .NONE, .NONE}, 0x2002, 0xE003, .D, {}} }, - - // C.LWSP rd, imm = 010 imm[5] rd!=0 imm[4:2,7:6] 10 - .C_LWSP = { {.C_LWSP, {.GPR_NONZERO, .MEM_C_SP_W, .NONE, .NONE}, {.C_RD_RS1, .C_SP_OFFSET_W, .NONE, .NONE}, 0x4002, 0xE003, .C, {}} }, - - // C.LDSP rd, imm = 011 imm[5] rd!=0 imm[4:3,8:6] 10 (RV64) - .C_LDSP = { {.C_LDSP, {.GPR_NONZERO, .MEM_C_SP_D, .NONE, .NONE}, {.C_RD_RS1, .C_SP_OFFSET_D, .NONE, .NONE}, 0x6002, 0xE003, .C, {rv64_only=true}} }, - - // CR-format funct4=1000 / 1001 with rd!=0: - // C.JR rs1 = 1000 rs1!=0 00000 10 (rs2=0) - // C.MV rd, rs2 = 1000 rd!=0 rs2!=0 10 - // C.EBREAK = 1001 00000 00000 10 (fully fixed 0x9002) - // C.JALR rs1 = 1001 rs1!=0 00000 10 (rs2=0) - // C.ADD rd, rs2 = 1001 rd!=0 rs2!=0 10 - .C_JR = { {.C_JR, {.GPR_NONZERO, .NONE, .NONE, .NONE}, {.C_RD_RS1, .NONE, .NONE, .NONE}, 0x8002, 0xF07F, .C, {branch=true}} }, - .C_MV = { {.C_MV, {.GPR_NONZERO, .GPR_NONZERO, .NONE, .NONE}, {.C_RD_RS1, .C_RS2, .NONE, .NONE}, 0x8002, 0xF003, .C, {}} }, - .C_EBREAK = { {.C_EBREAK, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x9002, 0xFFFF, .C, {}} }, - .C_JALR = { {.C_JALR, {.GPR_NONZERO, .NONE, .NONE, .NONE}, {.C_RD_RS1, .NONE, .NONE, .NONE}, 0x9002, 0xF07F, .C, {branch=true}} }, - .C_ADD = { {.C_ADD, {.GPR_NONZERO, .GPR_NONZERO, .NONE, .NONE}, {.C_RD_RS1, .C_RS2, .NONE, .NONE}, 0x9002, 0xF003, .C, {}} }, - - // C.FSDSP rs2, imm = 101 imm[5:3,8:6] rs2 10 - .C_FSDSP = { {.C_FSDSP, {.FPR, .MEM_C_SP_D, .NONE, .NONE}, {.C_RS2, .C_IMM_CSS_D, .NONE, .NONE}, 0xA002, 0xE003, .D, {}} }, - - // C.SWSP rs2, imm = 110 imm[5:2,7:6] rs2 10 - .C_SWSP = { {.C_SWSP, {.GPR, .MEM_C_SP_W, .NONE, .NONE}, {.C_RS2, .C_IMM_CSS_W, .NONE, .NONE}, 0xC002, 0xE003, .C, {}} }, - - // C.SDSP rs2, imm = 111 imm[5:3,8:6] rs2 10 (RV64) - .C_SDSP = { {.C_SDSP, {.GPR, .MEM_C_SP_D, .NONE, .NONE}, {.C_RS2, .C_IMM_CSS_D, .NONE, .NONE}, 0xE002, 0xE003, .C, {rv64_only=true}} }, - - // C.FLWSP rd, imm = 011 imm[5] rd imm[4:2,7:6] 10 (RV32-only) - .C_FLWSP = { {.C_FLWSP, {.FPR, .MEM_C_SP_W, .NONE, .NONE}, {.C_RD_RS1, .C_SP_OFFSET_W, .NONE, .NONE}, 0x6002, 0xE003, .F, {rv32_only=true}} }, - - // C.FSWSP rs2, imm = 111 imm[5:2,7:6] rs2 10 (RV32-only) - .C_FSWSP = { {.C_FSWSP, {.FPR, .MEM_C_SP_W, .NONE, .NONE}, {.C_RS2, .C_IMM_CSS_W, .NONE, .NONE}, 0xE002, 0xE003, .F, {rv32_only=true}} }, -} diff --git a/core/rexcode/isa/riscv/tablegen/gen.odin b/core/rexcode/isa/riscv/tablegen/gen.odin index 9d11056c5..8ad85fcef 100644 --- a/core/rexcode/isa/riscv/tablegen/gen.odin +++ b/core/rexcode/isa/riscv/tablegen/gen.odin @@ -34,6 +34,7 @@ import lib "../" // Package-scope aliases so the moved SoT resolves Mnemonic/Encoding unqualified. Encoding :: lib.Encoding Mnemonic :: lib.Mnemonic +Clobber :: lib.Clobber // The SoT's bit/mask literals reference these field-mask constants. MASK_OPCODE :: lib.MASK_OPCODE @@ -55,12 +56,13 @@ MASK_J :: lib.MASK_J Blob :: struct { global, file, typ: string } BLOBS := [?]Blob{ - {"ENCODE_FORMS", "riscv.encode_forms.bin", "Encoding"}, - {"ENCODE_RUNS", "riscv.encode_runs.bin", "Encode_Run"}, - {"DECODE_ENTRIES", "riscv.entries.bin", "Decode_Entry"}, - {"DECODE_INDEX_OPCODE", "riscv.idx_opcode.bin", "Decode_Index"}, - {"DECODE_INDEX_OP_FP", "riscv.idx_op_fp.bin", "Decode_Index"}, - {"DECODE_INDEX_RVC", "riscv.idx_rvc.bin", "Decode_Index"}, + {"ENCODE_FORMS", "riscv.encode_forms.bin", "Encoding"}, + {"ENCODE_RUNS", "riscv.encode_runs.bin", "Encode_Run"}, + {"DECODE_ENTRIES", "riscv.entries.bin", "Decode_Entry"}, + {"DECODE_INDEX_OPCODE", "riscv.idx_opcode.bin", "Decode_Index"}, + {"DECODE_INDEX_OP_FP", "riscv.idx_op_fp.bin", "Decode_Index"}, + {"DECODE_INDEX_RVC", "riscv.idx_rvc.bin", "Decode_Index"}, + {"CLOBBER_FORMS", "riscv.clobber_forms.bin", "Clobber"}, } DIR_GEN :: #directory + "/generated/" @@ -98,30 +100,43 @@ emit_encode_tables :: proc() -> (total: int) { sb := strings.builder_make() strings.write_string(&sb, "package rexcode_riscv_generated\n\n") strings.write_string(&sb, "// GENERATED by ../gen.odin -- DO NOT EDIT.\n") - strings.write_string(&sb, "// Flattened encode forms + per-mnemonic run index (source: ENCODING_TABLE).\n\n") + strings.write_string(&sb, "// Flattened encode forms + per-mnemonic run index (source: INSTRUCTION_TABLE).\n\n") strings.write_string(&sb, "import lib \"../..\"\n\n") - for m in Mnemonic { total += len(ENCODING_TABLE[m]) } + for m in Mnemonic { total += len(INSTRUCTION_TABLE[m]) } strings.write_string(&sb, "@(rodata)\n") fmt.sbprintfln(&sb, "ENCODE_FORMS := [%d]lib.Encoding{{", total) for m in Mnemonic { - forms := ENCODING_TABLE[m] + forms := INSTRUCTION_TABLE[m] if len(forms) == 0 { continue } fmt.sbprintfln(&sb, "\t// .%v", m) - for f in forms { + for &form in forms { + f := &form.encoding write_row(&sb, f.mnemonic, f.ops, f.enc, f.bits, f.mask, f.feature, f.flags) } } strings.write_string(&sb, "}\n\n") + strings.write_string(&sb, "@(rodata)\n") + fmt.sbprintfln(&sb, "CLOBBER_FORMS := [%d]lib.Clobber{{", total) + for m in Mnemonic { + forms := INSTRUCTION_TABLE[m] + if len(forms) == 0 { continue } + fmt.sbprintfln(&sb, "\t// .%v", m) + for &form in forms { + write_clobber_row(&sb, form.clobber) + } + } + strings.write_string(&sb, "}\n\n") + run_w := 0 for m in Mnemonic { run_w = max(run_w, len(reflect.enum_string(m))) } strings.write_string(&sb, "@(rodata)\n") strings.write_string(&sb, "ENCODE_RUNS := [lib.Mnemonic]lib.Encode_Run{\n") start := 0 for m in Mnemonic { - c := len(ENCODING_TABLE[m]) + c := len(INSTRUCTION_TABLE[m]) name := reflect.enum_string(m) fmt.sbprintf(&sb, "\t.%s", name) for _ in 0.. (total: int) { all: [dynamic]Entry defer delete(all) for m in Mnemonic { - for f in ENCODING_TABLE[m] { + for &form in INSTRUCTION_TABLE[m] { + f := &form.encoding e := Entry{ mnemonic = f.mnemonic, ops = f.ops, @@ -235,6 +251,64 @@ write_row :: proc(sb: ^strings.Builder, mn: lib.Mnemonic, ops: [4]lib.Operand_Ty mn, ops[0], ops[1], ops[2], ops[3], enc[0], enc[1], enc[2], enc[3], bits, mask, feature, flags_lit(flags)) } +write_clobber_row :: proc(sb: ^strings.Builder, c: lib.Clobber) { + write_set :: proc(sb: ^strings.Builder, name: string, set: $T) { + strings.write_string(sb, name) + strings.write_string(sb, "=") + strings.write_string(sb, "{") + i := 0 + for elem in set { + if i > 0 { strings.write_string(sb, ", ") } + strings.write_string(sb, ".") + fmt.sbprintf(sb, "%s", elem) + i += 1 + } + strings.write_string(sb, "}") + } + + strings.write_string(sb, "\t{") + defer strings.write_string(sb, "},\n") + i := -1 + if c.written != nil { + if i += 1; i > 0 { strings.write_string(sb, ", ") } + strings.write_string(sb, "written=") + fmt.sbprintf(sb, "%w", c.written) + } + if c.read != nil { + if i += 1; i > 0 { strings.write_string(sb, ", ") } + strings.write_string(sb, "read=") + fmt.sbprintf(sb, "%w", c.read) + } + if c.implicit_wr != nil { + if i += 1; i > 0 { strings.write_string(sb, ", ") } + write_set(sb, "implicit_wr", c.implicit_wr) + } + if c.implicit_rd != nil { + if i += 1; i > 0 { strings.write_string(sb, ", ") } + write_set(sb, "implicit_rd", c.implicit_rd) + } + if c.fflags_wr != nil { + if i += 1; i > 0 { strings.write_string(sb, ", ") } + write_set(sb, "fflags_wr", c.fflags_wr) + } + if c.reads_frm { + if i += 1; i > 0 { strings.write_string(sb, ", ") } + fmt.sbprintf(sb, "reads_frm=true") + } + if c.writes_mem { + if i += 1; i > 0 { strings.write_string(sb, ", ") } + fmt.sbprintf(sb, "writes_mem=true") + } + if c.reads_mem { + if i += 1; i > 0 { strings.write_string(sb, ", ") } + fmt.sbprintf(sb, "reads_mem=true") + } + if c.side_effects != nil { + if i += 1; i > 0 { strings.write_string(sb, ", ") } + write_set(sb, "side_effects", c.side_effects) + } +} + flags_lit :: proc(f: lib.Encoding_Flags) -> string { parts: [dynamic]string defer delete(parts) @@ -268,7 +342,8 @@ emit_writer :: proc() { emit_file(DIR_GEN + "writer.odin", &sb) } -LOADER_TYPES :: `// ----------------------------------------------------------------------------- +LOADER_TYPES :: ``` +// ----------------------------------------------------------------------------- // Subsidiary table types (generated scaffolding) // ----------------------------------------------------------------------------- @@ -294,9 +369,10 @@ Decode_Index :: struct #packed { count: u16, } #assert(size_of(Decode_Index) == 4) -` +``` -LOADER_ACCESSORS :: `// ----------------------------------------------------------------------------- +LOADER_ACCESSORS :: ``` +// ----------------------------------------------------------------------------- // Accessors // ----------------------------------------------------------------------------- @@ -307,7 +383,15 @@ encoding_forms :: #force_inline proc "contextless" (m: Mnemonic) -> []Encoding { r := ENCODE_RUNS[u16(m)] return ENCODE_FORMS[r.start:][:r.count] } -` + +// Per-mnemonic clobber forms: the run of CLOBBER_FORMS belonging to ` + "`m`" + `. +// Replaces the old ENCODING_TABLE[m] slice; the returned view is into rodata. +@(private, require_results) +clobber_forms :: #force_inline proc "contextless" (m: Mnemonic) -> []Clobber { + r := ENCODE_RUNS[u16(m)] + return CLOBBER_FORMS[r.start:][:r.count] +} +``` emit_loader :: proc() { sb := strings.builder_make() diff --git a/core/rexcode/isa/riscv/tablegen/generated/encode_tables.odin b/core/rexcode/isa/riscv/tablegen/generated/encode_tables.odin index 9d8328206..4bed4668a 100644 --- a/core/rexcode/isa/riscv/tablegen/generated/encode_tables.odin +++ b/core/rexcode/isa/riscv/tablegen/generated/encode_tables.odin @@ -3,7 +3,7 @@ package rexcode_riscv_generated // GENERATED by ../gen.odin -- DO NOT EDIT. -// Flattened encode forms + per-mnemonic run index (source: ENCODING_TABLE). +// Flattened encode forms + per-mnemonic run index (source: INSTRUCTION_TABLE). import lib "../.." @@ -407,6 +407,406 @@ ENCODE_FORMS := [198]lib.Encoding{ { .C_FSWSP, {.FPR,.MEM_C_SP_W,.NONE,.NONE}, {.C_RS2,.C_IMM_CSS_W,.NONE,.NONE}, 0x0000E002, 0x0000E003, .F, {rv32_only=true} }, } +@(rodata) +CLOBBER_FORMS := [198]lib.Clobber{ + // .LUI + {written={0}}, + // .AUIPC + {written={0}}, + // .JAL + {written={0}, side_effects={.CONTROL}}, + // .JALR + {written={0}, read={1}, side_effects={.CONTROL}}, + // .BEQ + {read={0, 1}, side_effects={.CONTROL}}, + // .BNE + {read={0, 1}, side_effects={.CONTROL}}, + // .BLT + {read={0, 1}, side_effects={.CONTROL}}, + // .BGE + {read={0, 1}, side_effects={.CONTROL}}, + // .BLTU + {read={0, 1}, side_effects={.CONTROL}}, + // .BGEU + {read={0, 1}, side_effects={.CONTROL}}, + // .LB + {written={0}, read={1}, reads_mem=true}, + // .LH + {written={0}, read={1}, reads_mem=true}, + // .LW + {written={0}, read={1}, reads_mem=true}, + // .LBU + {written={0}, read={1}, reads_mem=true}, + // .LHU + {written={0}, read={1}, reads_mem=true}, + // .SB + {read={0, 1}, writes_mem=true}, + // .SH + {read={0, 1}, writes_mem=true}, + // .SW + {read={0, 1}, writes_mem=true}, + // .LWU + {written={0}, read={1}, reads_mem=true}, + // .LD + {written={0}, read={1}, reads_mem=true}, + // .SD + {read={0, 1}, writes_mem=true}, + // .ADDI + {written={0}, read={1}}, + // .SLTI + {written={0}, read={1}}, + // .SLTIU + {written={0}, read={1}}, + // .XORI + {written={0}, read={1}}, + // .ORI + {written={0}, read={1}}, + // .ANDI + {written={0}, read={1}}, + // .SLLI + {written={0}, read={1}}, + // .SRLI + {written={0}, read={1}}, + // .SRAI + {written={0}, read={1}}, + // .ADDIW + {written={0}, read={1}}, + // .SLLIW + {written={0}, read={1}}, + // .SRLIW + {written={0}, read={1}}, + // .SRAIW + {written={0}, read={1}}, + // .ADD + {written={0}, read={1, 2}}, + // .SUB + {written={0}, read={1, 2}}, + // .SLL + {written={0}, read={1, 2}}, + // .SLT + {written={0}, read={1, 2}}, + // .SLTU + {written={0}, read={1, 2}}, + // .XOR + {written={0}, read={1, 2}}, + // .SRL + {written={0}, read={1, 2}}, + // .SRA + {written={0}, read={1, 2}}, + // .OR + {written={0}, read={1, 2}}, + // .AND + {written={0}, read={1, 2}}, + // .ADDW + {written={0}, read={1, 2}}, + // .SUBW + {written={0}, read={1, 2}}, + // .SLLW + {written={0}, read={1, 2}}, + // .SRLW + {written={0}, read={1, 2}}, + // .SRAW + {written={0}, read={1, 2}}, + // .FENCE + {side_effects={.FENCE}}, + // .FENCE_I + {side_effects={.IFENCE}}, + // .ECALL + {side_effects={.CONTROL, .TRAP}}, + // .EBREAK + {side_effects={.CONTROL, .TRAP}}, + // .CSRRW + {written={0, 1}, read={1, 2}}, + // .CSRRS + {written={0, 1}, read={1, 2}}, + // .CSRRC + {written={0, 1}, read={1, 2}}, + // .CSRRWI + {written={0, 1}, read={1}}, + // .CSRRSI + {written={0, 1}, read={1}}, + // .CSRRCI + {written={0, 1}, read={1}}, + // .MUL + {written={0}, read={1, 2}}, + // .MULH + {written={0}, read={1, 2}}, + // .MULHSU + {written={0}, read={1, 2}}, + // .MULHU + {written={0}, read={1, 2}}, + // .DIV + {written={0}, read={1, 2}}, + // .DIVU + {written={0}, read={1, 2}}, + // .REM + {written={0}, read={1, 2}}, + // .REMU + {written={0}, read={1, 2}}, + // .MULW + {written={0}, read={1, 2}}, + // .DIVW + {written={0}, read={1, 2}}, + // .DIVUW + {written={0}, read={1, 2}}, + // .REMW + {written={0}, read={1, 2}}, + // .REMUW + {written={0}, read={1, 2}}, + // .LR_W + {written={0}, read={1}, reads_mem=true, side_effects={.ATOMIC, .RESERVATION}}, + // .SC_W + {written={0}, read={1, 2}, writes_mem=true, side_effects={.ATOMIC, .RESERVATION}}, + // .AMOSWAP_W + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .AMOADD_W + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .AMOXOR_W + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .AMOAND_W + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .AMOOR_W + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .AMOMIN_W + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .AMOMAX_W + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .AMOMINU_W + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .AMOMAXU_W + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .LR_D + {written={0}, read={1}, reads_mem=true, side_effects={.ATOMIC, .RESERVATION}}, + // .SC_D + {written={0}, read={1, 2}, writes_mem=true, side_effects={.ATOMIC, .RESERVATION}}, + // .AMOSWAP_D + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .AMOADD_D + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .AMOXOR_D + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .AMOAND_D + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .AMOOR_D + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .AMOMIN_D + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .AMOMAX_D + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .AMOMINU_D + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .AMOMAXU_D + {written={0}, read={1, 2}, writes_mem=true, reads_mem=true, side_effects={.ATOMIC}}, + // .FLW + {written={0}, read={1}, reads_mem=true}, + // .FSW + {read={0, 1}, writes_mem=true}, + // .FMADD_S + {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}, + // .FMSUB_S + {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}, + // .FNMSUB_S + {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}, + // .FNMADD_S + {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}, + // .FADD_S + {written={0}, read={1, 2}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}, + // .FSUB_S + {written={0}, read={1, 2}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}, + // .FMUL_S + {written={0}, read={1, 2}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}, + // .FDIV_S + {written={0}, read={1, 2}, fflags_wr={.NV, .DZ, .OF, .UF, .NX}, reads_frm=true}, + // .FSQRT_S + {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}, + // .FSGNJ_S + {written={0}, read={1, 2}}, + // .FSGNJN_S + {written={0}, read={1, 2}}, + // .FSGNJX_S + {written={0}, read={1, 2}}, + // .FMIN_S + {written={0}, read={1, 2}, fflags_wr={.NV}}, + // .FMAX_S + {written={0}, read={1, 2}, fflags_wr={.NV}}, + // .FCVT_W_S + {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}, + // .FCVT_WU_S + {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}, + // .FMV_X_W + {written={0}, read={1}}, + // .FEQ_S + {written={0}, read={1, 2}, fflags_wr={.NV}}, + // .FLT_S + {written={0}, read={1, 2}, fflags_wr={.NV}}, + // .FLE_S + {written={0}, read={1, 2}, fflags_wr={.NV}}, + // .FCLASS_S + {written={0}, read={1}}, + // .FCVT_S_W + {written={0}, read={1}, fflags_wr={.NX}, reads_frm=true}, + // .FCVT_S_WU + {written={0}, read={1}, fflags_wr={.NX}, reads_frm=true}, + // .FMV_W_X + {written={0}, read={1}}, + // .FCVT_L_S + {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}, + // .FCVT_LU_S + {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}, + // .FCVT_S_L + {written={0}, read={1}, fflags_wr={.NX}, reads_frm=true}, + // .FCVT_S_LU + {written={0}, read={1}, fflags_wr={.NX}, reads_frm=true}, + // .FLD + {written={0}, read={1}, reads_mem=true}, + // .FSD + {read={0, 1}, writes_mem=true}, + // .FMADD_D + {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}, + // .FMSUB_D + {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}, + // .FNMSUB_D + {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}, + // .FNMADD_D + {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}, + // .FADD_D + {written={0}, read={1, 2}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}, + // .FSUB_D + {written={0}, read={1, 2}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}, + // .FMUL_D + {written={0}, read={1, 2}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}, + // .FDIV_D + {written={0}, read={1, 2}, fflags_wr={.NV, .DZ, .OF, .UF, .NX}, reads_frm=true}, + // .FSQRT_D + {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}, + // .FSGNJ_D + {written={0}, read={1, 2}}, + // .FSGNJN_D + {written={0}, read={1, 2}}, + // .FSGNJX_D + {written={0}, read={1, 2}}, + // .FMIN_D + {written={0}, read={1, 2}, fflags_wr={.NV}}, + // .FMAX_D + {written={0}, read={1, 2}, fflags_wr={.NV}}, + // .FCVT_S_D + {written={0}, read={1}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}, + // .FCVT_D_S + {written={0}, read={1}, fflags_wr={.NV}, reads_frm=true}, + // .FEQ_D + {written={0}, read={1, 2}, fflags_wr={.NV}}, + // .FLT_D + {written={0}, read={1, 2}, fflags_wr={.NV}}, + // .FLE_D + {written={0}, read={1, 2}, fflags_wr={.NV}}, + // .FCLASS_D + {written={0}, read={1}}, + // .FCVT_W_D + {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}, + // .FCVT_WU_D + {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}, + // .FCVT_D_W + {written={0}, read={1}, reads_frm=true}, + // .FCVT_D_WU + {written={0}, read={1}, reads_frm=true}, + // .FCVT_L_D + {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}, + // .FCVT_LU_D + {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}, + // .FCVT_D_L + {written={0}, read={1}, fflags_wr={.NX}, reads_frm=true}, + // .FCVT_D_LU + {written={0}, read={1}, fflags_wr={.NX}, reads_frm=true}, + // .FMV_X_D + {written={0}, read={1}}, + // .FMV_D_X + {written={0}, read={1}}, + // .C_NOP + {}, + // .C_EBREAK + {side_effects={.CONTROL, .TRAP}}, + // .C_ADDI4SPN + {written={0}, read={1}}, + // .C_LW + {written={0}, read={1}, reads_mem=true}, + // .C_LD + {written={0}, read={1}, reads_mem=true}, + // .C_SW + {read={0, 1}, writes_mem=true}, + // .C_SD + {read={0, 1}, writes_mem=true}, + // .C_FLW + {written={0}, read={1}, reads_mem=true}, + // .C_FSW + {read={0, 1}, writes_mem=true}, + // .C_FLD + {written={0}, read={1}, reads_mem=true}, + // .C_FSD + {read={0, 1}, writes_mem=true}, + // .C_ADDI + {written={0}, read={0}}, + // .C_ADDIW + {written={0}, read={0}}, + // .C_LI + {written={0}}, + // .C_LUI + {written={0}}, + // .C_ADDI16SP + {written={0}, read={0}}, + // .C_SRLI + {written={0}, read={0}}, + // .C_SRAI + {written={0}, read={0}}, + // .C_ANDI + {written={0}, read={0}}, + // .C_SUB + {written={0}, read={0, 1}}, + // .C_XOR + {written={0}, read={0, 1}}, + // .C_OR + {written={0}, read={0, 1}}, + // .C_AND + {written={0}, read={0, 1}}, + // .C_SUBW + {written={0}, read={0, 1}}, + // .C_ADDW + {written={0}, read={0, 1}}, + // .C_J + {side_effects={.CONTROL}}, + // .C_JAL + {implicit_wr={.RA}, side_effects={.CONTROL}}, + // .C_BEQZ + {read={0}, side_effects={.CONTROL}}, + // .C_BNEZ + {read={0}, side_effects={.CONTROL}}, + // .C_SLLI + {written={0}, read={0}}, + // .C_LWSP + {written={0}, implicit_rd={.SP}, reads_mem=true}, + // .C_LDSP + {written={0}, implicit_rd={.SP}, reads_mem=true}, + // .C_SWSP + {read={0}, implicit_rd={.SP}, writes_mem=true}, + // .C_SDSP + {read={0}, implicit_rd={.SP}, writes_mem=true}, + // .C_FLDSP + {written={0}, implicit_rd={.SP}, reads_mem=true}, + // .C_FSDSP + {read={0}, implicit_rd={.SP}, writes_mem=true}, + // .C_JR + {read={0}, side_effects={.CONTROL}}, + // .C_JALR + {read={0}, implicit_wr={.RA}, side_effects={.CONTROL}}, + // .C_MV + {written={0}, read={1}}, + // .C_ADD + {written={0}, read={0, 1}}, + // .C_FLWSP + {written={0}, implicit_rd={.SP}, reads_mem=true}, + // .C_FSWSP + {read={0}, implicit_rd={.SP}, writes_mem=true}, +} + @(rodata) ENCODE_RUNS := [lib.Mnemonic]lib.Encode_Run{ .INVALID = { 0, 0}, diff --git a/core/rexcode/isa/riscv/tablegen/generated/writer.odin b/core/rexcode/isa/riscv/tablegen/generated/writer.odin index 4997fdeb0..0d246c6cf 100644 --- a/core/rexcode/isa/riscv/tablegen/generated/writer.odin +++ b/core/rexcode/isa/riscv/tablegen/generated/writer.odin @@ -28,4 +28,5 @@ main :: proc() { w(TABLES + "riscv.idx_opcode.bin", raw(&DECODE_INDEX_OPCODE, size_of(DECODE_INDEX_OPCODE))) w(TABLES + "riscv.idx_op_fp.bin", raw(&DECODE_INDEX_OP_FP, size_of(DECODE_INDEX_OP_FP))) w(TABLES + "riscv.idx_rvc.bin", raw(&DECODE_INDEX_RVC, size_of(DECODE_INDEX_RVC))) + w(TABLES + "riscv.clobber_forms.bin", raw(&CLOBBER_FORMS, size_of(CLOBBER_FORMS))) } diff --git a/core/rexcode/isa/riscv/tablegen/instruction_table.odin b/core/rexcode/isa/riscv/tablegen/instruction_table.odin new file mode 100644 index 000000000..ca076d516 --- /dev/null +++ b/core/rexcode/isa/riscv/tablegen/instruction_table.odin @@ -0,0 +1,690 @@ +package rexcode_riscv_tablegen + +// Form couples one encoding shape with its architectural effects. +// `using encoding` keeps existing field access (form.opcode, form.ops, +// form.flags, ...) working unchanged when code moves from []Encoding to []Form. +Form :: struct { + using encoding: Encoding, + clobber: Clobber, +} + +@(rodata) +INSTRUCTION_TABLE := [Mnemonic][]Form{ + .INVALID = {}, + + // ========================================================================= + // §1 RV32I / RV64I base + // ========================================================================= + + // Upper-immediate + .LUI = { + {{.LUI, {.GPR,.IMM20,.NONE,.NONE}, {.RD,.IMM_U,.NONE,.NONE}, 0x00000037, MASK_U, .I, {}}, {written={0}}}, + }, + .AUIPC = { + {{.AUIPC, {.GPR,.IMM20,.NONE,.NONE}, {.RD,.IMM_U,.NONE,.NONE}, 0x00000017, MASK_U, .I, {}}, {written={0}}}, + }, + + // Jumps + .JAL = { + {{.JAL, {.GPR,.REL21,.NONE,.NONE}, {.RD,.IMM_J,.NONE,.NONE}, 0x0000006F, MASK_J, .I, {branch=true}}, {written={0}, side_effects={.CONTROL}}}, + }, + .JALR = { + {{.JALR, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00000067, MASK_OPCODE | MASK_FUNCT3, .I, {branch=true}}, {written={0}, read={1}, side_effects={.CONTROL}}}, + }, + + // Branches (B-type) + .BEQ = { + {{.BEQ, {.GPR,.GPR,.REL13,.NONE}, {.RS1,.RS2,.IMM_B,.NONE}, 0x00000063, MASK_B, .I, {branch=true}}, {read={0, 1}, side_effects={.CONTROL}}}, + }, + .BNE = { + {{.BNE, {.GPR,.GPR,.REL13,.NONE}, {.RS1,.RS2,.IMM_B,.NONE}, 0x00001063, MASK_B, .I, {branch=true}}, {read={0, 1}, side_effects={.CONTROL}}}, + }, + .BLT = { + {{.BLT, {.GPR,.GPR,.REL13,.NONE}, {.RS1,.RS2,.IMM_B,.NONE}, 0x00004063, MASK_B, .I, {branch=true}}, {read={0, 1}, side_effects={.CONTROL}}}, + }, + .BGE = { + {{.BGE, {.GPR,.GPR,.REL13,.NONE}, {.RS1,.RS2,.IMM_B,.NONE}, 0x00005063, MASK_B, .I, {branch=true}}, {read={0, 1}, side_effects={.CONTROL}}}, + }, + .BLTU = { + {{.BLTU, {.GPR,.GPR,.REL13,.NONE}, {.RS1,.RS2,.IMM_B,.NONE}, 0x00006063, MASK_B, .I, {branch=true}}, {read={0, 1}, side_effects={.CONTROL}}}, + }, + .BGEU = { + {{.BGEU, {.GPR,.GPR,.REL13,.NONE}, {.RS1,.RS2,.IMM_B,.NONE}, 0x00007063, MASK_B, .I, {branch=true}}, {read={0, 1}, side_effects={.CONTROL}}}, + }, + + // Loads (I-type) + .LB = { + {{.LB, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00000003, MASK_I, .I, {}}, {written={0}, read={1}, reads_mem=true}}, + }, + .LH = { + {{.LH, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00001003, MASK_I, .I, {}}, {written={0}, read={1}, reads_mem=true}}, + }, + .LW = { + {{.LW, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00002003, MASK_I, .I, {}}, {written={0}, read={1}, reads_mem=true}}, + }, + .LBU = { + {{.LBU, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00004003, MASK_I, .I, {}}, {written={0}, read={1}, reads_mem=true}}, + }, + .LHU = { + {{.LHU, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00005003, MASK_I, .I, {}}, {written={0}, read={1}, reads_mem=true}}, + }, + .LWU = { + {{.LWU, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00006003, MASK_I, .I, {rv64_only=true}}, {written={0}, read={1}, reads_mem=true}}, + }, + .LD = { + {{.LD, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00003003, MASK_I, .I, {rv64_only=true}}, {written={0}, read={1}, reads_mem=true}}, + }, + + // Stores (S-type) + .SB = { + {{.SB, {.GPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00000023, MASK_S, .I, {}}, {read={0, 1}, writes_mem=true}}, + }, + .SH = { + {{.SH, {.GPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00001023, MASK_S, .I, {}}, {read={0, 1}, writes_mem=true}}, + }, + .SW = { + {{.SW, {.GPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00002023, MASK_S, .I, {}}, {read={0, 1}, writes_mem=true}}, + }, + .SD = { + {{.SD, {.GPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00003023, MASK_S, .I, {rv64_only=true}}, {read={0, 1}, writes_mem=true}}, + }, + + // Integer reg-imm (I-type ALU) + .ADDI = { + {{.ADDI, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00000013, MASK_I, .I, {}}, {written={0}, read={1}}}, + }, + .SLTI = { + {{.SLTI, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00002013, MASK_I, .I, {}}, {written={0}, read={1}}}, + }, + .SLTIU = { + {{.SLTIU, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00003013, MASK_I, .I, {}}, {written={0}, read={1}}}, + }, + .XORI = { + {{.XORI, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00004013, MASK_I, .I, {}}, {written={0}, read={1}}}, + }, + .ORI = { + {{.ORI, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00006013, MASK_I, .I, {}}, {written={0}, read={1}}}, + }, + .ANDI = { + {{.ANDI, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00007013, MASK_I, .I, {}}, {written={0}, read={1}}}, + }, + + .SLLI = { + {{.SLLI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x00001013, MASK_OPCODE | MASK_FUNCT3 | 0xFC000000, .I, {}}, {written={0}, read={1}}}, + }, + .SRLI = { + {{.SRLI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x00005013, MASK_OPCODE | MASK_FUNCT3 | 0xFC000000, .I, {}}, {written={0}, read={1}}}, + }, + .SRAI = { + {{.SRAI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x40005013, MASK_OPCODE | MASK_FUNCT3 | 0xFC000000, .I, {}}, {written={0}, read={1}}}, + }, + + .ADDIW = { + {{.ADDIW, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x0000001B, MASK_I, .I, {rv64_only=true}}, {written={0}, read={1}}}, + }, + .SLLIW = { + {{.SLLIW, {.GPR,.GPR,.IMM5,.NONE}, {.RD,.RS1,.SHAMT5,.NONE}, 0x0000101B, MASK_R, .I, {rv64_only=true}}, {written={0}, read={1}}}, + }, + .SRLIW = { + {{.SRLIW, {.GPR,.GPR,.IMM5,.NONE}, {.RD,.RS1,.SHAMT5,.NONE}, 0x0000501B, MASK_R, .I, {rv64_only=true}}, {written={0}, read={1}}}, + }, + .SRAIW = { + {{.SRAIW, {.GPR,.GPR,.IMM5,.NONE}, {.RD,.RS1,.SHAMT5,.NONE}, 0x4000501B, MASK_R, .I, {rv64_only=true}}, {written={0}, read={1}}}, + }, + + // Integer reg-reg (R-type) + .ADD = { + {{.ADD, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00000033, MASK_R, .I, {}}, {written={0}, read={1, 2}}}, + }, + .SUB = { + {{.SUB, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x40000033, MASK_R, .I, {}}, {written={0}, read={1, 2}}}, + }, + .SLL = { + {{.SLL, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00001033, MASK_R, .I, {}}, {written={0}, read={1, 2}}}, + }, + .SLT = { + {{.SLT, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00002033, MASK_R, .I, {}}, {written={0}, read={1, 2}}}, + }, + .SLTU = { + {{.SLTU, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00003033, MASK_R, .I, {}}, {written={0}, read={1, 2}}}, + }, + .XOR = { + {{.XOR, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00004033, MASK_R, .I, {}}, {written={0}, read={1, 2}}}, + }, + .SRL = { + {{.SRL, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00005033, MASK_R, .I, {}}, {written={0}, read={1, 2}}}, + }, + .SRA = { + {{.SRA, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x40005033, MASK_R, .I, {}}, {written={0}, read={1, 2}}}, + }, + .OR = { + {{.OR, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00006033, MASK_R, .I, {}}, {written={0}, read={1, 2}}}, + }, + .AND = { + {{.AND, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00007033, MASK_R, .I, {}}, {written={0}, read={1, 2}}}, + }, + + .ADDW = { + {{.ADDW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0000003B, MASK_R, .I, {rv64_only=true}}, {written={0}, read={1, 2}}}, + }, + .SUBW = { + {{.SUBW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x4000003B, MASK_R, .I, {rv64_only=true}}, {written={0}, read={1, 2}}}, + }, + .SLLW = { + {{.SLLW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0000103B, MASK_R, .I, {rv64_only=true}}, {written={0}, read={1, 2}}}, + }, + .SRLW = { + {{.SRLW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0000503B, MASK_R, .I, {rv64_only=true}}, {written={0}, read={1, 2}}}, + }, + .SRAW = { + {{.SRAW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x4000503B, MASK_R, .I, {rv64_only=true}}, {written={0}, read={1, 2}}}, + }, + + // Memory ordering + .FENCE = { + {{.FENCE, {.FENCE_FLAGS,.FENCE_FLAGS,.NONE,.NONE}, {.FENCE_PRED,.FENCE_SUCC,.NONE,.NONE}, 0x0000000F, MASK_I, .I, {}}, {side_effects={.FENCE}}}, + }, + .FENCE_I = { + {{.FENCE_I, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x0000100F, 0xFFFFFFFF, .ZIFENCEI, {}}, {side_effects={.IFENCE}}}, + }, + + // System + .ECALL = { + {{.ECALL, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x00000073, 0xFFFFFFFF, .I, {branch=true}}, {side_effects={.TRAP, .CONTROL}}}, + }, + .EBREAK = { + {{.EBREAK, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x00100073, 0xFFFFFFFF, .I, {branch=true}}, {side_effects={.TRAP, .CONTROL}}}, + }, + + // ========================================================================= + // §2 Zicsr (CSR access) — csr operand (slot 1) marked r+w conservatively + // ========================================================================= + .CSRRW = { + {{.CSRRW, {.GPR,.CSR,.GPR,.NONE}, {.RD,.CSR_FIELD,.RS1,.NONE}, 0x00001073, MASK_I, .ZICSR, {}}, {written={0, 1}, read={1, 2}}}, + }, + .CSRRS = { + {{.CSRRS, {.GPR,.CSR,.GPR,.NONE}, {.RD,.CSR_FIELD,.RS1,.NONE}, 0x00002073, MASK_I, .ZICSR, {}}, {written={0, 1}, read={1, 2}}}, + }, + .CSRRC = { + {{.CSRRC, {.GPR,.CSR,.GPR,.NONE}, {.RD,.CSR_FIELD,.RS1,.NONE}, 0x00003073, MASK_I, .ZICSR, {}}, {written={0, 1}, read={1, 2}}}, + }, + .CSRRWI = { + {{.CSRRWI, {.GPR,.CSR,.ZIMM5,.NONE}, {.RD,.CSR_FIELD,.ZIMM_FIELD,.NONE}, 0x00005073, MASK_I, .ZICSR, {}}, {written={0, 1}, read={1}}}, + }, + .CSRRSI = { + {{.CSRRSI, {.GPR,.CSR,.ZIMM5,.NONE}, {.RD,.CSR_FIELD,.ZIMM_FIELD,.NONE}, 0x00006073, MASK_I, .ZICSR, {}}, {written={0, 1}, read={1}}}, + }, + .CSRRCI = { + {{.CSRRCI, {.GPR,.CSR,.ZIMM5,.NONE}, {.RD,.CSR_FIELD,.ZIMM_FIELD,.NONE}, 0x00007073, MASK_I, .ZICSR, {}}, {written={0, 1}, read={1}}}, + }, + + // ========================================================================= + // §3 M extension — pure dataflow; no trap, no flags (incl. DIV/REM by 0) + // ========================================================================= + .MUL = { + {{.MUL, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02000033, MASK_R, .M, {}}, {written={0}, read={1, 2}}}, + }, + .MULH = { + {{.MULH, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02001033, MASK_R, .M, {}}, {written={0}, read={1, 2}}}, + }, + .MULHSU = { + {{.MULHSU, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02002033, MASK_R, .M, {}}, {written={0}, read={1, 2}}}, + }, + .MULHU = { + {{.MULHU, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02003033, MASK_R, .M, {}}, {written={0}, read={1, 2}}}, + }, + .DIV = { + {{.DIV, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02004033, MASK_R, .M, {}}, {written={0}, read={1, 2}}}, + }, + .DIVU = { + {{.DIVU, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02005033, MASK_R, .M, {}}, {written={0}, read={1, 2}}}, + }, + .REM = { + {{.REM, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02006033, MASK_R, .M, {}}, {written={0}, read={1, 2}}}, + }, + .REMU = { + {{.REMU, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02007033, MASK_R, .M, {}}, {written={0}, read={1, 2}}}, + }, + + .MULW = { + {{.MULW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0200003B, MASK_R, .M, {rv64_only=true}}, {written={0}, read={1, 2}}}, + }, + .DIVW = { + {{.DIVW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0200403B, MASK_R, .M, {rv64_only=true}}, {written={0}, read={1, 2}}}, + }, + .DIVUW = { + {{.DIVUW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0200503B, MASK_R, .M, {rv64_only=true}}, {written={0}, read={1, 2}}}, + }, + .REMW = { + {{.REMW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0200603B, MASK_R, .M, {rv64_only=true}}, {written={0}, read={1, 2}}}, + }, + .REMUW = { + {{.REMUW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0200703B, MASK_R, .M, {rv64_only=true}}, {written={0}, read={1, 2}}}, + }, + + // ========================================================================= + // §4 A extension (atomics) + // ========================================================================= + .LR_W = { + {{.LR_W, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_A,.NONE,.NONE}, 0x1000202F, 0xF9F0707F, .A, {}}, {written={0}, read={1}, reads_mem=true, side_effects={.ATOMIC, .RESERVATION}}}, + }, + .SC_W = { + {{.SC_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x1800202F, 0xF800707F, .A, {}}, {written={0}, read={1, 2}, writes_mem=true, side_effects={.ATOMIC, .RESERVATION}}}, + }, + .AMOSWAP_W = { + {{.AMOSWAP_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x0800202F, 0xF800707F, .A, {}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + .AMOADD_W = { + {{.AMOADD_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x0000202F, 0xF800707F, .A, {}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + .AMOXOR_W = { + {{.AMOXOR_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x2000202F, 0xF800707F, .A, {}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + .AMOAND_W = { + {{.AMOAND_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x6000202F, 0xF800707F, .A, {}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + .AMOOR_W = { + {{.AMOOR_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x4000202F, 0xF800707F, .A, {}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + .AMOMIN_W = { + {{.AMOMIN_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x8000202F, 0xF800707F, .A, {}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + .AMOMAX_W = { + {{.AMOMAX_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0xA000202F, 0xF800707F, .A, {}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + .AMOMINU_W = { + {{.AMOMINU_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0xC000202F, 0xF800707F, .A, {}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + .AMOMAXU_W = { + {{.AMOMAXU_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0xE000202F, 0xF800707F, .A, {}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + + .LR_D = { + {{.LR_D, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_A,.NONE,.NONE}, 0x1000302F, 0xF9F0707F, .A, {rv64_only=true}}, {written={0}, read={1}, reads_mem=true, side_effects={.ATOMIC, .RESERVATION}}}, + }, + .SC_D = { + {{.SC_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x1800302F, 0xF800707F, .A, {rv64_only=true}}, {written={0}, read={1, 2}, writes_mem=true, side_effects={.ATOMIC, .RESERVATION}}}, + }, + .AMOSWAP_D = { + {{.AMOSWAP_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x0800302F, 0xF800707F, .A, {rv64_only=true}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + .AMOADD_D = { + {{.AMOADD_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x0000302F, 0xF800707F, .A, {rv64_only=true}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + .AMOXOR_D = { + {{.AMOXOR_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x2000302F, 0xF800707F, .A, {rv64_only=true}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + .AMOAND_D = { + {{.AMOAND_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x6000302F, 0xF800707F, .A, {rv64_only=true}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + .AMOOR_D = { + {{.AMOOR_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x4000302F, 0xF800707F, .A, {rv64_only=true}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + .AMOMIN_D = { + {{.AMOMIN_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x8000302F, 0xF800707F, .A, {rv64_only=true}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + .AMOMAX_D = { + {{.AMOMAX_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0xA000302F, 0xF800707F, .A, {rv64_only=true}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + .AMOMINU_D = { + {{.AMOMINU_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0xC000302F, 0xF800707F, .A, {rv64_only=true}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + .AMOMAXU_D = { + {{.AMOMAXU_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0xE000302F, 0xF800707F, .A, {rv64_only=true}}, {written={0}, read={1, 2}, reads_mem=true, writes_mem=true, side_effects={.ATOMIC}}}, + }, + + // ========================================================================= + // §5 F extension (single-precision) — reads_frm == encoding fp_round + // ========================================================================= + .FLW = { + {{.FLW, {.FPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00002007, MASK_I, .F, {}}, {written={0}, read={1}, reads_mem=true}}, + }, + .FSW = { + {{.FSW, {.FPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00002027, MASK_S, .F, {}}, {read={0, 1}, writes_mem=true}}, + }, + + .FMADD_S = { + {{.FMADD_S, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x00000043, 0x0600007F, .F, {fp_round=true}}, {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}}, + }, + .FMSUB_S = { + {{.FMSUB_S, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x00000047, 0x0600007F, .F, {fp_round=true}}, {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}}, + }, + .FNMSUB_S = { + {{.FNMSUB_S, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x0000004B, 0x0600007F, .F, {fp_round=true}}, {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}}, + }, + .FNMADD_S = { + {{.FNMADD_S, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x0000004F, 0x0600007F, .F, {fp_round=true}}, {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}}, + }, + + .FADD_S = { + {{.FADD_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00000053, MASK_OPCODE | MASK_FUNCT7, .F, {fp_round=true}}, {written={0}, read={1, 2}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}}, + }, + .FSUB_S = { + {{.FSUB_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x08000053, MASK_OPCODE | MASK_FUNCT7, .F, {fp_round=true}}, {written={0}, read={1, 2}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}}, + }, + .FMUL_S = { + {{.FMUL_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x10000053, MASK_OPCODE | MASK_FUNCT7, .F, {fp_round=true}}, {written={0}, read={1, 2}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}}, + }, + .FDIV_S = { + {{.FDIV_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x18000053, MASK_OPCODE | MASK_FUNCT7, .F, {fp_round=true}}, {written={0}, read={1, 2}, fflags_wr={.NV, .DZ, .OF, .UF, .NX}, reads_frm=true}}, + }, + .FSQRT_S = { + {{.FSQRT_S, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x58000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}}, + }, + + .FSGNJ_S = { + {{.FSGNJ_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x20000053, MASK_R, .F, {}}, {written={0}, read={1, 2}}}, + }, + .FSGNJN_S = { + {{.FSGNJN_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x20001053, MASK_R, .F, {}}, {written={0}, read={1, 2}}}, + }, + .FSGNJX_S = { + {{.FSGNJX_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x20002053, MASK_R, .F, {}}, {written={0}, read={1, 2}}}, + }, + + .FMIN_S = { + {{.FMIN_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x28000053, MASK_R, .F, {}}, {written={0}, read={1, 2}, fflags_wr={.NV}}}, + }, + .FMAX_S = { + {{.FMAX_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x28001053, MASK_R, .F, {}}, {written={0}, read={1, 2}, fflags_wr={.NV}}}, + }, + + .FCVT_W_S = { + {{.FCVT_W_S, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC0000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}}, + }, + .FCVT_WU_S = { + {{.FCVT_WU_S, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC0100053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}}, + }, + .FCVT_L_S = { + {{.FCVT_L_S, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC0200053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true, rv64_only=true}}, {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}}, + }, + .FCVT_LU_S = { + {{.FCVT_LU_S, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC0300053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true, rv64_only=true}}, {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}}, + }, + + .FCVT_S_W = { + {{.FCVT_S_W, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD0000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NX}, reads_frm=true}}, + }, + .FCVT_S_WU = { + {{.FCVT_S_WU, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD0100053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NX}, reads_frm=true}}, + }, + .FCVT_S_L = { + {{.FCVT_S_L, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD0200053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true, rv64_only=true}}, {written={0}, read={1}, fflags_wr={.NX}, reads_frm=true}}, + }, + .FCVT_S_LU = { + {{.FCVT_S_LU, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD0300053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .F, {fp_round=true, rv64_only=true}}, {written={0}, read={1}, fflags_wr={.NX}, reads_frm=true}}, + }, + + .FMV_X_W = { + {{.FMV_X_W, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xE0000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2 | MASK_FUNCT3, .F, {}}, {written={0}, read={1}}}, + }, + .FMV_W_X = { + {{.FMV_W_X, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xF0000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2 | MASK_FUNCT3, .F, {}}, {written={0}, read={1}}}, + }, + .FCLASS_S = { + {{.FCLASS_S, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xE0001053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2 | MASK_FUNCT3, .F, {}}, {written={0}, read={1}}}, + }, + + .FEQ_S = { + {{.FEQ_S, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA0002053, MASK_R, .F, {}}, {written={0}, read={1, 2}, fflags_wr={.NV}}}, + }, + .FLT_S = { + {{.FLT_S, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA0001053, MASK_R, .F, {}}, {written={0}, read={1, 2}, fflags_wr={.NV}}}, + }, + .FLE_S = { + {{.FLE_S, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA0000053, MASK_R, .F, {}}, {written={0}, read={1, 2}, fflags_wr={.NV}}}, + }, + + // ========================================================================= + // §6 D extension (double-precision) + // ========================================================================= + .FLD = { + {{.FLD, {.FPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00003007, MASK_I, .D, {}}, {written={0}, read={1}, reads_mem=true}}, + }, + .FSD = { + {{.FSD, {.FPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00003027, MASK_S, .D, {}}, {read={0, 1}, writes_mem=true}}, + }, + + .FMADD_D = { + {{.FMADD_D, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x02000043, 0x0600007F, .D, {fp_round=true}}, {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}}, + }, + .FMSUB_D = { + {{.FMSUB_D, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x02000047, 0x0600007F, .D, {fp_round=true}}, {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}}, + }, + .FNMSUB_D = { + {{.FNMSUB_D, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x0200004B, 0x0600007F, .D, {fp_round=true}}, {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}}, + }, + .FNMADD_D = { + {{.FNMADD_D, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x0200004F, 0x0600007F, .D, {fp_round=true}}, {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}}, + }, + + .FADD_D = { + {{.FADD_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02000053, MASK_OPCODE | MASK_FUNCT7, .D, {fp_round=true}}, {written={0}, read={1, 2}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}}, + }, + .FSUB_D = { + {{.FSUB_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A000053, MASK_OPCODE | MASK_FUNCT7, .D, {fp_round=true}}, {written={0}, read={1, 2}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}}, + }, + .FMUL_D = { + {{.FMUL_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x12000053, MASK_OPCODE | MASK_FUNCT7, .D, {fp_round=true}}, {written={0}, read={1, 2}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}}, + }, + .FDIV_D = { + {{.FDIV_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x1A000053, MASK_OPCODE | MASK_FUNCT7, .D, {fp_round=true}}, {written={0}, read={1, 2}, fflags_wr={.NV, .DZ, .OF, .UF, .NX}, reads_frm=true}}, + }, + .FSQRT_D = { + {{.FSQRT_D, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x5A000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}}, + }, + + .FSGNJ_D = { + {{.FSGNJ_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x22000053, MASK_R, .D, {}}, {written={0}, read={1, 2}}}, + }, + .FSGNJN_D = { + {{.FSGNJN_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x22001053, MASK_R, .D, {}}, {written={0}, read={1, 2}}}, + }, + .FSGNJX_D = { + {{.FSGNJX_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x22002053, MASK_R, .D, {}}, {written={0}, read={1, 2}}}, + }, + + .FMIN_D = { + {{.FMIN_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x2A000053, MASK_R, .D, {}}, {written={0}, read={1, 2}, fflags_wr={.NV}}}, + }, + .FMAX_D = { + {{.FMAX_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x2A001053, MASK_R, .D, {}}, {written={0}, read={1, 2}, fflags_wr={.NV}}}, + }, + + .FCVT_S_D = { + {{.FCVT_S_D, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x40100053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}}, + }, + .FCVT_D_S = { + {{.FCVT_D_S, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x42000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NV}, reads_frm=true}}, + }, + + .FCVT_W_D = { + {{.FCVT_W_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC2000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}}, + }, + .FCVT_WU_D = { + {{.FCVT_WU_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC2100053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}}, + }, + .FCVT_L_D = { + {{.FCVT_L_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC2200053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true, rv64_only=true}}, {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}}, + }, + .FCVT_LU_D = { + {{.FCVT_LU_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC2300053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true, rv64_only=true}}, {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}}, + }, + + // FCVT_D_W / FCVT_D_WU are always exact (32-bit int fits a double), so no + // fflags — but reads_frm follows the fp_round flag for class-uniformity. + .FCVT_D_W = { + {{.FCVT_D_W, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD2000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true}}, {written={0}, read={1}, reads_frm=true}}, + }, + .FCVT_D_WU = { + {{.FCVT_D_WU, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD2100053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true}}, {written={0}, read={1}, reads_frm=true}}, + }, + .FCVT_D_L = { + {{.FCVT_D_L, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD2200053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true, rv64_only=true}}, {written={0}, read={1}, fflags_wr={.NX}, reads_frm=true}}, + }, + .FCVT_D_LU = { + {{.FCVT_D_LU, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD2300053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .D, {fp_round=true, rv64_only=true}}, {written={0}, read={1}, fflags_wr={.NX}, reads_frm=true}}, + }, + + .FMV_X_D = { + {{.FMV_X_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xE2000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2 | MASK_FUNCT3, .D, {rv64_only=true}}, {written={0}, read={1}}}, + }, + .FMV_D_X = { + {{.FMV_D_X, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xF2000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2 | MASK_FUNCT3, .D, {rv64_only=true}}, {written={0}, read={1}}}, + }, + .FCLASS_D = { + {{.FCLASS_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xE2001053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2 | MASK_FUNCT3, .D, {}}, {written={0}, read={1}}}, + }, + + .FEQ_D = { + {{.FEQ_D, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA2002053, MASK_R, .D, {}}, {written={0}, read={1, 2}, fflags_wr={.NV}}}, + }, + .FLT_D = { + {{.FLT_D, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA2001053, MASK_R, .D, {}}, {written={0}, read={1, 2}, fflags_wr={.NV}}}, + }, + .FLE_D = { + {{.FLE_D, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA2000053, MASK_R, .D, {}}, {written={0}, read={1, 2}, fflags_wr={.NV}}}, + }, + + // ========================================================================= + // C extension: Quadrant 0 (op = 00) + // ========================================================================= + .C_ADDI4SPN = { + {{.C_ADDI4SPN, {.GPR_C, .GPR_SP, .IMM_C8U, .NONE}, {.C_RD_PRIMED, .NONE, .C_IMM_CIW, .NONE}, 0x0000, 0xE003, .C, {}}, {written={0}, read={1}}}, + }, + .C_FLD = { + {{.C_FLD, {.FPR_C, .MEM_C_D, .NONE, .NONE}, {.C_RD_PRIMED, .C_OFFSET_BASE_D, .NONE, .NONE}, 0x2000, 0xE003, .D, {}}, {written={0}, read={1}, reads_mem=true}}, + }, + .C_LW = { + {{.C_LW, {.GPR_C, .MEM_C_W, .NONE, .NONE}, {.C_RD_PRIMED, .C_OFFSET_BASE_W, .NONE, .NONE}, 0x4000, 0xE003, .C, {}}, {written={0}, read={1}, reads_mem=true}}, + }, + .C_LD = { + {{.C_LD, {.GPR_C, .MEM_C_D, .NONE, .NONE}, {.C_RD_PRIMED, .C_OFFSET_BASE_D, .NONE, .NONE}, 0x6000, 0xE003, .C, {rv64_only=true}}, {written={0}, read={1}, reads_mem=true}}, + }, + .C_FSD = { + {{.C_FSD, {.FPR_C, .MEM_C_D, .NONE, .NONE}, {.C_RS2_PRIMED, .C_OFFSET_BASE_D, .NONE, .NONE}, 0xA000, 0xE003, .D, {}}, {read={0, 1}, writes_mem=true}}, + }, + .C_SW = { + {{.C_SW, {.GPR_C, .MEM_C_W, .NONE, .NONE}, {.C_RS2_PRIMED, .C_OFFSET_BASE_W, .NONE, .NONE}, 0xC000, 0xE003, .C, {}}, {read={0, 1}, writes_mem=true}}, + }, + .C_SD = { + {{.C_SD, {.GPR_C, .MEM_C_D, .NONE, .NONE}, {.C_RS2_PRIMED, .C_OFFSET_BASE_D, .NONE, .NONE}, 0xE000, 0xE003, .C, {rv64_only=true}}, {read={0, 1}, writes_mem=true}}, + }, + + // C.FLW / C.FSW — RV32-only, share the C.LD / C.SD slots + .C_FLW = { + {{.C_FLW, {.FPR_C, .MEM_C_W, .NONE, .NONE}, {.C_RD_PRIMED, .C_OFFSET_BASE_W, .NONE, .NONE}, 0x6000, 0xE003, .F, {rv32_only=true}}, {written={0}, read={1}, reads_mem=true}}, + }, + .C_FSW = { + {{.C_FSW, {.FPR_C, .MEM_C_W, .NONE, .NONE}, {.C_RS2_PRIMED, .C_OFFSET_BASE_W, .NONE, .NONE}, 0xE000, 0xE003, .F, {rv32_only=true}}, {read={0, 1}, writes_mem=true}}, + }, + + // ========================================================================= + // C extension: Quadrant 1 (op = 01) + // ========================================================================= + .C_NOP = { + {{.C_NOP, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x0001, 0xFFFF, .C, {}}, {}}, + }, + .C_ADDI = { + {{.C_ADDI, {.GPR_NONZERO, .IMM_C6S, .NONE, .NONE}, {.C_RD_RS1, .C_IMM_CI_S, .NONE, .NONE}, 0x0001, 0xE003, .C, {}}, {written={0}, read={0}}}, + }, + .C_JAL = { + {{.C_JAL, {.REL12, .NONE, .NONE, .NONE}, {.C_BRANCH12, .NONE, .NONE, .NONE}, 0x2001, 0xE003, .C, {rv32_only=true, branch=true}}, {implicit_wr={.RA}, side_effects={.CONTROL}}}, + }, + .C_ADDIW = { + {{.C_ADDIW, {.GPR_NONZERO, .IMM_C6S, .NONE, .NONE}, {.C_RD_RS1, .C_IMM_CI_S, .NONE, .NONE}, 0x2001, 0xE003, .C, {rv64_only=true}}, {written={0}, read={0}}}, + }, + .C_LI = { + {{.C_LI, {.GPR_NONZERO, .IMM_C6S, .NONE, .NONE}, {.C_RD_RS1, .C_IMM_CI_S, .NONE, .NONE}, 0x4001, 0xE003, .C, {}}, {written={0}}}, + }, + .C_ADDI16SP = { + {{.C_ADDI16SP, {.GPR_SP, .IMM_C10S, .NONE, .NONE}, {.NONE, .C_IMM_ADDI16SP, .NONE, .NONE}, 0x6101, 0xEF83, .C, {}}, {written={0}, read={0}}}, + }, + .C_LUI = { + {{.C_LUI, {.GPR_NONZERO, .IMM_C18S, .NONE, .NONE}, {.C_RD_RS1, .C_IMM_LUI, .NONE, .NONE}, 0x6001, 0xE003, .C, {}}, {written={0}}}, + }, + .C_SRLI = { + {{.C_SRLI, {.GPR_C, .IMM_C6U, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_IMM_CI_U, .NONE, .NONE}, 0x8001, 0xEC03, .C, {}}, {written={0}, read={0}}}, + }, + .C_SRAI = { + {{.C_SRAI, {.GPR_C, .IMM_C6U, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_IMM_CI_U, .NONE, .NONE}, 0x8401, 0xEC03, .C, {}}, {written={0}, read={0}}}, + }, + .C_ANDI = { + {{.C_ANDI, {.GPR_C, .IMM_C6S, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_IMM_CI_S, .NONE, .NONE}, 0x8801, 0xEC03, .C, {}}, {written={0}, read={0}}}, + }, + .C_SUB = { + {{.C_SUB, {.GPR_C, .GPR_C, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_RS2_PRIMED, .NONE, .NONE}, 0x8C01, 0xFC63, .C, {}}, {written={0}, read={0, 1}}}, + }, + .C_XOR = { + {{.C_XOR, {.GPR_C, .GPR_C, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_RS2_PRIMED, .NONE, .NONE}, 0x8C21, 0xFC63, .C, {}}, {written={0}, read={0, 1}}}, + }, + .C_OR = { + {{.C_OR, {.GPR_C, .GPR_C, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_RS2_PRIMED, .NONE, .NONE}, 0x8C41, 0xFC63, .C, {}}, {written={0}, read={0, 1}}}, + }, + .C_AND = { + {{.C_AND, {.GPR_C, .GPR_C, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_RS2_PRIMED, .NONE, .NONE}, 0x8C61, 0xFC63, .C, {}}, {written={0}, read={0, 1}}}, + }, + .C_SUBW = { + {{.C_SUBW, {.GPR_C, .GPR_C, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_RS2_PRIMED, .NONE, .NONE}, 0x9C01, 0xFC63, .C, {rv64_only=true}}, {written={0}, read={0, 1}}}, + }, + .C_ADDW = { + {{.C_ADDW, {.GPR_C, .GPR_C, .NONE, .NONE}, {.C_RD_RS1_PRIMED, .C_RS2_PRIMED, .NONE, .NONE}, 0x9C21, 0xFC63, .C, {rv64_only=true}}, {written={0}, read={0, 1}}}, + }, + .C_J = { + {{.C_J, {.REL12, .NONE, .NONE, .NONE}, {.C_BRANCH12, .NONE, .NONE, .NONE}, 0xA001, 0xE003, .C, {branch=true}}, {side_effects={.CONTROL}}}, + }, + .C_BEQZ = { + {{.C_BEQZ, {.GPR_C, .REL9, .NONE, .NONE}, {.C_RS1_PRIMED, .C_BRANCH9, .NONE, .NONE}, 0xC001, 0xE003, .C, {branch=true}}, {read={0}, side_effects={.CONTROL}}}, + }, + .C_BNEZ = { + {{.C_BNEZ, {.GPR_C, .REL9, .NONE, .NONE}, {.C_RS1_PRIMED, .C_BRANCH9, .NONE, .NONE}, 0xE001, 0xE003, .C, {branch=true}}, {read={0}, side_effects={.CONTROL}}}, + }, + + // ========================================================================= + // C extension: Quadrant 2 (op = 10) + // ========================================================================= + .C_SLLI = { + {{.C_SLLI, {.GPR_NONZERO, .IMM_C6U, .NONE, .NONE}, {.C_RD_RS1, .C_IMM_CI_U, .NONE, .NONE}, 0x0002, 0xE003, .C, {}}, {written={0}, read={0}}}, + }, + .C_FLDSP = { + {{.C_FLDSP, {.FPR, .MEM_C_SP_D, .NONE, .NONE}, {.C_RD_RS1, .C_SP_OFFSET_D, .NONE, .NONE}, 0x2002, 0xE003, .D, {}}, {written={0}, implicit_rd={.SP}, reads_mem=true}}, + }, + .C_LWSP = { + {{.C_LWSP, {.GPR_NONZERO, .MEM_C_SP_W, .NONE, .NONE}, {.C_RD_RS1, .C_SP_OFFSET_W, .NONE, .NONE}, 0x4002, 0xE003, .C, {}}, {written={0}, implicit_rd={.SP}, reads_mem=true}}, + }, + .C_LDSP = { + {{.C_LDSP, {.GPR_NONZERO, .MEM_C_SP_D, .NONE, .NONE}, {.C_RD_RS1, .C_SP_OFFSET_D, .NONE, .NONE}, 0x6002, 0xE003, .C, {rv64_only=true}}, {written={0}, implicit_rd={.SP}, reads_mem=true}}, + }, + .C_JR = { + {{.C_JR, {.GPR_NONZERO, .NONE, .NONE, .NONE}, {.C_RD_RS1, .NONE, .NONE, .NONE}, 0x8002, 0xF07F, .C, {branch=true}}, {read={0}, side_effects={.CONTROL}}}, + }, + .C_MV = { + {{.C_MV, {.GPR_NONZERO, .GPR_NONZERO, .NONE, .NONE}, {.C_RD_RS1, .C_RS2, .NONE, .NONE}, 0x8002, 0xF003, .C, {}}, {written={0}, read={1}}}, + }, + .C_EBREAK = { + {{.C_EBREAK, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x9002, 0xFFFF, .C, {}}, {side_effects={.TRAP, .CONTROL}}}, + }, + .C_JALR = { + {{.C_JALR, {.GPR_NONZERO, .NONE, .NONE, .NONE}, {.C_RD_RS1, .NONE, .NONE, .NONE}, 0x9002, 0xF07F, .C, {branch=true}}, {read={0}, implicit_wr={.RA}, side_effects={.CONTROL}}}, + }, + .C_ADD = { + {{.C_ADD, {.GPR_NONZERO, .GPR_NONZERO, .NONE, .NONE}, {.C_RD_RS1, .C_RS2, .NONE, .NONE}, 0x9002, 0xF003, .C, {}}, {written={0}, read={0, 1}}}, + }, + .C_FSDSP = { + {{.C_FSDSP, {.FPR, .MEM_C_SP_D, .NONE, .NONE}, {.C_RS2, .C_IMM_CSS_D, .NONE, .NONE}, 0xA002, 0xE003, .D, {}}, {read={0}, implicit_rd={.SP}, writes_mem=true}}, + }, + .C_SWSP = { + {{.C_SWSP, {.GPR, .MEM_C_SP_W, .NONE, .NONE}, {.C_RS2, .C_IMM_CSS_W, .NONE, .NONE}, 0xC002, 0xE003, .C, {}}, {read={0}, implicit_rd={.SP}, writes_mem=true}}, + }, + .C_SDSP = { + {{.C_SDSP, {.GPR, .MEM_C_SP_D, .NONE, .NONE}, {.C_RS2, .C_IMM_CSS_D, .NONE, .NONE}, 0xE002, 0xE003, .C, {rv64_only=true}}, {read={0}, implicit_rd={.SP}, writes_mem=true}}, + }, + + // C.FLWSP / C.FSWSP — RV32-only, share the C.LDSP / C.SDSP slots + .C_FLWSP = { + {{.C_FLWSP, {.FPR, .MEM_C_SP_W, .NONE, .NONE}, {.C_RD_RS1, .C_SP_OFFSET_W, .NONE, .NONE}, 0x6002, 0xE003, .F, {rv32_only=true}}, {written={0}, implicit_rd={.SP}, reads_mem=true}}, + }, + .C_FSWSP = { + {{.C_FSWSP, {.FPR, .MEM_C_SP_W, .NONE, .NONE}, {.C_RS2, .C_IMM_CSS_W, .NONE, .NONE}, 0xE002, 0xE003, .F, {rv32_only=true}}, {read={0}, implicit_rd={.SP}, writes_mem=true}}, + }, +} diff --git a/core/rexcode/isa/riscv/tables.odin b/core/rexcode/isa/riscv/tables.odin index de5093efc..4d708c3d3 100644 --- a/core/rexcode/isa/riscv/tables.odin +++ b/core/rexcode/isa/riscv/tables.odin @@ -39,26 +39,34 @@ Decode_Index :: struct #packed { count: u16, } #assert(size_of(Decode_Index) == 4) - // ----------------------------------------------------------------------------- // Loaded tables (rodata, embedded from tables/*.bin at compile time) // ----------------------------------------------------------------------------- -@(rodata) ENCODE_FORMS := #load("tables/riscv.encode_forms.bin", []Encoding) -@(rodata) ENCODE_RUNS := #load("tables/riscv.encode_runs.bin", []Encode_Run) -@(rodata) DECODE_ENTRIES := #load("tables/riscv.entries.bin", []Decode_Entry) -@(rodata) DECODE_INDEX_OPCODE := #load("tables/riscv.idx_opcode.bin", []Decode_Index) -@(rodata) DECODE_INDEX_OP_FP := #load("tables/riscv.idx_op_fp.bin", []Decode_Index) -@(rodata) DECODE_INDEX_RVC := #load("tables/riscv.idx_rvc.bin", []Decode_Index) +@(rodata) ENCODE_FORMS := #load("tables/riscv.encode_forms.bin", []Encoding) +@(rodata) ENCODE_RUNS := #load("tables/riscv.encode_runs.bin", []Encode_Run) +@(rodata) DECODE_ENTRIES := #load("tables/riscv.entries.bin", []Decode_Entry) +@(rodata) DECODE_INDEX_OPCODE := #load("tables/riscv.idx_opcode.bin", []Decode_Index) +@(rodata) DECODE_INDEX_OP_FP := #load("tables/riscv.idx_op_fp.bin", []Decode_Index) +@(rodata) DECODE_INDEX_RVC := #load("tables/riscv.idx_rvc.bin", []Decode_Index) +@(rodata) CLOBBER_FORMS := #load("tables/riscv.clobber_forms.bin", []Clobber) // ----------------------------------------------------------------------------- // Accessors // ----------------------------------------------------------------------------- -// Per-mnemonic encode forms: the run of ENCODE_FORMS belonging to `m`. +// Per-mnemonic encode forms: the run of ENCODE_FORMS belonging to ` + "`m`" + `. // Replaces the old ENCODING_TABLE[m] slice; the returned view is into rodata. @(private, require_results) encoding_forms :: #force_inline proc "contextless" (m: Mnemonic) -> []Encoding { r := ENCODE_RUNS[u16(m)] return ENCODE_FORMS[r.start:][:r.count] } + +// Per-mnemonic clobber forms: the run of CLOBBER_FORMS belonging to ` + "`m`" + `. +// Replaces the old ENCODING_TABLE[m] slice; the returned view is into rodata. +@(private, require_results) +clobber_forms :: #force_inline proc "contextless" (m: Mnemonic) -> []Clobber { + r := ENCODE_RUNS[u16(m)] + return CLOBBER_FORMS[r.start:][:r.count] +} \ No newline at end of file