xref: /original-bsd/sys/luna68k/luna68k/locore.s (revision f673f637)
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.13 (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/* set 60 to hz, when running LUNA-I */
807	.globl	_modify_clock_param
808	jbsr	_modify_clock_param
809
810/* initialize source/destination control registers for movs */
811	moveq	#FC_USERD,d0		| user space
812	movc	d0,sfc			|   as source
813	movc	d0,dfc			|   and destination of transfers
814
815/*
816 * LUNA  PIO initialization.
817 */
818	movw	PIO0_A,d0		| dipsw-1,2 (from port A&B)
819	movw	d0,_dipswitch
820
821/* configure kernel and proc0 VA space so we can get going */
822	.globl	_Sysseg, _pmap_bootstrap, _avail_start
823	movl	#_end,d5		| end of static kernel text/data
824	addl	#NBPG-1,d5
825	andl	#PG_FRAME,d5		| round to a page
826	movl	d5,a4			| PA=VA
827	pea	a5@			| firstpa
828	pea	a4@			| nextpa
829	jbsr	_pmap_bootstrap		| bootstrap(firstpa, nextpa)
830	addql	#8,sp
831
832/*
833 * Prepare to enable MMU.
834 */
835	movl	_Sysseg,d1		| system segment table addr read value (a KVA)
836#if defined(LUNA2)
837	cmpl	#-2,_mmutype		| 68040?
838	jne	Lmotommu1		| no, skip
839
840	.long	0x4e7b1807		| movc d1,srp
841/* we must set tt-registers here */
842	movl	#0x403FA040,d0		| tt0 for LUNA2 0x40000000-0x7fffffff
843	.long	0x4e7b0004		| movc d0,itt0
844	.long	0x4e7b0006		| movc d0,dtt0
845	movl	#0x807FA040,d0		| tt1 for LUNA2 0x80000000-0xffffffff
846	.long	0x4e7b0005		| movc d0,itt1
847	.long	0x4e7b0007		| movc d0,dtt1
848	.word	0xf4d8			| cinva bc
849	.word	0xf518			| pflusha
850	movl	#0x8000,d0
851	.long	0x4e7b0003		| movc d0,tc
852	movl	#0x80008000,d0
853	movc	d0,cacr			| turn on both caches
854	jmp	Lenab1
855Lmotommu1:
856#endif
857	lea	_protorp,a0
858	movl	#0x80000202,a0@		| nolimit + share global + 4 byte PTEs
859	movl	d1,a0@(4)		| + segtable address
860	pmove	a0@,srp			| load the supervisor root pointer
861	movl	#0x80000002,a0@		| reinit upper half for CRP loads
862/* we must set tt-registers here */
863	lea	_protott0,a0		| tt0 for LUNA1 0x40000000-0x7fffffff
864	.word	0xf010			| pmove	a0@,mmutt0
865	.word	0x0800
866	lea	_protott1,a0		| tt1 for LUNA1 0x80000000-0xffffffff
867	.word	0xf010			| pmove	a0@,mmutt1
868	.word	0x0c00
869	lea	_mapping_tc,a2
870	movl	#0x82c0aa00,a2@		| value to load TC with
871	pmove	a2@,tc			| load it
872
873/*
874 * Should be running mapped from this point on
875 */
876Lenab1:
877#ifdef FPCOPROC
878/* fpp check */
879	movl	a1,sp@-
880	jbsr	_checkfpp		| check fpp
881	frestore _fppnull		| reset
882	movl	sp@+,a1
883#endif
884/* select the software page size now */
885	lea	tmpstk,sp		| temporary stack
886	jbsr	_vm_set_page_size	| select software page size
887/* set kernel stack, user SP, and initial pcb */
888	lea	_kstack,a1		| proc0 kernel stack
889	lea	a1@(UPAGES*NBPG-4),sp	| set kernel stack to end of area
890	movl	#USRSTACK-4,a2
891	movl	a2,usp			| init user SP
892	movl	_proc0paddr,a1		| get proc0 pcb addr
893	movl	a1,_curpcb		| proc0 is running
894#ifdef FPCOPROC
895	clrl	a1@(PCB_FPCTX)		| ensure null FP context
896	movl	a1,sp@-
897	jbsr	_m68881_restore		| restore it (does not kill a1)
898	addql	#4,sp
899#endif
900/* flush TLB and turn on caches */
901	jbsr	_TBIA			| invalidate TLB
902#if defined(LUNA2)
903	cmpl	#-2,_mmutype		| 68040?
904	jeq	Lnocache0		| yes, cache already on
905#endif
906	movl	#CACHE_ON,d0
907	movc	d0,cacr			| clear cache(s)
908Lnocache0:
909/* final setup for C code */
910	movw	#PSL_LOWIPL,sr		| lower SPL
911	movl	d7,_boothowto		| save reboot flags
912	movl	d6,_bootdev		|   and boot device
913	jbsr	_main			| call main()
914
915/* proc[1] == init now running here;
916 * create a null exception frame and return to user mode in icode
917 */
918#if defined(LUNA2)
919	cmpl	#-2,_mmutype		| 68040?
920	jne	Lnoflush		| no, skip
921	.word	0xf478			| cpusha dc
922	.word	0xf498			| cinva ic
923Lnoflush:
924#endif
925	clrw	sp@-			| vector offset/frame type
926	clrl	sp@-			| return to icode location 0
927	movw	#PSL_USER,sp@-		| in user mode
928	rte
929
930/*
931 * Signal "trampoline" code (18 bytes).  Invoked from RTE setup by sendsig().
932 *
933 * Stack looks like:
934 *
935 *	sp+0 ->	signal number
936 *	sp+4	signal specific code
937 *	sp+8	pointer to signal context frame (scp)
938 *	sp+12	address of handler
939 *	sp+16	saved hardware state
940 *			.
941 *			.
942 *	scp+0->	beginning of signal context frame
943 */
944	.globl	_sigcode, _esigcode, _sigcodetrap
945	.data
946_sigcode:
947	movl	sp@(12),a0		| signal handler addr	(4 bytes)
948	jsr	a0@			| call signal handler	(2 bytes)
949	addql	#4,sp			| pop signo		(2 bytes)
950_sigcodetrap:
951	trap	#1			| special syscall entry	(2 bytes)
952	movl	d0,sp@(4)		| save errno		(4 bytes)
953	moveq	#1,d0			| syscall == exit	(2 bytes)
954	trap	#0			| exit(errno)		(2 bytes)
955	.align	2
956_esigcode:
957
958/*
959 * Icode is copied out to process 1 to exec init.
960 * If the exec fails, process 1 exits.
961 */
962	.globl	_icode,_szicode
963	.text
964_icode:
965	clrl	sp@-
966	pea	pc@((argv-.)+2)
967	pea	pc@((init-.)+2)
968	clrl	sp@-
969	moveq	#SYS_execve,d0
970	trap	#0
971	moveq	#SYS_exit,d0
972	trap	#0
973init:
974	.asciz	"/sbin/init"
975	.even
976argv:
977	.long	init+6-_icode		| argv[0] = "init" ("/sbin/init" + 6)
978	.long	eicode-_icode		| argv[1] follows icode after copyout
979	.long	0
980eicode:
981
982_szicode:
983	.long	_szicode-_icode
984
985/*
986 * Primitives
987 */
988
989#ifdef __STDC__
990#define EXPORT(name)	.globl _ ## name; _ ## name:
991#else
992#define EXPORT(name)	.globl _/**/name; _/**/name:
993#endif
994#ifdef GPROF
995#define	ENTRY(name) \
996	EXPORT(name) link a6,\#0; jbsr mcount; unlk a6
997#define ALTENTRY(name, rname) \
998	ENTRY(name); jra rname+12
999#else
1000#define	ENTRY(name) \
1001	EXPORT(name)
1002#define ALTENTRY(name, rname) \
1003	ENTRY(name)
1004#endif
1005
1006/*
1007 * For gcc2
1008 */
1009ENTRY(__main)
1010	rts
1011
1012/*
1013 * copyinstr(fromaddr, toaddr, maxlength, &lencopied)
1014 *
1015 * Copy a null terminated string from the user address space into
1016 * the kernel address space.
1017 * NOTE: maxlength must be < 64K
1018 */
1019ENTRY(copyinstr)
1020	movl	_curpcb,a0		| current pcb
1021	movl	#Lcisflt1,a0@(PCB_ONFAULT) | set up to catch faults
1022	movl	sp@(4),a0		| a0 = fromaddr
1023	movl	sp@(8),a1		| a1 = toaddr
1024	moveq	#0,d0
1025	movw	sp@(14),d0		| d0 = maxlength
1026	jlt	Lcisflt1		| negative count, error
1027	jeq	Lcisdone		| zero count, all done
1028	subql	#1,d0			| set up for dbeq
1029Lcisloop:
1030	movsb	a0@+,d1			| grab a byte
1031	nop
1032	movb	d1,a1@+			| copy it
1033	dbeq	d0,Lcisloop		| if !null and more, continue
1034	jne	Lcisflt2		| ran out of room, error
1035	moveq	#0,d0			| got a null, all done
1036Lcisdone:
1037	tstl	sp@(16)			| return length desired?
1038	jeq	Lcisret			| no, just return
1039	subl	sp@(4),a0		| determine how much was copied
1040	movl	sp@(16),a1		| return location
1041	movl	a0,a1@			| stash it
1042Lcisret:
1043	movl	_curpcb,a0		| current pcb
1044	clrl	a0@(PCB_ONFAULT) 	| clear fault addr
1045	rts
1046Lcisflt1:
1047	moveq	#EFAULT,d0		| copy fault
1048	jra	Lcisdone
1049Lcisflt2:
1050	moveq	#ENAMETOOLONG,d0	| ran out of space
1051	jra	Lcisdone
1052
1053/*
1054 * copyoutstr(fromaddr, toaddr, maxlength, &lencopied)
1055 *
1056 * Copy a null terminated string from the kernel
1057 * address space to the user address space.
1058 * NOTE: maxlength must be < 64K
1059 */
1060ENTRY(copyoutstr)
1061	movl	_curpcb,a0		| current pcb
1062	movl	#Lcosflt1,a0@(PCB_ONFAULT) | set up to catch faults
1063	movl	sp@(4),a0		| a0 = fromaddr
1064	movl	sp@(8),a1		| a1 = toaddr
1065	moveq	#0,d0
1066	movw	sp@(14),d0		| d0 = maxlength
1067	jlt	Lcosflt1		| negative count, error
1068	jeq	Lcosdone		| zero count, all done
1069	subql	#1,d0			| set up for dbeq
1070Lcosloop:
1071	movb	a0@+,d1			| grab a byte
1072	movsb	d1,a1@+			| copy it
1073	nop
1074	dbeq	d0,Lcosloop		| if !null and more, continue
1075	jne	Lcosflt2		| ran out of room, error
1076	moveq	#0,d0			| got a null, all done
1077Lcosdone:
1078	tstl	sp@(16)			| return length desired?
1079	jeq	Lcosret			| no, just return
1080	subl	sp@(4),a0		| determine how much was copied
1081	movl	sp@(16),a1		| return location
1082	movl	a0,a1@			| stash it
1083Lcosret:
1084	movl	_curpcb,a0		| current pcb
1085	clrl	a0@(PCB_ONFAULT) 	| clear fault addr
1086	rts
1087Lcosflt1:
1088	moveq	#EFAULT,d0		| copy fault
1089	jra	Lcosdone
1090Lcosflt2:
1091	moveq	#ENAMETOOLONG,d0	| ran out of space
1092	jra	Lcosdone
1093
1094/*
1095 * copystr(fromaddr, toaddr, maxlength, &lencopied)
1096 *
1097 * Copy a null terminated string from one point to another in
1098 * the kernel address space.
1099 * NOTE: maxlength must be < 64K
1100 */
1101ENTRY(copystr)
1102	movl	sp@(4),a0		| a0 = fromaddr
1103	movl	sp@(8),a1		| a1 = toaddr
1104	moveq	#0,d0
1105	movw	sp@(14),d0		| d0 = maxlength
1106	jlt	Lcsflt1			| negative count, error
1107	jeq	Lcsdone			| zero count, all done
1108	subql	#1,d0			| set up for dbeq
1109Lcsloop:
1110	movb	a0@+,a1@+		| copy a byte
1111	dbeq	d0,Lcsloop		| if !null and more, continue
1112	jne	Lcsflt2			| ran out of room, error
1113	moveq	#0,d0			| got a null, all done
1114Lcsdone:
1115	tstl	sp@(16)			| return length desired?
1116	jeq	Lcsret			| no, just return
1117	subl	sp@(4),a0		| determine how much was copied
1118	movl	sp@(16),a1		| return location
1119	movl	a0,a1@			| stash it
1120Lcsret:
1121	rts
1122Lcsflt1:
1123	moveq	#EFAULT,d0		| copy fault
1124	jra	Lcsdone
1125Lcsflt2:
1126	moveq	#ENAMETOOLONG,d0	| ran out of space
1127	jra	Lcsdone
1128
1129/*
1130 * Copyin(from_user, to_kernel, len)
1131 * Copyout(from_kernel, to_user, len)
1132 *
1133 * Copy specified amount of data between kernel and user space.
1134 *
1135 * XXX both use the DBcc instruction which has 16-bit limitation so only
1136 * 64k units can be copied, where "unit" is either a byte or a longword
1137 * depending on alignment.  To be safe, assume it can copy at most
1138 * 64k bytes.  Don't make MAXBSIZE or MAXPHYS larger than 64k without
1139 * fixing this code!
1140 */
1141ENTRY(copyin)
1142	movl	d2,sp@-			| scratch register
1143	movl	_curpcb,a0		| current pcb
1144	movl	#Lciflt,a0@(PCB_ONFAULT) | set up to catch faults
1145	movl	sp@(16),d2		| check count
1146	jlt	Lciflt			| negative, error
1147	jeq	Lcidone			| zero, done
1148	movl	sp@(8),a0		| src address
1149	movl	sp@(12),a1		| dest address
1150	movl	a0,d0
1151	btst	#0,d0			| src address odd?
1152	jeq	Lcieven			| no, go check dest
1153	movsb	a0@+,d1			| yes, get a byte
1154	nop
1155	movb	d1,a1@+			| put a byte
1156	subql	#1,d2			| adjust count
1157	jeq	Lcidone			| exit if done
1158Lcieven:
1159	movl	a1,d0
1160	btst	#0,d0			| dest address odd?
1161	jne	Lcibyte			| yes, must copy by bytes
1162	movl	d2,d0			| no, get count
1163	lsrl	#2,d0			| convert to longwords
1164	jeq	Lcibyte			| no longwords, copy bytes
1165	subql	#1,d0			| set up for dbf
1166Lcilloop:
1167	movsl	a0@+,d1			| get a long
1168	nop
1169	movl	d1,a1@+			| put a long
1170	dbf	d0,Lcilloop		| til done
1171	andl	#3,d2			| what remains
1172	jeq	Lcidone			| all done
1173Lcibyte:
1174	subql	#1,d2			| set up for dbf
1175Lcibloop:
1176	movsb	a0@+,d1			| get a byte
1177	nop
1178	movb	d1,a1@+			| put a byte
1179	dbf	d2,Lcibloop		| til done
1180Lcidone:
1181	moveq	#0,d0			| success
1182Lciexit:
1183	movl	_curpcb,a0		| current pcb
1184	clrl	a0@(PCB_ONFAULT) 	| clear fault catcher
1185	movl	sp@+,d2			| restore scratch reg
1186	rts
1187Lciflt:
1188	moveq	#EFAULT,d0		| got a fault
1189	jra	Lciexit
1190
1191ENTRY(copyout)
1192	movl	d2,sp@-			| scratch register
1193	movl	_curpcb,a0		| current pcb
1194	movl	#Lcoflt,a0@(PCB_ONFAULT) | catch faults
1195	movl	sp@(16),d2		| check count
1196	jlt	Lcoflt			| negative, error
1197	jeq	Lcodone			| zero, done
1198	movl	sp@(8),a0		| src address
1199	movl	sp@(12),a1		| dest address
1200	movl	a0,d0
1201	btst	#0,d0			| src address odd?
1202	jeq	Lcoeven			| no, go check dest
1203	movb	a0@+,d1			| yes, get a byte
1204	movsb	d1,a1@+			| put a byte
1205	nop
1206	subql	#1,d2			| adjust count
1207	jeq	Lcodone			| exit if done
1208Lcoeven:
1209	movl	a1,d0
1210	btst	#0,d0			| dest address odd?
1211	jne	Lcobyte			| yes, must copy by bytes
1212	movl	d2,d0			| no, get count
1213	lsrl	#2,d0			| convert to longwords
1214	jeq	Lcobyte			| no longwords, copy bytes
1215	subql	#1,d0			| set up for dbf
1216Lcolloop:
1217	movl	a0@+,d1			| get a long
1218	movsl	d1,a1@+			| put a long
1219	nop
1220	dbf	d0,Lcolloop		| til done
1221	andl	#3,d2			| what remains
1222	jeq	Lcodone			| all done
1223Lcobyte:
1224	subql	#1,d2			| set up for dbf
1225Lcobloop:
1226	movb	a0@+,d1			| get a byte
1227	movsb	d1,a1@+			| put a byte
1228	nop
1229	dbf	d2,Lcobloop		| til done
1230Lcodone:
1231	moveq	#0,d0			| success
1232Lcoexit:
1233	movl	_curpcb,a0		| current pcb
1234	clrl	a0@(PCB_ONFAULT) 	| clear fault catcher
1235	movl	sp@+,d2			| restore scratch reg
1236	rts
1237Lcoflt:
1238	moveq	#EFAULT,d0		| got a fault
1239	jra	Lcoexit
1240
1241/*
1242 * non-local gotos
1243 */
1244ENTRY(setjmp)
1245	movl	sp@(4),a0	| savearea pointer
1246	moveml	#0xFCFC,a0@	| save d2-d7/a2-a7
1247	movl	sp@,a0@(48)	| and return address
1248	moveq	#0,d0		| return 0
1249	rts
1250
1251ENTRY(longjmp)
1252	movl	sp@(4),a0
1253	moveml	a0@+,#0xFCFC
1254	movl	a0@,sp@
1255	moveq	#1,d0
1256	rts
1257
1258/*
1259 * The following primitives manipulate the run queues.
1260 * _whichqs tells which of the 32 queues _qs
1261 * have processes in them.  Setrq puts processes into queues, Remrq
1262 * removes them from queues.  The running process is on no queue,
1263 * other processes are on a queue related to p->p_pri, divided by 4
1264 * actually to shrink the 0-127 range of priorities into the 32 available
1265 * queues.
1266 */
1267
1268	.globl	_whichqs,_qs,_cnt,_panic
1269	.globl	_curproc,_want_resched
1270
1271/*
1272 * Setrq(p)
1273 *
1274 * Call should be made at spl6(), and p->p_stat should be SRUN
1275 */
1276ENTRY(setrq)
1277	movl	sp@(4),a0
1278	tstl	a0@(P_RLINK)
1279	jeq	Lset1
1280	movl	#Lset2,sp@-
1281	jbsr	_panic
1282Lset1:
1283	clrl	d0
1284	movb	a0@(P_PRI),d0
1285	lsrb	#2,d0
1286	movl	_whichqs,d1
1287	bset	d0,d1
1288	movl	d1,_whichqs
1289	lslb	#3,d0
1290	addl	#_qs,d0
1291	movl	d0,a0@(P_LINK)
1292	movl	d0,a1
1293	movl	a1@(P_RLINK),a0@(P_RLINK)
1294	movl	a0,a1@(P_RLINK)
1295	movl	a0@(P_RLINK),a1
1296	movl	a0,a1@(P_LINK)
1297	rts
1298
1299Lset2:
1300	.asciz	"setrq"
1301	.even
1302
1303/*
1304 * Remrq(p)
1305 *
1306 * Call should be made at spl6().
1307 */
1308ENTRY(remrq)
1309	movl	sp@(4),a0
1310	clrl	d0
1311	movb	a0@(P_PRI),d0
1312	lsrb	#2,d0
1313	movl	_whichqs,d1
1314	bclr	d0,d1
1315	jne	Lrem1
1316	movl	#Lrem3,sp@-
1317	jbsr	_panic
1318Lrem1:
1319	movl	d1,_whichqs
1320	movl	a0@(P_LINK),a1
1321	movl	a0@(P_RLINK),a1@(P_RLINK)
1322	movl	a0@(P_RLINK),a1
1323	movl	a0@(P_LINK),a1@(P_LINK)
1324	movl	#_qs,a1
1325	movl	d0,d1
1326	lslb	#3,d1
1327	addl	d1,a1
1328	cmpl	a1@(P_LINK),a1
1329	jeq	Lrem2
1330	movl	_whichqs,d1
1331	bset	d0,d1
1332	movl	d1,_whichqs
1333Lrem2:
1334	clrl	a0@(P_RLINK)
1335	rts
1336
1337Lrem3:
1338	.asciz	"remrq"
1339Lsw0:
1340	.asciz	"swtch"
1341	.even
1342
1343	.globl	_curpcb
1344	.globl	_masterpaddr	| XXX compatibility (debuggers)
1345	.data
1346_masterpaddr:			| XXX compatibility (debuggers)
1347_curpcb:
1348	.long	0
1349mdpflag:
1350	.byte	0		| copy of proc md_flags low byte
1351	.align	2
1352	.comm	nullpcb,SIZEOF_PCB
1353	.text
1354
1355/*
1356 * At exit of a process, do a swtch for the last time.
1357 * The mapping of the pcb at p->p_addr has already been deleted,
1358 * and the memory for the pcb+stack has been freed.
1359 * The ipl is high enough to prevent the memory from being reallocated.
1360 */
1361ENTRY(swtch_exit)
1362	movl	#nullpcb,_curpcb	| save state into garbage pcb
1363	lea	tmpstk,sp		| goto a tmp stack
1364	jra	_cpu_swtch
1365
1366/*
1367 * When no processes are on the runq, Swtch branches to idle
1368 * to wait for something to come ready.
1369 */
1370	.globl	idle
1371Lidle:
1372	stop	#PSL_LOWIPL
1373idle:
1374	movw	#PSL_HIGHIPL,sr
1375	tstl	_whichqs
1376	jeq	Lidle
1377	movw	#PSL_LOWIPL,sr
1378	jra	Lsw1
1379
1380Lbadsw:
1381	movl	#Lsw0,sp@-
1382	jbsr	_panic
1383	/*NOTREACHED*/
1384
1385/*
1386 * cpu_swtch()
1387 *
1388 * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the
1389 * entire ATC.  The effort involved in selective flushing may not be
1390 * worth it, maybe we should just flush the whole thing?
1391 *
1392 * NOTE 2: With the new VM layout we now no longer know if an inactive
1393 * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag
1394 * bit).  For now, we just always flush the full ATC.
1395 */
1396ENTRY(cpu_swtch)
1397	movl	_curpcb,a0		| current pcb
1398	movw	sr,a0@(PCB_PS)		| save sr before changing ipl
1399#ifdef notyet
1400	movl	_curproc,sp@-		| remember last proc running
1401#endif
1402	clrl	_curproc
1403	addql	#1,_cnt+V_SWTCH
1404
1405Lsw1:
1406	/*
1407	 * Find the highest-priority queue that isn't empty,
1408	 * then take the first proc from that queue.
1409	 */
1410	clrl	d0
1411	lea	_whichqs,a0
1412	movl	a0@,d1
1413Lswchk:
1414	btst	d0,d1
1415	jne	Lswfnd
1416	addqb	#1,d0
1417	cmpb	#32,d0
1418	jne	Lswchk
1419	jra	idle
1420Lswfnd:
1421	movw	#PSL_HIGHIPL,sr		| lock out interrupts
1422	movl	a0@,d1			| and check again...
1423	bclr	d0,d1
1424	jeq	Lsw1			| proc moved, rescan
1425	movl	d1,a0@			| update whichqs
1426	moveq	#1,d1			| double check for higher priority
1427	lsll	d0,d1			| process (which may have snuck in
1428	subql	#1,d1			| while we were finding this one)
1429	andl	a0@,d1
1430	jeq	Lswok			| no one got in, continue
1431	movl	a0@,d1
1432	bset	d0,d1			| otherwise put this one back
1433	movl	d1,a0@
1434	jra	Lsw1			| and rescan
1435Lswok:
1436	movl	d0,d1
1437	lslb	#3,d1			| convert queue number to index
1438	addl	#_qs,d1			| locate queue (q)
1439	movl	d1,a1
1440	cmpl	a1@(P_LINK),a1		| anyone on queue?
1441	jeq	Lbadsw			| no, panic
1442	movl	a1@(P_LINK),a0			| p = q->p_link
1443	movl	a0@(P_LINK),a1@(P_LINK)		| q->p_link = p->p_link
1444	movl	a0@(P_LINK),a1			| q = p->p_link
1445	movl	a0@(P_RLINK),a1@(P_RLINK)	| q->p_rlink = p->p_rlink
1446	cmpl	a0@(P_LINK),d1		| anyone left on queue?
1447	jeq	Lsw2			| no, skip
1448	movl	_whichqs,d1
1449	bset	d0,d1			| yes, reset bit
1450	movl	d1,_whichqs
1451Lsw2:
1452	movl	a0,_curproc
1453	clrl	_want_resched
1454#ifdef notyet
1455	movl	sp@+,a1
1456	cmpl	a0,a1			| switching to same proc?
1457	jeq	Lswdone			| yes, skip save and restore
1458#endif
1459	/*
1460	 * Save state of previous process in its pcb.
1461	 */
1462	movl	_curpcb,a1
1463	moveml	#0xFCFC,a1@(PCB_REGS)	| save non-scratch registers
1464	movl	usp,a2			| grab USP (a2 has been saved)
1465	movl	a2,a1@(PCB_USP)		| and save it
1466#ifdef FPCOPROC
1467	lea	a1@(PCB_FPCTX),a2	| pointer to FP save area
1468	fsave	a2@			| save FP state
1469	tstb	a2@			| null state frame?
1470	jeq	Lswnofpsave		| yes, all done
1471	fmovem	fp0-fp7,a2@(216)	| save FP general registers
1472	fmovem	fpcr/fpsr/fpi,a2@(312)	| save FP control registers
1473Lswnofpsave:
1474#endif
1475
1476#ifdef DIAGNOSTIC
1477	tstl	a0@(P_WCHAN)
1478	jne	Lbadsw
1479	cmpb	#SRUN,a0@(P_STAT)
1480	jne	Lbadsw
1481#endif
1482	clrl	a0@(P_RLINK)		| clear back link
1483	movb	a0@(P_MDFLAG+3),mdpflag	| low byte of p_md.md_flags
1484	movl	a0@(P_ADDR),a1		| get p_addr
1485	movl	a1,_curpcb
1486
1487	/* see if pmap_activate needs to be called; should remove this */
1488	movl	a0@(P_VMSPACE),a0	| vmspace = p->p_vmspace
1489#ifdef DIAGNOSTIC
1490	tstl	a0			| map == VM_MAP_NULL?
1491	jeq	Lbadsw			| panic
1492#endif
1493	lea	a0@(VM_PMAP),a0		| pmap = &vmspace.vm_pmap
1494	tstl	a0@(PM_STCHG)		| pmap->st_changed?
1495	jeq	Lswnochg		| no, skip
1496	pea	a1@			| push pcb (at p_addr)
1497	pea	a0@			| push pmap
1498	jbsr	_pmap_activate		| pmap_activate(pmap, pcb)
1499	addql	#8,sp
1500	movl	_curpcb,a1		| restore p_addr
1501Lswnochg:
1502
1503	movl	#PGSHIFT,d1
1504	movl	a1,d0
1505	lsrl	d1,d0			| convert p_addr to page number
1506	lsll	#2,d0			| and now to Sysmap offset
1507	addl	_Sysmap,d0		| add Sysmap base to get PTE addr
1508#ifdef notdef
1509	movw	#PSL_HIGHIPL,sr		| go crit while changing PTEs
1510#endif
1511	lea	tmpstk,sp		| now goto a tmp stack for NMI
1512	movl	d0,a0			| address of new context
1513	movl	_Umap,a2		| address of PTEs for kstack
1514	moveq	#UPAGES-1,d0		| sizeof kstack
1515Lres1:
1516	movl	a0@+,d1			| get PTE
1517	andl	#~PG_PROT,d1		| mask out old protection
1518	orl	#PG_RW+PG_V,d1		| ensure valid and writable
1519	movl	d1,a2@+			| load it up
1520	dbf	d0,Lres1		| til done
1521#if defined(LUNA2)
1522	cmpl	#-2,_mmutype		| 68040?
1523	jne	Lres1a			| no, skip
1524	.word	0xf518			| yes, pflusha
1525	movl	a1@(PCB_USTP),d0	| get USTP
1526	moveq	#PGSHIFT,d1
1527	lsll	d1,d0			| convert to addr
1528	.long	0x4e7b0806		| movc d0,urp
1529	jra	Lcxswdone
1530Lres1a:
1531#endif
1532	movl	#CACHE_CLR,d0
1533	movc	d0,cacr			| invalidate cache(s)
1534	pflusha				| flush entire TLB
1535	movl	a1@(PCB_USTP),d0	| get USTP
1536	moveq	#PGSHIFT,d1
1537	lsll	d1,d0			| convert to addr
1538	lea	_protorp,a0		| CRP prototype
1539	movl	d0,a0@(4)		| stash USTP
1540	pmove	a0@,crp			| load new user root pointer
1541Lcxswdone:
1542	moveml	a1@(PCB_REGS),#0xFCFC	| and registers
1543	movl	a1@(PCB_USP),a0
1544	movl	a0,usp			| and USP
1545#ifdef FPCOPROC
1546	lea	a1@(PCB_FPCTX),a0	| pointer to FP save area
1547	tstb	a0@			| null state frame?
1548	jeq	Lresfprest		| yes, easy
1549#if defined(LUNA2)
1550	cmpl	#-2,_mmutype		| 68040?
1551	jne	Lresnot040		| no, skip
1552	clrl	sp@-			| yes...
1553	frestore sp@+			| ...magic!
1554Lresnot040:
1555#endif
1556	fmovem	a0@(312),fpcr/fpsr/fpi	| restore FP control registers
1557	fmovem	a0@(216),fp0-fp7	| restore FP general registers
1558Lresfprest:
1559	frestore a0@			| restore state
1560#endif
1561	movw	a1@(PCB_PS),sr		| no, restore PS
1562	moveq	#1,d0			| return 1 (for alternate returns)
1563	rts
1564
1565/*
1566 * savectx(pcb, altreturn)
1567 * Update pcb, saving current processor state and arranging
1568 * for alternate return ala longjmp in swtch if altreturn is true.
1569 */
1570ENTRY(savectx)
1571	movl	sp@(4),a1
1572	movw	sr,a1@(PCB_PS)
1573	movl	usp,a0			| grab USP
1574	movl	a0,a1@(PCB_USP)		| and save it
1575	moveml	#0xFCFC,a1@(PCB_REGS)	| save non-scratch registers
1576#ifdef FPCOPROC
1577	lea	a1@(PCB_FPCTX),a0	| pointer to FP save area
1578	fsave	a0@			| save FP state
1579	tstb	a0@			| null state frame?
1580	jeq	Lsvnofpsave		| yes, all done
1581	fmovem	fp0-fp7,a0@(216)	| save FP general registers
1582	fmovem	fpcr/fpsr/fpi,a0@(312)	| save FP control registers
1583Lsvnofpsave:
1584#endif
1585	tstl	sp@(8)			| altreturn?
1586	jeq	Lsavedone
1587	movl	sp,d0			| relocate current sp relative to a1
1588	subl	#_kstack,d0		|   (sp is relative to kstack):
1589	addl	d0,a1			|   a1 += sp - kstack;
1590	movl	sp@,a1@			| write return pc at (relocated) sp@
1591Lsavedone:
1592	moveq	#0,d0			| return 0
1593	rts
1594
1595/*
1596 * {fu,su},{byte,sword,word}
1597 */
1598ALTENTRY(fuiword, _fuword)
1599ENTRY(fuword)
1600	movl	sp@(4),a0		| address to read
1601	movl	_curpcb,a1		| current pcb
1602	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
1603	movsl	a0@,d0			| do read from user space
1604	nop
1605	jra	Lfsdone
1606
1607ENTRY(fusword)
1608	movl	sp@(4),a0
1609	movl	_curpcb,a1		| current pcb
1610	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
1611	moveq	#0,d0
1612	movsw	a0@,d0			| do read from user space
1613	nop
1614	jra	Lfsdone
1615
1616/* Just like fusword, but tells trap code not to page in. */
1617ENTRY(fuswintr)
1618	movl	sp@(4),a0
1619	movl	_curpcb,a1
1620	movl	#_fswintr,a1@(PCB_ONFAULT)
1621	moveq	#0,d0
1622	movsw	a0@,d0
1623	nop
1624	jra	Lfsdone
1625
1626ALTENTRY(fuibyte, _fubyte)
1627ENTRY(fubyte)
1628	movl	sp@(4),a0		| address to read
1629	movl	_curpcb,a1		| current pcb
1630	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
1631	moveq	#0,d0
1632	movsb	a0@,d0			| do read from user space
1633	nop
1634	jra	Lfsdone
1635
1636Lfserr:
1637	moveq	#-1,d0			| error indicator
1638Lfsdone:
1639	clrl	a1@(PCB_ONFAULT) 	| clear fault address
1640	rts
1641
1642/* Just like Lfserr, but the address is different (& exported). */
1643	.globl	_fswintr
1644_fswintr:
1645	moveq	#-1,d0
1646	jra	Lfsdone
1647
1648
1649/*
1650 * Write a longword in user instruction space.
1651 * Largely the same as suword but with a final i-cache purge on those
1652 * machines with split caches.
1653 */
1654ENTRY(suiword)
1655	movl	sp@(4),a0		| address to write
1656	movl	sp@(8),d0		| value to put there
1657	movl	_curpcb,a1		| current pcb
1658	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
1659	movsl	d0,a0@			| do write to user space
1660	nop
1661	moveq	#0,d0			| indicate no fault
1662#if defined(LUNA2)
1663	cmpl	#-2,_mmutype		| 68040?
1664	jne	Lsuicpurge		| no, skip
1665	.word	0xf498			| cinva ic (XXX overkill)
1666	jra	Lfsdone
1667Lsuicpurge:
1668#endif
1669	movl	#IC_CLEAR,d1
1670	movc	d1,cacr			| invalidate i-cache
1671	jra	Lfsdone
1672
1673ENTRY(suword)
1674	movl	sp@(4),a0		| address to write
1675	movl	sp@(8),d0		| value to put there
1676	movl	_curpcb,a1		| current pcb
1677	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
1678	movsl	d0,a0@			| do write to user space
1679	nop
1680	moveq	#0,d0			| indicate no fault
1681	jra	Lfsdone
1682
1683ENTRY(susword)
1684	movl	sp@(4),a0		| address to write
1685	movw	sp@(10),d0		| value to put there
1686	movl	_curpcb,a1		| current pcb
1687	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
1688	movsw	d0,a0@			| do write to user space
1689	nop
1690	moveq	#0,d0			| indicate no fault
1691	jra	Lfsdone
1692
1693ENTRY(suswintr)
1694	movl	sp@(4),a0
1695	movw	sp@(10),d0
1696	movl	_curpcb,a1
1697	movl	#_fswintr,a1@(PCB_ONFAULT)
1698	movsw	d0,a0@
1699	nop
1700	moveq	#0,d0
1701	jra	Lfsdone
1702
1703ALTENTRY(suibyte, _subyte)
1704ENTRY(subyte)
1705	movl	sp@(4),a0		| address to write
1706	movb	sp@(11),d0		| value to put there
1707	movl	_curpcb,a1		| current pcb
1708	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
1709	movsb	d0,a0@			| do write to user space
1710	nop
1711	moveq	#0,d0			| indicate no fault
1712	jra	Lfsdone
1713
1714#if defined(LUNA2)
1715ENTRY(suline)
1716	movl	sp@(4),a0		| address to write
1717	movl	_curpcb,a1		| current pcb
1718	movl	#Lslerr,a1@(PCB_ONFAULT) | where to return to on a fault
1719	movl	sp@(8),a1		| address of line
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	movl	a1@+,d0			| get lword
1730	movsl	d0,a0@+			| put lword
1731	nop				| sync
1732	moveq	#0,d0			| indicate no fault
1733	jra	Lsldone
1734Lslerr:
1735	moveq	#-1,d0
1736Lsldone:
1737	movl	_curpcb,a1		| current pcb
1738	clrl	a1@(PCB_ONFAULT) 	| clear fault address
1739	rts
1740#endif
1741
1742/*
1743 * Invalidate entire TLB.
1744 */
1745ENTRY(TBIA)
1746__TBIA:
1747#if defined(LUNA2)
1748	cmpl	#-2,_mmutype		| 68040?
1749	jne	Lmotommu3		| no, skip
1750	.word	0xf518			| yes, pflusha
1751	rts
1752Lmotommu3:
1753#endif
1754	pflusha				| flush entire TLB
1755	movl	#DC_CLEAR,d0
1756	movc	d0,cacr			| invalidate on-chip d-cache
1757	rts
1758
1759/*
1760 * Invalidate any TLB entry for given VA (TB Invalidate Single)
1761 */
1762ENTRY(TBIS)
1763#ifdef DEBUG
1764	tstl	fulltflush		| being conservative?
1765	jne	__TBIA			| yes, flush entire TLB
1766#endif
1767#if defined(LUNA2)
1768	cmpl	#-2,_mmutype		| 68040?
1769	jne	Lmotommu4		| no, skip
1770	movl	sp@(4),a0
1771	movc	dfc,d1
1772	moveq	#1,d0			| user space
1773	movc	d0,dfc
1774	.word	0xf508			| pflush a0@
1775	moveq	#5,d0			| super space
1776	movc	d0,dfc
1777	.word	0xf508			| pflush a0@
1778	movc	d1,dfc
1779	rts
1780Lmotommu4:
1781#endif
1782
1783	movl	sp@(4),a0		| get addr to flush
1784	pflush	#0,#0,a0@		| flush address from both sides
1785	movl	#DC_CLEAR,d0
1786	movc	d0,cacr			| invalidate on-chip data cache
1787	rts
1788
1789/*
1790 * Invalidate supervisor side of TLB
1791 */
1792ENTRY(TBIAS)
1793#ifdef DEBUG
1794	tstl	fulltflush		| being conservative?
1795	jne	__TBIA			| yes, flush everything
1796#endif
1797#if defined(LUNA2)
1798	cmpl	#-2,_mmutype		| 68040?
1799	jne	Lmotommu5		| no, skip
1800	.word	0xf518			| yes, pflusha (for now) XXX
1801	rts
1802Lmotommu5:
1803#endif
1804	pflush #4,#4			| flush supervisor TLB entries
1805	movl	#DC_CLEAR,d0
1806	movc	d0,cacr			| invalidate on-chip d-cache
1807	rts
1808
1809/*
1810 * Invalidate user side of TLB
1811 */
1812ENTRY(TBIAU)
1813#ifdef DEBUG
1814	tstl	fulltflush		| being conservative?
1815	jne	__TBIA			| yes, flush everything
1816#endif
1817#if defined(LUNA2)
1818	cmpl	#-2,_mmutype		| 68040?
1819	jne	Lmotommu6		| no, skip
1820	.word	0xf518			| yes, pflusha (for now) XXX
1821	rts
1822Lmotommu6:
1823#endif
1824	pflush	#0,#4			| flush user TLB entries
1825	movl	#DC_CLEAR,d0
1826	movc	d0,cacr			| invalidate on-chip d-cache
1827	rts
1828
1829/*
1830 * Invalidate instruction cache
1831 */
1832ENTRY(ICIA)
1833#if defined(LUNA2)
1834ENTRY(ICPA)
1835	cmpl	#-2,_mmutype		| 68040
1836	jne	Lmotommu7		| no, skip
1837	.word	0xf498			| cinva ic
1838	rts
1839Lmotommu7:
1840#endif
1841	movl	#IC_CLEAR,d0
1842	movc	d0,cacr			| invalidate i-cache
1843	rts
1844
1845/*
1846 * Invalidate data cache.
1847 * NOTE: we do not flush 68030 on-chip cache as there are no aliasing
1848 * problems with DC_WA.  The only cases we have to worry about are context
1849 * switch and TLB changes, both of which are handled "in-line" in resume
1850 * and TBI*.
1851 */
1852ENTRY(DCIA)
1853__DCIA:
1854#if defined(LUNA2)
1855	cmpl	#-2,_mmutype		| 68040
1856	jne	Lmotommu8		| no, skip
1857	/* XXX implement */
1858	rts
1859Lmotommu8:
1860#endif
1861	rts
1862
1863ENTRY(DCIS)
1864__DCIS:
1865#if defined(LUNA2)
1866	cmpl	#-2,_mmutype		| 68040
1867	jne	Lmotommu9		| no, skip
1868	/* XXX implement */
1869	rts
1870Lmotommu9:
1871#endif
1872	rts
1873
1874ENTRY(DCIU)
1875__DCIU:
1876#if defined(LUNA2)
1877	cmpl	#-2,_mmutype		| 68040
1878	jne	LmotommuA		| no, skip
1879	/* XXX implement */
1880	rts
1881LmotommuA:
1882#endif
1883	rts
1884
1885#if defined(LUNA2)
1886ENTRY(ICPL)
1887	movl	sp@(4),a0		| address
1888	.word	0xf488			| cinvl ic,a0@
1889	rts
1890ENTRY(ICPP)
1891	movl	sp@(4),a0		| address
1892	.word	0xf490			| cinvp ic,a0@
1893	rts
1894ENTRY(DCPL)
1895	movl	sp@(4),a0		| address
1896	.word	0xf448			| cinvl dc,a0@
1897	rts
1898ENTRY(DCPP)
1899	movl	sp@(4),a0		| address
1900	.word	0xf450			| cinvp dc,a0@
1901	rts
1902ENTRY(DCPA)
1903	.word	0xf458			| cinva dc
1904	rts
1905ENTRY(DCFL)
1906	movl	sp@(4),a0		| address
1907	.word	0xf468			| cpushl dc,a0@
1908	rts
1909ENTRY(DCFP)
1910	movl	sp@(4),a0		| address
1911	.word	0xf470			| cpushp dc,a0@
1912	rts
1913#endif
1914
1915ENTRY(PCIA)
1916#if defined(LUNA2)
1917ENTRY(DCFA)
1918	cmpl	#-2,_mmutype		| 68040
1919	jne	LmotommuB		| no, skip
1920	.word	0xf478			| cpusha dc
1921	rts
1922LmotommuB:
1923#endif
1924	movl	#DC_CLEAR,d0
1925	movc	d0,cacr			| invalidate on-chip d-cache
1926	rts
1927
1928#if 0 /****************************************************************/
1929/* external cache control */
1930ENTRY(ecacheon)
1931	rts
1932
1933ENTRY(ecacheoff)
1934	rts
1935#endif /****************************************************************/
1936
1937/*
1938 * Get callers current SP value.
1939 * Note that simply taking the address of a local variable in a C function
1940
1941 * doesn't work because callee saved registers may be outside the stack frame
1942 * defined by A6 (e.g. GCC generated code).
1943 */
1944	.globl	_getsp
1945_getsp:
1946	movl	sp,d0			| get current SP
1947	addql	#4,d0			| compensate for return address
1948	rts
1949
1950	.globl	_getsfc, _getdfc
1951_getsfc:
1952	movc	sfc,d0
1953	rts
1954_getdfc:
1955	movc	dfc,d0
1956	rts
1957
1958/*
1959 * Load a new user segment table pointer.
1960 */
1961ENTRY(loadustp)
1962	movl	sp@(4),d0		| new USTP
1963	moveq	#PGSHIFT,d1
1964	lsll	d1,d0			| convert to addr
1965#if defined(LUNA2)
1966	cmpl	#-2,_mmutype		| 68040?
1967	jne	LmotommuC		| no, skip
1968	.long	0x4e7b0806		| movc d0,urp
1969	rts
1970LmotommuC:
1971#endif
1972	lea	_protorp,a0		| CRP prototype
1973	movl	d0,a0@(4)		| stash USTP
1974	pmove	a0@,crp			| load root pointer
1975	movl	#DC_CLEAR,d0
1976	movc	d0,cacr			| invalidate on-chip d-cache
1977	rts
1978
1979ENTRY(ploadw)
1980	movl	sp@(4),a0		| address to load
1981	ploadw	#1,a0@			| pre-load translation
1982	rts
1983
1984/*
1985 * Set processor priority level calls.  Most are implemented with
1986 * inline asm expansions.  However, spl0 requires special handling
1987 * as we need to check for our emulated software interrupts.
1988 */
1989
1990ENTRY(spl0)
1991	moveq	#0,d0
1992	movw	sr,d0			| get old SR for return
1993	movw	#PSL_LOWIPL,sr		| restore new SR
1994	tstb	_ssir			| software interrupt pending?
1995	jeq	Lspldone		| no, all done
1996	subql	#4,sp			| make room for RTE frame
1997	movl	sp@(4),sp@(2)		| position return address
1998	clrw	sp@(6)			| set frame type 0
1999	movw	#PSL_LOWIPL,sp@		| and new SR
2000	jra	Lgotsir			| go handle it
2001Lspldone:
2002	rts
2003
2004ENTRY(_insque)
2005	movw	sr,d0
2006	movw	#PSL_HIGHIPL,sr		| atomic
2007	movl	sp@(8),a0		| where to insert (after)
2008	movl	sp@(4),a1		| element to insert (e)
2009	movl	a0@,a1@			| e->next = after->next
2010	movl	a0,a1@(4)		| e->prev = after
2011	movl	a1,a0@			| after->next = e
2012	movl	a1@,a0
2013	movl	a1,a0@(4)		| e->next->prev = e
2014	movw	d0,sr
2015	rts
2016
2017ENTRY(_remque)
2018	movw	sr,d0
2019	movw	#PSL_HIGHIPL,sr		| atomic
2020	movl	sp@(4),a0		| element to remove (e)
2021	movl	a0@,a1
2022	movl	a0@(4),a0
2023	movl	a0,a1@(4)		| e->next->prev = e->prev
2024	movl	a1,a0@			| e->prev->next = e->next
2025	movw	d0,sr
2026	rts
2027
2028/*
2029 * bzero(addr, count)
2030 */
2031ALTENTRY(blkclr, _bzero)
2032ENTRY(bzero)
2033	movl	sp@(4),a0	| address
2034	movl	sp@(8),d0	| count
2035	jeq	Lbzdone		| if zero, nothing to do
2036	movl	a0,d1
2037	btst	#0,d1		| address odd?
2038	jeq	Lbzeven		| no, can copy words
2039	clrb	a0@+		| yes, zero byte to get to even boundary
2040	subql	#1,d0		| decrement count
2041	jeq	Lbzdone		| none left, all done
2042Lbzeven:
2043	movl	d0,d1
2044	andl	#31,d0
2045	lsrl	#5,d1		| convert count to 8*longword count
2046	jeq	Lbzbyte		| no such blocks, zero byte at a time
2047Lbzloop:
2048	clrl	a0@+; clrl	a0@+; clrl	a0@+; clrl	a0@+;
2049	clrl	a0@+; clrl	a0@+; clrl	a0@+; clrl	a0@+;
2050	subql	#1,d1		| one more block zeroed
2051	jne	Lbzloop		| more to go, do it
2052	tstl	d0		| partial block left?
2053	jeq	Lbzdone		| no, all done
2054Lbzbyte:
2055	clrb	a0@+
2056	subql	#1,d0		| one more byte cleared
2057	jne	Lbzbyte		| more to go, do it
2058Lbzdone:
2059	rts
2060
2061/*
2062 * strlen(str)
2063 */
2064ENTRY(strlen)
2065	moveq	#-1,d0
2066	movl	sp@(4),a0	| string
2067Lslloop:
2068	addql	#1,d0		| increment count
2069	tstb	a0@+		| null?
2070	jne	Lslloop		| no, keep going
2071	rts
2072
2073/*
2074 * bcmp(s1, s2, len)
2075 *
2076 * WARNING!  This guy only works with counts up to 64K
2077 */
2078ENTRY(bcmp)
2079	movl	sp@(4),a0		| string 1
2080	movl	sp@(8),a1		| string 2
2081	moveq	#0,d0
2082	movw	sp@(14),d0		| length
2083	jeq	Lcmpdone		| if zero, nothing to do
2084	subqw	#1,d0			| set up for DBcc loop
2085Lcmploop:
2086	cmpmb	a0@+,a1@+		| equal?
2087	dbne	d0,Lcmploop		| yes, keep going
2088	addqw	#1,d0			| +1 gives zero on match
2089Lcmpdone:
2090	rts
2091
2092/*
2093 * {ov}bcopy(from, to, len)
2094 *
2095 * Works for counts up to 128K.
2096 */
2097ALTENTRY(ovbcopy, _bcopy)
2098ENTRY(bcopy)
2099	movl	sp@(12),d0		| get count
2100	jeq	Lcpyexit		| if zero, return
2101	movl	sp@(4),a0		| src address
2102	movl	sp@(8),a1		| dest address
2103	cmpl	a1,a0			| src before dest?
2104	jlt	Lcpyback		| yes, copy backwards (avoids overlap)
2105	movl	a0,d1
2106	btst	#0,d1			| src address odd?
2107	jeq	Lcfeven			| no, go check dest
2108	movb	a0@+,a1@+		| yes, copy a byte
2109	subql	#1,d0			| update count
2110	jeq	Lcpyexit		| exit if done
2111Lcfeven:
2112	movl	a1,d1
2113	btst	#0,d1			| dest address odd?
2114	jne	Lcfbyte			| yes, must copy by bytes
2115	movl	d0,d1			| no, get count
2116	lsrl	#2,d1			| convert to longwords
2117	jeq	Lcfbyte			| no longwords, copy bytes
2118	subql	#1,d1			| set up for dbf
2119Lcflloop:
2120	movl	a0@+,a1@+		| copy longwords
2121	dbf	d1,Lcflloop		| til done
2122	andl	#3,d0			| get remaining count
2123	jeq	Lcpyexit		| done if none
2124Lcfbyte:
2125	subql	#1,d0			| set up for dbf
2126Lcfbloop:
2127	movb	a0@+,a1@+		| copy bytes
2128	dbf	d0,Lcfbloop		| til done
2129Lcpyexit:
2130	rts
2131Lcpyback:
2132	addl	d0,a0			| add count to src
2133	addl	d0,a1			| add count to dest
2134	movl	a0,d1
2135	btst	#0,d1			| src address odd?
2136	jeq	Lcbeven			| no, go check dest
2137	movb	a0@-,a1@-		| yes, copy a byte
2138	subql	#1,d0			| update count
2139	jeq	Lcpyexit		| exit if done
2140Lcbeven:
2141	movl	a1,d1
2142	btst	#0,d1			| dest address odd?
2143	jne	Lcbbyte			| yes, must copy by bytes
2144	movl	d0,d1			| no, get count
2145	lsrl	#2,d1			| convert to longwords
2146	jeq	Lcbbyte			| no longwords, copy bytes
2147	subql	#1,d1			| set up for dbf
2148Lcblloop:
2149	movl	a0@-,a1@-		| copy longwords
2150	dbf	d1,Lcblloop		| til done
2151	andl	#3,d0			| get remaining count
2152	jeq	Lcpyexit		| done if none
2153Lcbbyte:
2154	subql	#1,d0			| set up for dbf
2155Lcbbloop:
2156	movb	a0@-,a1@-		| copy bytes
2157	dbf	d0,Lcbbloop		| til done
2158	rts
2159
2160/*
2161 * Emulate fancy VAX string operations:
2162 *	scanc(count, startc, table, mask)
2163 *	skpc(mask, count, startc)
2164 *	locc(mask, count, startc)
2165 */
2166ENTRY(scanc)
2167	movl	sp@(4),d0	| get length
2168	jeq	Lscdone		| nothing to do, return
2169	movl	sp@(8),a0	| start of scan
2170	movl	sp@(12),a1	| table to compare with
2171	movb	sp@(19),d1	| and mask to use
2172	movw	d2,sp@-		| need a scratch register
2173	clrw	d2		| clear it out
2174	subqw	#1,d0		| adjust for dbra
2175Lscloop:
2176	movb	a0@+,d2		| get character
2177	movb	a1@(0,d2:w),d2	| get table entry
2178	andb	d1,d2		| mask it
2179	dbne	d0,Lscloop	| keep going til no more or non-zero
2180	addqw	#1,d0		| overshot by one
2181	movw	sp@+,d2		| restore scratch
2182Lscdone:
2183	rts
2184
2185ENTRY(skpc)
2186	movl	sp@(8),d0	| get length
2187	jeq	Lskdone		| nothing to do, return
2188	movb	sp@(7),d1	| mask to use
2189	movl	sp@(12),a0	| where to start
2190	subqw	#1,d0		| adjust for dbcc
2191Lskloop:
2192	cmpb	a0@+,d1		| compate with mask
2193	dbne	d0,Lskloop	| keep going til no more or zero
2194	addqw	#1,d0		| overshot by one
2195Lskdone:
2196	rts
2197
2198ENTRY(locc)
2199	movl	sp@(8),d0	| get length
2200	jeq	Llcdone		| nothing to do, return
2201	movb	sp@(7),d1	| mask to use
2202	movl	sp@(12),a0	| where to start
2203	subqw	#1,d0		| adjust for dbcc
2204Llcloop:
2205	cmpb	a0@+,d1		| compate with mask
2206	dbeq	d0,Llcloop	| keep going til no more or non-zero
2207	addqw	#1,d0		| overshot by one
2208Llcdone:
2209	rts
2210
2211/*
2212 * Emulate VAX FFS (find first set) instruction.
2213 */
2214ENTRY(ffs)
2215	moveq	#-1,d0
2216	movl	sp@(4),d1
2217	jeq	Lffsdone
2218Lffsloop:
2219	addql	#1,d0
2220	btst	d0,d1
2221	jeq	Lffsloop
2222Lffsdone:
2223	addql	#1,d0
2224	rts
2225
2226#ifdef FPCOPROC
2227/*
2228 * Save and restore 68881 state.
2229 * Pretty awful looking since our assembler does not
2230 * recognize FP mnemonics.
2231 */
2232ENTRY(m68881_save)
2233	movl	sp@(4),a0		| save area pointer
2234	fsave	a0@			| save state
2235	tstb	a0@			| null state frame?
2236	jeq	Lm68881sdone		| yes, all done
2237	fmovem fp0-fp7,a0@(216)		| save FP general registers
2238	fmovem fpcr/fpsr/fpi,a0@(312)	| save FP control registers
2239Lm68881sdone:
2240	rts
2241
2242ENTRY(m68881_restore)
2243	movl	sp@(4),a0		| save area pointer
2244	tstb	a0@			| null state frame?
2245	jeq	Lm68881rdone		| yes, easy
2246	fmovem	a0@(312),fpcr/fpsr/fpi	| restore FP control registers
2247	fmovem	a0@(216),fp0-fp7	| restore FP general registers
2248Lm68881rdone:
2249	frestore a0@			| restore state
2250	rts
2251
2252/* LUNA */
2253
2254	.globl	_fpp_svarea
2255
2256/* Fpp is MC68882 ? */
2257ENTRY(is_68882)
2258	frestore _fppnull	| initialize fpp
2259	movl	#2,d0
2260	fmovecr	#0,fp1
2261	fsinx	fp1,fp2
2262	lea	_fpp_svarea,a0	| save area
2263	movw	sr,d1		| save status reg.
2264	movw	#0x2700,sr	| mask intrrupt
2265	fsave	a0@		| save fpp context
2266	movw	d1,sr		| restore status reg.
2267	movl	a0@,d1
2268	andl	#0x00ff0000,d1  | check status field
2269	cmpl	#0x00180000,d1  | 68881(idle)?
2270	beq	_is81
2271	cmpl	#0x00b40000,d1	| 68881(busy)?
2272	beq	_is81
2273	cmpl	#0x00380000,d1	| 68882(idle)?
2274	beq	_is82
2275	cmpl	#0x00d40000,d1	| 68882(busy)?
2276	beq	_is82
2277	bra	_is82out	| default 68881
2278_is81:
2279	clrl	d0
2280	bra	_is82out
2281_is82:
2282	movl	#1,d0
2283_is82out:
2284	frestore a0@
2285	rts
2286
2287#ifdef	OLD_LUNA
2288/* We have fpp ? */
2289ENTRY(havefpp)
2290	movl	a2,sp@-
2291	clrl	d0
2292	movl	vb,a2
2293	movl	a2@(FLINE_VEC),a0	| save vectors
2294	movl	a2@(COPRO_VEC),a1
2295	movl	sp,d1
2296	movl	#_fpvec,a2@(FLINE_VEC)	| change vectors
2297	movl	#_fpvec,a2@(COPRO_VEC)
2298	fnop				| cause exception ?
2299	movl	#1,d0
2300_fpvec:	movl	a0,a2@(FLINE_VEC)	| restore vectors
2301	movl	a1,a2@(COPRO_VEC)
2302	movl	d1,sp
2303	movl	sp@+,a2
2304	rts
2305#endif
2306#endif
2307
2308/*
2309 * Handle the nitty-gritty of rebooting the machine.
2310 * Basically we just turn off the MMU and jump to the appropriate ROM routine.
2311 * Note that we must be running in an address range that is mapped one-to-one
2312 * logical to physical so that the PC is still valid immediately after the MMU
2313 * is turned off.  We have conveniently mapped the last page of physical
2314 * memory this way.
2315 */
2316	.globl	_doboot
2317_doboot:
2318	movl	#0x41000004,a0
2319	movl	a0@,a1			| get PROM restart entry address
2320#if defined(LUNA2)
2321	cmpl	#-2,_mmutype		| 68040?
2322	jne	LmotommuF		| no, skip
2323
2324	movw	#PSL_HIGHIPL,sr		| no interrupts
2325
2326	movl	#0x41000000,a0
2327	movl	a0@,d0
2328	movc	d0,isp			| set ISP
2329
2330	.word	0xf4f8			| cpusha bc
2331	movl	#0,d0
2332	movc	d0,cacr			| caches off
2333	movql	#0,d0
2334	.long	0x4e7b0004		| movc d0,itt0
2335	.long	0x4e7b0005		| movc d0,itt1
2336	.long	0x4e7b0006		| movc d0,dtt0
2337	.long	0x4e7b0007		| movc d0,dtt1
2338
2339	.long	0x4e7b0003		| movc d0,tc
2340
2341	jmp	a1@			| goto REBOOT
2342LmotommuF:
2343#endif
2344	movl	#CACHE_OFF,d0
2345	movc	d0,cacr			| disable on-chip cache(s)
2346	movl	#_tcroff,a0		| value for pmove to TC (turn off MMU)
2347	pmove	a0@,tc			| disable MMU
2348	jmp	a1@			| goto REBOOT
2349
2350	.data
2351	.globl	_machineid,_mmutype
2352_machineid:
2353	.long	1		| default to LUNA-I
2354_mmutype:
2355	.long	-1		| default to 68030 PMMU
2356	.globl	_protorp,_protott0,_protott1
2357_protorp:
2358	.long	0,0		| prototype root pointer
2359_protott0:
2360	.long	0x403f8543	| tt0 (for LUNA1 kernel 0x40000000-0x7fffffff)
2361_protott1:
2362	.long	0x807F8543	| tt1 (for LUNA1 kernel 0x80000000-0xffffffff)
2363_mapping_tc:
2364	.long	0
2365	.globl	_cold
2366_cold:
2367	.long	1		| cold start flag
2368	.globl	_want_resched
2369_want_resched:
2370	.long	0
2371	.globl	_proc0paddr
2372_proc0paddr:
2373	.long	0		| KVA of proc0 u-area
2374
2375	.globl	_tcroff
2376_tcroff:
2377	.long	0		| TC reg. reset flag
2378
2379#ifdef FPCOPROC
2380	.globl	_fppnull
2381_fppnull:
2382	.long	0
2383#endif
2384	.globl	_clock_on
2385_clock_on:
2386	.long	0		| clock is enable ?
2387	.globl	_dipswitch
2388_dipswitch:
2389	.word	0		| dipsw(front panel) value
2390	.globl	_KernInter
2391_KernInter:			| Kernel InterFace Field
2392	.space	KIFF_SIZE
2393#ifdef DEBUG
2394	.globl	fulltflush, fullcflush
2395fulltflush:
2396	.long	0
2397fullcflush:
2398	.long	0
2399#endif
2400#ifdef HPFPLIB
2401/*
2402 * Undefined symbols from hpux_float.o:
2403 *
2404 * kdb_printf:	A kernel debugger print routine, we just use printf instead.
2405 * processor:	HP-UX equiv. of machineid, set to 3 if it is a 68040.
2406 * u:		Ye ole u-area.  The code wants to grab the first longword
2407 *		indirect off of that and clear the 0x40000 bit there.
2408 *		Oddly enough this was incorrect even in HP-UX!
2409 * runrun:	Old name for want_resched.
2410 */
2411	.globl	_kdb_printf,_processor,_u,_runrun
2412_kdb_printf:
2413	.long	_printf
2414_processor:
2415	.long	0
2416_u:
2417	.long	.+4
2418	.long	0
2419	.set	_runrun,_want_resched
2420#endif
2421/* interrupt counters */
2422	.globl	_intrcnt,_eintrcnt,_intrnames,_eintrnames
2423_intrnames:
2424	.asciz	"spur"
2425	.asciz	"lev1"
2426	.asciz	"lev2"
2427	.asciz	"lev3"
2428	.asciz	"lev4"
2429	.asciz	"clock"
2430	.asciz	"lev7"
2431	.asciz	"nmi"
2432_eintrnames:
2433	.even
2434_intrcnt:
2435	.long	0,0,0,0,0,0,0,0,0
2436_eintrcnt:
2437