基本指令集占有0
~63
的指令编码码位,提供处理器管理指令以及最基本且必需的运算和寄存器、储存器管理指令。
在操作对象上,基本指令集中分为以下几种指令:
- 寄存器指令:绝大多数用到寄存器的指令都属于此类;
- 内存指令:
ldm
和stm
; - 转移指令:能直接作用于ip寄存器的指令;
- 系统管理指令:下表中有
*
的为系统管理指令。
一条指令分为两部分:
- 操作码:指令名对应的编码
- 操作数:操作数分为
寄存器操作数
、立即数操作数
和内存操作数
;大多数指令都使用寄存器操作数,只在某些必要的指令中使用立即数和内存操作数。
指令编号后有
*
的为系统管理指令,只能在内核态调用。 空白的指令编号为保留使用wide参数在指令名上体现在指令名后有b/w/d/q(字节、字、双字、四字)
q
结尾可以省略
编号 | 指令格式 | 编码 | 指令名 | 说明 |
---|---|---|---|---|
0 | nop | 00 | 空指令 | 暂停CPU直到中断产生 |
1 | add r1, r2, r3 | 01 r1[4],r2[4] r3[4],wide[4] | 加法 | |
2 | sub r1, r2, r3 | 02 r1[4],r2[4] r3[4],wide[4] | 减法 | |
3 | inc r1 | 03 r1[4],wide[4] | 自增1 | |
4 | dec r1 | 04 r2[4],wide[4] | 自减1 | |
5 | shl r1, r2 | 05 r1[4],r2[4] wide[8] | 左位移 | 将r2左移r1位 |
6 | shr r1, r2 | 06 r1[4],r2[4] wide[8] | 右位移 | |
7 | rol r1, r2 | 07 r1[4],r2[4] wide[8] | 左旋 | |
8 | ror r1, r2 | 08 r1[4],r2[4] wide[8] | 右旋 | |
9 | cmp r1, r2 | 09 r1[4],r2[4] | 比较 | |
10 | and r1, r2, r3 | 0a r1[4],r2[4] r3[4],wide[4] | 与运算 | |
11 | or r1, r2, r3 | 0b r1[4],r2[4] r3[4],wide[4] | 或运算 | |
12 | not r1, r2 | 0c r1[4],r2[4] wide[8] | 非运算 | |
13 | xor r1, r2, r3 | 0d r1[4],r2[4] r3[4],wide[4] | 异或运算 | |
14 | 0e | |||
15 | 0f | |||
16 | jc(w/d/q) imm | 10 16/32/64[4],cond[4] imm[16/32/64] | 跳转 | |
17 | cc(w/d/q) imm | 11 16/32/64[4],cond[4] imm[16/32/64] | 函数调用 | 将ip转储 |
18 | r | 12 | 从函数返回 | 将ipdump作为返回地址 |
19 | loop r, imm | 13 r1[8],imm[32] | 条件循环 | r为非零时跳转到相对地址imm处 |
20* | ir imm | 14 mod[8] | 从中断返回 | |
21 | sysc | 15 | 陷入内核态 | |
22* | sysr | 16 | 跳回用户态 | |
23 | 17 | |||
24 | 18 | |||
25 | 19 | |||
26 | 1a | |||
27 | 1b | |||
28 | 1c | |||
29 | 1d | |||
30 | 1e | |||
31 | 1f | |||
32 | ldi imm, r | 20 8/16/32/64[4],r[4] imm[8/16/32/64] | 加载立即数 | |
33 | ldm r1, r2 | 21 r1[4],r2[4] wide[8] | 从内存加载 | 将r1所指的内存处的数据加载到r2中(r1前可不加*号) |
34 | stm r1, r2 | 22 r1[4],r2[4] wide[8] | 保存到内存 | 将r1的内容保存到r2所指的内存中(r2前可不加*号) |
35* | in imm/r1,r2 | 23 r2[4],mvflg[4] imm[16]/r1[4] | 端口输入 | 第一个是端口号,第二个是储存输入的寄存器。 |
36* | out r1,imm/r2 | 24 r1[4],mvflg[4] imm[16]/r2[4] | 端口输出 | 第一个是储存输入的寄存器,第二个参数是端口号。 |
37 | 25 | |||
38 | 26 | |||
39 | 27 | |||
40 | 28 | |||
41 | 29 | |||
42 | 2a | |||
43 | 2b | |||
44 | 2c | |||
45 | 2d | |||
46 | 2e | |||
47 | 2f | |||
48* | ei | 30 | 使能中断 | |
49* | di | 31 | 关闭中断 | |
50* | ep | 32 | 使能分页 | |
51* | dp | 33 | 关闭分页 | |
52* | livt r | 34 r[8] | 加载中断向量表 | |
53* | lkpt r | 35 r[8] | 加载内核态页表 | |
54* | lupt r | 36 r[8] | 加载用户态页表 | |
55* | lscp r | 37 r[8] | 加载系统调用指针 | |
55 | lipdump r | 38 r[8] | 将ipdump加载到寄存器中 | |
57 | lflagdump r | 39 r[8] | 将flgdump加载到寄存器中 | |
58 | sipdump r | 3a r[8] | 将寄存器的值写入ipdump | |
59 | sflagdump r | 3a r[8] | 将寄存器的值写入flgdump | |
60 | cpuid | 3c | 获取处理器信息和一些硬件信息 | 详见cpuid一节 |
61* | initext r | 3d r[8] | 初始化扩展指令集 | r为指令集代码 |
62* | destext | 3e | 销毁扩展指令集 | |
63 | 3f |
- 条件指令名:
下表的条件指令名与条件码表一一对应
[jc] | [cc] |
---|---|
j | c |
jz | cz |
jx | cx |
jo | co |
je | ce |
jne | cne |
jh | ch |
jl | cl |
jnh | cnh |
jnl | cnl |
jb | cb |
js | cs |
jnb | cnb |
jns | cns |
- 条件码:
[cond] | 说明 | 注 |
---|---|---|
0 | non | |
1 | zero | |
2 | signed | |
3 | overflow | |
4 | equal | |
5 | n-equal | |
6 | higher | 将两数作为有符号整数比较 |
7 | lower | 将两数作为有符号整数比较 |
8 | n-higher | |
9 | n-lower | |
a | bigger | 将两数作为无符号整数比较 |
b | smaller | 将两数作为无符号整数比较 |
c | n-bigger | |
d | n-smaller |
- 中断返回模式码
[mod] | 说明 |
---|---|
0 | panic, 复位CPU |
1 | retry, 重新执行指令 |
- 移动指令标志位
[mvflg] | 说明 |
---|---|
0 | r1,r2 |
1 | r,m |
2 | m,r |
3 | m1,m2 |
cpuid指令可获得处理器的硬件信息。(或者一些特殊功能)
x1中的
*
代表可以是任意值。
参数寄存器 | x0 | x1 | 返回结果 |
---|---|---|---|
0 | * | EOM,最多32字节,存在x0、x1、x2、x3中 | |
1 | * | 共有多少核心,存在x0中 | |
2 | * | 返回此核心的id,存在x0中 | |
3 | * | 在运行vrisc的终端中输出x1指向的字符串 | |
4 | * | x0: 物理硬件(0)/软件模拟(1)/带jit的软件模拟(2)/虚拟化(4) |
- 通用寄存器:16个,
x0
~x15
- 指令指针寄存器:虚拟机初始化时为0;SMP多核架构中开启核心0之外的核心时使用io接口配置ip寄存器; 与通常不同,由于指令集实现为纯软件,指向目前要执行的指令比指向下一条指令更加合理。
- 标志位寄存器:标志系统状态
- ^0 零标志:指令的目标操作数在指令执行后的值为0时置位
- ^1 符号标志:指令的目标操作数是寄存器,指令执行后的目标寄存器最高位
- ^2 溢出标志:指令的目标操作数是寄存器,指令执行后的目标寄存器值小于任意一个源寄存器值
- ^3 相等标志:cmp指令执行后设置
- ^4 绝对大于标志:cmp指令执行后设置
- ^5 绝对小于标志:cmp指令执行后设置
- ^6 相对大于标志:cmp指令执行后设置
- ^7 相对小于标志:cmp指令执行后设置
- ^8 中断使能标志
- ^9 分页使能标志
- ^10 特权级标志(0: 内核态)
- 中断向量表寄存器:指向中断向量表(中断向量表有关详见中断机制)
- 内核态/用户态页表指针寄存器:分页机制相关寄存器(见分页机制)
- 系统调用指针寄存器
- 中断信息寄存器:发生中断时中断信息存在此寄存器
- ipdump寄存器:在发生跳转或中断时,跳转前的ip将被转存至此
- flagdump寄存器:在发生中断时,跳转前的ip将被转存至此
分页机制由标志位寄存器
的第7位开启。
分为用户态
和内核态
两组页表。
顶级页目录由内核态/用户态页表指针寄存器
储存。
通过分页机制,可以使用虚拟地址空间
来访问内存。
一个普通物理页的大小为16KB。
没有开启分页时,机器使用物理地址访问内存。
开启分页时,使用虚拟地址访问内存。
虚拟地址为64位地址,包含整个虚拟地址空间;虚拟地址的最高位为用户标志位,最高位置位则表示此地址为用户态地址,否则表示内核态地址。
虚拟地址各位段的含义如下:
位 | 项目 |
---|---|
63 | 用户态标志 |
62~54 | 保留 |
53~44 | 四级页表项 |
43~34 | 三级页表项 |
33~24 | 二级页表项 |
23~14 | 一级页表项 |
13~0 | 页内偏移 |
一个页表项8字节,一个页表最多1024个页表项;
页表的起始地址只能是16K的整数倍;
页表项为一个物理地址,指向低一级的页表起始地址,一级页表项指向物理页起始地址;
页表项数少于1024个时,需要在最后一项后再填充一个64位整数0,表示页表结束。
由于页表项的最低14位一定是0,所以在最低14位中设置了一些标志位,表明它所指的页表或物理页的相关信息,如下:
位 | 项目 | 说明 |
---|---|---|
13~4 | 保留使用 | |
3 | 可写权限 | 0为不可写,1为可写 |
2 | 可读权限 | 0为不可读,1为可读 |
1 | 大页标志 | 置位说明此高级页表指向一个物理页,而不是下一级页表。一级页表项的此位无效。 |
0 | 有效标志 | 当此页表项指向一个物理页时,复位说明此页不在内存中。 |
大页是高级页表项直接指向的物理页。
当页表项的大页标志
置位时,高级页表项储存的值应为一个物理页的起始地址。
大页的大小:16M、16G、16T;只要你的内存足够大,就可以分配,机器不会限制。
操作系统应为系统调用提供一个入口函数,系统调用号可随意设置,系统调用过程中不对参数传递和堆栈操作做出任何要求。
vrisc通过扩展指令集来提供如基本数学运算扩展
、单指令多数据扩展
等额外功能。
扩展指令集需要用initext
与destext
指令对进行加载和卸载操作。