如何使用 AVX2 中的等效指令替换丢失的VPERMIL2PS指令?
VPERMIL2PS ymm1, ymm2, ymm3, ymm4/m256, imz2
使用来自 ymm4/mem 的控件置换 ymm2 和 ymm3 中的单精度浮点值,结果存储在具有选择性零匹配控件的 ymm1 中。
VPERMIL2PS (VEX.256 encoded version)
DEST[31:0] sel_and_condzerosp(SRC1[127:0], SRC2[127:0], SRC3[3:0])
DEST[63:32] sel_and_condzerosp(SRC1[127:0], SRC2[127:0], SRC3[35:32])
DEST[95:64] sel_and_condzerosp(SRC1[127:0], SRC2[127:0], SRC3[67:64])
DEST[127:96] sel_and_condzerosp(SRC1[127:0], SRC2[127:0], SRC3[99:96])
DEST[159:128] sel_and_condzerosp(SRC1[255:128], SRC2[255:128], SRC3[131:128])
DEST[191:160] sel_and_condzerosp(SRC1[255:128], SRC2[255:128], SRC3[163:160])
DEST[223:192] sel_and_condzerosp(SRC1[255:128], SRC2[255:128], SRC3[195:192])
DEST[255:224] sel_and_condzerosp(SRC1[255:128], SRC2[255:128], SRC3[227:224])
英特尔 C/C++ 编译器内在等效项
VPERMIL2PS __m128 _mm_permute2_ps (__m128 a, __m128 b, __m128i ctrl, int imm)
VPERMIL2PS __m256 _mm256_permute2_ps (__m256 a, __m256 b, __m256i ctrl, int imm)
VPERMIL2PS ymm1, ymm2, ymm3,ymm4/m256, imz2 描述 - 使用来自 ymm4/mem 的控件置换 ymm2 和 ymm3 中的单精度浮点值,结果存储在 ymm1 中,并带有选择性的零匹配控件。imz2:is4 立即字节的一部分,提供适用于双源置换指令的控制功能。
最接近的指令是 VPERMILPS .. 这个指令仍然有效
VPERMILPS (256-bit immediate version)
DEST[31:0] Select4(SRC1[127:0], imm8[1:0]);
DEST[63:32] Select4(SRC1[127:0], imm8[3:2]);
DEST[95:64] Select4(SRC1[127:0], imm8[5:4]);
DEST[127:96] Select4(SRC1[127:0], imm8[7:6]);
DEST[159:128] Select4(SRC1[255:128], imm8[1:0]);
DEST[191:160] Select4(SRC1[255:128], imm8[3:2]);
DEST[223:192] Select4(SRC1[255:128], imm8[5:4]);
DEST[255:224] Select4(SRC1[255:128], imm8[7:6]);
VPERMILPS ymm1、ymm2、ymm3/m256 描述 - RVM V/V AVX 使用来自 ymm3/mem 的控件在 ymm2 中置换单精度浮点值并将结果存储在 ymm1 中。
我很难说它如何正确,因为为了可靠性,您需要模拟指令VPERMIL2PS,因此我呼吁当地专家!
最近的英特尔(R) AVX 架构更改 2009 年 1 月 29 日 删除:VPERMIL2PS 和 VPERMIL2PD
所有 PERMIL2 指令都消失了——包括 128 位和 256 位版本。像下面的 FMA 一样,他们使用 VEX.W 位来选择来自内存的源——我们不再朝着使用 VEX.W 的方向发展。
英特尔编译器不理解此 VPERMIL2PS 指令。
AVX-512 指令需要最新的处理器,这不是一个通用的解决方案.. Visual Studio成功组装了该指令,但该指令无法在处理器上执行,抛出异常。
反汇编代码
align 20h;
Yperm_msk ymmword 000000000100000006000000070000000C0000000D0000000A0000000B000000h
vmovups ymm0, [rbp+920h+var_8C0]
vmovdqu ymm1, Yperm_msk
vpermil2ps ymm0, ymm0, [rbp+920h+var_880], ymm1, 920h+var_920
vmovups [rbp+920h+var_1A0], ymm0
指令的完整描述
手术
select2sp(src1, src2, sel) // This macro is used by another macro “sel_and_condzerosp“ below
{
if (sel[2:0]=0) then TMP src1[31:0]
if (sel[2:0]=1) then TMP src1[63:32]
if (sel[2:0]=2) then TMP src1[95:64]
if (sel[2:0]=3) then TMP src1[127:96]
if (sel[2:0]=4) then TMP src2[31:0]
if (sel[2:0]=5) then TMP src2[63:32]
if (sel[2:0]=6) then TMP src2[95:64]
if (sel[2:0]=7) then TMP src2[127:96]
return TMP
}
sel_and_condzerosp(src1, src2, sel) // This macro is used by VPERMIL2PS
{
TMP[31:0] select2sp(src1[127:0], src2[127:0], sel[2:0])
IF (imm8[1:0] = 2) AND (sel[3]=1) THEN TMP[31:0] 0
IF (imm8[1:0] = 3) AND (sel[3]=0) THEN TMP[31:0] 0
return TMP
}
VPERMIL2PS(VEX.256 编码版本)
DEST[31:0] sel_and_condzerosp(SRC1[127:0], SRC2[127:0], SRC3[3:0])
DEST[63:32] sel_and_condzerosp(SRC1[127:0], SRC2[127:0], SRC3[35:32])
DEST[95:64] sel_and_condzerosp(SRC1[127:0], SRC2[127:0], SRC3[67:64])
DEST[127:96] sel_and_condzerosp(SRC1[127:0], SRC2[127:0], SRC3[99:96])
DEST[159:128] sel_and_condzerosp(SRC1[255:128], SRC2[255:128], SRC3[131:128])
DEST[191:160] sel_and_condzerosp(SRC1[255:128], SRC2[255:128], SRC3[163:160])
DEST[223:192] sel_and_condzerosp(SRC1[255:128], SRC2[255:128], SRC3[195:192])
DEST[255:224] sel_and_condzerosp(SRC1[255:128], SRC2[255:128], SRC3[227:224])
Bochs 模拟此指令的方式
class bxInstruction_c;
void BX_CPP_AttrRegparmN(1) BX_CPU_C::VPERMIL2PS_VdqHdqWdqIbR(bxInstruction_c *i)
{
BxPackedYmmRegister op1 = BX_READ_YMM_REG(i->src1());
BxPackedYmmRegister op2 = BX_READ_YMM_REG(i->src2());
BxPackedYmmRegister op3 = BX_READ_YMM_REG(i->src3()), result;
unsigned len = i->getVL();
result.clear();
for (unsigned n=0; n < len; n++) {
xmm_permil2ps(&result.ymm128(n), &op1.ymm128(n), &op2.ymm128(n), &op3.ymm128(n), i->Ib() & 3);
}
BX_WRITE_YMM_REGZ_VLEN(i->dst(), result, len);
BX_NEXT_INSTR(i);
}
BX_CPP_INLINE void xmm_permil2ps(BxPackedXmmRegister *r, const BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, unsigned m2z)
{
for(unsigned n=0; n < 4; n++) {
Bit32u ctrl = op3->xmm32u(n);
if ((m2z ^ ((ctrl >> 3) & 0x1)) == 0x3)
r->xmm32u(n) = 0;
else
r->xmm32u(n) = (ctrl & 0x4) ? op1->xmm32u(ctrl & 0x3) : op2->xmm32u(ctrl & 0x3);
}
}