xref: /netbsd/sys/arch/atari/atari/locore.s (revision 60e2ec70)
1/*	$NetBSD: locore.s,v 1.117 2023/01/06 10:28:27 tsutsui 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(idepth)
346	INTERRUPT_SAVEREG
347	jbsr	_C_LABEL(intr_dispatch)	|  handle interrupt
348	INTERRUPT_RESTOREREG
349	subql	#1,_C_LABEL(idepth)
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(idepth)
362	INTERRUPT_SAVEREG
363	jbsr	_C_LABEL(falcon_display_switch)
364	INTERRUPT_RESTOREREG
365	subql	#1,_C_LABEL(idepth)
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(idepth)
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(idepth)
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(idepth)
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(idepth)
473	jra	_ASM_LABEL(rei)		|  all done
474
475ENTRY_NOPROFILE(badmfpint)
476	addql	#1,_C_LABEL(idepth)
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(idepth)
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/* Use common m68k sigreturn */
622#include <m68k/m68k/sigreturn.s>
623
624/*
625 * Interrupt handlers.
626 *
627 *	Level 0:	Spurious: ignored.
628 *	Level 1:	softint
629 *	Level 2:	HBL
630 *	Level 3:	not used
631 *	Level 4:	not used
632 *	Level 5:	SCC (not used)
633 *	Level 6:	MFP1/MFP2 (not used -> autovectored)
634 *	Level 7:	Non-maskable: shouldn't be possible. ignore.
635 */
636
637/* Provide a generic interrupt dispatcher, only handle hardclock (int6)
638 * specially, to improve performance
639 */
640
641ENTRY_NOPROFILE(spurintr)
642	addql	#1,_C_LABEL(intrcnt)+0
643	INTERRUPT_SAVEREG		|  save scratch registers
644	CPUINFO_INCREMENT(CI_NINTR)
645	INTERRUPT_RESTOREREG		|  restore scratch regs
646	jra	_ASM_LABEL(rei)
647
648	/* MFP timer A handler --- System clock --- */
649ASENTRY_NOPROFILE(mfp_tima)
650	addql	#1,_C_LABEL(idepth)
651	INTERRUPT_SAVEREG		|  save scratch registers
652	movl	%sp,%sp@-		|  push pointer to clockframe
653	jbsr	_C_LABEL(hardclock)	|  call generic clock int routine
654	addql	#4,%sp			|  pop params
655	addql	#1,_C_LABEL(intrcnt_user)+52
656					|  add another system clock interrupt
657	CPUINFO_INCREMENT(CI_NINTR)
658	INTERRUPT_RESTOREREG		|  restore scratch regs
659	subql	#1,_C_LABEL(idepth)
660	jra	_ASM_LABEL(rei)		|  all done
661
662#ifdef STATCLOCK
663	/* MFP timer C handler --- Stat/Prof clock --- */
664ASENTRY_NOPROFILE(mfp_timc)
665	addql	#1,_C_LABEL(idepth)
666	INTERRUPT_SAVEREG		|  save scratch registers
667	jbsr	_C_LABEL(statintr)	|  call statistics clock handler
668	addql	#1,_C_LABEL(intrcnt)+36	|  add another stat clock interrupt
669	CPUINFO_INCREMENT(CI_NINTR)
670	INTERRUPT_RESTOREREG		|  restore scratch regs
671	subql	#1,_C_LABEL(idepth)
672	jra	_ASM_LABEL(rei)		|  all done
673#endif /* STATCLOCK */
674
675#if NKBD > 0
676	/* MFP ACIA handler --- keyboard/midi --- */
677ASENTRY_NOPROFILE(mfp_kbd)
678	addql	#1,_C_LABEL(idepth)
679	addql	#1,_C_LABEL(intrcnt)+8	|  add another kbd/mouse interrupt
680
681	INTERRUPT_SAVEREG		|  save scratch registers
682	movw	%sp@(16),%sp@-		|  push previous SR value
683	clrw	%sp@-			|     padded to longword
684	jbsr	_C_LABEL(kbdintr)	|  handle interrupt
685	addql	#4,%sp			|  pop SR
686	CPUINFO_INCREMENT(CI_NINTR)
687	INTERRUPT_RESTOREREG		|  restore scratch regs
688	subql	#1,_C_LABEL(idepth)
689	jra	_ASM_LABEL(rei)
690#endif /* NKBD */
691
692#if NNCRSCSI > 0
693	/* MFP2 SCSI DMA handler --- NCR5380 --- */
694ASENTRY_NOPROFILE(mfp2_5380dm)
695	addql	#1,_C_LABEL(idepth)
696	addql	#1,_C_LABEL(intrcnt)+24	|  add another 5380-DMA interrupt
697
698	INTERRUPT_SAVEREG		|  save scratch registers
699	movw	%sp@(16),%sp@-		|  push previous SR value
700	clrw	%sp@-			|     padded to longword
701	jbsr	_C_LABEL(scsi_dma)	|  handle interrupt
702	addql	#4,%sp			|  pop SR
703	CPUINFO_INCREMENT(CI_NINTR)
704	INTERRUPT_RESTOREREG		|  restore scratch regs
705	subql	#1,_C_LABEL(idepth)
706	jra	_ASM_LABEL(rei)
707
708	/* MFP2 SCSI handler --- NCR5380 --- */
709ASENTRY_NOPROFILE(mfp2_5380)
710	addql	#1,_C_LABEL(idepth)
711	addql	#1,_C_LABEL(intrcnt)+20	|  add another 5380-SCSI interrupt
712
713	INTERRUPT_SAVEREG		|  save scratch registers
714	movw	%sp@(16),%sp@-		|  push previous SR value
715	clrw	%sp@-			|     padded to longword
716	jbsr	_C_LABEL(scsi_ctrl)	|  handle interrupt
717	addql	#4,%sp			|  pop SR
718	CPUINFO_INCREMENT(CI_NINTR)
719	INTERRUPT_RESTOREREG		|  restore scratch regs
720	subql	#1,_C_LABEL(idepth)
721	jra	_ASM_LABEL(rei)
722#endif /* NNCRSCSI > 0 */
723
724#ifdef _ATARIHW_
725	/* Level 1 (Software) interrupt handler */
726ENTRY_NOPROFILE(lev1intr)
727	addql	#1,_C_LABEL(idepth)
728	INTERRUPT_SAVEREG		|  save scratch registers
729	movl	_C_LABEL(stio_addr),%a0 |  get KVA of ST-IO area
730	moveb	#0, %a0@(SCU_SOFTINT)	|  Turn off software interrupt
731	addql	#1,_C_LABEL(intrcnt)+16	|  add another software interrupt
732	jbsr	_C_LABEL(nullop)	|  XXX handle software interrupts
733	CPUINFO_INCREMENT(CI_NINTR)
734	INTERRUPT_RESTOREREG
735	subql	#1,_C_LABEL(idepth)
736	jra	_ASM_LABEL(rei)
737
738	/*
739	 * Should never occur, except when special hardware modification
740	 * is installed. In this case, one expects to be dropped into
741	 * the debugger.
742	 */
743ENTRY_NOPROFILE(lev7intr)
744#ifdef DDB
745	/*
746	 * Note that the nmi has to be turned off while handling it because
747	 * the hardware modification has no de-bouncing logic....
748	 */
749	addql	#1,_C_LABEL(idepth)
750	movl	%a0, %sp@-		|  save a0
751	movl	_C_LABEL(stio_addr),%a0	|  get KVA of ST-IO area
752	movb	%a0@(SCU_SYSMASK),%sp@-	|  save current sysmask
753	movb	#0, %a0@(SCU_SYSMASK)	|  disable all interrupts
754	trap	#15			|  drop into the debugger
755	movb	%sp@+, %a0@(SCU_SYSMASK)|  restore sysmask
756	movl	%sp@+, %a0		|  restore a0
757	subql	#1,_C_LABEL(idepth)
758#endif
759	addql	#1,_C_LABEL(intrcnt)+28	|  add another nmi interrupt
760	rte				|  all done
761
762#endif /* _ATARIHW_ */
763
764
765/*
766 * Emulation of VAX REI instruction.
767 *
768 * This code deals with checking for and servicing ASTs
769 * (profiling, scheduling) and software interrupts (network, softclock).
770 * We check for ASTs first, just like the VAX.  To avoid excess overhead
771 * the T_ASTFLT handling code will also check for software interrupts so we
772 * do not have to do it here.  After identifying that we need an AST we
773 * drop the IPL to allow device interrupts.
774 *
775 * This code is complicated by the fact that sendsig may have been called
776 * necessitating a stack cleanup.  A cleanup should only be needed at this
777 * point for coprocessor mid-instruction frames (type 9), but we also test
778 * for bus error frames (type 10 and 11).
779 */
780ASENTRY_NOPROFILE(rei)
781#ifdef DEBUG
782	tstl	_C_LABEL(panicstr)	|  have we panicked?
783	jne	Ldorte			|  yes, do not make matters worse
784#endif
785	tstl	_C_LABEL(astpending)	|  AST pending?
786	jeq	Lchksir			|  no, go check for SIR
787Lrei1:
788	btst	#5,%sp@			|  yes, are we returning to user mode?
789	jne	Lchksir			|  no, go check for SIR
790	movw	#PSL_LOWIPL,%sr		|  lower SPL
791	clrl	%sp@-			|  stack adjust
792	moveml	#0xFFFF,%sp@-		|  save all registers
793	movl	%usp,%a1		|  including
794	movl	%a1,%sp@(FR_SP)		|     the users SP
795	clrl	%sp@-			|  VA == none
796	clrl	%sp@-			|  code == none
797	movl	#T_ASTFLT,%sp@-		|  type == async system trap
798	pea	%sp@(12)		|  fp == address of trap frame
799	jbsr	_C_LABEL(trap)		|  go handle it
800	lea	%sp@(16),%sp		|  pop value args
801	movl	%sp@(FR_SP),%a0		|  restore user SP
802	movl	%a0,%usp		|    from save area
803	movw	%sp@(FR_ADJ),%d0	|  need to adjust stack?
804	jne	Laststkadj		|  yes, go to it
805	moveml	%sp@+,#0x7FFF		|  no, restore most user regs
806	addql	#8,%sp			|  toss SP and stack adjust
807	rte				|  and do real RTE
808Laststkadj:
809	lea	%sp@(FR_HW),%a1		|  pointer to HW frame
810	addql	#8,%a1			|  source pointer
811	movl	%a1,%a0			|  source
812	addw	%d0,%a0			|   + hole size = dest pointer
813	movl	%a1@-,%a0@-		|  copy
814	movl	%a1@-,%a0@-		|   8 bytes
815	movl	%a0,%sp@(FR_SP)		|  new SSP
816	moveml	%sp@+,#0x7FFF		|  restore user registers
817	movl	%sp@,%sp		|  and our SP
818	rte				|  and do real RTE
819Lchksir:
820	tstb	_C_LABEL(ssir)		|  SIR pending?
821	jeq	Ldorte			|  no, all done
822	movl	%d0,%sp@-		|  need a scratch register
823	movw	%sp@(4),%d0		|  get SR
824	andw	#PSL_IPL7,%d0		|  mask all but IPL
825	jne	Lnosir			|  came from interrupt, no can do
826	movl	%sp@+,%d0		|  restore scratch register
827Lgotsir:
828	movw	#SPL1,%sr		|  prevent others from servicing int
829	tstb	_C_LABEL(ssir)		|  too late?
830	jeq	Ldorte			|  yes, oh well...
831	clrl	%sp@-			|  stack adjust
832	moveml	#0xFFFF,%sp@-		|  save all registers
833	movl	%usp,%a1		|  including
834	movl	%a1,%sp@(FR_SP)		|     the users SP
835	clrl	%sp@-			|  VA == none
836	clrl	%sp@-			|  code == none
837	movl	#T_SSIR,%sp@-		|  type == software interrupt
838	pea	%sp@(12)		|  fp == address of trap frame
839	jbsr	_C_LABEL(trap)		|  go handle it
840	lea	%sp@(16),%sp		|  pop value args
841	movl	%sp@(FR_SP),%a0		|  restore
842	movl	%a0,%usp		|    user SP
843	moveml	%sp@+,#0x7FFF		|  and all remaining registers
844	addql	#8,%sp			|  pop SP and stack adjust
845	rte
846Lnosir:
847	movl	%sp@+,%d0		|  restore scratch register
848Ldorte:
849	rte				|  real return
850
851/*
852 * Initialization
853 *
854 * A5 contains physical load point from boot
855 * exceptions vector thru our table, that's bad.. just hope nothing exceptional
856 * happens till we had time to initialize ourselves..
857 */
858	BSS(lowram,4)
859	BSS(esym,4)
860
861	.globl	_C_LABEL(edata)
862	.globl	_C_LABEL(etext),_C_LABEL(end)
863
864GLOBAL(bootversion)
865	.word	0x0003			|  Glues kernel/installboot/loadbsd
866					|    and other bootcode together.
867ASENTRY_NOPROFILE(start)
868	movw	#PSL_HIGHIPL,%sr	| No interrupts
869
870	/*
871	 * a0 = start of loaded kernel
872	 * a1 = value of esym
873	 * d0 = fastmem size
874	 * d1 = stmem size
875	 * d2 = cputype
876	 * d3 = boothowto
877	 * d4 = size of loaded kernel
878	 */
879	movl	#8,%a5			| Addresses 0-8 are mapped to ROM on the
880	addql	#8,%a0			|  atari ST. We cannot set these.
881	subl	#8,%d4
882
883	/*
884	 * Copy until end of kernel relocation code.
885	 */
886Lstart0:
887	movl	%a0@+,%a5@+
888	subl	#4, %d4
889	cmpl	#Lstart3,%a5
890	jle	Lstart0
891	/*
892	 * Enter kernel at destination address and continue copy
893	 * Make sure that the jump is absolute (by adding ':l') otherwise
894	 * the assembler tries to use a pc-relative jump.
895	 * Which is definitely not what is needed at this point!
896	 */
897	jmp	Lstart2:l
898Lstart2:
899	movl	%a0@+,%a5@+		| copy the rest of the kernel
900	subl	#4, %d4
901	jcc	Lstart2
902Lstart3:
903
904	lea	_ASM_LABEL(tmpstk),%sp	| give ourselves a temporary stack
905
906	/*
907	 *  save the passed parameters. `prepass' them on the stack for
908	 *  later catch by _start_c
909	 */
910	movl	%a1,%sp@-		| pass address of _esym
911	movl	%d1,%sp@-		| pass stmem-size
912	movl	%d0,%sp@-		| pass fastmem-size
913	movl	%d5,%sp@-		| pass fastmem_start
914	movl	%d2,%sp@-		| pass machine id
915	movl	%d3,_C_LABEL(boothowto)	| save reboot flags
916
917
918	/*
919	 * Set cputype and mmutype dependent on the machine-id passed
920	 * in from the loader. Also make sure that all caches are cleared.
921	 */
922	movl	#ATARI_68030,%d1		| 68030 type from loader
923	andl	%d2,%d1
924	jeq	Ltestfor020			| Not an 68030, try 68020
925	movl	#MMU_68030,_C_LABEL(mmutype)	| Use 68030 MMU
926	movl	#CPU_68030,_C_LABEL(cputype)	|   and a 68030 CPU
927	movl	#CACHE_OFF,%d0			| 68020/030 cache clear
928	jra	Lend_cpuset			| skip to init.
929Ltestfor020:
930	movl	#ATARI_68020,%d1		| 68020 type from loader
931	andl	%d2,%d1
932	jeq	Ltestfor040
933	movl	#MMU_68851,_C_LABEL(mmutype)	| Assume 68851 with 68020
934	movl	#CPU_68020,_C_LABEL(cputype)	|   and a 68020 CPU
935	movl	#CACHE_OFF,%d0			| 68020/030 cache clear
936	jra	Lend_cpuset			| skip to init.
937Ltestfor040:
938	movl	#CACHE_OFF,%d0			| 68020/030 cache
939	movl	#ATARI_68040,%d1
940	andl	%d2,%d1
941	jeq	Ltestfor060
942	movl	#MMU_68040,_C_LABEL(mmutype)	| Use a 68040 MMU
943	movl	#CPU_68040,_C_LABEL(cputype)	|   and a 68040 CPU
944	.word	0xf4f8				| cpusha bc - push&inval caches
945	movl	#CACHE40_OFF,%d0		| 68040 cache disable
946	jra	Lend_cpuset			| skip to init.
947Ltestfor060:
948	movl    #ATARI_68060,%d1
949	andl	%d2,%d1
950	jeq	Lend_cpuset
951	movl	#MMU_68040,_C_LABEL(mmutype)	| Use a 68040 MMU
952	movl	#CPU_68060,_C_LABEL(cputype)	|   and a 68060 CPU
953	.word	0xf4f8				| cpusha bc - push&inval caches
954	movl	#CACHE40_OFF,%d0		| 68040 cache disable
955	orl	#IC60_CABC,%d0			|   and clear  060 branch cache
956
957Lend_cpuset:
958	movc	%d0,%cacr		| clear and disable on-chip cache(s)
959	movl	#_C_LABEL(vectab),%a0	| set address of vector table
960	movc	%a0,%vbr
961
962	/*
963	 * Initialize source/destination control registers for movs
964	 */
965	moveq	#FC_USERD,%d0		| user space
966	movc	%d0,%sfc		|   as source
967	movc	%d0,%dfc		|   and destination of transfers
968
969	/*
970	 * let the C function initialize everything and enable the MMU
971	 */
972	jsr	_C_LABEL(start_c)
973
974	/*
975	 * set kernel stack, user SP
976	 */
977	movl	_C_LABEL(lwp0uarea),%a1	| grab lwp0 uarea
978	lea	%a1@(USPACE-4),%sp	| set kernel stack to end of area
979	movl	#USRSTACK-4,%a2
980	movl	%a2,%usp		| init user SP
981	movl	%a2,%a1@(PCB_USP)	| and save it
982	clrw	%a1@(PCB_FLAGS)		| clear flags
983
984	/* flush TLB and turn on caches */
985	jbsr	_C_LABEL(_TBIA)		|  invalidate TLB
986	movl	#CACHE_ON,%d0
987	cmpl	#MMU_68040,_C_LABEL(mmutype)
988	jne	Lcacheon
989	/*  is this needed? MLH */
990	.word	0xf4f8			|  cpusha bc - push & invalidate caches
991	movl	#CACHE40_ON,%d0
992#ifdef M68060
993	cmpl	#CPU_68060,_C_LABEL(cputype)
994	jne	Lcacheon
995	movl	#CACHE60_ON,%d0
996#endif
997Lcacheon:
998	movc	%d0,%cacr		|  clear cache(s)
999
1000	/*
1001	 * Final setup for C code
1002	 */
1003#ifdef notdef
1004	movl	%d6,_C_LABEL(bootdev)	|    and boot device
1005#endif
1006
1007	/*
1008	 * Create a fake exception frame that returns to user mode,
1009	 * make space for the rest of a fake saved register set, and
1010	 * pass a pointer to the register set to "main()".
1011	 * "main()" will call "icode()", which fakes
1012	 * an "execve()" system call, which is why we need to do that
1013	 * ("main()" sets "u.u_ar0" to point to the register set).
1014	 * When "main()" returns, we're running in process 1 and have
1015	 * successfully faked the "execve()".  We load up the registers from
1016	 * that set; the "rte" loads the PC and PSR, which jumps to "init".
1017	 */
1018	movl	#0,%a6			|  make DDB stack_trace() work
1019	clrw	%sp@-			|  vector offset/frame type
1020	clrl	%sp@-			|  PC - filled in by "execve"
1021	movw	#PSL_USER,%sp@-		|  in user mode
1022	clrl	%sp@-			|  stack adjust count
1023	lea	%sp@(-64),%sp		|  construct space for D0-D7/A0-A7
1024	lea	_C_LABEL(lwp0),%a0	| lwp0 in a0
1025	movl	%sp,%a0@(L_MD_REGS)     | save frame for lwp0
1026	movl	%usp,%a1
1027	movl	%a1,%sp@(FR_SP)		| save user stack pointer in frame
1028	pea	%sp@			|  addr of space for D0
1029	jbsr	_C_LABEL(main)		|  main(r0)
1030	addql	#4,%sp			|  pop args
1031	cmpl	#MMU_68040,_C_LABEL(mmutype)
1032	jne	Lnoflush		|  Not an 68040, skip flush
1033	.word	0xf478			|  cpusha dc
1034	.word	0xf498			|  cinva ic
1035Lnoflush:
1036	movl	%sp@(FR_SP),%a0		|  grab and load
1037	movl	%a0,%usp		|    user SP
1038	moveml	%sp@+,#0x7FFF		|  load most registers (all but SSP)
1039	addql	#8,%sp			|  pop SSP and stack adjust count
1040	rte
1041
1042/*
1043 * Use common m68k sigcode.
1044 */
1045#include <m68k/m68k/sigcode.s>
1046#ifdef COMPAT_SUNOS
1047#include <m68k/m68k/sunos_sigcode.s>
1048#endif
1049
1050/*
1051 * Primitives
1052 */
1053
1054/*
1055 * Use common m68k support routines.
1056 */
1057#include <m68k/m68k/support.s>
1058
1059/*
1060 * non-local gotos
1061 */
1062ENTRY(qsetjmp)
1063	movl	%sp@(4),%a0		|  savearea pointer
1064	lea	%a0@(40),%a0		|  skip regs we do not save
1065	movl	%a6,%a0@+		|  save FP
1066	movl	%sp,%a0@+		|  save SP
1067	movl	%sp@,%a0@		|  and return address
1068	moveq	#0,%d0			|  return 0
1069	rts
1070
1071/*
1072 * Use common m68k process/lwp switch and context save subroutines.
1073 */
1074#define FPCOPROC
1075#include <m68k/m68k/switch_subr.s>
1076
1077
1078#if defined(M68040)
1079ENTRY(suline)
1080	movl	%sp@(4),%a0		| address to write
1081	movl	_C_LABEL(curpcb),%a1	| current pcb
1082	movl	#Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault
1083	movl	%sp@(8),%a1		| address of line
1084	movl	%a1@+,%d0		| get lword
1085	movsl	%d0,%a0@+		| put lword
1086	nop				| sync
1087	movl	%a1@+,%d0		| get lword
1088	movsl	%d0,%a0@+		| put lword
1089	nop				| sync
1090	movl	%a1@+,%d0		| get lword
1091	movsl	%d0,%a0@+		| put lword
1092	nop				| sync
1093	movl	%a1@+,%d0		| get lword
1094	movsl	%d0,%a0@+		| put lword
1095	nop				| sync
1096	moveq	#0,%d0			| indicate no fault
1097	jra	Lsldone
1098Lslerr:
1099	moveq	#-1,%d0
1100Lsldone:
1101	movl	_C_LABEL(curpcb),%a1	| current pcb
1102	clrl	%a1@(PCB_ONFAULT)	| clear fault address
1103	rts
1104#endif /* defined(M68040) */
1105
1106ENTRY(ecacheon)
1107	rts
1108
1109ENTRY(ecacheoff)
1110	rts
1111
1112/*
1113 * Get callers current SP value.
1114 * Note that simply taking the address of a local variable in a C function
1115 * doesn't work because callee saved registers may be outside the stack frame
1116 * defined by A6 (e.g. GCC generated code).
1117 */
1118ENTRY_NOPROFILE(getsp)
1119	movl	%sp,%d0			|  get current SP
1120	addql	#4,%d0			|  compensate for return address
1121	rts
1122
1123/*
1124 * Check out a virtual address to see if it's okay to write to.
1125 *
1126 * probeva(va, fc)
1127 *
1128 */
1129ENTRY(probeva)
1130	movl	%sp@(8),%d0
1131	movec	%d0,%dfc
1132	movl	%sp@(4),%a0
1133	.word	0xf548			|  ptestw (a0)
1134	moveq	#FC_USERD,%d0		|  restore DFC to user space
1135	movc	%d0,%dfc
1136	.word	0x4e7a,0x0805		|  movec  MMUSR,d0
1137	rts
1138
1139/*
1140 * Load a new user segment table pointer.
1141 */
1142ENTRY(loadustp)
1143	movl	%sp@(4),%d0			| new USTP
1144	moveq	#PGSHIFT,%d1
1145	lsll	%d1,%d0				| convert to addr
1146#if defined(M68060)
1147	cmpl	#CPU_68060,_C_LABEL(cputype)	| 68060?
1148	jeq	Lldustp060			|  yes, skip
1149#endif
1150	cmpl	#MMU_68040,_C_LABEL(mmutype)	| 68040?
1151	jeq	Lldustp040			|  yes, skip
1152	pflusha					| flush entire TLB
1153	lea	_C_LABEL(protorp),%a0		| CRP prototype
1154	movl	%d0,%a0@(4)			| stash USTP
1155	pmove	%a0@,%crp			| load root pointer
1156	movl	#CACHE_CLR,%d0
1157	movc	%d0,%cacr			| invalidate on-chip d-cache
1158	rts
1159#if defined(M68060)
1160Lldustp060:
1161	movc	%cacr,%d1
1162	orl	#IC60_CUBC,%d1		| clear user branch cache entries
1163	movc	%d1,%cacr
1164#endif
1165Lldustp040:
1166	.word	0xf518			| pflusha
1167	.word	0x4e7b,0x0806		| movec d0,URP
1168	rts
1169
1170/*
1171 * Flush any hardware context associated with given USTP.
1172 * Only does something for HP330 where we must flush RPT
1173 * and ATC entries in PMMU.
1174 */
1175ENTRY(flushustp)
1176#if defined(M68060)
1177	cmpl	#CPU_68060,_C_LABEL(cputype)
1178	jeq	Lflustp060		|  A 060 needs special treatment
1179#endif
1180	cmpl	#MMU_68040,_C_LABEL(mmutype)
1181	jeq	Lnot68851
1182	tstl	_C_LABEL(mmutype)	|  68851 PMMU?
1183	jle	Lnot68851		|  no, nothing to do
1184	movl	%sp@(4),%d0		|  get USTP to flush
1185	moveq	#PGSHIFT,%d1
1186	lsll	%d1,%d0			|  convert to address
1187	movl	%d0,_C_LABEL(protorp)+4	|  stash USTP
1188	pflushr	_C_LABEL(protorp)	|  flush RPT/TLB entries
1189Lnot68851:
1190	rts
1191#if defined(M68060)
1192Lflustp060:
1193	movc	%cacr,%d1
1194	orl	IC60_CUBC,%d1		| clear user branch cache entries
1195	movc	%d1,%cacr
1196	rts
1197#endif
1198
1199ENTRY(ploadw)
1200	movl	%sp@(4),%a0		|  address to load
1201	cmpl	#MMU_68040,_C_LABEL(mmutype)
1202	jeq	Lploadw040
1203	ploadw	#1,%a0@			|  pre-load translation
1204Lploadw040:				|  should 68040 do a ptest?
1205	rts
1206
1207/*
1208 * Set processor priority level calls.  Most are implemented with
1209 * inline asm expansions.  However, spl0 requires special handling
1210 * as we need to check for our emulated software interrupts.
1211 */
1212
1213ENTRY(spl0)
1214	moveq	#0,%d0
1215	movw	%sr,%d0			|  get old SR for return
1216	movw	#PSL_LOWIPL,%sr		|  restore new SR
1217	tstb	_C_LABEL(ssir)		|  software interrupt pending?
1218	jeq	Lspldone		|  no, all done
1219	subql	#4,%sp			|  make room for RTE frame
1220	movl	%sp@(4),%sp@(2)		|  position return address
1221	clrw	%sp@(6)			|  set frame type 0
1222	movw	#PSL_LOWIPL,%sp@	|  and new SR
1223	jra	Lgotsir			|  go handle it
1224Lspldone:
1225	rts
1226
1227/*
1228 * Handle the nitty-gritty of rebooting the machine.
1229 *
1230 */
1231ENTRY_NOPROFILE(doboot)
1232	movl	#CACHE_OFF,%d0
1233	cmpl	#MMU_68040,_C_LABEL(mmutype) |  is it 68040?
1234	jne	Ldoboot0
1235	.word	0xf4f8			|  cpusha bc - push and inval caches
1236	nop
1237	movl	#CACHE40_OFF,%d0
1238Ldoboot0:
1239	movc	%d0,%cacr		|  disable on-chip cache(s)
1240
1241	movw	#0x2700,%sr		|  cut off any interrupts
1242
1243	/*
1244	 * Clear first 2k of ST-memory. We start clearing at address 0x8
1245	 * because the lower 8 bytes are mapped to ROM.
1246	 * This makes sure that the machine will 'cold-boot'.
1247	 */
1248	movl	_C_LABEL(page_zero),%a0
1249	addl	#0x8,%a0
1250	movl	#512,%d0
1251Ldb1:
1252	clrl	%a0@+
1253	dbra	%d0,Ldb1
1254
1255	lea	Ldoreboot,%a1		| a1 = start of copy range
1256	lea	Ldorebootend,%a2	| a2 = end of copy range
1257	movl	_C_LABEL(page_zero),%a0	| a0 = virtual base for page zero
1258	addl	%a1,%a0			|		+ offset of Ldoreboot
1259Ldb2:					| Do the copy
1260	movl	%a1@+,%a0@+
1261	cmpl	%a2,%a1
1262	jle	Ldb2
1263
1264	/*
1265	 * Ok, turn off MMU..
1266	 */
1267Ldoreboot:
1268	cmpl	#MMU_68040,_C_LABEL(mmutype)
1269	jeq	Lmmuoff040		| Go turn off 68040 MMU
1270	lea	_ASM_LABEL(zero),%a0
1271	pmove	%a0@,%tc		| Turn off MMU
1272	lea	_ASM_LABEL(nullrp),%a0
1273	pmove	%a0@,%crp		| Invalidate CPU root pointer
1274	pmove	%a0@,%srp		|  and the Supervisor root pointer
1275	jra	Ldoboot1		| Ok, continue with actual reboot
1276Lmmuoff040:
1277	movl	#0,%d0
1278	.word	0x4e7b,0x0003		|  movc d0,TC
1279	.word	0x4e7b,0x0806		|  movc d0,URP
1280	.word	0x4e7b,0x0807		|  movc d0,SRP
1281
1282Ldoboot1:
1283	movl	#0, %a0
1284	movc	%a0,%vbr
1285	movl	%a0@(4), %a0		| fetch reset-vector
1286	jmp	%a0@			| jump through it
1287	/* NOTREACHED */
1288
1289/*  A do-nothing MMU root pointer (includes the following long as well) */
1290
1291ASLOCAL(nullrp)
1292	.long	0x7fff0001
1293ASLOCAL(zero)
1294	.long	0
1295Ldorebootend:
1296
1297	.data
1298	.p2align 2
1299	.space	PAGE_SIZE
1300ASLOCAL(tmpstk)
1301GLOBAL(protorp)
1302	.long	0x80000002,0		|  prototype root pointer
1303
1304#ifdef M68060 /* XXX */
1305L60iem:		.long	0
1306L60fpiem:	.long	0
1307L60fpdem:	.long	0
1308L60fpeaem:	.long	0
1309L60bpe:		.long	0
1310#endif
1311#ifdef DEBUG
1312
1313ASLOCAL(fulltflush)
1314	.long	0
1315ASLOCAL(fullcflush)
1316	.long	0
1317GLOBAL(timebomb)
1318	.long	0
1319#endif
1320ASLOCAL(plx_nonmi)
1321	.long	0
1322GLOBAL(plx_status)
1323	.long	0
1324
1325/* interrupt counters & names */
1326#include <atari/atari/intrcnt.h>
1327