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, 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 Rv64Instruction<Reg> where Reg: Register<Type = u64> {}
24
25#[instruction_execution]
26impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
27    for Rv64Instruction<Reg>
28where
29    Reg: Register<Type = u64>,
30{
31}
32
33#[instruction_execution]
34impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
35    ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
36    for Rv64Instruction<Reg>
37where
38    Reg: Register<Type = u64>,
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 & 0x3f;
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 u64)))
77            }
78            Self::Sltu { rd, rs1: _, rs2: _ } => {
79                let value = rs1_value < rs2_value;
80                Ok(ControlFlow::Continue((rd, value as u64)))
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 & 0x3f;
88                let value = rs1_value >> shamt;
89                Ok(ControlFlow::Continue((rd, value)))
90            }
91            Self::Sra { rd, rs1: _, rs2: _ } => {
92                let shamt = rs2_value & 0x3f;
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::Addw { rd, rs1: _, rs2: _ } => {
106                let sum = (rs1_value as i32).wrapping_add(rs2_value as i32);
107                Ok(ControlFlow::Continue((rd, i64::from(sum).cast_unsigned())))
108            }
109            Self::Subw { rd, rs1: _, rs2: _ } => {
110                let diff = (rs1_value as i32).wrapping_sub(rs2_value as i32);
111                Ok(ControlFlow::Continue((rd, i64::from(diff).cast_unsigned())))
112            }
113            Self::Sllw { rd, rs1: _, rs2: _ } => {
114                let shamt = rs2_value & 0x1f;
115                let shifted = (rs1_value as u32) << shamt;
116                Ok(ControlFlow::Continue((
117                    rd,
118                    i64::from(shifted.cast_signed()).cast_unsigned(),
119                )))
120            }
121            Self::Srlw { rd, rs1: _, rs2: _ } => {
122                let shamt = rs2_value & 0x1f;
123                let shifted = (rs1_value as u32) >> shamt;
124                Ok(ControlFlow::Continue((
125                    rd,
126                    i64::from(shifted.cast_signed()).cast_unsigned(),
127                )))
128            }
129            Self::Sraw { rd, rs1: _, rs2: _ } => {
130                let shamt = rs2_value & 0x1f;
131                let shifted = (rs1_value as i32) >> shamt;
132                Ok(ControlFlow::Continue((
133                    rd,
134                    i64::from(shifted).cast_unsigned(),
135                )))
136            }
137
138            Self::Addi { rd, rs1: _, imm } => {
139                let value = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
140                Ok(ControlFlow::Continue((rd, value)))
141            }
142            Self::Slti { rd, rs1: _, imm } => {
143                let value = rs1_value.cast_signed() < i64::from(imm);
144                Ok(ControlFlow::Continue((rd, value as u64)))
145            }
146            Self::Sltiu { rd, rs1: _, imm } => {
147                let value = rs1_value < i64::from(imm).cast_unsigned();
148                Ok(ControlFlow::Continue((rd, value as u64)))
149            }
150            Self::Xori { rd, rs1: _, imm } => {
151                let value = rs1_value ^ i64::from(imm).cast_unsigned();
152                Ok(ControlFlow::Continue((rd, value)))
153            }
154            Self::Ori { rd, rs1: _, imm } => {
155                let value = rs1_value | i64::from(imm).cast_unsigned();
156                Ok(ControlFlow::Continue((rd, value)))
157            }
158            Self::Andi { rd, rs1: _, imm } => {
159                let value = rs1_value & i64::from(imm).cast_unsigned();
160                Ok(ControlFlow::Continue((rd, value)))
161            }
162            Self::Slli { rd, rs1: _, shamt } => {
163                let value = rs1_value << shamt;
164                Ok(ControlFlow::Continue((rd, value)))
165            }
166            Self::Srli { rd, rs1: _, shamt } => {
167                let value = rs1_value >> shamt;
168                Ok(ControlFlow::Continue((rd, value)))
169            }
170            Self::Srai { rd, rs1: _, shamt } => {
171                let value = rs1_value.cast_signed() >> shamt;
172                Ok(ControlFlow::Continue((rd, value.cast_unsigned())))
173            }
174
175            Self::Addiw { rd, rs1: _, imm } => {
176                let sum = (rs1_value as i32).wrapping_add(i32::from(imm));
177                Ok(ControlFlow::Continue((rd, i64::from(sum).cast_unsigned())))
178            }
179            Self::Slliw { rd, rs1: _, shamt } => {
180                let shifted = (rs1_value as u32) << shamt;
181                Ok(ControlFlow::Continue((
182                    rd,
183                    i64::from(shifted.cast_signed()).cast_unsigned(),
184                )))
185            }
186            Self::Srliw { rd, rs1: _, shamt } => {
187                let shifted = (rs1_value as u32) >> shamt;
188                Ok(ControlFlow::Continue((
189                    rd,
190                    i64::from(shifted.cast_signed()).cast_unsigned(),
191                )))
192            }
193            Self::Sraiw { rd, rs1: _, shamt } => {
194                let shifted = (rs1_value as i32) >> shamt;
195                Ok(ControlFlow::Continue((
196                    rd,
197                    i64::from(shifted).cast_unsigned(),
198                )))
199            }
200
201            Self::Lb { rd, rs1: _, imm } => {
202                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
203                let value = i64::from(memory.read::<i8>(addr)?);
204                Ok(ControlFlow::Continue((rd, value.cast_unsigned())))
205            }
206            Self::Lh { rd, rs1: _, imm } => {
207                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
208                let value = i64::from(memory.read::<i16>(addr)?);
209                Ok(ControlFlow::Continue((rd, value.cast_unsigned())))
210            }
211            Self::Lw { rd, rs1: _, imm } => {
212                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
213                let value = i64::from(memory.read::<i32>(addr)?);
214                Ok(ControlFlow::Continue((rd, value.cast_unsigned())))
215            }
216            Self::Ld { rd, rs1: _, imm } => {
217                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
218                let value = memory.read::<u64>(addr)?;
219                Ok(ControlFlow::Continue((rd, value)))
220            }
221            Self::Lbu { rd, rs1: _, imm } => {
222                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
223                let value = memory.read::<u8>(addr)?;
224                Ok(ControlFlow::Continue((rd, value as u64)))
225            }
226            Self::Lhu { rd, rs1: _, imm } => {
227                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
228                let value = memory.read::<u16>(addr)?;
229                Ok(ControlFlow::Continue((rd, value as u64)))
230            }
231            Self::Lwu { rd, rs1: _, imm } => {
232                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
233                let value = memory.read::<u32>(addr)?;
234                Ok(ControlFlow::Continue((rd, value as u64)))
235            }
236
237            Self::Jalr { rd, rs1: _, imm } => {
238                let target = (rs1_value.wrapping_add(i64::from(imm).cast_unsigned())) & !1u64;
239                regs.write(rd, program_counter.get_pc());
240                return program_counter
241                    .set_pc(memory, target)
242                    .map(|control_flow| control_flow.map_continue(|()| Default::default()))
243                    .map_err(ExecutionError::from);
244            }
245
246            Self::Sb {
247                rs2: _,
248                rs1: _,
249                imm,
250            } => {
251                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
252                memory.write(addr, rs2_value as u8)?;
253                Ok(ControlFlow::Continue(Default::default()))
254            }
255            Self::Sh {
256                rs2: _,
257                rs1: _,
258                imm,
259            } => {
260                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
261                memory.write(addr, rs2_value as u16)?;
262                Ok(ControlFlow::Continue(Default::default()))
263            }
264            Self::Sw {
265                rs2: _,
266                rs1: _,
267                imm,
268            } => {
269                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
270                memory.write(addr, rs2_value as u32)?;
271                Ok(ControlFlow::Continue(Default::default()))
272            }
273            Self::Sd {
274                rs2: _,
275                rs1: _,
276                imm,
277            } => {
278                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
279                memory.write(addr, rs2_value)?;
280                Ok(ControlFlow::Continue(Default::default()))
281            }
282
283            Self::Beq {
284                rs1: _,
285                rs2: _,
286                imm,
287            } => {
288                if rs1_value == rs2_value {
289                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
290                    return program_counter
291                        .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
292                        .map(|control_flow| control_flow.map_continue(|()| Default::default()))
293                        .map_err(ExecutionError::from);
294                }
295
296                Ok(ControlFlow::Continue(Default::default()))
297            }
298            Self::Bne {
299                rs1: _,
300                rs2: _,
301                imm,
302            } => {
303                if rs1_value != rs2_value {
304                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
305                    return program_counter
306                        .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
307                        .map(|control_flow| control_flow.map_continue(|()| Default::default()))
308                        .map_err(ExecutionError::from);
309                }
310
311                Ok(ControlFlow::Continue(Default::default()))
312            }
313            Self::Blt {
314                rs1: _,
315                rs2: _,
316                imm,
317            } => {
318                if rs1_value.cast_signed() < rs2_value.cast_signed() {
319                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
320                    return program_counter
321                        .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
322                        .map(|control_flow| control_flow.map_continue(|()| Default::default()))
323                        .map_err(ExecutionError::from);
324                }
325
326                Ok(ControlFlow::Continue(Default::default()))
327            }
328            Self::Bge {
329                rs1: _,
330                rs2: _,
331                imm,
332            } => {
333                if rs1_value.cast_signed() >= rs2_value.cast_signed() {
334                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
335                    return program_counter
336                        .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
337                        .map(|control_flow| control_flow.map_continue(|()| Default::default()))
338                        .map_err(ExecutionError::from);
339                }
340
341                Ok(ControlFlow::Continue(Default::default()))
342            }
343            Self::Bltu {
344                rs1: _,
345                rs2: _,
346                imm,
347            } => {
348                if rs1_value < rs2_value {
349                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
350                    return program_counter
351                        .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
352                        .map(|control_flow| control_flow.map_continue(|()| Default::default()))
353                        .map_err(ExecutionError::from);
354                }
355
356                Ok(ControlFlow::Continue(Default::default()))
357            }
358            Self::Bgeu {
359                rs1: _,
360                rs2: _,
361                imm,
362            } => {
363                if rs1_value >= rs2_value {
364                    let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
365                    return program_counter
366                        .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
367                        .map(|control_flow| control_flow.map_continue(|()| Default::default()))
368                        .map_err(ExecutionError::from);
369                }
370
371                Ok(ControlFlow::Continue(Default::default()))
372            }
373
374            Self::Lui { rd, imm } => {
375                Ok(ControlFlow::Continue((rd, i64::from(imm).cast_unsigned())))
376            }
377
378            Self::Auipc { rd, imm } => {
379                let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
380                Ok(ControlFlow::Continue((
381                    rd,
382                    old_pc.wrapping_add(i64::from(imm).cast_unsigned()),
383                )))
384            }
385
386            Self::Jal { rd, imm } => {
387                let pc = program_counter.get_pc();
388                let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
389                regs.write(rd, pc);
390                return program_counter
391                    .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
392                    .map(|control_flow| control_flow.map_continue(|()| Default::default()))
393                    .map_err(ExecutionError::from);
394            }
395
396            Self::Fence { pred, succ } => {
397                system_instruction_handler.handle_fence(pred, succ);
398                Ok(ControlFlow::Continue(Default::default()))
399            }
400            Self::FenceTso => {
401                system_instruction_handler.handle_fence_tso();
402                Ok(ControlFlow::Continue(Default::default()))
403            }
404
405            Self::Ecall => {
406                return system_instruction_handler
407                    .handle_ecall(regs, memory, program_counter)
408                    .map(|control_flow| control_flow.map_continue(|()| Default::default()));
409            }
410            Self::Ebreak => {
411                system_instruction_handler.handle_ebreak(regs, memory, program_counter.get_pc());
412                Ok(ControlFlow::Continue(Default::default()))
413            }
414
415            Self::Unimp => {
416                let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
417                return Err(ExecutionError::IllegalInstruction { address: old_pc });
418            }
419        }
420    }
421}