Begin work on pseudo-aliases

This commit is contained in:
gingerBill
2026-08-20 17:51:47 +01:00
parent 43ff42bf33
commit cfb8a109b6
17 changed files with 2403 additions and 272 deletions

View File

@@ -40,7 +40,7 @@ LABEL_UNDEFINED :: isa.LABEL_UNDEFINED
Label_Map :: isa.Label_Map
// Extension this entry belongs to (metadata, not used by the matcher).
Feature :: enum u8 {
Feature :: enum u16 {
I, // RV32I / RV64I base integer
M, // multiply / divide
A, // atomics
@@ -49,6 +49,13 @@ Feature :: enum u8 {
ZICSR, // CSR access (CSRRW/S/C + immediate forms)
ZIFENCEI, // FENCE.I (instruction-fetch fence)
C, // 16-bit compressed instructions
ZBA, // address-generation bit-manip
ZBB, // basic bit-manip
ZBC, // carry-less multiply
ZBS, // single-bit bit-manip
ZICOND, // conditional zeroing
ZFH, // half-precision (binary16) FP
PRIV, // privileged trap-return / TLB maintenance
}
Encoding_Flags :: bit_field u8 {
@@ -150,10 +157,10 @@ Encoding :: struct #packed {
enc: [4]Operand_Encoding, // 4
bits: u32, // 4 -- static bit pattern
mask: u32, // 4 -- which bits are static
feature: Feature, // 1
feature: Feature, // 2
flags: Encoding_Flags, // 1
}
#assert(size_of(Encoding) == 20)
#assert(size_of(Encoding) == 21)
// inst_size_from_bits returns 2 for compressed (RVC) instructions, 4 for the
// standard 32-bit base ISA. RISC-V uses a length-encoding convention where

View File

@@ -139,4 +139,89 @@ Mnemonic :: enum u16 {
C_FLDSP, C_FSDSP,
C_JR, C_JALR, C_MV, C_ADD,
C_FLWSP, C_FSWSP,
SH1ADD,
SH2ADD,
SH3ADD,
ADD_UW,
SH1ADD_UW,
SH2ADD_UW,
SH3ADD_UW,
SLLI_UW,
ANDN,
ORN,
XNOR,
CLZ,
CTZ,
CPOP,
SEXT_B,
SEXT_H,
ZEXT_H,
MIN,
MINU,
MAX,
MAXU,
ROL,
ROR,
RORI,
ORC_B,
REV8,
CLZW,
CTZW,
CPOPW,
ROLW,
RORW,
RORIW,
CLMUL,
CLMULH,
CLMULR,
BCLR,
BCLRI,
BEXT,
BEXTI,
BINV,
BINVI,
BSET,
BSETI,
CZERO_EQZ,
CZERO_NEZ,
FLH,
FSH,
FMADD_H,
FMSUB_H,
FNMSUB_H,
FNMADD_H,
FADD_H,
FSUB_H,
FMUL_H,
FDIV_H,
FSQRT_H,
FSGNJ_H,
FSGNJN_H,
FSGNJX_H,
FMIN_H,
FMAX_H,
FCVT_W_H,
FCVT_WU_H,
FCVT_L_H,
FCVT_LU_H,
FCVT_H_W,
FCVT_H_WU,
FCVT_H_L,
FCVT_H_LU,
FCVT_S_H,
FCVT_H_S,
FCVT_D_H,
FCVT_H_D,
FMV_X_H,
FMV_H_X,
FCLASS_H,
FEQ_H,
FLT_H,
FLE_H,
MRET,
SRET,
WFI,
SFENCE_VMA,
}

View File

@@ -0,0 +1,171 @@
package rexcode_riscv
// =============================================================================
// RISC-V PSEUDO-INSTRUCTION ALIAS TABLE
//
// Every entry here lowers to exactly ONE real INSTRUCTION_TABLE mnemonic by
// filling that target's operand slots. The real entry supplies the encoding
// and the clobber set for free — a pseudo's dataflow is its target's dataflow.
//
// Pseudos that CANNOT be expressed this way (value-dependent expansions and a
// couple of fixed-word HINTs) are listed as comments at the bottom; they stay
// procedures or dedicated table rows.
// =============================================================================
// How each operand slot of the target instruction is filled.
Alias_Src :: enum u8 {
NONE, // slot unused
ARG0, // user's 1st operand
ARG1, // user's 2nd operand
ARG2, // user's 3rd operand
X0, // hardwired zero (x0)
X1, // link register (ra / x1)
LIT, // the `lit` field below (immediate literal)
CSR_LIT, // the `csr` field below (fixed 12-bit CSR address)
}
Pseudo_Alias :: struct {
target: Mnemonic, // real instruction emitted
src: [4]Alias_Src, // how to fill target's four operand slots
lit: i16, // immediate when a src slot is .LIT
csr: u16, // CSR address when a src slot is .CSR_LIT
nargs: u8, // operands the user supplies (ARG0..<ARGn)
rv32_only: bool, // base gate (the *h counter reads)
}
Pseudo_Mnemonic :: enum u16 {
INVALID,
// integer moves / arithmetic
NOP, MV, NOT, NEG, NEGW, SEXT_W, ZEXT_B,
// set-if / compare-to-zero
SEQZ, SNEZ, SLTZ, SGTZ,
// branch-on-zero
BEQZ, BNEZ, BLEZ, BGEZ, BLTZ, BGTZ,
// branch with swapped operands
BGT, BLE, BGTU, BLEU,
// jumps
J, JAL_RA, JR, JALR_RA, RET,
// generic CSR access
CSRR, CSRW, CSRS, CSRC, CSRWI, CSRSI, CSRCI,
// named counter reads (CSR baked in)
RDCYCLE, RDTIME, RDINSTRET, RDCYCLEH, RDTIMEH, RDINSTRETH,
// fcsr / frm / fflags accessors
FRCSR, FSCSR, FRRM, FSRM, FRFLAGS, FSFLAGS, FSRMI, FSFLAGSI,
// FP sign-injection moves
FMV_S, FABS_S, FNEG_S,
FMV_D, FABS_D, FNEG_D,
FMV_H, FABS_H, FNEG_H,
// memory ordering
FENCE_ALL,
}
@(rodata)
PSEUDO_ALIASES := [Pseudo_Mnemonic]Pseudo_Alias{
.INVALID = {},
// -------------------------------------------------------------------------
// Integer moves / arithmetic
// -------------------------------------------------------------------------
.NOP = {target = .ADDI, src = {.X0, .X0, .LIT, .NONE}, nargs = 0}, // addi x0, x0, 0
.MV = {target = .ADDI, src = {.ARG0, .ARG1, .LIT, .NONE}, nargs = 2}, // addi rd, rs, 0
.NOT = {target = .XORI, src = {.ARG0, .ARG1, .LIT, .NONE}, lit = -1, nargs = 2}, // xori rd, rs, -1
.NEG = {target = .SUB, src = {.ARG0, .X0, .ARG1, .NONE}, nargs = 2}, // sub rd, x0, rs
.NEGW = {target = .SUBW, src = {.ARG0, .X0, .ARG1, .NONE}, nargs = 2}, // subw rd, x0, rs (RV64)
.SEXT_W = {target = .ADDIW, src = {.ARG0, .ARG1, .LIT, .NONE}, nargs = 2}, // addiw rd, rs, 0 (RV64)
.ZEXT_B = {target = .ANDI, src = {.ARG0, .ARG1, .LIT, .NONE}, lit = 255, nargs = 2}, // andi rd, rs, 255
// -------------------------------------------------------------------------
// Set-if-condition against zero
// -------------------------------------------------------------------------
.SEQZ = {target = .SLTIU, src = {.ARG0, .ARG1, .LIT, .NONE}, lit = 1, nargs = 2}, // sltiu rd, rs, 1
.SNEZ = {target = .SLTU, src = {.ARG0, .X0, .ARG1, .NONE}, nargs = 2}, // sltu rd, x0, rs
.SLTZ = {target = .SLT, src = {.ARG0, .ARG1, .X0, .NONE}, nargs = 2}, // slt rd, rs, x0
.SGTZ = {target = .SLT, src = {.ARG0, .X0, .ARG1, .NONE}, nargs = 2}, // slt rd, x0, rs
// -------------------------------------------------------------------------
// Branch on comparison with zero (target ops: rs1, rs2, offset)
// -------------------------------------------------------------------------
.BEQZ = {target = .BEQ, src = {.ARG0, .X0, .ARG1, .NONE}, nargs = 2}, // beq rs, x0, off
.BNEZ = {target = .BNE, src = {.ARG0, .X0, .ARG1, .NONE}, nargs = 2}, // bne rs, x0, off
.BLEZ = {target = .BGE, src = {.X0, .ARG0, .ARG1, .NONE}, nargs = 2}, // bge x0, rs, off
.BGEZ = {target = .BGE, src = {.ARG0, .X0, .ARG1, .NONE}, nargs = 2}, // bge rs, x0, off
.BLTZ = {target = .BLT, src = {.ARG0, .X0, .ARG1, .NONE}, nargs = 2}, // blt rs, x0, off
.BGTZ = {target = .BLT, src = {.X0, .ARG0, .ARG1, .NONE}, nargs = 2}, // blt x0, rs, off
// -------------------------------------------------------------------------
// Branch with the two source registers swapped (encode-only rewrite;
// never participates in decode, so the swap is safe)
// -------------------------------------------------------------------------
.BGT = {target = .BLT, src = {.ARG1, .ARG0, .ARG2, .NONE}, nargs = 3}, // blt rt, rs, off
.BLE = {target = .BGE, src = {.ARG1, .ARG0, .ARG2, .NONE}, nargs = 3}, // bge rt, rs, off
.BGTU = {target = .BLTU, src = {.ARG1, .ARG0, .ARG2, .NONE}, nargs = 3}, // bltu rt, rs, off
.BLEU = {target = .BGEU, src = {.ARG1, .ARG0, .ARG2, .NONE}, nargs = 3}, // bgeu rt, rs, off
// -------------------------------------------------------------------------
// Jumps. JAL_RA / JALR_RA are the single-operand forms that default the
// link register to ra; the front-end selects them by argument count vs the
// real 2-operand JAL / JALR.
// -------------------------------------------------------------------------
.J = {target = .JAL, src = {.X0, .ARG0, .NONE, .NONE}, nargs = 1}, // jal x0, off
.JAL_RA = {target = .JAL, src = {.X1, .ARG0, .NONE, .NONE}, nargs = 1}, // jal x1, off
.JR = {target = .JALR, src = {.X0, .ARG0, .LIT, .NONE}, nargs = 1}, // jalr x0, rs, 0
.JALR_RA = {target = .JALR, src = {.X1, .ARG0, .LIT, .NONE}, nargs = 1}, // jalr x1, rs, 0
.RET = {target = .JALR, src = {.X0, .X1, .LIT, .NONE}, nargs = 0}, // jalr x0, ra, 0
// -------------------------------------------------------------------------
// Generic CSR access (target ops: rd, csr, rs1/zimm)
// -------------------------------------------------------------------------
.CSRR = {target = .CSRRS, src = {.ARG0, .ARG1, .X0, .NONE}, nargs = 2}, // csrrs rd, csr, x0
.CSRW = {target = .CSRRW, src = {.X0, .ARG0, .ARG1, .NONE}, nargs = 2}, // csrrw x0, csr, rs
.CSRS = {target = .CSRRS, src = {.X0, .ARG0, .ARG1, .NONE}, nargs = 2}, // csrrs x0, csr, rs
.CSRC = {target = .CSRRC, src = {.X0, .ARG0, .ARG1, .NONE}, nargs = 2}, // csrrc x0, csr, rs
.CSRWI = {target = .CSRRWI, src = {.X0, .ARG0, .ARG1, .NONE}, nargs = 2}, // csrrwi x0, csr, imm
.CSRSI = {target = .CSRRSI, src = {.X0, .ARG0, .ARG1, .NONE}, nargs = 2}, // csrrsi x0, csr, imm
.CSRCI = {target = .CSRRCI, src = {.X0, .ARG0, .ARG1, .NONE}, nargs = 2}, // csrrci x0, csr, imm
// -------------------------------------------------------------------------
// Named counter reads — CSR baked in, so nargs = 1 (just rd).
// The *h forms read the high word and exist only on RV32.
// -------------------------------------------------------------------------
.RDCYCLE = {target = .CSRRS, src = {.ARG0, .CSR_LIT, .X0, .NONE}, csr = 0xC00, nargs = 1},
.RDTIME = {target = .CSRRS, src = {.ARG0, .CSR_LIT, .X0, .NONE}, csr = 0xC01, nargs = 1},
.RDINSTRET = {target = .CSRRS, src = {.ARG0, .CSR_LIT, .X0, .NONE}, csr = 0xC02, nargs = 1},
.RDCYCLEH = {target = .CSRRS, src = {.ARG0, .CSR_LIT, .X0, .NONE}, csr = 0xC80, nargs = 1, rv32_only = true},
.RDTIMEH = {target = .CSRRS, src = {.ARG0, .CSR_LIT, .X0, .NONE}, csr = 0xC81, nargs = 1, rv32_only = true},
.RDINSTRETH = {target = .CSRRS, src = {.ARG0, .CSR_LIT, .X0, .NONE}, csr = 0xC82, nargs = 1, rv32_only = true},
// -------------------------------------------------------------------------
// fcsr / frm / fflags accessors. The read forms use CSRRS+x0; the write
// forms shown keep the old value in rd (rd, rs). Write-only spellings
// (fscsr rs, fsrm rs, fsflags rs, fsrmi imm, fsflagsi imm) default rd = x0
// and are dispatched by argument count — add them if you want those too.
// -------------------------------------------------------------------------
.FRCSR = {target = .CSRRS, src = {.ARG0, .CSR_LIT, .X0, .NONE}, csr = 0x003, nargs = 1},
.FSCSR = {target = .CSRRW, src = {.ARG0, .CSR_LIT, .ARG1, .NONE}, csr = 0x003, nargs = 2},
.FRRM = {target = .CSRRS, src = {.ARG0, .CSR_LIT, .X0, .NONE}, csr = 0x002, nargs = 1},
.FSRM = {target = .CSRRW, src = {.ARG0, .CSR_LIT, .ARG1, .NONE}, csr = 0x002, nargs = 2},
.FRFLAGS = {target = .CSRRS, src = {.ARG0, .CSR_LIT, .X0, .NONE}, csr = 0x001, nargs = 1},
.FSFLAGS = {target = .CSRRW, src = {.ARG0, .CSR_LIT, .ARG1, .NONE}, csr = 0x001, nargs = 2},
.FSRMI = {target = .CSRRWI, src = {.ARG0, .CSR_LIT, .ARG1, .NONE}, csr = 0x002, nargs = 2},
.FSFLAGSI = {target = .CSRRWI, src = {.ARG0, .CSR_LIT, .ARG1, .NONE}, csr = 0x001, nargs = 2},
// -------------------------------------------------------------------------
// FP moves via sign-injection: fmv=SGNJ(rs,rs), fneg=SGNJN, fabs=SGNJX.
// Both source slots are the same user register.
// -------------------------------------------------------------------------
.FMV_S = {target = .FSGNJ_S, src = {.ARG0, .ARG1, .ARG1, .NONE}, nargs = 2},
.FABS_S = {target = .FSGNJX_S, src = {.ARG0, .ARG1, .ARG1, .NONE}, nargs = 2},
.FNEG_S = {target = .FSGNJN_S, src = {.ARG0, .ARG1, .ARG1, .NONE}, nargs = 2},
.FMV_D = {target = .FSGNJ_D, src = {.ARG0, .ARG1, .ARG1, .NONE}, nargs = 2},
.FABS_D = {target = .FSGNJX_D, src = {.ARG0, .ARG1, .ARG1, .NONE}, nargs = 2},
.FNEG_D = {target = .FSGNJN_D, src = {.ARG0, .ARG1, .ARG1, .NONE}, nargs = 2},
.FMV_H = {target = .FSGNJ_H, src = {.ARG0, .ARG1, .ARG1, .NONE}, nargs = 2}, // Zfh
.FABS_H = {target = .FSGNJX_H, src = {.ARG0, .ARG1, .ARG1, .NONE}, nargs = 2}, // Zfh
.FNEG_H = {target = .FSGNJN_H, src = {.ARG0, .ARG1, .ARG1, .NONE}, nargs = 2}, // Zfh
// -------------------------------------------------------------------------
// Bare `fence` == `fence iorw, iorw`; both fence-flag slots take lit = 0xF.
// (This assumes the lit fill applies to every .LIT slot. If your filler is
// single-slot, make FENCE_ALL a special case instead.)
// -------------------------------------------------------------------------
.FENCE_ALL = {target = .FENCE, src = {.LIT, .LIT, .NONE, .NONE}, lit = 0xF, nargs = 0},
}

File diff suppressed because it is too large Load Diff

View File

@@ -331,6 +331,10 @@ flags_lit :: proc(f: lib.Encoding_Flags) -> string {
if f.rv64_only { append(&parts, "rv64_only=true") }
if f.branch { append(&parts, "branch=true") }
if f.fp_round { append(&parts, "fp_round=true") }
if f.explicit_count > 0 {
append(&parts, fmt.tprintf("explicit_count=%d", f.explicit_count))
}
if f.has_implicit { append(&parts, "has_implicit=true") }
return strings.join(parts[:], ", ", context.temp_allocator)
}
@@ -375,9 +379,9 @@ Decode_Entry :: struct #packed {
bits: u32, // 4
mask: u32, // 4
feature: Feature, // 1
flags: Encoding_Flags, // 1
flags: Encoding_Flags, // 2
}
#assert(size_of(Decode_Entry) == 20)
#assert(size_of(Decode_Entry) == 21)
Decode_Index :: struct #packed {
start: u16,

View File

@@ -8,7 +8,7 @@ package rexcode_riscv_generated
import lib "../.."
@(rodata)
DECODE_ENTRIES := [198]lib.Decode_Entry{
DECODE_ENTRIES := [283]lib.Decode_Entry{
{ .LB, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00000003, 0x0000707F, .I, {} },
{ .LH, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00001003, 0x0000707F, .I, {} },
{ .LW, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00002003, 0x0000707F, .I, {} },
@@ -18,11 +18,25 @@ DECODE_ENTRIES := [198]lib.Decode_Entry{
{ .LD, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00003003, 0x0000707F, .I, {rv64_only=true} },
{ .FLW, {.FPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00002007, 0x0000707F, .F, {} },
{ .FLD, {.FPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00003007, 0x0000707F, .D, {} },
{ .FLH, {.FPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00001007, 0x0000707F, .ZFH, {} },
{ .FENCE_I, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x0000100F, 0xFFFFFFFF, .ZIFENCEI, {} },
{ .FENCE, {.FENCE_FLAGS,.FENCE_FLAGS,.NONE,.NONE}, {.FENCE_PRED,.FENCE_SUCC,.NONE,.NONE}, 0x0000000F, 0x0000707F, .I, {} },
{ .CLZ, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x60001013, 0xFFF0707F, .ZBB, {} },
{ .CTZ, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x60101013, 0xFFF0707F, .ZBB, {} },
{ .CPOP, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x60201013, 0xFFF0707F, .ZBB, {} },
{ .SEXT_B, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x60401013, 0xFFF0707F, .ZBB, {} },
{ .SEXT_H, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x60501013, 0xFFF0707F, .ZBB, {} },
{ .ORC_B, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x28705013, 0xFFF0707F, .ZBB, {} },
{ .REV8, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x69805013, 0xFFF0707F, .ZBB, {rv32_only=true} },
{ .REV8, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x6B805013, 0xFFF0707F, .ZBB, {rv64_only=true} },
{ .SLLI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x00001013, 0xFC00707F, .I, {} },
{ .SRLI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x00005013, 0xFC00707F, .I, {} },
{ .SRAI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x40005013, 0xFC00707F, .I, {} },
{ .RORI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x60005013, 0xFC00707F, .ZBB, {} },
{ .BCLRI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x48001013, 0xFC00707F, .ZBS, {} },
{ .BEXTI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x48005013, 0xFC00707F, .ZBS, {} },
{ .BINVI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x68001013, 0xFC00707F, .ZBS, {} },
{ .BSETI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x28001013, 0xFC00707F, .ZBS, {} },
{ .ADDI, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00000013, 0x0000707F, .I, {} },
{ .SLTI, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00002013, 0x0000707F, .I, {} },
{ .SLTIU, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00003013, 0x0000707F, .I, {} },
@@ -30,9 +44,14 @@ DECODE_ENTRIES := [198]lib.Decode_Entry{
{ .ORI, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00006013, 0x0000707F, .I, {} },
{ .ANDI, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x00007013, 0x0000707F, .I, {} },
{ .AUIPC, {.GPR,.IMM20,.NONE,.NONE}, {.RD,.IMM_U,.NONE,.NONE}, 0x00000017, 0x0000007F, .I, {} },
{ .CLZW, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x6000101B, 0xFFF0707F, .ZBB, {rv64_only=true} },
{ .CTZW, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x6010101B, 0xFFF0707F, .ZBB, {rv64_only=true} },
{ .CPOPW, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x6020101B, 0xFFF0707F, .ZBB, {rv64_only=true} },
{ .SLLIW, {.GPR,.GPR,.IMM5,.NONE}, {.RD,.RS1,.SHAMT5,.NONE}, 0x0000101B, 0xFE00707F, .I, {rv64_only=true} },
{ .SRLIW, {.GPR,.GPR,.IMM5,.NONE}, {.RD,.RS1,.SHAMT5,.NONE}, 0x0000501B, 0xFE00707F, .I, {rv64_only=true} },
{ .SRAIW, {.GPR,.GPR,.IMM5,.NONE}, {.RD,.RS1,.SHAMT5,.NONE}, 0x4000501B, 0xFE00707F, .I, {rv64_only=true} },
{ .RORIW, {.GPR,.GPR,.IMM5,.NONE}, {.RD,.RS1,.SHAMT5,.NONE}, 0x6000501B, 0xFE00707F, .ZBB, {rv64_only=true} },
{ .SLLI_UW, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x0800101B, 0xFC00707F, .ZBA, {rv64_only=true} },
{ .ADDIW, {.GPR,.GPR,.IMM12,.NONE}, {.RD,.RS1,.IMM_I,.NONE}, 0x0000001B, 0x0000707F, .I, {rv64_only=true} },
{ .SB, {.GPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00000023, 0x0000707F, .I, {} },
{ .SH, {.GPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00001023, 0x0000707F, .I, {} },
@@ -40,6 +59,7 @@ DECODE_ENTRIES := [198]lib.Decode_Entry{
{ .SD, {.GPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00003023, 0x0000707F, .I, {rv64_only=true} },
{ .FSW, {.FPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00002027, 0x0000707F, .F, {} },
{ .FSD, {.FPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00003027, 0x0000707F, .D, {} },
{ .FSH, {.FPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00001027, 0x0000707F, .ZFH, {} },
{ .LR_W, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_A,.NONE,.NONE}, 0x1000202F, 0xF9F0707F, .A, {} },
{ .LR_D, {.GPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_A,.NONE,.NONE}, 0x1000302F, 0xF9F0707F, .A, {rv64_only=true} },
{ .SC_W, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0x1800202F, 0xF800707F, .A, {} },
@@ -62,6 +82,7 @@ DECODE_ENTRIES := [198]lib.Decode_Entry{
{ .AMOMAX_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0xA000302F, 0xF800707F, .A, {rv64_only=true} },
{ .AMOMINU_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0xC000302F, 0xF800707F, .A, {rv64_only=true} },
{ .AMOMAXU_D, {.GPR,.GPR,.MEM,.NONE}, {.RD,.RS2,.OFFSET_BASE_A,.NONE}, 0xE000302F, 0xF800707F, .A, {rv64_only=true} },
{ .ZEXT_H, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x08004033, 0xFFF0707F, .ZBB, {rv32_only=true} },
{ .ADD, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00000033, 0xFE00707F, .I, {} },
{ .SUB, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x40000033, 0xFE00707F, .I, {} },
{ .SLL, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00001033, 0xFE00707F, .I, {} },
@@ -80,7 +101,29 @@ DECODE_ENTRIES := [198]lib.Decode_Entry{
{ .DIVU, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02005033, 0xFE00707F, .M, {} },
{ .REM, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02006033, 0xFE00707F, .M, {} },
{ .REMU, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02007033, 0xFE00707F, .M, {} },
{ .SH1ADD, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x20002033, 0xFE00707F, .ZBA, {} },
{ .SH2ADD, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x20004033, 0xFE00707F, .ZBA, {} },
{ .SH3ADD, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x20006033, 0xFE00707F, .ZBA, {} },
{ .ANDN, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x40007033, 0xFE00707F, .ZBB, {} },
{ .ORN, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x40006033, 0xFE00707F, .ZBB, {} },
{ .XNOR, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x40004033, 0xFE00707F, .ZBB, {} },
{ .MIN, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A004033, 0xFE00707F, .ZBB, {} },
{ .MINU, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A005033, 0xFE00707F, .ZBB, {} },
{ .MAX, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A006033, 0xFE00707F, .ZBB, {} },
{ .MAXU, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A007033, 0xFE00707F, .ZBB, {} },
{ .ROL, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x60001033, 0xFE00707F, .ZBB, {} },
{ .ROR, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x60005033, 0xFE00707F, .ZBB, {} },
{ .CLMUL, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A001033, 0xFE00707F, .ZBC, {} },
{ .CLMULH, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A003033, 0xFE00707F, .ZBC, {} },
{ .CLMULR, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A002033, 0xFE00707F, .ZBC, {} },
{ .BCLR, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x48001033, 0xFE00707F, .ZBS, {} },
{ .BEXT, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x48005033, 0xFE00707F, .ZBS, {} },
{ .BINV, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x68001033, 0xFE00707F, .ZBS, {} },
{ .BSET, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x28001033, 0xFE00707F, .ZBS, {} },
{ .CZERO_EQZ, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0E005033, 0xFE00707F, .ZICOND, {} },
{ .CZERO_NEZ, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0E007033, 0xFE00707F, .ZICOND, {} },
{ .LUI, {.GPR,.IMM20,.NONE,.NONE}, {.RD,.IMM_U,.NONE,.NONE}, 0x00000037, 0x0000007F, .I, {} },
{ .ZEXT_H, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x0800403B, 0xFFF0707F, .ZBB, {rv64_only=true} },
{ .ADDW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0000003B, 0xFE00707F, .I, {rv64_only=true} },
{ .SUBW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x4000003B, 0xFE00707F, .I, {rv64_only=true} },
{ .SLLW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0000103B, 0xFE00707F, .I, {rv64_only=true} },
@@ -91,42 +134,69 @@ DECODE_ENTRIES := [198]lib.Decode_Entry{
{ .DIVUW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0200503B, 0xFE00707F, .M, {rv64_only=true} },
{ .REMW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0200603B, 0xFE00707F, .M, {rv64_only=true} },
{ .REMUW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0200703B, 0xFE00707F, .M, {rv64_only=true} },
{ .ADD_UW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0800003B, 0xFE00707F, .ZBA, {rv64_only=true} },
{ .SH1ADD_UW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x2000203B, 0xFE00707F, .ZBA, {rv64_only=true} },
{ .SH2ADD_UW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x2000403B, 0xFE00707F, .ZBA, {rv64_only=true} },
{ .SH3ADD_UW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x2000603B, 0xFE00707F, .ZBA, {rv64_only=true} },
{ .ROLW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x6000103B, 0xFE00707F, .ZBB, {rv64_only=true} },
{ .RORW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x6000503B, 0xFE00707F, .ZBB, {rv64_only=true} },
{ .FMADD_S, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x00000043, 0x0600007F, .F, {fp_round=true} },
{ .FMADD_D, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x02000043, 0x0600007F, .D, {fp_round=true} },
{ .FMADD_H, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x04000043, 0x0600007F, .ZFH, {fp_round=true} },
{ .FMSUB_S, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x00000047, 0x0600007F, .F, {fp_round=true} },
{ .FMSUB_D, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x02000047, 0x0600007F, .D, {fp_round=true} },
{ .FMSUB_H, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x04000047, 0x0600007F, .ZFH, {fp_round=true} },
{ .FNMSUB_S, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x0000004B, 0x0600007F, .F, {fp_round=true} },
{ .FNMSUB_D, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x0200004B, 0x0600007F, .D, {fp_round=true} },
{ .FNMSUB_H, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x0400004B, 0x0600007F, .ZFH, {fp_round=true} },
{ .FNMADD_S, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x0000004F, 0x0600007F, .F, {fp_round=true} },
{ .FNMADD_D, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x0200004F, 0x0600007F, .D, {fp_round=true} },
{ .FNMADD_H, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x0400004F, 0x0600007F, .ZFH, {fp_round=true} },
{ .FADD_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x00000053, 0xFE00007F, .F, {fp_round=true} },
{ .FADD_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x02000053, 0xFE00007F, .D, {fp_round=true} },
{ .FADD_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x04000053, 0xFE00007F, .ZFH, {fp_round=true} },
{ .FSUB_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x08000053, 0xFE00007F, .F, {fp_round=true} },
{ .FSUB_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A000053, 0xFE00007F, .D, {fp_round=true} },
{ .FSUB_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0C000053, 0xFE00007F, .ZFH, {fp_round=true} },
{ .FMUL_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x10000053, 0xFE00007F, .F, {fp_round=true} },
{ .FMUL_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x12000053, 0xFE00007F, .D, {fp_round=true} },
{ .FMUL_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x14000053, 0xFE00007F, .ZFH, {fp_round=true} },
{ .FDIV_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x18000053, 0xFE00007F, .F, {fp_round=true} },
{ .FDIV_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x1A000053, 0xFE00007F, .D, {fp_round=true} },
{ .FDIV_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x1C000053, 0xFE00007F, .ZFH, {fp_round=true} },
{ .FSGNJ_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x20000053, 0xFE00707F, .F, {} },
{ .FSGNJN_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x20001053, 0xFE00707F, .F, {} },
{ .FSGNJX_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x20002053, 0xFE00707F, .F, {} },
{ .FSGNJ_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x22000053, 0xFE00707F, .D, {} },
{ .FSGNJN_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x22001053, 0xFE00707F, .D, {} },
{ .FSGNJX_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x22002053, 0xFE00707F, .D, {} },
{ .FSGNJ_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x24000053, 0xFE00707F, .ZFH, {} },
{ .FSGNJN_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x24001053, 0xFE00707F, .ZFH, {} },
{ .FSGNJX_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x24002053, 0xFE00707F, .ZFH, {} },
{ .FMIN_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x28000053, 0xFE00707F, .F, {} },
{ .FMAX_S, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x28001053, 0xFE00707F, .F, {} },
{ .FMIN_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x2A000053, 0xFE00707F, .D, {} },
{ .FMAX_D, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x2A001053, 0xFE00707F, .D, {} },
{ .FMIN_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x2C000053, 0xFE00707F, .ZFH, {} },
{ .FMAX_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x2C001053, 0xFE00707F, .ZFH, {} },
{ .FCVT_S_D, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x40100053, 0xFFF0007F, .D, {fp_round=true} },
{ .FCVT_S_H, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x40200053, 0xFFF0007F, .ZFH, {fp_round=true} },
{ .FCVT_D_S, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x42000053, 0xFFF0007F, .D, {fp_round=true} },
{ .FCVT_D_H, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x42200053, 0xFFF0007F, .ZFH, {fp_round=true} },
{ .FCVT_H_S, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x44000053, 0xFFF0007F, .ZFH, {fp_round=true} },
{ .FCVT_H_D, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x44100053, 0xFFF0007F, .ZFH, {fp_round=true} },
{ .FSQRT_S, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x58000053, 0xFFF0007F, .F, {fp_round=true} },
{ .FSQRT_D, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x5A000053, 0xFFF0007F, .D, {fp_round=true} },
{ .FSQRT_H, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x5C000053, 0xFFF0007F, .ZFH, {fp_round=true} },
{ .FEQ_S, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA0002053, 0xFE00707F, .F, {} },
{ .FLT_S, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA0001053, 0xFE00707F, .F, {} },
{ .FLE_S, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA0000053, 0xFE00707F, .F, {} },
{ .FEQ_D, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA2002053, 0xFE00707F, .D, {} },
{ .FLT_D, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA2001053, 0xFE00707F, .D, {} },
{ .FLE_D, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA2000053, 0xFE00707F, .D, {} },
{ .FEQ_H, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA4002053, 0xFE00707F, .ZFH, {} },
{ .FLT_H, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA4001053, 0xFE00707F, .ZFH, {} },
{ .FLE_H, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA4000053, 0xFE00707F, .ZFH, {} },
{ .FCVT_W_S, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC0000053, 0xFFF0007F, .F, {fp_round=true} },
{ .FCVT_WU_S, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC0100053, 0xFFF0007F, .F, {fp_round=true} },
{ .FCVT_L_S, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC0200053, 0xFFF0007F, .F, {rv64_only=true, fp_round=true} },
@@ -135,6 +205,10 @@ DECODE_ENTRIES := [198]lib.Decode_Entry{
{ .FCVT_WU_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC2100053, 0xFFF0007F, .D, {fp_round=true} },
{ .FCVT_L_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC2200053, 0xFFF0007F, .D, {rv64_only=true, fp_round=true} },
{ .FCVT_LU_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC2300053, 0xFFF0007F, .D, {rv64_only=true, fp_round=true} },
{ .FCVT_W_H, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC4000053, 0xFFF0007F, .ZFH, {fp_round=true} },
{ .FCVT_WU_H, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC4100053, 0xFFF0007F, .ZFH, {fp_round=true} },
{ .FCVT_L_H, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC4200053, 0xFFF0007F, .ZFH, {rv64_only=true, fp_round=true} },
{ .FCVT_LU_H, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC4300053, 0xFFF0007F, .ZFH, {rv64_only=true, fp_round=true} },
{ .FCVT_S_W, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD0000053, 0xFFF0007F, .F, {fp_round=true} },
{ .FCVT_S_WU, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD0100053, 0xFFF0007F, .F, {fp_round=true} },
{ .FCVT_S_L, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD0200053, 0xFFF0007F, .F, {rv64_only=true, fp_round=true} },
@@ -143,12 +217,19 @@ DECODE_ENTRIES := [198]lib.Decode_Entry{
{ .FCVT_D_WU, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD2100053, 0xFFF0007F, .D, {fp_round=true} },
{ .FCVT_D_L, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD2200053, 0xFFF0007F, .D, {rv64_only=true, fp_round=true} },
{ .FCVT_D_LU, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD2300053, 0xFFF0007F, .D, {rv64_only=true, fp_round=true} },
{ .FCVT_H_W, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD4000053, 0xFFF0007F, .ZFH, {fp_round=true} },
{ .FCVT_H_WU, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD4100053, 0xFFF0007F, .ZFH, {fp_round=true} },
{ .FCVT_H_L, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD4200053, 0xFFF0007F, .ZFH, {rv64_only=true, fp_round=true} },
{ .FCVT_H_LU, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD4300053, 0xFFF0007F, .ZFH, {rv64_only=true, fp_round=true} },
{ .FMV_X_W, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xE0000053, 0xFFF0707F, .F, {} },
{ .FCLASS_S, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xE0001053, 0xFFF0707F, .F, {} },
{ .FCLASS_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xE2001053, 0xFFF0707F, .D, {} },
{ .FMV_X_D, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xE2000053, 0xFFF0707F, .D, {rv64_only=true} },
{ .FMV_X_H, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xE4000053, 0xFFF0707F, .ZFH, {} },
{ .FCLASS_H, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xE4001053, 0xFFF0707F, .ZFH, {} },
{ .FMV_W_X, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xF0000053, 0xFFF0707F, .F, {} },
{ .FMV_D_X, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xF2000053, 0xFFF0707F, .D, {rv64_only=true} },
{ .FMV_H_X, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xF4000053, 0xFFF0707F, .ZFH, {} },
{ .BEQ, {.GPR,.GPR,.REL13,.NONE}, {.RS1,.RS2,.IMM_B,.NONE}, 0x00000063, 0x0000707F, .I, {branch=true} },
{ .BNE, {.GPR,.GPR,.REL13,.NONE}, {.RS1,.RS2,.IMM_B,.NONE}, 0x00001063, 0x0000707F, .I, {branch=true} },
{ .BLT, {.GPR,.GPR,.REL13,.NONE}, {.RS1,.RS2,.IMM_B,.NONE}, 0x00004063, 0x0000707F, .I, {branch=true} },
@@ -159,6 +240,10 @@ DECODE_ENTRIES := [198]lib.Decode_Entry{
{ .JAL, {.GPR,.REL21,.NONE,.NONE}, {.RD,.IMM_J,.NONE,.NONE}, 0x0000006F, 0x0000007F, .I, {branch=true} },
{ .ECALL, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x00000073, 0xFFFFFFFF, .I, {branch=true} },
{ .EBREAK, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x00100073, 0xFFFFFFFF, .I, {branch=true} },
{ .MRET, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x30200073, 0xFFFFFFFF, .PRIV, {branch=true} },
{ .SRET, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x10200073, 0xFFFFFFFF, .PRIV, {branch=true} },
{ .WFI, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x10500073, 0xFFFFFFFF, .PRIV, {} },
{ .SFENCE_VMA, {.GPR,.GPR,.NONE,.NONE}, {.RS1,.RS2,.NONE,.NONE}, 0x12000073, 0xFE007FFF, .PRIV, {} },
{ .CSRRW, {.GPR,.CSR,.GPR,.NONE}, {.RD,.CSR_FIELD,.RS1,.NONE}, 0x00001073, 0x0000707F, .ZICSR, {} },
{ .CSRRS, {.GPR,.CSR,.GPR,.NONE}, {.RD,.CSR_FIELD,.RS1,.NONE}, 0x00002073, 0x0000707F, .ZICSR, {} },
{ .CSRRC, {.GPR,.CSR,.GPR,.NONE}, {.RD,.CSR_FIELD,.RS1,.NONE}, 0x00003073, 0x0000707F, .ZICSR, {} },
@@ -212,82 +297,95 @@ DECODE_ENTRIES := [198]lib.Decode_Entry{
@(rodata)
DECODE_INDEX_OPCODE := [128]lib.Decode_Index{
0x03 = { 0, 7},
0x07 = { 7, 2},
0x0F = { 9, 2},
0x13 = { 11, 9},
0x17 = { 20, 1},
0x1B = { 21, 4},
0x23 = { 25, 4},
0x27 = { 29, 2},
0x2F = { 31, 22},
0x33 = { 53, 18},
0x37 = { 71, 1},
0x3B = { 72, 10},
0x43 = { 82, 2},
0x47 = { 84, 2},
0x4B = { 86, 2},
0x4F = { 88, 2},
0x53 = { 90, 50},
0x63 = { 140, 6},
0x67 = { 146, 1},
0x6F = { 147, 1},
0x73 = { 148, 8},
0x07 = { 7, 3},
0x0F = { 10, 2},
0x13 = { 12, 22},
0x17 = { 34, 1},
0x1B = { 35, 9},
0x23 = { 44, 4},
0x27 = { 48, 3},
0x2F = { 51, 22},
0x33 = { 73, 40},
0x37 = { 113, 1},
0x3B = { 114, 17},
0x43 = { 131, 3},
0x47 = { 134, 3},
0x4B = { 137, 3},
0x4F = { 140, 3},
0x53 = { 143, 78},
0x63 = { 221, 6},
0x67 = { 227, 1},
0x6F = { 228, 1},
0x73 = { 229, 12},
}
@(rodata)
DECODE_INDEX_OP_FP := [128]lib.Decode_Index{
0x00 = { 90, 1},
0x01 = { 91, 1},
0x04 = { 92, 1},
0x05 = { 93, 1},
0x08 = { 94, 1},
0x09 = { 95, 1},
0x0C = { 96, 1},
0x0D = { 97, 1},
0x10 = { 98, 3},
0x11 = { 101, 3},
0x14 = { 104, 2},
0x15 = { 106, 2},
0x20 = { 108, 1},
0x21 = { 109, 1},
0x2C = { 110, 1},
0x2D = { 111, 1},
0x50 = { 112, 3},
0x51 = { 115, 3},
0x60 = { 118, 4},
0x61 = { 122, 4},
0x68 = { 126, 4},
0x69 = { 130, 4},
0x70 = { 134, 2},
0x71 = { 136, 2},
0x78 = { 138, 1},
0x79 = { 139, 1},
0x00 = { 143, 1},
0x01 = { 144, 1},
0x02 = { 145, 1},
0x04 = { 146, 1},
0x05 = { 147, 1},
0x06 = { 148, 1},
0x08 = { 149, 1},
0x09 = { 150, 1},
0x0A = { 151, 1},
0x0C = { 152, 1},
0x0D = { 153, 1},
0x0E = { 154, 1},
0x10 = { 155, 3},
0x11 = { 158, 3},
0x12 = { 161, 3},
0x14 = { 164, 2},
0x15 = { 166, 2},
0x16 = { 168, 2},
0x20 = { 170, 2},
0x21 = { 172, 2},
0x22 = { 174, 2},
0x2C = { 176, 1},
0x2D = { 177, 1},
0x2E = { 178, 1},
0x50 = { 179, 3},
0x51 = { 182, 3},
0x52 = { 185, 3},
0x60 = { 188, 4},
0x61 = { 192, 4},
0x62 = { 196, 4},
0x68 = { 200, 4},
0x69 = { 204, 4},
0x6A = { 208, 4},
0x70 = { 212, 2},
0x71 = { 214, 2},
0x72 = { 216, 2},
0x78 = { 218, 1},
0x79 = { 219, 1},
0x7A = { 220, 1},
}
@(rodata)
DECODE_INDEX_RVC := [32]lib.Decode_Index{
0x00 = { 156, 1},
0x01 = { 157, 2},
0x02 = { 159, 1},
0x04 = { 160, 1},
0x05 = { 161, 2},
0x06 = { 163, 1},
0x08 = { 164, 1},
0x09 = { 165, 1},
0x0A = { 166, 1},
0x0C = { 167, 2},
0x0D = { 169, 2},
0x0E = { 171, 2},
0x11 = { 173, 9},
0x12 = { 182, 5},
0x14 = { 187, 1},
0x15 = { 188, 1},
0x16 = { 189, 1},
0x18 = { 190, 1},
0x19 = { 191, 1},
0x1A = { 192, 1},
0x1C = { 193, 2},
0x1D = { 195, 1},
0x1E = { 196, 2},
0x00 = { 241, 1},
0x01 = { 242, 2},
0x02 = { 244, 1},
0x04 = { 245, 1},
0x05 = { 246, 2},
0x06 = { 248, 1},
0x08 = { 249, 1},
0x09 = { 250, 1},
0x0A = { 251, 1},
0x0C = { 252, 2},
0x0D = { 254, 2},
0x0E = { 256, 2},
0x11 = { 258, 9},
0x12 = { 267, 5},
0x14 = { 272, 1},
0x15 = { 273, 1},
0x16 = { 274, 1},
0x18 = { 275, 1},
0x19 = { 276, 1},
0x1A = { 277, 1},
0x1C = { 278, 2},
0x1D = { 280, 1},
0x1E = { 281, 2},
}

File diff suppressed because it is too large Load Diff

View File

@@ -687,4 +687,326 @@ INSTRUCTION_TABLE := [Mnemonic][]Form{
.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}},
},
// =========================================================================
// §7 Zba — address generation. Pure dataflow, no flags, no traps.
// =========================================================================
.SH1ADD = {
{{.SH1ADD, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x20002033, MASK_R, .ZBA, {}}, {written={0}, read={1, 2}}},
},
.SH2ADD = {
{{.SH2ADD, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x20004033, MASK_R, .ZBA, {}}, {written={0}, read={1, 2}}},
},
.SH3ADD = {
{{.SH3ADD, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x20006033, MASK_R, .ZBA, {}}, {written={0}, read={1, 2}}},
},
// *.UW forms zero-extend rs1's low word; RV64-only by construction.
.ADD_UW = {
{{.ADD_UW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0800003B, MASK_R, .ZBA, {rv64_only=true}}, {written={0}, read={1, 2}}},
},
.SH1ADD_UW = {
{{.SH1ADD_UW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x2000203B, MASK_R, .ZBA, {rv64_only=true}}, {written={0}, read={1, 2}}},
},
.SH2ADD_UW = {
{{.SH2ADD_UW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x2000403B, MASK_R, .ZBA, {rv64_only=true}}, {written={0}, read={1, 2}}},
},
.SH3ADD_UW = {
{{.SH3ADD_UW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x2000603B, MASK_R, .ZBA, {rv64_only=true}}, {written={0}, read={1, 2}}},
},
// SLLI.UW: OP-IMM-32 opcode but a 6-bit shamt (funct6 @31-26 = 000010).
.SLLI_UW = {
{{.SLLI_UW, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x0800101B, MASK_OPCODE | MASK_FUNCT3 | 0xFC000000, .ZBA, {rv64_only=true}}, {written={0}, read={1}}},
},
// =========================================================================
// §8 Zbb — basic bit-manipulation. All pure dataflow, no flags, no traps.
// =========================================================================
// Logic with negated operand (R-type)
.ANDN = {
{{.ANDN, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x40007033, MASK_R, .ZBB, {}}, {written={0}, read={1, 2}}},
},
.ORN = {
{{.ORN, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x40006033, MASK_R, .ZBB, {}}, {written={0}, read={1, 2}}},
},
.XNOR = {
{{.XNOR, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x40004033, MASK_R, .ZBB, {}}, {written={0}, read={1, 2}}},
},
// Count leading/trailing zeros, popcount (unary; rs2 is a selector)
.CLZ = {
{{.CLZ, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x60001013, MASK_OPCODE | MASK_FUNCT3 | MASK_FUNCT7 | MASK_RS2, .ZBB, {}}, {written={0}, read={1}}},
},
.CTZ = {
{{.CTZ, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x60101013, MASK_OPCODE | MASK_FUNCT3 | MASK_FUNCT7 | MASK_RS2, .ZBB, {}}, {written={0}, read={1}}},
},
.CPOP = {
{{.CPOP, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x60201013, MASK_OPCODE | MASK_FUNCT3 | MASK_FUNCT7 | MASK_RS2, .ZBB, {}}, {written={0}, read={1}}},
},
// Sign/zero extend (unary)
.SEXT_B = {
{{.SEXT_B, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x60401013, MASK_OPCODE | MASK_FUNCT3 | MASK_FUNCT7 | MASK_RS2, .ZBB, {}}, {written={0}, read={1}}},
},
.SEXT_H = {
{{.SEXT_H, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x60501013, MASK_OPCODE | MASK_FUNCT3 | MASK_FUNCT7 | MASK_RS2, .ZBB, {}}, {written={0}, read={1}}},
},
// ZEXT.H differs by base: OP (0x33) on RV32, OP-32 (0x3B) on RV64.
// Two forms in one slice keeps the same mnemonic valid on both.
.ZEXT_H = {
{{.ZEXT_H, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x08004033, MASK_OPCODE | MASK_FUNCT3 | MASK_FUNCT7 | MASK_RS2, .ZBB, {rv32_only=true}}, {written={0}, read={1}}},
{{.ZEXT_H, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x0800403B, MASK_OPCODE | MASK_FUNCT3 | MASK_FUNCT7 | MASK_RS2, .ZBB, {rv64_only=true}}, {written={0}, read={1}}},
},
// Min / max (R-type)
.MIN = {
{{.MIN, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A004033, MASK_R, .ZBB, {}}, {written={0}, read={1, 2}}},
},
.MINU = {
{{.MINU, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A005033, MASK_R, .ZBB, {}}, {written={0}, read={1, 2}}},
},
.MAX = {
{{.MAX, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A006033, MASK_R, .ZBB, {}}, {written={0}, read={1, 2}}},
},
.MAXU = {
{{.MAXU, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A007033, MASK_R, .ZBB, {}}, {written={0}, read={1, 2}}},
},
// Rotate (R-type) + rotate-immediate (6-bit funct6 shift-imm)
.ROL = {
{{.ROL, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x60001033, MASK_R, .ZBB, {}}, {written={0}, read={1, 2}}},
},
.ROR = {
{{.ROR, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x60005033, MASK_R, .ZBB, {}}, {written={0}, read={1, 2}}},
},
.RORI = {
{{.RORI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x60005013, MASK_OPCODE | MASK_FUNCT3 | 0xFC000000, .ZBB, {}}, {written={0}, read={1}}},
},
// Byte-granule ops (unary)
.ORC_B = {
{{.ORC_B, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x28705013, MASK_OPCODE | MASK_FUNCT3 | MASK_FUNCT7 | MASK_RS2, .ZBB, {}}, {written={0}, read={1}}},
},
// REV8 byte-reverse: RV32 uses funct7=0110100, RV64 uses 0110101 (imm[11:0]
// widens with XLEN). Two forms cover both bases.
.REV8 = {
{{.REV8, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x69805013, MASK_OPCODE | MASK_FUNCT3 | MASK_FUNCT7 | MASK_RS2, .ZBB, {rv32_only=true}}, {written={0}, read={1}}},
{{.REV8, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x6B805013, MASK_OPCODE | MASK_FUNCT3 | MASK_FUNCT7 | MASK_RS2, .ZBB, {rv64_only=true}}, {written={0}, read={1}}},
},
// Word variants — RV64 only
.CLZW = {
{{.CLZW, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x6000101B, MASK_OPCODE | MASK_FUNCT3 | MASK_FUNCT7 | MASK_RS2, .ZBB, {rv64_only=true}}, {written={0}, read={1}}},
},
.CTZW = {
{{.CTZW, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x6010101B, MASK_OPCODE | MASK_FUNCT3 | MASK_FUNCT7 | MASK_RS2, .ZBB, {rv64_only=true}}, {written={0}, read={1}}},
},
.CPOPW = {
{{.CPOPW, {.GPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x6020101B, MASK_OPCODE | MASK_FUNCT3 | MASK_FUNCT7 | MASK_RS2, .ZBB, {rv64_only=true}}, {written={0}, read={1}}},
},
.ROLW = {
{{.ROLW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x6000103B, MASK_R, .ZBB, {rv64_only=true}}, {written={0}, read={1, 2}}},
},
.RORW = {
{{.RORW, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x6000503B, MASK_R, .ZBB, {rv64_only=true}}, {written={0}, read={1, 2}}},
},
// RORIW: OP-IMM-32 with a 5-bit shamt, so funct7 is fully fixed (MASK_R).
.RORIW = {
{{.RORIW, {.GPR,.GPR,.IMM5,.NONE}, {.RD,.RS1,.SHAMT5,.NONE}, 0x6000501B, MASK_R, .ZBB, {rv64_only=true}}, {written={0}, read={1}}},
},
// =========================================================================
// §9 Zbc — carry-less multiply. Pure dataflow.
// =========================================================================
.CLMUL = {
{{.CLMUL, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A001033, MASK_R, .ZBC, {}}, {written={0}, read={1, 2}}},
},
.CLMULH = {
{{.CLMULH, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A003033, MASK_R, .ZBC, {}}, {written={0}, read={1, 2}}},
},
.CLMULR = {
{{.CLMULR, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0A002033, MASK_R, .ZBC, {}}, {written={0}, read={1, 2}}},
},
// =========================================================================
// §10 Zbs — single-bit ops. Register and 6-bit-immediate forms.
// =========================================================================
.BCLR = {
{{.BCLR, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x48001033, MASK_R, .ZBS, {}}, {written={0}, read={1, 2}}},
},
.BCLRI = {
{{.BCLRI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x48001013, MASK_OPCODE | MASK_FUNCT3 | 0xFC000000, .ZBS, {}}, {written={0}, read={1}}},
},
.BEXT = {
{{.BEXT, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x48005033, MASK_R, .ZBS, {}}, {written={0}, read={1, 2}}},
},
.BEXTI = {
{{.BEXTI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x48005013, MASK_OPCODE | MASK_FUNCT3 | 0xFC000000, .ZBS, {}}, {written={0}, read={1}}},
},
.BINV = {
{{.BINV, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x68001033, MASK_R, .ZBS, {}}, {written={0}, read={1, 2}}},
},
.BINVI = {
{{.BINVI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x68001013, MASK_OPCODE | MASK_FUNCT3 | 0xFC000000, .ZBS, {}}, {written={0}, read={1}}},
},
.BSET = {
{{.BSET, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x28001033, MASK_R, .ZBS, {}}, {written={0}, read={1, 2}}},
},
.BSETI = {
{{.BSETI, {.GPR,.GPR,.IMM6,.NONE}, {.RD,.RS1,.SHAMT6,.NONE}, 0x28001013, MASK_OPCODE | MASK_FUNCT3 | 0xFC000000, .ZBS, {}}, {written={0}, read={1}}},
},
// =========================================================================
// §11 Zicond — conditional zero. rd = (cond on rs2) ? 0 : rs1.
// =========================================================================
.CZERO_EQZ = {
{{.CZERO_EQZ, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0E005033, MASK_R, .ZICOND, {}}, {written={0}, read={1, 2}}},
},
.CZERO_NEZ = {
{{.CZERO_NEZ, {.GPR,.GPR,.GPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0E007033, MASK_R, .ZICOND, {}}, {written={0}, read={1, 2}}},
},
// =========================================================================
// §12 Zfh (half-precision, binary16) — mirrors §5 with fmt=10 (bits 26-25).
// reads_frm == encoding fp_round, exactly as in the F/D sections.
// =========================================================================
.FLH = {
{{.FLH, {.FPR,.MEM,.NONE,.NONE}, {.RD,.OFFSET_BASE_I,.NONE,.NONE}, 0x00001007, MASK_I, .ZFH, {}}, {written={0}, read={1}, reads_mem=true}},
},
.FSH = {
{{.FSH, {.FPR,.MEM,.NONE,.NONE}, {.RS2,.OFFSET_BASE_S,.NONE,.NONE}, 0x00001027, MASK_S, .ZFH, {}}, {read={0, 1}, writes_mem=true}},
},
.FMADD_H = {
{{.FMADD_H, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x04000043, 0x0600007F, .ZFH, {fp_round=true}}, {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}},
},
.FMSUB_H = {
{{.FMSUB_H, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x04000047, 0x0600007F, .ZFH, {fp_round=true}}, {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}},
},
.FNMSUB_H = {
{{.FNMSUB_H, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x0400004B, 0x0600007F, .ZFH, {fp_round=true}}, {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}},
},
.FNMADD_H = {
{{.FNMADD_H, {.FPR,.FPR,.FPR,.FPR}, {.RD,.RS1,.RS2,.RS3}, 0x0400004F, 0x0600007F, .ZFH, {fp_round=true}}, {written={0}, read={1, 2, 3}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}},
},
.FADD_H = {
{{.FADD_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x04000053, MASK_OPCODE | MASK_FUNCT7, .ZFH, {fp_round=true}}, {written={0}, read={1, 2}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}},
},
.FSUB_H = {
{{.FSUB_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x0C000053, MASK_OPCODE | MASK_FUNCT7, .ZFH, {fp_round=true}}, {written={0}, read={1, 2}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}},
},
.FMUL_H = {
{{.FMUL_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x14000053, MASK_OPCODE | MASK_FUNCT7, .ZFH, {fp_round=true}}, {written={0}, read={1, 2}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}},
},
.FDIV_H = {
{{.FDIV_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x1C000053, MASK_OPCODE | MASK_FUNCT7, .ZFH, {fp_round=true}}, {written={0}, read={1, 2}, fflags_wr={.NV, .DZ, .OF, .UF, .NX}, reads_frm=true}},
},
.FSQRT_H = {
{{.FSQRT_H, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x5C000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .ZFH, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}},
},
.FSGNJ_H = {
{{.FSGNJ_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x24000053, MASK_R, .ZFH, {}}, {written={0}, read={1, 2}}},
},
.FSGNJN_H = {
{{.FSGNJN_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x24001053, MASK_R, .ZFH, {}}, {written={0}, read={1, 2}}},
},
.FSGNJX_H = {
{{.FSGNJX_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x24002053, MASK_R, .ZFH, {}}, {written={0}, read={1, 2}}},
},
.FMIN_H = {
{{.FMIN_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x2C000053, MASK_R, .ZFH, {}}, {written={0}, read={1, 2}, fflags_wr={.NV}}},
},
.FMAX_H = {
{{.FMAX_H, {.FPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0x2C001053, MASK_R, .ZFH, {}}, {written={0}, read={1, 2}, fflags_wr={.NV}}},
},
// Half <-> integer conversions. Int->half can overflow the narrow range,
// so those carry OF alongside NX.
.FCVT_W_H = {
{{.FCVT_W_H, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC4000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .ZFH, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}},
},
.FCVT_WU_H = {
{{.FCVT_WU_H, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC4100053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .ZFH, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}},
},
.FCVT_L_H = {
{{.FCVT_L_H, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC4200053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .ZFH, {fp_round=true, rv64_only=true}}, {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}},
},
.FCVT_LU_H = {
{{.FCVT_LU_H, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xC4300053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .ZFH, {fp_round=true, rv64_only=true}}, {written={0}, read={1}, fflags_wr={.NV, .NX}, reads_frm=true}},
},
.FCVT_H_W = {
{{.FCVT_H_W, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD4000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .ZFH, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.OF, .NX}, reads_frm=true}},
},
.FCVT_H_WU = {
{{.FCVT_H_WU, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD4100053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .ZFH, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.OF, .NX}, reads_frm=true}},
},
.FCVT_H_L = {
{{.FCVT_H_L, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD4200053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .ZFH, {fp_round=true, rv64_only=true}}, {written={0}, read={1}, fflags_wr={.OF, .NX}, reads_frm=true}},
},
.FCVT_H_LU = {
{{.FCVT_H_LU, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xD4300053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .ZFH, {fp_round=true, rv64_only=true}}, {written={0}, read={1}, fflags_wr={.OF, .NX}, reads_frm=true}},
},
// Half <-> single/double. Widening (H->S, H->D) is value-exact -> {.NV}
// only; narrowing (S->H, D->H) can round -> full flag set. Requires F/D.
.FCVT_S_H = {
{{.FCVT_S_H, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x40200053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .ZFH, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NV}, reads_frm=true}},
},
.FCVT_H_S = {
{{.FCVT_H_S, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x44000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .ZFH, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}},
},
.FCVT_D_H = {
{{.FCVT_D_H, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x42200053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .ZFH, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NV}, reads_frm=true}},
},
.FCVT_H_D = {
{{.FCVT_H_D, {.FPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0x44100053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2, .ZFH, {fp_round=true}}, {written={0}, read={1}, fflags_wr={.NV, .OF, .UF, .NX}, reads_frm=true}},
},
// Bit-pattern move / classify (no rounding, no flags)
.FMV_X_H = {
{{.FMV_X_H, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xE4000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2 | MASK_FUNCT3, .ZFH, {}}, {written={0}, read={1}}},
},
.FMV_H_X = {
{{.FMV_H_X, {.FPR,.GPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xF4000053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2 | MASK_FUNCT3, .ZFH, {}}, {written={0}, read={1}}},
},
.FCLASS_H = {
{{.FCLASS_H, {.GPR,.FPR,.NONE,.NONE}, {.RD,.RS1,.NONE,.NONE}, 0xE4001053, MASK_OPCODE | MASK_FUNCT7 | MASK_RS2 | MASK_FUNCT3, .ZFH, {}}, {written={0}, read={1}}},
},
// Comparisons -> GPR result; only NV possible.
.FEQ_H = {
{{.FEQ_H, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA4002053, MASK_R, .ZFH, {}}, {written={0}, read={1, 2}, fflags_wr={.NV}}},
},
.FLT_H = {
{{.FLT_H, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA4001053, MASK_R, .ZFH, {}}, {written={0}, read={1, 2}, fflags_wr={.NV}}},
},
.FLE_H = {
{{.FLE_H, {.GPR,.FPR,.FPR,.NONE}, {.RD,.RS1,.RS2,.NONE}, 0xA4000053, MASK_R, .ZFH, {}}, {written={0}, read={1, 2}, fflags_wr={.NV}}},
},
// =========================================================================
// §13 Privileged — trap-return + TLB maintenance (SYSTEM opcode, 0x73).
// MRET/SRET/WFI are fully fixed 32-bit words (mask 0xFFFFFFFF, no operands).
// =========================================================================
.MRET = {
{{.MRET, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x30200073, 0xFFFFFFFF, .PRIV, {branch=true}}, {side_effects={.CONTROL}}},
},
.SRET = {
{{.SRET, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x10200073, 0xFFFFFFFF, .PRIV, {branch=true}}, {side_effects={.CONTROL}}},
},
// WFI: wait-for-interrupt hint. No PC redirect and no register effects in the
// architectural sense; execution resumes after the wakeup event.
.WFI = {
{{.WFI, {.NONE,.NONE,.NONE,.NONE}, {.NONE,.NONE,.NONE,.NONE}, 0x10500073, 0xFFFFFFFF, .PRIV, {}}, {}},
},
// SFENCE.VMA rs1(vaddr), rs2(asid): both operands optional (x0 = "all").
// Reads rs1/rs2; acts as an address-translation ordering fence.
.SFENCE_VMA = {
{{.SFENCE_VMA, {.GPR,.GPR,.NONE,.NONE}, {.RS1,.RS2,.NONE,.NONE}, 0x12000073, MASK_OPCODE | MASK_FUNCT3 | MASK_FUNCT7 | MASK_RD, .PRIV, {}}, {read={0, 1}, side_effects={.FENCE}}},
},
}

View File

@@ -30,9 +30,9 @@ Decode_Entry :: struct #packed {
bits: u32, // 4
mask: u32, // 4
feature: Feature, // 1
flags: Encoding_Flags, // 1
flags: Encoding_Flags, // 2
}
#assert(size_of(Decode_Entry) == 20)
#assert(size_of(Decode_Entry) == 21)
Decode_Index :: struct #packed {
start: u16,

View File

@@ -338,6 +338,24 @@ main :: proc() {
}
""")
strings.write_string(&sb, "\n");
strings.write_string(&sb, "\n");
strings.write_string(&sb, """
struct PseudoAlias {
Mnemonic target;
};
enum PseudoMnemonic : u16 {
PM_INVALID,
PSEUDO_MNEMONIC_COUNT
};
PseudoMnemonic pseudo_mnemonic_lookup(String const &name) {
return PM_INVALID;
}
PseudoAlias pseudo_alias(PseudoMnemonic pm) {
return {};
}
""")
strings.write_string(&sb, "\tstatic u16 const register_codes [REG_COUNT];\n")