llvm-6502/include/llvm/Support/Endian.h

229 lines
7.8 KiB
C++

//===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares generic functions to read and write endian specific data.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_ENDIAN_H
#define LLVM_SUPPORT_ENDIAN_H
#include "llvm/Config/config.h"
#include "llvm/System/SwapByteOrder.h"
#include "llvm/Support/type_traits.h"
namespace llvm {
namespace support {
enum endianness {big, little};
enum alignment {unaligned, aligned};
template<typename value_type, int host, int target>
static typename enable_if_c<host == target, value_type>::type
SwapByteOrderIfDifferent(value_type value) {
// Target endianess is the same as the host. Just pass the value through.
return value;
}
template<typename value_type, int host, int target>
static typename enable_if_c<host != target, value_type>::type
SwapByteOrderIfDifferent(value_type value) {
return sys::SwapByteOrder<value_type>(value);
}
namespace detail {
template<typename value_type, alignment align>
struct alignment_access_helper;
template<typename value_type>
struct alignment_access_helper<value_type, aligned>
{
value_type val;
};
// Provides unaligned loads and stores.
#pragma pack(push)
#pragma pack(1)
template<typename value_type>
struct alignment_access_helper<value_type, unaligned>
{
value_type val;
};
#pragma pack(pop)
} // end namespace detail
#if defined(LLVM_IS_HOST_BIG_ENDIAN) \
|| defined(_BIG_ENDIAN) || defined(__BIG_ENDIAN__)
static const endianness host_endianness = big;
#else
static const endianness host_endianness = little;
#endif
struct endian {
template<typename value_type, alignment align>
static value_type read_le(const void *memory) {
return SwapByteOrderIfDifferent<value_type, host_endianness, little>(
reinterpret_cast<const detail::alignment_access_helper
<value_type, align> *>(memory)->val);
}
template<typename value_type, alignment align>
static void write_le(void *memory, value_type value) {
reinterpret_cast<detail::alignment_access_helper<value_type, align> *>
(memory)->val =
SwapByteOrderIfDifferent< value_type
, host_endianness
, little>(value);
}
template<typename value_type, alignment align>
static value_type read_be(const void *memory) {
return SwapByteOrderIfDifferent<value_type, host_endianness, big>(
reinterpret_cast<const detail::alignment_access_helper
<value_type, align> *>(memory)->val);
}
template<typename value_type, alignment align>
static void write_be(void *memory, value_type value) {
reinterpret_cast<detail::alignment_access_helper
<value_type, align> *>(memory)->val =
SwapByteOrderIfDifferent< value_type
, host_endianness
, big>(value);
}
};
namespace detail {
template<typename value_type,
endianness target_endianness,
alignment target_alignment>
class packed_endian_specific_integral;
template<typename value_type>
class packed_endian_specific_integral<value_type, little, unaligned> {
public:
operator value_type() const {
return endian::read_le<value_type, unaligned>(Value);
}
private:
uint8_t Value[sizeof(value_type)];
};
template<typename value_type>
class packed_endian_specific_integral<value_type, big, unaligned> {
public:
operator value_type() const {
return endian::read_be<value_type, unaligned>(Value);
}
private:
uint8_t Value[sizeof(value_type)];
};
template<typename value_type>
class packed_endian_specific_integral<value_type, little, aligned> {
public:
operator value_type() const {
return endian::read_le<value_type, aligned>(&Value);
}
private:
value_type Value;
};
template<typename value_type>
class packed_endian_specific_integral<value_type, big, aligned> {
public:
operator value_type() const {
return endian::read_be<value_type, aligned>(&Value);
}
private:
value_type Value;
};
} // end namespace detail
typedef detail::packed_endian_specific_integral
<uint8_t, little, unaligned> ulittle8_t;
typedef detail::packed_endian_specific_integral
<uint16_t, little, unaligned> ulittle16_t;
typedef detail::packed_endian_specific_integral
<uint32_t, little, unaligned> ulittle32_t;
typedef detail::packed_endian_specific_integral
<uint64_t, little, unaligned> ulittle64_t;
typedef detail::packed_endian_specific_integral
<int8_t, little, unaligned> little8_t;
typedef detail::packed_endian_specific_integral
<int16_t, little, unaligned> little16_t;
typedef detail::packed_endian_specific_integral
<int32_t, little, unaligned> little32_t;
typedef detail::packed_endian_specific_integral
<int64_t, little, unaligned> little64_t;
typedef detail::packed_endian_specific_integral
<uint8_t, little, aligned> aligned_ulittle8_t;
typedef detail::packed_endian_specific_integral
<uint16_t, little, aligned> aligned_ulittle16_t;
typedef detail::packed_endian_specific_integral
<uint32_t, little, aligned> aligned_ulittle32_t;
typedef detail::packed_endian_specific_integral
<uint64_t, little, aligned> aligned_ulittle64_t;
typedef detail::packed_endian_specific_integral
<int8_t, little, aligned> aligned_little8_t;
typedef detail::packed_endian_specific_integral
<int16_t, little, aligned> aligned_little16_t;
typedef detail::packed_endian_specific_integral
<int32_t, little, aligned> aligned_little32_t;
typedef detail::packed_endian_specific_integral
<int64_t, little, aligned> aligned_little64_t;
typedef detail::packed_endian_specific_integral
<uint8_t, big, unaligned> ubig8_t;
typedef detail::packed_endian_specific_integral
<uint16_t, big, unaligned> ubig16_t;
typedef detail::packed_endian_specific_integral
<uint32_t, big, unaligned> ubig32_t;
typedef detail::packed_endian_specific_integral
<uint64_t, big, unaligned> ubig64_t;
typedef detail::packed_endian_specific_integral
<int8_t, big, unaligned> big8_t;
typedef detail::packed_endian_specific_integral
<int16_t, big, unaligned> big16_t;
typedef detail::packed_endian_specific_integral
<int32_t, big, unaligned> big32_t;
typedef detail::packed_endian_specific_integral
<int64_t, big, unaligned> big64_t;
typedef detail::packed_endian_specific_integral
<uint8_t, big, aligned> aligned_ubig8_t;
typedef detail::packed_endian_specific_integral
<uint16_t, big, aligned> aligned_ubig16_t;
typedef detail::packed_endian_specific_integral
<uint32_t, big, aligned> aligned_ubig32_t;
typedef detail::packed_endian_specific_integral
<uint64_t, big, aligned> aligned_ubig64_t;
typedef detail::packed_endian_specific_integral
<int8_t, big, aligned> aligned_big8_t;
typedef detail::packed_endian_specific_integral
<int16_t, big, aligned> aligned_big16_t;
typedef detail::packed_endian_specific_integral
<int32_t, big, aligned> aligned_big32_t;
typedef detail::packed_endian_specific_integral
<int64_t, big, aligned> aligned_big64_t;
} // end namespace llvm
} // end namespace support
#endif