RISC-V ISA

· 1184字 · 3分钟

RISC-V ISA 🔗

RV32I 特性 🔗

  • 32 位字节可寻址的地址空间
  • 所有指令均为 32 位长
  • 31 个寄存器,全部 32 位宽,寄存器 0 硬连线为零
  • 所有操作都在寄存器之间(没有寄存器到内存的操作)
  • 加载/存储字加上有符号和无符号加载/存储字节和半字
  • 所有算术,逻辑和移位指令都有立即数版本的指令
  • 立即数总是符号扩展
  • 仅提供一种数据寻址模式(寄存器+立即数)和 PC 相对分支
  • 无乘法或除法指令
  • 一个指令,用于将大立即数加载到寄存器的高位,这样加载 32 位常量到寄存器只需要两条指令

RV32I 寄存器 🔗

x0 / zero

x1 / ra

x2 / sp

x3 / gp

x4 / tp

x5 / t0

x6 / t1

x7 / t2

x8 / s0 / fp

x9 / s1

x10 / a0

x11 / a1

x12 / a2

x13 / a3

x14 / a4

x15 / a5

x16 / a6

x17 / a7

x18 / s2

x19 / s3

x20 / s4

x21 / s5

x22 / s6

x23 / s7

x24 / s8

x25 / s9

x26 / s10

x27 / s11

x28 / t3

x29 / t4

x30 / t5

x31 / t6

pc

RV32I 指令 - 整数运算 🔗

add rd,rs1,rs2 🔗

addi rd,rs1,imm 🔗

  • nop = addi zero,zero,0

  • mv rd,rs = addi rd,rs,0

  • li rd,IMMEDIATE

sub rd,rs1,rs2 🔗

  • neg rd,rs = sub rd,x0,rs

and rd,rs1,rs2 🔗

andi rd,rs1,imm 🔗

or rd,rs1,rs2 🔗

ori rd,rs1,imm 🔗

xor rd,rs1,rs2 🔗

xori rd,rs1,imm 🔗

  • not rd,rs = xori rd,rs,-1

sll rd,rs1,rs2 🔗

slli rd,rs1,imm 🔗

sra rd,rs1,rs2 🔗

srai rd,rs1,imm 🔗

srl rd,rs1,rs2 🔗

srli rd,rs1,imm 🔗

lui rd,immu 🔗

auipc rd,immu 🔗

RV32I 指令 - 比较 🔗

slt rd,rs1,rs2 🔗

  • sltz rd,rs = slt rd,rs,zero

  • sgtz rd,rs = slt rd,zero,rs

slti rd,rs1,imm 🔗

sltu rd,rs1,rs2 🔗

  • snez rd,rs = sltu rd,x0,rs

sltiu rd,rs1,imm 🔗

  • seqz rd,rs = sltiu rd,rs,1

RV32I 指令 - 控制转移 🔗

beq rs1,rs2,imm 🔗

  • beqz rs,imm = beq rs,zero,imm

bne rs1,rs2,imm 🔗

  • bnez rs,imm = bne rs,zero,imm

bge rs1,rs2,imm 🔗

  • blez rs,imm = bge zero,rs,imm

  • bgez rs,imm = bge rs,zero,imm

  • ble rs1,rs2,imm = bge rs2,rs1,imm

bgeu rs1,rs2,imm 🔗

  • bleu rs1,rs2,imm = bgeu rs2,rs1,imm

blt rs1,rs2,imm 🔗

  • bltz rs,imm = blt rs,zero,imm

  • bgtz rs,imm = blt zero,rs,imm

  • bgt rs1,rs2,imm = blt rs2,rs1,imm

bltu rs1,rs2,imm 🔗

  • bgtu rs1,rs2,imm = bltu rs2,rs1,imm

jal rd,immu 🔗

  • j immu = jal zero,immu

  • jal immu = jal ra,immu

jalr rd,rs1,immu 🔗

  • jr rs = jalr zero,rs,0

  • ret = jalr zero,ra,0

  • tail {immu,imm} = auipc t1,immu & jalr zero,t1,imm

  • jalr rs = jalr ra,rs,0

  • call {immu,imm} = auipc ra,immu & jalr ra,ra,imm

RV32I 指令 - 加载与存储 🔗

lb rd,rs1,imm 🔗

lbu rd,rs1,imm 🔗

lh rd,rs1,imm 🔗

lhu rd,rs1,imm 🔗

lw rd,rs1,imm 🔗

sb rs1,rs2,imm 🔗

sh rs1,rs2,imm 🔗

sw rs1,rs2,imm 🔗

  • lla rd,SYMBOL

  • la rd,SYMBOL

  • lb/lh/lw rd,SYMBOL

  • sb/sh/sw rd,SYMBOL

RV32I 指令 - 杂项 🔗

fence pred{iorw},succ{iorw} 🔗

  • fence = fence iorw,iorw

fence.i 🔗

ebreak 🔗

ecall 🔗

csrrc rd,csr,rs1 🔗

csrrci rd,csr,imm 🔗

csrrs rd,csr,rs1 🔗

csrrsi rd,csr,imm 🔗

csrrw rd,csr,rs1 🔗

csrrwi rd,csr,imm 🔗

RISC-V 函数调用规范 🔗

函数调用过程通常分为 6 个阶段[Patterson and Hennessy 2017]。

  1. 将参数存储到函数能够访问到的位置;
  2. 跳转到函数开始位置(使用 RV32I 的 jal 指令);
  3. 获取函数需要的局部存储资源,按需保存寄存器;
  4. 执行函数中的指令;
  5. 将返回值存储到调用者能够访问到的位置,恢复寄存器,释放局部存储资源;
  6. 返回调用函数的位置(使用 ret 指令)。

函数调用中需要保证:

  • 函数参数位于a0-7
  • sp,s0-11,fs0-11调用前后保持不变
  • 虽然不需要ra保持不变,但函数需要保存它,否则无法返回
  • 返回值位于a0-1

RV32M 整数乘法和除法扩展 🔗

mul rd,rs1,rs2 🔗

mulh rd,rs1,rs2 🔗

mulhu rd,rs1,rs2 🔗

mulhsu rd,rs1,rs2 🔗

div rd,rs1,rs2 🔗

divu rd,rs1,rs2 🔗

rem rd,rs1,rs2 🔗

remu rd,rs1,rs2 🔗

RV64I 相比 RV32I 增加的指令 🔗

addw 🔗

addiw 🔗

subw 🔗

sllw 🔗

slliw 🔗

sraw 🔗

sraiw 🔗

srlw 🔗

srliw 🔗

ld 🔗

sd 🔗

lwu 🔗

RV64M 相比 RV32M 增加的指令 🔗

mulw 🔗

divw 🔗

divuw 🔗

remw 🔗

remuw 🔗

RV32/64 特权指令 🔗

mret 🔗

sret 🔗

sfence.vma 🔗

wfi 🔗