TEMU  3.0
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 
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 
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 
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 
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 
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 
108 static inline uint32_t
109 temu_swapBigHost32Half(uint32_t Word)
110 {
111  return temu_swap32Half(Word);
112 }
113 
124 static inline uint64_t
125 temu_swapBigHost64Word(uint64_t DWord)
126 {
127  return temu_swap64Word(DWord);
128 }
129 
140 static inline uint32_t
141 temu_swapLittleHost32Half(uint32_t Word)
142 {
143  return Word;
144 }
145 
156 static inline uint64_t
157 temu_swapLittleHost64Word(uint64_t DWord)
158 {
159  return DWord;
160 }
161 
172 static inline uint16_t
173 temu_swapBigHost16(uint16_t HWord)
174 {
175  return temu_swap16(HWord);
176 }
177 
188 static inline uint32_t
189 temu_swapBigHost32(uint32_t Word)
190 {
191  return temu_swap32(Word);
192 }
193 
204 static inline uint64_t
205 temu_swapBigHost64(uint64_t DWord)
206 {
207  return temu_swap64(DWord);
208 }
209 
220 static inline uint16_t
221 temu_swapLittleHost16(uint16_t HWord)
222 {
223  return HWord;
224 }
225 
236 static inline uint32_t
237 temu_swapLittleHost32(uint32_t Word)
238 {
239  return Word;
240 }
241 
252 static inline uint64_t
253 temu_swapLittleHost64(uint64_t DWord)
254 {
255  return DWord;
256 }
257 
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 
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 
295 static inline int
296 temu_popcount32(uint32_t Word)
297 {
298  int Res = __builtin_popcount(Word);
299  return Res;
300 }
301 
308 static inline int
309 temu_parity32(uint32_t Word)
310 {
311  int Res = __builtin_parity(Word);
312  return Res;
313 }
314 
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 
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 
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 
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 
383 static inline int
384 temu_popcount64(uint64_t Word)
385 {
386  int Res = __builtin_popcountl(Word);
387  return Res;
388 }
389 
396 static inline int
397 temu_parity64(uint64_t Word)
398 {
399  int Res = __builtin_parityl(Word);
400  return Res;
401 }
402 
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 
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 
440 static inline uint32_t
441 temu_clearLeftmostBit32(uint32_t Word)
442 {
443  return Word & (Word - 1);
444 }
445 
452 static inline uint64_t
453 temu_clearLeftmostBit64(uint64_t Word)
454 {
455  return Word & (Word - 1);
456 }
457 
464 static inline uint32_t
465 temu_setRightmostZeroBit32(uint32_t Word)
466 {
467  return Word | (Word + 1);
468 }
469 
476 static inline uint64_t
477 temu_setRightmostZeoroBit64(uint64_t Word)
478 {
479  return Word | (Word + 1);
480 }
481 
488 static inline uint32_t
489 temu_isolateLeftmostBit32(uint32_t Word)
490 {
491  return Word & -Word;
492 }
493 
500 static inline uint64_t
501 temu_isolateLeftmostBit64(uint64_t Word)
502 {
503  return Word & -Word;
504 }
505 
513 static inline uint32_t
514 temu_isolateRightMostZeroBit32(uint32_t Word)
515 {
516  return (~Word) & (Word + 1);
517 }
518 
526 static inline uint64_t
527 temu_isolateRightMostZeroBit64(uint64_t Word)
528 {
529  return (~Word) & (Word + 1);
530 }
531 
538 static inline uint32_t
539 temu_identifyTrailingZeroes32(uint32_t Word)
540 {
541  return (~Word) & (Word - 1);
542 }
543 
550 static inline uint64_t
551 temu_identifyTrailingZeroes64(uint64_t Word)
552 {
553  return (~Word) & (Word - 1);
554 }
555 
562 static inline uint32_t
563 temu_identifyTrailingZeroesAndFirst32(uint32_t Word)
564 {
565  return Word ^ (Word - 1);
566 }
567 
574 static inline uint64_t
575 temu_identifyTrailingZeroesAndFirst64(uint64_t Word)
576 {
577  return Word ^ (Word - 1);
578 }
579 
586 static inline uint32_t
587 temu_propagateRightMostBit32(uint32_t Word)
588 {
589  return Word | (Word - 1);
590 }
591 
598 static inline uint64_t
599 temu_propagateRightMostBit64(uint64_t Word)
600 {
601  return Word | (Word - 1);
602 }
603 
610 static inline uint32_t
611 temu_clearRightMostBits32(uint32_t Word)
612 {
613  return ((Word | (Word - 1)) + 1) & Word;
614 }
615 
622 static inline uint64_t
623 temu_clearRightMostBits64(uint64_t Word)
624 {
625  return ((Word | (Word - 1)) + 1) & Word;
626 }
627 
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 
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 
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 
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 
692 static inline bool
693 temu_crossesBoundary32(uint32_t A, uint32_t L, uint32_t Size)
694 {
695  return -(A | -Size) < L;
696 }
697 
706 static inline bool
707 temu_crossesBoundary64(uint64_t A, uint64_t L, uint64_t Size)
708 {
709  return -(A | -Size) < L;
710 }
711 
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 
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 
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 
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 
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 
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 
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 */