这是我第一次在stackoverflow上发布问题,所以请尝试忽略我在格式化问题/代码时可能遇到的任何错误。但请同样指出我,所以我可能会更加小心。
我试图编写一些简单的内在函数例程来添加两个128位(包含4个浮点变量)数字。我在网上找到了一些代码,并试图让它在我的系统上运行。代码如下:
//this is a sample Intrinsics program to add two vectors.
#include <iostream>
#include <iomanip>
#include <xmmintrin.h>
#include <stdio.h>
using namespace std;
struct vector4 {
float x, y, z, w; };
//functions to operate on them.
vector4 set_vector(float x, float y, float z, float w = 0) {
vector4 temp;
temp.x = x;
temp.y = y;
temp.z = z;
temp.w = w;
return temp;
}
void print_vector(const vector4& v) {
cout << " This is the contents of vector: " << endl;
cout << " > vector.x = " << v.x << endl;
cout << " vector.y = " << v.y << endl;
cout << " vector.z = " << v.z << endl;
cout << " vector.w = " << v.w << endl;
}
vector4 sse_vector4_add(const vector4&a, const vector4& b) {
vector4 result;
asm volatile (
"movl $a, %eax" //move operands into registers.
"\n\tmovl $b, %ebx"
"\n\tmovups (%eax), xmm0" //move register contents into SSE registers.
"\n\tmovups (%ebx), xmm1"
"\n\taddps xmm0, xmm1" //add the elements. addps operates on single-precision vectors.
"\n\t movups xmm0, result" //move result into vector4 type data.
);
return result;
}
int main() {
vector4 a, b, result;
a = set_vector(1.1, 2.1, 3.2, 4.5);
b = set_vector(2.2, 4.2, 5.6);
result = sse_vector4_add(a, b);
print_vector(a);
print_vector(b);
print_vector(result);
return 0;
}
我使用的g ++参数是:
g++ -Wall -pedantic -g -march=i386 -msse intrinsics_SSE_example.C -o h
我得到的错误如下:
intrinsics_SSE_example.C: Assembler messages:
intrinsics_SSE_example.C:45: Error: too many memory references for movups
intrinsics_SSE_example.C:46: Error: too many memory references for movups
intrinsics_SSE_example.C:47: Error: too many memory references for addps
intrinsics_SSE_example.C:48: Error: too many memory references for movups
我花了很多时间试图调试这些错误,谷歌搜索等等。我是Intrinsics的完全菜鸟,因此可能忽略了一些重要的事情。
感谢任何帮助,
谢谢,
斯利拉姆。
答案 0 :(得分:2)
您使用的是ASM块,而非内在块。
由于这些xmmX是寄存器,因此您应在其前面添加%
:
"\n\tmovups (%eax), %xmm0"
// etc.
你的ASM有几个错误。
ebx
注册。 $a
等被认为是汇编程序中的全局符号,它不是。addps %xmm0, %xmm1
会将结果存储到xmm1中。请记住,在AT&amp; T语法中,目的地位于右侧。更正的ASM块就像
asm volatile (
"movl %1, %%eax"
"\n\tmovl %2, %%ecx"
"\n\tmovups (%%eax), %%xmm0"
"\n\tmovups (%%ecx), %%xmm1"
"\n\taddps %%xmm0, %%xmm1"
"\n\tmovups %%xmm0, %0"
: "=m"(result)
: "r"(&a), "r"(&b)
: "eax", "ecx");
基本上,%0将替换为result
的地址,%1和%2将替换为&a
和&b
。有关详细说明,请参阅http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html。 "eax", "ecx"
阻止这两个寄存器用作%n的替换。
但前两个movl
是不必要的......
asm volatile(
"\n\tmovups (%1), %%xmm0"
"\n\tmovups (%2), %%xmm1"
"\n\taddps %%xmm1, %%xmm0"
"\n\tmovups %%xmm0, %0"
: "=m"(result)
: "r"(&a), "r"(&b));
既然你提到了内在的,为什么不使用__builtin_ia32_addps
?