~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/include/asm/assembler.h

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0-only */
  2 /*
  3  *  arch/arm/include/asm/assembler.h
  4  *
  5  *  Copyright (C) 1996-2000 Russell King
  6  *
  7  *  This file contains arm architecture specific defines
  8  *  for the different processors.
  9  *
 10  *  Do not include any C declarations in this file - it is included by
 11  *  assembler source.
 12  */
 13 #ifndef __ASM_ASSEMBLER_H__
 14 #define __ASM_ASSEMBLER_H__
 15 
 16 #ifndef __ASSEMBLY__
 17 #error "Only include this from assembly code"
 18 #endif
 19 
 20 #include <asm/ptrace.h>
 21 #include <asm/opcodes-virt.h>
 22 #include <asm/asm-offsets.h>
 23 #include <asm/page.h>
 24 #include <asm/pgtable.h>
 25 #include <asm/thread_info.h>
 26 #include <asm/uaccess-asm.h>
 27 
 28 #define IOMEM(x)        (x)
 29 
 30 /*
 31  * Endian independent macros for shifting bytes within registers.
 32  */
 33 #ifndef __ARMEB__
 34 #define lspull          lsr
 35 #define lspush          lsl
 36 #define get_byte_0      lsl #0
 37 #define get_byte_1      lsr #8
 38 #define get_byte_2      lsr #16
 39 #define get_byte_3      lsr #24
 40 #define put_byte_0      lsl #0
 41 #define put_byte_1      lsl #8
 42 #define put_byte_2      lsl #16
 43 #define put_byte_3      lsl #24
 44 #else
 45 #define lspull          lsl
 46 #define lspush          lsr
 47 #define get_byte_0      lsr #24
 48 #define get_byte_1      lsr #16
 49 #define get_byte_2      lsr #8
 50 #define get_byte_3      lsl #0
 51 #define put_byte_0      lsl #24
 52 #define put_byte_1      lsl #16
 53 #define put_byte_2      lsl #8
 54 #define put_byte_3      lsl #0
 55 #endif
 56 
 57 /* Select code for any configuration running in BE8 mode */
 58 #ifdef CONFIG_CPU_ENDIAN_BE8
 59 #define ARM_BE8(code...) code
 60 #else
 61 #define ARM_BE8(code...)
 62 #endif
 63 
 64 /*
 65  * Data preload for architectures that support it
 66  */
 67 #if __LINUX_ARM_ARCH__ >= 5
 68 #define PLD(code...)    code
 69 #else
 70 #define PLD(code...)
 71 #endif
 72 
 73 /*
 74  * This can be used to enable code to cacheline align the destination
 75  * pointer when bulk writing to memory.  Experiments on StrongARM and
 76  * XScale didn't show this a worthwhile thing to do when the cache is not
 77  * set to write-allocate (this would need further testing on XScale when WA
 78  * is used).
 79  *
 80  * On Feroceon there is much to gain however, regardless of cache mode.
 81  */
 82 #ifdef CONFIG_CPU_FEROCEON
 83 #define CALGN(code...) code
 84 #else
 85 #define CALGN(code...)
 86 #endif
 87 
 88 #define IMM12_MASK 0xfff
 89 
 90 /* the frame pointer used for stack unwinding */
 91 ARM(    fpreg   .req    r11     )
 92 THUMB(  fpreg   .req    r7      )
 93 
 94 /*
 95  * Enable and disable interrupts
 96  */
 97 #if __LINUX_ARM_ARCH__ >= 6
 98         .macro  disable_irq_notrace
 99         cpsid   i
100         .endm
101 
102         .macro  enable_irq_notrace
103         cpsie   i
104         .endm
105 #else
106         .macro  disable_irq_notrace
107         msr     cpsr_c, #PSR_I_BIT | SVC_MODE
108         .endm
109 
110         .macro  enable_irq_notrace
111         msr     cpsr_c, #SVC_MODE
112         .endm
113 #endif
114 
115 #if __LINUX_ARM_ARCH__ < 7
116         .macro  dsb, args
117         mcr     p15, 0, r0, c7, c10, 4
118         .endm
119 
120         .macro  isb, args
121         mcr     p15, 0, r0, c7, c5, 4
122         .endm
123 #endif
124 
125         .macro asm_trace_hardirqs_off, save=1
126 #if defined(CONFIG_TRACE_IRQFLAGS)
127         .if \save
128         stmdb   sp!, {r0-r3, ip, lr}
129         .endif
130         bl      trace_hardirqs_off
131         .if \save
132         ldmia   sp!, {r0-r3, ip, lr}
133         .endif
134 #endif
135         .endm
136 
137         .macro asm_trace_hardirqs_on, cond=al, save=1
138 #if defined(CONFIG_TRACE_IRQFLAGS)
139         /*
140          * actually the registers should be pushed and pop'd conditionally, but
141          * after bl the flags are certainly clobbered
142          */
143         .if \save
144         stmdb   sp!, {r0-r3, ip, lr}
145         .endif
146         bl\cond trace_hardirqs_on
147         .if \save
148         ldmia   sp!, {r0-r3, ip, lr}
149         .endif
150 #endif
151         .endm
152 
153         .macro disable_irq, save=1
154         disable_irq_notrace
155         asm_trace_hardirqs_off \save
156         .endm
157 
158         .macro enable_irq
159         asm_trace_hardirqs_on
160         enable_irq_notrace
161         .endm
162 /*
163  * Save the current IRQ state and disable IRQs.  Note that this macro
164  * assumes FIQs are enabled, and that the processor is in SVC mode.
165  */
166         .macro  save_and_disable_irqs, oldcpsr
167 #ifdef CONFIG_CPU_V7M
168         mrs     \oldcpsr, primask
169 #else
170         mrs     \oldcpsr, cpsr
171 #endif
172         disable_irq
173         .endm
174 
175         .macro  save_and_disable_irqs_notrace, oldcpsr
176 #ifdef CONFIG_CPU_V7M
177         mrs     \oldcpsr, primask
178 #else
179         mrs     \oldcpsr, cpsr
180 #endif
181         disable_irq_notrace
182         .endm
183 
184 /*
185  * Restore interrupt state previously stored in a register.  We don't
186  * guarantee that this will preserve the flags.
187  */
188         .macro  restore_irqs_notrace, oldcpsr
189 #ifdef CONFIG_CPU_V7M
190         msr     primask, \oldcpsr
191 #else
192         msr     cpsr_c, \oldcpsr
193 #endif
194         .endm
195 
196         .macro restore_irqs, oldcpsr
197         tst     \oldcpsr, #PSR_I_BIT
198         asm_trace_hardirqs_on cond=eq
199         restore_irqs_notrace \oldcpsr
200         .endm
201 
202 /*
203  * Assembly version of "adr rd, BSYM(sym)".  This should only be used to
204  * reference local symbols in the same assembly file which are to be
205  * resolved by the assembler.  Other usage is undefined.
206  */
207         .irp    c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
208         .macro  badr\c, rd, sym
209 #ifdef CONFIG_THUMB2_KERNEL
210         adr\c   \rd, \sym + 1
211 #else
212         adr\c   \rd, \sym
213 #endif
214         .endm
215         .endr
216 
217 /*
218  * Get current thread_info.
219  */
220         .macro  get_thread_info, rd
221         /* thread_info is the first member of struct task_struct */
222         get_current \rd
223         .endm
224 
225 /*
226  * Increment/decrement the preempt count.
227  */
228 #ifdef CONFIG_PREEMPT_COUNT
229         .macro  inc_preempt_count, ti, tmp
230         ldr     \tmp, [\ti, #TI_PREEMPT]        @ get preempt count
231         add     \tmp, \tmp, #1                  @ increment it
232         str     \tmp, [\ti, #TI_PREEMPT]
233         .endm
234 
235         .macro  dec_preempt_count, ti, tmp
236         ldr     \tmp, [\ti, #TI_PREEMPT]        @ get preempt count
237         sub     \tmp, \tmp, #1                  @ decrement it
238         str     \tmp, [\ti, #TI_PREEMPT]
239         .endm
240 #else
241         .macro  inc_preempt_count, ti, tmp
242         .endm
243 
244         .macro  dec_preempt_count, ti, tmp
245         .endm
246 #endif
247 
248 #define USERL(l, x...)                          \
249 9999:   x;                                      \
250         .pushsection __ex_table,"a";            \
251         .align  3;                              \
252         .long   9999b,l;                        \
253         .popsection
254 
255 #define USER(x...)      USERL(9001f, x)
256 
257 #ifdef CONFIG_SMP
258 #define ALT_SMP(instr...)                                       \
259 9998:   instr
260 /*
261  * Note: if you get assembler errors from ALT_UP() when building with
262  * CONFIG_THUMB2_KERNEL, you almost certainly need to use
263  * ALT_SMP( W(instr) ... )
264  */
265 #define ALT_UP(instr...)                                        \
266         .pushsection ".alt.smp.init", "a"                       ;\
267         .align  2                                               ;\
268         .long   9998b - .                                       ;\
269 9997:   instr                                                   ;\
270         .if . - 9997b == 2                                      ;\
271                 nop                                             ;\
272         .endif                                                  ;\
273         .if . - 9997b != 4                                      ;\
274                 .error "ALT_UP() content must assemble to exactly 4 bytes";\
275         .endif                                                  ;\
276         .popsection
277 #define ALT_UP_B(label)                                 \
278         .pushsection ".alt.smp.init", "a"                       ;\
279         .align  2                                               ;\
280         .long   9998b - .                                       ;\
281         W(b)    . + (label - 9998b)                                     ;\
282         .popsection
283 #else
284 #define ALT_SMP(instr...)
285 #define ALT_UP(instr...) instr
286 #define ALT_UP_B(label) b label
287 #endif
288 
289         /*
290          * this_cpu_offset - load the per-CPU offset of this CPU into
291          *                   register 'rd'
292          */
293         .macro          this_cpu_offset, rd:req
294 #ifdef CONFIG_SMP
295 ALT_SMP(mrc             p15, 0, \rd, c13, c0, 4)
296 #ifdef CONFIG_CPU_V6
297 ALT_UP_B(.L1_\@)
298 .L0_\@:
299         .subsection     1
300 .L1_\@: ldr_va          \rd, __per_cpu_offset
301         b               .L0_\@
302         .previous
303 #endif
304 #else
305         mov             \rd, #0
306 #endif
307         .endm
308 
309         /*
310          * set_current - store the task pointer of this CPU's current task
311          */
312         .macro          set_current, rn:req, tmp:req
313 #if defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO) || defined(CONFIG_SMP)
314 9998:   mcr             p15, 0, \rn, c13, c0, 3         @ set TPIDRURO register
315 #ifdef CONFIG_CPU_V6
316 ALT_UP_B(.L0_\@)
317         .subsection     1
318 .L0_\@: str_va          \rn, __current, \tmp
319         b               .L1_\@
320         .previous
321 .L1_\@:
322 #endif
323 #else
324         str_va          \rn, __current, \tmp
325 #endif
326         .endm
327 
328         /*
329          * get_current - load the task pointer of this CPU's current task
330          */
331         .macro          get_current, rd:req
332 #if defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO) || defined(CONFIG_SMP)
333 9998:   mrc             p15, 0, \rd, c13, c0, 3         @ get TPIDRURO register
334 #ifdef CONFIG_CPU_V6
335 ALT_UP_B(.L0_\@)
336         .subsection     1
337 .L0_\@: ldr_va          \rd, __current
338         b               .L1_\@
339         .previous
340 .L1_\@:
341 #endif
342 #else
343         ldr_va          \rd, __current
344 #endif
345         .endm
346 
347         /*
348          * reload_current - reload the task pointer of this CPU's current task
349          *                  into the TLS register
350          */
351         .macro          reload_current, t1:req, t2:req
352 #if defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO) || defined(CONFIG_SMP)
353 #ifdef CONFIG_CPU_V6
354 ALT_SMP(nop)
355 ALT_UP_B(.L0_\@)
356 #endif
357         ldr_this_cpu    \t1, __entry_task, \t1, \t2
358         mcr             p15, 0, \t1, c13, c0, 3         @ store in TPIDRURO
359 .L0_\@:
360 #endif
361         .endm
362 
363 /*
364  * Instruction barrier
365  */
366         .macro  instr_sync
367 #if __LINUX_ARM_ARCH__ >= 7
368         isb
369 #elif __LINUX_ARM_ARCH__ == 6
370         mcr     p15, 0, r0, c7, c5, 4
371 #endif
372         .endm
373 
374 /*
375  * SMP data memory barrier
376  */
377         .macro  smp_dmb mode
378 #ifdef CONFIG_SMP
379 #if __LINUX_ARM_ARCH__ >= 7
380         .ifeqs "\mode","arm"
381         ALT_SMP(dmb     ish)
382         .else
383         ALT_SMP(W(dmb)  ish)
384         .endif
385 #elif __LINUX_ARM_ARCH__ == 6
386         ALT_SMP(mcr     p15, 0, r0, c7, c10, 5) @ dmb
387 #else
388 #error Incompatible SMP platform
389 #endif
390         .ifeqs "\mode","arm"
391         ALT_UP(nop)
392         .else
393         ALT_UP(W(nop))
394         .endif
395 #endif
396         .endm
397 
398 /*
399  * Raw SMP data memory barrier
400  */
401         .macro  __smp_dmb mode
402 #if __LINUX_ARM_ARCH__ >= 7
403         .ifeqs "\mode","arm"
404         dmb     ish
405         .else
406         W(dmb)  ish
407         .endif
408 #elif __LINUX_ARM_ARCH__ == 6
409         mcr     p15, 0, r0, c7, c10, 5  @ dmb
410 #else
411         .error "Incompatible SMP platform"
412 #endif
413         .endm
414 
415 #if defined(CONFIG_CPU_V7M)
416         /*
417          * setmode is used to assert to be in svc mode during boot. For v7-M
418          * this is done in __v7m_setup, so setmode can be empty here.
419          */
420         .macro  setmode, mode, reg
421         .endm
422 #elif defined(CONFIG_THUMB2_KERNEL)
423         .macro  setmode, mode, reg
424         mov     \reg, #\mode
425         msr     cpsr_c, \reg
426         .endm
427 #else
428         .macro  setmode, mode, reg
429         msr     cpsr_c, #\mode
430         .endm
431 #endif
432 
433 /*
434  * Helper macro to enter SVC mode cleanly and mask interrupts. reg is
435  * a scratch register for the macro to overwrite.
436  *
437  * This macro is intended for forcing the CPU into SVC mode at boot time.
438  * you cannot return to the original mode.
439  */
440 .macro safe_svcmode_maskall reg:req
441 #if __LINUX_ARM_ARCH__ >= 6 && !defined(CONFIG_CPU_V7M)
442         mrs     \reg , cpsr
443         eor     \reg, \reg, #HYP_MODE
444         tst     \reg, #MODE_MASK
445         bic     \reg , \reg , #MODE_MASK
446         orr     \reg , \reg , #PSR_I_BIT | PSR_F_BIT | SVC_MODE
447 THUMB(  orr     \reg , \reg , #PSR_T_BIT        )
448         bne     1f
449         orr     \reg, \reg, #PSR_A_BIT
450         badr    lr, 2f
451         msr     spsr_cxsf, \reg
452         __MSR_ELR_HYP(14)
453         __ERET
454 1:      msr     cpsr_c, \reg
455 2:
456 #else
457 /*
458  * workaround for possibly broken pre-v6 hardware
459  * (akita, Sharp Zaurus C-1000, PXA270-based)
460  */
461         setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, \reg
462 #endif
463 .endm
464 
465 /*
466  * STRT/LDRT access macros with ARM and Thumb-2 variants
467  */
468 #ifdef CONFIG_THUMB2_KERNEL
469 
470         .macro  usraccoff, instr, reg, ptr, inc, off, cond, abort, t=TUSER()
471 9999:
472         .if     \inc == 1
473         \instr\()b\t\cond\().w \reg, [\ptr, #\off]
474         .elseif \inc == 4
475         \instr\t\cond\().w \reg, [\ptr, #\off]
476         .else
477         .error  "Unsupported inc macro argument"
478         .endif
479 
480         .pushsection __ex_table,"a"
481         .align  3
482         .long   9999b, \abort
483         .popsection
484         .endm
485 
486         .macro  usracc, instr, reg, ptr, inc, cond, rept, abort
487         @ explicit IT instruction needed because of the label
488         @ introduced by the USER macro
489         .ifnc   \cond,al
490         .if     \rept == 1
491         itt     \cond
492         .elseif \rept == 2
493         ittt    \cond
494         .else
495         .error  "Unsupported rept macro argument"
496         .endif
497         .endif
498 
499         @ Slightly optimised to avoid incrementing the pointer twice
500         usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort
501         .if     \rept == 2
502         usraccoff \instr, \reg, \ptr, \inc, \inc, \cond, \abort
503         .endif
504 
505         add\cond \ptr, #\rept * \inc
506         .endm
507 
508 #else   /* !CONFIG_THUMB2_KERNEL */
509 
510         .macro  usracc, instr, reg, ptr, inc, cond, rept, abort, t=TUSER()
511         .rept   \rept
512 9999:
513         .if     \inc == 1
514         \instr\()b\t\cond \reg, [\ptr], #\inc
515         .elseif \inc == 4
516         \instr\t\cond \reg, [\ptr], #\inc
517         .else
518         .error  "Unsupported inc macro argument"
519         .endif
520 
521         .pushsection __ex_table,"a"
522         .align  3
523         .long   9999b, \abort
524         .popsection
525         .endr
526         .endm
527 
528 #endif  /* CONFIG_THUMB2_KERNEL */
529 
530         .macro  strusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
531         usracc  str, \reg, \ptr, \inc, \cond, \rept, \abort
532         .endm
533 
534         .macro  ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
535         usracc  ldr, \reg, \ptr, \inc, \cond, \rept, \abort
536         .endm
537 
538 /* Utility macro for declaring string literals */
539         .macro  string name:req, string
540         .type \name , #object
541 \name:
542         .asciz "\string"
543         .size \name , . - \name
544         .endm
545 
546         .irp    c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
547         .macro  ret\c, reg
548 #if __LINUX_ARM_ARCH__ < 6
549         mov\c   pc, \reg
550 #else
551         .ifeqs  "\reg", "lr"
552         bx\c    \reg
553         .else
554         mov\c   pc, \reg
555         .endif
556 #endif
557         .endm
558         .endr
559 
560         .macro  ret.w, reg
561         ret     \reg
562 #ifdef CONFIG_THUMB2_KERNEL
563         nop
564 #endif
565         .endm
566 
567         .macro  bug, msg, line
568 #ifdef CONFIG_THUMB2_KERNEL
569 1:      .inst   0xde02
570 #else
571 1:      .inst   0xe7f001f2
572 #endif
573 #ifdef CONFIG_DEBUG_BUGVERBOSE
574         .pushsection .rodata.str, "aMS", %progbits, 1
575 2:      .asciz  "\msg"
576         .popsection
577         .pushsection __bug_table, "aw"
578         .align  2
579         .word   1b, 2b
580         .hword  \line
581         .popsection
582 #endif
583         .endm
584 
585 #ifdef CONFIG_KPROBES
586 #define _ASM_NOKPROBE(entry)                            \
587         .pushsection "_kprobe_blacklist", "aw" ;        \
588         .balign 4 ;                                     \
589         .long entry;                                    \
590         .popsection
591 #else
592 #define _ASM_NOKPROBE(entry)
593 #endif
594 
595         .macro          __adldst_l, op, reg, sym, tmp, c
596         .if             __LINUX_ARM_ARCH__ < 7
597         ldr\c           \tmp, .La\@
598         .subsection     1
599         .align          2
600 .La\@:  .long           \sym - .Lpc\@
601         .previous
602         .else
603         .ifnb           \c
604  THUMB( ittt            \c                      )
605         .endif
606         movw\c          \tmp, #:lower16:\sym - .Lpc\@
607         movt\c          \tmp, #:upper16:\sym - .Lpc\@
608         .endif
609 
610 #ifndef CONFIG_THUMB2_KERNEL
611         .set            .Lpc\@, . + 8                   // PC bias
612         .ifc            \op, add
613         add\c           \reg, \tmp, pc
614         .else
615         \op\c           \reg, [pc, \tmp]
616         .endif
617 #else
618 .Lb\@:  add\c           \tmp, \tmp, pc
619         /*
620          * In Thumb-2 builds, the PC bias depends on whether we are currently
621          * emitting into a .arm or a .thumb section. The size of the add opcode
622          * above will be 2 bytes when emitting in Thumb mode and 4 bytes when
623          * emitting in ARM mode, so let's use this to account for the bias.
624          */
625         .set            .Lpc\@, . + (. - .Lb\@)
626 
627         .ifnc           \op, add
628         \op\c           \reg, [\tmp]
629         .endif
630 #endif
631         .endm
632 
633         /*
634          * mov_l - move a constant value or [relocated] address into a register
635          */
636         .macro          mov_l, dst:req, imm:req, cond
637         .if             __LINUX_ARM_ARCH__ < 7
638         ldr\cond        \dst, =\imm
639         .else
640         movw\cond       \dst, #:lower16:\imm
641         movt\cond       \dst, #:upper16:\imm
642         .endif
643         .endm
644 
645         /*
646          * adr_l - adr pseudo-op with unlimited range
647          *
648          * @dst: destination register
649          * @sym: name of the symbol
650          * @cond: conditional opcode suffix
651          */
652         .macro          adr_l, dst:req, sym:req, cond
653         __adldst_l      add, \dst, \sym, \dst, \cond
654         .endm
655 
656         /*
657          * ldr_l - ldr <literal> pseudo-op with unlimited range
658          *
659          * @dst: destination register
660          * @sym: name of the symbol
661          * @cond: conditional opcode suffix
662          */
663         .macro          ldr_l, dst:req, sym:req, cond
664         __adldst_l      ldr, \dst, \sym, \dst, \cond
665         .endm
666 
667         /*
668          * str_l - str <literal> pseudo-op with unlimited range
669          *
670          * @src: source register
671          * @sym: name of the symbol
672          * @tmp: mandatory scratch register
673          * @cond: conditional opcode suffix
674          */
675         .macro          str_l, src:req, sym:req, tmp:req, cond
676         __adldst_l      str, \src, \sym, \tmp, \cond
677         .endm
678 
679         .macro          __ldst_va, op, reg, tmp, sym, cond, offset
680 #if __LINUX_ARM_ARCH__ >= 7 || \
681     !defined(CONFIG_ARM_HAS_GROUP_RELOCS) || \
682     (defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS))
683         mov_l           \tmp, \sym, \cond
684 #else
685         /*
686          * Avoid a literal load, by emitting a sequence of ADD/LDR instructions
687          * with the appropriate relocations. The combined sequence has a range
688          * of -/+ 256 MiB, which should be sufficient for the core kernel and
689          * for modules loaded into the module region.
690          */
691         .globl          \sym
692         .reloc          .L0_\@, R_ARM_ALU_PC_G0_NC, \sym
693         .reloc          .L1_\@, R_ARM_ALU_PC_G1_NC, \sym
694         .reloc          .L2_\@, R_ARM_LDR_PC_G2, \sym
695 .L0_\@: sub\cond        \tmp, pc, #8 - \offset
696 .L1_\@: sub\cond        \tmp, \tmp, #4 - \offset
697 .L2_\@:
698 #endif
699         \op\cond        \reg, [\tmp, #\offset]
700         .endm
701 
702         /*
703          * ldr_va - load a 32-bit word from the virtual address of \sym
704          */
705         .macro          ldr_va, rd:req, sym:req, cond, tmp, offset=0
706         .ifnb           \tmp
707         __ldst_va       ldr, \rd, \tmp, \sym, \cond, \offset
708         .else
709         __ldst_va       ldr, \rd, \rd, \sym, \cond, \offset
710         .endif
711         .endm
712 
713         /*
714          * str_va - store a 32-bit word to the virtual address of \sym
715          */
716         .macro          str_va, rn:req, sym:req, tmp:req, cond
717         __ldst_va       str, \rn, \tmp, \sym, \cond, 0
718         .endm
719 
720         /*
721          * ldr_this_cpu_armv6 - Load a 32-bit word from the per-CPU variable 'sym',
722          *                      without using a temp register. Supported in ARM mode
723          *                      only.
724          */
725         .macro          ldr_this_cpu_armv6, rd:req, sym:req
726         this_cpu_offset \rd
727         .globl          \sym
728         .reloc          .L0_\@, R_ARM_ALU_PC_G0_NC, \sym
729         .reloc          .L1_\@, R_ARM_ALU_PC_G1_NC, \sym
730         .reloc          .L2_\@, R_ARM_LDR_PC_G2, \sym
731         add             \rd, \rd, pc
732 .L0_\@: sub             \rd, \rd, #4
733 .L1_\@: sub             \rd, \rd, #0
734 .L2_\@: ldr             \rd, [\rd, #4]
735         .endm
736 
737         /*
738          * ldr_this_cpu - Load a 32-bit word from the per-CPU variable 'sym'
739          *                into register 'rd', which may be the stack pointer,
740          *                using 't1' and 't2' as general temp registers. These
741          *                are permitted to overlap with 'rd' if != sp
742          */
743         .macro          ldr_this_cpu, rd:req, sym:req, t1:req, t2:req
744 #ifndef CONFIG_SMP
745         ldr_va          \rd, \sym, tmp=\t1
746 #elif __LINUX_ARM_ARCH__ >= 7 || \
747       !defined(CONFIG_ARM_HAS_GROUP_RELOCS) || \
748       (defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS))
749         this_cpu_offset \t1
750         mov_l           \t2, \sym
751         ldr             \rd, [\t1, \t2]
752 #else
753         ldr_this_cpu_armv6 \rd, \sym
754 #endif
755         .endm
756 
757         /*
758          * rev_l - byte-swap a 32-bit value
759          *
760          * @val: source/destination register
761          * @tmp: scratch register
762          */
763         .macro          rev_l, val:req, tmp:req
764         .if             __LINUX_ARM_ARCH__ < 6
765         eor             \tmp, \val, \val, ror #16
766         bic             \tmp, \tmp, #0x00ff0000
767         mov             \val, \val, ror #8
768         eor             \val, \val, \tmp, lsr #8
769         .else
770         rev             \val, \val
771         .endif
772         .endm
773 
774         .if             __LINUX_ARM_ARCH__ < 6
775         .set            .Lrev_l_uses_tmp, 1
776         .else
777         .set            .Lrev_l_uses_tmp, 0
778         .endif
779 
780         /*
781          * bl_r - branch and link to register
782          *
783          * @dst: target to branch to
784          * @c: conditional opcode suffix
785          */
786         .macro          bl_r, dst:req, c
787         .if             __LINUX_ARM_ARCH__ < 6
788         mov\c           lr, pc
789         mov\c           pc, \dst
790         .else
791         blx\c           \dst
792         .endif
793         .endm
794 
795 #endif /* __ASM_ASSEMBLER_H__ */
796 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php