/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */1/*2* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)3*4* This program is free software; you can redistribute it and/or modify5* it under the terms of the GNU General Public License version 2 as6* published by the Free Software Foundation.7*8* vineetg: May 20119* -Support single cycle endian-swap insn in ARC700 4.1010*11* vineetg: June 200912* -Better htonl implementation (5 instead of 9 ALU instructions)13* -Hardware assisted single cycle bswap (Use Case of ARC custom instrn)14*/1516#ifndef __ASM_ARC_SWAB_H17#define __ASM_ARC_SWAB_H1819#include <linux/types.h>2021/* Native single cycle endian swap insn */22#ifdef CONFIG_ARC_HAS_SWAPE2324#define __arch_swab32(x) \25({ \26unsigned int tmp = x; \27__asm__( \28" swape %0, %1 \n" \29: "=r" (tmp) \30: "r" (tmp)); \31tmp; \32})3334#else3536/* Several ways of Endian-Swap Emulation for ARC37* 0: kernel generic38* 1: ARC optimised "C"39* 2: ARC Custom instruction40*/41#define ARC_BSWAP_TYPE 14243#if (ARC_BSWAP_TYPE == 1) /******* Software only ********/4445/* The kernel default implementation of htonl is46* return x<<24 | x>>24 |47* (x & (__u32)0x0000ff00UL)<<8 | (x & (__u32)0x00ff0000UL)>>8;48*49* This generates 9 instructions on ARC (excluding the ld/st)50*51* 8051fd8c: ld r3,[r7,20] ; Mem op : Get the value to be swapped52* 8051fd98: asl r5,r3,24 ; get 3rd Byte53* 8051fd9c: lsr r2,r3,24 ; get 0th Byte54* 8051fda0: and r4,r3,0xff0055* 8051fda8: asl r4,r4,8 ; get 1st Byte56* 8051fdac: and r3,r3,0x00ff000057* 8051fdb4: or r2,r2,r5 ; combine 0th and 3rd Bytes58* 8051fdb8: lsr r3,r3,8 ; 2nd Byte at correct place in Dst Reg59* 8051fdbc: or r2,r2,r4 ; combine 0,3 Bytes with 1st Byte60* 8051fdc0: or r2,r2,r3 ; combine 0,3,1 Bytes with 2nd Byte61* 8051fdc4: st r2,[r1,20] ; Mem op : save result back to mem62*63* Joern suggested a better "C" algorithm which is great since64* (1) It is portable to any architecture65* (2) At the same time it takes advantage of ARC ISA (rotate intrns)66*/6768#define __arch_swab32(x) \69({ unsigned long __in = (x), __tmp; \70__tmp = __in << 8 | __in >> 24; /* ror tmp,in,24 */ \71__in = __in << 24 | __in >> 8; /* ror in,in,8 */ \72__tmp ^= __in; \73__tmp &= 0xff00ff; \74__tmp ^ __in; \75})7677#elif (ARC_BSWAP_TYPE == 2) /* Custom single cycle bswap instruction */7879#define __arch_swab32(x) \80({ \81unsigned int tmp = x; \82__asm__( \83" .extInstruction bswap, 7, 0x00, SUFFIX_NONE, SYNTAX_2OP \n"\84" bswap %0, %1 \n"\85: "=r" (tmp) \86: "r" (tmp)); \87tmp; \88})8990#endif /* ARC_BSWAP_TYPE=zzz */9192#endif /* CONFIG_ARC_HAS_SWAPE */9394#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)95#define __SWAB_64_THRU_32__96#endif9798#endif99100101