18e3e3a7aSWarner Losh /* 20495ed39SKyle Evans ** $Id: lopcodes.h $ 38e3e3a7aSWarner Losh ** Opcodes for Lua virtual machine 48e3e3a7aSWarner Losh ** See Copyright Notice in lua.h 58e3e3a7aSWarner Losh */ 68e3e3a7aSWarner Losh 78e3e3a7aSWarner Losh #ifndef lopcodes_h 88e3e3a7aSWarner Losh #define lopcodes_h 98e3e3a7aSWarner Losh 108e3e3a7aSWarner Losh #include "llimits.h" 118e3e3a7aSWarner Losh 128e3e3a7aSWarner Losh 138e3e3a7aSWarner Losh /*=========================================================================== 140495ed39SKyle Evans We assume that instructions are unsigned 32-bit integers. 150495ed39SKyle Evans All instructions have an opcode in the first 7 bits. 160495ed39SKyle Evans Instructions can have the following formats: 178e3e3a7aSWarner Losh 180495ed39SKyle Evans 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 190495ed39SKyle Evans 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 200495ed39SKyle Evans iABC C(8) | B(8) |k| A(8) | Op(7) | 210495ed39SKyle Evans iABx Bx(17) | A(8) | Op(7) | 220495ed39SKyle Evans iAsBx sBx (signed)(17) | A(8) | Op(7) | 230495ed39SKyle Evans iAx Ax(25) | Op(7) | 240495ed39SKyle Evans isJ sJ(25) | Op(7) | 250495ed39SKyle Evans 260495ed39SKyle Evans A signed argument is represented in excess K: the represented value is 270495ed39SKyle Evans the written unsigned value minus K, where K is half the maximum for the 280495ed39SKyle Evans corresponding unsigned argument. 298e3e3a7aSWarner Losh ===========================================================================*/ 308e3e3a7aSWarner Losh 318e3e3a7aSWarner Losh 320495ed39SKyle Evans enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */ 338e3e3a7aSWarner Losh 348e3e3a7aSWarner Losh 358e3e3a7aSWarner Losh /* 368e3e3a7aSWarner Losh ** size and position of opcode arguments. 378e3e3a7aSWarner Losh */ 380495ed39SKyle Evans #define SIZE_C 8 390495ed39SKyle Evans #define SIZE_B 8 400495ed39SKyle Evans #define SIZE_Bx (SIZE_C + SIZE_B + 1) 418e3e3a7aSWarner Losh #define SIZE_A 8 420495ed39SKyle Evans #define SIZE_Ax (SIZE_Bx + SIZE_A) 430495ed39SKyle Evans #define SIZE_sJ (SIZE_Bx + SIZE_A) 448e3e3a7aSWarner Losh 450495ed39SKyle Evans #define SIZE_OP 7 468e3e3a7aSWarner Losh 478e3e3a7aSWarner Losh #define POS_OP 0 480495ed39SKyle Evans 498e3e3a7aSWarner Losh #define POS_A (POS_OP + SIZE_OP) 500495ed39SKyle Evans #define POS_k (POS_A + SIZE_A) 510495ed39SKyle Evans #define POS_B (POS_k + 1) 520495ed39SKyle Evans #define POS_C (POS_B + SIZE_B) 530495ed39SKyle Evans 540495ed39SKyle Evans #define POS_Bx POS_k 550495ed39SKyle Evans 568e3e3a7aSWarner Losh #define POS_Ax POS_A 578e3e3a7aSWarner Losh 580495ed39SKyle Evans #define POS_sJ POS_A 590495ed39SKyle Evans 608e3e3a7aSWarner Losh 618e3e3a7aSWarner Losh /* 628e3e3a7aSWarner Losh ** limits for opcode arguments. 630495ed39SKyle Evans ** we use (signed) 'int' to manipulate most arguments, 640495ed39SKyle Evans ** so they must fit in ints. 658e3e3a7aSWarner Losh */ 660495ed39SKyle Evans 670495ed39SKyle Evans /* Check whether type 'int' has at least 'b' bits ('b' < 32) */ 680495ed39SKyle Evans #define L_INTHASBITS(b) ((UINT_MAX >> ((b) - 1)) >= 1) 690495ed39SKyle Evans 700495ed39SKyle Evans 710495ed39SKyle Evans #if L_INTHASBITS(SIZE_Bx) 728e3e3a7aSWarner Losh #define MAXARG_Bx ((1<<SIZE_Bx)-1) 738e3e3a7aSWarner Losh #else 748e3e3a7aSWarner Losh #define MAXARG_Bx MAX_INT 758e3e3a7aSWarner Losh #endif 768e3e3a7aSWarner Losh 770495ed39SKyle Evans #define OFFSET_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */ 780495ed39SKyle Evans 790495ed39SKyle Evans 800495ed39SKyle Evans #if L_INTHASBITS(SIZE_Ax) 818e3e3a7aSWarner Losh #define MAXARG_Ax ((1<<SIZE_Ax)-1) 828e3e3a7aSWarner Losh #else 838e3e3a7aSWarner Losh #define MAXARG_Ax MAX_INT 848e3e3a7aSWarner Losh #endif 858e3e3a7aSWarner Losh 860495ed39SKyle Evans #if L_INTHASBITS(SIZE_sJ) 870495ed39SKyle Evans #define MAXARG_sJ ((1 << SIZE_sJ) - 1) 880495ed39SKyle Evans #else 890495ed39SKyle Evans #define MAXARG_sJ MAX_INT 900495ed39SKyle Evans #endif 910495ed39SKyle Evans 920495ed39SKyle Evans #define OFFSET_sJ (MAXARG_sJ >> 1) 930495ed39SKyle Evans 948e3e3a7aSWarner Losh 958e3e3a7aSWarner Losh #define MAXARG_A ((1<<SIZE_A)-1) 968e3e3a7aSWarner Losh #define MAXARG_B ((1<<SIZE_B)-1) 978e3e3a7aSWarner Losh #define MAXARG_C ((1<<SIZE_C)-1) 980495ed39SKyle Evans #define OFFSET_sC (MAXARG_C >> 1) 990495ed39SKyle Evans 1000495ed39SKyle Evans #define int2sC(i) ((i) + OFFSET_sC) 1010495ed39SKyle Evans #define sC2int(i) ((i) - OFFSET_sC) 1028e3e3a7aSWarner Losh 1038e3e3a7aSWarner Losh 1048e3e3a7aSWarner Losh /* creates a mask with 'n' 1 bits at position 'p' */ 1058e3e3a7aSWarner Losh #define MASK1(n,p) ((~((~(Instruction)0)<<(n)))<<(p)) 1068e3e3a7aSWarner Losh 1078e3e3a7aSWarner Losh /* creates a mask with 'n' 0 bits at position 'p' */ 1088e3e3a7aSWarner Losh #define MASK0(n,p) (~MASK1(n,p)) 1098e3e3a7aSWarner Losh 1108e3e3a7aSWarner Losh /* 1118e3e3a7aSWarner Losh ** the following macros help to manipulate instructions 1128e3e3a7aSWarner Losh */ 1138e3e3a7aSWarner Losh 1148e3e3a7aSWarner Losh #define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0))) 1158e3e3a7aSWarner Losh #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ 1168e3e3a7aSWarner Losh ((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP)))) 1178e3e3a7aSWarner Losh 1180495ed39SKyle Evans #define checkopm(i,m) (getOpMode(GET_OPCODE(i)) == m) 1190495ed39SKyle Evans 1200495ed39SKyle Evans 1210495ed39SKyle Evans #define getarg(i,pos,size) (cast_int(((i)>>(pos)) & MASK1(size,0))) 1228e3e3a7aSWarner Losh #define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ 1238e3e3a7aSWarner Losh ((cast(Instruction, v)<<pos)&MASK1(size,pos)))) 1248e3e3a7aSWarner Losh 1258e3e3a7aSWarner Losh #define GETARG_A(i) getarg(i, POS_A, SIZE_A) 1268e3e3a7aSWarner Losh #define SETARG_A(i,v) setarg(i, v, POS_A, SIZE_A) 1278e3e3a7aSWarner Losh 1280495ed39SKyle Evans #define GETARG_B(i) check_exp(checkopm(i, iABC), getarg(i, POS_B, SIZE_B)) 1290495ed39SKyle Evans #define GETARG_sB(i) sC2int(GETARG_B(i)) 1308e3e3a7aSWarner Losh #define SETARG_B(i,v) setarg(i, v, POS_B, SIZE_B) 1318e3e3a7aSWarner Losh 1320495ed39SKyle Evans #define GETARG_C(i) check_exp(checkopm(i, iABC), getarg(i, POS_C, SIZE_C)) 1330495ed39SKyle Evans #define GETARG_sC(i) sC2int(GETARG_C(i)) 1348e3e3a7aSWarner Losh #define SETARG_C(i,v) setarg(i, v, POS_C, SIZE_C) 1358e3e3a7aSWarner Losh 1360495ed39SKyle Evans #define TESTARG_k(i) check_exp(checkopm(i, iABC), (cast_int(((i) & (1u << POS_k))))) 1370495ed39SKyle Evans #define GETARG_k(i) check_exp(checkopm(i, iABC), getarg(i, POS_k, 1)) 1380495ed39SKyle Evans #define SETARG_k(i,v) setarg(i, v, POS_k, 1) 1390495ed39SKyle Evans 1400495ed39SKyle Evans #define GETARG_Bx(i) check_exp(checkopm(i, iABx), getarg(i, POS_Bx, SIZE_Bx)) 1418e3e3a7aSWarner Losh #define SETARG_Bx(i,v) setarg(i, v, POS_Bx, SIZE_Bx) 1428e3e3a7aSWarner Losh 1430495ed39SKyle Evans #define GETARG_Ax(i) check_exp(checkopm(i, iAx), getarg(i, POS_Ax, SIZE_Ax)) 1448e3e3a7aSWarner Losh #define SETARG_Ax(i,v) setarg(i, v, POS_Ax, SIZE_Ax) 1458e3e3a7aSWarner Losh 1460495ed39SKyle Evans #define GETARG_sBx(i) \ 1470495ed39SKyle Evans check_exp(checkopm(i, iAsBx), getarg(i, POS_Bx, SIZE_Bx) - OFFSET_sBx) 1480495ed39SKyle Evans #define SETARG_sBx(i,b) SETARG_Bx((i),cast_uint((b)+OFFSET_sBx)) 1490495ed39SKyle Evans 1500495ed39SKyle Evans #define GETARG_sJ(i) \ 1510495ed39SKyle Evans check_exp(checkopm(i, isJ), getarg(i, POS_sJ, SIZE_sJ) - OFFSET_sJ) 1520495ed39SKyle Evans #define SETARG_sJ(i,j) \ 1530495ed39SKyle Evans setarg(i, cast_uint((j)+OFFSET_sJ), POS_sJ, SIZE_sJ) 1548e3e3a7aSWarner Losh 1558e3e3a7aSWarner Losh 1560495ed39SKyle Evans #define CREATE_ABCk(o,a,b,c,k) ((cast(Instruction, o)<<POS_OP) \ 1578e3e3a7aSWarner Losh | (cast(Instruction, a)<<POS_A) \ 1588e3e3a7aSWarner Losh | (cast(Instruction, b)<<POS_B) \ 1590495ed39SKyle Evans | (cast(Instruction, c)<<POS_C) \ 1600495ed39SKyle Evans | (cast(Instruction, k)<<POS_k)) 1618e3e3a7aSWarner Losh 1628e3e3a7aSWarner Losh #define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \ 1638e3e3a7aSWarner Losh | (cast(Instruction, a)<<POS_A) \ 1648e3e3a7aSWarner Losh | (cast(Instruction, bc)<<POS_Bx)) 1658e3e3a7aSWarner Losh 1668e3e3a7aSWarner Losh #define CREATE_Ax(o,a) ((cast(Instruction, o)<<POS_OP) \ 1678e3e3a7aSWarner Losh | (cast(Instruction, a)<<POS_Ax)) 1688e3e3a7aSWarner Losh 1690495ed39SKyle Evans #define CREATE_sJ(o,j,k) ((cast(Instruction, o) << POS_OP) \ 1700495ed39SKyle Evans | (cast(Instruction, j) << POS_sJ) \ 1710495ed39SKyle Evans | (cast(Instruction, k) << POS_k)) 1728e3e3a7aSWarner Losh 1738e3e3a7aSWarner Losh 1748e3e3a7aSWarner Losh #if !defined(MAXINDEXRK) /* (for debugging only) */ 1750495ed39SKyle Evans #define MAXINDEXRK MAXARG_B 1768e3e3a7aSWarner Losh #endif 1778e3e3a7aSWarner Losh 1788e3e3a7aSWarner Losh 1798e3e3a7aSWarner Losh /* 1808e3e3a7aSWarner Losh ** invalid register that fits in 8 bits 1818e3e3a7aSWarner Losh */ 1828e3e3a7aSWarner Losh #define NO_REG MAXARG_A 1838e3e3a7aSWarner Losh 1848e3e3a7aSWarner Losh 1858e3e3a7aSWarner Losh /* 1860495ed39SKyle Evans ** R[x] - register 1870495ed39SKyle Evans ** K[x] - constant (in constant table) 1880495ed39SKyle Evans ** RK(x) == if k(i) then K[x] else R[x] 1898e3e3a7aSWarner Losh */ 1908e3e3a7aSWarner Losh 1918e3e3a7aSWarner Losh 1928e3e3a7aSWarner Losh /* 193*8c784bb8SWarner Losh ** Grep "ORDER OP" if you change these enums. Opcodes marked with a (*) 194*8c784bb8SWarner Losh ** has extra descriptions in the notes after the enumeration. 1958e3e3a7aSWarner Losh */ 1968e3e3a7aSWarner Losh 1978e3e3a7aSWarner Losh typedef enum { 1988e3e3a7aSWarner Losh /*---------------------------------------------------------------------- 1998e3e3a7aSWarner Losh name args description 2008e3e3a7aSWarner Losh ------------------------------------------------------------------------*/ 2010495ed39SKyle Evans OP_MOVE,/* A B R[A] := R[B] */ 2020495ed39SKyle Evans OP_LOADI,/* A sBx R[A] := sBx */ 2030495ed39SKyle Evans OP_LOADF,/* A sBx R[A] := (lua_Number)sBx */ 2040495ed39SKyle Evans OP_LOADK,/* A Bx R[A] := K[Bx] */ 2050495ed39SKyle Evans OP_LOADKX,/* A R[A] := K[extra arg] */ 2060495ed39SKyle Evans OP_LOADFALSE,/* A R[A] := false */ 207*8c784bb8SWarner Losh OP_LFALSESKIP,/*A R[A] := false; pc++ (*) */ 2080495ed39SKyle Evans OP_LOADTRUE,/* A R[A] := true */ 2090495ed39SKyle Evans OP_LOADNIL,/* A B R[A], R[A+1], ..., R[A+B] := nil */ 2100495ed39SKyle Evans OP_GETUPVAL,/* A B R[A] := UpValue[B] */ 2110495ed39SKyle Evans OP_SETUPVAL,/* A B UpValue[B] := R[A] */ 2128e3e3a7aSWarner Losh 2130495ed39SKyle Evans OP_GETTABUP,/* A B C R[A] := UpValue[B][K[C]:string] */ 2140495ed39SKyle Evans OP_GETTABLE,/* A B C R[A] := R[B][R[C]] */ 2150495ed39SKyle Evans OP_GETI,/* A B C R[A] := R[B][C] */ 2160495ed39SKyle Evans OP_GETFIELD,/* A B C R[A] := R[B][K[C]:string] */ 2178e3e3a7aSWarner Losh 2180495ed39SKyle Evans OP_SETTABUP,/* A B C UpValue[A][K[B]:string] := RK(C) */ 2190495ed39SKyle Evans OP_SETTABLE,/* A B C R[A][R[B]] := RK(C) */ 2200495ed39SKyle Evans OP_SETI,/* A B C R[A][B] := RK(C) */ 2210495ed39SKyle Evans OP_SETFIELD,/* A B C R[A][K[B]:string] := RK(C) */ 2228e3e3a7aSWarner Losh 2230495ed39SKyle Evans OP_NEWTABLE,/* A B C k R[A] := {} */ 2248e3e3a7aSWarner Losh 2250495ed39SKyle Evans OP_SELF,/* A B C R[A+1] := R[B]; R[A] := R[B][RK(C):string] */ 2268e3e3a7aSWarner Losh 2270495ed39SKyle Evans OP_ADDI,/* A B sC R[A] := R[B] + sC */ 2288e3e3a7aSWarner Losh 229*8c784bb8SWarner Losh OP_ADDK,/* A B C R[A] := R[B] + K[C]:number */ 230*8c784bb8SWarner Losh OP_SUBK,/* A B C R[A] := R[B] - K[C]:number */ 231*8c784bb8SWarner Losh OP_MULK,/* A B C R[A] := R[B] * K[C]:number */ 232*8c784bb8SWarner Losh OP_MODK,/* A B C R[A] := R[B] % K[C]:number */ 233*8c784bb8SWarner Losh OP_POWK,/* A B C R[A] := R[B] ^ K[C]:number */ 234*8c784bb8SWarner Losh OP_DIVK,/* A B C R[A] := R[B] / K[C]:number */ 235*8c784bb8SWarner Losh OP_IDIVK,/* A B C R[A] := R[B] // K[C]:number */ 2368e3e3a7aSWarner Losh 2370495ed39SKyle Evans OP_BANDK,/* A B C R[A] := R[B] & K[C]:integer */ 2380495ed39SKyle Evans OP_BORK,/* A B C R[A] := R[B] | K[C]:integer */ 2390495ed39SKyle Evans OP_BXORK,/* A B C R[A] := R[B] ~ K[C]:integer */ 2408e3e3a7aSWarner Losh 2410495ed39SKyle Evans OP_SHRI,/* A B sC R[A] := R[B] >> sC */ 2420495ed39SKyle Evans OP_SHLI,/* A B sC R[A] := sC << R[B] */ 2438e3e3a7aSWarner Losh 2440495ed39SKyle Evans OP_ADD,/* A B C R[A] := R[B] + R[C] */ 2450495ed39SKyle Evans OP_SUB,/* A B C R[A] := R[B] - R[C] */ 2460495ed39SKyle Evans OP_MUL,/* A B C R[A] := R[B] * R[C] */ 2470495ed39SKyle Evans OP_MOD,/* A B C R[A] := R[B] % R[C] */ 2480495ed39SKyle Evans OP_POW,/* A B C R[A] := R[B] ^ R[C] */ 2490495ed39SKyle Evans OP_DIV,/* A B C R[A] := R[B] / R[C] */ 2500495ed39SKyle Evans OP_IDIV,/* A B C R[A] := R[B] // R[C] */ 2518e3e3a7aSWarner Losh 2520495ed39SKyle Evans OP_BAND,/* A B C R[A] := R[B] & R[C] */ 2530495ed39SKyle Evans OP_BOR,/* A B C R[A] := R[B] | R[C] */ 2540495ed39SKyle Evans OP_BXOR,/* A B C R[A] := R[B] ~ R[C] */ 2550495ed39SKyle Evans OP_SHL,/* A B C R[A] := R[B] << R[C] */ 2560495ed39SKyle Evans OP_SHR,/* A B C R[A] := R[B] >> R[C] */ 2578e3e3a7aSWarner Losh 258*8c784bb8SWarner Losh OP_MMBIN,/* A B C call C metamethod over R[A] and R[B] (*) */ 2590495ed39SKyle Evans OP_MMBINI,/* A sB C k call C metamethod over R[A] and sB */ 2600495ed39SKyle Evans OP_MMBINK,/* A B C k call C metamethod over R[A] and K[B] */ 2618e3e3a7aSWarner Losh 2620495ed39SKyle Evans OP_UNM,/* A B R[A] := -R[B] */ 2630495ed39SKyle Evans OP_BNOT,/* A B R[A] := ~R[B] */ 2640495ed39SKyle Evans OP_NOT,/* A B R[A] := not R[B] */ 2650495ed39SKyle Evans OP_LEN,/* A B R[A] := #R[B] (length operator) */ 2668e3e3a7aSWarner Losh 2670495ed39SKyle Evans OP_CONCAT,/* A B R[A] := R[A].. ... ..R[A + B - 1] */ 2688e3e3a7aSWarner Losh 2690495ed39SKyle Evans OP_CLOSE,/* A close all upvalues >= R[A] */ 2700495ed39SKyle Evans OP_TBC,/* A mark variable A "to be closed" */ 2710495ed39SKyle Evans OP_JMP,/* sJ pc += sJ */ 2720495ed39SKyle Evans OP_EQ,/* A B k if ((R[A] == R[B]) ~= k) then pc++ */ 2730495ed39SKyle Evans OP_LT,/* A B k if ((R[A] < R[B]) ~= k) then pc++ */ 2740495ed39SKyle Evans OP_LE,/* A B k if ((R[A] <= R[B]) ~= k) then pc++ */ 2750495ed39SKyle Evans 2760495ed39SKyle Evans OP_EQK,/* A B k if ((R[A] == K[B]) ~= k) then pc++ */ 2770495ed39SKyle Evans OP_EQI,/* A sB k if ((R[A] == sB) ~= k) then pc++ */ 2780495ed39SKyle Evans OP_LTI,/* A sB k if ((R[A] < sB) ~= k) then pc++ */ 2790495ed39SKyle Evans OP_LEI,/* A sB k if ((R[A] <= sB) ~= k) then pc++ */ 2800495ed39SKyle Evans OP_GTI,/* A sB k if ((R[A] > sB) ~= k) then pc++ */ 2810495ed39SKyle Evans OP_GEI,/* A sB k if ((R[A] >= sB) ~= k) then pc++ */ 2820495ed39SKyle Evans 2830495ed39SKyle Evans OP_TEST,/* A k if (not R[A] == k) then pc++ */ 284*8c784bb8SWarner Losh OP_TESTSET,/* A B k if (not R[B] == k) then pc++ else R[A] := R[B] (*) */ 2850495ed39SKyle Evans 2860495ed39SKyle Evans OP_CALL,/* A B C R[A], ... ,R[A+C-2] := R[A](R[A+1], ... ,R[A+B-1]) */ 2870495ed39SKyle Evans OP_TAILCALL,/* A B C k return R[A](R[A+1], ... ,R[A+B-1]) */ 2880495ed39SKyle Evans 2890495ed39SKyle Evans OP_RETURN,/* A B C k return R[A], ... ,R[A+B-2] (see note) */ 2900495ed39SKyle Evans OP_RETURN0,/* return */ 2910495ed39SKyle Evans OP_RETURN1,/* A return R[A] */ 2920495ed39SKyle Evans 2930495ed39SKyle Evans OP_FORLOOP,/* A Bx update counters; if loop continues then pc-=Bx; */ 2940495ed39SKyle Evans OP_FORPREP,/* A Bx <check values and prepare counters>; 2950495ed39SKyle Evans if not to run then pc+=Bx+1; */ 2960495ed39SKyle Evans 2970495ed39SKyle Evans OP_TFORPREP,/* A Bx create upvalue for R[A + 3]; pc+=Bx */ 2980495ed39SKyle Evans OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */ 2990495ed39SKyle Evans OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */ 3000495ed39SKyle Evans 3010495ed39SKyle Evans OP_SETLIST,/* A B C k R[A][C+i] := R[A+i], 1 <= i <= B */ 3020495ed39SKyle Evans 3030495ed39SKyle Evans OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */ 3040495ed39SKyle Evans 3050495ed39SKyle Evans OP_VARARG,/* A C R[A], R[A+1], ..., R[A+C-2] = vararg */ 3060495ed39SKyle Evans 3070495ed39SKyle Evans OP_VARARGPREP,/*A (adjust vararg parameters) */ 3088e3e3a7aSWarner Losh 3098e3e3a7aSWarner Losh OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ 3108e3e3a7aSWarner Losh } OpCode; 3118e3e3a7aSWarner Losh 3128e3e3a7aSWarner Losh 3130495ed39SKyle Evans #define NUM_OPCODES ((int)(OP_EXTRAARG) + 1) 3148e3e3a7aSWarner Losh 3158e3e3a7aSWarner Losh 3168e3e3a7aSWarner Losh 3178e3e3a7aSWarner Losh /*=========================================================================== 3188e3e3a7aSWarner Losh Notes: 319*8c784bb8SWarner Losh 320*8c784bb8SWarner Losh (*) Opcode OP_LFALSESKIP is used to convert a condition to a boolean 321*8c784bb8SWarner Losh value, in a code equivalent to (not cond ? false : true). (It 322*8c784bb8SWarner Losh produces false and skips the next instruction producing true.) 323*8c784bb8SWarner Losh 324*8c784bb8SWarner Losh (*) Opcodes OP_MMBIN and variants follow each arithmetic and 325*8c784bb8SWarner Losh bitwise opcode. If the operation succeeds, it skips this next 326*8c784bb8SWarner Losh opcode. Otherwise, this opcode calls the corresponding metamethod. 327*8c784bb8SWarner Losh 328*8c784bb8SWarner Losh (*) Opcode OP_TESTSET is used in short-circuit expressions that need 329*8c784bb8SWarner Losh both to jump and to produce a value, such as (a = b or c). 330*8c784bb8SWarner Losh 3310495ed39SKyle Evans (*) In OP_CALL, if (B == 0) then B = top - A. If (C == 0), then 3320495ed39SKyle Evans 'top' is set to last_result+1, so next open instruction (OP_CALL, 3330495ed39SKyle Evans OP_RETURN*, OP_SETLIST) may use 'top'. 3348e3e3a7aSWarner Losh 3350495ed39SKyle Evans (*) In OP_VARARG, if (C == 0) then use actual number of varargs and 3368e3e3a7aSWarner Losh set top (like in OP_CALL with C == 0). 3378e3e3a7aSWarner Losh 3388e3e3a7aSWarner Losh (*) In OP_RETURN, if (B == 0) then return up to 'top'. 3398e3e3a7aSWarner Losh 3400495ed39SKyle Evans (*) In OP_LOADKX and OP_NEWTABLE, the next instruction is always 3410495ed39SKyle Evans OP_EXTRAARG. 3428e3e3a7aSWarner Losh 3430495ed39SKyle Evans (*) In OP_SETLIST, if (B == 0) then real B = 'top'; if k, then 3440495ed39SKyle Evans real C = EXTRAARG _ C (the bits of EXTRAARG concatenated with the 3450495ed39SKyle Evans bits of C). 3468e3e3a7aSWarner Losh 3470495ed39SKyle Evans (*) In OP_NEWTABLE, B is log2 of the hash size (which is always a 3480495ed39SKyle Evans power of 2) plus 1, or zero for size zero. If not k, the array size 3490495ed39SKyle Evans is C. Otherwise, the array size is EXTRAARG _ C. 3500495ed39SKyle Evans 3510495ed39SKyle Evans (*) For comparisons, k specifies what condition the test should accept 3528e3e3a7aSWarner Losh (true or false). 3538e3e3a7aSWarner Losh 3540495ed39SKyle Evans (*) In OP_MMBINI/OP_MMBINK, k means the arguments were flipped 3550495ed39SKyle Evans (the constant is the first operand). 3560495ed39SKyle Evans 3578e3e3a7aSWarner Losh (*) All 'skips' (pc++) assume that next instruction is a jump. 3588e3e3a7aSWarner Losh 3590495ed39SKyle Evans (*) In instructions OP_RETURN/OP_TAILCALL, 'k' specifies that the 3600495ed39SKyle Evans function builds upvalues, which may need to be closed. C > 0 means 3610495ed39SKyle Evans the function is vararg, so that its 'func' must be corrected before 3620495ed39SKyle Evans returning; in this case, (C - 1) is its number of fixed parameters. 3630495ed39SKyle Evans 3640495ed39SKyle Evans (*) In comparisons with an immediate operand, C signals whether the 3650495ed39SKyle Evans original operand was a float. (It must be corrected in case of 3660495ed39SKyle Evans metamethods.) 3670495ed39SKyle Evans 3688e3e3a7aSWarner Losh ===========================================================================*/ 3698e3e3a7aSWarner Losh 3708e3e3a7aSWarner Losh 3718e3e3a7aSWarner Losh /* 3728e3e3a7aSWarner Losh ** masks for instruction properties. The format is: 3730495ed39SKyle Evans ** bits 0-2: op mode 3740495ed39SKyle Evans ** bit 3: instruction set register A 3750495ed39SKyle Evans ** bit 4: operator is a test (next instruction must be a jump) 3760495ed39SKyle Evans ** bit 5: instruction uses 'L->top' set by previous instruction (when B == 0) 3770495ed39SKyle Evans ** bit 6: instruction sets 'L->top' for next instruction (when C == 0) 3780495ed39SKyle Evans ** bit 7: instruction is an MM instruction (call a metamethod) 3798e3e3a7aSWarner Losh */ 3808e3e3a7aSWarner Losh 3810495ed39SKyle Evans LUAI_DDEC(const lu_byte luaP_opmodes[NUM_OPCODES];) 3828e3e3a7aSWarner Losh 3830495ed39SKyle Evans #define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 7)) 3840495ed39SKyle Evans #define testAMode(m) (luaP_opmodes[m] & (1 << 3)) 3850495ed39SKyle Evans #define testTMode(m) (luaP_opmodes[m] & (1 << 4)) 3860495ed39SKyle Evans #define testITMode(m) (luaP_opmodes[m] & (1 << 5)) 3870495ed39SKyle Evans #define testOTMode(m) (luaP_opmodes[m] & (1 << 6)) 3880495ed39SKyle Evans #define testMMMode(m) (luaP_opmodes[m] & (1 << 7)) 3898e3e3a7aSWarner Losh 3900495ed39SKyle Evans /* "out top" (set top for next instruction) */ 3910495ed39SKyle Evans #define isOT(i) \ 3920495ed39SKyle Evans ((testOTMode(GET_OPCODE(i)) && GETARG_C(i) == 0) || \ 3930495ed39SKyle Evans GET_OPCODE(i) == OP_TAILCALL) 3948e3e3a7aSWarner Losh 3950495ed39SKyle Evans /* "in top" (uses top from previous instruction) */ 3960495ed39SKyle Evans #define isIT(i) (testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0) 3978e3e3a7aSWarner Losh 3980495ed39SKyle Evans #define opmode(mm,ot,it,t,a,m) \ 3990495ed39SKyle Evans (((mm) << 7) | ((ot) << 6) | ((it) << 5) | ((t) << 4) | ((a) << 3) | (m)) 4008e3e3a7aSWarner Losh 4018e3e3a7aSWarner Losh 4028e3e3a7aSWarner Losh /* number of list items to accumulate before a SETLIST instruction */ 4038e3e3a7aSWarner Losh #define LFIELDS_PER_FLUSH 50 4048e3e3a7aSWarner Losh 4058e3e3a7aSWarner Losh #endif 406