RISC-V指令集之RV32I
- 1 RV32I的寄存器
- 2 RV32I的指令
- 2.1 算术运算指令
- 2.2 逻辑运算指令
- 2.3 移位运算指令
- 2.4 内存读写指令
- 2.5 分支与跳转指令
本文属于《 RISC-V指令集基础系列教程》之一,欢迎查看其它文章。
1 RV32I的寄存器
如下图,列出了RV32I 寄存器和由RISC-V 应用程序二进制接口(Application Binary Interface,ABI)定义的寄存器名称。我们将在示例代码中使用ABI 名称来提升可读性。
在RISC-V 的规范里面,RV32I定义了32 个通用寄存器,其中31个是常规寄存器,1个恒为0值的x0寄存器。
2 RV32I的指令
RV32I具备的所有指令,如下所示。
这里展示了RV32I指令集的每一条指令,并且每条指令的具体格式,以及指令类型。
RV32I指令集,一共包含了47条指令,分别涵盖了数据传输、算术运算、逻辑运算、分支跳转、比较判断等功能。
我们按不同类型,划分来看:
2.1 算术运算指令
算术运算指令,有add、sub、addi、lui、auipc,其指令形式与含义,如下所示:
指令形式 | 功能说明 |
---|---|
add rd, rs1, rs2 | rd = rs1 + rs2 |
sub rd, rs1, rs2 | rd = rs1 - rs2 |
addi rd, rs1, imm | rd = rs1 + imm |
lui rd, imm | rd = imm << 12 |
auipc rd, imm | rd = PC + (imm << 12) |
2.2 逻辑运算指令
逻辑运算指令,有xor、or、and、xori、ori、andi,其指令形式与含义,如下所示:
指令形式 | 功能说明 |
---|---|
xor rd, rs1, rs2 | rd = rs1 ^ rs2,表示rs1与rs2按位异或,结果存入rd |
or rd, rs1, rs2 | rd = rs1 \ rs2,表示rs1与rs2按位或,结果存入rd |
and rd, rs1, rs2 | rd = rs1 & rs2,表示rs1与rs2按位与,结果存入rd |
xori rd, rs1, imm | rd = rs1 ^ imm,表示rs1与imm按位异或,结果存入rd |
ori rd, rs1, imm | rd = rs1 \ imm,表示rs1与imm按位或,结果存入rd |
andi rd, rs1, imm | rd = rs1 & imm,表示rs1与imm按位与,结果存入rd |
2.3 移位运算指令
移位运算指令,有sll、srl、sra等,共10条,其指令形式与含义,如下所示:
指令形式 | 功能说明 |
---|---|
sll rd, rs1, rs2 | rd = rs1 << rs2,表示将rs1逻辑左移,左移位数为rs2,结果存入rd |
srl rd, rs1, rs2 | rd = rs1 >> rs2,表示将rs1逻辑右移,右移位数为rs2,结果存入rd |
sra rd, rs1, rs2 | rd = rs1 >> rs2,表示将rs1算术右移,右移位数为rs2,结果存入rd |
slt rd, rs1, rs2 | rd = (rs1 < rs2) ? 1:0,表示rs1小于rs2,则将1写入rd,否则将0写入rd |
sltu rd, rs1, rs2 | rd = (rs1 < rs2) ? 1:0,表示无符号的rs1小于rs2,则将1写入rd,否则将0写入rd |
slli rd, rs1, imm | rd = rs1 << imm[0:4],表示将rs1逻辑左移,左移位数为imm,结果存入rd |
srli rd, rs1, imm | rd = rs1 >> imm[0:4],表示将rs1逻辑右移,右移位数为imm,结果存入rd |
srai rd, rs1, imm | rd = rs1 >> imm[0:4],表示将rs1算术右移,右移位数为imm,结果存入rd |
slti rd, rs1, imm | rd = (rs1 < imm) ? 1:0,表示rs1小于imm,则将1写入rd,否则将0写入rd |
sltiu rd, rs1, imm | rd = (rs1 < imm) ? 1:0,表示无符号的rs1小于imm,则将1写入rd,否则将0写入rd |
2.4 内存读写指令
RV32I数据读写指令,可以从内存中加载数据到寄存器,或者将寄存器值存储到内存。亦或者将数据从一个寄存器复制到另一个。或者将立即数或标签地址加载到寄存器。
RV32I内存读写指令,有lb、lh、lw等,共8条,其指令形式与含义,如下所示:
指令形式 | 功能说明 |
---|---|
lb rd, imm(rs1) | rd = M[rs1+imm][0:7],表示从内存地址(rs1+imm)中,加载一个8位有符号字节到寄存器rd |
lh rd, imm(rs1) | rd=M[rs1+imm][0:15],表示从内存地址(rs1+imm)中,加载一个16位有符号半字到寄存器rd |
lw rd, imm(rs1) | rd = M[rs1+imm][0:31],表示从内存地址(rs1+imm)中,加载一个32位有符号或无符号字到寄存器rd |
lbu rd, imm(rs1) | rd = M[rs1+imm][0:7],表示从内存地址(rs1+imm)中,加载一个8位无符号字节到寄存器rd |
lhu rd, imm(rs1) | rd = M[rs1+inm][0:15],表示从内存地址(rs1+imm)中,加载一个16位无符号半字到寄存器rd |
sb rs2, imm(rs1) | M[rs1+imm][0:7] = rs2[0:7],表示将rs2中的最低8位值,存储到(rs1+imm)地址的内存中 |
sh rs2, imm(rs1) | M[rs1+imm][0:15] = rs2[0:15],表示将rs2中的最低16位值,存储到(rs1+imm)地址的内存中 |
sw rs2, imm(rs1) | M[rs1+imm][0:31] = rs2[0:31],表示将rs2中的最低32位值,存储到(rs1+imm)地址的内存中 |
2.5 分支与跳转指令
条件跳转指令,是依据指令中的条件来决定跳转。换句话说就是,通过判断条件来决定是否改变当前执行流程。
RV32I分支与跳转指令,有beq、bne、blt等,共8条,其指令形式与含义,如下所示:
指令形式 | 功能说明 |
---|---|
beq rs1, rs2, imm | if(rs1 == rs2) PC+=imm,表示如果rs1等于rs2,则跳转到PC+imm |
bne rs1, rs2, imm | if(rs1 != rs2) PC+=imm,表示如果rs1不等于rs2,则跳转到PC+imm |
blt rs1, rs2, imm | if(rs1 < rs2) PC+=imm,表示如果有符号的rs1小于rs2,则跳转到PC+imm |
bge rs1, rs2, imm | if(rs1 >= rs2) PC+=imm,表示如果有符号的rs1大于等于rs2,则跳转到PC+imm |
bltu rs1, rs2, imm | if(rs1 < rs2) PC+=imm,表示如果无符号的rs1小于rs2,则跳转到PC+imm |
bgeu rs1, rs2, imm | if(rs1 >= rs2) PC+=imm,表示如果无符号的rs1大于等于rs2,则跳转到PC+imm |
jal rd, imm | rd = PC+4; PC += imm,表示首先将PC+4的地址值存储到寄存器rd,然后跳转到PC+imm处 |
jalr rd, imm(rs1) | rd = PC+4; PC= rs1 + imm,表示首先将PC+4的地址值存储到寄存器rd,然后跳转到rs1+imm处 |
关于跳转指令,还有几条常用伪指令:
指令形式 | 功能说明 |
---|---|
j lab | 跳转到lab标签地址处 |
jr rs1 | 跳转到寄存器rs1指定的地址 |
jal lab | 首先将PC+4的地址值存储到返回寄存器ra,然后跳转到lab标签处 |
ret | 跳转到返回寄存器ra保存的地址 |
通过上述内容的学习,我们了解了RV32I指令集有哪些指令,以及这些指令的字节码(机器码)构成。