- RV32I 指令格式
- 用于寄存器-寄存器操作的R类型指令
- 用于短立即数和访存load操作的I型指令
- 用于访存store操作的s型指令
- 用于条件跳转操作的B类型指令
- 用于长立即数的U型指令
- 用于无条件跳转的J型指令
特点:
- 所有指令都是32bits, 简化了指令解码;
- RISV-V指令提供3个寄存器操作数,这样的好处就是当一个操作需要3个操作数时,一条指令就可以完成,而不需要用其他的指令来辅助;
- 所有指令,要读写的寄存器标识符所在的位置是固定的,解码逻辑可以简化;
- 立即数总是符号位扩展的,符号位总是在指令中最高位。这意味着可能成为关键路径的立即数符号扩展,可以在指令解码之前进行;
寄存器个数:x0~x31, 其中x0固定为0;
RV32I 整数计算
- RISC-V中没有字节或半字宽度的整数计算操作。操作始终 是以完整的寄存器宽度。内存访问需要的能量比算术运算高几个数量级。因此低宽度的数 据访问可以节省大量的能量,但低宽度的运算不会。
- RV32I 也不包含乘法和除法,它们包含在可选的RV32M扩展中;
RV32I 的 Load和Store
- 除了提供32位字(lw,sw)的load和store外,RV32I 支持load有符号和无符号字节和半字(lb,lbu,lh,lhu)和store字节和半字(sb,sh)。有符号字节和半字符号扩展为32位再写入目的寄存器。
- 即使是自然数据类型更窄,低位宽数据也是被 扩展后再处理,这使得后续的整数计算指令能正确处理所有的32位。在文本和无符号整数 中常用的无符号字节和半字,在写入目标寄存器之前都被无符号扩展到32位。
- 虽然ARM-32和MIPS-32要求存储在内存中的数据,要按照数据的自然大小进行边界 对齐,但是RISC-V没有这个要求。
RV32I 条件分支
- RV32I 可以比较两个寄存器并根据比较结果上进行分支跳转。
- 比较可以是:相等 (beq),不相等 (bne),大于等于(bge),或小于(blt)。最后两种比较有符号比 较,RV32I也提供相应的无符号版本比较的:bgeu和bltu。
- RISC-V去掉了MIPS-32,Oracle SPARC等指令集中被 广为诟病的延迟分支特性等。
- 省略了x86-32中的循环指令:loop,loope,loopz,loopne, loopnz。
RV32I 无条件跳转
- 跳转并链接指令(jal)具有双重功能。
- 若将下一条指令PC + 4的地址保存 到目标寄存器中,通常是返回地址寄存器ra(见图2.4),便可以用它来实现过程调用。
- 如果使用零寄存器(x0)替换ra作为目标寄存器,则可以实现无条件跳转,因为x0不能 更改。
- RV32I避开了错综复杂的程序调用指令,例如x86-32的进入和离开 指令,或Intel Itanium,Oracle SPARC 和 Cadence Tensilica 中的寄存器窗口。
RV32I 杂项
- 控制状态寄存器指令 (csrrc、csrrs、csrrw、csrrci、csrrsi、csrrwi), 使我们可以轻松地访问一些程序性能计数器。
- ecall指令用于向运行时环境发出请求,例如系统调用。调试器 使用ebreak指令将控制转移到调试环境
- fence 指令对外部可见的访存请求,如设备I / O和内存访问等进行串行化。
- fence.i指令同步指令和数据 流。在执行fence.i指令之前,对于同一个硬件线程,RISC-V不保证用存储指令写到内存 指令区的数据可以被取指令取到。
对于RV32I总的特点为:
⚫ 32位字节可寻址的地址空间
⚫ 所有指令均为32位长
⚫ 31个寄存器,全部32位宽,寄存器0硬连线为零
⚫ 所有操作都在寄存器之间(没有寄存器到内存的操作)
⚫ 加载/存储字加上有符号和无符号加载/存储字节和半字
⚫ 所有算术,逻辑和移位指令都有立即数版本的指令
⚫ 立即数总是符号扩展
⚫ 仅提供一种数据寻址模式(寄存器+立即数)和PC相对分支
⚫ 无乘法或除法指令
⚫ 一个指令,用于将大立即数加载到寄存器的高位,这样加载32位常量到寄存器只需要两条指令
RV32I与ARM/MIPS/X86所具备的优势: