---
title: 替换x86 pcmpestrm汇编指令
description: "编译报错Error: unknown mnemonic 'pcmpestrm' -- 'pcmpestrm'。"
url: https://www.hikunpeng.com/document/detail/zh/kunpenggrf/codeprtr/kunpengtaishanporting_12_0038.html
sourcePath: /source/zh/kunpenggrf/codeprtr/kunpengtaishanporting_12_0038.html
indexId: f7847336c4da11dcd72f33c295f0452569d250524d13375dfb6862620107faca65
---
# 替换x86 pcmpestrm汇编指令

#### 现象描述

编译报错Error: unknown mnemonic 'pcmpestrm' -- 'pcmpestrm'。


#### 问题原因

pcmpestrm指令是x86指令集中SSE4中的指令。根据指令介绍，其用途是根据指定的比较模式，判断字符串str2的字节是否在str1中出现，将每个字节的对比结果返回（最大长度16字节）。该指令是典型的x86复杂指令，通过一条指令即完成复杂的字符串匹配功能，鲲鹏架构中无类似实现。对于这种指令，需要彻底了解其功能，通过C代码重新实现。

指令介绍：

https://software.intel.com/sites/landingpage/IntrinsicsGuide/#techs=SSE4_2&expand=835(https://software.intel.com/sites/landingpage/IntrinsicsGuide/#techs=SSE4_2&expand=835)

https://docs.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2010/bb514080(v=vs.100)(https://docs.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2010/bb514080(v=vs.100))


#### 处理步骤

如下代码段是Impala中对pcmpestrm指令的调用，该调用参考Intel的_mm_cmpestrm接口实现将pcmpestrm指令封装成SSE4_cmpestrm：


```
template<int MODE>
static inline __m128i SSE4_cmpestrm(__m128i str1, int len1, __m128i str2, int len2) {
#ifdef __clang__
/// Use asm reg rather than Yz output constraint to workaround LLVM bug 13199 -
/// clang doesn't support Y-prefixed asm constraints.
register volatile __m128i result asm ("xmm0");
__asm__ __volatile__ ("pcmpestrm %5, %2, %1": "=x"(result) : "x"(str1), "xm"(str2), "a"(len1), "d"(len2), "i"(MODE) : "cc");
#else
__m128i result;
__asm__ __volatile__ ("pcmpestrm %5, %2, %1": "=Yz"(result) : "x"(str1), "xm"(str2), "a"(len1), "d"(len2), "i"(MODE) : "cc");
#endif
return result;
}
```

从指令介绍中看，不同的模式所执行的操作差异较大，完全实现指令功能所需代码行太多。结合代码中对接口的调用，实际使用到的模式为PCMPSTR_EQUAL_ANY |PCMPSTR_UBYTE_OPS。即按照字节长度做匹配，对比str2中的每个字符是否在str1中出现，若出现，则将对应bit位置设置为1。

根据识别到的功能进行代码实现：

```
#include <arm_neon.h>
typedefunion __attribute__((aligned(16))) __oword {
int32x4_t m128i;
uint8_tm128i_u8[16];
} __oword;
template <int MODE>
static inline uint16_t SSE4_cmpestrm(int32x4_tstr1, intlen1, int32x4_tstr2, intlen2){
__oword a, b;
a.m128i = str1;
b.m128i = str2;
uint16_t result = 0;
uint16_t i = 0;
uint16_t j = 0;
// Impala中用到的模式 STRCHR_MODE = PCMPSTR_EQUAL_ANY | PCMPSTR_UBYTE_OPS
for (i = 0; i < len2; i++)
{
for (j = 0; j < len1; j++)
{
if (a.m128i_u8[j] == b.m128i_u8[i])
{
result |= (1 << i);
}
}
}
return result;
}
```

无直接替代指令的场景，需要结合指令功能、所需功能共同分析，切忌生搬硬套直接代码复制替换。
