diff --git a/src/suricata.c b/src/suricata.c index 293df00b23..ec5b7cfe4f 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -795,6 +795,12 @@ static void PrintBuildInfo(void) #endif #if defined(__SSE2__) strlcat(features, "SSE_2 ", sizeof(features)); +#endif +#if defined(__ARM_FEATURE_SVE) + strlcat(features, "SVE ", sizeof(features)); +#endif +#if defined(__ARM_NEON) + strlcat(features, "NEON ", sizeof(features)); #endif if (strlen(features) == 0) { strlcat(features, "none", sizeof(features)); diff --git a/src/util-memcmp.h b/src/util-memcmp.h index f9fc75357c..ec2c780af1 100644 --- a/src/util-memcmp.h +++ b/src/util-memcmp.h @@ -282,6 +282,94 @@ static inline int SCMemcmpLowercase(const void *s1, const void *s2, size_t len) return 0; } +#elif defined(__aarch64__) +#include + +#if defined(__ARM_FEATURE_SVE) +#include + +static inline int SCMemcmp(const void *s1, const void *s2, size_t len) +{ + uint64_t i = 0; + int vec_size = svcntb(); + svbool_t pg = svwhilelt_b8(i, len); + do { + svuint8_t b1 = svld1(pg, (uint8_t *)s1 + i); + svuint8_t b2 = svld1(pg, (uint8_t *)s2 + i); + svbool_t match = svcmpne(pg, b1, b2); + if (svptest_any(pg, match)) + return 1; + + i += vec_size; + pg = svwhilelt_b8(i, len); + } while (svptest_any(svptrue_b64(), pg)); + return 0; +} + +#else + +/* wrapper around memcmp to match the retvals of the SIMD implementations */ +#define SCMemcmp(a, b, c) ({ memcmp((a), (b), (c)) ? 1 : 0; }) + +#endif + +#define SCMEMCMP_BYTES 16 + +#define UPPER_LOW 0x41 /* "A" */ +#define UPPER_HIGH 0x5A /* "Z" */ +#define UPPER_DELTA 0x20 + +static inline int SCMemcmpLowercase(const void *s1, const void *s2, size_t len) +{ + size_t offset = 0; + uint8x16_t b1, mask1, mask2, delta, b3, equiv; + uint8x16_t b2, upper1, upper2; + uint64_t eqt, eqb; + + /* setup registers for upper to lower conversion */ + upper1 = vdupq_n_u8(UPPER_LOW); + upper2 = vdupq_n_u8(UPPER_HIGH); + delta = vdupq_n_u8(UPPER_DELTA); + + do { + if (likely(len - offset < SCMEMCMP_BYTES)) { + return MemcmpLowercase(s1, s2, len - offset); + } + + /* unaligned loading of the bytes to compare */ + b1 = vld1q_u8(s1); + b2 = vld1q_u8(s2); + + /* mark all chars bigger than upper1 */ + mask1 = vcgeq_u8(b2, upper1); + /* mark all chars lower than upper2 */ + mask2 = vcleq_u8(b2, upper2); + /* merge the two, leaving only those that are true in both */ + mask1 = vandq_u8(mask1, mask2); + + /* Generate only 0x20 which is the delta from a upper-case to lower-case */ + mask1 = vandq_u8(mask1, delta); + + /* add 0x20 to each upper case value */ + b3 = vaddq_u8(b2, mask1); + + /* do the actual compare */ + equiv = vceqq_u8(b1, b3); + + /* move the values to a GP */ + eqb = vgetq_lane_u64(vreinterpretq_u64_u8(equiv), 0); + eqt = vgetq_lane_u64(vreinterpretq_u64_u8(equiv), 1); + + if (!(~eqb == 0 && ~eqt == 0)) { + return 1; + } + offset += SCMEMCMP_BYTES; + s1 += SCMEMCMP_BYTES; + s2 += SCMEMCMP_BYTES; + } while (len > offset); + + return 0; +} #else /* No SIMD support, fall back to plain memcmp and a home grown lowercase one */