1.3.2 RISC-V指令概述

RV32I指令集包括四种核心指令格式(R/I/S/U)和两种变体格式(B/J),如图1-7所示。其中opcode表示指令操作码,funct7、funct3表示功能码,rs1、rs2表示指令中的源寄存器,rd表示目标寄存器,imm表示立即数。这六种指令格式的划分依据是:

· 图1-7 RISC-V基础指令格式

· R类型指令:两源操作数都来自寄存器的指令。

· I类型指令:其中一个源操作数为立即数的指令,以及访存Load类指令。

· S类型指令:访存Store类指令。

· B类型指令:条件跳转指令。

· U类型指令:长立即数操作指令。

· J类型指令:无条件跳转指令。

算术运算类指令如图1-8所示。其中add指令完成两个操作数寄存器rs1和rs2的整数加法操作,结果写回rd寄存器。如果结果发生了溢出,不进行处理,直接保留低32-bit数据;sub指令完成两个操作数寄存器rs1和rs2的整数减法操作,结果写回rd寄存器。同样,如果结果发生了溢出,不进行处理,直接保留低32-bit数据;slt完成两个操作数寄存器rs1和rs2的有符号数比较操作,如果src1的值小于src2,结果为1,否则为0,结果写回rd寄存器;以i结尾的指令为立即数模式,其运算与不带i的指令完全相同,只是第二个源操作数为立即数,而非寄存器。

· 图1-8 算术运算类指令

逻辑运算类指令如图1-9所示。其中and指令完成两操作数的按位与操作;or指令完成两操作数的按位或操作;xor指令完成两操作数的按位异或操作;以i结尾的指令为立即数模式。

· 图1-9 逻辑运算类指令

移位类指令如图1-10所示。其中sll为逻辑左移指令,rs1和rs2为两操作数寄存器,将rs1进行逻辑左移操作,低位补0,移位量为rs2的低5-bit,结果写回rd寄存器;srl为逻辑右移指令,rs1和rs2为两操作数寄存器,将rs1进行逻辑右移操作,高位补0,移位量为rs2的低5-bit,结果写回rd寄存器;sra为算术右移指令,rs1和rs2为两操作数寄存器,将rs1进行算术右移操作,高位补符号位,移位量为rs2的低5-bit,结果写回rd寄存器;lui指令将指令编码中的20位立即数写入rd的高20-bit,rd的低12-bit置零;auipc指令构建一个32-bit的移位量,其中高20-bit来自指令编码,低12-bit置零,将该移位量与auipc的PC相加,结果写入rd中。

· 图1-10 移位类指令

访存类指令如图1-11所示。RISC-V存储器访问指令简洁,它作为一种RISC指令集架构,和所有的RISC指令集架构一样具有专门的Load/Store指令,而除了Load/Store指令以外其他指令无法访问存储器。这些都极大地简化了CPU的硬件设计,降低了成本。对于32位架构的RISC-V架构CPU,其Load/Store指令支持一个8位(字节)、16位(半字)、32位(字)的存储器读写操作。而64位架构的RISC-V架构CPU,还可以进行64位(双字)的存储器读写操作。

· 图1-11 访存类指令

分支跳转类指令格式如图1-12所示。jal、jalr为无条件跳转链接指令,将PC+4保存到目标寄存器。目标寄存器选择非x0寄存器能实现过程调用与返回。MIPS、ARM等架构需要两条指令实现条件分支跳转,第一条指令实现比较,将比较结果保存到通用寄存器,第二条指令根据前一条指令的结果判断跳转条件。RISC-V将比较和跳转放在一条指令中完成,这样可以缩减指令数量,简化硬件设计。

· 图1-12 分支跳转类指令

RISC-V架构要求CPU最低要支持静态分支预测,规定无条件跳转指令预测为跳转,带条件跳转指令如果是向地址减小的方向跳转则预测为跳转,否则预测为不跳转。所有基于RISC-V架构的编译器都支持这种静态分支预测机制,保证了低端CPU也有不错的性能。高端CPU可以采用更加精确高效的动态分支预测机制。