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