1/*	$NetBSD: asm.h,v 1.29 2000/12/14 21:29:51 jeffs Exp $	*/
2
3/*
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Copyright (c) 1992, 1993
7 *	The Regents of the University of California.  All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * Ralph Campbell.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 *	@(#)machAsmDefs.h	8.1 (Berkeley) 6/10/93
37 *	JNPR: asm.h,v 1.10 2007/08/09 11:23:32 katta
38 * $FreeBSD$
39 */
40
41/*
42 * machAsmDefs.h --
43 *
44 *	Macros used when writing assembler programs.
45 *
46 *	Copyright (C) 1989 Digital Equipment Corporation.
47 *	Permission to use, copy, modify, and distribute this software and
48 *	its documentation for any purpose and without fee is hereby granted,
49 *	provided that the above copyright notice appears in all copies.
50 *	Digital Equipment Corporation makes no representations about the
51 *	suitability of this software for any purpose.  It is provided "as is"
52 *	without express or implied warranty.
53 *
54 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsmDefs.h,
55 *	v 1.2 89/08/15 18:28:24 rab Exp  SPRITE (DECWRL)
56 */
57
58#ifndef _MACHINE_ASM_H_
59#define	_MACHINE_ASM_H_
60
61#include <machine/abi.h>
62#include <machine/regdef.h>
63#include <machine/endian.h>
64#include <machine/cdefs.h>
65
66#undef __FBSDID
67#if !defined(lint) && !defined(STRIP_FBSDID)
68#define	__FBSDID(s)	.ident s
69#else
70#define	__FBSDID(s)	/* nothing */
71#endif
72
73/*
74 * Define -pg profile entry code.
75 * Must always be noreorder, must never use a macro instruction
76 * Final addiu to t9 must always equal the size of this _KERN_MCOUNT
77 */
78#define	_KERN_MCOUNT			\
79	.set	push;			\
80	.set	noreorder;		\
81	.set	noat;			\
82	subu	sp,sp,16;		\
83	sw	t9,12(sp);		\
84	move	AT,ra;			\
85	lui	t9,%hi(_mcount);	\
86	addiu	t9,t9,%lo(_mcount);	\
87	jalr	t9;			\
88	nop;				\
89	lw	t9,4(sp);		\
90	addiu	sp,sp,8;		\
91	addiu	t9,t9,40;		\
92	.set	pop;
93
94#ifdef GPROF
95#define	MCOUNT _KERN_MCOUNT
96#else
97#define	MCOUNT
98#endif
99
100#define	_C_LABEL(x)	x
101
102#ifdef USE_AENT
103#define	AENT(x)		\
104	.aent	x, 0
105#else
106#define	AENT(x)
107#endif
108
109/*
110 * WARN_REFERENCES: create a warning if the specified symbol is referenced
111 */
112#define	WARN_REFERENCES(_sym,_msg)				\
113	.section .gnu.warning. ## _sym ; .ascii _msg ; .text
114
115#ifdef __ELF__
116# define _C_LABEL(x)    x
117#else
118#  define _C_LABEL(x)   _ ## x
119#endif
120
121/*
122 * WEAK_ALIAS: create a weak alias.
123 */
124#define	WEAK_ALIAS(alias,sym)						\
125	.weak alias;							\
126	alias = sym
127
128/*
129 * STRONG_ALIAS: create a strong alias.
130 */
131#define STRONG_ALIAS(alias,sym)						\
132	.globl alias;							\
133	alias = sym
134
135#define	GLOBAL(sym)						\
136	.globl sym; sym:
137
138#define	ENTRY(sym)						\
139	.text; .globl sym; .ent sym; sym:
140
141#define	ASM_ENTRY(sym)						\
142	.text; .globl sym; .type sym,@function; sym:
143
144/*
145 * LEAF
146 *	A leaf routine does
147 *	- call no other function,
148 *	- never use any register that callee-saved (S0-S8), and
149 *	- not use any local stack storage.
150 */
151#define	LEAF(x)			\
152	.globl	_C_LABEL(x);	\
153	.ent	_C_LABEL(x), 0;	\
154_C_LABEL(x): ;			\
155	.frame sp, 0, ra;	\
156	MCOUNT
157
158/*
159 * LEAF_NOPROFILE
160 *	No profilable leaf routine.
161 */
162#define	LEAF_NOPROFILE(x)	\
163	.globl	_C_LABEL(x);	\
164	.ent	_C_LABEL(x), 0;	\
165_C_LABEL(x): ;			\
166	.frame	sp, 0, ra
167
168/*
169 * XLEAF
170 *	declare alternate entry to leaf routine
171 */
172#define	XLEAF(x)		\
173	.globl	_C_LABEL(x);	\
174	AENT (_C_LABEL(x));	\
175_C_LABEL(x):
176
177/*
178 * NESTED
179 *	A function calls other functions and needs
180 *	therefore stack space to save/restore registers.
181 */
182#define	NESTED(x, fsize, retpc)		\
183	.globl	_C_LABEL(x);		\
184	.ent	_C_LABEL(x), 0;		\
185_C_LABEL(x): ;				\
186	.frame	sp, fsize, retpc;	\
187	MCOUNT
188
189/*
190 * NESTED_NOPROFILE(x)
191 *	No profilable nested routine.
192 */
193#define	NESTED_NOPROFILE(x, fsize, retpc)	\
194	.globl	_C_LABEL(x);			\
195	.ent	_C_LABEL(x), 0;			\
196_C_LABEL(x): ;					\
197	.frame	sp, fsize, retpc
198
199/*
200 * XNESTED
201 *	declare alternate entry point to nested routine.
202 */
203#define	XNESTED(x)		\
204	.globl	_C_LABEL(x);	\
205	AENT (_C_LABEL(x));	\
206_C_LABEL(x):
207
208/*
209 * END
210 *	Mark end of a procedure.
211 */
212#define	END(x)			\
213	.end _C_LABEL(x)
214
215/*
216 * IMPORT -- import external symbol
217 */
218#define	IMPORT(sym, size)	\
219	.extern _C_LABEL(sym),size
220
221/*
222 * EXPORT -- export definition of symbol
223 */
224#define	EXPORT(x)		\
225	.globl	_C_LABEL(x);	\
226_C_LABEL(x):
227
228/*
229 * VECTOR
230 *	exception vector entrypoint
231 *	XXX: regmask should be used to generate .mask
232 */
233#define	VECTOR(x, regmask)	\
234	.ent	_C_LABEL(x),0;	\
235	EXPORT(x);		\
236
237#define	VECTOR_END(x)		\
238	EXPORT(x ## End);	\
239	END(x)
240
241/*
242 * Macros to panic and printf from assembly language.
243 */
244#define	PANIC(msg)			\
245	PTR_LA	a0, 9f;			\
246	jal	_C_LABEL(panic);	\
247	nop;				\
248	MSG(msg)
249
250#define	PANIC_KSEG0(msg, reg)	PANIC(msg)
251
252#define	PRINTF(msg)			\
253	PTR_LA	a0, 9f;			\
254	jal	_C_LABEL(printf);	\
255	nop;				\
256	MSG(msg)
257
258#define	MSG(msg)			\
259	.rdata;				\
2609:	.asciiz	msg;			\
261	.text
262
263#define	ASMSTR(str)			\
264	.asciiz str;			\
265	.align	3
266
267#if defined(__mips_o32) || defined(__mips_o64)
268#define	ALSK	7		/* stack alignment */
269#define	ALMASK	-7		/* stack alignment */
270#define	SZFPREG	4
271#define	FP_L	lwc1
272#define	FP_S	swc1
273#else
274#define	ALSK	15		/* stack alignment */
275#define	ALMASK	-15		/* stack alignment */
276#define	SZFPREG	8
277#define	FP_L	ldc1
278#define	FP_S	sdc1
279#endif
280
281/*
282 *   Endian-independent assembly-code aliases for unaligned memory accesses.
283 */
284#if _BYTE_ORDER == _LITTLE_ENDIAN
285# define LWHI lwr
286# define LWLO lwl
287# define SWHI swr
288# define SWLO swl
289# if SZREG == 4
290#  define REG_LHI   lwr
291#  define REG_LLO   lwl
292#  define REG_SHI   swr
293#  define REG_SLO   swl
294# else
295#  define REG_LHI   ldr
296#  define REG_LLO   ldl
297#  define REG_SHI   sdr
298#  define REG_SLO   sdl
299# endif
300#endif
301
302#if _BYTE_ORDER == _BIG_ENDIAN
303# define LWHI lwl
304# define LWLO lwr
305# define SWHI swl
306# define SWLO swr
307# if SZREG == 4
308#  define REG_LHI   lwl
309#  define REG_LLO   lwr
310#  define REG_SHI   swl
311#  define REG_SLO   swr
312# else
313#  define REG_LHI   ldl
314#  define REG_LLO   ldr
315#  define REG_SHI   sdl
316#  define REG_SLO   sdr
317# endif
318#endif
319
320/*
321 * While it would be nice to be compatible with the SGI
322 * REG_L and REG_S macros, because they do not take parameters, it
323 * is impossible to use them with the _MIPS_SIM_ABIX32 model.
324 *
325 * These macros hide the use of mips3 instructions from the
326 * assembler to prevent the assembler from generating 64-bit style
327 * ABI calls.
328 */
329#if _MIPS_SZPTR == 32
330#define	PTR_ADD		add
331#define	PTR_ADDI	addi
332#define	PTR_ADDU	addu
333#define	PTR_ADDIU	addiu
334#define	PTR_SUB		add
335#define	PTR_SUBI	subi
336#define	PTR_SUBU	subu
337#define	PTR_SUBIU	subu
338#define	PTR_L		lw
339#define	PTR_LA		la
340#define	PTR_LI		li
341#define	PTR_S		sw
342#define	PTR_SLL		sll
343#define	PTR_SLLV	sllv
344#define	PTR_SRL		srl
345#define	PTR_SRLV	srlv
346#define	PTR_SRA		sra
347#define	PTR_SRAV	srav
348#define	PTR_LL		ll
349#define	PTR_SC		sc
350#define	PTR_WORD	.word
351#define	PTR_SCALESHIFT	2
352#else /* _MIPS_SZPTR == 64 */
353#define	PTR_ADD		dadd
354#define	PTR_ADDI	daddi
355#define	PTR_ADDU	daddu
356#define	PTR_ADDIU	daddiu
357#define	PTR_SUB		dadd
358#define	PTR_SUBI	dsubi
359#define	PTR_SUBU	dsubu
360#define	PTR_SUBIU	dsubu
361#define	PTR_L		ld
362#define	PTR_LA		dla
363#define	PTR_LI		dli
364#define	PTR_S		sd
365#define	PTR_SLL		dsll
366#define	PTR_SLLV	dsllv
367#define	PTR_SRL		dsrl
368#define	PTR_SRLV	dsrlv
369#define	PTR_SRA		dsra
370#define	PTR_SRAV	dsrav
371#define	PTR_LL		lld
372#define	PTR_SC		scd
373#define	PTR_WORD	.dword
374#define	PTR_SCALESHIFT	3
375#endif /* _MIPS_SZPTR == 64 */
376
377#if _MIPS_SZINT == 32
378#define	INT_ADD		add
379#define	INT_ADDI	addi
380#define	INT_ADDU	addu
381#define	INT_ADDIU	addiu
382#define	INT_SUB		add
383#define	INT_SUBI	subi
384#define	INT_SUBU	subu
385#define	INT_SUBIU	subu
386#define	INT_L		lw
387#define	INT_LA		la
388#define	INT_S		sw
389#define	INT_SLL		sll
390#define	INT_SLLV	sllv
391#define	INT_SRL		srl
392#define	INT_SRLV	srlv
393#define	INT_SRA		sra
394#define	INT_SRAV	srav
395#define	INT_LL		ll
396#define	INT_SC		sc
397#define	INT_WORD	.word
398#define	INT_SCALESHIFT	2
399#else
400#define	INT_ADD		dadd
401#define	INT_ADDI	daddi
402#define	INT_ADDU	daddu
403#define	INT_ADDIU	daddiu
404#define	INT_SUB		dadd
405#define	INT_SUBI	dsubi
406#define	INT_SUBU	dsubu
407#define	INT_SUBIU	dsubu
408#define	INT_L		ld
409#define	INT_LA		dla
410#define	INT_S		sd
411#define	INT_SLL		dsll
412#define	INT_SLLV	dsllv
413#define	INT_SRL		dsrl
414#define	INT_SRLV	dsrlv
415#define	INT_SRA		dsra
416#define	INT_SRAV	dsrav
417#define	INT_LL		lld
418#define	INT_SC		scd
419#define	INT_WORD	.dword
420#define	INT_SCALESHIFT	3
421#endif
422
423#if _MIPS_SZLONG == 32
424#define	LONG_ADD	add
425#define	LONG_ADDI	addi
426#define	LONG_ADDU	addu
427#define	LONG_ADDIU	addiu
428#define	LONG_SUB	add
429#define	LONG_SUBI	subi
430#define	LONG_SUBU	subu
431#define	LONG_SUBIU	subu
432#define	LONG_L		lw
433#define	LONG_LA		la
434#define	LONG_S		sw
435#define	LONG_SLL	sll
436#define	LONG_SLLV	sllv
437#define	LONG_SRL	srl
438#define	LONG_SRLV	srlv
439#define	LONG_SRA	sra
440#define	LONG_SRAV	srav
441#define	LONG_LL		ll
442#define	LONG_SC		sc
443#define	LONG_WORD	.word
444#define	LONG_SCALESHIFT	2
445#else
446#define	LONG_ADD	dadd
447#define	LONG_ADDI	daddi
448#define	LONG_ADDU	daddu
449#define	LONG_ADDIU	daddiu
450#define	LONG_SUB	dadd
451#define	LONG_SUBI	dsubi
452#define	LONG_SUBU	dsubu
453#define	LONG_SUBIU	dsubu
454#define	LONG_L		ld
455#define	LONG_LA		dla
456#define	LONG_S		sd
457#define	LONG_SLL	dsll
458#define	LONG_SLLV	dsllv
459#define	LONG_SRL	dsrl
460#define	LONG_SRLV	dsrlv
461#define	LONG_SRA	dsra
462#define	LONG_SRAV	dsrav
463#define	LONG_LL		lld
464#define	LONG_SC		scd
465#define	LONG_WORD	.dword
466#define	LONG_SCALESHIFT	3
467#endif
468
469#if SZREG == 4
470#define	REG_L		lw
471#define	REG_S		sw
472#define	REG_LI		li
473#define	REG_ADDU	addu
474#define	REG_SLL		sll
475#define	REG_SLLV	sllv
476#define	REG_SRL		srl
477#define	REG_SRLV	srlv
478#define	REG_SRA		sra
479#define	REG_SRAV	srav
480#define	REG_LL		ll
481#define	REG_SC		sc
482#define	REG_SCALESHIFT	2
483#else
484#define	REG_L		ld
485#define	REG_S		sd
486#define	REG_LI		dli
487#define	REG_ADDU	daddu
488#define	REG_SLL		dsll
489#define	REG_SLLV	dsllv
490#define	REG_SRL		dsrl
491#define	REG_SRLV	dsrlv
492#define	REG_SRA		dsra
493#define	REG_SRAV	dsrav
494#define	REG_LL		lld
495#define	REG_SC		scd
496#define	REG_SCALESHIFT	3
497#endif
498
499#if _MIPS_ISA == _MIPS_ISA_MIPS1 || _MIPS_ISA == _MIPS_ISA_MIPS2 || \
500    _MIPS_ISA == _MIPS_ISA_MIPS32
501#define	MFC0		mfc0
502#define	MTC0		mtc0
503#endif
504#if _MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4 || \
505    _MIPS_ISA == _MIPS_ISA_MIPS64
506#define	MFC0		dmfc0
507#define	MTC0		dmtc0
508#endif
509
510#if defined(__mips_o32) || defined(__mips_o64)
511
512#ifdef __ABICALLS__
513#define	CPRESTORE(r)	.cprestore r
514#define	CPLOAD(r)	.cpload r
515#else
516#define	CPRESTORE(r)	/* not needed */
517#define	CPLOAD(r)	/* not needed */
518#endif
519
520#define	SETUP_GP	\
521			.set push;				\
522			.set noreorder;				\
523			.cpload	t9;				\
524			.set pop
525#define	SETUP_GPX(r)	\
526			.set push;				\
527			.set noreorder;				\
528			move	r,ra;	/* save old ra */	\
529			bal	7f;				\
530			nop;					\
531		7:	.cpload	ra;				\
532			move	ra,r;				\
533			.set pop
534#define	SETUP_GPX_L(r,lbl)	\
535			.set push;				\
536			.set noreorder;				\
537			move	r,ra;	/* save old ra */	\
538			bal	lbl;				\
539			nop;					\
540		lbl:	.cpload	ra;				\
541			move	ra,r;				\
542			.set pop
543#define	SAVE_GP(x)	.cprestore x
544
545#define	SETUP_GP64(a,b)		/* n32/n64 specific */
546#define	SETUP_GP64_R(a,b)	/* n32/n64 specific */
547#define	SETUP_GPX64(a,b)	/* n32/n64 specific */
548#define	SETUP_GPX64_L(a,b,c)	/* n32/n64 specific */
549#define	RESTORE_GP64		/* n32/n64 specific */
550#define	USE_ALT_CP(a)		/* n32/n64 specific */
551#endif /* __mips_o32 || __mips_o64 */
552
553#if defined(__mips_o32) || defined(__mips_o64)
554#define	REG_PROLOGUE	.set push
555#define	REG_EPILOGUE	.set pop
556#endif
557#if defined(__mips_n32) || defined(__mips_n64)
558#define	REG_PROLOGUE	.set push ; .set mips3
559#define	REG_EPILOGUE	.set pop
560#endif
561
562#if defined(__mips_n32) || defined(__mips_n64)
563#define	SETUP_GP		/* o32 specific */
564#define	SETUP_GPX(r)		/* o32 specific */
565#define	SETUP_GPX_L(r,lbl)	/* o32 specific */
566#define	SAVE_GP(x)		/* o32 specific */
567#define	SETUP_GP64(a,b)		.cpsetup $25, a, b
568#define	SETUP_GPX64(a,b)	\
569				.set push;			\
570				move	b,ra;			\
571				.set noreorder;			\
572				bal	7f;			\
573				nop;				\
574			7:	.set pop;			\
575				.cpsetup ra, a, 7b;		\
576				move	ra,b
577#define	SETUP_GPX64_L(a,b,c)	\
578				.set push;			\
579				move	b,ra;			\
580				.set noreorder;			\
581				bal	c;			\
582				nop;				\
583			c:	.set pop;			\
584				.cpsetup ra, a, c;		\
585				move	ra,b
586#define	RESTORE_GP64		.cpreturn
587#define	USE_ALT_CP(a)		.cplocal a
588#endif	/* __mips_n32 || __mips_n64 */
589
590#define	GET_CPU_PCPU(reg)		\
591	PTR_L	reg, _C_LABEL(pcpup);
592
593/*
594 * Description of the setjmp buffer
595 *
596 * word  0	magic number	(dependant on creator)
597 *       1	RA
598 *       2	S0
599 *       3	S1
600 *       4	S2
601 *       5	S3
602 *       6	S4
603 *       7	S5
604 *       8	S6
605 *       9	S7
606 *       10	SP
607 *       11	S8
608 *       12	GP		(dependent on ABI)
609 *       13	signal mask	(dependant on magic)
610 *       14	(con't)
611 *       15	(con't)
612 *       16	(con't)
613 *
614 * The magic number number identifies the jmp_buf and
615 * how the buffer was created as well as providing
616 * a sanity check
617 *
618 */
619
620#define _JB_MAGIC__SETJMP	0xBADFACED
621#define _JB_MAGIC_SETJMP	0xFACEDBAD
622
623/* Valid for all jmp_buf's */
624
625#define _JB_MAGIC		0
626#define _JB_REG_RA		1
627#define _JB_REG_S0		2
628#define _JB_REG_S1		3
629#define _JB_REG_S2		4
630#define _JB_REG_S3		5
631#define _JB_REG_S4		6
632#define _JB_REG_S5		7
633#define _JB_REG_S6		8
634#define _JB_REG_S7		9
635#define _JB_REG_SP		10
636#define _JB_REG_S8		11
637#if defined(__mips_n32) || defined(__mips_n64)
638#define	_JB_REG_GP		12
639#endif
640
641/* Only valid with the _JB_MAGIC_SETJMP magic */
642
643#define _JB_SIGMASK		13
644#define	__JB_SIGMASK_REMAINDER	14	/* sigmask_t is 128-bits */
645
646#define _JB_FPREG_F20		15
647#define _JB_FPREG_F21		16
648#define _JB_FPREG_F22		17
649#define _JB_FPREG_F23		18
650#define _JB_FPREG_F24		19
651#define _JB_FPREG_F25		20
652#define _JB_FPREG_F26		21
653#define _JB_FPREG_F27		22
654#define _JB_FPREG_F28		23
655#define _JB_FPREG_F29		24
656#define _JB_FPREG_F30		25
657#define _JB_FPREG_F31		26
658#define _JB_FPREG_FCSR		27
659
660/*
661 * Various macros for dealing with TLB hazards
662 * (a) why so many?
663 * (b) when to use?
664 * (c) why not used everywhere?
665 */
666/*
667 * Assume that w alaways need nops to escape CP0 hazard
668 * TODO: Make hazard delays configurable. Stuck with 5 cycles on the moment
669 * For more info on CP0 hazards see Chapter 7 (p.99) of "MIPS32 Architecture
670 *    For Programmers Volume III: The MIPS32 Privileged Resource Architecture"
671 */
672#if defined(CPU_NLM)
673#define	HAZARD_DELAY	sll $0,3
674#define	ITLBNOPFIX	sll $0,3
675#elif defined(CPU_RMI)
676#define	HAZARD_DELAY
677#define	ITLBNOPFIX
678#elif defined(CPU_MIPS74K)
679#define	HAZARD_DELAY	sll $0,$0,3
680#define	ITLBNOPFIX	sll $0,$0,3
681#else
682#define	ITLBNOPFIX	nop;nop;nop;nop;nop;nop;nop;nop;nop;sll $0,$0,3;
683#define	HAZARD_DELAY	nop;nop;nop;nop;sll $0,$0,3;
684#endif
685
686#endif /* !_MACHINE_ASM_H_ */
687