ab_riscv_primitives/instructions/
zvbc.rs1#[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 ZvbcInstruction<Hart>
50where
51 Hart: HartConfig,
52{
53 VclmulVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
56 VclmulVx { vd: VReg, vs2: VReg, rs1: Hart::Reg, vm: bool },
58 VclmulhVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
61 VclmulhVx { vd: VReg, vs2: VReg, rs1: Hart::Reg, vm: bool },
63}
64
65#[instruction]
66const impl<Reg, Hart> Instruction for ZvbcInstruction<Hart>
67where
68 Reg: [const] Register,
69 Hart: [const] VectorHartConfig<Reg = Reg>,
70{
71 const OWN_ISA_EXTENSIONS: &'static [IsaExtension] = {
72 assert!(
74 Hart::VECTOR_LENGTHS.elen.supports(Eew::E64),
75 "Zvbc requires `ELEN >= 64`"
76 );
77 &[IsaExtension::new("zvbc", 1, 0)]
78 };
79
80 const ALIGNMENT: u8 = align_of::<u32>() as u8;
81
82 type Hart = Hart;
83
84 #[inline(always)]
85 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
86 fn try_decode(instruction: u32) -> Option<Self> {
87 let opcode = (instruction & 0b111_1111) as u8;
88 if opcode != 0b101_0111 {
89 None?;
90 }
91 const {
93 assert!(
94 Hart::VECTOR_LENGTHS.elen.supports(Eew::E64),
95 "Zvbc requires `ELEN >= 64`"
96 );
97 }
98 let vd_bits = ((instruction >> 7) & 0x1f) as u8;
99 let funct3 = ((instruction >> 12) & 0b111) as u8;
100 let vs1_bits = ((instruction >> 15) & 0x1f) as u8;
101 let vs2_bits = ((instruction >> 20) & 0x1f) as u8;
102 let vm = ((instruction >> 25) & 1) as u8 == 1;
104 let funct6 = ((instruction >> 26) & 0b11_1111) as u8;
105 let vd = VReg::from_bits(vd_bits)?;
106 if vd.is_mask(vm) {
107 None?;
108 }
109 let vs2 = VReg::from_bits(vs2_bits)?;
110 if vs2.is_mask(vm) {
111 None?;
112 }
113 match funct3 {
114 0b010 => {
116 let vs1 = VReg::from_bits(vs1_bits)?;
117 if vs1.is_mask(vm) {
118 None?;
119 }
120 match funct6 {
121 0b00_1100 => Some(Self::VclmulVv { vd, vs2, vs1, vm }),
122 0b00_1101 => Some(Self::VclmulhVv { vd, vs2, vs1, vm }),
123 _ => None,
124 }
125 }
126 0b110 => {
128 let rs1 = Reg::from_bits(vs1_bits)?;
129 match funct6 {
130 0b00_1100 => Some(Self::VclmulVx { vd, vs2, rs1, vm }),
131 0b00_1101 => Some(Self::VclmulhVx { vd, vs2, rs1, vm }),
132 _ => None,
133 }
134 }
135 _ => None,
136 }
137 }
138
139 #[inline(always)]
140 fn size(&self) -> u8 {
141 size_of::<u32>() as u8
142 }
143}
144
145#[instruction]
146impl<Reg, Hart> fmt::Display for ZvbcInstruction<Hart>
147where
148 Reg: fmt::Display + Copy,
149 Hart: HartConfig<Reg = Reg>,
150{
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 #[rustfmt::skip]
153 match self {
154 Self::VclmulVv { vd, vs2, vs1, vm } => write!(f, "vclmul.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
155 Self::VclmulVx { vd, vs2, rs1, vm } => write!(f, "vclmul.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
156 Self::VclmulhVv { vd, vs2, vs1, vm } => write!(f, "vclmulh.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
157 Self::VclmulhVx { vd, vs2, rs1, vm } => write!(f, "vclmulh.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
158 }
159 }
160}
161
162#[inline(always)]
164fn mask_suffix(vm: &bool) -> &'static str {
165 if *vm { "" } else { ", v0.t" }
166}