我在C ++中有以下代码:
inline void armMultiply(const float* __restrict__ src1,
const float* __restrict__ src2,
float* __restrict__ dst)
{
__asm volatile(
"vld1.f32 {q0}, [%[src1]:128]! \n\t"
:
:[dst] "r" (dst), [src1] "r" (src1), [src2] "r" (src2)
);
}
为什么我会得到错误向量寄存器?
答案 0 :(得分:1)
你得到这个错误是因为你的内联汇编用于32位arm,但是你正在编译64位arm(使用clang - 使用gcc你会得到一个不同的错误)。
(内联)装配在32位和64位臂之间是不同的,因此您需要使用例如#if defined(__ARM_NEON__) && !defined(__aarch64__)
,或者如果您想为64位和32位设置不同的程序集:#ifdef __aarch64__
.. #elif defined(__ARM_NEON__)
等。
正如其他人评论的那样,除非你真的需要手工操作生产的组件,否则内在函数可以同样好(在某些情况下,比你自己生产的更好)。你可以,例如通过内在函数完成两个vld1_f32
次调用,一个vmul_f32
和一个vst1_f32
。
编辑:
用于加载到64位的SIMD寄存器的相应内联汇编行将是:
"ld1 {v0.4s}, [%[src1]], #16 \n\t"
为了支持两者,您的功能可能会是这样的:
inline void armMultiply(const float* __restrict__ src1,
const float* __restrict__ src2,
float* __restrict__ dst)
{
#ifdef __aarch64__
__asm volatile(
"ld1 {v0.4s}, [%[src1]], #16 \n\t"
:
:[dst] "r" (dst), [src1] "r" (src1), [src2] "r" (src2)
);
#elif defined(__ARM_NEON__)
__asm volatile(
"vld1.f32 {q0}, [%[src1]:128]! \n\t"
:
:[dst] "r" (dst), [src1] "r" (src1), [src2] "r" (src2)
);
#else
#error this requires neon
#endif
}
答案 1 :(得分:0)
假设我们正在谈论GCC,那么文档说你应该使用" w" ("浮点或SIMD向量寄存器")而不是" r" ("允许注册操作数,前提是它在通用寄存器")中作为约束。
https://gcc.gnu.org/onlinedocs/gcc-6.3.0/gcc/Machine-Constraints.html#Machine-Constraints
https://gcc.gnu.org/onlinedocs/gcc-6.3.0/gcc/Simple-Constraints.html#Simple-Constraints