Home | History | Annotate | Line # | Download | only in include
      1 /* $NetBSD: asm.h,v 1.46 2024/06/09 22:35:37 riastradh 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 #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 (at) 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  * STRONG_ALIAS: create a strong alias.
    622  */
    623 #define STRONG_ALIAS(alias,sym)					\
    624 	.globl alias;						\
    625 	alias = sym
    626 
    627 /*
    628  * WARN_REFERENCES: create a warning if the specified symbol is referenced.
    629  */
    630 #ifdef __STDC__
    631 #define	WARN_REFERENCES(sym,msg)					\
    632 	.pushsection .gnu.warning. ## sym;				\
    633 	.ascii msg;							\
    634 	.popsection
    635 #else
    636 #define	WARN_REFERENCES(sym,msg)					\
    637 	.pushsection .gnu.warning./**/sym;				\
    638 	.ascii msg;							\
    639 	.popsection
    640 #endif /* __STDC__ */
    641 
    642 /*
    643  * Kernel RCS ID tag and copyright macros
    644  */
    645 #define	__SECTIONSTRING(_sec, _str)				\
    646 	.pushsection _sec,"MS",@progbits,1;			\
    647 	.asciz _str;						\
    648 	.popsection
    649 
    650 #ifdef _KERNEL
    651 
    652 #ifdef _NETBSD_REVISIONID
    653 #define	__KERNEL_RCSID(_n, _s)						      \
    654 	__SECTIONSTRING(.ident, _s);					      \
    655 	__SECTIONSTRING(.ident,						      \
    656 	    "$" "NetBSD: " __FILE__ " " _NETBSD_REVISIONID " $")
    657 #else
    658 #define	__KERNEL_RCSID(_n, _s)		__SECTIONSTRING(.ident, _s)
    659 #endif
    660 #define	__KERNEL_COPYRIGHT(_n, _s)	__SECTIONSTRING(.copyright, _s)
    661 
    662 #ifdef NO_KERNEL_RCSIDS
    663 #undef __KERNEL_RCSID
    664 #define	__KERNEL_RCSID(_n, _s)		/* nothing */
    665 #endif
    666 
    667 #if defined(MULTIPROCESSOR)
    668 
    669 /*
    670  * Get various per-cpu values.  A pointer to our cpu_info structure
    671  * is stored in SysValue.  These macros clobber v0, t0, t8..t11.
    672  * SET_CURLWP also clobbers a0.
    673  *
    674  * All return values are in v0.
    675  */
    676 #define	GET_CURLWP							\
    677 	call_pal PAL_OSF1_rdval
    678 
    679 /*
    680  * Issue barriers to coordinate mutex_exit on this CPU with
    681  * mutex_vector_enter on another CPU.
    682  *
    683  * 1. Any prior mutex_exit by oldlwp must be visible to other
    684  *    CPUs before we set ci_curlwp := newlwp on this one,
    685  *    requiring a store-before-store barrier.
    686  *
    687  * 2. ci_curlwp := newlwp must be visible on all other CPUs
    688  *    before any subsequent mutex_exit by newlwp can even test
    689  *    whether there might be waiters, requiring a
    690  *    store-before-load barrier.
    691  *
    692  * See kern_mutex.c for details -- this is necessary for
    693  * adaptive mutexes to detect whether the lwp is on the CPU in
    694  * order to safely block without requiring atomic r/m/w in
    695  * mutex_exit.
    696  */
    697 #define	SET_CURLWP(r)							\
    698 	ldq	v0, L_CPU(r)					;	\
    699 	mov	r, a0						;	\
    700 	wmb	/* store-before-store XXX patch out if !MP? */	;	\
    701 	stq	r, CPU_INFO_CURLWP(v0)				;	\
    702 	mb	/* store-before-load XXX patch out if !MP? */	;	\
    703 	call_pal PAL_OSF1_wrval
    704 
    705 #else	/* if not MULTIPROCESSOR... */
    706 
    707 IMPORT(cpu_info_primary, CPU_INFO_SIZEOF)
    708 
    709 #define	GET_CURLWP		lda v0, cpu_info_primary	;	\
    710 				ldq v0, CPU_INFO_CURLWP(v0)
    711 
    712 #define	SET_CURLWP(r)		lda v0, cpu_info_primary 	;	\
    713 				stq r, CPU_INFO_CURLWP(v0)
    714 
    715 #endif /* MULTIPROCESSOR */
    716 
    717 #else /* !_KERNEL */
    718 
    719 #ifdef _NETBSD_REVISIONID
    720 #define	RCSID(_s)							      \
    721 	__SECTIONSTRING(.ident, _s);					      \
    722 	__SECTIONSTRING(.ident,						      \
    723 	    "$" "NetBSD: " __FILE__ " " _NETBSD_REVISIONID " $")
    724 #else
    725 #define	RCSID(_s)		__SECTIONSTRING(.ident, _s)
    726 #endif
    727 
    728 #endif /* _KERNEL */
    729