// elfcpp_swap.h -- Handle swapping for elfcpp -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2006-2022 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of elfcpp.
#ifdef HAVE_BYTESWAP_H
#include <byteswap.h>
-#else
+#endif // defined(HAVE_BYTESWAP_H)
+
// Provide our own versions of the byteswap functions.
-inline uint16_t
+#if !HAVE_DECL_BSWAP_16
+static inline uint16_t
bswap_16(uint16_t v)
{
return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
}
+#endif // !HAVE_DECL_BSWAP16
-inline uint32_t
+#if !HAVE_DECL_BSWAP_32
+static inline uint32_t
bswap_32(uint32_t v)
{
return ( ((v & 0xff000000) >> 24)
| ((v & 0x0000ff00) << 8)
| ((v & 0x000000ff) << 24));
}
+#endif // !HAVE_DECL_BSWAP32
-inline uint64_t
+#if !HAVE_DECL_BSWAP_64
+static inline uint64_t
bswap_64(uint64_t v)
{
return ( ((v & 0xff00000000000000ULL) >> 56)
| ((v & 0x000000000000ff00ULL) << 40)
| ((v & 0x00000000000000ffULL) << 56));
}
-#endif // !defined(HAVE_BYTESWAP_H)
+#endif // !HAVE_DECL_BSWAP64
// gcc 4.3 and later provides __builtin_bswap32 and __builtin_bswap64.
}
};
+// Swap_aligned32 is a template based on size and on whether the
+// target is big endian. It defines the type Valtype and the
+// functions readval and writeval. The functions read and write
+// values of the appropriate size out of buffers which may not be
+// 64-bit aligned, but are 32-bit aligned.
+
+template<int size, bool big_endian>
+struct Swap_aligned32
+{
+ typedef typename Valtype_base<size>::Valtype Valtype;
+
+ static inline Valtype
+ readval(const unsigned char* wv)
+ { return Swap<size, big_endian>::readval(
+ reinterpret_cast<const Valtype*>(wv)); }
+
+ static inline void
+ writeval(unsigned char* wv, Valtype v)
+ { Swap<size, big_endian>::writeval(reinterpret_cast<Valtype*>(wv), v); }
+};
+
+template<>
+struct Swap_aligned32<64, true>
+{
+ typedef Valtype_base<64>::Valtype Valtype;
+
+ static inline Valtype
+ readval(const unsigned char* wv)
+ {
+ return ((static_cast<Valtype>(Swap<32, true>::readval(wv)) << 32)
+ | static_cast<Valtype>(Swap<32, true>::readval(wv + 4)));
+ }
+
+ static inline void
+ writeval(unsigned char* wv, Valtype v)
+ {
+ typedef Valtype_base<32>::Valtype Valtype32;
+
+ Swap<32, true>::writeval(wv, static_cast<Valtype32>(v >> 32));
+ Swap<32, true>::writeval(wv + 4, static_cast<Valtype32>(v));
+ }
+};
+
+template<>
+struct Swap_aligned32<64, false>
+{
+ typedef Valtype_base<64>::Valtype Valtype;
+
+ static inline Valtype
+ readval(const unsigned char* wv)
+ {
+ return ((static_cast<Valtype>(Swap<32, false>::readval(wv + 4)) << 32)
+ | static_cast<Valtype>(Swap<32, false>::readval(wv)));
+ }
+
+ static inline void
+ writeval(unsigned char* wv, Valtype v)
+ {
+ typedef Valtype_base<32>::Valtype Valtype32;
+
+ Swap<32, false>::writeval(wv + 4, static_cast<Valtype32>(v >> 32));
+ Swap<32, false>::writeval(wv, static_cast<Valtype32>(v));
+ }
+};
+
} // End namespace elfcpp.
#endif // !defined(ELFCPP_SWAP_H)