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