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