Home | History | Annotate | Line # | Download | only in mac68k
      1 /*	$NetBSD: locore.s,v 1.186 2025/11/04 22:33: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 	/* 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 /* phase 2 of pmap setup, returns pointer to lwp0 uarea in %a0 */
    419 	jbsr	_C_LABEL(pmap_bootstrap2)
    420 /* set kernel stack, user SP, lwp0, and initial pcb */
    421 	lea	%a0@(USPACE-4),%sp	| set kernel stack to end of area
    422 	movl	#USRSTACK-4,%a2
    423 	movl	%a2,%usp		| init %USP
    424 
    425 /* flush TLB and turn on caches */
    426 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
    427 	jeq	Ltbia040		| yes, cache already on
    428 	pflusha
    429 	movl	#CACHE_ON,%d0
    430 	movc	%d0,%cacr		| clear cache(s)
    431 #ifdef __notyet__
    432 	tstl	_C_LABEL(ectype)
    433 	jeq	Lnocache0
    434 					| Enable external cache here
    435 #endif
    436 	jra	Lnocache0
    437 
    438 Ltbia040:
    439 	.word	0xf518			| pflusha
    440 
    441 Lnocache0:
    442 /* Final setup for call to main(). */
    443 	jbsr	_C_LABEL(mac68k_init)
    444 
    445 /*
    446  * Create a fake exception frame so that cpu_lwp_fork() can copy it.
    447  * main() nevers returns; we exit to user mode from a forked process
    448  * later on.
    449  */
    450 	clrw	%sp@-			| vector offset/frame type
    451 	clrl	%sp@-			| PC - filled in by "execve"
    452 	movw	#PSL_USER,%sp@-		| in user mode
    453 	clrl	%sp@-			| stack adjust count and padding
    454 	lea	%sp@(-64),%sp		| construct space for D0-D7/A0-A7
    455 	lea	_C_LABEL(lwp0),%a0	| save pointer to frame
    456 	movl	%sp,%a0@(L_MD_REGS)	|   in lwp0.l_md.md_regs
    457 
    458 	jra	_C_LABEL(main)		| main()
    459 	PANIC("main() returned")
    460 	/* NOTREACHED */
    461 
    462 /*
    463  * Trap/interrupt vector routines
    464  */
    465 #include <m68k/m68k/trap_subr.s>
    466 
    467 /*
    468  * Use common m68k bus error and address error handlers.
    469  */
    470 	.data
    471 GLOBAL(mac68k_a2_fromfault)
    472 	.long	0
    473 GLOBAL(m68k_fault_addr)
    474 	.long	0
    475 
    476 #include <m68k/m68k/busaddrerr.s>
    477 
    478 /*
    479  * FP exceptions.
    480  */
    481 ENTRY_NOPROFILE(fpfline)
    482 #if defined(M68040)
    483 	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
    484 	jne	Lfp_unimp		| no, skip FPSP
    485 	cmpw	#0x202c,%sp@(6)		| format type 2?
    486 	jne	_C_LABEL(illinst)	| no, not an FP emulation
    487 Ldofp_unimp:
    488 #ifdef FPSP
    489 	jmp	_ASM_LABEL(fpsp_unimp)	| yes, go handle it
    490 #endif
    491 Lfp_unimp:
    492 #endif /* M68040 */
    493 #ifdef FPU_EMULATE
    494 	clrl	%sp@-			| stack adjust count
    495 	moveml	#0xFFFF,%sp@-		| save registers
    496 	moveq	#T_FPEMULI,%d0		| denote as FP emulation trap
    497 	jra	_ASM_LABEL(fault)	| do it
    498 #else
    499 	jra	_C_LABEL(illinst)
    500 #endif
    501 
    502 ENTRY_NOPROFILE(fpunsupp)
    503 #if defined(M68040)
    504 	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
    505 	jne	_C_LABEL(illinst)	| no, treat as illinst
    506 #ifdef FPSP
    507 	jmp	_ASM_LABEL(fpsp_unsupp)	| yes, go handle it
    508 #endif
    509 Lfp_unsupp:
    510 #endif /* M68040 */
    511 #ifdef FPU_EMULATE
    512 	clrl	%sp@-			| stack adjust count
    513 	moveml	#0xFFFF,%sp@-		| save registers
    514 	moveq	#T_FPEMULD,%d0		| denote as FP emulation trap
    515 	jra	_ASM_LABEL(fault)	| do it
    516 #else
    517 	jra	_C_LABEL(illinst)
    518 #endif
    519 
    520 /*
    521  * Handles all other FP coprocessor exceptions.
    522  * Note that since some FP exceptions generate mid-instruction frames
    523  * and may cause signal delivery, we need to test for stack adjustment
    524  * after the trap call.
    525  */
    526 ENTRY_NOPROFILE(fpfault)
    527 	clrl	%sp@-		| stack adjust count
    528 	moveml	#0xFFFF,%sp@-	| save user registers
    529 	movl	%usp,%a0	| and save
    530 	movl	%a0,%sp@(FR_SP)	|   the user stack pointer
    531 	clrl	%sp@-		| no VA arg
    532 	movl	_C_LABEL(curpcb),%a0 | current pcb
    533 	lea	%a0@(PCB_FPCTX),%a0 | address of FP savearea
    534 	fsave	%a0@		| save state
    535 #if defined(M68040) || defined(M68060)
    536 	/* always null state frame on 68040, 68060 */
    537 	cmpl	#FPU_68040,_C_LABEL(fputype)
    538 	jge	Lfptnull
    539 #endif
    540 	tstb	%a0@		| null state frame?
    541 	jeq	Lfptnull	| yes, safe
    542 	clrw	%d0		| no, need to tweak BIU
    543 	movb	%a0@(1),%d0	| get frame size
    544 	bset	#3,%a0@(0,%d0:w) | set exc_pend bit of BIU
    545 Lfptnull:
    546 	fmovem	%fpsr,%sp@-	| push %fpsr as code argument
    547 	frestore %a0@		| restore state
    548 	movl	#T_FPERR,%sp@-	| push type arg
    549 	jra	_ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup
    550 
    551 /*
    552  * Other exceptions only cause four and six word stack frame and require
    553  * no post-trap stack adjustment.
    554  */
    555 
    556 ENTRY_NOPROFILE(badtrap)
    557 	moveml	#0xC0C0,%sp@-		| save scratch regs
    558 	movw	%sp@(22),%sp@-		| push exception vector info
    559 	clrw	%sp@-
    560 	movl	%sp@(22),%sp@-		| and PC
    561 	jbsr	_C_LABEL(straytrap)	| report
    562 	addql	#8,%sp			| pop args
    563 	moveml	%sp@+,#0x0303		| restore regs
    564 	jra	_ASM_LABEL(rei)		| all done
    565 
    566 ENTRY_NOPROFILE(trap0)
    567 	clrl	%sp@-			| pad SR to longword
    568 	moveml	#0xFFFF,%sp@-		| save user registers
    569 	movl	%usp,%a0		| save %USP
    570 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    571 	movl	%d0,%sp@-		| push syscall number
    572 	jbsr	_C_LABEL(syscall)	| handle it
    573 	addql	#4,%sp			| pop syscall arg
    574 	tstl	_C_LABEL(astpending)
    575 	jne	.Lrei2
    576 	tstb	_C_LABEL(ssir)
    577 	jeq	.Ltrap1
    578 	movw	#SPL1,%sr
    579 	tstb	_C_LABEL(ssir)
    580 	jne	.Lsir1
    581 .Ltrap1:
    582 	movl	%sp@(FR_SP),%a0		| grab and restore
    583 	movl	%a0,%usp		|   %USP
    584 	moveml	%sp@+,#0x7FFF		| restore most registers
    585 	addql	#8,%sp			| pop SSP and align word
    586 	rte
    587 
    588 /*
    589  * Trap 12 is the entry point for the cachectl "syscall" (both HP-UX & BSD)
    590  *	cachectl(command, addr, length)
    591  * command in %d0, addr in %a1, length in %d1
    592  */
    593 ENTRY_NOPROFILE(trap12)
    594 	movl	_C_LABEL(curlwp),%a0
    595 	movl	%a0@(L_PROC),%sp@-	| push proc pointer
    596 	movl	%d1,%sp@-		| push length
    597 	movl	%a1,%sp@-		| push addr
    598 	movl	%d0,%sp@-		| push command
    599 	jbsr	_C_LABEL(cachectl1)	| do it
    600 	lea	%sp@(16),%sp		| pop args
    601 	jra	_ASM_LABEL(rei)		| all done
    602 
    603 /*
    604  * Trace (single-step) trap.  Kernel-mode is special.
    605  * User mode traps are simply passed on to trap().
    606  */
    607 ENTRY_NOPROFILE(trace)
    608 	clrl	%sp@-			| stack adjust count
    609 	moveml	#0xFFFF,%sp@-
    610 	moveq	#T_TRACE,%d0
    611 
    612 	| Check PSW and see what happen.
    613 	|   T=0 S=0	(should not happen)
    614 	|   T=1 S=0	trace trap from user mode
    615 	|   T=0 S=1	trace trap on a trap instruction
    616 	|   T=1 S=1	trace trap from system mode (kernel breakpoint)
    617 
    618 	movw	%sp@(FR_HW),%d1		| get PSW
    619 	notw	%d1			| XXX no support for T0 on 680[234]0
    620 	andw	#PSL_TS,%d1		| from system mode (T=1, S=1)?
    621 	jeq	Lkbrkpt			| yes, kernel breakpoint
    622 	jra	_ASM_LABEL(fault)	| no, user-mode fault
    623 
    624 /*
    625  * Trap 15 is used for:
    626  *	- GDB breakpoints (in user programs)
    627  *	- KGDB breakpoints (in the kernel)
    628  *	- trace traps for SUN binaries (not fully supported yet)
    629  * User mode traps are simply passed to trap().
    630  */
    631 ENTRY_NOPROFILE(trap15)
    632 	clrl	%sp@-			| stack adjust count
    633 	moveml	#0xFFFF,%sp@-
    634 	moveq	#T_TRAP15,%d0
    635 	movw	%sp@(FR_HW),%d1		| get PSW
    636 	andw	#PSL_S,%d1		| from system mode?
    637 	jne	Lkbrkpt			| yes, kernel breakpoint
    638 	jra	_ASM_LABEL(fault)	| no, user-mode fault
    639 
    640 Lkbrkpt: | Kernel-mode breakpoint or trace trap. (%d0=trap_type)
    641 	| Save the system %sp rather than the user %usp.
    642 	movw	#PSL_HIGHIPL,%sr	| lock out interrupts
    643 	lea	%sp@(FR_SIZE),%a6	| Save stack pointer
    644 	movl	%a6,%sp@(FR_SP)		|  from before trap
    645 
    646 	| If were are not on tmpstk switch to it.
    647 	| (so debugger can change the stack pointer)
    648 	movl	%a6,%d1
    649 	cmpl	#_ASM_LABEL(tmpstk),%d1
    650 	jls	Lbrkpt2			| already on tmpstk
    651 	| Copy frame to the temporary stack
    652 	movl	%sp,%a0			| %a0=src
    653 	lea	_ASM_LABEL(tmpstk)-96,%a1 | %a1=dst
    654 	movl	%a1,%sp			| %sp=new frame
    655 	moveq	#FR_SIZE,%d1
    656 Lbrkpt1:
    657 	movl	%a0@+,%a1@+
    658 	subql	#4,%d1
    659 	bgt	Lbrkpt1
    660 
    661 Lbrkpt2:
    662 	| Call the trap handler for the kernel debugger.
    663 	| Do not call trap() to do it, so that we can
    664 	| set breakpoints in trap() if we want.  We know
    665 	| the trap type is either T_TRACE or T_BREAKPOINT.
    666 	| If we have both DDB and KGDB, let KGDB see it first,
    667 	| because KGDB will just return 0 if not connected.
    668 	| Save args in %d2, %a2
    669 	movl	%d0,%d2			| trap type
    670 	movl	%sp,%a2			| frame ptr
    671 #ifdef KGDB
    672 	| Let KGDB handle it (if connected)
    673 	movl	%a2,%sp@-		| push frame ptr
    674 	movl	%d2,%sp@-		| push trap type
    675 	jbsr	_C_LABEL(kgdb_trap)	| handle the trap
    676 	addql	#8,%sp			| pop args
    677 	cmpl	#0,%d0			| did kgdb handle it?
    678 	jne	Lbrkpt3			| yes, done
    679 #endif
    680 #ifdef DDB
    681 	| Let DDB handle it
    682 	movl	%a2,%sp@-		| push frame ptr
    683 	movl	%d2,%sp@-		| push trap type
    684 	jbsr	_C_LABEL(kdb_trap)	| handle the trap
    685 	addql	#8,%sp			| pop args
    686 #if 0	/* not needed on hp300 */
    687 	cmpl	#0,%d0			| did ddb handle it?
    688 	jne	Lbrkpt3			| yes, done
    689 #endif
    690 #endif
    691 	/* Sun 3 drops into PROM here. */
    692 Lbrkpt3:
    693 	| The stack pointer may have been modified, or
    694 	| data below it modified (by kgdb push call),
    695 	| so push the hardware frame at the current %sp
    696 	| before restoring registers and returning.
    697 
    698 	movl	%sp@(FR_SP),%a0		| modified %sp
    699 	lea	%sp@(FR_SIZE),%a1	| end of our frame
    700 	movl	%a1@-,%a0@-		| copy 2 longs with
    701 	movl	%a1@-,%a0@-		| ... predecrement
    702 	movl	%a0,%sp@(FR_SP)		| %sp = h/w frame
    703 	moveml	%sp@+,#0x7FFF		| restore all but %sp
    704 	movl	%sp@,%sp		| ... and %sp
    705 	rte				| all done
    706 
    707 /*
    708  * Interrupt handlers.
    709  *
    710  * Most 68k-based Macintosh computers
    711  *
    712  *      Level 0:        Spurious: ignored
    713  *      Level 1:        VIA1 (clock, ADB)
    714  *      Level 2:        VIA2 (NuBus, SCSI)
    715  *      Level 3:
    716  *      Level 4:        Serial (SCC)
    717  *      Level 5:
    718  *      Level 6:
    719  *      Level 7:        Non-maskable: parity errors, RESET button
    720  *
    721  * On the Q700, Q900 and Q950 in "A/UX mode": this should become:
    722  *
    723  *	Level 0:        Spurious: ignored
    724  *	Level 1:        Software
    725  *	Level 2:        VIA2 (except ethernet, sound)
    726  *	Level 3:        Ethernet
    727  *	Level 4:        Serial (SCC)
    728  *	Level 5:        Sound
    729  *	Level 6:        VIA1
    730  *	Level 7:        NMIs: parity errors, RESET button, YANCC error
    731  *
    732  * On the 660AV and 840AV:
    733  *
    734  *	Level 0:        Spurious: ignored
    735  *	Level 1:        VIA1 (clock, ADB)
    736  *	Level 2:        VIA2 (NuBus, SCSI)
    737  *	Level 3:        PSC device interrupt
    738  *	Level 4:        PSC DMA and serial
    739  *	Level 5:        ???
    740  *	Level 6:        ???
    741  *	Level 7:        NMIs: parity errors?, RESET button
    742  */
    743 
    744 ENTRY_NOPROFILE(spurintr)
    745 	addql	#1,_C_LABEL(intrcnt)+0
    746 	INTERRUPT_SAVEREG
    747 	CPUINFO_INCREMENT(CI_NINTR)
    748 	INTERRUPT_RESTOREREG
    749 	jra	_ASM_LABEL(rei)
    750 
    751 ENTRY_NOPROFILE(intrhand)
    752 	INTERRUPT_SAVEREG
    753 	jbsr	_C_LABEL(intr_dispatch)	| call dispatch routine
    754 	INTERRUPT_RESTOREREG
    755 	jra	_ASM_LABEL(rei)		| all done
    756 
    757 ENTRY_NOPROFILE(lev7intr)
    758 	addql	#1,_C_LABEL(intrcnt)+16
    759 	clrl	%sp@-			| pad %SR to longword
    760 	moveml	#0xFFFF,%sp@-		| save registers
    761 	movl	%usp,%a0		| and save
    762 	movl	%a0,%sp@(FR_SP)		|   the user stack pointer
    763 	jbsr	_C_LABEL(nmihand)	| call handler
    764 	movl	%sp@(FR_SP),%a0		| restore
    765 	movl	%a0,%usp		|   %USP
    766 	moveml	%sp@+,#0x7FFF		| and remaining registers
    767 	addql	#8,%sp			| pop SSP and align word
    768 	jra	_ASM_LABEL(rei)
    769 
    770 /*
    771  * We could tweak rtclock_intr and gain 12 cycles on the 020 and 030 by
    772  * saving the status register directly to the stack, but this would lose
    773  * badly on the 040.  Aligning the stack takes 10 more cycles than this
    774  * code does, so it's a good compromise.
    775  *
    776  * A pointer to the clockframe is passed as an argument in the usual
    777  * fashion.
    778  */
    779 ENTRY_NOPROFILE(rtclock_intr)
    780 	movl	%sp@(4),%a1		| stash pointer to clockframe
    781 	movl	%d2,%sp@-		| save %d2
    782 	movw	%sr,%d2			| save SPL
    783 					| raise SPL to splclock()
    784 	movw	_C_LABEL(ipl2psl_table)+IPL_CLOCK*2,%sr
    785 	movl	%a1,%sp@-		| push pointer to clockframe
    786 	jbsr	_C_LABEL(hardclock)	| call generic clock int routine
    787 	addql	#4,%sp			| pop param
    788 	jbsr	_C_LABEL(mrg_VBLQueue)	| give programs in the VBLqueue a chance
    789 	addql	#1,_C_LABEL(intrcnt)+32	| record a clock interrupt
    790 	INTERRUPT_SAVEREG
    791 	CPUINFO_INCREMENT(CI_NINTR)
    792 	INTERRUPT_RESTOREREG
    793 	movw	%d2,%sr			| restore SPL
    794 	movl	%sp@+,%d2		| restore %d2
    795 	rts				| go back from whence we came
    796 
    797 /*
    798  * Emulation of VAX REI instruction.
    799  *
    800  * This code deals with checking for and servicing ASTs
    801  * (profiling, scheduling) and software interrupts (network, softclock).
    802  * We check for ASTs first, just like the VAX.  To avoid excess overhead
    803  * the T_ASTFLT handling code will also check for software interrupts so we
    804  * do not have to do it here.  After identifying that we need an AST we
    805  * drop the IPL to allow device interrupts.
    806  *
    807  * This code is complicated by the fact that sendsig may have been called
    808  * necessitating a stack cleanup.
    809  */
    810 
    811 ASENTRY_NOPROFILE(rei)
    812 	tstl	_C_LABEL(astpending)	| AST pending?
    813 	jeq	.Lchksir		| no, go check for SIR
    814 .Lrei1:
    815 	btst	#5,%sp@			| yes, are we returning to user mode?
    816 	jne	.Lchksir		| no, go check for SIR
    817 	movw	#PSL_LOWIPL,%sr		| lower SPL
    818 	clrl	%sp@-			| stack adjust
    819 	moveml	#0xFFFF,%sp@-		| save all registers
    820 	movl	%usp,%a1		| including
    821 	movl	%a1,%sp@(FR_SP)		|    %USP
    822 .Lrei2:
    823 	clrl	%sp@-			| VA == none
    824 	clrl	%sp@-			| code == none
    825 	movl	#T_ASTFLT,%sp@-		| type == async system trap
    826 	pea	%sp@(12)		| fp == address of trap frame
    827 	jbsr	_C_LABEL(trap)		| go handle it
    828 	lea	%sp@(16),%sp		| pop value args
    829 	movl	%sp@(FR_SP),%a0		| restore %USP
    830 	movl	%a0,%usp		|   from save area
    831 	movw	%sp@(FR_ADJ),%d0	| need to adjust stack?
    832 	jne	.Laststkadj		| yes, go to it
    833 	moveml	%sp@+,#0x7FFF		| no, restore most user regs
    834 	addql	#8,%sp			| toss %SP and stack adjust
    835 	rte				| and do real RTE
    836 .Laststkadj:
    837 	lea	%sp@(FR_HW),%a1		| pointer to HW frame
    838 	addql	#8,%a1			| source pointer
    839 	movl	%a1,%a0			| source
    840 	addw	%d0,%a0			|  + hole size = dest pointer
    841 	movl	%a1@-,%a0@-		| copy
    842 	movl	%a1@-,%a0@-		|  8 bytes
    843 	movl	%a0,%sp@(FR_SP)		| new SSP
    844 	moveml	%sp@+,#0x7FFF		| restore user registers
    845 	movl	%sp@,%sp		| and our %SP
    846 	rte				| and do real RTE
    847 .Lchksir:
    848 	tstb	_C_LABEL(ssir)		| SIR pending?
    849 	jeq	.Ldorte			| no, all done
    850 	movl	%d0,%sp@-		| need a scratch register
    851 	movw	%sp@(4),%d0		| get SR
    852 	andw	#PSL_IPL7,%d0		| mask all but IPL
    853 	jne	.Lnosir			| came from interrupt, no can do
    854 	movl	%sp@+,%d0		| restore scratch register
    855 .Lgotsir:
    856 	movw	#SPL1,%sr		| prevent others from servicing int
    857 	tstb	_C_LABEL(ssir)		| too late?
    858 	jeq	.Ldorte			| yes, oh well...
    859 	clrl	%sp@-			| stack adjust
    860 	moveml	#0xFFFF,%sp@-		| save all registers
    861 	movl	%usp,%a1		| including
    862 	movl	%a1,%sp@(FR_SP)		|    %USP
    863 .Lsir1:
    864 	clrl	%sp@-			| VA == none
    865 	clrl	%sp@-			| code == none
    866 	movl	#T_SSIR,%sp@-		| type == software interrupt
    867 	pea	%sp@(12)		| fp == address of trap frame
    868 	jbsr	_C_LABEL(trap)		| go handle it
    869 	lea	%sp@(16),%sp		| pop value args
    870 	movl	%sp@(FR_SP),%a0		| restore
    871 	movl	%a0,%usp		|   %USP
    872 	moveml	%sp@+,#0x7FFF		| and all remaining registers
    873 	addql	#8,%sp			| pop %SP and stack adjust
    874 	rte
    875 .Lnosir:
    876 	movl	%sp@+,%d0		| restore scratch register
    877 .Ldorte:
    878 	rte				| real return
    879 
    880 /*
    881  * Primitives
    882  */
    883 
    884 /*
    885  * Use common m68k process/lwp switch and context save subroutines.
    886  */
    887 #define FPCOPROC	/* XXX: Temp. Reqd. */
    888 #include <m68k/m68k/switch_subr.s>
    889 
    890 #if defined(M68040)
    891 ENTRY(suline)
    892 	movl	%sp@(4),%a0		| address to write
    893 	movl	_C_LABEL(curpcb),%a1	| current pcb
    894 	movl	#Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault
    895 	movl	%sp@(8),%a1		| address of line
    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 	movl	%a1@+,%d0		| get lword
    903 	movsl	%d0,%a0@+		| put lword
    904 	nop				| sync
    905 	movl	%a1@+,%d0		| get lword
    906 	movsl	%d0,%a0@+		| put lword
    907 	nop				| sync
    908 	moveq	#0,%d0			| indicate no fault
    909 	jra	Lsldone
    910 Lslerr:
    911 	moveq	#-1,%d0
    912 Lsldone:
    913 	movl	_C_LABEL(curpcb),%a1	| current pcb
    914 	clrl	%a1@(PCB_ONFAULT) 	| clear fault address
    915 	rts
    916 #endif
    917 
    918 ENTRY(ecacheon)
    919 	rts
    920 
    921 ENTRY(ecacheoff)
    922 	rts
    923 
    924 /*
    925  * Set processor priority level calls.  Most are implemented with
    926  * inline asm expansions.  However, spl0 requires special handling
    927  * as we need to check for our emulated software interrupts.
    928  */
    929 
    930 ALTENTRY(splnone, _spl0)
    931 ENTRY(spl0)
    932 	moveq	#0,%d0
    933 	movw	%sr,%d0			| get old SR for return
    934 	movw	#PSL_LOWIPL,%sr		| restore new SR
    935 	tstb	_C_LABEL(ssir)		| software interrupt pending?
    936 	jeq	.Lspldone		| no, all done
    937 	subql	#4,%sp			| make room for RTE frame
    938 	movl	%sp@(4),%sp@(2)		| position return address
    939 	clrw	%sp@(6)			| set frame type 0
    940 	movw	#PSL_LOWIPL,%sp@	| and new SR
    941 	jra	.Lgotsir		| go handle it
    942 .Lspldone:
    943 	rts
    944 
    945 /*
    946  * delay() - delay for a specified number of microseconds
    947  * _delay() - calibrator helper for delay()
    948  *
    949  * Notice that delay_factor is scaled up by a factor of 128 to avoid loss
    950  * of precision for small delays.  As a result of this we need to avoid
    951  * overflow.
    952  *
    953  * The branch target for the loops must be aligned on a half-line (8-byte)
    954  * boundary to minimize cache effects.  This guarantees both that there
    955  * will be no prefetch stalls due to cache line burst operations and that
    956  * the loops will run from a single cache half-line.
    957  */
    958 	.align	8			| align to half-line boundary
    959 					| (use nop instructions if necessary!)
    960 ALTENTRY(_delay, _delay)
    961 ENTRY(delay)
    962 	movl	%sp@(4),%d0		| get microseconds to delay
    963 	cmpl	#0x40000,%d0		| is it a "large" delay?
    964 	bls	.Ldelayshort		| no, normal calculation
    965 	movql	#0x7f,%d1		| adjust for scaled multiplier (to
    966 	addl	%d1,%d0			|   avoid overflow)
    967 	lsrl	#7,%d0
    968 	mulul	_C_LABEL(delay_factor),%d0 | calculate number of loop iterations
    969 	bra	.Ldelaysetup		| go do it!
    970 .Ldelayshort:
    971 	mulul	_C_LABEL(delay_factor),%d0 | calculate number of loop iterations
    972 	lsrl	#7,%d0			| adjust for scaled multiplier
    973 .Ldelaysetup:
    974 	jeq	.Ldelayexit		| bail out if nothing to do
    975 	movql	#0,%d1			| put bits 15-0 in %d1 for the
    976 	movw	%d0,%d1			|   inner loop, and move bits
    977 	movw	#0,%d0			|   31-16 to the low-order word
    978 	subql	#1,%d1			|   of %d0 for the outer loop
    979 	swap	%d0
    980 .Ldelay:
    981 	tstl	_C_LABEL(delay_flag)	| this never changes for delay()!
    982 	dbeq	%d1,.Ldelay		|   (used only for timing purposes)
    983 	dbeq	%d0,.Ldelay
    984 	addqw	#1,%d1			| adjust end count and
    985 	swap	%d0			|    return the longword result
    986 	orl	%d1,%d0
    987 .Ldelayexit:
    988 	rts
    989 
    990 /*
    991  * Handle the nitty-gritty of rebooting the machine.
    992  * Basically we just turn off the MMU and jump to the appropriate ROM routine.
    993  * Note that we must be running in an address range that is mapped one-to-one
    994  * logical to physical so that the PC is still valid immediately after the MMU
    995  * is turned off.  We have conveniently mapped the last page of physical
    996  * memory this way.
    997  */
    998 ENTRY_NOPROFILE(doboot)
    999 #if defined(M68040)
   1000 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
   1001 	jeq	Lnocache5		| yes, skip
   1002 #endif
   1003 	movl	#CACHE_OFF,%d0
   1004 	movc	%d0,%cacr		| disable on-chip cache(s)
   1005 Lnocache5:
   1006 	movl	_C_LABEL(maxaddr),%a0	| last page of physical memory
   1007 	lea	Lbootcode,%a1		| start of boot code
   1008 	lea	Lebootcode,%a3		| end of boot code
   1009 Lbootcopy:
   1010 	movw	%a1@+,%a0@+		| copy a word
   1011 	cmpl	%a3,%a1			| done yet?
   1012 	jcs	Lbootcopy		| no, keep going
   1013 #if defined(M68040)
   1014 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
   1015 	jne	LmotommuE		| no, skip
   1016 	.word	0xf4f8			| cpusha bc
   1017 LmotommuE:
   1018 #endif
   1019 	movl	_C_LABEL(maxaddr),%a0
   1020 	jmp	%a0@			| jump to last page
   1021 
   1022 Lbootcode:
   1023 	lea	%a0@(0x800),%sp		| physical %SP in case of NMI
   1024 	movl	_C_LABEL(MacOSROMBase),%a1 | Load MacOS ROMBase
   1025 
   1026 #if defined(M68040)
   1027 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
   1028 	jne	LmotommuF		| no, skip
   1029 	movl	#0,%d0
   1030 	movc	%d0,%cacr		| caches off
   1031 	.long	0x4e7b0003		| movc %d0,%tc (disable MMU)
   1032 	jra	Ldoboot1
   1033 LmotommuF:
   1034 #endif
   1035 	lea	_ASM_LABEL(longscratch),%a3
   1036 	movl	#0,%a3@			| value for pmove to %TC (turn off MMU)
   1037 	pmove	%a3@,%tc		| disable MMU
   1038 
   1039 Ldoboot1:
   1040 	lea	%a1@(0x90),%a1		| offset of ROM reset routine
   1041 	jmp	%a1@			| and jump to ROM to reset machine
   1042 Lebootcode:
   1043 
   1044 /*
   1045  * u_long ptest040(void *addr, u_int fc);
   1046  *
   1047  * ptest040() does an 040 PTESTR (addr) and returns the 040 MMUSR iff
   1048  * translation is enabled.  This allows us to find the physical address
   1049  * corresponding to a MacOS logical address for get_physical().
   1050  * sar  01-oct-1996
   1051  */
   1052 ENTRY_NOPROFILE(ptest040)
   1053 #if defined(M68040)
   1054 	.long	0x4e7a0003		| movc %tc,%d0
   1055 	andw	#0x8000,%d0
   1056 	jeq	Lget_phys1		| MMU is disabled
   1057 	movc	%dfc,%d1		| Save %DFC
   1058 	movl	%sp@(8),%d0		| Set FC for ptestr
   1059 	movc	%d0,%dfc
   1060 	movl	%sp@(4),%a0		| logical address to look up
   1061 	.word	0xf568			| ptestr (%a0)
   1062 	.long	0x4e7a0805		| movc %mmusr,%d0
   1063 	movc	%d1,%dfc		| Restore %DFC
   1064 	rts
   1065 Lget_phys1:
   1066 #endif
   1067 	movql	#0,%d0			| return failure
   1068 	rts
   1069 
   1070 /*
   1071  * LAK: (7/24/94) This routine was added so that the
   1072  *  C routine that runs at startup can figure out how MacOS
   1073  *  had mapped memory.  We want to keep the same mapping so
   1074  *  that when we set our MMU pointer, the PC doesn't point
   1075  *  in the middle of nowhere.
   1076  *
   1077  * long get_pte(void *addr, unsigned long pte[2], unsigned short *psr)
   1078  *
   1079  *  Takes "addr" and looks it up in the current MMU pages.  Puts
   1080  *  the PTE of that address in "pte" and the result of the
   1081  *  search in "psr".  "pte" should be 2 longs in case it is
   1082  *  a long-format entry.
   1083  *
   1084  *  One possible problem here is that setting the TT register
   1085  *  may screw something up if we access user data space in a
   1086  *  called function or in an interrupt service routine.
   1087  *
   1088  *  Returns -1 on error, 0 if pte is a short-format pte, or
   1089  *  1 if pte is a long-format pte.
   1090  *
   1091  *  Be sure to only call this routine if the MMU is enabled.  This
   1092  *  routine is probably more general than it needs to be -- it
   1093  *  could simply return the physical address (replacing
   1094  *  get_physical() in machdep).
   1095  *
   1096  *  "gas" does not understand the %tt0 register, so we must hand-
   1097  *  assemble the instructions.
   1098  */
   1099 ENTRY_NOPROFILE(get_pte)
   1100 	subql	#4,%sp		| make temporary space
   1101 
   1102 	lea	_ASM_LABEL(longscratch),%a0
   1103 	movl	#MAC68K_TT_GET_PTE,%a0@ | See pmap.h
   1104 	.long	0xf0100800	| pmove %a0@,%tt0
   1105 
   1106 	movl	%sp@(8),%a0	| logical address to look up
   1107 	movl	#0,%a1		| clear in case of failure
   1108 	ptestr	#FC_USERD,%a0@,#7,%a1 | search for logical address
   1109 	pmove	%psr,%sp@	| store processor status register
   1110 	movw	%sp@,%d1
   1111 	movl	%sp@(16),%a0	| where to store the %psr
   1112 	movw	%d1,%a0@	| send back to caller
   1113 	andw	#0xc400,%d1	| if bus error, exceeded limit, or invalid
   1114 	jne	get_pte_fail1	| leave now
   1115 	tstl	%a1		| check address we got back
   1116 	jeq	get_pte_fail2	| if 0, then was not set -- fail
   1117 
   1118 	movl	%a1,%d0
   1119 	movl	%d0,_ASM_LABEL(pte_tmp)	| save for later
   1120 
   1121 	| send first long back to user
   1122 	movl	%sp@(12),%a0	| address of where to put pte
   1123 	movsl	%a1@,%d0	|
   1124 	movl	%d0,%a0@	| first long
   1125 
   1126 	andl	#3,%d0		| dt bits of pte
   1127 	cmpl	#1,%d0		| should be 1 if page descriptor
   1128 	jne	get_pte_fail3	| if not, get out now
   1129 
   1130 	movl	%sp@(16),%a0	| addr of stored %psr
   1131 	movw	%a0@,%d0	| get %psr again
   1132 	andw	#7,%d0		| number of levels it found
   1133 	addw	#-1,%d0		| find previous level
   1134 	movl	%sp@(8),%a0	| logical address to look up
   1135 	movl	#0,%a1		| clear in case of failure
   1136 
   1137 	cmpl	#0,%d0
   1138 	jeq	pte_level_zero
   1139 	cmpl	#1,%d0
   1140 	jeq	pte_level_one
   1141 	cmpl	#2,%d0
   1142 	jeq	pte_level_two
   1143 	cmpl	#3,%d0
   1144 	jeq	pte_level_three
   1145 	cmpl	#4,%d0
   1146 	jeq	pte_level_four
   1147 	cmpl	#5,%d0
   1148 	jeq	pte_level_five
   1149 	cmpl	#6,%d0
   1150 	jeq	pte_level_six
   1151 	jra	get_pte_fail4	| really should have been one of these...
   1152 
   1153 pte_level_zero:
   1154 	| must get CRP to get length of entries at first level
   1155 	lea	_ASM_LABEL(longscratch),%a0 | space for two longs
   1156 	pmove	%crp,%a0@	| save root pointer
   1157 	movl	%a0@,%d0	| load high long
   1158 	jra	pte_got_parent
   1159 pte_level_one:
   1160 	ptestr	#FC_USERD,%a0@,#1,%a1 | search for logical address
   1161 	pmove	%psr,%sp@	| store processor status register
   1162 	movw	%sp@,%d1
   1163 	jra	pte_got_it
   1164 pte_level_two:
   1165 	ptestr	#FC_USERD,%a0@,#2,%a1 | search for logical address
   1166 	pmove	%psr,%sp@	| store processor status register
   1167 	movw	%sp@,%d1
   1168 	jra	pte_got_it
   1169 pte_level_three:
   1170 	ptestr	#FC_USERD,%a0@,#3,%a1 | search for logical address
   1171 	pmove	%psr,%sp@	| store processor status register
   1172 	movw	%sp@,%d1
   1173 	jra	pte_got_it
   1174 pte_level_four:
   1175 	ptestr	#FC_USERD,%a0@,#4,%a1 | search for logical address
   1176 	pmove	%psr,%sp@	| store processor status register
   1177 	movw	%sp@,%d1
   1178 	jra	pte_got_it
   1179 pte_level_five:
   1180 	ptestr	#FC_USERD,%a0@,#5,%a1 | search for logical address
   1181 	pmove	%psr,%sp@	| store processor status register
   1182 	movw	%sp@,%d1
   1183 	jra	pte_got_it
   1184 pte_level_six:
   1185 	ptestr	#FC_USERD,%a0@,#6,%a1 | search for logical address
   1186 	pmove	%psr,%sp@	| store processor status register
   1187 	movw	%sp@,%d1
   1188 
   1189 pte_got_it:
   1190 	andw	#0xc400,%d1	| if bus error, exceeded limit, or invalid
   1191 	jne	get_pte_fail5	| leave now
   1192 	tstl	%a1		| check address we got back
   1193 	jeq	get_pte_fail6	| if 0, then was not set -- fail
   1194 
   1195 	movsl	%a1@,%d0		| get pte of parent
   1196 	movl	%d0,_C_LABEL(macos_tt0)	| XXX for later analysis (kill me)
   1197 pte_got_parent:
   1198 	andl	#3,%d0		| dt bits of pte
   1199 	cmpl	#2,%d0		| child is short-format descriptor
   1200 	jeq	short_format
   1201 	cmpl	#3,%d0		| child is long-format descriptor
   1202 	jne	get_pte_fail7
   1203 
   1204 	| long_format -- we must go back, change the tt, and get the
   1205 	|  second long.  The reason we didn't do this in the first place
   1206 	|  is that the first long might have been the last long of RAM.
   1207 
   1208 	movl	_ASM_LABEL(pte_tmp),%a1	| get address of our original pte
   1209 	addql	#4,%a1		| address of ite second long
   1210 
   1211 	| send second long back to user
   1212 	movl	%sp@(12),%a0	| address of where to put pte
   1213 	movsl	%a1@,%d0	|
   1214 	movl	%d0,%a0@(4)	| write in second long
   1215 
   1216 	movql	#1,%d0		| return long-format
   1217 	jra	get_pte_success
   1218 
   1219 short_format:
   1220 	movql	#0,%d0		| return short-format
   1221 	jra	get_pte_success
   1222 
   1223 get_pte_fail:
   1224 	movql	#-1,%d0		| return failure
   1225 
   1226 get_pte_success:
   1227 	lea	_ASM_LABEL(longscratch),%a0 | disable tt
   1228 	movl	#0,%a0@
   1229 	.long	0xf0100800	| pmove %a0@,%tt0
   1230 
   1231 	addql	#4,%sp		| return temporary space
   1232 	rts
   1233 
   1234 get_pte_fail1:
   1235 	jbsr	_C_LABEL(printstar)
   1236 	jra	get_pte_fail
   1237 get_pte_fail2:
   1238 	jbsr	_C_LABEL(printstar)
   1239 	jbsr	_C_LABEL(printstar)
   1240 	jra	get_pte_fail
   1241 get_pte_fail3:
   1242 	jbsr	_C_LABEL(printstar)
   1243 	jbsr	_C_LABEL(printstar)
   1244 	jbsr	_C_LABEL(printstar)
   1245 	jra	get_pte_fail
   1246 get_pte_fail4:
   1247 	jbsr	_C_LABEL(printstar)
   1248 	jbsr	_C_LABEL(printstar)
   1249 	jbsr	_C_LABEL(printstar)
   1250 	jbsr	_C_LABEL(printstar)
   1251 	jra	get_pte_fail
   1252 get_pte_fail5:
   1253 	jbsr	_C_LABEL(printstar)
   1254 	jbsr	_C_LABEL(printstar)
   1255 	jbsr	_C_LABEL(printstar)
   1256 	jbsr	_C_LABEL(printstar)
   1257 	jbsr	_C_LABEL(printstar)
   1258 	jra	get_pte_fail
   1259 get_pte_fail6:
   1260 	jbsr	_C_LABEL(printstar)
   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 	jra	get_pte_fail
   1267 get_pte_fail7:
   1268 	jbsr	_C_LABEL(printstar)
   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 	jra	get_pte_fail
   1276 get_pte_fail8:
   1277 	jbsr	_C_LABEL(printstar)
   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 	jra	get_pte_fail
   1286 get_pte_fail9:
   1287 	jbsr	_C_LABEL(printstar)
   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 	jra	get_pte_fail
   1297 get_pte_fail10:
   1298 	jbsr	_C_LABEL(printstar)
   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 	jra	get_pte_fail
   1309 
   1310 /*
   1311  * Misc. global variables.
   1312  */
   1313 	.data
   1314 GLOBAL(sanity_check)
   1315 	.long	0x18621862	| this is our stack overflow checker.
   1316 
   1317 	.space	4 * PAGE_SIZE
   1318 	.align	4
   1319 ASLOCAL(tmpstk)
   1320 
   1321 GLOBAL(machineid)
   1322 	.long	0		| default to 320
   1323 
   1324 GLOBAL(mmutype)
   1325 	.long	MMU_68851	| default to 68851 PMMU
   1326 
   1327 GLOBAL(cputype)
   1328 	.long	CPU_68020	| default to 68020 CPU
   1329 
   1330 #ifdef __notyet__
   1331 GLOBAL(ectype)
   1332 	.long	EC_NONE		| external cache type, default to none
   1333 #endif
   1334 
   1335 GLOBAL(fputype)
   1336 	.long	FPU_68882	| default to 68882 FPU
   1337 
   1338 GLOBAL(intiolimit)
   1339 	.long	0		| KVA of end of internal IO space
   1340 
   1341 GLOBAL(load_addr)
   1342 	.long	0		| Physical address of kernel
   1343 
   1344 ASLOCAL(lastpage)
   1345 	.long	0		| LAK: to store the addr of last page in mem
   1346 
   1347 GLOBAL(MacOSROMBase)
   1348 	.long	0x40800000
   1349 GLOBAL(mac68k_vrsrc_cnt)
   1350 	.long	0
   1351 GLOBAL(mac68k_vrsrc_vec)
   1352 	.word	0, 0, 0, 0, 0, 0
   1353 
   1354 #ifdef DEBUG
   1355 ASGLOBAL(fulltflush)
   1356 	.long	0
   1357 
   1358 ASGLOBAL(fullcflush)
   1359 	.long	0
   1360 #endif
   1361 
   1362 /* interrupt counters -- leave some space for overriding the names */
   1363 
   1364 GLOBAL(intrnames)
   1365 	.asciz	"spur    "
   1366 	.asciz	"via1    "
   1367 	.asciz	"via2    "
   1368 	.asciz	"unused1 "
   1369 	.asciz	"scc     "
   1370 	.asciz	"unused2 "
   1371 	.asciz	"unused3 "
   1372 	.asciz	"nmi     "
   1373 	.asciz	"clock   "
   1374 GLOBAL(eintrnames)
   1375 	.even
   1376 
   1377 GLOBAL(intrcnt)
   1378 	.long	0,0,0,0,0,0,0,0,0
   1379 GLOBAL(eintrcnt)
   1380