1#[cfg(test)]
4mod tests;
5
6use crate::hart::{HartConfig, VectorHartConfig};
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::instructions::{ImplementedExtension, Instruction, IsaExtension};
22use crate::registers::general_purpose::Register;
23use crate::registers::vector::VReg;
24use ab_riscv_macros::instruction;
25use core::fmt;
26
27#[instruction(
44 inherit = [ZveXxInstruction],
45)]
46#[derive(Debug, Clone, Copy)]
47#[derive_const(PartialEq, Eq)]
48#[rustfmt::skip]
49pub enum ZvkbInstruction<Hart>
50where
51 Hart: HartConfig,
52{
53 VandnVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
58 VandnVx { vd: VReg, vs2: VReg, rs1: Hart::Reg, vm: bool },
60
61 Vbrev8V { vd: VReg, vs2: VReg, vm: bool },
65
66 Vrev8V { vd: VReg, vs2: VReg, vm: bool },
70
71 VrolVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
75 VrolVx { vd: VReg, vs2: VReg, rs1: Hart::Reg, vm: bool },
77
78 VrorVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
85 VrorVx { vd: VReg, vs2: VReg, rs1: Hart::Reg, vm: bool },
87 VrorVi { vd: VReg, vs2: VReg, uimm: u8, vm: bool },
90}
91
92#[instruction]
93const impl<Reg, Hart> Instruction for ZvkbInstruction<Hart>
94where
95 Reg: [const] Register,
96 Hart: [const] VectorHartConfig<Reg = Reg>,
97{
98 const OWN_ISA_EXTENSIONS: &'static [IsaExtension] = &[IsaExtension::new("zvkb", 1, 0)];
99
100 const ALIGNMENT: u8 = align_of::<u32>() as u8;
101
102 type Hart = Hart;
103
104 #[inline(always)]
105 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
106 fn try_decode(instruction: u32) -> Option<Self> {
107 let opcode = (instruction & 0b111_1111) as u8;
108
109 if opcode != 0b101_0111 {
110 None?;
111 }
112
113 let vd_bits = ((instruction >> 7) & 0x1f) as u8;
114 let funct3 = ((instruction >> 12) & 0b111) as u8;
115 let vs1_bits = ((instruction >> 15) & 0x1f) as u8;
116 let vs2_bits = ((instruction >> 20) & 0x1f) as u8;
117 let vm = ((instruction >> 25) & 1) as u8 == 1;
119 let funct6 = ((instruction >> 26) & 0b11_1111) as u8;
120
121 let vd = VReg::from_bits(vd_bits)?;
122 if vd.is_mask(vm) {
123 None?;
124 }
125 let vs2 = VReg::from_bits(vs2_bits)?;
126 if vs2.is_mask(vm) {
127 None?;
128 }
129
130 match funct3 {
131 0b000 => {
133 let vs1 = VReg::from_bits(vs1_bits)?;
134 if vs1.is_mask(vm) {
135 None?;
136 }
137 match funct6 {
138 0b00_0001 => Some(Self::VandnVv { vd, vs2, vs1, vm }),
139 0b01_0100 => Some(Self::VrorVv { vd, vs2, vs1, vm }),
140 0b01_0101 => Some(Self::VrolVv { vd, vs2, vs1, vm }),
141 _ => None,
142 }
143 }
144 0b100 => {
146 let rs1 = Reg::from_bits(vs1_bits)?;
147 match funct6 {
148 0b00_0001 => Some(Self::VandnVx { vd, vs2, rs1, vm }),
149 0b01_0100 => Some(Self::VrorVx { vd, vs2, rs1, vm }),
150 0b01_0101 => Some(Self::VrolVx { vd, vs2, rs1, vm }),
151 _ => None,
152 }
153 }
154 0b011 => {
157 if funct6 >> 1 != 0b0_1010 {
158 None?;
159 }
160 let uimm = vs1_bits | ((funct6 & 1) << 5);
161 Some(Self::VrorVi { vd, vs2, uimm, vm })
162 }
163 0b010 => {
167 if funct6 != 0b01_0010 {
168 None?;
169 }
170 match vs1_bits {
171 0b01000 => Some(Self::Vbrev8V { vd, vs2, vm }),
172 0b01001 => Some(Self::Vrev8V { vd, vs2, vm }),
173 _ => None,
174 }
175 }
176 _ => None,
177 }
178 }
179
180 #[inline(always)]
181 fn size(&self) -> u8 {
182 size_of::<u32>() as u8
183 }
184}
185
186#[instruction]
187impl<Reg, Hart> fmt::Display for ZvkbInstruction<Hart>
188where
189 Reg: fmt::Display + Copy,
190 Hart: HartConfig<Reg = Reg>,
191{
192 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193 #[rustfmt::skip]
194 match self {
195 Self::VandnVv { vd, vs2, vs1, vm } => write!(f, "vandn.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
196 Self::VandnVx { vd, vs2, rs1, vm } => write!(f, "vandn.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
197 Self::Vbrev8V { vd, vs2, vm } => write!(f, "vbrev8.v {vd}, {vs2}{}", mask_suffix(vm)),
198 Self::Vrev8V { vd, vs2, vm } => write!(f, "vrev8.v {vd}, {vs2}{}", mask_suffix(vm)),
199 Self::VrolVv { vd, vs2, vs1, vm } => write!(f, "vrol.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
200 Self::VrolVx { vd, vs2, rs1, vm } => write!(f, "vrol.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
201 Self::VrorVv { vd, vs2, vs1, vm } => write!(f, "vror.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
202 Self::VrorVx { vd, vs2, rs1, vm } => write!(f, "vror.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
203 Self::VrorVi { vd, vs2, uimm, vm } => write!(f, "vror.vi {vd}, {vs2}, {uimm}{}", mask_suffix(vm)),
204 }
205 }
206}
207
208#[inline(always)]
210fn mask_suffix(vm: &bool) -> &'static str {
211 if *vm { "" } else { ", v0.t" }
212}