0 概述

RV32C是RISC-V架构中的一种指令集,其设计目标是提供高效的指令压缩技术,同时保持RISC-V架构的简洁和灵活性。它是RISC-V架构中的一个重要的扩展,为嵌入式系统和低功耗设备提供了方便和支持。基于32位寄存器的RISC-V架构,同时增加了压缩指令集(C),可以将32位指令压缩为16位或更短的指令,从而减少指令存储和传输的开销,提高指令的缓存效率,同时降低功耗和成本。

RV32C指令集包含了一些常用的指令,如算术、逻辑、数据传输、分支和跳转等指令。尽管这些指令可以被压缩成16位或更短的指令,但是其功能与32位指令相同。此外外,还提供了一些特殊的压缩寄存器,用于存储压缩指令的结果。

总的来说,RV32C是RISC-V架构中的一种扩展,它为程序员提供了一些常用指令的压缩形式,可以减少指令存储和传输的开销,提高指令的缓存效率,同时也能够降低功耗和成本。

1 RV32C指令集概述

相比于ARM和MIPS中为了缩小代码而从心设计指令集来说,RV32C采用了一种新颖的办法:每条短指令必须和一条标准的32位RISC-V指令一一对应。此外,16位指令只对汇编器和链接器可见,是否以短指令取代对应的宽指令有它们自己觉决定,这对弈编译器编写者和汇编语言程序原始很幸福的。基于对程序的观察发现:

  • 对十个常用寄存器(a0-a5,s0-s1,sp和ra)的访问频率要远超其他寄存器;
  • 许多指令的写入目标是它们的源操作数之一;
  • 立即数往往很小。

RV32C的指令集可以表述为:

2 RV32C指令集详解

2.1 加载/存储指令

2.1.1 C.LWSP指令(c.lwsp rd,uimm(x2))

x[rd] = sext(M[x[2] + uimm][31:0])
  • 栈指针相关字加载(Load Word, Stack-Pointer Relative),扩展形式为lw rd,uimm(x2),rd=x0时非法。

2.1.2 C.SWSP指令(c.swsp rs2,uimm(x2))

M[x[2] + uimm][31:0] = x[rs2]
  • 栈指针相关字存储(Store Word, Stack-Pointer Relative),扩展形式为sw rs2,uimm(x2)。

2.1.3 C.LW指令(c.lw rd‘’,uimm(rs1′))

x[8+rd’] = sext(M[x[8+rs1’] + uimm][31:0])
  • 字加载(Load Word),扩展形式为lw rd,uimm(rs1),其中rd=8+rd’,rs1=8+rs1′

2.1.4 C.SW指令(c.sw rs2′,uimm(rs1′))

M[x[8+rs1’] + uimm][31:0] = x[8+rs2’]
  • 字存储(Store Word),扩展形式为sw rs2,uimm(rs1),其中rs2=8+rs2’,rs1=8+rs1’。

2.2 跳转指令

2.2.1 C.J指令(c.j offset)

pc += sext(offset)
  • 跳转(Jump),扩展形式为jal x0,offset

2.2.2 C.JAL指令(c.jal offset)

x[1] = pc+2; pc += sext(offset)
  • 链接跳转(Jump and Link),扩展形式为jal x1,offset

2.2.3 C.JALR指令(c.jalr rs1)

t = pc+2; pc = x[rs1]; x[1] = t
  • 寄存器链接跳转(Jump and Link Register),扩展形式为jalr x1,0(rs1),当rs1=x0时非法。

2.3 判断分支指令

2.3.1 C.BEQZ指令(c.beqz rs1′,offset)

if (x[8+rs1’] == 0) pc += sext(offset)
  • 等于零时分支(Branch if Equal to Zero),扩展形式为beq rs1,x0,offset,其中rs1=8+rs1’。

2.3.2 C.BNEZ指令(c.bnez rs1′,offset)

if (x[8+rs1’] ≠ 0) pc += sext(offset)
  • 不等于零时分支(Branch if Not Equal to Zero),扩展形式为bne rs1,x0,ofset,其中rs1=8+rs1’。

2.4 算数指令

2.4.1 C.LI指令(c.li rd,imm)

x[rd] = sext(imm)
  • 立即数加载(Load Immediate),扩展形式为addi rd,x0,imm。

2.4.2 C.LUI指令(c.lui rd,imm)

x[rd] = sext(imm[17:12] << 12)
  • 高位立即数加载(Load Upper Immediate),扩展形式为lui rd,imm,当rd=x2或imm=0时非法

2.4.3 C.ADDI指令(c.addi rd,imm)

x[rd] = x[rd] + sext(imm)
  • 加立即数(Add Immediate),扩展形式为addi rd,rd,imm

2.4.4 C.ADDI16SP指令(c.addi16sp imm)

x[2] = x[2] + sext(imm)
  • 加16倍立即数到栈指针(Add Immediate, Scaled by 16, to Stack Pointer),扩展形式为addi x2,x2,imm,imm=0时非法。

2.4.5 C.ADDI4SPN指令(c.addi4spn rd’,uimm)

x[8+rd’] = x[2] + uimm
  • 加4倍立即数到栈指针(Add Immediate, Scaled by 4, to Stack Pointer, Nondestructive),扩展形式为addi rd,x2,uimm,其中rd=8+rd’。uimm=0时非法。

2.4.6 C.SLLI指令(c.slli rd,uimm)

x[rd] = x[rd] << uimm
  • 立即数逻辑左移(Shift Left Logical Immediate),扩展形式为slli rd,rd,uimm。

2.4.7 C.SRLI指令(c.srli rd’,uimm)

x[8+rd’] = x[8+rd’] >>u uimm
  • 立即数逻辑右移(Shift Right Logical Immediate),扩展形式为srli rd,rd,uimm,其中rd=8+rd’。

2.4.8 C.SRAI指令(srai rd’,uimm)

x[8+rd’] = x[8+rd’] >>s uimm
  • 立即数算数右移(Shift Right Arithmetic Immediate),扩展形式为srai rd,rd,uimm,其中rd=8+rd’。

2.4.9 C.ANDI指令(c.andi rd’,imm)

x[8+rd’] = x[8+rd’] & sext(imm)
  • 与立即数(AND Immediate),扩展形式为andi rd,rd,imm,其中rd=8+rd’。

2.4.10 C.MV指令(c.mv rd,rs2)

x[rd] = x[rs2]
  • 移动(Move),扩展形式为add,rd,x0,rs2,rs2=0时非法。

2.4.11 C.ADD指令(c.add rd,rs2)

x[rd] = x[rd] + x[rs2]
  • 加(Add),扩展形式为add rd,rd,rs2。rd=x0或rs2=x0时非法。

2.4.12 C.AND指令(c.and rd’.rs2’)

x[8+rd’] = x[8+rd’] & x[8+rs2’]
  • 与(AND),扩展形式为and rd,rd,rs2,其中rd=8+rd’,rs2=8+rs2’。

2.4.13 C.OR指令(c.or rd’,rs2’)

x[8+rd’] = x[8+rd’] | x[8+rs2’]
  • 或(OR),扩展形式为or rd,rd,rs2,其中rd=8+rd’,rs2=8+rs2’。

2.4.14 C.XOR指令(c.xor rd’,rs2’)

x[8+rd’] = x[8+rd’] ^ x[8+rs2’]
  • 异或(Exclusive-OR),扩展形式为xor rd,rd,rs2,其中rd=8+rd’,rs2=8+rs2’。

2.4.15 C.SUB指令(c.sub rd’,rs2’)

x[8+rd’] = x[8+rd’] - x[8+rs2’]
  • 扩展形式为sub rd,rd,rs2,其中rd=8+rd’,rs2=8+rs2’。

2.5 系统指令

2.5.1C.EBREAK指令(c.ebreak)

RaiseException(Breakpoint)
  • 环境断点(Environment Breakpoint),扩展形式为ebreak。