7.2 基于寄存器的指令集
Dalvik 字节码指令集的字节码指令集不支持无符号整数运算,因此参照 Dalvik 设计了以下指令集。
基于纯寄存器的指令集,指令系统存在下列的要求:
- 每条指令按照 16 bit 对齐。
- 寄存器的索引位宽有 4 bit、8 bit、16 bit。
- 最多支持 65536 个寄存器。
- 每个寄存器 32 bit。
- 64 bit寄存器由相邻的两个 32 bit 寄存器组合而成。
- 指令操作码位宽为 8 bit。
- 指令中可有子操作码,具体位宽看具体的指令格式。
- 32 bit 寄存器内可以存储 32 bit的整数、浮点数。
- 64 bit 寄存器内可以存储 64 bit的整数、浮点数。
- 位宽小于 32 位的值,需要进行扩展(零扩展、符号扩展)到 32 bit。
- 助记符中的 I 表示寄存器索引,后面的数字表示索引位宽
指令格式
总体格式:
操作码 + [ 操作子码 ] + ( 操作数 )*
寄存器位宽索引支持的寄存器数量:
位宽 | 寄存器数量 | 索引范围 |
---|
4 bit | 16 | [ 0, 15 ] |
8 bit | 256 | [ 0, 255 ] |
16 bit | 65536 | [ 0, 65535 ] |
空指令
文本格式: nop
助记符 | 操作码 | 对齐 | 注解 |
---|
格式 | 8 bit | 8bit | 指令宽度:16 bit |
| | | |
nop | 0 | | 空操作,用于对齐 |
常量赋值指令
文本格式: op des, imm
助记符 | 操作码 | 目的寄存器 | 立即数 | 注解 |
---|
| 8 bit | 4 bit | 4 bit | 4 bit 立即数,指令宽度:16 bit |
const-w32-I4-i4 | | des | imm | imm 为有符号整数,有符号扩展至 32 bit。 |
const-w64-I4-i4 | | des | imm | imm 为有符号整数,有符号扩展至 32 bit。 |
const-w32-I4-u4 | | des | imm | imm 为无符号整数,无符号扩展至 32 bit。 |
const-w64-I4-u4 | | des | imm | imm 为无符号整数,无符号扩展至 32 bit。 |
| | | | |
| 8 bit | 8 bit | 16 bit | 16 bit 立即数,指令宽度:32 bit |
const-w32-I8-i16 | | des | imm | imm 为有符号整数,有符号扩展至 32 bit。 |
const-w64-I8-i16 | | des | imm | imm 为有符号整数,有符号扩展至 64 bit。 |
const-w32-I8-u16 | | des | imm | imm 为无符号整数,无符号扩展至 32 bit。 |
const-w64-I8-u16 | | des | imm | imm 为无符号整数,无符号扩展至 64 bit。 |
const-w32-I8-L16 | | des | imm | imm 为无符号整数。imm 存放在寄存器的低 16 bit,不改变高 16 bit。 |
const-w32-I8-H16 | | des | imm | imm 为无符号整数。imm 存放在寄存器的高 16 bit,不改变低 16 bit。 |
| | | | |
| 8 bit | 8 bit | 32 bit | 32 bit 立即数,指令宽度:48 bit |
const-w32-I8 | | des | imm | 原样拷贝,支持32 bit 整数和浮点。 |
const-w64-I8-i32 | | des | imm | imm 为有符号整数,有符号扩展至 64 bit。 |
const-w64-I8-u32 | | des | imm | imm 为无符号整数,无符号扩展至 64 bit。 |
| | | | |
| 8 bit | 8 bit | 64 bit | 64 bit 立即数,指令宽度:80 bit |
const-w64-I8 | | des | imm | 原样拷贝,支持64 bit整数和浮点。 |
文本格式:op.sub des,imm
助记符 | 操作码 | 操作子码 | 目的寄存器 | 立即数 | 注解 |
---|
| 8 bit | 8 bit | 8 bit | 8 bit | 指令宽度:32 bit |
const-w32-I8 | | subop | des | imm | imm 为无符号整数 |
操作子码定义
助记符 | 操作子码 | 注解 |
---|
B0 | | imm存放在寄存器的第 1 个字节,不改变其他字节。 |
B1 | | imm存放在寄存器的第 2 个字节,不改变其他字节。 |
B2 | | imm存放在寄存器的第 3 个字节,不改变其他字节。 |
B3 | | imm存放在寄存器的第 4 个字节,不改变其他字节。 |
寄存器赋值指令
文本格式:op des,src
文本格式:op des,src
助记符 | 操作码 | 目的寄存器 | 源寄存器 | 注解 |
---|
| 8 bit | 4 bit | 4 bit | 指令宽度:16 bit |
move-w32-I4 | | des | src | 32 位寄存器值传递 |
move-w64-I4 | | des | src | 64 位寄存器值传递 |
| | | | |
| 8 bit | 8 bit | 16 bit | 指令宽度:32 bit |
move-w32-I8I16 | | des | src | 32 位寄存器值传递 |
move-w64-I8I16 | | des | src | 64 位寄存器值传递 |
文本格式:op.sub des,src
助记符 | 操作码 | 操作子码 | 目的寄存器 | 源寄存器 | 注解 |
---|
| 8 bit | 8 bit | 8 bit | 8 bit | 指令宽度:32 bit |
mov-I8 | sub | des | src | | |
| | | | | |
| 8 bit | 8 bit | 16 bit | 16 bit | 指令宽度:48 bit |
mov-I16 | sub | des | src | | |
操作子码定义
助记符含义:
目标位宽-源数据获取转换位宽
- i:符号扩展。
- u:零扩展。
- 只有目标位宽时,表示源位宽直接拷贝传递。
目标类型-源类型
助记符 | 操作子码 | 注解 |
---|
w32-B0-i8 | 0 | 获取寄存器的第 1 个字节,进行符号扩展到 32 位 |
w32-B0-u8 | 1 | 获取寄存器的第 1 个字节,进行零扩展到 32 位 |
w32-B1-i8 | 2 | 获取寄存器的第 2 个字节,进行符号扩展到 32 位 |
w32-B1-u8 | 3 | 获取寄存器的第 2 个字节,进行零扩展到 32 位 |
w32-B2-i8 | 4 | 获取寄存器的第 3 个字节,进行符号扩展到 32 位 |
w32-B2-u8 | 5 | 获取寄存器的第 3 个字节,进行零扩展到 32 位 |
w32-B3-i8 | 6 | 获取寄存器的第 4 个字节,进行符号扩展到 32 位 |
w32-B3-u8 | 7 | 获取寄存器的第 4 个字节,进行零扩展到 32 位 |
| | |
w32-L16-i16 | 8 | 获取寄存器的低 16 位,进行符号扩展到 32 位 |
w32-L16-u16 | 9 | 获取寄存器的低 16 位,进行零扩展到 32 位 |
w32-H16-i16 | 10 | 获取寄存器的高 16 位,进行符号扩展到 32 位 |
w32-H16-u16 | 11 | 获取寄存器的高 16 位,进行零扩展到 32 位 |
w32 | 12 | 32 位原值拷贝传递 |
| | |
w64-B0-i8 | 13 | 获取寄存器的第 1 个字节,进行符号扩展到 64 位 |
w64-B0-u8 | 14 | 获取寄存器的第 1 个字节,进行零扩展到 64 位 |
w64-B1-i8 | 15 | 获取寄存器的第 2 个字节,进行符号扩展到 64 位 |
w64-B1-u8 | 16 | 获取寄存器的第 2 个字节,进行零扩展到 64 位 |
w64-B2-i8 | 17 | 获取寄存器的第 3 个字节,进行符号扩展到 64 位 |
w64-B2-u8 | 18 | 获取寄存器的第 3 个字节,进行零扩展到 64 位 |
w64-B3-i8 | 19 | 获取寄存器的第 4 个字节,进行符号扩展到 64 位 |
w64-B3-u8 | 20 | 获取寄存器的第 4 个字节,进行零扩展到 64 位 |
| | |
w64-L16-i16 | 21 | 获取寄存器的低 16 位,进行符号扩展到 32 位 |
w64-L16-u16 | 22 | 获取寄存器的低 16 位,进行零扩展到 32 位 |
w64-H16-i16 | 23 | 获取寄存器的高 16 位,进行符号扩展到 32 位 |
w64-H16-u16 | 24 | 获取寄存器的高 16 位,进行零扩展到 32 位 |
w64-i32 | 25 | 获取寄存器的 32 位,进行符号扩展到 64 位 |
w64-u32 | 26 | 获取寄存器的 32 位,进行零扩展到 64 位 |
w64 | 27 | 64 位原值拷贝传递 |
| | |
i32-f32 | 28 | 32 位有符号整数转 32 位浮点数 |
i32-f64 | 29 | 32 位有符号整数转 64 位浮点数 |
u32-f32 | 30 | 32 位无符号整数转 32 位浮点数 |
u32-f64 | 31 | 32 位无符号整数转 64 位浮点数 |
| | |
i64-f32 | 32 | 64 位有符号整数转 32 位浮点数 |
i64-f64 | 33 | 64 位有符号整数转 32 位浮点数 |
u64-f32 | 34 | 64 位无符号整数转 32 位浮点数 |
u64-f64 | 35 | 64 位无符号整数转 64 位浮点数 |
| | |
f32-i32 | 36 | 32 位浮点数转 32 位有符号 |
f32-i64 | 37 | 32 位浮点数转 64 位有符号 |
f32-u32 | 38 | 32 位浮点数转 32 位无符号 |
f32-u64 | 39 | 32 位浮点数转 64 位无符号 |
f32-f64 | 49 | 32 位浮点数转 64 位浮点数 |
| | |
f64-i32 | 41 | 64 位浮点数转 32 位有符号 |
f64-i64 | 42 | 64 位浮点数转 64 位有符号 |
f64-u32 | 43 | 64 位浮点数转 32 位无符号 |
f64-u64 | 44 | 64 位浮点数转 64 位无符号 |
f64-f32 | 45 | 64 位浮点数转 32 位浮点数 |
数学运算指令
三地址操作
三地址文本格式: op.sub des,src,src2
助记符 | 操作码 | 操作子码 | 目的寄存器 | 源寄存器 | 源操作数 | 注解 |
---|
| 8 bit | 8 bit | 8 bit | 4 bit | 4 bit | 指令宽度:32 bit |
math-I4 | | sub | des | src | src2 | |
| 8 bit | 8 bit | 16 bit | 8 bit | 8 bit | 指令宽度:48 bit |
math-I16I8 | | sub | des | src | src2 | |
| 8 bit | 8 bit | 16 bit | 16 bit | 16 bit | 指令宽度:64 bit |
math-I16 | | sub | des | src | src2 | |
子码定义
助记符 | 操作子码 | 注解 |
---|
add-int32 | 0 | 32 位有符号 加 + |
sub-int32 | 1 | 32 位有符号 减 - |
mul-int32 | 2 | 32 位有符号 乘 * |
div-int32 | 3 | 32 位有符号 除 / |
mod-int32 | 4 | 32 位有符号 模 % |
| | |
add-uint32 | 5 | 32 位无符号 加 + |
sub-uint32 | 6 | 32 位无符号 减 - |
mul-uint32 | 7 | 32 位无符号 乘 * |
div-uint32 | 8 | 32 位无符号 除 / |
mod-uint32 | 9 | 32 位无符号 模 % |
| | |
add-int64 | 10 | 64 位有符号 加 + |
sub-int64 | 11 | 64 位有符号 减 - |
mul-int64 | 12 | 64 位有符号 乘 * |
div-int64 | 13 | 64 位有符号 除 / |
mod-int64 | 14 | 64 位有符号 |
| | |
add-uint64 | 15 | 64 位无符号 加 + |
sub-uint64 | 16 | 64 位无符号 减 - |
mul-uint64 | 17 | 64 位无符号 乘 * |
div-uint64 | 18 | 64 位无符号 除 / |
mod-uint64 | 19 | 64 位无符号 模 % |
| | |
add-flt32 | 20 | 32 位浮点 加 + |
sub-flt32 | 21 | 32 位浮点 减 - |
mul-flt32 | 22 | 32 位浮点 乘 * |
div-flt32 | 23 | 32 位浮点 除 / |
mod-flt32 | 24 | 32 位浮点 模 % |
| | |
add-flt64 | 25 | 64 位浮点 加 + |
sub-flt64 | 26 | 64 位浮点 减 - |
mul-flt64 | 27 | 64 位浮点 乘 * |
div-flt64 | 28 | 64 位浮点 除 / |
mod-flt64 | 29 | 64 位浮点 模 % |
| | |
sl-w32 | 30 | 32 位 左移 |
sr-w32 | 31 | 32 位 右移 |
sra-w32 | 32 | 32 位 算术右移 |
rol-w32 | 33 | 32 位 循环左移 |
ror-w32 | 34 | 32 位 循环右移 |
and-w32 | 35 | 32 位 位与 |
or-w32 | 36 | 32 位 位或 |
xor-w32 | 37 | 32 位 位异或 |
| | |
sl-w64 | 38 | 64 位 左移 |
sr-w64 | 39 | 64 位 右移 |
sra-w64 | 40 | 64 位 算术右移 |
rol-w32 | 41 | 64 位 循环左移 |
ror-w32 | 42 | 64 位 循环右移 |
and-w64 | 43 | 64 位 位与 |
or-w64 | 44 | 64 位 位或 |
xor-w64 | 45 | 64 位 位异或 |
| | |
andl-w32 | 46 | 32 位 逻辑与 |
orl-w32 | 47 | 32 位 逻辑或 |
| | |
cmp-int32 | 48 | src < src2 : des=-1 |
cmp-uint32 | 49 | src == src2 : des=0 |
cmp-int64 | 50 | src > src2 : des=1 |
cmp-uint64 | 51 | |
cmp-flt32 | 52 | |
cmp-flt64 | 53 | |
| | |
二地址操作
二地址文本格式: op.sub des,src
助记符 | 操作码 | 操作子码 | 目的寄存器 | 源寄存器 | 源操作数 | 注解 |
---|
| 8 bit | 8 bit | 8 bit | 8 bit | 指令宽度:32 bit | |
math-I8 | | sub | des | src | | |
| 8 bit | 8 bit | 16 bit | 16 bit | 指令宽度:48 bit | |
math-I16 | | sub | des | src | | |
子码定义
助记符 | 操作子码 | 注解 |
---|
not-w32 | 0 | 32 位 按位取反 |
not-w64 | 1 | 64 位 按位取反 |
| | |
inv-w32 | 2 | 32 位 逻辑取反 |
inv-w64 | 3 | 64 位 逻辑取反 |
| | |
neg-int32 | 4 | 32 位 符号取反 |
neg-int64 | 5 | 64 位 符号取反 |
neg-flt32 | 6 | 32 位 符号取反 |
neg-flt64 | 7 | 64 位 符号取反 |
| | |
abs-int32 | 8 | 32 位 取绝对值 |
abs-int64 | 9 | 64 位 取绝对值 |
abs-flt32 | 10 | 32 位 取绝对值 |
abs-flt64 | 11 | 64 位 取绝对值 |
| | |
sin-flt32 | 12 | 三角函数 |
cos-flt32 | 13 | 三角函数 |
tan-flt32 | 14 | 三角函数 |
asin-flt32 | 15 | 三角函数 |
acos-flt32 | 16 | 三角函数 |
atan-flt32 | 17 | 三角函数 |
| | |
sin-flt64 | 18 | 三角函数 |
cos-flt64 | 19 | 三角函数 |
tan-flt64 | 20 | 三角函数 |
asin-flt64 | 21 | 三角函数 |
acos-flt64 | 22 | 三角函数 |
atan-flt64 | 23 | 三角函数 |
跳转指令
直接跳转指令
文本格式: goto imm
助记符 | 操作码 | 对齐 | 立即数 | 注解 |
---|
| 8 bit | | 8 bit | 指令宽度: 16 bit |
goto8 | | | imm | 8 bit有符号偏移 |
| 8 bit | 8 bit | 16 bit | 指令宽度: 32 bit |
goto16 | | | imm | |
| 8 bit | 8 bit | 32 bit | 指令宽度: 48 bit |
goto32 | | | imm | |
分支跳转指令
文本格式
jbr src,src2,imm
jbr src,imm
- 类型编码:标识操作数的类型。
- 操作子码:标识比较方法。
- 和 0 比较时,无源操作数 src2。
助记符 | 操作码 | 操作子码 | 类型码 | 源操作数 | 源操作数 | 立即数 | 注解 |
---|
| 8 bit | 4 bit | 4 bit | | | | |
| | | | 8 bit | 8 bit | 16 bit | 指令宽度: 32 bit |
| | | | 8 bit | 8 bit | 32 bit | 指令宽度: 32 bit |
| | | | 16 bit | 16 bit | 16 bit | 指令宽度: 32 bit |
| | | | 16 bit | 16 bit | 32 bit | 指令宽度: 32 bit |
| | | | src | src2 | imm | |
操作子码
助记符 | 操作子码 | 注解 |
---|
eq | 0 | if( src == src2 ) goto imm |
ne | 1 | if( src != src2 ) goto imm |
lt | 2 | if( src < src2 ) goto imm |
le | 3 | if( src <= src2 ) goto imm |
gt | 4 | if( src > src2 ) goto imm |
ge | 5 | if( src >= src2 ) goto imm |
eqz | 6 | if( src == 0 ) goto imm |
nez | 7 | if( src != 0 ) goto imm |
ltz | 8 | if( src < 0 ) goto imm |
lez | 9 | if( src <= 0 ) goto imm |
gtz | 10 | if( src > 0 ) goto imm |
gez | 11 | if( src >= 0 ) goto imm |
注意: 和 0 比较时,无源操作数 src2。
类型码
助记符 | 操作子码 | 注解 |
---|
int32 | 0 | 32 位有符号比较 |
uint32 | 1 | 32 位无符号比较 |
int64 | 2 | 64 位有符号比较 |
uint64 | 3 | 64 位无符号比较 |
flt32 | 4 | 32 位浮点数比较 |
flt64 | 5 | 64 位浮点数比较 |
返回指令
文本格式: op src
op imm
助记符 | 操作码 | 操作子码 | 立即数码 | 源操作数 | 注解 |
---|
| 8 bit | | | 8 bit | 指令宽度: 16 bit |
return-void | | | | | 无参数返回 |
return-w32-I8 | | | | | 返回 32 bit 值 |
return-w64-I8 | | | | | 返回 64 bit 值 |
| | | | | |
| 8 bit | 4 bit | 4 bit | 16/32/64 bit | |
操作子码
助记符 | 操作子码 | 注解 |
---|
I16 | 0 | 寄存器索引16位 |
int32 | 1 | 立即数转换到32位有符号整数 |
uint32 | 2 | 立即数转换到32位有符号整数 |
int64 | 3 | 立即数转换到32位有符号整数 |
uint64 | 4 | 立即数转换到32位有符号整数 |
flt32 | 5 | 立即数转换到32位有符号整数 |
flt64 | 6 | 立即数转换到32位有符号整数 |
立即数码
助记符 | 操作子码 | 注解 |
---|
B16 | 0 | 16 位立即数 |
B32 | 1 | 32 位立即数 |
B64 | 2 | 64 位立即数 |
函数调用指令
不固定参数调用
文本格式:op argcnt, arg,arg2,…,func
助记符 | 操作码 | 参数个数 | 参数寄存器 | 函数 | 注解 |
---|
| 8 bit | 8 bit | 16 bit | 32 bit | |
invoke-virtual-nofix | | argcnt | arg… | func | 调用虚函数 |
invoke-direct-nofix | | argcnt | arg… | func | 直接调用函数 |
invoke-static-nofix | | argcnt | arg… | func | 调用静态函数 |
invoke-interface-nofix | | argcnt | arg… | func | 调用接口函数 |
invoke-native-nofix | | argcnt | arg… | func | 调用C语言函数 |
范围参数调用
文本格式:op argcnt,start, end,func
助记符 | 操作码 | 参数个数 | 起始寄存器 | 结束寄存器索引 | 函数 | 注解 |
---|
| 8 bit | 8 bit | 16 bit | 16 bit | 32 bit | |
invoke-virtual-range | | argcnt | arg… | func | 调用虚函数 | |
invoke-direct-range | | argcnt | arg… | func | 直接调用函数 | |
invoke-static-range | | argcnt | arg… | func | 调用静态函数 | |
invoke-interface-range | | argcnt | arg… | func | 调用接口函数 | |
invoke-native-range | | argcnt | arg… | func | 调用C语言函数 | |
获取返回值指令
文本格式:op des
助记符 | 操作码 | 对齐 | 源寄存器 | 注解 |
---|
| 8 bit | | 8 bit | 指令宽度: 16 bit |
get-result-w32-I8 | | | des | 获取32位返回值 |
get-result-w64-I8 | | | des | 获取64位返回值 |
get-result-obj-I8 | | | des | 获取对象返回值 |
| 8 bit | 8 bit | 16 bit | 指令宽度: 32 bit |
get-result-w32-I16 | | | des | 获取32位返回值 |
get-result-w64-I16 | | | des | 获取64位返回值 |
get-result-obj-I16 | | | des | 获取对象返回值 |
异常处理指令
文本格式:op des
助记符 | 操作码 | 对齐 | 源寄存器 | 注解 |
---|
| 8 bit | | 8 bit | 指令宽度: 16 bit |
get-exception-I8 | | | des | 获取异常对象 |
throw-I8 | | src | 抛出异常对象 | |
| 8 bit | 8 bit | 16 bit | 指令宽度: 32 bit |
get-exception-I16 | | | des | 获取异常对象 |
throw-I16 | | src | 抛出异常对象 | |
7.3 基于栈和寄存器的指令集
本章节描述的是作者按照 RISC 指令系统设计的虚拟机指令集。
其类似与硬件指令集,可作为编译器后端指令系统目标,用于提供类似硬件指令系统环境,避免编译原理初学者陷入对硬件指令系统不了解的深渊。
降低学习难度,提高学习效率。
这类指令的主要特点如下:
- 1 寄存器的数量固定;
- 2 指令所操作的寄存器数量固定;
- 3 指令的含义简单;
1 寄存器
虚拟机的寄存器分为三种:
- 1 整数寄存器:主要用于整数运算,位宽为 64 bit,根据指令的含义可选择 32 bit 和 64 bit 运算模式。
- 2 浮点寄存器:主要用于浮点数运算,位宽为 64 bit,和通用寄存器一致,可选择位宽模式。
- 3 系统寄存器:对用户不可见,与虚拟机运行系统相关,对其进行操作隐藏在相关指令的实现细节中。
- 4 根据指令格式,整数寄存器、浮点寄存器最多可以有32个。
2 指令格式
每条指令是 32bit 大小对齐的,其中最低 9bit 是操作码,其余23bit作为操作数或者操作码的补充。如下表所示:
2.1 格式1
2.2 格式2
多数指令使用此格式。
操作码 | 目的操作数 | 源操作数 | 源操作数 | 操作子码 |
---|
9 bit | 5 bit | 5 bit | 5 bit | 8 bit |
2.3 格式3
该格式主要用于比较指令后的三元选择赋值操作。
操作码 | 目的操作数 | 源操作数 | 源操作数 | 源操作数 | 操作子码 |
---|
9 bit | 5 bit | 5 bit | 5 bit | 5 bit | 3 bit |
2.4 格式4
当指令中需要使用立即数时,且在指令中没有足够的空间可以存储时,可以使用指令后跟32bit对齐的立即数操作数。
- 32bit立即数:32bit 指令跟 1 个 32bit 立即数,虚拟机解析执行时,按照指令表达的语义参与运算。
- 64bit立即数:32bit 指令跟 2 个 32bit 立即数,虚拟机解析执行时,按照指令表达的语义,组合成 64bit,后参与运算。
- 其他位宽的立即数类似。
格式如下所示:
指令 | 立即数 1 | 立即数 2 | … | 立即数 n |
---|
32 bit | 32 bit | 32 bit | … | 32 bit |
3 寄存器与寄存器—指令集
3.1 空指令
空指令一般用于对齐,在本指令集中没有特殊含义,执行空操作。
格式如下:
助记符 | 操作码 | 操作数 |
---|
| 9 bit | 23 bit |
Nop | 0 | 0 |
3.2 算术运算
算术运算包含 +、-、*、/、%,支持的运算类型有 int32、uint32、int64、uint64、flt32、flt64。
- 文本格式: op des,src,src2
- 指令含义:des = src op src2
- 子操作码:可以用于将运算结果进行截断、扩展。
- 助记符后缀的数字(32、64)标识指令运算使用的寄存器位宽。
- 助记符后缀的 i 表示进行有符号运算。
- 助记符后缀的 u 表示进行无符号运算。
- 助记符后缀的 f 表示进行有符号运算。
指令格式如下所示:
助记符 | 操作码 | 目的操作数 | 源操作数 | 源操作数 | 操作子码 |
---|
| 9 bit | 5 bit | 5 bit | 5 bit | 8 bit |
| | | | | |
add-i32 | | des | src | src2 | |
sub-i32 | | des | src | src2 | |
mul-i32 | | des | src | src2 | |
div-i32 | | des | src | src2 | |
mod-i32 | | des | src | src2 | |
| | | | | |
add-u32 | | des | src | src2 | |
sub-u32 | | des | src | src2 | |
mul-u32 | | des | src | src2 | |
div-u32 | | des | src | src2 | |
mod-u32 | | des | src | src2 | |
| | | | | |
add-i64 | | des | src | src2 | |
sub-i64 | | des | src | src2 | |
mul-i64 | | des | src | src2 | |
div-i64 | | des | src | src2 | |
mod-i64 | | des | src | src2 | |
| | | | | |
add-u64 | | des | src | src2 | |
sub-u64 | | des | src | src2 | |
mul-u64 | | des | src | src2 | |
div-u64 | | des | src | src2 | |
mod-u64 | | des | src | src2 | |
| | | | | |
add-f32 | | des | src | src2 | |
sub-f32 | | des | src | src2 | |
mul-f32 | | des | src | src2 | |
div-f32 | | des | src | src2 | |
| | | | | |
add-f64 | | des | src | src2 | |
sub-f64 | | des | src | src2 | |
mul-f64 | | des | src | src2 | |
div-f64 | | des | src | src2 | |
3.2 位运算
位运算包括位相关的与、或、非、异或、移位、取反等运算。
支持的运算类型有 uint32、uint64。
- 文本格式: op des,src,src2
- 指令含义:des = src op src2
- 子操作码:可以用于将运算结果进行截断、扩展。
- i32:表示进行 32bit 的位运算。
- i64:表示进行 64bit 的位运算。
- 位运算都是看作无符号运算。
指令格式如下所示:
助记符 | 操作码 | 目的操作数 | 源操作数 | 源操作数 | 操作子码 |
---|
| 9 bit | 5 bit | 5 bit | 5 bit | 8 bit |
| | | | | |
sl-i32 | | des | src | src2 | |
sr-i32 | | des | src | src2 | |
sra-i32 | | des | src | src2 | |
and-i32 | | des | src | src2 | |
or-i32 | | des | src | src2 | |
xor-i32 | | des | src | src2 | |
andn-i32 | | des | src | src2 | |
orn-i32 | | des | src | src2 | |
xorn-i32 | | des | src | src2 | |
not-i32 | | des | src | src2 | |
| | | | | |
sl-i64 | | des | src | src2 | |
sr-i64 | | des | src | src2 | |
sra-i64 | | des | src | src2 | |
and-i64 | | des | src | src2 | |
or-i64 | | des | src | src2 | |
xor-i64 | | des | src | src2 | |
andn-i64 | | des | src | src2 | |
orn-i64 | | des | src | src2 | |
xorn-i64 | | des | src | src2 | |
not-i64 | | des | src | src2 | |
3.3 逻辑比较
逻辑比较运算包括:<、>、<=、>=、==、!=、 ==0、!=0.
支持的运算类型有 int32、uint32、int64、uint64、flt32\flt64。
- 文本格式: op des,src,src2
- 指令含义:des = src op src2
- 子操作码:可以用于标识比较的方法。
- 比较的结果,存储在整数寄存器中,且使用位宽 64 bit,即des是整数寄存器。
指令格式如下所示:
助记符 | 操作码 | 目的操作数 | 源操作数 | 源操作数 | 操作子码 |
---|
| 9 bit | 5 bit | 5 bit | 5 bit | 8 bit |
| | | | | |
cmp-i32 | | des | src | src2 | |
cmp-u32 | | des | src | src2 | |
cmp-i64 | | des | src | src2 | |
cmp-u64 | | des | src | src2 | |
cmp-f32 | | des | src | src2 | |
cmp-f64 | | des | src | src2 | |
操作子码定义如下:
助记符 | 操作码 | 含义 |
---|
lt | | < |
le | | <= |
gt | | > |
ge | | >= |
eq | | == |
ne | | != |
ez | | ==0,此时没有源操作数src2 |
nz | | !=0,此时没有源操作数src2 |
当不使用操作子码,而是使用下面方式运算:
- src < src2,设置des寄存器为 -1。
- src == src2,设置des寄存器为 0。
- src > src2,设置des寄存器为 -1。
3.4 条件赋值
条件赋值指令使用比较指令的结果,对另外 2 个源操作数进行选择,传递个目标操作数。
指令格式如下所示:
助记符 | 操作码 | 目的操作数 | 源操作数 | 源操作数 | 源操作数 | 操作子码 |
---|
| 9 bit | 5 bit | 5 bit | 5 bit | 5 bit | 3 bit |
sel-i32 | | des | src | src2 | cond | |
sel-u32 | | des | src | src2 | cond | |
sel-i64 | | des | src | src2 | cond | |
sel-u64 | | des | src | src2 | cond | |
sel-f32 | | des | src | src2 | cond | |
sel-f64 | | des | src | src2 | cond | |
当比较系列指令使用操作子码方式时:
- cond == 0 :des = src
- cond != 0 :des = src2
当比较系列指令不使用操作子码方式时,本系列指令要求使用操作子码进行判断:
操作子码定义如下:
助记符 | 操作码 | 含义 |
---|
lt | | < :des = cond == -1 ? src : src2 |
le | | <= :des = cond < 1 ? src : src2 |
gt | | > :des = cond == 1 ? src : src2 |
ge | | >= :des = cond > -1 ? src : src2 |
eq | | == :des = cond == 0 ? src : src2 |
ne | | != :des = cond != 0 ? src : src2 |
3.5 赋值指令
此系列包括寄存器间赋值或类型转换。
助记符 | 操作码 | 目的操作数 | 源操作数 | 源操作数 | 操作子码 |
---|
| 9 bit | 5 bit | 5 bit | 5 bit | 8 bit |
| | | | | |
mov | | des | src | | |
操作子码用于获取源操作数并转换到响应的类型。
操作子码定义如下:
助记符 | 操作码 | 含义 |
---|
i8-i32 | | |
u8-i32 | | |
i8-i64 | | |
u8-u64 | | |
| | |
i16-i32 | | |
u16-i32 | | |
i16-i64 | | |
u16-i64 | | |
| | |
i32_i32 | | |
i32-i64 | | |
i32-f32 | | |
i32-f64 | | |
| | |
u32-u32 | | |
u32-u64 | | |
u32-f32 | | |
u32-f64 | | |
| | |
i64-i64 | | |
i64-f32 | | |
i64-f64 | | |
| | |
u64-u64 | | |
u64-f32 | | |
u64-f64 | | |
| | |
f32-i32 | | |
f32-u32 | | |
f32-i64 | | |
f32-u64 | | |
f32-f32 | | |
f32-f64 | | |
| | |
f64-i32 | | |
f64-u32 | | |
f64-i64 | | |
f64-u64 | | |
f64-f32 | | |
f64-f64 | | |
| | |
f32-bit-u32 | | 位转换 |
u32-bit-f32 | | 位转换 |
f64-bit-u64 | | 位转换 |
u64-bit-f64 | | 位转换 |
3.6 加载存储指令
此系列指令功能是从内存中读取、存储特定类型数据。
助记符 | 操作码 | 目的操作数 | 源操作数 | 源操作数 | 操作子码 | 注释 |
---|
| 9 bit | 5 bit | 5 bit | 5 bit | 8 bit | |
| | | | | | |
load | | des | base | offset | | 从基址内存中获取数据 |
store | | des | base | offset | | |
| | | | | | |
gload | | des | base | offset | | 从全局内存中获取数据 |
gstore | | des | base | offset | | |
操作子码定义如下:
助记符 | 操作码 | 含义 |
---|
i8 | | |
u8 | | |
i16 | | |
u16 | | |
i32 | | |
u32 | | |
i64 | | |
u64 | | |
f32 | | |
f64 | | |
3.7 出入栈指令
此系列指令用于将数据入栈,同时可以进行类型转换。
注意:入栈数据应当进行 32bit 对齐。以加快虚拟机执行速度数据
助记符 | 操作码 | 目的操作数 | 源操作数 | 源操作数 | 操作子码 |
---|
| 9 bit | 5 bit | 5 bit | 5 bit | 8 bit |
| | | | | |
push | | des | | | |
pop | | des | | | |
操作子码定义如下: | | | | | |
助记符 | 操作码 | 含义 | | | |
— | — | — | | | |
i8 | | | | | |
u8 | | | | | |
i16 | | | | | |
u16 | | | | | |
i32 | | | | | |
u32 | | | | | |
i64 | | | | | |
u64 | | | | | |
f32 | | | | | |
f64 | | | | | |
3.8 栈内存分配释放
此系列指令用于栈内存分配释放。
注意:立即数是无符号整数。
助记符 | 操作码 | 目的操作数 | 立即数 | 注释 |
---|
| 9 bit | 5 bit | 18 bit | |
grown | | des | imm | 分配栈内存,将分配后的栈指针值传递到 des 寄存器 |
| 9 bit | 23 bit | 释放栈内存, | |
shrunk | | imm | | |
3.9 跳转指令
- 跳转的偏移量是无符号整数值;
- 相对于函数代码的起始地址;
- 偏移量是偏移的指令条数;
助记符 | 操作码 | 目的操作数 | 立即数 | 注释 |
---|
| 9 bit | 23 bit | | |
jmp | | imm | | 直接跳转 |
| 9 bit | 5 bit | 18 bit | |
jmpx | | reg | | 偏移量在 reg 寄存器中 |
| 9 bit | 5 bit | 18 bit | |
jtab | | reg | imm | reg 表示偏移量索引,imm表示偏移量数组中偏移数据条数,指令后面接 32 bit 对齐的偏移量数组 |
3.10 分支指令
此系列指令用于条件分支跳转。
助记符 | 操作码 | 目的操作数 | 源操作数 | 源操作数 | 操作子码 | 偏移立即数 |
---|
| 9 bit | 5 bit | 5 bit | 5 bit | 8 bit | 32 bit |
jbr-i32 | | src | src2 | | cond | offset |
jbr-u32 | | src | src2 | | cond | offset |
jbr-i64 | | src | src2 | | cond | offset |
jbr-u64 | | src | src2 | | cond | offset |
jbr-f32 | | src | src2 | | cond | offset |
jbr-f64 | | src | src2 | | cond | offset |
操作子码定义如下:
助记符 | 操作码 | 含义 |
---|
lt | | < |
le | | <= |
gt | | > |
ge | | >= |
eq | | == |
ne | | != |
ez | | ==0,此时没有源操作数src2 |
nz | | !=0,此时没有源操作数src2 |
3.11 函数指令
助记符 | 操作码 | 目的操作数 | 立即数 | 注释 |
---|
| 9 bit | 23 bit | 32 bit | |
call | | | imm | imm表示函数的偏移量或者是编号,看虚拟机的具体实现 |
| 9 bit | 5 bit | 18 bit | |
callx | | reg | | reg 寄存器中保存函数的偏移量或者是编号,看虚拟机的具体实现 |
| 9 bit | 23 bit | | |
ret | | | | 函数返回 |
4 寄存器与立即数–指令集
待续