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    ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
9    RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands, ThreadedExecutableInstruction,
10    ThreadedExecutionResult,
11};
12use ab_riscv_macros::instruction_execution;
13use ab_riscv_primitives::prelude::*;
14
15#[instruction_execution]
16const impl<Reg> ExecutableInstructionOperands for ZicondInstruction<Reg> where Reg: Register {}
17
18#[instruction_execution]
19const impl<Reg, Env> ExecutableInstructionCsr<Env> for ZicondInstruction<Reg> where Reg: Register {}
20
21#[instruction_execution]
22const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
23    for ZicondInstruction<Reg>
24where
25    Reg: [const] Register,
26    Regs: [const] RegisterFile<Reg>,
27{
28    #[inline(always)]
29    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
30    fn execute(
31        self,
32        Rs1Rs2OperandValues {
33            rs1_value,
34            rs2_value,
35        }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
36        _regs: &mut Regs,
37        _env: &mut Env,
38        _memory: &mut Memory,
39        _program_counter: &mut PC,
40    ) -> ExecutionResult<Self::Reg> {
41        match self {
42            // Conditional zero, equal to zero.
43            //
44            // rd = (rs2 == 0) ? 0 : rs1
45            Self::CzeroEqz { rd, rs1: _, rs2: _ } => {
46                let condition = rs2_value;
47                let src = rs1_value;
48                let result = if condition == Reg::Type::from(0u8) {
49                    Reg::Type::from(0u8)
50                } else {
51                    src
52                };
53                ExecutionResult::Continue { rd, value: result }
54            }
55
56            // Conditional zero, nonzero.
57            //
58            // rd = (rs2 != 0) ? 0 : rs1
59            Self::CzeroNez { rd, rs1: _, rs2: _ } => {
60                let condition = rs2_value;
61                let src = rs1_value;
62                let result = if condition == Reg::Type::from(0u8) {
63                    src
64                } else {
65                    Reg::Type::from(0u8)
66                };
67                ExecutionResult::Continue { rd, value: result }
68            }
69        }
70    }
71}