xref: /freebsd/contrib/lua/src/lopcodes.h (revision a9490b81b032b43cdb3c8c76b4d01bbad9ff82c1)
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