asm.h revision 1.13 1 /* $NetBSD: asm.h,v 1.13 1997/04/08 00:19:04 cgd 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 (at) 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 /* (T) 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 that registers should be saved starting at "old_sp-8", where the
182 * return address should be stored. Other registers follow at -16-24-32..
183 * starting from register 0 (if saved) and up. Then float registers (ifany)
184 * are saved.
185 *
186 * If you need to alias a leaf function, or to provide multiple entry points
187 * use the LEAF() macro for the main entry point and XLEAF() for the other
188 * additional/alternate entry points.
189 * "XLEAF"s must be nested within a "LEAF" and a ".end".
190 * Similar rules for nested routines, e.g. use NESTED/XNESTED
191 * Symbols that should not be exported can be declared with the STATIC_xxx
192 * macros.
193 *
194 * All functions must be terminated by the END macro
195 *
196 * It is conceivable, although currently at the limits of compiler
197 * technology, that while performing inter-procedural optimizations
198 * the compiler/linker be able to avoid unnecessary register spills
199 * if told about the register usage of LEAF procedures (and by transitive
200 * closure of NESTED procedures as well). Assembly code can help
201 * this process using the .reguse directive:
202 *
203 * .reguse i_mask, f_mask
204 *
205 * where the register masks are built as above or-ing M_xx defines.
206 *
207 *
208 * All symbols are internal unless EXPORTed. Symbols that are IMPORTed
209 * must be appropriately described to the debugger.
210 *
211 */
212
213 /*
214 * MCOUNT
215 */
216
217 #ifndef GPROF
218 #define MCOUNT /* nothing */
219 #else
220 #define MCOUNT \
221 .set noat; \
222 jsr at_reg,_mcount; \
223 .set at
224 #endif
225
226 /*
227 * LEAF
228 * Declare a global leaf function.
229 * A leaf function does not call other functions AND does not
230 * use any register that is callee-saved AND does not modify
231 * the stack pointer.
232 */
233 #define LEAF(_name_,_n_args_) \
234 .globl _name_; \
235 .ent _name_ 0; \
236 _name_:; \
237 .frame sp,0,ra; \
238 MCOUNT
239 /* should have been
240 .proc _name_,_n_args_; \
241 .frame 0,ra,0,0
242 */
243
244 #define LEAF_NOPROFILE(_name_,_n_args_) \
245 .globl _name_; \
246 .ent _name_ 0; \
247 _name_:; \
248 .frame sp,0,ra
249 /* should have been
250 .proc _name_,_n_args_; \
251 .frame 0,ra,0,0
252 */
253
254 /*
255 * STATIC_LEAF
256 * Declare a local leaf function.
257 */
258 #define STATIC_LEAF(_name_,_n_args_) \
259 .ent _name_ 0; \
260 _name_:; \
261 .frame sp,0,ra; \
262 MCOUNT
263 /* should have been
264 .proc _name_,_n_args_; \
265 .frame 0,ra,0,0
266 */
267 /*
268 * XLEAF
269 * Global alias for a leaf function, or alternate entry point
270 */
271 #define XLEAF(_name_,_n_args_) \
272 .globl _name_; \
273 .aent _name_ 0; \
274 _name_:
275 /* should have been
276 .aproc _name_,_n_args_;
277 */
278
279 /*
280 * STATIC_XLEAF
281 * Local alias for a leaf function, or alternate entry point
282 */
283 #define STATIC_XLEAF(_name_,_n_args_) \
284 .aent _name_ 0; \
285 _name_:
286 /* should have been
287 .aproc _name_,_n_args_;
288 */
289
290 /*
291 * NESTED
292 * Declare a (global) nested function
293 * A nested function calls other functions and needs
294 * therefore stack space to save/restore registers.
295 */
296 #define NESTED(_name_, _n_args_, _framesize_, _pc_reg_, _i_mask_, _f_mask_ ) \
297 .globl _name_; \
298 .ent _name_ 0; \
299 _name_:; \
300 .frame sp,_framesize_,_pc_reg_; \
301 .livereg _i_mask_,_f_mask_; \
302 MCOUNT
303 /* should have been
304 .proc _name_,_n_args_; \
305 .frame _framesize_, _pc_reg_, _i_mask_, _f_mask_
306 */
307
308 #define NESTED_NOPROFILE(_name_, _n_args_, _framesize_, _pc_reg_, _i_mask_, _f_mask_ ) \
309 .globl _name_; \
310 .ent _name_ 0; \
311 _name_:; \
312 .frame sp,_framesize_,_pc_reg_; \
313 .livereg _i_mask_,_f_mask_
314 /* should have been
315 .proc _name_,_n_args_; \
316 .frame _framesize_, _pc_reg_, _i_mask_, _f_mask_
317 */
318
319 /*
320 * STATIC_NESTED
321 * Declare a local nested function.
322 */
323 #define STATIC_NESTED(_name_, _n_args_, _framesize_, _pc_reg_, _i_mask_, _f_mask_ ) \
324 .ent _name_ 0; \
325 _name_:; \
326 .frame sp,_framesize_,_pc_reg_; \
327 .livereg _i_mask_,_f_mask_; \
328 MCOUNT
329 /* should have been
330 .proc _name_,_n_args_; \
331 .frame _framesize_, _pc_reg_, _i_mask_, _f_mask_
332 */
333
334 /*
335 * XNESTED
336 * Same as XLEAF, for a nested function.
337 */
338 #define XNESTED(_name_,_n_args_) \
339 .globl _name_; \
340 .aent _name_ 0; \
341 _name_:
342 /* should have been
343 .aproc _name_,_n_args_;
344 */
345
346
347 /*
348 * STATIC_XNESTED
349 * Same as STATIC_XLEAF, for a nested function.
350 */
351 #define STATIC_XNESTED(_name_,_n_args_) \
352 .aent _name_ 0; \
353 _name_:
354 /* should have been
355 .aproc _name_,_n_args_;
356 */
357
358
359 /*
360 * END
361 * Function delimiter
362 */
363 #define END(_name_) \
364 .end _name_
365
366
367 /*
368 * CALL
369 * Function invocation
370 */
371 #define CALL(_name_) \
372 jsr ra,_name_; \
373 ldgp gp,0(ra)
374 /* but this would cover longer jumps
375 br ra,.+4; \
376 bsr ra,_name_
377 */
378
379
380 /*
381 * RET
382 * Return from function
383 */
384 #define RET \
385 ret zero,(ra),1
386
387
388 /*
389 * EXPORT
390 * Export a symbol
391 */
392 #define EXPORT(_name_) \
393 .globl _name_; \
394 _name_:
395
396
397 /*
398 * IMPORT
399 * Make an external name visible, typecheck the size
400 */
401 #define IMPORT(_name_, _size_) \
402 .extern _name_,_size_
403
404
405 /*
406 * ABS
407 * Define an absolute symbol
408 */
409 #define ABS(_name_, _value_) \
410 .globl _name_; \
411 _name_ = _value_
412
413
414 /*
415 * BSS
416 * Allocate un-initialized space for a global symbol
417 */
418 #define BSS(_name_,_numbytes_) \
419 .comm _name_,_numbytes_
420
421 /*
422 * VECTOR
423 * Make an exception entry point look like a called function,
424 * to make it digestible to the debugger (KERNEL only)
425 */
426 #define VECTOR(_name_, _i_mask_) \
427 .globl _name_; \
428 .ent _name_ 0; \
429 _name_:; \
430 .mask _i_mask_|IM_EXC,0; \
431 .frame sp,MSS_SIZE,ra;
432 /* .livereg _i_mask_|IM_EXC,0
433 /* should have been
434 .proc _name_,1; \
435 .frame MSS_SIZE,$31,_i_mask_,0; \
436 */
437
438 /*
439 * MSG
440 * Allocate space for a message (a read-only ascii string)
441 */
442 #define ASCIZ .asciz
443 #define MSG(msg,reg,label) \
444 lda reg, label; \
445 .data; \
446 label: ASCIZ msg; \
447 .text;
448
449 /*
450 * PRINTF
451 * Print a message
452 */
453 #define PRINTF(msg,label) \
454 MSG(msg,a0,label); \
455 CALL(printf)
456
457 /*
458 * PANIC
459 * Fatal error (KERNEL)
460 */
461 #define PANIC(msg,label) \
462 MSG(msg,a0,label); \
463 CALL(panic)
464
465 /*
466 * Register mask defines, used to define both save
467 * and use register sets.
468 *
469 * NOTE: The bit order should HAVE BEEN maintained when saving
470 * registers on the stack: sp goes at the highest
471 * address, gp lower on the stack, etc etc
472 * BUT NOONE CARES ABOUT DEBUGGERS AT MIPS
473 */
474
475 #define IM_EXC 0x80000000
476 #define IM_SP 0x40000000
477 #define IM_GP 0x20000000
478 #define IM_AT 0x10000000
479 #define IM_T12 0x08000000
480 # define IM_PV IM_T4
481 #define IM_RA 0x04000000
482 #define IM_T11 0x02000000
483 # define IM_AI IM_T3
484 #define IM_T10 0x01000000
485 #define IM_T9 0x00800000
486 #define IM_T8 0x00400000
487 #define IM_A5 0x00200000
488 #define IM_A4 0x00100000
489 #define IM_A3 0x00080000
490 #define IM_A2 0x00040000
491 #define IM_A1 0x00020000
492 #define IM_A0 0x00010000
493 #define IM_S6 0x00008000
494 #define IM_S5 0x00004000
495 #define IM_S4 0x00002000
496 #define IM_S3 0x00001000
497 #define IM_S2 0x00000800
498 #define IM_S1 0x00000400
499 #define IM_S0 0x00000200
500 #define IM_T7 0x00000100
501 #define IM_T6 0x00000080
502 #define IM_T5 0x00000040
503 #define IM_T4 0x00000020
504 #define IM_T3 0x00000010
505 #define IM_T2 0x00000008
506 #define IM_T1 0x00000004
507 #define IM_T0 0x00000002
508 #define IM_V0 0x00000001
509
510 #define FM_T15 0x40000000
511 #define FM_T14 0x20000000
512 #define FM_T13 0x10000000
513 #define FM_T12 0x08000000
514 #define FM_T11 0x04000000
515 #define FM_T10 0x02000000
516 #define FM_T9 0x01000000
517 #define FM_T8 0x00800000
518 #define FM_T7 0x00400000
519 #define FM_A5 0x00200000
520 #define FM_A4 0x00100000
521 #define FM_A3 0x00080000
522 #define FM_A2 0x00040000
523 #define FM_A1 0x00020000
524 #define FM_A0 0x00010000
525 #define FM_T6 0x00008000
526 #define FM_T5 0x00004000
527 #define FM_T4 0x00002000
528 #define FM_T3 0x00001000
529 #define FM_T2 0x00000800
530 #define FM_T1 0x00000400
531 #define FM_S7 0x00000200
532 #define FM_S6 0x00000100
533 #define FM_S5 0x00000080
534 #define FM_S4 0x00000040
535 #define FM_S3 0x00000020
536 #define FM_S2 0x00000010
537 #define FM_S1 0x00000008
538 #define FM_S0 0x00000004
539 #define FM_T0 0x00000002
540 #define FM_V1 FM_T0
541 #define FM_V0 0x00000001
542
543 /*
544 * PAL "function" codes (used as arguments to call_pal instructions).
545 *
546 * Those marked with "P" are privileged, and those marked with "U"
547 * are unprivileged.
548 */
549
550 /* Common PAL function codes. */
551 #define PAL_halt 0x0000 /* P */
552 #define PAL_draina 0x0002 /* P */
553 #define PAL_cserve 0x0009 /* P */
554 #define PAL_swppal 0x000a /* P */
555 #define PAL_bpt 0x0080 /* U */
556 #define PAL_bugchk 0x0081 /* U */
557 #define PAL_imb 0x0086 /* U */
558 #define PAL_rdunique 0x009e /* U */
559 #define PAL_wrunique 0x009f /* U */
560 #define PAL_gentrap 0x00aa /* U */
561
562 /* VMS PAL function codes. */
563 #define PAL_VMS_ldqp 0x0003 /* P */
564 #define PAL_VMS_stqp 0x0004 /* P */
565 #define PAL_VMS_mtpr_fen 0x000c /* P */
566 #define PAL_VMS_mtpr_ipir 0x000d /* P */
567 #define PAL_VMS_mfpr_ipl 0x000e /* P */
568 #define PAL_VMS_mtpr_ipl 0x000f /* P */
569 #define PAL_VMS_mfpr_mces 0x0010 /* P */
570 #define PAL_VMS_mtpr_mces 0x0011 /* P */
571 #define PAL_VMS_mfpr_prbr 0x0013 /* P */
572 #define PAL_VMS_mtpr_prbr 0x0014 /* P */
573 #define PAL_VMS_mfpr_ptbr 0x0015 /* P */
574 #define PAL_VMS_mtpr_scbb 0x0017 /* P */
575 #define PAL_VMS_mtpr_sirr 0x0018 /* P */
576 #define PAL_VMS_mtpr_tbia 0x001b /* P */
577 #define PAL_VMS_mtpr_tbiap 0x001c /* P */
578 #define PAL_VMS_mtpr_tbis 0x001d /* P */
579 #define PAL_VMS_mfpr_usp 0x0022 /* P */
580 #define PAL_VMS_mtpr_usp 0x0023 /* P */
581 #define PAL_VMS_mfpr_vptb 0x0029 /* P */
582 #define PAL_VMS_mfpr_whami 0x003f /* P */
583 #define PAL_VMS_rei 0x0092 /* U */
584
585 /* OSF/1 PAL function codes. */
586 #define PAL_OSF1_rdmces 0x0010 /* P */
587 #define PAL_OSF1_wrmces 0x0011 /* P */
588 #define PAL_OSF1_wrfen 0x002b /* P */
589 #define PAL_OSF1_wrvptptr 0x002d /* P */
590 #define PAL_OSF1_swpctx 0x0030 /* P */
591 #define PAL_OSF1_wrval 0x0031 /* P */
592 #define PAL_OSF1_rdval 0x0032 /* P */
593 #define PAL_OSF1_tbi 0x0033 /* P */
594 #define PAL_OSF1_wrent 0x0034 /* P */
595 #define PAL_OSF1_swpipl 0x0035 /* P */
596 #define PAL_OSF1_rdps 0x0036 /* P */
597 #define PAL_OSF1_wrkgp 0x0037 /* P */
598 #define PAL_OSF1_wrusp 0x0038 /* P */
599 #define PAL_OSF1_rdusp 0x003a /* P */
600 #define PAL_OSF1_whami 0x003c /* P */
601 #define PAL_OSF1_retsys 0x003d /* P */
602 #define PAL_OSF1_rti 0x003f /* P */
603 #define PAL_OSF1_callsys 0x0083 /* U */
604 #define PAL_OSF1_imb 0x0086 /* U */
605
606
607 /*
608 * System call glue.
609 */
610 #define SYSCALLNUM(name) \
611 ___CONCAT(SYS_,name)
612
613 #define CALLSYS_NOERROR(name) \
614 ldiq v0, SYSCALLNUM(name); \
615 call_pal PAL_OSF1_callsys
616
617 /*
618 * Load the global pointer.
619 */
620 #define LDGP(reg) \
621 ldgp gp, 0(reg)
622
623 /*
624 * WEAK_ALIAS: create a weak alias (ELF only).
625 */
626 #ifdef __ELF__
627 #define WEAK_ALIAS(alias,sym) \
628 .weak alias; \
629 alias = sym
630 #endif
631
632 /*
633 * Kernel RCS ID tag and copyright macros
634 */
635
636 #ifdef _KERNEL
637
638 #define __KERNEL_SECTIONSTRING(_sec, _str) \
639 .section _sec ; .asciz _str ; .text
640
641 #ifdef __ELF__
642
643 #define __KERNEL_RCSID(_n, _s) __KERNEL_SECTIONSTRING(.ident, _s)
644 #define __KERNEL_COPYRIGHT(_n, _s) __KERNEL_SECTIONSTRING(.copyright, _s)
645
646 #else /* __ELF__ */
647
648 #define __KERNEL_RCSID(_n, _s) __KERNEL_SECTIONSTRING(.text, _s)
649 #define __KERNEL_COPYRIGHT(_n, _s) __KERNEL_SECTIONSTRING(.text, _s)
650
651 #endif /* __ELF__ */
652
653 #ifdef NO_KERNEL_RCSIDS
654 #undef __KERNEL_RCSID
655 #define __KERNEL_RCSID(_n, _s) /* nothing */
656 #endif
657
658 #endif /* _KERNEL */
659