Home | History | Annotate | Line # | Download | only in atari
      1 /*	$NetBSD: locore.s,v 1.127 2024/01/19 18:18:53 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1988 University of Utah.
      5  * Copyright (c) 1980, 1990 The Regents of the University of California.
      6  * All rights reserved.
      7  *
      8  * This code is derived from software contributed to Berkeley by
      9  * the Systems Programming Group of the University of Utah Computer
     10  * Science Department.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions and the following disclaimer.
     17  * 2. Redistributions in binary form must reproduce the above copyright
     18  *    notice, this list of conditions and the following disclaimer in the
     19  *    documentation and/or other materials provided with the distribution.
     20  * 3. Neither the name of the University nor the names of its contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  *
     36  * from: Utah $Hdr: locore.s 1.58 91/04/22$
     37  *
     38  *	@(#)locore.s	7.11 (Berkeley) 5/9/91
     39  */
     40 
     41 /*
     42  *
     43  * Original (hp300) Author: unknown, maybe Mike Hibler?
     44  * Amiga author: Markus Wild
     45  * Atari Modifications: Leo Weppelman
     46  */
     47 
     48 #include "opt_compat_netbsd.h"
     49 #include "opt_compat_sunos.h"
     50 #include "opt_ddb.h"
     51 #include "opt_fpsp.h"
     52 #include "opt_kgdb.h"
     53 #include "opt_lockdebug.h"
     54 #include "opt_mbtype.h"
     55 #include "opt_m68k_arch.h"
     56 
     57 #include "kbd.h"
     58 #include "ncrscsi.h"
     59 #include "zs.h"
     60 
     61 #include "assym.h"
     62 #include <machine/asm.h>
     63 
     64 /*
     65  * This is for kvm_mkdb, and should be the address of the beginning
     66  * of the kernel text segment (not necessarily the same as kernbase).
     67  */
     68 	.text
     69 	GLOBAL(kernel_text)
     70 
     71 /*
     72  * Clear & skip page zero, it will not be mapped
     73  */
     74 	.fill	PAGE_SIZE/4,4,0
     75 
     76 #include <atari/atari/vectors.s>
     77 
     78 	.text
     79 	.even
     80 /*
     81  * Do a dump.
     82  * Called by auto-restart.
     83  */
     84 ENTRY_NOPROFILE(doadump)
     85 	jbsr	_C_LABEL(dumpsys)
     86 	jbsr	_C_LABEL(doboot)
     87 	/*NOTREACHED*/
     88 
     89 /*
     90  * Trap/interrupt vector routines
     91  */
     92 #include <m68k/m68k/trap_subr.s>
     93 
     94 #if defined(M68040) || defined(M68060)
     95 ENTRY_NOPROFILE(addrerr4060)
     96 	clrl	%sp@-			| stack adjust count
     97 	moveml	#0xFFFF,%sp@-		| save user registers
     98 	movl	%usp,%a0		| save the user SP
     99 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    100 	movl	%sp@(FR_HW+8),%sp@-
    101 	clrl	%sp@-			| dummy code
    102 	movl	#T_ADDRERR,%sp@-	| mark address error
    103 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    104 #endif /* defined(M68040) || defined(M68060) */
    105 
    106 #if defined(M68060)
    107 ENTRY_NOPROFILE(buserr60)
    108 	clrl	%sp@-			| stack adjust count
    109 	moveml	#0xFFFF,%sp@-		| save user registers
    110 	movl	%usp,%a0		| save the user SP
    111 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    112 	movel	%sp@(FR_HW+12),%d0	| FSLW
    113 	btst	#2,%d0			| branch prediction error?
    114 	jeq	Lnobpe
    115 	movc	%cacr,%d2
    116 	orl	#IC60_CABC,%d2		| clear all branch cache entries
    117 	movc	%d2,%cacr
    118 	movl	%d0,%d1
    119 	addql	#1,L60bpe
    120 	andl	#0x7ffd,%d1
    121 	jeq	_ASM_LABEL(faultstkadjnotrap2)
    122 Lnobpe:
    123 | we need to adjust for misaligned addresses
    124 	movl	%sp@(FR_HW+8),%d1	| grab VA
    125 	btst	#27,%d0			| check for mis-aligned access
    126 	jeq	Lberr3			| no, skip
    127 	addl	#28,%d1			| yes, get into next page
    128 					| operand case: 3,
    129 					| instruction case: 4+12+12
    130 	andl	#PG_FRAME,%d1           | and truncate
    131 Lberr3:
    132 	movl	%d1,%sp@-
    133 	movl	%d0,%sp@-		| code is FSLW now.
    134 	andw	#0x1f80,%d0
    135 	jeq	Lisberr
    136 	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
    137 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    138 #endif /* defined(M68060) */
    139 
    140 #if defined(M68040)
    141 ENTRY_NOPROFILE(buserr40)
    142 	clrl	%sp@-			| stack adjust count
    143 	moveml	#0xFFFF,%sp@-		| save user registers
    144 	movl	%usp,%a0		| save the user SP
    145 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    146 	movl	%sp@(FR_HW+20),%d1	| get fault address
    147 	moveq	#0,%d0
    148 	movw	%sp@(FR_HW+12),%d0	| get SSW
    149 	btst	#11,%d0			| check for mis-aligned
    150 	jeq	Lbe1stpg		| no skip
    151 	addl	#3,%d1			| get into next page
    152 	andl	#PG_FRAME,%d1		| and truncate
    153 Lbe1stpg:
    154 	movl	%d1,%sp@-		| pass fault address.
    155 	movl	%d0,%sp@-		| pass SSW as code
    156 	btst	#10,%d0			| test ATC
    157 	jeq	Lisberr			| it is a bus error
    158 	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
    159 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    160 #endif /* defined(M68040) */
    161 
    162 #if defined(M68020) || defined(M68030)
    163 ENTRY_NOPROFILE(buserr2030)
    164 ENTRY_NOPROFILE(addrerr2030)
    165 	clrl	%sp@-			| stack adjust count
    166 	moveml	#0xFFFF,%sp@-		| save user registers
    167 	movl	%usp,%a0		| save the user SP
    168 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    169 	moveq	#0,%d0
    170 	movw	%sp@(FR_HW+10),%d0	| grab SSW for fault processing
    171 	btst	#12,%d0			| RB set?
    172 	jeq	LbeX0			| no, test RC
    173 	bset	#14,%d0			| yes, must set FB
    174 	movw	%d0,%sp@(FR_HW+10)	| for hardware too
    175 LbeX0:
    176 	btst	#13,%d0			| RC set?
    177 	jeq	LbeX1			| no, skip
    178 	bset	#15,%d0			| yes, must set FC
    179 	movw	%d0,%sp@(FR_HW+10)	| for hardware too
    180 LbeX1:
    181 	btst	#8,%d0			| data fault?
    182 	jeq	Lbe0			| no, check for hard cases
    183 	movl	%sp@(FR_HW+16),%d1	| fault address is as given in frame
    184 	jra	Lbe10			| thats it
    185 Lbe0:
    186 	btst	#4,%sp@(FR_HW+6)	| long (type B) stack frame?
    187 	jne	Lbe4			| yes, go handle
    188 	movl	%sp@(FR_HW+2),%d1	| no, can use save PC
    189 	btst	#14,%d0			| FB set?
    190 	jeq	Lbe3			| no, try FC
    191 	addql	#4,%d1			| yes, adjust address
    192 	jra	Lbe10			| done
    193 Lbe3:
    194 	btst	#15,%d0			| FC set?
    195 	jeq	Lbe10			| no, done
    196 	addql	#2,%d1			| yes, adjust address
    197 	jra	Lbe10			| done
    198 Lbe4:
    199 	movl	%sp@(FR_HW+36),%d1	| long format, use stage B address
    200 	btst	#15,%d0			| FC set?
    201 	jeq	Lbe10			| no, all done
    202 	subql	#2,%d1			| yes, adjust address
    203 Lbe10:
    204 	movl	%d1,%sp@-		| push fault VA
    205 	movl	%d0,%sp@-		| and padded SSW
    206 	movw	%sp@(FR_HW+8+6),%d0	| get frame format/vector offset
    207 	andw	#0x0FFF,%d0		| clear out frame format
    208 	cmpw	#12,%d0			| address error vector?
    209 	jeq	Lisaerr			| yes, go to it
    210 	movl	%d1,%a0			| fault address
    211 	movl	%sp@,%d0		| function code from ssw
    212 	btst	#8,%d0			| data fault?
    213 	jne	Lbe10a
    214 	movql	#1,%d0			| user program access FC
    215 					| (we do not separate data/program)
    216 	btst	#5,%sp@(FR_HW+8)	| supervisor mode?
    217 	jeq	Lbe10a			| if no, done
    218 	movql	#5,%d0			| else supervisor program access
    219 Lbe10a:
    220 	ptestr	%d0,%a0@,#7		| do a table search
    221 	pmove	%psr,%sp@		| save result
    222 	movb	%sp@,%d1
    223 	btst	#2,%d1			| invalid (incl. limit viol. and berr)?
    224 	jeq	Lmightnotbemerr		| no -> wp check
    225 	btst	#7,%d1			| is it MMU table berr?
    226 	jeq	Lismerr			| no, must be fast
    227 	jra	Lisberr1		| real bus err needs not be fast.
    228 Lmightnotbemerr:
    229 	btst	#3,%d1			| write protect bit set?
    230 	jeq	Lisberr1		| no: must be bus error
    231 	movl	%sp@,%d0		| ssw into low word of d0
    232 	andw	#0xc0,%d0		| Write protect is set on page:
    233 	cmpw	#0x40,%d0		| was it read cycle?
    234 	jeq	Lisberr1		| yes, was not WPE, must be bus err
    235 Lismerr:
    236 	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
    237 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    238 Lisaerr:
    239 	movl	#T_ADDRERR,%sp@-	| mark address error
    240 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    241 Lisberr1:
    242 	clrw	%sp@			| re-clear pad word
    243 #endif /* !(defined(M68020) || defined(M68030)) */
    244 
    245 Lisberr:				| also used by M68040/60
    246 	tstl	_C_LABEL(nofault)	| device probe?
    247 	jeq	LberrIsProbe		| no, handle as usual
    248 	movl	_C_LABEL(nofault),%sp@-	| yes,
    249 	jbsr	_C_LABEL(longjmp)	|  longjmp(nofault)
    250 	/* NOTREACHED */
    251 LberrIsProbe:
    252 	movl	#T_BUSERR,%sp@-		| mark bus error
    253 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    254 
    255 	/*
    256 	 * This is where the default vectors end-up!
    257 	 * At the time of the 'machine-type' probes, it seems necessary
    258 	 * that the 'nofault' test is done first. Because the MMU is not
    259 	 * yet setup at this point, the real fault handlers sometimes
    260 	 * misinterpret the cause of the fault.
    261 	 */
    262 ENTRY_NOPROFILE(buserr)
    263 ENTRY_NOPROFILE(addrerr)
    264 	tstl	_C_LABEL(nofault)	| device probe?
    265 	jeq	1f			| no, halt...
    266 	movl	_C_LABEL(nofault),%sp@-	| yes,
    267 	jbsr	_C_LABEL(longjmp)	|  longjmp(nofault)
    268 	/* NOTREACHED */
    269 1:
    270 	jra	_C_LABEL(badtrap)	| only catch probes!
    271 
    272 /*
    273  * FP exceptions.
    274  */
    275 ENTRY_NOPROFILE(fpfline)
    276 	cmpl	#MMU_68040,_C_LABEL(mmutype)
    277 	jne	fpfline_not40		|  not a 040 FPU, do 6888? emulation
    278 	cmpw	#0x202c,%sp@(6)		|  format type 2?
    279 	jne	_C_LABEL(illinst)	|  no, not an FP emulation
    280 #ifdef FPSP
    281 	jmp	_ASM_LABEL(fpsp_unimp)	|  yes, go handle it
    282 #endif
    283 fpfline_not40:
    284 	clrl	%sp@-			|  stack adjust count
    285 	moveml	#0xFFFF,%sp@-		|  save registers
    286 	moveq	#T_FPEMULI,%d0		|  denote as FP emulation trap
    287 	jra	_ASM_LABEL(fault)	|  do it
    288 
    289 ENTRY_NOPROFILE(fpunsupp)
    290 	cmpl	#MMU_68040,_C_LABEL(mmutype)
    291 	jne	fpunsupp_not40		| not a 040 FPU, try 6888?
    292 #ifdef FPSP
    293 	jmp	_ASM_LABEL(fpsp_unsupp)	|  yes, go handle it
    294 #endif
    295 fpunsupp_not40:
    296 	clrl	%sp@-			|  stack adjust count
    297 	moveml	#0xFFFF,%sp@-		|  save registers
    298 	moveq	#T_FPEMULD,%d0		|  denote as FP emulation trap
    299 	jra	_ASM_LABEL(fault)	|  do it
    300 
    301 /*
    302  * Handles all other FP coprocessor exceptions.
    303  * Note that since some FP exceptions generate mid-instruction frames
    304  * and may cause signal delivery, we need to test for stack adjustment
    305  * after the trap call.
    306  */
    307 ENTRY_NOPROFILE(fpfault)
    308 	clrl	%sp@-			|  stack adjust count
    309 	moveml	#0xFFFF,%sp@-		|  save user registers
    310 	movl	%usp,%a0		|  and save
    311 	movl	%a0,%sp@(FR_SP)		|    the user stack pointer
    312 	clrl	%sp@-			|  no VA arg
    313 	movl	_C_LABEL(curpcb),%a0	|  current pcb
    314 	lea	%a0@(PCB_FPCTX),%a0	|  address of FP savearea
    315 	fsave	%a0@			|  save state
    316 
    317 #if defined(M68040) || defined(M68060)
    318 #ifdef notdef /* XXX: Can't use this while we don't have the cputype */
    319 	movb	_C_LABEL(cputype), %d0
    320 	andb	#(ATARI_68040|ATARI_68060), %d0
    321 	jne	Lfptnull
    322 #else
    323 	cmpb	#0x41,%a0@		|  is it the 68040 FPU-frame format?
    324 	jeq	Lfptnull		|  yes, safe
    325 #endif /* notdef */
    326 #endif /* defined(M68040) || defined(M68060) */
    327 
    328 	tstb	%a0@			|  null state frame?
    329 	jeq	Lfptnull		|  yes, safe
    330 	clrw	%d0			|  no, need to tweak BIU
    331 	movb	%a0@(1),%d0		|  get frame size
    332 	bset	#3,%a0@(0,%d0:w)	|  set exc_pend bit of BIU
    333 Lfptnull:
    334 	fmovem	%fpsr,%sp@-		|  push fpsr as code argument
    335 	frestore %a0@			|  restore state
    336 	movl	#T_FPERR,%sp@-		|  push type arg
    337 	jra	_ASM_LABEL(faultstkadj)	|  call trap and deal with stack cleanup
    338 
    339 /*
    340  * Other exceptions only cause four and six word stack frame and require
    341  * no post-trap stack adjustment.
    342  */
    343 
    344 ENTRY_NOPROFILE(intr_glue)
    345 	addql	#1,_C_LABEL(intr_depth)
    346 	INTERRUPT_SAVEREG
    347 	jbsr	_C_LABEL(intr_dispatch)	|  handle interrupt
    348 	INTERRUPT_RESTOREREG
    349 	subql	#1,_C_LABEL(intr_depth)
    350 	jra	_ASM_LABEL(rei)
    351 
    352 ENTRY_NOPROFILE(lev2intr)
    353 	rte				|  HBL, can't be turned off on Falcon!
    354 
    355 ENTRY_NOPROFILE(lev4intr)		|  VBL interrupt
    356 #ifdef FALCON_VIDEO
    357 	tstl	_C_LABEL(falcon_needs_vbl)
    358 	jne	1f			|  Yes, go service a VBL-request
    359 	rte				|  Nothing to do.
    360 1:
    361 	addql	#1,_C_LABEL(intr_depth)
    362 	INTERRUPT_SAVEREG
    363 	jbsr	_C_LABEL(falcon_display_switch)
    364 	INTERRUPT_RESTOREREG
    365 	subql	#1,_C_LABEL(intr_depth)
    366 #endif /* FALCON_VIDEO */
    367 	rte
    368 
    369 ENTRY_NOPROFILE(lev5intr)
    370 ENTRY_NOPROFILE(lev6intr)
    371 
    372 #ifdef _MILANHW_
    373 	/* XXX
    374 	 * Need to find better places to define these (Leo)
    375 	 */
    376 #define	PLX_PCICR	0x4204
    377 #define	PLX_CNTRL	0x42ec
    378 #define	PLX_DMCFGA	0x42ac
    379 	addql	#1,_C_LABEL(intr_depth)
    380 	moveml	%d0-%d2/%a0-%a1,%sp@-
    381 	movw	%sp@(20),%sp@-		|  push previous SR value
    382 	clrw	%sp@-			|	padded to longword
    383 	movl	_C_LABEL(stio_addr),%a0	| get KVA of ST-IO area
    384 	movew	#0xffff,%a0@(PLX_PCICR)	| clear PCI_SR error bits
    385 	movel	%a0@(PLX_CNTRL),%d0	| Change PCI command code from
    386 	andw	#0xf0ff,%d0
    387 	movw	%sr,%d2			| Block interrupts for now
    388 	oriw	#0x0700,%sr
    389 	movl	%d0,%a0@(PLX_CNTRL)
    390 	movq	#0,%d1			| clear upper bits
    391 					| Read any (uncached!) PCI address
    392 					|  to fetch vector number
    393 	movl	_C_LABEL(pci_mem_uncached),%a1
    394 	movb	%a1@,%d1
    395 	orw	#0x0600,%d0		| Change PCI command code back
    396 	movel	%d0,%a0@(PLX_CNTRL)	|  to Read Cycle
    397 	movew	%d2,%sr			| Re-enable interrupts
    398 	movel	%d1,%sp@-		| Call handler
    399 	jbsr	_C_LABEL(milan_isa_intr)
    400 	addql	#8,%sp
    401 	moveml  %sp@+,%d0-%d2/%a0-%a1
    402 	subql	#1,_C_LABEL(intr_depth)
    403 	jra	_ASM_LABEL(rei)
    404 
    405 /*
    406  * Support functions for reading and writing the Milan PCI config space.
    407  * Of interest:
    408  *   - We need exclusive access to the PLX9080 during config space
    409  *     access, hence the splhigh().
    410  *   - The 'confread' function shortcircuits the NMI to make probes to
    411  *     unexplored pci-config space possible.
    412  */
    413 ENTRY(milan_pci_confread)
    414 	movl	%sp@(4),%d0		| get tag and regno
    415 	bset	#31,%d0			| add config space flag
    416 	andl	#~3,%d0			| access type 0
    417 	movl	_C_LABEL(stio_addr),%a0	| get KVA of ST-IO area
    418 	movw	%sr,%d1			| goto splhigh
    419 	oriw	#0x0700,%sr
    420 	movb	#1,_ASM_LABEL(plx_nonmi)| no NMI interrupts please!
    421 	movl	%d0,%a0@(PLX_DMCFGA)	| write tag to the config register
    422 	movl	_C_LABEL(pci_io_addr),%a1
    423 	movl	%a1@,%d0		| fetch value
    424 	movl	#0,%a0@(PLX_DMCFGA)	| back to normal PCI access
    425 
    426 					| Make sure the C-function can peek
    427 	movw	%a0@(PLX_PCICR),_C_LABEL(plx_status) | at the access results.
    428 
    429 	movw	#0xf900,%a0@(PLX_PCICR)	| Clear potential error bits
    430 	movb	#0, _ASM_LABEL(plx_nonmi)
    431 	movw	%d1,%sr			| splx
    432 	rts
    433 
    434 ENTRY(milan_pci_confwrite)
    435 	movl	%sp@(4),%d0		| get tag and regno
    436 	bset	#31,%d0			| add config space flag
    437 	andl	#~3,%d0			| access type 0
    438 	movl	_C_LABEL(stio_addr),%a0	| get KVA of ST-IO area
    439 	movw	%sr,%d1			| goto splhigh
    440 	oriw	#0x0700,%sr
    441 	movl	%d0,%a0@(PLX_DMCFGA)	| write tag to the config register
    442 	movl	_C_LABEL(pci_io_addr),%a1
    443 	movl	%sp@(8),%a1@		| write value
    444 	movl	#0,%a0@(PLX_DMCFGA)	| back to normal PCI access
    445 	movw	%d1,%sr			| splx
    446 	rts
    447 
    448 ENTRY_NOPROFILE(lev7intr)
    449 	tstl	_ASM_LABEL(plx_nonmi)	| milan_conf_read shortcut
    450 	jne	1f			| .... get out immediately
    451 	INTERRUPT_SAVEREG
    452 	movl	_C_LABEL(stio_addr),%a0	| get KVA of ST-IO area
    453 	movw	%a0@(PLX_PCICR),_C_LABEL(plx_status)
    454 	movw	#0xf900,%a0@(PLX_PCICR)	| Clear error bits
    455 	jbsr	_C_LABEL(nmihandler)	| notify...
    456 	INTERRUPT_RESTOREREG
    457 	addql	#1,_C_LABEL(intrcnt)+28	| add another nmi interrupt
    458 1:
    459 	rte				| all done
    460 #endif /* _MILANHW_ */
    461 
    462 ENTRY_NOPROFILE(lev3intr)
    463 ENTRY_NOPROFILE(badtrap)
    464 	addql	#1,_C_LABEL(intr_depth)
    465 	INTERRUPT_SAVEREG
    466 	movw	%sp@(22),%sp@-		|  push exception vector info
    467 	clrw	%sp@-
    468 	movl	%sp@(22),%sp@-		|  and PC
    469 	jbsr	_C_LABEL(straytrap)	|  report
    470 	addql	#8,%sp			|  pop args
    471 	INTERRUPT_RESTOREREG		|  restore regs
    472 	subql	#1,_C_LABEL(intr_depth)
    473 	jra	_ASM_LABEL(rei)		|  all done
    474 
    475 ENTRY_NOPROFILE(badmfpint)
    476 	addql	#1,_C_LABEL(intr_depth)
    477 	INTERRUPT_SAVEREG		|  save scratch regs
    478 	movw	%sp@(22),%sp@-		|  push exception vector info
    479 	clrw	%sp@-
    480 	movl	%sp@(22),%sp@-		|  and PC
    481 	jbsr	_C_LABEL(straymfpint)	|  report
    482 	addql	#8,%sp			|  pop args
    483 	INTERRUPT_RESTOREREG		|  restore regs
    484 	subql	#1,_C_LABEL(intr_depth)
    485 	jra	_ASM_LABEL(rei)		|  all done
    486 
    487 ENTRY_NOPROFILE(trap0)
    488 	clrl	%sp@-			|  stack adjust count
    489 	moveml	#0xFFFF,%sp@-		|  save user registers
    490 	movl	%usp,%a0		|  save the user SP
    491 	movl	%a0,%sp@(FR_SP)		|    in the savearea
    492 	movl	%d0,%sp@-		|  push syscall number
    493 	jbsr	_C_LABEL(syscall)	|  handle it
    494 	addql	#4,%sp			|  pop syscall arg
    495 	movl	%sp@(FR_SP),%a0		|  grab and restore
    496 	movl	%a0,%usp		|    user SP
    497 	moveml	%sp@+,#0x7FFF		|  restore most registers
    498 	addql	#8,%sp			|  pop SP and stack adjust
    499 	jra	_ASM_LABEL(rei)		|  all done
    500 
    501 /*
    502  * Trap 12 is the entry point for the cachectl "syscall"
    503  *	cachectl(command, addr, length)
    504  * command in d0, addr in a1, length in d1
    505  */
    506 ENTRY_NOPROFILE(trap12)
    507 	movl	_C_LABEL(curlwp),%a0
    508 	movl	%a0@(L_PROC),%sp@-	|  push curproc pointer
    509 	movl	%d1,%sp@-		|  push length
    510 	movl	%a1,%sp@-		|  push addr
    511 	movl	%d0,%sp@-		|  push command
    512 	jbsr	_C_LABEL(cachectl1)	|  do it
    513 	lea	%sp@(16),%sp		|  pop args
    514 	jra	_ASM_LABEL(rei)		|  all done
    515 
    516 /*
    517  * Trace (single-step) trap.  Kernel-mode is special.
    518  * User mode traps are simply passed on to trap().
    519  */
    520 ENTRY_NOPROFILE(trace)
    521 	clrl	%sp@-			| stack adjust count
    522 	moveml	#0xFFFF,%sp@-
    523 	moveq	#T_TRACE,%d0
    524 
    525 	| Check PSW and see what happen.
    526 	|   T=0 S=0	(should not happen)
    527 	|   T=1 S=0	trace trap from user mode
    528 	|   T=0 S=1	trace trap on a trap instruction
    529 	|   T=1 S=1	trace trap from system mode (kernel breakpoint)
    530 
    531 	movw	%sp@(FR_HW),%d1		| get PSW
    532 	notw	%d1			| XXX no support for T0 on 680[234]0
    533 	andw	#PSL_TS,%d1		| from system mode (T=1, S=1)?
    534 	jeq	Lkbrkpt			| yes, kernel breakpoint
    535 	jra	_ASM_LABEL(fault)	| no, user-mode fault
    536 
    537 /*
    538  * Trap 15 is used for:
    539  *	- GDB breakpoints (in user programs)
    540  *	- KGDB breakpoints (in the kernel)
    541  *	- trace traps for SUN binaries (not fully supported yet)
    542  * User mode traps are simply passed to trap().
    543  */
    544 ENTRY_NOPROFILE(trap15)
    545 	clrl	%sp@-
    546 	moveml	#0xFFFF,%sp@-
    547 	moveq	#T_TRAP15,%d0
    548 	movw	%sp@(FR_HW),%d1		|  get PSW
    549 	andw	#PSL_S,%d1		|  from system mode?
    550 	jne	Lkbrkpt			|  yes, kernel breakpoint
    551 	jra	_ASM_LABEL(fault)	|  no, user-mode fault
    552 
    553 Lkbrkpt:
    554 	| Kernel-mode breakpoint or trace trap. (d0=trap_type)
    555 	| Save the system sp rather than the user sp.
    556 	movw	#PSL_HIGHIPL,%sr	| lock out interrupts
    557 	lea	%sp@(FR_SIZE),%a6	| Save stack pointer
    558 	movl	%a6,%sp@(FR_SP)		|  from before trap
    559 
    560 	| If were are not on tmpstk switch to it.
    561 	| (so debugger can change the stack pointer)
    562 	movl	%a6,%d1
    563 	cmpl	#_ASM_LABEL(tmpstk),%d1
    564 	jls	Lbrkpt2				| already on tmpstk
    565 	| Copy frame to the temporary stack
    566 	movl	%sp,%a0				| a0=src
    567 	lea	_ASM_LABEL(tmpstk)-96,%a1	| a1=dst
    568 	movl	%a1,%sp				| sp=new frame
    569 	moveq	#FR_SIZE,%d1
    570 Lbrkpt1:
    571 	movl	%a0@+,%a1@+
    572 	subql	#4,%d1
    573 	bgt	Lbrkpt1
    574 
    575 Lbrkpt2:
    576 	| Call the trap handler for the kernel debugger.
    577 	| Do not call trap() to do it, so that we can
    578 	| set breakpoints in trap() if we want.  We know
    579 	| the trap type is either T_TRACE or T_BREAKPOINT.
    580 	| If we have both DDB and KGDB, let KGDB see it first,
    581 	| because KGDB will just return 0 if not connected.
    582 	| Save args in d2, a2
    583 	movl	%d0,%d2			| trap type
    584 	movl	%sp,%a2			| frame ptr
    585 #ifdef KGDB
    586 	| Let KGDB handle it (if connected)
    587 	movl	%a2,%sp@-		| push frame ptr
    588 	movl	%d2,%sp@-		| push trap type
    589 	jbsr	_C_LABEL(kgdb_trap)	| handle the trap
    590 	addql	#8,%sp			| pop args
    591 	cmpl	#0,%d0			| did kgdb handle it?
    592 	jne	Lbrkpt3			| yes, done
    593 #endif
    594 #ifdef DDB
    595 	| Let DDB handle it
    596 	movl	%a2,%sp@-		| push frame ptr
    597 	movl	%d2,%sp@-		| push trap type
    598 	jbsr	_C_LABEL(kdb_trap)	| handle the trap
    599 	addql	#8,%sp			| pop args
    600 #if 0	/* not needed on atari */
    601 	cmpl	#0,%d0			| did ddb handle it?
    602 	jne	Lbrkpt3			| yes, done
    603 #endif
    604 #endif
    605 	/* Sun 3 drops into PROM here. */
    606 Lbrkpt3:
    607 	| The stack pointer may have been modified, or
    608 	| data below it modified (by kgdb push call),
    609 	| so push the hardware frame at the current sp
    610 	| before restoring registers and returning.
    611 
    612 	movl	%sp@(FR_SP),%a0		| modified sp
    613 	lea	%sp@(FR_SIZE),%a1	| end of our frame
    614 	movl	%a1@-,%a0@-		| copy 2 longs with
    615 	movl	%a1@-,%a0@-		| ... predecrement
    616 	movl	%a0,%sp@(FR_SP)		| sp = h/w frame
    617 	moveml	%sp@+,#0x7FFF		| restore all but sp
    618 	movl	%sp@,%sp		| ... and sp
    619 	rte				| all done
    620 
    621 /*
    622  * Interrupt handlers.
    623  *
    624  *	Level 0:	Spurious: ignored.
    625  *	Level 1:	softint
    626  *	Level 2:	HBL
    627  *	Level 3:	not used
    628  *	Level 4:	not used
    629  *	Level 5:	SCC (not used)
    630  *	Level 6:	MFP1/MFP2 (not used -> autovectored)
    631  *	Level 7:	Non-maskable: shouldn't be possible. ignore.
    632  */
    633 
    634 /* Provide a generic interrupt dispatcher, only handle hardclock (int6)
    635  * specially, to improve performance
    636  */
    637 
    638 ENTRY_NOPROFILE(spurintr)
    639 	addql	#1,_C_LABEL(intrcnt)+0
    640 	INTERRUPT_SAVEREG		|  save scratch registers
    641 	CPUINFO_INCREMENT(CI_NINTR)
    642 	INTERRUPT_RESTOREREG		|  restore scratch regs
    643 	jra	_ASM_LABEL(rei)
    644 
    645 	/* MFP timer A handler --- System clock --- */
    646 ASENTRY_NOPROFILE(mfp_tima)
    647 	addql	#1,_C_LABEL(intr_depth)
    648 	INTERRUPT_SAVEREG		|  save scratch registers
    649 	movl	%sp,%sp@-		|  push pointer to clockframe
    650 	jbsr	_C_LABEL(hardclock)	|  call generic clock int routine
    651 	addql	#4,%sp			|  pop params
    652 	addql	#1,_C_LABEL(intrcnt_user)+52
    653 					|  add another system clock interrupt
    654 	CPUINFO_INCREMENT(CI_NINTR)
    655 	INTERRUPT_RESTOREREG		|  restore scratch regs
    656 	subql	#1,_C_LABEL(intr_depth)
    657 	jra	_ASM_LABEL(rei)		|  all done
    658 
    659 #ifdef STATCLOCK
    660 	/* MFP timer C handler --- Stat/Prof clock --- */
    661 ASENTRY_NOPROFILE(mfp_timc)
    662 	addql	#1,_C_LABEL(intr_depth)
    663 	INTERRUPT_SAVEREG		|  save scratch registers
    664 	jbsr	_C_LABEL(statintr)	|  call statistics clock handler
    665 	addql	#1,_C_LABEL(intrcnt)+36	|  add another stat clock interrupt
    666 	CPUINFO_INCREMENT(CI_NINTR)
    667 	INTERRUPT_RESTOREREG		|  restore scratch regs
    668 	subql	#1,_C_LABEL(intr_depth)
    669 	jra	_ASM_LABEL(rei)		|  all done
    670 #endif /* STATCLOCK */
    671 
    672 #if NKBD > 0
    673 	/* MFP ACIA handler --- keyboard/midi --- */
    674 ASENTRY_NOPROFILE(mfp_kbd)
    675 	addql	#1,_C_LABEL(intr_depth)
    676 	addql	#1,_C_LABEL(intrcnt)+8	|  add another kbd/mouse interrupt
    677 
    678 	INTERRUPT_SAVEREG		|  save scratch registers
    679 	movw	%sp@(16),%sp@-		|  push previous SR value
    680 	clrw	%sp@-			|     padded to longword
    681 	jbsr	_C_LABEL(kbdintr)	|  handle interrupt
    682 	addql	#4,%sp			|  pop SR
    683 	CPUINFO_INCREMENT(CI_NINTR)
    684 	INTERRUPT_RESTOREREG		|  restore scratch regs
    685 	subql	#1,_C_LABEL(intr_depth)
    686 	jra	_ASM_LABEL(rei)
    687 #endif /* NKBD */
    688 
    689 #if NNCRSCSI > 0
    690 	/* MFP2 SCSI DMA handler --- NCR5380 --- */
    691 ASENTRY_NOPROFILE(mfp2_5380dm)
    692 	addql	#1,_C_LABEL(intr_depth)
    693 	addql	#1,_C_LABEL(intrcnt)+24	|  add another 5380-DMA interrupt
    694 
    695 	INTERRUPT_SAVEREG		|  save scratch registers
    696 	movw	%sp@(16),%sp@-		|  push previous SR value
    697 	clrw	%sp@-			|     padded to longword
    698 	jbsr	_C_LABEL(scsi_dma)	|  handle interrupt
    699 	addql	#4,%sp			|  pop SR
    700 	CPUINFO_INCREMENT(CI_NINTR)
    701 	INTERRUPT_RESTOREREG		|  restore scratch regs
    702 	subql	#1,_C_LABEL(intr_depth)
    703 	jra	_ASM_LABEL(rei)
    704 
    705 	/* MFP2 SCSI handler --- NCR5380 --- */
    706 ASENTRY_NOPROFILE(mfp2_5380)
    707 	addql	#1,_C_LABEL(intr_depth)
    708 	addql	#1,_C_LABEL(intrcnt)+20	|  add another 5380-SCSI interrupt
    709 
    710 	INTERRUPT_SAVEREG		|  save scratch registers
    711 	movw	%sp@(16),%sp@-		|  push previous SR value
    712 	clrw	%sp@-			|     padded to longword
    713 	jbsr	_C_LABEL(scsi_ctrl)	|  handle interrupt
    714 	addql	#4,%sp			|  pop SR
    715 	CPUINFO_INCREMENT(CI_NINTR)
    716 	INTERRUPT_RESTOREREG		|  restore scratch regs
    717 	subql	#1,_C_LABEL(intr_depth)
    718 	jra	_ASM_LABEL(rei)
    719 #endif /* NNCRSCSI > 0 */
    720 
    721 #ifdef _ATARIHW_
    722 	/* Level 1 (Software) interrupt handler */
    723 ENTRY_NOPROFILE(lev1intr)
    724 	addql	#1,_C_LABEL(intr_depth)
    725 	INTERRUPT_SAVEREG		|  save scratch registers
    726 	movl	_C_LABEL(stio_addr),%a0 |  get KVA of ST-IO area
    727 	moveb	#0, %a0@(SCU_SOFTINT)	|  Turn off software interrupt
    728 	addql	#1,_C_LABEL(intrcnt)+16	|  add another software interrupt
    729 	jbsr	_C_LABEL(nullop)	|  XXX handle software interrupts
    730 	CPUINFO_INCREMENT(CI_NINTR)
    731 	INTERRUPT_RESTOREREG
    732 	subql	#1,_C_LABEL(intr_depth)
    733 	jra	_ASM_LABEL(rei)
    734 
    735 	/*
    736 	 * Should never occur, except when special hardware modification
    737 	 * is installed. In this case, one expects to be dropped into
    738 	 * the debugger.
    739 	 */
    740 ENTRY_NOPROFILE(lev7intr)
    741 #ifdef DDB
    742 	/*
    743 	 * Note that the nmi has to be turned off while handling it because
    744 	 * the hardware modification has no de-bouncing logic....
    745 	 */
    746 	addql	#1,_C_LABEL(intr_depth)
    747 	movl	%a0, %sp@-		|  save a0
    748 	movl	_C_LABEL(stio_addr),%a0	|  get KVA of ST-IO area
    749 	movb	%a0@(SCU_SYSMASK),%sp@-	|  save current sysmask
    750 	movb	#0, %a0@(SCU_SYSMASK)	|  disable all interrupts
    751 	trap	#15			|  drop into the debugger
    752 	movb	%sp@+, %a0@(SCU_SYSMASK)|  restore sysmask
    753 	movl	%sp@+, %a0		|  restore a0
    754 	subql	#1,_C_LABEL(intr_depth)
    755 #endif
    756 	addql	#1,_C_LABEL(intrcnt)+28	|  add another nmi interrupt
    757 	rte				|  all done
    758 
    759 #endif /* _ATARIHW_ */
    760 
    761 
    762 /*
    763  * Emulation of VAX REI instruction.
    764  *
    765  * This code deals with checking for and servicing ASTs
    766  * (profiling, scheduling) and software interrupts (network, softclock).
    767  * We check for ASTs first, just like the VAX.  To avoid excess overhead
    768  * the T_ASTFLT handling code will also check for software interrupts so we
    769  * do not have to do it here.  After identifying that we need an AST we
    770  * drop the IPL to allow device interrupts.
    771  *
    772  * This code is complicated by the fact that sendsig may have been called
    773  * necessitating a stack cleanup.  A cleanup should only be needed at this
    774  * point for coprocessor mid-instruction frames (type 9), but we also test
    775  * for bus error frames (type 10 and 11).
    776  */
    777 ASENTRY_NOPROFILE(rei)
    778 #ifdef DEBUG
    779 	tstl	_C_LABEL(panicstr)	|  have we panicked?
    780 	jne	Ldorte			|  yes, do not make matters worse
    781 #endif
    782 	tstl	_C_LABEL(astpending)	|  AST pending?
    783 	jeq	Lchksir			|  no, go check for SIR
    784 Lrei1:
    785 	btst	#5,%sp@			|  yes, are we returning to user mode?
    786 	jne	Lchksir			|  no, go check for SIR
    787 	movw	#PSL_LOWIPL,%sr		|  lower SPL
    788 	clrl	%sp@-			|  stack adjust
    789 	moveml	#0xFFFF,%sp@-		|  save all registers
    790 	movl	%usp,%a1		|  including
    791 	movl	%a1,%sp@(FR_SP)		|     the users SP
    792 	clrl	%sp@-			|  VA == none
    793 	clrl	%sp@-			|  code == none
    794 	movl	#T_ASTFLT,%sp@-		|  type == async system trap
    795 	pea	%sp@(12)		|  fp == address of trap frame
    796 	jbsr	_C_LABEL(trap)		|  go handle it
    797 	lea	%sp@(16),%sp		|  pop value args
    798 	movl	%sp@(FR_SP),%a0		|  restore user SP
    799 	movl	%a0,%usp		|    from save area
    800 	movw	%sp@(FR_ADJ),%d0	|  need to adjust stack?
    801 	jne	Laststkadj		|  yes, go to it
    802 	moveml	%sp@+,#0x7FFF		|  no, restore most user regs
    803 	addql	#8,%sp			|  toss SP and stack adjust
    804 	rte				|  and do real RTE
    805 Laststkadj:
    806 	lea	%sp@(FR_HW),%a1		|  pointer to HW frame
    807 	addql	#8,%a1			|  source pointer
    808 	movl	%a1,%a0			|  source
    809 	addw	%d0,%a0			|   + hole size = dest pointer
    810 	movl	%a1@-,%a0@-		|  copy
    811 	movl	%a1@-,%a0@-		|   8 bytes
    812 	movl	%a0,%sp@(FR_SP)		|  new SSP
    813 	moveml	%sp@+,#0x7FFF		|  restore user registers
    814 	movl	%sp@,%sp		|  and our SP
    815 	rte				|  and do real RTE
    816 Lchksir:
    817 	tstb	_C_LABEL(ssir)		|  SIR pending?
    818 	jeq	Ldorte			|  no, all done
    819 	movl	%d0,%sp@-		|  need a scratch register
    820 	movw	%sp@(4),%d0		|  get SR
    821 	andw	#PSL_IPL7,%d0		|  mask all but IPL
    822 	jne	Lnosir			|  came from interrupt, no can do
    823 	movl	%sp@+,%d0		|  restore scratch register
    824 Lgotsir:
    825 	movw	#SPL1,%sr		|  prevent others from servicing int
    826 	tstb	_C_LABEL(ssir)		|  too late?
    827 	jeq	Ldorte			|  yes, oh well...
    828 	clrl	%sp@-			|  stack adjust
    829 	moveml	#0xFFFF,%sp@-		|  save all registers
    830 	movl	%usp,%a1		|  including
    831 	movl	%a1,%sp@(FR_SP)		|     the users SP
    832 	clrl	%sp@-			|  VA == none
    833 	clrl	%sp@-			|  code == none
    834 	movl	#T_SSIR,%sp@-		|  type == software interrupt
    835 	pea	%sp@(12)		|  fp == address of trap frame
    836 	jbsr	_C_LABEL(trap)		|  go handle it
    837 	lea	%sp@(16),%sp		|  pop value args
    838 	movl	%sp@(FR_SP),%a0		|  restore
    839 	movl	%a0,%usp		|    user SP
    840 	moveml	%sp@+,#0x7FFF		|  and all remaining registers
    841 	addql	#8,%sp			|  pop SP and stack adjust
    842 	rte
    843 Lnosir:
    844 	movl	%sp@+,%d0		|  restore scratch register
    845 Ldorte:
    846 	rte				|  real return
    847 
    848 /*
    849  * Initialization
    850  *
    851  * A5 contains physical load point from boot
    852  * exceptions vector thru our table, that's bad.. just hope nothing exceptional
    853  * happens till we had time to initialize ourselves..
    854  */
    855 	BSS(lowram,4)
    856 	BSS(esym,4)
    857 
    858 	.globl	_C_LABEL(edata)
    859 	.globl	_C_LABEL(etext),_C_LABEL(end)
    860 
    861 GLOBAL(bootversion)
    862 	.word	0x0003			|  Glues kernel/installboot/loadbsd
    863 					|    and other bootcode together.
    864 ASENTRY_NOPROFILE(start)
    865 	movw	#PSL_HIGHIPL,%sr	| No interrupts
    866 
    867 	/*
    868 	 * a0 = start of loaded kernel
    869 	 * a1 = value of esym
    870 	 * d0 = fastmem size
    871 	 * d1 = stmem size
    872 	 * d2 = cputype
    873 	 * d3 = boothowto
    874 	 * d4 = size of loaded kernel
    875 	 */
    876 	movl	#8,%a5			| Addresses 0-8 are mapped to ROM on the
    877 	addql	#8,%a0			|  atari ST. We cannot set these.
    878 	subl	#8,%d4
    879 
    880 	/*
    881 	 * Copy until end of kernel relocation code.
    882 	 */
    883 Lstart0:
    884 	movl	%a0@+,%a5@+
    885 	subl	#4, %d4
    886 	cmpl	#Lstart3,%a5
    887 	jle	Lstart0
    888 	/*
    889 	 * Enter kernel at destination address and continue copy
    890 	 * Make sure that the jump is absolute (by adding ':l') otherwise
    891 	 * the assembler tries to use a pc-relative jump.
    892 	 * Which is definitely not what is needed at this point!
    893 	 */
    894 	jmp	Lstart2:l
    895 Lstart2:
    896 	movl	%a0@+,%a5@+		| copy the rest of the kernel
    897 	subl	#4, %d4
    898 	jcc	Lstart2
    899 Lstart3:
    900 
    901 	lea	_ASM_LABEL(tmpstk),%sp	| give ourselves a temporary stack
    902 
    903 	/*
    904 	 *  save the passed parameters. `prepass' them on the stack for
    905 	 *  later catch by _start_c
    906 	 */
    907 	movl	%a1,%sp@-		| pass address of _esym
    908 	movl	%d1,%sp@-		| pass stmem-size
    909 	movl	%d0,%sp@-		| pass fastmem-size
    910 	movl	%d5,%sp@-		| pass fastmem_start
    911 	movl	%d2,%sp@-		| pass machine id
    912 	movl	%d3,_C_LABEL(boothowto)	| save reboot flags
    913 
    914 
    915 	/*
    916 	 * Set cputype and mmutype dependent on the machine-id passed
    917 	 * in from the loader. Also make sure that all caches are cleared.
    918 	 */
    919 	movl	#ATARI_68030,%d1		| 68030 type from loader
    920 	andl	%d2,%d1
    921 	jeq	Ltestfor020			| Not an 68030, try 68020
    922 	movl	#MMU_68030,_C_LABEL(mmutype)	| Use 68030 MMU
    923 	movl	#CPU_68030,_C_LABEL(cputype)	|   and a 68030 CPU
    924 	movl	#CACHE_OFF,%d0			| 68020/030 cache clear
    925 	jra	Lend_cpuset			| skip to init.
    926 Ltestfor020:
    927 	movl	#ATARI_68020,%d1		| 68020 type from loader
    928 	andl	%d2,%d1
    929 	jeq	Ltestfor040
    930 	movl	#MMU_68851,_C_LABEL(mmutype)	| Assume 68851 with 68020
    931 	movl	#CPU_68020,_C_LABEL(cputype)	|   and a 68020 CPU
    932 	movl	#CACHE_OFF,%d0			| 68020/030 cache clear
    933 	jra	Lend_cpuset			| skip to init.
    934 Ltestfor040:
    935 	movl	#CACHE_OFF,%d0			| 68020/030 cache
    936 	movl	#ATARI_68040,%d1
    937 	andl	%d2,%d1
    938 	jeq	Ltestfor060
    939 	movl	#MMU_68040,_C_LABEL(mmutype)	| Use a 68040 MMU
    940 	movl	#CPU_68040,_C_LABEL(cputype)	|   and a 68040 CPU
    941 	.word	0xf4f8				| cpusha bc - push&inval caches
    942 	movl	#CACHE40_OFF,%d0		| 68040 cache disable
    943 	jra	Lend_cpuset			| skip to init.
    944 Ltestfor060:
    945 	movl    #ATARI_68060,%d1
    946 	andl	%d2,%d1
    947 	jeq	Lend_cpuset
    948 	movl	#MMU_68040,_C_LABEL(mmutype)	| Use a 68040 MMU
    949 	movl	#CPU_68060,_C_LABEL(cputype)	|   and a 68060 CPU
    950 	.word	0xf4f8				| cpusha bc - push&inval caches
    951 	movl	#CACHE40_OFF,%d0		| 68040 cache disable
    952 	orl	#IC60_CABC,%d0			|   and clear  060 branch cache
    953 
    954 Lend_cpuset:
    955 	movc	%d0,%cacr		| clear and disable on-chip cache(s)
    956 	movl	#_C_LABEL(vectab),%a0	| set address of vector table
    957 	movc	%a0,%vbr
    958 
    959 	/*
    960 	 * Initialize source/destination control registers for movs
    961 	 */
    962 	moveq	#FC_USERD,%d0		| user space
    963 	movc	%d0,%sfc		|   as source
    964 	movc	%d0,%dfc		|   and destination of transfers
    965 
    966 	/*
    967 	 * let the C function initialize everything and enable the MMU
    968 	 */
    969 	jsr	_C_LABEL(start_c)
    970 
    971 	/*
    972 	 * set kernel stack, user SP
    973 	 */
    974 	movl	_C_LABEL(lwp0uarea),%a1	| grab lwp0 uarea
    975 	lea	%a1@(USPACE-4),%sp	| set kernel stack to end of area
    976 	movl	#USRSTACK-4,%a2
    977 	movl	%a2,%usp		| init user SP
    978 	movl	%a2,%a1@(PCB_USP)	| and save it
    979 	clrw	%a1@(PCB_FLAGS)		| clear flags
    980 
    981 	/* flush TLB and turn on caches */
    982 	jbsr	_C_LABEL(_TBIA)		|  invalidate TLB
    983 	movl	#CACHE_ON,%d0
    984 	cmpl	#MMU_68040,_C_LABEL(mmutype)
    985 	jne	Lcacheon
    986 	/*  is this needed? MLH */
    987 	.word	0xf4f8			|  cpusha bc - push & invalidate caches
    988 	movl	#CACHE40_ON,%d0
    989 #ifdef M68060
    990 	cmpl	#CPU_68060,_C_LABEL(cputype)
    991 	jne	Lcacheon
    992 	movl	#CACHE60_ON,%d0
    993 #endif
    994 Lcacheon:
    995 	movc	%d0,%cacr		|  clear cache(s)
    996 
    997 	/*
    998 	 * Final setup for C code
    999 	 */
   1000 #ifdef notdef
   1001 	movl	%d6,_C_LABEL(bootdev)	|    and boot device
   1002 #endif
   1003 
   1004 	/*
   1005 	 * Create a fake exception frame that returns to user mode,
   1006 	 * make space for the rest of a fake saved register set, and
   1007 	 * pass a pointer to the register set to "main()".
   1008 	 * "main()" will call "icode()", which fakes
   1009 	 * an "execve()" system call, which is why we need to do that
   1010 	 * ("main()" sets "u.u_ar0" to point to the register set).
   1011 	 * When "main()" returns, we're running in process 1 and have
   1012 	 * successfully faked the "execve()".  We load up the registers from
   1013 	 * that set; the "rte" loads the PC and PSR, which jumps to "init".
   1014 	 */
   1015 	movl	#0,%a6			|  make DDB stack_trace() work
   1016 	clrw	%sp@-			|  vector offset/frame type
   1017 	clrl	%sp@-			|  PC - filled in by "execve"
   1018 	movw	#PSL_USER,%sp@-		|  in user mode
   1019 	clrl	%sp@-			|  stack adjust count
   1020 	lea	%sp@(-64),%sp		|  construct space for D0-D7/A0-A7
   1021 	lea	_C_LABEL(lwp0),%a0	| lwp0 in a0
   1022 	movl	%sp,%a0@(L_MD_REGS)     | save frame for lwp0
   1023 	movl	%usp,%a1
   1024 	movl	%a1,%sp@(FR_SP)		| save user stack pointer in frame
   1025 	pea	%sp@			|  addr of space for D0
   1026 	jbsr	_C_LABEL(main)		|  main(r0)
   1027 	addql	#4,%sp			|  pop args
   1028 	cmpl	#MMU_68040,_C_LABEL(mmutype)
   1029 	jne	Lnoflush		|  Not an 68040, skip flush
   1030 	.word	0xf478			|  cpusha dc
   1031 	.word	0xf498			|  cinva ic
   1032 Lnoflush:
   1033 	movl	%sp@(FR_SP),%a0		|  grab and load
   1034 	movl	%a0,%usp		|    user SP
   1035 	moveml	%sp@+,#0x7FFF		|  load most registers (all but SSP)
   1036 	addql	#8,%sp			|  pop SSP and stack adjust count
   1037 	rte
   1038 
   1039 /*
   1040  * Primitives
   1041  */
   1042 
   1043 /*
   1044  * non-local gotos
   1045  */
   1046 ENTRY(qsetjmp)
   1047 	movl	%sp@(4),%a0		|  savearea pointer
   1048 	lea	%a0@(40),%a0		|  skip regs we do not save
   1049 	movl	%a6,%a0@+		|  save FP
   1050 	movl	%sp,%a0@+		|  save SP
   1051 	movl	%sp@,%a0@		|  and return address
   1052 	moveq	#0,%d0			|  return 0
   1053 	rts
   1054 
   1055 /*
   1056  * Use common m68k process/lwp switch and context save subroutines.
   1057  */
   1058 #define FPCOPROC
   1059 #include <m68k/m68k/switch_subr.s>
   1060 
   1061 
   1062 #if defined(M68040)
   1063 ENTRY(suline)
   1064 	movl	%sp@(4),%a0		| address to write
   1065 	movl	_C_LABEL(curpcb),%a1	| current pcb
   1066 	movl	#Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault
   1067 	movl	%sp@(8),%a1		| address of line
   1068 	movl	%a1@+,%d0		| get lword
   1069 	movsl	%d0,%a0@+		| put lword
   1070 	nop				| sync
   1071 	movl	%a1@+,%d0		| get lword
   1072 	movsl	%d0,%a0@+		| put lword
   1073 	nop				| sync
   1074 	movl	%a1@+,%d0		| get lword
   1075 	movsl	%d0,%a0@+		| put lword
   1076 	nop				| sync
   1077 	movl	%a1@+,%d0		| get lword
   1078 	movsl	%d0,%a0@+		| put lword
   1079 	nop				| sync
   1080 	moveq	#0,%d0			| indicate no fault
   1081 	jra	Lsldone
   1082 Lslerr:
   1083 	moveq	#-1,%d0
   1084 Lsldone:
   1085 	movl	_C_LABEL(curpcb),%a1	| current pcb
   1086 	clrl	%a1@(PCB_ONFAULT)	| clear fault address
   1087 	rts
   1088 #endif /* defined(M68040) */
   1089 
   1090 ENTRY(ecacheon)
   1091 	rts
   1092 
   1093 ENTRY(ecacheoff)
   1094 	rts
   1095 
   1096 /*
   1097  * Check out a virtual address to see if it's okay to write to.
   1098  *
   1099  * probeva(va, fc)
   1100  *
   1101  */
   1102 ENTRY(probeva)
   1103 	movl	%sp@(8),%d0
   1104 	movec	%d0,%dfc
   1105 	movl	%sp@(4),%a0
   1106 	.word	0xf548			|  ptestw (a0)
   1107 	moveq	#FC_USERD,%d0		|  restore DFC to user space
   1108 	movc	%d0,%dfc
   1109 	.word	0x4e7a,0x0805		|  movec  MMUSR,d0
   1110 	rts
   1111 
   1112 /*
   1113  * Set processor priority level calls.  Most are implemented with
   1114  * inline asm expansions.  However, spl0 requires special handling
   1115  * as we need to check for our emulated software interrupts.
   1116  */
   1117 
   1118 ENTRY(spl0)
   1119 	moveq	#0,%d0
   1120 	movw	%sr,%d0			|  get old SR for return
   1121 	movw	#PSL_LOWIPL,%sr		|  restore new SR
   1122 	tstb	_C_LABEL(ssir)		|  software interrupt pending?
   1123 	jeq	Lspldone		|  no, all done
   1124 	subql	#4,%sp			|  make room for RTE frame
   1125 	movl	%sp@(4),%sp@(2)		|  position return address
   1126 	clrw	%sp@(6)			|  set frame type 0
   1127 	movw	#PSL_LOWIPL,%sp@	|  and new SR
   1128 	jra	Lgotsir			|  go handle it
   1129 Lspldone:
   1130 	rts
   1131 
   1132 /*
   1133  * Handle the nitty-gritty of rebooting the machine.
   1134  *
   1135  */
   1136 ENTRY_NOPROFILE(doboot)
   1137 	movl	#CACHE_OFF,%d0
   1138 	cmpl	#MMU_68040,_C_LABEL(mmutype) |  is it 68040?
   1139 	jne	Ldoboot0
   1140 	.word	0xf4f8			|  cpusha bc - push and inval caches
   1141 	nop
   1142 	movl	#CACHE40_OFF,%d0
   1143 Ldoboot0:
   1144 	movc	%d0,%cacr		|  disable on-chip cache(s)
   1145 
   1146 	movw	#0x2700,%sr		|  cut off any interrupts
   1147 
   1148 	/*
   1149 	 * Clear first 2k of ST-memory. We start clearing at address 0x8
   1150 	 * because the lower 8 bytes are mapped to ROM.
   1151 	 * This makes sure that the machine will 'cold-boot'.
   1152 	 */
   1153 	movl	_C_LABEL(page_zero),%a0
   1154 	addl	#0x8,%a0
   1155 	movl	#512,%d0
   1156 Ldb1:
   1157 	clrl	%a0@+
   1158 	dbra	%d0,Ldb1
   1159 
   1160 	lea	Ldoreboot,%a1		| a1 = start of copy range
   1161 	lea	Ldorebootend,%a2	| a2 = end of copy range
   1162 	movl	_C_LABEL(page_zero),%a0	| a0 = virtual base for page zero
   1163 	addl	%a1,%a0			|		+ offset of Ldoreboot
   1164 Ldb2:					| Do the copy
   1165 	movl	%a1@+,%a0@+
   1166 	cmpl	%a2,%a1
   1167 	jle	Ldb2
   1168 
   1169 	/*
   1170 	 * Ok, turn off MMU..
   1171 	 */
   1172 Ldoreboot:
   1173 	cmpl	#MMU_68040,_C_LABEL(mmutype)
   1174 	jeq	Lmmuoff040		| Go turn off 68040 MMU
   1175 	lea	_ASM_LABEL(zero),%a0
   1176 	pmove	%a0@,%tc		| Turn off MMU
   1177 	lea	_ASM_LABEL(nullrp),%a0
   1178 	pmove	%a0@,%crp		| Invalidate CPU root pointer
   1179 	pmove	%a0@,%srp		|  and the Supervisor root pointer
   1180 	jra	Ldoboot1		| Ok, continue with actual reboot
   1181 Lmmuoff040:
   1182 	movl	#0,%d0
   1183 	.word	0x4e7b,0x0003		|  movc d0,TC
   1184 	.word	0x4e7b,0x0806		|  movc d0,URP
   1185 	.word	0x4e7b,0x0807		|  movc d0,SRP
   1186 
   1187 Ldoboot1:
   1188 	movl	#0, %a0
   1189 	movc	%a0,%vbr
   1190 	movl	%a0@(4), %a0		| fetch reset-vector
   1191 	jmp	%a0@			| jump through it
   1192 	/* NOTREACHED */
   1193 
   1194 /*  A do-nothing MMU root pointer (includes the following long as well) */
   1195 
   1196 ASLOCAL(nullrp)
   1197 	.long	0x7fff0001
   1198 ASLOCAL(zero)
   1199 	.long	0
   1200 Ldorebootend:
   1201 
   1202 	.data
   1203 	.p2align 2
   1204 	.space	PAGE_SIZE
   1205 ASLOCAL(tmpstk)
   1206 
   1207 #ifdef M68060 /* XXX */
   1208 L60iem:		.long	0
   1209 L60fpiem:	.long	0
   1210 L60fpdem:	.long	0
   1211 L60fpeaem:	.long	0
   1212 L60bpe:		.long	0
   1213 #endif
   1214 #ifdef DEBUG
   1215 
   1216 ASLOCAL(fulltflush)
   1217 	.long	0
   1218 ASLOCAL(fullcflush)
   1219 	.long	0
   1220 GLOBAL(timebomb)
   1221 	.long	0
   1222 #endif
   1223 ASLOCAL(plx_nonmi)
   1224 	.long	0
   1225 GLOBAL(plx_status)
   1226 	.long	0
   1227 
   1228 /* interrupt counters & names */
   1229 #include <atari/atari/intrcnt.h>
   1230