application.mui: implemented MUIM_Application_UnpushMethod
[AROS.git] / compiler / arossupport / include / macros.h
blob05936ae1005b5502a1961cf9640538f1944b00d5
1 #ifndef AROS_MACROS_H
2 #define AROS_MACROS_H
4 /*
5 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
6 $Id$
8 Desc: Miscellanous macros
9 Lang: english
12 #ifndef AROS_SYSTEM_H
13 # include <aros/system.h>
14 #endif
16 /* Reverse the bits in a byte */
17 #define AROS_SWAP_BITS_BYTE_GENERIC(_b) \
18 ({ \
19 UBYTE __aros_swap_tmp = _b, \
20 b = __aros_swap_tmp; \
22 b = ((b >> 1) & 0x55) | ((b << 1) & 0xaa); \
23 b = ((b >> 2) & 0x33) | ((b << 2) & 0xcc); \
24 ((b >> 4) & 0x0f) | ((b << 4) & 0xf0); \
27 /* Reverse the bits in a word */
28 #define AROS_SWAP_BITS_WORD_GENERIC(_w) \
29 ({ \
30 UWORD __aros_swap_tmp = _w, \
31 w = __aros_swap_tmp; \
33 w = ((w >> 1) & 0x5555) | ((w << 1) & 0xaaaa); \
34 w = ((w >> 2) & 0x3333) | ((w << 2) & 0xcccc); \
35 w = ((w >> 4) & 0x0f0f) | ((w << 4) & 0xf0f0); \
36 ((w >> 8) & 0x00ff) | ((w << 8) & 0xff00); \
39 /* Reverse the bits in a long */
40 #define AROS_SWAP_BITS_LONG_GENERIC(_l) \
41 ({ \
42 ULONG __aros_swap_tmp = _l, l = __aros_swap_tmp; \
44 l = ((l >> 1) & 0x55555555UL) | ((l << 1) & 0xaaaaaaaaUL); \
45 l = ((l >> 2) & 0x33333333UL) | ((l << 2) & 0xccccccccUL); \
46 l = ((l >> 4) & 0x0f0f0f0fUL) | ((l << 4) & 0xf0f0f0f0UL); \
47 l = ((l >> 8) & 0x00ff00ffUL) | ((l << 8) & 0xff00ff00UL); \
48 ((l >> 16) & 0x0000ffffUL) | ((l << 16) & 0xffff0000UL); \
51 /* Reverse the bits in a quad */
52 #define AROS_SWAP_BITS_QUAD_GENERIC(_q) \
53 ({ \
54 UQUAD __aros_swap_tmp = _q, q = __aros_swap_tmp; \
56 q = ((q >> 1) & 0x5555555555555555ULL) | ((q << 1) & 0xaaaaaaaaaaaaaaaaULL); \
57 q = ((q >> 2) & 0x3333333333333333ULL) | ((q << 2) & 0xccccccccccccccccULL); \
58 q = ((q >> 4) & 0x0f0f0f0f0f0f0f0fULL) | ((q << 4) & 0xf0f0f0f0f0f0f0f0ULL); \
59 q = ((q >> 8) & 0x00ff00ff00ff00ffULL) | ((q << 8) & 0xff00ff00ff00ff00ULL); \
60 q = ((q >> 16) & 0x0000ffff0000ffffULL) | ((q << 16) & 0xffff0000ffff0000ULL); \
61 ((q >> 32) & 0x00000000ffffffffULL) | ((q << 32) & 0xffffffff00000000ULL); \
64 /* Reverse the bytes in a word */
65 #define AROS_SWAP_BYTES_WORD_GENERIC(_w) \
66 ({ \
67 const UWORD __aros_swap_tmp = _w, \
68 w = __aros_swap_tmp; \
70 (UWORD)(((w >> 8) & 0x00FF) | ((w << 8) & 0xFF00)); \
73 /* Reverse the bytes in a long */
74 #define AROS_SWAP_BYTES_LONG_GENERIC(_l) \
75 ({ \
76 const ULONG __aros_swap_tmp = _l, \
77 l = __aros_swap_tmp; \
79 ((ULONG)AROS_SWAP_BYTES_WORD(l & 0xFFFF) << 16) | \
80 (AROS_SWAP_BYTES_WORD((l >> 16) & 0xFFFF)); \
83 /* Reverse the bytes in a quad */
84 #define AROS_SWAP_BYTES_QUAD_GENERIC(_q) \
85 ({ \
86 const UQUAD __aros_swap_tmp = _q, \
87 q = __aros_swap_tmp; \
89 ((UQUAD)AROS_SWAP_BYTES_LONG(q & 0xFFFFFFFFULL) << 32) | \
90 (AROS_SWAP_BYTES_LONG(q >> 32) & 0xFFFFFFFFULL); \
93 /* Reverse the words in a long */
94 #define AROS_SWAP_WORDS_LONG_GENERIC(_l) \
95 ({ \
96 const ULONG __aros_swap_tmp = _l, l = __aros_swap_tmp; \
98 (ULONG)(((l >> 16) & 0x0000FFFFUL) | ((l << 16) & 0xFFFF0000UL)); \
101 /* Reverse the words in a quad */
102 #define AROS_SWAP_WORDS_QUAD_GENERIC(_q) \
103 ({ \
104 const UQUAD __aros_swap_tmp = _q, q = __aros_swap_tmp; \
106 ((UQUAD)AROS_SWAP_WORDS_LONG(q & 0xFFFFFFFFULL) << 32) | \
107 (AROS_SWAP_WORDS_LONG(q >> 32) & 0xFFFFFFFFULL); \
110 /* Reverse the longs in a quad */
111 #define AROS_SWAP_LONGS_QUAD_GENERIC(_q) \
112 ({ \
113 const UQUAD __aros_swap_tmp = _q, q = __aros_swap_tmp; \
115 (UQUAD)(((q >> 32) & 0xFFFFFFFFULL) | ((q << 32) & 0xFFFFFFFF00000000ULL)); \
118 /* Use the CPU-specific definitions of the above macros, if they exist, but reuse
119 the generic macros in case the given value is a compile-time constant, because
120 the compiler will optimize things out for us. */
121 #if !defined(AROS_SWAP_BITS_BYTE_CPU)
122 # define AROS_SWAP_BITS_BYTE(b) AROS_SWAP_BITS_BYTE_GENERIC(b)
123 #elif defined(__GNUC__)
124 # define AROS_SWAP_BITS_BYTE(b) \
126 __builtin_constant_p(b) \
127 ? AROS_SWAP_BITS_BYTE_GENERIC(b) \
128 : AROS_SWAP_BITS_BYTE_CPU(b) \
130 #else
131 # define AROS_SWAP_BITS_BYTE(b) AROS_SWAP_BITS_BYTE_CPU(b)
132 #endif
134 #if !defined(AROS_SWAP_BITS_WORD_CPU)
135 # define AROS_SWAP_BITS_WORD(w) AROS_SWAP_BITS_WORD_GENERIC(w)
136 #elif defined(__GNUC__)
137 # define AROS_SWAP_BITS_WORD(w) \
139 __builtin_constant_p(w) \
140 ? AROS_SWAP_BITS_WORD_GENERIC(w) \
141 : AROS_SWAP_BITS_WORD_CPU(w) \
143 #else
144 # define AROS_SWAP_BITS_WORD(w) AROS_SWAP_BITS_WORD_CPU(w)
145 #endif
147 #if !defined(AROS_SWAP_BITS_LONG_CPU)
148 # define AROS_SWAP_BITS_LONG(l) AROS_SWAP_BITS_LONG_GENERIC(l)
149 #elif defined(__GNUC__)
150 # define AROS_SWAP_BITS_LONG(l) \
152 __builtin_constant_p(l) \
153 ? AROS_SWAP_BITS_LONG_GENERIC(l) \
154 : AROS_SWAP_BITS_LONG_CPU(l) \
156 #else
157 # define AROS_SWAP_BITS_LONG(l) AROS_SWAP_BITS_LONG_CPU(l)
158 #endif
160 #if !defined(AROS_SWAP_BITS_QUAD_CPU)
161 # define AROS_SWAP_BITS_QUAD(q) AROS_SWAP_BITS_QUAD_GENERIC(q)
162 #elif defined(__GNUC__)
163 # define AROS_SWAP_BITS_QUAD(q) \
165 __builtin_constant_p(q) \
166 ? AROS_SWAP_BITS_QUAD_GENERIC(q) \
167 : AROS_SWAP_BITS_QUAD_CPU(q) \
169 #else
170 # define AROS_SWAP_BITS_QUAD(q) AROS_SWAP_BITS_QUAD_CPU(q)
171 #endif
173 /* Just for consistency... */
174 #define AROS_SWAP_BYTES_BYTE(b) ((UBYTE)b)
175 #define AROS_SWAP_WORDS_WORD(w) ((ULONG)l)
176 #define AROS_SWAP_LONGS_LONG(l) ((UWORD)l)
177 #define AROS_SWAP_QUADS_QUAD(q) ((UQUAD)q)
179 #if !defined(AROS_SWAP_BYTES_WORD_CPU)
180 # define AROS_SWAP_BYTES_WORD(w) AROS_SWAP_BYTES_WORD_GENERIC(w)
181 #elif defined(__GNUC__)
182 # define AROS_SWAP_BYTES_WORD(w) \
184 __builtin_constant_p(w) \
185 ? AROS_SWAP_BYTES_WORD_GENERIC(w) \
186 : AROS_SWAP_BYTES_WORD_CPU(w) \
188 #else
189 # define AROS_SWAP_BYTES_WORD(w) AROS_SWAP_BYTES_WORD_CPU(w)
190 #endif
192 #if !defined(AROS_SWAP_BYTES_LONG_CPU)
193 # define AROS_SWAP_BYTES_LONG(l) AROS_SWAP_BYTES_LONG_GENERIC(l)
194 #elif defined(__GNUC__)
195 # define AROS_SWAP_BYTES_LONG(l) \
197 __builtin_constant_p(l) \
198 ? AROS_SWAP_BYTES_LONG_GENERIC(l) \
199 : AROS_SWAP_BYTES_LONG_CPU(l) \
201 #else
202 # define AROS_SWAP_BYTES_LONG(l) AROS_SWAP_BYTES_LONG_CPU(l)
203 #endif
205 #if !defined(AROS_SWAP_BYTES_QUAD_CPU)
206 # define AROS_SWAP_BYTES_QUAD(q) AROS_SWAP_BYTES_QUAD_GENERIC(q)
207 #elif defined(__GNUC__)
208 # define AROS_SWAP_BYTES_QUAD(q) \
210 __builtin_constant_p(q) \
211 ? AROS_SWAP_BYTES_QUAD_GENERIC(q) \
212 : AROS_SWAP_BYTES_QUAD_CPU(q) \
214 #else
215 # define AROS_SWAP_BYTES_QUAD(q) AROS_SWAP_BYTES_QUAD_CPU(q)
216 #endif
218 #if !defined(AROS_SWAP_WORDS_LONG_CPU)
219 # define AROS_SWAP_WORDS_LONG(l) AROS_SWAP_WORDS_LONG_GENERIC(l)
220 #elif defined(__GNUC__)
221 # define AROS_SWAP_WORDS_LONG(l) \
223 __builtin_constant_p(l) \
224 ? AROS_SWAP_WORDS_LONG_GENERIC(l) \
225 : AROS_SWAP_WORDS_LONG_CPU(l) \
227 #else
228 # define AROS_SWAP_WORDS_LONG(l) AROS_SWAP_WORDS_LONG_CPU(l)
229 #endif
231 #if !defined(AROS_SWAP_WORDS_QUAD_CPU)
232 # define AROS_SWAP_WORDS_QUAD(q) AROS_SWAP_WORDS_QUAD_GENERIC(q)
233 #elif defined(__GNUC__)
234 # define AROS_SWAP_WORDS_QUAD(q) \
236 __builtin_constant_p(q) \
237 ? AROS_SWAP_WORDS_QUAD_GENERIC(q) \
238 : AROS_SWAP_WORDS_QUAD_CPU(q) \
240 #else
241 # define AROS_SWAP_WORDS_QUAD(l) AROS_SWAP_WORDS_QUAD_CPU(l)
242 #endif
244 #if !defined(AROS_SWAP_LONGS_QUAD_CPU)
245 # define AROS_SWAP_LONGS_QUAD(q) AROS_SWAP_LONGS_QUAD_GENERIC(q)
246 #elif defined(__GNUC__)
247 # define AROS_SWAP_LONGS_QUAD(q) \
249 __builtin_constant_p(q) \
250 ? AROS_SWAP_LONGS_QUAD_GENERIC(q) \
251 : AROS_SWAP_LONGS_QUAD_CPU(q) \
253 #else
254 # define AROS_SWAP_LONGS_QUAD(q) AROS_SWAP_LONGS_QUAD_CPU(q)
255 #endif
257 #if AROS_BIG_ENDIAN
258 # define AROS_BE(type)
259 # define AROS_LE(type) AROS_SWAP_BYTES_ ## type
260 #else
261 # define AROS_BE(type) AROS_SWAP_BYTES_ ## type
262 # define AROS_LE(type)
263 #endif
265 /* Convert a word, long or quad to big endian and vice versa on the current hardware */
266 #define AROS_WORD2BE(w) AROS_BE(WORD)(w)
267 #define AROS_LONG2BE(l) AROS_BE(LONG)(l)
268 #define AROS_QUAD2BE(q) AROS_BE(QUAD)(q)
269 #define AROS_BE2WORD(w) AROS_BE(WORD)(w)
270 #define AROS_BE2LONG(l) AROS_BE(LONG)(l)
271 #define AROS_BE2QUAD(q) AROS_BE(QUAD)(q)
273 /* Convert a word, long or quad to little endian and vice versa on the current hardware */
274 #define AROS_WORD2LE(w) AROS_LE(WORD)(w)
275 #define AROS_LONG2LE(l) AROS_LE(LONG)(l)
276 #define AROS_QUAD2LE(q) AROS_LE(QUAD)(q)
277 #define AROS_LE2WORD(w) AROS_LE(WORD)(w)
278 #define AROS_LE2LONG(l) AROS_LE(LONG)(l)
279 #define AROS_LE2QUAD(q) AROS_LE(QUAD)(q)
281 /* Return the least set bit, ie. 0xFF00 will return 0x0100 */
282 #ifndef AROS_LEAST_BIT
283 # define AROS_LEAST_BIT(l) ((l) & -(l))
284 #endif
286 /* Check if an int is a power of two */
287 #ifndef AROS_IS_POWER_OF_2
288 # define AROS_IS_POWER_OF_2(l) (((l) & -(l)) == (l))
289 #endif
291 /* Round down <x> to a multiple of <r>. <r> must be a power of two */
292 #ifndef AROS_ROUNDDOWN2
293 # define AROS_ROUNDDOWN2(x,r) ((x) & ~((r) - 1))
294 #endif
296 /* Round up <x> to a multiple of <r>. <r> must be a power of two */
297 #ifndef AROS_ROUNDUP2
298 # define AROS_ROUNDUP2(x,r) (((x) + ((r) - 1)) & ~((r) - 1))
299 #endif
301 /* Return the number of the least set bit, ie. 0xFF00 will return 8 */
302 #ifndef AROS_LEAST_BIT_POS
303 # define AROS_LEAST_BIT_POS(l) \
304 (((l) & 0x0000FFFFUL) ? \
305 ((l) & 0x000000FFUL) ? \
306 ((l) & 0x0000000FUL) ? \
307 ((l) & 0x03UL) ? \
308 ((l) & 0x01UL) ? 0 : 1 \
309 : ((l) & 0x04UL) ? 2 : 3 \
310 : ((l) & 0x30UL) ? \
311 ((l) & 0x10UL) ? 4 : 5 \
312 : ((l) & 0x40UL) ? 6 : 7 \
313 : ((l) & 0x00000F00UL) ? \
314 ((l) & 0x0300UL) ? \
315 ((l) & 0x0100UL) ? 8 : 9 \
316 : ((l) & 0x0400UL) ? 10 : 11 \
317 : ((l) & 0x3000UL) ? \
318 ((l) & 0x1000UL) ? 12 : 13 \
319 : ((l) & 0x4000UL) ? 14 : 15 \
320 : ((l) & 0x00FF0000UL) ? \
321 ((l) & 0x000F0000UL) ? \
322 ((l) & 0x030000UL) ? \
323 ((l) & 0x010000UL) ? 16 : 17 \
324 : ((l) & 0x040000UL) ? 18 : 19 \
325 : ((l) & 0x300000UL) ? \
326 ((l) & 0x100000UL) ? 20 : 21 \
327 : ((l) & 0x400000UL) ? 22 : 23 \
328 : ((l) & 0x0F00000000UL) ? \
329 ((l) & 0x03000000UL) ? \
330 ((l) & 0x01000000UL) ? 24 : 25 \
331 : ((l) & 0x04000000UL) ? 26 : 27 \
332 : ((l) & 0x30000000UL) ? \
333 ((l) & 0x10000000UL) ? 28 : 29 \
334 : ((l) & 0x40000000UL) ? 30 : (l) ? 31 : -1)
335 #endif /* AROS_LEAST_BIT_POS */
337 /* Swap two integer variables */
338 #ifndef AROS_SWAP
339 # define AROS_SWAP(x,y) (x) ^= (y) ^= (x) ^= (y)
340 #endif
342 /* Build an 'ID' as used by iffparse.library and some other libraries as well. */
343 #define AROS_MAKE_ID(a,b,c,d) (((ULONG) (a)<<24) | ((ULONG) (b)<<16) | \
344 ((ULONG) (c)<<8) | ((ULONG) (d)))
346 #endif /* AROS_MACROS_H */