Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Gcc NEON内联程序集-存储查询_Gcc_Assembly_Arm_Inline Assembly_Neon - Fatal编程技术网

Gcc NEON内联程序集-存储查询

Gcc NEON内联程序集-存储查询,gcc,assembly,arm,inline-assembly,neon,Gcc,Assembly,Arm,Inline Assembly,Neon,我试图学习如何使用gcc和内联汇编来利用NEON。 虽然它令人困惑且进展缓慢,但我还是取得了一些进展(自从我上次尝试编写汇编以来已经10年了)。 我的简单程序加载一个(小)向量,求和并存储它。我遇到的问题是,我似乎无法将结果存储在我想要的地方。 当我在输出列表中使用未使用的数组指针(r)时,会出现一个错误“asm中不可能的约束”。如果我再创建一个指向它的第二个指针(rptr),它将进行汇编,但它会重新使用一个输入寄存器r2,该寄存器是一个寄存器,有效地覆盖了输入。 (我知道我的数组大小为32个元

我试图学习如何使用gcc和内联汇编来利用NEON。 虽然它令人困惑且进展缓慢,但我还是取得了一些进展(自从我上次尝试编写汇编以来已经10年了)。 我的简单程序加载一个(小)向量,求和并存储它。我遇到的问题是,我似乎无法将结果存储在我想要的地方。 当我在输出列表中使用未使用的数组指针(r)时,会出现一个错误“asm中不可能的约束”。如果我再创建一个指向它的第二个指针(rptr),它将进行汇编,但它会重新使用一个输入寄存器r2,该寄存器是一个寄存器,有效地覆盖了输入。 (我知道我的数组大小为32个元素,并且我只处理一个元素,我计划尝试循环,或者尝试加载更多寄存器以进行并行处理)

void vecSum()
{
//两个32位类型的输入阵列,一个输出
int32_t a[32];
int32_t b[32];
int32_t r[32];
//初始化
对于(int-cnt=0;cnt<32;cnt++)
{
a[cnt]=0x33333333;
b[cnt]=0x11111111;
r[cnt]=0;
}
void*rptr=r;
__反复无常(
“vld1.32{d0},[%[ina]]!\n”//a处加载霓虹灯寄存器和我们的数据,后递增寄存器
“vld1.32{d1},[%[inb]]!\n”
“vqadd.s32 d0,d1\n”//执行sat
“vst1.32 d0,[%[结果]]\n”//存储答案
:[结果]“=r”(rptr)/*r*/
:[ina]“r”(a),[inb]“r”(b)
:/*“d0”、“d1”、“d2”*/);
对于(int g=0;g<32;g++)
{
printf(“0x[%d]%x”,g,a[g]);
}    
}
Objdump:

for(int-cnt=0;cnt<32;cnt++)
780:e3530080 cmp r3,#128;0x80
784:1afffff7 bne 768
“vld1.32{d1},[%[inb]]!\n”
“vqadd.s32 d0,d1\n”//执行sat
“vst1.32 d0,[%[结果]]\n”
:[结果]“=r”(rptr)
:[ina]“r”(a),[inb]“r”(b)
:/*“d0”、“d1”、“d2”*/);
788:f422078f vld1.32{d0}[r2]
78c:f421178d vld1.32{d1}[r1]!
790:f2200011 vqadd.s32 d0、d0、d1
794:f402078f vst1.32{d0}[r2]
总之,如果我尝试
vst1.32 d0,[%[result]]
其中result是数组指针r,我会得到一个编译错误。如果I rptr(指向r的另一个指针)返回,则使用r2(数组a)作为输出


有人能解释为什么我输出到r时出错吗?为什么ptr-to-r是一个?

rptr
被声明为一个输出,而它应该是一个输入,并且在clobber列表中缺少
“内存”


或者,您可以将数组放在结构中,并使用结构(而不是指针)作为asm语句的参数

考虑asm是否包含
add%[result]、%[ina]、%[inb]
。为
result
ina
分配r2没有任何害处。因为GCC不分析asm语句的内容,所以它的默认假设是它包含一条这样的指令,所以如果您的指令更复杂,那么您需要这样说,以便按照预期工作

具体地说,为了防止出现问题的重叠寄存器分配,您需要诚实地告诉自己,您的asm修改输入寄存器——最简单的是通过(就GCC而言,这实际上使它们成为输出)。不这样做的另一个令人不快的副作用是,编译器会假设,例如,r1在之后仍然保留
b
的地址,并且可能会生成以后的代码,依赖于asm实际所做的操作,这些代码随后会出现可怕的错误

此外,您不修改
结果
指针,只将其值用作输入,因此说它是只写输出操作数是非常错误的

至于
r
的问题,通过将其指定为输出操作数,可以说asm将值写回该变量。除了不能使用C中的数组变量(数组不是可修改的左值)之外,您需要为asm提供一个变量,该变量保存数组的地址,并可以重新分配给它,即指针变量。可以将数组直接用作输入操作数的原因是,它不是变量,并且计算结果为数组的表达式会自动转换为指向该数组第一个元素的指针(但仍然不是左值)

总而言之,对于
a
b
,使用适当的指针变量,该代码的适当操作数和约束条件看起来更像这样:

: [ina] "+r" (aptr), [inb] "+r" (bptr)
: [result] "r" (r)
: "d0", "d1", "memory" /* getting clobbers right is also important */

旁注:如果你只想掌握霓虹灯指令而不是与GCC作战,则是一个可供选择的替代方案。

约束<代码>=R 告诉你,你的代码产生的值<代码> RPTR < /代码>,这似乎不是真的。汇编程序的输出在内存中;AFAIK的适当约束是
[result]“+r”(rptr)
(假设最终需要
*rptr++=xxx
)谢谢,这似乎达到了预期效果。大多数示例都处理=r,事实上,我的(旧的)gcc how-to页面没有列出“+”修饰符。我现在找到了新的。知道为什么+r使用(rptr)而不是直接使用(r)工作吗?因为我试图执行“写入”,所以我假设vstr需要一个输出。寄存器是否也应成为“m”约束?所以按照你说的,我应该使用::[ina]“r”(a),[inb]“r”(b),[result]“m”(rptr):“memory”?你不是在写
rptr
,而是在写它指向的东西。将
“m”
约束与
rptr
一起使用是错误的,地址需要在寄存器中。但是您正在写入
[ina]
[inb]
(通过增加它们),以便将它们作为输入/输出,或作为输入约束以匹配输出。预处理您想要增加的
rptr
,因此它也需要是一个输入/输出。
for(int cnt = 0; cnt < 32; cnt++)
 780:   e3530080    cmp r3, #128    ; 0x80
 784:   1afffff7    bne 768 <_Z8vecSum32v+0x28>
"vld1.32 {d1},[%[inb]]!\n"
"vqadd.s32 d0,d1\n" //perform the sat
"vst1.32 d0,[%[result]]\n"
: [result]"=r" (rptr)
: [ina] "r" (a), [inb] "r" (b)
: /*"d0", "d1", "d2"*/);
 788:   f422078f    vld1.32 {d0}, [r2]
 78c:   f421178d    vld1.32 {d1}, [r1]!
 790:   f2200011    vqadd.s32   d0, d0, d1
 794:   f402078f    vst1.32 {d0}, [r2]
: [ina] "+r" (aptr), [inb] "+r" (bptr)
: [result] "r" (r)
: "d0", "d1", "memory" /* getting clobbers right is also important */