附录 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, rs2 | rd = (rs1 * rs2)[63:0](低 64 位) | 000 |
mulh rd, rs1, rs2 | rd = (rs1 * rs2)[127:64](有符号乘高 64 位) | 001 |
mulhsu rd, rs1, rs2 | rd = (有符号 rs1 * 无符号 rs2)[127:64] | 010 |
mulhu rd, rs1, rs2 | rd = (rs1 * rs2)[127:64](无符号乘高 64 位) | 011 |
div rd, rs1, rs2 | rd = rs1 / rs2(有符号,向零舍入) | 100 |
divu rd, rs1, rs2 | rd = rs1 / rs2(无符号) | 101 |
rem rd, rs1, rs2 | rd = rs1 % rs2(有符号,向零舍入) | 110 |
remu rd, rs1, rs2 | rd = rs1 % rs2(无符号) | 111 |
除零行为:除法结果为 -1(~0),取余结果为被除数。不产生异常。
RV64I W 变体(32 位操作,opcode=0111011,funct7=0000001)
| 指令 | 操作语义 | funct3 |
|---|---|---|
mulw rd, rs1, rs2 | rd = sign_extend((rs1 * rs2)[31:0]) | 000 |
divw rd, rs1, rs2 | rd = sign_extend(rs1[31:0] / rs2[31:0]) | 100 |
divuw rd, rs1, rs2 | rd = sign_extend(rs1[31:0] /u rs2[31:0]) | 101 |
remw rd, rs1, rs2 | rd = sign_extend(rs1[31:0] % rs2[31:0]) | 110 |
remuw rd, rs1, rs2 | rd = sign_extend(rs1[31:0] %u rs2[31:0]) | 111 |
A 扩展:原子操作
所有 A 扩展指令 opcode=0101111。分为 LR/SC(加载保留/条件存储)和 AMO(原子内存操作)两类。
LR/SC(opcode=0101111)
| 指令 | 操作语义 | funct3 | funct7 |
|---|---|---|---|
lr.w rd, (rs1) | rd = M[rs1][31:0]; 设置保留位(32 位) | 010 | 00010xx |
lr.d rd, (rs1) | rd = M[rs1][63:0]; 设置保留位(64 位) | 011 | 00010xx |
sc.w rd, rs2, (rs1) | 若保留位有效:M[rs1][31:0]=rs2[31:0], rd=0; 否则 rd=1 | 010 | 00011xx |
sc.d rd, rs2, (rs1) | 若保留位有效:M[rs1][63:0]=rs2, rd=0; 否则 rd=1 | 011 | 00011xx |
说明: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 += rs2 | 00000 |
amoswap.w/d rd, rs2, (rs1) | 原子交换:M = rs2 | 00001 |
amoor.w/d rd, rs2, (rs1) | 原子或:M |= rs2 | 00010 |
amoand.w/d rd, rs2, (rs1) | 原子与:M &= rs2 | 00011 |
amoxor.w/d rd, rs2, (rs1) | 原子异或:M ^= rs2 | 00100 |
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
| 指令 | 操作语义 | fmt | funct3 |
|---|---|---|---|
flw fd, imm(rs1) | fd = M[rs1+imm][31:0](单精度 load) | S | 010 |
fsw fs2, imm(rs1) | M[rs1+imm][31:0] = fs2[31:0](单精度 store) | S | 010 |
浮点算术运算(opcode=1010011,fmt=S)
| 指令 | 操作语义 | funct5 | 说明 |
|---|---|---|---|
fadd.s fd, fs1, fs2 | fd = fs1 + fs2 | 00000 | 单精度加法 |
fsub.s fd, fs1, fs2 | fd = fs1 - fs2 | 00001 | 单精度减法 |
fmul.s fd, fs1, fs2 | fd = fs1 * fs2 | 00010 | 单精度乘法 |
fdiv.s fd, fs1, fs2 | fd = fs1 / fs2 | 00011 | 单精度除法 |
fsqrt.s fd, fs1 | fd = sqrt(fs1) | 01011 | 单精度平方根(rs2=x0) |
fmin.s fd, fs1, fs2 | fd = min(fs1, fs2) | 00101 | 单精度最小值 |
fmax.s fd, fs1, fs2 | fd = max(fs1, fs2) | 00101 | 单精度最大值(funct3=001) |
fmadd.s fd, fs1, fs2, fs3 | fd = fs1 * fs2 + fs3 | — | 融合乘加(opcode=1000011) |
fmsub.s fd, fs1, fs2, fs3 | fd = fs1 * fs2 - fs3 | — | 融合乘减(opcode=1000111) |
fnmsub.s fd, fs1, fs2, fs3 | fd = -fs1 * fs2 + fs3 | — | 负乘加(opcode=1001011) |
fnmadd.s fd, fs1, fs2, fs3 | fd = -fs1 * fs2 - fs3 | — | 负乘减(opcode=1001111) |
FMA 指令(fmadd/fmsub/fnmsub/fnmadd)为 R4-type(4 寄存器格式),opcode 不同于普通浮点运算。
浮点转换(opcode=1010011)
| 指令 | 操作语义 | 源 fmt | 目标 fmt | funct5 |
|---|---|---|---|---|
fcvt.w.s rd, fs1 | rd = sign_extend(int32_t(fs1)); 向零舍入 | S | W | 11000 |
fcvt.wu.s rd, fs1 | rd = sign_extend(uint32_t(fs1)); 向零舍入 | S | WU | 11000 |
fcvt.l.s rd, fs1 | rd = int64_t(fs1); 向零舍入 | S | L | 11000 |
fcvt.lu.s rd, fs1 | rd = uint64_t(fs1); 向零舍入 | S | LU | 11000 |
fcvt.s.w fd, rs1 | fd = float32(int32_t(rs1)) | W | S | 11010 |
fcvt.s.wu fd, rs1 | fd = float32(uint32_t(rs1)) | WU | S | 11010 |
fcvt.s.l fd, rs1 | fd = float32(int64_t(rs1)) | L | S | 11010 |
fcvt.s.lu fd, rs1 | fd = float32(uint64_t(rs1)) | LU | S | 11010 |
浮点比较(opcode=1010011,fmt=S)
| 指令 | 操作语义 | funct5 | funct3 |
|---|---|---|---|
fleq.s rd, fs1, fs2 | rd = (fs1 == fs2) ? 1 : 0 | 10100 | 010 |
fltq.s rd, fs1, fs2 | rd = (fs1 < fs2) ? 1 : 0 | 10100 | 001 |
fle.s rd, fs1, fs2 | rd = (fs1 <= fs2) ? 1 : 0 | 10100 | 000 |
浮点移动(opcode=1010011)
| 指令 | 操作语义 | funct5 | 说明 |
|---|---|---|---|
fsgnj.s fd, fs1, fs2 | fd = {fs2[31], fs1[30:0]}(符号注入) | 00100 | funct3=000 |
fsgnjn.s fd, fs1, fs2 | fd = {~fs2[31], fs1[30:0]}(负符号注入) | 00100 | funct3=001 |
fsgnjx.s fd, fs1, fs2 | fd = {fs1[31]^fs2[31], fs1[30:0]}(异或符号注入) | 00100 | funct3=010 |
fclass.s rd, fs1 | rd = 分类结果(10 类编码) | 11100 | funct3=001 |
fmv.x.w rd, fs1 | rd = sign_extend(fs1[31:0])(FP→整数) | 11100 | funct3=000 |
D 扩展:双精度浮点
D 扩展在 F 基础上增加双精度(64 位)指令。fmt=01(D)。包含所有 F 扩展指令的双精度版本。
浮点 Load/Store(双精度)
| 指令 | 操作语义 | fmt | funct3 |
|---|---|---|---|
fld fd, imm(rs1) | fd = M[rs1+imm][63:0](双精度 load) | D | 011 |
fsd fs2, imm(rs1) | M[rs1+imm][63:0] = fs2[63:0](双精度 store) | D | 011 |
浮点算术运算(fmt=D)
| 指令 | 操作语义 | funct5 |
|---|---|---|
fadd.d fd, fs1, fs2 | fd = fs1 + fs2(双精度) | 00000 |
fsub.d fd, fs1, fs2 | fd = fs1 - fs2(双精度) | 00001 |
fmul.d fd, fs1, fs2 | fd = fs1 * fs2(双精度) | 00010 |
fdiv.d fd, fs1, fs2 | fd = fs1 / fs2(双精度) | 00011 |
fsqrt.d fd, fs1 | fd = sqrt(fs1)(双精度) | 01011 |
fmin.d fd, fs1, fs2 | fd = min(fs1, fs2)(双精度) | 00101 |
fmax.d fd, fs1, fs2 | fd = max(fs1, fs2)(双精度) | 00101 |
fmadd.d fd, fs1, fs2, fs3 | fd = fs1 * fs2 + fs3(FMA) | — |
fmsub.d fd, fs1, fs2, fs3 | fd = fs1 * fs2 - fs3 | — |
fnmsub.d fd, fs1, fs2, fs3 | fd = -fs1 * fs2 + fs3 | — |
fnmadd.d fd, fs1, fs2, fs3 | fd = -fs1 * fs2 - fs3 | — |
浮点转换(D 扩展)
| 指令 | 操作语义 | 源 fmt | 目标 fmt | funct5 |
|---|---|---|---|---|
fcvt.d.s fd, fs1 | fd = float64(float32(fs1)) | S | D | 01000 |
fcvt.s.d fd, fs1 | fd = float32(float64(fs1)) | D | S | 01000 |
fcvt.w.d rd, fs1 | rd = sign_extend(int32_t(fs1)); 向零舍入 | D | W | 11000 |
fcvt.wu.d rd, fs1 | rd = sign_extend(uint32_t(fs1)); 向零舍入 | D | WU | 11000 |
fcvt.l.d rd, fs1 | rd = int64_t(fs1); 向零舍入 | D | L | 11000 |
fcvt.lu.d rd, fs1 | rd = uint64_t(fs1); 向零舍入 | D | LU | 11000 |
fcvt.d.w fd, rs1 | fd = float64(int32_t(rs1)) | W | D | 11010 |
fcvt.d.wu fd, rs1 | fd = float64(uint32_t(rs1)) | WU | D | 11010 |
fcvt.d.l fd, rs1 | fd = float64(int64_t(rs1)) | L | D | 11010 |
fcvt.d.lu fd, rs1 | fd = float64(uint64_t(rs1)) | LU | D | 11010 |
浮点比较与移动(fmt=D)
| 指令 | 操作语义 | fmt |
|---|---|---|
fleq.d rd, fs1, fs2 | rd = (fs1 == fs2) ? 1 : 0 | D |
fltq.d rd, fs1, fs2 | rd = (fs1 < fs2) ? 1 : 0 | D |
fle.d rd, fs1, fs2 | rd = (fs1 <= fs2) ? 1 : 0 | D |
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, fs1 | rd = fs1[63:0](FP→整数,64 位) | D |
浮点寄存器移动(跨类型)
| 指令 | 操作语义 | fmt |
|---|---|---|
fmv.w.x fd, rs1 | fd[31:0] = rs1[31:0]; fd[63:32]=1s(整数→SP) | S |
fmv.d.x fd, rs1 | fd = 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_00 | addi rd', sp, imm*4 |
c.fld rd', imm(rs1') | 双精度 load | 001_xxx_xxxxxxx_00 | fld rd', imm*8(rs1') |
c.lw rd', imm(rs1') | 32 位 load | 010_xxx_xxxxxxx_00 | lw rd', imm*4(rs1') |
c.ld rd', imm(rs1') | 64 位 load | 011_xxx_xxxxxxx_00 | ld rd', imm*8(rs1') |
c.fsd rs2', imm(rs1') | 双精度 store | 101_xxx_xxxxxxx_00 | fsd rs2', imm*8(rs1') |
c.sw rs2', imm(rs1') | 32 位 store | 110_xxx_xxxxxxx_00 | sw rs2', imm*4(rs1') |
c.sd rs2', imm(rs1') | 64 位 store | 111_xxx_xxxxxxx_00 | sd 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, imm | rd=rd+imm(rd≠x0,imm≠0) | addi rd, rd, imm |
c.addiw rd, imm | 32 位加法(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 imm | sp=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 位 store | sw rs2, imm(sp) |
c.sdsp rs2, imm(sp) | 64 位 store | sd rs2, imm(sp) |
压缩指令注意:寄存器编码有限(3 位或 5 位),立即数范围受限。压缩指令总是对应唯一的 32 位指令,由汇编器自动选择。编写汇编时直接使用 32 位伪指令或伪指令即可,汇编器会尽可能生成压缩编码以减小代码尺寸。
C 扩展寄存器编码
| 3 位编码 (rd'/rs') | 寄存器 | 说明 |
|---|---|---|
| 000 | x8 (s0) | C0/C1 中使用的 rd'/rs' 寄存器组 |
| 001 | x9 (s1) | |
| 010 | x10 (a0) | |
| 011 | x11 (a1) | |
| 100 | x12 (a2) | |
| 101 | x13 (a3) | |
| 110 | x14 (a4) | |
| 111 | x15 (a5) |
| 5 位编码 (rd/rs) | 可用的寄存器 |
|---|---|
| 5-bit | x0-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)。