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, ExecutionError, ProgramCounter, RegisterFile, SystemInstructionHandler,
15 VirtualMemory,
16};
17use ab_riscv_macros::instruction_execution;
18use ab_riscv_primitives::prelude::*;
19use core::ops::ControlFlow;
20
21#[instruction_execution]
22impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
23 ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
24 for Rv32Instruction<Reg>
25where
26 Reg: Register<Type = u32>,
27 Regs: RegisterFile<Reg>,
28 Memory: VirtualMemory,
29 PC: ProgramCounter<Reg::Type, Memory, CustomError>,
30 InstructionHandler: SystemInstructionHandler<Reg, Regs, Memory, PC, CustomError>,
31{
32 #[inline(always)]
33 fn execute(
34 self,
35 regs: &mut Regs,
36 _ext_state: &mut ExtState,
37 memory: &mut Memory,
38 program_counter: &mut PC,
39 system_instruction_handler: &mut InstructionHandler,
40 ) -> Result<ControlFlow<()>, ExecutionError<Reg::Type, CustomError>> {
41 match self {
42 Self::Add { rd, rs1, rs2 } => {
43 let value = regs.read(rs1).wrapping_add(regs.read(rs2));
44 regs.write(rd, value);
45 }
46 Self::Sub { rd, rs1, rs2 } => {
47 let value = regs.read(rs1).wrapping_sub(regs.read(rs2));
48 regs.write(rd, value);
49 }
50 Self::Sll { rd, rs1, rs2 } => {
51 let shamt = regs.read(rs2) & 0x1f;
52 let value = regs.read(rs1) << shamt;
53 regs.write(rd, value);
54 }
55 Self::Slt { rd, rs1, rs2 } => {
56 let value = regs.read(rs1).cast_signed() < regs.read(rs2).cast_signed();
57 regs.write(rd, value as u32);
58 }
59 Self::Sltu { rd, rs1, rs2 } => {
60 let value = regs.read(rs1) < regs.read(rs2);
61 regs.write(rd, value as u32);
62 }
63 Self::Xor { rd, rs1, rs2 } => {
64 let value = regs.read(rs1) ^ regs.read(rs2);
65 regs.write(rd, value);
66 }
67 Self::Srl { rd, rs1, rs2 } => {
68 let shamt = regs.read(rs2) & 0x1f;
69 let value = regs.read(rs1) >> shamt;
70 regs.write(rd, value);
71 }
72 Self::Sra { rd, rs1, rs2 } => {
73 let shamt = regs.read(rs2) & 0x1f;
74 let value = regs.read(rs1).cast_signed() >> shamt;
75 regs.write(rd, value.cast_unsigned());
76 }
77 Self::Or { rd, rs1, rs2 } => {
78 let value = regs.read(rs1) | regs.read(rs2);
79 regs.write(rd, value);
80 }
81 Self::And { rd, rs1, rs2 } => {
82 let value = regs.read(rs1) & regs.read(rs2);
83 regs.write(rd, value);
84 }
85
86 Self::Addi { rd, rs1, imm } => {
87 let value = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
88 regs.write(rd, value);
89 }
90 Self::Slti { rd, rs1, imm } => {
91 let value = regs.read(rs1).cast_signed() < i32::from(imm);
92 regs.write(rd, value as u32);
93 }
94 Self::Sltiu { rd, rs1, imm } => {
95 let value = regs.read(rs1) < i32::from(imm).cast_unsigned();
96 regs.write(rd, value as u32);
97 }
98 Self::Xori { rd, rs1, imm } => {
99 let value = regs.read(rs1) ^ i32::from(imm).cast_unsigned();
100 regs.write(rd, value);
101 }
102 Self::Ori { rd, rs1, imm } => {
103 let value = regs.read(rs1) | i32::from(imm).cast_unsigned();
104 regs.write(rd, value);
105 }
106 Self::Andi { rd, rs1, imm } => {
107 let value = regs.read(rs1) & i32::from(imm).cast_unsigned();
108 regs.write(rd, value);
109 }
110 Self::Slli { rd, rs1, shamt } => {
111 let value = regs.read(rs1) << shamt;
112 regs.write(rd, value);
113 }
114 Self::Srli { rd, rs1, shamt } => {
115 let value = regs.read(rs1) >> shamt;
116 regs.write(rd, value);
117 }
118 Self::Srai { rd, rs1, shamt } => {
119 let value = regs.read(rs1).cast_signed() >> shamt;
120 regs.write(rd, value.cast_unsigned());
121 }
122
123 Self::Lb { rd, rs1, imm } => {
124 let addr = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
125 let value = i32::from(memory.read::<i8>(u64::from(addr))?);
126 regs.write(rd, value.cast_unsigned());
127 }
128 Self::Lh { rd, rs1, imm } => {
129 let addr = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
130 let value = i32::from(memory.read::<i16>(u64::from(addr))?);
131 regs.write(rd, value.cast_unsigned());
132 }
133 Self::Lw { rd, rs1, imm } => {
134 let addr = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
135 let value = memory.read::<u32>(u64::from(addr))?;
136 regs.write(rd, value);
137 }
138 Self::Lbu { rd, rs1, imm } => {
139 let addr = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
140 let value = memory.read::<u8>(u64::from(addr))?;
141 regs.write(rd, value as u32);
142 }
143 Self::Lhu { rd, rs1, imm } => {
144 let addr = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
145 let value = memory.read::<u16>(u64::from(addr))?;
146 regs.write(rd, value as u32);
147 }
148
149 Self::Jalr { rd, rs1, imm } => {
150 let target = (regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned())) & !1u32;
151 regs.write(rd, program_counter.get_pc());
152 return program_counter
153 .set_pc(memory, target)
154 .map_err(ExecutionError::from);
155 }
156
157 Self::Sb { rs2, rs1, imm } => {
158 let addr = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
159 memory.write(u64::from(addr), regs.read(rs2) as u8)?;
160 }
161 Self::Sh { rs2, rs1, imm } => {
162 let addr = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
163 memory.write(u64::from(addr), regs.read(rs2) as u16)?;
164 }
165 Self::Sw { rs2, rs1, imm } => {
166 let addr = regs.read(rs1).wrapping_add(i32::from(imm).cast_unsigned());
167 memory.write(u64::from(addr), regs.read(rs2))?;
168 }
169
170 Self::Beq { rs1, rs2, imm } => {
171 if regs.read(rs1) == regs.read(rs2) {
172 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
173 return program_counter
174 .set_pc(memory, old_pc.wrapping_add(imm.cast_unsigned()))
175 .map_err(ExecutionError::from);
176 }
177 }
178 Self::Bne { rs1, rs2, imm } => {
179 if regs.read(rs1) != regs.read(rs2) {
180 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
181 return program_counter
182 .set_pc(memory, old_pc.wrapping_add(imm.cast_unsigned()))
183 .map_err(ExecutionError::from);
184 }
185 }
186 Self::Blt { rs1, rs2, imm } => {
187 if regs.read(rs1).cast_signed() < regs.read(rs2).cast_signed() {
188 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
189 return program_counter
190 .set_pc(memory, old_pc.wrapping_add(imm.cast_unsigned()))
191 .map_err(ExecutionError::from);
192 }
193 }
194 Self::Bge { rs1, rs2, imm } => {
195 if regs.read(rs1).cast_signed() >= regs.read(rs2).cast_signed() {
196 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
197 return program_counter
198 .set_pc(memory, old_pc.wrapping_add(imm.cast_unsigned()))
199 .map_err(ExecutionError::from);
200 }
201 }
202 Self::Bltu { rs1, rs2, imm } => {
203 if regs.read(rs1) < regs.read(rs2) {
204 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
205 return program_counter
206 .set_pc(memory, old_pc.wrapping_add(imm.cast_unsigned()))
207 .map_err(ExecutionError::from);
208 }
209 }
210 Self::Bgeu { rs1, rs2, imm } => {
211 if regs.read(rs1) >= regs.read(rs2) {
212 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
213 return program_counter
214 .set_pc(memory, old_pc.wrapping_add(imm.cast_unsigned()))
215 .map_err(ExecutionError::from);
216 }
217 }
218
219 Self::Lui { rd, imm } => {
220 regs.write(rd, imm.cast_unsigned());
221 }
222
223 Self::Auipc { rd, imm } => {
224 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
225 regs.write(rd, old_pc.wrapping_add(imm.cast_unsigned()));
226 }
227
228 Self::Jal { rd, imm } => {
229 let pc = program_counter.get_pc();
230 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
231 regs.write(rd, pc);
232 return program_counter
233 .set_pc(memory, old_pc.wrapping_add(imm.cast_unsigned()))
234 .map_err(ExecutionError::from);
235 }
236
237 Self::Fence { pred, succ } => {
238 system_instruction_handler.handle_fence(pred, succ);
239 }
240 Self::FenceTso => {
241 system_instruction_handler.handle_fence_tso();
242 }
243
244 Self::Ecall => {
245 return system_instruction_handler.handle_ecall(regs, memory, program_counter);
246 }
247 Self::Ebreak => {
248 system_instruction_handler.handle_ebreak(regs, memory, program_counter.get_pc());
249 }
250
251 Self::Unimp => {
252 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
253 return Err(ExecutionError::IllegalInstruction { address: old_pc });
254 }
255 }
256
257 Ok(ControlFlow::Continue(()))
258 }
259}