Apollo 11.0
自动驾驶开放平台
sse2neon.h
浏览该文件的文档.
1#ifndef SSE2NEON_H
2#define SSE2NEON_H
3
4// This header file provides a simple API translation layer
5// between SSE intrinsics to their corresponding Arm/Aarch64 NEON versions
6//
7// Contributors to this work are:
8// John W. Ratcliff <jratcliffscarab@gmail.com>
9// Brandon Rowlett <browlett@nvidia.com>
10// Ken Fast <kfast@gdeb.com>
11// Eric van Beurden <evanbeurden@nvidia.com>
12// Alexander Potylitsin <apotylitsin@nvidia.com>
13// Hasindu Gamaarachchi <hasindu2008@gmail.com>
14// Jim Huang <jserv@ccns.ncku.edu.tw>
15// Mark Cheng <marktwtn@gmail.com>
16// Malcolm James MacLeod <malcolm@gulden.com>
17// Devin Hussey (easyaspi314) <husseydevin@gmail.com>
18// Sebastian Pop <spop@amazon.com>
19// Developer Ecosystem Engineering <DeveloperEcosystemEngineering@apple.com>
20// Danila Kutenin <danilak@google.com>
21// François Turban (JishinMaster) <francois.turban@gmail.com>
22// Pei-Hsuan Hung <afcidk@gmail.com>
23// Yang-Hao Yuan <yuanyanghau@gmail.com>
24// Syoyo Fujita <syoyo@lighttransport.com>
25// Brecht Van Lommel <brecht@blender.org>
26// Jonathan Hue <jhue@adobe.com>
27// Cuda Chen <clh960524@gmail.com>
28// Aymen Qader <aymen.qader@arm.com>
29
30/*
31 * sse2neon is freely redistributable under the MIT License.
32 *
33 * Permission is hereby granted, free of charge, to any person obtaining a copy
34 * of this software and associated documentation files (the "Software"), to deal
35 * in the Software without restriction, including without limitation the rights
36 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
37 * copies of the Software, and to permit persons to whom the Software is
38 * furnished to do so, subject to the following conditions:
39 *
40 * The above copyright notice and this permission notice shall be included in
41 * all copies or substantial portions of the Software.
42 *
43 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
46 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
47 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
48 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
49 * SOFTWARE.
50 */
51
52/* Tunable configurations */
53
54/* Enable precise implementation of math operations
55 * This would slow down the computation a bit, but gives consistent result with
56 * x86 SSE. (e.g. would solve a hole or NaN pixel in the rendering result)
57 */
58/* _mm_min|max_ps|ss|pd|sd */
59#ifndef SSE2NEON_PRECISE_MINMAX
60#define SSE2NEON_PRECISE_MINMAX (0)
61#endif
62/* _mm_rcp_ps and _mm_div_ps */
63#ifndef SSE2NEON_PRECISE_DIV
64#define SSE2NEON_PRECISE_DIV (0)
65#endif
66/* _mm_sqrt_ps and _mm_rsqrt_ps */
67#ifndef SSE2NEON_PRECISE_SQRT
68#define SSE2NEON_PRECISE_SQRT (0)
69#endif
70/* _mm_dp_pd */
71#ifndef SSE2NEON_PRECISE_DP
72#define SSE2NEON_PRECISE_DP (0)
73#endif
74
75/* compiler specific definitions */
76#if defined(__GNUC__) || defined(__clang__)
77#pragma push_macro("FORCE_INLINE")
78#pragma push_macro("ALIGN_STRUCT")
79#define FORCE_INLINE static inline __attribute__((always_inline))
80#define ALIGN_STRUCT(x) __attribute__((aligned(x)))
81#define _sse2neon_likely(x) __builtin_expect(!!(x), 1)
82#define _sse2neon_unlikely(x) __builtin_expect(!!(x), 0)
83#else /* non-GNU / non-clang compilers */
84#warning "Macro name collisions may happen with unsupported compiler."
85#ifndef FORCE_INLINE
86#define FORCE_INLINE static inline
87#endif
88#ifndef ALIGN_STRUCT
89#define ALIGN_STRUCT(x) __declspec(align(x))
90#endif
91#define _sse2neon_likely(x) (x)
92#define _sse2neon_unlikely(x) (x)
93#endif
94
95/* C language does not allow initializing a variable with a function call. */
96#ifdef __cplusplus
97#define _sse2neon_const static const
98#else
99#define _sse2neon_const const
100#endif
101
102#include <stdint.h>
103#include <stdlib.h>
104
105#if defined(_WIN32)
106/* Definitions for _mm_{malloc,free} are provided by <malloc.h>
107 * from both MinGW-w64 and MSVC.
108 */
109#define SSE2NEON_ALLOC_DEFINED
110#endif
111
112/* If using MSVC */
113#ifdef _MSC_VER
114#include <intrin.h>
115#if (defined(_M_AMD64) || defined(__x86_64__)) || \
116 (defined(_M_ARM) || defined(__arm__))
117#define SSE2NEON_HAS_BITSCAN64
118#endif
119#endif
120
121/* Compiler barrier */
122#define SSE2NEON_BARRIER() \
123 do { \
124 __asm__ __volatile__("" ::: "memory"); \
125 (void) 0; \
126 } while (0)
127
128/* Memory barriers
129 * __atomic_thread_fence does not include a compiler barrier; instead,
130 * the barrier is part of __atomic_load/__atomic_store's "volatile-like"
131 * semantics.
132 */
133#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
134#include <stdatomic.h>
135#endif
136
138{
140#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
141 !defined(__STDC_NO_ATOMICS__)
142 atomic_thread_fence(memory_order_seq_cst);
143#elif defined(__GNUC__) || defined(__clang__)
144 __atomic_thread_fence(__ATOMIC_SEQ_CST);
145#else
146 /* FIXME: MSVC support */
147#endif
148}
149
150/* Architecture-specific build options */
151/* FIXME: #pragma GCC push_options is only available on GCC */
152#if defined(__GNUC__)
153#if defined(__arm__) && __ARM_ARCH == 7
154/* According to ARM C Language Extensions Architecture specification,
155 * __ARM_NEON is defined to a value indicating the Advanced SIMD (NEON)
156 * architecture supported.
157 */
158#if !defined(__ARM_NEON) || !defined(__ARM_NEON__)
159#error "You must enable NEON instructions (e.g. -mfpu=neon) to use SSE2NEON."
160#endif
161#if !defined(__clang__)
162#pragma GCC push_options
163#pragma GCC target("fpu=neon")
164#endif
165#elif defined(__aarch64__)
166#if !defined(__clang__)
167#pragma GCC push_options
168#pragma GCC target("+simd")
169#endif
170#elif __ARM_ARCH == 8
171#if !defined(__ARM_NEON) || !defined(__ARM_NEON__)
172#error \
173 "You must enable NEON instructions (e.g. -mfpu=neon-fp-armv8) to use SSE2NEON."
174#endif
175#if !defined(__clang__)
176#pragma GCC push_options
177#endif
178#else
179#error "Unsupported target. Must be either ARMv7-A+NEON or ARMv8-A."
180#endif
181#endif
182
183#include <arm_neon.h>
184#if !defined(__aarch64__) && (__ARM_ARCH == 8)
185#if defined __has_include && __has_include(<arm_acle.h>)
186#include <arm_acle.h>
187#endif
188#endif
189
190/* Apple Silicon cache lines are double of what is commonly used by Intel, AMD
191 * and other Arm microarchtectures use.
192 * From sysctl -a on Apple M1:
193 * hw.cachelinesize: 128
194 */
195#if defined(__APPLE__) && (defined(__aarch64__) || defined(__arm64__))
196#define SSE2NEON_CACHELINE_SIZE 128
197#else
198#define SSE2NEON_CACHELINE_SIZE 64
199#endif
200
201/* Rounding functions require either Aarch64 instructions or libm failback */
202#if !defined(__aarch64__)
203#include <math.h>
204#endif
205
206/* On ARMv7, some registers, such as PMUSERENR and PMCCNTR, are read-only
207 * or even not accessible in user mode.
208 * To write or access to these registers in user mode,
209 * we have to perform syscall instead.
210 */
211#if !defined(__aarch64__)
212#include <sys/time.h>
213#endif
214
215/* "__has_builtin" can be used to query support for built-in functions
216 * provided by gcc/clang and other compilers that support it.
217 */
218#ifndef __has_builtin /* GCC prior to 10 or non-clang compilers */
219/* Compatibility with gcc <= 9 */
220#if defined(__GNUC__) && (__GNUC__ <= 9)
221#define __has_builtin(x) HAS##x
222#define HAS__builtin_popcount 1
223#define HAS__builtin_popcountll 1
224
225// __builtin_shuffle introduced in GCC 4.7.0
226#if (__GNUC__ >= 5) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7))
227#define HAS__builtin_shuffle 1
228#else
229#define HAS__builtin_shuffle 0
230#endif
231
232#define HAS__builtin_shufflevector 0
233#define HAS__builtin_nontemporal_store 0
234#else
235#define __has_builtin(x) 0
236#endif
237#endif
238
247#define _MM_SHUFFLE(fp3, fp2, fp1, fp0) \
248 (((fp3) << 6) | ((fp2) << 4) | ((fp1) << 2) | ((fp0)))
249
250#if __has_builtin(__builtin_shufflevector)
251#define _sse2neon_shuffle(type, a, b, ...) \
252 __builtin_shufflevector(a, b, __VA_ARGS__)
253#elif __has_builtin(__builtin_shuffle)
254#define _sse2neon_shuffle(type, a, b, ...) \
255 __extension__({ \
256 type tmp = {__VA_ARGS__}; \
257 __builtin_shuffle(a, b, tmp); \
258 })
259#endif
260
261#ifdef _sse2neon_shuffle
262#define vshuffle_s16(a, b, ...) _sse2neon_shuffle(int16x4_t, a, b, __VA_ARGS__)
263#define vshuffleq_s16(a, b, ...) _sse2neon_shuffle(int16x8_t, a, b, __VA_ARGS__)
264#define vshuffle_s32(a, b, ...) _sse2neon_shuffle(int32x2_t, a, b, __VA_ARGS__)
265#define vshuffleq_s32(a, b, ...) _sse2neon_shuffle(int32x4_t, a, b, __VA_ARGS__)
266#define vshuffle_s64(a, b, ...) _sse2neon_shuffle(int64x1_t, a, b, __VA_ARGS__)
267#define vshuffleq_s64(a, b, ...) _sse2neon_shuffle(int64x2_t, a, b, __VA_ARGS__)
268#endif
269
270/* Rounding mode macros. */
271#define _MM_FROUND_TO_NEAREST_INT 0x00
272#define _MM_FROUND_TO_NEG_INF 0x01
273#define _MM_FROUND_TO_POS_INF 0x02
274#define _MM_FROUND_TO_ZERO 0x03
275#define _MM_FROUND_CUR_DIRECTION 0x04
276#define _MM_FROUND_NO_EXC 0x08
277#define _MM_FROUND_RAISE_EXC 0x00
278#define _MM_FROUND_NINT (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_RAISE_EXC)
279#define _MM_FROUND_FLOOR (_MM_FROUND_TO_NEG_INF | _MM_FROUND_RAISE_EXC)
280#define _MM_FROUND_CEIL (_MM_FROUND_TO_POS_INF | _MM_FROUND_RAISE_EXC)
281#define _MM_FROUND_TRUNC (_MM_FROUND_TO_ZERO | _MM_FROUND_RAISE_EXC)
282#define _MM_FROUND_RINT (_MM_FROUND_CUR_DIRECTION | _MM_FROUND_RAISE_EXC)
283#define _MM_FROUND_NEARBYINT (_MM_FROUND_CUR_DIRECTION | _MM_FROUND_NO_EXC)
284#define _MM_ROUND_NEAREST 0x0000
285#define _MM_ROUND_DOWN 0x2000
286#define _MM_ROUND_UP 0x4000
287#define _MM_ROUND_TOWARD_ZERO 0x6000
288/* Flush zero mode macros. */
289#define _MM_FLUSH_ZERO_MASK 0x8000
290#define _MM_FLUSH_ZERO_ON 0x8000
291#define _MM_FLUSH_ZERO_OFF 0x0000
292/* Denormals are zeros mode macros. */
293#define _MM_DENORMALS_ZERO_MASK 0x0040
294#define _MM_DENORMALS_ZERO_ON 0x0040
295#define _MM_DENORMALS_ZERO_OFF 0x0000
296
297/* indicate immediate constant argument in a given range */
298#define __constrange(a, b) const
299
300/* A few intrinsics accept traditional data types like ints or floats, but
301 * most operate on data types that are specific to SSE.
302 * If a vector type ends in d, it contains doubles, and if it does not have
303 * a suffix, it contains floats. An integer vector type can contain any type
304 * of integer, from chars to shorts to unsigned long longs.
305 */
306typedef int64x1_t __m64;
307typedef float32x4_t __m128; /* 128-bit vector containing 4 floats */
308// On ARM 32-bit architecture, the float64x2_t is not supported.
309// The data type __m128d should be represented in a different way for related
310// intrinsic conversion.
311#if defined(__aarch64__)
312typedef float64x2_t __m128d; /* 128-bit vector containing 2 doubles */
313#else
314typedef float32x4_t __m128d;
315#endif
316typedef int64x2_t __m128i; /* 128-bit vector containing integers */
317
318// __int64 is defined in the Intrinsics Guide which maps to different datatype
319// in different data model
320#if !(defined(_WIN32) || defined(_WIN64) || defined(__int64))
321#if (defined(__x86_64__) || defined(__i386__))
322#define __int64 long long
323#else
324#define __int64 int64_t
325#endif
326#endif
327
328/* type-safe casting between types */
329
330#define vreinterpretq_m128_f16(x) vreinterpretq_f32_f16(x)
331#define vreinterpretq_m128_f32(x) (x)
332#define vreinterpretq_m128_f64(x) vreinterpretq_f32_f64(x)
333
334#define vreinterpretq_m128_u8(x) vreinterpretq_f32_u8(x)
335#define vreinterpretq_m128_u16(x) vreinterpretq_f32_u16(x)
336#define vreinterpretq_m128_u32(x) vreinterpretq_f32_u32(x)
337#define vreinterpretq_m128_u64(x) vreinterpretq_f32_u64(x)
338
339#define vreinterpretq_m128_s8(x) vreinterpretq_f32_s8(x)
340#define vreinterpretq_m128_s16(x) vreinterpretq_f32_s16(x)
341#define vreinterpretq_m128_s32(x) vreinterpretq_f32_s32(x)
342#define vreinterpretq_m128_s64(x) vreinterpretq_f32_s64(x)
343
344#define vreinterpretq_f16_m128(x) vreinterpretq_f16_f32(x)
345#define vreinterpretq_f32_m128(x) (x)
346#define vreinterpretq_f64_m128(x) vreinterpretq_f64_f32(x)
347
348#define vreinterpretq_u8_m128(x) vreinterpretq_u8_f32(x)
349#define vreinterpretq_u16_m128(x) vreinterpretq_u16_f32(x)
350#define vreinterpretq_u32_m128(x) vreinterpretq_u32_f32(x)
351#define vreinterpretq_u64_m128(x) vreinterpretq_u64_f32(x)
352
353#define vreinterpretq_s8_m128(x) vreinterpretq_s8_f32(x)
354#define vreinterpretq_s16_m128(x) vreinterpretq_s16_f32(x)
355#define vreinterpretq_s32_m128(x) vreinterpretq_s32_f32(x)
356#define vreinterpretq_s64_m128(x) vreinterpretq_s64_f32(x)
357
358#define vreinterpretq_m128i_s8(x) vreinterpretq_s64_s8(x)
359#define vreinterpretq_m128i_s16(x) vreinterpretq_s64_s16(x)
360#define vreinterpretq_m128i_s32(x) vreinterpretq_s64_s32(x)
361#define vreinterpretq_m128i_s64(x) (x)
362
363#define vreinterpretq_m128i_u8(x) vreinterpretq_s64_u8(x)
364#define vreinterpretq_m128i_u16(x) vreinterpretq_s64_u16(x)
365#define vreinterpretq_m128i_u32(x) vreinterpretq_s64_u32(x)
366#define vreinterpretq_m128i_u64(x) vreinterpretq_s64_u64(x)
367
368#define vreinterpretq_f32_m128i(x) vreinterpretq_f32_s64(x)
369#define vreinterpretq_f64_m128i(x) vreinterpretq_f64_s64(x)
370
371#define vreinterpretq_s8_m128i(x) vreinterpretq_s8_s64(x)
372#define vreinterpretq_s16_m128i(x) vreinterpretq_s16_s64(x)
373#define vreinterpretq_s32_m128i(x) vreinterpretq_s32_s64(x)
374#define vreinterpretq_s64_m128i(x) (x)
375
376#define vreinterpretq_u8_m128i(x) vreinterpretq_u8_s64(x)
377#define vreinterpretq_u16_m128i(x) vreinterpretq_u16_s64(x)
378#define vreinterpretq_u32_m128i(x) vreinterpretq_u32_s64(x)
379#define vreinterpretq_u64_m128i(x) vreinterpretq_u64_s64(x)
380
381#define vreinterpret_m64_s8(x) vreinterpret_s64_s8(x)
382#define vreinterpret_m64_s16(x) vreinterpret_s64_s16(x)
383#define vreinterpret_m64_s32(x) vreinterpret_s64_s32(x)
384#define vreinterpret_m64_s64(x) (x)
385
386#define vreinterpret_m64_u8(x) vreinterpret_s64_u8(x)
387#define vreinterpret_m64_u16(x) vreinterpret_s64_u16(x)
388#define vreinterpret_m64_u32(x) vreinterpret_s64_u32(x)
389#define vreinterpret_m64_u64(x) vreinterpret_s64_u64(x)
390
391#define vreinterpret_m64_f16(x) vreinterpret_s64_f16(x)
392#define vreinterpret_m64_f32(x) vreinterpret_s64_f32(x)
393#define vreinterpret_m64_f64(x) vreinterpret_s64_f64(x)
394
395#define vreinterpret_u8_m64(x) vreinterpret_u8_s64(x)
396#define vreinterpret_u16_m64(x) vreinterpret_u16_s64(x)
397#define vreinterpret_u32_m64(x) vreinterpret_u32_s64(x)
398#define vreinterpret_u64_m64(x) vreinterpret_u64_s64(x)
399
400#define vreinterpret_s8_m64(x) vreinterpret_s8_s64(x)
401#define vreinterpret_s16_m64(x) vreinterpret_s16_s64(x)
402#define vreinterpret_s32_m64(x) vreinterpret_s32_s64(x)
403#define vreinterpret_s64_m64(x) (x)
404
405#define vreinterpret_f32_m64(x) vreinterpret_f32_s64(x)
406
407#if defined(__aarch64__)
408#define vreinterpretq_m128d_s32(x) vreinterpretq_f64_s32(x)
409#define vreinterpretq_m128d_s64(x) vreinterpretq_f64_s64(x)
410
411#define vreinterpretq_m128d_u64(x) vreinterpretq_f64_u64(x)
412
413#define vreinterpretq_m128d_f32(x) vreinterpretq_f64_f32(x)
414#define vreinterpretq_m128d_f64(x) (x)
415
416#define vreinterpretq_s64_m128d(x) vreinterpretq_s64_f64(x)
417
418#define vreinterpretq_u32_m128d(x) vreinterpretq_u32_f64(x)
419#define vreinterpretq_u64_m128d(x) vreinterpretq_u64_f64(x)
420
421#define vreinterpretq_f64_m128d(x) (x)
422#define vreinterpretq_f32_m128d(x) vreinterpretq_f32_f64(x)
423#else
424#define vreinterpretq_m128d_s32(x) vreinterpretq_f32_s32(x)
425#define vreinterpretq_m128d_s64(x) vreinterpretq_f32_s64(x)
426
427#define vreinterpretq_m128d_u32(x) vreinterpretq_f32_u32(x)
428#define vreinterpretq_m128d_u64(x) vreinterpretq_f32_u64(x)
429
430#define vreinterpretq_m128d_f32(x) (x)
431
432#define vreinterpretq_s64_m128d(x) vreinterpretq_s64_f32(x)
433
434#define vreinterpretq_u32_m128d(x) vreinterpretq_u32_f32(x)
435#define vreinterpretq_u64_m128d(x) vreinterpretq_u64_f32(x)
436
437#define vreinterpretq_f32_m128d(x) (x)
438#endif
439
440// A struct is defined in this header file called 'SIMDVec' which can be used
441// by applications which attempt to access the contents of an __m128 struct
442// directly. It is important to note that accessing the __m128 struct directly
443// is bad coding practice by Microsoft: @see:
444// https://docs.microsoft.com/en-us/cpp/cpp/m128
445//
446// However, some legacy source code may try to access the contents of an __m128
447// struct directly so the developer can use the SIMDVec as an alias for it. Any
448// casting must be done manually by the developer, as you cannot cast or
449// otherwise alias the base NEON data type for intrinsic operations.
450//
451// union intended to allow direct access to an __m128 variable using the names
452// that the MSVC compiler provides. This union should really only be used when
453// trying to access the members of the vector as integer values. GCC/clang
454// allow native access to the float members through a simple array access
455// operator (in C since 4.6, in C++ since 4.8).
456//
457// Ideally direct accesses to SIMD vectors should not be used since it can cause
458// a performance hit. If it really is needed however, the original __m128
459// variable can be aliased with a pointer to this union and used to access
460// individual components. The use of this union should be hidden behind a macro
461// that is used throughout the codebase to access the members instead of always
462// declaring this type of variable.
463typedef union ALIGN_STRUCT(16) SIMDVec {
464 float m128_f32[4]; // as floats - DON'T USE. Added for convenience.
465 int8_t m128_i8[16]; // as signed 8-bit integers.
466 int16_t m128_i16[8]; // as signed 16-bit integers.
467 int32_t m128_i32[4]; // as signed 32-bit integers.
468 int64_t m128_i64[2]; // as signed 64-bit integers.
469 uint8_t m128_u8[16]; // as unsigned 8-bit integers.
470 uint16_t m128_u16[8]; // as unsigned 16-bit integers.
471 uint32_t m128_u32[4]; // as unsigned 32-bit integers.
472 uint64_t m128_u64[2]; // as unsigned 64-bit integers.
474
475// casting using SIMDVec
476#define vreinterpretq_nth_u64_m128i(x, n) (((SIMDVec *) &x)->m128_u64[n])
477#define vreinterpretq_nth_u32_m128i(x, n) (((SIMDVec *) &x)->m128_u32[n])
478#define vreinterpretq_nth_u8_m128i(x, n) (((SIMDVec *) &x)->m128_u8[n])
479
480/* SSE macros */
481#define _MM_GET_FLUSH_ZERO_MODE _sse2neon_mm_get_flush_zero_mode
482#define _MM_SET_FLUSH_ZERO_MODE _sse2neon_mm_set_flush_zero_mode
483#define _MM_GET_DENORMALS_ZERO_MODE _sse2neon_mm_get_denormals_zero_mode
484#define _MM_SET_DENORMALS_ZERO_MODE _sse2neon_mm_set_denormals_zero_mode
485
486// Function declaration
487// SSE
493// SSE2
500FORCE_INLINE __m128i _mm_set_epi32(int, int, int, int);
501FORCE_INLINE __m128i _mm_set_epi64x(int64_t, int64_t);
502FORCE_INLINE __m128d _mm_set_pd(double, double);
505// SSE4.1
512// SSE4.2
513FORCE_INLINE uint32_t _mm_crc32_u8(uint32_t, uint8_t);
514
515/* Backwards compatibility for compilers with lack of specific type support */
516
517// Older gcc does not define vld1q_u8_x4 type
518#if defined(__GNUC__) && !defined(__clang__) && \
519 ((__GNUC__ <= 12 && defined(__arm__)) || \
520 (__GNUC__ == 10 && __GNUC_MINOR__ < 3 && defined(__aarch64__)) || \
521 (__GNUC__ <= 9 && defined(__aarch64__)))
522FORCE_INLINE uint8x16x4_t _sse2neon_vld1q_u8_x4(const uint8_t *p)
523{
524 uint8x16x4_t ret;
525 ret.val[0] = vld1q_u8(p + 0);
526 ret.val[1] = vld1q_u8(p + 16);
527 ret.val[2] = vld1q_u8(p + 32);
528 ret.val[3] = vld1q_u8(p + 48);
529 return ret;
530}
531#else
532// Wraps vld1q_u8_x4
533FORCE_INLINE uint8x16x4_t _sse2neon_vld1q_u8_x4(const uint8_t *p)
534{
535 return vld1q_u8_x4(p);
536}
537#endif
538
539#if !defined(__aarch64__)
540/* emulate vaddv u8 variant */
541FORCE_INLINE uint8_t _sse2neon_vaddv_u8(uint8x8_t v8)
542{
543 const uint64x1_t v1 = vpaddl_u32(vpaddl_u16(vpaddl_u8(v8)));
544 return vget_lane_u8(vreinterpret_u8_u64(v1), 0);
545}
546#else
547// Wraps vaddv_u8
548FORCE_INLINE uint8_t _sse2neon_vaddv_u8(uint8x8_t v8)
549{
550 return vaddv_u8(v8);
551}
552#endif
553
554#if !defined(__aarch64__)
555/* emulate vaddvq u8 variant */
557{
558 uint8x8_t tmp = vpadd_u8(vget_low_u8(a), vget_high_u8(a));
559 uint8_t res = 0;
560 for (int i = 0; i < 8; ++i)
561 res += tmp[i];
562 return res;
563}
564#else
565// Wraps vaddvq_u8
566FORCE_INLINE uint8_t _sse2neon_vaddvq_u8(uint8x16_t a)
567{
568 return vaddvq_u8(a);
569}
570#endif
571
572#if !defined(__aarch64__)
573/* emulate vaddvq u16 variant */
574FORCE_INLINE uint16_t _sse2neon_vaddvq_u16(uint16x8_t a)
575{
576 uint32x4_t m = vpaddlq_u16(a);
577 uint64x2_t n = vpaddlq_u32(m);
578 uint64x1_t o = vget_low_u64(n) + vget_high_u64(n);
579
580 return vget_lane_u32((uint32x2_t) o, 0);
581}
582#else
583// Wraps vaddvq_u16
584FORCE_INLINE uint16_t _sse2neon_vaddvq_u16(uint16x8_t a)
585{
586 return vaddvq_u16(a);
587}
588#endif
589
590/* Function Naming Conventions
591 * The naming convention of SSE intrinsics is straightforward. A generic SSE
592 * intrinsic function is given as follows:
593 * _mm_<name>_<data_type>
594 *
595 * The parts of this format are given as follows:
596 * 1. <name> describes the operation performed by the intrinsic
597 * 2. <data_type> identifies the data type of the function's primary arguments
598 *
599 * This last part, <data_type>, is a little complicated. It identifies the
600 * content of the input values, and can be set to any of the following values:
601 * + ps - vectors contain floats (ps stands for packed single-precision)
602 * + pd - vectors cantain doubles (pd stands for packed double-precision)
603 * + epi8/epi16/epi32/epi64 - vectors contain 8-bit/16-bit/32-bit/64-bit
604 * signed integers
605 * + epu8/epu16/epu32/epu64 - vectors contain 8-bit/16-bit/32-bit/64-bit
606 * unsigned integers
607 * + si128 - unspecified 128-bit vector or 256-bit vector
608 * + m128/m128i/m128d - identifies input vector types when they are different
609 * than the type of the returned vector
610 *
611 * For example, _mm_setzero_ps. The _mm implies that the function returns
612 * a 128-bit vector. The _ps at the end implies that the argument vectors
613 * contain floats.
614 *
615 * A complete example: Byte Shuffle - pshufb (_mm_shuffle_epi8)
616 * // Set packed 16-bit integers. 128 bits, 8 short, per 16 bits
617 * __m128i v_in = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8);
618 * // Set packed 8-bit integers
619 * // 128 bits, 16 chars, per 8 bits
620 * __m128i v_perm = _mm_setr_epi8(1, 0, 2, 3, 8, 9, 10, 11,
621 * 4, 5, 12, 13, 6, 7, 14, 15);
622 * // Shuffle packed 8-bit integers
623 * __m128i v_out = _mm_shuffle_epi8(v_in, v_perm); // pshufb
624 *
625 * Data (Number, Binary, Byte Index):
626 +------+------+-------------+------+------+-------------+
627 | 1 | 2 | 3 | 4 | Number
628 +------+------+------+------+------+------+------+------+
629 | 0000 | 0001 | 0000 | 0010 | 0000 | 0011 | 0000 | 0100 | Binary
630 +------+------+------+------+------+------+------+------+
631 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | Index
632 +------+------+------+------+------+------+------+------+
633
634 +------+------+------+------+------+------+------+------+
635 | 5 | 6 | 7 | 8 | Number
636 +------+------+------+------+------+------+------+------+
637 | 0000 | 0101 | 0000 | 0110 | 0000 | 0111 | 0000 | 1000 | Binary
638 +------+------+------+------+------+------+------+------+
639 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Index
640 +------+------+------+------+------+------+------+------+
641 * Index (Byte Index):
642 +------+------+------+------+------+------+------+------+
643 | 1 | 0 | 2 | 3 | 8 | 9 | 10 | 11 |
644 +------+------+------+------+------+------+------+------+
645
646 +------+------+------+------+------+------+------+------+
647 | 4 | 5 | 12 | 13 | 6 | 7 | 14 | 15 |
648 +------+------+------+------+------+------+------+------+
649 * Result:
650 +------+------+------+------+------+------+------+------+
651 | 1 | 0 | 2 | 3 | 8 | 9 | 10 | 11 | Index
652 +------+------+------+------+------+------+------+------+
653 | 0001 | 0000 | 0000 | 0010 | 0000 | 0101 | 0000 | 0110 | Binary
654 +------+------+------+------+------+------+------+------+
655 | 256 | 2 | 5 | 6 | Number
656 +------+------+------+------+------+------+------+------+
657
658 +------+------+------+------+------+------+------+------+
659 | 4 | 5 | 12 | 13 | 6 | 7 | 14 | 15 | Index
660 +------+------+------+------+------+------+------+------+
661 | 0000 | 0011 | 0000 | 0111 | 0000 | 0100 | 0000 | 1000 | Binary
662 +------+------+------+------+------+------+------+------+
663 | 3 | 7 | 4 | 8 | Number
664 +------+------+------+------+------+------+-------------+
665 */
666
667/* Constants for use with _mm_prefetch. */
669 _MM_HINT_NTA = 0, /* load data to L1 and L2 cache, mark it as NTA */
670 _MM_HINT_T0 = 1, /* load data to L1 and L2 cache */
671 _MM_HINT_T1 = 2, /* load data to L2 cache only */
672 _MM_HINT_T2 = 3, /* load data to L2 cache only, mark it as NTA */
673};
674
675// The bit field mapping to the FPCR(floating-point control register)
676typedef struct {
677 uint16_t res0;
678 uint8_t res1 : 6;
679 uint8_t bit22 : 1;
680 uint8_t bit23 : 1;
681 uint8_t bit24 : 1;
682 uint8_t res2 : 7;
683#if defined(__aarch64__)
684 uint32_t res3;
685#endif
687
688// Takes the upper 64 bits of a and places it in the low end of the result
689// Takes the lower 64 bits of b and places it into the high end of the result.
691{
692 float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a));
693 float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b));
694 return vreinterpretq_m128_f32(vcombine_f32(a32, b10));
695}
696
697// takes the lower two 32-bit values from a and swaps them and places in high
698// end of result takes the higher two 32 bit values from b and swaps them and
699// places in low end of result.
701{
702 float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a)));
703 float32x2_t b23 = vrev64_f32(vget_high_f32(vreinterpretq_f32_m128(b)));
704 return vreinterpretq_m128_f32(vcombine_f32(a01, b23));
705}
706
708{
709 float32x2_t a21 = vget_high_f32(
711 float32x2_t b03 = vget_low_f32(
713 return vreinterpretq_m128_f32(vcombine_f32(a21, b03));
714}
715
717{
718 float32x2_t a03 = vget_low_f32(
720 float32x2_t b21 = vget_high_f32(
722 return vreinterpretq_m128_f32(vcombine_f32(a03, b21));
723}
724
726{
727 float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a));
728 float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b));
729 return vreinterpretq_m128_f32(vcombine_f32(a10, b10));
730}
731
733{
734 float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a)));
735 float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b));
736 return vreinterpretq_m128_f32(vcombine_f32(a01, b10));
737}
738
740{
741 float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a)));
742 float32x2_t b01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(b)));
743 return vreinterpretq_m128_f32(vcombine_f32(a01, b01));
744}
745
746// keeps the low 64 bits of b in the low and puts the high 64 bits of a in the
747// high
749{
750 float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a));
751 float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b));
752 return vreinterpretq_m128_f32(vcombine_f32(a10, b32));
753}
754
756{
757 float32x2_t a11 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(a)), 1);
758 float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
759 return vreinterpretq_m128_f32(vcombine_f32(a11, b00));
760}
761
763{
764 float32x2_t a22 =
765 vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 0);
766 float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
767 return vreinterpretq_m128_f32(vcombine_f32(a22, b00));
768}
769
771{
772 float32x2_t a00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(a)), 0);
773 float32x2_t b22 =
774 vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(b)), 0);
775 return vreinterpretq_m128_f32(vcombine_f32(a00, b22));
776}
777
779{
780 float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
781 float32x2_t a22 =
782 vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 0);
783 float32x2_t a02 = vset_lane_f32(a0, a22, 1); /* TODO: use vzip ?*/
784 float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b));
785 return vreinterpretq_m128_f32(vcombine_f32(a02, b32));
786}
787
789{
790 float32x2_t a33 =
791 vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 1);
792 float32x2_t b11 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 1);
793 return vreinterpretq_m128_f32(vcombine_f32(a33, b11));
794}
795
797{
798 float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a));
799 float32_t b2 = vgetq_lane_f32(vreinterpretq_f32_m128(b), 2);
800 float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
801 float32x2_t b20 = vset_lane_f32(b2, b00, 1);
802 return vreinterpretq_m128_f32(vcombine_f32(a10, b20));
803}
804
806{
807 float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a)));
808 float32_t b2 = vgetq_lane_f32(b, 2);
809 float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
810 float32x2_t b20 = vset_lane_f32(b2, b00, 1);
811 return vreinterpretq_m128_f32(vcombine_f32(a01, b20));
812}
813
815{
816 float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a));
817 float32_t b2 = vgetq_lane_f32(b, 2);
818 float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0);
819 float32x2_t b20 = vset_lane_f32(b2, b00, 1);
820 return vreinterpretq_m128_f32(vcombine_f32(a32, b20));
821}
822
823// Kahan summation for accurate summation of floating-point numbers.
824// http://blog.zachbjornson.com/2019/08/11/fast-float-summation.html
825FORCE_INLINE void _sse2neon_kadd_f32(float *sum, float *c, float y)
826{
827 y -= *c;
828 float t = *sum + y;
829 *c = (t - *sum) - y;
830 *sum = t;
831}
832
833#if defined(__ARM_FEATURE_CRYPTO) && \
834 (defined(__aarch64__) || __has_builtin(__builtin_arm_crypto_vmullp64))
835// Wraps vmull_p64
836FORCE_INLINE uint64x2_t _sse2neon_vmull_p64(uint64x1_t _a, uint64x1_t _b)
837{
838 poly64_t a = vget_lane_p64(vreinterpret_p64_u64(_a), 0);
839 poly64_t b = vget_lane_p64(vreinterpret_p64_u64(_b), 0);
840 return vreinterpretq_u64_p128(vmull_p64(a, b));
841}
842#else // ARMv7 polyfill
843// ARMv7/some A64 lacks vmull_p64, but it has vmull_p8.
844//
845// vmull_p8 calculates 8 8-bit->16-bit polynomial multiplies, but we need a
846// 64-bit->128-bit polynomial multiply.
847//
848// It needs some work and is somewhat slow, but it is still faster than all
849// known scalar methods.
850//
851// Algorithm adapted to C from
852// https://www.workofard.com/2017/07/ghash-for-low-end-cores/, which is adapted
853// from "Fast Software Polynomial Multiplication on ARM Processors Using the
854// NEON Engine" by Danilo Camara, Conrado Gouvea, Julio Lopez and Ricardo Dahab
855// (https://hal.inria.fr/hal-01506572)
856static uint64x2_t _sse2neon_vmull_p64(uint64x1_t _a, uint64x1_t _b)
857{
858 poly8x8_t a = vreinterpret_p8_u64(_a);
859 poly8x8_t b = vreinterpret_p8_u64(_b);
860
861 // Masks
862 uint8x16_t k48_32 = vcombine_u8(vcreate_u8(0x0000ffffffffffff),
863 vcreate_u8(0x00000000ffffffff));
864 uint8x16_t k16_00 = vcombine_u8(vcreate_u8(0x000000000000ffff),
865 vcreate_u8(0x0000000000000000));
866
867 // Do the multiplies, rotating with vext to get all combinations
868 uint8x16_t d = vreinterpretq_u8_p16(vmull_p8(a, b)); // D = A0 * B0
869 uint8x16_t e =
870 vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 1))); // E = A0 * B1
871 uint8x16_t f =
872 vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 1), b)); // F = A1 * B0
873 uint8x16_t g =
874 vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 2))); // G = A0 * B2
875 uint8x16_t h =
876 vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 2), b)); // H = A2 * B0
877 uint8x16_t i =
878 vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 3))); // I = A0 * B3
879 uint8x16_t j =
880 vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 3), b)); // J = A3 * B0
881 uint8x16_t k =
882 vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 4))); // L = A0 * B4
883
884 // Add cross products
885 uint8x16_t l = veorq_u8(e, f); // L = E + F
886 uint8x16_t m = veorq_u8(g, h); // M = G + H
887 uint8x16_t n = veorq_u8(i, j); // N = I + J
888
889 // Interleave. Using vzip1 and vzip2 prevents Clang from emitting TBL
890 // instructions.
891#if defined(__aarch64__)
892 uint8x16_t lm_p0 = vreinterpretq_u8_u64(
893 vzip1q_u64(vreinterpretq_u64_u8(l), vreinterpretq_u64_u8(m)));
894 uint8x16_t lm_p1 = vreinterpretq_u8_u64(
895 vzip2q_u64(vreinterpretq_u64_u8(l), vreinterpretq_u64_u8(m)));
896 uint8x16_t nk_p0 = vreinterpretq_u8_u64(
897 vzip1q_u64(vreinterpretq_u64_u8(n), vreinterpretq_u64_u8(k)));
898 uint8x16_t nk_p1 = vreinterpretq_u8_u64(
899 vzip2q_u64(vreinterpretq_u64_u8(n), vreinterpretq_u64_u8(k)));
900#else
901 uint8x16_t lm_p0 = vcombine_u8(vget_low_u8(l), vget_low_u8(m));
902 uint8x16_t lm_p1 = vcombine_u8(vget_high_u8(l), vget_high_u8(m));
903 uint8x16_t nk_p0 = vcombine_u8(vget_low_u8(n), vget_low_u8(k));
904 uint8x16_t nk_p1 = vcombine_u8(vget_high_u8(n), vget_high_u8(k));
905#endif
906 // t0 = (L) (P0 + P1) << 8
907 // t1 = (M) (P2 + P3) << 16
908 uint8x16_t t0t1_tmp = veorq_u8(lm_p0, lm_p1);
909 uint8x16_t t0t1_h = vandq_u8(lm_p1, k48_32);
910 uint8x16_t t0t1_l = veorq_u8(t0t1_tmp, t0t1_h);
911
912 // t2 = (N) (P4 + P5) << 24
913 // t3 = (K) (P6 + P7) << 32
914 uint8x16_t t2t3_tmp = veorq_u8(nk_p0, nk_p1);
915 uint8x16_t t2t3_h = vandq_u8(nk_p1, k16_00);
916 uint8x16_t t2t3_l = veorq_u8(t2t3_tmp, t2t3_h);
917
918 // De-interleave
919#if defined(__aarch64__)
920 uint8x16_t t0 = vreinterpretq_u8_u64(
921 vuzp1q_u64(vreinterpretq_u64_u8(t0t1_l), vreinterpretq_u64_u8(t0t1_h)));
922 uint8x16_t t1 = vreinterpretq_u8_u64(
923 vuzp2q_u64(vreinterpretq_u64_u8(t0t1_l), vreinterpretq_u64_u8(t0t1_h)));
924 uint8x16_t t2 = vreinterpretq_u8_u64(
925 vuzp1q_u64(vreinterpretq_u64_u8(t2t3_l), vreinterpretq_u64_u8(t2t3_h)));
926 uint8x16_t t3 = vreinterpretq_u8_u64(
927 vuzp2q_u64(vreinterpretq_u64_u8(t2t3_l), vreinterpretq_u64_u8(t2t3_h)));
928#else
929 uint8x16_t t1 = vcombine_u8(vget_high_u8(t0t1_l), vget_high_u8(t0t1_h));
930 uint8x16_t t0 = vcombine_u8(vget_low_u8(t0t1_l), vget_low_u8(t0t1_h));
931 uint8x16_t t3 = vcombine_u8(vget_high_u8(t2t3_l), vget_high_u8(t2t3_h));
932 uint8x16_t t2 = vcombine_u8(vget_low_u8(t2t3_l), vget_low_u8(t2t3_h));
933#endif
934 // Shift the cross products
935 uint8x16_t t0_shift = vextq_u8(t0, t0, 15); // t0 << 8
936 uint8x16_t t1_shift = vextq_u8(t1, t1, 14); // t1 << 16
937 uint8x16_t t2_shift = vextq_u8(t2, t2, 13); // t2 << 24
938 uint8x16_t t3_shift = vextq_u8(t3, t3, 12); // t3 << 32
939
940 // Accumulate the products
941 uint8x16_t cross1 = veorq_u8(t0_shift, t1_shift);
942 uint8x16_t cross2 = veorq_u8(t2_shift, t3_shift);
943 uint8x16_t mix = veorq_u8(d, cross1);
944 uint8x16_t r = veorq_u8(mix, cross2);
945 return vreinterpretq_u64_u8(r);
946}
947#endif // ARMv7 polyfill
948
949// C equivalent:
950// __m128i _mm_shuffle_epi32_default(__m128i a,
951// __constrange(0, 255) int imm) {
952// __m128i ret;
953// ret[0] = a[imm & 0x3]; ret[1] = a[(imm >> 2) & 0x3];
954// ret[2] = a[(imm >> 4) & 0x03]; ret[3] = a[(imm >> 6) & 0x03];
955// return ret;
956// }
957#define _mm_shuffle_epi32_default(a, imm) \
958 __extension__({ \
959 int32x4_t ret; \
960 ret = vmovq_n_s32( \
961 vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm) & (0x3))); \
962 ret = vsetq_lane_s32( \
963 vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 2) & 0x3), \
964 ret, 1); \
965 ret = vsetq_lane_s32( \
966 vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 4) & 0x3), \
967 ret, 2); \
968 ret = vsetq_lane_s32( \
969 vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 6) & 0x3), \
970 ret, 3); \
971 vreinterpretq_m128i_s32(ret); \
972 })
973
974// Takes the upper 64 bits of a and places it in the low end of the result
975// Takes the lower 64 bits of a and places it into the high end of the result.
977{
978 int32x2_t a32 = vget_high_s32(vreinterpretq_s32_m128i(a));
979 int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a));
980 return vreinterpretq_m128i_s32(vcombine_s32(a32, a10));
981}
982
983// takes the lower two 32-bit values from a and swaps them and places in low end
984// of result takes the higher two 32 bit values from a and swaps them and places
985// in high end of result.
987{
988 int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a)));
989 int32x2_t a23 = vrev64_s32(vget_high_s32(vreinterpretq_s32_m128i(a)));
990 return vreinterpretq_m128i_s32(vcombine_s32(a01, a23));
991}
992
993// rotates the least significant 32 bits into the most significant 32 bits, and
994// shifts the rest down
1000
1001// rotates the most significant 32 bits into the least significant 32 bits, and
1002// shifts the rest up
1008
1009// gets the lower 64 bits of a, and places it in the upper 64 bits
1010// gets the lower 64 bits of a and places it in the lower 64 bits
1012{
1013 int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a));
1014 return vreinterpretq_m128i_s32(vcombine_s32(a10, a10));
1015}
1016
1017// gets the lower 64 bits of a, swaps the 0 and 1 elements, and places it in the
1018// lower 64 bits gets the lower 64 bits of a, and places it in the upper 64 bits
1020{
1021 int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a)));
1022 int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a));
1023 return vreinterpretq_m128i_s32(vcombine_s32(a01, a10));
1024}
1025
1026// gets the lower 64 bits of a, swaps the 0 and 1 elements and places it in the
1027// upper 64 bits gets the lower 64 bits of a, swaps the 0 and 1 elements, and
1028// places it in the lower 64 bits
1030{
1031 int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a)));
1032 return vreinterpretq_m128i_s32(vcombine_s32(a01, a01));
1033}
1034
1036{
1037 int32x2_t a11 = vdup_lane_s32(vget_low_s32(vreinterpretq_s32_m128i(a)), 1);
1038 int32x2_t a22 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 0);
1039 return vreinterpretq_m128i_s32(vcombine_s32(a11, a22));
1040}
1041
1043{
1044 int32x2_t a22 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 0);
1045 int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a)));
1046 return vreinterpretq_m128i_s32(vcombine_s32(a22, a01));
1047}
1048
1050{
1051 int32x2_t a32 = vget_high_s32(vreinterpretq_s32_m128i(a));
1052 int32x2_t a33 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 1);
1053 return vreinterpretq_m128i_s32(vcombine_s32(a32, a33));
1054}
1055
1056// FORCE_INLINE __m128i _mm_shuffle_epi32_splat(__m128i a, __constrange(0,255)
1057// int imm)
1058#if defined(__aarch64__)
1059#define _mm_shuffle_epi32_splat(a, imm) \
1060 __extension__({ \
1061 vreinterpretq_m128i_s32( \
1062 vdupq_laneq_s32(vreinterpretq_s32_m128i(a), (imm))); \
1063 })
1064#else
1065#define _mm_shuffle_epi32_splat(a, imm) \
1066 __extension__({ \
1067 vreinterpretq_m128i_s32( \
1068 vdupq_n_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm)))); \
1069 })
1070#endif
1071
1072// NEON does not support a general purpose permute intrinsic
1073// Selects four specific single-precision, floating-point values from a and b,
1074// based on the mask i.
1075//
1076// C equivalent:
1077// __m128 _mm_shuffle_ps_default(__m128 a, __m128 b,
1078// __constrange(0, 255) int imm) {
1079// __m128 ret;
1080// ret[0] = a[imm & 0x3]; ret[1] = a[(imm >> 2) & 0x3];
1081// ret[2] = b[(imm >> 4) & 0x03]; ret[3] = b[(imm >> 6) & 0x03];
1082// return ret;
1083// }
1084//
1085// https://msdn.microsoft.com/en-us/library/vstudio/5f0858x0(v=vs.100).aspx
1086#define _mm_shuffle_ps_default(a, b, imm) \
1087 __extension__({ \
1088 float32x4_t ret; \
1089 ret = vmovq_n_f32( \
1090 vgetq_lane_f32(vreinterpretq_f32_m128(a), (imm) & (0x3))); \
1091 ret = vsetq_lane_f32( \
1092 vgetq_lane_f32(vreinterpretq_f32_m128(a), ((imm) >> 2) & 0x3), \
1093 ret, 1); \
1094 ret = vsetq_lane_f32( \
1095 vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 4) & 0x3), \
1096 ret, 2); \
1097 ret = vsetq_lane_f32( \
1098 vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 6) & 0x3), \
1099 ret, 3); \
1100 vreinterpretq_m128_f32(ret); \
1101 })
1102
1103// Shuffles the lower 4 signed or unsigned 16-bit integers in a as specified
1104// by imm.
1105// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/y41dkk37(v=vs.100)
1106// FORCE_INLINE __m128i _mm_shufflelo_epi16_function(__m128i a,
1107// __constrange(0,255) int
1108// imm)
1109#define _mm_shufflelo_epi16_function(a, imm) \
1110 __extension__({ \
1111 int16x8_t ret = vreinterpretq_s16_m128i(a); \
1112 int16x4_t lowBits = vget_low_s16(ret); \
1113 ret = vsetq_lane_s16(vget_lane_s16(lowBits, (imm) & (0x3)), ret, 0); \
1114 ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 2) & 0x3), ret, \
1115 1); \
1116 ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 4) & 0x3), ret, \
1117 2); \
1118 ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 6) & 0x3), ret, \
1119 3); \
1120 vreinterpretq_m128i_s16(ret); \
1121 })
1122
1123// Shuffles the upper 4 signed or unsigned 16-bit integers in a as specified
1124// by imm.
1125// https://msdn.microsoft.com/en-us/library/13ywktbs(v=vs.100).aspx
1126// FORCE_INLINE __m128i _mm_shufflehi_epi16_function(__m128i a,
1127// __constrange(0,255) int
1128// imm)
1129#define _mm_shufflehi_epi16_function(a, imm) \
1130 __extension__({ \
1131 int16x8_t ret = vreinterpretq_s16_m128i(a); \
1132 int16x4_t highBits = vget_high_s16(ret); \
1133 ret = vsetq_lane_s16(vget_lane_s16(highBits, (imm) & (0x3)), ret, 4); \
1134 ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 2) & 0x3), ret, \
1135 5); \
1136 ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 4) & 0x3), ret, \
1137 6); \
1138 ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 6) & 0x3), ret, \
1139 7); \
1140 vreinterpretq_m128i_s16(ret); \
1141 })
1142
1143/* MMX */
1144
1145//_mm_empty is a no-op on arm
1147
1148/* SSE */
1149
1150// Adds the four single-precision, floating-point values of a and b.
1151//
1152// r0 := a0 + b0
1153// r1 := a1 + b1
1154// r2 := a2 + b2
1155// r3 := a3 + b3
1156//
1157// https://msdn.microsoft.com/en-us/library/vstudio/c9848chc(v=vs.100).aspx
1163
1164// adds the scalar single-precision floating point values of a and b.
1165// https://msdn.microsoft.com/en-us/library/be94x2y6(v=vs.100).aspx
1167{
1168 float32_t b0 = vgetq_lane_f32(vreinterpretq_f32_m128(b), 0);
1169 float32x4_t value = vsetq_lane_f32(b0, vdupq_n_f32(0), 0);
1170 // the upper values in the result must be the remnants of <a>.
1171 return vreinterpretq_m128_f32(vaddq_f32(a, value));
1172}
1173
1174// Computes the bitwise AND of the four single-precision, floating-point values
1175// of a and b.
1176//
1177// r0 := a0 & b0
1178// r1 := a1 & b1
1179// r2 := a2 & b2
1180// r3 := a3 & b3
1181//
1182// https://msdn.microsoft.com/en-us/library/vstudio/73ck1xc5(v=vs.100).aspx
1188
1189// Computes the bitwise AND-NOT of the four single-precision, floating-point
1190// values of a and b.
1191//
1192// r0 := ~a0 & b0
1193// r1 := ~a1 & b1
1194// r2 := ~a2 & b2
1195// r3 := ~a3 & b3
1196//
1197// https://msdn.microsoft.com/en-us/library/vstudio/68h7wd02(v=vs.100).aspx
1199{
1201 vbicq_s32(vreinterpretq_s32_m128(b),
1202 vreinterpretq_s32_m128(a))); // *NOTE* argument swap
1203}
1204
1205// Average packed unsigned 16-bit integers in a and b, and store the results in
1206// dst.
1207//
1208// FOR j := 0 to 3
1209// i := j*16
1210// dst[i+15:i] := (a[i+15:i] + b[i+15:i] + 1) >> 1
1211// ENDFOR
1212//
1213// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_avg_pu16
1219
1220// Average packed unsigned 8-bit integers in a and b, and store the results in
1221// dst.
1222//
1223// FOR j := 0 to 7
1224// i := j*8
1225// dst[i+7:i] := (a[i+7:i] + b[i+7:i] + 1) >> 1
1226// ENDFOR
1227//
1228// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_avg_pu8
1234
1235// Compares for equality.
1236// https://msdn.microsoft.com/en-us/library/vstudio/36aectz5(v=vs.100).aspx
1242
1243// Compares for equality.
1244// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/k423z28e(v=vs.100)
1246{
1247 return _mm_move_ss(a, _mm_cmpeq_ps(a, b));
1248}
1249
1250// Compares for greater than or equal.
1251// https://msdn.microsoft.com/en-us/library/vstudio/fs813y2t(v=vs.100).aspx
1257
1258// Compares for greater than or equal.
1259// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/kesh3ddc(v=vs.100)
1261{
1262 return _mm_move_ss(a, _mm_cmpge_ps(a, b));
1263}
1264
1265// Compares for greater than.
1266//
1267// r0 := (a0 > b0) ? 0xffffffff : 0x0
1268// r1 := (a1 > b1) ? 0xffffffff : 0x0
1269// r2 := (a2 > b2) ? 0xffffffff : 0x0
1270// r3 := (a3 > b3) ? 0xffffffff : 0x0
1271//
1272// https://msdn.microsoft.com/en-us/library/vstudio/11dy102s(v=vs.100).aspx
1278
1279// Compares for greater than.
1280// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/1xyyyy9e(v=vs.100)
1282{
1283 return _mm_move_ss(a, _mm_cmpgt_ps(a, b));
1284}
1285
1286// Compares for less than or equal.
1287//
1288// r0 := (a0 <= b0) ? 0xffffffff : 0x0
1289// r1 := (a1 <= b1) ? 0xffffffff : 0x0
1290// r2 := (a2 <= b2) ? 0xffffffff : 0x0
1291// r3 := (a3 <= b3) ? 0xffffffff : 0x0
1292//
1293// https://msdn.microsoft.com/en-us/library/vstudio/1s75w83z(v=vs.100).aspx
1299
1300// Compares for less than or equal.
1301// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/a7x0hbhw(v=vs.100)
1303{
1304 return _mm_move_ss(a, _mm_cmple_ps(a, b));
1305}
1306
1307// Compares for less than
1308// https://msdn.microsoft.com/en-us/library/vstudio/f330yhc8(v=vs.100).aspx
1314
1315// Compares for less than
1316// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/fy94wye7(v=vs.100)
1318{
1319 return _mm_move_ss(a, _mm_cmplt_ps(a, b));
1320}
1321
1322// Compares for inequality.
1323// https://msdn.microsoft.com/en-us/library/sf44thbx(v=vs.100).aspx
1329
1330// Compares for inequality.
1331// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/ekya8fh4(v=vs.100)
1333{
1334 return _mm_move_ss(a, _mm_cmpneq_ps(a, b));
1335}
1336
1337// Compares for not greater than or equal.
1338// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/wsexys62(v=vs.100)
1344
1345// Compares for not greater than or equal.
1346// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/fk2y80s8(v=vs.100)
1348{
1349 return _mm_move_ss(a, _mm_cmpnge_ps(a, b));
1350}
1351
1352// Compares for not greater than.
1353// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/d0xh7w0s(v=vs.100)
1359
1360// Compares for not greater than.
1361// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/z7x9ydwh(v=vs.100)
1363{
1364 return _mm_move_ss(a, _mm_cmpngt_ps(a, b));
1365}
1366
1367// Compares for not less than or equal.
1368// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/6a330kxw(v=vs.100)
1374
1375// Compares for not less than or equal.
1376// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/z7x9ydwh(v=vs.100)
1378{
1379 return _mm_move_ss(a, _mm_cmpnle_ps(a, b));
1380}
1381
1382// Compares for not less than.
1383// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/4686bbdw(v=vs.100)
1389
1390// Compares for not less than.
1391// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/56b9z2wf(v=vs.100)
1393{
1394 return _mm_move_ss(a, _mm_cmpnlt_ps(a, b));
1395}
1396
1397// Compares the four 32-bit floats in a and b to check if any values are NaN.
1398// Ordered compare between each value returns true for "orderable" and false for
1399// "not orderable" (NaN).
1400// https://msdn.microsoft.com/en-us/library/vstudio/0h9w00fx(v=vs.100).aspx see
1401// also:
1402// http://stackoverflow.com/questions/8627331/what-does-ordered-unordered-comparison-mean
1403// http://stackoverflow.com/questions/29349621/neon-isnanval-intrinsics
1405{
1406 // Note: NEON does not have ordered compare builtin
1407 // Need to compare a eq a and b eq b to check for NaN
1408 // Do AND of results to get final
1409 uint32x4_t ceqaa =
1411 uint32x4_t ceqbb =
1413 return vreinterpretq_m128_u32(vandq_u32(ceqaa, ceqbb));
1414}
1415
1416// Compares for ordered.
1417// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/343t62da(v=vs.100)
1419{
1420 return _mm_move_ss(a, _mm_cmpord_ps(a, b));
1421}
1422
1423// Compares for unordered.
1424// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/khy6fk1t(v=vs.100)
1426{
1427 uint32x4_t f32a =
1429 uint32x4_t f32b =
1431 return vreinterpretq_m128_u32(vmvnq_u32(vandq_u32(f32a, f32b)));
1432}
1433
1434// Compares for unordered.
1435// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/2as2387b(v=vs.100)
1440
1441// Compares the lower single-precision floating point scalar values of a and b
1442// using an equality operation. :
1443// https://msdn.microsoft.com/en-us/library/93yx2h2b(v=vs.100).aspx
1445{
1446 uint32x4_t a_eq_b =
1448 return vgetq_lane_u32(a_eq_b, 0) & 0x1;
1449}
1450
1451// Compares the lower single-precision floating point scalar values of a and b
1452// using a greater than or equal operation. :
1453// https://msdn.microsoft.com/en-us/library/8t80des6(v=vs.100).aspx
1455{
1456 uint32x4_t a_ge_b =
1458 return vgetq_lane_u32(a_ge_b, 0) & 0x1;
1459}
1460
1461// Compares the lower single-precision floating point scalar values of a and b
1462// using a greater than operation. :
1463// https://msdn.microsoft.com/en-us/library/b0738e0t(v=vs.100).aspx
1465{
1466 uint32x4_t a_gt_b =
1468 return vgetq_lane_u32(a_gt_b, 0) & 0x1;
1469}
1470
1471// Compares the lower single-precision floating point scalar values of a and b
1472// using a less than or equal operation. :
1473// https://msdn.microsoft.com/en-us/library/1w4t7c57(v=vs.90).aspx
1475{
1476 uint32x4_t a_le_b =
1478 return vgetq_lane_u32(a_le_b, 0) & 0x1;
1479}
1480
1481// Compares the lower single-precision floating point scalar values of a and b
1482// using a less than operation. :
1483// https://msdn.microsoft.com/en-us/library/2kwe606b(v=vs.90).aspx Important
1484// note!! The documentation on MSDN is incorrect! If either of the values is a
1485// NAN the docs say you will get a one, but in fact, it will return a zero!!
1487{
1488 uint32x4_t a_lt_b =
1490 return vgetq_lane_u32(a_lt_b, 0) & 0x1;
1491}
1492
1493// Compares the lower single-precision floating point scalar values of a and b
1494// using an inequality operation. :
1495// https://msdn.microsoft.com/en-us/library/bafh5e0a(v=vs.90).aspx
1497{
1498 return !_mm_comieq_ss(a, b);
1499}
1500
1501// Convert packed signed 32-bit integers in b to packed single-precision
1502// (32-bit) floating-point elements, store the results in the lower 2 elements
1503// of dst, and copy the upper 2 packed elements from a to the upper elements of
1504// dst.
1505//
1506// dst[31:0] := Convert_Int32_To_FP32(b[31:0])
1507// dst[63:32] := Convert_Int32_To_FP32(b[63:32])
1508// dst[95:64] := a[95:64]
1509// dst[127:96] := a[127:96]
1510//
1511// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvt_pi2ps
1513{
1515 vcombine_f32(vcvt_f32_s32(vreinterpret_s32_m64(b)),
1516 vget_high_f32(vreinterpretq_f32_m128(a))));
1517}
1518
1519// Convert packed single-precision (32-bit) floating-point elements in a to
1520// packed 32-bit integers, and store the results in dst.
1521//
1522// FOR j := 0 to 1
1523// i := 32*j
1524// dst[i+31:i] := Convert_FP32_To_Int32(a[i+31:i])
1525// ENDFOR
1526//
1527// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvt_ps2pi
1529{
1530#if defined(__aarch64__) || defined(__ARM_FEATURE_DIRECTED_ROUNDING)
1531 return vreinterpret_m64_s32(
1532 vget_low_s32(vcvtnq_s32_f32(vrndiq_f32(vreinterpretq_f32_m128(a)))));
1533#else
1534 return vreinterpret_m64_s32(vcvt_s32_f32(vget_low_f32(
1536#endif
1537}
1538
1539// Convert the signed 32-bit integer b to a single-precision (32-bit)
1540// floating-point element, store the result in the lower element of dst, and
1541// copy the upper 3 packed elements from a to the upper elements of dst.
1542//
1543// dst[31:0] := Convert_Int32_To_FP32(b[31:0])
1544// dst[127:32] := a[127:32]
1545//
1546// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvt_si2ss
1548{
1550 vsetq_lane_f32((float) b, vreinterpretq_f32_m128(a), 0));
1551}
1552
1553// Convert the lower single-precision (32-bit) floating-point element in a to a
1554// 32-bit integer, and store the result in dst.
1555// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvt_ss2si
1557{
1558#if defined(__aarch64__) || defined(__ARM_FEATURE_DIRECTED_ROUNDING)
1559 return vgetq_lane_s32(vcvtnq_s32_f32(vrndiq_f32(vreinterpretq_f32_m128(a))),
1560 0);
1561#else
1562 float32_t data = vgetq_lane_f32(
1564 return (int32_t) data;
1565#endif
1566}
1567
1568// Convert packed 16-bit integers in a to packed single-precision (32-bit)
1569// floating-point elements, and store the results in dst.
1570//
1571// FOR j := 0 to 3
1572// i := j*16
1573// m := j*32
1574// dst[m+31:m] := Convert_Int16_To_FP32(a[i+15:i])
1575// ENDFOR
1576//
1577// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtpi16_ps
1579{
1581 vcvtq_f32_s32(vmovl_s16(vreinterpret_s16_m64(a))));
1582}
1583
1584// Convert packed 32-bit integers in b to packed single-precision (32-bit)
1585// floating-point elements, store the results in the lower 2 elements of dst,
1586// and copy the upper 2 packed elements from a to the upper elements of dst.
1587//
1588// dst[31:0] := Convert_Int32_To_FP32(b[31:0])
1589// dst[63:32] := Convert_Int32_To_FP32(b[63:32])
1590// dst[95:64] := a[95:64]
1591// dst[127:96] := a[127:96]
1592//
1593// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtpi32_ps
1595{
1597 vcombine_f32(vcvt_f32_s32(vreinterpret_s32_m64(b)),
1598 vget_high_f32(vreinterpretq_f32_m128(a))));
1599}
1600
1601// Convert packed signed 32-bit integers in a to packed single-precision
1602// (32-bit) floating-point elements, store the results in the lower 2 elements
1603// of dst, then convert the packed signed 32-bit integers in b to
1604// single-precision (32-bit) floating-point element, and store the results in
1605// the upper 2 elements of dst.
1606//
1607// dst[31:0] := Convert_Int32_To_FP32(a[31:0])
1608// dst[63:32] := Convert_Int32_To_FP32(a[63:32])
1609// dst[95:64] := Convert_Int32_To_FP32(b[31:0])
1610// dst[127:96] := Convert_Int32_To_FP32(b[63:32])
1611//
1612// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtpi32x2_ps
1614{
1615 return vreinterpretq_m128_f32(vcvtq_f32_s32(
1616 vcombine_s32(vreinterpret_s32_m64(a), vreinterpret_s32_m64(b))));
1617}
1618
1619// Convert the lower packed 8-bit integers in a to packed single-precision
1620// (32-bit) floating-point elements, and store the results in dst.
1621//
1622// FOR j := 0 to 3
1623// i := j*8
1624// m := j*32
1625// dst[m+31:m] := Convert_Int8_To_FP32(a[i+7:i])
1626// ENDFOR
1627//
1628// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtpi8_ps
1630{
1631 return vreinterpretq_m128_f32(vcvtq_f32_s32(
1632 vmovl_s16(vget_low_s16(vmovl_s8(vreinterpret_s8_m64(a))))));
1633}
1634
1635// Convert packed single-precision (32-bit) floating-point elements in a to
1636// packed 16-bit integers, and store the results in dst. Note: this intrinsic
1637// will generate 0x7FFF, rather than 0x8000, for input values between 0x7FFF and
1638// 0x7FFFFFFF.
1639//
1640// FOR j := 0 to 3
1641// i := 16*j
1642// k := 32*j
1643// IF a[k+31:k] >= FP32(0x7FFF) && a[k+31:k] <= FP32(0x7FFFFFFF)
1644// dst[i+15:i] := 0x7FFF
1645// ELSE
1646// dst[i+15:i] := Convert_FP32_To_Int16(a[k+31:k])
1647// FI
1648// ENDFOR
1649//
1650// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtps_pi16
1656
1657// Convert packed single-precision (32-bit) floating-point elements in a to
1658// packed 32-bit integers, and store the results in dst.
1659//
1660// FOR j := 0 to 1
1661// i := 32*j
1662// dst[i+31:i] := Convert_FP32_To_Int32(a[i+31:i])
1663// ENDFOR
1664//
1665// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtps_pi32
1666#define _mm_cvtps_pi32(a) _mm_cvt_ps2pi(a)
1667
1668// Convert packed single-precision (32-bit) floating-point elements in a to
1669// packed 8-bit integers, and store the results in lower 4 elements of dst.
1670// Note: this intrinsic will generate 0x7F, rather than 0x80, for input values
1671// between 0x7F and 0x7FFFFFFF.
1672//
1673// FOR j := 0 to 3
1674// i := 8*j
1675// k := 32*j
1676// IF a[k+31:k] >= FP32(0x7F) && a[k+31:k] <= FP32(0x7FFFFFFF)
1677// dst[i+7:i] := 0x7F
1678// ELSE
1679// dst[i+7:i] := Convert_FP32_To_Int8(a[k+31:k])
1680// FI
1681// ENDFOR
1682//
1683// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtps_pi8
1685{
1686 return vreinterpret_m64_s8(vqmovn_s16(
1687 vcombine_s16(vreinterpret_s16_m64(_mm_cvtps_pi16(a)), vdup_n_s16(0))));
1688}
1689
1690// Convert packed unsigned 16-bit integers in a to packed single-precision
1691// (32-bit) floating-point elements, and store the results in dst.
1692//
1693// FOR j := 0 to 3
1694// i := j*16
1695// m := j*32
1696// dst[m+31:m] := Convert_UInt16_To_FP32(a[i+15:i])
1697// ENDFOR
1698//
1699// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtpu16_ps
1701{
1703 vcvtq_f32_u32(vmovl_u16(vreinterpret_u16_m64(a))));
1704}
1705
1706// Convert the lower packed unsigned 8-bit integers in a to packed
1707// single-precision (32-bit) floating-point elements, and store the results in
1708// dst.
1709//
1710// FOR j := 0 to 3
1711// i := j*8
1712// m := j*32
1713// dst[m+31:m] := Convert_UInt8_To_FP32(a[i+7:i])
1714// ENDFOR
1715//
1716// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtpu8_ps
1718{
1719 return vreinterpretq_m128_f32(vcvtq_f32_u32(
1720 vmovl_u16(vget_low_u16(vmovl_u8(vreinterpret_u8_m64(a))))));
1721}
1722
1723// Convert the signed 32-bit integer b to a single-precision (32-bit)
1724// floating-point element, store the result in the lower element of dst, and
1725// copy the upper 3 packed elements from a to the upper elements of dst.
1726//
1727// dst[31:0] := Convert_Int32_To_FP32(b[31:0])
1728// dst[127:32] := a[127:32]
1729//
1730// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi32_ss
1731#define _mm_cvtsi32_ss(a, b) _mm_cvt_si2ss(a, b)
1732
1733// Convert the signed 64-bit integer b to a single-precision (32-bit)
1734// floating-point element, store the result in the lower element of dst, and
1735// copy the upper 3 packed elements from a to the upper elements of dst.
1736//
1737// dst[31:0] := Convert_Int64_To_FP32(b[63:0])
1738// dst[127:32] := a[127:32]
1739//
1740// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi64_ss
1742{
1744 vsetq_lane_f32((float) b, vreinterpretq_f32_m128(a), 0));
1745}
1746
1747// Copy the lower single-precision (32-bit) floating-point element of a to dst.
1748//
1749// dst[31:0] := a[31:0]
1750//
1751// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtss_f32
1753{
1754 return vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
1755}
1756
1757// Convert the lower single-precision (32-bit) floating-point element in a to a
1758// 32-bit integer, and store the result in dst.
1759//
1760// dst[31:0] := Convert_FP32_To_Int32(a[31:0])
1761//
1762// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtss_si32
1763#define _mm_cvtss_si32(a) _mm_cvt_ss2si(a)
1764
1765// Convert the lower single-precision (32-bit) floating-point element in a to a
1766// 64-bit integer, and store the result in dst.
1767//
1768// dst[63:0] := Convert_FP32_To_Int64(a[31:0])
1769//
1770// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtss_si64
1772{
1773#if defined(__aarch64__) || defined(__ARM_FEATURE_DIRECTED_ROUNDING)
1774 return (int64_t) vgetq_lane_f32(vrndiq_f32(vreinterpretq_f32_m128(a)), 0);
1775#else
1776 float32_t data = vgetq_lane_f32(
1778 return (int64_t) data;
1779#endif
1780}
1781
1782// Convert packed single-precision (32-bit) floating-point elements in a to
1783// packed 32-bit integers with truncation, and store the results in dst.
1784//
1785// FOR j := 0 to 1
1786// i := 32*j
1787// dst[i+31:i] := Convert_FP32_To_Int32_Truncate(a[i+31:i])
1788// ENDFOR
1789//
1790// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtt_ps2pi
1792{
1793 return vreinterpret_m64_s32(
1794 vget_low_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a))));
1795}
1796
1797// Convert the lower single-precision (32-bit) floating-point element in a to a
1798// 32-bit integer with truncation, and store the result in dst.
1799//
1800// dst[31:0] := Convert_FP32_To_Int32_Truncate(a[31:0])
1801//
1802// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtt_ss2si
1804{
1805 return vgetq_lane_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a)), 0);
1806}
1807
1808// Convert packed single-precision (32-bit) floating-point elements in a to
1809// packed 32-bit integers with truncation, and store the results in dst.
1810//
1811// FOR j := 0 to 1
1812// i := 32*j
1813// dst[i+31:i] := Convert_FP32_To_Int32_Truncate(a[i+31:i])
1814// ENDFOR
1815//
1816// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvttps_pi32
1817#define _mm_cvttps_pi32(a) _mm_cvtt_ps2pi(a)
1818
1819// Convert the lower single-precision (32-bit) floating-point element in a to a
1820// 32-bit integer with truncation, and store the result in dst.
1821//
1822// dst[31:0] := Convert_FP32_To_Int32_Truncate(a[31:0])
1823//
1824// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvttss_si32
1825#define _mm_cvttss_si32(a) _mm_cvtt_ss2si(a)
1826
1827// Convert the lower single-precision (32-bit) floating-point element in a to a
1828// 64-bit integer with truncation, and store the result in dst.
1829//
1830// dst[63:0] := Convert_FP32_To_Int64_Truncate(a[31:0])
1831//
1832// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvttss_si64
1834{
1835 return (int64_t) vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
1836}
1837
1838// Divides the four single-precision, floating-point values of a and b.
1839//
1840// r0 := a0 / b0
1841// r1 := a1 / b1
1842// r2 := a2 / b2
1843// r3 := a3 / b3
1844//
1845// https://msdn.microsoft.com/en-us/library/edaw8147(v=vs.100).aspx
1847{
1848#if defined(__aarch64__) && !SSE2NEON_PRECISE_DIV
1851#else
1852 float32x4_t recip = vrecpeq_f32(vreinterpretq_f32_m128(b));
1853 recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(b)));
1854#if SSE2NEON_PRECISE_DIV
1855 // Additional Netwon-Raphson iteration for accuracy
1856 recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(b)));
1857#endif
1858 return vreinterpretq_m128_f32(vmulq_f32(vreinterpretq_f32_m128(a), recip));
1859#endif
1860}
1861
1862// Divides the scalar single-precision floating point value of a by b.
1863// https://msdn.microsoft.com/en-us/library/4y73xa49(v=vs.100).aspx
1865{
1866 float32_t value =
1867 vgetq_lane_f32(vreinterpretq_f32_m128(_mm_div_ps(a, b)), 0);
1869 vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0));
1870}
1871
1872// Extract a 16-bit integer from a, selected with imm8, and store the result in
1873// the lower element of dst.
1874// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_extract_pi16
1875#define _mm_extract_pi16(a, imm) \
1876 (int32_t) vget_lane_u16(vreinterpret_u16_m64(a), (imm))
1877
1878// Free aligned memory that was allocated with _mm_malloc.
1879// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_free
1880#if !defined(SSE2NEON_ALLOC_DEFINED)
1881FORCE_INLINE void _mm_free(void *addr)
1882{
1883 free(addr);
1884}
1885#endif
1886
1887// Macro: Get the flush zero bits from the MXCSR control and status register.
1888// The flush zero may contain any of the following flags: _MM_FLUSH_ZERO_ON or
1889// _MM_FLUSH_ZERO_OFF
1890// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_MM_GET_FLUSH_ZERO_MODE
1892{
1893 union {
1894 fpcr_bitfield field;
1895#if defined(__aarch64__)
1896 uint64_t value;
1897#else
1898 uint32_t value;
1899#endif
1900 } r;
1901
1902#if defined(__aarch64__)
1903 __asm__ __volatile__("mrs %0, FPCR" : "=r"(r.value)); /* read */
1904#else
1905 __asm__ __volatile__("vmrs %0, FPSCR" : "=r"(r.value)); /* read */
1906#endif
1907
1908 return r.field.bit24 ? _MM_FLUSH_ZERO_ON : _MM_FLUSH_ZERO_OFF;
1909}
1910
1911// Macro: Get the rounding mode bits from the MXCSR control and status register.
1912// The rounding mode may contain any of the following flags: _MM_ROUND_NEAREST,
1913// _MM_ROUND_DOWN, _MM_ROUND_UP, _MM_ROUND_TOWARD_ZERO
1914// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_MM_GET_ROUNDING_MODE
1916{
1917 union {
1918 fpcr_bitfield field;
1919#if defined(__aarch64__)
1920 uint64_t value;
1921#else
1922 uint32_t value;
1923#endif
1924 } r;
1925
1926#if defined(__aarch64__)
1927 __asm__ __volatile__("mrs %0, FPCR" : "=r"(r.value)); /* read */
1928#else
1929 __asm__ __volatile__("vmrs %0, FPSCR" : "=r"(r.value)); /* read */
1930#endif
1931
1932 if (r.field.bit22) {
1933 return r.field.bit23 ? _MM_ROUND_TOWARD_ZERO : _MM_ROUND_UP;
1934 } else {
1935 return r.field.bit23 ? _MM_ROUND_DOWN : _MM_ROUND_NEAREST;
1936 }
1937}
1938
1939// Copy a to dst, and insert the 16-bit integer i into dst at the location
1940// specified by imm8.
1941// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_insert_pi16
1942#define _mm_insert_pi16(a, b, imm) \
1943 __extension__({ \
1944 vreinterpret_m64_s16( \
1945 vset_lane_s16((b), vreinterpret_s16_m64(a), (imm))); \
1946 })
1947
1948// Loads four single-precision, floating-point values.
1949// https://msdn.microsoft.com/en-us/library/vstudio/zzd50xxt(v=vs.100).aspx
1951{
1952 return vreinterpretq_m128_f32(vld1q_f32(p));
1953}
1954
1955// Load a single-precision (32-bit) floating-point element from memory into all
1956// elements of dst.
1957//
1958// dst[31:0] := MEM[mem_addr+31:mem_addr]
1959// dst[63:32] := MEM[mem_addr+31:mem_addr]
1960// dst[95:64] := MEM[mem_addr+31:mem_addr]
1961// dst[127:96] := MEM[mem_addr+31:mem_addr]
1962//
1963// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_load_ps1
1964#define _mm_load_ps1 _mm_load1_ps
1965
1966// Loads an single - precision, floating - point value into the low word and
1967// clears the upper three words.
1968// https://msdn.microsoft.com/en-us/library/548bb9h4%28v=vs.90%29.aspx
1970{
1971 return vreinterpretq_m128_f32(vsetq_lane_f32(*p, vdupq_n_f32(0), 0));
1972}
1973
1974// Loads a single single-precision, floating-point value, copying it into all
1975// four words
1976// https://msdn.microsoft.com/en-us/library/vstudio/5cdkf716(v=vs.100).aspx
1978{
1979 return vreinterpretq_m128_f32(vld1q_dup_f32(p));
1980}
1981
1982// Sets the upper two single-precision, floating-point values with 64
1983// bits of data loaded from the address p; the lower two values are passed
1984// through from a.
1985//
1986// r0 := a0
1987// r1 := a1
1988// r2 := *p0
1989// r3 := *p1
1990//
1991// https://msdn.microsoft.com/en-us/library/w92wta0x(v%3dvs.100).aspx
1993{
1995 vcombine_f32(vget_low_f32(a), vld1_f32((const float32_t *) p)));
1996}
1997
1998// Sets the lower two single-precision, floating-point values with 64
1999// bits of data loaded from the address p; the upper two values are passed
2000// through from a.
2001//
2002// Return Value
2003// r0 := *p0
2004// r1 := *p1
2005// r2 := a2
2006// r3 := a3
2007//
2008// https://msdn.microsoft.com/en-us/library/s57cyak2(v=vs.100).aspx
2010{
2012 vcombine_f32(vld1_f32((const float32_t *) p), vget_high_f32(a)));
2013}
2014
2015// Load 4 single-precision (32-bit) floating-point elements from memory into dst
2016// in reverse order. mem_addr must be aligned on a 16-byte boundary or a
2017// general-protection exception may be generated.
2018//
2019// dst[31:0] := MEM[mem_addr+127:mem_addr+96]
2020// dst[63:32] := MEM[mem_addr+95:mem_addr+64]
2021// dst[95:64] := MEM[mem_addr+63:mem_addr+32]
2022// dst[127:96] := MEM[mem_addr+31:mem_addr]
2023//
2024// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_loadr_ps
2026{
2027 float32x4_t v = vrev64q_f32(vld1q_f32(p));
2028 return vreinterpretq_m128_f32(vextq_f32(v, v, 2));
2029}
2030
2031// Loads four single-precision, floating-point values.
2032// https://msdn.microsoft.com/en-us/library/x1b16s7z%28v=vs.90%29.aspx
2034{
2035 // for neon, alignment doesn't matter, so _mm_load_ps and _mm_loadu_ps are
2036 // equivalent for neon
2037 return vreinterpretq_m128_f32(vld1q_f32(p));
2038}
2039
2040// Load unaligned 16-bit integer from memory into the first element of dst.
2041//
2042// dst[15:0] := MEM[mem_addr+15:mem_addr]
2043// dst[MAX:16] := 0
2044//
2045// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_loadu_si16
2047{
2049 vsetq_lane_s16(*(const int16_t *) p, vdupq_n_s16(0), 0));
2050}
2051
2052// Load unaligned 64-bit integer from memory into the first element of dst.
2053//
2054// dst[63:0] := MEM[mem_addr+63:mem_addr]
2055// dst[MAX:64] := 0
2056//
2057// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_loadu_si64
2059{
2061 vcombine_s64(vld1_s64((const int64_t *) p), vdup_n_s64(0)));
2062}
2063
2064// Allocate aligned blocks of memory.
2065// https://software.intel.com/en-us/
2066// cpp-compiler-developer-guide-and-reference-allocating-and-freeing-aligned-memory-blocks
2067#if !defined(SSE2NEON_ALLOC_DEFINED)
2068FORCE_INLINE void *_mm_malloc(size_t size, size_t align)
2069{
2070 void *ptr;
2071 if (align == 1)
2072 return malloc(size);
2073 if (align == 2 || (sizeof(void *) == 8 && align == 4))
2074 align = sizeof(void *);
2075 if (!posix_memalign(&ptr, align, size))
2076 return ptr;
2077 return NULL;
2078}
2079#endif
2080
2081// Conditionally store 8-bit integer elements from a into memory using mask
2082// (elements are not stored when the highest bit is not set in the corresponding
2083// element) and a non-temporal memory hint.
2084// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_maskmove_si64
2085FORCE_INLINE void _mm_maskmove_si64(__m64 a, __m64 mask, char *mem_addr)
2086{
2087 int8x8_t shr_mask = vshr_n_s8(vreinterpret_s8_m64(mask), 7);
2088 __m128 b = _mm_load_ps((const float *) mem_addr);
2089 int8x8_t masked =
2090 vbsl_s8(vreinterpret_u8_s8(shr_mask), vreinterpret_s8_m64(a),
2091 vreinterpret_s8_u64(vget_low_u64(vreinterpretq_u64_m128(b))));
2092 vst1_s8((int8_t *) mem_addr, masked);
2093}
2094
2095// Conditionally store 8-bit integer elements from a into memory using mask
2096// (elements are not stored when the highest bit is not set in the corresponding
2097// element) and a non-temporal memory hint.
2098// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_m_maskmovq
2099#define _m_maskmovq(a, mask, mem_addr) _mm_maskmove_si64(a, mask, mem_addr)
2100
2101// Compare packed signed 16-bit integers in a and b, and store packed maximum
2102// values in dst.
2103//
2104// FOR j := 0 to 3
2105// i := j*16
2106// dst[i+15:i] := MAX(a[i+15:i], b[i+15:i])
2107// ENDFOR
2108//
2109// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_max_pi16
2115
2116// Computes the maximums of the four single-precision, floating-point values of
2117// a and b.
2118// https://msdn.microsoft.com/en-us/library/vstudio/ff5d607a(v=vs.100).aspx
2120{
2121#if SSE2NEON_PRECISE_MINMAX
2122 float32x4_t _a = vreinterpretq_f32_m128(a);
2123 float32x4_t _b = vreinterpretq_f32_m128(b);
2124 return vreinterpretq_m128_f32(vbslq_f32(vcgtq_f32(_a, _b), _a, _b));
2125#else
2128#endif
2129}
2130
2131// Compare packed unsigned 8-bit integers in a and b, and store packed maximum
2132// values in dst.
2133//
2134// FOR j := 0 to 7
2135// i := j*8
2136// dst[i+7:i] := MAX(a[i+7:i], b[i+7:i])
2137// ENDFOR
2138//
2139// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_max_pu8
2145
2146// Computes the maximum of the two lower scalar single-precision floating point
2147// values of a and b.
2148// https://msdn.microsoft.com/en-us/library/s6db5esz(v=vs.100).aspx
2150{
2151 float32_t value = vgetq_lane_f32(_mm_max_ps(a, b), 0);
2153 vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0));
2154}
2155
2156// Compare packed signed 16-bit integers in a and b, and store packed minimum
2157// values in dst.
2158//
2159// FOR j := 0 to 3
2160// i := j*16
2161// dst[i+15:i] := MIN(a[i+15:i], b[i+15:i])
2162// ENDFOR
2163//
2164// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_min_pi16
2170
2171// Computes the minima of the four single-precision, floating-point values of a
2172// and b.
2173// https://msdn.microsoft.com/en-us/library/vstudio/wh13kadz(v=vs.100).aspx
2175{
2176#if SSE2NEON_PRECISE_MINMAX
2177 float32x4_t _a = vreinterpretq_f32_m128(a);
2178 float32x4_t _b = vreinterpretq_f32_m128(b);
2179 return vreinterpretq_m128_f32(vbslq_f32(vcltq_f32(_a, _b), _a, _b));
2180#else
2183#endif
2184}
2185
2186// Compare packed unsigned 8-bit integers in a and b, and store packed minimum
2187// values in dst.
2188//
2189// FOR j := 0 to 7
2190// i := j*8
2191// dst[i+7:i] := MIN(a[i+7:i], b[i+7:i])
2192// ENDFOR
2193//
2194// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_min_pu8
2200
2201// Computes the minimum of the two lower scalar single-precision floating point
2202// values of a and b.
2203// https://msdn.microsoft.com/en-us/library/0a9y7xaa(v=vs.100).aspx
2205{
2206 float32_t value = vgetq_lane_f32(_mm_min_ps(a, b), 0);
2208 vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0));
2209}
2210
2211// Sets the low word to the single-precision, floating-point value of b
2212// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/35hdzazd(v=vs.100)
2214{
2216 vsetq_lane_f32(vgetq_lane_f32(vreinterpretq_f32_m128(b), 0),
2217 vreinterpretq_f32_m128(a), 0));
2218}
2219
2220// Moves the upper two values of B into the lower two values of A.
2221//
2222// r3 := a3
2223// r2 := a2
2224// r1 := b3
2225// r0 := b2
2227{
2228 float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(__A));
2229 float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(__B));
2230 return vreinterpretq_m128_f32(vcombine_f32(b32, a32));
2231}
2232
2233// Moves the lower two values of B into the upper two values of A.
2234//
2235// r3 := b1
2236// r2 := b0
2237// r1 := a1
2238// r0 := a0
2240{
2241 float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(__A));
2242 float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(__B));
2243 return vreinterpretq_m128_f32(vcombine_f32(a10, b10));
2244}
2245
2246// Create mask from the most significant bit of each 8-bit element in a, and
2247// store the result in dst.
2248// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_movemask_pi8
2250{
2251 uint8x8_t input = vreinterpret_u8_m64(a);
2252#if defined(__aarch64__)
2253 static const int8x8_t shift = {0, 1, 2, 3, 4, 5, 6, 7};
2254 uint8x8_t tmp = vshr_n_u8(input, 7);
2255 return vaddv_u8(vshl_u8(tmp, shift));
2256#else
2257 // Refer the implementation of `_mm_movemask_epi8`
2258 uint16x4_t high_bits = vreinterpret_u16_u8(vshr_n_u8(input, 7));
2259 uint32x2_t paired16 =
2260 vreinterpret_u32_u16(vsra_n_u16(high_bits, high_bits, 7));
2261 uint8x8_t paired32 =
2262 vreinterpret_u8_u32(vsra_n_u32(paired16, paired16, 14));
2263 return vget_lane_u8(paired32, 0) | ((int) vget_lane_u8(paired32, 4) << 4);
2264#endif
2265}
2266
2267// NEON does not provide this method
2268// Creates a 4-bit mask from the most significant bits of the four
2269// single-precision, floating-point values.
2270// https://msdn.microsoft.com/en-us/library/vstudio/4490ys29(v=vs.100).aspx
2272{
2273 uint32x4_t input = vreinterpretq_u32_m128(a);
2274#if defined(__aarch64__)
2275 static const int32x4_t shift = {0, 1, 2, 3};
2276 uint32x4_t tmp = vshrq_n_u32(input, 31);
2277 return vaddvq_u32(vshlq_u32(tmp, shift));
2278#else
2279 // Uses the exact same method as _mm_movemask_epi8, see that for details.
2280 // Shift out everything but the sign bits with a 32-bit unsigned shift
2281 // right.
2282 uint64x2_t high_bits = vreinterpretq_u64_u32(vshrq_n_u32(input, 31));
2283 // Merge the two pairs together with a 64-bit unsigned shift right + add.
2284 uint8x16_t paired =
2285 vreinterpretq_u8_u64(vsraq_n_u64(high_bits, high_bits, 31));
2286 // Extract the result.
2287 return vgetq_lane_u8(paired, 0) | (vgetq_lane_u8(paired, 8) << 2);
2288#endif
2289}
2290
2291// Multiplies the four single-precision, floating-point values of a and b.
2292//
2293// r0 := a0 * b0
2294// r1 := a1 * b1
2295// r2 := a2 * b2
2296// r3 := a3 * b3
2297//
2298// https://msdn.microsoft.com/en-us/library/vstudio/22kbk6t9(v=vs.100).aspx
2304
2305// Multiply the lower single-precision (32-bit) floating-point element in a and
2306// b, store the result in the lower element of dst, and copy the upper 3 packed
2307// elements from a to the upper elements of dst.
2308//
2309// dst[31:0] := a[31:0] * b[31:0]
2310// dst[127:32] := a[127:32]
2311//
2312// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mul_ss
2314{
2315 return _mm_move_ss(a, _mm_mul_ps(a, b));
2316}
2317
2318// Multiply the packed unsigned 16-bit integers in a and b, producing
2319// intermediate 32-bit integers, and store the high 16 bits of the intermediate
2320// integers in dst.
2321// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mulhi_pu16
2323{
2324 return vreinterpret_m64_u16(vshrn_n_u32(
2325 vmull_u16(vreinterpret_u16_m64(a), vreinterpret_u16_m64(b)), 16));
2326}
2327
2328// Computes the bitwise OR of the four single-precision, floating-point values
2329// of a and b.
2330// https://msdn.microsoft.com/en-us/library/vstudio/7ctdsyy0(v=vs.100).aspx
2336
2337// Average packed unsigned 8-bit integers in a and b, and store the results in
2338// dst.
2339//
2340// FOR j := 0 to 7
2341// i := j*8
2342// dst[i+7:i] := (a[i+7:i] + b[i+7:i] + 1) >> 1
2343// ENDFOR
2344//
2345// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_m_pavgb
2346#define _m_pavgb(a, b) _mm_avg_pu8(a, b)
2347
2348// Average packed unsigned 16-bit integers in a and b, and store the results in
2349// dst.
2350//
2351// FOR j := 0 to 3
2352// i := j*16
2353// dst[i+15:i] := (a[i+15:i] + b[i+15:i] + 1) >> 1
2354// ENDFOR
2355//
2356// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_m_pavgw
2357#define _m_pavgw(a, b) _mm_avg_pu16(a, b)
2358
2359// Extract a 16-bit integer from a, selected with imm8, and store the result in
2360// the lower element of dst.
2361// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_m_pextrw
2362#define _m_pextrw(a, imm) _mm_extract_pi16(a, imm)
2363
2364// Copy a to dst, and insert the 16-bit integer i into dst at the location
2365// specified by imm8.
2366// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=m_pinsrw
2367#define _m_pinsrw(a, i, imm) _mm_insert_pi16(a, i, imm)
2368
2369// Compare packed signed 16-bit integers in a and b, and store packed maximum
2370// values in dst.
2371// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_m_pmaxsw
2372#define _m_pmaxsw(a, b) _mm_max_pi16(a, b)
2373
2374// Compare packed unsigned 8-bit integers in a and b, and store packed maximum
2375// values in dst.
2376// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_m_pmaxub
2377#define _m_pmaxub(a, b) _mm_max_pu8(a, b)
2378
2379// Compare packed signed 16-bit integers in a and b, and store packed minimum
2380// values in dst.
2381// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_m_pminsw
2382#define _m_pminsw(a, b) _mm_min_pi16(a, b)
2383
2384// Compare packed unsigned 8-bit integers in a and b, and store packed minimum
2385// values in dst.
2386// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_m_pminub
2387#define _m_pminub(a, b) _mm_min_pu8(a, b)
2388
2389// Create mask from the most significant bit of each 8-bit element in a, and
2390// store the result in dst.
2391// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_m_pmovmskb
2392#define _m_pmovmskb(a) _mm_movemask_pi8(a)
2393
2394// Multiply the packed unsigned 16-bit integers in a and b, producing
2395// intermediate 32-bit integers, and store the high 16 bits of the intermediate
2396// integers in dst.
2397// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_m_pmulhuw
2398#define _m_pmulhuw(a, b) _mm_mulhi_pu16(a, b)
2399
2400// Fetch the line of data from memory that contains address p to a location in
2401// the cache heirarchy specified by the locality hint i.
2402// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_prefetch
2403FORCE_INLINE void _mm_prefetch(char const *p, int i)
2404{
2405 switch (i) {
2406 case _MM_HINT_NTA:
2407 __builtin_prefetch(p, 0, 0);
2408 break;
2409 case _MM_HINT_T0:
2410 __builtin_prefetch(p, 0, 3);
2411 break;
2412 case _MM_HINT_T1:
2413 __builtin_prefetch(p, 0, 2);
2414 break;
2415 case _MM_HINT_T2:
2416 __builtin_prefetch(p, 0, 1);
2417 break;
2418 }
2419}
2420
2421// Compute the absolute differences of packed unsigned 8-bit integers in a and
2422// b, then horizontally sum each consecutive 8 differences to produce four
2423// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low
2424// 16 bits of dst.
2425// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=m_psadbw
2426#define _m_psadbw(a, b) _mm_sad_pu8(a, b)
2427
2428// Shuffle 16-bit integers in a using the control in imm8, and store the results
2429// in dst.
2430// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_m_pshufw
2431#define _m_pshufw(a, imm) _mm_shuffle_pi16(a, imm)
2432
2433// Compute the approximate reciprocal of packed single-precision (32-bit)
2434// floating-point elements in a, and store the results in dst. The maximum
2435// relative error for this approximation is less than 1.5*2^-12.
2436// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_rcp_ps
2438{
2439 float32x4_t recip = vrecpeq_f32(vreinterpretq_f32_m128(in));
2440 recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(in)));
2441#if SSE2NEON_PRECISE_DIV
2442 // Additional Netwon-Raphson iteration for accuracy
2443 recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(in)));
2444#endif
2445 return vreinterpretq_m128_f32(recip);
2446}
2447
2448// Compute the approximate reciprocal of the lower single-precision (32-bit)
2449// floating-point element in a, store the result in the lower element of dst,
2450// and copy the upper 3 packed elements from a to the upper elements of dst. The
2451// maximum relative error for this approximation is less than 1.5*2^-12.
2452//
2453// dst[31:0] := (1.0 / a[31:0])
2454// dst[127:32] := a[127:32]
2455//
2456// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_rcp_ss
2458{
2459 return _mm_move_ss(a, _mm_rcp_ps(a));
2460}
2461
2462// Computes the approximations of the reciprocal square roots of the four
2463// single-precision floating point values of in.
2464// The current precision is 1% error.
2465// https://msdn.microsoft.com/en-us/library/22hfsh53(v=vs.100).aspx
2467{
2468 float32x4_t out = vrsqrteq_f32(vreinterpretq_f32_m128(in));
2469#if SSE2NEON_PRECISE_SQRT
2470 // Additional Netwon-Raphson iteration for accuracy
2471 out = vmulq_f32(
2472 out, vrsqrtsq_f32(vmulq_f32(vreinterpretq_f32_m128(in), out), out));
2473 out = vmulq_f32(
2474 out, vrsqrtsq_f32(vmulq_f32(vreinterpretq_f32_m128(in), out), out));
2475#endif
2476 return vreinterpretq_m128_f32(out);
2477}
2478
2479// Compute the approximate reciprocal square root of the lower single-precision
2480// (32-bit) floating-point element in a, store the result in the lower element
2481// of dst, and copy the upper 3 packed elements from a to the upper elements of
2482// dst.
2483// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_rsqrt_ss
2485{
2486 return vsetq_lane_f32(vgetq_lane_f32(_mm_rsqrt_ps(in), 0), in, 0);
2487}
2488
2489// Compute the absolute differences of packed unsigned 8-bit integers in a and
2490// b, then horizontally sum each consecutive 8 differences to produce four
2491// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low
2492// 16 bits of dst.
2493// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sad_pu8
2495{
2496 uint64x1_t t = vpaddl_u32(vpaddl_u16(
2497 vpaddl_u8(vabd_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b)))));
2498 return vreinterpret_m64_u16(
2499 vset_lane_u16(vget_lane_u64(t, 0), vdup_n_u16(0), 0));
2500}
2501
2502// Macro: Set the flush zero bits of the MXCSR control and status register to
2503// the value in unsigned 32-bit integer a. The flush zero may contain any of the
2504// following flags: _MM_FLUSH_ZERO_ON or _MM_FLUSH_ZERO_OFF
2505// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_MM_SET_FLUSH_ZERO_MODE
2507{
2508 // AArch32 Advanced SIMD arithmetic always uses the Flush-to-zero setting,
2509 // regardless of the value of the FZ bit.
2510 union {
2511 fpcr_bitfield field;
2512#if defined(__aarch64__)
2513 uint64_t value;
2514#else
2515 uint32_t value;
2516#endif
2517 } r;
2518
2519#if defined(__aarch64__)
2520 __asm__ __volatile__("mrs %0, FPCR" : "=r"(r.value)); /* read */
2521#else
2522 __asm__ __volatile__("vmrs %0, FPSCR" : "=r"(r.value)); /* read */
2523#endif
2524
2525 r.field.bit24 = (flag & _MM_FLUSH_ZERO_MASK) == _MM_FLUSH_ZERO_ON;
2526
2527#if defined(__aarch64__)
2528 __asm__ __volatile__("msr FPCR, %0" ::"r"(r)); /* write */
2529#else
2530 __asm__ __volatile__("vmsr FPSCR, %0" ::"r"(r)); /* write */
2531#endif
2532}
2533
2534// Sets the four single-precision, floating-point values to the four inputs.
2535// https://msdn.microsoft.com/en-us/library/vstudio/afh0zf75(v=vs.100).aspx
2536FORCE_INLINE __m128 _mm_set_ps(float w, float z, float y, float x)
2537{
2538 float ALIGN_STRUCT(16) data[4] = {x, y, z, w};
2539 return vreinterpretq_m128_f32(vld1q_f32(data));
2540}
2541
2542// Sets the four single-precision, floating-point values to w.
2543// https://msdn.microsoft.com/en-us/library/vstudio/2x1se8ha(v=vs.100).aspx
2545{
2546 return vreinterpretq_m128_f32(vdupq_n_f32(_w));
2547}
2548
2549// Macro: Set the rounding mode bits of the MXCSR control and status register to
2550// the value in unsigned 32-bit integer a. The rounding mode may contain any of
2551// the following flags: _MM_ROUND_NEAREST, _MM_ROUND_DOWN, _MM_ROUND_UP,
2552// _MM_ROUND_TOWARD_ZERO
2553// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_MM_SET_ROUNDING_MODE
2555{
2556 union {
2557 fpcr_bitfield field;
2558#if defined(__aarch64__)
2559 uint64_t value;
2560#else
2561 uint32_t value;
2562#endif
2563 } r;
2564
2565#if defined(__aarch64__)
2566 __asm__ __volatile__("mrs %0, FPCR" : "=r"(r.value)); /* read */
2567#else
2568 __asm__ __volatile__("vmrs %0, FPSCR" : "=r"(r.value)); /* read */
2569#endif
2570
2571 switch (rounding) {
2573 r.field.bit22 = 1;
2574 r.field.bit23 = 1;
2575 break;
2576 case _MM_ROUND_DOWN:
2577 r.field.bit22 = 0;
2578 r.field.bit23 = 1;
2579 break;
2580 case _MM_ROUND_UP:
2581 r.field.bit22 = 1;
2582 r.field.bit23 = 0;
2583 break;
2584 default: //_MM_ROUND_NEAREST
2585 r.field.bit22 = 0;
2586 r.field.bit23 = 0;
2587 }
2588
2589#if defined(__aarch64__)
2590 __asm__ __volatile__("msr FPCR, %0" ::"r"(r)); /* write */
2591#else
2592 __asm__ __volatile__("vmsr FPSCR, %0" ::"r"(r)); /* write */
2593#endif
2594}
2595
2596// Copy single-precision (32-bit) floating-point element a to the lower element
2597// of dst, and zero the upper 3 elements.
2598// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_set_ss
2600{
2601 return vreinterpretq_m128_f32(vsetq_lane_f32(a, vdupq_n_f32(0), 0));
2602}
2603
2604// Sets the four single-precision, floating-point values to w.
2605//
2606// r0 := r1 := r2 := r3 := w
2607//
2608// https://msdn.microsoft.com/en-us/library/vstudio/2x1se8ha(v=vs.100).aspx
2610{
2611 return vreinterpretq_m128_f32(vdupq_n_f32(_w));
2612}
2613
2614// FIXME: _mm_setcsr() implementation supports changing the rounding mode only.
2615FORCE_INLINE void _mm_setcsr(unsigned int a)
2616{
2618}
2619
2620// FIXME: _mm_getcsr() implementation supports reading the rounding mode only.
2622{
2623 return _MM_GET_ROUNDING_MODE();
2624}
2625
2626// Sets the four single-precision, floating-point values to the four inputs in
2627// reverse order.
2628// https://msdn.microsoft.com/en-us/library/vstudio/d2172ct3(v=vs.100).aspx
2629FORCE_INLINE __m128 _mm_setr_ps(float w, float z, float y, float x)
2630{
2631 float ALIGN_STRUCT(16) data[4] = {w, z, y, x};
2632 return vreinterpretq_m128_f32(vld1q_f32(data));
2633}
2634
2635// Clears the four single-precision, floating-point values.
2636// https://msdn.microsoft.com/en-us/library/vstudio/tk1t2tbz(v=vs.100).aspx
2638{
2639 return vreinterpretq_m128_f32(vdupq_n_f32(0));
2640}
2641
2642// Shuffle 16-bit integers in a using the control in imm8, and store the results
2643// in dst.
2644// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_shuffle_pi16
2645#ifdef _sse2neon_shuffle
2646#define _mm_shuffle_pi16(a, imm) \
2647 __extension__({ \
2648 vreinterpret_m64_s16(vshuffle_s16( \
2649 vreinterpret_s16_m64(a), vreinterpret_s16_m64(a), (imm & 0x3), \
2650 ((imm >> 2) & 0x3), ((imm >> 4) & 0x3), ((imm >> 6) & 0x3))); \
2651 })
2652#else
2653#define _mm_shuffle_pi16(a, imm) \
2654 __extension__({ \
2655 int16x4_t ret; \
2656 ret = \
2657 vmov_n_s16(vget_lane_s16(vreinterpret_s16_m64(a), (imm) & (0x3))); \
2658 ret = vset_lane_s16( \
2659 vget_lane_s16(vreinterpret_s16_m64(a), ((imm) >> 2) & 0x3), ret, \
2660 1); \
2661 ret = vset_lane_s16( \
2662 vget_lane_s16(vreinterpret_s16_m64(a), ((imm) >> 4) & 0x3), ret, \
2663 2); \
2664 ret = vset_lane_s16( \
2665 vget_lane_s16(vreinterpret_s16_m64(a), ((imm) >> 6) & 0x3), ret, \
2666 3); \
2667 vreinterpret_m64_s16(ret); \
2668 })
2669#endif
2670
2671// Perform a serializing operation on all store-to-memory instructions that were
2672// issued prior to this instruction. Guarantees that every store instruction
2673// that precedes, in program order, is globally visible before any store
2674// instruction which follows the fence in program order.
2675// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sfence
2677{
2679}
2680
2681// Perform a serializing operation on all load-from-memory and store-to-memory
2682// instructions that were issued prior to this instruction. Guarantees that
2683// every memory access that precedes, in program order, the memory fence
2684// instruction is globally visible before any memory instruction which follows
2685// the fence in program order.
2686// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mfence
2688{
2690}
2691
2692// Perform a serializing operation on all load-from-memory instructions that
2693// were issued prior to this instruction. Guarantees that every load instruction
2694// that precedes, in program order, is globally visible before any load
2695// instruction which follows the fence in program order.
2696// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_lfence
2698{
2700}
2701
2702// FORCE_INLINE __m128 _mm_shuffle_ps(__m128 a, __m128 b, __constrange(0,255)
2703// int imm)
2704#ifdef _sse2neon_shuffle
2705#define _mm_shuffle_ps(a, b, imm) \
2706 __extension__({ \
2707 float32x4_t _input1 = vreinterpretq_f32_m128(a); \
2708 float32x4_t _input2 = vreinterpretq_f32_m128(b); \
2709 float32x4_t _shuf = \
2710 vshuffleq_s32(_input1, _input2, (imm) & (0x3), ((imm) >> 2) & 0x3, \
2711 (((imm) >> 4) & 0x3) + 4, (((imm) >> 6) & 0x3) + 4); \
2712 vreinterpretq_m128_f32(_shuf); \
2713 })
2714#else // generic
2715#define _mm_shuffle_ps(a, b, imm) \
2716 __extension__({ \
2717 __m128 ret; \
2718 switch (imm) { \
2719 case _MM_SHUFFLE(1, 0, 3, 2): \
2720 ret = _mm_shuffle_ps_1032((a), (b)); \
2721 break; \
2722 case _MM_SHUFFLE(2, 3, 0, 1): \
2723 ret = _mm_shuffle_ps_2301((a), (b)); \
2724 break; \
2725 case _MM_SHUFFLE(0, 3, 2, 1): \
2726 ret = _mm_shuffle_ps_0321((a), (b)); \
2727 break; \
2728 case _MM_SHUFFLE(2, 1, 0, 3): \
2729 ret = _mm_shuffle_ps_2103((a), (b)); \
2730 break; \
2731 case _MM_SHUFFLE(1, 0, 1, 0): \
2732 ret = _mm_movelh_ps((a), (b)); \
2733 break; \
2734 case _MM_SHUFFLE(1, 0, 0, 1): \
2735 ret = _mm_shuffle_ps_1001((a), (b)); \
2736 break; \
2737 case _MM_SHUFFLE(0, 1, 0, 1): \
2738 ret = _mm_shuffle_ps_0101((a), (b)); \
2739 break; \
2740 case _MM_SHUFFLE(3, 2, 1, 0): \
2741 ret = _mm_shuffle_ps_3210((a), (b)); \
2742 break; \
2743 case _MM_SHUFFLE(0, 0, 1, 1): \
2744 ret = _mm_shuffle_ps_0011((a), (b)); \
2745 break; \
2746 case _MM_SHUFFLE(0, 0, 2, 2): \
2747 ret = _mm_shuffle_ps_0022((a), (b)); \
2748 break; \
2749 case _MM_SHUFFLE(2, 2, 0, 0): \
2750 ret = _mm_shuffle_ps_2200((a), (b)); \
2751 break; \
2752 case _MM_SHUFFLE(3, 2, 0, 2): \
2753 ret = _mm_shuffle_ps_3202((a), (b)); \
2754 break; \
2755 case _MM_SHUFFLE(3, 2, 3, 2): \
2756 ret = _mm_movehl_ps((b), (a)); \
2757 break; \
2758 case _MM_SHUFFLE(1, 1, 3, 3): \
2759 ret = _mm_shuffle_ps_1133((a), (b)); \
2760 break; \
2761 case _MM_SHUFFLE(2, 0, 1, 0): \
2762 ret = _mm_shuffle_ps_2010((a), (b)); \
2763 break; \
2764 case _MM_SHUFFLE(2, 0, 0, 1): \
2765 ret = _mm_shuffle_ps_2001((a), (b)); \
2766 break; \
2767 case _MM_SHUFFLE(2, 0, 3, 2): \
2768 ret = _mm_shuffle_ps_2032((a), (b)); \
2769 break; \
2770 default: \
2771 ret = _mm_shuffle_ps_default((a), (b), (imm)); \
2772 break; \
2773 } \
2774 ret; \
2775 })
2776#endif
2777
2778// Computes the approximations of square roots of the four single-precision,
2779// floating-point values of a. First computes reciprocal square roots and then
2780// reciprocals of the four values.
2781//
2782// r0 := sqrt(a0)
2783// r1 := sqrt(a1)
2784// r2 := sqrt(a2)
2785// r3 := sqrt(a3)
2786//
2787// https://msdn.microsoft.com/en-us/library/vstudio/8z67bwwk(v=vs.100).aspx
2789{
2790#if SSE2NEON_PRECISE_SQRT
2791 float32x4_t recip = vrsqrteq_f32(vreinterpretq_f32_m128(in));
2792
2793 // Test for vrsqrteq_f32(0) -> positive infinity case.
2794 // Change to zero, so that s * 1/sqrt(s) result is zero too.
2795 const uint32x4_t pos_inf = vdupq_n_u32(0x7F800000);
2796 const uint32x4_t div_by_zero =
2797 vceqq_u32(pos_inf, vreinterpretq_u32_f32(recip));
2798 recip = vreinterpretq_f32_u32(
2799 vandq_u32(vmvnq_u32(div_by_zero), vreinterpretq_u32_f32(recip)));
2800
2801 // Additional Netwon-Raphson iteration for accuracy
2802 recip = vmulq_f32(
2803 vrsqrtsq_f32(vmulq_f32(recip, recip), vreinterpretq_f32_m128(in)),
2804 recip);
2805 recip = vmulq_f32(
2806 vrsqrtsq_f32(vmulq_f32(recip, recip), vreinterpretq_f32_m128(in)),
2807 recip);
2808
2809 // sqrt(s) = s * 1/sqrt(s)
2810 return vreinterpretq_m128_f32(vmulq_f32(vreinterpretq_f32_m128(in), recip));
2811#elif defined(__aarch64__)
2812 return vreinterpretq_m128_f32(vsqrtq_f32(vreinterpretq_f32_m128(in)));
2813#else
2814 float32x4_t recipsq = vrsqrteq_f32(vreinterpretq_f32_m128(in));
2815 float32x4_t sq = vrecpeq_f32(recipsq);
2816 return vreinterpretq_m128_f32(sq);
2817#endif
2818}
2819
2820// Computes the approximation of the square root of the scalar single-precision
2821// floating point value of in.
2822// https://msdn.microsoft.com/en-us/library/ahfsc22d(v=vs.100).aspx
2824{
2825 float32_t value =
2826 vgetq_lane_f32(vreinterpretq_f32_m128(_mm_sqrt_ps(in)), 0);
2828 vsetq_lane_f32(value, vreinterpretq_f32_m128(in), 0));
2829}
2830
2831// Stores four single-precision, floating-point values.
2832// https://msdn.microsoft.com/en-us/library/vstudio/s3h4ay6y(v=vs.100).aspx
2834{
2835 vst1q_f32(p, vreinterpretq_f32_m128(a));
2836}
2837
2838// Store the lower single-precision (32-bit) floating-point element from a into
2839// 4 contiguous elements in memory. mem_addr must be aligned on a 16-byte
2840// boundary or a general-protection exception may be generated.
2841//
2842// MEM[mem_addr+31:mem_addr] := a[31:0]
2843// MEM[mem_addr+63:mem_addr+32] := a[31:0]
2844// MEM[mem_addr+95:mem_addr+64] := a[31:0]
2845// MEM[mem_addr+127:mem_addr+96] := a[31:0]
2846//
2847// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_store_ps1
2849{
2850 float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
2851 vst1q_f32(p, vdupq_n_f32(a0));
2852}
2853
2854// Stores the lower single - precision, floating - point value.
2855// https://msdn.microsoft.com/en-us/library/tzz10fbx(v=vs.100).aspx
2857{
2858 vst1q_lane_f32(p, vreinterpretq_f32_m128(a), 0);
2859}
2860
2861// Store the lower single-precision (32-bit) floating-point element from a into
2862// 4 contiguous elements in memory. mem_addr must be aligned on a 16-byte
2863// boundary or a general-protection exception may be generated.
2864//
2865// MEM[mem_addr+31:mem_addr] := a[31:0]
2866// MEM[mem_addr+63:mem_addr+32] := a[31:0]
2867// MEM[mem_addr+95:mem_addr+64] := a[31:0]
2868// MEM[mem_addr+127:mem_addr+96] := a[31:0]
2869//
2870// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_store1_ps
2871#define _mm_store1_ps _mm_store_ps1
2872
2873// Stores the upper two single-precision, floating-point values of a to the
2874// address p.
2875//
2876// *p0 := a2
2877// *p1 := a3
2878//
2879// https://msdn.microsoft.com/en-us/library/a7525fs8(v%3dvs.90).aspx
2881{
2882 *p = vreinterpret_m64_f32(vget_high_f32(a));
2883}
2884
2885// Stores the lower two single-precision floating point values of a to the
2886// address p.
2887//
2888// *p0 := a0
2889// *p1 := a1
2890//
2891// https://msdn.microsoft.com/en-us/library/h54t98ks(v=vs.90).aspx
2893{
2894 *p = vreinterpret_m64_f32(vget_low_f32(a));
2895}
2896
2897// Store 4 single-precision (32-bit) floating-point elements from a into memory
2898// in reverse order. mem_addr must be aligned on a 16-byte boundary or a
2899// general-protection exception may be generated.
2900//
2901// MEM[mem_addr+31:mem_addr] := a[127:96]
2902// MEM[mem_addr+63:mem_addr+32] := a[95:64]
2903// MEM[mem_addr+95:mem_addr+64] := a[63:32]
2904// MEM[mem_addr+127:mem_addr+96] := a[31:0]
2905//
2906// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_storer_ps
2908{
2909 float32x4_t tmp = vrev64q_f32(vreinterpretq_f32_m128(a));
2910 float32x4_t rev = vextq_f32(tmp, tmp, 2);
2911 vst1q_f32(p, rev);
2912}
2913
2914// Stores four single-precision, floating-point values.
2915// https://msdn.microsoft.com/en-us/library/44e30x22(v=vs.100).aspx
2917{
2918 vst1q_f32(p, vreinterpretq_f32_m128(a));
2919}
2920
2921// Stores 16-bits of integer data a at the address p.
2922// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_storeu_si16
2924{
2925 vst1q_lane_s16((int16_t *) p, vreinterpretq_s16_m128i(a), 0);
2926}
2927
2928// Stores 64-bits of integer data a at the address p.
2929// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_storeu_si64
2931{
2932 vst1q_lane_s64((int64_t *) p, vreinterpretq_s64_m128i(a), 0);
2933}
2934
2935// Store 64-bits of integer data from a into memory using a non-temporal memory
2936// hint.
2937// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_stream_pi
2939{
2940 vst1_s64((int64_t *) p, vreinterpret_s64_m64(a));
2941}
2942
2943// Store 128-bits (composed of 4 packed single-precision (32-bit) floating-
2944// point elements) from a into memory using a non-temporal memory hint.
2945// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_stream_ps
2947{
2948#if __has_builtin(__builtin_nontemporal_store)
2949 __builtin_nontemporal_store(a, (float32x4_t *) p);
2950#else
2951 vst1q_f32(p, vreinterpretq_f32_m128(a));
2952#endif
2953}
2954
2955// Subtracts the four single-precision, floating-point values of a and b.
2956//
2957// r0 := a0 - b0
2958// r1 := a1 - b1
2959// r2 := a2 - b2
2960// r3 := a3 - b3
2961//
2962// https://msdn.microsoft.com/en-us/library/vstudio/1zad2k61(v=vs.100).aspx
2968
2969// Subtract the lower single-precision (32-bit) floating-point element in b from
2970// the lower single-precision (32-bit) floating-point element in a, store the
2971// result in the lower element of dst, and copy the upper 3 packed elements from
2972// a to the upper elements of dst.
2973//
2974// dst[31:0] := a[31:0] - b[31:0]
2975// dst[127:32] := a[127:32]
2976//
2977// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sub_ss
2979{
2980 return _mm_move_ss(a, _mm_sub_ps(a, b));
2981}
2982
2983// Macro: Transpose the 4x4 matrix formed by the 4 rows of single-precision
2984// (32-bit) floating-point elements in row0, row1, row2, and row3, and store the
2985// transposed matrix in these vectors (row0 now contains column 0, etc.).
2986// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=MM_TRANSPOSE4_PS
2987#define _MM_TRANSPOSE4_PS(row0, row1, row2, row3) \
2988 do { \
2989 float32x4x2_t ROW01 = vtrnq_f32(row0, row1); \
2990 float32x4x2_t ROW23 = vtrnq_f32(row2, row3); \
2991 row0 = vcombine_f32(vget_low_f32(ROW01.val[0]), \
2992 vget_low_f32(ROW23.val[0])); \
2993 row1 = vcombine_f32(vget_low_f32(ROW01.val[1]), \
2994 vget_low_f32(ROW23.val[1])); \
2995 row2 = vcombine_f32(vget_high_f32(ROW01.val[0]), \
2996 vget_high_f32(ROW23.val[0])); \
2997 row3 = vcombine_f32(vget_high_f32(ROW01.val[1]), \
2998 vget_high_f32(ROW23.val[1])); \
2999 } while (0)
3000
3001// according to the documentation, these intrinsics behave the same as the
3002// non-'u' versions. We'll just alias them here.
3003#define _mm_ucomieq_ss _mm_comieq_ss
3004#define _mm_ucomige_ss _mm_comige_ss
3005#define _mm_ucomigt_ss _mm_comigt_ss
3006#define _mm_ucomile_ss _mm_comile_ss
3007#define _mm_ucomilt_ss _mm_comilt_ss
3008#define _mm_ucomineq_ss _mm_comineq_ss
3009
3010// Return vector of type __m128i with undefined elements.
3011// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=mm_undefined_si128
3013{
3014#if defined(__GNUC__) || defined(__clang__)
3015#pragma GCC diagnostic push
3016#pragma GCC diagnostic ignored "-Wuninitialized"
3017#endif
3018 __m128i a;
3019 return a;
3020#if defined(__GNUC__) || defined(__clang__)
3021#pragma GCC diagnostic pop
3022#endif
3023}
3024
3025// Return vector of type __m128 with undefined elements.
3026// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_undefined_ps
3028{
3029#if defined(__GNUC__) || defined(__clang__)
3030#pragma GCC diagnostic push
3031#pragma GCC diagnostic ignored "-Wuninitialized"
3032#endif
3033 __m128 a;
3034 return a;
3035#if defined(__GNUC__) || defined(__clang__)
3036#pragma GCC diagnostic pop
3037#endif
3038}
3039
3040// Selects and interleaves the upper two single-precision, floating-point values
3041// from a and b.
3042//
3043// r0 := a2
3044// r1 := b2
3045// r2 := a3
3046// r3 := b3
3047//
3048// https://msdn.microsoft.com/en-us/library/skccxx7d%28v=vs.90%29.aspx
3050{
3051#if defined(__aarch64__)
3054#else
3055 float32x2_t a1 = vget_high_f32(vreinterpretq_f32_m128(a));
3056 float32x2_t b1 = vget_high_f32(vreinterpretq_f32_m128(b));
3057 float32x2x2_t result = vzip_f32(a1, b1);
3058 return vreinterpretq_m128_f32(vcombine_f32(result.val[0], result.val[1]));
3059#endif
3060}
3061
3062// Selects and interleaves the lower two single-precision, floating-point values
3063// from a and b.
3064//
3065// r0 := a0
3066// r1 := b0
3067// r2 := a1
3068// r3 := b1
3069//
3070// https://msdn.microsoft.com/en-us/library/25st103b%28v=vs.90%29.aspx
3072{
3073#if defined(__aarch64__)
3076#else
3077 float32x2_t a1 = vget_low_f32(vreinterpretq_f32_m128(a));
3078 float32x2_t b1 = vget_low_f32(vreinterpretq_f32_m128(b));
3079 float32x2x2_t result = vzip_f32(a1, b1);
3080 return vreinterpretq_m128_f32(vcombine_f32(result.val[0], result.val[1]));
3081#endif
3082}
3083
3084// Computes bitwise EXOR (exclusive-or) of the four single-precision,
3085// floating-point values of a and b.
3086// https://msdn.microsoft.com/en-us/library/ss6k3wk8(v=vs.100).aspx
3092
3093/* SSE2 */
3094
3095// Adds the 8 signed or unsigned 16-bit integers in a to the 8 signed or
3096// unsigned 16-bit integers in b.
3097// https://msdn.microsoft.com/en-us/library/fceha5k4(v=vs.100).aspx
3103
3104// Adds the 4 signed or unsigned 32-bit integers in a to the 4 signed or
3105// unsigned 32-bit integers in b.
3106//
3107// r0 := a0 + b0
3108// r1 := a1 + b1
3109// r2 := a2 + b2
3110// r3 := a3 + b3
3111//
3112// https://msdn.microsoft.com/en-us/library/vstudio/09xs4fkk(v=vs.100).aspx
3118
3119// Adds the 4 signed or unsigned 64-bit integers in a to the 4 signed or
3120// unsigned 32-bit integers in b.
3121// https://msdn.microsoft.com/en-us/library/vstudio/09xs4fkk(v=vs.100).aspx
3127
3128// Adds the 16 signed or unsigned 8-bit integers in a to the 16 signed or
3129// unsigned 8-bit integers in b.
3130// https://technet.microsoft.com/en-us/subscriptions/yc7tcyzs(v=vs.90)
3136
3137// Add packed double-precision (64-bit) floating-point elements in a and b, and
3138// store the results in dst.
3139// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_add_pd
3141{
3142#if defined(__aarch64__)
3143 return vreinterpretq_m128d_f64(
3144 vaddq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
3145#else
3146 double *da = (double *) &a;
3147 double *db = (double *) &b;
3148 double c[2];
3149 c[0] = da[0] + db[0];
3150 c[1] = da[1] + db[1];
3151 return vld1q_f32((float32_t *) c);
3152#endif
3153}
3154
3155// Add the lower double-precision (64-bit) floating-point element in a and b,
3156// store the result in the lower element of dst, and copy the upper element from
3157// a to the upper element of dst.
3158//
3159// dst[63:0] := a[63:0] + b[63:0]
3160// dst[127:64] := a[127:64]
3161//
3162// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_add_sd
3164{
3165#if defined(__aarch64__)
3166 return _mm_move_sd(a, _mm_add_pd(a, b));
3167#else
3168 double *da = (double *) &a;
3169 double *db = (double *) &b;
3170 double c[2];
3171 c[0] = da[0] + db[0];
3172 c[1] = da[1];
3173 return vld1q_f32((float32_t *) c);
3174#endif
3175}
3176
3177// Add 64-bit integers a and b, and store the result in dst.
3178//
3179// dst[63:0] := a[63:0] + b[63:0]
3180//
3181// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_add_si64
3187
3188// Adds the 8 signed 16-bit integers in a to the 8 signed 16-bit integers in b
3189// and saturates.
3190//
3191// r0 := SignedSaturate(a0 + b0)
3192// r1 := SignedSaturate(a1 + b1)
3193// ...
3194// r7 := SignedSaturate(a7 + b7)
3195//
3196// https://msdn.microsoft.com/en-us/library/1a306ef8(v=vs.100).aspx
3202
3203// Add packed signed 8-bit integers in a and b using saturation, and store the
3204// results in dst.
3205//
3206// FOR j := 0 to 15
3207// i := j*8
3208// dst[i+7:i] := Saturate8( a[i+7:i] + b[i+7:i] )
3209// ENDFOR
3210//
3211// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_adds_epi8
3217
3218// Add packed unsigned 16-bit integers in a and b using saturation, and store
3219// the results in dst.
3220// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_adds_epu16
3226
3227// Adds the 16 unsigned 8-bit integers in a to the 16 unsigned 8-bit integers in
3228// b and saturates..
3229// https://msdn.microsoft.com/en-us/library/9hahyddy(v=vs.100).aspx
3235
3236// Compute the bitwise AND of packed double-precision (64-bit) floating-point
3237// elements in a and b, and store the results in dst.
3238//
3239// FOR j := 0 to 1
3240// i := j*64
3241// dst[i+63:i] := a[i+63:i] AND b[i+63:i]
3242// ENDFOR
3243//
3244// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_and_pd
3250
3251// Computes the bitwise AND of the 128-bit value in a and the 128-bit value in
3252// b.
3253//
3254// r := a & b
3255//
3256// https://msdn.microsoft.com/en-us/library/vstudio/6d1txsa8(v=vs.100).aspx
3262
3263// Compute the bitwise NOT of packed double-precision (64-bit) floating-point
3264// elements in a and then AND with b, and store the results in dst.
3265//
3266// FOR j := 0 to 1
3267// i := j*64
3268// dst[i+63:i] := ((NOT a[i+63:i]) AND b[i+63:i])
3269// ENDFOR
3270//
3271// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_andnot_pd
3273{
3274 // *NOTE* argument swap
3277}
3278
3279// Computes the bitwise AND of the 128-bit value in b and the bitwise NOT of the
3280// 128-bit value in a.
3281//
3282// r := (~a) & b
3283//
3284// https://msdn.microsoft.com/en-us/library/vstudio/1beaceh8(v=vs.100).aspx
3286{
3288 vbicq_s32(vreinterpretq_s32_m128i(b),
3289 vreinterpretq_s32_m128i(a))); // *NOTE* argument swap
3290}
3291
3292// Computes the average of the 8 unsigned 16-bit integers in a and the 8
3293// unsigned 16-bit integers in b and rounds.
3294//
3295// r0 := (a0 + b0) / 2
3296// r1 := (a1 + b1) / 2
3297// ...
3298// r7 := (a7 + b7) / 2
3299//
3300// https://msdn.microsoft.com/en-us/library/vstudio/y13ca3c8(v=vs.90).aspx
3306
3307// Computes the average of the 16 unsigned 8-bit integers in a and the 16
3308// unsigned 8-bit integers in b and rounds.
3309//
3310// r0 := (a0 + b0) / 2
3311// r1 := (a1 + b1) / 2
3312// ...
3313// r15 := (a15 + b15) / 2
3314//
3315// https://msdn.microsoft.com/en-us/library/vstudio/8zwh554a(v%3dvs.90).aspx
3321
3322// Shift a left by imm8 bytes while shifting in zeros, and store the results in
3323// dst.
3324// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_bslli_si128
3325#define _mm_bslli_si128(a, imm) _mm_slli_si128(a, imm)
3326
3327// Shift a right by imm8 bytes while shifting in zeros, and store the results in
3328// dst.
3329// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_bsrli_si128
3330#define _mm_bsrli_si128(a, imm) _mm_srli_si128(a, imm)
3331
3332// Cast vector of type __m128d to type __m128. This intrinsic is only used for
3333// compilation and does not generate any instructions, thus it has zero latency.
3334// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_castpd_ps
3339
3340// Cast vector of type __m128d to type __m128i. This intrinsic is only used for
3341// compilation and does not generate any instructions, thus it has zero latency.
3342// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_castpd_si128
3347
3348// Cast vector of type __m128 to type __m128d. This intrinsic is only used for
3349// compilation and does not generate any instructions, thus it has zero latency.
3350// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_castps_pd
3355
3356// Applies a type cast to reinterpret four 32-bit floating point values passed
3357// in as a 128-bit parameter as packed 32-bit integers.
3358// https://msdn.microsoft.com/en-us/library/bb514099.aspx
3363
3364// Cast vector of type __m128i to type __m128d. This intrinsic is only used for
3365// compilation and does not generate any instructions, thus it has zero latency.
3366// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_castsi128_pd
3368{
3369#if defined(__aarch64__)
3370 return vreinterpretq_m128d_f64(vreinterpretq_f64_m128i(a));
3371#else
3373#endif
3374}
3375
3376// Applies a type cast to reinterpret four 32-bit integers passed in as a
3377// 128-bit parameter as packed 32-bit floating point values.
3378// https://msdn.microsoft.com/en-us/library/bb514029.aspx
3383
3384// Invalidate and flush the cache line that contains p from all levels of the
3385// cache hierarchy.
3386// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_clflush
3387#if defined(__APPLE__)
3388#include <libkern/OSCacheControl.h>
3389#endif
3390FORCE_INLINE void _mm_clflush(void const *p)
3391{
3392 (void) p;
3393
3394 /* sys_icache_invalidate is supported since macOS 10.5.
3395 * However, it does not work on non-jailbroken iOS devices, although the
3396 * compilation is successful.
3397 */
3398#if defined(__APPLE__)
3399 sys_icache_invalidate((void *) (uintptr_t) p, SSE2NEON_CACHELINE_SIZE);
3400#elif defined(__GNUC__) || defined(__clang__)
3401 uintptr_t ptr = (uintptr_t) p;
3402 __builtin___clear_cache((char *) ptr,
3403 (char *) ptr + SSE2NEON_CACHELINE_SIZE);
3404#else
3405 /* FIXME: MSVC support */
3406#endif
3407}
3408
3409// Compares the 8 signed or unsigned 16-bit integers in a and the 8 signed or
3410// unsigned 16-bit integers in b for equality.
3411// https://msdn.microsoft.com/en-us/library/2ay060te(v=vs.100).aspx
3417
3418// Compare packed 32-bit integers in a and b for equality, and store the results
3419// in dst
3425
3426// Compares the 16 signed or unsigned 8-bit integers in a and the 16 signed or
3427// unsigned 8-bit integers in b for equality.
3428// https://msdn.microsoft.com/en-us/library/windows/desktop/bz5xk21a(v=vs.90).aspx
3434
3435// Compare packed double-precision (64-bit) floating-point elements in a and b
3436// for equality, and store the results in dst.
3437// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpeq_pd
3439{
3440#if defined(__aarch64__)
3442 vceqq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
3443#else
3444 // (a == b) -> (a_lo == b_lo) && (a_hi == b_hi)
3445 uint32x4_t cmp =
3447 uint32x4_t swapped = vrev64q_u32(cmp);
3448 return vreinterpretq_m128d_u32(vandq_u32(cmp, swapped));
3449#endif
3450}
3451
3452// Compare the lower double-precision (64-bit) floating-point elements in a and
3453// b for equality, store the result in the lower element of dst, and copy the
3454// upper element from a to the upper element of dst.
3455// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpeq_sd
3460
3461// Compare packed double-precision (64-bit) floating-point elements in a and b
3462// for greater-than-or-equal, and store the results in dst.
3463// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpge_pd
3465{
3466#if defined(__aarch64__)
3468 vcgeq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
3469#else
3470 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3471 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
3472 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3473 uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
3474 uint64_t d[2];
3475 d[0] = (*(double *) &a0) >= (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
3476 d[1] = (*(double *) &a1) >= (*(double *) &b1) ? ~UINT64_C(0) : UINT64_C(0);
3477
3478 return vreinterpretq_m128d_u64(vld1q_u64(d));
3479#endif
3480}
3481
3482// Compare the lower double-precision (64-bit) floating-point elements in a and
3483// b for greater-than-or-equal, store the result in the lower element of dst,
3484// and copy the upper element from a to the upper element of dst.
3485// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpge_sd
3487{
3488#if defined(__aarch64__)
3489 return _mm_move_sd(a, _mm_cmpge_pd(a, b));
3490#else
3491 // expand "_mm_cmpge_pd()" to reduce unnecessary operations
3492 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3493 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
3494 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3495 uint64_t d[2];
3496 d[0] = (*(double *) &a0) >= (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
3497 d[1] = a1;
3498
3499 return vreinterpretq_m128d_u64(vld1q_u64(d));
3500#endif
3501}
3502
3503// Compares the 8 signed 16-bit integers in a and the 8 signed 16-bit integers
3504// in b for greater than.
3505//
3506// r0 := (a0 > b0) ? 0xffff : 0x0
3507// r1 := (a1 > b1) ? 0xffff : 0x0
3508// ...
3509// r7 := (a7 > b7) ? 0xffff : 0x0
3510//
3511// https://technet.microsoft.com/en-us/library/xd43yfsa(v=vs.100).aspx
3517
3518// Compares the 4 signed 32-bit integers in a and the 4 signed 32-bit integers
3519// in b for greater than.
3520// https://msdn.microsoft.com/en-us/library/vstudio/1s9f2z0y(v=vs.100).aspx
3526
3527// Compares the 16 signed 8-bit integers in a and the 16 signed 8-bit integers
3528// in b for greater than.
3529//
3530// r0 := (a0 > b0) ? 0xff : 0x0
3531// r1 := (a1 > b1) ? 0xff : 0x0
3532// ...
3533// r15 := (a15 > b15) ? 0xff : 0x0
3534//
3535// https://msdn.microsoft.com/zh-tw/library/wf45zt2b(v=vs.100).aspx
3541
3542// Compare packed double-precision (64-bit) floating-point elements in a and b
3543// for greater-than, and store the results in dst.
3544// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpgt_pd
3546{
3547#if defined(__aarch64__)
3549 vcgtq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
3550#else
3551 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3552 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
3553 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3554 uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
3555 uint64_t d[2];
3556 d[0] = (*(double *) &a0) > (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
3557 d[1] = (*(double *) &a1) > (*(double *) &b1) ? ~UINT64_C(0) : UINT64_C(0);
3558
3559 return vreinterpretq_m128d_u64(vld1q_u64(d));
3560#endif
3561}
3562
3563// Compare the lower double-precision (64-bit) floating-point elements in a and
3564// b for greater-than, store the result in the lower element of dst, and copy
3565// the upper element from a to the upper element of dst.
3566// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpgt_sd
3568{
3569#if defined(__aarch64__)
3570 return _mm_move_sd(a, _mm_cmpgt_pd(a, b));
3571#else
3572 // expand "_mm_cmpge_pd()" to reduce unnecessary operations
3573 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3574 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
3575 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3576 uint64_t d[2];
3577 d[0] = (*(double *) &a0) > (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
3578 d[1] = a1;
3579
3580 return vreinterpretq_m128d_u64(vld1q_u64(d));
3581#endif
3582}
3583
3584// Compare packed double-precision (64-bit) floating-point elements in a and b
3585// for less-than-or-equal, and store the results in dst.
3586// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmple_pd
3588{
3589#if defined(__aarch64__)
3591 vcleq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
3592#else
3593 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3594 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
3595 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3596 uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
3597 uint64_t d[2];
3598 d[0] = (*(double *) &a0) <= (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
3599 d[1] = (*(double *) &a1) <= (*(double *) &b1) ? ~UINT64_C(0) : UINT64_C(0);
3600
3601 return vreinterpretq_m128d_u64(vld1q_u64(d));
3602#endif
3603}
3604
3605// Compare the lower double-precision (64-bit) floating-point elements in a and
3606// b for less-than-or-equal, store the result in the lower element of dst, and
3607// copy the upper element from a to the upper element of dst.
3608// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmple_sd
3610{
3611#if defined(__aarch64__)
3612 return _mm_move_sd(a, _mm_cmple_pd(a, b));
3613#else
3614 // expand "_mm_cmpge_pd()" to reduce unnecessary operations
3615 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3616 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
3617 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3618 uint64_t d[2];
3619 d[0] = (*(double *) &a0) <= (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
3620 d[1] = a1;
3621
3622 return vreinterpretq_m128d_u64(vld1q_u64(d));
3623#endif
3624}
3625
3626// Compares the 8 signed 16-bit integers in a and the 8 signed 16-bit integers
3627// in b for less than.
3628//
3629// r0 := (a0 < b0) ? 0xffff : 0x0
3630// r1 := (a1 < b1) ? 0xffff : 0x0
3631// ...
3632// r7 := (a7 < b7) ? 0xffff : 0x0
3633//
3634// https://technet.microsoft.com/en-us/library/t863edb2(v=vs.100).aspx
3640
3641
3642// Compares the 4 signed 32-bit integers in a and the 4 signed 32-bit integers
3643// in b for less than.
3644// https://msdn.microsoft.com/en-us/library/vstudio/4ak0bf5d(v=vs.100).aspx
3650
3651// Compares the 16 signed 8-bit integers in a and the 16 signed 8-bit integers
3652// in b for lesser than.
3653// https://msdn.microsoft.com/en-us/library/windows/desktop/9s46csht(v=vs.90).aspx
3659
3660// Compare packed double-precision (64-bit) floating-point elements in a and b
3661// for less-than, and store the results in dst.
3662// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmplt_pd
3664{
3665#if defined(__aarch64__)
3667 vcltq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
3668#else
3669 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3670 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
3671 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3672 uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
3673 uint64_t d[2];
3674 d[0] = (*(double *) &a0) < (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
3675 d[1] = (*(double *) &a1) < (*(double *) &b1) ? ~UINT64_C(0) : UINT64_C(0);
3676
3677 return vreinterpretq_m128d_u64(vld1q_u64(d));
3678#endif
3679}
3680
3681// Compare the lower double-precision (64-bit) floating-point elements in a and
3682// b for less-than, store the result in the lower element of dst, and copy the
3683// upper element from a to the upper element of dst.
3684// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmplt_sd
3686{
3687#if defined(__aarch64__)
3688 return _mm_move_sd(a, _mm_cmplt_pd(a, b));
3689#else
3690 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3691 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
3692 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3693 uint64_t d[2];
3694 d[0] = (*(double *) &a0) < (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
3695 d[1] = a1;
3696
3697 return vreinterpretq_m128d_u64(vld1q_u64(d));
3698#endif
3699}
3700
3701// Compare packed double-precision (64-bit) floating-point elements in a and b
3702// for not-equal, and store the results in dst.
3703// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpneq_pd
3705{
3706#if defined(__aarch64__)
3707 return vreinterpretq_m128d_s32(vmvnq_s32(vreinterpretq_s32_u64(
3708 vceqq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)))));
3709#else
3710 // (a == b) -> (a_lo == b_lo) && (a_hi == b_hi)
3711 uint32x4_t cmp =
3713 uint32x4_t swapped = vrev64q_u32(cmp);
3714 return vreinterpretq_m128d_u32(vmvnq_u32(vandq_u32(cmp, swapped)));
3715#endif
3716}
3717
3718// Compare the lower double-precision (64-bit) floating-point elements in a and
3719// b for not-equal, store the result in the lower element of dst, and copy the
3720// upper element from a to the upper element of dst.
3721// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpneq_sd
3726
3727// Compare packed double-precision (64-bit) floating-point elements in a and b
3728// for not-greater-than-or-equal, and store the results in dst.
3729// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpnge_pd
3731{
3732#if defined(__aarch64__)
3733 return vreinterpretq_m128d_u64(veorq_u64(
3734 vcgeq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)),
3735 vdupq_n_u64(UINT64_MAX)));
3736#else
3737 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3738 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
3739 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3740 uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
3741 uint64_t d[2];
3742 d[0] =
3743 !((*(double *) &a0) >= (*(double *) &b0)) ? ~UINT64_C(0) : UINT64_C(0);
3744 d[1] =
3745 !((*(double *) &a1) >= (*(double *) &b1)) ? ~UINT64_C(0) : UINT64_C(0);
3746
3747 return vreinterpretq_m128d_u64(vld1q_u64(d));
3748#endif
3749}
3750
3751// Compare the lower double-precision (64-bit) floating-point elements in a and
3752// b for not-greater-than-or-equal, store the result in the lower element of
3753// dst, and copy the upper element from a to the upper element of dst.
3754// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpnge_sd
3759
3760// Compare packed double-precision (64-bit) floating-point elements in a and b
3761// for not-greater-than, and store the results in dst.
3762// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_cmpngt_pd
3764{
3765#if defined(__aarch64__)
3766 return vreinterpretq_m128d_u64(veorq_u64(
3767 vcgtq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)),
3768 vdupq_n_u64(UINT64_MAX)));
3769#else
3770 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3771 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
3772 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3773 uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
3774 uint64_t d[2];
3775 d[0] =
3776 !((*(double *) &a0) > (*(double *) &b0)) ? ~UINT64_C(0) : UINT64_C(0);
3777 d[1] =
3778 !((*(double *) &a1) > (*(double *) &b1)) ? ~UINT64_C(0) : UINT64_C(0);
3779
3780 return vreinterpretq_m128d_u64(vld1q_u64(d));
3781#endif
3782}
3783
3784// Compare the lower double-precision (64-bit) floating-point elements in a and
3785// b for not-greater-than, store the result in the lower element of dst, and
3786// copy the upper element from a to the upper element of dst.
3787// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpngt_sd
3792
3793// Compare packed double-precision (64-bit) floating-point elements in a and b
3794// for not-less-than-or-equal, and store the results in dst.
3795// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpnle_pd
3797{
3798#if defined(__aarch64__)
3799 return vreinterpretq_m128d_u64(veorq_u64(
3800 vcleq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)),
3801 vdupq_n_u64(UINT64_MAX)));
3802#else
3803 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3804 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
3805 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3806 uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
3807 uint64_t d[2];
3808 d[0] =
3809 !((*(double *) &a0) <= (*(double *) &b0)) ? ~UINT64_C(0) : UINT64_C(0);
3810 d[1] =
3811 !((*(double *) &a1) <= (*(double *) &b1)) ? ~UINT64_C(0) : UINT64_C(0);
3812
3813 return vreinterpretq_m128d_u64(vld1q_u64(d));
3814#endif
3815}
3816
3817// Compare the lower double-precision (64-bit) floating-point elements in a and
3818// b for not-less-than-or-equal, store the result in the lower element of dst,
3819// and copy the upper element from a to the upper element of dst.
3820// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpnle_sd
3825
3826// Compare packed double-precision (64-bit) floating-point elements in a and b
3827// for not-less-than, and store the results in dst.
3828// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpnlt_pd
3830{
3831#if defined(__aarch64__)
3832 return vreinterpretq_m128d_u64(veorq_u64(
3833 vcltq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)),
3834 vdupq_n_u64(UINT64_MAX)));
3835#else
3836 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3837 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
3838 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3839 uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
3840 uint64_t d[2];
3841 d[0] =
3842 !((*(double *) &a0) < (*(double *) &b0)) ? ~UINT64_C(0) : UINT64_C(0);
3843 d[1] =
3844 !((*(double *) &a1) < (*(double *) &b1)) ? ~UINT64_C(0) : UINT64_C(0);
3845
3846 return vreinterpretq_m128d_u64(vld1q_u64(d));
3847#endif
3848}
3849
3850// Compare the lower double-precision (64-bit) floating-point elements in a and
3851// b for not-less-than, store the result in the lower element of dst, and copy
3852// the upper element from a to the upper element of dst.
3853// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpnlt_sd
3858
3859// Compare packed double-precision (64-bit) floating-point elements in a and b
3860// to see if neither is NaN, and store the results in dst.
3861// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpord_pd
3863{
3864#if defined(__aarch64__)
3865 // Excluding NaNs, any two floating point numbers can be compared.
3866 uint64x2_t not_nan_a =
3867 vceqq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(a));
3868 uint64x2_t not_nan_b =
3869 vceqq_f64(vreinterpretq_f64_m128d(b), vreinterpretq_f64_m128d(b));
3870 return vreinterpretq_m128d_u64(vandq_u64(not_nan_a, not_nan_b));
3871#else
3872 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3873 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
3874 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3875 uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
3876 uint64_t d[2];
3877 d[0] = ((*(double *) &a0) == (*(double *) &a0) &&
3878 (*(double *) &b0) == (*(double *) &b0))
3879 ? ~UINT64_C(0)
3880 : UINT64_C(0);
3881 d[1] = ((*(double *) &a1) == (*(double *) &a1) &&
3882 (*(double *) &b1) == (*(double *) &b1))
3883 ? ~UINT64_C(0)
3884 : UINT64_C(0);
3885
3886 return vreinterpretq_m128d_u64(vld1q_u64(d));
3887#endif
3888}
3889
3890// Compare the lower double-precision (64-bit) floating-point elements in a and
3891// b to see if neither is NaN, store the result in the lower element of dst, and
3892// copy the upper element from a to the upper element of dst.
3893// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpord_sd
3895{
3896#if defined(__aarch64__)
3897 return _mm_move_sd(a, _mm_cmpord_pd(a, b));
3898#else
3899 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3900 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3901 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
3902 uint64_t d[2];
3903 d[0] = ((*(double *) &a0) == (*(double *) &a0) &&
3904 (*(double *) &b0) == (*(double *) &b0))
3905 ? ~UINT64_C(0)
3906 : UINT64_C(0);
3907 d[1] = a1;
3908
3909 return vreinterpretq_m128d_u64(vld1q_u64(d));
3910#endif
3911}
3912
3913// Compare packed double-precision (64-bit) floating-point elements in a and b
3914// to see if either is NaN, and store the results in dst.
3915// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpunord_pd
3917{
3918#if defined(__aarch64__)
3919 // Two NaNs are not equal in comparison operation.
3920 uint64x2_t not_nan_a =
3921 vceqq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(a));
3922 uint64x2_t not_nan_b =
3923 vceqq_f64(vreinterpretq_f64_m128d(b), vreinterpretq_f64_m128d(b));
3925 vmvnq_s32(vreinterpretq_s32_u64(vandq_u64(not_nan_a, not_nan_b))));
3926#else
3927 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3928 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
3929 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3930 uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
3931 uint64_t d[2];
3932 d[0] = ((*(double *) &a0) == (*(double *) &a0) &&
3933 (*(double *) &b0) == (*(double *) &b0))
3934 ? UINT64_C(0)
3935 : ~UINT64_C(0);
3936 d[1] = ((*(double *) &a1) == (*(double *) &a1) &&
3937 (*(double *) &b1) == (*(double *) &b1))
3938 ? UINT64_C(0)
3939 : ~UINT64_C(0);
3940
3941 return vreinterpretq_m128d_u64(vld1q_u64(d));
3942#endif
3943}
3944
3945// Compare the lower double-precision (64-bit) floating-point elements in a and
3946// b to see if either is NaN, store the result in the lower element of dst, and
3947// copy the upper element from a to the upper element of dst.
3948// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpunord_sd
3950{
3951#if defined(__aarch64__)
3952 return _mm_move_sd(a, _mm_cmpunord_pd(a, b));
3953#else
3954 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3955 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3956 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
3957 uint64_t d[2];
3958 d[0] = ((*(double *) &a0) == (*(double *) &a0) &&
3959 (*(double *) &b0) == (*(double *) &b0))
3960 ? UINT64_C(0)
3961 : ~UINT64_C(0);
3962 d[1] = a1;
3963
3964 return vreinterpretq_m128d_u64(vld1q_u64(d));
3965#endif
3966}
3967
3968// Compare the lower double-precision (64-bit) floating-point element in a and b
3969// for greater-than-or-equal, and return the boolean result (0 or 1).
3970// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_comige_sd
3972{
3973#if defined(__aarch64__)
3974 return vgetq_lane_u64(vcgeq_f64(a, b), 0) & 0x1;
3975#else
3976 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3977 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3978
3979 return (*(double *) &a0 >= *(double *) &b0);
3980#endif
3981}
3982
3983// Compare the lower double-precision (64-bit) floating-point element in a and b
3984// for greater-than, and return the boolean result (0 or 1).
3985// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_comigt_sd
3987{
3988#if defined(__aarch64__)
3989 return vgetq_lane_u64(vcgtq_f64(a, b), 0) & 0x1;
3990#else
3991 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
3992 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
3993
3994 return (*(double *) &a0 > *(double *) &b0);
3995#endif
3996}
3997
3998// Compare the lower double-precision (64-bit) floating-point element in a and b
3999// for less-than-or-equal, and return the boolean result (0 or 1).
4000// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_comile_sd
4002{
4003#if defined(__aarch64__)
4004 return vgetq_lane_u64(vcleq_f64(a, b), 0) & 0x1;
4005#else
4006 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
4007 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
4008
4009 return (*(double *) &a0 <= *(double *) &b0);
4010#endif
4011}
4012
4013// Compare the lower double-precision (64-bit) floating-point element in a and b
4014// for less-than, and return the boolean result (0 or 1).
4015// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_comilt_sd
4017{
4018#if defined(__aarch64__)
4019 return vgetq_lane_u64(vcltq_f64(a, b), 0) & 0x1;
4020#else
4021 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
4022 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
4023
4024 return (*(double *) &a0 < *(double *) &b0);
4025#endif
4026}
4027
4028// Compare the lower double-precision (64-bit) floating-point element in a and b
4029// for equality, and return the boolean result (0 or 1).
4030// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_comieq_sd
4032{
4033#if defined(__aarch64__)
4034 return vgetq_lane_u64(vceqq_f64(a, b), 0) & 0x1;
4035#else
4036 uint32x4_t a_not_nan =
4038 uint32x4_t b_not_nan =
4040 uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan);
4041 uint32x4_t a_eq_b =
4043 uint64x2_t and_results = vandq_u64(vreinterpretq_u64_u32(a_and_b_not_nan),
4044 vreinterpretq_u64_u32(a_eq_b));
4045 return vgetq_lane_u64(and_results, 0) & 0x1;
4046#endif
4047}
4048
4049// Compare the lower double-precision (64-bit) floating-point element in a and b
4050// for not-equal, and return the boolean result (0 or 1).
4051// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_comineq_sd
4053{
4054 return !_mm_comieq_sd(a, b);
4055}
4056
4057// Convert packed signed 32-bit integers in a to packed double-precision
4058// (64-bit) floating-point elements, and store the results in dst.
4059//
4060// FOR j := 0 to 1
4061// i := j*32
4062// m := j*64
4063// dst[m+63:m] := Convert_Int32_To_FP64(a[i+31:i])
4064// ENDFOR
4065//
4066// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtepi32_pd
4068{
4069#if defined(__aarch64__)
4070 return vreinterpretq_m128d_f64(
4071 vcvtq_f64_s64(vmovl_s32(vget_low_s32(vreinterpretq_s32_m128i(a)))));
4072#else
4073 double a0 = (double) vgetq_lane_s32(vreinterpretq_s32_m128i(a), 0);
4074 double a1 = (double) vgetq_lane_s32(vreinterpretq_s32_m128i(a), 1);
4075 return _mm_set_pd(a1, a0);
4076#endif
4077}
4078
4079// Converts the four signed 32-bit integer values of a to single-precision,
4080// floating-point values
4081// https://msdn.microsoft.com/en-us/library/vstudio/36bwxcx5(v=vs.100).aspx
4086
4087// Convert packed double-precision (64-bit) floating-point elements in a to
4088// packed 32-bit integers, and store the results in dst.
4089//
4090// FOR j := 0 to 1
4091// i := 32*j
4092// k := 64*j
4093// dst[i+31:i] := Convert_FP64_To_Int32(a[k+63:k])
4094// ENDFOR
4095//
4096// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtpd_epi32
4098{
4099// vrnd32xq_f64 not supported on clang
4100#if defined(__ARM_FEATURE_FRINT) && !defined(__clang__)
4101 float64x2_t rounded = vrnd32xq_f64(vreinterpretq_f64_m128d(a));
4102 int64x2_t integers = vcvtq_s64_f64(rounded);
4104 vcombine_s32(vmovn_s64(integers), vdup_n_s32(0)));
4105#else
4107 double d0 = ((double *) &rnd)[0];
4108 double d1 = ((double *) &rnd)[1];
4109 return _mm_set_epi32(0, 0, (int32_t) d1, (int32_t) d0);
4110#endif
4111}
4112
4113// Convert packed double-precision (64-bit) floating-point elements in a to
4114// packed 32-bit integers, and store the results in dst.
4115//
4116// FOR j := 0 to 1
4117// i := 32*j
4118// k := 64*j
4119// dst[i+31:i] := Convert_FP64_To_Int32(a[k+63:k])
4120// ENDFOR
4121//
4122// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtpd_pi32
4124{
4126 double d0 = ((double *) &rnd)[0];
4127 double d1 = ((double *) &rnd)[1];
4128 int32_t ALIGN_STRUCT(16) data[2] = {(int32_t) d0, (int32_t) d1};
4129 return vreinterpret_m64_s32(vld1_s32(data));
4130}
4131
4132// Convert packed double-precision (64-bit) floating-point elements in a to
4133// packed single-precision (32-bit) floating-point elements, and store the
4134// results in dst.
4135//
4136// FOR j := 0 to 1
4137// i := 32*j
4138// k := 64*j
4139// dst[i+31:i] := Convert_FP64_To_FP32(a[k+64:k])
4140// ENDFOR
4141// dst[127:64] := 0
4142//
4143// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtpd_ps
4145{
4146#if defined(__aarch64__)
4147 float32x2_t tmp = vcvt_f32_f64(vreinterpretq_f64_m128d(a));
4148 return vreinterpretq_m128_f32(vcombine_f32(tmp, vdup_n_f32(0)));
4149#else
4150 float a0 = (float) ((double *) &a)[0];
4151 float a1 = (float) ((double *) &a)[1];
4152 return _mm_set_ps(0, 0, a1, a0);
4153#endif
4154}
4155
4156// Convert packed signed 32-bit integers in a to packed double-precision
4157// (64-bit) floating-point elements, and store the results in dst.
4158//
4159// FOR j := 0 to 1
4160// i := j*32
4161// m := j*64
4162// dst[m+63:m] := Convert_Int32_To_FP64(a[i+31:i])
4163// ENDFOR
4164//
4165// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtpi32_pd
4167{
4168#if defined(__aarch64__)
4169 return vreinterpretq_m128d_f64(
4170 vcvtq_f64_s64(vmovl_s32(vreinterpret_s32_m64(a))));
4171#else
4172 double a0 = (double) vget_lane_s32(vreinterpret_s32_m64(a), 0);
4173 double a1 = (double) vget_lane_s32(vreinterpret_s32_m64(a), 1);
4174 return _mm_set_pd(a1, a0);
4175#endif
4176}
4177
4178// Converts the four single-precision, floating-point values of a to signed
4179// 32-bit integer values.
4180//
4181// r0 := (int) a0
4182// r1 := (int) a1
4183// r2 := (int) a2
4184// r3 := (int) a3
4185//
4186// https://msdn.microsoft.com/en-us/library/vstudio/xdc42k5e(v=vs.100).aspx
4187// *NOTE*. The default rounding mode on SSE is 'round to even', which ARMv7-A
4188// does not support! It is supported on ARMv8-A however.
4190{
4191#if defined(__ARM_FEATURE_FRINT)
4192 return vreinterpretq_m128i_s32(vcvtq_s32_f32(vrnd32xq_f32(a)));
4193#elif defined(__aarch64__) || defined(__ARM_FEATURE_DIRECTED_ROUNDING)
4194 switch (_MM_GET_ROUNDING_MODE()) {
4195 case _MM_ROUND_NEAREST:
4196 return vreinterpretq_m128i_s32(vcvtnq_s32_f32(a));
4197 case _MM_ROUND_DOWN:
4198 return vreinterpretq_m128i_s32(vcvtmq_s32_f32(a));
4199 case _MM_ROUND_UP:
4200 return vreinterpretq_m128i_s32(vcvtpq_s32_f32(a));
4201 default: // _MM_ROUND_TOWARD_ZERO
4202 return vreinterpretq_m128i_s32(vcvtq_s32_f32(a));
4203 }
4204#else
4205 float *f = (float *) &a;
4206 switch (_MM_GET_ROUNDING_MODE()) {
4207 case _MM_ROUND_NEAREST: {
4208 uint32x4_t signmask = vdupq_n_u32(0x80000000);
4209 float32x4_t half = vbslq_f32(signmask, vreinterpretq_f32_m128(a),
4210 vdupq_n_f32(0.5f)); /* +/- 0.5 */
4211 int32x4_t r_normal = vcvtq_s32_f32(vaddq_f32(
4212 vreinterpretq_f32_m128(a), half)); /* round to integer: [a + 0.5]*/
4213 int32x4_t r_trunc = vcvtq_s32_f32(
4214 vreinterpretq_f32_m128(a)); /* truncate to integer: [a] */
4215 int32x4_t plusone = vreinterpretq_s32_u32(vshrq_n_u32(
4216 vreinterpretq_u32_s32(vnegq_s32(r_trunc)), 31)); /* 1 or 0 */
4217 int32x4_t r_even = vbicq_s32(vaddq_s32(r_trunc, plusone),
4218 vdupq_n_s32(1)); /* ([a] + {0,1}) & ~1 */
4219 float32x4_t delta = vsubq_f32(
4221 vcvtq_f32_s32(r_trunc)); /* compute delta: delta = (a - [a]) */
4222 uint32x4_t is_delta_half =
4223 vceqq_f32(delta, half); /* delta == +/- 0.5 */
4225 vbslq_s32(is_delta_half, r_even, r_normal));
4226 }
4227 case _MM_ROUND_DOWN:
4228 return _mm_set_epi32(floorf(f[3]), floorf(f[2]), floorf(f[1]),
4229 floorf(f[0]));
4230 case _MM_ROUND_UP:
4231 return _mm_set_epi32(ceilf(f[3]), ceilf(f[2]), ceilf(f[1]),
4232 ceilf(f[0]));
4233 default: // _MM_ROUND_TOWARD_ZERO
4234 return _mm_set_epi32((int32_t) f[3], (int32_t) f[2], (int32_t) f[1],
4235 (int32_t) f[0]);
4236 }
4237#endif
4238}
4239
4240// Convert packed single-precision (32-bit) floating-point elements in a to
4241// packed double-precision (64-bit) floating-point elements, and store the
4242// results in dst.
4243//
4244// FOR j := 0 to 1
4245// i := 64*j
4246// k := 32*j
4247// dst[i+63:i] := Convert_FP32_To_FP64(a[k+31:k])
4248// ENDFOR
4249//
4250// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtps_pd
4252{
4253#if defined(__aarch64__)
4254 return vreinterpretq_m128d_f64(
4255 vcvt_f64_f32(vget_low_f32(vreinterpretq_f32_m128(a))));
4256#else
4257 double a0 = (double) vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
4258 double a1 = (double) vgetq_lane_f32(vreinterpretq_f32_m128(a), 1);
4259 return _mm_set_pd(a1, a0);
4260#endif
4261}
4262
4263// Copy the lower double-precision (64-bit) floating-point element of a to dst.
4264//
4265// dst[63:0] := a[63:0]
4266//
4267// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsd_f64
4269{
4270#if defined(__aarch64__)
4271 return (double) vgetq_lane_f64(vreinterpretq_f64_m128d(a), 0);
4272#else
4273 return ((double *) &a)[0];
4274#endif
4275}
4276
4277// Convert the lower double-precision (64-bit) floating-point element in a to a
4278// 32-bit integer, and store the result in dst.
4279//
4280// dst[31:0] := Convert_FP64_To_Int32(a[63:0])
4281//
4282// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsd_si32
4284{
4285#if defined(__aarch64__)
4286 return (int32_t) vgetq_lane_f64(vrndiq_f64(vreinterpretq_f64_m128d(a)), 0);
4287#else
4289 double ret = ((double *) &rnd)[0];
4290 return (int32_t) ret;
4291#endif
4292}
4293
4294// Convert the lower double-precision (64-bit) floating-point element in a to a
4295// 64-bit integer, and store the result in dst.
4296//
4297// dst[63:0] := Convert_FP64_To_Int64(a[63:0])
4298//
4299// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsd_si64
4301{
4302#if defined(__aarch64__)
4303 return (int64_t) vgetq_lane_f64(vrndiq_f64(vreinterpretq_f64_m128d(a)), 0);
4304#else
4306 double ret = ((double *) &rnd)[0];
4307 return (int64_t) ret;
4308#endif
4309}
4310
4311// Convert the lower double-precision (64-bit) floating-point element in a to a
4312// 64-bit integer, and store the result in dst.
4313//
4314// dst[63:0] := Convert_FP64_To_Int64(a[63:0])
4315//
4316// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsd_si64x
4317#define _mm_cvtsd_si64x _mm_cvtsd_si64
4318
4319// Convert the lower double-precision (64-bit) floating-point element in b to a
4320// single-precision (32-bit) floating-point element, store the result in the
4321// lower element of dst, and copy the upper 3 packed elements from a to the
4322// upper elements of dst.
4323// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsd_ss
4325{
4326#if defined(__aarch64__)
4327 return vreinterpretq_m128_f32(vsetq_lane_f32(
4328 vget_lane_f32(vcvt_f32_f64(vreinterpretq_f64_m128d(b)), 0),
4329 vreinterpretq_f32_m128(a), 0));
4330#else
4331 return vreinterpretq_m128_f32(vsetq_lane_f32((float) ((double *) &b)[0],
4332 vreinterpretq_f32_m128(a), 0));
4333#endif
4334}
4335
4336// Copy the lower 32-bit integer in a to dst.
4337//
4338// dst[31:0] := a[31:0]
4339//
4340// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi128_si32
4342{
4343 return vgetq_lane_s32(vreinterpretq_s32_m128i(a), 0);
4344}
4345
4346// Copy the lower 64-bit integer in a to dst.
4347//
4348// dst[63:0] := a[63:0]
4349//
4350// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi128_si64
4352{
4353 return vgetq_lane_s64(vreinterpretq_s64_m128i(a), 0);
4354}
4355
4356// Copy the lower 64-bit integer in a to dst.
4357// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi128_si64x
4358#define _mm_cvtsi128_si64x(a) _mm_cvtsi128_si64(a)
4359
4360// Convert the signed 32-bit integer b to a double-precision (64-bit)
4361// floating-point element, store the result in the lower element of dst, and
4362// copy the upper element from a to the upper element of dst.
4363// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi32_sd
4365{
4366#if defined(__aarch64__)
4367 return vreinterpretq_m128d_f64(
4368 vsetq_lane_f64((double) b, vreinterpretq_f64_m128d(a), 0));
4369#else
4370 double bf = (double) b;
4372 vsetq_lane_s64(*(int64_t *) &bf, vreinterpretq_s64_m128d(a), 0));
4373#endif
4374}
4375
4376// Copy the lower 64-bit integer in a to dst.
4377//
4378// dst[63:0] := a[63:0]
4379//
4380// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi128_si64x
4381#define _mm_cvtsi128_si64x(a) _mm_cvtsi128_si64(a)
4382
4383// Moves 32-bit integer a to the least significant 32 bits of an __m128 object,
4384// zero extending the upper bits.
4385//
4386// r0 := a
4387// r1 := 0x0
4388// r2 := 0x0
4389// r3 := 0x0
4390//
4391// https://msdn.microsoft.com/en-us/library/ct3539ha%28v=vs.90%29.aspx
4393{
4394 return vreinterpretq_m128i_s32(vsetq_lane_s32(a, vdupq_n_s32(0), 0));
4395}
4396
4397// Convert the signed 64-bit integer b to a double-precision (64-bit)
4398// floating-point element, store the result in the lower element of dst, and
4399// copy the upper element from a to the upper element of dst.
4400// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi64_sd
4402{
4403#if defined(__aarch64__)
4404 return vreinterpretq_m128d_f64(
4405 vsetq_lane_f64((double) b, vreinterpretq_f64_m128d(a), 0));
4406#else
4407 double bf = (double) b;
4409 vsetq_lane_s64(*(int64_t *) &bf, vreinterpretq_s64_m128d(a), 0));
4410#endif
4411}
4412
4413// Moves 64-bit integer a to the least significant 64 bits of an __m128 object,
4414// zero extending the upper bits.
4415//
4416// r0 := a
4417// r1 := 0x0
4419{
4420 return vreinterpretq_m128i_s64(vsetq_lane_s64(a, vdupq_n_s64(0), 0));
4421}
4422
4423// Copy 64-bit integer a to the lower element of dst, and zero the upper
4424// element.
4425// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi64x_si128
4426#define _mm_cvtsi64x_si128(a) _mm_cvtsi64_si128(a)
4427
4428// Convert the signed 64-bit integer b to a double-precision (64-bit)
4429// floating-point element, store the result in the lower element of dst, and
4430// copy the upper element from a to the upper element of dst.
4431// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi64x_sd
4432#define _mm_cvtsi64x_sd(a, b) _mm_cvtsi64_sd(a, b)
4433
4434// Convert the lower single-precision (32-bit) floating-point element in b to a
4435// double-precision (64-bit) floating-point element, store the result in the
4436// lower element of dst, and copy the upper element from a to the upper element
4437// of dst.
4438//
4439// dst[63:0] := Convert_FP32_To_FP64(b[31:0])
4440// dst[127:64] := a[127:64]
4441//
4442// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtss_sd
4444{
4445 double d = (double) vgetq_lane_f32(vreinterpretq_f32_m128(b), 0);
4446#if defined(__aarch64__)
4447 return vreinterpretq_m128d_f64(
4448 vsetq_lane_f64(d, vreinterpretq_f64_m128d(a), 0));
4449#else
4451 vsetq_lane_s64(*(int64_t *) &d, vreinterpretq_s64_m128d(a), 0));
4452#endif
4453}
4454
4455// Convert packed double-precision (64-bit) floating-point elements in a to
4456// packed 32-bit integers with truncation, and store the results in dst.
4457// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvttpd_epi32
4459{
4460 double a0 = ((double *) &a)[0];
4461 double a1 = ((double *) &a)[1];
4462 return _mm_set_epi32(0, 0, (int32_t) a1, (int32_t) a0);
4463}
4464
4465// Convert packed double-precision (64-bit) floating-point elements in a to
4466// packed 32-bit integers with truncation, and store the results in dst.
4467// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvttpd_pi32
4469{
4470 double a0 = ((double *) &a)[0];
4471 double a1 = ((double *) &a)[1];
4472 int32_t ALIGN_STRUCT(16) data[2] = {(int32_t) a0, (int32_t) a1};
4473 return vreinterpret_m64_s32(vld1_s32(data));
4474}
4475
4476// Converts the four single-precision, floating-point values of a to signed
4477// 32-bit integer values using truncate.
4478// https://msdn.microsoft.com/en-us/library/vstudio/1h005y6x(v=vs.100).aspx
4483
4484// Convert the lower double-precision (64-bit) floating-point element in a to a
4485// 32-bit integer with truncation, and store the result in dst.
4486//
4487// dst[63:0] := Convert_FP64_To_Int32_Truncate(a[63:0])
4488//
4489// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvttsd_si32
4491{
4492 double ret = *((double *) &a);
4493 return (int32_t) ret;
4494}
4495
4496// Convert the lower double-precision (64-bit) floating-point element in a to a
4497// 64-bit integer with truncation, and store the result in dst.
4498//
4499// dst[63:0] := Convert_FP64_To_Int64_Truncate(a[63:0])
4500//
4501// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvttsd_si64
4503{
4504#if defined(__aarch64__)
4505 return vgetq_lane_s64(vcvtq_s64_f64(vreinterpretq_f64_m128d(a)), 0);
4506#else
4507 double ret = *((double *) &a);
4508 return (int64_t) ret;
4509#endif
4510}
4511
4512// Convert the lower double-precision (64-bit) floating-point element in a to a
4513// 64-bit integer with truncation, and store the result in dst.
4514//
4515// dst[63:0] := Convert_FP64_To_Int64_Truncate(a[63:0])
4516//
4517// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvttsd_si64x
4518#define _mm_cvttsd_si64x(a) _mm_cvttsd_si64(a)
4519
4520// Divide packed double-precision (64-bit) floating-point elements in a by
4521// packed elements in b, and store the results in dst.
4522//
4523// FOR j := 0 to 1
4524// i := 64*j
4525// dst[i+63:i] := a[i+63:i] / b[i+63:i]
4526// ENDFOR
4527//
4528// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_div_pd
4530{
4531#if defined(__aarch64__)
4532 return vreinterpretq_m128d_f64(
4533 vdivq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
4534#else
4535 double *da = (double *) &a;
4536 double *db = (double *) &b;
4537 double c[2];
4538 c[0] = da[0] / db[0];
4539 c[1] = da[1] / db[1];
4540 return vld1q_f32((float32_t *) c);
4541#endif
4542}
4543
4544// Divide the lower double-precision (64-bit) floating-point element in a by the
4545// lower double-precision (64-bit) floating-point element in b, store the result
4546// in the lower element of dst, and copy the upper element from a to the upper
4547// element of dst.
4548// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_div_sd
4550{
4551#if defined(__aarch64__)
4552 float64x2_t tmp =
4553 vdivq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b));
4554 return vreinterpretq_m128d_f64(
4555 vsetq_lane_f64(vgetq_lane_f64(vreinterpretq_f64_m128d(a), 1), tmp, 1));
4556#else
4557 return _mm_move_sd(a, _mm_div_pd(a, b));
4558#endif
4559}
4560
4561// Extracts the selected signed or unsigned 16-bit integer from a and zero
4562// extends.
4563// https://msdn.microsoft.com/en-us/library/6dceta0c(v=vs.100).aspx
4564// FORCE_INLINE int _mm_extract_epi16(__m128i a, __constrange(0,8) int imm)
4565#define _mm_extract_epi16(a, imm) \
4566 vgetq_lane_u16(vreinterpretq_u16_m128i(a), (imm))
4567
4568// Inserts the least significant 16 bits of b into the selected 16-bit integer
4569// of a.
4570// https://msdn.microsoft.com/en-us/library/kaze8hz1%28v=vs.100%29.aspx
4571// FORCE_INLINE __m128i _mm_insert_epi16(__m128i a, int b,
4572// __constrange(0,8) int imm)
4573#define _mm_insert_epi16(a, b, imm) \
4574 __extension__({ \
4575 vreinterpretq_m128i_s16( \
4576 vsetq_lane_s16((b), vreinterpretq_s16_m128i(a), (imm))); \
4577 })
4578
4579// Loads two double-precision from 16-byte aligned memory, floating-point
4580// values.
4581//
4582// dst[127:0] := MEM[mem_addr+127:mem_addr]
4583//
4584// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_load_pd
4586{
4587#if defined(__aarch64__)
4588 return vreinterpretq_m128d_f64(vld1q_f64(p));
4589#else
4590 const float *fp = (const float *) p;
4591 float ALIGN_STRUCT(16) data[4] = {fp[0], fp[1], fp[2], fp[3]};
4592 return vreinterpretq_m128d_f32(vld1q_f32(data));
4593#endif
4594}
4595
4596// Load a double-precision (64-bit) floating-point element from memory into both
4597// elements of dst.
4598//
4599// dst[63:0] := MEM[mem_addr+63:mem_addr]
4600// dst[127:64] := MEM[mem_addr+63:mem_addr]
4601//
4602// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_load_pd1
4603#define _mm_load_pd1 _mm_load1_pd
4604
4605// Load a double-precision (64-bit) floating-point element from memory into the
4606// lower of dst, and zero the upper element. mem_addr does not need to be
4607// aligned on any particular boundary.
4608//
4609// dst[63:0] := MEM[mem_addr+63:mem_addr]
4610// dst[127:64] := 0
4611//
4612// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_load_sd
4614{
4615#if defined(__aarch64__)
4616 return vreinterpretq_m128d_f64(vsetq_lane_f64(*p, vdupq_n_f64(0), 0));
4617#else
4618 const float *fp = (const float *) p;
4619 float ALIGN_STRUCT(16) data[4] = {fp[0], fp[1], 0, 0};
4620 return vreinterpretq_m128d_f32(vld1q_f32(data));
4621#endif
4622}
4623
4624// Loads 128-bit value. :
4625// https://msdn.microsoft.com/en-us/library/atzzad1h(v=vs.80).aspx
4627{
4628 return vreinterpretq_m128i_s32(vld1q_s32((const int32_t *) p));
4629}
4630
4631// Load a double-precision (64-bit) floating-point element from memory into both
4632// elements of dst.
4633//
4634// dst[63:0] := MEM[mem_addr+63:mem_addr]
4635// dst[127:64] := MEM[mem_addr+63:mem_addr]
4636//
4637// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_load1_pd
4639{
4640#if defined(__aarch64__)
4641 return vreinterpretq_m128d_f64(vld1q_dup_f64(p));
4642#else
4643 return vreinterpretq_m128d_s64(vdupq_n_s64(*(const int64_t *) p));
4644#endif
4645}
4646
4647// Load a double-precision (64-bit) floating-point element from memory into the
4648// upper element of dst, and copy the lower element from a to dst. mem_addr does
4649// not need to be aligned on any particular boundary.
4650//
4651// dst[63:0] := a[63:0]
4652// dst[127:64] := MEM[mem_addr+63:mem_addr]
4653//
4654// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_loadh_pd
4656{
4657#if defined(__aarch64__)
4658 return vreinterpretq_m128d_f64(
4659 vcombine_f64(vget_low_f64(vreinterpretq_f64_m128d(a)), vld1_f64(p)));
4660#else
4661 return vreinterpretq_m128d_f32(vcombine_f32(
4662 vget_low_f32(vreinterpretq_f32_m128d(a)), vld1_f32((const float *) p)));
4663#endif
4664}
4665
4666// Load 64-bit integer from memory into the first element of dst.
4667// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_loadl_epi64
4669{
4670 /* Load the lower 64 bits of the value pointed to by p into the
4671 * lower 64 bits of the result, zeroing the upper 64 bits of the result.
4672 */
4674 vcombine_s32(vld1_s32((int32_t const *) p), vcreate_s32(0)));
4675}
4676
4677// Load a double-precision (64-bit) floating-point element from memory into the
4678// lower element of dst, and copy the upper element from a to dst. mem_addr does
4679// not need to be aligned on any particular boundary.
4680//
4681// dst[63:0] := MEM[mem_addr+63:mem_addr]
4682// dst[127:64] := a[127:64]
4683//
4684// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_loadl_pd
4686{
4687#if defined(__aarch64__)
4688 return vreinterpretq_m128d_f64(
4689 vcombine_f64(vld1_f64(p), vget_high_f64(vreinterpretq_f64_m128d(a))));
4690#else
4692 vcombine_f32(vld1_f32((const float *) p),
4693 vget_high_f32(vreinterpretq_f32_m128d(a))));
4694#endif
4695}
4696
4697// Load 2 double-precision (64-bit) floating-point elements from memory into dst
4698// in reverse order. mem_addr must be aligned on a 16-byte boundary or a
4699// general-protection exception may be generated.
4700//
4701// dst[63:0] := MEM[mem_addr+127:mem_addr+64]
4702// dst[127:64] := MEM[mem_addr+63:mem_addr]
4703//
4704// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_loadr_pd
4706{
4707#if defined(__aarch64__)
4708 float64x2_t v = vld1q_f64(p);
4709 return vreinterpretq_m128d_f64(vextq_f64(v, v, 1));
4710#else
4711 int64x2_t v = vld1q_s64((const int64_t *) p);
4712 return vreinterpretq_m128d_s64(vextq_s64(v, v, 1));
4713#endif
4714}
4715
4716// Loads two double-precision from unaligned memory, floating-point values.
4717// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_loadu_pd
4719{
4720 return _mm_load_pd(p);
4721}
4722
4723// Loads 128-bit value. :
4724// https://msdn.microsoft.com/zh-cn/library/f4k12ae8(v=vs.90).aspx
4726{
4727 return vreinterpretq_m128i_s32(vld1q_s32((const int32_t *) p));
4728}
4729
4730// Load unaligned 32-bit integer from memory into the first element of dst.
4731//
4732// dst[31:0] := MEM[mem_addr+31:mem_addr]
4733// dst[MAX:32] := 0
4734//
4735// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_loadu_si32
4737{
4739 vsetq_lane_s32(*(const int32_t *) p, vdupq_n_s32(0), 0));
4740}
4741
4742// Multiplies the 8 signed 16-bit integers from a by the 8 signed 16-bit
4743// integers from b.
4744//
4745// r0 := (a0 * b0) + (a1 * b1)
4746// r1 := (a2 * b2) + (a3 * b3)
4747// r2 := (a4 * b4) + (a5 * b5)
4748// r3 := (a6 * b6) + (a7 * b7)
4749// https://msdn.microsoft.com/en-us/library/yht36sa6(v=vs.90).aspx
4751{
4752 int32x4_t low = vmull_s16(vget_low_s16(vreinterpretq_s16_m128i(a)),
4753 vget_low_s16(vreinterpretq_s16_m128i(b)));
4754#if defined(__aarch64__)
4755 int32x4_t high =
4756 vmull_high_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b));
4757
4758 return vreinterpretq_m128i_s32(vpaddq_s32(low, high));
4759#else
4760 int32x4_t high = vmull_s16(vget_high_s16(vreinterpretq_s16_m128i(a)),
4761 vget_high_s16(vreinterpretq_s16_m128i(b)));
4762
4763 int32x2_t low_sum = vpadd_s32(vget_low_s32(low), vget_high_s32(low));
4764 int32x2_t high_sum = vpadd_s32(vget_low_s32(high), vget_high_s32(high));
4765
4766 return vreinterpretq_m128i_s32(vcombine_s32(low_sum, high_sum));
4767#endif
4768}
4769
4770// Conditionally store 8-bit integer elements from a into memory using mask
4771// (elements are not stored when the highest bit is not set in the corresponding
4772// element) and a non-temporal memory hint. mem_addr does not need to be aligned
4773// on any particular boundary.
4774// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_maskmoveu_si128
4776{
4777 int8x16_t shr_mask = vshrq_n_s8(vreinterpretq_s8_m128i(mask), 7);
4778 __m128 b = _mm_load_ps((const float *) mem_addr);
4779 int8x16_t masked =
4780 vbslq_s8(vreinterpretq_u8_s8(shr_mask), vreinterpretq_s8_m128i(a),
4782 vst1q_s8((int8_t *) mem_addr, masked);
4783}
4784
4785// Computes the pairwise maxima of the 8 signed 16-bit integers from a and the 8
4786// signed 16-bit integers from b.
4787// https://msdn.microsoft.com/en-us/LIBRary/3x060h7c(v=vs.100).aspx
4793
4794// Computes the pairwise maxima of the 16 unsigned 8-bit integers from a and the
4795// 16 unsigned 8-bit integers from b.
4796// https://msdn.microsoft.com/en-us/library/st6634za(v=vs.100).aspx
4802
4803// Compare packed double-precision (64-bit) floating-point elements in a and b,
4804// and store packed maximum values in dst.
4805// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_max_pd
4807{
4808#if defined(__aarch64__)
4809#if SSE2NEON_PRECISE_MINMAX
4810 float64x2_t _a = vreinterpretq_f64_m128d(a);
4811 float64x2_t _b = vreinterpretq_f64_m128d(b);
4812 return vreinterpretq_m128d_f64(vbslq_f64(vcgtq_f64(_a, _b), _a, _b));
4813#else
4814 return vreinterpretq_m128d_f64(
4815 vmaxq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
4816#endif
4817#else
4818 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
4819 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
4820 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
4821 uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
4822 uint64_t d[2];
4823 d[0] = (*(double *) &a0) > (*(double *) &b0) ? a0 : b0;
4824 d[1] = (*(double *) &a1) > (*(double *) &b1) ? a1 : b1;
4825
4826 return vreinterpretq_m128d_u64(vld1q_u64(d));
4827#endif
4828}
4829
4830// Compare the lower double-precision (64-bit) floating-point elements in a and
4831// b, store the maximum value in the lower element of dst, and copy the upper
4832// element from a to the upper element of dst.
4833// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_max_sd
4835{
4836#if defined(__aarch64__)
4837 return _mm_move_sd(a, _mm_max_pd(a, b));
4838#else
4839 double *da = (double *) &a;
4840 double *db = (double *) &b;
4841 double c[2] = {da[0] > db[0] ? da[0] : db[0], da[1]};
4842 return vreinterpretq_m128d_f32(vld1q_f32((float32_t *) c));
4843#endif
4844}
4845
4846// Computes the pairwise minima of the 8 signed 16-bit integers from a and the 8
4847// signed 16-bit integers from b.
4848// https://msdn.microsoft.com/en-us/library/vstudio/6te997ew(v=vs.100).aspx
4854
4855// Computes the pairwise minima of the 16 unsigned 8-bit integers from a and the
4856// 16 unsigned 8-bit integers from b.
4857// https://msdn.microsoft.com/ko-kr/library/17k8cf58(v=vs.100).aspxx
4863
4864// Compare packed double-precision (64-bit) floating-point elements in a and b,
4865// and store packed minimum values in dst.
4866// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_min_pd
4868{
4869#if defined(__aarch64__)
4870#if SSE2NEON_PRECISE_MINMAX
4871 float64x2_t _a = vreinterpretq_f64_m128d(a);
4872 float64x2_t _b = vreinterpretq_f64_m128d(b);
4873 return vreinterpretq_m128d_f64(vbslq_f64(vcltq_f64(_a, _b), _a, _b));
4874#else
4875 return vreinterpretq_m128d_f64(
4876 vminq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
4877#endif
4878#else
4879 uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
4880 uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
4881 uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
4882 uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
4883 uint64_t d[2];
4884 d[0] = (*(double *) &a0) < (*(double *) &b0) ? a0 : b0;
4885 d[1] = (*(double *) &a1) < (*(double *) &b1) ? a1 : b1;
4886 return vreinterpretq_m128d_u64(vld1q_u64(d));
4887#endif
4888}
4889
4890// Compare the lower double-precision (64-bit) floating-point elements in a and
4891// b, store the minimum value in the lower element of dst, and copy the upper
4892// element from a to the upper element of dst.
4893// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_min_sd
4895{
4896#if defined(__aarch64__)
4897 return _mm_move_sd(a, _mm_min_pd(a, b));
4898#else
4899 double *da = (double *) &a;
4900 double *db = (double *) &b;
4901 double c[2] = {da[0] < db[0] ? da[0] : db[0], da[1]};
4902 return vreinterpretq_m128d_f32(vld1q_f32((float32_t *) c));
4903#endif
4904}
4905
4906// Copy the lower 64-bit integer in a to the lower element of dst, and zero the
4907// upper element.
4908//
4909// dst[63:0] := a[63:0]
4910// dst[127:64] := 0
4911//
4912// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_move_epi64
4914{
4916 vsetq_lane_s64(0, vreinterpretq_s64_m128i(a), 1));
4917}
4918
4919// Move the lower double-precision (64-bit) floating-point element from b to the
4920// lower element of dst, and copy the upper element from a to the upper element
4921// of dst.
4922//
4923// dst[63:0] := b[63:0]
4924// dst[127:64] := a[127:64]
4925//
4926// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_move_sd
4928{
4930 vcombine_f32(vget_low_f32(vreinterpretq_f32_m128d(b)),
4931 vget_high_f32(vreinterpretq_f32_m128d(a))));
4932}
4933
4934// NEON does not provide a version of this function.
4935// Creates a 16-bit mask from the most significant bits of the 16 signed or
4936// unsigned 8-bit integers in a and zero extends the upper bits.
4937// https://msdn.microsoft.com/en-us/library/vstudio/s090c8fk(v=vs.100).aspx
4939{
4940 // Use increasingly wide shifts+adds to collect the sign bits
4941 // together.
4942 // Since the widening shifts would be rather confusing to follow in little
4943 // endian, everything will be illustrated in big endian order instead. This
4944 // has a different result - the bits would actually be reversed on a big
4945 // endian machine.
4946
4947 // Starting input (only half the elements are shown):
4948 // 89 ff 1d c0 00 10 99 33
4949 uint8x16_t input = vreinterpretq_u8_m128i(a);
4950
4951 // Shift out everything but the sign bits with an unsigned shift right.
4952 //
4953 // Bytes of the vector::
4954 // 89 ff 1d c0 00 10 99 33
4955 // \ \ \ \ \ \ \ \ high_bits = (uint16x4_t)(input >> 7)
4956 // | | | | | | | |
4957 // 01 01 00 01 00 00 01 00
4958 //
4959 // Bits of first important lane(s):
4960 // 10001001 (89)
4961 // \______
4962 // |
4963 // 00000001 (01)
4964 uint16x8_t high_bits = vreinterpretq_u16_u8(vshrq_n_u8(input, 7));
4965
4966 // Merge the even lanes together with a 16-bit unsigned shift right + add.
4967 // 'xx' represents garbage data which will be ignored in the final result.
4968 // In the important bytes, the add functions like a binary OR.
4969 //
4970 // 01 01 00 01 00 00 01 00
4971 // \_ | \_ | \_ | \_ | paired16 = (uint32x4_t)(input + (input >> 7))
4972 // \| \| \| \|
4973 // xx 03 xx 01 xx 00 xx 02
4974 //
4975 // 00000001 00000001 (01 01)
4976 // \_______ |
4977 // \|
4978 // xxxxxxxx xxxxxx11 (xx 03)
4979 uint32x4_t paired16 =
4980 vreinterpretq_u32_u16(vsraq_n_u16(high_bits, high_bits, 7));
4981
4982 // Repeat with a wider 32-bit shift + add.
4983 // xx 03 xx 01 xx 00 xx 02
4984 // \____ | \____ | paired32 = (uint64x1_t)(paired16 + (paired16 >>
4985 // 14))
4986 // \| \|
4987 // xx xx xx 0d xx xx xx 02
4988 //
4989 // 00000011 00000001 (03 01)
4990 // \\_____ ||
4991 // '----.\||
4992 // xxxxxxxx xxxx1101 (xx 0d)
4993 uint64x2_t paired32 =
4994 vreinterpretq_u64_u32(vsraq_n_u32(paired16, paired16, 14));
4995
4996 // Last, an even wider 64-bit shift + add to get our result in the low 8 bit
4997 // lanes. xx xx xx 0d xx xx xx 02
4998 // \_________ | paired64 = (uint8x8_t)(paired32 + (paired32 >>
4999 // 28))
5000 // \|
5001 // xx xx xx xx xx xx xx d2
5002 //
5003 // 00001101 00000010 (0d 02)
5004 // \ \___ | |
5005 // '---. \| |
5006 // xxxxxxxx 11010010 (xx d2)
5007 uint8x16_t paired64 =
5008 vreinterpretq_u8_u64(vsraq_n_u64(paired32, paired32, 28));
5009
5010 // Extract the low 8 bits from each 64-bit lane with 2 8-bit extracts.
5011 // xx xx xx xx xx xx xx d2
5012 // || return paired64[0]
5013 // d2
5014 // Note: Little endian would return the correct value 4b (01001011) instead.
5015 return vgetq_lane_u8(paired64, 0) | ((int) vgetq_lane_u8(paired64, 8) << 8);
5016}
5017
5018// Set each bit of mask dst based on the most significant bit of the
5019// corresponding packed double-precision (64-bit) floating-point element in a.
5020// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_movemask_pd
5022{
5023 uint64x2_t input = vreinterpretq_u64_m128d(a);
5024 uint64x2_t high_bits = vshrq_n_u64(input, 63);
5025 return vgetq_lane_u64(high_bits, 0) | (vgetq_lane_u64(high_bits, 1) << 1);
5026}
5027
5028// Copy the lower 64-bit integer in a to dst.
5029//
5030// dst[63:0] := a[63:0]
5031//
5032// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_movepi64_pi64
5037
5038// Copy the 64-bit integer a to the lower element of dst, and zero the upper
5039// element.
5040//
5041// dst[63:0] := a[63:0]
5042// dst[127:64] := 0
5043//
5044// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_movpi64_epi64
5046{
5048 vcombine_s64(vreinterpret_s64_m64(a), vdup_n_s64(0)));
5049}
5050
5051// Multiply the low unsigned 32-bit integers from each packed 64-bit element in
5052// a and b, and store the unsigned 64-bit results in dst.
5053//
5054// r0 := (a0 & 0xFFFFFFFF) * (b0 & 0xFFFFFFFF)
5055// r1 := (a2 & 0xFFFFFFFF) * (b2 & 0xFFFFFFFF)
5057{
5058 // vmull_u32 upcasts instead of masking, so we downcast.
5059 uint32x2_t a_lo = vmovn_u64(vreinterpretq_u64_m128i(a));
5060 uint32x2_t b_lo = vmovn_u64(vreinterpretq_u64_m128i(b));
5061 return vreinterpretq_m128i_u64(vmull_u32(a_lo, b_lo));
5062}
5063
5064// Multiply packed double-precision (64-bit) floating-point elements in a and b,
5065// and store the results in dst.
5066// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mul_pd
5068{
5069#if defined(__aarch64__)
5070 return vreinterpretq_m128d_f64(
5071 vmulq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
5072#else
5073 double *da = (double *) &a;
5074 double *db = (double *) &b;
5075 double c[2];
5076 c[0] = da[0] * db[0];
5077 c[1] = da[1] * db[1];
5078 return vld1q_f32((float32_t *) c);
5079#endif
5080}
5081
5082// Multiply the lower double-precision (64-bit) floating-point element in a and
5083// b, store the result in the lower element of dst, and copy the upper element
5084// from a to the upper element of dst.
5085// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=mm_mul_sd
5087{
5088 return _mm_move_sd(a, _mm_mul_pd(a, b));
5089}
5090
5091// Multiply the low unsigned 32-bit integers from a and b, and store the
5092// unsigned 64-bit result in dst.
5093//
5094// dst[63:0] := a[31:0] * b[31:0]
5095//
5096// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mul_su32
5098{
5099 return vreinterpret_m64_u64(vget_low_u64(
5100 vmull_u32(vreinterpret_u32_m64(a), vreinterpret_u32_m64(b))));
5101}
5102
5103// Multiplies the 8 signed 16-bit integers from a by the 8 signed 16-bit
5104// integers from b.
5105//
5106// r0 := (a0 * b0)[31:16]
5107// r1 := (a1 * b1)[31:16]
5108// ...
5109// r7 := (a7 * b7)[31:16]
5110//
5111// https://msdn.microsoft.com/en-us/library/vstudio/59hddw1d(v=vs.100).aspx
5113{
5114 /* FIXME: issue with large values because of result saturation */
5115 // int16x8_t ret = vqdmulhq_s16(vreinterpretq_s16_m128i(a),
5116 // vreinterpretq_s16_m128i(b)); /* =2*a*b */ return
5117 // vreinterpretq_m128i_s16(vshrq_n_s16(ret, 1));
5118 int16x4_t a3210 = vget_low_s16(vreinterpretq_s16_m128i(a));
5119 int16x4_t b3210 = vget_low_s16(vreinterpretq_s16_m128i(b));
5120 int32x4_t ab3210 = vmull_s16(a3210, b3210); /* 3333222211110000 */
5121 int16x4_t a7654 = vget_high_s16(vreinterpretq_s16_m128i(a));
5122 int16x4_t b7654 = vget_high_s16(vreinterpretq_s16_m128i(b));
5123 int32x4_t ab7654 = vmull_s16(a7654, b7654); /* 7777666655554444 */
5124 uint16x8x2_t r =
5125 vuzpq_u16(vreinterpretq_u16_s32(ab3210), vreinterpretq_u16_s32(ab7654));
5126 return vreinterpretq_m128i_u16(r.val[1]);
5127}
5128
5129// Multiply the packed unsigned 16-bit integers in a and b, producing
5130// intermediate 32-bit integers, and store the high 16 bits of the intermediate
5131// integers in dst.
5132// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mulhi_epu16
5134{
5135 uint16x4_t a3210 = vget_low_u16(vreinterpretq_u16_m128i(a));
5136 uint16x4_t b3210 = vget_low_u16(vreinterpretq_u16_m128i(b));
5137 uint32x4_t ab3210 = vmull_u16(a3210, b3210);
5138#if defined(__aarch64__)
5139 uint32x4_t ab7654 =
5140 vmull_high_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b));
5141 uint16x8_t r = vuzp2q_u16(vreinterpretq_u16_u32(ab3210),
5142 vreinterpretq_u16_u32(ab7654));
5143 return vreinterpretq_m128i_u16(r);
5144#else
5145 uint16x4_t a7654 = vget_high_u16(vreinterpretq_u16_m128i(a));
5146 uint16x4_t b7654 = vget_high_u16(vreinterpretq_u16_m128i(b));
5147 uint32x4_t ab7654 = vmull_u16(a7654, b7654);
5148 uint16x8x2_t r =
5149 vuzpq_u16(vreinterpretq_u16_u32(ab3210), vreinterpretq_u16_u32(ab7654));
5150 return vreinterpretq_m128i_u16(r.val[1]);
5151#endif
5152}
5153
5154// Multiplies the 8 signed or unsigned 16-bit integers from a by the 8 signed or
5155// unsigned 16-bit integers from b.
5156//
5157// r0 := (a0 * b0)[15:0]
5158// r1 := (a1 * b1)[15:0]
5159// ...
5160// r7 := (a7 * b7)[15:0]
5161//
5162// https://msdn.microsoft.com/en-us/library/vstudio/9ks1472s(v=vs.100).aspx
5168
5169// Compute the bitwise OR of packed double-precision (64-bit) floating-point
5170// elements in a and b, and store the results in dst.
5171// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=mm_or_pd
5177
5178// Computes the bitwise OR of the 128-bit value in a and the 128-bit value in b.
5179//
5180// r := a | b
5181//
5182// https://msdn.microsoft.com/en-us/library/vstudio/ew8ty0db(v=vs.100).aspx
5188
5189// Packs the 16 signed 16-bit integers from a and b into 8-bit integers and
5190// saturates.
5191// https://msdn.microsoft.com/en-us/library/k4y4f7w5%28v=vs.90%29.aspx
5193{
5195 vcombine_s8(vqmovn_s16(vreinterpretq_s16_m128i(a)),
5196 vqmovn_s16(vreinterpretq_s16_m128i(b))));
5197}
5198
5199// Packs the 8 signed 32-bit integers from a and b into signed 16-bit integers
5200// and saturates.
5201//
5202// r0 := SignedSaturate(a0)
5203// r1 := SignedSaturate(a1)
5204// r2 := SignedSaturate(a2)
5205// r3 := SignedSaturate(a3)
5206// r4 := SignedSaturate(b0)
5207// r5 := SignedSaturate(b1)
5208// r6 := SignedSaturate(b2)
5209// r7 := SignedSaturate(b3)
5210//
5211// https://msdn.microsoft.com/en-us/library/393t56f9%28v=vs.90%29.aspx
5213{
5215 vcombine_s16(vqmovn_s32(vreinterpretq_s32_m128i(a)),
5216 vqmovn_s32(vreinterpretq_s32_m128i(b))));
5217}
5218
5219// Packs the 16 signed 16 - bit integers from a and b into 8 - bit unsigned
5220// integers and saturates.
5221//
5222// r0 := UnsignedSaturate(a0)
5223// r1 := UnsignedSaturate(a1)
5224// ...
5225// r7 := UnsignedSaturate(a7)
5226// r8 := UnsignedSaturate(b0)
5227// r9 := UnsignedSaturate(b1)
5228// ...
5229// r15 := UnsignedSaturate(b7)
5230//
5231// https://msdn.microsoft.com/en-us/library/07ad1wx4(v=vs.100).aspx
5233{
5235 vcombine_u8(vqmovun_s16(vreinterpretq_s16_m128i(a)),
5236 vqmovun_s16(vreinterpretq_s16_m128i(b))));
5237}
5238
5239// Pause the processor. This is typically used in spin-wait loops and depending
5240// on the x86 processor typical values are in the 40-100 cycle range. The
5241// 'yield' instruction isn't a good fit because it's effectively a nop on most
5242// Arm cores. Experience with several databases has shown has shown an 'isb' is
5243// a reasonable approximation.
5245{
5246 __asm__ __volatile__("isb\n");
5247}
5248
5249// Compute the absolute differences of packed unsigned 8-bit integers in a and
5250// b, then horizontally sum each consecutive 8 differences to produce two
5251// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low
5252// 16 bits of 64-bit elements in dst.
5253// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sad_epu8
5255{
5256 uint16x8_t t = vpaddlq_u8(vabdq_u8((uint8x16_t) a, (uint8x16_t) b));
5257 return vreinterpretq_m128i_u64(vpaddlq_u32(vpaddlq_u16(t)));
5258}
5259
5260// Sets the 8 signed 16-bit integer values.
5261// https://msdn.microsoft.com/en-au/library/3e0fek84(v=vs.90).aspx
5263 short i6,
5264 short i5,
5265 short i4,
5266 short i3,
5267 short i2,
5268 short i1,
5269 short i0)
5270{
5271 int16_t ALIGN_STRUCT(16) data[8] = {i0, i1, i2, i3, i4, i5, i6, i7};
5272 return vreinterpretq_m128i_s16(vld1q_s16(data));
5273}
5274
5275// Sets the 4 signed 32-bit integer values.
5276// https://msdn.microsoft.com/en-us/library/vstudio/019beekt(v=vs.100).aspx
5277FORCE_INLINE __m128i _mm_set_epi32(int i3, int i2, int i1, int i0)
5278{
5279 int32_t ALIGN_STRUCT(16) data[4] = {i0, i1, i2, i3};
5280 return vreinterpretq_m128i_s32(vld1q_s32(data));
5281}
5282
5283// Returns the __m128i structure with its two 64-bit integer values
5284// initialized to the values of the two 64-bit integers passed in.
5285// https://msdn.microsoft.com/en-us/library/dk2sdw0h(v=vs.120).aspx
5287{
5288 return _mm_set_epi64x((int64_t) i1, (int64_t) i2);
5289}
5290
5291// Returns the __m128i structure with its two 64-bit integer values
5292// initialized to the values of the two 64-bit integers passed in.
5293// https://msdn.microsoft.com/en-us/library/dk2sdw0h(v=vs.120).aspx
5294FORCE_INLINE __m128i _mm_set_epi64x(int64_t i1, int64_t i2)
5295{
5297 vcombine_s64(vcreate_s64(i2), vcreate_s64(i1)));
5298}
5299
5300// Sets the 16 signed 8-bit integer values.
5301// https://msdn.microsoft.com/en-us/library/x0cx8zd3(v=vs.90).aspx
5303 signed char b14,
5304 signed char b13,
5305 signed char b12,
5306 signed char b11,
5307 signed char b10,
5308 signed char b9,
5309 signed char b8,
5310 signed char b7,
5311 signed char b6,
5312 signed char b5,
5313 signed char b4,
5314 signed char b3,
5315 signed char b2,
5316 signed char b1,
5317 signed char b0)
5318{
5319 int8_t ALIGN_STRUCT(16)
5320 data[16] = {(int8_t) b0, (int8_t) b1, (int8_t) b2, (int8_t) b3,
5321 (int8_t) b4, (int8_t) b5, (int8_t) b6, (int8_t) b7,
5322 (int8_t) b8, (int8_t) b9, (int8_t) b10, (int8_t) b11,
5323 (int8_t) b12, (int8_t) b13, (int8_t) b14, (int8_t) b15};
5324 return (__m128i) vld1q_s8(data);
5325}
5326
5327// Set packed double-precision (64-bit) floating-point elements in dst with the
5328// supplied values.
5329// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_set_pd
5330FORCE_INLINE __m128d _mm_set_pd(double e1, double e0)
5331{
5332 double ALIGN_STRUCT(16) data[2] = {e0, e1};
5333#if defined(__aarch64__)
5334 return vreinterpretq_m128d_f64(vld1q_f64((float64_t *) data));
5335#else
5336 return vreinterpretq_m128d_f32(vld1q_f32((float32_t *) data));
5337#endif
5338}
5339
5340// Broadcast double-precision (64-bit) floating-point value a to all elements of
5341// dst.
5342// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_set_pd1
5343#define _mm_set_pd1 _mm_set1_pd
5344
5345// Copy double-precision (64-bit) floating-point element a to the lower element
5346// of dst, and zero the upper element.
5347// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_set_sd
5349{
5350#if defined(__aarch64__)
5351 return vreinterpretq_m128d_f64(vsetq_lane_f64(a, vdupq_n_f64(0), 0));
5352#else
5353 return _mm_set_pd(0, a);
5354#endif
5355}
5356
5357// Sets the 8 signed 16-bit integer values to w.
5358//
5359// r0 := w
5360// r1 := w
5361// ...
5362// r7 := w
5363//
5364// https://msdn.microsoft.com/en-us/library/k0ya3x0e(v=vs.90).aspx
5366{
5367 return vreinterpretq_m128i_s16(vdupq_n_s16(w));
5368}
5369
5370// Sets the 4 signed 32-bit integer values to i.
5371//
5372// r0 := i
5373// r1 := i
5374// r2 := i
5375// r3 := I
5376//
5377// https://msdn.microsoft.com/en-us/library/vstudio/h4xscxat(v=vs.100).aspx
5379{
5380 return vreinterpretq_m128i_s32(vdupq_n_s32(_i));
5381}
5382
5383// Sets the 2 signed 64-bit integer values to i.
5384// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/whtfzhzk(v=vs.100)
5386{
5387 return vreinterpretq_m128i_s64(vdupq_n_s64((int64_t) _i));
5388}
5389
5390// Sets the 2 signed 64-bit integer values to i.
5391// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_set1_epi64x
5393{
5394 return vreinterpretq_m128i_s64(vdupq_n_s64(_i));
5395}
5396
5397// Sets the 16 signed 8-bit integer values to b.
5398//
5399// r0 := b
5400// r1 := b
5401// ...
5402// r15 := b
5403//
5404// https://msdn.microsoft.com/en-us/library/6e14xhyf(v=vs.100).aspx
5406{
5407 return vreinterpretq_m128i_s8(vdupq_n_s8(w));
5408}
5409
5410// Broadcast double-precision (64-bit) floating-point value a to all elements of
5411// dst.
5412// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_set1_pd
5414{
5415#if defined(__aarch64__)
5416 return vreinterpretq_m128d_f64(vdupq_n_f64(d));
5417#else
5418 return vreinterpretq_m128d_s64(vdupq_n_s64(*(int64_t *) &d));
5419#endif
5420}
5421
5422// Sets the 8 signed 16-bit integer values in reverse order.
5423//
5424// Return Value
5425// r0 := w0
5426// r1 := w1
5427// ...
5428// r7 := w7
5430 short w1,
5431 short w2,
5432 short w3,
5433 short w4,
5434 short w5,
5435 short w6,
5436 short w7)
5437{
5438 int16_t ALIGN_STRUCT(16) data[8] = {w0, w1, w2, w3, w4, w5, w6, w7};
5439 return vreinterpretq_m128i_s16(vld1q_s16((int16_t *) data));
5440}
5441
5442// Sets the 4 signed 32-bit integer values in reverse order
5443// https://technet.microsoft.com/en-us/library/security/27yb3ee5(v=vs.90).aspx
5444FORCE_INLINE __m128i _mm_setr_epi32(int i3, int i2, int i1, int i0)
5445{
5446 int32_t ALIGN_STRUCT(16) data[4] = {i3, i2, i1, i0};
5447 return vreinterpretq_m128i_s32(vld1q_s32(data));
5448}
5449
5450// Set packed 64-bit integers in dst with the supplied values in reverse order.
5451// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_setr_epi64
5453{
5454 return vreinterpretq_m128i_s64(vcombine_s64(e1, e0));
5455}
5456
5457// Sets the 16 signed 8-bit integer values in reverse order.
5458// https://msdn.microsoft.com/en-us/library/2khb9c7k(v=vs.90).aspx
5460 signed char b1,
5461 signed char b2,
5462 signed char b3,
5463 signed char b4,
5464 signed char b5,
5465 signed char b6,
5466 signed char b7,
5467 signed char b8,
5468 signed char b9,
5469 signed char b10,
5470 signed char b11,
5471 signed char b12,
5472 signed char b13,
5473 signed char b14,
5474 signed char b15)
5475{
5476 int8_t ALIGN_STRUCT(16)
5477 data[16] = {(int8_t) b0, (int8_t) b1, (int8_t) b2, (int8_t) b3,
5478 (int8_t) b4, (int8_t) b5, (int8_t) b6, (int8_t) b7,
5479 (int8_t) b8, (int8_t) b9, (int8_t) b10, (int8_t) b11,
5480 (int8_t) b12, (int8_t) b13, (int8_t) b14, (int8_t) b15};
5481 return (__m128i) vld1q_s8(data);
5482}
5483
5484// Set packed double-precision (64-bit) floating-point elements in dst with the
5485// supplied values in reverse order.
5486// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_setr_pd
5487FORCE_INLINE __m128d _mm_setr_pd(double e1, double e0)
5488{
5489 return _mm_set_pd(e0, e1);
5490}
5491
5492// Return vector of type __m128d with all elements set to zero.
5493// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_setzero_pd
5495{
5496#if defined(__aarch64__)
5497 return vreinterpretq_m128d_f64(vdupq_n_f64(0));
5498#else
5499 return vreinterpretq_m128d_f32(vdupq_n_f32(0));
5500#endif
5501}
5502
5503// Sets the 128-bit value to zero
5504// https://msdn.microsoft.com/en-us/library/vstudio/ys7dw0kh(v=vs.100).aspx
5506{
5507 return vreinterpretq_m128i_s32(vdupq_n_s32(0));
5508}
5509
5510// Shuffles the 4 signed or unsigned 32-bit integers in a as specified by imm.
5511// https://msdn.microsoft.com/en-us/library/56f67xbk%28v=vs.90%29.aspx
5512// FORCE_INLINE __m128i _mm_shuffle_epi32(__m128i a,
5513// __constrange(0,255) int imm)
5514#ifdef _sse2neon_shuffle
5515#define _mm_shuffle_epi32(a, imm) \
5516 __extension__({ \
5517 int32x4_t _input = vreinterpretq_s32_m128i(a); \
5518 int32x4_t _shuf = \
5519 vshuffleq_s32(_input, _input, (imm) & (0x3), ((imm) >> 2) & 0x3, \
5520 ((imm) >> 4) & 0x3, ((imm) >> 6) & 0x3); \
5521 vreinterpretq_m128i_s32(_shuf); \
5522 })
5523#else // generic
5524#define _mm_shuffle_epi32(a, imm) \
5525 __extension__({ \
5526 __m128i ret; \
5527 switch (imm) { \
5528 case _MM_SHUFFLE(1, 0, 3, 2): \
5529 ret = _mm_shuffle_epi_1032((a)); \
5530 break; \
5531 case _MM_SHUFFLE(2, 3, 0, 1): \
5532 ret = _mm_shuffle_epi_2301((a)); \
5533 break; \
5534 case _MM_SHUFFLE(0, 3, 2, 1): \
5535 ret = _mm_shuffle_epi_0321((a)); \
5536 break; \
5537 case _MM_SHUFFLE(2, 1, 0, 3): \
5538 ret = _mm_shuffle_epi_2103((a)); \
5539 break; \
5540 case _MM_SHUFFLE(1, 0, 1, 0): \
5541 ret = _mm_shuffle_epi_1010((a)); \
5542 break; \
5543 case _MM_SHUFFLE(1, 0, 0, 1): \
5544 ret = _mm_shuffle_epi_1001((a)); \
5545 break; \
5546 case _MM_SHUFFLE(0, 1, 0, 1): \
5547 ret = _mm_shuffle_epi_0101((a)); \
5548 break; \
5549 case _MM_SHUFFLE(2, 2, 1, 1): \
5550 ret = _mm_shuffle_epi_2211((a)); \
5551 break; \
5552 case _MM_SHUFFLE(0, 1, 2, 2): \
5553 ret = _mm_shuffle_epi_0122((a)); \
5554 break; \
5555 case _MM_SHUFFLE(3, 3, 3, 2): \
5556 ret = _mm_shuffle_epi_3332((a)); \
5557 break; \
5558 case _MM_SHUFFLE(0, 0, 0, 0): \
5559 ret = _mm_shuffle_epi32_splat((a), 0); \
5560 break; \
5561 case _MM_SHUFFLE(1, 1, 1, 1): \
5562 ret = _mm_shuffle_epi32_splat((a), 1); \
5563 break; \
5564 case _MM_SHUFFLE(2, 2, 2, 2): \
5565 ret = _mm_shuffle_epi32_splat((a), 2); \
5566 break; \
5567 case _MM_SHUFFLE(3, 3, 3, 3): \
5568 ret = _mm_shuffle_epi32_splat((a), 3); \
5569 break; \
5570 default: \
5571 ret = _mm_shuffle_epi32_default((a), (imm)); \
5572 break; \
5573 } \
5574 ret; \
5575 })
5576#endif
5577
5578// Shuffle double-precision (64-bit) floating-point elements using the control
5579// in imm8, and store the results in dst.
5580//
5581// dst[63:0] := (imm8[0] == 0) ? a[63:0] : a[127:64]
5582// dst[127:64] := (imm8[1] == 0) ? b[63:0] : b[127:64]
5583//
5584// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_shuffle_pd
5585#ifdef _sse2neon_shuffle
5586#define _mm_shuffle_pd(a, b, imm8) \
5587 vreinterpretq_m128d_s64( \
5588 vshuffleq_s64(vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b), \
5589 imm8 & 0x1, ((imm8 & 0x2) >> 1) + 2))
5590#else
5591#define _mm_shuffle_pd(a, b, imm8) \
5592 _mm_castsi128_pd(_mm_set_epi64x( \
5593 vgetq_lane_s64(vreinterpretq_s64_m128d(b), (imm8 & 0x2) >> 1), \
5594 vgetq_lane_s64(vreinterpretq_s64_m128d(a), imm8 & 0x1)))
5595#endif
5596
5597// FORCE_INLINE __m128i _mm_shufflehi_epi16(__m128i a,
5598// __constrange(0,255) int imm)
5599#ifdef _sse2neon_shuffle
5600#define _mm_shufflehi_epi16(a, imm) \
5601 __extension__({ \
5602 int16x8_t _input = vreinterpretq_s16_m128i(a); \
5603 int16x8_t _shuf = \
5604 vshuffleq_s16(_input, _input, 0, 1, 2, 3, ((imm) & (0x3)) + 4, \
5605 (((imm) >> 2) & 0x3) + 4, (((imm) >> 4) & 0x3) + 4, \
5606 (((imm) >> 6) & 0x3) + 4); \
5607 vreinterpretq_m128i_s16(_shuf); \
5608 })
5609#else // generic
5610#define _mm_shufflehi_epi16(a, imm) _mm_shufflehi_epi16_function((a), (imm))
5611#endif
5612
5613// FORCE_INLINE __m128i _mm_shufflelo_epi16(__m128i a,
5614// __constrange(0,255) int imm)
5615#ifdef _sse2neon_shuffle
5616#define _mm_shufflelo_epi16(a, imm) \
5617 __extension__({ \
5618 int16x8_t _input = vreinterpretq_s16_m128i(a); \
5619 int16x8_t _shuf = vshuffleq_s16( \
5620 _input, _input, ((imm) & (0x3)), (((imm) >> 2) & 0x3), \
5621 (((imm) >> 4) & 0x3), (((imm) >> 6) & 0x3), 4, 5, 6, 7); \
5622 vreinterpretq_m128i_s16(_shuf); \
5623 })
5624#else // generic
5625#define _mm_shufflelo_epi16(a, imm) _mm_shufflelo_epi16_function((a), (imm))
5626#endif
5627
5628// Shift packed 16-bit integers in a left by count while shifting in zeros, and
5629// store the results in dst.
5630//
5631// FOR j := 0 to 7
5632// i := j*16
5633// IF count[63:0] > 15
5634// dst[i+15:i] := 0
5635// ELSE
5636// dst[i+15:i] := ZeroExtend16(a[i+15:i] << count[63:0])
5637// FI
5638// ENDFOR
5639//
5640// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sll_epi16
5642{
5643 uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
5644 if (_sse2neon_unlikely(c & ~15))
5645 return _mm_setzero_si128();
5646
5647 int16x8_t vc = vdupq_n_s16((int16_t) c);
5648 return vreinterpretq_m128i_s16(vshlq_s16(vreinterpretq_s16_m128i(a), vc));
5649}
5650
5651// Shift packed 32-bit integers in a left by count while shifting in zeros, and
5652// store the results in dst.
5653//
5654// FOR j := 0 to 3
5655// i := j*32
5656// IF count[63:0] > 31
5657// dst[i+31:i] := 0
5658// ELSE
5659// dst[i+31:i] := ZeroExtend32(a[i+31:i] << count[63:0])
5660// FI
5661// ENDFOR
5662//
5663// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sll_epi32
5665{
5666 uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
5667 if (_sse2neon_unlikely(c & ~31))
5668 return _mm_setzero_si128();
5669
5670 int32x4_t vc = vdupq_n_s32((int32_t) c);
5671 return vreinterpretq_m128i_s32(vshlq_s32(vreinterpretq_s32_m128i(a), vc));
5672}
5673
5674// Shift packed 64-bit integers in a left by count while shifting in zeros, and
5675// store the results in dst.
5676//
5677// FOR j := 0 to 1
5678// i := j*64
5679// IF count[63:0] > 63
5680// dst[i+63:i] := 0
5681// ELSE
5682// dst[i+63:i] := ZeroExtend64(a[i+63:i] << count[63:0])
5683// FI
5684// ENDFOR
5685//
5686// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sll_epi64
5688{
5689 uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
5690 if (_sse2neon_unlikely(c & ~63))
5691 return _mm_setzero_si128();
5692
5693 int64x2_t vc = vdupq_n_s64((int64_t) c);
5694 return vreinterpretq_m128i_s64(vshlq_s64(vreinterpretq_s64_m128i(a), vc));
5695}
5696
5697// Shift packed 16-bit integers in a left by imm8 while shifting in zeros, and
5698// store the results in dst.
5699//
5700// FOR j := 0 to 7
5701// i := j*16
5702// IF imm8[7:0] > 15
5703// dst[i+15:i] := 0
5704// ELSE
5705// dst[i+15:i] := ZeroExtend16(a[i+15:i] << imm8[7:0])
5706// FI
5707// ENDFOR
5708//
5709// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_slli_epi16
5711{
5712 if (_sse2neon_unlikely(imm & ~15))
5713 return _mm_setzero_si128();
5715 vshlq_s16(vreinterpretq_s16_m128i(a), vdupq_n_s16(imm)));
5716}
5717
5718// Shift packed 32-bit integers in a left by imm8 while shifting in zeros, and
5719// store the results in dst.
5720//
5721// FOR j := 0 to 3
5722// i := j*32
5723// IF imm8[7:0] > 31
5724// dst[i+31:i] := 0
5725// ELSE
5726// dst[i+31:i] := ZeroExtend32(a[i+31:i] << imm8[7:0])
5727// FI
5728// ENDFOR
5729//
5730// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_slli_epi32
5732{
5733 if (_sse2neon_unlikely(imm & ~31))
5734 return _mm_setzero_si128();
5736 vshlq_s32(vreinterpretq_s32_m128i(a), vdupq_n_s32(imm)));
5737}
5738
5739// Shift packed 64-bit integers in a left by imm8 while shifting in zeros, and
5740// store the results in dst.
5741//
5742// FOR j := 0 to 1
5743// i := j*64
5744// IF imm8[7:0] > 63
5745// dst[i+63:i] := 0
5746// ELSE
5747// dst[i+63:i] := ZeroExtend64(a[i+63:i] << imm8[7:0])
5748// FI
5749// ENDFOR
5750//
5751// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_slli_epi64
5753{
5754 if (_sse2neon_unlikely(imm & ~63))
5755 return _mm_setzero_si128();
5757 vshlq_s64(vreinterpretq_s64_m128i(a), vdupq_n_s64(imm)));
5758}
5759
5760// Shift a left by imm8 bytes while shifting in zeros, and store the results in
5761// dst.
5762//
5763// tmp := imm8[7:0]
5764// IF tmp > 15
5765// tmp := 16
5766// FI
5767// dst[127:0] := a[127:0] << (tmp*8)
5768//
5769// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_slli_si128
5770#define _mm_slli_si128(a, imm) \
5771 __extension__({ \
5772 int8x16_t ret; \
5773 if (_sse2neon_unlikely(imm == 0)) \
5774 ret = vreinterpretq_s8_m128i(a); \
5775 else if (_sse2neon_unlikely((imm) & ~15)) \
5776 ret = vdupq_n_s8(0); \
5777 else \
5778 ret = vextq_s8(vdupq_n_s8(0), vreinterpretq_s8_m128i(a), \
5779 ((imm <= 0 || imm > 15) ? 0 : (16 - imm))); \
5780 vreinterpretq_m128i_s8(ret); \
5781 })
5782
5783// Compute the square root of packed double-precision (64-bit) floating-point
5784// elements in a, and store the results in dst.
5785// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sqrt_pd
5787{
5788#if defined(__aarch64__)
5789 return vreinterpretq_m128d_f64(vsqrtq_f64(vreinterpretq_f64_m128d(a)));
5790#else
5791 double a0 = sqrt(((double *) &a)[0]);
5792 double a1 = sqrt(((double *) &a)[1]);
5793 return _mm_set_pd(a1, a0);
5794#endif
5795}
5796
5797// Compute the square root of the lower double-precision (64-bit) floating-point
5798// element in b, store the result in the lower element of dst, and copy the
5799// upper element from a to the upper element of dst.
5800// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sqrt_sd
5802{
5803#if defined(__aarch64__)
5804 return _mm_move_sd(a, _mm_sqrt_pd(b));
5805#else
5806 return _mm_set_pd(((double *) &a)[1], sqrt(((double *) &b)[0]));
5807#endif
5808}
5809
5810// Shift packed 16-bit integers in a right by count while shifting in sign bits,
5811// and store the results in dst.
5812//
5813// FOR j := 0 to 7
5814// i := j*16
5815// IF count[63:0] > 15
5816// dst[i+15:i] := (a[i+15] ? 0xFFFF : 0x0)
5817// ELSE
5818// dst[i+15:i] := SignExtend16(a[i+15:i] >> count[63:0])
5819// FI
5820// ENDFOR
5821//
5822// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sra_epi16
5824{
5825 int64_t c = (int64_t) vget_low_s64((int64x2_t) count);
5826 if (_sse2neon_unlikely(c & ~15))
5828 return vreinterpretq_m128i_s16(vshlq_s16((int16x8_t) a, vdupq_n_s16(-c)));
5829}
5830
5831// Shift packed 32-bit integers in a right by count while shifting in sign bits,
5832// and store the results in dst.
5833//
5834// FOR j := 0 to 3
5835// i := j*32
5836// IF count[63:0] > 31
5837// dst[i+31:i] := (a[i+31] ? 0xFFFFFFFF : 0x0)
5838// ELSE
5839// dst[i+31:i] := SignExtend32(a[i+31:i] >> count[63:0])
5840// FI
5841// ENDFOR
5842//
5843// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sra_epi32
5845{
5846 int64_t c = (int64_t) vget_low_s64((int64x2_t) count);
5847 if (_sse2neon_unlikely(c & ~31))
5849 return vreinterpretq_m128i_s32(vshlq_s32((int32x4_t) a, vdupq_n_s32(-c)));
5850}
5851
5852// Shift packed 16-bit integers in a right by imm8 while shifting in sign
5853// bits, and store the results in dst.
5854//
5855// FOR j := 0 to 7
5856// i := j*16
5857// IF imm8[7:0] > 15
5858// dst[i+15:i] := (a[i+15] ? 0xFFFF : 0x0)
5859// ELSE
5860// dst[i+15:i] := SignExtend16(a[i+15:i] >> imm8[7:0])
5861// FI
5862// ENDFOR
5863//
5864// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_srai_epi16
5866{
5867 const int count = (imm & ~15) ? 15 : imm;
5868 return (__m128i) vshlq_s16((int16x8_t) a, vdupq_n_s16(-count));
5869}
5870
5871// Shift packed 32-bit integers in a right by imm8 while shifting in sign bits,
5872// and store the results in dst.
5873//
5874// FOR j := 0 to 3
5875// i := j*32
5876// IF imm8[7:0] > 31
5877// dst[i+31:i] := (a[i+31] ? 0xFFFFFFFF : 0x0)
5878// ELSE
5879// dst[i+31:i] := SignExtend32(a[i+31:i] >> imm8[7:0])
5880// FI
5881// ENDFOR
5882//
5883// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_srai_epi32
5884// FORCE_INLINE __m128i _mm_srai_epi32(__m128i a, __constrange(0,255) int imm)
5885#define _mm_srai_epi32(a, imm) \
5886 __extension__({ \
5887 __m128i ret; \
5888 if (_sse2neon_unlikely((imm) == 0)) { \
5889 ret = a; \
5890 } else if (_sse2neon_likely(0 < (imm) && (imm) < 32)) { \
5891 ret = vreinterpretq_m128i_s32( \
5892 vshlq_s32(vreinterpretq_s32_m128i(a), vdupq_n_s32(-(imm)))); \
5893 } else { \
5894 ret = vreinterpretq_m128i_s32( \
5895 vshrq_n_s32(vreinterpretq_s32_m128i(a), 31)); \
5896 } \
5897 ret; \
5898 })
5899
5900// Shift packed 16-bit integers in a right by count while shifting in zeros, and
5901// store the results in dst.
5902//
5903// FOR j := 0 to 7
5904// i := j*16
5905// IF count[63:0] > 15
5906// dst[i+15:i] := 0
5907// ELSE
5908// dst[i+15:i] := ZeroExtend16(a[i+15:i] >> count[63:0])
5909// FI
5910// ENDFOR
5911//
5912// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_srl_epi16
5914{
5915 uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
5916 if (_sse2neon_unlikely(c & ~15))
5917 return _mm_setzero_si128();
5918
5919 int16x8_t vc = vdupq_n_s16(-(int16_t) c);
5920 return vreinterpretq_m128i_u16(vshlq_u16(vreinterpretq_u16_m128i(a), vc));
5921}
5922
5923// Shift packed 32-bit integers in a right by count while shifting in zeros, and
5924// store the results in dst.
5925//
5926// FOR j := 0 to 3
5927// i := j*32
5928// IF count[63:0] > 31
5929// dst[i+31:i] := 0
5930// ELSE
5931// dst[i+31:i] := ZeroExtend32(a[i+31:i] >> count[63:0])
5932// FI
5933// ENDFOR
5934//
5935// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_srl_epi32
5937{
5938 uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
5939 if (_sse2neon_unlikely(c & ~31))
5940 return _mm_setzero_si128();
5941
5942 int32x4_t vc = vdupq_n_s32(-(int32_t) c);
5943 return vreinterpretq_m128i_u32(vshlq_u32(vreinterpretq_u32_m128i(a), vc));
5944}
5945
5946// Shift packed 64-bit integers in a right by count while shifting in zeros, and
5947// store the results in dst.
5948//
5949// FOR j := 0 to 1
5950// i := j*64
5951// IF count[63:0] > 63
5952// dst[i+63:i] := 0
5953// ELSE
5954// dst[i+63:i] := ZeroExtend64(a[i+63:i] >> count[63:0])
5955// FI
5956// ENDFOR
5957//
5958// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_srl_epi64
5960{
5961 uint64_t c = vreinterpretq_nth_u64_m128i(count, 0);
5962 if (_sse2neon_unlikely(c & ~63))
5963 return _mm_setzero_si128();
5964
5965 int64x2_t vc = vdupq_n_s64(-(int64_t) c);
5966 return vreinterpretq_m128i_u64(vshlq_u64(vreinterpretq_u64_m128i(a), vc));
5967}
5968
5969// Shift packed 16-bit integers in a right by imm8 while shifting in zeros, and
5970// store the results in dst.
5971//
5972// FOR j := 0 to 7
5973// i := j*16
5974// IF imm8[7:0] > 15
5975// dst[i+15:i] := 0
5976// ELSE
5977// dst[i+15:i] := ZeroExtend16(a[i+15:i] >> imm8[7:0])
5978// FI
5979// ENDFOR
5980//
5981// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_srli_epi16
5982#define _mm_srli_epi16(a, imm) \
5983 __extension__({ \
5984 __m128i ret; \
5985 if (_sse2neon_unlikely((imm) & ~15)) { \
5986 ret = _mm_setzero_si128(); \
5987 } else { \
5988 ret = vreinterpretq_m128i_u16( \
5989 vshlq_u16(vreinterpretq_u16_m128i(a), vdupq_n_s16(-(imm)))); \
5990 } \
5991 ret; \
5992 })
5993
5994// Shift packed 32-bit integers in a right by imm8 while shifting in zeros, and
5995// store the results in dst.
5996//
5997// FOR j := 0 to 3
5998// i := j*32
5999// IF imm8[7:0] > 31
6000// dst[i+31:i] := 0
6001// ELSE
6002// dst[i+31:i] := ZeroExtend32(a[i+31:i] >> imm8[7:0])
6003// FI
6004// ENDFOR
6005//
6006// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_srli_epi32
6007// FORCE_INLINE __m128i _mm_srli_epi32(__m128i a, __constrange(0,255) int imm)
6008#define _mm_srli_epi32(a, imm) \
6009 __extension__({ \
6010 __m128i ret; \
6011 if (_sse2neon_unlikely((imm) & ~31)) { \
6012 ret = _mm_setzero_si128(); \
6013 } else { \
6014 ret = vreinterpretq_m128i_u32( \
6015 vshlq_u32(vreinterpretq_u32_m128i(a), vdupq_n_s32(-(imm)))); \
6016 } \
6017 ret; \
6018 })
6019
6020// Shift packed 64-bit integers in a right by imm8 while shifting in zeros, and
6021// store the results in dst.
6022//
6023// FOR j := 0 to 1
6024// i := j*64
6025// IF imm8[7:0] > 63
6026// dst[i+63:i] := 0
6027// ELSE
6028// dst[i+63:i] := ZeroExtend64(a[i+63:i] >> imm8[7:0])
6029// FI
6030// ENDFOR
6031//
6032// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_srli_epi64
6033#define _mm_srli_epi64(a, imm) \
6034 __extension__({ \
6035 __m128i ret; \
6036 if (_sse2neon_unlikely((imm) & ~63)) { \
6037 ret = _mm_setzero_si128(); \
6038 } else { \
6039 ret = vreinterpretq_m128i_u64( \
6040 vshlq_u64(vreinterpretq_u64_m128i(a), vdupq_n_s64(-(imm)))); \
6041 } \
6042 ret; \
6043 })
6044
6045// Shift a right by imm8 bytes while shifting in zeros, and store the results in
6046// dst.
6047//
6048// tmp := imm8[7:0]
6049// IF tmp > 15
6050// tmp := 16
6051// FI
6052// dst[127:0] := a[127:0] >> (tmp*8)
6053//
6054// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_srli_si128
6055#define _mm_srli_si128(a, imm) \
6056 __extension__({ \
6057 int8x16_t ret; \
6058 if (_sse2neon_unlikely((imm) & ~15)) \
6059 ret = vdupq_n_s8(0); \
6060 else \
6061 ret = vextq_s8(vreinterpretq_s8_m128i(a), vdupq_n_s8(0), \
6062 (imm > 15 ? 0 : imm)); \
6063 vreinterpretq_m128i_s8(ret); \
6064 })
6065
6066// Store 128-bits (composed of 2 packed double-precision (64-bit) floating-point
6067// elements) from a into memory. mem_addr must be aligned on a 16-byte boundary
6068// or a general-protection exception may be generated.
6069// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_store_pd
6070FORCE_INLINE void _mm_store_pd(double *mem_addr, __m128d a)
6071{
6072#if defined(__aarch64__)
6073 vst1q_f64((float64_t *) mem_addr, vreinterpretq_f64_m128d(a));
6074#else
6075 vst1q_f32((float32_t *) mem_addr, vreinterpretq_f32_m128d(a));
6076#endif
6077}
6078
6079// Store the lower double-precision (64-bit) floating-point element from a into
6080// 2 contiguous elements in memory. mem_addr must be aligned on a 16-byte
6081// boundary or a general-protection exception may be generated.
6082// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_store_pd1
6083FORCE_INLINE void _mm_store_pd1(double *mem_addr, __m128d a)
6084{
6085#if defined(__aarch64__)
6086 float64x1_t a_low = vget_low_f64(vreinterpretq_f64_m128d(a));
6087 vst1q_f64((float64_t *) mem_addr,
6088 vreinterpretq_f64_m128d(vcombine_f64(a_low, a_low)));
6089#else
6090 float32x2_t a_low = vget_low_f32(vreinterpretq_f32_m128d(a));
6091 vst1q_f32((float32_t *) mem_addr,
6092 vreinterpretq_f32_m128d(vcombine_f32(a_low, a_low)));
6093#endif
6094}
6095
6096// Store the lower double-precision (64-bit) floating-point element from a into
6097// memory. mem_addr does not need to be aligned on any particular boundary.
6098// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=mm_store_sd
6099FORCE_INLINE void _mm_store_sd(double *mem_addr, __m128d a)
6100{
6101#if defined(__aarch64__)
6102 vst1_f64((float64_t *) mem_addr, vget_low_f64(vreinterpretq_f64_m128d(a)));
6103#else
6104 vst1_u64((uint64_t *) mem_addr, vget_low_u64(vreinterpretq_u64_m128d(a)));
6105#endif
6106}
6107
6108// Stores four 32-bit integer values as (as a __m128i value) at the address p.
6109// https://msdn.microsoft.com/en-us/library/vstudio/edk11s13(v=vs.100).aspx
6111{
6112 vst1q_s32((int32_t *) p, vreinterpretq_s32_m128i(a));
6113}
6114
6115// Store the lower double-precision (64-bit) floating-point element from a into
6116// 2 contiguous elements in memory. mem_addr must be aligned on a 16-byte
6117// boundary or a general-protection exception may be generated.
6118// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#expand=9,526,5601&text=_mm_store1_pd
6119#define _mm_store1_pd _mm_store_pd1
6120
6121// Store the upper double-precision (64-bit) floating-point element from a into
6122// memory.
6123//
6124// MEM[mem_addr+63:mem_addr] := a[127:64]
6125//
6126// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_storeh_pd
6127FORCE_INLINE void _mm_storeh_pd(double *mem_addr, __m128d a)
6128{
6129#if defined(__aarch64__)
6130 vst1_f64((float64_t *) mem_addr, vget_high_f64(vreinterpretq_f64_m128d(a)));
6131#else
6132 vst1_f32((float32_t *) mem_addr, vget_high_f32(vreinterpretq_f32_m128d(a)));
6133#endif
6134}
6135
6136// Reads the lower 64 bits of b and stores them into the lower 64 bits of a.
6137// https://msdn.microsoft.com/en-us/library/hhwf428f%28v=vs.90%29.aspx
6139{
6140 vst1_u64((uint64_t *) a, vget_low_u64(vreinterpretq_u64_m128i(b)));
6141}
6142
6143// Store the lower double-precision (64-bit) floating-point element from a into
6144// memory.
6145//
6146// MEM[mem_addr+63:mem_addr] := a[63:0]
6147//
6148// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_storel_pd
6149FORCE_INLINE void _mm_storel_pd(double *mem_addr, __m128d a)
6150{
6151#if defined(__aarch64__)
6152 vst1_f64((float64_t *) mem_addr, vget_low_f64(vreinterpretq_f64_m128d(a)));
6153#else
6154 vst1_f32((float32_t *) mem_addr, vget_low_f32(vreinterpretq_f32_m128d(a)));
6155#endif
6156}
6157
6158// Store 2 double-precision (64-bit) floating-point elements from a into memory
6159// in reverse order. mem_addr must be aligned on a 16-byte boundary or a
6160// general-protection exception may be generated.
6161//
6162// MEM[mem_addr+63:mem_addr] := a[127:64]
6163// MEM[mem_addr+127:mem_addr+64] := a[63:0]
6164//
6165// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_storer_pd
6166FORCE_INLINE void _mm_storer_pd(double *mem_addr, __m128d a)
6167{
6168 float32x4_t f = vreinterpretq_f32_m128d(a);
6169 _mm_store_pd(mem_addr, vreinterpretq_m128d_f32(vextq_f32(f, f, 2)));
6170}
6171
6172// Store 128-bits (composed of 2 packed double-precision (64-bit) floating-point
6173// elements) from a into memory. mem_addr does not need to be aligned on any
6174// particular boundary.
6175// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_storeu_pd
6176FORCE_INLINE void _mm_storeu_pd(double *mem_addr, __m128d a)
6177{
6178 _mm_store_pd(mem_addr, a);
6179}
6180
6181// Stores 128-bits of integer data a at the address p.
6182// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_storeu_si128
6184{
6185 vst1q_s32((int32_t *) p, vreinterpretq_s32_m128i(a));
6186}
6187
6188// Stores 32-bits of integer data a at the address p.
6189// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_storeu_si32
6191{
6192 vst1q_lane_s32((int32_t *) p, vreinterpretq_s32_m128i(a), 0);
6193}
6194
6195// Store 128-bits (composed of 2 packed double-precision (64-bit) floating-point
6196// elements) from a into memory using a non-temporal memory hint. mem_addr must
6197// be aligned on a 16-byte boundary or a general-protection exception may be
6198// generated.
6199// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_stream_pd
6201{
6202#if __has_builtin(__builtin_nontemporal_store)
6203 __builtin_nontemporal_store(a, (float32x4_t *) p);
6204#elif defined(__aarch64__)
6205 vst1q_f64(p, vreinterpretq_f64_m128d(a));
6206#else
6207 vst1q_s64((int64_t *) p, vreinterpretq_s64_m128d(a));
6208#endif
6209}
6210
6211// Stores the data in a to the address p without polluting the caches. If the
6212// cache line containing address p is already in the cache, the cache will be
6213// updated.
6214// https://msdn.microsoft.com/en-us/library/ba08y07y%28v=vs.90%29.aspx
6216{
6217#if __has_builtin(__builtin_nontemporal_store)
6218 __builtin_nontemporal_store(a, p);
6219#else
6220 vst1q_s64((int64_t *) p, vreinterpretq_s64_m128i(a));
6221#endif
6222}
6223
6224// Store 32-bit integer a into memory using a non-temporal hint to minimize
6225// cache pollution. If the cache line containing address mem_addr is already in
6226// the cache, the cache will be updated.
6227// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_stream_si32
6229{
6230 vst1q_lane_s32((int32_t *) p, vdupq_n_s32(a), 0);
6231}
6232
6233// Store 64-bit integer a into memory using a non-temporal hint to minimize
6234// cache pollution. If the cache line containing address mem_addr is already in
6235// the cache, the cache will be updated.
6236// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_stream_si64
6238{
6239 vst1_s64((int64_t *) p, vdup_n_s64((int64_t) a));
6240}
6241
6242// Subtract packed 16-bit integers in b from packed 16-bit integers in a, and
6243// store the results in dst.
6244// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sub_epi16
6250
6251// Subtracts the 4 signed or unsigned 32-bit integers of b from the 4 signed or
6252// unsigned 32-bit integers of a.
6253//
6254// r0 := a0 - b0
6255// r1 := a1 - b1
6256// r2 := a2 - b2
6257// r3 := a3 - b3
6258//
6259// https://msdn.microsoft.com/en-us/library/vstudio/fhh866h0(v=vs.100).aspx
6265
6266// Subtract 2 packed 64-bit integers in b from 2 packed 64-bit integers in a,
6267// and store the results in dst.
6268// r0 := a0 - b0
6269// r1 := a1 - b1
6275
6276// Subtract packed 8-bit integers in b from packed 8-bit integers in a, and
6277// store the results in dst.
6278// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sub_epi8
6284
6285// Subtract packed double-precision (64-bit) floating-point elements in b from
6286// packed double-precision (64-bit) floating-point elements in a, and store the
6287// results in dst.
6288//
6289// FOR j := 0 to 1
6290// i := j*64
6291// dst[i+63:i] := a[i+63:i] - b[i+63:i]
6292// ENDFOR
6293//
6294// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=mm_sub_pd
6296{
6297#if defined(__aarch64__)
6298 return vreinterpretq_m128d_f64(
6299 vsubq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
6300#else
6301 double *da = (double *) &a;
6302 double *db = (double *) &b;
6303 double c[2];
6304 c[0] = da[0] - db[0];
6305 c[1] = da[1] - db[1];
6306 return vld1q_f32((float32_t *) c);
6307#endif
6308}
6309
6310// Subtract the lower double-precision (64-bit) floating-point element in b from
6311// the lower double-precision (64-bit) floating-point element in a, store the
6312// result in the lower element of dst, and copy the upper element from a to the
6313// upper element of dst.
6314// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sub_sd
6316{
6317 return _mm_move_sd(a, _mm_sub_pd(a, b));
6318}
6319
6320// Subtract 64-bit integer b from 64-bit integer a, and store the result in dst.
6321//
6322// dst[63:0] := a[63:0] - b[63:0]
6323//
6324// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sub_si64
6330
6331// Subtracts the 8 signed 16-bit integers of b from the 8 signed 16-bit integers
6332// of a and saturates.
6333//
6334// r0 := SignedSaturate(a0 - b0)
6335// r1 := SignedSaturate(a1 - b1)
6336// ...
6337// r7 := SignedSaturate(a7 - b7)
6338//
6339// https://technet.microsoft.com/en-us/subscriptions/3247z5b8(v=vs.90)
6345
6346// Subtracts the 16 signed 8-bit integers of b from the 16 signed 8-bit integers
6347// of a and saturates.
6348//
6349// r0 := SignedSaturate(a0 - b0)
6350// r1 := SignedSaturate(a1 - b1)
6351// ...
6352// r15 := SignedSaturate(a15 - b15)
6353//
6354// https://technet.microsoft.com/en-us/subscriptions/by7kzks1(v=vs.90)
6360
6361// Subtracts the 8 unsigned 16-bit integers of bfrom the 8 unsigned 16-bit
6362// integers of a and saturates..
6363// https://technet.microsoft.com/en-us/subscriptions/index/f44y0s19(v=vs.90).aspx
6369
6370// Subtracts the 16 unsigned 8-bit integers of b from the 16 unsigned 8-bit
6371// integers of a and saturates.
6372//
6373// r0 := UnsignedSaturate(a0 - b0)
6374// r1 := UnsignedSaturate(a1 - b1)
6375// ...
6376// r15 := UnsignedSaturate(a15 - b15)
6377//
6378// https://technet.microsoft.com/en-us/subscriptions/yadkxc18(v=vs.90)
6384
6385#define _mm_ucomieq_sd _mm_comieq_sd
6386#define _mm_ucomige_sd _mm_comige_sd
6387#define _mm_ucomigt_sd _mm_comigt_sd
6388#define _mm_ucomile_sd _mm_comile_sd
6389#define _mm_ucomilt_sd _mm_comilt_sd
6390#define _mm_ucomineq_sd _mm_comineq_sd
6391
6392// Return vector of type __m128d with undefined elements.
6393// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_undefined_pd
6395{
6396#if defined(__GNUC__) || defined(__clang__)
6397#pragma GCC diagnostic push
6398#pragma GCC diagnostic ignored "-Wuninitialized"
6399#endif
6400 __m128d a;
6401 return a;
6402#if defined(__GNUC__) || defined(__clang__)
6403#pragma GCC diagnostic pop
6404#endif
6405}
6406
6407// Interleaves the upper 4 signed or unsigned 16-bit integers in a with the
6408// upper 4 signed or unsigned 16-bit integers in b.
6409//
6410// r0 := a4
6411// r1 := b4
6412// r2 := a5
6413// r3 := b5
6414// r4 := a6
6415// r5 := b6
6416// r6 := a7
6417// r7 := b7
6418//
6419// https://msdn.microsoft.com/en-us/library/03196cz7(v=vs.100).aspx
6421{
6422#if defined(__aarch64__)
6425#else
6426 int16x4_t a1 = vget_high_s16(vreinterpretq_s16_m128i(a));
6427 int16x4_t b1 = vget_high_s16(vreinterpretq_s16_m128i(b));
6428 int16x4x2_t result = vzip_s16(a1, b1);
6429 return vreinterpretq_m128i_s16(vcombine_s16(result.val[0], result.val[1]));
6430#endif
6431}
6432
6433// Interleaves the upper 2 signed or unsigned 32-bit integers in a with the
6434// upper 2 signed or unsigned 32-bit integers in b.
6435// https://msdn.microsoft.com/en-us/library/65sa7cbs(v=vs.100).aspx
6437{
6438#if defined(__aarch64__)
6441#else
6442 int32x2_t a1 = vget_high_s32(vreinterpretq_s32_m128i(a));
6443 int32x2_t b1 = vget_high_s32(vreinterpretq_s32_m128i(b));
6444 int32x2x2_t result = vzip_s32(a1, b1);
6445 return vreinterpretq_m128i_s32(vcombine_s32(result.val[0], result.val[1]));
6446#endif
6447}
6448
6449// Interleaves the upper signed or unsigned 64-bit integer in a with the
6450// upper signed or unsigned 64-bit integer in b.
6451//
6452// r0 := a1
6453// r1 := b1
6455{
6456 int64x1_t a_h = vget_high_s64(vreinterpretq_s64_m128i(a));
6457 int64x1_t b_h = vget_high_s64(vreinterpretq_s64_m128i(b));
6458 return vreinterpretq_m128i_s64(vcombine_s64(a_h, b_h));
6459}
6460
6461// Interleaves the upper 8 signed or unsigned 8-bit integers in a with the upper
6462// 8 signed or unsigned 8-bit integers in b.
6463//
6464// r0 := a8
6465// r1 := b8
6466// r2 := a9
6467// r3 := b9
6468// ...
6469// r14 := a15
6470// r15 := b15
6471//
6472// https://msdn.microsoft.com/en-us/library/t5h7783k(v=vs.100).aspx
6474{
6475#if defined(__aarch64__)
6478#else
6479 int8x8_t a1 =
6480 vreinterpret_s8_s16(vget_high_s16(vreinterpretq_s16_m128i(a)));
6481 int8x8_t b1 =
6482 vreinterpret_s8_s16(vget_high_s16(vreinterpretq_s16_m128i(b)));
6483 int8x8x2_t result = vzip_s8(a1, b1);
6484 return vreinterpretq_m128i_s8(vcombine_s8(result.val[0], result.val[1]));
6485#endif
6486}
6487
6488// Unpack and interleave double-precision (64-bit) floating-point elements from
6489// the high half of a and b, and store the results in dst.
6490//
6491// DEFINE INTERLEAVE_HIGH_QWORDS(src1[127:0], src2[127:0]) {
6492// dst[63:0] := src1[127:64]
6493// dst[127:64] := src2[127:64]
6494// RETURN dst[127:0]
6495// }
6496// dst[127:0] := INTERLEAVE_HIGH_QWORDS(a[127:0], b[127:0])
6497//
6498// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_unpackhi_pd
6500{
6501#if defined(__aarch64__)
6502 return vreinterpretq_m128d_f64(
6503 vzip2q_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
6504#else
6506 vcombine_s64(vget_high_s64(vreinterpretq_s64_m128d(a)),
6507 vget_high_s64(vreinterpretq_s64_m128d(b))));
6508#endif
6509}
6510
6511// Interleaves the lower 4 signed or unsigned 16-bit integers in a with the
6512// lower 4 signed or unsigned 16-bit integers in b.
6513//
6514// r0 := a0
6515// r1 := b0
6516// r2 := a1
6517// r3 := b1
6518// r4 := a2
6519// r5 := b2
6520// r6 := a3
6521// r7 := b3
6522//
6523// https://msdn.microsoft.com/en-us/library/btxb17bw%28v=vs.90%29.aspx
6525{
6526#if defined(__aarch64__)
6529#else
6530 int16x4_t a1 = vget_low_s16(vreinterpretq_s16_m128i(a));
6531 int16x4_t b1 = vget_low_s16(vreinterpretq_s16_m128i(b));
6532 int16x4x2_t result = vzip_s16(a1, b1);
6533 return vreinterpretq_m128i_s16(vcombine_s16(result.val[0], result.val[1]));
6534#endif
6535}
6536
6537// Interleaves the lower 2 signed or unsigned 32 - bit integers in a with the
6538// lower 2 signed or unsigned 32 - bit integers in b.
6539//
6540// r0 := a0
6541// r1 := b0
6542// r2 := a1
6543// r3 := b1
6544//
6545// https://msdn.microsoft.com/en-us/library/x8atst9d(v=vs.100).aspx
6547{
6548#if defined(__aarch64__)
6551#else
6552 int32x2_t a1 = vget_low_s32(vreinterpretq_s32_m128i(a));
6553 int32x2_t b1 = vget_low_s32(vreinterpretq_s32_m128i(b));
6554 int32x2x2_t result = vzip_s32(a1, b1);
6555 return vreinterpretq_m128i_s32(vcombine_s32(result.val[0], result.val[1]));
6556#endif
6557}
6558
6560{
6561 int64x1_t a_l = vget_low_s64(vreinterpretq_s64_m128i(a));
6562 int64x1_t b_l = vget_low_s64(vreinterpretq_s64_m128i(b));
6563 return vreinterpretq_m128i_s64(vcombine_s64(a_l, b_l));
6564}
6565
6566// Interleaves the lower 8 signed or unsigned 8-bit integers in a with the lower
6567// 8 signed or unsigned 8-bit integers in b.
6568//
6569// r0 := a0
6570// r1 := b0
6571// r2 := a1
6572// r3 := b1
6573// ...
6574// r14 := a7
6575// r15 := b7
6576//
6577// https://msdn.microsoft.com/en-us/library/xf7k860c%28v=vs.90%29.aspx
6579{
6580#if defined(__aarch64__)
6583#else
6584 int8x8_t a1 = vreinterpret_s8_s16(vget_low_s16(vreinterpretq_s16_m128i(a)));
6585 int8x8_t b1 = vreinterpret_s8_s16(vget_low_s16(vreinterpretq_s16_m128i(b)));
6586 int8x8x2_t result = vzip_s8(a1, b1);
6587 return vreinterpretq_m128i_s8(vcombine_s8(result.val[0], result.val[1]));
6588#endif
6589}
6590
6591// Unpack and interleave double-precision (64-bit) floating-point elements from
6592// the low half of a and b, and store the results in dst.
6593//
6594// DEFINE INTERLEAVE_QWORDS(src1[127:0], src2[127:0]) {
6595// dst[63:0] := src1[63:0]
6596// dst[127:64] := src2[63:0]
6597// RETURN dst[127:0]
6598// }
6599// dst[127:0] := INTERLEAVE_QWORDS(a[127:0], b[127:0])
6600//
6601// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_unpacklo_pd
6603{
6604#if defined(__aarch64__)
6605 return vreinterpretq_m128d_f64(
6606 vzip1q_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
6607#else
6609 vcombine_s64(vget_low_s64(vreinterpretq_s64_m128d(a)),
6610 vget_low_s64(vreinterpretq_s64_m128d(b))));
6611#endif
6612}
6613
6614// Compute the bitwise XOR of packed double-precision (64-bit) floating-point
6615// elements in a and b, and store the results in dst.
6616//
6617// FOR j := 0 to 1
6618// i := j*64
6619// dst[i+63:i] := a[i+63:i] XOR b[i+63:i]
6620// ENDFOR
6621//
6622// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_xor_pd
6628
6629// Computes the bitwise XOR of the 128-bit value in a and the 128-bit value in
6630// b. https://msdn.microsoft.com/en-us/library/fzt08www(v=vs.100).aspx
6636
6637/* SSE3 */
6638
6639// Alternatively add and subtract packed double-precision (64-bit)
6640// floating-point elements in a to/from packed elements in b, and store the
6641// results in dst.
6642//
6643// FOR j := 0 to 1
6644// i := j*64
6645// IF ((j & 1) == 0)
6646// dst[i+63:i] := a[i+63:i] - b[i+63:i]
6647// ELSE
6648// dst[i+63:i] := a[i+63:i] + b[i+63:i]
6649// FI
6650// ENDFOR
6651//
6652// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_addsub_pd
6654{
6655 _sse2neon_const __m128d mask = _mm_set_pd(1.0f, -1.0f);
6656#if defined(__aarch64__)
6657 return vreinterpretq_m128d_f64(vfmaq_f64(vreinterpretq_f64_m128d(a),
6658 vreinterpretq_f64_m128d(b),
6659 vreinterpretq_f64_m128d(mask)));
6660#else
6661 return _mm_add_pd(_mm_mul_pd(b, mask), a);
6662#endif
6663}
6664
6665// Alternatively add and subtract packed single-precision (32-bit)
6666// floating-point elements in a to/from packed elements in b, and store the
6667// results in dst.
6668// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=addsub_ps
6670{
6671 _sse2neon_const __m128 mask = _mm_setr_ps(-1.0f, 1.0f, -1.0f, 1.0f);
6672#if defined(__aarch64__) || defined(__ARM_FEATURE_FMA) /* VFPv4+ */
6676#else
6677 return _mm_add_ps(_mm_mul_ps(b, mask), a);
6678#endif
6679}
6680
6681// Horizontally add adjacent pairs of double-precision (64-bit) floating-point
6682// elements in a and b, and pack the results in dst.
6683// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_hadd_pd
6685{
6686#if defined(__aarch64__)
6687 return vreinterpretq_m128d_f64(
6688 vpaddq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
6689#else
6690 double *da = (double *) &a;
6691 double *db = (double *) &b;
6692 double c[] = {da[0] + da[1], db[0] + db[1]};
6693 return vreinterpretq_m128d_u64(vld1q_u64((uint64_t *) c));
6694#endif
6695}
6696
6697// Computes pairwise add of each argument as single-precision, floating-point
6698// values a and b.
6699// https://msdn.microsoft.com/en-us/library/yd9wecaa.aspx
6701{
6702#if defined(__aarch64__)
6705#else
6706 float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a));
6707 float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a));
6708 float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b));
6709 float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b));
6711 vcombine_f32(vpadd_f32(a10, a32), vpadd_f32(b10, b32)));
6712#endif
6713}
6714
6715// Horizontally subtract adjacent pairs of double-precision (64-bit)
6716// floating-point elements in a and b, and pack the results in dst.
6717// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_hsub_pd
6719{
6720#if defined(__aarch64__)
6721 float64x2_t a = vreinterpretq_f64_m128d(_a);
6722 float64x2_t b = vreinterpretq_f64_m128d(_b);
6723 return vreinterpretq_m128d_f64(
6724 vsubq_f64(vuzp1q_f64(a, b), vuzp2q_f64(a, b)));
6725#else
6726 double *da = (double *) &_a;
6727 double *db = (double *) &_b;
6728 double c[] = {da[0] - da[1], db[0] - db[1]};
6729 return vreinterpretq_m128d_u64(vld1q_u64((uint64_t *) c));
6730#endif
6731}
6732
6733// Horizontally subtract adjacent pairs of single-precision (32-bit)
6734// floating-point elements in a and b, and pack the results in dst.
6735// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_hsub_ps
6737{
6738 float32x4_t a = vreinterpretq_f32_m128(_a);
6739 float32x4_t b = vreinterpretq_f32_m128(_b);
6740#if defined(__aarch64__)
6742 vsubq_f32(vuzp1q_f32(a, b), vuzp2q_f32(a, b)));
6743#else
6744 float32x4x2_t c = vuzpq_f32(a, b);
6745 return vreinterpretq_m128_f32(vsubq_f32(c.val[0], c.val[1]));
6746#endif
6747}
6748
6749// Load 128-bits of integer data from unaligned memory into dst. This intrinsic
6750// may perform better than _mm_loadu_si128 when the data crosses a cache line
6751// boundary.
6752//
6753// dst[127:0] := MEM[mem_addr+127:mem_addr]
6754//
6755// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_lddqu_si128
6756#define _mm_lddqu_si128 _mm_loadu_si128
6757
6758// Load a double-precision (64-bit) floating-point element from memory into both
6759// elements of dst.
6760//
6761// dst[63:0] := MEM[mem_addr+63:mem_addr]
6762// dst[127:64] := MEM[mem_addr+63:mem_addr]
6763//
6764// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_loaddup_pd
6765#define _mm_loaddup_pd _mm_load1_pd
6766
6767// Duplicate the low double-precision (64-bit) floating-point element from a,
6768// and store the results in dst.
6769// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_movedup_pd
6771{
6772#if defined(__aarch64__)
6773 return vreinterpretq_m128d_f64(
6774 vdupq_laneq_f64(vreinterpretq_f64_m128d(a), 0));
6775#else
6777 vdupq_n_u64(vgetq_lane_u64(vreinterpretq_u64_m128d(a), 0)));
6778#endif
6779}
6780
6781// Duplicate odd-indexed single-precision (32-bit) floating-point elements
6782// from a, and store the results in dst.
6783// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_movehdup_ps
6785{
6786#if defined(__aarch64__)
6789#elif defined(_sse2neon_shuffle)
6790 return vreinterpretq_m128_f32(vshuffleq_s32(
6792#else
6793 float32_t a1 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 1);
6794 float32_t a3 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 3);
6795 float ALIGN_STRUCT(16) data[4] = {a1, a1, a3, a3};
6796 return vreinterpretq_m128_f32(vld1q_f32(data));
6797#endif
6798}
6799
6800// Duplicate even-indexed single-precision (32-bit) floating-point elements
6801// from a, and store the results in dst.
6802// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_moveldup_ps
6804{
6805#if defined(__aarch64__)
6808#elif defined(_sse2neon_shuffle)
6809 return vreinterpretq_m128_f32(vshuffleq_s32(
6811#else
6812 float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0);
6813 float32_t a2 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 2);
6814 float ALIGN_STRUCT(16) data[4] = {a0, a0, a2, a2};
6815 return vreinterpretq_m128_f32(vld1q_f32(data));
6816#endif
6817}
6818
6819/* SSSE3 */
6820
6821// Compute the absolute value of packed signed 16-bit integers in a, and store
6822// the unsigned results in dst.
6823//
6824// FOR j := 0 to 7
6825// i := j*16
6826// dst[i+15:i] := ABS(a[i+15:i])
6827// ENDFOR
6828//
6829// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_abs_epi16
6834
6835// Compute the absolute value of packed signed 32-bit integers in a, and store
6836// the unsigned results in dst.
6837//
6838// FOR j := 0 to 3
6839// i := j*32
6840// dst[i+31:i] := ABS(a[i+31:i])
6841// ENDFOR
6842//
6843// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_abs_epi32
6848
6849// Compute the absolute value of packed signed 8-bit integers in a, and store
6850// the unsigned results in dst.
6851//
6852// FOR j := 0 to 15
6853// i := j*8
6854// dst[i+7:i] := ABS(a[i+7:i])
6855// ENDFOR
6856//
6857// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_abs_epi8
6862
6863// Compute the absolute value of packed signed 16-bit integers in a, and store
6864// the unsigned results in dst.
6865//
6866// FOR j := 0 to 3
6867// i := j*16
6868// dst[i+15:i] := ABS(a[i+15:i])
6869// ENDFOR
6870//
6871// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_abs_pi16
6876
6877// Compute the absolute value of packed signed 32-bit integers in a, and store
6878// the unsigned results in dst.
6879//
6880// FOR j := 0 to 1
6881// i := j*32
6882// dst[i+31:i] := ABS(a[i+31:i])
6883// ENDFOR
6884//
6885// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_abs_pi32
6890
6891// Compute the absolute value of packed signed 8-bit integers in a, and store
6892// the unsigned results in dst.
6893//
6894// FOR j := 0 to 7
6895// i := j*8
6896// dst[i+7:i] := ABS(a[i+7:i])
6897// ENDFOR
6898//
6899// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_abs_pi8
6904
6905// Concatenate 16-byte blocks in a and b into a 32-byte temporary result, shift
6906// the result right by imm8 bytes, and store the low 16 bytes in dst.
6907//
6908// tmp[255:0] := ((a[127:0] << 128)[255:0] OR b[127:0]) >> (imm8*8)
6909// dst[127:0] := tmp[127:0]
6910//
6911// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_alignr_epi8
6912#define _mm_alignr_epi8(a, b, imm) \
6913 __extension__({ \
6914 uint8x16_t _a = vreinterpretq_u8_m128i(a); \
6915 uint8x16_t _b = vreinterpretq_u8_m128i(b); \
6916 __m128i ret; \
6917 if (_sse2neon_unlikely((imm) & ~31)) \
6918 ret = vreinterpretq_m128i_u8(vdupq_n_u8(0)); \
6919 else if (imm >= 16) \
6920 ret = _mm_srli_si128(a, imm >= 16 ? imm - 16 : 0); \
6921 else \
6922 ret = \
6923 vreinterpretq_m128i_u8(vextq_u8(_b, _a, imm < 16 ? imm : 0)); \
6924 ret; \
6925 })
6926
6927// Concatenate 8-byte blocks in a and b into a 16-byte temporary result, shift
6928// the result right by imm8 bytes, and store the low 8 bytes in dst.
6929//
6930// tmp[127:0] := ((a[63:0] << 64)[127:0] OR b[63:0]) >> (imm8*8)
6931// dst[63:0] := tmp[63:0]
6932//
6933// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_alignr_pi8
6934#define _mm_alignr_pi8(a, b, imm) \
6935 __extension__({ \
6936 __m64 ret; \
6937 if (_sse2neon_unlikely((imm) >= 16)) { \
6938 ret = vreinterpret_m64_s8(vdup_n_s8(0)); \
6939 } else { \
6940 uint8x8_t tmp_low, tmp_high; \
6941 if ((imm) >= 8) { \
6942 const int idx = (imm) -8; \
6943 tmp_low = vreinterpret_u8_m64(a); \
6944 tmp_high = vdup_n_u8(0); \
6945 ret = vreinterpret_m64_u8(vext_u8(tmp_low, tmp_high, idx)); \
6946 } else { \
6947 const int idx = (imm); \
6948 tmp_low = vreinterpret_u8_m64(b); \
6949 tmp_high = vreinterpret_u8_m64(a); \
6950 ret = vreinterpret_m64_u8(vext_u8(tmp_low, tmp_high, idx)); \
6951 } \
6952 } \
6953 ret; \
6954 })
6955
6956// Computes pairwise add of each argument as a 16-bit signed or unsigned integer
6957// values a and b.
6959{
6960 int16x8_t a = vreinterpretq_s16_m128i(_a);
6961 int16x8_t b = vreinterpretq_s16_m128i(_b);
6962#if defined(__aarch64__)
6963 return vreinterpretq_m128i_s16(vpaddq_s16(a, b));
6964#else
6966 vcombine_s16(vpadd_s16(vget_low_s16(a), vget_high_s16(a)),
6967 vpadd_s16(vget_low_s16(b), vget_high_s16(b))));
6968#endif
6969}
6970
6971// Computes pairwise add of each argument as a 32-bit signed or unsigned integer
6972// values a and b.
6974{
6975 int32x4_t a = vreinterpretq_s32_m128i(_a);
6976 int32x4_t b = vreinterpretq_s32_m128i(_b);
6977#if defined(__aarch64__)
6978 return vreinterpretq_m128i_s32(vpaddq_s32(a, b));
6979#else
6981 vcombine_s32(vpadd_s32(vget_low_s32(a), vget_high_s32(a)),
6982 vpadd_s32(vget_low_s32(b), vget_high_s32(b))));
6983#endif
6984}
6985
6986// Horizontally add adjacent pairs of 16-bit integers in a and b, and pack the
6987// signed 16-bit results in dst.
6988// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_hadd_pi16
6994
6995// Horizontally add adjacent pairs of 32-bit integers in a and b, and pack the
6996// signed 32-bit results in dst.
6997// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_hadd_pi32
7003
7004// Computes saturated pairwise sub of each argument as a 16-bit signed
7005// integer values a and b.
7007{
7008#if defined(__aarch64__)
7009 int16x8_t a = vreinterpretq_s16_m128i(_a);
7010 int16x8_t b = vreinterpretq_s16_m128i(_b);
7011 return vreinterpretq_s64_s16(
7012 vqaddq_s16(vuzp1q_s16(a, b), vuzp2q_s16(a, b)));
7013#else
7014 int32x4_t a = vreinterpretq_s32_m128i(_a);
7015 int32x4_t b = vreinterpretq_s32_m128i(_b);
7016 // Interleave using vshrn/vmovn
7017 // [a0|a2|a4|a6|b0|b2|b4|b6]
7018 // [a1|a3|a5|a7|b1|b3|b5|b7]
7019 int16x8_t ab0246 = vcombine_s16(vmovn_s32(a), vmovn_s32(b));
7020 int16x8_t ab1357 = vcombine_s16(vshrn_n_s32(a, 16), vshrn_n_s32(b, 16));
7021 // Saturated add
7022 return vreinterpretq_m128i_s16(vqaddq_s16(ab0246, ab1357));
7023#endif
7024}
7025
7026// Horizontally add adjacent pairs of signed 16-bit integers in a and b using
7027// saturation, and pack the signed 16-bit results in dst.
7028// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_hadds_pi16
7030{
7031 int16x4_t a = vreinterpret_s16_m64(_a);
7032 int16x4_t b = vreinterpret_s16_m64(_b);
7033#if defined(__aarch64__)
7034 return vreinterpret_s64_s16(vqadd_s16(vuzp1_s16(a, b), vuzp2_s16(a, b)));
7035#else
7036 int16x4x2_t res = vuzp_s16(a, b);
7037 return vreinterpret_s64_s16(vqadd_s16(res.val[0], res.val[1]));
7038#endif
7039}
7040
7041// Horizontally subtract adjacent pairs of 16-bit integers in a and b, and pack
7042// the signed 16-bit results in dst.
7043// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_hsub_epi16
7045{
7046 int16x8_t a = vreinterpretq_s16_m128i(_a);
7047 int16x8_t b = vreinterpretq_s16_m128i(_b);
7048#if defined(__aarch64__)
7050 vsubq_s16(vuzp1q_s16(a, b), vuzp2q_s16(a, b)));
7051#else
7052 int16x8x2_t c = vuzpq_s16(a, b);
7053 return vreinterpretq_m128i_s16(vsubq_s16(c.val[0], c.val[1]));
7054#endif
7055}
7056
7057// Horizontally subtract adjacent pairs of 32-bit integers in a and b, and pack
7058// the signed 32-bit results in dst.
7059// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_hsub_epi32
7061{
7062 int32x4_t a = vreinterpretq_s32_m128i(_a);
7063 int32x4_t b = vreinterpretq_s32_m128i(_b);
7064#if defined(__aarch64__)
7066 vsubq_s32(vuzp1q_s32(a, b), vuzp2q_s32(a, b)));
7067#else
7068 int32x4x2_t c = vuzpq_s32(a, b);
7069 return vreinterpretq_m128i_s32(vsubq_s32(c.val[0], c.val[1]));
7070#endif
7071}
7072
7073// Horizontally subtract adjacent pairs of 16-bit integers in a and b, and pack
7074// the signed 16-bit results in dst.
7075// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_hsub_pi16
7077{
7078 int16x4_t a = vreinterpret_s16_m64(_a);
7079 int16x4_t b = vreinterpret_s16_m64(_b);
7080#if defined(__aarch64__)
7081 return vreinterpret_m64_s16(vsub_s16(vuzp1_s16(a, b), vuzp2_s16(a, b)));
7082#else
7083 int16x4x2_t c = vuzp_s16(a, b);
7084 return vreinterpret_m64_s16(vsub_s16(c.val[0], c.val[1]));
7085#endif
7086}
7087
7088// Horizontally subtract adjacent pairs of 32-bit integers in a and b, and pack
7089// the signed 32-bit results in dst.
7090// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=mm_hsub_pi32
7092{
7093 int32x2_t a = vreinterpret_s32_m64(_a);
7094 int32x2_t b = vreinterpret_s32_m64(_b);
7095#if defined(__aarch64__)
7096 return vreinterpret_m64_s32(vsub_s32(vuzp1_s32(a, b), vuzp2_s32(a, b)));
7097#else
7098 int32x2x2_t c = vuzp_s32(a, b);
7099 return vreinterpret_m64_s32(vsub_s32(c.val[0], c.val[1]));
7100#endif
7101}
7102
7103// Computes saturated pairwise difference of each argument as a 16-bit signed
7104// integer values a and b.
7105// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_hsubs_epi16
7107{
7108 int16x8_t a = vreinterpretq_s16_m128i(_a);
7109 int16x8_t b = vreinterpretq_s16_m128i(_b);
7110#if defined(__aarch64__)
7112 vqsubq_s16(vuzp1q_s16(a, b), vuzp2q_s16(a, b)));
7113#else
7114 int16x8x2_t c = vuzpq_s16(a, b);
7115 return vreinterpretq_m128i_s16(vqsubq_s16(c.val[0], c.val[1]));
7116#endif
7117}
7118
7119// Horizontally subtract adjacent pairs of signed 16-bit integers in a and b
7120// using saturation, and pack the signed 16-bit results in dst.
7121// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_hsubs_pi16
7123{
7124 int16x4_t a = vreinterpret_s16_m64(_a);
7125 int16x4_t b = vreinterpret_s16_m64(_b);
7126#if defined(__aarch64__)
7127 return vreinterpret_m64_s16(vqsub_s16(vuzp1_s16(a, b), vuzp2_s16(a, b)));
7128#else
7129 int16x4x2_t c = vuzp_s16(a, b);
7130 return vreinterpret_m64_s16(vqsub_s16(c.val[0], c.val[1]));
7131#endif
7132}
7133
7134// Vertically multiply each unsigned 8-bit integer from a with the corresponding
7135// signed 8-bit integer from b, producing intermediate signed 16-bit integers.
7136// Horizontally add adjacent pairs of intermediate signed 16-bit integers,
7137// and pack the saturated results in dst.
7138//
7139// FOR j := 0 to 7
7140// i := j*16
7141// dst[i+15:i] := Saturate_To_Int16( a[i+15:i+8]*b[i+15:i+8] +
7142// a[i+7:i]*b[i+7:i] )
7143// ENDFOR
7145{
7146#if defined(__aarch64__)
7147 uint8x16_t a = vreinterpretq_u8_m128i(_a);
7148 int8x16_t b = vreinterpretq_s8_m128i(_b);
7149 int16x8_t tl = vmulq_s16(vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(a))),
7150 vmovl_s8(vget_low_s8(b)));
7151 int16x8_t th = vmulq_s16(vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(a))),
7152 vmovl_s8(vget_high_s8(b)));
7154 vqaddq_s16(vuzp1q_s16(tl, th), vuzp2q_s16(tl, th)));
7155#else
7156 // This would be much simpler if x86 would choose to zero extend OR sign
7157 // extend, not both. This could probably be optimized better.
7158 uint16x8_t a = vreinterpretq_u16_m128i(_a);
7159 int16x8_t b = vreinterpretq_s16_m128i(_b);
7160
7161 // Zero extend a
7162 int16x8_t a_odd = vreinterpretq_s16_u16(vshrq_n_u16(a, 8));
7163 int16x8_t a_even = vreinterpretq_s16_u16(vbicq_u16(a, vdupq_n_u16(0xff00)));
7164
7165 // Sign extend by shifting left then shifting right.
7166 int16x8_t b_even = vshrq_n_s16(vshlq_n_s16(b, 8), 8);
7167 int16x8_t b_odd = vshrq_n_s16(b, 8);
7168
7169 // multiply
7170 int16x8_t prod1 = vmulq_s16(a_even, b_even);
7171 int16x8_t prod2 = vmulq_s16(a_odd, b_odd);
7172
7173 // saturated add
7174 return vreinterpretq_m128i_s16(vqaddq_s16(prod1, prod2));
7175#endif
7176}
7177
7178// Vertically multiply each unsigned 8-bit integer from a with the corresponding
7179// signed 8-bit integer from b, producing intermediate signed 16-bit integers.
7180// Horizontally add adjacent pairs of intermediate signed 16-bit integers, and
7181// pack the saturated results in dst.
7182// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_maddubs_pi16
7184{
7185 uint16x4_t a = vreinterpret_u16_m64(_a);
7186 int16x4_t b = vreinterpret_s16_m64(_b);
7187
7188 // Zero extend a
7189 int16x4_t a_odd = vreinterpret_s16_u16(vshr_n_u16(a, 8));
7190 int16x4_t a_even = vreinterpret_s16_u16(vand_u16(a, vdup_n_u16(0xff)));
7191
7192 // Sign extend by shifting left then shifting right.
7193 int16x4_t b_even = vshr_n_s16(vshl_n_s16(b, 8), 8);
7194 int16x4_t b_odd = vshr_n_s16(b, 8);
7195
7196 // multiply
7197 int16x4_t prod1 = vmul_s16(a_even, b_even);
7198 int16x4_t prod2 = vmul_s16(a_odd, b_odd);
7199
7200 // saturated add
7201 return vreinterpret_m64_s16(vqadd_s16(prod1, prod2));
7202}
7203
7204// Multiply packed signed 16-bit integers in a and b, producing intermediate
7205// signed 32-bit integers. Shift right by 15 bits while rounding up, and store
7206// the packed 16-bit integers in dst.
7207//
7208// r0 := Round(((int32_t)a0 * (int32_t)b0) >> 15)
7209// r1 := Round(((int32_t)a1 * (int32_t)b1) >> 15)
7210// r2 := Round(((int32_t)a2 * (int32_t)b2) >> 15)
7211// ...
7212// r7 := Round(((int32_t)a7 * (int32_t)b7) >> 15)
7214{
7215 // Has issues due to saturation
7216 // return vreinterpretq_m128i_s16(vqrdmulhq_s16(a, b));
7217
7218 // Multiply
7219 int32x4_t mul_lo = vmull_s16(vget_low_s16(vreinterpretq_s16_m128i(a)),
7220 vget_low_s16(vreinterpretq_s16_m128i(b)));
7221 int32x4_t mul_hi = vmull_s16(vget_high_s16(vreinterpretq_s16_m128i(a)),
7222 vget_high_s16(vreinterpretq_s16_m128i(b)));
7223
7224 // Rounding narrowing shift right
7225 // narrow = (int16_t)((mul + 16384) >> 15);
7226 int16x4_t narrow_lo = vrshrn_n_s32(mul_lo, 15);
7227 int16x4_t narrow_hi = vrshrn_n_s32(mul_hi, 15);
7228
7229 // Join together
7230 return vreinterpretq_m128i_s16(vcombine_s16(narrow_lo, narrow_hi));
7231}
7232
7233// Multiply packed signed 16-bit integers in a and b, producing intermediate
7234// signed 32-bit integers. Truncate each intermediate integer to the 18 most
7235// significant bits, round by adding 1, and store bits [16:1] to dst.
7236// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mulhrs_pi16
7238{
7239 int32x4_t mul_extend =
7240 vmull_s16((vreinterpret_s16_m64(a)), (vreinterpret_s16_m64(b)));
7241
7242 // Rounding narrowing shift right
7243 return vreinterpret_m64_s16(vrshrn_n_s32(mul_extend, 15));
7244}
7245
7246// Shuffle packed 8-bit integers in a according to shuffle control mask in the
7247// corresponding 8-bit element of b, and store the results in dst.
7248// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_shuffle_epi8
7250{
7251 int8x16_t tbl = vreinterpretq_s8_m128i(a); // input a
7252 uint8x16_t idx = vreinterpretq_u8_m128i(b); // input b
7253 uint8x16_t idx_masked =
7254 vandq_u8(idx, vdupq_n_u8(0x8F)); // avoid using meaningless bits
7255#if defined(__aarch64__)
7256 return vreinterpretq_m128i_s8(vqtbl1q_s8(tbl, idx_masked));
7257#elif defined(__GNUC__)
7258 int8x16_t ret;
7259 // %e and %f represent the even and odd D registers
7260 // respectively.
7261 __asm__ __volatile__(
7262 "vtbl.8 %e[ret], {%e[tbl], %f[tbl]}, %e[idx]\n"
7263 "vtbl.8 %f[ret], {%e[tbl], %f[tbl]}, %f[idx]\n"
7264 : [ret] "=&w"(ret)
7265 : [tbl] "w"(tbl), [idx] "w"(idx_masked));
7266 return vreinterpretq_m128i_s8(ret);
7267#else
7268 // use this line if testing on aarch64
7269 int8x8x2_t a_split = {vget_low_s8(tbl), vget_high_s8(tbl)};
7271 vcombine_s8(vtbl2_s8(a_split, vget_low_u8(idx_masked)),
7272 vtbl2_s8(a_split, vget_high_u8(idx_masked))));
7273#endif
7274}
7275
7276// Shuffle packed 8-bit integers in a according to shuffle control mask in the
7277// corresponding 8-bit element of b, and store the results in dst.
7278//
7279// FOR j := 0 to 7
7280// i := j*8
7281// IF b[i+7] == 1
7282// dst[i+7:i] := 0
7283// ELSE
7284// index[2:0] := b[i+2:i]
7285// dst[i+7:i] := a[index*8+7:index*8]
7286// FI
7287// ENDFOR
7288//
7289// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_shuffle_pi8
7291{
7292 const int8x8_t controlMask =
7293 vand_s8(vreinterpret_s8_m64(b), vdup_n_s8((int8_t) (0x1 << 7 | 0x07)));
7294 int8x8_t res = vtbl1_s8(vreinterpret_s8_m64(a), controlMask);
7295 return vreinterpret_m64_s8(res);
7296}
7297
7298// Negate packed 16-bit integers in a when the corresponding signed
7299// 16-bit integer in b is negative, and store the results in dst.
7300// Element in dst are zeroed out when the corresponding element
7301// in b is zero.
7302//
7303// for i in 0..7
7304// if b[i] < 0
7305// r[i] := -a[i]
7306// else if b[i] == 0
7307// r[i] := 0
7308// else
7309// r[i] := a[i]
7310// fi
7311// done
7313{
7314 int16x8_t a = vreinterpretq_s16_m128i(_a);
7315 int16x8_t b = vreinterpretq_s16_m128i(_b);
7316
7317 // signed shift right: faster than vclt
7318 // (b < 0) ? 0xFFFF : 0
7319 uint16x8_t ltMask = vreinterpretq_u16_s16(vshrq_n_s16(b, 15));
7320 // (b == 0) ? 0xFFFF : 0
7321#if defined(__aarch64__)
7322 int16x8_t zeroMask = vreinterpretq_s16_u16(vceqzq_s16(b));
7323#else
7324 int16x8_t zeroMask = vreinterpretq_s16_u16(vceqq_s16(b, vdupq_n_s16(0)));
7325#endif
7326
7327 // bitwise select either a or negative 'a' (vnegq_s16(a) equals to negative
7328 // 'a') based on ltMask
7329 int16x8_t masked = vbslq_s16(ltMask, vnegq_s16(a), a);
7330 // res = masked & (~zeroMask)
7331 int16x8_t res = vbicq_s16(masked, zeroMask);
7332 return vreinterpretq_m128i_s16(res);
7333}
7334
7335// Negate packed 32-bit integers in a when the corresponding signed
7336// 32-bit integer in b is negative, and store the results in dst.
7337// Element in dst are zeroed out when the corresponding element
7338// in b is zero.
7339//
7340// for i in 0..3
7341// if b[i] < 0
7342// r[i] := -a[i]
7343// else if b[i] == 0
7344// r[i] := 0
7345// else
7346// r[i] := a[i]
7347// fi
7348// done
7350{
7351 int32x4_t a = vreinterpretq_s32_m128i(_a);
7352 int32x4_t b = vreinterpretq_s32_m128i(_b);
7353
7354 // signed shift right: faster than vclt
7355 // (b < 0) ? 0xFFFFFFFF : 0
7356 uint32x4_t ltMask = vreinterpretq_u32_s32(vshrq_n_s32(b, 31));
7357
7358 // (b == 0) ? 0xFFFFFFFF : 0
7359#if defined(__aarch64__)
7360 int32x4_t zeroMask = vreinterpretq_s32_u32(vceqzq_s32(b));
7361#else
7362 int32x4_t zeroMask = vreinterpretq_s32_u32(vceqq_s32(b, vdupq_n_s32(0)));
7363#endif
7364
7365 // bitwise select either a or negative 'a' (vnegq_s32(a) equals to negative
7366 // 'a') based on ltMask
7367 int32x4_t masked = vbslq_s32(ltMask, vnegq_s32(a), a);
7368 // res = masked & (~zeroMask)
7369 int32x4_t res = vbicq_s32(masked, zeroMask);
7370 return vreinterpretq_m128i_s32(res);
7371}
7372
7373// Negate packed 8-bit integers in a when the corresponding signed
7374// 8-bit integer in b is negative, and store the results in dst.
7375// Element in dst are zeroed out when the corresponding element
7376// in b is zero.
7377//
7378// for i in 0..15
7379// if b[i] < 0
7380// r[i] := -a[i]
7381// else if b[i] == 0
7382// r[i] := 0
7383// else
7384// r[i] := a[i]
7385// fi
7386// done
7388{
7389 int8x16_t a = vreinterpretq_s8_m128i(_a);
7390 int8x16_t b = vreinterpretq_s8_m128i(_b);
7391
7392 // signed shift right: faster than vclt
7393 // (b < 0) ? 0xFF : 0
7394 uint8x16_t ltMask = vreinterpretq_u8_s8(vshrq_n_s8(b, 7));
7395
7396 // (b == 0) ? 0xFF : 0
7397#if defined(__aarch64__)
7398 int8x16_t zeroMask = vreinterpretq_s8_u8(vceqzq_s8(b));
7399#else
7400 int8x16_t zeroMask = vreinterpretq_s8_u8(vceqq_s8(b, vdupq_n_s8(0)));
7401#endif
7402
7403 // bitwise select either a or negative 'a' (vnegq_s8(a) return negative 'a')
7404 // based on ltMask
7405 int8x16_t masked = vbslq_s8(ltMask, vnegq_s8(a), a);
7406 // res = masked & (~zeroMask)
7407 int8x16_t res = vbicq_s8(masked, zeroMask);
7408
7409 return vreinterpretq_m128i_s8(res);
7410}
7411
7412// Negate packed 16-bit integers in a when the corresponding signed 16-bit
7413// integer in b is negative, and store the results in dst. Element in dst are
7414// zeroed out when the corresponding element in b is zero.
7415//
7416// FOR j := 0 to 3
7417// i := j*16
7418// IF b[i+15:i] < 0
7419// dst[i+15:i] := -(a[i+15:i])
7420// ELSE IF b[i+15:i] == 0
7421// dst[i+15:i] := 0
7422// ELSE
7423// dst[i+15:i] := a[i+15:i]
7424// FI
7425// ENDFOR
7426//
7427// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sign_pi16
7429{
7430 int16x4_t a = vreinterpret_s16_m64(_a);
7431 int16x4_t b = vreinterpret_s16_m64(_b);
7432
7433 // signed shift right: faster than vclt
7434 // (b < 0) ? 0xFFFF : 0
7435 uint16x4_t ltMask = vreinterpret_u16_s16(vshr_n_s16(b, 15));
7436
7437 // (b == 0) ? 0xFFFF : 0
7438#if defined(__aarch64__)
7439 int16x4_t zeroMask = vreinterpret_s16_u16(vceqz_s16(b));
7440#else
7441 int16x4_t zeroMask = vreinterpret_s16_u16(vceq_s16(b, vdup_n_s16(0)));
7442#endif
7443
7444 // bitwise select either a or negative 'a' (vneg_s16(a) return negative 'a')
7445 // based on ltMask
7446 int16x4_t masked = vbsl_s16(ltMask, vneg_s16(a), a);
7447 // res = masked & (~zeroMask)
7448 int16x4_t res = vbic_s16(masked, zeroMask);
7449
7450 return vreinterpret_m64_s16(res);
7451}
7452
7453// Negate packed 32-bit integers in a when the corresponding signed 32-bit
7454// integer in b is negative, and store the results in dst. Element in dst are
7455// zeroed out when the corresponding element in b is zero.
7456//
7457// FOR j := 0 to 1
7458// i := j*32
7459// IF b[i+31:i] < 0
7460// dst[i+31:i] := -(a[i+31:i])
7461// ELSE IF b[i+31:i] == 0
7462// dst[i+31:i] := 0
7463// ELSE
7464// dst[i+31:i] := a[i+31:i]
7465// FI
7466// ENDFOR
7467//
7468// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sign_pi32
7470{
7471 int32x2_t a = vreinterpret_s32_m64(_a);
7472 int32x2_t b = vreinterpret_s32_m64(_b);
7473
7474 // signed shift right: faster than vclt
7475 // (b < 0) ? 0xFFFFFFFF : 0
7476 uint32x2_t ltMask = vreinterpret_u32_s32(vshr_n_s32(b, 31));
7477
7478 // (b == 0) ? 0xFFFFFFFF : 0
7479#if defined(__aarch64__)
7480 int32x2_t zeroMask = vreinterpret_s32_u32(vceqz_s32(b));
7481#else
7482 int32x2_t zeroMask = vreinterpret_s32_u32(vceq_s32(b, vdup_n_s32(0)));
7483#endif
7484
7485 // bitwise select either a or negative 'a' (vneg_s32(a) return negative 'a')
7486 // based on ltMask
7487 int32x2_t masked = vbsl_s32(ltMask, vneg_s32(a), a);
7488 // res = masked & (~zeroMask)
7489 int32x2_t res = vbic_s32(masked, zeroMask);
7490
7491 return vreinterpret_m64_s32(res);
7492}
7493
7494// Negate packed 8-bit integers in a when the corresponding signed 8-bit integer
7495// in b is negative, and store the results in dst. Element in dst are zeroed out
7496// when the corresponding element in b is zero.
7497//
7498// FOR j := 0 to 7
7499// i := j*8
7500// IF b[i+7:i] < 0
7501// dst[i+7:i] := -(a[i+7:i])
7502// ELSE IF b[i+7:i] == 0
7503// dst[i+7:i] := 0
7504// ELSE
7505// dst[i+7:i] := a[i+7:i]
7506// FI
7507// ENDFOR
7508//
7509// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sign_pi8
7511{
7512 int8x8_t a = vreinterpret_s8_m64(_a);
7513 int8x8_t b = vreinterpret_s8_m64(_b);
7514
7515 // signed shift right: faster than vclt
7516 // (b < 0) ? 0xFF : 0
7517 uint8x8_t ltMask = vreinterpret_u8_s8(vshr_n_s8(b, 7));
7518
7519 // (b == 0) ? 0xFF : 0
7520#if defined(__aarch64__)
7521 int8x8_t zeroMask = vreinterpret_s8_u8(vceqz_s8(b));
7522#else
7523 int8x8_t zeroMask = vreinterpret_s8_u8(vceq_s8(b, vdup_n_s8(0)));
7524#endif
7525
7526 // bitwise select either a or negative 'a' (vneg_s8(a) return negative 'a')
7527 // based on ltMask
7528 int8x8_t masked = vbsl_s8(ltMask, vneg_s8(a), a);
7529 // res = masked & (~zeroMask)
7530 int8x8_t res = vbic_s8(masked, zeroMask);
7531
7532 return vreinterpret_m64_s8(res);
7533}
7534
7535/* SSE4.1 */
7536
7537// Blend packed 16-bit integers from a and b using control mask imm8, and store
7538// the results in dst.
7539//
7540// FOR j := 0 to 7
7541// i := j*16
7542// IF imm8[j]
7543// dst[i+15:i] := b[i+15:i]
7544// ELSE
7545// dst[i+15:i] := a[i+15:i]
7546// FI
7547// ENDFOR
7548// FORCE_INLINE __m128i _mm_blend_epi16(__m128i a, __m128i b,
7549// __constrange(0,255) int imm)
7550#define _mm_blend_epi16(a, b, imm) \
7551 __extension__({ \
7552 const uint16_t _mask[8] = {((imm) & (1 << 0)) ? (uint16_t) -1 : 0x0, \
7553 ((imm) & (1 << 1)) ? (uint16_t) -1 : 0x0, \
7554 ((imm) & (1 << 2)) ? (uint16_t) -1 : 0x0, \
7555 ((imm) & (1 << 3)) ? (uint16_t) -1 : 0x0, \
7556 ((imm) & (1 << 4)) ? (uint16_t) -1 : 0x0, \
7557 ((imm) & (1 << 5)) ? (uint16_t) -1 : 0x0, \
7558 ((imm) & (1 << 6)) ? (uint16_t) -1 : 0x0, \
7559 ((imm) & (1 << 7)) ? (uint16_t) -1 : 0x0}; \
7560 uint16x8_t _mask_vec = vld1q_u16(_mask); \
7561 uint16x8_t _a = vreinterpretq_u16_m128i(a); \
7562 uint16x8_t _b = vreinterpretq_u16_m128i(b); \
7563 vreinterpretq_m128i_u16(vbslq_u16(_mask_vec, _b, _a)); \
7564 })
7565
7566// Blend packed double-precision (64-bit) floating-point elements from a and b
7567// using control mask imm8, and store the results in dst.
7568// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_blend_pd
7569#define _mm_blend_pd(a, b, imm) \
7570 __extension__({ \
7571 const uint64_t _mask[2] = { \
7572 ((imm) & (1 << 0)) ? ~UINT64_C(0) : UINT64_C(0), \
7573 ((imm) & (1 << 1)) ? ~UINT64_C(0) : UINT64_C(0)}; \
7574 uint64x2_t _mask_vec = vld1q_u64(_mask); \
7575 uint64x2_t _a = vreinterpretq_u64_m128d(a); \
7576 uint64x2_t _b = vreinterpretq_u64_m128d(b); \
7577 vreinterpretq_m128d_u64(vbslq_u64(_mask_vec, _b, _a)); \
7578 })
7579
7580// Blend packed single-precision (32-bit) floating-point elements from a and b
7581// using mask, and store the results in dst.
7582// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_blend_ps
7584{
7585 const uint32_t ALIGN_STRUCT(16)
7586 data[4] = {((imm8) & (1 << 0)) ? UINT32_MAX : 0,
7587 ((imm8) & (1 << 1)) ? UINT32_MAX : 0,
7588 ((imm8) & (1 << 2)) ? UINT32_MAX : 0,
7589 ((imm8) & (1 << 3)) ? UINT32_MAX : 0};
7590 uint32x4_t mask = vld1q_u32(data);
7591 float32x4_t a = vreinterpretq_f32_m128(_a);
7592 float32x4_t b = vreinterpretq_f32_m128(_b);
7593 return vreinterpretq_m128_f32(vbslq_f32(mask, b, a));
7594}
7595
7596// Blend packed 8-bit integers from a and b using mask, and store the results in
7597// dst.
7598//
7599// FOR j := 0 to 15
7600// i := j*8
7601// IF mask[i+7]
7602// dst[i+7:i] := b[i+7:i]
7603// ELSE
7604// dst[i+7:i] := a[i+7:i]
7605// FI
7606// ENDFOR
7608{
7609 // Use a signed shift right to create a mask with the sign bit
7610 uint8x16_t mask =
7611 vreinterpretq_u8_s8(vshrq_n_s8(vreinterpretq_s8_m128i(_mask), 7));
7612 uint8x16_t a = vreinterpretq_u8_m128i(_a);
7613 uint8x16_t b = vreinterpretq_u8_m128i(_b);
7614 return vreinterpretq_m128i_u8(vbslq_u8(mask, b, a));
7615}
7616
7617// Blend packed double-precision (64-bit) floating-point elements from a and b
7618// using mask, and store the results in dst.
7619// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_blendv_pd
7621{
7622 uint64x2_t mask =
7623 vreinterpretq_u64_s64(vshrq_n_s64(vreinterpretq_s64_m128d(_mask), 63));
7624#if defined(__aarch64__)
7625 float64x2_t a = vreinterpretq_f64_m128d(_a);
7626 float64x2_t b = vreinterpretq_f64_m128d(_b);
7627 return vreinterpretq_m128d_f64(vbslq_f64(mask, b, a));
7628#else
7629 uint64x2_t a = vreinterpretq_u64_m128d(_a);
7630 uint64x2_t b = vreinterpretq_u64_m128d(_b);
7631 return vreinterpretq_m128d_u64(vbslq_u64(mask, b, a));
7632#endif
7633}
7634
7635// Blend packed single-precision (32-bit) floating-point elements from a and b
7636// using mask, and store the results in dst.
7637// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_blendv_ps
7639{
7640 // Use a signed shift right to create a mask with the sign bit
7641 uint32x4_t mask =
7642 vreinterpretq_u32_s32(vshrq_n_s32(vreinterpretq_s32_m128(_mask), 31));
7643 float32x4_t a = vreinterpretq_f32_m128(_a);
7644 float32x4_t b = vreinterpretq_f32_m128(_b);
7645 return vreinterpretq_m128_f32(vbslq_f32(mask, b, a));
7646}
7647
7648// Round the packed double-precision (64-bit) floating-point elements in a up
7649// to an integer value, and store the results as packed double-precision
7650// floating-point elements in dst.
7651// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_ceil_pd
7653{
7654#if defined(__aarch64__)
7655 return vreinterpretq_m128d_f64(vrndpq_f64(vreinterpretq_f64_m128d(a)));
7656#else
7657 double *f = (double *) &a;
7658 return _mm_set_pd(ceil(f[1]), ceil(f[0]));
7659#endif
7660}
7661
7662// Round the packed single-precision (32-bit) floating-point elements in a up to
7663// an integer value, and store the results as packed single-precision
7664// floating-point elements in dst.
7665// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_ceil_ps
7667{
7668#if defined(__aarch64__) || defined(__ARM_FEATURE_DIRECTED_ROUNDING)
7669 return vreinterpretq_m128_f32(vrndpq_f32(vreinterpretq_f32_m128(a)));
7670#else
7671 float *f = (float *) &a;
7672 return _mm_set_ps(ceilf(f[3]), ceilf(f[2]), ceilf(f[1]), ceilf(f[0]));
7673#endif
7674}
7675
7676// Round the lower double-precision (64-bit) floating-point element in b up to
7677// an integer value, store the result as a double-precision floating-point
7678// element in the lower element of dst, and copy the upper element from a to the
7679// upper element of dst.
7680// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_ceil_sd
7685
7686// Round the lower single-precision (32-bit) floating-point element in b up to
7687// an integer value, store the result as a single-precision floating-point
7688// element in the lower element of dst, and copy the upper 3 packed elements
7689// from a to the upper elements of dst.
7690//
7691// dst[31:0] := CEIL(b[31:0])
7692// dst[127:32] := a[127:32]
7693//
7694// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_ceil_ss
7699
7700// Compare packed 64-bit integers in a and b for equality, and store the results
7701// in dst
7703{
7704#if defined(__aarch64__)
7707#else
7708 // ARMv7 lacks vceqq_u64
7709 // (a == b) -> (a_lo == b_lo) && (a_hi == b_hi)
7710 uint32x4_t cmp =
7712 uint32x4_t swapped = vrev64q_u32(cmp);
7713 return vreinterpretq_m128i_u32(vandq_u32(cmp, swapped));
7714#endif
7715}
7716
7717// Converts the four signed 16-bit integers in the lower 64 bits to four signed
7718// 32-bit integers.
7720{
7722 vmovl_s16(vget_low_s16(vreinterpretq_s16_m128i(a))));
7723}
7724
7725// Converts the two signed 16-bit integers in the lower 32 bits two signed
7726// 32-bit integers.
7728{
7729 int16x8_t s16x8 = vreinterpretq_s16_m128i(a); /* xxxx xxxx xxxx 0B0A */
7730 int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000x 000x 000B 000A */
7731 int64x2_t s64x2 = vmovl_s32(vget_low_s32(s32x4)); /* 0000 000B 0000 000A */
7732 return vreinterpretq_m128i_s64(s64x2);
7733}
7734
7735// Converts the two signed 32-bit integers in the lower 64 bits to two signed
7736// 64-bit integers.
7738{
7740 vmovl_s32(vget_low_s32(vreinterpretq_s32_m128i(a))));
7741}
7742
7743// Converts the four unsigned 8-bit integers in the lower 16 bits to four
7744// unsigned 32-bit integers.
7746{
7747 int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx DCBA */
7748 int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0D0C 0B0A */
7749 return vreinterpretq_m128i_s16(s16x8);
7750}
7751
7752// Converts the four unsigned 8-bit integers in the lower 32 bits to four
7753// unsigned 32-bit integers.
7755{
7756 int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx DCBA */
7757 int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0D0C 0B0A */
7758 int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000D 000C 000B 000A */
7759 return vreinterpretq_m128i_s32(s32x4);
7760}
7761
7762// Converts the two signed 8-bit integers in the lower 32 bits to four
7763// signed 64-bit integers.
7765{
7766 int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx xxBA */
7767 int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0x0x 0B0A */
7768 int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000x 000x 000B 000A */
7769 int64x2_t s64x2 = vmovl_s32(vget_low_s32(s32x4)); /* 0000 000B 0000 000A */
7770 return vreinterpretq_m128i_s64(s64x2);
7771}
7772
7773// Converts the four unsigned 16-bit integers in the lower 64 bits to four
7774// unsigned 32-bit integers.
7776{
7778 vmovl_u16(vget_low_u16(vreinterpretq_u16_m128i(a))));
7779}
7780
7781// Converts the two unsigned 16-bit integers in the lower 32 bits to two
7782// unsigned 64-bit integers.
7784{
7785 uint16x8_t u16x8 = vreinterpretq_u16_m128i(a); /* xxxx xxxx xxxx 0B0A */
7786 uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000x 000x 000B 000A */
7787 uint64x2_t u64x2 = vmovl_u32(vget_low_u32(u32x4)); /* 0000 000B 0000 000A */
7788 return vreinterpretq_m128i_u64(u64x2);
7789}
7790
7791// Converts the two unsigned 32-bit integers in the lower 64 bits to two
7792// unsigned 64-bit integers.
7794{
7796 vmovl_u32(vget_low_u32(vreinterpretq_u32_m128i(a))));
7797}
7798
7799// Zero extend packed unsigned 8-bit integers in a to packed 16-bit integers,
7800// and store the results in dst.
7801// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtepu8_epi16
7803{
7804 uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx HGFE DCBA */
7805 uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0H0G 0F0E 0D0C 0B0A */
7806 return vreinterpretq_m128i_u16(u16x8);
7807}
7808
7809// Converts the four unsigned 8-bit integers in the lower 32 bits to four
7810// unsigned 32-bit integers.
7811// https://msdn.microsoft.com/en-us/library/bb531467%28v=vs.100%29.aspx
7813{
7814 uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx xxxx DCBA */
7815 uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0D0C 0B0A */
7816 uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000D 000C 000B 000A */
7817 return vreinterpretq_m128i_u32(u32x4);
7818}
7819
7820// Converts the two unsigned 8-bit integers in the lower 16 bits to two
7821// unsigned 64-bit integers.
7823{
7824 uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx xxxx xxBA */
7825 uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0x0x 0B0A */
7826 uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000x 000x 000B 000A */
7827 uint64x2_t u64x2 = vmovl_u32(vget_low_u32(u32x4)); /* 0000 000B 0000 000A */
7828 return vreinterpretq_m128i_u64(u64x2);
7829}
7830
7831// Conditionally multiply the packed double-precision (64-bit) floating-point
7832// elements in a and b using the high 4 bits in imm8, sum the four products, and
7833// conditionally store the sum in dst using the low 4 bits of imm8.
7834// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_dp_pd
7836{
7837 // Generate mask value from constant immediate bit value
7838 const int64_t bit0Mask = imm & 0x01 ? UINT64_MAX : 0;
7839 const int64_t bit1Mask = imm & 0x02 ? UINT64_MAX : 0;
7840#if !SSE2NEON_PRECISE_DP
7841 const int64_t bit4Mask = imm & 0x10 ? UINT64_MAX : 0;
7842 const int64_t bit5Mask = imm & 0x20 ? UINT64_MAX : 0;
7843#endif
7844 // Conditional multiplication
7845#if !SSE2NEON_PRECISE_DP
7846 __m128d mul = _mm_mul_pd(a, b);
7847 const __m128d mulMask =
7848 _mm_castsi128_pd(_mm_set_epi64x(bit5Mask, bit4Mask));
7849 __m128d tmp = _mm_and_pd(mul, mulMask);
7850#else
7851#if defined(__aarch64__)
7852 double d0 = (imm & 0x10) ? vgetq_lane_f64(vreinterpretq_f64_m128d(a), 0) *
7853 vgetq_lane_f64(vreinterpretq_f64_m128d(b), 0)
7854 : 0;
7855 double d1 = (imm & 0x20) ? vgetq_lane_f64(vreinterpretq_f64_m128d(a), 1) *
7856 vgetq_lane_f64(vreinterpretq_f64_m128d(b), 1)
7857 : 0;
7858#else
7859 double d0 = (imm & 0x10) ? ((double *) &a)[0] * ((double *) &b)[0] : 0;
7860 double d1 = (imm & 0x20) ? ((double *) &a)[1] * ((double *) &b)[1] : 0;
7861#endif
7862 __m128d tmp = _mm_set_pd(d1, d0);
7863#endif
7864 // Sum the products
7865#if defined(__aarch64__)
7866 double sum = vpaddd_f64(vreinterpretq_f64_m128d(tmp));
7867#else
7868 double sum = *((double *) &tmp) + *(((double *) &tmp) + 1);
7869#endif
7870 // Conditionally store the sum
7871 const __m128d sumMask =
7872 _mm_castsi128_pd(_mm_set_epi64x(bit1Mask, bit0Mask));
7873 __m128d res = _mm_and_pd(_mm_set_pd1(sum), sumMask);
7874 return res;
7875}
7876
7877// Conditionally multiply the packed single-precision (32-bit) floating-point
7878// elements in a and b using the high 4 bits in imm8, sum the four products,
7879// and conditionally store the sum in dst using the low 4 bits of imm.
7880// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_dp_ps
7882{
7883#if defined(__aarch64__)
7884 /* shortcuts */
7885 if (imm == 0xFF) {
7886 return _mm_set1_ps(vaddvq_f32(_mm_mul_ps(a, b)));
7887 }
7888 if (imm == 0x7F) {
7889 float32x4_t m = _mm_mul_ps(a, b);
7890 m[3] = 0;
7891 return _mm_set1_ps(vaddvq_f32(m));
7892 }
7893#endif
7894
7895 float s = 0, c = 0;
7896 float32x4_t f32a = vreinterpretq_f32_m128(a);
7897 float32x4_t f32b = vreinterpretq_f32_m128(b);
7898
7899 /* To improve the accuracy of floating-point summation, Kahan algorithm
7900 * is used for each operation.
7901 */
7902 if (imm & (1 << 4))
7903 _sse2neon_kadd_f32(&s, &c, f32a[0] * f32b[0]);
7904 if (imm & (1 << 5))
7905 _sse2neon_kadd_f32(&s, &c, f32a[1] * f32b[1]);
7906 if (imm & (1 << 6))
7907 _sse2neon_kadd_f32(&s, &c, f32a[2] * f32b[2]);
7908 if (imm & (1 << 7))
7909 _sse2neon_kadd_f32(&s, &c, f32a[3] * f32b[3]);
7910 s += c;
7911
7912 float32x4_t res = {
7913 (imm & 0x1) ? s : 0,
7914 (imm & 0x2) ? s : 0,
7915 (imm & 0x4) ? s : 0,
7916 (imm & 0x8) ? s : 0,
7917 };
7918 return vreinterpretq_m128_f32(res);
7919}
7920
7921// Extracts the selected signed or unsigned 32-bit integer from a and zero
7922// extends.
7923// FORCE_INLINE int _mm_extract_epi32(__m128i a, __constrange(0,4) int imm)
7924#define _mm_extract_epi32(a, imm) \
7925 vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm))
7926
7927// Extracts the selected signed or unsigned 64-bit integer from a and zero
7928// extends.
7929// FORCE_INLINE __int64 _mm_extract_epi64(__m128i a, __constrange(0,2) int imm)
7930#define _mm_extract_epi64(a, imm) \
7931 vgetq_lane_s64(vreinterpretq_s64_m128i(a), (imm))
7932
7933// Extracts the selected signed or unsigned 8-bit integer from a and zero
7934// extends.
7935// FORCE_INLINE int _mm_extract_epi8(__m128i a, __constrange(0,16) int imm)
7936// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_extract_epi8
7937#define _mm_extract_epi8(a, imm) vgetq_lane_u8(vreinterpretq_u8_m128i(a), (imm))
7938
7939// Extracts the selected single-precision (32-bit) floating-point from a.
7940// FORCE_INLINE int _mm_extract_ps(__m128 a, __constrange(0,4) int imm)
7941#define _mm_extract_ps(a, imm) vgetq_lane_s32(vreinterpretq_s32_m128(a), (imm))
7942
7943// Round the packed double-precision (64-bit) floating-point elements in a down
7944// to an integer value, and store the results as packed double-precision
7945// floating-point elements in dst.
7946// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_floor_pd
7948{
7949#if defined(__aarch64__)
7950 return vreinterpretq_m128d_f64(vrndmq_f64(vreinterpretq_f64_m128d(a)));
7951#else
7952 double *f = (double *) &a;
7953 return _mm_set_pd(floor(f[1]), floor(f[0]));
7954#endif
7955}
7956
7957// Round the packed single-precision (32-bit) floating-point elements in a down
7958// to an integer value, and store the results as packed single-precision
7959// floating-point elements in dst.
7960// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_floor_ps
7962{
7963#if defined(__aarch64__) || defined(__ARM_FEATURE_DIRECTED_ROUNDING)
7964 return vreinterpretq_m128_f32(vrndmq_f32(vreinterpretq_f32_m128(a)));
7965#else
7966 float *f = (float *) &a;
7967 return _mm_set_ps(floorf(f[3]), floorf(f[2]), floorf(f[1]), floorf(f[0]));
7968#endif
7969}
7970
7971// Round the lower double-precision (64-bit) floating-point element in b down to
7972// an integer value, store the result as a double-precision floating-point
7973// element in the lower element of dst, and copy the upper element from a to the
7974// upper element of dst.
7975// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_floor_sd
7980
7981// Round the lower single-precision (32-bit) floating-point element in b down to
7982// an integer value, store the result as a single-precision floating-point
7983// element in the lower element of dst, and copy the upper 3 packed elements
7984// from a to the upper elements of dst.
7985//
7986// dst[31:0] := FLOOR(b[31:0])
7987// dst[127:32] := a[127:32]
7988//
7989// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_floor_ss
7994
7995// Inserts the least significant 32 bits of b into the selected 32-bit integer
7996// of a.
7997// FORCE_INLINE __m128i _mm_insert_epi32(__m128i a, int b,
7998// __constrange(0,4) int imm)
7999#define _mm_insert_epi32(a, b, imm) \
8000 __extension__({ \
8001 vreinterpretq_m128i_s32( \
8002 vsetq_lane_s32((b), vreinterpretq_s32_m128i(a), (imm))); \
8003 })
8004
8005// Inserts the least significant 64 bits of b into the selected 64-bit integer
8006// of a.
8007// FORCE_INLINE __m128i _mm_insert_epi64(__m128i a, __int64 b,
8008// __constrange(0,2) int imm)
8009#define _mm_insert_epi64(a, b, imm) \
8010 __extension__({ \
8011 vreinterpretq_m128i_s64( \
8012 vsetq_lane_s64((b), vreinterpretq_s64_m128i(a), (imm))); \
8013 })
8014
8015// Inserts the least significant 8 bits of b into the selected 8-bit integer
8016// of a.
8017// FORCE_INLINE __m128i _mm_insert_epi8(__m128i a, int b,
8018// __constrange(0,16) int imm)
8019#define _mm_insert_epi8(a, b, imm) \
8020 __extension__({ \
8021 vreinterpretq_m128i_s8( \
8022 vsetq_lane_s8((b), vreinterpretq_s8_m128i(a), (imm))); \
8023 })
8024
8025// Copy a to tmp, then insert a single-precision (32-bit) floating-point
8026// element from b into tmp using the control in imm8. Store tmp to dst using
8027// the mask in imm8 (elements are zeroed out when the corresponding bit is set).
8028// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=insert_ps
8029#define _mm_insert_ps(a, b, imm8) \
8030 __extension__({ \
8031 float32x4_t tmp1 = \
8032 vsetq_lane_f32(vgetq_lane_f32(b, (imm8 >> 6) & 0x3), \
8033 vreinterpretq_f32_m128(a), 0); \
8034 float32x4_t tmp2 = \
8035 vsetq_lane_f32(vgetq_lane_f32(tmp1, 0), vreinterpretq_f32_m128(a), \
8036 ((imm8 >> 4) & 0x3)); \
8037 const uint32_t data[4] = {((imm8) & (1 << 0)) ? UINT32_MAX : 0, \
8038 ((imm8) & (1 << 1)) ? UINT32_MAX : 0, \
8039 ((imm8) & (1 << 2)) ? UINT32_MAX : 0, \
8040 ((imm8) & (1 << 3)) ? UINT32_MAX : 0}; \
8041 uint32x4_t mask = vld1q_u32(data); \
8042 float32x4_t all_zeros = vdupq_n_f32(0); \
8043 \
8044 vreinterpretq_m128_f32( \
8045 vbslq_f32(mask, all_zeros, vreinterpretq_f32_m128(tmp2))); \
8046 })
8047
8048// epi versions of min/max
8049// Computes the pariwise maximums of the four signed 32-bit integer values of a
8050// and b.
8051//
8052// A 128-bit parameter that can be defined with the following equations:
8053// r0 := (a0 > b0) ? a0 : b0
8054// r1 := (a1 > b1) ? a1 : b1
8055// r2 := (a2 > b2) ? a2 : b2
8056// r3 := (a3 > b3) ? a3 : b3
8057//
8058// https://msdn.microsoft.com/en-us/library/vstudio/bb514055(v=vs.100).aspx
8064
8065// Compare packed signed 8-bit integers in a and b, and store packed maximum
8066// values in dst.
8067// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_max_epi8
8073
8074// Compare packed unsigned 16-bit integers in a and b, and store packed maximum
8075// values in dst.
8076// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_max_epu16
8082
8083// Compare packed unsigned 32-bit integers in a and b, and store packed maximum
8084// values in dst.
8085// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_max_epu32
8091
8092// Computes the pariwise minima of the four signed 32-bit integer values of a
8093// and b.
8094//
8095// A 128-bit parameter that can be defined with the following equations:
8096// r0 := (a0 < b0) ? a0 : b0
8097// r1 := (a1 < b1) ? a1 : b1
8098// r2 := (a2 < b2) ? a2 : b2
8099// r3 := (a3 < b3) ? a3 : b3
8100//
8101// https://msdn.microsoft.com/en-us/library/vstudio/bb531476(v=vs.100).aspx
8107
8108// Compare packed signed 8-bit integers in a and b, and store packed minimum
8109// values in dst.
8110// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_min_epi8
8116
8117// Compare packed unsigned 16-bit integers in a and b, and store packed minimum
8118// values in dst.
8119// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_min_epu16
8125
8126// Compare packed unsigned 32-bit integers in a and b, and store packed minimum
8127// values in dst.
8128// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_max_epu32
8134
8135// Horizontally compute the minimum amongst the packed unsigned 16-bit integers
8136// in a, store the minimum and index in dst, and zero the remaining bits in dst.
8137//
8138// index[2:0] := 0
8139// min[15:0] := a[15:0]
8140// FOR j := 0 to 7
8141// i := j*16
8142// IF a[i+15:i] < min[15:0]
8143// index[2:0] := j
8144// min[15:0] := a[i+15:i]
8145// FI
8146// ENDFOR
8147// dst[15:0] := min[15:0]
8148// dst[18:16] := index[2:0]
8149// dst[127:19] := 0
8150//
8151// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_minpos_epu16
8153{
8154 __m128i dst;
8155 uint16_t min, idx = 0;
8156#if defined(__aarch64__)
8157 // Find the minimum value
8158 min = vminvq_u16(vreinterpretq_u16_m128i(a));
8159
8160 // Get the index of the minimum value
8161 static const uint16_t idxv[] = {0, 1, 2, 3, 4, 5, 6, 7};
8162 uint16x8_t minv = vdupq_n_u16(min);
8163 uint16x8_t cmeq = vceqq_u16(minv, vreinterpretq_u16_m128i(a));
8164 idx = vminvq_u16(vornq_u16(vld1q_u16(idxv), cmeq));
8165#else
8166 // Find the minimum value
8167 __m64 tmp;
8169 vmin_u16(vget_low_u16(vreinterpretq_u16_m128i(a)),
8170 vget_high_u16(vreinterpretq_u16_m128i(a))));
8172 vpmin_u16(vreinterpret_u16_m64(tmp), vreinterpret_u16_m64(tmp)));
8174 vpmin_u16(vreinterpret_u16_m64(tmp), vreinterpret_u16_m64(tmp)));
8175 min = vget_lane_u16(vreinterpret_u16_m64(tmp), 0);
8176 // Get the index of the minimum value
8177 int i;
8178 for (i = 0; i < 8; i++) {
8179 if (min == vgetq_lane_u16(vreinterpretq_u16_m128i(a), 0)) {
8180 idx = (uint16_t) i;
8181 break;
8182 }
8183 a = _mm_srli_si128(a, 2);
8184 }
8185#endif
8186 // Generate result
8187 dst = _mm_setzero_si128();
8189 vsetq_lane_u16(min, vreinterpretq_u16_m128i(dst), 0));
8191 vsetq_lane_u16(idx, vreinterpretq_u16_m128i(dst), 1));
8192 return dst;
8193}
8194
8195// Compute the sum of absolute differences (SADs) of quadruplets of unsigned
8196// 8-bit integers in a compared to those in b, and store the 16-bit results in
8197// dst. Eight SADs are performed using one quadruplet from b and eight
8198// quadruplets from a. One quadruplet is selected from b starting at on the
8199// offset specified in imm8. Eight quadruplets are formed from sequential 8-bit
8200// integers selected from a starting at the offset specified in imm8.
8201// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mpsadbw_epu8
8203{
8204 uint8x16_t _a, _b;
8205
8206 switch (imm & 0x4) {
8207 case 0:
8208 // do nothing
8209 _a = vreinterpretq_u8_m128i(a);
8210 break;
8211 case 4:
8212 _a = vreinterpretq_u8_u32(vextq_u32(vreinterpretq_u32_m128i(a),
8214 break;
8215 default:
8216#if defined(__GNUC__) || defined(__clang__)
8217 __builtin_unreachable();
8218#endif
8219 break;
8220 }
8221
8222 switch (imm & 0x3) {
8223 case 0:
8224 _b = vreinterpretq_u8_u32(
8225 vdupq_n_u32(vgetq_lane_u32(vreinterpretq_u32_m128i(b), 0)));
8226 break;
8227 case 1:
8228 _b = vreinterpretq_u8_u32(
8229 vdupq_n_u32(vgetq_lane_u32(vreinterpretq_u32_m128i(b), 1)));
8230 break;
8231 case 2:
8232 _b = vreinterpretq_u8_u32(
8233 vdupq_n_u32(vgetq_lane_u32(vreinterpretq_u32_m128i(b), 2)));
8234 break;
8235 case 3:
8236 _b = vreinterpretq_u8_u32(
8237 vdupq_n_u32(vgetq_lane_u32(vreinterpretq_u32_m128i(b), 3)));
8238 break;
8239 default:
8240#if defined(__GNUC__) || defined(__clang__)
8241 __builtin_unreachable();
8242#endif
8243 break;
8244 }
8245
8246 int16x8_t c04, c15, c26, c37;
8247 uint8x8_t low_b = vget_low_u8(_b);
8248 c04 = vreinterpretq_s16_u16(vabdl_u8(vget_low_u8(_a), low_b));
8249 uint8x16_t _a_1 = vextq_u8(_a, _a, 1);
8250 c15 = vreinterpretq_s16_u16(vabdl_u8(vget_low_u8(_a_1), low_b));
8251 uint8x16_t _a_2 = vextq_u8(_a, _a, 2);
8252 c26 = vreinterpretq_s16_u16(vabdl_u8(vget_low_u8(_a_2), low_b));
8253 uint8x16_t _a_3 = vextq_u8(_a, _a, 3);
8254 c37 = vreinterpretq_s16_u16(vabdl_u8(vget_low_u8(_a_3), low_b));
8255#if defined(__aarch64__)
8256 // |0|4|2|6|
8257 c04 = vpaddq_s16(c04, c26);
8258 // |1|5|3|7|
8259 c15 = vpaddq_s16(c15, c37);
8260
8261 int32x4_t trn1_c =
8262 vtrn1q_s32(vreinterpretq_s32_s16(c04), vreinterpretq_s32_s16(c15));
8263 int32x4_t trn2_c =
8264 vtrn2q_s32(vreinterpretq_s32_s16(c04), vreinterpretq_s32_s16(c15));
8265 return vreinterpretq_m128i_s16(vpaddq_s16(vreinterpretq_s16_s32(trn1_c),
8266 vreinterpretq_s16_s32(trn2_c)));
8267#else
8268 int16x4_t c01, c23, c45, c67;
8269 c01 = vpadd_s16(vget_low_s16(c04), vget_low_s16(c15));
8270 c23 = vpadd_s16(vget_low_s16(c26), vget_low_s16(c37));
8271 c45 = vpadd_s16(vget_high_s16(c04), vget_high_s16(c15));
8272 c67 = vpadd_s16(vget_high_s16(c26), vget_high_s16(c37));
8273
8275 vcombine_s16(vpadd_s16(c01, c23), vpadd_s16(c45, c67)));
8276#endif
8277}
8278
8279// Multiply the low signed 32-bit integers from each packed 64-bit element in
8280// a and b, and store the signed 64-bit results in dst.
8281//
8282// r0 := (int64_t)(int32_t)a0 * (int64_t)(int32_t)b0
8283// r1 := (int64_t)(int32_t)a2 * (int64_t)(int32_t)b2
8285{
8286 // vmull_s32 upcasts instead of masking, so we downcast.
8287 int32x2_t a_lo = vmovn_s64(vreinterpretq_s64_m128i(a));
8288 int32x2_t b_lo = vmovn_s64(vreinterpretq_s64_m128i(b));
8289 return vreinterpretq_m128i_s64(vmull_s32(a_lo, b_lo));
8290}
8291
8292// Multiplies the 4 signed or unsigned 32-bit integers from a by the 4 signed or
8293// unsigned 32-bit integers from b.
8294// https://msdn.microsoft.com/en-us/library/vstudio/bb531409(v=vs.100).aspx
8300
8301// Packs the 8 unsigned 32-bit integers from a and b into unsigned 16-bit
8302// integers and saturates.
8303//
8304// r0 := UnsignedSaturate(a0)
8305// r1 := UnsignedSaturate(a1)
8306// r2 := UnsignedSaturate(a2)
8307// r3 := UnsignedSaturate(a3)
8308// r4 := UnsignedSaturate(b0)
8309// r5 := UnsignedSaturate(b1)
8310// r6 := UnsignedSaturate(b2)
8311// r7 := UnsignedSaturate(b3)
8313{
8315 vcombine_u16(vqmovun_s32(vreinterpretq_s32_m128i(a)),
8316 vqmovun_s32(vreinterpretq_s32_m128i(b))));
8317}
8318
8319// Round the packed double-precision (64-bit) floating-point elements in a using
8320// the rounding parameter, and store the results as packed double-precision
8321// floating-point elements in dst.
8322// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_round_pd
8324{
8325#if defined(__aarch64__)
8326 switch (rounding) {
8328 return vreinterpretq_m128d_f64(vrndnq_f64(vreinterpretq_f64_m128d(a)));
8330 return _mm_floor_pd(a);
8332 return _mm_ceil_pd(a);
8334 return vreinterpretq_m128d_f64(vrndq_f64(vreinterpretq_f64_m128d(a)));
8335 default: //_MM_FROUND_CUR_DIRECTION
8336 return vreinterpretq_m128d_f64(vrndiq_f64(vreinterpretq_f64_m128d(a)));
8337 }
8338#else
8339 double *v_double = (double *) &a;
8340
8341 if (rounding == (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC) ||
8342 (rounding == _MM_FROUND_CUR_DIRECTION &&
8344 double res[2], tmp;
8345 for (int i = 0; i < 2; i++) {
8346 tmp = (v_double[i] < 0) ? -v_double[i] : v_double[i];
8347 double roundDown = floor(tmp); // Round down value
8348 double roundUp = ceil(tmp); // Round up value
8349 double diffDown = tmp - roundDown;
8350 double diffUp = roundUp - tmp;
8351 if (diffDown < diffUp) {
8352 /* If it's closer to the round down value, then use it */
8353 res[i] = roundDown;
8354 } else if (diffDown > diffUp) {
8355 /* If it's closer to the round up value, then use it */
8356 res[i] = roundUp;
8357 } else {
8358 /* If it's equidistant between round up and round down value,
8359 * pick the one which is an even number */
8360 double half = roundDown / 2;
8361 if (half != floor(half)) {
8362 /* If the round down value is odd, return the round up value
8363 */
8364 res[i] = roundUp;
8365 } else {
8366 /* If the round up value is odd, return the round down value
8367 */
8368 res[i] = roundDown;
8369 }
8370 }
8371 res[i] = (v_double[i] < 0) ? -res[i] : res[i];
8372 }
8373 return _mm_set_pd(res[1], res[0]);
8374 } else if (rounding == (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC) ||
8375 (rounding == _MM_FROUND_CUR_DIRECTION &&
8377 return _mm_floor_pd(a);
8378 } else if (rounding == (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC) ||
8379 (rounding == _MM_FROUND_CUR_DIRECTION &&
8381 return _mm_ceil_pd(a);
8382 }
8383 return _mm_set_pd(v_double[1] > 0 ? floor(v_double[1]) : ceil(v_double[1]),
8384 v_double[0] > 0 ? floor(v_double[0]) : ceil(v_double[0]));
8385#endif
8386}
8387
8388// Round the packed single-precision (32-bit) floating-point elements in a using
8389// the rounding parameter, and store the results as packed single-precision
8390// floating-point elements in dst.
8391// software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_round_ps
8393{
8394#if defined(__aarch64__) || defined(__ARM_FEATURE_DIRECTED_ROUNDING)
8395 switch (rounding) {
8397 return vreinterpretq_m128_f32(vrndnq_f32(vreinterpretq_f32_m128(a)));
8399 return _mm_floor_ps(a);
8401 return _mm_ceil_ps(a);
8403 return vreinterpretq_m128_f32(vrndq_f32(vreinterpretq_f32_m128(a)));
8404 default: //_MM_FROUND_CUR_DIRECTION
8405 return vreinterpretq_m128_f32(vrndiq_f32(vreinterpretq_f32_m128(a)));
8406 }
8407#else
8408 float *v_float = (float *) &a;
8409
8410 if (rounding == (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC) ||
8411 (rounding == _MM_FROUND_CUR_DIRECTION &&
8413 uint32x4_t signmask = vdupq_n_u32(0x80000000);
8414 float32x4_t half = vbslq_f32(signmask, vreinterpretq_f32_m128(a),
8415 vdupq_n_f32(0.5f)); /* +/- 0.5 */
8416 int32x4_t r_normal = vcvtq_s32_f32(vaddq_f32(
8417 vreinterpretq_f32_m128(a), half)); /* round to integer: [a + 0.5]*/
8418 int32x4_t r_trunc = vcvtq_s32_f32(
8419 vreinterpretq_f32_m128(a)); /* truncate to integer: [a] */
8420 int32x4_t plusone = vreinterpretq_s32_u32(vshrq_n_u32(
8421 vreinterpretq_u32_s32(vnegq_s32(r_trunc)), 31)); /* 1 or 0 */
8422 int32x4_t r_even = vbicq_s32(vaddq_s32(r_trunc, plusone),
8423 vdupq_n_s32(1)); /* ([a] + {0,1}) & ~1 */
8424 float32x4_t delta = vsubq_f32(
8426 vcvtq_f32_s32(r_trunc)); /* compute delta: delta = (a - [a]) */
8427 uint32x4_t is_delta_half =
8428 vceqq_f32(delta, half); /* delta == +/- 0.5 */
8430 vcvtq_f32_s32(vbslq_s32(is_delta_half, r_even, r_normal)));
8431 } else if (rounding == (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC) ||
8432 (rounding == _MM_FROUND_CUR_DIRECTION &&
8434 return _mm_floor_ps(a);
8435 } else if (rounding == (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC) ||
8436 (rounding == _MM_FROUND_CUR_DIRECTION &&
8438 return _mm_ceil_ps(a);
8439 }
8440 return _mm_set_ps(v_float[3] > 0 ? floorf(v_float[3]) : ceilf(v_float[3]),
8441 v_float[2] > 0 ? floorf(v_float[2]) : ceilf(v_float[2]),
8442 v_float[1] > 0 ? floorf(v_float[1]) : ceilf(v_float[1]),
8443 v_float[0] > 0 ? floorf(v_float[0]) : ceilf(v_float[0]));
8444#endif
8445}
8446
8447// Round the lower double-precision (64-bit) floating-point element in b using
8448// the rounding parameter, store the result as a double-precision floating-point
8449// element in the lower element of dst, and copy the upper element from a to the
8450// upper element of dst.
8451// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_round_sd
8453{
8454 return _mm_move_sd(a, _mm_round_pd(b, rounding));
8455}
8456
8457// Round the lower single-precision (32-bit) floating-point element in b using
8458// the rounding parameter, store the result as a single-precision floating-point
8459// element in the lower element of dst, and copy the upper 3 packed elements
8460// from a to the upper elements of dst. Rounding is done according to the
8461// rounding[3:0] parameter, which can be one of:
8462// (_MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC) // round to nearest, and
8463// suppress exceptions
8464// (_MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC) // round down, and
8465// suppress exceptions
8466// (_MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC) // round up, and suppress
8467// exceptions
8468// (_MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC) // truncate, and suppress
8469// exceptions _MM_FROUND_CUR_DIRECTION // use MXCSR.RC; see
8470// _MM_SET_ROUNDING_MODE
8471// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_round_ss
8473{
8474 return _mm_move_ss(a, _mm_round_ps(b, rounding));
8475}
8476
8477// Load 128-bits of integer data from memory into dst using a non-temporal
8478// memory hint. mem_addr must be aligned on a 16-byte boundary or a
8479// general-protection exception may be generated.
8480//
8481// dst[127:0] := MEM[mem_addr+127:mem_addr]
8482//
8483// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_stream_load_si128
8485{
8486#if __has_builtin(__builtin_nontemporal_store)
8487 return __builtin_nontemporal_load(p);
8488#else
8489 return vreinterpretq_m128i_s64(vld1q_s64((int64_t *) p));
8490#endif
8491}
8492
8493// Compute the bitwise NOT of a and then AND with a 128-bit vector containing
8494// all 1's, and return 1 if the result is zero, otherwise return 0.
8495// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_test_all_ones
8497{
8498 return (uint64_t) (vgetq_lane_s64(a, 0) & vgetq_lane_s64(a, 1)) ==
8499 ~(uint64_t) 0;
8500}
8501
8502// Compute the bitwise AND of 128 bits (representing integer data) in a and
8503// mask, and return 1 if the result is zero, otherwise return 0.
8504// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_test_all_zeros
8506{
8507 int64x2_t a_and_mask =
8509 return !(vgetq_lane_s64(a_and_mask, 0) | vgetq_lane_s64(a_and_mask, 1));
8510}
8511
8512// Compute the bitwise AND of 128 bits (representing integer data) in a and
8513// mask, and set ZF to 1 if the result is zero, otherwise set ZF to 0. Compute
8514// the bitwise NOT of a and then AND with mask, and set CF to 1 if the result is
8515// zero, otherwise set CF to 0. Return 1 if both the ZF and CF values are zero,
8516// otherwise return 0.
8517// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=mm_test_mix_ones_zero
8519{
8520 uint64x2_t zf =
8522 uint64x2_t cf =
8524 uint64x2_t result = vandq_u64(zf, cf);
8525 return !(vgetq_lane_u64(result, 0) | vgetq_lane_u64(result, 1));
8526}
8527
8528// Compute the bitwise AND of 128 bits (representing integer data) in a and b,
8529// and set ZF to 1 if the result is zero, otherwise set ZF to 0. Compute the
8530// bitwise NOT of a and then AND with b, and set CF to 1 if the result is zero,
8531// otherwise set CF to 0. Return the CF value.
8532// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_testc_si128
8534{
8535 int64x2_t s64 =
8537 return !(vgetq_lane_s64(s64, 0) | vgetq_lane_s64(s64, 1));
8538}
8539
8540// Compute the bitwise AND of 128 bits (representing integer data) in a and b,
8541// and set ZF to 1 if the result is zero, otherwise set ZF to 0. Compute the
8542// bitwise NOT of a and then AND with b, and set CF to 1 if the result is zero,
8543// otherwise set CF to 0. Return 1 if both the ZF and CF values are zero,
8544// otherwise return 0.
8545// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_testnzc_si128
8546#define _mm_testnzc_si128(a, b) _mm_test_mix_ones_zeros(a, b)
8547
8548// Compute the bitwise AND of 128 bits (representing integer data) in a and b,
8549// and set ZF to 1 if the result is zero, otherwise set ZF to 0. Compute the
8550// bitwise NOT of a and then AND with b, and set CF to 1 if the result is zero,
8551// otherwise set CF to 0. Return the ZF value.
8552// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_testz_si128
8554{
8555 int64x2_t s64 =
8557 return !(vgetq_lane_s64(s64, 0) | vgetq_lane_s64(s64, 1));
8558}
8559
8560/* SSE4.2 */
8561
8562const static uint16_t _sse2neon_cmpestr_mask16b[8] ALIGN_STRUCT(16) = {
8563 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
8564};
8565const static uint8_t _sse2neon_cmpestr_mask8b[16] ALIGN_STRUCT(16) = {
8566 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
8567 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
8568};
8569
8570/* specify the source data format */
8571#define _SIDD_UBYTE_OPS 0x00 /* unsigned 8-bit characters */
8572#define _SIDD_UWORD_OPS 0x01 /* unsigned 16-bit characters */
8573#define _SIDD_SBYTE_OPS 0x02 /* signed 8-bit characters */
8574#define _SIDD_SWORD_OPS 0x03 /* signed 16-bit characters */
8575
8576/* specify the comparison operation */
8577#define _SIDD_CMP_EQUAL_ANY 0x00 /* compare equal any: strchr */
8578#define _SIDD_CMP_RANGES 0x04 /* compare ranges */
8579#define _SIDD_CMP_EQUAL_EACH 0x08 /* compare equal each: strcmp */
8580#define _SIDD_CMP_EQUAL_ORDERED 0x0C /* compare equal ordered */
8581
8582/* specify the polarity */
8583#define _SIDD_POSITIVE_POLARITY 0x00
8584#define _SIDD_MASKED_POSITIVE_POLARITY 0x20
8585#define _SIDD_NEGATIVE_POLARITY 0x10 /* negate results */
8586#define _SIDD_MASKED_NEGATIVE_POLARITY \
8587 0x30 /* negate results only before end of string */
8588
8589/* specify the output selection in _mm_cmpXstri */
8590#define _SIDD_LEAST_SIGNIFICANT 0x00
8591#define _SIDD_MOST_SIGNIFICANT 0x40
8592
8593/* specify the output selection in _mm_cmpXstrm */
8594#define _SIDD_BIT_MASK 0x00
8595#define _SIDD_UNIT_MASK 0x40
8596
8597/* Pattern Matching for C macros.
8598 * https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms
8599 */
8600
8601/* catenate */
8602#define SSE2NEON_PRIMITIVE_CAT(a, ...) a##__VA_ARGS__
8603#define SSE2NEON_CAT(a, b) SSE2NEON_PRIMITIVE_CAT(a, b)
8604
8605#define SSE2NEON_IIF(c) SSE2NEON_PRIMITIVE_CAT(SSE2NEON_IIF_, c)
8606/* run the 2nd parameter */
8607#define SSE2NEON_IIF_0(t, ...) __VA_ARGS__
8608/* run the 1st parameter */
8609#define SSE2NEON_IIF_1(t, ...) t
8610
8611#define SSE2NEON_COMPL(b) SSE2NEON_PRIMITIVE_CAT(SSE2NEON_COMPL_, b)
8612#define SSE2NEON_COMPL_0 1
8613#define SSE2NEON_COMPL_1 0
8614
8615#define SSE2NEON_DEC(x) SSE2NEON_PRIMITIVE_CAT(SSE2NEON_DEC_, x)
8616#define SSE2NEON_DEC_1 0
8617#define SSE2NEON_DEC_2 1
8618#define SSE2NEON_DEC_3 2
8619#define SSE2NEON_DEC_4 3
8620#define SSE2NEON_DEC_5 4
8621#define SSE2NEON_DEC_6 5
8622#define SSE2NEON_DEC_7 6
8623#define SSE2NEON_DEC_8 7
8624#define SSE2NEON_DEC_9 8
8625#define SSE2NEON_DEC_10 9
8626#define SSE2NEON_DEC_11 10
8627#define SSE2NEON_DEC_12 11
8628#define SSE2NEON_DEC_13 12
8629#define SSE2NEON_DEC_14 13
8630#define SSE2NEON_DEC_15 14
8631#define SSE2NEON_DEC_16 15
8632
8633/* detection */
8634#define SSE2NEON_CHECK_N(x, n, ...) n
8635#define SSE2NEON_CHECK(...) SSE2NEON_CHECK_N(__VA_ARGS__, 0, )
8636#define SSE2NEON_PROBE(x) x, 1,
8637
8638#define SSE2NEON_NOT(x) SSE2NEON_CHECK(SSE2NEON_PRIMITIVE_CAT(SSE2NEON_NOT_, x))
8639#define SSE2NEON_NOT_0 SSE2NEON_PROBE(~)
8640
8641#define SSE2NEON_BOOL(x) SSE2NEON_COMPL(SSE2NEON_NOT(x))
8642#define SSE2NEON_IF(c) SSE2NEON_IIF(SSE2NEON_BOOL(c))
8643
8644#define SSE2NEON_EAT(...)
8645#define SSE2NEON_EXPAND(...) __VA_ARGS__
8646#define SSE2NEON_WHEN(c) SSE2NEON_IF(c)(SSE2NEON_EXPAND, SSE2NEON_EAT)
8647
8648/* recursion */
8649/* deferred expression */
8650#define SSE2NEON_EMPTY()
8651#define SSE2NEON_DEFER(id) id SSE2NEON_EMPTY()
8652#define SSE2NEON_OBSTRUCT(...) __VA_ARGS__ SSE2NEON_DEFER(SSE2NEON_EMPTY)()
8653#define SSE2NEON_EXPAND(...) __VA_ARGS__
8654
8655#define SSE2NEON_EVAL(...) \
8656 SSE2NEON_EVAL1(SSE2NEON_EVAL1(SSE2NEON_EVAL1(__VA_ARGS__)))
8657#define SSE2NEON_EVAL1(...) \
8658 SSE2NEON_EVAL2(SSE2NEON_EVAL2(SSE2NEON_EVAL2(__VA_ARGS__)))
8659#define SSE2NEON_EVAL2(...) \
8660 SSE2NEON_EVAL3(SSE2NEON_EVAL3(SSE2NEON_EVAL3(__VA_ARGS__)))
8661#define SSE2NEON_EVAL3(...) __VA_ARGS__
8662
8663#define SSE2NEON_REPEAT(count, macro, ...) \
8664 SSE2NEON_WHEN(count) \
8665 (SSE2NEON_OBSTRUCT(SSE2NEON_REPEAT_INDIRECT)()( \
8666 SSE2NEON_DEC(count), macro, \
8667 __VA_ARGS__) SSE2NEON_OBSTRUCT(macro)(SSE2NEON_DEC(count), \
8668 __VA_ARGS__))
8669#define SSE2NEON_REPEAT_INDIRECT() SSE2NEON_REPEAT
8670
8671#define SSE2NEON_SIZE_OF_byte 8
8672#define SSE2NEON_NUMBER_OF_LANES_byte 16
8673#define SSE2NEON_SIZE_OF_word 16
8674#define SSE2NEON_NUMBER_OF_LANES_word 8
8675
8676#define SSE2NEON_COMPARE_EQUAL_THEN_FILL_LANE(i, type) \
8677 mtx[i] = vreinterpretq_m128i_##type(vceqq_##type( \
8678 vdupq_n_##type(vgetq_lane_##type(vreinterpretq_##type##_m128i(b), i)), \
8679 vreinterpretq_##type##_m128i(a)));
8680
8681#define SSE2NEON_FILL_LANE(i, type) \
8682 vec_b[i] = \
8683 vdupq_n_##type(vgetq_lane_##type(vreinterpretq_##type##_m128i(b), i));
8684
8685#define PCMPSTR_RANGES(a, b, mtx, data_type_prefix, type_prefix, size, \
8686 number_of_lanes, byte_or_word) \
8687 do { \
8688 SSE2NEON_CAT( \
8689 data_type_prefix, \
8690 SSE2NEON_CAT(size, \
8691 SSE2NEON_CAT(x, SSE2NEON_CAT(number_of_lanes, _t)))) \
8692 vec_b[number_of_lanes]; \
8693 __m128i mask = SSE2NEON_IIF(byte_or_word)( \
8694 vreinterpretq_m128i_u16(vdupq_n_u16(0xff)), \
8695 vreinterpretq_m128i_u32(vdupq_n_u32(0xffff))); \
8696 SSE2NEON_EVAL(SSE2NEON_REPEAT(number_of_lanes, SSE2NEON_FILL_LANE, \
8697 SSE2NEON_CAT(type_prefix, size))) \
8698 for (int i = 0; i < number_of_lanes; i++) { \
8699 mtx[i] = SSE2NEON_CAT(vreinterpretq_m128i_u, \
8700 size)(SSE2NEON_CAT(vbslq_u, size)( \
8701 SSE2NEON_CAT(vreinterpretq_u, \
8702 SSE2NEON_CAT(size, _m128i))(mask), \
8703 SSE2NEON_CAT(vcgeq_, SSE2NEON_CAT(type_prefix, size))( \
8704 vec_b[i], \
8705 SSE2NEON_CAT( \
8706 vreinterpretq_, \
8707 SSE2NEON_CAT(type_prefix, \
8708 SSE2NEON_CAT(size, _m128i(a))))), \
8709 SSE2NEON_CAT(vcleq_, SSE2NEON_CAT(type_prefix, size))( \
8710 vec_b[i], \
8711 SSE2NEON_CAT( \
8712 vreinterpretq_, \
8713 SSE2NEON_CAT(type_prefix, \
8714 SSE2NEON_CAT(size, _m128i(a))))))); \
8715 } \
8716 } while (0)
8717
8718#define PCMPSTR_EQ(a, b, mtx, size, number_of_lanes) \
8719 do { \
8720 SSE2NEON_EVAL(SSE2NEON_REPEAT(number_of_lanes, \
8721 SSE2NEON_COMPARE_EQUAL_THEN_FILL_LANE, \
8722 SSE2NEON_CAT(u, size))) \
8723 } while (0)
8724
8725#define SSE2NEON_CMP_EQUAL_ANY_IMPL(type) \
8726 static int _sse2neon_cmp_##type##_equal_any(__m128i a, int la, __m128i b, \
8727 int lb) \
8728 { \
8729 __m128i mtx[16]; \
8730 PCMPSTR_EQ(a, b, mtx, SSE2NEON_CAT(SSE2NEON_SIZE_OF_, type), \
8731 SSE2NEON_CAT(SSE2NEON_NUMBER_OF_LANES_, type)); \
8732 return SSE2NEON_CAT( \
8733 _sse2neon_aggregate_equal_any_, \
8734 SSE2NEON_CAT( \
8735 SSE2NEON_CAT(SSE2NEON_SIZE_OF_, type), \
8736 SSE2NEON_CAT(x, SSE2NEON_CAT(SSE2NEON_NUMBER_OF_LANES_, \
8737 type))))(la, lb, mtx); \
8738 }
8739
8740#define SSE2NEON_CMP_RANGES_IMPL(type, data_type, us, byte_or_word) \
8741 static int _sse2neon_cmp_##us##type##_ranges(__m128i a, int la, __m128i b, \
8742 int lb) \
8743 { \
8744 __m128i mtx[16]; \
8745 PCMPSTR_RANGES( \
8746 a, b, mtx, data_type, us, SSE2NEON_CAT(SSE2NEON_SIZE_OF_, type), \
8747 SSE2NEON_CAT(SSE2NEON_NUMBER_OF_LANES_, type), byte_or_word); \
8748 return SSE2NEON_CAT( \
8749 _sse2neon_aggregate_ranges_, \
8750 SSE2NEON_CAT( \
8751 SSE2NEON_CAT(SSE2NEON_SIZE_OF_, type), \
8752 SSE2NEON_CAT(x, SSE2NEON_CAT(SSE2NEON_NUMBER_OF_LANES_, \
8753 type))))(la, lb, mtx); \
8754 }
8755
8756#define SSE2NEON_CMP_EQUAL_ORDERED_IMPL(type) \
8757 static int _sse2neon_cmp_##type##_equal_ordered(__m128i a, int la, \
8758 __m128i b, int lb) \
8759 { \
8760 __m128i mtx[16]; \
8761 PCMPSTR_EQ(a, b, mtx, SSE2NEON_CAT(SSE2NEON_SIZE_OF_, type), \
8762 SSE2NEON_CAT(SSE2NEON_NUMBER_OF_LANES_, type)); \
8763 return SSE2NEON_CAT( \
8764 _sse2neon_aggregate_equal_ordered_, \
8765 SSE2NEON_CAT( \
8766 SSE2NEON_CAT(SSE2NEON_SIZE_OF_, type), \
8767 SSE2NEON_CAT(x, \
8768 SSE2NEON_CAT(SSE2NEON_NUMBER_OF_LANES_, type))))( \
8769 SSE2NEON_CAT(SSE2NEON_NUMBER_OF_LANES_, type), la, lb, mtx); \
8770 }
8771
8772static int _sse2neon_aggregate_equal_any_8x16(int la, int lb, __m128i mtx[16])
8773{
8774 int res = 0;
8775 int m = (1 << la) - 1;
8776 uint8x8_t vec_mask = vld1_u8(_sse2neon_cmpestr_mask8b);
8777 uint8x8_t t_lo = vtst_u8(vdup_n_u8(m & 0xff), vec_mask);
8778 uint8x8_t t_hi = vtst_u8(vdup_n_u8(m >> 8), vec_mask);
8779 uint8x16_t vec = vcombine_u8(t_lo, t_hi);
8780 for (int j = 0; j < lb; j++) {
8781 mtx[j] = vreinterpretq_m128i_u8(
8782 vandq_u8(vec, vreinterpretq_u8_m128i(mtx[j])));
8783 mtx[j] = vreinterpretq_m128i_u8(
8784 vshrq_n_u8(vreinterpretq_u8_m128i(mtx[j]), 7));
8785 int tmp = _sse2neon_vaddvq_u8(vreinterpretq_u8_m128i(mtx[j])) ? 1 : 0;
8786 res |= (tmp << j);
8787 }
8788 return res;
8789}
8790
8791static int _sse2neon_aggregate_equal_any_16x8(int la, int lb, __m128i mtx[16])
8792{
8793 int res = 0;
8794 int m = (1 << la) - 1;
8795 uint16x8_t vec =
8796 vtstq_u16(vdupq_n_u16(m), vld1q_u16(_sse2neon_cmpestr_mask16b));
8797 for (int j = 0; j < lb; j++) {
8798 mtx[j] = vreinterpretq_m128i_u16(
8799 vandq_u16(vec, vreinterpretq_u16_m128i(mtx[j])));
8800 mtx[j] = vreinterpretq_m128i_u16(
8801 vshrq_n_u16(vreinterpretq_u16_m128i(mtx[j]), 15));
8802 int tmp = _sse2neon_vaddvq_u16(vreinterpretq_u16_m128i(mtx[j])) ? 1 : 0;
8803 res |= (tmp << j);
8804 }
8805 return res;
8806}
8807
8808/* clang-format off */
8809#define SSE2NEON_GENERATE_CMP_EQUAL_ANY(prefix) \
8810 prefix##IMPL(byte) \
8811 prefix##IMPL(word)
8812/* clang-format on */
8813
8814SSE2NEON_GENERATE_CMP_EQUAL_ANY(SSE2NEON_CMP_EQUAL_ANY_)
8815
8816static int _sse2neon_aggregate_ranges_16x8(int la, int lb, __m128i mtx[16])
8817{
8818 int res = 0;
8819 int m = (1 << la) - 1;
8820 uint16x8_t vec =
8821 vtstq_u16(vdupq_n_u16(m), vld1q_u16(_sse2neon_cmpestr_mask16b));
8822 for (int j = 0; j < lb; j++) {
8823 mtx[j] = vreinterpretq_m128i_u16(
8824 vandq_u16(vec, vreinterpretq_u16_m128i(mtx[j])));
8825 mtx[j] = vreinterpretq_m128i_u16(
8826 vshrq_n_u16(vreinterpretq_u16_m128i(mtx[j]), 15));
8828 vshrq_n_u32(vreinterpretq_u32_m128i(mtx[j]), 16));
8829 uint32x4_t vec_res = vandq_u32(vreinterpretq_u32_m128i(mtx[j]),
8831#if defined(__aarch64__)
8832 int t = vaddvq_u32(vec_res) ? 1 : 0;
8833#else
8834 uint64x2_t sumh = vpaddlq_u32(vec_res);
8835 int t = vgetq_lane_u64(sumh, 0) + vgetq_lane_u64(sumh, 1);
8836#endif
8837 res |= (t << j);
8838 }
8839 return res;
8840}
8841
8842static int _sse2neon_aggregate_ranges_8x16(int la, int lb, __m128i mtx[16])
8843{
8844 int res = 0;
8845 int m = (1 << la) - 1;
8846 uint8x8_t vec_mask = vld1_u8(_sse2neon_cmpestr_mask8b);
8847 uint8x8_t t_lo = vtst_u8(vdup_n_u8(m & 0xff), vec_mask);
8848 uint8x8_t t_hi = vtst_u8(vdup_n_u8(m >> 8), vec_mask);
8849 uint8x16_t vec = vcombine_u8(t_lo, t_hi);
8850 for (int j = 0; j < lb; j++) {
8851 mtx[j] = vreinterpretq_m128i_u8(
8852 vandq_u8(vec, vreinterpretq_u8_m128i(mtx[j])));
8853 mtx[j] = vreinterpretq_m128i_u8(
8854 vshrq_n_u8(vreinterpretq_u8_m128i(mtx[j]), 7));
8856 vshrq_n_u16(vreinterpretq_u16_m128i(mtx[j]), 8));
8857 uint16x8_t vec_res = vandq_u16(vreinterpretq_u16_m128i(mtx[j]),
8859 int t = _sse2neon_vaddvq_u16(vec_res) ? 1 : 0;
8860 res |= (t << j);
8861 }
8862 return res;
8863}
8864
8865#define SSE2NEON_CMP_RANGES_IS_BYTE 1
8866#define SSE2NEON_CMP_RANGES_IS_WORD 0
8867
8868/* clang-format off */
8869#define SSE2NEON_GENERATE_CMP_RANGES(prefix) \
8870 prefix##IMPL(byte, uint, u, prefix##IS_BYTE) \
8871 prefix##IMPL(byte, int, s, prefix##IS_BYTE) \
8872 prefix##IMPL(word, uint, u, prefix##IS_WORD) \
8873 prefix##IMPL(word, int, s, prefix##IS_WORD)
8874/* clang-format on */
8875
8876SSE2NEON_GENERATE_CMP_RANGES(SSE2NEON_CMP_RANGES_)
8877
8878#undef SSE2NEON_CMP_RANGES_IS_BYTE
8879#undef SSE2NEON_CMP_RANGES_IS_WORD
8880
8881static int _sse2neon_cmp_byte_equal_each(__m128i a, int la, __m128i b, int lb)
8882{
8883 uint8x16_t mtx =
8885 int m0 = (la < lb) ? 0 : ((1 << la) - (1 << lb));
8886 int m1 = 0x10000 - (1 << la);
8887 int tb = 0x10000 - (1 << lb);
8888 uint8x8_t vec_mask, vec0_lo, vec0_hi, vec1_lo, vec1_hi;
8889 uint8x8_t tmp_lo, tmp_hi, res_lo, res_hi;
8890 vec_mask = vld1_u8(_sse2neon_cmpestr_mask8b);
8891 vec0_lo = vtst_u8(vdup_n_u8(m0), vec_mask);
8892 vec0_hi = vtst_u8(vdup_n_u8(m0 >> 8), vec_mask);
8893 vec1_lo = vtst_u8(vdup_n_u8(m1), vec_mask);
8894 vec1_hi = vtst_u8(vdup_n_u8(m1 >> 8), vec_mask);
8895 tmp_lo = vtst_u8(vdup_n_u8(tb), vec_mask);
8896 tmp_hi = vtst_u8(vdup_n_u8(tb >> 8), vec_mask);
8897
8898 res_lo = vbsl_u8(vec0_lo, vdup_n_u8(0), vget_low_u8(mtx));
8899 res_hi = vbsl_u8(vec0_hi, vdup_n_u8(0), vget_high_u8(mtx));
8900 res_lo = vbsl_u8(vec1_lo, tmp_lo, res_lo);
8901 res_hi = vbsl_u8(vec1_hi, tmp_hi, res_hi);
8902 res_lo = vand_u8(res_lo, vec_mask);
8903 res_hi = vand_u8(res_hi, vec_mask);
8904
8905 int res = _sse2neon_vaddv_u8(res_lo) + (_sse2neon_vaddv_u8(res_hi) << 8);
8906 return res;
8907}
8908
8909static int _sse2neon_cmp_word_equal_each(__m128i a, int la, __m128i b, int lb)
8910{
8911 uint16x8_t mtx =
8913 int m0 = (la < lb) ? 0 : ((1 << la) - (1 << lb));
8914 int m1 = 0x100 - (1 << la);
8915 int tb = 0x100 - (1 << lb);
8916 uint16x8_t vec_mask = vld1q_u16(_sse2neon_cmpestr_mask16b);
8917 uint16x8_t vec0 = vtstq_u16(vdupq_n_u16(m0), vec_mask);
8918 uint16x8_t vec1 = vtstq_u16(vdupq_n_u16(m1), vec_mask);
8919 uint16x8_t tmp = vtstq_u16(vdupq_n_u16(tb), vec_mask);
8920 mtx = vbslq_u16(vec0, vdupq_n_u16(0), mtx);
8921 mtx = vbslq_u16(vec1, tmp, mtx);
8922 mtx = vandq_u16(mtx, vec_mask);
8923 return _sse2neon_vaddvq_u16(mtx);
8924}
8925
8926#define SSE2NEON_AGGREGATE_EQUAL_ORDER_IS_UBYTE 1
8927#define SSE2NEON_AGGREGATE_EQUAL_ORDER_IS_UWORD 0
8928
8929#define SSE2NEON_AGGREGATE_EQUAL_ORDER_IMPL(size, number_of_lanes, data_type) \
8930 static int _sse2neon_aggregate_equal_ordered_##size##x##number_of_lanes( \
8931 int bound, int la, int lb, __m128i mtx[16]) \
8932 { \
8933 int res = 0; \
8934 int m1 = SSE2NEON_IIF(data_type)(0x10000, 0x100) - (1 << la); \
8935 uint##size##x8_t vec_mask = SSE2NEON_IIF(data_type)( \
8936 vld1_u##size(_sse2neon_cmpestr_mask##size##b), \
8937 vld1q_u##size(_sse2neon_cmpestr_mask##size##b)); \
8938 uint##size##x##number_of_lanes##_t vec1 = SSE2NEON_IIF(data_type)( \
8939 vcombine_u##size(vtst_u##size(vdup_n_u##size(m1), vec_mask), \
8940 vtst_u##size(vdup_n_u##size(m1 >> 8), vec_mask)), \
8941 vtstq_u##size(vdupq_n_u##size(m1), vec_mask)); \
8942 uint##size##x##number_of_lanes##_t vec_minusone = vdupq_n_u##size(-1); \
8943 uint##size##x##number_of_lanes##_t vec_zero = vdupq_n_u##size(0); \
8944 for (int j = 0; j < lb; j++) { \
8945 mtx[j] = vreinterpretq_m128i_u##size(vbslq_u##size( \
8946 vec1, vec_minusone, vreinterpretq_u##size##_m128i(mtx[j]))); \
8947 } \
8948 for (int j = lb; j < bound; j++) { \
8949 mtx[j] = vreinterpretq_m128i_u##size( \
8950 vbslq_u##size(vec1, vec_minusone, vec_zero)); \
8951 } \
8952 unsigned SSE2NEON_IIF(data_type)(char, short) *ptr = \
8953 (unsigned SSE2NEON_IIF(data_type)(char, short) *) mtx; \
8954 for (int i = 0; i < bound; i++) { \
8955 int val = 1; \
8956 for (int j = 0, k = i; j < bound - i && k < bound; j++, k++) \
8957 val &= ptr[k * bound + j]; \
8958 res += val << i; \
8959 } \
8960 return res; \
8961 }
8962
8963/* clang-format off */
8964#define SSE2NEON_GENERATE_AGGREGATE_EQUAL_ORDER(prefix) \
8965 prefix##IMPL(8, 16, prefix##IS_UBYTE) \
8966 prefix##IMPL(16, 8, prefix##IS_UWORD)
8967/* clang-format on */
8968
8969SSE2NEON_GENERATE_AGGREGATE_EQUAL_ORDER(SSE2NEON_AGGREGATE_EQUAL_ORDER_)
8970
8971#undef SSE2NEON_AGGREGATE_EQUAL_ORDER_IS_UBYTE
8972#undef SSE2NEON_AGGREGATE_EQUAL_ORDER_IS_UWORD
8973
8974/* clang-format off */
8975#define SSE2NEON_GENERATE_CMP_EQUAL_ORDERED(prefix) \
8976 prefix##IMPL(byte) \
8977 prefix##IMPL(word)
8978/* clang-format on */
8979
8980SSE2NEON_GENERATE_CMP_EQUAL_ORDERED(SSE2NEON_CMP_EQUAL_ORDERED_)
8981
8982#define SSE2NEON_CMPESTR_LIST \
8983 _(CMP_UBYTE_EQUAL_ANY, cmp_byte_equal_any) \
8984 _(CMP_UWORD_EQUAL_ANY, cmp_word_equal_any) \
8985 _(CMP_SBYTE_EQUAL_ANY, cmp_byte_equal_any) \
8986 _(CMP_SWORD_EQUAL_ANY, cmp_word_equal_any) \
8987 _(CMP_UBYTE_RANGES, cmp_ubyte_ranges) \
8988 _(CMP_UWORD_RANGES, cmp_uword_ranges) \
8989 _(CMP_SBYTE_RANGES, cmp_sbyte_ranges) \
8990 _(CMP_SWORD_RANGES, cmp_sword_ranges) \
8991 _(CMP_UBYTE_EQUAL_EACH, cmp_byte_equal_each) \
8992 _(CMP_UWORD_EQUAL_EACH, cmp_word_equal_each) \
8993 _(CMP_SBYTE_EQUAL_EACH, cmp_byte_equal_each) \
8994 _(CMP_SWORD_EQUAL_EACH, cmp_word_equal_each) \
8995 _(CMP_UBYTE_EQUAL_ORDERED, cmp_byte_equal_ordered) \
8996 _(CMP_UWORD_EQUAL_ORDERED, cmp_word_equal_ordered) \
8997 _(CMP_SBYTE_EQUAL_ORDERED, cmp_byte_equal_ordered) \
8998 _(CMP_SWORD_EQUAL_ORDERED, cmp_word_equal_ordered)
8999
9000enum {
9001#define _(name, func_suffix) name,
9003#undef _
9005typedef int (*cmpestr_func_t)(__m128i a, int la, __m128i b, int lb);
9006static cmpestr_func_t _sse2neon_cmpfunc_table[] = {
9007#define _(name, func_suffix) _sse2neon_##func_suffix,
9009#undef _
9010};
9011
9012FORCE_INLINE int _sse2neon_sido_negative(int res, int lb, int imm8, int bound)
9013{
9014 switch (imm8 & 0x30) {
9016 res ^= 0xffffffff;
9017 break;
9019 res ^= (1 << lb) - 1;
9020 break;
9021 default:
9022 break;
9023 }
9024
9025 return res & ((bound == 8) ? 0xFF : 0xFFFF);
9026}
9027
9028FORCE_INLINE int _sse2neon_clz(unsigned int x)
9029{
9030#if _MSC_VER
9031 DWORD cnt = 0;
9032 if (_BitScanForward(&cnt, x))
9033 return cnt;
9034 return 32;
9035#else
9036 return x != 0 ? __builtin_clz(x) : 32;
9037#endif
9038}
9039
9040FORCE_INLINE int _sse2neon_ctz(unsigned int x)
9041{
9042#if _MSC_VER
9043 DWORD cnt = 0;
9044 if (_BitScanReverse(&cnt, x))
9045 return 31 - cnt;
9046 return 32;
9047#else
9048 return x != 0 ? __builtin_ctz(x) : 32;
9049#endif
9050}
9051
9052FORCE_INLINE int _sse2neon_ctzll(unsigned long long x)
9053{
9054#if _MSC_VER
9055 unsigned long cnt;
9056#ifdef defined(SSE2NEON_HAS_BITSCAN64)
9057 (defined(_M_AMD64) || defined(__x86_64__))
9058 if((_BitScanForward64(&cnt, x))
9059 return (int)(cnt);
9060#else
9061 if (_BitScanForward(&cnt, (unsigned long) (x)))
9062 return (int) cnt;
9063 if (_BitScanForward(&cnt, (unsigned long) (x >> 32)))
9064 return (int) (cnt + 32);
9065#endif
9066 return 64;
9067#else
9068 return x != 0 ? __builtin_ctzll(x) : 64;
9069#endif
9070}
9071
9072#define SSE2NEON_MIN(x, y) (x) < (y) ? (x) : (y)
9073
9074#define SSE2NEON_CMPSTR_SET_UPPER(var, imm) \
9075 const int var = (imm & 0x01) ? 8 : 16
9076
9077#define SSE2NEON_CMPESTRX_LEN_PAIR(a, b, la, lb) \
9078 int tmp1 = la ^ (la >> 31); \
9079 la = tmp1 - (la >> 31); \
9080 int tmp2 = lb ^ (lb >> 31); \
9081 lb = tmp2 - (lb >> 31); \
9082 la = SSE2NEON_MIN(la, bound); \
9083 lb = SSE2NEON_MIN(lb, bound)
9084
9085// Compare all pairs of character in string a and b,
9086// then aggregate the result.
9087// As the only difference of PCMPESTR* and PCMPISTR* is the way to calculate the
9088// length of string, we use SSE2NEON_CMP{I,E}STRX_GET_LEN to get the length of
9089// string a and b.
9090#define SSE2NEON_COMP_AGG(a, b, la, lb, imm8, IE) \
9091 SSE2NEON_CMPSTR_SET_UPPER(bound, imm8); \
9092 SSE2NEON_##IE##_LEN_PAIR(a, b, la, lb); \
9093 int r2 = (_sse2neon_cmpfunc_table[imm8 & 0x0f])(a, la, b, lb); \
9094 r2 = _sse2neon_sido_negative(r2, lb, imm8, bound)
9095
9096#define SSE2NEON_CMPSTR_GENERATE_INDEX(r2, bound, imm8) \
9097 return (r2 == 0) ? bound \
9098 : ((imm8 & 0x40) ? (31 - _sse2neon_clz(r2)) \
9099 : _sse2neon_ctz(r2))
9100
9101#define SSE2NEON_CMPSTR_GENERATE_MASK(dst) \
9102 __m128i dst = vreinterpretq_m128i_u8(vdupq_n_u8(0)); \
9103 if (imm8 & 0x40) { \
9104 if (bound == 8) { \
9105 uint16x8_t tmp = vtstq_u16(vdupq_n_u16(r2), \
9106 vld1q_u16(_sse2neon_cmpestr_mask16b)); \
9107 dst = vreinterpretq_m128i_u16(vbslq_u16( \
9108 tmp, vdupq_n_u16(-1), vreinterpretq_u16_m128i(dst))); \
9109 } else { \
9110 uint8x16_t vec_r2 = \
9111 vcombine_u8(vdup_n_u8(r2), vdup_n_u8(r2 >> 8)); \
9112 uint8x16_t tmp = \
9113 vtstq_u8(vec_r2, vld1q_u8(_sse2neon_cmpestr_mask8b)); \
9114 dst = vreinterpretq_m128i_u8( \
9115 vbslq_u8(tmp, vdupq_n_u8(-1), vreinterpretq_u8_m128i(dst))); \
9116 } \
9117 } else { \
9118 if (bound == 16) { \
9119 dst = vreinterpretq_m128i_u16( \
9120 vsetq_lane_u16(r2 & 0xffff, vreinterpretq_u16_m128i(dst), 0)); \
9121 } else { \
9122 dst = vreinterpretq_m128i_u8( \
9123 vsetq_lane_u8(r2 & 0xff, vreinterpretq_u8_m128i(dst), 0)); \
9124 } \
9125 } \
9126 return dst
9127
9128// Compare packed strings in a and b with lengths la and lb using the control
9129// in imm8, and returns 1 if b did not contain a null character and the
9130// resulting mask was zero, and 0 otherwise.
9131// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpestra
9133 int la,
9134 __m128i b,
9135 int lb,
9136 const int imm8)
9137{
9138 int lb_cpy = lb;
9139 SSE2NEON_COMP_AGG(a, b, la, lb, imm8, CMPESTRX);
9140 return !r2 & (lb_cpy > bound);
9141}
9142
9143// Compare packed strings in a and b with lengths la and lb using the control in
9144// imm8, and returns 1 if the resulting mask was non-zero, and 0 otherwise.
9145// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpestrc
9147 int la,
9148 __m128i b,
9149 int lb,
9150 const int imm8)
9151{
9152 SSE2NEON_COMP_AGG(a, b, la, lb, imm8, CMPESTRX);
9153 return r2 != 0;
9154}
9155
9156// Compare packed strings in a and b with lengths la and lb using the control
9157// in imm8, and store the generated index in dst.
9158// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpestri
9160 int la,
9161 __m128i b,
9162 int lb,
9163 const int imm8)
9164{
9165 SSE2NEON_COMP_AGG(a, b, la, lb, imm8, CMPESTRX);
9166 SSE2NEON_CMPSTR_GENERATE_INDEX(r2, bound, imm8);
9167}
9168
9169// Compare packed strings in a and b with lengths la and lb using the control
9170// in imm8, and store the generated mask in dst.
9171// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpestrm
9173_mm_cmpestrm(__m128i a, int la, __m128i b, int lb, const int imm8)
9174{
9175 SSE2NEON_COMP_AGG(a, b, la, lb, imm8, CMPESTRX);
9177}
9178
9179// Compare packed strings in a and b with lengths la and lb using the control in
9180// imm8, and returns bit 0 of the resulting bit mask.
9181// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpestro
9183 int la,
9184 __m128i b,
9185 int lb,
9186 const int imm8)
9187{
9188 SSE2NEON_COMP_AGG(a, b, la, lb, imm8, CMPESTRX);
9189 return r2 & 1;
9190}
9191
9192// Compare packed strings in a and b with lengths la and lb using the control in
9193// imm8, and returns 1 if any character in a was null, and 0 otherwise.
9194// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpestrs
9196 int la,
9197 __m128i b,
9198 int lb,
9199 const int imm8)
9200{
9201 SSE2NEON_CMPSTR_SET_UPPER(bound, imm8);
9202 return la <= (bound - 1);
9203}
9204
9205// Compare packed strings in a and b with lengths la and lb using the control in
9206// imm8, and returns 1 if any character in b was null, and 0 otherwise.
9207// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpestrz
9209 int la,
9210 __m128i b,
9211 int lb,
9212 const int imm8)
9213{
9214 SSE2NEON_CMPSTR_SET_UPPER(bound, imm8);
9215 return lb <= (bound - 1);
9216}
9217
9218#define SSE2NEON_CMPISTRX_LENGTH(str, len, imm8) \
9219 do { \
9220 if (imm8 & 0x01) { \
9221 uint16x8_t equal_mask_##str = \
9222 vceqq_u16(vreinterpretq_u16_m128i(str), vdupq_n_u16(0)); \
9223 uint8x8_t res_##str = vshrn_n_u16(equal_mask_##str, 4); \
9224 uint64_t matches_##str = \
9225 vget_lane_u64(vreinterpret_u64_u8(res_##str), 0); \
9226 len = _sse2neon_ctzll(matches_##str) >> 3; \
9227 } else { \
9228 uint16x8_t equal_mask_##str = vreinterpretq_u16_u8( \
9229 vceqq_u8(vreinterpretq_u8_m128i(str), vdupq_n_u8(0))); \
9230 uint8x8_t res_##str = vshrn_n_u16(equal_mask_##str, 4); \
9231 uint64_t matches_##str = \
9232 vget_lane_u64(vreinterpret_u64_u8(res_##str), 0); \
9233 len = _sse2neon_ctzll(matches_##str) >> 2; \
9234 } \
9235 } while (0)
9236
9237#define SSE2NEON_CMPISTRX_LEN_PAIR(a, b, la, lb) \
9238 int la, lb; \
9239 do { \
9240 SSE2NEON_CMPISTRX_LENGTH(a, la, imm8); \
9241 SSE2NEON_CMPISTRX_LENGTH(b, lb, imm8); \
9242 } while (0)
9243
9244// Compare packed strings with implicit lengths in a and b using the control in
9245// imm8, and returns 1 if b did not contain a null character and the resulting
9246// mask was zero, and 0 otherwise.
9247// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpistra
9248FORCE_INLINE int _mm_cmpistra(__m128i a, __m128i b, const int imm8)
9249{
9250 SSE2NEON_COMP_AGG(a, b, la, lb, imm8, CMPISTRX);
9251 return !r2 & (lb >= bound);
9252}
9253
9254// Compare packed strings with implicit lengths in a and b using the control in
9255// imm8, and returns 1 if the resulting mask was non-zero, and 0 otherwise.
9256// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpistrc
9257FORCE_INLINE int _mm_cmpistrc(__m128i a, __m128i b, const int imm8)
9258{
9259 SSE2NEON_COMP_AGG(a, b, la, lb, imm8, CMPISTRX);
9260 return r2 != 0;
9261}
9262
9263// Compare packed strings with implicit lengths in a and b using the control in
9264// imm8, and store the generated index in dst.
9265// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpistri
9266FORCE_INLINE int _mm_cmpistri(__m128i a, __m128i b, const int imm8)
9267{
9268 SSE2NEON_COMP_AGG(a, b, la, lb, imm8, CMPISTRX);
9269 SSE2NEON_CMPSTR_GENERATE_INDEX(r2, bound, imm8);
9270}
9271
9272// Compare packed strings with implicit lengths in a and b using the control in
9273// imm8, and store the generated mask in dst.
9274// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpistrm
9276{
9277 SSE2NEON_COMP_AGG(a, b, la, lb, imm8, CMPISTRX);
9279}
9280
9281// Compare packed strings with implicit lengths in a and b using the control in
9282// imm8, and returns bit 0 of the resulting bit mask.
9283// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpistro
9284FORCE_INLINE int _mm_cmpistro(__m128i a, __m128i b, const int imm8)
9285{
9286 SSE2NEON_COMP_AGG(a, b, la, lb, imm8, CMPISTRX);
9287 return r2 & 1;
9288}
9289
9290// Compare packed strings with implicit lengths in a and b using the control in
9291// imm8, and returns 1 if any character in a was null, and 0 otherwise.
9292// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpistrs
9293FORCE_INLINE int _mm_cmpistrs(__m128i a, __m128i b, const int imm8)
9294{
9295 SSE2NEON_CMPSTR_SET_UPPER(bound, imm8);
9296 int la;
9297 SSE2NEON_CMPISTRX_LENGTH(a, la, imm8);
9298 return la <= (bound - 1);
9299}
9300
9301// Compare packed strings with implicit lengths in a and b using the control in
9302// imm8, and returns 1 if any character in b was null, and 0 otherwise.
9303// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpistrz
9304FORCE_INLINE int _mm_cmpistrz(__m128i a, __m128i b, const int imm8)
9305{
9306 SSE2NEON_CMPSTR_SET_UPPER(bound, imm8);
9307 int lb;
9308 SSE2NEON_CMPISTRX_LENGTH(b, lb, imm8);
9309 return lb <= (bound - 1);
9310}
9311
9312// Compares the 2 signed 64-bit integers in a and the 2 signed 64-bit integers
9313// in b for greater than.
9315{
9316#if defined(__aarch64__)
9319#else
9320 return vreinterpretq_m128i_s64(vshrq_n_s64(
9322 63));
9323#endif
9324}
9325
9326// Starting with the initial value in crc, accumulates a CRC32 value for
9327// unsigned 16-bit integer v.
9328// https://msdn.microsoft.com/en-us/library/bb531411(v=vs.100)
9329FORCE_INLINE uint32_t _mm_crc32_u16(uint32_t crc, uint16_t v)
9330{
9331#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
9332 __asm__ __volatile__("crc32ch %w[c], %w[c], %w[v]\n\t"
9333 : [c] "+r"(crc)
9334 : [v] "r"(v));
9335#elif (__ARM_ARCH == 8) && defined(__ARM_FEATURE_CRC32)
9336 crc = __crc32ch(crc, v);
9337#else
9338 crc = _mm_crc32_u8(crc, v & 0xff);
9339 crc = _mm_crc32_u8(crc, (v >> 8) & 0xff);
9340#endif
9341 return crc;
9342}
9343
9344// Starting with the initial value in crc, accumulates a CRC32 value for
9345// unsigned 32-bit integer v.
9346// https://msdn.microsoft.com/en-us/library/bb531394(v=vs.100)
9347FORCE_INLINE uint32_t _mm_crc32_u32(uint32_t crc, uint32_t v)
9348{
9349#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
9350 __asm__ __volatile__("crc32cw %w[c], %w[c], %w[v]\n\t"
9351 : [c] "+r"(crc)
9352 : [v] "r"(v));
9353#elif (__ARM_ARCH == 8) && defined(__ARM_FEATURE_CRC32)
9354 crc = __crc32cw(crc, v);
9355#else
9356 crc = _mm_crc32_u16(crc, v & 0xffff);
9357 crc = _mm_crc32_u16(crc, (v >> 16) & 0xffff);
9358#endif
9359 return crc;
9360}
9361
9362// Starting with the initial value in crc, accumulates a CRC32 value for
9363// unsigned 64-bit integer v.
9364// https://msdn.microsoft.com/en-us/library/bb514033(v=vs.100)
9365FORCE_INLINE uint64_t _mm_crc32_u64(uint64_t crc, uint64_t v)
9366{
9367#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
9368 __asm__ __volatile__("crc32cx %w[c], %w[c], %x[v]\n\t"
9369 : [c] "+r"(crc)
9370 : [v] "r"(v));
9371#else
9372 crc = _mm_crc32_u32((uint32_t) (crc), v & 0xffffffff);
9373 crc = _mm_crc32_u32((uint32_t) (crc), (v >> 32) & 0xffffffff);
9374#endif
9375 return crc;
9376}
9377
9378// Starting with the initial value in crc, accumulates a CRC32 value for
9379// unsigned 8-bit integer v.
9380// https://msdn.microsoft.com/en-us/library/bb514036(v=vs.100)
9381FORCE_INLINE uint32_t _mm_crc32_u8(uint32_t crc, uint8_t v)
9382{
9383#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
9384 __asm__ __volatile__("crc32cb %w[c], %w[c], %w[v]\n\t"
9385 : [c] "+r"(crc)
9386 : [v] "r"(v));
9387#elif (__ARM_ARCH == 8) && defined(__ARM_FEATURE_CRC32)
9388 crc = __crc32cb(crc, v);
9389#else
9390 crc ^= v;
9391 for (int bit = 0; bit < 8; bit++) {
9392 if (crc & 1)
9393 crc = (crc >> 1) ^ UINT32_C(0x82f63b78);
9394 else
9395 crc = (crc >> 1);
9396 }
9397#endif
9398 return crc;
9399}
9400
9401/* AES */
9402
9403#if !defined(__ARM_FEATURE_CRYPTO)
9404/* clang-format off */
9405#define SSE2NEON_AES_SBOX(w) \
9406 { \
9407 w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), \
9408 w(0xc5), w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), \
9409 w(0xab), w(0x76), w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), \
9410 w(0x59), w(0x47), w(0xf0), w(0xad), w(0xd4), w(0xa2), w(0xaf), \
9411 w(0x9c), w(0xa4), w(0x72), w(0xc0), w(0xb7), w(0xfd), w(0x93), \
9412 w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc), w(0x34), w(0xa5), \
9413 w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15), w(0x04), \
9414 w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a), \
9415 w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), \
9416 w(0x75), w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), \
9417 w(0x5a), w(0xa0), w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), \
9418 w(0xe3), w(0x2f), w(0x84), w(0x53), w(0xd1), w(0x00), w(0xed), \
9419 w(0x20), w(0xfc), w(0xb1), w(0x5b), w(0x6a), w(0xcb), w(0xbe), \
9420 w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf), w(0xd0), w(0xef), \
9421 w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85), w(0x45), \
9422 w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8), \
9423 w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), \
9424 w(0xf5), w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), \
9425 w(0xf3), w(0xd2), w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), \
9426 w(0x97), w(0x44), w(0x17), w(0xc4), w(0xa7), w(0x7e), w(0x3d), \
9427 w(0x64), w(0x5d), w(0x19), w(0x73), w(0x60), w(0x81), w(0x4f), \
9428 w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88), w(0x46), w(0xee), \
9429 w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb), w(0xe0), \
9430 w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c), \
9431 w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), \
9432 w(0x79), w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), \
9433 w(0x4e), w(0xa9), w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), \
9434 w(0x7a), w(0xae), w(0x08), w(0xba), w(0x78), w(0x25), w(0x2e), \
9435 w(0x1c), w(0xa6), w(0xb4), w(0xc6), w(0xe8), w(0xdd), w(0x74), \
9436 w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a), w(0x70), w(0x3e), \
9437 w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e), w(0x61), \
9438 w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e), \
9439 w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), \
9440 w(0x94), w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), \
9441 w(0x28), w(0xdf), w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), \
9442 w(0xe6), w(0x42), w(0x68), w(0x41), w(0x99), w(0x2d), w(0x0f), \
9443 w(0xb0), w(0x54), w(0xbb), w(0x16) \
9444 }
9445#define SSE2NEON_AES_RSBOX(w) \
9446 { \
9447 w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), \
9448 w(0x38), w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), \
9449 w(0xd7), w(0xfb), w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), \
9450 w(0x2f), w(0xff), w(0x87), w(0x34), w(0x8e), w(0x43), w(0x44), \
9451 w(0xc4), w(0xde), w(0xe9), w(0xcb), w(0x54), w(0x7b), w(0x94), \
9452 w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d), w(0xee), w(0x4c), \
9453 w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e), w(0x08), \
9454 w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2), \
9455 w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), \
9456 w(0x25), w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), \
9457 w(0x98), w(0x16), w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), \
9458 w(0x65), w(0xb6), w(0x92), w(0x6c), w(0x70), w(0x48), w(0x50), \
9459 w(0xfd), w(0xed), w(0xb9), w(0xda), w(0x5e), w(0x15), w(0x46), \
9460 w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84), w(0x90), w(0xd8), \
9461 w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a), w(0xf7), \
9462 w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06), \
9463 w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), \
9464 w(0x02), w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), \
9465 w(0x8a), w(0x6b), w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), \
9466 w(0x67), w(0xdc), w(0xea), w(0x97), w(0xf2), w(0xcf), w(0xce), \
9467 w(0xf0), w(0xb4), w(0xe6), w(0x73), w(0x96), w(0xac), w(0x74), \
9468 w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85), w(0xe2), w(0xf9), \
9469 w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e), w(0x47), \
9470 w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89), \
9471 w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), \
9472 w(0x1b), w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), \
9473 w(0x79), w(0x20), w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), \
9474 w(0xcd), w(0x5a), w(0xf4), w(0x1f), w(0xdd), w(0xa8), w(0x33), \
9475 w(0x88), w(0x07), w(0xc7), w(0x31), w(0xb1), w(0x12), w(0x10), \
9476 w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f), w(0x60), w(0x51), \
9477 w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d), w(0x2d), \
9478 w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef), \
9479 w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), \
9480 w(0xb0), w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), \
9481 w(0x99), w(0x61), w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), \
9482 w(0x77), w(0xd6), w(0x26), w(0xe1), w(0x69), w(0x14), w(0x63), \
9483 w(0x55), w(0x21), w(0x0c), w(0x7d) \
9484 }
9485/* clang-format on */
9486
9487/* X Macro trick. See https://en.wikipedia.org/wiki/X_Macro */
9488#define SSE2NEON_AES_H0(x) (x)
9489static const uint8_t _sse2neon_sbox[256] = SSE2NEON_AES_SBOX(SSE2NEON_AES_H0);
9490static const uint8_t _sse2neon_rsbox[256] = SSE2NEON_AES_RSBOX(SSE2NEON_AES_H0);
9491#undef SSE2NEON_AES_H0
9492
9493/* x_time function and matrix multiply function */
9494#if !defined(__aarch64__)
9495#define SSE2NEON_XT(x) (((x) << 1) ^ ((((x) >> 7) & 1) * 0x1b))
9496#define SSE2NEON_MULTIPLY(x, y) \
9497 (((y & 1) * x) ^ ((y >> 1 & 1) * SSE2NEON_XT(x)) ^ \
9498 ((y >> 2 & 1) * SSE2NEON_XT(SSE2NEON_XT(x))) ^ \
9499 ((y >> 3 & 1) * SSE2NEON_XT(SSE2NEON_XT(SSE2NEON_XT(x)))) ^ \
9500 ((y >> 4 & 1) * SSE2NEON_XT(SSE2NEON_XT(SSE2NEON_XT(SSE2NEON_XT(x))))))
9501#endif
9502
9503// In the absence of crypto extensions, implement aesenc using regular neon
9504// intrinsics instead. See:
9505// https://www.workofard.com/2017/01/accelerated-aes-for-the-arm64-linux-kernel/
9506// https://www.workofard.com/2017/07/ghash-for-low-end-cores/ and
9507// https://github.com/ColinIanKing/linux-next-mirror/blob/b5f466091e130caaf0735976648f72bd5e09aa84/crypto/aegis128-neon-inner.c#L52
9508// for more information Reproduced with permission of the author.
9510{
9511#if defined(__aarch64__)
9512 static const uint8_t shift_rows[] = {
9513 0x0, 0x5, 0xa, 0xf, 0x4, 0x9, 0xe, 0x3,
9514 0x8, 0xd, 0x2, 0x7, 0xc, 0x1, 0x6, 0xb,
9515 };
9516 static const uint8_t ror32by8[] = {
9517 0x1, 0x2, 0x3, 0x0, 0x5, 0x6, 0x7, 0x4,
9518 0x9, 0xa, 0xb, 0x8, 0xd, 0xe, 0xf, 0xc,
9519 };
9520
9521 uint8x16_t v;
9522 uint8x16_t w = vreinterpretq_u8_m128i(a);
9523
9524 /* shift rows */
9525 w = vqtbl1q_u8(w, vld1q_u8(shift_rows));
9526
9527 /* sub bytes */
9528 // Here, we separate the whole 256-bytes table into 4 64-bytes tables, and
9529 // look up each of the table. After each lookup, we load the next table
9530 // which locates at the next 64-bytes. In the meantime, the index in the
9531 // table would be smaller than it was, so the index parameters of
9532 // `vqtbx4q_u8()` need to be added the same constant as the loaded tables.
9533 v = vqtbl4q_u8(_sse2neon_vld1q_u8_x4(_sse2neon_sbox), w);
9534 // 'w-0x40' equals to 'vsubq_u8(w, vdupq_n_u8(0x40))'
9535 v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(_sse2neon_sbox + 0x40), w - 0x40);
9536 v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(_sse2neon_sbox + 0x80), w - 0x80);
9537 v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(_sse2neon_sbox + 0xc0), w - 0xc0);
9538
9539 /* mix columns */
9540 w = (v << 1) ^ (uint8x16_t) (((int8x16_t) v >> 7) & 0x1b);
9541 w ^= (uint8x16_t) vrev32q_u16((uint16x8_t) v);
9542 w ^= vqtbl1q_u8(v ^ w, vld1q_u8(ror32by8));
9543
9544 /* add round key */
9545 return vreinterpretq_m128i_u8(w) ^ RoundKey;
9546
9547#else /* ARMv7-A implementation for a table-based AES */
9548#define SSE2NEON_AES_B2W(b0, b1, b2, b3) \
9549 (((uint32_t) (b3) << 24) | ((uint32_t) (b2) << 16) | \
9550 ((uint32_t) (b1) << 8) | (uint32_t) (b0))
9551// muliplying 'x' by 2 in GF(2^8)
9552#define SSE2NEON_AES_F2(x) ((x << 1) ^ (((x >> 7) & 1) * 0x011b /* WPOLY */))
9553// muliplying 'x' by 3 in GF(2^8)
9554#define SSE2NEON_AES_F3(x) (SSE2NEON_AES_F2(x) ^ x)
9555#define SSE2NEON_AES_U0(p) \
9556 SSE2NEON_AES_B2W(SSE2NEON_AES_F2(p), p, p, SSE2NEON_AES_F3(p))
9557#define SSE2NEON_AES_U1(p) \
9558 SSE2NEON_AES_B2W(SSE2NEON_AES_F3(p), SSE2NEON_AES_F2(p), p, p)
9559#define SSE2NEON_AES_U2(p) \
9560 SSE2NEON_AES_B2W(p, SSE2NEON_AES_F3(p), SSE2NEON_AES_F2(p), p)
9561#define SSE2NEON_AES_U3(p) \
9562 SSE2NEON_AES_B2W(p, p, SSE2NEON_AES_F3(p), SSE2NEON_AES_F2(p))
9563
9564 // this generates a table containing every possible permutation of
9565 // shift_rows() and sub_bytes() with mix_columns().
9566 static const uint32_t ALIGN_STRUCT(16) aes_table[4][256] = {
9571 };
9572#undef SSE2NEON_AES_B2W
9573#undef SSE2NEON_AES_F2
9574#undef SSE2NEON_AES_F3
9575#undef SSE2NEON_AES_U0
9576#undef SSE2NEON_AES_U1
9577#undef SSE2NEON_AES_U2
9578#undef SSE2NEON_AES_U3
9579
9580 uint32_t x0 = _mm_cvtsi128_si32(a); // get a[31:0]
9581 uint32_t x1 =
9582 _mm_cvtsi128_si32(_mm_shuffle_epi32(a, 0x55)); // get a[63:32]
9583 uint32_t x2 =
9584 _mm_cvtsi128_si32(_mm_shuffle_epi32(a, 0xAA)); // get a[95:64]
9585 uint32_t x3 =
9586 _mm_cvtsi128_si32(_mm_shuffle_epi32(a, 0xFF)); // get a[127:96]
9587
9588 // finish the modulo addition step in mix_columns()
9589 __m128i out = _mm_set_epi32(
9590 (aes_table[0][x3 & 0xff] ^ aes_table[1][(x0 >> 8) & 0xff] ^
9591 aes_table[2][(x1 >> 16) & 0xff] ^ aes_table[3][x2 >> 24]),
9592 (aes_table[0][x2 & 0xff] ^ aes_table[1][(x3 >> 8) & 0xff] ^
9593 aes_table[2][(x0 >> 16) & 0xff] ^ aes_table[3][x1 >> 24]),
9594 (aes_table[0][x1 & 0xff] ^ aes_table[1][(x2 >> 8) & 0xff] ^
9595 aes_table[2][(x3 >> 16) & 0xff] ^ aes_table[3][x0 >> 24]),
9596 (aes_table[0][x0 & 0xff] ^ aes_table[1][(x1 >> 8) & 0xff] ^
9597 aes_table[2][(x2 >> 16) & 0xff] ^ aes_table[3][x3 >> 24]));
9598
9599 return _mm_xor_si128(out, RoundKey);
9600#endif
9601}
9602
9603// Perform one round of an AES decryption flow on data (state) in a using the
9604// round key in RoundKey, and store the result in dst.
9605// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdec_si128
9607{
9608#if defined(__aarch64__)
9609 static const uint8_t inv_shift_rows[] = {
9610 0x0, 0xd, 0xa, 0x7, 0x4, 0x1, 0xe, 0xb,
9611 0x8, 0x5, 0x2, 0xf, 0xc, 0x9, 0x6, 0x3,
9612 };
9613 static const uint8_t ror32by8[] = {
9614 0x1, 0x2, 0x3, 0x0, 0x5, 0x6, 0x7, 0x4,
9615 0x9, 0xa, 0xb, 0x8, 0xd, 0xe, 0xf, 0xc,
9616 };
9617
9618 uint8x16_t v;
9619 uint8x16_t w = vreinterpretq_u8_m128i(a);
9620
9621 // inverse shift rows
9622 w = vqtbl1q_u8(w, vld1q_u8(inv_shift_rows));
9623
9624 // inverse sub bytes
9625 v = vqtbl4q_u8(_sse2neon_vld1q_u8_x4(_sse2neon_rsbox), w);
9626 v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(_sse2neon_rsbox + 0x40), w - 0x40);
9627 v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(_sse2neon_rsbox + 0x80), w - 0x80);
9628 v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(_sse2neon_rsbox + 0xc0), w - 0xc0);
9629
9630 // inverse mix columns
9631 // muliplying 'v' by 4 in GF(2^8)
9632 w = (v << 1) ^ (uint8x16_t) (((int8x16_t) v >> 7) & 0x1b);
9633 w = (w << 1) ^ (uint8x16_t) (((int8x16_t) w >> 7) & 0x1b);
9634 v ^= w;
9635 v ^= (uint8x16_t) vrev32q_u16((uint16x8_t) w);
9636
9637 w = (v << 1) ^ (uint8x16_t) (((int8x16_t) v >> 7) &
9638 0x1b); // muliplying 'v' by 2 in GF(2^8)
9639 w ^= (uint8x16_t) vrev32q_u16((uint16x8_t) v);
9640 w ^= vqtbl1q_u8(v ^ w, vld1q_u8(ror32by8));
9641
9642 // add round key
9643 return vreinterpretq_m128i_u8(w) ^ RoundKey;
9644
9645#else /* ARMv7-A NEON implementation */
9646 /* FIXME: optimized for NEON */
9647 uint8_t i, e, f, g, h, v[4][4];
9648 uint8_t *_a = (uint8_t *) &a;
9649 for (i = 0; i < 16; ++i) {
9650 v[((i / 4) + (i % 4)) % 4][i % 4] = _sse2neon_rsbox[_a[i]];
9651 }
9652
9653 // inverse mix columns
9654 for (i = 0; i < 4; ++i) {
9655 e = v[i][0];
9656 f = v[i][1];
9657 g = v[i][2];
9658 h = v[i][3];
9659
9660 v[i][0] = SSE2NEON_MULTIPLY(e, 0x0e) ^ SSE2NEON_MULTIPLY(f, 0x0b) ^
9661 SSE2NEON_MULTIPLY(g, 0x0d) ^ SSE2NEON_MULTIPLY(h, 0x09);
9662 v[i][1] = SSE2NEON_MULTIPLY(e, 0x09) ^ SSE2NEON_MULTIPLY(f, 0x0e) ^
9663 SSE2NEON_MULTIPLY(g, 0x0b) ^ SSE2NEON_MULTIPLY(h, 0x0d);
9664 v[i][2] = SSE2NEON_MULTIPLY(e, 0x0d) ^ SSE2NEON_MULTIPLY(f, 0x09) ^
9665 SSE2NEON_MULTIPLY(g, 0x0e) ^ SSE2NEON_MULTIPLY(h, 0x0b);
9666 v[i][3] = SSE2NEON_MULTIPLY(e, 0x0b) ^ SSE2NEON_MULTIPLY(f, 0x0d) ^
9667 SSE2NEON_MULTIPLY(g, 0x09) ^ SSE2NEON_MULTIPLY(h, 0x0e);
9668 }
9669
9670 return vreinterpretq_m128i_u8(vld1q_u8((uint8_t *) v)) ^ RoundKey;
9671#endif
9672}
9673
9674// Perform the last round of an AES encryption flow on data (state) in a using
9675// the round key in RoundKey, and store the result in dst.
9676// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenclast_si128
9678{
9679#if defined(__aarch64__)
9680 static const uint8_t shift_rows[] = {
9681 0x0, 0x5, 0xa, 0xf, 0x4, 0x9, 0xe, 0x3,
9682 0x8, 0xd, 0x2, 0x7, 0xc, 0x1, 0x6, 0xb,
9683 };
9684
9685 uint8x16_t v;
9686 uint8x16_t w = vreinterpretq_u8_m128i(a);
9687
9688 // shift rows
9689 w = vqtbl1q_u8(w, vld1q_u8(shift_rows));
9690
9691 // sub bytes
9692 v = vqtbl4q_u8(_sse2neon_vld1q_u8_x4(_sse2neon_sbox), w);
9693 v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(_sse2neon_sbox + 0x40), w - 0x40);
9694 v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(_sse2neon_sbox + 0x80), w - 0x80);
9695 v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(_sse2neon_sbox + 0xc0), w - 0xc0);
9696
9697 // add round key
9698 return vreinterpretq_m128i_u8(v) ^ RoundKey;
9699
9700#else /* ARMv7-A implementation */
9701 uint8_t v[16] = {
9702 _sse2neon_sbox[vgetq_lane_u8(vreinterpretq_u8_m128i(a), 0)],
9703 _sse2neon_sbox[vgetq_lane_u8(vreinterpretq_u8_m128i(a), 5)],
9704 _sse2neon_sbox[vgetq_lane_u8(vreinterpretq_u8_m128i(a), 10)],
9705 _sse2neon_sbox[vgetq_lane_u8(vreinterpretq_u8_m128i(a), 15)],
9706 _sse2neon_sbox[vgetq_lane_u8(vreinterpretq_u8_m128i(a), 4)],
9707 _sse2neon_sbox[vgetq_lane_u8(vreinterpretq_u8_m128i(a), 9)],
9708 _sse2neon_sbox[vgetq_lane_u8(vreinterpretq_u8_m128i(a), 14)],
9709 _sse2neon_sbox[vgetq_lane_u8(vreinterpretq_u8_m128i(a), 3)],
9710 _sse2neon_sbox[vgetq_lane_u8(vreinterpretq_u8_m128i(a), 8)],
9711 _sse2neon_sbox[vgetq_lane_u8(vreinterpretq_u8_m128i(a), 13)],
9712 _sse2neon_sbox[vgetq_lane_u8(vreinterpretq_u8_m128i(a), 2)],
9713 _sse2neon_sbox[vgetq_lane_u8(vreinterpretq_u8_m128i(a), 7)],
9714 _sse2neon_sbox[vgetq_lane_u8(vreinterpretq_u8_m128i(a), 12)],
9715 _sse2neon_sbox[vgetq_lane_u8(vreinterpretq_u8_m128i(a), 1)],
9716 _sse2neon_sbox[vgetq_lane_u8(vreinterpretq_u8_m128i(a), 6)],
9717 _sse2neon_sbox[vgetq_lane_u8(vreinterpretq_u8_m128i(a), 11)],
9718 };
9719
9720 return vreinterpretq_m128i_u8(vld1q_u8(v)) ^ RoundKey;
9721#endif
9722}
9723
9724// Perform the last round of an AES decryption flow on data (state) in a using
9725// the round key in RoundKey, and store the result in dst.
9726// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdeclast_si128
9728{
9729#if defined(__aarch64__)
9730 static const uint8_t inv_shift_rows[] = {
9731 0x0, 0xd, 0xa, 0x7, 0x4, 0x1, 0xe, 0xb,
9732 0x8, 0x5, 0x2, 0xf, 0xc, 0x9, 0x6, 0x3,
9733 };
9734
9735 uint8x16_t v;
9736 uint8x16_t w = vreinterpretq_u8_m128i(a);
9737
9738 // inverse shift rows
9739 w = vqtbl1q_u8(w, vld1q_u8(inv_shift_rows));
9740
9741 // inverse sub bytes
9742 v = vqtbl4q_u8(_sse2neon_vld1q_u8_x4(_sse2neon_rsbox), w);
9743 v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(_sse2neon_rsbox + 0x40), w - 0x40);
9744 v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(_sse2neon_rsbox + 0x80), w - 0x80);
9745 v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(_sse2neon_rsbox + 0xc0), w - 0xc0);
9746
9747 // add round key
9748 return vreinterpretq_m128i_u8(v) ^ RoundKey;
9749
9750#else /* ARMv7-A NEON implementation */
9751 /* FIXME: optimized for NEON */
9752 uint8_t v[4][4];
9753 uint8_t *_a = (uint8_t *) &a;
9754 for (int i = 0; i < 16; ++i) {
9755 v[((i / 4) + (i % 4)) % 4][i % 4] = _sse2neon_rsbox[_a[i]];
9756 }
9757
9758 return vreinterpretq_m128i_u8(vld1q_u8((uint8_t *) v)) ^ RoundKey;
9759#endif
9760}
9761
9762// Perform the InvMixColumns transformation on a and store the result in dst.
9763// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesimc_si128
9765{
9766#if defined(__aarch64__)
9767 static const uint8_t ror32by8[] = {
9768 0x1, 0x2, 0x3, 0x0, 0x5, 0x6, 0x7, 0x4,
9769 0x9, 0xa, 0xb, 0x8, 0xd, 0xe, 0xf, 0xc,
9770 };
9771 uint8x16_t v = vreinterpretq_u8_m128i(a);
9772 uint8x16_t w;
9773
9774 // multiplying 'v' by 4 in GF(2^8)
9775 w = (v << 1) ^ (uint8x16_t) (((int8x16_t) v >> 7) & 0x1b);
9776 w = (w << 1) ^ (uint8x16_t) (((int8x16_t) w >> 7) & 0x1b);
9777 v ^= w;
9778 v ^= (uint8x16_t) vrev32q_u16((uint16x8_t) w);
9779
9780 // multiplying 'v' by 2 in GF(2^8)
9781 w = (v << 1) ^ (uint8x16_t) (((int8x16_t) v >> 7) & 0x1b);
9782 w ^= (uint8x16_t) vrev32q_u16((uint16x8_t) v);
9783 w ^= vqtbl1q_u8(v ^ w, vld1q_u8(ror32by8));
9784 return vreinterpretq_m128i_u8(w);
9785
9786#else /* ARMv7-A NEON implementation */
9787 uint8_t i, e, f, g, h, v[4][4];
9788 vst1q_u8((uint8_t *) v, vreinterpretq_u8_m128i(a));
9789 for (i = 0; i < 4; ++i) {
9790 e = v[i][0];
9791 f = v[i][1];
9792 g = v[i][2];
9793 h = v[i][3];
9794
9795 v[i][0] = SSE2NEON_MULTIPLY(e, 0x0e) ^ SSE2NEON_MULTIPLY(f, 0x0b) ^
9796 SSE2NEON_MULTIPLY(g, 0x0d) ^ SSE2NEON_MULTIPLY(h, 0x09);
9797 v[i][1] = SSE2NEON_MULTIPLY(e, 0x09) ^ SSE2NEON_MULTIPLY(f, 0x0e) ^
9798 SSE2NEON_MULTIPLY(g, 0x0b) ^ SSE2NEON_MULTIPLY(h, 0x0d);
9799 v[i][2] = SSE2NEON_MULTIPLY(e, 0x0d) ^ SSE2NEON_MULTIPLY(f, 0x09) ^
9800 SSE2NEON_MULTIPLY(g, 0x0e) ^ SSE2NEON_MULTIPLY(h, 0x0b);
9801 v[i][3] = SSE2NEON_MULTIPLY(e, 0x0b) ^ SSE2NEON_MULTIPLY(f, 0x0d) ^
9802 SSE2NEON_MULTIPLY(g, 0x09) ^ SSE2NEON_MULTIPLY(h, 0x0e);
9803 }
9804
9805 return vreinterpretq_m128i_u8(vld1q_u8((uint8_t *) v));
9806#endif
9807}
9808
9809// Emits the Advanced Encryption Standard (AES) instruction aeskeygenassist.
9810// This instruction generates a round key for AES encryption. See
9811// https://kazakov.life/2017/11/01/cryptocurrency-mining-on-ios-devices/
9812// for details.
9813//
9814// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aeskeygenassist_si128
9816{
9817#if defined(__aarch64__)
9818 uint8x16_t _a = vreinterpretq_u8_m128i(a);
9819 uint8x16_t v = vqtbl4q_u8(_sse2neon_vld1q_u8_x4(_sse2neon_sbox), _a);
9820 v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(_sse2neon_sbox + 0x40), _a - 0x40);
9821 v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(_sse2neon_sbox + 0x80), _a - 0x80);
9822 v = vqtbx4q_u8(v, _sse2neon_vld1q_u8_x4(_sse2neon_sbox + 0xc0), _a - 0xc0);
9823
9824 uint32x4_t select_mask = {0xffffffff, 0x0, 0xffffffff, 0x0};
9825 uint64x2_t v_mask = vshrq_n_u64(vreinterpretq_u64_u8(v), 32);
9826 uint32x4_t x = vbslq_u32(select_mask, vreinterpretq_u32_u64(v_mask),
9827 vreinterpretq_u32_u8(v));
9828 uint32x4_t ror_x = vorrq_u32(vshrq_n_u32(x, 8), vshlq_n_u32(x, 24));
9829 uint32x4_t ror_xor_x = veorq_u32(ror_x, vdupq_n_u32(rcon));
9830
9831 return vreinterpretq_m128i_u32(vbslq_u32(select_mask, x, ror_xor_x));
9832
9833#else /* ARMv7-A NEON implementation */
9834 uint32_t X1 = _mm_cvtsi128_si32(_mm_shuffle_epi32(a, 0x55));
9835 uint32_t X3 = _mm_cvtsi128_si32(_mm_shuffle_epi32(a, 0xFF));
9836 for (int i = 0; i < 4; ++i) {
9837 ((uint8_t *) &X1)[i] = _sse2neon_sbox[((uint8_t *) &X1)[i]];
9838 ((uint8_t *) &X3)[i] = _sse2neon_sbox[((uint8_t *) &X3)[i]];
9839 }
9840 return _mm_set_epi32(((X3 >> 8) | (X3 << 24)) ^ rcon, X3,
9841 ((X1 >> 8) | (X1 << 24)) ^ rcon, X1);
9842#endif
9843}
9844#undef SSE2NEON_AES_SBOX
9845#undef SSE2NEON_AES_RSBOX
9846
9847#if defined(__aarch64__)
9848#undef SSE2NEON_XT
9849#undef SSE2NEON_MULTIPLY
9850#endif
9851
9852#else /* __ARM_FEATURE_CRYPTO */
9853// Implements equivalent of 'aesenc' by combining AESE (with an empty key) and
9854// AESMC and then manually applying the real key as an xor operation. This
9855// unfortunately means an additional xor op; the compiler should be able to
9856// optimize this away for repeated calls however. See
9857// https://blog.michaelbrase.com/2018/05/08/emulating-x86-aes-intrinsics-on-armv8-a
9858// for more details.
9860{
9862 vaesmcq_u8(vaeseq_u8(vreinterpretq_u8_m128i(a), vdupq_n_u8(0))) ^
9864}
9865
9866// Perform one round of an AES decryption flow on data (state) in a using the
9867// round key in RoundKey, and store the result in dst.
9868// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdec_si128
9870{
9871 return vreinterpretq_m128i_u8(veorq_u8(
9872 vaesimcq_u8(vaesdq_u8(vreinterpretq_u8_m128i(a), vdupq_n_u8(0))),
9873 vreinterpretq_u8_m128i(RoundKey)));
9874}
9875
9876// Perform the last round of an AES encryption flow on data (state) in a using
9877// the round key in RoundKey, and store the result in dst.
9878// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenclast_si128
9880{
9881 return _mm_xor_si128(vreinterpretq_m128i_u8(vaeseq_u8(
9882 vreinterpretq_u8_m128i(a), vdupq_n_u8(0))),
9883 RoundKey);
9884}
9885
9886// Perform the last round of an AES decryption flow on data (state) in a using
9887// the round key in RoundKey, and store the result in dst.
9888// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdeclast_si128
9890{
9892 vaesdq_u8(vreinterpretq_u8_m128i(a), vdupq_n_u8(0))) ^
9893 vreinterpretq_u8_m128i(RoundKey);
9894}
9895
9896// Perform the InvMixColumns transformation on a and store the result in dst.
9897// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesimc_si128
9899{
9900 return vreinterpretq_m128i_u8(vaesimcq_u8(a));
9901}
9902
9903// Assist in expanding the AES cipher key by computing steps towards generating
9904// a round key for encryption cipher using data from a and an 8-bit round
9905// constant specified in imm8, and store the result in dst."
9906// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aeskeygenassist_si128
9908{
9909 // AESE does ShiftRows and SubBytes on A
9910 uint8x16_t u8 = vaeseq_u8(vreinterpretq_u8_m128i(a), vdupq_n_u8(0));
9911
9912 uint8x16_t dest = {
9913 // Undo ShiftRows step from AESE and extract X1 and X3
9914 u8[0x4], u8[0x1], u8[0xE], u8[0xB], // SubBytes(X1)
9915 u8[0x1], u8[0xE], u8[0xB], u8[0x4], // ROT(SubBytes(X1))
9916 u8[0xC], u8[0x9], u8[0x6], u8[0x3], // SubBytes(X3)
9917 u8[0x9], u8[0x6], u8[0x3], u8[0xC], // ROT(SubBytes(X3))
9918 };
9919 uint32x4_t r = {0, (unsigned) rcon, 0, (unsigned) rcon};
9921}
9922#endif
9923
9924/* Others */
9925
9926// Perform a carry-less multiplication of two 64-bit integers, selected from a
9927// and b according to imm8, and store the results in dst.
9928// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_clmulepi64_si128
9930{
9931 uint64x2_t a = vreinterpretq_u64_m128i(_a);
9932 uint64x2_t b = vreinterpretq_u64_m128i(_b);
9933 switch (imm & 0x11) {
9934 case 0x00:
9936 _sse2neon_vmull_p64(vget_low_u64(a), vget_low_u64(b)));
9937 case 0x01:
9939 _sse2neon_vmull_p64(vget_high_u64(a), vget_low_u64(b)));
9940 case 0x10:
9942 _sse2neon_vmull_p64(vget_low_u64(a), vget_high_u64(b)));
9943 case 0x11:
9945 _sse2neon_vmull_p64(vget_high_u64(a), vget_high_u64(b)));
9946 default:
9947 abort();
9948 }
9949}
9950
9952{
9953 union {
9954 fpcr_bitfield field;
9955#if defined(__aarch64__)
9956 uint64_t value;
9957#else
9958 uint32_t value;
9959#endif
9960 } r;
9961
9962#if defined(__aarch64__)
9963 __asm__ __volatile__("mrs %0, FPCR" : "=r"(r.value)); /* read */
9964#else
9965 __asm__ __volatile__("vmrs %0, FPSCR" : "=r"(r.value)); /* read */
9966#endif
9967
9968 return r.field.bit24 ? _MM_DENORMALS_ZERO_ON : _MM_DENORMALS_ZERO_OFF;
9969}
9970
9971// Count the number of bits set to 1 in unsigned 32-bit integer a, and
9972// return that count in dst.
9973// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_popcnt_u32
9974FORCE_INLINE int _mm_popcnt_u32(unsigned int a)
9975{
9976#if defined(__aarch64__)
9977#if __has_builtin(__builtin_popcount)
9978 return __builtin_popcount(a);
9979#else
9980 return (int) vaddlv_u8(vcnt_u8(vcreate_u8((uint64_t) a)));
9981#endif
9982#else
9983 uint32_t count = 0;
9984 uint8x8_t input_val, count8x8_val;
9985 uint16x4_t count16x4_val;
9986 uint32x2_t count32x2_val;
9987
9988 input_val = vld1_u8((uint8_t *) &a);
9989 count8x8_val = vcnt_u8(input_val);
9990 count16x4_val = vpaddl_u8(count8x8_val);
9991 count32x2_val = vpaddl_u16(count16x4_val);
9992
9993 vst1_u32(&count, count32x2_val);
9994 return count;
9995#endif
9996}
9997
9998// Count the number of bits set to 1 in unsigned 64-bit integer a, and
9999// return that count in dst.
10000// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_popcnt_u64
10001FORCE_INLINE int64_t _mm_popcnt_u64(uint64_t a)
10002{
10003#if defined(__aarch64__)
10004#if __has_builtin(__builtin_popcountll)
10005 return __builtin_popcountll(a);
10006#else
10007 return (int64_t) vaddlv_u8(vcnt_u8(vcreate_u8(a)));
10008#endif
10009#else
10010 uint64_t count = 0;
10011 uint8x8_t input_val, count8x8_val;
10012 uint16x4_t count16x4_val;
10013 uint32x2_t count32x2_val;
10014 uint64x1_t count64x1_val;
10015
10016 input_val = vld1_u8((uint8_t *) &a);
10017 count8x8_val = vcnt_u8(input_val);
10018 count16x4_val = vpaddl_u8(count8x8_val);
10019 count32x2_val = vpaddl_u16(count16x4_val);
10020 count64x1_val = vpaddl_u32(count32x2_val);
10021 vst1_u64(&count, count64x1_val);
10022 return count;
10023#endif
10024}
10025
10027{
10028 // AArch32 Advanced SIMD arithmetic always uses the Flush-to-zero setting,
10029 // regardless of the value of the FZ bit.
10030 union {
10031 fpcr_bitfield field;
10032#if defined(__aarch64__)
10033 uint64_t value;
10034#else
10035 uint32_t value;
10036#endif
10037 } r;
10038
10039#if defined(__aarch64__)
10040 __asm__ __volatile__("mrs %0, FPCR" : "=r"(r.value)); /* read */
10041#else
10042 __asm__ __volatile__("vmrs %0, FPSCR" : "=r"(r.value)); /* read */
10043#endif
10044
10045 r.field.bit24 = (flag & _MM_DENORMALS_ZERO_MASK) == _MM_DENORMALS_ZERO_ON;
10046
10047#if defined(__aarch64__)
10048 __asm__ __volatile__("msr FPCR, %0" ::"r"(r)); /* write */
10049#else
10050 __asm__ __volatile__("vmsr FPSCR, %0" ::"r"(r)); /* write */
10051#endif
10052}
10053
10054// Return the current 64-bit value of the processor's time-stamp counter.
10055// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=rdtsc
10056
10057FORCE_INLINE uint64_t _rdtsc(void)
10058{
10059#if defined(__aarch64__)
10060 uint64_t val;
10061
10062 /* According to ARM DDI 0487F.c, from Armv8.0 to Armv8.5 inclusive, the
10063 * system counter is at least 56 bits wide; from Armv8.6, the counter
10064 * must be 64 bits wide. So the system counter could be less than 64
10065 * bits wide and it is attributed with the flag 'cap_user_time_short'
10066 * is true.
10067 */
10068 __asm__ __volatile__("mrs %0, cntvct_el0" : "=r"(val));
10069
10070 return val;
10071#else
10072 uint32_t pmccntr, pmuseren, pmcntenset;
10073 // Read the user mode Performance Monitoring Unit (PMU)
10074 // User Enable Register (PMUSERENR) access permissions.
10075 __asm__ __volatile__("mrc p15, 0, %0, c9, c14, 0" : "=r"(pmuseren));
10076 if (pmuseren & 1) { // Allows reading PMUSERENR for user mode code.
10077 __asm__ __volatile__("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcntenset));
10078 if (pmcntenset & 0x80000000UL) { // Is it counting?
10079 __asm__ __volatile__("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr));
10080 // The counter is set up to count every 64th cycle
10081 return (uint64_t) (pmccntr) << 6;
10082 }
10083 }
10084
10085 // Fallback to syscall as we can't enable PMUSERENR in user mode.
10086 struct timeval tv;
10087 gettimeofday(&tv, NULL);
10088 return (uint64_t) (tv.tv_sec) * 1000000 + tv.tv_usec;
10089#endif
10090}
10091
10092#if defined(__GNUC__) || defined(__clang__)
10093#pragma pop_macro("ALIGN_STRUCT")
10094#pragma pop_macro("FORCE_INLINE")
10095#endif
10096
10097#if defined(__GNUC__) && !defined(__clang__)
10098#pragma GCC pop_options
10099#endif
10100
10101#endif
double f
FORCE_INLINE int _mm_comige_sd(__m128d a, __m128d b)
Definition sse2neon.h:3971
FORCE_INLINE __m128 _mm_xor_ps(__m128 a, __m128 b)
Definition sse2neon.h:3087
FORCE_INLINE __m128 _mm_cmpnlt_ps(__m128 a, __m128 b)
Definition sse2neon.h:1384
FORCE_INLINE void _sse2neon_mm_set_flush_zero_mode(unsigned int flag)
Definition sse2neon.h:2506
FORCE_INLINE int _mm_comieq_ss(__m128 a, __m128 b)
Definition sse2neon.h:1444
FORCE_INLINE __m128 _mm_cmpngt_ps(__m128 a, __m128 b)
Definition sse2neon.h:1354
FORCE_INLINE __m128 _mm_movehdup_ps(__m128 a)
Definition sse2neon.h:6784
FORCE_INLINE __m128i _mm_abs_epi8(__m128i a)
Definition sse2neon.h:6858
#define vreinterpret_m64_f32(x)
Definition sse2neon.h:392
FORCE_INLINE __m128i _mm_cmpeq_epi64(__m128i a, __m128i b)
Definition sse2neon.h:7702
#define SSE2NEON_CMPSTR_GENERATE_MASK(dst)
Definition sse2neon.h:9101
FORCE_INLINE uint16_t _sse2neon_vaddvq_u16(uint16x8_t a)
Definition sse2neon.h:574
#define _MM_FROUND_TO_POS_INF
Definition sse2neon.h:273
#define vreinterpretq_u32_m128d(x)
Definition sse2neon.h:434
#define vreinterpret_m64_s32(x)
Definition sse2neon.h:383
FORCE_INLINE __m128i _mm_unpackhi_epi16(__m128i a, __m128i b)
Definition sse2neon.h:6420
FORCE_INLINE __m128i _mm_setr_epi64(__m64 e1, __m64 e0)
Definition sse2neon.h:5452
#define SSE2NEON_CACHELINE_SIZE
Definition sse2neon.h:198
FORCE_INLINE int _mm_cvt_ss2si(__m128 a)
Definition sse2neon.h:1556
FORCE_INLINE __m128i _mm_packs_epi32(__m128i a, __m128i b)
Definition sse2neon.h:5212
#define vreinterpretq_m128_s32(x)
Definition sse2neon.h:341
FORCE_INLINE __m128i _mm_max_epi8(__m128i a, __m128i b)
Definition sse2neon.h:8068
FORCE_INLINE __m128d _mm_cvtsi64_sd(__m128d a, int64_t b)
Definition sse2neon.h:4401
FORCE_INLINE __m128i _mm_cmpgt_epi8(__m128i a, __m128i b)
Definition sse2neon.h:3536
FORCE_INLINE __m128i _mm_slli_epi32(__m128i a, int imm)
Definition sse2neon.h:5731
FORCE_INLINE __m64 _mm_avg_pu16(__m64 a, __m64 b)
Definition sse2neon.h:1214
FORCE_INLINE __m128i _mm_min_epi16(__m128i a, __m128i b)
Definition sse2neon.h:4849
FORCE_INLINE __m64 _mm_max_pu8(__m64 a, __m64 b)
Definition sse2neon.h:2140
FORCE_INLINE __m128d _mm_cmpeq_pd(__m128d a, __m128d b)
Definition sse2neon.h:3438
FORCE_INLINE __m128 _mm_sub_ps(__m128 a, __m128 b)
Definition sse2neon.h:2963
FORCE_INLINE __m128d _mm_div_sd(__m128d a, __m128d b)
Definition sse2neon.h:4549
FORCE_INLINE __m128d _mm_and_pd(__m128d a, __m128d b)
Definition sse2neon.h:3245
FORCE_INLINE __m128d _mm_setzero_pd(void)
Definition sse2neon.h:5494
#define SSE2NEON_AES_U2(p)
FORCE_INLINE __m128i _mm_set1_epi16(short w)
Definition sse2neon.h:5365
FORCE_INLINE void _mm_store_si128(__m128i *p, __m128i a)
Definition sse2neon.h:6110
FORCE_INLINE unsigned int _sse2neon_mm_get_flush_zero_mode()
Definition sse2neon.h:1891
FORCE_INLINE __m128 _mm_cvtpi8_ps(__m64 a)
Definition sse2neon.h:1629
#define vreinterpretq_m128_f32(x)
Definition sse2neon.h:331
float32x4_t __m128
Definition sse2neon.h:307
FORCE_INLINE double _mm_cvtsd_f64(__m128d a)
Definition sse2neon.h:4268
FORCE_INLINE __m128i _mm_adds_epi8(__m128i a, __m128i b)
Definition sse2neon.h:3212
FORCE_INLINE int _mm_cmpestrs(__m128i a, int la, __m128i b, int lb, const int imm8)
Definition sse2neon.h:9195
FORCE_INLINE __m128i _mm_loadu_si16(const void *p)
Definition sse2neon.h:2046
FORCE_INLINE __m128i _mm_add_epi64(__m128i a, __m128i b)
Definition sse2neon.h:3122
FORCE_INLINE void _mm_sfence(void)
Definition sse2neon.h:2676
FORCE_INLINE __m128 _mm_load_ss(const float *p)
Definition sse2neon.h:1969
FORCE_INLINE __m128d _mm_cmpeq_sd(__m128d a, __m128d b)
Definition sse2neon.h:3456
FORCE_INLINE void _mm_stream_ps(float *p, __m128 a)
Definition sse2neon.h:2946
FORCE_INLINE __m128i _mm_andnot_si128(__m128i a, __m128i b)
Definition sse2neon.h:3285
#define SSE2NEON_MULTIPLY(x, y)
Definition sse2neon.h:9496
FORCE_INLINE unsigned int _sse2neon_mm_get_denormals_zero_mode()
Definition sse2neon.h:9951
#define SSE2NEON_GENERATE_CMP_RANGES(prefix)
Definition sse2neon.h:8869
FORCE_INLINE __m128i _mm_set_epi8(signed char b15, signed char b14, signed char b13, signed char b12, signed char b11, signed char b10, signed char b9, signed char b8, signed char b7, signed char b6, signed char b5, signed char b4, signed char b3, signed char b2, signed char b1, signed char b0)
Definition sse2neon.h:5302
FORCE_INLINE __m128 _mm_addsub_ps(__m128 a, __m128 b)
Definition sse2neon.h:6669
FORCE_INLINE __m128i _mm_mul_epi32(__m128i a, __m128i b)
Definition sse2neon.h:8284
#define vreinterpretq_m128i_s8(x)
Definition sse2neon.h:358
FORCE_INLINE void _mm_storeu_si16(void *p, __m128i a)
Definition sse2neon.h:2923
FORCE_INLINE __m128i _mm_aesenclast_si128(__m128i a, __m128i RoundKey)
Definition sse2neon.h:9677
FORCE_INLINE __m128i _mm_hsubs_epi16(__m128i _a, __m128i _b)
Definition sse2neon.h:7106
FORCE_INLINE __m128i _mm_unpacklo_epi8(__m128i a, __m128i b)
Definition sse2neon.h:6578
FORCE_INLINE __m128i _mm_shuffle_epi_2301(__m128i a)
Definition sse2neon.h:986
FORCE_INLINE __m128i _mm_adds_epu8(__m128i a, __m128i b)
Definition sse2neon.h:3230
#define vreinterpret_m64_s8(x)
Definition sse2neon.h:381
FORCE_INLINE __m128d _mm_cvtsi32_sd(__m128d a, int32_t b)
Definition sse2neon.h:4364
FORCE_INLINE int _mm_cmpestri(__m128i a, int la, __m128i b, int lb, const int imm8)
Definition sse2neon.h:9159
FORCE_INLINE __m128i _mm_hadd_epi16(__m128i _a, __m128i _b)
Definition sse2neon.h:6958
#define _SIDD_MASKED_NEGATIVE_POLARITY
Definition sse2neon.h:8586
#define vreinterpret_u16_m64(x)
Definition sse2neon.h:396
FORCE_INLINE __m128 _mm_hadd_ps(__m128 a, __m128 b)
Definition sse2neon.h:6700
#define vreinterpretq_m128i_u64(x)
Definition sse2neon.h:366
FORCE_INLINE int _mm_cmpestrz(__m128i a, int la, __m128i b, int lb, const int imm8)
Definition sse2neon.h:9208
FORCE_INLINE __m128i _mm_set_epi32(int, int, int, int)
Definition sse2neon.h:5277
FORCE_INLINE __m128d _mm_cmpord_sd(__m128d a, __m128d b)
Definition sse2neon.h:3894
FORCE_INLINE uint8x16x4_t _sse2neon_vld1q_u8_x4(const uint8_t *p)
Definition sse2neon.h:533
FORCE_INLINE __m128i _mm_unpacklo_epi32(__m128i a, __m128i b)
Definition sse2neon.h:6546
FORCE_INLINE __m128d _mm_cvtps_pd(__m128 a)
Definition sse2neon.h:4251
FORCE_INLINE __m64 _mm_hsub_pi32(__m64 _a, __m64 _b)
Definition sse2neon.h:7091
FORCE_INLINE __m128 _mm_shuffle_ps_1032(__m128 a, __m128 b)
Definition sse2neon.h:690
#define SSE2NEON_CMPSTR_SET_UPPER(var, imm)
Definition sse2neon.h:9074
FORCE_INLINE __m128d _mm_min_pd(__m128d a, __m128d b)
Definition sse2neon.h:4867
#define vreinterpret_m64_s64(x)
Definition sse2neon.h:384
FORCE_INLINE __m128i _mm_cmpistrm(__m128i a, __m128i b, const int imm8)
Definition sse2neon.h:9275
#define vreinterpretq_u8_m128i(x)
Definition sse2neon.h:376
FORCE_INLINE __m128i _mm_srl_epi16(__m128i a, __m128i count)
Definition sse2neon.h:5913
FORCE_INLINE __m128d _mm_ceil_pd(__m128d)
Definition sse2neon.h:7652
FORCE_INLINE void _mm_store_ps1(float *p, __m128 a)
Definition sse2neon.h:2848
#define vreinterpretq_s16_m128i(x)
Definition sse2neon.h:372
#define _MM_FLUSH_ZERO_MASK
Definition sse2neon.h:289
FORCE_INLINE __m128i _mm_mulhi_epi16(__m128i a, __m128i b)
Definition sse2neon.h:5112
#define vreinterpretq_u64_m128d(x)
Definition sse2neon.h:435
FORCE_INLINE __m128 _mm_cmpnge_ps(__m128 a, __m128 b)
Definition sse2neon.h:1339
FORCE_INLINE __m128i _mm_mulhrs_epi16(__m128i a, __m128i b)
Definition sse2neon.h:7213
#define vreinterpretq_s8_m128(x)
Definition sse2neon.h:353
FORCE_INLINE __m128i _mm_movpi64_epi64(__m64 a)
Definition sse2neon.h:5045
FORCE_INLINE void _sse2neon_smp_mb(void)
Definition sse2neon.h:137
FORCE_INLINE __m64 _mm_avg_pu8(__m64 a, __m64 b)
Definition sse2neon.h:1229
FORCE_INLINE __m128i _mm_add_epi32(__m128i a, __m128i b)
Definition sse2neon.h:3113
FORCE_INLINE __m128i _mm_packus_epi32(__m128i a, __m128i b)
Definition sse2neon.h:8312
FORCE_INLINE __m128 _mm_setr_ps(float w, float z, float y, float x)
Definition sse2neon.h:2629
FORCE_INLINE __m128d _mm_load_pd(const double *p)
Definition sse2neon.h:4585
FORCE_INLINE __m128d _mm_cmplt_sd(__m128d a, __m128d b)
Definition sse2neon.h:3685
FORCE_INLINE __m128i _mm_cmpgt_epi32(__m128i a, __m128i b)
Definition sse2neon.h:3521
FORCE_INLINE __m128i _mm_unpackhi_epi32(__m128i a, __m128i b)
Definition sse2neon.h:6436
#define vreinterpret_m64_u8(x)
Definition sse2neon.h:386
#define vreinterpretq_m128d_s32(x)
Definition sse2neon.h:424
FORCE_INLINE void _mm_maskmove_si64(__m64 a, __m64 mask, char *mem_addr)
Definition sse2neon.h:2085
FORCE_INLINE __m128d _mm_mul_sd(__m128d a, __m128d b)
Definition sse2neon.h:5086
FORCE_INLINE __m128 _mm_mul_ss(__m128 a, __m128 b)
Definition sse2neon.h:2313
FORCE_INLINE __m128 _mm_movehl_ps(__m128 __A, __m128 __B)
Definition sse2neon.h:2226
FORCE_INLINE __m128i _mm_sra_epi16(__m128i a, __m128i count)
Definition sse2neon.h:5823
FORCE_INLINE __m128 _mm_div_ps(__m128 a, __m128 b)
Definition sse2neon.h:1846
FORCE_INLINE int _mm_comige_ss(__m128 a, __m128 b)
Definition sse2neon.h:1454
FORCE_INLINE void _mm_storer_ps(float *p, __m128 a)
Definition sse2neon.h:2907
FORCE_INLINE __m128i _mm_sign_epi8(__m128i _a, __m128i _b)
Definition sse2neon.h:7387
FORCE_INLINE __m128d _mm_cmpgt_sd(__m128d a, __m128d b)
Definition sse2neon.h:3567
FORCE_INLINE __m128d _mm_loadr_pd(const double *p)
Definition sse2neon.h:4705
FORCE_INLINE uint32_t _mm_crc32_u32(uint32_t crc, uint32_t v)
Definition sse2neon.h:9347
FORCE_INLINE __m64 _mm_sign_pi32(__m64 _a, __m64 _b)
Definition sse2neon.h:7469
FORCE_INLINE __m128d _mm_loadl_pd(__m128d a, const double *p)
Definition sse2neon.h:4685
FORCE_INLINE __m128d _mm_loadu_pd(const double *p)
Definition sse2neon.h:4718
FORCE_INLINE __m128 _mm_shuffle_ps_0321(__m128 a, __m128 b)
Definition sse2neon.h:707
#define _sse2neon_unlikely(x)
Definition sse2neon.h:92
FORCE_INLINE __m128i _mm_cmpeq_epi16(__m128i a, __m128i b)
Definition sse2neon.h:3412
FORCE_INLINE uint32_t _mm_crc32_u16(uint32_t crc, uint16_t v)
Definition sse2neon.h:9329
FORCE_INLINE __m128i _mm_subs_epu16(__m128i a, __m128i b)
Definition sse2neon.h:6364
FORCE_INLINE __m128d _mm_setr_pd(double e1, double e0)
Definition sse2neon.h:5487
FORCE_INLINE int _mm_cmpistrz(__m128i a, __m128i b, const int imm8)
Definition sse2neon.h:9304
#define vreinterpretq_f32_m128i(x)
Definition sse2neon.h:368
FORCE_INLINE __m128i _mm_shuffle_epi_0321(__m128i a)
Definition sse2neon.h:995
FORCE_INLINE uint8_t _sse2neon_vaddvq_u8(uint8x16_t a)
Definition sse2neon.h:556
FORCE_INLINE __m128i _mm_unpackhi_epi64(__m128i a, __m128i b)
Definition sse2neon.h:6454
FORCE_INLINE __m128i _mm_sub_epi64(__m128i a, __m128i b)
Definition sse2neon.h:6270
FORCE_INLINE __m128i _mm_loadu_si128(const __m128i *p)
Definition sse2neon.h:4725
FORCE_INLINE __m128i _mm_cvtps_epi32(__m128)
Definition sse2neon.h:4189
FORCE_INLINE int _mm_movemask_epi8(__m128i a)
Definition sse2neon.h:4938
FORCE_INLINE __m128i _mm_srl_epi32(__m128i a, __m128i count)
Definition sse2neon.h:5936
FORCE_INLINE __m64 _mm_cvt_ps2pi(__m128 a)
Definition sse2neon.h:1528
#define vreinterpret_m64_u16(x)
Definition sse2neon.h:387
FORCE_INLINE __m128 _mm_cvt_pi2ps(__m128 a, __m64 b)
Definition sse2neon.h:1512
FORCE_INLINE int64_t _mm_cvttss_si64(__m128 a)
Definition sse2neon.h:1833
FORCE_INLINE __m64 _mm_sad_pu8(__m64 a, __m64 b)
Definition sse2neon.h:2494
FORCE_INLINE int _mm_test_all_ones(__m128i a)
Definition sse2neon.h:8496
FORCE_INLINE __m128i _mm_cmpeq_epi32(__m128i, __m128i)
Definition sse2neon.h:3420
#define _MM_DENORMALS_ZERO_OFF
Definition sse2neon.h:295
FORCE_INLINE __m128d _mm_cmpge_sd(__m128d a, __m128d b)
Definition sse2neon.h:3486
FORCE_INLINE int _mm_comineq_sd(__m128d a, __m128d b)
Definition sse2neon.h:4052
FORCE_INLINE __m128i _mm_hadds_epi16(__m128i _a, __m128i _b)
Definition sse2neon.h:7006
FORCE_INLINE __m64 _mm_abs_pi16(__m64 a)
Definition sse2neon.h:6872
FORCE_INLINE void _mm_storeu_si64(void *p, __m128i a)
Definition sse2neon.h:2930
FORCE_INLINE __m128i _mm_blendv_epi8(__m128i _a, __m128i _b, __m128i _mask)
Definition sse2neon.h:7607
FORCE_INLINE __m128d _mm_round_sd(__m128d a, __m128d b, int rounding)
Definition sse2neon.h:8452
FORCE_INLINE __m128d _mm_add_sd(__m128d a, __m128d b)
Definition sse2neon.h:3163
#define vreinterpretq_m128_u32(x)
Definition sse2neon.h:336
FORCE_INLINE void _mm_storeh_pd(double *mem_addr, __m128d a)
Definition sse2neon.h:6127
FORCE_INLINE __m128 _mm_set_ps(float w, float z, float y, float x)
Definition sse2neon.h:2536
FORCE_INLINE __m128d _mm_move_sd(__m128d, __m128d)
Definition sse2neon.h:4927
FORCE_INLINE int _mm_comieq_sd(__m128d a, __m128d b)
Definition sse2neon.h:4031
FORCE_INLINE __m128 _mm_cmpeq_ss(__m128 a, __m128 b)
Definition sse2neon.h:1245
FORCE_INLINE __m128i _mm_cvtpd_epi32(__m128d a)
Definition sse2neon.h:4097
FORCE_INLINE __m128 _mm_cmpge_ps(__m128 a, __m128 b)
Definition sse2neon.h:1252
#define SSE2NEON_AES_U0(p)
#define _sse2neon_const
Definition sse2neon.h:99
#define vreinterpretq_s32_m128i(x)
Definition sse2neon.h:373
#define vreinterpret_s64_m64(x)
Definition sse2neon.h:403
FORCE_INLINE int _mm_testz_si128(__m128i a, __m128i b)
Definition sse2neon.h:8553
FORCE_INLINE __m128i _mm_abs_epi32(__m128i a)
Definition sse2neon.h:6844
#define vreinterpretq_m128i_s16(x)
Definition sse2neon.h:359
FORCE_INLINE __m64 _mm_mul_su32(__m64 a, __m64 b)
Definition sse2neon.h:5097
#define vreinterpretq_f32_m128d(x)
Definition sse2neon.h:437
FORCE_INLINE __m128i _mm_setzero_si128()
Definition sse2neon.h:5505
FORCE_INLINE __m128i _mm_and_si128(__m128i, __m128i)
Definition sse2neon.h:3257
FORCE_INLINE __m128i _mm_adds_epu16(__m128i a, __m128i b)
Definition sse2neon.h:3221
FORCE_INLINE __m64 _mm_cvtps_pi8(__m128 a)
Definition sse2neon.h:1684
FORCE_INLINE __m128 _mm_dp_ps(__m128 a, __m128 b, const int imm)
Definition sse2neon.h:7881
FORCE_INLINE __m128 _mm_sqrt_ss(__m128 in)
Definition sse2neon.h:2823
#define vreinterpretq_m128d_s64(x)
Definition sse2neon.h:425
FORCE_INLINE __m128i _mm_set1_epi32(int)
Definition sse2neon.h:5378
FORCE_INLINE void _mm_setcsr(unsigned int a)
Definition sse2neon.h:2615
FORCE_INLINE __m128i _mm_shuffle_epi_1032(__m128i a)
Definition sse2neon.h:976
float32x4_t __m128d
Definition sse2neon.h:314
FORCE_INLINE __m128 _mm_unpackhi_ps(__m128 a, __m128 b)
Definition sse2neon.h:3049
#define SSE2NEON_AES_RSBOX(w)
Definition sse2neon.h:9445
FORCE_INLINE __m128i _mm_shuffle_epi_0122(__m128i a)
Definition sse2neon.h:1042
FORCE_INLINE int _mm_cmpestrc(__m128i a, int la, __m128i b, int lb, const int imm8)
Definition sse2neon.h:9146
FORCE_INLINE __m128 _mm_rcp_ps(__m128 in)
Definition sse2neon.h:2437
#define vreinterpretq_s8_m128i(x)
Definition sse2neon.h:371
FORCE_INLINE __m128i _mm_max_epu8(__m128i a, __m128i b)
Definition sse2neon.h:4797
FORCE_INLINE __m128i _mm_loadu_si32(const void *p)
Definition sse2neon.h:4736
FORCE_INLINE void _mm_stream_si64(__int64 *p, __int64 a)
Definition sse2neon.h:6237
FORCE_INLINE __m128 _mm_shuffle_ps_2301(__m128 a, __m128 b)
Definition sse2neon.h:700
FORCE_INLINE __m128d _mm_cmpnge_sd(__m128d a, __m128d b)
Definition sse2neon.h:3755
FORCE_INLINE __m128 _mm_shuffle_ps_1001(__m128 a, __m128 b)
Definition sse2neon.h:732
FORCE_INLINE __m128d _mm_cvtpi32_pd(__m64 a)
Definition sse2neon.h:4166
FORCE_INLINE __m128i _mm_madd_epi16(__m128i a, __m128i b)
Definition sse2neon.h:4750
#define SSE2NEON_GENERATE_CMP_EQUAL_ORDERED(prefix)
Definition sse2neon.h:8975
FORCE_INLINE __m128d _mm_floor_pd(__m128d)
Definition sse2neon.h:7947
FORCE_INLINE __m128 _mm_cmpnle_ps(__m128 a, __m128 b)
Definition sse2neon.h:1369
FORCE_INLINE __m128d _mm_ceil_sd(__m128d a, __m128d b)
Definition sse2neon.h:7681
FORCE_INLINE uint64_t _rdtsc(void)
Definition sse2neon.h:10057
FORCE_INLINE __m128i _mm_add_epi16(__m128i a, __m128i b)
Definition sse2neon.h:3098
FORCE_INLINE __m128d _mm_cmplt_pd(__m128d a, __m128d b)
Definition sse2neon.h:3663
FORCE_INLINE int32_t _mm_cvttsd_si32(__m128d a)
Definition sse2neon.h:4490
FORCE_INLINE void _mm_storeu_ps(float *p, __m128 a)
Definition sse2neon.h:2916
FORCE_INLINE __m64 _mm_hsub_pi16(__m64 _a, __m64 _b)
Definition sse2neon.h:7076
FORCE_INLINE __m128d _mm_cmpord_pd(__m128d a, __m128d b)
Definition sse2neon.h:3862
#define vreinterpretq_s64_m128d(x)
Definition sse2neon.h:432
FORCE_INLINE __m128i _mm_setr_epi32(int i3, int i2, int i1, int i0)
Definition sse2neon.h:5444
FORCE_INLINE __m128i _mm_cvtepu8_epi16(__m128i a)
Definition sse2neon.h:7802
FORCE_INLINE __m128 _mm_moveldup_ps(__m128 a)
Definition sse2neon.h:6803
FORCE_INLINE __m128i _mm_shuffle_epi_1010(__m128i a)
Definition sse2neon.h:1011
FORCE_INLINE __m128d _mm_or_pd(__m128d a, __m128d b)
Definition sse2neon.h:5172
FORCE_INLINE __m128i _mm_cvtepu8_epi32(__m128i a)
Definition sse2neon.h:7812
FORCE_INLINE __m64 _mm_sign_pi8(__m64 _a, __m64 _b)
Definition sse2neon.h:7510
FORCE_INLINE __m128d _mm_load1_pd(const double *p)
Definition sse2neon.h:4638
#define _MM_DENORMALS_ZERO_ON
Definition sse2neon.h:294
FORCE_INLINE __m128i _mm_add_epi8(__m128i a, __m128i b)
Definition sse2neon.h:3131
FORCE_INLINE __m64 _mm_cvtt_ps2pi(__m128 a)
Definition sse2neon.h:1791
FORCE_INLINE __m128 _mm_shuffle_ps_3210(__m128 a, __m128 b)
Definition sse2neon.h:748
FORCE_INLINE __m128 _mm_mul_ps(__m128 a, __m128 b)
Definition sse2neon.h:2299
FORCE_INLINE __m128i _mm_set1_epi8(signed char w)
Definition sse2neon.h:5405
#define vreinterpretq_m128i_u8(x)
Definition sse2neon.h:363
FORCE_INLINE int _mm_comile_ss(__m128 a, __m128 b)
Definition sse2neon.h:1474
FORCE_INLINE __m128i _mm_cvttps_epi32(__m128 a)
Definition sse2neon.h:4479
FORCE_INLINE __m128d _mm_round_pd(__m128d, int)
Definition sse2neon.h:8323
FORCE_INLINE __m128 _mm_cvtpi16_ps(__m64 a)
Definition sse2neon.h:1578
#define _MM_ROUND_NEAREST
Definition sse2neon.h:284
FORCE_INLINE __m128 _mm_loadl_pi(__m128 a, __m64 const *p)
Definition sse2neon.h:2009
FORCE_INLINE __m128 _mm_shuffle_ps_1010(__m128 a, __m128 b)
Definition sse2neon.h:725
FORCE_INLINE int _mm_test_all_zeros(__m128i a, __m128i mask)
Definition sse2neon.h:8505
FORCE_INLINE __m128i _mm_clmulepi64_si128(__m128i _a, __m128i _b, const int imm)
Definition sse2neon.h:9929
#define vreinterpret_u32_m64(x)
Definition sse2neon.h:397
FORCE_INLINE __m64 _mm_movepi64_pi64(__m128i a)
Definition sse2neon.h:5033
#define vreinterpretq_nth_u64_m128i(x, n)
Definition sse2neon.h:476
FORCE_INLINE __m128 _mm_cmpunord_ps(__m128 a, __m128 b)
Definition sse2neon.h:1425
FORCE_INLINE __m128d _mm_cmpneq_pd(__m128d a, __m128d b)
Definition sse2neon.h:3704
FORCE_INLINE __m128i _mm_min_epi8(__m128i a, __m128i b)
Definition sse2neon.h:8111
FORCE_INLINE __m128i _mm_min_epu32(__m128i a, __m128i b)
Definition sse2neon.h:8129
FORCE_INLINE __m128 _mm_cvtpi32_ps(__m128 a, __m64 b)
Definition sse2neon.h:1594
#define vreinterpretq_m128d_f32(x)
Definition sse2neon.h:430
FORCE_INLINE __m128d _mm_cmpnlt_pd(__m128d a, __m128d b)
Definition sse2neon.h:3829
FORCE_INLINE int64_t _mm_cvtsd_si64(__m128d a)
Definition sse2neon.h:4300
#define vreinterpretq_f64_m128i(x)
Definition sse2neon.h:369
FORCE_INLINE __m128 _mm_cmple_ps(__m128 a, __m128 b)
Definition sse2neon.h:1294
FORCE_INLINE __m128d _mm_unpackhi_pd(__m128d a, __m128d b)
Definition sse2neon.h:6499
FORCE_INLINE __m128i _mm_cvttpd_epi32(__m128d a)
Definition sse2neon.h:4458
#define vreinterpret_m64_s16(x)
Definition sse2neon.h:382
FORCE_INLINE int _mm_movemask_pd(__m128d a)
Definition sse2neon.h:5021
FORCE_INLINE __m128 _mm_set_ps1(float)
Definition sse2neon.h:2544
#define SSE2NEON_CMPSTR_GENERATE_INDEX(r2, bound, imm8)
Definition sse2neon.h:9096
FORCE_INLINE __m128d _mm_cmpnle_sd(__m128d a, __m128d b)
Definition sse2neon.h:3821
FORCE_INLINE __m128i _mm_max_epu32(__m128i a, __m128i b)
Definition sse2neon.h:8086
#define _SIDD_NEGATIVE_POLARITY
Definition sse2neon.h:8585
#define _MM_ROUND_DOWN
Definition sse2neon.h:285
FORCE_INLINE __m128i _mm_min_epi32(__m128i a, __m128i b)
Definition sse2neon.h:8102
FORCE_INLINE __m128 _mm_shuffle_ps_2010(__m128 a, __m128 b)
Definition sse2neon.h:796
FORCE_INLINE __m128i _mm_set1_epi64(__m64 _i)
Definition sse2neon.h:5385
FORCE_INLINE __m128 _mm_undefined_ps(void)
Definition sse2neon.h:3027
FORCE_INLINE __m128d _mm_cmpunord_sd(__m128d a, __m128d b)
Definition sse2neon.h:3949
FORCE_INLINE __m128d _mm_hadd_pd(__m128d a, __m128d b)
Definition sse2neon.h:6684
FORCE_INLINE __m128 _mm_set1_ps(float _w)
Definition sse2neon.h:2609
FORCE_INLINE __m128i _mm_slli_epi64(__m128i a, int imm)
Definition sse2neon.h:5752
FORCE_INLINE __m128 _mm_sub_ss(__m128 a, __m128 b)
Definition sse2neon.h:2978
FORCE_INLINE __m128i _mm_packus_epi16(const __m128i a, const __m128i b)
Definition sse2neon.h:5232
FORCE_INLINE __m128i _mm_cvtepi32_epi64(__m128i a)
Definition sse2neon.h:7737
FORCE_INLINE __m128i _mm_srai_epi16(__m128i a, int imm)
Definition sse2neon.h:5865
FORCE_INLINE __m128d _mm_set_sd(double a)
Definition sse2neon.h:5348
FORCE_INLINE __m64 _mm_cvtpd_pi32(__m128d a)
Definition sse2neon.h:4123
FORCE_INLINE __m128 _mm_ceil_ss(__m128 a, __m128 b)
Definition sse2neon.h:7695
FORCE_INLINE __m128i _mm_shuffle_epi8(__m128i a, __m128i b)
Definition sse2neon.h:7249
FORCE_INLINE __m64 _mm_abs_pi8(__m64 a)
Definition sse2neon.h:6900
FORCE_INLINE __m128d _mm_addsub_pd(__m128d a, __m128d b)
Definition sse2neon.h:6653
FORCE_INLINE __m128 _mm_cmpngt_ss(__m128 a, __m128 b)
Definition sse2neon.h:1362
FORCE_INLINE int _mm_comilt_sd(__m128d a, __m128d b)
Definition sse2neon.h:4016
FORCE_INLINE __m128i _mm_undefined_si128(void)
Definition sse2neon.h:3012
FORCE_INLINE int _mm_comile_sd(__m128d a, __m128d b)
Definition sse2neon.h:4001
FORCE_INLINE __m128d _mm_max_pd(__m128d a, __m128d b)
Definition sse2neon.h:4806
FORCE_INLINE __m128 _mm_shuffle_ps_0011(__m128 a, __m128 b)
Definition sse2neon.h:755
FORCE_INLINE __m64 _mm_min_pu8(__m64 a, __m64 b)
Definition sse2neon.h:2195
FORCE_INLINE __m128d _mm_castsi128_pd(__m128i a)
Definition sse2neon.h:3367
FORCE_INLINE __m128d _mm_mul_pd(__m128d a, __m128d b)
Definition sse2neon.h:5067
#define _MM_FROUND_TO_NEG_INF
Definition sse2neon.h:272
FORCE_INLINE __m128d _mm_dp_pd(__m128d a, __m128d b, const int imm)
Definition sse2neon.h:7835
FORCE_INLINE int _mm_test_mix_ones_zeros(__m128i a, __m128i mask)
Definition sse2neon.h:8518
FORCE_INLINE void _mm_storel_pd(double *mem_addr, __m128d a)
Definition sse2neon.h:6149
FORCE_INLINE void _mm_storel_pi(__m64 *p, __m128 a)
Definition sse2neon.h:2892
FORCE_INLINE void _sse2neon_kadd_f32(float *sum, float *c, float y)
Definition sse2neon.h:825
FORCE_INLINE int _mm_popcnt_u32(unsigned int a)
Definition sse2neon.h:9974
FORCE_INLINE __m128 _mm_cmpgt_ps(__m128 a, __m128 b)
Definition sse2neon.h:1273
FORCE_INLINE __m128 _mm_cvtpu8_ps(__m64 a)
Definition sse2neon.h:1717
FORCE_INLINE __m128 _mm_max_ss(__m128 a, __m128 b)
Definition sse2neon.h:2149
FORCE_INLINE void _mm_empty(void)
Definition sse2neon.h:1146
FORCE_INLINE __m128i _mm_sub_epi32(__m128i a, __m128i b)
Definition sse2neon.h:6260
#define vreinterpretq_u64_m128(x)
Definition sse2neon.h:351
FORCE_INLINE void _mm_storeu_si32(void *p, __m128i a)
Definition sse2neon.h:6190
FORCE_INLINE __m128i _mm_unpackhi_epi8(__m128i a, __m128i b)
Definition sse2neon.h:6473
FORCE_INLINE void _mm_stream_si128(__m128i *p, __m128i a)
Definition sse2neon.h:6215
FORCE_INLINE uint32_t _mm_crc32_u8(uint32_t, uint8_t)
Definition sse2neon.h:9381
#define ALIGN_STRUCT(x)
Definition sse2neon.h:89
FORCE_INLINE __m128 _mm_cmpneq_ss(__m128 a, __m128 b)
Definition sse2neon.h:1332
FORCE_INLINE __m128i _mm_cvtepi8_epi32(__m128i a)
Definition sse2neon.h:7754
FORCE_INLINE __m128d _mm_cmpngt_pd(__m128d a, __m128d b)
Definition sse2neon.h:3763
FORCE_INLINE void _mm_storeu_pd(double *mem_addr, __m128d a)
Definition sse2neon.h:6176
FORCE_INLINE int _sse2neon_ctzll(unsigned long long x)
Definition sse2neon.h:9052
FORCE_INLINE __m128 _mm_cmpnlt_ss(__m128 a, __m128 b)
Definition sse2neon.h:1392
FORCE_INLINE int64_t _mm_cvtss_si64(__m128 a)
Definition sse2neon.h:1771
FORCE_INLINE __m128 _mm_cmpunord_ss(__m128 a, __m128 b)
Definition sse2neon.h:1436
FORCE_INLINE __m128i _mm_packs_epi16(__m128i a, __m128i b)
Definition sse2neon.h:5192
FORCE_INLINE __m64 _mm_add_si64(__m64 a, __m64 b)
Definition sse2neon.h:3182
FORCE_INLINE __m128 _mm_loadu_ps(const float *p)
Definition sse2neon.h:2033
FORCE_INLINE __m128i _mm_hadd_epi32(__m128i _a, __m128i _b)
Definition sse2neon.h:6973
FORCE_INLINE int _mm_comilt_ss(__m128 a, __m128 b)
Definition sse2neon.h:1486
FORCE_INLINE int64_t _mm_cvtsi128_si64(__m128i a)
Definition sse2neon.h:4351
FORCE_INLINE __m128i _mm_xor_si128(__m128i a, __m128i b)
Definition sse2neon.h:6631
FORCE_INLINE __m128i _mm_maddubs_epi16(__m128i _a, __m128i _b)
Definition sse2neon.h:7144
FORCE_INLINE __m128 _mm_shuffle_ps_0022(__m128 a, __m128 b)
Definition sse2neon.h:762
FORCE_INLINE __m128i _mm_cmpeq_epi8(__m128i a, __m128i b)
Definition sse2neon.h:3429
#define vreinterpretq_s32_m128(x)
Definition sse2neon.h:355
FORCE_INLINE void _mm_store_ss(float *p, __m128 a)
Definition sse2neon.h:2856
FORCE_INLINE __m64 _mm_mulhrs_pi16(__m64 a, __m64 b)
Definition sse2neon.h:7237
FORCE_INLINE __m128 _mm_cmpnle_ss(__m128 a, __m128 b)
Definition sse2neon.h:1377
FORCE_INLINE __m64 _mm_hsubs_pi16(__m64 _a, __m64 _b)
Definition sse2neon.h:7122
FORCE_INLINE __m128i _mm_castpd_si128(__m128d a)
Definition sse2neon.h:3343
FORCE_INLINE __m128d _mm_cmpnle_pd(__m128d a, __m128d b)
Definition sse2neon.h:3796
FORCE_INLINE __m128i _mm_sll_epi32(__m128i a, __m128i count)
Definition sse2neon.h:5664
FORCE_INLINE __m128i _mm_sign_epi32(__m128i _a, __m128i _b)
Definition sse2neon.h:7349
FORCE_INLINE uint8_t _sse2neon_vaddv_u8(uint8x8_t v8)
Definition sse2neon.h:541
FORCE_INLINE __m128i _mm_cvtepi16_epi32(__m128i a)
Definition sse2neon.h:7719
#define vreinterpretq_u32_m128i(x)
Definition sse2neon.h:378
FORCE_INLINE void * _mm_malloc(size_t size, size_t align)
Definition sse2neon.h:2068
FORCE_INLINE __m64 _mm_hadds_pi16(__m64 _a, __m64 _b)
Definition sse2neon.h:7029
FORCE_INLINE __m128i _mm_setr_epi8(signed char b0, signed char b1, signed char b2, signed char b3, signed char b4, signed char b5, signed char b6, signed char b7, signed char b8, signed char b9, signed char b10, signed char b11, signed char b12, signed char b13, signed char b14, signed char b15)
Definition sse2neon.h:5459
FORCE_INLINE __m128i _mm_load_si128(const __m128i *p)
Definition sse2neon.h:4626
FORCE_INLINE __m128 _mm_andnot_ps(__m128 a, __m128 b)
Definition sse2neon.h:1198
FORCE_INLINE __m128 _mm_movelh_ps(__m128 __A, __m128 __B)
Definition sse2neon.h:2239
FORCE_INLINE __m128d _mm_cmpunord_pd(__m128d a, __m128d b)
Definition sse2neon.h:3916
FORCE_INLINE __m128i _mm_sub_epi16(__m128i a, __m128i b)
Definition sse2neon.h:6245
FORCE_INLINE __m128i _mm_cvtepi8_epi64(__m128i a)
Definition sse2neon.h:7764
FORCE_INLINE __m128i _mm_shuffle_epi_3332(__m128i a)
Definition sse2neon.h:1049
FORCE_INLINE __m128 _mm_rsqrt_ss(__m128 in)
Definition sse2neon.h:2484
#define vreinterpretq_m128i_s64(x)
Definition sse2neon.h:361
FORCE_INLINE __m128 _mm_setzero_ps(void)
Definition sse2neon.h:2637
FORCE_INLINE int _sse2neon_clz(unsigned int x)
Definition sse2neon.h:9028
#define vreinterpretq_m128_s64(x)
Definition sse2neon.h:342
FORCE_INLINE void _mm_storeu_si128(__m128i *p, __m128i a)
Definition sse2neon.h:6183
FORCE_INLINE void _mm_free(void *addr)
Definition sse2neon.h:1881
#define vreinterpretq_u32_m128(x)
Definition sse2neon.h:350
#define SSE2NEON_COMP_AGG(a, b, la, lb, imm8, IE)
Definition sse2neon.h:9090
FORCE_INLINE __m128d _mm_div_pd(__m128d a, __m128d b)
Definition sse2neon.h:4529
FORCE_INLINE __m128 _mm_loadr_ps(const float *p)
Definition sse2neon.h:2025
FORCE_INLINE __m128i _mm_sad_epu8(__m128i a, __m128i b)
Definition sse2neon.h:5254
FORCE_INLINE int _mm_comigt_sd(__m128d a, __m128d b)
Definition sse2neon.h:3986
FORCE_INLINE __m128i _mm_cvtepu8_epi64(__m128i a)
Definition sse2neon.h:7822
FORCE_INLINE __m128 _mm_and_ps(__m128 a, __m128 b)
Definition sse2neon.h:1183
FORCE_INLINE __m128i _mm_aeskeygenassist_si128(__m128i a, const int rcon)
Definition sse2neon.h:9815
FORCE_INLINE __m128i _mm_cmplt_epi32(__m128i a, __m128i b)
Definition sse2neon.h:3645
FORCE_INLINE __m128d _mm_cmple_pd(__m128d a, __m128d b)
Definition sse2neon.h:3587
FORCE_INLINE __m128i _mm_hsub_epi16(__m128i _a, __m128i _b)
Definition sse2neon.h:7044
FORCE_INLINE int _mm_comineq_ss(__m128 a, __m128 b)
Definition sse2neon.h:1496
FORCE_INLINE __m128i _mm_set1_epi64x(int64_t _i)
Definition sse2neon.h:5392
FORCE_INLINE __m128i _mm_move_epi64(__m128i a)
Definition sse2neon.h:4913
#define _MM_ROUND_UP
Definition sse2neon.h:286
FORCE_INLINE __m128d _mm_hsub_pd(__m128d _a, __m128d _b)
Definition sse2neon.h:6718
FORCE_INLINE __m128i _mm_slli_epi16(__m128i a, int imm)
Definition sse2neon.h:5710
FORCE_INLINE __m128 _mm_div_ss(__m128 a, __m128 b)
Definition sse2neon.h:1864
FORCE_INLINE int _mm_cmpistrc(__m128i a, __m128i b, const int imm8)
Definition sse2neon.h:9257
int64x1_t __m64
Definition sse2neon.h:306
FORCE_INLINE __m128i _mm_min_epu16(__m128i a, __m128i b)
Definition sse2neon.h:8120
FORCE_INLINE __m128i _mm_min_epu8(__m128i a, __m128i b)
Definition sse2neon.h:4858
FORCE_INLINE __m128i _mm_sra_epi32(__m128i a, __m128i count)
Definition sse2neon.h:5844
FORCE_INLINE __m128 _mm_castsi128_ps(__m128i a)
Definition sse2neon.h:3379
FORCE_INLINE __m128i _mm_cmplt_epi8(__m128i a, __m128i b)
Definition sse2neon.h:3654
#define vreinterpret_s32_m64(x)
Definition sse2neon.h:402
FORCE_INLINE int _mm_cmpistrs(__m128i a, __m128i b, const int imm8)
Definition sse2neon.h:9293
FORCE_INLINE __m64 _mm_shuffle_pi8(__m64 a, __m64 b)
Definition sse2neon.h:7290
#define vreinterpretq_m128d_u32(x)
Definition sse2neon.h:427
FORCE_INLINE __m128d _mm_andnot_pd(__m128d a, __m128d b)
Definition sse2neon.h:3272
FORCE_INLINE __m128d _mm_cvtss_sd(__m128d a, __m128 b)
Definition sse2neon.h:4443
#define vreinterpret_m64_u64(x)
Definition sse2neon.h:389
FORCE_INLINE __m64 _mm_max_pi16(__m64 a, __m64 b)
Definition sse2neon.h:2110
#define __int64
Definition sse2neon.h:324
FORCE_INLINE __m128 _mm_shuffle_ps_3202(__m128 a, __m128 b)
Definition sse2neon.h:778
FORCE_INLINE __m128i _mm_cmpgt_epi16(__m128i a, __m128i b)
Definition sse2neon.h:3512
FORCE_INLINE __m128 _mm_floor_ps(__m128)
Definition sse2neon.h:7961
FORCE_INLINE __m128d _mm_cmpgt_pd(__m128d a, __m128d b)
Definition sse2neon.h:3545
#define vreinterpretq_u64_m128i(x)
Definition sse2neon.h:379
FORCE_INLINE __m128i _mm_cvtsi64_si128(int64_t a)
Definition sse2neon.h:4418
FORCE_INLINE __m128i _mm_cvtepu16_epi32(__m128i a)
Definition sse2neon.h:7775
FORCE_INLINE __m128i _mm_loadl_epi64(__m128i const *p)
Definition sse2neon.h:4668
FORCE_INLINE void _sse2neon_mm_set_denormals_zero_mode(unsigned int flag)
Definition sse2neon.h:10026
FORCE_INLINE __m128 _mm_blendv_ps(__m128 _a, __m128 _b, __m128 _mask)
Definition sse2neon.h:7638
FORCE_INLINE __m128i _mm_set_epi64x(int64_t, int64_t)
Definition sse2neon.h:5294
#define _MM_ROUND_TOWARD_ZERO
Definition sse2neon.h:287
FORCE_INLINE __m128 _mm_shuffle_ps_0101(__m128 a, __m128 b)
Definition sse2neon.h:739
FORCE_INLINE __m128 _mm_cmpeq_ps(__m128 a, __m128 b)
Definition sse2neon.h:1237
FORCE_INLINE __m128i _mm_aesimc_si128(__m128i a)
Definition sse2neon.h:9764
FORCE_INLINE __m64 _mm_sub_si64(__m64 a, __m64 b)
Definition sse2neon.h:6325
FORCE_INLINE void _mm_maskmoveu_si128(__m128i a, __m128i mask, char *mem_addr)
Definition sse2neon.h:4775
FORCE_INLINE __m128 _mm_cmplt_ss(__m128 a, __m128 b)
Definition sse2neon.h:1317
FORCE_INLINE __m128i _mm_max_epi32(__m128i a, __m128i b)
Definition sse2neon.h:8059
FORCE_INLINE int _mm_cmpestra(__m128i a, int la, __m128i b, int lb, const int imm8)
Definition sse2neon.h:9132
#define SSE2NEON_CMPESTR_LIST
Definition sse2neon.h:8982
FORCE_INLINE __m128i _mm_subs_epi8(__m128i a, __m128i b)
Definition sse2neon.h:6355
FORCE_INLINE __m128 _mm_add_ps(__m128 a, __m128 b)
Definition sse2neon.h:1158
FORCE_INLINE __m128 _mm_cmpord_ss(__m128 a, __m128 b)
Definition sse2neon.h:1418
FORCE_INLINE __m128 _mm_cmplt_ps(__m128 a, __m128 b)
Definition sse2neon.h:1309
FORCE_INLINE int _mm_movemask_ps(__m128 a)
Definition sse2neon.h:2271
FORCE_INLINE __m128d _mm_floor_sd(__m128d a, __m128d b)
Definition sse2neon.h:7976
FORCE_INLINE __m128i _mm_setr_epi16(short w0, short w1, short w2, short w3, short w4, short w5, short w6, short w7)
Definition sse2neon.h:5429
FORCE_INLINE __m128i _mm_or_si128(__m128i, __m128i)
Definition sse2neon.h:5183
FORCE_INLINE __m128d _mm_cmpneq_sd(__m128d a, __m128d b)
Definition sse2neon.h:3722
FORCE_INLINE __m128i _mm_aesdeclast_si128(__m128i a, __m128i RoundKey)
Definition sse2neon.h:9727
FORCE_INLINE __m128i _mm_cvtepi8_epi16(__m128i a)
Definition sse2neon.h:7745
FORCE_INLINE __m128i _mm_cvtepu32_epi64(__m128i a)
Definition sse2neon.h:7793
#define _mm_set_pd1
Definition sse2neon.h:5343
FORCE_INLINE __m128i _mm_max_epi16(__m128i a, __m128i b)
Definition sse2neon.h:4788
FORCE_INLINE void _mm_stream_si32(int *p, int a)
Definition sse2neon.h:6228
FORCE_INLINE __m128i _mm_max_epu16(__m128i a, __m128i b)
Definition sse2neon.h:8077
FORCE_INLINE __m128i _mm_hsub_epi32(__m128i _a, __m128i _b)
Definition sse2neon.h:7060
FORCE_INLINE __m128d _mm_cmpnlt_sd(__m128d a, __m128d b)
Definition sse2neon.h:3854
FORCE_INLINE __m128i _mm_aesdec_si128(__m128i a, __m128i RoundKey)
Definition sse2neon.h:9606
FORCE_INLINE __m128i _mm_adds_epi16(__m128i a, __m128i b)
Definition sse2neon.h:3197
FORCE_INLINE int32_t _mm_cvtsd_si32(__m128d a)
Definition sse2neon.h:4283
FORCE_INLINE void _mm_storel_epi64(__m128i *a, __m128i b)
Definition sse2neon.h:6138
FORCE_INLINE __m128d _mm_set1_pd(double d)
Definition sse2neon.h:5413
#define _MM_FROUND_TO_NEAREST_INT
Definition sse2neon.h:271
FORCE_INLINE __m128 _mm_unpacklo_ps(__m128 a, __m128 b)
Definition sse2neon.h:3071
FORCE_INLINE __m128 _mm_cvtsi64_ss(__m128 a, int64_t b)
Definition sse2neon.h:1741
#define vreinterpretq_m128d_u64(x)
Definition sse2neon.h:428
FORCE_INLINE __m128i _mm_cvtsi32_si128(int a)
Definition sse2neon.h:4392
FORCE_INLINE __m128 _mm_cmple_ss(__m128 a, __m128 b)
Definition sse2neon.h:1302
FORCE_INLINE __m128d _mm_sub_pd(__m128d a, __m128d b)
Definition sse2neon.h:6295
FORCE_INLINE uint64_t _mm_crc32_u64(uint64_t crc, uint64_t v)
Definition sse2neon.h:9365
#define SSE2NEON_AES_U3(p)
#define FORCE_INLINE
Definition sse2neon.h:86
#define vreinterpret_s16_m64(x)
Definition sse2neon.h:401
FORCE_INLINE __m128i _mm_abs_epi16(__m128i a)
Definition sse2neon.h:6830
FORCE_INLINE __m128i _mm_set_epi16(short i7, short i6, short i5, short i4, short i3, short i2, short i1, short i0)
Definition sse2neon.h:5262
FORCE_INLINE __m128d _mm_load_sd(const double *p)
Definition sse2neon.h:4613
FORCE_INLINE __m128 _mm_cmpnge_ss(__m128 a, __m128 b)
Definition sse2neon.h:1347
FORCE_INLINE unsigned int _mm_getcsr()
Definition sse2neon.h:2621
FORCE_INLINE __m128 _mm_cvtpd_ps(__m128d a)
Definition sse2neon.h:4144
#define vreinterpretq_m128i_u32(x)
Definition sse2neon.h:365
FORCE_INLINE __m128i _mm_subs_epu8(__m128i a, __m128i b)
Definition sse2neon.h:6379
FORCE_INLINE __m64 _mm_min_pi16(__m64 a, __m64 b)
Definition sse2neon.h:2165
FORCE_INLINE __m128i _mm_shuffle_epi_0101(__m128i a)
Definition sse2neon.h:1029
FORCE_INLINE int _mm_cmpistri(__m128i a, __m128i b, const int imm8)
Definition sse2neon.h:9266
#define SSE2NEON_AES_U1(p)
FORCE_INLINE __m128d _mm_sub_sd(__m128d a, __m128d b)
Definition sse2neon.h:6315
FORCE_INLINE __m128i _mm_cmpestrm(__m128i a, int la, __m128i b, int lb, const int imm8)
Definition sse2neon.h:9173
FORCE_INLINE int _sse2neon_sido_negative(int res, int lb, int imm8, int bound)
Definition sse2neon.h:9012
FORCE_INLINE __m128i _mm_avg_epu16(__m128i a, __m128i b)
Definition sse2neon.h:3301
FORCE_INLINE __m128i _mm_shuffle_epi_2103(__m128i a)
Definition sse2neon.h:1003
FORCE_INLINE __m128 _mm_add_ss(__m128 a, __m128 b)
Definition sse2neon.h:1166
FORCE_INLINE void _mm_stream_pi(__m64 *p, __m64 a)
Definition sse2neon.h:2938
FORCE_INLINE __m128 _mm_ceil_ps(__m128)
Definition sse2neon.h:7666
FORCE_INLINE __m128i _mm_mpsadbw_epu8(__m128i a, __m128i b, const int imm)
Definition sse2neon.h:8202
#define vreinterpretq_m128i_s32(x)
Definition sse2neon.h:360
FORCE_INLINE __m128i _mm_mullo_epi32(__m128i a, __m128i b)
Definition sse2neon.h:8295
FORCE_INLINE __m128 _mm_blend_ps(__m128 _a, __m128 _b, const char imm8)
Definition sse2neon.h:7583
FORCE_INLINE __m128i _mm_aesenc_si128(__m128i a, __m128i RoundKey)
Definition sse2neon.h:9509
FORCE_INLINE __m128 _mm_shuffle_ps_2103(__m128 a, __m128 b)
Definition sse2neon.h:716
FORCE_INLINE __m128 _mm_set_ss(float a)
Definition sse2neon.h:2599
FORCE_INLINE __m128 _mm_shuffle_ps_2032(__m128 a, __m128 b)
Definition sse2neon.h:814
FORCE_INLINE __m128i _mm_mullo_epi16(__m128i a, __m128i b)
Definition sse2neon.h:5163
FORCE_INLINE __m128 _mm_shuffle_ps_2001(__m128 a, __m128 b)
Definition sse2neon.h:805
FORCE_INLINE int64_t _mm_popcnt_u64(uint64_t a)
Definition sse2neon.h:10001
FORCE_INLINE void _mm_pause()
Definition sse2neon.h:5244
FORCE_INLINE __m128i _mm_subs_epi16(__m128i a, __m128i b)
Definition sse2neon.h:6340
FORCE_INLINE __m128i _mm_minpos_epu16(__m128i a)
Definition sse2neon.h:8152
#define SSE2NEON_GENERATE_CMP_EQUAL_ANY(prefix)
Definition sse2neon.h:8809
FORCE_INLINE __m128d _mm_cvtepi32_pd(__m128i a)
Definition sse2neon.h:4067
FORCE_INLINE __m128d _mm_sqrt_sd(__m128d a, __m128d b)
Definition sse2neon.h:5801
FORCE_INLINE int _mm_cmpistro(__m128i a, __m128i b, const int imm8)
Definition sse2neon.h:9284
#define SSE2NEON_BARRIER()
Definition sse2neon.h:122
FORCE_INLINE __m128 _mm_loadh_pi(__m128 a, __m64 const *p)
Definition sse2neon.h:1992
FORCE_INLINE __m128 _mm_cmpgt_ss(__m128 a, __m128 b)
Definition sse2neon.h:1281
FORCE_INLINE __m128 _mm_rcp_ss(__m128 a)
Definition sse2neon.h:2457
FORCE_INLINE __m128 _mm_castpd_ps(__m128d a)
Definition sse2neon.h:3335
FORCE_INLINE __m128 _mm_move_ss(__m128, __m128)
Definition sse2neon.h:2213
FORCE_INLINE __m64 _mm_cvttpd_pi32(__m128d a)
Definition sse2neon.h:4468
FORCE_INLINE __m128i _mm_sign_epi16(__m128i _a, __m128i _b)
Definition sse2neon.h:7312
FORCE_INLINE __m128i _mm_cmplt_epi16(__m128i a, __m128i b)
Definition sse2neon.h:3635
#define vreinterpretq_f32_m128(x)
Definition sse2neon.h:345
FORCE_INLINE __m128 _mm_round_ps(__m128, int)
Definition sse2neon.h:8392
FORCE_INLINE __m128 _mm_shuffle_ps_2200(__m128 a, __m128 b)
Definition sse2neon.h:770
FORCE_INLINE __m128i _mm_mul_epu32(__m128i a, __m128i b)
Definition sse2neon.h:5056
FORCE_INLINE __m128d _mm_cmpnge_pd(__m128d a, __m128d b)
Definition sse2neon.h:3730
FORCE_INLINE __m64 _mm_mulhi_pu16(__m64 a, __m64 b)
Definition sse2neon.h:2322
FORCE_INLINE __m128 _mm_floor_ss(__m128 a, __m128 b)
Definition sse2neon.h:7990
FORCE_INLINE __m128i _mm_set_epi64(__m64 i1, __m64 i2)
Definition sse2neon.h:5286
FORCE_INLINE void _mm_store_pd(double *mem_addr, __m128d a)
Definition sse2neon.h:6070
FORCE_INLINE __m128i _mm_mulhi_epu16(__m128i a, __m128i b)
Definition sse2neon.h:5133
FORCE_INLINE __m128 _mm_cmpneq_ps(__m128 a, __m128 b)
Definition sse2neon.h:1324
FORCE_INLINE void _mm_storer_pd(double *mem_addr, __m128d a)
Definition sse2neon.h:6166
FORCE_INLINE int _mm_cmpistra(__m128i a, __m128i b, const int imm8)
Definition sse2neon.h:9248
FORCE_INLINE __m128i _mm_shuffle_epi_1001(__m128i a)
Definition sse2neon.h:1019
FORCE_INLINE __m128d _mm_undefined_pd(void)
Definition sse2neon.h:6394
#define _MM_FROUND_TO_ZERO
Definition sse2neon.h:274
FORCE_INLINE __m128d _mm_set_pd(double, double)
Definition sse2neon.h:5330
#define SSE2NEON_GENERATE_AGGREGATE_EQUAL_ORDER(prefix)
Definition sse2neon.h:8964
FORCE_INLINE __m128d _mm_castps_pd(__m128 a)
Definition sse2neon.h:3351
FORCE_INLINE __m128 _mm_shuffle_ps_1133(__m128 a, __m128 b)
Definition sse2neon.h:788
FORCE_INLINE __m128 _mm_load1_ps(const float *p)
Definition sse2neon.h:1977
FORCE_INLINE __m128i _mm_cvtepu16_epi64(__m128i a)
Definition sse2neon.h:7783
FORCE_INLINE __m128i _mm_cvtepi16_epi64(__m128i a)
Definition sse2neon.h:7727
FORCE_INLINE __m128 _mm_hsub_ps(__m128 _a, __m128 _b)
Definition sse2neon.h:6736
FORCE_INLINE __m128 _mm_cvtpi32x2_ps(__m64 a, __m64 b)
Definition sse2neon.h:1613
#define _MM_FLUSH_ZERO_ON
Definition sse2neon.h:290
FORCE_INLINE __m128i _mm_cmpgt_epi64(__m128i a, __m128i b)
Definition sse2neon.h:9314
FORCE_INLINE void _mm_prefetch(char const *p, int i)
Definition sse2neon.h:2403
#define _MM_DENORMALS_ZERO_MASK
Definition sse2neon.h:293
FORCE_INLINE __m128 _mm_cvtpu16_ps(__m64 a)
Definition sse2neon.h:1700
FORCE_INLINE int _mm_testc_si128(__m128i a, __m128i b)
Definition sse2neon.h:8533
FORCE_INLINE __m128i _mm_castps_si128(__m128)
Definition sse2neon.h:3359
FORCE_INLINE void _mm_lfence(void)
Definition sse2neon.h:2697
FORCE_INLINE __m128 _mm_load_ps(const float *p)
Definition sse2neon.h:1950
FORCE_INLINE __m128d _mm_min_sd(__m128d a, __m128d b)
Definition sse2neon.h:4894
#define vreinterpretq_m128i_u16(x)
Definition sse2neon.h:364
FORCE_INLINE __m64 _mm_cvtps_pi16(__m128 a)
Definition sse2neon.h:1651
_mm_hint
Definition sse2neon.h:668
@ _MM_HINT_T1
Definition sse2neon.h:671
@ _MM_HINT_T0
Definition sse2neon.h:670
@ _MM_HINT_T2
Definition sse2neon.h:672
@ _MM_HINT_NTA
Definition sse2neon.h:669
#define _MM_FROUND_CUR_DIRECTION
Definition sse2neon.h:275
int(* cmpestr_func_t)(__m128i a, int la, __m128i b, int lb)
Definition sse2neon.h:9005
int64x2_t __m128i
Definition sse2neon.h:316
FORCE_INLINE __m128i _mm_avg_epu8(__m128i a, __m128i b)
Definition sse2neon.h:3316
FORCE_INLINE __m128 _mm_round_ss(__m128 a, __m128 b, int rounding)
Definition sse2neon.h:8472
#define SSE2NEON_AES_SBOX(w)
Definition sse2neon.h:9405
FORCE_INLINE __m128 _mm_rsqrt_ps(__m128 in)
Definition sse2neon.h:2466
FORCE_INLINE void _mm_store_sd(double *mem_addr, __m128d a)
Definition sse2neon.h:6099
#define vreinterpretq_u16_m128i(x)
Definition sse2neon.h:377
FORCE_INLINE __m128 _mm_cvtsd_ss(__m128 a, __m128d b)
Definition sse2neon.h:4324
FORCE_INLINE int _mm_movemask_pi8(__m64 a)
Definition sse2neon.h:2249
FORCE_INLINE __m128i _mm_shuffle_epi_2211(__m128i a)
Definition sse2neon.h:1035
FORCE_INLINE int _mm_cvtt_ss2si(__m128 a)
Definition sse2neon.h:1803
FORCE_INLINE __m128d _mm_cmpge_pd(__m128d a, __m128d b)
Definition sse2neon.h:3464
FORCE_INLINE void _mm_stream_pd(double *p, __m128d a)
Definition sse2neon.h:6200
FORCE_INLINE __m128d _mm_add_pd(__m128d a, __m128d b)
Definition sse2neon.h:3140
FORCE_INLINE void _mm_store_ps(float *p, __m128 a)
Definition sse2neon.h:2833
FORCE_INLINE int64_t _mm_cvttsd_si64(__m128d a)
Definition sse2neon.h:4502
FORCE_INLINE __m128i _mm_unpacklo_epi64(__m128i a, __m128i b)
Definition sse2neon.h:6559
FORCE_INLINE __m128d _mm_sqrt_pd(__m128d a)
Definition sse2neon.h:5786
FORCE_INLINE __m64 _mm_hadd_pi16(__m64 a, __m64 b)
Definition sse2neon.h:6989
FORCE_INLINE void _MM_SET_ROUNDING_MODE(int rounding)
Definition sse2neon.h:2554
FORCE_INLINE __m128d _mm_loadh_pd(__m128d a, const double *p)
Definition sse2neon.h:4655
FORCE_INLINE __m128i _mm_sub_epi8(__m128i a, __m128i b)
Definition sse2neon.h:6279
FORCE_INLINE __m128i _mm_sll_epi64(__m128i a, __m128i count)
Definition sse2neon.h:5687
#define SSE2NEON_CMPISTRX_LENGTH(str, len, imm8)
Definition sse2neon.h:9218
FORCE_INLINE __m128d _mm_max_sd(__m128d a, __m128d b)
Definition sse2neon.h:4834
FORCE_INLINE __m128 _mm_cvt_si2ss(__m128 a, int b)
Definition sse2neon.h:1547
#define vreinterpret_s8_m64(x)
Definition sse2neon.h:400
#define _mm_srli_si128(a, imm)
Definition sse2neon.h:6055
#define _mm_shuffle_epi32(a, imm)
Definition sse2neon.h:5524
FORCE_INLINE __m128 _mm_sqrt_ps(__m128 in)
Definition sse2neon.h:2788
FORCE_INLINE __m128i _mm_sll_epi16(__m128i a, __m128i count)
Definition sse2neon.h:5641
#define vreinterpret_u8_m64(x)
Definition sse2neon.h:395
FORCE_INLINE void _mm_storeh_pi(__m64 *p, __m128 a)
Definition sse2neon.h:2880
FORCE_INLINE __m128i _mm_unpacklo_epi16(__m128i a, __m128i b)
Definition sse2neon.h:6524
FORCE_INLINE int _mm_comigt_ss(__m128 a, __m128 b)
Definition sse2neon.h:1464
FORCE_INLINE __m64 _mm_sign_pi16(__m64 _a, __m64 _b)
Definition sse2neon.h:7428
FORCE_INLINE __m128 _mm_cmpge_ss(__m128 a, __m128 b)
Definition sse2neon.h:1260
FORCE_INLINE unsigned int _MM_GET_ROUNDING_MODE()
Definition sse2neon.h:1915
FORCE_INLINE __m128 _mm_min_ps(__m128 a, __m128 b)
Definition sse2neon.h:2174
FORCE_INLINE __m128d _mm_movedup_pd(__m128d a)
Definition sse2neon.h:6770
FORCE_INLINE __m128i _mm_loadu_si64(const void *p)
Definition sse2neon.h:2058
FORCE_INLINE __m128d _mm_xor_pd(__m128d a, __m128d b)
Definition sse2neon.h:6623
FORCE_INLINE __m128i _mm_stream_load_si128(__m128i *p)
Definition sse2neon.h:8484
FORCE_INLINE void _mm_store_pd1(double *mem_addr, __m128d a)
Definition sse2neon.h:6083
FORCE_INLINE __m128 _mm_cvtepi32_ps(__m128i a)
Definition sse2neon.h:4082
FORCE_INLINE __m128 _mm_or_ps(__m128, __m128)
Definition sse2neon.h:2331
FORCE_INLINE __m128d _mm_blendv_pd(__m128d _a, __m128d _b, __m128d _mask)
Definition sse2neon.h:7620
FORCE_INLINE __m128d _mm_unpacklo_pd(__m128d a, __m128d b)
Definition sse2neon.h:6602
FORCE_INLINE int _sse2neon_ctz(unsigned int x)
Definition sse2neon.h:9040
FORCE_INLINE __m128 _mm_min_ss(__m128 a, __m128 b)
Definition sse2neon.h:2204
FORCE_INLINE __m128d _mm_cmple_sd(__m128d a, __m128d b)
Definition sse2neon.h:3609
FORCE_INLINE __m128d _mm_cmpngt_sd(__m128d a, __m128d b)
Definition sse2neon.h:3788
#define SSE2NEON_AES_H0(x)
Definition sse2neon.h:9488
FORCE_INLINE __m64 _mm_abs_pi32(__m64 a)
Definition sse2neon.h:6886
FORCE_INLINE __m128i _mm_srl_epi64(__m128i a, __m128i count)
Definition sse2neon.h:5959
FORCE_INLINE int _mm_cmpestro(__m128i a, int la, __m128i b, int lb, const int imm8)
Definition sse2neon.h:9182
FORCE_INLINE __m128 _mm_max_ps(__m128 a, __m128 b)
Definition sse2neon.h:2119
FORCE_INLINE __m64 _mm_hadd_pi32(__m64 a, __m64 b)
Definition sse2neon.h:6998
FORCE_INLINE void _mm_mfence(void)
Definition sse2neon.h:2687
FORCE_INLINE float _mm_cvtss_f32(__m128 a)
Definition sse2neon.h:1752
FORCE_INLINE __m128 _mm_cmpord_ps(__m128 a, __m128 b)
Definition sse2neon.h:1404
#define _MM_FROUND_NO_EXC
Definition sse2neon.h:276
#define vreinterpretq_s64_m128i(x)
Definition sse2neon.h:374
FORCE_INLINE int _mm_cvtsi128_si32(__m128i a)
Definition sse2neon.h:4341
#define _MM_FLUSH_ZERO_OFF
Definition sse2neon.h:291
FORCE_INLINE __m64 _mm_maddubs_pi16(__m64 _a, __m64 _b)
Definition sse2neon.h:7183
SIMDVec
Definition sse2neon.h:473
FORCE_INLINE void _mm_clflush(void const *p)
Definition sse2neon.h:3390
uint16_t res0
Definition sse2neon.h:677
uint8_t bit23
Definition sse2neon.h:680
uint8_t res1
Definition sse2neon.h:678
uint8_t bit24
Definition sse2neon.h:681
uint8_t bit22
Definition sse2neon.h:679
uint8_t res2
Definition sse2neon.h:682