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