5、operands 的寻址
AVX 能够支持到 4 个 operands。因此,operands 寻址依靠以下几个域来提供:
* VEX.vvvv:提供对 dest、src1 以及 src2 寄存器操作数的寻址。
* ModRM.reg:也可提供对 dest、src1 以及 src2 寄存器操作数的寻址。
* ModRM.r/m:除了提供对 dest、src1 以及 src2 的寄存器操作数寻址外,还可提供对内存操作数的寻址。
* imme[7:4]:提供对第 4 个寄存器操作数的寻址(也就是 src3 寄存器操作数)
-------------------------------------------------------------------------------------------
所有的 operands 寻址就是依靠这几个域的组合,这 4 个域提供了丰富的组合模式。imme 字节的 bit7 ~ bit4 被用来提供额外的 第 4 个寄存器操作数。
值得注意的是:
在 AVX 指令中寄存器 ID 值都是与原来的寄存器 ID 相反的。
编码 AVX 指令 原来指令
--------------------------------------------------
1111 => xmm0/ymm0 xmm15
1110 => xmm1/ymm1 xmm14
... ...
0001 => xmm14/ymm14 xmm1
0000 => xmm15/ymm15 xmm0
----------------------------------------------------------------------------------------
1、以下面指令为例,这是一条全 4 个 operands 的指令。
指令:
vblendvpd ymm1, ymm2, ymm3/m256, ymm4
----------------------------------------------------------
这条指令的描述为:
VEX.NDS.256.66.0F3A 4B /r /is4
2、AVX.vvvv 提供的寻址
这条指令 AVX.vvvv 提供的寻址是 VEX.NDS,也就是 AVX.vvvv 提供 src1 (第 1 个源操作数),即:第 2 个操作数。
上面指令中的 ymm2 由 AVX.vvvv 负责提供。
3、ModRM.reg 提供的寻址
上面指令中的 ymm1 由 ModRM.reg 提供。当 AVX.vvvv 提供 src1 的寻址,dest 的寻址由 ModRM.reg 提供。
4、ModRM.r/m 提供的寻址
上面指令中的 src2 操作数是 ymm3/m256 寻址,它可以是 registers 或者 memory 操作数。因此,它必须由 ModRM.r/m 提供。
5、imme[7:4] 提供的寻址
最后一个操作数 ymm4 必须由 imme[7:4] 提供。
总结:
例1:
vblendvpd ymm1, ymm2, ymm3/m256, ymm4
----- ------ ------------ ------
| | | |
+-------+--------+----------+-----------> dest: ModRM.reg(registers)
| | |
+--------+----------+-----------> src1: VEX.vvvv(VEX.NDS)
| |
+----------+-----------> src2:ModRM.r/m(register/memory)
|
+-----------> src3:imme[7:4](registers)
vblendvpd 的操作数是 VEX.NDS (VEX.vvvv 作为第 1 个源操作数),因此 VEX.vvvv 提供 src1 操作数,而 src2 操作数是 ymm3/m256,是一个 registers/memory 类型,因此由 ModRM.r/m 提供。那么 dest 则由 ModRM.reg 提供,最后 1 个操作数则由 imme[7:4] 来提供。
例2: vpslldq xmm1, xmm2, imm8
------ ------ -----
| | |
+------+------+-------------------> dest: VEX.vvvv(VEX.NDD)
| |
+------+-------------------> src1: ModRM.r/m
|
+------------------> src2: imm8(immediate)
vpslldq 指令的操作数表述为 VEX.NDD(VEX.vvvv 作为 dest 操作数),因此 VEX.vvvv 提供 dest 操作数,而 src1 由 ModRM.r/m 提供,是因为 ModRM.reg 要对 vpslldq 指令的 opcode 进行补充定义。ModRM.reg 不提供操作数寻址。
最后一个操作数是个立即数寻址,即 1 byte 的 immediate 。
vpslldq xmm1,xmm2,imm8 的指令描述如下:
* VEX.NDD.128.66.0F 73 /7 ib
-------------------------------------
意即:VEX.vvvv 提供 dest 寻址,属于 VEX.128(VEX.L = 0)128 位操作数,66 是 SIMD prefix,escape prefix 是 0F。
opcode 是 73 ,但是要由 ModRM.reg 来补充定义,也就是 /7 表示:ModRM.reg = 111(/7)。
ib 是最后操作数,它是一个立即数,imme8
例3: vlddqu ymm1, m256
------ ------
| |
+-------+-----------------> dest: ModRM.reg(registers)
|
+-----------------> src1: ModRM.r/m (memory)
vlddqu 指令的描述是:
* VEX.256.F2.0F F0 /r
---------------------------------
此时,VEX.vvvv 不提供任何操作数的寻址(无 NDS、NDS 以及 DDS),那么 VEX.vvvv 必须为 1111,否则会产生 #UD 异常。
VEX.256 (VEX.L = 1)操作数为 256 位。SIMD prefix 为 F2,escape prefix 为 0F
opcode 为 F0。
这条指令的 dest 则要由 ModRM.reg 来寻址,src 则要由 ModRM.r/m 来寻址。