1pub enum Opcode {
2 Nop = 0,
3 InitStack = 1,
4 Call = 2,
5 Syscall,
6 Ret,
7 RetV,
8 Jmp,
9 Jz,
10 PushNil,
11 PushTrue,
12 PushI32,
13 PushI16,
14 PushI8,
15 PushF32,
16 PushString,
17 PushGlobal,
18 PushStack,
19 PushGlobalTable,
20 PushLocalTable,
21 PushTop,
22 PushReturn,
23 PopGlobal,
24 PopStack,
25 PopGlobalTable,
26 PopLocalTable,
27 Neg,
28 Add,
29 Sub,
30 Mul,
31 Div,
32 Mod,
33 BitTest,
34 And,
35 Or,
36 SetE,
37 SetNE,
38 SetG,
39 SetLE,
40 SetL,
41 SetGE,
42}
43
44impl TryFrom<i32> for Opcode {
45 type Error = ();
46
47 fn try_from(v: i32) -> core::result::Result<Self, Self::Error> {
48 match v {
49 x if x == Opcode::Nop as i32 => Ok(Opcode::Nop),
50 x if x == Opcode::InitStack as i32 => Ok(Opcode::InitStack),
51 x if x == Opcode::Call as i32 => Ok(Opcode::Call),
52 x if x == Opcode::Syscall as i32 => Ok(Opcode::Syscall),
53 x if x == Opcode::Ret as i32 => Ok(Opcode::Ret),
54 x if x == Opcode::RetV as i32 => Ok(Opcode::RetV),
55 x if x == Opcode::Jmp as i32 => Ok(Opcode::Jmp),
56 x if x == Opcode::Jz as i32 => Ok(Opcode::Jz),
57 x if x == Opcode::PushNil as i32 => Ok(Opcode::PushNil),
58 x if x == Opcode::PushTrue as i32 => Ok(Opcode::PushTrue),
59 x if x == Opcode::PushI32 as i32 => Ok(Opcode::PushI32),
60 x if x == Opcode::PushI16 as i32 => Ok(Opcode::PushI16),
61 x if x == Opcode::PushI8 as i32 => Ok(Opcode::PushI8),
62 x if x == Opcode::PushF32 as i32 => Ok(Opcode::PushF32),
63 x if x == Opcode::PushString as i32 => Ok(Opcode::PushString),
64 x if x == Opcode::PushGlobal as i32 => Ok(Opcode::PushGlobal),
65 x if x == Opcode::PushStack as i32 => Ok(Opcode::PushStack),
66 x if x == Opcode::PushGlobalTable as i32 => Ok(Opcode::PushGlobalTable),
67 x if x == Opcode::PushLocalTable as i32 => Ok(Opcode::PushLocalTable),
68 x if x == Opcode::PushTop as i32 => Ok(Opcode::PushTop),
69 x if x == Opcode::PushReturn as i32 => Ok(Opcode::PushReturn),
70 x if x == Opcode::PopGlobal as i32 => Ok(Opcode::PopGlobal),
71 x if x == Opcode::PopStack as i32 => Ok(Opcode::PopStack),
72 x if x == Opcode::PopGlobalTable as i32 => Ok(Opcode::PopGlobalTable),
73 x if x == Opcode::PopLocalTable as i32 => Ok(Opcode::PopLocalTable),
74 x if x == Opcode::Neg as i32 => Ok(Opcode::Neg),
75 x if x == Opcode::Add as i32 => Ok(Opcode::Add),
76 x if x == Opcode::Sub as i32 => Ok(Opcode::Sub),
77 x if x == Opcode::Mul as i32 => Ok(Opcode::Mul),
78 x if x == Opcode::Div as i32 => Ok(Opcode::Div),
79 x if x == Opcode::Mod as i32 => Ok(Opcode::Mod),
80 x if x == Opcode::BitTest as i32 => Ok(Opcode::BitTest),
81 x if x == Opcode::And as i32 => Ok(Opcode::And),
82 x if x == Opcode::Or as i32 => Ok(Opcode::Or),
83 x if x == Opcode::SetE as i32 => Ok(Opcode::SetE),
84 x if x == Opcode::SetNE as i32 => Ok(Opcode::SetNE),
85 x if x == Opcode::SetG as i32 => Ok(Opcode::SetG),
86 x if x == Opcode::SetLE as i32 => Ok(Opcode::SetLE),
87 x if x == Opcode::SetL as i32 => Ok(Opcode::SetL),
88 x if x == Opcode::SetGE as i32 => Ok(Opcode::SetGE),
89 _ => Err(()),
90 }
91 }
92}
93
94impl TryFrom<u8> for Opcode {
95 type Error = ();
96
97 fn try_from(v: u8) -> core::result::Result<Self, Self::Error> {
98 match v {
99 x if x == Opcode::Nop as u8 => Ok(Opcode::Nop),
100 x if x == Opcode::InitStack as u8 => Ok(Opcode::InitStack),
101 x if x == Opcode::Call as u8 => Ok(Opcode::Call),
102 x if x == Opcode::Syscall as u8 => Ok(Opcode::Syscall),
103 x if x == Opcode::Ret as u8 => Ok(Opcode::Ret),
104 x if x == Opcode::RetV as u8 => Ok(Opcode::RetV),
105 x if x == Opcode::Jmp as u8 => Ok(Opcode::Jmp),
106 x if x == Opcode::Jz as u8 => Ok(Opcode::Jz),
107 x if x == Opcode::PushNil as u8 => Ok(Opcode::PushNil),
108 x if x == Opcode::PushTrue as u8 => Ok(Opcode::PushTrue),
109 x if x == Opcode::PushI32 as u8 => Ok(Opcode::PushI32),
110 x if x == Opcode::PushI16 as u8 => Ok(Opcode::PushI16),
111 x if x == Opcode::PushI8 as u8 => Ok(Opcode::PushI8),
112 x if x == Opcode::PushF32 as u8 => Ok(Opcode::PushF32),
113 x if x == Opcode::PushString as u8 => Ok(Opcode::PushString),
114 x if x == Opcode::PushGlobal as u8 => Ok(Opcode::PushGlobal),
115 x if x == Opcode::PushStack as u8 => Ok(Opcode::PushStack),
116 x if x == Opcode::PushGlobalTable as u8 => Ok(Opcode::PushGlobalTable),
117 x if x == Opcode::PushLocalTable as u8 => Ok(Opcode::PushLocalTable),
118 x if x == Opcode::PushTop as u8 => Ok(Opcode::PushTop),
119 x if x == Opcode::PushReturn as u8 => Ok(Opcode::PushReturn),
120 x if x == Opcode::PopGlobal as u8 => Ok(Opcode::PopGlobal),
121 x if x == Opcode::PopStack as u8 => Ok(Opcode::PopStack),
122 x if x == Opcode::PopGlobalTable as u8 => Ok(Opcode::PopGlobalTable),
123 x if x == Opcode::PopLocalTable as u8 => Ok(Opcode::PopLocalTable),
124 x if x == Opcode::Neg as u8 => Ok(Opcode::Neg),
125 x if x == Opcode::Add as u8 => Ok(Opcode::Add),
126 x if x == Opcode::Sub as u8 => Ok(Opcode::Sub),
127 x if x == Opcode::Mul as u8 => Ok(Opcode::Mul),
128 x if x == Opcode::Div as u8 => Ok(Opcode::Div),
129 x if x == Opcode::Mod as u8 => Ok(Opcode::Mod),
130 x if x == Opcode::BitTest as u8 => Ok(Opcode::BitTest),
131 x if x == Opcode::And as u8 => Ok(Opcode::And),
132 x if x == Opcode::Or as u8 => Ok(Opcode::Or),
133 x if x == Opcode::SetE as u8 => Ok(Opcode::SetE),
134 x if x == Opcode::SetNE as u8 => Ok(Opcode::SetNE),
135 x if x == Opcode::SetG as u8 => Ok(Opcode::SetG),
136 x if x == Opcode::SetLE as u8 => Ok(Opcode::SetLE),
137 x if x == Opcode::SetL as u8 => Ok(Opcode::SetL),
138 x if x == Opcode::SetGE as u8 => Ok(Opcode::SetGE),
139 _ => Err(()),
140 }
141 }
142}
143
144impl TryFrom<&str> for Opcode {
145 type Error = ();
146
147 fn try_from(v: &str) -> core::result::Result<Self, Self::Error> {
148 match v {
149 x if x == "nop" => Ok(Opcode::Nop),
150 x if x == "init_stack" => Ok(Opcode::InitStack),
151 x if x == "call" => Ok(Opcode::Call),
152 x if x == "syscall" => Ok(Opcode::Syscall),
153 x if x == "ret" => Ok(Opcode::Ret),
154 x if x == "retv" => Ok(Opcode::RetV),
155 x if x == "jmp" => Ok(Opcode::Jmp),
156 x if x == "jz" => Ok(Opcode::Jz),
157 x if x == "push_nil" => Ok(Opcode::PushNil),
158 x if x == "push_true" => Ok(Opcode::PushTrue),
159 x if x == "push_i32" => Ok(Opcode::PushI32),
160 x if x == "push_i16" => Ok(Opcode::PushI16),
161 x if x == "push_i8" => Ok(Opcode::PushI8),
162 x if x == "push_f32" => Ok(Opcode::PushF32),
163 x if x == "push_string" => Ok(Opcode::PushString),
164 x if x == "push_global" => Ok(Opcode::PushGlobal),
165 x if x == "push_stack" => Ok(Opcode::PushStack),
166 x if x == "push_global_table" => Ok(Opcode::PushGlobalTable),
167 x if x == "push_local_table" => Ok(Opcode::PushLocalTable),
168 x if x == "push_top" => Ok(Opcode::PushTop),
169 x if x == "push_return" => Ok(Opcode::PushReturn),
170 x if x == "pop_global" => Ok(Opcode::PopGlobal),
171 x if x == "pop_stack" => Ok(Opcode::PopStack),
172 x if x == "pop_global_table" => Ok(Opcode::PopGlobalTable),
173 x if x == "pop_local_table" => Ok(Opcode::PopLocalTable),
174 x if x == "neg" => Ok(Opcode::Neg),
175 x if x == "add" => Ok(Opcode::Add),
176 x if x == "sub" => Ok(Opcode::Sub),
177 x if x == "mul" => Ok(Opcode::Mul),
178 x if x == "div" => Ok(Opcode::Div),
179 x if x == "mod" => Ok(Opcode::Mod),
180 x if x == "bit_test" => Ok(Opcode::BitTest),
181 x if x == "and" => Ok(Opcode::And),
182 x if x == "or" => Ok(Opcode::Or),
183 x if x == "set_e" => Ok(Opcode::SetE),
184 x if x == "set_ne" => Ok(Opcode::SetNE),
185 x if x == "set_g" => Ok(Opcode::SetG),
186 x if x == "set_le" => Ok(Opcode::SetLE),
187 x if x == "set_l" => Ok(Opcode::SetL),
188 x if x == "set_ge" => Ok(Opcode::SetGE),
189 _ => Err(()),
190 }
191 }
192}
193
194impl ToString for Opcode {
195 fn to_string(&self) -> String {
196 match self {
197 Opcode::Nop => "nop",
198 Opcode::InitStack => "init_stack",
199 Opcode::Call => "call",
200 Opcode::Syscall => "syscall",
201 Opcode::Ret => "ret",
202 Opcode::RetV => "retv",
203 Opcode::Jmp => "jmp",
204 Opcode::Jz => "jz",
205 Opcode::PushNil => "push_nil",
206 Opcode::PushTrue => "push_true",
207 Opcode::PushI32 => "push_i32",
208 Opcode::PushI16 => "push_i16",
209 Opcode::PushI8 => "push_i8",
210 Opcode::PushF32 => "push_f32",
211 Opcode::PushString => "push_string",
212 Opcode::PushGlobal => "push_global",
213 Opcode::PushStack => "push_stack",
214 Opcode::PushGlobalTable => "push_global_table",
215 Opcode::PushLocalTable => "push_local_table",
216 Opcode::PushTop => "push_top",
217 Opcode::PushReturn => "push_return",
218 Opcode::PopGlobal => "pop_global",
219 Opcode::PopStack => "pop_stack",
220 Opcode::PopGlobalTable => "pop_global_table",
221 Opcode::PopLocalTable => "pop_local_table",
222 Opcode::Neg => "neg",
223 Opcode::Add => "add",
224 Opcode::Sub => "sub",
225 Opcode::Mul => "mul",
226 Opcode::Div => "div",
227 Opcode::Mod => "mod",
228 Opcode::BitTest => "bit_test",
229 Opcode::And => "and",
230 Opcode::Or => "or",
231 Opcode::SetE => "set_e",
232 Opcode::SetNE => "set_ne",
233 Opcode::SetG => "set_g",
234 Opcode::SetLE => "set_le",
235 Opcode::SetL => "set_l",
236 Opcode::SetGE => "set_ge",
237 }
238 .to_string()
239 }
240}
241
242pub trait OpcodeBase {
243 fn opcode(&self) -> Opcode;
244 fn address(&self) -> u32;
245 fn mnemonic(&self) -> &'static str;
246 fn disassemble(&self) -> String;
247}