大家一起从零设计RISC-V处理器(四)之RISC-V 32位(RV32I)指令集详细介绍

1.简述

指令集是协议规范, 大家遵循规范进行设计,不用考虑软件、工具、应用等一系列的问题;设计RISCV处理器就需要仔细且反复阅读RISC-V标准;
RISC-V官方标准主要分为两部分:用户指令集、特权模式;下面进行详细的介绍:

2.RV特权模式

根据不同的应用场景和需求,同一指令集根据不用特权模式在设计上采取不同的策略;为了加强对操作系统和信息安全的支持,定义三种模式,每一钟模式对应一个特权层级,机器模式层级最高,普通用户模式层级最低,层级越高软件可操作的权限就越高;类似在linux系统,一般在普通用户权限下操作,如果需要安装依赖库或者在根目录下操作等,就需要进入超级用户,也就是root,获得更高的权限(当然可直接用sudo),这是一种保护措施,以防用户误操作导致系统损坏;
在处理器设计时,机器模式是必须要实现的,其他两个模式根据需求加以实现,我们目标是简易的MCU,因此也只需要实现机器模式即可;
在这里插入图片描述

3.RV指令集分类

如图所示,指令集分为基础指令集和扩展指令集;又根据处理器位数不同,分为32位、64位以及128位,其中32位指令集(RV32I)为了进一步支持嵌入式又制定嵌入式指令集(RV32E),将32个32位的通用寄存器砍掉一半,即只有16个32位的通用寄存器,其他保持不变;
 “I” 基本整数集,其中包含整数的基本计算、Load/Store和控制流,所有的硬件实现都必须包含这一部分。
 “C”压缩指令扩展,将某些指令进行压缩,提高代码密度;
 “M” 整数乘除法扩展,增加了整数寄存器中的乘除法指令。
 “A” 原子操作扩展,增加对储存器的原子读、写、修改和处理器间的同步。
 “F” 单精度浮点扩展,增加了浮点寄存器、计算指令、L/S指令。
 “D” 双精度扩展,扩展双精度浮点寄存器,双精度计算指令、L/S指令。
 I+C+M+F+A+D 被缩写为 “G” ,共同组成通用的标量指令。
在后续ISA的版本迭代过程中,RV32G和RV64G总是保持不变。

可以看出扩展指令支持也比较丰富,但不是我们需要实现的内容就不展开了,后期项目升级需要实现时单独拿出来讨论;
在这里插入图片描述

4.RV寄存器

RV32I型具有32个32-bit的通用寄存器,具体定义和功能如下:
在这里插入图片描述

5.RV32I指令类型

如图,RV32I 6大类指令类型,从这里可以看出Bit域定义是非常规整的,相同的定义总是在同一位置,这样让代码更简洁、实现更加容易;

  • opcode:操作码,每个指令类型都有只属于自己的编码值,用于区分不同的指令类型;
  • rd:目标寄存器:需要写入的通用寄存器,该Bit域是寄存器的地址;
  • func7、func3:表示指令的功能,同一指令类型中通过这几个bit域来区分具体功能(数字“7”代表是占用7-bit位宽,数字“3”同样);
  • rs1:源寄存器1,需要读取得通用寄存器,该Bit域是寄存器的地址;
  • rs2:源寄存器2,需要读取得通用寄存器,该Bit域是寄存器的地址;
  • imm:立即数,该Bit域的数值可直接用于计算,是常数;
    在这里插入图片描述

6.RV32I指令总览

如下,是RV32I所有指令,总共47条,详细功能在后面介绍;;这里印证上面所说的同一类型的指令,操作码一致,而不同的功能通过func3、func7来区分;但是U、J型操作码是有区别的,而且I型中不同功能的指令操作码也是不一致,这些区别后面会详细讨论;
在这里插入图片描述

7.RV32I指令介绍

1)U-type

U型为两条指令,主要作用将常数(也叫立即数)计算后直接存入目标寄存器中,由于立即数占了20-bit,没有多余的bit做为func,因此这两条指令的操作码不一致作为区分;

  • lui指令:将其携带的20位立即数作为32位的高位,低12位置0,然后将结果载入到目标寄存器中;
  • 汇编写法:
lui  rd,  imm

在这里插入图片描述

  • auipc指令:将其携带的20位立即数作为32位的高位,低12位置0,然后与当前的PC值相加,将结果写入目标寄存器中;
  • 汇编写法:
auipc  rd, imm

在这里插入图片描述

2)J-type

J型也只有两条指令,同U型一样,操作码不一致;

  • jal指令:将其携带的20位立即数做符号扩展,并左移一位,产生32bit的有符号数,然后与PC值相加产生指令存储器的目标地址,跳转至PC±1MB的地址范围;同时将紧随其后的指令的地址存入目标寄存器;
  • 汇编写法:
jal  rd, offset

在这里插入图片描述

  • jalr指令:将其携带的12位立即数与源寄存器1值相加,并将结果的末尾清零,作为跳转的地址;与jal指令一样,将其后的指令地址存入目标寄存器中;
  • 汇编写法:
jalr rd, offset(rs1)

在这里插入图片描述

3)B-type

  • beq:源寄存器1、2值相等,跳转至目标地址;而目标地址由立即数符号扩展,并左移1位与PC值相加产生;
  • 汇编写法:
beq  rs1, rs2, imm

在这里插入图片描述

  • bne:源寄存器1、2值不相等,跳转至目标地址;而目标地址由立即数符号扩展,并左移1位与PC值相加产生;
  • 汇编写法:
bne  rs1, rs2, imm

在这里插入图片描述

  • blt:源寄存器1小于源寄存器2值,跳转至目标地址;而目标地址由立即数符号扩展,并左移1位与PC值相加产生;
  • 汇编写法:
blt  rs1, rs2, imm

在这里插入图片描述

  • bge:源寄存器1不小于源寄存器2值,跳转至目标地址;而目标地址由立即数符号扩展,并左移1位与PC值相加产生;
  • 汇编写法:
bge  rs1, rs2, imm

在这里插入图片描述

  • bltu:源寄存器1小于源寄存器2值,跳转至目标地址;而目标地址由立即数符号扩展,并左移1位与PC值相加产生;
  • 汇编写法:
bltu  rs1, rs2, imm

在这里插入图片描述

  • bgeu:源寄存器1不小于源寄存器2值,跳转至目标地址;而目标地址由立即数符号扩展,并左移1位与PC值相加产生;
  • 汇编写法:
bgeu  rs1, rs2, imm

在这里插入图片描述

4)I-type

I型主要分成两类功能:操作数据存储器、立即数运算;还有其他但这里先不讨论;
先介绍操作数据存储器指令,即Load指令;

  • lb:立即数符号扩展后,与源寄存器1相加,作为读取数据的地址,读出该地址的1字节数据,经符号扩展写入到目标寄存器中;
  • 汇编写法:
lb  rd, offset(rs1)

在这里插入图片描述

  • lh:立即数符号扩展后,与源寄存器1相加,作为读取数据的地址,读出该地址的2字节数据,经符号扩展写入到目标寄存器中;
  • 汇编写法:
lh  rd, offset(rs1)

在这里插入图片描述

  • lw:立即数符号扩展后,与源寄存器1相加,作为读取数据的地址,读出该地址的4字节数据,经符号扩展写入到目标寄存器中;
  • 汇编写法:
lw  rd, offset(rs1)

在这里插入图片描述

  • lbu:立即数符号扩展后,与源寄存器1相加,作为读取数据的地址,读出该地址的1字节数据,经0扩展写入到目标寄存器中;
  • 汇编写法:
lbu  rd, offset(rs1)

在这里插入图片描述

  • lhu:立即数符号扩展后,与源寄存器1相加,作为读取数据的地址,读出该地址的2字节数据,经0扩展写入到目标寄存器中;
  • 汇编写法:
lhu  rd, offset(rs1)

在这里插入图片描述
接下来介绍立即数运算指令:

  • addi:立即数做符号扩展,与源寄存器1相加(忽略溢出),将结果存入目标寄存器;
  • 汇编写法:
addi  rd, rs1, imm

在这里插入图片描述

  • slti:立即数做符号扩展,与源寄存器1做比较:条件成立目标寄存器置1,否则置0;
  • 汇编写法:
slti  rd, rs1, imm

在这里插入图片描述

  • sltiu:立即数做符号扩展,与源寄存器1做比较:条件成立目标寄存器置1,否则置0;
  • 汇编写法:
sltiu  rd, rs1, imm

在这里插入图片描述

  • xori:立即数做符号扩展,与源寄存器1相异或,将结果存入目标寄存器;
  • 汇编写法:
xori  rd, rs1, imm

在这里插入图片描述

  • ori:立即数做符号扩展,与源寄存器1相或,将结果存入目标寄存器;
  • 汇编写法:
ori  rd, rs1, imm

在这里插入图片描述

  • ani:立即数做符号扩展,与源寄存器相与,将结果存入目标寄存器;
  • 汇编写法:
ani  rd, rs1, imm

在这里插入图片描述

  • slli:将源寄存器1值左移shamt位,空位填0,结果写入目标寄存器;shamt[5]为0有效;
  • 汇编写法:
slli  rd, rs1, shamt

在这里插入图片描述

  • srli :将源寄存器1值右移shamt位,空位填0,结果写入目标寄存器;shamt[5]为0有效;
  • 汇编写法:
srli  rd, rs1, shamt

在这里插入图片描述

  • srai:将源寄存器1值循环右移shamt位,结果写入目标寄存器;shamt[5]为0有效;
  • 汇编写法:
srai  rd, rs1, shamt

在这里插入图片描述

5)S-type

  • sb:立即数符号扩展后,与源寄存器1相加作为数据存储器的地址,将源寄存器2的最低字节存入;
  • 汇编写法:
sb  rs2, offset(rs1)

在这里插入图片描述

  • sh:立即数符号扩展后,与源寄存器1相加作为数据存储器的地址,将源寄存器2的最低2个字节存入;
  • 汇编写法:
sh  rs2, offset(rs1)

在这里插入图片描述

  • sw:立即数符号扩展后,与源寄存器1相加作为数据存储器的地址,将源寄存器2的整字存入;
  • 汇编写法:
sw  rs2, offset(rs1)

在这里插入图片描述

6)R-type

  • add:源寄存器1、2相加(忽略溢出),结果将被写入目标寄存器中;
  • 汇编写法:
add rd, rs1, rs2

在这里插入图片描述

  • sub:源寄存器1 - 源寄存器2(忽略溢出),结果将被写入目标寄存器中;
  • 汇编写法:
sub rd, rs1, rs2

在这里插入图片描述

  • sll:源寄存器1值左移源寄存器2[4:0]位,空位补0,结果写入目标寄存器;
  • 汇编写法:
sll rd, rs1, rs2

在这里插入图片描述

  • slt:有符号比较源寄存器1、2值,源寄存器1小,目标寄存器写1,否则写0;
  • 汇编写法:
slt rd, rs1, rs2

在这里插入图片描述

  • sltu:无符号比较源寄存器1、2值,源寄存器1小,目标寄存器写1,否则写0;
  • 汇编写法:
sltu rd, rs1, rs2

在这里插入图片描述

  • xor:源寄存器1、2按位异或,结果写入目标寄存器;
  • 汇编写法:
xor rd, rs1, rs2

在这里插入图片描述

  • srl:源寄存器1值右移源寄存器2[4:0]位,空位补0,结果写入目标寄存器;
  • 汇编写法:
srl rd, rs1, rs2

在这里插入图片描述

  • sra:源寄存器1值循环右移源寄存器2[4:0]位,结果写入目标寄存器;
  • 汇编写法:
sra rd, rs1, rs2

在这里插入图片描述

  • or:源寄存器1、2按位或,结果写入目标寄存器;
  • 汇编写法:
or rd, rs1, rs2

在这里插入图片描述

  • and:源寄存器1、2按位与,结果写入目标寄存器;
  • 汇编写法:
and rd, rs1, rs2

在这里插入图片描述

8.RV32I指令集归类

1)算术与逻辑运算指令

如图是算术与逻辑运算指令,I和R两大类型的指令;
在这里插入图片描述
我们可以通过操作码来区分是R型还是I型,func3来区分逻辑功能,因此有了如下表,左右两列是各自的func3数字,可以看出,具有相同计算功能的指令func3是一致的,从这里再一次体现了RV指令集的规整;
注意R型中的add和sub指令func3是一样的,这里通过func7来区分;
在这里插入图片描述

2)数据载入和存储指令

这些是访问数据存储的指令,分别是读取和写入;
在这里插入图片描述

3)跳转指令

RV32只有两种跳转指令,无条件跳转:J型;有条件跳转:B型
在这里插入图片描述

9.总结

为了方便理解以及日后的回顾,用了比较通俗的表达方式,并不规范,同时也省略很多细节,最后还是建议大家仔细阅读参考文件中的书籍;


由于CSDN开始限制放置二维码,所以只有搜索 芯王国 关注我的公众号,公众号中有更多资源和干货,同时加入IC/FPGA,RISCV的交流群
QQ群号:897532154
我的gitee:传送门


参考文献

【1】《计算机组成与设计-硬件与软件接口》RISC-V版本
【2】《手把手教你设计CPU——RISC-V处理器篇》
【3】《基于FPGA与RISC-V的嵌入式系统设计》
【4】《RISC-V官方手册》

<think>好的,我现在要回答用户关于RISC-V指令集组成的问题。首先,我需要回顾自己之前的知识,并结合用户提供的引用资料来确保准确性。用户提供的引用中有几个关键点需要参考,比如引用[2]提到RISC-V是一种指令集规范,而引用[3]和[5]详细说明了指令集在软硬件中的作用以及指令格式的特点。 首先,RISC-V的指令集架构分为基础指令和扩展指令。基础指令是必须的,而扩展指令是可选的。用户可能想知道具体有哪些基础指令集和常见的扩展。根据引用[4]和[5],RV32I是基础整数指令集,包含基本的算术、逻辑、加载存储和控制流指令。然后扩展部分如M(乘除)、A(原子操作)、F(单精度浮点)、D(双精度浮点)、C(压缩指令)等,这些扩展可以根据需求添加。 接下来要确认每个指令集的具体内容。例如,RV32I包括寄存器操作、内存访问、分支跳转等。扩展指令如M添加了乘法和除法指令,而C扩展可以减少代码大小。引用[5]提到指令格式的规整性,这可能影响指令的解码和执行效率,这也需要在回答中提及。 另外,用户可能对指令格式感兴趣,比如RISC-V的六种基本指令格式:R、I、S、B、U、J。这些格式的区分有助于理解指令如何编码,引用[5]指出立即数字段的符号扩展处理,这也是一个需要强调的点。 需要确保回答结构清晰,分点列出基础指令和扩展指令,并简要说明每个部分的作用。同时,要使用正确的中文术语,避免技术术语错误。最后,生成的相关问题要围绕指令集的组成、设计优势和应用场景展开,帮助用户进一步探索。 现在检查是否有遗漏的部分,比如用户提供的引用中是否有其他重要信息。引用[3]提到指令集不仅包括硬件单元,还涉及数据格式和存储模型,这一点可以在基础指令部分提到。引用[4]提到实现处理器的项目,可能关联到指令集的应用,但用户主要询问组成,所以可能不需要深入这部分。 最后,确保所有数学表达式和公式使用正确的LaTeX格式,例如寄存器使用$符号包裹,但根据用户提供的示例,可能不需要在文本中过多使用数学表达式,除非涉及具体指令格式的表示。比如,指令格式中的字段可以用类似$imm[31:12]$的形式表示,但需要符合用户给出的格式要求,即行内用$...$,独立公式用$$...$$。 总结回答的结构: 1. 基础指令集RV32I/RV64I) - 整数运算 - 内存访问 - 控制流 2. 标准扩展指令集 - M、A、F、D、C等 3. 指令格式 - 六种基本格式 - 立即数处理 4. 模块化设计优势 生成的相关问题要引导用户深入了解各部分细节或设计优势,例如指令格式的设计如何提升性能,模块化的好处,扩展指令的应用场景等。</think>RISC-V指令集架构采用模块化设计,由基础指令集和可扩展指令集组成。其核心特点为“基础+扩展”的灵活组合模式,具体组成如下: ### 一、基础整数指令集RV32I/RV64I) 所有RISC-V处理器必须实现的基础指令集,包含: 1. **整数运算**:加法($add$)、减法($sub$)、逻辑运算($and$, $or$, $xor$)等 2. **内存访问**:加载($lw$)、存储($sw$)指令,支持字节/半字/字操作 3. **控制流**:条件分支($beq$, $bne$)、跳转指令($jal$, $jalr$) 4. **系统指令**:环境调用($ecall$)、中断返回($mret$),用于操作系统交互[^3] $$ \text{典型指令格式示例:} \quad \text{add \ rd, rs1, rs2} \quad (R型指令) $$ ### 二、标准扩展指令集 | 扩展名称 | 功能描述 | 关键指令示例 | |---------|---------|-------------| | M扩展 | 硬件乘除 | $mul$, $div$ | | A扩展 | 原子操作 | $amoadd.w$(原子加法)[^5] | | F/D扩展 | 单/双精度浮点 | $fadd.s$, $fmul.d$ | | C扩展 | 压缩指令(16) | $c.addi$(代码密度提升40%)[^2] | ### 三、指令格式设计 采用六种统一格式(R/I/S/B/U/J),特点包括: 1. 寄存器字段固定置(rs1/rs2/rd始终在指令相同置) 2. 立即数字段拼接规则:例如B型指令的立即数由$imm[12|10:5|4:1|11]$组成 3. 符号扩展优化:立即数最高提前确定,允许流水线早期完成符号扩展[^5] ### 、模块化优势 通过组合不同扩展(如RV32IMAFDC),可构建适用于嵌入式系统(RV32EC)、高性能计算(RV64GC)等不同场景的处理器[^4]。这种设计使RISC-V既能保持核心精简(基础指令仅40条),又能通过扩展满足特定领域需求[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值