… | |
… | |
29 | #ifndef ECB_H |
29 | #ifndef ECB_H |
30 | #define ECB_H |
30 | #define ECB_H |
31 | |
31 | |
32 | #define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))) |
32 | #define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))) |
33 | |
33 | |
|
|
34 | #define ECB_HEADER_INLINE static inline |
|
|
35 | |
34 | #if ECB_GCC_VERSION(3,1) |
36 | #if ECB_GCC_VERSION(3,1) |
35 | # define ecb_attribute(attrlist) __attribute__(attrlist) |
37 | # define ecb_attribute(attrlist) __attribute__(attrlist) |
36 | # define ecb_is_constant(c) __builtin_constant_p (c) |
38 | # define ecb_is_constant(c) __builtin_constant_p (c) |
37 | # define ecb_expect(expr,value) __builtin_expect ((expr),(value)) |
39 | # define ecb_expect(expr,value) __builtin_expect ((expr),(value)) |
38 | # define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality) |
40 | # define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality) |
… | |
… | |
59 | #define ecb_cold ecb_attribute ((cold)) // 4.3 |
61 | #define ecb_cold ecb_attribute ((cold)) // 4.3 |
60 | |
62 | |
61 | #if ECB_GCC_VERSION(4,5) |
63 | #if ECB_GCC_VERSION(4,5) |
62 | # define ecb_unreachable() __builtin_unreachable () |
64 | # define ecb_unreachable() __builtin_unreachable () |
63 | #else |
65 | #else |
64 | // this seems to work fine, but gcc always emits a warning for it :/ |
66 | /* this seems to work fine, but gcc always emits a warning for it :/ */ |
65 | static inline void ecb_unreachable () ecb_attribute ((noreturn)); |
67 | ECB_HEADER_INLINE void ecb_unreachable () ecb_attribute ((noreturn)); |
66 | static inline void ecb_unreachable () { } |
68 | ECB_HEADER_INLINE void ecb_unreachable () { } |
67 | #endif |
69 | #endif |
68 | |
70 | |
69 | // put into ifs if you are very sure that the expression |
71 | /* put into ifs if you are very sure that the expression */ |
70 | // is mostly true or mosty false. note that these return |
72 | /* is mostly true or mosty false. note that these return */ |
71 | // booleans, not the expression. |
73 | /* booleans, not the expression. */ |
72 | #define ecb_expect_false(expr) ecb_expect ((expr) ? 1 : 0, 0) |
74 | #define ecb_expect_false(expr) ecb_expect ((expr) ? 1 : 0, 0) |
73 | #define ecb_expect_true(expr) ecb_expect ((expr) ? 1 : 0, 1) |
75 | #define ecb_expect_true(expr) ecb_expect ((expr) ? 1 : 0, 1) |
74 | |
76 | |
75 | // try to tell the compiler that some condition is definitely true |
77 | /* try to tell the compiler that some condition is definitely true */ |
76 | #define ecb_assume(cond) do { if (!(cond)) unreachable (); } while (0) |
78 | #define ecb_assume(cond) do { if (!(cond)) unreachable (); } while (0) |
77 | |
79 | |
78 | // count trailing zero bits and count # of one bits |
80 | /* count trailing zero bits and count # of one bits */ |
79 | #if ECB_GCC_VERSION(3,4) |
81 | #if ECB_GCC_VERSION(3,4) |
80 | static inline int ecb_ctz (unsigned int x) { return __builtin_ctz (x); } |
82 | ECB_HEADER_INLINE int ecb_ctz (unsigned int x) { return __builtin_ctz (x); } |
81 | static inline int ecb_popcount (unsigned int x) { return __builtin_popcount (x); } |
83 | ECB_HEADER_INLINE int ecb_popcount (unsigned int x) { return __builtin_popcount (x); } |
82 | #else |
84 | #else |
|
|
85 | ECB_HEADER_INLINE |
83 | static int ecb_ctz (unsigned int x) ecb_const |
86 | ecb_ctz (unsigned int x) ecb_const |
84 | { |
87 | { |
85 | int r = 0; |
88 | int r = 0; |
86 | |
89 | |
87 | x &= -x; // this isolates the lowest bit |
90 | x &= -x; // this isolates the lowest bit |
88 | |
91 | |
… | |
… | |
93 | if (x & 0xffff0000) r += 16; |
96 | if (x & 0xffff0000) r += 16; |
94 | |
97 | |
95 | return r; |
98 | return r; |
96 | } |
99 | } |
97 | |
100 | |
|
|
101 | ECB_HEADER_INLINE |
98 | static int ecb_popcount (unsigned int x) ecb_const |
102 | ecb_popcount (unsigned int x) ecb_const |
99 | { |
103 | { |
100 | x -= (x >> 1) & 0x55555555; |
104 | x -= (x >> 1) & 0x55555555; |
101 | x = ((x >> 2) & 0x33333333) + (x & 0x33333333); |
105 | x = ((x >> 2) & 0x33333333) + (x & 0x33333333); |
102 | x = ((x >> 4) + x) & 0x0f0f0f0f; |
106 | x = ((x >> 4) + x) & 0x0f0f0f0f; |
103 | x *= 0x01010101; |
107 | x *= 0x01010101; |
104 | |
108 | |
105 | return x >> 24; |
109 | return x >> 24; |
106 | } |
110 | } |
107 | #endif |
111 | #endif |
108 | |
112 | |
|
|
113 | ECB_HEADER_INLINE unsigned char |
|
|
114 | ecb_byteorder_helper () ecb_const |
|
|
115 | { |
|
|
116 | const uint32_t u = 0x11223344; |
|
|
117 | return *(unsigned char *)&u; |
|
|
118 | } |
|
|
119 | |
|
|
120 | ECB_HEADER_INLINE bool ecb_big_endian () ecb_const { return ecb_byteorder_helper () == 0x11; }; |
|
|
121 | ECB_HEADER_INLINE bool ecb_network () ecb_const { return big_endian (); }; |
|
|
122 | ECB_HEADER_INLINE bool ecb_little_endian () ecb_const { return ecb_byteorder_helper () == 0x44; }; |
|
|
123 | ECB_HEADER_INLINE bool ecb_vax () ecb_const { return little_endian (); }; |
|
|
124 | |
|
|
125 | |
109 | #endif |
126 | #endif |
110 | |
127 | |