ab_riscv_primitives/instructions/
zvbb.rs1#[cfg(test)]
4mod tests;
5pub mod zvkb;
6
7use crate::instructions::Instruction;
8use crate::instructions::v::zvexx::ZveXxInstruction;
9use crate::instructions::v::zvexx::arith::ZveXxArithInstruction;
10use crate::instructions::v::zvexx::carry::ZveXxCarryInstruction;
11use crate::instructions::v::zvexx::config::ZveXxConfigInstruction;
12use crate::instructions::v::zvexx::fixed_point::ZveXxFixedPointInstruction;
13use crate::instructions::v::zvexx::load::{LoadStoreNreg, Nf, SegVmNf, ZveXxLoadInstruction};
14use crate::instructions::v::zvexx::mask::ZveXxMaskInstruction;
15use crate::instructions::v::zvexx::muldiv::ZveXxMulDivInstruction;
16use crate::instructions::v::zvexx::perm::ZveXxPermInstruction;
17use crate::instructions::v::zvexx::reduction::ZveXxReductionInstruction;
18use crate::instructions::v::zvexx::store::ZveXxStoreInstruction;
19use crate::instructions::v::zvexx::widen_narrow::ZveXxWidenNarrowInstruction;
20use crate::instructions::v::{Eew, V};
21use crate::instructions::zicsr::ZicsrInstruction;
22use crate::instructions::zvbb::zvkb::ZvkbInstruction;
23use crate::registers::general_purpose::Register;
24use crate::registers::vector::VReg;
25use ab_riscv_macros::instruction;
26use core::fmt;
27
28#[instruction(
53 inherit = [ZvkbInstruction],
54)]
55#[derive(Debug, Clone, Copy)]
56#[derive_const(PartialEq, Eq)]
57#[rustfmt::skip]
58pub enum ZvbbInstruction<Reg> {
59 VbrevV { vd: VReg, vs2: VReg, vm: bool },
62 VclzV { vd: VReg, vs2: VReg, vm: bool },
65 VctzV { vd: VReg, vs2: VReg, vm: bool },
68 VcpopV { vd: VReg, vs2: VReg, vm: bool },
71 VwsllVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
74 VwsllVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
76 VwsllVi { vd: VReg, vs2: VReg, uimm: u8, vm: bool },
79}
80
81#[instruction]
82const impl<Reg> Instruction for ZvbbInstruction<Reg>
83where
84 Reg: [const] Register,
85{
86 type Reg = Reg;
87
88 #[inline(always)]
89 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
90 fn try_decode(instruction: u32) -> Option<Self> {
91 let opcode = (instruction & 0b111_1111) as u8;
92
93 if opcode != 0b101_0111 {
94 None?;
95 }
96
97 let vd_bits = ((instruction >> 7) & 0x1f) as u8;
98 let funct3 = ((instruction >> 12) & 0b111) as u8;
99 let vs1_bits = ((instruction >> 15) & 0x1f) as u8;
100 let vs2_bits = ((instruction >> 20) & 0x1f) as u8;
101 let vm = ((instruction >> 25) & 1) as u8 == 1;
103 let funct6 = ((instruction >> 26) & 0b11_1111) as u8;
104
105 let vd = VReg::from_bits(vd_bits)?;
106 let vs2 = VReg::from_bits(vs2_bits)?;
107
108 match funct3 {
109 0b000 => {
111 if funct6 != 0b11_0101 {
112 None?;
113 }
114 let vs1 = VReg::from_bits(vs1_bits)?;
115 Some(Self::VwsllVv { vd, vs2, vs1, vm })
116 }
117 0b100 => {
119 if funct6 != 0b11_0101 {
120 None?;
121 }
122 let rs1 = Reg::from_bits(vs1_bits)?;
123 Some(Self::VwsllVx { vd, vs2, rs1, vm })
124 }
125 0b011 => {
127 if funct6 != 0b11_0101 {
128 None?;
129 }
130 let uimm = vs1_bits;
131 Some(Self::VwsllVi { vd, vs2, uimm, vm })
132 }
133 0b010 => {
137 if funct6 != 0b01_0010 {
138 None?;
139 }
140 match vs1_bits {
141 0b01010 => Some(Self::VbrevV { vd, vs2, vm }),
142 0b01100 => Some(Self::VclzV { vd, vs2, vm }),
143 0b01101 => Some(Self::VctzV { vd, vs2, vm }),
144 0b01110 => Some(Self::VcpopV { vd, vs2, vm }),
145 _ => None,
146 }
147 }
148 _ => None,
149 }
150 }
151
152 #[inline(always)]
153 fn alignment() -> u8 {
154 align_of::<u32>() as u8
155 }
156
157 #[inline(always)]
158 fn size(&self) -> u8 {
159 size_of::<u32>() as u8
160 }
161}
162
163#[instruction]
164impl<Reg> fmt::Display for ZvbbInstruction<Reg>
165where
166 Reg: fmt::Display + Copy,
167{
168 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169 #[rustfmt::skip]
170 match self {
171 Self::VbrevV { vd, vs2, vm } => write!(f, "vbrev.v {vd}, {vs2}{}", mask_suffix(vm)),
172 Self::VclzV { vd, vs2, vm } => write!(f, "vclz.v {vd}, {vs2}{}", mask_suffix(vm)),
173 Self::VctzV { vd, vs2, vm } => write!(f, "vctz.v {vd}, {vs2}{}", mask_suffix(vm)),
174 Self::VcpopV { vd, vs2, vm } => write!(f, "vcpop.v {vd}, {vs2}{}", mask_suffix(vm)),
175 Self::VwsllVv { vd, vs2, vs1, vm } => write!(f, "vwsll.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
176 Self::VwsllVx { vd, vs2, rs1, vm } => write!(f, "vwsll.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
177 Self::VwsllVi { vd, vs2, uimm, vm } => write!(f, "vwsll.vi {vd}, {vs2}, {uimm}{}", mask_suffix(vm)),
178 }
179 }
180}
181
182#[inline(always)]
184fn mask_suffix(vm: &bool) -> &'static str {
185 if *vm { "" } else { ", v0.t" }
186}