用c ++编写汇编代码

时间:2017-02-27 21:14:40

标签: c++ assembly arm neon

我在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)
                 );
}

为什么我会得到错误向量寄存器?

2 个答案:

答案 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