替换x86 CRC32汇编指令
现象描述
编译错误:unknown mnemonic 'crc32q' -- 'crc32q (x3),x2'或operand 1 should be an integer register -- 'crc32b (x1),x0'或unrecognized command line option ‘-msse4.2’。
可能原因
x86使用的是crc32b和crc32q汇编指令完成CRC32C校验值计算功能,而Arm64平台使用crc32cb、crc32ch、crc32cw、crc32cx 4个汇编指令完成CRC32C校验值计算功能。
处理步骤
请使用crc32cb、crc32ch、crc32cw、crc32cx取代x86的CRC32系列汇编指令,替换方法如表1所示,并在编译时添加编译参数-mcpu=generic+crc。
指令 |
输入数据位宽(bit) |
备注 |
---|---|---|
crc32cb |
8 |
适用输入数据位宽为8bit,可用于替换x86的crc32b汇编指令。 |
crc32ch |
16 |
适用输入数据位宽为16bit。 |
crc32cw |
32 |
适用输入数据位宽为32bit。 |
crc32cx |
64 |
适用输入数据位宽为64bit,可用于替换x86的crc32q汇编指令。 |
示例:
- 在x86下的实现:
#define CRC32CB(crc, value) __asm__("crc32b\t" "(%1), %0" : "=r"(crc) : "r"(value), "0"(crc)) #define CRC32CP(crc, value) __asm__("crc32q\t" "(%1), %0" : "=r"(crc) : "r"(value), "0"(crc)) uint32_t crc32c(uint32_t crc, void const *buf, unsigned int len) { uint64_t crc0 = crc; unsigned char const *next = buf; unsigned char const * const end = next + (len - (len & 7)); while (next < end) { CRC32CP(crc0, next); next += 8; } len &= 7; while (len) { CRC32CB(crc0, next); next++; len--; } return crc0; }
- 在Arm64平台下的实现:
#define CRC32CX(crc, value) __asm__("crc32cx %w[c], %w[c], %x[v]":[c]"+r"(crc):[v]"r"(value)) #define CRC32CW(crc, value) __asm__("crc32cw %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value)) #define CRC32CH(crc, value) __asm__("crc32ch %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value)) #define CRC32CB(crc, value) __asm__("crc32cb %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value)) uint32_t crc32c_arm64_le_hw(uint32_t crc, const uint8_t *p, unsigned int len) { int64_t length = len; while ((length -= sizeof(uint64_t)) >= 0) { CRC32CX(crc, *((uint64_t *)p)); p += sizeof(uint64_t); } if (length & sizeof(uint32_t)) { CRC32CW(crc, *((uint32_t *)p)); p += sizeof(uint32_t); } if (length & sizeof(uint16_t)) { CRC32CH(crc, *((uint16_t *)p)); p += sizeof(uint16_t); } if (length & sizeof(uint8_t)) { CRC32CB(crc, *p); } return crc; }
父主题: 源码修改类案例