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