Skip to main content

ab_riscv_interpreter/
zicond.rs

1//! Zicond extension
2
3#[cfg(test)]
4mod tests;
5
6use crate::{
7    ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
8    RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
9};
10use ab_riscv_macros::instruction_execution;
11use ab_riscv_primitives::prelude::*;
12use core::ops::ControlFlow;
13
14#[instruction_execution]
15impl<Reg> ExecutableInstructionOperands for ZicondInstruction<Reg> where Reg: Register {}
16
17#[instruction_execution]
18impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
19    for ZicondInstruction<Reg>
20where
21    Reg: Register,
22{
23}
24
25#[instruction_execution]
26impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
27    ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
28    for ZicondInstruction<Reg>
29where
30    Reg: Register,
31    Regs: RegisterFile<Reg>,
32{
33    #[inline(always)]
34    fn execute(
35        self,
36        Rs1Rs2OperandValues {
37            rs1_value,
38            rs2_value,
39        }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
40        _regs: &mut Regs,
41        _ext_state: &mut ExtState,
42        _memory: &mut Memory,
43        _program_counter: &mut PC,
44        _system_instruction_handler: &mut InstructionHandler,
45    ) -> Result<
46        ControlFlow<(), (Self::Reg, <Self::Reg as Register>::Type)>,
47        ExecutionError<Reg::Type, CustomError>,
48    > {
49        match self {
50            // Conditional zero, equal to zero.
51            //
52            // rd = (rs2 == 0) ? 0 : rs1
53            Self::CzeroEqz { rd, rs1: _, rs2: _ } => {
54                let condition = rs2_value;
55                let src = rs1_value;
56                let result = if condition == Reg::Type::from(0u8) {
57                    Reg::Type::from(0u8)
58                } else {
59                    src
60                };
61                Ok(ControlFlow::Continue((rd, result)))
62            }
63
64            // Conditional zero, nonzero.
65            //
66            // rd = (rs2 != 0) ? 0 : rs1
67            Self::CzeroNez { rd, rs1: _, rs2: _ } => {
68                let condition = rs2_value;
69                let src = rs1_value;
70                let result = if condition != Reg::Type::from(0u8) {
71                    Reg::Type::from(0u8)
72                } else {
73                    src
74                };
75                Ok(ControlFlow::Continue((rd, result)))
76            }
77        }
78    }
79}