Skip to main content

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}