如何使用另一个XMM寄存器条目中的4个相同浮点填充x86 XMM寄存器?

时间:2010-01-06 19:51:29

标签: c++ c x86 inline-assembly sse

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

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

3 个答案:

答案 0 :(得分: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_ps_mm_cvtss_f32的最佳方式:

    __m128 first = ...;
    __m128 xxxx = _mm_set1_ps(_mm_cvtss_f32(first));
    
  3. 请注意,第二种方法会在MSVC as discussed here上产生可怕的代码,并且只会产生'xxxx',这与第一种方法不同。

      

    我正在尝试实现一些内联   汇编程序(在C / C ++代码中)采取   SSE的优势

    这是非常不可移植的。使用内在函数。

答案 1 :(得分:6)

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

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

MOVAPS XMM0, XMM2
SHUFPS XMM0, XMM0, 0x00

答案 2 :(得分:1)

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

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

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

正如其他人所说,你也可以使用shufps