updated for new hooks
[libfirm] / ir / adt / bitset_ia32.h
1
2 #ifndef _BITSET_IA32_H
3 #define _BITSET_IA32_H
4
5 #undef _bitset_inside_clear
6 #undef _bitset_inside_set
7 #undef _bitset_inside_flip
8 #undef _bitset_inside_is_set
9
10 #undef _bitset_inside_nlz
11 #undef _bitset_inside_ntz
12 #undef _bitset_inside_ntz_value
13
14 #define _bitset_inside_set(unit,bit) \
15         __asm__( "btsl %1,%0" :"=m" (unit) :"Ir" (bit))
16
17 #define _bitset_inside_clear(unit,bit) \
18         __asm__( "btrl %1,%0" :"=m" (unit) :"Ir" (bit))
19
20 #define _bitset_inside_flip(unit,bit) \
21         __asm__( "btcl %1,%0" :"=m" (unit) :"Ir" (bit))
22
23 #define _bitset_inside_is_set(unit,bit) _bitset_ia32_inside_is_set(unit, bit)
24 #define _bitset_inside_nlz(unit) _bitset_ia32_inside_nlz(unit)
25 #define _bitset_inside_ntz(unit) _bitset_ia32_inside_ntz(unit)
26 #define _bitset_inside_ntz_value(unit) _bitset_ia32_inside_ntz_value(unit)
27
28 static INLINE int _bitset_ia32_inside_is_set(unsigned long *unit, unsigned bit)
29 {
30         int res = 0;
31         __asm__("mov $0,%0\n\tbtl %1,%2\n\tadc $0,%0"
32                         : "=r" (res)
33                         : "Ir" (bit), "m" (unit)
34                         : "cc");
35         return res;
36 }
37
38 static INLINE unsigned _bitset_ia32_inside_nlz(unsigned long *unit)
39 {
40         unsigned res = 0;
41         __asm__("bsrl %1,%0" :"=r" (res) :"m" (unit));
42         return *unit == 0 ? 32 : res;
43 }
44
45 static INLINE unsigned _bitset_ia32_inside_ntz(unsigned long *unit) {
46         unsigned res = 0;
47         __asm__("bsfl %1,%0" :"=r" (res) :"m" (unit));
48         return *unit == 0 ? 32 : res;
49 }
50
51 static INLINE unsigned _bitset_ia32_inside_ntz_value(unsigned long unit) {
52         unsigned res = 0;
53         __asm__("bsfl %1,%0" :"=r" (res) :"rm" (unit));
54         return unit == 0 ? 32 : res;
55 }
56
57 #if defined(__GNUC__) && defined(__SSE2__)
58
59 #include <stddef.h>
60 #include <xmmintrin.h>
61
62 #undef _bitset_units
63 #undef _bitset_overall_size
64 #undef _bitset_data_ptr
65
66 #undef _BITSET_BINOP_UNITS_INC
67
68 #undef _bitset_inside_binop_and
69 #undef _bitset_inside_binop_andnot
70 #undef _bitset_inside_binop_or
71 #undef _bitset_inside_binop_xor
72
73 #undef _bitset_inside_binop_with_zero_and
74 #undef _bitset_inside_binop_with_zero_andnot
75 #undef _bitset_inside_binop_with_zero_or
76 #undef _bitset_inside_binop_with_zero_xor
77
78 #define _bitset_units(highest_bit) (round_up2(highest_bit, 128) / BS_UNIT_SIZE_BITS)
79
80 #define _bitset_overall_size(bitset_base_size,highest_bit) \
81         ((bitset_base_size) + 16 + _bitset_units(highest_bit) * BS_UNIT_SIZE)
82
83 #define _bitset_data_ptr(data,bitset_base_size,highest_bit) \
84   _bitset_sse_data_ptr(data, bitset_base_size, highest_bit)
85
86 static INLINE unsigned long *_bitset_sse_data_ptr(void *data, size_t bitset_base_size,
87                 unsigned long highest_bit)
88 {
89         ptrdiff_t diff;
90         char *units = data;
91
92         diff = (units - (char *) 0) + bitset_base_size;
93         diff = round_up2(diff, 16);
94         units = (char *) 0 + diff;
95         return (unsigned long *) units;
96 }
97
98 #define _BITSET_BINOP_UNITS_INC 4
99 #define _bitset_inside_binop_and(tgt,src) _bitset_sse_inside_binop_and(tgt,src)
100 #define _bitset_inside_binop_andnot(tgt,src) _bitset_sse_inside_binop_andnot(tgt,src)
101 #define _bitset_inside_binop_or(tgt,src) _bitset_sse_inside_binop_or(tgt,src)
102 #define _bitset_inside_binop_xor(tgt,src) _bitset_sse_inside_binop_xor(tgt,src)
103
104 #define _BITSET_SSE_BINOP(name) \
105 static INLINE void _bitset_sse_inside_binop_ ## name(unsigned long *tgt, unsigned long *src) \
106 { \
107         __m128i src_op = _mm_load_si128((__m128i *) src); \
108         __m128i tgt_op = _mm_load_si128((__m128i *) tgt); \
109         __m128i res = _mm_ ## name ## _si128(tgt_op, src_op); \
110         _mm_store_si128((void *) tgt, res); \
111 }
112
113
114 static INLINE void _bitset_sse_inside_binop_with_zero_and(unsigned long *tgt)
115 {
116         tgt[0] = 0;
117         tgt[1] = 0;
118         tgt[2] = 0;
119         tgt[3] = 0;
120 }
121
122 static INLINE void _bitset_sse_inside_binop_andnot(unsigned long *tgt, unsigned long *src)
123 {
124         __m128i src_op = _mm_load_si128((void *) src);
125         __m128i tgt_op = _mm_load_si128((void *) tgt);
126         __m128i res = _mm_andnot_si128(src_op, tgt_op);
127         _mm_store_si128((__m128i *) tgt, res);
128 }
129
130 _BITSET_SSE_BINOP(and)
131 _BITSET_SSE_BINOP(or)
132 _BITSET_SSE_BINOP(xor)
133
134
135 #endif
136 #endif