2 /* From: NetBSD: asm.h,v 1.18 1997/11/03 04:22:06 ross Exp */
5 * Copyright (c) 1991,1990,1989,1994,1995,1996 Carnegie Mellon University
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.
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.
18 * Carnegie Mellon requests users of this software to return to
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
25 * any improvements or extensions that they make and grant Carnegie Mellon
26 * the rights to redistribute these changes.
30 * Assembly coding style
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.
39 * "ALPHA Calling Standard", DEC 27-Apr-90
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.
47 * In this sense, this file is a proper part of the
48 * definition of the (software) Alpha architecture.
52 * Symbolic register names and register saving rules
55 * T Saved by caller (Temporaries)
56 * S Saved by callee (call-Safe registers)
59 #define v0 $0 /* (T) return value */
60 #define t0 $1 /* (T) temporary registers */
69 #define s0 $9 /* (S) call-safe registers */
76 #define a0 $16 /* (T) argument registers */
82 #define t8 $22 /* (T) temporary registers */
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 */
93 /* In the kernel, we use t7 to point at the per-cpu globals. */
98 /* Floating point registers (XXXX VERIFY THIS) */
99 #define fv0 $f0 /* (T) return value (real) */
100 #define fv1 $f1 /* (T) return value (imaginary)*/
102 #define fs0 $f2 /* (S) call-safe registers */
110 #define ft1 $f10 /* (T) temporary registers */
116 #define fa0 $f16 /* (T) argument registers */
122 #define ft7 $f22 /* (T) more temporaries */
131 #define fzero $f31 /* wired zero */
134 /* Other DEC standard names */
135 #define ai $25 /* (T) argument information */
136 #define pv $27 /* (T) procedure value */
143 #define __CONCAT(a,b) a ## b
145 #define __CONCAT(a,b) a/**/b
147 #define ___CONCAT(a,b) __CONCAT(a,b)
150 * Macro to make a local label name.
152 #define LLABEL(name,num) ___CONCAT(___CONCAT(L,name),num)
156 * Debuggers need symbol table information to be able to properly
157 * decode a stack trace. The minimum that should be provided is:
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);
168 * NESTED functions (functions that call other functions) should define
169 * how they handle their stack frame in a .frame directive:
171 * .frame framesize, pc_reg, i_mask, f_mask
173 * where "framesize" is the size of the frame for this function, in bytes.
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
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
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.
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:
191 * .frame $15,framesize,$26,0
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
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)
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
211 * All functions must be terminated by the END macro
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:
220 * .reguse i_mask, f_mask
222 * where the register masks are built as above or-ing M_xx defines.
225 * All symbols are internal unless EXPORTed. Symbols that are IMPORTed
226 * must be appropriately described to the debugger.
234 #if !defined(GPROF) && !defined(PROF)
235 #define MCOUNT /* nothing */
239 jsr at_reg,_mcount; \
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.
251 #define PALVECT(_name_) \
255 #define ESETUP(_name_) \
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; \
268 stq at_reg,(FRAME_AT*8)(sp); \
270 stq ra,(FRAME_RA*8)(sp); \
272 bsr ra,exception_save_regs /* jmp/CALL trashes pv/t12 */
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
281 #define LEAF(_name_,_n_args_) \
288 .proc _name_,_n_args_; \
292 #define LEAF_NOPROFILE(_name_,_n_args_) \
298 .proc _name_,_n_args_; \
304 * Declare a local leaf function.
306 #define STATIC_LEAF(_name_,_n_args_) \
312 .proc _name_,_n_args_; \
317 * Global alias for a leaf function, or alternate entry point
319 #define XLEAF(_name_,_n_args_) \
324 .aproc _name_,_n_args_;
329 * Local alias for a leaf function, or alternate entry point
331 #define STATIC_XLEAF(_name_,_n_args_) \
335 .aproc _name_,_n_args_;
340 * Declare a (global) nested function
341 * A nested function calls other functions and needs
342 * therefore stack space to save/restore registers.
344 #define NESTED(_name_, _n_args_, _framesize_, _pc_reg_, _i_mask_, _f_mask_ ) \
348 .frame sp,_framesize_,_pc_reg_; \
349 .livereg _i_mask_,_f_mask_; \
352 .proc _name_,_n_args_; \
353 .frame _framesize_, _pc_reg_, _i_mask_, _f_mask_
356 #define NESTED_NOPROFILE(_name_, _n_args_, _framesize_, _pc_reg_, _i_mask_, _f_mask_ ) \
360 .frame sp,_framesize_,_pc_reg_; \
361 .livereg _i_mask_,_f_mask_
363 .proc _name_,_n_args_; \
364 .frame _framesize_, _pc_reg_, _i_mask_, _f_mask_
369 * Declare a local nested function.
371 #define STATIC_NESTED(_name_, _n_args_, _framesize_, _pc_reg_, _i_mask_, _f_mask_ ) \
374 .frame sp,_framesize_,_pc_reg_; \
375 .livereg _i_mask_,_f_mask_; \
378 .proc _name_,_n_args_; \
379 .frame _framesize_, _pc_reg_, _i_mask_, _f_mask_
384 * Same as XLEAF, for a nested function.
386 #define XNESTED(_name_,_n_args_) \
391 .aproc _name_,_n_args_;
397 * Same as STATIC_XLEAF, for a nested function.
399 #define STATIC_XNESTED(_name_,_n_args_) \
403 .aproc _name_,_n_args_;
411 #define END(_name_) \
417 * Function invocation
419 #define CALL(_name_) \
423 /* but this would cover longer jumps
431 * Return from function
441 #define EXPORT(_name_) \
448 * Make an external name visible, typecheck the size
450 #define IMPORT(_name_, _size_) \
451 .extern _name_,_size_
456 * Define an absolute symbol
458 #define ABS(_name_, _value_) \
465 * Allocate un-initialized space for a global symbol
467 #define BSS(_name_,_numbytes_) \
468 .comm _name_,_numbytes_
472 * Make an exception entry point look like a called function,
473 * to make it digestible to the debugger (KERNEL only)
475 #define VECTOR(_name_, _i_mask_) \
479 .mask _i_mask_|IM_EXC,0; \
480 .frame sp,MSS_SIZE,ra;
481 /* .livereg _i_mask_|IM_EXC,0 */
484 .frame MSS_SIZE,$31,_i_mask_,0; \
489 * Allocate space for a message (a read-only ascii string)
492 #define MSG(msg,reg,label) \
502 #define PRINTF(msg,label) \
508 * Fatal error (KERNEL)
510 #define PANIC(msg,label) \
515 * Register mask defines, used to define both save
516 * and use register sets.
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
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
530 #define IM_RA 0x04000000
531 #define IM_T11 0x02000000
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
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
590 #define FM_V0 0x00000001
592 /* Pull in PAL "function" codes. */
593 #include <machine/pal.h>
598 #define SYSCALLNUM(name) \
601 #define CALLSYS_NOERROR(name) \
602 ldiq v0, SYSCALLNUM(name); \
603 call_pal PAL_OSF1_callsys
606 * Load the global pointer.
612 * WEAK_ALIAS: create a weak alias (ELF only).
615 #define WEAK_ALIAS(alias,sym) \
621 * Kernel RCS ID tag and copyright macros
627 #define __KERNEL_SECTIONSTRING(_sec, _str) \
628 .section _sec ; .asciz _str ; .text
630 #define __KERNEL_SECTIONSTRING(_sec, _str) \
631 .data ; .asciz _str ; .align 3 ; .text
634 #define __KERNEL_RCSID(_n, _s) __KERNEL_SECTIONSTRING(.ident, _s)
635 #define __KERNEL_COPYRIGHT(_n, _s) __KERNEL_SECTIONSTRING(.copyright, _s)
637 #ifdef NO_KERNEL_RCSIDS
638 #undef __KERNEL_RCSID
639 #define __KERNEL_RCSID(_n, _s) /* nothing */