AMDGPU 指令運算元語法¶
慣例¶
以下符號貫穿本文件
符號
描述
{0..N}
從 0 到 N(包含)範圍內的任何整數值。
<x>
x 的語法和含義在其他地方解釋。
運算元¶
v (32 位元)¶
向量暫存器。共有 256 個 32 位元向量暫存器。
一系列向量暫存器可用於處理超過 32 位元的資料。
組譯器目前支援具有 1 到 12、16 和 32 個向量暫存器的元組。
注意:N 和 K 必須滿足以下條件
N <= K。
0 <= N <= 255。
0 <= K <= 255。
K-N+1 必須在 1 到 12 的範圍內,或等於 16 或 32。
GFX90A 和 GFX942 有額外的對齊要求:向量暫存器對必須是偶數對齊(第一個暫存器必須是偶數)。
範例
v255
v[0]
v[0:1]
v[1:1]
v[0:3]
v[2*2]
v[1-1:2-1]
[v252]
[v252,v253,v254,v255]
非循序位址(NSA)語法
GFX10+ image 指令可以對影像位址使用特殊的 NSA(非循序位址)語法
語法
描述
[Vm, Vn, … Vk]
32 位元向量暫存器的序列。每個暫存器可以使用上述定義的語法指定。
與標準語法相反,NSA 序列中的暫存器不需要具有連續的索引。此外,同一個暫存器可以在序列中出現多次。
GFX11+ 有額外的限制:如果位址大小佔用超過 5 個 dword,則從第 5 個元素開始的暫存器必須是連續的。
範例
[v32,v1,v[2]]
[v[32],v[1:1],[v2]]
[v4,v4,v4,v4]
v (16 位元)¶
16 位元向量暫存器。每個32 位元向量暫存器分為兩個 16 位元低位和高位暫存器,因此共有 512 個 16 位元向量暫存器。
只有 VOP3、VOP3P 和 VINTERP 指令可以使用op_sel修飾符存取所有 512 個暫存器。VOP1、VOP2 和 VOPC 指令目前只能使用以下描述的語法存取 128 個低位 16 位元暫存器。
警告
本節內容不完整。組譯器中對 16 位元暫存器的支援仍在開發中。
語法
描述
v<N>
單個 16 位元向量暫存器(低半部分)。
注意:N 必須滿足以下條件
0 <= N <= 127。
範例
v127
a¶
累加器暫存器。共有 256 個 32 位元累加器暫存器。
一系列累加器暫存器可用於處理超過 32 位元的資料。
組譯器目前支援具有 1 到 12、16 和 32 個累加器暫存器的元組。
注意:N 和 K 必須滿足以下條件
N <= K。
0 <= N <= 255。
0 <= K <= 255。
K-N+1 必須在 1 到 12 的範圍內,或等於 16 或 32。
GFX90A 和 GFX942 有額外的對齊要求:累加器暫存器對必須是偶數對齊(第一個暫存器必須是偶數)。
範例
a255
a[0]
a[0:1]
a[1:1]
a[0:3]
a[2*2]
a[1-1:2-1]
[a252]
[a252,a253,a254,a255]
acc0
acc[1]
[acc250]
[acc2,acc3]
s¶
純量 32 位元暫存器。可用的純量暫存器數量取決於 GPU
GPU
純量暫存器數量
GFX7
104
GFX8
102
GFX9
102
GFX10+
106
一系列純量暫存器可用於處理超過 32 位元的資料。組譯器目前支援具有 1 到 12、16 和 32 個純量暫存器的元組。
純量暫存器對必須是偶數對齊(第一個暫存器必須是偶數)。4 個或更多純量暫存器的序列必須是四字組對齊。
注意:N 和 K 必須滿足以下條件
N 必須根據序列大小正確對齊。
N <= K。
0 <= N < SMAX,其中 SMAX 是可用純量暫存器的數量。
0 <= K < SMAX,其中 SMAX 是可用純量暫存器的數量。
K-N+1 必須在 1 到 12 的範圍內,或等於 16 或 32。
範例
s0
s[0]
s[0:1]
s[1:1]
s[0:3]
s[2*2]
s[1-1:2-1]
[s4]
[s4,s5,s6,s7]
純量暫存器對齊無效的範例
s[1:2]
s[2:5]
trap¶
一組 trap 處理常式暫存器
ttmp¶
Trap 處理常式臨時純量暫存器,32 位元寬。可用的 ttmp 暫存器數量取決於 GPU
GPU
ttmp 暫存器數量
GFX7
12
GFX8
12
GFX9
16
GFX10+
16
一系列 ttmp 暫存器可用於處理超過 32 位元的資料。組譯器目前支援具有 1 到 12 和 16 個 ttmp 暫存器的元組。
ttmp 暫存器對必須是偶數對齊(第一個暫存器必須是偶數)。4 個或更多 ttmp 暫存器的序列必須是四字組對齊。
注意:N 和 K 必須滿足以下條件
N 必須根據序列大小正確對齊。
N <= K。
0 <= N < TMAX,其中 TMAX 是可用 ttmp 暫存器的數量。
0 <= K < TMAX,其中 TMAX 是可用 ttmp 暫存器的數量。
K-N+1 必須在 1 到 12 的範圍內,或等於 16。
範例
ttmp0
ttmp[0]
ttmp[0:1]
ttmp[1:1]
ttmp[0:3]
ttmp[2*2]
ttmp[1-1:2-1]
[ttmp4]
[ttmp4,ttmp5,ttmp6,ttmp7]
ttmp 暫存器對齊無效的範例
ttmp[1:2]
ttmp[2:5]
tba¶
Trap 基底位址,64 位元寬。保存指向當前 trap 處理常式程式的指標。
語法
描述
可用性
tba
64 位元 trap 基底位址 暫存器。
GFX7、GFX8
[tba]
64 位元 trap 基底位址 暫存器(SP3 語法)。
GFX7、GFX8
[tba_lo,tba_hi]
64 位元 trap 基底位址 暫存器(SP3 語法)。
GFX7、GFX8
trap 基底位址的高位和低位 32 位元可以作為單獨的暫存器存取
語法
描述
可用性
tba_lo
trap 基底位址暫存器的低位 32 位元。
GFX7、GFX8
tba_hi
trap 基底位址暫存器的高位 32 位元。
GFX7、GFX8
[tba_lo]
trap 基底位址暫存器的低位 32 位元(SP3 語法)。
GFX7、GFX8
[tba_hi]
trap 基底位址暫存器的高位 32 位元(SP3 語法)。
GFX7、GFX8
tma¶
Trap 記憶體位址,64 位元寬。
語法
描述
可用性
tma
64 位元 trap 記憶體位址 暫存器。
GFX7、GFX8
[tma]
64 位元 trap 記憶體位址 暫存器(SP3 語法)。
GFX7、GFX8
[tma_lo,tma_hi]
64 位元 trap 記憶體位址 暫存器(SP3 語法)。
GFX7、GFX8
trap 記憶體位址的高位和低位 32 位元可以作為單獨的暫存器存取
語法
描述
可用性
tma_lo
trap 記憶體位址暫存器的低位 32 位元。
GFX7、GFX8
tma_hi
trap 記憶體位址暫存器的高位 32 位元。
GFX7、GFX8
[tma_lo]
trap 記憶體位址暫存器的低位 32 位元(SP3 語法)。
GFX7、GFX8
[tma_hi]
trap 記憶體位址暫存器的高位 32 位元(SP3 語法)。
GFX7、GFX8
flat_scratch¶
Flat scratch 位址,64 位元寬。保存 scratch 記憶體的基底位址。
語法
描述
flat_scratch
64 位元 flat scratch 位址暫存器。
[flat_scratch]
64 位元 flat scratch 位址暫存器(SP3 語法)。
[flat_scratch_lo,flat_scratch_hi]
64 位元 flat scratch 位址暫存器(SP3 語法)。
flat scratch 位址的高位和低位 32 位元可以作為單獨的暫存器存取
語法
描述
flat_scratch_lo
flat scratch 位址暫存器的低位 32 位元。
flat_scratch_hi
flat scratch 位址暫存器的高位 32 位元。
[flat_scratch_lo]
flat scratch 位址暫存器的低位 32 位元(SP3 語法)。
[flat_scratch_hi]
flat scratch 位址暫存器的高位 32 位元(SP3 語法)。
xnack_mask¶
Xnack 遮罩,64 位元寬。保存 64 位元遮罩,指示哪些線程因向量記憶體運算而收到 XNACK。
有關 xnack 功能的可用性,請參閱此表格。
語法
描述
xnack_mask
64 位元 xnack 遮罩 暫存器。
[xnack_mask]
64 位元 xnack 遮罩 暫存器(SP3 語法)。
[xnack_mask_lo,xnack_mask_hi]
64 位元 xnack 遮罩 暫存器(SP3 語法)。
xnack 遮罩的高位和低位 32 位元可以作為單獨的暫存器存取
語法
描述
xnack_mask_lo
xnack 遮罩暫存器的低位 32 位元。
xnack_mask_hi
xnack 遮罩暫存器的高位 32 位元。
[xnack_mask_lo]
xnack 遮罩暫存器的低位 32 位元(SP3 語法)。
[xnack_mask_hi]
xnack 遮罩暫存器的高位 32 位元(SP3 語法)。
vcc¶
向量條件碼,64 位元寬。每個線程一個位元的位元遮罩;它保存向量比較運算的結果。
請注意,GFX10+ H/W 在 wave32 模式下不使用 vcc 的高位 32 位元。
語法
描述
vcc
64 位元向量條件碼暫存器。
[vcc]
64 位元向量條件碼暫存器(SP3 語法)。
[vcc_lo,vcc_hi]
64 位元向量條件碼暫存器(SP3 語法)。
向量條件碼的高位和低位 32 位元可以作為單獨的暫存器存取
語法
描述
vcc_lo
向量條件碼暫存器的低位 32 位元。
vcc_hi
向量條件碼暫存器的高位 32 位元。
[vcc_lo]
向量條件碼暫存器的低位 32 位元(SP3 語法)。
[vcc_hi]
向量條件碼暫存器的高位 32 位元(SP3 語法)。
m0¶
32 位元記憶體暫存器。它具有多種用途,包括暫存器索引和邊界檢查。
語法
描述
m0
32 位元記憶體暫存器。
[m0]
32 位元記憶體暫存器(SP3 語法)。
exec¶
執行遮罩,64 位元寬。每個線程一個位元的位元遮罩,應用於向量指令,並控制哪些線程執行以及哪些線程忽略指令。
請注意,GFX10+ H/W 在 wave32 模式下不使用 exec 的高位 32 位元。
語法
描述
exec
64 位元執行遮罩暫存器。
[exec]
64 位元執行遮罩暫存器(SP3 語法)。
[exec_lo,exec_hi]
64 位元執行遮罩暫存器(SP3 語法)。
執行遮罩的高位和低位 32 位元可以作為單獨的暫存器存取
語法
描述
exec_lo
執行遮罩暫存器的低位 32 位元。
exec_hi
執行遮罩暫存器的高位 32 位元。
[exec_lo]
執行遮罩暫存器的低位 32 位元(SP3 語法)。
[exec_hi]
執行遮罩暫存器的高位 32 位元(SP3 語法)。
vccz¶
單個位元旗標,指示vcc是否全為零。
注意:當 GFX10+ 在 wave32 模式下運作時,此暫存器反映vcc_lo的狀態。
execz¶
單個位元旗標,指示exec是否全為零。
注意:當 GFX10+ 在 wave32 模式下運作時,此暫存器反映exec_lo的狀態。
scc¶
單個位元旗標,指示純量比較運算的結果。
lds_direct¶
特殊運算元,使用m0作為位址,提供從 LDS 記憶體中提取的 32 位元值。
null¶
這是一個特殊運算元,可以用作來源或目的地。
當用作目的地時,運算的結果將被丟棄。
當用作來源時,它提供零值。
內嵌常數¶
內嵌常數是一個整數或浮點數值,編碼為指令的一部分。將內嵌常數與字面值進行比較。
內嵌常數包括
如果一個數字可以編碼為字面值或常數,則組譯器會選擇後者編碼,因為它更有效率。
iconst¶
只有一小部分整數可以編碼為內嵌常數。它們在下表中列出。其他整數編碼為字面值。
值
注意
{0..64}
正整數內嵌常數。
{-16..-1}
負整數內嵌常數。
fconst¶
編碼為內嵌常數的浮點數。
只有一小部分浮點數可以編碼為內嵌常數。它們在下表中列出。其他浮點數編碼為字面值。
值
注意
可用性
0.0
與整數常數 0 相同。
所有 GPU
0.5
浮點數常數 0.5
所有 GPU
1.0
浮點數常數 1.0
所有 GPU
2.0
浮點數常數 2.0
所有 GPU
4.0
浮點數常數 4.0
所有 GPU
-0.5
浮點數常數 -0.5
所有 GPU
-1.0
浮點數常數 -1.0
所有 GPU
-2.0
浮點數常數 -2.0
所有 GPU
-4.0
浮點數常數 -4.0
所有 GPU
0.1592
1.0/(2.0*pi)。僅適用於 16 位元運算元。
GFX8+
0.15915494
1.0/(2.0*pi)。僅適用於 16 位元和 32 位元運算元。
GFX8+
0.15915494309189532
1.0/(2.0*pi)。
GFX8+
警告
浮點數內嵌常數不能與16 位元整數運算元一起使用。組譯器將這些值編碼為字面值。
ival¶
編碼為內嵌常數的符號運算元。這些運算元提供對 H/W 暫存器的唯讀存取。
語法
替代語法 (SP3)
注意
可用性
shared_base
src_shared_base
共享記憶體區域的基底位址。
GFX9+
shared_limit
src_shared_limit
共享記憶體區域結尾的位址。
GFX9+
private_base
src_private_base
私有記憶體區域的基底位址。
GFX9+
private_limit
src_private_limit
私有記憶體區域結尾的位址。
GFX9+
pops_exiting_wave_id
src_pops_exiting_wave_id
POPS 的專用計數器。
GFX9、GFX10
literal¶
字面值是一個 64 位元值,編碼為指令流中單獨的 32 位元 dword。將字面值與內嵌常數進行比較。
如果一個數字可以編碼為字面值或內嵌常數,組譯器會選擇後者編碼,因為它更有效率。
一條指令只能使用一個字面值,但多個運算元可以參考同一個字面值。
uimm8¶
uimm32¶
uimm20¶
值必須在 0..0xFFFFF 範圍內。
simm21¶
值必須在 -0x100000..0x0FFFFF 範圍內。
off¶
特殊實體,指示不使用此運算元的值。
語法
描述
off
指示未使用的運算元。
數字¶
整數¶
整數為 64 位元寬。它們會轉換為預期的運算元類型,如此處所述。
整數可以用二進制、八進制、十六進制和十進制格式指定
格式
語法
範例
十進制
[-]?[1-9][0-9]*
-1234
二進制
[-]?0b[01]+
0b1010
八進制
[-]?0[0-7]+
010
十六進制
[-]?0x[0-9a-fA-F]+
0xff
[-]?[0x]?[0-9][0-9a-fA-F]*[hH]
0ffh
浮點數¶
所有浮點數都作為雙精度(64 位元寬)處理。它們會轉換為預期的運算元類型,如此處所述。
浮點數可以用十六進制和十進制格式指定
格式
語法
範例
注意
十進制
[-]?[0-9]*[.][0-9]*([eE][+-]?[0-9]*)?
-1.234, 234e2
必須包含十進制分隔符或指數。
十六進制
[-]0x[0-9a-fA-F]*(.[0-9a-fA-F]*)?[pP][+-]?[0-9a-fA-F]+
-0x1afp-10, 0x.1afp10
表達式¶
表達式會評估為 64 位元整數。請注意,不支援浮點數表達式。
表達式有兩種
絕對表達式¶
絕對表達式的值在程式重定位後不會改變。絕對表達式不得包含未指定和可重定位的值,例如標籤。
絕對表達式會評估為 64 位元整數值,並轉換為預期的運算元類型,如此處所述。
範例
x = -1
y = x + 10
可重定位表達式¶
可重定位表達式的值取決於程式重定位。
請注意,可重定位表達式的使用僅限於分支目標和 32 位元整數運算元。
可重定位表達式會評估為 64 位元整數值,這取決於運算元種類和表達式中使用的符號的重定位類型。例如,如果指令參考標籤,則此參考會評估為從指令後的位址到標籤位址的偏移量
label:
v_add_co_u32_e32 v0, vcc, label, v1 // 'label' operand is evaluated to -4
運算元與運算¶
表達式由 64 位元整數運算元和運算組成。運算元包括整數和符號。
表達式也可以使用“.”,它是對目前 PC(程式計數器)的參考。
表達式語法¶
表達式的語法如下所示
expr ::= expr binop expr | primaryexpr ;
primaryexpr ::= '(' expr ')' | symbol | number | '.' | unop primaryexpr ;
binop ::= '&&'
| '||'
| '|'
| '^'
| '&'
| '!'
| '=='
| '!='
| '<>'
| '<'
| '<='
| '>'
| '>='
| '<<'
| '>>'
| '+'
| '-'
| '*'
| '/'
| '%' ;
unop ::= '~'
| '+'
| '-'
| '!' ;
二元運算子¶
二元運算子在下表中描述。它們對 64 位元整數進行運算並產生 64 位元整數。優先級較高的運算子會先執行。
運算子
優先級
含義
*
5
*
/
5
/
%
5
%
+
4
+
-
4
-
<<
3
<<
>>
3
>>
==
2
==
!=
2
!=
<>
2
!=
<
2
<
<=
2
<=
>
2
>
>=
2
>=
|
1
|
^
1
^
&
1
&
&&
0
&&
||
0
||
一元運算子¶
一元運算子在下表中描述。它們對 64 位元整數進行運算並產生 64 位元整數。
運算子
含義
!
!
~
~
+
+
-
-
符號¶
符號是一個命名的 64 位元整數值,表示可重定位位址或絕對(不可重定位)數字。
- 符號名稱具有以下語法
[a-zA-Z_.][a-zA-Z0-9_$.@]*
下表提供了一些用於符號定義的語法範例。
語法
含義
.globl <S>
宣告一個全域符號 S,但不為其指定值。
.set <S>, <E>
將表達式 E 的值指定給符號 S。
<S> = <E>
將表達式 E 的值指定給符號 S。
<S>
宣告一個標籤 S,並將目前 PC 值指定給它。
符號可以在宣告或指定之前使用;未指定的符號假定為 PC 相關。
有關符號的其他資訊,請參見此處。
類型與大小轉換¶
本節描述當 64 位元整數、浮點數或表達式用於具有不同類型或大小的運算元時會發生什麼情況。
整數值轉換¶
指令運算元可以指定為 64 位元整數或絕對表達式。這些值使用以下步驟轉換為預期的運算元類型
1. 驗證。組譯器檢查輸入值是否可以在不丟失精度的情況下截斷為所需的截斷寬度(參見下表)。在以下兩種情況下,此操作已啟用
截斷的位元全為 0。
截斷的位元全為 1,並且截斷後的值已設定其 MSB 位元。
在所有其他情況下,組譯器會觸發錯誤。
2. 轉換。輸入值轉換為下表中描述的預期類型。根據運算元種類,此轉換由組譯器或 AMDGPU H/W(或兩者)執行。
預期類型
截斷寬度
轉換
描述
i16、u16、b16
16
num.u16
截斷為 16 位元。
i32、u32、b32
32
num.u32
截斷為 32 位元。
i64
32
{-1,num.i32}
截斷為 32 位元,然後將結果符號擴展為 64 位元。
u64、b64
32
{0,num.u32}
截斷為 32 位元,然後將結果零擴展為 64 位元。
f16
16
num.u16
使用低位 16 位元作為 f16 值。
f32
32
num.u32
使用低位 32 位元作為 f32 值。
f64
32
{num.u32,0}
使用數字的低位 32 位元作為結果的高位 32 位元;結果的低位 32 位元歸零。
已啟用轉換的範例
// GFX9
v_add_u16 v0, -1, 0 // src0 = 0xFFFF
v_add_f16 v0, -1, 0 // src0 = 0xFFFF (NaN)
//
v_add_u32 v0, -1, 0 // src0 = 0xFFFFFFFF
v_add_f32 v0, -1, 0 // src0 = 0xFFFFFFFF (NaN)
//
v_add_u16 v0, 0xff00, v0 // src0 = 0xff00
v_add_u16 v0, 0xffffffffffffff00, v0 // src0 = 0xff00
v_add_u16 v0, -256, v0 // src0 = 0xff00
//
s_bfe_i64 s[0:1], 0xffefffff, s3 // src0 = 0xffffffffffefffff
s_bfe_u64 s[0:1], 0xffefffff, s3 // src0 = 0x00000000ffefffff
v_ceil_f64_e32 v[0:1], 0xffefffff // src0 = 0xffefffff00000000 (-1.7976922776554302e308)
//
x = 0xffefffff //
s_bfe_i64 s[0:1], x, s3 // src0 = 0xffffffffffefffff
s_bfe_u64 s[0:1], x, s3 // src0 = 0x00000000ffefffff
v_ceil_f64_e32 v[0:1], x // src0 = 0xffefffff00000000 (-1.7976922776554302e308)
已停用轉換的範例
// GFX9
v_add_u16 v0, 0x1ff00, v0 // truncated bits are not all 0 or 1
v_add_u16 v0, 0xffffffffffff00ff, v0 // truncated bits do not match MSB of the result
浮點數值轉換¶
指令運算元可以指定為 64 位元浮點數。這些值使用以下步驟轉換為預期的運算元類型
1. 驗證。組譯器檢查輸入 f64 數字是否可以在沒有溢位或下溢的情況下轉換為所需的浮點數類型(參見下表)。允許精度損失。如果此轉換不可能,則組譯器會觸發錯誤。
2. 轉換。輸入值轉換為下表中描述的預期類型。根據運算元種類,這由組譯器或 AMDGPU H/W(或兩者)執行。
預期類型
所需 FP 類型
轉換
描述
i16、u16、b16
f16
f16(num)
轉換為 f16 並使用結果的位元作為整數值。該值必須編碼為字面值,否則會發生錯誤。請注意,該值不能編碼為內嵌常數。
i32、u32、b32
f32
f32(num)
轉換為 f32 並使用結果的位元作為整數值。
i64、u64、b64
-
-
已停用轉換。
f16
f16
f16(num)
轉換為 f16。
f32
f32
f32(num)
轉換為 f32。
f64
f64
{num.u32.hi,0}
使用數字的高位 32 位元作為結果的高位 32 位元;零填充結果的低位 32 位元。
請注意,結果可能與原始數字不同。
已啟用轉換的範例
// GFX9
v_add_f16 v0, 1.0, 0 // src0 = 0x3C00 (1.0)
v_add_u16 v0, 1.0, 0 // src0 = 0x3C00
//
v_add_f32 v0, 1.0, 0 // src0 = 0x3F800000 (1.0)
v_add_u32 v0, 1.0, 0 // src0 = 0x3F800000
// src0 before conversion:
// 1.7976931348623157e308 = 0x7fefffffffffffff
// src0 after conversion:
// 1.7976922776554302e308 = 0x7fefffff00000000
v_ceil_f64 v[0:1], 1.7976931348623157e308
v_add_f16 v1, 65500.0, v2 // ok for f16.
v_add_f32 v1, 65600.0, v2 // ok for f32, but would result in overflow for f16.
已停用轉換的範例
// GFX9
v_add_f16 v1, 65600.0, v2 // overflow
可重定位值轉換¶
可重定位的表達式 可以搭配 32 位元整數運算元和跳躍目標使用。
當可重定位表達式的值經由連結器解析時,會根據需要進行轉換,並截斷至運算元大小。轉換方式取決於重定位類型和運算元種類。
例如,當指令的 32 位元運算元參考一個可重定位表達式 expr 時,此參考會被評估為一個 64 位元偏移量,該偏移量是以位元組計算,從指令之後的位址到被參考的位址。然後,該值會被截斷為 32 位元並編碼為字面值。
expr = .
v_add_co_u32_e32 v0, vcc, expr, v1 // 'expr' operand is evaluated to -4
// and then truncated to 0xFFFFFFFC
再舉一個例子,當分支指令參考一個標籤時,此參考會被評估為一個偏移量,該偏移量是以雙字組計算,從指令之後的位址到標籤位址。然後,該值會被截斷為 16 位元。
label:
s_branch label // 'label' operand is evaluated to -1 and truncated to 0xFFFF