Home | History | Annotate | Line # | Download | only in mac68k
      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
     96 GLOBAL(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...
    107 ASLOCAL(longscratch)
    108 	.long	0
    109 ASLOCAL(longscratch2)
    110 	.long	0
    111 ASLOCAL(pte_tmp)			| for get_pte()
    112 	.long	0
    113 GLOBAL(macos_crp1)
    114 	.long	0
    115 GLOBAL(macos_crp2)
    116 	.long	0
    117 GLOBAL(macos_tc)
    118 	.long	0
    119 GLOBAL(macos_tt0)
    120 	.long	0
    121 GLOBAL(macos_tt1)
    122 	.long	0
    123 GLOBAL(bletch)
    124 	.long	0
    125 
    126 BSS(esym,4)
    127 
    128 ASENTRY_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 
    167 Lnot68030:
    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 
    183 Lis68020:
    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 
    191 Lstart1:
    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
    207 1:
    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
    215 1:
    216 #endif
    217 	/* Config botch; no hope. */
    218 	movl	_C_LABEL(MacOSROMBase),%a1 | Load MacOS ROMBase
    219 	jra	Ldoboot1
    220 
    221 Lstart2:
    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 
    235 Lget040TC:
    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
    243 LnotAV:
    244 	movql	#0,%d0			| otherwise,
    245 	.long	0x4e7b0003		| movc %d0,%tc ;Disable MMU
    246 LsaveTC:
    247 	movl	%d0,%a0@
    248 
    249 Lstart3:
    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 
    291 Ldjmemccfg:
    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 
    314 Ldjmemc610:
    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 
    331 Ldjmemctop:
    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
    339 L1stbankcopy1:
    340 	movl	%a0@+,%a2@+
    341 	dbra	%d0,L1stbankcopy1
    342 	movl	#0xFFFF,%d0
    343 L1stbankcopy2:
    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
    350 Ldjcopy:
    351 	movl	%a0@+,%a2@+
    352 	dbra	%d0,Ldjcopy
    353 
    354 	movl	#0x8800000,%a0
    355 	lea	_ASM_LABEL(Ldjmemcdone),%a2
    356 	jmp	%a0@
    357 
    358 Lsetup1stbank:
    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 
    370 Ldjmemcdone:
    371 	movl	#0x400000,%a2
    372 	movl	#0x9000000,%a0
    373 	movl	#0xFFFF,%d0
    374 Lcopyback1:
    375 	movl	%a0@+,%a2@+
    376 	dbra	%d0,Lcopyback1
    377 	movl	#0xFFFF,%d0
    378 Lcopyback2:
    379 	movl	%a0@+,%a2@+
    380 	dbra	%d0,Lcopyback2
    381 
    382 Lnodjmemc:
    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 
    392 Lenablepre040MMU:
    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 
    401 LnokillTT:
    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 
    412 Lloaddone:
    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 
    439 Ltbia040:
    440 	.word	0xf518			| pflusha
    441 
    442 Lnocache0:
    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
    472 GLOBAL(mac68k_a2_fromfault)
    473 	.long	0
    474 GLOBAL(m68k_fault_addr)
    475 	.long	0
    476 
    477 #include <m68k/m68k/busaddrerr.s>
    478 
    479 /*
    480  * FP exceptions.
    481  */
    482 ENTRY_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
    488 Ldofp_unimp:
    489 #ifdef FPSP
    490 	jmp	_ASM_LABEL(fpsp_unimp)	| yes, go handle it
    491 #endif
    492 Lfp_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 
    503 ENTRY_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
    510 Lfp_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  */
    527 ENTRY_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
    546 Lfptnull:
    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 
    557 ENTRY_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 
    567 ENTRY_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  */
    594 ENTRY_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  */
    608 ENTRY_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  */
    632 ENTRY_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 
    641 Lkbrkpt: | 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
    657 Lbrkpt1:
    658 	movl	%a0@+,%a1@+
    659 	subql	#4,%d1
    660 	bgt	Lbrkpt1
    661 
    662 Lbrkpt2:
    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. */
    693 Lbrkpt3:
    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 
    745 ENTRY_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 
    752 ENTRY_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 
    758 ENTRY_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  */
    780 ENTRY_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 
    812 ASENTRY_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)
    892 ENTRY(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
    911 Lslerr:
    912 	moveq	#-1,%d0
    913 Lsldone:
    914 	movl	_C_LABEL(curpcb),%a1	| current pcb
    915 	clrl	%a1@(PCB_ONFAULT) 	| clear fault address
    916 	rts
    917 #endif
    918 
    919 ENTRY(ecacheon)
    920 	rts
    921 
    922 ENTRY(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 
    931 ALTENTRY(splnone, _spl0)
    932 ENTRY(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!)
    961 ALTENTRY(_delay, _delay)
    962 ENTRY(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  */
    999 ENTRY_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)
   1006 Lnocache5:
   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
   1010 Lbootcopy:
   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
   1018 LmotommuE:
   1019 #endif
   1020 	movl	_C_LABEL(maxaddr),%a0
   1021 	jmp	%a0@			| jump to last page
   1022 
   1023 Lbootcode:
   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
   1034 LmotommuF:
   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 
   1040 Ldoboot1:
   1041 	lea	%a1@(0x90),%a1		| offset of ROM reset routine
   1042 	jmp	%a1@			| and jump to ROM to reset machine
   1043 Lebootcode:
   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  */
   1053 ENTRY_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
   1066 Lget_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  */
   1100 ENTRY_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 
   1154 pte_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
   1160 pte_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
   1165 pte_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
   1170 pte_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
   1175 pte_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
   1180 pte_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
   1185 pte_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 
   1190 pte_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)
   1198 pte_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 
   1220 short_format:
   1221 	movql	#0,%d0		| return short-format
   1222 	jra	get_pte_success
   1223 
   1224 get_pte_fail:
   1225 	movql	#-1,%d0		| return failure
   1226 
   1227 get_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 
   1235 get_pte_fail1:
   1236 	jbsr	_C_LABEL(printstar)
   1237 	jra	get_pte_fail
   1238 get_pte_fail2:
   1239 	jbsr	_C_LABEL(printstar)
   1240 	jbsr	_C_LABEL(printstar)
   1241 	jra	get_pte_fail
   1242 get_pte_fail3:
   1243 	jbsr	_C_LABEL(printstar)
   1244 	jbsr	_C_LABEL(printstar)
   1245 	jbsr	_C_LABEL(printstar)
   1246 	jra	get_pte_fail
   1247 get_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
   1253 get_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
   1260 get_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
   1268 get_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
   1277 get_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
   1287 get_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
   1298 get_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
   1315 GLOBAL(sanity_check)
   1316 	.long	0x18621862	| this is our stack overflow checker.
   1317 
   1318 	.space	4 * PAGE_SIZE
   1319 	.align	4
   1320 ASLOCAL(tmpstk)
   1321 
   1322 GLOBAL(machineid)
   1323 	.long	0		| default to 320
   1324 
   1325 GLOBAL(mmutype)
   1326 	.long	MMU_68851	| default to 68851 PMMU
   1327 
   1328 GLOBAL(cputype)
   1329 	.long	CPU_68020	| default to 68020 CPU
   1330 
   1331 #ifdef __notyet__
   1332 GLOBAL(ectype)
   1333 	.long	EC_NONE		| external cache type, default to none
   1334 #endif
   1335 
   1336 GLOBAL(fputype)
   1337 	.long	FPU_68882	| default to 68882 FPU
   1338 
   1339 GLOBAL(intiolimit)
   1340 	.long	0		| KVA of end of internal IO space
   1341 
   1342 GLOBAL(load_addr)
   1343 	.long	0		| Physical address of kernel
   1344 
   1345 ASLOCAL(lastpage)
   1346 	.long	0		| LAK: to store the addr of last page in mem
   1347 
   1348 GLOBAL(MacOSROMBase)
   1349 	.long	0x40800000
   1350 GLOBAL(mac68k_vrsrc_cnt)
   1351 	.long	0
   1352 GLOBAL(mac68k_vrsrc_vec)
   1353 	.word	0, 0, 0, 0, 0, 0
   1354 
   1355 #ifdef DEBUG
   1356 ASGLOBAL(fulltflush)
   1357 	.long	0
   1358 
   1359 ASGLOBAL(fullcflush)
   1360 	.long	0
   1361 #endif
   1362 
   1363 /* interrupt counters -- leave some space for overriding the names */
   1364 
   1365 GLOBAL(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   "
   1375 GLOBAL(eintrnames)
   1376 	.even
   1377 
   1378 GLOBAL(intrcnt)
   1379 	.long	0,0,0,0,0,0,0,0,0
   1380 GLOBAL(eintrcnt)
   1381