1 #ifndef HARDWARE_BYTESWAP_H 2 #define HARDWARE_BYTESWAP_H 3 4 /* 5 byteswap routines 6 7 Copyright © 2002-2023 The MorphOS Development Team, All Rights Reserved. 8 */ 9 10 #ifndef EXEC_TYPES_H 11 # include <exec/types.h> 12 #endif 13 14 /* 15 ** generic byteswap routines, 16, 32 and 2 x 16 bits 16 */ 17 18 #define __SWAPWORD_C(x) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) 19 20 #define __SWAPLONG_C(x) \ 21 ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ 22 (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) 23 24 #define __SWAP2WORD_C(x) \ 25 ((((x) & 0x00ff00ff) << 8) | \ 26 (((x) & 0xff00ff00) >> 8)) 27 28 #define __SWAPQUAD_C(x) \ 29 ((((x) & 0xff00000000000000ULL) >> 56) | \ 30 (((x) & 0x00ff000000000000ULL) >> 40) | \ 31 (((x) & 0x0000ff0000000000ULL) >> 24) | \ 32 (((x) & 0x000000ff00000000ULL) >> 8) | \ 33 (((x) & 0x00000000ff000000ULL) << 8) | \ 34 (((x) & 0x0000000000ff0000ULL) << 24) | \ 35 (((x) & 0x000000000000ff00ULL) << 40) | \ 36 (((x) & 0x00000000000000ffULL) << 56)) 37 38 /* 39 ** byteswap for constant values 40 */ 41 #define SWAPWORD_C(x) __SWAPWORD_C((UWORD) (x)) 42 #define SWAPLONG_C(x) __SWAPLONG_C((ULONG) (x)) 43 #define SWAP2WORD_C(x) __SWAP2WORD_C((ULONG) (x)) 44 #define SWAPQUAD_C(x) __SWAPQUAD_C((UQUAD) (x)) 45 46 /* 47 ** __extension__ supress warnings of GNU C extensions if -pedantic is used 48 */ 49 50 #if defined(__GNUC__) && defined(mc68000) 51 52 /* 53 ** m68k assembler byteswap routines 54 */ 55 56 #define SWAPWORD(x) \ 57 (__extension__ \ 58 ({ register UWORD __x = x; \ 59 if (__builtin_constant_p(x)) \ 60 { \ 61 __x = SWAPWORD_C(__x); \ 62 } \ 63 else \ 64 { \ 65 __asm__ ( \ 66 "rolw #8,%0" \ 67 : "=d" (__x) \ 68 : "0" (__x) \ 69 : "cc"); \ 70 } \ 71 __x; \ 72 })) 73 74 #define SWAPLONG(x) \ 75 (__extension__ \ 76 ({ register ULONG __x = x; \ 77 if (__builtin_constant_p(x)) \ 78 { \ 79 __x = SWAPLONG_C(__x); \ 80 } \ 81 else \ 82 { \ 83 __asm__ ( \ 84 "rolw #8,%0;" \ 85 " swap %0;" \ 86 " rolw #8,%0" \ 87 : "=d" (__x) \ 88 : "0" (__x) \ 89 : "cc"); \ 90 } \ 91 __x; \ 92 })) 93 94 #define SWAP2WORD(x) \ 95 (__extension__ \ 96 ({ register ULONG __x = x; \ 97 if (__builtin_constant_p(x)) \ 98 { \ 99 __x = SWAP2WORD_C(__x); \ 100 } \ 101 else \ 102 { \ 103 __asm__ ( \ 104 "rolw #8,%0;" \ 105 " swap %0;" \ 106 " rolw #8,%0;" \ 107 " swap %0" \ 108 : "=d" (__x) \ 109 : "0" (__x) \ 110 : "cc"); \ 111 } \ 112 __x; \ 113 })) 114 115 #elif defined(__GNUC__) && (defined(PPC) || defined(__PPC__) || defined(__powerpc__)) 116 117 /* 118 ** powerpc assembler byteswap routines 119 */ 120 121 #define SWAPWORD(x) \ 122 (__extension__ \ 123 ({ register UWORD __x = x; \ 124 if (__builtin_constant_p(x)) \ 125 { \ 126 __x = SWAPWORD_C(__x); \ 127 } \ 128 else \ 129 { \ 130 __asm__ ( \ 131 "rotrwi %0,%0,8;" \ 132 " inslwi %0,%0,8,16" \ 133 : "=r" (__x) \ 134 : "0" (__x)); \ 135 } \ 136 __x; \ 137 })) 138 139 #define SWAPLONG(x) \ 140 (__extension__ \ 141 ({ register ULONG __x = x; \ 142 if (__builtin_constant_p(x)) \ 143 { \ 144 __x = SWAPLONG_C(__x); \ 145 } \ 146 else \ 147 { \ 148 __asm__ ( \ 149 " rlwinm %0,%1,24,0,31;" \ 150 " rlwimi %0,%1,8,8,15;" \ 151 " rlwimi %0,%1,8,24,31;" \ 152 : "=&r" (__x) \ 153 : "r" (__x)); \ 154 } \ 155 __x; \ 156 })) 157 158 159 #define SWAPWORD_P(x) \ 160 (__extension__ \ 161 ({ \ 162 __asm__ ( \ 163 "lhbrx 0,0,%0;" \ 164 " sth 0,0(%0)" \ 165 : /* no outputs */ \ 166 : "r" ((UWORD *) (x)) \ 167 : "memory", "r0"); \ 168 })) 169 170 #define SWAPLONG_P(x) \ 171 (__extension__ \ 172 ({ \ 173 __asm__ ( \ 174 "lwbrx 0,0,%0;" \ 175 " stw 0,0(%0)" \ 176 : /* no outputs */ \ 177 : "r" ((ULONG *) (x)) \ 178 : "memory", "r0"); \ 179 })) 180 181 #define SWAP2WORD_P(x) \ 182 (__extension__ \ 183 ({ \ 184 __asm__ ( \ 185 "lhbrx 0,0,%0;" \ 186 " sth 0,0(%0);" \ 187 " lhbrx 0,%1,%0;" \ 188 " sth 0,2(%0)" \ 189 : /* no outputs */ \ 190 : "r" ((ULONG *) (x)), "r" (2) \ 191 : "memory", "r0"); \ 192 })) 193 194 #elif defined(__GNUC__) 195 196 /* 197 ** Use default GCC routines... see below. 198 */ 199 200 #else /* defined(__GNUC__) */ 201 202 /* 203 ** CPU independant byteswap for all non-GCC systems 204 */ 205 206 #define SWAPWORD(x) SWAPWORD_C(x) 207 #define SWAPLONG(x) SWAPLONG_C(x) 208 #define SWAP2WORD(x) SWAPWORD_C(x) 209 #define SWAPQUAD(x) SWAPQUAD_C(x) 210 211 #define SWAPWORD_P(x) \ 212 do { register UWORD __xv, *__xx = (UWORD *) (x); \ 213 __xv = *__xx; *__xx = SWAPWORD(__xv); } while(0) 214 215 #define SWAPLONG_P(x) \ 216 do { register ULONG __xv, *__xx = (ULONG *) (x); __xv = *__xx; \ 217 *__xx = SWAPLONG(__xv); } while(0) 218 219 #define SWAP2WORD_P(x) \ 220 do { register ULONG __xv, *__xx = (ULONG *) (x); \ 221 __xv = *__xx; *__xx = SWAP2WORD(__xv); } while(0) 222 223 224 #define SWAPQUAD_P(x) \ 225 do { register UQUAD __xv, *__xx = (UQUAD *) (x); __xv = *__xx; \ 226 *__xx = SWAPQUAD(__xv); } while(0) 227 228 #endif /* defined(__GNUC__) && defined(mc68000) */ 229 230 231 /* 232 ** CPU independant byteswap for all GCC systems 233 */ 234 #ifndef SWAPWORD 235 #define SWAPWORD(x) \ 236 (__extension__ \ 237 ({ register UWORD __x = x; \ 238 __x = __SWAPWORD_C(__x); \ 239 __x; \ 240 })) 241 #endif /* SWAPWORD */ 242 243 #ifndef SWAPLONG 244 #define SWAPLONG(x) \ 245 (__extension__ \ 246 ({ register ULONG __x = x; \ 247 __x = __SWAPLONG_C(__x); \ 248 __x; \ 249 })) 250 #endif /* SWAPLONG */ 251 252 #ifndef SWAP2WORD 253 #define SWAP2WORD(x) \ 254 (__extension__ \ 255 ({ register ULONG __x = x; \ 256 __x = __SWAP2WORD_C(__x); \ 257 __x; \ 258 })) 259 #endif /* SWAP2WORD */ 260 261 #ifndef SWAPQUAD 262 #define SWAPQUAD(x) \ 263 (__extension__ \ 264 ({ register UQUAD __x = x; \ 265 __x = __SWAPQUAD_C(__x); \ 266 __x; \ 267 })) 268 #endif /* SWAPQUAD */ 269 270 #ifndef SWAPWORD_P 271 #define SWAPWORD_P(x) \ 272 ({ register UWORD __xv, *__xx = (UWORD *) (x); \ 273 __xv = *__xx; *__xx = SWAPWORD(__xv); }) 274 #endif /* SWAPWORD_P */ 275 276 #ifndef SWAPLONG_P 277 #define SWAPLONG_P(x) \ 278 ({ register ULONG __xv, *__xx = (ULONG *) (x); \ 279 __xv = *__xx; *__xx = SWAPLONG(__xv); }) 280 #endif /* SWAPLONG_P */ 281 282 #ifndef SWAP2WORD_P 283 #define SWAP2WORD_P(x) \ 284 ({ register ULONG __xv, *__xx = (ULONG *) (x); \ 285 __xv = *__xx; *__xx = SWAP2WORD(__xv); }) 286 #endif /* SWAP2WORD_P */ 287 288 #ifndef SWAPQUAD_P 289 #define SWAPQUAD_P(x) \ 290 ({ register UQUAD __xv, *__xx = (UQUAD *) (x); \ 291 __xv = *__xx; *__xx = SWAPQUAD(__xv); }) 292 #endif /* SWAPQUAD_P */ 293 294 295 #if defined(__BIG_ENDIAN__) || defined(_BIG_ENDIAN) || defined(mc68000) || \ 296 defined(__M68K__) || defined(__MORPHOS__) || defined(__SASC) || \ 297 (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ 298 __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 299 300 /* 301 ** big-endian cpus 302 */ 303 304 #define BE_SWAPWORD_C(x) SWAPWORD_C(x) 305 #define BE_SWAPLONG_C(x) SWAPLONG_C(x) 306 #define BE_SWAP2WORD_C(x) SWAP2WORD_C(x) 307 #define BE_SWAPQUAD_C(x) SWAPQUAD_C(x) 308 309 #define BE_SWAPWORD(x) SWAPWORD(x) 310 #define BE_SWAPLONG(x) SWAPLONG(x) 311 #define BE_SWAP2WORD(x) SWAP2WORD(x) 312 #define BE_SWAPQUAD(x) SWAPQUAD(x) 313 314 #define BE_SWAPWORD_P(x) SWAPWORD_P(x) 315 #define BE_SWAPLONG_P(x) SWAPLONG_P(x) 316 #define BE_SWAP2WORD_P(x) SWAP2WORD_P(x) 317 #define BE_SWAPQUAD_P(x) SWAPQUAD_P(x) 318 319 #define LE_SWAPWORD_C(x) (x) 320 #define LE_SWAPLONG_C(x) (x) 321 #define LE_SWAP2WORD_C(x) (x) 322 #define LE_SWAPQUAD_C(x) (x) 323 324 #define LE_SWAPWORD(x) (x) 325 #define LE_SWAPLONG(x) (x) 326 #define LE_SWAP2WORD(x) (x) 327 #define LE_SWAPQUAD(x) (x) 328 329 #define LE_SWAPWORD_P(x) do {} while(0) 330 #define LE_SWAPLONG_P(x) do {} while(0) 331 #define LE_SWAP2WORD_P(x) do {} while(0) 332 #define LE_SWAPQUAD_P(x) do {} while(0) 333 334 #elif defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN) || \ 335 (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ 336 __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 337 /* 338 ** little-endian cpus 339 */ 340 341 #define BE_SWAPWORD_C(x) (x) 342 #define BE_SWAPLONG_C(x) (x) 343 #define BE_SWAP2WORD_C(x) (x) 344 #define BE_SWAPQUAD_C(x) (x) 345 346 #define BE_SWAPWORD(x) (x) 347 #define BE_SWAPLONG(x) (x) 348 #define BE_SWAP2WORD(x) (x) 349 #define BE_SWAPQUAD(x) (x) 350 351 #define BE_SWAPWORD_P(x) do {} while(0) 352 #define BE_SWAPLONG_P(x) do {} while(0) 353 #define BE_SWAP2WORD_P(x) do {} while(0) 354 #define BE_SWAPQUAD_P(x) do {} while(0) 355 356 #define LE_SWAPWORD_C(x) SWAPWORD_C(x) 357 #define LE_SWAPLONG_C(x) SWAPLONG_C(x) 358 #define LE_SWAP2WORD_C(x) SWAP2WORD_C(x) 359 #define LE_SWAPQUAD_C(x) SWAPQUAD_C(x) 360 361 #define LE_SWAPWORD(x) SWAPWORD(x) 362 #define LE_SWAPLONG(x) SWAPLONG(x) 363 #define LE_SWAP2WORD(x) SWAP2WORD(x) 364 #define LE_SWAPQUAD(x) SWAPQUAD(x) 365 366 #define LE_SWAPWORD_P(x) SWAPWORD_P(x) 367 #define LE_SWAPLONG_P(x) SWAPLONG_P(x) 368 #define LE_SWAP2WORD_P(x) SWAP2WORD_P(x) 369 #define LE_SWAPQUAD_P(x) SWAPQUAD_P(x) 370 371 #else /* endianity */ 372 373 #error UNKNOWN ENDIANITY! 374 375 #endif /* endianity */ 376 377 378 #endif /* HARDWARE_BYTESWAP_H */