xref: /netbsd/sys/arch/mips/mips/mipsX_subr.S (revision bf9ec67e)
1/*	$NetBSD: mipsX_subr.S,v 1.2 2002/03/11 16:39:40 uch Exp $	*/
2
3/*
4 * Copyright 2002 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Simon Burge for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed for the NetBSD Project by
20 *	Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 *    or promote products derived from this software without specific prior
23 *    written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38/*
39 * Copyright (c) 1997 Jonathan Stone (hereinafter referred to as the author)
40 * All rights reserved.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 *    notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 *    notice, this list of conditions and the following disclaimer in the
49 *    documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software
51 *    must display the following acknowledgement:
52 *      This product includes software developed by Jonathan R. Stone for
53 *      the NetBSD Project.
54 * 4. The name of the author may not be used to endorse or promote products
55 *    derived from this software without specific prior written permission.
56 *
57 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67 * SUCH DAMAGE.
68 */
69
70/*
71 * Copyright (c) 1992, 1993
72 *	The Regents of the University of California.  All rights reserved.
73 *
74 * This code is derived from software contributed to Berkeley by
75 * Digital Equipment Corporation and Ralph Campbell.
76 *
77 * Redistribution and use in source and binary forms, with or without
78 * modification, are permitted provided that the following conditions
79 * are met:
80 * 1. Redistributions of source code must retain the above copyright
81 *    notice, this list of conditions and the following disclaimer.
82 * 2. Redistributions in binary form must reproduce the above copyright
83 *    notice, this list of conditions and the following disclaimer in the
84 *    documentation and/or other materials provided with the distribution.
85 * 3. All advertising materials mentioning features or use of this software
86 *    must display the following acknowledgement:
87 *	This product includes software developed by the University of
88 *	California, Berkeley and its contributors.
89 * 4. Neither the name of the University nor the names of its contributors
90 *    may be used to endorse or promote products derived from this software
91 *    without specific prior written permission.
92 *
93 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
94 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
95 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
96 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
97 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
98 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
99 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
101 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
102 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
103 * SUCH DAMAGE.
104 *
105 * Copyright (C) 1989 Digital Equipment Corporation.
106 * Permission to use, copy, modify, and distribute this software and
107 * its documentation for any purpose and without fee is hereby granted,
108 * provided that the above copyright notice appears in all copies.
109 * Digital Equipment Corporation makes no representations about the
110 * suitability of this software for any purpose.  It is provided "as is"
111 * without express or implied warranty.
112 *
113 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
114 *	v 1.1 89/07/11 17:55:04 nelson Exp  SPRITE (DECWRL)
115 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
116 *	v 9.2 90/01/29 18:00:39 shirriff Exp  SPRITE (DECWRL)
117 * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
118 *	v 1.1 89/07/10 14:27:41 nelson Exp  SPRITE (DECWRL)
119 *
120 *	@(#)locore.s	8.5 (Berkeley) 1/4/94
121 */
122#include "opt_cputype.h"
123#include "opt_ddb.h"
124#include "opt_kgdb.h"
125
126#include <sys/cdefs.h>
127
128#include <mips/asm.h>
129#include <mips/cpuregs.h>
130#if defined(MIPS3) && !defined(MIPS3_5900)
131#include <mips/cache_r4k.h>
132#endif
133
134#include <machine/param.h>
135#include <machine/endian.h>
136
137#include "assym.h"
138
139/*
140 * XXX MIPS3_5900 is still "special" for much of this code.
141 * XXX MIPS3_4100 is still "special" in tlb update code
142 */
143
144#if MIPS1
145#error This file can not be compiled with MIPS1 defined
146#endif
147
148#if MIPS3 + MIPS32 + MIPS64 != 1
149# error  Only one of MIPS{3,32,64} can be defined
150#endif
151
152/*
153 * Use 64bit cp0 instructions?
154 */
155#if defined(MIPS3)
156#if defined(MIPS3_5900)		/* the 5900 has mips32-like mmu registers */
157#undef	USE_64BIT_FUNCTIONS
158#else
159#define	USE_64BIT_FUNCTIONS
160#endif
161#endif
162
163#if defined(MIPS32)
164#undef	USE_64BIT_FUNCTIONS
165#endif
166
167#if defined(MIPS64)
168#define	USE_64BIT_FUNCTIONS
169#endif
170
171#if defined(USE_64BIT_FUNCTIONS)
172#define	_SLL		dsll
173#define	_SRL		dsrl
174#define	WIRED_SHIFT	34
175#else
176#define	_SLL		sll
177#define	_SRL		srl
178#define	WIRED_SHIFT	2
179#endif
180
181/*
182 * Use correct-sized m?c0/dm?c0 opcodes.
183 */
184#if defined(USE_64BIT_FUNCTIONS)
185#define	_MFC0	dmfc0
186#define	_MTC0	dmtc0
187#else
188#define	_MFC0	mfc0
189#define	_MTC0	mtc0
190#endif
191
192
193/*
194 * Set ISA level for the assembler.
195 */
196#if defined(MIPS3)
197	.set	mips3
198#endif
199
200#if defined(MIPS32)
201	.set	mips32
202#endif
203
204#if defined(MIPS64)
205	.set	mips64
206#endif
207
208/*
209 * Set up hazard/interlock dependancies.
210 */
211#if !defined(MIPS3_5900)
212#undef COP0_SYNC
213#define	COP0_SYNC	/* nothing */
214#endif
215
216/*
217 * CPP function renaming macros.
218 */
219#if defined(LOSING_WITH_CPP)
220
221#if defined(MIPS3)
222#define	MIPSX_PREFIX	mips3
223#endif
224
225#if defined(MIPS32)
226#define	MIPSX_PREFIX	mips32
227#endif
228
229#if defined(MIPS64)
230#define	MIPSX_PREFIX	mips64
231#endif
232
233#ifdef __STDC__
234#define	MIPSX(name)	MIPSX_PREFIX ## _ ## name
235#else
236#define	MIPSX(name)	MIPSX_PREFIX/**/_/**/name
237#endif
238
239#else	/* LOSING_WITH_CPP */
240
241#if defined(MIPS3)
242#define	MIPSX(name)	mips3_/**/name
243#endif
244
245#if defined(MIPS3_5900)
246#undef MIPSX
247#define	MIPSX(name)	mips5900_/**/name
248#endif
249
250#if defined(MIPS32)
251#define	MIPSX(name)	mips32_/**/name
252#endif
253
254#if defined(MIPS64)
255#define	MIPSX(name)	mips64_/**/name
256#endif
257
258#endif	/* LOSING_WITH_CPP */
259
260/*
261 * XXX We need a cleaner way of handling the instruction hazards of
262 * the various processors.  Here are the relevant rules for the QED 52XX:
263 *	tlbw[ri]	-- two integer ops beforehand
264 *	tlbr		-- two integer ops beforehand
265 *	tlbp		-- two integer ops beforehand
266 *	mtc0	[PageMask,EntryHi,Cp0] -- two integer ops afterwards
267 *	changing JTLB	-- two integer ops afterwards
268 *	mtc0	[EPC,ErrorEPC,Status] -- two int ops afterwards before eret
269 *	config.k0	-- five int ops before kseg0, ckseg0 memref
270 *
271 * For the IDT R4000, some hazards are:
272 *	mtc0/mfc0	one integer op before and after
273 *	tlbp		-- one integer op afterwards
274 * Obvious solution is to take least common denominator.
275 *
276 * For the Toshiba R5900, TX79:
277 *	mtc0		following sync.p
278 *	tlbw[ri], tlbp	following sync.p or eret
279 * for those CPU, define COP0_SYNC as sync.p
280 */
281
282
283/*
284 *============================================================================
285 *
286 *  MIPS III ISA support, part 1: locore exception vectors.
287 *  The following code is copied to the vector locations to which
288 *  the CPU jumps in response to an exception or a TLB miss.
289 *
290 *============================================================================
291 */
292	.set	noreorder
293
294/*
295 * TLB handling data.   'segbase' points to the base of the segment
296 * table.   this is read and written by C code in mips_machdep.c.
297 *
298 * XXX: use linear mapped PTs at fixed VA in kseg2 in the future?
299 */
300	.text
301
302
303/*
304 *----------------------------------------------------------------------------
305 *
306 * mips3_TLBMiss --
307 *
308 *	Vector code for the TLB-miss exception vector 0x80000000
309 *	on an r4000.
310 *
311 * This code is copied to the TLB exception vector address to
312 * handle TLB translation misses.
313 * NOTE: This code should be relocatable and max 32 instructions!!!
314 *
315 * Don't check for invalid pte's here. We load them as well and
316 * let the processor trap to load the correct value after service.
317 *----------------------------------------------------------------------------
318 */
319VECTOR(MIPSX(TLBMiss), unknown)
320	.set	noat
321	mfc0	k0, MIPS_COP_0_BAD_VADDR	#00: k0=bad address
322	lui	k1, %hi(segbase)		#01: k1=hi of segbase
323	bltz	k0, 4f				#02: k0<0 -> 4f (kernel fault)
324	srl	k0, 20				#03: k0=seg offset (almost)
325	lw	k1, %lo(segbase)(k1)		#04: k1=segment tab base
326	andi	k0, k0, 0xffc			#05: k0=seg offset (mask 0x3)
327	addu	k1, k0, k1			#06: k1=seg entry address
328	lw	k1, 0(k1)			#07: k1=seg entry
329	mfc0	k0, MIPS_COP_0_BAD_VADDR	#08: k0=bad address (again)
330	beq	k1, zero, 5f			#09: ==0 -- no page table
331	srl	k0, 10				#0a: k0=VPN (aka va>>10)
332	andi	k0, k0, 0xff8			#0b: k0=page tab offset
333	addu	k1, k1, k0			#0c: k1=pte address
334	lw	k0, 0(k1)			#0d: k0=lo0 pte
335	lw	k1, 4(k1)			#0e: k1=lo1 pte
336	sll	k0, 2				#0f: chop top 2 bits (part 1a)
337	srl	k0, 2				#10: chop top 2 bits (part 1b)
338#ifdef MIPS3_5900
339	mtc0	k0, MIPS_COP_0_TLB_LO0		#11: lo0 is loaded
340	sync.p					#12: R5900 cop0 hazard
341	sll	k1, 2				#13: chop top 2 bits (part 2a)
342	srl	k1, 2				#14: chop top 2 bits (part 2b)
343	mtc0	k1, MIPS_COP_0_TLB_LO1		#15: lo1 is loaded
344	sync.p					#16: R5900 cop0 hazard
345#else /* MIPS3_5900 */
346	mtc0	k0, MIPS_COP_0_TLB_LO0		#11: lo0 is loaded
347	sll	k1, 2				#12: chop top 2 bits (part 2a)
348	srl	k1, 2				#13: chop top 2 bits (part 2b)
349	mtc0	k1, MIPS_COP_0_TLB_LO1		#14: lo1 is loaded
350	nop					#15: standard nop
351	nop					#16: extra nop for QED5230
352#endif /* MIPS3_5900 */
353	tlbwr					#17: write to tlb
354	nop					#18: standard nop
355	nop					#19: needed by R4000/4400
356	nop					#1a: needed by R4000/4400
357	eret					#1b: return from exception
3584:	j _C_LABEL(MIPSX(TLBMissException))	#1c: kernel exception
359	nop					#1d: branch delay slot
3605:	j	slowfault			#1e: no page table present
361	nop					#1f: branch delay slot
362	.set	at
363VECTOR_END(MIPSX(TLBMiss))
364
365#if defined(USE_64BIT_FUNCTIONS)
366/*
367 * mips3_XTLBMiss routine
368 *
369 *	Vector code for the XTLB-miss exception vector 0x80000080 on an r4000.
370 *
371 * This code is copied to the XTLB exception vector address to
372 * handle TLB translation misses while in 64-bit mode.
373 * NOTE: This code should be relocatable and max 32 instructions!!!
374 *
375 * Note that we do not support the full size of the PTEs, relying
376 * on appropriate truncation/sign extension.
377 *
378 * Don't check for invalid pte's here. We load them as well and
379 * let the processor trap to load the correct value after service.
380 */
381VECTOR(MIPSX(XTLBMiss), unknown)
382	.set	noat
383	dmfc0	k0, MIPS_COP_0_BAD_VADDR	#00: k0=bad address
384	lui	k1, %hi(segbase)		#01: k1=hi of segbase
385	bltz	k0, 4f				#02: k0<0 -> 4f (kernel fault)
386	srl	k0, 20				#03: k0=seg offset (almost)
387	lw	k1, %lo(segbase)(k1)		#04: k1=segment tab base
388	andi	k0, k0, 0xffc			#05: k0=seg offset (mask 0x3)
389	addu	k1, k0, k1			#06: k1=seg entry address
390	lw	k1, 0(k1)			#07: k1=seg entry
391	dmfc0	k0, MIPS_COP_0_BAD_VADDR	#08: k0=bad address (again)
392	beq	k1, zero, 5f			#09: ==0 -- no page table
393	srl	k0, 10				#0a: k0=VPN (aka va>>10)
394	andi	k0, k0, 0xff8			#0b: k0=page tab offset
395	addu	k1, k1, k0			#0c: k1=pte address
396	lw	k0, 0(k1)			#0d: k0=lo0 pte
397	lw	k1, 4(k1)			#0e: k1=lo1 pte
398	sll	k0, 2				#0f: chop top 2 bits (part 1a)
399	srl	k0, 2				#10: chop top 2 bits (part 1b)
400	mtc0	k0, MIPS_COP_0_TLB_LO0		#11: lo0 is loaded
401	sll	k1, 2				#12: chop top 2 bits (part 2a)
402	srl	k1, 2				#13: chop top 2 bits (part 2b)
403	mtc0	k1, MIPS_COP_0_TLB_LO1	#14: lo1 is loaded
404	nop					#15: standard nop
405	nop					#16: extra nop for QED5230
406	tlbwr					#17: write to tlb
407	nop					#18: standard nop
408	nop					#19: needed by R4000/4400
409	nop					#1a: needed by R4000/4400
410	eret					#1b: return from exception
4114:	j _C_LABEL(MIPSX(TLBMissException))	#1c: kernel exception
412	nop					#1d: branch delay slot
4135:	j	slowfault			#1e: no page table present
414	nop					#1f: branch delay slot
415	.set	at
416VECTOR_END(MIPSX(XTLBMiss))
417#endif /* USE_64BIT_FUNCTIONS */
418
419/*
420 * Vector to real handler in KSEG1.
421 */
422VECTOR(MIPSX(cache), unknown)
423	la	k0, _C_LABEL(MIPSX(cacheException))
424	li	k1, MIPS_PHYS_MASK
425	and	k0, k1
426	li	k1, MIPS_KSEG1_START
427	or	k0, k1
428	j	k0
429	nop
430VECTOR_END(MIPSX(cache))
431
432/*
433 * Handle MIPS32/MIPS64 style interrupt exception vector.
434 */
435VECTOR(MIPSX(intr), unknown)
436	la	k0, MIPSX(KernIntr)
437	j	k0
438	nop
439VECTOR_END(MIPSX(intr))
440
441/*
442 *----------------------------------------------------------------------------
443 *
444 * mipsN_exception --
445 *
446 *	Vector code for the general exception vector 0x80000180
447 *	on an r4000 or r4400.
448 *
449 * This code is copied to the general exception vector address to
450 * handle most exceptions.
451 * NOTE: This code should be relocatable and max 32 instructions!!!
452 *----------------------------------------------------------------------------
453 */
454VECTOR(MIPSX(exception), unknown)
455/*
456 * Find out what mode we came from and jump to the proper handler.
457 */
458	.set	noat
459	mfc0	k0, MIPS_COP_0_STATUS		#00: get the status register
460	mfc0	k1, MIPS_COP_0_CAUSE		#01: get the cause register
461	and	k0, k0, MIPS3_SR_KSU_USER	#02: test for user mode
462						#    sneaky but the bits are
463						#    with us........
464	sll	k0, k0, 3			#03: shift user bit for cause index
465	and	k1, k1, MIPS3_CR_EXC_CODE	#04: mask out the cause bits.
466	or	k1, k1, k0			#05: change index to user table
4671:
468	la	k0, MIPSX(excpt_sw)		#06: get base of the jump table
469	addu	k0, k0, k1			#07: get the address of the
470						#     function entry.  Note that
471						#     the cause is already
472						#     shifted left by 2 bits so
473						#     we dont have to shift.
474	lw	k0, 0(k0)			#08: get the function address
475	#nop					#    -slip-
476
477	j	k0				#09: jump to the function
478	nop					#0a: branch delay slot
479	.set	at
480VECTOR_END(MIPSX(exception))
481
482/*----------------------------------------------------------------------------
483 *
484 * slowfault --
485 *
486 * Alternate entry point into the mips3_UserGenException or
487 * or mips3_user_Kern_exception, when the ULTB miss handler couldn't
488 * find a TLB entry.
489 *
490 * Find out what mode we came from and call the appropriate handler.
491 *
492 *----------------------------------------------------------------------------
493 */
494
495/*
496 * We couldn't find a TLB entry.
497 * Find out what mode we came from and call the appropriate handler.
498 */
499slowfault:
500	.set	noat
501	mfc0	k0, MIPS_COP_0_STATUS
502	nop
503	and	k0, k0, MIPS3_SR_KSU_USER
504	bne	k0, zero, _C_LABEL(MIPSX(UserGenException))
505	nop
506	.set	at
507/*
508 * Fall though ...
509 */
510
511/*
512 * mips3_KernGenException
513 *
514 * Handle an exception from kernel mode.
515 * Build trapframe on stack to hold interrupted kernel context, then
516 * call trap() to process the condition.
517 *
518 * trapframe is pointed to by the 5th arg
519 * and a dummy sixth argument is used to avoid alignment problems
520 *	{
521 *	register_t cf_args[4 + 1];
522 *	register_t cf_pad;		(for 8 word alignment)
523 *	register_t cf_sp;
524 *	register_t cf_ra;
525 *	mips_reg_t kf_regs[17];		- trapframe begins here
526 * 	mips_reg_t kf_sr;		-
527 * 	mips_reg_t kf_mullo;		-
528 * 	mips_reg_t kf_mulhi;		-
529 * 	mips_reg_t kf_epc;		- may be changed by trap() call
530 * };
531 */
532NESTED_NOPROFILE(MIPSX(KernGenException), KERNFRAME_SIZ, ra)
533	.set	noat
534	.mask	0x80000000, -4
535#if defined(DDB) || defined(KGDB)
536	la	k0, _C_LABEL(kdbaux)
537	REG_S	s0, SF_REG_S0(k0)
538	REG_S	s1, SF_REG_S1(k0)
539	REG_S	s2, SF_REG_S2(k0)
540	REG_S	s3, SF_REG_S3(k0)
541	REG_S	s4, SF_REG_S4(k0)
542	REG_S	s5, SF_REG_S5(k0)
543	REG_S	s6, SF_REG_S6(k0)
544	REG_S	s7, SF_REG_S7(k0)
545	REG_S	sp, SF_REG_SP(k0)
546	REG_S	s8, SF_REG_S8(k0)
547	REG_S	gp, SF_REG_RA(k0)
548#endif
549/*
550 * Save the relevant kernel registers onto the stack.
551 * We don't need to save s0 - s8, sp and gp because
552 * the compiler does it for us.
553 */
554	subu	sp, sp, KERNFRAME_SIZ
555	REG_S	AT, TF_BASE+TF_REG_AST(sp)
556	REG_S	v0, TF_BASE+TF_REG_V0(sp)
557	REG_S	v1, TF_BASE+TF_REG_V1(sp)
558	mflo	v0
559	mfhi	v1
560	REG_S	a0, TF_BASE+TF_REG_A0(sp)
561	REG_S	a1, TF_BASE+TF_REG_A1(sp)
562	REG_S	a2, TF_BASE+TF_REG_A2(sp)
563	REG_S	a3, TF_BASE+TF_REG_A3(sp)
564	mfc0	a0, MIPS_COP_0_STATUS		# 1st arg is STATUS
565	REG_S	t0, TF_BASE+TF_REG_T0(sp)
566	REG_S	t1, TF_BASE+TF_REG_T1(sp)
567	REG_S	t2, TF_BASE+TF_REG_T2(sp)
568	REG_S	t3, TF_BASE+TF_REG_T3(sp)
569	mfc0	a1, MIPS_COP_0_CAUSE		# 2nd arg is CAUSE
570	REG_S	t4, TF_BASE+TF_REG_T4(sp)
571	REG_S	t5, TF_BASE+TF_REG_T5(sp)
572	REG_S	t6, TF_BASE+TF_REG_T6(sp)
573	REG_S	t7, TF_BASE+TF_REG_T7(sp)
574	mfc0	a2, MIPS_COP_0_BAD_VADDR	# 3rd arg is fault address
575	REG_S	t8, TF_BASE+TF_REG_T8(sp)
576	REG_S	t9, TF_BASE+TF_REG_T9(sp)
577	REG_S	ra, TF_BASE+TF_REG_RA(sp)
578	REG_S	a0, TF_BASE+TF_REG_SR(sp)
579	mfc0	a3, MIPS_COP_0_EXC_PC		# 4th arg is exception PC
580	REG_S	v0, TF_BASE+TF_REG_MULLO(sp)
581	REG_S	v1, TF_BASE+TF_REG_MULHI(sp)
582	REG_S	a3, TF_BASE+TF_REG_EPC(sp)
583	addu	v0, sp, TF_BASE
584	sw	v0, KERNFRAME_ARG5(sp)		# 5th arg is p. to trapframe
585#ifdef IPL_ICU_MASK
586	.set at
587	lw	v0, _C_LABEL(md_imask)
588	sw	v0, TF_BASE+TF_PPL(sp)
589	nop
590	.set noat
591#endif
592/*
593 * Call the trap handler.
594 */
595#if defined(DDB) || defined(DEBUG) || defined(KGDB)
596	addu	v0, sp, KERNFRAME_SIZ
597	sw	v0, KERNFRAME_SP(sp)
598#endif
599	mtc0	zero, MIPS_COP_0_STATUS		# Set kernel no error level
600	COP0_SYNC
601	nop
602	nop
603	nop
604	jal	_C_LABEL(trap)			#
605	sw	a3, KERNFRAME_RA(sp)		# for debugging
606
607/*
608 * Restore registers and return from the exception.
609 */
610	mtc0	zero, MIPS_COP_0_STATUS		# Make sure int disabled
611	COP0_SYNC
612	nop					# 3 nop delay
613	nop
614	nop
615#ifdef IPL_ICU_MASK
616	.set at
617	lw	a0, TF_BASE+TF_PPL(sp)
618	sw	a0, _C_LABEL(md_imask)
619	jal	_C_LABEL(md_imask_update)
620	nop
621	.set noat
622#endif
623	REG_L	a0, TF_BASE+TF_REG_SR(sp)	# ??? why differs ???
624	REG_L	t0, TF_BASE+TF_REG_MULLO(sp)
625	REG_L	t1, TF_BASE+TF_REG_MULHI(sp)
626	REG_L	k0, TF_BASE+TF_REG_EPC(sp)	# might be changed inside trap
627	mtc0	a0, MIPS_COP_0_STATUS		# restore the SR, disable intrs
628	COP0_SYNC
629	mtlo	t0
630	mthi	t1
631	_MTC0	k0, MIPS_COP_0_EXC_PC		# set return address
632	COP0_SYNC
633	REG_L	AT, TF_BASE+TF_REG_AST(sp)
634	REG_L	v0, TF_BASE+TF_REG_V0(sp)
635	REG_L	v1, TF_BASE+TF_REG_V1(sp)
636	REG_L	a0, TF_BASE+TF_REG_A0(sp)
637	REG_L	a1, TF_BASE+TF_REG_A1(sp)
638	REG_L	a2, TF_BASE+TF_REG_A2(sp)
639	REG_L	a3, TF_BASE+TF_REG_A3(sp)
640	REG_L	t0, TF_BASE+TF_REG_T0(sp)
641	REG_L	t1, TF_BASE+TF_REG_T1(sp)
642	REG_L	t2, TF_BASE+TF_REG_T2(sp)
643	REG_L	t3, TF_BASE+TF_REG_T3(sp)
644	REG_L	t4, TF_BASE+TF_REG_T4(sp)
645	REG_L	t5, TF_BASE+TF_REG_T5(sp)
646	REG_L	t6, TF_BASE+TF_REG_T6(sp)
647	REG_L	t7, TF_BASE+TF_REG_T7(sp)
648	REG_L	t8, TF_BASE+TF_REG_T8(sp)
649	REG_L	t9, TF_BASE+TF_REG_T9(sp)
650	REG_L	ra, TF_BASE+TF_REG_RA(sp)
651	addu	sp, sp, KERNFRAME_SIZ
652#ifdef DDBnotyet
653	la	k0, _C_LABEL(kdbaux)
654	REG_L	s0, SF_REG_S0(k0)
655	REG_L	s1, SF_REG_S1(k0)
656	REG_L	s2, SF_REG_S2(k0)
657	REG_L	s3, SF_REG_S3(k0)
658	REG_L	s4, SF_REG_S4(k0)
659	REG_L	s5, SF_REG_S5(k0)
660	REG_L	s6, SF_REG_S6(k0)
661	REG_L	s7, SF_REG_S7(k0)
662	REG_L	sp, SF_REG_SP(k0)
663	REG_L	s8, SF_REG_S8(k0)
664	REG_L	gp, SF_REG_RA(k0)
665#endif
666	eret					# return to interrupted point
667	.set	at
668END(MIPSX(KernGenException))
669
670/*
671 * mipsN_UserGenException
672 *
673 * Handle an exception from user mode.
674 * Save user context atop the kernel stack, then call trap() to process
675 * the condition.  The context can be manipulated alternatively via
676 * curproc->p_md.md_regs.
677 */
678NESTED_NOPROFILE(MIPSX(UserGenException), CALLFRAME_SIZ, ra)
679	.set	noat
680	.mask	0x80000000, -4
681/*
682 * Save all of the registers except for the kernel temporaries in u_pcb.
683 */
684	lw	k1, _C_LABEL(curpcb)
685	#nop					# -slip-
686	addu	k1, k1, USPACE - FRAME_SIZ
687	REG_S	AT, FRAME_AST(k1)
688	REG_S	v0, FRAME_V0(k1)
689	REG_S	v1, FRAME_V1(k1)
690	mflo	v0
691	REG_S	a0, FRAME_A0(k1)
692	REG_S	a1, FRAME_A1(k1)
693	REG_S	a2, FRAME_A2(k1)
694	REG_S	a3, FRAME_A3(k1)
695	mfhi	v1
696	REG_S	t0, FRAME_T0(k1)
697	REG_S	t1, FRAME_T1(k1)
698	REG_S	t2, FRAME_T2(k1)
699	REG_S	t3, FRAME_T3(k1)
700	mfc0	a0, MIPS_COP_0_STATUS		# 1st arg is STATUS
701	REG_S	t4, FRAME_T4(k1)
702	REG_S	t5, FRAME_T5(k1)
703	REG_S	t6, FRAME_T6(k1)
704	REG_S	t7, FRAME_T7(k1)
705	mfc0	a1, MIPS_COP_0_CAUSE		# 2nd arg is CAUSE
706	REG_S	s0, FRAME_S0(k1)
707	REG_S	s1, FRAME_S1(k1)
708	REG_S	s2, FRAME_S2(k1)
709	REG_S	s3, FRAME_S3(k1)
710	_MFC0	a2, MIPS_COP_0_BAD_VADDR	# 3rd arg is fault address
711	REG_S	s4, FRAME_S4(k1)
712	REG_S	s5, FRAME_S5(k1)
713	REG_S	s6, FRAME_S6(k1)
714	REG_S	s7, FRAME_S7(k1)
715	_MFC0	a3, MIPS_COP_0_EXC_PC		# 4th arg is exception PC
716	REG_S	t8, FRAME_T8(k1)
717	REG_S	t9, FRAME_T9(k1)
718	REG_S	gp, FRAME_GP(k1)
719	REG_S	sp, FRAME_SP(k1)
720	REG_S	s8, FRAME_S8(k1)
721	REG_S	ra, FRAME_RA(k1)
722	REG_S	a0, FRAME_SR(k1)
723	REG_S	v0, FRAME_MULLO(k1)
724	REG_S	v1, FRAME_MULHI(k1)
725	REG_S	a3, FRAME_EPC(k1)
726#ifdef IPL_ICU_MASK
727	.set at
728	lw	t0, _C_LABEL(md_imask)
729	sw	t0, FRAME_PPL(k1)
730	.set noat
731#endif
732	addu	sp, k1, -CALLFRAME_SIZ	# switch to kernel SP
733#ifdef __GP_SUPPORT__
734	la	gp, _C_LABEL(_gp)		# switch to kernel GP
735#endif
736/*
737 * Turn off fpu and enter kernel mode
738 */
739	.set	at
740	and	t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_KSU_MASK | MIPS_SR_INT_IE)
741	.set	noat
742/*
743 * Call the trap handler.
744 */
745	mtc0	t0, MIPS_COP_0_STATUS
746	COP0_SYNC
747	jal	_C_LABEL(trap)
748	sw	a3, CALLFRAME_SIZ-4(sp)		# for debugging
749/*
750 * Check pending asynchronous traps.
751 */
752	lw	t0, _C_LABEL(curproc)
753	lw	t0, P_MD_ASTPENDING(t0)
754	beq	t0, zero, 1f
755	nop
756/*
757 * We have pending asynchronous traps; all the state is already saved.
758 */
759	jal	_C_LABEL(ast)
760	lw	a0, CALLFRAME_SIZ + FRAME_EPC(sp)
7611:
762/*
763 * Restore user registers and return.
764 * First disable interrupts and set exception level.
765 */
766	mtc0	zero, MIPS_COP_0_STATUS		# disable interrupt
767	COP0_SYNC
768	nop					# 3 clock delay before
769	nop					# exceptions blocked
770	nop					# for R4X
771	li	v0, MIPS_SR_EXL
772	mtc0	v0, MIPS_COP_0_STATUS		# set exception level
773	COP0_SYNC
774	nop					# 3 nop delay
775	nop
776	nop
777	addu	a1, sp, CALLFRAME_SIZ
778#ifdef IPL_ICU_MASK
779	.set at
780	lw	t0, FRAME_PPL(a1)
781	sw	t0, _C_LABEL(md_imask)
782	jal	_C_LABEL(md_imask_update)
783	nop
784	addu	a1, sp, CALLFRAME_SIZ
785	.set noat
786#endif
787 #	REG_L	a0, FRAME_SR(a1)
788	REG_L	t0, FRAME_MULLO(a1)
789	REG_L	t1, FRAME_MULHI(a1)
790	REG_L	v0, FRAME_EPC(a1)
791 #	mtc0	a0, MIPS_COP_0_STATUS		# still exception level
792	mtlo	t0
793	mthi	t1
794	_MTC0	v0, MIPS_COP_0_EXC_PC		# set return address
795	COP0_SYNC
796	move	k1, a1
797	REG_L	AT, FRAME_AST(k1)
798	REG_L	v0, FRAME_V0(k1)
799	REG_L	v1, FRAME_V1(k1)
800	REG_L	a0, FRAME_A0(k1)
801	REG_L	a1, FRAME_A1(k1)
802	REG_L	a2, FRAME_A2(k1)
803	REG_L	a3, FRAME_A3(k1)
804	REG_L	t0, FRAME_T0(k1)
805	REG_L	t1, FRAME_T1(k1)
806	REG_L	t2, FRAME_T2(k1)
807	REG_L	t3, FRAME_T3(k1)
808	REG_L	t4, FRAME_T4(k1)
809	REG_L	t5, FRAME_T5(k1)
810	REG_L	t6, FRAME_T6(k1)
811	REG_L	t7, FRAME_T7(k1)
812	REG_L	s0, FRAME_S0(k1)
813	REG_L	s1, FRAME_S1(k1)
814	REG_L	s2, FRAME_S2(k1)
815	REG_L	s3, FRAME_S3(k1)
816	REG_L	s4, FRAME_S4(k1)
817	REG_L	s5, FRAME_S5(k1)
818	REG_L	s6, FRAME_S6(k1)
819	REG_L	s7, FRAME_S7(k1)
820	REG_L	t8, FRAME_T8(k1)
821	REG_L	t9, FRAME_T9(k1)
822	REG_L	k0, FRAME_SR(k1)
823	DYNAMIC_STATUS_MASK_TOUSER(k0,ra)	# machine dependent masking
824	REG_L	gp, FRAME_GP(k1)
825	REG_L	sp, FRAME_SP(k1)
826	REG_L	s8, FRAME_S8(k1)
827	REG_L	ra, FRAME_RA(k1)
828	mtc0	k0, MIPS_COP_0_STATUS		# restore status
829	COP0_SYNC
830	nop
831	nop
832	eret					# return to interrupted point
833	.set	at
834END(MIPSX(UserGenException))
835
836/*
837 * mipsN_SystemCall
838 *
839 * Save user context in u_pcb, then call syscall() to process a system call.
840 * The context can be manipulated alternatively via curproc->p_md.md_regs;
841 */
842NESTED_NOPROFILE(MIPSX(SystemCall), CALLFRAME_SIZ, ra)
843	.set	noat
844	.mask	0x80000000, -4
845	lw	k1, _C_LABEL(curpcb)
846	#nop					# -slip-
847	addu	k1, k1, USPACE - FRAME_SIZ
848	#REG_S	AT, FRAME_AST(k1)
849	REG_S	v0, FRAME_V0(k1)		# syscall #
850	REG_S	v1, FRAME_V1(k1)		# used by syscall()
851	mflo	v0
852	REG_S	a0, FRAME_A0(k1)
853	REG_S	a1, FRAME_A1(k1)
854	REG_S	a2, FRAME_A2(k1)
855	REG_S	a3, FRAME_A3(k1)
856	lw	a0, _C_LABEL(curproc)		# 1st arg is curproc
857	mfhi	v1
858	#REG_S	t0, FRAME_T0(k1)		# no need to save temp regs
859	#REG_S	t1, FRAME_T1(k1)
860	#REG_S	t2, FRAME_T2(k1)
861	#REG_S	t3, FRAME_T3(k1)
862	mfc0	a1, MIPS_COP_0_STATUS		# 2nd arg is STATUS
863	#REG_S	t4, FRAME_T4(k1)
864	#REG_S	t5, FRAME_T5(k1)
865	#REG_S	t6, FRAME_T6(k1)
866	#REG_S	t7, FRAME_T7(k1)
867	mfc0	a2, MIPS_COP_0_CAUSE		# 3rd arg is CAUSE
868	REG_S	s0, FRAME_S0(k1)
869	REG_S	s1, FRAME_S1(k1)
870	REG_S	s2, FRAME_S2(k1)
871	REG_S	s3, FRAME_S3(k1)
872	mfc0	a3, MIPS_COP_0_EXC_PC		# 4th arg is PC
873	REG_S	s4, FRAME_S4(k1)
874	REG_S	s5, FRAME_S5(k1)
875	REG_S	s6, FRAME_S6(k1)
876	REG_S	s7, FRAME_S7(k1)
877	#REG_S	t8, FRAME_T8(k1)
878	#REG_S	t9, FRAME_T9(k1)
879	REG_S	gp, FRAME_GP(k1)
880	REG_S	sp, FRAME_SP(k1)
881	REG_S	s8, FRAME_S8(k1)
882	REG_S	ra, FRAME_RA(k1)
883	REG_S	a1, FRAME_SR(k1)
884	REG_S	v0, FRAME_MULLO(k1)
885	REG_S	v1, FRAME_MULHI(k1)
886	REG_S	a3, FRAME_EPC(k1)
887#ifdef IPL_ICU_MASK
888	.set at
889	lw	t0, _C_LABEL(md_imask)
890	sw	t0, FRAME_PPL(k1)
891	.set noat
892#endif
893	addu	sp, k1, -CALLFRAME_SIZ
894#ifdef __GP_SUPPORT__
895	la	gp, _C_LABEL(_gp)		# switch to kernel GP
896#endif
897/*
898 * Turn off fpu and enter kernel mode
899 */
900	.set	at
901	lw	t1, P_MD_SYSCALL(a0)		# t1 = syscall
902	and	t0, a1, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_KSU_MASK)
903	.set	noat
904#if defined(DDB) || defined(DEBUG) || defined(KGDB)
905	move	ra, a3
906	sw	ra, CALLFRAME_RA(sp)
907#endif
908/*
909 * Call the system call handler.
910 */
911	mtc0	t0, MIPS_COP_0_STATUS		# re-enable interrupts
912	COP0_SYNC
913	jal	t1
914	nop
915/*
916 * Check pending asynchronous traps.
917 */
918	lw	t0, _C_LABEL(curproc)
919	lw	t0, P_MD_ASTPENDING(t0)
920	beq	t0, zero, 1f
921	nop
922/*
923 * We have pending asynchronous traps; all the state is already saved.
924 */
925	jal	_C_LABEL(ast)
926	lw	a0, CALLFRAME_SIZ + FRAME_EPC(sp)
9271:
928/*
929 * Restore user registers and return.
930 * First disable interrupts and set exception level.
931 */
932	mtc0	zero, MIPS_COP_0_STATUS		# disable int
933	COP0_SYNC
934	nop					# 3 op delay
935	nop
936	nop
937
938	li	v0, MIPS_SR_EXL
939	mtc0	v0, MIPS_COP_0_STATUS		# set exception level
940	COP0_SYNC
941	nop					# 3 op delay
942	nop
943	nop
944/*
945 * Restore user registers and return.
946 */
947	addu	a1, sp, CALLFRAME_SIZ
948#ifdef IPL_ICU_MASK
949	.set at
950	lw	t0, FRAME_PPL(a1)
951	sw	t0, _C_LABEL(md_imask)
952	jal	_C_LABEL(md_imask_update)
953	nop
954	addu	a1, sp, CALLFRAME_SIZ
955	.set noat
956#endif
957 #	REG_L	a0, FRAME_SR(a1)
958	REG_L	t0, FRAME_MULLO(a1)
959	REG_L	t1, FRAME_MULHI(a1)
960	REG_L	v0, FRAME_EPC(a1)		# might be changed in syscall
961 #	mtc0	a0, MIPS_COP_0_STATUS		# this should disable interrupts
962	mtlo	t0
963	mthi	t1
964	_MTC0	v0, MIPS_COP_0_EXC_PC		# set return address
965	COP0_SYNC
966	move	k1, a1
967	REG_L	AT, FRAME_AST(k1)
968	REG_L	v0, FRAME_V0(k1)
969	REG_L	v1, FRAME_V1(k1)
970	REG_L	a0, FRAME_A0(k1)
971	REG_L	a1, FRAME_A1(k1)
972	REG_L	a2, FRAME_A2(k1)
973	REG_L	a3, FRAME_A3(k1)
974	REG_L	t0, FRAME_T0(k1)
975	REG_L	t1, FRAME_T1(k1)
976	REG_L	t2, FRAME_T2(k1)
977	REG_L	t3, FRAME_T3(k1)
978	REG_L	t4, FRAME_T4(k1)
979	REG_L	t5, FRAME_T5(k1)
980	REG_L	t6, FRAME_T6(k1)
981	REG_L	t7, FRAME_T7(k1)
982	REG_L	s0, FRAME_S0(k1)
983	REG_L	s1, FRAME_S1(k1)
984	REG_L	s2, FRAME_S2(k1)
985	REG_L	s3, FRAME_S3(k1)
986	REG_L	s4, FRAME_S4(k1)
987	REG_L	s5, FRAME_S5(k1)
988	REG_L	s6, FRAME_S6(k1)
989	REG_L	s7, FRAME_S7(k1)
990	REG_L	t8, FRAME_T8(k1)
991	REG_L	t9, FRAME_T9(k1)
992	REG_L	k0, FRAME_SR(k1)
993	DYNAMIC_STATUS_MASK_TOUSER(k0,ra)	# machine dependent masking
994	REG_L	gp, FRAME_GP(k1)
995	REG_L	sp, FRAME_SP(k1)
996	REG_L	s8, FRAME_S8(k1)
997	REG_L	ra, FRAME_RA(k1)
998	mtc0	k0, MIPS_COP_0_STATUS
999	COP0_SYNC
1000	nop
1001	nop
1002	nop
1003
1004	eret					# return to syscall point
1005	.set	at
1006END(MIPSX(SystemCall))
1007
1008/*
1009 * Panic on cache errors.  A lot more could be done to recover
1010 * from some types of errors but it is tricky.
1011 */
1012NESTED_NOPROFILE(MIPSX(cacheException), KERNFRAME_SIZ, ra)
1013	.set	noat
1014	.mask	0x80000000, -4
1015#ifdef sbmips	/* XXX!  SB-1 needs a real cache error handler */
1016	eret
1017	nop
1018#endif
1019	la	k0, panic			# return to panic
1020	la	a0, 9f				# panicstr
1021	_MFC0	a1, MIPS_COP_0_ERROR_PC
1022	mfc0	a2, MIPS_COP_0_ECC
1023	mfc0	a3, MIPS_COP_0_CACHE_ERR
1024
1025	_MTC0	k0, MIPS_COP_0_ERROR_PC		# set return address
1026	COP0_SYNC
1027
1028	mfc0	k0, MIPS_COP_0_STATUS		# restore status
1029	li	k1, MIPS3_SR_DIAG_PE		# ignore further errors
1030	or	k0, k1
1031	mtc0	k0, MIPS_COP_0_STATUS		# restore status
1032	COP0_SYNC
1033	nop
1034	nop
1035	nop
1036
1037	eret
1038
1039	MSG("cache error @ EPC 0x%x ErrCtl 0x%x CacheErr 0x%x");
1040	.set	at
1041END(MIPSX(cacheException))
1042
1043/*
1044 * mipsX_KernIntr
1045 *
1046 * Handle an interrupt from kernel mode.
1047 * Build intrframe on stack to hold interrupted kernel context, then
1048 * call cpu_intr() to process it.
1049 *
1050 */
1051NESTED_NOPROFILE(MIPSX(KernIntr), KERNFRAME_SIZ, ra)
1052	.set	noat
1053	.mask	0x80000000, -4
1054	subu	sp, sp, KERNFRAME_SIZ
1055/*
1056 * Save the relevant kernel registers onto the stack.
1057 * We don't need to save s0 - s8, sp and gp because
1058 * the compiler does it for us.
1059 */
1060	REG_S	AT, TF_BASE+TF_REG_AST(sp)
1061	REG_S	v0, TF_BASE+TF_REG_V0(sp)
1062	REG_S	v1, TF_BASE+TF_REG_V1(sp)
1063	mflo	v0
1064	mfhi	v1
1065	REG_S	a0, TF_BASE+TF_REG_A0(sp)
1066	REG_S	a1, TF_BASE+TF_REG_A1(sp)
1067	REG_S	a2, TF_BASE+TF_REG_A2(sp)
1068	REG_S	a3, TF_BASE+TF_REG_A3(sp)
1069	mfc0	a0, MIPS_COP_0_STATUS		# 1st arg is STATUS
1070	REG_S	t0, TF_BASE+TF_REG_T0(sp)
1071	REG_S	t1, TF_BASE+TF_REG_T1(sp)
1072	REG_S	t2, TF_BASE+TF_REG_T2(sp)
1073	REG_S	t3, TF_BASE+TF_REG_T3(sp)
1074	mfc0	a1, MIPS_COP_0_CAUSE		# 2nd arg is CAUSE
1075	REG_S	t4, TF_BASE+TF_REG_T4(sp)
1076	REG_S	t5, TF_BASE+TF_REG_T5(sp)
1077	REG_S	t6, TF_BASE+TF_REG_T6(sp)
1078	REG_S	t7, TF_BASE+TF_REG_T7(sp)
1079	mfc0	a2, MIPS_COP_0_EXC_PC		# 3rd arg is exception PC
1080	REG_S	t8, TF_BASE+TF_REG_T8(sp)
1081	REG_S	t9, TF_BASE+TF_REG_T9(sp)
1082	REG_S	ra, TF_BASE+TF_REG_RA(sp)
1083	REG_S	a0, TF_BASE+TF_REG_SR(sp)
1084	REG_S	v0, TF_BASE+TF_REG_MULLO(sp)
1085	REG_S	v1, TF_BASE+TF_REG_MULHI(sp)
1086	REG_S	a2, TF_BASE+TF_REG_EPC(sp)
1087/*
1088 * Call the interrupt handler.
1089 */
1090#if defined(DDB) || defined(DEBUG) || defined(KGDB)
1091	move	ra, a2
1092	sw	ra, KERNFRAME_RA(sp)		# for debugging
1093#endif
1094#ifdef IPL_ICU_MASK
1095	.set at
1096	lw	t0, _C_LABEL(md_imask)
1097	sw	t0, TF_BASE+TF_PPL(sp)
1098	.set noat
1099#endif
1100	mtc0	zero, MIPS_COP_0_STATUS		# Reset exl, trap possible.
1101	COP0_SYNC
1102	jal	_C_LABEL(cpu_intr)
1103	and	a3, a0, a1			# 4th is STATUS & CAUSE
1104/*
1105 * Restore registers and return from the interrupt.
1106 */
1107	mtc0	zero, MIPS_COP_0_STATUS		# Disable interrupt
1108	COP0_SYNC
1109	nop
1110	nop
1111	nop
1112#ifdef IPL_ICU_MASK
1113	.set at
1114	lw	a0, TF_BASE+TF_PPL(sp)
1115	sw	a0, _C_LABEL(md_imask)
1116	jal	_C_LABEL(md_imask_update)
1117	nop
1118	.set noat
1119#endif
1120	REG_L	a0, TF_BASE+TF_REG_SR(sp)	# ??? why differs ???
1121	DYNAMIC_STATUS_MASK(a0,t0)		# machine dependent masking
1122	REG_L	t0, TF_BASE+TF_REG_MULLO(sp)
1123	REG_L	t1, TF_BASE+TF_REG_MULHI(sp)
1124	REG_L	v0, TF_BASE+TF_REG_EPC(sp)
1125	mtc0	a0, MIPS_COP_0_STATUS		# restore the SR, disable intrs
1126	COP0_SYNC
1127	mtlo	t0
1128	mthi	t1
1129	_MTC0	v0, MIPS_COP_0_EXC_PC		# set return address
1130	COP0_SYNC
1131
1132	REG_L	AT, TF_BASE+TF_REG_AST(sp)
1133	REG_L	v0, TF_BASE+TF_REG_V0(sp)
1134	REG_L	v1, TF_BASE+TF_REG_V1(sp)
1135	REG_L	a0, TF_BASE+TF_REG_A0(sp)
1136	REG_L	a1, TF_BASE+TF_REG_A1(sp)
1137	REG_L	a2, TF_BASE+TF_REG_A2(sp)
1138	REG_L	a3, TF_BASE+TF_REG_A3(sp)
1139	REG_L	t0, TF_BASE+TF_REG_T0(sp)
1140	REG_L	t1, TF_BASE+TF_REG_T1(sp)
1141	REG_L	t2, TF_BASE+TF_REG_T2(sp)
1142	REG_L	t3, TF_BASE+TF_REG_T3(sp)
1143	REG_L	t4, TF_BASE+TF_REG_T4(sp)
1144	REG_L	t5, TF_BASE+TF_REG_T5(sp)
1145	REG_L	t6, TF_BASE+TF_REG_T6(sp)
1146	REG_L	t7, TF_BASE+TF_REG_T7(sp)
1147	REG_L	t8, TF_BASE+TF_REG_T8(sp)
1148	REG_L	t9, TF_BASE+TF_REG_T9(sp)
1149	REG_L	ra, TF_BASE+TF_REG_RA(sp)
1150	addu	sp, sp, KERNFRAME_SIZ		# restore kernel SP
1151	eret					# return to interrupted point
1152	.set	at
1153END(MIPSX(KernIntr))
1154
1155/*----------------------------------------------------------------------------
1156 * XXX this comment block should be updated XXX
1157 * mipsN_UserIntr --
1158 *
1159 *	Handle an interrupt from user mode.
1160 *	Note: we save minimal state in the u.u_pcb struct and use the standard
1161 *	kernel stack since there has to be a u page if we came from user mode.
1162 *	If there is a pending software interrupt, then save the remaining state
1163 *	and call softintr(). This is all because if we call switch() inside
1164 *	cpu_intr(), not all the user registers have been saved in u.u_pcb.
1165 *
1166 * Results:
1167 * 	None.
1168 *
1169 * Side effects:
1170 *	None.
1171 *
1172 *----------------------------------------------------------------------------
1173 */
1174NESTED_NOPROFILE(MIPSX(UserIntr), CALLFRAME_SIZ, ra)
1175	.set	noat
1176	.mask	0x80000000, -4
1177/*
1178 * Save the relevant user registers into the u_pcb.
1179 * We don't need to save s0 - s8 because the compiler does it for us.
1180 */
1181	lw	k1, _C_LABEL(curpcb)
1182	#nop					# -slip-
1183	addu	k1, k1, USPACE - FRAME_SIZ
1184	REG_S	AT, FRAME_AST(k1)
1185	REG_S	v0, FRAME_V0(k1)
1186	REG_S	v1, FRAME_V1(k1)
1187	mflo	v0
1188	REG_S	a0, FRAME_A0(k1)
1189	REG_S	a1, FRAME_A1(k1)
1190	REG_S	a2, FRAME_A2(k1)
1191	REG_S	a3, FRAME_A3(k1)
1192	mfhi	v1
1193	REG_S	t0, FRAME_T0(k1)
1194	REG_S	t1, FRAME_T1(k1)
1195	REG_S	t2, FRAME_T2(k1)
1196	REG_S	t3, FRAME_T3(k1)
1197	mfc0	a0, MIPS_COP_0_STATUS		# 1st arg is STATUS
1198	REG_S	t4, FRAME_T4(k1)
1199	REG_S	t5, FRAME_T5(k1)
1200	REG_S	t6, FRAME_T6(k1)
1201	REG_S	t7, FRAME_T7(k1)
1202	mfc0	a1, MIPS_COP_0_CAUSE		# 2nd arg is CAUSE
1203	REG_S	t8, FRAME_T8(k1)
1204	REG_S	t9, FRAME_T9(k1)
1205	REG_S	gp, FRAME_GP(k1)
1206	REG_S	sp, FRAME_SP(k1)
1207	mfc0	a2, MIPS_COP_0_EXC_PC		# 3rd arg is PC
1208	REG_S	ra, FRAME_RA(k1)
1209	REG_S	a0, FRAME_SR(k1)
1210	REG_S	v0, FRAME_MULLO(k1)
1211	REG_S	v1, FRAME_MULHI(k1)
1212	REG_S	a2, FRAME_EPC(k1)
1213#ifdef IPL_ICU_MASK
1214	.set at
1215	lw	t0, _C_LABEL(md_imask)
1216	sw	t0, FRAME_PPL(k1)
1217	.set noat
1218#endif
1219	addu	sp, k1, -CALLFRAME_SIZ		# switch to kernel SP
1220#ifdef __GP_SUPPORT__
1221	la	gp, _C_LABEL(_gp)		# switch to kernel GP
1222#endif
1223/*
1224 * Turn off fpu and enter kernel mode
1225 */
1226	.set	at
1227	and	t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_INT_IE | MIPS_SR_KSU_MASK)
1228	.set	noat
1229#if defined(DDB) || defined(DEBUG) || defined(KGDB)
1230	move	ra, a2
1231	sw	ra, CALLFRAME_RA(sp)
1232#endif
1233/*
1234 * Call the interrupt handler.
1235 */
1236	mtc0	t0, MIPS_COP_0_STATUS
1237	COP0_SYNC
1238	jal	_C_LABEL(cpu_intr)
1239	and	a3, a0, a1			# 4th is STATUS & CAUSE
1240/*
1241 * Restore registers and return from the interrupt.
1242 */
1243	nop
1244	mtc0	zero, MIPS_COP_0_STATUS
1245	COP0_SYNC
1246	nop					# 3 nop hazard
1247	nop
1248	nop
1249	li	v0, MIPS_SR_EXL
1250	mtc0	v0, MIPS_COP_0_STATUS		# set exception level bit.
1251	COP0_SYNC
1252	nop					# 3 nop hazard
1253	nop
1254	nop
1255	lw	v0, _C_LABEL(curproc)
1256	addu	a1, sp, CALLFRAME_SIZ
1257 #	REG_L	a0, FRAME_SR(a1)
1258	lw	v0, P_MD_ASTPENDING(v0)		# any pending ast?
1259 #	mtc0	a0, MIPS_COP_0_STATUS		# restore the SR, disable intrs
1260/*
1261 * Check pending asynchronous traps.
1262 */
1263	beq	v0, zero, 1f			# if no, skip ast processing
1264	nop					# -delay slot-
1265/*
1266 * We have pending asynchronous traps; save remaining user state in u_pcb.
1267 */
1268	REG_S	s0, FRAME_S0(a1)
1269	REG_S	s1, FRAME_S1(a1)
1270	REG_S	s2, FRAME_S2(a1)
1271	REG_S	s3, FRAME_S3(a1)
1272	REG_S	s4, FRAME_S4(a1)
1273	REG_S	s5, FRAME_S5(a1)
1274	REG_S	s6, FRAME_S6(a1)
1275	REG_S	s7, FRAME_S7(a1)
1276	REG_S	s8, FRAME_S8(a1)
1277	REG_L	a0, FRAME_EPC(a1)	# argument is interrupted PC
1278#ifdef IPL_ICU_MASK
1279	jal	_C_LABEL(spllowersofthigh);
1280	nop
1281#else
1282	li	t0, MIPS_HARD_INT_MASK | MIPS_SR_INT_IE
1283	DYNAMIC_STATUS_MASK(t0,t1)		# machine dependent masking
1284	mtc0	t0, MIPS_COP_0_STATUS		# enable interrupts (spl0)
1285	COP0_SYNC
1286#endif
1287	jal	_C_LABEL(ast)
1288	nop
1289/*
1290 * Restore user registers and return. NOTE: interrupts are enabled.
1291 */
1292	mtc0	zero, MIPS_COP_0_STATUS
1293	COP0_SYNC
1294	nop					# 3 nop delay
1295	nop
1296	nop
1297	li	v0, MIPS_SR_EXL
1298	mtc0	v0, MIPS_COP_0_STATUS		# set exception level bit.
1299	COP0_SYNC
1300	nop					# 3 nop delay
1301	nop
1302	nop
1303
1304	addu	a1, sp, CALLFRAME_SIZ
1305 #	REG_L	a0, FRAME_SR(a1)
1306	REG_L	s0, FRAME_S0(a1)
1307	REG_L	s1, FRAME_S1(a1)
1308	REG_L	s2, FRAME_S2(a1)
1309	REG_L	s3, FRAME_S3(a1)
1310	REG_L	s4, FRAME_S4(a1)
1311	REG_L	s5, FRAME_S5(a1)
1312	REG_L	s6, FRAME_S6(a1)
1313	REG_L	s7, FRAME_S7(a1)
1314	REG_L	s8, FRAME_S8(a1)
1315 #	mtc0	a0, MIPS_COP_0_STATUS		# this should disable interrupts
1316
13171:
1318	REG_L	t0, FRAME_MULLO(a1)
1319	REG_L	t1, FRAME_MULHI(a1)
1320	REG_L	v0, FRAME_EPC(a1)
1321	mtlo	t0
1322	mthi	t1
1323	_MTC0	v0, MIPS_COP_0_EXC_PC		# set return address
1324	COP0_SYNC
1325	nop					# ??? how much delay ???
1326	nop
1327
1328	move	k1, a1
1329#ifdef IPL_ICU_MASK
1330	.set at
1331	lw	t0, FRAME_PPL(k1)
1332	sw	t0, _C_LABEL(md_imask)
1333	jal	_C_LABEL(md_imask_update)
1334	nop
1335	.set noat
1336#endif
1337	REG_L	AT, FRAME_AST(k1)
1338	REG_L	v0, FRAME_V0(k1)
1339	REG_L	v1, FRAME_V1(k1)
1340	REG_L	a0, FRAME_A0(k1)
1341	REG_L	a1, FRAME_A1(k1)
1342	REG_L	a2, FRAME_A2(k1)
1343	REG_L	a3, FRAME_A3(k1)
1344	REG_L	t0, FRAME_T0(k1)
1345	REG_L	t1, FRAME_T1(k1)
1346	REG_L	t2, FRAME_T2(k1)
1347	REG_L	t3, FRAME_T3(k1)
1348	REG_L	t4, FRAME_T4(k1)
1349	REG_L	t5, FRAME_T5(k1)
1350	REG_L	t6, FRAME_T6(k1)
1351	REG_L	t7, FRAME_T7(k1)
1352	REG_L	t8, FRAME_T8(k1)
1353	REG_L	t9, FRAME_T9(k1)
1354	REG_L	k0, FRAME_SR(k1)
1355	DYNAMIC_STATUS_MASK_TOUSER(k0,ra)	# machine dependent masking
1356	REG_L	gp, FRAME_GP(k1)
1357	REG_L	sp, FRAME_SP(k1)
1358	REG_L	ra, FRAME_RA(k1)
1359	mtc0	k0, MIPS_COP_0_STATUS		# restore the SR
1360	COP0_SYNC
1361	nop					# required for QED 5230
1362	nop
1363	eret					# return to interrupted point
1364	.set	at
1365END(MIPSX(UserIntr))
1366
1367
1368/*----------------------------------------------------------------------------
1369 *
1370 *	R4000 TLB exception handlers
1371 *
1372 *----------------------------------------------------------------------------
1373 */
1374
1375
1376/*----------------------------------------------------------------------------
1377 *
1378 * mips3_TLBInvalidException --
1379 *
1380 *	Handle a TLB invalid exception from kernel mode in kernel space.
1381 *	The BaddVAddr, Context, and EntryHi registers contain the failed
1382 *	virtual address.
1383 *
1384 *	The case of wired TLB entries is special.  The wired TLB entries
1385 *	are used to keep the u area TLB's valid.  The PTE entries for these
1386 *	do not have MIPS3_PG_G set; the kernel instead relies
1387 *	on the switch_resume function to set these bits.
1388 *
1389 *	To preserve this situation, we set PG_G bits on the "other" TLB entries
1390 *	when they are wired.
1391 *
1392 * Results:
1393 *	None.
1394 *
1395 * Side effects:
1396 *	None.
1397 *
1398 *----------------------------------------------------------------------------
1399 */
1400LEAF_NOPROFILE(MIPSX(TLBInvalidException))
1401	.set	noat
1402	_MFC0	k0, MIPS_COP_0_BAD_VADDR	# get the fault address
1403	li	k1, VM_MIN_KERNEL_ADDRESS	# compute index
1404	bgez	k0, _C_LABEL(MIPSX(KernGenException))	# full trap processing
1405	subu	k0, k0, k1
1406	lw	k1, _C_LABEL(Sysmapsize)	# index within range?
1407	srl	k0, k0, PGSHIFT
1408	sltu	k1, k0, k1
1409	beq	k1, zero, outofworld		# No. Failing beyond. . .
1410	lw	k1, _C_LABEL(Sysmap)
1411
1412	sll	k0, k0, 2			# compute offset from index
1413	addu	k1, k1, k0
1414	tlbp					# Probe the invalid entry
1415	COP0_SYNC
1416	and	k0, k0, 4			# check even/odd page
1417	nop					# required for QED 5230
1418	bne	k0, zero, KernTLBIOdd
1419	nop
1420
1421	mfc0	k0, MIPS_COP_0_TLB_INDEX
1422	nop
1423	bltz	k0, outofworld			# ASSERT(TLB entry exists)
1424	lw	k0, 0(k1)			# get PTE entry
1425
1426	_SLL	k0, k0, WIRED_SHIFT		# get rid of "wired" bit
1427	_SRL	k0, k0, WIRED_SHIFT
1428	mtc0	k0, MIPS_COP_0_TLB_LO0		# load PTE entry
1429	COP0_SYNC
1430	and	k0, k0, MIPS3_PG_V		# check for valid entry
1431	nop					# required for QED5230
1432	beq	k0, zero, _C_LABEL(MIPSX(KernGenException))	# PTE invalid
1433	lw	k0, 4(k1)			# get odd PTE entry
1434	_SLL	k0, k0, WIRED_SHIFT
1435	mfc0	k1, MIPS_COP_0_TLB_INDEX
1436	_SRL	k0, k0, WIRED_SHIFT
1437	sltiu	k1, k1, MIPS3_TLB_WIRED_UPAGES	# Luckily this is MIPS3_PG_G
1438	or	k1, k1, k0
1439	_MTC0	k0, MIPS_COP_0_TLB_LO1		# load PTE entry
1440	COP0_SYNC
1441	nop
1442	nop					# required for QED5230
1443	tlbwi					# write TLB
1444	COP0_SYNC
1445	nop
1446	nop
1447	nop
1448	nop
1449	nop
1450	eret
1451
1452KernTLBIOdd:
1453	mfc0	k0, MIPS_COP_0_TLB_INDEX
1454	nop
1455	bltz	k0, outofworld			# assert(TLB Entry exists)
1456	lw	k0, 0(k1)			# get PTE entry
1457
1458	_SLL	k0, k0, WIRED_SHIFT		# get rid of wired bit
1459	_SRL	k0, k0, WIRED_SHIFT
1460	_MTC0	k0, MIPS_COP_0_TLB_LO1		# save PTE entry
1461	COP0_SYNC
1462	and	k0, k0, MIPS3_PG_V		# check for valid entry
1463	nop					# required for QED5230
1464	beq	k0, zero, _C_LABEL(MIPSX(KernGenException))	# PTE invalid
1465	lw	k0, -4(k1)			# get even PTE entry
1466	_SLL	k0, k0, WIRED_SHIFT
1467	mfc0	k1, MIPS_COP_0_TLB_INDEX
1468	_SRL	k0, k0, WIRED_SHIFT
1469	sltiu	k1, k1, MIPS3_TLB_WIRED_UPAGES	# Luckily this is MIPS3_PG_G
1470	or	k1, k1, k0
1471	_MTC0	k0, MIPS_COP_0_TLB_LO0		# save PTE entry
1472	COP0_SYNC
1473	nop
1474	nop					# required for QED5230
1475	tlbwi					# update TLB
1476	COP0_SYNC
1477	nop
1478	nop
1479	nop
1480	nop
1481	nop
1482	eret
1483END(MIPSX(TLBInvalidException))
1484
1485/*----------------------------------------------------------------------------
1486 *
1487 * mipsN_TLBMissException --
1488 *
1489 *	Handle a TLB miss exception from kernel mode in kernel space.
1490 *	The BaddVAddr, Context, and EntryHi registers contain the failed
1491 *	virtual address.
1492 *
1493 * Results:
1494 *	None.
1495 *
1496 * Side effects:
1497 *	None.
1498 *
1499 *----------------------------------------------------------------------------
1500 */
1501LEAF_NOPROFILE(MIPSX(TLBMissException))
1502	.set	noat
1503	_MFC0	k0, MIPS_COP_0_BAD_VADDR	# get the fault address
1504	li	k1, VM_MIN_KERNEL_ADDRESS	# compute index
1505	subu	k0, k0, k1
1506	lw	k1, _C_LABEL(Sysmapsize)	# index within range?
1507	srl	k0, k0, PGSHIFT
1508	sltu	k1, k0, k1
1509#ifdef newsmips
1510	/* news5000 has ROM work area at 0xfff00000. */
1511	bne	k1, zero, 1f
1512	nop
1513	j	checkromwork
15141:
1515#else
1516	beq	k1, zero, outofworld		# No. Failing beyond. . .
1517#endif
1518	lw	k1, _C_LABEL(Sysmap)
1519	srl	k0, k0, 1
1520	sll	k0, k0, 3			# compute offset from index
1521	addu	k1, k1, k0
1522	lw	k0, 0(k1)			# get PTE entry
1523	lw	k1, 4(k1)			# get odd PTE entry
1524	_SLL	k0, k0, WIRED_SHIFT		# get rid of "wired" bit
1525	_SRL	k0, k0, WIRED_SHIFT
1526	_MTC0	k0, MIPS_COP_0_TLB_LO0		# load PTE entry
1527	COP0_SYNC
1528	_SLL	k1, k1, WIRED_SHIFT
1529	_SRL	k1, k1, WIRED_SHIFT
1530	_MTC0	k1, MIPS_COP_0_TLB_LO1		# load PTE entry
1531	COP0_SYNC
1532	nop
1533	nop					# required for QED5230
1534	tlbwr					# write TLB
1535	COP0_SYNC
1536	nop
1537	nop
1538	nop
1539	nop
1540	nop
1541	eret
1542
1543outofworld:
1544	/* eret to panic so shutdown can use K2.  Try to ensure valid $sp. */
1545	la	a0,_C_LABEL(panic)
1546	_MFC0	a2, MIPS_COP_0_EXC_PC
1547	move	a1, sp
1548	sll	k0, k0, PGSHIFT
1549	_MTC0	a0, MIPS_COP_0_EXC_PC		# return to panic
1550	COP0_SYNC
1551	li	k1, VM_MIN_KERNEL_ADDRESS
1552	addu	a3, k0, k1
1553#if defined(DDB)
1554	bltz	sp, 1f				# for ddb try to keep frame
1555	nop
1556#endif
1557	la	sp, start			# set sp to a valid place
15581:	la	a0, 9f				# string
1559	eret
1560
1561	.set	at
1562END(MIPSX(TLBMissException))
1563
1564	MSG("TLB out of universe: ksp %p epc %p vaddr %p")
1565
1566/*
1567 * Mark where code entered from exception hander jumptable
1568 * ends, for stack traceback code.
1569 */
1570
1571	.globl	_C_LABEL(MIPSX(exceptionentry_end))
1572_C_LABEL(MIPSX(exceptionentry_end)):
1573
1574/*--------------------------------------------------------------------------
1575 *
1576 * mipsN_SetPID --
1577 *
1578 *	Write the given pid into the TLB pid reg.
1579 *
1580 *	mips3_SetPID(pid)
1581 *		int pid;
1582 *
1583 * Results:
1584 *	None.
1585 *
1586 * Side effects:
1587 *	PID set in the entry hi register.
1588 *
1589 *--------------------------------------------------------------------------
1590 */
1591LEAF(MIPSX(SetPID))
1592	_MTC0	a0, MIPS_COP_0_TLB_HI		# Write the hi reg value
1593	COP0_SYNC
1594	/* XXX simonb: lose these nops for mips32/64? */
1595	nop					# required for QED5230
1596	nop					# required for QED5230
1597	j	ra
1598	nop
1599END(MIPSX(SetPID))
1600
1601/*--------------------------------------------------------------------------
1602 *
1603 * mipsN_TLBUpdate --
1604 *
1605 *	Update the TLB if highreg is found; otherwise, enter the data.
1606 *
1607 *	mips3_TLBUpdate(virpageadr, lowregx)
1608 *		unsigned virpageadr, lowregx;
1609 *
1610 * Results:
1611 *	< 0 if loaded >= 0 if updated.
1612 *
1613 * Side effects:
1614 *	None.
1615 *
1616 *--------------------------------------------------------------------------
1617 */
1618LEAF(MIPSX(TLBUpdate))
1619	mfc0	v1, MIPS_COP_0_STATUS	# Save the status register.
1620	mtc0	zero, MIPS_COP_0_STATUS	# Disable interrupts
1621	COP0_SYNC
1622	and	t1, a0, MIPS3_PG_ODDPG	# t1 = Even/Odd flag
1623	li	v0, (MIPS3_PG_HVPN | MIPS3_PG_ASID)
1624	and	a0, a0, v0
1625	_MFC0	t0, MIPS_COP_0_TLB_HI		# Save current PID
1626	_MTC0	a0, MIPS_COP_0_TLB_HI		# Init high reg
1627	COP0_SYNC
1628	and	a2, a1, MIPS3_PG_G		# Copy global bit
1629	nop
1630	nop
1631	tlbp					# Probe for the entry.
1632	COP0_SYNC
1633	_SLL	a1, a1, WIRED_SHIFT		# Clear top 34 bits of EntryLo
1634	_SRL	a1, a1, WIRED_SHIFT
1635	bne	t1, zero, 2f			# Decide even odd
1636	mfc0	v0, MIPS_COP_0_TLB_INDEX	# See what we got
1637# EVEN
1638	nop
1639	bltz	v0, 1f				# index < 0 => !found
1640	nop
1641	nop					# required for QED5230
1642
1643	tlbr					# update, read entry first
1644	COP0_SYNC
1645	nop
1646	nop
1647	nop
1648	_MTC0	a1, MIPS_COP_0_TLB_LO0		# init low reg0.
1649	COP0_SYNC
1650	nop
1651	nop					# required for QED5230
1652	tlbwi					# update slot found
1653	COP0_SYNC
1654	nop					# required for QED5230
1655	nop					# required for QED5230
1656	b	4f
1657	nop
16581:
1659#if defined(MIPS3) && defined(MIPS3_4100)		/* VR4100 core */
1660	lw	v0, _C_LABEL(default_pg_mask)	# default_pg_mask declared
1661	mtc0	v0, MIPS_COP_0_TLB_PG_MASK	#	in mips_machdep.c
1662#else
1663	mtc0	zero, MIPS_COP_0_TLB_PG_MASK	# init mask.
1664#endif
1665	COP0_SYNC
1666	_MTC0	a0, MIPS_COP_0_TLB_HI		# init high reg.
1667	COP0_SYNC
1668	_MTC0	a1, MIPS_COP_0_TLB_LO0		# init low reg0.
1669	COP0_SYNC
1670	_MTC0	a2, MIPS_COP_0_TLB_LO1		# init low reg1.
1671	COP0_SYNC
1672	nop
1673	nop					# required for QED5230
1674	tlbwr					# enter into a random slot
1675	COP0_SYNC
1676	nop					# required for QED5230
1677	nop					# required for QED5230
1678	b	4f
1679	nop
1680# ODD
16812:
1682	nop
1683	bltz	v0, 3f				# index < 0 => !found
1684	nop
1685	nop					# required for QED5230
1686
1687	tlbr					# read the entry first
1688	COP0_SYNC
1689	nop
1690	nop
1691	nop
1692	_MTC0	a1, MIPS_COP_0_TLB_LO1		# init low reg1.
1693	COP0_SYNC
1694	nop
1695	nop					# required for QED5230
1696	tlbwi					# update slot found
1697	COP0_SYNC
1698	nop					# required for QED5230
1699	nop					# required for QED5230
1700	b	4f
1701	nop
17023:
1703#if defined(MIPS3) && defined(MIPS3_4100)		/* VR4100 core */
1704	lw	v0, _C_LABEL(default_pg_mask)	# default_pg_mask declared
1705	mtc0	v0, MIPS_COP_0_TLB_PG_MASK	#	in mips_machdep.c
1706#else
1707	mtc0	zero, MIPS_COP_0_TLB_PG_MASK	# init mask.
1708#endif
1709	COP0_SYNC
1710	_MTC0	a0, MIPS_COP_0_TLB_HI		# init high reg.
1711	COP0_SYNC
1712	_MTC0	a2, MIPS_COP_0_TLB_LO0		# init low reg0.
1713	COP0_SYNC
1714	_MTC0	a1, MIPS_COP_0_TLB_LO1		# init low reg1.
1715	COP0_SYNC
1716	nop
1717	nop					# required for QED5230
1718	tlbwr					# enter into a random slot
1719	COP0_SYNC
17204:						# Make shure pipeline
1721	nop					# advances before we
1722	nop					# uses the tlb.
1723	nop
1724	nop
1725	_MTC0	t0, MIPS_COP_0_TLB_HI		# restore PID
1726	COP0_SYNC
1727	nop					# required for QED5230
1728	nop					# required for QED5230
1729	j	ra
1730	mtc0	v1, MIPS_COP_0_STATUS		# Restore the status register
1731	COP0_SYNC				# XXXX - not executed!!
1732END(MIPSX(TLBUpdate))
1733
1734/*--------------------------------------------------------------------------
1735 *
1736 * mipsN_TLBRead --
1737 *
1738 *	Read the TLB entry.
1739 *
1740 *	mips3_TLBRead(entry, tlb)
1741 *		unsigned entry;
1742 *		struct tlb *tlb;
1743 *
1744 * Results:
1745 *	None.
1746 *
1747 * Side effects:
1748 *	tlb will contain the TLB entry found.
1749 *
1750 *--------------------------------------------------------------------------
1751 */
1752LEAF(MIPSX(TLBRead))
1753	mfc0	v1, MIPS_COP_0_STATUS		# Save the status register.
1754	mtc0	zero, MIPS_COP_0_STATUS		# Disable interrupts
1755	COP0_SYNC
1756	nop
1757	mfc0	t6, MIPS_COP_0_TLB_PG_MASK	# save current pgMask
1758	nop
1759	_MFC0	t0, MIPS_COP_0_TLB_HI		# Get current PID
1760
1761	mtc0	a0, MIPS_COP_0_TLB_INDEX	# Set the index register
1762	COP0_SYNC
1763	nop
1764	nop					# required for QED5230
1765	tlbr					# Read from the TLB
1766	COP0_SYNC
1767	nop
1768	nop
1769	nop
1770	mfc0	t2, MIPS_COP_0_TLB_PG_MASK	# fetch the pgMask
1771	_MFC0	t3, MIPS_COP_0_TLB_HI		# fetch the hi entry
1772	_MFC0	t4, MIPS_COP_0_TLB_LO0		# See what we got
1773	_MFC0	t5, MIPS_COP_0_TLB_LO1		# See what we got
1774	_MTC0	t0, MIPS_COP_0_TLB_HI		# restore PID
1775	COP0_SYNC
1776	mtc0	t6, MIPS_COP_0_TLB_PG_MASK	# restore pgMask
1777	COP0_SYNC
1778	nop
1779	nop
1780	nop					# wait for PID active
1781	mtc0	v1, MIPS_COP_0_STATUS		# Restore the status register
1782	COP0_SYNC
1783	nop
1784	sw	t2, 0(a1)
1785	sw	t3, 4(a1)
1786	sw	t4, 8(a1)
1787	j	ra
1788	sw	t5, 12(a1)
1789END(MIPSX(TLBRead))
1790
1791#if defined(MIPS3) && !defined(MIPS3_5900)
1792/*----------------------------------------------------------------------------
1793 *
1794 * mips3_VCED --
1795 *
1796 *	Handle virtual coherency exceptions.
1797 *	Called directly from the mips3 execption-table code.
1798 *	only k0, k1 are avaiable on entry
1799 *
1800 * Results:
1801 *	None.
1802 *
1803 * Side effects:
1804 *	Remaps the conflicting address as uncached and returns
1805 *	from the execption.
1806 *
1807 *	NB: cannot be profiled, all registers are user registers on entry.
1808 *
1809 *----------------------------------------------------------------------------
1810 */
1811LEAF_NOPROFILE(MIPSX(VCED))
1812	.set	noat
1813	mfc0	k0, MIPS_COP_0_BAD_VADDR	# fault addr.
1814	li	k1, -16
1815	and	k0, k1
1816	cache	(CACHE_R4K_SD | CACHEOP_R4K_HIT_WB_INV), 0(k0)
1817	cache	(CACHE_R4K_D | CACHEOP_R4K_HIT_INV), 0(k0)
1818#ifdef DEBUG
1819	mfc0	k0, MIPS_COP_0_BAD_VADDR
1820	la	k1, VCED_vaddr
1821	sw	k0, 0(k1)
1822	mfc0	k0, MIPS_COP_0_EXC_PC
1823	la	k1, VCED_epc
1824	sw	k0, 0(k1)
1825	la	k1, VCED_count		# count number of exceptions
1826	srl	k0, k0, 26		# position upper 4 bits of VA
1827	and	k0, k0, 0x3c		# mask it off
1828	add	k1, k0			# get address of count table
1829	lw	k0, 0(k1)
1830	addu	k0, 1
1831	sw	k0, 0(k1)
1832#endif
1833	eret
1834	.set	at
1835
1836#ifdef DEBUG
1837	.data
1838	.globl	_C_LABEL(VCED_count)
1839_C_LABEL(VCED_count):
1840	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1841	.globl	_C_LABEL(VCED_epc)
1842_C_LABEL(VCED_epc):
1843	.word	0
1844	.globl	_C_LABEL(VCED_vaddr)
1845_C_LABEL(VCED_vaddr):
1846	.word	0
1847	.text
1848#endif
1849END(MIPSX(VCED))
1850
1851LEAF_NOPROFILE(MIPSX(VCEI))
1852	.set	noat
1853	mfc0	k0, MIPS_COP_0_BAD_VADDR	# fault addr.
1854	cache	(CACHE_R4K_SD | CACHEOP_R4K_HIT_WB_INV), 0(k0)
1855	cache	(CACHE_R4K_I | CACHEOP_R4K_HIT_INV), 0(k0)
1856#ifdef DEBUG
1857	mfc0	k0, MIPS_COP_0_BAD_VADDR
1858	la	k1, VCEI_vaddr
1859	sw	k0, 0(k1)
1860	la	k1, VCEI_count		# count number of exceptions
1861	srl	k0, k0, 26		# position upper 4 bits of VA
1862	and	k0, k0, 0x3c		# mask it off
1863	add	k1, k0			# get address of count table
1864	lw	k0, 0(k1)
1865	addu	k0, 1
1866	sw	k0, 0(k1)
1867#endif
1868	eret
1869	.set	at
1870
1871#ifdef DEBUG
1872	.data
1873	.globl	_C_LABEL(VCEI_count)
1874_C_LABEL(VCEI_count):
1875	.word	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1876	.globl	_C_LABEL(VCEI_vaddr)
1877_C_LABEL(VCEI_vaddr):
1878	.word	0
1879	.text
1880#endif
1881END(MIPSX(VCEI))
1882#endif /* MIPS3 && !MIPS3_5900 */
1883
1884/*
1885 * mipsN_proc_trampoline()
1886 *
1887 * Arrange for a function to be invoked neatly, after a cpu_switch().
1888 * Call the service function with one argument, specified by the s0
1889 * and s1 respectively.  There is no need register save operation.
1890 */
1891LEAF(MIPSX(proc_trampoline))
1892	jal	ra, s0
1893	move	a0, s1
1894	.set	noat
1895	#
1896	# Make sure to disable interrupts here, as otherwise
1897	# we can take an interrupt *after* EXL is set, and
1898	# end up returning to a bogus PC since the PC is not
1899	# saved if EXL=1.
1900	#
1901	mtc0	zero, MIPS_COP_0_STATUS		# disable int
1902	COP0_SYNC
1903	nop					# 3 op delay
1904	nop
1905	nop
1906	li	a0, MIPS_SR_EXL			# set exception level
1907	mtc0	a0, MIPS_COP_0_STATUS
1908	COP0_SYNC
1909	nop
1910	nop
1911	addu	a1, sp, CALLFRAME_SIZ
1912 #	REG_L	a0, FRAME_SR(a1)
1913	REG_L	t0, FRAME_MULLO(a1)
1914	REG_L	t1, FRAME_MULHI(a1)
1915	REG_L	v0, FRAME_EPC(a1)
1916	mtlo	t0
1917	mthi	t1
1918	_MTC0	v0, MIPS_COP_0_EXC_PC
1919	COP0_SYNC
1920	nop
1921	move	k1, a1
1922#ifdef IPL_ICU_MASK
1923	.set at
1924	lw	t0, FRAME_PPL(k1)
1925	sw	t0, _C_LABEL(md_imask)
1926	jal	_C_LABEL(md_imask_update)
1927	nop
1928	.set noat
1929#endif
1930	REG_L	AT, FRAME_AST(k1)
1931	REG_L	v0, FRAME_V0(k1)
1932	REG_L	v1, FRAME_V1(k1)
1933	REG_L	a0, FRAME_A0(k1)
1934	REG_L	a1, FRAME_A1(k1)
1935	REG_L	a2, FRAME_A2(k1)
1936	REG_L	a3, FRAME_A3(k1)
1937	REG_L	t0, FRAME_T0(k1)
1938	REG_L	t1, FRAME_T1(k1)
1939	REG_L	t2, FRAME_T2(k1)
1940	REG_L	t3, FRAME_T3(k1)
1941	REG_L	t4, FRAME_T4(k1)
1942	REG_L	t5, FRAME_T5(k1)
1943	REG_L	t6, FRAME_T6(k1)
1944	REG_L	t7, FRAME_T7(k1)
1945	REG_L	s0, FRAME_S0(k1)
1946	REG_L	s1, FRAME_S1(k1)
1947	REG_L	s2, FRAME_S2(k1)
1948	REG_L	s3, FRAME_S3(k1)
1949	REG_L	s4, FRAME_S4(k1)
1950	REG_L	s5, FRAME_S5(k1)
1951	REG_L	s6, FRAME_S6(k1)
1952	REG_L	s7, FRAME_S7(k1)
1953	REG_L	t8, FRAME_T8(k1)
1954	REG_L	t9, FRAME_T9(k1)
1955	REG_L	k0, FRAME_SR(k1)
1956	DYNAMIC_STATUS_MASK(k0,sp)		# machine dependent masking
1957	REG_L	gp, FRAME_GP(k1)
1958	REG_L	s8, FRAME_S8(k1)
1959	REG_L	ra, FRAME_RA(k1)
1960	REG_L	sp, FRAME_SP(k1)
1961	mtc0	k0, MIPS_COP_0_STATUS
1962	COP0_SYNC
1963	nop
1964	nop
1965	eret
1966	.set	at
1967END(MIPSX(proc_trampoline))
1968
1969/*
1970 * void mipsN_cpu_switch_resume(struct proc *newproc)
1971 *
1972 * Wiredown the USPACE of newproc in TLB entry#0.  Check whether target
1973 * USPACE is already in another place of TLB before that, and make
1974 * sure TBIS(it) in the case.
1975 */
1976LEAF_NOPROFILE(MIPSX(cpu_switch_resume))
1977	lw	a1, P_MD_UPTE_0(a0)		# a1 = upte[0]
1978	lw	a2, P_MD_UPTE_1(a0)		# a2 = upte[1]
1979	lw	v0, P_ADDR(a0)			# va = p->p_addr
1980	li	s0, MIPS_KSEG2_START
1981	blt	v0, s0, resume
1982	nop
1983
1984	and	s0, v0, MIPS3_PG_ODDPG
1985	beq	s0, zero, entry0
1986	nop
1987
1988	PANIC("USPACE sat on odd page boundary")
1989
1990entry0:
1991	_MTC0	v0, MIPS_COP_0_TLB_HI		# VPN = va
1992	COP0_SYNC
1993	nop
1994	nop
1995	tlbp					# probe VPN
1996	COP0_SYNC
1997	nop
1998	nop
1999	mfc0	s0, MIPS_COP_0_TLB_INDEX
2000	nop
2001	bltz	s0, entry0set
2002	sll	s0, s0, 13			# PAGE_SHIFT + 1
2003	la	s0, MIPS_KSEG0_START(s0)
2004	_MTC0	s0, MIPS_COP_0_TLB_HI
2005	COP0_SYNC
2006	_MTC0	zero, MIPS_COP_0_TLB_LO0
2007	COP0_SYNC
2008	_MTC0	zero, MIPS_COP_0_TLB_LO1
2009	COP0_SYNC
2010	nop
2011	nop
2012	tlbwi
2013	COP0_SYNC
2014	nop
2015	nop
2016	_MTC0	v0, MIPS_COP_0_TLB_HI		# set VPN again
2017	COP0_SYNC
2018entry0set:
2019	mtc0	zero, MIPS_COP_0_TLB_INDEX	# TLB entry #0
2020	COP0_SYNC
2021	or	a1, MIPS3_PG_G
2022	_MTC0	a1, MIPS_COP_0_TLB_LO0		# upte[0] | PG_G
2023	COP0_SYNC
2024	or	a2, MIPS3_PG_G
2025	_MTC0	a2, MIPS_COP_0_TLB_LO1		# upte[1] | PG_G
2026	COP0_SYNC
2027	nop
2028	nop
2029	tlbwi					# set TLB entry #0
2030	COP0_SYNC
2031	nop
2032	nop
2033
2034resume:
2035	j	ra
2036	nop
2037END(MIPSX(cpu_switch_resume))
2038
2039/*
2040 * void mipsN_TBIS(vaddr_t va)
2041 *
2042 * Invalidate a TLB entry which has the given vaddr and ASID if found.
2043 */
2044LEAF_NOPROFILE(MIPSX(TBIS))
2045	mfc0	v1, MIPS_COP_0_STATUS		# save status register
2046	mtc0	zero, MIPS_COP_0_STATUS		# disable interrupts
2047	COP0_SYNC
2048
2049	li	v0, (MIPS3_PG_HVPN | MIPS3_PG_ASID)
2050	_MFC0	t0, MIPS_COP_0_TLB_HI		# save current ASID
2051	mfc0	t3, MIPS_COP_0_TLB_PG_MASK	# save current pgMask
2052	and	a0, a0, v0			# make sure valid entryHi
2053	_MTC0	a0, MIPS_COP_0_TLB_HI		# look for the vaddr & ASID
2054	COP0_SYNC
2055	nop
2056	nop
2057	tlbp					# probe the entry in question
2058	COP0_SYNC
2059	nop
2060	nop
2061	mfc0	v0, MIPS_COP_0_TLB_INDEX	# see what we got
2062	#nop					# -slip-
2063	#nop					# -slip-
2064	bltz	v0, 1f				# index < 0 then skip
2065	li	t1, MIPS_KSEG0_START		# invalid address
2066	sll	v0, v0, 13			# PAGE_SHIFT + 1
2067	addu	t1, t1, v0
2068	_MTC0	t1, MIPS_COP_0_TLB_HI		# make entryHi invalid
2069	COP0_SYNC
2070	_MTC0	zero, MIPS_COP_0_TLB_LO0	# zero out entryLo0
2071	COP0_SYNC
2072	_MTC0	zero, MIPS_COP_0_TLB_LO1	# zero out entryLo1
2073	COP0_SYNC
2074	mtc0	zero, MIPS_COP_0_TLB_PG_MASK	# zero out pageMask
2075	COP0_SYNC
2076	nop
2077	nop
2078	tlbwi
2079	COP0_SYNC
2080	nop
2081	nop
20821:
2083	_MTC0	t0, MIPS_COP_0_TLB_HI		# restore current ASID
2084	COP0_SYNC
2085	mtc0	t3, MIPS_COP_0_TLB_PG_MASK	# restore pgMask
2086	COP0_SYNC
2087	nop
2088	nop
2089	j	ra
2090	mtc0	v1, MIPS_COP_0_STATUS		# restore status register
2091	COP0_SYNC				# XXXX - not executed!!
2092END(MIPSX(TBIS))
2093
2094/*
2095 * void mips3_TBIAP(int sizeofTLB)
2096 *
2097 * Invalidate TLB entries belong to per process user spaces while
2098 * leaving entries for kernel space marked global intact.
2099 */
2100LEAF_NOPROFILE(MIPSX(TBIAP))
2101	mfc0	v1, MIPS_COP_0_STATUS		# save status register
2102	mtc0	zero, MIPS_COP_0_STATUS		# disable interrupts
2103	COP0_SYNC
2104
2105	move	t2, a0
2106	mfc0	t1, MIPS_COP_0_TLB_WIRED
2107	li	v0, MIPS_KSEG0_START		# invalid address
2108	mfc0	t3, MIPS_COP_0_TLB_PG_MASK	# save current pgMask
2109
2110	# do {} while (t1 < t2)
21111:
2112	mtc0	t1, MIPS_COP_0_TLB_INDEX	# set index
2113	COP0_SYNC
2114	sll	t4, t1, 13			# PAGE_SHIFT + 1
2115	nop
2116	/* XXX simonb: lose this nop for mips32/64? */
2117	nop
2118	tlbr					# obtain an entry
2119	COP0_SYNC
2120	/* XXX simonb: lose these nops for mips32/64? */
2121	nop
2122	nop
2123	nop
2124	_MFC0	a0, MIPS_COP_0_TLB_LO1
2125	and	a0, a0, MIPS3_PG_G		# check to see it has G bit
2126	bnez	a0, 2f
2127	addu	t4, t4, v0
2128
2129	_MTC0	t4, MIPS_COP_0_TLB_HI		# make entryHi invalid
2130	COP0_SYNC
2131	_MTC0	zero, MIPS_COP_0_TLB_LO0	# zero out entryLo0
2132	COP0_SYNC
2133	_MTC0	zero, MIPS_COP_0_TLB_LO1	# zero out entryLo1
2134	COP0_SYNC
2135	mtc0	zero, MIPS_COP_0_TLB_PG_MASK	# zero out mask entry
2136	COP0_SYNC
2137	/* XXX simonb: lose these nops for mips32/64? */
2138	nop
2139	nop
2140	tlbwi					# invalidate the TLB entry
2141	COP0_SYNC
21422:
2143	addu	t1, t1, 1
2144	bne	t1, t2, 1b
2145	nop
2146
2147	mtc0	t3, MIPS_COP_0_TLB_PG_MASK	# restore pgMask
2148	COP0_SYNC
2149	/* XXX simonb: lose these nops for mips32/64? */
2150	nop
2151	nop
2152	j	ra				# new ASID will be set soon
2153	mtc0	v1, MIPS_COP_0_STATUS		# restore status register
2154	COP0_SYNC				# XXXX - not executed!!
2155END(MIPSX(TBIAP))
2156
2157/*
2158 * void mipsN_TBIA(int sizeofTLB)
2159 *
2160 * Invalidate all of non-wired TLB entries.
2161 */
2162LEAF_NOPROFILE(MIPSX(TBIA))
2163	mfc0	v1, MIPS_COP_0_STATUS		# save status register
2164	mtc0	zero, MIPS_COP_0_STATUS		# disable interrupts
2165	COP0_SYNC
2166
2167	li	v0, MIPS_KSEG0_START		# invalid address
2168	_MFC0	t0, MIPS_COP_0_TLB_HI		# save current ASID
2169	mfc0	t1, MIPS_COP_0_TLB_WIRED
2170	mfc0	t2, MIPS_COP_0_TLB_PG_MASK	# save current pgMask
2171
2172	_MTC0	zero, MIPS_COP_0_TLB_LO0	# zero out entryLo0
2173	COP0_SYNC
2174	_MTC0	zero, MIPS_COP_0_TLB_LO1	# zero out entryLo1
2175	COP0_SYNC
2176	mtc0	zero, MIPS_COP_0_TLB_PG_MASK	# zero out pageMask
2177	COP0_SYNC
2178
2179	# do {} while (t1 < a0)
21801:
2181	mtc0	t1, MIPS_COP_0_TLB_INDEX	# set TLBindex
2182	COP0_SYNC
2183	sll	t4, t1, 13			# PAGE_SHIFT + 1
2184	add	t4, v0, t4
2185	_MTC0	t4, MIPS_COP_0_TLB_HI		# make entryHi invalid
2186	COP0_SYNC
2187	nop
2188	nop
2189	tlbwi					# clear the entry
2190	COP0_SYNC
2191	addu	t1, t1, 1			# increment index
2192	bne	t1, a0, 1b
2193	nop
2194
2195	_MTC0	t0, MIPS_COP_0_TLB_HI		# restore ASID
2196	COP0_SYNC
2197	mtc0	t2, MIPS_COP_0_TLB_PG_MASK	# restore pgMask
2198	COP0_SYNC
2199	nop
2200	nop
2201	j	ra
2202	mtc0	v1, MIPS_COP_0_STATUS		# restore status register
2203	COP0_SYNC				# XXXX - not executed!!
2204END(MIPSX(TBIA))
2205
2206	.data
2207
2208	.globl _C_LABEL(MIPSX(locoresw))
2209_C_LABEL(MIPSX(locoresw)):
2210	.word _C_LABEL(MIPSX(cpu_switch_resume))
2211	.word _C_LABEL(MIPSX(proc_trampoline))
2212	.word _C_LABEL(mips_idle)
2213
2214MIPSX(excpt_sw):
2215	####
2216	#### The kernel exception handlers.
2217	####
2218	.word _C_LABEL(MIPSX(KernIntr))		#  0 external interrupt
2219	.word _C_LABEL(MIPSX(KernGenException))	#  1 TLB modification
2220	.word _C_LABEL(MIPSX(TLBInvalidException))# 2 TLB miss (LW/I-fetch)
2221	.word _C_LABEL(MIPSX(TLBInvalidException))# 3 TLB miss (SW)
2222	.word _C_LABEL(MIPSX(KernGenException))	#  4 address error (LW/I-fetch)
2223	.word _C_LABEL(MIPSX(KernGenException))	#  5 address error (SW)
2224	.word _C_LABEL(MIPSX(KernGenException))	#  6 bus error (I-fetch)
2225	.word _C_LABEL(MIPSX(KernGenException))	#  7 bus error (load or store)
2226	.word _C_LABEL(MIPSX(KernGenException))	#  8 system call
2227	.word _C_LABEL(MIPSX(KernGenException))	#  9 breakpoint
2228	.word _C_LABEL(MIPSX(KernGenException))	# 10 reserved instruction
2229	.word _C_LABEL(MIPSX(KernGenException))	# 11 coprocessor unusable
2230	.word _C_LABEL(MIPSX(KernGenException))	# 12 arithmetic overflow
2231	.word _C_LABEL(MIPSX(KernGenException))	# 13 r4k trap exception
2232#if defined(MIPS3) && !defined(MIPS3_5900)
2233	.word _C_LABEL(mips3_VCEI)		# 14 r4k virt coherence
2234#else
2235	.word _C_LABEL(MIPSX(KernGenException))	# 14 reserved
2236#endif
2237	.word _C_LABEL(MIPSX(KernGenException))	# 15 r4k FP exception
2238	.word _C_LABEL(MIPSX(KernGenException))	# 16 reserved
2239	.word _C_LABEL(MIPSX(KernGenException))	# 17 reserved
2240	.word _C_LABEL(MIPSX(KernGenException))	# 18 reserved
2241	.word _C_LABEL(MIPSX(KernGenException))	# 19 reserved
2242	.word _C_LABEL(MIPSX(KernGenException))	# 20 reserved
2243	.word _C_LABEL(MIPSX(KernGenException))	# 21 reserved
2244	.word _C_LABEL(MIPSX(KernGenException))	# 22 reserved
2245	.word _C_LABEL(MIPSX(KernGenException))	# 23 watch exception
2246	.word _C_LABEL(MIPSX(KernGenException))	# 24 reserved
2247	.word _C_LABEL(MIPSX(KernGenException))	# 25 reserved
2248	.word _C_LABEL(MIPSX(KernGenException))	# 26 reserved
2249	.word _C_LABEL(MIPSX(KernGenException))	# 27 reserved
2250	.word _C_LABEL(MIPSX(KernGenException))	# 28 reserved
2251	.word _C_LABEL(MIPSX(KernGenException))	# 29 reserved
2252	.word _C_LABEL(MIPSX(KernGenException))	# 30 reserved
2253#if defined(MIPS3) && !defined(MIPS3_5900)
2254	.word _C_LABEL(mips3_VCED)		# 31 v. coherence exception data
2255#else
2256	.word _C_LABEL(MIPSX(KernGenException))	# 31 reserved
2257#endif
2258	#####
2259	##### The user exception handlers.
2260	#####
2261	.word _C_LABEL(MIPSX(UserIntr))		#  0
2262	.word _C_LABEL(MIPSX(UserGenException))	#  1
2263	.word _C_LABEL(MIPSX(UserGenException))	#  2
2264	.word _C_LABEL(MIPSX(UserGenException))	#  3
2265	.word _C_LABEL(MIPSX(UserGenException))	#  4
2266	.word _C_LABEL(MIPSX(UserGenException))	#  5
2267	.word _C_LABEL(MIPSX(UserGenException))	#  6
2268	.word _C_LABEL(MIPSX(UserGenException))	#  7
2269	.word _C_LABEL(MIPSX(SystemCall))	#  8
2270	.word _C_LABEL(MIPSX(UserGenException))	#  9
2271	.word _C_LABEL(MIPSX(UserGenException))	# 10
2272	.word _C_LABEL(MIPSX(UserGenException))	# 11
2273	.word _C_LABEL(MIPSX(UserGenException))	# 12
2274	.word _C_LABEL(MIPSX(UserGenException))	# 13
2275#if defined(MIPS3) && !defined(MIPS3_5900)
2276	.word _C_LABEL(mips3_VCEI)		# 14
2277#else
2278	.word _C_LABEL(MIPSX(UserGenException))	# 14
2279#endif
2280	.word _C_LABEL(MIPSX(UserGenException))	# 15
2281	.word _C_LABEL(MIPSX(UserGenException))	# 16
2282	.word _C_LABEL(MIPSX(UserGenException))	# 17
2283	.word _C_LABEL(MIPSX(UserGenException))	# 18
2284	.word _C_LABEL(MIPSX(UserGenException))	# 19
2285	.word _C_LABEL(MIPSX(UserGenException))	# 20
2286	.word _C_LABEL(MIPSX(UserGenException))	# 21
2287	.word _C_LABEL(MIPSX(UserGenException))	# 22
2288	.word _C_LABEL(MIPSX(UserGenException))	# 23
2289	.word _C_LABEL(MIPSX(UserGenException))	# 24
2290	.word _C_LABEL(MIPSX(UserGenException))	# 25
2291	.word _C_LABEL(MIPSX(UserGenException))	# 26
2292	.word _C_LABEL(MIPSX(UserGenException))	# 27
2293	.word _C_LABEL(MIPSX(UserGenException))	# 28
2294	.word _C_LABEL(MIPSX(UserGenException))	# 29
2295	.word _C_LABEL(MIPSX(UserGenException))	# 30
2296#if defined(MIPS3) && !defined(MIPS3_5900)
2297	.word _C_LABEL(mips3_VCED)		# 31 v. coherence exception data
2298#else
2299	.word _C_LABEL(MIPSX(UserGenException))	# 31
2300#endif
2301