1use crate::priv_prelude::*;
2
3macro_rules! define_op_code (
4 ($ty_name:ident, $s:literal) => (
5 #[derive(Clone, Debug, Serialize)]
6 pub struct $ty_name {
7 span: Span,
8 }
9
10 impl Spanned for $ty_name {
11 fn span(&self) -> Span {
12 self.span.clone()
13 }
14 }
15 );
16);
17
18macro_rules! op_code_ty (
19 (reg) => { Ident };
20 (imm) => { AsmImmediate };
21);
22
23macro_rules! push_register_arg_idents (
24 ($vec_name:ident, ()) => {};
25 ($vec_name:ident, ($arg_name_head:ident: reg, $($arg_name:ident: $arg_ty:tt,)*)) => {
26 $vec_name.push($arg_name_head.clone());
27 push_register_arg_idents!($vec_name, ($($arg_name: $arg_ty,)*))
28 };
29 ($vec_name:ident, ($arg_name_head:ident: imm, $($arg_name:ident: $arg_ty:tt,)*)) => {
30 let _ = $arg_name_head;
31 push_register_arg_idents!($vec_name, ($($arg_name: $arg_ty,)*))
32 };
33);
34
35macro_rules! push_immediate_idents (
36 ($vec_name:ident, ()) => {};
37 ($vec_name:ident, ($arg_name_head:ident: reg, $($arg_name:ident: $arg_ty:tt,)*)) => {
38 let _ = $arg_name_head;
39 push_immediate_idents!($vec_name, ($($arg_name: $arg_ty,)*))
40 };
41 ($vec_name:ident, ($arg_name_head:ident: imm, $($arg_name:ident: $arg_ty:tt,)*)) => {
42 $vec_name.push(Ident::new($arg_name_head.span()));
43 push_immediate_idents!($vec_name, ($($arg_name: $arg_ty,)*))
44 };
45);
46
47macro_rules! ignore_remaining (
48 () => {};
49 ($arg_name_head:ident: $arg_ty_head:tt, $($arg_name:ident: $arg_ty:tt,)*) => {{
50 let _ = $arg_name_head;
51 ignore_remaining!($($arg_name: $arg_ty,)*);
52 }};
53);
54
55macro_rules! immediate_ident_opt (
56 () => {
57 None
58 };
59 ($arg_name_head:ident: reg, $($arg_name:ident: $arg_ty:tt,)*) => {{
60 let _ = $arg_name_head;
61 immediate_ident_opt!($($arg_name: $arg_ty,)*)
62 }};
63 ($arg_name_head:ident: imm, $($arg_name:ident: $arg_ty:tt,)*) => {{
64 ignore_remaining!($($arg_name: $arg_ty,)*);
65 Some(Ident::new($arg_name_head.span()))
66 }};
67);
68
69macro_rules! get_span (
70 ($start:expr, ()) => { $start };
71 ($start:expr, ($arg_name:ident,)) => {
72 Span::join($start, &$arg_name.span())
73 };
74 ($start:expr, ($arg_name_head:ident, $($arg_name:ident,)*)) => {{
75 let _ = $arg_name_head;
76 get_span!($start, ($($arg_name,)*))
77 }};
78);
79
80pub trait Inst {
82 const LIT: &'static str;
84
85 type Args;
87
88 fn instruction(ident: Ident, args: Self::Args) -> Instruction;
89}
90
91macro_rules! define_op_codes (
92 ($(($op_name:ident, $ty_name:ident, $s:literal, ($($arg_name:ident: $arg_ty:tt),*)),)*) => {
93 $(
94 define_op_code!($ty_name, $s);
95
96 impl Inst for $ty_name {
97 const LIT: &'static str = $s;
98 type Args = ($(op_code_ty!($arg_ty),)*);
99
100 fn instruction(ident: Ident, ($($arg_name,)*): Self::Args) -> Instruction {
101 Instruction::$op_name {
102 token: $ty_name { span: ident.span().clone() },
103 $($arg_name,)*
104 }
105 }
106 }
107 )*
108
109 #[derive(Clone, Debug, Serialize)]
110 pub enum Instruction {
111 $($op_name {
112 token: $ty_name,
113 $($arg_name: op_code_ty!($arg_ty),)*
114 },)*
115 }
116
117 impl Instruction {
118 pub fn op_code_ident(&self) -> Ident {
119 match self {
120 $(Instruction::$op_name { token, .. } => {
121 Ident::new(token.span())
122 },)*
123 }
124 }
125
126 pub fn op_code_as_str(&self) -> &'static str {
127 match self {
128 $(Instruction::$op_name { .. } => {
129 $s
130 },)*
131 }
132 }
133
134 #[allow(clippy::vec_init_then_push)]
135 pub fn register_arg_idents(&self) -> Vec<Ident> {
136 match self {
137 $(Instruction::$op_name { $($arg_name,)* .. } => {
138 #[allow(unused_mut)]
139 let mut ret = Vec::new();
140 push_register_arg_idents!(ret, ($($arg_name: $arg_ty,)*));
141 ret
142 },)*
143 }
144 }
145
146 pub fn immediate_ident_opt(&self) -> Option<Ident> {
147 match self {
148 $(Instruction::$op_name { $($arg_name,)* .. } => {
149 immediate_ident_opt!($($arg_name: $arg_ty,)*)
150 },)*
151 }
152 }
153
154 #[allow(clippy::vec_init_then_push)]
155 pub fn immediate_idents(&self) -> Vec<Ident> {
156 match self {
157 $(Instruction::$op_name { $($arg_name,)* .. } => {
158 #[allow(unused_mut)]
159 let mut ret = Vec::new();
160 push_immediate_idents!(ret, ($($arg_name: $arg_ty,)*));
161 ret
162 },)*
163 }
164 }
165
166 }
167
168 impl Spanned for Instruction {
169 fn span(&self) -> Span {
170 match self {
171 $(Instruction::$op_name { token, $($arg_name,)* } => {
172 get_span!(token.span(), ($($arg_name,)*))
173 },)*
174 }
175 }
176 }
177 };
178);
179
180define_op_codes!(
181 (Add, AddOpcode, "add", (ret: reg, lhs: reg, rhs: reg)),
183 (Addi, AddiOpcode, "addi", (ret: reg, lhs: reg, rhs: imm)),
184 (And, AndOpcode, "and", (ret: reg, lhs: reg, rhs: reg)),
185 (Andi, AndiOpcode, "andi", (ret: reg, lhs: reg, rhs: imm)),
186 (Div, DivOpcode, "div", (ret: reg, lhs: reg, rhs: reg)),
187 (Divi, DiviOpcode, "divi", (ret: reg, lhs: reg, rhs: imm)),
188 (Eq, EqOpcode, "eq", (ret: reg, lhs: reg, rhs: reg)),
189 (Exp, ExpOpcode, "exp", (ret: reg, base: reg, power: reg)),
190 (Expi, ExpiOpcode, "expi", (ret: reg, base: reg, power: imm)),
191 (Gt, GtOpcode, "gt", (ret: reg, lhs: reg, rhs: reg)),
192 (Lt, LtOpcode, "lt", (ret: reg, lhs: reg, rhs: reg)),
193 (Mlog, MlogOpcode, "mlog", (ret: reg, arg: reg, base: reg)),
194 (Mod, ModOpcode, "mod", (ret: reg, lhs: reg, rhs: reg)),
195 (Modi, ModiOpcode, "modi", (ret: reg, lhs: reg, rhs: imm)),
196 (Move, MoveOpcode, "move", (ret: reg, from: reg)),
197 (Movi, MoviOpcode, "movi", (ret: reg, arg: imm)),
198 (Mroo, MrooOpcode, "mroo", (ret: reg, arg: reg, root: reg)),
199 (Mul, MulOpcode, "mul", (ret: reg, lhs: reg, rhs: reg)),
200 (Muli, MuliOpcode, "muli", (ret: reg, lhs: reg, rhs: imm)),
201 (Noop, NoopOpcode, "noop", ()),
202 (Not, NotOpcode, "not", (ret: reg, arg: reg)),
203 (Or, OrOpcode, "or", (ret: reg, lhs: reg, rhs: reg)),
204 (Ori, OriOpcode, "ori", (ret: reg, lhs: reg, rhs: imm)),
205 (Sll, SllOpcode, "sll", (ret: reg, lhs: reg, rhs: reg)),
206 (Slli, SlliOpcode, "slli", (ret: reg, lhs: reg, rhs: imm)),
207 (Srl, SrlOpcode, "srl", (ret: reg, lhs: reg, rhs: reg)),
208 (Srli, SrliOpcode, "srli", (ret: reg, lhs: reg, rhs: imm)),
209 (Sub, SubOpcode, "sub", (ret: reg, lhs: reg, rhs: reg)),
210 (Subi, SubiOpcode, "subi", (ret: reg, lhs: reg, rhs: imm)),
211 (Wqcm, WqcmOpcode, "wqcm", (ret: reg, lhs: reg, rhs: reg, op_mode: imm)),
212 (Wqop, WqopOpcode, "wqop", (ret: reg, lhs: reg, rhs: reg, op_mode: imm)),
213 (Wqml, WqmlOpcode, "wqml", (ret: reg, lhs: reg, rhs: reg, indirect: imm)),
214 (Wqdv, WqdvOpcode, "wqdv", (ret: reg, lhs: reg, rhs: reg, indirect: imm)),
215 (Wqmd, WqmdOpcode, "wqmd", (ret: reg, lhs_a: reg, lhs_b: reg, rhs: reg)),
216 (Wqam, WqamOpcode, "wqam", (ret: reg, lhs_a: reg, lhs_b: reg, rhs: reg)),
217 (Wqmm, WqmmOpcode, "wqmm", (ret: reg, lhs_a: reg, lhs_b: reg, rhs: reg)),
218 (Xor, XorOpcode, "xor", (ret: reg, lhs: reg, rhs: reg)),
219 (Xori, XoriOpcode, "xori", (ret: reg, lhs: reg, rhs: imm)),
220 (Jmp, JmpOpcode, "jmp", (offset: reg)),
222 (Ji, JiOpcode, "ji", (offset: imm)),
223 (Jne, JneOpcode, "jne", (lhs: reg, rhs: reg, offset: reg)),
224 (Jnei, JneiOpcode, "jnei", (lhs: reg, rhs: reg, offset: imm)),
225 (Jnzi, JnziOpcode, "jnzi", (arg: reg, offset: imm)),
226 (Jmpb, JmpbOpcode, "jmpb", (offset_reg: reg, offset: imm)),
227 (Jmpf, JmpfOpcode, "jmpf", (offset_reg: reg, offset: imm)),
228 (Jnzb, JnzbOpcode, "jnzb", (arg: reg, offset_reg: reg, offset: imm)),
229 (Jnzf, JnzfOpcode, "jnzf", (arg: reg, offset_reg: reg, offset: imm)),
230 (Jneb, JnebOpcode, "jneb", (lhs: reg, rhs: reg, offset_reg: reg, offset: imm)),
231 (Jnef, JnefOpcode, "jnef", (lhs: reg, rhs: reg, offset_reg: reg, offset: imm)),
232 (Jal, JalOpcode, "jal", (addr: reg, offset_reg: reg, offset: imm)),
233 (Ret, RetOpcode, "ret", (value: reg)),
234 (Aloc, AlocOpcode, "aloc", (size: reg)),
236 (Cfei, CfeiOpcode, "cfei", (size: imm)),
237 (Cfsi, CfsiOpcode, "cfsi", (size: imm)),
238 (Cfe, CfeOpcode, "cfe", (size: reg)),
239 (Cfs, CfsOpcode, "cfs", (size: reg)),
240 (Lb, LbOpcode, "lb", (ret: reg, addr: reg, offset: imm)),
241 (Lw, LwOpcode, "lw", (ret: reg, addr: reg, offset: imm)),
242 (Mcl, MclOpcode, "mcl", (addr: reg, size: reg)),
243 (Mcli, McliOpcode, "mcli", (addr: reg, size: imm)),
244 (
245 Mcp,
246 McpOpcode,
247 "mcp",
248 (dst_addr: reg, src_addr: reg, size: reg)
249 ),
250 (
251 Mcpi,
252 McpiOpcode,
253 "mcpi",
254 (dst_addr: reg, src_addr: reg, size: imm)
255 ),
256 (
257 Meq,
258 MeqOpcode,
259 "meq",
260 (ret: reg, lhs_addr: reg, rhs_addr: reg, size: reg)
261 ),
262 (Sb, SbOpcode, "sb", (addr: reg, value: reg, offset: imm)),
263 (Sw, SwOpcode, "sw", (addr: reg, value: reg, offset: imm)),
264 (Bal, BalOpcode, "bal", (ret: reg, asset: reg, contract: reg)),
266 (Bhei, BheiOpcode, "bhei", (ret: reg)),
267 (Bhsh, BhshOpcode, "bhsh", (addr: reg, height: reg)),
268 (Burn, BurnOpcode, "burn", (coins: reg, sub_id: reg)),
269 (
270 Call,
271 CallOpcode,
272 "call",
273 (args_addr: reg, coins: reg, asset: reg, gas: reg)
274 ),
275 (Cb, CbOpcode, "cb", (addr: reg)),
276 (
277 Ccp,
278 CcpOpcode,
279 "ccp",
280 (dst_addr: reg, contract: reg, src_addr: reg, size: reg)
281 ),
282 (Croo, CrooOpcode, "croo", (addr: reg, contract: reg)),
283 (Csiz, CsizOpcode, "csiz", (ret: reg, contract: reg)),
284 (Bsiz, BsizOpcode, "bsiz", (ret: reg, contract: reg)),
285 (Ldc, LdcOpcode, "ldc", (contract: reg, addr: reg, size: reg, mode: imm)),
286 (Bldd, BlddOpcode, "bldd", (dst_ptr: reg, addr: reg, offset: reg, len: reg)),
287 (
288 Log,
289 LogOpcode,
290 "log",
291 (reg_a: reg, reg_b: reg, reg_c: reg, reg_d: reg)
292 ),
293 (
294 Logd,
295 LogdOpcode,
296 "logd",
297 (reg_a: reg, reg_b: reg, addr: reg, size: reg)
298 ),
299 (Mint, MintOpcode, "mint", (coins: reg, sub_id: reg)),
300 (Retd, RetdOpcode, "retd", (addr: reg, size: reg)),
301 (Rvrt, RvrtOpcode, "rvrt", (value: reg)),
302 (
303 Smo,
304 SmoOpcode,
305 "smo",
306 (addr: reg, len: reg, output: reg, coins: reg)
307 ),
308 (Scwq, ScwqOpcode, "scwq", (addr: reg, is_set: reg, len: reg)),
309 (
310 Srw,
311 SrwOpcode,
312 "srw",
313 (ret: reg, is_set: reg, state_addr: reg)
314 ),
315 (
316 Srwq,
317 SrwqOpcode,
318 "srwq",
319 (addr: reg, is_set: reg, state_addr: reg, count: reg)
320 ),
321 (
322 Sww,
323 SwwOpcode,
324 "sww",
325 (state_addr: reg, is_set: reg, value: reg)
326 ),
327 (
328 Swwq,
329 SwwqOpcode,
330 "swwq",
331 (state_addr: reg, is_set: reg, addr: reg, count: reg)
332 ),
333 (Time, TimeOpcode, "time", (ret: reg, height: reg)),
334 (Tr, TrOpcode, "tr", (contract: reg, coins: reg, asset: reg)),
335 (
336 Tro,
337 TroOpcode,
338 "tro",
339 (addr: reg, output: reg, coins: reg, asset: reg)
340 ),
341 (Eck1, Eck1Opcode, "eck1", (addr: reg, sig: reg, hash: reg)),
343 (Ecr1, Ecr1Opcode, "ecr1", (addr: reg, sig: reg, hash: reg)),
344 (Ed19, Ed19Opcode, "ed19", (addr: reg, sig: reg, hash: reg, len: reg)),
345 (K256, K256Opcode, "k256", (addr: reg, data: reg, size: reg)),
346 (S256, S256Opcode, "s256", (addr: reg, data: reg, size: reg)),
347 (ECOP, ECOPOpcode, "ecop", (dst_addr: reg, curve: reg, operation: reg, src_addr: reg)),
348 (EPAR, EPAROpcode, "epar", (ret: reg, curve: reg, groups_of_points: reg, addr: reg)),
349 (Ecal, EcalOpcode, "ecal", (reg_a: reg, reg_b: reg, reg_c: reg, reg_d: reg)),
351 (Flag, FlagOpcode, "flag", (value: reg)),
352 (Gm, GmOpcode, "gm", (ret: reg, op: imm)),
353 (
354 Gtf,
355 GtfOpcode,
356 "gtf",
357 (ret: reg, index: reg, tx_field_id: imm)
358 ),
359 (Blob, BlobOpcode, "blob", (size: imm)),
361);