RV32A/RV64A指令集

      RV32A/RV64A指令包括两类:AMO(atomic memory operation)指令,Load-Reserved/Store-Conditional指令

      计算机体系结构中的存储器模型(或者说存储器一致性模型)主要分为三类:按序一致性模型,松散一致性模型,释放一致性模型。

      更详细存储器一致性介绍请看:https://blog.csdn.net/jfengamarsoft/article/details/70923658?utm_source=blogxgwz2

      按序一致性模型就是严格按序模型,如果处理器指令集架构符合按序一致性模型,那么多个处理器核上执行的程序就好像一个单核处理器上顺序执行一样。例如两个处理器核core0,core1,core0上执行了A,B,C,D四条存储器访问指令,core1 上执行了a,b,c,d四条访存指令。按序一致性模型系统上执行这8条指令的效果就好像在一个core上顺序执行了A a B b C c D d的指令流,或者A B a b C c D d,或者其他顺序,总之,只要符合core0和core1程序顺序,即从core0看,是A,B,C,D,从core1看是a,b,c,d的任意顺序都是合法的。

     按序一致性模型的两条规则:

  • 各个处理器核按照其程序顺序来执行,执行完一条后启动执行下一条指令,不能改变存储器访问指令的顺序(即便访问的是不同的存储器地址)。
  • 从全局看,每一个存储器写指令的操作都需要能够被系统中的所有处理器核同时观测到。就好像处理器系统(包括所有的处理器核)和存储系统之间有一个开关,一次只会连接一个处理器核和存储系统,因此对存储器的访问都是原子的,串行化的。

      松散一致性模型:对于不同存储器访问指令,就单核而言,理论上是可以改变其执行顺序的。松散一致性模型允许多核系统中,每个单核改变其存储器访问指令(比如是访问不同的地址)的执行顺序。松散一致性模型可以通过fence指令,来同步多核之间的存储器访问。在fence之前的所有存储器访问指令,必须比该fence指令之后的所有存储器访问指令先执行。

      释放一致性模型进一步支持获取(acquire)释放(release)机制:

  • 定义一种获取acquire指令,它仅屏障其之前的所有存储器访问操作。
  • 定义一种释放release指令,它仅屏障其之后的所有存储器访问。


      AMO指令要求整个读出,计算,写回必须为原子性质,就是读出和写回之间,该存储器地址不能被其它进程访问,通常总线会锁定。

      AMO指令也可以支持释放一致性模型,可以通过指令中的aq/rl位,来设置获取或释放属性。


amoswap.w rd, rs2,(rs1) 指令不具有获取和释放属性,不具备屏障功能。

amoswap.w.aq rd, rs2,(rs1) 指令具有获取属性,能够屏蔽其之后的所有存储器访问操作。

amoswap.w.rl rd, rs2,(rs1)指令具有释放属性,能够屏蔽其之前的所有存储器访问操作。

amoswap.w.aqrl rd, rs2,(rs1)指令具有获取释放属性,能够屏蔽其之前之后的所有存储器访问操作。

AMO指令实现上锁操作例子:

li t0, 1 #t0寄存器初始值为1

again:

amoswap.w.aq t0, t0, (a0)

bnez t0, again #如果锁中的值非0,意味着当前的锁仍然被其它进程占用,因此从新读取该锁的值。

…

critical section

…

amoswap.w.rl x0, x0,(a0) #写操作完成,向锁中写0


对于RV32A,LR/SC指令访问的地址,必须32位对齐,否则会产生异常,LR/SC指令也支持释放一致性模型,和AMO指令类似。

LR指令用于从存储器中(地址为rs1寄存器的值指定)读出一个32/64位数据,存放至rd寄存器中。

SC指令用于向存储器(地址为rs1寄存器的值指定)中写入一个32/64位数据,数据的值来自于rs2寄存器中的值。SC指令不一定执行成功,只有满足如下条件,SC指令才能执行成功。

  • LR和SC指令成对地访问相同的地址。
  • LR和SC指令之间没有任何其它的写操作(来自任何一个hart)访问同样的地址。
  • LR和SC指令之间没有任何中断与异常发生。
  • LR和SC指令之间没有执行MRET指令。

如果执行成功,则向rd寄存器写回数值0,如果执行失败,则向rd寄存器写回一个非0值。如果执行失败,意味着没有真正写入存储器。

LR/SC 能够实现lock-free 数据结构.

下面是一个inline的比较交换函数,仅需要3条指令。

# a0 holds address of memory location
# a1 holds expected value
# a2 holds desired value
# a0 holds return value, 0 if successful, !0 otherwise
cas:

lr.w t0, (a0) # Load original value.

bne t0, a1, fail # Doesn’t match, so fail.

sc.w a0, a2, (a0) # Try to update.

jr ra # Return.

fail:
li a0, 1 # Set return to failure.

jr ra # Return.

RV32A/RV64A都支持的原子指令共11条,另外还有11条指令仅支持RV64A。

amoadd.d

amoadd.d rd, rs2, (rs1)      //x[rd] = AMO64(M[x[rs1]] + x[rs2])
原子加双字(Atomic Memory Operation: Add Doubleword). R-type, RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的双字记为 t,把这个双字变为 t+x[rs2],把x[rd]设为 t。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amoadd.d R 0 0 0 0 0                         0 1 1           0 1 0 1 1 1 1

示例:

0:    003332af              amoadd.d    x5,x3,(x6)


amoadd.w

amoadd.w rd, rs2, (rs1)    //x[rd] = AMO32(M[x[rs1]] + x[rs2])
原子加字(Atomic Memory Operation: Add Word). R-type, RV32A and RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的字记为 t,把这个字变为 t+x[rs2],把 x[rd]设为符号位扩展的 t。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amoadd.w R 0 0 0 0 0                         0 1 0           0 1 0 1 1 1 1

示例:

4:    003322af              amoadd.w    x5,x3,(x6)
 


amoand.d

amoand.d rd, rs2, (rs1)    //x[rd] = AMO64(M[x[rs1]] & x[rs2])
原子双字与 (Atomic Memory Operation: AND Doubleword). R-type, RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的双字记为 t,把这个双字变为 t 和 x[rs2]位与的结果, 把 x[rd]设为 t。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amoand.d R 0 1 1 0 0                         0 1 1           0 1 0 1 1 1 1

示例:

8:    603332af              amoand.d    x5,x3,(x6)
 


amoand.w

amoand.w rd, rs2, (rs1)    //x[rd] = AMO32(M[x[rs1]] & x[rs2])
原子字与 (Atomic Memory Operation: AND Word). R-type, RV32A and RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的字记为 t,把这个字变为 t 和 x[rs2]位与的结果, 把 x[rd]设为符号位扩展的 t

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amoand.w R 0 1 1 0 0                         0 1 0           0 1 0 1 1 1 1

示例:

c:    603322af              amoand.w    x5,x3,(x6)
 


amomax.d

amomax.d rd, rs2, (rs1)    //x[rd] = AMO64(M[x[rs1]] MAX x[rs2])
原子最大双字(Atomic Memory Operation: Maximum Doubleword). R-type, RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的双字记为 t,把这个双字变为 t 和 x[rs2]中较大的一个(用二进制补码比较), 把 x[rd]设为 t

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amomax.d R 1 0 1 0 0                         0 1 1           0 1 0 1 1 1 1

示例:

20:    a03332af              amomax.d    x5,x3,(x6)
 


amomax.w

amomax.w rd, rs2, (rs1)    //x[rd] = AMO32(M[x[rs1]] MAX x[rs2])
原子最大字(Atomic Memory Operation: Maximum Word). R-type, RV32A and RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的字记为 t,把这个字变为 t 和 x[rs2]中较大的一个(用二进制补码比较), 把 x[rd]设为符号位扩展的 t。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amomax.w R 1 0 1 0 0                         0 1 0           0 1 0 1 1 1 1

示例:

24:    a03322af              amomax.w    x5,x3,(x6)


amomaxu.d

amomaxu.d rd, rs2, (rs1)    //x[rd] = AMO64(M[x[rs1]] MAXU x[rs2])
原子无符号最大双字(Atomic Memory Operation: Maximum Doubleword, Unsigned). R-type,RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的双字记为 t,把这个双字变为 t 和 x[rs2]中较大的一个(用无符号比较), 把 x[rd]设为 t。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amomaxu.d R 1 1 1 0 0                         0 1 1           0 1 0 1 1 1 1

示例:

38:    e03332af              amomaxu.d    x5,x3,(x6)
 


amomaxu.w

amomaxu.w rd, rs2, (rs1)   //x[rd] = AMO32(M[x[rs1]] MAXU x[rs2])
原子无符号最大字(Atomic Memory Operation: Maximum Word, Unsigned). R-type, RV32A and RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的字记为 t,把这个字变为 t 和 x[rs2]中较大的一个(用无符号比较), 把 x[rd]设为符号位扩展的 t。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amomaxu.w R 1 1 1 0 0                         0 1 0           0 1 0 1 1 1 1

示例:

3c:    e03322af              amomaxu.w    x5,x3,(x6)


amomin.d

amomin.d rd, rs2, (rs1)     //x[rd] = AMO64(M[x[rs1]] MIN x[rs2])
原子最小双字(Atomic Memory Operation: Minimum Doubleword). R-type, RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的双字记为 t,把这个双字变为 t 和 x[rs2]中较小的一个(用二进制补码比较), 把 x[rd]设为 t。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amomin.d R 1 0 0 0 0                         0 1 1           0 1 0 1 1 1 1

示例:

28:    803332af              amomin.d    x5,x3,(x6)


amomin.w

amomin.w rd, rs2, (rs1)     //x[rd] = AMO32(M[x[rs1]] MIN x[rs2])
原子最小字(Atomic Memory Operation: Minimum Word). R-type, RV32A and RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的字记为 t,把这个字变为 t 和 x[rs2]中较小的一个(用二进制补码比较), 把 x[rd]设为符号位扩展的 t。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amomin.w R 1 0 0 0 0                         0 1 0           0 1 0 1 1 1 1

示例:

2c:    803322af              amomin.w    x5,x3,(x6)


amominu.d

amominu.d rd, rs2,(rs1)   //x[rd] = AMO64(M[x[rs1]] MINU x[rs2])
原子无符号最小双字(Atomic Memory Operation: Minimum Doubleword, Unsigned). R-type,RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的双字记为 t,把这个双字变为 t 和 x[rs2]中较小的一个(用无符号比较), 把 x[rd]设为 t。
      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amominu.d R 1 1 0 0 0                         0 1 1           0 1 0 1 1 1 1

示例:

30:    c03332af              amominu.d    x5,x3,(x6)


amominu.w

amominu.w rd, rs2, (rs1)   //x[rd] = AMO32(M[x[rs1]] MINU x[rs2])
原子无符号最大字(Atomic Memory Operation: Minimum Word, Unsigned). R-type, RV32A and RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的字记为 t,把这个字变为 t 和 x[rs2]中较小的一个(用无符号比较), 把 x[rd]设为符号位扩展的 t。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amominu.w R 1 1 0 0 0                         0 1 0           0 1 0 1 1 1 1

示例:

 
34:    c03322af              amominu.w    x5,x3,(x6)
 


amoor.d

amoor.d rd, rs2, (rs1)    //x[rd] = AMO64(M[x[rs1]] | x[rs2])
原子双字或 (Atomic Memory Operation: OR Doubleword). R-type, RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的双字记为 t,把这个双字变为 t 和 x[rs2]位或的结果, 把 x[rd]设为 t。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amoor.d R 0 1 0 0 0                         0 1 1           0 1 0 1 1 1 1

示例:

10:    403332af              amoor.d    x5,x3,(x6)


amoor.w

amoor.w rd, rs2, (rs1)    //x[rd] = AMO32(M[x[rs1]] | x[rs2])
原子字或 (Atomic Memory Operation: OR Word). R-type, RV32A and RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的字记为 t,把这个字变为 t 和 x[rs2]位或的结果, 把 x[rd]设为符号位扩展的 t。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amoor.w R 0 1 0 0 0                         0 1 0           0 1 0 1 1 1 1

示例:

14:    403322af              amoor.w    x5,x3,(x6)
 
 


amoswap.d

amoswap.d rd, rs2, (rs1)    //x[rd] = AMO64(M[x[rs1]] SWAP x[rs2])
原子双字交换 (Atomic Memory Operation: Swap Doubleword). R-type, RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的双字记为 t,把这个双字变为 x[rs2]的值,把 x[rd]设为 t。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amoswap.d R 0 0 0 0 1                         0 1 1           0 1 0 1 1 1 1

示例:

40:    083332af              amoswap.d    x5,x3,(x6)


amoswap.w

amoswap.w rd, rs2, (rs1)    //x[rd] = AMO32(M[x[rs1]] SWAP x[rs2])
原子字交换 (Atomic Memory Operation: Swap Doubleword). R-type, RV32A and RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的字记为 t,把这个字变为 x[rs2]的值,把 x[rd]设为 符号位扩展的t。
      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amoswap.w R 0 0 0 0 1                         0 1 0           0 1 0 1 1 1 1

示例:

44:    083322af              amoswap.w    x5,x3,(x6)


amoxor.d

amoxor.d rd, rs2, (rs1)    //x[rd] = AMO64(M[x[rs1]] ^ x[rs2])
原子双字异或 (Atomic Memory Operation: XOR Doubleword). R-type, RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的双字记为 t,把这个双字变为 t 和 x[rs2]按位异或的结果, 把 x[rd]设为 t。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amoxor.d R 0 0 1 0 0                         0 1 1           0 1 0 1 1 1 1

示例:

18:    203332af              amoxor.d    x5,x3,(x6)


amoxor.w

amoxor.w rd, rs2, (rs1)    //x[rd] = AMO32(M[x[rs1]] ^ x[rs2])
原子字异或 (Atomic Memory Operation: XOR Word). R-type, RV32A and RV64A.
进行如下的原子操作:将内存中地址为 x[rs1]中的字记为 t,把这个字变为 t 和 x[rs2]按位异或的结果, 把 x[rd]设为符号位扩展的 t。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
amoxor.w R 0 0 1 0 0                         0 1 0           0 1 0 1 1 1 1

示例:

1c:    203322af              amoxor.w    x5,x3,(x6)


lr.d

lr.d rd, (rs1)      //x[rd] = LoadReserved64(M[x[rs1]])
加载保留双字(Load-Reserved Doubleword). R-type, RV64A.
从内存中地址为 x[rs1]中加载八个字节,写入 x[rd], 并对这个内存双字注册保留。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
lr.d R 0 0 0 1 0                         0 1 1           0 1 0 1 1 1 1

示例:

48:    100332af              lr.d    x5,(x6)


lr.w

lr.w rd, (rs1)    //x[rd] = LoadReserved32(M[x[rs1]])
加载保留字(Load-Reserved Word). R-type, RV32A and RV64A.
从内存中地址为 x[rs1]中加载四个字节,符号位扩展后写入 x[rd], 并对这个内存字注册保留。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
lr.w R 0 0 0 1 0                         0 1 0           0 1 0 1 1 1 1

示例:

4c:    100322af              lr.w    x5,(x6)
 


sc.d

sc.d rd, rs2, (rs1)    //x[rd] = StoreConditonal64(M[x[rs1], x[rs2])
条件存入双字(Store-Conditional Doubleword). R-type, RV64A only.
如果内存地址 x[rs1]上存在加载保留,将 x[rs2]寄存器中的 8 字节数存入该地址。如果存入成功,向寄存器 x[rd]中存入 0,否则存入一个非 0 的错误码。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
sc.d R 0 0 0 1 1                         0 1 1           0 1 0 1 1 1 1

示例:

50:    183332af              sc.d    x5,x3,(x6)
 


sc.w

sc.w rd, rs2, (rs1)    //x[rd] = StoreConditonal32(M[x[rs1], x[rs2])
条件存入字(Store-Conditional Word). R-type, RV32A and RV64A.
内存地址 x[rs1]上存在加载保留,将 x[rs2]寄存器中的 4 字节数存入该地址。如果存入成功,向寄存器 x[rd]中存入 0,否则存入一个非 0 的错误码。

      aq rl rs2 rs1 func3 rd opcode
name type 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
sc.w R 0 0 0 1 1                         0 1 0           0 1 0 1 1 1 1

示例:

54:    183322af              sc.w    x5,x3,(x6)





posted on 2018-10-29 19:19  迈克老狼2012  阅读(5645)  评论(1编辑  收藏  举报

导航