主页
FPGA培训
关于平台
企业孵化
峰会大赛
展厅预约
FPGA知识库
联系我们
登录 注册
首页 > 技术文章 > RISC-V RV32I 基本6种指令集
RISC-V RV32I 基本6种指令集
来源: 2021-09-28 11:18

RISC-V 的RV32I是最基本的指令集,包括6种,其中4种核心的类型(R/I/S/U)。

本文是参考文档:The RISC-V Instruction Set Manual Volume I: Unprivileged ISA Document Version 20191213

c21.png


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

1.非常的规整,可以看到rs1和rs2都作为数据源寄存器,同时rd一直作为目标寄存器。然后这三个寄存器在6种类型指令中的位置是固定的!这使得硬件解码非常简单。

2.立即数的最高位一直在最左边,这方便了做符号位的拓展。

3.相比与arm,将指令放不下的立即数放进常量池然后用load去读。risc v用的是两条指令,先用U type读高20位的数据,然后再用加法加上低12位。这使得不用去访问外部存储也能处理高位宽的常数。

4.立即数默认都是有符号数的,都需要符号拓展。

5.B类型和S类型的差别,是B的立即数是S的立即数*2,但是为了保证第2个特点,同时保持最多的位的位置保持不变,比如指令的6到11位,仅仅改变了第6位从S的imm[0]变为imm[11]。这也是方便了硬件解码,但是苦逼了编译器。

6.U类型和J类型同第五点。

7.讲多一个,常用寄存器有一个x0,他的值一直为0,这个当你指令不需要一个寄存器就用它,或者用x0实现一些特殊的指令,比如ADDI x0, x0, 0,就是啥也不干。

接下来讲几种整数运算指令

整体就是寄存器-立即数用I类型指令,寄存器-寄存器用R类型指令。


寄存器-立即数运算

c22.png

比如

ADDI rd, rs1, imm:就是REG[rd] = REG[rs1] + $signed(imm);

SLTI (set less than immediate) rd, rs1, imm:就是当REG[rs1]比$signed(imm)小的时候,REG[rd]为1,否则为0,有符号比较。

SLTIU跟SLTI差不多,不过是无符号数比较。

ANDI, ORI, XORI是逻辑操作,(有符号数)。ANDI rd, rs1, imm:REG[rd] = REG[rs1] & imm

成3.png

移位操作也是编译成I type的。移位的位数是imm[4:0],所以一次指令最多可以移动32位,跟寄存器的位宽一样。

SLLI:是逻辑左移,低位补零

SRLI:是逻辑右移, 高位补零

SRAI:是算术右移,高位补原来高位。

(这里我有个问题,原文是说The right shift type is encoded in bit 30,所以按说应该右移类型的第30位应该是1,左移是0吼,但又好像不太是。anyway)

成4.png

LUI (load upper immediate): LUI rd imm。就是REG[rd] [31:12] = imm。REG[rd] [11:0] = 0。就是把imm赋给rd的高20位,然后低12位补零。一般后面加一个addi的指令,把低12位的值给上。这样子,通过两条指令,就把一个32位的imm赋给了寄存器啦。

AUIPC (add upper immediate to pc):就是在LUI的基础上,再加上这个命令的pc地址。同样后面再加一个12位的加法,就可以寻址到任何位置的指令的地址啦。


整数的寄存器-寄存器运算指令

这种就比较简单了,都是把rs1,rs2寄存器里面的值运算一下,然后将结果给rd就完事了。

成5.png

ADD就是加,SUB就是减,都不考虑溢出的哦。

SLT和SLTU分别是有符号比较和无符号数比较,rs1<rs2的话,rd为1,否则为0。

SLL, SRL, and SRA就是逻辑左,逻辑右,算术右的运算,是rs1进行移位,移动的位数是rs2的低5位。


控制指令

控制指令就是if else这种分支跳转的指令了,这个玩意复杂可以很复杂,我这里就是简单介绍一下指令。


非条件跳转

成6.png

JAL:就是pc指针跳转到当前位置加上{$signed(imm[20:1]),0},这是J型,你软件给说JAL rd 16,其实实现的是pc = pc + 32。然后将pc + 4这个值赋给rd存放好到时候要返回来的地址。imm是2个字节对齐的,20位就是2MB的寻址空间了,imm有符号数的哦。

成7.png

JALR功能跟JAL差不多,比如JALR rd rs1 imm,那就是pc = REG[rs1] +imm。然后把最低有效的位置0。


条件跳转指令

成8.png

所有的条件跳转都是B类型的指令。B类型的imm都是2字节对齐的。

BEQ and BNE分别当rs1和rs2相等和不相等时,跳转。否则就不跳。

BLT and BLTU 分别是有符号数比较和无符号数比较,当rs1<rs2时候就跳,否则不跳

BGE and BGEU 分别是有符号数比较和无符号数比较,当rs1>=rs2时候就跳,否则不跳


再强调哦,跳转分支我这里只是说明一下指令,具体有一些预测分支啊,应用啊,link啊啥的。


load and store 指令

RISC V的load 和store指令也是一个特色哦,就是load和store只能通过寄存器来操作,就是一定要把地址放在在寄存器里面,然后load这个寄存器的地址读取memory里面的数据。

成9.png

LOAD从mem读取一个32位的数据到rd。地址是REG[rs1] + imm

STORE 是把rs2里面的数据放到地址是REG[rs10] + imm

LH 从mem读取一个16位的数据,然后符号拓展到32位,再放到rd中

LHU 从mem读取一个16位的数据,然后高位补0到32位,再放到rd中

LB and LBU 同理处理8位的数据

SW, SH, and SB同理分别sore 32,16,8位的数据。


总结

RV32I是RISC V最基本的指令集类型,还有一些低功耗的呀,高性能的呀啥的,RV32I指令集的特点是特别规整,这加大了额外的编辑器的工作量,比如B指令啥的,但是却简化的硬件设计,应该还是非常值得的呀。RV32I一共有40条指令,我这里一共介绍了33条指令,后面还有一些memory order,environment call and breakpoints,HINT的,稍稍复杂,怕讲的太误人了。我这里也不一定正确,请多指教。

————————————————

声明:文章来源于CSDN,博主 数字芯片设计与验证--关易寿,本文内容及配图的版权归版权所有人所有,内容仅代表作者个人观点,不代表本网站观点或证实其内容的真实性。对于本网刊载的各类评论非本网评论员评论,仅代表评论者个人观点,并不代表本网证实或赞成其描述。如其他媒体、网站或个人转载使用,需保留本网注明的“稿件来源”,并自负法律责任。本文转载仅为更好的传播行业信息,若有内容图片侵权或者其他问题,请及时通过邮件联系我们,以便做侵删处理。

原文链接:https://blog.csdn.net/q876507447/article/details/105477887