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