Home | History | Annotate | Download | only in src
      1 /* Unaligned memory access functionality.
      2    Copyright (C) 2000, 2001, 2002, 2003 Red Hat, Inc.
      3    Written by Ulrich Drepper <drepper (at) 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