162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * include/asm-xtensa/swab.h
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
662306a36Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
762306a36Sopenharmony_ci * for more details.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Copyright (C) 2001 - 2005 Tensilica Inc.
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#ifndef _XTENSA_SWAB_H
1362306a36Sopenharmony_ci#define _XTENSA_SWAB_H
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/types.h>
1662306a36Sopenharmony_ci#include <linux/compiler.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define __SWAB_64_THRU_32__
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic inline __attribute_const__ __u32 __arch_swab32(__u32 x)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci    __u32 res;
2362306a36Sopenharmony_ci    /* instruction sequence from Xtensa ISA release 2/2000 */
2462306a36Sopenharmony_ci    __asm__("ssai     8           \n\t"
2562306a36Sopenharmony_ci	    "srli     %0, %1, 16  \n\t"
2662306a36Sopenharmony_ci	    "src      %0, %0, %1  \n\t"
2762306a36Sopenharmony_ci	    "src      %0, %0, %0  \n\t"
2862306a36Sopenharmony_ci	    "src      %0, %1, %0  \n"
2962306a36Sopenharmony_ci	    : "=&a" (res)
3062306a36Sopenharmony_ci	    : "a" (x)
3162306a36Sopenharmony_ci	    );
3262306a36Sopenharmony_ci    return res;
3362306a36Sopenharmony_ci}
3462306a36Sopenharmony_ci#define __arch_swab32 __arch_swab32
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistatic inline __attribute_const__ __u16 __arch_swab16(__u16 x)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci    /* Given that 'short' values are signed (i.e., can be negative),
3962306a36Sopenharmony_ci     * we cannot assume that the upper 16-bits of the register are
4062306a36Sopenharmony_ci     * zero.  We are careful to mask values after shifting.
4162306a36Sopenharmony_ci     */
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci    /* There exists an anomaly between xt-gcc and xt-xcc.  xt-gcc
4462306a36Sopenharmony_ci     * inserts an extui instruction after putting this function inline
4562306a36Sopenharmony_ci     * to ensure that it uses only the least-significant 16 bits of
4662306a36Sopenharmony_ci     * the result.  xt-xcc doesn't use an extui, but assumes the
4762306a36Sopenharmony_ci     * __asm__ macro follows convention that the upper 16 bits of an
4862306a36Sopenharmony_ci     * 'unsigned short' result are still zero.  This macro doesn't
4962306a36Sopenharmony_ci     * follow convention; indeed, it leaves garbage in the upport 16
5062306a36Sopenharmony_ci     * bits of the register.
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci     * Declaring the temporary variables 'res' and 'tmp' to be 32-bit
5362306a36Sopenharmony_ci     * types while the return type of the function is a 16-bit type
5462306a36Sopenharmony_ci     * forces both compilers to insert exactly one extui instruction
5562306a36Sopenharmony_ci     * (or equivalent) to mask off the upper 16 bits. */
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci    __u32 res;
5862306a36Sopenharmony_ci    __u32 tmp;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci    __asm__("extui    %1, %2, 8, 8\n\t"
6162306a36Sopenharmony_ci	    "slli     %0, %2, 8   \n\t"
6262306a36Sopenharmony_ci	    "or       %0, %0, %1  \n"
6362306a36Sopenharmony_ci	    : "=&a" (res), "=&a" (tmp)
6462306a36Sopenharmony_ci	    : "a" (x)
6562306a36Sopenharmony_ci	    );
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci    return res;
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci#define __arch_swab16 __arch_swab16
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci#endif /* _XTENSA_SWAB_H */
72