]> git.saurik.com Git - apple/xnu.git/blob - osfmk/arm/asm.h
xnu-7195.60.75.tar.gz
[apple/xnu.git] / osfmk / arm / asm.h
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 Software.Distribution@CS.CMU.EDU
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 #include <arm/arch.h>
61
62 #define FRAME pushl %ebp; movl %esp, %ebp
63 #define EMARF leave
64
65
66 /* There is another definition of ALIGN for .c sources */
67 #ifdef ASSEMBLER
68 #define ALIGN 2
69 #endif /* ASSEMBLER */
70
71 #ifndef FALIGN
72 #define FALIGN ALIGN
73 #endif
74
75 #define LB(x,n) n
76 #if __STDC__
77 #ifndef __NO_UNDERSCORES__
78 #define LCL(x) L ## x
79 #define EXT(x) _ ## x
80 #define LEXT(x) _ ## x ## :
81 #else
82 #define LCL(x) .L ## x
83 #define EXT(x) x
84 #define LEXT(x) x ## :
85 #endif
86 #define LBc(x,n) n ## :
87 #define LBb(x,n) n ## b
88 #define LBf(x,n) n ## f
89 #else /* __STDC__ */
90 #ifndef __NO_UNDERSCORES__
91 #define LCL(x) L/**/x
92 #define EXT(x) _/**/x
93 #define LEXT(x) _/**/x/**/:
94 #else /* __NO_UNDERSCORES__ */
95 #define LCL(x) .L/**/x
96 #define EXT(x) x
97 #define LEXT(x) x/**/:
98 #endif /* __NO_UNDERSCORES__ */
99 #define LBc(x,n) n/**/:
100 #define LBb(x,n) n/**/b
101 #define LBf(x,n) n/**/f
102 #endif /* __STDC__ */
103
104 #define String .asciz
105 #define Value .word
106 #define Times(a,b) (a*b)
107 #define Divide(a,b) (a/b)
108
109 #if 0 /* TOTOJK */
110 #ifdef __ELF__
111 #define ELF_FUNC(x) .type x,@function
112 #define ELF_DATA(x) .type x,@object
113 #define ELF_SIZE(x,s) .size x,s
114 #else
115 #define ELF_FUNC(x)
116 #define ELF_DATA(x)
117 #define ELF_SIZE(x,s)
118 #endif
119 #else
120 #define ELF_FUNC(x)
121 #define ELF_DATA(x)
122 #define ELF_SIZE(x,s)
123 #endif /* TODOJK */
124
125 #define Entry(x) .globl EXT(x); ELF_FUNC(EXT(x)); .align FALIGN; LEXT(x)
126 #define ENTRY(x) Entry(x) MCOUNT
127 #define ENTRY2(x,y) .globl EXT(x); .globl EXT(y); \
128 ELF_FUNC(EXT(x)); ELF_FUNC(EXT(y)); \
129 .align FALIGN; LEXT(x); LEXT(y) \
130 MCOUNT
131 #if __STDC__
132 #define ASENTRY(x) .globl x; .align FALIGN; x ## : ELF_FUNC(x) MCOUNT
133 #else
134 #define ASENTRY(x) .globl x; .align FALIGN; x: ELF_FUNC(x) MCOUNT
135 #endif /* __STDC__ */
136
137 #define DATA(x) .globl EXT(x); ELF_DATA(EXT(x)); .align ALIGN; LEXT(x)
138
139 #define End(x) ELF_SIZE(x,.-x)
140 #define END(x) End(EXT(x))
141 #define ENDDATA(x) END(x)
142 #define Enddata(x) End(x)
143
144 #ifdef ASSEMBLER
145
146 #define MCOUNT
147
148 #else /* NOT ASSEMBLER */
149
150 /* These defines are here for .c files that wish to reference global symbols
151 * within __asm__ statements.
152 */
153 #ifndef __NO_UNDERSCORES__
154 #define CC_SYM_PREFIX "_"
155 #else
156 #define CC_SYM_PREFIX ""
157 #endif /* __NO_UNDERSCORES__ */
158 #endif /* ASSEMBLER */
159
160 #ifdef ASSEMBLER
161
162 #if defined (_ARM_ARCH_4T)
163 # define RET bx lr
164 # define RETeq bxeq lr
165 # define RETne bxne lr
166 # ifdef __STDC__
167 # define RETc(c) bx##c lr
168 # else
169 # define RETc(c) bx/**/c lr
170 # endif
171 #else
172 # define RET mov pc, lr
173 # define RETeq moveq pc, lr
174 # define RETne movne pc, lr
175 # ifdef __STDC__
176 # define RETc(c) mov##c pc, lr
177 # else
178 # define RETc(c) mov/**/c pc, lr
179 # endif
180 #endif
181
182 #if defined (__thumb__)
183 /* Provide a PI mechanism for thumb branching. */
184 # define BRANCH_EXTERN(x) ldr pc, [pc, #-4] ; \
185 .long EXT(x)
186 #else
187 # define BRANCH_EXTERN(x) b EXT(x)
188 #endif
189
190 /*
191 * arg0: Register for thread pointer
192 */
193 .macro READ_THREAD
194 mrc p15, 0, $0, c13, c0, 4 /* Read TPIDRPRW */
195 .endmacro
196
197
198 /* Macros for loading up addresses that are external to the .s file.
199 * LOAD_ADDR: loads the address for (label) into (reg). Not safe for
200 * loading to the PC.
201 * LOAD_ADDR_PC: Variant for loading to the PC; load the address of (label)
202 * into the pc.
203 * LOAD_ADDR_GEN_DEF: The general definition needed to support loading
204 * a label address.
205 *
206 * Usage: For any label accessed, we require one (and only one) instance
207 * of LOAD_ADDR_GEN_DEF(label).
208 *
209 * Example:
210 * LOAD_ADDR(r0, arm_init)
211 * LOAD_ADDR(lr, arm_init_cpu)
212 * LOAD_ADDR_PC(arm_init)
213 * ...
214 *
215 * LOAD_ADDR_GEN_DEF(arm_init)
216 * LOAD_ADDR_GEN_DEF(arm_init_cpu)
217 */
218
219 #if SLIDABLE
220 /* Definitions for a position dependent kernel using non-lazy pointers.
221 */
222
223 /* TODO: Make this work with thumb .s files. */
224 #define PC_INC 0x8
225
226 /* We need wrapper macros in order to ensure that __LINE__ is expanded.
227 *
228 * There is some small potential for duplicate labels here, but because
229 * we do not export the generated labels, it should not be an issue.
230 */
231
232 #define GLUE_LABEL_GUTS(label, tag) L_##label##_##tag##_glue
233 #define GLUE_LABEL(label, tag) GLUE_LABEL_GUTS(label, tag)
234
235 #define LOAD_ADDR(reg, label) \
236 movw reg, :lower16:(label##$non_lazy_ptr - (GLUE_LABEL(label, __LINE__) + PC_INC)) ; \
237 movt reg, :upper16:(label##$non_lazy_ptr - (GLUE_LABEL(label, __LINE__) + PC_INC)) ; \
238 GLUE_LABEL(label, __LINE__): ; \
239 ldr reg, [pc, reg]
240
241 /* Designed with the understanding that directly branching to thumb code
242 * is unreliable; this should allow for dealing with __thumb__ in
243 * assembly; the non-thumb variant still needs to provide the glue label
244 * to avoid failing to build on undefined symbols.
245 *
246 * TODO: Make this actually use a scratch register; this macro is convenient
247 * for translating (ldr pc, [?]) to a slidable format without the risk of
248 * clobbering registers, but it is also wasteful.
249 */
250 #if defined(__thumb__)
251 #define LOAD_ADDR_PC(label) \
252 stmfd sp!, { r0 } ; \
253 stmfd sp!, { r0 } ; \
254 LOAD_ADDR(r0, label) ; \
255 str r0, [sp, #4] ; \
256 ldmfd sp!, { r0 } ; \
257 ldmfd sp!, { pc }
258 #else
259 #define LOAD_ADDR_PC(label) \
260 b EXT(label)
261 #endif
262
263 #define LOAD_ADDR_GEN_DEF(label) \
264 .section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers ; \
265 .align 2 ; \
266 label##$non_lazy_ptr: ; \
267 .indirect_symbol EXT(label) ; \
268 .long 0
269
270 #else /* !SLIDABLE */
271
272 /* Definitions for a position dependent kernel */
273 #define LOAD_ADDR(reg, label) \
274 ldr reg, L_##label
275
276 #if defined(__thumb__)
277 #define LOAD_ADDR_PC(label) \
278 ldr pc, L_##label
279 #else
280 #define LOAD_ADDR_PC(label) \
281 b EXT(label)
282 #endif
283
284 #define LOAD_ADDR_GEN_DEF(label) \
285 .text ; \
286 .align 2 ; \
287 L_##label: ; \
288 .long EXT(label)
289
290 #endif /* SLIDABLE */
291
292 /* The linker can deal with branching from ARM to thumb in unconditional
293 * branches, but not in conditional branches. To support this in our
294 * assembly (which allows us to build xnu without -mno-thumb), use the
295 * following macros for branching conditionally to external symbols.
296 * These macros are used just like the corresponding conditional branch
297 * instructions.
298 */
299
300 #define SHIM_LABEL_GUTS(line_num) L_cond_extern_##line_num##_shim
301 #define SHIM_LABEL(line_num) SHIM_LABEL_GUTS(line_num)
302
303 #define COND_EXTERN_BEQ(label) \
304 bne SHIM_LABEL(__LINE__) ; \
305 b EXT(label) ; \
306 SHIM_LABEL(__LINE__):
307
308 #define COND_EXTERN_BLNE(label) \
309 beq SHIM_LABEL(__LINE__) ; \
310 bl EXT(label) ; \
311 SHIM_LABEL(__LINE__):
312
313 #define COND_EXTERN_BLGT(label) \
314 ble SHIM_LABEL(__LINE__) ; \
315 bl EXT(label) ; \
316 SHIM_LABEL(__LINE__):
317
318 #endif /* ASSEMBLER */
319
320 #endif /* _ARM_ASM_H_ */