中文
注册
我要评分
文档获取效率
文档正确性
内容完整性
文档易理解
在线提单
论坛求助

替换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。

表1 替换方法

指令

输入数据位宽(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;  
    }