source: trunk/lib/sse_simd_t.h @ 337

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

Add a 64 bit splat method.

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