port.h revision 65f3fc55f562452e64156525d5dc0fcd9fbaf898
1c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// Copyright 2013 Google Inc. All Rights Reserved. 2c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// 3c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// Licensed under the Apache License, Version 2.0 (the "License"); 4c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// you may not use this file except in compliance with the License. 5c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// You may obtain a copy of the License at 6c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// 7c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// http://www.apache.org/licenses/LICENSE-2.0 8c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// 9c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// Unless required by applicable law or agreed to in writing, software 10c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// distributed under the License is distributed on an "AS IS" BASIS, 11c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// See the License for the specific language governing permissions and 13c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// limitations under the License. 14c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// 15c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// Macros for endianness, branch prediction and unaligned loads and stores. 16c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 17c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#ifndef BROTLI_ENC_PORT_H_ 18c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define BROTLI_ENC_PORT_H_ 19c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 2065f3fc55f562452e64156525d5dc0fcd9fbaf898Zoltan Szabadka#include <string.h> 2165f3fc55f562452e64156525d5dc0fcd9fbaf898Zoltan Szabadka 22c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#if defined OS_LINUX || defined OS_CYGWIN 23c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#include <endian.h> 24c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#elif defined OS_FREEBSD 25c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#include <machine/endian.h> 26c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#elif defined OS_MACOSX 27c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#include <machine/endian.h> 28c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka/* Let's try and follow the Linux convention */ 29c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define __BYTE_ORDER BYTE_ORDER 30c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define __LITTLE_ENDIAN LITTLE_ENDIAN 31c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define __BIG_ENDIAN BIG_ENDIAN 32c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#endif 33c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 34c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// define the macros IS_LITTLE_ENDIAN or IS_BIG_ENDIAN 35c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// using the above endian definitions from endian.h if 36c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// endian.h was included 37c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#ifdef __BYTE_ORDER 38c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#if __BYTE_ORDER == __LITTLE_ENDIAN 39c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define IS_LITTLE_ENDIAN 40c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#endif 41c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 42c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#if __BYTE_ORDER == __BIG_ENDIAN 43c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define IS_BIG_ENDIAN 44c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#endif 45c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 46c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#else 47c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 48c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#if defined(__LITTLE_ENDIAN__) 49c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define IS_LITTLE_ENDIAN 50c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#elif defined(__BIG_ENDIAN__) 51c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define IS_BIG_ENDIAN 52c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#endif 53c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#endif // __BYTE_ORDER 54c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 55f0b88cbcdb1983bbcd680e6f0de8a21924eb025cZoltan Szabadka// Enable little-endian optimization for x64 architecture on Windows. 56f0b88cbcdb1983bbcd680e6f0de8a21924eb025cZoltan Szabadka#if (defined(_WIN32) || defined(_WIN64)) && defined(_M_X64) 57f0b88cbcdb1983bbcd680e6f0de8a21924eb025cZoltan Szabadka#define IS_LITTLE_ENDIAN 58f0b88cbcdb1983bbcd680e6f0de8a21924eb025cZoltan Szabadka#endif 59f0b88cbcdb1983bbcd680e6f0de8a21924eb025cZoltan Szabadka 6083aa24dc8686b62177d776a3baab5f69badc1a78Zoltan Szabadka/* Compatibility with non-clang compilers. */ 6183aa24dc8686b62177d776a3baab5f69badc1a78Zoltan Szabadka#ifndef __has_builtin 6283aa24dc8686b62177d776a3baab5f69badc1a78Zoltan Szabadka#define __has_builtin(x) 0 6383aa24dc8686b62177d776a3baab5f69badc1a78Zoltan Szabadka#endif 6483aa24dc8686b62177d776a3baab5f69badc1a78Zoltan Szabadka 6583aa24dc8686b62177d776a3baab5f69badc1a78Zoltan Szabadka#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || \ 6683aa24dc8686b62177d776a3baab5f69badc1a78Zoltan Szabadka (defined(__llvm__) && __has_builtin(__builtin_expect)) 67c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define PREDICT_FALSE(x) (__builtin_expect(x, 0)) 68c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) 69c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#else 7083aa24dc8686b62177d776a3baab5f69badc1a78Zoltan Szabadka#define PREDICT_FALSE(x) (x) 7183aa24dc8686b62177d776a3baab5f69badc1a78Zoltan Szabadka#define PREDICT_TRUE(x) (x) 72c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#endif 73c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 74c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// Portable handling of unaligned loads, stores, and copies. 75c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// On some platforms, like ARM, the copy functions can be more efficient 76c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// then a load and a store. 77c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 78c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#if defined(ARCH_PIII) || defined(ARCH_ATHLON) || \ 79c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka defined(ARCH_K8) || defined(_ARCH_PPC) 80c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 81c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// x86 and x86-64 can perform unaligned loads/stores directly; 82c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// modern PowerPC hardware can also do unaligned integer loads and stores; 83c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// but note: the FPU still sends unaligned loads and stores to a trap handler! 84c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 85c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define BROTLI_UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32_t *>(_p)) 86c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define BROTLI_UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64_t *>(_p)) 87c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 88c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define BROTLI_UNALIGNED_STORE32(_p, _val) \ 89c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka (*reinterpret_cast<uint32_t *>(_p) = (_val)) 90c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define BROTLI_UNALIGNED_STORE64(_p, _val) \ 91c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka (*reinterpret_cast<uint64_t *>(_p) = (_val)) 92c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 93c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#elif defined(__arm__) && \ 94c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka !defined(__ARM_ARCH_5__) && \ 95c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka !defined(__ARM_ARCH_5T__) && \ 96c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka !defined(__ARM_ARCH_5TE__) && \ 97c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka !defined(__ARM_ARCH_5TEJ__) && \ 98c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka !defined(__ARM_ARCH_6__) && \ 99c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka !defined(__ARM_ARCH_6J__) && \ 100c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka !defined(__ARM_ARCH_6K__) && \ 101c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka !defined(__ARM_ARCH_6Z__) && \ 102c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka !defined(__ARM_ARCH_6ZK__) && \ 103c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka !defined(__ARM_ARCH_6T2__) 104c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 105c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// ARMv7 and newer support native unaligned accesses, but only of 16-bit 106c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// and 32-bit values (not 64-bit); older versions either raise a fatal signal, 107c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// do an unaligned read and rotate the words around a bit, or do the reads very 108c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// slowly (trip through kernel mode). 109c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 110c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define BROTLI_UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32_t *>(_p)) 111c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define BROTLI_UNALIGNED_STORE32(_p, _val) \ 112c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka (*reinterpret_cast<uint32_t *>(_p) = (_val)) 113c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 114c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadkainline uint64_t BROTLI_UNALIGNED_LOAD64(const void *p) { 115c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka uint64_t t; 116c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka memcpy(&t, p, sizeof t); 117c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka return t; 118c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka} 119c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 120c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadkainline void BROTLI_UNALIGNED_STORE64(void *p, uint64_t v) { 121c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka memcpy(p, &v, sizeof v); 122c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka} 123c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 124c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#else 125c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 126c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// These functions are provided for architectures that don't support 127c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// unaligned loads and stores. 128c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 129c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadkainline uint32_t BROTLI_UNALIGNED_LOAD32(const void *p) { 130c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka uint32_t t; 131c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka memcpy(&t, p, sizeof t); 132c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka return t; 133c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka} 134c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 135c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadkainline uint64_t BROTLI_UNALIGNED_LOAD64(const void *p) { 136c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka uint64_t t; 137c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka memcpy(&t, p, sizeof t); 138c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka return t; 139c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka} 140c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 141c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadkainline void BROTLI_UNALIGNED_STORE32(void *p, uint32_t v) { 142c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka memcpy(p, &v, sizeof v); 143c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka} 144c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 145c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadkainline void BROTLI_UNALIGNED_STORE64(void *p, uint64_t v) { 146c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka memcpy(p, &v, sizeof v); 147c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka} 148c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 149c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#endif 150c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka 151c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#endif // BROTLI_ENC_PORT_H_ 152