Do a better endian.h setup that isn't as fragile

We redefine the top-level macros to our own in order to maintain
compatibility with compound initializers by wrapping the mid or low
level definitions from the OS header.

This allows, hopefully optimized, macros from the host OS's headers to
be used when building any hosted target obviating the need for
NEED_GENERIC_BYTESWAPS unless the target simply doesn't define its
own optimized versions (MIPS!).

Throw in some 64-bit swaps for completeness' sake; they generate no code
if not yet used anyway.

Change-Id: I21b384b55fea46833d01ea3cad1ad8952ea01a11
This commit is contained in:
Michael Sevakis 2014-08-24 19:46:43 -04:00
parent d3cf366868
commit 6ffb8ffeee
3 changed files with 228 additions and 119 deletions

View file

@ -133,24 +133,6 @@ int get_cpu_boost_counter(void);
#define PTR_ADD(ptr, x) ((typeof(ptr))((char*)(ptr) + (x))) #define PTR_ADD(ptr, x) ((typeof(ptr))((char*)(ptr) + (x)))
#define PTR_SUB(ptr, x) ((typeof(ptr))((char*)(ptr) - (x))) #define PTR_SUB(ptr, x) ((typeof(ptr))((char*)(ptr) - (x)))
/* newer? SDL includes endian.h, So we ignore it */
#if (CONFIG_PLATFORM & PLATFORM_HOSTED) || defined(__PCTOOL__)
#undef letoh16
#undef letoh32
#undef htole16
#undef htole32
#undef betoh16
#undef betoh32
#undef htobe16
#undef htobe32
#endif
/* Android NDK contains swap16 and swap32, ignore them */
#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
#undef swap16
#undef swap32
#endif
/* Get the byte offset of a type's member */ /* Get the byte offset of a type's member */
#ifndef offsetof #ifndef offsetof
#define offsetof(type, member) __builtin_offsetof(type, member) #define offsetof(type, member) __builtin_offsetof(type, member)
@ -206,111 +188,11 @@ enum {
#include "system-target.h" #include "system-target.h"
#elif defined(HAVE_SDL) /* SDL build */ #elif defined(HAVE_SDL) /* SDL build */
#include "system-sdl.h" #include "system-sdl.h"
#define NEED_GENERIC_BYTESWAPS
#elif defined(__PCTOOL__) #elif defined(__PCTOOL__)
#include "system-sdl.h" #include "system-sdl.h"
#define NEED_GENERIC_BYTESWAPS
#endif #endif
#include "bitswap.h" #include "bitswap.h"
#include "rbendian.h"
#ifdef NEED_GENERIC_BYTESWAPS
static inline uint16_t swap16_hw(uint16_t value)
/*
result[15..8] = value[ 7..0];
result[ 7..0] = value[15..8];
*/
{
return (value >> 8) | (value << 8);
}
static inline uint32_t swap32_hw(uint32_t value)
/*
result[31..24] = value[ 7.. 0];
result[23..16] = value[15.. 8];
result[15.. 8] = value[23..16];
result[ 7.. 0] = value[31..24];
*/
{
uint32_t hi = swap16_hw(value >> 16);
uint32_t lo = swap16_hw(value & 0xffff);
return (lo << 16) | hi;
}
static inline uint32_t swap_odd_even32_hw(uint32_t value)
{
/*
result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
*/
uint32_t t = value & 0xff00ff00;
return (t >> 8) | ((t ^ value) << 8);
}
static inline uint32_t swaw32_hw(uint32_t value)
{
/*
result[31..16] = value[15.. 0];
result[15.. 0] = value[31..16];
*/
return (value >> 16) | (value << 16);
}
#endif /* NEED_GENERIC_BYTESWAPS */
/* static endianness conversion */
#define SWAP16_CONST(x) \
((typeof(x))( ((uint16_t)(x) >> 8) | ((uint16_t)(x) << 8) ))
#define SWAP32_CONST(x) \
((typeof(x))( ((uint32_t)(x) >> 24) | \
(((uint32_t)(x) & 0xff0000) >> 8) | \
(((uint32_t)(x) & 0xff00) << 8) | \
((uint32_t)(x) << 24) ))
#define SWAP_ODD_EVEN32_CONST(x) \
((typeof(x))( ((uint32_t)SWAP16_CONST((uint32_t)(x) >> 16) << 16) | \
SWAP16_CONST((uint32_t)(x))) )
#define SWAW32_CONST(x) \
((typeof(x))( ((uint32_t)(x) << 16) | ((uint32_t)(x) >> 16) ))
/* Select best method based upon whether x is a constant expression */
#define swap16(x) \
( __builtin_constant_p(x) ? SWAP16_CONST(x) : (typeof(x))swap16_hw(x) )
#define swap32(x) \
( __builtin_constant_p(x) ? SWAP32_CONST(x) : (typeof(x))swap32_hw(x) )
#define swap_odd_even32(x) \
( __builtin_constant_p(x) ? SWAP_ODD_EVEN32_CONST(x) : (typeof(x))swap_odd_even32_hw(x) )
#define swaw32(x) \
( __builtin_constant_p(x) ? SWAW32_CONST(x) : (typeof(x))swaw32_hw(x) )
#ifdef ROCKBOX_LITTLE_ENDIAN
#define letoh16(x) (x)
#define letoh32(x) (x)
#define htole16(x) (x)
#define htole32(x) (x)
#define betoh16(x) swap16(x)
#define betoh32(x) swap32(x)
#define htobe16(x) swap16(x)
#define htobe32(x) swap32(x)
#define swap_odd_even_be32(x) (x)
#define swap_odd_even_le32(x) swap_odd_even32(x)
#else
#define letoh16(x) swap16(x)
#define letoh32(x) swap32(x)
#define htole16(x) swap16(x)
#define htole32(x) swap32(x)
#define betoh16(x) (x)
#define betoh32(x) (x)
#define htobe16(x) (x)
#define htobe32(x) (x)
#define swap_odd_even_be32(x) swap_odd_even32(x)
#define swap_odd_even_le32(x) (x)
#endif
#ifndef BIT_N #ifndef BIT_N
#define BIT_N(n) (1U << (n)) #define BIT_N(n) (1U << (n))

168
firmware/include/rbendian.h Normal file
View file

@ -0,0 +1,168 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Alan Korr
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef _RBENDIAN_H_
#define _RBENDIAN_H_
#include "config.h"
#include <endian.h>
/* clear these out since we redefine them to be truely constant compatible */
#undef swap16
#undef swap32
#undef swap64
#undef letoh16
#undef letoh32
#undef letoh64
#undef htole16
#undef htole32
#undef htole64
#undef betoh16
#undef betoh32
#undef betoh64
#undef htobe16
#undef htobe32
#undef htobe64
#ifndef __ENDIAN_H_NATIVE_RB
#if defined (__bswap_16)
#define __swap16_os(x) __bswap_16(x)
#define __swap32_os(x) __bswap_32(x)
#define __swap64_os(x) __bswap_64(x)
#elif defined (__swap16)
#define __swap16_os(x) __swap16(x)
#define __swap32_os(x) __swap32(x)
#define __swap64_os(x) __swap64(x)
#else
#error "Missing OS swap defines."
#endif
/* wrap these because they aren't compatible with compound initializers */
static FORCE_INLINE uint16_t swap16_hw(uint16_t x)
{ return __swap16_os(x); }
static FORCE_INLINE uint32_t swap32_hw(uint32_t x)
{ return __swap32_os(x); }
static FORCE_INLINE uint64_t swap64_hw(uint64_t x)
{ return __swap64_os(x); }
#endif /* __ENDIAN_H_NATIVE_RB */
#if defined(NEED_GENERIC_BYTESWAPS) || !defined(__ENDIAN_H_NATIVE_RB)
/* these are uniquely ours it seems */
static inline uint32_t swap_odd_even32_hw(uint32_t value)
/*
* result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
* result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
*/
{
uint32_t t = value & 0xff00ff00;
return (t >> 8) | ((t ^ value) << 8);
}
static inline uint32_t swaw32_hw(uint32_t value)
/*
* result[31..16] = value[15.. 0];
* result[15.. 0] = value[31..16];
*/
{
return (value >> 16) | (value << 16);
}
#endif /* Generic */
/* static endianness conversion */
#define SWAP16_CONST(x) \
((typeof(x))( ((uint16_t)(x) >> 8) | ((uint16_t)(x) << 8) ))
#define SWAP32_CONST(x) \
((typeof(x))( (((uint32_t)(x) & 0xff000000) >> 24) | \
(((uint32_t)(x) & 0x00ff0000) >> 8) | \
(((uint32_t)(x) & 0x0000ff00) << 8) | \
(((uint32_t)(x) & 0x000000ff) << 24) ))
#define SWAP64_CONST(x) \
((typeof(x))( (((uint64_t)(x) & 0xff00000000000000ull) >> 56) | \
(((uint64_t)(x) & 0x00ff000000000000ull) >> 40) | \
(((uint64_t)(x) & 0x0000ff0000000000ull) >> 24) | \
(((uint64_t)(x) & 0x000000ff00000000ull) >> 8) | \
(((uint64_t)(x) & 0x00000000ff000000ull) << 8) | \
(((uint64_t)(x) & 0x0000000000ff0000ull) << 24) | \
(((uint64_t)(x) & 0x000000000000ff00ull) << 40) | \
(((uint64_t)(x) & 0x00000000000000ffull) << 56) ))
#define SWAP_ODD_EVEN32_CONST(x) \
((typeof(x))( ((uint32_t)SWAP16_CONST((uint32_t)(x) >> 16) << 16) | \
SWAP16_CONST((uint32_t)(x))) )
#define SWAW32_CONST(x) \
((typeof(x))( ((uint32_t)(x) << 16) | ((uint32_t)(x) >> 16) ))
/* select best method based upon whether x is a constant expression */
#define swap16(x) \
( __builtin_constant_p(x) ? SWAP16_CONST(x) : (typeof(x))swap16_hw(x) )
#define swap32(x) \
( __builtin_constant_p(x) ? SWAP32_CONST(x) : (typeof(x))swap32_hw(x) )
#define swap64(x) \
( __builtin_constant_p(x) ? SWAP64_CONST(x) : (typeof(x))swap64_hw(x) )
#define swap_odd_even32(x) \
( __builtin_constant_p(x) ? SWAP_ODD_EVEN32_CONST(x) : (typeof(x))swap_odd_even32_hw(x) )
#define swaw32(x) \
( __builtin_constant_p(x) ? SWAW32_CONST(x) : (typeof(x))swaw32_hw(x) )
#if defined(ROCKBOX_LITTLE_ENDIAN)
#define letoh16(x) (x)
#define letoh32(x) (x)
#define letoh64(x) (x)
#define htole16(x) (x)
#define htole32(x) (x)
#define htole64(x) (x)
#define betoh16(x) swap16(x)
#define betoh32(x) swap32(x)
#define betoh64(x) swap64(x)
#define htobe16(x) swap16(x)
#define htobe32(x) swap32(x)
#define htobe64(x) swap64(x)
#define swap_odd_even_be32(x) (x)
#define swap_odd_even_le32(x) swap_odd_even32(x)
#elif defined(ROCKBOX_BIG_ENDIAN)
#define letoh16(x) swap16(x)
#define letoh32(x) swap32(x)
#define letoh64(x) swap64(x)
#define htole16(x) swap16(x)
#define htole32(x) swap32(x)
#define htole64(x) swap64(x)
#define betoh16(x) (x)
#define betoh32(x) (x)
#define betoh64(x) (x)
#define htobe16(x) (x)
#define htobe32(x) (x)
#define htobe64(x) (x)
#define swap_odd_even_be32(x) swap_odd_even32(x)
#define swap_odd_even_le32(x) (x)
#else
#error "Unknown endianness!"
#endif
#endif /* _RBENDIAN_H_ */

View file

@ -0,0 +1,59 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Alan Korr
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef _ENDIAN_H_
#define _ENDIAN_H_
#ifndef _RBENDIAN_H_
/* this only defines what may be substituted in the native endian.h */
#error "Include rbendian.h instead."
#endif
#define __ENDIAN_H_NATIVE_RB
#ifdef NEED_GENERIC_BYTESWAPS
static inline uint16_t swap16_hw(uint16_t value)
/*
* result[15..8] = value[ 7..0];
* result[ 7..0] = value[15..8];
*/
{
return (value >> 8) | (value << 8);
}
static inline uint32_t swap32_hw(uint32_t value)
/*
* result[31..24] = value[ 7.. 0];
* result[23..16] = value[15.. 8];
* result[15.. 8] = value[23..16];
* result[ 7.. 0] = value[31..24];
*/
{
uint32_t hi = swap16_hw(value >> 16);
uint32_t lo = swap16_hw(value & 0xffff);
return (lo << 16) | hi;
}
#endif /* NEED_GENERIC_BYTESWAPS */
static FORCE_INLINE uint64_t swap64_hw(uint64_t x)
{ return swap32_hw((uint32_t)(x >> 32)) |
((uint64_t)swap32_hw((uint32_t)x) << 32); }
#endif /* _ENDIAN_H_ */