Skip to main content

sp1_core_executor/disassembler/
rrs.rs

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