pub(crate) mod a;
pub(crate) mod b;
pub(crate) mod c;
pub(crate) mod d;
pub(crate) mod f;
pub(crate) mod h;
pub(crate) mod i;
pub(crate) mod m;
pub(crate) mod pseudo;
pub(crate) mod q;
pub(crate) mod system;
pub(crate) mod v;
pub(crate) mod zawrs;
pub(crate) mod zcb;
pub(crate) mod zfa;
pub(crate) mod zfh;
pub(crate) mod zicbo;
pub(crate) mod zicond;
pub(crate) mod zimop;
use crate::Isa;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum Codec {
Li,
CssSqsp,
CssSdsp,
CssSwsp,
CsSq,
CsSd,
CsSw,
Cs,
CrJr,
CrJalr,
CrMv,
Cr,
ClLq,
ClLd,
ClLw,
ClB,
ClH,
CsB,
CsH,
CuRd,
CjJal,
Cj,
Ciw4spn,
CiNone,
CiLui,
CiLi,
CiLqsp,
CiLdsp,
CiLwsp,
Ci16sp,
CiSh6,
Ci,
CbSh6,
CbImm,
Cb,
RF,
RL,
RA,
R4M,
RM,
R,
SB,
S,
ICsr,
ISh7,
ISh6,
ISh5,
I,
Uj,
U,
None,
Illegal,
V,
Vu,
Vu6,
VsetVli,
VsetIvli,
}
pub(crate) mod fmt {
pub(crate) const NONE: &str = "";
pub(crate) const RS1: &str = "1";
pub(crate) const OFFSET: &str = "o";
pub(crate) const PRED_SUCC: &str = "p,s";
pub(crate) const RS1_RS2: &str = "1,2";
pub(crate) const RD_IMM: &str = "0,i";
pub(crate) const RD_UIMM: &str = "0,u";
pub(crate) const RD_OFFSET: &str = "0,o";
pub(crate) const RD_RS1_RS2: &str = "0,1,2";
pub(crate) const FRD_RS1: &str = "3,1";
pub(crate) const FRD_FRS1: &str = "3,4";
pub(crate) const RD_FRS1: &str = "0,4";
pub(crate) const RD_FRS1_FRS2: &str = "0,4,5";
pub(crate) const FRD_FRS1_FRS2: &str = "3,4,5";
pub(crate) const RM_FRD_FRS1: &str = "3,4r";
pub(crate) const RM_FRD_RS1: &str = "3,1r";
pub(crate) const RM_RD_FRS1: &str = "0,4r";
pub(crate) const RM_FRD_FRS1_FRS2: &str = "3,4,5r";
pub(crate) const RM_FRD_FRS1_FRS2_FRS3: &str = "3,4,5,6r";
pub(crate) const RD_RS1_IMM: &str = "0,1,i";
pub(crate) const RD_RS1_SHAMT: &str = "0,1,>";
pub(crate) const RD_OFFSET_RS1: &str = "0,i(1)";
pub(crate) const FRD_OFFSET_RS1: &str = "3,i(1)";
pub(crate) const RD_CSR_RS1: &str = "0,c,1";
pub(crate) const RD_CSR_ZIMM: &str = "0,c,7";
pub(crate) const RS2_OFFSET_RS1: &str = "2,i(1)";
pub(crate) const FRS2_OFFSET_RS1: &str = "5,i(1)";
pub(crate) const RS1_RS2_OFFSET: &str = "1,2,o";
pub(crate) const RD_RS2_ADDR_RS1: &str = "0,2,(1)";
pub(crate) const RD_ADDR_RS1: &str = "0,(1)";
pub(crate) const RD: &str = "0";
pub(crate) const RD_ZIMM: &str = "0,7";
pub(crate) const RD_RS1: &str = "0,1";
pub(crate) const RD_RS2: &str = "0,2";
pub(crate) const RS1_OFFSET: &str = "1,o";
pub(crate) const RS2_OFFSET: &str = "2,o";
pub(crate) const OFFSET_RS1: &str = "i(1)";
pub(crate) const RD_SHAMT: &str = "0,>";
pub(crate) const RD_CSR: &str = "0,c";
pub(crate) const CSR_RS1: &str = "c,1";
pub(crate) const CSR_ZIMM: &str = "c,7";
pub(crate) const IMM: &str = "i";
pub(crate) const WIDEN_FRD_FRS1: &str = "3,4R";
pub(crate) const WIDEN_FRD_RS1: &str = "3,1R";
pub(crate) const INSN: &str = "l, x";
pub(crate) const RAW: &str = "x";
pub(crate) const ADDR_RS1: &str = "(1)";
pub(crate) const RS2: &str = "2";
pub(crate) const RS2_ADDR_RS1: &str = "2,(1)";
pub(crate) const UIMM: &str = "u";
pub(crate) const FRD_FLI: &str = "3,F";
pub(crate) const FRD_RS1_RS2: &str = "3,1,2";
pub(crate) const PREFETCH: &str = "P(1)";
}
#[derive(Clone, Copy, Debug)]
pub(crate) enum Constraint {
RdEq(u8),
Rs1Eq(u8),
Rs2Eq(u8),
Rs2EqRs1,
RdEqRs1,
ImmEq(i32),
ImmMaskEq(i32, i32),
CsrEq(i32),
}
pub(crate) struct Pseudo {
pub(crate) op: &'static Opcode,
pub(crate) when: &'static [Constraint],
}
impl Pseudo {
pub(crate) const fn new(op: &'static Opcode, when: &'static [Constraint]) -> Self {
Pseudo { op, when }
}
}
pub(crate) struct MaskedOpcode {
pub(crate) bits: u32,
pub(crate) mask: u32,
pub(crate) op: Opcode,
}
pub(crate) const fn masked(bits: u32, mask: u32, op: Opcode) -> MaskedOpcode {
MaskedOpcode { bits, mask, op }
}
pub(crate) fn lookup_masked(table: &'static [MaskedOpcode], inst: u64) -> Option<&'static Opcode> {
let inst = inst as u32;
table
.iter()
.find(|e| inst & e.mask == e.bits)
.map(|e| &e.op)
}
pub(crate) struct Opcode {
pub(crate) name: &'static str,
pub(crate) codec: Codec,
pub(crate) format: &'static str,
pub(crate) pseudo: &'static [Pseudo],
pub(crate) decompress: [Option<&'static Opcode>; 3],
pub(crate) illegal_if: &'static [Constraint],
pub(crate) hint_if: &'static [Constraint],
pub(crate) isas: u8,
}
impl Opcode {
pub(crate) const fn new(name: &'static str, codec: Codec, format: &'static str) -> Self {
Opcode {
name,
codec,
format,
pseudo: &[],
decompress: [None; 3],
illegal_if: &[],
hint_if: &[],
isas: 0b111,
}
}
pub(crate) const fn rv64(self) -> Self {
Opcode {
isas: 0b110,
..self
}
}
pub(crate) const fn rv32_only(self) -> Self {
Opcode {
isas: 0b001,
..self
}
}
pub(crate) const fn rv64_only(self) -> Self {
Opcode {
isas: 0b010,
..self
}
}
pub(crate) const fn rv128(self) -> Self {
Opcode {
isas: 0b100,
..self
}
}
pub(crate) fn exists_in(&self, isa: Isa) -> bool {
match self.decompress {
[None, None, None] => self.isas & (1 << isa as u8) != 0,
expansions => expansions[isa as usize].is_some_and(|e| e.exists_in(isa)),
}
}
}
impl PartialEq for Opcode {
fn eq(&self, other: &Self) -> bool {
core::ptr::eq(self, other)
}
}
impl Eq for Opcode {}
impl core::fmt::Debug for Opcode {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(self.name)
}
}
pub(crate) static ILLEGAL: Opcode = Opcode::new(".insn", Codec::Illegal, fmt::INSN);
pub(crate) static RESERVED_PARCEL: Opcode = Opcode::new(".2byte", Codec::Illegal, fmt::RAW);