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 26/* C byte conversion functions */ 27 28INLINE_PSIM_ENDIAN(unsigned_1) endian_h2t_1(unsigned_1 x); 29INLINE_PSIM_ENDIAN(unsigned_2) endian_h2t_2(unsigned_2 x); 30INLINE_PSIM_ENDIAN(unsigned_4) endian_h2t_4(unsigned_4 x); 31INLINE_PSIM_ENDIAN(unsigned_8) endian_h2t_8(unsigned_8 x); 32 33INLINE_PSIM_ENDIAN(unsigned_1) endian_t2h_1(unsigned_1 x); 34INLINE_PSIM_ENDIAN(unsigned_2) endian_t2h_2(unsigned_2 x); 35INLINE_PSIM_ENDIAN(unsigned_4) endian_t2h_4(unsigned_4 x); 36INLINE_PSIM_ENDIAN(unsigned_8) endian_t2h_8(unsigned_8 x); 37 38INLINE_PSIM_ENDIAN(unsigned_1) swap_1(unsigned_1 x); 39INLINE_PSIM_ENDIAN(unsigned_2) swap_2(unsigned_2 x); 40INLINE_PSIM_ENDIAN(unsigned_4) swap_4(unsigned_4 x); 41INLINE_PSIM_ENDIAN(unsigned_8) swap_8(unsigned_8 x); 42 43INLINE_PSIM_ENDIAN(unsigned_1) endian_h2be_1(unsigned_1 x); 44INLINE_PSIM_ENDIAN(unsigned_2) endian_h2be_2(unsigned_2 x); 45INLINE_PSIM_ENDIAN(unsigned_4) endian_h2be_4(unsigned_4 x); 46INLINE_PSIM_ENDIAN(unsigned_8) endian_h2be_8(unsigned_8 x); 47 48INLINE_PSIM_ENDIAN(unsigned_1) endian_be2h_1(unsigned_1 x); 49INLINE_PSIM_ENDIAN(unsigned_2) endian_be2h_2(unsigned_2 x); 50INLINE_PSIM_ENDIAN(unsigned_4) endian_be2h_4(unsigned_4 x); 51INLINE_PSIM_ENDIAN(unsigned_8) endian_be2h_8(unsigned_8 x); 52 53INLINE_PSIM_ENDIAN(unsigned_1) endian_h2le_1(unsigned_1 x); 54INLINE_PSIM_ENDIAN(unsigned_2) endian_h2le_2(unsigned_2 x); 55INLINE_PSIM_ENDIAN(unsigned_4) endian_h2le_4(unsigned_4 x); 56INLINE_PSIM_ENDIAN(unsigned_8) endian_h2le_8(unsigned_8 x); 57 58INLINE_PSIM_ENDIAN(unsigned_1) endian_le2h_1(unsigned_1 x); 59INLINE_PSIM_ENDIAN(unsigned_2) endian_le2h_2(unsigned_2 x); 60INLINE_PSIM_ENDIAN(unsigned_4) endian_le2h_4(unsigned_4 x); 61INLINE_PSIM_ENDIAN(unsigned_8) endian_le2h_8(unsigned_8 x); 62 63 64/* Host dependant: 65 66 The CPP below defines information about the compilation host. In 67 particular it defines the macro's: 68 69 WITH_HOST_BYTE_ORDER The byte order of the host. Could 70 be any of LITTLE_ENDIAN, BIG_ENDIAN 71 or 0 (unknown). Those macro's also 72 need to be defined. 73 74 */ 75 76 77/* NetBSD: 78 79 NetBSD is easy, everything you could ever want is in a header file 80 (well almost :-) */ 81 82#if defined(__NetBSD__) 83# include <machine/endian.h> 84# if (WITH_HOST_BYTE_ORDER == 0) 85# undef WITH_HOST_BYTE_ORDER 86# define WITH_HOST_BYTE_ORDER BYTE_ORDER 87# endif 88# if (BYTE_ORDER != WITH_HOST_BYTE_ORDER) 89# error "host endian incorrectly configured, check config.h" 90# endif 91#endif 92 93/* Linux is similarly easy. */ 94 95#if defined(__linux__) 96# include <endian.h> 97# if defined(__LITTLE_ENDIAN) && !defined(LITTLE_ENDIAN) 98# define LITTLE_ENDIAN __LITTLE_ENDIAN 99# endif 100# if defined(__BIG_ENDIAN) && !defined(BIG_ENDIAN) 101# define BIG_ENDIAN __BIG_ENDIAN 102# endif 103# if defined(__BYTE_ORDER) && !defined(BYTE_ORDER) 104# define BYTE_ORDER __BYTE_ORDER 105# endif 106# if (WITH_HOST_BYTE_ORDER == 0) 107# undef WITH_HOST_BYTE_ORDER 108# define WITH_HOST_BYTE_ORDER BYTE_ORDER 109# endif 110# if (BYTE_ORDER != WITH_HOST_BYTE_ORDER) 111# error "host endian incorrectly configured, check config.h" 112# endif 113#endif 114 115/* INSERT HERE - hosts that have available LITTLE_ENDIAN and 116 BIG_ENDIAN macro's */ 117 118 119/* Some hosts don't define LITTLE_ENDIAN or BIG_ENDIAN, help them out */ 120 121#ifndef LITTLE_ENDIAN 122#define LITTLE_ENDIAN 1234 123#endif 124#ifndef BIG_ENDIAN 125#define BIG_ENDIAN 4321 126#endif 127 128 129/* SunOS on SPARC: 130 131 Big endian last time I looked */ 132 133#if defined(sparc) || defined(__sparc__) 134# if (WITH_HOST_BYTE_ORDER == 0) 135# undef WITH_HOST_BYTE_ORDER 136# define WITH_HOST_BYTE_ORDER BIG_ENDIAN 137# endif 138# if (WITH_HOST_BYTE_ORDER != BIG_ENDIAN) 139# error "sun was big endian last time I looked ..." 140# endif 141#endif 142 143 144/* Random x86 145 146 Little endian last time I looked */ 147 148#if defined(i386) || defined(i486) || defined(i586) || defined (i686) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined (__i686__) 149# if (WITH_HOST_BYTE_ORDER == 0) 150# undef WITH_HOST_BYTE_ORDER 151# define WITH_HOST_BYTE_ORDER LITTLE_ENDIAN 152# endif 153# if (WITH_HOST_BYTE_ORDER != LITTLE_ENDIAN) 154# error "x86 was little endian last time I looked ..." 155# endif 156#endif 157 158#if (defined (__i486__) || defined (__i586__) || defined (__i686__)) && defined(__GNUC__) && WITH_BSWAP 159#undef htonl 160#undef ntohl 161#define htonl(IN) __extension__ ({ int _out; __asm__ ("bswap %0" : "=r" (_out) : "0" (IN)); _out; }) 162#define ntohl(IN) __extension__ ({ int _out; __asm__ ("bswap %0" : "=r" (_out) : "0" (IN)); _out; }) 163#endif 164 165/* Power or PowerPC running AIX */ 166#if defined(_POWER) && defined(_AIX) 167# if (WITH_HOST_BYTE_ORDER == 0) 168# undef WITH_HOST_BYTE_ORDER 169# define WITH_HOST_BYTE_ORDER BIG_ENDIAN 170# endif 171# if (WITH_HOST_BYTE_ORDER != BIG_ENDIAN) 172# error "Power/PowerPC AIX was big endian last time I looked ..." 173# endif 174#endif 175 176/* Solaris running PowerPC */ 177#if defined(__PPC) && defined(__sun__) 178# if (WITH_HOST_BYTE_ORDER == 0) 179# undef WITH_HOST_BYTE_ORDER 180# define WITH_HOST_BYTE_ORDER LITTLE_ENDIAN 181# endif 182# if (WITH_HOST_BYTE_ORDER != LITTLE_ENDIAN) 183# error "Solaris on PowerPCs was little endian last time I looked ..." 184# endif 185#endif 186 187/* HP/PA */ 188#if defined(__hppa__) 189# if (WITH_HOST_BYTE_ORDER == 0) 190# undef WITH_HOST_BYTE_ORDER 191# define WITH_HOST_BYTE_ORDER BIG_ENDIAN 192# endif 193# if (WITH_HOST_BYTE_ORDER != BIG_ENDIAN) 194# error "HP/PA was big endian last time I looked ..." 195# endif 196#endif 197 198/* Big endian MIPS */ 199#if defined(__MIPSEB__) 200# if (WITH_HOST_BYTE_ORDER == 0) 201# undef WITH_HOST_BYTE_ORDER 202# define WITH_HOST_BYTE_ORDER BIG_ENDIAN 203# endif 204# if (WITH_HOST_BYTE_ORDER != BIG_ENDIAN) 205# error "MIPSEB was big endian last time I looked ..." 206# endif 207#endif 208 209/* Little endian MIPS */ 210#if defined(__MIPSEL__) 211# if (WITH_HOST_BYTE_ORDER == 0) 212# undef WITH_HOST_BYTE_ORDER 213# define WITH_HOST_BYTE_ORDER LITTLE_ENDIAN 214# endif 215# if (WITH_HOST_BYTE_ORDER != LITTLE_ENDIAN) 216# error "MIPSEL was little endian last time I looked ..." 217# endif 218#endif 219 220/* Windows NT */ 221#if defined(__WIN32__) 222# if (WITH_HOST_BYTE_ORDER == 0) 223# undef WITH_HOST_BYTE_ORDER 224# define WITH_HOST_BYTE_ORDER LITTLE_ENDIAN 225# endif 226# if (WITH_HOST_BYTE_ORDER != LITTLE_ENDIAN) 227# error "Windows NT was little endian last time I looked ..." 228# endif 229#endif 230 231/* Alpha running DEC unix */ 232#if defined(__osf__) && defined(__alpha__) 233# if (WITH_HOST_BYTE_ORDER == 0) 234# undef WITH_HOST_BYTE_ORDER 235# define WITH_HOST_BYTE_ORDER LITTLE_ENDIAN 236# endif 237# if (WITH_HOST_BYTE_ORDER != LITTLE_ENDIAN) 238# error "AXP running DEC unix was little endian last time I looked ..." 239# endif 240#endif 241 242 243/* INSERT HERE - additional hosts that do not have LITTLE_ENDIAN and 244 BIG_ENDIAN definitions available. */ 245 246/* SWAP */ 247 248#define SWAP_1 swap_1 249#define SWAP_2 swap_2 250#define SWAP_4 swap_4 251#define SWAP_8 swap_8 252 253 254/* HOST to BE */ 255 256#define H2BE_1 endian_h2be_1 257#define H2BE_2 endian_h2be_2 258#define H2BE_4 endian_h2be_4 259#define H2BE_8 endian_h2be_8 260#define BE2H_1 endian_be2h_1 261#define BE2H_2 endian_be2h_2 262#define BE2H_4 endian_be2h_4 263#define BE2H_8 endian_be2h_8 264 265 266/* HOST to LE */ 267 268#define H2LE_1 endian_h2le_1 269#define H2LE_2 endian_h2le_2 270#define H2LE_4 endian_h2le_4 271#define H2LE_8 endian_h2le_8 272#define LE2H_1 endian_le2h_1 273#define LE2H_2 endian_le2h_2 274#define LE2H_4 endian_le2h_4 275#define LE2H_8 endian_le2h_8 276 277 278/* HOST to TARGET */ 279 280#define H2T_1 endian_h2t_1 281#define H2T_2 endian_h2t_2 282#define H2T_4 endian_h2t_4 283#define H2T_8 endian_h2t_8 284#define T2H_1 endian_t2h_1 285#define T2H_2 endian_t2h_2 286#define T2H_4 endian_t2h_4 287#define T2H_8 endian_t2h_8 288 289 290/* CONVERT IN PLACE 291 292 These macros, given an argument of unknown size, swap its value in 293 place if a host/target conversion is required. */ 294 295#define H2T(VARIABLE) \ 296do { \ 297 switch (sizeof(VARIABLE)) { \ 298 case 1: VARIABLE = H2T_1(VARIABLE); break; \ 299 case 2: VARIABLE = H2T_2(VARIABLE); break; \ 300 case 4: VARIABLE = H2T_4(VARIABLE); break; \ 301 case 8: VARIABLE = H2T_8(VARIABLE); break; \ 302 } \ 303} while (0) 304 305#define T2H(VARIABLE) \ 306do { \ 307 switch (sizeof(VARIABLE)) { \ 308 case 1: VARIABLE = T2H_1(VARIABLE); break; \ 309 case 2: VARIABLE = T2H_2(VARIABLE); break; \ 310 case 4: VARIABLE = T2H_4(VARIABLE); break; \ 311 case 8: VARIABLE = T2H_8(VARIABLE); break; \ 312 } \ 313} while (0) 314 315#define SWAP(VARIABLE) \ 316do { \ 317 switch (sizeof(VARIABLE)) { \ 318 case 1: VARIABLE = SWAP_1(VARIABLE); break; \ 319 case 2: VARIABLE = SWAP_2(VARIABLE); break; \ 320 case 4: VARIABLE = SWAP_4(VARIABLE); break; \ 321 case 8: VARIABLE = SWAP_8(VARIABLE); break; \ 322 } \ 323} while (0) 324 325#define H2BE(VARIABLE) \ 326do { \ 327 switch (sizeof(VARIABLE)) { \ 328 case 1: VARIABLE = H2BE_1(VARIABLE); break; \ 329 case 2: VARIABLE = H2BE_2(VARIABLE); break; \ 330 case 4: VARIABLE = H2BE_4(VARIABLE); break; \ 331 case 8: VARIABLE = H2BE_8(VARIABLE); break; \ 332 } \ 333} while (0) 334 335#define BE2H(VARIABLE) \ 336do { \ 337 switch (sizeof(VARIABLE)) { \ 338 case 1: VARIABLE = BE2H_1(VARIABLE); break; \ 339 case 2: VARIABLE = BE2H_2(VARIABLE); break; \ 340 case 4: VARIABLE = BE2H_4(VARIABLE); break; \ 341 case 8: VARIABLE = BE2H_8(VARIABLE); break; \ 342 } \ 343} while (0) 344 345#define H2LE(VARIABLE) \ 346do { \ 347 switch (sizeof(VARIABLE)) { \ 348 case 1: VARIABLE = H2LE_1(VARIABLE); break; \ 349 case 2: VARIABLE = H2LE_2(VARIABLE); break; \ 350 case 4: VARIABLE = H2LE_4(VARIABLE); break; \ 351 case 8: VARIABLE = H2LE_8(VARIABLE); break; \ 352 } \ 353} while (0) 354 355#define LE2H(VARIABLE) \ 356do { \ 357 switch (sizeof(VARIABLE)) { \ 358 case 1: VARIABLE = LE2H_1(VARIABLE); break; \ 359 case 2: VARIABLE = LE2H_2(VARIABLE); break; \ 360 case 4: VARIABLE = LE2H_4(VARIABLE); break; \ 361 case 8: VARIABLE = LE2H_8(VARIABLE); break; \ 362 } \ 363} while (0) 364 365 366 367/* TARGET WORD: 368 369 Byte swap a quantity the size of the targets word */ 370 371#if (WITH_TARGET_WORD_BITSIZE == 64) 372#define H2T_word H2T_8 373#define T2H_word T2H_8 374#define H2BE_word H2BE_8 375#define BE2H_word BE2H_8 376#define H2LE_word H2LE_8 377#define LE2H_word LE2H_8 378#define SWAP_word SWAP_8 379#endif 380#if (WITH_TARGET_WORD_BITSIZE == 32) 381#define H2T_word H2T_4 382#define T2H_word T2H_4 383#define H2BE_word H2BE_4 384#define BE2H_word BE2H_4 385#define H2LE_word H2LE_4 386#define LE2H_word LE2H_4 387#define SWAP_word SWAP_4 388#endif 389 390 391/* TARGET CELL: 392 393 Byte swap a quantity the size of the targets IEEE 1275 memory cell */ 394 395#define H2T_cell H2T_4 396#define T2H_cell T2H_4 397#define H2BE_cell H2BE_4 398#define BE2H_cell BE2H_4 399#define H2LE_cell H2LE_4 400#define LE2H_cell LE2H_4 401#define SWAP_cell SWAP_4 402 403 404#if (SIM_ENDIAN_INLINE & INCLUDE_MODULE) 405# include "sim-endian.c" 406#endif 407 408#endif /* _SIM_ENDIAN_H_ */ 409