bitops.h 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #include <asm/assembler.h>
  2. #include <asm/unwind.h>
  3. #include <asm/export.h>
  4. #if __LINUX_ARM_ARCH__ >= 6
  5. .macro bitop, name, instr
  6. ENTRY( \name )
  7. UNWIND( .fnstart )
  8. ands ip, r1, #3
  9. strneb r1, [ip] @ assert word-aligned
  10. mov r2, #1
  11. and r3, r0, #31 @ Get bit offset
  12. mov r0, r0, lsr #5
  13. add r1, r1, r0, lsl #2 @ Get word offset
  14. #if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
  15. .arch_extension mp
  16. ALT_SMP(W(pldw) [r1])
  17. ALT_UP(W(nop))
  18. #endif
  19. mov r3, r2, lsl r3
  20. 1: ldrex r2, [r1]
  21. \instr r2, r2, r3
  22. strex r0, r2, [r1]
  23. cmp r0, #0
  24. bne 1b
  25. bx lr
  26. UNWIND( .fnend )
  27. ENDPROC(\name )
  28. EXPORT_SYMBOL(\name )
  29. .endm
  30. .macro testop, name, instr, store
  31. ENTRY( \name )
  32. UNWIND( .fnstart )
  33. ands ip, r1, #3
  34. strneb r1, [ip] @ assert word-aligned
  35. mov r2, #1
  36. and r3, r0, #31 @ Get bit offset
  37. mov r0, r0, lsr #5
  38. add r1, r1, r0, lsl #2 @ Get word offset
  39. mov r3, r2, lsl r3 @ create mask
  40. smp_dmb
  41. #if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
  42. .arch_extension mp
  43. ALT_SMP(W(pldw) [r1])
  44. ALT_UP(W(nop))
  45. #endif
  46. 1: ldrex r2, [r1]
  47. ands r0, r2, r3 @ save old value of bit
  48. \instr r2, r2, r3 @ toggle bit
  49. strex ip, r2, [r1]
  50. cmp ip, #0
  51. bne 1b
  52. smp_dmb
  53. cmp r0, #0
  54. movne r0, #1
  55. 2: bx lr
  56. UNWIND( .fnend )
  57. ENDPROC(\name )
  58. EXPORT_SYMBOL(\name )
  59. .endm
  60. #else
  61. .macro bitop, name, instr
  62. ENTRY( \name )
  63. UNWIND( .fnstart )
  64. ands ip, r1, #3
  65. strneb r1, [ip] @ assert word-aligned
  66. and r2, r0, #31
  67. mov r0, r0, lsr #5
  68. mov r3, #1
  69. mov r3, r3, lsl r2
  70. save_and_disable_irqs ip
  71. ldr r2, [r1, r0, lsl #2]
  72. \instr r2, r2, r3
  73. str r2, [r1, r0, lsl #2]
  74. restore_irqs ip
  75. ret lr
  76. UNWIND( .fnend )
  77. ENDPROC(\name )
  78. EXPORT_SYMBOL(\name )
  79. .endm
  80. /**
  81. * testop - implement a test_and_xxx_bit operation.
  82. * @instr: operational instruction
  83. * @store: store instruction
  84. *
  85. * Note: we can trivially conditionalise the store instruction
  86. * to avoid dirtying the data cache.
  87. */
  88. .macro testop, name, instr, store
  89. ENTRY( \name )
  90. UNWIND( .fnstart )
  91. ands ip, r1, #3
  92. strneb r1, [ip] @ assert word-aligned
  93. and r3, r0, #31
  94. mov r0, r0, lsr #5
  95. save_and_disable_irqs ip
  96. ldr r2, [r1, r0, lsl #2]!
  97. mov r0, #1
  98. tst r2, r0, lsl r3
  99. \instr r2, r2, r0, lsl r3
  100. \store r2, [r1]
  101. moveq r0, #0
  102. restore_irqs ip
  103. ret lr
  104. UNWIND( .fnend )
  105. ENDPROC(\name )
  106. EXPORT_SYMBOL(\name )
  107. .endm
  108. #endif