162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  arch/arm/include/asm/assembler.h
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Copyright (C) 1996-2000 Russell King
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *  This file contains arm architecture specific defines
862306a36Sopenharmony_ci *  for the different processors.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci *  Do not include any C declarations in this file - it is included by
1162306a36Sopenharmony_ci *  assembler source.
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci#ifndef __ASM_ASSEMBLER_H__
1462306a36Sopenharmony_ci#define __ASM_ASSEMBLER_H__
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#ifndef __ASSEMBLY__
1762306a36Sopenharmony_ci#error "Only include this from assembly code"
1862306a36Sopenharmony_ci#endif
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include <asm/ptrace.h>
2162306a36Sopenharmony_ci#include <asm/opcodes-virt.h>
2262306a36Sopenharmony_ci#include <asm/asm-offsets.h>
2362306a36Sopenharmony_ci#include <asm/page.h>
2462306a36Sopenharmony_ci#include <asm/thread_info.h>
2562306a36Sopenharmony_ci#include <asm/uaccess-asm.h>
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#define IOMEM(x)	(x)
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/*
3062306a36Sopenharmony_ci * Endian independent macros for shifting bytes within registers.
3162306a36Sopenharmony_ci */
3262306a36Sopenharmony_ci#ifndef __ARMEB__
3362306a36Sopenharmony_ci#define lspull          lsr
3462306a36Sopenharmony_ci#define lspush          lsl
3562306a36Sopenharmony_ci#define get_byte_0      lsl #0
3662306a36Sopenharmony_ci#define get_byte_1	lsr #8
3762306a36Sopenharmony_ci#define get_byte_2	lsr #16
3862306a36Sopenharmony_ci#define get_byte_3	lsr #24
3962306a36Sopenharmony_ci#define put_byte_0      lsl #0
4062306a36Sopenharmony_ci#define put_byte_1	lsl #8
4162306a36Sopenharmony_ci#define put_byte_2	lsl #16
4262306a36Sopenharmony_ci#define put_byte_3	lsl #24
4362306a36Sopenharmony_ci#else
4462306a36Sopenharmony_ci#define lspull          lsl
4562306a36Sopenharmony_ci#define lspush          lsr
4662306a36Sopenharmony_ci#define get_byte_0	lsr #24
4762306a36Sopenharmony_ci#define get_byte_1	lsr #16
4862306a36Sopenharmony_ci#define get_byte_2	lsr #8
4962306a36Sopenharmony_ci#define get_byte_3      lsl #0
5062306a36Sopenharmony_ci#define put_byte_0	lsl #24
5162306a36Sopenharmony_ci#define put_byte_1	lsl #16
5262306a36Sopenharmony_ci#define put_byte_2	lsl #8
5362306a36Sopenharmony_ci#define put_byte_3      lsl #0
5462306a36Sopenharmony_ci#endif
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/* Select code for any configuration running in BE8 mode */
5762306a36Sopenharmony_ci#ifdef CONFIG_CPU_ENDIAN_BE8
5862306a36Sopenharmony_ci#define ARM_BE8(code...) code
5962306a36Sopenharmony_ci#else
6062306a36Sopenharmony_ci#define ARM_BE8(code...)
6162306a36Sopenharmony_ci#endif
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci/*
6462306a36Sopenharmony_ci * Data preload for architectures that support it
6562306a36Sopenharmony_ci */
6662306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 5
6762306a36Sopenharmony_ci#define PLD(code...)	code
6862306a36Sopenharmony_ci#else
6962306a36Sopenharmony_ci#define PLD(code...)
7062306a36Sopenharmony_ci#endif
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci/*
7362306a36Sopenharmony_ci * This can be used to enable code to cacheline align the destination
7462306a36Sopenharmony_ci * pointer when bulk writing to memory.  Experiments on StrongARM and
7562306a36Sopenharmony_ci * XScale didn't show this a worthwhile thing to do when the cache is not
7662306a36Sopenharmony_ci * set to write-allocate (this would need further testing on XScale when WA
7762306a36Sopenharmony_ci * is used).
7862306a36Sopenharmony_ci *
7962306a36Sopenharmony_ci * On Feroceon there is much to gain however, regardless of cache mode.
8062306a36Sopenharmony_ci */
8162306a36Sopenharmony_ci#ifdef CONFIG_CPU_FEROCEON
8262306a36Sopenharmony_ci#define CALGN(code...) code
8362306a36Sopenharmony_ci#else
8462306a36Sopenharmony_ci#define CALGN(code...)
8562306a36Sopenharmony_ci#endif
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci#define IMM12_MASK 0xfff
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci/* the frame pointer used for stack unwinding */
9062306a36Sopenharmony_ciARM(	fpreg	.req	r11	)
9162306a36Sopenharmony_ciTHUMB(	fpreg	.req	r7	)
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci/*
9462306a36Sopenharmony_ci * Enable and disable interrupts
9562306a36Sopenharmony_ci */
9662306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 6
9762306a36Sopenharmony_ci	.macro	disable_irq_notrace
9862306a36Sopenharmony_ci	cpsid	i
9962306a36Sopenharmony_ci	.endm
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	.macro	enable_irq_notrace
10262306a36Sopenharmony_ci	cpsie	i
10362306a36Sopenharmony_ci	.endm
10462306a36Sopenharmony_ci#else
10562306a36Sopenharmony_ci	.macro	disable_irq_notrace
10662306a36Sopenharmony_ci	msr	cpsr_c, #PSR_I_BIT | SVC_MODE
10762306a36Sopenharmony_ci	.endm
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	.macro	enable_irq_notrace
11062306a36Sopenharmony_ci	msr	cpsr_c, #SVC_MODE
11162306a36Sopenharmony_ci	.endm
11262306a36Sopenharmony_ci#endif
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ < 7
11562306a36Sopenharmony_ci	.macro	dsb, args
11662306a36Sopenharmony_ci	mcr	p15, 0, r0, c7, c10, 4
11762306a36Sopenharmony_ci	.endm
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	.macro	isb, args
12062306a36Sopenharmony_ci	mcr	p15, 0, r0, c7, c5, 4
12162306a36Sopenharmony_ci	.endm
12262306a36Sopenharmony_ci#endif
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	.macro asm_trace_hardirqs_off, save=1
12562306a36Sopenharmony_ci#if defined(CONFIG_TRACE_IRQFLAGS)
12662306a36Sopenharmony_ci	.if \save
12762306a36Sopenharmony_ci	stmdb   sp!, {r0-r3, ip, lr}
12862306a36Sopenharmony_ci	.endif
12962306a36Sopenharmony_ci	bl	trace_hardirqs_off
13062306a36Sopenharmony_ci	.if \save
13162306a36Sopenharmony_ci	ldmia	sp!, {r0-r3, ip, lr}
13262306a36Sopenharmony_ci	.endif
13362306a36Sopenharmony_ci#endif
13462306a36Sopenharmony_ci	.endm
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	.macro asm_trace_hardirqs_on, cond=al, save=1
13762306a36Sopenharmony_ci#if defined(CONFIG_TRACE_IRQFLAGS)
13862306a36Sopenharmony_ci	/*
13962306a36Sopenharmony_ci	 * actually the registers should be pushed and pop'd conditionally, but
14062306a36Sopenharmony_ci	 * after bl the flags are certainly clobbered
14162306a36Sopenharmony_ci	 */
14262306a36Sopenharmony_ci	.if \save
14362306a36Sopenharmony_ci	stmdb   sp!, {r0-r3, ip, lr}
14462306a36Sopenharmony_ci	.endif
14562306a36Sopenharmony_ci	bl\cond	trace_hardirqs_on
14662306a36Sopenharmony_ci	.if \save
14762306a36Sopenharmony_ci	ldmia	sp!, {r0-r3, ip, lr}
14862306a36Sopenharmony_ci	.endif
14962306a36Sopenharmony_ci#endif
15062306a36Sopenharmony_ci	.endm
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	.macro disable_irq, save=1
15362306a36Sopenharmony_ci	disable_irq_notrace
15462306a36Sopenharmony_ci	asm_trace_hardirqs_off \save
15562306a36Sopenharmony_ci	.endm
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	.macro enable_irq
15862306a36Sopenharmony_ci	asm_trace_hardirqs_on
15962306a36Sopenharmony_ci	enable_irq_notrace
16062306a36Sopenharmony_ci	.endm
16162306a36Sopenharmony_ci/*
16262306a36Sopenharmony_ci * Save the current IRQ state and disable IRQs.  Note that this macro
16362306a36Sopenharmony_ci * assumes FIQs are enabled, and that the processor is in SVC mode.
16462306a36Sopenharmony_ci */
16562306a36Sopenharmony_ci	.macro	save_and_disable_irqs, oldcpsr
16662306a36Sopenharmony_ci#ifdef CONFIG_CPU_V7M
16762306a36Sopenharmony_ci	mrs	\oldcpsr, primask
16862306a36Sopenharmony_ci#else
16962306a36Sopenharmony_ci	mrs	\oldcpsr, cpsr
17062306a36Sopenharmony_ci#endif
17162306a36Sopenharmony_ci	disable_irq
17262306a36Sopenharmony_ci	.endm
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	.macro	save_and_disable_irqs_notrace, oldcpsr
17562306a36Sopenharmony_ci#ifdef CONFIG_CPU_V7M
17662306a36Sopenharmony_ci	mrs	\oldcpsr, primask
17762306a36Sopenharmony_ci#else
17862306a36Sopenharmony_ci	mrs	\oldcpsr, cpsr
17962306a36Sopenharmony_ci#endif
18062306a36Sopenharmony_ci	disable_irq_notrace
18162306a36Sopenharmony_ci	.endm
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci/*
18462306a36Sopenharmony_ci * Restore interrupt state previously stored in a register.  We don't
18562306a36Sopenharmony_ci * guarantee that this will preserve the flags.
18662306a36Sopenharmony_ci */
18762306a36Sopenharmony_ci	.macro	restore_irqs_notrace, oldcpsr
18862306a36Sopenharmony_ci#ifdef CONFIG_CPU_V7M
18962306a36Sopenharmony_ci	msr	primask, \oldcpsr
19062306a36Sopenharmony_ci#else
19162306a36Sopenharmony_ci	msr	cpsr_c, \oldcpsr
19262306a36Sopenharmony_ci#endif
19362306a36Sopenharmony_ci	.endm
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	.macro restore_irqs, oldcpsr
19662306a36Sopenharmony_ci	tst	\oldcpsr, #PSR_I_BIT
19762306a36Sopenharmony_ci	asm_trace_hardirqs_on cond=eq
19862306a36Sopenharmony_ci	restore_irqs_notrace \oldcpsr
19962306a36Sopenharmony_ci	.endm
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci/*
20262306a36Sopenharmony_ci * Assembly version of "adr rd, BSYM(sym)".  This should only be used to
20362306a36Sopenharmony_ci * reference local symbols in the same assembly file which are to be
20462306a36Sopenharmony_ci * resolved by the assembler.  Other usage is undefined.
20562306a36Sopenharmony_ci */
20662306a36Sopenharmony_ci	.irp	c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
20762306a36Sopenharmony_ci	.macro	badr\c, rd, sym
20862306a36Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL
20962306a36Sopenharmony_ci	adr\c	\rd, \sym + 1
21062306a36Sopenharmony_ci#else
21162306a36Sopenharmony_ci	adr\c	\rd, \sym
21262306a36Sopenharmony_ci#endif
21362306a36Sopenharmony_ci	.endm
21462306a36Sopenharmony_ci	.endr
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci/*
21762306a36Sopenharmony_ci * Get current thread_info.
21862306a36Sopenharmony_ci */
21962306a36Sopenharmony_ci	.macro	get_thread_info, rd
22062306a36Sopenharmony_ci	/* thread_info is the first member of struct task_struct */
22162306a36Sopenharmony_ci	get_current \rd
22262306a36Sopenharmony_ci	.endm
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci/*
22562306a36Sopenharmony_ci * Increment/decrement the preempt count.
22662306a36Sopenharmony_ci */
22762306a36Sopenharmony_ci#ifdef CONFIG_PREEMPT_COUNT
22862306a36Sopenharmony_ci	.macro	inc_preempt_count, ti, tmp
22962306a36Sopenharmony_ci	ldr	\tmp, [\ti, #TI_PREEMPT]	@ get preempt count
23062306a36Sopenharmony_ci	add	\tmp, \tmp, #1			@ increment it
23162306a36Sopenharmony_ci	str	\tmp, [\ti, #TI_PREEMPT]
23262306a36Sopenharmony_ci	.endm
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	.macro	dec_preempt_count, ti, tmp
23562306a36Sopenharmony_ci	ldr	\tmp, [\ti, #TI_PREEMPT]	@ get preempt count
23662306a36Sopenharmony_ci	sub	\tmp, \tmp, #1			@ decrement it
23762306a36Sopenharmony_ci	str	\tmp, [\ti, #TI_PREEMPT]
23862306a36Sopenharmony_ci	.endm
23962306a36Sopenharmony_ci#else
24062306a36Sopenharmony_ci	.macro	inc_preempt_count, ti, tmp
24162306a36Sopenharmony_ci	.endm
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	.macro	dec_preempt_count, ti, tmp
24462306a36Sopenharmony_ci	.endm
24562306a36Sopenharmony_ci#endif
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci#define USERL(l, x...)				\
24862306a36Sopenharmony_ci9999:	x;					\
24962306a36Sopenharmony_ci	.pushsection __ex_table,"a";		\
25062306a36Sopenharmony_ci	.align	3;				\
25162306a36Sopenharmony_ci	.long	9999b,l;			\
25262306a36Sopenharmony_ci	.popsection
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci#define USER(x...)	USERL(9001f, x)
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci#ifdef CONFIG_SMP
25762306a36Sopenharmony_ci#define ALT_SMP(instr...)					\
25862306a36Sopenharmony_ci9998:	instr
25962306a36Sopenharmony_ci/*
26062306a36Sopenharmony_ci * Note: if you get assembler errors from ALT_UP() when building with
26162306a36Sopenharmony_ci * CONFIG_THUMB2_KERNEL, you almost certainly need to use
26262306a36Sopenharmony_ci * ALT_SMP( W(instr) ... )
26362306a36Sopenharmony_ci */
26462306a36Sopenharmony_ci#define ALT_UP(instr...)					\
26562306a36Sopenharmony_ci	.pushsection ".alt.smp.init", "a"			;\
26662306a36Sopenharmony_ci	.align	2						;\
26762306a36Sopenharmony_ci	.long	9998b - .					;\
26862306a36Sopenharmony_ci9997:	instr							;\
26962306a36Sopenharmony_ci	.if . - 9997b == 2					;\
27062306a36Sopenharmony_ci		nop						;\
27162306a36Sopenharmony_ci	.endif							;\
27262306a36Sopenharmony_ci	.if . - 9997b != 4					;\
27362306a36Sopenharmony_ci		.error "ALT_UP() content must assemble to exactly 4 bytes";\
27462306a36Sopenharmony_ci	.endif							;\
27562306a36Sopenharmony_ci	.popsection
27662306a36Sopenharmony_ci#define ALT_UP_B(label)					\
27762306a36Sopenharmony_ci	.pushsection ".alt.smp.init", "a"			;\
27862306a36Sopenharmony_ci	.align	2						;\
27962306a36Sopenharmony_ci	.long	9998b - .					;\
28062306a36Sopenharmony_ci	W(b)	. + (label - 9998b)					;\
28162306a36Sopenharmony_ci	.popsection
28262306a36Sopenharmony_ci#else
28362306a36Sopenharmony_ci#define ALT_SMP(instr...)
28462306a36Sopenharmony_ci#define ALT_UP(instr...) instr
28562306a36Sopenharmony_ci#define ALT_UP_B(label) b label
28662306a36Sopenharmony_ci#endif
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	/*
28962306a36Sopenharmony_ci	 * this_cpu_offset - load the per-CPU offset of this CPU into
29062306a36Sopenharmony_ci	 * 		     register 'rd'
29162306a36Sopenharmony_ci	 */
29262306a36Sopenharmony_ci	.macro		this_cpu_offset, rd:req
29362306a36Sopenharmony_ci#ifdef CONFIG_SMP
29462306a36Sopenharmony_ciALT_SMP(mrc		p15, 0, \rd, c13, c0, 4)
29562306a36Sopenharmony_ci#ifdef CONFIG_CPU_V6
29662306a36Sopenharmony_ciALT_UP_B(.L1_\@)
29762306a36Sopenharmony_ci.L0_\@:
29862306a36Sopenharmony_ci	.subsection	1
29962306a36Sopenharmony_ci.L1_\@: ldr_va		\rd, __per_cpu_offset
30062306a36Sopenharmony_ci	b		.L0_\@
30162306a36Sopenharmony_ci	.previous
30262306a36Sopenharmony_ci#endif
30362306a36Sopenharmony_ci#else
30462306a36Sopenharmony_ci	mov		\rd, #0
30562306a36Sopenharmony_ci#endif
30662306a36Sopenharmony_ci	.endm
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	/*
30962306a36Sopenharmony_ci	 * set_current - store the task pointer of this CPU's current task
31062306a36Sopenharmony_ci	 */
31162306a36Sopenharmony_ci	.macro		set_current, rn:req, tmp:req
31262306a36Sopenharmony_ci#if defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO) || defined(CONFIG_SMP)
31362306a36Sopenharmony_ci9998:	mcr		p15, 0, \rn, c13, c0, 3		@ set TPIDRURO register
31462306a36Sopenharmony_ci#ifdef CONFIG_CPU_V6
31562306a36Sopenharmony_ciALT_UP_B(.L0_\@)
31662306a36Sopenharmony_ci	.subsection	1
31762306a36Sopenharmony_ci.L0_\@: str_va		\rn, __current, \tmp
31862306a36Sopenharmony_ci	b		.L1_\@
31962306a36Sopenharmony_ci	.previous
32062306a36Sopenharmony_ci.L1_\@:
32162306a36Sopenharmony_ci#endif
32262306a36Sopenharmony_ci#else
32362306a36Sopenharmony_ci	str_va		\rn, __current, \tmp
32462306a36Sopenharmony_ci#endif
32562306a36Sopenharmony_ci	.endm
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	/*
32862306a36Sopenharmony_ci	 * get_current - load the task pointer of this CPU's current task
32962306a36Sopenharmony_ci	 */
33062306a36Sopenharmony_ci	.macro		get_current, rd:req
33162306a36Sopenharmony_ci#if defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO) || defined(CONFIG_SMP)
33262306a36Sopenharmony_ci9998:	mrc		p15, 0, \rd, c13, c0, 3		@ get TPIDRURO register
33362306a36Sopenharmony_ci#ifdef CONFIG_CPU_V6
33462306a36Sopenharmony_ciALT_UP_B(.L0_\@)
33562306a36Sopenharmony_ci	.subsection	1
33662306a36Sopenharmony_ci.L0_\@: ldr_va		\rd, __current
33762306a36Sopenharmony_ci	b		.L1_\@
33862306a36Sopenharmony_ci	.previous
33962306a36Sopenharmony_ci.L1_\@:
34062306a36Sopenharmony_ci#endif
34162306a36Sopenharmony_ci#else
34262306a36Sopenharmony_ci	ldr_va		\rd, __current
34362306a36Sopenharmony_ci#endif
34462306a36Sopenharmony_ci	.endm
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	/*
34762306a36Sopenharmony_ci	 * reload_current - reload the task pointer of this CPU's current task
34862306a36Sopenharmony_ci	 *		    into the TLS register
34962306a36Sopenharmony_ci	 */
35062306a36Sopenharmony_ci	.macro		reload_current, t1:req, t2:req
35162306a36Sopenharmony_ci#if defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO) || defined(CONFIG_SMP)
35262306a36Sopenharmony_ci#ifdef CONFIG_CPU_V6
35362306a36Sopenharmony_ciALT_SMP(nop)
35462306a36Sopenharmony_ciALT_UP_B(.L0_\@)
35562306a36Sopenharmony_ci#endif
35662306a36Sopenharmony_ci	ldr_this_cpu	\t1, __entry_task, \t1, \t2
35762306a36Sopenharmony_ci	mcr		p15, 0, \t1, c13, c0, 3		@ store in TPIDRURO
35862306a36Sopenharmony_ci.L0_\@:
35962306a36Sopenharmony_ci#endif
36062306a36Sopenharmony_ci	.endm
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci/*
36362306a36Sopenharmony_ci * Instruction barrier
36462306a36Sopenharmony_ci */
36562306a36Sopenharmony_ci	.macro	instr_sync
36662306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 7
36762306a36Sopenharmony_ci	isb
36862306a36Sopenharmony_ci#elif __LINUX_ARM_ARCH__ == 6
36962306a36Sopenharmony_ci	mcr	p15, 0, r0, c7, c5, 4
37062306a36Sopenharmony_ci#endif
37162306a36Sopenharmony_ci	.endm
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci/*
37462306a36Sopenharmony_ci * SMP data memory barrier
37562306a36Sopenharmony_ci */
37662306a36Sopenharmony_ci	.macro	smp_dmb mode
37762306a36Sopenharmony_ci#ifdef CONFIG_SMP
37862306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 7
37962306a36Sopenharmony_ci	.ifeqs "\mode","arm"
38062306a36Sopenharmony_ci	ALT_SMP(dmb	ish)
38162306a36Sopenharmony_ci	.else
38262306a36Sopenharmony_ci	ALT_SMP(W(dmb)	ish)
38362306a36Sopenharmony_ci	.endif
38462306a36Sopenharmony_ci#elif __LINUX_ARM_ARCH__ == 6
38562306a36Sopenharmony_ci	ALT_SMP(mcr	p15, 0, r0, c7, c10, 5)	@ dmb
38662306a36Sopenharmony_ci#else
38762306a36Sopenharmony_ci#error Incompatible SMP platform
38862306a36Sopenharmony_ci#endif
38962306a36Sopenharmony_ci	.ifeqs "\mode","arm"
39062306a36Sopenharmony_ci	ALT_UP(nop)
39162306a36Sopenharmony_ci	.else
39262306a36Sopenharmony_ci	ALT_UP(W(nop))
39362306a36Sopenharmony_ci	.endif
39462306a36Sopenharmony_ci#endif
39562306a36Sopenharmony_ci	.endm
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci/*
39862306a36Sopenharmony_ci * Raw SMP data memory barrier
39962306a36Sopenharmony_ci */
40062306a36Sopenharmony_ci	.macro	__smp_dmb mode
40162306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 7
40262306a36Sopenharmony_ci	.ifeqs "\mode","arm"
40362306a36Sopenharmony_ci	dmb	ish
40462306a36Sopenharmony_ci	.else
40562306a36Sopenharmony_ci	W(dmb)	ish
40662306a36Sopenharmony_ci	.endif
40762306a36Sopenharmony_ci#elif __LINUX_ARM_ARCH__ == 6
40862306a36Sopenharmony_ci	mcr	p15, 0, r0, c7, c10, 5	@ dmb
40962306a36Sopenharmony_ci#else
41062306a36Sopenharmony_ci	.error "Incompatible SMP platform"
41162306a36Sopenharmony_ci#endif
41262306a36Sopenharmony_ci	.endm
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci#if defined(CONFIG_CPU_V7M)
41562306a36Sopenharmony_ci	/*
41662306a36Sopenharmony_ci	 * setmode is used to assert to be in svc mode during boot. For v7-M
41762306a36Sopenharmony_ci	 * this is done in __v7m_setup, so setmode can be empty here.
41862306a36Sopenharmony_ci	 */
41962306a36Sopenharmony_ci	.macro	setmode, mode, reg
42062306a36Sopenharmony_ci	.endm
42162306a36Sopenharmony_ci#elif defined(CONFIG_THUMB2_KERNEL)
42262306a36Sopenharmony_ci	.macro	setmode, mode, reg
42362306a36Sopenharmony_ci	mov	\reg, #\mode
42462306a36Sopenharmony_ci	msr	cpsr_c, \reg
42562306a36Sopenharmony_ci	.endm
42662306a36Sopenharmony_ci#else
42762306a36Sopenharmony_ci	.macro	setmode, mode, reg
42862306a36Sopenharmony_ci	msr	cpsr_c, #\mode
42962306a36Sopenharmony_ci	.endm
43062306a36Sopenharmony_ci#endif
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci/*
43362306a36Sopenharmony_ci * Helper macro to enter SVC mode cleanly and mask interrupts. reg is
43462306a36Sopenharmony_ci * a scratch register for the macro to overwrite.
43562306a36Sopenharmony_ci *
43662306a36Sopenharmony_ci * This macro is intended for forcing the CPU into SVC mode at boot time.
43762306a36Sopenharmony_ci * you cannot return to the original mode.
43862306a36Sopenharmony_ci */
43962306a36Sopenharmony_ci.macro safe_svcmode_maskall reg:req
44062306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 6 && !defined(CONFIG_CPU_V7M)
44162306a36Sopenharmony_ci	mrs	\reg , cpsr
44262306a36Sopenharmony_ci	eor	\reg, \reg, #HYP_MODE
44362306a36Sopenharmony_ci	tst	\reg, #MODE_MASK
44462306a36Sopenharmony_ci	bic	\reg , \reg , #MODE_MASK
44562306a36Sopenharmony_ci	orr	\reg , \reg , #PSR_I_BIT | PSR_F_BIT | SVC_MODE
44662306a36Sopenharmony_ciTHUMB(	orr	\reg , \reg , #PSR_T_BIT	)
44762306a36Sopenharmony_ci	bne	1f
44862306a36Sopenharmony_ci	orr	\reg, \reg, #PSR_A_BIT
44962306a36Sopenharmony_ci	badr	lr, 2f
45062306a36Sopenharmony_ci	msr	spsr_cxsf, \reg
45162306a36Sopenharmony_ci	__MSR_ELR_HYP(14)
45262306a36Sopenharmony_ci	__ERET
45362306a36Sopenharmony_ci1:	msr	cpsr_c, \reg
45462306a36Sopenharmony_ci2:
45562306a36Sopenharmony_ci#else
45662306a36Sopenharmony_ci/*
45762306a36Sopenharmony_ci * workaround for possibly broken pre-v6 hardware
45862306a36Sopenharmony_ci * (akita, Sharp Zaurus C-1000, PXA270-based)
45962306a36Sopenharmony_ci */
46062306a36Sopenharmony_ci	setmode	PSR_F_BIT | PSR_I_BIT | SVC_MODE, \reg
46162306a36Sopenharmony_ci#endif
46262306a36Sopenharmony_ci.endm
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci/*
46562306a36Sopenharmony_ci * STRT/LDRT access macros with ARM and Thumb-2 variants
46662306a36Sopenharmony_ci */
46762306a36Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	.macro	usraccoff, instr, reg, ptr, inc, off, cond, abort, t=TUSER()
47062306a36Sopenharmony_ci9999:
47162306a36Sopenharmony_ci	.if	\inc == 1
47262306a36Sopenharmony_ci	\instr\()b\t\cond\().w \reg, [\ptr, #\off]
47362306a36Sopenharmony_ci	.elseif	\inc == 4
47462306a36Sopenharmony_ci	\instr\t\cond\().w \reg, [\ptr, #\off]
47562306a36Sopenharmony_ci	.else
47662306a36Sopenharmony_ci	.error	"Unsupported inc macro argument"
47762306a36Sopenharmony_ci	.endif
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	.pushsection __ex_table,"a"
48062306a36Sopenharmony_ci	.align	3
48162306a36Sopenharmony_ci	.long	9999b, \abort
48262306a36Sopenharmony_ci	.popsection
48362306a36Sopenharmony_ci	.endm
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort
48662306a36Sopenharmony_ci	@ explicit IT instruction needed because of the label
48762306a36Sopenharmony_ci	@ introduced by the USER macro
48862306a36Sopenharmony_ci	.ifnc	\cond,al
48962306a36Sopenharmony_ci	.if	\rept == 1
49062306a36Sopenharmony_ci	itt	\cond
49162306a36Sopenharmony_ci	.elseif	\rept == 2
49262306a36Sopenharmony_ci	ittt	\cond
49362306a36Sopenharmony_ci	.else
49462306a36Sopenharmony_ci	.error	"Unsupported rept macro argument"
49562306a36Sopenharmony_ci	.endif
49662306a36Sopenharmony_ci	.endif
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	@ Slightly optimised to avoid incrementing the pointer twice
49962306a36Sopenharmony_ci	usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort
50062306a36Sopenharmony_ci	.if	\rept == 2
50162306a36Sopenharmony_ci	usraccoff \instr, \reg, \ptr, \inc, \inc, \cond, \abort
50262306a36Sopenharmony_ci	.endif
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	add\cond \ptr, #\rept * \inc
50562306a36Sopenharmony_ci	.endm
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci#else	/* !CONFIG_THUMB2_KERNEL */
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort, t=TUSER()
51062306a36Sopenharmony_ci	.rept	\rept
51162306a36Sopenharmony_ci9999:
51262306a36Sopenharmony_ci	.if	\inc == 1
51362306a36Sopenharmony_ci	\instr\()b\t\cond \reg, [\ptr], #\inc
51462306a36Sopenharmony_ci	.elseif	\inc == 4
51562306a36Sopenharmony_ci	\instr\t\cond \reg, [\ptr], #\inc
51662306a36Sopenharmony_ci	.else
51762306a36Sopenharmony_ci	.error	"Unsupported inc macro argument"
51862306a36Sopenharmony_ci	.endif
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	.pushsection __ex_table,"a"
52162306a36Sopenharmony_ci	.align	3
52262306a36Sopenharmony_ci	.long	9999b, \abort
52362306a36Sopenharmony_ci	.popsection
52462306a36Sopenharmony_ci	.endr
52562306a36Sopenharmony_ci	.endm
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci#endif	/* CONFIG_THUMB2_KERNEL */
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	.macro	strusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
53062306a36Sopenharmony_ci	usracc	str, \reg, \ptr, \inc, \cond, \rept, \abort
53162306a36Sopenharmony_ci	.endm
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	.macro	ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
53462306a36Sopenharmony_ci	usracc	ldr, \reg, \ptr, \inc, \cond, \rept, \abort
53562306a36Sopenharmony_ci	.endm
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci/* Utility macro for declaring string literals */
53862306a36Sopenharmony_ci	.macro	string name:req, string
53962306a36Sopenharmony_ci	.type \name , #object
54062306a36Sopenharmony_ci\name:
54162306a36Sopenharmony_ci	.asciz "\string"
54262306a36Sopenharmony_ci	.size \name , . - \name
54362306a36Sopenharmony_ci	.endm
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	.irp	c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
54662306a36Sopenharmony_ci	.macro	ret\c, reg
54762306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ < 6
54862306a36Sopenharmony_ci	mov\c	pc, \reg
54962306a36Sopenharmony_ci#else
55062306a36Sopenharmony_ci	.ifeqs	"\reg", "lr"
55162306a36Sopenharmony_ci	bx\c	\reg
55262306a36Sopenharmony_ci	.else
55362306a36Sopenharmony_ci	mov\c	pc, \reg
55462306a36Sopenharmony_ci	.endif
55562306a36Sopenharmony_ci#endif
55662306a36Sopenharmony_ci	.endm
55762306a36Sopenharmony_ci	.endr
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci	.macro	ret.w, reg
56062306a36Sopenharmony_ci	ret	\reg
56162306a36Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL
56262306a36Sopenharmony_ci	nop
56362306a36Sopenharmony_ci#endif
56462306a36Sopenharmony_ci	.endm
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	.macro	bug, msg, line
56762306a36Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL
56862306a36Sopenharmony_ci1:	.inst	0xde02
56962306a36Sopenharmony_ci#else
57062306a36Sopenharmony_ci1:	.inst	0xe7f001f2
57162306a36Sopenharmony_ci#endif
57262306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_BUGVERBOSE
57362306a36Sopenharmony_ci	.pushsection .rodata.str, "aMS", %progbits, 1
57462306a36Sopenharmony_ci2:	.asciz	"\msg"
57562306a36Sopenharmony_ci	.popsection
57662306a36Sopenharmony_ci	.pushsection __bug_table, "aw"
57762306a36Sopenharmony_ci	.align	2
57862306a36Sopenharmony_ci	.word	1b, 2b
57962306a36Sopenharmony_ci	.hword	\line
58062306a36Sopenharmony_ci	.popsection
58162306a36Sopenharmony_ci#endif
58262306a36Sopenharmony_ci	.endm
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci#ifdef CONFIG_KPROBES
58562306a36Sopenharmony_ci#define _ASM_NOKPROBE(entry)				\
58662306a36Sopenharmony_ci	.pushsection "_kprobe_blacklist", "aw" ;	\
58762306a36Sopenharmony_ci	.balign 4 ;					\
58862306a36Sopenharmony_ci	.long entry;					\
58962306a36Sopenharmony_ci	.popsection
59062306a36Sopenharmony_ci#else
59162306a36Sopenharmony_ci#define _ASM_NOKPROBE(entry)
59262306a36Sopenharmony_ci#endif
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	.macro		__adldst_l, op, reg, sym, tmp, c
59562306a36Sopenharmony_ci	.if		__LINUX_ARM_ARCH__ < 7
59662306a36Sopenharmony_ci	ldr\c		\tmp, .La\@
59762306a36Sopenharmony_ci	.subsection	1
59862306a36Sopenharmony_ci	.align		2
59962306a36Sopenharmony_ci.La\@:	.long		\sym - .Lpc\@
60062306a36Sopenharmony_ci	.previous
60162306a36Sopenharmony_ci	.else
60262306a36Sopenharmony_ci	.ifnb		\c
60362306a36Sopenharmony_ci THUMB(	ittt		\c			)
60462306a36Sopenharmony_ci	.endif
60562306a36Sopenharmony_ci	movw\c		\tmp, #:lower16:\sym - .Lpc\@
60662306a36Sopenharmony_ci	movt\c		\tmp, #:upper16:\sym - .Lpc\@
60762306a36Sopenharmony_ci	.endif
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci#ifndef CONFIG_THUMB2_KERNEL
61062306a36Sopenharmony_ci	.set		.Lpc\@, . + 8			// PC bias
61162306a36Sopenharmony_ci	.ifc		\op, add
61262306a36Sopenharmony_ci	add\c		\reg, \tmp, pc
61362306a36Sopenharmony_ci	.else
61462306a36Sopenharmony_ci	\op\c		\reg, [pc, \tmp]
61562306a36Sopenharmony_ci	.endif
61662306a36Sopenharmony_ci#else
61762306a36Sopenharmony_ci.Lb\@:	add\c		\tmp, \tmp, pc
61862306a36Sopenharmony_ci	/*
61962306a36Sopenharmony_ci	 * In Thumb-2 builds, the PC bias depends on whether we are currently
62062306a36Sopenharmony_ci	 * emitting into a .arm or a .thumb section. The size of the add opcode
62162306a36Sopenharmony_ci	 * above will be 2 bytes when emitting in Thumb mode and 4 bytes when
62262306a36Sopenharmony_ci	 * emitting in ARM mode, so let's use this to account for the bias.
62362306a36Sopenharmony_ci	 */
62462306a36Sopenharmony_ci	.set		.Lpc\@, . + (. - .Lb\@)
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	.ifnc		\op, add
62762306a36Sopenharmony_ci	\op\c		\reg, [\tmp]
62862306a36Sopenharmony_ci	.endif
62962306a36Sopenharmony_ci#endif
63062306a36Sopenharmony_ci	.endm
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	/*
63362306a36Sopenharmony_ci	 * mov_l - move a constant value or [relocated] address into a register
63462306a36Sopenharmony_ci	 */
63562306a36Sopenharmony_ci	.macro		mov_l, dst:req, imm:req, cond
63662306a36Sopenharmony_ci	.if		__LINUX_ARM_ARCH__ < 7
63762306a36Sopenharmony_ci	ldr\cond	\dst, =\imm
63862306a36Sopenharmony_ci	.else
63962306a36Sopenharmony_ci	movw\cond	\dst, #:lower16:\imm
64062306a36Sopenharmony_ci	movt\cond	\dst, #:upper16:\imm
64162306a36Sopenharmony_ci	.endif
64262306a36Sopenharmony_ci	.endm
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	/*
64562306a36Sopenharmony_ci	 * adr_l - adr pseudo-op with unlimited range
64662306a36Sopenharmony_ci	 *
64762306a36Sopenharmony_ci	 * @dst: destination register
64862306a36Sopenharmony_ci	 * @sym: name of the symbol
64962306a36Sopenharmony_ci	 * @cond: conditional opcode suffix
65062306a36Sopenharmony_ci	 */
65162306a36Sopenharmony_ci	.macro		adr_l, dst:req, sym:req, cond
65262306a36Sopenharmony_ci	__adldst_l	add, \dst, \sym, \dst, \cond
65362306a36Sopenharmony_ci	.endm
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci	/*
65662306a36Sopenharmony_ci	 * ldr_l - ldr <literal> pseudo-op with unlimited range
65762306a36Sopenharmony_ci	 *
65862306a36Sopenharmony_ci	 * @dst: destination register
65962306a36Sopenharmony_ci	 * @sym: name of the symbol
66062306a36Sopenharmony_ci	 * @cond: conditional opcode suffix
66162306a36Sopenharmony_ci	 */
66262306a36Sopenharmony_ci	.macro		ldr_l, dst:req, sym:req, cond
66362306a36Sopenharmony_ci	__adldst_l	ldr, \dst, \sym, \dst, \cond
66462306a36Sopenharmony_ci	.endm
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	/*
66762306a36Sopenharmony_ci	 * str_l - str <literal> pseudo-op with unlimited range
66862306a36Sopenharmony_ci	 *
66962306a36Sopenharmony_ci	 * @src: source register
67062306a36Sopenharmony_ci	 * @sym: name of the symbol
67162306a36Sopenharmony_ci	 * @tmp: mandatory scratch register
67262306a36Sopenharmony_ci	 * @cond: conditional opcode suffix
67362306a36Sopenharmony_ci	 */
67462306a36Sopenharmony_ci	.macro		str_l, src:req, sym:req, tmp:req, cond
67562306a36Sopenharmony_ci	__adldst_l	str, \src, \sym, \tmp, \cond
67662306a36Sopenharmony_ci	.endm
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci	.macro		__ldst_va, op, reg, tmp, sym, cond, offset
67962306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 7 || \
68062306a36Sopenharmony_ci    !defined(CONFIG_ARM_HAS_GROUP_RELOCS) || \
68162306a36Sopenharmony_ci    (defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS))
68262306a36Sopenharmony_ci	mov_l		\tmp, \sym, \cond
68362306a36Sopenharmony_ci#else
68462306a36Sopenharmony_ci	/*
68562306a36Sopenharmony_ci	 * Avoid a literal load, by emitting a sequence of ADD/LDR instructions
68662306a36Sopenharmony_ci	 * with the appropriate relocations. The combined sequence has a range
68762306a36Sopenharmony_ci	 * of -/+ 256 MiB, which should be sufficient for the core kernel and
68862306a36Sopenharmony_ci	 * for modules loaded into the module region.
68962306a36Sopenharmony_ci	 */
69062306a36Sopenharmony_ci	.globl		\sym
69162306a36Sopenharmony_ci	.reloc		.L0_\@, R_ARM_ALU_PC_G0_NC, \sym
69262306a36Sopenharmony_ci	.reloc		.L1_\@, R_ARM_ALU_PC_G1_NC, \sym
69362306a36Sopenharmony_ci	.reloc		.L2_\@, R_ARM_LDR_PC_G2, \sym
69462306a36Sopenharmony_ci.L0_\@: sub\cond	\tmp, pc, #8 - \offset
69562306a36Sopenharmony_ci.L1_\@: sub\cond	\tmp, \tmp, #4 - \offset
69662306a36Sopenharmony_ci.L2_\@:
69762306a36Sopenharmony_ci#endif
69862306a36Sopenharmony_ci	\op\cond	\reg, [\tmp, #\offset]
69962306a36Sopenharmony_ci	.endm
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci	/*
70262306a36Sopenharmony_ci	 * ldr_va - load a 32-bit word from the virtual address of \sym
70362306a36Sopenharmony_ci	 */
70462306a36Sopenharmony_ci	.macro		ldr_va, rd:req, sym:req, cond, tmp, offset=0
70562306a36Sopenharmony_ci	.ifnb		\tmp
70662306a36Sopenharmony_ci	__ldst_va	ldr, \rd, \tmp, \sym, \cond, \offset
70762306a36Sopenharmony_ci	.else
70862306a36Sopenharmony_ci	__ldst_va	ldr, \rd, \rd, \sym, \cond, \offset
70962306a36Sopenharmony_ci	.endif
71062306a36Sopenharmony_ci	.endm
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci	/*
71362306a36Sopenharmony_ci	 * str_va - store a 32-bit word to the virtual address of \sym
71462306a36Sopenharmony_ci	 */
71562306a36Sopenharmony_ci	.macro		str_va, rn:req, sym:req, tmp:req, cond
71662306a36Sopenharmony_ci	__ldst_va	str, \rn, \tmp, \sym, \cond, 0
71762306a36Sopenharmony_ci	.endm
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	/*
72062306a36Sopenharmony_ci	 * ldr_this_cpu_armv6 - Load a 32-bit word from the per-CPU variable 'sym',
72162306a36Sopenharmony_ci	 *			without using a temp register. Supported in ARM mode
72262306a36Sopenharmony_ci	 *			only.
72362306a36Sopenharmony_ci	 */
72462306a36Sopenharmony_ci	.macro		ldr_this_cpu_armv6, rd:req, sym:req
72562306a36Sopenharmony_ci	this_cpu_offset	\rd
72662306a36Sopenharmony_ci	.globl		\sym
72762306a36Sopenharmony_ci	.reloc		.L0_\@, R_ARM_ALU_PC_G0_NC, \sym
72862306a36Sopenharmony_ci	.reloc		.L1_\@, R_ARM_ALU_PC_G1_NC, \sym
72962306a36Sopenharmony_ci	.reloc		.L2_\@, R_ARM_LDR_PC_G2, \sym
73062306a36Sopenharmony_ci	add		\rd, \rd, pc
73162306a36Sopenharmony_ci.L0_\@: sub		\rd, \rd, #4
73262306a36Sopenharmony_ci.L1_\@: sub		\rd, \rd, #0
73362306a36Sopenharmony_ci.L2_\@: ldr		\rd, [\rd, #4]
73462306a36Sopenharmony_ci	.endm
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci	/*
73762306a36Sopenharmony_ci	 * ldr_this_cpu - Load a 32-bit word from the per-CPU variable 'sym'
73862306a36Sopenharmony_ci	 *		  into register 'rd', which may be the stack pointer,
73962306a36Sopenharmony_ci	 *		  using 't1' and 't2' as general temp registers. These
74062306a36Sopenharmony_ci	 *		  are permitted to overlap with 'rd' if != sp
74162306a36Sopenharmony_ci	 */
74262306a36Sopenharmony_ci	.macro		ldr_this_cpu, rd:req, sym:req, t1:req, t2:req
74362306a36Sopenharmony_ci#ifndef CONFIG_SMP
74462306a36Sopenharmony_ci	ldr_va		\rd, \sym, tmp=\t1
74562306a36Sopenharmony_ci#elif __LINUX_ARM_ARCH__ >= 7 || \
74662306a36Sopenharmony_ci      !defined(CONFIG_ARM_HAS_GROUP_RELOCS) || \
74762306a36Sopenharmony_ci      (defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS))
74862306a36Sopenharmony_ci	this_cpu_offset	\t1
74962306a36Sopenharmony_ci	mov_l		\t2, \sym
75062306a36Sopenharmony_ci	ldr		\rd, [\t1, \t2]
75162306a36Sopenharmony_ci#else
75262306a36Sopenharmony_ci	ldr_this_cpu_armv6 \rd, \sym
75362306a36Sopenharmony_ci#endif
75462306a36Sopenharmony_ci	.endm
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	/*
75762306a36Sopenharmony_ci	 * rev_l - byte-swap a 32-bit value
75862306a36Sopenharmony_ci	 *
75962306a36Sopenharmony_ci	 * @val: source/destination register
76062306a36Sopenharmony_ci	 * @tmp: scratch register
76162306a36Sopenharmony_ci	 */
76262306a36Sopenharmony_ci	.macro		rev_l, val:req, tmp:req
76362306a36Sopenharmony_ci	.if		__LINUX_ARM_ARCH__ < 6
76462306a36Sopenharmony_ci	eor		\tmp, \val, \val, ror #16
76562306a36Sopenharmony_ci	bic		\tmp, \tmp, #0x00ff0000
76662306a36Sopenharmony_ci	mov		\val, \val, ror #8
76762306a36Sopenharmony_ci	eor		\val, \val, \tmp, lsr #8
76862306a36Sopenharmony_ci	.else
76962306a36Sopenharmony_ci	rev		\val, \val
77062306a36Sopenharmony_ci	.endif
77162306a36Sopenharmony_ci	.endm
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	.if		__LINUX_ARM_ARCH__ < 6
77462306a36Sopenharmony_ci	.set		.Lrev_l_uses_tmp, 1
77562306a36Sopenharmony_ci	.else
77662306a36Sopenharmony_ci	.set		.Lrev_l_uses_tmp, 0
77762306a36Sopenharmony_ci	.endif
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci	/*
78062306a36Sopenharmony_ci	 * bl_r - branch and link to register
78162306a36Sopenharmony_ci	 *
78262306a36Sopenharmony_ci	 * @dst: target to branch to
78362306a36Sopenharmony_ci	 * @c: conditional opcode suffix
78462306a36Sopenharmony_ci	 */
78562306a36Sopenharmony_ci	.macro		bl_r, dst:req, c
78662306a36Sopenharmony_ci	.if		__LINUX_ARM_ARCH__ < 6
78762306a36Sopenharmony_ci	mov\c		lr, pc
78862306a36Sopenharmony_ci	mov\c		pc, \dst
78962306a36Sopenharmony_ci	.else
79062306a36Sopenharmony_ci	blx\c		\dst
79162306a36Sopenharmony_ci	.endif
79262306a36Sopenharmony_ci	.endm
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci#endif /* __ASM_ASSEMBLER_H__ */
795