Bas*_*der 4 c++ assembly gcc simd
我想将存储在一个xmm寄存器中的数据与一个浮点值相乘,并将结果保存在xmm寄存器中.我做了一个小图解来解释它好一点.

如你所见,我的数据中有一个xmm0寄存器.例如,它包含:
xmm0 = | 4.0 | 2.5 | 3.5 | 2.0 |
每个浮点存储在4个字节中.我的xmm0寄存器是128位,长16个字节.
这很好用.现在我想将0.5存储在另一个xmm寄存器中,例如xmm1,并将该寄存器与xmm0寄存器相乘,以便存储在xmm0中的每个值乘以0.5.
我完全不知道如何在XMM寄存器中存储0.5.有什么建议?
顺便说一句:它是C++中的内联汇编程序.
void filter(image* src_image, image* dst_image)
{
float* src = src_image->data;
float* dst = dst_image->data;
__asm__ __volatile__ (
"movaps (%%esi), %%xmm0\n"
// Multiply %xmm0 with a float, e.g. 0.5
"movaps %%xmm0, (%%edi)\n"
:
: "S"(src), "D"(dst) :
);
}
Run Code Online (Sandbox Code Playgroud)
这是我想做的事情的安静简单版本.我得到了一些存储在浮点数组中的图像数据.指向这些数组的指针将传递给程序集.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);
}
Run Code Online (Sandbox Code Playgroud)
如果编译器生成错误的代码(并且仅在向编译器供应商提交错误之后),您应该只使用内联ASM.
如果你真的想留在集会中,有很多方法可以完成这项任务.您可以在ASM块之外定义比例向量:
const __m128 half = _mm_set1_ps(0.5f);
Run Code Online (Sandbox Code Playgroud)
然后就像使用其他操作数一样在ASM中使用它.
如果你真的想要,你可以在没有任何负载的情况下完成:
"mov $0x3f000000, %%eax\n" // encoding of 0.5
"movd %%eax, %%xmm1\n" // move to xmm1
"shufps $0, %%xmm1, %%xmm1\n" // splat across all lanes of xmm1
Run Code Online (Sandbox Code Playgroud)
这只是两种方法.还有很多其他方法.您可能会花一些时间使用英特尔指令集参考.
| 归档时间: |
|
| 查看次数: |
4939 次 |
| 最近记录: |