luaJIT指令集介绍
----------------目录---------------
(a)相关ByteCode定义介绍
(b)lj_bc.h和lj_bc.c
(1)字节码format简介
(2)操作数的相关范围定义,和部分定义常量
(3)通过掩码镜像,来获取相对应区域的值
(4)通过掩码镜像,来设置相对应区域的值
(5)合成实现操作符
(6)关于字节码指令的定义
(7)BCMode定义
(8)参数类型校验
-------------------------------------
(a)相关ByteCode定义介绍
在luaJIT中定义了BCIns、BCReg、BCLine这4中类型,都是int32类型,也就是32位,关于为什么BC line number是有符号32位,这个在之后讨论
/* -- Common type definitions --------------------------------------------- */
/* Types for handling bytecodes. Need this here, details in lj_bc.h. */
typedef uint32_t BCIns; //BC指令
typedef uint32_t BCPos; //BC位置
typedef uint32_t BCReg; //BC参数
typedef int32_t BCLine; //BC行数
在之后的luaJIT字节码实现过程中,这4个类型是经常用到的
(b)lj_bc.h和lj_bc.c
(1)字节码format简介
/* Bytecode instruction format, 32 bit wide, fields of 8 or 16 bit:
** +----+----+----+----+
** | B | C | A | OP | Format ABC
** +----+----+----+----+
** | D | A | OP | Format AD
** +--------------------
高位低位
这一部分描述了JIT,ByteCode的模板,相比于lua这里Bx变成了D,而Ax不存在了
(2)操作数的相关范围定义,和部分定义常量
#define BCMAX_A 0xff A的最大范围
#define BCMAX_B 0xff B的最大范围
#define BCMAX_C 0xff C的最大范围
#define BCMAX_D 0xffff D的最大范围
#define BCBIAS_J 0x8000 跳转指令标记码
#define NO_REG BCMAX_A 没有参数定义
#define NO_JMP (~(BCPos)0) 没有跳转定义
这一部分定义了操作参数的范围,还有几个常量定义
(3)通过掩码镜像,来获取相对应区域的值
/* Macros to get instruction fields. */
#define bc_op(i) ((BCOp)((i)&0xff))
#define bc_a(i) ((BCReg)(((i)>>8)&0xff))
#define bc_b(i) ((BCReg)((i)>>24))
#define bc_c(i) ((BCReg)(((i)>>16)&0xff))
#define bc_d(i) ((BCReg)((i)>>16))
#define bc_j(i) ((ptrdiff_t)bc_d(i)-BCBIAS_J)
这一部分定义了如何获取相对应的参数的值,从这里也可以看出,各个参数区域的位置
(4)通过掩码镜像,来设置相对应区域的值
#define setbc_byte(p, x, ofs) \
((uint8_t *)(p))[LJ_ENDIAN_SELECT(ofs, 3-ofs)] = (uint8_t)(x) 这就是一种贼骚的操作,先把32位转换成8位指针,强行分成4组后做处理
#define setbc_op(p, x) setbc_byte(p, (x), 0)
#define setbc_a(p, x) setbc_byte(p, (x), 1)
#define setbc_b(p, x) setbc_byte(p, (x), 3)
#define setbc_c(p, x) setbc_byte(p, (x), 2)
#define setbc_d(p, x) \
((uint16_t *)(p))[LJ_ENDIAN_SELECT(1, 0)] = (uint16_t)(x) 这里一样,强行拆成两组然后做骚操作
#define setbc_j(p, x) setbc_d(p, (BCPos)((int32_t)(x)+BCBIAS_J)) 设置跳转,用BCBIAS_J做标记
/* Macros to compose instructions. */
#define BCINS_ABC(o, a, b, c) \
(((BCIns)(o))|((BCIns)(a)<<8)|((BCIns)(b)<<24)|((BCIns)(c)<<16)) 这一部分实现合成操作码指令
#define BCINS_AD(o, a, d) \
(((BCIns)(o))|((BCIns)(a)<<8)|((BCIns)(d)<<16))
#define BCINS_AJ(o, a, j) BCINS_AD(o, a, (BCPos)((int32_t)(j)+BCBIAS_J)) 这一部分合成跳转指令
(6)关于字节码指令的定义
tips:
EQ 就是 EQUAL等于
NQ 就是 NOT EQUAL不等于
GT 就是 GREATER THAN大于
LT 就是 LESS THAN小于
GE 就是 GREATER THAN OR EQUAL 大于等于
LE 就是 LESS THAN OR EQUAL 小于等于
/* Bytecode instruction definition. Order matters, see below.
**
** (name, filler, Amode, Bmode, Cmode or Dmode, metamethod)还有相对应的元操作
**
** The opcode name suffixes specify the type for RB/RC or RD:
** V = variable slot局部变量表
** S = string const
** N = number const
** P = primitive type (~itype) 私有变量
** B = unsigned byte literal 原义字符
** M = multiple args/results 多参数和返回
后缀命名指定 说明不同的后缀存有不同的意义*/
#define BCDEF(_) \
/* Comparison ops. ORDER OPR. */ \
_(ISLT, var, ___, var, lt) \
_(ISGE, var, ___, var, lt) \
_(ISLE, var, ___, var, le) \
_(ISGT, var, ___, var, le) \
\
_(ISEQV, var, ___, var, eq) \
_(ISNEV, var, ___, var, eq) \
_(ISEQS, var, ___, str, eq) \
_(ISNES, var, ___, str, eq) \
_(ISEQN, var, ___, num, eq) \
_(ISNEN, var, ___, num, eq) \
_(ISEQP, var, ___, pri, eq) \
_(ISNEP, var, ___, pri, eq) \
\
/* Unary test and copy ops. */ \
_(ISTC, dst, ___, var, ___) \
_(ISFC, dst, ___, var, ___) \
_(IST, ___, ___, var, ___) \
_(ISF, ___, ___, var, ___) \
\
/* Unary ops. */ \
_(MOV, dst, ___, var, ___) \
_(NOT, dst, ___, var, ___) \
_(UNM, dst, ___, var, unm) \
_(LEN, dst, ___, var, len) \
\
/* Binary ops. ORDER OPR. VV last, POW must be next. */ \
_(ADDVN, dst, var, num, add) \
_(SUBVN, dst, var, num, sub) \
_(MULVN, dst, var, num, mul) \
_(DIVVN, dst, var, num, div) \
_(MODVN, dst, var, num, mod) \
\
_(ADDNV, dst, var, num, add) \
_(SUBNV, dst, var, num, sub) \
_(MULNV, dst, var, num, mul) \
_(DIVNV, dst, var, num, div) \
_(MODNV, dst, var, num, mod) \
\
_(ADDVV, dst, var, var, add) \
_(SUBVV, dst, var, var, sub) \
_(MULVV, dst, var, var, mul) \
_(DIVVV, dst, var, var, div) \
_(MODVV, dst, var, var, mod) \
\
_(POW, dst, var, var, pow) \
_(CAT, dst, rbase, rbase, concat) \
\
/* Constant ops. */ \
_(KSTR, dst, ___, str, ___) \
_(KCDATA, dst, ___, cdata, ___) \
_(KSHORT, dst, ___, lits, ___) \
_(KNUM, dst, ___, num, ___) \
_(KPRI, dst, ___, pri, ___) \
_(KNIL, base, ___, base, ___) \
\
/* Upvalue and function ops. */ \
_(UGET, dst, ___, uv, ___) \
_(USETV, uv, ___, var, ___) \
_(USETS, uv, ___, str, ___) \
_(USETN, uv, ___, num, ___) \
_(USETP, uv, ___, pri, ___) \
_(UCLO, rbase, ___, jump, ___) \
_(FNEW, dst, ___, func, gc) \
\
/* Table ops. */ \
_(TNEW, dst, ___, lit, gc) \
_(TDUP, dst, ___, tab, gc) \
_(GGET, dst, ___, str, index) \
_(GSET, var, ___, str, newindex) \
_(TGETV, dst, var, var, index) \
_(TGETS, dst, var, str, index) \
_(TGETB, dst, var, lit, index) \
_(TSETV, var, var, var, newindex) \
_(TSETS, var, var, str, newindex) \
_(TSETB, var, var, lit, newindex) \
_(TSETM, base, ___, num, newindex) \
\
/* Calls and vararg handling. T = tail call. */ \
_(CALLM, base, lit, lit, call) \
_(CALL, base, lit, lit, call) \
_(CALLMT, base, ___, lit, call) \
_(CALLT, base, ___, lit, call) \
_(ITERC, base, lit, lit, call) \
_(ITERN, base, lit, lit, call) \
_(VARG, base, lit, lit, ___) \
_(ISNEXT, base, ___, jump, ___) \
\
/* Returns. */ \
_(RETM, base, ___, lit, ___) \
_(RET, rbase, ___, lit, ___) \
_(RET0, rbase, ___, lit, ___) \
_(RET1, rbase, ___, lit, ___) \
\
/* Loops and branches. I/J = interp/JIT, I/C/L = init/call/loop. */ \
_(FORI, base, ___, jump, ___) \
_(JFORI, base, ___, jump, ___) \
\
_(FORL, base, ___, jump, ___) \
_(IFORL, base, ___, jump, ___) \
_(JFORL, base, ___, lit, ___) \
\
_(ITERL, base, ___, jump, ___) \
_(IITERL, base, ___, jump, ___) \
_(JITERL, base, ___, lit, ___) \
\
_(LOOP, rbase, ___, jump, ___) \
_(ILOOP, rbase, ___, jump, ___) \
_(JLOOP, rbase, ___, lit, ___) \
\
_(JMP, rbase, ___, jump, ___) \
\
/* Function headers. I/J = interp/JIT, F/V/C = fixarg/vararg/C func. */ \
_(FUNCF, rbase, ___, ___, ___) \
_(IFUNCF, rbase, ___, ___, ___) \
_(JFUNCF, rbase, ___, lit, ___) \
_(FUNCV, rbase, ___, ___, ___) \
_(IFUNCV, rbase, ___, ___, ___) \
_(JFUNCV, rbase, ___, lit, ___) \
_(FUNCC, rbase, ___, ___, ___) \
_(FUNCCW, rbase, ___, ___, ___)
在这之后以下两行代码处理了这部分的定义
/* Bytecode opcode numbers. */
typedef enum {
#define BCENUM(name, ma, mb, mc, mt) BC_##name,
BCDEF(BCENUM)
#undef BCENUM
BC__MAX
} BCOp;
这里对之前定义过得BENUM完全undef了,这也就表明这里的枚举,仅仅是枚举用,命名为BC_操作名
/* This solves a circular dependency problem, change as needed. */
#define FF_next_N 4
这里说FF_next_N是用来解决循环依赖问题的,之后可以关注下
(7)BCMode定义
typedef enum {
BCMnone, BCMdst, BCMbase, BCMvar, BCMrbase, BCMuv, /* Mode A must be <= 7 */
BCMlit, BCMlits, BCMpri, BCMnum, BCMstr, BCMtab, BCMfunc, BCMjump, BCMcdata,
BCM_max
} BCMode;
这里定义了BCMode的类型,这里主要是定义参数类型,因为扩展了很多操作指令,所以参数类型的也变得更丰富
(8)参数类型校验
这里的参数校验定义为
a 0~2 位
b 3~6位
c 7~10位
d 与c相同,但是有hasd这个校验步骤,就是检验b是不是modeNone
mm 11位以后
到这里全部的指令集定义已经完全介绍完毕,接下来将介绍read和write来进一步讲解