asm.h revision 178172
1/*	$NetBSD: asm.h,v 1.29 2000/12/14 21:29:51 jeffs 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 * 4. 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 *	JNPR: asm.h,v 1.10 2007/08/09 11:23:32 katta
36 * $FreeBSD: head/sys/mips/include/asm.h 178172 2008-04-13 07:27:37Z imp $
37 */
38
39/*
40 * machAsmDefs.h --
41 *
42 *	Macros used when writing assembler programs.
43 *
44 *	Copyright (C) 1989 Digital Equipment Corporation.
45 *	Permission to use, copy, modify, and distribute this software and
46 *	its documentation for any purpose and without fee is hereby granted,
47 *	provided that the above copyright notice appears in all copies.
48 *	Digital Equipment Corporation makes no representations about the
49 *	suitability of this software for any purpose.  It is provided "as is"
50 *	without express or implied warranty.
51 *
52 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsmDefs.h,
53 *	v 1.2 89/08/15 18:28:24 rab Exp  SPRITE (DECWRL)
54 */
55
56#ifndef _MACHINE_ASM_H_
57#define	_MACHINE_ASM_H_
58
59#ifndef NO_REG_DEFS
60#include <machine/regdef.h>
61#endif
62#include <machine/endian.h>
63
64#undef __FBSDID
65#if !defined(lint) && !defined(STRIP_FBSDID)
66#define	__FBSDID(s)	.ident s
67#else
68#define	__FBSDID(s)	/* nothing */
69#endif
70
71/*
72 * Define -pg profile entry code.
73 * Must always be noreorder, must never use a macro instruction
74 * Final addiu to t9 must always equal the size of this _KERN_MCOUNT
75 */
76#define	_KERN_MCOUNT			\
77	.set	push;			\
78	.set	noreorder;		\
79	.set	noat;			\
80	subu	sp,sp,16;		\
81	sw	t9,12(sp);		\
82	move	AT,ra;			\
83	lui	t9,%hi(_mcount);	\
84	addiu	t9,t9,%lo(_mcount);	\
85	jalr	t9;			\
86	nop;				\
87	lw	t9,4(sp);		\
88	addiu	sp,sp,8;		\
89	addiu	t9,t9,40;		\
90	.set	pop;
91
92#ifdef GPROF
93#define	MCOUNT _KERN_MCOUNT
94#else
95#define	MCOUNT
96#endif
97
98#define	_C_LABEL(x)	x
99
100/*
101 *  Endian-independent assembly-code aliases for unaligned memory accesses.
102 */
103#if BYTE_ORDER == LITTLE_ENDIAN
104#define	LWLO	lwl
105#define	LWHI	lwr
106#define	SWLO	swl
107#define	SWHI	swr
108#endif
109
110#if BYTE_ORDER == BIG_ENDIAN
111#define	LWLO	lwr
112#define	LWHI	lwl
113#define	SWLO	swr
114#define	SWHI	swl
115#endif
116
117#ifdef USE_AENT
118#define	AENT(x)		\
119	.aent	x, 0
120#else
121#define	AENT(x)
122#endif
123
124/*
125 * WARN_REFERENCES: create a warning if the specified symbol is referenced
126 */
127#define	WARN_REFERENCES(_sym,_msg)				\
128	.section .gnu.warning. ## _sym ; .ascii _msg ; .text
129
130/*
131 * These are temp registers whose names can be used in either the old
132 * or new ABI, although they map to different physical registers.  In
133 * the old ABI, they map to t4-t7, and in the new ABI, they map to a4-a7.
134 *
135 * Because they overlap with the last 4 arg regs in the new ABI, ta0-ta3
136 * should be used only when we need more than t0-t3.
137 */
138#if defined(__mips_n32) || defined(__mips_n64)
139#define ta0     $8
140#define ta1     $9
141#define ta2     $10
142#define ta3     $11
143#else
144#define ta0     $12
145#define ta1     $13
146#define ta2     $14
147#define ta3     $15
148#endif /* __mips_n32 || __mips_n64 */
149
150#ifdef __ELF__
151# define _C_LABEL(x)    x
152#else
153#  define _C_LABEL(x)   _ ## x
154#endif
155
156/*
157 * WEAK_ALIAS: create a weak alias.
158 */
159#define	WEAK_ALIAS(alias,sym)						\
160	.weak alias;							\
161	alias = sym
162
163/*
164 * STRONG_ALIAS: create a strong alias.
165 */
166#define STRONG_ALIAS(alias,sym)						\
167	.globl alias;							\
168	alias = sym
169
170#define	GLOBAL(sym)						\
171	.globl sym; sym:
172
173#define	ENTRY(sym)						\
174	.text; .globl sym; .ent sym; sym:
175
176#define	ASM_ENTRY(sym)						\
177	.text; .globl sym; .type sym,@function; sym:
178
179/*
180 * LEAF
181 *	A leaf routine does
182 *	- call no other function,
183 *	- never use any register that callee-saved (S0-S8), and
184 *	- not use any local stack storage.
185 */
186#define	LEAF(x)			\
187	.globl	_C_LABEL(x);	\
188	.ent	_C_LABEL(x), 0;	\
189_C_LABEL(x): ;			\
190	.frame sp, 0, ra;	\
191	MCOUNT
192
193/*
194 * LEAF_NOPROFILE
195 *	No profilable leaf routine.
196 */
197#define	LEAF_NOPROFILE(x)	\
198	.globl	_C_LABEL(x);	\
199	.ent	_C_LABEL(x), 0;	\
200_C_LABEL(x): ;			\
201	.frame	sp, 0, ra
202
203/*
204 * XLEAF
205 *	declare alternate entry to leaf routine
206 */
207#define	XLEAF(x)		\
208	.globl	_C_LABEL(x);	\
209	AENT (_C_LABEL(x));	\
210_C_LABEL(x):
211
212/*
213 * NESTED
214 *	A function calls other functions and needs
215 *	therefore stack space to save/restore registers.
216 */
217#define	NESTED(x, fsize, retpc)		\
218	.globl	_C_LABEL(x);		\
219	.ent	_C_LABEL(x), 0;		\
220_C_LABEL(x): ;				\
221	.frame	sp, fsize, retpc;	\
222	MCOUNT
223
224/*
225 * NESTED_NOPROFILE(x)
226 *	No profilable nested routine.
227 */
228#define	NESTED_NOPROFILE(x, fsize, retpc)	\
229	.globl	_C_LABEL(x);			\
230	.ent	_C_LABEL(x), 0;			\
231_C_LABEL(x): ;					\
232	.frame	sp, fsize, retpc
233
234/*
235 * XNESTED
236 *	declare alternate entry point to nested routine.
237 */
238#define	XNESTED(x)		\
239	.globl	_C_LABEL(x);	\
240	AENT (_C_LABEL(x));	\
241_C_LABEL(x):
242
243/*
244 * END
245 *	Mark end of a procedure.
246 */
247#define	END(x)			\
248	.end _C_LABEL(x)
249
250/*
251 * IMPORT -- import external symbol
252 */
253#define	IMPORT(sym, size)	\
254	.extern _C_LABEL(sym),size
255
256/*
257 * EXPORT -- export definition of symbol
258 */
259#define	EXPORT(x)		\
260	.globl	_C_LABEL(x);	\
261_C_LABEL(x):
262
263/*
264 * VECTOR
265 *	exception vector entrypoint
266 *	XXX: regmask should be used to generate .mask
267 */
268#define	VECTOR(x, regmask)	\
269	.ent	_C_LABEL(x),0;	\
270	EXPORT(x);		\
271
272#define	VECTOR_END(x)		\
273	EXPORT(x ## End);	\
274	END(x)
275
276#define	KSEG0TEXT_START
277#define	KSEG0TEXT_END
278#define	KSEG0TEXT	.text
279
280/*
281 * Macros to panic and printf from assembly language.
282 */
283#define	PANIC(msg)			\
284	la	a0, 9f;			\
285	jal	_C_LABEL(panic);	\
286	nop;				\
287	MSG(msg)
288
289#define	PANIC_KSEG0(msg, reg)	PANIC(msg)
290
291#define	PRINTF(msg)			\
292	la	a0, 9f;			\
293	jal	_C_LABEL(printf);	\
294	nop;				\
295	MSG(msg)
296
297#define	MSG(msg)			\
298	.rdata;				\
2999:	.asciiz	msg;			\
300	.text
301
302#define	ASMSTR(str)			\
303	.asciiz str;			\
304	.align	3
305
306/*
307 * Call ast if required
308 */
309#define DO_AST				             \
31044:				                     \
311	la	s0, _C_LABEL(disableintr)           ;\
312	jalr	s0                                  ;\
313	nop                                         ;\
314	GET_CPU_PCPU(s1)                            ;\
315	lw	s3, PC_CURPCB(s1)                   ;\
316	lw	s1, PC_CURTHREAD(s1)                ;\
317	lw	s2, TD_FLAGS(s1)                    ;\
318	li	s0, TDF_ASTPENDING | TDF_NEEDRESCHED;\
319	and	s2, s0                              ;\
320	la	s0, _C_LABEL(enableintr)            ;\
321	jalr	s0                                  ;\
322	nop                                         ;\
323	beq	s2, zero, 4f                        ;\
324	nop                                         ;\
325	la	s0, _C_LABEL(ast)                   ;\
326	jalr	s0                                  ;\
327	addu	a0, s3, U_PCB_REGS                  ;\
328	j 44b			                    ;\
329        nop                                         ;\
3304:
331
332
333/*
334 * XXX retain dialects XXX
335 */
336#define	ALEAF(x)			XLEAF(x)
337#define	NLEAF(x)			LEAF_NOPROFILE(x)
338#define	NON_LEAF(x, fsize, retpc)	NESTED(x, fsize, retpc)
339#define	NNON_LEAF(x, fsize, retpc)	NESTED_NOPROFILE(x, fsize, retpc)
340
341/*
342 *  standard callframe {
343 *  	register_t cf_args[4];		arg0 - arg3
344 *  	register_t cf_sp;		frame pointer
345 *  	register_t cf_ra;		return address
346 *  };
347 */
348#define	CALLFRAME_SIZ	(4 * (4 + 2))
349#define	CALLFRAME_SP	(4 * 4)
350#define	CALLFRAME_RA	(4 * 5)
351#define	START_FRAME	CALLFRAME_SIZ
352
353/*
354 * While it would be nice to be compatible with the SGI
355 * REG_L and REG_S macros, because they do not take parameters, it
356 * is impossible to use them with the _MIPS_SIM_ABIX32 model.
357 *
358 * These macros hide the use of mips3 instructions from the
359 * assembler to prevent the assembler from generating 64-bit style
360 * ABI calls.
361 */
362
363#if !defined(_MIPS_BSD_API) || _MIPS_BSD_API == _MIPS_BSD_API_LP32
364#define	REG_L		lw
365#define	REG_S		sw
366#define	REG_LI		li
367#define	REG_PROLOGUE	.set push
368#define	REG_EPILOGUE	.set pop
369#define	SZREG		4
370#else
371#define	REG_L		ld
372#define	REG_S		sd
373#define	REG_LI		dli
374#define	REG_PROLOGUE	.set push ; .set mips3
375#define	REG_EPILOGUE	.set pop
376#define	SZREG		8
377#endif	/* _MIPS_BSD_API */
378
379#define	mfc0_macro(data, spr)						\
380	__asm __volatile ("mfc0 %0, $%1"				\
381			: "=r" (data)	/* outputs */			\
382			: "i" (spr));	/* inputs */
383
384#define	mtc0_macro(data, spr)						\
385	__asm __volatile ("mtc0 %0, $%1"				\
386			:				/* outputs */	\
387			: "r" (data), "i" (spr));	/* inputs */
388
389#define	cfc0_macro(data, spr)						\
390	__asm __volatile ("cfc0 %0, $%1"				\
391			: "=r" (data)	/* outputs */			\
392			: "i" (spr));	/* inputs */
393
394#define	ctc0_macro(data, spr)						\
395	__asm __volatile ("ctc0 %0, $%1"				\
396			:				/* outputs */	\
397			: "r" (data), "i" (spr));	/* inputs */
398
399
400#define	lbu_macro(data, addr)						\
401	__asm __volatile ("lbu %0, 0x0(%1)"				\
402			: "=r" (data)	/* outputs */			\
403			: "r" (addr));	/* inputs */
404
405#define	lb_macro(data, addr)						\
406	__asm __volatile ("lb %0, 0x0(%1)"				\
407			: "=r" (data)	/* outputs */			\
408			: "r" (addr));	/* inputs */
409
410#define	lwl_macro(data, addr)						\
411	__asm __volatile ("lwl %0, 0x0(%1)"				\
412			: "=r" (data)	/* outputs */			\
413			: "r" (addr));	/* inputs */
414
415#define	lwr_macro(data, addr)						\
416	__asm __volatile ("lwr %0, 0x0(%1)"				\
417			: "=r" (data)	/* outputs */			\
418			: "r" (addr));	/* inputs */
419
420#define	ldl_macro(data, addr)						\
421	__asm __volatile ("ldl %0, 0x0(%1)"				\
422			: "=r" (data)	/* outputs */			\
423			: "r" (addr));	/* inputs */
424
425#define	ldr_macro(data, addr)						\
426	__asm __volatile ("ldr %0, 0x0(%1)"				\
427			: "=r" (data)	/* outputs */			\
428			: "r" (addr));	/* inputs */
429
430#define	sb_macro(data, addr)						\
431	__asm __volatile ("sb %0, 0x0(%1)"				\
432			:				/* outputs */	\
433			: "r" (data), "r" (addr));	/* inputs */
434
435#define	swl_macro(data, addr)						\
436	__asm __volatile ("swl %0, 0x0(%1)"				\
437			: 				/* outputs */	\
438			: "r" (data), "r" (addr));	/* inputs */
439
440#define	swr_macro(data, addr)						\
441	__asm __volatile ("swr %0, 0x0(%1)"				\
442			: 				/* outputs */	\
443			: "r" (data), "r" (addr));	/* inputs */
444
445#define	sdl_macro(data, addr)						\
446	__asm __volatile ("sdl %0, 0x0(%1)"				\
447			: 				/* outputs */	\
448			: "r" (data), "r" (addr));	/* inputs */
449
450#define	sdr_macro(data, addr)						\
451	__asm __volatile ("sdr %0, 0x0(%1)"				\
452			:				/* outputs */	\
453			: "r" (data), "r" (addr));	/* inputs */
454
455#define	mfgr_macro(data, gr)						\
456	__asm __volatile ("move %0, $%1"				\
457			: "=r" (data)	/* outputs */			\
458			: "i" (gr));	/* inputs */
459
460#define	dmfc0_macro(data, spr)						\
461	__asm __volatile ("dmfc0 %0, $%1"				\
462			: "=r" (data)	/* outputs */			\
463			: "i" (spr));	/* inputs */
464
465#define	dmtc0_macro(data, spr, sel)					\
466	__asm __volatile ("dmtc0	%0, $%1, %2"			\
467			:			/* no  outputs */	\
468			: "r" (data), "i" (spr), "i" (sel)); /* inputs */
469
470/*
471 * The DYNAMIC_STATUS_MASK option adds an additional masking operation
472 * when updating the hardware interrupt mask in the status register.
473 *
474 * This is useful for platforms that need to at run-time mask
475 * interrupts based on motherboard configuration or to handle
476 * slowly clearing interrupts.
477 *
478 * XXX this is only currently implemented for mips3.
479 */
480#ifdef MIPS_DYNAMIC_STATUS_MASK
481#define	DYNAMIC_STATUS_MASK(sr,scratch)			\
482	lw	scratch, mips_dynamic_status_mask;	\
483	and	sr, sr, scratch
484
485#define	DYNAMIC_STATUS_MASK_TOUSER(sr,scratch1)		\
486	ori	sr, (MIPS_INT_MASK | MIPS_SR_INT_IE);	\
487	DYNAMIC_STATUS_MASK(sr,scratch1)
488#else
489#define	DYNAMIC_STATUS_MASK(sr,scratch)
490#define	DYNAMIC_STATUS_MASK_TOUSER(sr,scratch1)
491#endif
492
493#ifdef SMP
494	/*
495	 * FREEBSD_DEVELOPERS_FIXME
496	 * In multiprocessor case, store/retrieve the pcpu structure
497	 * address for current CPU in scratch register for fast access.
498	 */
499#error "Write GET_CPU_PCPU for SMP"
500#else
501#define	GET_CPU_PCPU(reg)		\
502	lw	reg, _C_LABEL(pcpup);
503#endif
504
505/*
506 * Description of the setjmp buffer
507 *
508 * word  0	magic number	(dependant on creator)
509 *       1	RA
510 *       2	S0
511 *       3	S1
512 *       4	S2
513 *       5	S3
514 *       6	S4
515 *       7	S5
516 *       8	S6
517 *       9	S7
518 *       10	SP
519 *       11	S8
520 *       12	signal mask	(dependant on magic)
521 *       13	(con't)
522 *       14	(con't)
523 *       15	(con't)
524 *
525 * The magic number number identifies the jmp_buf and
526 * how the buffer was created as well as providing
527 * a sanity check
528 *
529 */
530
531#define _JB_MAGIC__SETJMP	0xBADFACED
532#define _JB_MAGIC_SETJMP	0xFACEDBAD
533
534/* Valid for all jmp_buf's */
535
536#define _JB_MAGIC		0
537#define _JB_REG_RA		1
538#define _JB_REG_S0		2
539#define _JB_REG_S1		3
540#define _JB_REG_S2		4
541#define _JB_REG_S3		5
542#define _JB_REG_S4		6
543#define _JB_REG_S5		7
544#define _JB_REG_S6		8
545#define _JB_REG_S7		9
546#define _JB_REG_SP		10
547#define _JB_REG_S8		11
548
549/* Only valid with the _JB_MAGIC_SETJMP magic */
550
551#define _JB_SIGMASK		12
552
553#endif /* !_MACHINE_ASM_H_ */
554