luadec_rust/lua51/opcodes.rs
1/// Lua 5.1 opcodes, matching the enum order in lopcodes.h
2#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3#[repr(u8)]
4pub enum OpCode {
5 Move = 0, // A B R(A) := R(B)
6 LoadK = 1, // A Bx R(A) := Kst(Bx)
7 LoadBool = 2, // A B C R(A) := (Bool)B; if (C) pc++
8 LoadNil = 3, // A B R(A) := ... := R(B) := nil
9 GetUpval = 4, // A B R(A) := UpValue[B]
10 GetGlobal = 5, // A Bx R(A) := Gbl[Kst(Bx)]
11 GetTable = 6, // A B C R(A) := R(B)[RK(C)]
12 SetGlobal = 7, // A Bx Gbl[Kst(Bx)] := R(A)
13 SetUpval = 8, // A B UpValue[B] := R(A)
14 SetTable = 9, // A B C R(A)[RK(B)] := RK(C)
15 NewTable = 10, // A B C R(A) := {} (size = B,C)
16 Self_ = 11, // A B C R(A+1) := R(B); R(A) := R(B)[RK(C)]
17 Add = 12, // A B C R(A) := RK(B) + RK(C)
18 Sub = 13, // A B C R(A) := RK(B) - RK(C)
19 Mul = 14, // A B C R(A) := RK(B) * RK(C)
20 Div = 15, // A B C R(A) := RK(B) / RK(C)
21 Mod = 16, // A B C R(A) := RK(B) % RK(C)
22 Pow = 17, // A B C R(A) := RK(B) ^ RK(C)
23 Unm = 18, // A B R(A) := -R(B)
24 Not = 19, // A B R(A) := not R(B)
25 Len = 20, // A B R(A) := length of R(B)
26 Concat = 21, // A B C R(A) := R(B).. ... ..R(C)
27 Jmp = 22, // sBx pc+=sBx
28 Eq = 23, // A B C if ((RK(B) == RK(C)) ~= A) then pc++
29 Lt = 24, // A B C if ((RK(B) < RK(C)) ~= A) then pc++
30 Le = 25, // A B C if ((RK(B) <= RK(C)) ~= A) then pc++
31 Test = 26, // A C if not (R(A) <=> C) then pc++
32 TestSet = 27, // A B C if (R(B) <=> C) then R(A) := R(B) else pc++
33 Call = 28, // A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1))
34 TailCall = 29, // A B C return R(A)(R(A+1), ... ,R(A+B-1))
35 Return = 30, // A B return R(A), ... ,R(A+B-2)
36 ForLoop = 31, // A sBx R(A)+=R(A+2); if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }
37 ForPrep = 32, // A sBx R(A)-=R(A+2); pc+=sBx
38 TForLoop = 33, // A C R(A+3), ... ,R(A+3+C) := R(A)(R(A+1), R(A+2));
39 SetList = 34, // A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B
40 Close = 35, // A close all variables in the stack up to (>=) R(A)
41 Closure = 36, // A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))
42 VarArg = 37, // A B R(A), R(A+1), ..., R(A+B-1) = vararg
43}
44
45pub const NUM_OPCODES: usize = 38;
46
47impl OpCode {
48 pub fn from_u8(v: u8) -> Option<OpCode> {
49 if v < NUM_OPCODES as u8 {
50 // SAFETY: OpCode is repr(u8) with contiguous values 0..37
51 Some(unsafe { std::mem::transmute(v) })
52 } else {
53 None
54 }
55 }
56
57 pub fn name(self) -> &'static str {
58 OPCODE_NAMES[self as usize]
59 }
60}
61
62impl std::fmt::Display for OpCode {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 f.write_str(self.name())
65 }
66}
67
68/// Opcode name table, corresponding to luaP_opnames in lopcodes.c
69const OPCODE_NAMES: [&str; NUM_OPCODES] = [
70 "MOVE", "LOADK", "LOADBOOL", "LOADNIL", "GETUPVAL", "GETGLOBAL", "GETTABLE", "SETGLOBAL",
71 "SETUPVAL", "SETTABLE", "NEWTABLE", "SELF", "ADD", "SUB", "MUL", "DIV", "MOD", "POW", "UNM",
72 "NOT", "LEN", "CONCAT", "JMP", "EQ", "LT", "LE", "TEST", "TESTSET", "CALL", "TAILCALL",
73 "RETURN", "FORLOOP", "FORPREP", "TFORLOOP", "SETLIST", "CLOSE", "CLOSURE", "VARARG",
74];
75
76/// Instruction format
77#[derive(Debug, Clone, Copy, PartialEq, Eq)]
78pub enum OpMode {
79 ABC,
80 ABx,
81 AsBx,
82}
83
84/// Argument mode mask
85#[derive(Debug, Clone, Copy, PartialEq, Eq)]
86pub enum OpArgMask {
87 /// Argument is not used
88 N,
89 /// Argument is used
90 U,
91 /// Argument is a register or jump offset
92 R,
93 /// Argument is a constant or register/constant
94 K,
95}
96
97/// Opcode metadata
98#[derive(Debug, Clone, Copy)]
99pub struct OpProp {
100 pub mode: OpMode,
101 pub b_mode: OpArgMask,
102 pub c_mode: OpArgMask,
103 pub sets_a: bool,
104 pub is_test: bool,
105}
106
107/// Opcode property table, matching luaP_opmodes in lopcodes.c
108pub const OP_PROPS: [OpProp; NUM_OPCODES] = {
109 use OpArgMask::*;
110 use OpMode::*;
111 const fn p(is_test: bool, sets_a: bool, b: OpArgMask, c: OpArgMask, mode: OpMode) -> OpProp {
112 OpProp {
113 mode,
114 b_mode: b,
115 c_mode: c,
116 sets_a,
117 is_test,
118 }
119 }
120 [
121 // T A B C mode
122 p(false, true, R, N, ABC), // MOVE
123 p(false, true, K, N, ABx), // LOADK
124 p(false, true, U, U, ABC), // LOADBOOL
125 p(false, true, R, N, ABC), // LOADNIL
126 p(false, true, U, N, ABC), // GETUPVAL
127 p(false, true, K, N, ABx), // GETGLOBAL
128 p(false, true, R, K, ABC), // GETTABLE
129 p(false, false, K, N, ABx), // SETGLOBAL
130 p(false, false, U, N, ABC), // SETUPVAL
131 p(false, false, K, K, ABC), // SETTABLE
132 p(false, true, U, U, ABC), // NEWTABLE
133 p(false, true, R, K, ABC), // SELF
134 p(false, true, K, K, ABC), // ADD
135 p(false, true, K, K, ABC), // SUB
136 p(false, true, K, K, ABC), // MUL
137 p(false, true, K, K, ABC), // DIV
138 p(false, true, K, K, ABC), // MOD
139 p(false, true, K, K, ABC), // POW
140 p(false, true, R, N, ABC), // UNM
141 p(false, true, R, N, ABC), // NOT
142 p(false, true, R, N, ABC), // LEN
143 p(false, true, R, R, ABC), // CONCAT
144 p(false, false, R, N, AsBx), // JMP
145 p(true, false, K, K, ABC), // EQ
146 p(true, false, K, K, ABC), // LT
147 p(true, false, K, K, ABC), // LE
148 p(true, true, R, U, ABC), // TEST
149 p(true, true, R, U, ABC), // TESTSET
150 p(false, true, U, U, ABC), // CALL
151 p(false, true, U, U, ABC), // TAILCALL
152 p(false, false, U, N, ABC), // RETURN
153 p(false, true, R, N, AsBx), // FORLOOP
154 p(false, true, R, N, AsBx), // FORPREP
155 p(true, false, N, U, ABC), // TFORLOOP
156 p(false, false, U, U, ABC), // SETLIST
157 p(false, false, N, N, ABC), // CLOSE
158 p(false, true, U, N, ABx), // CLOSURE
159 p(false, true, U, N, ABC), // VARARG
160 ]
161};
162
163impl OpCode {
164 pub fn props(self) -> &'static OpProp {
165 &OP_PROPS[self as usize]
166 }
167}