1 /* SPDX-License-Identifier: GPL-2.0 */ 2 3 #ifndef _ASM_S390_ARCH_HWEIGHT_H 4 #define _ASM_S390_ARCH_HWEIGHT_H 5 6 #include <linux/types.h> 7 8 static __always_inline unsigned long popcnt_z196(unsigned long w) 9 { 10 unsigned long cnt; 11 12 asm volatile(".insn rrf,0xb9e10000,%[cnt],%[w],0,0" 13 : [cnt] "=d" (cnt) 14 : [w] "d" (w) 15 : "cc"); 16 return cnt; 17 } 18 19 static __always_inline unsigned long popcnt_z15(unsigned long w) 20 { 21 unsigned long cnt; 22 23 asm volatile(".insn rrf,0xb9e10000,%[cnt],%[w],8,0" 24 : [cnt] "=d" (cnt) 25 : [w] "d" (w) 26 : "cc"); 27 return cnt; 28 } 29 30 static __always_inline unsigned long __arch_hweight64(__u64 w) 31 { 32 if (IS_ENABLED(CONFIG_HAVE_MARCH_Z15_FEATURES)) 33 return popcnt_z15(w); 34 if (IS_ENABLED(CONFIG_HAVE_MARCH_Z196_FEATURES)) { 35 w = popcnt_z196(w); 36 w += w >> 32; 37 w += w >> 16; 38 w += w >> 8; 39 return w & 0xff; 40 } 41 return __sw_hweight64(w); 42 } 43 44 static __always_inline unsigned int __arch_hweight32(unsigned int w) 45 { 46 if (IS_ENABLED(CONFIG_HAVE_MARCH_Z15_FEATURES)) 47 return popcnt_z15(w); 48 if (IS_ENABLED(CONFIG_HAVE_MARCH_Z196_FEATURES)) { 49 w = popcnt_z196(w); 50 w += w >> 16; 51 w += w >> 8; 52 return w & 0xff; 53 } 54 return __sw_hweight32(w); 55 } 56 57 static __always_inline unsigned int __arch_hweight16(unsigned int w) 58 { 59 if (IS_ENABLED(CONFIG_HAVE_MARCH_Z15_FEATURES)) 60 return popcnt_z15((unsigned short)w); 61 if (IS_ENABLED(CONFIG_HAVE_MARCH_Z196_FEATURES)) { 62 w = popcnt_z196(w); 63 w += w >> 8; 64 return w & 0xff; 65 } 66 return __sw_hweight16(w); 67 } 68 69 static __always_inline unsigned int __arch_hweight8(unsigned int w) 70 { 71 if (IS_ENABLED(CONFIG_HAVE_MARCH_Z196_FEATURES)) 72 return popcnt_z196((unsigned char)w); 73 return __sw_hweight8(w); 74 } 75 76 #endif /* _ASM_S390_ARCH_HWEIGHT_H */ 77