bitops.h 2.1 KB

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