Menu Close

RISC-V指令集讲解(3)I-Type 移位指令和U-type指令

1.   I-Type 移位指令

 

相关参考文章:

RISC-V教学教案

 

上文RISC-V指令集讲解 (2) I-Type整数寄存器-立即数指令介绍了I-type中的6个指令,本文将继续介绍I-type中其余的整数寄存器-立即数指令(这里是属于I-type的移位指令)和U-type中的整数寄存器-立即数指令。

图1所示为移动次数为立即数的移位指令,后面会介绍其他的移位指令。从机器编码格式上可以看出这三个指令与上文提到的6个I-type指令有些不同,本文的I-immediate被分为两个部分:

imm[11:5]中的imm[10](机器码的bit 30)用来区分移位类型,其中SLLI和SRLI指令机器码的bit 30为0,而SRAI指令机器码的bit 30为1  [1]。

imm[4:0]或shamt[4:0](shift amount)意为移动量,可以看到SLLI,SRLI和SRAI的shamt的范围都是[4:0],这是因为在RV32I中,最大的移位量是31位,也就是2^5 – 1。RISC-V 移位指令

图1 移位指令机器编码格式 [1]

1.1. SLLI

SLLI(shift left logical immediate),立即数逻辑左移指令格式为 SLLI rd,rs1,shamt。x[rd] = x[rs1] ≪ shamt

其机器码如图2所示,SLLI的OP-IMM为001_0011,funct3为001,IMM[10]为0。移动多少位由imm[4:0]来决定。该指令将rs1中的值左移shamt[4:0],rs1的低位补零,结果写入rd中。

示例:

SLLI  x13,x12,3

将x12寄存器中的值左移3位,并将结果写入x13寄存器中。

OP-IMM为001_0011

funct3为001

shamt为5’b0_0011

bit 25-31 为7’b000_0000

rs1为 5’b0_1100

rd为 5’b0_1101

所以SLLI  x13,x12,3对应的机器码为0000000_00011_01100_001_01101_0010011,对应的16进制为32’h0036_1693

%title插图%num

图2 SLLI机器编码格式 [2]

 

%title插图%num

 

1.2. SRLI

SRLI(shift right logical immediate),立即数逻辑右移指令格式为 SRLI rd,rs1,shamtx[rd] = x[rs1] ≫𝑢 shamt

其机器码如图3所示,SRLI的OP-IMM为001_0011,funct3为101,IMM[10]为0。该指令将rs1中的值右移shamt[4:0]位,rs1的高位补零,结果写入rd中。

示例:

SRLI  x13,x12,5

x12寄存器中的值右移5位,并将结果写入x13中

 

%title插图%num

图3 SRLI机器编码格式 [2]

 

1.3. SRAI

SRAI(shift right arithmetic immediate),立即数算术右移指令格式为 SRAI rd,rs1,shamt。x[rd] =  x[rs1] ≫𝑠 shamt

其机器码如图4所示,SRAI的OP-IMM为001_0011,funct3为101,IMM[10]为1。该指令将rs1中的值右移shamt[4:0]位,rs1的高位由原rs1[31]填充(符号位填充),结果写入rd中。

示例:

SRAI  x13,x12,3

将x12寄存器中的值算术右移3位,并将结果写入x13中

 

 

%title插图%num

图4 SRAI机器编码格式 [2]

注意:

SRLI,SRAI的OP-IMM和funct3编码皆相同,由imm[10]的值区别指令 [1]。

 

1.4. 举例区分算术右移和逻辑右移

注意区分算术右移和逻辑右移,例如1100_1100(这里以8-bit数进行说明,RV32I中寄存器中实际存储的数为32-bit),

1100_1100算术右移三位,结果为1111_1001

0011_0011算术右移三位,结果为0000_0110

而1100_1100逻辑右移三位结果是0001_1001

0011_0011逻辑右移三位,结果为0000_0110

 

2.   U-Type整数寄存器-立即数指令

这里介绍的两条U-type指令中的AUIPC不再是操作通用寄存器(x0-x31),而是对程序计数器(program counter,PC)进行操作。

图5是LUI和AUIPC的机器码格式,将其与I-type的机器码进行比较,可以看到该类型没有rs1和funct3,取而代之的是一个20位的立即数(I-type中12位立即数的位置包含在内)。

注意U-type中的指令opcode是不相同的。与I-type相同的,U-type对应的immediate,固定为20位,被命名为U-immediate[31:12],如图5所示。RISC-V lui,auipc

图5 U-type 整数寄存器-立即数指令 [1]

 

2.1. LUI

LUI(load upper immediate),高位立即数加载指令格式为 LUI rd,immediate。x[rd] = sext(immediate[31:12] << 12)

其机器码如图6所示,LUI的opcode为011_0111。该指令是把U-immediate写入rd的高20位,rd的低12位补零。

指令示例,

LUI x8,0xf0000

将0xf000_0000加载进x8寄存器中

opcode为011_0111

rd为5’b01000

immediate[31:12]为1111_0000_0000_0000_0000

其对应的32位机器码为1111_0000_0000_0000_0000_01000_0110111,用16进制化简后得到32’hF000_0437RISC-V LUI机器码

图6 LUI机器编码格式 [2]

 

2.2. AUIPC

AUIPC(add upper immediate to PC),PC加立即数指令格式为 AUIPC rd,immediate。x[rd] = pc + sext(immediate[31:12] << 12)

其机器码如图7所示,AUIPC的opcode为001_0111。该指令是将20位的立即数符号扩展后,左移12位,和当前的PC相加,结果写入rd寄存器。

RISC-V AUIPC机器码

图7 AUIPC机器编码格式 [2]

指令示例:

AUIPC x12,0xf00

将0xf0_0000加上当前的PC,加载进x12寄存器中。

 

注意:

大多立即数很小或需要所有XLEN位。 RISC-V选择了非对称立即拆分(常规指令中为12位,再加上20位特殊的上载立即指令,比如LUI),以增加可用于常规指令的操作码空间 [1]。

AUIPC和JALR(后续文章会进行介绍)中的12位立即数的组合可以将控制权转移到任何32位PC相对地址,而AUIPC加上常规加载或存储指令中的12位立即数偏移量可以访问任何32位PC相对的数据地址。

当前的PC可以通过将AUIPC的U-immediate设置为0来获得。

 

3.文章参考

[1] Riscv.org, 2021. [Online]. Available: https://riscv.org/wp-content/uploads/2019/12/riscv-spec-20191213.pdf. [Accessed: 22- Feb- 2021].

[2] D. Patterson and A. Waterman, The RISC-V reader. Berkeley: Strawberry Canyon LLC, 2018.

Posted in RISC-V, RISC-V 教案, 指令集, 教材与教案, 文章

4 Comments

  1. 210111班_薛高映

    老师您好,看完视频和课件,我在立即数逻辑左移(SLLI)那里有点问题:x[rd] = x[rs1] ≪ shamt代表将x12中的值左移shamt位并将结果存入x12:
    OP-IMM为001_0011

    funct3为001

    shamt为5’b0_0011

    bit 25-31 为7’b000_0000

    rs1为 5’b0_1100

    rd为 5’b0_1101
    如果逻辑左移三位低位补零,rs1左移三位的结果不应该是0_0000而不是0_1101,

发表评论

相关链接