xref: /netbsd-src/sys/arch/cesfic/cesfic/locore.s (revision 6279c1e992621a887496dc9278adf6ed8aff06c5)
1/*	$NetBSD: locore.s,v 1.46 2024/01/17 12:33:49 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 *
37 *	@(#)locore.s	8.6 (Berkeley) 5/27/94
38 */
39
40/*
41 * Copyright (c) 1994, 1995 Gordon W. Ross
42 * Copyright (c) 1988 University of Utah.
43 *
44 * This code is derived from software contributed to Berkeley by
45 * the Systems Programming Group of the University of Utah Computer
46 * Science Department.
47 *
48 * Redistribution and use in source and binary forms, with or without
49 * modification, are permitted provided that the following conditions
50 * are met:
51 * 1. Redistributions of source code must retain the above copyright
52 *    notice, this list of conditions and the following disclaimer.
53 * 2. Redistributions in binary form must reproduce the above copyright
54 *    notice, this list of conditions and the following disclaimer in the
55 *    documentation and/or other materials provided with the distribution.
56 * 3. All advertising materials mentioning features or use of this software
57 *    must display the following acknowledgement:
58 *	This product includes software developed by the University of
59 *	California, Berkeley and its contributors.
60 * 4. Neither the name of the University nor the names of its contributors
61 *    may be used to endorse or promote products derived from this software
62 *    without specific prior written permission.
63 *
64 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
65 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
66 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
67 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
68 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
69 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
70 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
71 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
72 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
73 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
74 * SUCH DAMAGE.
75 *
76 * from: Utah $Hdr: locore.s 1.66 92/12/22$
77 *
78 *	@(#)locore.s	8.6 (Berkeley) 5/27/94
79 */
80
81#include "opt_compat_netbsd.h"
82#include "opt_compat_sunos.h"
83#include "opt_ddb.h"
84#include "opt_fpsp.h"
85#include "opt_fpu_emulate.h"
86#include "opt_m68k_arch.h"
87
88#include "ksyms.h"
89#include "assym.h"
90#include <machine/asm.h>
91#include <machine/trap.h>
92
93/*
94 * This is for kvm_mkdb, and should be the address of the beginning
95 * of the kernel text segment (not necessarily the same as kernbase).
96 */
97	.text
98GLOBAL(kernel_text)
99
100/*
101 * Temporary stack for a variety of purposes.
102 * Try and make this the first thing is the data segment so it
103 * is page aligned.  Note that if we overflow here, we run into
104 * our text segment.
105 */
106	.data
107	.space	PAGE_SIZE
108ASLOCAL(tmpstk)
109
110	.text
111/*
112 * Macro to relocate a symbol, used before MMU is enabled.
113 */
114#define	_RELOC(var, ar)		\
115	lea	var-KERNBASE,ar;		\
116	addl	%a5,ar
117
118#define	RELOC(var, ar)		_RELOC(_C_LABEL(var), ar)
119#define	ASRELOC(var, ar)	_RELOC(_ASM_LABEL(var), ar)
120
121/*
122 * Initialization
123 *
124 * A4 contains the address of the end of the symtab
125 * A5 contains physical load point from boot
126 * VBR contains zero from ROM.  Exceptions will continue to vector
127 * through ROM until MMU is turned on at which time they will vector
128 * through our table (vectors.s).
129 */
130
131BSS(lowram,4)
132BSS(esym,4)
133
134	.text
135ASENTRY_NOPROFILE(start)
136	movw	#PSL_HIGHIPL, %sr	| no interrupts
137	movl	#CACHE_OFF, %d0
138	movc	%d0, %cacr		| clear and disable on-chip cache(s)
139
140	/* XXX fixed load address */
141	movl	#0x20100000, %a5
142
143	movl	#0x20000000, %a0
144	RELOC(edata, %a1)
1451:
146	movl	%a5@+, %a0@+
147	cmpl	%a5, %a1
148	bne	1b
149
150	movl	#0x20000000, %a5
151
152	ASRELOC(tmpstk, %a0)
153	movl	%a0, %sp		| give ourselves a temporary stack
154
155	RELOC(edata, %a0)
156	RELOC(end, %a1)
1572:
158	clrb	%a0@+
159	cmpl	%a0, %a1
160	bne	2b
161
162	RELOC(esym, %a0)
163#if 0
164	movl	%a4, %a0@		| store end of symbol table
165#else
166	clrl	%a0@			| no symbol table, yet
167#endif
168
169	RELOC(lowram, %a0)
170	movl	%a5, %a0@		| store start of physical memory
171
172#if 0
173	RELOC(boothowto, %a0)		| save reboot flags
174	movl	%d7, %a0@
175	RELOC(bootdev, %a0)		|   and boot device
176	movl	%d6, %a0@
177#endif
178
179	/*
180	 * All data registers are now free.  All address registers
181	 * except a5 are free.  a5 is used by the RELOC() macro,
182	 * and cannot be used until after the MMU is enabled.
183	 */
184
185/* determine our CPU/MMU combo - check for all regardless of kernel config */
186	movl	#0x200,%d0		| data freeze bit
187	movc	%d0,%cacr		|   only exists on 68030
188	movc	%cacr,%d0		| read it back
189	tstl	%d0			| zero?
190	jeq	Lnot68030		| yes, we have 68020/68040
191	RELOC(mmutype, %a0)		| no, we have 68030
192	movl	#MMU_68030,%a0@		| set to reflect 68030 PMMU
193	RELOC(cputype, %a0)
194	movl	#CPU_68030,%a0@		| and 68030 CPU
195	jra	Lstart1
196Lnot68030:
197	bset	#31,%d0			| data cache enable bit
198	movc	%d0,%cacr		|   only exists on 68040
199	movc	%cacr,%d0		| read it back
200	tstl	%d0			| zero?
201	beq	Lis68020		| yes, we have 68020
202	moveq	#0,%d0			| now turn it back off
203	movec	%d0,%cacr		|   before we access any data
204	RELOC(mmutype, %a0)
205	movl	#MMU_68040,%a0@		| with a 68040 MMU
206	RELOC(cputype, %a0)
207	movl	#CPU_68040,%a0@		| and a 68040 CPU
208	RELOC(fputype, %a0)
209	movl	#FPU_68040,%a0@		| ...and FPU
210	jra	Lstart1
211Lis68020:
212	/* impossible */
213
214Lstart1:
215
216/* initialize source/destination control registers for movs */
217	moveq	#FC_USERD,%d0		| user space
218	movc	%d0,%sfc		|   as source
219	movc	%d0,%dfc		|   and destination of transfers
220
221/* initialize memory size (for pmap_bootstrap) */
222	movl	0x5c00ac00, %d0
223	andb	#0x60, %d0
224	jne	Lnot8M
225	movl	#0x20800000, %d1	| memory end, 8M
226	jra	Lmemok
227Lnot8M:
228	cmpb	#0x20, %d0
229	jne	Lunkmem
230	movl	#0x22000000, %d1	| memory end, 32M
231	jra	Lmemok
232Lunkmem:
233	/* ??? */
234	movl	#0x20400000, %d1	| memory end, assume at least 4M
235
236Lmemok:
237	moveq	#PGSHIFT,%d2
238	lsrl	%d2,%d1			| convert to page (click) number
239	movl	%a5,%d0			| lowram value from ROM via boot
240	lsrl	%d2,%d0			| convert to page number
241	subl	%d0,%d1			| compute amount of RAM present
242	RELOC(physmem, %a0)
243	movl	%d1,%a0@		| and physmem
244/* configure kernel and lwp0 VA space so we can get going */
245	.globl	_Sysseg_pa, _pmap_bootstrap, _avail_start
246#if NKSYMS || defined(DDB) || defined(MODULAR)
247	RELOC(esym,%a0)			| end of static kernel test/data/syms
248	movl	%a0@,%d5
249	jne	Lstart2
250#endif
251	movl	#_C_LABEL(end),%d5	| end of static kernel text/data
252Lstart2:
253	addl	#PAGE_SIZE-1,%d5
254	andl	#PG_FRAME,%d5		| round to a page
255	movl	%d5,%a4
256	addl	%a5,%a4			| convert to PA
257	subl	#KERNBASE, %a4
258	pea	%a5@			| firstpa
259	pea	%a4@			| nextpa
260	RELOC(pmap_bootstrap,%a0)
261	jbsr	%a0@			| pmap_bootstrap(firstpa, nextpa)
262	addql	#8,%sp
263
264/*
265 * Prepare to enable MMU.
266 */
267	RELOC(Sysseg_pa, %a0)		| system segment table addr
268	movl	%a0@,%d1		| read value (a PA)
269	subl	#KERNBASE, %d1
270
271	RELOC(mmutype, %a0)
272	cmpl	#MMU_68040,%a0@		| 68040?
273	jne	Lmotommu1		| no, skip
274	.long	0x4e7b1807		| movc d1,srp
275	jra	Lstploaddone
276Lmotommu1:
277#ifdef M68030
278	RELOC(protorp, %a0)
279	movl	%d1,%a0@(4)		| segtable address
280	pmove	%a0@,%srp		| load the supervisor root pointer
281#endif /* M68030 */
282Lstploaddone:
283
284	RELOC(mmutype, %a0)
285	cmpl	#MMU_68040,%a0@		| 68040?
286	jne	Lmotommu2		| no, skip
287
288	movel #0x2000c000, %d0		| double map RAM
289	.long	0x4e7b0004		| movc d0,itt0
290	.long	0x4e7b0006		| movc d0,dtt0
291	moveq	#0, %d0			| ensure TT regs are disabled
292	.long	0x4e7b0005		| movc d0,itt1
293	.long	0x4e7b0007		| movc d0,dtt1
294
295	.word	0xf4d8			| cinva bc
296	.word	0xf518			| pflusha
297
298	movl	#MMU40_TCR_BITS, %d0
299	.long	0x4e7b0003		| movc d0,tc
300	movl	#0x80008000, %d0
301	movc	%d0, %cacr		| turn on both caches
302
303	jmp	Lenab1:l		| avoid pc-relative
304Lmotommu2:
305	/* XXX do TT here */
306	pflusha
307	RELOC(prototc, %a2)
308	movl	#MMU51_TCR_BITS,%a2@	| value to load TC with
309	pmove	%a2@,%tc		| load it
310	jmp	Lenab1
311
312/*
313 * Should be running mapped from this point on
314 */
315Lenab1:
316	.word	0xf4d8			| cinva bc
317	.word	0xf518			| pflusha
318	nop
319	nop
320	nop
321	nop
322	nop
323	moveq	#0,%d0			| ensure TT regs are disabled
324	.long	0x4e7b0004		| movc d0,itt0
325	.long	0x4e7b0005		| movc d0,itt1
326	.long	0x4e7b0006		| movc d0,dtt0
327	.long	0x4e7b0007		| movc d0,dtt1
328
329	lea	_ASM_LABEL(tmpstk),%sp	| re-load temporary stack
330	jbsr	_C_LABEL(vec_init)	| initialize vector table
331/* call final pmap setup */
332	jbsr	_C_LABEL(pmap_bootstrap_finalize)
333/* set kernel stack, user SP */
334	movl	_C_LABEL(lwp0uarea),%a1	| get lwp0 uarea
335	lea	%a1@(USPACE-4),%sp	| set kernel stack to end of area
336	movl	#USRSTACK-4,%a2
337	movl	%a2,%usp		| init user SP
338
339	tstl	_C_LABEL(fputype)	| Have an FPU?
340	jeq	Lenab2			| No, skip.
341	clrl	%a1@(PCB_FPCTX)		| ensure null FP context
342	movl	%a1,%sp@-
343	jbsr	_C_LABEL(m68881_restore)   | restore it (does not kill a1)
344	addql	#4,%sp
345Lenab2:
346
347/* flush TLB and turn on caches */
348	jbsr	_C_LABEL(_TBIA)		| invalidate TLB
349	cmpl	#MMU_68040,_C_LABEL(mmutype)	| 68040?
350	jeq	Lnocache0		| yes, cache already on
351	movl	#CACHE_ON,%d0
352	movc	%d0,%cacr		| clear cache(s)
353Lnocache0:
354
355/* Final setup for call to main(). */
356	jbsr	_C_LABEL(fic_init)
357
358/*
359 * Create a fake exception frame so that cpu_lwp_fork() can copy it.
360 * main() nevers returns; we exit to user mode from a forked process
361 * later on.
362 */
363	clrw	%sp@-			| vector offset/frame type
364	clrl	%sp@-			| PC - filled in by "execve"
365	movw	#PSL_USER,%sp@-		| in user mode
366	clrl	%sp@-			| stack adjust count and padding
367	lea	%sp@(-64),%sp		| construct space for D0-D7/A0-A7
368	lea	_C_LABEL(lwp0),%a0	| save pointer to frame
369	movl	%sp,%a0@(L_MD_REGS)	|   in lwp0.l_md.md_regs
370
371	jra	_C_LABEL(main)		| main()
372
373	pea	Lmainreturned		| Yow!  Main returned!
374	jbsr	_C_LABEL(panic)
375	/* NOTREACHED */
376Lmainreturned:
377	.asciz	"main() returned"
378	.even
379
380/*
381 * Trap/interrupt vector routines
382 */
383#include <m68k/m68k/trap_subr.s>
384
385/*
386 * Use common m68k bus error and address error handlers.
387 */
388#include <m68k/m68k/busaddrerr.s>
389
390/*
391 * FP exceptions.
392 */
393ENTRY_NOPROFILE(fpfline)
394#if defined(M68040)
395	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
396	jne	Lfp_unimp		| no, skip FPSP
397	cmpw	#0x202c,%sp@(6)		| format type 2?
398	jne	_C_LABEL(illinst)	| no, not an FP emulation
399Ldofp_unimp:
400#ifdef FPSP
401#if 0
402	addl	#1, _C_LABEL(evcnt_fpsp_unimp)+EVCNT_COUNT
403#endif
404	jmp	_ASM_LABEL(fpsp_unimp)	| yes, go handle it
405#endif
406Lfp_unimp:
407#endif /* M68040 */
408#ifdef FPU_EMULATE
409	clrl	%sp@-			| stack adjust count
410	moveml	#0xFFFF,%sp@-		| save registers
411	moveq	#T_FPEMULI,%d0		| denote as FP emulation trap
412	jra	_ASM_LABEL(fault)	| do it
413#else
414	jra	_C_LABEL(illinst)
415#endif
416
417ENTRY_NOPROFILE(fpunsupp)
418#if defined(M68040)
419	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
420	jne	_C_LABEL(illinst)	| no, treat as illinst
421#ifdef FPSP
422#if 0
423	addl	#1, _C_LABEL(evcnt_fpsp_unsupp)+EVCNT_COUNT
424#endif
425	jmp	_ASM_LABEL(fpsp_unsupp)	| yes, go handle it
426#endif
427Lfp_unsupp:
428#endif /* M68040 */
429#ifdef FPU_EMULATE
430	clrl	%sp@-			| stack adjust count
431	moveml	#0xFFFF,%sp@-		| save registers
432	moveq	#T_FPEMULD,%d0		| denote as FP emulation trap
433	jra	_ASM_LABEL(fault)	| do it
434#else
435	jra	_C_LABEL(illinst)
436#endif
437
438/*
439 * Handles all other FP coprocessor exceptions.
440 * Note that since some FP exceptions generate mid-instruction frames
441 * and may cause signal delivery, we need to test for stack adjustment
442 * after the trap call.
443 */
444ENTRY_NOPROFILE(fpfault)
445	clrl	%sp@-		| stack adjust count
446	moveml	#0xFFFF,%sp@-	| save user registers
447	movl	%usp,%a0		| and save
448	movl	%a0,%sp@(FR_SP)	|   the user stack pointer
449	clrl	%sp@-		| no VA arg
450	movl	_C_LABEL(curpcb),%a0 | current pcb
451	lea	%a0@(PCB_FPCTX),%a0 | address of FP savearea
452	fsave	%a0@		| save state
453#if defined(M68040) || defined(M68060)
454	/* always null state frame on 68040, 68060 */
455	cmpl	#FPU_68040,_C_LABEL(fputype)
456	jge	Lfptnull
457#endif
458	tstb	%a0@		| null state frame?
459	jeq	Lfptnull	| yes, safe
460	clrw	%d0		| no, need to tweak BIU
461	movb	%a0@(1),%d0	| get frame size
462	bset	#3,%a0@(0,%d0:w)	| set exc_pend bit of BIU
463Lfptnull:
464	fmovem	%fpsr,%sp@-	| push %fpsr as code argument
465	frestore %a0@		| restore state
466	movl	#T_FPERR,%sp@-	| push type arg
467	jra	_ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup
468
469
470ENTRY_NOPROFILE(badtrap)
471	moveml	#0xC0C0,%sp@-		| save scratch regs
472	movw	%sp@(22),%sp@-		| push exception vector info
473	clrw	%sp@-
474	movl	%sp@(22),%sp@-		| and PC
475	jbsr	_C_LABEL(straytrap)	| report
476	addql	#8,%sp			| pop args
477	moveml	%sp@+,#0x0303		| restore regs
478	jra	_ASM_LABEL(rei)		| all done
479
480ENTRY_NOPROFILE(trap0)
481	clrl	%sp@-			| stack adjust count
482	moveml	#0xFFFF,%sp@-		| save user registers
483	movl	%usp,%a0			| save the user SP
484	movl	%a0,%sp@(FR_SP)		|   in the savearea
485	movl	%d0,%sp@-			| push syscall number
486	jbsr	_C_LABEL(syscall)	| handle it
487	addql	#4,%sp			| pop syscall arg
488	tstl	_C_LABEL(astpending)
489	jne	Lrei2
490	tstb	_C_LABEL(ssir)
491	jeq	Ltrap1
492	movw	#SPL1,%sr
493	tstb	_C_LABEL(ssir)
494	jne	Lsir1
495Ltrap1:
496	movl	%sp@(FR_SP),%a0		| grab and restore
497	movl	%a0,%usp			|   user SP
498	moveml	%sp@+,#0x7FFF		| restore most registers
499	addql	#8,%sp			| pop SP and stack adjust
500	rte
501
502/*
503 * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD)
504 *	cachectl(command, addr, length)
505 * command in d0, addr in a1, length in d1
506 */
507ENTRY_NOPROFILE(trap12)
508	movl	_C_LABEL(curlwp),%a0
509	movl	%a0@(L_PROC),%sp@-	| push current proc pointer
510	movl	%d1,%sp@-			| push length
511	movl	%a1,%sp@-			| push addr
512	movl	%d0,%sp@-			| push command
513	jbsr	_C_LABEL(cachectl1)	| do it
514	lea	%sp@(16),%sp		| pop args
515	jra	_ASM_LABEL(rei)		| all done
516
517/*
518 * Trace (single-step) trap.  Kernel-mode is special.
519 * User mode traps are simply passed on to trap().
520 */
521ENTRY_NOPROFILE(trace)
522	clrl	%sp@-			| stack adjust count
523	moveml	#0xFFFF,%sp@-
524	moveq	#T_TRACE,%d0
525
526	| Check PSW and see what happen.
527	|   T=0 S=0	(should not happen)
528	|   T=1 S=0	trace trap from user mode
529	|   T=0 S=1	trace trap on a trap instruction
530	|   T=1 S=1	trace trap from system mode (kernel breakpoint)
531
532	movw	%sp@(FR_HW),%d1		| get PSW
533	notw	%d1			| XXX no support for T0 on 680[234]0
534	andw	#PSL_TS,%d1		| from system mode (T=1, S=1)?
535	jeq	Lkbrkpt			| yes, kernel breakpoint
536	jra	_ASM_LABEL(fault)	| no, user-mode fault
537
538
539/*
540 * Trap 15 is used for:
541 *	- GDB breakpoints (in user programs)
542 *	- KGDB breakpoints (in the kernel)
543 *	- trace traps for SUN binaries (not fully supported yet)
544 * User mode traps are simply passed to trap().
545 */
546ENTRY_NOPROFILE(trap15)
547	clrl	%sp@-			| stack adjust count
548	moveml	#0xFFFF,%sp@-
549	moveq	#T_TRAP15,%d0
550	movw	%sp@(FR_HW),%d1		| get PSW
551	andw	#PSL_S,%d1		| from system mode?
552	jne	Lkbrkpt			| yes, kernel breakpoint
553	jra	_ASM_LABEL(fault)	| no, user-mode fault
554
555Lkbrkpt: | Kernel-mode breakpoint or trace trap. (%d0=trap_type)
556	| Save the system sp rather than the user sp.
557	movw	#PSL_HIGHIPL,%sr		| lock out interrupts
558	lea	%sp@(FR_SIZE),%a6		| Save stack pointer
559	movl	%a6,%sp@(FR_SP)		|  from before trap
560
561	| If were are not on tmpstk switch to it.
562	| (so debugger can change the stack pointer)
563	movl	%a6,%d1
564	cmpl	#_ASM_LABEL(tmpstk),%d1
565	jls	Lbrkpt2			| already on tmpstk
566	| Copy frame to the temporary stack
567	movl	%sp,%a0			| %a0=src
568	lea	_ASM_LABEL(tmpstk)-96,%a1 | a1=dst
569	movl	%a1,%sp			| %sp=new frame
570	moveq	#FR_SIZE,%d1
571Lbrkpt1:
572	movl	%a0@+,%a1@+
573	subql	#4,%d1
574	bgt	Lbrkpt1
575
576Lbrkpt2:
577	| Call the trap handler for the kernel debugger.
578	| Do not call trap() to do it, so that we can
579	| set breakpoints in trap() if we want.  We know
580	| the trap type is either T_TRACE or T_BREAKPOINT.
581	movl	%d0,%sp@-		| push trap type
582	jbsr	_C_LABEL(trap_kdebug)
583	addql	#4,%sp			| pop args
584
585	| The stack pointer may have been modified, or
586	| data below it modified (by kgdb push call),
587	| so push the hardware frame at the current sp
588	| before restoring registers and returning.
589
590	movl	%sp@(FR_SP),%a0		| modified %sp
591	lea	%sp@(FR_SIZE),%a1		| end of our frame
592	movl	%a1@-,%a0@-		| copy 2 longs with
593	movl	%a1@-,%a0@-		| ... predecrement
594	movl	%a0,%sp@(FR_SP)		| %sp = h/w frame
595	moveml	%sp@+,#0x7FFF		| restore all but %sp
596	movl	%sp@,%sp			| ... and %sp
597	rte				| all done
598
599/*
600 * Interrupt handlers.
601 */
602
603ENTRY_NOPROFILE(lev6intr)	/* Level 6: clock */
604	INTERRUPT_SAVEREG
605	/* XXX */
606	movl _C_LABEL(clockbase), %a0
607	movl %a0@, %d0
608	movl %d0, %a0@
609	btst #2, %d0
610	jeq 1f
611	addql	#1,_C_LABEL(m68k_intr_evcnt)+CLOCK_INTRCNT
612	lea	%sp@(0), %a1		| a1 = &clockframe
613	movl	%a1, %sp@-
614	jbsr	_C_LABEL(hardclock)	| hardclock(&frame)
615	addql	#4, %sp
616	jra 2f
6171:
618	movl	%d0, %sp@-
619	jbsr	_C_LABEL(otherclock)
620	addql	#4, %sp
6212:
622	INTERRUPT_RESTOREREG
623	jra	_ASM_LABEL(rei)		| all done
624
625ENTRY_NOPROFILE(lev7intr)	/* level 7: parity errors, reset key */
626	addql	#1,_C_LABEL(m68k_intr_evcnt)+NMI_INTRCNT
627	clrl	%sp@-
628	moveml	#0xFFFF,%sp@-		| save registers
629	movl	%usp,%a0			| and save
630	movl	%a0,%sp@(FR_SP)		|   the user stack pointer
631	jbsr	_C_LABEL(nmihand)	| call handler
632	movl	%sp@(FR_SP),%a0		| restore
633	movl	%a0,%usp			|   user SP
634	moveml	%sp@+,#0x7FFF		| and remaining registers
635	addql	#8,%sp			| pop SP and stack adjust
636	jra	_ASM_LABEL(rei)		| all done
637
638/*
639 * Emulation of VAX REI instruction.
640 *
641 * This code deals with checking for and servicing ASTs
642 * (profiling, scheduling) and software interrupts (network, softclock).
643 * We check for ASTs first, just like the VAX.  To avoid excess overhead
644 * the T_ASTFLT handling code will also check for software interrupts so we
645 * do not have to do it here.  After identifying that we need an AST we
646 * drop the IPL to allow device interrupts.
647 *
648 * This code is complicated by the fact that sendsig may have been called
649 * necessitating a stack cleanup.
650 */
651BSS(ssir,1)
652
653ASENTRY_NOPROFILE(rei)
654	tstl	_C_LABEL(astpending)	| AST pending?
655	jeq	Lchksir			| no, go check for SIR
656Lrei1:
657	btst	#5,%sp@			| yes, are we returning to user mode?
658	jne	Lchksir			| no, go check for SIR
659	movw	#PSL_LOWIPL,%sr		| lower SPL
660	clrl	%sp@-			| stack adjust
661	moveml	#0xFFFF,%sp@-		| save all registers
662	movl	%usp,%a1			| including
663	movl	%a1,%sp@(FR_SP)		|    the users SP
664Lrei2:
665	clrl	%sp@-			| VA == none
666	clrl	%sp@-			| code == none
667	movl	#T_ASTFLT,%sp@-		| type == async system trap
668	pea	%sp@(12)		| fp == address of trap frame
669	jbsr	_C_LABEL(trap)		| go handle it
670	lea	%sp@(16),%sp		| pop value args
671	movl	%sp@(FR_SP),%a0		| restore user SP
672	movl	%a0,%usp			|   from save area
673	movw	%sp@(FR_ADJ),%d0		| need to adjust stack?
674	jne	Laststkadj		| yes, go to it
675	moveml	%sp@+,#0x7FFF		| no, restore most user regs
676	addql	#8,%sp			| toss SP and stack adjust
677	rte				| and do real RTE
678Laststkadj:
679	lea	%sp@(FR_HW),%a1		| pointer to HW frame
680	addql	#8,%a1			| source pointer
681	movl	%a1,%a0			| source
682	addw	%d0,%a0			|  + hole size = dest pointer
683	movl	%a1@-,%a0@-		| copy
684	movl	%a1@-,%a0@-		|  8 bytes
685	movl	%a0,%sp@(FR_SP)		| new SSP
686	moveml	%sp@+,#0x7FFF		| restore user registers
687	movl	%sp@,%sp			| and our SP
688	rte				| and do real RTE
689Lchksir:
690	tstb	_C_LABEL(ssir)		| SIR pending?
691	jeq	Ldorte			| no, all done
692	movl	%d0,%sp@-			| need a scratch register
693	movw	%sp@(4),%d0		| get SR
694	andw	#PSL_IPL7,%d0		| mask all but IPL
695	jne	Lnosir			| came from interrupt, no can do
696	movl	%sp@+,%d0			| restore scratch register
697Lgotsir:
698	movw	#SPL1,%sr		| prevent others from servicing int
699	tstb	_C_LABEL(ssir)		| too late?
700	jeq	Ldorte			| yes, oh well...
701	clrl	%sp@-			| stack adjust
702	moveml	#0xFFFF,%sp@-		| save all registers
703	movl	%usp,%a1			| including
704	movl	%a1,%sp@(FR_SP)		|    the users SP
705Lsir1:
706	clrl	%sp@-			| VA == none
707	clrl	%sp@-			| code == none
708	movl	#T_SSIR,%sp@-		| type == software interrupt
709	pea	%sp@(12)		| fp == address of trap frame
710	jbsr	_C_LABEL(trap)		| go handle it
711	lea	%sp@(16),%sp		| pop value args
712	movl	%sp@(FR_SP),%a0		| restore
713	movl	%a0,%usp			|   user SP
714	moveml	%sp@+,#0x7FFF		| and all remaining registers
715	addql	#8,%sp			| pop SP and stack adjust
716	rte
717Lnosir:
718	movl	%sp@+,%d0			| restore scratch register
719Ldorte:
720	rte				| real return
721
722/*
723 * Primitives
724 */
725
726/*
727 * Use common m68k process/lwp switch and context save subroutines.
728 */
729#define	FPCOPROC	/* XXX: Temporarily required */
730#include <m68k/m68k/switch_subr.s>
731
732
733#if defined(M68040)
734ENTRY(suline)
735	movl	%sp@(4),%a0		| address to write
736	movl	_C_LABEL(curpcb),%a1	| current pcb
737	movl	#Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault
738	movl	%sp@(8),%a1		| address of line
739	movl	%a1@+,%d0			| get lword
740	movsl	%d0,%a0@+			| put lword
741	nop				| sync
742	movl	%a1@+,%d0			| get lword
743	movsl	%d0,%a0@+			| put lword
744	nop				| sync
745	movl	%a1@+,%d0			| get lword
746	movsl	%d0,%a0@+			| put lword
747	nop				| sync
748	movl	%a1@+,%d0			| get lword
749	movsl	%d0,%a0@+			| put lword
750	nop				| sync
751	moveq	#0,%d0			| indicate no fault
752	jra	Lsldone
753Lslerr:
754	moveq	#-1,%d0
755Lsldone:
756	movl	_C_LABEL(curpcb),%a1	| current pcb
757	clrl	%a1@(PCB_ONFAULT) 	| clear fault address
758	rts
759#endif
760
761/*
762 * Set processor priority level calls.  Most are implemented with
763 * inline asm expansions.  However, spl0 requires special handling
764 * as we need to check for our emulated software interrupts.
765 */
766
767ENTRY(spl0)
768	moveq	#0,%d0
769	movw	%sr,%d0			| get old SR for return
770	movw	#PSL_LOWIPL,%sr		| restore new SR
771	tstb	_C_LABEL(ssir)		| software interrupt pending?
772	jeq	Lspldone		| no, all done
773	subql	#4,%sp			| make room for RTE frame
774	movl	%sp@(4),%sp@(2)		| position return address
775	clrw	%sp@(6)			| set frame type 0
776	movw	#PSL_LOWIPL,%sp@		| and new SR
777	jra	Lgotsir			| go handle it
778Lspldone:
779	rts
780
781/*
782 * _delay(u_int N)
783 *
784 * Delay for at least (N/256) microseconds.
785 * This routine depends on the variable:  delay_divisor
786 * which should be set based on the CPU clock rate.
787 */
788ENTRY_NOPROFILE(_delay)
789	| d0 = arg = (usecs << 8)
790	movl	%sp@(4),%d0
791	| d1 = delay_divisor
792	movl	_C_LABEL(delay_divisor),%d1
793L_delay:
794	subl	%d1,%d0
795	jgt	L_delay
796	rts
797
798ENTRY_NOPROFILE(doboot)
799	movl #0x5c00c060, %d0		| want phys addressing
800	.long	0x4e7b0006		| movc d0,dtt0
801	movl	#1, 0x5c00b800		| reset
802	stop	#0x2700			| paranoia
803
804	.data
805GLOBAL(mmutype)
806	.long	MMU_HP		| default to HP MMU
807GLOBAL(cputype)
808	.long	CPU_68020	| default to 68020 CPU
809GLOBAL(fputype)
810	.long	FPU_68881	| default to 68881 FPU
811GLOBAL(prototc)
812	.long	0		| prototype translation control
813
814#ifdef DEBUG
815	.globl	fulltflush, fullcflush
816fulltflush:
817	.long	0
818fullcflush:
819	.long	0
820#endif
821