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