Changed the implementation of nlz in bitfiddle.
[libfirm] / include / libfirm / adt / bitset_ia32.h
1 /*
2  * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief    intel 80x86 implementation of bitsets
23  * @version  $Id$
24  */
25 #ifndef _BITSET_IA32_H
26 #define _BITSET_IA32_H
27
28 #undef _bitset_inside_clear
29 #undef _bitset_inside_set
30 #undef _bitset_inside_flip
31
32 #define _bitset_inside_set(unit, bit) \
33         __asm__ __volatile__( "btsl %1,%0" :"=m" (*unit) : "Ir" (bit) : "cc")
34
35 #define _bitset_inside_clear(unit, bit) \
36         __asm__ __volatile__( "btrl %1,%0" :"=m" (*unit) : "Ir" (bit) : "cc")
37
38 #define _bitset_inside_flip(unit, bit) \
39         __asm__ __volatile__( "btcl %1,%0" :"=m" (*unit) : "Ir" (bit) : "cc")
40
41 #undef _bitset_inside_is_set
42 #undef _bitset_inside_nlz
43 #undef _bitset_inside_ntz
44 #undef _bitset_inside_ntz_value
45
46 #define _bitset_inside_is_set(unit, bit) _bitset_ia32_inside_is_set(unit, bit)
47 #define _bitset_inside_nlz(unit)         _bitset_ia32_inside_nlz(unit)
48 #define _bitset_inside_ntz(unit)         _bitset_ia32_inside_ntz(unit)
49 #define _bitset_inside_ntz_value(unit)   _bitset_ia32_inside_ntz_value(unit)
50
51 static INLINE int _bitset_ia32_inside_is_set(bitset_unit_t *unit, unsigned bit)
52 {
53         int res;
54         __asm__("btl   %2, %1\n\t"
55                         "mov   $0, %0\n\t"
56                         "adc   $0, %0"
57                         : "=r" (res)
58                         : "m" (*unit), "Ir" (bit)
59                         : "cc");
60         return res;
61 }
62
63 static INLINE unsigned _bitset_ia32_inside_nlz(bitset_unit_t *unit)
64 {
65         unsigned res, tmp;
66         __asm__("bsrl   %1, %0\n\t"
67                         "mov    $ffffffff, %2\n\t"
68                         "cmovz  %2, %0\n\t"
69                         "neg    %0\n\t"
70                         "add   $31, %0"
71                         : "=&r" (res)
72                         : "m" (*unit), "r" (tmp)
73                         : "cc");
74         return res;
75 }
76
77 static INLINE unsigned _bitset_ia32_inside_ntz(bitset_unit_t *unit) {
78         unsigned res, tmp;
79         __asm__("bsf l  %1, %0\n\t"
80                         "mov   $32, %2\n\t"
81                         "cmovz  %2, %0\n\t"
82                         : "=&r" (res)
83                         : "m" (*unit), "r" (tmp)
84                         : "cc");
85         return res;
86 }
87
88 static INLINE unsigned _bitset_ia32_inside_ntz_value(bitset_unit_t unit) {
89         unsigned res, tmp;
90         __asm__("bsfl   %1, %0\n\t"
91                         "mov   $32, %2\n\t"
92                         "cmovz  %2, %0\n\t"
93                         : "=&r" (res)
94                         : "r" (unit), "r" (tmp)
95                         : "cc");
96         return res;
97 }
98
99 #if defined(__GNUC__) && defined(__SSE2__)
100
101 #include <stddef.h>
102 #include <xmmintrin.h>
103
104 #undef _bitset_units
105 #undef _bitset_overall_size
106 #undef _bitset_data_ptr
107
108 #undef _BITSET_BINOP_UNITS_INC
109
110 #undef _bitset_inside_binop_and
111 #undef _bitset_inside_binop_andnot
112 #undef _bitset_inside_binop_or
113 #undef _bitset_inside_binop_xor
114
115 #define _bitset_units(highest_bit) (round_up2(highest_bit, 128) / BS_UNIT_SIZE_BITS)
116
117 #define _bitset_overall_size(bitset_base_size,highest_bit) \
118         ((bitset_base_size) + 16 + _bitset_units(highest_bit) * BS_UNIT_SIZE)
119
120 #define _bitset_data_ptr(data,bitset_base_size,highest_bit) \
121   _bitset_sse_data_ptr(data, bitset_base_size, highest_bit)
122
123 static INLINE bitset_unit_t *_bitset_sse_data_ptr(void *data, size_t bitset_base_size,
124                 bitset_pos_t highest_bit)
125 {
126         ptrdiff_t diff;
127         char *units = data;
128
129         diff = (units - (char *) 0) + bitset_base_size;
130         diff = round_up2(diff, 16);
131         units = (char *) 0 + diff;
132         return (bitset_unit_t *) units;
133 }
134
135 #define _BITSET_BINOP_UNITS_INC 4
136 #define _bitset_inside_binop_and(tgt,src) _bitset_sse_inside_binop_and(tgt,src)
137 #define _bitset_inside_binop_andnot(tgt,src) _bitset_sse_inside_binop_andnot(tgt,src)
138 #define _bitset_inside_binop_or(tgt,src) _bitset_sse_inside_binop_or(tgt,src)
139 #define _bitset_inside_binop_xor(tgt,src) _bitset_sse_inside_binop_xor(tgt,src)
140
141 #define _BITSET_SSE_BINOP(name) \
142 static INLINE void _bitset_sse_inside_binop_ ## name(bitset_unit_t *tgt, bitset_unit_t *src) \
143 { \
144         __m128i src_op = _mm_load_si128((__m128i *) src); \
145         __m128i tgt_op = _mm_load_si128((__m128i *) tgt); \
146         __m128i res = _mm_ ## name ## _si128(tgt_op, src_op); \
147         _mm_store_si128((void *) tgt, res); \
148 }
149
150
151 static INLINE void _bitset_sse_inside_binop_with_zero_and(bitset_unit_t *tgt)
152 {
153         tgt[0] = 0;
154         tgt[1] = 0;
155         tgt[2] = 0;
156         tgt[3] = 0;
157 }
158
159 static INLINE void _bitset_sse_inside_binop_andnot(bitset_unit_t *tgt, bitset_unit_t *src)
160 {
161         __m128i src_op = _mm_load_si128((void *) src);
162         __m128i tgt_op = _mm_load_si128((void *) tgt);
163         __m128i res = _mm_andnot_si128(src_op, tgt_op);
164         _mm_store_si128((__m128i *) tgt, res);
165 }
166
167 _BITSET_SSE_BINOP(and)
168 _BITSET_SSE_BINOP(or)
169 _BITSET_SSE_BINOP(xor)
170
171
172 #endif
173 #endif