1*61145dc2SMartin Matuska // SPDX-License-Identifier: MIT 2eda14cbcSMatt Macy /* 3eda14cbcSMatt Macy ** $Id: lopcodes.h,v 1.142.1.2 2014/10/20 18:32:09 roberto Exp $ 4eda14cbcSMatt Macy ** Opcodes for Lua virtual machine 5eda14cbcSMatt Macy ** See Copyright Notice in lua.h 6eda14cbcSMatt Macy */ 7eda14cbcSMatt Macy 8eda14cbcSMatt Macy #ifndef lopcodes_h 9eda14cbcSMatt Macy #define lopcodes_h 10eda14cbcSMatt Macy 11eda14cbcSMatt Macy #include "llimits.h" 12eda14cbcSMatt Macy 13eda14cbcSMatt Macy 14eda14cbcSMatt Macy /*=========================================================================== 15eda14cbcSMatt Macy We assume that instructions are unsigned numbers. 16eda14cbcSMatt Macy All instructions have an opcode in the first 6 bits. 17eda14cbcSMatt Macy Instructions can have the following fields: 18eda14cbcSMatt Macy `A' : 8 bits 19eda14cbcSMatt Macy `B' : 9 bits 20eda14cbcSMatt Macy `C' : 9 bits 21eda14cbcSMatt Macy 'Ax' : 26 bits ('A', 'B', and 'C' together) 22eda14cbcSMatt Macy `Bx' : 18 bits (`B' and `C' together) 23eda14cbcSMatt Macy `sBx' : signed Bx 24eda14cbcSMatt Macy 25eda14cbcSMatt Macy A signed argument is represented in excess K; that is, the number 26eda14cbcSMatt Macy value is the unsigned value minus K. K is exactly the maximum value 27eda14cbcSMatt Macy for that argument (so that -max is represented by 0, and +max is 28eda14cbcSMatt Macy represented by 2*max), which is half the maximum for the corresponding 29eda14cbcSMatt Macy unsigned argument. 30eda14cbcSMatt Macy ===========================================================================*/ 31eda14cbcSMatt Macy 32eda14cbcSMatt Macy 33eda14cbcSMatt Macy enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ 34eda14cbcSMatt Macy 35eda14cbcSMatt Macy 36eda14cbcSMatt Macy /* 37eda14cbcSMatt Macy ** size and position of opcode arguments. 38eda14cbcSMatt Macy */ 39eda14cbcSMatt Macy #define SIZE_C 9 40eda14cbcSMatt Macy #define SIZE_B 9 41eda14cbcSMatt Macy #define SIZE_Bx (SIZE_C + SIZE_B) 42eda14cbcSMatt Macy #define SIZE_A 8 43eda14cbcSMatt Macy #define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A) 44eda14cbcSMatt Macy 45eda14cbcSMatt Macy #define SIZE_OP 6 46eda14cbcSMatt Macy 47eda14cbcSMatt Macy #define POS_OP 0 48eda14cbcSMatt Macy #define POS_A (POS_OP + SIZE_OP) 49eda14cbcSMatt Macy #define POS_C (POS_A + SIZE_A) 50eda14cbcSMatt Macy #define POS_B (POS_C + SIZE_C) 51eda14cbcSMatt Macy #define POS_Bx POS_C 52eda14cbcSMatt Macy #define POS_Ax POS_A 53eda14cbcSMatt Macy 54eda14cbcSMatt Macy 55eda14cbcSMatt Macy /* 56eda14cbcSMatt Macy ** limits for opcode arguments. 57eda14cbcSMatt Macy ** we use (signed) int to manipulate most arguments, 58eda14cbcSMatt Macy ** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) 59eda14cbcSMatt Macy */ 60eda14cbcSMatt Macy #if SIZE_Bx < LUAI_BITSINT-1 61eda14cbcSMatt Macy #define MAXARG_Bx ((1<<SIZE_Bx)-1) 62eda14cbcSMatt Macy #define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */ 63eda14cbcSMatt Macy #else 64eda14cbcSMatt Macy #define MAXARG_Bx MAX_INT 65eda14cbcSMatt Macy #define MAXARG_sBx MAX_INT 66eda14cbcSMatt Macy #endif 67eda14cbcSMatt Macy 68eda14cbcSMatt Macy #if SIZE_Ax < LUAI_BITSINT-1 69eda14cbcSMatt Macy #define MAXARG_Ax ((1<<SIZE_Ax)-1) 70eda14cbcSMatt Macy #else 71eda14cbcSMatt Macy #define MAXARG_Ax MAX_INT 72eda14cbcSMatt Macy #endif 73eda14cbcSMatt Macy 74eda14cbcSMatt Macy 75eda14cbcSMatt Macy #define MAXARG_A ((1<<SIZE_A)-1) 76eda14cbcSMatt Macy #define MAXARG_B ((1<<SIZE_B)-1) 77eda14cbcSMatt Macy #define MAXARG_C ((1<<SIZE_C)-1) 78eda14cbcSMatt Macy 79eda14cbcSMatt Macy 80eda14cbcSMatt Macy /* creates a mask with `n' 1 bits at position `p' */ 81eda14cbcSMatt Macy #define MASK1(n,p) ((~((~(Instruction)0)<<(n)))<<(p)) 82eda14cbcSMatt Macy 83eda14cbcSMatt Macy /* creates a mask with `n' 0 bits at position `p' */ 84eda14cbcSMatt Macy #define MASK0(n,p) (~MASK1(n,p)) 85eda14cbcSMatt Macy 86eda14cbcSMatt Macy /* 87eda14cbcSMatt Macy ** the following macros help to manipulate instructions 88eda14cbcSMatt Macy */ 89eda14cbcSMatt Macy 90eda14cbcSMatt Macy #define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0))) 91eda14cbcSMatt Macy #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ 92eda14cbcSMatt Macy ((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP)))) 93eda14cbcSMatt Macy 94eda14cbcSMatt Macy #define getarg(i,pos,size) (cast(int, ((i)>>pos) & MASK1(size,0))) 95eda14cbcSMatt Macy #define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ 96eda14cbcSMatt Macy ((cast(Instruction, v)<<pos)&MASK1(size,pos)))) 97eda14cbcSMatt Macy 98eda14cbcSMatt Macy #define GETARG_A(i) getarg(i, POS_A, SIZE_A) 99eda14cbcSMatt Macy #define SETARG_A(i,v) setarg(i, v, POS_A, SIZE_A) 100eda14cbcSMatt Macy 101eda14cbcSMatt Macy #define GETARG_B(i) getarg(i, POS_B, SIZE_B) 102eda14cbcSMatt Macy #define SETARG_B(i,v) setarg(i, v, POS_B, SIZE_B) 103eda14cbcSMatt Macy 104eda14cbcSMatt Macy #define GETARG_C(i) getarg(i, POS_C, SIZE_C) 105eda14cbcSMatt Macy #define SETARG_C(i,v) setarg(i, v, POS_C, SIZE_C) 106eda14cbcSMatt Macy 107eda14cbcSMatt Macy #define GETARG_Bx(i) getarg(i, POS_Bx, SIZE_Bx) 108eda14cbcSMatt Macy #define SETARG_Bx(i,v) setarg(i, v, POS_Bx, SIZE_Bx) 109eda14cbcSMatt Macy 110eda14cbcSMatt Macy #define GETARG_Ax(i) getarg(i, POS_Ax, SIZE_Ax) 111eda14cbcSMatt Macy #define SETARG_Ax(i,v) setarg(i, v, POS_Ax, SIZE_Ax) 112eda14cbcSMatt Macy 113eda14cbcSMatt Macy #define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx) 114eda14cbcSMatt Macy #define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx)) 115eda14cbcSMatt Macy 116eda14cbcSMatt Macy 117eda14cbcSMatt Macy #define CREATE_ABC(o,a,b,c) ((cast(Instruction, o)<<POS_OP) \ 118eda14cbcSMatt Macy | (cast(Instruction, a)<<POS_A) \ 119eda14cbcSMatt Macy | (cast(Instruction, b)<<POS_B) \ 120eda14cbcSMatt Macy | (cast(Instruction, c)<<POS_C)) 121eda14cbcSMatt Macy 122eda14cbcSMatt Macy #define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \ 123eda14cbcSMatt Macy | (cast(Instruction, a)<<POS_A) \ 124eda14cbcSMatt Macy | (cast(Instruction, bc)<<POS_Bx)) 125eda14cbcSMatt Macy 126eda14cbcSMatt Macy #define CREATE_Ax(o,a) ((cast(Instruction, o)<<POS_OP) \ 127eda14cbcSMatt Macy | (cast(Instruction, a)<<POS_Ax)) 128eda14cbcSMatt Macy 129eda14cbcSMatt Macy 130eda14cbcSMatt Macy /* 131eda14cbcSMatt Macy ** Macros to operate RK indices 132eda14cbcSMatt Macy */ 133eda14cbcSMatt Macy 134eda14cbcSMatt Macy /* this bit 1 means constant (0 means register) */ 135eda14cbcSMatt Macy #define BITRK (1 << (SIZE_B - 1)) 136eda14cbcSMatt Macy 137eda14cbcSMatt Macy /* test whether value is a constant */ 138eda14cbcSMatt Macy #define ISK(x) ((x) & BITRK) 139eda14cbcSMatt Macy 140eda14cbcSMatt Macy /* gets the index of the constant */ 141eda14cbcSMatt Macy #define INDEXK(r) ((int)(r) & ~BITRK) 142eda14cbcSMatt Macy 143eda14cbcSMatt Macy #define MAXINDEXRK (BITRK - 1) 144eda14cbcSMatt Macy 145eda14cbcSMatt Macy /* code a constant index as a RK value */ 146eda14cbcSMatt Macy #define RKASK(x) ((x) | BITRK) 147eda14cbcSMatt Macy 148eda14cbcSMatt Macy 149eda14cbcSMatt Macy /* 150eda14cbcSMatt Macy ** invalid register that fits in 8 bits 151eda14cbcSMatt Macy */ 152eda14cbcSMatt Macy #define NO_REG MAXARG_A 153eda14cbcSMatt Macy 154eda14cbcSMatt Macy 155eda14cbcSMatt Macy /* 156eda14cbcSMatt Macy ** R(x) - register 157eda14cbcSMatt Macy ** Kst(x) - constant (in constant table) 158eda14cbcSMatt Macy ** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x) 159eda14cbcSMatt Macy */ 160eda14cbcSMatt Macy 161eda14cbcSMatt Macy 162eda14cbcSMatt Macy /* 163eda14cbcSMatt Macy ** grep "ORDER OP" if you change these enums 164eda14cbcSMatt Macy */ 165eda14cbcSMatt Macy 166eda14cbcSMatt Macy typedef enum { 167eda14cbcSMatt Macy /*---------------------------------------------------------------------- 168eda14cbcSMatt Macy name args description 169eda14cbcSMatt Macy ------------------------------------------------------------------------*/ 170eda14cbcSMatt Macy OP_MOVE,/* A B R(A) := R(B) */ 171eda14cbcSMatt Macy OP_LOADK,/* A Bx R(A) := Kst(Bx) */ 172eda14cbcSMatt Macy OP_LOADKX,/* A R(A) := Kst(extra arg) */ 173eda14cbcSMatt Macy OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */ 174eda14cbcSMatt Macy OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil */ 175eda14cbcSMatt Macy OP_GETUPVAL,/* A B R(A) := UpValue[B] */ 176eda14cbcSMatt Macy 177eda14cbcSMatt Macy OP_GETTABUP,/* A B C R(A) := UpValue[B][RK(C)] */ 178eda14cbcSMatt Macy OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */ 179eda14cbcSMatt Macy 180eda14cbcSMatt Macy OP_SETTABUP,/* A B C UpValue[A][RK(B)] := RK(C) */ 181eda14cbcSMatt Macy OP_SETUPVAL,/* A B UpValue[B] := R(A) */ 182eda14cbcSMatt Macy OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */ 183eda14cbcSMatt Macy 184eda14cbcSMatt Macy OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */ 185eda14cbcSMatt Macy 186eda14cbcSMatt Macy OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */ 187eda14cbcSMatt Macy 188eda14cbcSMatt Macy OP_ADD,/* A B C R(A) := RK(B) + RK(C) */ 189eda14cbcSMatt Macy OP_SUB,/* A B C R(A) := RK(B) - RK(C) */ 190eda14cbcSMatt Macy OP_MUL,/* A B C R(A) := RK(B) * RK(C) */ 191eda14cbcSMatt Macy OP_DIV,/* A B C R(A) := RK(B) / RK(C) */ 192eda14cbcSMatt Macy OP_MOD,/* A B C R(A) := RK(B) % RK(C) */ 193eda14cbcSMatt Macy OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */ 194eda14cbcSMatt Macy OP_UNM,/* A B R(A) := -R(B) */ 195eda14cbcSMatt Macy OP_NOT,/* A B R(A) := not R(B) */ 196eda14cbcSMatt Macy OP_LEN,/* A B R(A) := length of R(B) */ 197eda14cbcSMatt Macy 198eda14cbcSMatt Macy OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ 199eda14cbcSMatt Macy 200eda14cbcSMatt Macy OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */ 201eda14cbcSMatt Macy OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ 202eda14cbcSMatt Macy OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ 203eda14cbcSMatt Macy OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ 204eda14cbcSMatt Macy 205eda14cbcSMatt Macy OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ 206eda14cbcSMatt Macy OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ 207eda14cbcSMatt Macy 208eda14cbcSMatt Macy OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ 209eda14cbcSMatt Macy OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ 210eda14cbcSMatt Macy OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ 211eda14cbcSMatt Macy 212eda14cbcSMatt Macy OP_FORLOOP,/* A sBx R(A)+=R(A+2); 213eda14cbcSMatt Macy if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/ 214eda14cbcSMatt Macy OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */ 215eda14cbcSMatt Macy 216eda14cbcSMatt Macy OP_TFORCALL,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */ 217eda14cbcSMatt Macy OP_TFORLOOP,/* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }*/ 218eda14cbcSMatt Macy 219eda14cbcSMatt Macy OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */ 220eda14cbcSMatt Macy 221eda14cbcSMatt Macy OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */ 222eda14cbcSMatt Macy 223eda14cbcSMatt Macy OP_VARARG,/* A B R(A), R(A+1), ..., R(A+B-2) = vararg */ 224eda14cbcSMatt Macy 225eda14cbcSMatt Macy OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ 226eda14cbcSMatt Macy } OpCode; 227eda14cbcSMatt Macy 228eda14cbcSMatt Macy 229eda14cbcSMatt Macy #define NUM_OPCODES (cast(int, OP_EXTRAARG) + 1) 230eda14cbcSMatt Macy 231eda14cbcSMatt Macy 232eda14cbcSMatt Macy 233eda14cbcSMatt Macy /*=========================================================================== 234eda14cbcSMatt Macy Notes: 235eda14cbcSMatt Macy (*) In OP_CALL, if (B == 0) then B = top. If (C == 0), then `top' is 236eda14cbcSMatt Macy set to last_result+1, so next open instruction (OP_CALL, OP_RETURN, 237eda14cbcSMatt Macy OP_SETLIST) may use `top'. 238eda14cbcSMatt Macy 239eda14cbcSMatt Macy (*) In OP_VARARG, if (B == 0) then use actual number of varargs and 240eda14cbcSMatt Macy set top (like in OP_CALL with C == 0). 241eda14cbcSMatt Macy 242eda14cbcSMatt Macy (*) In OP_RETURN, if (B == 0) then return up to `top'. 243eda14cbcSMatt Macy 244eda14cbcSMatt Macy (*) In OP_SETLIST, if (B == 0) then B = `top'; if (C == 0) then next 245eda14cbcSMatt Macy 'instruction' is EXTRAARG(real C). 246eda14cbcSMatt Macy 247eda14cbcSMatt Macy (*) In OP_LOADKX, the next 'instruction' is always EXTRAARG. 248eda14cbcSMatt Macy 249eda14cbcSMatt Macy (*) For comparisons, A specifies what condition the test should accept 250eda14cbcSMatt Macy (true or false). 251eda14cbcSMatt Macy 252eda14cbcSMatt Macy (*) All `skips' (pc++) assume that next instruction is a jump. 253eda14cbcSMatt Macy 254eda14cbcSMatt Macy ===========================================================================*/ 255eda14cbcSMatt Macy 256eda14cbcSMatt Macy 257eda14cbcSMatt Macy /* 258eda14cbcSMatt Macy ** masks for instruction properties. The format is: 259eda14cbcSMatt Macy ** bits 0-1: op mode 260eda14cbcSMatt Macy ** bits 2-3: C arg mode 261eda14cbcSMatt Macy ** bits 4-5: B arg mode 262eda14cbcSMatt Macy ** bit 6: instruction set register A 263eda14cbcSMatt Macy ** bit 7: operator is a test (next instruction must be a jump) 264eda14cbcSMatt Macy */ 265eda14cbcSMatt Macy 266eda14cbcSMatt Macy enum OpArgMask { 267eda14cbcSMatt Macy OpArgN, /* argument is not used */ 268eda14cbcSMatt Macy OpArgU, /* argument is used */ 269eda14cbcSMatt Macy OpArgR, /* argument is a register or a jump offset */ 270eda14cbcSMatt Macy OpArgK /* argument is a constant or register/constant */ 271eda14cbcSMatt Macy }; 272eda14cbcSMatt Macy 273eda14cbcSMatt Macy LUAI_DDEC const lu_byte luaP_opmodes[NUM_OPCODES]; 274eda14cbcSMatt Macy 275eda14cbcSMatt Macy #define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) 276eda14cbcSMatt Macy #define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) 277eda14cbcSMatt Macy #define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) 278eda14cbcSMatt Macy #define testAMode(m) (luaP_opmodes[m] & (1 << 6)) 279eda14cbcSMatt Macy #define testTMode(m) (luaP_opmodes[m] & (1 << 7)) 280eda14cbcSMatt Macy 281eda14cbcSMatt Macy 282eda14cbcSMatt Macy LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ 283eda14cbcSMatt Macy 284eda14cbcSMatt Macy 285eda14cbcSMatt Macy /* number of list items to accumulate before a SETLIST instruction */ 286eda14cbcSMatt Macy #define LFIELDS_PER_FLUSH 50 287eda14cbcSMatt Macy 288eda14cbcSMatt Macy 289eda14cbcSMatt Macy #endif 290