1/*
2 * Based on arch/arm/include/asm/assembler.h
3 *
4 * Copyright (C) 1996-2000 Russell King
5 * Copyright (C) 2012 ARM Ltd.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19#ifndef __ASSEMBLY__
20#error "Only include this from assembly code"
21#endif
22
23#ifndef __ASM_ASSEMBLER_H
24#define __ASM_ASSEMBLER_H
25
26#include <asm/ptrace.h>
27#include <asm/thread_info.h>
28
29/*
30 * Stack pushing/popping (register pairs only). Equivalent to store decrement
31 * before, load increment after.
32 */
33	.macro	push, xreg1, xreg2
34	stp	\xreg1, \xreg2, [sp, #-16]!
35	.endm
36
37	.macro	pop, xreg1, xreg2
38	ldp	\xreg1, \xreg2, [sp], #16
39	.endm
40
41/*
42 * Enable and disable interrupts.
43 */
44	.macro	disable_irq
45	msr	daifset, #2
46	.endm
47
48	.macro	enable_irq
49	msr	daifclr, #2
50	.endm
51
52/*
53 * Save/disable and restore interrupts.
54 */
55	.macro	save_and_disable_irqs, olddaif
56	mrs	\olddaif, daif
57	disable_irq
58	.endm
59
60	.macro	restore_irqs, olddaif
61	msr	daif, \olddaif
62	.endm
63
64/*
65 * Enable and disable debug exceptions.
66 */
67	.macro	disable_dbg
68	msr	daifset, #8
69	.endm
70
71	.macro	enable_dbg
72	msr	daifclr, #8
73	.endm
74
75	.macro	disable_step_tsk, flgs, tmp
76	tbz	\flgs, #TIF_SINGLESTEP, 9990f
77	mrs	\tmp, mdscr_el1
78	bic	\tmp, \tmp, #1
79	msr	mdscr_el1, \tmp
80	isb	// Synchronise with enable_dbg
819990:
82	.endm
83
84	.macro	enable_step_tsk, flgs, tmp
85	tbz	\flgs, #TIF_SINGLESTEP, 9990f
86	disable_dbg
87	mrs	\tmp, mdscr_el1
88	orr	\tmp, \tmp, #1
89	msr	mdscr_el1, \tmp
909990:
91	.endm
92
93/*
94 * Enable both debug exceptions and interrupts. This is likely to be
95 * faster than two daifclr operations, since writes to this register
96 * are self-synchronising.
97 */
98	.macro	enable_dbg_and_irq
99	msr	daifclr, #(8 | 2)
100	.endm
101
102/*
103 * SMP data memory barrier
104 */
105	.macro	smp_dmb, opt
106#ifdef CONFIG_SMP
107	dmb	\opt
108#endif
109	.endm
110
111#define USER(l, x...)				\
1129999:	x;					\
113	.section __ex_table,"a";		\
114	.align	3;				\
115	.quad	9999b,l;			\
116	.previous
117
118/*
119 * Register aliases.
120 */
121lr	.req	x30		// link register
122
123/*
124 * Vector entry
125 */
126	 .macro	ventry	label
127	.align	7
128	b	\label
129	.endm
130
131/*
132 * Select code when configured for BE.
133 */
134#ifdef CONFIG_CPU_BIG_ENDIAN
135#define CPU_BE(code...) code
136#else
137#define CPU_BE(code...)
138#endif
139
140/*
141 * Select code when configured for LE.
142 */
143#ifdef CONFIG_CPU_BIG_ENDIAN
144#define CPU_LE(code...)
145#else
146#define CPU_LE(code...) code
147#endif
148
149/*
150 * Define a macro that constructs a 64-bit value by concatenating two
151 * 32-bit registers. Note that on big endian systems the order of the
152 * registers is swapped.
153 */
154#ifndef CONFIG_CPU_BIG_ENDIAN
155	.macro	regs_to_64, rd, lbits, hbits
156#else
157	.macro	regs_to_64, rd, hbits, lbits
158#endif
159	orr	\rd, \lbits, \hbits, lsl #32
160	.endm
161
162/*
163 * Pseudo-ops for PC-relative adr/ldr/str <reg>, <symbol> where
164 * <symbol> is within the range +/- 4 GB of the PC.
165 */
166	/*
167	 * @dst: destination register (64 bit wide)
168	 * @sym: name of the symbol
169	 * @tmp: optional scratch register to be used if <dst> == sp, which
170	 *       is not allowed in an adrp instruction
171	 */
172	.macro	adr_l, dst, sym, tmp=
173	.ifb	\tmp
174	adrp	\dst, \sym
175	add	\dst, \dst, :lo12:\sym
176	.else
177	adrp	\tmp, \sym
178	add	\dst, \tmp, :lo12:\sym
179	.endif
180	.endm
181
182	/*
183	 * @dst: destination register (32 or 64 bit wide)
184	 * @sym: name of the symbol
185	 * @tmp: optional 64-bit scratch register to be used if <dst> is a
186	 *       32-bit wide register, in which case it cannot be used to hold
187	 *       the address
188	 */
189	.macro	ldr_l, dst, sym, tmp=
190	.ifb	\tmp
191	adrp	\dst, \sym
192	ldr	\dst, [\dst, :lo12:\sym]
193	.else
194	adrp	\tmp, \sym
195	ldr	\dst, [\tmp, :lo12:\sym]
196	.endif
197	.endm
198
199	/*
200	 * @src: source register (32 or 64 bit wide)
201	 * @sym: name of the symbol
202	 * @tmp: mandatory 64-bit scratch register to calculate the address
203	 *       while <src> needs to be preserved.
204	 */
205	.macro	str_l, src, sym, tmp
206	adrp	\tmp, \sym
207	str	\src, [\tmp, :lo12:\sym]
208	.endm
209
210#endif	/* __ASM_ASSEMBLER_H */
211