《英特尔软件开发人员手册》将VCVTTPD2QQ描述为:
Convert eight packed double-precision floating-point values
from zmm2/m512 to eight packed quadword integers in zmm1
using truncation with writemask k1.
我正在使用VCVTTPD2QQ将八个双精度64位浮点数加载到zmm1中,编码如下:
mov rax,18446744073709551615
KMOVQ k1,rax
EVEX.512.66.0F.W1 VCVTTPD2QQ zmm1 {k1}{z},[r11+r15]
我用全1填充k1表示要移动所有8个数字。
如果以这种方式编码,我仍然会得到相同的结果:
VCVTTPD2QQ zmm1 {k1}{z},[r11+r15]
Intel手册通过寄存器名称区分三种可能的编码;如果名称是zmm寄存器,则应移动8。
为什么我只将4个数据点加载到zmm1中,而没有8个数据点?
编辑:
我取消了写掩码,正如彼得·科德斯在下面说的那样,在这里没有任何区别。我还创建了一个内存数组,并以:
访问它test_array: dq 24.0, 93.0, 43.0, 28.0, 86.0, 143.0, 17.0, 129.0, 33.0, 67.0, 55.0
mov rdi,test_array
EVEX.512.66.0F.W1 VCVTTPD2QQ zmm1,[rdi]
调试器显示的内容与访问从外部文件读取的数组(4个元素,而不是8个)相同。这是gdb的输出:
(gdb) i r zmm1
zmm1 {v16_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v8_double = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0}, v64_int8 = {0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5d, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1c, 0x0 <repeats 39 times>}, v32_int16 = {0x18, 0x0, 0x0, 0x0, 0x5d,
0x0, 0x0, 0x0, 0x2b, 0x0, 0x0, 0x0, 0x1c, 0x0 <repeats 19 times>}, v16_int32 = {0x18, 0x0, 0x5d, 0x0, 0x2b, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v8_int64 = {0x18, 0x5d, 0x2b, 0x1c, 0x0, 0x0, 0x0,
0x0}, v4_int128 = {0x5d0000000000000018, 0x1c000000000000002b, 0x0, 0x0}}
在v8_int64部分中,我们看到前四个值(正确),但后四个为零,输入数据不为零。
正如Peter Cordes和Michael Petch在最后的评论中都怀疑,此问题是由gdb中的错误引起的。显然,gdb无法显示zmm寄存器的高256位。
正如彼得·科德斯(Peter Cordes)所说,简单的测试是在内存中声明一个测试数组:
section .data
test_array2: times 8 dq 0
section .text
VCVTTPD2QQ zmm1,[r11+r15]
mov rdi,test_array2
vmovdqu64 [rdi],zmm1
mov rax,[rdi+0]
mov rax,[rdi+8]
mov rax,[rdi+16]
mov rax,[rdi+24]
mov rax,[rdi+32]
mov rax,[rdi+40]
mov rax,[rdi+48]
mov rax,[rdi+56]
使用gdb浏览rax的每一行,[rdi + xxx]行并查看rax中的值。就我而言,所有8个值都与输入数据匹配,即使gdb将zmm1的高256位显示为零。
[如果我发布了带有原始问题的MCR示例,其他人可能早些发现了。
感谢所有评论。