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