arch_hweight.h 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. #ifndef _ASM_X86_HWEIGHT_H
  2. #define _ASM_X86_HWEIGHT_H
  3. #ifdef CONFIG_64BIT
  4. /* popcnt %rdi, %rax */
  5. #define POPCNT ".byte 0xf3,0x48,0x0f,0xb8,0xc7"
  6. #define REG_IN "D"
  7. #define REG_OUT "a"
  8. #else
  9. /* popcnt %eax, %eax */
  10. #define POPCNT ".byte 0xf3,0x0f,0xb8,0xc0"
  11. #define REG_IN "a"
  12. #define REG_OUT "a"
  13. #endif
  14. /*
  15. * __sw_hweightXX are called from within the alternatives below
  16. * and callee-clobbered registers need to be taken care of. See
  17. * ARCH_HWEIGHT_CFLAGS in <arch/x86/Kconfig> for the respective
  18. * compiler switches.
  19. */
  20. static inline unsigned int __arch_hweight32(unsigned int w)
  21. {
  22. unsigned int res = 0;
  23. asm (ALTERNATIVE("call __sw_hweight32", POPCNT, X86_FEATURE_POPCNT)
  24. : "="REG_OUT (res)
  25. : REG_IN (w));
  26. return res;
  27. }
  28. static inline unsigned int __arch_hweight16(unsigned int w)
  29. {
  30. return __arch_hweight32(w & 0xffff);
  31. }
  32. static inline unsigned int __arch_hweight8(unsigned int w)
  33. {
  34. return __arch_hweight32(w & 0xff);
  35. }
  36. static inline unsigned long __arch_hweight64(__u64 w)
  37. {
  38. unsigned long res = 0;
  39. #ifdef CONFIG_X86_32
  40. return __arch_hweight32((u32)w) +
  41. __arch_hweight32((u32)(w >> 32));
  42. #else
  43. asm (ALTERNATIVE("call __sw_hweight64", POPCNT, X86_FEATURE_POPCNT)
  44. : "="REG_OUT (res)
  45. : REG_IN (w));
  46. #endif /* CONFIG_X86_32 */
  47. return res;
  48. }
  49. #endif