用c++写汇编代码
writing assembly code in c++
我在 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)
);
}
为什么我得到了预期的错误向量寄存器?
假设我们谈论的是 GCC,文档说您应该使用 "w" ("Floating point or SIMD vector register") 而不是 "r" ("register operand is allowed provided that it is in a general register") 作为约束.
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
您收到此错误是因为您的内联汇编适用于 32 位 arm,但您正在为 64 位 arm 编译(使用 clang - 使用 gcc 您会得到不同的错误)。
(内联)汇编在 32 位和 64 位 arm 之间是不同的,所以你需要用例如保护它。 #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
}
我在 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)
);
}
为什么我得到了预期的错误向量寄存器?
假设我们谈论的是 GCC,文档说您应该使用 "w" ("Floating point or SIMD vector register") 而不是 "r" ("register operand is allowed provided that it is in a general register") 作为约束.
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
您收到此错误是因为您的内联汇编适用于 32 位 arm,但您正在为 64 位 arm 编译(使用 clang - 使用 gcc 您会得到不同的错误)。
(内联)汇编在 32 位和 64 位 arm 之间是不同的,所以你需要用例如保护它。 #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
}