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 @\ 236name: @\ 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 @\ 251name: @\ 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 @\ 262name: 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 @\ 270name: @\ 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 @\ 285name: @\ 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 @\ 295name: 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 @\ 305name: 306 307/* 308 * P_HANDLER -- declare private handler 309 */ 310#define P_HANDLER(name) \ 311 .align 2 @\ 312name: 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 @\ 356name: 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 @\ 3831: 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 @\ 402L ## 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_ */ 451

