mirror of
https://github.com/odin-lang/Odin.git
synced 2026-08-25 22:41:34 +00:00
rexcode: riscv INSTRUCTION_TABLE which includes the clobber information
This commit is contained in:
47
core/rexcode/isa/riscv/clobber_types.odin
Normal file
47
core/rexcode/isa/riscv/clobber_types.odin
Normal file
@@ -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,
|
||||
}
|
||||
@@ -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}} },
|
||||
}
|
||||
@@ -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..<run_w-len(name) { strings.write_byte(&sb, ' ') }
|
||||
@@ -141,7 +156,8 @@ emit_decode_tables :: proc() -> (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()
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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)))
|
||||
}
|
||||
|
||||
690
core/rexcode/isa/riscv/tablegen/instruction_table.odin
Normal file
690
core/rexcode/isa/riscv/tablegen/instruction_table.odin
Normal file
@@ -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}},
|
||||
},
|
||||
}
|
||||
@@ -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]
|
||||
}
|
||||
Reference in New Issue
Block a user