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