我想组装一个使用ARM的CRC指令的文件。汇编程序产生错误Error: selected processor does not support 'crc32b w1,w0,w0'
。GAS是否从内联汇编生成指令?
有运行时检查到位,所以我们对这条指令很安全。该技术在i686和x86_64上正常工作。例如,我可以组装使用英特尔CRC intrinsics或SHA Intrinsics而不使用-mcrc
或-msha
(并且在没有这些功能的机器上)的文件。
下面是测试情况:
$ cat test.cxx
#include <arm_neon.h>
#define GCC_INLINE_ATTRIB __attribute__((__gnu_inline__, __always_inline__, __artificial__))
#if defined(__GNUC__) && !defined(__ARM_FEATURE_CRC32)
__inline unsigned int GCC_INLINE_ATTRIB
CRC32B(unsigned int crc, unsigned char v)
{
unsigned int r;
asm ("crc32b %w2, %w1, %w0" : "=r"(r) : "r"(crc), "r"((unsigned int)v));
return r;
}
#else
// Use the intrinsic
# define CRC32B(a,b) __crc32b(a,b)
#endif
int main(int argc, char* argv[])
{
return CRC32B(argc, argc);
}
这里是结果:
$ g++ test.cxx -c
/tmp/ccqHBPUf.s: Assembler messages:
/tmp/ccqHBPUf.s:23: Error: selected processor does not support `crc32b w1,w0,w0'
配售ASM代码的源文件,并使用不同的选项编译是不可行的,因为CRC32B
会也用于C++头文件。
如何让GAS组装指令?
GCC的配置和选项是我们尝试这样做的原因。用户不会阅读手册,因此他们不会将-march=armv8-a+crc+crypto -mtune=cortex-a53
添加到CFLAGS
和CXXFLAGS
。
此外,发行版编译为“最低能力”的机器,所以我们希望硬件加速例程可用。当库由Linaro等发行版提供时,两个代码路径(软件CRC和硬件加速CRC)将可用。
该机器是一个LeMaker HiKey,它是ARMv8/Aarch64。它的A53处理器具有CRC和加密(CRC和加密是可选的架构下):
$ cat /proc/cpuinfo
Processor : AArch64 Processor rev 3 (aarch64)
processor : 0
...
processor : 7
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x41
CPU architecture: AArch64
GCC缺乏最常用的定义一个希望默认为存在:
$ g++ -dM -E - </dev/null | sort | egrep -i '(arm|neon|aarch|asimd)'
#define __aarch64__ 1
#define __AARCH64_CMODEL_SMALL__ 1
#define __AARCH64EL__ 1
使用GCC的-march=native
对ARM不起作用:
$ g++ -march=native -dM -E - </dev/null | sort | egrep -i '(arm|neon|aarch|asimd)'
cc1: error: unknown value ‘native’ for -march
而且锵:
$ clang++ -dM -E - </dev/null | sort | egrep -i '(arm|neon|aarch|asimd)'
#define __AARCH64EL__ 1
#define __ARM_64BIT_STATE 1
#define __ARM_ACLE 200
#define __ARM_ALIGN_MAX_STACK_PWR 4
#define __ARM_ARCH 8
#define __ARM_ARCH_ISA_A64 1
#define __ARM_ARCH_PROFILE 'A'
#define __ARM_FEATURE_CLZ 1
#define __ARM_FEATURE_DIV 1
#define __ARM_FEATURE_FMA 1
#define __ARM_FEATURE_UNALIGNED 1
#define __ARM_FP 0xe
#define __ARM_FP16_FORMAT_IEEE 1
#define __ARM_FP_FENV_ROUNDING 1
#define __ARM_NEON 1
#define __ARM_NEON_FP 0xe
#define __ARM_PCS_AAPCS64 1
#define __ARM_SIZEOF_MINIMAL_ENUM 4
#define __ARM_SIZEOF_WCHAR_T 4
#define __aarch64__ 1
GCC版本:
$ gcc -v
...
gcc version 4.9.2 (Debian/Linaro 4.9.2-10)
GAS版本:
$ as -v
GNU assembler version 2.24 (aarch64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.24
我没有一个环境中测试这一点,但它听起来像是你需要的是'.arch_extension name'。也许直接添加到这个asm指令。根据[docs](https://sourceware.org/binutils/docs/as/ARM-Directives.html),这允许您*为增加或删除扩展到正在编译为*的架构。如果失败了,可能会添加'.arch name'作为'basic'asm的“顶级”位? –
还是有更多的限制,我错过了?向像这样的asm指令添加指令并不是什么新东西。人们一直在使用它来将intel风格的汇编程序放入asm指令中。 –
@David - 谢谢。我沿着同样的思路思考。唉,A-32,Aarch32和Aarch64不是IA32。我昨天尝试了'.arch_extension',但是它导致了错误。 '.arch_extension'需要2016年的Binutils 2.26。2.26支持Aarch32和Aarch64。另请参阅Linaro Toolchain邮件列表上的[Error:unknown pseudo-op:'.arch_extension'](https://lists.linaro.org/pipermail/linaro-toolchain/2017-April/006112.html)。 – jww