xref: /netbsd/sys/arch/mvme68k/mvme68k/locore.s (revision bf9ec67e)
1/*	$NetBSD: locore.s,v 1.89 2002/05/14 02:03:02 matt Exp $	*/
2
3/*
4 * Copyright (c) 1988 University of Utah.
5 * Copyright (c) 1980, 1990, 1993
6 *	The Regents of the University of California.  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.66 92/12/22$
41 *
42 *	@(#)locore.s	8.6 (Berkeley) 5/27/94
43 */
44
45#include "opt_compat_netbsd.h"
46#include "opt_compat_svr4.h"
47#include "opt_compat_sunos.h"
48#include "opt_fpsp.h"
49#include "opt_ddb.h"
50#include "opt_kgdb.h"
51#include "opt_lockdebug.h"
52
53#include "assym.h"
54#include <machine/asm.h>
55#include <machine/trap.h>
56
57
58/*
59 * Temporary stack for a variety of purposes.
60 * Try and make this the first thing is the data segment so it
61 * is page aligned.  Note that if we overflow here, we run into
62 * our text segment.
63 */
64	.data
65	.space	NBPG
66ASLOCAL(tmpstk)
67
68ASLOCAL(bug_vbr)
69	.long	0
70
71#include <mvme68k/mvme68k/vectors.s>
72
73
74/*
75 * Macro to relocate a symbol, used before MMU is enabled.
76 */
77#define	_RELOC(var, ar)		\
78	lea	var,ar
79
80#define	RELOC(var, ar)		_RELOC(_C_LABEL(var), ar)
81#define	ASRELOC(var, ar)	_RELOC(_ASM_LABEL(var), ar)
82
83/*
84 * Macro to call into the Bug ROM monitor
85 */
86#define	CALLBUG(func)	\
87	trap #15; .short func
88
89/*
90 * Initialization
91 *
92 * The bootstrap loader loads us in starting at 0, and VBR is non-zero.
93 * On entry, args on stack are boot device, boot filename, console unit,
94 * boot flags (howto), boot device name, filesystem type name.
95 */
96BSS(lowram,4)
97BSS(esym,4)
98
99	.globl	_C_LABEL(edata)
100	.globl	_C_LABEL(etext),_C_LABEL(end)
101
102
103/*
104 * This is for kvm_mkdb, and should be the address of the beginning
105 * of the kernel text segment (not necessarily the same as kernbase).
106 */
107	.text
108GLOBAL(kernel_text)
109
110/*
111 * start of kernel and .text!
112 */
113ASENTRY_NOPROFILE(start)
114	movw	#PSL_HIGHIPL,%sr	| no interrupts
115	movl	#0,%a5			| RAM starts at 0 (a5)
116	movl	%sp@(4), %d7		| get boothowto
117	movl	%sp@(8), %d6		| get bootaddr
118	movl	%sp@(12),%d5		| get bootctrllun
119	movl	%sp@(16),%d4		| get bootdevlun
120	movl	%sp@(20),%d3		| get bootpart
121	movl	%sp@(24),%d2		| get esyms
122
123	RELOC(bootpart,%a0)
124	movl	%d3, %a0@		| save bootpart
125	RELOC(bootdevlun,%a0)
126	movl	%d4, %a0@		| save bootdevlun
127	RELOC(bootctrllun,%a0)
128	movl	%d5, %a0@		| save booctrllun
129	RELOC(bootaddr,%a0)
130	movl	%d6, %a0@		| save bootaddr
131	RELOC(boothowto,%a0)
132	movl	%d7, %a0@		| save boothowto
133	/* note: d3-d7 free, d2 still in use */
134
135	ASRELOC(tmpstk, %a0)
136	movl	%a0,%sp			| give ourselves a temporary stack
137
138	RELOC(edata,%a0)		| clear out BSS
139	movl	#_C_LABEL(end) - 4, %d0	| (must be <= 256 kB)
140	subl	#_C_LABEL(edata), %d0
141	lsrl	#2,%d0
1421:	clrl	%a0@+
143	dbra	%d0,1b
144
145	RELOC(esym, %a0)
146	movl	%d2,%a0@		| store end of symbol table
147	/* d2 now free */
148	RELOC(lowram, %a0)
149	movl	%a5,%a0@		| store start of physical memory
150	movl	#CACHE_OFF,%d0
151	movc	%d0,%cacr		| clear and disable on-chip cache(s)
152
153	/* ask the Bug what we are... */
154	clrl	%sp@-
155	CALLBUG(MVMEPROM_GETBRDID)
156	movl	%sp@+,%a1
157
158	/* copy to a struct mvmeprom_brdid */
159	movl	#MVMEPROM_BRDID_SIZE,%d0
160	RELOC(boardid,%a0)
1611:	movb	%a1@+,%a0@+
162	subql	#1,%d0
163	jbne	1b
164
165	/*
166	 * Grab the model number from _boardid and use the value
167	 * to setup machineid, cputype, and mmutype.
168	 */
169	clrl	%d0
170	RELOC(boardid,%a1)
171	movw	%a1@(MVMEPROM_BRDID_MODEL_OFFSET),%d0
172	RELOC(machineid,%a0)
173	movl	%d0,%a0@
174
175	ASRELOC(Lbrdid2mach,%a0)
176Lbrdmatch:
177	cmpw	%a0@+,%d0
178	jbeq	Lgotmatch
179	addw	#0x12,%a0		| Each entry is 20-2 bytes long
180	tstw	%a0@
181	jbne	Lbrdmatch
182
183	/*
184	 * If we fall to here, the board is not supported.
185	 * Print a warning, then drop out to the Bug.
186	 */
187	movl	#Lenotconf,%sp@-
188	movl	#Lnotconf,%sp@-
189	CALLBUG(MVMEPROM_OUTSTRCRLF)
190	addql	#8,%sp			| clean up stack after call
191
192	CALLBUG(MVMEPROM_EXIT)
193	/* NOTREACHED */
194
195	.data
196Lnotconf:
197	.ascii	"Sorry, the kernel isn't configured for this model."
198Lenotconf:
199	.even
200
201ASLOCAL(Lbrdid2mach)
202#ifdef MVME147
203	.word	MVME_147
204	.word		CPU_68030
205	.word		MMU_68030
206	.word		FPU_68882
207	.long		_C_LABEL(busaddrerr2030)
208	.long		_C_LABEL(busaddrerr2030)
209	.long		Linit147
210#endif
211#ifdef MVME162
212	.word	MVME_162
213	.word		CPU_68040
214	.word		MMU_68040
215	.word		FPU_68040
216	.long		_C_LABEL(buserr40)
217	.long		_C_LABEL(addrerr4060)
218	.long		Linit1x2
219#endif
220#ifdef MVME167
221	.word	MVME_167
222	.word		CPU_68040
223	.word		MMU_68040
224	.word		FPU_68040
225	.long		_C_LABEL(buserr40)
226	.long		_C_LABEL(addrerr4060)
227	.long		Linit1x7
228#endif
229#ifdef MVME172
230	.word	MVME_172
231	.word		CPU_68060
232	.word		MMU_68040
233	.word		FPU_68060
234	.long		_C_LABEL(buserr60)
235	.long		_C_LABEL(addrerr4060)
236	.long		Linit1x2
237#endif
238#ifdef MVME177
239	.word	MVME_177
240	.word		CPU_68060
241	.word		MMU_68040
242	.word		FPU_68060
243	.long		_C_LABEL(buserr60)
244	.long		_C_LABEL(addrerr4060)
245	.long		Linit1x7
246#endif
247	.word	0
248	.text
249	.even
250
251/*
252 * We have a match, so the kernel should support this board.
253 * a0 points to the matching entry in Lbrdid2mach.
254 */
255Lgotmatch:
256	movew	%a0@+,%d1		| Copy the CPU type
257	extl	%d1
258	RELOC(cputype,%a1)
259	movel	%d1,%a1@
260	movew	%a0@+,%d1		| Copy the MMU type
261	extl	%d1
262	RELOC(mmutype,%a1)
263	movel	%d1,%a1@
264	movew	%a0@+,%d1		| Copy the FPU type
265	extl	%d1
266	RELOC(fputype,%a1)
267	movel	%d1,%a1@
268	movel	%a0@+,%a2		| Fetch the bus error vector
269	RELOC(vectab,%a1)
270	movl	%a2,%a1@(8)
271	movel	%a0@+,%a2		| Fetch the address error vector
272	movl	%a2,%a1@(12)
273	movel	%a0@,%a0		| Finally, the board-specific init code
274	jmp	%a0@
275
276
277#ifdef MVME147
278Linit147:
279	/* MVME-147 - 68030 CPU/MMU, 68882 FPU */
280	/* XXXCDC SHUTUP 147 CALL */
281	movb	#0, 0xfffe1026		| serial interrupt off
282	movb	#0, 0xfffe1018		| timer 1 off
283	movb	#0, 0xfffe1028		| ethernet off
284	/* XXXCDC SHUTUP 147 CALL */
285
286	/* Save our ethernet address */
287	RELOC(mvme_ea, %a0)
288	lea	0xfffe0778,%a1		| XXXCDC -- HARDWIRED HEX
289	movb	#0x08,%a0@+
290	clrb	%a0@+
291	movb	#0x3e,%a0@+
292	movql	#0x0f,%d0
293	andb	%a1@+,%d0
294	orb	#0x20,%d0
295	movb	%d0,%a0@+
296	movb	%a1@+,%a0@+
297	movb	%a1@,%a0@
298
299	/*
300	 * Fix up the physical addresses of the MVME147's onboard
301	 * I/O registers.
302	 */
303	RELOC(intiobase_phys, %a0);
304	movl	#INTIOBASE147,%a0@
305	RELOC(intiotop_phys, %a0);
306	movl	#INTIOTOP147,%a0@
307
308	/* initialise list of physical memory segments for pmap_bootstrap */
309	RELOC(phys_seg_list, %a0)
310	movl	%a5,%a0@		| phys_seg_list[0].ps_start
311	movl	0xfffe0774,%d1		| End + 1 of onboard memory
312	movl	%d1,%a0@(4)		| phys_seg_list[0].ps_end
313	clrl	%a0@(8)			| phys_seg_list[0].ps_startpage
314
315	/* offboard RAM */
316	clrl	%a0@(0x0c)		| phys_seg_list[1].ps_start
317	movl	#NBPG-1,%d0
318	addl	0xfffe0764,%d0		| Start of offboard segment
319	andl	#-NBPG,%d0		| Round up to page boundary
320	jbeq	Lsavmaxmem		| Jump if none defined
321	movl	#NBPG,%d1		| Note: implicit '+1'
322	addl	0xfffe0768,%d1		| End of offboard segment
323	andl	#-NBPG,%d1		| Round up to page boundary
324	cmpl	%d1,%d0			| Quick and dirty validity check
325	jbcs	Loff_ok			| Yup, looks good.
326	movel	%a0@(4),%d1		| Just use onboard RAM otherwise
327	jbra	Lsavmaxmem
328Loff_ok:
329	movl	%d0,%a0@(0x0c)		| phys_seg_list[1].ps_start
330	movl	%d1,%a0@(0x10)		| phys_seg_list[1].ps_end
331	clrl	%a0@(0x14)		| phys_seg_list[1].ps_startpage
332
333	/*
334	 * Offboard RAM needs to be cleared to zero to initialise parity
335	 * on most VMEbus RAM cards. Without this, some cards will buserr
336	 * when first read.
337	 */
338	movel	%d0,%a0			| offboard start address again.
339Lclearoff:
340	clrl	%a0@+			| zap a word
341	cmpl	%a0,%d1			| reached end?
342	jbne	Lclearoff
343
344Lsavmaxmem:
345	moveq	#PGSHIFT,%d2
346	lsrl	%d2,%d1			| convert to page (click) number
347	RELOC(maxmem, %a0)
348	movl	%d1,%a0@		| save as maxmem
349	jra	Lstart1
350#endif
351
352#if defined(MVME162) || defined(MVME172)
353Linit1x2:
354	/* MVME-162 - 68040 CPU/MMU/FPU */
355	/* MVME-172 - 68060 CPU/MMU/FPU */
356
357	/*
358	 * Verify the user has removed the GPIO#0 jumper...
359	 */
360	btst	#0,0xfff4202d		| Clear == jumper installed
361	jne	1f			| Ok.
362
363	movl	#Le1x2jump,%sp@-
364	movl	#L1x2jump,%sp@-
365	CALLBUG(MVMEPROM_OUTSTRCRLF)
366	addql	#8,%sp			| clean up stack after call
367
368	CALLBUG(MVMEPROM_EXIT)
369	/* NOTREACHED */
370
3711:
372	/*
373	 * Determine if this board has a VMEchip2
374	 */
375	btst	#1,0xfff4202e		| VMEchip2 presence detect
376	jne	2f			| Jump if it doesn't exist.
377
378	/*
379	 * Disable all interrupts from VMEchip2. This is especially
380	 * useful when the kernel doesn't have the VMEchip2 driver
381	 * configured. If we didn't do this, then we're at the mercy
382	 * of whatever VMEchip2 interrupts the ROM set up. For example,
383	 * hitting the ABORT switch could kill the system...
384	 */
385	movl	0xfff40088,%d0
386	andl	#0xff7fffff,%d0		| Clear 'MIEN'
387	movl	%d0,0xfff40088
3882:
389	/*
390	 * Determine how much onboard memory is installed
391	 */
392	movql	#0x07,%d0
393	andb	0xfff42024,%d0
394	ASRELOC(Ldramsize1x2,%a0)
395	movl	%a0@(%d0:w:4),%d1	| Lookup the size
396	jeq	Lmemcquery		| Assume a MEMC chip if this is zero.
397	jra	Lis1xx_common
398
399	.data
400	.even
401	/*
402	 * Table of DRAM register size values -> actual size in bytes
403	 */
404ASLOCAL(Ldramsize1x2)
405	.long	0x00100000
406	.long	0x00200000
407	.long	0x00000000
408	.long	0x00400000
409	.long	0x00400000
410	.long	0x00800000
411	.long	0x00000000
412	.long	0x01000000
413
414L1x2jump:
415	.ascii	"You must remove the jumper from pins 15-16 of J22 (mvme162)"
416	.ascii	"or pins 1-2\015\012"
417	.ascii	"J11 (mvme162-LX) first! See NetBSD/mvme68k FAQ for details."
418Le1x2jump:
419	.even
420
421	.text
422#endif
423
424#if defined(MVME167) || defined(MVME177)
425Linit1x7:
426	/* MVME-167 - 68040 CPU/MMU/FPU */
427	/* MVME-177 - 68060 CPU/MMU/FPU */
428
429	/*
430	 * Verify the user has removed the GPIO#0 jumper...
431	 */
432	movel	#0x00000001,%d0
433	andl	0xfff40088,%d0		| Clear == jumper installed
434	jne	1f			| Ok.
435
436	movl	#Le1x7jump,%sp@-
437	movl	#L1x7jump,%sp@-
438	CALLBUG(MVMEPROM_OUTSTRCRLF)
439	addql	#8,%sp			| clean up stack after call
440
441	CALLBUG(MVMEPROM_EXIT)
442	/* NOTREACHED */
443
4441:
445	/*
446	 * Disable all interrupts from VMEchip2. This is especially
447	 * useful when the kernel doesn't have the VMEchip2 driver
448	 * configured. If we didn't do this, then we're at the mercy
449	 * of whatever VMEchip2 interrupts the ROM set up. For example,
450	 * hitting the ABORT switch could kill the system...
451	 */
452	movl	0xfff40088,%d0
453	andl	#0xff7fffff,%d0		| Clear 'MIEN'
454	movl	%d0,0xfff40088
455
456	.data
457	.even
458L1x7jump:
459	.ascii	"You must remove the jumper from pins 1-2 of J1!\015\012"
460	.ascii	"See NetBSD/mvme68k FAQ for details."
461Le1x7jump:
462	.even
463
464	.text
465#endif
466
467#if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177)
468Lmemcquery:
469	/*
470	 * Figure out the size of onboard DRAM by querying
471	 * the memory controller ASIC(s)
472	 */
473	lea	0xfff43008,%a0		| MEMC040/MEMECC Controller #1
474	jbsr	memc040read
475	movl	%d0,%d1
476
477	lea	0xfff43108,%a0		| MEMC040/MEMECC Controller #2
478	jbsr	memc040read
479	addl	%d0,%d1
480
481Lis1xx_common:
482	/* Save our ethernet address */
483	RELOC(mvme_ea, %a0)
484	lea	0xfffc1f2c,%a1
485	movb	%a1@+,%a0@+
486	movb	%a1@+,%a0@+
487	movb	%a1@+,%a0@+
488	movb	%a1@+,%a0@+
489	movb	%a1@+,%a0@+
490	movb	%a1@,%a0@
491
492	/*
493	 * Fix up the physical addresses of the onboard
494	 * I/O registers.
495	 */
496	RELOC(intiobase_phys, %a0);
497	movl	#INTIOBASE1xx,%a0@
498	RELOC(intiotop_phys, %a0);
499	movl	#INTIOTOP1xx,%a0@
500
501	/*
502	 * Initialise first physical memory segment with onboard RAM details
503	 */
504	RELOC(phys_seg_list, %a0)
505	movl	%a5,%a0@		| phys_seg_list[0].ps_start
506	movl	%d1,%a0@(4)		| phys_seg_list[0].ps_end
507	clrl	%a0@(8)			| phys_seg_list[0].ps_startpage
508
509	/* offboard RAM */
510	clrl	%a0@(0x0c)		| phys_seg_list[1].ps_start
511	movl	#NBPG-1,%d0
512	addl	0xfffc0000,%d0		| Start of offboard segment
513	andl	#-NBPG,%d0		| Round up to page boundary
514	jbeq	Ldone1xx		| Jump if none defined
515	movl	#NBPG,%d1		| Note: implicit '+1'
516	addl	0xfffc0004,%d1		| End of offboard segment
517	andl	#-NBPG,%d1		| Round up to page boundary
518	cmpl	%d1,%d0			| Quick and dirty validity check
519	jbcs	Lramsave1xx		| Yup, looks good.
520	movel	%a0@(4),%d1		| Just use onboard RAM otherwise
521	jbra	Ldone1xx
522
523Lramsave1xx:
524	movl	%d0,%a0@(0x0c)		| phys_seg_list[1].ps_start
525	movl	%d1,%a0@(0x10)		| phys_seg_list[1].ps_end
526	clrl	%a0@(0x14)		| phys_seg_list[1].ps_startpage
527
528	/*
529	 * Offboard RAM needs to be cleared to zero to initialise parity
530	 * on most VMEbus RAM cards. Without this, some cards will buserr
531	 * when first read.
532	 */
533	movel	%d0,%a0			| offboard start address again.
534Lramclr1xx:
535	clrl	%a0@+			| zap a word
536	cmpl	%a0,%d1			| reached end?
537	jbne	Lramclr1xx
538
539Ldone1xx:
540	moveq	#PGSHIFT,%d2
541	lsrl	%d2,%d1			| convert to page (click) number
542	RELOC(maxmem, %a0)
543	movl	%d1,%a0@		| save as maxmem
544
545	/* FALLTHROUGH to Lstart1 */
546#endif
547
548
549Lstart1:
550/* initialize source/destination control registers for movs */
551	moveq	#FC_USERD,%d0		| user space
552	movc	%d0,%sfc		|   as source
553	movc	%d0,%dfc		|   and destination of transfers
554/*
555 * configure kernel and proc0 VA space so we can get going
556 */
557#ifdef DDB
558	RELOC(esym,%a0)			| end of static kernel text/data syms
559	movl	%a0@,%d2
560	jne	Lstart2
561#endif
562	movl	#_C_LABEL(end),%d2	| end of static kernel text/data
563Lstart2:
564	addl	#NBPG-1,%d2
565	andl	#PG_FRAME,%d2		| round to a page
566	movl	%d2,%a4
567	addl	%a5,%a4			| convert to PA
568	pea	%a5@			| firstpa
569	pea	%a4@			| nextpa
570	RELOC(pmap_bootstrap,%a0)
571	jbsr	%a0@			| pmap_bootstrap(firstpa, nextpa)
572	addql	#8,%sp
573
574/*
575 * Enable the MMU.
576 * Since the kernel is mapped logical == physical, we just turn it on.
577 */
578	RELOC(Sysseg, %a0)		| system segment table addr
579	movl	%a0@,%d1		| read value (a KVA)
580	addl	%a5,%d1			| convert to PA
581	RELOC(mmutype, %a0)
582	cmpl	#MMU_68040,%a0@		| 68040?
583	jne	Lmotommu1		| no, skip
584	.long	0x4e7b1807		| movc d1,srp
585	jra	Lstploaddone
586Lmotommu1:
587	RELOC(protorp, %a0)
588	movl	#0x80000202,%a0@	| nolimit + share global + 4 byte PTEs
589	movl	%d1,%a0@(4)		| + segtable address
590	pmove	%a0@,%srp		| load the supervisor root pointer
591	movl	#0x80000002,%a0@	| reinit upper half for CRP loads
592Lstploaddone:
593	RELOC(mmutype, %a0)
594	cmpl	#MMU_68040,%a0@		| 68040?
595	jne	Lmotommu2		| no, skip
596	moveq	#0,%d0			| ensure TT regs are disabled
597	.long	0x4e7b0004		| movc d0,itt0
598	.long	0x4e7b0005		| movc d0,itt1
599	.long	0x4e7b0006		| movc d0,dtt0
600	.long	0x4e7b0007		| movc d0,dtt1
601	.word	0xf4d8			| cinva bc
602	.word	0xf518			| pflusha
603	movl	#0x8000,%d0
604	.long	0x4e7b0003		| movc d0,tc
605#ifdef M68060
606	RELOC(cputype, %a0)
607	cmpl	#CPU_68060,%a0@		| 68060?
608	jne	Lnot060cache
609	movl	#1,%d0
610	.long	0x4e7b0808		| movcl d0,pcr
611	movl	#0xa0808000,%d0
612	movc	%d0,%cacr		| enable store buffer, both caches
613	jmp	Lenab1
614Lnot060cache:
615#endif
616	movl	#0x80008000,%d0
617	movc	%d0,%cacr		| turn on both caches
618	jmp	Lenab1
619Lmotommu2:
620	movl	#0x82c0aa00,%sp@-	| value to load TC with
621	pmove	%sp@,%tc		| load it
622
623/*
624 * Should be running mapped from this point on
625 */
626Lenab1:
627/* Point the cpu VBR at our vector table */
628	movc	%vbr,%d0		| Preserve Bug's VBR address
629	movl	%d0,_ASM_LABEL(bug_vbr)
630	movl	#_C_LABEL(vectab),%d0	| get our VBR address
631	movc	%d0,%vbr
632/* select the software page size now */
633	lea	_ASM_LABEL(tmpstk),%sp	| temporary stack
634	jbsr	_C_LABEL(uvm_setpagesize)  | select software page size
635/* set kernel stack, user SP, and initial pcb */
636	movl	_C_LABEL(proc0paddr),%a1 | get proc0 pcb addr
637	lea	%a1@(USPACE-4),%sp	| set kernel stack to end of area
638	lea	_C_LABEL(proc0),%a2	| initialize proc0.p_addr so that
639	movl	%a1,%a2@(P_ADDR)	|   we don't deref NULL in trap()
640	movl	#USRSTACK-4,%a2
641	movl	%a2,%usp		| init user SP
642	movl	%a1,_C_LABEL(curpcb)	| proc0 is running
643	tstl	_C_LABEL(fputype)	| Have an FPU?
644	jeq	Lenab2			| No, skip.
645	clrl	%a1@(PCB_FPCTX)		| ensure null FP context
646	movl	%a1,%sp@-
647	jbsr	_C_LABEL(m68881_restore) | restore it (does not kill a1)
648	addql	#4,%sp
649Lenab2:
650	cmpl	#MMU_68040,_C_LABEL(mmutype)	| 68040?
651	jeq	Ltbia040		| yes, cache already on
652	pflusha
653	movl	#CACHE_ON,%d0
654	movc	%d0,%cacr		| clear cache(s)
655	jra	Lenab3
656Ltbia040:
657	.word	0xf518
658Lenab3:
659/*
660 * final setup for C code:
661 * Create a fake exception frame so that cpu_fork() can copy it.
662 * main() nevers returns; we exit to user mode from a forked process
663 * later on.
664 */
665	jbsr	_C_LABEL(mvme68k_init)	| additional pre-main initialization
666	movw	#PSL_LOWIPL,%sr		| lower SPL
667	clrw	%sp@-			| vector offset/frame type
668	clrl	%sp@-			| PC - filled in by "execve"
669	movw	#PSL_USER,%sp@-		| in user mode
670	clrl	%sp@-			| stack adjust count and padding
671	lea	%sp@(-64),%sp		| construct space for D0-D7/A0-A7
672	lea	_C_LABEL(proc0),%a0	| save pointer to frame
673	movl	%sp,%a0@(P_MD_REGS)	|   in proc0.p_md.md_regs
674
675	jra	_C_LABEL(main)		| main()
676
677#if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177)
678/*
679 * Probe for a memory controller ASIC (MEMC040 or MEMECC) at the
680 * address in a0. If found, return the size in bytes of any RAM
681 * controlled by the ASIC in d0. Otherwise return zero.
682 */
683ASLOCAL(memc040read)
684	moveml	%d1-%d2/%a1-%a2,%sp@-	| save scratch regs
685	movc	%vbr,%d2		| Save vbr
686	RELOC(vectab,%a2)		| Install our own vectab, temporarily
687	movc	%a2,%vbr
688	ASRELOC(Lmemc040berr,%a1)	| get address of bus error handler
689	movl	%a2@(8),%sp@-		| Save current bus error handler addr
690	movl	%a1,%a2@(8)		| Install our own handler
691	movl	%sp,%d0			| Save current stack pointer value
692	movql	#0x07,%d1
693	andb	%a0@,%d1		| Access MEMC040/MEMECC
694	movl	#0x400000,%d0
695	lsll	%d1,%d0			| Convert to memory size, in bytes
696Lmemc040ret:
697	movc	%d2,%vbr		| Restore original vbr
698	movl	%sp@+,%a2@(8)		| Restore original bus error handler
699	moveml  %sp@+,%d1-%d2/%a1-%a2
700	rts
701/*
702 * If the memory controller doesn't exist, we get a bus error trying
703 * to access a0@ above. Control passes here, where we flag 'no bytes',
704 * ditch the exception frame and return as normal.
705 */
706Lmemc040berr:
707	movl	%d0,%sp			| Get rid of the exception frame
708	movql	#0,%d0			| No ASIC at this location, then!
709	jbra	Lmemc040ret		| Done
710#endif
711
712/*
713 * proc_trampoline: call function in register a2 with a3 as an arg
714 * and then rei.
715 */
716GLOBAL(proc_trampoline)
717	movl    %a3,%sp@-		| push function arg
718	jbsr    %a2@			| call function
719	addql   #4,%sp			| pop arg
720	movl    %sp@(FR_SP),%a0		| grab and load
721	movl    %a0,%usp		|   user SP
722	moveml  %sp@+,#0x7FFF		| restore most user regs
723	addql   #8,%sp			| toss SP and stack adjust
724	jra     _ASM_LABEL(rei)         | and return
725
726/*
727 * Trap/interrupt vector routines
728 */
729#include <m68k/m68k/trap_subr.s>
730
731#if defined(M68040) || defined(M68060)
732ENTRY_NOPROFILE(addrerr4060)
733	clrl	%sp@-			| stack adjust count
734	moveml	#0xFFFF,%sp@-		| save user registers
735	movl	%usp,%a0		| save the user SP
736	movl	%a0,%sp@(FR_SP)		|   in the savearea
737	movl	%sp@(FR_HW+8),%sp@-
738	clrl	%sp@-			| dummy code
739	movl	#T_ADDRERR,%sp@-	| mark address error
740	jra	_ASM_LABEL(faultstkadj)	| and deal with it
741#endif
742
743#if defined(M68060)
744ENTRY_NOPROFILE(buserr60)
745	clrl	%sp@-			| stack adjust count
746	moveml	#0xFFFF,%sp@-		| save user registers
747	movl	%usp,%a0		| save the user SP
748	movl	%a0,%sp@(FR_SP)		|   in the savearea
749	movel	%sp@(FR_HW+12),%d0	| FSLW
750	btst	#2,%d0			| branch prediction error?
751	jeq	Lnobpe
752	movc	%cacr,%d2
753	orl	#IC60_CABC,%d2		| clear all branch cache entries
754	movc	%d2,%cacr
755	movl	%d0,%d1
756	andl	#0x7ffd,%d1
757	jeq	_ASM_LABEL(faultstkadjnotrap2)
758Lnobpe:
759| we need to adjust for misaligned addresses
760	movl	%sp@(FR_HW+8),%d1	| grab VA
761	btst	#27,%d0			| check for mis-aligned access
762	jeq	Lberr3			| no, skip
763	addl	#28,%d1			| yes, get into next page
764					| operand case: 3,
765					| instruction case: 4+12+12
766	andl	#PG_FRAME,%d1		| and truncate
767Lberr3:
768	movl	%d1,%sp@-
769	movl	%d0,%sp@-		| code is FSLW now.
770	andw	#0x1f80,%d0
771	jeq	Lberr60			| it is a bus error
772	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
773	jra	_ASM_LABEL(faultstkadj)	| and deal with it
774Lberr60:
775	tstl	_C_LABEL(nofault)	| catch bus error?
776	jeq	Lisberr			| no, handle as usual
777	movl	_C_LABEL(nofault),%sp@-	| yes,
778	jbsr	_C_LABEL(longjmp)	|  longjmp(nofault)
779	/* NOTREACHED */
780#endif
781#if defined(M68040)
782ENTRY_NOPROFILE(buserr40)
783	clrl	%sp@-			| stack adjust count
784	moveml	#0xFFFF,%sp@-		| save user registers
785	movl	%usp,%a0		| save the user SP
786	movl	%a0,%sp@(FR_SP)		|   in the savearea
787	movl	%sp@(FR_HW+20),%d1	| get fault address
788	moveq	#0,%d0
789	movw	%sp@(FR_HW+12),%d0	| get SSW
790	btst	#11,%d0			| check for mis-aligned
791	jeq	Lbe1stpg		| no skip
792	addl	#3,%d1			| get into next page
793	andl	#PG_FRAME,%d1		| and truncate
794Lbe1stpg:
795	movl	%d1,%sp@-		| pass fault address.
796	movl	%d0,%sp@-		| pass SSW as code
797	btst	#10,%d0			| test ATC
798	jeq	Lberr40			| it is a bus error
799	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
800	jra	_ASM_LABEL(faultstkadj)	| and deal with it
801Lberr40:
802	tstl	_C_LABEL(nofault)	| catch bus error?
803	jeq	Lisberr			| no, handle as usual
804	movl	_C_LABEL(nofault),%sp@-	| yes,
805	jbsr	_C_LABEL(longjmp)	|  longjmp(nofault)
806	/* NOTREACHED */
807#endif
808
809#if defined(M68020) || defined(M68030)
810ENTRY_NOPROFILE(busaddrerr2030)
811	clrl	%sp@-			| stack adjust count
812	moveml	#0xFFFF,%sp@-		| save user registers
813	movl	%usp,%a0		| save the user SP
814	movl	%a0,%sp@(FR_SP)		|   in the savearea
815	moveq	#0,%d0
816	movw	%sp@(FR_HW+10),%d0	| grab SSW for fault processing
817	btst	#12,%d0			| RB set?
818	jeq	LbeX0			| no, test RC
819	bset	#14,%d0			| yes, must set FB
820	movw	%d0,%sp@(FR_HW+10)	| for hardware too
821LbeX0:
822	btst	#13,%d0			| RC set?
823	jeq	LbeX1			| no, skip
824	bset	#15,%d0			| yes, must set FC
825	movw	%d0,%sp@(FR_HW+10)	| for hardware too
826LbeX1:
827	btst	#8,%d0			| data fault?
828	jeq	Lbe0			| no, check for hard cases
829	movl	%sp@(FR_HW+16),%d1	| fault address is as given in frame
830	jra	Lbe10			| thats it
831Lbe0:
832	btst	#4,%sp@(FR_HW+6)	| long (type B) stack frame?
833	jne	Lbe4			| yes, go handle
834	movl	%sp@(FR_HW+2),%d1	| no, can use save PC
835	btst	#14,%d0			| FB set?
836	jeq	Lbe3			| no, try FC
837	addql	#4,%d1			| yes, adjust address
838	jra	Lbe10			| done
839Lbe3:
840	btst	#15,%d0			| FC set?
841	jeq	Lbe10			| no, done
842	addql	#2,%d1			| yes, adjust address
843	jra	Lbe10			| done
844Lbe4:
845	movl	%sp@(FR_HW+36),%d1	| long format, use stage B address
846	btst	#15,%d0			| FC set?
847	jeq	Lbe10			| no, all done
848	subql	#2,%d1			| yes, adjust address
849Lbe10:
850	movl	%d1,%sp@-		| push fault VA
851	movl	%d0,%sp@-		| and padded SSW
852	movw	%sp@(FR_HW+8+6),%d0	| get frame format/vector offset
853	andw	#0x0FFF,%d0		| clear out frame format
854	cmpw	#12,%d0			| address error vector?
855	jeq	Lisaerr			| yes, go to it
856	movl	%d1,%a0			| fault address
857	movl	%sp@,%d0		| function code from ssw
858	btst	#8,%d0			| data fault?
859	jne	Lbe10a
860	movql	#1,%d0			| user program access FC
861					| (we dont separate data/program)
862	btst	#5,%sp@(FR_HW+8)	| supervisor mode?
863	jeq	Lbe10a			| if no, done
864	movql	#5,%d0			| else supervisor program access
865Lbe10a:
866	ptestr	%d0,%a0@,#7		| do a table search
867	pmove	%psr,%sp@		| save result
868	movb	%sp@,%d1
869	btst	#2,%d1			| invalid (incl. limit viol. and berr)?
870	jeq	Lmightnotbemerr		| no -> wp check
871	btst	#7,%d1			| is it MMU table berr?
872	jne	Lisberr1		| yes, needs not be fast.
873Lismerr:
874	movl	#T_MMUFLT,%sp@-		| show that we are an MMU fault
875	jra	_ASM_LABEL(faultstkadj)	| and deal with it
876Lmightnotbemerr:
877	btst	#3,%d1			| write protect bit set?
878	jeq	Lisberr1		| no: must be bus error
879	movl	%sp@,%d0		| ssw into low word of d0
880	andw	#0xc0,%d0		| Write protect is set on page:
881	cmpw	#0x40,%d0		| was it read cycle?
882	jne	Lismerr			| no, was not WPE, must be MMU fault
883	jra	Lisberr1		| real bus err needs not be fast.
884Lisaerr:
885	movl	#T_ADDRERR,%sp@-	| mark address error
886	jra	_ASM_LABEL(faultstkadj)	| and deal with it
887Lisberr1:
888	clrw	%sp@			| re-clear pad word
889	tstl	_C_LABEL(nofault)	| catch bus error?
890	jeq	Lisberr			| no, handle as usual
891	movl	_C_LABEL(nofault),%sp@-	| yes,
892	jbsr	_C_LABEL(longjmp)	|  longjmp(nofault)
893	/* NOTREACHED */
894#endif /* M68020 || M68030 */
895
896Lisberr:				| also used by M68040/60
897	movl	#T_BUSERR,%sp@-		| mark bus error
898	jra	_ASM_LABEL(faultstkadj)	| and deal with it
899
900/*
901 * FP exceptions.
902 */
903ENTRY_NOPROFILE(fpfline)
904#if defined(M68040)
905	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
906	jne	Lfp_unimp		| no, skip FPSP
907	cmpw	#0x202c,%sp@(6)		| format type 2?
908	jne	_C_LABEL(illinst)	| no, not an FP emulation
909#ifdef FPSP
910	jmp	_ASM_LABEL(fpsp_unimp)	| yes, go handle it
911#else
912	clrl	%sp@-			| stack adjust count
913	moveml	#0xFFFF,%sp@-		| save registers
914	moveq	#T_FPEMULD,%d0		| denote as FP emulation trap
915	jra	_ASM_LABEL(fault)	| do it
916#endif
917Lfp_unimp:
918#endif /* M68040 */
919	jra	_C_LABEL(illinst)
920
921ENTRY_NOPROFILE(fpunsupp)
922#if defined(M68040)
923	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
924	jne	Lfp_unsupp		| No, skip FPSP
925#ifdef FPSP
926	jmp	_ASM_LABEL(fpsp_unsupp)	| yes, go handle it
927#else
928	clrl	%sp@-			| stack adjust count
929	moveml	#0xFFFF,%sp@-		| save registers
930	moveq	#T_FPEMULD,%d0		| denote as FP emulation trap
931	jra	_ASM_LABEL(fault)	| do it
932#endif
933Lfp_unsupp:
934#endif /* M68040 */
935	jra	_C_LABEL(illinst)
936
937/*
938 * Handles all other FP coprocessor exceptions.
939 * Note that since some FP exceptions generate mid-instruction frames
940 * and may cause signal delivery, we need to test for stack adjustment
941 * after the trap call.
942 */
943ENTRY_NOPROFILE(fpfault)
944	clrl	%sp@-		| stack adjust count
945	moveml	#0xFFFF,%sp@-	| save user registers
946	movl	%usp,%a0	| and save
947	movl	%a0,%sp@(FR_SP)	|   the user stack pointer
948	clrl	%sp@-		| no VA arg
949	movl	_C_LABEL(curpcb),%a0 | current pcb
950	lea	%a0@(PCB_FPCTX),%a0 | address of FP savearea
951	fsave	%a0@		| save state
952#if defined(M68040) || defined(M68060)
953	/* always null state frame on 68040, 68060 */
954	cmpl	#FPU_68040,_C_LABEL(fputype)
955	jle	Lfptnull
956#endif
957	tstb	%a0@		| null state frame?
958	jeq	Lfptnull	| yes, safe
959	clrw	%d0		| no, need to tweak BIU
960	movb	%a0@(1),%d0	| get frame size
961	bset	#3,%a0@(0,%d0:w) | set exc_pend bit of BIU
962Lfptnull:
963	fmovem	%fpsr,%sp@-	| push fpsr as code argument
964	frestore %a0@		| restore state
965	movl	#T_FPERR,%sp@-	| push type arg
966	jra	_ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup
967
968
969/*
970 * Other exceptions only cause four and six word stack frame and require
971 * no post-trap stack adjustment.
972 */
973
974ENTRY_NOPROFILE(badtrap)
975	moveml	#0xC0C0,%sp@-		| save scratch regs
976	movw	%sp@(22),%sp@-		| push exception vector info
977	clrw	%sp@-
978	movl	%sp@(22),%sp@-		| and PC
979	jbsr	_C_LABEL(straytrap)	| report
980	addql	#8,%sp			| pop args
981	moveml	%sp@+,#0x0303		| restore regs
982	jra	_ASM_LABEL(rei)		| all done
983
984ENTRY_NOPROFILE(trap0)
985	clrl	%sp@-			| stack adjust count
986	moveml	#0xFFFF,%sp@-		| save user registers
987	movl	%usp,%a0		| save the user SP
988	movl	%a0,%sp@(FR_SP)		|   in the savearea
989	movl	%d0,%sp@-		| push syscall number
990	jbsr	_C_LABEL(syscall)	| handle it
991	addql	#4,%sp			| pop syscall arg
992	tstl	_C_LABEL(astpending)	| AST pending?
993	jne	Lrei1			| Yup, go deal with it.
994	movl	%sp@(FR_SP),%a0		| grab and restore
995	movl	%a0,%usp		|   user SP
996	moveml	%sp@+,#0x7FFF		| restore most registers
997	addql	#8,%sp			| pop SP and stack adjust
998	rte
999
1000/*
1001 * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD)
1002 *	cachectl(command, addr, length)
1003 * command in d0, addr in a1, length in d1
1004 */
1005ENTRY_NOPROFILE(trap12)
1006	movl	_C_LABEL(curproc),%sp@-	| push curproc pointer
1007	movl	%d1,%sp@-		| push length
1008	movl	%a1,%sp@-		| push addr
1009	movl	%d0,%sp@-		| push command
1010	jbsr	_C_LABEL(cachectl1)	| do it
1011	lea	%sp@(16),%sp		| pop args
1012	jra	_ASM_LABEL(rei)		| all done
1013
1014/*
1015 * Trace (single-step) trap.  Kernel-mode is special.
1016 * User mode traps are simply passed on to trap().
1017 */
1018ENTRY_NOPROFILE(trace)
1019	clrl	%sp@-			| stack adjust count
1020	moveml	#0xFFFF,%sp@-
1021	moveq	#T_TRACE,%d0
1022
1023	| Check PSW and see what happen.
1024	|   T=0 S=0	(should not happen)
1025	|   T=1 S=0	trace trap from user mode
1026	|   T=0 S=1	trace trap on a trap instruction
1027	|   T=1 S=1	trace trap from system mode (kernel breakpoint)
1028
1029	movw	%sp@(FR_HW),%d1		| get PSW
1030	notw	%d1			| XXX no support for T0 on 680[234]0
1031	andw	#PSL_TS,%d1		| from system mode (T=1, S=1)?
1032	jeq	Lkbrkpt			| yes, kernel breakpoint
1033	jra	_ASM_LABEL(fault)	| no, user-mode fault
1034
1035/*
1036 * Trap 15 is used for:
1037 *	- GDB breakpoints (in user programs)
1038 *	- KGDB breakpoints (in the kernel)
1039 *	- trace traps for SUN binaries (not fully supported yet)
1040 * User mode traps are simply passed to trap().
1041 */
1042ENTRY_NOPROFILE(trap15)
1043	clrl	%sp@-			| stack adjust count
1044	moveml	#0xFFFF,%sp@-
1045	moveq	#T_TRAP15,%d0
1046	movw	%sp@(FR_HW),%d1		| get PSW
1047	andw	#PSL_S,%d1		| from system mode?
1048	jne	Lkbrkpt			| yes, kernel breakpoint
1049	jra	_ASM_LABEL(fault)	| no, user-mode fault
1050
1051Lkbrkpt: | Kernel-mode breakpoint or trace trap. (d0=trap_type)
1052	| Save the system sp rather than the user sp.
1053	movw	#PSL_HIGHIPL,%sr	| lock out interrupts
1054	lea	%sp@(FR_SIZE),%a6	| Save stack pointer
1055	movl	%a6,%sp@(FR_SP)		|  from before trap
1056
1057	| If were are not on tmpstk switch to it.
1058	| (so debugger can change the stack pointer)
1059	movl	%a6,%d1
1060	cmpl	#_ASM_LABEL(tmpstk),%d1
1061	jls	Lbrkpt2			| already on tmpstk
1062	| Copy frame to the temporary stack
1063	movl	%sp,%a0			| a0=src
1064	lea	_ASM_LABEL(tmpstk)-96,%a1 | a1=dst
1065	movl	%a1,%sp			| sp=new frame
1066	movql	#FR_SIZE,%d1
1067Lbrkpt1:
1068	movl	%a0@+,%a1@+
1069	subql	#4,%d1
1070	jbgt	Lbrkpt1
1071
1072Lbrkpt2:
1073	| Call the trap handler for the kernel debugger.
1074	| Do not call trap() to do it, so that we can
1075	| set breakpoints in trap() if we want.  We know
1076	| the trap type is either T_TRACE or T_BREAKPOINT.
1077	| If we have both DDB and KGDB, let KGDB see it first,
1078	| because KGDB will just return 0 if not connected.
1079	| Save args in d2, a2
1080	movl	%d0,%d2			| trap type
1081	movl	%sp,%a2			| frame ptr
1082#ifdef KGDB
1083	| Let KGDB handle it (if connected)
1084	movl	%a2,%sp@-		| push frame ptr
1085	movl	%d2,%sp@-		| push trap type
1086	jbsr	_C_LABEL(kgdb_trap)	| handle the trap
1087	addql	#8,%sp			| pop args
1088	cmpl	#0,%d0			| did kgdb handle it?
1089	jne	Lbrkpt3			| yes, done
1090#endif
1091#ifdef DDB
1092	| Let DDB handle it
1093	movl	%a2,%sp@-		| push frame ptr
1094	movl	%d2,%sp@-		| push trap type
1095	jbsr	_C_LABEL(kdb_trap)	| handle the trap
1096	addql	#8,%sp			| pop args
1097#endif
1098	/* Sun 3 drops into PROM here. */
1099Lbrkpt3:
1100	| The stack pointer may have been modified, or
1101	| data below it modified (by kgdb push call),
1102	| so push the hardware frame at the current sp
1103	| before restoring registers and returning.
1104
1105	movl	%sp@(FR_SP),%a0		| modified sp
1106	lea	%sp@(FR_SIZE),%a1	| end of our frame
1107	movl	%a1@-,%a0@-		| copy 2 longs with
1108	movl	%a1@-,%a0@-		| ... predecrement
1109	movl	%a0,%sp@(FR_SP)		| sp = h/w frame
1110	moveml	%sp@+,#0x7FFF		| restore all but sp
1111	movl	%sp@,%sp		| ... and sp
1112	rte				| all done
1113
1114/*
1115 * Use common m68k sigreturn routine.
1116 */
1117#include <m68k/m68k/sigreturn.s>
1118
1119/*
1120 * Interrupt handlers.
1121 *
1122 * For auto-vectored interrupts, the CPU provides the
1123 * vector 0x18+level.
1124 *
1125 * intrhand_autovec is the entry point for auto-vectored
1126 * interrupts.
1127 *
1128 * For vectored interrupts, we pull the pc, evec, and exception frame
1129 * and pass them to the vectored interrupt dispatcher.  The vectored
1130 * interrupt dispatcher will deal with strays.
1131 *
1132 * intrhand_vectored is the entry point for vectored interrupts.
1133 */
1134
1135#define INTERRUPT_SAVEREG	moveml  #0xC0C0,%sp@-
1136#define INTERRUPT_RESTOREREG	moveml  %sp@+,#0x0303
1137
1138ENTRY_NOPROFILE(intrhand_autovec)
1139	addql	#1,_C_LABEL(interrupt_depth)
1140	INTERRUPT_SAVEREG
1141	lea	%sp@(16),%a1		| get pointer to frame
1142	movl	%a1,%sp@-
1143	jbsr	_C_LABEL(isrdispatch_autovec)  | call dispatcher
1144	addql	#4,%sp
1145	jbra	Lintrhand_exit
1146
1147ENTRY_NOPROFILE(intrhand_vectored)
1148	addql	#1,_C_LABEL(interrupt_depth)
1149	INTERRUPT_SAVEREG
1150	lea	%sp@(16),%a1		| get pointer to frame
1151	movl	%a1,%sp@-
1152	movw	%sr,%d0
1153	bfextu	%d0,21,3,%d0		| Get current ipl
1154	movl	%d0,%sp@-		| Push it
1155	jbsr	_C_LABEL(isrdispatch_vectored) | call dispatcher
1156	addql	#8,%sp
1157Lintrhand_exit:
1158	INTERRUPT_RESTOREREG
1159	subql	#1,_C_LABEL(interrupt_depth)
1160
1161	/* FALLTHROUGH to rei */
1162
1163#undef INTERRUPT_SAVEREG
1164#undef INTERRUPT_RESTOREREG
1165
1166/*
1167 * Emulation of VAX REI instruction.
1168 *
1169 * This code deals with checking for and servicing ASTs
1170 * (profiling, scheduling).
1171 * After identifing that we need an AST we drop the IPL to allow device
1172 * interrupts.
1173 *
1174 * This code is complicated by the fact that sendsig may have been called
1175 * necessitating a stack cleanup.
1176 */
1177ASENTRY_NOPROFILE(rei)
1178	tstl	_C_LABEL(astpending)	| AST pending?
1179	jeq	Ldorte			| Nope. Just return.
1180	btst	#5,%sp@			| Returning to kernel mode?
1181	jne	Ldorte			| Yup. Can't do ASTs
1182	movw	#PSL_LOWIPL,%sr		| lower SPL
1183	clrl	%sp@-			| stack adjust
1184	moveml	#0xFFFF,%sp@-		| save all registers
1185	movl	%usp,%a1		| including
1186	movl	%a1,%sp@(FR_SP)		|    the users SP
1187Lrei1:	clrl	%sp@-			| VA == none
1188	clrl	%sp@-			| code == none
1189	movl	#T_ASTFLT,%sp@-		| type == async system trap
1190	jbsr	_C_LABEL(trap)		| go handle it
1191	lea	%sp@(12),%sp		| pop value args
1192	movl	%sp@(FR_SP),%a0		| restore user SP
1193	movl	%a0,%usp		|   from save area
1194	movw	%sp@(FR_ADJ),%d0	| need to adjust stack?
1195	jne	Laststkadj		| yes, go to it
1196	moveml	%sp@+,#0x7FFF		| no, restore most user regs
1197	addql	#8,%sp			| toss SP and stack adjust
1198Ldorte:	rte				| and do real RTE
1199
1200Laststkadj:
1201	lea	%sp@(FR_HW),%a1		| pointer to HW frame
1202	addql	#8,%a1			| source pointer
1203	movl	%a1,%a0			| source
1204	addw	%d0,%a0			|  + hole size = dest pointer
1205	movl	%a1@-,%a0@-		| copy
1206	movl	%a1@-,%a0@-		|  8 bytes
1207	movl	%a0,%sp@(FR_SP)		| new SSP
1208	moveml	%sp@+,#0x7FFF		| restore user registers
1209	movl	%sp@,%sp		| and our SP
1210	rte				| and do real RTE
1211
1212/*
1213 * Use common m68k sigcode.
1214 */
1215#include <m68k/m68k/sigcode.s>
1216#ifdef COMPAT_SUNOS
1217#include <m68k/m68k/sunos_sigcode.s>
1218#endif
1219#ifdef COMPAT_SVR4
1220#include <m68k/m68k/svr4_sigcode.s>
1221#endif
1222
1223/*
1224 * Primitives
1225 */
1226
1227/*
1228 * Use common m68k support routines.
1229 */
1230#include <m68k/m68k/support.s>
1231
1232/*
1233 * Use common m68k process manipulation routines.
1234 */
1235#include <m68k/m68k/proc_subr.s>
1236
1237	.data
1238GLOBAL(curpcb)
1239GLOBAL(masterpaddr)		| XXXcompatibility (debuggers)
1240	.long	0
1241
1242ASLOCAL(mdpflag)
1243	.byte	0		| copy of proc md_flags low byte
1244#ifdef __ELF__
1245	.align	4
1246#else
1247	.align	2
1248#endif
1249
1250ASBSS(nullpcb,SIZEOF_PCB)
1251
1252/*
1253 * At exit of a process, do a switch for the last time.
1254 * Switch to a safe stack and PCB, and select a new process to run.  The
1255 * old stack and u-area will be freed by the reaper.
1256 *
1257 * MUST BE CALLED AT SPLHIGH!
1258 */
1259ENTRY(switch_exit)
1260	movl    %sp@(4),%a0
1261	/* save state into garbage pcb */
1262	movl    #_ASM_LABEL(nullpcb),_C_LABEL(curpcb)
1263	lea     _ASM_LABEL(tmpstk),%sp	| goto a tmp stack
1264
1265	/* Schedule the vmspace and stack to be freed. */
1266	movl	%a0,%sp@-		| exit2(p)
1267	jbsr	_C_LABEL(exit2)
1268	lea	%sp@(4),%sp		| pop args
1269
1270#if defined(LOCKDEBUG)
1271	/* Acquire sched_lock */
1272	jbsr	_C_LABEL(sched_lock_idle)
1273#endif
1274
1275	jra	_C_LABEL(cpu_switch)
1276
1277/*
1278 * When no processes are on the runq, Swtch branches to Idle
1279 * to wait for something to come ready.
1280 */
1281ASENTRY_NOPROFILE(Idle)
1282#if defined(LOCKDEBUG)
1283	/* Release sched_lock */
1284	jbsr	_C_LABEL(sched_unlock_idle)
1285#endif
1286	stop	#PSL_LOWIPL
1287	movw	#PSL_HIGHIPL,%sr
1288#if defined(LOCKDEBUG)
1289	/* Acquire sched_lock */
1290	jbsr	_C_LABEL(sched_lock_idle)
1291#endif
1292	movl    _C_LABEL(sched_whichqs),%d0
1293	jeq     _ASM_LABEL(Idle)
1294	jra	Lsw1
1295
1296Lbadsw:
1297	PANIC("switch")
1298	/*NOTREACHED*/
1299
1300/*
1301 * cpu_switch()
1302 *
1303 * NOTE: With the new VM layout we now no longer know if an inactive
1304 * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag
1305 * bit).  For now, we just always flush the full ATC.
1306 */
1307ENTRY(cpu_switch)
1308	movl	_C_LABEL(curpcb),%a0	| current pcb
1309	movw	%sr,%a0@(PCB_PS)	| save sr before changing ipl
1310#ifdef notyet
1311	movl	_C_LABEL(curproc),%sp@-	| remember last proc running
1312#endif
1313	clrl	_C_LABEL(curproc)
1314
1315	/*
1316	 * Find the highest-priority queue that isn't empty,
1317	 * then take the first proc from that queue.
1318	 */
1319	movl    _C_LABEL(sched_whichqs),%d0
1320	jeq     _ASM_LABEL(Idle)
1321Lsw1:
1322	/*
1323	 * Interrupts are blocked, sched_lock is held.  If
1324	 * we come here via Idle, %d0 contains the contents
1325	 * of a non-zero sched_whichqs.
1326	 */
1327	movl    %d0,%d1
1328	negl    %d0
1329	andl    %d1,%d0
1330	bfffo   %d0{#0:#32},%d1
1331	eorib   #31,%d1
1332
1333	movl    %d1,%d0
1334	lslb    #3,%d1			| convert queue number to index
1335	addl    #_C_LABEL(sched_qs),%d1	| locate queue (q)
1336	movl    %d1,%a1
1337	movl    %a1@(P_FORW),%a0	| p = q->p_forw
1338	cmpal   %d1,%a0			| anyone on queue?
1339	jeq     Lbadsw                  | no, panic
1340#ifdef DIAGNOSTIC
1341	tstl	%a0@(P_WCHAN)
1342	jne	Lbadsw
1343	cmpb	#SRUN,%a0@(P_STAT)
1344	jne	Lbadsw
1345#endif
1346	movl    %a0@(P_FORW),%a1@(P_FORW) | q->p_forw = p->p_forw
1347	movl    %a0@(P_FORW),%a1	| n = p->p_forw
1348	movl    %d1,%a1@(P_BACK)	| n->p_back = q
1349	cmpal   %d1,%a1			| anyone left on queue?
1350	jne     Lsw2			| yes, skip
1351	movl    _C_LABEL(sched_whichqs),%d1
1352	bclr    %d0,%d1			| no, clear bit
1353	movl    %d1,_C_LABEL(sched_whichqs)
1354Lsw2:
1355	/* p->p_cpu initialized in fork1() for single-processor */
1356	movb	#SONPROC,%a0@(P_STAT)	| p->p_stat = SONPROC
1357	movl	%a0,_C_LABEL(curproc)
1358	clrl	_C_LABEL(want_resched)
1359#ifdef notyet
1360	movl	%sp@+,%a1
1361	cmpl	%a0,%a1			| switching to same proc?
1362	jeq	Lswdone			| yes, skip save and restore
1363#endif
1364	/*
1365	 * Save state of previous process in its pcb.
1366	 */
1367	movl	_C_LABEL(curpcb),%a1
1368	moveml	#0xFCFC,%a1@(PCB_REGS)	| save non-scratch registers
1369	movl	%usp,%a2		| grab USP (a2 has been saved)
1370	movl	%a2,%a1@(PCB_USP)	| and save it
1371
1372	tstl	_C_LABEL(fputype)	| Do we have an FPU?
1373	jeq	Lswnofpsave		| No  Then don't attempt save.
1374	lea	%a1@(PCB_FPCTX),%a2	| pointer to FP save area
1375	fsave	%a2@			| save FP state
1376#if defined(M68020) || defined(M68030) || defined(M68040)
1377#if defined(M68060)
1378	cmpl	#FPU_68060,_C_LABEL(fputype)
1379	jeq	Lsavfp60
1380#endif
1381	tstb	%a2@			| null state frame?
1382	jeq	Lswnofpsave		| yes, all done
1383	fmovem	%fp0-%fp7,%a2@(FPF_REGS) | save FP general registers
1384	fmovem	%fpcr/%fpsr/%fpi,%a2@(FPF_FPCR) | save FP control registers
1385#if defined(M68060)
1386	jra	Lswnofpsave
1387Lsavfp60:
1388#endif
1389#endif
1390#if defined(M68060)
1391	tstb	%a2@(2)			| null state frame?
1392	jeq	Lswnofpsave		| yes, all done
1393	fmovem	%fp0-%fp7,%a2@(FPF_REGS) | save FP general registers
1394	fmovem	%fpcr,%a2@(FPF_FPCR)	| save FP control registers
1395	fmovem	%fpsr,%a2@(FPF_FPSR)
1396	fmovem	%fpi,%a2@(FPF_FPI)
1397#endif
1398Lswnofpsave:
1399
1400	clrl	%a0@(P_BACK)		| clear back link
1401	/* low byte of p_md.md_flags */
1402	movb	%a0@(P_MD_FLAGS+3),_ASM_LABEL(mdpflag)
1403	movl	%a0@(P_ADDR),%a1	| get p_addr
1404	movl	%a1,_C_LABEL(curpcb)
1405
1406#if defined(LOCKDEBUG)
1407	/*
1408	 * Done mucking with the run queues, release the
1409	 * scheduler lock, but keep interrupts out.
1410	 */
1411	movl	%a0,%sp@-		| not args...
1412	movl	%a1,%sp@-		| ...just saving
1413	jbsr	_C_LABEL(sched_unlock_idle)
1414	movl	%sp@+,%a1
1415	movl	%sp@+,%a0
1416#endif
1417
1418	/*
1419	 * Activate process's address space.
1420	 * XXX Should remember the last USTP value loaded, and call this
1421	 * XXX only of it has changed.
1422	 */
1423	pea	%a0@			| push proc
1424	jbsr	_C_LABEL(pmap_activate)	| pmap_activate(p)
1425	addql	#4,%sp
1426	movl	_C_LABEL(curpcb),%a1	| restore p_addr
1427
1428	lea     _ASM_LABEL(tmpstk),%sp	| now goto a tmp stack for NMI
1429
1430	moveml	%a1@(PCB_REGS),#0xFCFC	| and registers
1431	movl	%a1@(PCB_USP),%a0
1432	movl	%a0,%usp		| and USP
1433	tstl	_C_LABEL(fputype)	| Do we have an FPU?
1434	jeq	Lnofprest		| No  Then don't attempt restore.
1435	lea	%a1@(PCB_FPCTX),%a0	| pointer to FP save area
1436#if defined(M68020) || defined(M68030) || defined(M68040)
1437#if defined(M68060)
1438	cmpl	#FPU_68060,_C_LABEL(fputype)
1439	jeq	Lresfp60rest1
1440#endif
1441	tstb	%a0@			| null state frame?
1442	jeq	Lresfprest		| yes, easy
1443	fmovem	%a0@(FPF_FPCR),%fpcr/%fpsr/%fpi | restore FP control registers
1444	fmovem	%a0@(FPF_REGS),%fp0-%fp7	| restore FP general registers
1445#if defined(M68060)
1446	jra	Lresfprest
1447#endif
1448#endif
1449
1450#if defined(M68060)
1451Lresfp60rest1:
1452	tstb	%a0@(2)			| null state frame?
1453	jeq	Lresfprest		| yes, easy
1454	fmovem	%a0@(FPF_FPCR),%fpcr	| restore FP control registers
1455	fmovem	%a0@(FPF_FPSR),%fpsr
1456	fmovem	%a0@(FPF_FPI),%fpi
1457	fmovem	%a0@(FPF_REGS),%fp0-%fp7 | restore FP general registers
1458#endif
1459Lresfprest:
1460	frestore %a0@			| restore state
1461Lnofprest:
1462	movw	%a1@(PCB_PS),%sr	| no, restore PS
1463	moveq	#1,%d0			| return 1 (for alternate returns)
1464	rts
1465
1466/*
1467 * savectx(pcb)
1468 * Update pcb, saving current processor state.
1469 */
1470ENTRY(savectx)
1471	movl	%sp@(4),%a1
1472	movw	%sr,%a1@(PCB_PS)
1473	movl	%usp,%a0		| grab USP
1474	movl	%a0,%a1@(PCB_USP)	| and save it
1475	moveml	#0xFCFC,%a1@(PCB_REGS)	| save non-scratch registers
1476
1477	tstl	_C_LABEL(fputype)	| Do we have FPU?
1478	jeq	Lsvnofpsave		| No?  Then don't save state.
1479	lea	%a1@(PCB_FPCTX),%a0	| pointer to FP save area
1480	fsave	%a0@			| save FP state
1481#if defined(M68020) || defined(M68030) || defined(M68040)
1482#if defined(M68060)
1483	cmpl	#FPU_68060,_C_LABEL(fputype)
1484	jeq	Lsvsavfp60
1485#endif
1486	tstb	%a0@			| null state frame?
1487	jeq	Lsvnofpsave		| yes, all done
1488	fmovem	%fp0-%fp7,%a0@(FPF_REGS)	| save FP general registers
1489	fmovem	%fpcr/%fpsr/%fpi,%a0@(FPF_FPCR) | save FP control registers
1490#if defined(M68060)
1491	jra	Lsvnofpsave
1492Lsvsavfp60:
1493#endif
1494#endif
1495#if defined(M68060)
1496	tstb	%a0@(2)			| null state frame?
1497	jeq	Lsvnofpsave		| yes, all done
1498	fmovem	%fp0-%fp7,%a0@(FPF_REGS) | save FP general registers
1499	fmovem	%fpcr,%a0@(FPF_FPCR)	| save FP control registers
1500	fmovem	%fpsr,%a0@(FPF_FPSR)
1501	fmovem	%fpi,%a0@(FPF_FPI)
1502#endif
1503Lsvnofpsave:
1504	moveq	#0,%d0			| return 0
1505	rts
1506
1507#if defined(M68040) || defined(M68060)
1508ENTRY(suline)
1509	movl	%sp@(4),%a0		| address to write
1510	movl	_C_LABEL(curpcb),%a1	| current pcb
1511	movl	#Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault
1512	movl	%sp@(8),%a1		| address of line
1513	movl	%a1@+,%d0		| get lword
1514	movsl	%d0,%a0@+		| put lword
1515	nop				| sync
1516	movl	%a1@+,%d0		| get lword
1517	movsl	%d0,%a0@+		| put lword
1518	nop				| sync
1519	movl	%a1@+,%d0		| get lword
1520	movsl	%d0,%a0@+		| put lword
1521	nop				| sync
1522	movl	%a1@+,%d0		| get lword
1523	movsl	%d0,%a0@+		| put lword
1524	nop				| sync
1525	moveq	#0,%d0			| indicate no fault
1526	jra	Lsldone
1527Lslerr:
1528	moveq	#-1,%d0
1529Lsldone:
1530	movl	_C_LABEL(curpcb),%a1	| current pcb
1531	clrl	%a1@(PCB_ONFAULT)	| clear fault address
1532	rts
1533#endif
1534
1535
1536ENTRY(ecacheon)
1537	rts
1538
1539ENTRY(ecacheoff)
1540	rts
1541
1542/*
1543 * Get callers current SP value.
1544 * Note that simply taking the address of a local variable in a C function
1545 * doesn't work because callee saved registers may be outside the stack frame
1546 * defined by A6 (e.g. GCC generated code).
1547 */
1548ENTRY_NOPROFILE(getsp)
1549	movl	%sp,%d0			| get current SP
1550	addql	#4,%d0			| compensate for return address
1551	movl	%d0,%a0
1552	rts
1553
1554ENTRY_NOPROFILE(getsfc)
1555	movc	%sfc,%d0
1556	movl	%d0,%a0
1557	rts
1558
1559ENTRY_NOPROFILE(getdfc)
1560	movc	%dfc,%d0
1561	movl	%d0,%a0
1562	rts
1563
1564/*
1565 * Load a new user segment table pointer.
1566 */
1567ENTRY(loadustp)
1568	movl	%sp@(4),%d0		| new USTP
1569	moveq	#PGSHIFT, %d1
1570	lsll	%d1,%d0			| convert to addr
1571#if defined(M68040) || defined(M68060)
1572	cmpl    #MMU_68040,_C_LABEL(mmutype) | 68040?
1573	jne     LmotommuC               | no, skip
1574	.word	0xf518			| pflusha
1575	.long   0x4e7b0806              | movc d0,urp
1576#ifdef M68060
1577	cmpl	#CPU_68060,_C_LABEL(cputype)
1578	jne	Lldno60
1579	movc	%cacr,%d0
1580	orl	#IC60_CUBC,%d0		| clear user branch cache entries
1581	movc	%d0,%cacr
1582Lldno60:
1583#endif
1584	rts
1585LmotommuC:
1586#endif
1587	pflusha				| flush entire TLB
1588	lea	_C_LABEL(protorp),%a0	| CRP prototype
1589	movl	%d0,%a0@(4)		| stash USTP
1590	pmove	%a0@,%crp		| load root pointer
1591	movl	#CACHE_CLR,%d0
1592	movc	%d0,%cacr		| invalidate cache(s)
1593	rts
1594
1595ENTRY(ploadw)
1596#ifdef M68030
1597#if defined(M68040) || defined(M68060)
1598	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
1599	jeq	Lploadwskp		| yes, skip
1600#endif
1601	movl	%sp@(4),%a0		| address to load
1602	ploadw	#1,%a0@			| pre-load translation
1603Lploadwskp:
1604#endif
1605	rts
1606
1607ENTRY(getsr)
1608	moveq	#0,%d0
1609	movw	%sr,%d0
1610	rts
1611
1612/*
1613 * _delay(unsigned N)
1614 *
1615 * Delay for at least (N/1024) microseconds.
1616 * This routine depends on the variable:  delay_divisor
1617 * which should be set based on the CPU clock rate.
1618 */
1619ENTRY_NOPROFILE(_delay)
1620	| d0 = arg = (usecs << 10)
1621	movl	%sp@(4),%d0
1622	| d1 = delay_divisor
1623	movl	_C_LABEL(delay_divisor),%d1
1624	jra	L_delay			/* Jump into the loop! */
1625
1626	/*
1627	 * Align the branch target of the loop to a half-line (8-byte)
1628	 * boundary to minimize cache effects.  This guarantees both
1629	 * that there will be no prefetch stalls due to cache line burst
1630	 * operations and that the loop will run from a single cache
1631	 * half-line.
1632	 */
1633#ifdef __ELF__
1634	.align	8
1635#else
1636	.align	3
1637#endif
1638L_delay:
1639	subl	%d1,%d0
1640	jgt	L_delay
1641	rts
1642
1643/*
1644 * Save and restore 68881 state.
1645 */
1646ENTRY(m68881_save)
1647	movl	%sp@(4),%a0		| save area pointer
1648	fsave	%a0@			| save state
1649#if defined(M68020) || defined(M68030) || defined(M68040)
1650#if defined(M68060)
1651	cmpl	#FPU_68060,_C_LABEL(fputype)
1652	jeq	Lm68060fpsave
1653#endif
1654Lm68881fpsave:
1655	tstb	%a0@			| null state frame?
1656	jeq	Lm68881sdone		| yes, all done
1657	fmovem	%fp0-%fp7,%a0@(FPF_REGS)	| save FP general registers
1658	fmovem	%fpcr/%fpsr/%fpi,%a0@(FPF_FPCR) | save FP control registers
1659Lm68881sdone:
1660	rts
1661#endif
1662#if defined(M68060)
1663Lm68060fpsave:
1664	tstb	%a0@(2)			| null state frame?
1665	jeq	Lm68060sdone		| yes, all done
1666	fmovem	%fp0-%fp7,%a0@(FPF_REGS)	| save FP general registers
1667	fmovem	%fpcr,%a0@(FPF_FPCR)	| save FP control registers
1668	fmovem	%fpsr,%a0@(FPF_FPSR)
1669	fmovem	%fpi,%a0@(FPF_FPI)
1670Lm68060sdone:
1671        rts
1672#endif
1673
1674ENTRY(m68881_restore)
1675	movl	%sp@(4),%a0		| save area pointer
1676#if defined(M68020) || defined(M68030) || defined(M68040)
1677#if defined(M68060)
1678	cmpl	#FPU_68060,_C_LABEL(fputype)
1679	jeq	Lm68060fprestore
1680#endif
1681Lm68881fprestore:
1682	tstb	%a0@			| null state frame?
1683	jeq	Lm68881rdone		| yes, easy
1684	fmovem	%a0@(FPF_FPCR),%fpcr/%fpsr/%fpi | restore FP control registers
1685	fmovem	%a0@(FPF_REGS),%fp0-%fp7	| restore FP general registers
1686Lm68881rdone:
1687	frestore %a0@			| restore state
1688	rts
1689#endif
1690#if defined(M68060)
1691Lm68060fprestore:
1692	tstb	%a0@(2)			| null state frame?
1693	jeq	Lm68060fprdone		| yes, easy
1694	fmovem	%a0@(FPF_FPCR),%fpcr	| restore FP control registers
1695	fmovem	%a0@(FPF_FPSR),%fpsr
1696	fmovem	%a0@(FPF_FPI),%fpi
1697	fmovem	%a0@(FPF_REGS),%fp0-%fp7 | restore FP general registers
1698Lm68060fprdone:
1699	frestore %a0@			| restore state
1700	rts
1701#endif
1702
1703/*
1704 * Handle the nitty-gritty of rebooting the machine.
1705 * Basically we just turn off the MMU, restore the Bug's initial VBR
1706 * and either return to Bug or jump through the ROM reset vector
1707 * depending on how the system was halted.
1708 */
1709ENTRY_NOPROFILE(doboot)
1710	movw	#PSL_HIGHIPL,%sr
1711	movl	_C_LABEL(boothowto),%d1	| load howto
1712	movl	%sp@(4),%d2		| arg
1713	movl	_ASM_LABEL(bug_vbr),%d3	| Fetch Bug's original VBR value
1714	movl	_C_LABEL(machineid),%d4	| What type of board is this?
1715	movl	#CACHE_OFF,%d0
1716#if defined(M68040) || defined(M68060)
1717	cmpl	#MMU_68040,_C_LABEL(mmutype)	| 68040/68060?
1718	jne	Lnocache0		| no, skip
1719	.word	0xf4f8			| cpusha bc - push and invalidate caches
1720	nop
1721	movl	#CACHE40_OFF,%d0
1722#endif
1723Lnocache0:
1724	movc	%d0,%cacr		| disable on-chip cache(s)
1725
1726#if defined(M68040) || defined(M68060)
1727	cmpl	#MMU_68040,_C_LABEL(mmutype)
1728	jne	LmotommuF
1729	movql	#0,%d0
1730	movc	%d0,%cacr
1731	.long	0x4e7b0003              | movc d0,tc
1732	jra	Lbootcommon
1733LmotommuF:
1734#endif
1735	clrl	%sp@-			| value for pmove to TC (turn off MMU)
1736	pmove	%sp@,%tc		| disable MMU
1737	addql	#4,%sp
1738
1739Lbootcommon:
1740	/*
1741	 * MMU Switched off by now, so relocate all absolute references
1742	 */
1743	ASRELOC(tmpstk, %sp)		| physical SP in case of NMI
1744	movc	%d3,%vbr		| Restore Bug's VBR
1745	andl	#RB_SBOOT, %d1		| mask off
1746	jbne	Lsboot			| sboot?
1747	/* NOT sboot */
1748	tstl	%d2			| autoboot?
1749	jbeq	Ldoreset		| yes!
1750	CALLBUG(MVMEPROM_EXIT)		| return to bug
1751	/* NOTREACHED */
1752
1753Ldoreset:
1754	movl	#0xff800000,%a0		| Bug's reset vector address
1755	movl	%a0@+, %a7		| get SP
1756	movl	%a0@, %a0		| get PC
1757	jmp	%a0@			| go!
1758
1759Lsboot: /* sboot */
1760	tstl	%d2			| autoboot?
1761	jbeq	1f			| yes!
1762	jmp 	0x4000			| back to sboot
17631:	jmp	0x400a			| tell sboot to reboot us
1764
1765
1766/*
1767 * Misc. global variables.
1768 */
1769	.data
1770
1771GLOBAL(machineid)
1772	.long	MVME_147	| default to MVME_147
1773
1774GLOBAL(mmutype)
1775	.long	MMU_68030	| default to MMU_68030
1776
1777GLOBAL(cputype)
1778	.long	CPU_68030	| default to CPU_68030
1779
1780GLOBAL(fputype)
1781	.long	FPU_68882	| default to FPU_68882
1782
1783GLOBAL(protorp)
1784	.long	0,0		| prototype root pointer
1785
1786/*
1787 * Information from first stage boot program
1788 */
1789GLOBAL(bootpart)
1790	.long	0
1791GLOBAL(bootdevlun)
1792	.long	0
1793GLOBAL(bootctrllun)
1794	.long	0
1795GLOBAL(bootaddr)
1796	.long	0
1797
1798GLOBAL(want_resched)
1799	.long	0
1800
1801GLOBAL(proc0paddr)
1802	.long	0		| KVA of proc0 u-area
1803
1804GLOBAL(intiobase)
1805	.long	0		| KVA of base of internal IO space
1806
1807GLOBAL(intiolimit)
1808	.long	0		| KVA of end of internal IO space
1809
1810GLOBAL(intiobase_phys)
1811	.long	0		| PA of board's I/O registers
1812
1813GLOBAL(intiotop_phys)
1814	.long	0		| PA of top of board's I/O registers
1815
1816/*
1817 * interrupt counters.
1818 * XXXSCW: Will go away soon; kept here to keep vmstat happy
1819 */
1820GLOBAL(intrnames)
1821	.asciz	"spur"
1822	.asciz	"lev1"
1823	.asciz	"lev2"
1824	.asciz	"lev3"
1825	.asciz	"lev4"
1826	.asciz	"clock"
1827	.asciz	"lev6"
1828	.asciz	"nmi"
1829	.asciz	"statclock"
1830GLOBAL(eintrnames)
1831	.even
1832
1833GLOBAL(intrcnt)
1834	.long	0,0,0,0,0,0,0,0,0,0
1835GLOBAL(eintrcnt)
1836