欧洲世界杯_06年世界杯梅西 - hello186.com

一起学RISC-V汇编第4讲之指令格式

2025-10-02 04:04:16 世界杯经典比赛 9355

一起学RISC-V汇编第4讲之指令格式

RISC-V指令集的一个特点就是指令是定长的,对于RV32I ISA,一共有47条指令,有6种指令指令格式,分别为R/I/S/B/U/J类型,其中:

R型用于寄存器-寄存器间的操作(10条)

I型用于短立即数和访存(Load)操作(25条)

S型用于访存Store操作(3条)

B型用于条件跳转(6条)

U型用于长立即数(2条)

J型用于无条件跳转(1条)

格式如下图所示:

从图中可以看出RV32I指令集:

指令的长度固定为32位,以4字节边界对齐;

源寄存器rs1、rs2,以及目标寄存器rd的位置保持不变;

RISC-V的指令编码风格是操作码(opcode)放在低位,操作码占7bit;

立即数的符号位放置在最高位(31位),方便进行符号扩展;

RISC-V 指令格式为三操作数或者两操作数,操作数只能为立即数或寄存器;

B类型分支跳转指令是在S类型基础上将立即数进行了旋转,J类型跳转指令是在U类型基础上将立即数进行了旋转,所以也可以认为RISC-V仅有4种指令类型;

B型分支指令和J型跳转指令的地址需要左移1位(相当于乘以2),以获得更大的跳转范围。意味着:B型分支指令和J型跳转指令实际上只能跳转到偶数地址。

下面分别进行讲解:

1 RISC-V指令格式

1.1 R-type

R-type是最常用的指令类型,表示寄存器-寄存器操作,指令的操作由7bit的opcode、3位的func3、7位的func7 共同决定的(func3字段正好3位,func7字段正好7位);R-type包含有三个寄存器(两个源寄存器rs1与rs2,一个目的寄存器rd),寄存器位宽为5bit,可以寻址32个寄存器(指令集定义的通用寄存器个数2^5),由这些小细节可见,RISC-V指令集经过了巧妙的设计。

RV32I一共有10条R-type指令:

其详细编码如下:

以上指令的使用形式为:

# 加(算术指令)

ADD rd, rs1, rs2

# 减(算术指令)

SUB rd, rs1, rs2

# 逻辑左移(移位指令)

SLL rd, rs1, rs2

# 小于则置位(比较-置位)

SLT rd, rs1, rs2

# 无符号小于则置位(比较-置位)

SLTU rd, rs1, rs2

# 异或(逻辑指令)

XOR rd, rs1, rs2

# 逻辑右移(移位指令)

SRL rd, rs1, rs2

# 算术右移 (移位指令)

SRA rd, rs1, rs2

# 或(逻辑指令)

OR rd, rs1, rs2

# 与(逻辑指令)

AND rd, rs1, rs2

1.2 I-type

I-type指令有两个寄存器和一个立即数,相当于将R-type指令格式中的一个寄存器改为立即数,立即数一共12位,也即支持有符号数[-2028, 2017],如果是无符号数范围为[0-4096];指令的操作由7bit的opcode、3位的func3来决定。

RV32I一共有25条I-type指令,这里列出15条,分为9条短立即数操作,5条load取数操作,以及1条跳转操作。其它10条I-type指令为CSR读写指令以及环境指令等,后续会讲到。

可见:

短立即数操作为1.1中 R-type中的指令中的rs2寄存器换成立即数,表示寄存器与立即数进行计算,结果存到目的寄存器里;

load取数操作中,rs1为寄存器,立即数为偏移地址,表示寄存器相对寻址。

9条短立即数操作:

以上指令的使用形式为:

# 加立即数(算术指令)

ADDI rd, rs1, imm

# 小于立即数则置位(比较-置位)

SLTI rd, rs1, imm

# 无符号小于立即数则置位(比较-置位)

SLTIU rd, rs1, imm

# 异或立即数(逻辑指令)

XORI rd, rs1, imm

# 或立即数(逻辑指令)

ORI rd, rs1, imm

# 与立即数(逻辑指令)

ANDI rd, rs1, imm

# 逻辑左移立即数(移位指令)

SLLI rd, rs1, shamt

# 逻辑右移立即数(移位指令)

SRLI rd, rs1, shamt

# 算术右移立即数 (移位指令)

SRAI rd, rs1, shamt

注意:riscv中没有SUBI指令,SUBI可以由ADDI来实现(减一个数等于加一个负数)。

5条load取数操作:

以上指令的使用形式为:

# 取字节(取指令)

LB rd, imm(rs1)

# 取半字(取指令)

LH rd, imm(rs1)

# 取字(取数令)

LW rd, imm(rs1)

# 取无符号字节(取指令)

LBU rd, imm(rs1)

# 取无符号半字(取指令)

LHU rd, imm(rs1)

RV32I为什么没有LWU指令?实际上LWU属于RV64I的指令,LB,LH 都是load数到32位寄存器里,由于寄存器比要取的数宽,所以存在符号扩展,在RV64I架构,寄存器为64bit的,LW才存在符号扩展,所以LWU属于RV64I的指令。

1条跳转操作:

这条指令的使用形式为:

# 寄存器跳转并链接(跳转指令)

JALR rd, imm(rs1)

1.3 S-type

S-type指令操作由7bit的opcode、3位的func3来决定,S-type指令没有目的寄存器,一般表示访存的store操作,如sw,sd等。指令中包含两个源寄存器(rs1,rs2)与一个12位立即数(imm[31:25]与imm[11:7],这么样拆分目的在于尽量固定rs1,rs2 位域的位置,方便译码)

RV32I一共有3条S-type指令,实现的同样是寄存器相对寻址:

以上指令的使用形式为:

# 存字节(存指令)

SB rs2, imm(rs1)

# 存半数(存指令)

SH rs2, imm(rs1)

# 存字(存指令)

SW rs2, imm(rs1)

1.4 B-type

B-type指令操作由7bit的opcode、3位的func3来决定;指令中包含两个源寄存器(rs1,rs2)与一个12位立即数,B-typed 一般表示条件跳转操作指令(分支指令),如相等(beq)、不相等(bne)、大于等于(bge)以及小于(blt)等跳转指令。

RV32I一共有6条B-type指令:

以上指令的使用形式为:

# 相等时分支(分支指令)

BEQ rs1, rs2, imm

# 不等时分支(分支指令)

BNE rs1, rs2, imm

# 小于时分支(分支指令)

BLT rs1, rs2, imm

# 大于等于时分支(分支指令)

BGE rs1, rs2, imm

# 无符号小于时分支(分支指令)

BLTU rs1, rs2, imm

# 无符号大于等于时分支(分支指令)

BGEU rs1, rs2, imm

为什么没有小于等于、大于这些分支指令?

实际上if (a <= b),可以转换为 if (b >= a) , 所以只需交换操作数即可,无需专门的指令,riscv中小于等于、大于等分支指令都是伪指令,后续伪指令章会讲到。

1.5 U-type

U-type指令操作仅由7位opcode决定;指令包括一个目的寄存器rd和20位的立即数,U-type一般表示长立即数操作,例如 lui 指令,将立即数左移 12 位,并将低 12 位置零,结果写回目的寄存器中。

RV32I一共有2条U-type指令:

以上指令的使用形式为:

# 装入高位立即数(算术指令)

LUI rd, imm

# PC加高位立即数(算术指令)

AUIPC rd, imm

看这个指令的描述,可以与I-type的短立即数(12bit)配合,得到一个完整的32bit立即数。

1.6 J-type

J-type指令操作仅由7位opcode决定,与U-type一样只有一个目的寄存器rd和20位的立即数,但是立即数的位域与U-type的组成不同,J-type一般用于无条件跳转,如jal指令,RV32I一共有1条J-type指令。

以上指令的使用形式为:

# 跳转(跳转指令)

JAL rd, imm

2 RISC-V是如何译码的?

通过opcode来得到指令类型,RISC-V 规范中给出了如下图所示的 opcode 表格(适用于 RV32G 和 RV64G):

opcode一共7位,低两bit固定位1(inst[1:0]=0b11),根据inst[6:5] 与 nst[4: 2]可查表。根据指令类型,可以判断得到是属于R/I/S/B/U/J中的某一类型,然后按照其格式进行拆分译码,例如:如果是R-type,进一步拆分func3和func7字段。

如表中对应关系为:

指令类型

对应opcode map中的类型

R类型

OP

I类型

OP-IMM、LOAD、JALR

S类型

STORE

B类型

BRANCH

U类型

AUIPC、LUI

J类型

JAL

详情可以参考芯来开源的蜂鸟解码实现:

https://github.com/riscv-mcu/e203_hbirdv2/blob/master/rtl/e203/core/e203_exu_decode.v

参考:

《riscv-spec-20191213.pdf》

3、寄存器 — RISC-V RT-Thread 编程指南 0.0.1 文档 (riscv-rtthread-programming-manual.readthedocs.io)

RISC-V 指令格式和6种基本整数指令_csrrw-CSDN博客

计算机系统基础(五)之RISC-V指令集

从零开始,徒手写一个 RISC-V 模拟器(2)——RISC-V 指令集与 CPU - 泰晓科技 (tinylab.org)