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