1 /* This file is part of the program psim.
3 Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #ifndef _SIM_ENDIAN_H_
23 #define _SIM_ENDIAN_H_
25 #ifndef INLINE_SIM_ENDIAN
26 #define INLINE_SIM_ENDIAN
30 /* C byte conversion functions */
32 INLINE_SIM_ENDIAN unsigned_1
endian_h2t_1(unsigned_1 x
);
33 INLINE_SIM_ENDIAN unsigned_2
endian_h2t_2(unsigned_2 x
);
34 INLINE_SIM_ENDIAN unsigned_4
endian_h2t_4(unsigned_4 x
);
35 INLINE_SIM_ENDIAN unsigned_8
endian_h2t_8(unsigned_8 x
);
37 INLINE_SIM_ENDIAN unsigned_1
endian_t2h_1(unsigned_1 x
);
38 INLINE_SIM_ENDIAN unsigned_2
endian_t2h_2(unsigned_2 x
);
39 INLINE_SIM_ENDIAN unsigned_4
endian_t2h_4(unsigned_4 x
);
40 INLINE_SIM_ENDIAN unsigned_8
endian_t2h_8(unsigned_8 x
);
42 INLINE_SIM_ENDIAN unsigned_1
swap_1(unsigned_1 x
);
43 INLINE_SIM_ENDIAN unsigned_2
swap_2(unsigned_2 x
);
44 INLINE_SIM_ENDIAN unsigned_4
swap_4(unsigned_4 x
);
45 INLINE_SIM_ENDIAN unsigned_8
swap_8(unsigned_8 x
);
50 The CPP below defines information about the compilation host. In
51 particular it defines the macro's:
53 WITH_HOST_BYTE_ORDER The byte order of the host. Could
54 be any of LITTLE_ENDIAN, BIG_ENDIAN
55 or 0 (unknown). Those macro's also
58 WITH_NTOH Network byte order macros defined.
59 Possible value is 32 or (maybe one
60 day 64 because some 64bit network
61 byte order macro is defined.
67 NetBSD is easy, everything you could ever want is in a header file
70 #if defined(__NetBSD__)
71 # include <machine/endian.h>
72 # define WITH_NTOH 32 /* what about alpha? */
73 # if (WITH_HOST_BYTE_ORDER == 0)
74 # undef WITH_HOST_BYTE_ORDER
75 # define WITH_HOST_BYTE_ORDER BYTE_ORDER
77 # if (BYTE_ORDER != WITH_HOST_BYTE_ORDER)
78 # error "host endian incorrectly configured, check config.h"
82 /* Linux is similarly easy. */
84 #if defined(__linux__)
86 # include <asm/byteorder.h>
87 # if defined(__LITTLE_ENDIAN) && !defined(LITTLE_ENDIAN)
88 # define LITTLE_ENDIAN __LITTLE_ENDIAN
90 # if defined(__BIG_ENDIAN) && !defined(BIG_ENDIAN)
91 # define BIG_ENDIAN __BIG_ENDIAN
93 # if defined(__BYTE_ORDER) && !defined(BYTE_ORDER)
94 # define BYTE_ORDER __BYTE_ORDER
96 # if !defined(__alpha__)
97 # define WITH_NTOH 32 /* what about alpha? */
99 # if (WITH_HOST_BYTE_ORDER == 0)
100 # undef WITH_HOST_BYTE_ORDER
101 # define WITH_HOST_BYTE_ORDER BYTE_ORDER
103 # if (BYTE_ORDER != WITH_HOST_BYTE_ORDER)
104 # error "host endian incorrectly configured, check config.h"
108 /* INSERT HERE - hosts that have available LITTLE_ENDIAN and
109 BIG_ENDIAN macro's */
112 /* Some hosts don't define LITTLE_ENDIAN or BIG_ENDIAN, help them out */
114 #ifndef LITTLE_ENDIAN
115 #define LITTLE_ENDIAN 1234
118 #define BIG_ENDIAN 4321
124 Big endian last time I looked */
126 #if defined(sparc) || defined(__sparc__)
127 # if (WITH_HOST_BYTE_ORDER == 0)
128 # undef WITH_HOST_BYTE_ORDER
129 # define WITH_HOST_BYTE_ORDER BIG_ENDIAN
131 # if (WITH_HOST_BYTE_ORDER != BIG_ENDIAN)
132 # error "sun was big endian last time I looked ..."
139 Little endian last time I looked */
141 #if defined(i386) || defined(i486) || defined(i586) || defined(__i386__) || defined(__i486__) || defined(__i586__)
142 # if (WITH_HOST_BYTE_ORDER == 0)
143 # undef WITH_HOST_BYTE_ORDER
144 # define WITH_HOST_BYTE_ORDER LITTLE_ENDIAN
146 # if (WITH_HOST_BYTE_ORDER != LITTLE_ENDIAN)
147 # error "x86 was little endian last time I looked ..."
151 #if (defined (__i486__) || defined (__i586__)) && defined(__GNUC__) && WITH_BSWAP && WITH_NTOH
154 #define htonl(IN) __extension__ ({ int _out; __asm__ ("bswap %0" : "=r" (_out) : "0" (IN)); _out; })
155 #define ntohl(IN) __extension__ ({ int _out; __asm__ ("bswap %0" : "=r" (_out) : "0" (IN)); _out; })
159 /* Configure defines WORDS_BIGENDIAN if the host is big endian. */
161 #if (WITH_HOST_BYTE_ORDER == 0)
162 # undef WITH_HOST_BYTE_ORDER
163 # ifdef WORDS_BIGENDIAN
164 # define WITH_HOST_BYTE_ORDER BIG_ENDIAN
166 # define WITH_HOST_BYTE_ORDER LITTLE_ENDIAN
172 Some times a swap must always be performed, select the most
173 effecient method to swap a collection of bytes.
181 #if (WITH_HOST_BYTE_ORDER \
183 && WITH_HOST_BYTE_ORDER == LITTLE_ENDIAN)
184 #define SWAP_1(X) (X)
185 #define SWAP_2(X) ntohs(X)
186 #define SWAP_4(X) ntohl(X)
187 #define SWAP_8(X) swap_8(X)
189 #define SWAP_1(X) (X)
190 #define SWAP_2(X) swap_2(X)
191 #define SWAP_4(X) swap_4(X)
192 #define SWAP_8(X) swap_8(X)
198 Convert between host and target byte orders by the most efficient
199 method known (if needed at all)
201 TARG BE TARG LE TARG ??
203 HOST LE htohl ok ok|ntohl
204 HOST ?? ntohl swap swap
211 Returns the value swapped according to the host/target byte order */
213 /* no need to swap */
214 #if (WITH_HOST_BYTE_ORDER \
215 && WITH_TARGET_BYTE_ORDER \
216 && WITH_HOST_BYTE_ORDER == WITH_TARGET_BYTE_ORDER )
227 /* have ntoh and big endian target */
228 #if (WITH_TARGET_BYTE_ORDER == BIG_ENDIAN \
229 && WITH_HOST_BYTE_ORDER != BIG_ENDIAN \
231 #define H2T_8(X) endian_h2t_8(X)
232 #define H2T_4(X) htonl(X)
233 #define H2T_2(X) htons(X)
235 #define T2H_8(X) endian_t2h_8(X)
236 #define T2H_4(X) htonl(X)
237 #define T2H_2(X) htons(X)
241 /* have ntoh, little host and unknown target */
242 #if (WITH_HOST_BYTE_ORDER == LITTLE_ENDIAN \
243 && WITH_TARGET_BYTE_ORDER == 0 \
245 #define H2T_8(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER \
246 ? (X) : endian_h2t_8(X))
247 #define H2T_4(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER \
249 #define H2T_2(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER \
251 #define H2T_1(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER \
253 #define T2H_8(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER \
254 ? (X) : endian_t2h_8(X))
255 #define T2H_4(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER \
257 #define T2H_2(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER \
259 #define T2H_1(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER \
263 /* if all else fails use software */
266 #define H2T_2(X) endian_h2t_2(X)
267 #define H2T_4(X) endian_h2t_4(X)
268 #define H2T_8(X) endian_h2t_8(X)
270 #define T2H_2(X) endian_t2h_2(X)
271 #define T2H_4(X) endian_t2h_4(X)
272 #define T2H_8(X) endian_t2h_8(X)
278 These macros, given an argument of unknown size, swap its value in
279 place if a host/target conversion is required. */
281 #define H2T(VARIABLE) \
283 switch (sizeof(VARIABLE)) { \
284 case 1: VARIABLE = H2T_1(VARIABLE); break; \
285 case 2: VARIABLE = H2T_2(VARIABLE); break; \
286 case 4: VARIABLE = H2T_4(VARIABLE); break; \
287 case 8: VARIABLE = H2T_8(VARIABLE); break; \
291 #define T2H(VARIABLE) \
293 switch (sizeof(VARIABLE)) { \
294 case 1: VARIABLE = T2H_1(VARIABLE); break; \
295 case 2: VARIABLE = T2H_2(VARIABLE); break; \
296 case 4: VARIABLE = T2H_4(VARIABLE); break; \
297 case 8: VARIABLE = T2H_8(VARIABLE); break; \
304 Byte swap a quantity the size of the targets word */
306 #if (WITH_TARGET_WORD_BITSIZE == 64)
307 #define H2T_word(X) H2T_8(X)
308 #define T2H_word(X) T2H_8(X)
310 #if (WITH_TARGET_WORD_BITSIZE == 32)
311 #define H2T_word(X) H2T_4(X)
312 #define T2H_word(X) T2H_4(X)
315 #endif /* _SIM_ENDIAN_H_ */