Skip to main content

ab_riscv_interpreter/
rv64.rs

1//! Base RISC-V RV64 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 Rv64Instruction<Reg>
25where
26    Reg: Register<Type = u64>,
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) & 0x3f;
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 u64);
58            }
59            Self::Sltu { rd, rs1, rs2 } => {
60                let value = regs.read(rs1) < regs.read(rs2);
61                regs.write(rd, value as u64);
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) & 0x3f;
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) & 0x3f;
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::Addw { rd, rs1, rs2 } => {
87                let sum = (regs.read(rs1) as i32).wrapping_add(regs.read(rs2) as i32);
88                regs.write(rd, i64::from(sum).cast_unsigned());
89            }
90            Self::Subw { rd, rs1, rs2 } => {
91                let diff = (regs.read(rs1) as i32).wrapping_sub(regs.read(rs2) as i32);
92                regs.write(rd, i64::from(diff).cast_unsigned());
93            }
94            Self::Sllw { rd, rs1, rs2 } => {
95                let shamt = regs.read(rs2) & 0x1f;
96                let shifted = (regs.read(rs1) as u32) << shamt;
97                regs.write(rd, i64::from(shifted.cast_signed()).cast_unsigned());
98            }
99            Self::Srlw { rd, rs1, rs2 } => {
100                let shamt = regs.read(rs2) & 0x1f;
101                let shifted = (regs.read(rs1) as u32) >> shamt;
102                regs.write(rd, i64::from(shifted.cast_signed()).cast_unsigned());
103            }
104            Self::Sraw { rd, rs1, rs2 } => {
105                let shamt = regs.read(rs2) & 0x1f;
106                let shifted = (regs.read(rs1) as i32) >> shamt;
107                regs.write(rd, i64::from(shifted).cast_unsigned());
108            }
109
110            Self::Addi { rd, rs1, imm } => {
111                let value = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
112                regs.write(rd, value);
113            }
114            Self::Slti { rd, rs1, imm } => {
115                let value = regs.read(rs1).cast_signed() < i64::from(imm);
116                regs.write(rd, value as u64);
117            }
118            Self::Sltiu { rd, rs1, imm } => {
119                let value = regs.read(rs1) < i64::from(imm).cast_unsigned();
120                regs.write(rd, value as u64);
121            }
122            Self::Xori { rd, rs1, imm } => {
123                let value = regs.read(rs1) ^ i64::from(imm).cast_unsigned();
124                regs.write(rd, value);
125            }
126            Self::Ori { rd, rs1, imm } => {
127                let value = regs.read(rs1) | i64::from(imm).cast_unsigned();
128                regs.write(rd, value);
129            }
130            Self::Andi { rd, rs1, imm } => {
131                let value = regs.read(rs1) & i64::from(imm).cast_unsigned();
132                regs.write(rd, value);
133            }
134            Self::Slli { rd, rs1, shamt } => {
135                let value = regs.read(rs1) << shamt;
136                regs.write(rd, value);
137            }
138            Self::Srli { rd, rs1, shamt } => {
139                let value = regs.read(rs1) >> shamt;
140                regs.write(rd, value);
141            }
142            Self::Srai { rd, rs1, shamt } => {
143                let value = regs.read(rs1).cast_signed() >> shamt;
144                regs.write(rd, value.cast_unsigned());
145            }
146
147            Self::Addiw { rd, rs1, imm } => {
148                let sum = (regs.read(rs1) as i32).wrapping_add(i32::from(imm));
149                regs.write(rd, i64::from(sum).cast_unsigned());
150            }
151            Self::Slliw { rd, rs1, shamt } => {
152                let shifted = (regs.read(rs1) as u32) << shamt;
153                regs.write(rd, i64::from(shifted.cast_signed()).cast_unsigned());
154            }
155            Self::Srliw { rd, rs1, shamt } => {
156                let shifted = (regs.read(rs1) as u32) >> shamt;
157                regs.write(rd, i64::from(shifted.cast_signed()).cast_unsigned());
158            }
159            Self::Sraiw { rd, rs1, shamt } => {
160                let shifted = (regs.read(rs1) as i32) >> shamt;
161                regs.write(rd, i64::from(shifted).cast_unsigned());
162            }
163
164            Self::Lb { rd, rs1, imm } => {
165                let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
166                let value = i64::from(memory.read::<i8>(addr)?);
167                regs.write(rd, value.cast_unsigned());
168            }
169            Self::Lh { rd, rs1, imm } => {
170                let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
171                let value = i64::from(memory.read::<i16>(addr)?);
172                regs.write(rd, value.cast_unsigned());
173            }
174            Self::Lw { rd, rs1, imm } => {
175                let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
176                let value = i64::from(memory.read::<i32>(addr)?);
177                regs.write(rd, value.cast_unsigned());
178            }
179            Self::Ld { rd, rs1, imm } => {
180                let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
181                let value = memory.read::<u64>(addr)?;
182                regs.write(rd, value);
183            }
184            Self::Lbu { rd, rs1, imm } => {
185                let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
186                let value = memory.read::<u8>(addr)?;
187                regs.write(rd, value as u64);
188            }
189            Self::Lhu { rd, rs1, imm } => {
190                let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
191                let value = memory.read::<u16>(addr)?;
192                regs.write(rd, value as u64);
193            }
194            Self::Lwu { rd, rs1, imm } => {
195                let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
196                let value = memory.read::<u32>(addr)?;
197                regs.write(rd, value as u64);
198            }
199
200            Self::Jalr { rd, rs1, imm } => {
201                let target = (regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned())) & !1u64;
202                regs.write(rd, program_counter.get_pc());
203                return program_counter
204                    .set_pc(memory, target)
205                    .map_err(ExecutionError::from);
206            }
207
208            Self::Sb { rs2, rs1, imm } => {
209                let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
210                memory.write(addr, regs.read(rs2) as u8)?;
211            }
212            Self::Sh { rs2, rs1, imm } => {
213                let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
214                memory.write(addr, regs.read(rs2) as u16)?;
215            }
216            Self::Sw { rs2, rs1, imm } => {
217                let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
218                memory.write(addr, regs.read(rs2) as u32)?;
219            }
220            Self::Sd { rs2, rs1, imm } => {
221                let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
222                memory.write(addr, regs.read(rs2))?;
223            }
224
225            Self::Beq { rs1, rs2, imm } => {
226                if regs.read(rs1) == regs.read(rs2) {
227                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
228                    return program_counter
229                        .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
230                        .map_err(ExecutionError::from);
231                }
232            }
233            Self::Bne { rs1, rs2, imm } => {
234                if regs.read(rs1) != regs.read(rs2) {
235                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
236                    return program_counter
237                        .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
238                        .map_err(ExecutionError::from);
239                }
240            }
241            Self::Blt { rs1, rs2, imm } => {
242                if regs.read(rs1).cast_signed() < regs.read(rs2).cast_signed() {
243                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
244                    return program_counter
245                        .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
246                        .map_err(ExecutionError::from);
247                }
248            }
249            Self::Bge { rs1, rs2, imm } => {
250                if regs.read(rs1).cast_signed() >= regs.read(rs2).cast_signed() {
251                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
252                    return program_counter
253                        .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
254                        .map_err(ExecutionError::from);
255                }
256            }
257            Self::Bltu { rs1, rs2, imm } => {
258                if regs.read(rs1) < regs.read(rs2) {
259                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
260                    return program_counter
261                        .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
262                        .map_err(ExecutionError::from);
263                }
264            }
265            Self::Bgeu { rs1, rs2, imm } => {
266                if regs.read(rs1) >= regs.read(rs2) {
267                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
268                    return program_counter
269                        .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
270                        .map_err(ExecutionError::from);
271                }
272            }
273
274            Self::Lui { rd, imm } => {
275                regs.write(rd, i64::from(imm).cast_unsigned());
276            }
277
278            Self::Auipc { rd, imm } => {
279                let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
280                regs.write(rd, old_pc.wrapping_add(i64::from(imm).cast_unsigned()));
281            }
282
283            Self::Jal { rd, imm } => {
284                let pc = program_counter.get_pc();
285                let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
286                regs.write(rd, pc);
287                return program_counter
288                    .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
289                    .map_err(ExecutionError::from);
290            }
291
292            Self::Fence { pred, succ } => {
293                system_instruction_handler.handle_fence(pred, succ);
294            }
295            Self::FenceTso => {
296                system_instruction_handler.handle_fence_tso();
297            }
298
299            Self::Ecall => {
300                return system_instruction_handler.handle_ecall(regs, memory, program_counter);
301            }
302            Self::Ebreak => {
303                system_instruction_handler.handle_ebreak(regs, memory, program_counter.get_pc());
304            }
305
306            Self::Unimp => {
307                let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
308                return Err(ExecutionError::IllegalInstruction { address: old_pc });
309            }
310        }
311
312        Ok(ControlFlow::Continue(()))
313    }
314}