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)






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM