ab_riscv_primitives/instructions/zvbb/
zvkb.rs1#[cfg(test)]
4mod tests;
5
6use crate::instructions::Instruction;
7use crate::instructions::v::zvexx::ZveXxInstruction;
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::v::{Eew, V};
20use crate::instructions::zicsr::ZicsrInstruction;
21use crate::registers::general_purpose::Register;
22use crate::registers::vector::VReg;
23use ab_riscv_macros::instruction;
24use core::fmt;
25
26#[instruction(
43 inherit = [ZveXxInstruction],
44)]
45#[derive(Debug, Clone, Copy)]
46#[derive_const(PartialEq, Eq)]
47#[rustfmt::skip]
48pub enum ZvkbInstruction<Reg> {
49 VandnVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
54 VandnVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
56
57 Vbrev8V { vd: VReg, vs2: VReg, vm: bool },
61
62 Vrev8V { vd: VReg, vs2: VReg, vm: bool },
66
67 VrolVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
71 VrolVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
73
74 VrorVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
81 VrorVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
83 VrorVi { vd: VReg, vs2: VReg, uimm: u8, vm: bool },
86}
87
88#[instruction]
89const impl<Reg> Instruction for ZvkbInstruction<Reg>
90where
91 Reg: [const] Register,
92{
93 const ALIGNMENT: u8 = align_of::<u32>() as u8;
94
95 type Reg = Reg;
96
97 #[inline(always)]
98 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
99 fn try_decode(instruction: u32) -> Option<Self> {
100 let opcode = (instruction & 0b111_1111) as u8;
101
102 if opcode != 0b101_0111 {
103 None?;
104 }
105
106 let vd_bits = ((instruction >> 7) & 0x1f) as u8;
107 let funct3 = ((instruction >> 12) & 0b111) as u8;
108 let vs1_bits = ((instruction >> 15) & 0x1f) as u8;
109 let vs2_bits = ((instruction >> 20) & 0x1f) as u8;
110 let vm = ((instruction >> 25) & 1) as u8 == 1;
112 let funct6 = ((instruction >> 26) & 0b11_1111) as u8;
113
114 let vd = VReg::from_bits(vd_bits)?;
115 let vs2 = VReg::from_bits(vs2_bits)?;
116
117 match funct3 {
118 0b000 => {
120 let vs1 = VReg::from_bits(vs1_bits)?;
121 match funct6 {
122 0b00_0001 => Some(Self::VandnVv { vd, vs2, vs1, vm }),
123 0b01_0100 => Some(Self::VrorVv { vd, vs2, vs1, vm }),
124 0b01_0101 => Some(Self::VrolVv { vd, vs2, vs1, vm }),
125 _ => None,
126 }
127 }
128 0b100 => {
130 let rs1 = Reg::from_bits(vs1_bits)?;
131 match funct6 {
132 0b00_0001 => Some(Self::VandnVx { vd, vs2, rs1, vm }),
133 0b01_0100 => Some(Self::VrorVx { vd, vs2, rs1, vm }),
134 0b01_0101 => Some(Self::VrolVx { vd, vs2, rs1, vm }),
135 _ => None,
136 }
137 }
138 0b011 => {
141 if funct6 >> 1 != 0b0_1010 {
142 None?;
143 }
144 let uimm = vs1_bits | ((funct6 & 1) << 5);
145 Some(Self::VrorVi { vd, vs2, uimm, vm })
146 }
147 0b010 => {
151 if funct6 != 0b01_0010 {
152 None?;
153 }
154 match vs1_bits {
155 0b01000 => Some(Self::Vbrev8V { vd, vs2, vm }),
156 0b01001 => Some(Self::Vrev8V { vd, vs2, vm }),
157 _ => None,
158 }
159 }
160 _ => None,
161 }
162 }
163
164 #[inline(always)]
165 fn size(&self) -> u8 {
166 size_of::<u32>() as u8
167 }
168}
169
170#[instruction]
171impl<Reg> fmt::Display for ZvkbInstruction<Reg>
172where
173 Reg: fmt::Display + Copy,
174{
175 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176 #[rustfmt::skip]
177 match self {
178 Self::VandnVv { vd, vs2, vs1, vm } => write!(f, "vandn.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
179 Self::VandnVx { vd, vs2, rs1, vm } => write!(f, "vandn.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
180 Self::Vbrev8V { vd, vs2, vm } => write!(f, "vbrev8.v {vd}, {vs2}{}", mask_suffix(vm)),
181 Self::Vrev8V { vd, vs2, vm } => write!(f, "vrev8.v {vd}, {vs2}{}", mask_suffix(vm)),
182 Self::VrolVv { vd, vs2, vs1, vm } => write!(f, "vrol.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
183 Self::VrolVx { vd, vs2, rs1, vm } => write!(f, "vrol.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
184 Self::VrorVv { vd, vs2, vs1, vm } => write!(f, "vror.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
185 Self::VrorVx { vd, vs2, rs1, vm } => write!(f, "vror.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
186 Self::VrorVi { vd, vs2, uimm, vm } => write!(f, "vror.vi {vd}, {vs2}, {uimm}{}", mask_suffix(vm)),
187 }
188 }
189}
190
191#[inline(always)]
193fn mask_suffix(vm: &bool) -> &'static str {
194 if *vm { "" } else { ", v0.t" }
195}