Skip to content
Published at:

附录 B. 标准扩展指令速查表

RISC-V 标准扩展在 RV64I 基础上增加了乘法除法(M)、原子操作(A)、单/双精度浮点(F/D)、压缩指令(C)等功能。本章提供所有标准扩展的完整指令速查表。


M 扩展:乘除法

所有 M 扩展指令均为 R-type。乘法指令 opcode=0110011,funct7=0000001。除法指令 opcode=0110011,funct7=0000001。

标准乘除法(64 位操作)

指令操作语义funct3
mul rd, rs1, rs2rd = (rs1 * rs2)[63:0](低 64 位)000
mulh rd, rs1, rs2rd = (rs1 * rs2)[127:64](有符号乘高 64 位)001
mulhsu rd, rs1, rs2rd = (有符号 rs1 * 无符号 rs2)[127:64]010
mulhu rd, rs1, rs2rd = (rs1 * rs2)[127:64](无符号乘高 64 位)011
div rd, rs1, rs2rd = rs1 / rs2(有符号,向零舍入)100
divu rd, rs1, rs2rd = rs1 / rs2(无符号)101
rem rd, rs1, rs2rd = rs1 % rs2(有符号,向零舍入)110
remu rd, rs1, rs2rd = rs1 % rs2(无符号)111

除零行为:除法结果为 -1(~0),取余结果为被除数。不产生异常。

RV64I W 变体(32 位操作,opcode=0111011,funct7=0000001)

指令操作语义funct3
mulw rd, rs1, rs2rd = sign_extend((rs1 * rs2)[31:0])000
divw rd, rs1, rs2rd = sign_extend(rs1[31:0] / rs2[31:0])100
divuw rd, rs1, rs2rd = sign_extend(rs1[31:0] /u rs2[31:0])101
remw rd, rs1, rs2rd = sign_extend(rs1[31:0] % rs2[31:0])110
remuw rd, rs1, rs2rd = sign_extend(rs1[31:0] %u rs2[31:0])111

A 扩展:原子操作

所有 A 扩展指令 opcode=0101111。分为 LR/SC(加载保留/条件存储)和 AMO(原子内存操作)两类。

LR/SC(opcode=0101111)

指令操作语义funct3funct7
lr.w rd, (rs1)rd = M[rs1][31:0]; 设置保留位(32 位)01000010xx
lr.d rd, (rs1)rd = M[rs1][63:0]; 设置保留位(64 位)01100010xx
sc.w rd, rs2, (rs1)若保留位有效:M[rs1][31:0]=rs2[31:0], rd=0; 否则 rd=101000011xx
sc.d rd, rs2, (rs1)若保留位有效:M[rs1][63:0]=rs2, rd=0; 否则 rd=101100011xx

说明:LR(Load-Reserved)在读取时设置硬件保留位;SC(Store-Conditional)仅在保留位仍有效时写入,否则失败(rd=1 表示失败)。funct7 的 bit[1:0](aq/rl)控制顺序语义:aq(Acquire),rl(Release)。

AMO 指令(opcode=0101111)

每条 AMO 指令读取 M[rs1] 的旧值写入 rd,同时对内存值执行原子二元运算,将结果写回 M[rs1]。funct5 选择运算,funct3 选择数据宽度(010=.w, 011=.d)。

指令操作语义funct5
amoadd.w/d rd, rs2, (rs1)原子加:M += rs200000
amoswap.w/d rd, rs2, (rs1)原子交换:M = rs200001
amoor.w/d rd, rs2, (rs1)原子或:M |= rs200010
amoand.w/d rd, rs2, (rs1)原子与:M &= rs200011
amoxor.w/d rd, rs2, (rs1)原子异或:M ^= rs200100
amomax.w/d rd, rs2, (rs1)原子有符号最大:M = max(M, rs2)01010
amomaxu.w/d rd, rs2, (rs1)原子无符号最大:M = maxu(M, rs2)01011
amomin.w/d rd, rs2, (rs1)原子有符号最小:M = min(M, rs2)01100
amominu.w/d rd, rs2, (rs1)原子无符号最小:M = minu(M, rs2)01101
A 扩展指令数数量
LR/SC(32+64)4
AMO(9 操作 x 2 宽度)18
合计22

F 扩展:单精度浮点

F 扩展指令的 opcode 和 fmt 字段取决于指令类别。浮点通用 opcode=1010011(FP 运算),Load opcode=0000111,Store opcode=0100111。fmt 字段(inst[26:25]):00=单精度(S),01=双精度(D),10=半精度(H),11=四倍精度(Q)。

浮点 Load/Store

指令操作语义fmtfunct3
flw fd, imm(rs1)fd = M[rs1+imm][31:0](单精度 load)S010
fsw fs2, imm(rs1)M[rs1+imm][31:0] = fs2[31:0](单精度 store)S010

浮点算术运算(opcode=1010011,fmt=S)

指令操作语义funct5说明
fadd.s fd, fs1, fs2fd = fs1 + fs200000单精度加法
fsub.s fd, fs1, fs2fd = fs1 - fs200001单精度减法
fmul.s fd, fs1, fs2fd = fs1 * fs200010单精度乘法
fdiv.s fd, fs1, fs2fd = fs1 / fs200011单精度除法
fsqrt.s fd, fs1fd = sqrt(fs1)01011单精度平方根(rs2=x0)
fmin.s fd, fs1, fs2fd = min(fs1, fs2)00101单精度最小值
fmax.s fd, fs1, fs2fd = max(fs1, fs2)00101单精度最大值(funct3=001)
fmadd.s fd, fs1, fs2, fs3fd = fs1 * fs2 + fs3融合乘加(opcode=1000011)
fmsub.s fd, fs1, fs2, fs3fd = fs1 * fs2 - fs3融合乘减(opcode=1000111)
fnmsub.s fd, fs1, fs2, fs3fd = -fs1 * fs2 + fs3负乘加(opcode=1001011)
fnmadd.s fd, fs1, fs2, fs3fd = -fs1 * fs2 - fs3负乘减(opcode=1001111)

FMA 指令(fmadd/fmsub/fnmsub/fnmadd)为 R4-type(4 寄存器格式),opcode 不同于普通浮点运算。

浮点转换(opcode=1010011)

指令操作语义源 fmt目标 fmtfunct5
fcvt.w.s rd, fs1rd = sign_extend(int32_t(fs1)); 向零舍入SW11000
fcvt.wu.s rd, fs1rd = sign_extend(uint32_t(fs1)); 向零舍入SWU11000
fcvt.l.s rd, fs1rd = int64_t(fs1); 向零舍入SL11000
fcvt.lu.s rd, fs1rd = uint64_t(fs1); 向零舍入SLU11000
fcvt.s.w fd, rs1fd = float32(int32_t(rs1))WS11010
fcvt.s.wu fd, rs1fd = float32(uint32_t(rs1))WUS11010
fcvt.s.l fd, rs1fd = float32(int64_t(rs1))LS11010
fcvt.s.lu fd, rs1fd = float32(uint64_t(rs1))LUS11010

浮点比较(opcode=1010011,fmt=S)

指令操作语义funct5funct3
fleq.s rd, fs1, fs2rd = (fs1 == fs2) ? 1 : 010100010
fltq.s rd, fs1, fs2rd = (fs1 < fs2) ? 1 : 010100001
fle.s rd, fs1, fs2rd = (fs1 <= fs2) ? 1 : 010100000

浮点移动(opcode=1010011)

指令操作语义funct5说明
fsgnj.s fd, fs1, fs2fd = {fs2[31], fs1[30:0]}(符号注入)00100funct3=000
fsgnjn.s fd, fs1, fs2fd = {~fs2[31], fs1[30:0]}(负符号注入)00100funct3=001
fsgnjx.s fd, fs1, fs2fd = {fs1[31]^fs2[31], fs1[30:0]}(异或符号注入)00100funct3=010
fclass.s rd, fs1rd = 分类结果(10 类编码)11100funct3=001
fmv.x.w rd, fs1rd = sign_extend(fs1[31:0])(FP→整数)11100funct3=000

D 扩展:双精度浮点

D 扩展在 F 基础上增加双精度(64 位)指令。fmt=01(D)。包含所有 F 扩展指令的双精度版本。

浮点 Load/Store(双精度)

指令操作语义fmtfunct3
fld fd, imm(rs1)fd = M[rs1+imm][63:0](双精度 load)D011
fsd fs2, imm(rs1)M[rs1+imm][63:0] = fs2[63:0](双精度 store)D011

浮点算术运算(fmt=D)

指令操作语义funct5
fadd.d fd, fs1, fs2fd = fs1 + fs2(双精度)00000
fsub.d fd, fs1, fs2fd = fs1 - fs2(双精度)00001
fmul.d fd, fs1, fs2fd = fs1 * fs2(双精度)00010
fdiv.d fd, fs1, fs2fd = fs1 / fs2(双精度)00011
fsqrt.d fd, fs1fd = sqrt(fs1)(双精度)01011
fmin.d fd, fs1, fs2fd = min(fs1, fs2)(双精度)00101
fmax.d fd, fs1, fs2fd = max(fs1, fs2)(双精度)00101
fmadd.d fd, fs1, fs2, fs3fd = fs1 * fs2 + fs3(FMA)
fmsub.d fd, fs1, fs2, fs3fd = fs1 * fs2 - fs3
fnmsub.d fd, fs1, fs2, fs3fd = -fs1 * fs2 + fs3
fnmadd.d fd, fs1, fs2, fs3fd = -fs1 * fs2 - fs3

浮点转换(D 扩展)

指令操作语义源 fmt目标 fmtfunct5
fcvt.d.s fd, fs1fd = float64(float32(fs1))SD01000
fcvt.s.d fd, fs1fd = float32(float64(fs1))DS01000
fcvt.w.d rd, fs1rd = sign_extend(int32_t(fs1)); 向零舍入DW11000
fcvt.wu.d rd, fs1rd = sign_extend(uint32_t(fs1)); 向零舍入DWU11000
fcvt.l.d rd, fs1rd = int64_t(fs1); 向零舍入DL11000
fcvt.lu.d rd, fs1rd = uint64_t(fs1); 向零舍入DLU11000
fcvt.d.w fd, rs1fd = float64(int32_t(rs1))WD11010
fcvt.d.wu fd, rs1fd = float64(uint32_t(rs1))WUD11010
fcvt.d.l fd, rs1fd = float64(int64_t(rs1))LD11010
fcvt.d.lu fd, rs1fd = float64(uint64_t(rs1))LUD11010

浮点比较与移动(fmt=D)

指令操作语义fmt
fleq.d rd, fs1, fs2rd = (fs1 == fs2) ? 1 : 0D
fltq.d rd, fs1, fs2rd = (fs1 < fs2) ? 1 : 0D
fle.d rd, fs1, fs2rd = (fs1 <= fs2) ? 1 : 0D
fsgnj.d fd, fs1, fs2符号注入(同 S)D
fsgnjn.d fd, fs1, fs2负符号注入D
fsgnjx.d fd, fs1, fs2异或符号注入D
fclass.d rd, fs1双精度分类D
fmv.d fd, fs双精度浮点寄存器间移动D
fmv.x.d rd, fs1rd = fs1[63:0](FP→整数,64 位)D

浮点寄存器移动(跨类型)

指令操作语义fmt
fmv.w.x fd, rs1fd[31:0] = rs1[31:0]; fd[63:32]=1s(整数→SP)S
fmv.d.x fd, rs1fd = rs1(整数→DP)D

F/D 扩展依赖关系:D 扩展必然包含 F 扩展。实现 D 必须同时支持 S 精度指令。


C 扩展:压缩指令

C 扩展提供 16 位压缩编码,缩小代码体积。每条 C 指令有对应的 32 位等效指令。压缩指令的 opcode 位于 [1:0] 位。

Quadrant 0(opcode[1:0]=00):C0 指令

指令编码含义16 位指令32 位等效
c.addi4spn rd', imm栈指针加立即数(imm≠0, rd'=x8-x15)000_0_xxx_xxxxxxx_00addi rd', sp, imm*4
c.fld rd', imm(rs1')双精度 load001_xxx_xxxxxxx_00fld rd', imm*8(rs1')
c.lw rd', imm(rs1')32 位 load010_xxx_xxxxxxx_00lw rd', imm*4(rs1')
c.ld rd', imm(rs1')64 位 load011_xxx_xxxxxxx_00ld rd', imm*8(rs1')
c.fsd rs2', imm(rs1')双精度 store101_xxx_xxxxxxx_00fsd rs2', imm*8(rs1')
c.sw rs2', imm(rs1')32 位 store110_xxx_xxxxxxx_00sw rs2', imm*4(rs1')
c.sd rs2', imm(rs1')64 位 store111_xxx_xxxxxxx_00sd rs2', imm*8(rs1')
c.addi4spn rd', nzuimm栈偏移地址(立即数零扩展,nz)addi rd', sp, nzuimm

寄存器编码:rd' 和 rs1' 使用 3 位编码(000=x8, 001=x9, ..., 111=x15)。

Quadrant 1(opcode[1:0]=01):C1 指令

指令编码含义32 位等效
c.addi rd, immrd=rd+imm(rd≠x0,imm≠0)addi rd, rd, imm
c.addiw rd, imm32 位加法(rd≠x0)addiw rd, rd, imm
c.jal add带链接跳转(RV32)jal x1, offset
c.li rd, imm加载立即数(rd≠x0)addi rd, x0, imm
c.lui rd, imm加载高立即数(rd≠{x0,x2},imm≠0)lui rd, imm
c.addi16sp immsp=sp+imm(imm≠0,16 字节对齐)addi sp, sp, imm
c.srli rd', imm逻辑右移(rd'=x8-x15)srli rd', rd', imm
c.srai rd', imm算术右移srai rd', rd', imm
c.andi rd', imm按位与andi rd', rd', imm
c.sub rd', rs2'减法sub rd', rd', rs2'
c.xor rd', rs2'异或xor rd', rd', rs2'
c.or rd', rs2'按位或or rd', rd', rs2'
c.and rd', rs2'按位与and rd', rd', rs2'
c.j offset无条件跳转jal x0, offset
c.beqz rs1', offset为零跳转beq rs1', x0, offset
c.bnez rs1', offset非零跳转bne rs1', x0, offset

Quadrant 2(opcode[1:0]=10):C2 指令

指令编码含义32 位等效
c.slli rd, imm逻辑左移(rd≠x0,imm≠0)slli rd, rd, imm
c.fldsp fd, imm(sp)双精度 FP load(相对 sp)fld fd, imm(sp)
c.lwsp rd, imm(sp)32 位 load(rd≠x0)lw rd, imm(sp)
c.ldsp rd, imm(sp)64 位 load(rd≠x0)ld rd, imm(sp)
c.jr rs1跳转至寄存器(rs1≠x0)jalr x0, rs1, 0
c.mv rd, rs2寄存器移动(rd≠x0,rs2≠x0)add rd, x0, rs2
c.ebreak断点ebreak
c.jalr rs1带链接跳转(rs1≠x0)jalr x1, rs1, 0
c.add rd, rs2加法(rd≠x0,rs2≠x0)add rd, rd, rs2
c.fsdsp fs2, imm(sp)双精度 FP store(相对 sp)fsd fs2, imm(sp)
c.swsp rs2, imm(sp)32 位 storesw rs2, imm(sp)
c.sdsp rs2, imm(sp)64 位 storesd rs2, imm(sp)

压缩指令注意:寄存器编码有限(3 位或 5 位),立即数范围受限。压缩指令总是对应唯一的 32 位指令,由汇编器自动选择。编写汇编时直接使用 32 位伪指令或伪指令即可,汇编器会尽可能生成压缩编码以减小代码尺寸。

C 扩展寄存器编码

3 位编码 (rd'/rs')寄存器说明
000x8 (s0)C0/C1 中使用的 rd'/rs' 寄存器组
001x9 (s1)
010x10 (a0)
011x11 (a1)
100x12 (a2)
101x13 (a3)
110x14 (a4)
111x15 (a5)
5 位编码 (rd/rs)可用的寄存器
5-bitx0-x31 全范围

扩展速查总结

扩展名描述指令数(约)依赖
M整数乘除法8 + 5(W) = 13
A原子操作4(LR/SC) + 18(AMO) = 22
F单精度浮点~30(含 FMA/转换/比较)
D双精度浮点~30(含转换/比较/移动)F
C压缩指令~27(16 位编码)

RISC-V 常见组合:RV64IMA(嵌入式)、RV64IMAFD(通用计算,又名 RV64G)、RV64IMAFDC(含压缩指令,又名 RV64GC)。