返回目 录
1.
XOP 与 FMA4 指令集简介2.
XOP 指令编码格式3.
XOP prefix4.
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 更优,但 SSE5 既然有 Intel 值得学习的地方,AMD 是知道的。
AMD 最终决定放弃 SSE5 指令集跟进 Intel,除发布兼容 AVX 指令集的 FMA4 指令外,另外推出一套 XOP 指令集。但是 AMD 的 FMA4 指令只是对 AVX 指令集有限支持。
XOP 指令集的产生是 AMD 也不愿 SSE5 被全盘推翻,保留了一些 SSE5 指令的优秀的地方。
2、 AMD 的 FMA4 指令与 Intel 的 AVX 指令的关系
FMA4 指令是 FMA 指令的 AMD 版本。
可以说 AMD 的 FMA4 与 Intel 的 AVX 指令(包括 Intel 的 FMA 指令)在编码方式上大同小义,差异很小。
即可说:FMA4 指令沿用 AVX 指令的编码方式,并进行一些修改与扩充。
AMD 的 FMA4 指令与 Intel 的 AVX 指令(包括 Intel 的 FMA 指令)区别就象是:AMD 的 SSE 指令与 Intel 的 SSE 指令之间的区别。
也就是说: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 指令的区别
XOP 与 AVX 之间的区别就像是: AMD 的 3Dnow 指令与 Intel 的 SSE 指令之间的区别。
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 个字节了是 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 位下它必须保证下一个字节是以 11-XXXXXX 开头的。
XOP prefix 是 8F,则需保证下一个字节是大于等于 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 字节
= 09
表示指令不需要 imm8 字节
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,就能区分通用指令与 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 字节。
随着 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 个数而不同。
以上一节的几条指令为例,说一说 FMA4/XOP 指令的解析
1、 FMA4 指令的解析
(1)有以下指令:
vfmaddpd xmm1, xmm9, [rax], xmm10
接上节,它的 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 的指令
举上节中的例子:
(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