15e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer//===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===// 25e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer// 35e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer// The LLVM Compiler Infrastructure 45e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer// 55e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer// This file is distributed under the University of Illinois Open Source 65e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer// License. See LICENSE.TXT for details. 75e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer// 85e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer//===----------------------------------------------------------------------===// 95e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer// 105e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer// This file declares generic functions to read and write endian specific data. 115e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer// 125e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer//===----------------------------------------------------------------------===// 135e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 145e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer#ifndef LLVM_SUPPORT_ENDIAN_H 155e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer#define LLVM_SUPPORT_ENDIAN_H 165e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 17c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer#include "llvm/Support/AlignOf.h" 181f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Host.h" 191f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/SwapByteOrder.h" 205e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 215e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencernamespace llvm { 225e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencernamespace support { 23c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencerenum endianness {big, little, native}; 245e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 25c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer// These are named values for common alignments. 26c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencerenum {aligned = 0, unaligned = 1}; 275e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 285e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencernamespace detail { 29c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer /// \brief ::value is either alignment, or alignof(T) if alignment is 0. 30c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer template<class T, int alignment> 31c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer struct PickAlignment { 32c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer enum {value = alignment == 0 ? AlignOf<T>::Alignment : alignment}; 33c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer }; 345e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer} // end namespace detail 355e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 362e6048f8690105f7174e24ceba8e7c9f67009411Michael J. Spencernamespace endian { 3736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// Swap the bytes of value to match the given endianness. 38c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertemplate<typename value_type, endianness endian> 39c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencerinline value_type byte_swap(value_type value) { 4021a01d1ea89dba97c4f9e1f9f41485729a4046bcRafael Espindola if (endian != native && sys::IsBigEndianHost != (endian == big)) 41c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines sys::swapByteOrder(value); 42c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer return value; 43c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer} 442e6048f8690105f7174e24ceba8e7c9f67009411Michael J. Spencer 4536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// Read a value of a particular endianness from memory. 46c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertemplate<typename value_type, 47c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer endianness endian, 48c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer std::size_t alignment> 49c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencerinline value_type read(const void *memory) { 50c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer value_type ret; 51c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer 52c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer memcpy(&ret, 53c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer LLVM_ASSUME_ALIGNED(memory, 54c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer (detail::PickAlignment<value_type, alignment>::value)), 55c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer sizeof(value_type)); 56c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer return byte_swap<value_type, endian>(ret); 57c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer} 582e6048f8690105f7174e24ceba8e7c9f67009411Michael J. Spencer 5936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// Read a value of a particular endianness from a buffer, and increment the 6036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// buffer past that value. 614c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainartemplate<typename value_type, endianness endian, std::size_t alignment, 624c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar typename CharT> 634c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarinline value_type readNext(const CharT *&memory) { 6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines value_type ret = read<value_type, endian, alignment>(memory); 6536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines memory += sizeof(value_type); 6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return ret; 6736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 6836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 6936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// Write a value to memory with a particular endianness. 70c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertemplate<typename value_type, 71c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer endianness endian, 72c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer std::size_t alignment> 73c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencerinline void write(void *memory, value_type value) { 74c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer value = byte_swap<value_type, endian>(value); 75c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer memcpy(LLVM_ASSUME_ALIGNED(memory, 76c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer (detail::PickAlignment<value_type, alignment>::value)), 77c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer &value, 78c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer sizeof(value_type)); 792e6048f8690105f7174e24ceba8e7c9f67009411Michael J. Spencer} 80f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 81f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <typename value_type> 82f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarusing make_unsigned_t = typename std::make_unsigned<value_type>::type; 83f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 84f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar/// Read a value of a particular endianness from memory, for a location 85f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar/// that starts at the given bit offset within the first byte. 86f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <typename value_type, endianness endian, std::size_t alignment> 87f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline value_type readAtBitAlignment(const void *memory, uint64_t startBit) { 88f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar assert(startBit < 8); 89f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (startBit == 0) 90f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return read<value_type, endian, alignment>(memory); 91f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar else { 92f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Read two values and compose the result from them. 93f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar value_type val[2]; 94f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar memcpy(&val[0], 95f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar LLVM_ASSUME_ALIGNED( 96f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar memory, (detail::PickAlignment<value_type, alignment>::value)), 97f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar sizeof(value_type) * 2); 98f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar val[0] = byte_swap<value_type, endian>(val[0]); 99f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar val[1] = byte_swap<value_type, endian>(val[1]); 100f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 101f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Shift bits from the lower value into place. 102f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar make_unsigned_t<value_type> lowerVal = val[0] >> startBit; 103f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Mask off upper bits after right shift in case of signed type. 104f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar make_unsigned_t<value_type> numBitsFirstVal = 105f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar (sizeof(value_type) * 8) - startBit; 106f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar lowerVal &= ((make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1; 107f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 108f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Get the bits from the upper value. 109f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar make_unsigned_t<value_type> upperVal = 110f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar val[1] & (((make_unsigned_t<value_type>)1 << startBit) - 1); 111f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Shift them in to place. 112f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar upperVal <<= numBitsFirstVal; 113f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 114f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return lowerVal | upperVal; 115f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 116f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 117f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 118f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar/// Write a value to memory with a particular endianness, for a location 119f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar/// that starts at the given bit offset within the first byte. 120f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <typename value_type, endianness endian, std::size_t alignment> 121f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline void writeAtBitAlignment(void *memory, value_type value, 122f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar uint64_t startBit) { 123f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar assert(startBit < 8); 124f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (startBit == 0) 125f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar write<value_type, endian, alignment>(memory, value); 126f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar else { 127f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Read two values and shift the result into them. 128f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar value_type val[2]; 129f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar memcpy(&val[0], 130f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar LLVM_ASSUME_ALIGNED( 131f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar memory, (detail::PickAlignment<value_type, alignment>::value)), 132f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar sizeof(value_type) * 2); 133f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar val[0] = byte_swap<value_type, endian>(val[0]); 134f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar val[1] = byte_swap<value_type, endian>(val[1]); 135f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 136f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Mask off any existing bits in the upper part of the lower value that 137f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // we want to replace. 138f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar val[0] &= ((make_unsigned_t<value_type>)1 << startBit) - 1; 139f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar make_unsigned_t<value_type> numBitsFirstVal = 140f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar (sizeof(value_type) * 8) - startBit; 141f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar make_unsigned_t<value_type> lowerVal = value; 142f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (startBit > 0) { 143f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Mask off the upper bits in the new value that are not going to go into 144f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // the lower value. This avoids a left shift of a negative value, which 145f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // is undefined behavior. 146f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar lowerVal &= (((make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1); 147f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Now shift the new bits into place 148f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar lowerVal <<= startBit; 149f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 150f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar val[0] |= lowerVal; 151f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 152f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Mask off any existing bits in the lower part of the upper value that 153f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // we want to replace. 154f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar val[1] &= ~(((make_unsigned_t<value_type>)1 << startBit) - 1); 155f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Next shift the bits that go into the upper value into position. 156f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar make_unsigned_t<value_type> upperVal = value >> numBitsFirstVal; 157f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Mask off upper bits after right shift in case of signed type. 158f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar upperVal &= ((make_unsigned_t<value_type>)1 << startBit) - 1; 159f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar val[1] |= upperVal; 160f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 161f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // Finally, rewrite values. 162f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar val[0] = byte_swap<value_type, endian>(val[0]); 163f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar val[1] = byte_swap<value_type, endian>(val[1]); 164f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar memcpy(LLVM_ASSUME_ALIGNED( 165f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar memory, (detail::PickAlignment<value_type, alignment>::value)), 166f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar &val[0], sizeof(value_type) * 2); 167f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar } 168f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 169c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer} // end namespace endian 1705e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 1715e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencernamespace detail { 1725e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertemplate<typename value_type, 173fd7c230c85dbc9b1c5145319a0d5eaeb99f61176Michael J. Spencer endianness endian, 174c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer std::size_t alignment> 175c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencerstruct packed_endian_specific_integral { 176de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar packed_endian_specific_integral() = default; 177de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 178de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar explicit packed_endian_specific_integral(value_type val) { *this = val; } 179de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 1805e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer operator value_type() const { 181c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer return endian::read<value_type, endian, alignment>( 182c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer (const void*)Value.buffer); 1835e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer } 1845e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 18524973c1063bfb7ac353732a4e8eb801830336c5fEli Bendersky void operator=(value_type newValue) { 186c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer endian::write<value_type, endian, alignment>( 187c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer (void*)Value.buffer, newValue); 18824973c1063bfb7ac353732a4e8eb801830336c5fEli Bendersky } 1895e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 19037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines packed_endian_specific_integral &operator+=(value_type newValue) { 19137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines *this = *this + newValue; 19237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return *this; 19337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 19437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 19537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines packed_endian_specific_integral &operator-=(value_type newValue) { 19637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines *this = *this - newValue; 19737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return *this; 19837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 19937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 2006948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar packed_endian_specific_integral &operator|=(value_type newValue) { 2016948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar *this = *this | newValue; 2026948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return *this; 2036948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar } 2046948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar 2056948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar packed_endian_specific_integral &operator&=(value_type newValue) { 2066948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar *this = *this & newValue; 2076948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return *this; 2086948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar } 2096948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar 2105e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencerprivate: 211c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer AlignedCharArray<PickAlignment<value_type, alignment>::value, 212c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer sizeof(value_type)> Value; 21337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 21437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinespublic: 21537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines struct ref { 21637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines explicit ref(void *Ptr) : Ptr(Ptr) {} 21737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 21837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines operator value_type() const { 21937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return endian::read<value_type, endian, alignment>(Ptr); 22037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 22137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 22237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines void operator=(value_type NewValue) { 22337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines endian::write<value_type, endian, alignment>(Ptr, NewValue); 22437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 22537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 22637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines private: 22737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines void *Ptr; 22837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines }; 2295e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer}; 23037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 2315e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer} // end namespace detail 2325e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 2335e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2345e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <uint16_t, little, unaligned> ulittle16_t; 2355e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2365e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <uint32_t, little, unaligned> ulittle32_t; 2375e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2385e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <uint64_t, little, unaligned> ulittle64_t; 2395e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 2405e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2415e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <int16_t, little, unaligned> little16_t; 2425e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2435e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <int32_t, little, unaligned> little32_t; 2445e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2455e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <int64_t, little, unaligned> little64_t; 2465e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 2475e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2485e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <uint16_t, little, aligned> aligned_ulittle16_t; 2495e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2505e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <uint32_t, little, aligned> aligned_ulittle32_t; 2515e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2525e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <uint64_t, little, aligned> aligned_ulittle64_t; 2535e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 2545e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2555e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <int16_t, little, aligned> aligned_little16_t; 2565e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2575e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <int32_t, little, aligned> aligned_little32_t; 2585e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2595e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <int64_t, little, aligned> aligned_little64_t; 2605e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 2615e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2625e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <uint16_t, big, unaligned> ubig16_t; 2635e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2645e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <uint32_t, big, unaligned> ubig32_t; 2655e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2665e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <uint64_t, big, unaligned> ubig64_t; 2675e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 2685e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2695e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <int16_t, big, unaligned> big16_t; 2705e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2715e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <int32_t, big, unaligned> big32_t; 2725e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2735e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <int64_t, big, unaligned> big64_t; 2745e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 2755e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2765e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <uint16_t, big, aligned> aligned_ubig16_t; 2775e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2785e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <uint32_t, big, aligned> aligned_ubig32_t; 2795e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2805e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <uint64_t, big, aligned> aligned_ubig64_t; 2815e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 2825e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2835e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <int16_t, big, aligned> aligned_big16_t; 2845e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2855e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <int32_t, big, aligned> aligned_big32_t; 2865e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral 2875e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer <int64_t, big, aligned> aligned_big64_t; 2885e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 289c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertypedef detail::packed_endian_specific_integral 290c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer <uint16_t, native, unaligned> unaligned_uint16_t; 291c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertypedef detail::packed_endian_specific_integral 292c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer <uint32_t, native, unaligned> unaligned_uint32_t; 293c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertypedef detail::packed_endian_specific_integral 294c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer <uint64_t, native, unaligned> unaligned_uint64_t; 295c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer 296c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertypedef detail::packed_endian_specific_integral 297c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer <int16_t, native, unaligned> unaligned_int16_t; 298c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertypedef detail::packed_endian_specific_integral 299c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer <int32_t, native, unaligned> unaligned_int32_t; 300c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertypedef detail::packed_endian_specific_integral 301c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer <int64_t, native, unaligned> unaligned_int64_t; 3024c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 3034c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarnamespace endian { 304f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <typename T, endianness E> inline T read(const void *P) { 305f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return *(const detail::packed_endian_specific_integral<T, E, unaligned> *)P; 306f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 307f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 308f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <endianness E> inline uint16_t read16(const void *P) { 309f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return read<uint16_t, E>(P); 310f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 311f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <endianness E> inline uint32_t read32(const void *P) { 312f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return read<uint32_t, E>(P); 313f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 314f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <endianness E> inline uint64_t read64(const void *P) { 315f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return read<uint64_t, E>(P); 316f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 317f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 318f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline uint16_t read16le(const void *P) { return read16<little>(P); } 319f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline uint32_t read32le(const void *P) { return read32<little>(P); } 320f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline uint64_t read64le(const void *P) { return read64<little>(P); } 321f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline uint16_t read16be(const void *P) { return read16<big>(P); } 322f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline uint32_t read32be(const void *P) { return read32<big>(P); } 323f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline uint64_t read64be(const void *P) { return read64<big>(P); } 324f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 325f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <typename T, endianness E> inline void write(void *P, T V) { 326f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar *(detail::packed_endian_specific_integral<T, E, unaligned> *)P = V; 327f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 328f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 329f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <endianness E> inline void write16(void *P, uint16_t V) { 330f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar write<uint16_t, E>(P, V); 331f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 332f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <endianness E> inline void write32(void *P, uint32_t V) { 333f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar write<uint32_t, E>(P, V); 334f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 335f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <endianness E> inline void write64(void *P, uint64_t V) { 336f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar write<uint64_t, E>(P, V); 337f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 338f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 339f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline void write16le(void *P, uint16_t V) { write16<little>(P, V); } 340f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline void write32le(void *P, uint32_t V) { write32<little>(P, V); } 341f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline void write64le(void *P, uint64_t V) { write64<little>(P, V); } 342f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline void write16be(void *P, uint16_t V) { write16<big>(P, V); } 343f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline void write32be(void *P, uint32_t V) { write32<big>(P, V); } 344f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline void write64be(void *P, uint64_t V) { write64<big>(P, V); } 3454c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar} // end namespace endian 3465e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer} // end namespace support 3474c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar} // end namespace llvm 3485e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer 3495e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer#endif 350