Skip to main content

ab_riscv_interpreter/rv32/zce/
zcb.rs

1//! Zcb compressed instruction execution (RV32)
2//!
3//! C.ZEXT.W is absent in RV32 - the enum has no such variant.
4
5#[cfg(test)]
6mod tests;
7
8use crate::{
9    ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
10    ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands, SystemInstructionHandler,
11    VirtualMemory,
12};
13use ab_riscv_macros::instruction_execution;
14use ab_riscv_primitives::prelude::*;
15use core::ops::ControlFlow;
16
17#[instruction_execution]
18impl<Reg> ExecutableInstructionOperands for Rv32ZcbInstruction<Reg> where Reg: Register<Type = u32> {}
19
20#[instruction_execution]
21impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
22    for Rv32ZcbInstruction<Reg>
23where
24    Reg: Register<Type = u32>,
25{
26}
27
28#[instruction_execution]
29impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
30    ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
31    for Rv32ZcbInstruction<Reg>
32where
33    Reg: Register<Type = u32>,
34    Regs: RegisterFile<Reg>,
35    Memory: VirtualMemory,
36    PC: ProgramCounter<Reg::Type, Memory, CustomError>,
37    InstructionHandler: SystemInstructionHandler<Reg, Regs, Memory, PC, CustomError>,
38{
39    #[inline(always)]
40    fn execute(
41        self,
42        Rs1Rs2OperandValues {
43            rs1_value,
44            rs2_value,
45        }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
46        regs: &mut Regs,
47        _ext_state: &mut ExtState,
48        memory: &mut Memory,
49        _program_counter: &mut PC,
50        _system_instruction_handler: &mut InstructionHandler,
51    ) -> Result<
52        ControlFlow<(), (Self::Reg, <Self::Reg as Register>::Type)>,
53        ExecutionError<Reg::Type, CustomError>,
54    > {
55        match self {
56            Self::CLbu { rd, rs1: _, uimm } => {
57                let addr = u64::from(rs1_value.wrapping_add(u32::from(uimm)));
58                let value = memory.read::<u8>(addr)?;
59                Ok(ControlFlow::Continue((rd, u32::from(value))))
60            }
61            Self::CLh { rd, rs1: _, uimm } => {
62                let addr = u64::from(rs1_value.wrapping_add(u32::from(uimm)));
63                let value = i32::from(memory.read::<i16>(addr)?);
64                Ok(ControlFlow::Continue((rd, value.cast_unsigned())))
65            }
66            Self::CLhu { rd, rs1: _, uimm } => {
67                let addr = u64::from(rs1_value.wrapping_add(u32::from(uimm)));
68                let value = memory.read::<u16>(addr)?;
69                Ok(ControlFlow::Continue((rd, u32::from(value))))
70            }
71            Self::CSb {
72                rs1: _,
73                rs2: _,
74                uimm,
75            } => {
76                let addr = u64::from(rs1_value.wrapping_add(u32::from(uimm)));
77                memory.write(addr, rs2_value as u8)?;
78                Ok(ControlFlow::Continue(Default::default()))
79            }
80            Self::CSh {
81                rs1: _,
82                rs2: _,
83                uimm,
84            } => {
85                let addr = u64::from(rs1_value.wrapping_add(u32::from(uimm)));
86                memory.write(addr, rs2_value as u16)?;
87                Ok(ControlFlow::Continue(Default::default()))
88            }
89            Self::CZextB { rd } => {
90                let value = regs.read(rd) & 0xff;
91                Ok(ControlFlow::Continue((rd, value)))
92            }
93            Self::CSextB { rd } => {
94                let value = i32::from(regs.read(rd) as i8);
95                Ok(ControlFlow::Continue((rd, value.cast_unsigned())))
96            }
97            Self::CZextH { rd } => {
98                let value = regs.read(rd) & 0xffff;
99                Ok(ControlFlow::Continue((rd, value)))
100            }
101            Self::CSextH { rd } => {
102                let value = i32::from(regs.read(rd) as i16);
103                Ok(ControlFlow::Continue((rd, value.cast_unsigned())))
104            }
105            Self::CNot { rd } => {
106                let value = !regs.read(rd);
107                Ok(ControlFlow::Continue((rd, value)))
108            }
109            Self::CMul { rd, rs2: _ } => {
110                let value = regs.read(rd).wrapping_mul(rs2_value);
111                Ok(ControlFlow::Continue((rd, value)))
112            }
113        }
114    }
115}