/* ** $Id: lopcodes.h,v 1.85 2002/01/09 22:02:47 roberto Exp $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ #ifndef lopcodes_h #define lopcodes_h #include "llimits.h" /*=========================================================================== We assume that instructions are unsigned numbers. All instructions have an opcode in the first 6 bits. Instructions can have the following fields: `A' : 8 bits (25-32) `B' : 8 bits (17-24) `C' : 10 bits (7-16) `Bc' : 18 bits (`B' and `C' together) `sBc' : signed Bc A signed argument is represented in excess K; that is, the number value is the unsigned value minus K. K is exactly the maximum value for that argument (so that -max is represented by 0, and +max is represented by 2*max), which is half the maximum for the corresponding unsigned argument. ===========================================================================*/ enum OpMode {iABC, iABc, iAsBc}; /* basic instruction format */ /* ** size and position of opcode arguments. */ #define SIZE_C 10 #define SIZE_B 8 #define SIZE_Bc (SIZE_C + SIZE_B) #define SIZE_A 8 #define SIZE_OP 6 #define POS_C SIZE_OP #define POS_B (POS_C + SIZE_C) #define POS_Bc POS_C #define POS_A (POS_B + SIZE_B) /* ** limits for opcode arguments. ** we use (signed) int to manipulate most arguments, ** so they must fit in BITS_INT-1 bits (-1 for sign) */ #if SIZE_Bc < BITS_INT-1 #define MAXARG_Bc ((1<>1) /* `sBc' is signed */ #else #define MAXARG_Bc MAX_INT #define MAXARG_sBc MAX_INT #endif #define MAXARG_A ((1<>POS_A)) #define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ (cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0))) #define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ (cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) #define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ (cast(Instruction, b)<>POS_Bc) & MASK1(SIZE_Bc,0))) #define SETARG_Bc(i,b) ((i) = (((i)&MASK0(SIZE_Bc,POS_Bc)) | \ (cast(Instruction, b)< R/K(C)) then pc++ */ OP_TESTGE,/* A C if not (R(A) >= R/K(C)) then pc++ */ OP_TESTT,/* A B if (R(B)) then R(A) := R(B) else pc++ */ OP_TESTF,/* A B if not (R(B)) then R(A) := R(B) else pc++ */ OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1))*/ OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see (3)) */ OP_FORPREP,/* A sBc */ OP_FORLOOP,/* A sBc */ OP_TFORPREP,/* A sBc */ OP_TFORLOOP,/* A sBc */ OP_SETLIST,/* A Bc R(A)[Bc-Bc%FPF+i] := R(A+i), 1 <= i <= Bc%FPF+1 */ OP_SETLISTO,/* A Bc */ OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/ OP_CLOSURE/* A Bc R(A) := closure(KPROTO[Bc], R(A), ... ,R(A+n)) */ } OpCode; #define NUM_OPCODES (cast(int, OP_CLOSURE+1)) /*=========================================================================== Notes: (1) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, and can be 0: OP_CALL then sets `top' to last_result+1, so next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. (2) In OP_RETURN, if (B == 0) then return up to `top' ===========================================================================*/ /* ** masks for instruction properties */ enum OpModeMask { OpModeBreg = 2, /* B is a register */ OpModeCreg, /* C is a register/constant */ OpModesetA, /* instruction set register A */ OpModeK, /* Bc is a constant */ OpModeT /* operator is a test */ }; extern const lu_byte luaP_opmodes[NUM_OPCODES]; #define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) #define testOpMode(m, b) (luaP_opmodes[m] & (1 << (b))) /* ** constant instructions */ extern const Instruction luaP_yieldop; /* ** opcode names (only included when compiled with LUA_OPNAMES) */ extern const char *const luaP_opnames[]; #endif