1 | /* |
2 | ** Bytecode instruction format. |
3 | ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h |
4 | */ |
5 | |
6 | #ifndef _LJ_BC_H |
7 | #define _LJ_BC_H |
8 | |
9 | #include "lj_def.h" |
10 | #include "lj_arch.h" |
11 | |
12 | /* Bytecode instruction format, 32 bit wide, fields of 8 or 16 bit: |
13 | ** |
14 | ** +----+----+----+----+ |
15 | ** | B | C | A | OP | Format ABC |
16 | ** +----+----+----+----+ |
17 | ** | D | A | OP | Format AD |
18 | ** +-------------------- |
19 | ** MSB LSB |
20 | ** |
21 | ** In-memory instructions are always stored in host byte order. |
22 | */ |
23 | |
24 | /* Operand ranges and related constants. */ |
25 | #define BCMAX_A 0xff |
26 | #define BCMAX_B 0xff |
27 | #define BCMAX_C 0xff |
28 | #define BCMAX_D 0xffff |
29 | #define BCBIAS_J 0x8000 |
30 | #define NO_REG BCMAX_A |
31 | #define NO_JMP (~(BCPos)0) |
32 | |
33 | /* Macros to get instruction fields. */ |
34 | #define bc_op(i) ((BCOp)((i)&0xff)) |
35 | #define bc_a(i) ((BCReg)(((i)>>8)&0xff)) |
36 | #define bc_b(i) ((BCReg)((i)>>24)) |
37 | #define bc_c(i) ((BCReg)(((i)>>16)&0xff)) |
38 | #define bc_d(i) ((BCReg)((i)>>16)) |
39 | #define bc_j(i) ((ptrdiff_t)bc_d(i)-BCBIAS_J) |
40 | |
41 | /* Macros to set instruction fields. */ |
42 | #define setbc_byte(p, x, ofs) \ |
43 | ((uint8_t *)(p))[LJ_ENDIAN_SELECT(ofs, 3-ofs)] = (uint8_t)(x) |
44 | #define setbc_op(p, x) setbc_byte(p, (x), 0) |
45 | #define setbc_a(p, x) setbc_byte(p, (x), 1) |
46 | #define setbc_b(p, x) setbc_byte(p, (x), 3) |
47 | #define setbc_c(p, x) setbc_byte(p, (x), 2) |
48 | #define setbc_d(p, x) \ |
49 | ((uint16_t *)(p))[LJ_ENDIAN_SELECT(1, 0)] = (uint16_t)(x) |
50 | #define setbc_j(p, x) setbc_d(p, (BCPos)((int32_t)(x)+BCBIAS_J)) |
51 | |
52 | /* Macros to compose instructions. */ |
53 | #define BCINS_ABC(o, a, b, c) \ |
54 | (((BCIns)(o))|((BCIns)(a)<<8)|((BCIns)(b)<<24)|((BCIns)(c)<<16)) |
55 | #define BCINS_AD(o, a, d) \ |
56 | (((BCIns)(o))|((BCIns)(a)<<8)|((BCIns)(d)<<16)) |
57 | #define BCINS_AJ(o, a, j) BCINS_AD(o, a, (BCPos)((int32_t)(j)+BCBIAS_J)) |
58 | |
59 | /* Bytecode instruction definition. Order matters, see below. |
60 | ** |
61 | ** (name, filler, Amode, Bmode, Cmode or Dmode, metamethod) |
62 | ** |
63 | ** The opcode name suffixes specify the type for RB/RC or RD: |
64 | ** V = variable slot |
65 | ** S = string const |
66 | ** N = number const |
67 | ** P = primitive type (~itype) |
68 | ** B = unsigned byte literal |
69 | ** M = multiple args/results |
70 | */ |
71 | #define BCDEF(_) \ |
72 | /* Comparison ops. ORDER OPR. */ \ |
73 | _(ISLT, var, ___, var, lt) \ |
74 | _(ISGE, var, ___, var, lt) \ |
75 | _(ISLE, var, ___, var, le) \ |
76 | _(ISGT, var, ___, var, le) \ |
77 | \ |
78 | _(ISEQV, var, ___, var, eq) \ |
79 | _(ISNEV, var, ___, var, eq) \ |
80 | _(ISEQS, var, ___, str, eq) \ |
81 | _(ISNES, var, ___, str, eq) \ |
82 | _(ISEQN, var, ___, num, eq) \ |
83 | _(ISNEN, var, ___, num, eq) \ |
84 | _(ISEQP, var, ___, pri, eq) \ |
85 | _(ISNEP, var, ___, pri, eq) \ |
86 | \ |
87 | /* Unary test and copy ops. */ \ |
88 | _(ISTC, dst, ___, var, ___) \ |
89 | _(ISFC, dst, ___, var, ___) \ |
90 | _(IST, ___, ___, var, ___) \ |
91 | _(ISF, ___, ___, var, ___) \ |
92 | _(ISTYPE, var, ___, lit, ___) \ |
93 | _(ISNUM, var, ___, lit, ___) \ |
94 | \ |
95 | /* Unary ops. */ \ |
96 | _(MOV, dst, ___, var, ___) \ |
97 | _(NOT, dst, ___, var, ___) \ |
98 | _(UNM, dst, ___, var, unm) \ |
99 | _(LEN, dst, ___, var, len) \ |
100 | \ |
101 | /* Binary ops. ORDER OPR. VV last, POW must be next. */ \ |
102 | _(ADDVN, dst, var, num, add) \ |
103 | _(SUBVN, dst, var, num, sub) \ |
104 | _(MULVN, dst, var, num, mul) \ |
105 | _(DIVVN, dst, var, num, div) \ |
106 | _(MODVN, dst, var, num, mod) \ |
107 | \ |
108 | _(ADDNV, dst, var, num, add) \ |
109 | _(SUBNV, dst, var, num, sub) \ |
110 | _(MULNV, dst, var, num, mul) \ |
111 | _(DIVNV, dst, var, num, div) \ |
112 | _(MODNV, dst, var, num, mod) \ |
113 | \ |
114 | _(ADDVV, dst, var, var, add) \ |
115 | _(SUBVV, dst, var, var, sub) \ |
116 | _(MULVV, dst, var, var, mul) \ |
117 | _(DIVVV, dst, var, var, div) \ |
118 | _(MODVV, dst, var, var, mod) \ |
119 | \ |
120 | _(POW, dst, var, var, pow) \ |
121 | _(CAT, dst, rbase, rbase, concat) \ |
122 | \ |
123 | /* Constant ops. */ \ |
124 | _(KSTR, dst, ___, str, ___) \ |
125 | _(KCDATA, dst, ___, cdata, ___) \ |
126 | _(KSHORT, dst, ___, lits, ___) \ |
127 | _(KNUM, dst, ___, num, ___) \ |
128 | _(KPRI, dst, ___, pri, ___) \ |
129 | _(KNIL, base, ___, base, ___) \ |
130 | \ |
131 | /* Upvalue and function ops. */ \ |
132 | _(UGET, dst, ___, uv, ___) \ |
133 | _(USETV, uv, ___, var, ___) \ |
134 | _(USETS, uv, ___, str, ___) \ |
135 | _(USETN, uv, ___, num, ___) \ |
136 | _(USETP, uv, ___, pri, ___) \ |
137 | _(UCLO, rbase, ___, jump, ___) \ |
138 | _(FNEW, dst, ___, func, gc) \ |
139 | \ |
140 | /* Table ops. */ \ |
141 | _(TNEW, dst, ___, lit, gc) \ |
142 | _(TDUP, dst, ___, tab, gc) \ |
143 | _(GGET, dst, ___, str, index) \ |
144 | _(GSET, var, ___, str, newindex) \ |
145 | _(TGETV, dst, var, var, index) \ |
146 | _(TGETS, dst, var, str, index) \ |
147 | _(TGETB, dst, var, lit, index) \ |
148 | _(TGETR, dst, var, var, index) \ |
149 | _(TSETV, var, var, var, newindex) \ |
150 | _(TSETS, var, var, str, newindex) \ |
151 | _(TSETB, var, var, lit, newindex) \ |
152 | _(TSETM, base, ___, num, newindex) \ |
153 | _(TSETR, var, var, var, newindex) \ |
154 | \ |
155 | /* Calls and vararg handling. T = tail call. */ \ |
156 | _(CALLM, base, lit, lit, call) \ |
157 | _(CALL, base, lit, lit, call) \ |
158 | _(CALLMT, base, ___, lit, call) \ |
159 | _(CALLT, base, ___, lit, call) \ |
160 | _(ITERC, base, lit, lit, call) \ |
161 | _(ITERN, base, lit, lit, call) \ |
162 | _(VARG, base, lit, lit, ___) \ |
163 | _(ISNEXT, base, ___, jump, ___) \ |
164 | \ |
165 | /* Returns. */ \ |
166 | _(RETM, base, ___, lit, ___) \ |
167 | _(RET, rbase, ___, lit, ___) \ |
168 | _(RET0, rbase, ___, lit, ___) \ |
169 | _(RET1, rbase, ___, lit, ___) \ |
170 | \ |
171 | /* Loops and branches. I/J = interp/JIT, I/C/L = init/call/loop. */ \ |
172 | _(FORI, base, ___, jump, ___) \ |
173 | _(JFORI, base, ___, jump, ___) \ |
174 | \ |
175 | _(FORL, base, ___, jump, ___) \ |
176 | _(IFORL, base, ___, jump, ___) \ |
177 | _(JFORL, base, ___, lit, ___) \ |
178 | \ |
179 | _(ITERL, base, ___, jump, ___) \ |
180 | _(IITERL, base, ___, jump, ___) \ |
181 | _(JITERL, base, ___, lit, ___) \ |
182 | \ |
183 | _(LOOP, rbase, ___, jump, ___) \ |
184 | _(ILOOP, rbase, ___, jump, ___) \ |
185 | _(JLOOP, rbase, ___, lit, ___) \ |
186 | \ |
187 | _(JMP, rbase, ___, jump, ___) \ |
188 | \ |
189 | /* Function headers. I/J = interp/JIT, F/V/C = fixarg/vararg/C func. */ \ |
190 | _(FUNCF, rbase, ___, ___, ___) \ |
191 | _(IFUNCF, rbase, ___, ___, ___) \ |
192 | _(JFUNCF, rbase, ___, lit, ___) \ |
193 | _(FUNCV, rbase, ___, ___, ___) \ |
194 | _(IFUNCV, rbase, ___, ___, ___) \ |
195 | _(JFUNCV, rbase, ___, lit, ___) \ |
196 | _(FUNCC, rbase, ___, ___, ___) \ |
197 | _(FUNCCW, rbase, ___, ___, ___) |
198 | |
199 | /* Bytecode opcode numbers. */ |
200 | typedef enum { |
201 | #define BCENUM(name, ma, mb, mc, mt) BC_##name, |
202 | BCDEF(BCENUM) |
203 | #undef BCENUM |
204 | BC__MAX |
205 | } BCOp; |
206 | |
207 | LJ_STATIC_ASSERT((int)BC_ISEQV+1 == (int)BC_ISNEV); |
208 | LJ_STATIC_ASSERT(((int)BC_ISEQV^1) == (int)BC_ISNEV); |
209 | LJ_STATIC_ASSERT(((int)BC_ISEQS^1) == (int)BC_ISNES); |
210 | LJ_STATIC_ASSERT(((int)BC_ISEQN^1) == (int)BC_ISNEN); |
211 | LJ_STATIC_ASSERT(((int)BC_ISEQP^1) == (int)BC_ISNEP); |
212 | LJ_STATIC_ASSERT(((int)BC_ISLT^1) == (int)BC_ISGE); |
213 | LJ_STATIC_ASSERT(((int)BC_ISLE^1) == (int)BC_ISGT); |
214 | LJ_STATIC_ASSERT(((int)BC_ISLT^3) == (int)BC_ISGT); |
215 | LJ_STATIC_ASSERT((int)BC_IST-(int)BC_ISTC == (int)BC_ISF-(int)BC_ISFC); |
216 | LJ_STATIC_ASSERT((int)BC_CALLT-(int)BC_CALL == (int)BC_CALLMT-(int)BC_CALLM); |
217 | LJ_STATIC_ASSERT((int)BC_CALLMT + 1 == (int)BC_CALLT); |
218 | LJ_STATIC_ASSERT((int)BC_RETM + 1 == (int)BC_RET); |
219 | LJ_STATIC_ASSERT((int)BC_FORL + 1 == (int)BC_IFORL); |
220 | LJ_STATIC_ASSERT((int)BC_FORL + 2 == (int)BC_JFORL); |
221 | LJ_STATIC_ASSERT((int)BC_ITERL + 1 == (int)BC_IITERL); |
222 | LJ_STATIC_ASSERT((int)BC_ITERL + 2 == (int)BC_JITERL); |
223 | LJ_STATIC_ASSERT((int)BC_LOOP + 1 == (int)BC_ILOOP); |
224 | LJ_STATIC_ASSERT((int)BC_LOOP + 2 == (int)BC_JLOOP); |
225 | LJ_STATIC_ASSERT((int)BC_FUNCF + 1 == (int)BC_IFUNCF); |
226 | LJ_STATIC_ASSERT((int)BC_FUNCF + 2 == (int)BC_JFUNCF); |
227 | LJ_STATIC_ASSERT((int)BC_FUNCV + 1 == (int)BC_IFUNCV); |
228 | LJ_STATIC_ASSERT((int)BC_FUNCV + 2 == (int)BC_JFUNCV); |
229 | |
230 | /* This solves a circular dependency problem, change as needed. */ |
231 | #define FF_next_N 4 |
232 | |
233 | /* Stack slots used by FORI/FORL, relative to operand A. */ |
234 | enum { |
235 | FORL_IDX, FORL_STOP, FORL_STEP, FORL_EXT |
236 | }; |
237 | |
238 | /* Bytecode operand modes. ORDER BCMode */ |
239 | typedef enum { |
240 | BCMnone, BCMdst, BCMbase, BCMvar, BCMrbase, BCMuv, /* Mode A must be <= 7 */ |
241 | BCMlit, BCMlits, BCMpri, BCMnum, BCMstr, BCMtab, BCMfunc, BCMjump, BCMcdata, |
242 | BCM_max |
243 | } BCMode; |
244 | #define BCM___ BCMnone |
245 | |
246 | #define bcmode_a(op) ((BCMode)(lj_bc_mode[op] & 7)) |
247 | #define bcmode_b(op) ((BCMode)((lj_bc_mode[op]>>3) & 15)) |
248 | #define bcmode_c(op) ((BCMode)((lj_bc_mode[op]>>7) & 15)) |
249 | #define bcmode_d(op) bcmode_c(op) |
250 | #define bcmode_hasd(op) ((lj_bc_mode[op] & (15<<3)) == (BCMnone<<3)) |
251 | #define bcmode_mm(op) ((MMS)(lj_bc_mode[op]>>11)) |
252 | |
253 | #define BCMODE(name, ma, mb, mc, mm) \ |
254 | (BCM##ma|(BCM##mb<<3)|(BCM##mc<<7)|(MM_##mm<<11)), |
255 | #define BCMODE_FF 0 |
256 | |
257 | static LJ_AINLINE int bc_isret(BCOp op) |
258 | { |
259 | return (op == BC_RETM || op == BC_RET || op == BC_RET0 || op == BC_RET1); |
260 | } |
261 | |
262 | LJ_DATA const uint16_t lj_bc_mode[]; |
263 | LJ_DATA const uint16_t lj_bc_ofs[]; |
264 | |
265 | #endif |
266 | |