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::*;
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}