/xmlbench/trunk

To get this branch, use:
bzr branch http://darksoft.org/webbzr/xmlbench/trunk

« back to all changes in this revision

Viewing changes to parse/parabix.20090211/lib/sse_simd_t.h

  • Committer: Suren A. Chilingaryan
  • Date: 2009-09-23 17:13:04 UTC
  • Revision ID: csa@dside.dyndns.org-20090923171304-osvtr4zqb29h11kd
Intel, Tango, Phobos, and RapidXML parsers; Memory benchmark scripts

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*  Idealized SIMD Operations with SSE versions
2
 
    Copyright (C) 2006, 2007, 2008, 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
28
 
typedef __m128i SIMD_type;
29
 
/*------------------------------------------------------------*/
30
 
/* I. SIMD bitwise logical operations */
31
 
 
32
 
static inline SIMD_type simd_and(SIMD_type b1, SIMD_type b2) {
33
 
        return _mm_and_si128(b1, b2);
34
 
}
35
 
static inline SIMD_type simd_andc(SIMD_type b1, SIMD_type b2) {
36
 
        return _mm_andnot_si128(b2, b1);
37
 
}
38
 
static inline SIMD_type simd_or(SIMD_type b1, SIMD_type b2) {
39
 
        return  _mm_or_si128(b1, b2);
40
 
}
41
 
static inline SIMD_type simd_xor(SIMD_type b1, SIMD_type b2) {
42
 
        return  _mm_xor_si128(b1, b2);
43
 
}
44
 
static inline SIMD_type simd_not(SIMD_type b) {
45
 
        return  simd_xor(b, _mm_set1_epi32(0xFFFFFFFF));
46
 
}
47
 
static inline SIMD_type simd_nor(SIMD_type b1, SIMD_type b2) {
48
 
        return  simd_not(simd_or(b1,b2));
49
 
}
50
 
static 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
 
 
63
 
enum HOM_t {x,h,l};
64
 
 
65
 
/* simd<fw> is a template struct providing all the simd operations
66
 
 * for a given field width.  */
67
 
template <int fw>
68
 
struct 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
 
 
124
 
template<> inline SIMD_type simd<2>::himask() {return _mm_set1_epi8(0xAA);}
125
 
 
126
 
template<> inline SIMD_type simd<4>::himask() {return _mm_set1_epi8(0xCC);}
127
 
 
128
 
template<> inline SIMD_type simd<8>::himask() {return _mm_set1_epi8(0xF0);}
129
 
 
130
 
template<> inline SIMD_type simd<16>::himask() {return _mm_set1_epi16(0xFF00);}
131
 
 
132
 
template<> inline SIMD_type simd<32>::himask() {return _mm_set1_epi32(0xFFFF0000);}
133
 
 
134
 
template<> inline SIMD_type simd<64>::himask() {return _mm_set_epi32(-1,0,-1,0);}
135
 
 
136
 
template<> inline SIMD_type simd<128>::himask() {return _mm_set_epi32(-1,-1,0,0);}
137
 
 
138
 
template<> template <int n> inline SIMD_type simd<4>::constant() {return _mm_set1_epi8((n)<<4|(n));}
139
 
 
140
 
template<> template <int n> inline SIMD_type simd<8>::constant() {return _mm_set1_epi8(n);}
141
 
 
142
 
template<> template <int n> inline SIMD_type simd<16>::constant() {return _mm_set1_epi16(n);}
143
 
 
144
 
template<> template <int n> inline SIMD_type simd<32>::constant() {return _mm_set1_epi32(n);}
145
 
 
146
 
template<> template <> inline SIMD_type simd<1>::constant<0>() {return simd<8>::constant<0>();}
147
 
template<> template <> inline SIMD_type simd<1>::constant<1>() {return simd<8>::constant<-1>();}
148
 
 
149
 
template<> 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.
152
 
template <> 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.
158
 
template <> 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
 
 
164
 
template<> template<int sh> inline SIMD_type simd<16>::slli(SIMD_type r) {return _mm_slli_epi16(r, sh);}
165
 
 
166
 
template<> template<int sh> inline SIMD_type simd<32>::slli(SIMD_type r) {return _mm_slli_epi32(r, sh);}
167
 
 
168
 
template<> template<int sh> inline SIMD_type simd<64>::slli(SIMD_type r) {return _mm_slli_epi64(r, sh);}
169
 
 
170
 
template<> template<int sh> inline SIMD_type simd<16>::srli(SIMD_type r) {return _mm_srli_epi16(r, sh);}
171
 
 
172
 
template<> template<int sh> inline SIMD_type simd<32>::srli(SIMD_type r) {return _mm_srli_epi32(r, sh);}
173
 
 
174
 
template<> 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*/
178
 
template<> template<int sh> inline SIMD_type simd<16>::srai(SIMD_type r) {return _mm_srai_epi16(r, sh);}
179
 
 
180
 
template<> 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
 
 
195
 
template<> template<int sh>
196
 
inline 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
 
 
200
 
template<> template<int sh>
201
 
inline 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
 
 
205
 
template<> template<int sh>
206
 
inline 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
 
 
218
 
template<> template<int sh>
219
 
inline SIMD_type simd<2>::srli(SIMD_type r) {
220
 
        return simd_and(simd<32>::srli<sh>(r),simd<2>::constant<(3>>sh)>());
221
 
}
222
 
 
223
 
template<> template<int sh>
224
 
inline SIMD_type simd<4>::srli(SIMD_type r) {
225
 
        return simd_and(simd<32>::srli<sh>(r),simd<4>::constant<(15>>sh)>());
226
 
}
227
 
 
228
 
template<> template<int sh>
229
 
inline 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
 
 
238
 
template<> template<int shft>
239
 
inline 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
 
 
245
 
template<> template<int shft>
246
 
inline 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
 
 
255
 
template<>
256
 
inline 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
 
 
262
 
template<>
263
 
inline 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
 
 
269
 
template<>
270
 
inline 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
 
 
276
 
template<>
277
 
inline 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
 
 
289
 
template<> inline SIMD_type simd<8>::add(SIMD_type r1, SIMD_type r2) {return _mm_add_epi8(r1, r2);}
290
 
 
291
 
template<> inline SIMD_type simd<16>::add(SIMD_type r1, SIMD_type r2) {return _mm_add_epi16(r1, r2);}
292
 
 
293
 
template<> inline SIMD_type simd<32>::add(SIMD_type r1, SIMD_type r2) {return _mm_add_epi32(r1, r2);}
294
 
 
295
 
template<> inline SIMD_type simd<64>::add(SIMD_type r1, SIMD_type r2) {return _mm_add_epi64(r1, r2);}
296
 
 
297
 
template<>
298
 
inline 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
 
 
305
 
template<>
306
 
SIMD_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
 
 
317
 
template<> inline SIMD_type simd<8>::sub(SIMD_type r1, SIMD_type r2) {return _mm_sub_epi8(r1, r2);}
318
 
 
319
 
template<> inline SIMD_type simd<16>::sub(SIMD_type r1, SIMD_type r2) {return _mm_sub_epi16(r1, r2);}
320
 
 
321
 
template<> inline SIMD_type simd<32>::sub(SIMD_type r1, SIMD_type r2) {return _mm_sub_epi32(r1, r2);}
322
 
 
323
 
template<> inline SIMD_type simd<64>::sub(SIMD_type r1, SIMD_type r2) {return _mm_sub_epi64(r1, r2);}
324
 
 
325
 
 
326
 
template<>
327
 
inline 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
 
 
335
 
template<>
336
 
inline 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 for 16 bits only. */
343
 
 
344
 
template<> inline SIMD_type simd<16>::mult(SIMD_type r1, SIMD_type r2) {return _mm_mullo_epi16(r1, r2);}
345
 
 
346
 
/* simd_max for 8 bits only. */
347
 
 
348
 
template<> inline SIMD_type simd<8>::max(SIMD_type r1, SIMD_type r2) {return _mm_max_epu8(r1, r2);}
349
 
 
350
 
 
351
 
/* simd_eq
352
 
 * fw: 8,16,32*/
353
 
 
354
 
template<> inline SIMD_type simd<8>::eq(SIMD_type r1, SIMD_type r2) {return _mm_cmpeq_epi8(r1, r2);}
355
 
 
356
 
template<> inline SIMD_type simd<16>::eq(SIMD_type r1, SIMD_type r2) {return _mm_cmpeq_epi16(r1, r2);}
357
 
 
358
 
template<> inline SIMD_type simd<32>::eq(SIMD_type r1, SIMD_type r2) {return _mm_cmpeq_epi32(r1, r2);}
359
 
 
360
 
 
361
 
 
362
 
/*simd_pack
363
 
 * fw: 2,4,8,16*/
364
 
 
365
 
/* Built-in operation for fw = 16. */
366
 
template<>
367
 
inline SIMD_type simd<16>::pack(SIMD_type r1, SIMD_type r2) {
368
 
        return _mm_packus_epi16(simd_andc(r2, simd<16>::himask()), simd_andc(r1, simd<16>::himask()));
369
 
}
370
 
 
371
 
/* fw: 2, 4, 8 */
372
 
template<int fw>
373
 
inline SIMD_type simd<fw>::pack(SIMD_type r1, SIMD_type r2){
374
 
        return simd<fw*2>::pack(simd_if(simd<fw>::himask(),simd<128>::srli<fw/2>(r1),r1),
375
 
                                simd_if(simd<fw>::himask(),simd<128>::srli<fw/2>(r2),r2));
376
 
}
377
 
 
378
 
/* simd_mergeh
379
 
 * fw: 1,2,4,8,16,32,64*/
380
 
template<int fw>
381
 
inline SIMD_type simd<fw>::mergeh(SIMD_type r1, SIMD_type r2){
382
 
        /*fw: 1,2,4*/
383
 
        return simd<fw*2>::mergeh(simd_if(simd<fw*2>::himask(),r1,simd<fw*2>::srli<fw>(r2)),
384
 
                                  simd_if(simd<fw*2>::himask(),simd<fw*2>::slli<fw>(r1),r2));
385
 
}
386
 
 
387
 
template<> inline SIMD_type simd<8>::mergeh(SIMD_type r1, SIMD_type r2) {return _mm_unpackhi_epi8(r2, r1);}
388
 
template<> inline SIMD_type simd<16>::mergeh(SIMD_type r1, SIMD_type r2) {return _mm_unpackhi_epi16(r2, r1);}
389
 
template<> inline SIMD_type simd<32>::mergeh(SIMD_type r1, SIMD_type r2) {return _mm_unpackhi_epi32(r2, r1);}
390
 
template<> inline SIMD_type simd<64>::mergeh(SIMD_type r1, SIMD_type r2) {return _mm_unpackhi_epi64(r2, r1);}
391
 
 
392
 
 
393
 
/* simd_mergel
394
 
 * fw: 1,2,4,8,16,32,64*/
395
 
template<int fw>
396
 
inline SIMD_type simd<fw>::mergel(SIMD_type r1, SIMD_type r2){
397
 
        /*fw: 1,2,4*/
398
 
        return simd<fw*2>::mergel(simd_if(simd<fw*2>::himask(),r1,simd<fw*2>::srli<fw>(r2)),
399
 
                                  simd_if(simd<fw*2>::himask(),simd<fw*2>::slli<fw>(r1),r2));
400
 
}
401
 
 
402
 
template<> inline SIMD_type simd<8>::mergel(SIMD_type r1, SIMD_type r2) {return _mm_unpacklo_epi8(r2, r1);}
403
 
template<> inline SIMD_type simd<16>::mergel(SIMD_type r1, SIMD_type r2) {return _mm_unpacklo_epi16(r2, r1);}
404
 
template<> inline SIMD_type simd<32>::mergel(SIMD_type r1, SIMD_type r2) {return _mm_unpacklo_epi32(r2, r1);}
405
 
template<> inline SIMD_type simd<64>::mergel(SIMD_type r1, SIMD_type r2) {return _mm_unpacklo_epi64(r2, r1);}
406
 
 
407
 
 
408
 
 
409
 
 
410
 
 
411
 
#define simd_all_eq_8(v1, v2) simd_all_true<8>(_mm_cmpeq_epi8(v1, v2))
412
 
#define simd_all_le_8(v1, v2) simd_all_eq_8(simd_max_8(v1, v2), v2)
413
 
 
414
 
#define simd_all_signed_gt_8(v1, v2) simd_all_true_8(_mm_cmpgt_epi8(v1, v2))
415
 
 
416
 
#define simd_cmpgt_8(v1,v2) _mm_cmpgt_epi8(v1, v2)
417
 
 
418
 
 
419
 
 
420
 
/* simd_all_true
421
 
 * fw: 8*/
422
 
template<int fw>
423
 
static inline int simd_all_true(SIMD_type r);
424
 
template<>
425
 
static inline int simd_all_true<8>(SIMD_type r) {
426
 
        return _mm_movemask_epi8(r) == 0xFFFF;
427
 
}
428
 
 
429
 
/* simd_any_true
430
 
 * fw: 8*/
431
 
template<int fw>
432
 
static inline int simd_any_true(SIMD_type r);
433
 
template<>
434
 
static inline int simd_any_true<8>(SIMD_type r) {
435
 
        return _mm_movemask_epi8(r) != 0;
436
 
}
437
 
 
438
 
/* simd_any_sign_bit
439
 
 * fw: 8*/
440
 
template<int fw>
441
 
static inline int simd_any_sign_bit(SIMD_type r);
442
 
template<>
443
 
static inline int simd_any_sign_bit<8>(SIMD_type r) {
444
 
        return _mm_movemask_epi8(r) != 0;
445
 
}
446
 
 
447
 
 
448
 
 
449
 
/* IV.  Half operand modifiers - implementations. */
450
 
/* Half operand modifier functions.*/
451
 
 
452
 
/* Half operand modifier*/
453
 
/* Half operand modifier*/
454
 
template <int fw, HOM_t m>
455
 
struct SIMD {
456
 
        static inline SIMD_type hom(SIMD_type r) {}
457
 
};
458
 
 
459
 
template <int fw>
460
 
struct SIMD<fw, x> {
461
 
        static inline SIMD_type hom(SIMD_type r) {return r;}
462
 
        static inline SIMD_type l2x(SIMD_type r) {return r;}
463
 
};
464
 
 
465
 
template <int fw>
466
 
struct SIMD<fw, l> {
467
 
        static inline SIMD_type hom(SIMD_type r) {return simd_andc(r, simd<fw>::himask());}
468
 
        static inline SIMD_type l2x(SIMD_type r) {return r;}
469
 
};
470
 
 
471
 
//template <int fw>
472
 
//struct SIMD<fw, h> {
473
 
//      static inline SIMD_type hom(SIMD_type r) {return simd<fw>::srli<fw/2>(r);}
474
 
//      static inline SIMD_type l2x(SIMD_type r) {return simd<fw>::srli<fw/2>(r);}
475
 
//};
476
 
//
477
 
template <>
478
 
struct SIMD<2, h> {
479
 
        static inline SIMD_type hom(SIMD_type r) {return simd<2>::srli<1>(r);}
480
 
        static inline SIMD_type l2x(SIMD_type r) {return simd<2>::srli<1>(r);}
481
 
};
482
 
 
483
 
template <>
484
 
struct SIMD<4, h> {
485
 
        static inline SIMD_type hom(SIMD_type r) {return simd<4>::srli<2>(r);}
486
 
        static inline SIMD_type l2x(SIMD_type r) {return simd<4>::srli<2>(r);}
487
 
};
488
 
 
489
 
template <>
490
 
struct SIMD<8, h> {
491
 
        static inline SIMD_type hom(SIMD_type r) {return simd<8>::srli<4>(r);}
492
 
        static inline SIMD_type l2x(SIMD_type r) {return simd<8>::srli<4>(r);}
493
 
};
494
 
 
495
 
template <>
496
 
struct SIMD<16, h> {
497
 
        static inline SIMD_type hom(SIMD_type r) {return simd<16>::srli<8>(r);}
498
 
        static inline SIMD_type l2x(SIMD_type r) {return simd<16>::srli<8>(r);}
499
 
};
500
 
 
501
 
template <>
502
 
struct SIMD<32, h> {
503
 
        static inline SIMD_type hom(SIMD_type r) {return simd<32>::srli<16>(r);}
504
 
        static inline SIMD_type l2x(SIMD_type r) {return simd<32>::srli<16>(r);}
505
 
};
506
 
 
507
 
 
508
 
/* SIMD operations extended with HOM*/
509
 
template<int fw> template <HOM_t m1, HOM_t m2>
510
 
inline SIMD_type simd<fw>::add(SIMD_type r1, SIMD_type r2){
511
 
        return simd<fw>::add(SIMD<fw,m1>::hom(r1),SIMD<fw,m2>::hom(r2));
512
 
}
513
 
 
514
 
template<int fw> template <HOM_t m1, HOM_t m2>
515
 
inline SIMD_type simd<fw>::sub(SIMD_type r1, SIMD_type r2){
516
 
        return simd<fw>::sub(SIMD<fw,m1>::hom(r1),SIMD<fw,m2>::hom(r2));
517
 
}
518
 
 
519
 
template<int fw> template <HOM_t m1, HOM_t m2>
520
 
inline SIMD_type simd<fw>::pack(SIMD_type r1, SIMD_type r2){
521
 
        return simd<fw>::pack(SIMD<fw,m1>::l2x(r1),SIMD<fw,m2>::l2x(r2));
522
 
}
523
 
 
524
 
template<int fw> template <HOM_t m1, HOM_t m2>
525
 
inline SIMD_type simd<fw>::mergeh(SIMD_type r1, SIMD_type r2){
526
 
        return simd<fw>::mergeh(SIMD<fw,m1>::hom(r1),SIMD<fw,m2>::hom(r2));
527
 
}
528
 
 
529
 
template<int fw> template <HOM_t m1, HOM_t m2>
530
 
inline SIMD_type simd<fw>::mergel(SIMD_type r1, SIMD_type r2){
531
 
        return simd<fw>::mergel(SIMD<fw,m1>::hom(r1),SIMD<fw,m2>::hom(r2));
532
 
}
533
 
 
534
 
 
535
 
//
536
 
//template <HOM_t m>
537
 
//struct HOM {
538
 
//template<int fw> SIMD_type hom(SIMD_type r) {return r;}
539
 
//template<int fw> SIMD_type l2x(SIMD_type r) {return r;}
540
 
//};
541
 
//
542
 
//template <> 
543
 
//template <int fw>
544
 
//SIMD_type HOM<l>::hom(SIMD_type r) {return simd_andc(r, simd<fw>::himask());}
545
 
//
546
 
//template <> 
547
 
//template <int fw>
548
 
//SIMD_type HOM<h>::hom(SIMD_type r) {return simd<fw>::srli<fw/2>(r);}
549
 
//
550
 
//template <> 
551
 
//template <int fw>
552
 
//SIMD_type HOM<h>::l2x(SIMD_type r) {return simd<fw>::srli<fw/2>(r);}
553
 
//
554
 
//
555
 
///* SIMD operations extended with Half-Operand Modifiers */
556
 
//
557
 
//template<int fw> template <HOM_t m1, HOM_t m2>
558
 
//inline SIMD_type simd<fw>::add(SIMD_type r1, SIMD_type r2){
559
 
//      return simd<fw>::add(HOM<m1>::hom<fw>, HOM<m2>::hom<fw>(r2));
560
 
//}
561
 
//
562
 
//template<int fw> template <HOM_t m1, HOM_t m2>
563
 
//inline SIMD_type simd<fw>::sub(SIMD_type r1, SIMD_type r2){
564
 
//      return simd<fw>::sub(HOM<m1>::hom<fw>, HOM<m2>::hom<fw>(r2));
565
 
//}
566
 
//
567
 
//template<int fw> template <HOM_t m1, HOM_t m2>
568
 
//inline SIMD_type simd<fw>::mult(SIMD_type r1, SIMD_type r2){
569
 
//      return simd<fw>::mult(HOM<m1>::hom<fw>, HOM<m2>::hom<fw>(r2));
570
 
//}
571
 
//
572
 
//template<int fw> template <HOM_t m1, HOM_t m2>
573
 
//inline SIMD_type simd<fw>::pack(SIMD_type r1, SIMD_type r2){
574
 
//      return simd<fw>::pack(HOM<m1>::l2x<fw>, HOM<m2>::hom<fw>::hom(r2));
575
 
//}
576
 
//
577
 
//template<int fw> template <HOM_t m1, HOM_t m2>
578
 
//inline SIMD_type simd<fw>::mergeh(SIMD_type r1, SIMD_type r2){
579
 
//      return simd<fw>::mergeh(HOM<m1>::hom<fw>, HOM<m2>::hom<fw>::hom(r2));
580
 
//}
581
 
//
582
 
//template<int fw> template <HOM_t m1, HOM_t m2>
583
 
//inline SIMD_type simd<fw>::mergel(SIMD_type r1, SIMD_type r2){
584
 
//      return simd<fw>::mergel(HOM<m1>::hom<fw>, HOM<m2>::hom<fw>::hom(r2));
585
 
//} 
586
 
 
587
 
/* V.  sisd operations on full 128-bit register width. */
588
 
 
589
 
//struct sisd {
590
 
//      template <int shft> inline SIMD_type slli(SIMD_type r) {return simd<128>::slli<shft>(r);}
591
 
//      template <int shft> inline SIMD_type srli(SIMD_type r) {return simd<128>::srli<shft>(r);}
592
 
//      inline SIMD_type sll(SIMD_type r, SIMD_type shft) {return simd<128>::sll<shft>(r, shft);}
593
 
//      inline SIMD_type srl(SIMD_type r, SIMD_type shft) {return simd<128>::srl<shft>(r, shft);}
594
 
//};
595
 
 
596
 
 
597
 
#define sisd_store_aligned(r, addr) _mm_store_si128(addr, r)
598
 
#define sisd_store_unaligned(r, addr) _mm_storeu_si128(addr, r)
599
 
#define sisd_load_aligned(addr) _mm_load_si128(addr)
600
 
#ifndef USE_LDDQU
601
 
#define sisd_load_unaligned(addr) _mm_loadu_si128(addr)
602
 
#endif
603
 
#ifdef USE_LDDQU
604
 
#define sisd_load_unaligned(addr) _mm_lddqu_si128(addr)
605
 
#endif
606
 
 
607
 
 
608
 
#define bitblock_test_bit(blk, n) \
609
 
   sisd_to_int(sisd_srli(sisd_slli(blk, ((BLOCKSIZE-1)-(n))), BLOCKSIZE-1))
610
 
 
611
 
 
612
 
#if (BYTE_ORDER == BIG_ENDIAN)
613
 
void print_bit_block(char * var_name, SIMD_type v) {
614
 
  union {SIMD_type vec; unsigned char elems[8];} x;
615
 
  x.vec = v;
616
 
  unsigned char c, bit_reversed;
617
 
  int i;
618
 
  printf("%20s = ", var_name);
619
 
  for (i = 0; i < sizeof(SIMD_type); i++) {
620
 
    c = x.elems[i];
621
 
     printf("%02X ", c); 
622
 
  }
623
 
  printf("\n");
624
 
}
625
 
#endif
626
 
 
627
 
#if (BYTE_ORDER == LITTLE_ENDIAN)
628
 
void print_bit_block(char * var_name, SIMD_type v) {
629
 
  union {SIMD_type vec; unsigned char elems[8];} x;
630
 
  x.vec = v;
631
 
  unsigned char c, bit_reversed;
632
 
  int i;
633
 
  printf("%20s = ", var_name);
634
 
  for (i = sizeof(SIMD_type)-1; i >= 0; i--) {
635
 
    c = x.elems[i];
636
 
     printf("%02X ", c); 
637
 
  }
638
 
  printf("\n");
639
 
}
640
 
#endif
641
 
 
642
 
 
643
 
static inline int bitblock_has_bit(SIMD_type v) {
644
 
  return !simd_all_true<8>(simd<8>::eq(v, simd<8>::constant<0>()));
645
 
}
646
 
 
647
 
static inline int bitblock_bit_count(SIMD_type v) {
648
 
  int bit_count = 0;
649
 
  SIMD_type cts_2 = simd<2>::add<l,h>(v, v);
650
 
  SIMD_type cts_4 = simd<4>::add<l,h>(cts_2, cts_2);
651
 
  SIMD_type cts_8 = simd<8>::add<l,h>(cts_4, cts_4);
652
 
  SIMD_type cts_64 = _mm_sad_epu8(cts_8, simd<8>::constant<0>());
653
 
  /* SIMD_type cts_128 = simd<a28>::add<l,h>(cts_64, cts_64) */;
654
 
  SIMD_type cts_128 = simd<64>::add(cts_64, simd<128>::srli<64>(cts_64));
655
 
  return (int) sisd_to_int(cts_128);
656
 
}
657
 
#endif
658