【轉】AMD 的 XOP 指令集編碼內幕
X86s咱只能說和3DNOW! FMA3 FMA4 SSE4A XOP一樣沒用,除非IA兩家都同意支持然后這東西還得有明顯的性能提升讓大量軟件非用不可,那沒準有可能像AVX一樣十年八年以后能推下去,不然這東西又不像VT-X一樣不用渾身難受軟件憑啥放棄對老硬件的支持去縮小受眾,像EM64T一樣可有可無或者AVX512一樣實現代價巨大那就是推不動
AMD 的 XOP 指令集編碼內幕
返回
目 錄
1.?XOP 與 FMA4 指令集簡介
2.?XOP 指令編碼格式
3.?XOP prefix
4.?FMA4/XOP 指令 opcode 描述方式
5.?FMA4/XOP 指令 operands 的尋址
6.?FMA4/XOP 指令解析
?
附錄:?AVX 與 XOP 指令集中的 registers 編碼反相
XOP 與 FMA4 指令簡介
1、 XOP 指令產生的背景
??AMD 搶出推出 SSE5 指令集,但 Intel 打著如意算盤,卻不跟進,推出了全新的 AVX 指令集。
??AVX 借鑒了一些 SSE5 的思想,但進行了擴充改良。客觀地說,AVX 比 SSE5 更優(yōu),但 SSE5 既然有 Intel 值得學習的地方,AMD 是知道的。
??AMD 最終決定放棄 SSE5 指令集跟進 Intel,除發(fā)布兼容 AVX 指令集的 FMA4 指令外,另外推出一套 XOP 指令集。但是 AMD 的 FMA4 指令只是對 AVX 指令集有限支持。
??XOP 指令集的產生是 AMD 也不愿 SSE5 被全盤推翻,保留了一些 SSE5 指令的優(yōu)秀的地方。
2、 AMD 的 FMA4 指令與 Intel 的 AVX 指令的關系
FMA4 指令是 FMA 指令的 AMD 版本。
可以說 AMD 的 FMA4 與 Intel 的 AVX 指令(包括 Intel 的 FMA 指令)在編碼方式上大同小義,差異很小。
即可說:FMA4 指令沿用 AVX 指令的編碼方式,并進行一些修改與擴充。
AMD 的 FMA4 指令與 Intel 的 AVX 指令(包括 Intel 的 FMA 指令)區(qū)別就象是:AMD 的 SSE 指令與 Intel 的 SSE 指令之間的區(qū)別。
也就是說:Intel 的 AVX 中的 FMA 指令有的,AMD 的 FMA4 可能會有,可能不會有。而 AMD 有的,Intel 不會有。
3、 XOP 指令集的特點
可以說 XOP 指令集編碼方案是基于 AVX 指令集的。只是有些修改。當然 XOP 指令集有自已的特點。
(1)在 XOP 指令中使用 XOP prefix 代替 VEX prefix
說白了,在 XOP 中稱為 XOP prefix 而不是 VEX prefix,但并不是簡單的名稱不同,雖然編碼方案一樣,但內容差異很大。
(2)XOP prefix 固定為 3-byte,并沒有 2-byte 的 XOP prefix
(3)XOP 指令的改良主要體現在 operands 的尋址上,XOP 指令的 operands 尋址更靈活強大。
4、 XOP 指令與 AVX 指令的區(qū)別
XOP 與 AVX 之間的區(qū)別就像是: AMD 的 3Dnow 指令與 Intel 的 SSE 指令之間的區(qū)別。
XOP 是 AMD 自已推出的另一套指令。這是 Intel 目前不具備的。
而 Intel 的 AVX 指令 AMD 則進行了有限的支持。
?
上圖是 XOP 指令編碼格式,這和 AVX 指令編碼序列是一樣的,只是 XOP prefix 不同而已。
1、 legacy prefix 部分
這些是原來的 prefix,即:
effective opernad-size override prefix:66
effective address-size override prefix:67
effective segment override prefix:2E、3E、26、64、65、36
lock prefix:F0
rep/repz prefix:F3
repz prefix:F2
但是,和 AVX 指令情形一樣,在 XOP 指令序列里,僅有 address-size override prefix 和 segment override prefix 才有效。
其它 legacy prefix 與 XOP prefix 同時出現會產生 #UD 異常。
2、 XOP prefix 部分
XOP prefix 集成了 SIMD prefix 與 REX prefix,但是在 XOP 指令中并不需要 escape prefix。
XOP prefix 固定為 3-byte 而第 1 個 byte 固定為?8F
XOP prefix 的作用為:
提供 registers 尋址
集成 REX prefix 與 escape prefix
對 opcode 的補充
指明 operands 的 size
3、 opcode 部分
除了是 XOP 指令的 opcode 部分外,還提供操作數據的 size
4、ModRM 部分
和通用指令中的 ModRM 意義一樣,提供 operands 尋址
5、 SIB 部分
和通用指令中的 SIB 意義一樣。提供 memory 尋址。
6、 displacement 部分
和通用指令中的 displacement 意義一樣,提供 displacement 值。
7、 immediate 部分
除了提供 immediate 值外,主要的作用是提供 registers 尋址。
imme[7:4] 提供 registers 尋址。
上面的 XOP prefix 的結構圖。
XOP prefix 共有 3 bytes,其中 first byte 是?8F,記作: XOP.8F
?
1、XOP.8F
XOP prefix 的第 1 個字節(jié)了是 8F,在通用指令里 opcode 8F 是一組 Group opcode,僅當 ModRM.reg = 000 時,這個 opcode 才是有效的,它是 POP 指令。
ModRM.reg ≠ 000 時,這個 opcode 8F 是無效的 opcode,即:當 ModRM 值大于等于 00-001-000(08H)時, 這個 8F 是無效的 opcode
AMD 選擇使用 8F 作為 XOP prefix,正是基于這個原因。
?
(1)XOP prefix 與 VEX prefix 的對比
VEX prefix 是 C4 或 C5,在 16 位 或 32 位下它必須保證下一個字節(jié)是以 11-XXXXXX 開頭的。
XOP prefix 是 8F,則需保證下一個字節(jié)是大于等于 08H?則可
關于 VEX prefix 詳見:VEX prefix
由于,這個 prefix 的取值不同,就決定了它們之間的編碼差異。
?
?
2、 XOP prefix 的 byte 1 結構
域
位
描述
R
[7]
[XOP.R + ModRM.reg]
X
[6]
[XOP.X + SIB.index]
B
[5]
[XOP.B + SIB.base],[XOP.B + ModRM.r/m] 以及 [XOP.B + opcode.reg]
mmmmm
[4:0]
= 08
表示指令需要 imm8 字節(jié)
= 09
表示指令不需要 imm8 字節(jié)
XOP.RXB 與 VEX.RXB 作用一致,這一位也是反相作用。 分別用于擴展 ModRM.reg、SIB.index 以及 ModRM.r/m、SIB.base、opcode.reg
例如:當 XOP.R = 1、ModRM.reg = 000 時,register ID 值為 1000 表示 xmm0 寄存器。
XOP.mmmmm 指示 imm8 部分是否存在,另一個作用是表明 opcode 是 XOP 指令:ModRM >= 08H
有關 registers 編碼反相,詳見:AVX 和 XOP 指令中的 registers 編碼反相
?
3、XOP prefix 的 byte 2 結構
域
位
描述
W
[7]
在 XOP/FMA4 指令中主要作用是:對 operands 尋址進行配置
vvvv
[6:3]
提供 retisters 尋址,具體是哪個 operand 依賴于 opcode
L
[2]
operands 長度(xmm or ymm?)
pp
[1:0]
00
none
01
66
10
F3
11
F2
XOP.vvvv 提供的 registers 尋址依賴于 XOP.W 配置。
有關 XOP.vvvv 尋址,詳見:operands 尋址
?
?
4、XOP.RXB 與 VEX.RXB 的差異
在 AVX 指令的 VEX prefix 中,VEX.RXB 在 legacy 模式與 long 的 compaitibility 模式下必須: VEX.RXB = 11X(以 11 開頭)
而 XOP 指令的 XOP prefix 中,XOP.RXB 則在 legacy 模式與 long 的 compaitibility 模式下不必為 11 開頭
前面已經說過,這是因為:opcode 8F 僅當 ModRM.reg = 000 時才有效。因此,只要大于等于 08H,就能區(qū)分通用指令與 XOP 指令。
?
XOP 指令以下這條指令為例:
vpmacsdd xmm0, xmm7, [eax], xmm1
它的 opcode 是 9e,在?32 位模式下,它的編碼結構如下:
8f
101
01000
0
1000
0
00
9e
00
000
000
0001
0000
XOP.8F
RXB
mmmmm
W
vvvv
L
pp
opcode
mod
reg
r/m
[7:4]
[3:0]
XOP.[RXBmmmmm] =?a8
XOP.[WvvvvLpp] =?40
ModRM =?00
imm8 =?10
它最終的編碼為:8f a8 40 9e 00 10
?
?
5、Intel 的 FMA 指令中 VEX.W 與 AMD 的 FMA4 指令中 VEX.W 的差異
對于 W 標志位, AMD 與 Intel 存在設計理念的差異。
?
(1)Intel 的 FMA 指令中 VEX.W 主要作用是選擇指令處理數據的不同,從而根據不同的數據產生不同的指令,例如:
vfmadd132ps?xmm0, xmm1, xmm2
vfmadd132pd?xmm0, xmm1, xmm2
上面是 2 個版本的指令,它們的?opcode 碼是相同的
第 1 條的 VEX.W = 0
第 2 條的 VEX.W = 1
它們處理的數據分別是?packed single-precision float-point 數據和?packed double-precision float-point?數據
當 VEX.W = 0 是處理 packed single-precision float point 數據
當 VEX.W = 1 是處理 packed double-precision float point 數據。
?
?
(2)AMD 的 FMA4 指令中 XOP.W 主要作用對 operands 尋址進行配置,例如:
vfmaddpd?xmm1, xmm2,?[rax], xmm4
vfmaddpd?xmm1, xmm2,?xmm3, [rax]
上面是 2 個版本的 vfmaddpd 指令,它們處理的是 packed double-precision float point 數據。
第 1 條的 VEX.W = 0
第 2 條的 VEX.W = 1
當 XOP.W = 0 時, ModRM.r/m 提供 third operand(即:src2)尋址。
當 XOP.W = 1 時, ModRM.r/m 提供 fourth operand(即:src3)尋址。
?
再來看一看,下面兩條 FMA4 指令:
vfmaddps?xmm1, xmm2,?[rax], xmm4
vfmaddps?xmm1, xmm2,?xmm3, [rax]
上面是 2 個版本的 vfmaddps 指令,它們處理的是 packed singled-precision float point 數據。
這兩條指令和上面兩條指令的?opcode 是不同的。
Intel 的設計理念是:采用相同的 opcode 碼,而根據 VEX.W 的取值不同,從而達到指令處理多種數據。
AMD 的設計理念是:采用不同的 opcode 碼,達到指令處理多種數據。又而根據 VEX.W 的取值不同,而達到 operand 尋址的多樣性。
AMD 的設計上允許 operand 的多樣性,達到真正的 4 個 operands
而 Intel 的指令不支持 4 個 operands。
這就是為什么 Intel 的是 FMA 指令,而 AMD 的是 FMA4 指令的原因。
1、FMA4 指令的 opcode 描述
由于 FMA4 指令是 FMA 指令的 AMD 版本,支持 4 個操作數。
vfmaddpd xmm1, xmm2, xmm3/mem128, xmm4
上面這條指令形式,它的 opcode 描述為:
VEX? RXB.mmmmm? W.vvvv.L.pp?? Opcode
C4???? RXB.03?? 0.xsrc1.0.01? 69 /r /is4
可以很直觀的看出:
VEX.C4
VEX.mmmmm = 11
VEX.W = 0
VEX.vvvv 對 src1 進行尋址
VEX.L = 0
VEX.pp = 01
opcode = 69
imm8[7:4] 提供尋址
?
(1)operands 尋址表
這條指令有 4 個 operands,這 4 個 operands 的尋址情況是:
ModRM.reg
VEX.vvvv
ModRM.r/m
imm8[7:4]
提供 first operand 尋址
提供 second operand 尋址
提供 third operand 尋址
提供 fouth operand 尋址
/r:表示 destination operand(first operand)由 ModRM.reg 提供尋址。
?
?
2、XOP 指令的 opcode 描述
vphaddbd xmm1, xmm2/mem128
這是一條 XOP 指令,它的 opcode 描述為:
XOP??? RXB.mmmmmm??? W.vvvv.L.pp??? Opcode
8F???? RXB.09??????? 0.1111.0.00??? c2 /r
8F:這是 XOP prefix
XOP.mmmmmm = 09 : 表示不需要 imm8
XOP.W = 0 :2 個 operands 時為 0
XOP.vvvv = 1111 :表示不需要 XOP.vvvv 提供尋址,它必須為 1111
XOP.L = 0 : 128 位
XOP.pp = 00 :不需要 SIMD prefix
opcode = c2
/r :ModRM.reg 提供 destination operand 尋址
?
(2)operands 尋址表
這條指令只有 2 個 operands,那么它的尋址就簡單多了
ModRM.reg
VEX.vvvv
ModRM.r/m
imm8[7:4]
提供 first operand 尋址
不需要,必須為 1111
提供 second operand 尋址
不需要
只有 2 個 operands,它不需要 imm8 字節(jié)。
?
隨著 Opcode 的復雜化,無論是 Intel 還是 AMD 的 opcode 描述,都是旨在使用很容易對 Opcode 掌握清楚。
相對比通用指令集中的 opcode 描述要復雜。關于通用指令的 opcode 描述,詳見:指令 opcode 碼
AMD 的 XOP/FMA4 指令 operands 最多可以 4 個 operands,因此要分開下以幾種情況描述
XOP/FMA4 指令的 operands 尋址很大程度上依賴于 XOP.W 和 VEX.W 的取值。
?
1、 4 個 operands 的尋址情況
像以下這個 FMA4 指令的 2 種尋址模式
???????????????????????????????????????????????VEX??? RXB.mmmmmm??? W.vvvv.L.pp??? Opcode
vfmaddpd xmm1, xmm2,?xmm3/mem128, xmm4???????? c4???? RXB.03????????0.xsrc1.0.01?? 69 /r /is4
?
???????????????????????????????????????????????VEX??? RXB.mmmmmm??? W.vvvv.L.pp??? Opcode
vfmaddpd xmm1, xmm2,?xmm3, xmm4/mem128???????? c4???? RXB.03????????1.xsrc1.0.01?? 69 /r /is4
AMD 定義的 operands 尋址模式表:
VEX.W/XOP.W
ModRM.reg
VEX.vvvv/XOP.vvvv
ModRM.r/m
imm8[7:4]
0
dest
src1
src2
src3
1
dest
src1
src3
src2
當 VEX.W/XOP.W = 0 時:ModRM.r/m 提供 src2 operand(即:third operand)尋址,而 imm8[7:4] 則提供 src3(即:fourth operand)尋址。
當 VEX.W/XOP.W = 1 時:ModRM.r/m 提供 src3 operand(即:fourth operand)尋址,而 imm8[7:4] 則提供 src2(即:third operand)尋址。
而 dest operand(即:first operand)固定由 ModRm.reg 提供尋址。
src1 operand(即:second operand)固定由 VEX.vvvv/XOP.vvvv 提供尋址。
?
那么,指令?vfmaddpd?的 2 種尋址模式如下:
vfmaddpd xmm1, xmm2, xmm3/mem128, xmm4
???????? ----? ----? -----------? ----
????????? |???? |???????? |???????? |
????????? +-----|---------|---------|---------------->? ModRM.reg
??????????????? |???????? |???????? |?
??????????????? +---------|---------|---------------->? VEX.vvvv
????????????????????????? |???????? |
????????????????????????? +---------|---------------->? ModRM.r/m
??????????????????????????????????? |
??????????????????????????????????? +---------------->? imm8[7:4]
vfmaddpd xmm1, xmm2, xmm3, xmm4/mem128
???????? ----? ----? ----? -----------
????????? |???? |???? |???????? |
????????? +-----|-----|---------|------------------->? ModRM.reg
??????????????? |???? |???????? |?
??????????????? +-----|---------|------------------->? VEX.vvvv
????????????????????? |???????? |
????????????????????? +---------|------------------->? imm8[7:4]
??????????????????????????????? |
??????????????????????????????? +------------------->? ModRM.r/m
實際上,很容易看出 xmm3/mem128 這個 operands 到底是由誰提供尋址。
因為,指令中 xmm3/mem128?既可 register 也可以 memory,那么它只能由 ModRM.r/m 提供尋址,這是肯定的。
?
?
?
2、 3 個 operands 的尋址情況
下面是某條 XOP 指令的 opcode 描述:
?????????????????????????????????????? XOP??? RXB.mmmmmm??? W.vvvv.L.pp??? Opcode
vprotb xmm1, xmm2/mem128, xmm3???????? 8f???? RXB.09????????0.xcnt.0.00??? 90 /r
?
?????????????????????????????????????? XOP??? RXB.mmmmmm??? W.vvvv.L.pp??? Opcode
vprotb xmm1, xmm2, xmm3/mem128???????? 8f???? RXB.09????????1.xcnt.0.00??? 90 /r
?
?????????????????????????????????????? XOP??? RXB.mmmmmm??? W.vvvv.L.pp??? Opcode
vprotb xmm1, xmm2/mem128, imm8???????? 8f???? RXB.08????????0.1111.0.00??? c0 /r /ib
對于 3 個 operands 都是 register 的情況下:
XOP.W
ModRM.reg
XOP.vvvv
ModRM.r/m
0
dest
src2
src1
1
dest
src1
src2
?
對于,第 3 個 operand 是 imm8 的情況下:
XOP.W
ModRM.reg
XOP.vvvv
ModRM.r/m
imm8
0
dest
1111
src1
src2
這種情況下,XOP.vvvv 必須為 1111,指示指令不需要 XOP.vvvv 尋址,而 src2 則由 imm8 提供立即數。
那么,這條指令的 3 種尋址模式是:
vprotb xmm1, xmm2/mem128, xmm3
?????? ----? -----------? ----
??????? |??????? |???????? |
??????? +--------|---------|----------------------->? ModRM.reg
???????????????? |???????? |
???????????????? +---------|----------------------->? ModRM.r/m
?????????????????????????? |
?????????????????????????? +----------------------->? XOP.vvvv
?
vprotb xmm1, xmm2, xmm3/mem128
?????? ----? ----? -----------
??????? |???? |???????? |
??????? +-----|---------|-------------------------->? ModRM.reg
????????????? |???????? |
????????????? +---------|-------------------------->? XOP.vvvv
??????????????????????? |
??????????????????????? +-------------------------->? ModRM.r/m
?
vprotb xmm1, xmm2/mem128, imm8
?????? ----? -----------? ----
??????? |??????? |???????? |
??????? +--------|---------|----------------------->? ModRM.reg
???????????????? |???????? |
???????????????? +---------|----------------------->? ModRM.r/m
?????????????????????????? |
?????????????????????????? +----------------------->? imm8 (XOP.vvvv = 1111)
?
?
?
3、2 個 operands 的尋址情況
像下面這條 XOP 指令:
????????????????????????????????? XOP??? RXB.mmmmmm??? W.vvvv.L.pp??? Opcode
vfrczpd xmm1, xmm2/mem128???????? 8f???? RXB.09??????? 0.1111.0.00??? 81 /r
它的 operands 尋址情況是:
XOP.W
ModRM.reg
XOP.vvvv
ModRM.r/m
0
dest
1111
src
?
那么這條指令的 operand 是:
vfrczpd xmm1, xmm2/mem128
??????? ----? -----------
???????? |??????? |??????
???????? +--------|--------------------------->? ModRM.reg
????????????????? |????????
????????????????? +--------------------------->? ModRM.r/m? (XOP.vvvv = 1111)
?
?
4、FMA4/XOP 指令的 operands 尋址總結
(1)destination operand(first operand)由 ModRM.reg 提供尋址。
(2)而指令的 src1 和 src2 以及 src3 根據 VEX.W/XOP.W 的取值不同,以及指令的 operands 個數而不同。
以上一節(jié)的幾條指令為例,說一說 FMA4/XOP 指令的解析
?
1、 FMA4 指令的解析
(1)有以下指令:
vfmaddpd xmm1, xmm9, [rax], xmm10
接上節(jié),它的 opcode 描述是:
?????????????????????????????????????????????? VEX??? RXB.mmmmmm??? W.vvvv.L.pp??? Opcode
vfmaddpd xmm1, xmm2, xmm3/mem128, xmm4???????? c4???? RXB.03??????? 0.xsrc1.0.01?? 69 /r /is4
將指令分解為:
c4
101
00011
0
0110
0
01
69
00
001
000
1010
0000
VEX.C4
VEX.RXB
VEX.mmmmm
VEX.W
VEX.vvvv
VEX.L
VEX.pp
opcode
mod
reg
r/m
VEX.[RXBmmmmm] =?a3
VEX.[WvvvvLpp] =?31
ModRM =?08
imm8 =?a0
那么,它的編碼是:c4 a3 31 69 08 a0
?
?
(2)將它的 operands 改變一下為:
vfmaddpd xmm1, xmm9, xmm10, [rax]
將指令為解為:
c4
101
00011
1
0110
0
01
69
00
001
000
1010
0000
VEX.C4
VEX.RXB
VEX.mmmmm
VEX.W
VEX.vvvv
VEX.L
VEX.pp
opcode
mod
reg
r/m
VEX.[RXBmmmmm] =?a3
VEX.[WvvvvLpp] =?b1
ModRM =?08
imm8 =?a0
那么,它的編碼是:c4 a3 b1 69 08 a0
?
可以看出:上面兩個例子中,僅僅只有 VEX.W 不同而已,其它是完全相同的。
對于 memory 尋址,所有的通用指令中的 memory 尋址修飾都可以使用在這里,即:可以作?address-size override?以及?segment override
?
?
?
2、 XOP 指令解析
(1)3 個 operands 的指令
舉上節(jié)中的例子:
(1) vprotb xmm8, [rax], xmm0
(2) vprotb xmm0, xmm10, [rax]?
(3) vprotb xmm0, [rax], 1
指令1 的分解部分為:
8f
001
01001
0
1111
0
00
90
00
000
000
XOP.8F
XOP.RXB
XOP.mmmmm
XOP.W
XOP.vvvv
XOP.L
XOP.pp
opcode
mod
reg
r/m
XOP.[RXBmmmmm] =?29
XOP.[WvvvvLpp] =?78
ModRM =?00
它的最終編碼是:?8f 29 78 90 00
?
指令2 的分解部分為:
8f
101
01001
1
0101
0
00
90
00
000
000
XOP.8F
XOP.RXB
XOP.mmmmm
XOP.W
XOP.vvvv
XOP.L
XOP.pp
opcode
mod
reg
r/m
XOP.[RXBmmmmm] =?a9
XOP.[WvvvvLpp] =?a8
ModRM =?00
它的最終編碼是:?8f a9 a8 90 00
?
指令3 的分解部分為:
8f
101
01000
0
1111
0
00
c0
00
000
000
01
XOP.8F
XOP.RXB
XOP.mmmmm
XOP.W
XOP.vvvv
XOP.L
XOP.pp
opcode
mod
reg
r/m
XOP.[RXBmmmmm] =?a8
XOP.[WvvvvLpp] =?78
ModRM =?00
imm8 =?01
它的最終編碼是:?8f a8 78 c0 00 01
?
?
(2)2 個 operands 的指令
(1)vfrczpd xmm1, xmm2
(2)vfpczpd xmm1, [rax]
指令1 的分解部分為:
8f
101
01001
0
1111
0
00
81
11
001
010
XOP.8F
XOP.RXB
XOP.mmmmm
XOP.W
XOP.vvvv
XOP.L
XOP.pp
opcode
mod
reg
r/m
XOP.[RXBmmmmm] =?a9
XOP.[WvvvvLpp] =?78
ModRM =?ca
它的編碼是:8f a9 78 81 ca
?
指令2 的分解部分為:
8f
101
01001
0
1111
0
00
81
00
001
000
XOP.8F
XOP.RXB
XOP.mmmmm
XOP.W
XOP.vvvv
XOP.L
XOP.pp
opcode
mod
reg
r/m
XOP.[RXBmmmmm] =?a9
XOP.[WvvvvLpp] =?78
ModRM =?08
它的編碼是:8f a9 78 81 08