Home | History | Annotate | Line # | Download | only in sun3
      1 /*	$NetBSD: locore.s,v 1.110 2024/01/17 12:33:50 thorpej 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  *	@(#)locore.s	8.6 (Berkeley) 5/27/94
     37  */
     38 
     39 /*
     40  * Copyright (c) 1994, 1995 Gordon W. Ross
     41  * Copyright (c) 1993 Adam Glass
     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  *	@(#)locore.s	8.6 (Berkeley) 5/27/94
     78  */
     79 
     80 #include "opt_compat_netbsd.h"
     81 #include "opt_compat_sunos.h"
     82 #include "opt_kgdb.h"
     83 #include "opt_lockdebug.h"
     84 
     85 #include "assym.h"
     86 #include <machine/asm.h>
     87 #include <machine/trap.h>
     88 
     89 | Remember this is a fun project!
     90 
     91 | This is for kvm_mkdb, and should be the address of the beginning
     92 | of the kernel text segment (not necessarily the same as kernbase).
     93 	.text
     94 GLOBAL(kernel_text)
     95 
     96 | This is the entry point, as well as the end of the temporary stack
     97 | used during process switch (one 8K page ending at start)
     98 ASGLOBAL(tmpstk)
     99 ASGLOBAL(start)
    100 
    101 | First we need to set it up so we can access the sun MMU, and be otherwise
    102 | undisturbed.  Until otherwise noted, all code must be position independent
    103 | as the boot loader put us low in memory, but we are linked high.
    104 	movw	#PSL_HIGHIPL,%sr	| no interrupts
    105 	moveq	#FC_CONTROL,%d0		| make movs access "control"
    106 	movc	%d0,%sfc		| space where the sun3 designers
    107 	movc	%d0,%dfc		| put all the "useful" stuff
    108 
    109 | Set context zero and stay there until pmap_bootstrap.
    110 	moveq	#0,%d0
    111 	movsb	%d0,CONTEXT_REG
    112 
    113 | In order to "move" the kernel to high memory, we are going to copy the
    114 | first 4 Mb of pmegs such that we will be mapped at the linked address.
    115 | This is all done by copying in the segment map (top-level MMU table).
    116 | We will unscramble which PMEGs we actually need later.
    117 
    118 	movl	#(SEGMAP_BASE+0),%a0		| src
    119 	movl	#(SEGMAP_BASE+KERNBASE3),%a1	| dst
    120 	movl	#(0x400000/NBSG),%d0		| count
    121 
    122 L_per_pmeg:
    123 	movsb	%a0@,%d1		| copy segmap entry
    124 	movsb	%d1,%a1@
    125 	addl	#NBSG,%a0		| increment pointers
    126 	addl	#NBSG,%a1
    127 	subql	#1,%d0			| decrement count
    128 	bgt	L_per_pmeg
    129 
    130 | Kernel is now double mapped at zero and KERNBASE.
    131 | Force a long jump to the relocated code (high VA).
    132 	movl	#IC_CLEAR,%d0		| Flush the I-cache
    133 	movc	%d0,%cacr
    134 	jmp	L_high_code:l		| long jump
    135 
    136 L_high_code:
    137 | We are now running in the correctly relocated kernel, so
    138 | we are no longer restricted to position-independent code.
    139 
    140 | Do bootstrap stuff needed before main() gets called.
    141 | Make sure the initial frame pointer is zero so that
    142 | the backtrace algorithm used by KGDB terminates nicely.
    143 	lea	_ASM_LABEL(tmpstk),%sp
    144 	movl	#0,%a6
    145 	jsr	_C_LABEL(_bootstrap)	| See locore2.c
    146 
    147 | Now that _bootstrap() is done using the PROM functions,
    148 | we can safely set the %sfc/dfc to something != FC_CONTROL
    149 	moveq	#FC_USERD,%d0		| make movs access "user data"
    150 	movc	%d0,%sfc		| space for copyin/copyout
    151 	movc	%d0,%dfc
    152 
    153 | Setup process zero user/kernel stacks.
    154 	lea	_C_LABEL(lwp0),%a0	| lwp0
    155 	movl	%a0@(L_PCB),%a1		| XXXuvm_lwp_getuarea
    156 	lea	%a1@(USPACE-4),%sp	| set SSP to last word
    157 	movl	#USRSTACK3-4,%a2
    158 	movl	%a2,%usp		| init user SP
    159 
    160 | Note curpcb was already set in _bootstrap().
    161 | Will do fpu initialization during autoconfig (see fpu.c)
    162 | The interrupt vector table and stack are now ready.
    163 | Interrupts will be enabled later, AFTER  autoconfiguration
    164 | is finished, to avoid spurrious interrupts.
    165 
    166 /*
    167  * Create a fake exception frame so that cpu_lwp_fork() can copy it.
    168  * main() nevers returns; we exit to user mode from a forked process
    169  * later on.
    170  */
    171 	clrw	%sp@-			| tf_format,tf_vector
    172 	clrl	%sp@-			| tf_pc (filled in later)
    173 	movw	#PSL_USER,%sp@-		| tf_sr for user mode
    174 	clrl	%sp@-			| tf_stackadj
    175 	lea	%sp@(-64),%sp		| tf_regs[16]
    176 	movl	%a1,%a0@(L_MD_REGS)	| lwp0.p_md.md_regs = trapframe
    177 	jbsr	_C_LABEL(main)		| main(&trapframe)
    178 	PANIC("main() returned")
    179 
    180 | That is all the assembly startup code we need on the sun3!
    181 | The rest of this is like the hp300/locore.s where possible.
    182 
    183 /*
    184  * Trap/interrupt vector routines
    185  */
    186 #include <m68k/m68k/trap_subr.s>
    187 
    188 GLOBAL(buserr)
    189 	tstl	_C_LABEL(nofault)	| device probe?
    190 	jeq	_C_LABEL(addrerr)	| no, handle as usual
    191 	movl	_C_LABEL(nofault),%sp@-	| yes,
    192 	jbsr	_C_LABEL(longjmp)	|  longjmp(nofault)
    193 GLOBAL(addrerr)
    194 	clrl	%sp@-			| stack adjust count
    195 	moveml	#0xFFFF,%sp@-		| save user registers
    196 	movl	%usp,%a0		| save the user SP
    197 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    198 	lea	%sp@(FR_HW),%a1		| grab base of HW berr frame
    199 	moveq	#0,%d0
    200 	movw	%a1@(10),%d0		| grab SSW for fault processing
    201 	btst	#12,%d0			| RB set?
    202 	jeq	LbeX0			| no, test RC
    203 	bset	#14,%d0			| yes, must set FB
    204 	movw	%d0,%a1@(10)		| for hardware too
    205 LbeX0:
    206 	btst	#13,%d0			| RC set?
    207 	jeq	LbeX1			| no, skip
    208 	bset	#15,%d0			| yes, must set FC
    209 	movw	%d0,%a1@(10)		| for hardware too
    210 LbeX1:
    211 	btst	#8,%d0			| data fault?
    212 	jeq	Lbe0			| no, check for hard cases
    213 	movl	%a1@(16),%d1		| fault address is as given in frame
    214 	jra	Lbe10			| thats it
    215 Lbe0:
    216 	btst	#4,%a1@(6)		| long (type B) stack frame?
    217 	jne	Lbe4			| yes, go handle
    218 	movl	%a1@(2),%d1		| no, can use save PC
    219 	btst	#14,%d0			| FB set?
    220 	jeq	Lbe3			| no, try FC
    221 	addql	#4,%d1			| yes, adjust address
    222 	jra	Lbe10			| done
    223 Lbe3:
    224 	btst	#15,%d0			| FC set?
    225 	jeq	Lbe10			| no, done
    226 	addql	#2,%d1			| yes, adjust address
    227 	jra	Lbe10			| done
    228 Lbe4:
    229 	movl	%a1@(36),%d1		| long format, use stage B address
    230 	btst	#15,%d0			| FC set?
    231 	jeq	Lbe10			| no, all done
    232 	subql	#2,%d1			| yes, adjust address
    233 Lbe10:
    234 	movl	%d1,%sp@-		| push fault VA
    235 	movl	%d0,%sp@-		| and padded SSW
    236 	movw	%a1@(6),%d0		| get frame format/vector offset
    237 	andw	#0x0FFF,%d0		| clear out frame format
    238 	cmpw	#12,%d0			| address error vector?
    239 	jeq	Lisaerr			| yes, go to it
    240 
    241 /*
    242  * the sun3 specific code
    243  *
    244  * our mission: figure out whether what we are looking at is
    245  *              bus error in the UNIX sense, or
    246  *	        a memory error i.e a page fault
    247  *
    248  * [this code replaces similarly mmu specific code in the hp300 code]
    249  */
    250 sun3_mmu_specific:
    251 	clrl %d0			| make sure top bits are cleared too
    252 	movl %d1,%sp@-			| save %d1
    253 	movc %sfc,%d1			| save %sfc to %d1
    254 	moveq #FC_CONTROL,%d0		| %sfc = FC_CONTROL
    255 	movc %d0,%sfc
    256 	movsb BUSERR_REG,%d0		| get value of bus error register
    257 	movc %d1,%sfc			| restore %sfc
    258 	movl %sp@+,%d1			| restore %d1
    259 	andb #BUSERR_MMU,%d0		| is this an MMU fault?
    260 	jeq Lisberr			| non-MMU bus error
    261 /* End of sun3 specific code. */
    262 
    263 Lismerr:
    264 	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
    265 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    266 Lisaerr:
    267 	movl	#T_ADDRERR,%sp@-	| mark address error
    268 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    269 Lisberr:
    270 	movl	#T_BUSERR,%sp@-		| mark bus error
    271 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    272 
    273 /*
    274  * FP exceptions.
    275  */
    276 GLOBAL(fpfline)
    277 	clrl	%sp@-			| stack adjust count
    278 	moveml	#0xFFFF,%sp@-		| save registers
    279 	moveq	#T_FPEMULI,%d0		| denote as FP emulation trap
    280 	jra	_ASM_LABEL(fault)	| do it
    281 
    282 GLOBAL(fpunsupp)
    283 	clrl	%sp@-			| stack adjust count
    284 	moveml	#0xFFFF,%sp@-		| save registers
    285 	moveq	#T_FPEMULD,%d0		| denote as FP emulation trap
    286 	jra	_ASM_LABEL(fault)	| do it
    287 
    288 /*
    289  * Handles all other FP coprocessor exceptions.
    290  * Note that since some FP exceptions generate mid-instruction frames
    291  * and may cause signal delivery, we need to test for stack adjustment
    292  * after the trap call.
    293  */
    294 GLOBAL(fpfault)
    295 	clrl	%sp@-		| stack adjust count
    296 	moveml	#0xFFFF,%sp@-	| save user registers
    297 	movl	%usp,%a0	| and save
    298 	movl	%a0,%sp@(FR_SP)	|   the user stack pointer
    299 	clrl	%sp@-		| no VA arg
    300 	movl	_C_LABEL(curpcb),%a0	| current pcb
    301 	lea	%a0@(PCB_FPCTX),%a0 | address of FP savearea
    302 	fsave	%a0@		| save state
    303 	tstb	%a0@		| null state frame?
    304 	jeq	Lfptnull	| yes, safe
    305 	clrw	%d0		| no, need to tweak BIU
    306 	movb	%a0@(1),%d0	| get frame size
    307 	bset	#3,%a0@(0,%d0:w) | set exc_pend bit of BIU
    308 Lfptnull:
    309 	fmovem	%fpsr,%sp@-	| push fpsr as code argument
    310 	frestore %a0@		| restore state
    311 	movl	#T_FPERR,%sp@-	| push type arg
    312 	jra	_ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup
    313 
    314 /*
    315  * Other exceptions only cause four and six word stack frame and require
    316  * no post-trap stack adjustment.
    317  */
    318 GLOBAL(badtrap)
    319 	clrl	%sp@-			| stack adjust count
    320 	moveml	#0xFFFF,%sp@-		| save std frame regs
    321 	jbsr	_C_LABEL(straytrap)	| report
    322 	moveml	%sp@+,#0xFFFF		| restore regs
    323 	addql	#4,%sp			| stack adjust count
    324 	jra	_ASM_LABEL(rei)		| all done
    325 
    326 /*
    327  * Trap 0 is for system calls
    328  */
    329 GLOBAL(trap0)
    330 	clrl	%sp@-			| stack adjust count
    331 	moveml	#0xFFFF,%sp@-		| save user registers
    332 	movl	%usp,%a0		| save the user SP
    333 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    334 	movl	%d0,%sp@-		| push syscall number
    335 	jbsr	_C_LABEL(syscall)	| handle it
    336 	addql	#4,%sp			| pop syscall arg
    337 	movl	%sp@(FR_SP),%a0		| grab and restore
    338 	movl	%a0,%usp		|   user SP
    339 	moveml	%sp@+,#0x7FFF		| restore most registers
    340 	addql	#8,%sp			| pop SP and stack adjust
    341 	jra	_ASM_LABEL(rei)		| all done
    342 
    343 /*
    344  * Trap 12 is the entry point for the cachectl "syscall"
    345  *	cachectl(command, addr, length)
    346  * command in %d0, addr in %a1, length in %d1
    347  */
    348 GLOBAL(trap12)
    349 	movl	_C_LABEL(curlwp),%a0
    350 	movl	%a0@(L_PROC),%sp@-	| push curproc pointer
    351 	movl	%d1,%sp@-		| push length
    352 	movl	%a1,%sp@-		| push addr
    353 	movl	%d0,%sp@-		| push command
    354 	jbsr	_C_LABEL(cachectl1)	| do it
    355 	lea	%sp@(16),%sp		| pop args
    356 	jra	_ASM_LABEL(rei)		| all done
    357 
    358 /*
    359  * Trace (single-step) trap.  Kernel-mode is special.
    360  * User mode traps are simply passed on to trap().
    361  */
    362 GLOBAL(trace)
    363 	clrl	%sp@-			| stack adjust count
    364 	moveml	#0xFFFF,%sp@-
    365 	moveq	#T_TRACE,%d0
    366 
    367 	| Check PSW and see what happen.
    368 	|   T=0 S=0	(should not happen)
    369 	|   T=1 S=0	trace trap from user mode
    370 	|   T=0 S=1	trace trap on a trap instruction
    371 	|   T=1 S=1	trace trap from system mode (kernel breakpoint)
    372 
    373 	movw	%sp@(FR_HW),%d1		| get PSW
    374 	notw	%d1			| XXX no support for T0 on 680[234]0
    375 	andw	#PSL_TS,%d1		| from system mode (T=1, S=1)?
    376 	jeq	_ASM_LABEL(kbrkpt)	|  yes, kernel brkpt
    377 	jra	_ASM_LABEL(fault)	| no, user-mode fault
    378 
    379 /*
    380  * Trap 15 is used for:
    381  *	- GDB breakpoints (in user programs)
    382  *	- KGDB breakpoints (in the kernel)
    383  *	- trace traps for SUN binaries (not fully supported yet)
    384  * User mode traps are simply passed to trap().
    385  */
    386 GLOBAL(trap15)
    387 	clrl	%sp@-			| stack adjust count
    388 	moveml	#0xFFFF,%sp@-
    389 	moveq	#T_TRAP15,%d0
    390 	btst	#5,%sp@(FR_HW)		| was supervisor mode?
    391 	jne	_ASM_LABEL(kbrkpt)	|  yes, kernel brkpt
    392 	jra	_ASM_LABEL(fault)	| no, user-mode fault
    393 
    394 ASLOCAL(kbrkpt)
    395 	| Kernel-mode breakpoint or trace trap. (%d0=trap_type)
    396 	| Save the system sp rather than the user sp.
    397 	movw	#PSL_HIGHIPL,%sr	| lock out interrupts
    398 	lea	%sp@(FR_SIZE),%a6	| Save stack pointer
    399 	movl	%a6,%sp@(FR_SP)		|  from before trap
    400 
    401 	| If we are not on tmpstk switch to it.
    402 	| (so debugger can change the stack pointer)
    403 	movl	%a6,%d1
    404 	cmpl	#_ASM_LABEL(tmpstk),%d1
    405 	jls	Lbrkpt2			| already on tmpstk
    406 	| Copy frame to the temporary stack
    407 	movl	%sp,%a0			| %a0=src
    408 	lea	_ASM_LABEL(tmpstk)-96,%a1	| %a1=dst
    409 	movl	%a1,%sp			| sp=new frame
    410 	moveq	#FR_SIZE,%d1
    411 Lbrkpt1:
    412 	movl	%a0@+,%a1@+
    413 	subql	#4,%d1
    414 	bgt	Lbrkpt1
    415 
    416 Lbrkpt2:
    417 	| Call the trap handler for the kernel debugger.
    418 	| Do not call trap() to handle it, so that we can
    419 	| set breakpoints in trap() if we want.  We know
    420 	| the trap type is either T_TRACE or T_BREAKPOINT.
    421 	movl	%d0,%sp@-		| push trap type
    422 	jbsr	_C_LABEL(trap_kdebug)
    423 	addql	#4,%sp			| pop args
    424 
    425 	| The stack pointer may have been modified, or
    426 	| data below it modified (by kgdb push call),
    427 	| so push the hardware frame at the current sp
    428 	| before restoring registers and returning.
    429 	movl	%sp@(FR_SP),%a0		| modified sp
    430 	lea	%sp@(FR_SIZE),%a1	| end of our frame
    431 	movl	%a1@-,%a0@-		| copy 2 longs with
    432 	movl	%a1@-,%a0@-		| ... predecrement
    433 	movl	%a0,%sp@(FR_SP)		| sp = h/w frame
    434 	moveml	%sp@+,#0x7FFF		| restore all but sp
    435 	movl	%sp@,%sp		| ... and sp
    436 	rte				| all done
    437 
    438 /*
    439  * Interrupt handlers.  Most are auto-vectored,
    440  * and hard-wired the same way on all sun3 models.
    441  * Format in the stack is:
    442  *   %d0,%d1,%a0,%a1, sr, pc, vo
    443  */
    444 
    445 /* clock: see clock.c */
    446 #ifdef __ELF__
    447 	.align	4
    448 #else
    449 	.align	2
    450 #endif
    451 GLOBAL(_isr_clock)
    452 	INTERRUPT_SAVEREG
    453 	jbsr	_C_LABEL(clock_intr)
    454 	INTERRUPT_RESTOREREG
    455 	jra	_ASM_LABEL(rei)
    456 
    457 /*
    458  * Emulation of VAX REI instruction.
    459  *
    460  * This code is (mostly) un-altered from the hp300 code,
    461  * except that sun machines do not need a simulated SIR
    462  * because they have a real software interrupt register.
    463  *
    464  * This code deals with checking for and servicing ASTs
    465  * (profiling, scheduling) and software interrupts (network, softclock).
    466  * We check for ASTs first, just like the VAX.  To avoid excess overhead
    467  * the T_ASTFLT handling code will also check for software interrupts so we
    468  * do not have to do it here.  After identifying that we need an AST we
    469  * drop the IPL to allow device interrupts.
    470  *
    471  * This code is complicated by the fact that sendsig may have been called
    472  * necessitating a stack cleanup.
    473  */
    474 
    475 ASGLOBAL(rei)
    476 #ifdef	DIAGNOSTIC
    477 	tstl	_C_LABEL(panicstr)	| have we panicked?
    478 	jne	Ldorte			| yes, do not make matters worse
    479 #endif
    480 	tstl	_C_LABEL(astpending)	| AST pending?
    481 	jeq	Ldorte			| no, done
    482 Lrei1:
    483 	btst	#5,%sp@			| yes, are we returning to user mode?
    484 	jne	Ldorte			| no, done
    485 	movw	#PSL_LOWIPL,%sr		| lower SPL
    486 	clrl	%sp@-			| stack adjust
    487 	moveml	#0xFFFF,%sp@-		| save all registers
    488 	movl	%usp,%a1		| including
    489 	movl	%a1,%sp@(FR_SP)		|    the users SP
    490 	clrl	%sp@-			| VA == none
    491 	clrl	%sp@-			| code == none
    492 	movl	#T_ASTFLT,%sp@-		| type == async system trap
    493 	pea	%sp@(12)		| fp == address of trap frame
    494 	jbsr	_C_LABEL(trap)		| go handle it
    495 	lea	%sp@(16),%sp		| pop value args
    496 	movl	%sp@(FR_SP),%a0		| restore user SP
    497 	movl	%a0,%usp		|   from save area
    498 	movw	%sp@(FR_ADJ),%d0	| need to adjust stack?
    499 	jne	Laststkadj		| yes, go to it
    500 	moveml	%sp@+,#0x7FFF		| no, restore most user regs
    501 	addql	#8,%sp			| toss SP and stack adjust
    502 	rte				| and do real RTE
    503 Laststkadj:
    504 	lea	%sp@(FR_HW),%a1		| pointer to HW frame
    505 	addql	#8,%a1			| source pointer
    506 	movl	%a1,%a0			| source
    507 	addw	%d0,%a0			|  + hole size = dest pointer
    508 	movl	%a1@-,%a0@-		| copy
    509 	movl	%a1@-,%a0@-		|  8 bytes
    510 	movl	%a0,%sp@(FR_SP)		| new SSP
    511 	moveml	%sp@+,#0x7FFF		| restore user registers
    512 	movl	%sp@,%sp		| and our SP
    513 Ldorte:
    514 	rte				| real return
    515 
    516 /*
    517  * Initialization is at the beginning of this file, because the
    518  * kernel entry point needs to be at zero for compatibility with
    519  * the Sun boot loader.  This works on Sun machines because the
    520  * interrupt vector table for reset is NOT at address zero.
    521  * (The MMU has a "boot" bit that forces access to the PROM)
    522  */
    523 
    524 /*
    525  * Primitives
    526  */
    527 
    528 /*
    529  * Use common m68k process/lwp switch and context save subroutines.
    530  */
    531 #define FPCOPROC	/* XXX: Temp. Reqd. */
    532 #include <m68k/m68k/switch_subr.s>
    533 
    534 
    535 /* suline() */
    536 /* TBIA, TBIS, TBIAS, TBIAU */
    537 
    538 /*
    539  * Invalidate instruction cache
    540  */
    541 ENTRY(ICIA)
    542 	movl	#IC_CLEAR,%d0
    543 	movc	%d0,%cacr		| invalidate i-cache
    544 	rts
    545 
    546 /* DCIA, DCIS */
    547 
    548 /*
    549  * Invalidate data cache.
    550  */
    551 ENTRY(DCIU)
    552 	rts
    553 
    554 /* ICPL, ICPP, DCPL, DCPP, DCPA, DCFL, DCFP */
    555 /* PCIA, ecacheon, ecacheoff */
    556 
    557 /* loadustp, ptest_addr */
    558 
    559 /*
    560  * _delay(unsigned N)
    561  * Delay for at least (N/256) microseconds.
    562  * This routine depends on the variable:  delay_divisor
    563  * which should be set based on the CPU clock rate.
    564  * XXX: Currently this is set based on the CPU model,
    565  * XXX: but this should be determined at run time...
    566  */
    567 GLOBAL(_delay)
    568 	| %d0 = arg = (usecs << 8)
    569 	movl	%sp@(4),%d0
    570 	| %d1 = delay_divisor;
    571 	movl	_C_LABEL(delay_divisor),%d1
    572 	jra	L_delay			/* Jump into the loop! */
    573 
    574 	/*
    575 	 * Align the branch target of the loop to a half-line (8-byte)
    576 	 * boundary to minimize cache effects.  This guarantees both
    577 	 * that there will be no prefetch stalls due to cache line burst
    578 	 * operations and that the loop will run from a single cache
    579 	 * half-line.
    580 	 */
    581 #ifdef __ELF__
    582 	.align	8
    583 #else
    584 	.align	3
    585 #endif
    586 L_delay:
    587 	subl	%d1,%d0
    588 	jgt	L_delay
    589 	rts
    590 
    591 /*
    592  * void set_segmap_allctx(vaddr_t va, int sme)
    593  */
    594 ENTRY(set_segmap_allctx)
    595 	linkw	%fp,#0
    596 	moveml	#0x3000,%sp@-
    597 	movl	8(%fp),%d3		| d3 = va
    598 	andl	#0xffffffc,%d3
    599 	bset	#29,%d3
    600 	movl	%d3,%a1			| a1 = ctrladdr, d3 avail
    601 	movl	12(%fp),%d1		| d1 = sme
    602 	moveq	#FC_CONTROL,%d0
    603 	movl	#CONTEXT_REG,%a0	| a0 = ctxreg
    604 	movc	%sfc,%d3		| d3 = oldsfc
    605 	movc	%d0,%sfc
    606 	movsb	%a0@,%d2
    607 	andi	#7,%d2			| d2 = oldctx
    608 	movc	%d3,%sfc		| restore sfc, d3 avail
    609 	movc	%dfc,%d3		| d3 = olddfc
    610 	movc	%d0,%dfc
    611 	movl	#(CONTEXT_NUM - 1),%d0	| d0 = ctx number
    612 1:
    613 	movsb	%d0,%a0@		| change to ctx
    614 	movsb	%d1,%a1@		| set segmap
    615 	dbf	%d0,1b			| loop setting each ctx
    616 	movsb	%d2,%a0@		| restore ctx
    617 	movc	%d3,%dfc		| restore dfc
    618 	moveml	%sp@+,#0x000c
    619 	unlk	%fp
    620 	rts
    621 
    622 | Define some addresses, mostly so DDB can print useful info.
    623 | Not using _C_LABEL() here because these symbols are never
    624 | referenced by any C code, and if the leading underscore
    625 | ever goes away, these lines turn into syntax errors...
    626 	.set	_KERNBASE3,KERNBASE3
    627 	.set	_MONSTART,SUN3_MONSTART
    628 	.set	_PROM_BASE,SUN3_PROM_BASE
    629 	.set	_MONEND,SUN3_MONEND
    630 
    631 |The end!
    632