1 /* $NetBSD: asm.h,v 1.26 2001/12/18 17:12:32 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1991,1990,1989,1994,1995,1996 Carnegie Mellon University 5 * All Rights Reserved. 6 * 7 * Permission to use, copy, modify and distribute this software and its 8 * documentation is hereby granted, provided that both the copyright 9 * notice and this permission notice appear in all copies of the 10 * software, derivative works or modified versions, and any portions 11 * thereof, and that both notices appear in supporting documentation. 12 * 13 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 14 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 15 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 16 * 17 * Carnegie Mellon requests users of this software to return to 18 * 19 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 20 * School of Computer Science 21 * Carnegie Mellon University 22 * Pittsburgh PA 15213-3890 23 * 24 * any improvements or extensions that they make and grant Carnegie Mellon 25 * the rights to redistribute these changes. 26 */ 27 28 /* 29 * Assembly coding style 30 * 31 * This file contains macros and register defines to 32 * aid in writing more readable assembly code. 33 * Some rules to make assembly code understandable by 34 * a debugger are also noted. 35 * 36 * The document 37 * 38 * "ALPHA Calling Standard", DEC 27-Apr-90 39 * 40 * defines (a superset of) the rules and conventions 41 * we use. While we make no promise of adhering to 42 * such standard and its evolution (esp where we 43 * can get faster code paths) it is certainly intended 44 * that we be interoperable with such standard. 45 * 46 * In this sense, this file is a proper part of the 47 * definition of the (software) Alpha architecture. 48 */ 49 50 /* 51 * Symbolic register names and register saving rules 52 * 53 * Legend: 54 * T Saved by caller (Temporaries) 55 * S Saved by callee (call-Safe registers) 56 */ 57 58 #define v0 $0 /* (T) return value */ 59 #define t0 $1 /* (T) temporary registers */ 60 #define t1 $2 61 #define t2 $3 62 #define t3 $4 63 #define t4 $5 64 #define t5 $6 65 #define t6 $7 66 #define t7 $8 67 68 #define s0 $9 /* (S) call-safe registers */ 69 #define s1 $10 70 #define s2 $11 71 #define s3 $12 72 #define s4 $13 73 #define s5 $14 74 #define s6 $15 75 #define a0 $16 /* (T) argument registers */ 76 #define a1 $17 77 #define a2 $18 78 #define a3 $19 79 #define a4 $20 80 #define a5 $21 81 #define t8 $22 /* (T) temporary registers */ 82 #define t9 $23 83 #define t10 $24 84 #define t11 $25 85 #define ra $26 /* (S) return address */ 86 #define t12 $27 /* (T) another temporary */ 87 #define at_reg $28 /* (T) assembler scratch */ 88 #define gp $29 /* (T) (local) data pointer */ 89 #define sp $30 /* (S) stack pointer */ 90 #define zero $31 /* wired zero */ 91 92 /* Floating point registers (XXXX VERIFY THIS) */ 93 #define fv0 $f0 /* (T) return value (real) */ 94 #define fv1 $f1 /* (T) return value (imaginary)*/ 95 #define ft0 fv1 96 #define fs0 $f2 /* (S) call-safe registers */ 97 #define fs1 $f3 98 #define fs2 $f4 99 #define fs3 $f5 100 #define fs4 $f6 101 #define fs5 $f7 102 #define fs6 $f8 103 #define fs7 $f9 104 #define ft1 $f10 /* (T) temporary registers */ 105 #define ft2 $f11 106 #define ft3 $f12 107 #define ft4 $f13 108 #define ft5 $f14 109 #define ft6 $f15 110 #define fa0 $f16 /* (T) argument registers */ 111 #define fa1 $f17 112 #define fa2 $f18 113 #define fa3 $f19 114 #define fa4 $f20 115 #define fa5 $f21 116 #define ft7 $f22 /* (T) more temporaries */ 117 #define ft8 $f23 118 #define ft9 $f24 119 #define ft10 $f25 120 #define ft11 $f26 121 #define ft12 $f27 122 #define ft13 $f28 123 #define ft14 $f29 124 #define ft15 $f30 125 #define fzero $f31 /* wired zero */ 126 127 128 /* Other DEC standard names */ 129 #define ai $25 /* (T) argument information */ 130 #define pv $27 /* (T) procedure value */ 131 132 133 /* 134 * Useful stuff. 135 */ 136 #ifdef __STDC__ 137 #define __CONCAT(a,b) a ## b 138 #else 139 #define __CONCAT(a,b) a/**/b 140 #endif 141 #define ___CONCAT(a,b) __CONCAT(a,b) 142 143 /* 144 * Macro to make a local label name. 145 */ 146 #define LLABEL(name,num) ___CONCAT(___CONCAT(L,name),num) 147 148 /* 149 * 150 * Debuggers need symbol table information to be able to properly 151 * decode a stack trace. The minimum that should be provided is: 152 * 153 * name: 154 * .proc name,numargs 155 * 156 * where "name" is the function's name; 157 * "numargs" how many arguments it expects. For varargs 158 * procedures this should be a negative number, 159 * indicating the minimum required number of 160 * arguments (which is at least 1); 161 * 162 * NESTED functions (functions that call other functions) should define 163 * how they handle their stack frame in a .frame directive: 164 * 165 * .frame framesize, pc_reg, i_mask, f_mask 166 * 167 * where "framesize" is the size of the frame for this function, in bytes. 168 * That is: 169 * new_sp + framesize == old_sp 170 * Framesizes should be rounded to a cacheline size. 171 * Note that old_sp plays the role of a conventional 172 * "frame pointer"; 173 * "pc_reg" is either a register which preserves the caller's PC 174 * or 'std', if std the saved PC should be stored at 175 * old_sp-8 176 * "i_mask" is a bitmask that indicates which of the integer 177 * registers are saved. See the M_xx defines at the 178 * end for the encoding of this 32bit value. 179 * "f_mask" is the same, for floating point registers. 180 * 181 * Note, 10/31/97: This is interesting but it isn't the way gcc outputs 182 * frame directives and it isn't the way the macros below output them 183 * either. Frame directives look like this: 184 * 185 * .frame $15,framesize,$26,0 186 * 187 * If no fp is set up then $30 should be used instead of $15. 188 * Also, gdb expects to find a <lda sp,-framesize(sp)> at the beginning 189 * of a procedure. Don't use things like sub sp,framesize,sp for this 190 * reason. End Note 10/31/97. ross@netbsd.org 191 * 192 * Note that registers should be saved starting at "old_sp-8", where the 193 * return address should be stored. Other registers follow at -16-24-32.. 194 * starting from register 0 (if saved) and up. Then float registers (ifany) 195 * are saved. 196 * 197 * If you need to alias a leaf function, or to provide multiple entry points 198 * use the LEAF() macro for the main entry point and XLEAF() for the other 199 * additional/alternate entry points. 200 * "XLEAF"s must be nested within a "LEAF" and a ".end". 201 * Similar rules for nested routines, e.g. use NESTED/XNESTED 202 * Symbols that should not be exported can be declared with the STATIC_xxx 203 * macros. 204 * 205 * All functions must be terminated by the END macro 206 * 207 * It is conceivable, although currently at the limits of compiler 208 * technology, that while performing inter-procedural optimizations 209 * the compiler/linker be able to avoid unnecessary register spills 210 * if told about the register usage of LEAF procedures (and by transitive 211 * closure of NESTED procedures as well). Assembly code can help 212 * this process using the .reguse directive: 213 * 214 * .reguse i_mask, f_mask 215 * 216 * where the register masks are built as above or-ing M_xx defines. 217 * 218 * 219 * All symbols are internal unless EXPORTed. Symbols that are IMPORTed 220 * must be appropriately described to the debugger. 221 * 222 */ 223 224 /* 225 * MCOUNT 226 */ 227 228 #ifndef GPROF 229 #define MCOUNT /* nothing */ 230 #else 231 #define MCOUNT \ 232 .set noat; \ 233 jsr at_reg,_mcount; \ 234 .set at 235 #endif 236 /* 237 * PALVECT, ESETUP, and ERSAVE 238 * Declare a palcode transfer point, and carefully construct 239 * gdb symbols with an unusual _negative_ register-save offset 240 * so that gdb can find the otherwise lost PC and then 241 * invert the vector for traceback. Also, fix up framesize, 242 * allowing for the palframe for the same reason. 243 */ 244 245 #define PALVECT(_name_) \ 246 ESETUP(_name_); \ 247 ERSAVE() 248 249 #define ESETUP(_name_) \ 250 /* .loc 1 __LINE__; */ \ 251 .globl _name_; \ 252 .ent _name_ 0; \ 253 _name_:; \ 254 .set noat; \ 255 lda sp,-(FRAME_SW_SIZE*8)(sp); \ 256 .frame $30,(FRAME_SW_SIZE+6)*8,$26,0; /* give gdb the real size */\ 257 .mask 0x4000000,-0x28; \ 258 .set at 259 260 #define ERSAVE() \ 261 .set noat; \ 262 stq at_reg,(FRAME_AT*8)(sp); \ 263 .set at; \ 264 stq ra,(FRAME_RA*8)(sp); \ 265 /* .loc 1 __LINE__; */ \ 266 bsr ra,exception_save_regs /* jmp/CALL trashes pv/t12 */ 267 268 269 /* 270 * LEAF 271 * Declare a global leaf function. 272 * A leaf function does not call other functions AND does not 273 * use any register that is callee-saved AND does not modify 274 * the stack pointer. 275 */ 276 #define LEAF(_name_,_n_args_) \ 277 .globl _name_; \ 278 .ent _name_ 0; \ 279 _name_:; \ 280 .frame sp,0,ra; \ 281 MCOUNT 282 /* should have been 283 .proc _name_,_n_args_; \ 284 .frame 0,ra,0,0 285 */ 286 287 #define LEAF_NOPROFILE(_name_,_n_args_) \ 288 .globl _name_; \ 289 .ent _name_ 0; \ 290 _name_:; \ 291 .frame sp,0,ra 292 /* should have been 293 .proc _name_,_n_args_; \ 294 .frame 0,ra,0,0 295 */ 296 297 /* 298 * STATIC_LEAF 299 * Declare a local leaf function. 300 */ 301 #define STATIC_LEAF(_name_,_n_args_) \ 302 .ent _name_ 0; \ 303 _name_:; \ 304 .frame sp,0,ra; \ 305 MCOUNT 306 /* should have been 307 .proc _name_,_n_args_; \ 308 .frame 0,ra,0,0 309 */ 310 /* 311 * XLEAF 312 * Global alias for a leaf function, or alternate entry point 313 */ 314 #define XLEAF(_name_,_n_args_) \ 315 .globl _name_; \ 316 .aent _name_ 0; \ 317 _name_: 318 /* should have been 319 .aproc _name_,_n_args_; 320 */ 321 322 /* 323 * STATIC_XLEAF 324 * Local alias for a leaf function, or alternate entry point 325 */ 326 #define STATIC_XLEAF(_name_,_n_args_) \ 327 .aent _name_ 0; \ 328 _name_: 329 /* should have been 330 .aproc _name_,_n_args_; 331 */ 332 333 /* 334 * NESTED 335 * Declare a (global) nested function 336 * A nested function calls other functions and needs 337 * therefore stack space to save/restore registers. 338 */ 339 #define NESTED(_name_, _n_args_, _framesize_, _pc_reg_, _i_mask_, _f_mask_ ) \ 340 .globl _name_; \ 341 .ent _name_ 0; \ 342 _name_:; \ 343 .frame sp,_framesize_,_pc_reg_; \ 344 .livereg _i_mask_,_f_mask_; \ 345 MCOUNT 346 /* should have been 347 .proc _name_,_n_args_; \ 348 .frame _framesize_, _pc_reg_, _i_mask_, _f_mask_ 349 */ 350 351 #define NESTED_NOPROFILE(_name_, _n_args_, _framesize_, _pc_reg_, _i_mask_, _f_mask_ ) \ 352 .globl _name_; \ 353 .ent _name_ 0; \ 354 _name_:; \ 355 .frame sp,_framesize_,_pc_reg_; \ 356 .livereg _i_mask_,_f_mask_ 357 /* should have been 358 .proc _name_,_n_args_; \ 359 .frame _framesize_, _pc_reg_, _i_mask_, _f_mask_ 360 */ 361 362 /* 363 * STATIC_NESTED 364 * Declare a local nested function. 365 */ 366 #define STATIC_NESTED(_name_, _n_args_, _framesize_, _pc_reg_, _i_mask_, _f_mask_ ) \ 367 .ent _name_ 0; \ 368 _name_:; \ 369 .frame sp,_framesize_,_pc_reg_; \ 370 .livereg _i_mask_,_f_mask_; \ 371 MCOUNT 372 /* should have been 373 .proc _name_,_n_args_; \ 374 .frame _framesize_, _pc_reg_, _i_mask_, _f_mask_ 375 */ 376 377 /* 378 * XNESTED 379 * Same as XLEAF, for a nested function. 380 */ 381 #define XNESTED(_name_,_n_args_) \ 382 .globl _name_; \ 383 .aent _name_ 0; \ 384 _name_: 385 /* should have been 386 .aproc _name_,_n_args_; 387 */ 388 389 390 /* 391 * STATIC_XNESTED 392 * Same as STATIC_XLEAF, for a nested function. 393 */ 394 #define STATIC_XNESTED(_name_,_n_args_) \ 395 .aent _name_ 0; \ 396 _name_: 397 /* should have been 398 .aproc _name_,_n_args_; 399 */ 400 401 402 /* 403 * END 404 * Function delimiter 405 */ 406 #define END(_name_) \ 407 .end _name_ 408 409 410 /* 411 * CALL 412 * Function invocation 413 */ 414 #define CALL(_name_) \ 415 /* .loc 1 __LINE__; */ \ 416 jsr ra,_name_; \ 417 ldgp gp,0(ra) 418 /* but this would cover longer jumps 419 br ra,.+4; \ 420 bsr ra,_name_ 421 */ 422 423 424 /* 425 * RET 426 * Return from function 427 */ 428 #define RET \ 429 ret zero,(ra),1 430 431 432 /* 433 * EXPORT 434 * Export a symbol 435 */ 436 #define EXPORT(_name_) \ 437 .globl _name_; \ 438 _name_: 439 440 441 /* 442 * IMPORT 443 * Make an external name visible, typecheck the size 444 */ 445 #define IMPORT(_name_, _size_) \ 446 .extern _name_,_size_ 447 448 449 /* 450 * ABS 451 * Define an absolute symbol 452 */ 453 #define ABS(_name_, _value_) \ 454 .globl _name_; \ 455 _name_ = _value_ 456 457 458 /* 459 * BSS 460 * Allocate un-initialized space for a global symbol 461 */ 462 #define BSS(_name_,_numbytes_) \ 463 .comm _name_,_numbytes_ 464 465 /* 466 * VECTOR 467 * Make an exception entry point look like a called function, 468 * to make it digestible to the debugger (KERNEL only) 469 */ 470 #define VECTOR(_name_, _i_mask_) \ 471 .globl _name_; \ 472 .ent _name_ 0; \ 473 _name_:; \ 474 .mask _i_mask_|IM_EXC,0; \ 475 .frame sp,MSS_SIZE,ra; 476 /* .livereg _i_mask_|IM_EXC,0 */ 477 /* should have been 478 .proc _name_,1; \ 479 .frame MSS_SIZE,$31,_i_mask_,0; \ 480 */ 481 482 /* 483 * MSG 484 * Allocate space for a message (a read-only ascii string) 485 */ 486 #define ASCIZ .asciz 487 #define MSG(msg,reg,label) \ 488 lda reg, label; \ 489 .data; \ 490 label: ASCIZ msg; \ 491 .text; 492 493 /* 494 * PRINTF 495 * Print a message 496 */ 497 #define PRINTF(msg,label) \ 498 MSG(msg,a0,label); \ 499 CALL(printf) 500 501 /* 502 * PANIC 503 * Fatal error (KERNEL) 504 */ 505 #define PANIC(msg,label) \ 506 MSG(msg,a0,label); \ 507 CALL(panic) 508 509 /* 510 * Register mask defines, used to define both save 511 * and use register sets. 512 * 513 * NOTE: The bit order should HAVE BEEN maintained when saving 514 * registers on the stack: sp goes at the highest 515 * address, gp lower on the stack, etc etc 516 * BUT NOONE CARES ABOUT DEBUGGERS AT MIPS 517 */ 518 519 #define IM_EXC 0x80000000 520 #define IM_SP 0x40000000 521 #define IM_GP 0x20000000 522 #define IM_AT 0x10000000 523 #define IM_T12 0x08000000 524 # define IM_PV IM_T4 525 #define IM_RA 0x04000000 526 #define IM_T11 0x02000000 527 # define IM_AI IM_T3 528 #define IM_T10 0x01000000 529 #define IM_T9 0x00800000 530 #define IM_T8 0x00400000 531 #define IM_A5 0x00200000 532 #define IM_A4 0x00100000 533 #define IM_A3 0x00080000 534 #define IM_A2 0x00040000 535 #define IM_A1 0x00020000 536 #define IM_A0 0x00010000 537 #define IM_S6 0x00008000 538 #define IM_S5 0x00004000 539 #define IM_S4 0x00002000 540 #define IM_S3 0x00001000 541 #define IM_S2 0x00000800 542 #define IM_S1 0x00000400 543 #define IM_S0 0x00000200 544 #define IM_T7 0x00000100 545 #define IM_T6 0x00000080 546 #define IM_T5 0x00000040 547 #define IM_T4 0x00000020 548 #define IM_T3 0x00000010 549 #define IM_T2 0x00000008 550 #define IM_T1 0x00000004 551 #define IM_T0 0x00000002 552 #define IM_V0 0x00000001 553 554 #define FM_T15 0x40000000 555 #define FM_T14 0x20000000 556 #define FM_T13 0x10000000 557 #define FM_T12 0x08000000 558 #define FM_T11 0x04000000 559 #define FM_T10 0x02000000 560 #define FM_T9 0x01000000 561 #define FM_T8 0x00800000 562 #define FM_T7 0x00400000 563 #define FM_A5 0x00200000 564 #define FM_A4 0x00100000 565 #define FM_A3 0x00080000 566 #define FM_A2 0x00040000 567 #define FM_A1 0x00020000 568 #define FM_A0 0x00010000 569 #define FM_T6 0x00008000 570 #define FM_T5 0x00004000 571 #define FM_T4 0x00002000 572 #define FM_T3 0x00001000 573 #define FM_T2 0x00000800 574 #define FM_T1 0x00000400 575 #define FM_S7 0x00000200 576 #define FM_S6 0x00000100 577 #define FM_S5 0x00000080 578 #define FM_S4 0x00000040 579 #define FM_S3 0x00000020 580 #define FM_S2 0x00000010 581 #define FM_S1 0x00000008 582 #define FM_S0 0x00000004 583 #define FM_T0 0x00000002 584 #define FM_V1 FM_T0 585 #define FM_V0 0x00000001 586 587 /* Pull in PAL "function" codes. */ 588 #include <machine/pal.h> 589 590 /* 591 * System call glue. 592 */ 593 #define SYSCALLNUM(name) \ 594 ___CONCAT(SYS_,name) 595 596 #define CALLSYS_NOERROR(name) \ 597 ldiq v0, SYSCALLNUM(name); \ 598 call_pal PAL_OSF1_callsys 599 600 #define LINUX_SYSCALLNUM(name) \ 601 ___CONCAT(LINUX_SYS_,name) 602 603 #define LINUX_CALLSYS_NOERROR(name) \ 604 ldiq v0, LINUX_SYSCALLNUM(name); \ 605 call_pal PAL_OSF1_callsys 606 607 /* 608 * Load the global pointer. 609 */ 610 #define LDGP(reg) \ 611 ldgp gp, 0(reg) 612 613 /* 614 * WEAK_ALIAS: create a weak alias. 615 */ 616 #define WEAK_ALIAS(alias,sym) \ 617 .weak alias; \ 618 alias = sym 619 620 /* 621 * WARN_REFERENCES: create a warning if the specified symbol is referenced. 622 */ 623 #ifdef __STDC__ 624 #define WARN_REFERENCES(_sym,_msg) \ 625 .section .gnu.warning. ## _sym ; .ascii _msg ; .text 626 #else 627 #define WARN_REFERENCES(_sym,_msg) \ 628 .section .gnu.warning./**/_sym ; .ascii _msg ; .text 629 #endif /* __STDC__ */ 630 631 /* 632 * Kernel RCS ID tag and copyright macros 633 */ 634 635 #ifdef _KERNEL 636 637 #define __KERNEL_SECTIONSTRING(_sec, _str) \ 638 .section _sec ; .asciz _str ; .text 639 640 #define __KERNEL_RCSID(_n, _s) __KERNEL_SECTIONSTRING(.ident, _s) 641 #define __KERNEL_COPYRIGHT(_n, _s) __KERNEL_SECTIONSTRING(.copyright, _s) 642 643 #ifdef NO_KERNEL_RCSIDS 644 #undef __KERNEL_RCSID 645 #define __KERNEL_RCSID(_n, _s) /* nothing */ 646 #endif 647 648 #endif /* _KERNEL */ 649