RISC_V基础指令集

        RV32I指令格式

用于寄存器—寄存器操作的R类型指令

用于短立即数和访存LOAD操作的I型指令

用于访存store操作的S型指令

用于条件跳转操作的B型指令

用于长立即数的U型指令

用于无条件跳转的J型指令

RISC_V实际上只有四种基本格式,分支指令B类型的立即数字段是在S类型的基础上调转了一位而来,而跳转指令J类型则是将直接字段在U类型的技术上调转了十二位而得来的

31                                    25 24                20 19                15 14        12 11                        7 6                0
imm[31:12]rd0110111U lui
imm[31:12]rd0010111U auipc
imm[20|10:1|11|19:12]rd1101111J jal
imm[11:0]rs1000rd1100111I jalr
imm[12|10:5]rs2rs1000imm[4:1|11]1100011B beq
imm[12|10:5]rs2rs1001imm[4:1|11]1100011B bne
imm[12|10:5]rs2rs1100imm[4:1|11]1100011B blt
imm[12|10:5]rs2rs1101imm[4:1|11]1100011B bge
imm[12|10:5]rs2rs1110imm[4:1|11]1100011B bltu
imm[12|10:5]rs2rs1111imm[4:1|11]1100011B bgeu
imm[11:0]rs1000rd0000011I lb
imm[11:0]rs1001rd0000011I lh
imm[11:0]rs1010rd0000011I lw
imm[11:0]rs1100rd0000011I lbu
imm[11:0]rs1101rd0000011I lhu
imm[11:5]rs2rs1000imm[4:0]0100011S sb
imm[11:5]rs2rs1001imm[4:0]0100011S sh
imm[11:5]rs2rs1010imm[4:0]0100011S sw
imm[11:0]rs1000rd0010011I addi
imm[11:0]rs1010rd0010011I slti
imm[11:0]rs1011rd0010011I sltiu
imm[11:0]rs1100rd0010011I xori
imm[11:0]rs1110rd0010011I ori
imm[11:0]rs1111rd0010011I andi
0000000shamtrs1001rd0010011I slli
0000000shamtrs1101rd0010011I srli
0100000shamtrs1101rd0010011I srai
0000000rs2rs1000rd0110011R add
0100000rs2rs1000rd0110011R sub
0000000rs2rs1001rd0110011R sll
0000000rs2rs1010rd0110011R slt
0000000rs2rs1011rd0110011Rsltu
0000000rs2rs1100rd0110011R xor
0000000rs2rs1101rd0110011R srl
0100000rs2rs1101rd0110011R sra
0000000rs2rs1110rd0110011R or
0000000rs2rs1111rd0110011R and
0000predsucc00000000000000001111I fence
00000000000000000001000000001111I fence.i
0000000000000000000000001110011I ecall
00000000000000000000000001110011I ebreak
csrrs1001rd1110011I csrrw
csrrs1010rd1110011I csrrs
csrrs1011rd1110011I csrrc
csrzimm101rd1110011I csrrwi
csrzimm110rd1110011I cssrrsi
csrzimm111rd1110011I csrrci

表 2.3:RV32I带有指令布局,操作码格式类型和名称 有指令布局,操作码格式类型和名称 有指令布局,操作码格式类型和名称 有指令布局,操作码格式类型和名称 有指令布局,操作码格式类型和名称 有指令布局,操作码格式类型和名称 的操作码映射。(此图 基于 [Waterman and Asanovi'c 2017]的表 19.2。)

RV32I寄存器与整数计算

简单的算术指令(add, sub)、逻辑指令(and, or, xor)以及移位指令(sll, srl, sra)和其他ISA差不多。他们从寄存器读取两个32位的值,并将32位结果写入目标寄存器。RV32I还提供了这些指令的立即数版本,RV32I的立即数会进行符号扩展,如果需要,可以用立即数表示负数

程序可以根据比较结果生成布尔值。为应对这种使用场景下,RV32I提供一个当小于时置位的指令。如果第一个操作数小于第二个操作数,它将目标寄存器设置为1,否则为0。不出所料,对这个指令,有一个有符号版本(slt)和无符号版本(sltu),分别用于处理有符号和无符号整数比较。相应的,上述两条指令也有立即数版本的(slti,sltiu)。正如我们将要看到的,虽然RV32I分支指令可以检查两个寄存器之间的所有关系,但一些条件表达式涉及多对寄存器之间的关系。对于这些表达式,编译器或汇编语言程序员可以将slt以及与或异或等逻辑指令组合使用来解决更复杂的条件表达式。

剩下的两条整数计算指令主要用于构造大的常量数值和链接。加载立即数到高位(lui)将20位常量加载到寄存器的高20位。接着便可以使用标准的立即指令来创建32位常量。这样子,仅使用2条32位RV32I指令,便可构造一个32位常量。向PC高位加上立即数(auipc)让我们仅用两条指令,便可以基于当前PC以任意偏移量转移控制流或者访问数据。将auipc中的20位立即数与jalr(参见下面)中12位立即数的组合,我们可以将执行流转移到任何32位PC相对地址。而auipc加上普通加载或存储指令中的12位立即数偏移量,使我们可以访问任何32位PC相对地址的数据。

RV32I的寄存器

RV32I的Load和Store

除了提供32位字(lw,sw)的加载和存储外,图2.1中说明,RV32I 支持加载有符号和无符号字节和半字(lb,lbu,lh,lhu)和存储字节和半字(sb,sh)。有符号字节和半字符号扩展为32位再写入目的寄存器。即使是自然数据类型更窄,低位宽数据也是被扩展后再处理,这使得后续的整数计算指令能正确处理所有的32位。在文本和无符号整数中常用的无符号字节和半字,在写入目标寄存器之前都被无符号扩展到32位。 加载和存储的支持的唯一寻址模式是符号扩展12位立即数到基地址寄存器,RISC-V没有特殊的堆栈指令。将31个寄存器中的某一个作为堆栈指针,标准寻址模式使用起来和压栈(push)和出栈(pop)类似,并且不增加ISA的复杂性。RISC-V不支持延迟加载(delayed load)。

RV32I条件分支

RV32I可以比较两个寄存器并根据比较结果上进行分支跳转。比较可以是:相等(beq),不相等 (bne),大于等于(bge),或小于(blt)。最后两种比较有符号比较,RV32I也提供相应的无符号版本比较的:bgeu和bltu。剩下的两个比较关系(大于和小于等于)可以通过简单地交换两个操作数,即可完成比较。因为x < y表示y > x且x ≥ y表示y ≤ x。 由于RISC-V指令长度必须是两个字节的倍数——关于可选的双字节指令 ,分支指令的寻址方式是12位的立即数乘以2,符号扩展它,然后将得到值加到PC上作为分支的跳转地址。

补充说明:不使用条件码实现大位宽数据的加法

在 RV32I中是通过 中是通过 sltu计算进位来实现的: 计算进位来实现的:
add a0,a2,a4 # 加低 32 位: a0 = a2 + a4
sltu a2,a0,a2 # 若 (a2+a4) < a2那么 a2’ = 1, 否则 a2’ = 0
add a5,a3,a5 # 加高 32位: a5 = a3 + a5
add a1,a2,a5 # 加上低 32位的进位

补充说明:获取 PC
当前的 PC可以通过将 auipc的 U立即数字段设置为 0来获得。对于 来获得。对于 来获得。对于 x86-32,要想读取 ,要想读取 PC, 你需要先进行函数调用,(这样子可以将 你需要先进行函数调用,(这样子可以将 你需要先进行函数调用,(这样子可以将 PC推入堆栈) ;然后被调用的函数可以从堆栈中读 取刚被压栈的 PC,最后将 PC值返回给调用者(需要再弹出堆栈)。因此,或许当前的 值返回给调用者(需要再弹出堆栈)。因此,或许当前的 PC至少需要 1个 store,2个 load和 2个跳转

补充说明: 软件检查溢出
大部分(但不是所有)程序都忽略整数算术溢出,因此 大部分(但不是所有)程序都忽略整数算术溢出,因此 大部分(但不是所有)程序都忽略整数算术溢出,因此 大部分(但不是所有)程序都忽略整数算术溢出,因此 大部分(但不是所有)程序都忽略整数算术溢出,因此 RISCRISCRISCRISC-V依赖于软件溢出检查 。依赖于软件溢出检查 。无符号加法的溢出只需要在指令 后添一个额外分支:addu t0,t1,t2; bltu t0, t1,overflow。

对于带符号的加法,如果已知一个操作数则溢出检查只需要在后添条分支 对于带符号的加法,如果已知一个操作数则溢出检查只需要在后添条分支 对于带符号的加法,如果已知一个操作数则溢出检查只需要在后添条分支 指令: addi t0,t1,+ imm; blt t0,t1,overflow。

这覆盖了常见的加立即数情况。对于一般带符号法,我们需要在指令后添三个 这覆盖了常见的加立即数情况。对于一般带符号法,我们需要在指令后添三个 这覆盖了常见的加立即数情况。对于一般带符号法,我们需要在指令后添三个 这覆盖了常见的加立即数情况。对于一般带符号法,我们需要在指令后添三个 附加指令,当且仅一个操作数为负时结果才能小于另否则就是溢出。
add t0, t1, t2
slti t3, t2, 0 # t3 = (t2<0)
slt t4, t0, t1 # t4 = (t1+t2<t1)
bne t3, t4, overflow # 若 (t2<0) && (t1+t2>=t1)
# || (t2>=0) && (t1+t2<t1)则为溢出

RV32I无条件跳转

跳转并链接指令(jal)具有双重功能。若将下一条指令PC + 4的地址保存到目标寄存器中,通常是返回地址寄存器ra(见上表),便可以用它来实现过程调用。如果使用零寄存器(x0)替换ra作为目标寄存器,则可以实现无条件跳转,因为x0不能更改。像分支一样,jal将其20位分支地址乘以2,进行符号扩展后再添加到PC上,便得到了跳转地址。 跳转和链接指令的寄存器版本(jalr)同样是多用途的。它可以调用地址是动态计算出来的函数,或者也可以实现调用返回(只需ra作为源寄存器,零寄存器(x0)作为目的寄存器)。Switch和case语句的地址跳转,也可以使用jalr指令,目的寄存器设为x0。

RV32I杂项

控制状态寄存器指令 (csrrc、csrrs、csrrw、csrrci、csrrsi、csrrwi),使我们可以轻松地访问一些程序性能计数器。对于这些64位计数器, 我们一次可以读取32位。这些计数器包括了系统时间, 时钟周期以及执行的指令数目。

在RISC-V指令集中,ecall指令用于向运行时环境发出请求,例如系统调用。调试器使用ebreak指令将控制转移到调试环境。

fence指令对外部可见的访存请求,如设备I / O和内存访问等进行串行化。外部可见指对处理器的其他核心、线程,外部设备或协处理器可见。fence.i指令同步指令和数据流。在执行fence.i指令之前,对于同一个硬件线程,RISC-V不保证用存储指令写到内存指令区的数据可以被取指令取到。

RISC-V使用内存映射I / O,不需要inout等指令来进行I/O状态控制,为支持字符串处理,RISC-V还可以进行字节存取

那里,继承了如下这些特性: 那里,继承了如下这些特性: 那里,继承了如下这些特性: 那里,继承了如下这些特性: 那里,继承了如下这些特性:

 ⚫ 32位字节可寻址的地址空间 

⚫ 所有指令均为 32位长

⚫ 31个寄存器,全部 32位宽,寄存器 0硬连线为零 

⚫ 所有操作都在寄存器之间(没有寄存器到内存的操作 )

⚫ 加载 /存储字加上有符号和无符号加载、存储字节和半字

⚫ 所有算术,逻辑和移位指令都有立即数版本

⚫ 立即数总是符号扩展

⚫ 仅提供一种数据寻址模式(寄存器 +立即数)和 PC相对分支

⚫ 无乘法或除法指令 

⚫ 一个指令,用于将大立即数加载到寄存器的高位,这样加载32位常量到寄存器只需要两条指令

  • 15
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值