ab_riscv_primitives/instructions/
zvbc.rs1#[cfg(test)]
4mod tests;
5
6use crate::instructions::Instruction;
7use crate::instructions::v::Eew;
8use crate::instructions::v::zvexx::arith::ZveXxArithInstruction;
9use crate::instructions::v::zvexx::carry::ZveXxCarryInstruction;
10use crate::instructions::v::zvexx::config::ZveXxConfigInstruction;
11use crate::instructions::v::zvexx::fixed_point::ZveXxFixedPointInstruction;
12use crate::instructions::v::zvexx::load::{LoadStoreNreg, Nf, SegVmNf, ZveXxLoadInstruction};
13use crate::instructions::v::zvexx::mask::ZveXxMaskInstruction;
14use crate::instructions::v::zvexx::muldiv::ZveXxMulDivInstruction;
15use crate::instructions::v::zvexx::perm::ZveXxPermInstruction;
16use crate::instructions::v::zvexx::reduction::ZveXxReductionInstruction;
17use crate::instructions::v::zvexx::store::ZveXxStoreInstruction;
18use crate::instructions::v::zvexx::widen_narrow::ZveXxWidenNarrowInstruction;
19use crate::instructions::zicsr::ZicsrInstruction;
20use crate::registers::general_purpose::Register;
21use crate::registers::vector::VReg;
22use ab_riscv_macros::instruction;
23use core::fmt;
24
25#[instruction(
40 inherit = [ZveXxInstruction],
41)]
42#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43#[rustfmt::skip]
44pub enum ZvbcInstruction<Reg> {
45 VclmulVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
48 VclmulVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
50 VclmulhVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
53 VclmulhVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
55}
56
57#[instruction]
58const impl<Reg> Instruction for ZvbcInstruction<Reg>
59where
60 Reg: [const] Register,
61{
62 type Reg = Reg;
63
64 #[inline(always)]
65 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
66 fn try_decode(instruction: u32) -> Option<Self> {
67 let opcode = (instruction & 0b111_1111) as u8;
68 if opcode != 0b101_0111 {
69 None?;
70 }
71 let vd_bits = ((instruction >> 7) & 0x1f) as u8;
72 let funct3 = ((instruction >> 12) & 0b111) as u8;
73 let vs1_bits = ((instruction >> 15) & 0x1f) as u8;
74 let vs2_bits = ((instruction >> 20) & 0x1f) as u8;
75 let vm = ((instruction >> 25) & 1) as u8 == 1;
77 let funct6 = ((instruction >> 26) & 0b11_1111) as u8;
78 let vd = VReg::from_bits(vd_bits)?;
79 let vs2 = VReg::from_bits(vs2_bits)?;
80 match funct3 {
81 0b010 => {
83 let vs1 = VReg::from_bits(vs1_bits)?;
84 match funct6 {
85 0b00_1100 => Some(Self::VclmulVv { vd, vs2, vs1, vm }),
86 0b00_1101 => Some(Self::VclmulhVv { vd, vs2, vs1, vm }),
87 _ => None,
88 }
89 }
90 0b110 => {
92 let rs1 = Reg::from_bits(vs1_bits)?;
93 match funct6 {
94 0b00_1100 => Some(Self::VclmulVx { vd, vs2, rs1, vm }),
95 0b00_1101 => Some(Self::VclmulhVx { vd, vs2, rs1, vm }),
96 _ => None,
97 }
98 }
99 _ => None,
100 }
101 }
102
103 #[inline(always)]
104 fn alignment() -> u8 {
105 align_of::<u32>() as u8
106 }
107
108 #[inline(always)]
109 fn size(&self) -> u8 {
110 size_of::<u32>() as u8
111 }
112}
113
114#[instruction]
115impl<Reg> fmt::Display for ZvbcInstruction<Reg>
116where
117 Reg: fmt::Display + Copy,
118{
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 #[rustfmt::skip]
121 match self {
122 Self::VclmulVv { vd, vs2, vs1, vm } => write!(f, "vclmul.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
123 Self::VclmulVx { vd, vs2, rs1, vm } => write!(f, "vclmul.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
124 Self::VclmulhVv { vd, vs2, vs1, vm } => write!(f, "vclmulh.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
125 Self::VclmulhVx { vd, vs2, rs1, vm } => write!(f, "vclmulh.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
126 }
127 }
128}
129
130#[inline(always)]
132fn mask_suffix(vm: &bool) -> &'static str {
133 if *vm { "" } else { ", v0.t" }
134}