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