xref: /linux/arch/arm64/include/asm/assembler.h (revision 2ba9268dd603d23e17643437b2246acb6844953b)
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
81 9990:
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
90 9990:
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...)				\
112 9999:	x;					\
113 	.section __ex_table,"a";		\
114 	.align	3;				\
115 	.quad	9999b,l;			\
116 	.previous
117 
118 /*
119  * Register aliases.
120  */
121 lr	.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 #endif	/* __ASM_ASSEMBLER_H */
163