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, ExecutionError, ProgramCounter, RegisterFile, SystemInstructionHandler,
15    VirtualMemory,
16};
17use ab_riscv_macros::instruction_execution;
18use ab_riscv_primitives::prelude::*;
19use core::ops::ControlFlow;
20
21#[instruction_execution]
22impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
23    ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
24    for Rv32Instruction<Reg>
25where
26    Reg: Register<Type = u32>,
27    Regs: RegisterFile<Reg>,
28    Memory: VirtualMemory,
29    PC: ProgramCounter<Reg::Type, Memory, CustomError>,
30    InstructionHandler: SystemInstructionHandler<Reg, Regs, Memory, PC, CustomError>,
31{
32    #[inline(always)]
33    fn execute(
34        self,
35        regs: &mut Regs,
36        _ext_state: &mut ExtState,
37        memory: &mut Memory,
38        program_counter: &mut PC,
39        system_instruction_handler: &mut InstructionHandler,
40    ) -> Result<ControlFlow<()>, ExecutionError<Reg::Type, CustomError>> {
41        match self {
42            Self::Add { rd, rs1, rs2 } => {
43                let value = regs.read(rs1).wrapping_add(regs.read(rs2));
44                regs.write(rd, value);
45            }
46            Self::Sub { rd, rs1, rs2 } => {
47                let value = regs.read(rs1).wrapping_sub(regs.read(rs2));
48                regs.write(rd, value);
49            }
50            Self::Sll { rd, rs1, rs2 } => {
51                let shamt = regs.read(rs2) & 0x1f;
52                let value = regs.read(rs1) << shamt;
53                regs.write(rd, value);
54            }
55            Self::Slt { rd, rs1, rs2 } => {
56                let value = regs.read(rs1).cast_signed() < regs.read(rs2).cast_signed();
57                regs.write(rd, value as u32);
58            }
59            Self::Sltu { rd, rs1, rs2 } => {
60                let value = regs.read(rs1) < regs.read(rs2);
61                regs.write(rd, value as u32);
62            }
63            Self::Xor { rd, rs1, rs2 } => {
64                let value = regs.read(rs1) ^ regs.read(rs2);
65                regs.write(rd, value);
66            }
67            Self::Srl { rd, rs1, rs2 } => {
68                let shamt = regs.read(rs2) & 0x1f;
69                let value = regs.read(rs1) >> shamt;
70                regs.write(rd, value);
71            }
72            Self::Sra { rd, rs1, rs2 } => {
73                let shamt = regs.read(rs2) & 0x1f;
74                let value = regs.read(rs1).cast_signed() >> shamt;
75                regs.write(rd, value.cast_unsigned());
76            }
77            Self::Or { rd, rs1, rs2 } => {
78                let value = regs.read(rs1) | regs.read(rs2);
79                regs.write(rd, value);
80            }
81            Self::And { rd, rs1, rs2 } => {
82                let value = regs.read(rs1) & regs.read(rs2);
83                regs.write(rd, value);
84            }
85
86            Self::Addi { rd, rs1, imm } => {
87                let value = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
88                regs.write(rd, value);
89            }
90            Self::Slti { rd, rs1, imm } => {
91                let value = regs.read(rs1).cast_signed() < i32::from(imm);
92                regs.write(rd, value as u32);
93            }
94            Self::Sltiu { rd, rs1, imm } => {
95                let value = regs.read(rs1) < i32::from(imm).cast_unsigned();
96                regs.write(rd, value as u32);
97            }
98            Self::Xori { rd, rs1, imm } => {
99                let value = regs.read(rs1) ^ i32::from(imm).cast_unsigned();
100                regs.write(rd, value);
101            }
102            Self::Ori { rd, rs1, imm } => {
103                let value = regs.read(rs1) | i32::from(imm).cast_unsigned();
104                regs.write(rd, value);
105            }
106            Self::Andi { rd, rs1, imm } => {
107                let value = regs.read(rs1) & i32::from(imm).cast_unsigned();
108                regs.write(rd, value);
109            }
110            Self::Slli { rd, rs1, shamt } => {
111                let value = regs.read(rs1) << shamt;
112                regs.write(rd, value);
113            }
114            Self::Srli { rd, rs1, shamt } => {
115                let value = regs.read(rs1) >> shamt;
116                regs.write(rd, value);
117            }
118            Self::Srai { rd, rs1, shamt } => {
119                let value = regs.read(rs1).cast_signed() >> shamt;
120                regs.write(rd, value.cast_unsigned());
121            }
122
123            Self::Lb { rd, rs1, imm } => {
124                let addr = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
125                let value = i32::from(memory.read::<i8>(u64::from(addr))?);
126                regs.write(rd, value.cast_unsigned());
127            }
128            Self::Lh { rd, rs1, imm } => {
129                let addr = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
130                let value = i32::from(memory.read::<i16>(u64::from(addr))?);
131                regs.write(rd, value.cast_unsigned());
132            }
133            Self::Lw { rd, rs1, imm } => {
134                let addr = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
135                let value = memory.read::<u32>(u64::from(addr))?;
136                regs.write(rd, value);
137            }
138            Self::Lbu { rd, rs1, imm } => {
139                let addr = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
140                let value = memory.read::<u8>(u64::from(addr))?;
141                regs.write(rd, value as u32);
142            }
143            Self::Lhu { rd, rs1, imm } => {
144                let addr = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
145                let value = memory.read::<u16>(u64::from(addr))?;
146                regs.write(rd, value as u32);
147            }
148
149            Self::Jalr { rd, rs1, imm } => {
150                let target = (regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned())) & !1u32;
151                regs.write(rd, program_counter.get_pc());
152                return program_counter
153                    .set_pc(memory, target)
154                    .map_err(ExecutionError::from);
155            }
156
157            Self::Sb { rs2, rs1, imm } => {
158                let addr = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
159                memory.write(u64::from(addr), regs.read(rs2) as u8)?;
160            }
161            Self::Sh { rs2, rs1, imm } => {
162                let addr = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
163                memory.write(u64::from(addr), regs.read(rs2) as u16)?;
164            }
165            Self::Sw { rs2, rs1, imm } => {
166                let addr = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
167                memory.write(u64::from(addr), regs.read(rs2))?;
168            }
169
170            Self::Beq { rs1, rs2, imm } => {
171                if regs.read(rs1) == regs.read(rs2) {
172                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
173                    return program_counter
174                        .set_pc(memory, old_pc.wrapping_add(imm.cast_unsigned()))
175                        .map_err(ExecutionError::from);
176                }
177            }
178            Self::Bne { rs1, rs2, imm } => {
179                if regs.read(rs1) != regs.read(rs2) {
180                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
181                    return program_counter
182                        .set_pc(memory, old_pc.wrapping_add(imm.cast_unsigned()))
183                        .map_err(ExecutionError::from);
184                }
185            }
186            Self::Blt { rs1, rs2, imm } => {
187                if regs.read(rs1).cast_signed() < regs.read(rs2).cast_signed() {
188                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
189                    return program_counter
190                        .set_pc(memory, old_pc.wrapping_add(imm.cast_unsigned()))
191                        .map_err(ExecutionError::from);
192                }
193            }
194            Self::Bge { rs1, rs2, imm } => {
195                if regs.read(rs1).cast_signed() >= regs.read(rs2).cast_signed() {
196                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
197                    return program_counter
198                        .set_pc(memory, old_pc.wrapping_add(imm.cast_unsigned()))
199                        .map_err(ExecutionError::from);
200                }
201            }
202            Self::Bltu { rs1, rs2, imm } => {
203                if regs.read(rs1) < regs.read(rs2) {
204                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
205                    return program_counter
206                        .set_pc(memory, old_pc.wrapping_add(imm.cast_unsigned()))
207                        .map_err(ExecutionError::from);
208                }
209            }
210            Self::Bgeu { rs1, rs2, imm } => {
211                if regs.read(rs1) >= regs.read(rs2) {
212                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
213                    return program_counter
214                        .set_pc(memory, old_pc.wrapping_add(imm.cast_unsigned()))
215                        .map_err(ExecutionError::from);
216                }
217            }
218
219            Self::Lui { rd, imm } => {
220                regs.write(rd, imm.cast_unsigned());
221            }
222
223            Self::Auipc { rd, imm } => {
224                let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
225                regs.write(rd, old_pc.wrapping_add(imm.cast_unsigned()));
226            }
227
228            Self::Jal { rd, imm } => {
229                let pc = program_counter.get_pc();
230                let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
231                regs.write(rd, pc);
232                return program_counter
233                    .set_pc(memory, old_pc.wrapping_add(imm.cast_unsigned()))
234                    .map_err(ExecutionError::from);
235            }
236
237            Self::Fence { pred, succ } => {
238                system_instruction_handler.handle_fence(pred, succ);
239            }
240            Self::FenceTso => {
241                system_instruction_handler.handle_fence_tso();
242            }
243
244            Self::Ecall => {
245                return system_instruction_handler.handle_ecall(regs, memory, program_counter);
246            }
247            Self::Ebreak => {
248                system_instruction_handler.handle_ebreak(regs, memory, program_counter.get_pc());
249            }
250
251            Self::Unimp => {
252                let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
253                return Err(ExecutionError::IllegalInstruction { address: old_pc });
254            }
255        }
256
257        Ok(ControlFlow::Continue(()))
258    }
259}