|
|
1.1 root 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 ([email protected])
33: * Implemented Dynamic / PIC macros.
34: *
35: * 28-Dec-96 Umesh Vaishampayan ([email protected])
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 ([email protected])
43: * Created.
44: */
45:
46: #ifndef _ARCH_PPC_ASM_HELP_H_
47: #define _ARCH_PPC_ASM_HELP_H_
48:
49: #import <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_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.