source: trunk/lib/sse_simd_t.h @ 336

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

Widened name field in print_bit_block to 30 characters. Added 64 bit field SIMD equal function with SSE 41 support.

File size: 23.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#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/* Shift immediate operations with direct implementation by built-ins. */
198
199template<> template<int sh> inline SIMD_type simd<16>::slli(SIMD_type r) {return _mm_slli_epi16(r, sh);}
200
201template<> template<int sh> inline SIMD_type simd<32>::slli(SIMD_type r) {return _mm_slli_epi32(r, sh);}
202
203template<> template<int sh> inline SIMD_type simd<64>::slli(SIMD_type r) {return _mm_slli_epi64(r, sh);}
204
205template<> template<int sh> inline SIMD_type simd<16>::srli(SIMD_type r) {return _mm_srli_epi16(r, sh);}
206
207template<> template<int sh> inline SIMD_type simd<32>::srli(SIMD_type r) {return _mm_srli_epi32(r, sh);}
208
209template<> template<int sh> inline SIMD_type simd<64>::srli(SIMD_type r) {return _mm_srli_epi64(r, sh);}
210
211/* simd_srai
212 * fw: 16,32*/
213template<> template<int sh> inline SIMD_type simd<16>::srai(SIMD_type r) {return _mm_srai_epi16(r, sh);}
214
215template<> template<int sh> inline SIMD_type simd<32>::srai(SIMD_type r) {return _mm_srai_epi32(r, sh);}
216                 
217
218
219/* General rules for slli/srli for field widths 2, 4, 8 in terms of 32-bit shifts. */
220
221
222// Doesn't work:
223//template<int fw> template<int sh>
224//inline SIMD_type simd<fw>::slli(SIMD_type r) {
225//      return simd_and(simd<32>::slli<sh>(r), simd<fw>::constant<6>());
226//}
227//
228
229
230template<> template<int sh>
231inline SIMD_type simd<2>::slli(SIMD_type r) {
232        return simd_and(simd<32>::slli<sh>(r),simd<2>::constant<((3<<sh)&3)>());
233}
234
235template<> template<int sh>
236inline SIMD_type simd<4>::slli(SIMD_type r) {
237        return simd_and(simd<32>::slli<sh>(r),simd<4>::constant<((15<<sh)&15)>());
238}
239
240template<> template<int sh>
241inline SIMD_type simd<8>::slli(SIMD_type r) {
242        return simd_and(simd<32>::slli<sh>(r),simd<8>::constant<((255<<sh)&255)>());
243}
244
245
246//template<int fw> template<int sh>
247//inline SIMD_type simd<fw>::srli(SIMD_type r) {
248//      return simd_and(simd<32>::srli<sh>(r),simd<fw>::constant<((1<<(fw-sh))-1)>());
249//}
250//
251
252
253template<> template<int sh>
254inline SIMD_type simd<2>::srli(SIMD_type r) {
255        return simd_and(simd<32>::srli<sh>(r),simd<2>::constant<(3>>sh)>());
256}
257
258template<> template<int sh>
259inline SIMD_type simd<4>::srli(SIMD_type r) {
260        return simd_and(simd<32>::srli<sh>(r),simd<4>::constant<(15>>sh)>());
261}
262
263template<> template<int sh>
264inline SIMD_type simd<8>::srli(SIMD_type r) {
265        return simd_and(simd<32>::srli<sh>(r),simd<8>::constant<(255>>sh)>());
266}
267
268
269
270
271/* Shift immediate for 128-bit fields */
272
273template<> template<int shft>
274inline SIMD_type simd<128>::slli(SIMD_type r) {
275        return (shft % 8 == 0 ? _mm_slli_si128(r, shft/8) :
276                shft >= 64 ? simd<64>::slli<shft-64>(_mm_slli_si128(r, 8)) :
277                simd_or(simd<64>::slli<shft>(r), _mm_slli_si128(simd<64>::srli<64-shft>(r), 8)));
278}
279
280template<> template<int shft>
281inline SIMD_type simd<128>::srli(SIMD_type r) {
282        return (shft % 8 == 0 ? _mm_srli_si128(r, shft/8) :
283                shft >= 64 ? simd<64>::srli<shft-64>(_mm_srli_si128(r, 8)) :
284                simd_or(simd<64>::srli<shft>(r), _mm_srli_si128(simd<64>::slli<64-shft>(r), 8)));
285}
286
287
288/* Shifts with shift values specified in an operand register. */
289
290template<>
291inline SIMD_type simd<128>::srl(SIMD_type r, SIMD_type shft) {
292        return simd_or(_mm_srl_epi64(r, shft),
293                       simd_or(_mm_srli_si128(_mm_srl_epi64(r, _mm_sub_epi32(shft, sisd_from_int(64))), 8),
294                               _mm_srli_si128(_mm_sll_epi64(r, _mm_sub_epi32(sisd_from_int(64), shft)), 8)));
295}
296
297template<>
298inline SIMD_type simd<128>::sll(SIMD_type r, SIMD_type shft) {
299        return simd_or(_mm_sll_epi64(r, shft),
300                       simd_or(_mm_slli_si128(_mm_sll_epi64(r, _mm_sub_epi32(shft, sisd_from_int(64))), 8),
301                               _mm_slli_si128(_mm_srl_epi64(r, _mm_sub_epi32(sisd_from_int(64), shft)), 8)));
302}
303
304template<>
305inline SIMD_type simd<64>::srl(SIMD_type r, SIMD_type shft) {
306        return simd_if(simd<128>::himask(),
307                       _mm_srl_epi64(r, _mm_srli_si128(shft, 8)),
308                       _mm_srl_epi64(r, simd_andc(shft, simd<128>::himask())));
309}
310
311template<>
312inline SIMD_type simd<64>::sll(SIMD_type r, SIMD_type shft) {
313        return simd_if(simd<128>::himask(),
314                       _mm_sll_epi64(r, _mm_srli_si128(shft, 8)),
315                       _mm_sll_epi64(r, simd_andc(shft, simd<128>::himask())));
316}
317
318
319/* simd_add
320 * fw: 2,4,8,16,32,64
321
322   Use built-ins for 8, 16, 32, 64, simulations for 2, 4. */
323
324template<> inline SIMD_type simd<8>::add(SIMD_type r1, SIMD_type r2) {return _mm_add_epi8(r1, r2);}
325
326template<> inline SIMD_type simd<16>::add(SIMD_type r1, SIMD_type r2) {return _mm_add_epi16(r1, r2);}
327
328template<> inline SIMD_type simd<32>::add(SIMD_type r1, SIMD_type r2) {return _mm_add_epi32(r1, r2);}
329
330template<> inline SIMD_type simd<64>::add(SIMD_type r1, SIMD_type r2) {return _mm_add_epi64(r1, r2);}
331
332template<>
333inline SIMD_type simd<2>::add(SIMD_type r1, SIMD_type r2) {
334         SIMD_type c1 = simd_xor(r1,r2);
335         SIMD_type borrow = simd_and(r1,r2);
336         SIMD_type c2 = simd_xor(c1,(simd<128>::slli<1>(borrow)));
337         return simd_if(simd<2>::himask(),c2,c1);
338}
339
340template<>
341SIMD_type simd<4>::add(SIMD_type r1, SIMD_type r2) {
342        return simd_if(simd<8>::himask(), 
343                       simd<8>::add(r1,simd_and(r2,simd<8>::himask())),
344                       simd<8>::add(r1, r2));
345}
346
347/* simd_sub
348 * fw: 2,4,8,16,32,64
349
350   Use built-ins for 8, 16, 32, 64, simulations for 2, 4. */
351
352template<> inline SIMD_type simd<8>::sub(SIMD_type r1, SIMD_type r2) {return _mm_sub_epi8(r1, r2);}
353
354template<> inline SIMD_type simd<16>::sub(SIMD_type r1, SIMD_type r2) {return _mm_sub_epi16(r1, r2);}
355
356template<> inline SIMD_type simd<32>::sub(SIMD_type r1, SIMD_type r2) {return _mm_sub_epi32(r1, r2);}
357
358template<> inline SIMD_type simd<64>::sub(SIMD_type r1, SIMD_type r2) {return _mm_sub_epi64(r1, r2);}
359
360
361template<>
362inline SIMD_type simd<2>::sub(SIMD_type r1, SIMD_type r2)
363{
364         SIMD_type c1 = simd_xor(r1,r2);
365         SIMD_type borrow = simd_andc(r2,r1);
366         SIMD_type c2 = simd_xor(c1,(simd<128>::slli<1>(borrow)));
367         return simd_if(simd<2>::himask(),c2,c1);
368}
369
370template<>
371inline SIMD_type simd<4>::sub(SIMD_type r1, SIMD_type r2){
372        return simd_if(simd<8>::himask(), 
373                       simd<8>::sub(r1, simd_and(r2,simd<8>::himask())),
374                       simd<8>::sub(r1, r2));
375}
376
377/* simd_mult built-in for 16 bits only. */
378
379template<> inline SIMD_type simd<16>::mult(SIMD_type r1, SIMD_type r2) {return _mm_mullo_epi16(r1, r2);}
380
381
382/* _mm_mul_epu2 is equivalent of simd<64>::mult<l,l>*/
383template<> inline SIMD_type simd<32>::mult(SIMD_type r1, SIMD_type r2) {
384        return simd_or(_mm_mul_epu32(r1, r2),
385                       simd::slli<32>(_mm_mul_epu32(simd::srli<32>(r1), simd::srli<32>(r2))));
386}
387
388
389template<>
390inline SIMD_type simd<8>::mult(SIMD_type r1, SIMD_type r2){
391        return simd_or(simd<16>::mult<h,x>(r1, simd_and(simd<16>::himask(), r2)),
392                       simd<16>::mult<l,l>(r1, r2));
393}
394
395
396
397
398
399/* simd_max for 8 bits only. */
400
401template<> inline SIMD_type simd<8>::max(SIMD_type r1, SIMD_type r2) {return _mm_max_epu8(r1, r2);}
402
403
404/* simd_eq
405 * fw: 8,16,32*/
406
407template<> inline SIMD_type simd<8>::eq(SIMD_type r1, SIMD_type r2) {return _mm_cmpeq_epi8(r1, r2);}
408
409template<> inline SIMD_type simd<16>::eq(SIMD_type r1, SIMD_type r2) {return _mm_cmpeq_epi16(r1, r2);}
410
411template<> inline SIMD_type simd<32>::eq(SIMD_type r1, SIMD_type r2) {return _mm_cmpeq_epi32(r1, r2);}
412
413template<> inline SIMD_type simd<64>::eq(SIMD_type r1, SIMD_type r2) {
414
415#ifdef __SSE4_1__
416  return _mm_cmpeq_epi64(r1, r2);
417#else
418  SIMD_type t = _mm_cmpeq_epi32(r1, r2);
419  return simd_and(t, _mm_shuffle_epi32(t,_MM_SHUFFLE(2,3,0,1)));
420#endif
421
422}
423
424/*simd_pack
425 * fw: 2,4,8,16*/
426
427/* Built-in operation for fw = 16. */
428template<>
429inline SIMD_type simd<16>::pack(SIMD_type r1, SIMD_type r2) {
430        return _mm_packus_epi16(simd_andc(r2, simd<16>::himask()), simd_andc(r1, simd<16>::himask()));
431}
432
433/* fw: 2, 4, 8 */
434template<int fw>
435inline SIMD_type simd<fw>::pack(SIMD_type r1, SIMD_type r2){
436        return simd<fw*2>::pack(simd_if(simd<fw>::himask(),simd<128>::srli<fw/2>(r1),r1),
437                                simd_if(simd<fw>::himask(),simd<128>::srli<fw/2>(r2),r2));
438}
439
440/* simd_mergeh
441 * fw: 1,2,4,8,16,32,64*/
442template<int fw>
443inline SIMD_type simd<fw>::mergeh(SIMD_type r1, SIMD_type r2){
444        /*fw: 1,2,4*/
445        return simd<fw*2>::mergeh(simd_if(simd<fw*2>::himask(),r1,simd<fw*2>::srli<fw>(r2)),
446                                  simd_if(simd<fw*2>::himask(),simd<fw*2>::slli<fw>(r1),r2));
447}
448
449template<> inline SIMD_type simd<8>::mergeh(SIMD_type r1, SIMD_type r2) {return _mm_unpackhi_epi8(r2, r1);}
450template<> inline SIMD_type simd<16>::mergeh(SIMD_type r1, SIMD_type r2) {return _mm_unpackhi_epi16(r2, r1);}
451template<> inline SIMD_type simd<32>::mergeh(SIMD_type r1, SIMD_type r2) {return _mm_unpackhi_epi32(r2, r1);}
452template<> inline SIMD_type simd<64>::mergeh(SIMD_type r1, SIMD_type r2) {return _mm_unpackhi_epi64(r2, r1);}
453
454
455/* simd_mergel
456 * fw: 1,2,4,8,16,32,64*/
457template<int fw>
458inline SIMD_type simd<fw>::mergel(SIMD_type r1, SIMD_type r2){
459        /*fw: 1,2,4*/
460        return simd<fw*2>::mergel(simd_if(simd<fw*2>::himask(),r1,simd<fw*2>::srli<fw>(r2)),
461                                  simd_if(simd<fw*2>::himask(),simd<fw*2>::slli<fw>(r1),r2));
462}
463
464template<> inline SIMD_type simd<8>::mergel(SIMD_type r1, SIMD_type r2) {return _mm_unpacklo_epi8(r2, r1);}
465template<> inline SIMD_type simd<16>::mergel(SIMD_type r1, SIMD_type r2) {return _mm_unpacklo_epi16(r2, r1);}
466template<> inline SIMD_type simd<32>::mergel(SIMD_type r1, SIMD_type r2) {return _mm_unpacklo_epi32(r2, r1);}
467template<> inline SIMD_type simd<64>::mergel(SIMD_type r1, SIMD_type r2) {return _mm_unpacklo_epi64(r2, r1);}
468
469
470#define simd_all_eq_8(v1, v2) simd_all_true<8>(_mm_cmpeq_epi8(v1, v2))
471#define simd_mask_eq_8(v1, v2, hex_mask) simd_mask_true<8>(_mm_cmpeq_epi8(v1, v2), hex_mask)
472#define simd_all_le_8(v1, v2) simd_all_eq_8(simd_max_8(v1, v2), v2)
473
474#define simd_all_signed_gt_8(v1, v2) simd_all_true_8(_mm_cmpgt_epi8(v1, v2))
475
476#define simd_cmpgt_8(v1,v2) _mm_cmpgt_epi8(v1, v2)
477
478
479
480/* simd_all_true
481 * fw: 8*/
482template<int fw>
483static inline int simd_all_true(SIMD_type r);
484template<>
485inline int simd_all_true<8>(SIMD_type r) {
486        return _mm_movemask_epi8(r) == 0xFFFF;
487}
488
489/* simd_any_true
490 * fw: 8*/
491template<int fw>
492static inline int simd_any_true(SIMD_type r);
493template<>
494inline int simd_any_true<8>(SIMD_type r) {
495        return _mm_movemask_epi8(r) != 0;
496}
497
498/* simd_mask_true
499 * fw: 8*/
500template<int fw>
501static inline int simd_mask_true(SIMD_type v, int mask_16_bit) {
502        return (_mm_movemask_epi8(v) & mask_16_bit) == mask_16_bit;
503}
504
505/* simd_any_sign_bit
506 * fw: 8*/
507template<int fw>
508static inline int simd_any_sign_bit(SIMD_type r);
509template<>
510inline int simd_any_sign_bit<8>(SIMD_type r) {
511        return _mm_movemask_epi8(r) != 0;
512}
513
514
515
516/* IV.  Half operand modifiers - implementations. */
517/* Half operand modifier functions.*/
518
519template <int fw, HOM_t m>
520struct SIMD {
521        static inline SIMD_type hom(SIMD_type r) {}
522};
523
524template <int fw>
525struct SIMD<fw, x> {
526        static inline SIMD_type hom(SIMD_type r) {return r;}
527        static inline SIMD_type l2x(SIMD_type r) {return r;}
528};
529
530template <int fw>
531struct SIMD<fw, l> {
532        static inline SIMD_type hom(SIMD_type r) {return simd_andc(r, simd<fw>::himask());}
533        static inline SIMD_type l2x(SIMD_type r) {return r;}
534};
535
536// Wish we could make this generic.
537//template <int fw>
538//struct SIMD<fw, h> {
539//      static inline SIMD_type hom(SIMD_type r) {return simd<fw>::srli<fw/2>(r);}
540//      static inline SIMD_type l2x(SIMD_type r) {return simd<fw>::srli<fw/2>(r);}
541//};
542//
543template <>
544struct SIMD<2, h> {
545        static inline SIMD_type hom(SIMD_type r) {return simd<2>::srli<1>(r);}
546        static inline SIMD_type l2x(SIMD_type r) {return simd<2>::srli<1>(r);}
547};
548
549template <>
550struct SIMD<4, h> {
551        static inline SIMD_type hom(SIMD_type r) {return simd<4>::srli<2>(r);}
552        static inline SIMD_type l2x(SIMD_type r) {return simd<4>::srli<2>(r);}
553};
554
555template <>
556struct SIMD<8, h> {
557        static inline SIMD_type hom(SIMD_type r) {return simd<8>::srli<4>(r);}
558        static inline SIMD_type l2x(SIMD_type r) {return simd<8>::srli<4>(r);}
559};
560
561template <>
562struct SIMD<16, h> {
563        static inline SIMD_type hom(SIMD_type r) {return simd<16>::srli<8>(r);}
564        static inline SIMD_type l2x(SIMD_type r) {return simd<16>::srli<8>(r);}
565};
566
567template <>
568struct SIMD<32, h> {
569        static inline SIMD_type hom(SIMD_type r) {return simd<32>::srli<16>(r);}
570        static inline SIMD_type l2x(SIMD_type r) {return simd<32>::srli<16>(r);}
571};
572
573
574/* SIMD operations extended with HOM*/
575template<int fw> template <HOM_t m1, HOM_t m2>
576inline SIMD_type simd<fw>::add(SIMD_type r1, SIMD_type r2){
577        return simd<fw>::add(SIMD<fw,m1>::hom(r1),SIMD<fw,m2>::hom(r2));
578}
579
580template<int fw> template <HOM_t m1, HOM_t m2>
581inline SIMD_type simd<fw>::sub(SIMD_type r1, SIMD_type r2){
582        return simd<fw>::sub(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>::pack(SIMD_type r1, SIMD_type r2){
587        return simd<fw>::pack(SIMD<fw,m1>::l2x(r1),SIMD<fw,m2>::l2x(r2));
588}
589
590template<int fw> template <HOM_t m1, HOM_t m2>
591inline SIMD_type simd<fw>::mergeh(SIMD_type r1, SIMD_type r2){
592        return simd<fw>::mergeh(SIMD<fw,m1>::hom(r1),SIMD<fw,m2>::hom(r2));
593}
594
595template<int fw> template <HOM_t m1, HOM_t m2>
596inline SIMD_type simd<fw>::mergel(SIMD_type r1, SIMD_type r2){
597        return simd<fw>::mergel(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>::mult(SIMD_type r1, SIMD_type r2){
602        return simd<fw>::mult(SIMD<fw,m1>::hom(r1),SIMD<fw,m2>::hom(r2));
603}
604
605
606//
607//template <HOM_t m>
608//struct HOM {
609//template<int fw> SIMD_type hom(SIMD_type r) {return r;}
610//template<int fw> SIMD_type l2x(SIMD_type r) {return r;}
611//};
612//
613//template <>
614//template <int fw>
615//SIMD_type HOM<l>::hom(SIMD_type r) {return simd_andc(r, simd<fw>::himask());}
616//
617//template <>
618//template <int fw>
619//SIMD_type HOM<h>::hom(SIMD_type r) {return simd<fw>::srli<fw/2>(r);}
620//
621//template <>
622//template <int fw>
623//SIMD_type HOM<h>::l2x(SIMD_type r) {return simd<fw>::srli<fw/2>(r);}
624//
625//
626///* SIMD operations extended with Half-Operand Modifiers */
627//
628//template<int fw> template <HOM_t m1, HOM_t m2>
629//inline SIMD_type simd<fw>::add(SIMD_type r1, SIMD_type r2){
630//      return simd<fw>::add(HOM<m1>::hom<fw>, HOM<m2>::hom<fw>(r2));
631//}
632//
633//template<int fw> template <HOM_t m1, HOM_t m2>
634//inline SIMD_type simd<fw>::sub(SIMD_type r1, SIMD_type r2){
635//      return simd<fw>::sub(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>::mult(SIMD_type r1, SIMD_type r2){
640//      return simd<fw>::mult(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>::pack(SIMD_type r1, SIMD_type r2){
645//      return simd<fw>::pack(HOM<m1>::l2x<fw>, HOM<m2>::hom<fw>::hom(r2));
646//}
647//
648//template<int fw> template <HOM_t m1, HOM_t m2>
649//inline SIMD_type simd<fw>::mergeh(SIMD_type r1, SIMD_type r2){
650//      return simd<fw>::mergeh(HOM<m1>::hom<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>::mergel(SIMD_type r1, SIMD_type r2){
655//      return simd<fw>::mergel(HOM<m1>::hom<fw>, HOM<m2>::hom<fw>::hom(r2));
656//}
657 
658/* V.  sisd operations on full 128-bit register width. */
659
660//struct sisd {
661//      template <int shft> inline SIMD_type slli(SIMD_type r) {return simd<128>::slli<shft>(r);}
662//      template <int shft> inline SIMD_type srli(SIMD_type r) {return simd<128>::srli<shft>(r);}
663//      inline SIMD_type sll(SIMD_type r, SIMD_type shft) {return simd<128>::sll<shft>(r, shft);}
664//      inline SIMD_type srl(SIMD_type r, SIMD_type shft) {return simd<128>::srl<shft>(r, shft);}
665//};
666
667
668#define sisd_store_aligned(r, addr) _mm_store_si128(addr, r)
669#define sisd_store_unaligned(r, addr) _mm_storeu_si128(addr, r)
670#define sisd_load_aligned(addr) _mm_load_si128(addr)
671#ifndef USE_LDDQU
672#define sisd_load_unaligned(addr) _mm_loadu_si128(addr)
673#endif
674#ifdef USE_LDDQU
675#define sisd_load_unaligned(addr) _mm_lddqu_si128(addr)
676#endif
677
678
679#define bitblock_test_bit(blk, n) \
680   sisd_to_int(sisd_srli(sisd_slli(blk, ((BLOCKSIZE-1)-(n))), BLOCKSIZE-1))
681
682
683#if (BYTE_ORDER == BIG_ENDIAN)
684void print_bit_block(const char * var_name, SIMD_type v) {
685  union {SIMD_type vec; unsigned char elems[8];} x;
686  x.vec = v;
687  unsigned char c, bit_reversed;
688  int i;
689  printf("%30s = ", var_name);
690  for (i = 0; i < sizeof(SIMD_type); i++) {
691    c = x.elems[i];
692     printf("%02X ", c); 
693  }
694  printf("\n");
695}
696#endif
697
698#if (BYTE_ORDER == LITTLE_ENDIAN)
699void print_bit_block(const char * var_name, SIMD_type v) {
700  union {SIMD_type vec; unsigned char elems[8];} x;
701  x.vec = v;
702  unsigned char c, bit_reversed;
703  int i;
704  printf("%30s = ", var_name);
705  for (i = sizeof(SIMD_type)-1; i >= 0; i--) {
706    c = x.elems[i];
707     printf("%02X ", c); 
708  }
709  printf("\n");
710}
711#endif
712
713
714static inline int bitblock_has_bit(SIMD_type v) {
715  return !simd_all_true<8>(simd<8>::eq(v, simd<8>::constant<0>()));
716}
717
718static inline int bitblock_bit_count(SIMD_type v) {
719  int bit_count = 0;
720  SIMD_type cts_2 = simd<2>::add<l,h>(v, v);
721  SIMD_type cts_4 = simd<4>::add<l,h>(cts_2, cts_2);
722  SIMD_type cts_8 = simd<8>::add<l,h>(cts_4, cts_4);
723  SIMD_type cts_64 = _mm_sad_epu8(cts_8, simd<8>::constant<0>());
724  /* SIMD_type cts_128 = simd<a28>::add<l,h>(cts_64, cts_64) */;
725  SIMD_type cts_128 = simd<64>::add(cts_64, simd<128>::srli<64>(cts_64));
726  return (int) sisd_to_int(cts_128);
727}
728#endif
729
Note: See TracBrowser for help on using the repository browser.