繁体   English   中英

SSE中的SSE4内联汇编问题

[英]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值。 (或者你可以添加更多的内联汇编来调用movhpdmovhld指令直接从寄存器中获取double值,而不是使用约束将它们分配给y 。)

而且你有它 - 编译并运行良好。 当然,输入值是未定义的(无论这些寄存器中是否随机出现),因此输出仍然是垃圾 - 如果您想获得有意义的结果,则需要先添加一些内容以将值加载到寄存器中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM