luaJIT指令集介绍

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做标记

(5)合成实现操作符

	/* 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来进一步讲解


 
 
 
 
 
 
 
 
 

猜你喜欢

转载自blog.csdn.net/Hello_YJQ/article/details/78345069