1/*
2 * Copyright (c) 2000 Apple Computer, 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/* Copyright (c) 1996 NeXT Software, Inc.  All rights reserved.
29 *
30 *	File:	architecture/ppc/asm_help.h
31 *	Author:	Mike DeMoney, NeXT Software, Inc.
32 *
33 *	This header file defines macros useful when writing assembly code
34 *	for the PowerPC processors.
35 *	r12 is used as the tmp register / PICIFY base.
36 *
37 * HISTORY
38 * 20-May-97  Umesh Vaishampayan (umeshv@apple.com)
39 *	Implemented Dynamic / PIC macros.
40 *
41 * 28-Dec-96  Umesh Vaishampayan (umeshv@NeXT.com)
42 *	added ".align" directive to various macros to avoid alignment
43 *  	faults. Moved Register Usage #defines to reg_help.h as that's
44 *	where they should have been in the first place.
45 *	Added Dynamic / PIC macroes for routines which refernce external
46 *	symbols. Not implemented fully as yet.
47 *
48 * 05-Nov-92  Mike DeMoney (mike@next.com)
49 *	Created.
50 */
51
52#ifndef	_ARCH_PPC_ASM_HELP_H_
53#define	_ARCH_PPC_ASM_HELP_H_
54
55#include	<architecture/ppc/reg_help.h>
56
57#ifdef	__ASSEMBLER__
58/*
59 * ppc stack frames look like this after procedure prolog has
60 * been executed:
61 *
62 * Higher address:
63 *			.........
64 *		+-------------------------------+
65 * 		| caller's LR			|
66 *		+-------------------------------+
67 * 		| caller's CR			|
68 *		+-------------------------------+
69 * Caller's SP->| caller's caller's sp		|  ^^ Caller's Frame ^^
70 *		+===============================+  vv Called Rtn Frame vv
71 *		|	Save Area for		| FPF 31
72 *			..........
73 *		| 	Caller's FPF's		| FPF n
74 *		+-------------------------------+
75 *		|	Save Area for		| GRF 31
76 *			..........
77 *		| 	Caller's GRF's		| GRF n
78 *		+-------------------------------+
79 *		|	alignment pad		|
80 *			............
81 *		|	(if necessary)		|
82 *		+-------------------------------+
83 *		|	Local			|
84 *			........
85 *		| 	Variables		|
86 *		+-------------------------------+
87 * SP + X ->	| aN for FUTURE call		|
88 *		+-------------------------------+
89 *			..........
90 *		+-------------------------------+
91 * SP + 28 ->	| a1 for FUTURE call		|
92 *		+-------------------------------+
93 * SP + 24 ->	| a0 for FUTURE call		|
94 *		+-------------------------------+
95 * SP + 20 ->	| caller's TOC			|
96 *		+-------------------------------+
97 * SP + 16 ->	| reserved			|
98 *		+-------------------------------+
99 * SP + 12 ->	| reserved			|
100 *		+-------------------------------+
101 * SP + 8 ->	| LR callee-save for FUTURE call|
102 *		+-------------------------------+
103 * SP + 4 ->	| CR callee-save for FUTURE call|
104 *		+-------------------------------+
105 * SP ->	| caller's sp			|
106 *		+===============================+
107 * Lower address:
108 *
109 * NOTE: All state with the exception of LR and CR are saved in the
110 * called routines frame.  LR and CR are saved in the CALLER'S FRAME.
111 *
112 * ALSO NOTE: Args to the called routine are found in the caller's frame.
113 */
114
115/*
116 * ARG(n) -- stack offset to n'th argument
117 *
118 * NOTE CAREFULLY!  These macros start numbering arguments at 1 (NOT 0)
119 * The first argument is ARG(1).
120 *
121 * ALSO NOTE:  This stack offset is only valid if using routine
122 * DOES NOT alter SP.
123 *
124 */
125#define	ARG(n)		((((n) - 1) * 4) + 24)
126
127/*
128 * Macros for building stack frame according to C calling conventions.
129 * lr, cr, and sp are saved.
130 *
131 * NOTE WELL: localvarsize is in bytes, maxargsout is a count of words,
132 * grfsaved and fpfsaved is a count of registers.  BE SURE TO COUNT
133 * BOTH FP (r31) AND sN REGISTERS IN THE COUNT OF GRF REGISTERS SAVED!
134 * This will be TWO more than the N of the highest sN register you
135 * save: s2 implies you are saving s2, s1, s0, and fp => grfsaved
136 * should be 4!
137 *
138 * FURTHER NOTE: These macros do NOT SAVE GRF or FPF registers.  User
139 * must do that.  GRF sN regs should be saved via
140 *	stmw	sN,SAVED_GRF_S(N)(sp)
141 * where N is the highest numbered s* register to be saved.  E.g. if
142 * s0, s1, and s2 are to be saved use:
143 *	stmw	s2,SAVED_GRF_S(2)(sp)
144 * Note that this also saves fp.
145 * An individual saved grf can be loaded via:
146 *	lwz	s2,SAVED_GRF_S(2)(sp)
147 * Analogous stuff works for fpf's.
148 *
149 * NOTE: these simple routines will be replaced with more complicated
150 * ones once we know what the linker and gdb will require as for as
151 * register use masks and frame declarations.
152 *
153 * Warning: ROUND_TO_STACK is only to be used in assembly language;
154 * for C usage, use ROUND_FRAME() in reg_help.h.
155 */
156#define	ROUND_TO_STACK(len)				\
157	(((len) + STACK_INCR - 1) / STACK_INCR * STACK_INCR)
158
159#define	BUILD_FRAME(localvarsize, maxargsout, grfsaved, fpfsaved)	\
160	.set	__argoutsize, ROUND_TO_STACK((maxargsout) * 4)		@\
161	.if	__argoutsize < 32					@\
162	  .set	__argoutsize,32						@\
163	.endif								@\
164	.set	__framesize, ROUND_TO_STACK(				\
165			24 + __argoutsize + (localvarsize)		\
166			+ 4*(grfsaved) + 8*(fpfsaved))			@\
167	.set	__grfbase,(__framesize - 4*(grfsaved) - 8*(fpfsaved))	@\
168	.set	__fpfbase,(__framesize - 8*(fpfsaved))			@\
169	mflr	r0							@\
170	mfcr	r12							@\
171	stw	r0,8(sp)						@\
172	stw	r12,4(sp)						@\
173	stwu	r1,-__framesize(r1)
174
175/*
176 * Macros for referencing data in stack frame.
177 *
178 * NOTE WELL: ARG's and VAR's start at 1, NOT 0. Why ??? (FIXME)
179 */
180#define	LOCAL_VAR(n)	(((n)-1)*4 + __argoutsize + 24)
181#define	SAVED_GRF_S(n)	(__grfbase + ((grfsaved) - (n) - 2) * 4)
182#define	SAVED_FRF_FS(n)	(__fpfbase + ((fpfsaved) - (n) - 1) * 4)
183#define	ARG_IN(n)	(ARG(n) + __framesize)
184#define	ARG_OUT(n)	(ARG(n) + 0)
185#define	SAVED_FP	(__grfbase + ((grfsaved) - 1) * 4)
186#define	SAVED_LR	(__framesize + 8)
187#define	SAVED_CR	(__framesize + 4)
188
189/*
190 * Macros for unwinding stack frame.
191 * NOTE: GRF's and FPF's are NOT RESTORED.  User must do this before
192 * using this macro.
193 */
194#define	RETURN						\
195	.if	__framesize				@\
196	  lwz32	r0,r1,SAVED_LR				@\
197	  lwz32	r12,r1,SAVED_CR				@\
198	  addic	sp,r1,__framesize			@\
199	  mtlr	r0					@\
200	  mtcrf	0xff,r12				@\
201	  blr						@\
202	.else						@\
203	  blr						@\
204	.endif
205
206
207/*
208 * Macros for declaring procedures
209 *
210 * Use of these macros allows ctags to have a predictable way
211 * to find various types of declarations.  They also simplify
212 * inserting appropriate symbol table information.
213 *
214 * NOTE: these simple stubs will be replaced with more
215 * complicated versions once we know what the linker and gdb
216 * will require as far as register use masks and frame declarations.
217 * These macros may also be ifdef'ed in the future to contain profiling
218 * code.
219 *
220 * FIXME: Document what makes a leaf a LEAF and a handler a HANDLER.
221 * (E.g. leaf's have return pc in lr, NESTED's have rpc in offset off
222 * sp, handlers have rpc in exception frame which is found via exception
223 * link, etc etc.)
224 */
225
226/*
227 * TEXT -- declare start of text segment
228 */
229#define	TEXT						\
230	.text						@\
231	.align 2
232
233/*
234 * LEAF -- declare global leaf procedure
235 * NOTE: Control SHOULD NOT FLOW into a LEAF!  A LEAF should only
236 * be jumped to.  (A leaf may do an align.)  Use a LABEL() if you
237 * need control to flow into the label.
238 */
239#define	LEAF(name)					\
240	.align 2					@\
241	.globl	name					@\
242name:							@\
243	.set	__framesize,0
244
245/*
246 * X_LEAF -- declare alternate global label for leaf
247 */
248#define	X_LEAF(name, value)				\
249	.globl	name					@\
250	.set	name,value
251
252/*
253 * P_LEAF -- declare private leaf procedure
254 */
255#define	P_LEAF(name)					\
256	.align 2					@\
257name:							@\
258	.set	__framesize,0
259
260/*
261 * LABEL -- declare a global code label
262 * MUST be used (rather than LEAF, NESTED, etc) if control
263 * "flows into" the label.
264 */
265#define	LABEL(name)					\
266	.align 2					@\
267	.globl	name					@\
268name:
269
270/*
271 * NESTED -- declare procedure that invokes other procedures
272 */
273#define	NESTED(name, localvarsize, maxargsout, grfsaved, fpfsaved)\
274	.align 2				@\
275	.globl	name				@\
276name:						@\
277	BUILD_FRAME(localvarsize, maxargsout, grfsaved, fpfsaved)
278
279/*
280 * X_NESTED -- declare alternate global label for nested proc
281 */
282#define	X_NESTED(name, value)			\
283	.globl	name				@\
284	.set	name,value
285
286/*
287 * P_NESTED -- declare private nested procedure
288 */
289#define	P_NESTED(name, localvarsize, maxargsout, grfsaved, fpfsaved)\
290	.align 2					@\
291name:							@\
292	BUILD_FRAME(locavarsize, maxargsout, grfsaved, fpfsaved)
293
294/*
295 * HANDLER -- declare procedure with exception frame rather than
296 * standard C frame
297 */
298#define	HANDLER(name)					\
299	.align 2					@\
300	.globl	name					@\
301name:
302
303/*
304 * X_HANDLER -- declare alternate name for exception handler
305 * (Should appear immediately before a HANDLER declaration or
306 * another X_HANDLER declaration)
307 */
308#define	X_HANDLER(name)					\
309	.align 2					@\
310	.globl	name					@\
311name:
312
313/*
314 * P_HANDLER -- declare private handler
315 */
316#define	P_HANDLER(name)					\
317	.align 2				@\
318name:
319
320/*
321 * END -- mark end of procedure
322 * FIXME: Unimplemented for now.
323 */
324#define	END(name)
325
326/*
327 * BL -- call procedure (relative)
328 */
329#define	BL(name)					\
330	bl	name
331
332/*
333 * Storage definition macros
334 * The main purpose of these is to allow an easy handle for ctags
335 */
336
337/*
338 * IMPORT -- import symbol
339 */
340#define	IMPORT(name)					\
341	.reference	name
342
343/*
344 * ABS -- declare global absolute symbol
345 */
346#define	ABS(name, value)				\
347	.globl	name					@\
348	.set	name,value
349
350/*
351 * P_ABS -- declare private absolute symbol
352 */
353#define	P_ABS(name, value)				\
354	.set	name,value
355
356/*
357 * EXPORT -- declare global label for data
358 */
359#define	EXPORT(name)					\
360	.align 2					@\
361	.globl	name					@\
362name:
363
364/*
365 * BSS -- declare global zero'ed storage
366 */
367#define	BSS(name,size)					\
368	.comm	name,size
369
370
371/*
372 * P_BSS -- declare private zero'ed storage
373 */
374#define	P_BSS(name,size)				\
375	.lcomm	name,size
376
377/*
378 * dynamic/PIC macros for routines which reference external symbols
379 */
380#if defined(__DYNAMIC__)
381#define PICIFY_REG r12
382
383/* Assume that the lr is saved before calling any of these macros */
384/* using PICIFY() */
385
386#define PICIFY(var)				\
387	mflr	r0				@\
388	bl	1f				@\
3891:	mflr	PICIFY_REG			@\
390	mtlr	r0				@\
391	addis	PICIFY_REG, PICIFY_REG, ha16(L ## var ## $non_lazy_ptr - 1b) @\
392	lwz	PICIFY_REG, lo16(L ## var ## $non_lazy_ptr - 1b)(PICIFY_REG)
393
394#define CALL_EXTERN_AGAIN(var)			\
395	PICIFY(var)				@\
396	mtctr	PICIFY_REG			@\
397	mflr	r0				@\
398	stw	r0,8(r1)			@\
399	stwu	r1,-56(r1)			@\
400	bctrl					@\
401	addic	r1,r1,56     			@\
402	lwz	r0,8(r1)			@\
403	mtlr	r0
404
405#define NON_LAZY_STUB(var)			\
406	.non_lazy_symbol_pointer		@\
407	.align 2				@\
408L ## var ## $non_lazy_ptr:			@\
409	.indirect_symbol var			@\
410	.long 0					@\
411	.text					@\
412	.align 2
413
414#define	BRANCH_EXTERN(var)			\
415	PICIFY(var)				@\
416	mtctr	PICIFY_REG			@\
417	bctr					@\
418	NON_LAZY_STUB(var)
419
420#define CALL_EXTERN(var)			\
421	CALL_EXTERN_AGAIN(var)			@\
422	NON_LAZY_STUB(var)
423
424#define REG_TO_EXTERN(reg, var)			\
425	PICIFY(var)				@\
426	stw reg, 0(PICIFY_REG)			@\
427	NON_LAZY_STUB(var)
428
429#define EXTERN_TO_REG(reg, var)			\
430	PICIFY(var)				@\
431	lwz	reg, 0(PICIFY_REG)		@\
432	NON_LAZY_STUB(var)
433
434#else /* ! __DYNAMIC__ */
435#define TMP_REG r12
436#define BRANCH_EXTERN(var)			\
437	b	var
438
439#define CALL_EXTERN(var)			\
440	bl	var
441
442#define CALL_EXTERN_AGAIN(var)			\
443	CALL_EXTERN(var)
444
445#define REG_TO_EXTERN(reg, var)			\
446	lis	TMP_REG, ha16(var)		@\
447	stw	reg, lo16(var)(TMP_REG)
448
449#define EXTERN_TO_REG(reg, var)			\
450	lis	reg, ha16(var)			@\
451	lwz	reg, lo16(var)(reg)
452
453#endif	/* __DYNAMIC__ */
454
455#endif	/* __ASSEMBLER__ */
456#endif	/* _ARCH_PPC_ASM_HELP_H_ */
457