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