blob: 4c6b4fe40d3389a807fcc81f8e6021eaffc56164 [file] [log] [blame]
Vikas Aroraaf51b942014-08-28 10:51:12 -07001// Copyright 2014 Google Inc. All Rights Reserved.
2//
3// Use of this source code is governed by a BSD-style license
4// that can be found in the COPYING file in the root of the source
5// tree. An additional intellectual property rights grant can be found
6// in the file PATENTS. All contributing project authors may
7// be found in the AUTHORS file in the root of the source tree.
8// -----------------------------------------------------------------------------
9//
10// Endian related functions.
11
12#ifndef WEBP_UTILS_ENDIAN_INL_H_
13#define WEBP_UTILS_ENDIAN_INL_H_
14
15#ifdef HAVE_CONFIG_H
16#include "webp/config.h"
17#endif
18
19#include "webp/types.h"
20
21// some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__)
22#if !defined(WORDS_BIGENDIAN) && \
23 (defined(__BIG_ENDIAN__) || defined(_M_PPC) || \
24 (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
25#define WORDS_BIGENDIAN
26#endif
27
28#if defined(WORDS_BIGENDIAN)
29#define HToLE32 BSwap32
30#define HToLE16 BSwap16
31#else
32#define HToLE32(x) (x)
33#define HToLE16(x) (x)
34#endif
35
36#if !defined(HAVE_CONFIG_H)
37#ifdef __GNUC__
38# define LOCAL_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__)
39#else
40# define LOCAL_GCC_VERSION 0
41#endif // __GNUC__
42
43#ifdef __clang__
44# define LOCAL_CLANG_VERSION ((__clang_major__ << 8) | __clang_minor__)
45#else
46# define LOCAL_CLANG_VERSION 0
47#endif // __clang__
48
49// clang-3.3 and gcc-4.3 have builtin functions for swap32/swap64
50#if LOCAL_GCC_VERSION >= 0x403 || LOCAL_CLANG_VERSION >= 0x303
51#define HAVE_BUILTIN_BSWAP32
52#define HAVE_BUILTIN_BSWAP64
53#endif
54// clang-3.3 and gcc-4.8 have a builtin function for swap16
55#if LOCAL_GCC_VERSION >= 0x408 || LOCAL_CLANG_VERSION >= 0x303
56#define HAVE_BUILTIN_BSWAP16
57#endif
58#endif // !HAVE_CONFIG_H
59
60static WEBP_INLINE uint16_t BSwap16(uint16_t x) {
61#if defined(HAVE_BUILTIN_BSWAP16)
62 return __builtin_bswap16(x);
63#elif defined(_MSC_VER)
64 return _byteswap_ushort(x);
65#else
66 // gcc will recognize a 'rorw $8, ...' here:
67 return (x >> 8) | ((x & 0xff) << 8);
68#endif // HAVE_BUILTIN_BSWAP16
69}
70
71static WEBP_INLINE uint32_t BSwap32(uint32_t x) {
72#if defined(HAVE_BUILTIN_BSWAP32)
73 return __builtin_bswap32(x);
74#elif defined(__i386__) || defined(__x86_64__)
75 uint32_t swapped_bytes;
76 __asm__ volatile("bswap %0" : "=r"(swapped_bytes) : "0"(x));
77 return swapped_bytes;
78#elif defined(_MSC_VER)
79 return (uint32_t)_byteswap_ulong(x);
80#else
81 return (x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x << 24);
82#endif // HAVE_BUILTIN_BSWAP32
83}
84
85static WEBP_INLINE uint64_t BSwap64(uint64_t x) {
86#if defined(HAVE_BUILTIN_BSWAP64)
87 return __builtin_bswap64(x);
88#elif defined(__x86_64__)
89 uint64_t swapped_bytes;
90 __asm__ volatile("bswapq %0" : "=r"(swapped_bytes) : "0"(x));
91 return swapped_bytes;
92#elif defined(_MSC_VER)
93 return (uint64_t)_byteswap_uint64(x);
94#else // generic code for swapping 64-bit values (suggested by bdb@)
95 x = ((x & 0xffffffff00000000ull) >> 32) | ((x & 0x00000000ffffffffull) << 32);
96 x = ((x & 0xffff0000ffff0000ull) >> 16) | ((x & 0x0000ffff0000ffffull) << 16);
97 x = ((x & 0xff00ff00ff00ff00ull) >> 8) | ((x & 0x00ff00ff00ff00ffull) << 8);
98 return x;
99#endif // HAVE_BUILTIN_BSWAP64
100}
101
102#endif // WEBP_UTILS_ENDIAN_INL_H_