rlm@1: /* rlm@1: ** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $ rlm@1: ** Opcodes for Lua virtual machine rlm@1: ** See Copyright Notice in lua.h rlm@1: */ rlm@1: rlm@1: #ifndef lopcodes_h rlm@1: #define lopcodes_h rlm@1: rlm@1: #include "llimits.h" rlm@1: rlm@1: rlm@1: /*=========================================================================== rlm@1: We assume that instructions are unsigned numbers. rlm@1: All instructions have an opcode in the first 6 bits. rlm@1: Instructions can have the following fields: rlm@1: `A' : 8 bits rlm@1: `B' : 9 bits rlm@1: `C' : 9 bits rlm@1: `Bx' : 18 bits (`B' and `C' together) rlm@1: `sBx' : signed Bx rlm@1: rlm@1: A signed argument is represented in excess K; that is, the number rlm@1: value is the unsigned value minus K. K is exactly the maximum value rlm@1: for that argument (so that -max is represented by 0, and +max is rlm@1: represented by 2*max), which is half the maximum for the corresponding rlm@1: unsigned argument. rlm@1: ===========================================================================*/ rlm@1: rlm@1: rlm@1: enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ rlm@1: rlm@1: rlm@1: /* rlm@1: ** size and position of opcode arguments. rlm@1: */ rlm@1: #define SIZE_C 9 rlm@1: #define SIZE_B 9 rlm@1: #define SIZE_Bx (SIZE_C + SIZE_B) rlm@1: #define SIZE_A 8 rlm@1: rlm@1: #define SIZE_OP 6 rlm@1: rlm@1: #define POS_OP 0 rlm@1: #define POS_A (POS_OP + SIZE_OP) rlm@1: #define POS_C (POS_A + SIZE_A) rlm@1: #define POS_B (POS_C + SIZE_C) rlm@1: #define POS_Bx POS_C rlm@1: rlm@1: rlm@1: /* rlm@1: ** limits for opcode arguments. rlm@1: ** we use (signed) int to manipulate most arguments, rlm@1: ** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) rlm@1: */ rlm@1: #if SIZE_Bx < LUAI_BITSINT-1 rlm@1: #define MAXARG_Bx ((1<>1) /* `sBx' is signed */ rlm@1: #else rlm@1: #define MAXARG_Bx MAX_INT rlm@1: #define MAXARG_sBx MAX_INT rlm@1: #endif rlm@1: rlm@1: rlm@1: #define MAXARG_A ((1<>POS_OP) & MASK1(SIZE_OP,0))) rlm@1: #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ rlm@1: ((cast(Instruction, o)<>POS_A) & MASK1(SIZE_A,0))) rlm@1: #define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ rlm@1: ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0))) rlm@1: #define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ rlm@1: ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) rlm@1: #define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ rlm@1: ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) rlm@1: #define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ rlm@1: ((cast(Instruction, b)< C) then pc++ */ rlm@1: OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ rlm@1: rlm@1: OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ rlm@1: OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ rlm@1: OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ rlm@1: rlm@1: OP_FORLOOP,/* A sBx R(A)+=R(A+2); rlm@1: if R(A) =) R(A)*/ rlm@1: OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ rlm@1: rlm@1: OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ rlm@1: } OpCode; rlm@1: rlm@1: rlm@1: #define NUM_OPCODES (cast(int, OP_VARARG) + 1) rlm@1: rlm@1: rlm@1: rlm@1: /*=========================================================================== rlm@1: Notes: rlm@1: (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, rlm@1: and can be 0: OP_CALL then sets `top' to last_result+1, so rlm@1: next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. rlm@1: rlm@1: (*) In OP_VARARG, if (B == 0) then use actual number of varargs and rlm@1: set top (like in OP_CALL with C == 0). rlm@1: rlm@1: (*) In OP_RETURN, if (B == 0) then return up to `top' rlm@1: rlm@1: (*) In OP_SETLIST, if (B == 0) then B = `top'; rlm@1: if (C == 0) then next `instruction' is real C rlm@1: rlm@1: (*) For comparisons, A specifies what condition the test should accept rlm@1: (true or false). rlm@1: rlm@1: (*) All `skips' (pc++) assume that next instruction is a jump rlm@1: ===========================================================================*/ rlm@1: rlm@1: rlm@1: /* rlm@1: ** masks for instruction properties. The format is: rlm@1: ** bits 0-1: op mode rlm@1: ** bits 2-3: C arg mode rlm@1: ** bits 4-5: B arg mode rlm@1: ** bit 6: instruction set register A rlm@1: ** bit 7: operator is a test rlm@1: */ rlm@1: rlm@1: enum OpArgMask { rlm@1: OpArgN, /* argument is not used */ rlm@1: OpArgU, /* argument is used */ rlm@1: OpArgR, /* argument is a register or a jump offset */ rlm@1: OpArgK /* argument is a constant or register/constant */ rlm@1: }; rlm@1: rlm@1: LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; rlm@1: rlm@1: #define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) rlm@1: #define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) rlm@1: #define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) rlm@1: #define testAMode(m) (luaP_opmodes[m] & (1 << 6)) rlm@1: #define testTMode(m) (luaP_opmodes[m] & (1 << 7)) rlm@1: rlm@1: rlm@1: LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ rlm@1: rlm@1: rlm@1: /* number of list items to accumulate before a SETLIST instruction */ rlm@1: #define LFIELDS_PER_FLUSH 50 rlm@1: rlm@1: rlm@1: #endif