在里面
MOVMSKPD reg, xmm
,
VMOVMSKPD reg, xmm2
或
VMOVMSKPD reg, ymm2
我认为reg是r32或r64。
但在MASM中,我进行了测试,得到了以下结果:
MOVMSKPD rbx, xmm0 ;OK, 66| 48/ 0F 50 D8
MOVMSKPD ebx, xmm0 ;OK, 66| 0F 50 D8
我怀疑这个结果是否正确,尤其是因为它有“48前缀”。48小时是具有W位ON的REX前缀。
相反,以下代码编码在完全相同的机器代码中,每个代码都带有VEX。W位为零。
000004F9 C5 F9/ 50 D8 VMOVMSKPD rbx, xmm0
000004FD C5 F9/ 50 D8 VMOVMSKPD ebx, xmm0
所有这些代码编码正确吗?
我使用了ml64.exe。目标是x86_64(64-BIT模式)。
[test2.asm]
;MOVMSKPD reg, xmm ;66 0F 50 /r
MOVMSKPD rbx, xmm0 ;OK, with a 48 prefix
MOVMSKPD ebx, xmm0 ;OK, without a 48 prefix
;VMOVMSKPD reg, xmm2 ;VEX.128.66.0F.WIG 50 /r
VMOVMSKPD rbx, xmm0 ;OK
VMOVMSKPD ebx, xmm0 ;OK, but the same machine code as above.
;VMOVMSKPD reg, ymm2 ;VEX.256.66.0F.WIG 50 /r
VMOVMSKPD rbx, ymm0 ;OK
VMOVMSKPD ebx, ymm0 ;OK, but the same machine code as above.
[测试2.lst]
;MOVMSKPD reg, xmm ;66 0F 50 /r
000004F0 66| 48/ 0F 50 D8 MOVMSKPD rbx, xmm0
000004F5 66| 0F 50 D8 MOVMSKPD ebx, xmm0
;VMOVMSKPD reg, xmm2 ;VEX.128.66.0F.WIG 50 /r
000004F9 C5 F9/ 50 D8 VMOVMSKPD rbx, xmm0
000004FD C5 F9/ 50 D8 VMOVMSKPD ebx, xmm0
;VMOVMSKPD reg, ymm2 ;VEX.256.66.0F.WIG 50 /r
00000501 C5 FD/ 50 D8 VMOVMSKPD rbx, ymm0
00000505 C5 FD/ 50 D8 VMOVMSKPD ebx, ymm0
关于操作数大小重写前缀(0x66)。
在“英特尔手册PDF”中,我发现一句话:“此前缀与MMX、SSE和/或SSE2指令一起使用是保留的,可能会导致不可预测的行为。”
http://gec.di.uminho.pt/Discip/Lesi/AC10203/docs/P4ISAformat.pdf
第2章指令格式
2.2.指令前缀
操作数大小重写前缀允许程序在16位和32位操作数大小之间切换。
任意一个操作数大小都可以是默认值。此前缀选择非默认大小。
此前缀与MMX、SSE和/或SSE2指令一起使用是保留的,可能会导致不可预测的行为(请参阅下面的注释)。
注释
一些SSE和SSE2指令具有三字节操作码。
对于这三个字节的操作码,第三操作码字节可以是F2H、F3H或66H。
例如,SSE2指令CVTQ2PD具有三字节操作码F3 0F E6。
这三个字节操作码中的第三个操作码字节不应被视为前缀,即使它与操作数大小前缀(66H)或重复前缀之一(F2H和F3H)具有相同的编码。
如上所述,保留将操作数大小和重复前缀与SSE和SSE2指令一起使用。
还应注意的是,在不支持SSE2的英特尔处理器上执行SSE2指令(CPUID功能标志寄存器EDX位26已清除)将导致不可预测的代码执行。
我认为REX。REX前缀的W比特类似于66前缀。
所以我怀疑REX。W位只能在旧式指令中使用,不能在MMX、SSE和/或SSE2指令中自由使用(自行判断)。
我认为在MMX/SSE/AVX指令中,如果REX,它可以安全地使用。W写在指令表的操作码列中,但如果是REX。W不是写在那里的,它不能用来自我判断。
我认为如下:
-
在传统指令中,可以使用REX。W位对于GPR几乎是自由的,尤其是对于目标操作数的大小。
-
在MMX/SSE/SSE2/AVX/AVX2/AVX512中,不能使用REX。W自由位。
PS1,2023/07/2401:38,JST
AMD手册:AMD 64位技术,24108C-2001年1月
结果的零扩展。
在64位模式中,当使用GPR目标执行32位操作时,处理器零将32位结果扩展到完整的64位目标。
对GPR的8位和16位操作保留目的地GPR的所有未写入的高位。
这与部分宽度结果的传统16位和32位语义一致。
英特尔手册:
MOVMSKPD提取压缩双精度浮点符号掩码
Operation
(V)MOVMSKPD (128-bit Versions)
DEST[0] := SRC[63]
DEST[1] := SRC[127]
IF DEST = r32
THEN DEST[31:2] := 0;
ELSE DEST[63:2] := 0;
FI
VMOVMSKPD (VEX.256 Encoded Version)
DEST[0] := SRC[63]
DEST[1] := SRC[127]
DEST[2] := SRC[191]
DEST[3] := SRC[255]
IF DEST = r32
THEN DEST[31:4] := 0;
ELSE DEST[63:4] := 0;
FI
在上文中,请注意以下内容
IF DEST = r32
THEN DEST[31:2] := 0;
ELSE DEST[63:2] := 0;
FI
但根据AMD手册,在64-BIT模式下,如果目的地是32-BIT通用寄存器(GPR),则底层64-BIT GPR的上部32个BIT被清零。
但根据英特尔手册,如果reg为32-BIT,则DEST[31:2]:=0;如果reg为64-BIT,那么DEST[63:2]:=0。
我认为如果它使用REX遵循AMD的一般规则,这是不一致的。W位。
如果它遵循AMD一般规则,如果目的地是32-BIT,则底层寄存器的高32位被清零,从而DEST[63:2]:=0。如果它是正确的,在手册中,写
IF DEST = r32
THEN DEST[31:2] := 0;
ELSE DEST[63:2] := 0;
FI
没有意义,因为在这两种情况下,DEST[63:2]:=0。
我的观点是“假设一切都是正确的”,如果指令
MOVMSKPD ebx, xmm0
存在于64-BIT模式中,则它不服从AMD的一般规则,因此它是不一致的。
我使用了“矛盾证明”或荒诞还原的方法。
ps22023/07/24,03:05,JST
我认为:
reg is r32 if cpu is in 32-BIT mode (compatible mode).
reg is r64 if cpu is in 64-BIT mode (long mode).
并且它不能被REX控制。W位或VEX。W位。
我认为没有指示
MOVMSKPD ebx,xmm0
64-BIT模式或“英特尔手册”中的“操作伪码”在目标寄存器的高32位中不正确。根据AMD的一般规则,当CPU处于64-BIT模式时,如果目标操作数是32-BIT GPR,则底层64-BIT GPR的高32位被清零,但《英特尔手册》规定,如果DEST=r32,则底层64位GPR的高32比特被保留。
ps32023/07/24,17:24,JST
ps42023/07/25 01:22,JST
我在《英特尔手册》的附录B中找到了MOVMSKPS的编码,作为使用REX推广的特殊情况指令。W
第2D卷B-63
指令格式和编码
B.13 64位模式的特殊编码
以下奔腾、P6、MMX、SSE、SSE2、SSE3指令通过使用REX在IA-32e模式下升级为64位操作。W.但是,这些条目属于特殊情况,不符合一般规则(第B.4节中规定)。
表B-34。使用REX推广的特殊情况说明。W(续)
ps52023/07/25205:49,JST
3.1.1.1指令汇总表中的操作码列(无VEX前缀的指令)
雷克斯。W表示影响操作数大小或指令语义的REX前缀的使用。第2章讨论了REX前缀和其他可选/强制指令前缀的排序。
请注意,将旧指令提升为64位行为的REX前缀没有在操作码列中明确列出。
我认为重要的是,它将省略REX前缀限制为仅将操作码列中的64位行为提升为“遗留指令”。因此,对于非遗留指令,基本上,将其提升为64位行为的REX前缀在操作码列中明确列出。
3.1.1.3操作码汇总表中的指令列
reg用于指令的通用寄存器
当寄存器的宽度与指令的操作的语义无关时。
寄存器可以是r16、r32或r64。
另一方面:
r/m8字节操作数,它是字节通用寄存器(AL、CL、DL、BL、AH、CH、DH、BH、BPL、SPL、DIL和SIL)的内容,或者是来自内存的字节。字节寄存器R8B-R15B可使用REX。R在64位模式中。
-
在r/m8的情况下,r表示8位GPR。
-
在r/m16的情况下,r表示一个16位的GPR。
-
在r/m32的情况下,r表示32位GPR。
-
在r/m64的情况下,r表示64位GPR。
我认为在reg/m8中,reg表示r16/r32/r64 GPR,而在指令中,寄存器的宽度与指令操作的语义无关。
所以,我认为
-
在reg/m8的情况下,reg表示r16/r32/r64 GPR。
-
在reg/m16的情况下,reg表示r16/r32/r64 GPR。
-
在reg/m32的情况下,reg表示r16/r32/r64 GPR。
-
在reg/m64的情况下,reg表示r16/r32/r64 GPR。
ps62023/07/25206:32,JST
英特尔手册
3-12第1卷
3.4.1.1 64位模式下的通用寄存器
在64位模式下,操作数大小决定目标通用中的有效位数
寄存器:
-
64位操作数在目标通用寄存器中生成64位结果。
-
32位操作数生成32位结果,零扩展到目标通用寄存器中的64位结果。
-
8位和16位操作数产生8位或16位结果。目的通用寄存器的高56位或48位(分别)不通过该操作进行修改。如果8位或16位运算的结果用于64位地址计算,则显式地将寄存器符号扩展到完整的64位。