xref: /netbsd-src/sys/arch/mac68k/mac68k/locore.s (revision 3ced769fe7a334399fec58501b354c1d245c9a4f)
1/*	$NetBSD: locore.s,v 1.184 2024/02/28 13:05:40 thorpej Exp $	*/
2
3/*
4 * Copyright (c) 1988 University of Utah.
5 * Copyright (c) 1982, 1990 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * the Systems Programming Group of the University of Utah Computer
10 * Science Department.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37/*-
38 * Copyright (C) 1993	Allen K. Briggs, Chris P. Caputo,
39 *			Michael L. Finch, Bradley A. Grantham, and
40 *			Lawrence A. Kesteloot
41 * All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 *    notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 *    notice, this list of conditions and the following disclaimer in the
50 *    documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 *    must display the following acknowledgement:
53 *	This product includes software developed by the Alice Group.
54 * 4. The names of the Alice Group or any of its members may not be used
55 *    to endorse or promote products derived from this software without
56 *    specific prior written permission.
57 *
58 * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR
59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
60 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
61 * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT,
62 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
63 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
64 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
65 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
66 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
67 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68 *
69 */
70
71/*
72 * from: Utah $Hdr: locore.s 1.58 91/04/22$
73 *
74 *	@(#)locore.s	7.11 (Berkeley) 5/9/91
75 */
76
77#include "opt_compat_netbsd.h"
78#include "opt_compat_sunos.h"
79#include "opt_ddb.h"
80#include "opt_fpu_emulate.h"
81#include "opt_kgdb.h"
82#include "opt_lockdebug.h"
83#include "opt_fpsp.h"
84#include "opt_m68k_arch.h"
85
86#include "assym.h"
87
88#include <machine/asm.h>
89#include <machine/trap.h>
90
91/*
92 * This is for kvm_mkdb, and should be the address of the beginning
93 * of the kernel text segment (not necessarily the same as kernbase).
94 */
95	.text
96GLOBAL(kernel_text)
97
98#include <mac68k/mac68k/vectors.s>
99#include <mac68k/mac68k/macglobals.s>
100
101/*
102 * Initialization
103 */
104
105	.data
106| Scratch memory.  Careful when messing with these...
107ASLOCAL(longscratch)
108	.long	0
109ASLOCAL(longscratch2)
110	.long	0
111ASLOCAL(pte_tmp)			| for get_pte()
112	.long	0
113GLOBAL(macos_crp1)
114	.long	0
115GLOBAL(macos_crp2)
116	.long	0
117GLOBAL(macos_tc)
118	.long	0
119GLOBAL(macos_tt0)
120	.long	0
121GLOBAL(macos_tt1)
122	.long	0
123GLOBAL(bletch)
124	.long	0
125
126BSS(esym,4)
127
128ASENTRY_NOPROFILE(start)
129	movw	#PSL_HIGHIPL,%sr	| no interrupts.  ever.
130	lea	_ASM_LABEL(tmpstk),%sp	| give ourselves a temporary stack
131
132	movl	#CACHE_OFF,%d0
133	movc	%d0,%cacr		| clear and disable on-chip cache(s)
134
135	/* Initialize source/destination control registers for movs */
136	movql	#FC_USERD,%d0		| user space
137	movc	%d0,%sfc		|   as source
138	movc	%d0,%dfc		|   and destination of transfers
139
140	/*
141	 * Some parameters provided by MacOS
142	 *
143	 * LAK: This section is the new way to pass information from the booter
144	 * to the kernel.  At A1 there is an environment variable which has
145	 * a bunch of stuff in ascii format, "VAR=value\0VAR=value\0\0".
146	 */
147	movl	%a1,%sp@-		| Address of buffer
148	movl	%d4,%sp@-		| Some flags... (mostly not used)
149	jbsr	_C_LABEL(getenvvars)	| Parse the environment buffer
150	addql	#8,%sp
151
152	/* Determine MMU/MPU from what we can test empirically */
153	movl	#0x200,%d0		| data freeze bit
154	movc	%d0,%cacr		|   only exists on 68030
155	movc	%cacr,%d0		| read it back
156	tstl	%d0			| zero?
157	jeq	Lnot68030		| yes, we have 68020/68040
158
159	movl	#CACHE_OFF,%d0		| disable and clear both caches
160	movc	%d0,%cacr
161	lea	_C_LABEL(mmutype),%a0	| no, we have 68030
162	movl	#MMU_68030,%a0@		| set to reflect 68030 PMMU
163	lea	_C_LABEL(cputype),%a0
164	movl	#CPU_68030,%a0@		| and 68030 MPU
165	jra	Lstart1
166
167Lnot68030:
168	bset	#31,%d0			| data cache enable bit
169	movc	%d0,%cacr		|   only exists on 68040
170	movc	%cacr,%d0		| read it back
171	tstl	%d0			| zero?
172	beq	Lis68020		| yes, we have 68020
173
174	movql	#CACHE40_OFF,%d0	| now turn it back off
175	movc	%d0,%cacr		|   before we access any data
176	.word	0xf4f8			| cpusha bc ;push and invalidate caches
177	lea	_C_LABEL(mmutype),%a0
178	movl	#MMU_68040,%a0@		| Reflect 68040 MMU
179	lea	_C_LABEL(cputype),%a0
180	movl	#CPU_68040,%a0@		| and 68040 MPU
181	jra	Lstart1
182
183Lis68020:
184	movl	#CACHE_OFF,%d0		| disable and clear cache
185	movc	%d0,%cacr
186	lea	_C_LABEL(mmutype),%a0	| Must be 68020+68851
187	movl	#MMU_68851,%a0@		| Reflect 68851 PMMU
188	lea	_C_LABEL(cputype),%a0
189	movl	#CPU_68020,%a0@		| and 68020 MPU
190
191Lstart1:
192	/*
193	 * Now that we know what CPU we have, initialize the address error
194	 * and bus error handlers in the vector table:
195	 *
196	 *	vectab+8	bus error
197	 *	vectab+12	address error
198	 */
199	lea	_C_LABEL(cputype),%a0
200	lea	_C_LABEL(vectab),%a2
201#if defined(M68040)
202	cmpl	#CPU_68040,%a0@		| 68040?
203	jne	1f			| no, skip
204	movl	#_C_LABEL(buserr40),%a2@(8)
205	movl	#_C_LABEL(addrerr4060),%a2@(12)
206	jra	Lstart2
2071:
208#endif
209#if defined(M68020) || defined(M68030)
210	cmpl	#CPU_68040,%a0@		| 68040?
211	jeq	1f			| yes, skip
212	movl	#_C_LABEL(busaddrerr2030),%a2@(8)
213	movl	#_C_LABEL(busaddrerr2030),%a2@(12)
214	jra	Lstart2
2151:
216#endif
217	/* Config botch; no hope. */
218	movl	_C_LABEL(MacOSROMBase),%a1 | Load MacOS ROMBase
219	jra	Ldoboot1
220
221Lstart2:
222	jbsr	_C_LABEL(setmachdep)	| Set some machine-dep stuff
223	jbsr	_C_LABEL(consinit)	| XXX Should only be if graybar on
224
225/*
226 * Figure out MacOS mappings and bootstrap NetBSD
227 */
228	lea	_C_LABEL(macos_tc),%a0	| get current %TC
229	cmpl	#MMU_68040,_C_LABEL(mmutype) | check to see if 68040
230	jeq	Lget040TC
231
232	pmove	%tc,%a0@
233	jra	Lstart3
234
235Lget040TC:
236#if 0
237	movl	_C_LABEL(current_mac_model),%a1	 | if an AV Mac, save current
238	cmpl	#MACH_CLASSAV,%a1@(CPUINFO_CLASS) | %TC so internal video will
239	jne	LnotAV				 | get configured
240#endif
241	.long	0x4e7a0003		| movc %tc,%d0
242	jra	LsaveTC
243LnotAV:
244	movql	#0,%d0			| otherwise,
245	.long	0x4e7b0003		| movc %d0,%tc ;Disable MMU
246LsaveTC:
247	movl	%d0,%a0@
248
249Lstart3:
250	movl	%a0@,%sp@-		| get Mac OS mapping, relocate video,
251	jbsr	_C_LABEL(bootstrap_mac68k) |   bootstrap pmap, et al.
252	addql	#4,%sp
253
254	/*
255	 * Set up the vector table, and race to get the MMU
256	 * enabled.
257	 */
258	movl	#_C_LABEL(vectab),%d0	| set Vector Base Register
259	movc	%d0,%vbr
260
261	movl	_C_LABEL(Sysseg),%a1	| system segment table addr
262	addl	_C_LABEL(load_addr),%a1	| Make it physical addr
263	cmpl	#MMU_68040,_C_LABEL(mmutype)
264	jne	Lenablepre040MMU	| if not 040, skip
265
266	movql	#0,%d0
267	.long	0x4e7b0003		| movc %d0,%tc   ;Disable MMU
268	.long	0x4e7b0004		| movc %d0,%itt0 ;Disable itt0
269	.long	0x4e7b0005		| movc %d0,%itt1 ;Disable itt1
270	.long	0x4e7b0006		| movc %d0,%dtt0 ;Disable dtt0
271	.long	0x4e7b0007		| movc %d0,%dtt1 ;Disable dtt1
272	movl	%a1,%d1
273	.word	0xf518			| pflusha
274	.long	0x4e7b1807		| movc %d1,%srp
275
276#if defined(DJMEMCMAX)
277	movl	%a3,%sp@-
278	cmpl	#MACH_MACC610,_C_LABEL(machineid)
279	jeq	Ldjmemc610
280	cmpl	#MACH_MACQ610,_C_LABEL(machineid)
281	jeq	Ldjmemc610
282	cmpl	#MACH_MACC650,_C_LABEL(machineid)
283	jeq	Ldjmemccfg
284	cmpl	#MACH_MACQ650,_C_LABEL(machineid)
285	jeq	Ldjmemccfg
286	cmpl	#MACH_MACQ800,_C_LABEL(machineid)
287	jeq	Ldjmemccfg
288
289	jra	Lnodjmemc
290
291Ldjmemccfg:
292	movl	#0x50f0e00c,%a0
293	movl	%a0@,%d0	| determine where RAM SIMMs start
294	andl	#0x000000FF,%d0
295	addl	#0x10,%d0	| bank 3 start
296	addl	#0x10,%d0	| bank 4 start
297
298	movl	#0x50f0e014,%a0
299	movl	%d0,%a0@+	| bank 4
300	addl	#0x10,%d0
301	movl	%d0,%a0@+	| bank 5
302	addl	#0x10,%d0
303
304	movl	%d0,%a0@+	| bank 6
305	addl	#0x10,%d0
306	movl	%d0,%a0@+	| bank 7
307	addl	#0x10,%d0
308	movl	%d0,%a0@+	| bank 8
309	addl	#0x10,%d0
310	movl	%d0,%a0@+	| bank 9
311	addl	#0x10,%d0
312	jra	Ldjmemctop
313
314Ldjmemc610:
315	movl	#0x50f0e00c,%a0
316	movl	%a0@,%d0	| determine where RAM SIMMs start
317	andl	#0x000000FF,%d0
318	addl	#0x10,%d0	| bank 3 start
319
320	movl	#0x50f0e014,%a0
321	movl	%d0,%a0@+	| bank 4
322	addl	#0x10,%d0
323	movl	%d0,%a0@+	| bank 5
324	movl	%d0,%a0@+	| bank 6
325	addl	#0x10,%d0
326	movl	%d0,%a0@+	| bank 7
327	movl	%d0,%a0@+	| bank 8
328	addl	#0x10,%d0
329	movl	%d0,%a0@+	| bank 9
330
331Ldjmemctop:
332	movl	#0x50F0E02C,%a0
333	movl	%d0,%a0@	| memtop
334
335	| preserve ~512KB beyond 4MB just in case
336	movl	#0x400000,%a0
337	movl	#0x9000000,%a2
338	movl	#0xFFFF,%d0
339L1stbankcopy1:
340	movl	%a0@+,%a2@+
341	dbra	%d0,L1stbankcopy1
342	movl	#0xFFFF,%d0
343L1stbankcopy2:
344	movl	%a0@+,%a2@+
345	dbra	%d0,L1stbankcopy2
346
347	lea	_ASM_LABEL(Lsetup1stbank),%a0
348	movl	#0x8800000,%a2	| Pick a location that should be in bank 4
349	movl	#0x64,%d0
350Ldjcopy:
351	movl	%a0@+,%a2@+
352	dbra	%d0,Ldjcopy
353
354	movl	#0x8800000,%a0
355	lea	_ASM_LABEL(Ldjmemcdone),%a2
356	jmp	%a0@
357
358Lsetup1stbank:
359	| now configure banks 2 & 3
360	movl	#0x50f0e00c,%a0
361	movl	%a0@,%d0	| determine where RAM SIMMs start
362	andl	#0x000000FF,%d0
363	movl	%d0,%a0@+
364	addl	#0x10,%d0	| bank 3 start
365	movl	%d0,%a0@
366
367	| and return to where we came from.
368	jmp	%a2@
369
370Ldjmemcdone:
371	movl	#0x400000,%a2
372	movl	#0x9000000,%a0
373	movl	#0xFFFF,%d0
374Lcopyback1:
375	movl	%a0@+,%a2@+
376	dbra	%d0,Lcopyback1
377	movl	#0xFFFF,%d0
378Lcopyback2:
379	movl	%a0@+,%a2@+
380	dbra	%d0,Lcopyback2
381
382Lnodjmemc:
383	movl	%sp@+,%a3
384#endif
385
386	movl	#MMU40_TCR_BITS,%d0
387	.long	0x4e7b0003		| movc %d0,%tc   ;Enable MMU
388	movl	#CACHE40_ON,%d0
389	movc	%d0,%cacr		| turn on both caches
390	jra	Lloaddone
391
392Lenablepre040MMU:
393	tstl	_C_LABEL(mmutype)	| TTx instructions will break 68851
394	jgt	LnokillTT
395
396	lea	_ASM_LABEL(longscratch),%a0 | disable TTx registers on 68030
397	movl	#0,%a0@
398	.long	0xf0100800		| movl %a0@,%tt0
399	.long	0xf0100c00		| movl %a0@,%tt1
400
401LnokillTT:
402#if defined(M68020) || defined(M68030)
403	lea	_C_LABEL(protorp),%a0
404	movl	%a1,%a0@(4)		| segtable address
405	pmove	%a0@,%srp		| load the supervisor root pointer
406	pflusha
407	lea	_ASM_LABEL(longscratch),%a2
408	movl	#MMU51_TCR_BITS,%a2@	| value to load %TC with
409	pmove	%a2@,%tc		| load it
410#endif /* M68020 || M68030 */
411
412Lloaddone:
413
414/*
415 * Should be running mapped from this point on
416 */
417	lea	_ASM_LABEL(tmpstk),%sp	| temporary stack
418/* call final pmap setup */
419	jbsr	_C_LABEL(pmap_bootstrap_finalize)
420/* set kernel stack, user SP, lwp0, and initial pcb */
421	movl	_C_LABEL(lwp0uarea),%a1	| get lwp0 uarea
422	lea	%a1@(USPACE-4),%sp	|   set kernel stack to end of area
423	movl	#USRSTACK-4,%a2
424	movl	%a2,%usp		| init %USP
425
426/* flush TLB and turn on caches */
427	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
428	jeq	Ltbia040		| yes, cache already on
429	pflusha
430	movl	#CACHE_ON,%d0
431	movc	%d0,%cacr		| clear cache(s)
432#ifdef __notyet__
433	tstl	_C_LABEL(ectype)
434	jeq	Lnocache0
435					| Enable external cache here
436#endif
437	jra	Lnocache0
438
439Ltbia040:
440	.word	0xf518			| pflusha
441
442Lnocache0:
443/* Final setup for call to main(). */
444	jbsr	_C_LABEL(mac68k_init)
445
446/*
447 * Create a fake exception frame so that cpu_lwp_fork() can copy it.
448 * main() nevers returns; we exit to user mode from a forked process
449 * later on.
450 */
451	clrw	%sp@-			| vector offset/frame type
452	clrl	%sp@-			| PC - filled in by "execve"
453	movw	#PSL_USER,%sp@-		| in user mode
454	clrl	%sp@-			| stack adjust count and padding
455	lea	%sp@(-64),%sp		| construct space for D0-D7/A0-A7
456	lea	_C_LABEL(lwp0),%a0	| save pointer to frame
457	movl	%sp,%a0@(L_MD_REGS)	|   in lwp0.l_md.md_regs
458
459	jra	_C_LABEL(main)		| main()
460	PANIC("main() returned")
461	/* NOTREACHED */
462
463/*
464 * Trap/interrupt vector routines
465 */
466#include <m68k/m68k/trap_subr.s>
467
468/*
469 * Use common m68k bus error and address error handlers.
470 */
471	.data
472GLOBAL(mac68k_a2_fromfault)
473	.long	0
474GLOBAL(m68k_fault_addr)
475	.long	0
476
477#include <m68k/m68k/busaddrerr.s>
478
479/*
480 * FP exceptions.
481 */
482ENTRY_NOPROFILE(fpfline)
483#if defined(M68040)
484	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
485	jne	Lfp_unimp		| no, skip FPSP
486	cmpw	#0x202c,%sp@(6)		| format type 2?
487	jne	_C_LABEL(illinst)	| no, not an FP emulation
488Ldofp_unimp:
489#ifdef FPSP
490	jmp	_ASM_LABEL(fpsp_unimp)	| yes, go handle it
491#endif
492Lfp_unimp:
493#endif /* M68040 */
494#ifdef FPU_EMULATE
495	clrl	%sp@-			| stack adjust count
496	moveml	#0xFFFF,%sp@-		| save registers
497	moveq	#T_FPEMULI,%d0		| denote as FP emulation trap
498	jra	_ASM_LABEL(fault)	| do it
499#else
500	jra	_C_LABEL(illinst)
501#endif
502
503ENTRY_NOPROFILE(fpunsupp)
504#if defined(M68040)
505	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
506	jne	_C_LABEL(illinst)	| no, treat as illinst
507#ifdef FPSP
508	jmp	_ASM_LABEL(fpsp_unsupp)	| yes, go handle it
509#endif
510Lfp_unsupp:
511#endif /* M68040 */
512#ifdef FPU_EMULATE
513	clrl	%sp@-			| stack adjust count
514	moveml	#0xFFFF,%sp@-		| save registers
515	moveq	#T_FPEMULD,%d0		| denote as FP emulation trap
516	jra	_ASM_LABEL(fault)	| do it
517#else
518	jra	_C_LABEL(illinst)
519#endif
520
521/*
522 * Handles all other FP coprocessor exceptions.
523 * Note that since some FP exceptions generate mid-instruction frames
524 * and may cause signal delivery, we need to test for stack adjustment
525 * after the trap call.
526 */
527ENTRY_NOPROFILE(fpfault)
528	clrl	%sp@-		| stack adjust count
529	moveml	#0xFFFF,%sp@-	| save user registers
530	movl	%usp,%a0	| and save
531	movl	%a0,%sp@(FR_SP)	|   the user stack pointer
532	clrl	%sp@-		| no VA arg
533	movl	_C_LABEL(curpcb),%a0 | current pcb
534	lea	%a0@(PCB_FPCTX),%a0 | address of FP savearea
535	fsave	%a0@		| save state
536#if defined(M68040) || defined(M68060)
537	/* always null state frame on 68040, 68060 */
538	cmpl	#FPU_68040,_C_LABEL(fputype)
539	jge	Lfptnull
540#endif
541	tstb	%a0@		| null state frame?
542	jeq	Lfptnull	| yes, safe
543	clrw	%d0		| no, need to tweak BIU
544	movb	%a0@(1),%d0	| get frame size
545	bset	#3,%a0@(0,%d0:w) | set exc_pend bit of BIU
546Lfptnull:
547	fmovem	%fpsr,%sp@-	| push %fpsr as code argument
548	frestore %a0@		| restore state
549	movl	#T_FPERR,%sp@-	| push type arg
550	jra	_ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup
551
552/*
553 * Other exceptions only cause four and six word stack frame and require
554 * no post-trap stack adjustment.
555 */
556
557ENTRY_NOPROFILE(badtrap)
558	moveml	#0xC0C0,%sp@-		| save scratch regs
559	movw	%sp@(22),%sp@-		| push exception vector info
560	clrw	%sp@-
561	movl	%sp@(22),%sp@-		| and PC
562	jbsr	_C_LABEL(straytrap)	| report
563	addql	#8,%sp			| pop args
564	moveml	%sp@+,#0x0303		| restore regs
565	jra	_ASM_LABEL(rei)		| all done
566
567ENTRY_NOPROFILE(trap0)
568	clrl	%sp@-			| pad SR to longword
569	moveml	#0xFFFF,%sp@-		| save user registers
570	movl	%usp,%a0		| save %USP
571	movl	%a0,%sp@(FR_SP)		|   in the savearea
572	movl	%d0,%sp@-		| push syscall number
573	jbsr	_C_LABEL(syscall)	| handle it
574	addql	#4,%sp			| pop syscall arg
575	tstl	_C_LABEL(astpending)
576	jne	.Lrei2
577	tstb	_C_LABEL(ssir)
578	jeq	.Ltrap1
579	movw	#SPL1,%sr
580	tstb	_C_LABEL(ssir)
581	jne	.Lsir1
582.Ltrap1:
583	movl	%sp@(FR_SP),%a0		| grab and restore
584	movl	%a0,%usp		|   %USP
585	moveml	%sp@+,#0x7FFF		| restore most registers
586	addql	#8,%sp			| pop SSP and align word
587	rte
588
589/*
590 * Trap 12 is the entry point for the cachectl "syscall" (both HP-UX & BSD)
591 *	cachectl(command, addr, length)
592 * command in %d0, addr in %a1, length in %d1
593 */
594ENTRY_NOPROFILE(trap12)
595	movl	_C_LABEL(curlwp),%a0
596	movl	%a0@(L_PROC),%sp@-	| push proc pointer
597	movl	%d1,%sp@-		| push length
598	movl	%a1,%sp@-		| push addr
599	movl	%d0,%sp@-		| push command
600	jbsr	_C_LABEL(cachectl1)	| do it
601	lea	%sp@(16),%sp		| pop args
602	jra	_ASM_LABEL(rei)		| all done
603
604/*
605 * Trace (single-step) trap.  Kernel-mode is special.
606 * User mode traps are simply passed on to trap().
607 */
608ENTRY_NOPROFILE(trace)
609	clrl	%sp@-			| stack adjust count
610	moveml	#0xFFFF,%sp@-
611	moveq	#T_TRACE,%d0
612
613	| Check PSW and see what happen.
614	|   T=0 S=0	(should not happen)
615	|   T=1 S=0	trace trap from user mode
616	|   T=0 S=1	trace trap on a trap instruction
617	|   T=1 S=1	trace trap from system mode (kernel breakpoint)
618
619	movw	%sp@(FR_HW),%d1		| get PSW
620	notw	%d1			| XXX no support for T0 on 680[234]0
621	andw	#PSL_TS,%d1		| from system mode (T=1, S=1)?
622	jeq	Lkbrkpt			| yes, kernel breakpoint
623	jra	_ASM_LABEL(fault)	| no, user-mode fault
624
625/*
626 * Trap 15 is used for:
627 *	- GDB breakpoints (in user programs)
628 *	- KGDB breakpoints (in the kernel)
629 *	- trace traps for SUN binaries (not fully supported yet)
630 * User mode traps are simply passed to trap().
631 */
632ENTRY_NOPROFILE(trap15)
633	clrl	%sp@-			| stack adjust count
634	moveml	#0xFFFF,%sp@-
635	moveq	#T_TRAP15,%d0
636	movw	%sp@(FR_HW),%d1		| get PSW
637	andw	#PSL_S,%d1		| from system mode?
638	jne	Lkbrkpt			| yes, kernel breakpoint
639	jra	_ASM_LABEL(fault)	| no, user-mode fault
640
641Lkbrkpt: | Kernel-mode breakpoint or trace trap. (%d0=trap_type)
642	| Save the system %sp rather than the user %usp.
643	movw	#PSL_HIGHIPL,%sr	| lock out interrupts
644	lea	%sp@(FR_SIZE),%a6	| Save stack pointer
645	movl	%a6,%sp@(FR_SP)		|  from before trap
646
647	| If were are not on tmpstk switch to it.
648	| (so debugger can change the stack pointer)
649	movl	%a6,%d1
650	cmpl	#_ASM_LABEL(tmpstk),%d1
651	jls	Lbrkpt2			| already on tmpstk
652	| Copy frame to the temporary stack
653	movl	%sp,%a0			| %a0=src
654	lea	_ASM_LABEL(tmpstk)-96,%a1 | %a1=dst
655	movl	%a1,%sp			| %sp=new frame
656	moveq	#FR_SIZE,%d1
657Lbrkpt1:
658	movl	%a0@+,%a1@+
659	subql	#4,%d1
660	bgt	Lbrkpt1
661
662Lbrkpt2:
663	| Call the trap handler for the kernel debugger.
664	| Do not call trap() to do it, so that we can
665	| set breakpoints in trap() if we want.  We know
666	| the trap type is either T_TRACE or T_BREAKPOINT.
667	| If we have both DDB and KGDB, let KGDB see it first,
668	| because KGDB will just return 0 if not connected.
669	| Save args in %d2, %a2
670	movl	%d0,%d2			| trap type
671	movl	%sp,%a2			| frame ptr
672#ifdef KGDB
673	| Let KGDB handle it (if connected)
674	movl	%a2,%sp@-		| push frame ptr
675	movl	%d2,%sp@-		| push trap type
676	jbsr	_C_LABEL(kgdb_trap)	| handle the trap
677	addql	#8,%sp			| pop args
678	cmpl	#0,%d0			| did kgdb handle it?
679	jne	Lbrkpt3			| yes, done
680#endif
681#ifdef DDB
682	| Let DDB handle it
683	movl	%a2,%sp@-		| push frame ptr
684	movl	%d2,%sp@-		| push trap type
685	jbsr	_C_LABEL(kdb_trap)	| handle the trap
686	addql	#8,%sp			| pop args
687#if 0	/* not needed on hp300 */
688	cmpl	#0,%d0			| did ddb handle it?
689	jne	Lbrkpt3			| yes, done
690#endif
691#endif
692	/* Sun 3 drops into PROM here. */
693Lbrkpt3:
694	| The stack pointer may have been modified, or
695	| data below it modified (by kgdb push call),
696	| so push the hardware frame at the current %sp
697	| before restoring registers and returning.
698
699	movl	%sp@(FR_SP),%a0		| modified %sp
700	lea	%sp@(FR_SIZE),%a1	| end of our frame
701	movl	%a1@-,%a0@-		| copy 2 longs with
702	movl	%a1@-,%a0@-		| ... predecrement
703	movl	%a0,%sp@(FR_SP)		| %sp = h/w frame
704	moveml	%sp@+,#0x7FFF		| restore all but %sp
705	movl	%sp@,%sp		| ... and %sp
706	rte				| all done
707
708/*
709 * Interrupt handlers.
710 *
711 * Most 68k-based Macintosh computers
712 *
713 *      Level 0:        Spurious: ignored
714 *      Level 1:        VIA1 (clock, ADB)
715 *      Level 2:        VIA2 (NuBus, SCSI)
716 *      Level 3:
717 *      Level 4:        Serial (SCC)
718 *      Level 5:
719 *      Level 6:
720 *      Level 7:        Non-maskable: parity errors, RESET button
721 *
722 * On the Q700, Q900 and Q950 in "A/UX mode": this should become:
723 *
724 *	Level 0:        Spurious: ignored
725 *	Level 1:        Software
726 *	Level 2:        VIA2 (except ethernet, sound)
727 *	Level 3:        Ethernet
728 *	Level 4:        Serial (SCC)
729 *	Level 5:        Sound
730 *	Level 6:        VIA1
731 *	Level 7:        NMIs: parity errors, RESET button, YANCC error
732 *
733 * On the 660AV and 840AV:
734 *
735 *	Level 0:        Spurious: ignored
736 *	Level 1:        VIA1 (clock, ADB)
737 *	Level 2:        VIA2 (NuBus, SCSI)
738 *	Level 3:        PSC device interrupt
739 *	Level 4:        PSC DMA and serial
740 *	Level 5:        ???
741 *	Level 6:        ???
742 *	Level 7:        NMIs: parity errors?, RESET button
743 */
744
745ENTRY_NOPROFILE(spurintr)
746	addql	#1,_C_LABEL(intrcnt)+0
747	INTERRUPT_SAVEREG
748	CPUINFO_INCREMENT(CI_NINTR)
749	INTERRUPT_RESTOREREG
750	jra	_ASM_LABEL(rei)
751
752ENTRY_NOPROFILE(intrhand)
753	INTERRUPT_SAVEREG
754	jbsr	_C_LABEL(intr_dispatch)	| call dispatch routine
755	INTERRUPT_RESTOREREG
756	jra	_ASM_LABEL(rei)		| all done
757
758ENTRY_NOPROFILE(lev7intr)
759	addql	#1,_C_LABEL(intrcnt)+16
760	clrl	%sp@-			| pad %SR to longword
761	moveml	#0xFFFF,%sp@-		| save registers
762	movl	%usp,%a0		| and save
763	movl	%a0,%sp@(FR_SP)		|   the user stack pointer
764	jbsr	_C_LABEL(nmihand)	| call handler
765	movl	%sp@(FR_SP),%a0		| restore
766	movl	%a0,%usp		|   %USP
767	moveml	%sp@+,#0x7FFF		| and remaining registers
768	addql	#8,%sp			| pop SSP and align word
769	jra	_ASM_LABEL(rei)
770
771/*
772 * We could tweak rtclock_intr and gain 12 cycles on the 020 and 030 by
773 * saving the status register directly to the stack, but this would lose
774 * badly on the 040.  Aligning the stack takes 10 more cycles than this
775 * code does, so it's a good compromise.
776 *
777 * A pointer to the clockframe is passed as an argument in the usual
778 * fashion.
779 */
780ENTRY_NOPROFILE(rtclock_intr)
781	movl	%sp@(4),%a1		| stash pointer to clockframe
782	movl	%d2,%sp@-		| save %d2
783	movw	%sr,%d2			| save SPL
784					| raise SPL to splclock()
785	movw	_C_LABEL(ipl2psl_table)+IPL_CLOCK*2,%sr
786	movl	%a1,%sp@-		| push pointer to clockframe
787	jbsr	_C_LABEL(hardclock)	| call generic clock int routine
788	addql	#4,%sp			| pop param
789	jbsr	_C_LABEL(mrg_VBLQueue)	| give programs in the VBLqueue a chance
790	addql	#1,_C_LABEL(intrcnt)+32	| record a clock interrupt
791	INTERRUPT_SAVEREG
792	CPUINFO_INCREMENT(CI_NINTR)
793	INTERRUPT_RESTOREREG
794	movw	%d2,%sr			| restore SPL
795	movl	%sp@+,%d2		| restore %d2
796	rts				| go back from whence we came
797
798/*
799 * Emulation of VAX REI instruction.
800 *
801 * This code deals with checking for and servicing ASTs
802 * (profiling, scheduling) and software interrupts (network, softclock).
803 * We check for ASTs first, just like the VAX.  To avoid excess overhead
804 * the T_ASTFLT handling code will also check for software interrupts so we
805 * do not have to do it here.  After identifying that we need an AST we
806 * drop the IPL to allow device interrupts.
807 *
808 * This code is complicated by the fact that sendsig may have been called
809 * necessitating a stack cleanup.
810 */
811
812ASENTRY_NOPROFILE(rei)
813	tstl	_C_LABEL(astpending)	| AST pending?
814	jeq	.Lchksir		| no, go check for SIR
815.Lrei1:
816	btst	#5,%sp@			| yes, are we returning to user mode?
817	jne	.Lchksir		| no, go check for SIR
818	movw	#PSL_LOWIPL,%sr		| lower SPL
819	clrl	%sp@-			| stack adjust
820	moveml	#0xFFFF,%sp@-		| save all registers
821	movl	%usp,%a1		| including
822	movl	%a1,%sp@(FR_SP)		|    %USP
823.Lrei2:
824	clrl	%sp@-			| VA == none
825	clrl	%sp@-			| code == none
826	movl	#T_ASTFLT,%sp@-		| type == async system trap
827	pea	%sp@(12)		| fp == address of trap frame
828	jbsr	_C_LABEL(trap)		| go handle it
829	lea	%sp@(16),%sp		| pop value args
830	movl	%sp@(FR_SP),%a0		| restore %USP
831	movl	%a0,%usp		|   from save area
832	movw	%sp@(FR_ADJ),%d0	| need to adjust stack?
833	jne	.Laststkadj		| yes, go to it
834	moveml	%sp@+,#0x7FFF		| no, restore most user regs
835	addql	#8,%sp			| toss %SP and stack adjust
836	rte				| and do real RTE
837.Laststkadj:
838	lea	%sp@(FR_HW),%a1		| pointer to HW frame
839	addql	#8,%a1			| source pointer
840	movl	%a1,%a0			| source
841	addw	%d0,%a0			|  + hole size = dest pointer
842	movl	%a1@-,%a0@-		| copy
843	movl	%a1@-,%a0@-		|  8 bytes
844	movl	%a0,%sp@(FR_SP)		| new SSP
845	moveml	%sp@+,#0x7FFF		| restore user registers
846	movl	%sp@,%sp		| and our %SP
847	rte				| and do real RTE
848.Lchksir:
849	tstb	_C_LABEL(ssir)		| SIR pending?
850	jeq	.Ldorte			| no, all done
851	movl	%d0,%sp@-		| need a scratch register
852	movw	%sp@(4),%d0		| get SR
853	andw	#PSL_IPL7,%d0		| mask all but IPL
854	jne	.Lnosir			| came from interrupt, no can do
855	movl	%sp@+,%d0		| restore scratch register
856.Lgotsir:
857	movw	#SPL1,%sr		| prevent others from servicing int
858	tstb	_C_LABEL(ssir)		| too late?
859	jeq	.Ldorte			| yes, oh well...
860	clrl	%sp@-			| stack adjust
861	moveml	#0xFFFF,%sp@-		| save all registers
862	movl	%usp,%a1		| including
863	movl	%a1,%sp@(FR_SP)		|    %USP
864.Lsir1:
865	clrl	%sp@-			| VA == none
866	clrl	%sp@-			| code == none
867	movl	#T_SSIR,%sp@-		| type == software interrupt
868	pea	%sp@(12)		| fp == address of trap frame
869	jbsr	_C_LABEL(trap)		| go handle it
870	lea	%sp@(16),%sp		| pop value args
871	movl	%sp@(FR_SP),%a0		| restore
872	movl	%a0,%usp		|   %USP
873	moveml	%sp@+,#0x7FFF		| and all remaining registers
874	addql	#8,%sp			| pop %SP and stack adjust
875	rte
876.Lnosir:
877	movl	%sp@+,%d0		| restore scratch register
878.Ldorte:
879	rte				| real return
880
881/*
882 * Primitives
883 */
884
885/*
886 * Use common m68k process/lwp switch and context save subroutines.
887 */
888#define FPCOPROC	/* XXX: Temp. Reqd. */
889#include <m68k/m68k/switch_subr.s>
890
891#if defined(M68040)
892ENTRY(suline)
893	movl	%sp@(4),%a0		| address to write
894	movl	_C_LABEL(curpcb),%a1	| current pcb
895	movl	#Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault
896	movl	%sp@(8),%a1		| address of line
897	movl	%a1@+,%d0		| get lword
898	movsl	%d0,%a0@+		| put lword
899	nop				| sync
900	movl	%a1@+,%d0		| get lword
901	movsl	%d0,%a0@+		| put lword
902	nop				| sync
903	movl	%a1@+,%d0		| get lword
904	movsl	%d0,%a0@+		| put lword
905	nop				| sync
906	movl	%a1@+,%d0		| get lword
907	movsl	%d0,%a0@+		| put lword
908	nop				| sync
909	moveq	#0,%d0			| indicate no fault
910	jra	Lsldone
911Lslerr:
912	moveq	#-1,%d0
913Lsldone:
914	movl	_C_LABEL(curpcb),%a1	| current pcb
915	clrl	%a1@(PCB_ONFAULT) 	| clear fault address
916	rts
917#endif
918
919ENTRY(ecacheon)
920	rts
921
922ENTRY(ecacheoff)
923	rts
924
925/*
926 * Set processor priority level calls.  Most are implemented with
927 * inline asm expansions.  However, spl0 requires special handling
928 * as we need to check for our emulated software interrupts.
929 */
930
931ALTENTRY(splnone, _spl0)
932ENTRY(spl0)
933	moveq	#0,%d0
934	movw	%sr,%d0			| get old SR for return
935	movw	#PSL_LOWIPL,%sr		| restore new SR
936	tstb	_C_LABEL(ssir)		| software interrupt pending?
937	jeq	.Lspldone		| no, all done
938	subql	#4,%sp			| make room for RTE frame
939	movl	%sp@(4),%sp@(2)		| position return address
940	clrw	%sp@(6)			| set frame type 0
941	movw	#PSL_LOWIPL,%sp@	| and new SR
942	jra	.Lgotsir		| go handle it
943.Lspldone:
944	rts
945
946/*
947 * delay() - delay for a specified number of microseconds
948 * _delay() - calibrator helper for delay()
949 *
950 * Notice that delay_factor is scaled up by a factor of 128 to avoid loss
951 * of precision for small delays.  As a result of this we need to avoid
952 * overflow.
953 *
954 * The branch target for the loops must be aligned on a half-line (8-byte)
955 * boundary to minimize cache effects.  This guarantees both that there
956 * will be no prefetch stalls due to cache line burst operations and that
957 * the loops will run from a single cache half-line.
958 */
959	.align	8			| align to half-line boundary
960					| (use nop instructions if necessary!)
961ALTENTRY(_delay, _delay)
962ENTRY(delay)
963	movl	%sp@(4),%d0		| get microseconds to delay
964	cmpl	#0x40000,%d0		| is it a "large" delay?
965	bls	.Ldelayshort		| no, normal calculation
966	movql	#0x7f,%d1		| adjust for scaled multiplier (to
967	addl	%d1,%d0			|   avoid overflow)
968	lsrl	#7,%d0
969	mulul	_C_LABEL(delay_factor),%d0 | calculate number of loop iterations
970	bra	.Ldelaysetup		| go do it!
971.Ldelayshort:
972	mulul	_C_LABEL(delay_factor),%d0 | calculate number of loop iterations
973	lsrl	#7,%d0			| adjust for scaled multiplier
974.Ldelaysetup:
975	jeq	.Ldelayexit		| bail out if nothing to do
976	movql	#0,%d1			| put bits 15-0 in %d1 for the
977	movw	%d0,%d1			|   inner loop, and move bits
978	movw	#0,%d0			|   31-16 to the low-order word
979	subql	#1,%d1			|   of %d0 for the outer loop
980	swap	%d0
981.Ldelay:
982	tstl	_C_LABEL(delay_flag)	| this never changes for delay()!
983	dbeq	%d1,.Ldelay		|   (used only for timing purposes)
984	dbeq	%d0,.Ldelay
985	addqw	#1,%d1			| adjust end count and
986	swap	%d0			|    return the longword result
987	orl	%d1,%d0
988.Ldelayexit:
989	rts
990
991/*
992 * Handle the nitty-gritty of rebooting the machine.
993 * Basically we just turn off the MMU and jump to the appropriate ROM routine.
994 * Note that we must be running in an address range that is mapped one-to-one
995 * logical to physical so that the PC is still valid immediately after the MMU
996 * is turned off.  We have conveniently mapped the last page of physical
997 * memory this way.
998 */
999ENTRY_NOPROFILE(doboot)
1000#if defined(M68040)
1001	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
1002	jeq	Lnocache5		| yes, skip
1003#endif
1004	movl	#CACHE_OFF,%d0
1005	movc	%d0,%cacr		| disable on-chip cache(s)
1006Lnocache5:
1007	movl	_C_LABEL(maxaddr),%a0	| last page of physical memory
1008	lea	Lbootcode,%a1		| start of boot code
1009	lea	Lebootcode,%a3		| end of boot code
1010Lbootcopy:
1011	movw	%a1@+,%a0@+		| copy a word
1012	cmpl	%a3,%a1			| done yet?
1013	jcs	Lbootcopy		| no, keep going
1014#if defined(M68040)
1015	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
1016	jne	LmotommuE		| no, skip
1017	.word	0xf4f8			| cpusha bc
1018LmotommuE:
1019#endif
1020	movl	_C_LABEL(maxaddr),%a0
1021	jmp	%a0@			| jump to last page
1022
1023Lbootcode:
1024	lea	%a0@(0x800),%sp		| physical %SP in case of NMI
1025	movl	_C_LABEL(MacOSROMBase),%a1 | Load MacOS ROMBase
1026
1027#if defined(M68040)
1028	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
1029	jne	LmotommuF		| no, skip
1030	movl	#0,%d0
1031	movc	%d0,%cacr		| caches off
1032	.long	0x4e7b0003		| movc %d0,%tc (disable MMU)
1033	jra	Ldoboot1
1034LmotommuF:
1035#endif
1036	lea	_ASM_LABEL(longscratch),%a3
1037	movl	#0,%a3@			| value for pmove to %TC (turn off MMU)
1038	pmove	%a3@,%tc		| disable MMU
1039
1040Ldoboot1:
1041	lea	%a1@(0x90),%a1		| offset of ROM reset routine
1042	jmp	%a1@			| and jump to ROM to reset machine
1043Lebootcode:
1044
1045/*
1046 * u_long ptest040(void *addr, u_int fc);
1047 *
1048 * ptest040() does an 040 PTESTR (addr) and returns the 040 MMUSR iff
1049 * translation is enabled.  This allows us to find the physical address
1050 * corresponding to a MacOS logical address for get_physical().
1051 * sar  01-oct-1996
1052 */
1053ENTRY_NOPROFILE(ptest040)
1054#if defined(M68040)
1055	.long	0x4e7a0003		| movc %tc,%d0
1056	andw	#0x8000,%d0
1057	jeq	Lget_phys1		| MMU is disabled
1058	movc	%dfc,%d1		| Save %DFC
1059	movl	%sp@(8),%d0		| Set FC for ptestr
1060	movc	%d0,%dfc
1061	movl	%sp@(4),%a0		| logical address to look up
1062	.word	0xf568			| ptestr (%a0)
1063	.long	0x4e7a0805		| movc %mmusr,%d0
1064	movc	%d1,%dfc		| Restore %DFC
1065	rts
1066Lget_phys1:
1067#endif
1068	movql	#0,%d0			| return failure
1069	rts
1070
1071/*
1072 * LAK: (7/24/94) This routine was added so that the
1073 *  C routine that runs at startup can figure out how MacOS
1074 *  had mapped memory.  We want to keep the same mapping so
1075 *  that when we set our MMU pointer, the PC doesn't point
1076 *  in the middle of nowhere.
1077 *
1078 * long get_pte(void *addr, unsigned long pte[2], unsigned short *psr)
1079 *
1080 *  Takes "addr" and looks it up in the current MMU pages.  Puts
1081 *  the PTE of that address in "pte" and the result of the
1082 *  search in "psr".  "pte" should be 2 longs in case it is
1083 *  a long-format entry.
1084 *
1085 *  One possible problem here is that setting the TT register
1086 *  may screw something up if we access user data space in a
1087 *  called function or in an interrupt service routine.
1088 *
1089 *  Returns -1 on error, 0 if pte is a short-format pte, or
1090 *  1 if pte is a long-format pte.
1091 *
1092 *  Be sure to only call this routine if the MMU is enabled.  This
1093 *  routine is probably more general than it needs to be -- it
1094 *  could simply return the physical address (replacing
1095 *  get_physical() in machdep).
1096 *
1097 *  "gas" does not understand the %tt0 register, so we must hand-
1098 *  assemble the instructions.
1099 */
1100ENTRY_NOPROFILE(get_pte)
1101	subql	#4,%sp		| make temporary space
1102
1103	lea	_ASM_LABEL(longscratch),%a0
1104	movl	#MAC68K_TT_GET_PTE,%a0@ | See pmap.h
1105	.long	0xf0100800	| pmove %a0@,%tt0
1106
1107	movl	%sp@(8),%a0	| logical address to look up
1108	movl	#0,%a1		| clear in case of failure
1109	ptestr	#FC_USERD,%a0@,#7,%a1 | search for logical address
1110	pmove	%psr,%sp@	| store processor status register
1111	movw	%sp@,%d1
1112	movl	%sp@(16),%a0	| where to store the %psr
1113	movw	%d1,%a0@	| send back to caller
1114	andw	#0xc400,%d1	| if bus error, exceeded limit, or invalid
1115	jne	get_pte_fail1	| leave now
1116	tstl	%a1		| check address we got back
1117	jeq	get_pte_fail2	| if 0, then was not set -- fail
1118
1119	movl	%a1,%d0
1120	movl	%d0,_ASM_LABEL(pte_tmp)	| save for later
1121
1122	| send first long back to user
1123	movl	%sp@(12),%a0	| address of where to put pte
1124	movsl	%a1@,%d0	|
1125	movl	%d0,%a0@	| first long
1126
1127	andl	#3,%d0		| dt bits of pte
1128	cmpl	#1,%d0		| should be 1 if page descriptor
1129	jne	get_pte_fail3	| if not, get out now
1130
1131	movl	%sp@(16),%a0	| addr of stored %psr
1132	movw	%a0@,%d0	| get %psr again
1133	andw	#7,%d0		| number of levels it found
1134	addw	#-1,%d0		| find previous level
1135	movl	%sp@(8),%a0	| logical address to look up
1136	movl	#0,%a1		| clear in case of failure
1137
1138	cmpl	#0,%d0
1139	jeq	pte_level_zero
1140	cmpl	#1,%d0
1141	jeq	pte_level_one
1142	cmpl	#2,%d0
1143	jeq	pte_level_two
1144	cmpl	#3,%d0
1145	jeq	pte_level_three
1146	cmpl	#4,%d0
1147	jeq	pte_level_four
1148	cmpl	#5,%d0
1149	jeq	pte_level_five
1150	cmpl	#6,%d0
1151	jeq	pte_level_six
1152	jra	get_pte_fail4	| really should have been one of these...
1153
1154pte_level_zero:
1155	| must get CRP to get length of entries at first level
1156	lea	_ASM_LABEL(longscratch),%a0 | space for two longs
1157	pmove	%crp,%a0@	| save root pointer
1158	movl	%a0@,%d0	| load high long
1159	jra	pte_got_parent
1160pte_level_one:
1161	ptestr	#FC_USERD,%a0@,#1,%a1 | search for logical address
1162	pmove	%psr,%sp@	| store processor status register
1163	movw	%sp@,%d1
1164	jra	pte_got_it
1165pte_level_two:
1166	ptestr	#FC_USERD,%a0@,#2,%a1 | search for logical address
1167	pmove	%psr,%sp@	| store processor status register
1168	movw	%sp@,%d1
1169	jra	pte_got_it
1170pte_level_three:
1171	ptestr	#FC_USERD,%a0@,#3,%a1 | search for logical address
1172	pmove	%psr,%sp@	| store processor status register
1173	movw	%sp@,%d1
1174	jra	pte_got_it
1175pte_level_four:
1176	ptestr	#FC_USERD,%a0@,#4,%a1 | search for logical address
1177	pmove	%psr,%sp@	| store processor status register
1178	movw	%sp@,%d1
1179	jra	pte_got_it
1180pte_level_five:
1181	ptestr	#FC_USERD,%a0@,#5,%a1 | search for logical address
1182	pmove	%psr,%sp@	| store processor status register
1183	movw	%sp@,%d1
1184	jra	pte_got_it
1185pte_level_six:
1186	ptestr	#FC_USERD,%a0@,#6,%a1 | search for logical address
1187	pmove	%psr,%sp@	| store processor status register
1188	movw	%sp@,%d1
1189
1190pte_got_it:
1191	andw	#0xc400,%d1	| if bus error, exceeded limit, or invalid
1192	jne	get_pte_fail5	| leave now
1193	tstl	%a1		| check address we got back
1194	jeq	get_pte_fail6	| if 0, then was not set -- fail
1195
1196	movsl	%a1@,%d0		| get pte of parent
1197	movl	%d0,_C_LABEL(macos_tt0)	| XXX for later analysis (kill me)
1198pte_got_parent:
1199	andl	#3,%d0		| dt bits of pte
1200	cmpl	#2,%d0		| child is short-format descriptor
1201	jeq	short_format
1202	cmpl	#3,%d0		| child is long-format descriptor
1203	jne	get_pte_fail7
1204
1205	| long_format -- we must go back, change the tt, and get the
1206	|  second long.  The reason we didn't do this in the first place
1207	|  is that the first long might have been the last long of RAM.
1208
1209	movl	_ASM_LABEL(pte_tmp),%a1	| get address of our original pte
1210	addql	#4,%a1		| address of ite second long
1211
1212	| send second long back to user
1213	movl	%sp@(12),%a0	| address of where to put pte
1214	movsl	%a1@,%d0	|
1215	movl	%d0,%a0@(4)	| write in second long
1216
1217	movql	#1,%d0		| return long-format
1218	jra	get_pte_success
1219
1220short_format:
1221	movql	#0,%d0		| return short-format
1222	jra	get_pte_success
1223
1224get_pte_fail:
1225	movql	#-1,%d0		| return failure
1226
1227get_pte_success:
1228	lea	_ASM_LABEL(longscratch),%a0 | disable tt
1229	movl	#0,%a0@
1230	.long	0xf0100800	| pmove %a0@,%tt0
1231
1232	addql	#4,%sp		| return temporary space
1233	rts
1234
1235get_pte_fail1:
1236	jbsr	_C_LABEL(printstar)
1237	jra	get_pte_fail
1238get_pte_fail2:
1239	jbsr	_C_LABEL(printstar)
1240	jbsr	_C_LABEL(printstar)
1241	jra	get_pte_fail
1242get_pte_fail3:
1243	jbsr	_C_LABEL(printstar)
1244	jbsr	_C_LABEL(printstar)
1245	jbsr	_C_LABEL(printstar)
1246	jra	get_pte_fail
1247get_pte_fail4:
1248	jbsr	_C_LABEL(printstar)
1249	jbsr	_C_LABEL(printstar)
1250	jbsr	_C_LABEL(printstar)
1251	jbsr	_C_LABEL(printstar)
1252	jra	get_pte_fail
1253get_pte_fail5:
1254	jbsr	_C_LABEL(printstar)
1255	jbsr	_C_LABEL(printstar)
1256	jbsr	_C_LABEL(printstar)
1257	jbsr	_C_LABEL(printstar)
1258	jbsr	_C_LABEL(printstar)
1259	jra	get_pte_fail
1260get_pte_fail6:
1261	jbsr	_C_LABEL(printstar)
1262	jbsr	_C_LABEL(printstar)
1263	jbsr	_C_LABEL(printstar)
1264	jbsr	_C_LABEL(printstar)
1265	jbsr	_C_LABEL(printstar)
1266	jbsr	_C_LABEL(printstar)
1267	jra	get_pte_fail
1268get_pte_fail7:
1269	jbsr	_C_LABEL(printstar)
1270	jbsr	_C_LABEL(printstar)
1271	jbsr	_C_LABEL(printstar)
1272	jbsr	_C_LABEL(printstar)
1273	jbsr	_C_LABEL(printstar)
1274	jbsr	_C_LABEL(printstar)
1275	jbsr	_C_LABEL(printstar)
1276	jra	get_pte_fail
1277get_pte_fail8:
1278	jbsr	_C_LABEL(printstar)
1279	jbsr	_C_LABEL(printstar)
1280	jbsr	_C_LABEL(printstar)
1281	jbsr	_C_LABEL(printstar)
1282	jbsr	_C_LABEL(printstar)
1283	jbsr	_C_LABEL(printstar)
1284	jbsr	_C_LABEL(printstar)
1285	jbsr	_C_LABEL(printstar)
1286	jra	get_pte_fail
1287get_pte_fail9:
1288	jbsr	_C_LABEL(printstar)
1289	jbsr	_C_LABEL(printstar)
1290	jbsr	_C_LABEL(printstar)
1291	jbsr	_C_LABEL(printstar)
1292	jbsr	_C_LABEL(printstar)
1293	jbsr	_C_LABEL(printstar)
1294	jbsr	_C_LABEL(printstar)
1295	jbsr	_C_LABEL(printstar)
1296	jbsr	_C_LABEL(printstar)
1297	jra	get_pte_fail
1298get_pte_fail10:
1299	jbsr	_C_LABEL(printstar)
1300	jbsr	_C_LABEL(printstar)
1301	jbsr	_C_LABEL(printstar)
1302	jbsr	_C_LABEL(printstar)
1303	jbsr	_C_LABEL(printstar)
1304	jbsr	_C_LABEL(printstar)
1305	jbsr	_C_LABEL(printstar)
1306	jbsr	_C_LABEL(printstar)
1307	jbsr	_C_LABEL(printstar)
1308	jbsr	_C_LABEL(printstar)
1309	jra	get_pte_fail
1310
1311/*
1312 * Misc. global variables.
1313 */
1314	.data
1315GLOBAL(sanity_check)
1316	.long	0x18621862	| this is our stack overflow checker.
1317
1318	.space	4 * PAGE_SIZE
1319	.align	4
1320ASLOCAL(tmpstk)
1321
1322GLOBAL(machineid)
1323	.long	0		| default to 320
1324
1325GLOBAL(mmutype)
1326	.long	MMU_68851	| default to 68851 PMMU
1327
1328GLOBAL(cputype)
1329	.long	CPU_68020	| default to 68020 CPU
1330
1331#ifdef __notyet__
1332GLOBAL(ectype)
1333	.long	EC_NONE		| external cache type, default to none
1334#endif
1335
1336GLOBAL(fputype)
1337	.long	FPU_68882	| default to 68882 FPU
1338
1339GLOBAL(intiolimit)
1340	.long	0		| KVA of end of internal IO space
1341
1342GLOBAL(load_addr)
1343	.long	0		| Physical address of kernel
1344
1345ASLOCAL(lastpage)
1346	.long	0		| LAK: to store the addr of last page in mem
1347
1348GLOBAL(MacOSROMBase)
1349	.long	0x40800000
1350GLOBAL(mac68k_vrsrc_cnt)
1351	.long	0
1352GLOBAL(mac68k_vrsrc_vec)
1353	.word	0, 0, 0, 0, 0, 0
1354
1355#ifdef DEBUG
1356ASGLOBAL(fulltflush)
1357	.long	0
1358
1359ASGLOBAL(fullcflush)
1360	.long	0
1361#endif
1362
1363/* interrupt counters -- leave some space for overriding the names */
1364
1365GLOBAL(intrnames)
1366	.asciz	"spur    "
1367	.asciz	"via1    "
1368	.asciz	"via2    "
1369	.asciz	"unused1 "
1370	.asciz	"scc     "
1371	.asciz	"unused2 "
1372	.asciz	"unused3 "
1373	.asciz	"nmi     "
1374	.asciz	"clock   "
1375GLOBAL(eintrnames)
1376	.even
1377
1378GLOBAL(intrcnt)
1379	.long	0,0,0,0,0,0,0,0,0
1380GLOBAL(eintrcnt)
1381