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]。
- 将参数存储到函数能够访问到的位置;
- 跳转到函数开始位置(使用 RV32I 的 jal 指令);
- 获取函数需要的局部存储资源,按需保存寄存器;
- 执行函数中的指令;
- 将返回值存储到调用者能够访问到的位置,恢复寄存器,释放局部存储资源;
- 返回调用函数的位置(使用 ret 指令)。
函数调用中需要保证:
- 函数参数位于
a0-7
sp
,s0-11
,fs0-11
调用前后保持不变- 虽然不需要
ra
保持不变,但函数需要保存它,否则无法返回 - 返回值位于
a0-1