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) | 24*a9490b81SWarner Losh isJ sJ (signed)(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 /* 1938c784bb8SWarner Losh ** Grep "ORDER OP" if you change these enums. Opcodes marked with a (*) 1948c784bb8SWarner 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 */ 2078c784bb8SWarner 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 2298c784bb8SWarner Losh OP_ADDK,/* A B C R[A] := R[B] + K[C]:number */ 2308c784bb8SWarner Losh OP_SUBK,/* A B C R[A] := R[B] - K[C]:number */ 2318c784bb8SWarner Losh OP_MULK,/* A B C R[A] := R[B] * K[C]:number */ 2328c784bb8SWarner Losh OP_MODK,/* A B C R[A] := R[B] % K[C]:number */ 2338c784bb8SWarner Losh OP_POWK,/* A B C R[A] := R[B] ^ K[C]:number */ 2348c784bb8SWarner Losh OP_DIVK,/* A B C R[A] := R[B] / K[C]:number */ 2358c784bb8SWarner 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 2588c784bb8SWarner 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++ */ 2848c784bb8SWarner 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: 3198c784bb8SWarner Losh 3208c784bb8SWarner Losh (*) Opcode OP_LFALSESKIP is used to convert a condition to a boolean 3218c784bb8SWarner Losh value, in a code equivalent to (not cond ? false : true). (It 3228c784bb8SWarner Losh produces false and skips the next instruction producing true.) 3238c784bb8SWarner Losh 3248c784bb8SWarner Losh (*) Opcodes OP_MMBIN and variants follow each arithmetic and 3258c784bb8SWarner Losh bitwise opcode. If the operation succeeds, it skips this next 3268c784bb8SWarner Losh opcode. Otherwise, this opcode calls the corresponding metamethod. 3278c784bb8SWarner Losh 3288c784bb8SWarner Losh (*) Opcode OP_TESTSET is used in short-circuit expressions that need 3298c784bb8SWarner Losh both to jump and to produce a value, such as (a = b or c). 3308c784bb8SWarner 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