xref: /openbsd/sys/arch/alpha/include/asm.h (revision 6750a6d9)
1 /* $OpenBSD: asm.h,v 1.16 2023/12/06 06:15:33 miod Exp $ */
2 /* $NetBSD: asm.h,v 1.23 2000/06/23 12:18:45 kleink 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 /* Floating point registers  (XXXX VERIFY THIS) */
94 #define	fv0	$f0	/* (T)		return value (real)	*/
95 #define	fv1	$f1	/* (T)		return value (imaginary)*/
96 #define	ft0	fv1
97 #define	fs0	$f2	/* (S)		call-safe registers	*/
98 #define	fs1	$f3
99 #define	fs2	$f4
100 #define	fs3	$f5
101 #define	fs4	$f6
102 #define	fs5	$f7
103 #define	fs6	$f8
104 #define	fs7	$f9
105 #define	ft1	$f10	/* (T)		temporary registers	*/
106 #define	ft2	$f11
107 #define	ft3	$f12
108 #define	ft4	$f13
109 #define	ft5	$f14
110 #define	ft6	$f15
111 #define	fa0	$f16	/* (T)		argument registers	*/
112 #define	fa1	$f17
113 #define	fa2	$f18
114 #define	fa3	$f19
115 #define	fa4	$f20
116 #define	fa5	$f21
117 #define	ft7	$f22	/* (T)		more temporaries	*/
118 #define	ft8	$f23
119 #define	ft9	$f24
120 #define	ft10	$f25
121 #define	ft11	$f26
122 #define	ft12	$f27
123 #define	ft13	$f28
124 #define	ft14	$f29
125 #define	ft15	$f30
126 #define	fzero	$f31	/*		wired zero		*/
127 
128 
129 /* Other DEC standard names */
130 #define fp	$15	/* (S)		frame pointer		*/
131 #define ai	$25	/* (T)		argument information	*/
132 #define pv	$27	/* (T)		procedure value		*/
133 #define AT	$28	/* (T)		assembler scratch	*/
134 
135 
136 /*
137  * Useful stuff.
138  */
139 #ifdef __STDC__
140 #define	__CONCAT(a,b)	a ## b
141 #else
142 #define	__CONCAT(a,b)	a/**/b
143 #endif
144 #define ___CONCAT(a,b)	__CONCAT(a,b)
145 
146 /*
147  * Macro to make a local label name.
148  */
149 #define	LLABEL(name,num)	___CONCAT(___CONCAT(L,name),num)
150 
151 /*
152  *
153  * Debuggers need symbol table information to be able to properly
154  * decode a stack trace.  The minimum that should be provided is:
155  *
156  * 	name:
157  *		.proc	name,numargs
158  *
159  * where "name" 	is the function's name;
160  *	 "numargs"	how many arguments it expects. For varargs
161  *			procedures this should be a negative number,
162  *			indicating the minimum required number of
163  *			arguments (which is at least 1);
164  *
165  * NESTED functions (functions that call other functions) should define
166  * how they handle their stack frame in a .frame directive:
167  *
168  *		.frame	framesize, pc_reg, i_mask, f_mask
169  *
170  * where "framesize"	is the size of the frame for this function, in bytes.
171  *			That is:
172  *				new_sp + framesize == old_sp
173  *			Framesizes should be rounded to a cacheline size.
174  *			Note that old_sp plays the role of a conventional
175  *			"frame pointer";
176  *	 "pc_reg"	is either a register which preserves the caller's PC
177  *			or 'std', if std the saved PC should be stored at
178  *				old_sp-8
179  * 	 "i_mask"	is a bitmask that indicates which of the integer
180  *			registers are saved. See the M_xx defines at the
181  *			end for the encoding of this 32bit value.
182  *	 "f_mask"	is the same, for floating point registers.
183  *
184  * Note, 10/31/97: This is interesting but it isn't the way gcc outputs
185  * frame directives and it isn't the way the macros below output them
186  * either. Frame directives look like this:
187  *
188  *		.frame	$15,framesize,$26,0
189  *
190  * If no fp is set up then $30 should be used instead of $15.
191  * Also, gdb expects to find a <lda sp,-framesize(sp)> at the beginning
192  * of a procedure. Don't use things like sub sp,framesize,sp for this
193  * reason. End Note 10/31/97. ross@netbsd.org
194  *
195  * Note that registers should be saved starting at "old_sp-8", where the
196  * return address should be stored. Other registers follow at -16-24-32..
197  * starting from register 0 (if saved) and up. Then float registers (ifany)
198  * are saved.
199  *
200  * If you need to alias a leaf function, or to provide multiple entry points
201  * use the LEAF() macro for the main entry point and XLEAF() for the other
202  * additional/alternate entry points.
203  * "XLEAF"s must be nested within a "LEAF" and a ".end".
204  * Similar rules for nested routines, e.g. use NESTED/XNESTED
205  * Symbols that should not be exported can be declared with the STATIC_xxx
206  * macros.
207  *
208  * All functions must be terminated by the END macro
209  *
210  * It is conceivable, although currently at the limits of compiler
211  * technology, that while performing inter-procedural optimizations
212  * the compiler/linker be able to avoid unnecessary register spills
213  * if told about the register usage of LEAF procedures (and by transitive
214  * closure of NESTED procedures as well).  Assembly code can help
215  * this process using the .reguse directive:
216  *
217  *		.reguse	i_mask, f_mask
218  *
219  * where the register masks are built as above or-ing M_xx defines.
220  *
221  *
222  * All symbols are internal unless EXPORTed.  Symbols that are IMPORTed
223  * must be appropriately described to the debugger.
224  *
225  */
226 
227 /*
228  * MCOUNT
229  */
230 
231 #ifndef GPROF
232 #define MCOUNT	/* nothing */
233 #else
234 #define MCOUNT							\
235 	.set noat;						\
236 	jsr	at_reg,_mcount;					\
237 	.set at
238 #endif
239 /*
240  * PALVECT, ESETUP, and ERSAVE
241  *	Declare a palcode transfer point, and carefully construct
242  *	gdb symbols with an unusual _negative_ register-save offset
243  *	so that gdb can find the otherwise lost PC and then
244  *	invert the vector for traceback. Also, fix up framesize,
245  *	allowing for the palframe for the same reason.
246  */
247 
248 #define PALVECT(_name_)						\
249 	ESETUP(_name_);						\
250 	ERSAVE()
251 
252 #define	ESETUP(_name_)						\
253 	/* .loc	1 __LINE__; */					\
254 	.globl	_name_;						\
255 	.ent	_name_ 0;					\
256 _name_:;							\
257 	.set	noat;						\
258 	lda	sp,-(FRAME_SW_SIZE*8)(sp);			\
259 	.frame	$30,(FRAME_SW_SIZE+6)*8,$26,0;   /* give gdb the real size */\
260 	.mask	0x4000000,-0x28;				\
261 	.set	at
262 
263 #define	ERSAVE()						\
264 	.set	noat;						\
265 	stq	at_reg,(FRAME_AT*8)(sp);			\
266 	.set	at;						\
267 	stq	ra,(FRAME_RA*8)(sp);				\
268 	/* .loc	1 __LINE__; */					\
269 	bsr	ra,exception_save_regs         /* jmp/CALL trashes pv/t12 */
270 
271 
272 /*
273  * LEAF
274  *	Declare a global leaf function.
275  *	A leaf function does not call other functions AND does not
276  *	use any register that is callee-saved AND does not modify
277  *	the stack pointer.
278  */
279 #define	LEAF(_name_,_n_args_)					\
280 	.globl	_name_;						\
281 	.ent	_name_ 0;					\
282 _name_:;							\
283 	.frame	sp,0,ra;					\
284 	MCOUNT
285 /* should have been
286 	.proc	_name_,_n_args_;				\
287 	.frame	0,ra,0,0
288 */
289 
290 #define	LEAF_NOPROFILE(_name_,_n_args_)					\
291 	.globl	_name_;						\
292 	.ent	_name_ 0;					\
293 _name_:;							\
294 	.frame	sp,0,ra
295 /* should have been
296 	.proc	_name_,_n_args_;				\
297 	.frame	0,ra,0,0
298 */
299 
300 /*
301  * STATIC_LEAF
302  *	Declare a local leaf function.
303  */
304 #define STATIC_LEAF(_name_,_n_args_)				\
305 	.ent	_name_ 0;					\
306 _name_:;							\
307 	.frame	sp,0,ra;					\
308 	MCOUNT
309 /* should have been
310 	.proc	_name_,_n_args_;				\
311 	.frame	0,ra,0,0
312 */
313 /*
314  * XLEAF
315  *	Global alias for a leaf function, or alternate entry point
316  */
317 #define	XLEAF(_name_,_n_args_)					\
318 	.globl	_name_;						\
319 	.aent	_name_ 0;					\
320 _name_:
321 /* should have been
322 	.aproc	_name_,_n_args_;
323 */
324 
325 /*
326  * STATIC_XLEAF
327  *	Local alias for a leaf function, or alternate entry point
328  */
329 #define	STATIC_XLEAF(_name_,_n_args_)				\
330 	.aent	_name_ 0;					\
331 _name_:
332 /* should have been
333 	.aproc	_name_,_n_args_;
334 */
335 
336 /*
337  * NESTED
338  *	Declare a (global) nested function
339  *	A nested function calls other functions and needs
340  *	therefore stack space to save/restore registers.
341  */
342 #define	NESTED(_name_, _n_args_, _framesize_, _pc_reg_, _i_mask_, _f_mask_ ) \
343 	.globl	_name_;						\
344 	.ent	_name_ 0;					\
345 _name_:;							\
346 	.frame	sp,_framesize_,_pc_reg_;			\
347 	.livereg _i_mask_,_f_mask_;				\
348 	MCOUNT
349 /* should have been
350 	.proc	_name_,_n_args_;				\
351 	.frame	_framesize_, _pc_reg_, _i_mask_, _f_mask_
352 */
353 
354 #define	NESTED_NOPROFILE(_name_, _n_args_, _framesize_, _pc_reg_, _i_mask_, _f_mask_ ) \
355 	.globl	_name_;						\
356 	.ent	_name_ 0;					\
357 _name_:;							\
358 	.frame	sp,_framesize_,_pc_reg_;			\
359 	.livereg _i_mask_,_f_mask_
360 /* should have been
361 	.proc	_name_,_n_args_;				\
362 	.frame	_framesize_, _pc_reg_, _i_mask_, _f_mask_
363 */
364 
365 /*
366  * STATIC_NESTED
367  *	Declare a local nested function.
368  */
369 #define	STATIC_NESTED(_name_, _n_args_, _framesize_, _pc_reg_, _i_mask_, _f_mask_ ) \
370 	.ent	_name_ 0;					\
371 _name_:;							\
372 	.frame	sp,_framesize_,_pc_reg_;			\
373 	.livereg _i_mask_,_f_mask_;				\
374 	MCOUNT
375 /* should have been
376 	.proc	_name_,_n_args_;				\
377 	.frame	_framesize_, _pc_reg_, _i_mask_, _f_mask_
378 */
379 
380 /*
381  * XNESTED
382  *	Same as XLEAF, for a nested function.
383  */
384 #define	XNESTED(_name_,_n_args_)				\
385 	.globl	_name_;						\
386 	.aent	_name_ 0;					\
387 _name_:
388 /* should have been
389 	.aproc	_name_,_n_args_;
390 */
391 
392 
393 /*
394  * STATIC_XNESTED
395  *	Same as STATIC_XLEAF, for a nested function.
396  */
397 #define	STATIC_XNESTED(_name_,_n_args_)				\
398 	.aent	_name_ 0;					\
399 _name_:
400 /* should have been
401 	.aproc	_name_,_n_args_;
402 */
403 
404 
405 /*
406  * END
407  *	Function delimiter
408  */
409 #define	END(_name_)						\
410 	.end	_name_
411 
412 
413 /*
414  * CALL
415  *	Function invocation
416  */
417 #define	CALL(_name_)						\
418 	/* .loc	1 __LINE__; */					\
419 	jsr	ra,_name_;					\
420 	ldgp	gp,0(ra)
421 /* but this would cover longer jumps
422 	br	ra,.+4;						\
423 	bsr	ra,_name_
424 */
425 
426 
427 /*
428  * RET
429  *	Return from function
430  */
431 #define	RET							\
432 	ret	zero,(ra),1
433 
434 
435 /*
436  * EXPORT
437  *	Export a symbol
438  */
439 #define	EXPORT(_name_)						\
440 	.globl	_name_;						\
441 _name_:
442 
443 
444 /*
445  * IMPORT
446  *	Make an external name visible, typecheck the size
447  */
448 #define	IMPORT(_name_, _size_)					\
449 	.extern	_name_,_size_
450 
451 
452 /*
453  * ABS
454  *	Define an absolute symbol
455  */
456 #define	ABS(_name_, _value_)					\
457 	.globl	_name_;						\
458 _name_	=	_value_
459 
460 
461 /*
462  * BSS
463  *	Allocate un-initialized space for a global symbol
464  */
465 #define	BSS(_name_,_numbytes_)					\
466 	.comm	_name_,_numbytes_
467 
468 /*
469  * VECTOR
470  *	Make an exception entry point look like a called function,
471  *	to make it digestible to the debugger (KERNEL only)
472  */
473 #define	VECTOR(_name_, _i_mask_)				\
474 	.globl	_name_;						\
475 	.ent	_name_ 0;					\
476 _name_:;							\
477 	.mask	_i_mask_|IM_EXC,0;				\
478 	.frame	sp,MSS_SIZE,ra;
479 /*	.livereg _i_mask_|IM_EXC,0	*/
480 /* should have been
481 	.proc	_name_,1;					\
482 	.frame	MSS_SIZE,$31,_i_mask_,0;			\
483 */
484 
485 /*
486  * MSG
487  *	Allocate space for a message (a read-only ascii string)
488  */
489 #define	ASCIZ	.asciz
490 #define	MSG(msg,reg,label)					\
491 	lda reg, label;						\
492 	.data;							\
493 label:	ASCIZ msg;						\
494 	.text;
495 
496 /*
497  * PRINTF
498  *	Print a message
499  */
500 #define	PRINTF(msg,label)					\
501 	MSG(msg,a0,label);					\
502 	CALL(printf)
503 
504 /*
505  * PANIC
506  *	Fatal error (KERNEL)
507  */
508 #define	PANIC(msg,label)					\
509 	MSG(msg,a0,label);					\
510 	CALL(panic)
511 
512 /*
513  * Register mask defines, used to define both save
514  * and use register sets.
515  *
516  * NOTE: The bit order should HAVE BEEN maintained when saving
517  *	 registers on the stack: sp goes at the highest
518  *	 address, gp lower on the stack, etc etc
519  *	 BUT NOONE CARES ABOUT DEBUGGERS AT MIPS
520  */
521 
522 #define	IM_EXC	0x80000000
523 #define	IM_SP	0x40000000
524 #define	IM_GP	0x20000000
525 #define	IM_AT	0x10000000
526 #define	IM_T12	0x08000000
527 #	define	IM_PV	IM_T4
528 #define	IM_RA	0x04000000
529 #define	IM_T11	0x02000000
530 #	define	IM_AI	IM_T3
531 #define	IM_T10	0x01000000
532 #define	IM_T9	0x00800000
533 #define	IM_T8	0x00400000
534 #define	IM_A5	0x00200000
535 #define	IM_A4	0x00100000
536 #define	IM_A3	0x00080000
537 #define	IM_A2	0x00040000
538 #define	IM_A1	0x00020000
539 #define	IM_A0	0x00010000
540 #define	IM_S6	0x00008000
541 #define	IM_S5	0x00004000
542 #define	IM_S4	0x00002000
543 #define	IM_S3	0x00001000
544 #define	IM_S2	0x00000800
545 #define	IM_S1	0x00000400
546 #define	IM_S0	0x00000200
547 #define	IM_T7	0x00000100
548 #define	IM_T6	0x00000080
549 #define	IM_T5	0x00000040
550 #define	IM_T4	0x00000020
551 #define	IM_T3	0x00000010
552 #define	IM_T2	0x00000008
553 #define	IM_T1	0x00000004
554 #define	IM_T0	0x00000002
555 #define	IM_V0	0x00000001
556 
557 #define	FM_T15	0x40000000
558 #define	FM_T14	0x20000000
559 #define	FM_T13	0x10000000
560 #define	FM_T12	0x08000000
561 #define	FM_T11	0x04000000
562 #define	FM_T10	0x02000000
563 #define	FM_T9	0x01000000
564 #define	FM_T8	0x00800000
565 #define	FM_T7	0x00400000
566 #define	FM_A5	0x00200000
567 #define	FM_A4	0x00100000
568 #define	FM_A3	0x00080000
569 #define	FM_A2	0x00040000
570 #define	FM_A1	0x00020000
571 #define	FM_A0	0x00010000
572 #define	FM_T6	0x00008000
573 #define	FM_T5	0x00004000
574 #define	FM_T4	0x00002000
575 #define	FM_T3	0x00001000
576 #define	FM_T2	0x00000800
577 #define	FM_T1	0x00000400
578 #define	FM_S7	0x00000200
579 #define	FM_S6	0x00000100
580 #define	FM_S5	0x00000080
581 #define	FM_S4	0x00000040
582 #define	FM_S3	0x00000020
583 #define	FM_S2	0x00000010
584 #define	FM_S1	0x00000008
585 #define	FM_S0	0x00000004
586 #define	FM_T0	0x00000002
587 #define	FM_V1	FM_T0
588 #define	FM_V0	0x00000001
589 
590 /* Pull in PAL "function" codes. */
591 #include <machine/pal.h>
592 
593 /*
594  * Load the global pointer.
595  */
596 #define	LDGP(reg)						\
597 	ldgp	gp, 0(reg)
598 
599 /*
600  * STRONG_ALIAS, WEAK_ALIAS
601  *	Create a strong or weak alias.
602  */
603 #define STRONG_ALIAS(alias,sym)					\
604 	.global alias;						\
605 	alias = sym
606 #define WEAK_ALIAS(alias,sym)					\
607 	.weak alias;						\
608 	alias = sym
609