1da0c48c4Sopenharmony_ci/* Unaligned memory access functionality. 2da0c48c4Sopenharmony_ci Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2008 Red Hat, Inc. 3da0c48c4Sopenharmony_ci Written by Ulrich Drepper <drepper@redhat.com>, 2001. 4da0c48c4Sopenharmony_ci 5da0c48c4Sopenharmony_ci This file is free software; you can redistribute it and/or modify 6da0c48c4Sopenharmony_ci it under the terms of either 7da0c48c4Sopenharmony_ci 8da0c48c4Sopenharmony_ci * the GNU Lesser General Public License as published by the Free 9da0c48c4Sopenharmony_ci Software Foundation; either version 3 of the License, or (at 10da0c48c4Sopenharmony_ci your option) any later version 11da0c48c4Sopenharmony_ci 12da0c48c4Sopenharmony_ci or 13da0c48c4Sopenharmony_ci 14da0c48c4Sopenharmony_ci * the GNU General Public License as published by the Free 15da0c48c4Sopenharmony_ci Software Foundation; either version 2 of the License, or (at 16da0c48c4Sopenharmony_ci your option) any later version 17da0c48c4Sopenharmony_ci 18da0c48c4Sopenharmony_ci or both in parallel, as here. 19da0c48c4Sopenharmony_ci 20da0c48c4Sopenharmony_ci elfutils is distributed in the hope that it will be useful, but 21da0c48c4Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 22da0c48c4Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23da0c48c4Sopenharmony_ci General Public License for more details. 24da0c48c4Sopenharmony_ci 25da0c48c4Sopenharmony_ci You should have received copies of the GNU General Public License and 26da0c48c4Sopenharmony_ci the GNU Lesser General Public License along with this program. If 27da0c48c4Sopenharmony_ci not, see <http://www.gnu.org/licenses/>. */ 28da0c48c4Sopenharmony_ci 29da0c48c4Sopenharmony_ci#ifndef _MEMORY_ACCESS_H 30da0c48c4Sopenharmony_ci#define _MEMORY_ACCESS_H 1 31da0c48c4Sopenharmony_ci 32da0c48c4Sopenharmony_ci#include <limits.h> 33da0c48c4Sopenharmony_ci#include <stdint.h> 34da0c48c4Sopenharmony_ci 35da0c48c4Sopenharmony_ci#include <system.h> 36da0c48c4Sopenharmony_ci 37da0c48c4Sopenharmony_ci/* When loading this file we require the macro MACHINE_ENCODING to be 38da0c48c4Sopenharmony_ci defined to signal the endianness of the architecture which is 39da0c48c4Sopenharmony_ci defined. */ 40da0c48c4Sopenharmony_ci#ifndef MACHINE_ENCODING 41da0c48c4Sopenharmony_ci# error "MACHINE_ENCODING needs to be defined" 42da0c48c4Sopenharmony_ci#endif 43da0c48c4Sopenharmony_ci#if MACHINE_ENCODING != BIG_ENDIAN && MACHINE_ENCODING != LITTLE_ENDIAN 44da0c48c4Sopenharmony_ci# error "MACHINE_ENCODING must signal either big or little endian" 45da0c48c4Sopenharmony_ci#endif 46da0c48c4Sopenharmony_ci 47da0c48c4Sopenharmony_ci 48da0c48c4Sopenharmony_ci/* We use simple memory access functions in case the hardware allows it. 49da0c48c4Sopenharmony_ci The caller has to make sure we don't have alias problems. */ 50da0c48c4Sopenharmony_ci#if ALLOW_UNALIGNED 51da0c48c4Sopenharmony_ci 52da0c48c4Sopenharmony_ci# define read_2ubyte_unaligned(Addr) \ 53da0c48c4Sopenharmony_ci (unlikely (MACHINE_ENCODING != BYTE_ORDER) \ 54da0c48c4Sopenharmony_ci ? bswap_16 (*((const uint16_t *) (Addr))) \ 55da0c48c4Sopenharmony_ci : *((const uint16_t *) (Addr))) 56da0c48c4Sopenharmony_ci# define read_2sbyte_unaligned(Addr) \ 57da0c48c4Sopenharmony_ci (unlikely (MACHINE_ENCODING != BYTE_ORDER) \ 58da0c48c4Sopenharmony_ci ? (int16_t) bswap_16 (*((const int16_t *) (Addr))) \ 59da0c48c4Sopenharmony_ci : *((const int16_t *) (Addr))) 60da0c48c4Sopenharmony_ci 61da0c48c4Sopenharmony_ci# define read_4ubyte_unaligned_noncvt(Addr) \ 62da0c48c4Sopenharmony_ci *((const uint32_t *) (Addr)) 63da0c48c4Sopenharmony_ci# define read_4ubyte_unaligned(Addr) \ 64da0c48c4Sopenharmony_ci (unlikely (MACHINE_ENCODING != BYTE_ORDER) \ 65da0c48c4Sopenharmony_ci ? bswap_32 (*((const uint32_t *) (Addr))) \ 66da0c48c4Sopenharmony_ci : *((const uint32_t *) (Addr))) 67da0c48c4Sopenharmony_ci# define read_4sbyte_unaligned(Addr) \ 68da0c48c4Sopenharmony_ci (unlikely (MACHINE_ENCODING != BYTE_ORDER) \ 69da0c48c4Sopenharmony_ci ? (int32_t) bswap_32 (*((const int32_t *) (Addr))) \ 70da0c48c4Sopenharmony_ci : *((const int32_t *) (Addr))) 71da0c48c4Sopenharmony_ci 72da0c48c4Sopenharmony_ci# define read_8ubyte_unaligned(Addr) \ 73da0c48c4Sopenharmony_ci (unlikely (MACHINE_ENCODING != BYTE_ORDER) \ 74da0c48c4Sopenharmony_ci ? bswap_64 (*((const uint64_t *) (Addr))) \ 75da0c48c4Sopenharmony_ci : *((const uint64_t *) (Addr))) 76da0c48c4Sopenharmony_ci# define read_8sbyte_unaligned(Addr) \ 77da0c48c4Sopenharmony_ci (unlikely (MACHINE_ENCODING != BYTE_ORDER) \ 78da0c48c4Sopenharmony_ci ? (int64_t) bswap_64 (*((const int64_t *) (Addr))) \ 79da0c48c4Sopenharmony_ci : *((const int64_t *) (Addr))) 80da0c48c4Sopenharmony_ci 81da0c48c4Sopenharmony_ci#else 82da0c48c4Sopenharmony_ci 83da0c48c4Sopenharmony_ciunion unaligned 84da0c48c4Sopenharmony_ci { 85da0c48c4Sopenharmony_ci void *p; 86da0c48c4Sopenharmony_ci uint16_t u2; 87da0c48c4Sopenharmony_ci uint32_t u4; 88da0c48c4Sopenharmony_ci uint64_t u8; 89da0c48c4Sopenharmony_ci int16_t s2; 90da0c48c4Sopenharmony_ci int32_t s4; 91da0c48c4Sopenharmony_ci int64_t s8; 92da0c48c4Sopenharmony_ci } attribute_packed; 93da0c48c4Sopenharmony_ci 94da0c48c4Sopenharmony_cistatic inline uint16_t 95da0c48c4Sopenharmony_ciread_2ubyte_unaligned (const void *p) 96da0c48c4Sopenharmony_ci{ 97da0c48c4Sopenharmony_ci const union unaligned *up = p; 98da0c48c4Sopenharmony_ci if (MACHINE_ENCODING != BYTE_ORDER) 99da0c48c4Sopenharmony_ci return bswap_16 (up->u2); 100da0c48c4Sopenharmony_ci return up->u2; 101da0c48c4Sopenharmony_ci} 102da0c48c4Sopenharmony_cistatic inline int16_t 103da0c48c4Sopenharmony_ciread_2sbyte_unaligned (const void *p) 104da0c48c4Sopenharmony_ci{ 105da0c48c4Sopenharmony_ci const union unaligned *up = p; 106da0c48c4Sopenharmony_ci if (MACHINE_ENCODING != BYTE_ORDER) 107da0c48c4Sopenharmony_ci return (int16_t) bswap_16 (up->u2); 108da0c48c4Sopenharmony_ci return up->s2; 109da0c48c4Sopenharmony_ci} 110da0c48c4Sopenharmony_ci 111da0c48c4Sopenharmony_cistatic inline uint32_t 112da0c48c4Sopenharmony_ciread_4ubyte_unaligned_noncvt (const void *p) 113da0c48c4Sopenharmony_ci{ 114da0c48c4Sopenharmony_ci const union unaligned *up = p; 115da0c48c4Sopenharmony_ci return up->u4; 116da0c48c4Sopenharmony_ci} 117da0c48c4Sopenharmony_cistatic inline uint32_t 118da0c48c4Sopenharmony_ciread_4ubyte_unaligned (const void *p) 119da0c48c4Sopenharmony_ci{ 120da0c48c4Sopenharmony_ci const union unaligned *up = p; 121da0c48c4Sopenharmony_ci if (MACHINE_ENCODING != BYTE_ORDER) 122da0c48c4Sopenharmony_ci return bswap_32 (up->u4); 123da0c48c4Sopenharmony_ci return up->u4; 124da0c48c4Sopenharmony_ci} 125da0c48c4Sopenharmony_cistatic inline int32_t 126da0c48c4Sopenharmony_ciread_4sbyte_unaligned (const void *p) 127da0c48c4Sopenharmony_ci{ 128da0c48c4Sopenharmony_ci const union unaligned *up = p; 129da0c48c4Sopenharmony_ci if (MACHINE_ENCODING != BYTE_ORDER) 130da0c48c4Sopenharmony_ci return (int32_t) bswap_32 (up->u4); 131da0c48c4Sopenharmony_ci return up->s4; 132da0c48c4Sopenharmony_ci} 133da0c48c4Sopenharmony_ci 134da0c48c4Sopenharmony_cistatic inline uint64_t 135da0c48c4Sopenharmony_ciread_8ubyte_unaligned (const void *p) 136da0c48c4Sopenharmony_ci{ 137da0c48c4Sopenharmony_ci const union unaligned *up = p; 138da0c48c4Sopenharmony_ci if (MACHINE_ENCODING != BYTE_ORDER) 139da0c48c4Sopenharmony_ci return bswap_64 (up->u8); 140da0c48c4Sopenharmony_ci return up->u8; 141da0c48c4Sopenharmony_ci} 142da0c48c4Sopenharmony_cistatic inline int64_t 143da0c48c4Sopenharmony_ciread_8sbyte_unaligned (const void *p) 144da0c48c4Sopenharmony_ci{ 145da0c48c4Sopenharmony_ci const union unaligned *up = p; 146da0c48c4Sopenharmony_ci if (MACHINE_ENCODING != BYTE_ORDER) 147da0c48c4Sopenharmony_ci return (int64_t) bswap_64 (up->u8); 148da0c48c4Sopenharmony_ci return up->s8; 149da0c48c4Sopenharmony_ci} 150da0c48c4Sopenharmony_ci 151da0c48c4Sopenharmony_ci#endif /* allow unaligned */ 152da0c48c4Sopenharmony_ci 153da0c48c4Sopenharmony_ci 154da0c48c4Sopenharmony_ci#define read_2ubyte_unaligned_inc(Addr) \ 155da0c48c4Sopenharmony_ci ({ uint16_t t_ = read_2ubyte_unaligned (Addr); \ 156da0c48c4Sopenharmony_ci Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \ 157da0c48c4Sopenharmony_ci t_; }) 158da0c48c4Sopenharmony_ci#define read_2sbyte_unaligned_inc(Addr) \ 159da0c48c4Sopenharmony_ci ({ int16_t t_ = read_2sbyte_unaligned (Addr); \ 160da0c48c4Sopenharmony_ci Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \ 161da0c48c4Sopenharmony_ci t_; }) 162da0c48c4Sopenharmony_ci 163da0c48c4Sopenharmony_ci#define read_4ubyte_unaligned_inc(Addr) \ 164da0c48c4Sopenharmony_ci ({ uint32_t t_ = read_4ubyte_unaligned (Addr); \ 165da0c48c4Sopenharmony_ci Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \ 166da0c48c4Sopenharmony_ci t_; }) 167da0c48c4Sopenharmony_ci#define read_4sbyte_unaligned_inc(Addr) \ 168da0c48c4Sopenharmony_ci ({ int32_t t_ = read_4sbyte_unaligned (Addr); \ 169da0c48c4Sopenharmony_ci Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \ 170da0c48c4Sopenharmony_ci t_; }) 171da0c48c4Sopenharmony_ci 172da0c48c4Sopenharmony_ci#define read_8ubyte_unaligned_inc(Addr) \ 173da0c48c4Sopenharmony_ci ({ uint64_t t_ = read_8ubyte_unaligned (Addr); \ 174da0c48c4Sopenharmony_ci Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \ 175da0c48c4Sopenharmony_ci t_; }) 176da0c48c4Sopenharmony_ci#define read_8sbyte_unaligned_inc(Addr) \ 177da0c48c4Sopenharmony_ci ({ int64_t t_ = read_8sbyte_unaligned (Addr); \ 178da0c48c4Sopenharmony_ci Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \ 179da0c48c4Sopenharmony_ci t_; }) 180da0c48c4Sopenharmony_ci 181da0c48c4Sopenharmony_ci#endif /* memory-access.h */ 182