TEMU  4.4
The Terma Emulator
Bitmanip.h
Go to the documentation of this file.
1 //===-- temu-c/Bitmanip.h - Low level bit/byte manipulation -----*- C++ -*-===//
2 //
3 // TEMU: The Terma Emulator
4 // (c) Terma 2015, 2016, 2017
5 // Authors: Mattias Holm <maho (at) terma.com>
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef TEMU_BITMANIP_H
10 #define TEMU_BITMANIP_H
11 
12 #include <assert.h>
13 #include <stdbool.h>
14 #include <stdint.h>
15 
16 #ifndef __has_builtin
17 #define __has_builtin(x) 0
18 #endif
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 /*!
25  * Swap half words inside 32 bit word
26  * \param Word The word to be swapped
27  * \result the swapped word
28  */
29 static inline uint32_t
30 temu_swap32Half(uint32_t Word)
31 {
32  uint32_t Res = Word << 16 | Word >> 16;
33  return Res;
34 }
35 
36 /*!
37  * Swap words inside 64 bit word
38  * \param DWord The word to be swapped
39  * \result the swapped word
40  */
41 static inline uint64_t
42 temu_swap64Word(uint64_t DWord)
43 {
44  uint64_t Res = DWord << 32 | DWord >> 32;
45  return Res;
46 }
47 
48 /*!
49  * Swap bytes in 16 bit word
50  * \param HWord The word to be swapped
51  * \result the swapped word
52  */
53 static inline uint16_t
54 temu_swap16(uint16_t HWord)
55 {
56 #if 1
57  uint16_t Res = __builtin_bswap16(HWord);
58 #else
59  uint16_t Res = HWord << 8 | HWord >> 8;
60 #endif
61  return Res;
62 }
63 
64 /*!
65  * Swap bytes in 32 bit word
66  * \param Word The word to be swapped
67  * \result the swapped word
68  */
69 static inline uint32_t
70 temu_swap32(uint32_t Word)
71 {
72 #if 1
73  uint32_t Res = __builtin_bswap32(Word);
74 #else
75  uint32_t Res =
76  (((uint32_t)temu_swap16(Word)) << 16) | (uint32_t)temu_swap16(Word >> 16);
77 #endif
78  return Res;
79 }
80 
81 /*!
82  * Swap bytes in 64 bit word
83  * \param DWord The word to be swapped
84  * \result the swapped word
85  */
86 static inline uint64_t
87 temu_swap64(uint64_t DWord)
88 {
89 #if 1
90  uint64_t Res = __builtin_bswap64(DWord);
91 #else
92  uint64_t Res = (((uint64_t)temu_swap32(DWord)) << 32) |
93  (uint64_t)temu_swap32(DWord >> 32);
94 #endif
95  return Res;
96 }
97 
98 /*!
99  * Swap between big endian and host endian. Note that at present we
100  * only have little endian hosts, so these functions simply
101  * wrap. However, they declare intent and it is recommended that you
102  * use these for swapping when you want to go between little<->host
103  * and big<->host.
104  *
105  * \param Word The word to be swapped
106  * \result the swapped word
107  */
108 static inline uint32_t
109 temu_swapBigHost32Half(uint32_t Word)
110 {
111  return temu_swap32Half(Word);
112 }
113 
114 /*!
115  * Swap between big endian and host endian. Note that at present we
116  * only have little endian hosts, so these functions simply
117  * wrap. However, they declare intent and it is recommended that you
118  * use these for swapping when you want to go between little<->host
119  * and big<->host.
120  *
121  * \param DWord The word to be swapped
122  * \result the swapped word
123  */
124 static inline uint64_t
125 temu_swapBigHost64Word(uint64_t DWord)
126 {
127  return temu_swap64Word(DWord);
128 }
129 
130 /*!
131  * Swap between little endian to host endian. Note that at present we
132  * only have little endian hosts, so these functions simply
133  * wrap. However, they declare intent and it is recommended that you
134  * use these for swapping when you want to go between little<->host
135  * and big<->host.
136  *
137  * \param Word The word to be swapped
138  * \result the swapped word
139  */
140 static inline uint32_t
141 temu_swapLittleHost32Half(uint32_t Word)
142 {
143  return Word;
144 }
145 
146 /*!
147  * Swap between little endian and host endian. Note that at present we
148  * only have little endian hosts, so these functions simply
149  * wrap. However, they declare intent and it is recommended that you
150  * use these for swapping when you want to go between little<->host
151  * and big<->host.
152  *
153  * \param DWord The word to be swapped
154  * \result the swapped word
155  */
156 static inline uint64_t
157 temu_swapLittleHost64Word(uint64_t DWord)
158 {
159  return DWord;
160 }
161 
162 /*!
163  * Swap between big endian and host endian. Note that at present we
164  * only have little endian hosts, so these functions simply
165  * wrap. However, they declare intent and it is recommended that you
166  * use these for swapping when you want to go between little<->host
167  * and big<->host.
168  *
169  * \param HWord The word to be swapped
170  * \result the swapped word
171  */
172 static inline uint16_t
173 temu_swapBigHost16(uint16_t HWord)
174 {
175  return temu_swap16(HWord);
176 }
177 
178 /*!
179  * Swap between big endian and host endian. Note that at present we
180  * only have little endian hosts, so these functions simply
181  * wrap. However, they declare intent and it is recommended that you
182  * use these for swapping when you want to go between little<->host
183  * and big<->host.
184  *
185  * \param Word The word to be swapped
186  * \result the swapped word
187  */
188 static inline uint32_t
189 temu_swapBigHost32(uint32_t Word)
190 {
191  return temu_swap32(Word);
192 }
193 
194 /*!
195  * Swap between big endian and host endian. Note that at present we
196  * only have little endian hosts, so these functions simply
197  * wrap. However, they declare intent and it is recommended that you
198  * use these for swapping when you want to go between little<->host
199  * and big<->host.
200  *
201  * \param DWord The word to be swapped
202  * \result the swapped word
203  */
204 static inline uint64_t
205 temu_swapBigHost64(uint64_t DWord)
206 {
207  return temu_swap64(DWord);
208 }
209 
210 /*!
211  * Swap between little endian and host endian. Note that at present we
212  * only have little endian hosts, so these functions simply
213  * wrap. However, they declare intent and it is recommended that you
214  * use these for swapping when you want to go between little<->host
215  * and big<->host.
216  *
217  * \param HWord The word to be swapped
218  * \result the swapped word
219  */
220 static inline uint16_t
221 temu_swapLittleHost16(uint16_t HWord)
222 {
223  return HWord;
224 }
225 
226 /*!
227  * Swap between little endian and host endian. Note that at present we
228  * only have little endian hosts, so these functions simply
229  * wrap. However, they declare intent and it is recommended that you
230  * use these for swapping when you want to go between little<->host
231  * and big<->host.
232  *
233  * \param Word The word to be swapped
234  * \result the swapped word
235  */
236 static inline uint32_t
237 temu_swapLittleHost32(uint32_t Word)
238 {
239  return Word;
240 }
241 
242 /*!
243  * Swap between little endian and host endian. Note that at present we
244  * only have little endian hosts, so these functions simply
245  * wrap. However, they declare intent and it is recommended that you
246  * use these for swapping when you want to go between little<->host
247  * and big<->host.
248  *
249  * \param DWord The word to be swapped
250  * \result the swapped word
251  */
252 static inline uint64_t
253 temu_swapLittleHost64(uint64_t DWord)
254 {
255  return DWord;
256 }
257 
258 /*!
259  * Count trailing zeroes, this can be used as a square root on a power
260  * of 2 word.
261  *
262  * \param Word the word, in which trailing zeros to be counted
263  * \result Number of trailing zeros in Word
264  */
265 static inline int
266 temu_ctz32(uint32_t Word)
267 {
268  if (Word == 0)
269  return 32; // Due to semantics of compiler ctz
270  int Res = __builtin_ctz(Word);
271  return Res;
272 }
273 
274 /*!
275  * Count leading zeroes
276  *
277  * \param Word the word, in which leading zeros to be counted
278  * \result Number of leading zeros in Word
279  */
280 static inline int
281 temu_clz32(uint32_t Word)
282 {
283  if (Word == 0)
284  return 32;
285  int Res = __builtin_clz(Word);
286  return Res;
287 }
288 
289 /*!
290  * Count number of bits set in word
291  *
292  * \param Word The word, in which bits to be counted
293  * \result The number of bits
294  */
295 static inline int
296 temu_popcount32(uint32_t Word)
297 {
298  int Res = __builtin_popcount(Word);
299  return Res;
300 }
301 
302 /*!
303  * Compute parity of word
304  *
305  * \param Word The word, in which parity to be computed
306  * \result The parity of the word
307  */
308 static inline int
309 temu_parity32(uint32_t Word)
310 {
311  int Res = __builtin_parity(Word);
312  return Res;
313 }
314 
315 /*!
316  * Count trailing zeroes
317  *
318  * \param Word The word, in which trailing zeros to be counted
319  * \result The number of trailing zeros in Word
320  */
321 static inline int
322 temu_ctz64(uint64_t Word)
323 {
324  if (Word == 0)
325  return 64;
326  int Res = __builtin_ctzl(Word);
327  return Res;
328 }
329 
330 /*!
331  * Count leading zeroes
332  *
333  * \param Word The word, in which leading zeros to be counted
334  * \result The number of leading zeros in Word
335  */
336 static inline int
337 temu_clz64(uint64_t Word)
338 {
339  if (Word == 0)
340  return 64;
341  int Res = __builtin_clzl(Word);
342  return Res;
343 }
344 
345 
346 /*!
347  * Count trailing zeroes, this can be used as a square root on a power
348  * of 2 word.
349  *
350  * \param Word the word, in which trailing zeros to be counted
351  * \result Number of trailing zeros in Word
352  */
353 static inline int
354 temu_ctz16(uint16_t Word)
355 {
356  if (Word == 0)
357  return 16; // Due to semantics of compiler ctz
358  int Res = __builtin_ctz(Word);
359  return Res;
360 }
361 
362 /*!
363  * Count leading zeroes
364  *
365  * \param Word the word, in which leading zeros to be counted
366  * \result Number of leading zeros in Word
367  */
368 static inline int
369 temu_clz16(uint16_t Word)
370 {
371  if (Word == 0)
372  return 16;
373  int Res = __builtin_clz(Word) - 16;
374  return Res;
375 }
376 
377 /*!
378  * Count count number of bit set
379  *
380  * \param Word The word, in which bits to be counted
381  * \result The number of bits set in Word
382  */
383 static inline int
384 temu_popcount64(uint64_t Word)
385 {
386  int Res = __builtin_popcountl(Word);
387  return Res;
388 }
389 
390 /*!
391  * Compute parity
392  *
393  * \param Word The word, in which parity to be computed
394  * \result The parity of word
395  */
396 static inline int
397 temu_parity64(uint64_t Word)
398 {
399  int Res = __builtin_parityl(Word);
400  return Res;
401 }
402 
403 /*!
404  * Predicate for checking if word is a power of 2
405  * See Hacker's Delight, 1st edition, p11
406  *
407  * \param Word The word to be checked
408  * \result 0 for false, otherwise true
409  */
410 static inline int
411 temu_isPow2_32(uint32_t Word)
412 {
413  if (Word) {
414  return (Word & (Word - 1)) == 0;
415  }
416  return 0;
417 }
418 
419 /*!
420  * Predicate for checking if word is a power of 2
421  *
422  * \param Word The word to be checked
423  * \result 0 for false, otherwise true
424  */
425 static inline int
426 temu_isPow2_64(uint64_t Word)
427 {
428  if (Word) {
429  return (Word & (Word - 1)) == 0;
430  }
431  return 0;
432 }
433 
434 /*!
435  * Clear lower set bit in word
436  *
437  * \param Word The word, in which the lower set bit will be cleared
438  * \result A copy of Word with ther lowest set bit cleared
439  */
440 static inline uint32_t
441 temu_clearLeftmostBit32(uint32_t Word)
442 {
443  return Word & (Word - 1);
444 }
445 
446 /*!
447  * Clear lower set bit in word
448  *
449  * \param Word The word, in which the lower set bit will be cleared
450  * \result A copy of Word with ther lowest set bit cleared
451  */
452 static inline uint64_t
453 temu_clearLeftmostBit64(uint64_t Word)
454 {
455  return Word & (Word - 1);
456 }
457 
458 /*!
459  * Set right most bit that is zero
460  *
461  * \param Word The word, in which the right most set bit will be cleared
462  * \result A copy of Word, with the right most bit cleared
463  */
464 static inline uint32_t
465 temu_setRightmostZeroBit32(uint32_t Word)
466 {
467  return Word | (Word + 1);
468 }
469 
470 /*!
471  * Set right most bit that is zero
472  *
473  * \param Word The word, in which the right most set bit will be set
474  * \result A copy of Word, with the right most bit cleared
475  */
476 static inline uint64_t
477 temu_setRightmostZeoroBit64(uint64_t Word)
478 {
479  return Word | (Word + 1);
480 }
481 
482 /*!
483  * Isolate left most bit
484  *
485  * \param Word The word, in which the right most set bit will be cleared
486  * \result A copy of word, in which the right most set bit will be cleared
487  */
488 static inline uint32_t
489 temu_isolateLeftmostBit32(uint32_t Word)
490 {
491  return Word & -Word;
492 }
493 
494 /*!
495  * Isolate left most bit
496  *
497  * \param Word The word, in which the right most set bit will be cleared
498  * \result A copy of word, in which the right most set bit will be cleared
499  */
500 static inline uint64_t
501 temu_isolateLeftmostBit64(uint64_t Word)
502 {
503  return Word & -Word;
504 }
505 
506 /*!
507  * Isolate right most bit with value zero (it will be 1 in the result)
508  *
509  * \param Word The word, in which the right most bit with value zero will be
510  * isolated \result A copy of Word, in which the right most bit with value zero
511  * will be isolated
512  */
513 static inline uint32_t
514 temu_isolateRightMostZeroBit32(uint32_t Word)
515 {
516  return (~Word) & (Word + 1);
517 }
518 
519 /*!
520  * Isolate right most bit with value zero (it will be 1 in the result)
521  *
522  * \param Word The word, in which the right most bit with value zero will be
523  * isolated \result A copy of Word, in which the right most bit with value zero
524  * will be isolated
525  */
526 static inline uint64_t
527 temu_isolateRightMostZeroBit64(uint64_t Word)
528 {
529  return (~Word) & (Word + 1);
530 }
531 
532 /*!
533  * Get word with all trailing zeroes set
534  *
535  * \param Word The word, in which trailing zeros to be set
536  * \result A copy of word, with trailing zeros set
537  */
538 static inline uint32_t
539 temu_identifyTrailingZeroes32(uint32_t Word)
540 {
541  return (~Word) & (Word - 1);
542 }
543 
544 /*!
545  * Get word with all trailing zeroes set
546  *
547  * \param Word The word, in which trailing zeros to be set
548  * \result A copy of word, with trailing zeros set
549  */
550 static inline uint64_t
551 temu_identifyTrailingZeroes64(uint64_t Word)
552 {
553  return (~Word) & (Word - 1);
554 }
555 
556 /*!
557  * Get word with all trailing zeroes set, and the fist bit set
558  *
559  * \param Word Word to get trailing zero mask from
560  * \result Word, with all trailing zeroes set, and the fist bit set
561  */
562 static inline uint32_t
563 temu_identifyTrailingZeroesAndFirst32(uint32_t Word)
564 {
565  return Word ^ (Word - 1);
566 }
567 
568 /*!
569  * Get word with all trailing zeroes set, and the fist bit set
570  *
571  * \param Word Word to get trailing zero mask from
572  * \result Word, with all trailing zeroes set, and the fist bit set
573  */
574 static inline uint64_t
575 temu_identifyTrailingZeroesAndFirst64(uint64_t Word)
576 {
577  return Word ^ (Word - 1);
578 }
579 
580 /*!
581  * Propagate the right most set bit to the bits below it
582  *
583  * \param Word Word to propagate bits
584  * \result Word with lower zero-bits set
585  */
586 static inline uint32_t
587 temu_propagateRightMostBit32(uint32_t Word)
588 {
589  return Word | (Word - 1);
590 }
591 
592 /*!
593  * Propagate the right most set bit to the bits below it
594  *
595  * \param Word Word to propagate bits
596  * \result Word with lower zero-bits set
597  */
598 static inline uint64_t
599 temu_propagateRightMostBit64(uint64_t Word)
600 {
601  return Word | (Word - 1);
602 }
603 
604 /*!
605  * Clear right most bit in a word
606  *
607  * \param Word The word, in which right most bit to be cleared
608  * \result A copy of Word, in which right most bit to be cleared
609  */
610 static inline uint32_t
611 temu_clearRightMostBits32(uint32_t Word)
612 {
613  return ((Word | (Word - 1)) + 1) & Word;
614 }
615 
616 /*!
617  * Clear right most bit in a word
618  *
619  * \param Word The word, in which right most bit to be cleared
620  * \result A copy of Word, in which right most bit to be cleared
621  */
622 static inline uint64_t
623 temu_clearRightMostBits64(uint64_t Word)
624 {
625  return ((Word | (Word - 1)) + 1) & Word;
626 }
627 
628 /*!
629  * Round down to multiples of specified power of 2
630  *
631  * \param Word The word to be rounded
632  * \param Size Power of 2 sized block
633  * \result A rounded copy of Word
634  */
635 static inline uint32_t
636 temu_roundDownToPow2_32(uint32_t Word, uint32_t Size)
637 {
638  uint32_t Res = Word & -Size;
639  return Res;
640 }
641 
642 /*!
643  * Round down to multiples of specified power of 2
644  *
645  * \param Word The word to be rounded
646  * \param Size Power of 2 sided block
647  * \result A rounded copy of Word
648  */
649 static inline uint64_t
650 temu_roundDownToPow2_64(uint64_t Word, uint64_t Size)
651 {
652  uint64_t Res = Word & -Size;
653  return Res;
654 }
655 
656 /*!
657  * Round up to multiples of specified power of 2
658  *
659  * \param Word The word to be rounded
660  * \param Size Power of 2 sized block
661  * \result A rounded copy of Word
662  */
663 static inline uint32_t
664 temu_roundUpToPow2_32(uint32_t Word, uint32_t Size)
665 {
666  uint32_t Res = (Word + (Size - 1)) & -Size;
667  return Res;
668 }
669 
670 /*!
671  * Round up to multiples of specified power of 2
672  *
673  * \param Word The word to be rounded
674  * \param Size Power of 2 sized block
675  * \result A rounded copy of Word
676  */
677 static inline uint64_t
678 temu_roundUpToPow2_64(uint64_t Word, uint64_t Size)
679 {
680  uint64_t Res = (Word + (Size - 1)) & -Size;
681  return Res;
682 }
683 
684 /*!
685  * Checks whether A + L crosses power of 2 boundary (e.g. page)
686  *
687  * \param A Address value
688  * \param L Length / offset value
689  * \param Size boundary size (power of 2 size)
690  * \result True if boundary is crossed. False otherwise.
691  */
692 static inline bool
693 temu_crossesBoundary32(uint32_t A, uint32_t L, uint32_t Size)
694 {
695  return -(A | -Size) < L;
696 }
697 
698 /*!
699  * Checks whether A + L crosses power of 2 boundary (e.g. page)
700  *
701  * \param A Address value
702  * \param L Length / offset value
703  * \param Size boundary size (power of 2 size)
704  * \result True if boundary is crossed. False otherwise.
705  */
706 static inline bool
707 temu_crossesBoundary64(uint64_t A, uint64_t L, uint64_t Size)
708 {
709  return -(A | -Size) < L;
710 }
711 
712 /*!
713  * Round up to nearest power of 2
714  *
715  * \param Word The word to be round
716  * \result A copy of Word rounded up to nearest power of 2
717  */
718 static inline uint32_t
719 temu_roundUpNearestPow2_32(uint32_t Word)
720 {
721  uint32_t Res = 1 << (32 - temu_clz32(Word - 1));
722  return Res;
723 }
724 
725 /*!
726  * Round up to nearest power of 2
727  *
728  * \param Word The word to be round
729  * \result A copy of Word rounded up to nearest power of 2
730  */
731 static inline uint64_t
732 temu_roundUpNearestPow2_64(uint64_t Word)
733 {
734  uint64_t Res = UINT64_C(1) << (64 - temu_clz64(Word - 1));
735  return Res;
736 }
737 
738 /*!
739  * Round down to nearest power of 2
740  *
741  * \param Word The word to be round
742  * \result A copy of Word rounded down to nearest power of 2
743  */
744 static inline uint32_t
745 temu_roundDownNearestPow2_32(uint32_t Word)
746 {
747  uint32_t Res = 1 << (31 - temu_clz32(Word));
748  return Res;
749 }
750 
751 /*!
752  * Round up to nearest power of 2
753  *
754  * \param Word The word to be round
755  * \result A copy of Word rounded down to nearest power of 2
756  */
757 static inline uint64_t
758 temu_roundDownNearestPow2_64(uint64_t Word)
759 {
760  uint64_t Res = UINT64_C(1) << (63 - temu_clz64(Word));
761  return Res;
762 }
763 
764 /*!
765  * Reverses bits in a 16 bit word.
766  *
767  * \note that this should be replaced with __buintin_bitreverse16(), but that is
768  * only supported in clang at present, not GCC.
769  *
770  * \param Word The word to reverse the bits in
771  * \result Word with reversed bits.
772  */
773 
774 static inline uint16_t
775 temu_bitreverse16(uint16_t Word)
776 {
777 #if __has_builtin(__builtin_bitreverse16)
778  return __builtin_bitreverse16(Word);
779 #else
780  uint32_t Res = (Word & 0x55555555) << 1 | (Word & 0xaaaaaaaa) >> 1;
781  Res = (Res & 0x33333333) << 2 | (Res & 0xcccccccc) >> 2;
782  Res = (Res & 0x0f0f0f0f) << 4 | (Res & 0xf0f0f0f0) >> 4;
783  Res = (Res & 0x00ff00ff) << 8 | (Res & 0xff00ff00) >> 8;
784  return Res;
785 #endif
786 }
787 
788 /*!
789  * Reverses bits in a 32 bit word.
790  *
791  * \note that this should be replaced with __buintin_bitreverse32(),
792  * but that is only supported in clang at present, not GCC.
793  *
794  * \param Word The word to reverse the bits in
795  * \result Word with reversed bits.
796  */
797 static inline uint32_t
798 temu_bitreverse32(uint32_t Word)
799 {
800 #if __has_builtin(__builtin_bitreverse32)
801  return __builtin_bitreverse32(Word);
802 #else
803  uint32_t Res = (Word & 0x55555555) << 1 | (Word & 0xaaaaaaaa) >> 1;
804  Res = (Res & 0x33333333) << 2 | (Res & 0xcccccccc) >> 2;
805  Res = (Res & 0x0f0f0f0f) << 4 | (Res & 0xf0f0f0f0) >> 4;
806  Res = (Res & 0x00ff00ff) << 8 | (Res & 0xff00ff00) >> 8;
807  Res = (Res & 0x0000ffff) << 16 | (Res & 0xffff0000) >> 16;
808  return Res;
809 #endif
810 }
811 
812 static inline uint64_t
813 temu_bitreverse64(uint64_t DWord)
814 {
815 #if __has_builtin(__builtin_bitreverse64)
816  return __builtin_bitreverse64(DWord);
817 #else
818  uint64_t reversed = (uint64_t)temu_bitreverse32(DWord >> 32) |
819  ((uint64_t)temu_bitreverse32(DWord) << 32);
820  return reversed;
821 #endif
822 }
823 
824 static inline uint64_t
825 temu_signExtend_8_64(uint8_t Val)
826 {
827  return (int64_t)(int8_t)Val;
828 }
829 
830 static inline uint32_t
831 temu_signExtend_8_32(uint8_t Val)
832 {
833  return (int32_t)(int8_t)Val;
834 }
835 
836 static inline uint16_t
837 temu_signExtend_8_16(uint8_t Val)
838 {
839  return (int16_t)(int8_t)Val;
840 }
841 
842 /*!
843  * Checks whether the addition of signed inputs with carry would overflow;
844  * a+b+carry
845  *
846  * \param a is the first input
847  * \param b is the second input
848  * \param carry is the carry; can be either zero or one
849  * \return true if it overflows, false otherwise
850  */
851 static inline uint32_t
852 temu_signed32AddOverflows(uint32_t a, uint32_t b, uint32_t carry)
853 {
854  assert(carry <= 1);
855  return ((((a + b + carry) ^ a) & ((a + b + carry) ^ b)) >> 31) & 1;
856 }
857 
858 static inline uint32_t
859 temu_rotate32Left(uint32_t a, uint32_t steps)
860 {
861 #if __has_builtin(__builtin_rotateleft32)
862  return __builtin_rotateleft32(a, steps);
863 #else
864  return ((a << steps) | (a >> (32 - steps)));
865 #endif
866 }
867 
868 static inline uint32_t
869 temu_rotate32Right(uint32_t a, uint32_t steps)
870 {
871 #if __has_builtin(__builtin_rotateright32)
872  return __builtin_rotateright32(a, steps);
873 #else
874  return ((a >> steps) | (a << (32 - steps)));
875 #endif
876 }
877 
878 #ifdef __cplusplus
879 }
880 #endif
881 
882 #endif /* !TEMU_BITMANIP_H */
__has_builtin
#define __has_builtin(x)
Definition: Bitmanip.h:17