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