1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 #ifndef _ASM_RISCV_SWAB_H 3 #define _ASM_RISCV_SWAB_H 4 5 #include <linux/types.h> 6 #include <linux/compiler.h> 7 #include <asm/cpufeature-macros.h> 8 #include <asm/hwcap.h> 9 #include <asm-generic/swab.h> 10 11 #if defined(CONFIG_TOOLCHAIN_HAS_ZBB) && defined(CONFIG_RISCV_ISA_ZBB) && !defined(NO_ALTERNATIVE) 12 13 // Duplicated from include/uapi/linux/swab.h 14 #define ___constant_swab16(x) ((__u16)( \ 15 (((__u16)(x) & (__u16)0x00ffU) << 8) | \ 16 (((__u16)(x) & (__u16)0xff00U) >> 8))) 17 18 #define ___constant_swab32(x) ((__u32)( \ 19 (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ 20 (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ 21 (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ 22 (((__u32)(x) & (__u32)0xff000000UL) >> 24))) 23 24 #define ___constant_swab64(x) ((__u64)( \ 25 (((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \ 26 (((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \ 27 (((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \ 28 (((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \ 29 (((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \ 30 (((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ 31 (((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \ 32 (((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56))) 33 34 #define ARCH_SWAB(size, value) \ 35 ({ \ 36 unsigned long x = value; \ 37 \ 38 if (riscv_has_extension_likely(RISCV_ISA_EXT_ZBB)) { \ 39 asm volatile (".option push\n" \ 40 ".option arch,+zbb\n" \ 41 "rev8 %0, %1\n" \ 42 ".option pop\n" \ 43 : "=r" (x) : "r" (x)); \ 44 x = x >> (BITS_PER_LONG - size); \ 45 } else { \ 46 x = ___constant_swab##size(value); \ 47 } \ 48 x; \ 49 }) 50 __arch_swab16(__u16 value)51static __always_inline __u16 __arch_swab16(__u16 value) 52 { 53 return ARCH_SWAB(16, value); 54 } 55 __arch_swab32(__u32 value)56static __always_inline __u32 __arch_swab32(__u32 value) 57 { 58 return ARCH_SWAB(32, value); 59 } 60 61 #ifdef CONFIG_64BIT __arch_swab64(__u64 value)62static __always_inline __u64 __arch_swab64(__u64 value) 63 { 64 return ARCH_SWAB(64, value); 65 } 66 #else __arch_swab64(__u64 value)67static __always_inline __u64 __arch_swab64(__u64 value) 68 { 69 __u32 h = value >> 32; 70 __u32 l = value & ((1ULL << 32) - 1); 71 72 return ((__u64)(__arch_swab32(l)) << 32) | ((__u64)(__arch_swab32(h))); 73 } 74 #endif 75 76 #define __arch_swab64 __arch_swab64 77 #define __arch_swab32 __arch_swab32 78 #define __arch_swab16 __arch_swab16 79 80 #undef ___constant_swab16 81 #undef ___constant_swab32 82 #undef ___constant_swab64 83 84 #undef ARCH_SWAB 85 86 #endif /* defined(CONFIG_TOOLCHAIN_HAS_ZBB) && defined(CONFIG_RISCV_ISA_ZBB) && !defined(NO_ALTERNATIVE) */ 87 #endif /* _ASM_RISCV_SWAB_H */ 88