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