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