]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
8f6c56a5 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
8f6c56a5 A |
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 | |
8ad349bb | 24 | * limitations under the License. |
8f6c56a5 A |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
1c79356b A |
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 @\ | |
242 | name: @\ | |
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 @\ | |
257 | name: @\ | |
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 @\ | |
268 | name: | |
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 @\ | |
276 | name: @\ | |
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 @\ | |
291 | name: @\ | |
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 @\ | |
301 | name: | |
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 @\ | |
311 | name: | |
312 | ||
313 | /* | |
314 | * P_HANDLER -- declare private handler | |
315 | */ | |
316 | #define P_HANDLER(name) \ | |
317 | .align 2 @\ | |
318 | name: | |
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 @\ | |
362 | name: | |
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 @\ | |
389 | 1: 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 @\ | |
408 | L ## 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_ */ |