eal/ppc: undefine AltiVec keyword vector
[dpdk.git] / lib / hash / rte_hash_crc.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #ifndef _RTE_HASH_CRC_H_
6 #define _RTE_HASH_CRC_H_
7
8 /**
9  * @file
10  *
11  * RTE CRC Hash
12  */
13
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17
18 #include <stdint.h>
19
20 #include <rte_branch_prediction.h>
21 #include <rte_common.h>
22 #include <rte_config.h>
23 #include <rte_cpuflags.h>
24 #include <rte_log.h>
25
26 #include "rte_crc_sw.h"
27
28 #define CRC32_SW            (1U << 0)
29 #define CRC32_SSE42         (1U << 1)
30 #define CRC32_x64           (1U << 2)
31 #define CRC32_SSE42_x64     (CRC32_x64|CRC32_SSE42)
32 #define CRC32_ARM64         (1U << 3)
33
34 static uint8_t crc32_alg = CRC32_SW;
35
36 #if defined(RTE_ARCH_ARM64) && defined(__ARM_FEATURE_CRC32)
37 #include "rte_crc_arm64.h"
38 #elif defined(RTE_ARCH_X86)
39 #include "rte_crc_x86.h"
40 #else
41 #include "rte_crc_generic.h"
42 #endif
43
44 /**
45  * Allow or disallow use of SSE4.2/ARMv8 intrinsics for CRC32 hash
46  * calculation.
47  *
48  * @param alg
49  *   An OR of following flags:
50  *   - (CRC32_SW) Don't use SSE4.2/ARMv8 intrinsics (default non-[x86/ARMv8])
51  *   - (CRC32_SSE42) Use SSE4.2 intrinsics if available
52  *   - (CRC32_SSE42_x64) Use 64-bit SSE4.2 intrinsic if available (default x86)
53  *   - (CRC32_ARM64) Use ARMv8 CRC intrinsic if available (default ARMv8)
54  *
55  */
56 static inline void
57 rte_hash_crc_set_alg(uint8_t alg)
58 {
59         crc32_alg = CRC32_SW;
60
61         if (alg == CRC32_SW)
62                 return;
63
64 #if defined RTE_ARCH_X86
65         if (!(alg & CRC32_SSE42_x64))
66                 RTE_LOG(WARNING, HASH,
67                         "Unsupported CRC32 algorithm requested using CRC32_x64/CRC32_SSE42\n");
68         if (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_EM64T) || alg == CRC32_SSE42)
69                 crc32_alg = CRC32_SSE42;
70         else
71                 crc32_alg = CRC32_SSE42_x64;
72 #endif
73
74 #if defined RTE_ARCH_ARM64
75         if (!(alg & CRC32_ARM64))
76                 RTE_LOG(WARNING, HASH,
77                         "Unsupported CRC32 algorithm requested using CRC32_ARM64\n");
78         if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_CRC32))
79                 crc32_alg = CRC32_ARM64;
80 #endif
81
82         if (crc32_alg == CRC32_SW)
83                 RTE_LOG(WARNING, HASH,
84                         "Unsupported CRC32 algorithm requested using CRC32_SW\n");
85 }
86
87 /* Setting the best available algorithm */
88 RTE_INIT(rte_hash_crc_init_alg)
89 {
90 #if defined(RTE_ARCH_X86)
91         rte_hash_crc_set_alg(CRC32_SSE42_x64);
92 #elif defined(RTE_ARCH_ARM64) && defined(__ARM_FEATURE_CRC32)
93         rte_hash_crc_set_alg(CRC32_ARM64);
94 #else
95         rte_hash_crc_set_alg(CRC32_SW);
96 #endif
97 }
98
99 #ifdef __DOXYGEN__
100
101 /**
102  * Use single CRC32 instruction to perform a hash on a byte value.
103  *
104  * @param data
105  *   Data to perform hash on.
106  * @param init_val
107  *   Value to initialise hash generator.
108  * @return
109  *   32bit calculated hash value.
110  */
111 static inline uint32_t
112 rte_hash_crc_1byte(uint8_t data, uint32_t init_val);
113
114 /**
115  * Use single CRC32 instruction to perform a hash on a 2 bytes value.
116  *
117  * @param data
118  *   Data to perform hash on.
119  * @param init_val
120  *   Value to initialise hash generator.
121  * @return
122  *   32bit calculated hash value.
123  */
124 static inline uint32_t
125 rte_hash_crc_2byte(uint16_t data, uint32_t init_val);
126
127 /**
128  * Use single CRC32 instruction to perform a hash on a 4 bytes value.
129  *
130  * @param data
131  *   Data to perform hash on.
132  * @param init_val
133  *   Value to initialise hash generator.
134  * @return
135  *   32bit calculated hash value.
136  */
137 static inline uint32_t
138 rte_hash_crc_4byte(uint32_t data, uint32_t init_val);
139
140 /**
141  * Use single CRC32 instruction to perform a hash on a 8 bytes value.
142  *
143  * @param data
144  *   Data to perform hash on.
145  * @param init_val
146  *   Value to initialise hash generator.
147  * @return
148  *   32bit calculated hash value.
149  */
150 static inline uint32_t
151 rte_hash_crc_8byte(uint64_t data, uint32_t init_val);
152
153 #endif /* __DOXYGEN__ */
154
155 /**
156  * Calculate CRC32 hash on user-supplied byte array.
157  *
158  * @param data
159  *   Data to perform hash on.
160  * @param data_len
161  *   How many bytes to use to calculate hash value.
162  * @param init_val
163  *   Value to initialise hash generator.
164  * @return
165  *   32bit calculated hash value.
166  */
167 static inline uint32_t
168 rte_hash_crc(const void *data, uint32_t data_len, uint32_t init_val)
169 {
170         unsigned i;
171         uintptr_t pd = (uintptr_t) data;
172
173         for (i = 0; i < data_len / 8; i++) {
174                 init_val = rte_hash_crc_8byte(*(const uint64_t *)pd, init_val);
175                 pd += 8;
176         }
177
178         if (data_len & 0x4) {
179                 init_val = rte_hash_crc_4byte(*(const uint32_t *)pd, init_val);
180                 pd += 4;
181         }
182
183         if (data_len & 0x2) {
184                 init_val = rte_hash_crc_2byte(*(const uint16_t *)pd, init_val);
185                 pd += 2;
186         }
187
188         if (data_len & 0x1)
189                 init_val = rte_hash_crc_1byte(*(const uint8_t *)pd, init_val);
190
191         return init_val;
192 }
193
194 #ifdef __cplusplus
195 }
196 #endif
197
198 #endif /* _RTE_HASH_CRC_H_ */