Skip to main content

ab_riscv_interpreter/rv32/c/
zca.rs

1//! RV32 Zca extension
2
3#[cfg(test)]
4mod tests;
5
6use crate::{
7    ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
8    ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands, SystemInstructionHandler,
9    VirtualMemory,
10};
11use ab_riscv_macros::instruction_execution;
12use ab_riscv_primitives::prelude::*;
13use core::ops::ControlFlow;
14
15#[instruction_execution]
16impl<Reg> ExecutableInstructionOperands for Rv32ZcaInstruction<Reg> where Reg: Register<Type = u32> {}
17
18#[instruction_execution]
19impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
20    for Rv32ZcaInstruction<Reg>
21where
22    Reg: Register<Type = u32>,
23{
24}
25
26#[instruction_execution]
27impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
28    ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
29    for Rv32ZcaInstruction<Reg>
30where
31    Reg: Register<Type = u32>,
32    Regs: RegisterFile<Reg>,
33    Memory: VirtualMemory,
34    PC: ProgramCounter<Reg::Type, Memory, CustomError>,
35    InstructionHandler: SystemInstructionHandler<Reg, Regs, Memory, PC, CustomError>,
36{
37    #[inline(always)]
38    fn execute(
39        self,
40        Rs1Rs2OperandValues {
41            rs1_value,
42            rs2_value,
43        }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
44        regs: &mut Regs,
45        _ext_state: &mut ExtState,
46        memory: &mut Memory,
47        program_counter: &mut PC,
48        system_instruction_handler: &mut InstructionHandler,
49    ) -> Result<
50        ControlFlow<(), (Self::Reg, <Self::Reg as Register>::Type)>,
51        ExecutionError<Reg::Type, CustomError>,
52    > {
53        match self {
54            // Quadrant 00
55            Self::CAddi4spn { rd, nzuimm } => {
56                let sp_val = regs.read(Reg::SP);
57                Ok(ControlFlow::Continue((
58                    rd,
59                    sp_val.wrapping_add(u32::from(nzuimm)),
60                )))
61            }
62            Self::CLw { rd, rs1: _, uimm } => {
63                let addr = rs1_value.wrapping_add(u32::from(uimm));
64                let value = memory.read::<i32>(u64::from(addr))?.cast_unsigned();
65                Ok(ControlFlow::Continue((rd, value)))
66            }
67            Self::CSw {
68                rs1: _,
69                rs2: _,
70                uimm,
71            } => {
72                let addr = rs1_value.wrapping_add(u32::from(uimm));
73                memory.write(u64::from(addr), rs2_value)?;
74                Ok(ControlFlow::Continue(Default::default()))
75            }
76
77            // Quadrant 01
78            Self::CNop => Ok(ControlFlow::Continue(Default::default())),
79            Self::CAddi { rd, nzimm } => {
80                let value = regs.read(rd).wrapping_add(i32::from(nzimm).cast_unsigned());
81                Ok(ControlFlow::Continue((rd, value)))
82            }
83            Self::CJal { imm } => {
84                let return_addr = program_counter.get_pc();
85                regs.write(Reg::RA, return_addr);
86                let old_pc = program_counter.old_pc(size_of::<u16>() as u8);
87                program_counter
88                    .set_pc(memory, old_pc.wrapping_add(i32::from(imm).cast_unsigned()))
89                    .map(|control_flow| control_flow.map_continue(|()| Default::default()))
90                    .map_err(ExecutionError::from)
91            }
92            Self::CLi { rd, imm } => {
93                Ok(ControlFlow::Continue((rd, i32::from(imm).cast_unsigned())))
94            }
95            Self::CAddi16sp { nzimm } => {
96                let value = regs
97                    .read(Reg::SP)
98                    .wrapping_add(i32::from(nzimm).cast_unsigned());
99                Ok(ControlFlow::Continue((Reg::SP, value)))
100            }
101            Self::CLui { rd, nzimm } => {
102                Ok(ControlFlow::Continue((rd, nzimm.to_i32().cast_unsigned())))
103            }
104            Self::CSrli { rd, shamt } => {
105                let value = regs.read(rd) >> shamt;
106                Ok(ControlFlow::Continue((rd, value)))
107            }
108            Self::CSrai { rd, shamt } => {
109                let value = regs.read(rd).cast_signed() >> shamt;
110                Ok(ControlFlow::Continue((rd, value.cast_unsigned())))
111            }
112            Self::CAndi { rd, imm } => {
113                let value = regs.read(rd) & i32::from(imm).cast_unsigned();
114                Ok(ControlFlow::Continue((rd, value)))
115            }
116            Self::CSub { rd, rs2: _ } => {
117                let value = regs.read(rd).wrapping_sub(rs2_value);
118                Ok(ControlFlow::Continue((rd, value)))
119            }
120            Self::CXor { rd, rs2: _ } => {
121                let value = regs.read(rd) ^ rs2_value;
122                Ok(ControlFlow::Continue((rd, value)))
123            }
124            Self::COr { rd, rs2: _ } => {
125                let value = regs.read(rd) | rs2_value;
126                Ok(ControlFlow::Continue((rd, value)))
127            }
128            Self::CAnd { rd, rs2: _ } => {
129                let value = regs.read(rd) & rs2_value;
130                Ok(ControlFlow::Continue((rd, value)))
131            }
132            Self::CJ { imm } => {
133                let old_pc = program_counter.old_pc(size_of::<u16>() as u8);
134                program_counter
135                    .set_pc(memory, old_pc.wrapping_add(i32::from(imm).cast_unsigned()))
136                    .map(|control_flow| control_flow.map_continue(|()| Default::default()))
137                    .map_err(ExecutionError::from)
138            }
139            Self::CBeqz { rs1: _, imm } => {
140                if rs1_value == 0 {
141                    let old_pc = program_counter.old_pc(size_of::<u16>() as u8);
142                    return program_counter
143                        .set_pc(memory, old_pc.wrapping_add(i32::from(imm).cast_unsigned()))
144                        .map(|control_flow| control_flow.map_continue(|()| Default::default()))
145                        .map_err(ExecutionError::from);
146                }
147
148                Ok(ControlFlow::Continue(Default::default()))
149            }
150            Self::CBnez { rs1: _, imm } => {
151                if rs1_value != 0 {
152                    let old_pc = program_counter.old_pc(size_of::<u16>() as u8);
153                    return program_counter
154                        .set_pc(memory, old_pc.wrapping_add(i32::from(imm).cast_unsigned()))
155                        .map(|control_flow| control_flow.map_continue(|()| Default::default()))
156                        .map_err(ExecutionError::from);
157                }
158
159                Ok(ControlFlow::Continue(Default::default()))
160            }
161
162            // Quadrant 10
163            Self::CSlli { rd, shamt } => {
164                let value = regs.read(rd) << shamt;
165                Ok(ControlFlow::Continue((rd, value)))
166            }
167            Self::CLwsp { rd, uimm } => {
168                let addr = regs.read(Reg::SP).wrapping_add(u32::from(uimm));
169                let value = memory.read::<i32>(u64::from(addr))?.cast_unsigned();
170                Ok(ControlFlow::Continue((rd, value)))
171            }
172            Self::CJr { rs1: _ } => {
173                let target = rs1_value & !1;
174                program_counter
175                    .set_pc(memory, target)
176                    .map(|control_flow| control_flow.map_continue(|()| Default::default()))
177                    .map_err(ExecutionError::from)
178            }
179            Self::CMv { rd, rs2: _ } => Ok(ControlFlow::Continue((rd, rs2_value))),
180            Self::CEbreak => {
181                system_instruction_handler.handle_ebreak(regs, memory, program_counter.get_pc());
182                Ok(ControlFlow::Continue(Default::default()))
183            }
184            Self::CJalr { rs1: _ } => {
185                let target = rs1_value & !1;
186                let return_addr = program_counter.get_pc();
187                regs.write(Reg::RA, return_addr);
188                return program_counter
189                    .set_pc(memory, target)
190                    .map(|control_flow| control_flow.map_continue(|()| Default::default()))
191                    .map_err(ExecutionError::from);
192            }
193            Self::CAdd { rd, rs2: _ } => {
194                let value = regs.read(rd).wrapping_add(rs2_value);
195                Ok(ControlFlow::Continue((rd, value)))
196            }
197            Self::CSwsp { rs2: _, uimm } => {
198                let addr = regs.read(Reg::SP).wrapping_add(u32::from(uimm));
199                memory.write(u64::from(addr), rs2_value)?;
200                Ok(ControlFlow::Continue(Default::default()))
201            }
202            Self::CUnimp => {
203                let old_pc = program_counter.old_pc(size_of::<u16>() as u8);
204                Err(ExecutionError::IllegalInstruction { address: old_pc })
205            }
206        }
207    }
208}