Home | History | Annotate | Line # | Download | only in hp300
locore.s revision 1.166
      1 /*	$NetBSD: locore.s,v 1.165 2011/12/22 15:33:29 tsutsui 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_svr4.h"
     83 #include "opt_compat_sunos.h"
     84 #include "opt_ddb.h"
     85 #include "opt_fpsp.h"
     86 #include "opt_kgdb.h"
     87 #include "opt_lockdebug.h"
     88 #include "opt_fpu_emulate.h"
     89 #include "opt_m68k_arch.h"
     90 
     91 #include "assym.h"
     92 #include <machine/asm.h>
     93 #include <machine/trap.h>
     94 
     95 #include "opt_useleds.h"
     96 #ifdef USELEDS
     97 #include <hp300/hp300/leds.h>
     98 #endif
     99 
    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 #include <hp300/hp300/vectors.s>
    132 
    133 /*
    134  * Macro to relocate a symbol, used before MMU is enabled.
    135  */
    136 #ifdef __STDC__
    137 #define	IMMEDIATE		#
    138 #define	_RELOC(var, ar)			\
    139 	movel	IMMEDIATE var,ar;	\
    140 	addl	%a5,ar
    141 #else
    142 #define	_RELOC(var, ar)			\
    143 	movel	#var,ar;		\
    144 	addl	%a5,ar
    145 #endif /* __STDC__ */
    146 
    147 #define	RELOC(var, ar)		_RELOC(_C_LABEL(var), ar)
    148 #define	ASRELOC(var, ar)	_RELOC(_ASM_LABEL(var), ar)
    149 
    150 /*
    151  * Final bits of grunt work required to reboot the system.  The MMU
    152  * must be disabled when this is invoked.
    153  */
    154 #define DOREBOOT						\
    155 	/* Reset Vector Base Register to what PROM expects. */  \
    156 	movl	#0,%d0;						\
    157 	movc	%d0,%vbr;					\
    158 	/* Jump to REQ_REBOOT */				\
    159 	jmp	0x1A4;
    160 
    161 /*
    162  * Initialization
    163  *
    164  * A4 contains the address of the end of the symtab
    165  * A5 contains physical load point from boot
    166  * VBR contains zero from ROM.  Exceptions will continue to vector
    167  * through ROM until MMU is turned on at which time they will vector
    168  * through our table (vectors.s).
    169  */
    170 
    171 BSS(lowram,4)
    172 BSS(esym,4)
    173 
    174 ASENTRY_NOPROFILE(start)
    175 	movw	#PSL_HIGHIPL,%sr	| no interrupts
    176 	ASRELOC(tmpstk, %a0)
    177 	movl	%a0,%sp			| give ourselves a temporary stack
    178 	RELOC(esym, %a0)
    179 #if 1
    180 	movl	%a4,%a0@		| store end of symbol table
    181 #else
    182 	clrl	%a0@			| no symbol table, yet
    183 #endif
    184 	RELOC(lowram, %a0)
    185 	movl	%a5,%a0@		| store start of physical memory
    186 	movl	#CACHE_OFF,%d0
    187 	movc	%d0,%cacr		| clear and disable on-chip cache(s)
    188 
    189 /* check for internal HP-IB in SYSFLAG */
    190 	btst	#5,0xfffffed2		| internal HP-IB?
    191 	jeq	Lhaveihpib		| yes, have HP-IB just continue
    192 	RELOC(internalhpib, %a0)
    193 	movl	#0,%a0@			| no, clear associated address
    194 Lhaveihpib:
    195 
    196 	RELOC(boothowto, %a0)		| save reboot flags
    197 	movl	%d7,%a0@
    198 	RELOC(bootdev, %a0)		|   and boot device
    199 	movl	%d6,%a0@
    200 
    201 	/*
    202 	 * All data registers are now free.  All address registers
    203 	 * except %a5 are free.  %a5 is used by the RELOC() macro,
    204 	 * and cannot be used until after the MMU is enabled.
    205 	 */
    206 
    207 /* determine our CPU/MMU combo - check for all regardless of kernel config */
    208 	movl	#INTIOBASE+MMUBASE,%a1
    209 	movl	#DC_FREEZE,%d0		| data freeze bit
    210 	movc	%d0,%cacr		|   only exists on 68030
    211 	movc	%cacr,%d0		| read it back
    212 	tstl	%d0			| zero?
    213 	jeq	Lnot68030		| yes, we have 68020/68040
    214 
    215 	/*
    216 	 * 68030 models
    217 	 */
    218 
    219 	RELOC(mmutype, %a0)		| no, we have 68030
    220 	movl	#MMU_68030,%a0@		| set to reflect 68030 PMMU
    221 	RELOC(cputype, %a0)
    222 	movl	#CPU_68030,%a0@		| and 68030 CPU
    223 	RELOC(machineid, %a0)
    224 	movl	#0x80,%a1@(MMUCMD)	| set magic cookie
    225 	movl	%a1@(MMUCMD),%d0	| read it back
    226 	btst	#7,%d0			| cookie still on?
    227 	jeq	Lnot370			| no, 360, 362 or 375
    228 	movl	#0,%a1@(MMUCMD)		| clear magic cookie
    229 	movl	%a1@(MMUCMD),%d0	| read it back
    230 	btst	#7,%d0			| still on?
    231 	jeq	Lisa370			| no, must be a 370
    232 	movl	#HP_340,%a0@		| yes, must be a 340
    233 	jra	Lstart1
    234 Lnot370:
    235 	movl	#HP_360,%a0@		| type is at least a 360
    236 	movl	#0,%a1@(MMUCMD)		| clear magic cookie2
    237 	movl	%a1@(MMUCMD),%d0	| read it back
    238 	btst	#16,%d0			| still on?
    239 	jeq	Lisa36x			| no, must be a 360 or a 362
    240 	RELOC(mmuid, %a0)		| save MMU ID
    241 	lsrl	#MMUID_SHIFT,%d0
    242 	andl	#MMUID_MASK,%d0
    243 	movl	%d0,%a0@
    244 	RELOC(machineid, %a0)
    245 	cmpb	#MMUID_345,%d0		| are we a 345?
    246 	beq	Lisa345
    247 	cmpb	#MMUID_375,%d0		| how about a 375?
    248 	beq	Lisa375
    249 	movl	#HP_400,%a0@		| must be a 400
    250 	jra	Lhaspac
    251 Lisa36x:
    252 	/*
    253 	 * If we found a 360, we need to check for a 362 (neither the 360
    254 	 * nor the 362 have a nonzero mmuid). Identify 362 by checking
    255 	 * on-board VRX framebuffer which has secid 0x11 at dio scode 132.
    256 	 */
    257 	movl	#DIOII_BASE,%a0		| probe dio scode 132
    258 	ASRELOC(phys_badaddr,%a3)
    259 	jbsr	%a3@
    260 	tstl	%d0			| device at scode 132?
    261 	jne	Lstart1			| no, not 362, assume 360
    262 	movb	%a0@(DIO_IDOFF),%d0
    263 	cmpb	#DIO_DEVICE_ID_FRAMEBUFFER,%d0	| framebuffer?
    264 	jne	Lstart1			| no, not 362, assume 360
    265 	movb	%a0@(DIO_SECIDOFF),%d0
    266 	cmpb	#0x11,%d0		| VRX sti on 362?
    267 	jne	Lstart1			| no, not 362, assume 360
    268 	RELOC(machineid,%a0)
    269 	movl	#HP_362,%a0@
    270 	jra	Lstart1
    271 Lisa345:
    272 	movl	#HP_345,%a0@
    273 	jra	Lhaspac
    274 Lisa375:
    275 	movl	#HP_375,%a0@
    276 	jra	Lhaspac
    277 Lisa370:
    278 	movl	#HP_370,%a0@		| set to 370
    279 Lhaspac:
    280 	RELOC(ectype, %a0)
    281 	movl	#EC_PHYS,%a0@		| also has a physical address cache
    282 	jra	Lstart1
    283 
    284 	/*
    285 	 * End of 68030 section
    286 	 */
    287 
    288 Lnot68030:
    289 	bset	#31,%d0			| data cache enable bit
    290 	movc	%d0,%cacr		|   only exists on 68040
    291 	movc	%cacr,%d0		| read it back
    292 	tstl	%d0			| zero?
    293 	beq	Lis68020		| yes, we have 68020
    294 	moveq	#0,%d0			| now turn it back off
    295 	movec	%d0,%cacr		|   before we access any data
    296 
    297 	/*
    298 	 * 68040 models
    299 	 */
    300 
    301 	RELOC(mmutype, %a0)
    302 	movl	#MMU_68040,%a0@		| with a 68040 MMU
    303 	RELOC(cputype, %a0)
    304 	movl	#CPU_68040,%a0@		| and a 68040 CPU
    305 	RELOC(fputype, %a0)
    306 	movl	#FPU_68040,%a0@		| ...and FPU
    307 	RELOC(ectype, %a0)
    308 	movl	#EC_NONE,%a0@		| and no cache (for now XXX)
    309 	RELOC(mmuid,%a0)		| save MMU ID
    310 	movl	%a1@(MMUCMD),%d0
    311 	lsrl	#MMUID_SHIFT,%d0
    312 	andl	#MMUID_MASK,%d0
    313 	movl	%d0,%a0@
    314 	RELOC(machineid, %a0)
    315 	cmpb	#MMUID_425_T,%d0	| are we a 425t?
    316 	jeq	Lisa425
    317 	cmpb	#MMUID_425_S,%d0	| how about 425s?
    318 	jeq	Lisa425
    319 	cmpb	#MMUID_425_E,%d0	| or maybe a 425e?
    320 	jeq	Lisa425
    321 	cmpb	#MMUID_433_T,%d0	| or a 433t?
    322 	jeq	Lisa433
    323 	cmpb	#MMUID_433_S,%d0	| or a 433s?
    324 	jeq	Lisa433
    325 	cmpb	#MMUID_385,%d0		| or a 385?
    326 	jeq	Lisa385
    327 	cmpb	#MMUID_382,%d0		| or a 382?
    328 	jeq	Lisa382
    329 	movl	#HP_380,%a0@		| guess we're a 380
    330 	jra	Lstart1
    331 Lisa425:
    332 	movl	#HP_425,%a0@
    333 	jra	Lstart1
    334 Lisa433:
    335 	movl	#HP_433,%a0@
    336 	jra	Lstart1
    337 Lisa385:
    338 	movl	#HP_385,%a0@
    339 	jra	Lstart1
    340 Lisa382:
    341 	movl	#HP_382,%a0@
    342 	jra	Lstart1
    343 
    344 	/*
    345 	 * End of 68040 section
    346 	 */
    347 
    348 	/*
    349 	 * 68020 models
    350 	 */
    351 
    352 Lis68020:
    353 	RELOC(fputype, %a0)		| all of the 68020 systems
    354 	movl	#FPU_68881,%a0@		|   have a 68881 FPU
    355 	movl	#1,%a1@(MMUCMD)		| a 68020, write HP MMU location
    356 	movl	%a1@(MMUCMD),%d0	| read it back
    357 	btst	#0,%d0			| non-zero?
    358 	jne	Lishpmmu		| yes, we have HP MMU
    359 	RELOC(mmutype, %a0)
    360 	movl	#MMU_68851,%a0@		| no, we have PMMU
    361 	RELOC(machineid, %a0)
    362 	movl	#HP_330,%a0@		| and 330 CPU
    363 	jra	Lstart1
    364 Lishpmmu:
    365 	RELOC(ectype, %a0)		| 320 or 350
    366 	movl	#EC_VIRT,%a0@		| both have a virtual address cache
    367 	movl	#0x80,%a1@(MMUCMD)	| set magic cookie
    368 	movl	%a1@(MMUCMD),%d0	| read it back
    369 	btst	#7,%d0			| cookie still on?
    370 	jeq	Lis320			| no, just a 320
    371 	RELOC(machineid, %a0)
    372 	movl	#HP_350,%a0@		| yes, a 350
    373 	jra	Lstart1
    374 Lis320:
    375 	RELOC(machineid, %a0)
    376 	movl	#HP_320,%a0@
    377 
    378 	/*
    379 	 * End of 68020 section
    380 	 */
    381 
    382 Lstart1:
    383 	/*
    384 	 * Now that we know what CPU we have, initialize the address error
    385 	 * and bus error handlers in the vector table:
    386 	 *
    387 	 *	vectab+8	bus error
    388 	 *	vectab+12	address error
    389 	 */
    390 	RELOC(cputype, %a0)
    391 #if 0
    392 	/* XXX assembler/linker feature/bug */
    393 	RELOC(vectab, %a2)
    394 #else
    395 	movl	#_C_LABEL(vectab),%a2
    396 	addl	%a5,%a2
    397 #endif
    398 #if defined(M68040)
    399 	cmpl	#CPU_68040,%a0@		| 68040?
    400 	jne	1f			| no, skip
    401 	movl	#_C_LABEL(buserr40),%a2@(8)
    402 	movl	#_C_LABEL(addrerr4060),%a2@(12)
    403 	jra	Lstart2
    404 1:
    405 #endif
    406 #if defined(M68020) || defined(M68030)
    407 	cmpl	#CPU_68040,%a0@		| 68040?
    408 	jeq	1f			| yes, skip
    409 	movl	#_C_LABEL(busaddrerr2030),%a2@(8)
    410 	movl	#_C_LABEL(busaddrerr2030),%a2@(12)
    411 	jra	Lstart2
    412 1:
    413 #endif
    414 	/* Config botch; no hope. */
    415 	DOREBOOT
    416 
    417 Lstart2:
    418 	movl	#0,%a1@(MMUCMD)		| clear out MMU again
    419 /* initialize source/destination control registers for movs */
    420 	moveq	#FC_USERD,%d0		| user space
    421 	movc	%d0,%sfc		|   as source
    422 	movc	%d0,%dfc		|   and destination of transfers
    423 /* save the first PA as bootinfo_pa to map it to a virtual address later. */
    424 	movl	%a5,%d0			| lowram value from ROM via boot
    425 	RELOC(bootinfo_pa, %a0)
    426 	movl	%d0,%a0@		| save the lowram as bootinfo PA
    427 /* initialize memory sizes (for pmap_bootstrap) */
    428 	movl	#MAXADDR,%d1		| last page
    429 	moveq	#PGSHIFT,%d2
    430 	lsrl	%d2,%d1			| convert to page (click) number
    431 	RELOC(maxmem, %a0)
    432 	movl	%d1,%a0@		| save as maxmem
    433 	lsrl	%d2,%d0			| convert the lowram to page number
    434 	subl	%d0,%d1			| compute amount of RAM present
    435 	RELOC(physmem, %a0)
    436 	movl	%d1,%a0@		| and physmem
    437 
    438 /* configure kernel and lwp0 VA space so we can get going */
    439 #if NKSYMS || defined(DDB) || defined(LKM)
    440 	RELOC(esym,%a0)			| end of static kernel test/data/syms
    441 	movl	%a0@,%d5
    442 	jne	Lstart3
    443 #endif
    444 	movl	#_C_LABEL(end),%d5	| end of static kernel text/data
    445 Lstart3:
    446 	addl	#PAGE_SIZE-1,%d5
    447 	andl	#PG_FRAME,%d5		| round to a page
    448 	movl	%d5,%a4
    449 	addl	%a5,%a4			| convert to PA
    450 	pea	%a5@			| firstpa
    451 	pea	%a4@			| nextpa
    452 	RELOC(pmap_bootstrap,%a0)
    453 	jbsr	%a0@			| pmap_bootstrap(firstpa, nextpa)
    454 	addql	#8,%sp
    455 
    456 /*
    457  * Prepare to enable MMU.
    458  * Since the kernel is not mapped logical == physical we must insure
    459  * that when the MMU is turned on, all prefetched addresses (including
    460  * the PC) are valid.  In order guarantee that, we use the last physical
    461  * page (which is conveniently mapped == VA) and load it up with enough
    462  * code to defeat the prefetch, then we execute the jump back to here.
    463  *
    464  * Is this all really necessary, or am I paranoid??
    465  */
    466 	RELOC(Sysseg_pa, %a0)		| system segment table addr
    467 	movl	%a0@,%d1		| read value (a PA)
    468 	RELOC(mmutype, %a0)
    469 	tstl	%a0@			| HP MMU?
    470 	jeq	Lhpmmu2			| yes, skip
    471 	cmpl	#MMU_68040,%a0@		| 68040?
    472 	jne	Lmotommu1		| no, skip
    473 	.long	0x4e7b1807		| movc %d1,%srp
    474 	jra	Lstploaddone
    475 Lmotommu1:
    476 	RELOC(protorp, %a0)
    477 	movl	#0x80000202,%a0@	| nolimit + share global + 4 byte PTEs
    478 	movl	%d1,%a0@(4)		| + segtable address
    479 	pmove	%a0@,%srp		| load the supervisor root pointer
    480 	movl	#0x80000002,%a0@	| reinit upper half for CRP loads
    481 	jra	Lstploaddone		| done
    482 Lhpmmu2:
    483 	moveq	#PGSHIFT,%d2
    484 	lsrl	%d2,%d1			| convert to page frame
    485 	movl	%d1,INTIOBASE+MMUBASE+MMUSSTP | load in sysseg table register
    486 Lstploaddone:
    487 	lea	MAXADDR,%a2		| PA of last RAM page
    488 #if 0
    489 	ASRELOC(Lhighcode, %a1)		| addr of high code
    490 	ASRELOC(Lehighcode, %a3)	| end addr
    491 #else
    492 	/* don't want pc-relative addressing */
    493 	.word	0x43f9			| lea Lhighcode, %a1
    494 	.long	Lhighcode
    495 	addl	%a5, %a1
    496 	.word	0x47f9			| lea Lehighcode, %a3
    497 	.long	Lehighcode
    498 	addl	%a5, %a3
    499 #endif
    500 Lcodecopy:
    501 	movw	%a1@+,%a2@+		| copy a word
    502 	cmpl	%a3,%a1			| done yet?
    503 	jcs	Lcodecopy		| no, keep going
    504 	jmp	MAXADDR			| go for it!
    505 
    506 	/*
    507 	 * BEGIN MMU TRAMPOLINE.  This section of code is not
    508 	 * executed in-place.  It's copied to the last page
    509 	 * of RAM (mapped va == pa) and executed there.
    510 	 */
    511 
    512 Lhighcode:
    513 	/*
    514 	 * Set up the vector table, and race to get the MMU
    515 	 * enabled.
    516 	 */
    517 	movl	#_C_LABEL(vectab),%d0	| set Vector Base Register
    518 	movc	%d0,%vbr
    519 
    520 	RELOC(mmutype, %a0)
    521 	tstl	%a0@			| HP MMU?
    522 	jeq	Lhpmmu3			| yes, skip
    523 	cmpl	#MMU_68040,%a0@		| 68040?
    524 	jne	Lmotommu2		| no, skip
    525 	movw	#0,INTIOBASE+MMUBASE+MMUCMD+2
    526 	movw	#MMU_IEN+MMU_CEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD+2
    527 					| enable FPU and caches
    528 	moveq	#0,%d0			| ensure TT regs are disabled
    529 	.long	0x4e7b0004		| movc %d0,%itt0
    530 	.long	0x4e7b0005		| movc %d0,%itt1
    531 	.long	0x4e7b0006		| movc %d0,%dtt0
    532 	.long	0x4e7b0007		| movc %d0,%dtt1
    533 	.word	0xf4d8			| cinva bc
    534 	.word	0xf518			| pflusha
    535 #if PGSHIFT == 13
    536 	movl	#0xc000,%d0
    537 #else
    538 	movl	#0x8000,%d0
    539 #endif
    540 	.long	0x4e7b0003		| movc %d0,%tc
    541 	movl	#CACHE40_ON,%d0
    542 	movc	%d0,%cacr		| turn on both caches
    543 	jmp	Lenab1:l		| forced not be pc-relative
    544 Lmotommu2:
    545 	movl	#MMU_IEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD
    546 					| enable 68881 and i-cache
    547 	pflusha
    548 	RELOC(prototc, %a2)
    549 #if PGSHIFT == 13
    550 	movl	#0x82d08b00,%a2@	| value to load TC with
    551 #else
    552 	movl	#0x82c0aa00,%a2@	| value to load TC with
    553 #endif
    554 	pmove	%a2@,%tc		| load it
    555 	jmp	Lenab1:l		| forced not be pc-relative
    556 Lhpmmu3:
    557 	movl	#0,INTIOBASE+MMUBASE+MMUCMD		| clear external cache
    558 	movl	#MMU_ENAB,INTIOBASE+MMUBASE+MMUCMD	| turn on MMU
    559 	jmp	Lenab1:l		| forced not be pc-relative
    560 Lehighcode:
    561 
    562 	/*
    563 	 * END MMU TRAMPOLINE.  Address register %a5 is now free.
    564 	 */
    565 
    566 /*
    567  * Should be running mapped from this point on
    568  */
    569 Lenab1:
    570 	lea	_ASM_LABEL(tmpstk),%sp	| temporary stack
    571 /* call final pmap setup */
    572 	jbsr	_C_LABEL(pmap_bootstrap_finalize)
    573 /* set kernel stack, user SP */
    574 	movl	_C_LABEL(lwp0uarea),%a1	| get lwp0 uarea
    575 	lea	%a1@(USPACE-4),%sp	| set kernel stack to end of area
    576 	movl	#USRSTACK-4,%a2
    577 	movl	%a2,%usp		| init user SP
    578 
    579 	jbsr	_C_LABEL(fpu_probe)
    580 	movl	%d0,_C_LABEL(fputype)
    581 	tstl	_C_LABEL(fputype)	| Have an FPU?
    582 	jeq	Lenab2			| No, skip.
    583 	clrl	%a1@(PCB_FPCTX)		| ensure null FP context
    584 	movl	%a1,%sp@-
    585 	jbsr	_C_LABEL(m68881_restore) | restore it (does not kill %a1)
    586 	addql	#4,%sp
    587 Lenab2:
    588 /* flush TLB and turn on caches */
    589 	jbsr	_C_LABEL(_TBIA)		| invalidate TLB
    590 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
    591 	jeq	Lnocache0		| yes, cache already on
    592 	movl	#CACHE_ON,%d0
    593 	movc	%d0,%cacr		| clear cache(s)
    594 	tstl	_C_LABEL(ectype)
    595 	jeq	Lnocache0
    596 	MMUADDR(%a0)
    597 	orl	#MMU_CEN,%a0@(MMUCMD)	| turn on external cache
    598 Lnocache0:
    599 /* Final setup for call to main(). */
    600 	jbsr	_C_LABEL(hp300_init)
    601 
    602 /*
    603  * Create a fake exception frame so that cpu_lwp_fork() can copy it.
    604  * main() nevers returns; we exit to user mode from a forked process
    605  * later on.
    606  */
    607 	clrw	%sp@-			| vector offset/frame type
    608 	clrl	%sp@-			| PC - filled in by "execve"
    609 	movw	#PSL_USER,%sp@-		| in user mode
    610 	clrl	%sp@-			| stack adjust count and padding
    611 	lea	%sp@(-64),%sp		| construct space for D0-D7/A0-A7
    612 	lea	_C_LABEL(lwp0),%a0	| save pointer to frame
    613 	movl	%sp,%a0@(L_MD_REGS)	|   in lwp0.l_md.md_regs
    614 
    615 	jra	_C_LABEL(main)		| main()
    616 	PANIC("main() returned")
    617 	/* NOTREACHED */
    618 
    619 /*
    620  * Trap/interrupt vector routines
    621  */
    622 #include <m68k/m68k/trap_subr.s>
    623 
    624 	.data
    625 GLOBAL(m68k_fault_addr)
    626 	.long	0
    627 
    628 #if defined(M68040) || defined(M68060)
    629 ENTRY_NOPROFILE(addrerr4060)
    630 	clrl	%sp@-			| stack adjust count
    631 	moveml	#0xFFFF,%sp@-		| save user registers
    632 	movl	%usp,%a0		| save the user SP
    633 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    634 	movl	%sp@(FR_HW+8),%sp@-
    635 	clrl	%sp@-			| dummy code
    636 	movl	#T_ADDRERR,%sp@-	| mark address error
    637 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    638 #endif
    639 
    640 #if defined(M68060)
    641 ENTRY_NOPROFILE(buserr60)
    642 	clrl	%sp@-			| stack adjust count
    643 	moveml	#0xFFFF,%sp@-		| save user registers
    644 	movl	%usp,%a0		| save the user SP
    645 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    646 	movel	%sp@(FR_HW+12),%d0	| FSLW
    647 	btst	#2,%d0			| branch prediction error?
    648 	jeq	Lnobpe
    649 	movc	%cacr,%d2
    650 	orl	#IC60_CABC,%d2		| clear all branch cache entries
    651 	movc	%d2,%cacr
    652 	movl	%d0,%d1
    653 	addql	#1,L60bpe
    654 	andl	#0x7ffd,%d1
    655 	jeq	_ASM_LABEL(faultstkadjnotrap2)
    656 Lnobpe:
    657 | we need to adjust for misaligned addresses
    658 	movl	%sp@(FR_HW+8),%d1	| grab VA
    659 	btst	#27,%d0			| check for mis-aligned access
    660 	jeq	Lberr3			| no, skip
    661 	addl	#28,%d1			| yes, get into next page
    662 					| operand case: 3,
    663 					| instruction case: 4+12+12
    664 	andl	#PG_FRAME,%d1           | and truncate
    665 Lberr3:
    666 	movl	%d1,%sp@-
    667 	movl	%d0,%sp@-		| code is FSLW now.
    668 	andw	#0x1f80,%d0
    669 	jeq	Lberr60			| it is a bus error
    670 	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
    671 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    672 Lberr60:
    673 	tstl	_C_LABEL(nofault)	| catch bus error?
    674 	jeq	Lisberr			| no, handle as usual
    675 	movl	%sp@(FR_HW+8+8),_C_LABEL(m68k_fault_addr) | save fault addr
    676 	movl	_C_LABEL(nofault),%sp@-	| yes,
    677 	jbsr	_C_LABEL(longjmp)	|  longjmp(nofault)
    678 	/* NOTREACHED */
    679 #endif
    680 #if defined(M68040)
    681 ENTRY_NOPROFILE(buserr40)
    682 	clrl	%sp@-			| stack adjust count
    683 	moveml	#0xFFFF,%sp@-		| save user registers
    684 	movl	%usp,%a0		| save the user SP
    685 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    686 	movl	%sp@(FR_HW+20),%d1	| get fault address
    687 	moveq	#0,%d0
    688 	movw	%sp@(FR_HW+12),%d0	| get SSW
    689 	btst	#11,%d0			| check for mis-aligned
    690 	jeq	Lbe1stpg		| no skip
    691 	addl	#3,%d1			| get into next page
    692 	andl	#PG_FRAME,%d1		| and truncate
    693 Lbe1stpg:
    694 	movl	%d1,%sp@-		| pass fault address.
    695 	movl	%d0,%sp@-		| pass SSW as code
    696 	btst	#10,%d0			| test ATC
    697 	jeq	Lberr40			| it is a bus error
    698 	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
    699 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    700 Lberr40:
    701 	tstl	_C_LABEL(nofault)	| catch bus error?
    702 	jeq	Lisberr			| no, handle as usual
    703 	movl	%sp@(FR_HW+8+20),_C_LABEL(m68k_fault_addr) | save fault addr
    704 	movl	_C_LABEL(nofault),%sp@-	| yes,
    705 	jbsr	_C_LABEL(longjmp)	|  longjmp(nofault)
    706 	/* NOTREACHED */
    707 #endif
    708 
    709 #if defined(M68020) || defined(M68030)
    710 ENTRY_NOPROFILE(busaddrerr2030)
    711 	clrl	%sp@-			| stack adjust count
    712 	moveml	#0xFFFF,%sp@-		| save user registers
    713 	movl	%usp,%a0		| save the user SP
    714 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    715 	moveq	#0,%d0
    716 	movw	%sp@(FR_HW+10),%d0	| grab SSW for fault processing
    717 	btst	#12,%d0			| RB set?
    718 	jeq	LbeX0			| no, test RC
    719 	bset	#14,%d0			| yes, must set FB
    720 	movw	%d0,%sp@(FR_HW+10)	| for hardware too
    721 LbeX0:
    722 	btst	#13,%d0			| RC set?
    723 	jeq	LbeX1			| no, skip
    724 	bset	#15,%d0			| yes, must set FC
    725 	movw	%d0,%sp@(FR_HW+10)	| for hardware too
    726 LbeX1:
    727 	btst	#8,%d0			| data fault?
    728 	jeq	Lbe0			| no, check for hard cases
    729 	movl	%sp@(FR_HW+16),%d1	| fault address is as given in frame
    730 	jra	Lbe10			| thats it
    731 Lbe0:
    732 	btst	#4,%sp@(FR_HW+6)	| long (type B) stack frame?
    733 	jne	Lbe4			| yes, go handle
    734 	movl	%sp@(FR_HW+2),%d1	| no, can use save PC
    735 	btst	#14,%d0			| FB set?
    736 	jeq	Lbe3			| no, try FC
    737 	addql	#4,%d1			| yes, adjust address
    738 	jra	Lbe10			| done
    739 Lbe3:
    740 	btst	#15,%d0			| FC set?
    741 	jeq	Lbe10			| no, done
    742 	addql	#2,%d1			| yes, adjust address
    743 	jra	Lbe10			| done
    744 Lbe4:
    745 	movl	%sp@(FR_HW+36),%d1	| long format, use stage B address
    746 	btst	#15,%d0			| FC set?
    747 	jeq	Lbe10			| no, all done
    748 	subql	#2,%d1			| yes, adjust address
    749 Lbe10:
    750 	movl	%d1,%sp@-		| push fault VA
    751 	movl	%d0,%sp@-		| and padded SSW
    752 	movw	%sp@(FR_HW+8+6),%d0	| get frame format/vector offset
    753 	andw	#0x0FFF,%d0		| clear out frame format
    754 	cmpw	#12,%d0			| address error vector?
    755 	jeq	Lisaerr			| yes, go to it
    756 #if defined(M68K_MMU_MOTOROLA)
    757 #if defined(M68K_MMU_HP)
    758 	tstl	_C_LABEL(mmutype)	| HP MMU?
    759 	jeq	Lbehpmmu		| yes, different MMU fault handler
    760 #endif
    761 	movl	%d1,%a0			| fault address
    762 	movl	%sp@,%d0		| function code from ssw
    763 	btst	#8,%d0			| data fault?
    764 	jne	Lbe10a
    765 	movql	#1,%d0			| user program access FC
    766 					| (we dont separate data/program)
    767 	btst	#5,%sp@(FR_HW+8)	| supervisor mode?
    768 	jeq	Lbe10a			| if no, done
    769 	movql	#5,%d0			| else supervisor program access
    770 Lbe10a:
    771 	ptestr	%d0,%a0@,#7		| do a table search
    772 	pmove	%psr,%sp@		| save result
    773 	movb	%sp@,%d1
    774 	btst	#2,%d1			| invalid (incl. limit viol. and berr)?
    775 	jeq	Lmightnotbemerr		| no -> wp check
    776 	btst	#7,%d1			| is it MMU table berr?
    777 	jne	Lisberr1		| yes, needs not be fast.
    778 #endif /* M68K_MMU_MOTOROLA */
    779 Lismerr:
    780 	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
    781 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    782 #if defined(M68K_MMU_MOTOROLA)
    783 Lmightnotbemerr:
    784 	btst	#3,%d1			| write protect bit set?
    785 	jeq	Lisberr1		| no: must be bus error
    786 	movl	%sp@,%d0		| ssw into low word of %d0
    787 	andw	#0xc0,%d0		| Write protect is set on page:
    788 	cmpw	#0x40,%d0		| was it read cycle?
    789 	jne	Lismerr			| no, was not WPE, must be MMU fault
    790 	jra	Lisberr1		| real bus err needs not be fast.
    791 #endif /* M68K_MMU_MOTOROLA */
    792 #if defined(M68K_MMU_HP)
    793 Lbehpmmu:
    794 	MMUADDR(%a0)
    795 	movl	%a0@(MMUSTAT),%d0	| read MMU status
    796 	btst	#3,%d0			| MMU fault?
    797 	jeq	Lisberr1		| no, just a non-MMU bus error
    798 	andl	#~MMU_FAULT,%a0@(MMUSTAT)| yes, clear fault bits
    799 	movw	%d0,%sp@		| pass MMU stat in upper half of code
    800 	jra	Lismerr			| and handle it
    801 #endif
    802 Lisaerr:
    803 	movl	#T_ADDRERR,%sp@-	| mark address error
    804 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    805 Lisberr1:
    806 	clrw	%sp@			| re-clear pad word
    807 	tstl	_C_LABEL(nofault)	| catch bus error?
    808 	jeq	Lisberr			| no, handle as usual
    809 	movl	%sp@(FR_HW+8+16),_C_LABEL(m68k_fault_addr) | save fault addr
    810 	movl	_C_LABEL(nofault),%sp@-	| yes,
    811 	jbsr	_C_LABEL(longjmp)	|  longjmp(nofault)
    812 	/* NOTREACHED */
    813 #endif /* M68020 || M68030 */
    814 
    815 Lisberr:				| also used by M68040/60
    816 	movl	#T_BUSERR,%sp@-		| mark bus error
    817 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    818 
    819 /*
    820  * FP exceptions.
    821  */
    822 ENTRY_NOPROFILE(fpfline)
    823 #if defined(M68040)
    824 	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
    825 	jne	Lfp_unimp		| no, skip FPSP
    826 	cmpw	#0x202c,%sp@(6)		| format type 2?
    827 	jne	_C_LABEL(illinst)	| no, not an FP emulation
    828 Ldofp_unimp:
    829 #ifdef FPSP
    830 	jmp	_ASM_LABEL(fpsp_unimp)	| yes, go handle it
    831 #endif
    832 Lfp_unimp:
    833 #endif /* M68040 */
    834 #ifdef FPU_EMULATE
    835 	clrl	%sp@-			| stack adjust count
    836 	moveml	#0xFFFF,%sp@-		| save registers
    837 	moveq	#T_FPEMULI,%d0		| denote as FP emulation trap
    838 	jra	_ASM_LABEL(fault)	| do it
    839 #else
    840 	jra	_C_LABEL(illinst)
    841 #endif
    842 
    843 ENTRY_NOPROFILE(fpunsupp)
    844 #if defined(M68040)
    845 	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
    846 	jne	_C_LABEL(illinst)	| no, treat as illinst
    847 #ifdef FPSP
    848 	jmp	_ASM_LABEL(fpsp_unsupp)	| yes, go handle it
    849 #endif
    850 Lfp_unsupp:
    851 #endif /* M68040 */
    852 #ifdef FPU_EMULATE
    853 	clrl	%sp@-			| stack adjust count
    854 	moveml	#0xFFFF,%sp@-		| save registers
    855 	moveq	#T_FPEMULD,%d0		| denote as FP emulation trap
    856 	jra	_ASM_LABEL(fault)	| do it
    857 #else
    858 	jra	_C_LABEL(illinst)
    859 #endif
    860 
    861 /*
    862  * Handles all other FP coprocessor exceptions.
    863  * Note that since some FP exceptions generate mid-instruction frames
    864  * and may cause signal delivery, we need to test for stack adjustment
    865  * after the trap call.
    866  */
    867 ENTRY_NOPROFILE(fpfault)
    868 	clrl	%sp@-			| stack adjust count
    869 	moveml	#0xFFFF,%sp@-		| save user registers
    870 	movl	%usp,%a0		| and save
    871 	movl	%a0,%sp@(FR_SP)		|   the user stack pointer
    872 	clrl	%sp@-			| no VA arg
    873 	movl	_C_LABEL(curpcb),%a0	| current pcb
    874 	lea	%a0@(PCB_FPCTX),%a0	| address of FP savearea
    875 	fsave	%a0@			| save state
    876 #if defined(M68040) || defined(M68060)
    877 	/* always null state frame on 68040, 68060 */
    878 	cmpl	#FPU_68040,_C_LABEL(fputype)
    879 	jge	Lfptnull
    880 #endif
    881 	tstb	%a0@			| null state frame?
    882 	jeq	Lfptnull		| yes, safe
    883 	clrw	%d0			| no, need to tweak BIU
    884 	movb	%a0@(1),%d0		| get frame size
    885 	bset	#3,%a0@(0,%d0:w)	| set exc_pend bit of BIU
    886 Lfptnull:
    887 	fmovem	%fpsr,%sp@-		| push %fpsr as code argument
    888 	frestore %a0@			| restore state
    889 	movl	#T_FPERR,%sp@-		| push type arg
    890 	jra	_ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup
    891 
    892 /*
    893  * Other exceptions only cause four and six word stack frame and require
    894  * no post-trap stack adjustment.
    895  */
    896 
    897 ENTRY_NOPROFILE(badtrap)
    898 	moveml	#0xC0C0,%sp@-		| save scratch regs
    899 	movw	%sp@(22),%sp@-		| push exception vector info
    900 	clrw	%sp@-
    901 	movl	%sp@(22),%sp@-		| and PC
    902 	jbsr	_C_LABEL(straytrap)	| report
    903 	addql	#8,%sp			| pop args
    904 	moveml	%sp@+,#0x0303		| restore regs
    905 	jra	_ASM_LABEL(rei)		| all done
    906 
    907 ENTRY_NOPROFILE(trap0)
    908 	clrl	%sp@-			| stack adjust count
    909 	moveml	#0xFFFF,%sp@-		| save user registers
    910 	movl	%usp,%a0		| save the user SP
    911 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    912 	movl	%d0,%sp@-		| push syscall number
    913 	jbsr	_C_LABEL(syscall)	| handle it
    914 	addql	#4,%sp			| pop syscall arg
    915 	tstl	_C_LABEL(astpending)	| AST pending?
    916 	jne	Lrei			| yes, handle it via trap
    917 	movl	%sp@(FR_SP),%a0		| grab and restore
    918 	movl	%a0,%usp		|   user SP
    919 	moveml	%sp@+,#0x7FFF		| restore most registers
    920 	addql	#8,%sp			| pop SP and stack adjust
    921 	rte
    922 
    923 /*
    924  * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD)
    925  *	cachectl(command, addr, length)
    926  * command in %d0, addr in %a1, length in %d1
    927  */
    928 ENTRY_NOPROFILE(trap12)
    929 	movl	_C_LABEL(curlwp),%a0
    930 	movl	%a0@(L_PROC),%sp@-	| push current proc pointer
    931 	movl	%d1,%sp@-		| push length
    932 	movl	%a1,%sp@-		| push addr
    933 	movl	%d0,%sp@-		| push command
    934 	jbsr	_C_LABEL(cachectl1)	| do it
    935 	lea	%sp@(16),%sp		| pop args
    936 	jra	_ASM_LABEL(rei)		| all done
    937 
    938 /*
    939  * Trace (single-step) trap.  Kernel-mode is special.
    940  * User mode traps are simply passed on to trap().
    941  */
    942 ENTRY_NOPROFILE(trace)
    943 	clrl	%sp@-			| stack adjust count
    944 	moveml	#0xFFFF,%sp@-
    945 	moveq	#T_TRACE,%d0
    946 
    947 	| Check PSW and see what happen.
    948 	|   T=0 S=0	(should not happen)
    949 	|   T=1 S=0	trace trap from user mode
    950 	|   T=0 S=1	trace trap on a trap instruction
    951 	|   T=1 S=1	trace trap from system mode (kernel breakpoint)
    952 
    953 	movw	%sp@(FR_HW),%d1		| get PSW
    954 	notw	%d1			| XXX no support for T0 on 680[234]0
    955 	andw	#PSL_TS,%d1		| from system mode (T=1, S=1)?
    956 	jeq	Lkbrkpt			| yes, kernel breakpoint
    957 	jra	_ASM_LABEL(fault)	| no, user-mode fault
    958 
    959 /*
    960  * Trap 15 is used for:
    961  *	- GDB breakpoints (in user programs)
    962  *	- KGDB breakpoints (in the kernel)
    963  *	- trace traps for SUN binaries (not fully supported yet)
    964  * User mode traps are simply passed to trap().
    965  */
    966 ENTRY_NOPROFILE(trap15)
    967 	clrl	%sp@-			| stack adjust count
    968 	moveml	#0xFFFF,%sp@-
    969 	moveq	#T_TRAP15,%d0
    970 	movw	%sp@(FR_HW),%d1		| get PSW
    971 	andw	#PSL_S,%d1		| from system mode?
    972 	jne	Lkbrkpt			| yes, kernel breakpoint
    973 	jra	_ASM_LABEL(fault)	| no, user-mode fault
    974 
    975 Lkbrkpt: | Kernel-mode breakpoint or trace trap. (%d0=trap_type)
    976 	| Save the system sp rather than the user sp.
    977 	movw	#PSL_HIGHIPL,%sr	| lock out interrupts
    978 	lea	%sp@(FR_SIZE),%a6	| Save stack pointer
    979 	movl	%a6,%sp@(FR_SP)		|  from before trap
    980 
    981 	| If were are not on tmpstk switch to it.
    982 	| (so debugger can change the stack pointer)
    983 	movl	%a6,%d1
    984 	cmpl	#_ASM_LABEL(tmpstk),%d1
    985 	jls	Lbrkpt2			| already on tmpstk
    986 	| Copy frame to the temporary stack
    987 	movl	%sp,%a0			| %a0=src
    988 	lea	_ASM_LABEL(tmpstk)-96,%a1 | %a1=dst
    989 	movl	%a1,%sp			| %sp=new frame
    990 	moveq	#FR_SIZE,%d1
    991 Lbrkpt1:
    992 	movl	%a0@+,%a1@+
    993 	subql	#4,%d1
    994 	jgt	Lbrkpt1
    995 
    996 Lbrkpt2:
    997 	| Call the trap handler for the kernel debugger.
    998 	| Do not call trap() to do it, so that we can
    999 	| set breakpoints in trap() if we want.  We know
   1000 	| the trap type is either T_TRACE or T_BREAKPOINT.
   1001 	| If we have both DDB and KGDB, let KGDB see it first,
   1002 	| because KGDB will just return 0 if not connected.
   1003 	| Save args in %d2, %a2
   1004 	movl	%d0,%d2			| trap type
   1005 	movl	%sp,%a2			| frame ptr
   1006 #ifdef KGDB
   1007 	| Let KGDB handle it (if connected)
   1008 	movl	%a2,%sp@-		| push frame ptr
   1009 	movl	%d2,%sp@-		| push trap type
   1010 	jbsr	_C_LABEL(kgdb_trap)	| handle the trap
   1011 	addql	#8,%sp			| pop args
   1012 	cmpl	#0,%d0			| did kgdb handle it?
   1013 	jne	Lbrkpt3			| yes, done
   1014 #endif
   1015 #ifdef DDB
   1016 	| Let DDB handle it
   1017 	movl	%a2,%sp@-		| push frame ptr
   1018 	movl	%d2,%sp@-		| push trap type
   1019 	jbsr	_C_LABEL(kdb_trap)	| handle the trap
   1020 	addql	#8,%sp			| pop args
   1021 #if 0	/* not needed on hp300 */
   1022 	cmpl	#0,%d0			| did ddb handle it?
   1023 	jne	Lbrkpt3			| yes, done
   1024 #endif
   1025 #endif
   1026 	/* Sun 3 drops into PROM here. */
   1027 Lbrkpt3:
   1028 	| The stack pointer may have been modified, or
   1029 	| data below it modified (by kgdb push call),
   1030 	| so push the hardware frame at the current sp
   1031 	| before restoring registers and returning.
   1032 
   1033 	movl	%sp@(FR_SP),%a0		| modified %sp
   1034 	lea	%sp@(FR_SIZE),%a1	| end of our frame
   1035 	movl	%a1@-,%a0@-		| copy 2 longs with
   1036 	movl	%a1@-,%a0@-		| ... predecrement
   1037 	movl	%a0,%sp@(FR_SP)		| %sp = h/w frame
   1038 	moveml	%sp@+,#0x7FFF		| restore all but %sp
   1039 	movl	%sp@,%sp		| ... and %sp
   1040 	rte				| all done
   1041 
   1042 /* Use common m68k sigreturn */
   1043 #include <m68k/m68k/sigreturn.s>
   1044 
   1045 /*
   1046  * Interrupt handlers.
   1047  * All device interrupts are auto-vectored.  The CPU provides
   1048  * the vector 0x18+level.  Note we count spurious interrupts, but
   1049  * we don't do anything else with them.
   1050  */
   1051 
   1052 /* 64-bit evcnt counter increments */
   1053 #define EVCNT_COUNTER(ipl)					\
   1054 	_C_LABEL(hp300_intr_list) + (ipl)*SIZEOF_HI + HI_EVCNT
   1055 #define EVCNT_INCREMENT(ipl)					\
   1056 	clrl	%d0;						\
   1057 	addql	#1,EVCNT_COUNTER(ipl)+4;			\
   1058 	movel	EVCNT_COUNTER(ipl),%d1;				\
   1059 	addxl	%d0,%d1;					\
   1060 	movel	%d1,EVCNT_COUNTER(ipl)
   1061 
   1062 ENTRY_NOPROFILE(spurintr)	/* level 0 */
   1063 	INTERRUPT_SAVEREG
   1064 	EVCNT_INCREMENT(0)
   1065 	CPUINFO_INCREMENT(CI_NINTR)
   1066 	INTERRUPT_RESTOREREG
   1067 	jra	_ASM_LABEL(rei)
   1068 
   1069 ENTRY_NOPROFILE(intrhand)	/* levels 1 through 5 */
   1070 	addql	#1,_C_LABEL(idepth)	| entering interrupt
   1071 	INTERRUPT_SAVEREG
   1072 	movw	%sp@(22),%sp@-		| push exception vector info
   1073 	clrw	%sp@-
   1074 	jbsr	_C_LABEL(intr_dispatch)	| call dispatch routine
   1075 	addql	#4,%sp
   1076 	INTERRUPT_RESTOREREG
   1077 	subql	#1,_C_LABEL(idepth)	| exiting from interrupt
   1078 	jra	_ASM_LABEL(rei)		| all done
   1079 
   1080 ENTRY_NOPROFILE(lev6intr)	/* level 6: clock */
   1081 	addql	#1,_C_LABEL(idepth)	| entering interrupt
   1082 	INTERRUPT_SAVEREG
   1083 	CLKADDR(%a0)
   1084 	movb	%a0@(CLKSR),%d0		| read clock status
   1085 Lclkagain:
   1086 	btst	#0,%d0			| clear timer1 int immediately to
   1087 	jeq	Lnotim1			|  minimize chance of losing another
   1088 	movpw	%a0@(CLKMSB1),%d1	|  due to statintr processing delay
   1089 	movl	_C_LABEL(clkint),%d1	| clkcounter += clkint
   1090 	addl	%d1,_C_LABEL(clkcounter)
   1091 Lnotim1:
   1092 	btst	#2,%d0			| timer3 interrupt?
   1093 	jeq	Lnotim3			| no, skip statclock
   1094 	movpw	%a0@(CLKMSB3),%d1	| clear timer3 interrupt
   1095 	lea	%sp@(16),%a1		| a1 = &clockframe
   1096 	movl	%d0,%sp@-		| save status
   1097 	movl	%a1,%sp@-
   1098 	jbsr	_C_LABEL(statintr)	| statintr(&frame)
   1099 	addql	#4,%sp
   1100 	movl	%sp@+,%d0		| restore pre-statintr status
   1101 	CLKADDR(%a0)
   1102 Lnotim3:
   1103 	btst	#0,%d0			| timer1 interrupt?
   1104 	jeq	Lrecheck		| no, skip hardclock
   1105 	EVCNT_INCREMENT(6)
   1106 	lea	%sp@(16),%a1		| a1 = &clockframe
   1107 	movl	%a1,%sp@-
   1108 #ifdef USELEDS
   1109 	tstl	_C_LABEL(ledaddr)	| using LEDs?
   1110 	jeq	Lnoleds0		| no, skip this code
   1111 	movl	_ASM_LABEL(heartbeat),%d0 | get tick count
   1112 	addql	#1,%d0			|  increment
   1113 	movl	_C_LABEL(hz),%d1
   1114 	addl	#50,%d1			| get the timing a little closer
   1115 	tstb	_ASM_LABEL(beatstatus)	| time to slow down?
   1116 	jeq	Lslowthrob		| yes, slow down
   1117 	lsrl	#3,%d1			| no, fast throb
   1118 Lslowthrob:
   1119 	lsrl	#1,%d1			| slow throb
   1120 	cmpl	%d0,%d1			| are we there yet?
   1121 	jne	Lnoleds1		| no, nothing to do
   1122 	addqb	#1,_ASM_LABEL(beatstatus) | incr beat status
   1123 	cmpb	#3,_ASM_LABEL(beatstatus) | time to reset?
   1124 	jle	Ltwinkle		  | no, twinkle the lights
   1125 	movb	#0,_ASM_LABEL(beatstatus) | reset the status indicator
   1126 Ltwinkle:
   1127 	movl	#LED_PULSE,%sp@-
   1128 	movl	#LED_DISK+LED_LANRCV+LED_LANXMT,%sp@-
   1129 	clrl	%sp@-
   1130 	jbsr	_C_LABEL(ledcontrol)	| toggle pulse, turn all others off
   1131 	lea	%sp@(12),%sp
   1132 	movql	#0,%d0
   1133 Lnoleds1:
   1134 	movl	%d0,_ASM_LABEL(heartbeat)
   1135 Lnoleds0:
   1136 #endif /* USELEDS */
   1137 	jbsr	_C_LABEL(hardclock)	| hardclock(&frame)
   1138 	addql	#4,%sp
   1139 Lrecheck:
   1140 	CPUINFO_INCREMENT(CI_NINTR)	| chalk up another interrupt
   1141 	CLKADDR(%a0)
   1142 	movb	%a0@(CLKSR),%d0		| see if anything happened
   1143 	jmi	Lclkagain		|  while we were in hardclock/statintr
   1144 	INTERRUPT_RESTOREREG
   1145 	subql	#1,_C_LABEL(idepth)	| exiting from interrupt
   1146 	jra	_ASM_LABEL(rei)		| all done
   1147 
   1148 ENTRY_NOPROFILE(lev7intr)	/* level 7: parity errors, reset key */
   1149 	clrl	%sp@-
   1150 	moveml	#0xFFFF,%sp@-		| save registers
   1151 	EVCNT_INCREMENT(7)
   1152 	movl	%usp,%a0		| and save
   1153 	movl	%a0,%sp@(FR_SP)		|   the user stack pointer
   1154 	jbsr	_C_LABEL(nmihand)	| call handler
   1155 	movl	%sp@(FR_SP),%a0		| restore
   1156 	movl	%a0,%usp		|   user SP
   1157 	moveml	%sp@+,#0x7FFF		| and remaining registers
   1158 	addql	#8,%sp			| pop SP and stack adjust
   1159 	jra	_ASM_LABEL(rei)		| all done
   1160 
   1161 /*
   1162  * Emulation of VAX REI instruction.
   1163  *
   1164  * This code deals with checking for and servicing
   1165  * ASTs (profiling, scheduling).
   1166  * After identifing that we need an AST we drop the IPL
   1167  * to allow device interrupts.
   1168  *
   1169  * This code is complicated by the fact that sendsig may have been called
   1170  * necessitating a stack cleanup.
   1171  */
   1172 
   1173 ASENTRY_NOPROFILE(rei)
   1174 	tstl	_C_LABEL(astpending)	| AST pending?
   1175 	jne	1f			| no, done
   1176 	rte
   1177 1:
   1178 	btst	#5,%sp@			| yes, are we returning to user mode?
   1179 	jeq	2f			| no, done
   1180 	rte
   1181 2:
   1182 	movw	#PSL_LOWIPL,%sr		| lower SPL
   1183 	clrl	%sp@-			| stack adjust
   1184 	moveml	#0xFFFF,%sp@-		| save all registers
   1185 	movl	%usp,%a1		| including
   1186 	movl	%a1,%sp@(FR_SP)		|    the users SP
   1187 Lrei:
   1188 	clrl	%sp@-			| VA == none
   1189 	clrl	%sp@-			| code == none
   1190 	movl	#T_ASTFLT,%sp@-		| type == async system trap
   1191 	pea	%sp@(12)		| fp == address of trap frame
   1192 	jbsr	_C_LABEL(trap)		| go handle it
   1193 	lea	%sp@(16),%sp		| pop value args
   1194 	movl	%sp@(FR_SP),%a0		| restore user SP
   1195 	movl	%a0,%usp		|   from save area
   1196 	movw	%sp@(FR_ADJ),%d0	| need to adjust stack?
   1197 	jne	Laststkadj		| yes, go to it
   1198 	moveml	%sp@+,#0x7FFF		| no, restore most user regs
   1199 	addql	#8,%sp			| toss SP and stack adjust
   1200 	rte				| and do real RTE
   1201 Laststkadj:
   1202 	lea	%sp@(FR_HW),%a1		| pointer to HW frame
   1203 	addql	#8,%a1			| source pointer
   1204 	movl	%a1,%a0			| source
   1205 	addw	%d0,%a0			|  + hole size = dest pointer
   1206 	movl	%a1@-,%a0@-		| copy
   1207 	movl	%a1@-,%a0@-		|  8 bytes
   1208 	movl	%a0,%sp@(FR_SP)		| new SSP
   1209 	moveml	%sp@+,#0x7FFF		| restore user registers
   1210 	movl	%sp@,%sp		| and our SP
   1211 	rte				| and do real RTE
   1212 
   1213 /*
   1214  * Use common m68k sigcode.
   1215  */
   1216 #include <m68k/m68k/sigcode.s>
   1217 #ifdef COMPAT_SUNOS
   1218 #include <m68k/m68k/sunos_sigcode.s>
   1219 #endif
   1220 #ifdef COMPAT_SVR4
   1221 #include <m68k/m68k/svr4_sigcode.s>
   1222 #endif
   1223 
   1224 /*
   1225  * Primitives
   1226  */
   1227 
   1228 /*
   1229  * Use common m68k support routines.
   1230  */
   1231 #include <m68k/m68k/support.s>
   1232 
   1233 /*
   1234  * Use common m68k process/lwp switch and context save subroutines.
   1235  */
   1236 #define FPCOPROC	/* XXX: Temp. reqd. */
   1237 #include <m68k/m68k/switch_subr.s>
   1238 
   1239 
   1240 #if defined(M68040)
   1241 ENTRY(suline)
   1242 	movl	%sp@(4),%a0		| address to write
   1243 	movl	_C_LABEL(curpcb),%a1	| current pcb
   1244 	movl	#Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault
   1245 	movl	%sp@(8),%a1		| address of line
   1246 	movl	%a1@+,%d0		| get lword
   1247 	movsl	%d0,%a0@+		| put lword
   1248 	nop				| sync
   1249 	movl	%a1@+,%d0		| get lword
   1250 	movsl	%d0,%a0@+		| put lword
   1251 	nop				| sync
   1252 	movl	%a1@+,%d0		| get lword
   1253 	movsl	%d0,%a0@+		| put lword
   1254 	nop				| sync
   1255 	movl	%a1@+,%d0		| get lword
   1256 	movsl	%d0,%a0@+		| put lword
   1257 	nop				| sync
   1258 	moveq	#0,%d0			| indicate no fault
   1259 	jra	Lsldone
   1260 Lslerr:
   1261 	moveq	#-1,%d0
   1262 Lsldone:
   1263 	movl	_C_LABEL(curpcb),%a1	| current pcb
   1264 	clrl	%a1@(PCB_ONFAULT)	| clear fault address
   1265 	rts
   1266 #endif
   1267 
   1268 ENTRY(ecacheon)
   1269 	tstl	_C_LABEL(ectype)
   1270 	jeq	Lnocache7
   1271 	MMUADDR(%a0)
   1272 	orl	#MMU_CEN,%a0@(MMUCMD)
   1273 Lnocache7:
   1274 	rts
   1275 
   1276 ENTRY(ecacheoff)
   1277 	tstl	_C_LABEL(ectype)
   1278 	jeq	Lnocache8
   1279 	MMUADDR(%a0)
   1280 	andl	#~MMU_CEN,%a0@(MMUCMD)
   1281 Lnocache8:
   1282 	rts
   1283 
   1284 /*
   1285  * Load a new user segment table pointer.
   1286  */
   1287 ENTRY(loadustp)
   1288 #if defined(M68K_MMU_MOTOROLA)
   1289 	tstl	_C_LABEL(mmutype)	| HP MMU?
   1290 	jeq	Lhpmmu9			| yes, skip
   1291 	movl	%sp@(4),%d0		| new USTP
   1292 	moveq	#PGSHIFT,%d1
   1293 	lsll	%d1,%d0			| convert to addr
   1294 #if defined(M68040)
   1295 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
   1296 	jne	LmotommuC		| no, skip
   1297 	.word	0xf518			| yes, pflusha
   1298 	.long	0x4e7b0806		| movc %d0,%urp
   1299 	rts
   1300 LmotommuC:
   1301 #endif
   1302 	pflusha				| flush entire TLB
   1303 	lea	_C_LABEL(protorp),%a0	| CRP prototype
   1304 	movl	%d0,%a0@(4)		| stash USTP
   1305 	pmove	%a0@,%crp		| load root pointer
   1306 	movl	#CACHE_CLR,%d0
   1307 	movc	%d0,%cacr		| invalidate cache(s)
   1308 	rts
   1309 Lhpmmu9:
   1310 #endif
   1311 #if defined(M68K_MMU_HP)
   1312 	movl	#CACHE_CLR,%d0
   1313 	movc	%d0,%cacr		| invalidate cache(s)
   1314 	MMUADDR(%a0)
   1315 	movl	%a0@(MMUTBINVAL),%d1	| invalidate TLB
   1316 	tstl	_C_LABEL(ectype)	| have external VAC?
   1317 	jle	1f			| no, skip
   1318 	andl	#~MMU_CEN,%a0@(MMUCMD)	| toggle cache enable
   1319 	orl	#MMU_CEN,%a0@(MMUCMD)	| to clear data cache
   1320 1:
   1321 	movl	%sp@(4),%a0@(MMUUSTP)	| load a new USTP
   1322 #endif
   1323 	rts
   1324 
   1325 ENTRY(ploadw)
   1326 #if defined(M68K_MMU_MOTOROLA)
   1327 	movl	%sp@(4),%a0		| address to load
   1328 #if defined(M68K_MMU_HP)
   1329 	tstl	_C_LABEL(mmutype)	| HP MMU?
   1330 	jeq	Lploadwskp		| yes, skip
   1331 #endif
   1332 #if defined(M68040)
   1333 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
   1334 	jeq	Lploadwskp		| yes, skip
   1335 #endif
   1336 	ploadw	#1,%a0@			| pre-load translation
   1337 Lploadwskp:
   1338 #endif
   1339 	rts
   1340 
   1341 /*
   1342  * _delay(u_int N)
   1343  *
   1344  * Delay for at least (N/256) microseconds.
   1345  * This routine depends on the variable:  delay_divisor
   1346  * which should be set based on the CPU clock rate.
   1347  */
   1348 ENTRY_NOPROFILE(_delay)
   1349 	| %d0 = arg = (usecs << 8)
   1350 	movl	%sp@(4),%d0
   1351 	| %d1 = delay_divisor
   1352 	movl	_C_LABEL(delay_divisor),%d1
   1353 	jra	L_delay			/* Jump into the loop! */
   1354 
   1355 	/*
   1356 	 * Align the branch target of the loop to a half-line (8-byte)
   1357 	 * boundary to minimize cache effects.  This guarantees both
   1358 	 * that there will be no prefetch stalls due to cache line burst
   1359 	 * operations and that the loop will run from a single cache
   1360 	 * half-line.
   1361 	 */
   1362 	.align	8
   1363 L_delay:
   1364 	subl	%d1,%d0
   1365 	jgt	L_delay
   1366 	rts
   1367 
   1368 /*
   1369  * Probe a memory address, and see if it causes a bus error.
   1370  * This function is only to be used in physical mode, and before our
   1371  * trap vectors are initialized.
   1372  * Invoke with address to probe in %a0.
   1373  * Alters: %a3 %d0
   1374  */
   1375 #define BUSERR  0xfffffffc
   1376 ASLOCAL(phys_badaddr)
   1377 	ASRELOC(_bsave,%a3)
   1378 	movl	BUSERR,%a3@		| save ROM bus errror handler
   1379 	ASRELOC(_ssave,%a3)
   1380 	movl	%sp,%a3@		| and current stack pointer
   1381 	ASRELOC(catchbad,%a3)
   1382 	movl	%a3,BUSERR		| plug in our handler
   1383 	movb	%a0@,%d0		| access address
   1384 	ASRELOC(_bsave,%a3)		| no fault!
   1385 	movl	%a3@,BUSERR
   1386 	clrl	%d0			| return success
   1387 	rts
   1388 ASLOCAL(catchbad)
   1389 	ASRELOC(_bsave,%a3)		| got a bus error, so restore handler
   1390 	movl	%a3@,BUSERR
   1391 	ASRELOC(_ssave,%a3)
   1392 	movl	%a3@,%sp		| and stack
   1393 	moveq	#1,%d0			| return fault
   1394 	rts
   1395 #undef	BUSERR
   1396 
   1397 	.data
   1398 ASLOCAL(_bsave)
   1399 	.long   0
   1400 ASLOCAL(_ssave)
   1401 	.long   0
   1402 	.text
   1403 
   1404 /*
   1405  * Handle the nitty-gritty of rebooting the machine.
   1406  * Basically we just turn off the MMU and jump to the appropriate ROM routine.
   1407  * Note that we must be running in an address range that is mapped one-to-one
   1408  * logical to physical so that the PC is still valid immediately after the MMU
   1409  * is turned off.  We have conveniently mapped the last page of physical
   1410  * memory this way.
   1411  */
   1412 ENTRY_NOPROFILE(doboot)
   1413 #if defined(M68040)
   1414 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
   1415 	jeq	Lnocache5		| yes, skip
   1416 #endif
   1417 	movl	#CACHE_OFF,%d0
   1418 	movc	%d0,%cacr		| disable on-chip cache(s)
   1419 	tstl	_C_LABEL(ectype)	| external cache?
   1420 	jeq	Lnocache5		| no, skip
   1421 	MMUADDR(%a0)
   1422 	andl	#~MMU_CEN,%a0@(MMUCMD)	| disable external cache
   1423 Lnocache5:
   1424 	lea	MAXADDR,%a0		| last page of physical memory
   1425 	movl	_C_LABEL(boothowto),%a0@+ | store howto
   1426 	movl	_C_LABEL(bootdev),%a0@+	| and devtype
   1427 	lea	Lbootcode,%a1		| start of boot code
   1428 	lea	Lebootcode,%a3		| end of boot code
   1429 Lbootcopy:
   1430 	movw	%a1@+,%a0@+		| copy a word
   1431 	cmpl	%a3,%a1			| done yet?
   1432 	jcs	Lbootcopy		| no, keep going
   1433 #if defined(M68040)
   1434 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
   1435 	jne	LmotommuE		| no, skip
   1436 	.word	0xf4f8			| cpusha bc
   1437 LmotommuE:
   1438 #endif
   1439 	jmp	MAXADDR+8		| jump to last page
   1440 
   1441 Lbootcode:
   1442 	lea	MAXADDR+0x800,%sp	| physical SP in case of NMI
   1443 #if defined(M68040)
   1444 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
   1445 	jne	LmotommuF		| no, skip
   1446 	movl	#0,%d0
   1447 	movc	%d0,%cacr		| caches off
   1448 	.long	0x4e7b0003		| movc %d0,%tc
   1449 	movl	%d2,MAXADDR+PAGE_SIZE-4	| restore old high page contents
   1450 	DOREBOOT
   1451 LmotommuF:
   1452 #endif
   1453 #if defined(M68K_MMU_MOTOROLA)
   1454 	tstl	_C_LABEL(mmutype)	| HP MMU?
   1455 	jeq	LhpmmuB			| yes, skip
   1456 	movl	#0,%a0@			| value for pmove to TC (turn off MMU)
   1457 	pmove	%a0@,%tc		| disable MMU
   1458 	DOREBOOT
   1459 LhpmmuB:
   1460 #endif
   1461 #if defined(M68K_MMU_HP)
   1462 	MMUADDR(%a0)
   1463 	movl	#0xFFFF0000,%a0@(MMUCMD)	| totally disable MMU
   1464 	movl	%d2,MAXADDR+PAGE_SIZE-4	| restore old high page contents
   1465 	DOREBOOT
   1466 #endif
   1467 Lebootcode:
   1468 
   1469 /*
   1470  * Misc. global variables.
   1471  */
   1472 	.data
   1473 GLOBAL(machineid)
   1474 	.long	HP_320			| default to 320
   1475 
   1476 GLOBAL(mmuid)
   1477 	.long	0			| default to nothing
   1478 
   1479 GLOBAL(mmutype)
   1480 	.long	MMU_HP			| default to HP MMU
   1481 
   1482 GLOBAL(cputype)
   1483 	.long	CPU_68020		| default to 68020 CPU
   1484 
   1485 GLOBAL(ectype)
   1486 	.long	EC_NONE			| external cache type, default to none
   1487 
   1488 GLOBAL(fputype)
   1489 	.long	FPU_68882		| default to 68882 FPU
   1490 
   1491 GLOBAL(protorp)
   1492 	.long	0,0			| prototype root pointer
   1493 
   1494 GLOBAL(prototc)
   1495 	.long	0			| prototype translation control
   1496 
   1497 GLOBAL(internalhpib)
   1498 	.long	1			| has internal HP-IB, default to yes
   1499 
   1500 GLOBAL(intiobase)
   1501 	.long	0			| KVA of base of internal IO space
   1502 
   1503 GLOBAL(intiolimit)
   1504 	.long	0			| KVA of end of internal IO space
   1505 
   1506 GLOBAL(extiobase)
   1507 	.long	0			| KVA of base of external IO space
   1508 
   1509 GLOBAL(CLKbase)
   1510 	.long	0			| KVA of base of clock registers
   1511 
   1512 GLOBAL(MMUbase)
   1513 	.long	0			| KVA of base of HP MMU registers
   1514 
   1515 #ifdef USELEDS
   1516 ASLOCAL(heartbeat)
   1517 	.long	0			| clock ticks since last heartbeat
   1518 
   1519 ASLOCAL(beatstatus)
   1520 	.long	0			| for determining a fast or slow throb
   1521 #endif
   1522 
   1523 #ifdef DEBUG
   1524 ASGLOBAL(fulltflush)
   1525 	.long	0
   1526 
   1527 ASGLOBAL(fullcflush)
   1528 	.long	0
   1529 #endif
   1530