1/* Copyright (C) 2013-2017 Povilas Kanapickas <povilas@radix.lt>
2
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE_1_0.txt or copy at
5 http://www.boost.org/LICENSE_1_0.txt)
6*/
7
8#ifndef LIBSIMDPP_SIMDPP_DETAIL_INSN_I_SUB_H
9#define LIBSIMDPP_SIMDPP_DETAIL_INSN_I_SUB_H
10
11#ifndef LIBSIMDPP_SIMD_H
12 #error "This file must be included through simd.h"
13#endif
14
15#include <simdpp/types.h>
16#include <simdpp/detail/null/math.h>
17#include <simdpp/core/move_l.h>
18#include <simdpp/detail/vector_array_macros.h>
19
20namespace simdpp {
21namespace SIMDPP_ARCH_NAMESPACE {
22namespace detail {
23namespace insn {
24
25static SIMDPP_INL
26uint8<16> i_isub(const uint8<16>& a, const uint8<16>& b)
27{
28#if SIMDPP_USE_NULL
29 return detail::null::sub(a, b);
30#elif SIMDPP_USE_SSE2
31 return _mm_sub_epi8(a.native(), b.native());
32#elif SIMDPP_USE_NEON
33 return vsubq_u8(a.native(), b.native());
34#elif SIMDPP_USE_ALTIVEC
35 return vec_sub(a.native(), b.native());
36#elif SIMDPP_USE_MSA
37 return (v16u8) __msa_subv_b((v16i8) a.native(), (v16i8) b.native());
38#endif
39}
40
41#if SIMDPP_USE_AVX2
42static SIMDPP_INL
43uint8<32> i_isub(const uint8<32>& a, const uint8<32>& b)
44{
45 return _mm256_sub_epi8(a.native(), b.native());
46}
47#endif
48
49#if SIMDPP_USE_AVX512BW
50static SIMDPP_INL
51uint8<64> i_isub(const uint8<64>& a, const uint8<64>& b)
52{
53 return _mm512_sub_epi8(a.native(), b.native());
54}
55#endif
56
57// -----------------------------------------------------------------------------
58
59static SIMDPP_INL
60uint16<8> i_isub(const uint16<8>& a, const uint16<8>& b)
61{
62#if SIMDPP_USE_NULL
63 return detail::null::sub(a, b);
64#elif SIMDPP_USE_SSE2
65 return _mm_sub_epi16(a.native(), b.native());
66#elif SIMDPP_USE_NEON
67 return vsubq_u16(a.native(), b.native());
68#elif SIMDPP_USE_ALTIVEC
69 return vec_sub(a.native(), b.native());
70#elif SIMDPP_USE_MSA
71 return (v8u16) __msa_subv_h((v8i16) a.native(), (v8i16) b.native());
72#endif
73}
74
75#if SIMDPP_USE_AVX2
76static SIMDPP_INL
77uint16<16> i_isub(const uint16<16>& a, const uint16<16>& b)
78{
79 return _mm256_sub_epi16(a.native(), b.native());
80}
81#endif
82
83#if SIMDPP_USE_AVX512BW
84static SIMDPP_INL
85uint16<32> i_isub(const uint16<32>& a, const uint16<32>& b)
86{
87 return _mm512_sub_epi16(a.native(), b.native());
88}
89#endif
90
91// -----------------------------------------------------------------------------
92
93static SIMDPP_INL
94uint32<4> i_isub(const uint32<4>& a, const uint32<4>& b)
95{
96#if SIMDPP_USE_NULL
97 return detail::null::sub(a, b);
98#elif SIMDPP_USE_SSE2
99 return _mm_sub_epi32(a.native(), b.native());
100#elif SIMDPP_USE_NEON
101 return vsubq_u32(a.native(), b.native());
102#elif SIMDPP_USE_ALTIVEC
103 return vec_sub(a.native(), b.native());
104#elif SIMDPP_USE_MSA
105 return (v4u32) __msa_subv_w((v4i32)a.native(), (v4i32)b.native());
106#endif
107}
108
109#if SIMDPP_USE_AVX2
110static SIMDPP_INL
111uint32<8> i_isub(const uint32<8>& a, const uint32<8>& b)
112{
113 return _mm256_sub_epi32(a.native(), b.native());
114}
115#endif
116
117#if SIMDPP_USE_AVX512F
118static SIMDPP_INL
119uint32<16> i_isub(const uint32<16>& a, const uint32<16>& b)
120{
121 return _mm512_sub_epi32(a.native(), b.native());
122}
123#endif
124
125// -----------------------------------------------------------------------------
126
127static SIMDPP_INL
128uint64<2> i_isub(const uint64<2>& a, const uint64<2>& b)
129{
130#if SIMDPP_USE_SSE2
131 return _mm_sub_epi64(a.native(), b.native());
132#elif SIMDPP_USE_NEON
133 return vsubq_u64(a.native(), b.native());
134#elif SIMDPP_USE_VSX_207
135 return vec_sub(a.native(), b.native());
136#elif SIMDPP_USE_MSA
137 return (v2u64) __msa_subv_d((v2i64) a.native(), (v2i64) b.native());
138#elif SIMDPP_USE_NULL || SIMDPP_USE_ALTIVEC
139 return detail::null::sub(a, b);
140#endif
141}
142
143#if SIMDPP_USE_AVX2
144static SIMDPP_INL
145uint64<4> i_isub(const uint64<4>& a, const uint64<4>& b)
146{
147 return _mm256_sub_epi64(a.native(), b.native());
148}
149#endif
150
151#if SIMDPP_USE_AVX512F
152static SIMDPP_INL
153uint64<8> i_isub(const uint64<8>& a, const uint64<8>& b)
154{
155 return _mm512_sub_epi64(a.native(), b.native());
156}
157#endif
158
159// -----------------------------------------------------------------------------
160
161template<class V> SIMDPP_INL
162V i_isub(const V& a, const V& b)
163{
164 SIMDPP_VEC_ARRAY_IMPL2(V, i_isub, a, b)
165}
166
167} // namespace insn
168} // namespace detail
169} // namespace SIMDPP_ARCH_NAMESPACE
170} // namespace simdpp
171
172#endif
173