Skip to main content

ab_riscv_interpreter/
rv64.rs

1//! Base RISC-V RV64 instruction set
2
3pub mod a;
4pub mod b;
5pub mod c;
6pub mod m;
7#[cfg(test)]
8pub(crate) mod test_utils;
9#[cfg(test)]
10mod tests;
11#[cfg(test)]
12mod threaded_tests;
13pub mod zabha;
14pub mod zacas;
15pub mod zalasr;
16pub mod zce;
17pub mod zk;
18
19use crate::{
20    ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
21    ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
22    PackedAddress, ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
23    SystemInstructionHandler, ThreadedExecutableInstruction, ThreadedExecutionResult,
24    VirtualMemory,
25};
26use ab_riscv_macros::instruction_execution;
27use ab_riscv_primitives::prelude::*;
28use core::ops::ControlFlow;
29
30#[instruction_execution]
31const impl<Reg> ExecutableInstructionOperands for Rv64Instruction<Reg> where
32    Reg: Register<Type = u64>
33{
34}
35
36#[instruction_execution]
37const impl<Reg, Env> ExecutableInstructionCsr<Env> for Rv64Instruction<Reg> where
38    Reg: Register<Type = u64>
39{
40}
41
42#[instruction_execution]
43const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
44    for Rv64Instruction<Reg>
45where
46    Reg: [const] Register<Type = u64>,
47    Regs: [const] RegisterFile<Reg>,
48    Env: [const] SystemInstructionHandler<Reg, Regs, Memory, PC>,
49    Memory: [const] VirtualMemory,
50    PC: [const] ProgramCounter<Reg::Type, Memory>,
51{
52    #[inline(always)]
53    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
54    fn execute(
55        self,
56        Rs1Rs2OperandValues {
57            rs1_value,
58            rs2_value,
59        }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
60        regs: &mut Regs,
61        env: &mut Env,
62        memory: &mut Memory,
63        program_counter: &mut PC,
64    ) -> ExecutionResult<Self::Reg> {
65        match self {
66            Self::Add { rd, rs1: _, rs2: _ } => {
67                let value = rs1_value.wrapping_add(rs2_value);
68                ExecutionResult::Continue { rd, value }
69            }
70            Self::Sub { rd, rs1: _, rs2: _ } => {
71                let value = rs1_value.wrapping_sub(rs2_value);
72                ExecutionResult::Continue { rd, value }
73            }
74            Self::Sll { rd, rs1: _, rs2: _ } => {
75                let shamt = rs2_value & 0x3f;
76                let value = rs1_value << shamt;
77                ExecutionResult::Continue { rd, value }
78            }
79            Self::Slt { rd, rs1: _, rs2: _ } => {
80                let value = rs1_value.cast_signed() < rs2_value.cast_signed();
81                ExecutionResult::Continue {
82                    rd,
83                    value: u64::from(value),
84                }
85            }
86            Self::Sltu { rd, rs1: _, rs2: _ } => {
87                let value = rs1_value < rs2_value;
88                ExecutionResult::Continue {
89                    rd,
90                    value: u64::from(value),
91                }
92            }
93            Self::Xor { rd, rs1: _, rs2: _ } => {
94                let value = rs1_value ^ rs2_value;
95                ExecutionResult::Continue { rd, value }
96            }
97            Self::Srl { rd, rs1: _, rs2: _ } => {
98                let shamt = rs2_value & 0x3f;
99                let value = rs1_value >> shamt;
100                ExecutionResult::Continue { rd, value }
101            }
102            Self::Sra { rd, rs1: _, rs2: _ } => {
103                let shamt = rs2_value & 0x3f;
104                let value = rs1_value.cast_signed() >> shamt;
105                ExecutionResult::Continue {
106                    rd,
107                    value: value.cast_unsigned(),
108                }
109            }
110            Self::Or { rd, rs1: _, rs2: _ } => {
111                let value = rs1_value | rs2_value;
112                ExecutionResult::Continue { rd, value }
113            }
114            Self::And { rd, rs1: _, rs2: _ } => {
115                let value = rs1_value & rs2_value;
116                ExecutionResult::Continue { rd, value }
117            }
118
119            Self::Addw { rd, rs1: _, rs2: _ } => {
120                let sum = (rs1_value as i32).wrapping_add(rs2_value as i32);
121                ExecutionResult::Continue {
122                    rd,
123                    value: i64::from(sum).cast_unsigned(),
124                }
125            }
126            Self::Subw { rd, rs1: _, rs2: _ } => {
127                let diff = (rs1_value as i32).wrapping_sub(rs2_value as i32);
128                ExecutionResult::Continue {
129                    rd,
130                    value: i64::from(diff).cast_unsigned(),
131                }
132            }
133            Self::Sllw { rd, rs1: _, rs2: _ } => {
134                let shamt = rs2_value & 0x1f;
135                let shifted = (rs1_value as u32) << shamt;
136                ExecutionResult::Continue {
137                    rd,
138                    value: i64::from(shifted.cast_signed()).cast_unsigned(),
139                }
140            }
141            Self::Srlw { rd, rs1: _, rs2: _ } => {
142                let shamt = rs2_value & 0x1f;
143                let shifted = (rs1_value as u32) >> shamt;
144                ExecutionResult::Continue {
145                    rd,
146                    value: i64::from(shifted.cast_signed()).cast_unsigned(),
147                }
148            }
149            Self::Sraw { rd, rs1: _, rs2: _ } => {
150                let shamt = rs2_value & 0x1f;
151                let shifted = (rs1_value as i32) >> shamt;
152                ExecutionResult::Continue {
153                    rd,
154                    value: i64::from(shifted).cast_unsigned(),
155                }
156            }
157
158            Self::Addi { rd, rs1: _, imm } => {
159                let value = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
160                ExecutionResult::Continue { rd, value }
161            }
162            Self::Slti { rd, rs1: _, imm } => {
163                let value = rs1_value.cast_signed() < i64::from(imm);
164                ExecutionResult::Continue {
165                    rd,
166                    value: u64::from(value),
167                }
168            }
169            Self::Sltiu { rd, rs1: _, imm } => {
170                let value = rs1_value < i64::from(imm).cast_unsigned();
171                ExecutionResult::Continue {
172                    rd,
173                    value: u64::from(value),
174                }
175            }
176            Self::Xori { rd, rs1: _, imm } => {
177                let value = rs1_value ^ i64::from(imm).cast_unsigned();
178                ExecutionResult::Continue { rd, value }
179            }
180            Self::Ori { rd, rs1: _, imm } => {
181                let value = rs1_value | i64::from(imm).cast_unsigned();
182                ExecutionResult::Continue { rd, value }
183            }
184            Self::Andi { rd, rs1: _, imm } => {
185                let value = rs1_value & i64::from(imm).cast_unsigned();
186                ExecutionResult::Continue { rd, value }
187            }
188            Self::Slli { rd, rs1: _, shamt } => {
189                let value = rs1_value << shamt;
190                ExecutionResult::Continue { rd, value }
191            }
192            Self::Srli { rd, rs1: _, shamt } => {
193                let value = rs1_value >> shamt;
194                ExecutionResult::Continue { rd, value }
195            }
196            Self::Srai { rd, rs1: _, shamt } => {
197                let value = rs1_value.cast_signed() >> shamt;
198                ExecutionResult::Continue {
199                    rd,
200                    value: value.cast_unsigned(),
201                }
202            }
203
204            Self::Addiw { rd, rs1: _, imm } => {
205                let sum = (rs1_value as i32).wrapping_add(i32::from(imm));
206                ExecutionResult::Continue {
207                    rd,
208                    value: i64::from(sum).cast_unsigned(),
209                }
210            }
211            Self::Slliw { rd, rs1: _, shamt } => {
212                let shifted = (rs1_value as u32) << shamt;
213                ExecutionResult::Continue {
214                    rd,
215                    value: i64::from(shifted.cast_signed()).cast_unsigned(),
216                }
217            }
218            Self::Srliw { rd, rs1: _, shamt } => {
219                let shifted = (rs1_value as u32) >> shamt;
220                ExecutionResult::Continue {
221                    rd,
222                    value: i64::from(shifted.cast_signed()).cast_unsigned(),
223                }
224            }
225            Self::Sraiw { rd, rs1: _, shamt } => {
226                let shifted = (rs1_value as i32) >> shamt;
227                ExecutionResult::Continue {
228                    rd,
229                    value: i64::from(shifted).cast_unsigned(),
230                }
231            }
232
233            Self::Lb { rd, rs1: _, imm } => {
234                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
235                let value = i64::from(memory.read::<i8>(addr)?);
236                ExecutionResult::Continue {
237                    rd,
238                    value: value.cast_unsigned(),
239                }
240            }
241            Self::Lh { rd, rs1: _, imm } => {
242                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
243                let value = i64::from(memory.read::<i16>(addr)?);
244                ExecutionResult::Continue {
245                    rd,
246                    value: value.cast_unsigned(),
247                }
248            }
249            Self::Lw { rd, rs1: _, imm } => {
250                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
251                let value = i64::from(memory.read::<i32>(addr)?);
252                ExecutionResult::Continue {
253                    rd,
254                    value: value.cast_unsigned(),
255                }
256            }
257            Self::Ld { rd, rs1: _, imm } => {
258                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
259                let value = memory.read::<u64>(addr)?;
260                ExecutionResult::Continue { rd, value }
261            }
262            Self::Lbu { rd, rs1: _, imm } => {
263                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
264                let value = memory.read::<u8>(addr)?;
265                ExecutionResult::Continue {
266                    rd,
267                    value: u64::from(value),
268                }
269            }
270            Self::Lhu { rd, rs1: _, imm } => {
271                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
272                let value = memory.read::<u16>(addr)?;
273                ExecutionResult::Continue {
274                    rd,
275                    value: u64::from(value),
276                }
277            }
278            Self::Lwu { rd, rs1: _, imm } => {
279                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
280                let value = memory.read::<u32>(addr)?;
281                ExecutionResult::Continue {
282                    rd,
283                    value: u64::from(value),
284                }
285            }
286
287            Self::Jalr { rd, rs1: _, imm } => {
288                let target = (rs1_value.wrapping_add(i64::from(imm).cast_unsigned())) & !1u64;
289                regs.write(rd, program_counter.get_pc());
290
291                ExecutionResult::Jump { target }
292            }
293
294            Self::Sb {
295                rs2: _,
296                rs1: _,
297                imm,
298            } => {
299                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
300                memory.write(addr, rs2_value as u8)?;
301                ExecutionResult::ContinueNoWrite
302            }
303            Self::Sh {
304                rs2: _,
305                rs1: _,
306                imm,
307            } => {
308                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
309                memory.write(addr, rs2_value as u16)?;
310                ExecutionResult::ContinueNoWrite
311            }
312            Self::Sw {
313                rs2: _,
314                rs1: _,
315                imm,
316            } => {
317                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
318                memory.write(addr, rs2_value as u32)?;
319                ExecutionResult::ContinueNoWrite
320            }
321            Self::Sd {
322                rs2: _,
323                rs1: _,
324                imm,
325            } => {
326                let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
327                memory.write(addr, rs2_value)?;
328                ExecutionResult::ContinueNoWrite
329            }
330
331            Self::Beq {
332                rs1: _,
333                rs2: _,
334                imm,
335            } => {
336                if rs1_value == rs2_value {
337                    return ExecutionResult::Branch {
338                        offset: i32::from(imm),
339                    };
340                }
341
342                ExecutionResult::ContinueNoWrite
343            }
344            Self::Bne {
345                rs1: _,
346                rs2: _,
347                imm,
348            } => {
349                if rs1_value != rs2_value {
350                    return ExecutionResult::Branch {
351                        offset: i32::from(imm),
352                    };
353                }
354
355                ExecutionResult::ContinueNoWrite
356            }
357            Self::Blt {
358                rs1: _,
359                rs2: _,
360                imm,
361            } => {
362                if rs1_value.cast_signed() < rs2_value.cast_signed() {
363                    return ExecutionResult::Branch {
364                        offset: i32::from(imm),
365                    };
366                }
367
368                ExecutionResult::ContinueNoWrite
369            }
370            Self::Bge {
371                rs1: _,
372                rs2: _,
373                imm,
374            } => {
375                if rs1_value.cast_signed() >= rs2_value.cast_signed() {
376                    return ExecutionResult::Branch {
377                        offset: i32::from(imm),
378                    };
379                }
380
381                ExecutionResult::ContinueNoWrite
382            }
383            Self::Bltu {
384                rs1: _,
385                rs2: _,
386                imm,
387            } => {
388                if rs1_value < rs2_value {
389                    return ExecutionResult::Branch {
390                        offset: i32::from(imm),
391                    };
392                }
393
394                ExecutionResult::ContinueNoWrite
395            }
396            Self::Bgeu {
397                rs1: _,
398                rs2: _,
399                imm,
400            } => {
401                if rs1_value >= rs2_value {
402                    return ExecutionResult::Branch {
403                        offset: i32::from(imm),
404                    };
405                }
406
407                ExecutionResult::ContinueNoWrite
408            }
409
410            Self::Lui { rd, imm } => ExecutionResult::Continue {
411                rd,
412                value: i64::from(imm).cast_unsigned(),
413            },
414
415            Self::Auipc { rd, imm } => {
416                let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
417                ExecutionResult::Continue {
418                    rd,
419                    value: old_pc.wrapping_add(i64::from(imm).cast_unsigned()),
420                }
421            }
422
423            Self::Jal { rd, imm } => {
424                let pc = program_counter.get_pc();
425                regs.write(rd, pc);
426
427                ExecutionResult::Branch {
428                    offset: i32::from(imm),
429                }
430            }
431
432            Self::Fence { pred, succ } => {
433                env.handle_fence(pred, succ);
434                ExecutionResult::ContinueNoWrite
435            }
436            Self::FenceTso => {
437                env.handle_fence_tso();
438                ExecutionResult::ContinueNoWrite
439            }
440
441            Self::Ecall => match env.handle_ecall(regs, memory, program_counter)? {
442                ControlFlow::Continue(()) => ExecutionResult::ContinueNoWrite,
443                ControlFlow::Break(()) => ExecutionResult::Break,
444            },
445            Self::Ebreak => {
446                env.handle_ebreak(regs, memory, program_counter.get_pc());
447                ExecutionResult::ContinueNoWrite
448            }
449
450            Self::Unimp => {
451                let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
452                ExecutionResult::Err(ExecutionError::IllegalInstruction {
453                    address: PackedAddress::new(old_pc),
454                })
455            }
456        }
457    }
458}