]>
Commit | Line | Data |
---|---|---|
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_ */ |