1pub type Instruction = u64;
43
44pub type InstructionOpcode = u16;
45
46pub use paste::paste;
47
48#[doc(hidden)]
49#[macro_export]
50macro_rules! __apply {
51 ((0, $callback:ident), $(($name:ident, $code:expr)),*) => {
52 $crate::instructions::paste! {
53 $(
54 $callback!([< OP_ $name >], $name, $code);
55 )*
56 }
57 };
58 ((1, $x:ident, $callback:ident), $(($name:ident, $code:expr)),*) => {
59 $crate::instructions::paste! {
60 $(
61 $callback!([< OP_ $name >], $name, $code, $x);
62 )*
63 }
64 };
65 ((2, $x:ident, $y:ident, $callback:ident), $(($name:ident, $code:expr)),*) => {
66 $crate::instructions::paste! {
67 $(
68 $callback!([< OP_ $name >], $name, $code, $x, $y);
69 )*
70 }
71 };
72 ((100, $res:ident, $val:expr, $callback:ident, $others:expr), $(($name:ident, $code:expr)),*) => {
73 $crate::instructions::paste! {
74 let $res = match $val {
75 $( $code => $callback!([< OP_ $name >], $name, $code), )*
76 _ => $others
77 };
78 }
79 };
80 ((101, $x:ident, $res:ident, $val:expr, $callback:ident, $others:expr), $(($name:ident, $code:expr)),*) => {
81 $crate::instructions::paste! {
82 let $res = match $val {
83 $( $code => $callback!([< OP_ $name >], $name, $code, $x), )*
84 _ => $others
85 };
86 }
87 };
88 ((102, $x:ident, $y:ident, $res:ident, $val:expr, $callback:ident, $others:expr), $(($name:ident, $code:expr)),*) => {
89 $crate::instructions::paste! {
90 let $res = match $val {
91 $( $code => $callback!([< OP_ $name >], $name, $code, $x, $y), )*
92 _ => $others
93 };
94 }
95 };
96 ((200, $res:ident, $callback:ident), $(($name:ident, $code:expr)),*) => {
97 $crate::instructions::paste! {
98 let $res = [
99 $( $callback!([< OP_ $name >], $name, $code), )*
100 ];
101 }
102 };
103 ((201, $x:ident, $res:ident, $callback:ident), $(($name:ident, $code:expr)),*) => {
104 $crate::instructions::paste! {
105 let $res = [
106 $( $callback!([< OP_ $name >], $name, $code, $x), )*
107 ];
108 }
109 };
110 ((202, $x:ident, $y:ident, $res:ident, $callback:ident), $(($name:ident, $code:expr)),*) => {
111 $crate::instructions::paste! {
112 let $res = [
113 $( $callback!([< OP_ $name >], $name, $code, $x, $y), )*
114 ];
115 }
116 };
117}
118
119#[doc(hidden)]
120#[macro_export]
121macro_rules! __for_each_inst_inner {
122 ($callback:tt) => {
123 $crate::__apply!(
124 $callback,
125 (UNLOADED, 0x10),
127 (ADD, 0x11),
128 (ADDI, 0x12),
129 (ADDIW, 0x13),
130 (ADDW, 0x14),
131 (AND, 0x15),
132 (ANDI, 0x16),
133 (DIV, 0x17),
134 (DIVU, 0x18),
135 (DIVUW, 0x19),
136 (DIVW, 0x1a),
137 (LB_VERSION0, 0x1b),
138 (LB_VERSION1, 0x1c),
139 (LBU_VERSION0, 0x1d),
140 (LBU_VERSION1, 0x1e),
141 (LD_VERSION0, 0x1f),
142 (LD_VERSION1, 0x20),
143 (LH_VERSION0, 0x21),
144 (LH_VERSION1, 0x22),
145 (LHU_VERSION0, 0x23),
146 (LHU_VERSION1, 0x24),
147 (LUI, 0x25),
148 (LW_VERSION0, 0x26),
149 (LW_VERSION1, 0x27),
150 (LWU_VERSION0, 0x28),
151 (LWU_VERSION1, 0x29),
152 (MUL, 0x2a),
153 (MULH, 0x2b),
154 (MULHSU, 0x2c),
155 (MULHU, 0x2d),
156 (MULW, 0x2e),
157 (OR, 0x2f),
158 (ORI, 0x30),
159 (REM, 0x31),
160 (REMU, 0x32),
161 (REMUW, 0x33),
162 (REMW, 0x34),
163 (SB, 0x35),
164 (SD, 0x36),
165 (SH, 0x37),
166 (SLL, 0x38),
167 (SLLI, 0x39),
168 (SLLIW, 0x3a),
169 (SLLW, 0x3b),
170 (SLT, 0x3c),
171 (SLTI, 0x3d),
172 (SLTIU, 0x3e),
173 (SLTU, 0x3f),
174 (SRA, 0x40),
175 (SRAI, 0x41),
176 (SRAIW, 0x42),
177 (SRAW, 0x43),
178 (SRL, 0x44),
179 (SRLI, 0x45),
180 (SRLIW, 0x46),
181 (SRLW, 0x47),
182 (SUB, 0x48),
183 (SUBW, 0x49),
184 (SW, 0x4a),
185 (XOR, 0x4b),
186 (XORI, 0x4c),
187 (LR_W, 0x4d),
189 (SC_W, 0x4e),
190 (AMOSWAP_W, 0x4f),
191 (AMOADD_W, 0x50),
192 (AMOXOR_W, 0x51),
193 (AMOAND_W, 0x52),
194 (AMOOR_W, 0x53),
195 (AMOMIN_W, 0x54),
196 (AMOMAX_W, 0x55),
197 (AMOMINU_W, 0x56),
198 (AMOMAXU_W, 0x57),
199 (LR_D, 0x58),
200 (SC_D, 0x59),
201 (AMOSWAP_D, 0x5a),
202 (AMOADD_D, 0x5b),
203 (AMOXOR_D, 0x5c),
204 (AMOAND_D, 0x5d),
205 (AMOOR_D, 0x5e),
206 (AMOMIN_D, 0x5f),
207 (AMOMAX_D, 0x60),
208 (AMOMINU_D, 0x61),
209 (AMOMAXU_D, 0x62),
210 (ADDUW, 0x63),
212 (ANDN, 0x64),
213 (BCLR, 0x65),
214 (BCLRI, 0x66),
215 (BEXT, 0x67),
216 (BEXTI, 0x68),
217 (BINV, 0x69),
218 (BINVI, 0x6a),
219 (BSET, 0x6b),
220 (BSETI, 0x6c),
221 (CLMUL, 0x6d),
222 (CLMULH, 0x6e),
223 (CLMULR, 0x6f),
224 (CLZ, 0x70),
225 (CLZW, 0x71),
226 (CPOP, 0x72),
227 (CPOPW, 0x73),
228 (CTZ, 0x74),
229 (CTZW, 0x75),
230 (MAX, 0x76),
231 (MAXU, 0x77),
232 (MIN, 0x78),
233 (MINU, 0x79),
234 (ORCB, 0x7a),
235 (ORN, 0x7b),
236 (REV8, 0x7c),
237 (ROL, 0x7d),
238 (ROLW, 0x7e),
239 (ROR, 0x7f),
240 (RORI, 0x80),
241 (RORIW, 0x81),
242 (RORW, 0x82),
243 (SEXTB, 0x83),
244 (SEXTH, 0x84),
245 (SH1ADD, 0x85),
246 (SH1ADDUW, 0x86),
247 (SH2ADD, 0x87),
248 (SH2ADDUW, 0x88),
249 (SH3ADD, 0x89),
250 (SH3ADDUW, 0x8a),
251 (SLLIUW, 0x8b),
252 (XNOR, 0x8c),
253 (ZEXTH, 0x8d),
254 (WIDE_MUL, 0x8e),
256 (WIDE_MULU, 0x8f),
257 (WIDE_MULSU, 0x90),
258 (WIDE_DIV, 0x91),
259 (WIDE_DIVU, 0x92),
260 (ADC, 0x93),
261 (SBB, 0x94),
262 (ADCS, 0x95),
263 (SBBS, 0x96),
264 (ADD3A, 0x97),
265 (ADD3B, 0x98),
266 (ADD3C, 0x99),
267 (CUSTOM_LOAD_UIMM, 0x9a),
268 (CUSTOM_LOAD_IMM, 0x9b),
269 (AUIPC, 0x9c),
271 (BEQ, 0x9d),
272 (BGE, 0x9e),
273 (BGEU, 0x9f),
274 (BLT, 0xa0),
275 (BLTU, 0xa1),
276 (BNE, 0xa2),
277 (EBREAK, 0xa3),
278 (ECALL, 0xa4),
279 (FENCE, 0xa5),
280 (FENCEI, 0xa6),
281 (JAL, 0xa7),
282 (JALR_VERSION0, 0xa8),
283 (JALR_VERSION1, 0xa9),
284 (FAR_JUMP_REL, 0xaa),
285 (FAR_JUMP_ABS, 0xab),
286 (CUSTOM_TRACE_END, 0xac)
287 );
288 };
289}
290
291#[macro_export]
302macro_rules! for_each_inst {
303 ($callback:ident) => {
304 $crate::__for_each_inst_inner!((0, $callback));
305 };
306}
307
308#[macro_export]
309macro_rules! for_each_inst1 {
310 ($callback:ident, $x:ident) => {
311 $crate::__for_each_inst_inner!((1, $x, $callback));
312 };
313}
314
315#[macro_export]
316macro_rules! for_each_inst2 {
317 ($callback:ident, $x:ident, $y:ident) => {
318 $crate::__for_each_inst_inner!((2, $x, $y, $callback));
319 };
320}
321
322#[macro_export]
333macro_rules! for_each_inst_match {
334 ($callback:ident, $val:expr, $others:expr) => {{
335 $crate::__for_each_inst_inner!((100, __res__, $val, $callback, $others));
336 __res__
337 }};
338}
339
340#[macro_export]
341macro_rules! for_each_inst_match1 {
342 ($callback:ident, $val:expr, $others:expr, $x:ident) => {{
343 $crate::__for_each_inst_inner!((101, $x, __res__, $val, $callback, $others));
344 __res__
345 }};
346}
347
348#[macro_export]
349macro_rules! for_each_inst_match2 {
350 ($callback:ident, $val:expr, $others:expr, $x:ident, $y:ident) => {{
351 $crate::__for_each_inst_inner!((102, $x, $y, __res__, $val, $callback, $others));
352 __res__
353 }};
354}
355
356#[macro_export]
363macro_rules! for_each_inst_array {
364 ($callback:ident) => {{
365 $crate::__for_each_inst_inner!((200, __res__, $callback));
366 __res__
367 }};
368}
369
370#[macro_export]
371macro_rules! for_each_inst_array1 {
372 ($callback:ident, $x:ident) => {{
373 $crate::__for_each_inst_inner!((201, $x, __res__, $callback));
374 __res__
375 }};
376}
377
378#[macro_export]
379macro_rules! for_each_inst_array2 {
380 ($callback:ident, $x:ident, $y:ident) => {{
381 $crate::__for_each_inst_inner!((202, $x, $y, __res__, $callback));
382 __res__
383 }};
384}
385
386macro_rules! define_instruction {
388 ($name:ident, $real_name:ident, $code:expr) => {
389 pub const $name: InstructionOpcode = $code;
390 };
391}
392for_each_inst!(define_instruction);
393
394pub const MINIMAL_OPCODE: InstructionOpcode = OP_UNLOADED;
395pub const MAXIMUM_OPCODE: InstructionOpcode = OP_CUSTOM_TRACE_END;
396
397pub const MINIMAL_BASIC_BLOCK_END_OPCODE: InstructionOpcode = OP_AUIPC;
398pub const MAXIMUM_BASIC_BLOCK_END_OPCODE: InstructionOpcode = OP_FAR_JUMP_ABS;
399
400macro_rules! inst_real_name {
401 ($name:ident, $real_name:ident, $code:expr) => {
402 stringify!($real_name)
403 };
404}
405
406pub fn instruction_opcode_name(i: InstructionOpcode) -> &'static str {
407 for_each_inst_match!(inst_real_name, i, "UNKNOWN_INSTRUCTION!")
408}