Как я могу заменить отсутствующую инструкцию VPERMIL2PS, используя эквивалентные инструкции в AVX2?
VPERMIL2PS ymm1, ymm2, ymm3, ymm4/m256, imz2
Переставьте значения с плавающей запятой одинарной точности в ymm2 и ymm3, используя элементы управления из ymm4 / mem, результаты сохраняются в 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])
Внутренний эквивалент компилятора Intel 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 Описание - Перестановка значений с плавающей запятой одинарной точности в ymm2 и ymm3 с использованием элементов управления из ymm4 / mem, результаты сохраняются в 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 Перестановка значений с плавающей запятой одинарной точности в ymm2 с помощью элементов управления из ymm3 / mem и сохранение результата в ymm1.
Насколько это будет правильно, мне сказать сложно, потому что для надежности нужно эмулировать инструкцию VPERMIL2PS, поэтому обращаюсь к местным специалистам!
Последние архитектурные изменения Intel (R) AVX 29 января 2009 г. Удалены: VPERMIL2PS и VPERMIL2PD
Все инструкции PERMIL2 исчезли - как в 128-битном, так и в 256-битном вариантах. Как и в FMA ниже, они использовали бит VEX.W для выбора источника из памяти - мы больше не движемся в направлении использования VEX.W для этой цели.
Компилятор Intel не понимает эту инструкцию 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);
}
}