sp1_core_executor/
instruction.rs1use core::fmt::Debug;
4use serde::{Deserialize, Serialize};
5
6use crate::opcode::Opcode;
7
8#[derive(Clone, Copy, Serialize, Deserialize)]
14#[repr(C)]
15pub struct Instruction {
16 pub opcode: Opcode,
18 pub op_a: u8,
20 pub op_b: u32,
22 pub op_c: u32,
24 pub imm_b: bool,
26 pub imm_c: bool,
28}
29
30impl Instruction {
31 #[must_use]
33 pub const fn new(
34 opcode: Opcode,
35 op_a: u8,
36 op_b: u32,
37 op_c: u32,
38 imm_b: bool,
39 imm_c: bool,
40 ) -> Self {
41 Self { opcode, op_a, op_b, op_c, imm_b, imm_c }
42 }
43
44 #[must_use]
46 #[inline]
47 pub const fn is_alu_instruction(&self) -> bool {
48 matches!(
49 self.opcode,
50 Opcode::ADD |
51 Opcode::SUB |
52 Opcode::XOR |
53 Opcode::OR |
54 Opcode::AND |
55 Opcode::SLL |
56 Opcode::SRL |
57 Opcode::SRA |
58 Opcode::SLT |
59 Opcode::SLTU |
60 Opcode::MUL |
61 Opcode::MULH |
62 Opcode::MULHU |
63 Opcode::MULHSU |
64 Opcode::DIV |
65 Opcode::DIVU |
66 Opcode::REM |
67 Opcode::REMU
68 )
69 }
70
71 #[must_use]
73 #[inline]
74 pub const fn is_ecall_instruction(&self) -> bool {
75 matches!(self.opcode, Opcode::ECALL)
76 }
77
78 #[must_use]
80 #[inline]
81 pub const fn is_memory_load_instruction(&self) -> bool {
82 matches!(self.opcode, Opcode::LB | Opcode::LH | Opcode::LW | Opcode::LBU | Opcode::LHU)
83 }
84
85 #[must_use]
87 #[inline]
88 pub const fn is_memory_store_instruction(&self) -> bool {
89 matches!(self.opcode, Opcode::SB | Opcode::SH | Opcode::SW)
90 }
91
92 #[must_use]
94 #[inline]
95 pub const fn is_branch_instruction(&self) -> bool {
96 matches!(
97 self.opcode,
98 Opcode::BEQ | Opcode::BNE | Opcode::BLT | Opcode::BGE | Opcode::BLTU | Opcode::BGEU
99 )
100 }
101
102 #[must_use]
104 #[inline]
105 pub const fn is_jump_instruction(&self) -> bool {
106 matches!(self.opcode, Opcode::JAL | Opcode::JALR)
107 }
108
109 #[must_use]
111 #[inline]
112 pub const fn is_auipc_instruction(&self) -> bool {
113 matches!(self.opcode, Opcode::AUIPC)
114 }
115
116 #[must_use]
118 #[inline]
119 pub const fn is_divrem_instruction(&self) -> bool {
120 matches!(self.opcode, Opcode::DIV | Opcode::DIVU | Opcode::REM | Opcode::REMU)
121 }
122
123 #[must_use]
125 #[inline]
126 pub const fn is_ebreak_instruction(&self) -> bool {
127 matches!(self.opcode, Opcode::EBREAK)
128 }
129
130 #[must_use]
132 #[inline]
133 pub const fn is_unimp_instruction(&self) -> bool {
134 matches!(self.opcode, Opcode::UNIMP)
135 }
136}
137
138impl Debug for Instruction {
139 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140 let mnemonic = self.opcode.mnemonic();
141 let op_a_formatted = format!("%x{}", self.op_a);
142 let op_b_formatted = if self.imm_b || self.opcode == Opcode::AUIPC {
143 format!("{}", self.op_b as i32)
144 } else {
145 format!("%x{}", self.op_b)
146 };
147 let op_c_formatted =
148 if self.imm_c { format!("{}", self.op_c as i32) } else { format!("%x{}", self.op_c) };
149
150 let width = 10;
151 write!(
152 f,
153 "{mnemonic:<width$} {op_a_formatted:<width$} {op_b_formatted:<width$} {op_c_formatted:<width$}"
154 )
155 }
156}