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