This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.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_ */