启用 AVX2 的处理器上的非法指令 vgatherdps
Posted
技术标签:
【中文标题】启用 AVX2 的处理器上的非法指令 vgatherdps【英文标题】:Illegal instruction vgatherdps on AVX2 enabled processor 【发布时间】:2016-09-19 10:48:47 【问题描述】:我正在为 AVX2 指令开发代码生成器,并尝试在 AMD A10 8700 处理器上对其进行测试,根据规格,该处理器应该运行 AVX2。
但是,它会因 vgatherdps 指令中的非法指令而崩溃:
vmovdqu yMM0, [ r9+ PmainBase + -256]; LDdqyy;0
lea r9, [ PmainBase + -192];0
vpcmpeqw ymm8, ymm8, ymm8;0
vgatherdps YMM0, [ r9+ yMM0*4 ] ,ymm8;0
cpuid 信息表明包含 avx2,因此 VGATHERDPS 应该是合法的。
有什么线索吗?
【问题讨论】:
它确实执行了一些 AVX2 指令,所以它被启用了。该集合的机器代码是什么? 为什么每行末尾都有;0
cmets?以及像yMM0
这样的大小写不一致?从格式/可读性的角度来看,基本上你的代码是一团糟。 (不过,与它的组装方式无关)。
【参考方案1】:
根据Intel's Instruction Reference:
如果任何一对索引、掩码或目标寄存器相同, 此指令导致 UD 错误。
您的目标寄存器和索引寄存器是相同的 (ymm0
)。因此该指令是非法的。我很惊讶组装商没有拒绝它。所以我认为这是汇编程序中的一个错误。
这个限制背后的原因是收集指令实际上是写入两个寄存器。
-
它将收集的结果写入目的地。
它将一个零掩码写回掩码寄存器,指示哪些通道成功。
在正常执行下,掩码寄存器将被零完全覆盖。但是如果发生故障,并不是所有的加载都会成功。所以指令可能只被部分执行。覆盖掩码寄存器的目的是告诉信号处理程序哪些通道成功,哪些通道失败。
索引寄存器不能与目标寄存器或掩码寄存器混为一谈,因为它会被覆盖,从而无法在从信号处理程序返回时恢复指令。
【讨论】:
OP 正在编写代码生成器,因此他可能没有通过汇编程序运行他的代码。此外,idx
reg 不能匹配 dst
或 msk
reg 有一个很好的理由。看vgatherdps
VEX.256的伪代码:首先,msk
寄存器中每个lane的MSB被splatted到lane的所有位,然后对于那些启用的通道,硬件会尝试加载数据并在成功时清除该通道中的掩码。因为msk
被无条件地完全覆盖,所以它不能为dst
或idx
加上别名,否则会发生写冲突。
无论哪种方式,您都无法解决此写入冲突:丢失msk
,您无法判断哪个通道失败,丢失idx
,您无法重试,丢失dst
和那么该指令的意义何在?即使msk
部分更新为dst
值,由于带内通信问题,您也会有歧义;可以想象,你成功读取了0xFFFFFFFF
,但是如果这个值在掩码寄存器之内,你怎么判断0xFFFFFFFF
是读取成功,还是失败呢?此外,idx
不能别名 msk
,因为负索引是合法的。
最后,idx
不能为msk
别名,因为在vgather*
指令系列中,idx
可以是qword 或dword,而msk
和dst
通道大小总是匹配,如果dst
是双字而idx
是双字,那么只有寄存器的下半部分被填充,而上半部分为零。
“混乱”是因为它来自一个代码生成器,该代码生成器在案例和每条指令后面的一些 cmets 中对调试信息进行编码。代码适用于不反对语法的 Nasm。 ymm8 是掩码,出于显而易见的原因,它与 dest 不同。我没有意识到在 AVX2 上的 index 和 dest 不能重叠,而在改编代码生成器的 MIC 上似乎并非如此。
@IwillnotexistIdonotexist 哦。最初,我认为掩码只是有条件地归零。我的解释是成功的车道归零,失败的车道保持不变。如果索引与掩码混叠,则失败的通道不受影响。成功的车道归零。您将无法判断归零车道是成功还是从零开始,但在任何一种情况下都是无操作的。但你是对的,我没有考虑索引寄存器大小不同的情况。我将编辑修复后一段。【参考方案2】:
修复了机器描述,以便在收集指令和获取中使用不相交的寄存器集作为索引和目标
vmovdqu yMM4, [ PmainBase + -256]; LDdqyy;0
lea r8,[ PmainBase + -192];0
vpcmpeqw ymm8, ymm8, ymm8;0
vgatherdps YMM0,[r8+ yMM4*4 ] ,ymm8;0
现在可以正常使用了。
【讨论】:
以上是关于启用 AVX2 的处理器上的非法指令 vgatherdps的主要内容,如果未能解决你的问题,请参考以下文章
MSVC /arch:[指令集] - SSE3、AVX、AVX2