bitops.h 2.1 KB

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