b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ |
| 2 | /* |
| 3 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) |
| 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify |
| 6 | * it under the terms of the GNU General Public License version 2 as |
| 7 | * published by the Free Software Foundation. |
| 8 | * |
| 9 | * vineetg: May 2011 |
| 10 | * -Support single cycle endian-swap insn in ARC700 4.10 |
| 11 | * |
| 12 | * vineetg: June 2009 |
| 13 | * -Better htonl implementation (5 instead of 9 ALU instructions) |
| 14 | * -Hardware assisted single cycle bswap (Use Case of ARC custom instrn) |
| 15 | */ |
| 16 | |
| 17 | #ifndef __ASM_ARC_SWAB_H |
| 18 | #define __ASM_ARC_SWAB_H |
| 19 | |
| 20 | #include <linux/types.h> |
| 21 | |
| 22 | /* Native single cycle endian swap insn */ |
| 23 | #ifdef CONFIG_ARC_HAS_SWAPE |
| 24 | |
| 25 | #define __arch_swab32(x) \ |
| 26 | ({ \ |
| 27 | unsigned int tmp = x; \ |
| 28 | __asm__( \ |
| 29 | " swape %0, %1 \n" \ |
| 30 | : "=r" (tmp) \ |
| 31 | : "r" (tmp)); \ |
| 32 | tmp; \ |
| 33 | }) |
| 34 | |
| 35 | #else |
| 36 | |
| 37 | /* Several ways of Endian-Swap Emulation for ARC |
| 38 | * 0: kernel generic |
| 39 | * 1: ARC optimised "C" |
| 40 | * 2: ARC Custom instruction |
| 41 | */ |
| 42 | #define ARC_BSWAP_TYPE 1 |
| 43 | |
| 44 | #if (ARC_BSWAP_TYPE == 1) /******* Software only ********/ |
| 45 | |
| 46 | /* The kernel default implementation of htonl is |
| 47 | * return x<<24 | x>>24 | |
| 48 | * (x & (__u32)0x0000ff00UL)<<8 | (x & (__u32)0x00ff0000UL)>>8; |
| 49 | * |
| 50 | * This generates 9 instructions on ARC (excluding the ld/st) |
| 51 | * |
| 52 | * 8051fd8c: ld r3,[r7,20] ; Mem op : Get the value to be swapped |
| 53 | * 8051fd98: asl r5,r3,24 ; get 3rd Byte |
| 54 | * 8051fd9c: lsr r2,r3,24 ; get 0th Byte |
| 55 | * 8051fda0: and r4,r3,0xff00 |
| 56 | * 8051fda8: asl r4,r4,8 ; get 1st Byte |
| 57 | * 8051fdac: and r3,r3,0x00ff0000 |
| 58 | * 8051fdb4: or r2,r2,r5 ; combine 0th and 3rd Bytes |
| 59 | * 8051fdb8: lsr r3,r3,8 ; 2nd Byte at correct place in Dst Reg |
| 60 | * 8051fdbc: or r2,r2,r4 ; combine 0,3 Bytes with 1st Byte |
| 61 | * 8051fdc0: or r2,r2,r3 ; combine 0,3,1 Bytes with 2nd Byte |
| 62 | * 8051fdc4: st r2,[r1,20] ; Mem op : save result back to mem |
| 63 | * |
| 64 | * Joern suggested a better "C" algorithm which is great since |
| 65 | * (1) It is portable to any architecure |
| 66 | * (2) At the same time it takes advantage of ARC ISA (rotate intrns) |
| 67 | */ |
| 68 | |
| 69 | #define __arch_swab32(x) \ |
| 70 | ({ unsigned long __in = (x), __tmp; \ |
| 71 | __tmp = __in << 8 | __in >> 24; /* ror tmp,in,24 */ \ |
| 72 | __in = __in << 24 | __in >> 8; /* ror in,in,8 */ \ |
| 73 | __tmp ^= __in; \ |
| 74 | __tmp &= 0xff00ff; \ |
| 75 | __tmp ^ __in; \ |
| 76 | }) |
| 77 | |
| 78 | #elif (ARC_BSWAP_TYPE == 2) /* Custom single cycle bswap instruction */ |
| 79 | |
| 80 | #define __arch_swab32(x) \ |
| 81 | ({ \ |
| 82 | unsigned int tmp = x; \ |
| 83 | __asm__( \ |
| 84 | " .extInstruction bswap, 7, 0x00, SUFFIX_NONE, SYNTAX_2OP \n"\ |
| 85 | " bswap %0, %1 \n"\ |
| 86 | : "=r" (tmp) \ |
| 87 | : "r" (tmp)); \ |
| 88 | tmp; \ |
| 89 | }) |
| 90 | |
| 91 | #endif /* ARC_BSWAP_TYPE=zzz */ |
| 92 | |
| 93 | #endif /* CONFIG_ARC_HAS_SWAPE */ |
| 94 | |
| 95 | #if !defined(__STRICT_ANSI__) || defined(__KERNEL__) |
| 96 | #define __SWAB_64_THRU_32__ |
| 97 | #endif |
| 98 | |
| 99 | #endif |