1#[cfg(test)]
4mod tests;
5pub mod zvbc_helpers;
6
7use crate::v::vector_registers::{VectorRegisters, 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, Hart> ExecutableInstructionOperands for ZvbcInstruction<Hart>
33where
34 Reg: Register,
35 Hart: VectorHartConfig<Reg = Reg>,
36{
37}
38
39#[instruction_execution]
40const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for ZvbcInstruction<Hart>
41where
42 Reg: Register,
43 Hart: VectorHartConfig<Reg = Reg>,
44{
45}
46
47#[instruction_execution]
48impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
49 for ZvbcInstruction<Hart>
50where
51 Reg: Register,
52 Hart: VectorHartConfig<Reg = Reg>,
53 Regs: RegisterFile<Reg>,
54 Env: VectorRegistersExt<Hart = Hart>,
55 Memory: VirtualMemory,
56 PC: ProgramCounter<Reg::Type, Memory>,
57{
58 #[inline(always)]
59 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
60 fn execute(
61 self,
62 Rs1Rs2OperandValues {
63 rs1_value,
64 rs2_value,
65 }: Rs1Rs2OperandValues<Reg::Type>,
66 _regs: &mut Regs,
67 env: &mut Env,
68 memory: &mut Memory,
69 program_counter: &PC,
70 ) -> ExecutionResult<Reg> {
71 match self {
72 Self::VclmulVv { vd, vs2, vs1, vm } => {
74 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
75 ::core::hint::cold_path();
76 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
77 address: PackedAddress::new(
78 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
79 ),
80 });
81 }
82 let Some(config) = env.vector_config() else {
83 ::core::hint::cold_path();
84 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
85 address: PackedAddress::new(
86 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
87 ),
88 });
89 };
90 let sew = config.vtype().vsew();
91 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
92 program_counter,
93 config,
94 vd,
95 sew.as_eew(),
96 )?;
97 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
98 program_counter,
99 config,
100 vs2,
101 sew.as_eew(),
102 )?;
103 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
104 program_counter,
105 config,
106 vs1,
107 sew.as_eew(),
108 )?;
109 if sew != Vsew::E64 {
112 ::core::hint::cold_path();
113 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
114 address: PackedAddress::new(
115 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
116 ),
117 });
118 }
119 zvbc_helpers::execute_vclmul::<Reg, _>(
120 env,
121 vd,
122 vs2,
123 zvbc_helpers::OpSrc::Vreg(vs1),
124 sew,
125 vm,
126 );
127 }
128 Self::VclmulVx {
129 vm,
130 vd,
131 vs2,
132 rs1: _,
133 } => {
134 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
135 ::core::hint::cold_path();
136 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
137 address: PackedAddress::new(
138 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
139 ),
140 });
141 }
142 let Some(config) = env.vector_config() else {
143 ::core::hint::cold_path();
144 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
145 address: PackedAddress::new(
146 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
147 ),
148 });
149 };
150 let sew = config.vtype().vsew();
151 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
152 program_counter,
153 config,
154 vd,
155 sew.as_eew(),
156 )?;
157 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
158 program_counter,
159 config,
160 vs2,
161 sew.as_eew(),
162 )?;
163 if sew != Vsew::E64 {
166 ::core::hint::cold_path();
167 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
168 address: PackedAddress::new(
169 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
170 ),
171 });
172 }
173 let scalar = rs1_value.as_i64().cast_unsigned();
174 zvbc_helpers::execute_vclmul::<Reg, _>(
175 env,
176 vd,
177 vs2,
178 zvbc_helpers::OpSrc::Scalar(scalar),
179 sew,
180 vm,
181 );
182 }
183 Self::VclmulhVv { vd, vs2, vs1, vm } => {
185 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
186 ::core::hint::cold_path();
187 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
188 address: PackedAddress::new(
189 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
190 ),
191 });
192 }
193 let Some(config) = env.vector_config() else {
194 ::core::hint::cold_path();
195 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
196 address: PackedAddress::new(
197 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
198 ),
199 });
200 };
201 let sew = config.vtype().vsew();
202 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
203 program_counter,
204 config,
205 vd,
206 sew.as_eew(),
207 )?;
208 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
209 program_counter,
210 config,
211 vs2,
212 sew.as_eew(),
213 )?;
214 let vs1 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
215 program_counter,
216 config,
217 vs1,
218 sew.as_eew(),
219 )?;
220 if sew != Vsew::E64 {
223 ::core::hint::cold_path();
224 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
225 address: PackedAddress::new(
226 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
227 ),
228 });
229 }
230 zvbc_helpers::execute_vclmulh::<Reg, _>(
231 env,
232 vd,
233 vs2,
234 zvbc_helpers::OpSrc::Vreg(vs1),
235 sew,
236 vm,
237 );
238 }
239 Self::VclmulhVx {
240 vm,
241 vd,
242 vs2,
243 rs1: _,
244 } => {
245 if !zvexx_helpers::non_memory_instruction_allowed::<Reg, _>(env) {
246 ::core::hint::cold_path();
247 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
248 address: PackedAddress::new(
249 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
250 ),
251 });
252 }
253 let Some(config) = env.vector_config() else {
254 ::core::hint::cold_path();
255 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
256 address: PackedAddress::new(
257 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
258 ),
259 });
260 };
261 let sew = config.vtype().vsew();
262 let vd = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
263 program_counter,
264 config,
265 vd,
266 sew.as_eew(),
267 )?;
268 let vs2 = zvexx_helpers::vreg_group::<Reg, Env, _, _>(
269 program_counter,
270 config,
271 vs2,
272 sew.as_eew(),
273 )?;
274 if sew != Vsew::E64 {
277 ::core::hint::cold_path();
278 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
279 address: PackedAddress::new(
280 program_counter.old_pc(zvexx_helpers::INSTRUCTION_SIZE),
281 ),
282 });
283 }
284 let scalar = rs1_value.as_i64().cast_unsigned();
285 zvbc_helpers::execute_vclmulh::<Reg, _>(
286 env,
287 vd,
288 vs2,
289 zvbc_helpers::OpSrc::Scalar(scalar),
290 sew,
291 vm,
292 );
293 }
294 }
295 ExecutionResult::ContinueNoWrite
296 }
297}