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 */