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