luars/lua_vm/opcode/mod.rs
1mod instruction;
2
3pub use instruction::Instruction;
4
5/// Instruction format modes (Lua 5.5)
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum OpMode {
8 IABC, // iABC: C(8) | B(8) | k(1) | A(8) | Op(7)
9 IvABC, // ivABC: vC(10) | vB(6) | k(1) | A(8) | Op(7) - variable-size B and C
10 IABx, // iABx: Bx(17) | A(8) | Op(7)
11 IAsBx, // iAsBx: sBx(signed 17) | A(8) | Op(7)
12 IAx, // iAx: Ax(25) | Op(7)
13 IsJ, // isJ: sJ(signed 25) | Op(7)
14}
15
16/// Complete Lua 5.5 Opcode Set (86 opcodes)
17/// Based on lopcodes.h from Lua 5.5.0
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19#[repr(u8)]
20pub enum OpCode {
21 /*----------------------------------------------------------------------
22 Lua 5.5 Opcode Definitions (matching lopcodes.h)
23 Format: name args description
24 ------------------------------------------------------------------------*/
25 // Load and move operations
26 Move = 0, // A B R[A] := R[B]
27 LoadI, // A sBx R[A] := sBx
28 LoadF, // A sBx R[A] := (lua_Number)sBx
29 LoadK, // A Bx R[A] := K[Bx]
30 LoadKX, // A R[A] := K[extra arg]
31 LoadFalse, // A R[A] := false
32 LFalseSkip, // A R[A] := false; pc++
33 LoadTrue, // A R[A] := true
34 LoadNil, // A B R[A], R[A+1], ..., R[A+B] := nil
35
36 // Upvalue operations
37 GetUpval, // A B R[A] := UpValue[B]
38 SetUpval, // A B UpValue[B] := R[A]
39
40 // Table get operations
41 GetTabUp, // A B C R[A] := UpValue[B][K[C]:shortstring]
42 GetTable, // A B C R[A] := R[B][R[C]]
43 GetI, // A B C R[A] := R[B][C]
44 GetField, // A B C R[A] := R[B][K[C]:shortstring]
45
46 // Table set operations
47 SetTabUp, // A B C UpValue[A][K[B]:shortstring] := RK(C)
48 SetTable, // A B C R[A][R[B]] := RK(C)
49 SetI, // A B C R[A][B] := RK(C)
50 SetField, // A B C R[A][K[B]:shortstring] := RK(C)
51
52 // Table creation
53 NewTable, // A vB vC k R[A] := {} (ivABC format)
54
55 // Self call (method call syntax)
56 Self_, // A B C R[A+1] := R[B]; R[A] := R[B][K[C]:shortstring]
57
58 // Arithmetic with immediate
59 AddI, // A B sC R[A] := R[B] + sC
60
61 // Arithmetic with constant
62 AddK, // A B C R[A] := R[B] + K[C]:number
63 SubK, // A B C R[A] := R[B] - K[C]:number
64 MulK, // A B C R[A] := R[B] * K[C]:number
65 ModK, // A B C R[A] := R[B] % K[C]:number
66 PowK, // A B C R[A] := R[B] ^ K[C]:number
67 DivK, // A B C R[A] := R[B] / K[C]:number
68 IDivK, // A B C R[A] := R[B] // K[C]:number
69
70 // Bitwise operations with constant
71 BAndK, // A B C R[A] := R[B] & K[C]:integer
72 BOrK, // A B C R[A] := R[B] | K[C]:integer
73 BXorK, // A B C R[A] := R[B] ~ K[C]:integer
74
75 // Shift operations with immediate
76 ShlI, // A B sC R[A] := sC << R[B]
77 ShrI, // A B sC R[A] := R[B] >> sC
78
79 // Arithmetic operations (register-register)
80 Add, // A B C R[A] := R[B] + R[C]
81 Sub, // A B C R[A] := R[B] - R[C]
82 Mul, // A B C R[A] := R[B] * R[C]
83 Mod, // A B C R[A] := R[B] % R[C]
84 Pow, // A B C R[A] := R[B] ^ R[C]
85 Div, // A B C R[A] := R[B] / R[C]
86 IDiv, // A B C R[A] := R[B] // R[C]
87
88 // Bitwise operations (register-register)
89 BAnd, // A B C R[A] := R[B] & R[C]
90 BOr, // A B C R[A] := R[B] | R[C]
91 BXor, // A B C R[A] := R[B] ~ R[C]
92 Shl, // A B C R[A] := R[B] << R[C]
93 Shr, // A B C R[A] := R[B] >> R[C]
94
95 // Metamethod fallback operations
96 MmBin, // A B C call C metamethod over R[A] and R[B]
97 MmBinI, // A sB C k call C metamethod over R[A] and sB
98 MmBinK, // A B C k call C metamethod over R[A] and K[B]
99
100 // Unary operations
101 Unm, // A B R[A] := -R[B]
102 BNot, // A B R[A] := ~R[B]
103 Not, // A B R[A] := not R[B]
104 Len, // A B R[A] := #R[B] (length operator)
105
106 // String concatenation
107 Concat, // A B R[A] := R[A].. ... ..R[A + B - 1]
108
109 // Upvalue management
110 Close, // A close all upvalues >= R[A]
111 Tbc, // A mark variable A "to be closed"
112
113 // Control flow
114 Jmp, // sJ pc += sJ
115
116 // Comparison operations (register-register)
117 Eq, // A B k if ((R[A] == R[B]) ~= k) then pc++
118 Lt, // A B k if ((R[A] < R[B]) ~= k) then pc++
119 Le, // A B k if ((R[A] <= R[B]) ~= k) then pc++
120
121 // Comparison with constant/immediate
122 EqK, // A B k if ((R[A] == K[B]) ~= k) then pc++
123 EqI, // A sB k if ((R[A] == sB) ~= k) then pc++
124 LtI, // A sB k if ((R[A] < sB) ~= k) then pc++
125 LeI, // A sB k if ((R[A] <= sB) ~= k) then pc++
126 GtI, // A sB k if ((R[A] > sB) ~= k) then pc++
127 GeI, // A sB k if ((R[A] >= sB) ~= k) then pc++
128
129 // Conditional tests
130 Test, // A k if (not R[A] == k) then pc++
131 TestSet, // A B k if (not R[B] == k) then pc++ else R[A] := R[B]
132
133 // Function calls
134 Call, // A B C R[A], ... ,R[A+C-2] := R[A](R[A+1], ... ,R[A+B-1])
135 TailCall, // A B C k return R[A](R[A+1], ... ,R[A+B-1])
136
137 // Return operations
138 Return, // A B C k return R[A], ... ,R[A+B-2]
139 Return0, // return
140 Return1, // A return R[A]
141
142 // Numeric for loops
143 ForLoop, // A Bx update counters; if loop continues then pc-=Bx;
144 ForPrep, // A Bx <check values and prepare counters>; if not to run then pc+=Bx+1;
145
146 // Generic for loops
147 TForPrep, // A Bx create upvalue for R[A + 3]; pc+=Bx
148 TForCall, // A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2])
149 TForLoop, // A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx }
150
151 // Table list initialization
152 SetList, // A vB vC k R[A][vC+i] := R[A+i], 1 <= i <= vB (ivABC format)
153
154 // Closure creation
155 Closure, // A Bx R[A] := closure(KPROTO[Bx])
156
157 // Vararg operations
158 Vararg, // A B C k R[A], ..., R[A+C-2] = varargs
159 GetVarg, // A B C R[A] := R[B][R[C]], R[B] is vararg parameter (Lua 5.5)
160
161 // Error checking for globals (Lua 5.5)
162 ErrNNil, // A Bx raise error if R[A] ~= nil (K[Bx - 1] is global name)
163
164 // Vararg preparation
165 VarargPrep, // (adjust varargs)
166
167 // Extra argument for previous instruction
168 ExtraArg, // Ax extra (larger) argument for previous opcode
169}
170
171impl OpCode {
172 #[inline(always)]
173 pub fn from_u8(byte: u8) -> Self {
174 unsafe { std::mem::transmute(byte) }
175 }
176
177 /// Check if instruction uses "top" (IT mode - In Top)
178 /// These instructions depend on the value of 'top' from previous instruction
179 /// For all other instructions, top should be reset to base + nactvar
180 ///
181 /// From Lua 5.5 lopcodes.c:
182 /// - CALL: IT=1 (uses top for vararg count)
183 /// - TAILCALL: IT=1
184 /// - RETURN: IT=1 (uses top for return count)
185 /// - SETLIST: IT=1 (uses top for list size)
186 /// - VARARGPREP: IT=1 (sets up varargs)
187 pub fn uses_top(self) -> bool {
188 use OpCode::*;
189 matches!(self, Call | TailCall | Return | SetList | VarargPrep)
190 }
191
192 /// Get the instruction format mode for this opcode
193 /// Based on Lua 5.5 lopcodes.c luaP_opmodes table
194 pub fn get_mode(self) -> OpMode {
195 use OpCode::*;
196 match self {
197 // iAsBx format (signed Bx)
198 LoadI | LoadF => OpMode::IAsBx,
199
200 // iABx format (unsigned Bx)
201 LoadK | LoadKX | ForLoop | ForPrep | TForPrep | TForLoop | Closure | ErrNNil => {
202 OpMode::IABx
203 }
204
205 // isJ format (signed jump)
206 Jmp => OpMode::IsJ,
207
208 // iAx format
209 ExtraArg => OpMode::IAx,
210
211 // ivABC format (variable-size B and C fields)
212 NewTable | SetList => OpMode::IvABC,
213
214 // iABC format (everything else)
215 _ => OpMode::IABC,
216 }
217 }
218}