ab_riscv_interpreter/rv64/zce/
zcmp.rs1pub mod rv64_zcmp_helpers;
4#[cfg(test)]
5mod tests;
6
7use crate::{
8 ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
9 ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands, SystemInstructionHandler,
10 VirtualMemory,
11};
12use ab_riscv_macros::instruction_execution;
13use ab_riscv_primitives::prelude::*;
14use core::ops::ControlFlow;
15
16#[instruction_execution]
17impl<Reg> ExecutableInstructionOperands for Rv64ZcmpInstruction<Reg> where
18 Reg: ZcmpRegister<Type = u64>
19{
20}
21
22#[instruction_execution]
23impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
24 for Rv64ZcmpInstruction<Reg>
25where
26 Reg: ZcmpRegister<Type = u64>,
27{
28}
29
30#[instruction_execution]
31impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
32 ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
33 for Rv64ZcmpInstruction<Reg>
34where
35 Reg: ZcmpRegister<Type = u64>,
36 Regs: RegisterFile<Reg>,
37 Memory: VirtualMemory,
38 PC: ProgramCounter<Reg::Type, Memory, CustomError>,
39 InstructionHandler: SystemInstructionHandler<Reg, Regs, Memory, PC, CustomError>,
40{
41 #[inline(always)]
42 fn execute(
43 self,
44 Rs1Rs2OperandValues {
45 rs1_value,
46 rs2_value,
47 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
48 regs: &mut Regs,
49 _ext_state: &mut ExtState,
50 memory: &mut Memory,
51 program_counter: &mut PC,
52 _system_instruction_handler: &mut InstructionHandler,
53 ) -> Result<
54 ControlFlow<(), (Self::Reg, <Self::Reg as Register>::Type)>,
55 ExecutionError<Reg::Type, CustomError>,
56 > {
57 match self {
58 Self::CmPush { urlist, stack_adj } => {
59 rv64_zcmp_helpers::do_push(regs, memory, urlist, stack_adj)
60 }
61 Self::CmPop { urlist, stack_adj } => {
62 rv64_zcmp_helpers::do_pop(regs, memory, urlist, stack_adj)?;
63 Ok(ControlFlow::Continue(Default::default()))
64 }
65 Self::CmPopretz { urlist, stack_adj } => {
66 let ra_val = rv64_zcmp_helpers::do_pop(regs, memory, urlist, stack_adj)?;
67 regs.write(Reg::A0, 0);
69 let target = ra_val & !1;
71 program_counter
72 .set_pc(memory, target)
73 .map(|control_flow| control_flow.map_continue(|()| Default::default()))
74 .map_err(ExecutionError::from)
75 }
76 Self::CmPopret { urlist, stack_adj } => {
77 let ra_val = rv64_zcmp_helpers::do_pop(regs, memory, urlist, stack_adj)?;
78 let target = ra_val & !1;
80 program_counter
81 .set_pc(memory, target)
82 .map(|control_flow| control_flow.map_continue(|()| Default::default()))
83 .map_err(ExecutionError::from)
84 }
85 Self::CmMva01s { rs1: _, rs2: _ } => {
86 let v1 = rs1_value;
88 let v2 = rs2_value;
89 regs.write(Reg::A0, v1);
90 Ok(ControlFlow::Continue((Reg::A1, v2)))
91 }
92 Self::CmMvsa01 { rs1, rs2 } => {
93 let a0_val = regs.read(Reg::A0);
95 let a1_val = regs.read(Reg::A1);
96 regs.write(rs1, a0_val);
97 Ok(ControlFlow::Continue((rs2, a1_val)))
98 }
99 }
100 }
101}