1 /* $NetBSD: asm.h,v 1.29 2000/12/14 21:29:51 jeffs Exp $ */ 2 3 /* 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 * Copyright (c) 1992, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Ralph Campbell. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)machAsmDefs.h 8.1 (Berkeley) 6/10/93 37 * JNPR: asm.h,v 1.10 2007/08/09 11:23:32 katta 38 * $FreeBSD$ 39 */ 40 41 /* 42 * machAsmDefs.h -- 43 * 44 * Macros used when writing assembler programs. 45 * 46 * Copyright (C) 1989 Digital Equipment Corporation. 47 * Permission to use, copy, modify, and distribute this software and 48 * its documentation for any purpose and without fee is hereby granted, 49 * provided that the above copyright notice appears in all copies. 50 * Digital Equipment Corporation makes no representations about the 51 * suitability of this software for any purpose. It is provided "as is" 52 * without express or implied warranty. 53 * 54 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsmDefs.h, 55 * v 1.2 89/08/15 18:28:24 rab Exp SPRITE (DECWRL) 56 */ 57 58 #ifndef _MACHINE_ASM_H_ 59 #define _MACHINE_ASM_H_ 60 61 #include <machine/abi.h> 62 #include <machine/regdef.h> 63 #include <machine/endian.h> 64 #include <machine/cdefs.h> 65 66 #undef __FBSDID 67 #if !defined(lint) && !defined(STRIP_FBSDID) 68 #define __FBSDID(s) .ident s 69 #else 70 #define __FBSDID(s) /* nothing */ 71 #endif 72 73 /* 74 * Define -pg profile entry code. 75 * Must always be noreorder, must never use a macro instruction 76 * Final addiu to t9 must always equal the size of this _KERN_MCOUNT 77 */ 78 #define _KERN_MCOUNT \ 79 .set push; \ 80 .set noreorder; \ 81 .set noat; \ 82 subu sp,sp,16; \ 83 sw t9,12(sp); \ 84 move AT,ra; \ 85 lui t9,%hi(_mcount); \ 86 addiu t9,t9,%lo(_mcount); \ 87 jalr t9; \ 88 nop; \ 89 lw t9,4(sp); \ 90 addiu sp,sp,8; \ 91 addiu t9,t9,40; \ 92 .set pop; 93 94 #ifdef GPROF 95 #define MCOUNT _KERN_MCOUNT 96 #else 97 #define MCOUNT 98 #endif 99 100 #define _C_LABEL(x) x 101 102 #ifdef USE_AENT 103 #define AENT(x) \ 104 .aent x, 0 105 #else 106 #define AENT(x) 107 #endif 108 109 /* 110 * WARN_REFERENCES: create a warning if the specified symbol is referenced 111 */ 112 #define WARN_REFERENCES(_sym,_msg) \ 113 .section .gnu.warning. ## _sym ; .ascii _msg ; .text 114 115 #ifdef __ELF__ 116 # define _C_LABEL(x) x 117 #else 118 # define _C_LABEL(x) _ ## x 119 #endif 120 121 /* 122 * WEAK_ALIAS: create a weak alias. 123 */ 124 #define WEAK_ALIAS(alias,sym) \ 125 .weak alias; \ 126 alias = sym 127 128 /* 129 * STRONG_ALIAS: create a strong alias. 130 */ 131 #define STRONG_ALIAS(alias,sym) \ 132 .globl alias; \ 133 alias = sym 134 135 #define GLOBAL(sym) \ 136 .globl sym; sym: 137 138 #define ENTRY(sym) \ 139 .text; .globl sym; .ent sym; sym: 140 141 #define ASM_ENTRY(sym) \ 142 .text; .globl sym; .type sym,@function; sym: 143 144 /* 145 * LEAF 146 * A leaf routine does 147 * - call no other function, 148 * - never use any register that callee-saved (S0-S8), and 149 * - not use any local stack storage. 150 */ 151 #define LEAF(x) \ 152 .globl _C_LABEL(x); \ 153 .ent _C_LABEL(x), 0; \ 154 _C_LABEL(x): ; \ 155 .frame sp, 0, ra; \ 156 MCOUNT 157 158 /* 159 * LEAF_NOPROFILE 160 * No profilable leaf routine. 161 */ 162 #define LEAF_NOPROFILE(x) \ 163 .globl _C_LABEL(x); \ 164 .ent _C_LABEL(x), 0; \ 165 _C_LABEL(x): ; \ 166 .frame sp, 0, ra 167 168 /* 169 * XLEAF 170 * declare alternate entry to leaf routine 171 */ 172 #define XLEAF(x) \ 173 .globl _C_LABEL(x); \ 174 AENT (_C_LABEL(x)); \ 175 _C_LABEL(x): 176 177 /* 178 * NESTED 179 * A function calls other functions and needs 180 * therefore stack space to save/restore registers. 181 */ 182 #define NESTED(x, fsize, retpc) \ 183 .globl _C_LABEL(x); \ 184 .ent _C_LABEL(x), 0; \ 185 _C_LABEL(x): ; \ 186 .frame sp, fsize, retpc; \ 187 MCOUNT 188 189 /* 190 * NESTED_NOPROFILE(x) 191 * No profilable nested routine. 192 */ 193 #define NESTED_NOPROFILE(x, fsize, retpc) \ 194 .globl _C_LABEL(x); \ 195 .ent _C_LABEL(x), 0; \ 196 _C_LABEL(x): ; \ 197 .frame sp, fsize, retpc 198 199 /* 200 * XNESTED 201 * declare alternate entry point to nested routine. 202 */ 203 #define XNESTED(x) \ 204 .globl _C_LABEL(x); \ 205 AENT (_C_LABEL(x)); \ 206 _C_LABEL(x): 207 208 /* 209 * END 210 * Mark end of a procedure. 211 */ 212 #define END(x) \ 213 .end _C_LABEL(x) 214 215 /* 216 * IMPORT -- import external symbol 217 */ 218 #define IMPORT(sym, size) \ 219 .extern _C_LABEL(sym),size 220 221 /* 222 * EXPORT -- export definition of symbol 223 */ 224 #define EXPORT(x) \ 225 .globl _C_LABEL(x); \ 226 _C_LABEL(x): 227 228 /* 229 * VECTOR 230 * exception vector entrypoint 231 * XXX: regmask should be used to generate .mask 232 */ 233 #define VECTOR(x, regmask) \ 234 .ent _C_LABEL(x),0; \ 235 EXPORT(x); \ 236 237 #define VECTOR_END(x) \ 238 EXPORT(x ## End); \ 239 END(x) 240 241 /* 242 * Macros to panic and printf from assembly language. 243 */ 244 #define PANIC(msg) \ 245 PTR_LA a0, 9f; \ 246 jal _C_LABEL(panic); \ 247 nop; \ 248 MSG(msg) 249 250 #define PANIC_KSEG0(msg, reg) PANIC(msg) 251 252 #define PRINTF(msg) \ 253 PTR_LA a0, 9f; \ 254 jal _C_LABEL(printf); \ 255 nop; \ 256 MSG(msg) 257 258 #define MSG(msg) \ 259 .rdata; \ 260 9: .asciiz msg; \ 261 .text 262 263 #define ASMSTR(str) \ 264 .asciiz str; \ 265 .align 3 266 267 #if defined(__mips_o32) || defined(__mips_o64) 268 #define ALSK 7 /* stack alignment */ 269 #define ALMASK -7 /* stack alignment */ 270 #define SZFPREG 4 271 #define FP_L lwc1 272 #define FP_S swc1 273 #else 274 #define ALSK 15 /* stack alignment */ 275 #define ALMASK -15 /* stack alignment */ 276 #define SZFPREG 8 277 #define FP_L ldc1 278 #define FP_S sdc1 279 #endif 280 281 /* 282 * Endian-independent assembly-code aliases for unaligned memory accesses. 283 */ 284 #if _BYTE_ORDER == _LITTLE_ENDIAN 285 # define LWHI lwr 286 # define LWLO lwl 287 # define SWHI swr 288 # define SWLO swl 289 # if SZREG == 4 290 # define REG_LHI lwr 291 # define REG_LLO lwl 292 # define REG_SHI swr 293 # define REG_SLO swl 294 # else 295 # define REG_LHI ldr 296 # define REG_LLO ldl 297 # define REG_SHI sdr 298 # define REG_SLO sdl 299 # endif 300 #endif 301 302 #if _BYTE_ORDER == _BIG_ENDIAN 303 # define LWHI lwl 304 # define LWLO lwr 305 # define SWHI swl 306 # define SWLO swr 307 # if SZREG == 4 308 # define REG_LHI lwl 309 # define REG_LLO lwr 310 # define REG_SHI swl 311 # define REG_SLO swr 312 # else 313 # define REG_LHI ldl 314 # define REG_LLO ldr 315 # define REG_SHI sdl 316 # define REG_SLO sdr 317 # endif 318 #endif 319 320 /* 321 * While it would be nice to be compatible with the SGI 322 * REG_L and REG_S macros, because they do not take parameters, it 323 * is impossible to use them with the _MIPS_SIM_ABIX32 model. 324 * 325 * These macros hide the use of mips3 instructions from the 326 * assembler to prevent the assembler from generating 64-bit style 327 * ABI calls. 328 */ 329 #if _MIPS_SZPTR == 32 330 #define PTR_ADD add 331 #define PTR_ADDI addi 332 #define PTR_ADDU addu 333 #define PTR_ADDIU addiu 334 #define PTR_SUB add 335 #define PTR_SUBI subi 336 #define PTR_SUBU subu 337 #define PTR_SUBIU subu 338 #define PTR_L lw 339 #define PTR_LA la 340 #define PTR_LI li 341 #define PTR_S sw 342 #define PTR_SLL sll 343 #define PTR_SLLV sllv 344 #define PTR_SRL srl 345 #define PTR_SRLV srlv 346 #define PTR_SRA sra 347 #define PTR_SRAV srav 348 #define PTR_LL ll 349 #define PTR_SC sc 350 #define PTR_WORD .word 351 #define PTR_SCALESHIFT 2 352 #else /* _MIPS_SZPTR == 64 */ 353 #define PTR_ADD dadd 354 #define PTR_ADDI daddi 355 #define PTR_ADDU daddu 356 #define PTR_ADDIU daddiu 357 #define PTR_SUB dadd 358 #define PTR_SUBI dsubi 359 #define PTR_SUBU dsubu 360 #define PTR_SUBIU dsubu 361 #define PTR_L ld 362 #define PTR_LA dla 363 #define PTR_LI dli 364 #define PTR_S sd 365 #define PTR_SLL dsll 366 #define PTR_SLLV dsllv 367 #define PTR_SRL dsrl 368 #define PTR_SRLV dsrlv 369 #define PTR_SRA dsra 370 #define PTR_SRAV dsrav 371 #define PTR_LL lld 372 #define PTR_SC scd 373 #define PTR_WORD .dword 374 #define PTR_SCALESHIFT 3 375 #endif /* _MIPS_SZPTR == 64 */ 376 377 #if _MIPS_SZINT == 32 378 #define INT_ADD add 379 #define INT_ADDI addi 380 #define INT_ADDU addu 381 #define INT_ADDIU addiu 382 #define INT_SUB add 383 #define INT_SUBI subi 384 #define INT_SUBU subu 385 #define INT_SUBIU subu 386 #define INT_L lw 387 #define INT_LA la 388 #define INT_S sw 389 #define INT_SLL sll 390 #define INT_SLLV sllv 391 #define INT_SRL srl 392 #define INT_SRLV srlv 393 #define INT_SRA sra 394 #define INT_SRAV srav 395 #define INT_LL ll 396 #define INT_SC sc 397 #define INT_WORD .word 398 #define INT_SCALESHIFT 2 399 #else 400 #define INT_ADD dadd 401 #define INT_ADDI daddi 402 #define INT_ADDU daddu 403 #define INT_ADDIU daddiu 404 #define INT_SUB dadd 405 #define INT_SUBI dsubi 406 #define INT_SUBU dsubu 407 #define INT_SUBIU dsubu 408 #define INT_L ld 409 #define INT_LA dla 410 #define INT_S sd 411 #define INT_SLL dsll 412 #define INT_SLLV dsllv 413 #define INT_SRL dsrl 414 #define INT_SRLV dsrlv 415 #define INT_SRA dsra 416 #define INT_SRAV dsrav 417 #define INT_LL lld 418 #define INT_SC scd 419 #define INT_WORD .dword 420 #define INT_SCALESHIFT 3 421 #endif 422 423 #if _MIPS_SZLONG == 32 424 #define LONG_ADD add 425 #define LONG_ADDI addi 426 #define LONG_ADDU addu 427 #define LONG_ADDIU addiu 428 #define LONG_SUB add 429 #define LONG_SUBI subi 430 #define LONG_SUBU subu 431 #define LONG_SUBIU subu 432 #define LONG_L lw 433 #define LONG_LA la 434 #define LONG_S sw 435 #define LONG_SLL sll 436 #define LONG_SLLV sllv 437 #define LONG_SRL srl 438 #define LONG_SRLV srlv 439 #define LONG_SRA sra 440 #define LONG_SRAV srav 441 #define LONG_LL ll 442 #define LONG_SC sc 443 #define LONG_WORD .word 444 #define LONG_SCALESHIFT 2 445 #else 446 #define LONG_ADD dadd 447 #define LONG_ADDI daddi 448 #define LONG_ADDU daddu 449 #define LONG_ADDIU daddiu 450 #define LONG_SUB dadd 451 #define LONG_SUBI dsubi 452 #define LONG_SUBU dsubu 453 #define LONG_SUBIU dsubu 454 #define LONG_L ld 455 #define LONG_LA dla 456 #define LONG_S sd 457 #define LONG_SLL dsll 458 #define LONG_SLLV dsllv 459 #define LONG_SRL dsrl 460 #define LONG_SRLV dsrlv 461 #define LONG_SRA dsra 462 #define LONG_SRAV dsrav 463 #define LONG_LL lld 464 #define LONG_SC scd 465 #define LONG_WORD .dword 466 #define LONG_SCALESHIFT 3 467 #endif 468 469 #if SZREG == 4 470 #define REG_L lw 471 #define REG_S sw 472 #define REG_LI li 473 #define REG_ADDU addu 474 #define REG_SLL sll 475 #define REG_SLLV sllv 476 #define REG_SRL srl 477 #define REG_SRLV srlv 478 #define REG_SRA sra 479 #define REG_SRAV srav 480 #define REG_LL ll 481 #define REG_SC sc 482 #define REG_SCALESHIFT 2 483 #else 484 #define REG_L ld 485 #define REG_S sd 486 #define REG_LI dli 487 #define REG_ADDU daddu 488 #define REG_SLL dsll 489 #define REG_SLLV dsllv 490 #define REG_SRL dsrl 491 #define REG_SRLV dsrlv 492 #define REG_SRA dsra 493 #define REG_SRAV dsrav 494 #define REG_LL lld 495 #define REG_SC scd 496 #define REG_SCALESHIFT 3 497 #endif 498 499 #if _MIPS_ISA == _MIPS_ISA_MIPS1 || _MIPS_ISA == _MIPS_ISA_MIPS2 || \ 500 _MIPS_ISA == _MIPS_ISA_MIPS32 501 #define MFC0 mfc0 502 #define MTC0 mtc0 503 #endif 504 #if _MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4 || \ 505 _MIPS_ISA == _MIPS_ISA_MIPS64 506 #define MFC0 dmfc0 507 #define MTC0 dmtc0 508 #endif 509 510 #if defined(__mips_o32) || defined(__mips_o64) 511 512 #ifdef __ABICALLS__ 513 #define CPRESTORE(r) .cprestore r 514 #define CPLOAD(r) .cpload r 515 #else 516 #define CPRESTORE(r) /* not needed */ 517 #define CPLOAD(r) /* not needed */ 518 #endif 519 520 #define SETUP_GP \ 521 .set push; \ 522 .set noreorder; \ 523 .cpload t9; \ 524 .set pop 525 #define SETUP_GPX(r) \ 526 .set push; \ 527 .set noreorder; \ 528 move r,ra; /* save old ra */ \ 529 bal 7f; \ 530 nop; \ 531 7: .cpload ra; \ 532 move ra,r; \ 533 .set pop 534 #define SETUP_GPX_L(r,lbl) \ 535 .set push; \ 536 .set noreorder; \ 537 move r,ra; /* save old ra */ \ 538 bal lbl; \ 539 nop; \ 540 lbl: .cpload ra; \ 541 move ra,r; \ 542 .set pop 543 #define SAVE_GP(x) .cprestore x 544 545 #define SETUP_GP64(a,b) /* n32/n64 specific */ 546 #define SETUP_GP64_R(a,b) /* n32/n64 specific */ 547 #define SETUP_GPX64(a,b) /* n32/n64 specific */ 548 #define SETUP_GPX64_L(a,b,c) /* n32/n64 specific */ 549 #define RESTORE_GP64 /* n32/n64 specific */ 550 #define USE_ALT_CP(a) /* n32/n64 specific */ 551 #endif /* __mips_o32 || __mips_o64 */ 552 553 #if defined(__mips_o32) || defined(__mips_o64) 554 #define REG_PROLOGUE .set push 555 #define REG_EPILOGUE .set pop 556 #endif 557 #if defined(__mips_n32) || defined(__mips_n64) 558 #define REG_PROLOGUE .set push ; .set mips3 559 #define REG_EPILOGUE .set pop 560 #endif 561 562 #if defined(__mips_n32) || defined(__mips_n64) 563 #define SETUP_GP /* o32 specific */ 564 #define SETUP_GPX(r) /* o32 specific */ 565 #define SETUP_GPX_L(r,lbl) /* o32 specific */ 566 #define SAVE_GP(x) /* o32 specific */ 567 #define SETUP_GP64(a,b) .cpsetup $25, a, b 568 #define SETUP_GPX64(a,b) \ 569 .set push; \ 570 move b,ra; \ 571 .set noreorder; \ 572 bal 7f; \ 573 nop; \ 574 7: .set pop; \ 575 .cpsetup ra, a, 7b; \ 576 move ra,b 577 #define SETUP_GPX64_L(a,b,c) \ 578 .set push; \ 579 move b,ra; \ 580 .set noreorder; \ 581 bal c; \ 582 nop; \ 583 c: .set pop; \ 584 .cpsetup ra, a, c; \ 585 move ra,b 586 #define RESTORE_GP64 .cpreturn 587 #define USE_ALT_CP(a) .cplocal a 588 #endif /* __mips_n32 || __mips_n64 */ 589 590 #define GET_CPU_PCPU(reg) \ 591 PTR_L reg, _C_LABEL(pcpup); 592 593 /* 594 * Description of the setjmp buffer 595 * 596 * word 0 magic number (dependant on creator) 597 * 1 RA 598 * 2 S0 599 * 3 S1 600 * 4 S2 601 * 5 S3 602 * 6 S4 603 * 7 S5 604 * 8 S6 605 * 9 S7 606 * 10 SP 607 * 11 S8 608 * 12 GP (dependent on ABI) 609 * 13 signal mask (dependant on magic) 610 * 14 (con't) 611 * 15 (con't) 612 * 16 (con't) 613 * 614 * The magic number number identifies the jmp_buf and 615 * how the buffer was created as well as providing 616 * a sanity check 617 * 618 */ 619 620 #define _JB_MAGIC__SETJMP 0xBADFACED 621 #define _JB_MAGIC_SETJMP 0xFACEDBAD 622 623 /* Valid for all jmp_buf's */ 624 625 #define _JB_MAGIC 0 626 #define _JB_REG_RA 1 627 #define _JB_REG_S0 2 628 #define _JB_REG_S1 3 629 #define _JB_REG_S2 4 630 #define _JB_REG_S3 5 631 #define _JB_REG_S4 6 632 #define _JB_REG_S5 7 633 #define _JB_REG_S6 8 634 #define _JB_REG_S7 9 635 #define _JB_REG_SP 10 636 #define _JB_REG_S8 11 637 #if defined(__mips_n32) || defined(__mips_n64) 638 #define _JB_REG_GP 12 639 #endif 640 641 /* Only valid with the _JB_MAGIC_SETJMP magic */ 642 643 #define _JB_SIGMASK 13 644 #define __JB_SIGMASK_REMAINDER 14 /* sigmask_t is 128-bits */ 645 646 #define _JB_FPREG_F20 15 647 #define _JB_FPREG_F21 16 648 #define _JB_FPREG_F22 17 649 #define _JB_FPREG_F23 18 650 #define _JB_FPREG_F24 19 651 #define _JB_FPREG_F25 20 652 #define _JB_FPREG_F26 21 653 #define _JB_FPREG_F27 22 654 #define _JB_FPREG_F28 23 655 #define _JB_FPREG_F29 24 656 #define _JB_FPREG_F30 25 657 #define _JB_FPREG_F31 26 658 #define _JB_FPREG_FCSR 27 659 660 /* 661 * Various macros for dealing with TLB hazards 662 * (a) why so many? 663 * (b) when to use? 664 * (c) why not used everywhere? 665 */ 666 /* 667 * Assume that w alaways need nops to escape CP0 hazard 668 * TODO: Make hazard delays configurable. Stuck with 5 cycles on the moment 669 * For more info on CP0 hazards see Chapter 7 (p.99) of "MIPS32 Architecture 670 * For Programmers Volume III: The MIPS32 Privileged Resource Architecture" 671 */ 672 #if defined(CPU_NLM) 673 #define HAZARD_DELAY sll $0,3 674 #define ITLBNOPFIX sll $0,3 675 #elif defined(CPU_RMI) 676 #define HAZARD_DELAY 677 #define ITLBNOPFIX 678 #elif defined(CPU_MIPS74K) 679 #define HAZARD_DELAY sll $0,$0,3 680 #define ITLBNOPFIX sll $0,$0,3 681 #else 682 #define ITLBNOPFIX nop;nop;nop;nop;nop;nop;nop;nop;nop;sll $0,$0,3; 683 #define HAZARD_DELAY nop;nop;nop;nop;sll $0,$0,3; 684 #endif 685 686 #endif /* !_MACHINE_ASM_H_ */ 687