Home | History | Annotate | Download | only in asm
      1 /* SPDX-License-Identifier: GPL-2.0+ */
      2 /*
      3  * Based on Linux/Xtensa kernel version
      4  *
      5  * Copyright (C) 2001 - 2007 Tensilica Inc.
      6  */
      7 
      8 #ifndef _XTENSA_BYTEORDER_H
      9 #define _XTENSA_BYTEORDER_H
     10 
     11 #include <asm/types.h>
     12 
     13 static inline __attribute__((const)) __u32 ___arch__swab32(__u32 x)
     14 {
     15 	__u32 res;
     16 
     17 	/* instruction sequence from Xtensa ISA release 2/2000 */
     18 	__asm__("ssai     8\n\t"
     19 		"srli     %0, %1, 16\n\t"
     20 		"src      %0, %0, %1\n\t"
     21 		"src      %0, %0, %0\n\t"
     22 		"src      %0, %1, %0\n"
     23 		: "=&a" (res)
     24 		: "a" (x)
     25 		);
     26 	return res;
     27 }
     28 
     29 static inline __attribute__((const)) __u16 ___arch__swab16(__u16 x)
     30 {
     31 	/*
     32 	 * Given that 'short' values are signed (i.e., can be negative),
     33 	 * we cannot assume that the upper 16-bits of the register are
     34 	 * zero.  We are careful to mask values after shifting.
     35 	 */
     36 
     37 	/*
     38 	 * There exists an anomaly between xt-gcc and xt-xcc.  xt-gcc
     39 	 * inserts an extui instruction after putting this function inline
     40 	 * to ensure that it uses only the least-significant 16 bits of
     41 	 * the result.  xt-xcc doesn't use an extui, but assumes the
     42 	 * __asm__ macro follows convention that the upper 16 bits of an
     43 	 * 'unsigned short' result are still zero.  This macro doesn't
     44 	 * follow convention; indeed, it leaves garbage in the upport 16
     45 	 * bits of the register.
     46 	 *
     47 	 * Declaring the temporary variables 'res' and 'tmp' to be 32-bit
     48 	 * types while the return type of the function is a 16-bit type
     49 	 * forces both compilers to insert exactly one extui instruction
     50 	 * (or equivalent) to mask off the upper 16 bits.
     51 	 */
     52 
     53 	__u32 res;
     54 	__u32 tmp;
     55 
     56 	__asm__("extui    %1, %2, 8, 8\n\t"
     57 		"slli     %0, %2, 8\n\t"
     58 		"or       %0, %0, %1\n"
     59 		: "=&a" (res), "=&a" (tmp)
     60 		: "a" (x)
     61 		);
     62 
     63 	return res;
     64 }
     65 
     66 #define __arch__swab32(x) ___arch__swab32(x)
     67 #define __arch__swab16(x) ___arch__swab16(x)
     68 
     69 #if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
     70 #  define __BYTEORDER_HAS_U64__
     71 #  define __SWAB_64_THRU_32__
     72 #endif
     73 
     74 #ifdef __XTENSA_EL__
     75 # include <linux/byteorder/little_endian.h>
     76 #elif defined(__XTENSA_EB__)
     77 # include <linux/byteorder/big_endian.h>
     78 #else
     79 # error processor byte order undefined!
     80 #endif
     81 
     82 #endif /* _XTENSA_BYTEORDER_H */
     83