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) 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. */ 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