12

我正在尝试实现一些内联汇编器(在 C/C++ 代码中)以利用 SSE。我想将值(从 XMM 寄存器或内存)复制并复制到另一个 XMM 寄存器。例如,假设我在内存中有一些值 {1, 2, 3, 4}。我想复制这些值,使 xmm1 填充 {1, 1, 1, 1},xmm2 填充 {2, 2, 2, 2},依此类推。

查看英特尔参考手册,我找不到执行此操作的说明。我是否只需要结合使用重复的 MOVSS 和旋转(通过 PSHUFD?)?

4

3 回答 3

15

有两种方法:

  1. shufps专门使用:

    __m128 first = ...;
    __m128 xxxx = _mm_shuffle_ps(first, first, 0x00); // _MM_SHUFFLE(0, 0, 0, 0)
    __m128 yyyy = _mm_shuffle_ps(first, first, 0x55); // _MM_SHUFFLE(1, 1, 1, 1)
    __m128 zzzz = _mm_shuffle_ps(first, first, 0xAA); // _MM_SHUFFLE(2, 2, 2, 2)
    __m128 wwww = _mm_shuffle_ps(first, first, 0xFF); // _MM_SHUFFLE(3, 3, 3, 3)
    
  2. 让编译器使用_mm_set1_psand选择最佳方式_mm_cvtss_f32

    __m128 first = ...;
    __m128 xxxx = _mm_set1_ps(_mm_cvtss_f32(first));
    

请注意,第二种方法将在 MSVC 上产生可怕的代码,如此处所述,并且只会产生“xxxx”作为结果,这与第一种选择不同。

我正在尝试实现一些内联汇编器(在 C/C++ 代码中)以利用 SSE

这是非常不便携的。使用内在函数。

于 2010-01-06T20:07:24.440 回答
6

将源移动到目标寄存器。使用 'shufps' 并使用新的 dest 寄存器两次,然后选择适当的掩码。

以下示例将 XMM2.x 的值广播到 XMM0.xyzw

MOVAPS XMM0, XMM2
SHUFPS XMM0, XMM0, 0x00
于 2010-01-06T20:05:34.733 回答
2

如果您的值在内存中是 16 字节对齐的:

movdqa    (mem),    %xmm1
pshufd    $0xff,    %xmm1,    %xmm4
pshufd    $0xaa,    %xmm1,    %xmm3
pshufd    $0x55,    %xmm1,    %xmm2
pshufd    $0x00,    %xmm1,    %xmm1

如果没有,您可以执行未对齐的加载或四个标量加载。在较新的平台上,未对齐的负载应该更快;在较旧的平台上,标量负载可能会胜出。

正如其他人所指出的,您也可以使用shufps.

于 2010-01-06T20:08:45.623 回答