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