1pub mod a;
4pub mod b;
5pub mod c;
6pub mod m;
7#[cfg(test)]
8pub(crate) mod test_utils;
9#[cfg(test)]
10mod tests;
11#[cfg(test)]
12mod threaded_tests;
13pub mod zabha;
14pub mod zacas;
15pub mod zalasr;
16pub mod zce;
17pub mod zk;
18
19use crate::{
20 ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
21 ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
22 PackedAddress, ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
23 SystemInstructionHandler, ThreadedExecutableInstruction, ThreadedExecutionResult,
24 VirtualMemory,
25};
26use ab_riscv_macros::instruction_execution;
27use ab_riscv_primitives::prelude::*;
28
29#[instruction_execution]
30const impl<Reg, Hart> ExecutableInstructionOperands for Rv64Instruction<Hart>
31where
32 Reg: Register<Type = u64>,
33 Hart: HartConfig<Reg = Reg>,
34{
35}
36
37#[instruction_execution]
38const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for Rv64Instruction<Hart>
39where
40 Reg: Register<Type = u64>,
41 Hart: HartConfig<Reg = Reg>,
42{
43}
44
45#[instruction_execution]
46const impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
47 for Rv64Instruction<Hart>
48where
49 Reg: [const] Register<Type = u64>,
50 Hart: HartConfig<Reg = Reg>,
51 Regs: [const] RegisterFile<Reg>,
52 Env: [const] SystemInstructionHandler<Reg, Regs, Memory, PC>,
53 Memory: [const] VirtualMemory,
54 PC: [const] ProgramCounter<Reg::Type, Memory>,
55{
56 #[inline(always)]
57 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
58 fn execute(
59 self,
60 Rs1Rs2OperandValues {
61 rs1_value,
62 rs2_value,
63 }: Rs1Rs2OperandValues<Reg::Type>,
64 regs: &mut Regs,
65 env: &mut Env,
66 memory: &mut Memory,
67 program_counter: &PC,
68 ) -> ExecutionResult<Reg> {
69 match self {
70 Self::Add { rd, rs1: _, rs2: _ } => {
71 let value = rs1_value.wrapping_add(rs2_value);
72 ExecutionResult::Continue { rd, value }
73 }
74 Self::Sub { rd, rs1: _, rs2: _ } => {
75 let value = rs1_value.wrapping_sub(rs2_value);
76 ExecutionResult::Continue { rd, value }
77 }
78 Self::Sll { rd, rs1: _, rs2: _ } => {
79 let shamt = rs2_value & 0x3f;
80 let value = rs1_value << shamt;
81 ExecutionResult::Continue { rd, value }
82 }
83 Self::Slt { rd, rs1: _, rs2: _ } => {
84 let value = rs1_value.cast_signed() < rs2_value.cast_signed();
85 ExecutionResult::Continue {
86 rd,
87 value: u64::from(value),
88 }
89 }
90 Self::Sltu { rd, rs1: _, rs2: _ } => {
91 let value = rs1_value < rs2_value;
92 ExecutionResult::Continue {
93 rd,
94 value: u64::from(value),
95 }
96 }
97 Self::Xor { rd, rs1: _, rs2: _ } => {
98 let value = rs1_value ^ rs2_value;
99 ExecutionResult::Continue { rd, value }
100 }
101 Self::Srl { rd, rs1: _, rs2: _ } => {
102 let shamt = rs2_value & 0x3f;
103 let value = rs1_value >> shamt;
104 ExecutionResult::Continue { rd, value }
105 }
106 Self::Sra { rd, rs1: _, rs2: _ } => {
107 let shamt = rs2_value & 0x3f;
108 let value = rs1_value.cast_signed() >> shamt;
109 ExecutionResult::Continue {
110 rd,
111 value: value.cast_unsigned(),
112 }
113 }
114 Self::Or { rd, rs1: _, rs2: _ } => {
115 let value = rs1_value | rs2_value;
116 ExecutionResult::Continue { rd, value }
117 }
118 Self::And { rd, rs1: _, rs2: _ } => {
119 let value = rs1_value & rs2_value;
120 ExecutionResult::Continue { rd, value }
121 }
122
123 Self::Addw { rd, rs1: _, rs2: _ } => {
124 let sum = (rs1_value as i32).wrapping_add(rs2_value as i32);
125 ExecutionResult::Continue {
126 rd,
127 value: i64::from(sum).cast_unsigned(),
128 }
129 }
130 Self::Subw { rd, rs1: _, rs2: _ } => {
131 let diff = (rs1_value as i32).wrapping_sub(rs2_value as i32);
132 ExecutionResult::Continue {
133 rd,
134 value: i64::from(diff).cast_unsigned(),
135 }
136 }
137 Self::Sllw { rd, rs1: _, rs2: _ } => {
138 let shamt = rs2_value & 0x1f;
139 let shifted = (rs1_value as u32) << shamt;
140 ExecutionResult::Continue {
141 rd,
142 value: i64::from(shifted.cast_signed()).cast_unsigned(),
143 }
144 }
145 Self::Srlw { rd, rs1: _, rs2: _ } => {
146 let shamt = rs2_value & 0x1f;
147 let shifted = (rs1_value as u32) >> shamt;
148 ExecutionResult::Continue {
149 rd,
150 value: i64::from(shifted.cast_signed()).cast_unsigned(),
151 }
152 }
153 Self::Sraw { rd, rs1: _, rs2: _ } => {
154 let shamt = rs2_value & 0x1f;
155 let shifted = (rs1_value as i32) >> shamt;
156 ExecutionResult::Continue {
157 rd,
158 value: i64::from(shifted).cast_unsigned(),
159 }
160 }
161
162 Self::Addi { rd, rs1: _, imm } => {
163 let value = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
164 ExecutionResult::Continue { rd, value }
165 }
166 Self::Slti { rd, rs1: _, imm } => {
167 let value = rs1_value.cast_signed() < i64::from(imm);
168 ExecutionResult::Continue {
169 rd,
170 value: u64::from(value),
171 }
172 }
173 Self::Sltiu { rd, rs1: _, imm } => {
174 let value = rs1_value < i64::from(imm).cast_unsigned();
175 ExecutionResult::Continue {
176 rd,
177 value: u64::from(value),
178 }
179 }
180 Self::Xori { rd, rs1: _, imm } => {
181 let value = rs1_value ^ i64::from(imm).cast_unsigned();
182 ExecutionResult::Continue { rd, value }
183 }
184 Self::Ori { rd, rs1: _, imm } => {
185 let value = rs1_value | i64::from(imm).cast_unsigned();
186 ExecutionResult::Continue { rd, value }
187 }
188 Self::Andi { rd, rs1: _, imm } => {
189 let value = rs1_value & i64::from(imm).cast_unsigned();
190 ExecutionResult::Continue { rd, value }
191 }
192 Self::Slli { rd, rs1: _, shamt } => {
193 let value = rs1_value << shamt.get();
194 ExecutionResult::Continue { rd, value }
195 }
196 Self::Srli { rd, rs1: _, shamt } => {
197 let value = rs1_value >> shamt.get();
198 ExecutionResult::Continue { rd, value }
199 }
200 Self::Srai { rd, rs1: _, shamt } => {
201 let value = rs1_value.cast_signed() >> shamt.get();
202 ExecutionResult::Continue {
203 rd,
204 value: value.cast_unsigned(),
205 }
206 }
207
208 Self::Addiw { rd, rs1: _, imm } => {
209 let sum = (rs1_value as i32).wrapping_add(i32::from(imm));
210 ExecutionResult::Continue {
211 rd,
212 value: i64::from(sum).cast_unsigned(),
213 }
214 }
215 Self::Slliw { rd, rs1: _, shamt } => {
216 let shifted = (rs1_value as u32) << shamt.get();
217 ExecutionResult::Continue {
218 rd,
219 value: i64::from(shifted.cast_signed()).cast_unsigned(),
220 }
221 }
222 Self::Srliw { rd, rs1: _, shamt } => {
223 let shifted = (rs1_value as u32) >> shamt.get();
224 ExecutionResult::Continue {
225 rd,
226 value: i64::from(shifted.cast_signed()).cast_unsigned(),
227 }
228 }
229 Self::Sraiw { rd, rs1: _, shamt } => {
230 let shifted = (rs1_value as i32) >> shamt.get();
231 ExecutionResult::Continue {
232 rd,
233 value: i64::from(shifted).cast_unsigned(),
234 }
235 }
236
237 Self::Lb { rd, rs1: _, imm } => {
238 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
239 let value = i64::from(memory.read::<i8>(addr)?);
240 ExecutionResult::Continue {
241 rd,
242 value: value.cast_unsigned(),
243 }
244 }
245 Self::Lh { rd, rs1: _, imm } => {
246 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
247 let value = i64::from(memory.read::<i16>(addr)?);
248 ExecutionResult::Continue {
249 rd,
250 value: value.cast_unsigned(),
251 }
252 }
253 Self::Lw { rd, rs1: _, imm } => {
254 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
255 let value = i64::from(memory.read::<i32>(addr)?);
256 ExecutionResult::Continue {
257 rd,
258 value: value.cast_unsigned(),
259 }
260 }
261 Self::Ld { rd, rs1: _, imm } => {
262 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
263 let value = memory.read::<u64>(addr)?;
264 ExecutionResult::Continue { rd, value }
265 }
266 Self::Lbu { rd, rs1: _, imm } => {
267 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
268 let value = memory.read::<u8>(addr)?;
269 ExecutionResult::Continue {
270 rd,
271 value: u64::from(value),
272 }
273 }
274 Self::Lhu { rd, rs1: _, imm } => {
275 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
276 let value = memory.read::<u16>(addr)?;
277 ExecutionResult::Continue {
278 rd,
279 value: u64::from(value),
280 }
281 }
282 Self::Lwu { rd, rs1: _, imm } => {
283 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
284 let value = memory.read::<u32>(addr)?;
285 ExecutionResult::Continue {
286 rd,
287 value: u64::from(value),
288 }
289 }
290
291 Self::Jalr { rd, rs1: _, imm } => {
292 let target = (rs1_value.wrapping_add(i64::from(imm).cast_unsigned())) & !1u64;
293 regs.write(rd, program_counter.get_pc());
294
295 ExecutionResult::Jump { target }
296 }
297
298 Self::Sb {
299 rs2: _,
300 rs1: _,
301 imm,
302 } => {
303 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
304 memory.write(addr, rs2_value as u8)?;
305 ExecutionResult::ContinueNoWrite
306 }
307 Self::Sh {
308 rs2: _,
309 rs1: _,
310 imm,
311 } => {
312 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
313 memory.write(addr, rs2_value as u16)?;
314 ExecutionResult::ContinueNoWrite
315 }
316 Self::Sw {
317 rs2: _,
318 rs1: _,
319 imm,
320 } => {
321 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
322 memory.write(addr, rs2_value as u32)?;
323 ExecutionResult::ContinueNoWrite
324 }
325 Self::Sd {
326 rs2: _,
327 rs1: _,
328 imm,
329 } => {
330 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
331 memory.write(addr, rs2_value)?;
332 ExecutionResult::ContinueNoWrite
333 }
334
335 Self::Beq {
336 rs1: _,
337 rs2: _,
338 imm,
339 } => {
340 if rs1_value == rs2_value {
341 return ExecutionResult::Branch {
342 offset: i32::from(imm),
343 };
344 }
345
346 ExecutionResult::ContinueNoWrite
347 }
348 Self::Bne {
349 rs1: _,
350 rs2: _,
351 imm,
352 } => {
353 if rs1_value != rs2_value {
354 return ExecutionResult::Branch {
355 offset: i32::from(imm),
356 };
357 }
358
359 ExecutionResult::ContinueNoWrite
360 }
361 Self::Blt {
362 rs1: _,
363 rs2: _,
364 imm,
365 } => {
366 if rs1_value.cast_signed() < rs2_value.cast_signed() {
367 return ExecutionResult::Branch {
368 offset: i32::from(imm),
369 };
370 }
371
372 ExecutionResult::ContinueNoWrite
373 }
374 Self::Bge {
375 rs1: _,
376 rs2: _,
377 imm,
378 } => {
379 if rs1_value.cast_signed() >= rs2_value.cast_signed() {
380 return ExecutionResult::Branch {
381 offset: i32::from(imm),
382 };
383 }
384
385 ExecutionResult::ContinueNoWrite
386 }
387 Self::Bltu {
388 rs1: _,
389 rs2: _,
390 imm,
391 } => {
392 if rs1_value < rs2_value {
393 return ExecutionResult::Branch {
394 offset: i32::from(imm),
395 };
396 }
397
398 ExecutionResult::ContinueNoWrite
399 }
400 Self::Bgeu {
401 rs1: _,
402 rs2: _,
403 imm,
404 } => {
405 if rs1_value >= rs2_value {
406 return ExecutionResult::Branch {
407 offset: i32::from(imm),
408 };
409 }
410
411 ExecutionResult::ContinueNoWrite
412 }
413
414 Self::Lui { rd, imm } => ExecutionResult::Continue {
415 rd,
416 value: i64::from(imm).cast_unsigned(),
417 },
418
419 Self::Auipc { rd, imm } => {
420 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
421 ExecutionResult::Continue {
422 rd,
423 value: old_pc.wrapping_add(i64::from(imm).cast_unsigned()),
424 }
425 }
426
427 Self::Jal { rd, imm } => {
428 let pc = program_counter.get_pc();
429 regs.write(rd, pc);
430
431 ExecutionResult::Branch {
432 offset: i32::from(imm),
433 }
434 }
435
436 Self::Fence { pred, succ } => {
437 env.handle_fence(pred, succ);
438 ExecutionResult::ContinueNoWrite
439 }
440 Self::FenceTso => {
441 env.handle_fence_tso();
442 ExecutionResult::ContinueNoWrite
443 }
444
445 Self::Ecall => env.handle_ecall(regs, memory, program_counter),
446 Self::Ebreak => {
447 env.handle_ebreak(regs, memory, program_counter, size_of::<u32>() as u8)
448 }
449
450 Self::Unimp => {
451 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
452 ExecutionResult::Err(ExecutionError::IllegalInstruction {
453 address: PackedAddress::new(old_pc),
454 })
455 }
456 }
457 }
458}