RV32I指令集

2023-11-03

      RV32I是最基本的32位Base指令集,它支持32位寻址空间,支持字节地址访问,仅支持小端格式(little-endian,高地址高位,低地址地位),寄存器也是32位整数寄存器。RV32I指令集的目的是尽量简化硬件的实施设计,所以它只有47条指令。

      在RV32I指令集架构中,包括32个通用目的寄存器,其中x0被预留为常数0,其它31个寄存器(x1-x31)是普通的通用整数寄存器。在Risc-V汇编语言中,每个通用寄存器都有一个对应的ABI名字,也就是说在汇编语言中,x1等价于ra,它们都会编译成相同的机器码。

      在Risc-V架构中,要得到当前指令pc(指令在存储器中的位置,instruction program counter),可以通过AUIPC指令,把它读入到一个通用寄存器中。

寄存器 ABI名字(别名) 注释 Saver
x0  zero Hard-wired zero,常数0  
x1 ra Return address caller,调用函数的指令pc
x2 sp Stack pointer callee,被调用的函数指令pc
x3 gp Global pointer  
x4 tp Thread pointer  
x5 t0 Temporary/alternate link register caller
x6 t1 Temporaries caller
x7 t2 Temporaries caller
x8 s0/fp Saved register/frame pointer caller
x9 s1 Saved register caller
x10 a0 Function arguments/return values caller
x11 a1 Function arguments/return values caller
x12 a2 Function arguments caller
x13 a3 Function arguments caller
x14 a4 Function arguments caller
x15 a5 Function arguments caller
x16 a6 Function arguments caller
x17 a7 Function arguments caller
x18 s2 Saved registers caller
x19 s3 Saved registers caller
x20 s4 Saved registers caller
x21 s5 Saved registers caller
x22 s6 Saved registers caller
x23 s7 Saved registers caller
x24 s8 Saved registers caller
x25 s9 Saved registers caller
x26 s10 Saved registers caller
x27 s11 Saved registers caller
x28 t3 Temporaries caller
x29 t4 Temporaries caller
x30 t5 Temporaries caller
x31 t6 Temporaries caller

Base指令格式:

      RV32I指令格式包括以下6种,每种指令格式都是固定的32位指令,所以指令在内存中必须4字节对齐,否则将触发异常。其中rd表示目的寄存器,rs1是源操作数寄存器1,rs2是源操作数寄存器2。

image

imm表示指令中的立即数,比如imm[11:0],表示一个12位的立即数,它的高20位会符号位扩展,imm[31:12]表示一个32位的立即数,它的低12位会补0。

下图是各种指令格式扩展后的32位立即数。

image

RV32I整数指令集

RV32I整数指令集分为几个种类:

1.Load和store指令

Category Fmt RV32I base machine code(bin) comment
Loads load byte I lb rd, rs1, imm [31-20,imm][19-15,rs1]000[11-7,rd]0000011 rd=mem[rs1+imm], 8bit数据符号位扩展后返回rd
load half word I lh rd, rs1, imm [31-20,imm][19-15,rs1]001[11-7,rd]0000011 rd=mem[rs1+imm],16bit数据符号扩展后返回rd,应该保证地址对齐,否则产生异常
load word I lw rd, rs1, imm [31-20,imm][19-15,rs1]010[11-7,rd]0000011 rd=mem[rs1+imm],32bit数据返回rd,应该保证地址对齐,否则产生异常
load byte unsinged I lbu rd, rs1, imm [31-20,imm][19-15,rs1]100[11-7,rd]0000011 rd=mem[rs1+imm], 8bit数据高位补0后返回rd
load half unsinged I lhu rd, rs1, imm [31-20,imm][19-15,rs1]101[11-7,rd]0000011 rd=mem[rs1+imm], 16bit数据高位补0后返回rd

stores store byte S sb rs1, rs2, imm [31-25,imm[11-5]][24-20,rs2,][19-15,rs1]000[11-7,imm[4-0]]0100011 mem[rs1+imm]=rs2的低8bit数据
store half word S sh rs1, rs2, imm [31-25,imm[11-5]][24-20,rs2,][19-15,rs1]001[11-7,imm[4-0]]0100011 mem[rs1+imm]=rs2的低16bit数据
store word S sw rs1, rs2, imm [31-25,imm[11-5]][24-20,rs2,][19-15,rs1]010[11-7,imm[4-0]]0100011 mem[rs1+imm]=rs2的32bit数据

      RV32I是一个load /store架构,所有的memory访问都是通过load/store指令,其它指令都是在寄存器之间进行运算,比如加法指令,减法指令等等。注意,装入目的寄存器如果为x0,将会产生一个异常。Load/Store指令在memory和寄存器之间传输数据,Load指令编码为I型,store指令编码为S型。计算memory地址时候,imm都会符号扩展成32位,然后和rs1相加,得到memory地址。为了提高性能,load/store指令应该尽量对齐地址,比如lw指令,应该4字节对齐访问地址,lh应该双字节对齐访问地址。根据微架构实现的不同,不对齐地址的访问可能会比较慢,而且地址对齐访问,能够确保是原子操作,不对齐的话为了读取和存储数据正确,还有进行额外的同步操作。

image

2.整数计算指令(算术,逻辑指令,比较指令以及移位指令)

Category Fmt RV32I base machine code(bin) comment

arithmetric add R add rd, rs1, rs2 0000000[24-20,rs2][19-15,rs1]000[11-7,rd]0110011 rd=rs1+rs2,如果溢出,舍弃高位,保留低32bit
add immediate I addi rd, rs1, imm [31-20,imm][19-15,rs1]000[11-7,rd]0010011 rd=rs1+imm,12bit立即数会符号位扩展,结果写回rd时如果溢出,则舍弃高位,保留低32bit
subtract R sub rd, rs1, rs2 0100000[24-20,rs2][19-15,rs1]000[11-7,rd]0110011 rd=rs1-rs2,如果溢出,舍弃高位,保留低32bit
load upper imm U lui rd, imm [31-12,imm][11-7,rd]0110111 load imm to  high 20 bits of rd, and place 0 in low 12 bits
add upper imm to PC U auipc rd, imm [31-12,imm][11-7,rd]0010111 pc=pc+high 20 bits imm&low 12 bits 0, then result save to rd.
logical xor R xor rd, rs1, rs2 0000000[24-20,rs2][19-15,rs1]100[11-7,rd]0110011 rd=rs1^rs2, bitwise operation
xor immediate I xori rd, rs1, imm [31-20,imm][19-15,rs1]100[11-7,rd]0010011 rd=rs1^imm, i符号扩展12bit数imm,结果放在rd。
or R or rd, rs1, rs2 0000000[24-20,rs2][19-15,rs1]110[11-7,rd]0110011 rd=rs1|rs2, bitwise operation
or immediate I ori rd, rs1, imm [31-20,imm][19-15,rs1]110[11-7,rd]0010011 rd=rs1|imm,  符号扩展12bit数imm,结果放在rd。
and R and rd, rs1, rs2 0000000[24-20,rs2][19-15,rs1]111[11-7,rd]0110011 rd=rs1&rs2, bitwise operation
and immediate I andi rd, rs1, imm [31-20,imm][19-15,rs1]111[11-7,rd]0010011 rd=rs1&imm, i符号扩展12bit数imm,结果放在rd。

shifts shift left R SLL rd, rs1, rs2 0000000[24-20,rs2][19-15,rs1]001[11-7,rd]0110011 rd=rs1<<rs2,rs1左移值为rs2的低5bit,低位补0
shift left immediate I SLLI rd, rs1, shamt 0000000[24-20,imm][19-15,rs1]001[11-7,rd]0010011 rd=rs1<<shamt,rs1移动5bit立即数,低位补0
shift right R SRL rd, rs1, rs2 0000000[24-20,rs2][19-15,rs1]101[11-7,rd]0110011 rd=rs1>>rs2,高位补0,右移值为rs2中的低5位
shift right immediate I SRLI rd, rs1, shamt 0000000[24-20,imm][19-15,rs1]101[11-7,rd]0010011 rd=r1>>shamt,高位补0,右移值为5bit立即数
shift right arithmetirc R SRA rd, rs1, rs2 0100000[24-20,rs2][19-15,rs1]101[11-7,rd]0110011 rd=rs1>>rs2,高位补符号位,右移值为rs2中的低5位
shift right arith imm I SRAI rd, rs1, shamt 0100000[24-20,imm][19-15,rs1]101[11-7,rd]0010011 右移时,右边补符号位

compare set <  R slt rd, rs1, rs2 0000000[24-20,rs2][19-15,rs1]010[11-7,rd]0110011 if rs1< rs2, write 1 to rd, 有符号数比较
set < immediate  I slti rd, rs1, imm [31-20,imm][19-15,rs1]010[11-7,rd]0010011 if rs1<imm, write 1 to rd,imm会符号位扩展,所以进行有符号数比较
set < unsigned R sltu rd, rs1, rs2 0000000[24-20,rs2][19-15,rs1]011[11-7,rd]0110011 if rs1< rs2, write 1 to rd, 无符号数比较
set < imm unsigned I sltiu rd, rs1, imm [31-20,imm][19-15,rs1]011[11-7,rd]0010011 if rs1<imm, write 1 to rd,imm会符号位扩展,所以进行有符号数比较

      计算指令在寄存器和寄存器之间,或者在寄存器和立即数之间进行算术或逻辑运算。指令格式为I,R或者U型。整数计算指令不会产生异常。我们能够通过ADDI x0, x0, 0来模拟NOP指令,该指令除了改变pc值外,不会改变其它任何用户状态。


image

image

3. 控制指令,包括无条件跳转指令和条件跳转指令

Category Fmt RV32I base machine code(bin) comment
branch branch = SB beq  rs1, rs2,imm [31-25, imm[12][10:5]][24-20, rs2][19-15, rs1]000[11-7, imm[4:1][11]]1100011 if(rs1==rs2) pc=pc+imm*2,跳转指令
branch <> SB bne  rs1, rs2,imm [31-25, imm[12][10:5]][24-20, rs2][19-15, rs1]001[11-7, imm[4:1][11]]1100011 if(rs1!=rs2) pc=pc+imm*2,跳转指令
branch < SB blt  rs1, rs2,imm [31-25, imm[12][10:5]][24-20, rs2][19-15, rs1]100[11-7, imm[4:1][11]]1100011 if(rs1<rs2) pc=pc+imm*2,跳转指令 ,   有符号数
branch >= SB bge  rs1, rs2,imm [31-25, imm[12][10:5]][24-20, rs2][19-15, rs1]101[11-7, imm[4:1][11]]1100011 if(rs1>rs2) pc=pc+imm*2,跳转指令,有符号数
branch < unsigned SB bltu  rs1, rs2,imm [31-25, imm[12][10:5]][24-20, rs2][19-15, rs1]110[11-7, imm[4:1][11]]1100011 if(rs1<rs2) pc=pc+imm*2,跳转指令,无符号数
branch >=unsigned SB bgeu  rs1, rs2,imm [31-25, imm[12][10:5]][24-20, rs2][19-15, rs1]111[11-7, imm[4:1][11]]1100011 if(rs1>rs2) pc=pc+imm*2,跳转指令,无符号数
jump and link J&L UJ JAL rd, imm [31-12, imm[20][10:1][11][19:12]][11-7,rd]1101111 pc=pc+imm*2, 现在的pc+4写入rd寄存器
Jump and link register UJ JALR, rd, rs1, imm [31-20,imm[11:0]][19-15,rs1]000[11-7,rd]1100111 pc=rs1+imm, pc+4写入到rd寄存器

JAL指令使用20位的立即数作为偏移,所以它仅可以跳转到前后1M的地址空间。JALR使用12位的立即数,其值和rs1中的值相加,得到偏移量。

image

4. 同步指令

Category Fmt RV32I base machine code(bin) comment
Synch synch thread I FENCE iorw,iorw 0000[27-24,pred][23-20,succ]00000000000000001111 pred/succ分别表示fence之前和之后的 iorw
synch instr and data I FENCE.i 00000000000000000001000000001111 用于同步指令和数据流

Risc-V在多个hart(硬件线程)之间使用的是松散一致性模型,所以需要存储器fence指令。

fence指令能够保证存储器访问的执行顺序。在fence指令之前的所有存储器访问指令,比该fence之后的所有数据存储器访问指令先执行。

Risc-V架构将数据存储器的地址空间分为设备IO(device IO)和普通存储器空间,因此其读写访问分为四种类型:

I:设备读(device-input)

O:设备写(device-ouput)

R:存储器读(memory-reads)

W:存储器写(memory-writes)

PI/PO/PR/PW,分别f表示ence指令之前的四种读写访问类型,SI/SO/SR/SW分别表示fence指令之后的四种读写访问类型。

image

fence.i指令用于同步指令和数据流。如果程序中添加一个fence.i,则该指令能够保证fence.i之前所有指令的访存结果能被fence.i之后的所有指令访问到。通常说来,处理器的微架构硬件实现时,一旦遇到一条fence.i指令,便会先等到之前的所有访存指令执行完,然后冲刷流水线,包括Icache,使其后的所有指令,能够重新取指,从而得到最新的值。

注意:fence.i只能保证同一个hart(硬件线程)执行的指令流和数据流顺序,不能保证多个hart之间的指令流和数据流访问。

image


5.控制状态寄存器指令

Category Fmt RV32I base machine code(bin) comment
CSR CSRRW I CSRRW [31-20,csr][19-15, rs1]001[11-7,rd]1110011 csrrw rd, csr, rs1, 将csr索引的寄存器值读出,写到rd,将rs1中的值写入csr
CSRRS I CSRRS [31-20,csr][19-15, rs1]010[11-7,rd]1110011 csrrs rd, csr, rs1, 将csr索引寄存器值读出写到rd,以rs1为参考,如果rs1中某位为1,则置位对应的csr寄存器位,其他位不受影响。
CSRRC I CSRRC [31-20,csr][19-15, rs1]011[11-7,rd]1110011 csrrc rd, csr, rs1, 将csr索引寄存器值读出写到rd,以rs1为参考,如果rs1中某位为1,则清零对应的csr寄存器位,其他位不受影响。
CSRRWI I CSRRWI [31-20,csr][19-15, zimm]101[11-7,rd]1110011 csrrwi rd, csr, imm[4:0], 将csr索引寄存器值读出写到rd,5位立即数的值写入csr,高位补0
CSRRSI I CSRRSI [31-20,csr][19-15, zimm]110[11-7,rd]1110011 csrrsi rd, csr, imm[4:0], 将csr索引寄存器值读出写到rd,5位立即数的值(高位补0)逐位比较,如果为1,则置位csr相应位
CSRRCI I CSRRCI [31-20,csr][19-15, zimm]111[11-7,rd]1110011 csrrci rd, csr, imm[4:0], 将csr索引寄存器值读出写到rd,5位立即数的值(高位补0)逐位比较,如果为1,则清零csr相应位

CSR指令包括上面表中的6条指令,通常在用户层,不会访问写csr的指令。

这些CSR指令实现都是原子操作。对于CSRRW和CSRRWI来说,如果rd为x0,则不会有任何写操作。对于CSRS和CSRRC指令,如果rs1为x0,则不会有任何写操作。对于CSRRSI和CSRRCI来说,如果立即数为0,则不会有任何写操作。

用CSR指令可以实现一些伪指令,例如读取始终频率等。详细见伪指令列表。


image

6.环境调用和断点指令

Category Fmt RV32I base machine code(bin) comment
System system call I ECALL 00000000000000000000000001110011 用于生成环境调用异常,产生异常时候,mepc寄存器将保存当前指令pc值。
system break I EBREAK 00000000000100000000000001110011 生成断点,产生异常时候,mepc寄存器将保存当前指令pc值。

这两条指令能够产生环境调用异常和生成断点异常,产生异常时候,当前指令的pc值被写入mepc寄存器。

这两条指令在调试代码时候有用。

image










本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RV32I指令集 的相关文章

随机推荐

  • 如何修改maven本地仓库地址

    1 如果从未配置过本地仓库 那么默认的仓库文件夹应该是在user gt admin 或者管理员名字命名的文件夹 gt m2 gt repository 仓库文件夹 将文件挪动到maven文件夹下 当然 这么做的是因为仓库中有之前保留的很多j
  • obsidian插件无法加载的解决办法

    1 问题 插件安装 但启动不了 2 解决方案 1 去obsidian插件官网搜索 2 下载以下3个文件 到 obsidian plugin目录下 路径 F 2023年 obsidian plugins cMenu 1 1 1 3 进入obs
  • docker 安装gitlab血泪史(解决方式telnet查看未开通端口号)

    1 docker pull gitlab gitlab ce 2 执行 docker run d p 443 443 p 80 80 p 222 22 name gitlab restart always v home gitlab con
  • 图像语义分割python_图像语义分割ICNET_飞桨-源于产业实践的开源深度学习平台...

    图像语义分割 ICNET 类别 智能视觉 PaddleCV 应用 自动驾驶 室内导航 医学图像诊断 穿戴设备 虚拟现实与增强现实 无人机 模型概述 ICNet 主要用于图像实时语义分割 能够兼顾速度和准确性 ICNet的主要思想是将输入图像
  • mysql hash分区要点

    mysql 有很多种表分区的方式 这里写一些笔者对于hash分区的感悟 如有错误 恳请读者斧正 mysql hash分区不用像其他的分区指定 当某一列值得情况为某某某的情况去到某一分区 比如list分区和range分区 hash直接只用指定
  • My eclipse 无法打开workspace解决方案

    今天用myeclipse的时候试图引用code comment style 在引用的过程中死掉了 就杀死进程 myeclipse提示crash 再打开次workspace 就一直处于 loading workbench 状态 打开其他wor
  • 进程和线程的区别

    进程 Process 和线程 Thread 是操作系统中的两个重要概念 它们是实现多任务并发执行的两种方式 它们有以下主要区别 1 定义和资源 进程 进程是正在运行的程序的实例 拥有独立的地址空间和资源 每个进程都有自己的代码 数据 堆栈
  • Windows11 拒绝访问压缩(zipped)文件夹

    最近windows10被自动升级到windows11 使用的一个工具zip压缩包突然就无法解压了 提示 拒绝访问压缩 zipped 文件夹 提取文件之前 必须更改这个压缩文件夹的权限 我的尝试 更改了这个压缩包文件的属性中的各个用户权限 增
  • 数字图像处理 基于python读取DICOM、NIfTI格式医学图像文件

    一 医学图像 医学图像标注最重要的进步之一是应用机器学习来评估图像 以实现更精确 更快 更准确的医学诊断 在应用机器学习 ML 人工智能 AI 或任何其他诊断算法之前 您需要知道注释软件可以处理两种最常见的医疗和保健图像文件格式 包括 DI
  • SpringBoot如何避免SQL注入漏洞呢?

    转自 SpringBoot如何避免SQL注入漏洞呢 下文笔者讲述SpringBoot避免SQL注入漏洞的方法分享 如下所示 SQL盲注 SQL注入简介 SQL注入的风险 数据库中的数据被任意查看 修改 删除 SQL注入的原因 未对用户输入进
  • mysql的驱动connect放在哪里_MySQL文档阅读笔记之JDBC驱动参数autoReconnect的副作用...

    MySQL的特性之一可高度定制化 相应的MySQL提供的JDBC驱动也提供了相当多的参数 老实说 第一次阅读文档时 真心晕 不过还是禁不住的赞叹 MySQL的JDBC驱动都有茫茫多的参数 果然有特点 这些参数中autoReconnect吸引
  • 无注册中心使用dubbo

    前言 熟悉dubbo的朋友都知道 dubbo可通过指定Url方式绕过注册中心直连指定的服务地址 所以想当然会想到那么可不可以不使用注册中心 本文就是SpringBoot整合Dubbo 无注册中心 的示例展示 提供者dubbo provide
  • Cobar使用文档(可用作MySQL大型集群解决方案)

    Cobar使用文档 可用作MySQL大型集群解决方案 2013 12 11 16 06 17236人阅读 评论 0 收藏 举报 分类 cobar 1 转 http blog csdn net shagoo article details 8
  • Python操作Excel插入删除行

    Python操作Excel插入删除行 1 前言 2 使用openpyxl 3 使用xlwings 3 1 删除行 range api EntireRow Delete 3 2 插入行 sheet api Rows row number In
  • 信息系统之网络安全方案 — “3保1评”

    信息系统之网络安全方案 3保1评 序 什么是 3评1保 一 网络安全等级保护 1 1 概念 1 2等保发展 1 3法律要求 1 4分级及工作流程 二 涉密信息系统分级保护 2 1概念 2 2法律要求 2 3分级及工作流程 三 关键信息基础设
  • unity3d-常用组件

    Component 学习阶段我会不断的更新新的内容 文章如有误请指正 如果觉得对你有用 请点赞收藏关注一波 谢谢支持 Rigidbody 变量 公共函数 消息 公共函数 2D 静态函数 2D 射线 RaycastHit 2D 1 变量 Ph
  • 51单片机控制数码管显示以及控制打断

    实践内容 1 利用单片机的P0口接数码管的字段脚 P1 0脚接共阴极 P3 2 P3 3引脚接独立按键产生外部中断信号 编写程序 当程序正常运行时数码管显示H字符 当外部中断0有中断请求信号时 数码管从0 9循环显示一次后回到正常状态 如果
  • ARP攻击后续

    查看ARP缓存表 我们先了解一下ARP缓存表的概念 络设备一般都有一个ARP缓存 ARP Cache ARP缓存用来存放IP地址和MAC地址的关联信息 在发送数据前 设备会先查找ARP缓存表 如果缓存表中存在对方设备的MAC地址 则直接采用
  • VS2013编译FFMPEG遇到的坑

    因为需要 用到老的FFMPEG库 但官方又没有编译好的LIB和DLL 只能下载源码自己编译了 但对LINUX环境不懂 只有在WINDOWS上配置环境编译 记录过程如下 1 下载FFMPEG源码 下载地址 http ffmpeg zerano
  • RV32I指令集

    RV32I是最基本的32位Base指令集 它支持32位寻址空间 支持字节地址访问 仅支持小端格式 little endian 高地址高位 低地址地位 寄存器也是32位整数寄存器 RV32I指令集的目的是尽量简化硬件的实施设计 所以它只有47