aboutsummaryrefslogtreecommitdiff
path: root/platform/linux-generic/arch/x86
diff options
context:
space:
mode:
authorJere Leppänen <jere.leppanen@nokia.com>2021-03-23 20:38:33 +0200
committerPetri Savolainen <petri.savolainen@nokia.com>2021-04-07 14:16:15 +0300
commitf4dffdf0badcc8340540aaf6b248a5030a13fd36 (patch)
treebaf54cc6ffc254664ed9d35f750e02dbf9e49c9c /platform/linux-generic/arch/x86
parent8e0e67e3ed4af071056ac48545ffb82cbb4bf283 (diff)
linux-gen: hash: use x86 crc32 instructions
Use x86 SSE 4.2 crc32 instructions via gcc builtin functions, if available. These instructions support crc32c only. Signed-off-by: Jere Leppänen <jere.leppanen@nokia.com> Reviewed-by: Petri Savolainen <petri.savolainen@nokia.com>
Diffstat (limited to 'platform/linux-generic/arch/x86')
-rw-r--r--platform/linux-generic/arch/x86/odp/api/abi/hash_crc32.h77
1 files changed, 77 insertions, 0 deletions
diff --git a/platform/linux-generic/arch/x86/odp/api/abi/hash_crc32.h b/platform/linux-generic/arch/x86/odp/api/abi/hash_crc32.h
new file mode 100644
index 000000000..ae31d75fc
--- /dev/null
+++ b/platform/linux-generic/arch/x86/odp/api/abi/hash_crc32.h
@@ -0,0 +1,77 @@
+/* Copyright (c) 2021, Nokia
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ODP_API_ABI_HASH_CRC32_H_
+#define ODP_API_ABI_HASH_CRC32_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+uint32_t _odp_hash_crc32_generic(const void *data, uint32_t data_len,
+ uint32_t init_val);
+uint32_t _odp_hash_crc32c_generic(const void *data, uint32_t data_len,
+ uint32_t init_val);
+
+static inline uint32_t _odp_hash_crc32(const void *data, uint32_t data_len,
+ uint32_t init_val)
+{
+ return _odp_hash_crc32_generic(data, data_len, init_val);
+}
+
+#ifdef __SSE4_2__
+
+static inline uint32_t _odp_hash_crc32c(const void *data, uint32_t data_len,
+ uint32_t init_val)
+{
+ uint32_t i;
+ uintptr_t pd = (uintptr_t)data;
+
+#ifdef __x86_64__
+ for (i = 0; i < data_len / 8; i++) {
+ init_val = __builtin_ia32_crc32di(init_val, *(const uint64_t *)pd);
+ pd += 8;
+ }
+
+ if (data_len & 0x4) {
+ init_val = __builtin_ia32_crc32si(init_val, *(const uint32_t *)pd);
+ pd += 4;
+ }
+#else
+ for (i = 0; i < data_len / 4; i++) {
+ init_val = __builtin_ia32_crc32si(init_val, *(const uint32_t *)pd);
+ pd += 4;
+ }
+#endif
+
+ if (data_len & 0x2) {
+ init_val = __builtin_ia32_crc32hi(init_val, *(const uint16_t *)pd);
+ pd += 2;
+ }
+
+ if (data_len & 0x1)
+ init_val = __builtin_ia32_crc32qi(init_val, *(const uint8_t *)pd);
+
+ return init_val;
+}
+
+#else
+
+static inline uint32_t _odp_hash_crc32c(const void *data, uint32_t data_len,
+ uint32_t init_val)
+{
+ return _odp_hash_crc32c_generic(data, data_len, init_val);
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif