1/* If we're being compiled as a .c file, rather than being included in 2 d10v_sim.h, then ENDIAN_INLINE won't be defined yet. */ 3 4#ifndef ENDIAN_INLINE 5#define NO_ENDIAN_INLINE 6#include "d10v_sim.h" 7#define ENDIAN_INLINE 8#endif 9 10ENDIAN_INLINE uint16 11get_word (x) 12 uint8 *x; 13{ 14#if (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__) 15 16 unsigned short word = *(unsigned short *)x; 17 __asm__ ("xchgb %b0,%h0" : "=q" (word) : "0" (word)); 18 return word; 19 20#elif defined(WORDS_BIGENDIAN) 21 /* It is safe to do this on big endian hosts, since the d10v requires that words be 22 aligned on 16-bit boundaries. */ 23 return *(uint16 *)x; 24 25#else 26 return ((uint16)x[0]<<8) + x[1]; 27#endif 28} 29 30ENDIAN_INLINE uint32 31get_longword (x) 32 uint8 *x; 33{ 34#if (defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__) && defined(USE_BSWAP) 35 36 unsigned int long_word = *(unsigned *)x; 37 __asm__ ("bswap %0" : "=r" (long_word) : "0" (long_word)); 38 return long_word; 39 40#elif (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__) 41 42 unsigned int long_word = *(unsigned *)x; 43 __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ 44 "rorl $16,%0\n\t" /* swap words */ 45 "xchgb %b0,%h0" /* swap higher bytes */ 46 :"=q" (long_word) 47 : "0" (long_word)); 48 49 return long_word; 50 51#elif (defined(_POWER) && defined(_AIX)) || (defined(__PPC__) && defined(__BIG_ENDIAN__)) 52 /* Power & PowerPC computers in big endian mode can handle unaligned loads&stores */ 53 return *(uint32 *)x; 54 55#elif defined(WORDS_BIGENDIAN) 56 /* long words must be aligned on at least 16-bit boundaries, so this should be safe. */ 57 return (((uint32) *(uint16 *)x)<<16) | ((uint32) *(uint16 *)(x+2)); 58 59#else 60 return ((uint32)x[0]<<24) + ((uint32)x[1]<<16) + ((uint32)x[2]<<8) + ((uint32)x[3]); 61#endif 62} 63 64ENDIAN_INLINE int64 65get_longlong (x) 66 uint8 *x; 67{ 68 uint32 top = get_longword (x); 69 uint32 bottom = get_longword (x+4); 70 return (((int64)top)<<32) | (int64)bottom; 71} 72 73ENDIAN_INLINE void 74write_word (addr, data) 75 uint8 *addr; 76 uint16 data; 77{ 78#if (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__) 79 80 __asm__ ("xchgb %b0,%h0" : "=q" (data) : "0" (data)); 81 *(uint16 *)addr = data; 82 83#elif defined(WORDS_BIGENDIAN) 84 /* It is safe to do this on big endian hosts, since the d10v requires that words be 85 aligned on 16-bit boundaries. */ 86 *(uint16 *)addr = data; 87 88#else 89 addr[0] = (data >> 8) & 0xff; 90 addr[1] = data & 0xff; 91#endif 92} 93 94ENDIAN_INLINE void 95write_longword (addr, data) 96 uint8 *addr; 97 uint32 data; 98{ 99#if (defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__) && defined(USE_BSWAP) 100 101 __asm__ ("bswap %0" : "=r" (data) : "0" (data)); 102 *(uint32 *)addr = data; 103 104#elif (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__) 105 106 __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ 107 "rorl $16,%0\n\t" /* swap words */ 108 "xchgb %b0,%h0" /* swap higher bytes */ 109 :"=q" (data) 110 : "0" (data)); 111 112 *(uint32 *)addr = data; 113 114#elif (defined(_POWER) && defined(_AIX)) || (defined(__PPC__) && defined(__BIG_ENDIAN__)) 115 /* Power & PowerPC computers in big endian mode can handle unaligned loads&stores */ 116 *(uint32 *)addr = data; 117 118#elif defined(WORDS_BIGENDIAN) 119 *(uint16 *)addr = (uint16)(data >> 16); 120 *(uint16 *)(addr + 2) = (uint16)data; 121 122#else 123 addr[0] = (data >> 24) & 0xff; 124 addr[1] = (data >> 16) & 0xff; 125 addr[2] = (data >> 8) & 0xff; 126 addr[3] = data & 0xff; 127#endif 128} 129 130ENDIAN_INLINE void 131write_longlong (addr, data) 132 uint8 *addr; 133 int64 data; 134{ 135 write_longword (addr, (uint32)(data >> 32)); 136 write_longword (addr+4, (uint32)data); 137} 138