查看: 1802|回复: 0
收起左侧

RISC-V RV32I 基本6种指令集

[复制链接]

  离线 

  • TA的每日心情
    奋斗
    2021-3-3 12:32
  • 签到天数: 10 天

    [LV.3]

    发表于 2020-8-23 20:35:06 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 皋陶 于 2020-8-26 12:56 编辑

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

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


    国内芯片技术交流-RISC-V RV32I 基本6种指令集risc-v单片机中文社区(1)


    RISC-V的指令集有以下几个特点:
    • 非常的规整,可以看到rs1和rs2都作为数据源寄存器,同时rd一直作为目标寄存器。然后这三个寄存器在6种类型指令中的位置是固定的!这使得硬件解码非常简单。
    • 立即数的最高位一直在最左边,这方便了做符号位的拓展。
    • 相比与arm,将指令放不下的立即数放进常量池然后用load去读。risc v用的是两条指令,先用U type读高20位的数据,然后再用加法加上低12位。这使得不用去访问外部存储也能处理高位宽的常数。
    • 立即数默认都是有符号数的,都需要符号拓展。
    • B类型和S类型的差别,是B的立即数是S的立即数*2,但是为了保证第2个特点,同时保持最多的位的位置保持不变,比如指令的6到11位,仅仅改变了第6位从S的imm[0]变为imm[11]。这也是方便了硬件解码,但是苦逼了编译器。
    • U类型和J类型同第五点。
    • 讲多一个,常用寄存器有一个x0,他的值一直为0,这个当你指令不需要一个寄存器就用它,或者用x0实现一些特殊的指令,比如ADDI x0, x0, 0,就是啥也不干。



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

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


    寄存器-立即数运算

    国内芯片技术交流-RISC-V RV32I 基本6种指令集risc-v单片机中文社区(2)


    比如


    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


    国内芯片技术交流-RISC-V RV32I 基本6种指令集risc-v单片机中文社区(3)


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


    SLLI:是逻辑左移,低位补零
    SRLI:是逻辑右移, 高位补零
    SRAI:是算术右移,高位补原来高位。


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


    国内芯片技术交流-RISC-V RV32I 基本6种指令集risc-v单片机中文社区(4)


    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就完事了。


    国内芯片技术交流-RISC-V RV32I 基本6种指令集risc-v单片机中文社区(5)


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


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


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


    控制指令

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


    非条件跳转

    国内芯片技术交流-RISC-V RV32I 基本6种指令集risc-v单片机中文社区(6)


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


    国内芯片技术交流-RISC-V RV32I 基本6种指令集risc-v单片机中文社区(7)


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


    条件跳转指令

    国内芯片技术交流-RISC-V RV32I 基本6种指令集risc-v单片机中文社区(8)


    所有的条件跳转都是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里面的数据。


    国内芯片技术交流-RISC-V RV32I 基本6种指令集risc-v单片机中文社区(9)


    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的,稍稍复杂,怕讲的太误人了。我这里也不一定正确,请多指教。


    本篇完,感谢关注:RISC-V单片机中文网






    上一篇:RISC-V架构的工作模式
    下一篇:从零开始实现一个基于RISC-V的流水线处理器
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-4-25 07:06 , Processed in 0.594949 second(s), 48 queries .

    快速回复 返回顶部 返回列表