1 /* Unaligned memory access functionality. 2 Copyright (C) 2000, 2001, 2002, 2003 Red Hat, Inc. 3 Written by Ulrich Drepper <drepper@redhat.com>, 2001. 4 5 This program is Open Source software; you can redistribute it and/or 6 modify it under the terms of the Open Software License version 1.0 as 7 published by the Open Source Initiative. 8 9 You should have received a copy of the Open Software License along 10 with this program; if not, you may obtain a copy of the Open Software 11 License version 1.0 from http://www.opensource.org/licenses/osl.php or 12 by writing the Open Source Initiative c/o Lawrence Rosen, Esq., 13 3001 King Ranch Road, Ukiah, CA 95482. */ 14 15 #ifndef _UNALIGNED_H 16 #define _UNALIGNED_H 1 17 18 #include <byteswap.h> 19 #include <endian.h> 20 21 22 #ifndef UNALIGNED_ACCESS_CLASS 23 # error "UNALIGNED_ACCESS_CLASS must be defined" 24 #endif 25 26 27 /* Macros to convert from the host byte order to that of the object file. */ 28 #if UNALIGNED_ACCESS_CLASS == BYTE_ORDER 29 # define target_bswap_16(n) (n) 30 # define target_bswap_32(n) (n) 31 # define target_bswap_64(n) (n) 32 #else 33 # define target_bswap_16(n) bswap_16 (n) 34 # define target_bswap_32(n) bswap_32 (n) 35 # define target_bswap_64(n) bswap_64 (n) 36 #endif 37 38 39 union u_2ubyte_unaligned 40 { 41 uint16_t u; 42 char c[2]; 43 } __attribute__((packed)); 44 45 union u_4ubyte_unaligned 46 { 47 uint32_t u; 48 char c[4]; 49 } __attribute__((packed)); 50 51 union u_8ubyte_unaligned 52 { 53 uint64_t u; 54 char c[8]; 55 } __attribute__((packed)); 56 57 58 /* Macros to store value at unaligned address. */ 59 #define store_2ubyte_unaligned(ptr, value) \ 60 (void) (((union u_2ubyte_unaligned *) (ptr))->u = target_bswap_16 (value)) 61 #define store_4ubyte_unaligned(ptr, value) \ 62 (void) (((union u_4ubyte_unaligned *) (ptr))->u = target_bswap_32 (value)) 63 #define store_8ubyte_unaligned(ptr, value) \ 64 (void) (((union u_8ubyte_unaligned *) (ptr))->u = target_bswap_64 (value)) 65 66 67 /* Macros to add value to unaligned address. This is a bit more 68 complicated since the value must be read from memory and eventually 69 converted twice. */ 70 #if UNALIGNED_ACCESS_CLASS == BYTE_ORDER 71 # define add_2ubyte_unaligned(ptr, value) \ 72 (void) (((union u_2ubyte_unaligned *) (ptr))->u += value) 73 # define add_4ubyte_unaligned(ptr, value) \ 74 (void) (((union u_4ubyte_unaligned *) (ptr))->u += value) 75 # define add_8ubyte_unaligned(ptr, value) \ 76 (void) (((union u_8ubyte_unaligned *) (ptr))->u += value) 77 #else 78 # define add_2ubyte_unaligned(ptr, value) \ 79 do { \ 80 union u_2ubyte_unaligned *_ptr = (ptr); \ 81 uint16_t _val = bswap_16 (_ptr->u) + (value); \ 82 _ptr->u = bswap_16 (_val); \ 83 } while (0) 84 # define add_4ubyte_unaligned(ptr, value) \ 85 do { \ 86 union u_4ubyte_unaligned *_ptr = (ptr); \ 87 uint32_t _val = bswap_32 (_ptr->u) + (value); \ 88 _ptr->u = bswap_32 (_val); \ 89 } while (0) 90 # define add_8ubyte_unaligned(ptr, value) \ 91 do { \ 92 union u_8ubyte_unaligned *_ptr = (ptr); \ 93 uint64_t _val = bswap_64 (_ptr->u) + (value); \ 94 _ptr->u = bswap_64 (_val); \ 95 } while (0) 96 #endif 97 98 #endif /* unaligned.h */ 99