hash.h 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _ASM_HASH_H
  3. #define _ASM_HASH_H
  4. /*
  5. * The later H8SX models have a 32x32-bit multiply, but the H8/300H
  6. * and H8S have only 16x16->32. Since it's tolerably compact, this is
  7. * basically an inlined version of the __mulsi3 code. Since the inputs
  8. * are not expected to be small, it's also simplfied by skipping the
  9. * early-out checks.
  10. *
  11. * (Since neither CPU has any multi-bit shift instructions, a
  12. * shift-and-add version is a non-starter.)
  13. *
  14. * TODO: come up with an arch-specific version of the hashing in fs/namei.c,
  15. * since that is heavily dependent on rotates. Which, as mentioned, suck
  16. * horribly on H8.
  17. */
  18. #if defined(CONFIG_CPU_H300H) || defined(CONFIG_CPU_H8S)
  19. #define HAVE_ARCH__HASH_32 1
  20. /*
  21. * Multiply by k = 0x61C88647. Fitting this into three registers requires
  22. * one extra instruction, but reducing register pressure will probably
  23. * make that back and then some.
  24. *
  25. * GCC asm note: %e1 is the high half of operand %1, while %f1 is the
  26. * low half. So if %1 is er4, then %e1 is e4 and %f1 is r4.
  27. *
  28. * This has been designed to modify x in place, since that's the most
  29. * common usage, but preserve k, since hash_64() makes two calls in
  30. * quick succession.
  31. */
  32. static inline u32 __attribute_const__ __hash_32(u32 x)
  33. {
  34. u32 temp;
  35. asm( "mov.w %e1,%f0"
  36. "\n mulxu.w %f2,%0" /* klow * xhigh */
  37. "\n mov.w %f0,%e1" /* The extra instruction */
  38. "\n mov.w %f1,%f0"
  39. "\n mulxu.w %e2,%0" /* khigh * xlow */
  40. "\n add.w %e1,%f0"
  41. "\n mulxu.w %f2,%1" /* klow * xlow */
  42. "\n add.w %f0,%e1"
  43. : "=&r" (temp), "=r" (x)
  44. : "%r" (GOLDEN_RATIO_32), "1" (x));
  45. return x;
  46. }
  47. #endif
  48. #endif /* _ASM_HASH_H */