source: trunk/lib/sse_simd_t.h @ 399

Last change on this file since 399 was 379, checked in by ksherdy, 10 years ago

Added high mask and comments.

File size: 25.1 KB
Line 
1/*  Idealized SIMD Operations with SSE versions
2    Copyright (C) 2006, 2007, 2008, 2009, Robert D. Cameron and Dan Lin
3    Licensed to the public under the Open Software License 3.0.
4    Licensed to International Characters Inc.
5       under the Academic Free License version 3.0.
6*/
7#ifndef SSE_SIMD_H
8#define SSE_SIMD_H
9
10/*
11  Replace the following SSE version specific include directives with the x86intrin.h meta intrinsic header. This header is available with GCC 4.4.X
12*/
13#ifdef __MMX__
14#include <mmintrin.h>
15#endif
16
17#ifdef __SSE__
18#include <xmmintrin.h>
19#endif
20
21#ifdef __SSE2__
22#include <emmintrin.h>
23#endif
24
25#ifdef __SSE3__
26#include <pmmintrin.h>
27#endif
28
29#ifdef __SSSE3__
30#include <tmmintrin.h>
31#endif
32
33#ifdef __SSE4a__
34#include <ammintrin.h>
35#endif
36
37#if defined (__SSE4_2__) || defined (__SSE4_1__)
38
39#include <smmintrin.h>
40#endif
41
42/*------------------------------------------------------------*/
43#ifndef _MSC_VER
44#include <stdint.h>
45#endif
46#ifdef _MSC_VER
47#include "stdint.h"
48#define LITTLE_ENDIAN 1234
49#define BIG_ENDIAN 4321
50#define BYTE_ORDER LITTLE_ENDIAN
51#endif
52#include <limits.h>
53#ifndef LONG_BIT
54#define LONG_BIT (8* sizeof(unsigned long))
55#endif
56#include <emmintrin.h>
57#ifdef USE_LDDQU
58#include <pmmintrin.h>
59#endif
60
61#include <stdio.h>
62
63typedef __m128i SIMD_type;
64
65static inline void print_bit_block(const char * var_name, SIMD_type v);
66
67/*------------------------------------------------------------*/
68/* I. SIMD bitwise logical operations */
69
70static inline SIMD_type simd_and(SIMD_type b1, SIMD_type b2) {
71        return _mm_and_si128(b1, b2);
72}
73static inline SIMD_type simd_andc(SIMD_type b1, SIMD_type b2) {
74        return _mm_andnot_si128(b2, b1);
75}
76static inline SIMD_type simd_or(SIMD_type b1, SIMD_type b2) {
77        return  _mm_or_si128(b1, b2);
78}
79static inline SIMD_type simd_xor(SIMD_type b1, SIMD_type b2) {
80        return  _mm_xor_si128(b1, b2);
81}
82static inline SIMD_type simd_not(SIMD_type b) {
83        return  simd_xor(b, _mm_set1_epi32(0xFFFFFFFF));
84}
85static inline SIMD_type simd_nor(SIMD_type b1, SIMD_type b2) {
86        return  simd_not(simd_or(b1,b2));
87}
88static inline SIMD_type simd_if(SIMD_type cond, SIMD_type then_val, SIMD_type else_val) {       
89        return  simd_or(simd_and(then_val, cond), simd_andc(else_val, cond));
90}
91
92
93/*------------------------------------------------------------*/
94/* II. Declarations of field-width based operations. */
95
96/*  Half-operand modifier specifications use "x", "h" or "l",
97 *  "x" - no modification of the corresponding operand value
98 *  "h" - each n-bit field is modified by taking the high n/2 bits.
99 *  "l" - each n-bit field is modified by taking the low n/2 bits. */
100 
101enum HOM_t {x,h,l};
102
103/* simd<fw> is a template struct providing all the simd operations
104 * for a given field width.  */
105template <int fw>
106struct simd {
107        /* The himask selector in which each field is fw/2 1 bits,
108         * followed by fw/2 0 bits. */
109        static inline SIMD_type himask();
110
111        /* The himask selector in which each field is fw/2 0 bits,
112         * followed by fw/2 1 bits. */ 
113        static inline SIMD_type lomask();
114       
115        /* Splat constant generator with compile-time constant. */
116        template <int v> static inline SIMD_type constant();
117        /* Splat generator using the first field of a register. */
118        static inline SIMD_type splat(SIMD_type r);
119  /* Move mask */
120  static inline int movemask(SIMD_type r); 
121  /* Shuffle */
122  static inline SIMD_type shuffle(SIMD_type r, SIMD_type s);
123
124       
125        /* Shift immediate with the shift constant as a template parameter. */
126        template <int shft> static inline SIMD_type srli(SIMD_type r);
127        template <int shft> static inline SIMD_type slli(SIMD_type r);
128        template <int shft> static inline SIMD_type srai(SIMD_type r);
129       
130        /* Shift operations with register-specified shift values. */
131        static inline SIMD_type srl(SIMD_type r, SIMD_type shft);
132        static inline SIMD_type sll(SIMD_type r, SIMD_type shft);
133       
134        /* Binary operations. */
135        static inline SIMD_type add(SIMD_type r1, SIMD_type r2);
136        static inline SIMD_type sub(SIMD_type r1, SIMD_type r2);
137        static inline SIMD_type mult(SIMD_type r1, SIMD_type r2);
138        static inline SIMD_type max(SIMD_type r1, SIMD_type r2);
139        static inline SIMD_type eq(SIMD_type r1, SIMD_type r2);
140        static inline SIMD_type gt(SIMD_type r1, SIMD_type r2);
141        static inline SIMD_type pack(SIMD_type r1, SIMD_type r2);
142        static inline SIMD_type mergeh(SIMD_type r1, SIMD_type r2);
143        static inline SIMD_type mergel(SIMD_type r1, SIMD_type r2);
144
145//      /* Functions for half-operand modification. */
146//     
147//      template <HOM_t m> static inline SIMD_type hom(SIMD_type r);
148//      template <HOM_t m> static inline SIMD_type hx(SIMD_type r);
149       
150        /* Binary operations with half-operand modifiers */
151       
152        template <HOM_t m1, HOM_t m2> static inline SIMD_type add(SIMD_type r1, SIMD_type r2);
153        template <HOM_t m1, HOM_t m2> static inline SIMD_type sub(SIMD_type r1, SIMD_type r2);
154        template <HOM_t m1, HOM_t m2> static inline SIMD_type mult(SIMD_type r1, SIMD_type r2);
155        template <HOM_t m1, HOM_t m2> static inline SIMD_type pack(SIMD_type r1, SIMD_type r2);
156        template <HOM_t m1, HOM_t m2> static inline SIMD_type mergeh(SIMD_type r1, SIMD_type r2);
157        template <HOM_t m1, HOM_t m2> static inline SIMD_type mergel(SIMD_type r1, SIMD_type r2);
158
159};
160
161#define sisd_to_int(x) _mm_cvtsi128_si32(x)
162
163#define sisd_from_int(n) _mm_cvtsi32_si128(n)
164
165
166
167
168/* III.  Implementations of simd<fw> operations. */
169
170/* Constant generator functions for various field widths. */
171
172template<> inline SIMD_type simd<2>::himask() {return _mm_set1_epi8(0xAA);}
173
174template<> inline SIMD_type simd<4>::himask() {return _mm_set1_epi8(0xCC);}
175
176template<> inline SIMD_type simd<8>::himask() {return _mm_set1_epi8(0xF0);}
177
178template<> inline SIMD_type simd<16>::himask() {return _mm_set1_epi16(0xFF00);}
179
180template<> inline SIMD_type simd<32>::himask() {return _mm_set1_epi32(0xFFFF0000);}
181
182template<> inline SIMD_type simd<64>::himask() {return _mm_set_epi32(-1,0,-1,0);}
183
184template<> inline SIMD_type simd<128>::himask() {return _mm_set_epi32(-1,-1,0,0);}
185
186template<> inline SIMD_type simd<16>::lomask() {return _mm_set1_epi16(0x00FF);}
187
188template<> inline SIMD_type simd<32>::lomask() {return _mm_set1_epi32(0x0000FFFF);}
189
190template<> inline SIMD_type simd<64>::lomask() {return _mm_set_epi32(0,-1,0,-1);}
191
192template<> inline SIMD_type simd<128>::lomask() {return _mm_set_epi32(0,0,-1,-1);}
193
194template<> template <int n> inline SIMD_type simd<4>::constant() {return _mm_set1_epi8((n)<<4|(n));}
195
196template<> template <int n> inline SIMD_type simd<8>::constant() {return _mm_set1_epi8(n);}
197
198template<> template <int n> inline SIMD_type simd<16>::constant() {return _mm_set1_epi16(n);}
199
200template<> template <int n> inline SIMD_type simd<32>::constant() {return _mm_set1_epi32(n);}
201
202template<> template <> inline SIMD_type simd<1>::constant<0>() {return simd<8>::constant<0>();}
203template<> template <> inline SIMD_type simd<1>::constant<1>() {return simd<8>::constant<-1>();}
204
205template<> template <int n> inline SIMD_type simd<2>::constant() {return simd<4>::constant<(n<<2|n)>();}
206
207// Splat the first 8-bit int into all positions.
208template <> inline SIMD_type simd<8>::splat(SIMD_type x) {
209  return _mm_set1_epi8(*(uint8_t *)(&x));
210}
211
212// Splat the first 16-bit int into all positions.
213template <> inline SIMD_type simd<16>::splat(SIMD_type x) {
214  SIMD_type t = _mm_shufflelo_epi16(x,0);
215  return _mm_shuffle_epi32(t,0);
216}
217
218// Splat the first 32-bit int into all positions.
219template <> inline SIMD_type simd<32>::splat(SIMD_type x) {
220  return _mm_shuffle_epi32(x,0);
221}
222
223// Splat the first 64-bit int into all positions.
224template <> inline SIMD_type simd<64>::splat(SIMD_type x) {
225  return _mm_shuffle_epi32(x,_MM_SHUFFLE(1,0,1,0));
226}
227
228// Move mask 8-bit
229template <> inline int simd<8>::movemask(SIMD_type r) {
230  return _mm_movemask_epi8(r);
231}
232
233// Shuffle 8-bit
234template <> inline SIMD_type simd<8>::shuffle(SIMD_type r, SIMD_type s) {
235  return _mm_shuffle_epi8(r,s); // SSSE3 dependency
236}
237
238/* Shift immediate operations with direct implementation by built-ins. */
239
240template<> template<int sh> inline SIMD_type simd<16>::slli(SIMD_type r) {return _mm_slli_epi16(r, sh);}
241
242template<> template<int sh> inline SIMD_type simd<32>::slli(SIMD_type r) {return _mm_slli_epi32(r, sh);}
243
244template<> template<int sh> inline SIMD_type simd<64>::slli(SIMD_type r) {return _mm_slli_epi64(r, sh);}
245
246template<> template<int sh> inline SIMD_type simd<16>::srli(SIMD_type r) {return _mm_srli_epi16(r, sh);}
247
248template<> template<int sh> inline SIMD_type simd<32>::srli(SIMD_type r) {return _mm_srli_epi32(r, sh);}
249
250template<> template<int sh> inline SIMD_type simd<64>::srli(SIMD_type r) {return _mm_srli_epi64(r, sh);}
251
252/* simd_srai
253 * fw: 16,32*/
254template<> template<int sh> inline SIMD_type simd<16>::srai(SIMD_type r) {return _mm_srai_epi16(r, sh);}
255
256template<> template<int sh> inline SIMD_type simd<32>::srai(SIMD_type r) {return _mm_srai_epi32(r, sh);}
257                 
258
259
260/* General rules for slli/srli for field widths 2, 4, 8 in terms of 32-bit shifts. */
261
262
263// Doesn't work:
264//template<int fw> template<int sh>
265//inline SIMD_type simd<fw>::slli(SIMD_type r) {
266//      return simd_and(simd<32>::slli<sh>(r), simd<fw>::constant<6>());
267//}
268//
269
270
271template<> template<int sh>
272inline SIMD_type simd<2>::slli(SIMD_type r) {
273        return simd_and(simd<32>::slli<sh>(r),simd<2>::constant<((3<<sh)&3)>());
274}
275
276template<> template<int sh>
277inline SIMD_type simd<4>::slli(SIMD_type r) {
278        return simd_and(simd<32>::slli<sh>(r),simd<4>::constant<((15<<sh)&15)>());
279}
280
281template<> template<int sh>
282inline SIMD_type simd<8>::slli(SIMD_type r) {
283        return simd_and(simd<32>::slli<sh>(r),simd<8>::constant<((255<<sh)&255)>());
284}
285
286
287//template<int fw> template<int sh>
288//inline SIMD_type simd<fw>::srli(SIMD_type r) {
289//      return simd_and(simd<32>::srli<sh>(r),simd<fw>::constant<((1<<(fw-sh))-1)>());
290//}
291//
292
293
294template<> template<int sh>
295inline SIMD_type simd<2>::srli(SIMD_type r) {
296        return simd_and(simd<32>::srli<sh>(r),simd<2>::constant<(3>>sh)>());
297}
298
299template<> template<int sh>
300inline SIMD_type simd<4>::srli(SIMD_type r) {
301        return simd_and(simd<32>::srli<sh>(r),simd<4>::constant<(15>>sh)>());
302}
303
304template<> template<int sh>
305inline SIMD_type simd<8>::srli(SIMD_type r) {
306        return simd_and(simd<32>::srli<sh>(r),simd<8>::constant<(255>>sh)>());
307}
308
309
310
311
312/* Shift immediate for 128-bit fields */
313
314template<> template<int shft>
315inline SIMD_type simd<128>::slli(SIMD_type r) {
316        return (shft % 8 == 0 ? _mm_slli_si128(r, shft/8) :
317                shft >= 64 ? simd<64>::slli<shft-64>(_mm_slli_si128(r, 8)) :
318                simd_or(simd<64>::slli<shft>(r), _mm_slli_si128(simd<64>::srli<64-shft>(r), 8)));
319}
320
321template<> template<int shft>
322inline SIMD_type simd<128>::srli(SIMD_type r) {
323        return (shft % 8 == 0 ? _mm_srli_si128(r, shft/8) :
324                shft >= 64 ? simd<64>::srli<shft-64>(_mm_srli_si128(r, 8)) :
325                simd_or(simd<64>::srli<shft>(r), _mm_srli_si128(simd<64>::slli<64-shft>(r), 8)));
326}
327
328
329/* Shifts with shift values specified in an operand register. */
330
331template<>
332inline SIMD_type simd<128>::srl(SIMD_type r, SIMD_type shft) {
333        return simd_or(_mm_srl_epi64(r, shft),
334                       simd_or(_mm_srli_si128(_mm_srl_epi64(r, _mm_sub_epi32(shft, sisd_from_int(64))), 8),
335                               _mm_srli_si128(_mm_sll_epi64(r, _mm_sub_epi32(sisd_from_int(64), shft)), 8)));
336}
337
338template<>
339inline SIMD_type simd<128>::sll(SIMD_type r, SIMD_type shft) {
340        return simd_or(_mm_sll_epi64(r, shft),
341                       simd_or(_mm_slli_si128(_mm_sll_epi64(r, _mm_sub_epi32(shft, sisd_from_int(64))), 8),
342                               _mm_slli_si128(_mm_srl_epi64(r, _mm_sub_epi32(sisd_from_int(64), shft)), 8)));
343}
344
345template<>
346inline SIMD_type simd<64>::srl(SIMD_type r, SIMD_type shft) {
347        return simd_if(simd<128>::himask(),
348                       _mm_srl_epi64(r, _mm_srli_si128(shft, 8)),
349                       _mm_srl_epi64(r, simd_andc(shft, simd<128>::himask())));
350}
351
352template<>
353inline SIMD_type simd<64>::sll(SIMD_type r, SIMD_type shft) {
354        return simd_if(simd<128>::himask(),
355                       _mm_sll_epi64(r, _mm_srli_si128(shft, 8)),
356                       _mm_sll_epi64(r, simd_andc(shft, simd<128>::himask())));
357}
358
359
360/* simd_add
361 * fw: 2,4,8,16,32,64
362
363   Use built-ins for 8, 16, 32, 64, simulations for 2, 4. */
364
365template<> inline SIMD_type simd<8>::add(SIMD_type r1, SIMD_type r2) {return _mm_add_epi8(r1, r2);}
366
367template<> inline SIMD_type simd<16>::add(SIMD_type r1, SIMD_type r2) {return _mm_add_epi16(r1, r2);}
368
369template<> inline SIMD_type simd<32>::add(SIMD_type r1, SIMD_type r2) {return _mm_add_epi32(r1, r2);}
370
371template<> inline SIMD_type simd<64>::add(SIMD_type r1, SIMD_type r2) {return _mm_add_epi64(r1, r2);}
372
373template<>
374inline SIMD_type simd<2>::add(SIMD_type r1, SIMD_type r2) {
375         SIMD_type c1 = simd_xor(r1,r2);
376         SIMD_type borrow = simd_and(r1,r2);
377         SIMD_type c2 = simd_xor(c1,(simd<128>::slli<1>(borrow)));
378         return simd_if(simd<2>::himask(),c2,c1);
379}
380
381template<>
382inline SIMD_type simd<4>::add(SIMD_type r1, SIMD_type r2) {
383        return simd_if(simd<8>::himask(), 
384                       simd<8>::add(r1,simd_and(r2,simd<8>::himask())),
385                       simd<8>::add(r1, r2));
386}
387
388/* simd_sub
389 * fw: 2,4,8,16,32,64
390
391   Use built-ins for 8, 16, 32, 64, simulations for 2, 4. */
392
393template<> inline SIMD_type simd<8>::sub(SIMD_type r1, SIMD_type r2) {return _mm_sub_epi8(r1, r2);}
394
395template<> inline SIMD_type simd<16>::sub(SIMD_type r1, SIMD_type r2) {return _mm_sub_epi16(r1, r2);}
396
397template<> inline SIMD_type simd<32>::sub(SIMD_type r1, SIMD_type r2) {return _mm_sub_epi32(r1, r2);}
398
399template<> inline SIMD_type simd<64>::sub(SIMD_type r1, SIMD_type r2) {return _mm_sub_epi64(r1, r2);}
400
401
402template<>
403inline SIMD_type simd<2>::sub(SIMD_type r1, SIMD_type r2)
404{
405         SIMD_type c1 = simd_xor(r1,r2);
406         SIMD_type borrow = simd_andc(r2,r1);
407         SIMD_type c2 = simd_xor(c1,(simd<128>::slli<1>(borrow)));
408         return simd_if(simd<2>::himask(),c2,c1);
409}
410
411template<>
412inline SIMD_type simd<4>::sub(SIMD_type r1, SIMD_type r2){
413        return simd_if(simd<8>::himask(), 
414                       simd<8>::sub(r1, simd_and(r2,simd<8>::himask())),
415                       simd<8>::sub(r1, r2));
416}
417
418/* simd_mult built-in for 16 bits only. */
419
420template<> inline SIMD_type simd<16>::mult(SIMD_type r1, SIMD_type r2) {return _mm_mullo_epi16(r1, r2);}
421
422
423/* _mm_mul_epu2 is equivalent of simd<64>::mult<l,l>*/
424template<> inline SIMD_type simd<32>::mult(SIMD_type r1, SIMD_type r2) {
425        return simd_or(_mm_mul_epu32(r1, r2),
426                       simd::slli<32>(_mm_mul_epu32(simd::srli<32>(r1), simd::srli<32>(r2))));
427}
428
429
430template<>
431inline SIMD_type simd<8>::mult(SIMD_type r1, SIMD_type r2){
432        return simd_or(simd<16>::mult<h,x>(r1, simd_and(simd<16>::himask(), r2)),
433                       simd<16>::mult<l,l>(r1, r2));
434}
435
436
437
438
439
440/* simd_max for 8 bits only. */
441
442template<> inline SIMD_type simd<8>::max(SIMD_type r1, SIMD_type r2) {return _mm_max_epu8(r1, r2);}
443
444
445/* simd_eq
446 * fw: 8,16,32*/
447
448template<> inline SIMD_type simd<8>::eq(SIMD_type r1, SIMD_type r2) {return _mm_cmpeq_epi8(r1, r2);}
449
450template<> inline SIMD_type simd<16>::eq(SIMD_type r1, SIMD_type r2) {return _mm_cmpeq_epi16(r1, r2);}
451
452template<> inline SIMD_type simd<32>::eq(SIMD_type r1, SIMD_type r2) {return _mm_cmpeq_epi32(r1, r2);}
453
454template<> inline SIMD_type simd<64>::eq(SIMD_type r1, SIMD_type r2) {
455
456  #ifdef __SSE4_1__
457    return _mm_cmpeq_epi64(r1, r2);
458  #endif
459
460  // Fall back
461  SIMD_type t = _mm_cmpeq_epi32(r1, r2);
462  return simd_and(t, _mm_shuffle_epi32(t,_MM_SHUFFLE(2,3,0,1)));
463
464}
465
466/*simd_pack
467 * fw: 2,4,8,16*/
468
469/* Built-in operation for fw = 16. */
470template<>
471inline SIMD_type simd<16>::pack(SIMD_type r1, SIMD_type r2) {
472        return _mm_packus_epi16(simd_andc(r2, simd<16>::himask()), simd_andc(r1, simd<16>::himask()));
473}
474
475template<>
476inline SIMD_type simd<32>::pack(SIMD_type r1, SIMD_type r2) {
477
478  #ifdef __SSE4_1__
479        return _mm_packus_epi32(simd_andc(r2, simd<32>::himask()), simd_andc(r1, simd<32>::himask()));
480  #endif
481
482  // Fall back, SSSE3 dependency
483  return  simd_or (_mm_shuffle_epi8(simd_andc(r1, simd<32>::himask()), _mm_set_epi8(0,1,4,5,8,9,12,13,2,3,6,7,10,11,14,15)),
484                     _mm_shuffle_epi8(simd_andc(r2, simd<32>::himask()), _mm_set_epi8(2,3,6,7,10,11,14,15,0,1,4,5,8,9,12,13)));
485
486}
487
488template<>
489inline SIMD_type simd<64>::pack(SIMD_type r1, SIMD_type r2) {
490
491
492  return  simd_or(_mm_shuffle_epi32(simd_andc(r1, simd<64>::himask()), _MM_SHUFFLE(2,0,3,1)), 
493                  _mm_shuffle_epi32(simd_andc(r2, simd<64>::himask()), _MM_SHUFFLE(3,1,2,0))); // 1,3 contain 0
494 
495}
496
497/* fw: 2, 4, 8 */
498template<int fw>
499inline SIMD_type simd<fw>::pack(SIMD_type r1, SIMD_type r2){
500        return simd<fw*2>::pack(simd_if(simd<fw>::himask(),simd<128>::srli<fw/2>(r1),r1),
501                                simd_if(simd<fw>::himask(),simd<128>::srli<fw/2>(r2),r2));
502}
503
504/* simd_mergeh
505 * fw: 1,2,4,8,16,32,64*/
506template<int fw>
507inline SIMD_type simd<fw>::mergeh(SIMD_type r1, SIMD_type r2){
508        /*fw: 1,2,4*/
509        return simd<fw*2>::mergeh(simd_if(simd<fw*2>::himask(),r1,simd<fw*2>::srli<fw>(r2)),
510                                  simd_if(simd<fw*2>::himask(),simd<fw*2>::slli<fw>(r1),r2));
511}
512
513template<> inline SIMD_type simd<8>::mergeh(SIMD_type r1, SIMD_type r2) {return _mm_unpackhi_epi8(r2, r1);}
514template<> inline SIMD_type simd<16>::mergeh(SIMD_type r1, SIMD_type r2) {return _mm_unpackhi_epi16(r2, r1);}
515template<> inline SIMD_type simd<32>::mergeh(SIMD_type r1, SIMD_type r2) {return _mm_unpackhi_epi32(r2, r1);}
516template<> inline SIMD_type simd<64>::mergeh(SIMD_type r1, SIMD_type r2) {return _mm_unpackhi_epi64(r2, r1);}
517
518
519/* simd_mergel
520 * fw: 1,2,4,8,16,32,64*/
521template<int fw>
522inline SIMD_type simd<fw>::mergel(SIMD_type r1, SIMD_type r2){
523        /*fw: 1,2,4*/
524        return simd<fw*2>::mergel(simd_if(simd<fw*2>::himask(),r1,simd<fw*2>::srli<fw>(r2)),
525                                  simd_if(simd<fw*2>::himask(),simd<fw*2>::slli<fw>(r1),r2));
526}
527
528template<> inline SIMD_type simd<8>::mergel(SIMD_type r1, SIMD_type r2) {return _mm_unpacklo_epi8(r2, r1);}
529template<> inline SIMD_type simd<16>::mergel(SIMD_type r1, SIMD_type r2) {return _mm_unpacklo_epi16(r2, r1);}
530template<> inline SIMD_type simd<32>::mergel(SIMD_type r1, SIMD_type r2) {return _mm_unpacklo_epi32(r2, r1);}
531template<> inline SIMD_type simd<64>::mergel(SIMD_type r1, SIMD_type r2) {return _mm_unpacklo_epi64(r2, r1);}
532
533
534#define simd_all_eq_8(v1, v2) simd_all_true<8>(_mm_cmpeq_epi8(v1, v2))
535#define simd_mask_eq_8(v1, v2, hex_mask) simd_mask_true<8>(_mm_cmpeq_epi8(v1, v2), hex_mask)
536#define simd_all_le_8(v1, v2) simd_all_eq_8(simd_max_8(v1, v2), v2)
537
538#define simd_all_signed_gt_8(v1, v2) simd_all_true_8(_mm_cmpgt_epi8(v1, v2))
539
540#define simd_cmpgt_8(v1,v2) _mm_cmpgt_epi8(v1, v2)
541
542
543
544/* simd_all_true
545 * fw: 8*/
546template<int fw>
547static inline int simd_all_true(SIMD_type r);
548template<>
549inline int simd_all_true<8>(SIMD_type r) {
550        return _mm_movemask_epi8(r) == 0xFFFF;
551}
552
553/* simd_any_true
554 * fw: 8*/
555template<int fw>
556static inline int simd_any_true(SIMD_type r);
557template<>
558inline int simd_any_true<8>(SIMD_type r) {
559        return _mm_movemask_epi8(r) != 0;
560}
561
562/* simd_mask_true
563 * fw: 8*/
564template<int fw>
565static inline int simd_mask_true(SIMD_type v, int mask_16_bit) {
566        return (_mm_movemask_epi8(v) & mask_16_bit) == mask_16_bit;
567}
568
569/* simd_any_sign_bit
570 * fw: 8*/
571template<int fw>
572static inline int simd_any_sign_bit(SIMD_type r);
573template<>
574inline int simd_any_sign_bit<8>(SIMD_type r) {
575        return _mm_movemask_epi8(r) != 0;
576}
577
578
579
580/* IV.  Half operand modifiers - implementations. */
581/* Half operand modifier functions.*/
582
583template <int fw, HOM_t m>
584struct SIMD {
585        static inline SIMD_type hom(SIMD_type r) {}
586};
587
588template <int fw>
589struct SIMD<fw, x> {
590        static inline SIMD_type hom(SIMD_type r) {return r;}
591        static inline SIMD_type l2x(SIMD_type r) {return r;}
592};
593
594template <int fw>
595struct SIMD<fw, l> {
596        static inline SIMD_type hom(SIMD_type r) {return simd_andc(r, simd<fw>::himask());}
597        static inline SIMD_type l2x(SIMD_type r) {return r;}
598};
599
600// Wish we could make this generic.
601//template <int fw>
602//struct SIMD<fw, h> {
603//      static inline SIMD_type hom(SIMD_type r) {return simd<fw>::srli<fw/2>(r);}
604//      static inline SIMD_type l2x(SIMD_type r) {return simd<fw>::srli<fw/2>(r);}
605//};
606//
607template <>
608struct SIMD<2, h> {
609        static inline SIMD_type hom(SIMD_type r) {return simd<2>::srli<1>(r);}
610        static inline SIMD_type l2x(SIMD_type r) {return simd<2>::srli<1>(r);}
611};
612
613template <>
614struct SIMD<4, h> {
615        static inline SIMD_type hom(SIMD_type r) {return simd<4>::srli<2>(r);}
616        static inline SIMD_type l2x(SIMD_type r) {return simd<4>::srli<2>(r);}
617};
618
619template <>
620struct SIMD<8, h> {
621        static inline SIMD_type hom(SIMD_type r) {return simd<8>::srli<4>(r);}
622        static inline SIMD_type l2x(SIMD_type r) {return simd<8>::srli<4>(r);}
623};
624
625template <>
626struct SIMD<16, h> {
627        static inline SIMD_type hom(SIMD_type r) {return simd<16>::srli<8>(r);}
628        static inline SIMD_type l2x(SIMD_type r) {return simd<16>::srli<8>(r);}
629};
630
631template <>
632struct SIMD<32, h> {
633        static inline SIMD_type hom(SIMD_type r) {return simd<32>::srli<16>(r);}
634        static inline SIMD_type l2x(SIMD_type r) {return simd<32>::srli<16>(r);}
635};
636
637
638/* SIMD operations extended with HOM*/
639template<int fw> template <HOM_t m1, HOM_t m2>
640inline SIMD_type simd<fw>::add(SIMD_type r1, SIMD_type r2){
641        return simd<fw>::add(SIMD<fw,m1>::hom(r1),SIMD<fw,m2>::hom(r2));
642}
643
644template<int fw> template <HOM_t m1, HOM_t m2>
645inline SIMD_type simd<fw>::sub(SIMD_type r1, SIMD_type r2){
646        return simd<fw>::sub(SIMD<fw,m1>::hom(r1),SIMD<fw,m2>::hom(r2));
647}
648
649template<int fw> template <HOM_t m1, HOM_t m2>
650inline SIMD_type simd<fw>::pack(SIMD_type r1, SIMD_type r2){
651        return simd<fw>::pack(SIMD<fw,m1>::l2x(r1),SIMD<fw,m2>::l2x(r2));
652}
653
654template<int fw> template <HOM_t m1, HOM_t m2>
655inline SIMD_type simd<fw>::mergeh(SIMD_type r1, SIMD_type r2){
656        return simd<fw>::mergeh(SIMD<fw,m1>::hom(r1),SIMD<fw,m2>::hom(r2));
657}
658
659template<int fw> template <HOM_t m1, HOM_t m2>
660inline SIMD_type simd<fw>::mergel(SIMD_type r1, SIMD_type r2){
661        return simd<fw>::mergel(SIMD<fw,m1>::hom(r1),SIMD<fw,m2>::hom(r2));
662}
663
664template<int fw> template <HOM_t m1, HOM_t m2>
665inline SIMD_type simd<fw>::mult(SIMD_type r1, SIMD_type r2){
666        return simd<fw>::mult(SIMD<fw,m1>::hom(r1),SIMD<fw,m2>::hom(r2));
667}
668
669
670//
671//template <HOM_t m>
672//struct HOM {
673//template<int fw> SIMD_type hom(SIMD_type r) {return r;}
674//template<int fw> SIMD_type l2x(SIMD_type r) {return r;}
675//};
676//
677//template <>
678//template <int fw>
679//SIMD_type HOM<l>::hom(SIMD_type r) {return simd_andc(r, simd<fw>::himask());}
680//
681//template <>
682//template <int fw>
683//SIMD_type HOM<h>::hom(SIMD_type r) {return simd<fw>::srli<fw/2>(r);}
684//
685//template <>
686//template <int fw>
687//SIMD_type HOM<h>::l2x(SIMD_type r) {return simd<fw>::srli<fw/2>(r);}
688//
689//
690///* SIMD operations extended with Half-Operand Modifiers */
691//
692//template<int fw> template <HOM_t m1, HOM_t m2>
693//inline SIMD_type simd<fw>::add(SIMD_type r1, SIMD_type r2){
694//      return simd<fw>::add(HOM<m1>::hom<fw>, HOM<m2>::hom<fw>(r2));
695//}
696//
697//template<int fw> template <HOM_t m1, HOM_t m2>
698//inline SIMD_type simd<fw>::sub(SIMD_type r1, SIMD_type r2){
699//      return simd<fw>::sub(HOM<m1>::hom<fw>, HOM<m2>::hom<fw>(r2));
700//}
701//
702//template<int fw> template <HOM_t m1, HOM_t m2>
703//inline SIMD_type simd<fw>::mult(SIMD_type r1, SIMD_type r2){
704//      return simd<fw>::mult(HOM<m1>::hom<fw>, HOM<m2>::hom<fw>(r2));
705//}
706//
707//template<int fw> template <HOM_t m1, HOM_t m2>
708//inline SIMD_type simd<fw>::pack(SIMD_type r1, SIMD_type r2){
709//      return simd<fw>::pack(HOM<m1>::l2x<fw>, HOM<m2>::hom<fw>::hom(r2));
710//}
711//
712//template<int fw> template <HOM_t m1, HOM_t m2>
713//inline SIMD_type simd<fw>::mergeh(SIMD_type r1, SIMD_type r2){
714//      return simd<fw>::mergeh(HOM<m1>::hom<fw>, HOM<m2>::hom<fw>::hom(r2));
715//}
716//
717//template<int fw> template <HOM_t m1, HOM_t m2>
718//inline SIMD_type simd<fw>::mergel(SIMD_type r1, SIMD_type r2){
719//      return simd<fw>::mergel(HOM<m1>::hom<fw>, HOM<m2>::hom<fw>::hom(r2));
720//}
721 
722/* V.  sisd operations on full 128-bit register width. */
723
724//struct sisd {
725//      template <int shft> inline SIMD_type slli(SIMD_type r) {return simd<128>::slli<shft>(r);}
726//      template <int shft> inline SIMD_type srli(SIMD_type r) {return simd<128>::srli<shft>(r);}
727//      inline SIMD_type sll(SIMD_type r, SIMD_type shft) {return simd<128>::sll<shft>(r, shft);}
728//      inline SIMD_type srl(SIMD_type r, SIMD_type shft) {return simd<128>::srl<shft>(r, shft);}
729//};
730
731
732#define sisd_store_aligned(r, addr) _mm_store_si128(addr, r)
733#define sisd_store_unaligned(r, addr) _mm_storeu_si128(addr, r)
734#define sisd_load_aligned(addr) _mm_load_si128(addr)
735#ifndef USE_LDDQU
736#define sisd_load_unaligned(addr) _mm_loadu_si128(addr)
737#endif
738#ifdef USE_LDDQU
739#define sisd_load_unaligned(addr) _mm_lddqu_si128(addr)
740#endif
741
742
743#define bitblock_test_bit(blk, n) \
744   sisd_to_int(sisd_srli(sisd_slli(blk, ((BLOCKSIZE-1)-(n))), BLOCKSIZE-1))
745
746
747#if (BYTE_ORDER == BIG_ENDIAN)
748void print_bit_block(const char * var_name, SIMD_type v) {
749  union {SIMD_type vec; unsigned char elems[8];} x;
750  x.vec = v;
751  unsigned char c, bit_reversed;
752  int i;
753  printf("%30s = ", var_name);
754  for (i = 0; i < sizeof(SIMD_type); i++) {
755    c = x.elems[i];
756     printf("%02X ", c); 
757  }
758  printf("\n");
759}
760#endif
761
762#if (BYTE_ORDER == LITTLE_ENDIAN)
763void print_bit_block(const char * var_name, SIMD_type v) {
764  union {SIMD_type vec; unsigned char elems[8];} x;
765  x.vec = v;
766  unsigned char c, bit_reversed;
767  int i;
768  printf("%30s = ", var_name);
769  for (i = sizeof(SIMD_type)-1; i >= 0; i--) {
770    c = x.elems[i];
771     printf("%02X ", c); 
772  }
773  printf("\n");
774}
775#endif
776
777
778static inline int bitblock_has_bit(SIMD_type v) {
779  return !simd_all_true<8>(simd<8>::eq(v, simd<8>::constant<0>()));
780}
781
782static inline int bitblock_bit_count(SIMD_type v) {
783  int bit_count = 0;
784  SIMD_type cts_2 = simd<2>::add<l,h>(v, v);
785  SIMD_type cts_4 = simd<4>::add<l,h>(cts_2, cts_2);
786  SIMD_type cts_8 = simd<8>::add<l,h>(cts_4, cts_4);
787  SIMD_type cts_64 = _mm_sad_epu8(cts_8, simd<8>::constant<0>());
788  /* SIMD_type cts_128 = simd<a28>::add<l,h>(cts_64, cts_64) */;
789  SIMD_type cts_128 = simd<64>::add(cts_64, simd<128>::srli<64>(cts_64));
790  return (int) sisd_to_int(cts_128);
791}
792#endif
793
Note: See TracBrowser for help on using the repository browser.