diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-06-05 15:17:01 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-06-05 15:17:01 -0300 |
| commit | 762d059a13d83eb367238a6115bbb4f5f13fcb49 (patch) | |
| tree | f35fdf0675b791865d0d4800522b172903b34803 /lopcodes.h | |
| parent | 572a69b6afbd368beab8844bc876b0f9690b5253 (diff) | |
| download | lua-762d059a13d83eb367238a6115bbb4f5f13fcb49.tar.gz lua-762d059a13d83eb367238a6115bbb4f5f13fcb49.tar.bz2 lua-762d059a13d83eb367238a6115bbb4f5f13fcb49.zip | |
new implementation for the Virtual Machine
Diffstat (limited to 'lopcodes.h')
| -rw-r--r-- | lopcodes.h | 219 |
1 files changed, 127 insertions, 92 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lopcodes.h,v 1.71 2001/03/07 13:22:55 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.72 2001/04/06 18:25:00 roberto Exp roberto $ |
| 3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -12,29 +12,55 @@ | |||
| 12 | 12 | ||
| 13 | /*=========================================================================== | 13 | /*=========================================================================== |
| 14 | We assume that instructions are unsigned numbers. | 14 | We assume that instructions are unsigned numbers. |
| 15 | All instructions have an opcode in the first 6 bits. Moreover, | 15 | All instructions have an opcode in the first 6 bits. |
| 16 | an instruction can have 0, 1, or 2 arguments. Instructions can | 16 | Instructions can have the following fields: |
| 17 | have the following types: | 17 | `A' : 8 bits (25-32) |
| 18 | type 0: no arguments | 18 | `B' : 8 bits (17-24) |
| 19 | type 1: 1 unsigned argument in the higher bits (called `U') | 19 | `C' : 10 bits (7-16) |
| 20 | type 2: 1 signed argument in the higher bits (`S') | 20 | `Bc' : 18 bits (`B' and `C' together) |
| 21 | type 3: 1st unsigned argument in the higher bits (`A') | 21 | `sBc' : signed Bc |
| 22 | 2nd unsigned argument in the middle bits (`B') | ||
| 23 | 22 | ||
| 24 | A signed argument is represented in excess K; that is, the number | 23 | A signed argument is represented in excess K; that is, the number |
| 25 | value is the unsigned value minus K. K is exactly the maximum value | 24 | value is the unsigned value minus K. K is exactly the maximum value |
| 26 | for that argument (so that -max is represented by 0, and +max is | 25 | for that argument (so that -max is represented by 0, and +max is |
| 27 | represented by 2*max), which is half the maximum for the corresponding | 26 | represented by 2*max), which is half the maximum for the corresponding |
| 28 | unsigned argument. | 27 | unsigned argument. |
| 29 | |||
| 30 | The size of each argument is defined in `llimits.h'. The usual is an | ||
| 31 | instruction with 32 bits, U arguments with 26 bits (32-6), B arguments | ||
| 32 | with 9 bits, and A arguments with 17 bits (32-6-9). For small | ||
| 33 | installations, the instruction size can be 16, so U has 10 bits, | ||
| 34 | and A and B have 5 bits each. | ||
| 35 | ===========================================================================*/ | 28 | ===========================================================================*/ |
| 36 | 29 | ||
| 37 | 30 | ||
| 31 | /* | ||
| 32 | ** size and position of opcode arguments. | ||
| 33 | */ | ||
| 34 | #define SIZE_C 10 | ||
| 35 | #define SIZE_B 8 | ||
| 36 | #define SIZE_Bc (SIZE_C + SIZE_B) | ||
| 37 | #define SIZE_A 8 | ||
| 38 | |||
| 39 | #define SIZE_OP 6 | ||
| 40 | |||
| 41 | #define POS_C SIZE_OP | ||
| 42 | #define POS_B (POS_C + SIZE_C) | ||
| 43 | #define POS_Bc POS_C | ||
| 44 | #define POS_A (POS_B + SIZE_B) | ||
| 45 | |||
| 46 | |||
| 47 | /* | ||
| 48 | ** limits for opcode arguments. | ||
| 49 | ** we use (signed) int to manipulate most arguments, | ||
| 50 | ** so they must fit in BITS_INT-1 bits (-1 for sign) | ||
| 51 | */ | ||
| 52 | #if SIZE_Bc < BITS_INT-1 | ||
| 53 | #define MAXARG_Bc ((1<<SIZE_Bc)-1) | ||
| 54 | #define MAXARG_sBc (MAXARG_Bc>>1) /* `sBc' is signed */ | ||
| 55 | #else | ||
| 56 | #define MAXARG_Bc MAX_INT | ||
| 57 | #define MAXARG_sBc MAX_INT | ||
| 58 | #endif | ||
| 59 | |||
| 60 | |||
| 61 | #define MAXARG_A ((1<<SIZE_A)-1) | ||
| 62 | #define MAXARG_B ((1<<SIZE_B)-1) | ||
| 63 | #define MAXARG_C ((1<<SIZE_C)-1) | ||
| 38 | 64 | ||
| 39 | 65 | ||
| 40 | /* creates a mask with `n' 1 bits at position `p' */ | 66 | /* creates a mask with `n' 1 bits at position `p' */ |
| @@ -47,120 +73,129 @@ | |||
| 47 | ** the following macros help to manipulate instructions | 73 | ** the following macros help to manipulate instructions |
| 48 | */ | 74 | */ |
| 49 | 75 | ||
| 50 | #define CREATE_0(o) ((Instruction)(o)) | ||
| 51 | #define GET_OPCODE(i) ((OpCode)((i)&MASK1(SIZE_OP,0))) | 76 | #define GET_OPCODE(i) ((OpCode)((i)&MASK1(SIZE_OP,0))) |
| 52 | #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,0)) | (Instruction)(o))) | 77 | #define SET_OPCODE(i,o) (((i)&MASK0(SIZE_OP,0)) | (Instruction)(o)) |
| 53 | |||
| 54 | #define CREATE_U(o,u) ((Instruction)(o) | ((Instruction)(u)<<POS_U)) | ||
| 55 | #define GETARG_U(i) ((int)((i)>>POS_U)) | ||
| 56 | #define SETARG_U(i,u) ((i) = (((i)&MASK0(SIZE_U,POS_U)) | \ | ||
| 57 | ((Instruction)(u)<<POS_U))) | ||
| 58 | 78 | ||
| 59 | #define CREATE_S(o,s) CREATE_U((o),(s)+MAXARG_S) | ||
| 60 | #define GETARG_S(i) (GETARG_U(i)-MAXARG_S) | ||
| 61 | #define SETARG_S(i,s) SETARG_U((i),(s)+MAXARG_S) | ||
| 62 | |||
| 63 | |||
| 64 | #define CREATE_AB(o,a,b) ((Instruction)(o) | ((Instruction)(a)<<POS_A) \ | ||
| 65 | | ((Instruction)(b)<<POS_B)) | ||
| 66 | #define GETARG_A(i) ((int)((i)>>POS_A)) | 79 | #define GETARG_A(i) ((int)((i)>>POS_A)) |
| 67 | #define SETARG_A(i,a) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ | 80 | #define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ |
| 68 | ((Instruction)(a)<<POS_A))) | 81 | ((Instruction)(u)<<POS_A))) |
| 82 | |||
| 69 | #define GETARG_B(i) ((int)(((i)>>POS_B) & MASK1(SIZE_B,0))) | 83 | #define GETARG_B(i) ((int)(((i)>>POS_B) & MASK1(SIZE_B,0))) |
| 70 | #define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ | 84 | #define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ |
| 71 | ((Instruction)(b)<<POS_B))) | 85 | ((Instruction)(b)<<POS_B))) |
| 72 | 86 | ||
| 87 | #define GETARG_C(i) ((int)(((i)>>POS_C) & MASK1(SIZE_C,0))) | ||
| 88 | #define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ | ||
| 89 | ((Instruction)(b)<<POS_C))) | ||
| 90 | |||
| 91 | #define GETARG_Bc(i) ((int)(((i)>>POS_Bc) & MASK1(SIZE_Bc,0))) | ||
| 92 | #define SETARG_Bc(i,b) ((i) = (((i)&MASK0(SIZE_Bc,POS_Bc)) | \ | ||
| 93 | ((Instruction)(b)<<POS_Bc))) | ||
| 94 | |||
| 95 | #define GETARG_sBc(i) (GETARG_Bc(i)-MAXARG_sBc) | ||
| 96 | #define SETARG_sBc(i,b) SETARG_Bc((i),(b)+MAXARG_sBc) | ||
| 97 | |||
| 98 | |||
| 99 | #define CREATE_ABC(o,a,b,c) ((Instruction)(o) \ | ||
| 100 | | ((Instruction)(a)<<POS_A) \ | ||
| 101 | | ((Instruction)(b)<<POS_B) \ | ||
| 102 | | ((Instruction)(c)<<POS_C)) | ||
| 103 | |||
| 104 | #define CREATE_ABc(o,a,bc) ((Instruction)(o) \ | ||
| 105 | | ((Instruction)(a)<<POS_A) \ | ||
| 106 | | ((Instruction)(bc)<<POS_Bc)) | ||
| 107 | |||
| 108 | |||
| 109 | |||
| 73 | 110 | ||
| 74 | /* | 111 | /* |
| 75 | ** K = U argument used as index to `kstr' | 112 | ** an invalid register that fits in 8 bits |
| 76 | ** J = S argument used as jump offset (relative to pc of next instruction) | 113 | */ |
| 77 | ** L = unsigned argument used as index of local variable | 114 | #define NO_REG MAXARG_A |
| 78 | ** N = U argument used as index to `knum' | 115 | |
| 116 | |||
| 117 | /* | ||
| 118 | ** R(x) - register | ||
| 119 | ** Kst(x) - constant (in constant table) | ||
| 120 | ** R/K(x) == if x < MAXSTACK then R(x) else Kst(x-MAXSTACK) | ||
| 79 | */ | 121 | */ |
| 80 | 122 | ||
| 81 | typedef enum { | 123 | typedef enum { |
| 82 | /*---------------------------------------------------------------------- | 124 | /*---------------------------------------------------------------------- |
| 83 | name args stack before stack after side effects | 125 | name args description |
| 84 | ------------------------------------------------------------------------*/ | 126 | ------------------------------------------------------------------------*/ |
| 85 | OP_RETURN,/* U v_n-v_x(at u) (return) returns v_x-v_n */ | 127 | OP_MOVE,/* A B R(A) := R(B) */ |
| 86 | 128 | OP_LOADK,/* A Bc R(A) := Kst(Bc) */ | |
| 87 | OP_CALL,/* A B v_n-v_1 f(at a) r_b-r_1 f(v1,...,v_n) */ | 129 | OP_LOADINT,/* A sBc R(A) := (Number)sBc */ |
| 88 | 130 | OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */ | |
| 89 | OP_PUSHNIL,/* U - nil_1-nil_u */ | 131 | OP_LOADUPVAL,/* A Bc R(A) := UpValue[Bc] */ |
| 90 | OP_POP,/* U a_u-a_1 - */ | ||
| 91 | 132 | ||
| 92 | OP_PUSHINT,/* S - (lua_Number)s */ | 133 | OP_GETGLOBAL,/* A Bc R(A) := Gbl[Kst(Bc)] */ |
| 93 | OP_PUSHSTRING,/* K - KSTR[k] */ | 134 | OP_GETTABLE,/* A B C R(A) := R(B)[R/K(C)] */ |
| 94 | OP_PUSHNUM,/* N - KNUM[n] */ | ||
| 95 | OP_PUSHNEGNUM,/* N - -KNUM[n] */ | ||
| 96 | 135 | ||
| 97 | OP_PUSHUPVALUE,/* U - Closure[u] */ | 136 | OP_SETGLOBAL,/* A Bc Gbl[Kst(Bc)] := R(A) */ |
| 137 | OP_SETTABLE,/* A B C R(B)[R/K(C)] := R(A) */ | ||
| 98 | 138 | ||
| 99 | OP_GETLOCAL,/* L - LOC[l] */ | 139 | OP_NEWTABLE,/* A Bc R(A) := {} (size = Bc) */ |
| 100 | OP_GETGLOBAL,/* K - VAR[KSTR[k]] */ | ||
| 101 | 140 | ||
| 102 | OP_GETTABLE,/* - i t t[i] */ | 141 | OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[R/K(C)] */ |
| 103 | OP_GETDOTTED,/* K t t[KSTR[k]] */ | ||
| 104 | OP_GETINDEXED,/* L t t[LOC[l]] */ | ||
| 105 | OP_PUSHSELF,/* K t t t[KSTR[k]] */ | ||
| 106 | 142 | ||
| 107 | OP_CREATETABLE,/* U - newarray(size = u) */ | 143 | OP_ADD,/* A B C R(A) := R(B) + R/K(C) */ |
| 144 | OP_SUB,/* A B C R(A) := R(B) - R/K(C) */ | ||
| 145 | OP_MUL,/* A B C R(A) := R(B) * R/K(C) */ | ||
| 146 | OP_DIV,/* A B C R(A) := R(B) / R/K(C) */ | ||
| 147 | OP_POW,/* A B C R(A) := R(B) ^ R/K(C) */ | ||
| 148 | OP_UNM,/* A B R(A) := -R(B) */ | ||
| 149 | OP_NOT,/* A B R(A) := not R(B) */ | ||
| 108 | 150 | ||
| 109 | OP_SETLOCAL,/* L x - LOC[l]=x */ | 151 | OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ |
| 110 | OP_SETGLOBAL,/* K x - VAR[KSTR[k]]=x */ | ||
| 111 | OP_SETTABLE,/* A B v a_a-a_1 i t (pops b values) t[i]=v */ | ||
| 112 | 152 | ||
| 113 | OP_SETLIST,/* A B v_n-v_1 v_b v_b v_b[i+a*FPF]=v_i */ | 153 | OP_JMP,/* sBc PC += sBc */ |
| 114 | OP_SETMAP,/* U v_n k_n - v_1 k_1 v_u v_u v_u[k_i]=v_i */ | 154 | OP_CJMP,/* sBc if test then PC += sBc (see (1)) */ |
| 115 | 155 | ||
| 116 | OP_ADD,/* - y x x+y */ | 156 | OP_TESTEQ,/* B C test := (R(B) == R/K(C)) */ |
| 117 | OP_ADDI,/* S x x+s */ | 157 | OP_TESTNE,/* B C test := (R(B) ~= R/K(C)) */ |
| 118 | OP_SUB,/* - y x x-y */ | 158 | OP_TESTLT,/* B C test := (R(B) < R/K(C)) */ |
| 119 | OP_MULT,/* - y x x*y */ | 159 | OP_TESTLE,/* B C test := (R(B) <= R/K(C)) */ |
| 120 | OP_DIV,/* - y x x/y */ | 160 | OP_TESTGT,/* B C test := (R(B) > R/K(C)) */ |
| 121 | OP_POW,/* - y x x^y */ | 161 | OP_TESTGE,/* B C test := (R(B) >= R/K(C)) */ |
| 122 | OP_CONCAT,/* U v_u-v_1 v1..-..v_u */ | ||
| 123 | OP_MINUS,/* - x -x */ | ||
| 124 | OP_NOT,/* - x (x==nil)? 1 : nil */ | ||
| 125 | 162 | ||
| 126 | OP_JMPNE,/* J y x - (x~=y)? PC+=s */ | 163 | OP_TESTT,/* A B test := R(B); if (test) R(A) := R(B) */ |
| 127 | OP_JMPEQ,/* J y x - (x==y)? PC+=s */ | 164 | OP_TESTF,/* A B test := not R(B); if (test) R(A) := nil */ |
| 128 | OP_JMPLT,/* J y x - (x<y)? PC+=s */ | ||
| 129 | OP_JMPLE,/* J y x - (x<y)? PC+=s */ | ||
| 130 | OP_JMPGT,/* J y x - (x>y)? PC+=s */ | ||
| 131 | OP_JMPGE,/* J y x - (x>=y)? PC+=s */ | ||
| 132 | 165 | ||
| 133 | OP_JMPT,/* J x - (x~=nil)? PC+=s */ | 166 | OP_NILJMP,/* A R(A) := nil; PC++; */ |
| 134 | OP_JMPF,/* J x - (x==nil)? PC+=s */ | ||
| 135 | OP_JMPONT,/* J x (x~=nil)? x : - (x~=nil)? PC+=s */ | ||
| 136 | OP_JMPONF,/* J x (x==nil)? x : - (x==nil)? PC+=s */ | ||
| 137 | OP_JMP,/* J - - PC+=s */ | ||
| 138 | 167 | ||
| 139 | OP_PUSHNILJMP,/* - - nil PC++; */ | 168 | OP_CALL,/* A B C R(A), ... ,R(A+C-1) := R(A)(R(A+1), ... ,R(B-1))*/ |
| 169 | OP_RETURN,/* A B return R(A), ... ,R(B-1) (see (3)) */ | ||
| 140 | 170 | ||
| 141 | OP_FORPREP,/* J */ | 171 | OP_FORPREP,/* A sBc */ |
| 142 | OP_FORLOOP,/* J */ | 172 | OP_FORLOOP,/* A sBc */ |
| 143 | 173 | ||
| 144 | OP_LFORPREP,/* J */ | 174 | OP_TFORPREP,/* A sBc */ |
| 145 | OP_LFORLOOP,/* J */ | 175 | OP_TFORLOOP,/* A sBc */ |
| 146 | 176 | ||
| 147 | OP_CLOSURE/* A B v_b-v_1 closure(KPROTO[a], v_1-v_b) */ | 177 | OP_SETLIST,/* A Bc R(A)[Bc-Bc%FPF+i] := R(A+i), 1 <= i <= Bc%FPF+1 */ |
| 178 | OP_SETLISTO,/* A Bc */ | ||
| 148 | 179 | ||
| 180 | OP_CLOSURE /* A Bc R(A) := closure(KPROTO[Bc], R(A), ... ,R(A+n)) */ | ||
| 149 | } OpCode; | 181 | } OpCode; |
| 150 | 182 | ||
| 183 | |||
| 151 | #define NUM_OPCODES ((int)OP_CLOSURE+1) | 184 | #define NUM_OPCODES ((int)OP_CLOSURE+1) |
| 152 | 185 | ||
| 153 | 186 | ||
| 154 | #define ISJUMP(o) (OP_JMPNE <= (o) && (o) <= OP_JMP) | ||
| 155 | 187 | ||
| 188 | /*=========================================================================== | ||
| 189 | Notes: | ||
| 190 | (1) In the current implementation there is no `test' variable; | ||
| 191 | instructions OP_TEST* and OP_CJMP must always occur together. | ||
| 156 | 192 | ||
| 193 | (2) In OP_CALL, if (B == NO_REG) then B = top. C is the number of returns, | ||
| 194 | and can be NO_REG. OP_CALL always set "top" to last_result+1, so | ||
| 195 | next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use "top". | ||
| 157 | 196 | ||
| 158 | /* special code to fit a LUA_MULTRET inside an argB */ | 197 | (3) In OP_RETURN, if (B == NO_REG) then B = top. |
| 159 | #define MULT_RET 255 /* (<=MAXARG_B) */ | 198 | ===========================================================================*/ |
| 160 | #if MULT_RET>MAXARG_B | ||
| 161 | #undef MULT_RET | ||
| 162 | #define MULT_RET MAXARG_B | ||
| 163 | #endif | ||
| 164 | 199 | ||
| 165 | 200 | ||
| 166 | #endif | 201 | #endif |
