将_mm_shuffle_epi32转换为C表达式以进行排列?

jww*_*jww 5 x86 sse shuffle x86-64 sse2

我正在使用SSE2到NEON的端口。该端口尚处于早期阶段,并且产生了错误的结果。结果不正确的部分原因是_mm_shuffle_epi32我选择的NEON指令。

Microsoft的文档_mm_shuffle_epi32是精简版。在英特尔文档是更好的,但它不是我清楚什么是一些伪代码的是做。

SELECT4(src, control)
{
    CASE(control[1:0])
        0: tmp[31:0] := src[31:0]
        1: tmp[31:0] := src[63:32]
        2: tmp[31:0] := src[95:64]
        3: tmp[31:0] := src[127:96]
    ESAC
    RETURN tmp[31:0]
}

dst[31:0] := SELECT4(a[127:0], imm8[1:0])
dst[63:32] := SELECT4(a[127:0], imm8[3:2])
dst[95:64] := SELECT4(a[127:0], imm8[5:4])
dst[127:96] := SELECT4(a[127:0], imm8[7:6])
Run Code Online (Sandbox Code Playgroud)

我需要设想一下该怎么_mm_shuffle_epi32做。或更正确地说,排列是立即数应用于值的。我想我需要将其视为基本的C和AND与OR。

给定C语句和宏,例如:

v2 = _mm_shuffle_epi32(v1, _MM_SHUFFLE(i1,i2,i3,i4));
Run Code Online (Sandbox Code Playgroud)

展开为基本C语句时,结果C表达式是什么样子?

Pet*_*des 5

不会进行 AND/OR 运算,除非您需要解压缩包含四个 2 位索引的 8 位整数。

_MM_SHUFFLE扩展到四个 args做出您自己的定义,而不是将它们打包。

有点像

// dst = _mm_shuffle_epi32(src, _MM_SHUFFLE(d,c,b,a))
void pshufd(int dst[4], int src[4], int d,int c,int b,int a)
{   // note that the _MM_SHUFFLE args are high-element-first order
    dst[0] = src[a];
    dst[1] = src[b];
    dst[2] = src[c];
    dst[3] = src[d];
}
Run Code Online (Sandbox Code Playgroud)

向量从低元素 = 0 开始索引。低元素是存储在最低地址的内存中的元素,但是当值在寄存器中时,您应该将它们视为[ 3 2 1 0 ]. 在这种表示法中,向量右移(如psrldq)实际上向右移动。

这就是为什么_mm_set_epi32(3, 2, 1, 0)int foo[] = { 0, 1, 2, 3 };.