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