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