Skip to main content

ab_riscv_interpreter/
rv32.rs

1//! Base RISC-V RV32 instruction set
2
3pub mod b;
4pub mod c;
5pub mod m;
6#[cfg(test)]
7pub(crate) mod test_utils;
8#[cfg(test)]
9mod tests;
10pub mod zce;
11pub mod zk;
12
13use crate::{
14    ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
15    ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands, SystemInstructionHandler,
16    VirtualMemory,
17};
18use ab_riscv_macros::instruction_execution;
19use ab_riscv_primitives::prelude::*;
20use core::ops::ControlFlow;
21
22#[instruction_execution]
23impl<Reg> ExecutableInstructionOperands for Rv32Instruction<Reg> where Reg: Register<Type = u32> {}
24
25#[instruction_execution]
26impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
27    for Rv32Instruction<Reg>
28where
29    Reg: Register<Type = u32>,
30{
31}
32
33#[instruction_execution]
34impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
35    ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
36    for Rv32Instruction<Reg>
37where
38    Reg: Register<Type = u32>,
39    Regs: RegisterFile<Reg>,
40    Memory: VirtualMemory,
41    PC: ProgramCounter<Reg::Type, Memory, CustomError>,
42    InstructionHandler: SystemInstructionHandler<Reg, Regs, Memory, PC, CustomError>,
43{
44    #[inline(always)]
45    fn execute(
46        self,
47        Rs1Rs2OperandValues {
48            rs1_value,
49            rs2_value,
50        }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
51        regs: &mut Regs,
52        _ext_state: &mut ExtState,
53        memory: &mut Memory,
54        program_counter: &mut PC,
55        system_instruction_handler: &mut InstructionHandler,
56    ) -> Result<
57        ControlFlow<(), (Self::Reg, <Self::Reg as Register>::Type)>,
58        ExecutionError<Reg::Type, CustomError>,
59    > {
60        match self {
61            Self::Add { rd, rs1: _, rs2: _ } => {
62                let value = rs1_value.wrapping_add(rs2_value);
63                Ok(ControlFlow::Continue((rd, value)))
64            }
65            Self::Sub { rd, rs1: _, rs2: _ } => {
66                let value = rs1_value.wrapping_sub(rs2_value);
67                Ok(ControlFlow::Continue((rd, value)))
68            }
69            Self::Sll { rd, rs1: _, rs2: _ } => {
70                let shamt = rs2_value & 0x1f;
71                let value = rs1_value << shamt;
72                Ok(ControlFlow::Continue((rd, value)))
73            }
74            Self::Slt { rd, rs1: _, rs2: _ } => {
75                let value = rs1_value.cast_signed() < rs2_value.cast_signed();
76                Ok(ControlFlow::Continue((rd, value as u32)))
77            }
78            Self::Sltu { rd, rs1: _, rs2: _ } => {
79                let value = rs1_value < rs2_value;
80                Ok(ControlFlow::Continue((rd, value as u32)))
81            }
82            Self::Xor { rd, rs1: _, rs2: _ } => {
83                let value = rs1_value ^ rs2_value;
84                Ok(ControlFlow::Continue((rd, value)))
85            }
86            Self::Srl { rd, rs1: _, rs2: _ } => {
87                let shamt = rs2_value & 0x1f;
88                let value = rs1_value >> shamt;
89                Ok(ControlFlow::Continue((rd, value)))
90            }
91            Self::Sra { rd, rs1: _, rs2: _ } => {
92                let shamt = rs2_value & 0x1f;
93                let value = rs1_value.cast_signed() >> shamt;
94                Ok(ControlFlow::Continue((rd, value.cast_unsigned())))
95            }
96            Self::Or { rd, rs1: _, rs2: _ } => {
97                let value = rs1_value | rs2_value;
98                Ok(ControlFlow::Continue((rd, value)))
99            }
100            Self::And { rd, rs1: _, rs2: _ } => {
101                let value = rs1_value & rs2_value;
102                Ok(ControlFlow::Continue((rd, value)))
103            }
104
105            Self::Addi { rd, rs1: _, imm } => {
106                let value = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
107                Ok(ControlFlow::Continue((rd, value)))
108            }
109            Self::Slti { rd, rs1: _, imm } => {
110                let value = rs1_value.cast_signed() < i32::from(imm);
111                Ok(ControlFlow::Continue((rd, value as u32)))
112            }
113            Self::Sltiu { rd, rs1: _, imm } => {
114                let value = rs1_value < i32::from(imm).cast_unsigned();
115                Ok(ControlFlow::Continue((rd, value as u32)))
116            }
117            Self::Xori { rd, rs1: _, imm } => {
118                let value = rs1_value ^ i32::from(imm).cast_unsigned();
119                Ok(ControlFlow::Continue((rd, value)))
120            }
121            Self::Ori { rd, rs1: _, imm } => {
122                let value = rs1_value | i32::from(imm).cast_unsigned();
123                Ok(ControlFlow::Continue((rd, value)))
124            }
125            Self::Andi { rd, rs1: _, imm } => {
126                let value = rs1_value & i32::from(imm).cast_unsigned();
127                Ok(ControlFlow::Continue((rd, value)))
128            }
129            Self::Slli { rd, rs1: _, shamt } => {
130                let value = rs1_value << shamt;
131                Ok(ControlFlow::Continue((rd, value)))
132            }
133            Self::Srli { rd, rs1: _, shamt } => {
134                let value = rs1_value >> shamt;
135                Ok(ControlFlow::Continue((rd, value)))
136            }
137            Self::Srai { rd, rs1: _, shamt } => {
138                let value = rs1_value.cast_signed() >> shamt;
139                Ok(ControlFlow::Continue((rd, value.cast_unsigned())))
140            }
141
142            Self::Lb { rd, rs1: _, imm } => {
143                let addr = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
144                let value = i32::from(memory.read::<i8>(u64::from(addr))?);
145                Ok(ControlFlow::Continue((rd, value.cast_unsigned())))
146            }
147            Self::Lh { rd, rs1: _, imm } => {
148                let addr = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
149                let value = i32::from(memory.read::<i16>(u64::from(addr))?);
150                Ok(ControlFlow::Continue((rd, value.cast_unsigned())))
151            }
152            Self::Lw { rd, rs1: _, imm } => {
153                let addr = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
154                let value = memory.read::<u32>(u64::from(addr))?;
155                Ok(ControlFlow::Continue((rd, value)))
156            }
157            Self::Lbu { rd, rs1: _, imm } => {
158                let addr = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
159                let value = memory.read::<u8>(u64::from(addr))?;
160                Ok(ControlFlow::Continue((rd, value as u32)))
161            }
162            Self::Lhu { rd, rs1: _, imm } => {
163                let addr = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
164                let value = memory.read::<u16>(u64::from(addr))?;
165                Ok(ControlFlow::Continue((rd, value as u32)))
166            }
167
168            Self::Jalr { rd, rs1: _, imm } => {
169                let target = (rs1_value.wrapping_add(i32::from(imm).cast_unsigned())) & !1u32;
170                regs.write(rd, program_counter.get_pc());
171                return program_counter
172                    .set_pc(memory, target)
173                    .map(|control_flow| control_flow.map_continue(|()| Default::default()))
174                    .map_err(ExecutionError::from);
175            }
176
177            Self::Sb {
178                rs2: _,
179                rs1: _,
180                imm,
181            } => {
182                let addr = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
183                memory.write(u64::from(addr), rs2_value as u8)?;
184                Ok(ControlFlow::Continue(Default::default()))
185            }
186            Self::Sh {
187                rs2: _,
188                rs1: _,
189                imm,
190            } => {
191                let addr = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
192                memory.write(u64::from(addr), rs2_value as u16)?;
193                Ok(ControlFlow::Continue(Default::default()))
194            }
195            Self::Sw {
196                rs2: _,
197                rs1: _,
198                imm,
199            } => {
200                let addr = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
201                memory.write(u64::from(addr), rs2_value)?;
202                Ok(ControlFlow::Continue(Default::default()))
203            }
204
205            Self::Beq {
206                rs1: _,
207                rs2: _,
208                imm,
209            } => {
210                if rs1_value == rs2_value {
211                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
212                    return program_counter
213                        .set_pc(memory, old_pc.wrapping_add(imm.to_i32().cast_unsigned()))
214                        .map(|control_flow| control_flow.map_continue(|()| Default::default()))
215                        .map_err(ExecutionError::from);
216                }
217
218                Ok(ControlFlow::Continue(Default::default()))
219            }
220            Self::Bne {
221                rs1: _,
222                rs2: _,
223                imm,
224            } => {
225                if rs1_value != rs2_value {
226                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
227                    return program_counter
228                        .set_pc(memory, old_pc.wrapping_add(imm.to_i32().cast_unsigned()))
229                        .map(|control_flow| control_flow.map_continue(|()| Default::default()))
230                        .map_err(ExecutionError::from);
231                }
232
233                Ok(ControlFlow::Continue(Default::default()))
234            }
235            Self::Blt {
236                rs1: _,
237                rs2: _,
238                imm,
239            } => {
240                if rs1_value.cast_signed() < rs2_value.cast_signed() {
241                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
242                    return program_counter
243                        .set_pc(memory, old_pc.wrapping_add(imm.to_i32().cast_unsigned()))
244                        .map(|control_flow| control_flow.map_continue(|()| Default::default()))
245                        .map_err(ExecutionError::from);
246                }
247
248                Ok(ControlFlow::Continue(Default::default()))
249            }
250            Self::Bge {
251                rs1: _,
252                rs2: _,
253                imm,
254            } => {
255                if rs1_value.cast_signed() >= rs2_value.cast_signed() {
256                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
257                    return program_counter
258                        .set_pc(memory, old_pc.wrapping_add(imm.to_i32().cast_unsigned()))
259                        .map(|control_flow| control_flow.map_continue(|()| Default::default()))
260                        .map_err(ExecutionError::from);
261                }
262
263                Ok(ControlFlow::Continue(Default::default()))
264            }
265            Self::Bltu {
266                rs1: _,
267                rs2: _,
268                imm,
269            } => {
270                if rs1_value < rs2_value {
271                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
272                    return program_counter
273                        .set_pc(memory, old_pc.wrapping_add(imm.to_i32().cast_unsigned()))
274                        .map(|control_flow| control_flow.map_continue(|()| Default::default()))
275                        .map_err(ExecutionError::from);
276                }
277
278                Ok(ControlFlow::Continue(Default::default()))
279            }
280            Self::Bgeu {
281                rs1: _,
282                rs2: _,
283                imm,
284            } => {
285                if rs1_value >= rs2_value {
286                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
287                    return program_counter
288                        .set_pc(memory, old_pc.wrapping_add(imm.to_i32().cast_unsigned()))
289                        .map(|control_flow| control_flow.map_continue(|()| Default::default()))
290                        .map_err(ExecutionError::from);
291                }
292
293                Ok(ControlFlow::Continue(Default::default()))
294            }
295
296            Self::Lui { rd, imm } => Ok(ControlFlow::Continue((rd, imm.to_i32().cast_unsigned()))),
297
298            Self::Auipc { rd, imm } => {
299                let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
300                Ok(ControlFlow::Continue((
301                    rd,
302                    old_pc.wrapping_add(imm.to_i32().cast_unsigned()),
303                )))
304            }
305
306            Self::Jal { rd, imm } => {
307                let pc = program_counter.get_pc();
308                let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
309                regs.write(rd, pc);
310                return program_counter
311                    .set_pc(memory, old_pc.wrapping_add(imm.to_i32().cast_unsigned()))
312                    .map(|control_flow| control_flow.map_continue(|()| Default::default()))
313                    .map_err(ExecutionError::from);
314            }
315
316            Self::Fence { pred, succ } => {
317                system_instruction_handler.handle_fence(pred, succ);
318                Ok(ControlFlow::Continue(Default::default()))
319            }
320            Self::FenceTso => {
321                system_instruction_handler.handle_fence_tso();
322                Ok(ControlFlow::Continue(Default::default()))
323            }
324
325            Self::Ecall => {
326                return system_instruction_handler
327                    .handle_ecall(regs, memory, program_counter)
328                    .map(|control_flow| control_flow.map_continue(|()| Default::default()));
329            }
330            Self::Ebreak => {
331                system_instruction_handler.handle_ebreak(regs, memory, program_counter.get_pc());
332                Ok(ControlFlow::Continue(Default::default()))
333            }
334
335            Self::Unimp => {
336                let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
337                return Err(ExecutionError::IllegalInstruction { address: old_pc });
338            }
339        }
340    }
341}