diff options
author | Jere Leppänen <jere.leppanen@nokia.com> | 2021-03-23 20:38:33 +0200 |
---|---|---|
committer | Petri Savolainen <petri.savolainen@nokia.com> | 2021-04-07 14:16:15 +0300 |
commit | f4dffdf0badcc8340540aaf6b248a5030a13fd36 (patch) | |
tree | baf54cc6ffc254664ed9d35f750e02dbf9e49c9c /platform/linux-generic/arch/x86 | |
parent | 8e0e67e3ed4af071056ac48545ffb82cbb4bf283 (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.h | 77 |
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 |