1 /*        $NetBSD: asm.h,v 1.77 2025/01/06 10:46:43 martin 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           .org _C_LABEL(x) + 0x80
324 
325 /*
326  * Macros to panic and printf from assembly language.
327  */
328 #define   PANIC(msg)                              \
329           PTR_LA    a0, 9f;                       \
330           jal       _C_LABEL(panic);    \
331           nop;                                    \
332           MSG(msg)
333 
334 #define   PRINTF(msg)                             \
335           PTR_LA    a0, 9f;                       \
336           jal       _C_LABEL(printf);   \
337           nop;                                    \
338           MSG(msg)
339 
340 #define   MSG(msg)                      \
341           .rdata;                                 \
342 9:        .asciz    msg;                          \
343           .text
344 
345 #define   ASMSTR(str)                             \
346           .asciz str;                             \
347           .align    3
348 
349 #ifdef _NETBSD_REVISIONID
350 #define   RCSID(x)  .pushsection ".ident","MS",@progbits,1;           \
351                               .asciz x;                                         \
352                               .ascii "$"; .ascii "NetBSD: "; .ascii __FILE__;   \
353                               .ascii " "; .ascii _NETBSD_REVISIONID;            \
354                               .asciz " $";                                                \
355                               .popsection
356 #else
357 #define   RCSID(x)  .pushsection ".ident","MS",@progbits,1;           \
358                               .asciz x;                                         \
359                               .popsection
360 #endif
361 
362 /*
363  * XXX retain dialects XXX
364  */
365 #define   ALEAF(x)                      XLEAF(x)
366 #define   NLEAF(x)                      LEAF_NOPROFILE(x)
367 #define   NON_LEAF(x, fsize, retpc)     NESTED(x, fsize, retpc)
368 #define   NNON_LEAF(x, fsize, retpc)    NESTED_NOPROFILE(x, fsize, retpc)
369 
370 #if defined(__mips_o32)
371 #define   SZREG     4
372 #else
373 #define   SZREG     8
374 #endif
375 
376 #if defined(__mips_o32) || defined(__mips_o64)
377 #define   ALSK      7                   /* stack alignment */
378 #define   ALMASK    -7                  /* stack alignment */
379 #define   SZFPREG   4
380 #define   FP_L      lwc1
381 #define   FP_S      swc1
382 #else
383 #define   ALSK      15                  /* stack alignment */
384 #define   ALMASK    -15                 /* stack alignment */
385 #define   SZFPREG   8
386 #define   FP_L      ldc1
387 #define   FP_S      sdc1
388 #endif
389 
390 /*
391  *  standard callframe {
392  *        register_t cf_args[4];                  arg0 - arg3 (only on o32 and o64)
393  *        register_t cf_pad[N];                   o32/64 (N=0), n32 (N=1) n64 (N=1)
394  *        register_t cf_gp;             global pointer (only on n32 and n64)
395  *        register_t cf_sp;             frame pointer
396  *        register_t cf_ra;             return address
397  *  };
398  */
399 #if defined(__mips_o32) || defined(__mips_o64)
400 #define   CALLFRAME_SIZ       (SZREG * (4 + 2))
401 #define   CALLFRAME_S0        0
402 #elif defined(__mips_n32) || defined(__mips_n64)
403 #define   CALLFRAME_SIZ       (SZREG * 4)
404 #define   CALLFRAME_S0        (CALLFRAME_SIZ - 4 * SZREG)
405 #endif
406 #ifndef _KERNEL
407 #define   CALLFRAME_GP        (CALLFRAME_SIZ - 3 * SZREG)
408 #endif
409 #define   CALLFRAME_SP        (CALLFRAME_SIZ - 2 * SZREG)
410 #define   CALLFRAME_RA        (CALLFRAME_SIZ - 1 * SZREG)
411 
412 /*
413  * While it would be nice to be compatible with the SGI
414  * REG_L and REG_S macros, because they do not take parameters, it
415  * is impossible to use them with the _MIPS_SIM_ABIX32 model.
416  *
417  * These macros hide the use of mips3 instructions from the
418  * assembler to prevent the assembler from generating 64-bit style
419  * ABI calls.
420  */
421 #ifdef __mips_o32
422 #define   PTR_ADD             add
423 #define   PTR_ADDI  addi
424 #define   PTR_ADDU  addu
425 #define   PTR_ADDIU addiu
426 #define   PTR_SUB             subu
427 #define   PTR_SUBI  subi
428 #define   PTR_SUBU  subu
429 #define   PTR_SUBIU subu
430 #define   PTR_L               lw
431 #define   PTR_LA              la
432 #define   PTR_S               sw
433 #define   PTR_SLL             sll
434 #define   PTR_SLLV  sllv
435 #define   PTR_SRL             srl
436 #define   PTR_SRLV  srlv
437 #define   PTR_SRA             sra
438 #define   PTR_SRAV  srav
439 #define   PTR_LL              ll
440 #define   PTR_SC              sc
441 #define   PTR_WORD  .word
442 #define   PTR_SCALESHIFT      2
443 #else /* _MIPS_SZPTR == 64 */
444 #define   PTR_ADD             dadd
445 #define   PTR_ADDI  daddi
446 #define   PTR_ADDU  daddu
447 #define   PTR_ADDIU daddiu
448 #define   PTR_SUB             dsubu
449 #define   PTR_SUBI  dsubi
450 #define   PTR_SUBU  dsubu
451 #define   PTR_SUBIU dsubu
452 #ifdef __mips_n32
453 #define   PTR_L               lw
454 #define   PTR_LL              ll
455 #define   PTR_SC              sc
456 #define   PTR_S               sw
457 #define   PTR_SCALESHIFT      2
458 #define   PTR_WORD  .word
459 #else
460 #define   PTR_L               ld
461 #define   PTR_LL              lld
462 #define   PTR_SC              scd
463 #define   PTR_S               sd
464 #define   PTR_SCALESHIFT      3
465 #define   PTR_WORD  .dword
466 #endif
467 #define   PTR_LA              dla
468 #define   PTR_SLL             dsll
469 #define   PTR_SLLV  dsllv
470 #define   PTR_SRL             dsrl
471 #define   PTR_SRLV  dsrlv
472 #define   PTR_SRA             dsra
473 #define   PTR_SRAV  dsrav
474 #endif /* _MIPS_SZPTR == 64 */
475 
476 #if _MIPS_SZINT == 32
477 #define   INT_ADD             add
478 #define   INT_ADDI  addi
479 #define   INT_ADDU  addu
480 #define   INT_ADDIU addiu
481 #define   INT_SUB             subu
482 #define   INT_SUBI  subi
483 #define   INT_SUBU  subu
484 #define   INT_SUBIU subu
485 #define   INT_L               lw
486 #define   INT_LA              la
487 #define   INT_S               sw
488 #define   INT_SLL             sll
489 #define   INT_SLLV  sllv
490 #define   INT_SRL             srl
491 #define   INT_SRLV  srlv
492 #define   INT_SRA             sra
493 #define   INT_SRAV  srav
494 #define   INT_LL              ll
495 #define   INT_SC              sc
496 #define   INT_WORD  .word
497 #define   INT_SCALESHIFT      2
498 #else
499 #define   INT_ADD             dadd
500 #define   INT_ADDI  daddi
501 #define   INT_ADDU  daddu
502 #define   INT_ADDIU daddiu
503 #define   INT_SUB             dsubu
504 #define   INT_SUBI  dsubi
505 #define   INT_SUBU  dsubu
506 #define   INT_SUBIU dsubu
507 #define   INT_L               ld
508 #define   INT_LA              dla
509 #define   INT_S               sd
510 #define   INT_SLL             dsll
511 #define   INT_SLLV  dsllv
512 #define   INT_SRL             dsrl
513 #define   INT_SRLV  dsrlv
514 #define   INT_SRA             dsra
515 #define   INT_SRAV  dsrav
516 #define   INT_LL              lld
517 #define   INT_SC              scd
518 #define   INT_WORD  .dword
519 #define   INT_SCALESHIFT      3
520 #endif
521 
522 #if _MIPS_SZLONG == 32
523 #define   LONG_ADD  add
524 #define   LONG_ADDI addi
525 #define   LONG_ADDU addu
526 #define   LONG_ADDIU          addiu
527 #define   LONG_SUB  subu
528 #define   LONG_SUBI subi
529 #define   LONG_SUBU subu
530 #define   LONG_SUBIU          subu
531 #define   LONG_L              lw
532 #define   LONG_LA             la
533 #define   LONG_S              sw
534 #define   LONG_SLL  sll
535 #define   LONG_SLLV sllv
536 #define   LONG_SRL  srl
537 #define   LONG_SRLV srlv
538 #define   LONG_SRA  sra
539 #define   LONG_SRAV srav
540 #define   LONG_LL             ll
541 #define   LONG_SC             sc
542 #define   LONG_WORD .word
543 #define   LONG_SCALESHIFT     2
544 #else
545 #define   LONG_ADD  dadd
546 #define   LONG_ADDI daddi
547 #define   LONG_ADDU daddu
548 #define   LONG_ADDIU          daddiu
549 #define   LONG_SUB  dsubu
550 #define   LONG_SUBI dsubi
551 #define   LONG_SUBU dsubu
552 #define   LONG_SUBIU          dsubu
553 #define   LONG_L              ld
554 #define   LONG_LA             dla
555 #define   LONG_S              sd
556 #define   LONG_SLL  dsll
557 #define   LONG_SLLV dsllv
558 #define   LONG_SRL  dsrl
559 #define   LONG_SRLV dsrlv
560 #define   LONG_SRA  dsra
561 #define   LONG_SRAV dsrav
562 #define   LONG_LL             lld
563 #define   LONG_SC             scd
564 #define   LONG_WORD .dword
565 #define   LONG_SCALESHIFT     3
566 #endif
567 
568 #if SZREG == 4
569 #define   REG_L               lw
570 #define   REG_S               sw
571 #define   REG_LI              li
572 #define   REG_ADDU  addu
573 #define   REG_SLL             sll
574 #define   REG_SLLV  sllv
575 #define   REG_SRL             srl
576 #define   REG_SRLV  srlv
577 #define   REG_SRA             sra
578 #define   REG_SRAV  srav
579 #define   REG_LL              ll
580 #define   REG_SC              sc
581 #define   REG_SCALESHIFT      2
582 #else
583 #define   REG_L               ld
584 #define   REG_S               sd
585 #define   REG_LI              dli
586 #define   REG_ADDU  daddu
587 #define   REG_SLL             dsll
588 #define   REG_SLLV  dsllv
589 #define   REG_SRL             dsrl
590 #define   REG_SRLV  dsrlv
591 #define   REG_SRA             dsra
592 #define   REG_SRAV  dsrav
593 #define   REG_LL              lld
594 #define   REG_SC              scd
595 #define   REG_SCALESHIFT      3
596 #endif
597 
598 #if (MIPS1 + MIPS2) > 0
599 #define   NOP_L               nop
600 #else
601 #define   NOP_L               /* nothing */
602 #endif
603 
604 /* compiler define */
605 #if defined(MULTIPROCESSOR) && defined(__OCTEON__)
606 /*
607  * See common/lib/libc/arch/mips/atomic/membar_ops.S for notes on
608  * Octeon memory ordering guarantees and barriers.
609  *
610  * cnMIPS also has a quirk where the store buffer can get clogged and
611  * we need to apply a plunger to it _after_ releasing a lock or else
612  * other CPUs may spin for hundreds of thousands of cycles before they
613  * see the lock is released.  So we also have the quirky SYNC_PLUNGER
614  * barrier as syncw.  See the note in the SYNCW instruction description
615  * on p. 2168 of Cavium OCTEON III CN78XX Hardware Reference Manual,
616  * CN78XX-HM-0.99E, September 2014:
617  *
618  *        Core A (writer)
619  *
620  *        SW R1, DATA#                  change shared DATA value
621  *        LI R1, 1
622  *        SYNCW# (or SYNCWS)  Perform DATA store before performing FLAG store
623  *        SW R2, FLAG#                  say that the shared DATA value is valid
624  *        SYNCW# (or SYNCWS)  Force the FLAG store soon (CN78XX-specific)
625  *
626  *        ...
627  *
628  *        The second SYNCW instruction executed by core A is not
629  *        necessary for correctness, but has very important performance
630  *        effects on the CN78XX.  Without it, the store to FLAG may
631  *        linger in core A's write buffer before it becomes visible to
632  *        any other cores.  (If core A is not performing many stores,
633  *        this may add hundreds of thousands of cycles to the flag
634  *        release time since the CN78XX core nominally retains stores to
635  *        attempt to merge them before sending the store on the CMI.)
636  *        Applications should include this second SYNCW instruction after
637  *        flag or lock release.
638  */
639 #define   LLSCSYNC  /* nothing */
640 #define   BDSYNC              sync
641 #define   BDSYNC_ACQ          nop
642 #define   SYNC_ACQ  /* nothing */
643 #define   SYNC_REL  sync 4
644 #define   BDSYNC_PLUNGER      sync 4
645 #define   SYNC_PLUNGER        sync 4
646 #elif defined(MULTIPROCESSOR) && (__mips >= 3 || !defined(__mips_o32))
647 #define   LLSCSYNC  /* nothing */
648 #define   BDSYNC              sync
649 #define   BDSYNC_ACQ          sync
650 #define   SYNC_ACQ  sync
651 #define   SYNC_REL  sync
652 #define   BDSYNC_PLUNGER      nop
653 #define   SYNC_PLUNGER        /* nothing */
654 #else
655 #define   LLSCSYNC  /* nothing */
656 #define   BDSYNC              nop
657 #define   BDSYNC_ACQ          nop
658 #define   SYNC_ACQ  /* nothing */
659 #define   SYNC_REL  /* nothing */
660 #define   BDSYNC_PLUNGER      nop
661 #define   SYNC_PLUNGER        /* nothing */
662 #endif
663 
664 /*
665  * Store-before-load barrier.  Do not use this unless you know what
666  * you're doing.
667  */
668 #ifdef MULTIPROCESSOR
669 #define   SYNC_DEKKER         sync
670 #else
671 #define   SYNC_DEKKER         /* nothing */
672 #endif
673 
674 /*
675  * Store-before-store and load-before-load barriers.  These could be
676  * made weaker than release (load/store-before-store) and acquire
677  * (load-before-load/store) barriers, and newer MIPS does have
678  * instruction encodings for finer-grained barriers like this, but I
679  * dunno how to appropriately conditionalize their use or get the
680  * assembler to be happy with them, so we'll use these definitions for
681  * now.
682  */
683 #define   SYNC_PRODUCER       SYNC_REL
684 #define   SYNC_CONSUMER       SYNC_ACQ
685 
686 /* CPU dependent hook for cp0 load delays */
687 #if defined(MIPS1) || defined(MIPS2) || defined(MIPS3)
688 #define   MFC0_HAZARD         sll $0,$0,1         /* super scalar nop */
689 #else
690 #define   MFC0_HAZARD         /* nothing */
691 #endif
692 
693 #if _MIPS_ISA == _MIPS_ISA_MIPS1 || _MIPS_ISA == _MIPS_ISA_MIPS2 || \
694     _MIPS_ISA == _MIPS_ISA_MIPS32
695 #define   MFC0                mfc0
696 #define   MTC0                mtc0
697 #endif
698 #if _MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4 || \
699     _MIPS_ISA == _MIPS_ISA_MIPS64
700 #define   MFC0                dmfc0
701 #define   MTC0                dmtc0
702 #endif
703 
704 #if defined(__mips_o32) || defined(__mips_o64)
705 
706 #ifdef __mips_abicalls
707 #define   CPRESTORE(r)        .cprestore r
708 #define   CPLOAD(r) .cpload r
709 #else
710 #define   CPRESTORE(r)        /* not needed */
711 #define   CPLOAD(r) /* not needed */
712 #endif
713 
714 #define   SETUP_GP  \
715                               .set push;                                        \
716                               .set noreorder;                                   \
717                               .cpload   t9;                                     \
718                               .set pop
719 #define   SETUP_GPX(r)        \
720                               .set push;                                        \
721                               .set noreorder;                                   \
722                               move      r,ra;     /* save old ra */   \
723                               bal       7f;                                     \
724                               nop;                                              \
725                     7:        .cpload   ra;                                     \
726                               move      ra,r;                                   \
727                               .set pop
728 #define   SETUP_GPX_L(r,lbl)  \
729                               .set push;                                        \
730                               .set noreorder;                                   \
731                               move      r,ra;     /* save old ra */   \
732                               bal       lbl;                                    \
733                               nop;                                              \
734                     lbl:      .cpload   ra;                                     \
735                               move      ra,r;                                   \
736                               .set pop
737 #define   SAVE_GP(x)          .cprestore x
738 
739 #define   SETUP_GP64(a,b)               /* n32/n64 specific */
740 #define   SETUP_GP64_R(a,b)   /* n32/n64 specific */
741 #define   SETUP_GPX64(a,b)    /* n32/n64 specific */
742 #define   SETUP_GPX64_L(a,b,c)          /* n32/n64 specific */
743 #define   RESTORE_GP64                  /* n32/n64 specific */
744 #define   USE_ALT_CP(a)                 /* n32/n64 specific */
745 #endif /* __mips_o32 || __mips_o64 */
746 
747 #if defined(__mips_o32) || defined(__mips_o64)
748 #define   REG_PROLOGUE        .set push
749 #define   REG_EPILOGUE        .set pop
750 #endif
751 #if defined(__mips_n32) || defined(__mips_n64)
752 #define   REG_PROLOGUE        .set push ; .set mips3
753 #define   REG_EPILOGUE        .set pop
754 #endif
755 
756 #if defined(__mips_n32) || defined(__mips_n64)
757 #define   SETUP_GP            /* o32 specific */
758 #define   SETUP_GPX(r)                  /* o32 specific */
759 #define   SETUP_GPX_L(r,lbl)  /* o32 specific */
760 #define   SAVE_GP(x)                    /* o32 specific */
761 #define   SETUP_GP64(a,b)               .cpsetup t9, a, b
762 #define   SETUP_GPX64(a,b)    \
763                                         .set push;                              \
764                                         move      b,ra;                         \
765                                         .set noreorder;                         \
766                                         bal       7f;                           \
767                                         nop;                                    \
768                               7:        .set pop;                     \
769                                         .cpsetup ra, a, 7b;           \
770                                         move      ra,b
771 #define   SETUP_GPX64_L(a,b,c)          \
772                                         .set push;                              \
773                                         move      b,ra;                         \
774                                         .set noreorder;                         \
775                                         bal       c;                            \
776                                         nop;                                    \
777                               c:        .set pop;                     \
778                                         .cpsetup ra, a, c;            \
779                                         move      ra,b
780 #define   RESTORE_GP64                  .cpreturn
781 #define   USE_ALT_CP(a)                 .cplocal a
782 #endif    /* __mips_n32 || __mips_n64 */
783 
784 /*
785  * The DYNAMIC_STATUS_MASK option adds an additional masking operation
786  * when updating the hardware interrupt mask in the status register.
787  *
788  * This is useful for platforms that need to at run-time mask
789  * interrupts based on motherboard configuration or to handle
790  * slowly clearing interrupts.
791  *
792  * XXX this is only currently implemented for mips3.
793  */
794 #ifdef MIPS_DYNAMIC_STATUS_MASK
795 #define   DYNAMIC_STATUS_MASK(sr,scratch)         \
796           lw        scratch, mips_dynamic_status_mask; \
797           and       sr, sr, scratch
798 
799 #define   DYNAMIC_STATUS_MASK_TOUSER(sr,scratch1)           \
800           ori       sr, (MIPS_INT_MASK | MIPS_SR_INT_IE);   \
801           DYNAMIC_STATUS_MASK(sr,scratch1)
802 #else
803 #define   DYNAMIC_STATUS_MASK(sr,scratch)
804 #define   DYNAMIC_STATUS_MASK_TOUSER(sr,scratch1)
805 #endif
806 
807 /* See lock_stubs.S. */
808 #define   LOG2_MIPS_LOCK_RAS_SIZE       8
809 #define   MIPS_LOCK_RAS_SIZE  256       /* 16 bytes left over */
810 
811 #define   CPUVAR(off) _C_LABEL(cpu_info_store)+__CONCAT(CPU_INFO_,off)
812 
813 #endif /* _MIPS_ASM_H */
814