将一个浮点移动到一个xmm寄存器

我想将存储在一个xmm寄存器中的数据乘以一个浮点值并将结果保存在一个xmm寄存器中。 我做了一个小图片来解释它好一点。

正如你看到的,我有一个xmm0寄存器,里面有我的数据。 例如它包含:

xmm0 = | 4.0 | 2.5 | 3.5 | 2.0 |

每个浮点都以4个字节存储。 我的xmm0寄存器是128位,长16字节。

这工作很好。 现在,我想将0.5存储在另一个xmm寄存器中,例如xmm1,并将此寄存器与xmm0寄存器相乘,以便将存储在xmm0中的每个值与0.5相乘。

我完全不知道如何将0.5存储在XMM寄存器中。 有什么建议么?

顺便说一句:它是C ++中的内联汇编程序。

void filter(image* src_image, image* dst_image)
{
    float* src = src_image->data;
    float* dst = dst_image->data;

    __asm__ __volatile__ (              
        "movaps (%%esi), %%xmm0n"      
        // Multiply %xmm0 with a float, e.g. 0.5
        "movaps %%xmm0, (%%edi)n" 

        :
        : "S"(src), "D"(dst) :  
    );
}

这是我想要做的事情的简单版本。 我有一些图像数据存储在浮点数组中。 这些数组的指针被传递给程序集。 movaps获取阵列的前4个浮点值,将这16个字节存储在xmm0寄存器中。 这个xmm0应该乘以例如0.5。 比“新”值应存储在edi的数组中。


正如人们在评论中指出的那样,对于这种非常简单的操作,使用内在函数总是更好:

void filter(image* src_image, image* dst_image)
{
    const __m128 data = _mm_load_ps(src_image->data);
    const __m128 scaled = _mm_mul_ps(data, _mm_set1_ps(0.5f));
    _mm_store_ps(dst_image->data, scaled);
}

如果编译器生成错误代码(只有在向编译器供应商提交错误之后),才应使用内联ASM。

如果你真的想保持组装,有很多方法可以完成这个任务。 您可以在ASM块之外定义一个缩放矢量:

    const __m128 half = _mm_set1_ps(0.5f);

然后在ASM内部使用它,就像使用其他操作数一样。

如果你真的想要:你可以没有任何负载地做到这一点:

    "mov    $0x3f000000, %%eaxn"  // encoding of 0.5
    "movd   %%eax,       %%xmm1n" // move to xmm1
    "shufps $0, %%xmm1,  %%xmm1n" // splat across all lanes of xmm1

那只是两种方法。 还有很多其他的方法。 英特尔指令集参考中可能会花费一些质量时间。


假设你正在使用内在函数: __m128 halfx4 = _mm_set1_ps(0.5f);

编辑:

使用内在函数你会更好:

__m128 x = _mm_mul_ps(_mm_load_ps(src), halfx4);
_mm_store_ps(dst, x);

如果srcdst浮点数据不是16字节对齐的,则需要: _mm_loadu_ps_mm_storeu_ps - 它们较慢。


您正在寻找MOVSS指令(将内存中的单精度浮点数加载到SSE寄存器的最低4个字节中),然后使用随机数来填充其他3个浮点数:

movss  (whatever), %%xmm1
shufps %%xmm1, %%xmm1, $0

这也是_mm_set1_ps内部可能会这样做的方式。 然后你可以乘以这些SSE值或做任何你想要的:

mulps %%xmm1, %%xmm0
链接地址: http://www.djcxy.com/p/72725.html

上一篇: Moving a single float to a xmm register

下一篇: Uppercase a specific column in multy table SELECT (MySQL)