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