Line data Source code
1 : /*
2 : * Copyright (c) 2015 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 : /*
16 : Copyright (c) 2005 Eliot Dresselhaus
17 :
18 : Permission is hereby granted, free of charge, to any person obtaining
19 : a copy of this software and associated documentation files (the
20 : "Software"), to deal in the Software without restriction, including
21 : without limitation the rights to use, copy, modify, merge, publish,
22 : distribute, sublicense, and/or sell copies of the Software, and to
23 : permit persons to whom the Software is furnished to do so, subject to
24 : the following conditions:
25 :
26 : The above copyright notice and this permission notice shall be
27 : included in all copies or substantial portions of the Software.
28 :
29 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 : EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 : MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 : NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 : LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 : OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 : WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 : */
37 :
38 : #ifndef included_vector_sse2_h
39 : #define included_vector_sse2_h
40 :
41 : #include <vppinfra/error_bootstrap.h> /* for ASSERT */
42 : #include <x86intrin.h>
43 :
44 : /* *INDENT-OFF* */
45 : #define foreach_sse42_vec128i \
46 : _(i,8,16,epi8) _(i,16,8,epi16) _(i,32,4,epi32) _(i,64,2,epi64x)
47 : #define foreach_sse42_vec128u \
48 : _(u,8,16,epi8) _(u,16,8,epi16) _(u,32,4,epi32) _(u,64,2,epi64x)
49 : #define foreach_sse42_vec128f \
50 : _(f,32,4,ps) _(f,64,2,pd)
51 :
52 : /* splat, load_unaligned, store_unaligned, is_all_zero, is_equal,
53 : is_all_equal */
54 : #define _(t, s, c, i) \
55 : static_always_inline t##s##x##c \
56 : t##s##x##c##_splat (t##s x) \
57 : { return (t##s##x##c) _mm_set1_##i (x); } \
58 : \
59 : static_always_inline t##s##x##c \
60 : t##s##x##c##_load_unaligned (void *p) \
61 : { return (t##s##x##c) _mm_loadu_si128 (p); } \
62 : \
63 : static_always_inline void \
64 : t##s##x##c##_store_unaligned (t##s##x##c v, void *p) \
65 : { _mm_storeu_si128 ((__m128i *) p, (__m128i) v); } \
66 : \
67 : static_always_inline int \
68 : t##s##x##c##_is_all_zero (t##s##x##c x) \
69 : { return _mm_testz_si128 ((__m128i) x, (__m128i) x); } \
70 : \
71 : static_always_inline int \
72 : t##s##x##c##_is_equal (t##s##x##c a, t##s##x##c b) \
73 : { return t##s##x##c##_is_all_zero (a ^ b); } \
74 : \
75 : static_always_inline int \
76 : t##s##x##c##_is_all_equal (t##s##x##c v, t##s x) \
77 : { return t##s##x##c##_is_equal (v, t##s##x##c##_splat (x)); }; \
78 :
79 67370872142 : foreach_sse42_vec128i foreach_sse42_vec128u
80 : #undef _
81 :
82 : /* min, max */
83 : #define _(t, s, c, i) \
84 : static_always_inline t##s##x##c \
85 : t##s##x##c##_min (t##s##x##c a, t##s##x##c b) \
86 : { return (t##s##x##c) _mm_min_##i ((__m128i) a, (__m128i) b); } \
87 : \
88 : static_always_inline t##s##x##c \
89 : t##s##x##c##_max (t##s##x##c a, t##s##x##c b) \
90 : { return (t##s##x##c) _mm_max_##i ((__m128i) a, (__m128i) b); } \
91 :
92 : _(i,8,16,epi8) _(i,16,8,epi16) _(i,32,4,epi32) _(i,64,2,epi64)
93 41056 : _(u,8,16,epu8) _(u,16,8,epu16) _(u,32,4,epu32) _(u,64,2,epu64)
94 : #undef _
95 : /* *INDENT-ON* */
96 :
97 : #define CLIB_VEC128_SPLAT_DEFINED
98 : #define CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE
99 :
100 : /* 128 bit interleaves. */
101 : always_inline u8x16
102 : u8x16_interleave_hi (u8x16 a, u8x16 b)
103 : {
104 : return (u8x16) _mm_unpackhi_epi8 ((__m128i) a, (__m128i) b);
105 : }
106 :
107 : always_inline u8x16
108 : u8x16_interleave_lo (u8x16 a, u8x16 b)
109 : {
110 : return (u8x16) _mm_unpacklo_epi8 ((__m128i) a, (__m128i) b);
111 : }
112 :
113 : always_inline u16x8
114 : u16x8_interleave_hi (u16x8 a, u16x8 b)
115 : {
116 : return (u16x8) _mm_unpackhi_epi16 ((__m128i) a, (__m128i) b);
117 : }
118 :
119 : always_inline u16x8
120 : u16x8_interleave_lo (u16x8 a, u16x8 b)
121 : {
122 : return (u16x8) _mm_unpacklo_epi16 ((__m128i) a, (__m128i) b);
123 : }
124 :
125 : always_inline u32x4
126 575503000 : u32x4_interleave_hi (u32x4 a, u32x4 b)
127 : {
128 1151010000 : return (u32x4) _mm_unpackhi_epi32 ((__m128i) a, (__m128i) b);
129 : }
130 :
131 : always_inline u32x4
132 575503000 : u32x4_interleave_lo (u32x4 a, u32x4 b)
133 : {
134 1151010000 : return (u32x4) _mm_unpacklo_epi32 ((__m128i) a, (__m128i) b);
135 : }
136 :
137 : always_inline u64x2
138 : u64x2_interleave_hi (u64x2 a, u64x2 b)
139 : {
140 : return (u64x2) _mm_unpackhi_epi64 ((__m128i) a, (__m128i) b);
141 : }
142 :
143 : always_inline u64x2
144 : u64x2_interleave_lo (u64x2 a, u64x2 b)
145 : {
146 : return (u64x2) _mm_unpacklo_epi64 ((__m128i) a, (__m128i) b);
147 : }
148 :
149 : /* 128 bit packs. */
150 : #define _(f, t, fn) \
151 : always_inline t t##_pack (f lo, f hi) \
152 : { \
153 : return (t) fn ((__m128i) lo, (__m128i) hi); \
154 : }
155 :
156 0 : _ (i16x8, i8x16, _mm_packs_epi16)
157 : _ (i16x8, u8x16, _mm_packus_epi16)
158 0 : _ (i32x4, i16x8, _mm_packs_epi32)
159 : _ (i32x4, u16x8, _mm_packus_epi32)
160 :
161 : #undef _
162 :
163 : #define _signed_binop(n,m,f,g) \
164 : /* Unsigned */ \
165 : always_inline u##n##x##m \
166 : u##n##x##m##_##f (u##n##x##m x, u##n##x##m y) \
167 : { return (u##n##x##m) _mm_##g##n ((__m128i) x, (__m128i) y); } \
168 : \
169 : /* Signed */ \
170 : always_inline i##n##x##m \
171 : i##n##x##m##_##f (i##n##x##m x, i##n##x##m y) \
172 : { return (i##n##x##m) _mm_##g##n ((__m128i) x, (__m128i) y); }
173 : /* Addition/subtraction with saturation. */
174 : _signed_binop (8, 16, add_saturate, adds_epu)
175 : _signed_binop (16, 8, add_saturate, adds_epu)
176 : _signed_binop (8, 16, sub_saturate, subs_epu)
177 : _signed_binop (16, 8, sub_saturate, subs_epu)
178 : /* Multiplication. */
179 : always_inline i16x8 i16x8_mul_lo (i16x8 x, i16x8 y)
180 : {
181 : return (i16x8) _mm_mullo_epi16 ((__m128i) x, (__m128i) y);
182 : }
183 :
184 : always_inline u16x8
185 : u16x8_mul_lo (u16x8 x, u16x8 y)
186 : {
187 : return (u16x8) _mm_mullo_epi16 ((__m128i) x, (__m128i) y);
188 : }
189 :
190 : always_inline i16x8
191 : i16x8_mul_hi (i16x8 x, i16x8 y)
192 : {
193 : return (i16x8) _mm_mulhi_epu16 ((__m128i) x, (__m128i) y);
194 : }
195 :
196 : always_inline u16x8
197 : u16x8_mul_hi (u16x8 x, u16x8 y)
198 : {
199 : return (u16x8) _mm_mulhi_epu16 ((__m128i) x, (__m128i) y);
200 : }
201 :
202 : /* 128 bit shifts. */
203 :
204 : #define _(p,a,b,c,f) \
205 : always_inline p##a##x##b p##a##x##b##_ishift_##c (p##a##x##b x, int i) \
206 : { return (p##a##x##b) _mm_##f##i_epi##a ((__m128i) x, i); } \
207 : \
208 : always_inline p##a##x##b p##a##x##b##_shift_##c (p##a##x##b x, p##a##x##b y) \
209 : { return (p##a##x##b) _mm_##f##_epi##a ((__m128i) x, (__m128i) y); }
210 :
211 : _(u, 16, 8, left, sll)
212 : _(u, 32, 4, left, sll)
213 : _(u, 64, 2, left, sll)
214 : _(u, 16, 8, right, srl)
215 : _(u, 32, 4, right, srl)
216 : _(u, 64, 2, right, srl)
217 : _(i, 16, 8, left, sll)
218 : _(i, 32, 4, left, sll)
219 : _(i, 64, 2, left, sll) _(i, 16, 8, right, sra) _(i, 32, 4, right, sra)
220 : #undef _
221 :
222 : #define u8x16_word_shift_left(a,n) (u8x16) _mm_slli_si128((__m128i) a, n)
223 : #define u8x16_word_shift_right(a,n) (u8x16) _mm_srli_si128((__m128i) a, n)
224 :
225 : #define i8x16_word_shift_left(a,n) \
226 : ((i8x16) u8x16_word_shift_left((u8x16) (a), (n)))
227 : #define i8x16_word_shift_right(a,n) \
228 : ((i8x16) u8x16_word_shift_right((u8x16) (a), (n)))
229 :
230 : #define u16x8_word_shift_left(a,n) \
231 : ((u16x8) u8x16_word_shift_left((u8x16) (a), (n) * sizeof (u16)))
232 : #define i16x8_word_shift_left(a,n) \
233 : ((u16x8) u8x16_word_shift_left((u8x16) (a), (n) * sizeof (u16)))
234 : #define u16x8_word_shift_right(a,n) \
235 : ((u16x8) u8x16_word_shift_right((u8x16) (a), (n) * sizeof (u16)))
236 : #define i16x8_word_shift_right(a,n) \
237 : ((i16x8) u8x16_word_shift_right((u8x16) (a), (n) * sizeof (u16)))
238 :
239 : #define u32x4_word_shift_left(a,n) \
240 : ((u32x4) u8x16_word_shift_left((u8x16) (a), (n) * sizeof (u32)))
241 : #define i32x4_word_shift_left(a,n) \
242 : ((u32x4) u8x16_word_shift_left((u8x16) (a), (n) * sizeof (u32)))
243 : #define u32x4_word_shift_right(a,n) \
244 : ((u32x4) u8x16_word_shift_right((u8x16) (a), (n) * sizeof (u32)))
245 : #define i32x4_word_shift_right(a,n) \
246 : ((i32x4) u8x16_word_shift_right((u8x16) (a), (n) * sizeof (u32)))
247 :
248 : #define u64x2_word_shift_left(a,n) \
249 : ((u64x2) u8x16_word_shift_left((u8x16) (a), (n) * sizeof (u64)))
250 : #define i64x2_word_shift_left(a,n) \
251 : ((u64x2) u8x16_word_shift_left((u8x16) (a), (n) * sizeof (u64)))
252 : #define u64x2_word_shift_right(a,n) \
253 : ((u64x2) u8x16_word_shift_right((u8x16) (a), (n) * sizeof (u64)))
254 : #define i64x2_word_shift_right(a,n) \
255 : ((i64x2) u8x16_word_shift_right((u8x16) (a), (n) * sizeof (u64)))
256 :
257 : /* SSE2 has no rotate instructions: use shifts to simulate them. */
258 : #define _(t,n,lr1,lr2) \
259 : always_inline t##x##n \
260 : t##x##n##_irotate_##lr1 (t##x##n w, int i) \
261 : { \
262 : ASSERT (i >= 0 && i <= BITS (t)); \
263 : return (t##x##n##_ishift_##lr1 (w, i) \
264 : | t##x##n##_ishift_##lr2 (w, BITS (t) - i)); \
265 : } \
266 : \
267 : always_inline t##x##n \
268 : t##x##n##_rotate_##lr1 (t##x##n w, t##x##n i) \
269 : { \
270 : t##x##n j = t##x##n##_splat (BITS (t)); \
271 : return (t##x##n##_shift_##lr1 (w, i) \
272 : | t##x##n##_shift_##lr2 (w, j - i)); \
273 : }
274 :
275 : _(u16, 8, left, right);
276 : _(u16, 8, right, left);
277 : _(u32, 4, left, right);
278 : _(u32, 4, right, left);
279 : _(u64, 2, left, right);
280 : _(u64, 2, right, left);
281 :
282 : #undef _
283 :
284 : always_inline u32
285 : u8x16_max_scalar (u8x16 x)
286 : {
287 : x = u8x16_max (x, u8x16_word_shift_right (x, 8));
288 : x = u8x16_max (x, u8x16_word_shift_right (x, 4));
289 : x = u8x16_max (x, u8x16_word_shift_right (x, 2));
290 : x = u8x16_max (x, u8x16_word_shift_right (x, 1));
291 : return _mm_extract_epi16 ((__m128i) x, 0) & 0xff;
292 : }
293 :
294 : always_inline u8
295 : u8x16_min_scalar (u8x16 x)
296 : {
297 : x = u8x16_min (x, u8x16_word_shift_right (x, 8));
298 : x = u8x16_min (x, u8x16_word_shift_right (x, 4));
299 : x = u8x16_min (x, u8x16_word_shift_right (x, 2));
300 : x = u8x16_min (x, u8x16_word_shift_right (x, 1));
301 : return _mm_extract_epi16 ((__m128i) x, 0) & 0xff;
302 : }
303 :
304 : always_inline i16
305 : i16x8_max_scalar (i16x8 x)
306 : {
307 : x = i16x8_max (x, i16x8_word_shift_right (x, 4));
308 : x = i16x8_max (x, i16x8_word_shift_right (x, 2));
309 : x = i16x8_max (x, i16x8_word_shift_right (x, 1));
310 : return _mm_extract_epi16 ((__m128i) x, 0);
311 : }
312 :
313 : always_inline i16
314 : i16x8_min_scalar (i16x8 x)
315 : {
316 : x = i16x8_min (x, i16x8_word_shift_right (x, 4));
317 : x = i16x8_min (x, i16x8_word_shift_right (x, 2));
318 : x = i16x8_min (x, i16x8_word_shift_right (x, 1));
319 : return _mm_extract_epi16 ((__m128i) x, 0);
320 : }
321 :
322 : #define u8x16_align_right(a, b, imm) \
323 : (u8x16) _mm_alignr_epi8 ((__m128i) a, (__m128i) b, imm)
324 :
325 : static_always_inline u32
326 10264 : u32x4_min_scalar (u32x4 v)
327 : {
328 10264 : v = u32x4_min (v, (u32x4) u8x16_align_right ((u8x16) v, (u8x16) v, 8));
329 10264 : v = u32x4_min (v, (u32x4) u8x16_align_right ((u8x16) v, (u8x16) v, 4));
330 10264 : return v[0];
331 : }
332 :
333 : static_always_inline u32
334 : u32x4_max_scalar (u32x4 v)
335 : {
336 : v = u32x4_max (v, (u32x4) u8x16_align_right ((u8x16) v, (u8x16) v, 8));
337 : v = u32x4_max (v, (u32x4) u8x16_align_right ((u8x16) v, (u8x16) v, 4));
338 : return v[0];
339 : }
340 :
341 : static_always_inline u32
342 : i32x4_min_scalar (i32x4 v)
343 : {
344 : v = i32x4_min (v, (i32x4) u8x16_align_right ((u8x16) v, (u8x16) v, 8));
345 : v = i32x4_min (v, (i32x4) u8x16_align_right ((u8x16) v, (u8x16) v, 4));
346 : return v[0];
347 : }
348 :
349 : static_always_inline u32
350 : i32x4_max_scalar (i32x4 v)
351 : {
352 : v = i32x4_max (v, (i32x4) u8x16_align_right ((u8x16) v, (u8x16) v, 8));
353 : v = i32x4_max (v, (i32x4) u8x16_align_right ((u8x16) v, (u8x16) v, 4));
354 : return v[0];
355 : }
356 :
357 : static_always_inline u16
358 0 : u8x16_msb_mask (u8x16 v)
359 : {
360 0 : return _mm_movemask_epi8 ((__m128i) v);
361 : }
362 :
363 : static_always_inline u16
364 0 : i8x16_msb_mask (i8x16 v)
365 : {
366 0 : return _mm_movemask_epi8 ((__m128i) v);
367 : }
368 :
369 : #define CLIB_HAVE_VEC128_MSB_MASK
370 :
371 : #undef _signed_binop
372 :
373 : static_always_inline u32x4
374 : u32x4_byte_swap (u32x4 v)
375 : {
376 : u8x16 swap = {
377 : 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
378 : };
379 : return (u32x4) _mm_shuffle_epi8 ((__m128i) v, (__m128i) swap);
380 : }
381 :
382 : static_always_inline u16x8
383 : u16x8_byte_swap (u16x8 v)
384 : {
385 : u8x16 swap = {
386 : 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14,
387 : };
388 : return (u16x8) _mm_shuffle_epi8 ((__m128i) v, (__m128i) swap);
389 : }
390 :
391 : static_always_inline u8x16
392 8036920 : u8x16_reflect (u8x16 v)
393 : {
394 8036920 : u8x16 mask = {
395 : 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
396 : };
397 16073800 : return (u8x16) _mm_shuffle_epi8 ((__m128i) v, (__m128i) mask);
398 : }
399 :
400 : static_always_inline u32x4
401 : u32x4_hadd (u32x4 v1, u32x4 v2)
402 : {
403 : return (u32x4) _mm_hadd_epi32 ((__m128i) v1, (__m128i) v2);
404 : }
405 :
406 : static_always_inline u32 __clib_unused
407 : u32x4_sum_elts (u32x4 sum4)
408 : {
409 : sum4 += (u32x4) u8x16_align_right (sum4, sum4, 8);
410 : sum4 += (u32x4) u8x16_align_right (sum4, sum4, 4);
411 : return sum4[0];
412 : }
413 :
414 : /* _from_ */
415 : /* *INDENT-OFF* */
416 : #define _(f,t,i) \
417 : static_always_inline t \
418 : t##_from_##f (f x) \
419 : { return (t) _mm_cvt##i ((__m128i) x); }
420 :
421 : _(u8x16, u16x8, epu8_epi16)
422 : _(u8x16, u32x4, epu8_epi32)
423 : _(u8x16, u64x2, epu8_epi64)
424 : _(u16x8, u32x4, epu16_epi32)
425 : _(u16x8, u64x2, epu16_epi64)
426 43715582 : _(u32x4, u64x2, epu32_epi64)
427 :
428 : _(i8x16, i16x8, epi8_epi16)
429 : _(i8x16, i32x4, epi8_epi32)
430 : _(i8x16, i64x2, epi8_epi64)
431 : _(i16x8, i32x4, epi16_epi32)
432 : _(i16x8, i64x2, epi16_epi64)
433 : _(i32x4, i64x2, epi32_epi64)
434 : #undef _
435 : /* *INDENT-ON* */
436 :
437 : static_always_inline u64x2
438 : u64x2_gather (void *p0, void *p1)
439 : {
440 : u64x2 r = { *(u64 *) p0, *(u64 *) p1 };
441 : return r;
442 : }
443 :
444 : static_always_inline u32x4
445 106 : u32x4_gather (void *p0, void *p1, void *p2, void *p3)
446 : {
447 106 : u32x4 r = { *(u32 *) p0, *(u32 *) p1, *(u32 *) p2, *(u32 *) p3 };
448 106 : return r;
449 : }
450 :
451 :
452 : static_always_inline void
453 : u64x2_scatter (u64x2 r, void *p0, void *p1)
454 : {
455 : *(u64 *) p0 = r[0];
456 : *(u64 *) p1 = r[1];
457 : }
458 :
459 : static_always_inline void
460 : u32x4_scatter (u32x4 r, void *p0, void *p1, void *p2, void *p3)
461 : {
462 : *(u32 *) p0 = r[0];
463 : *(u32 *) p1 = r[1];
464 : *(u32 *) p2 = r[2];
465 : *(u32 *) p3 = r[3];
466 : }
467 :
468 : static_always_inline void
469 : u64x2_scatter_one (u64x2 r, int index, void *p)
470 : {
471 : *(u64 *) p = r[index];
472 : }
473 :
474 : static_always_inline void
475 : u32x4_scatter_one (u32x4 r, int index, void *p)
476 : {
477 : *(u32 *) p = r[index];
478 : }
479 :
480 : static_always_inline u8x16
481 0 : u8x16_blend (u8x16 v1, u8x16 v2, u8x16 mask)
482 : {
483 0 : return (u8x16) _mm_blendv_epi8 ((__m128i) v1, (__m128i) v2, (__m128i) mask);
484 : }
485 :
486 : static_always_inline u8x16
487 19665892 : u8x16_xor3 (u8x16 a, u8x16 b, u8x16 c)
488 : {
489 : #if __AVX512F__
490 19665892 : return (u8x16) _mm_ternarylogic_epi32 ((__m128i) a, (__m128i) b,
491 : (__m128i) c, 0x96);
492 : #endif
493 0 : return a ^ b ^ c;
494 : }
495 :
496 : static_always_inline u8x16
497 131379 : u8x16_load_partial (u8 *data, uword n)
498 : {
499 131379 : u8x16 r = {};
500 : #if defined(CLIB_HAVE_VEC128_MASK_LOAD_STORE)
501 : return u8x16_mask_load_zero (data, pow2_mask (n));
502 : #endif
503 131379 : if (n > 7)
504 : {
505 : u64x2 r;
506 26939 : r[1] = *(u64u *) (data + n - 8);
507 26939 : r >>= (16 - n) * 8;
508 26939 : r[0] = *(u64u *) data;
509 26939 : return (u8x16) r;
510 : }
511 104440 : else if (n > 3)
512 : {
513 103821 : u32x4 r = {};
514 103821 : r[1] = *(u32u *) (data + n - 4);
515 103821 : r >>= (8 - n) * 8;
516 103821 : r[0] = *(u32u *) data;
517 103821 : return (u8x16) r;
518 : }
519 619 : else if (n > 1)
520 : {
521 441 : u16x8 r = {};
522 441 : r[1] = *(u16u *) (data + n - 2);
523 441 : r >>= (4 - n) * 8;
524 441 : r[0] = *(u16u *) data;
525 441 : return (u8x16) r;
526 : }
527 178 : else if (n > 0)
528 178 : r[0] = *data;
529 178 : return r;
530 : }
531 :
532 : static_always_inline void
533 131379 : u8x16_store_partial (u8x16 r, u8 *data, uword n)
534 : {
535 : #if defined(CLIB_HAVE_VEC256_MASK_LOAD_STORE)
536 : u8x16_mask_store (r, data, pow2_mask (n));
537 : #else
538 131379 : if (n > 7)
539 : {
540 26939 : *(u64u *) (data + n - 8) = ((u64x2) r)[1] << ((16 - n) * 8);
541 26939 : *(u64u *) data = ((u64x2) r)[0];
542 : }
543 104440 : else if (n > 3)
544 : {
545 103821 : *(u32u *) (data + n - 4) = ((u32x4) r)[1] << ((8 - n) * 8);
546 103821 : *(u32u *) data = ((u32x4) r)[0];
547 : }
548 619 : else if (n > 1)
549 : {
550 441 : *(u16u *) (data + n - 2) = ((u16x8) r)[1] << ((4 - n) * 8);
551 441 : *(u16u *) data = ((u16x8) r)[0];
552 : }
553 178 : else if (n > 0)
554 178 : data[0] = r[0];
555 : #endif
556 131379 : }
557 :
558 : #endif /* included_vector_sse2_h */
559 :
560 : /*
561 : * fd.io coding-style-patch-verification: ON
562 : *
563 : * Local Variables:
564 : * eval: (c-set-style "gnu")
565 : * End:
566 : */
|