1 /* $NetBSD: asm.h,v 1.80 2026/09/17 16:34:33 riastradh Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Ralph Campbell. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)machAsmDefs.h 8.1 (Berkeley) 6/10/93 35 */ 36 37 /* 38 * machAsmDefs.h -- 39 * 40 * Macros used when writing assembler programs. 41 * 42 * Copyright (C) 1989 Digital Equipment Corporation. 43 * Permission to use, copy, modify, and distribute this software and 44 * its documentation for any purpose and without fee is hereby granted, 45 * provided that the above copyright notice appears in all copies. 46 * Digital Equipment Corporation makes no representations about the 47 * suitability of this software for any purpose. It is provided "as is" 48 * without express or implied warranty. 49 * 50 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsmDefs.h, 51 * v 1.2 89/08/15 18:28:24 rab Exp SPRITE (DECWRL) 52 */ 53 54 #ifndef _MIPS_ASM_H 55 #define _MIPS_ASM_H 56 57 #include <sys/cdefs.h> /* for API selection */ 58 #include <mips/regdef.h> 59 60 #if defined(_KERNEL_OPT) 61 #include "opt_gprof.h" 62 #include "opt_multiprocessor.h" 63 #endif 64 65 #ifdef __ASSEMBLER__ 66 #define __BIT(n) (1 << (n)) 67 #define __BITS(hi,lo) ((~((~0)<<((hi)+1)))&((~0)<<(lo))) 68 69 #define __LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask)) 70 #define __SHIFTOUT(__x, __mask) (((__x) & (__mask)) / __LOWEST_SET_BIT(__mask)) 71 #define __SHIFTIN(__x, __mask) ((__x) * __LOWEST_SET_BIT(__mask)) 72 #endif /* __ASSEMBLER__ */ 73 74 #ifndef GPROF 75 #define _MIPS_ASM_MCOUNT(x) 76 #else 77 /* 78 * Define -pg profile entry code. 79 * Must always be noreorder, must never use a macro instruction. 80 */ 81 #if defined(__mips_o32) /* Old 32-bit ABI */ 82 /* 83 * The old ABI version must also decrement two less words off the 84 * stack and the final addiu to t9 must always equal the size of this 85 * _MIPS_ASM_MCOUNT. 86 */ 87 #define _MIPS_ASM_MCOUNT(x) \ 88 .set push; \ 89 .set noreorder; \ 90 .set noat; \ 91 subu sp,16; \ 92 sw t9,12(sp); \ 93 move AT,ra; \ 94 lui t9,%hi(_mcount); \ 95 addiu t9,t9,%lo(_mcount); \ 96 jalr t9; \ 97 nop; \ 98 lw t9,4(sp); \ 99 addiu sp,8; \ 100 addiu t9,40; \ 101 .set pop; 102 #elif defined(__mips_o64) /* Old 64-bit ABI */ 103 # error yeahnah 104 #else /* New (n32/n64) ABI */ 105 /* 106 * The new ABI version just needs to put the return address in AT and 107 * call _mcount(). For the no abicalls case, skip the reloc dance. 108 */ 109 #ifdef __mips_abicalls 110 #if defined(__mips_n32) /* n32 */ 111 #define _MIPS_ASM_MCOUNT(x) \ 112 .set push; \ 113 .set noreorder; \ 114 .set noat; \ 115 subu sp,16; \ 116 sw t9,8(sp); \ 117 move AT,ra; \ 118 lui t9,%hi(_mcount); \ 119 addiu t9,t9,%lo(_mcount); \ 120 jalr t9; \ 121 nop; \ 122 lw t9,8(sp); \ 123 addiu sp,16; \ 124 .set pop; 125 #else /* n64 */ 126 #define _MIPS_ASM_MCOUNT(x) \ 127 .set push; \ 128 .set noreorder; \ 129 .set noat; \ 130 dsubu sp,16; \ 131 sd gp,0(sp); \ 132 sd t9,8(sp); \ 133 move AT,ra; \ 134 lui gp,%hi(%neg(%gp_rel(x))); \ 135 daddiu gp,%lo(%neg(%gp_rel(x))); \ 136 daddu gp,gp,t9; \ 137 ld t9,%call16(_mcount)(gp); \ 138 jalr t9; \ 139 nop; \ 140 ld gp,0(sp); \ 141 ld t9,8(sp); \ 142 daddiu sp,16; \ 143 .set pop; 144 #endif 145 #else /* !__mips_abicalls */ 146 #define _MIPS_ASM_MCOUNT(x) \ 147 .set push; \ 148 .set noreorder; \ 149 .set noat; \ 150 move AT,ra; \ 151 jal _mcount; \ 152 nop; \ 153 .set pop; 154 #endif /* !__mips_abicalls */ 155 #endif /* n32/n64 */ 156 #endif /* GPROF */ 157 158 #ifdef USE_AENT 159 #define AENT(x) \ 160 .aent x, 0 161 #else 162 #define AENT(x) 163 #endif 164 165 /* 166 * WEAK_ALIAS: create a weak alias. 167 */ 168 #define WEAK_ALIAS(alias,sym) \ 169 .weak alias; \ 170 alias = sym 171 /* 172 * STRONG_ALIAS: create a strong alias. 173 */ 174 #define STRONG_ALIAS(alias,sym) \ 175 .globl alias; \ 176 alias = sym 177 178 /* 179 * WARN_REFERENCES: create a warning if the specified symbol is referenced. 180 */ 181 #define WARN_REFERENCES(sym,msg) \ 182 .pushsection __CONCAT(.gnu.warning.,sym); \ 183 .ascii msg; \ 184 .popsection 185 186 /* 187 * STATIC_LEAF_NOPROFILE 188 * No profilable local leaf routine. 189 */ 190 #define STATIC_LEAF_NOPROFILE(x) \ 191 .ent _C_LABEL(x); \ 192 _C_LABEL(x): ; \ 193 .frame sp, 0, ra 194 195 /* 196 * LEAF_NOPROFILE 197 * No profilable leaf routine. 198 */ 199 #define LEAF_NOPROFILE(x) \ 200 .globl _C_LABEL(x); \ 201 STATIC_LEAF_NOPROFILE(x) 202 203 /* 204 * STATIC_LEAF 205 * Declare a local leaf function. 206 */ 207 #define STATIC_LEAF(x) \ 208 STATIC_LEAF_NOPROFILE(x); \ 209 _MIPS_ASM_MCOUNT(x) 210 211 /* 212 * LEAF 213 * A leaf routine does 214 * - call no other function, 215 * - never use any register that callee-saved (S0-S8), and 216 * - not use any local stack storage. 217 */ 218 #define LEAF(x) \ 219 LEAF_NOPROFILE(x); \ 220 _MIPS_ASM_MCOUNT(x) 221 222 /* 223 * STATIC_XLEAF 224 * declare alternate entry to a static leaf routine 225 */ 226 #define STATIC_XLEAF(x) \ 227 AENT (_C_LABEL(x)); \ 228 _C_LABEL(x): 229 230 /* 231 * XLEAF 232 * declare alternate entry to leaf routine 233 */ 234 #define XLEAF(x) \ 235 .globl _C_LABEL(x); \ 236 STATIC_XLEAF(x) 237 238 /* 239 * STATIC_NESTED_NOPROFILE 240 * No profilable local nested routine. 241 */ 242 #define STATIC_NESTED_NOPROFILE(x, fsize, retpc) \ 243 .ent _C_LABEL(x); \ 244 .type _C_LABEL(x), @function; \ 245 _C_LABEL(x): ; \ 246 .frame sp, fsize, retpc 247 248 /* 249 * NESTED_NOPROFILE 250 * No profilable nested routine. 251 */ 252 #define NESTED_NOPROFILE(x, fsize, retpc) \ 253 .globl _C_LABEL(x); \ 254 STATIC_NESTED_NOPROFILE(x, fsize, retpc) 255 256 /* 257 * NESTED 258 * A function calls other functions and needs 259 * therefore stack space to save/restore registers. 260 */ 261 #define NESTED(x, fsize, retpc) \ 262 NESTED_NOPROFILE(x, fsize, retpc); \ 263 _MIPS_ASM_MCOUNT(x) 264 265 /* 266 * STATIC_NESTED 267 * No profilable local nested routine. 268 */ 269 #define STATIC_NESTED(x, fsize, retpc) \ 270 STATIC_NESTED_NOPROFILE(x, fsize, retpc); \ 271 _MIPS_ASM_MCOUNT(x) 272 273 /* 274 * XNESTED 275 * declare alternate entry point to nested routine. 276 */ 277 #define XNESTED(x) \ 278 .globl _C_LABEL(x); \ 279 AENT (_C_LABEL(x)); \ 280 _C_LABEL(x): 281 282 /* 283 * END 284 * Mark end of a procedure. 285 */ 286 #define END(x) \ 287 .end _C_LABEL(x); \ 288 .size _C_LABEL(x), . - _C_LABEL(x) 289 290 /* 291 * IMPORT -- import external symbol 292 */ 293 #define IMPORT(sym, size) \ 294 .extern _C_LABEL(sym),size 295 296 /* 297 * EXPORT -- export definition of symbol 298 */ 299 #define EXPORT(x) \ 300 .globl _C_LABEL(x); \ 301 _C_LABEL(x): 302 303 /* 304 * EXPORT_OBJECT -- export definition of symbol of symbol 305 * type Object, visible to ksyms(4) address search. 306 */ 307 #define EXPORT_OBJECT(x) \ 308 EXPORT(x); \ 309 .type _C_LABEL(x), @object; 310 311 /* 312 * VECTOR 313 * exception vector entrypoint 314 * XXX: regmask should be used to generate .mask 315 */ 316 #define VECTOR(x, regmask) \ 317 .ent _C_LABEL(x); \ 318 EXPORT(x); \ 319 320 #define VECTOR_END(x) \ 321 EXPORT(__CONCAT(x,_end)); \ 322 END(x); \ 323 .space 0x80 - (. - _C_LABEL(x)); \ 324 .org _C_LABEL(x) + 0x80 325 326 /* 327 * Macros to panic and printf from assembly language. 328 */ 329 #define PANIC(msg) \ 330 PTR_LA a0, 9f; \ 331 jal _C_LABEL(panic); \ 332 nop; \ 333 MSG(msg) 334 335 #define PRINTF(msg) \ 336 PTR_LA a0, 9f; \ 337 jal _C_LABEL(printf); \ 338 nop; \ 339 MSG(msg) 340 341 #define MSG(msg) \ 342 .rdata; \ 343 9: .asciz msg; \ 344 .text 345 346 #define ASMSTR(str) \ 347 .asciz str; \ 348 .align 3 349 350 #ifdef _NETBSD_REVISIONID 351 #define RCSID(x) .pushsection ".ident","MS",@progbits,1; \ 352 .asciz x; \ 353 .ascii "$"; .ascii "NetBSD: "; .ascii __FILE__; \ 354 .ascii " "; .ascii _NETBSD_REVISIONID; \ 355 .asciz " $"; \ 356 .popsection 357 #else 358 #define RCSID(x) .pushsection ".ident","MS",@progbits,1; \ 359 .asciz x; \ 360 .popsection 361 #endif 362 363 /* 364 * XXX retain dialects XXX 365 */ 366 #define ALEAF(x) XLEAF(x) 367 #define NLEAF(x) LEAF_NOPROFILE(x) 368 #define NON_LEAF(x, fsize, retpc) NESTED(x, fsize, retpc) 369 #define NNON_LEAF(x, fsize, retpc) NESTED_NOPROFILE(x, fsize, retpc) 370 371 #if defined(__mips_o32) 372 #define SZREG 4 373 #else 374 #define SZREG 8 375 #endif 376 377 #if defined(__mips_o32) || defined(__mips_o64) 378 #define ALSK 7 /* stack alignment */ 379 #define ALMASK -7 /* stack alignment */ 380 #define SZFPREG 4 381 #define FP_L lwc1 382 #define FP_S swc1 383 #else 384 #define ALSK 15 /* stack alignment */ 385 #define ALMASK -15 /* stack alignment */ 386 #define SZFPREG 8 387 #define FP_L ldc1 388 #define FP_S sdc1 389 #endif 390 391 /* 392 * standard callframe { 393 * register_t cf_args[4]; arg0 - arg3 (only on o32 and o64) 394 * register_t cf_pad[N]; o32/64 (N=0), n32 (N=1) n64 (N=1) 395 * register_t cf_gp; global pointer (only on n32 and n64) 396 * register_t cf_sp; frame pointer 397 * register_t cf_ra; return address 398 * }; 399 */ 400 #if defined(__mips_o32) || defined(__mips_o64) 401 #define CALLFRAME_SIZ (SZREG * (4 + 2)) 402 #define CALLFRAME_S0 0 403 #elif defined(__mips_n32) || defined(__mips_n64) 404 #define CALLFRAME_SIZ (SZREG * 4) 405 #define CALLFRAME_S0 (CALLFRAME_SIZ - 4 * SZREG) 406 #endif 407 #ifndef _KERNEL 408 #define CALLFRAME_GP (CALLFRAME_SIZ - 3 * SZREG) 409 #endif 410 #define CALLFRAME_SP (CALLFRAME_SIZ - 2 * SZREG) 411 #define CALLFRAME_RA (CALLFRAME_SIZ - 1 * SZREG) 412 413 /* 414 * While it would be nice to be compatible with the SGI 415 * REG_L and REG_S macros, because they do not take parameters, it 416 * is impossible to use them with the _MIPS_SIM_ABIX32 model. 417 * 418 * These macros hide the use of mips3 instructions from the 419 * assembler to prevent the assembler from generating 64-bit style 420 * ABI calls. 421 */ 422 #ifdef __mips_o32 423 #define PTR_ADD add 424 #define PTR_ADDI addi 425 #define PTR_ADDU addu 426 #define PTR_ADDIU addiu 427 #define PTR_SUB subu 428 #define PTR_SUBI subi 429 #define PTR_SUBU subu 430 #define PTR_SUBIU subu 431 #define PTR_L lw 432 #define PTR_LA la 433 #define PTR_S sw 434 #define PTR_SLL sll 435 #define PTR_SLLV sllv 436 #define PTR_SRL srl 437 #define PTR_SRLV srlv 438 #define PTR_SRA sra 439 #define PTR_SRAV srav 440 #define PTR_LL ll 441 #define PTR_SC sc 442 #define PTR_WORD .word 443 #define PTR_SCALESHIFT 2 444 #else /* _MIPS_SZPTR == 64 */ 445 #define PTR_ADD dadd 446 #define PTR_ADDI daddi 447 #define PTR_ADDU daddu 448 #define PTR_ADDIU daddiu 449 #define PTR_SUB dsubu 450 #define PTR_SUBI dsubi 451 #define PTR_SUBU dsubu 452 #define PTR_SUBIU dsubu 453 #ifdef __mips_n32 454 #define PTR_L lw 455 #define PTR_LL ll 456 #define PTR_SC sc 457 #define PTR_S sw 458 #define PTR_SCALESHIFT 2 459 #define PTR_WORD .word 460 #else 461 #define PTR_L ld 462 #define PTR_LL lld 463 #define PTR_SC scd 464 #define PTR_S sd 465 #define PTR_SCALESHIFT 3 466 #define PTR_WORD .dword 467 #endif 468 #define PTR_LA dla 469 #define PTR_SLL dsll 470 #define PTR_SLLV dsllv 471 #define PTR_SRL dsrl 472 #define PTR_SRLV dsrlv 473 #define PTR_SRA dsra 474 #define PTR_SRAV dsrav 475 #endif /* _MIPS_SZPTR == 64 */ 476 477 #if _MIPS_SZINT == 32 478 #define INT_ADD add 479 #define INT_ADDI addi 480 #define INT_ADDU addu 481 #define INT_ADDIU addiu 482 #define INT_SUB subu 483 #define INT_SUBI subi 484 #define INT_SUBU subu 485 #define INT_SUBIU subu 486 #define INT_L lw 487 #define INT_LA la 488 #define INT_S sw 489 #define INT_SLL sll 490 #define INT_SLLV sllv 491 #define INT_SRL srl 492 #define INT_SRLV srlv 493 #define INT_SRA sra 494 #define INT_SRAV srav 495 #define INT_LL ll 496 #define INT_SC sc 497 #define INT_WORD .word 498 #define INT_SCALESHIFT 2 499 #else 500 #define INT_ADD dadd 501 #define INT_ADDI daddi 502 #define INT_ADDU daddu 503 #define INT_ADDIU daddiu 504 #define INT_SUB dsubu 505 #define INT_SUBI dsubi 506 #define INT_SUBU dsubu 507 #define INT_SUBIU dsubu 508 #define INT_L ld 509 #define INT_LA dla 510 #define INT_S sd 511 #define INT_SLL dsll 512 #define INT_SLLV dsllv 513 #define INT_SRL dsrl 514 #define INT_SRLV dsrlv 515 #define INT_SRA dsra 516 #define INT_SRAV dsrav 517 #define INT_LL lld 518 #define INT_SC scd 519 #define INT_WORD .dword 520 #define INT_SCALESHIFT 3 521 #endif 522 523 #if _MIPS_SZLONG == 32 524 #define LONG_ADD add 525 #define LONG_ADDI addi 526 #define LONG_ADDU addu 527 #define LONG_ADDIU addiu 528 #define LONG_SUB subu 529 #define LONG_SUBI subi 530 #define LONG_SUBU subu 531 #define LONG_SUBIU subu 532 #define LONG_L lw 533 #define LONG_LA la 534 #define LONG_S sw 535 #define LONG_SLL sll 536 #define LONG_SLLV sllv 537 #define LONG_SRL srl 538 #define LONG_SRLV srlv 539 #define LONG_SRA sra 540 #define LONG_SRAV srav 541 #define LONG_LL ll 542 #define LONG_SC sc 543 #define LONG_WORD .word 544 #define LONG_SCALESHIFT 2 545 #else 546 #define LONG_ADD dadd 547 #define LONG_ADDI daddi 548 #define LONG_ADDU daddu 549 #define LONG_ADDIU daddiu 550 #define LONG_SUB dsubu 551 #define LONG_SUBI dsubi 552 #define LONG_SUBU dsubu 553 #define LONG_SUBIU dsubu 554 #define LONG_L ld 555 #define LONG_LA dla 556 #define LONG_S sd 557 #define LONG_SLL dsll 558 #define LONG_SLLV dsllv 559 #define LONG_SRL dsrl 560 #define LONG_SRLV dsrlv 561 #define LONG_SRA dsra 562 #define LONG_SRAV dsrav 563 #define LONG_LL lld 564 #define LONG_SC scd 565 #define LONG_WORD .dword 566 #define LONG_SCALESHIFT 3 567 #endif 568 569 #if SZREG == 4 570 #define REG_L lw 571 #define REG_S sw 572 #define REG_LI li 573 #define REG_ADDU addu 574 #define REG_SLL sll 575 #define REG_SLLV sllv 576 #define REG_SRL srl 577 #define REG_SRLV srlv 578 #define REG_SRA sra 579 #define REG_SRAV srav 580 #define REG_LL ll 581 #define REG_SC sc 582 #define REG_SCALESHIFT 2 583 #else 584 #define REG_L ld 585 #define REG_S sd 586 #define REG_LI dli 587 #define REG_ADDU daddu 588 #define REG_SLL dsll 589 #define REG_SLLV dsllv 590 #define REG_SRL dsrl 591 #define REG_SRLV dsrlv 592 #define REG_SRA dsra 593 #define REG_SRAV dsrav 594 #define REG_LL lld 595 #define REG_SC scd 596 #define REG_SCALESHIFT 3 597 #endif 598 599 #if (MIPS1 + MIPS2) > 0 600 #define NOP_L nop 601 #else 602 #define NOP_L /* nothing */ 603 #endif 604 605 /* compiler define */ 606 #if defined(MULTIPROCESSOR) && defined(__OCTEON__) 607 /* 608 * See common/lib/libc/arch/mips/atomic/membar_ops.S for notes on 609 * Octeon memory ordering guarantees and barriers. 610 * 611 * cnMIPS also has a quirk where the store buffer can get clogged and 612 * we need to apply a plunger to it _after_ releasing a lock or else 613 * other CPUs may spin for hundreds of thousands of cycles before they 614 * see the lock is released. So we also have the quirky SYNC_PLUNGER 615 * barrier as syncw. See the note in the SYNCW instruction description 616 * on p. 2168 of Cavium OCTEON III CN78XX Hardware Reference Manual, 617 * CN78XX-HM-0.99E, September 2014: 618 * 619 * Core A (writer) 620 * 621 * SW R1, DATA # change shared DATA value 622 * LI R2, 1 623 * SYNCW # (or SYNCWS) Perform DATA store before performing FLAG store 624 * SW R2, FLAG # say that the shared DATA value is valid 625 * SYNCW # (or SYNCWS) Force the FLAG store soon (CN78XX-specific) 626 * 627 * ... 628 * 629 * The second SYNCW instruction executed by core A is not 630 * necessary for correctness, but has very important performance 631 * effects on the CN78XX. Without it, the store to FLAG may 632 * linger in core A's write buffer before it becomes visible to 633 * any other cores. (If core A is not performing many stores, 634 * this may add hundreds of thousands of cycles to the flag 635 * release time since the CN78XX core nominally retains stores to 636 * attempt to merge them before sending the store on the CMI.) 637 * Applications should include this second SYNCW instruction after 638 * flag or lock release. 639 * 640 * (This is not actually CN78XX-specific; it applies to other cnMIPS 641 * models too like CN50XX, whose manual calls it `OCTEON-specific' 642 * rather than `CN78XX-specific'.) 643 */ 644 #define LLSCSYNC /* nothing */ 645 #define BDSYNC sync 646 #define BDSYNC_ACQ nop 647 #define SYNC_ACQ /* nothing */ 648 #define SYNC_REL sync 4 649 #define BDSYNC_PLUNGER sync 4 650 #define SYNC_PLUNGER sync 4 651 #elif defined(MULTIPROCESSOR) && (__mips >= 3 || !defined(__mips_o32)) 652 #define LLSCSYNC /* nothing */ 653 #define BDSYNC sync 654 #define BDSYNC_ACQ sync 655 #define SYNC_ACQ sync 656 #define SYNC_REL sync 657 #define BDSYNC_PLUNGER nop 658 #define SYNC_PLUNGER /* nothing */ 659 #else 660 #define LLSCSYNC /* nothing */ 661 #define BDSYNC nop 662 #define BDSYNC_ACQ nop 663 #define SYNC_ACQ /* nothing */ 664 #define SYNC_REL /* nothing */ 665 #define BDSYNC_PLUNGER nop 666 #define SYNC_PLUNGER /* nothing */ 667 #endif 668 669 /* 670 * Store-before-load barrier. Do not use this unless you know what 671 * you're doing. 672 */ 673 #ifdef MULTIPROCESSOR 674 #define SYNC_DEKKER sync 675 #else 676 #define SYNC_DEKKER /* nothing */ 677 #endif 678 679 /* 680 * Store-before-store and load-before-load barriers. These could be 681 * made weaker than release (load/store-before-store) and acquire 682 * (load-before-load/store) barriers, and newer MIPS does have 683 * instruction encodings for finer-grained barriers like this, but I 684 * dunno how to appropriately conditionalize their use or get the 685 * assembler to be happy with them, so we'll use these definitions for 686 * now. 687 */ 688 #define SYNC_PRODUCER SYNC_REL 689 #define SYNC_CONSUMER SYNC_ACQ 690 691 /* 692 * CPU dependent hook for CP0 load delays -- must be issued between 693 * mfc0/dmfc0 and the use of the result register. 694 * 695 * Required for, e.g., R3000-class CPUs which don't make the result 696 * available until a cycle late. For example: 697 * 698 * > If one instruction delivers a result used by a subsequent 699 * > instruction, and either instruction is listed in Table 13.1, 700 * > Instructions with scheduling implications, the sum of the 701 * > late-result count of the first instruction and the 702 * > early-operand count of the second gives the number of nop or 703 * > other intervening (non-dependent) instructions required to 704 * > prevent a hazard or interlock. 705 * > [...] 706 * > Instruction Early Operand Late Result Hazard? 707 * > [...] 708 * > Integer/control 1 3 709 * > register moves: 710 * > mfc0, mtc0 711 * 712 * Integrated Device Technology, Inc., IDT R30xx Family Software 713 * Reference Manual, Revision 1.0, Ch. 13 `Instruction Timing and 714 * Optimization', pp. 13-1--13-2. 715 * https://student.cs.uwaterloo.ca/~cs350/common/r3000-manual.pdf#page=188 716 * 717 * > It should be noted that this sequence for fetching the 718 * > co-processor zero registers is required because there is a 719 * > one clock delay in the register value actually being loaded 720 * > into the general registers after the execution of the mfc0 721 * > instruction. 722 * 723 * Integrated Device Technology, Inc., IDT79R3041, Integrated 724 * RISController for Low-Cost Systems, Hardware User's Manual, 725 * Revision 1.12, July 1, 1995, Ch. 6 `Exception Handling', 726 * Sec. `Preserving Context', p. 6-15. 727 * https://stuff.mit.edu/afs/sipb/contrib/doc/specs/ic/cpu/mips/r3041.pdf#page=79 728 * 729 * In GNU binutils/gas without .set noreorder, a nop is issued 730 * automatically for any mfcN/dmfcN instruction or similar 731 * (INSN_LOAD_COPROC, or LC for short in opcodes/mips-opc.c). 732 * 733 * We issue the super-scalar SSNOP (sll $0,$0,1) rather than NOP 734 * because `some mips3 are superscalar and need this to do the right 735 * thing' [citation needed]. 736 */ 737 #if defined(MIPS1) || defined(MIPS2) || defined(MIPS3) 738 #define MFC0_HAZARD sll $0,$0,1 /* super scalar nop */ 739 #else 740 #define MFC0_HAZARD /* nothing */ 741 #endif 742 743 #if _MIPS_ISA == _MIPS_ISA_MIPS1 || _MIPS_ISA == _MIPS_ISA_MIPS2 || \ 744 _MIPS_ISA == _MIPS_ISA_MIPS32 745 #define MFC0 mfc0 746 #define MTC0 mtc0 747 #endif 748 #if _MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4 || \ 749 _MIPS_ISA == _MIPS_ISA_MIPS64 750 #define MFC0 dmfc0 751 #define MTC0 dmtc0 752 #endif 753 754 #if defined(__mips_o32) || defined(__mips_o64) 755 756 #ifdef __mips_abicalls 757 #define CPRESTORE(r) .cprestore r 758 #define CPLOAD(r) .cpload r 759 #else 760 #define CPRESTORE(r) /* not needed */ 761 #define CPLOAD(r) /* not needed */ 762 #endif 763 764 #define SETUP_GP \ 765 .set push; \ 766 .set noreorder; \ 767 .cpload t9; \ 768 .set pop 769 #define SETUP_GPX(r) \ 770 .set push; \ 771 .set noreorder; \ 772 move r,ra; /* save old ra */ \ 773 bal 7f; \ 774 nop; \ 775 7: .cpload ra; \ 776 move ra,r; \ 777 .set pop 778 #define SETUP_GPX_L(r,lbl) \ 779 .set push; \ 780 .set noreorder; \ 781 move r,ra; /* save old ra */ \ 782 bal lbl; \ 783 nop; \ 784 lbl: .cpload ra; \ 785 move ra,r; \ 786 .set pop 787 #define SAVE_GP(x) .cprestore x 788 789 #define SETUP_GP64(a,b) /* n32/n64 specific */ 790 #define SETUP_GP64_R(a,b) /* n32/n64 specific */ 791 #define SETUP_GPX64(a,b) /* n32/n64 specific */ 792 #define SETUP_GPX64_L(a,b,c) /* n32/n64 specific */ 793 #define RESTORE_GP64 /* n32/n64 specific */ 794 #define USE_ALT_CP(a) /* n32/n64 specific */ 795 #endif /* __mips_o32 || __mips_o64 */ 796 797 #if defined(__mips_o32) || defined(__mips_o64) 798 #define REG_PROLOGUE .set push 799 #define REG_EPILOGUE .set pop 800 #endif 801 #if defined(__mips_n32) || defined(__mips_n64) 802 #define REG_PROLOGUE .set push ; .set mips3 803 #define REG_EPILOGUE .set pop 804 #endif 805 806 #if defined(__mips_n32) || defined(__mips_n64) 807 #define SETUP_GP /* o32 specific */ 808 #define SETUP_GPX(r) /* o32 specific */ 809 #define SETUP_GPX_L(r,lbl) /* o32 specific */ 810 #define SAVE_GP(x) /* o32 specific */ 811 #define SETUP_GP64(a,b) .cpsetup t9, a, b 812 #define SETUP_GPX64(a,b) \ 813 .set push; \ 814 move b,ra; \ 815 .set noreorder; \ 816 bal 7f; \ 817 nop; \ 818 7: .set pop; \ 819 .cpsetup ra, a, 7b; \ 820 move ra,b 821 #define SETUP_GPX64_L(a,b,c) \ 822 .set push; \ 823 move b,ra; \ 824 .set noreorder; \ 825 bal c; \ 826 nop; \ 827 c: .set pop; \ 828 .cpsetup ra, a, c; \ 829 move ra,b 830 #define RESTORE_GP64 .cpreturn 831 #define USE_ALT_CP(a) .cplocal a 832 #endif /* __mips_n32 || __mips_n64 */ 833 834 /* 835 * The DYNAMIC_STATUS_MASK option adds an additional masking operation 836 * when updating the hardware interrupt mask in the status register. 837 * 838 * This is useful for platforms that need to at run-time mask 839 * interrupts based on motherboard configuration or to handle 840 * slowly clearing interrupts. 841 * 842 * XXX this is only currently implemented for mips3. 843 */ 844 #ifdef MIPS_DYNAMIC_STATUS_MASK 845 #define DYNAMIC_STATUS_MASK(sr,scratch) \ 846 lw scratch, mips_dynamic_status_mask; \ 847 and sr, sr, scratch 848 849 #define DYNAMIC_STATUS_MASK_TOUSER(sr,scratch1) \ 850 ori sr, (MIPS_INT_MASK | MIPS_SR_INT_IE); \ 851 DYNAMIC_STATUS_MASK(sr,scratch1) 852 #else 853 #define DYNAMIC_STATUS_MASK(sr,scratch) 854 #define DYNAMIC_STATUS_MASK_TOUSER(sr,scratch1) 855 #endif 856 857 /* See lock_stubs.S. */ 858 #define LOG2_MIPS_LOCK_RAS_SIZE 8 859 #define MIPS_LOCK_RAS_SIZE 256 /* 16 bytes left over */ 860 861 #define CPUVAR(off) _C_LABEL(cpu_info_store)+__CONCAT(CPU_INFO_,off) 862 863 #endif /* _MIPS_ASM_H */ 864