diff options
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 |