计算机组成与设计:硬件软件接口(RISC-V版)

第二章总结

本篇主要总结RSIC-V的指令集,分别介绍不同类型的指令功能以及指令的使用示例。

RISC-V指令集采用模块化设计,以书中介绍的为例,大体可将指令类型分为六种基本格式,分别为R型指令、I型指令、S型指令、B型指令、U型指令、J型指令。下面对每一种指令进行逐一介绍。

R型指令(寄存器-寄存器操作)

R型指令用于寄存器间的算术/逻辑运算,所有操作数均来自寄存器。

下面是R型指令格式:

funct7 rs2 rs1 funct3 rd opcode
7位 5位 5位 3位 5位 7位
其中:

opcode(操作码):指令的基本操作,这个缩写是它的惯用名称。

rd:目的操作数寄存器,用来存放操作结果。

funct3:一个另外的操作码字段。

rs1:第一个源操作数寄存器。

rs2:第二个源操作数寄存器。

funct7:一个另外的操作码字段。

R型指令包括:add、sub、sll、xor、srl、sra、or、and、lr.d、sc.d。

格式 指令 操作码 Funct3 Funct6/7
R型 add 0110011 000 0000000
R型 sub 0110011 000 0100000
R型 sll 0110011 001 0000000
R型 xor 0110011 100 0000000
R型 srl 0110011 101 0000000
R型 sra 0110011 101 0000000
R型 or 0110011 110 0000000
R型 and 0110011 111 0000000
R型 lr.d 0110011 011 0001000
R型 sc.d 0110011 011 0001100

示例:

1、add x5, x6, x7 

二进制编码:

0000000 | 00111 | 00110 | 000 | 00101 | 0110011

功能:寄存器加法(x5 = x6 + x7

2、sub x5, x6, x7

二进制编码:

0100000 | 00111 | 00110 | 000 | 00101 | 0110011

功能:寄存器减法(x5 = x6 + x7)

3、sll x5, x6, x7

二进制编码:

0000000 | 00111 | 00110 | 001 | 00101 | 0110011

功能:逻辑左移(x5 = x6 << x7

4、xor x5, x6, x9

二进制编码:

0000000 | 01001 | 00110 | 100 | 00101 | 0110011

功能:按位异或(x5 = x6 ^ x9

5、srl x5, x6, x7

二进制编码:

0000000 | 00111 | 00110 | 101 | 00101 | 0110011

功能:逻辑右移(x5 = x6 >> x7,高位补0)

6、sra x5, x6, x7

二进制编码:

0100000 | 00111 | 00110 | 101 | 00101 | 0110011

功能:算术右移(x5 = x6 >> x7,高位补符号位)

7、or x5, x6, x8

二进制编码:

0000000 | 01000 | 00110 | 110 | 00101 | 0110011

功能:按位或(x5 = x6 | x8

8、and x5, x6, x7

二进制编码:

0000000 | 00111 | 00110 | 111 | 00101 | 0110011

功能:按位与(x5 = x6 & x7

9、lr.d x5,  (x6)

二进制编码:

0001000 | 00000 | 00110 | 010 | 00101 | 0101111

功能:原子加载双字(从地址x6加载64位数据到x5,并在x6地址处标记原子保留)

10、sc.d x7, x5,  (x6)

二进制编码:

0001100 | 00101 | 00110 | 011 | 00111 | 0101111

功能:原子条件存储双字(先判断 x6内存是否有设置保留标记,如果设置了,则把 x5 值写入到x6地址中,并把 x7 寄存器设置成 0,表示保存成功。如果x6内存地址没有设置保留标记,则不保存,并把 x7 寄存器设置成 1 表示保存失败。)

I型指令(立即数操作与加载)

I型指令用于处理寄存器与立即数的运算,或从内存加载数据。

下面是I型指令格式:

immediate rs1 funct3 rd opcode
12位 5位 3位 5位 7位

其中:immediate代表12位符号数扩展值,部分指令(如移位)使用低5位,其余部分的字段含义与R型指令保持一致。

I型指令包括:lb, lh, lw, ld, lbu, lhu, lwu, addi, slli, xori, srli, srai, ori, andi, jalr。

格式 指令 操作码 Funct3 Funct6/7
I型 lb 0000011 000 n.a.
I型 lh 0000011 001 n.a.
I型 lw 0000011 010 n.a.
I型 ld 0000011 011 n.a.
I型 lbu 0000011 100 n.a.
I型 lhu 0000011 101 n.a.
I型 lwu 0000011 110 n.a.
I型 addi 0010011 000 n.a.
I型 slli 0010011 001 000000
I型 xori 0010011 100 n.a.
I型 srli 0010011 101 000000
I型 srai 0010011 101 010000
I型 ori 0010011 110 n.a.
I型 andi 0010011 111 n.a.
I型 jalr 1100111 000 n.a.

n.a.:表示该字段无对应指令。

示例:

1、lb x5, 40(x6)

二进制编码:

000000101000 | 00110 | 000 | 00101 | 0000011

功能:从内存地址 x6 + 40 加载一个字节(符号扩展)到 x5

2、lh x5, 40(x6)

二进制编码:

000000101000 | 00110 | 001 | 00101 | 0000011

功能:从内存地址 x6 + 40 加载半字(符号扩展)到 x5

3、lw x5, 40(x6)

二进制编码:

000000101000 | 00110 | 010 | 00101 | 0000011

功能:从内存地址 x6 + 40 加载字(符号扩展)到 x5

4、ld x5, 40(x6)

二进制编码:

000000101000 | 00110 | 011 | 00101 | 0000011

功能:从内存地址 x6 + 40 加载双字(符号扩展)到 x5

5、lbu x5, 40(x6)

二进制编码:

000000101000 | 00110 | 100 | 00101 | 0000011

功能:从内存地址 x6 + 40 加载一个字节(零扩展)到 x5

6、lhu x5, 40(x6)

二进制编码:

000000101000 | 00110 | 101 | 00101 | 0000011

功能:从内存地址 x6 + 40 加载半字(零扩展)到 x5

7、lwu x5, 40(x6)

二进制编码:

000000101000 | 00110 | 110 | 00101 | 0000011

功能:从内存地址 x6 + 40 加载字(零扩展)到 x5

8、addi x5, x6, 20

二进制编码:

000000010100 | 00110 | 000 | 00101 | 0010011

功能:x5 = x6 + 20(立即数加法)

9、slli x5, x6, 3

二进制编码:

0000000 | 00011 | 00110 | 001 | 00101 | 0010011

功能:x5 = x6 << 3(逻辑左移)

10、xori x5, x6, 20

二进制编码:

000000010100 | 00110 | 100 | 00101 | 0010011

功能:x5 = x6 ^ 20(按位异或)

11、srli x5, x6, 3

二进制编码:

0000000 | 00011 | 00110 | 101 | 00101 | 0010011

功能:x5 = x6 >> 3(逻辑右移)

12、srai x5, x6, 3

二进制编码:

0100000 | 00011 | 00110 | 101 | 00101 | 0010011

功能:x5 = x6 >> 3(算术右移,高位补符号位)

13、ori x5, x6, 20

二进制编码:

000000010100 | 00110 | 110 | 00101 | 0010011

功能:x5 = x6 | 20(按位或)

14、andi x5, x6, 20

二进制编码:

000000010100 | 00110 | 111 | 00101 | 0010011

功能:x5 = x6 & 20(按位与)

15、jalr x1, 100(x5)

二进制编码:

000001100100 | 00101 | 000 | 00001 | 1100111

功能:程序跳转到地址 x5 + 100,并将返回地址(PC + 4)存入x1寄存器

S型指令(存储操作)

S型指令用于将寄存器数据写入内存,操作数包含基址寄存器和立即数偏移。

下面是S型指令格式:

immediate[11:5] rs2 rs1 funct3 immediate[4:0] opcode
7位 5位 5位 3位 5位 7位

其中:与I型指令不同的是,S型指令的立即数部分拆分为了两块,这在一定程度上可以减轻译码电路的复杂度。

S型指令包括:sb, sh, sw, sd。

格式 指令 操作码 Funct3 Funct6/7
S型 sb 0100011 000 n.a.
S型 sh 0100011 001 n.a.
S型 sw 0100011 010 n.a.
S型 sd 0100011 111 n.a.

示例:

1、sb x5, 40(x6)

二进制编码:

0000101 | 00101 | 00110 | 000 | 000 | 0100011

功能:将寄存器 x5 的低8位(字节)存储到内存地址 x6 + 40

2、sh x5, 40(x6)

二进制编码:

0000101 | 00101 | 00110 | 001 | 000 | 0100011

功能:将寄存器 x5 的低16位(半字)存储到内存地址 x6 + 40

3、sw x5, 40(x6)

二进制编码:

0000101 | 00101 | 00110 | 010 | 000 | 0100011

功能:将寄存器 x5 的32位(字)存储到内存地址 x6 + 40

4、sd x5, 40(x6)

二进制编码:

0000101 | 00101 | 00110 | 011 | 000 | 0100011

功能:将寄存器 x5 的64位(双字)存储到内存地址 x6 + 40

B型指令(条件分支)

B型指令会根据条件跳转到目标地址,用于控制流分支。

下面是B型指令格式:

immediate[12,10:5] rs2 rs1 funct3 immediate[4:1,11] opcode
7位 5位 5位 3位 5位 7位

其中:B型指令的12位立即数会被符号扩展为32位,再左移1位,形成最终的分支偏移量。B型指令的特点是拆分后的立即数字段通过旋转拼接,避免了硬件中的移位操作,减少资源消耗。

B型指令包括beq, bne, blt, bge, bltu, bgeu。

格式 指令 操作码 Funct3 Funct6/7
B型 beq 1100111 000 n.a.
B型 bne 1100111 001 n.a.
B型 blt 1100111 100 n.a.
B型 bge 1100111 101 n.a.
B型 bltu 1100111 110 n.a.
B型 bgeu 1100111 111 n.a.

示例:

1、beq x5, x6, 100

二进制编码:

0000011 | 00110 | 00101 | 000 | 00100 | 1100011

功能:若 x5 == x6,则跳转到 PC + 100

2、bne x5, x6, 100

二进制编码:

0000011 | 00110 | 00101 | 001 | 00100 | 1100011

功能:若 x5 != x6,则跳转到 PC + 100

3、blt x5, x6, 100

二进制编码:

0000011 | 00110 | 00101 | 100 | 00100 | 1100011

功能:若 x5 < x6(有符号比较),则跳转到 PC + 100

4、bge x5, x6, 100

二进制编码:

0000011 | 00110 | 00101 | 101 | 00100 | 1100011

功能:若 x5 ≥ x6(有符号比较),则跳转到 PC + 100

5、bltu x5, x6, 100

二进制编码:

0000011 | 00110 | 00101 | 110 | 00100 | 1100011

功能:若 x5 < x6(无符号比较),则跳转到 PC + 100

6、bgeu x5, x6, 100

二进制编码:

0000011 | 00110 | 00101 | 111 | 00100 | 1100011

功能:若 x5 ≥ x6(无符号比较),则跳转到 PC + 100

U型指令(高位立即数操作)和J型指令(无条件跳转)

U型指令常用于处理20位高位立即数,用于构造大常数或地址。

J型指令可以实现长距离跳转,通常用于函数调用。

下面是U型指令和J型指令的指令格式:

immediate[31:12] rd opcode
20位 5位 7位

U型指令的立即数字段取的是需要加载的立即数的高20位,例如当需要加载0X12345678时,则需要在立即数字段上填写0X12345。

imm[20] imm[10:1] imm[11] imm[19:12] rd opcode
1位 10位 1位 8位 5位 7位

J型指令立即数字段的编码规则为:

imm[20] → 符号位(最高位)
imm[10:1] → 中间10位(位10到1)
imm[11] → 第11位
imm[19:12] → 高位8位(位19到12)

实际偏移量:符号扩展后的20位立即数 ​左移1位​(确保跳转地址按2字节对齐)

U型指令有lui。J型指令有jal。

格式 指令 操作码 Funct3 Funct6/7
U型 lui 0110111 n.a. n.a.
J型 jal 1101111 n.a. n.a.

示例:

U型指令 以加载一个大立即数0X12345678为例。

首先使用

lui x5, 0x12345

0001 0010 0011 0100 0101 | 00101 | 0110111

将大立即数的高20位加载在x5寄存器中(此时寄存器中的数据为0x12345000)。

然后使用

addi x5, x5, 0x678

011001111000 | 00101 | 000 | 00101 | 0010011

将大立即数的低12位加载到x5寄存器中(此时寄存器中的数据为0x12345678)。

此处需要注意的是,在使用addi指令时,由于立即数的扩展方式为符号扩展。因此,当需要加载的数据第11位为1时,使用上述方法加载大数据时要进行变化。

例:加载大立即数0X89ABCDEF至x5寄存器

首先进行拆解0X89ABCDEF → 0X89ABD , 0XDEF

然后分别使用

lui x5, 0x89ABD

addi x5, x5, 0xDEF

不难看出在上述拆解时,在高20位拆解后多加了一个1,这就是由于addi指令的符号扩展原因导致。如果使用0X89ABC进行加载,则最终结果为

0X89AB C000 + 0XFFFF FDEF = 0X89AB BDEF。

当采用0x89ABD时,最终结果为:

0X89AB D000 + 0XFFFF FDEF = 0X89AB CDEF。

所以在使用 lui 和 addi 指令加载大立即数时要格外注意这一点。

J型指令

jal x1, 0x1000

二进制编码:

0 | 0000000000 | 0 | 00000001 | 00001 | 1101111

功能:无条件跳转到目标地址 ​PC + 0x1000,并将返回地址(当前指令的下一条指令地址,即 ​PC + 4)存入寄存器 ​x1。

以上内容就是对RSIC-V中指令的全部介绍,若其中有地方出现错误烦请读者批评指正。

你可能感兴趣的:(risc-v)