mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	This patch is to overload operator+= and operator-= for
{u}{little}{big}{16,32,64}_t.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217637 91177308-0d34-0410-b5e6-96231b3b80d8
		
	
		
			
				
	
	
		
			202 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			202 lines
		
	
	
		
			7.0 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/Support/AlignOf.h"
 | |
| #include "llvm/Support/Host.h"
 | |
| #include "llvm/Support/SwapByteOrder.h"
 | |
| 
 | |
| namespace llvm {
 | |
| namespace support {
 | |
| enum endianness {big, little, native};
 | |
| 
 | |
| // These are named values for common alignments.
 | |
| enum {aligned = 0, unaligned = 1};
 | |
| 
 | |
| namespace detail {
 | |
|   /// \brief ::value is either alignment, or alignof(T) if alignment is 0.
 | |
|   template<class T, int alignment>
 | |
|   struct PickAlignment {
 | |
|     enum {value = alignment == 0 ? AlignOf<T>::Alignment : alignment};
 | |
|   };
 | |
| } // end namespace detail
 | |
| 
 | |
| namespace endian {
 | |
| /// Swap the bytes of value to match the given endianness.
 | |
| template<typename value_type, endianness endian>
 | |
| inline value_type byte_swap(value_type value) {
 | |
|   if (endian != native && sys::IsBigEndianHost != (endian == big))
 | |
|     sys::swapByteOrder(value);
 | |
|   return value;
 | |
| }
 | |
| 
 | |
| /// Read a value of a particular endianness from memory.
 | |
| template<typename value_type,
 | |
|          endianness endian,
 | |
|          std::size_t alignment>
 | |
| inline value_type read(const void *memory) {
 | |
|   value_type ret;
 | |
| 
 | |
|   memcpy(&ret,
 | |
|          LLVM_ASSUME_ALIGNED(memory,
 | |
|            (detail::PickAlignment<value_type, alignment>::value)),
 | |
|          sizeof(value_type));
 | |
|   return byte_swap<value_type, endian>(ret);
 | |
| }
 | |
| 
 | |
| /// Read a value of a particular endianness from a buffer, and increment the
 | |
| /// buffer past that value.
 | |
| template<typename value_type, endianness endian, std::size_t alignment>
 | |
| inline value_type readNext(const unsigned char *&memory) {
 | |
|   value_type ret = read<value_type, endian, alignment>(memory);
 | |
|   memory += sizeof(value_type);
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| /// Write a value to memory with a particular endianness.
 | |
| template<typename value_type,
 | |
|          endianness endian,
 | |
|          std::size_t alignment>
 | |
| inline void write(void *memory, value_type value) {
 | |
|   value = byte_swap<value_type, endian>(value);
 | |
|   memcpy(LLVM_ASSUME_ALIGNED(memory,
 | |
|            (detail::PickAlignment<value_type, alignment>::value)),
 | |
|          &value,
 | |
|          sizeof(value_type));
 | |
| }
 | |
| } // end namespace endian
 | |
| 
 | |
| namespace detail {
 | |
| template<typename value_type,
 | |
|          endianness endian,
 | |
|          std::size_t alignment>
 | |
| struct packed_endian_specific_integral {
 | |
|   operator value_type() const {
 | |
|     return endian::read<value_type, endian, alignment>(
 | |
|       (const void*)Value.buffer);
 | |
|   }
 | |
| 
 | |
|   void operator=(value_type newValue) {
 | |
|     endian::write<value_type, endian, alignment>(
 | |
|       (void*)Value.buffer, newValue);
 | |
|   }
 | |
| 
 | |
|   packed_endian_specific_integral &operator+=(value_type newValue) {
 | |
|     *this = *this + newValue;
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
|   packed_endian_specific_integral &operator-=(value_type newValue) {
 | |
|     *this = *this - newValue;
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   AlignedCharArray<PickAlignment<value_type, alignment>::value,
 | |
|                    sizeof(value_type)> Value;
 | |
| 
 | |
| public:
 | |
|   struct ref {
 | |
|     explicit ref(void *Ptr) : Ptr(Ptr) {}
 | |
| 
 | |
|     operator value_type() const {
 | |
|       return endian::read<value_type, endian, alignment>(Ptr);
 | |
|     }
 | |
| 
 | |
|     void operator=(value_type NewValue) {
 | |
|       endian::write<value_type, endian, alignment>(Ptr, NewValue);
 | |
|     }
 | |
| 
 | |
|   private:
 | |
|     void *Ptr;
 | |
|   };
 | |
| };
 | |
| 
 | |
| } // end namespace detail
 | |
| 
 | |
| 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
 | |
|                    <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
 | |
|                     <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
 | |
|                      <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
 | |
|                   <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
 | |
|                    <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
 | |
|                     <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
 | |
|                      <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;
 | |
| 
 | |
| typedef detail::packed_endian_specific_integral
 | |
|                   <uint16_t, native, unaligned> unaligned_uint16_t;
 | |
| typedef detail::packed_endian_specific_integral
 | |
|                   <uint32_t, native, unaligned> unaligned_uint32_t;
 | |
| typedef detail::packed_endian_specific_integral
 | |
|                   <uint64_t, native, unaligned> unaligned_uint64_t;
 | |
| 
 | |
| typedef detail::packed_endian_specific_integral
 | |
|                    <int16_t, native, unaligned> unaligned_int16_t;
 | |
| typedef detail::packed_endian_specific_integral
 | |
|                    <int32_t, native, unaligned> unaligned_int32_t;
 | |
| typedef detail::packed_endian_specific_integral
 | |
|                    <int64_t, native, unaligned> unaligned_int64_t;
 | |
| } // end namespace llvm
 | |
| } // end namespace support
 | |
| 
 | |
| #endif
 |