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