/* ** $Id: lopcodes.h,v 1.98 2002/06/06 18:17:33 roberto Exp roberto $ ** 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) `Bx' : 18 bits (`B' and `C' together) `sBx' : signed Bx 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, iABx, iAsBx}; /* basic instruction format */ /* ** size and position of opcode arguments. */ #define SIZE_C 10 #define SIZE_B 8 #define SIZE_Bx (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_Bx 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_Bx < BITS_INT-1 #define MAXARG_Bx ((1<>1) /* `sBx' is signed */ #else #define MAXARG_Bx MAX_INT #define MAXARG_sBx 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_Bx) & MASK1(SIZE_Bx,0))) #define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ ((cast(Instruction, b)< R/K(C)) ~= B) then pc++ */ OP_GE,/* A B C if ((R(A) >= R/K(C)) ~= B) then pc++ */ OP_TEST,/* A B C if (R(C) <=> B) then R(A) := R(C) else pc++ */ OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ OP_TAILCALL,/* A B return R(A)(R(A+1), ... ,R(A+B-1)) */ OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ OP_FORLOOP,/* A sBx R(A)+=R(A+2); if R(A) =) R(A)*/ OP_CLOSURE/* A Bx R(A) := closure(KPROTO[Bx], 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' (3) For comparisons, B specifies what conditions the test should accept. (4) All `skips' (pc++) assume that next instruction is a jump ===========================================================================*/ /* ** masks for instruction properties */ enum OpModeMask { OpModeBreg = 2, /* B is a register */ OpModeCreg, /* C is a register/constant */ OpModesetA, /* instruction set register A */ OpModeK, /* Bx 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))) #ifdef LUA_OPNAMES extern const char *const luaP_opnames[]; /* opcode names */ #endif /* number of list items to accumulate before a SETLIST instruction */ /* (must be a power of 2) */ #define LFIELDS_PER_FLUSH 32 #endif