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 if sew != Vsew::E64 {
108 ::core::hint::cold_path();
109 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
110 address: PackedAddress::new(
111 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
112 ),
113 });
114 }
115 unsafe {
117 zvbc_helpers::execute_vclmul::<Reg, _>(
118 env,
119 vd,
120 vs2,
121 zvbc_helpers::OpSrc::Vreg(vs1),
122 sew,
123 vm,
124 );
125 }
126 }
127 Self::VclmulVx {
128 vm,
129 vd,
130 vs2,
131 rs1: _,
132 } => {
133 if !env.vector_instructions_allowed() {
134 ::core::hint::cold_path();
135 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
136 address: PackedAddress::new(
137 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
138 ),
139 });
140 }
141 if !vm && vd == VReg::V0 {
142 ::core::hint::cold_path();
143 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
144 address: PackedAddress::new(
145 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
146 ),
147 });
148 }
149 let Some(vtype) = env.vtype() else {
150 ::core::hint::cold_path();
151 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
152 address: PackedAddress::new(
153 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
154 ),
155 });
156 };
157 let group_regs = vtype.vlmul().register_count();
158 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
159 program_counter,
160 vd,
161 group_regs,
162 )?;
163 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
164 program_counter,
165 vs2,
166 group_regs,
167 )?;
168 let sew = vtype.vsew();
169 if sew != Vsew::E64 {
172 ::core::hint::cold_path();
173 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
174 address: PackedAddress::new(
175 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
176 ),
177 });
178 }
179 let scalar = rs1_value.as_i64().cast_unsigned();
180 unsafe {
182 zvbc_helpers::execute_vclmul::<Reg, _>(
183 env,
184 vd,
185 vs2,
186 zvbc_helpers::OpSrc::Scalar(scalar),
187 sew,
188 vm,
189 );
190 }
191 }
192 Self::VclmulhVv { vd, vs2, vs1, vm } => {
194 if !env.vector_instructions_allowed() {
195 ::core::hint::cold_path();
196 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
197 address: PackedAddress::new(
198 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
199 ),
200 });
201 }
202 if !vm && vd == VReg::V0 {
203 ::core::hint::cold_path();
204 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
205 address: PackedAddress::new(
206 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
207 ),
208 });
209 }
210 let Some(vtype) = env.vtype() else {
211 ::core::hint::cold_path();
212 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
213 address: PackedAddress::new(
214 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
215 ),
216 });
217 };
218 let group_regs = vtype.vlmul().register_count();
219 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
220 program_counter,
221 vd,
222 group_regs,
223 )?;
224 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
225 program_counter,
226 vs2,
227 group_regs,
228 )?;
229 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
230 program_counter,
231 vs1,
232 group_regs,
233 )?;
234 let sew = vtype.vsew();
235 if sew != Vsew::E64 {
238 ::core::hint::cold_path();
239 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
240 address: PackedAddress::new(
241 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
242 ),
243 });
244 }
245 unsafe {
247 zvbc_helpers::execute_vclmulh::<Reg, _>(
248 env,
249 vd,
250 vs2,
251 zvbc_helpers::OpSrc::Vreg(vs1),
252 sew,
253 vm,
254 );
255 }
256 }
257 Self::VclmulhVx {
258 vm,
259 vd,
260 vs2,
261 rs1: _,
262 } => {
263 if !env.vector_instructions_allowed() {
264 ::core::hint::cold_path();
265 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
266 address: PackedAddress::new(
267 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
268 ),
269 });
270 }
271 if !vm && vd == VReg::V0 {
272 ::core::hint::cold_path();
273 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
274 address: PackedAddress::new(
275 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
276 ),
277 });
278 }
279 let Some(vtype) = env.vtype() else {
280 ::core::hint::cold_path();
281 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
282 address: PackedAddress::new(
283 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
284 ),
285 });
286 };
287 let group_regs = vtype.vlmul().register_count();
288 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
289 program_counter,
290 vd,
291 group_regs,
292 )?;
293 zvbc_helpers::check_vreg_group_alignment::<Reg, _, _>(
294 program_counter,
295 vs2,
296 group_regs,
297 )?;
298 let sew = vtype.vsew();
299 if sew != Vsew::E64 {
302 ::core::hint::cold_path();
303 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
304 address: PackedAddress::new(
305 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
306 ),
307 });
308 }
309 let scalar = rs1_value.as_i64().cast_unsigned();
310 unsafe {
312 zvbc_helpers::execute_vclmulh::<Reg, _>(
313 env,
314 vd,
315 vs2,
316 zvbc_helpers::OpSrc::Scalar(scalar),
317 sew,
318 vm,
319 );
320 }
321 }
322 }
323 ExecutionResult::ContinueNoWrite
324 }
325}