skip to content

Search

RISC-V 格式

10 min read Updated:
星空,流星与大地

RISC-V中的指令格式

总览

RISC-V 的6种指令格式:

  • R-format: 寄存器-寄存器数学指令
  • I-format: 寄存器-立即数指令以及加载指令
  • S-format: 存储指令
  • B-format: 分支指令
  • U-format: 上半立即数指令
  • J-format: 跳转指令

R-format

指令布局:

R指令布局

字段说明:

  • opcode (7 bits): 操作码,指示指令类型。对于 R-format 指令,opcode 通常为 0110011。
  • rd (5 bits): 目的寄存器地址
  • funct3 (3 bits): 功能码,指示具体操作
  • rs1 (5 bits): 源寄存器1地址
  • rs2 (5 bits): 源寄存器2地址
  • funct7 (7 bits): 功能码,进一步指示具体操作

指令示例:

add x18, x19, x20
add指令示例

所有R-format指令:

funct7rs2rs1funct3rdopcode指令名
0000000rs2rs1000rd0110011add
0100000rs2rs1000rd0110011sub
0000000rs2rs1001rd0110011sll
0000000rs2rs1010rd0110011slt
0000000rs2rs1011rd0110011sltu
0000000rs2rs1100rd0110011xor
0000000rs2rs1101rd0110011srl
0100000rs2rs1101rd0110011sra
0000000rs2rs1110rd0110011or
0000000rs2rs1111rd0110011and

I-format

立即数指令

指令布局:

I指令布局

字段说明:

  • I-format指令的字段与R-format指令的区别只在于 rs2 和 funct7 被替换成了一个12位的立即数 imm。
  • opcode (7 bits): 操作码,指示指令类型。对于 I-format 立即数指令,opcode 通常为 0010011(算术立即数指令)或 0000011(加载指令)。
  • rd (5 bits): 目的寄存器地址
  • funct3 (3 bits): 功能码,指示具体操作
  • rs1 (5 bits): 源寄存器地址
  • imm (12 bits): 立即数,直接编码在指令中。在数学立即数指令中,imm 是一个有符号数,可以表示 -2048 到 2047 之间的值,在使用之前一直符号扩展为 32 位。

指令示例:

addi x15, x1, -50
addi指令示例

所有I-format立即数指令:

`imm[11:0]` `funct3` `rd` `opcode` 指令
`imm[11:0]` `000` `rd` `0010011` `addi`
`imm[11:0]` `010` `rd` `0010011` `slti`
`imm[11:0]` `011` `rd` `0010011` `sltiu`
`imm[11:0]` `100` `rd` `0010011` `xori`
`imm[11:0]` `110` `rd` `0010011` `ori`
`imm[11:0]` `111` `rd` `0010011` `andi`
`0000000` / `shamt` `001` `rd` `0010011` `slli`
`0000000` / `shamt` `101` `rd` `0010011` `srli`
`0100000` / `shamt` `101` `rd` `0010011` `srai`

加载指令

指令布局:

I指令布局

字段说明:

  • I-format指令中,存储指令字段与立即数指令相同,区别在于 opcode 不同以及 imm 的使用方式不同。
  • opcode (7 bits): 操作码,指示指令类型。对于 I-format 加载指令,opcode 通常为 0000011。
  • rd (5 bits): 目的寄存器地址
  • funct3 (3 bits): 功能码,指示具体加载类型
  • rs1 (5 bits): 基址寄存器地址
  • imm (12 bits): 立即数,表示内存地址的偏移

指令示例:

lw x14, 8(x2)
lw指令示例

所有I-format加载指令:

imm[11:0]rs1funct3rdopcode指令
imm[11:0]rs1000rd0000011lb
imm[11:0]rs1001rd0000011lh
imm[11:0]rs1010rd0000011lw
imm[11:0]rs1100rd0000011lbu
imm[11:0]rs1101rd0000011lhu

S-format

指令布局:

S指令布局

字段说明:

  • opcode (7 bits): 操作码,指示指令类型。对于 S-format 存储指令,opcode 通常为 0100011。
  • funct3 (3 bits): 功能码,指示具体存储类型
  • rs1 (5 bits): 基址寄存器地址
  • rs2 (5 bits): 源寄存器地址,存储指令中 rs2 寄存器的值将被存储到内存中
  • imm (12 bits): 立即数,表示内存地址的偏移。

指令示例:

sw x14, 8(x2)
sw指令示例

所有S-format存储指令:

imm[11:5]rs2rs1funct3imm[4:0]opcode指令
imm[11:5]rs2rs1000imm[4:0]0100011sb
imm[11:5]rs2rs1001imm[4:0]0100011sh
imm[11:5]rs2rs1010imm[4:0]0100011sw

B-format

说明:

  • 如何表示Label? Label是跳转的指令地址,可以通过与当前指令的地址的差值来表示。这个差值就是一个立即数,直接编码在指令中。
  • Label一定要存偏移量的每一位吗? 不需要,立即数的每一位不需要存储在指令中。因为指令地址是对齐的。 (注意:只省略了偏移量的最后一位)

指令布局:

B指令布局

字段说明:

  • opcode (7 bits): 操作码,指示指令类型。对于 B-format 分支指令,opcode 通常为 1100011。
  • funct3 (3 bits): 功能码,指示具体分支类型
  • rs1 (5 bits): 源寄存器1地址
  • rs2 (5 bits): 源寄存器2地址
  • imm (13 bits): 立即数,表示跳转的偏移量。由于指令地址是对齐的,所以立即数的最后一位被省略了。

指令示例:

Loop: 
    beq x19, x10, End
    add x18, x18, x10
    addi x19, x19, -1
    j Loop
End:
beq指令示例

立即数扩展: 下面的图片演示了I/S/B-format指令中立即数的扩展方式

立即数扩展示例

所有B-format分支指令:

imm[12]imm[10:5]rs2rs1funct3imm[4:1]imm[11]opcode指令
imm[12]imm[10:5]rs2rs1000imm[4:1]imm[11]1100011beq
imm[12]imm[10:5]rs2rs1001imm[4:1]imm[11]1100011bne
imm[12]imm[10:5]rs2rs1100imm[4:1]imm[11]1100011blt
imm[12]imm[10:5]rs2rs1101imm[4:1]imm[11]1100011bge
imm[12]imm[10:5]rs2rs1110imm[4:1]imm[11]1100011bltu
imm[12]imm[10:5]rs2rs1111imm[4:1]imm[11]1100011bgeu

U-format

lui/auipc

指令含义:

  • lui (load upper immediate): 将20位立即数左移12位加载到寄存器中,低12位填0。
  • auipc (add upper immediate to pc): 将20位立即数左移12位加上当前指令地址(pc),并将结果存储在寄存器中。

典型用途:

# 加载一个32位立即数到寄存器中
lui rd, imm20
addi rd, rd, imm12
# 加载相对PC地址偏移量的指令地址到寄存器中
auipc rd, imm20
lw rd, imm12(rd)
# 实现32位立即数宽度的长跳转
auipc rd, imm20
jalr rd, imm12(rd)

指令结构

U指令布局

J-format

J指令布局

总结

RISC-V指令格式总结