皋陶 发表于 2021-3-6 12:09:49

RV32I基础整数指令集

本帖最后由 皋陶 于 2021-3-6 12:32 编辑

      RV32I是32位基础整数指令集,它支持32位寻址空间,支持字节地址访问,仅支持小端格式(little-endian,高地址高位,低地址地位),寄存器也是32位整数寄存器。
      RV32I指令集的目的是尽量简化硬件的实施设计,所以它只有40条指令(备注,之前是47条指令,在最新的规范中,一些csr指令被放在扩展指令集中)。这40条指令几乎能够模拟其它任何扩展指令(除了A扩展指令,因为原子指令需要硬件支持)。如果用更简单的实现方式,比如对于ECALL和EBREAK指令,调用时候,系统总是自陷(trap),以及用NOP指令模拟Fence指令,则RV32I甚至可以减少到38条指令(备注:在RISC V中,NOP指令是伪代码,其实就是addi, x0,x0,0)。
      实际上要实现机器模式的RiscV特权架构,还需要6条csr指令,之前这些指令都是在RV32I中的,现在被放在扩展指令集 Zicsr中了。所以说要实现一个完整的RiscV系统,至少要实现RV32I+Zicsr指令集。
      在RV32I指令集架构中,包括32个通用目的寄存器,其中x0被预留为常数0,其它31个寄存器(x1-x31)是普通的通用整数寄存器。在Risc-V汇编语言中,每个通用寄存器都有一个对应的ABI名字,也就是说在汇编语言中,x1等价于ra,它们都会汇编成相同的机器码。对于RV32I,通用寄存器是32位的寄存器,xlen=32;对于RV64I,通用寄存器是64位寄存器,xlen=64。
      在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字节对齐。比如一个分支跳转指令,当条件判定是跳转的时候,而目的地址不是4字节对齐,则产生指令地址不对齐异常。无条件跳转指令也是如此,目的地址不是4字节对齐,则产生指令地址不对齐异常。备注:但在实际应用中,很难会产生这种错误,因为在汇编语言中,我们用label作为跳转目的,汇编器会自动帮我们产生字节对齐的偏移地址。
      其中rd表示目的寄存器,rs1是源操作数寄存器1,rs2是源操作数寄存器2。

      imm表示指令中的立即数,比如imm,表示一个12位的立即数,它的高20位会符号位扩展,也就是用最左边的位imm来进行扩展。imm表示一个32位的立即数,它的低12位会补0。备注: csr指令中的5位立即数不需要符号位扩展。下图是各种指令格式扩展后的32位立即数。

      分支指令(B 类型)的立即数字段在 S 类型的基础上旋转了 1 位。跳转指令(J类型)的直接字段在 U 类型的基础上旋转了 12 位。因此,RISC-V 实际上只有四种基本格式,但我们可以保守地认为它有六种格式。RV32I整数指令集
RV32I整数指令集分为几个种类:
1.Load和store指令      RV32I是一个load /store架构,所有的memory访问都是通过load/store指令,其它指令都是在寄存器之间或者寄存器和立即数之间进行运算,比如加法指令,减法指令等等。注意,装入目的寄存器如果为x0,将会产生一个异常。Load/Store指令在memory和寄存器之间传输数据,Load指令编码为I型,store指令编码为S型。计算memory地址时候,imm都会符号扩展成32位,然后和rs1相加,得到memory地址。为了提高性能,load/store指令应该尽量对齐地址,比如lw指令,访问地址应该4字节对齐,lh访问地址应该双字节对齐。根据微架构实现的不同,不对齐地址的访问可能会比较慢,而且地址对齐访问,能够确保是原子操作,不对齐的话为了读取和存储数据正确,还要进行额外的同步操作。
lb
lb rd, offset(rs1)   //x = sext(M + sext(offset)])
字节加载 (Load Byte). I-type, RV32I and RV64I.
从地址 x + sign-extend(offset)读取一个字节,经符号位扩展后写入x。

imm(offset)
11109876543210rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
lbI 000 0000011
例子:Disassembly of section .text:00000000 <.text>:
    0:   00510503                lb      x10,5(x2)
    4:   fec18283                lb      x5,-20(x3)注:立即数为补码表示

lhlh rd, offset(rs1)   //x = sext(M + sext(offset)])
半字加载 (Load Halfword). I-type, RV32I and RV64I.
从地址 x + sign-extend(offset)读取两个字节,经符号位扩展后写入 x。
imm(offset)
11109876543210rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
lhI 001 0000011

例子:0:   00511503                lh      x10,5(x2)
lwlw rd, offset(rs1)   //x = sext(M + sext(offset)])
字加载 (Load Word). I-type, RV32I and RV64I.
从地址 x + sign-extend(offset)读取四个字节,写入 x。对于 RV64I,结果要进行符号位扩展。
压缩形式: c.lwsp rd, offset; c.lw rd, offset(rs1)
imm(offset)
11109876543210rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210RV32I
lwI 010 0000011√

例子:0:   00512503                lw      x10,5(x2)
lbulbu rd, offset(rs1)   //x = M + sext(offset)]
无符号字节加载 (Load Byte, Unsigned). I-type, RV32I and RV64I.
从地址 x + sign-extend(offset)读取一个字节,经零扩展后写入 x。
imm(offset)
11109876543210rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
lbuI 100 0000011

例子:   0:   00514503                lbu   x10,5(x2)
lhulhu rd, offset(rs1)   //x = M + sext(offset)]
无符号半字加载 (Load Halfword, Unsigned). I-type, RV32I and RV64I.
从地址 x + sign-extend(offset)读取两个字节,经零扩展后写入 x。

imm(offset)
11109876543210rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
lhuI 101 0000011
例子:   0:   00515503                lhu   x10,5(x2)
sbsb rs2, offset(rs1)   //M + sext(offset)] = x
存字节(Store Byte). S-type, RV32I and RV64I.
将 x的低位字节存入内存地址 x+sign-extend(offset)。

imm(offset) imm(offset)
111098765rs2rs1func343210opcode
nametype313029282726252423222120191817161514131211109876543210
sbS 000 0100011
例子:   0:   00520123                sb      x5,2(x4) # 0x2
shsh rs2, offset(rs1)   //M + sext(offset) = x
存半字(Store Halfword). S-type, RV32I and RV64I.
将 x的低位 2 个字节存入内存地址 x+sign-extend(offset)。
imm(offset) imm(offset)
111098765rs2rs1func343210opcode
nametype313029282726252423222120191817161514131211109876543210
shS 001 0100011

例子:4:   00521123                sh      x5,2(x4) # 0x2
swsw rs2, offset(rs1)   //M + sext(offset) = x
存字(Store Word). S-type, RV32I and RV64I.
将 x的低位 4 个字节存入内存地址 x+sign-extend(offset)。
压缩形式: c.swsp rs2, offset; c.sw rs2, offset(rs1)
imm(offset) imm(offset)
111098765rs2rs1func343210opcode
nametype313029282726252423222120191817161514131211109876543210
swS 010 0100011

例子:8:   00522123                sw      x5,2(x4) # 0x2
2.整数计算指令(算术,逻辑指令,比较指令以及移位指令)      计算指令在寄存器和寄存器之间,或者在寄存器和立即数之间进行算术或逻辑运算。指令格式为I,R,U。      整数计算指令不会产生异常,但我们可以通过分支指令增加溢出(overflow)检测,比如对于无符号数加法: add t0, t1, t2;
      bltu t0, t1, overflow; //如果t0<t1,则跳转到溢出处理对于有符号数,如果知道符号位,则可以用下面代码: addi t0, t1, +imm;
      blt t0, t1, overflow; //t0<t1,则跳转到溢出处理,因为imm为正数对于通用有符号数加法,可以用下面的指令: add t0, t1, t2;
      slti t3, t2, 0;//如果t2<0, t3=1
      slt t4, t0, t1; //如果t0<t1, t4=1
      bne t3, t4, overflow; //如果t3!=t4, 跳转到溢出程序处理算术指令:   addadd rd, rs1, rs2    //x = x + x
把寄存器 x加到寄存器 x上,结果写入 x。忽略算术溢出。加 (Add). R-type, RV32I and RV64I
压缩形式: c.add rd, rs2; c.mv rd, rs2
func7rs2rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
addR0000000 000 0110011

例子:      0:   00a48433                add   x8,x9,x10addiaddi rd, rs1, immediate    //x = x + sext(immediate)
加立即数(Add Immediate). I-type, RV32I and RV64I.
把符号位扩展的立即数加到寄存器 x上,结果写入 x。忽略算术溢出。
压缩形式: c.li rd, imm; c.addi rd, imm; c.addi16sp imm; c.addi4spn rd, imm
imm
11109876543210rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
addiI 000 0010011

我们可以用addi指令实现move指令, addi rd, rs1, 0 <=>mv rd,rs1 //x=x例子:0:   01430513                addi    x10,x6,20
    subsub rd, rs1, rs2    //x = x - x
减(Substract). R-type, RV32I and RV64I.
x减去 x,结果写入 x。忽略算术溢出。
压缩形式: c.sub rd, rs2
func7rs2rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
subR0100000 000 0110011
例子:   0:   40a48433                sub   x8,x9,x10
   luilui rd, immediate   //x = sext(immediate << 12)
高位立即数加载 (Load Upper Immediate). U-type, RV32I and RV64I.
20 位立即数 immediate 左移 12 位, 并将低 12 位置零, 写入 x中。
压缩形式: c.lui rd, imm
imm
191817161514131211109876543210rdopcode
nametype313029282726252423222120191817161514131211109876543210
luiU 0110111
例子:0:   00003237                lui   x4,0x3
4:   000141b7                lui   x3,0x14
8:   000102b7                lui   x5,0x10lui   x5,-0x10注意:立即数不能为负,范围是0..1048575。mm.s: Assembler messages:
mm.s:1: Error: lui expression not in range 0..1048575,

    auipcauipc rd, immediate    //x = pc + sext(immediate << 12)
PC 加立即数 (Add Upper Immediate to PC). U-type, RV32I and RV64I.
把符号位扩展的 20 位(左移 12 位)立即数加到 pc 上,结果写入 x。
imm
191817161514131211109876543210rdopcode
nametype313029282726252423222120191817161514131211109876543210
auipcU 0010111

例子:   0:   0000a297                auipc   x5,0xa用 auipc x5,0 我们能得到当前的pc值。
逻辑指令:   xorxor rd, rs1, rs2   //x = x ^ x
异或(Exclusive-OR). R-type, RV32I and RV64I.
x和 x按位异或,结果写入 x。
压缩形式: c.xor rd, rs2
func7rs2rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
xorR0000000 100 0110011

例子:   c:   00a4c433                xor   x8,x9,x10
xorixori rd, rs1, immediate   //x = x ^ sext(immediate)
立即数异或(Exclusive-OR Immediate). I-type, RV32I and RV64I.
x和有符号扩展的 immediate 按位异或,结果写入 x。
压缩形式: c.xor rd, rs2
imm
11109876543210rs1func3rdopcode
xoriI 100 0010011


例子:   0:   00224293                xori    x5,x4,2
oror rd, rs1, rs2    //x = x | x
取或(OR). R-type, RV32I and RV64I.
把寄存器 x和寄存器 x按位取或,结果写入 x。
压缩形式: c.or rd, rs2
func7rs2rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
orR0000000 110 0110011

例子:18:   00a4e433                or      x8,x9,x10
oriori rd, rs1, immediate   //x = x | sext(immediate)
立即数取或(OR Immediate). R-type, RV32I and RV64I.
把寄存器 x和有符号扩展的立即数 immediate 按位取或,结果写入 x。
压缩形式: c.or rd, rs2
imm
11109876543210rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
oriI 110 0010011


例子:   0:   00226293                ori   x5,x4,2
andand rd, rs1, rs2   //x = x & x
与 (And). R-type, RV32I and RV64I.
将寄存器 x和寄存器 x位与的结果写入 x。
压缩形式: c.and rd, rs2
func7rs2rs1func3rdopcode
andR0000000 111 0110011

例子:1c:   00a4f433                and   x8,x9,x10
andiandi rd, rs1, immediate//x = x & sext(immediate)
与立即数 (And Immediate). I-type, RV32I and RV64I.
把符号位扩展的立即数和寄存器 x上的值进行位与,结果写入 x。
压缩形式: c.andi rd, imm
imm
11109876543210rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
andiI 111 0010011

例子:0:   00227293                andi    x5,x4,2
移位指令:sllsll rd, rs1, rs2   //x = x ≪ x
逻辑左移(Shift Left Logical). R-type, RV32I and RV64I.
把寄存器 x左移 x位,空出的位置填入 0,结果写入 x。 x的低 5 位(如果是RV64I 则是低 6 位)代表移动位数,其高位则被忽略。

func7rs2rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
sllR0000000 001 0110011

例子:   0:   00a49433                sll   x8,x9,x10
sllislli rd, rs1, shamt   //x = x ≪ shamt
立即数逻辑左移(Shift Left Logical Immediate). I-type, RV32I and RV64I.
把寄存器 x左移 shamt位,空出的位置填入 0,结果写入 x。对于 RV32I,仅当 shamt=0
时,指令才是有效的。
压缩形式: c.slli rd, shamt
shamt
543210rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
slliI000000 001 0010011

例子:   0:   00511513                slli    x10,x2,0x5
srlsrl rd, rs1, rs2//x = (x ≫u x)
逻辑右移(Shift Right Logical). R-type, RV32I and RV64I.
把寄存器 x右移 x位,空出的位置填入 0,结果写入 x。 x的低 5 位(如果是 RV64I 则是低 6 位)代表移动位数,其高位则被忽略。

func7rs2rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
srlR0000000 101 0110011
例子:10:   00a4d433                srl   x8,x9,x10
srlisrli rd, rs1, shamt   //x = (x ≫u shamt)
立即数逻辑右移(Shift Right Logical Immediate). I-type, RV32I and RV64I.
把寄存器 x右移 shamt位,空出的位置填入 0,结果写入 x。对于 RV32I,仅当 shamt=0 时,指令才是有效的。
压缩形式: c.srli rd, shamt
shamt
543210rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
srliI000000 101 0010011
例子:   0:   00515513                srli    x10,x2,0x5
srasra rd, rs1, rs2    //x = (x ≫s x)
算术右移(Shift Right Arithmetic). R-type, RV32I and RV64I.
把寄存器 x右移 x位,空位用 x的最高位填充,结果写入 x。 x的低 5 位 (如果是 RV64I 则是低 6 位)为移动位数,高位则被忽略。
func7rs2rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
sraR0100000 101 0110011
例子:14:   40a4d433                sra   x8,x9,x10
sraisrai rd, rs1, shamt    //x = (x ≫s shamt)
立即数算术右移(Shift Right Arithmetic Immediate). I-type, RV32I and RV64I.
把寄存器 x右移 shamt 位,空位用 x的最高位填充,结果写入 x。对于 RV32I, 仅当 shamt=0 时指令有效。
压缩形式: c.srai rd, shamt
shamt
543210rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
sraiI010000 101 0010011
例子:   0:   40515513                srai    x10,x2,0x5
比较指令:
sltslt rd, rs1, rs2    //x = (x <s x)
小于则置位(Set if Less Than). R-type, RV32I and RV64I.
比较 x和 x中的数,如果 x更小,向 x写入 1,否则写入 0。
func7rs2rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
sltR0000000 010 0110011
例子:   4:   00a4a433                slt   x8,x9,x10
sltislti rd, rs1, immediate    //x = (x <s sext(immediate))
小于立即数则置位(Set if Less Than Immediate). I-type, RV32I and RV64I.
比较 x和有符号扩展的 immediate,如果 x更小,向 x写入 1,否则写入 0。
imm
11109876543210rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
sltiI 010 0010011
例子:   0:   00222293                slti    x5,x4,2
sltusltu rd, rs1, rs2   //x = (x <u x)
无符号小于则置位(Set if Less Than, Unsigned). R-type, RV32I and RV64I.
比较 x和 x,比较时视为无符号数。如果 x更小,向 x写入 1,否则写入 0。

func7rs2rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
sltuR0000000 011 0110011
例子:   8:   00a4b433                sltu    x8,x9,x10
sltiusltiu rd, rs1, immediate   //x = (x <u sext(immediate))
无符号小于立即数则置位(Set if Less Than Immediate, Unsigned). I-type, RV32I and RV64I.
比较 x和有符号扩展的 immediate,比较时视为无符号数。如果 x更小,向 x写入 1,否则写入 0
imm
11109876543210rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
sltiuI 011 0010011
例子:0:   00223293                sltiu   x5,x4,2


3. 控制指令,包括无条件跳转指令和条件跳转指令beqbeq rs1, rs2, offset   //if (rs1 == rs2) pc += sext(offset)
相等时分支跳转 (Branch if Equal). B-type, RV32I and RV64I.
若寄存器 x和寄存器 x的值相等,把 pc 的值设为当前值加上符号位扩展的偏移 offset。
压缩形式: c.beqz rs1, offset

  imm imm 
  121098765rs2rs1func3432111opcode
nametype313029282726252423222120191817161514131211109876543210
beqB                 000     1100011

例子:00000000 <label-0x8>:
    0:   00628463                beq   x5,x6,8 <label>
    4:   00a48433                add   x8,x9,x1000000008 <label>:
    8:   00d605b3                add   x11,x12,x13
bnebne rs1, rs2, offset   //if (rs1 ≠ rs2) pc += sext(offset)
不相等时分支跳转 (Branch if Not Equal). B-type, RV32I and RV64I.
若寄存器 x和寄存器 x的值不相等,把 pc 的值设为当前值加上符号位扩展的偏移offset。
压缩形式: c.bnez rs1, offset
  imm imm 
  121098765rs2rs1func3432111opcode
nametype313029282726252423222120191817161514131211109876543210
bneB                 001     1100011


例子:00000000 <label-0x8>:
    0:   00629463                bne   x5,x6,8 <label>
    4:   00a48433                add   x8,x9,x1000000008 <label>:
    8:   00d605b3                add   x11,x12,x13
bltblt rs1, rs2, offset    //if (rs1 <s rs2) pc += sext(offset)
小于时分支跳转 (Branch if LessThan). B-type, RV32I and RV64I.
若寄存器 x的值小于寄存器 x的值(均视为二进制补码),把 pc 的值设为当前值加上符号位扩展的偏移 offset。
  imm imm 
  121098765rs2rs1func3432111opcode
nametype313029282726252423222120191817161514131211109876543210
bltB                 100     1100011

例子:00000000 <label-0x8>:
    0:   0062c463                blt   x5,x6,8 <label>
    4:   00a48433                add   x8,x9,x1000000008 <label>:
    8:   00d605b3                add   x11,x12,x13

bge
bge rs1, rs2, offset//if (rs1 ≥s rs2) pc += sext(offset)
大于等于时分支 跳转(Branch if Greater Than or Equal). B-type, RV32I and RV64I.
若寄存器 x的值大于等于寄存器 x的值(均视为二进制补码),把 pc 的值设为当前值加上符号位扩展的偏移 offset。

  imm imm 
  121098765rs2rs1func3432111opcode
nametype313029282726252423222120191817161514131211109876543210
bgeB                 101     1100011
例子:00000000 <label-0x8>:
    0:   0062d463                bge   x5,x6,8 <label>
    4:   00a48433                add   x8,x9,x1000000008 <label>:
    8:   00d605b3                add   x11,x12,x13
bltubltu rs1, rs2, offset   //if (rs1 <u rs2) pc += sext(offset)
无符号小于时分支跳转 (Branch if LessThan, Unsigned). B-type, RV32I and RV64I.
若寄存器 x的值小于寄存器 x的值(均视为无符号数),把 pc 的值设为当前值加上
符号位扩展的偏移 offset。
  imm imm 
  121098765rs2rs1func3432111opcode
nametype313029282726252423222120191817161514131211109876543210
bltuB                 110     1100011
例子:00000000 <label-0x8>:
    0:   0062e463                bltu    x5,x6,8 <label>
    4:   00a48433                add   x8,x9,x1000000008 <label>:
    8:   00d605b3                add   x11,x12,x13
bgeubgeu rs1, rs2, offset   //if (rs1 ≥u rs2) pc += sext(offset)
无符号大于等于时分支跳转 (Branch if Greater Than or Equal, Unsigned). B-type, RV32I and RV64I.
若寄存器 x的值大于等于寄存器 x的值(均视为无符号数),把 pc 的值设为当前值加上符号位扩展的偏移 offset。
  imm imm 
  121098765rs2rs1func3432111opcode
nametype313029282726252423222120191817161514131211109876543210
bgeuB                 111     1100011
例子:00000000 <label-0x8>:
    0:   0062f463                bgeu    x5,x6,8 <label>
    4:   00a48433                add   x8,x9,x1000000008 <label>:
    8:   00d605b3                add   x11,x12,x13
jaljal rd, offset//x = pc+4; pc += sext(offset)
跳转并链接 (Jump andLink). J-type, RV32I and RV64I.
把下一条指令的地址(pc+4)保存到目的寄存器,然后把 pc 设置为当前值加上符号位扩展的offset。rd 默认为 x1。
压缩形式: c.j offset; c.jal offset

imm
2010987654321111918171615141312rdopcode
nametype313029282726252423222120191817161514131211109876543210
jalJ 1101111
例子:00000000 <label-0x1c>:
    0:   01430513                addi    x10,x6,20
    4:   01430593                addi    x11,x6,20
    8:   01430513                addi    x10,x6,20
    c:   01430513                addi    x10,x6,20
   10:   00c000ef                jal   x1,1c <label>
   14:   01430613                addi    x12,x6,20
   18:   01430613                addi    x12,x6,200000001c <label>:
   1c:   01430613                addi    x12,x6,20
   20:   01430613                addi    x12,x6,20
   24:   01430613                addi    x12,x6,20
注意:汇编和spec有点不一样,汇编里面jal的立即数是绝对地址,但指令编码是对的,偏移了12个字节,所以imm=110,imm默认为0。
00000004 <label>:
    4:   01430593                addi    x11,x6,20
    8:   01430513                addi    x10,x6,20
    c:   01430513                addi    x10,x6,20
   10:   ff5ff0ef                jal   x1,4 <label>
   14:   01430613                addi    x12,x6,20
   18:   01430613                addi    x12,x6,20偏移 为-12,补码表示
jalr
jalr rd, offset(rs1)   // t =pc+4; pc=(x+sext(offset))&~1; x=t
跳转并寄存器链接 (Jump and Link Register). I-type, RV32I and RV64I.
把 pc 设置为 x + sign-extend(offset),把计算出的地址的最低有效位设为 0,并将原 pc+4的值写入 f。 rd 默认为 x1。
压缩形式: c.jr rs1; c.jalr rs1

imm
11109876543210rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
jalrI 000 1100111
例子:00000000 <label-0x4>:
    0:   01430513                addi    x10,x6,2000000004 <label>:
    4:   01430593                addi    x11,x6,20
    8:   01430513                addi    x10,x6,20
    c:   01430513                addi    x10,x6,20
   10:   ffc082e7                jalr    x5,-4(x1)
   14:   01430613                addi    x12,x6,20
   18:   01430613                addi    x12,x6,20
00000000 <label-0x4>:
    0:   01430513                addi    x10,x6,2000000004 <label>:
    4:   01430593                addi    x11,x6,20
    8:   01430513                addi    x10,x6,20
    c:   01430513                addi    x10,x6,20
   10:   004082e7                jalr    x5,4(x1)
   14:   01430613                addi    x12,x6,20
   18:   01430613                addi    x12,x6,20



4. 同步指令fence
fence pred, succ   //Fence(pred, succ)
同步内存和 I/O(Fence Memory and I/O). I-type, RV32I and RV64I.
在后续指令中的内存和 I/O 访问对外部(例如其他线程)可见之前,使这条指令之前的内存及 I/O 访问对外部可见。比特中的第 3,2,1 和 0 位分别对应于设备输入,设备输出,内存读写。例如 fence r, rw,将前面读取与后面的读取和写入排序,使用 pred = 0010 和 succ = 0011进行编码。如果省略了参数,则表示 fence iorw, iorw,即对所有访存请求进行排序。


predsuccrs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
fenceI00000000000000000000000000001111
例子:0:   0ff0000f                fence   iorw,iorw


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,分别表示fence指令之前的四种读写访问类型,SI/SO/SR/SW分别表示fence指令之后的四种读写访问类型。


6.环境调用和断点指令

这两条指令能够产生环境调用异常和生成断点异常,产生异常时候,当前指令的pc值被写入mepc寄存器。这两条指令在调试代码时候有用。
ecallecall   //RaiseException(EnvironmentCall)
环境调用 (Environment Call). I-type, RV32I and RV64I.
通过引发环境调用异常来请求执行环境。
imm
11109876543210rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
ecallI00000000000000000000000001110011

例子:   0:   00000073                ecall
ebreakEbreak   //RaiseException(Breakpoint)
环境断点 (Environment Breakpoint). I-type, RV32I and RV64I.
通过抛出断点异常的方式请求调试器。
imm
11109876543210rs1func3rdopcode
nametype313029282726252423222120191817161514131211109876543210
ebreakI00000000000100000000000001110011

例子:   0:   00100073                ebreak



发表于 2021-6-25 06:57:14

facebook spy tool

https://i0.wp.com/www.techinpost.com/wp-content/uploads/2018/10/image001-1.jpg?ssl=

FB friends spy is a facebook windows application that offers to its user’s information about their friends they cannot find in there profiles:
1. Online presence information (offline/online) even if you are in offline chat mode.
2. People most interested by them.
3. People most interacting with them(on comments not messages , spying on messages is illegal and forbidden by facebook, so it is impossible to do, thank you for your understanding).
4. latest Facebook statuses
5. Places visited.
6. Events attending or already participated in
FB friend's spy will ask you for permissions to offer you the information you want, this information will and still be used only by you, it will not be used by anyone else.
FB friend’s spy uses Facebook SDK to connect to Facebook, so users don’t have to worry about their private or secret information.


https://zootovaryvsem.org/button3.png

williamhwf 发表于 2021-10-22 07:34:15

学习了~~
页: [1]
查看完整版本: RV32I基础整数指令集