Menu Close

RISC-V指令集讲解(1)通用寄存器和汇编指令分类

1. RISC-V通用寄存器和程序计数器

 

相关参考文章:

RISC-V教学教案

 

在之前的RISC-V简介中主要有

RISC-V 简介(1)RISC-V的由来

RISC-V 简介(2)RISC-V指令集的特点及分类

RISC-V 简介(3)RISC-V处理器前景及中国CPU发展现状

RISC-V 简介(4)RISC-V指令集编码结构

本文将开始详细讲解RISC-V指令集。CPU中包含32个通用寄存器,有时候也会被称为通用寄存器文件,如图1所示。通用寄存器的命名方式为X0-X31。其中第一个寄存器X0的值,被硬连线到0,因此值永远是0。其他寄存器X1-X31都是可读可写的。0-31也叫做索引号,索引号也可以理解为寄存器的地址,当指令需要调用通用寄存器时可以通过索引号查找。之后将会在介绍FPGA程序时讲解如何设计读写寄存器文件。对于32位系统,所有通用寄存器的宽度都是32bit,寄存器总个数也是32个。

PC(program counter)是程序计数器,也是一个寄存器。在CPU中PC寄存器并不和上述32个通用寄存器在一起,寄存器文件中不包含PC。PC的宽度和通用寄存器的宽度一样。XLEN的值一般跟RISC-V CPU架构有关系。 如果是32位架构的CPU,那么XLEN的值就是32。图1中XLEN-1 = 32-1 =31,即在一个通用寄存器中的最高位为31。在64位CPU中通用寄存器的宽度是64,同时PC宽度也是64位,最高位为64-1 =63。

RISC-V通用寄存器

图1 RISC-V通用寄存器和PC [1]

 

2. RISC-V汇编指令类型

RV32I 可被分为六种基本指令格式:

  1. 用于寄存器-寄存器操作的R类型指令
  2. 用于立即数和访存load操作的I 型指令
  3. 用于访存store操作的S型指令
  4. 用于条件跳转操作的B类型指令
  5. 用于长立即数的U型指令
  6. 用于无条件跳转的J型指令

图2列出来6种基本指令的机器码格式。

RISC-V指令类型机器码格式

图2 6种基本指令的机器码格式 [2]

 

2.1. R-Type

R-type是无立即数(immediate number,imm,无须从寄存器中取值,就能立即得到的数)的操作。R-type汇编指令机器码的二进制格式如图2所示。一条二进制指令长度是32-bit。bit 0-6(7个bit)是opcode (operation code) 操作码,用来标识出指令的类型,图3是部分R-type 汇编指令的opcode,可以看到R-type指令所有的opcode都是相同的,为011_0011。但是在bit 12-14的funct3和bit 25-31的funct7是不一样的,并以此来区分不同的R-type汇编指令。也就是说,opcode决定指令的大致分类,funct3和funct7决定指令更细致的分类。R-type指令的Bit 7-11是rd(destination register,目的寄存器)的索引号。rd寄存器是用来存储结果的寄存器。rs1(source register 1)和rs2(source register 2)叫做源寄存器,多数情况下指令需要读取这两个源寄存器寄存器的值,用于之后的运算。rs1的索引号在bit 15-19,rs2的索引号在bit 20-24。下面对如何使用寄存器索引号进行举例说明。

RISC-V指令类型机器码格式

RISC-V R-type opcode

图3 部分R-type 指令opcode举例 [2]

当在指令中rd的位置索引号的值为5’b00011,也就是十进制的3时。CPU收到这条指令后会检测到bit 7-11的值是3,就会在32个通用寄存器中找到X3寄存器作为rd寄存器,最后把结果写到x3寄存器里。如果此时在rs1 和rs2的索引号位置(二进制汇编指令)中bit 15-19 和bit 20-24的值是2和4,CPU会检测到在指令中rs1,rs2对应的通用寄存器是x2和x4后,就会从寄存器x2和x4中读取值并进行运算。

 

注意:

RISC-V汇编指令的格式是非常明晰的。在实际编码过程中,编码位置的安排都是有意义的。例如3个寄存器索引号在不同指令格式中的编码位置是永远不变的,Rd在bit 7-11,rs1在bit 15-19,rs2在bit 20-24。即使有些指令中可能没有用到部分寄存器,比如第二个指令类型I-type中没有rs2,但是rs1和rd的索引号也在对应的位置上。又例如在S-type里funct3在bit 12-14,与在R-type中的位置一致。Opcode是所有指令格式都有的,而且位置不变,永远都是bit 0-6。

 

2.2. I-Type

从R-type汇编指令的机器码格式基础上看,唯一差别是,I-type的bit 20-31(高12位)是一个立即数。其它部分与R-type很相似。当然,I-type的opcode一定与其它种类汇编指令的opcode值不同,因为对应的具体运算不同。

RISC-V指令类型机器码格式

 

2.3. S-Type

S-type指令的特点是没有rd寄存器,在该类指令中立即数(imm)被分成了两个部分,imm[11:5]在bit 25-31,imm[4:0]在bit 7-11。imm[4:0]这5位占用了rd的位置,说明该指令格式不需要回写。imm[11:5]占用了funct7的位置。

RISC-V指令类型机器码格式

 

2.4. U-Type

U-type指令中提供了一个20位的立即数(imm[31:12],将20位立即数左移12位)。最后的运算结果与20位立即数相关,并把结果回写到rd寄存器。Opcode决定其运算种类。 U-type中没有funct3,rs1,rs2和funct7,这种类型的指令结构非常简单。

RISC-V指令类型机器码格式

 

2.5. B-Type

B-type指令主要作为跳转指令使用,并且是带条件跳转(conditional jump),也就是通过判断条件是否成立来决定是否跳转,可以类比为verilog语言里的if语句。在图2中可以看到B-type的机器码结构,指令中不包含rd寄存器和funct7,但是包含rs1,rs2,funct3和立即数。立即数被分为两个区域,imm[12|10:5]和imm[4:1|11]。B-type指令立即数的编码是打乱顺序的,原因这里将不详细介绍,主要是为了增大与其他格式的共用部分。但是编码被打乱了,那么在CPU执行时要进行调整相应的译码顺序,且译码后CPU需要把打乱的立即数按照顺序还原。

RISC-V指令类型机器码格式

 

2.6. J-Type

该指令格式非常类似于U-type,也是只有Rd寄存器和立即数以及opcode。同时J-type的立即数也是打乱的。那就意味着在译码时CPU要先把立即数按顺序拼起来以还原本来的立即数。

RISC-V指令类型机器码格式

 

注意:

B-type指令的立即数字段是在S-type的基础上旋转了一位,同样的,J-type的立即数字段是在U-type基础上旋转了12位。因此RISC-V实际上只有四种基本格式,但可以保守的认为有六种格式 [2]。因为B-type和J-type的立即数都没有bit 0位,所以它们的立即数都是2的整数倍。

机器码全为0或者全为1的情况被认为是非法的RV32I指令,但是它们会被经常用来帮助调试或捕捉常见的错误 [2]。

 

3. 文章参考

[1] Riscv.org, 2021. [Online]. Available: https://riscv.org/wp-content/uploads/2019/12/riscv-spec-20191213.pdf. [Accessed: 22- Feb- 2021].

[2] D. Patterson and A. Waterman, The RISC-V reader. Berkeley: Strawberry Canyon LLC, 2018.

 

Posted in RISC-V, RISC-V 教案, 指令集, 教材与教案, 文章

发表评论

相关链接