RV32I指令集

      RV32I是最基本的32位Base指令集,它支持32位寻址空间,支持字节地址访问,仅支持小端格式(little-endian,高地址高位,低地址地位),寄存器也是32位整数寄存器。RV32I指令集的目的是尽量简化硬件的实施设计,所以它只有47条指令。

      在RV32I指令集架构中,包括32个通用目的寄存器,其中x0被预留为常数0,其它31个寄存器(x1-x31)是普通的通用整数寄存器。在Risc-V汇编语言中,每个通用寄存器都有一个对应的ABI名字,也就是说在汇编语言中,x1等价于ra,它们都会编译成相同的机器码。

      在Risc-V架构中,要得到当前指令pc(指令在存储器中的位置,instruction program counter),可以通过AUIPC指令,把它读入到一个通用寄存器中。

寄存器ABI名字(别名)注释Saver
x0 zeroHard-wired zero,常数0 
x1raReturn addresscaller,调用函数的指令pc
x2spStack pointercallee,被调用的函数指令pc
x3gpGlobal pointer 
x4tpThread pointer 
x5t0Temporary/alternate link registercaller
x6t1Temporariescaller
x7t2Temporariescaller
x8s0/fpSaved register/frame pointercaller
x9s1Saved registercaller
x10a0Function arguments/return valuescaller
x11a1Function arguments/return valuescaller
x12a2Function argumentscaller
x13a3Function argumentscaller
x14a4Function argumentscaller
x15a5Function argumentscaller
x16a6Function argumentscaller
x17a7Function argumentscaller
x18s2Saved registerscaller
x19s3Saved registerscaller
x20s4Saved registerscaller
x21s5Saved registerscaller
x22s6Saved registerscaller
x23s7Saved registerscaller
x24s8Saved registerscaller
x25s9Saved registerscaller
x26s10Saved registerscaller
x27s11Saved registerscaller
x28t3Temporariescaller
x29t4Temporariescaller
x30t5Temporariescaller
x31t6Temporariescaller

Base指令格式:

      RV32I指令格式包括以下6种,每种指令格式都是固定的32位指令,所以指令在内存中必须4字节对齐,否则将触发异常。其中rd表示目的寄存器,rs1是源操作数寄存器1,rs2是源操作数寄存器2。

image

imm表示指令中的立即数,比如imm[11:0],表示一个12位的立即数,它的高20位会符号位扩展,imm[31:12]表示一个32位的立即数,它的低12位会补0。

下图是各种指令格式扩展后的32位立即数。

image

RV32I整数指令集

RV32I整数指令集分为几个种类:

1.Load和store指令

CategoryFmtRV32I basemachine code(bin)comment
Loadsload byteIlb rd, rs1, imm[31-20,imm][19-15,rs1]000[11-7,rd]0000011rd=mem[rs1+imm], 8bit数据符号位扩展后返回rd
load half wordIlh rd, rs1, imm[31-20,imm][19-15,rs1]001[11-7,rd]0000011rd=mem[rs1+imm],16bit数据符号扩展后返回rd,应该保证地址对齐,否则产生异常
load wordIlw rd, rs1, imm[31-20,imm][19-15,rs1]010[11-7,rd]0000011rd=mem[rs1+imm],32bit数据返回rd,应该保证地址对齐,否则产生异常
load byte unsingedIlbu rd, rs1, imm[31-20,imm][19-15,rs1]100[11-7,rd]0000011rd=mem[rs1+imm], 8bit数据高位补0后返回rd
load half unsingedIlhu rd, rs1, imm[31-20,imm][19-15,rs1]101[11-7,rd]0000011rd=mem[rs1+imm], 16bit数据高位补0后返回rd

storesstore byteSsb rs1, rs2, imm[31-25,imm[11-5]][24-20,rs2,][19-15,rs1]000[11-7,imm[4-0]]0100011mem[rs1+imm]=rs2的低8bit数据
store half wordSsh rs1, rs2, imm[31-25,imm[11-5]][24-20,rs2,][19-15,rs1]001[11-7,imm[4-0]]0100011mem[rs1+imm]=rs2的低16bit数据
store wordSsw rs1, rs2, imm[31-25,imm[11-5]][24-20,rs2,][19-15,rs1]010[11-7,imm[4-0]]0100011mem[rs1+imm]=rs2的32bit数据

      RV32I是一个load /store架构,所有的memory访问都是通过load/store指令,其它指令都是在寄存器之间进行运算,比如加法指令,减法指令等等。注意,装入目的寄存器如果为x0,将会产生一个异常。Load/Store指令在memory和寄存器之间传输数据,Load指令编码为I型,store指令编码为S型。计算memory地址时候,imm都会符号扩展成32位,然后和rs1相加,得到memory地址。为了提高性能,load/store指令应该尽量对齐地址,比如lw指令,应该4字节对齐访问地址,lh应该双字节对齐访问地址。根据微架构实现的不同,不对齐地址的访问可能会比较慢,而且地址对齐访问,能够确保是原子操作,不对齐的话为了读取和存储数据正确,还有进行额外的同步操作。

image

2.整数计算指令(算术,逻辑指令,比较指令以及移位指令)

CategoryFmtRV32I basemachine code(bin)comment

arithmetricaddRadd rd, rs1, rs20000000[24-20,rs2][19-15,rs1]000[11-7,rd]0110011rd=rs1+rs2,如果溢出,舍弃高位,保留低32bit
add immediateIaddi rd, rs1, imm[31-20,imm][19-15,rs1]000[11-7,rd]0010011rd=rs1+imm,12bit立即数会符号位扩展,结果写回rd时如果溢出,则舍弃高位,保留低32bit
subtractRsub rd, rs1, rs20100000[24-20,rs2][19-15,rs1]000[11-7,rd]0110011rd=rs1-rs2,如果溢出,舍弃高位,保留低32bit
load upper immUlui rd, imm[31-12,imm][11-7,rd]0110111load imm to  high 20 bits of rd, and place 0 in low 12 bits
add upper imm to PCUauipc rd, imm[31-12,imm][11-7,rd]0010111pc=pc+high 20 bits imm&low 12 bits 0, then result save to rd.
logicalxorRxor rd, rs1, rs20000000[24-20,rs2][19-15,rs1]100[11-7,rd]0110011rd=rs1^rs2, bitwise operation
xor immediateIxori rd, rs1, imm[31-20,imm][19-15,rs1]100[11-7,rd]0010011rd=rs1^imm, i符号扩展12bit数imm,结果放在rd。
orRor rd, rs1, rs20000000[24-20,rs2][19-15,rs1]110[11-7,rd]0110011rd=rs1|rs2, bitwise operation
or immediateIori rd, rs1, imm[31-20,imm][19-15,rs1]110[11-7,rd]0010011rd=rs1|imm,  符号扩展12bit数imm,结果放在rd。
andRand rd, rs1, rs20000000[24-20,rs2][19-15,rs1]111[11-7,rd]0110011rd=rs1&rs2, bitwise operation
and immediateIandi rd, rs1, imm[31-20,imm][19-15,rs1]111[11-7,rd]0010011rd=rs1&imm, i符号扩展12bit数imm,结果放在rd。

shiftsshift leftRSLL rd, rs1, rs20000000[24-20,rs2][19-15,rs1]001[11-7,rd]0110011rd=rs1<<rs2,rs1左移值为rs2的低5bit,低位补0
shift left immediateISLLI rd, rs1, shamt0000000[24-20,imm][19-15,rs1]001[11-7,rd]0010011rd=rs1<<shamt,rs1移动5bit立即数,低位补0
shift rightRSRL rd, rs1, rs20000000[24-20,rs2][19-15,rs1]101[11-7,rd]0110011rd=rs1>>rs2,高位补0,右移值为rs2中的低5位
shift right immediateISRLI rd, rs1, shamt0000000[24-20,imm][19-15,rs1]101[11-7,rd]0010011rd=r1>>shamt,高位补0,右移值为5bit立即数
shift right arithmetircRSRA rd, rs1, rs20100000[24-20,rs2][19-15,rs1]101[11-7,rd]0110011rd=rs1>>rs2,高位补符号位,右移值为rs2中的低5位
shift right arith immISRAI rd, rs1, shamt0100000[24-20,imm][19-15,rs1]101[11-7,rd]0010011右移时,右边补符号位

compareset < Rslt rd, rs1, rs20000000[24-20,rs2][19-15,rs1]010[11-7,rd]0110011if rs1< rs2, write 1 to rd, 有符号数比较
set < immediate Islti rd, rs1, imm[31-20,imm][19-15,rs1]010[11-7,rd]0010011if rs1<imm, write 1 to rd,imm会符号位扩展,所以进行有符号数比较
set < unsignedRsltu rd, rs1, rs20000000[24-20,rs2][19-15,rs1]011[11-7,rd]0110011if rs1< rs2, write 1 to rd, 无符号数比较
set < imm unsignedIsltiu rd, rs1, imm[31-20,imm][19-15,rs1]011[11-7,rd]0010011if rs1<imm, write 1 to rd,imm会符号位扩展,所以进行有符号数比较

      计算指令在寄存器和寄存器之间,或者在寄存器和立即数之间进行算术或逻辑运算。指令格式为I,R或者U型。整数计算指令不会产生异常。我们能够通过ADDI x0, x0, 0来模拟NOP指令,该指令除了改变pc值外,不会改变其它任何用户状态。


image

image

3. 控制指令,包括无条件跳转指令和条件跳转指令

CategoryFmtRV32I basemachine code(bin)comment
branchbranch =SBbeq  rs1, rs2,imm[31-25, imm[12][10:5]][24-20, rs2][19-15, rs1]000[11-7, imm[4:1][11]]1100011if(rs1==rs2) pc=pc+imm*2,跳转指令
branch <>SBbne  rs1, rs2,imm[31-25, imm[12][10:5]][24-20, rs2][19-15, rs1]001[11-7, imm[4:1][11]]1100011if(rs1!=rs2) pc=pc+imm*2,跳转指令
branch <SBblt  rs1, rs2,imm[31-25, imm[12][10:5]][24-20, rs2][19-15, rs1]100[11-7, imm[4:1][11]]1100011if(rs1<rs2) pc=pc+imm*2,跳转指令 ,   有符号数
branch >=SBbge  rs1, rs2,imm[31-25, imm[12][10:5]][24-20, rs2][19-15, rs1]101[11-7, imm[4:1][11]]1100011if(rs1>rs2) pc=pc+imm*2,跳转指令,有符号数
branch < unsignedSBbltu  rs1, rs2,imm[31-25, imm[12][10:5]][24-20, rs2][19-15, rs1]110[11-7, imm[4:1][11]]1100011if(rs1<rs2) pc=pc+imm*2,跳转指令,无符号数
branch >=unsignedSBbgeu  rs1, rs2,imm[31-25, imm[12][10:5]][24-20, rs2][19-15, rs1]111[11-7, imm[4:1][11]]1100011if(rs1>rs2) pc=pc+imm*2,跳转指令,无符号数
jump and linkJ&LUJJAL rd, imm[31-12, imm[20][10:1][11][19:12]][11-7,rd]1101111pc=pc+imm*2, 现在的pc+4写入rd寄存器
Jump and link registerUJJALR, rd, rs1, imm[31-20,imm[11:0]][19-15,rs1]000[11-7,rd]1100111pc=rs1+imm, pc+4写入到rd寄存器

JAL指令使用20位的立即数作为偏移,所以它仅可以跳转到前后1M的地址空间。JALR使用12位的立即数,其值和rs1中的值相加,得到偏移量。

image

4. 同步指令

CategoryFmtRV32I basemachine code(bin)comment
Synchsynch threadIFENCE iorw,iorw0000[27-24,pred][23-20,succ]00000000000000001111pred/succ分别表示fence之前和之后的 iorw
synch instr and dataIFENCE.i00000000000000000001000000001111用于同步指令和数据流

Risc-V在多个hart(硬件线程)之间使用的是松散一致性模型,所以需要存储器fence指令。

fence指令能够保证存储器访问的执行顺序。在fence指令之前的所有存储器访问指令,比该fence之后的所有数据存储器访问指令先执行。

Risc-V架构将数据存储器的地址空间分为设备IO(device IO)和普通存储器空间,因此其读写访问分为四种类型:

I:设备读(device-input)

O:设备写(device-ouput)

R:存储器读(memory-reads)

W:存储器写(memory-writes)

PI/PO/PR/PW,分别f表示ence指令之前的四种读写访问类型,SI/SO/SR/SW分别表示fence指令之后的四种读写访问类型。

image

fence.i指令用于同步指令和数据流。如果程序中添加一个fence.i,则该指令能够保证fence.i之前所有指令的访存结果能被fence.i之后的所有指令访问到。通常说来,处理器的微架构硬件实现时,一旦遇到一条fence.i指令,便会先等到之前的所有访存指令执行完,然后冲刷流水线,包括Icache,使其后的所有指令,能够重新取指,从而得到最新的值。

注意:fence.i只能保证同一个hart(硬件线程)执行的指令流和数据流顺序,不能保证多个hart之间的指令流和数据流访问。

image


5.控制状态寄存器指令

CategoryFmtRV32I basemachine code(bin)comment
CSRCSRRWICSRRW[31-20,csr][19-15, rs1]001[11-7,rd]1110011csrrw rd, csr, rs1, 将csr索引的寄存器值读出,写到rd,将rs1中的值写入csr
CSRRSICSRRS[31-20,csr][19-15, rs1]010[11-7,rd]1110011csrrs rd, csr, rs1, 将csr索引寄存器值读出写到rd,以rs1为参考,如果rs1中某位为1,则置位对应的csr寄存器位,其他位不受影响。
CSRRCICSRRC[31-20,csr][19-15, rs1]011[11-7,rd]1110011csrrc rd, csr, rs1, 将csr索引寄存器值读出写到rd,以rs1为参考,如果rs1中某位为1,则清零对应的csr寄存器位,其他位不受影响。
CSRRWIICSRRWI[31-20,csr][19-15, zimm]101[11-7,rd]1110011csrrwi rd, csr, imm[4:0], 将csr索引寄存器值读出写到rd,5位立即数的值写入csr,高位补0
CSRRSIICSRRSI[31-20,csr][19-15, zimm]110[11-7,rd]1110011csrrsi rd, csr, imm[4:0], 将csr索引寄存器值读出写到rd,5位立即数的值(高位补0)逐位比较,如果为1,则置位csr相应位
CSRRCIICSRRCI[31-20,csr][19-15, zimm]111[11-7,rd]1110011csrrci rd, csr, imm[4:0], 将csr索引寄存器值读出写到rd,5位立即数的值(高位补0)逐位比较,如果为1,则清零csr相应位

CSR指令包括上面表中的6条指令,通常在用户层,不会访问写csr的指令。

这些CSR指令实现都是原子操作。对于CSRRW和CSRRWI来说,如果rd为x0,则不会有任何写操作。对于CSRS和CSRRC指令,如果rs1为x0,则不会有任何写操作。对于CSRRSI和CSRRCI来说,如果立即数为0,则不会有任何写操作。

用CSR指令可以实现一些伪指令,例如读取始终频率等。详细见伪指令列表。


image

6.环境调用和断点指令

CategoryFmtRV32I basemachine code(bin)comment
Systemsystem callIECALL00000000000000000000000001110011用于生成环境调用异常,产生异常时候,mepc寄存器将保存当前指令pc值。
system breakIEBREAK00000000000100000000000001110011生成断点,产生异常时候,mepc寄存器将保存当前指令pc值。

这两条指令能够产生环境调用异常和生成断点异常,产生异常时候,当前指令的pc值被写入mepc寄存器。

这两条指令在调试代码时候有用。

image










  • 1
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值