sp1_core_executor/disassembler/
rrs.rs

1use rrs_lib::{
2    instruction_formats::{BType, IType, ITypeCSR, ITypeShamt, JType, RType, SType, UType},
3    process_instruction, InstructionProcessor,
4};
5
6use crate::{Instruction, Opcode, Register};
7
8impl Instruction {
9    /// Create a new [`Instruction`] from an R-type instruction.
10    #[must_use]
11    pub const fn from_r_type(opcode: Opcode, dec_insn: &RType) -> Self {
12        Self::new(opcode, dec_insn.rd as u8, dec_insn.rs1 as u32, dec_insn.rs2 as u32, false, false)
13    }
14
15    /// Create a new [`Instruction`] from an I-type instruction.
16    #[must_use]
17    pub const fn from_i_type(opcode: Opcode, dec_insn: &IType) -> Self {
18        Self::new(opcode, dec_insn.rd as u8, dec_insn.rs1 as u32, dec_insn.imm as u32, false, true)
19    }
20
21    /// Create a new [`Instruction`] from an I-type instruction with a shamt.
22    #[must_use]
23    pub const fn from_i_type_shamt(opcode: Opcode, dec_insn: &ITypeShamt) -> Self {
24        Self::new(opcode, dec_insn.rd as u8, dec_insn.rs1 as u32, dec_insn.shamt, false, true)
25    }
26
27    /// Create a new [`Instruction`] from an S-type instruction.
28    #[must_use]
29    pub const fn from_s_type(opcode: Opcode, dec_insn: &SType) -> Self {
30        Self::new(opcode, dec_insn.rs2 as u8, dec_insn.rs1 as u32, dec_insn.imm as u32, false, true)
31    }
32
33    /// Create a new [`Instruction`] from a B-type instruction.
34    #[must_use]
35    pub const fn from_b_type(opcode: Opcode, dec_insn: &BType) -> Self {
36        Self::new(opcode, dec_insn.rs1 as u8, dec_insn.rs2 as u32, dec_insn.imm as u32, false, true)
37    }
38
39    /// Create a new [`Instruction`] that is not implemented.
40    #[must_use]
41    pub const fn unimp() -> Self {
42        Self::new(Opcode::UNIMP, 0, 0, 0, true, true)
43    }
44
45    /// Returns if the [`Instruction`] is an R-type instruction.
46    #[inline]
47    #[must_use]
48    pub const fn is_r_type(&self) -> bool {
49        !self.imm_c
50    }
51
52    /// Returns whether the [`Instruction`] is an I-type instruction.
53    #[inline]
54    #[must_use]
55    pub const fn is_i_type(&self) -> bool {
56        self.imm_c
57    }
58
59    /// Decode the [`Instruction`] in the R-type format.
60    #[inline]
61    #[must_use]
62    pub fn r_type(&self) -> (Register, Register, Register) {
63        (
64            Register::from_u8(self.op_a),
65            Register::from_u8(self.op_b as u8),
66            Register::from_u8(self.op_c as u8),
67        )
68    }
69
70    /// Decode the [`Instruction`] in the I-type format.
71    #[inline]
72    #[must_use]
73    pub fn i_type(&self) -> (Register, Register, u32) {
74        (Register::from_u8(self.op_a), Register::from_u8(self.op_b as u8), self.op_c)
75    }
76
77    /// Decode the [`Instruction`] in the S-type format.
78    #[inline]
79    #[must_use]
80    pub fn s_type(&self) -> (Register, Register, u32) {
81        (Register::from_u8(self.op_a), Register::from_u8(self.op_b as u8), self.op_c)
82    }
83
84    /// Decode the [`Instruction`] in the B-type format.
85    #[inline]
86    #[must_use]
87    pub fn b_type(&self) -> (Register, Register, u32) {
88        (Register::from_u8(self.op_a), Register::from_u8(self.op_b as u8), self.op_c)
89    }
90
91    /// Decode the [`Instruction`] in the J-type format.
92    #[inline]
93    #[must_use]
94    pub fn j_type(&self) -> (Register, u32) {
95        (Register::from_u8(self.op_a), self.op_b)
96    }
97
98    /// Decode the [`Instruction`] in the U-type format.
99    #[inline]
100    #[must_use]
101    pub fn u_type(&self) -> (Register, u32) {
102        (Register::from_u8(self.op_a), self.op_b)
103    }
104}
105
106/// A transpiler that converts the 32-bit encoded instructions into instructions.
107pub(crate) struct InstructionTranspiler;
108
109impl InstructionProcessor for InstructionTranspiler {
110    type InstructionResult = Instruction;
111
112    fn process_add(&mut self, dec_insn: RType) -> Self::InstructionResult {
113        Instruction::from_r_type(Opcode::ADD, &dec_insn)
114    }
115
116    fn process_addi(&mut self, dec_insn: IType) -> Self::InstructionResult {
117        Instruction::from_i_type(Opcode::ADD, &dec_insn)
118    }
119
120    fn process_sub(&mut self, dec_insn: RType) -> Self::InstructionResult {
121        Instruction::from_r_type(Opcode::SUB, &dec_insn)
122    }
123
124    fn process_xor(&mut self, dec_insn: RType) -> Self::InstructionResult {
125        Instruction::from_r_type(Opcode::XOR, &dec_insn)
126    }
127
128    fn process_xori(&mut self, dec_insn: IType) -> Self::InstructionResult {
129        Instruction::from_i_type(Opcode::XOR, &dec_insn)
130    }
131
132    fn process_or(&mut self, dec_insn: RType) -> Self::InstructionResult {
133        Instruction::from_r_type(Opcode::OR, &dec_insn)
134    }
135
136    fn process_ori(&mut self, dec_insn: IType) -> Self::InstructionResult {
137        Instruction::from_i_type(Opcode::OR, &dec_insn)
138    }
139
140    fn process_and(&mut self, dec_insn: RType) -> Self::InstructionResult {
141        Instruction::from_r_type(Opcode::AND, &dec_insn)
142    }
143
144    fn process_andi(&mut self, dec_insn: IType) -> Self::InstructionResult {
145        Instruction::from_i_type(Opcode::AND, &dec_insn)
146    }
147
148    fn process_sll(&mut self, dec_insn: RType) -> Self::InstructionResult {
149        Instruction::from_r_type(Opcode::SLL, &dec_insn)
150    }
151
152    fn process_slli(&mut self, dec_insn: ITypeShamt) -> Self::InstructionResult {
153        Instruction::from_i_type_shamt(Opcode::SLL, &dec_insn)
154    }
155
156    fn process_srl(&mut self, dec_insn: RType) -> Self::InstructionResult {
157        Instruction::from_r_type(Opcode::SRL, &dec_insn)
158    }
159
160    fn process_srli(&mut self, dec_insn: ITypeShamt) -> Self::InstructionResult {
161        Instruction::from_i_type_shamt(Opcode::SRL, &dec_insn)
162    }
163
164    fn process_sra(&mut self, dec_insn: RType) -> Self::InstructionResult {
165        Instruction::from_r_type(Opcode::SRA, &dec_insn)
166    }
167
168    fn process_srai(&mut self, dec_insn: ITypeShamt) -> Self::InstructionResult {
169        Instruction::from_i_type_shamt(Opcode::SRA, &dec_insn)
170    }
171
172    fn process_slt(&mut self, dec_insn: RType) -> Self::InstructionResult {
173        Instruction::from_r_type(Opcode::SLT, &dec_insn)
174    }
175
176    fn process_slti(&mut self, dec_insn: IType) -> Self::InstructionResult {
177        Instruction::from_i_type(Opcode::SLT, &dec_insn)
178    }
179
180    fn process_sltu(&mut self, dec_insn: RType) -> Self::InstructionResult {
181        Instruction::from_r_type(Opcode::SLTU, &dec_insn)
182    }
183
184    fn process_sltui(&mut self, dec_insn: IType) -> Self::InstructionResult {
185        Instruction::from_i_type(Opcode::SLTU, &dec_insn)
186    }
187
188    fn process_lb(&mut self, dec_insn: IType) -> Self::InstructionResult {
189        Instruction::from_i_type(Opcode::LB, &dec_insn)
190    }
191
192    fn process_lh(&mut self, dec_insn: IType) -> Self::InstructionResult {
193        Instruction::from_i_type(Opcode::LH, &dec_insn)
194    }
195
196    fn process_lw(&mut self, dec_insn: IType) -> Self::InstructionResult {
197        Instruction::from_i_type(Opcode::LW, &dec_insn)
198    }
199
200    fn process_lbu(&mut self, dec_insn: IType) -> Self::InstructionResult {
201        Instruction::from_i_type(Opcode::LBU, &dec_insn)
202    }
203
204    fn process_lhu(&mut self, dec_insn: IType) -> Self::InstructionResult {
205        Instruction::from_i_type(Opcode::LHU, &dec_insn)
206    }
207
208    fn process_sb(&mut self, dec_insn: SType) -> Self::InstructionResult {
209        Instruction::from_s_type(Opcode::SB, &dec_insn)
210    }
211
212    fn process_sh(&mut self, dec_insn: SType) -> Self::InstructionResult {
213        Instruction::from_s_type(Opcode::SH, &dec_insn)
214    }
215
216    fn process_sw(&mut self, dec_insn: SType) -> Self::InstructionResult {
217        Instruction::from_s_type(Opcode::SW, &dec_insn)
218    }
219
220    fn process_beq(&mut self, dec_insn: BType) -> Self::InstructionResult {
221        Instruction::from_b_type(Opcode::BEQ, &dec_insn)
222    }
223
224    fn process_bne(&mut self, dec_insn: BType) -> Self::InstructionResult {
225        Instruction::from_b_type(Opcode::BNE, &dec_insn)
226    }
227
228    fn process_blt(&mut self, dec_insn: BType) -> Self::InstructionResult {
229        Instruction::from_b_type(Opcode::BLT, &dec_insn)
230    }
231
232    fn process_bge(&mut self, dec_insn: BType) -> Self::InstructionResult {
233        Instruction::from_b_type(Opcode::BGE, &dec_insn)
234    }
235
236    fn process_bltu(&mut self, dec_insn: BType) -> Self::InstructionResult {
237        Instruction::from_b_type(Opcode::BLTU, &dec_insn)
238    }
239
240    fn process_bgeu(&mut self, dec_insn: BType) -> Self::InstructionResult {
241        Instruction::from_b_type(Opcode::BGEU, &dec_insn)
242    }
243
244    fn process_jal(&mut self, dec_insn: JType) -> Self::InstructionResult {
245        Instruction::new(Opcode::JAL, dec_insn.rd as u8, dec_insn.imm as u32, 0, true, true)
246    }
247
248    fn process_jalr(&mut self, dec_insn: IType) -> Self::InstructionResult {
249        Instruction::new(
250            Opcode::JALR,
251            dec_insn.rd as u8,
252            dec_insn.rs1 as u32,
253            dec_insn.imm as u32,
254            false,
255            true,
256        )
257    }
258
259    fn process_lui(&mut self, dec_insn: UType) -> Self::InstructionResult {
260        // LUI instructions are handled in a special way inside the zkVM.
261        //
262        // Notably, LUI instructions are converted to an SLL instruction with `imm_b` and `imm_c`
263        // turned on. Additionally the `op_c` should be set to 12.
264        Instruction::new(Opcode::ADD, dec_insn.rd as u8, 0, dec_insn.imm as u32, true, true)
265    }
266
267    /// AUIPC instructions have the third operand set to imm << 12.
268    fn process_auipc(&mut self, dec_insn: UType) -> Self::InstructionResult {
269        Instruction::new(
270            Opcode::AUIPC,
271            dec_insn.rd as u8,
272            dec_insn.imm as u32,
273            dec_insn.imm as u32,
274            true,
275            true,
276        )
277    }
278
279    fn process_ecall(&mut self) -> Self::InstructionResult {
280        Instruction::new(
281            Opcode::ECALL,
282            Register::X5 as u8,
283            Register::X10 as u32,
284            Register::X11 as u32,
285            false,
286            false,
287        )
288    }
289
290    fn process_ebreak(&mut self) -> Self::InstructionResult {
291        Instruction::new(Opcode::EBREAK, 0, 0, 0, false, false)
292    }
293
294    fn process_mul(&mut self, dec_insn: RType) -> Self::InstructionResult {
295        Instruction::from_r_type(Opcode::MUL, &dec_insn)
296    }
297
298    fn process_mulh(&mut self, dec_insn: RType) -> Self::InstructionResult {
299        Instruction::from_r_type(Opcode::MULH, &dec_insn)
300    }
301
302    fn process_mulhu(&mut self, dec_insn: RType) -> Self::InstructionResult {
303        Instruction::from_r_type(Opcode::MULHU, &dec_insn)
304    }
305
306    fn process_mulhsu(&mut self, dec_insn: RType) -> Self::InstructionResult {
307        Instruction::from_r_type(Opcode::MULHSU, &dec_insn)
308    }
309
310    fn process_div(&mut self, dec_insn: RType) -> Self::InstructionResult {
311        Instruction::from_r_type(Opcode::DIV, &dec_insn)
312    }
313
314    fn process_divu(&mut self, dec_insn: RType) -> Self::InstructionResult {
315        Instruction::from_r_type(Opcode::DIVU, &dec_insn)
316    }
317
318    fn process_rem(&mut self, dec_insn: RType) -> Self::InstructionResult {
319        Instruction::from_r_type(Opcode::REM, &dec_insn)
320    }
321
322    fn process_remu(&mut self, dec_insn: RType) -> Self::InstructionResult {
323        Instruction::from_r_type(Opcode::REMU, &dec_insn)
324    }
325
326    fn process_csrrc(&mut self, _: ITypeCSR) -> Self::InstructionResult {
327        Instruction::unimp()
328    }
329
330    fn process_csrrci(&mut self, _: ITypeCSR) -> Self::InstructionResult {
331        Instruction::unimp()
332    }
333
334    fn process_csrrs(&mut self, _: ITypeCSR) -> Self::InstructionResult {
335        Instruction::unimp()
336    }
337
338    fn process_csrrsi(&mut self, _: ITypeCSR) -> Self::InstructionResult {
339        Instruction::unimp()
340    }
341
342    fn process_csrrw(&mut self, _: ITypeCSR) -> Self::InstructionResult {
343        Instruction::unimp()
344    }
345
346    fn process_csrrwi(&mut self, _: ITypeCSR) -> Self::InstructionResult {
347        Instruction::unimp()
348    }
349
350    fn process_fence(&mut self, _: IType) -> Self::InstructionResult {
351        Instruction::unimp()
352    }
353
354    fn process_mret(&mut self) -> Self::InstructionResult {
355        Instruction::unimp()
356    }
357
358    fn process_wfi(&mut self) -> Self::InstructionResult {
359        Instruction::unimp()
360    }
361}
362
363/// Transpile the [`Instruction`]s from the 32-bit encoded instructions.
364///
365/// # Panics
366///
367/// This function will return an error if the [`Instruction`] cannot be processed.
368#[must_use]
369pub(crate) fn transpile(instructions_u32: &[u32]) -> Vec<Instruction> {
370    let mut instructions = Vec::new();
371    let mut transpiler = InstructionTranspiler;
372    for instruction_u32 in instructions_u32 {
373        let instruction = process_instruction(&mut transpiler, *instruction_u32).unwrap();
374        instructions.push(instruction);
375    }
376    instructions
377}