assembler.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*
  2. * arch/arm/include/asm/assembler.h
  3. *
  4. * Copyright (C) 1996-2000 Russell King
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * This file contains arm architecture specific defines
  11. * for the different processors.
  12. *
  13. * Do not include any C declarations in this file - it is included by
  14. * assembler source.
  15. */
  16. #ifndef __ASM_ASSEMBLER_H__
  17. #define __ASM_ASSEMBLER_H__
  18. #ifndef __ASSEMBLY__
  19. #error "Only include this from assembly code"
  20. #endif
  21. #include <asm/ptrace.h>
  22. #include <asm/domain.h>
  23. #define IOMEM(x) (x)
  24. /*
  25. * Endian independent macros for shifting bytes within registers.
  26. */
  27. #ifndef __ARMEB__
  28. #define pull lsr
  29. #define push lsl
  30. #define get_byte_0 lsl #0
  31. #define get_byte_1 lsr #8
  32. #define get_byte_2 lsr #16
  33. #define get_byte_3 lsr #24
  34. #define put_byte_0 lsl #0
  35. #define put_byte_1 lsl #8
  36. #define put_byte_2 lsl #16
  37. #define put_byte_3 lsl #24
  38. #else
  39. #define pull lsl
  40. #define push lsr
  41. #define get_byte_0 lsr #24
  42. #define get_byte_1 lsr #16
  43. #define get_byte_2 lsr #8
  44. #define get_byte_3 lsl #0
  45. #define put_byte_0 lsl #24
  46. #define put_byte_1 lsl #16
  47. #define put_byte_2 lsl #8
  48. #define put_byte_3 lsl #0
  49. #endif
  50. /*
  51. * Data preload for architectures that support it
  52. */
  53. #if __LINUX_ARM_ARCH__ >= 5
  54. #define PLD(code...) code
  55. #else
  56. #define PLD(code...)
  57. #endif
  58. /*
  59. * This can be used to enable code to cacheline align the destination
  60. * pointer when bulk writing to memory. Experiments on StrongARM and
  61. * XScale didn't show this a worthwhile thing to do when the cache is not
  62. * set to write-allocate (this would need further testing on XScale when WA
  63. * is used).
  64. *
  65. * On Feroceon there is much to gain however, regardless of cache mode.
  66. */
  67. #ifdef CONFIG_CPU_FEROCEON
  68. #define CALGN(code...) code
  69. #else
  70. #define CALGN(code...)
  71. #endif
  72. /*
  73. * Enable and disable interrupts
  74. */
  75. #if __LINUX_ARM_ARCH__ >= 6
  76. .macro disable_irq_notrace
  77. cpsid i
  78. .endm
  79. .macro enable_irq_notrace
  80. cpsie i
  81. .endm
  82. #else
  83. .macro disable_irq_notrace
  84. msr cpsr_c, #PSR_I_BIT | SVC_MODE
  85. .endm
  86. .macro enable_irq_notrace
  87. msr cpsr_c, #SVC_MODE
  88. .endm
  89. #endif
  90. .macro asm_trace_hardirqs_off
  91. #if defined(CONFIG_TRACE_IRQFLAGS)
  92. stmdb sp!, {r0-r3, ip, lr}
  93. bl trace_hardirqs_off
  94. ldmia sp!, {r0-r3, ip, lr}
  95. #endif
  96. .endm
  97. .macro asm_trace_hardirqs_on_cond, cond
  98. #if defined(CONFIG_TRACE_IRQFLAGS)
  99. /*
  100. * actually the registers should be pushed and pop'd conditionally, but
  101. * after bl the flags are certainly clobbered
  102. */
  103. stmdb sp!, {r0-r3, ip, lr}
  104. bl\cond trace_hardirqs_on
  105. ldmia sp!, {r0-r3, ip, lr}
  106. #endif
  107. .endm
  108. .macro asm_trace_hardirqs_on
  109. asm_trace_hardirqs_on_cond al
  110. .endm
  111. .macro disable_irq
  112. disable_irq_notrace
  113. asm_trace_hardirqs_off
  114. .endm
  115. .macro enable_irq
  116. asm_trace_hardirqs_on
  117. enable_irq_notrace
  118. .endm
  119. /*
  120. * Save the current IRQ state and disable IRQs. Note that this macro
  121. * assumes FIQs are enabled, and that the processor is in SVC mode.
  122. */
  123. .macro save_and_disable_irqs, oldcpsr
  124. mrs \oldcpsr, cpsr
  125. disable_irq
  126. .endm
  127. .macro save_and_disable_irqs_notrace, oldcpsr
  128. mrs \oldcpsr, cpsr
  129. disable_irq_notrace
  130. .endm
  131. /*
  132. * Restore interrupt state previously stored in a register. We don't
  133. * guarantee that this will preserve the flags.
  134. */
  135. .macro restore_irqs_notrace, oldcpsr
  136. msr cpsr_c, \oldcpsr
  137. .endm
  138. .macro restore_irqs, oldcpsr
  139. tst \oldcpsr, #PSR_I_BIT
  140. asm_trace_hardirqs_on_cond eq
  141. restore_irqs_notrace \oldcpsr
  142. .endm
  143. #define USER(x...) \
  144. 9999: x; \
  145. .pushsection __ex_table,"a"; \
  146. .align 3; \
  147. .long 9999b,9001f; \
  148. .popsection
  149. #ifdef CONFIG_SMP
  150. #define ALT_SMP(instr...) \
  151. 9998: instr
  152. /*
  153. * Note: if you get assembler errors from ALT_UP() when building with
  154. * CONFIG_THUMB2_KERNEL, you almost certainly need to use
  155. * ALT_SMP( W(instr) ... )
  156. */
  157. #define ALT_UP(instr...) \
  158. .pushsection ".alt.smp.init", "a" ;\
  159. .long 9998b ;\
  160. 9997: instr ;\
  161. .if . - 9997b != 4 ;\
  162. .error "ALT_UP() content must assemble to exactly 4 bytes";\
  163. .endif ;\
  164. .popsection
  165. #define ALT_UP_B(label) \
  166. .equ up_b_offset, label - 9998b ;\
  167. .pushsection ".alt.smp.init", "a" ;\
  168. .long 9998b ;\
  169. W(b) . + up_b_offset ;\
  170. .popsection
  171. #else
  172. #define ALT_SMP(instr...)
  173. #define ALT_UP(instr...) instr
  174. #define ALT_UP_B(label) b label
  175. #endif
  176. /*
  177. * Instruction barrier
  178. */
  179. .macro instr_sync
  180. #if __LINUX_ARM_ARCH__ >= 7
  181. isb
  182. #elif __LINUX_ARM_ARCH__ == 6
  183. mcr p15, 0, r0, c7, c5, 4
  184. #endif
  185. .endm
  186. /*
  187. * SMP data memory barrier
  188. */
  189. .macro smp_dmb mode
  190. #ifdef CONFIG_SMP
  191. #if __LINUX_ARM_ARCH__ >= 7
  192. .ifeqs "\mode","arm"
  193. ALT_SMP(dmb)
  194. .else
  195. ALT_SMP(W(dmb))
  196. .endif
  197. #elif __LINUX_ARM_ARCH__ == 6
  198. ALT_SMP(mcr p15, 0, r0, c7, c10, 5) @ dmb
  199. #else
  200. #error Incompatible SMP platform
  201. #endif
  202. .ifeqs "\mode","arm"
  203. ALT_UP(nop)
  204. .else
  205. ALT_UP(W(nop))
  206. .endif
  207. #endif
  208. .endm
  209. #ifdef CONFIG_THUMB2_KERNEL
  210. .macro setmode, mode, reg
  211. mov \reg, #\mode
  212. msr cpsr_c, \reg
  213. .endm
  214. #else
  215. .macro setmode, mode, reg
  216. msr cpsr_c, #\mode
  217. .endm
  218. #endif
  219. /*
  220. * STRT/LDRT access macros with ARM and Thumb-2 variants
  221. */
  222. #ifdef CONFIG_THUMB2_KERNEL
  223. .macro usraccoff, instr, reg, ptr, inc, off, cond, abort, t=TUSER()
  224. 9999:
  225. .if \inc == 1
  226. \instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
  227. .elseif \inc == 4
  228. \instr\cond\()\t\().w \reg, [\ptr, #\off]
  229. .else
  230. .error "Unsupported inc macro argument"
  231. .endif
  232. .pushsection __ex_table,"a"
  233. .align 3
  234. .long 9999b, \abort
  235. .popsection
  236. .endm
  237. .macro usracc, instr, reg, ptr, inc, cond, rept, abort
  238. @ explicit IT instruction needed because of the label
  239. @ introduced by the USER macro
  240. .ifnc \cond,al
  241. .if \rept == 1
  242. itt \cond
  243. .elseif \rept == 2
  244. ittt \cond
  245. .else
  246. .error "Unsupported rept macro argument"
  247. .endif
  248. .endif
  249. @ Slightly optimised to avoid incrementing the pointer twice
  250. usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort
  251. .if \rept == 2
  252. usraccoff \instr, \reg, \ptr, \inc, \inc, \cond, \abort
  253. .endif
  254. add\cond \ptr, #\rept * \inc
  255. .endm
  256. #else /* !CONFIG_THUMB2_KERNEL */
  257. .macro usracc, instr, reg, ptr, inc, cond, rept, abort, t=TUSER()
  258. .rept \rept
  259. 9999:
  260. .if \inc == 1
  261. \instr\cond\()b\()\t \reg, [\ptr], #\inc
  262. .elseif \inc == 4
  263. \instr\cond\()\t \reg, [\ptr], #\inc
  264. .else
  265. .error "Unsupported inc macro argument"
  266. .endif
  267. .pushsection __ex_table,"a"
  268. .align 3
  269. .long 9999b, \abort
  270. .popsection
  271. .endr
  272. .endm
  273. #endif /* CONFIG_THUMB2_KERNEL */
  274. .macro strusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
  275. usracc str, \reg, \ptr, \inc, \cond, \rept, \abort
  276. .endm
  277. .macro ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
  278. usracc ldr, \reg, \ptr, \inc, \cond, \rept, \abort
  279. .endm
  280. /* Utility macro for declaring string literals */
  281. .macro string name:req, string
  282. .type \name , #object
  283. \name:
  284. .asciz "\string"
  285. .size \name , . - \name
  286. .endm
  287. .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req
  288. #ifndef CONFIG_CPU_USE_DOMAINS
  289. adds \tmp, \addr, #\size - 1
  290. sbcccs \tmp, \tmp, \limit
  291. bcs \bad
  292. #endif
  293. .endm
  294. #endif /* __ASM_ASSEMBLER_H__ */