Home | History | Annotate | Line # | Download | only in include
asm.h revision 1.35
      1 /* $NetBSD: asm.h,v 1.35 2017/01/14 16:15:10 martin 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	/* (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 #undef __CONCAT
    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 (at) 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 LINUX_SYSCALLNUM(name)					\
    602 	___CONCAT(LINUX_SYS_,name)
    603 
    604 #define LINUX_CALLSYS_NOERROR(name)				\
    605 	ldiq	v0, LINUX_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.
    616  */
    617 #define WEAK_ALIAS(alias,sym)					\
    618 	.weak alias;						\
    619 	alias = sym
    620 
    621 /*
    622  * STRONG_ALIAS: create a strong alias.
    623  */
    624 #define STRONG_ALIAS(alias,sym)					\
    625 	.globl alias;						\
    626 	alias = sym
    627 
    628 /*
    629  * WARN_REFERENCES: create a warning if the specified symbol is referenced.
    630  */
    631 #ifdef __STDC__
    632 #define	WARN_REFERENCES(sym,msg)					\
    633 	.pushsection .gnu.warning. ## sym;				\
    634 	.ascii msg;							\
    635 	.popsection
    636 #else
    637 #define	WARN_REFERENCES(sym,msg)					\
    638 	.pushsection .gnu.warning./**/sym;				\
    639 	.ascii msg;							\
    640 	.popsection
    641 #endif /* __STDC__ */
    642 
    643 /*
    644  * Kernel RCS ID tag and copyright macros
    645  */
    646 #undef __SECTIONSTRING
    647 #define	__SECTIONSTRING(_sec, _str)				\
    648 	.pushsection _sec ; .asciz _str ; .popsection
    649 
    650 #ifdef _KERNEL
    651 
    652 #define	__KERNEL_RCSID(_n, _s)		__SECTIONSTRING(.ident, _s)
    653 #define	__KERNEL_COPYRIGHT(_n, _s)	__SECTIONSTRING(.copyright, _s)
    654 
    655 #ifdef NO_KERNEL_RCSIDS
    656 #undef __KERNEL_RCSID
    657 #define	__KERNEL_RCSID(_n, _s)		/* nothing */
    658 #endif
    659 
    660 #if defined(MULTIPROCESSOR)
    661 
    662 /*
    663  * Get various per-cpu values.  A pointer to our cpu_info structure
    664  * is stored in SysValue.  These macros clobber v0, t0, t8..t11.
    665  *
    666  * All return values are in v0.
    667  */
    668 #define	GET_CPUINFO		call_pal PAL_OSF1_rdval
    669 
    670 #define	GET_CURLWP							\
    671 	call_pal PAL_OSF1_rdval					;	\
    672 	addq	v0, CPU_INFO_CURLWP, v0
    673 
    674 #define	GET_FPCURLWP							\
    675 	call_pal PAL_OSF1_rdval					;	\
    676 	addq	v0, CPU_INFO_FPCURLWP, v0
    677 
    678 #define	GET_CURPCB							\
    679 	call_pal PAL_OSF1_rdval					;	\
    680 	addq	v0, CPU_INFO_CURPCB, v0
    681 
    682 #define	GET_IDLE_PCB(reg)						\
    683 	call_pal PAL_OSF1_rdval					;	\
    684 	ldq	reg, CPU_INFO_IDLE_PCB_PADDR(v0)
    685 
    686 #else	/* if not MULTIPROCESSOR... */
    687 
    688 IMPORT(cpu_info_primary, CPU_INFO_SIZEOF)
    689 
    690 #define	GET_CPUINFO		lda v0, cpu_info_primary
    691 
    692 #define	GET_CURLWP		lda v0, cpu_info_primary + CPU_INFO_CURLWP
    693 
    694 #define	GET_FPCURLWP		lda v0, cpu_info_primary + CPU_INFO_FPCURLWP
    695 
    696 #define	GET_CURPCB		lda v0, cpu_info_primary + CPU_INFO_CURPCB
    697 
    698 #define	GET_IDLE_PCB(reg)						\
    699 	lda	reg, cpu_info_primary				;	\
    700 	ldq	reg, CPU_INFO_IDLE_PCB_PADDR(reg)
    701 #endif /* MULTIPROCESSOR */
    702 #else
    703 #define	RCSID(_s)		__SECTIONSTRING(.ident, _s)
    704 
    705 #endif /* _KERNEL */
    706