Assembly VPERMIL2PS和VPERMIL2PD所有PERMIL2指令消失-替换缺失的指令

Assembly VPERMIL2PS和VPERMIL2PD所有PERMIL2指令消失-替换缺失的指令,assembly,x86,avx,avx2,xop,Assembly,X86,Avx,Avx2,Xop,如何使用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

如何使用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
说明的完整说明

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])
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);
  }
}
操作

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编码版本)

Bochs模拟此指令的方式

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])
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);
  }
}
bxInstruction\u 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()),结果;
无符号len=i->getVL();
result.clear();
for(无符号n=0;nIb()&3);
}
BX_WRITE_YMM_REGZ_VLEN(i->dst(),result,len);
下一个仪器(一);
}
BX_CPP_内联无效xmm_许可证2PS(BxPackedXmmRegister*r,常数BxPackedXmmRegister*op1,常数BxPackedXmmRegister*op2,常数BxPackedXmmRegister*op3,无符号m2z)
{
for(无符号n=0;n<4;n++){
Bit32u ctrl=op3->xmm32u(n);
if((m2z^((ctrl>>3)&0x1))==0x3)
r->xmm32u(n)=0;
其他的
r->xmm32u(n)=(ctrl&0x4)?op1->xmm32u(ctrl&0x3):op2->xmm32u(ctrl&0x3);
}
}
它们并没有“消失”,它们从一开始就不存在于任何真正的CPU中。2009年是AVX1的第一个CPU发布之前,而AVX仍处于规划阶段。IDK你在看什么,甚至提到了他们

ISA ref手册的当前版本,或者不提。也没有。也许是在Sandybridge发布之前的10年版本的“未来扩展”手册

因为为了可靠性,您需要模拟指令VPERMIL2PS

不,您不知道,它从一开始就不存在,因此没有使用它的代码。(或者很少;可能是根据早期的预发行版AVX文档编写的)。您只需要精确地实现任何给定问题所需的功能

您标记了这个(AMD)XOP,但您只引用了Intel文档;我想XOP确实有一些双输入洗牌,但我没有去检查文档。当然,仅适用于128位向量


AVX1确实有一些2输入洗牌,但没有变量控制。有/
pd
具有即时控制功能,和
…pd
执行两个单独的通道内版本的相应128位随机播放

在2x>代码> VSUFFPS +<代码> VBDENPS中,可以建立任何固定的2输入,<>强> >最好的情况是一个代码> VSUFPPS,或者中间是“代码> VSUFPPS < /代码> +>代码> VBLNDPS或2x<代码> VSUFFPS(例如,将您想要的元素收集到一个向量中,然后按正确的顺序排列)。任何
vshufps
shuffls都可以是
vunpcklps
hps
。请记住,immediate
vblendps
很便宜,但在英特尔上shuffles的吞吐量只有1个时钟(只有在冰湖之前的端口5)

您甚至可以使用变量控制2x
vpermilps
并比较或shift+
vblendvps
来模拟
vpermil2ps
,因为
vpermilps
忽略索引中的高位。因此这将是
(ctrl&0x4)?op2[ctrl&0x3]:op2[ctrl&0x3]的BOCHS实现
使用
vpermilps
ctrl
上洗牌两个输入(它隐式地只查看低位2位),然后使用整数移位将该位移到顶部,从而混合
ctrl&4

(也可以选择使用
vandps
模拟条件归零,方法是使用
vpslld
将第三个索引位置于混合的顶部,使用
vpsrad
或与零结果进行比较,为
vpand
创建and掩码。或者在Skylake上,对于任何端口,
vblendvps
都是2 uops,因此您可以使用它来混合。)d为零,而不是移位/和或cmp/和)

但是,如果您关心编译时常量shuffle控件的性能,请不要天真地忽略这一点。