前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >luaJIT指令集介绍[通俗易懂]

luaJIT指令集介绍[通俗易懂]

作者头像
全栈程序员站长
发布2022-11-08 17:59:29
8480
发布2022-11-08 17:59:29
举报
文章被收录于专栏:全栈程序员必看

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位,这个在之后讨论

代码语言:javascript
复制
/* -- 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)操作数的相关范围定义,和部分定义常量

代码语言:javascript
复制
	#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)通过掩码镜像,来获取相对应区域的值

代码语言:javascript
复制
 /* 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)通过掩码镜像,来设置相对应区域的值

代码语言:javascript
复制
 #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)合成实现操作符

代码语言:javascript
复制
 /* 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:

代码语言:javascript
复制
 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来进一步讲解
 







版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。 发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/185028.html原文链接:https://javaforall.cn  【正版授权,激活自己账号】:  Jetbrains全系列IDE使用 售后保障 童叟无欺    【官方授权 正版激活】:  官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...  
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年10月7日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档