source: trunk/lib/sse_simd_t.h @ 328

Last change on this file since 328 was 328, checked in by cameron, 10 years ago

Add simd<8>::mult, simd<32>::mult

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