1 /* Copyright 2015 Google Inc. All Rights Reserved.
2 
3    Distributed under MIT license.
4    See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5 */
6 
7 /* Macros for compiler / platform specific features and build options.
8 
9    Build options are:
10     * BROTLI_BUILD_32_BIT disables 64-bit optimizations
11     * BROTLI_BUILD_64_BIT forces to use 64-bit optimizations
12     * BROTLI_BUILD_BIG_ENDIAN forces to use big-endian optimizations
13     * BROTLI_BUILD_ENDIAN_NEUTRAL disables endian-aware optimizations
14     * BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations
15     * BROTLI_BUILD_MODERN_COMPILER forces to use modern compilers built-ins,
16       features and attributes
17     * BROTLI_BUILD_PORTABLE disables dangerous optimizations, like unaligned
18       read and overlapping memcpy; this reduces decompression speed by 5%
19     * BROTLI_BUILD_NO_RBIT disables "rbit" optimization for ARM CPUs
20     * BROTLI_DEBUG dumps file name and line number when decoder detects stream
21       or memory error
22     * BROTLI_ENABLE_LOG enables asserts and dumps various state information
23  */
24 
25 #ifndef BROTLI_DEC_PORT_H_
26 #define BROTLI_DEC_PORT_H_
27 
28 #if defined(BROTLI_ENABLE_LOG) || defined(BROTLI_DEBUG)
29 #include <assert.h>
30 #include <stdio.h>
31 #endif
32 
33 #include <brotli/port.h>
34 
35 #if defined(__arm__) || defined(__thumb__) || \
36     defined(_M_ARM) || defined(_M_ARMT) || defined(__ARM64_ARCH_8__)
37 #define BROTLI_TARGET_ARM
38 #if (defined(__ARM_ARCH) && (__ARM_ARCH == 7)) || \
39     (defined(M_ARM) && (M_ARM == 7))
40 #define BROTLI_TARGET_ARMV7
41 #endif  /* ARMv7 */
42 #if defined(__aarch64__) || defined(__ARM64_ARCH_8__)
43 #define BROTLI_TARGET_ARMV8
44 #endif  /* ARMv8 */
45 #endif  /* ARM */
46 
47 #if defined(__i386) || defined(_M_IX86)
48 #define BROTLI_TARGET_X86
49 #endif
50 
51 #if defined(__x86_64__) || defined(_M_X64)
52 #define BROTLI_TARGET_X64
53 #endif
54 
55 #if defined(__PPC64__)
56 #define BROTLI_TARGET_POWERPC64
57 #endif
58 
59 #ifdef BROTLI_BUILD_PORTABLE
60 #define BROTLI_ALIGNED_READ (!!1)
61 #elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) || \
62      defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8)
63 /* Allow unaligned read only for white-listed CPUs. */
64 #define BROTLI_ALIGNED_READ (!!0)
65 #else
66 #define BROTLI_ALIGNED_READ (!!1)
67 #endif
68 
69 /* IS_CONSTANT macros returns true for compile-time constant expressions. */
70 #if BROTLI_MODERN_COMPILER || __has_builtin(__builtin_constant_p)
71 #define IS_CONSTANT(x) (!!__builtin_constant_p(x))
72 #else
73 #define IS_CONSTANT(x) (!!0)
74 #endif
75 
76 #ifdef BROTLI_ENABLE_LOG
77 #define BROTLI_DCHECK(x) assert(x)
78 #define BROTLI_LOG(x) printf x
79 #else
80 #define BROTLI_DCHECK(x)
81 #define BROTLI_LOG(x)
82 #endif
83 
84 #if defined(BROTLI_DEBUG) || defined(BROTLI_ENABLE_LOG)
BrotliDump(const char * f,int l,const char * fn)85 static BROTLI_INLINE void BrotliDump(const char* f, int l, const char* fn) {
86   fprintf(stderr, "%s:%d (%s)\n", f, l, fn);
87   fflush(stderr);
88 }
89 #define BROTLI_DUMP() BrotliDump(__FILE__, __LINE__, __FUNCTION__)
90 #else
91 #define BROTLI_DUMP() (void)(0)
92 #endif
93 
94 #if defined(BROTLI_BUILD_64_BIT)
95 #define BROTLI_64_BITS 1
96 #elif defined(BROTLI_BUILD_32_BIT)
97 #define BROTLI_64_BITS 0
98 #elif defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8) || \
99     defined(BROTLI_TARGET_POWERPC64)
100 #define BROTLI_64_BITS 1
101 #else
102 #define BROTLI_64_BITS 0
103 #endif
104 
105 #if (BROTLI_64_BITS)
106 #define reg_t uint64_t
107 #else
108 #define reg_t uint32_t
109 #endif
110 
111 #if defined(BROTLI_BUILD_BIG_ENDIAN)
112 #define BROTLI_LITTLE_ENDIAN 0
113 #define BROTLI_BIG_ENDIAN 1
114 #elif defined(BROTLI_BUILD_LITTLE_ENDIAN)
115 #define BROTLI_LITTLE_ENDIAN 1
116 #define BROTLI_BIG_ENDIAN 0
117 #elif defined(BROTLI_BUILD_ENDIAN_NEUTRAL)
118 #define BROTLI_LITTLE_ENDIAN 0
119 #define BROTLI_BIG_ENDIAN 0
120 #elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
121 #define BROTLI_LITTLE_ENDIAN 1
122 #define BROTLI_BIG_ENDIAN 0
123 #elif defined(_WIN32)
124 /* Win32 can currently always be assumed to be little endian */
125 #define BROTLI_LITTLE_ENDIAN 1
126 #define BROTLI_BIG_ENDIAN 0
127 #else
128 #if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
129 #define BROTLI_BIG_ENDIAN 1
130 #else
131 #define BROTLI_BIG_ENDIAN 0
132 #endif
133 #define BROTLI_LITTLE_ENDIAN 0
134 #endif
135 
136 #define BROTLI_REPEAT(N, X) {     \
137   if ((N & 1) != 0) {X;}          \
138   if ((N & 2) != 0) {X; X;}       \
139   if ((N & 4) != 0) {X; X; X; X;} \
140 }
141 
142 #if (BROTLI_MODERN_COMPILER || defined(__llvm__)) && \
143     !defined(BROTLI_BUILD_NO_RBIT)
144 #if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8)
145 /* TODO: detect ARMv6T2 and enable this code for it. */
BrotliRBit(reg_t input)146 static BROTLI_INLINE reg_t BrotliRBit(reg_t input) {
147   reg_t output;
148   __asm__("rbit %0, %1\n" : "=r"(output) : "r"(input));
149   return output;
150 }
151 #define BROTLI_RBIT(x) BrotliRBit(x)
152 #endif  /* armv7 */
153 #endif  /* gcc || clang */
154 
155 #if defined(BROTLI_TARGET_ARM)
156 #define BROTLI_HAS_UBFX (!!1)
157 #else
158 #define BROTLI_HAS_UBFX (!!0)
159 #endif
160 
161 #define BROTLI_ALLOC(S, L) S->alloc_func(S->memory_manager_opaque, L)
162 
163 #define BROTLI_FREE(S, X) {                  \
164   S->free_func(S->memory_manager_opaque, X); \
165   X = NULL;                                  \
166 }
167 
168 #endif  /* BROTLI_DEC_PORT_H_ */
169