Home | History | Annotate | Download | only in src
      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 (at) 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