|
|
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.