Skip to main content

ab_riscv_interpreter/
rv32.rs

1//! Base RISC-V RV32 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;
11pub mod zabha;
12pub mod zacas;
13pub mod zalasr;
14pub mod zce;
15pub mod zk;
16
17use crate::{
18    ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
19    ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
20    PackedAddress, ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
21    SystemInstructionHandler, ThreadedExecutableInstruction, ThreadedExecutionResult,
22    VirtualMemory,
23};
24use ab_riscv_macros::instruction_execution;
25use ab_riscv_primitives::prelude::*;
26
27#[instruction_execution]
28const impl<Reg, Hart> ExecutableInstructionOperands for Rv32Instruction<Hart>
29where
30    Reg: Register<Type = u32>,
31    Hart: HartConfig<Reg = Reg>,
32{
33}
34
35#[instruction_execution]
36const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for Rv32Instruction<Hart>
37where
38    Reg: Register<Type = u32>,
39    Hart: HartConfig<Reg = Reg>,
40{
41}
42
43#[instruction_execution]
44const impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
45    for Rv32Instruction<Hart>
46where
47    Reg: [const] Register<Type = u32>,
48    Hart: HartConfig<Reg = Reg>,
49    Regs: [const] RegisterFile<Reg>,
50    Env: [const] SystemInstructionHandler<Reg, Regs, Memory, PC>,
51    Memory: [const] VirtualMemory,
52    PC: [const] ProgramCounter<Reg::Type, Memory>,
53{
54    #[inline(always)]
55    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
56    fn execute(
57        self,
58        Rs1Rs2OperandValues {
59            rs1_value,
60            rs2_value,
61        }: Rs1Rs2OperandValues<Reg::Type>,
62        regs: &mut Regs,
63        env: &mut Env,
64        memory: &mut Memory,
65        program_counter: &PC,
66    ) -> ExecutionResult<Reg> {
67        match self {
68            Self::Add { rd, rs1: _, rs2: _ } => {
69                let value = rs1_value.wrapping_add(rs2_value);
70                ExecutionResult::Continue { rd, value }
71            }
72            Self::Sub { rd, rs1: _, rs2: _ } => {
73                let value = rs1_value.wrapping_sub(rs2_value);
74                ExecutionResult::Continue { rd, value }
75            }
76            Self::Sll { rd, rs1: _, rs2: _ } => {
77                let shamt = rs2_value & 0x1f;
78                let value = rs1_value << shamt;
79                ExecutionResult::Continue { rd, value }
80            }
81            Self::Slt { rd, rs1: _, rs2: _ } => {
82                let value = rs1_value.cast_signed() < rs2_value.cast_signed();
83                ExecutionResult::Continue {
84                    rd,
85                    value: u32::from(value),
86                }
87            }
88            Self::Sltu { rd, rs1: _, rs2: _ } => {
89                let value = rs1_value < rs2_value;
90                ExecutionResult::Continue {
91                    rd,
92                    value: u32::from(value),
93                }
94            }
95            Self::Xor { rd, rs1: _, rs2: _ } => {
96                let value = rs1_value ^ rs2_value;
97                ExecutionResult::Continue { rd, value }
98            }
99            Self::Srl { rd, rs1: _, rs2: _ } => {
100                let shamt = rs2_value & 0x1f;
101                let value = rs1_value >> shamt;
102                ExecutionResult::Continue { rd, value }
103            }
104            Self::Sra { rd, rs1: _, rs2: _ } => {
105                let shamt = rs2_value & 0x1f;
106                let value = rs1_value.cast_signed() >> shamt;
107                ExecutionResult::Continue {
108                    rd,
109                    value: value.cast_unsigned(),
110                }
111            }
112            Self::Or { rd, rs1: _, rs2: _ } => {
113                let value = rs1_value | rs2_value;
114                ExecutionResult::Continue { rd, value }
115            }
116            Self::And { rd, rs1: _, rs2: _ } => {
117                let value = rs1_value & rs2_value;
118                ExecutionResult::Continue { rd, value }
119            }
120
121            Self::Addi { rd, rs1: _, imm } => {
122                let value = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
123                ExecutionResult::Continue { rd, value }
124            }
125            Self::Slti { rd, rs1: _, imm } => {
126                let value = rs1_value.cast_signed() < i32::from(imm);
127                ExecutionResult::Continue {
128                    rd,
129                    value: u32::from(value),
130                }
131            }
132            Self::Sltiu { rd, rs1: _, imm } => {
133                let value = rs1_value < i32::from(imm).cast_unsigned();
134                ExecutionResult::Continue {
135                    rd,
136                    value: u32::from(value),
137                }
138            }
139            Self::Xori { rd, rs1: _, imm } => {
140                let value = rs1_value ^ i32::from(imm).cast_unsigned();
141                ExecutionResult::Continue { rd, value }
142            }
143            Self::Ori { rd, rs1: _, imm } => {
144                let value = rs1_value | i32::from(imm).cast_unsigned();
145                ExecutionResult::Continue { rd, value }
146            }
147            Self::Andi { rd, rs1: _, imm } => {
148                let value = rs1_value & i32::from(imm).cast_unsigned();
149                ExecutionResult::Continue { rd, value }
150            }
151            Self::Slli { rd, rs1: _, shamt } => {
152                let value = rs1_value << shamt.get();
153                ExecutionResult::Continue { rd, value }
154            }
155            Self::Srli { rd, rs1: _, shamt } => {
156                let value = rs1_value >> shamt.get();
157                ExecutionResult::Continue { rd, value }
158            }
159            Self::Srai { rd, rs1: _, shamt } => {
160                let value = rs1_value.cast_signed() >> shamt.get();
161                ExecutionResult::Continue {
162                    rd,
163                    value: value.cast_unsigned(),
164                }
165            }
166
167            Self::Lb { rd, rs1: _, imm } => {
168                let addr = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
169                let value = i32::from(memory.read::<i8>(u64::from(addr))?);
170                ExecutionResult::Continue {
171                    rd,
172                    value: value.cast_unsigned(),
173                }
174            }
175            Self::Lh { rd, rs1: _, imm } => {
176                let addr = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
177                let value = i32::from(memory.read::<i16>(u64::from(addr))?);
178                ExecutionResult::Continue {
179                    rd,
180                    value: value.cast_unsigned(),
181                }
182            }
183            Self::Lw { rd, rs1: _, imm } => {
184                let addr = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
185                let value = memory.read::<u32>(u64::from(addr))?;
186                ExecutionResult::Continue { rd, value }
187            }
188            Self::Lbu { rd, rs1: _, imm } => {
189                let addr = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
190                let value = memory.read::<u8>(u64::from(addr))?;
191                ExecutionResult::Continue {
192                    rd,
193                    value: u32::from(value),
194                }
195            }
196            Self::Lhu { rd, rs1: _, imm } => {
197                let addr = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
198                let value = memory.read::<u16>(u64::from(addr))?;
199                ExecutionResult::Continue {
200                    rd,
201                    value: u32::from(value),
202                }
203            }
204
205            Self::Jalr { rd, rs1: _, imm } => {
206                let target = (rs1_value.wrapping_add(i32::from(imm).cast_unsigned())) & !1u32;
207                regs.write(rd, program_counter.get_pc());
208
209                ExecutionResult::Jump { target }
210            }
211
212            Self::Sb {
213                rs2: _,
214                rs1: _,
215                imm,
216            } => {
217                let addr = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
218                memory.write(u64::from(addr), rs2_value as u8)?;
219                ExecutionResult::ContinueNoWrite
220            }
221            Self::Sh {
222                rs2: _,
223                rs1: _,
224                imm,
225            } => {
226                let addr = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
227                memory.write(u64::from(addr), rs2_value as u16)?;
228                ExecutionResult::ContinueNoWrite
229            }
230            Self::Sw {
231                rs2: _,
232                rs1: _,
233                imm,
234            } => {
235                let addr = rs1_value.wrapping_add(i32::from(imm).cast_unsigned());
236                memory.write(u64::from(addr), rs2_value)?;
237                ExecutionResult::ContinueNoWrite
238            }
239
240            Self::Beq {
241                rs1: _,
242                rs2: _,
243                imm,
244            } => {
245                if rs1_value == rs2_value {
246                    return ExecutionResult::Branch {
247                        offset: i32::from(imm),
248                    };
249                }
250
251                ExecutionResult::ContinueNoWrite
252            }
253            Self::Bne {
254                rs1: _,
255                rs2: _,
256                imm,
257            } => {
258                if rs1_value != rs2_value {
259                    return ExecutionResult::Branch {
260                        offset: i32::from(imm),
261                    };
262                }
263
264                ExecutionResult::ContinueNoWrite
265            }
266            Self::Blt {
267                rs1: _,
268                rs2: _,
269                imm,
270            } => {
271                if rs1_value.cast_signed() < rs2_value.cast_signed() {
272                    return ExecutionResult::Branch {
273                        offset: i32::from(imm),
274                    };
275                }
276
277                ExecutionResult::ContinueNoWrite
278            }
279            Self::Bge {
280                rs1: _,
281                rs2: _,
282                imm,
283            } => {
284                if rs1_value.cast_signed() >= rs2_value.cast_signed() {
285                    return ExecutionResult::Branch {
286                        offset: i32::from(imm),
287                    };
288                }
289
290                ExecutionResult::ContinueNoWrite
291            }
292            Self::Bltu {
293                rs1: _,
294                rs2: _,
295                imm,
296            } => {
297                if rs1_value < rs2_value {
298                    return ExecutionResult::Branch {
299                        offset: i32::from(imm),
300                    };
301                }
302
303                ExecutionResult::ContinueNoWrite
304            }
305            Self::Bgeu {
306                rs1: _,
307                rs2: _,
308                imm,
309            } => {
310                if rs1_value >= rs2_value {
311                    return ExecutionResult::Branch {
312                        offset: i32::from(imm),
313                    };
314                }
315
316                ExecutionResult::ContinueNoWrite
317            }
318
319            Self::Lui { rd, imm } => ExecutionResult::Continue {
320                rd,
321                value: imm.to_i32().cast_unsigned(),
322            },
323
324            Self::Auipc { rd, imm } => {
325                let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
326                ExecutionResult::Continue {
327                    rd,
328                    value: old_pc.wrapping_add(imm.to_i32().cast_unsigned()),
329                }
330            }
331
332            Self::Jal { rd, imm } => {
333                let pc = program_counter.get_pc();
334                regs.write(rd, pc);
335
336                ExecutionResult::Branch {
337                    offset: imm.to_i32(),
338                }
339            }
340
341            Self::Fence { pred, succ } => {
342                env.handle_fence(pred, succ);
343                ExecutionResult::ContinueNoWrite
344            }
345            Self::FenceTso => {
346                env.handle_fence_tso();
347                ExecutionResult::ContinueNoWrite
348            }
349
350            Self::Ecall => env.handle_ecall(regs, memory, program_counter),
351            Self::Ebreak => {
352                env.handle_ebreak(regs, memory, program_counter, size_of::<u32>() as u8)
353            }
354
355            Self::Unimp => {
356                let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
357                ExecutionResult::Err(ExecutionError::IllegalInstruction {
358                    address: PackedAddress::new(old_pc),
359                })
360            }
361        }
362    }
363}