xref: /original-bsd/sys/luna68k/luna68k/locore.s (revision 860e07fc)
1/*
2 * Copyright (c) 1988 University of Utah.
3 * Copyright (c) 1992 OMRON Corporation.
4 * Copyright (c) 1980, 1990 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * the Systems Programming Group of the University of Utah Computer
9 * Science Department.
10 *
11 * %sccs.include.redist.c%
12 *
13 * from: Utah $Hdr: locore.s 1.62 92/01/20$
14 * OMRON: $Id: locore.s,v 1.2 92/06/14 06:16:34 moti Exp $
15 *
16 * from: hp300/hp300/locore.s   7.16 (Berkeley) 7/8/92
17 *
18 *	@(#)locore.s	7.5 (Berkeley) 09/08/92
19 */
20
21#include "assym.s"
22#include "vectors.s"
23
24	.text
25/*
26 * This is where we wind up if the kernel jumps to location 0.
27 * (i.e. a bogus PC)  This is known to immediately follow the vector
28 * table and is hence at 0x400 (see reset vector in vectors.s).
29 */
30	.globl	_panic
31	pea	Ljmp0panic
32	jbsr	_panic
33	/* NOTREACHED */
34Ljmp0panic:
35	.asciz	"kernel jump to zero"
36	.even
37
38/*
39 * Do a dump.
40 * Called by auto-restart.
41 */
42	.globl	_dumpsys
43	.globl	_doadump
44_doadump:
45	jbsr	_dumpsys
46	jbsr	_doboot
47	/*NOTREACHED*/
48
49/*
50 * Trap/interrupt vector routines
51 */
52
53	.globl	_trap, _nofault, _longjmp
54_buserr:
55	tstl	_nofault		| device probe?
56	jeq	_addrerr		| no, handle as usual
57	movl	_nofault,sp@-		| yes,
58	jbsr	_longjmp		|  longjmp(nofault)
59_addrerr:
60	clrw	sp@-			| pad SR to longword
61	moveml	#0xFFFF,sp@-		| save user registers
62	movl	usp,a0			| save the user SP
63	movl	a0,sp@(60)		|   in the savearea
64	lea	sp@(64),a1		| grab base of HW berr frame
65	moveq	#0,d0
66	movw	a1@(12),d0		| grab SSW for fault processing
67	btst	#12,d0			| RB set?
68	jeq	LbeX0			| no, test RC
69	bset	#14,d0			| yes, must set FB
70	movw	d0,a1@(12)		| for hardware too
71LbeX0:
72	btst	#13,d0			| RC set?
73	jeq	LbeX1			| no, skip
74	bset	#15,d0			| yes, must set FC
75	movw	d0,a1@(12)		| for hardware too
76LbeX1:
77	btst	#8,d0			| data fault?
78	jeq	Lbe0			| no, check for hard cases
79	movl	a1@(18),d1		| fault address is as given in frame
80	jra	Lbe10			| thats it
81Lbe0:
82	btst	#4,a1@(8)		| long (type B) stack frame?
83	jne	Lbe4			| yes, go handle
84	movl	a1@(4),d1		| no, can use save PC
85	btst	#14,d0			| FB set?
86	jeq	Lbe3			| no, try FC
87	addql	#4,d1			| yes, adjust address
88	jra	Lbe10			| done
89Lbe3:
90	btst	#15,d0			| FC set?
91	jeq	Lbe10			| no, done
92	addql	#2,d1			| yes, adjust address
93	jra	Lbe10			| done
94Lbe4:
95	movl	a1@(38),d1		| long format, use stage B address
96	btst	#15,d0			| FC set?
97	jeq	Lbe10			| no, all done
98	subql	#2,d1			| yes, adjust address
99Lbe10:
100	movl	d1,sp@-			| push fault VA
101	movl	d0,sp@-			| and padded SSW
102	movw	a1@(8),d0		| get frame format/vector offset
103	andw	#0x0FFF,d0		| clear out frame format
104	cmpw	#12,d0			| address error vector?
105	jeq	Lisaerr			| yes, go to it
106	movl	d1,a0			| fault address
107	ptestr	#1,a0@,#7		| do a table search
108	pmove	psr,sp@			| save result
109	btst	#7,sp@			| bus error bit set?
110	jeq	Lismerr			| no, must be MMU fault
111	clrw	sp@			| yes, re-clear pad word
112	jra	Lisberr			| and process as normal bus error
113Lismerr:
114	movl	#T_MMUFLT,sp@-		| show that we are an MMU fault
115	jra	Ltrapnstkadj		| and deal with it
116Lisaerr:
117	movl	#T_ADDRERR,sp@-		| mark address error
118	jra	Ltrapnstkadj		| and deal with it
119Lisberr:
120	movl	#T_BUSERR,sp@-		| mark bus error
121Ltrapnstkadj:
122	jbsr	_trap			| handle the error
123	lea	sp@(12),sp		| pop value args
124	movl	sp@(60),a0		| restore user SP
125	movl	a0,usp			|   from save area
126	movw	sp@(64),d0		| need to adjust stack?
127	jne	Lstkadj			| yes, go to it
128	moveml	sp@+,#0x7FFF		| no, restore most user regs
129	addql	#6,sp			| toss SSP and pad
130	jra	rei			| all done
131Lstkadj:
132	lea	sp@(66),a1		| pointer to HW frame
133	addql	#8,a1			| source pointer
134	movl	a1,a0			| source
135	addw	d0,a0			|  + hole size = dest pointer
136	movl	a1@-,a0@-		| copy
137	movl	a1@-,a0@-		|  8 bytes
138	movl	a0,sp@(60)		| new SSP
139	moveml	sp@+,#0x7FFF		| restore user registers
140	movl	sp@,sp			| and our SP
141	jra	rei			| all done
142
143/*
144 * FP exceptions.
145 */
146_fpfline:
147	jra	_illinst
148
149_fpunsupp:
150	jra	_illinst
151
152/*
153 * Handles all other FP coprocessor exceptions.
154 * Note that since some FP exceptions generate mid-instruction frames
155 * and may cause signal delivery, we need to test for stack adjustment
156 * after the trap call.
157 */
158_fpfault:
159#ifdef FPCOPROC
160	clrw	sp@-		| pad SR to longword
161	moveml	#0xFFFF,sp@-	| save user registers
162	movl	usp,a0		| and save
163	movl	a0,sp@(60)	|   the user stack pointer
164	clrl	sp@-		| no VA arg
165	movl	_curpcb,a0	| current pcb
166	lea	a0@(PCB_FPCTX),a0 | address of FP savearea
167	fsave	a0@		| save state
168	tstb	a0@		| null state frame?
169	jeq	Lfptnull	| yes, safe
170	clrw	d0		| no, need to tweak BIU
171	movb	a0@(1),d0	| get frame size
172	bset	#3,a0@(0,d0:w)	| set exc_pend bit of BIU
173Lfptnull:
174	fmovem	fpsr,sp@-	| push fpsr as code argument
175	frestore a0@		| restore state
176	movl	#T_FPERR,sp@-	| push type arg
177	jra	Ltrapnstkadj	| call trap and deal with stack cleanup
178#else
179	jra	_badtrap	| treat as an unexpected trap
180#endif
181
182/*
183 * Coprocessor and format errors can generate mid-instruction stack
184 * frames and cause signal delivery hence we need to check for potential
185 * stack adjustment.
186 */
187_coperr:
188	clrw	sp@-
189	moveml	#0xFFFF,sp@-
190	movl	usp,a0		| get and save
191	movl	a0,sp@(60)	|   the user stack pointer
192	clrl	sp@-		| no VA arg
193	clrl	sp@-		| or code arg
194	movl	#T_COPERR,sp@-	| push trap type
195	jra	Ltrapnstkadj	| call trap and deal with stack adjustments
196
197_fmterr:
198	clrw	sp@-
199	moveml	#0xFFFF,sp@-
200	movl	usp,a0		| get and save
201	movl	a0,sp@(60)	|   the user stack pointer
202	clrl	sp@-		| no VA arg
203	clrl	sp@-		| or code arg
204	movl	#T_FMTERR,sp@-	| push trap type
205	jra	Ltrapnstkadj	| call trap and deal with stack adjustments
206
207/*
208 * Other exceptions only cause four and six word stack frame and require
209 * no post-trap stack adjustment.
210 */
211_illinst:
212	clrw	sp@-
213	moveml	#0xFFFF,sp@-
214	moveq	#T_ILLINST,d0
215	jra	fault
216
217_zerodiv:
218	clrw	sp@-
219	moveml	#0xFFFF,sp@-
220	moveq	#T_ZERODIV,d0
221	jra	fault
222
223_chkinst:
224	clrw	sp@-
225	moveml	#0xFFFF,sp@-
226	moveq	#T_CHKINST,d0
227	jra	fault
228
229_trapvinst:
230	clrw	sp@-
231	moveml	#0xFFFF,sp@-
232	moveq	#T_TRAPVINST,d0
233	jra	fault
234
235_privinst:
236	clrw	sp@-
237	moveml	#0xFFFF,sp@-
238	moveq	#T_PRIVINST,d0
239	jra	fault
240
241	.globl	fault
242fault:
243	movl	usp,a0			| get and save
244	movl	a0,sp@(60)		|   the user stack pointer
245	clrl	sp@-			| no VA arg
246	clrl	sp@-			| or code arg
247	movl	d0,sp@-			| push trap type
248	jbsr	_trap			| handle trap
249	lea	sp@(12),sp		| pop value args
250	movl	sp@(60),a0		| restore
251	movl	a0,usp			|   user SP
252	moveml	sp@+,#0x7FFF		| restore most user regs
253	addql	#6,sp			| pop SP and pad word
254	jra	rei			| all done
255
256	.globl	_straytrap
257_badtrap:
258	clrw	sp@-			| pad SR
259	moveml	#0xC0C0,sp@-		| save scratch regs
260	movw	sp@(24),sp@-		| push exception vector info
261	clrw	sp@-
262	movl	sp@(24),sp@-		| and PC
263	jbsr	_straytrap		| report
264	addql	#8,sp			| pop args
265	moveml	sp@+,#0x0303		| restore regs
266	addql	#2,sp			| pop padding
267	jra	rei			| all done
268
269	.globl	_syscall
270_trap0:
271	clrw	sp@-			| pad SR to longword
272	moveml	#0xFFFF,sp@-		| save user registers
273	movl	usp,a0			| save the user SP
274	movl	a0,sp@(60)		|   in the savearea
275	movl	d0,sp@-			| push syscall number
276	jbsr	_syscall		| handle it
277	addql	#4,sp			| pop syscall arg
278	movl	sp@(60),a0		| grab and restore
279	movl	a0,usp			|   user SP
280	moveml	sp@+,#0x7FFF		| restore most registers
281	addql	#6,sp			| pop SSP and align word
282	jra	rei			| all done
283
284/*
285 * trap1 is sigreturn and trap2 is breakpoint.
286 */
287_trap1:
288	jra	sigreturn		| trap1 is sigreturn
289
290_trap2:
291	jra	_trace			| trap2 is breakpoint
292
293/*
294 * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD)
295 *	cachectl(command, addr, length)
296 * command in d0, addr in a1, length in d1
297 */
298	.globl	_cachectl
299_trap12:
300	movl	d1,sp@-			| push length
301	movl	a1,sp@-			| push addr
302	movl	d0,sp@-			| push command
303	jbsr	_cachectl		| do it
304	lea	sp@(12),sp		| pop args
305	jra	rei			| all done
306
307/*
308 * Trap 15 is used for:
309 *	- KGDB traps
310 *	- trace traps for SUN binaries (not fully supported yet)
311 * We just pass it on and let trap() sort it all out
312 */
313_trap15:
314	clrw	sp@-
315	moveml	#0xFFFF,sp@-
316#ifdef KGDB
317	moveq	#T_TRAP15,d0
318	movl	sp@(64),d1		| from user mode?
319	andl	#PSL_S,d1
320	jeq	fault
321	movl	d0,sp@-
322	.globl	_kgdb_trap_glue
323	jbsr	_kgdb_trap_glue		| returns if no debugger
324	addl	#4,sp
325#endif
326	moveq	#T_TRAP15,d0
327	jra	fault
328
329/*
330 * Hit a breakpoint (trap 1 or 2) instruction.
331 * Push the code and treat as a normal fault.
332 */
333_trace:
334	clrw	sp@-
335	moveml	#0xFFFF,sp@-
336#ifdef KGDB
337	moveq	#T_TRACE,d0
338	movl	sp@(64),d1		| from user mode?
339	andl	#PSL_S,d1
340	jeq	fault
341	movl	d0,sp@-
342	jbsr	_kgdb_trap_glue		| returns if no debugger
343	addl	#4,sp
344#endif
345	moveq	#T_TRACE,d0
346	jra	fault
347
348/*
349 * The sigreturn() syscall comes here.  It requires special handling
350 * because we must open a hole in the stack to fill in the (possibly much
351 * larger) original stack frame.
352 */
353sigreturn:
354	lea	sp@(-84),sp		| leave enough space for largest frame
355	movl	sp@(84),sp@		| move up current 8 byte frame
356	movl	sp@(88),sp@(4)
357	movw	#84,sp@-		| default: adjust by 84 bytes
358	moveml	#0xFFFF,sp@-		| save user registers
359	movl	usp,a0			| save the user SP
360	movl	a0,sp@(60)		|   in the savearea
361	movl	#SYS_sigreturn,sp@-	| push syscall number
362	jbsr	_syscall		| handle it
363	addql	#4,sp			| pop syscall#
364	movl	sp@(60),a0		| grab and restore
365	movl	a0,usp			|   user SP
366	lea	sp@(64),a1		| pointer to HW frame
367	movw	a1@+,d0			| do we need to adjust the stack?
368	jeq	Lsigr1			| no, just continue
369	moveq	#92,d1			| total size
370	subw	d0,d1			|  - hole size = frame size
371	lea	a1@(92),a0		| destination
372	addw	d1,a1			| source
373	lsrw	#1,d1			| convert to word count
374	subqw	#1,d1			| minus 1 for dbf
375Lsigrlp:
376	movw	a1@-,a0@-		| copy a word
377	dbf	d1,Lsigrlp		| continue
378	movl	a0,a1			| new HW frame base
379Lsigr1:
380	movl	a1,sp@(60)		| new SP value
381	moveml	sp@+,#0x7FFF		| restore user registers
382	movl	sp@,sp			| and our SP
383	jra	rei			| all done
384
385/*
386 * Interrupt handlers.
387 * All DIO device interrupts are auto-vectored.  Most can be configured
388 * to interrupt in the range IPL2 to IPL5.  Here are our assignments:
389 *
390 *	Level 0:	Spurious: ignored.
391 *	Level 1:	(low XP)
392 *	Level 2:	SCSI
393 *	Level 3:	LANCE
394 *	Level 4:	[PC98]
395 *	Level 5:	Clock
396 *	Level 6:	RS232C
397 *	Level 7:	Non-maskable: parity errors, Abort SW
398 */
399	.globl	_hardclock, _nmihand
400
401_spurintr:
402	addql	#1,_intrcnt+0
403	addql	#1,_cnt+V_INTR
404	jra	rei
405
406_lev1intr:
407	addql	#1,_intrcnt+4
408	addql	#1,_cnt+V_INTR
409	jra	rei			| XP not surpported yet	XXXX
410
411_lev2intr:
412	addql	#1,_intrcnt+8
413	clrw	sp@-
414	moveml	#0xC0C0,sp@-
415	jbsr	__scintr
416	moveml	sp@+,#0x0303
417	addql	#2,sp
418	addql	#1,_cnt+V_INTR
419	jra	rei
420
421_lev3intr:
422	addql	#1,_intrcnt+12
423	clrw	sp@-
424	moveml	#0xC0C0,sp@-
425	jbsr	__leintr
426	moveml	sp@+,#0x0303
427	addql	#2,sp
428	addql	#1,_cnt+V_INTR
429	jra	rei
430
431_lev4intr:
432	addql	#1,_intrcnt+16
433	addql	#1,_cnt+V_INTR
434	jra	rei			| EX-PC not surpported yet XXXX
435
436_lev6intr:
437	addql	#1,_intrcnt+24
438	clrw	sp@-
439	moveml	#0xC0C0,sp@-
440	jbsr	_siointr
441	moveml	sp@+,#0x0303
442	addql	#2,sp
443	addql	#1,_cnt+V_INTR
444	jra	rei
445
446_lev5intr:
447	clrw	sp@-
448	moveml	#0xC0C0,sp@-
449#ifdef DEBUG
450	.globl	_panicstr, _regdump, _panic
451	cmpl	#_kstack+NBPG,sp	| are we still in stack pages?
452	jcc	Lstackok		| yes, continue normally
453	tstl	_curproc		| if !curproc could have swtch_exit'ed,
454	jeq	Lstackok		|     might be on tmpstk
455	tstl	_panicstr		| have we paniced?
456	jne	Lstackok		| yes, do not re-panic
457	lea	tmpstk,sp		| no, switch to tmpstk
458	moveml	#0xFFFF,sp@-		| push all registers
459	movl	#Lstkrip,sp@-		| push panic message
460	jbsr	_printf			| preview
461	addql	#4,sp
462	movl	sp,a0			| remember this spot
463	movl	#256,sp@-		| longword count
464	movl	a0,sp@-			| and reg pointer
465	jbsr	_regdump		| dump core
466	addql	#8,sp			| pop params
467	movl	#Lstkrip,sp@-		| push panic message
468	jbsr	_panic			| ES and D
469Lstkrip:
470	.asciz	"k-stack overflow"
471	.even
472Lstackok:
473#endif
474	lea	sp@(16),a1		| a1 = &clockframe
475	btst	#CLK_INT,CLOCK_REG 	| system-clock intrrupt?
476	jeq	Lnottimer		| no, skip hardclock
477	movb	#CLK_CLR,CLOCK_REG	| clear system-clock interrupt
478        tstl	_clock_on		| system-clock started?
479        jeq	Lnottimer		| no, skip hardclock
480	addql	#1,_intrcnt+28		| count hardclock interrupt
481	movl	a1,sp@-
482	jbsr	_hardclock		| hardclock(&frame)
483	addql	#4,sp
484Lnottimer:
485	moveml	sp@+,#0x0303		| restore scratch regs
486	addql	#2,sp			| pop pad word
487	addql	#1,_cnt+V_INTR		| chalk up another interrupt
488	jra	rei			| all done
489
490_lev7intr:
491	addql	#1,_intrcnt+36
492	clrw	sp@-			| pad SR to longword
493	moveml	#0xFFFF,sp@-		| save registers
494	movl	usp,a0			| and save
495	movl	a0,sp@(60)		|   the user stack pointer
496	jbsr	_nmihand		| call handler
497	movl	sp@(60),a0		| restore
498	movl	a0,usp			|   user SP
499	moveml	sp@+,#0x7FFF		| and remaining registers
500	addql	#6,sp			| pop SSP and align word
501	jra	rei			| all done
502
503/*
504 * Emulation of VAX REI instruction.
505 *
506 * This code deals with checking for and servicing ASTs
507 * (profiling, scheduling) and software interrupts (network, softclock).
508 * We check for ASTs first, just like the VAX.  To avoid excess overhead
509 * the T_ASTFLT handling code will also check for software interrupts so we
510 * do not have to do it here.
511 *
512 * This code is complicated by the fact that sendsig may have been called
513 * necessitating a stack cleanup.
514 */
515	.comm	_ssir,1
516	.globl	_astpending
517rei:
518#ifdef DEBUG
519	tstl	_panicstr		| have we paniced?
520	jne	Ldorte			| yes, do not make matters worse
521#endif
522	tstl	_astpending		| AST pending?
523	jeq	Lchksir			| no, go check for SIR
524Lrei1:
525	btst	#5,sp@			| yes, are we returning to user mode?
526	jne	Lchksir			| no, go check for SIR
527	clrw	sp@-			| pad SR to longword
528	moveml	#0xFFFF,sp@-		| save all registers
529	movl	usp,a1			| including
530	movl	a1,sp@(60)		|    the users SP
531	clrl	sp@-			| VA == none
532	clrl	sp@-			| code == none
533	movl	#T_ASTFLT,sp@-		| type == async system trap
534	jbsr	_trap			| go handle it
535	lea	sp@(12),sp		| pop value args
536	movl	sp@(60),a0		| restore user SP
537	movl	a0,usp			|   from save area
538	movw	sp@(64),d0		| need to adjust stack?
539	jne	Laststkadj		| yes, go to it
540	moveml	sp@+,#0x7FFF		| no, restore most user regs
541	addql	#6,sp			| toss SSP and pad
542	rte				| and do real RTE
543Laststkadj:
544	lea	sp@(66),a1		| pointer to HW frame
545	addql	#8,a1			| source pointer
546	movl	a1,a0			| source
547	addw	d0,a0			|  + hole size = dest pointer
548	movl	a1@-,a0@-		| copy
549	movl	a1@-,a0@-		|  8 bytes
550	movl	a0,sp@(60)		| new SSP
551	moveml	sp@+,#0x7FFF		| restore user registers
552	movl	sp@,sp			| and our SP
553	rte				| and return
554Lchksir:
555	tstb	_ssir			| SIR pending?
556	jeq	Ldorte			| no, all done
557	movl	d0,sp@-			| need a scratch register
558	movw	sp@(4),d0		| get SR
559	andw	#PSL_IPL7,d0		| mask all but IPL
560	jne	Lnosir			| came from interrupt, no can do
561	movl	sp@+,d0			| restore scratch register
562Lgotsir:
563	movw	#SPL1,sr		| prevent others from servicing int
564	tstb	_ssir			| too late?
565	jeq	Ldorte			| yes, oh well...
566	clrw	sp@-			| pad SR to longword
567	moveml	#0xFFFF,sp@-		| save all registers
568	movl	usp,a1			| including
569	movl	a1,sp@(60)		|    the users SP
570	clrl	sp@-			| VA == none
571	clrl	sp@-			| code == none
572	movl	#T_SSIR,sp@-		| type == software interrupt
573	jbsr	_trap			| go handle it
574	lea	sp@(12),sp		| pop value args
575	movl	sp@(60),a0		| restore
576	movl	a0,usp			|   user SP
577	moveml	sp@+,#0x7FFF		| and all remaining registers
578	addql	#6,sp			| pop SSP and align word
579	rte
580Lnosir:
581	movl	sp@+,d0			| restore scratch register
582Ldorte:
583	rte				| real return
584
585/*
586 * Kernel access to the current processes kernel stack is via a fixed
587 * virtual address.  It is at the same address as in the users VA space.
588 * Umap contains the KVA of the first of UPAGES PTEs mapping VA _kstack.
589 */
590	.data
591	.set	_kstack,KERNELSTACK	| KERNELSTACK(0x3ff00000) != USRSTACK
592_Umap:	.long	0
593	.globl	_kstack, _Umap
594
595/*
596 * Initialization
597 *
598 * Kernel is loaded at 0.
599 * VBR contains zero from ROM.  Exceptions will continue to vector
600 * through ROM until MMU is turned on at which time they will vector
601 * through our table (vectors.s).
602 */
603	.comm	_lowram,4
604
605	.text
606	.globl	_edata
607	.globl	_etext,_end
608	.globl	start
609start:
610	movw	#PSL_HIGHIPL,sr		| no interrupts
611	lea	tmpstk,sp		| give ourselves a temporary stack
612	clrl	d0			| XXXX if loader set vbr = 0
613	movc	d0,vbr			| XXXX please remove these 2 lines
614/*
615 * a5 contains parameters address from booter.
616 * First, we copy parameters to save area.
617 * (Now just save maxmem and so on. Not complete yet.) XXXX
618 */
619	movl	a5@(KI_MAXADDR),d0	| maxaddr
620	moveq	#PGSHIFT,d1
621	lsrl	d1,d0			| convert to page (click) number
622	movl	d0,_maxmem		| argument saved in maxmem
623	movl	d0,_physmem		| physmem = maxmem
624	clrl	_lowram			| lowram = 0
625	movl	#0,a5			| kernel is loaded at 0
626	movl	#CACHE_OFF,d0
627	movc	d0,cacr			| clear and disable on-chip cache(s)
628
629/* initialize source/destination control registers for movs */
630	moveq	#FC_USERD,d0		| user space
631	movc	d0,sfc			|   as source
632	movc	d0,dfc			|   and destination of transfers
633
634/*
635 * LUNA  PIO initialization.
636 */
637	movb	#PIO_MODED,PIO0_CTL	| read dipswitch
638	movb	PIO0_B,d0		| dipsw-2 (from portB)
639	lsll	#8,d0
640	movb	PIO0_A,d0		| dipsw-1 (from portA)
641	movw	d0,_dipswitch
642
643/* configure kernel and proc0 VA space so we can get going */
644	.globl	_Sysseg, _pmap_bootstrap, _avail_start
645	movl	#_end,d5		| end of static kernel text/data
646	addl	#NBPG-1,d5
647	andl	#PG_FRAME,d5		| round to a page
648	movl	d5,a4			| PA=VA
649	pea	a5@			| firstpa
650	pea	a4@			| nextpa
651	jbsr	_pmap_bootstrap		| bootstrap(firstpa, nextpa)
652	addql	#8,sp
653
654/*
655 * Prepare to enable MMU.
656 */
657	movl	_Sysseg,a1		| system segment table addr read value (a KVA)
658	lea	_protorp,a0
659	movl	#0x80000202,a0@		| nolimit + share global + 4 byte PTEs
660	movl	a1,a0@(4)		| + segtable address
661	pmove	a0@,srp			| load the supervisor root pointer
662	movl	#0x80000002,a0@		| reinit upper half for CRP loads
663/* we must set tt-registers here */
664	lea	_protott0,a0
665	.word	0xf010			| pmove	a0@,mmutt0
666	.word	0x0800
667	lea	_protott1,a0
668	.word	0xf010			| pmove	a0@,mmutt1
669	.word	0x0c00
670	movl	#0x82c0aa00,a2@		| value to load TC with
671	pmove	a2@,tc			| load it
672
673/*
674 * Should be running mapped from this point on
675 */
676#ifdef FPCOPROC
677/* fpp check */
678	movl	a1,sp@-
679	jbsr	_checkfpp		| check fpp
680	frestore _fppnull		| reset
681	movl	sp@+,a1
682#endif
683/* select the software page size now */
684	lea	tmpstk,sp		| temporary stack
685	jbsr	_vm_set_page_size	| select software page size
686#ifdef BOOTDEBUG
687	movl	a5,sp@-			| phys load address (assumes VA 0)
688	movl	a4,sp@-			| first available PA
689	jbsr	_Opmap_bootstrap	| sync up pmap module
690	addql	#8,sp
691#endif
692/* set kernel stack, user SP, and initial pcb */
693	lea	_kstack,a1		| proc0 kernel stack
694	lea	a1@(UPAGES*NBPG-4),sp	| set kernel stack to end of area
695	movl	#USRSTACK-4,a2
696	movl	a2,usp			| init user SP
697	movl	_proc0paddr,a1		| get proc0 pcb addr
698	movl	a1,_curpcb		| proc0 is running
699	clrw	a1@(PCB_FLAGS)		| clear flags
700#ifdef FPCOPROC
701	clrl	a1@(PCB_FPCTX)		| ensure null FP context
702	movl	a1,sp@-
703	jbsr	_m68881_restore		| restore it (does not kill a1)
704	addql	#4,sp
705#endif
706/* flush TLB and turn on caches */
707	jbsr	_TBIA			| invalidate TLB
708	movl	#CACHE_ON,d0
709	movc	d0,cacr			| clear cache(s)
710/* final setup for C code */
711	movw	#PSL_LOWIPL,sr		| lower SPL
712	movl	d7,_boothowto		| save reboot flags
713	movl	d6,_bootdev		|   and boot device
714	jbsr	_main			| call main()
715
716/* proc[1] == init now running here;
717 * create a null exception frame and return to user mode in icode
718 */
719	clrw	sp@-			| vector offset/frame type
720	clrl	sp@-			| return to icode location 0
721	movw	#PSL_USER,sp@-		| in user mode
722	rte
723
724/*
725 * Signal "trampoline" code (18 bytes).  Invoked from RTE setup by sendsig().
726 *
727 * Stack looks like:
728 *
729 *	sp+0 ->	signal number
730 *	sp+4	signal specific code
731 *	sp+8	pointer to signal context frame (scp)
732 *	sp+12	address of handler
733 *	sp+16	saved hardware state
734 *			.
735 *			.
736 *	scp+0->	beginning of signal context frame
737 */
738	.globl	_sigcode, _esigcode
739	.data
740_sigcode:
741	movl	sp@(12),a0		| signal handler addr	(4 bytes)
742	jsr	a0@			| call signal handler	(2 bytes)
743	addql	#4,sp			| pop signo		(2 bytes)
744	trap	#1			| special syscall entry	(2 bytes)
745	movl	d0,sp@(4)		| save errno		(4 bytes)
746	moveq	#1,d0			| syscall == exit	(2 bytes)
747	trap	#0			| exit(errno)		(2 bytes)
748	.align	2
749_esigcode:
750
751/*
752 * Icode is copied out to process 1 to exec init.
753 * If the exec fails, process 1 exits.
754 */
755	.globl	_icode,_szicode
756	.text
757_icode:
758	clrl	sp@-
759	pea	pc@((argv-.)+2)
760	pea	pc@((init-.)+2)
761	clrl	sp@-
762	moveq	#SYS_execve,d0
763	trap	#0
764	moveq	#SYS_exit,d0
765	trap	#0
766init:
767	.asciz	"/sbin/init"
768	.even
769argv:
770	.long	init+6-_icode		| argv[0] = "init" ("/sbin/init" + 6)
771	.long	eicode-_icode		| argv[1] follows icode after copyout
772	.long	0
773eicode:
774
775_szicode:
776	.long	_szicode-_icode
777
778/*
779 * Primitives
780 */
781
782#ifdef GPROF
783#define	ENTRY(name) \
784	.globl _/**/name; _/**/name: link a6,#0; jbsr mcount; unlk a6
785#define ALTENTRY(name, rname) \
786	ENTRY(name); jra rname+12
787#else
788#define	ENTRY(name) \
789	.globl _/**/name; _/**/name:
790#define ALTENTRY(name, rname) \
791	.globl _/**/name; _/**/name:
792#endif
793
794/*
795 * copyinstr(fromaddr, toaddr, maxlength, &lencopied)
796 *
797 * Copy a null terminated string from the user address space into
798 * the kernel address space.
799 * NOTE: maxlength must be < 64K
800 */
801ENTRY(copyinstr)
802	movl	_curpcb,a0		| current pcb
803	movl	#Lcisflt1,a0@(PCB_ONFAULT) | set up to catch faults
804	movl	sp@(4),a0		| a0 = fromaddr
805	movl	sp@(8),a1		| a1 = toaddr
806	moveq	#0,d0
807	movw	sp@(14),d0		| d0 = maxlength
808	jlt	Lcisflt1		| negative count, error
809	jeq	Lcisdone		| zero count, all done
810	subql	#1,d0			| set up for dbeq
811Lcisloop:
812	movsb	a0@+,d1			| grab a byte
813	nop
814	movb	d1,a1@+			| copy it
815	dbeq	d0,Lcisloop		| if !null and more, continue
816	jne	Lcisflt2		| ran out of room, error
817	moveq	#0,d0			| got a null, all done
818Lcisdone:
819	tstl	sp@(16)			| return length desired?
820	jeq	Lcisret			| no, just return
821	subl	sp@(4),a0		| determine how much was copied
822	movl	sp@(16),a1		| return location
823	movl	a0,a1@			| stash it
824Lcisret:
825	movl	_curpcb,a0		| current pcb
826	clrl	a0@(PCB_ONFAULT) 	| clear fault addr
827	rts
828Lcisflt1:
829	moveq	#EFAULT,d0		| copy fault
830	jra	Lcisdone
831Lcisflt2:
832	moveq	#ENAMETOOLONG,d0	| ran out of space
833	jra	Lcisdone
834
835/*
836 * copyoutstr(fromaddr, toaddr, maxlength, &lencopied)
837 *
838 * Copy a null terminated string from the kernel
839 * address space to the user address space.
840 * NOTE: maxlength must be < 64K
841 */
842ENTRY(copyoutstr)
843	movl	_curpcb,a0		| current pcb
844	movl	#Lcosflt1,a0@(PCB_ONFAULT) | set up to catch faults
845	movl	sp@(4),a0		| a0 = fromaddr
846	movl	sp@(8),a1		| a1 = toaddr
847	moveq	#0,d0
848	movw	sp@(14),d0		| d0 = maxlength
849	jlt	Lcosflt1		| negative count, error
850	jeq	Lcosdone		| zero count, all done
851	subql	#1,d0			| set up for dbeq
852Lcosloop:
853	movb	a0@+,d1			| grab a byte
854	movsb	d1,a1@+			| copy it
855	nop
856	dbeq	d0,Lcosloop		| if !null and more, continue
857	jne	Lcosflt2		| ran out of room, error
858	moveq	#0,d0			| got a null, all done
859Lcosdone:
860	tstl	sp@(16)			| return length desired?
861	jeq	Lcosret			| no, just return
862	subl	sp@(4),a0		| determine how much was copied
863	movl	sp@(16),a1		| return location
864	movl	a0,a1@			| stash it
865Lcosret:
866	movl	_curpcb,a0		| current pcb
867	clrl	a0@(PCB_ONFAULT) 	| clear fault addr
868	rts
869Lcosflt1:
870	moveq	#EFAULT,d0		| copy fault
871	jra	Lcosdone
872Lcosflt2:
873	moveq	#ENAMETOOLONG,d0	| ran out of space
874	jra	Lcosdone
875
876/*
877 * copystr(fromaddr, toaddr, maxlength, &lencopied)
878 *
879 * Copy a null terminated string from one point to another in
880 * the kernel address space.
881 * NOTE: maxlength must be < 64K
882 */
883ENTRY(copystr)
884	movl	sp@(4),a0		| a0 = fromaddr
885	movl	sp@(8),a1		| a1 = toaddr
886	moveq	#0,d0
887	movw	sp@(14),d0		| d0 = maxlength
888	jlt	Lcsflt1			| negative count, error
889	jeq	Lcsdone			| zero count, all done
890	subql	#1,d0			| set up for dbeq
891Lcsloop:
892	movb	a0@+,a1@+		| copy a byte
893	dbeq	d0,Lcsloop		| if !null and more, continue
894	jne	Lcsflt2			| ran out of room, error
895	moveq	#0,d0			| got a null, all done
896Lcsdone:
897	tstl	sp@(16)			| return length desired?
898	jeq	Lcsret			| no, just return
899	subl	sp@(4),a0		| determine how much was copied
900	movl	sp@(16),a1		| return location
901	movl	a0,a1@			| stash it
902Lcsret:
903	rts
904Lcsflt1:
905	moveq	#EFAULT,d0		| copy fault
906	jra	Lcsdone
907Lcsflt2:
908	moveq	#ENAMETOOLONG,d0	| ran out of space
909	jra	Lcsdone
910
911/*
912 * Copyin(from, to, len)
913 *
914 * Copy specified amount of data from user space into the kernel.
915 * NOTE: len must be < 64K
916 */
917ENTRY(copyin)
918	movl	d2,sp@-			| scratch register
919	movl	_curpcb,a0		| current pcb
920	movl	#Lciflt,a0@(PCB_ONFAULT) | set up to catch faults
921	movl	sp@(16),d2		| check count
922	jlt	Lciflt			| negative, error
923	jeq	Lcidone			| zero, done
924	movl	sp@(8),a0		| src address
925	movl	sp@(12),a1		| dest address
926	movl	a0,d0
927	btst	#0,d0			| src address odd?
928	jeq	Lcieven			| no, go check dest
929	movsb	a0@+,d1			| yes, get a byte
930	nop
931	movb	d1,a1@+			| put a byte
932	subql	#1,d2			| adjust count
933	jeq	Lcidone			| exit if done
934Lcieven:
935	movl	a1,d0
936	btst	#0,d0			| dest address odd?
937	jne	Lcibyte			| yes, must copy by bytes
938	movl	d2,d0			| no, get count
939	lsrl	#2,d0			| convert to longwords
940	jeq	Lcibyte			| no longwords, copy bytes
941	subql	#1,d0			| set up for dbf
942Lcilloop:
943	movsl	a0@+,d1			| get a long
944	nop
945	movl	d1,a1@+			| put a long
946	dbf	d0,Lcilloop		| til done
947	andl	#3,d2			| what remains
948	jeq	Lcidone			| all done
949Lcibyte:
950	subql	#1,d2			| set up for dbf
951Lcibloop:
952	movsb	a0@+,d1			| get a byte
953	nop
954	movb	d1,a1@+			| put a byte
955	dbf	d2,Lcibloop		| til done
956Lcidone:
957	moveq	#0,d0			| success
958Lciexit:
959	movl	_curpcb,a0		| current pcb
960	clrl	a0@(PCB_ONFAULT) 	| clear fault catcher
961	movl	sp@+,d2			| restore scratch reg
962	rts
963Lciflt:
964	moveq	#EFAULT,d0		| got a fault
965	jra	Lciexit
966
967/*
968 * Copyout(from, to, len)
969 *
970 * Copy specified amount of data from kernel to the user space
971 * NOTE: len must be < 64K
972 */
973ENTRY(copyout)
974	movl	d2,sp@-			| scratch register
975	movl	_curpcb,a0		| current pcb
976	movl	#Lcoflt,a0@(PCB_ONFAULT) | catch faults
977	movl	sp@(16),d2		| check count
978	jlt	Lcoflt			| negative, error
979	jeq	Lcodone			| zero, done
980	movl	sp@(8),a0		| src address
981	movl	sp@(12),a1		| dest address
982	movl	a0,d0
983	btst	#0,d0			| src address odd?
984	jeq	Lcoeven			| no, go check dest
985	movb	a0@+,d1			| yes, get a byte
986	movsb	d1,a1@+			| put a byte
987	nop
988	subql	#1,d2			| adjust count
989	jeq	Lcodone			| exit if done
990Lcoeven:
991	movl	a1,d0
992	btst	#0,d0			| dest address odd?
993	jne	Lcobyte			| yes, must copy by bytes
994	movl	d2,d0			| no, get count
995	lsrl	#2,d0			| convert to longwords
996	jeq	Lcobyte			| no longwords, copy bytes
997	subql	#1,d0			| set up for dbf
998Lcolloop:
999	movl	a0@+,d1			| get a long
1000	movsl	d1,a1@+			| put a long
1001	nop
1002	dbf	d0,Lcolloop		| til done
1003	andl	#3,d2			| what remains
1004	jeq	Lcodone			| all done
1005Lcobyte:
1006	subql	#1,d2			| set up for dbf
1007Lcobloop:
1008	movb	a0@+,d1			| get a byte
1009	movsb	d1,a1@+			| put a byte
1010	nop
1011	dbf	d2,Lcobloop		| til done
1012Lcodone:
1013	moveq	#0,d0			| success
1014Lcoexit:
1015	movl	_curpcb,a0		| current pcb
1016	clrl	a0@(PCB_ONFAULT) 	| clear fault catcher
1017	movl	sp@+,d2			| restore scratch reg
1018	rts
1019Lcoflt:
1020	moveq	#EFAULT,d0		| got a fault
1021	jra	Lcoexit
1022
1023/*
1024 * non-local gotos
1025 */
1026ENTRY(setjmp)
1027	movl	sp@(4),a0	| savearea pointer
1028	moveml	#0xFCFC,a0@	| save d2-d7/a2-a7
1029	movl	sp@,a0@(48)	| and return address
1030	moveq	#0,d0		| return 0
1031	rts
1032
1033ENTRY(qsetjmp)
1034	movl	sp@(4),a0	| savearea pointer
1035	lea	a0@(40),a0	| skip regs we do not save
1036	movl	a6,a0@+		| save FP
1037	movl	sp,a0@+		| save SP
1038	movl	sp@,a0@		| and return address
1039	moveq	#0,d0		| return 0
1040	rts
1041
1042ENTRY(longjmp)
1043	movl	sp@(4),a0
1044	moveml	a0@+,#0xFCFC
1045	movl	a0@,sp@
1046	moveq	#1,d0
1047	rts
1048
1049/*
1050 * The following primitives manipulate the run queues.
1051 * _whichqs tells which of the 32 queues _qs
1052 * have processes in them.  Setrq puts processes into queues, Remrq
1053 * removes them from queues.  The running process is on no queue,
1054 * other processes are on a queue related to p->p_pri, divided by 4
1055 * actually to shrink the 0-127 range of priorities into the 32 available
1056 * queues.
1057 */
1058
1059	.globl	_whichqs,_qs,_cnt,_panic
1060	.globl	_curproc,_want_resched
1061
1062/*
1063 * Setrq(p)
1064 *
1065 * Call should be made at spl6(), and p->p_stat should be SRUN
1066 */
1067ENTRY(setrq)
1068	movl	sp@(4),a0
1069	tstl	a0@(P_RLINK)
1070	jeq	Lset1
1071	movl	#Lset2,sp@-
1072	jbsr	_panic
1073Lset1:
1074	clrl	d0
1075	movb	a0@(P_PRI),d0
1076	lsrb	#2,d0
1077	movl	_whichqs,d1
1078	bset	d0,d1
1079	movl	d1,_whichqs
1080	lslb	#3,d0
1081	addl	#_qs,d0
1082	movl	d0,a0@(P_LINK)
1083	movl	d0,a1
1084	movl	a1@(P_RLINK),a0@(P_RLINK)
1085	movl	a0,a1@(P_RLINK)
1086	movl	a0@(P_RLINK),a1
1087	movl	a0,a1@(P_LINK)
1088	rts
1089
1090Lset2:
1091	.asciz	"setrq"
1092	.even
1093
1094/*
1095 * Remrq(p)
1096 *
1097 * Call should be made at spl6().
1098 */
1099ENTRY(remrq)
1100	movl	sp@(4),a0
1101	clrl	d0
1102	movb	a0@(P_PRI),d0
1103	lsrb	#2,d0
1104	movl	_whichqs,d1
1105	bclr	d0,d1
1106	jne	Lrem1
1107	movl	#Lrem3,sp@-
1108	jbsr	_panic
1109Lrem1:
1110	movl	d1,_whichqs
1111	movl	a0@(P_LINK),a1
1112	movl	a0@(P_RLINK),a1@(P_RLINK)
1113	movl	a0@(P_RLINK),a1
1114	movl	a0@(P_LINK),a1@(P_LINK)
1115	movl	#_qs,a1
1116	movl	d0,d1
1117	lslb	#3,d1
1118	addl	d1,a1
1119	cmpl	a1@(P_LINK),a1
1120	jeq	Lrem2
1121	movl	_whichqs,d1
1122	bset	d0,d1
1123	movl	d1,_whichqs
1124Lrem2:
1125	clrl	a0@(P_RLINK)
1126	rts
1127
1128Lrem3:
1129	.asciz	"remrq"
1130Lsw0:
1131	.asciz	"swtch"
1132	.even
1133
1134	.globl	_curpcb
1135	.globl	_masterpaddr	| XXX compatibility (debuggers)
1136	.data
1137_masterpaddr:			| XXX compatibility (debuggers)
1138_curpcb:
1139	.long	0
1140pcbflag:
1141	.byte	0		| copy of pcb_flags low byte
1142	.align	2
1143	.comm	nullpcb,SIZEOF_PCB
1144	.text
1145
1146/*
1147 * At exit of a process, do a swtch for the last time.
1148 * The mapping of the pcb at p->p_addr has already been deleted,
1149 * and the memory for the pcb+stack has been freed.
1150 * The ipl is high enough to prevent the memory from being reallocated.
1151 */
1152ENTRY(swtch_exit)
1153	movl	#nullpcb,_curpcb	| save state into garbage pcb
1154	lea	tmpstk,sp		| goto a tmp stack
1155	jra	_cpu_swtch
1156
1157/*
1158 * When no processes are on the runq, Swtch branches to idle
1159 * to wait for something to come ready.
1160 */
1161	.globl	Idle
1162Lidle:
1163	stop	#PSL_LOWIPL
1164Idle:
1165idle:
1166	movw	#PSL_HIGHIPL,sr
1167	tstl	_whichqs
1168	jeq	Lidle
1169	movw	#PSL_LOWIPL,sr
1170	jra	Lsw1
1171
1172Lbadsw:
1173	movl	#Lsw0,sp@-
1174	jbsr	_panic
1175	/*NOTREACHED*/
1176
1177/*
1178 * cpu_swtch()
1179 *
1180 * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the
1181 * entire ATC.  The effort involved in selective flushing may not be
1182 * worth it, maybe we should just flush the whole thing?
1183 *
1184 * NOTE 2: With the new VM layout we now no longer know if an inactive
1185 * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag
1186 * bit).  For now, we just always flush the full ATC.
1187 */
1188ENTRY(cpu_swtch)
1189	movl	_curpcb,a0		| current pcb
1190	movw	sr,a0@(PCB_PS)		| save sr before changing ipl
1191#ifdef notyet
1192	movl	_curproc,sp@-		| remember last proc running
1193#endif
1194	clrl	_curproc
1195	addql	#1,_cnt+V_SWTCH
1196
1197Lsw1:
1198	/*
1199	 * Find the highest-priority queue that isn't empty,
1200	 * then take the first proc from that queue.
1201	 */
1202	clrl	d0
1203	lea	_whichqs,a0
1204	movl	a0@,d1
1205Lswchk:
1206	btst	d0,d1
1207	jne	Lswfnd
1208	addqb	#1,d0
1209	cmpb	#32,d0
1210	jne	Lswchk
1211	jra	idle
1212Lswfnd:
1213	movw	#PSL_HIGHIPL,sr		| lock out interrupts
1214	movl	a0@,d1			| and check again...
1215	bclr	d0,d1
1216	jeq	Lsw1			| proc moved, rescan
1217	movl	d1,a0@			| update whichqs
1218	moveq	#1,d1			| double check for higher priority
1219	lsll	d0,d1			| process (which may have snuck in
1220	subql	#1,d1			| while we were finding this one)
1221	andl	a0@,d1
1222	jeq	Lswok			| no one got in, continue
1223	movl	a0@,d1
1224	bset	d0,d1			| otherwise put this one back
1225	movl	d1,a0@
1226	jra	Lsw1			| and rescan
1227Lswok:
1228	movl	d0,d1
1229	lslb	#3,d1			| convert queue number to index
1230	addl	#_qs,d1			| locate queue (q)
1231	movl	d1,a1
1232	cmpl	a1@(P_LINK),a1		| anyone on queue?
1233	jeq	Lbadsw			| no, panic
1234	movl	a1@(P_LINK),a0			| p = q->p_link
1235	movl	a0@(P_LINK),a1@(P_LINK)		| q->p_link = p->p_link
1236	movl	a0@(P_LINK),a1			| q = p->p_link
1237	movl	a0@(P_RLINK),a1@(P_RLINK)	| q->p_rlink = p->p_rlink
1238	cmpl	a0@(P_LINK),d1		| anyone left on queue?
1239	jeq	Lsw2			| no, skip
1240	movl	_whichqs,d1
1241	bset	d0,d1			| yes, reset bit
1242	movl	d1,_whichqs
1243Lsw2:
1244	movl	a0,_curproc
1245	clrl	_want_resched
1246#ifdef notyet
1247	movl	sp@+,a1
1248	cmpl	a0,a1			| switching to same proc?
1249	jeq	Lswdone			| yes, skip save and restore
1250#endif
1251	/*
1252	 * Save state of previous process in its pcb.
1253	 */
1254	movl	_curpcb,a1
1255	moveml	#0xFCFC,a1@(PCB_REGS)	| save non-scratch registers
1256	movl	usp,a2			| grab USP (a2 has been saved)
1257	movl	a2,a1@(PCB_USP)		| and save it
1258#ifdef FPCOPROC
1259	lea	a1@(PCB_FPCTX),a2	| pointer to FP save area
1260	fsave	a2@			| save FP state
1261	tstb	a2@			| null state frame?
1262	jeq	Lswnofpsave		| yes, all done
1263	fmovem	fp0-fp7,a2@(216)	| save FP general registers
1264	fmovem	fpcr/fpsr/fpi,a2@(312)	| save FP control registers
1265Lswnofpsave:
1266#endif
1267
1268#ifdef DIAGNOSTIC
1269	tstl	a0@(P_WCHAN)
1270	jne	Lbadsw
1271	cmpb	#SRUN,a0@(P_STAT)
1272	jne	Lbadsw
1273#endif
1274	clrl	a0@(P_RLINK)		| clear back link
1275	movl	a0@(P_ADDR),a1		| get p_addr
1276	movl	a1,_curpcb
1277	movb	a1@(PCB_FLAGS+1),pcbflag | copy of pcb_flags low byte
1278
1279	/* see if pmap_activate needs to be called; should remove this */
1280	movl	a0@(P_VMSPACE),a0	| vmspace = p->p_vmspace
1281#ifdef DIAGNOSTIC
1282	tstl	a0			| map == VM_MAP_NULL?
1283	jeq	Lbadsw			| panic
1284#endif
1285	lea	a0@(VM_PMAP),a0		| pmap = &vmspace.vm_pmap
1286	tstl	a0@(PM_STCHG)		| pmap->st_changed?
1287	jeq	Lswnochg		| no, skip
1288	pea	a1@			| push pcb (at p_addr)
1289	pea	a0@			| push pmap
1290	jbsr	_pmap_activate		| pmap_activate(pmap, pcb)
1291	addql	#8,sp
1292	movl	_curpcb,a1		| restore p_addr
1293Lswnochg:
1294
1295	movl	#PGSHIFT,d1
1296	movl	a1,d0
1297	lsrl	d1,d0			| convert p_addr to page number
1298	lsll	#2,d0			| and now to Sysmap offset
1299	addl	_Sysmap,d0		| add Sysmap base to get PTE addr
1300#ifdef notdef
1301	movw	#PSL_HIGHIPL,sr		| go crit while changing PTEs
1302#endif
1303	lea	tmpstk,sp		| now goto a tmp stack for NMI
1304	movl	d0,a0			| address of new context
1305	movl	_Umap,a2		| address of PTEs for kstack
1306	moveq	#UPAGES-1,d0		| sizeof kstack
1307Lres1:
1308	movl	a0@+,d1			| get PTE
1309	andl	#~PG_PROT,d1		| mask out old protection
1310	orl	#PG_RW+PG_V,d1		| ensure valid and writable
1311	movl	d1,a2@+			| load it up
1312	dbf	d0,Lres1		| til done
1313	movl	#CACHE_CLR,d0
1314	movc	d0,cacr			| invalidate cache(s)
1315	pflusha				| flush entire TLB
1316	movl	a1@(PCB_USTP),d0	| get USTP
1317	moveq	#PGSHIFT,d1
1318	lsll	d1,d0			| convert to addr
1319	lea	_protorp,a0		| CRP prototype
1320	movl	d0,a0@(4)		| stash USTP
1321	pmove	a0@,crp			| load new user root pointer
1322	moveml	a1@(PCB_REGS),#0xFCFC	| and registers
1323	movl	a1@(PCB_USP),a0
1324	movl	a0,usp			| and USP
1325#ifdef FPCOPROC
1326	lea	a1@(PCB_FPCTX),a0	| pointer to FP save area
1327	tstb	a0@			| null state frame?
1328	jeq	Lresfprest		| yes, easy
1329	fmovem	a0@(312),fpcr/fpsr/fpi	| restore FP control registers
1330	fmovem	a0@(216),fp0-fp7	| restore FP general registers
1331Lresfprest:
1332	frestore a0@			| restore state
1333#endif
1334	movw	a1@(PCB_PS),sr		| no, restore PS
1335	moveq	#1,d0			| return 1 (for alternate returns)
1336	rts
1337
1338/*
1339 * savectx(pcb, altreturn)
1340 * Update pcb, saving current processor state and arranging
1341 * for alternate return ala longjmp in swtch if altreturn is true.
1342 */
1343ENTRY(savectx)
1344	movl	sp@(4),a1
1345	movw	sr,a1@(PCB_PS)
1346	movl	usp,a0			| grab USP
1347	movl	a0,a1@(PCB_USP)		| and save it
1348	moveml	#0xFCFC,a1@(PCB_REGS)	| save non-scratch registers
1349#ifdef FPCOPROC
1350	lea	a1@(PCB_FPCTX),a0	| pointer to FP save area
1351	fsave	a0@			| save FP state
1352	tstb	a0@			| null state frame?
1353	jeq	Lsvnofpsave		| yes, all done
1354	fmovem	fp0-fp7,a0@(216)	| save FP general registers
1355	fmovem	fpcr/fpsr/fpi,a0@(312)	| save FP control registers
1356Lsvnofpsave:
1357#endif
1358	tstl	sp@(8)			| altreturn?
1359	jeq	Lsavedone
1360	movl	sp,d0			| relocate current sp relative to a1
1361	subl	#_kstack,d0		|   (sp is relative to kstack):
1362	addl	d0,a1			|   a1 += sp - kstack;
1363	movl	sp@,a1@			| write return pc at (relocated) sp@
1364Lsavedone:
1365	moveq	#0,d0			| return 0
1366	rts
1367
1368/*
1369 * {fu,su},{byte,sword,word}
1370 */
1371ALTENTRY(fuiword, _fuword)
1372ENTRY(fuword)
1373	movl	sp@(4),a0		| address to read
1374	movl	_curpcb,a1		| current pcb
1375	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
1376	movsl	a0@,d0			| do read from user space
1377	nop
1378	jra	Lfsdone
1379
1380ENTRY(fusword)
1381	movl	sp@(4),a0
1382	movl	_curpcb,a1		| current pcb
1383	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
1384	moveq	#0,d0
1385	movsw	a0@,d0			| do read from user space
1386	nop
1387	jra	Lfsdone
1388
1389/* Just like fusword, but tells trap code not to page in. */
1390ENTRY(fuswintr)
1391	movl	sp@(4),a0
1392	movl	_curpcb,a1
1393	movl	#_fswintr,a1@(PCB_ONFAULT)
1394	moveq	#0,d0
1395	movsw	a0@,d0
1396	nop
1397	jra	Lfsdone
1398
1399ALTENTRY(fuibyte, _fubyte)
1400ENTRY(fubyte)
1401	movl	sp@(4),a0		| address to read
1402	movl	_curpcb,a1		| current pcb
1403	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
1404	moveq	#0,d0
1405	movsb	a0@,d0			| do read from user space
1406	nop
1407	jra	Lfsdone
1408
1409Lfserr:
1410	moveq	#-1,d0			| error indicator
1411Lfsdone:
1412	clrl	a1@(PCB_ONFAULT) 	| clear fault address
1413	rts
1414
1415/* Just like Lfserr, but the address is different (& exported). */
1416	.globl	_fswintr
1417_fswintr:
1418	moveq	#-1,d0
1419	jra	Lfsdone
1420
1421
1422/*
1423 * Write a longword in user instruction space.
1424 * Largely the same as suword but with a final i-cache purge on those
1425 * machines with split caches.
1426 */
1427ENTRY(suiword)
1428	movl	sp@(4),a0		| address to write
1429	movl	sp@(8),d0		| value to put there
1430	movl	_curpcb,a1		| current pcb
1431	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
1432	movsl	d0,a0@			| do write to user space
1433	nop
1434	moveq	#0,d0			| indicate no fault
1435	movl	#IC_CLEAR,d1
1436	movc	d1,cacr			| invalidate i-cache
1437	jra	Lfsdone
1438
1439ENTRY(suword)
1440	movl	sp@(4),a0		| address to write
1441	movl	sp@(8),d0		| value to put there
1442	movl	_curpcb,a1		| current pcb
1443	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
1444	movsl	d0,a0@			| do write to user space
1445	nop
1446	moveq	#0,d0			| indicate no fault
1447	jra	Lfsdone
1448
1449ENTRY(susword)
1450	movl	sp@(4),a0		| address to write
1451	movw	sp@(10),d0		| value to put there
1452	movl	_curpcb,a1		| current pcb
1453	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
1454	movsw	d0,a0@			| do write to user space
1455	nop
1456	moveq	#0,d0			| indicate no fault
1457	jra	Lfsdone
1458
1459ENTRY(suswintr)
1460	movl	sp@(4),a0
1461	movw	sp@(10),d0
1462	movl	_curpcb,a1
1463	movl	#_fswintr,a1@(PCB_ONFAULT)
1464	movsw	d0,a0@
1465	nop
1466	moveq	#0,d0
1467	jra	Lfsdone
1468
1469ALTENTRY(suibyte, _subyte)
1470ENTRY(subyte)
1471	movl	sp@(4),a0		| address to write
1472	movb	sp@(11),d0		| value to put there
1473	movl	_curpcb,a1		| current pcb
1474	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
1475	movsb	d0,a0@			| do write to user space
1476	nop
1477	moveq	#0,d0			| indicate no fault
1478	jra	Lfsdone
1479
1480/*
1481 * Invalidate entire TLB.
1482 */
1483ENTRY(TBIA)
1484__TBIA:
1485	pflusha				| flush entire TLB
1486	movl	#DC_CLEAR,d0
1487	movc	d0,cacr			| invalidate on-chip d-cache
1488	rts
1489
1490/*
1491 * Invalidate any TLB entry for given VA (TB Invalidate Single)
1492 */
1493ENTRY(TBIS)
1494#ifdef DEBUG
1495	tstl	fulltflush		| being conservative?
1496	jne	__TBIA			| yes, flush entire TLB
1497#endif
1498
1499	movl	sp@(4),a0		| get addr to flush
1500	pflush	#0,#0,a0@		| flush address from both sides
1501	movl	#DC_CLEAR,d0
1502	movc	d0,cacr			| invalidate on-chip data cache
1503	rts
1504
1505/*
1506 * Invalidate supervisor side of TLB
1507 */
1508ENTRY(TBIAS)
1509#ifdef DEBUG
1510	tstl	fulltflush		| being conservative?
1511	jne	__TBIA			| yes, flush everything
1512#endif
1513	pflush #4,#4			| flush supervisor TLB entries
1514	movl	#DC_CLEAR,d0
1515	movc	d0,cacr			| invalidate on-chip d-cache
1516	rts
1517
1518/*
1519 * Invalidate user side of TLB
1520 */
1521ENTRY(TBIAU)
1522#ifdef DEBUG
1523	tstl	fulltflush		| being conservative?
1524	jne	__TBIA			| yes, flush everything
1525#endif
1526	pflush	#0,#4			| flush user TLB entries
1527	movl	#DC_CLEAR,d0
1528	movc	d0,cacr			| invalidate on-chip d-cache
1529	rts
1530
1531/*
1532 * Invalidate instruction cache
1533 */
1534ENTRY(ICIA)
1535	movl	#IC_CLEAR,d0
1536	movc	d0,cacr			| invalidate i-cache
1537	rts
1538
1539ENTRY(PCIA)
1540	movl	#DC_CLEAR,d0
1541	movc	d0,cacr			| invalidate on-chip d-cache
1542	rts
1543
1544/*
1545 * Get callers current SP value.
1546 * Note that simply taking the address of a local variable in a C function
1547 * doesn't work because callee saved registers may be outside the stack frame
1548 * defined by A6 (e.g. GCC generated code).
1549 */
1550	.globl	_getsp
1551_getsp:
1552	movl	sp,d0			| get current SP
1553	addql	#4,d0			| compensate for return address
1554	rts
1555
1556	.globl	_getsfc, _getdfc
1557_getsfc:
1558	movc	sfc,d0
1559	rts
1560_getdfc:
1561	movc	dfc,d0
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	lea	_protorp,a0		| CRP prototype
1572	movl	d0,a0@(4)		| stash USTP
1573	pmove	a0@,crp			| load root pointer
1574	movl	#DC_CLEAR,d0
1575	movc	d0,cacr			| invalidate on-chip d-cache
1576	rts
1577
1578ENTRY(ploadw)
1579	movl	sp@(4),a0		| address to load
1580	ploadw	#1,a0@			| pre-load translation
1581	rts
1582
1583/*
1584 * Set processor priority level calls.  Most are implemented with
1585 * inline asm expansions.  However, spl0 requires special handling
1586 * as we need to check for our emulated software interrupts.
1587 */
1588
1589ENTRY(spl0)
1590	moveq	#0,d0
1591	movw	sr,d0			| get old SR for return
1592	movw	#PSL_LOWIPL,sr		| restore new SR
1593	tstb	_ssir			| software interrupt pending?
1594	jeq	Lspldone		| no, all done
1595	subql	#4,sp			| make room for RTE frame
1596	movl	sp@(4),sp@(2)		| position return address
1597	clrw	sp@(6)			| set frame type 0
1598	movw	#PSL_LOWIPL,sp@		| and new SR
1599	jra	Lgotsir			| go handle it
1600Lspldone:
1601	rts
1602
1603ENTRY(_insque)
1604	movw	sr,d0
1605	movw	#PSL_HIGHIPL,sr		| atomic
1606	movl	sp@(8),a0		| where to insert (after)
1607	movl	sp@(4),a1		| element to insert (e)
1608	movl	a0@,a1@			| e->next = after->next
1609	movl	a0,a1@(4)		| e->prev = after
1610	movl	a1,a0@			| after->next = e
1611	movl	a1@,a0
1612	movl	a1,a0@(4)		| e->next->prev = e
1613	movw	d0,sr
1614	rts
1615
1616ENTRY(_remque)
1617	movw	sr,d0
1618	movw	#PSL_HIGHIPL,sr		| atomic
1619	movl	sp@(4),a0		| element to remove (e)
1620	movl	a0@,a1
1621	movl	a0@(4),a0
1622	movl	a0,a1@(4)		| e->next->prev = e->prev
1623	movl	a1,a0@			| e->prev->next = e->next
1624	movw	d0,sr
1625	rts
1626
1627/*
1628 * bzero(addr, count)
1629 */
1630ALTENTRY(blkclr, _bzero)
1631ENTRY(bzero)
1632	movl	sp@(4),a0	| address
1633	movl	sp@(8),d0	| count
1634	jeq	Lbzdone		| if zero, nothing to do
1635	movl	a0,d1
1636	btst	#0,d1		| address odd?
1637	jeq	Lbzeven		| no, can copy words
1638	clrb	a0@+		| yes, zero byte to get to even boundary
1639	subql	#1,d0		| decrement count
1640	jeq	Lbzdone		| none left, all done
1641Lbzeven:
1642	movl	d0,d1
1643	andl	#31,d0
1644	lsrl	#5,d1		| convert count to 8*longword count
1645	jeq	Lbzbyte		| no such blocks, zero byte at a time
1646Lbzloop:
1647	clrl	a0@+; clrl	a0@+; clrl	a0@+; clrl	a0@+;
1648	clrl	a0@+; clrl	a0@+; clrl	a0@+; clrl	a0@+;
1649	subql	#1,d1		| one more block zeroed
1650	jne	Lbzloop		| more to go, do it
1651	tstl	d0		| partial block left?
1652	jeq	Lbzdone		| no, all done
1653Lbzbyte:
1654	clrb	a0@+
1655	subql	#1,d0		| one more byte cleared
1656	jne	Lbzbyte		| more to go, do it
1657Lbzdone:
1658	rts
1659
1660/*
1661 * strlen(str)
1662 */
1663ENTRY(strlen)
1664	moveq	#-1,d0
1665	movl	sp@(4),a0	| string
1666Lslloop:
1667	addql	#1,d0		| increment count
1668	tstb	a0@+		| null?
1669	jne	Lslloop		| no, keep going
1670	rts
1671
1672/*
1673 * bcmp(s1, s2, len)
1674 *
1675 * WARNING!  This guy only works with counts up to 64K
1676 */
1677ENTRY(bcmp)
1678	movl	sp@(4),a0		| string 1
1679	movl	sp@(8),a1		| string 2
1680	moveq	#0,d0
1681	movw	sp@(14),d0		| length
1682	jeq	Lcmpdone		| if zero, nothing to do
1683	subqw	#1,d0			| set up for DBcc loop
1684Lcmploop:
1685	cmpmb	a0@+,a1@+		| equal?
1686	dbne	d0,Lcmploop		| yes, keep going
1687	addqw	#1,d0			| +1 gives zero on match
1688Lcmpdone:
1689	rts
1690
1691/*
1692 * {ov}bcopy(from, to, len)
1693 *
1694 * Works for counts up to 128K.
1695 */
1696ALTENTRY(ovbcopy, _bcopy)
1697ENTRY(bcopy)
1698	movl	sp@(12),d0		| get count
1699	jeq	Lcpyexit		| if zero, return
1700	movl	sp@(4),a0		| src address
1701	movl	sp@(8),a1		| dest address
1702	cmpl	a1,a0			| src before dest?
1703	jlt	Lcpyback		| yes, copy backwards (avoids overlap)
1704	movl	a0,d1
1705	btst	#0,d1			| src address odd?
1706	jeq	Lcfeven			| no, go check dest
1707	movb	a0@+,a1@+		| yes, copy a byte
1708	subql	#1,d0			| update count
1709	jeq	Lcpyexit		| exit if done
1710Lcfeven:
1711	movl	a1,d1
1712	btst	#0,d1			| dest address odd?
1713	jne	Lcfbyte			| yes, must copy by bytes
1714	movl	d0,d1			| no, get count
1715	lsrl	#2,d1			| convert to longwords
1716	jeq	Lcfbyte			| no longwords, copy bytes
1717	subql	#1,d1			| set up for dbf
1718Lcflloop:
1719	movl	a0@+,a1@+		| copy longwords
1720	dbf	d1,Lcflloop		| til done
1721	andl	#3,d0			| get remaining count
1722	jeq	Lcpyexit		| done if none
1723Lcfbyte:
1724	subql	#1,d0			| set up for dbf
1725Lcfbloop:
1726	movb	a0@+,a1@+		| copy bytes
1727	dbf	d0,Lcfbloop		| til done
1728Lcpyexit:
1729	rts
1730Lcpyback:
1731	addl	d0,a0			| add count to src
1732	addl	d0,a1			| add count to dest
1733	movl	a0,d1
1734	btst	#0,d1			| src address odd?
1735	jeq	Lcbeven			| no, go check dest
1736	movb	a0@-,a1@-		| yes, copy a byte
1737	subql	#1,d0			| update count
1738	jeq	Lcpyexit		| exit if done
1739Lcbeven:
1740	movl	a1,d1
1741	btst	#0,d1			| dest address odd?
1742	jne	Lcbbyte			| yes, must copy by bytes
1743	movl	d0,d1			| no, get count
1744	lsrl	#2,d1			| convert to longwords
1745	jeq	Lcbbyte			| no longwords, copy bytes
1746	subql	#1,d1			| set up for dbf
1747Lcblloop:
1748	movl	a0@-,a1@-		| copy longwords
1749	dbf	d1,Lcblloop		| til done
1750	andl	#3,d0			| get remaining count
1751	jeq	Lcpyexit		| done if none
1752Lcbbyte:
1753	subql	#1,d0			| set up for dbf
1754Lcbbloop:
1755	movb	a0@-,a1@-		| copy bytes
1756	dbf	d0,Lcbbloop		| til done
1757	rts
1758
1759/*
1760 * Emulate fancy VAX string operations:
1761 *	scanc(count, startc, table, mask)
1762 *	skpc(mask, count, startc)
1763 *	locc(mask, count, startc)
1764 */
1765ENTRY(scanc)
1766	movl	sp@(4),d0	| get length
1767	jeq	Lscdone		| nothing to do, return
1768	movl	sp@(8),a0	| start of scan
1769	movl	sp@(12),a1	| table to compare with
1770	movb	sp@(19),d1	| and mask to use
1771	movw	d2,sp@-		| need a scratch register
1772	clrw	d2		| clear it out
1773	subqw	#1,d0		| adjust for dbra
1774Lscloop:
1775	movb	a0@+,d2		| get character
1776	movb	a1@(0,d2:w),d2	| get table entry
1777	andb	d1,d2		| mask it
1778	dbne	d0,Lscloop	| keep going til no more or non-zero
1779	addqw	#1,d0		| overshot by one
1780	movw	sp@+,d2		| restore scratch
1781Lscdone:
1782	rts
1783
1784ENTRY(skpc)
1785	movl	sp@(8),d0	| get length
1786	jeq	Lskdone		| nothing to do, return
1787	movb	sp@(7),d1	| mask to use
1788	movl	sp@(12),a0	| where to start
1789	subqw	#1,d0		| adjust for dbcc
1790Lskloop:
1791	cmpb	a0@+,d1		| compate with mask
1792	dbne	d0,Lskloop	| keep going til no more or zero
1793	addqw	#1,d0		| overshot by one
1794Lskdone:
1795	rts
1796
1797ENTRY(locc)
1798	movl	sp@(8),d0	| get length
1799	jeq	Llcdone		| nothing to do, return
1800	movb	sp@(7),d1	| mask to use
1801	movl	sp@(12),a0	| where to start
1802	subqw	#1,d0		| adjust for dbcc
1803Llcloop:
1804	cmpb	a0@+,d1		| compate with mask
1805	dbeq	d0,Llcloop	| keep going til no more or non-zero
1806	addqw	#1,d0		| overshot by one
1807Llcdone:
1808	rts
1809
1810/*
1811 * Emulate VAX FFS (find first set) instruction.
1812 */
1813ENTRY(ffs)
1814	moveq	#-1,d0
1815	movl	sp@(4),d1
1816	jeq	Lffsdone
1817Lffsloop:
1818	addql	#1,d0
1819	btst	d0,d1
1820	jeq	Lffsloop
1821Lffsdone:
1822	addql	#1,d0
1823	rts
1824
1825#ifdef FPCOPROC
1826/*
1827 * Save and restore 68881 state.
1828 * Pretty awful looking since our assembler does not
1829 * recognize FP mnemonics.
1830 */
1831ENTRY(m68881_save)
1832	movl	sp@(4),a0		| save area pointer
1833	fsave	a0@			| save state
1834	tstb	a0@			| null state frame?
1835	jeq	Lm68881sdone		| yes, all done
1836	fmovem fp0-fp7,a0@(216)		| save FP general registers
1837	fmovem fpcr/fpsr/fpi,a0@(312)	| save FP control registers
1838Lm68881sdone:
1839	rts
1840
1841ENTRY(m68881_restore)
1842	movl	sp@(4),a0		| save area pointer
1843	tstb	a0@			| null state frame?
1844	jeq	Lm68881rdone		| yes, easy
1845	fmovem	a0@(312),fpcr/fpsr/fpi	| restore FP control registers
1846	fmovem	a0@(216),fp0-fp7	| restore FP general registers
1847Lm68881rdone:
1848	frestore a0@			| restore state
1849	rts
1850
1851/* LUNA */
1852
1853	.globl	_fpp_svarea
1854
1855/* Fpp is MC68882 ? */
1856ENTRY(is_68882)
1857	frestore _fppnull	| initialize fpp
1858	movl	#2,d0
1859	fmovecr	#0,fp1
1860	fsinx	fp1,fp2
1861	lea	_fpp_svarea,a0	| save area
1862	movw	sr,d1		| save status reg.
1863	movw	#0x2700,sr	| mask intrrupt
1864	fsave	a0@		| save fpp context
1865	movw	d1,sr		| restore status reg.
1866	movl	a0@,d1
1867	andl	#0x00ff0000,d1  | check status field
1868	cmpl	#0x00180000,d1  | 68881(idle)?
1869	beq	_is81
1870	cmpl	#0x00b40000,d1	| 68881(busy)?
1871	beq	_is81
1872	cmpl	#0x00380000,d1	| 68882(idle)?
1873	beq	_is82
1874	cmpl	#0x00d40000,d1	| 68882(busy)?
1875	beq	_is82
1876	bra	_is82out	| default 68881
1877_is81:
1878	clrl	d0
1879	bra	_is82out
1880_is82:
1881	movl	#1,d0
1882_is82out:
1883	frestore a0@
1884	rts
1885
1886#ifdef	OLD_LUNA
1887/* We have fpp ? */
1888ENTRY(havefpp)
1889	movl	a2,sp@-
1890	clrl	d0
1891	movl	vb,a2
1892	movl	a2@(FLINE_VEC),a0	| save vectors
1893	movl	a2@(COPRO_VEC),a1
1894	movl	sp,d1
1895	movl	#_fpvec,a2@(FLINE_VEC)	| change vectors
1896	movl	#_fpvec,a2@(COPRO_VEC)
1897	fnop				| cause exception ?
1898	movl	#1,d0
1899_fpvec:	movl	a0,a2@(FLINE_VEC)	| restore vectors
1900	movl	a1,a2@(COPRO_VEC)
1901	movl	d1,sp
1902	movl	sp@+,a2
1903	rts
1904#endif
1905#endif
1906
1907/*
1908 * Handle the nitty-gritty of rebooting the machine.
1909 * Basically we just turn off the MMU and jump to the appropriate ROM routine.
1910 * Note that we must be running in an address range that is mapped one-to-one
1911 * logical to physical so that the PC is still valid immediately after the MMU
1912 * is turned off.  We have conveniently mapped the last page of physical
1913 * memory this way.
1914 */
1915	.globl	_doboot
1916_doboot:
1917	movl	#0x41000004,a0
1918	movl	a0@,a1			| get PROM restart entry address
1919	movl	#CACHE_OFF,d0
1920	movc	d0,cacr			| disable on-chip cache(s)
1921	movl	#_tcroff,a0		| value for pmove to TC (turn off MMU)
1922	pmove	a0@,tc			| disable MMU
1923	jmp	a1@			| goto REBOOT
1924
1925	.data
1926	.space	NBPG
1927tmpstk:
1928	.globl	_protorp,_protott0,_protott1
1929_protorp:
1930	.long	0,0		| prototype root pointer
1931_protott0:
1932	.long	0x807F8543	| prototype tt0 register (for kernel)
1933_protott1:
1934	.long	0		| prototype tt0 register (for user)
1935	.globl	_cold
1936_cold:
1937	.long	1		| cold start flag
1938	.globl	_want_resched
1939_want_resched:
1940	.long	0
1941	.globl	_proc0paddr
1942_proc0paddr:
1943	.long	0		| KVA of proc0 u-area
1944
1945	.globl	_tcroff
1946_tcroff:
1947	.long	0		| TC reg. reset flag
1948
1949#ifdef FPCOPROC
1950	.globl	_fppnull
1951_fppnull:
1952	.long	0
1953#endif
1954	.globl	_clock_on
1955_clock_on:
1956	.long	0		| clock is enable ?
1957	.globl	_dipswitch
1958_dipswitch:
1959	.word	0		| dipsw(front panel) value
1960#ifdef DEBUG
1961	.globl	fulltflush, fullcflush
1962fulltflush:
1963	.long	0
1964fullcflush:
1965	.long	0
1966	.globl	timebomb
1967timebomb:
1968	.long	0
1969#endif
1970/* interrupt counters */
1971	.globl	_intrcnt,_eintrcnt,_intrnames,_eintrnames
1972_intrnames:
1973	.asciz	"spur"
1974	.asciz	"lev1"
1975	.asciz	"lev2"
1976	.asciz	"lev3"
1977	.asciz	"lev4"
1978	.asciz	"clock"
1979	.asciz	"lev7"
1980	.asciz	"nmi"
1981_eintrnames:
1982	.even
1983_intrcnt:
1984	.long	0,0,0,0,0,0,0,0,0
1985_eintrcnt:
1986