Home | History | Annotate | Line # | Download | only in sun2
      1 /*	$NetBSD: locore.s,v 1.38 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) 2001 Matthew Fredette
     41  * Copyright (c) 1994, 1995 Gordon W. Ross
     42  * Copyright (c) 1993 Adam Glass
     43  * Copyright (c) 1988 University of Utah.
     44  *
     45  * This code is derived from software contributed to Berkeley by
     46  * the Systems Programming Group of the University of Utah Computer
     47  * Science Department.
     48  *
     49  * Redistribution and use in source and binary forms, with or without
     50  * modification, are permitted provided that the following conditions
     51  * are met:
     52  * 1. Redistributions of source code must retain the above copyright
     53  *    notice, this list of conditions and the following disclaimer.
     54  * 2. Redistributions in binary form must reproduce the above copyright
     55  *    notice, this list of conditions and the following disclaimer in the
     56  *    documentation and/or other materials provided with the distribution.
     57  * 3. All advertising materials mentioning features or use of this software
     58  *    must display the following acknowledgement:
     59  *	This product includes software developed by the University of
     60  *	California, Berkeley and its contributors.
     61  * 4. Neither the name of the University nor the names of its contributors
     62  *    may be used to endorse or promote products derived from this software
     63  *    without specific prior written permission.
     64  *
     65  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     66  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     67  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     68  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     69  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     70  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     71  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     72  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     73  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     74  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     75  * SUCH DAMAGE.
     76  *
     77  *	from: Utah $Hdr: locore.s 1.66 92/12/22$
     78  *	@(#)locore.s	8.6 (Berkeley) 5/27/94
     79  */
     80 
     81 #include "opt_compat_netbsd.h"
     82 #include "opt_compat_sunos.h"
     83 #include "opt_kgdb.h"
     84 #include "opt_lockdebug.h"
     85 
     86 #include "assym.h"
     87 #include <machine/asm.h>
     88 #include <machine/trap.h>
     89 
     90 | Remember this is a fun project!
     91 
     92 | This is for kvm_mkdb, and should be the address of the beginning
     93 | of the kernel text segment (not necessarily the same as kernbase).
     94 	.text
     95 GLOBAL(kernel_text)
     96 
     97 | This is the entry point, as well as the end of the temporary stack
     98 | used during process switch (two 2K pages ending at start)
     99 ASGLOBAL(tmpstk)
    100 ASGLOBAL(start)
    101 
    102 | As opposed to the sun3, on the sun2 the kernel is linked low.  The
    103 | boot loader loads us exactly where we are linked, so we don't have
    104 | to worry about writing position independent code or moving the
    105 | kernel around.
    106 	movw	#PSL_HIGHIPL,%sr	| no interrupts
    107 	moveq	#FC_CONTROL,%d0		| make movs access "control"
    108 	movc	%d0,%sfc		| space where the sun2 designers
    109 	movc	%d0,%dfc		| put all the "useful" stuff
    110 
    111 | Set context zero and stay there until pmap_bootstrap.
    112 	moveq	#0,%d0
    113 	movsb	%d0,CONTEXT_REG
    114 	movsb	%d0,SCONTEXT_REG
    115 
    116 | Jump around the g0 and g4 entry points.
    117 	jra	L_high_code
    118 
    119 | These entry points are here in pretty low memory, so that they
    120 | can be reached from virtual address zero using the classic,
    121 | old-school "g0" and "g4" commands from the monitor.  (I.e.,
    122 | they need to be reachable using 16-bit displacements from PCs
    123 | 0 and 4).
    124 ENTRY(g0_entry)
    125 	jra	_C_LABEL(g0_handler)
    126 ENTRY(g4_entry)
    127 	jra	_C_LABEL(g4_handler)
    128 
    129 L_high_code:
    130 | We are now running in the correctly relocated kernel, so
    131 | we are no longer restricted to position-independent code.
    132 
    133 | Disable interrupts, and initialize the soft copy of the
    134 | enable register.
    135 	movsw	SYSTEM_ENAB, %d0	| read the enable register
    136 	moveq	#ENA_INTS, %d1
    137 	notw	%d1
    138 	andw	%d1, %d0
    139 	movsw	%d0, SYSTEM_ENAB	| disable all interrupts
    140 	movw	%d0, _C_LABEL(enable_reg_soft)
    141 
    142 | Do bootstrap stuff needed before main() gets called.
    143 | Make sure the initial frame pointer is zero so that
    144 | the backtrace algorithm used by KGDB terminates nicely.
    145 	lea	_ASM_LABEL(tmpstk),%sp
    146 	movl	#0,%a6
    147 	jsr	_C_LABEL(_bootstrap)	| See locore2.c
    148 
    149 | Now that _bootstrap() is done using the PROM functions,
    150 | we can safely set the %sfc/dfc to something != FC_CONTROL
    151 	moveq	#FC_USERD,%d0		| make movs access "user data"
    152 	movc	%d0,%sfc		| space for copyin/copyout
    153 	movc	%d0,%dfc
    154 
    155 | Setup process zero user/kernel stacks.
    156 	lea	_C_LABEL(lwp0),%a0	| lwp0
    157 	movl	%a0@(L_PCB),%a1		| XXXuvm_lwp_getuarea
    158 	lea	%a1@(USPACE-4),%sp	| set SSP to last word
    159 	movl	#USRSTACK-4,%a2
    160 	movl	%a2,%usp		| init user SP
    161 
    162 | Note curpcb was already set in _bootstrap().
    163 | Will do fpu initialization during autoconfig (see fpu.c)
    164 | The interrupt vector table and stack are now ready.
    165 | Interrupts will be enabled later, AFTER  autoconfiguration
    166 | is finished, to avoid spurrious interrupts.
    167 
    168 /*
    169  * Create a fake exception frame so that cpu_lwp_fork() can copy it.
    170  * main() nevers returns; we exit to user mode from a forked process
    171  * later on.
    172  */
    173 	clrw	%sp@-			| tf_format,tf_vector
    174 	clrl	%sp@-			| tf_pc (filled in later)
    175 	movw	#PSL_USER,%sp@-		| tf_sr for user mode
    176 	clrl	%sp@-			| tf_stackadj
    177 	lea	%sp@(-64),%sp		| tf_regs[16]
    178 	movl	%a1,%a0@(L_MD_REGS)	| lwp0.p_md.md_regs = trapframe
    179 	jbsr	_C_LABEL(main)		| main(&trapframe)
    180 	PANIC("main() returned")
    181 
    182 | That is all the assembly startup code we need on the sun3!
    183 | The rest of this is like the hp300/locore.s where possible.
    184 
    185 /*
    186  * Trap/interrupt vector routines
    187  */
    188 #include <m68k/m68k/trap_subr.s>
    189 
    190 GLOBAL(buserr)
    191 	tstl	_C_LABEL(nofault)	| device probe?
    192 	jeq	_C_LABEL(addrerr)	| no, handle as usual
    193 	movl	_C_LABEL(nofault),%sp@-	| yes,
    194 	jbsr	_C_LABEL(longjmp)	|  longjmp(nofault)
    195 GLOBAL(addrerr)
    196 	clrl	%sp@-			| stack adjust count
    197 	moveml	#0xFFFF,%sp@-		| save user registers
    198 	movl	%usp,%a0		| save the user SP
    199 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    200 	lea	%sp@(FR_HW),%a1		| grab base of HW berr frame
    201 	moveq	#0,%d0
    202 	movw	%a1@(8),%d0		| grab SSW for fault processing
    203 	movl	%a1@(10),%d1		| fault address is as given in frame
    204 	movl	%d1,%sp@-		| push fault VA
    205 	movl	%d0,%sp@-		| and padded SSW
    206 	movw	%a1@(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 
    211 /*
    212  * the sun2 specific code
    213  *
    214  * our mission: figure out whether what we are looking at is
    215  *              bus error in the UNIX sense, or
    216  *	        a memory error i.e a page fault
    217  *
    218  * [this code replaces similarly mmu specific code in the hp300 code]
    219  */
    220 sun2_mmu_specific:
    221 	clrl %d0			| make sure top bits are cleared too
    222 	movl %d1,%sp@-			| save %d1
    223 	movc %sfc,%d1			| save %sfc to %d1
    224 	moveq #FC_CONTROL,%d0		| %sfc = FC_CONTROL
    225 	movc %d0,%sfc
    226 	movsw BUSERR_REG,%d0		| get value of bus error register
    227 	movc %d1,%sfc			| restore %sfc
    228 	movl %sp@+,%d1			| restore %d1
    229 #ifdef	DEBUG
    230 	movw %d0, _C_LABEL(buserr_reg)	| save bus error register value
    231 #endif
    232 	andb #BUSERR_PROTERR, %d0 	| is this an MMU (protection *or* page unavailable) fault?
    233 	jeq Lisberr			| non-MMU bus error
    234 /* End of sun2 specific code. */
    235 
    236 Lismerr:
    237 	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
    238 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    239 Lisaerr:
    240 	movl	#T_ADDRERR,%sp@-	| mark address error
    241 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    242 Lisberr:
    243 	movl	#T_BUSERR,%sp@-		| mark bus error
    244 	jra	_ASM_LABEL(faultstkadj)	| and deal with it
    245 
    246 /*
    247  * FP exceptions.
    248  */
    249 GLOBAL(fpfline)
    250 	clrl	%sp@-			| stack adjust count
    251 	moveml	#0xFFFF,%sp@-		| save registers
    252 	moveq	#T_FPEMULI,%d0		| denote as FP emulation trap
    253 	jra	_ASM_LABEL(fault)	| do it
    254 
    255 GLOBAL(fpunsupp)
    256 	clrl	%sp@-			| stack adjust count
    257 	moveml	#0xFFFF,%sp@-		| save registers
    258 	moveq	#T_FPEMULD,%d0		| denote as FP emulation trap
    259 	jra	_ASM_LABEL(fault)	| do it
    260 
    261 | Message for fpfault panic
    262 Lfp0:
    263 	.asciz	"fpfault"
    264 	.even
    265 
    266 /*
    267  * Handles all other FP coprocessor exceptions.
    268  * Since we can never have an FP coprocessor, this just panics.
    269  */
    270 GLOBAL(fpfault)
    271 	movl	#Lfp0,%sp@-
    272 	jbsr	_C_LABEL(panic)
    273 	/*NOTREACHED*/
    274 
    275 /*
    276  * Other exceptions only cause four and six word stack frame and require
    277  * no post-trap stack adjustment.
    278  */
    279 GLOBAL(badtrap)
    280 	clrl	%sp@-			| stack adjust count
    281 	moveml	#0xFFFF,%sp@-		| save std frame regs
    282 	jbsr	_C_LABEL(straytrap)	| report
    283 	moveml	%sp@+,#0xFFFF		| restore regs
    284 	addql	#4,%sp			| stack adjust count
    285 	jra	_ASM_LABEL(rei)		| all done
    286 
    287 /*
    288  * Trap 0 is for system calls
    289  */
    290 GLOBAL(trap0)
    291 	clrl	%sp@-			| stack adjust count
    292 	moveml	#0xFFFF,%sp@-		| save user registers
    293 	movl	%usp,%a0		| save the user SP
    294 	movl	%a0,%sp@(FR_SP)		|   in the savearea
    295 	movl	%d0,%sp@-		| push syscall number
    296 	jbsr	_C_LABEL(syscall)	| handle it
    297 	addql	#4,%sp			| pop syscall arg
    298 	movl	%sp@(FR_SP),%a0		| grab and restore
    299 	movl	%a0,%usp		|   user SP
    300 	moveml	%sp@+,#0x7FFF		| restore most registers
    301 	addql	#8,%sp			| pop SP and stack adjust
    302 	jra	_ASM_LABEL(rei)		| all done
    303 
    304 /*
    305  * Trap 12 is the entry point for the cachectl "syscall"
    306  *	cachectl(command, addr, length)
    307  * command in %d0, addr in %a1, length in %d1
    308  */
    309 GLOBAL(trap12)
    310 	jra	_ASM_LABEL(rei)		| all done
    311 
    312 /*
    313  * Trace (single-step) trap.  Kernel-mode is special.
    314  * User mode traps are simply passed on to trap().
    315  */
    316 GLOBAL(trace)
    317 	clrl	%sp@-			| stack adjust count
    318 	moveml	#0xFFFF,%sp@-
    319 	moveq	#T_TRACE,%d0
    320 
    321 	| Check PSW and see what happen.
    322 	|   T=0 S=0	(should not happen)
    323 	|   T=1 S=0	trace trap from user mode
    324 	|   T=0 S=1	trace trap on a trap instruction
    325 	|   T=1 S=1	trace trap from system mode (kernel breakpoint)
    326 
    327 	movw	%sp@(FR_HW),%d1		| get PSW
    328 	notw	%d1			| XXX no support for T0 on 680[234]0
    329 	andw	#PSL_TS,%d1		| from system mode (T=1, S=1)?
    330 	jeq	_ASM_LABEL(kbrkpt)	|  yes, kernel brkpt
    331 	jra	_ASM_LABEL(fault)	| no, user-mode fault
    332 
    333 /*
    334  * Trap 15 is used for:
    335  *	- GDB breakpoints (in user programs)
    336  *	- KGDB breakpoints (in the kernel)
    337  *	- trace traps for SUN binaries (not fully supported yet)
    338  * User mode traps are simply passed to trap().
    339  */
    340 GLOBAL(trap15)
    341 	clrl	%sp@-			| stack adjust count
    342 	moveml	#0xFFFF,%sp@-
    343 	moveq	#T_TRAP15,%d0
    344 	btst	#5,%sp@(FR_HW)		| was supervisor mode?
    345 	jne	_ASM_LABEL(kbrkpt)	|  yes, kernel brkpt
    346 	jra	_ASM_LABEL(fault)	| no, user-mode fault
    347 
    348 ASLOCAL(kbrkpt)
    349 	| Kernel-mode breakpoint or trace trap. (%d0=trap_type)
    350 	| Save the system sp rather than the user sp.
    351 	movw	#PSL_HIGHIPL,%sr	| lock out interrupts
    352 	lea	%sp@(FR_SIZE),%a6	| Save stack pointer
    353 	movl	%a6,%sp@(FR_SP)		|  from before trap
    354 
    355 	| If we are not on tmpstk switch to it.
    356 	| (so debugger can change the stack pointer)
    357 	movl	%a6,%d1
    358 	cmpl	#_ASM_LABEL(tmpstk),%d1
    359 	jls	Lbrkpt2 		| already on tmpstk
    360 	| Copy frame to the temporary stack
    361 	movl	%sp,%a0			| %a0=src
    362 	lea	_ASM_LABEL(tmpstk)-96,%a1	| %a1=dst
    363 	movl	%a1,%sp			| sp=new frame
    364 	moveq	#FR_SIZE,%d1
    365 Lbrkpt1:
    366 	movl	%a0@+,%a1@+
    367 	subql	#4,%d1
    368 	bgt	Lbrkpt1
    369 
    370 Lbrkpt2:
    371 	| Call the trap handler for the kernel debugger.
    372 	| Do not call trap() to handle it, so that we can
    373 	| set breakpoints in trap() if we want.  We know
    374 	| the trap type is either T_TRACE or T_BREAKPOINT.
    375 	movl	%d0,%sp@-		| push trap type
    376 	jbsr	_C_LABEL(trap_kdebug)
    377 	addql	#4,%sp			| pop args
    378 
    379 	| The stack pointer may have been modified, or
    380 	| data below it modified (by kgdb push call),
    381 	| so push the hardware frame at the current sp
    382 	| before restoring registers and returning.
    383 	movl	%sp@(FR_SP),%a0		| modified sp
    384 	lea	%sp@(FR_SIZE),%a1	| end of our frame
    385 	movl	%a1@-,%a0@-		| copy 2 longs with
    386 	movl	%a1@-,%a0@-		| ... predecrement
    387 	movl	%a0,%sp@(FR_SP)		| sp = h/w frame
    388 	moveml	%sp@+,#0x7FFF		| restore all but sp
    389 	movl	%sp@,%sp		| ... and sp
    390 	rte				| all done
    391 
    392 /*
    393  * Interrupt handlers.  Most are auto-vectored,
    394  * and hard-wired the same way on all sun3 models.
    395  * Format in the stack is:
    396  *   %d0,%d1,%a0,%a1, sr, pc, vo
    397  */
    398 
    399 /* clock: see clock.c */
    400 #ifdef __ELF__
    401 	.align	4
    402 #else
    403 	.align	2
    404 #endif
    405 GLOBAL(_isr_clock)
    406 	INTERRUPT_SAVEREG
    407 	jbsr	_C_LABEL(clock_intr)
    408 	INTERRUPT_RESTOREREG
    409 	jra	_ASM_LABEL(rei)
    410 
    411 /*
    412  * Emulation of VAX REI instruction.
    413  *
    414  * This code is (mostly) un-altered from the hp300 code,
    415  * except that sun machines do not need a simulated SIR
    416  * because they have a real software interrupt register.
    417  *
    418  * This code deals with checking for and servicing ASTs
    419  * (profiling, scheduling) and software interrupts (network, softclock).
    420  * We check for ASTs first, just like the VAX.  To avoid excess overhead
    421  * the T_ASTFLT handling code will also check for software interrupts so we
    422  * do not have to do it here.  After identifying that we need an AST we
    423  * drop the IPL to allow device interrupts.
    424  *
    425  * This code is complicated by the fact that sendsig may have been called
    426  * necessitating a stack cleanup.
    427  */
    428 
    429 ASGLOBAL(rei)
    430 #ifdef	DIAGNOSTIC
    431 	tstl	_C_LABEL(panicstr)	| have we panicked?
    432 	jne	Ldorte			| yes, do not make matters worse
    433 #endif
    434 	tstl	_C_LABEL(astpending)	| AST pending?
    435 	jeq	Ldorte			| no, done
    436 Lrei1:
    437 	btst	#5,%sp@			| yes, are we returning to user mode?
    438 	jne	Ldorte			| no, done
    439 	movw	#PSL_LOWIPL,%sr		| lower SPL
    440 	clrl	%sp@-			| stack adjust
    441 	moveml	#0xFFFF,%sp@-		| save all registers
    442 	movl	%usp,%a1		| including
    443 	movl	%a1,%sp@(FR_SP)		|    the users SP
    444 	clrl	%sp@-			| VA == none
    445 	clrl	%sp@-			| code == none
    446 	movl	#T_ASTFLT,%sp@-		| type == async system trap
    447 	pea	%sp@(12)		| fp == address of trap frame
    448 	jbsr	_C_LABEL(trap)		| go handle it
    449 	lea	%sp@(16),%sp		| pop value args
    450 	movl	%sp@(FR_SP),%a0		| restore user SP
    451 	movl	%a0,%usp		|   from save area
    452 	movw	%sp@(FR_ADJ),%d0	| need to adjust stack?
    453 	jne	Laststkadj		| yes, go to it
    454 	moveml	%sp@+,#0x7FFF		| no, restore most user regs
    455 	addql	#8,%sp			| toss SP and stack adjust
    456 	rte				| and do real RTE
    457 Laststkadj:
    458 	lea	%sp@(FR_HW),%a1		| pointer to HW frame
    459 	addql	#8,%a1			| source pointer
    460 	movl	%a1,%a0			| source
    461 	addw	%d0,%a0			|  + hole size = dest pointer
    462 	movl	%a1@-,%a0@-		| copy
    463 	movl	%a1@-,%a0@-		|  8 bytes
    464 	movl	%a0,%sp@(FR_SP)		| new SSP
    465 	moveml	%sp@+,#0x7FFF		| restore user registers
    466 	movl	%sp@,%sp		| and our SP
    467 Ldorte:
    468 	rte				| real return
    469 
    470 /*
    471  * Initialization is at the beginning of this file, because the
    472  * kernel entry point needs to be at zero for compatibility with
    473  * the Sun boot loader.  This works on Sun machines because the
    474  * interrupt vector table for reset is NOT at address zero.
    475  * (The MMU has a "boot" bit that forces access to the PROM)
    476  */
    477 
    478 /*
    479  * Primitives
    480  */
    481 
    482 /*
    483  * Use common m68k process/lwp switch and context save subroutines.
    484  */
    485 #undef FPCOPROC
    486 #include <m68k/m68k/switch_subr.s>
    487 
    488 /* loadustp, ptest_addr */
    489 
    490 #ifdef DIAGNOSTIC
    491 | Message for 68881 save/restore panic
    492 Lsr0:
    493 	.asciz	"m68881 save/restore"
    494 	.even
    495 #endif
    496 
    497 /*
    498  * Save and restore 68881 state.
    499  */
    500 ENTRY(m68881_save)
    501 ENTRY(m68881_restore)
    502 #ifdef	DIAGNOSTIC
    503 	movl	#Lsr0,%sp@-
    504         jbsr	_C_LABEL(panic)
    505         /*NOTREACHED*/
    506 #else
    507 	rts
    508 #endif
    509 
    510 /*
    511  * _delay(unsigned N)
    512  * Delay for at least (N/256) microseconds.
    513  * This routine depends on the variable:  delay_divisor
    514  * which should be set based on the CPU clock rate.
    515  * XXX: Currently this is set based on the CPU model,
    516  * XXX: but this should be determined at run time...
    517  */
    518 GLOBAL(_delay)
    519 	| %d0 = arg = (usecs << 8)
    520 	movl	%sp@(4),%d0
    521 	| %d1 = delay_divisor;
    522 	movl	_C_LABEL(delay_divisor),%d1
    523 
    524 	/*
    525 	 * Align the branch target of the loop to a half-line (8-byte)
    526 	 * boundary to minimize cache effects.  This guarantees both
    527 	 * that there will be no prefetch stalls due to cache line burst
    528 	 * operations and that the loop will run from a single cache
    529 	 * half-line.
    530 	 */
    531 #ifdef __ELF__
    532 	.align	8
    533 #else
    534 	.align	3
    535 #endif
    536 L_delay:
    537 	subl	%d1,%d0
    538 	jgt	L_delay
    539 	rts
    540 
    541 /*
    542  * Set or clear bits in the enable register.  This mimics the
    543  * strange behavior in SunOS' locore.o, where they keep a soft
    544  * copy of what they think is in the enable register and loop
    545  * making a change until it sticks.  This is apparently to
    546  * be concurrent-safe without disabling interrupts.  Why you
    547  * can't just disable interrupts while mucking with the register
    548  * I dunno, but it may jive with sun3/intreg.c using the single-instruction
    549  * bit operations and the sun3 intreg being memory-addressable,
    550  * i.e., once the sun2 was designed they realized the enable
    551  * register had to be treated this way, so on the sun3 they made
    552  * it memory-addressable so you could just use the single-instructions.
    553  */
    554 ENTRY(enable_reg_and)
    555 	movc	%dfc,%a1		| save current dfc
    556 	moveq	#FC_CONTROL, %d1
    557 	movc	%d1, %dfc		| make movs access "control"
    558 	movl	%sp@(4), %d1		| get our AND mask
    559 	clrl	%d0
    560 1:	andw	%d1, _C_LABEL(enable_reg_soft)	| do our AND
    561 	movew	_C_LABEL(enable_reg_soft), %d0	| get the result
    562 	movsw	%d0, SYSTEM_ENAB		| install the result
    563 	cmpw	_C_LABEL(enable_reg_soft), %d0
    564 	bne	1b				| install it again if the soft value changed
    565 	movc	%a1,%dfc		| restore dfc
    566 	rts
    567 
    568 ENTRY(enable_reg_or)
    569 	movc	%dfc,%a1		| save current dfc
    570 	moveq	#FC_CONTROL, %d1
    571 	movc	%d1, %dfc		| make movs access "control"
    572 	movl	%sp@(4), %d1		| get our OR mask
    573 	clrl	%d0
    574 1:	orw	%d1, _C_LABEL(enable_reg_soft)	| do our OR
    575 	movew	_C_LABEL(enable_reg_soft), %d0	| get the result
    576 	movsw	%d0, SYSTEM_ENAB			| install the result
    577 	cmpw	_C_LABEL(enable_reg_soft), %d0
    578 	bne	1b				| install it again if the soft value changed
    579 	movc	%a1,%dfc		| restore dfc
    580 	rts
    581 
    582 /*
    583  * Use common m68k 16-bit aligned copy routines.
    584  */
    585 #include <m68k/m68k/w16copy.s>
    586 
    587 | Define some addresses, mostly so DDB can print useful info.
    588 | Not using _C_LABEL() here because these symbols are never
    589 | referenced by any C code, and if the leading underscore
    590 | ever goes away, these lines turn into syntax errors...
    591 	.set	_KERNBASE,KERNBASE
    592 	.set	_MONSTART,SUN2_MONSTART
    593 	.set	_PROM_BASE,SUN2_PROM_BASE
    594 	.set	_MONEND,SUN2_MONEND
    595 
    596 |The end!
    597