From 6ffb8ffeeed9aca75c278906785a957d72b3ef57 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Sun, 24 Aug 2014 19:46:43 -0400 Subject: 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 --- firmware/export/system.h | 120 +---------------------------- firmware/include/rbendian.h | 168 +++++++++++++++++++++++++++++++++++++++++ firmware/libc/include/endian.h | 59 +++++++++++++++ 3 files changed, 228 insertions(+), 119 deletions(-) create mode 100644 firmware/include/rbendian.h create mode 100644 firmware/libc/include/endian.h diff --git a/firmware/export/system.h b/firmware/export/system.h index 5064fcd91d..4442eb96d7 100644 --- a/firmware/export/system.h +++ b/firmware/export/system.h @@ -133,24 +133,6 @@ int get_cpu_boost_counter(void); #define PTR_ADD(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 */ #ifndef offsetof #define offsetof(type, member) __builtin_offsetof(type, member) @@ -206,111 +188,11 @@ enum { #include "system-target.h" #elif defined(HAVE_SDL) /* SDL build */ #include "system-sdl.h" -#define NEED_GENERIC_BYTESWAPS #elif defined(__PCTOOL__) #include "system-sdl.h" -#define NEED_GENERIC_BYTESWAPS #endif #include "bitswap.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 +#include "rbendian.h" #ifndef BIT_N #define BIT_N(n) (1U << (n)) diff --git a/firmware/include/rbendian.h b/firmware/include/rbendian.h new file mode 100644 index 0000000000..21d3cae68d --- /dev/null +++ b/firmware/include/rbendian.h @@ -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 + +/* 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_ */ diff --git a/firmware/libc/include/endian.h b/firmware/libc/include/endian.h new file mode 100644 index 0000000000..de1c508da7 --- /dev/null +++ b/firmware/libc/include/endian.h @@ -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_ */ -- cgit v1.2.3