1da0c48c4Sopenharmony_ci/* Unaligned memory access functionality.
2da0c48c4Sopenharmony_ci   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2008 Red Hat, Inc.
3da0c48c4Sopenharmony_ci   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
4da0c48c4Sopenharmony_ci
5da0c48c4Sopenharmony_ci   This file is free software; you can redistribute it and/or modify
6da0c48c4Sopenharmony_ci   it under the terms of either
7da0c48c4Sopenharmony_ci
8da0c48c4Sopenharmony_ci     * the GNU Lesser General Public License as published by the Free
9da0c48c4Sopenharmony_ci       Software Foundation; either version 3 of the License, or (at
10da0c48c4Sopenharmony_ci       your option) any later version
11da0c48c4Sopenharmony_ci
12da0c48c4Sopenharmony_ci   or
13da0c48c4Sopenharmony_ci
14da0c48c4Sopenharmony_ci     * the GNU General Public License as published by the Free
15da0c48c4Sopenharmony_ci       Software Foundation; either version 2 of the License, or (at
16da0c48c4Sopenharmony_ci       your option) any later version
17da0c48c4Sopenharmony_ci
18da0c48c4Sopenharmony_ci   or both in parallel, as here.
19da0c48c4Sopenharmony_ci
20da0c48c4Sopenharmony_ci   elfutils is distributed in the hope that it will be useful, but
21da0c48c4Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
22da0c48c4Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23da0c48c4Sopenharmony_ci   General Public License for more details.
24da0c48c4Sopenharmony_ci
25da0c48c4Sopenharmony_ci   You should have received copies of the GNU General Public License and
26da0c48c4Sopenharmony_ci   the GNU Lesser General Public License along with this program.  If
27da0c48c4Sopenharmony_ci   not, see <http://www.gnu.org/licenses/>.  */
28da0c48c4Sopenharmony_ci
29da0c48c4Sopenharmony_ci#ifndef _MEMORY_ACCESS_H
30da0c48c4Sopenharmony_ci#define _MEMORY_ACCESS_H 1
31da0c48c4Sopenharmony_ci
32da0c48c4Sopenharmony_ci#include <limits.h>
33da0c48c4Sopenharmony_ci#include <stdint.h>
34da0c48c4Sopenharmony_ci
35da0c48c4Sopenharmony_ci#include <system.h>
36da0c48c4Sopenharmony_ci
37da0c48c4Sopenharmony_ci/* When loading this file we require the macro MACHINE_ENCODING to be
38da0c48c4Sopenharmony_ci   defined to signal the endianness of the architecture which is
39da0c48c4Sopenharmony_ci   defined.  */
40da0c48c4Sopenharmony_ci#ifndef MACHINE_ENCODING
41da0c48c4Sopenharmony_ci# error "MACHINE_ENCODING needs to be defined"
42da0c48c4Sopenharmony_ci#endif
43da0c48c4Sopenharmony_ci#if MACHINE_ENCODING != BIG_ENDIAN && MACHINE_ENCODING != LITTLE_ENDIAN
44da0c48c4Sopenharmony_ci# error "MACHINE_ENCODING must signal either big or little endian"
45da0c48c4Sopenharmony_ci#endif
46da0c48c4Sopenharmony_ci
47da0c48c4Sopenharmony_ci
48da0c48c4Sopenharmony_ci/* We use simple memory access functions in case the hardware allows it.
49da0c48c4Sopenharmony_ci   The caller has to make sure we don't have alias problems.  */
50da0c48c4Sopenharmony_ci#if ALLOW_UNALIGNED
51da0c48c4Sopenharmony_ci
52da0c48c4Sopenharmony_ci# define read_2ubyte_unaligned(Addr) \
53da0c48c4Sopenharmony_ci  (unlikely (MACHINE_ENCODING != BYTE_ORDER)				      \
54da0c48c4Sopenharmony_ci   ? bswap_16 (*((const uint16_t *) (Addr)))				      \
55da0c48c4Sopenharmony_ci   : *((const uint16_t *) (Addr)))
56da0c48c4Sopenharmony_ci# define read_2sbyte_unaligned(Addr) \
57da0c48c4Sopenharmony_ci  (unlikely (MACHINE_ENCODING != BYTE_ORDER)				      \
58da0c48c4Sopenharmony_ci   ? (int16_t) bswap_16 (*((const int16_t *) (Addr)))			      \
59da0c48c4Sopenharmony_ci   : *((const int16_t *) (Addr)))
60da0c48c4Sopenharmony_ci
61da0c48c4Sopenharmony_ci# define read_4ubyte_unaligned_noncvt(Addr) \
62da0c48c4Sopenharmony_ci   *((const uint32_t *) (Addr))
63da0c48c4Sopenharmony_ci# define read_4ubyte_unaligned(Addr) \
64da0c48c4Sopenharmony_ci  (unlikely (MACHINE_ENCODING != BYTE_ORDER)				      \
65da0c48c4Sopenharmony_ci   ? bswap_32 (*((const uint32_t *) (Addr)))				      \
66da0c48c4Sopenharmony_ci   : *((const uint32_t *) (Addr)))
67da0c48c4Sopenharmony_ci# define read_4sbyte_unaligned(Addr) \
68da0c48c4Sopenharmony_ci  (unlikely (MACHINE_ENCODING != BYTE_ORDER)				      \
69da0c48c4Sopenharmony_ci   ? (int32_t) bswap_32 (*((const int32_t *) (Addr)))			      \
70da0c48c4Sopenharmony_ci   : *((const int32_t *) (Addr)))
71da0c48c4Sopenharmony_ci
72da0c48c4Sopenharmony_ci# define read_8ubyte_unaligned(Addr) \
73da0c48c4Sopenharmony_ci  (unlikely (MACHINE_ENCODING != BYTE_ORDER)				      \
74da0c48c4Sopenharmony_ci   ? bswap_64 (*((const uint64_t *) (Addr)))				      \
75da0c48c4Sopenharmony_ci   : *((const uint64_t *) (Addr)))
76da0c48c4Sopenharmony_ci# define read_8sbyte_unaligned(Addr) \
77da0c48c4Sopenharmony_ci  (unlikely (MACHINE_ENCODING != BYTE_ORDER)				      \
78da0c48c4Sopenharmony_ci   ? (int64_t) bswap_64 (*((const int64_t *) (Addr)))			      \
79da0c48c4Sopenharmony_ci   : *((const int64_t *) (Addr)))
80da0c48c4Sopenharmony_ci
81da0c48c4Sopenharmony_ci#else
82da0c48c4Sopenharmony_ci
83da0c48c4Sopenharmony_ciunion unaligned
84da0c48c4Sopenharmony_ci  {
85da0c48c4Sopenharmony_ci    void *p;
86da0c48c4Sopenharmony_ci    uint16_t u2;
87da0c48c4Sopenharmony_ci    uint32_t u4;
88da0c48c4Sopenharmony_ci    uint64_t u8;
89da0c48c4Sopenharmony_ci    int16_t s2;
90da0c48c4Sopenharmony_ci    int32_t s4;
91da0c48c4Sopenharmony_ci    int64_t s8;
92da0c48c4Sopenharmony_ci  } attribute_packed;
93da0c48c4Sopenharmony_ci
94da0c48c4Sopenharmony_cistatic inline uint16_t
95da0c48c4Sopenharmony_ciread_2ubyte_unaligned (const void *p)
96da0c48c4Sopenharmony_ci{
97da0c48c4Sopenharmony_ci  const union unaligned *up = p;
98da0c48c4Sopenharmony_ci  if (MACHINE_ENCODING != BYTE_ORDER)
99da0c48c4Sopenharmony_ci    return bswap_16 (up->u2);
100da0c48c4Sopenharmony_ci  return up->u2;
101da0c48c4Sopenharmony_ci}
102da0c48c4Sopenharmony_cistatic inline int16_t
103da0c48c4Sopenharmony_ciread_2sbyte_unaligned (const void *p)
104da0c48c4Sopenharmony_ci{
105da0c48c4Sopenharmony_ci  const union unaligned *up = p;
106da0c48c4Sopenharmony_ci  if (MACHINE_ENCODING != BYTE_ORDER)
107da0c48c4Sopenharmony_ci    return (int16_t) bswap_16 (up->u2);
108da0c48c4Sopenharmony_ci  return up->s2;
109da0c48c4Sopenharmony_ci}
110da0c48c4Sopenharmony_ci
111da0c48c4Sopenharmony_cistatic inline uint32_t
112da0c48c4Sopenharmony_ciread_4ubyte_unaligned_noncvt (const void *p)
113da0c48c4Sopenharmony_ci{
114da0c48c4Sopenharmony_ci  const union unaligned *up = p;
115da0c48c4Sopenharmony_ci  return up->u4;
116da0c48c4Sopenharmony_ci}
117da0c48c4Sopenharmony_cistatic inline uint32_t
118da0c48c4Sopenharmony_ciread_4ubyte_unaligned (const void *p)
119da0c48c4Sopenharmony_ci{
120da0c48c4Sopenharmony_ci  const union unaligned *up = p;
121da0c48c4Sopenharmony_ci  if (MACHINE_ENCODING != BYTE_ORDER)
122da0c48c4Sopenharmony_ci    return bswap_32 (up->u4);
123da0c48c4Sopenharmony_ci  return up->u4;
124da0c48c4Sopenharmony_ci}
125da0c48c4Sopenharmony_cistatic inline int32_t
126da0c48c4Sopenharmony_ciread_4sbyte_unaligned (const void *p)
127da0c48c4Sopenharmony_ci{
128da0c48c4Sopenharmony_ci  const union unaligned *up = p;
129da0c48c4Sopenharmony_ci  if (MACHINE_ENCODING != BYTE_ORDER)
130da0c48c4Sopenharmony_ci    return (int32_t) bswap_32 (up->u4);
131da0c48c4Sopenharmony_ci  return up->s4;
132da0c48c4Sopenharmony_ci}
133da0c48c4Sopenharmony_ci
134da0c48c4Sopenharmony_cistatic inline uint64_t
135da0c48c4Sopenharmony_ciread_8ubyte_unaligned (const void *p)
136da0c48c4Sopenharmony_ci{
137da0c48c4Sopenharmony_ci  const union unaligned *up = p;
138da0c48c4Sopenharmony_ci  if (MACHINE_ENCODING != BYTE_ORDER)
139da0c48c4Sopenharmony_ci    return bswap_64 (up->u8);
140da0c48c4Sopenharmony_ci  return up->u8;
141da0c48c4Sopenharmony_ci}
142da0c48c4Sopenharmony_cistatic inline int64_t
143da0c48c4Sopenharmony_ciread_8sbyte_unaligned (const void *p)
144da0c48c4Sopenharmony_ci{
145da0c48c4Sopenharmony_ci  const union unaligned *up = p;
146da0c48c4Sopenharmony_ci  if (MACHINE_ENCODING != BYTE_ORDER)
147da0c48c4Sopenharmony_ci    return (int64_t) bswap_64 (up->u8);
148da0c48c4Sopenharmony_ci  return up->s8;
149da0c48c4Sopenharmony_ci}
150da0c48c4Sopenharmony_ci
151da0c48c4Sopenharmony_ci#endif	/* allow unaligned */
152da0c48c4Sopenharmony_ci
153da0c48c4Sopenharmony_ci
154da0c48c4Sopenharmony_ci#define read_2ubyte_unaligned_inc(Addr) \
155da0c48c4Sopenharmony_ci  ({ uint16_t t_ = read_2ubyte_unaligned (Addr);			      \
156da0c48c4Sopenharmony_ci     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2);		      \
157da0c48c4Sopenharmony_ci     t_; })
158da0c48c4Sopenharmony_ci#define read_2sbyte_unaligned_inc(Addr) \
159da0c48c4Sopenharmony_ci  ({ int16_t t_ = read_2sbyte_unaligned (Addr);				      \
160da0c48c4Sopenharmony_ci     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2);		      \
161da0c48c4Sopenharmony_ci     t_; })
162da0c48c4Sopenharmony_ci
163da0c48c4Sopenharmony_ci#define read_4ubyte_unaligned_inc(Addr) \
164da0c48c4Sopenharmony_ci  ({ uint32_t t_ = read_4ubyte_unaligned (Addr);			      \
165da0c48c4Sopenharmony_ci     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4);		      \
166da0c48c4Sopenharmony_ci     t_; })
167da0c48c4Sopenharmony_ci#define read_4sbyte_unaligned_inc(Addr) \
168da0c48c4Sopenharmony_ci  ({ int32_t t_ = read_4sbyte_unaligned (Addr);				      \
169da0c48c4Sopenharmony_ci     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4);		      \
170da0c48c4Sopenharmony_ci     t_; })
171da0c48c4Sopenharmony_ci
172da0c48c4Sopenharmony_ci#define read_8ubyte_unaligned_inc(Addr) \
173da0c48c4Sopenharmony_ci  ({ uint64_t t_ = read_8ubyte_unaligned (Addr);			      \
174da0c48c4Sopenharmony_ci     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8);		      \
175da0c48c4Sopenharmony_ci     t_; })
176da0c48c4Sopenharmony_ci#define read_8sbyte_unaligned_inc(Addr) \
177da0c48c4Sopenharmony_ci  ({ int64_t t_ = read_8sbyte_unaligned (Addr);				      \
178da0c48c4Sopenharmony_ci     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8);		      \
179da0c48c4Sopenharmony_ci     t_; })
180da0c48c4Sopenharmony_ci
181da0c48c4Sopenharmony_ci#endif	/* memory-access.h */
182