1#[cfg(test)]
4mod tests;
5pub mod zvbc_helpers;
6
7use crate::v::vector_registers::VectorRegistersExt;
8use crate::v::zvexx::arith::zvexx_arith_helpers;
9use crate::v::zvexx::carry::zvexx_carry_helpers;
10use crate::v::zvexx::config::zvexx_config_helpers;
11use crate::v::zvexx::fixed_point::zvexx_fixed_point_helpers;
12use crate::v::zvexx::load::zvexx_load_helpers;
13use crate::v::zvexx::mask::zvexx_mask_helpers;
14use crate::v::zvexx::muldiv::zvexx_muldiv_helpers;
15use crate::v::zvexx::perm::zvexx_perm_helpers;
16use crate::v::zvexx::reduction::zvexx_reduction_helpers;
17use crate::v::zvexx::store::zvexx_store_helpers;
18use crate::v::zvexx::widen_narrow::zvexx_widen_narrow_helpers;
19use crate::v::zvexx::zvexx_helpers;
20use crate::zicsr::zicsr_helpers;
21use crate::{
22 CsrError, Csrs, ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands,
23 ExecutionError, ExecutionResult, FetchInstructionResult, InstructionFetcher,
24 OpaqueThreadedExecutionResult, PackedAddress, ProgramCounter, RegisterFile,
25 Rs1Rs2OperandValues, Rs1Rs2Operands, ThreadedExecutableInstruction, ThreadedExecutionResult,
26 VirtualMemory,
27};
28use ab_riscv_macros::instruction_execution;
29use ab_riscv_primitives::prelude::*;
30
31#[instruction_execution]
32const impl<Reg> ExecutableInstructionOperands for ZvbcInstruction<Reg> where Reg: Register {}
33
34#[instruction_execution]
35const impl<Reg, Env> ExecutableInstructionCsr<Env> for ZvbcInstruction<Reg> where Reg: Register {}
36
37#[instruction_execution]
38impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
39 for ZvbcInstruction<Reg>
40where
41 Reg: Register,
42 Regs: RegisterFile<Reg>,
43 Env: VectorRegistersExt<Reg>,
44 [(); SUPPORTED_ELEN_VLEN::<{ Env::ELEN }, { Env::VLEN }>]:,
45 Memory: VirtualMemory,
46 PC: ProgramCounter<Reg::Type, Memory>,
47{
48 #[inline(always)]
49 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
50 fn execute(
51 self,
52 Rs1Rs2OperandValues {
53 rs1_value,
54 rs2_value,
55 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
56 _regs: &mut Regs,
57 env: &mut Env,
58 memory: &mut Memory,
59 program_counter: &mut PC,
60 ) -> ExecutionResult<Self::Reg> {
61 match self {
62 Self::VclmulVv { vd, vs2, vs1, vm } => {
64 if !env.vector_instructions_allowed() {
65 ::core::hint::cold_path();
66 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
67 address: PackedAddress::new(
68 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
69 ),
70 });
71 }
72 if !vm && vd == VReg::V0 {
73 ::core::hint::cold_path();
74 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
75 address: PackedAddress::new(
76 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
77 ),
78 });
79 }
80 let Some(vtype) = env.vtype() else {
81 ::core::hint::cold_path();
82 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
83 address: PackedAddress::new(
84 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
85 ),
86 });
87 };
88 let group_regs = vtype.vlmul().register_count();
89 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
90 program_counter,
91 vd,
92 group_regs,
93 )?;
94 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
95 program_counter,
96 vs2,
97 group_regs,
98 )?;
99 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
100 program_counter,
101 vs1,
102 group_regs,
103 )?;
104 let sew = vtype.vsew();
105 unsafe {
107 zvbc_helpers::execute_vclmul::<Reg, _>(
108 env,
109 vd,
110 vs2,
111 zvbc_helpers::OpSrc::Vreg(vs1),
112 sew,
113 vm,
114 );
115 }
116 }
117 Self::VclmulVx {
118 vm,
119 vd,
120 vs2,
121 rs1: _,
122 } => {
123 if !env.vector_instructions_allowed() {
124 ::core::hint::cold_path();
125 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
126 address: PackedAddress::new(
127 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
128 ),
129 });
130 }
131 if !vm && vd == VReg::V0 {
132 ::core::hint::cold_path();
133 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
134 address: PackedAddress::new(
135 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
136 ),
137 });
138 }
139 let Some(vtype) = env.vtype() else {
140 ::core::hint::cold_path();
141 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
142 address: PackedAddress::new(
143 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
144 ),
145 });
146 };
147 let group_regs = vtype.vlmul().register_count();
148 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
149 program_counter,
150 vd,
151 group_regs,
152 )?;
153 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
154 program_counter,
155 vs2,
156 group_regs,
157 )?;
158 let sew = vtype.vsew();
159 let scalar = rs1_value.as_i64().cast_unsigned();
160 unsafe {
162 zvbc_helpers::execute_vclmul::<Reg, _>(
163 env,
164 vd,
165 vs2,
166 zvbc_helpers::OpSrc::Scalar(scalar),
167 sew,
168 vm,
169 );
170 }
171 }
172 Self::VclmulhVv { vd, vs2, vs1, vm } => {
174 if !env.vector_instructions_allowed() {
175 ::core::hint::cold_path();
176 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
177 address: PackedAddress::new(
178 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
179 ),
180 });
181 }
182 if !vm && vd == VReg::V0 {
183 ::core::hint::cold_path();
184 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
185 address: PackedAddress::new(
186 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
187 ),
188 });
189 }
190 let Some(vtype) = env.vtype() else {
191 ::core::hint::cold_path();
192 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
193 address: PackedAddress::new(
194 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
195 ),
196 });
197 };
198 let group_regs = vtype.vlmul().register_count();
199 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
200 program_counter,
201 vd,
202 group_regs,
203 )?;
204 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
205 program_counter,
206 vs2,
207 group_regs,
208 )?;
209 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
210 program_counter,
211 vs1,
212 group_regs,
213 )?;
214 let sew = vtype.vsew();
215 unsafe {
217 zvbc_helpers::execute_vclmulh::<Reg, _>(
218 env,
219 vd,
220 vs2,
221 zvbc_helpers::OpSrc::Vreg(vs1),
222 sew,
223 vm,
224 );
225 }
226 }
227 Self::VclmulhVx {
228 vm,
229 vd,
230 vs2,
231 rs1: _,
232 } => {
233 if !env.vector_instructions_allowed() {
234 ::core::hint::cold_path();
235 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
236 address: PackedAddress::new(
237 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
238 ),
239 });
240 }
241 if !vm && vd == VReg::V0 {
242 ::core::hint::cold_path();
243 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
244 address: PackedAddress::new(
245 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
246 ),
247 });
248 }
249 let Some(vtype) = env.vtype() else {
250 ::core::hint::cold_path();
251 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
252 address: PackedAddress::new(
253 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
254 ),
255 });
256 };
257 let group_regs = vtype.vlmul().register_count();
258 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
259 program_counter,
260 vd,
261 group_regs,
262 )?;
263 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
264 program_counter,
265 vs2,
266 group_regs,
267 )?;
268 let sew = vtype.vsew();
269 let scalar = rs1_value.as_i64().cast_unsigned();
270 unsafe {
272 zvbc_helpers::execute_vclmulh::<Reg, _>(
273 env,
274 vd,
275 vs2,
276 zvbc_helpers::OpSrc::Scalar(scalar),
277 sew,
278 vm,
279 );
280 }
281 }
282 }
283 ExecutionResult::ContinueNoWrite
284 }
285}