Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
0002 /*
0003  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
0004  *
0005  * This program is free software; you can redistribute it and/or modify
0006  * it under the terms of the GNU General Public License version 2 as
0007  * published by the Free Software Foundation.
0008  *
0009  * vineetg: May 2011
0010  *  -Support single cycle endian-swap insn in ARC700 4.10
0011  *
0012  * vineetg: June 2009
0013  *  -Better htonl implementation (5 instead of 9 ALU instructions)
0014  *  -Hardware assisted single cycle bswap (Use Case of ARC custom instrn)
0015  */
0016 
0017 #ifndef __ASM_ARC_SWAB_H
0018 #define __ASM_ARC_SWAB_H
0019 
0020 #include <linux/types.h>
0021 
0022 /* Native single cycle endian swap insn */
0023 #ifdef CONFIG_ARC_HAS_SWAPE
0024 
0025 #define __arch_swab32(x)        \
0026 ({                  \
0027     unsigned int tmp = x;       \
0028     __asm__(            \
0029     "   swape   %0, %1  \n" \
0030     : "=r" (tmp)            \
0031     : "r" (tmp));           \
0032     tmp;                \
0033 })
0034 
0035 #else
0036 
0037 /* Several ways of Endian-Swap Emulation for ARC
0038  * 0: kernel generic
0039  * 1: ARC optimised "C"
0040  * 2: ARC Custom instruction
0041  */
0042 #define ARC_BSWAP_TYPE  1
0043 
0044 #if (ARC_BSWAP_TYPE == 1)       /******* Software only ********/
0045 
0046 /* The kernel default implementation of htonl is
0047  *      return  x<<24 | x>>24 |
0048  *       (x & (__u32)0x0000ff00UL)<<8 | (x & (__u32)0x00ff0000UL)>>8;
0049  *
0050  * This generates 9 instructions on ARC (excluding the ld/st)
0051  *
0052  * 8051fd8c:    ld     r3,[r7,20]   ; Mem op : Get the value to be swapped
0053  * 8051fd98:    asl    r5,r3,24     ; get  3rd Byte
0054  * 8051fd9c:    lsr    r2,r3,24     ; get  0th Byte
0055  * 8051fda0:    and    r4,r3,0xff00
0056  * 8051fda8:    asl    r4,r4,8      ; get 1st Byte
0057  * 8051fdac:    and    r3,r3,0x00ff0000
0058  * 8051fdb4:    or     r2,r2,r5     ; combine 0th and 3rd Bytes
0059  * 8051fdb8:    lsr    r3,r3,8      ; 2nd Byte at correct place in Dst Reg
0060  * 8051fdbc:    or     r2,r2,r4     ; combine 0,3 Bytes with 1st Byte
0061  * 8051fdc0:    or     r2,r2,r3     ; combine 0,3,1 Bytes with 2nd Byte
0062  * 8051fdc4:    st     r2,[r1,20]   ; Mem op : save result back to mem
0063  *
0064  * Joern suggested a better "C" algorithm which is great since
0065  * (1) It is portable to any architecure
0066  * (2) At the same time it takes advantage of ARC ISA (rotate intrns)
0067  */
0068 
0069 #define __arch_swab32(x)                    \
0070 ({  unsigned long __in = (x), __tmp;            \
0071     __tmp = __in << 8 | __in >> 24; /* ror tmp,in,24 */ \
0072     __in = __in << 24 | __in >> 8; /* ror in,in,8 */    \
0073     __tmp ^= __in;                      \
0074     __tmp &= 0xff00ff;                  \
0075     __tmp ^ __in;                       \
0076 })
0077 
0078 #elif (ARC_BSWAP_TYPE == 2) /* Custom single cycle bswap instruction */
0079 
0080 #define __arch_swab32(x)                        \
0081 ({                                  \
0082     unsigned int tmp = x;                       \
0083     __asm__(                            \
0084     "   .extInstruction bswap, 7, 0x00, SUFFIX_NONE, SYNTAX_2OP \n"\
0085     "   bswap  %0, %1                       \n"\
0086     : "=r" (tmp)                            \
0087     : "r" (tmp));                           \
0088     tmp;                                \
0089 })
0090 
0091 #endif /* ARC_BSWAP_TYPE=zzz */
0092 
0093 #endif /* CONFIG_ARC_HAS_SWAPE */
0094 
0095 #if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
0096 #define __SWAB_64_THRU_32__
0097 #endif
0098 
0099 #endif