RISC-V指令集架构特点及其总结

本文章对E203开源核的Decode模块进行总结。

一、 指令总结

六种基本指令格式,分别是:

  • 用于寄存器-寄存器操作的 R 类型指令
  • 用于短立即数和访存 load 操作的 I 型指令
  • 用于访存 store 操作的 S 型指令
  • 用于条件跳转操作的 B 类型指令
  • 用于长立即数的 U 型指令
  • 用于无条件跳转的 J 型指令

RISC-V的指令有几个特点:

  • 指令只有六种格式,并且所有的指令都是 32 位长,这简化了指令解码
  • RISC-V 指令提供三个寄存器操作数
  • 在 RISC-V 中对于所有指令,要读写的寄存器的标识符总是在同一位置,意味着在解码指令之前,就可以先开始访问寄存器。
  • 这些格式的立即数字段总是符号扩展,符号位总是在指令中最高位。这意味着可能成为关键路径的立即数符号扩展,可以在指令解码之前进行

32位risc-v整数指令集:
32位risc-v整数指令集
32位risc-v整数指令集
32位risc-v整数指令集
32位risc-v整数指令集

寄存器如下:
寄存器

所有位全部是 0 是非法的 RV32I 指令,所有位全部是 1 的指令也是非法指令

立即数总是进行符号扩展,并不需要一个立即数版本的 sub

sll(shift left logical)为右侧补0,srl为左侧补0,sra(shift right arithmetic)左侧补符号位。

slt(set less than):如果第一个操作数小于第二个操作数,它将目标寄存器设置为 1,否则为0。对这个指令,有一个有符号版本(slt)和无符号版本(sltu)。

加载立即数到高位(lui)将 20 位常量加载到寄存器的高 20 位。接着便可以使用标准的立即指令来创建 32位常量。例如lui+addi可以构造32位立即数和rs的计算。

当前的 PC 可以通过将 auipc 的 U 立即数字段设置为 0 来获得

向 PC 高位加上立即数(auipc)让我们仅用两条指令,便可以基于当前 PC 以任意偏移量转移控制流或者访问数据。将 auipc 中的 20 位立即数与 jalr(参见下面)中 12 位立即数的组合,我们可以将执行流转移到任何 32 位 PC 相对地址。而 auipc 加上普通加载或存储指令中的 12位立即数偏移量,使我们可以访问任何 32 位 PC 相对地址的数据。李例如(auipc+jalr; auipc+lw)

RISC-V 中没有字节或半字宽度的整数计算操作

除了提供 32 位字(lw,sw)的加载和存储外,RV32I 支持加载有符号和无符号字节和半字(lb,lbu,lh,lhu)以及存储字节和半字(sb,sh)。有符号字节和半字符号扩展为 32 位再写入目的寄存器。无符号字节和半字,在写入目标寄存器之前都被无符号扩展到 32 位(只要取得是非32位,都被扩展成32位放入rd,为了对齐)

与 x86-32 不同,RISC-V 没有特殊的堆栈指令。将 31 个寄存器中的某一个作为堆栈指针

RISC-V 选择了小尾端字节序

RV32I 可以比较两个寄存器并根据比较结果上进行分支跳转。比较可以是:相等(beq),不相等 (bne),大于等于(bge),或小于(blt)。

对于jal,有两种方式。rd = ra 或者 x0,当=ra则为有返回地址实现过程调用,=x0则为直接跳转。jal 将其 20 位分支地址乘以 2,进行符号扩展后再添加到 PC 上,便得到了跳转地址。

对于控制状态寄存器指令 (csrrc、csrrs、csrrw、csrrci、csrrsi、csrrwi),使我们可以轻松地访问一些程序性能计数器。对于这些 64 位计数器, 我们一次可以读取 32位。这些计数器包括了系统时间, 时钟周期以及执行的指令数目。

ecall 指令用于向运行时环境发出请求,例如系统调用。调试器使用 ebreak 指令将控制转移到调试环境。

fence 指令对外部可见的访存请求,如设备 I / O 和内存访问等进行串行化。外部可见指对处理器的其他核心、线程,外部设备或协处理器可见。fence.i 指令同步指令和数据流。在执行 fence.i 指令之前,对于同一个硬件线程,RISC-V 不保证用存储指令写到内存指令区的数据可以被取指令取到。

fence指令的定义:RISC-V 架构采用松散存储器模型(Relaxed Memo Model ),松散存储器模型对于访问不同地址的存储器读写指令的执行顺序不作要求,除非使用明确的存储器屏障指令。fence指令就是存储器屏障指令。

RISC-V 架构定义了 Fence Fence.I 两条存储器屏障指令,用于强行界定存储器访问的顺序,其定义如下:

  • 在程序中,如果添加了 Fence 指令,则 Fence 指令能够保证“在 Fence 之前所有指令造成的访存结果”必须比“在 Fence 之后所有指令造成的访存结果”先被观测到。
  • 在程序中,如果添加了 Fence .I指令,则“在 Fence.I 之后所有指令的取指令操作” 一定能够观测到“在 Fence.I 之前所有指令造成的访存结果”

版权声明:本文为CSDN博主「草芥小白」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_29768741/article/details/105301193

最新文章