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