1 /* Unaligned memory access functionality. 2 Copyright (C) 2000, 2001, 2002, 2003, 2008 Red Hat, Inc. 3 This file is part of elfutils. 4 Written by Ulrich Drepper <drepper@redhat.com>, 2001. 5 6 This file is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 elfutils is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 19 #ifndef _UNALIGNED_H 20 #define _UNALIGNED_H 1 21 22 #include <byteswap.h> 23 #include <endian.h> 24 25 26 #ifndef UNALIGNED_ACCESS_CLASS 27 # error "UNALIGNED_ACCESS_CLASS must be defined" 28 #endif 29 30 31 /* Macros to convert from the host byte order to that of the object file. */ 32 #if UNALIGNED_ACCESS_CLASS == BYTE_ORDER 33 # define target_bswap_16(n) (n) 34 # define target_bswap_32(n) (n) 35 # define target_bswap_64(n) (n) 36 #else 37 # define target_bswap_16(n) bswap_16 (n) 38 # define target_bswap_32(n) bswap_32 (n) 39 # define target_bswap_64(n) bswap_64 (n) 40 #endif 41 42 43 union u_2ubyte_unaligned 44 { 45 uint16_t u; 46 char c[2]; 47 } __attribute__((packed)); 48 49 union u_4ubyte_unaligned 50 { 51 uint32_t u; 52 char c[4]; 53 } __attribute__((packed)); 54 55 union u_8ubyte_unaligned 56 { 57 uint64_t u; 58 char c[8]; 59 } __attribute__((packed)); 60 61 62 /* Macros to store value at unaligned address. */ 63 #define store_2ubyte_unaligned(ptr, value) \ 64 (void) (((union u_2ubyte_unaligned *) (ptr))->u = target_bswap_16 (value)) 65 #define store_4ubyte_unaligned(ptr, value) \ 66 (void) (((union u_4ubyte_unaligned *) (ptr))->u = target_bswap_32 (value)) 67 #define store_8ubyte_unaligned(ptr, value) \ 68 (void) (((union u_8ubyte_unaligned *) (ptr))->u = target_bswap_64 (value)) 69 70 71 /* Macros to add value to unaligned address. This is a bit more 72 complicated since the value must be read from memory and eventually 73 converted twice. */ 74 #if UNALIGNED_ACCESS_CLASS == BYTE_ORDER 75 # define add_2ubyte_unaligned(ptr, value) \ 76 (void) (((union u_2ubyte_unaligned *) (ptr))->u += value) 77 # define add_4ubyte_unaligned(ptr, value) \ 78 (void) (((union u_4ubyte_unaligned *) (ptr))->u += value) 79 # define add_8ubyte_unaligned(ptr, value) \ 80 (void) (((union u_8ubyte_unaligned *) (ptr))->u += value) 81 #else 82 # define add_2ubyte_unaligned(ptr, value) \ 83 do { \ 84 union u_2ubyte_unaligned *_ptr = (void *) (ptr); \ 85 uint16_t _val = bswap_16 (_ptr->u) + (value); \ 86 _ptr->u = bswap_16 (_val); \ 87 } while (0) 88 # define add_4ubyte_unaligned(ptr, value) \ 89 do { \ 90 union u_4ubyte_unaligned *_ptr = (void *) (ptr); \ 91 uint32_t _val = bswap_32 (_ptr->u) + (value); \ 92 _ptr->u = bswap_32 (_val); \ 93 } while (0) 94 # define add_8ubyte_unaligned(ptr, value) \ 95 do { \ 96 union u_8ubyte_unaligned *_ptr = (void *) (ptr); \ 97 uint64_t _val = bswap_64 (_ptr->u) + (value); \ 98 _ptr->u = bswap_64 (_val); \ 99 } while (0) 100 #endif 101 102 #endif /* unaligned.h */ 103