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