]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/mips/include/asm.h
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / mips / include / asm.h
1 /*      $NetBSD: asm.h,v 1.29 2000/12/14 21:29:51 jeffs 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  * 4. 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  *      JNPR: asm.h,v 1.10 2007/08/09 11:23:32 katta
36  * $FreeBSD$
37  */
38
39 /*
40  * machAsmDefs.h --
41  *
42  *      Macros used when writing assembler programs.
43  *
44  *      Copyright (C) 1989 Digital Equipment Corporation.
45  *      Permission to use, copy, modify, and distribute this software and
46  *      its documentation for any purpose and without fee is hereby granted,
47  *      provided that the above copyright notice appears in all copies.
48  *      Digital Equipment Corporation makes no representations about the
49  *      suitability of this software for any purpose.  It is provided "as is"
50  *      without express or implied warranty.
51  *
52  * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsmDefs.h,
53  *      v 1.2 89/08/15 18:28:24 rab Exp  SPRITE (DECWRL)
54  */
55
56 #ifndef _MACHINE_ASM_H_
57 #define _MACHINE_ASM_H_
58
59 #ifndef NO_REG_DEFS
60 #include <machine/regdef.h>
61 #endif
62 #include <machine/endian.h>
63
64 #undef __FBSDID
65 #if !defined(lint) && !defined(STRIP_FBSDID)
66 #define __FBSDID(s)     .ident s
67 #else
68 #define __FBSDID(s)     /* nothing */
69 #endif
70
71 /*
72  * Define -pg profile entry code.
73  * Must always be noreorder, must never use a macro instruction
74  * Final addiu to t9 must always equal the size of this _KERN_MCOUNT
75  */
76 #define _KERN_MCOUNT                    \
77         .set    push;                   \
78         .set    noreorder;              \
79         .set    noat;                   \
80         subu    sp,sp,16;               \
81         sw      t9,12(sp);              \
82         move    AT,ra;                  \
83         lui     t9,%hi(_mcount);        \
84         addiu   t9,t9,%lo(_mcount);     \
85         jalr    t9;                     \
86         nop;                            \
87         lw      t9,4(sp);               \
88         addiu   sp,sp,8;                \
89         addiu   t9,t9,40;               \
90         .set    pop;
91
92 #ifdef GPROF
93 #define MCOUNT _KERN_MCOUNT
94 #else
95 #define MCOUNT
96 #endif
97
98 #define _C_LABEL(x)     x
99
100 /* 
101  *  Endian-independent assembly-code aliases for unaligned memory accesses.
102  */
103 #if BYTE_ORDER == LITTLE_ENDIAN
104 #define LWLO    lwl
105 #define LWHI    lwr
106 #define SWLO    swl
107 #define SWHI    swr
108 #endif
109
110 #if BYTE_ORDER == BIG_ENDIAN
111 #define LWLO    lwr
112 #define LWHI    lwl
113 #define SWLO    swr
114 #define SWHI    swl
115 #endif
116
117 #ifdef USE_AENT
118 #define AENT(x)         \
119         .aent   x, 0
120 #else
121 #define AENT(x)
122 #endif
123
124 /*
125  * WARN_REFERENCES: create a warning if the specified symbol is referenced
126  */
127 #define WARN_REFERENCES(_sym,_msg)                              \
128         .section .gnu.warning. ## _sym ; .ascii _msg ; .text
129
130 /*
131  * These are temp registers whose names can be used in either the old
132  * or new ABI, although they map to different physical registers.  In
133  * the old ABI, they map to t4-t7, and in the new ABI, they map to a4-a7.
134  *
135  * Because they overlap with the last 4 arg regs in the new ABI, ta0-ta3
136  * should be used only when we need more than t0-t3.
137  */
138 #if defined(__mips_n32) || defined(__mips_n64)
139 #define ta0     $8
140 #define ta1     $9
141 #define ta2     $10
142 #define ta3     $11
143 #else
144 #define ta0     $12
145 #define ta1     $13
146 #define ta2     $14
147 #define ta3     $15
148 #endif /* __mips_n32 || __mips_n64 */
149
150 #ifdef __ELF__
151 # define _C_LABEL(x)    x
152 #else
153 #  define _C_LABEL(x)   _ ## x
154 #endif
155
156 /*
157  * WEAK_ALIAS: create a weak alias.
158  */
159 #define WEAK_ALIAS(alias,sym)                                           \
160         .weak alias;                                                    \
161         alias = sym
162
163 /*
164  * STRONG_ALIAS: create a strong alias.
165  */
166 #define STRONG_ALIAS(alias,sym)                                         \
167         .globl alias;                                                   \
168         alias = sym
169
170 #define GLOBAL(sym)                                             \
171         .globl sym; sym:
172
173 #define ENTRY(sym)                                              \
174         .text; .globl sym; .ent sym; sym:
175
176 #define ASM_ENTRY(sym)                                          \
177         .text; .globl sym; .type sym,@function; sym:
178
179 /*
180  * LEAF
181  *      A leaf routine does
182  *      - call no other function,
183  *      - never use any register that callee-saved (S0-S8), and
184  *      - not use any local stack storage.
185  */
186 #define LEAF(x)                 \
187         .globl  _C_LABEL(x);    \
188         .ent    _C_LABEL(x), 0; \
189 _C_LABEL(x): ;                  \
190         .frame sp, 0, ra;       \
191         MCOUNT
192
193 /*
194  * LEAF_NOPROFILE
195  *      No profilable leaf routine.
196  */
197 #define LEAF_NOPROFILE(x)       \
198         .globl  _C_LABEL(x);    \
199         .ent    _C_LABEL(x), 0; \
200 _C_LABEL(x): ;                  \
201         .frame  sp, 0, ra
202
203 /*
204  * XLEAF
205  *      declare alternate entry to leaf routine
206  */
207 #define XLEAF(x)                \
208         .globl  _C_LABEL(x);    \
209         AENT (_C_LABEL(x));     \
210 _C_LABEL(x):
211
212 /*
213  * NESTED
214  *      A function calls other functions and needs
215  *      therefore stack space to save/restore registers.
216  */
217 #define NESTED(x, fsize, retpc)         \
218         .globl  _C_LABEL(x);            \
219         .ent    _C_LABEL(x), 0;         \
220 _C_LABEL(x): ;                          \
221         .frame  sp, fsize, retpc;       \
222         MCOUNT
223
224 /*
225  * NESTED_NOPROFILE(x)
226  *      No profilable nested routine.
227  */
228 #define NESTED_NOPROFILE(x, fsize, retpc)       \
229         .globl  _C_LABEL(x);                    \
230         .ent    _C_LABEL(x), 0;                 \
231 _C_LABEL(x): ;                                  \
232         .frame  sp, fsize, retpc
233
234 /*
235  * XNESTED
236  *      declare alternate entry point to nested routine.
237  */
238 #define XNESTED(x)              \
239         .globl  _C_LABEL(x);    \
240         AENT (_C_LABEL(x));     \
241 _C_LABEL(x):
242
243 /*
244  * END
245  *      Mark end of a procedure.
246  */
247 #define END(x)                  \
248         .end _C_LABEL(x)
249
250 /*
251  * IMPORT -- import external symbol
252  */
253 #define IMPORT(sym, size)       \
254         .extern _C_LABEL(sym),size
255
256 /*
257  * EXPORT -- export definition of symbol
258  */
259 #define EXPORT(x)               \
260         .globl  _C_LABEL(x);    \
261 _C_LABEL(x):
262
263 /*
264  * VECTOR
265  *      exception vector entrypoint
266  *      XXX: regmask should be used to generate .mask
267  */
268 #define VECTOR(x, regmask)      \
269         .ent    _C_LABEL(x),0;  \
270         EXPORT(x);              \
271
272 #define VECTOR_END(x)           \
273         EXPORT(x ## End);       \
274         END(x)
275
276 #define KSEG0TEXT_START
277 #define KSEG0TEXT_END
278 #define KSEG0TEXT       .text
279
280 /*
281  * Macros to panic and printf from assembly language.
282  */
283 #define PANIC(msg)                      \
284         la      a0, 9f;                 \
285         jal     _C_LABEL(panic);        \
286         nop;                            \
287         MSG(msg)
288
289 #define PANIC_KSEG0(msg, reg)   PANIC(msg)
290
291 #define PRINTF(msg)                     \
292         la      a0, 9f;                 \
293         jal     _C_LABEL(printf);       \
294         nop;                            \
295         MSG(msg)
296
297 #define MSG(msg)                        \
298         .rdata;                         \
299 9:      .asciiz msg;                    \
300         .text
301
302 #define ASMSTR(str)                     \
303         .asciiz str;                    \
304         .align  3
305
306 /*
307  * Call ast if required
308  */
309 #define DO_AST                                       \
310 44:                                                  \
311         la      s0, _C_LABEL(disableintr)           ;\
312         jalr    s0                                  ;\
313         nop                                         ;\
314         GET_CPU_PCPU(s1)                            ;\
315         lw      s3, PC_CURPCB(s1)                   ;\
316         lw      s1, PC_CURTHREAD(s1)                ;\
317         lw      s2, TD_FLAGS(s1)                    ;\
318         li      s0, TDF_ASTPENDING | TDF_NEEDRESCHED;\
319         and     s2, s0                              ;\
320         la      s0, _C_LABEL(enableintr)            ;\
321         jalr    s0                                  ;\
322         nop                                         ;\
323         beq     s2, zero, 4f                        ;\
324         nop                                         ;\
325         la      s0, _C_LABEL(ast)                   ;\
326         jalr    s0                                  ;\
327         addu    a0, s3, U_PCB_REGS                  ;\
328         j 44b                                       ;\
329         nop                                         ;\
330 4:
331
332
333 /*
334  * XXX retain dialects XXX
335  */
336 #define ALEAF(x)                        XLEAF(x)
337 #define NLEAF(x)                        LEAF_NOPROFILE(x)
338 #define NON_LEAF(x, fsize, retpc)       NESTED(x, fsize, retpc)
339 #define NNON_LEAF(x, fsize, retpc)      NESTED_NOPROFILE(x, fsize, retpc)
340
341 /*
342  *  standard callframe {
343  *      register_t cf_args[4];          arg0 - arg3
344  *      register_t cf_sp;               frame pointer
345  *      register_t cf_ra;               return address
346  *  };
347  */
348 #define CALLFRAME_SIZ   (4 * (4 + 2))
349 #define CALLFRAME_SP    (4 * 4)
350 #define CALLFRAME_RA    (4 * 5)
351 #define START_FRAME     CALLFRAME_SIZ
352
353 /*
354  * While it would be nice to be compatible with the SGI
355  * REG_L and REG_S macros, because they do not take parameters, it
356  * is impossible to use them with the _MIPS_SIM_ABIX32 model.
357  *
358  * These macros hide the use of mips3 instructions from the
359  * assembler to prevent the assembler from generating 64-bit style
360  * ABI calls.
361  */
362
363 #if !defined(_MIPS_BSD_API) || _MIPS_BSD_API == _MIPS_BSD_API_LP32
364 #define REG_L           lw
365 #define REG_S           sw
366 #define REG_LI          li
367 #define REG_PROLOGUE    .set push
368 #define REG_EPILOGUE    .set pop
369 #define SZREG           4
370 #else
371 #define REG_L           ld
372 #define REG_S           sd
373 #define REG_LI          dli
374 #define REG_PROLOGUE    .set push ; .set mips3
375 #define REG_EPILOGUE    .set pop
376 #define SZREG           8
377 #endif  /* _MIPS_BSD_API */
378
379 #define mfc0_macro(data, spr)                                           \
380         __asm __volatile ("mfc0 %0, $%1"                                \
381                         : "=r" (data)   /* outputs */                   \
382                         : "i" (spr));   /* inputs */
383
384 #define mtc0_macro(data, spr)                                           \
385         __asm __volatile ("mtc0 %0, $%1"                                \
386                         :                               /* outputs */   \
387                         : "r" (data), "i" (spr));       /* inputs */
388
389 #define cfc0_macro(data, spr)                                           \
390         __asm __volatile ("cfc0 %0, $%1"                                \
391                         : "=r" (data)   /* outputs */                   \
392                         : "i" (spr));   /* inputs */
393
394 #define ctc0_macro(data, spr)                                           \
395         __asm __volatile ("ctc0 %0, $%1"                                \
396                         :                               /* outputs */   \
397                         : "r" (data), "i" (spr));       /* inputs */
398
399
400 #define lbu_macro(data, addr)                                           \
401         __asm __volatile ("lbu %0, 0x0(%1)"                             \
402                         : "=r" (data)   /* outputs */                   \
403                         : "r" (addr));  /* inputs */
404
405 #define lb_macro(data, addr)                                            \
406         __asm __volatile ("lb %0, 0x0(%1)"                              \
407                         : "=r" (data)   /* outputs */                   \
408                         : "r" (addr));  /* inputs */
409
410 #define lwl_macro(data, addr)                                           \
411         __asm __volatile ("lwl %0, 0x0(%1)"                             \
412                         : "=r" (data)   /* outputs */                   \
413                         : "r" (addr));  /* inputs */
414
415 #define lwr_macro(data, addr)                                           \
416         __asm __volatile ("lwr %0, 0x0(%1)"                             \
417                         : "=r" (data)   /* outputs */                   \
418                         : "r" (addr));  /* inputs */
419
420 #define ldl_macro(data, addr)                                           \
421         __asm __volatile ("ldl %0, 0x0(%1)"                             \
422                         : "=r" (data)   /* outputs */                   \
423                         : "r" (addr));  /* inputs */
424
425 #define ldr_macro(data, addr)                                           \
426         __asm __volatile ("ldr %0, 0x0(%1)"                             \
427                         : "=r" (data)   /* outputs */                   \
428                         : "r" (addr));  /* inputs */
429
430 #define sb_macro(data, addr)                                            \
431         __asm __volatile ("sb %0, 0x0(%1)"                              \
432                         :                               /* outputs */   \
433                         : "r" (data), "r" (addr));      /* inputs */
434
435 #define swl_macro(data, addr)                                           \
436         __asm __volatile ("swl %0, 0x0(%1)"                             \
437                         :                               /* outputs */   \
438                         : "r" (data), "r" (addr));      /* inputs */
439
440 #define swr_macro(data, addr)                                           \
441         __asm __volatile ("swr %0, 0x0(%1)"                             \
442                         :                               /* outputs */   \
443                         : "r" (data), "r" (addr));      /* inputs */
444
445 #define sdl_macro(data, addr)                                           \
446         __asm __volatile ("sdl %0, 0x0(%1)"                             \
447                         :                               /* outputs */   \
448                         : "r" (data), "r" (addr));      /* inputs */
449
450 #define sdr_macro(data, addr)                                           \
451         __asm __volatile ("sdr %0, 0x0(%1)"                             \
452                         :                               /* outputs */   \
453                         : "r" (data), "r" (addr));      /* inputs */
454
455 #define mfgr_macro(data, gr)                                            \
456         __asm __volatile ("move %0, $%1"                                \
457                         : "=r" (data)   /* outputs */                   \
458                         : "i" (gr));    /* inputs */
459
460 #define dmfc0_macro(data, spr)                                          \
461         __asm __volatile ("dmfc0 %0, $%1"                               \
462                         : "=r" (data)   /* outputs */                   \
463                         : "i" (spr));   /* inputs */
464
465 #define dmtc0_macro(data, spr, sel)                                     \
466         __asm __volatile ("dmtc0        %0, $%1, %2"                    \
467                         :                       /* no  outputs */       \
468                         : "r" (data), "i" (spr), "i" (sel)); /* inputs */
469
470 /*
471  * The DYNAMIC_STATUS_MASK option adds an additional masking operation
472  * when updating the hardware interrupt mask in the status register.
473  *
474  * This is useful for platforms that need to at run-time mask
475  * interrupts based on motherboard configuration or to handle
476  * slowly clearing interrupts.
477  *
478  * XXX this is only currently implemented for mips3.
479  */
480 #ifdef MIPS_DYNAMIC_STATUS_MASK
481 #define DYNAMIC_STATUS_MASK(sr,scratch)                 \
482         lw      scratch, mips_dynamic_status_mask;      \
483         and     sr, sr, scratch
484
485 #define DYNAMIC_STATUS_MASK_TOUSER(sr,scratch1)         \
486         ori     sr, (MIPS_INT_MASK | MIPS_SR_INT_IE);   \
487         DYNAMIC_STATUS_MASK(sr,scratch1)
488 #else
489 #define DYNAMIC_STATUS_MASK(sr,scratch)
490 #define DYNAMIC_STATUS_MASK_TOUSER(sr,scratch1)
491 #endif
492
493 #ifdef SMP
494         /*
495          * FREEBSD_DEVELOPERS_FIXME
496          * In multiprocessor case, store/retrieve the pcpu structure
497          * address for current CPU in scratch register for fast access.
498          */
499 #error "Write GET_CPU_PCPU for SMP"
500 #else
501 #define GET_CPU_PCPU(reg)               \
502         lw      reg, _C_LABEL(pcpup);
503 #endif
504
505 /*
506  * Description of the setjmp buffer
507  *
508  * word  0      magic number    (dependant on creator)
509  *       1      RA
510  *       2      S0
511  *       3      S1
512  *       4      S2
513  *       5      S3
514  *       6      S4
515  *       7      S5
516  *       8      S6
517  *       9      S7
518  *       10     SP
519  *       11     S8
520  *       12     signal mask     (dependant on magic)
521  *       13     (con't)
522  *       14     (con't)
523  *       15     (con't)
524  *
525  * The magic number number identifies the jmp_buf and
526  * how the buffer was created as well as providing
527  * a sanity check
528  *
529  */
530
531 #define _JB_MAGIC__SETJMP       0xBADFACED
532 #define _JB_MAGIC_SETJMP        0xFACEDBAD
533
534 /* Valid for all jmp_buf's */
535
536 #define _JB_MAGIC               0
537 #define _JB_REG_RA              1
538 #define _JB_REG_S0              2
539 #define _JB_REG_S1              3
540 #define _JB_REG_S2              4
541 #define _JB_REG_S3              5
542 #define _JB_REG_S4              6
543 #define _JB_REG_S5              7
544 #define _JB_REG_S6              8
545 #define _JB_REG_S7              9
546 #define _JB_REG_SP              10
547 #define _JB_REG_S8              11
548
549 /* Only valid with the _JB_MAGIC_SETJMP magic */
550
551 #define _JB_SIGMASK             12
552
553 #endif /* !_MACHINE_ASM_H_ */