Wed Dec 16 16:17:22 1998 Dave Brolley <brolley@cygnus.com>
[binutils-gdb.git] / sim / ppc / sim-endian.h
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
4
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.
9
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.
14
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.
18
19 */
20
21
22 #ifndef _SIM_ENDIAN_H_
23 #define _SIM_ENDIAN_H_
24
25 #ifndef INLINE_SIM_ENDIAN
26 #define INLINE_SIM_ENDIAN
27 #endif
28
29
30 /* C byte conversion functions */
31
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);
36
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);
41
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);
46
47
48 /* Host dependant:
49
50 The CPP below defines information about the compilation host. In
51 particular it defines the macro's:
52
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
56 need to be defined.
57
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.
62 */
63
64
65 /* NetBSD:
66
67 NetBSD is easy, everything you could ever want is in a header file
68 (well almost :-) */
69
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
76 # endif
77 # if (BYTE_ORDER != WITH_HOST_BYTE_ORDER)
78 # error "host endian incorrectly configured, check config.h"
79 # endif
80 #endif
81
82 /* Linux is similarly easy. */
83
84 #if defined(__linux__)
85 # include <endian.h>
86 # include <asm/byteorder.h>
87 # if defined(__LITTLE_ENDIAN) && !defined(LITTLE_ENDIAN)
88 # define LITTLE_ENDIAN __LITTLE_ENDIAN
89 # endif
90 # if defined(__BIG_ENDIAN) && !defined(BIG_ENDIAN)
91 # define BIG_ENDIAN __BIG_ENDIAN
92 # endif
93 # if defined(__BYTE_ORDER) && !defined(BYTE_ORDER)
94 # define BYTE_ORDER __BYTE_ORDER
95 # endif
96 # if !defined(__alpha__)
97 # define WITH_NTOH 32 /* what about alpha? */
98 # endif
99 # if (WITH_HOST_BYTE_ORDER == 0)
100 # undef WITH_HOST_BYTE_ORDER
101 # define WITH_HOST_BYTE_ORDER BYTE_ORDER
102 # endif
103 # if (BYTE_ORDER != WITH_HOST_BYTE_ORDER)
104 # error "host endian incorrectly configured, check config.h"
105 # endif
106 #endif
107
108 /* INSERT HERE - hosts that have available LITTLE_ENDIAN and
109 BIG_ENDIAN macro's */
110
111
112 /* Some hosts don't define LITTLE_ENDIAN or BIG_ENDIAN, help them out */
113
114 #ifndef LITTLE_ENDIAN
115 #define LITTLE_ENDIAN 1234
116 #endif
117 #ifndef BIG_ENDIAN
118 #define BIG_ENDIAN 4321
119 #endif
120
121
122 /* SunOS on SPARC:
123
124 Big endian last time I looked */
125
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
130 # endif
131 # if (WITH_HOST_BYTE_ORDER != BIG_ENDIAN)
132 # error "sun was big endian last time I looked ..."
133 # endif
134 #endif
135
136
137 /* Random x86
138
139 Little endian last time I looked */
140
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
145 # endif
146 # if (WITH_HOST_BYTE_ORDER != LITTLE_ENDIAN)
147 # error "x86 was little endian last time I looked ..."
148 # endif
149 #endif
150
151 #if (defined (__i486__) || defined (__i586__)) && defined(__GNUC__) && WITH_BSWAP && WITH_NTOH
152 #undef htonl
153 #undef ntohl
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; })
156 #endif
157
158
159 /* Configure defines WORDS_BIGENDIAN if the host is big endian. */
160
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
165 # else
166 # define WITH_HOST_BYTE_ORDER LITTLE_ENDIAN
167 # endif
168 #endif
169
170 /* SWAP:
171
172 Some times a swap must always be performed, select the most
173 effecient method to swap a collection of bytes.
174
175 HOST BE sw
176 HOST LE sw/ntoh
177 HOST ?? sw
178
179 */
180
181 #if (WITH_HOST_BYTE_ORDER \
182 && WITH_NTOH \
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)
188 #else
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)
193 #endif
194
195
196 /* CONVERSION:
197
198 Convert between host and target byte orders by the most efficient
199 method known (if needed at all)
200
201 TARG BE TARG LE TARG ??
202 HOST BE ok swap swap
203 HOST LE htohl ok ok|ntohl
204 HOST ?? ntohl swap swap
205
206 */
207
208
209 /* FUNCTIONS:
210
211 Returns the value swapped according to the host/target byte order */
212
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 )
217 #define H2T_1(X) (X)
218 #define H2T_2(X) (X)
219 #define H2T_4(X) (X)
220 #define H2T_8(X) (X)
221 #define T2H_1(X) (X)
222 #define T2H_2(X) (X)
223 #define T2H_4(X) (X)
224 #define T2H_8(X) (X)
225 #endif
226
227 /* have ntoh and big endian target */
228 #if (WITH_TARGET_BYTE_ORDER == BIG_ENDIAN \
229 && WITH_HOST_BYTE_ORDER != BIG_ENDIAN \
230 && WITH_NTOH)
231 #define H2T_8(X) endian_h2t_8(X)
232 #define H2T_4(X) htonl(X)
233 #define H2T_2(X) htons(X)
234 #define H2T_1(X) (X)
235 #define T2H_8(X) endian_t2h_8(X)
236 #define T2H_4(X) htonl(X)
237 #define T2H_2(X) htons(X)
238 #define T2H_1(X) (X)
239 #endif
240
241 /* have ntoh, little host and unknown target */
242 #if (WITH_HOST_BYTE_ORDER == LITTLE_ENDIAN \
243 && WITH_TARGET_BYTE_ORDER == 0 \
244 && WITH_NTOH)
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 \
248 ? (X) : htonl(X))
249 #define H2T_2(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER \
250 ? (X) : htons(X))
251 #define H2T_1(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER \
252 ? (X) : (X))
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 \
256 ? (X) : htonl(X))
257 #define T2H_2(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER \
258 ? (X) : htons(X))
259 #define T2H_1(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER \
260 ? (X) : (X))
261 #endif
262
263 /* if all else fails use software */
264 #ifndef H2T_1
265 #define H2T_1(X) (X)
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)
269 #define T2H_1(X) (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)
273 #endif
274
275
276 /* CONVERT IN PLACE:
277
278 These macros, given an argument of unknown size, swap its value in
279 place if a host/target conversion is required. */
280
281 #define H2T(VARIABLE) \
282 do { \
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; \
288 } \
289 } while (0)
290
291 #define T2H(VARIABLE) \
292 do { \
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; \
298 } \
299 } while (0)
300
301
302 /* TARGET WORD:
303
304 Byte swap a quantity the size of the targets word */
305
306 #if (WITH_TARGET_WORD_BITSIZE == 64)
307 #define H2T_word(X) H2T_8(X)
308 #define T2H_word(X) T2H_8(X)
309 #endif
310 #if (WITH_TARGET_WORD_BITSIZE == 32)
311 #define H2T_word(X) H2T_4(X)
312 #define T2H_word(X) T2H_4(X)
313 #endif
314
315 #endif /* _SIM_ENDIAN_H_ */