Skip to main content

ab_riscv_interpreter/
zicond.rs

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