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