1use std::marker::PhantomData;
2
3use openvm_instructions::{instruction::Instruction, riscv::RV32_REGISTER_NUM_LIMBS, *};
4use openvm_stark_backend::p3_field::PrimeField32;
5use openvm_transpiler::util::{
6 from_b_type, from_i_type, from_i_type_shamt, from_j_type, from_load, from_r_type, from_s_type,
7 from_u_type, nop,
8};
9use rrs_lib::{
10 instruction_formats::{BType, IType, ITypeShamt, JType, RType, SType, UType},
11 InstructionProcessor,
12};
13
14use crate::{
15 BaseAluOpcode, BranchEqualOpcode, BranchLessThanOpcode, DivRemOpcode, LessThanOpcode,
16 MulHOpcode, MulOpcode, Rv32AuipcOpcode, Rv32JalLuiOpcode, Rv32JalrOpcode, Rv32LoadStoreOpcode,
17 ShiftOpcode,
18};
19
20pub(crate) struct InstructionTranspiler<F>(pub PhantomData<F>);
22
23impl<F: PrimeField32> InstructionProcessor for InstructionTranspiler<F> {
24 type InstructionResult = Instruction<F>;
25
26 fn process_add(&mut self, dec_insn: RType) -> Self::InstructionResult {
27 from_r_type(
28 BaseAluOpcode::ADD.global_opcode().as_usize(),
29 1,
30 &dec_insn,
31 false,
32 )
33 }
34
35 fn process_addi(&mut self, dec_insn: IType) -> Self::InstructionResult {
36 from_i_type(BaseAluOpcode::ADD.global_opcode().as_usize(), &dec_insn)
37 }
38
39 fn process_sub(&mut self, dec_insn: RType) -> Self::InstructionResult {
40 from_r_type(
41 BaseAluOpcode::SUB.global_opcode().as_usize(),
42 1,
43 &dec_insn,
44 false,
45 )
46 }
47
48 fn process_xor(&mut self, dec_insn: RType) -> Self::InstructionResult {
49 from_r_type(
50 BaseAluOpcode::XOR.global_opcode().as_usize(),
51 1,
52 &dec_insn,
53 false,
54 )
55 }
56
57 fn process_xori(&mut self, dec_insn: IType) -> Self::InstructionResult {
58 from_i_type(BaseAluOpcode::XOR.global_opcode().as_usize(), &dec_insn)
59 }
60
61 fn process_or(&mut self, dec_insn: RType) -> Self::InstructionResult {
62 from_r_type(
63 BaseAluOpcode::OR.global_opcode().as_usize(),
64 1,
65 &dec_insn,
66 false,
67 )
68 }
69
70 fn process_ori(&mut self, dec_insn: IType) -> Self::InstructionResult {
71 from_i_type(BaseAluOpcode::OR.global_opcode().as_usize(), &dec_insn)
72 }
73
74 fn process_and(&mut self, dec_insn: RType) -> Self::InstructionResult {
75 from_r_type(
76 BaseAluOpcode::AND.global_opcode().as_usize(),
77 1,
78 &dec_insn,
79 false,
80 )
81 }
82
83 fn process_andi(&mut self, dec_insn: IType) -> Self::InstructionResult {
84 from_i_type(BaseAluOpcode::AND.global_opcode().as_usize(), &dec_insn)
85 }
86
87 fn process_sll(&mut self, dec_insn: RType) -> Self::InstructionResult {
88 from_r_type(
89 ShiftOpcode::SLL.global_opcode().as_usize(),
90 1,
91 &dec_insn,
92 false,
93 )
94 }
95
96 fn process_slli(&mut self, dec_insn: ITypeShamt) -> Self::InstructionResult {
97 from_i_type_shamt(ShiftOpcode::SLL.global_opcode().as_usize(), &dec_insn)
98 }
99
100 fn process_srl(&mut self, dec_insn: RType) -> Self::InstructionResult {
101 from_r_type(
102 ShiftOpcode::SRL.global_opcode().as_usize(),
103 1,
104 &dec_insn,
105 false,
106 )
107 }
108
109 fn process_srli(&mut self, dec_insn: ITypeShamt) -> Self::InstructionResult {
110 from_i_type_shamt(ShiftOpcode::SRL.global_opcode().as_usize(), &dec_insn)
111 }
112
113 fn process_sra(&mut self, dec_insn: RType) -> Self::InstructionResult {
114 from_r_type(
115 ShiftOpcode::SRA.global_opcode().as_usize(),
116 1,
117 &dec_insn,
118 false,
119 )
120 }
121
122 fn process_srai(&mut self, dec_insn: ITypeShamt) -> Self::InstructionResult {
123 from_i_type_shamt(ShiftOpcode::SRA.global_opcode().as_usize(), &dec_insn)
124 }
125
126 fn process_slt(&mut self, dec_insn: RType) -> Self::InstructionResult {
127 from_r_type(
128 LessThanOpcode::SLT.global_opcode().as_usize(),
129 1,
130 &dec_insn,
131 false,
132 )
133 }
134
135 fn process_slti(&mut self, dec_insn: IType) -> Self::InstructionResult {
136 from_i_type(LessThanOpcode::SLT.global_opcode().as_usize(), &dec_insn)
137 }
138
139 fn process_sltu(&mut self, dec_insn: RType) -> Self::InstructionResult {
140 from_r_type(
141 LessThanOpcode::SLTU.global_opcode().as_usize(),
142 1,
143 &dec_insn,
144 false,
145 )
146 }
147
148 fn process_sltui(&mut self, dec_insn: IType) -> Self::InstructionResult {
149 from_i_type(LessThanOpcode::SLTU.global_opcode().as_usize(), &dec_insn)
150 }
151
152 fn process_lb(&mut self, dec_insn: IType) -> Self::InstructionResult {
153 from_load(
154 Rv32LoadStoreOpcode::LOADB.global_opcode().as_usize(),
155 &dec_insn,
156 )
157 }
158
159 fn process_lh(&mut self, dec_insn: IType) -> Self::InstructionResult {
160 from_load(
161 Rv32LoadStoreOpcode::LOADH.global_opcode().as_usize(),
162 &dec_insn,
163 )
164 }
165
166 fn process_lw(&mut self, dec_insn: IType) -> Self::InstructionResult {
167 from_load(
168 Rv32LoadStoreOpcode::LOADW.global_opcode().as_usize(),
169 &dec_insn,
170 )
171 }
172
173 fn process_lbu(&mut self, dec_insn: IType) -> Self::InstructionResult {
174 from_load(
175 Rv32LoadStoreOpcode::LOADBU.global_opcode().as_usize(),
176 &dec_insn,
177 )
178 }
179
180 fn process_lhu(&mut self, dec_insn: IType) -> Self::InstructionResult {
181 from_load(
182 Rv32LoadStoreOpcode::LOADHU.global_opcode().as_usize(),
183 &dec_insn,
184 )
185 }
186
187 fn process_sb(&mut self, dec_insn: SType) -> Self::InstructionResult {
188 from_s_type(
189 Rv32LoadStoreOpcode::STOREB.global_opcode().as_usize(),
190 &dec_insn,
191 )
192 }
193
194 fn process_sh(&mut self, dec_insn: SType) -> Self::InstructionResult {
195 from_s_type(
196 Rv32LoadStoreOpcode::STOREH.global_opcode().as_usize(),
197 &dec_insn,
198 )
199 }
200
201 fn process_sw(&mut self, dec_insn: SType) -> Self::InstructionResult {
202 from_s_type(
203 Rv32LoadStoreOpcode::STOREW.global_opcode().as_usize(),
204 &dec_insn,
205 )
206 }
207
208 fn process_beq(&mut self, dec_insn: BType) -> Self::InstructionResult {
209 from_b_type(BranchEqualOpcode::BEQ.global_opcode().as_usize(), &dec_insn)
210 }
211
212 fn process_bne(&mut self, dec_insn: BType) -> Self::InstructionResult {
213 from_b_type(BranchEqualOpcode::BNE.global_opcode().as_usize(), &dec_insn)
214 }
215
216 fn process_blt(&mut self, dec_insn: BType) -> Self::InstructionResult {
217 from_b_type(
218 BranchLessThanOpcode::BLT.global_opcode().as_usize(),
219 &dec_insn,
220 )
221 }
222
223 fn process_bge(&mut self, dec_insn: BType) -> Self::InstructionResult {
224 from_b_type(
225 BranchLessThanOpcode::BGE.global_opcode().as_usize(),
226 &dec_insn,
227 )
228 }
229
230 fn process_bltu(&mut self, dec_insn: BType) -> Self::InstructionResult {
231 from_b_type(
232 BranchLessThanOpcode::BLTU.global_opcode().as_usize(),
233 &dec_insn,
234 )
235 }
236
237 fn process_bgeu(&mut self, dec_insn: BType) -> Self::InstructionResult {
238 from_b_type(
239 BranchLessThanOpcode::BGEU.global_opcode().as_usize(),
240 &dec_insn,
241 )
242 }
243
244 fn process_jal(&mut self, dec_insn: JType) -> Self::InstructionResult {
245 from_j_type(Rv32JalLuiOpcode::JAL.global_opcode().as_usize(), &dec_insn)
246 }
247
248 fn process_jalr(&mut self, dec_insn: IType) -> Self::InstructionResult {
249 Instruction::new(
250 Rv32JalrOpcode::JALR.global_opcode(),
251 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rd),
252 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1),
253 F::from_canonical_u32((dec_insn.imm as u32) & 0xffff),
254 F::ONE,
255 F::ZERO,
256 F::from_bool(dec_insn.rd != 0),
257 F::from_bool(dec_insn.imm < 0),
258 )
259 }
260
261 fn process_lui(&mut self, dec_insn: UType) -> Self::InstructionResult {
262 if dec_insn.rd == 0 {
263 return nop();
264 }
265 let mut result = from_u_type(Rv32JalLuiOpcode::LUI.global_opcode().as_usize(), &dec_insn);
267 result.f = F::ONE;
268 result
269 }
270
271 fn process_auipc(&mut self, dec_insn: UType) -> Self::InstructionResult {
272 if dec_insn.rd == 0 {
273 return nop();
274 }
275 Instruction::new(
276 Rv32AuipcOpcode::AUIPC.global_opcode(),
277 F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rd),
278 F::ZERO,
279 F::from_canonical_u32(((dec_insn.imm as u32) & 0xfffff000) >> 8),
280 F::ONE, F::ZERO,
282 F::ZERO,
283 F::ZERO,
284 )
285 }
286
287 fn process_mul(&mut self, dec_insn: RType) -> Self::InstructionResult {
288 from_r_type(
289 MulOpcode::MUL.global_opcode().as_usize(),
290 0,
291 &dec_insn,
292 false,
293 )
294 }
295
296 fn process_mulh(&mut self, dec_insn: RType) -> Self::InstructionResult {
297 from_r_type(
298 MulHOpcode::MULH.global_opcode().as_usize(),
299 0,
300 &dec_insn,
301 false,
302 )
303 }
304
305 fn process_mulhu(&mut self, dec_insn: RType) -> Self::InstructionResult {
306 from_r_type(
307 MulHOpcode::MULHU.global_opcode().as_usize(),
308 0,
309 &dec_insn,
310 false,
311 )
312 }
313
314 fn process_mulhsu(&mut self, dec_insn: RType) -> Self::InstructionResult {
315 from_r_type(
316 MulHOpcode::MULHSU.global_opcode().as_usize(),
317 0,
318 &dec_insn,
319 false,
320 )
321 }
322
323 fn process_div(&mut self, dec_insn: RType) -> Self::InstructionResult {
324 from_r_type(
325 DivRemOpcode::DIV.global_opcode().as_usize(),
326 0,
327 &dec_insn,
328 false,
329 )
330 }
331
332 fn process_divu(&mut self, dec_insn: RType) -> Self::InstructionResult {
333 from_r_type(
334 DivRemOpcode::DIVU.global_opcode().as_usize(),
335 0,
336 &dec_insn,
337 false,
338 )
339 }
340
341 fn process_rem(&mut self, dec_insn: RType) -> Self::InstructionResult {
342 from_r_type(
343 DivRemOpcode::REM.global_opcode().as_usize(),
344 0,
345 &dec_insn,
346 false,
347 )
348 }
349
350 fn process_remu(&mut self, dec_insn: RType) -> Self::InstructionResult {
351 from_r_type(
352 DivRemOpcode::REMU.global_opcode().as_usize(),
353 0,
354 &dec_insn,
355 false,
356 )
357 }
358
359 fn process_fence(&mut self, dec_insn: IType) -> Self::InstructionResult {
360 tracing::debug!("Transpiling fence ({:?}) to nop", dec_insn);
361 nop()
362 }
363}