Home | History | Annotate | Line # | Download | only in mac68k
      1 /*	$NetBSD: locore.s,v 1.209 2026/04/07 12:36:22 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 	jbsr	_C_LABEL(setmachdep)	| Set some machine-dep stuff
    193 	jbsr	_C_LABEL(consinit)	| XXX Should only be if graybar on
    194 
    195 /*
    196  * Figure out MacOS mappings and bootstrap NetBSD
    197  */
    198 	lea	_C_LABEL(macos_tc),%a0	| get current %TC
    199 	cmpl	#MMU_68040,_C_LABEL(mmutype) | check to see if 68040
    200 	jeq	Lget040TC
    201 
    202 	pmove	%tc,%a0@
    203 	jra	Lstart3
    204 
    205 Lget040TC:
    206 #if 0
    207 	movl	_C_LABEL(current_mac_model),%a1	 | if an AV Mac, save current
    208 	cmpl	#MACH_CLASSAV,%a1@(CPUINFO_CLASS) | %TC so internal video will
    209 	jne	LnotAV				 | get configured
    210 #endif
    211 	.long	0x4e7a0003		| movc %tc,%d0
    212 	jra	LsaveTC
    213 LnotAV:
    214 	movql	#0,%d0			| otherwise,
    215 	.long	0x4e7b0003		| movc %d0,%tc ;Disable MMU
    216 LsaveTC:
    217 	movl	%d0,%a0@
    218 
    219 Lstart3:
    220 	movl	%a0@,%sp@-		| get Mac OS mapping, relocate video,
    221 	jbsr	_C_LABEL(bootstrap_mac68k) |   bootstrap pmap, et al.
    222 	addql	#4,%sp
    223 
    224 	/*
    225 	 * nextpa is returned in %d0.  We need to squirrel that
    226 	 * away in a callee-saved regstier for use later, after
    227 	 * the MMU is enabled.
    228 	 */
    229 	movl	%d0, %d7
    230 
    231 	/* NOTE: %d7 is now off-limits!! */
    232 
    233 	/*
    234 	 * Set up the vector table, and race to get the MMU
    235 	 * enabled.
    236 	 *
    237 	 * XXX Should move vec_init() call to Lloaddone, like other
    238 	 * XXX m68k platforms do.
    239 	 */
    240 	jbsr	_C_LABEL(vec_init)
    241 
    242 	movl	_C_LABEL(Sysseg_pa),%a1	| system segment table PA
    243 	cmpl	#MMU_68040,_C_LABEL(mmutype)
    244 	jne	Lenablepre040MMU	| if not 040, skip
    245 
    246 	movql	#0,%d0
    247 	.long	0x4e7b0003		| movc %d0,%tc   ;Disable MMU
    248 	.long	0x4e7b0004		| movc %d0,%itt0 ;Disable itt0
    249 	.long	0x4e7b0005		| movc %d0,%itt1 ;Disable itt1
    250 	.long	0x4e7b0006		| movc %d0,%dtt0 ;Disable dtt0
    251 	.long	0x4e7b0007		| movc %d0,%dtt1 ;Disable dtt1
    252 	movl	%a1,%d1
    253 	.word	0xf518			| pflusha
    254 	.long	0x4e7b1807		| movc %d1,%srp
    255 
    256 #if defined(DJMEMCMAX)
    257 	movl	%a3,%sp@-
    258 	cmpl	#MACH_MACC610,_C_LABEL(machineid)
    259 	jeq	Ldjmemc610
    260 	cmpl	#MACH_MACQ610,_C_LABEL(machineid)
    261 	jeq	Ldjmemc610
    262 	cmpl	#MACH_MACC650,_C_LABEL(machineid)
    263 	jeq	Ldjmemccfg
    264 	cmpl	#MACH_MACQ650,_C_LABEL(machineid)
    265 	jeq	Ldjmemccfg
    266 	cmpl	#MACH_MACQ800,_C_LABEL(machineid)
    267 	jeq	Ldjmemccfg
    268 
    269 	jra	Lnodjmemc
    270 
    271 Ldjmemccfg:
    272 	movl	#0x50f0e00c,%a0
    273 	movl	%a0@,%d0	| determine where RAM SIMMs start
    274 	andl	#0x000000FF,%d0
    275 	addl	#0x10,%d0	| bank 3 start
    276 	addl	#0x10,%d0	| bank 4 start
    277 
    278 	movl	#0x50f0e014,%a0
    279 	movl	%d0,%a0@+	| bank 4
    280 	addl	#0x10,%d0
    281 	movl	%d0,%a0@+	| bank 5
    282 	addl	#0x10,%d0
    283 
    284 	movl	%d0,%a0@+	| bank 6
    285 	addl	#0x10,%d0
    286 	movl	%d0,%a0@+	| bank 7
    287 	addl	#0x10,%d0
    288 	movl	%d0,%a0@+	| bank 8
    289 	addl	#0x10,%d0
    290 	movl	%d0,%a0@+	| bank 9
    291 	addl	#0x10,%d0
    292 	jra	Ldjmemctop
    293 
    294 Ldjmemc610:
    295 	movl	#0x50f0e00c,%a0
    296 	movl	%a0@,%d0	| determine where RAM SIMMs start
    297 	andl	#0x000000FF,%d0
    298 	addl	#0x10,%d0	| bank 3 start
    299 
    300 	movl	#0x50f0e014,%a0
    301 	movl	%d0,%a0@+	| bank 4
    302 	addl	#0x10,%d0
    303 	movl	%d0,%a0@+	| bank 5
    304 	movl	%d0,%a0@+	| bank 6
    305 	addl	#0x10,%d0
    306 	movl	%d0,%a0@+	| bank 7
    307 	movl	%d0,%a0@+	| bank 8
    308 	addl	#0x10,%d0
    309 	movl	%d0,%a0@+	| bank 9
    310 
    311 Ldjmemctop:
    312 	movl	#0x50F0E02C,%a0
    313 	movl	%d0,%a0@	| memtop
    314 
    315 	| preserve ~512KB beyond 4MB just in case
    316 	movl	#0x400000,%a0
    317 	movl	#0x9000000,%a2
    318 	movl	#0xFFFF,%d0
    319 L1stbankcopy1:
    320 	movl	%a0@+,%a2@+
    321 	dbra	%d0,L1stbankcopy1
    322 	movl	#0xFFFF,%d0
    323 L1stbankcopy2:
    324 	movl	%a0@+,%a2@+
    325 	dbra	%d0,L1stbankcopy2
    326 
    327 	lea	_ASM_LABEL(Lsetup1stbank),%a0
    328 	movl	#0x8800000,%a2	| Pick a location that should be in bank 4
    329 	movl	#0x64,%d0
    330 Ldjcopy:
    331 	movl	%a0@+,%a2@+
    332 	dbra	%d0,Ldjcopy
    333 
    334 	movl	#0x8800000,%a0
    335 	lea	_ASM_LABEL(Ldjmemcdone),%a2
    336 	jmp	%a0@
    337 
    338 Lsetup1stbank:
    339 	| now configure banks 2 & 3
    340 	movl	#0x50f0e00c,%a0
    341 	movl	%a0@,%d0	| determine where RAM SIMMs start
    342 	andl	#0x000000FF,%d0
    343 	movl	%d0,%a0@+
    344 	addl	#0x10,%d0	| bank 3 start
    345 	movl	%d0,%a0@
    346 
    347 	| and return to where we came from.
    348 	jmp	%a2@
    349 
    350 Ldjmemcdone:
    351 	movl	#0x400000,%a2
    352 	movl	#0x9000000,%a0
    353 	movl	#0xFFFF,%d0
    354 Lcopyback1:
    355 	movl	%a0@+,%a2@+
    356 	dbra	%d0,Lcopyback1
    357 	movl	#0xFFFF,%d0
    358 Lcopyback2:
    359 	movl	%a0@+,%a2@+
    360 	dbra	%d0,Lcopyback2
    361 
    362 Lnodjmemc:
    363 	movl	%sp@+,%a3
    364 #endif
    365 
    366 	movl	#MMU40_TCR_BITS,%d0
    367 	.long	0x4e7b0003		| movc %d0,%tc   ;Enable MMU
    368 	movl	#CACHE40_ON,%d0
    369 	movc	%d0,%cacr		| turn on both caches
    370 	jra	Lloaddone
    371 
    372 Lenablepre040MMU:
    373 	tstl	_C_LABEL(mmutype)	| TTx instructions will break 68851
    374 	jgt	LnokillTT
    375 
    376 	lea	_ASM_LABEL(longscratch),%a0 | disable TTx registers on 68030
    377 	movl	#0,%a0@
    378 	.long	0xf0100800		| movl %a0@,%tt0
    379 	.long	0xf0100c00		| movl %a0@,%tt1
    380 
    381 LnokillTT:
    382 #if defined(M68020) || defined(M68030)
    383 	lea	_C_LABEL(protorp),%a0
    384 	movl	%a1,%a0@(4)		| segtable address
    385 	pmove	%a0@,%srp		| load the supervisor root pointer
    386 	pflusha
    387 	lea	_ASM_LABEL(longscratch),%a2
    388 	movl	#MMU51_TCR_BITS,%a2@	| value to load %TC with
    389 	pmove	%a2@,%tc		| load it
    390 #endif /* M68020 || M68030 */
    391 
    392 /*
    393  * Should be running mapped from this point on
    394  */
    395 Lloaddone:
    396 	lea	_ASM_LABEL(tmpstk),%sp	| temporary stack
    397 
    398 	/* phase 2 of pmap setup, returns lwp0 SP in %a0 */
    399 	jbsr	_C_LABEL(pmap_bootstrap2)
    400 	movl	%a0,%sp			| now running on lwp0's stack
    401 	movl	#0,%a6			| terminate the stack back trace
    402 
    403 /* flush TLB and turn on caches */
    404 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
    405 	jeq	Ltbia040		| yes, cache already on
    406 	pflusha
    407 	movl	#CACHE_ON,%d0
    408 	movc	%d0,%cacr		| clear cache(s)
    409 #ifdef __notyet__
    410 	tstl	_C_LABEL(ectype)
    411 	jeq	Lnocache0
    412 					| Enable external cache here
    413 #endif
    414 	jra	Lnocache0
    415 
    416 Ltbia040:
    417 	.word	0xf518			| pflusha
    418 
    419 Lnocache0:
    420 	movl	%d7,%sp@-		| push nextpa saved above
    421 	jbsr	_C_LABEL(machine_init)	| additional pre-main initialization
    422 	addql	#4,%sp
    423 	jra	_C_LABEL(main)		| main() (never returns)
    424 
    425 /*
    426  * Use common m68k bus error and address error handlers.
    427  */
    428 	.data
    429 GLOBAL(mac68k_a2_fromfault)
    430 	.long	0
    431 GLOBAL(m68k_fault_addr)
    432 	.long	0
    433 
    434 /*
    435  * Interrupt handlers.
    436  *
    437  * Most 68k-based Macintosh computers
    438  *
    439  *      Level 0:        Spurious: ignored
    440  *      Level 1:        VIA1 (clock, ADB)
    441  *      Level 2:        VIA2 (NuBus, SCSI)
    442  *      Level 3:
    443  *      Level 4:        Serial (SCC)
    444  *      Level 5:
    445  *      Level 6:
    446  *      Level 7:        Non-maskable: parity errors, RESET button
    447  *
    448  * On the Q700, Q900 and Q950 in "A/UX mode": this should become:
    449  *
    450  *	Level 0:        Spurious: ignored
    451  *	Level 1:        Software
    452  *	Level 2:        VIA2 (except ethernet, sound)
    453  *	Level 3:        Ethernet
    454  *	Level 4:        Serial (SCC)
    455  *	Level 5:        Sound
    456  *	Level 6:        VIA1
    457  *	Level 7:        NMIs: parity errors, RESET button, YANCC error
    458  *
    459  * On the 660AV and 840AV:
    460  *
    461  *	Level 0:        Spurious: ignored
    462  *	Level 1:        VIA1 (clock, ADB)
    463  *	Level 2:        VIA2 (NuBus, SCSI)
    464  *	Level 3:        PSC device interrupt
    465  *	Level 4:        PSC DMA and serial
    466  *	Level 5:        ???
    467  *	Level 6:        ???
    468  *	Level 7:        NMIs: parity errors?, RESET button
    469  */
    470 
    471 ENTRY_NOPROFILE(spurintr)
    472 	addql	#1,_C_LABEL(intrcnt)+0
    473 	INTERRUPT_SAVEREG
    474 	CPUINFO_INCREMENT(CI_NINTR)
    475 	INTERRUPT_RESTOREREG
    476 	jra	_ASM_LABEL(rei)
    477 
    478 ENTRY_NOPROFILE(intrhand)
    479 	INTERRUPT_SAVEREG
    480 	jbsr	_C_LABEL(intr_dispatch)	| call dispatch routine
    481 	INTERRUPT_RESTOREREG
    482 	jra	_ASM_LABEL(rei)		| all done
    483 
    484 ENTRY_NOPROFILE(lev7intr)
    485 	addql	#1,_C_LABEL(intrcnt)+16
    486 	clrl	%sp@-			| pad %SR to longword
    487 	moveml	#0xFFFF,%sp@-		| save registers
    488 	movl	%usp,%a0		| and save
    489 	movl	%a0,%sp@(FR_SP)		|   the user stack pointer
    490 	jbsr	_C_LABEL(nmihand)	| call handler
    491 	movl	%sp@(FR_SP),%a0		| restore
    492 	movl	%a0,%usp		|   %USP
    493 	moveml	%sp@+,#0x7FFF		| and remaining registers
    494 	addql	#8,%sp			| pop SSP and align word
    495 	jra	_ASM_LABEL(rei)
    496 
    497 /*
    498  * We could tweak rtclock_intr and gain 12 cycles on the 020 and 030 by
    499  * saving the status register directly to the stack, but this would lose
    500  * badly on the 040.  Aligning the stack takes 10 more cycles than this
    501  * code does, so it's a good compromise.
    502  *
    503  * A pointer to the clockframe is passed as an argument in the usual
    504  * fashion.
    505  */
    506 ENTRY_NOPROFILE(rtclock_intr)
    507 	movl	%sp@(4),%a1		| stash pointer to clockframe
    508 	movl	%d2,%sp@-		| save %d2
    509 	movw	%sr,%d2			| save SPL
    510 					| raise SPL to splclock()
    511 	movw	_C_LABEL(ipl2psl_table)+IPL_CLOCK*2,%sr
    512 	movl	%a1,%sp@-		| push pointer to clockframe
    513 	jbsr	_C_LABEL(hardclock)	| call generic clock int routine
    514 	addql	#4,%sp			| pop param
    515 	jbsr	_C_LABEL(mrg_VBLQueue)	| give programs in the VBLqueue a chance
    516 	addql	#1,_C_LABEL(intrcnt)+32	| record a clock interrupt
    517 	INTERRUPT_SAVEREG
    518 	CPUINFO_INCREMENT(CI_NINTR)
    519 	INTERRUPT_RESTOREREG
    520 	movw	%d2,%sr			| restore SPL
    521 	movl	%sp@+,%d2		| restore %d2
    522 	rts				| go back from whence we came
    523 
    524 /*
    525  * delay() - delay for a specified number of microseconds
    526  * _delay() - calibrator helper for delay()
    527  *
    528  * Notice that delay_factor is scaled up by a factor of 128 to avoid loss
    529  * of precision for small delays.  As a result of this we need to avoid
    530  * overflow.
    531  *
    532  * The branch target for the loops must be aligned on a half-line (8-byte)
    533  * boundary to minimize cache effects.  This guarantees both that there
    534  * will be no prefetch stalls due to cache line burst operations and that
    535  * the loops will run from a single cache half-line.
    536  */
    537 	.align	8			| align to half-line boundary
    538 					| (use nop instructions if necessary!)
    539 ALTENTRY(_delay, _delay)
    540 ENTRY(delay)
    541 	movl	%sp@(4),%d0		| get microseconds to delay
    542 	cmpl	#0x40000,%d0		| is it a "large" delay?
    543 	bls	.Ldelayshort		| no, normal calculation
    544 	movql	#0x7f,%d1		| adjust for scaled multiplier (to
    545 	addl	%d1,%d0			|   avoid overflow)
    546 	lsrl	#7,%d0
    547 	mulul	_C_LABEL(delay_factor),%d0 | calculate number of loop iterations
    548 	bra	.Ldelaysetup		| go do it!
    549 .Ldelayshort:
    550 	mulul	_C_LABEL(delay_factor),%d0 | calculate number of loop iterations
    551 	lsrl	#7,%d0			| adjust for scaled multiplier
    552 .Ldelaysetup:
    553 	jeq	.Ldelayexit		| bail out if nothing to do
    554 	movql	#0,%d1			| put bits 15-0 in %d1 for the
    555 	movw	%d0,%d1			|   inner loop, and move bits
    556 	movw	#0,%d0			|   31-16 to the low-order word
    557 	subql	#1,%d1			|   of %d0 for the outer loop
    558 	swap	%d0
    559 .Ldelay:
    560 	tstl	_C_LABEL(delay_flag)	| this never changes for delay()!
    561 	dbeq	%d1,.Ldelay		|   (used only for timing purposes)
    562 	dbeq	%d0,.Ldelay
    563 	addqw	#1,%d1			| adjust end count and
    564 	swap	%d0			|    return the longword result
    565 	orl	%d1,%d0
    566 .Ldelayexit:
    567 	rts
    568 
    569 /*
    570  * Handle the nitty-gritty of rebooting the machine.
    571  * Basically we just turn off the MMU and jump to the appropriate ROM routine.
    572  * Note that we must be running in an address range that is mapped one-to-one
    573  * logical to physical so that the PC is still valid immediately after the MMU
    574  * is turned off.  We have conveniently mapped the last page of physical
    575  * memory this way.
    576  */
    577 ENTRY_NOPROFILE(doboot)
    578 #if defined(M68040)
    579 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
    580 	jeq	Lnocache5		| yes, skip
    581 #endif
    582 	movl	#CACHE_OFF,%d0
    583 	movc	%d0,%cacr		| disable on-chip cache(s)
    584 Lnocache5:
    585 	movl	_C_LABEL(last_page),%a0	| last page of physical memory
    586 	lea	Lbootcode,%a1		| start of boot code
    587 	lea	Lebootcode,%a3		| end of boot code
    588 Lbootcopy:
    589 	movw	%a1@+,%a0@+		| copy a word
    590 	cmpl	%a3,%a1			| done yet?
    591 	jcs	Lbootcopy		| no, keep going
    592 #if defined(M68040)
    593 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
    594 	jne	LmotommuE		| no, skip
    595 	.word	0xf4f8			| cpusha bc
    596 LmotommuE:
    597 #endif
    598 	movl	_C_LABEL(last_page),%a0
    599 	jmp	%a0@			| jump to last page
    600 
    601 Lbootcode:
    602 	lea	%a0@(0x800),%sp		| physical %SP in case of NMI
    603 	movl	_C_LABEL(MacOSROMBase),%a1 | Load MacOS ROMBase
    604 
    605 #if defined(M68040)
    606 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
    607 	jne	LmotommuF		| no, skip
    608 	movl	#0,%d0
    609 	movc	%d0,%cacr		| caches off
    610 	.long	0x4e7b0003		| movc %d0,%tc (disable MMU)
    611 	jra	Ldoboot1
    612 LmotommuF:
    613 #endif
    614 	lea	_ASM_LABEL(longscratch),%a3
    615 	movl	#0,%a3@			| value for pmove to %TC (turn off MMU)
    616 	pmove	%a3@,%tc		| disable MMU
    617 
    618 Ldoboot1:
    619 	lea	%a1@(0x90),%a1		| offset of ROM reset routine
    620 	jmp	%a1@			| and jump to ROM to reset machine
    621 Lebootcode:
    622 
    623 /*
    624  * u_long ptest040(void *addr, u_int fc);
    625  *
    626  * ptest040() does an 040 PTESTR (addr) and returns the 040 MMUSR iff
    627  * translation is enabled.  This allows us to find the physical address
    628  * corresponding to a MacOS logical address for get_physical().
    629  * sar  01-oct-1996
    630  */
    631 ENTRY_NOPROFILE(ptest040)
    632 #if defined(M68040)
    633 	.long	0x4e7a0003		| movc %tc,%d0
    634 	andw	#0x8000,%d0
    635 	jeq	Lget_phys1		| MMU is disabled
    636 	movc	%dfc,%d1		| Save %DFC
    637 	movl	%sp@(8),%d0		| Set FC for ptestr
    638 	movc	%d0,%dfc
    639 	movl	%sp@(4),%a0		| logical address to look up
    640 	.word	0xf568			| ptestr (%a0)
    641 	.long	0x4e7a0805		| movc %mmusr,%d0
    642 	movc	%d1,%dfc		| Restore %DFC
    643 	rts
    644 Lget_phys1:
    645 #endif
    646 	movql	#0,%d0			| return failure
    647 	rts
    648 
    649 /*
    650  * LAK: (7/24/94) This routine was added so that the
    651  *  C routine that runs at startup can figure out how MacOS
    652  *  had mapped memory.  We want to keep the same mapping so
    653  *  that when we set our MMU pointer, the PC doesn't point
    654  *  in the middle of nowhere.
    655  *
    656  * long get_pte(void *addr, unsigned long pte[2], unsigned short *psr)
    657  *
    658  *  Takes "addr" and looks it up in the current MMU pages.  Puts
    659  *  the PTE of that address in "pte" and the result of the
    660  *  search in "psr".  "pte" should be 2 longs in case it is
    661  *  a long-format entry.
    662  *
    663  *  One possible problem here is that setting the TT register
    664  *  may screw something up if we access user data space in a
    665  *  called function or in an interrupt service routine.
    666  *
    667  *  Returns -1 on error, 0 if pte is a short-format pte, or
    668  *  1 if pte is a long-format pte.
    669  *
    670  *  Be sure to only call this routine if the MMU is enabled.  This
    671  *  routine is probably more general than it needs to be -- it
    672  *  could simply return the physical address (replacing
    673  *  get_physical() in machdep).
    674  *
    675  *  "gas" does not understand the %tt0 register, so we must hand-
    676  *  assemble the instructions.
    677  */
    678 ENTRY_NOPROFILE(get_pte)
    679 	subql	#4,%sp		| make temporary space
    680 
    681 	lea	_ASM_LABEL(longscratch),%a0
    682 	movl	#MAC68K_TT_GET_PTE,%a0@ | See pmap.h
    683 	.long	0xf0100800	| pmove %a0@,%tt0
    684 
    685 	movl	%sp@(8),%a0	| logical address to look up
    686 	movl	#0,%a1		| clear in case of failure
    687 	ptestr	#FC_USERD,%a0@,#7,%a1 | search for logical address
    688 	pmove	%psr,%sp@	| store processor status register
    689 	movw	%sp@,%d1
    690 	movl	%sp@(16),%a0	| where to store the %psr
    691 	movw	%d1,%a0@	| send back to caller
    692 	andw	#0xc400,%d1	| if bus error, exceeded limit, or invalid
    693 	jne	get_pte_fail1	| leave now
    694 	tstl	%a1		| check address we got back
    695 	jeq	get_pte_fail2	| if 0, then was not set -- fail
    696 
    697 	movl	%a1,%d0
    698 	movl	%d0,_ASM_LABEL(pte_tmp)	| save for later
    699 
    700 	| send first long back to user
    701 	movl	%sp@(12),%a0	| address of where to put pte
    702 	movsl	%a1@,%d0	|
    703 	movl	%d0,%a0@	| first long
    704 
    705 	andl	#3,%d0		| dt bits of pte
    706 	cmpl	#1,%d0		| should be 1 if page descriptor
    707 	jne	get_pte_fail3	| if not, get out now
    708 
    709 	movl	%sp@(16),%a0	| addr of stored %psr
    710 	movw	%a0@,%d0	| get %psr again
    711 	andw	#7,%d0		| number of levels it found
    712 	addw	#-1,%d0		| find previous level
    713 	movl	%sp@(8),%a0	| logical address to look up
    714 	movl	#0,%a1		| clear in case of failure
    715 
    716 	cmpl	#0,%d0
    717 	jeq	pte_level_zero
    718 	cmpl	#1,%d0
    719 	jeq	pte_level_one
    720 	cmpl	#2,%d0
    721 	jeq	pte_level_two
    722 	cmpl	#3,%d0
    723 	jeq	pte_level_three
    724 	cmpl	#4,%d0
    725 	jeq	pte_level_four
    726 	cmpl	#5,%d0
    727 	jeq	pte_level_five
    728 	cmpl	#6,%d0
    729 	jeq	pte_level_six
    730 	jra	get_pte_fail4	| really should have been one of these...
    731 
    732 pte_level_zero:
    733 	| must get CRP to get length of entries at first level
    734 	lea	_ASM_LABEL(longscratch),%a0 | space for two longs
    735 	pmove	%crp,%a0@	| save root pointer
    736 	movl	%a0@,%d0	| load high long
    737 	jra	pte_got_parent
    738 pte_level_one:
    739 	ptestr	#FC_USERD,%a0@,#1,%a1 | search for logical address
    740 	pmove	%psr,%sp@	| store processor status register
    741 	movw	%sp@,%d1
    742 	jra	pte_got_it
    743 pte_level_two:
    744 	ptestr	#FC_USERD,%a0@,#2,%a1 | search for logical address
    745 	pmove	%psr,%sp@	| store processor status register
    746 	movw	%sp@,%d1
    747 	jra	pte_got_it
    748 pte_level_three:
    749 	ptestr	#FC_USERD,%a0@,#3,%a1 | search for logical address
    750 	pmove	%psr,%sp@	| store processor status register
    751 	movw	%sp@,%d1
    752 	jra	pte_got_it
    753 pte_level_four:
    754 	ptestr	#FC_USERD,%a0@,#4,%a1 | search for logical address
    755 	pmove	%psr,%sp@	| store processor status register
    756 	movw	%sp@,%d1
    757 	jra	pte_got_it
    758 pte_level_five:
    759 	ptestr	#FC_USERD,%a0@,#5,%a1 | search for logical address
    760 	pmove	%psr,%sp@	| store processor status register
    761 	movw	%sp@,%d1
    762 	jra	pte_got_it
    763 pte_level_six:
    764 	ptestr	#FC_USERD,%a0@,#6,%a1 | search for logical address
    765 	pmove	%psr,%sp@	| store processor status register
    766 	movw	%sp@,%d1
    767 
    768 pte_got_it:
    769 	andw	#0xc400,%d1	| if bus error, exceeded limit, or invalid
    770 	jne	get_pte_fail5	| leave now
    771 	tstl	%a1		| check address we got back
    772 	jeq	get_pte_fail6	| if 0, then was not set -- fail
    773 
    774 	movsl	%a1@,%d0		| get pte of parent
    775 	movl	%d0,_C_LABEL(macos_tt0)	| XXX for later analysis (kill me)
    776 pte_got_parent:
    777 	andl	#3,%d0		| dt bits of pte
    778 	cmpl	#2,%d0		| child is short-format descriptor
    779 	jeq	short_format
    780 	cmpl	#3,%d0		| child is long-format descriptor
    781 	jne	get_pte_fail7
    782 
    783 	| long_format -- we must go back, change the tt, and get the
    784 	|  second long.  The reason we didn't do this in the first place
    785 	|  is that the first long might have been the last long of RAM.
    786 
    787 	movl	_ASM_LABEL(pte_tmp),%a1	| get address of our original pte
    788 	addql	#4,%a1		| address of ite second long
    789 
    790 	| send second long back to user
    791 	movl	%sp@(12),%a0	| address of where to put pte
    792 	movsl	%a1@,%d0	|
    793 	movl	%d0,%a0@(4)	| write in second long
    794 
    795 	movql	#1,%d0		| return long-format
    796 	jra	get_pte_success
    797 
    798 short_format:
    799 	movql	#0,%d0		| return short-format
    800 	jra	get_pte_success
    801 
    802 get_pte_fail:
    803 	movql	#-1,%d0		| return failure
    804 
    805 get_pte_success:
    806 	lea	_ASM_LABEL(longscratch),%a0 | disable tt
    807 	movl	#0,%a0@
    808 	.long	0xf0100800	| pmove %a0@,%tt0
    809 
    810 	addql	#4,%sp		| return temporary space
    811 	rts
    812 
    813 get_pte_fail1:
    814 	jbsr	_C_LABEL(printstar)
    815 	jra	get_pte_fail
    816 get_pte_fail2:
    817 	jbsr	_C_LABEL(printstar)
    818 	jbsr	_C_LABEL(printstar)
    819 	jra	get_pte_fail
    820 get_pte_fail3:
    821 	jbsr	_C_LABEL(printstar)
    822 	jbsr	_C_LABEL(printstar)
    823 	jbsr	_C_LABEL(printstar)
    824 	jra	get_pte_fail
    825 get_pte_fail4:
    826 	jbsr	_C_LABEL(printstar)
    827 	jbsr	_C_LABEL(printstar)
    828 	jbsr	_C_LABEL(printstar)
    829 	jbsr	_C_LABEL(printstar)
    830 	jra	get_pte_fail
    831 get_pte_fail5:
    832 	jbsr	_C_LABEL(printstar)
    833 	jbsr	_C_LABEL(printstar)
    834 	jbsr	_C_LABEL(printstar)
    835 	jbsr	_C_LABEL(printstar)
    836 	jbsr	_C_LABEL(printstar)
    837 	jra	get_pte_fail
    838 get_pte_fail6:
    839 	jbsr	_C_LABEL(printstar)
    840 	jbsr	_C_LABEL(printstar)
    841 	jbsr	_C_LABEL(printstar)
    842 	jbsr	_C_LABEL(printstar)
    843 	jbsr	_C_LABEL(printstar)
    844 	jbsr	_C_LABEL(printstar)
    845 	jra	get_pte_fail
    846 get_pte_fail7:
    847 	jbsr	_C_LABEL(printstar)
    848 	jbsr	_C_LABEL(printstar)
    849 	jbsr	_C_LABEL(printstar)
    850 	jbsr	_C_LABEL(printstar)
    851 	jbsr	_C_LABEL(printstar)
    852 	jbsr	_C_LABEL(printstar)
    853 	jbsr	_C_LABEL(printstar)
    854 	jra	get_pte_fail
    855 get_pte_fail8:
    856 	jbsr	_C_LABEL(printstar)
    857 	jbsr	_C_LABEL(printstar)
    858 	jbsr	_C_LABEL(printstar)
    859 	jbsr	_C_LABEL(printstar)
    860 	jbsr	_C_LABEL(printstar)
    861 	jbsr	_C_LABEL(printstar)
    862 	jbsr	_C_LABEL(printstar)
    863 	jbsr	_C_LABEL(printstar)
    864 	jra	get_pte_fail
    865 get_pte_fail9:
    866 	jbsr	_C_LABEL(printstar)
    867 	jbsr	_C_LABEL(printstar)
    868 	jbsr	_C_LABEL(printstar)
    869 	jbsr	_C_LABEL(printstar)
    870 	jbsr	_C_LABEL(printstar)
    871 	jbsr	_C_LABEL(printstar)
    872 	jbsr	_C_LABEL(printstar)
    873 	jbsr	_C_LABEL(printstar)
    874 	jbsr	_C_LABEL(printstar)
    875 	jra	get_pte_fail
    876 get_pte_fail10:
    877 	jbsr	_C_LABEL(printstar)
    878 	jbsr	_C_LABEL(printstar)
    879 	jbsr	_C_LABEL(printstar)
    880 	jbsr	_C_LABEL(printstar)
    881 	jbsr	_C_LABEL(printstar)
    882 	jbsr	_C_LABEL(printstar)
    883 	jbsr	_C_LABEL(printstar)
    884 	jbsr	_C_LABEL(printstar)
    885 	jbsr	_C_LABEL(printstar)
    886 	jbsr	_C_LABEL(printstar)
    887 	jra	get_pte_fail
    888 
    889 /*
    890  * Misc. global variables.
    891  */
    892 	.data
    893 GLOBAL(sanity_check)
    894 	.long	0x18621862	| this is our stack overflow checker.
    895 
    896 	.space	4 * PAGE_SIZE
    897 	.align	4
    898 ASGLOBAL(tmpstk)
    899 
    900 GLOBAL(machineid)
    901 	.long	0		| default to 320
    902 
    903 GLOBAL(mmutype)
    904 	.long	MMU_68851	| default to 68851 PMMU
    905 
    906 GLOBAL(cputype)
    907 	.long	CPU_68020	| default to 68020 CPU
    908 
    909 #ifdef __notyet__
    910 GLOBAL(ectype)
    911 	.long	EC_NONE		| external cache type, default to none
    912 #endif
    913 
    914 GLOBAL(intiolimit)
    915 	.long	0		| KVA of end of internal IO space
    916 
    917 GLOBAL(load_addr)
    918 	.long	0		| Physical address of kernel
    919 
    920 ASLOCAL(lastpage)
    921 	.long	0		| LAK: to store the addr of last page in mem
    922 
    923 GLOBAL(MacOSROMBase)
    924 	.long	0x40800000
    925 GLOBAL(mac68k_vrsrc_cnt)
    926 	.long	0
    927 GLOBAL(mac68k_vrsrc_vec)
    928 	.word	0, 0, 0, 0, 0, 0
    929 
    930 #ifdef DEBUG
    931 ASGLOBAL(fulltflush)
    932 	.long	0
    933 
    934 ASGLOBAL(fullcflush)
    935 	.long	0
    936 #endif
    937 
    938 /* interrupt counters -- leave some space for overriding the names */
    939 
    940 GLOBAL(intrnames)
    941 	.asciz	"spur    "
    942 	.asciz	"via1    "
    943 	.asciz	"via2    "
    944 	.asciz	"unused1 "
    945 	.asciz	"scc     "
    946 	.asciz	"unused2 "
    947 	.asciz	"unused3 "
    948 	.asciz	"nmi     "
    949 	.asciz	"clock   "
    950 GLOBAL(eintrnames)
    951 	.even
    952 
    953 GLOBAL(intrcnt)
    954 	.long	0,0,0,0,0,0,0,0,0
    955 GLOBAL(eintrcnt)
    956