Skip to main content

ab_riscv_interpreter/
rv32.rs

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