OLD | NEW |
1 /* Copyright 2013 Google Inc. All Rights Reserved. | 1 /* Copyright 2013 Google Inc. All Rights Reserved. |
2 | 2 |
3 Distributed under MIT license. | 3 Distributed under MIT license. |
4 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT | 4 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT |
5 */ | 5 */ |
6 | 6 |
7 // Macros for endianness, branch prediction and unaligned loads and stores. | 7 /* Macros for endianness, branch prediction and unaligned loads and stores. */ |
8 | 8 |
9 #ifndef BROTLI_ENC_PORT_H_ | 9 #ifndef BROTLI_ENC_PORT_H_ |
10 #define BROTLI_ENC_PORT_H_ | 10 #define BROTLI_ENC_PORT_H_ |
11 | 11 |
12 #include <assert.h> | 12 #include <assert.h> |
13 #include <string.h> | 13 #include <string.h> /* memcpy */ |
14 #include "./types.h" | 14 |
| 15 #include <brotli/port.h> |
| 16 #include <brotli/types.h> |
15 | 17 |
16 #if defined OS_LINUX || defined OS_CYGWIN | 18 #if defined OS_LINUX || defined OS_CYGWIN |
17 #include <endian.h> | 19 #include <endian.h> |
18 #elif defined OS_FREEBSD | 20 #elif defined OS_FREEBSD |
19 #include <machine/endian.h> | 21 #include <machine/endian.h> |
20 #elif defined OS_MACOSX | 22 #elif defined OS_MACOSX |
21 #include <machine/endian.h> | 23 #include <machine/endian.h> |
22 /* Let's try and follow the Linux convention */ | 24 /* Let's try and follow the Linux convention */ |
23 #define __BYTE_ORDER BYTE_ORDER | 25 #define __BYTE_ORDER BYTE_ORDER |
24 #define __LITTLE_ENDIAN LITTLE_ENDIAN | 26 #define __LITTLE_ENDIAN LITTLE_ENDIAN |
25 #endif | 27 #endif |
26 | 28 |
27 // define the macro IS_LITTLE_ENDIAN | 29 /* define the macro IS_LITTLE_ENDIAN |
28 // using the above endian definitions from endian.h if | 30 using the above endian definitions from endian.h if |
29 // endian.h was included | 31 endian.h was included */ |
30 #ifdef __BYTE_ORDER | 32 #ifdef __BYTE_ORDER |
31 #if __BYTE_ORDER == __LITTLE_ENDIAN | 33 #if __BYTE_ORDER == __LITTLE_ENDIAN |
32 #define IS_LITTLE_ENDIAN | 34 #define IS_LITTLE_ENDIAN |
33 #endif | 35 #endif |
34 | 36 |
35 #else | 37 #else |
36 | 38 |
37 #if defined(__LITTLE_ENDIAN__) | 39 #if defined(__LITTLE_ENDIAN__) |
38 #define IS_LITTLE_ENDIAN | 40 #define IS_LITTLE_ENDIAN |
39 #endif | 41 #endif |
40 #endif // __BYTE_ORDER | 42 #endif /* __BYTE_ORDER */ |
41 | 43 |
42 #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) | 44 #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) |
43 #define IS_LITTLE_ENDIAN | 45 #define IS_LITTLE_ENDIAN |
44 #endif | 46 #endif |
45 | 47 |
46 // Enable little-endian optimization for x64 architecture on Windows. | 48 /* Enable little-endian optimization for x64 architecture on Windows. */ |
47 #if (defined(_WIN32) || defined(_WIN64)) && defined(_M_X64) | 49 #if (defined(_WIN32) || defined(_WIN64)) && defined(_M_X64) |
48 #define IS_LITTLE_ENDIAN | 50 #define IS_LITTLE_ENDIAN |
49 #endif | 51 #endif |
50 | 52 |
51 /* Compatibility with non-clang compilers. */ | 53 /* Portable handling of unaligned loads, stores, and copies. |
52 #ifndef __has_builtin | 54 On some platforms, like ARM, the copy functions can be more efficient |
53 #define __has_builtin(x) 0 | 55 then a load and a store. */ |
54 #endif | |
55 | |
56 #if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || \ | |
57 (defined(__llvm__) && __has_builtin(__builtin_expect)) | |
58 #define PREDICT_FALSE(x) (__builtin_expect(x, 0)) | |
59 #define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) | |
60 #else | |
61 #define PREDICT_FALSE(x) (x) | |
62 #define PREDICT_TRUE(x) (x) | |
63 #endif | |
64 | |
65 // Portable handling of unaligned loads, stores, and copies. | |
66 // On some platforms, like ARM, the copy functions can be more efficient | |
67 // then a load and a store. | |
68 | 56 |
69 #if defined(ARCH_PIII) || \ | 57 #if defined(ARCH_PIII) || \ |
70 defined(ARCH_ATHLON) || defined(ARCH_K8) || defined(_ARCH_PPC) | 58 defined(ARCH_ATHLON) || defined(ARCH_K8) || defined(_ARCH_PPC) |
71 | 59 |
72 // x86 and x86-64 can perform unaligned loads/stores directly; | 60 /* x86 and x86-64 can perform unaligned loads/stores directly; |
73 // modern PowerPC hardware can also do unaligned integer loads and stores; | 61 modern PowerPC hardware can also do unaligned integer loads and stores; |
74 // but note: the FPU still sends unaligned loads and stores to a trap handler! | 62 but note: the FPU still sends unaligned loads and stores to a trap handler! |
| 63 */ |
75 | 64 |
76 #define BROTLI_UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32_t *>(_p)) | 65 #define BROTLI_UNALIGNED_LOAD32(_p) (*(const uint32_t *)(_p)) |
77 #define BROTLI_UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64_t *>(_p)) | 66 #define BROTLI_UNALIGNED_LOAD64(_p) (*(const uint64_t *)(_p)) |
78 | 67 |
79 #define BROTLI_UNALIGNED_STORE32(_p, _val) \ | 68 #define BROTLI_UNALIGNED_STORE32(_p, _val) \ |
80 (*reinterpret_cast<uint32_t *>(_p) = (_val)) | 69 (*(uint32_t *)(_p) = (_val)) |
81 #define BROTLI_UNALIGNED_STORE64(_p, _val) \ | 70 #define BROTLI_UNALIGNED_STORE64(_p, _val) \ |
82 (*reinterpret_cast<uint64_t *>(_p) = (_val)) | 71 (*(uint64_t *)(_p) = (_val)) |
83 | 72 |
84 #elif defined(__arm__) && \ | 73 #elif defined(__arm__) && \ |
85 !defined(__ARM_ARCH_5__) && \ | 74 !defined(__ARM_ARCH_5__) && \ |
86 !defined(__ARM_ARCH_5T__) && \ | 75 !defined(__ARM_ARCH_5T__) && \ |
87 !defined(__ARM_ARCH_5TE__) && \ | 76 !defined(__ARM_ARCH_5TE__) && \ |
88 !defined(__ARM_ARCH_5TEJ__) && \ | 77 !defined(__ARM_ARCH_5TEJ__) && \ |
89 !defined(__ARM_ARCH_6__) && \ | 78 !defined(__ARM_ARCH_6__) && \ |
90 !defined(__ARM_ARCH_6J__) && \ | 79 !defined(__ARM_ARCH_6J__) && \ |
91 !defined(__ARM_ARCH_6K__) && \ | 80 !defined(__ARM_ARCH_6K__) && \ |
92 !defined(__ARM_ARCH_6Z__) && \ | 81 !defined(__ARM_ARCH_6Z__) && \ |
93 !defined(__ARM_ARCH_6ZK__) && \ | 82 !defined(__ARM_ARCH_6ZK__) && \ |
94 !defined(__ARM_ARCH_6T2__) | 83 !defined(__ARM_ARCH_6T2__) |
95 | 84 |
96 // ARMv7 and newer support native unaligned accesses, but only of 16-bit | 85 /* ARMv7 and newer support native unaligned accesses, but only of 16-bit |
97 // and 32-bit values (not 64-bit); older versions either raise a fatal signal, | 86 and 32-bit values (not 64-bit); older versions either raise a fatal signal, |
98 // do an unaligned read and rotate the words around a bit, or do the reads very | 87 do an unaligned read and rotate the words around a bit, or do the reads very |
99 // slowly (trip through kernel mode). | 88 slowly (trip through kernel mode). */ |
100 | 89 |
101 #define BROTLI_UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32_t *>(_p)) | 90 #define BROTLI_UNALIGNED_LOAD32(_p) (*(const uint32_t *)(_p)) |
102 #define BROTLI_UNALIGNED_STORE32(_p, _val) \ | 91 #define BROTLI_UNALIGNED_STORE32(_p, _val) \ |
103 (*reinterpret_cast<uint32_t *>(_p) = (_val)) | 92 (*(uint32_t *)(_p) = (_val)) |
104 | 93 |
105 inline uint64_t BROTLI_UNALIGNED_LOAD64(const void *p) { | 94 static BROTLI_INLINE uint64_t BROTLI_UNALIGNED_LOAD64(const void *p) { |
106 uint64_t t; | 95 uint64_t t; |
107 memcpy(&t, p, sizeof t); | 96 memcpy(&t, p, sizeof t); |
108 return t; | 97 return t; |
109 } | 98 } |
110 | 99 |
111 inline void BROTLI_UNALIGNED_STORE64(void *p, uint64_t v) { | 100 static BROTLI_INLINE void BROTLI_UNALIGNED_STORE64(void *p, uint64_t v) { |
112 memcpy(p, &v, sizeof v); | 101 memcpy(p, &v, sizeof v); |
113 } | 102 } |
114 | 103 |
115 #else | 104 #else |
116 | 105 |
117 // These functions are provided for architectures that don't support | 106 /* These functions are provided for architectures that don't support */ |
118 // unaligned loads and stores. | 107 /* unaligned loads and stores. */ |
119 | 108 |
120 inline uint32_t BROTLI_UNALIGNED_LOAD32(const void *p) { | 109 static BROTLI_INLINE uint32_t BROTLI_UNALIGNED_LOAD32(const void *p) { |
121 uint32_t t; | 110 uint32_t t; |
122 memcpy(&t, p, sizeof t); | 111 memcpy(&t, p, sizeof t); |
123 return t; | 112 return t; |
124 } | 113 } |
125 | 114 |
126 inline uint64_t BROTLI_UNALIGNED_LOAD64(const void *p) { | 115 static BROTLI_INLINE uint64_t BROTLI_UNALIGNED_LOAD64(const void *p) { |
127 uint64_t t; | 116 uint64_t t; |
128 memcpy(&t, p, sizeof t); | 117 memcpy(&t, p, sizeof t); |
129 return t; | 118 return t; |
130 } | 119 } |
131 | 120 |
132 inline void BROTLI_UNALIGNED_STORE32(void *p, uint32_t v) { | 121 static BROTLI_INLINE void BROTLI_UNALIGNED_STORE32(void *p, uint32_t v) { |
133 memcpy(p, &v, sizeof v); | 122 memcpy(p, &v, sizeof v); |
134 } | 123 } |
135 | 124 |
136 inline void BROTLI_UNALIGNED_STORE64(void *p, uint64_t v) { | 125 static BROTLI_INLINE void BROTLI_UNALIGNED_STORE64(void *p, uint64_t v) { |
137 memcpy(p, &v, sizeof v); | 126 memcpy(p, &v, sizeof v); |
138 } | 127 } |
139 | 128 |
140 #endif | 129 #endif |
141 | 130 |
142 #endif // BROTLI_ENC_PORT_H_ | 131 #define TEMPLATE_(T) \ |
| 132 static BROTLI_INLINE T brotli_min_ ## T (T a, T b) { return a < b ? a : b; } \ |
| 133 static BROTLI_INLINE T brotli_max_ ## T (T a, T b) { return a > b ? a : b; } |
| 134 TEMPLATE_(double) TEMPLATE_(float) TEMPLATE_(int) |
| 135 TEMPLATE_(size_t) TEMPLATE_(uint32_t) TEMPLATE_(uint8_t) |
| 136 #undef TEMPLATE_ |
| 137 #define BROTLI_MIN(T, A, B) (brotli_min_ ## T((A), (B))) |
| 138 #define BROTLI_MAX(T, A, B) (brotli_max_ ## T((A), (B))) |
| 139 |
| 140 #define BROTLI_SWAP(T, A, I, J) { \ |
| 141 T __brotli_swap_tmp = (A)[(I)]; \ |
| 142 (A)[(I)] = (A)[(J)]; \ |
| 143 (A)[(J)] = __brotli_swap_tmp; \ |
| 144 } |
| 145 |
| 146 #define BROTLI_ENSURE_CAPACITY(M, T, A, C, R) { \ |
| 147 if (C < (R)) { \ |
| 148 size_t _new_size = (C == 0) ? (R) : C; \ |
| 149 T* new_array; \ |
| 150 while (_new_size < (R)) _new_size *= 2; \ |
| 151 new_array = BROTLI_ALLOC((M), T, _new_size); \ |
| 152 if (!BROTLI_IS_OOM(m) && C != 0) \ |
| 153 memcpy(new_array, A, C * sizeof(T)); \ |
| 154 BROTLI_FREE((M), A); \ |
| 155 A = new_array; \ |
| 156 C = _new_size; \ |
| 157 } \ |
| 158 } |
| 159 |
| 160 #endif /* BROTLI_ENC_PORT_H_ */ |
OLD | NEW |