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 10 ENDIAN_INLINE uint16 11 get_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 30 ENDIAN_INLINE uint32 31 get_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 64 ENDIAN_INLINE int64 65 get_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 73 ENDIAN_INLINE void 74 write_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 94 ENDIAN_INLINE void 95 write_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 130 ENDIAN_INLINE void 131 write_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