#[cfg(feature = "vendor-corev")]
use crate::opcodes::xcv;
#[cfg(feature = "vendor-thead")]
use crate::opcodes::xthead;
use crate::opcodes::{
MaskedOpcode, Opcode, a, b, c, d, f, h, i, m, q, system, zabha, zalasr, zawrs, zcb, zcmp, zfa,
zfbfmin, zfh, zicbo, zicond, zilsd, zimop, zk,
};
#[cfg(feature = "vector")]
use crate::opcodes::{lookup_masked, v};
use crate::{Extension, Extensions, Isa};
fn compressed_0(isa: Isa, exts: Extensions, inst: u64) -> Option<&'static Opcode> {
let pairs = isa == Isa::Rv32 && exts.contains(Extension::Zclsd);
match (inst >> 13) & 7 {
0 if inst == 0 => Some(&c::C_UNIMP),
0 => Some(&c::C_ADDI4SPN),
1 => Some(if isa == Isa::Rv128 {
&c::C_LQ
} else {
&c::C_FLD
}),
2 => Some(&c::C_LW),
3 if pairs => Some(&zilsd::C_LD),
3 => Some(if isa == Isa::Rv32 {
&c::C_FLW
} else {
&c::C_LD
}),
4 => match ((inst >> 10) & 7, (inst >> 6) & 1) {
(0, _) => Some(&zcb::C_LBU),
(1, 0) => Some(&zcb::C_LHU),
(1, _) => Some(&zcb::C_LH),
(2, _) => Some(&zcb::C_SB),
(3, 0) => Some(&zcb::C_SH),
_ => None,
},
5 => Some(if isa == Isa::Rv128 {
&c::C_SQ
} else {
&c::C_FSD
}),
6 => Some(&c::C_SW),
7 if pairs => Some(&zilsd::C_SD),
7 => Some(if isa == Isa::Rv32 {
&c::C_FSW
} else {
&c::C_SD
}),
_ => None,
}
}
fn compressed_1(isa: Isa, inst: u64) -> Option<&'static Opcode> {
match (inst >> 13) & 7 {
0 => Some(match ((inst >> 7) & 0x1f, inst & 0x107c) {
(0, 0) => &c::C_NOP,
(0, _) => &c::C_NOP_HINT,
_ => &c::C_ADDI,
}),
1 => Some(if isa == Isa::Rv32 {
&c::C_JAL
} else {
&c::C_ADDIW
}),
2 => Some(&c::C_LI),
3 => Some(match (inst >> 7) & 0x1f {
2 => &c::C_ADDI16SP,
rd if rd & 1 == 1 && rd < 16 && inst & 0x107c == 0 => &zimop::C_MOP[rd as usize / 2],
_ => &c::C_LUI,
}),
4 => match (inst >> 10) & 3 {
0 => Some(&c::C_SRLI),
1 => Some(&c::C_SRAI),
2 => Some(&c::C_ANDI),
3 => match (inst >> 10) & 4 | (inst >> 5) & 3 {
0 => Some(&c::C_SUB),
1 => Some(&c::C_XOR),
2 => Some(&c::C_OR),
3 => Some(&c::C_AND),
4 => Some(&c::C_SUBW),
5 => Some(&c::C_ADDW),
6 => Some(&zcb::C_MUL),
7 => match (inst >> 2) & 7 {
0 => Some(&zcb::C_ZEXT_B),
1 => Some(&zcb::C_SEXT_B),
2 => Some(&zcb::C_ZEXT_H),
3 => Some(&zcb::C_SEXT_H),
4 => Some(&zcb::C_ZEXT_W),
5 => Some(&zcb::C_NOT),
_ => None,
},
_ => None,
},
_ => None,
},
5 => Some(&c::C_J),
6 => Some(&c::C_BEQZ),
7 => Some(&c::C_BNEZ),
_ => None,
}
}
fn compressed_2(isa: Isa, exts: Extensions, inst: u64) -> Option<&'static Opcode> {
let pairs = isa == Isa::Rv32 && exts.contains(Extension::Zclsd);
Some(match (inst >> 13) & 7 {
0 => &c::C_SLLI,
1 => {
if isa == Isa::Rv128 {
&c::C_LQSP
} else {
&c::C_FLDSP
}
}
2 => &c::C_LWSP,
3 if pairs => &zilsd::C_LDSP,
3 => {
if isa == Isa::Rv32 {
&c::C_FLWSP
} else {
&c::C_LDSP
}
}
4 => match (inst >> 12) & 1 {
0 => match (inst >> 2) & 0x1f {
0 => &c::C_JR,
_ => &c::C_MV,
},
1 => match (inst >> 2) & 0x1f {
0 => match (inst >> 7) & 0x1f {
0 => &c::C_EBREAK,
_ => &c::C_JALR,
},
_ => &c::C_ADD,
},
_ => return None,
},
5 if exts.contains(Extension::Zcmp) || exts.contains(Extension::Zcmt) => {
return push_pop_and_table_jumps(exts, inst);
}
5 => {
if isa == Isa::Rv128 {
&c::C_SQSP
} else {
&c::C_FSDSP
}
}
6 => &c::C_SWSP,
7 if pairs => &zilsd::C_SDSP,
7 => {
if isa == Isa::Rv32 {
&c::C_FSWSP
} else {
&c::C_SDSP
}
}
_ => return None,
})
}
fn load(isa: Isa, inst: u64) -> Option<&'static Opcode> {
Some(match (inst >> 12) & 7 {
0 => &i::LB,
1 => &i::LH,
2 => &i::LW,
3 if isa == Isa::Rv32 => &zilsd::LD,
3 => &i::LD,
4 => &i::LBU,
5 => &i::LHU,
6 => &i::LWU,
7 => &i::LDU,
_ => return None,
})
}
fn load_fp(inst: u64) -> Option<&'static Opcode> {
match (inst >> 12) & 7 {
1 => Some(&zfh::FLH),
2 => Some(&f::FLW),
3 => Some(&d::FLD),
4 => Some(&q::FLQ),
#[cfg(feature = "vector")]
_ => lookup_masked(&v::LOAD_FP, inst),
#[cfg(not(feature = "vector"))]
_ => None,
}
}
fn misc_mem(isa: Isa, inst: u64) -> Option<&'static Opcode> {
match (inst >> 12) & 7 {
0 if inst >> 20 == 0x833 => Some(&i::FENCE_TSO),
0 => Some(&i::FENCE),
1 => Some(&i::FENCE_I),
2 if isa == Isa::Rv128 => Some(&i::LQ),
2 if (inst >> 7) & 0x1f == 0 => match inst >> 20 {
0 => Some(&zicbo::CBO_INVAL),
1 => Some(&zicbo::CBO_CLEAN),
2 => Some(&zicbo::CBO_FLUSH),
4 => Some(&zicbo::CBO_ZERO),
_ => None,
},
_ => None,
}
}
fn crypto_op_imm(inst: u64) -> Option<&'static Opcode> {
Some(match ((inst >> 12) & 7, inst >> 20) {
(1, 0x08f) => &zk::ZIP,
(5, 0x08f) => &zk::UNZIP,
(5, 0x687) => &zk::BREV8,
(1, 0x100) => &zk::SHA256SUM0,
(1, 0x101) => &zk::SHA256SUM1,
(1, 0x102) => &zk::SHA256SIG0,
(1, 0x103) => &zk::SHA256SIG1,
(1, 0x104) => &zk::SHA512SUM0,
(1, 0x105) => &zk::SHA512SUM1,
(1, 0x106) => &zk::SHA512SIG0,
(1, 0x107) => &zk::SHA512SIG1,
(1, 0x108) => &zk::SM3P0,
(1, 0x109) => &zk::SM3P1,
(1, 0x300) => &zk::AES64IM,
(1, imm) if imm >> 4 == 0x31 => &zk::AES64KS1I,
_ => return None,
})
}
fn crypto_op(inst: u64) -> Option<&'static Opcode> {
if (inst >> 12) & 7 != 0 {
return None;
}
let funct7 = inst >> 25;
Some(match (funct7 & 0x1f, funct7) {
(0b10001, _) => &zk::AES32ESI,
(0b10011, _) => &zk::AES32ESMI,
(0b10101, _) => &zk::AES32DSI,
(0b10111, _) => &zk::AES32DSMI,
(0b11000, _) => &zk::SM4ED,
(0b11010, _) => &zk::SM4KS,
(_, 0x19) => &zk::AES64ES,
(_, 0x1b) => &zk::AES64ESM,
(_, 0x1d) => &zk::AES64DS,
(_, 0x1f) => &zk::AES64DSM,
(_, 0x3f) => &zk::AES64KS2,
(_, 0x28) => &zk::SHA512SUM0R,
(_, 0x29) => &zk::SHA512SUM1R,
(_, 0x2a) => &zk::SHA512SIG0L,
(_, 0x2e) => &zk::SHA512SIG0H,
(_, 0x2b) => &zk::SHA512SIG1L,
(_, 0x2f) => &zk::SHA512SIG1H,
_ => return None,
})
}
fn op_imm(isa: Isa, inst: u64) -> Option<&'static Opcode> {
if let Some(op) = crypto_op_imm(inst) {
return Some(op);
}
match (inst >> 12) & 7 {
0 => Some(&i::ADDI),
1 => {
if (inst >> 27) & 0x1f == 0 {
Some(&i::SLLI)
} else if inst >> 20 == 0x600 {
Some(&b::CLZ)
} else if inst >> 20 == 0x601 {
Some(&b::CTZ)
} else if inst >> 20 == 0x602 {
Some(&b::CPOP)
} else if inst >> 20 == 0x604 {
Some(&b::SEXT_B)
} else if inst >> 20 == 0x605 {
Some(&b::SEXT_H)
} else {
match isa {
Isa::Rv32 => match (inst >> 25) & 0x7f {
0x14 => Some(&b::BSETI),
0x24 => Some(&b::BCLRI),
0x34 => Some(&b::BINVI),
_ => None,
},
Isa::Rv64 => match (inst >> 26) & 0x3f {
0xa => Some(&b::BSET_64),
0x12 => Some(&b::BCLRI_64),
0x1a => Some(&b::BINVI_64),
_ => None,
},
_ => None,
}
}
}
2 => Some(&i::SLTI),
3 => Some(&i::SLTIU),
4 => Some(&i::XORI),
5 => {
if inst >> 20 == 0x287 {
Some(&b::ORC_B)
} else if (isa == Isa::Rv32 && inst >> 20 == 0x698)
|| (isa == Isa::Rv64 && inst >> 20 == 0x6b8)
{
Some(&b::REV8)
} else if isa == Isa::Rv32 && inst >> 25 == 0x30 {
Some(&b::RORI)
} else if isa == Isa::Rv64 && inst >> 26 == 0x18 {
Some(&b::RORI_64)
} else {
match (inst >> 27) & 0x1f {
0 => Some(&i::SRLI),
8 => Some(&i::SRAI),
9 => match isa {
Isa::Rv32 if (inst >> 25) & 0x7f == 0x24 => Some(&b::BEXTI),
Isa::Rv64 if (inst >> 26) & 0x3f == 0x12 => Some(&b::BEXTI_64),
_ => None,
},
_ => None,
}
}
}
6 => Some(&i::ORI),
7 => Some(&i::ANDI),
_ => None,
}
}
fn op_imm_32(inst: u64) -> Option<&'static Opcode> {
match (inst >> 12) & 7 {
0 => Some(&i::ADDIW),
1 => {
if (inst >> 26) & 0x3f == 2 {
Some(&b::SLLI_UW)
} else if (inst >> 25) & 0x7f == 0 {
Some(&i::SLLIW)
} else if inst >> 20 == 0x600 {
Some(&b::CLZW)
} else if inst >> 20 == 0x601 {
Some(&b::CTZW)
} else if inst >> 20 == 0x602 {
Some(&b::CPOPW)
} else {
None
}
}
5 => match (inst >> 25) & 0x7f {
0 => Some(&i::SRLIW),
32 => Some(&i::SRAIW),
48 => Some(&b::RORIW),
_ => None,
},
_ => None,
}
}
fn store(isa: Isa, inst: u64) -> Option<&'static Opcode> {
match (inst >> 12) & 7 {
0 => Some(&i::SB),
1 => Some(&i::SH),
2 => Some(&i::SW),
3 if isa == Isa::Rv32 => Some(&zilsd::SD),
3 => Some(&i::SD),
4 => Some(&i::SQ),
_ => None,
}
}
fn store_fp(inst: u64) -> Option<&'static Opcode> {
match (inst >> 12) & 7 {
1 => Some(&zfh::FSH),
2 => Some(&f::FSW),
3 => Some(&d::FSD),
4 => Some(&q::FSQ),
#[cfg(feature = "vector")]
_ => lookup_masked(&v::STORE_FP, inst),
#[cfg(not(feature = "vector"))]
_ => None,
}
}
fn amo(isa: Isa, inst: u64) -> Option<&'static Opcode> {
match (inst >> 24) & 0xf8 | (inst >> 12) & 7 {
2 => Some(&a::AMOADD_W),
3 => Some(&a::AMOADD_D),
4 => Some(&a::AMOADD_Q),
10 => Some(&a::AMOSWAP_W),
11 => Some(&a::AMOSWAP_D),
12 => Some(&a::AMOSWAP_Q),
18 => {
if (inst >> 20) & 0x1f == 0 {
Some(&a::LR_W)
} else {
None
}
}
19 => {
if (inst >> 20) & 0x1f == 0 {
Some(&a::LR_D)
} else {
None
}
}
20 => {
if (inst >> 20) & 0x1f == 0 {
Some(&a::LR_Q)
} else {
None
}
}
26 => Some(&a::SC_W),
27 => Some(&a::SC_D),
28 => Some(&a::SC_Q),
34 => Some(&a::AMOXOR_W),
8 => Some(&zabha::AMOSWAP_B),
9 => Some(&zabha::AMOSWAP_H),
0 => Some(&zabha::AMOADD_B),
1 => Some(&zabha::AMOADD_H),
32 => Some(&zabha::AMOXOR_B),
33 => Some(&zabha::AMOXOR_H),
96 => Some(&zabha::AMOAND_B),
97 => Some(&zabha::AMOAND_H),
64 => Some(&zabha::AMOOR_B),
65 => Some(&zabha::AMOOR_H),
128 => Some(&zabha::AMOMIN_B),
129 => Some(&zabha::AMOMIN_H),
160 => Some(&zabha::AMOMAX_B),
161 => Some(&zabha::AMOMAX_H),
192 => Some(&zabha::AMOMINU_B),
193 => Some(&zabha::AMOMINU_H),
224 => Some(&zabha::AMOMAXU_B),
225 => Some(&zabha::AMOMAXU_H),
40 => Some(&zabha::AMOCAS_B),
41 => Some(&zabha::AMOCAS_H),
42 => Some(&zabha::AMOCAS_W),
43 if isa == Isa::Rv32 => Some(&zabha::AMOCAS_D_RV32),
43 => Some(&zabha::AMOCAS_D),
44 => Some(&zabha::AMOCAS_Q),
48..=51 if (inst >> 26) & 1 == 1 && (inst >> 20) & 0x1f == 0 => Some(
[
&zalasr::LB_AQ,
&zalasr::LH_AQ,
&zalasr::LW_AQ,
&zalasr::LD_AQ,
][(inst >> 12 & 3) as usize],
),
56..=59 if (inst >> 25) & 1 == 1 && (inst >> 7) & 0x1f == 0 => Some(
[
&zalasr::SB_RL,
&zalasr::SH_RL,
&zalasr::SW_RL,
&zalasr::SD_RL,
][(inst >> 12 & 3) as usize],
),
74 => Some(&zimop::SSAMOSWAP_W),
75 => Some(&zimop::SSAMOSWAP_D),
35 => Some(&a::AMOXOR_D),
36 => Some(&a::AMOXOR_Q),
66 => Some(&a::AMOOR_W),
67 => Some(&a::AMOOR_D),
68 => Some(&a::AMOOR_Q),
98 => Some(&a::AMOAND_W),
99 => Some(&a::AMOAND_D),
100 => Some(&a::AMOAND_Q),
130 => Some(&a::AMOMIN_W),
131 => Some(&a::AMOMIN_D),
132 => Some(&a::AMOMIN_Q),
162 => Some(&a::AMOMAX_W),
163 => Some(&a::AMOMAX_D),
164 => Some(&a::AMOMAX_Q),
194 => Some(&a::AMOMINU_W),
195 => Some(&a::AMOMINU_D),
196 => Some(&a::AMOMINU_Q),
226 => Some(&a::AMOMAXU_W),
227 => Some(&a::AMOMAXU_D),
228 => Some(&a::AMOMAXU_Q),
_ => None,
}
}
fn op(isa: Isa, inst: u64) -> Option<&'static Opcode> {
if let Some(op) = crypto_op(inst) {
return Some(op);
}
match (inst >> 22) & 0x3f8 | (inst >> 12) & 7 {
0 => Some(&i::ADD),
1 => Some(&i::SLL),
2 => Some(&i::SLT),
3 => Some(&i::SLTU),
4 => Some(&i::XOR),
5 => Some(&i::SRL),
6 => Some(&i::OR),
7 => Some(&i::AND),
8 => Some(&m::MUL),
9 => Some(&m::MULH),
10 => Some(&m::MULHSU),
11 => Some(&m::MULHU),
12 => Some(&m::DIV),
13 => Some(&m::DIVU),
14 => Some(&m::REM),
15 => Some(&m::REMU),
36 if isa == Isa::Rv32 && inst >> 20 == 0x080 => Some(&b::ZEXT_H),
36 => Some(&zk::PACK),
39 => Some(&zk::PACKH),
162 => Some(&zk::XPERM4),
164 => Some(&zk::XPERM8),
41 => Some(&b::CLMUL),
42 => Some(&b::CLMULR),
43 => Some(&b::CLMULH),
44 => Some(&b::MIN),
45 => Some(&b::MINU),
46 => Some(&b::MAX),
47 => Some(&b::MAXU),
61 => Some(&zicond::CZERO_EQZ),
63 => Some(&zicond::CZERO_NEZ),
130 => Some(&b::SH1ADD),
132 => Some(&b::SH2ADD),
134 => Some(&b::SH3ADD),
161 => Some(&b::BSET),
256 => Some(&i::SUB),
260 => Some(&b::XNOR),
261 => Some(&i::SRA),
262 => Some(&b::ORN),
263 => Some(&b::ANDN),
289 => Some(&b::BCLR),
293 => Some(&b::BEXT),
385 => Some(&b::ROL),
389 => Some(&b::ROR),
417 => Some(&b::BINV),
_ => None,
}
}
fn op_32(inst: u64) -> Option<&'static Opcode> {
match (inst >> 22) & 0x3f8 | (inst >> 12) & 7 {
0 => Some(&i::ADDW),
1 => Some(&i::SLLW),
5 => Some(&i::SRLW),
8 => Some(&m::MULW),
12 => Some(&m::DIVW),
13 => Some(&m::DIVUW),
14 => Some(&m::REMW),
15 => Some(&m::REMUW),
32 => Some(&b::ADD_UW),
36 if inst >> 20 == 0x080 => Some(&b::ZEXT_H),
36 => Some(&zk::PACKW),
130 => Some(&b::SH1ADD_UW),
132 => Some(&b::SH2ADD_UW),
134 => Some(&b::SH3ADD_UW),
256 => Some(&i::SUBW),
261 => Some(&i::SRAW),
385 => Some(&b::ROLW),
389 => Some(&b::RORW),
_ => None,
}
}
fn madd(inst: u64) -> Option<&'static Opcode> {
match (inst >> 25) & 3 {
0 => Some(&f::FMADD_S),
1 => Some(&d::FMADD_D),
2 => Some(&zfh::FMADD_H),
3 => Some(&q::FMADD_Q),
_ => None,
}
}
fn msub(inst: u64) -> Option<&'static Opcode> {
match (inst >> 25) & 3 {
0 => Some(&f::FMSUB_S),
1 => Some(&d::FMSUB_D),
2 => Some(&zfh::FMSUB_H),
3 => Some(&q::FMSUB_Q),
_ => None,
}
}
fn nmsub(inst: u64) -> Option<&'static Opcode> {
match (inst >> 25) & 3 {
0 => Some(&f::FNMSUB_S),
1 => Some(&d::FNMSUB_D),
2 => Some(&zfh::FNMSUB_H),
3 => Some(&q::FNMSUB_Q),
_ => None,
}
}
fn nmadd(inst: u64) -> Option<&'static Opcode> {
match (inst >> 25) & 3 {
0 => Some(&f::FNMADD_S),
1 => Some(&d::FNMADD_D),
2 => Some(&zfh::FNMADD_H),
3 => Some(&q::FNMADD_Q),
_ => None,
}
}
fn op_fp(inst: u64) -> Option<&'static Opcode> {
match ((inst >> 25) & 0x7f, (inst >> 20) & 0x1f, (inst >> 12) & 7) {
(120, 1, 0) => Some(&zfa::FLI_S),
(20, _, 2) => Some(&zfa::FMINM_S),
(20, _, 3) => Some(&zfa::FMAXM_S),
(32, 4, _) => Some(&zfa::FROUND_S),
(32, 5, _) => Some(&zfa::FROUNDNX_S),
(80, _, 4) => Some(&zfa::FLEQ_S),
(80, _, 5) => Some(&zfa::FLTQ_S),
(121, 1, 0) => Some(&zfa::FLI_D),
(21, _, 2) => Some(&zfa::FMINM_D),
(21, _, 3) => Some(&zfa::FMAXM_D),
(33, 4, _) => Some(&zfa::FROUND_D),
(33, 5, _) => Some(&zfa::FROUNDNX_D),
(81, _, 4) => Some(&zfa::FLEQ_D),
(81, _, 5) => Some(&zfa::FLTQ_D),
(122, 1, 0) => Some(&zfa::FLI_H),
(22, _, 2) => Some(&zfa::FMINM_H),
(22, _, 3) => Some(&zfa::FMAXM_H),
(34, 4, _) => Some(&zfa::FROUND_H),
(34, 5, _) => Some(&zfa::FROUNDNX_H),
(82, _, 4) => Some(&zfa::FLEQ_H),
(82, _, 5) => Some(&zfa::FLTQ_H),
(123, 1, 0) => Some(&zfa::FLI_Q),
(23, _, 2) => Some(&zfa::FMINM_Q),
(23, _, 3) => Some(&zfa::FMAXM_Q),
(35, 4, _) => Some(&zfa::FROUND_Q),
(35, 5, _) => Some(&zfa::FROUNDNX_Q),
(83, _, 4) => Some(&zfa::FLEQ_Q),
(83, _, 5) => Some(&zfa::FLTQ_Q),
(97, 8, 1) => Some(&zfa::FCVTMOD_W_D),
(113, 1, 0) => Some(&zfa::FMVH_X_D),
(89, _, 0) => Some(&zfa::FMVP_D_X),
(115, 1, 0) => Some(&zfa::FMVH_X_Q),
(91, _, 0) => Some(&zfa::FMVP_Q_X),
(0, _, _) => Some(&f::FADD_S),
(2, _, _) => Some(&zfh::FADD_H),
(6, _, _) => Some(&zfh::FSUB_H),
(10, _, _) => Some(&zfh::FMUL_H),
(14, _, _) => Some(&zfh::FDIV_H),
(18, _, 0) => Some(&zfh::FSGNJ_H),
(18, _, 1) => Some(&zfh::FSGNJN_H),
(18, _, 2) => Some(&zfh::FSGNJX_H),
(22, _, 0) => Some(&zfh::FMIN_H),
(22, _, 1) => Some(&zfh::FMAX_H),
(32, 2, _) => Some(&zfh::FCVT_S_H),
(33, 2, _) => Some(&zfh::FCVT_D_H),
(35, 2, _) => Some(&zfh::FCVT_Q_H),
(34, 0, _) => Some(&zfh::FCVT_H_S),
(34, 8, _) => Some(&zfbfmin::FCVT_BF16_S),
(32, 6, _) => Some(&zfbfmin::FCVT_S_BF16),
(34, 1, _) => Some(&zfh::FCVT_H_D),
(34, 3, _) => Some(&zfh::FCVT_H_Q),
(46, 0, _) => Some(&zfh::FSQRT_H),
(82, _, 0) => Some(&zfh::FLE_H),
(82, _, 1) => Some(&zfh::FLT_H),
(82, _, 2) => Some(&zfh::FEQ_H),
(98, 0, _) => Some(&zfh::FCVT_W_H),
(98, 1, _) => Some(&zfh::FCVT_WU_H),
(98, 2, _) => Some(&zfh::FCVT_L_H),
(98, 3, _) => Some(&zfh::FCVT_LU_H),
(106, 0, _) => Some(&zfh::FCVT_H_W),
(106, 1, _) => Some(&zfh::FCVT_H_WU),
(106, 2, _) => Some(&zfh::FCVT_H_L),
(106, 3, _) => Some(&zfh::FCVT_H_LU),
(114, 0, 0) => Some(&zfh::FMV_X_H),
(114, 0, 1) => Some(&zfh::FCLASS_H),
(122, 0, 0) => Some(&zfh::FMV_H_X),
(1, _, _) => Some(&d::FADD_D),
(3, _, _) => Some(&q::FADD_Q),
(4, _, _) => Some(&f::FSUB_S),
(5, _, _) => Some(&d::FSUB_D),
(7, _, _) => Some(&q::FSUB_Q),
(8, _, _) => Some(&f::FMUL_S),
(9, _, _) => Some(&d::FMUL_D),
(11, _, _) => Some(&q::FMUL_Q),
(12, _, _) => Some(&f::FDIV_S),
(13, _, _) => Some(&d::FDIV_D),
(15, _, _) => Some(&q::FDIV_Q),
(16, _, 0) => Some(&f::FSGNJ_S),
(16, _, 1) => Some(&f::FSGNJN_S),
(16, _, 2) => Some(&f::FSGNJX_S),
(17, _, 0) => Some(&d::FSGNJ_D),
(17, _, 1) => Some(&d::FSGNJN_D),
(17, _, 2) => Some(&d::FSGNJX_D),
(19, _, 0) => Some(&q::FSGNJ_Q),
(19, _, 1) => Some(&q::FSGNJN_Q),
(19, _, 2) => Some(&q::FSGNJX_Q),
(20, _, 0) => Some(&f::FMIN_S),
(20, _, 1) => Some(&f::FMAX_S),
(21, _, 0) => Some(&d::FMIN_D),
(21, _, 1) => Some(&d::FMAX_D),
(23, _, 0) => Some(&q::FMIN_Q),
(23, _, 1) => Some(&q::FMAX_Q),
(32, 1, _) => Some(&d::FCVT_S_D),
(32, 3, _) => Some(&q::FCVT_S_Q),
(33, 0, _) => Some(&d::FCVT_D_S),
(33, 3, _) => Some(&q::FCVT_D_Q),
(35, 0, _) => Some(&q::FCVT_Q_S),
(35, 1, _) => Some(&q::FCVT_Q_D),
(44, 0, _) => Some(&f::FSQRT_S),
(45, 0, _) => Some(&d::FSQRT_D),
(47, 0, _) => Some(&q::FSQRT_Q),
(80, _, 0) => Some(&f::FLE_S),
(80, _, 1) => Some(&f::FLT_S),
(80, _, 2) => Some(&f::FEQ_S),
(81, _, 0) => Some(&d::FLE_D),
(81, _, 1) => Some(&d::FLT_D),
(81, _, 2) => Some(&d::FEQ_D),
(83, _, 0) => Some(&q::FLE_Q),
(83, _, 1) => Some(&q::FLT_Q),
(83, _, 2) => Some(&q::FEQ_Q),
(96, 0, _) => Some(&f::FCVT_W_S),
(96, 1, _) => Some(&f::FCVT_WU_S),
(96, 2, _) => Some(&f::FCVT_L_S),
(96, 3, _) => Some(&f::FCVT_LU_S),
(97, 0, _) => Some(&d::FCVT_W_D),
(97, 1, _) => Some(&d::FCVT_WU_D),
(97, 2, _) => Some(&d::FCVT_L_D),
(97, 3, _) => Some(&d::FCVT_LU_D),
(99, 0, _) => Some(&q::FCVT_W_Q),
(99, 1, _) => Some(&q::FCVT_WU_Q),
(99, 2, _) => Some(&q::FCVT_L_Q),
(99, 3, _) => Some(&q::FCVT_LU_Q),
(104, 0, _) => Some(&f::FCVT_S_W),
(104, 1, _) => Some(&f::FCVT_S_WU),
(104, 2, _) => Some(&f::FCVT_S_L),
(104, 3, _) => Some(&f::FCVT_S_LU),
(105, 0, _) => Some(&d::FCVT_D_W),
(105, 1, _) => Some(&d::FCVT_D_WU),
(105, 2, _) => Some(&d::FCVT_D_L),
(105, 3, _) => Some(&d::FCVT_D_LU),
(107, 0, _) => Some(&q::FCVT_Q_W),
(107, 1, _) => Some(&q::FCVT_Q_WU),
(107, 2, _) => Some(&q::FCVT_Q_L),
(107, 3, _) => Some(&q::FCVT_Q_LU),
(112, _, _) => match (inst >> 17) & 0xf8 | (inst >> 12) & 7 {
0 => Some(&f::FMV_X_W),
1 => Some(&f::FCLASS_S),
_ => None,
},
(113, _, _) => match (inst >> 17) & 0xf8 | (inst >> 12) & 7 {
0 => Some(&d::FMV_X_D),
1 => Some(&d::FCLASS_D),
_ => None,
},
(115, _, _) => match (inst >> 17) & 0xf8 | (inst >> 12) & 7 {
0 => Some(&q::FMV_X_Q),
1 => Some(&q::FCLASS_Q),
_ => None,
},
(120, _, _) => {
if (inst >> 17) & 0xf8 | (inst >> 12) & 7 == 0 {
Some(&f::FMV_W_X)
} else {
None
}
}
(121, _, _) => {
if (inst >> 17) & 0xf8 | (inst >> 12) & 7 == 0 {
Some(&d::FMV_D_X)
} else {
None
}
}
(123, _, _) => {
if (inst >> 17) & 0xf8 | (inst >> 12) & 7 == 0 {
Some(&q::FMV_Q_X)
} else {
None
}
}
_ => None,
}
}
fn custom2_rv128(inst: u64) -> Option<&'static Opcode> {
match (inst >> 12) & 7 {
0 => Some(&i::ADDID),
1 => {
if (inst >> 26) & 0x3f == 0 {
Some(&i::SLLID)
} else {
None
}
}
5 => match (inst >> 26) & 0x3f {
0 => Some(&i::SRLID),
16 => Some(&i::SRAID),
_ => None,
},
_ => None,
}
}
fn branch(inst: u64) -> Option<&'static Opcode> {
match (inst >> 12) & 7 {
0 => Some(&i::BEQ),
1 => Some(&i::BNE),
4 => Some(&i::BLT),
5 => Some(&i::BGE),
6 => Some(&i::BLTU),
7 => Some(&i::BGEU),
_ => None,
}
}
fn jalr(inst: u64) -> Option<&'static Opcode> {
if (inst >> 12) & 7 == 0 {
Some(&i::JALR)
} else {
None
}
}
fn system_inst(inst: u64) -> Option<&'static Opcode> {
match (inst >> 12) & 7 {
0 => match inst {
0x0000_0073 => Some(&system::ECALL),
0x0010_0073 => Some(&system::EBREAK),
0x00d0_0073 => Some(&zawrs::WRS_NTO),
0x01d0_0073 => Some(&zawrs::WRS_STO),
0x1020_0073 => Some(&system::SRET),
0x1050_0073 => Some(&system::WFI),
0x3020_0073 => Some(&system::MRET),
0x7b20_0073 => Some(&system::DRET),
0x1040_0073 => Some(&system::SCTRCLR),
0x1800_0073 => Some(&system::SFENCE_W_INVAL),
0x1810_0073 => Some(&system::SFENCE_INVAL_IR),
0x7020_0073 => Some(&system::MNRET),
_ if inst & 0x7fff == 0x0073 => match inst >> 25 {
0x09 => Some(&system::SFENCE_VMA),
0x0b => Some(&system::SINVAL_VMA),
0x11 => Some(&h::HFENCE_VVMA),
0x13 => Some(&h::HINVAL_VVMA),
0x31 => Some(&h::HFENCE_GVMA),
0x33 => Some(&h::HINVAL_GVMA),
_ => None,
},
_ => None,
},
1 => Some(&system::CSRRW),
4 if inst >> 31 == 0 => match (inst >> 25, (inst >> 20) & 0x1f, (inst >> 7) & 0x1f) {
(0x30, 0, _) => Some(&h::HLV_B),
(0x30, 1, _) => Some(&h::HLV_BU),
(0x32, 0, _) => Some(&h::HLV_H),
(0x32, 1, _) => Some(&h::HLV_HU),
(0x32, 3, _) => Some(&h::HLVX_HU),
(0x34, 0, _) => Some(&h::HLV_W),
(0x34, 1, _) => Some(&h::HLV_WU),
(0x34, 3, _) => Some(&h::HLVX_WU),
(0x36, 0, _) => Some(&h::HLV_D),
(0x31, _, 0) => Some(&h::HSV_B),
(0x33, _, 0) => Some(&h::HSV_H),
(0x35, _, 0) => Some(&h::HSV_W),
(0x37, _, 0) => Some(&h::HSV_D),
_ => None,
},
4 if inst & 0xb000_0000 == 0x8000_0000 => {
let n = (inst >> 30 & 1) << 2 | (inst >> 26 & 3);
match (inst >> 22) & 0xf {
0b0111 => Some(&zimop::MOP_R[(n << 2 | (inst >> 20 & 3)) as usize]),
0b1000..=0b1111 => Some(&zimop::MOP_RR[n as usize]),
_ => None,
}
}
2 => Some(&system::CSRRS),
3 => Some(&system::CSRRC),
5 => Some(&system::CSRRWI),
6 => Some(&system::CSRRSI),
7 => Some(&system::CSRRCI),
_ => None,
}
}
fn custom3_rv128(inst: u64) -> Option<&'static Opcode> {
match (inst >> 22) & 0x3f8 | (inst >> 12) & 7 {
0 => Some(&i::ADDD),
1 => Some(&i::SLLD),
5 => Some(&i::SRLD),
8 => Some(&m::MULD),
12 => Some(&m::DIVD),
13 => Some(&m::DIVUD),
14 => Some(&m::REMD),
15 => Some(&m::REMUD),
256 => Some(&i::SUBD),
261 => Some(&i::SRAD),
_ => None,
}
}
fn custom(exts: Extensions, inst: u64) -> Option<&'static Opcode> {
let tables: &[&'static [MaskedOpcode]] = &[
#[cfg(feature = "vendor-thead")]
&xthead::CUSTOM_0,
#[cfg(feature = "vendor-corev")]
&xcv::CUSTOM,
];
tables
.iter()
.copied()
.flatten()
.find(|e| inst as u32 & e.mask == e.bits && e.op.provided_by(exts))
.map(|e| &e.op)
}
fn uncompressed(isa: Isa, exts: Extensions, inst: u64) -> Option<&'static Opcode> {
match (inst >> 2) & 0x1f {
0 => load(isa, inst),
1 => load_fp(inst),
3 => misc_mem(isa, inst),
4 => op_imm(isa, inst),
5 => Some(&i::AUIPC),
6 => {
if isa == Isa::Rv64 {
op_imm_32(inst)
} else {
None
}
}
8 => store(isa, inst),
9 => store_fp(inst),
11 => amo(isa, inst),
12 => op(isa, inst),
13 => Some(&i::LUI),
14 => {
if isa == Isa::Rv64 {
op_32(inst)
} else {
None
}
}
16 => madd(inst),
17 => msub(inst),
18 => nmsub(inst),
19 => nmadd(inst),
20 => op_fp(inst),
#[cfg(feature = "vector")]
21 => lookup_masked(&v::OP_V, inst),
#[cfg(feature = "vector")]
29 => lookup_masked(&v::OP_VE, inst),
22 if isa == Isa::Rv128 => custom2_rv128(inst),
30 if isa == Isa::Rv128 => custom3_rv128(inst),
2 | 10 | 22 | 30 => custom(exts, inst),
24 => branch(inst),
25 => jalr(inst),
27 => Some(&i::JAL),
28 => system_inst(inst),
_ => None,
}
}
fn push_pop_and_table_jumps(exts: Extensions, inst: u64) -> Option<&'static Opcode> {
if (inst >> 10) & 7 == 0 {
let op = if (inst >> 2) & 0xff < 32 {
&zcmp::CM_JT
} else {
&zcmp::CM_JALT
};
return exts.contains(Extension::Zcmt).then_some(op);
}
if !exts.contains(Extension::Zcmp) {
return None;
}
match ((inst >> 8) & 0x1f, (inst >> 5) & 3) {
(0x18, _) => Some(&zcmp::CM_PUSH),
(0x1a, _) => Some(&zcmp::CM_POP),
(0x1c, _) => Some(&zcmp::CM_POPRETZ),
(0x1e, _) => Some(&zcmp::CM_POPRET),
(field, 1) if field >> 2 == 3 => Some(&zcmp::CM_MVSA01),
(field, 3) if field >> 2 == 3 => Some(&zcmp::CM_MVA01S),
_ => None,
}
}
pub(super) fn lookup(isa: Isa, exts: Extensions, inst: u64) -> Option<&'static Opcode> {
match inst & 3 {
0 => compressed_0(isa, exts, inst),
1 => compressed_1(isa, inst),
2 => compressed_2(isa, exts, inst),
_ => uncompressed(isa, exts, inst),
}
}