[英]SSE4 inline assembly problems in C++
Hello Everyone我想执行以下形式的内联汇编指令
BLENDPD xmm1,xmm2/m128, imm8
我是内联装配的新手,所以我遇到了一些困难。 我的代码是:
#include<iostream>
using namespace std;
int main()
{
long long y;
__asm("blendpd %0,$0xabcd000000001111abcd000000001111,$0x1":
"=r" (y):
);
cout<<y;
return 0;
}
我的第一个错误是得到一个128位操作数,所以我使用了长十六进制数,但我仍然需要输出为128位,因为我希望2能够在屏幕上打印y。 最重要的是我知道我的__asm语法是错误的,但无法弄清楚,加上我不确定使用英特尔或AT&T语法进行编译会在使用__asm时产生影响。
欢迎任何帮助。 干杯! =)
编辑:我现在有这个版本,并得到一个未定义的函数错误。
#include<iostream>
#include<emmintrin.h>
using namespace std;
int main()
{
const int mask=5;
__m128d v2 = _mm_set_pd(1.0, 2.0);
__m128d v1;
v1=_mm_blend_pd(v1, v2, mask);
return 0;
}
首先,对于这类事情,您很少需要使用内联汇编。 GCC通常提供“编译器内在”函数,允许您使用C函数语法而不是汇编语法调用给定的特殊指令。
在这种情况下,您想要的内部函数是_mm_blend_pd(),它具有此函数签名
#include <smmintrin.h>
__m128d _mm_blend_pd(__m128d v1, __m128d v2, const int mask);
编译器将用单个blendpd
指令替换它; 这实际上不是函数调用。
__m128d数据类型是一个包含两个双精度浮点值的向量; 你可以从像这样的双打数组中创建一个:
__m128d v = _mm_set_pd(1.0, 2.0);
要从矢量中检索值以打印它们,可以将矢量存储到双精度浮点数组中:
double a[2];
_mm_store_pd(a, v);
所有这些都基于英特尔内在函数手册, 网址为http://www.info.univ-angers.fr/~richer/ens/l3info/ao/intel_intrinsics.pdf ; 虽然这是指英特尔C ++编译器,但GCC支持相同的语法。
编辑:替换错误emmintrin.h
与正确smmintrin.h
。 另请注意, mask
值需要为2位(向量中每个值一位); 0,1,2或3以外的值会产生错误。 当然,您需要使用-msse4
GCC选项进行编译。
作为我的另一个答案的替代答案,这里是如何使用内联汇编而不是内在汇编。 (正如Thomas Pornin在我的另一个答案中指出的那样,内在函数通常更好,因为它们更便携,但有时你也想要这样的东西。)
首先,我作弊 - 我使用内部函数的版本,并用-S
编译它,并查看生成的汇编代码,它是:
movsd -64(%rbp), %xmm0
movhpd -56(%rbp), %xmm0
movsd -48(%rbp), %xmm1
movhpd -40(%rbp), %xmm1
blendpd $3, %xmm1, %xmm0
movlpd %xmm0, -64(%rbp)
movhpd %xmm0, -56(%rbp)
您可以在这里看到与原始代码不同的一些内容。 首先,请注意两个128位参数不是即时的 - 它们是xmm0和xmm1寄存器。 此外,您的操作数错误 - 掩码首先出现,包含输出的寄存器最后。 修复这些,并编译代码。
这里的第二个问题是你将通用寄存器的结果存储到y
,而blendpd指令不接触通用寄存器,所以这只是存储垃圾。 您需要xmm0
寄存器,您可以使用=Yz
(请参阅GCC的文档 )。 并且你不能把它存储long long
,即64位; 你需要一个128位向量变量。 解决所有这些问题,更正的代码是:
#include<iostream>
#include<smmintrin.h>
using namespace std;
int main()
{
__m128d y;
__asm("blendpd $0x3,%%xmm1,%%xmm0":
"=Yz" (y):
);
// cout<<y;
return 0;
}
你会注意到我必须注释掉cout
线,因为它没有处理SSE向量的规定; 你需要使用_mm_store_pd
内在函数来首先从y
获取单个double值。 (或者你可以添加更多的内联汇编来调用movhpd
和movhld
指令直接从寄存器中获取double值,而不是使用约束将它们分配给y
。)
而且你有它 - 编译并运行良好。 当然,输入值是未定义的(无论这些寄存器中是否随机出现),因此输出仍然是垃圾 - 如果您想获得有意义的结果,则需要先添加一些内容以将值加载到寄存器中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.