xref: /xnu-8796.101.5/osfmk/arm/asm.h (revision aca3beaa3dfbd42498b42c5e5ce20a938e6554e5)
1 /*
2  * Copyright (c) 2007 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /*
29  * @OSF_COPYRIGHT@
30  */
31 /*
32  * Mach Operating System
33  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
34  * All Rights Reserved.
35  *
36  * Permission to use, copy, modify and distribute this software and its
37  * documentation is hereby granted, provided that both the copyright
38  * notice and this permission notice appear in all copies of the
39  * software, derivative works or modified versions, and any portions
40  * thereof, and that both notices appear in supporting documentation.
41  *
42  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45  *
46  * Carnegie Mellon requests users of this software to return to
47  *
48  *  Software Distribution Coordinator  or  [email protected]
49  *  School of Computer Science
50  *  Carnegie Mellon University
51  *  Pittsburgh PA 15213-3890
52  *
53  * any improvements or extensions that they make and grant Carnegie Mellon
54  * the rights to redistribute these changes.
55  */
56 
57 #ifndef	_ARM_ASM_H_
58 #define	_ARM_ASM_H_
59 
60 #if defined (__arm__) || defined (__arm64__)
61 
62 #include <arm/arch.h>
63 
64 #define FRAME	pushl %ebp; movl %esp, %ebp
65 #define EMARF	leave
66 
67 
68 /* There is another definition of ALIGN for .c sources */
69 #ifdef ASSEMBLER
70 #define ALIGN 2
71 #endif /* ASSEMBLER */
72 
73 #ifndef FALIGN
74 #define FALIGN ALIGN
75 #endif
76 
77 #define LB(x,n) n
78 #if	__STDC__
79 #ifndef __NO_UNDERSCORES__
80 #define	LCL(x)	L ## x
81 #define EXT(x) _ ## x
82 #define LEXT(x) _ ## x ## :
83 #else
84 #define	LCL(x)	.L ## x
85 #define EXT(x) x
86 #define LEXT(x) x ## :
87 #endif
88 #define LBc(x,n) n ## :
89 #define LBb(x,n) n ## b
90 #define LBf(x,n) n ## f
91 #else /* __STDC__ */
92 #ifndef __NO_UNDERSCORES__
93 #define LCL(x) L/**/x
94 #define EXT(x) _/**/x
95 #define LEXT(x) _/**/x/**/:
96 #else /* __NO_UNDERSCORES__ */
97 #define	LCL(x)	.L/**/x
98 #define EXT(x) x
99 #define LEXT(x) x/**/:
100 #endif /* __NO_UNDERSCORES__ */
101 #define LBc(x,n) n/**/:
102 #define LBb(x,n) n/**/b
103 #define LBf(x,n) n/**/f
104 #endif /* __STDC__ */
105 
106 #define String	.asciz
107 #define Value	.word
108 #define Times(a,b) (a*b)
109 #define Divide(a,b) (a/b)
110 
111 #if 0 /* TOTOJK */
112 #ifdef __ELF__
113 #define ELF_FUNC(x)	.type x,@function
114 #define ELF_DATA(x)	.type x,@object
115 #define ELF_SIZE(x,s)	.size x,s
116 #else
117 #define ELF_FUNC(x)
118 #define ELF_DATA(x)
119 #define ELF_SIZE(x,s)
120 #endif
121 #else
122 #define ELF_FUNC(x)
123 #define ELF_DATA(x)
124 #define ELF_SIZE(x,s)
125 #endif /* TODOJK */
126 
127 #define	Entry(x)	.globl EXT(x); ELF_FUNC(EXT(x)); .align FALIGN; LEXT(x)
128 #define	ENTRY(x)	Entry(x) MCOUNT
129 #define	ENTRY2(x,y)	.globl EXT(x); .globl EXT(y); \
130 			ELF_FUNC(EXT(x)); ELF_FUNC(EXT(y)); \
131 			.align FALIGN; LEXT(x); LEXT(y) \
132 			MCOUNT
133 #if __STDC__
134 #define	ASENTRY(x) 	.globl x; .align FALIGN; x ## : ELF_FUNC(x) MCOUNT
135 #else
136 #define	ASENTRY(x) 	.globl x; .align FALIGN; x: ELF_FUNC(x) MCOUNT
137 #endif /* __STDC__ */
138 
139 #define	DATA(x)		.globl EXT(x); ELF_DATA(EXT(x)); .align ALIGN; LEXT(x)
140 
141 #define End(x)		ELF_SIZE(x,.-x)
142 #define END(x)		End(EXT(x))
143 #define ENDDATA(x)	END(x)
144 #define Enddata(x)	End(x)
145 
146 #ifdef ASSEMBLER
147 
148 #define MCOUNT
149 
150 #else /* NOT ASSEMBLER */
151 
152 /* These defines are here for .c files that wish to reference global symbols
153  * within __asm__ statements.
154  */
155 #ifndef __NO_UNDERSCORES__
156 #define CC_SYM_PREFIX "_"
157 #else
158 #define CC_SYM_PREFIX ""
159 #endif /* __NO_UNDERSCORES__ */
160 #endif /* ASSEMBLER */
161 
162 #ifdef ASSEMBLER
163 
164 #if defined (_ARM_ARCH_4T)
165 # define RET    bx      lr
166 # define RETeq  bxeq    lr
167 # define RETne  bxne    lr
168 # ifdef __STDC__
169 #  define RETc(c) bx##c lr
170 # else
171 #  define RETc(c) bx/**/c       lr
172 # endif
173 #else
174 # define RET    mov     pc, lr
175 # define RETeq  moveq   pc, lr
176 # define RETne  movne   pc, lr
177 # ifdef __STDC__
178 #  define RETc(c) mov##c        pc, lr
179 # else
180 #  define RETc(c) mov/**/c      pc, lr
181 # endif
182 #endif
183 
184 #if defined (__thumb__)
185 /* Provide a PI mechanism for thumb branching. */
186 # define BRANCH_EXTERN(x)	ldr	pc, [pc, #-4] ;	\
187 				.long	EXT(x)
188 #else
189 # define BRANCH_EXTERN(x)	b	EXT(x)
190 #endif
191 
192 /*
193  * arg0: Register for thread pointer
194  */
195 .macro READ_THREAD
196 	mrc p15, 0, $0, c13, c0, 4  /* Read TPIDRPRW */
197 .endmacro
198 
199 
200 /* Macros for loading up addresses that are external to the .s file.
201  * LOAD_ADDR:  loads the address for (label) into (reg). Not safe for
202  *   loading to the PC.
203  * LOAD_ADDR_PC:  Variant for loading to the PC; load the address of (label)
204  *   into the pc.
205  * LOAD_ADDR_GEN_DEF:  The general definition needed to support loading
206  *   a label address.
207  *
208  * Usage:  For any label accessed, we require one (and only one) instance
209  *   of LOAD_ADDR_GEN_DEF(label).
210  *
211  * Example:
212  *   LOAD_ADDR(r0, arm_init)
213  *   LOAD_ADDR(lr, arm_init_cpu)
214  *   LOAD_ADDR_PC(arm_init)
215  *   ...
216  *
217  *   LOAD_ADDR_GEN_DEF(arm_init)
218  *   LOAD_ADDR_GEN_DEF(arm_init_cpu)
219  */
220 
221 /* Definitions for a position dependent kernel using non-lazy pointers.
222  */
223 
224 /* TODO: Make this work with thumb .s files. */
225 #define PC_INC	0x8
226 
227 /* We need wrapper macros in order to ensure that __LINE__ is expanded.
228  *
229  * There is some small potential for duplicate labels here, but because
230  *   we do not export the generated labels, it should not be an issue.
231  */
232 
233 #define GLUE_LABEL_GUTS(label, tag) L_##label##_##tag##_glue
234 #define GLUE_LABEL(label, tag) GLUE_LABEL_GUTS(label, tag)
235 
236 #define LOAD_ADDR(reg, label)                                                                   \
237 	movw	reg, :lower16:(label##$non_lazy_ptr - (GLUE_LABEL(label, __LINE__) + PC_INC)) ; \
238 	movt	reg, :upper16:(label##$non_lazy_ptr - (GLUE_LABEL(label, __LINE__) + PC_INC)) ; \
239 GLUE_LABEL(label, __LINE__): ;                                                                  \
240 	ldr	reg, [pc, reg]
241 
242 /* Designed with the understanding that directly branching to thumb code
243  *   is unreliable; this should allow for dealing with __thumb__ in
244  *   assembly; the non-thumb variant still needs to provide the glue label
245  *   to avoid failing to build on undefined symbols.
246  *
247  * TODO: Make this actually use a scratch register; this macro is convenient
248  *   for translating (ldr pc, [?]) to a slidable format without the risk of
249  *   clobbering registers, but it is also wasteful.
250  */
251 #if defined(__thumb__)
252 #define LOAD_ADDR_PC(label)    \
253 	stmfd	sp!, { r0 } ;  \
254 	stmfd	sp!, { r0 } ;  \
255 	LOAD_ADDR(r0, label) ; \
256 	str	r0, [sp, #4] ; \
257 	ldmfd	sp!, { r0 } ;  \
258 	ldmfd	sp!, { pc }
259 #else
260 #define LOAD_ADDR_PC(label) \
261 	b	EXT(label)
262 #endif
263 
264 #define LOAD_ADDR_GEN_DEF(label)                                   \
265 	.section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers ; \
266 	.align 2 ;                                                 \
267 label##$non_lazy_ptr: ;                                            \
268 	.indirect_symbol	EXT(label) ;                       \
269 	.long			0
270 
271 /* The linker can deal with branching from ARM to thumb in unconditional
272  *   branches, but not in conditional branches.  To support this in our
273  *   assembly (which allows us to build xnu without -mno-thumb), use the
274  *   following macros for branching conditionally to external symbols.
275  *   These macros are used just like the corresponding conditional branch
276  *   instructions.
277  */
278 
279 #define SHIM_LABEL_GUTS(line_num) L_cond_extern_##line_num##_shim
280 #define SHIM_LABEL(line_num) SHIM_LABEL_GUTS(line_num)
281 
282 #define COND_EXTERN_BEQ(label)         \
283 	bne	SHIM_LABEL(__LINE__) ; \
284 	b	EXT(label) ;           \
285 SHIM_LABEL(__LINE__):
286 
287 #define COND_EXTERN_BLNE(label)        \
288 	beq	SHIM_LABEL(__LINE__) ; \
289 	bl	EXT(label) ;           \
290 SHIM_LABEL(__LINE__):
291 
292 #define COND_EXTERN_BLGT(label)        \
293 	ble	SHIM_LABEL(__LINE__) ; \
294 	bl	EXT(label) ;           \
295 SHIM_LABEL(__LINE__):
296 
297 #endif /* ASSEMBLER */
298 
299 #endif /* defined (__arm__) || defined (__arm64__) */
300 
301 #endif /* _ARM_ASM_H_ */
302