xref: /netbsd-src/sys/arch/mips/include/asm.h (revision 3816d47b2c42fcd6e549e3407f842a5b1a1d23ad)
1 /*	$NetBSD: asm.h,v 1.41 2009/12/14 00:46:04 matt Exp $	*/
2 
3 /*
4  * Copyright (c) 1992, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Ralph Campbell.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *	@(#)machAsmDefs.h	8.1 (Berkeley) 6/10/93
35  */
36 
37 /*
38  * machAsmDefs.h --
39  *
40  *	Macros used when writing assembler programs.
41  *
42  *	Copyright (C) 1989 Digital Equipment Corporation.
43  *	Permission to use, copy, modify, and distribute this software and
44  *	its documentation for any purpose and without fee is hereby granted,
45  *	provided that the above copyright notice appears in all copies.
46  *	Digital Equipment Corporation makes no representations about the
47  *	suitability of this software for any purpose.  It is provided "as is"
48  *	without express or implied warranty.
49  *
50  * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsmDefs.h,
51  *	v 1.2 89/08/15 18:28:24 rab Exp  SPRITE (DECWRL)
52  */
53 
54 #ifndef _MIPS_ASM_H
55 #define	_MIPS_ASM_H
56 
57 #include <machine/cdefs.h>	/* for API selection */
58 #include <mips/regdef.h>
59 
60 /*
61  * Define -pg profile entry code.
62  * Must always be noreorder, must never use a macro instruction
63  * Final addiu to t9 must always equal the size of this _KERN_MCOUNT
64  */
65 #define	_KERN_MCOUNT						\
66 	.set	push;						\
67 	.set	noreorder;					\
68 	.set	noat;						\
69 	subu	sp,sp,16;					\
70 	sw	t9,12(sp);					\
71 	move	AT,ra;						\
72 	lui	t9,%hi(_mcount); 				\
73 	addiu	t9,t9,%lo(_mcount);				\
74 	jalr	t9;						\
75 	nop;							\
76 	lw	t9,4(sp);					\
77 	addiu	sp,sp,8;					\
78 	addiu	t9,t9,40;					\
79 	.set	pop;
80 
81 #ifdef GPROF
82 #define	MCOUNT _KERN_MCOUNT
83 #else
84 #define	MCOUNT
85 #endif
86 
87 #ifdef __NO_LEADING_UNDERSCORES__
88 # define _C_LABEL(x)	x
89 #else
90 # ifdef __STDC__
91 #  define _C_LABEL(x)	_ ## x
92 # else
93 #  define _C_LABEL(x)	_/**/x
94 # endif
95 #endif
96 
97 #ifdef USE_AENT
98 #define	AENT(x)				\
99 	.aent	x, 0
100 #else
101 #define	AENT(x)
102 #endif
103 
104 /*
105  * WEAK_ALIAS: create a weak alias.
106  */
107 #define	WEAK_ALIAS(alias,sym)						\
108 	.weak alias;							\
109 	alias = sym
110 /*
111  * STRONG_ALIAS: create a strong alias.
112  */
113 #define	STRONG_ALIAS(alias,sym)						\
114 	.globl alias;							\
115 	alias = sym
116 
117 /*
118  * WARN_REFERENCES: create a warning if the specified symbol is referenced.
119  */
120 #ifdef __STDC__
121 #define	WARN_REFERENCES(_sym,_msg)				\
122 	.section .gnu.warning. ## _sym ; .ascii _msg ; .text
123 #else
124 #define	WARN_REFERENCES(_sym,_msg)				\
125 	.section .gnu.warning./**/_sym ; .ascii _msg ; .text
126 #endif /* __STDC__ */
127 
128 /*
129  * LEAF
130  *	A leaf routine does
131  *	- call no other function,
132  *	- never use any register that callee-saved (S0-S8), and
133  *	- not use any local stack storage.
134  */
135 #define	LEAF(x)				\
136 	.globl	_C_LABEL(x);		\
137 	.ent	_C_LABEL(x), 0;		\
138 _C_LABEL(x): ;				\
139 	.frame sp, 0, ra;		\
140 	MCOUNT
141 
142 /*
143  * LEAF_NOPROFILE
144  *	No profilable leaf routine.
145  */
146 #define	LEAF_NOPROFILE(x)		\
147 	.globl	_C_LABEL(x);		\
148 	.ent	_C_LABEL(x), 0;		\
149 _C_LABEL(x): ;				\
150 	.frame	sp, 0, ra
151 
152 /*
153  * STATIC_LEAF
154  *	Declare a local leaf function.
155  */
156 #define	STATIC_LEAF(x)			\
157 	.ent	_C_LABEL(x), 0;		\
158 _C_LABEL(x): ;				\
159 	.frame sp, 0, ra;		\
160 	MCOUNT
161 
162 /*
163  * XLEAF
164  *	declare alternate entry to leaf routine
165  */
166 #define	XLEAF(x)			\
167 	.globl	_C_LABEL(x);		\
168 	AENT (_C_LABEL(x));		\
169 _C_LABEL(x):
170 
171 /*
172  * STATIC_XLEAF
173  *	declare alternate entry to a static leaf routine
174  */
175 #define	STATIC_XLEAF(x)			\
176 	AENT (_C_LABEL(x));		\
177 _C_LABEL(x):
178 
179 /*
180  * NESTED
181  *	A function calls other functions and needs
182  *	therefore stack space to save/restore registers.
183  */
184 #define	NESTED(x, fsize, retpc)		\
185 	.globl	_C_LABEL(x);		\
186 	.ent	_C_LABEL(x), 0; 	\
187 _C_LABEL(x): ;				\
188 	.frame	sp, fsize, retpc;	\
189 	MCOUNT
190 
191 /*
192  * NESTED_NOPROFILE(x)
193  *	No profilable nested routine.
194  */
195 #define	NESTED_NOPROFILE(x, fsize, retpc)	\
196 	.globl	_C_LABEL(x);		\
197 	.ent	_C_LABEL(x), 0;		\
198 _C_LABEL(x): ;				\
199 	.frame	sp, fsize, retpc
200 
201 /*
202  * XNESTED
203  *	declare alternate entry point to nested routine.
204  */
205 #define	XNESTED(x)			\
206 	.globl	_C_LABEL(x);		\
207 	AENT (_C_LABEL(x));		\
208 _C_LABEL(x):
209 
210 /*
211  * END
212  *	Mark end of a procedure.
213  */
214 #define	END(x) \
215 	.end _C_LABEL(x);		\
216 	.size _C_LABEL(x), . - _C_LABEL(x)
217 
218 /*
219  * IMPORT -- import external symbol
220  */
221 #define	IMPORT(sym, size)		\
222 	.extern _C_LABEL(sym),size
223 
224 /*
225  * EXPORT -- export definition of symbol
226  */
227 #define	EXPORT(x)			\
228 	.globl	_C_LABEL(x);		\
229 _C_LABEL(x):
230 
231 /*
232  * VECTOR
233  *	exception vector entrypoint
234  *	XXX: regmask should be used to generate .mask
235  */
236 #define	VECTOR(x, regmask)		\
237 	.ent	_C_LABEL(x),0;		\
238 	EXPORT(x);			\
239 
240 #ifdef __STDC__
241 #define	VECTOR_END(x)			\
242 	EXPORT(x ## End);		\
243 	END(x)
244 #else
245 #define	VECTOR_END(x)			\
246 	EXPORT(x/**/End);		\
247 	END(x)
248 #endif
249 
250 /*
251  * Macros to panic and printf from assembly language.
252  */
253 #define	PANIC(msg)			\
254 	PTR_LA	a0, 9f;			\
255 	jal	_C_LABEL(panic);	\
256 	nop;				\
257 	MSG(msg)
258 
259 #define	PRINTF(msg)			\
260 	PTR_LA	a0, 9f;			\
261 	jal	_C_LABEL(printf);	\
262 	nop;				\
263 	MSG(msg)
264 
265 #define	MSG(msg)			\
266 	.rdata;				\
267 9:	.asciiz	msg;			\
268 	.text
269 
270 #define	ASMSTR(str)			\
271 	.asciiz str;			\
272 	.align	3
273 
274 #define	RCSID(name)	.pushsection ".ident"; .asciz name; .popsection
275 
276 /*
277  * XXX retain dialects XXX
278  */
279 #define	ALEAF(x)			XLEAF(x)
280 #define	NLEAF(x)			LEAF_NOPROFILE(x)
281 #define	NON_LEAF(x, fsize, retpc)	NESTED(x, fsize, retpc)
282 #define	NNON_LEAF(x, fsize, retpc)	NESTED_NOPROFILE(x, fsize, retpc)
283 
284 #if defined(__mips_o32)
285 #define	SZREG	4
286 #else
287 #define	SZREG	8
288 #endif
289 
290 #if defined(__mips_o32) || defined(__mips_o64)
291 #define	ALSK	7		/* stack alignment */
292 #define	ALMASK	-7		/* stack alignment */
293 #define	SZFPREG	4
294 #define	FP_L	lwc1
295 #define	FP_S	swc1
296 #else
297 #define	ALSK	15		/* stack alignment */
298 #define	ALMASK	-15		/* stack alignment */
299 #define	SZFPREG	8
300 #define	FP_L	ldc1
301 #define	FP_S	sdc1
302 #endif
303 
304 /*
305  *  standard callframe {
306  *	register_t cf_pad[N];		o32/64 (N=0), n32 (N=1) n64 (N=1)
307  *  	register_t cf_args[4];		arg0 - arg3 (only on o32 and o64)
308  *  	register_t cf_gp;		global pointer (only on n32 and n64)
309  *  	register_t cf_sp;		frame pointer
310  *  	register_t cf_ra;		return address
311  *  };
312  */
313 #if defined(__mips_o32) || defined(__mips_o64)
314 #define	CALLFRAME_SIZ	(SZREG * (4 + 2))
315 #define	CALLFRAME_S0	0
316 #elif defined(__mips_n32) || defined(__mips_n64)
317 #define	CALLFRAME_SIZ	(SZREG * 4)
318 #define	CALLFRAME_S0	(CALLFRAME_SIZ - 4 * SZREG)
319 #endif
320 #ifndef _KERNEL
321 #define	CALLFRAME_GP	(CALLFRAME_SIZ - 3 * SZREG)
322 #endif
323 #define	CALLFRAME_SP	(CALLFRAME_SIZ - 2 * SZREG)
324 #define	CALLFRAME_RA	(CALLFRAME_SIZ - 1 * SZREG)
325 
326 /*
327  * While it would be nice to be compatible with the SGI
328  * REG_L and REG_S macros, because they do not take parameters, it
329  * is impossible to use them with the _MIPS_SIM_ABIX32 model.
330  *
331  * These macros hide the use of mips3 instructions from the
332  * assembler to prevent the assembler from generating 64-bit style
333  * ABI calls.
334  */
335 #if _MIPS_SZPTR == 32
336 #define	PTR_ADD		add
337 #define	PTR_ADDI	addi
338 #define	PTR_ADDU	addu
339 #define	PTR_ADDIU	addiu
340 #define	PTR_SUB		add
341 #define	PTR_SUBI	subi
342 #define	PTR_SUBU	subu
343 #define	PTR_SUBIU	subu
344 #define	PTR_L		lw
345 #define	PTR_LA		la
346 #define	PTR_S		sw
347 #define	PTR_SLL		sll
348 #define	PTR_SLLV	sllv
349 #define	PTR_SRL		srl
350 #define	PTR_SRLV	srlv
351 #define	PTR_SRA		sra
352 #define	PTR_SRAV	srav
353 #define	PTR_LL		ll
354 #define	PTR_SC		sc
355 #define	PTR_WORD	.word
356 #define	PTR_SCALESHIFT	2
357 #else /* _MIPS_SZPTR == 64 */
358 #define	PTR_ADD		dadd
359 #define	PTR_ADDI	daddi
360 #define	PTR_ADDU	daddu
361 #define	PTR_ADDIU	daddiu
362 #define	PTR_SUB		dadd
363 #define	PTR_SUBI	dsubi
364 #define	PTR_SUBU	dsubu
365 #define	PTR_SUBIU	dsubu
366 #define	PTR_L		ld
367 #define	PTR_LA		dla
368 #define	PTR_S		sd
369 #define	PTR_SLL		dsll
370 #define	PTR_SLLV	dsllv
371 #define	PTR_SRL		dsrl
372 #define	PTR_SRLV	dsrlv
373 #define	PTR_SRA		dsra
374 #define	PTR_SRAV	dsrav
375 #define	PTR_LL		lld
376 #define	PTR_SC		scd
377 #define	PTR_WORD	.dword
378 #define	PTR_SCALESHIFT	3
379 #endif /* _MIPS_SZPTR == 64 */
380 
381 #if _MIPS_SZINT == 32
382 #define	INT_ADD		add
383 #define	INT_ADDI	addi
384 #define	INT_ADDU	addu
385 #define	INT_ADDIU	addiu
386 #define	INT_SUB		add
387 #define	INT_SUBI	subi
388 #define	INT_SUBU	subu
389 #define	INT_SUBIU	subu
390 #define	INT_L		lw
391 #define	INT_LA		la
392 #define	INT_S		sw
393 #define	INT_SLL		sll
394 #define	INT_SLLV	sllv
395 #define	INT_SRL		srl
396 #define	INT_SRLV	srlv
397 #define	INT_SRA		sra
398 #define	INT_SRAV	srav
399 #define	INT_LL		ll
400 #define	INT_SC		sc
401 #define	INT_WORD	.word
402 #define	INT_SCALESHIFT	2
403 #else
404 #define	INT_ADD		dadd
405 #define	INT_ADDI	daddi
406 #define	INT_ADDU	daddu
407 #define	INT_ADDIU	daddiu
408 #define	INT_SUB		dadd
409 #define	INT_SUBI	dsubi
410 #define	INT_SUBU	dsubu
411 #define	INT_SUBIU	dsubu
412 #define	INT_L		ld
413 #define	INT_LA		dla
414 #define	INT_S		sd
415 #define	INT_SLL		dsll
416 #define	INT_SLLV	dsllv
417 #define	INT_SRL		dsrl
418 #define	INT_SRLV	dsrlv
419 #define	INT_SRA		dsra
420 #define	INT_SRAV	dsrav
421 #define	INT_LL		lld
422 #define	INT_SC		scd
423 #define	INT_WORD	.dword
424 #define	INT_SCALESHIFT	3
425 #endif
426 
427 #if _MIPS_SZLONG == 32
428 #define	LONG_ADD	add
429 #define	LONG_ADDI	addi
430 #define	LONG_ADDU	addu
431 #define	LONG_ADDIU	addiu
432 #define	LONG_SUB	add
433 #define	LONG_SUBI	subi
434 #define	LONG_SUBU	subu
435 #define	LONG_SUBIU	subu
436 #define	LONG_L		lw
437 #define	LONG_LA		la
438 #define	LONG_S		sw
439 #define	LONG_SLL	sll
440 #define	LONG_SLLV	sllv
441 #define	LONG_SRL	srl
442 #define	LONG_SRLV	srlv
443 #define	LONG_SRA	sra
444 #define	LONG_SRAV	srav
445 #define	LONG_LL		ll
446 #define	LONG_SC		sc
447 #define	LONG_WORD	.word
448 #define	LONG_SCALESHIFT	2
449 #else
450 #define	LONG_ADD	dadd
451 #define	LONG_ADDI	daddi
452 #define	LONG_ADDU	daddu
453 #define	LONG_ADDIU	daddiu
454 #define	LONG_SUB	dadd
455 #define	LONG_SUBI	dsubi
456 #define	LONG_SUBU	dsubu
457 #define	LONG_SUBIU	dsubu
458 #define	LONG_L		ld
459 #define	LONG_LA		dla
460 #define	LONG_S		sd
461 #define	LONG_SLL	dsll
462 #define	LONG_SLLV	dsllv
463 #define	LONG_SRL	dsrl
464 #define	LONG_SRLV	dsrlv
465 #define	LONG_SRA	dsra
466 #define	LONG_SRAV	dsrav
467 #define	LONG_LL		lld
468 #define	LONG_SC		scd
469 #define	LONG_WORD	.dword
470 #define	LONG_SCALESHIFT	3
471 #endif
472 
473 #if SZREG == 4
474 #define	REG_L		lw
475 #define	REG_S		sw
476 #define	REG_LI		li
477 #define	REG_ADDU	addu
478 #define	REG_SLL		sll
479 #define	REG_SLLV	sllv
480 #define	REG_SRL		srl
481 #define	REG_SRLV	srlv
482 #define	REG_SRA		sra
483 #define	REG_SRAV	srav
484 #define	REG_LL		ll
485 #define	REG_SC		sc
486 #define	REG_SCALESHIFT	2
487 #else
488 #define	REG_L		ld
489 #define	REG_S		sd
490 #define	REG_LI		dli
491 #define	REG_ADDU	daddu
492 #define	REG_SLL		dsll
493 #define	REG_SLLV	dsllv
494 #define	REG_SRL		dsrl
495 #define	REG_SRLV	dsrlv
496 #define	REG_SRA		dsra
497 #define	REG_SRAV	dsrav
498 #define	REG_LL		lld
499 #define	REG_SC		scd
500 #define	REG_SCALESHIFT	3
501 #endif
502 
503 #if _MIPS_ISA == _MIPS_ISA_MIPS1 || _MIPS_ISA == _MIPS_ISA_MIPS2 || \
504     _MIPS_ISA == _MIPS_ISA_MIPS32
505 #define	MFC0		mfc0
506 #define	MTC0		mtc0
507 #endif
508 #if _MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4 || \
509     _MIPS_ISA == _MIPS_ISA_MIPS64
510 #define	MFC0		dmfc0
511 #define	MTC0		dmtc0
512 #endif
513 
514 #if defined(__mips_o32) || defined(__mips_o64)
515 
516 #ifdef __ABICALLS__
517 #define	CPRESTORE(r)	.cprestore r
518 #define	CPLOAD(r)	.cpload r
519 #else
520 #define	CPRESTORE(r)	/* not needed */
521 #define	CPLOAD(r)	/* not needed */
522 #endif
523 
524 #define	SETUP_GP	\
525 			.set push;				\
526 			.set noreorder;				\
527 			.cpload	t9;				\
528 			.set pop
529 #define	SETUP_GPX(r)	\
530 			.set push;				\
531 			.set noreorder;				\
532 			move	r,ra;	/* save old ra */	\
533 			bal	7f;				\
534 			nop;					\
535 		7:	.cpload	ra;				\
536 			move	ra,r;				\
537 			.set pop
538 #define	SETUP_GPX_L(r,lbl)	\
539 			.set push;				\
540 			.set noreorder;				\
541 			move	r,ra;	/* save old ra */	\
542 			bal	lbl;				\
543 			nop;					\
544 		lbl:	.cpload	ra;				\
545 			move	ra,r;				\
546 			.set pop
547 #define	SAVE_GP(x)	.cprestore x
548 
549 #define	SETUP_GP64(a,b)		/* n32/n64 specific */
550 #define	SETUP_GP64_R(a,b)	/* n32/n64 specific */
551 #define	SETUP_GPX64(a,b)	/* n32/n64 specific */
552 #define	SETUP_GPX64_L(a,b,c)	/* n32/n64 specific */
553 #define	RESTORE_GP64		/* n32/n64 specific */
554 #define	USE_ALT_CP(a)		/* n32/n64 specific */
555 #endif /* __mips_o32 || __mips_o64 */
556 
557 #if defined(__mips_o32) || defined(__mips_o64)
558 #define	REG_PROLOGUE	.set push
559 #define	REG_EPILOGUE	.set pop
560 #endif
561 #if defined(__mips_n32) || defined(__mips_n64)
562 #define	REG_PROLOGUE	.set push ; .set mips3
563 #define	REG_EPILOGUE	.set pop
564 #endif
565 
566 #if defined(__mips_n32) || defined(__mips_n64)
567 #define	SETUP_GP		/* o32 specific */
568 #define	SETUP_GPX(r)		/* o32 specific */
569 #define	SETUP_GPX_L(r,lbl)	/* o32 specific */
570 #define	SAVE_GP(x)		/* o32 specific */
571 #define	SETUP_GP64(a,b)		.cpsetup $25, a, b
572 #define	SETUP_GPX64(a,b)	\
573 				.set push;			\
574 				move	b,ra;			\
575 				.set noreorder;			\
576 				bal	7f;			\
577 				nop;				\
578 			7:	.set pop;			\
579 				.cpsetup ra, a, 7b;		\
580 				move	ra,b
581 #define	SETUP_GPX64_L(a,b,c)	\
582 				.set push;			\
583 				move	b,ra;			\
584 				.set noreorder;			\
585 				bal	c;			\
586 				nop;				\
587 			c:	.set pop;			\
588 				.cpsetup ra, a, c;		\
589 				move	ra,b
590 #define	RESTORE_GP64		.cpreturn
591 #define	USE_ALT_CP(a)		.cplocal a
592 #endif	/* __mips_n32 || __mips_n64 */
593 
594 /*
595  * The DYNAMIC_STATUS_MASK option adds an additional masking operation
596  * when updating the hardware interrupt mask in the status register.
597  *
598  * This is useful for platforms that need to at run-time mask
599  * interrupts based on motherboard configuration or to handle
600  * slowly clearing interrupts.
601  *
602  * XXX this is only currently implemented for mips3.
603  */
604 #ifdef MIPS_DYNAMIC_STATUS_MASK
605 #define	DYNAMIC_STATUS_MASK(sr,scratch)	\
606 	lw	scratch, mips_dynamic_status_mask; \
607 	and	sr, sr, scratch
608 
609 #define	DYNAMIC_STATUS_MASK_TOUSER(sr,scratch1)		\
610 	ori	sr, (MIPS_INT_MASK | MIPS_SR_INT_IE);	\
611 	DYNAMIC_STATUS_MASK(sr,scratch1)
612 #else
613 #define	DYNAMIC_STATUS_MASK(sr,scratch)
614 #define	DYNAMIC_STATUS_MASK_TOUSER(sr,scratch1)
615 #endif
616 
617 /* See lock_stubs.S. */
618 #define	MIPS_LOCK_RAS_SIZE	128
619 
620 #define	CPUVAR(off) _C_LABEL(cpu_info_store)+__CONCAT(CPU_INFO_,off)
621 
622 #endif /* _MIPS_ASM_H */
623