1#[derive(Debug, Copy, Clone)]
19pub enum OpMode {
20 IA,
21 IAB,
22 IABC,
23 IABx,
24 IAsBx,
25 IAx,
26 IAC,
27}
28
29pub const SIZE_OP: u32 = 6;
30pub const SIZE_A: u32 = 8;
31pub const SIZE_B: u32 = 9;
32pub const SIZE_C: u32 = 9;
33pub const SIZE_AX: u32 = SIZE_C + SIZE_B + SIZE_A;
34pub const SIZE_BX: u32 = SIZE_C + SIZE_B;
35
36pub const POS_OP: u32 = 0;
37pub const POS_A: u32 = POS_OP + SIZE_OP;
38pub const POS_C: u32 = POS_A + SIZE_A;
39pub const POS_B: u32 = POS_C + SIZE_C;
40pub const POS_BX: u32 = POS_C;
41pub const POS_AX: u32 = POS_A;
42
43pub const MAXARG_A: u32 = (1 << SIZE_A) - 1;
44pub const MAXARG_B: u32 = (1 << SIZE_B) - 1;
45pub const MAXARG_C: u32 = (1 << SIZE_C) - 1;
46pub const MAXARG_AX: u32 = (1 << SIZE_AX) - 1;
47pub const MAXARG_BX: u32 = (1 << SIZE_BX) - 1;
48pub const MAXARG_SBX: i32 = (MAXARG_BX as i32) >> 1;
49
50pub const MASK_K: u32 = 1 << (SIZE_B - 1);
51
52pub const NO_JUMP: i32 = -1;
53pub const NO_REG: u32 = MAXARG_A;
54
55pub fn is_const(index: u32) -> bool {
56 index & MASK_K != 0
57}
58
59pub fn is_var(index: u32) -> bool {
60 !is_const(index)
61}
62
63#[derive(Debug, Clone, Copy, PartialEq)]
64pub enum OpCode {
65 Move = 0,
68 LoadK,
71 LoadKx,
74 LoadBool,
78 LoadNil,
81 GetUpVal,
84
85 GetTabUp,
88 GetTable,
91
92 SetTabUp,
95 SetUpVal,
98 SetTable,
101
102 NewTable,
105
106 Self_,
110
111 Add,
114 Sub,
117 Mul,
120 Mod,
123 Pow,
126 Div,
129 IDiv,
132 BAdd,
135 BOr,
138 BXor,
141 Shl,
144 Shr,
147
148 Unm,
151 BNot,
154 Not,
157 Len,
160
161 Concat,
164
165 Jmp,
169
170 Eq,
173 Lt,
176 Le,
179
180 Test,
183 TestSet,
186
187 Call,
190
191 TailCall,
194
195 Return,
198
199 ForLoop,
203 ForPrep,
207
208 TForCall,
211 TForLoop,
214
215 SetList,
218
219 Closure,
222
223 Vararg,
226
227 ExtraArg,
230}
231
232impl OpCode {
233 pub fn from_u32(u: u32) -> OpCode {
234 match u {
235 _ if OpCode::Move as u32 == u => OpCode::Move,
236 _ if OpCode::LoadK as u32 == u => OpCode::LoadK,
237 _ if OpCode::LoadKx as u32 == u => OpCode::LoadKx,
238 _ if OpCode::LoadBool as u32 == u => OpCode::LoadBool,
239 _ if OpCode::LoadNil as u32 == u => OpCode::LoadNil,
240 _ if OpCode::GetUpVal as u32 == u => OpCode::GetUpVal,
241 _ if OpCode::GetTabUp as u32 == u => OpCode::GetTabUp,
242 _ if OpCode::GetTable as u32 == u => OpCode::GetTable,
243 _ if OpCode::SetTabUp as u32 == u => OpCode::SetTabUp,
244 _ if OpCode::SetUpVal as u32 == u => OpCode::SetUpVal,
245 _ if OpCode::SetTable as u32 == u => OpCode::SetTable,
246 _ if OpCode::NewTable as u32 == u => OpCode::NewTable,
247 _ if OpCode::Self_ as u32 == u => OpCode::Self_,
248 _ if OpCode::Add as u32 == u => OpCode::Add,
249 _ if OpCode::Sub as u32 == u => OpCode::Sub,
250 _ if OpCode::Mul as u32 == u => OpCode::Mul,
251 _ if OpCode::Mod as u32 == u => OpCode::Mod,
252 _ if OpCode::Pow as u32 == u => OpCode::Pow,
253 _ if OpCode::Div as u32 == u => OpCode::Div,
254 _ if OpCode::IDiv as u32 == u => OpCode::IDiv,
255 _ if OpCode::BAdd as u32 == u => OpCode::BAdd,
256 _ if OpCode::BOr as u32 == u => OpCode::BOr,
257 _ if OpCode::BXor as u32 == u => OpCode::BXor,
258 _ if OpCode::Shl as u32 == u => OpCode::Shl,
259 _ if OpCode::Shr as u32 == u => OpCode::Shr,
260 _ if OpCode::Unm as u32 == u => OpCode::Unm,
261 _ if OpCode::BNot as u32 == u => OpCode::BNot,
262 _ if OpCode::Not as u32 == u => OpCode::Not,
263 _ if OpCode::Len as u32 == u => OpCode::Len,
264 _ if OpCode::Concat as u32 == u => OpCode::Concat,
265 _ if OpCode::Jmp as u32 == u => OpCode::Jmp,
266 _ if OpCode::Eq as u32 == u => OpCode::Eq,
267 _ if OpCode::Lt as u32 == u => OpCode::Lt,
268 _ if OpCode::Le as u32 == u => OpCode::Le,
269 _ if OpCode::Test as u32 == u => OpCode::Test,
270 _ if OpCode::TestSet as u32 == u => OpCode::TestSet,
271 _ if OpCode::Call as u32 == u => OpCode::Call,
272 _ if OpCode::TailCall as u32 == u => OpCode::TailCall,
273 _ if OpCode::Return as u32 == u => OpCode::Return,
274 _ if OpCode::ForLoop as u32 == u => OpCode::ForLoop,
275 _ if OpCode::ForPrep as u32 == u => OpCode::ForPrep,
276 _ if OpCode::TForCall as u32 == u => OpCode::TForCall,
277 _ if OpCode::TForLoop as u32 == u => OpCode::TForLoop,
278 _ if OpCode::SetList as u32 == u => OpCode::SetList,
279 _ if OpCode::Closure as u32 == u => OpCode::Closure,
280 _ if OpCode::Vararg as u32 == u => OpCode::Vararg,
281 _ if OpCode::ExtraArg as u32 == u => OpCode::ExtraArg,
282 _ => unreachable!("unknown op code : {}!", u),
283 }
284 }
285}
286
287pub struct Instruction(u32);
288
289#[allow(dead_code)]
290#[allow(non_snake_case)]
291impl Instruction {
292 pub fn new() -> Self {
293 Instruction(0)
294 }
295
296 pub fn get_op(&self) -> OpCode {
297 OpCode::from_u32(((self.0) >> POS_OP) & Instruction::mask1(SIZE_OP, 0))
298 }
299
300 pub fn set_op(&mut self, op: OpCode) {
301 self.set_arg(op as u32, POS_OP, SIZE_OP)
302 }
303
304 pub fn get_arg_A(&self) -> u32 {
305 self.get_arg(POS_A, SIZE_A)
306 }
307
308 pub fn set_arg_A(&mut self, value: u32) {
309 self.set_arg(value, POS_A, SIZE_A);
310 }
311
312 pub fn get_arg_B(&self) -> u32 {
313 self.get_arg(POS_B, SIZE_B)
314 }
315
316 pub fn set_arg_B(&mut self, value: u32) {
317 self.set_arg(value, POS_B, SIZE_B);
318 }
319
320 pub fn get_arg_C(&self) -> u32 {
321 self.get_arg(POS_C, SIZE_C)
322 }
323
324 pub fn set_arg_C(&mut self, value: u32) {
325 self.set_arg(value, POS_C, SIZE_C);
326 }
327
328 pub fn get_arg_Ax(&self) -> u32 {
329 self.get_arg(POS_AX, SIZE_AX)
330 }
331
332 pub fn set_arg_Ax(&mut self, value: u32) {
333 self.set_arg(value, POS_AX, SIZE_AX);
334 }
335
336 pub fn get_arg_Bx(&self) -> u32 {
337 self.get_arg(POS_BX, SIZE_BX)
338 }
339
340 pub fn set_arg_Bx(&mut self, value: u32) {
341 self.set_arg(value, POS_BX, SIZE_BX);
342 }
343
344 pub fn get_arg_sBx(&self) -> i32 {
345 (self.get_arg(POS_BX, SIZE_BX) as i32) - MAXARG_SBX
346 }
347
348 pub fn set_arg_sBx(&mut self, value: i32) {
349 self.set_arg((value + MAXARG_SBX) as u32, POS_BX, SIZE_BX);
350 }
351
352 pub fn create_ABC(op: OpCode, a: u32, b: u32, c: u32) -> Self {
353 Instruction(((op as u32) << POS_OP) | (a << POS_A) | (b << POS_B) | (c << POS_C))
354 }
355
356 pub fn create_ABx(op: OpCode, a: u32, bx: u32) -> Self {
357 Instruction(((op as u32) << POS_OP) | (a << POS_A) | (bx << POS_BX))
358 }
359
360 pub fn create_AsBx(op: OpCode, a: u32, sBx: i32) -> Self {
361 Instruction(
362 ((op as u32) << POS_OP) | (a << POS_A) | (((sBx + MAXARG_SBX) as u32) << POS_BX),
363 )
364 }
365
366 pub fn create_Ax(op: OpCode, a: u32) -> Self {
367 Instruction(((op as u32) << POS_OP) | (a << POS_AX))
368 }
369
370 pub fn save(&mut self, a: u32) {
371 let mask = !(((1 << SIZE_A) - 1) << POS_A);
372 self.0 = (self.0 & mask) | (a << POS_A);
373 }
374
375 fn get_arg(&self, pos: u32, size: u32) -> u32 {
376 (self.0 >> pos) & Instruction::mask1(size, 0)
377 }
378
379 fn set_arg(&mut self, value: u32, pos: u32, size: u32) {
380 self.0 = (Instruction::mask1(size, pos) & (value << pos))
381 | (self.0 & Instruction::mask0(size, pos))
382 }
383
384 fn mask1(n: u32, p: u32) -> u32 {
385 (!((!0u32) << n)) << p
386 }
387
388 fn mask0(n: u32, p: u32) -> u32 {
389 !Instruction::mask1(n, p)
390 }
391
392 pub fn mode(&self) -> OpMode {
393 match self.get_op() {
394 OpCode::Move => OpMode::IAB,
395 OpCode::LoadK => OpMode::IABx,
396 OpCode::LoadKx => OpMode::IA,
397 OpCode::LoadBool => OpMode::IABC,
398 OpCode::LoadNil => OpMode::IAB,
399 OpCode::GetUpVal => OpMode::IAB,
400 OpCode::GetTabUp => OpMode::IABC,
401 OpCode::GetTable => OpMode::IABC,
402 OpCode::SetTabUp => OpMode::IABC,
403 OpCode::SetUpVal => OpMode::IAB,
404 OpCode::SetTable => OpMode::IABC,
405 OpCode::NewTable => OpMode::IABC,
406 OpCode::Self_ => OpMode::IABC,
407 OpCode::Add => OpMode::IABC,
408 OpCode::Sub => OpMode::IABC,
409 OpCode::Mul => OpMode::IABC,
410 OpCode::Mod => OpMode::IABC,
411 OpCode::Pow => OpMode::IABC,
412 OpCode::Div => OpMode::IABC,
413 OpCode::IDiv => OpMode::IABC,
414 OpCode::BAdd => OpMode::IABC,
415 OpCode::BOr => OpMode::IABC,
416 OpCode::BXor => OpMode::IABC,
417 OpCode::Shl => OpMode::IABC,
418 OpCode::Shr => OpMode::IABC,
419 OpCode::Unm => OpMode::IAB,
420 OpCode::BNot => OpMode::IAB,
421 OpCode::Not => OpMode::IAB,
422 OpCode::Len => OpMode::IAB,
423 OpCode::Concat => OpMode::IABC,
424 OpCode::Jmp => OpMode::IAsBx,
425 OpCode::Eq => OpMode::IABC,
426 OpCode::Lt => OpMode::IABC,
427 OpCode::Le => OpMode::IABC,
428 OpCode::Test => OpMode::IAC,
429 OpCode::TestSet => OpMode::IABC,
430 OpCode::Call => OpMode::IABC,
431 OpCode::TailCall => OpMode::IABC,
432 OpCode::Return => OpMode::IAB,
433 OpCode::ForLoop => OpMode::IAsBx,
434 OpCode::ForPrep => OpMode::IAsBx,
435 OpCode::TForCall => OpMode::IAC,
436 OpCode::TForLoop => OpMode::IAsBx,
437 OpCode::SetList => OpMode::IAsBx,
438 OpCode::Closure => OpMode::IABx,
439 OpCode::Vararg => OpMode::IAB,
440 OpCode::ExtraArg => OpMode::IAx,
441 }
442 }
443}
444
445use std::fmt;
446impl fmt::Debug for Instruction {
447 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
448 match self.mode() {
449 OpMode::IA => write!(
450 f,
451 "| {:<10} | {:<5} | {:<5} | {:<5} |",
452 format!("{:?}", self.get_op()),
453 self.get_arg_A(),
454 " ",
455 " "
456 ),
457 OpMode::IAB => write!(
458 f,
459 "| {:<10} | {:<5} | {:<5} | {:<5} |",
460 format!("{:?}", self.get_op()),
461 self.get_arg_A(),
462 self.get_arg_B(),
463 " "
464 ),
465 OpMode::IABC => write!(
466 f,
467 "| {:<10} | {:<5} | {:<5} | {:<5} |",
468 format!("{:?}", self.get_op()),
469 self.get_arg_A(),
470 self.get_arg_B(),
471 self.get_arg_C()
472 ),
473 OpMode::IAC => write!(
474 f,
475 "| {:<10} | {:<5} | {:<5} | {:<5} |",
476 format!("{:?}", self.get_op()),
477 self.get_arg_A(),
478 " ",
479 self.get_arg_C()
480 ),
481 OpMode::IABx => write!(
482 f,
483 "| {:<10} | {:<5} | {:<5} | {:<5} |",
484 format!("{:?}", self.get_op()),
485 self.get_arg_A(),
486 self.get_arg_Bx(),
487 " "
488 ),
489 OpMode::IAsBx => write!(
490 f,
491 "| {:<10} | {:<5} | {:<5} | {:<5} |",
492 format!("{:?}", self.get_op()),
493 self.get_arg_A(),
494 self.get_arg_sBx(),
495 " "
496 ),
497 OpMode::IAx => write!(
498 f,
499 "| {:<10} | {:<5} | {:<5} | {:<5} |",
500 format!("{:?}", self.get_op()),
501 self.get_arg_Ax(),
502 " ",
503 " "
504 ),
505 }
506 }
507}