Home | History | Annotate | Line # | Download | only in hp300
      1 /*	$NetBSD: locore.s,v 1.186 2024/02/04 18:52:35 andvar Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1980, 1990, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * This code is derived from software contributed to Berkeley by
      8  * the Systems Programming Group of the University of Utah Computer
      9  * Science Department.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  *
     35  * from: Utah $Hdr: locore.s 1.66 92/12/22$
     36  *
     37  *	@(#)locore.s	8.6 (Berkeley) 5/27/94
     38  */
     39 
     40 /*
     41  * Copyright (c) 1994, 1995 Gordon W. Ross
     42  * Copyright (c) 1988 University of Utah.
     43  *
     44  * This code is derived from software contributed to Berkeley by
     45  * the Systems Programming Group of the University of Utah Computer
     46  * Science Department.
     47  *
     48  * Redistribution and use in source and binary forms, with or without
     49  * modification, are permitted provided that the following conditions
     50  * are met:
     51  * 1. Redistributions of source code must retain the above copyright
     52  *    notice, this list of conditions and the following disclaimer.
     53  * 2. Redistributions in binary form must reproduce the above copyright
     54  *    notice, this list of conditions and the following disclaimer in the
     55  *    documentation and/or other materials provided with the distribution.
     56  * 3. All advertising materials mentioning features or use of this software
     57  *    must display the following acknowledgement:
     58  *	This product includes software developed by the University of
     59  *	California, Berkeley and its contributors.
     60  * 4. Neither the name of the University nor the names of its contributors
     61  *    may be used to endorse or promote products derived from this software
     62  *    without specific prior written permission.
     63  *
     64  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     65  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     66  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     67  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     68  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     69  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     70  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     71  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     72  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     73  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     74  * SUCH DAMAGE.
     75  *
     76  * from: Utah $Hdr: locore.s 1.66 92/12/22$
     77  *
     78  *	@(#)locore.s	8.6 (Berkeley) 5/27/94
     79  */
     80 
     81 #include "opt_compat_netbsd.h"
     82 #include "opt_compat_sunos.h"
     83 #include "opt_ddb.h"
     84 #include "opt_fpsp.h"
     85 #include "opt_kgdb.h"
     86 #include "opt_lockdebug.h"
     87 #include "opt_fpu_emulate.h"
     88 #include "opt_m68k_arch.h"
     89 
     90 #include "assym.h"
     91 #include <machine/asm.h>
     92 #include <machine/trap.h>
     93 
     94 #include "opt_useleds.h"
     95 #ifdef USELEDS
     96 #include <hp300/hp300/leds.h>
     97 #endif
     98 
     99 #include "audio.h"
    100 #include "ksyms.h"
    101 
    102 #define MMUADDR(ar)	movl	_C_LABEL(MMUbase),ar
    103 #define CLKADDR(ar)	movl	_C_LABEL(CLKbase),ar
    104 
    105 /*
    106  * This is for kvm_mkdb, and should be the address of the beginning
    107  * of the kernel text segment (not necessarily the same as kernbase).
    108  */
    109 	.text
    110 GLOBAL(kernel_text)
    111 
    112 /*
    113  * Clear and skip the first page of text; it will not be mapped at
    114  * VA 0.
    115  *
    116  * The bootloader places the bootinfo in this page, and we allocate
    117  * a VA for it and map it later.
    118  */
    119 	.fill	PAGE_SIZE/4,4,0
    120 
    121 /*
    122  * Temporary stack for a variety of purposes.
    123  * Try and make this the first thing is the data segment so it
    124  * is page aligned.  Note that if we overflow here, we run into
    125  * our text segment.
    126  */
    127 	.data
    128 	.space	PAGE_SIZE
    129 ASLOCAL(tmpstk)
    130 
    131 /*
    132  * Macro to relocate a symbol, used before MMU is enabled.
    133  */
    134 #define	IMMEDIATE		#
    135 #define	_RELOC(var, ar)			\
    136 	movel	IMMEDIATE var,ar;	\
    137 	addl	%a5,ar
    138 
    139 #define	RELOC(var, ar)		_RELOC(_C_LABEL(var), ar)
    140 #define	ASRELOC(var, ar)	_RELOC(_ASM_LABEL(var), ar)
    141 
    142 /*
    143  * Final bits of grunt work required to reboot the system.  The MMU
    144  * must be disabled when this is invoked.
    145  */
    146 #define DOREBOOT						\
    147 	/* Reset Vector Base Register to what PROM expects. */  \
    148 	movl	#0,%d0;						\
    149 	movc	%d0,%vbr;					\
    150 	/* Jump to REQ_REBOOT */				\
    151 	jmp	0x1A4;
    152 
    153 /*
    154  * Initialization
    155  *
    156  * A4 contains the address of the end of the symtab
    157  * A5 contains physical load point from boot
    158  * VBR contains zero from ROM.  Exceptions will continue to vector
    159  * through ROM until MMU is turned on at which time they will vector
    160  * through our table (vectors.s).
    161  */
    162 
    163 BSS(lowram,4)
    164 BSS(esym,4)
    165 
    166 ASENTRY_NOPROFILE(start)
    167 	movw	#PSL_HIGHIPL,%sr	| no interrupts
    168 	ASRELOC(tmpstk, %a0)
    169 	movl	%a0,%sp			| give ourselves a temporary stack
    170 	RELOC(esym, %a0)
    171 	movl	%a4,%a0@		| store end of symbol table
    172 	RELOC(lowram, %a0)
    173 	movl	%a5,%a0@		| store start of physical memory
    174 	movl	#CACHE_OFF,%d0
    175 	movc	%d0,%cacr		| clear and disable on-chip cache(s)
    176 
    177 /* check for internal HP-IB in SYSFLAG */
    178 	btst	#5,0xfffffed2		| internal HP-IB?
    179 	jeq	Lhaveihpib		| yes, have HP-IB just continue
    180 	RELOC(internalhpib, %a0)
    181 	movl	#0,%a0@			| no, clear associated address
    182 Lhaveihpib:
    183 
    184 	RELOC(boothowto, %a0)		| save reboot flags
    185 	movl	%d7,%a0@
    186 	RELOC(bootdev, %a0)		|   and boot device
    187 	movl	%d6,%a0@
    188 
    189 	/*
    190 	 * All data registers are now free.  All address registers
    191 	 * except %a5 are free.  %a5 is used by the RELOC() macro,
    192 	 * and cannot be used until after the MMU is enabled.
    193 	 */
    194 
    195 /* determine our CPU/MMU combo - check for all regardless of kernel config */
    196 	movl	#INTIOBASE+MMUBASE,%a1
    197 	movl	#DC_FREEZE,%d0		| data freeze bit
    198 	movc	%d0,%cacr		|   only exists on 68030
    199 	movc	%cacr,%d0		| read it back
    200 	tstl	%d0			| zero?
    201 	jeq	Lnot68030		| yes, we have 68020/68040
    202 
    203 	/*
    204 	 * 68030 models
    205 	 */
    206 
    207 	RELOC(mmutype, %a0)		| no, we have 68030
    208 	movl	#MMU_68030,%a0@		| set to reflect 68030 PMMU
    209 	RELOC(cputype, %a0)
    210 	movl	#CPU_68030,%a0@		| and 68030 CPU
    211 	RELOC(machineid, %a0)
    212 	movl	#0x80,%a1@(MMUCMD)	| set magic cookie
    213 	movl	%a1@(MMUCMD),%d0	| read it back
    214 	btst	#7,%d0			| cookie still on?
    215 	jeq	Lnot370			| no, 360, 362 or 375
    216 	movl	#0,%a1@(MMUCMD)		| clear magic cookie
    217 	movl	%a1@(MMUCMD),%d0	| read it back
    218 	btst	#7,%d0			| still on?
    219 	jeq	Lisa370			| no, must be a 370
    220 	movl	#HP_340,%a0@		| yes, must be a 340
    221 	jra	Lstart1
    222 Lnot370:
    223 	movl	#HP_360,%a0@		| type is at least a 360
    224 	movl	#0,%a1@(MMUCMD)		| clear magic cookie2
    225 	movl	%a1@(MMUCMD),%d0	| read it back
    226 	btst	#16,%d0			| still on?
    227 	jeq	Lisa36x			| no, must be a 360 or a 362
    228 	RELOC(mmuid, %a0)		| save MMU ID
    229 	lsrl	#MMUID_SHIFT,%d0
    230 	andl	#MMUID_MASK,%d0
    231 	movl	%d0,%a0@
    232 	RELOC(machineid, %a0)
    233 	cmpb	#MMUID_345,%d0		| are we a 345?
    234 	beq	Lisa345
    235 	cmpb	#MMUID_375,%d0		| how about a 375?
    236 	beq	Lisa375
    237 	movl	#HP_400,%a0@		| must be a 400
    238 	jra	Lhaspac
    239 Lisa36x:
    240 	/*
    241 	 * If we found a 360, we need to check for a 362 (neither the 360
    242 	 * nor the 362 have a nonzero mmuid). Identify 362 by checking
    243 	 * on-board VRX framebuffer which has secid 0x11 at dio scode 132.
    244 	 */
    245 	movl	#DIOII_BASE,%a0		| probe dio scode 132
    246 	ASRELOC(phys_badaddr,%a3)
    247 	jbsr	%a3@
    248 	tstl	%d0			| device at scode 132?
    249 	jne	Lstart1			| no, not 362, assume 360
    250 	movb	%a0@(DIO_IDOFF),%d0
    251 	cmpb	#DIO_DEVICE_ID_FRAMEBUFFER,%d0	| framebuffer?
    252 	jne	Lstart1			| no, not 362, assume 360
    253 	movb	%a0@(DIO_SECIDOFF),%d0
    254 	cmpb	#0x11,%d0		| VRX sti on 362?
    255 	jne	Lstart1			| no, not 362, assume 360
    256 	RELOC(machineid,%a0)
    257 	movl	#HP_362,%a0@
    258 	jra	Lstart1
    259 Lisa345:
    260 	movl	#HP_345,%a0@
    261 	jra	Lhaspac
    262 Lisa375:
    263 	movl	#HP_375,%a0@
    264 	jra	Lhaspac
    265 Lisa370:
    266 	movl	#HP_370,%a0@		| set to 370
    267 Lhaspac:
    268 	RELOC(ectype, %a0)
    269 	movl	#EC_PHYS,%a0@		| also has a physical address cache
    270 	jra	Lstart1
    271 
    272 	/*
    273 	 * End of 68030 section
    274 	 */
    275 
    276 Lnot68030:
    277 	bset	#31,%d0			| data cache enable bit
    278 	movc	%d0,%cacr		|   only exists on 68040
    279 	movc	%cacr,%d0		| read it back
    280 	tstl	%d0			| zero?
    281 	beq	Lis68020		| yes, we have 68020
    282 	moveq	#0,%d0			| now turn it back off
    283 	movec	%d0,%cacr		|   before we access any data
    284 
    285 	/*
    286 	 * 68040 models
    287 	 */
    288 
    289 	RELOC(mmutype, %a0)
    290 	movl	#MMU_68040,%a0@		| with a 68040 MMU
    291 	RELOC(cputype, %a0)
    292 	movl	#CPU_68040,%a0@		| and a 68040 CPU
    293 	RELOC(fputype, %a0)
    294 	movl	#FPU_68040,%a0@		| ...and FPU
    295 	RELOC(ectype, %a0)
    296 	movl	#EC_NONE,%a0@		| and no cache (for now XXX)
    297 	RELOC(mmuid,%a0)		| save MMU ID
    298 	movl	%a1@(MMUCMD),%d0
    299 	lsrl	#MMUID_SHIFT,%d0
    300 	andl	#MMUID_MASK,%d0
    301 	movl	%d0,%a0@
    302 	RELOC(machineid, %a0)
    303 	cmpb	#MMUID_425_T,%d0	| are we a 425t?
    304 	jeq	Lisa425
    305 	cmpb	#MMUID_425_S,%d0	| how about 425s?
    306 	jeq	Lisa425
    307 	cmpb	#MMUID_425_E,%d0	| or maybe a 425e?
    308 	jeq	Lisa425
    309 	cmpb	#MMUID_433_T,%d0	| or a 433t?
    310 	jeq	Lisa433
    311 	cmpb	#MMUID_433_S,%d0	| or a 433s?
    312 	jeq	Lisa433
    313 	cmpb	#MMUID_385,%d0		| or a 385?
    314 	jeq	Lisa385
    315 	cmpb	#MMUID_382,%d0		| or a 382?
    316 	jeq	Lisa382
    317 	movl	#HP_380,%a0@		| guess we're a 380
    318 	jra	Lstart1
    319 Lisa425:
    320 	movl	#HP_425,%a0@
    321 	jra	Lstart1
    322 Lisa433:
    323 	movl	#HP_433,%a0@
    324 	jra	Lstart1
    325 Lisa385:
    326 	movl	#HP_385,%a0@
    327 	jra	Lstart1
    328 Lisa382:
    329 	movl	#HP_382,%a0@
    330 	jra	Lstart1
    331 
    332 	/*
    333 	 * End of 68040 section
    334 	 */
    335 
    336 	/*
    337 	 * 68020 models
    338 	 */
    339 
    340 Lis68020:
    341 	RELOC(fputype, %a0)		| all of the 68020 systems
    342 	movl	#FPU_68881,%a0@		|   have a 68881 FPU
    343 	movl	#1,%a1@(MMUCMD)		| a 68020, write HP MMU location
    344 	movl	%a1@(MMUCMD),%d0	| read it back
    345 	btst	#0,%d0			| non-zero?
    346 	jne	Lishpmmu		| yes, we have HP MMU
    347 	RELOC(mmutype, %a0)
    348 	movl	#MMU_68851,%a0@		| no, we have PMMU
    349 	RELOC(machineid, %a0)
    350 	movl	#HP_330,%a0@		| and 330 CPU
    351 	jra	Lstart1
    352 Lishpmmu:
    353 	RELOC(ectype, %a0)		| 320 or 350
    354 	movl	#EC_VIRT,%a0@		| both have a virtual address cache
    355 	movl	#0x80,%a1@(MMUCMD)	| set magic cookie
    356 	movl	%a1@(MMUCMD),%d0	| read it back
    357 	btst	#7,%d0			| cookie still on?
    358 	jeq	Lis320			| no, just a 320
    359 	RELOC(machineid, %a0)
    360 	movl	#HP_350,%a0@		| yes, a 350
    361 	jra	Lstart1
    362 Lis320:
    363 	RELOC(machineid, %a0)
    364 	movl	#HP_320,%a0@
    365 
    366 	/*
    367 	 * End of 68020 section
    368 	 */
    369 
    370 Lstart1:
    371 	movl	#0,%a1@(MMUCMD)		| clear out MMU again
    372 /* initialize source/destination control registers for movs */
    373 	moveq	#FC_USERD,%d0		| user space
    374 	movc	%d0,%sfc		|   as source
    375 	movc	%d0,%dfc		|   and destination of transfers
    376 /* save the first PA as bootinfo_pa to map it to a virtual address later. */
    377 	movl	%a5,%d0			| lowram value from ROM via boot
    378 	RELOC(bootinfo_pa, %a0)
    379 	movl	%d0,%a0@		| save the lowram as bootinfo PA
    380 /* initialize memory sizes (for pmap_bootstrap) */
    381 	movl	#MAXADDR,%d1		| last page
    382 	moveq	#PGSHIFT,%d2
    383 	lsrl	%d2,%d1			| convert to page (click) number
    384 	RELOC(maxmem, %a0)
    385 	movl	%d1,%a0@		| save as maxmem
    386 	lsrl	%d2,%d0			| convert the lowram to page number
    387 	subl	%d0,%d1			| compute amount of RAM present
    388 	RELOC(physmem, %a0)
    389 	movl	%d1,%a0@		| and physmem
    390 
    391 /* configure kernel and lwp0 VA space so we can get going */
    392 #if NKSYMS || defined(DDB) || defined(MODULAR)
    393 	RELOC(esym,%a0)			| end of static kernel test/data/syms
    394 	movl	%a0@,%d5
    395 	jne	Lstart3
    396 #endif
    397 	movl	#_C_LABEL(end),%d5	| end of static kernel text/data
    398 Lstart3:
    399 	addl	#PAGE_SIZE-1,%d5
    400 	andl	#PG_FRAME,%d5		| round to a page
    401 	movl	%d5,%a4
    402 	addl	%a5,%a4			| convert to PA
    403 	pea	%a5@			| firstpa
    404 	pea	%a4@			| nextpa
    405 	RELOC(pmap_bootstrap,%a0)
    406 	jbsr	%a0@			| pmap_bootstrap(firstpa, nextpa)
    407 	addql	#8,%sp
    408 
    409 /*
    410  * Prepare to enable MMU.
    411  * Since the kernel is not mapped logical == physical we must insure
    412  * that when the MMU is turned on, all prefetched addresses (including
    413  * the PC) are valid.  In order guarantee that, we use the last physical
    414  * page (which is conveniently mapped == VA) and load it up with enough
    415  * code to defeat the prefetch, then we execute the jump back to here.
    416  *
    417  * Is this all really necessary, or am I paranoid??
    418  */
    419 	RELOC(Sysseg_pa, %a0)		| system segment table addr
    420 	movl	%a0@,%d1		| read value (a PA)
    421 	RELOC(mmutype, %a0)
    422 	tstl	%a0@			| HP MMU?
    423 	jeq	Lhpmmu2			| yes, skip
    424 	cmpl	#MMU_68040,%a0@		| 68040?
    425 	jne	Lmotommu1		| no, skip
    426 	.long	0x4e7b1807		| movc %d1,%srp
    427 	jra	Lstploaddone
    428 Lmotommu1:
    429 	RELOC(protorp, %a0)
    430 	movl	%d1,%a0@(4)		| segtable address
    431 	pmove	%a0@,%srp		| load the supervisor root pointer
    432 	jra	Lstploaddone		| done
    433 Lhpmmu2:
    434 	moveq	#PGSHIFT,%d2
    435 	lsrl	%d2,%d1			| convert to page frame
    436 	movl	%d1,INTIOBASE+MMUBASE+MMUSSTP | load in sysseg table register
    437 Lstploaddone:
    438 	lea	MAXADDR,%a2		| PA of last RAM page
    439 #if 0
    440 	ASRELOC(Lhighcode, %a1)		| addr of high code
    441 	ASRELOC(Lehighcode, %a3)	| end addr
    442 #else
    443 	/* don't want pc-relative addressing */
    444 	.word	0x43f9			| lea Lhighcode, %a1
    445 	.long	Lhighcode
    446 	addl	%a5, %a1
    447 	.word	0x47f9			| lea Lehighcode, %a3
    448 	.long	Lehighcode
    449 	addl	%a5, %a3
    450 #endif
    451 Lcodecopy:
    452 	movw	%a1@+,%a2@+		| copy a word
    453 	cmpl	%a3,%a1			| done yet?
    454 	jcs	Lcodecopy		| no, keep going
    455 	jmp	MAXADDR			| go for it!
    456 
    457 	/*
    458 	 * BEGIN MMU TRAMPOLINE.  This section of code is not
    459 	 * executed in-place.  It's copied to the last page
    460 	 * of RAM (mapped va == pa) and executed there.
    461 	 */
    462 
    463 Lhighcode:
    464 	RELOC(mmutype, %a0)
    465 	tstl	%a0@			| HP MMU?
    466 	jeq	Lhpmmu3			| yes, skip
    467 	cmpl	#MMU_68040,%a0@		| 68040?
    468 	jne	Lmotommu2		| no, skip
    469 	movw	#0,INTIOBASE+MMUBASE+MMUCMD+2
    470 	movw	#MMU_IEN+MMU_CEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD+2
    471 					| enable FPU and caches
    472 	moveq	#0,%d0			| ensure TT regs are disabled
    473 	.long	0x4e7b0004		| movc %d0,%itt0
    474 	.long	0x4e7b0005		| movc %d0,%itt1
    475 	.long	0x4e7b0006		| movc %d0,%dtt0
    476 	.long	0x4e7b0007		| movc %d0,%dtt1
    477 	.word	0xf4d8			| cinva bc
    478 	.word	0xf518			| pflusha
    479 	movl	#MMU40_TCR_BITS,%d0
    480 	.long	0x4e7b0003		| movc %d0,%tc
    481 	movl	#CACHE40_ON,%d0
    482 	movc	%d0,%cacr		| turn on both caches
    483 	jmp	Lenab1:l		| forced not be pc-relative
    484 Lmotommu2:
    485 	movl	#MMU_IEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD
    486 					| enable 68881 and i-cache
    487 	pflusha
    488 	RELOC(prototc, %a2)
    489 	movl	#MMU51_TCR_BITS,%a2@	| value to load TC with
    490 	pmove	%a2@,%tc		| load it
    491 	jmp	Lenab1:l		| forced not be pc-relative
    492 Lhpmmu3:
    493 	movl	#0,INTIOBASE+MMUBASE+MMUCMD		| clear external cache
    494 	movl	#MMU_ENAB,INTIOBASE+MMUBASE+MMUCMD	| turn on MMU
    495 	jmp	Lenab1:l		| forced not be pc-relative
    496 Lehighcode:
    497 
    498 	/*
    499 	 * END MMU TRAMPOLINE.  Address register %a5 is now free.
    500 	 */
    501 
    502 /*
    503  * Should be running mapped from this point on
    504  */
    505 Lenab1:
    506 	lea	_ASM_LABEL(tmpstk),%sp	| re-load the temporary stack
    507 	jbsr	_C_LABEL(vec_init)	| initialize the vector table
    508 /* call final pmap setup */
    509 	jbsr	_C_LABEL(pmap_bootstrap_finalize)
    510 /* set kernel stack, user SP */
    511 	movl	_C_LABEL(lwp0uarea),%a1	| get lwp0 uarea
    512 	lea	%a1@(USPACE-4),%sp	| set kernel stack to end of area
    513 	movl	#USRSTACK-4,%a2
    514 	movl	%a2,%usp		| init user SP
    515 
    516 	jbsr	_C_LABEL(fpu_probe)
    517 	movl	%d0,_C_LABEL(fputype)
    518 	tstl	_C_LABEL(fputype)	| Have an FPU?
    519 	jeq	Lenab2			| No, skip.
    520 	clrl	%a1@(PCB_FPCTX)		| ensure null FP context
    521 	movl	%a1,%sp@-
    522 	jbsr	_C_LABEL(m68881_restore) | restore it (does not kill %a1)
    523 	addql	#4,%sp
    524 Lenab2:
    525 /* flush TLB and turn on caches */
    526 	jbsr	_C_LABEL(_TBIA)		| invalidate TLB
    527 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
    528 	jeq	Lnocache0		| yes, cache already on
    529 	movl	#CACHE_ON,%d0
    530 	movc	%d0,%cacr		| clear cache(s)
    531 	tstl	_C_LABEL(ectype)
    532 	jeq	Lnocache0
    533 	MMUADDR(%a0)
    534 	orl	#MMU_CEN,%a0@(MMUCMD)	| turn on external cache
    535 Lnocache0:
    536 /* Final setup for call to main(). */
    537 	jbsr	_C_LABEL(hp300_init)
    538 
    539 /*
    540  * Create a fake exception frame so that cpu_lwp_fork() can copy it.
    541  * main() nevers returns; we exit to user mode from a forked process
    542  * later on.
    543  */
    544 	clrw	%sp@-			| vector offset/frame type
    545 	clrl	%sp@-			| PC - filled in by "execve"
    546 	movw	#PSL_USER,%sp@-		| in user mode
    547 	clrl	%sp@-			| stack adjust count and padding
    548 	lea	%sp@(-64),%sp		| construct space for D0-D7/A0-A7
    549 	lea	_C_LABEL(lwp0),%a0	| save pointer to frame
    550 	movl	%sp,%a0@(L_MD_REGS)	|   in lwp0.l_md.md_regs
    551 
    552 	jra	_C_LABEL(main)		| main()
    553 	PANIC("main() returned")
    554 	/* NOTREACHED */
    555 
    556 /*
    557  * Trap/interrupt vector routines
    558  */
    559 #include <m68k/m68k/trap_subr.s>
    560 
    561 /*
    562  * Use common m68k bus error and address error handlers.
    563  */
    564 #include <m68k/m68k/busaddrerr.s>
    565 
    566 /*
    567  * FP exceptions.
    568  */
    569 ENTRY_NOPROFILE(fpfline)
    570 #if defined(M68040)
    571 	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
    572 	jne	Lfp_unimp		| no, skip FPSP
    573 	cmpw	#0x202c,%sp@(6)		| format type 2?
    574 	jne	_C_LABEL(illinst)	| no, not an FP emulation
    575 Ldofp_unimp:
    576 #ifdef FPSP
    577 	jmp	_ASM_LABEL(fpsp_unimp)	| yes, go handle it
    578 #endif
    579 Lfp_unimp:
    580 #endif /* M68040 */
    581 #ifdef FPU_EMULATE
    582 	clrl	%sp@-			| stack adjust count
    583 	moveml	#0xFFFF,%sp@-		| save registers
    584 	moveq	#T_FPEMULI,%d0		| denote as FP emulation trap
    585 	jra	_ASM_LABEL(fault)	| do it
    586 #else
    587 	jra	_C_LABEL(illinst)
    588 #endif
    589 
    590 ENTRY_NOPROFILE(fpunsupp)
    591 #if defined(M68040)
    592 	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
    593 	jne	_C_LABEL(illinst)	| no, treat as illinst
    594 #ifdef FPSP
    595 	jmp	_ASM_LABEL(fpsp_unsupp)	| yes, go handle it
    596 #endif
    597 Lfp_unsupp:
    598 #endif /* M68040 */
    599 #ifdef FPU_EMULATE
    600 	clrl	%sp@-			| stack adjust count
    601 	moveml	#0xFFFF,%sp@-		| save registers
    602 	moveq	#T_FPEMULD,%d0		| denote as FP emulation trap
    603 	jra	_ASM_LABEL(fault)	| do it
    604 #else
    605 	jra	_C_LABEL(illinst)
    606 #endif
    607 
    608 /*
    609  * Handles all other FP coprocessor exceptions.
    610  * Note that since some FP exceptions generate mid-instruction frames
    611  * and may cause signal delivery, we need to test for stack adjustment
    612  * after the trap call.
    613  */
    614 ENTRY_NOPROFILE(fpfault)
    615 	clrl	%sp@-			| stack adjust count
    616 	moveml	#0xFFFF,%sp@-		| save user registers
    617 	movl	%usp,%a0		| and save
    618 	movl	%a0,%sp@(FR_SP)		|   the user stack pointer
    619 	clrl	%sp@-			| no VA arg
    620 	movl	_C_LABEL(curpcb),%a0	| current pcb
    621 	lea	%a0@(PCB_FPCTX),%a0	| address of FP savearea
    622 	fsave	%a0@			| save state
    623 #if defined(M68040) || defined(M68060)
    624 	/* always null state frame on 68040, 68060 */
    625 	cmpl	#FPU_68040,_C_LABEL(fputype)
    626 	jge	Lfptnull
    627 #endif
    628 	tstb	%a0@			| null state frame?
    629 	jeq	Lfptnull		| yes, safe
    630 	clrw	%d0			| no, need to tweak BIU
    631 	movb	%a0@(1),%d0		| get frame size
    632 	bset	#3,%a0@(0,%d0:w)	| set exc_pend bit of BIU
    633 Lfptnull:
    634 	fmovem	%fpsr,%sp@-		| push %fpsr as code argument
    635 	frestore %a0@			| restore state
    636 	movl	#T_FPERR,%sp@-		| push type arg
    637 	jra	_ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup
    638 
    639 /*
    640  * Other exceptions only cause four and six word stack frame and require
    641  * no post-trap stack adjustment.
    642  */
    643 
    644 ENTRY_NOPROFILE(badtrap)
    645 	moveml	#0xC0C0,%sp@-		| save scratch regs
    646 	movw	%sp@(22),%sp@-		| push exception vector info
    647 	clrw	%sp@-
    648 	movl	%sp@(22),%sp@-		| and PC
    649 	jbsr	_C_LABEL(straytrap)	| report
    650 	addql	#8,%sp			| pop args
    651 	moveml	%sp@+,#0x0303		| restore regs
    652 	jra	_ASM_LABEL(rei)		| all done
    653 
    654 ENTRY_NOPROFILE(trap0)
    655 	clrl	%sp@-			| stack adjust count
    656 	moveml	#0xFFFF,%sp@-		| save user registers
    657 	movl	%usp,%a0		| save the user SP
    658 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    659 	movl	%d0,%sp@-		| push syscall number
    660 	jbsr	_C_LABEL(syscall)	| handle it
    661 	addql	#4,%sp			| pop syscall arg
    662 	tstl	_C_LABEL(astpending)	| AST pending?
    663 	jne	Lrei			| yes, handle it via trap
    664 	movl	%sp@(FR_SP),%a0		| grab and restore
    665 	movl	%a0,%usp		|   user SP
    666 	moveml	%sp@+,#0x7FFF		| restore most registers
    667 	addql	#8,%sp			| pop SP and stack adjust
    668 	rte
    669 
    670 /*
    671  * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD)
    672  *	cachectl(command, addr, length)
    673  * command in %d0, addr in %a1, length in %d1
    674  */
    675 ENTRY_NOPROFILE(trap12)
    676 	movl	_C_LABEL(curlwp),%a0
    677 	movl	%a0@(L_PROC),%sp@-	| push current proc pointer
    678 	movl	%d1,%sp@-		| push length
    679 	movl	%a1,%sp@-		| push addr
    680 	movl	%d0,%sp@-		| push command
    681 	jbsr	_C_LABEL(cachectl1)	| do it
    682 	lea	%sp@(16),%sp		| pop args
    683 	jra	_ASM_LABEL(rei)		| all done
    684 
    685 /*
    686  * Trace (single-step) trap.  Kernel-mode is special.
    687  * User mode traps are simply passed on to trap().
    688  */
    689 ENTRY_NOPROFILE(trace)
    690 	clrl	%sp@-			| stack adjust count
    691 	moveml	#0xFFFF,%sp@-
    692 	moveq	#T_TRACE,%d0
    693 
    694 	| Check PSW and see what happen.
    695 	|   T=0 S=0	(should not happen)
    696 	|   T=1 S=0	trace trap from user mode
    697 	|   T=0 S=1	trace trap on a trap instruction
    698 	|   T=1 S=1	trace trap from system mode (kernel breakpoint)
    699 
    700 	movw	%sp@(FR_HW),%d1		| get PSW
    701 	notw	%d1			| XXX no support for T0 on 680[234]0
    702 	andw	#PSL_TS,%d1		| from system mode (T=1, S=1)?
    703 	jeq	Lkbrkpt			| yes, kernel breakpoint
    704 	jra	_ASM_LABEL(fault)	| no, user-mode fault
    705 
    706 /*
    707  * Trap 15 is used for:
    708  *	- GDB breakpoints (in user programs)
    709  *	- KGDB breakpoints (in the kernel)
    710  *	- trace traps for SUN binaries (not fully supported yet)
    711  * User mode traps are simply passed to trap().
    712  */
    713 ENTRY_NOPROFILE(trap15)
    714 	clrl	%sp@-			| stack adjust count
    715 	moveml	#0xFFFF,%sp@-
    716 	moveq	#T_TRAP15,%d0
    717 	movw	%sp@(FR_HW),%d1		| get PSW
    718 	andw	#PSL_S,%d1		| from system mode?
    719 	jne	Lkbrkpt			| yes, kernel breakpoint
    720 	jra	_ASM_LABEL(fault)	| no, user-mode fault
    721 
    722 Lkbrkpt: | Kernel-mode breakpoint or trace trap. (%d0=trap_type)
    723 	| Save the system sp rather than the user sp.
    724 	movw	#PSL_HIGHIPL,%sr	| lock out interrupts
    725 	lea	%sp@(FR_SIZE),%a6	| Save stack pointer
    726 	movl	%a6,%sp@(FR_SP)		|  from before trap
    727 
    728 	| If were are not on tmpstk switch to it.
    729 	| (so debugger can change the stack pointer)
    730 	movl	%a6,%d1
    731 	cmpl	#_ASM_LABEL(tmpstk),%d1
    732 	jls	Lbrkpt2			| already on tmpstk
    733 	| Copy frame to the temporary stack
    734 	movl	%sp,%a0			| %a0=src
    735 	lea	_ASM_LABEL(tmpstk)-96,%a1 | %a1=dst
    736 	movl	%a1,%sp			| %sp=new frame
    737 	moveq	#FR_SIZE,%d1
    738 Lbrkpt1:
    739 	movl	%a0@+,%a1@+
    740 	subql	#4,%d1
    741 	jgt	Lbrkpt1
    742 
    743 Lbrkpt2:
    744 	| Call the trap handler for the kernel debugger.
    745 	| Do not call trap() to do it, so that we can
    746 	| set breakpoints in trap() if we want.  We know
    747 	| the trap type is either T_TRACE or T_BREAKPOINT.
    748 	| If we have both DDB and KGDB, let KGDB see it first,
    749 	| because KGDB will just return 0 if not connected.
    750 	| Save args in %d2, %a2
    751 	movl	%d0,%d2			| trap type
    752 	movl	%sp,%a2			| frame ptr
    753 #ifdef KGDB
    754 	| Let KGDB handle it (if connected)
    755 	movl	%a2,%sp@-		| push frame ptr
    756 	movl	%d2,%sp@-		| push trap type
    757 	jbsr	_C_LABEL(kgdb_trap)	| handle the trap
    758 	addql	#8,%sp			| pop args
    759 	cmpl	#0,%d0			| did kgdb handle it?
    760 	jne	Lbrkpt3			| yes, done
    761 #endif
    762 #ifdef DDB
    763 	| Let DDB handle it
    764 	movl	%a2,%sp@-		| push frame ptr
    765 	movl	%d2,%sp@-		| push trap type
    766 	jbsr	_C_LABEL(kdb_trap)	| handle the trap
    767 	addql	#8,%sp			| pop args
    768 #if 0	/* not needed on hp300 */
    769 	cmpl	#0,%d0			| did ddb handle it?
    770 	jne	Lbrkpt3			| yes, done
    771 #endif
    772 #endif
    773 	/* Sun 3 drops into PROM here. */
    774 Lbrkpt3:
    775 	| The stack pointer may have been modified, or
    776 	| data below it modified (by kgdb push call),
    777 	| so push the hardware frame at the current sp
    778 	| before restoring registers and returning.
    779 
    780 	movl	%sp@(FR_SP),%a0		| modified %sp
    781 	lea	%sp@(FR_SIZE),%a1	| end of our frame
    782 	movl	%a1@-,%a0@-		| copy 2 longs with
    783 	movl	%a1@-,%a0@-		| ... predecrement
    784 	movl	%a0,%sp@(FR_SP)		| %sp = h/w frame
    785 	moveml	%sp@+,#0x7FFF		| restore all but %sp
    786 	movl	%sp@,%sp		| ... and %sp
    787 	rte				| all done
    788 
    789 /*
    790  * Interrupt handlers.
    791  * All device interrupts are auto-vectored.  The CPU provides
    792  * the vector 0x18+level.  Note we count spurious interrupts, but
    793  * we don't do anything else with them.
    794  */
    795 
    796 /* 64-bit evcnt counter increments */
    797 #define EVCNT_COUNTER(ipl)					\
    798 	_C_LABEL(m68k_intr_evcnt) + (ipl)*SIZEOF_EVCNT + EV_COUNT
    799 #define EVCNT_INCREMENT(ipl)					\
    800 	clrl	%d0;						\
    801 	addql	#1,EVCNT_COUNTER(ipl)+4;			\
    802 	movel	EVCNT_COUNTER(ipl),%d1;				\
    803 	addxl	%d0,%d1;					\
    804 	movel	%d1,EVCNT_COUNTER(ipl)
    805 
    806 ENTRY_NOPROFILE(lev6intr)	/* level 6: clock */
    807 	addql	#1,_C_LABEL(intr_depth)	| entering interrupt
    808 	INTERRUPT_SAVEREG
    809 	CLKADDR(%a0)
    810 	movb	%a0@(CLKSR),%d0		| read clock status
    811 Lclkagain:
    812 	btst	#0,%d0			| clear timer1 int immediately to
    813 	jeq	Lnotim1			|  minimize chance of losing another
    814 	movpw	%a0@(CLKMSB1),%d1	|  due to statintr processing delay
    815 	movl	_C_LABEL(clkint),%d1	| clkcounter += clkint
    816 	addl	%d1,_C_LABEL(clkcounter)
    817 Lnotim1:
    818 	btst	#2,%d0			| timer3 interrupt?
    819 	jeq	Lnotim3			| no, skip statclock
    820 	movpw	%a0@(CLKMSB3),%d1	| clear timer3 interrupt
    821 	lea	%sp@(0),%a1		| a1 = &clockframe
    822 	movl	%d0,%sp@-		| save status
    823 	movl	%a1,%sp@-
    824 	jbsr	_C_LABEL(statintr)	| statintr(&frame)
    825 	addql	#4,%sp
    826 	movl	%sp@+,%d0		| restore pre-statintr status
    827 	CLKADDR(%a0)
    828 Lnotim3:
    829 	btst	#0,%d0			| timer1 interrupt?
    830 	jeq	Lrecheck		| no, skip hardclock
    831 	EVCNT_INCREMENT(6)
    832 	lea	%sp@(0),%a1		| a1 = &clockframe
    833 	movl	%a1,%sp@-
    834 #ifdef USELEDS
    835 	tstl	_C_LABEL(ledaddr)	| using LEDs?
    836 	jeq	Lnoleds0		| no, skip this code
    837 	movl	_ASM_LABEL(heartbeat),%d0 | get tick count
    838 	addql	#1,%d0			|  increment
    839 	movl	_C_LABEL(hz),%d1
    840 	addl	#50,%d1			| get the timing a little closer
    841 	tstb	_ASM_LABEL(beatstatus)	| time to slow down?
    842 	jeq	Lslowthrob		| yes, slow down
    843 	lsrl	#3,%d1			| no, fast throb
    844 Lslowthrob:
    845 	lsrl	#1,%d1			| slow throb
    846 	cmpl	%d0,%d1			| are we there yet?
    847 	jne	Lnoleds1		| no, nothing to do
    848 	addqb	#1,_ASM_LABEL(beatstatus) | incr beat status
    849 	cmpb	#3,_ASM_LABEL(beatstatus) | time to reset?
    850 	jle	Ltwinkle		  | no, twinkle the lights
    851 	movb	#0,_ASM_LABEL(beatstatus) | reset the status indicator
    852 Ltwinkle:
    853 	movl	#LED_PULSE,%sp@-
    854 	movl	#LED_DISK+LED_LANRCV+LED_LANXMT,%sp@-
    855 	clrl	%sp@-
    856 	jbsr	_C_LABEL(ledcontrol)	| toggle pulse, turn all others off
    857 	lea	%sp@(12),%sp
    858 	movql	#0,%d0
    859 Lnoleds1:
    860 	movl	%d0,_ASM_LABEL(heartbeat)
    861 Lnoleds0:
    862 #endif /* USELEDS */
    863 	jbsr	_C_LABEL(hardclock)	| hardclock(&frame)
    864 	addql	#4,%sp
    865 Lrecheck:
    866 	CPUINFO_INCREMENT(CI_NINTR)	| chalk up another interrupt
    867 	CLKADDR(%a0)
    868 	movb	%a0@(CLKSR),%d0		| see if anything happened
    869 	jmi	Lclkagain		|  while we were in hardclock/statintr
    870 #if NAUDIO >0
    871 	jbsr	_C_LABEL(m68k_intr_autovec) | call dispatch routine
    872 					    |  in case the audio device
    873 					    |  generated the interrupt
    874 #endif
    875 	INTERRUPT_RESTOREREG
    876 	subql	#1,_C_LABEL(intr_depth)	| exiting from interrupt
    877 	jra	_ASM_LABEL(rei)		| all done
    878 
    879 ENTRY_NOPROFILE(lev7intr)	/* level 7: parity errors, reset key */
    880 	clrl	%sp@-
    881 	moveml	#0xFFFF,%sp@-		| save registers
    882 	EVCNT_INCREMENT(7)
    883 	movl	%usp,%a0		| and save
    884 	movl	%a0,%sp@(FR_SP)		|   the user stack pointer
    885 	jbsr	_C_LABEL(nmihand)	| call handler
    886 	movl	%sp@(FR_SP),%a0		| restore
    887 	movl	%a0,%usp		|   user SP
    888 	moveml	%sp@+,#0x7FFF		| and remaining registers
    889 	addql	#8,%sp			| pop SP and stack adjust
    890 	jra	_ASM_LABEL(rei)		| all done
    891 
    892 /*
    893  * Emulation of VAX REI instruction.
    894  *
    895  * This code deals with checking for and servicing
    896  * ASTs (profiling, scheduling).
    897  * After identifying that we need an AST we drop the IPL
    898  * to allow device interrupts.
    899  *
    900  * This code is complicated by the fact that sendsig may have been called
    901  * necessitating a stack cleanup.
    902  */
    903 
    904 ASENTRY_NOPROFILE(rei)
    905 	tstl	_C_LABEL(astpending)	| AST pending?
    906 	jne	1f			| no, done
    907 	rte
    908 1:
    909 	btst	#5,%sp@			| yes, are we returning to user mode?
    910 	jeq	2f			| no, done
    911 	rte
    912 2:
    913 	movw	#PSL_LOWIPL,%sr		| lower SPL
    914 	clrl	%sp@-			| stack adjust
    915 	moveml	#0xFFFF,%sp@-		| save all registers
    916 	movl	%usp,%a1		| including
    917 	movl	%a1,%sp@(FR_SP)		|    the users SP
    918 Lrei:
    919 	clrl	%sp@-			| VA == none
    920 	clrl	%sp@-			| code == none
    921 	movl	#T_ASTFLT,%sp@-		| type == async system trap
    922 	pea	%sp@(12)		| fp == address of trap frame
    923 	jbsr	_C_LABEL(trap)		| go handle it
    924 	lea	%sp@(16),%sp		| pop value args
    925 	movl	%sp@(FR_SP),%a0		| restore user SP
    926 	movl	%a0,%usp		|   from save area
    927 	movw	%sp@(FR_ADJ),%d0	| need to adjust stack?
    928 	jne	Laststkadj		| yes, go to it
    929 	moveml	%sp@+,#0x7FFF		| no, restore most user regs
    930 	addql	#8,%sp			| toss SP and stack adjust
    931 	rte				| and do real RTE
    932 Laststkadj:
    933 	lea	%sp@(FR_HW),%a1		| pointer to HW frame
    934 	addql	#8,%a1			| source pointer
    935 	movl	%a1,%a0			| source
    936 	addw	%d0,%a0			|  + hole size = dest pointer
    937 	movl	%a1@-,%a0@-		| copy
    938 	movl	%a1@-,%a0@-		|  8 bytes
    939 	movl	%a0,%sp@(FR_SP)		| new SSP
    940 	moveml	%sp@+,#0x7FFF		| restore user registers
    941 	movl	%sp@,%sp		| and our SP
    942 	rte				| and do real RTE
    943 
    944 /*
    945  * Primitives
    946  */
    947 
    948 /*
    949  * Use common m68k process/lwp switch and context save subroutines.
    950  */
    951 #define FPCOPROC	/* XXX: Temp. reqd. */
    952 #include <m68k/m68k/switch_subr.s>
    953 
    954 
    955 #if defined(M68040)
    956 ENTRY(suline)
    957 	movl	%sp@(4),%a0		| address to write
    958 	movl	_C_LABEL(curpcb),%a1	| current pcb
    959 	movl	#Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault
    960 	movl	%sp@(8),%a1		| address of line
    961 	movl	%a1@+,%d0		| get lword
    962 	movsl	%d0,%a0@+		| put lword
    963 	nop				| sync
    964 	movl	%a1@+,%d0		| get lword
    965 	movsl	%d0,%a0@+		| put lword
    966 	nop				| sync
    967 	movl	%a1@+,%d0		| get lword
    968 	movsl	%d0,%a0@+		| put lword
    969 	nop				| sync
    970 	movl	%a1@+,%d0		| get lword
    971 	movsl	%d0,%a0@+		| put lword
    972 	nop				| sync
    973 	moveq	#0,%d0			| indicate no fault
    974 	jra	Lsldone
    975 Lslerr:
    976 	moveq	#-1,%d0
    977 Lsldone:
    978 	movl	_C_LABEL(curpcb),%a1	| current pcb
    979 	clrl	%a1@(PCB_ONFAULT)	| clear fault address
    980 	rts
    981 #endif
    982 
    983 ENTRY(ecacheon)
    984 	tstl	_C_LABEL(ectype)
    985 	jeq	Lnocache7
    986 	MMUADDR(%a0)
    987 	orl	#MMU_CEN,%a0@(MMUCMD)
    988 Lnocache7:
    989 	rts
    990 
    991 ENTRY(ecacheoff)
    992 	tstl	_C_LABEL(ectype)
    993 	jeq	Lnocache8
    994 	MMUADDR(%a0)
    995 	andl	#~MMU_CEN,%a0@(MMUCMD)
    996 Lnocache8:
    997 	rts
    998 
    999 /*
   1000  * _delay(u_int N)
   1001  *
   1002  * Delay for at least (N/256) microseconds.
   1003  * This routine depends on the variable:  delay_divisor
   1004  * which should be set based on the CPU clock rate.
   1005  */
   1006 ENTRY_NOPROFILE(_delay)
   1007 	| %d0 = arg = (usecs << 8)
   1008 	movl	%sp@(4),%d0
   1009 	| %d1 = delay_divisor
   1010 	movl	_C_LABEL(delay_divisor),%d1
   1011 	jra	L_delay			/* Jump into the loop! */
   1012 
   1013 	/*
   1014 	 * Align the branch target of the loop to a half-line (8-byte)
   1015 	 * boundary to minimize cache effects.  This guarantees both
   1016 	 * that there will be no prefetch stalls due to cache line burst
   1017 	 * operations and that the loop will run from a single cache
   1018 	 * half-line.
   1019 	 */
   1020 	.align	8
   1021 L_delay:
   1022 	subl	%d1,%d0
   1023 	jgt	L_delay
   1024 	rts
   1025 
   1026 /*
   1027  * Probe a memory address, and see if it causes a bus error.
   1028  * This function is only to be used in physical mode, and before our
   1029  * trap vectors are initialized.
   1030  * Invoke with address to probe in %a0.
   1031  * Alters: %a3 %d0
   1032  */
   1033 #define BUSERR  0xfffffffc
   1034 ASLOCAL(phys_badaddr)
   1035 	ASRELOC(_bsave,%a3)
   1036 	movl	BUSERR,%a3@		| save ROM bus error handler
   1037 	ASRELOC(_ssave,%a3)
   1038 	movl	%sp,%a3@		| and current stack pointer
   1039 	ASRELOC(catchbad,%a3)
   1040 	movl	%a3,BUSERR		| plug in our handler
   1041 	movb	%a0@,%d0		| access address
   1042 	ASRELOC(_bsave,%a3)		| no fault!
   1043 	movl	%a3@,BUSERR
   1044 	clrl	%d0			| return success
   1045 	rts
   1046 ASLOCAL(catchbad)
   1047 	ASRELOC(_bsave,%a3)		| got a bus error, so restore handler
   1048 	movl	%a3@,BUSERR
   1049 	ASRELOC(_ssave,%a3)
   1050 	movl	%a3@,%sp		| and stack
   1051 	moveq	#1,%d0			| return fault
   1052 	rts
   1053 #undef	BUSERR
   1054 
   1055 	.data
   1056 ASLOCAL(_bsave)
   1057 	.long   0
   1058 ASLOCAL(_ssave)
   1059 	.long   0
   1060 	.text
   1061 
   1062 /*
   1063  * Handle the nitty-gritty of rebooting the machine.
   1064  * Basically we just turn off the MMU and jump to the appropriate ROM routine.
   1065  * Note that we must be running in an address range that is mapped one-to-one
   1066  * logical to physical so that the PC is still valid immediately after the MMU
   1067  * is turned off.  We have conveniently mapped the last page of physical
   1068  * memory this way.
   1069  */
   1070 ENTRY_NOPROFILE(doboot)
   1071 #if defined(M68040)
   1072 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
   1073 	jeq	Lnocache5		| yes, skip
   1074 #endif
   1075 	movl	#CACHE_OFF,%d0
   1076 	movc	%d0,%cacr		| disable on-chip cache(s)
   1077 	tstl	_C_LABEL(ectype)	| external cache?
   1078 	jeq	Lnocache5		| no, skip
   1079 	MMUADDR(%a0)
   1080 	andl	#~MMU_CEN,%a0@(MMUCMD)	| disable external cache
   1081 Lnocache5:
   1082 	lea	MAXADDR,%a0		| last page of physical memory
   1083 	movl	_C_LABEL(boothowto),%a0@+ | store howto
   1084 	movl	_C_LABEL(bootdev),%a0@+	| and devtype
   1085 	lea	Lbootcode,%a1		| start of boot code
   1086 	lea	Lebootcode,%a3		| end of boot code
   1087 Lbootcopy:
   1088 	movw	%a1@+,%a0@+		| copy a word
   1089 	cmpl	%a3,%a1			| done yet?
   1090 	jcs	Lbootcopy		| no, keep going
   1091 #if defined(M68040)
   1092 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
   1093 	jne	LmotommuE		| no, skip
   1094 	.word	0xf4f8			| cpusha bc
   1095 LmotommuE:
   1096 #endif
   1097 	jmp	MAXADDR+8		| jump to last page
   1098 
   1099 Lbootcode:
   1100 	lea	MAXADDR+0x800,%sp	| physical SP in case of NMI
   1101 #if defined(M68040)
   1102 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
   1103 	jne	LmotommuF		| no, skip
   1104 	movl	#0,%d0
   1105 	movc	%d0,%cacr		| caches off
   1106 	.long	0x4e7b0003		| movc %d0,%tc
   1107 	movl	%d2,MAXADDR+PAGE_SIZE-4	| restore old high page contents
   1108 	DOREBOOT
   1109 LmotommuF:
   1110 #endif
   1111 #if defined(M68K_MMU_MOTOROLA)
   1112 	tstl	_C_LABEL(mmutype)	| HP MMU?
   1113 	jeq	LhpmmuB			| yes, skip
   1114 	movl	#0,%a0@			| value for pmove to TC (turn off MMU)
   1115 	pmove	%a0@,%tc		| disable MMU
   1116 	DOREBOOT
   1117 LhpmmuB:
   1118 #endif
   1119 #if defined(M68K_MMU_HP)
   1120 	MMUADDR(%a0)
   1121 	movl	#0xFFFF0000,%a0@(MMUCMD)	| totally disable MMU
   1122 	movl	%d2,MAXADDR+PAGE_SIZE-4	| restore old high page contents
   1123 	DOREBOOT
   1124 #endif
   1125 Lebootcode:
   1126 
   1127 /*
   1128  * Misc. global variables.
   1129  */
   1130 	.data
   1131 GLOBAL(machineid)
   1132 	.long	HP_320			| default to 320
   1133 
   1134 GLOBAL(mmuid)
   1135 	.long	0			| default to nothing
   1136 
   1137 GLOBAL(mmutype)
   1138 	.long	MMU_HP			| default to HP MMU
   1139 
   1140 GLOBAL(cputype)
   1141 	.long	CPU_68020		| default to 68020 CPU
   1142 
   1143 GLOBAL(ectype)
   1144 	.long	EC_NONE			| external cache type, default to none
   1145 
   1146 GLOBAL(fputype)
   1147 	.long	FPU_68882		| default to 68882 FPU
   1148 
   1149 GLOBAL(prototc)
   1150 	.long	0			| prototype translation control
   1151 
   1152 GLOBAL(internalhpib)
   1153 	.long	1			| has internal HP-IB, default to yes
   1154 
   1155 GLOBAL(intiobase)
   1156 	.long	0			| KVA of base of internal IO space
   1157 
   1158 GLOBAL(intiolimit)
   1159 	.long	0			| KVA of end of internal IO space
   1160 
   1161 GLOBAL(extiobase)
   1162 	.long	0			| KVA of base of external IO space
   1163 
   1164 GLOBAL(CLKbase)
   1165 	.long	0			| KVA of base of clock registers
   1166 
   1167 GLOBAL(MMUbase)
   1168 	.long	0			| KVA of base of HP MMU registers
   1169 
   1170 #ifdef USELEDS
   1171 ASLOCAL(heartbeat)
   1172 	.long	0			| clock ticks since last heartbeat
   1173 
   1174 ASLOCAL(beatstatus)
   1175 	.long	0			| for determining a fast or slow throb
   1176 #endif
   1177 
   1178 #ifdef DEBUG
   1179 ASGLOBAL(fulltflush)
   1180 	.long	0
   1181 
   1182 ASGLOBAL(fullcflush)
   1183 	.long	0
   1184 #endif
   1185