atomic-llsc.h 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __ASM_SH_ATOMIC_LLSC_H
  3. #define __ASM_SH_ATOMIC_LLSC_H
  4. /*
  5. * SH-4A note:
  6. *
  7. * We basically get atomic_xxx_return() for free compared with
  8. * atomic_xxx(). movli.l/movco.l require r0 due to the instruction
  9. * encoding, so the retval is automatically set without having to
  10. * do any special work.
  11. */
  12. /*
  13. * To get proper branch prediction for the main line, we must branch
  14. * forward to code at the end of this object's .text section, then
  15. * branch back to restart the operation.
  16. */
  17. #define ATOMIC_OP(op) \
  18. static inline void atomic_##op(int i, atomic_t *v) \
  19. { \
  20. unsigned long tmp; \
  21. \
  22. __asm__ __volatile__ ( \
  23. "1: movli.l @%2, %0 ! atomic_" #op "\n" \
  24. " " #op " %1, %0 \n" \
  25. " movco.l %0, @%2 \n" \
  26. " bf 1b \n" \
  27. : "=&z" (tmp) \
  28. : "r" (i), "r" (&v->counter) \
  29. : "t"); \
  30. }
  31. #define ATOMIC_OP_RETURN(op) \
  32. static inline int atomic_##op##_return(int i, atomic_t *v) \
  33. { \
  34. unsigned long temp; \
  35. \
  36. __asm__ __volatile__ ( \
  37. "1: movli.l @%2, %0 ! atomic_" #op "_return \n" \
  38. " " #op " %1, %0 \n" \
  39. " movco.l %0, @%2 \n" \
  40. " bf 1b \n" \
  41. " synco \n" \
  42. : "=&z" (temp) \
  43. : "r" (i), "r" (&v->counter) \
  44. : "t"); \
  45. \
  46. return temp; \
  47. }
  48. #define ATOMIC_FETCH_OP(op) \
  49. static inline int atomic_fetch_##op(int i, atomic_t *v) \
  50. { \
  51. unsigned long res, temp; \
  52. \
  53. __asm__ __volatile__ ( \
  54. "1: movli.l @%3, %0 ! atomic_fetch_" #op " \n" \
  55. " mov %0, %1 \n" \
  56. " " #op " %2, %0 \n" \
  57. " movco.l %0, @%3 \n" \
  58. " bf 1b \n" \
  59. " synco \n" \
  60. : "=&z" (temp), "=&r" (res) \
  61. : "r" (i), "r" (&v->counter) \
  62. : "t"); \
  63. \
  64. return res; \
  65. }
  66. #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op) ATOMIC_FETCH_OP(op)
  67. ATOMIC_OPS(add)
  68. ATOMIC_OPS(sub)
  69. #undef ATOMIC_OPS
  70. #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_FETCH_OP(op)
  71. ATOMIC_OPS(and)
  72. ATOMIC_OPS(or)
  73. ATOMIC_OPS(xor)
  74. #undef ATOMIC_OPS
  75. #undef ATOMIC_FETCH_OP
  76. #undef ATOMIC_OP_RETURN
  77. #undef ATOMIC_OP
  78. #endif /* __ASM_SH_ATOMIC_LLSC_H */