xref: /netbsd/sys/arch/amigappc/amigappc/locore.S (revision bf9ec67e)
1/*      $NetBSD: locore.S,v 1.8 2001/12/03 21:10:48 aymeric Exp $   */
2
3/*
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1996 TooLs GmbH.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *      This product includes software developed by TooLs GmbH.
19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 *    derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/* Amiga part written by Adam Ciarcinski adam@albedo.art.pl */
35
36/*
37 * Some instructions gas doesn't understand (yet?)
38 */
39#define bdneq   bdnzf 2,
40
41#include "opt_ddb.h"
42#include "opt_ipkdb.h"
43#include "opt_lockdebug.h"
44#include "assym.h"
45
46#include <sys/syscall.h>
47
48#include <machine/param.h>
49#include <machine/pmap.h>
50#include <machine/psl.h>
51#include <machine/trap.h>
52#include <machine/asm.h>
53#include <machine/p5reg.h>
54
55#include <machine/hid.h>
56#include <amiga/amiga/custom.h>
57
58	.data
59GLOBAL(proc0paddr)
60	.long	0
61GLOBAL(ssir)
62	.word	0
63GLOBAL(delaydivisor)
64	.long	0
65GLOBAL(lowram)
66	.long	0
67
68GLOBAL(eintrnames)
69	.align	4
70GLOBAL(intrcnt)
71	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
72	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
73	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
74	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
75	.long	0,0,0,0
76GLOBAL(eintrcnt)
77
78GLOBAL(powersave)
79	.long	0
80
81idle_u:
82	.long	0			/* fake uarea during idle after exit */
83openfirmware_entry:
84	.long	0			/* openfirmware entry point */
85srsave:
86	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
87
88
89/*
90 * This symbol is here for the benefit of kvm_mkdb, and is supposed to
91 * mark the start of kernel text.
92 */
93        .text
94        .globl  _C_LABEL(kernel_text)
95_C_LABEL(kernel_text):
96
97/*
98 * Startup entry
99 * This is where bootloader jumps after successful kernel loading.
100 * Must be the first address in text segment
101 */
102	.text
103	.globl	__start
104__start:
105/*
106 * Disable M68k
107 * First of all we must disable M68k, since it cannot be done by
108 * the loader (which is run under M68k).
109 */
110	lis	5,P5BASE@h
111	/* ori	5,5,P5BASE@l	- we assume that the lsb is 0x0000 */
112	li	3,P5_M68K_RESET
113	stb	3,P5_REG_RESET(5)
114
115/*
116 * Disable Amiga interrupts
117 */
118	lis	4,0xbfd000@h
119	ori	4,4,0xbfd000@l
120	li	3,0x7f
121	stb	3,0xd00(4)	/* CIAB icr */
122	stb	3,0x1d01(4)	/* CIAA icr */
123
124/*
125 * Change interrupt master
126 * Only one CPU can get Amiga interrupts, either M68k or PowerPC.
127 */
128	li	3,P5_SET_CLEAR|P5_DISABLE_INT
129	stb	3,P5_IPL_EMU(5)	/* disable interrupts */
130	li	3,P5_INT_MASTER
131	stb	3,P5_REG_INT(5)	/* let the PowerPC get interrupts */
132	li	3,P5_DISABLE_INT
133	stb     3,P5_IPL_EMU(5)	/* enable interrupts */
134	li	3,P5_LVL7
135	stb	3,P5_INT_LVL(5)
136
137/*
138 * Remove ROM mapping
139 * This will give us extra 512K RAM
140 */
141	li	3,0x60
142	stb	3,P5_REG_LOCK(5)
143	li	3,0x50
144	stb	3,P5_REG_LOCK(5)
145	li	3,0x30
146	stb	3,P5_REG_LOCK(5)
147	li	3,P5_SET_CLEAR|P5_SHADOW
148	stb	3,P5_REG_SHADOW(5)
149	li	3,0x00
150	stb	3,P5_REG_LOCK(5)
151
152
153/*
154 * Clear BAT registers
155 * Clearing segment register
156 */
157	xor	0,0,0
158	mtibatu	0,0
159	mtibatu	1,0
160	mtibatu	2,0
161	mtibatu	3,0
162	mtdbatu	0,0
163	mtdbatu	1,0
164	mtdbatu	2,0
165	mtdbatu	3,0
166	mtsr	0,0
167	mtsr	1,0
168	mtsr	2,0
169	mtsr	3,0
170	mtsr	4,0
171	mtsr	5,0
172	mtsr	6,0
173	mtsr	7,0
174	mtsr	8,0
175	mtsr	9,0
176	mtsr	10,0
177	mtsr	11,0
178	mtsr	12,0
179	mtsr	13,0
180	mtsr	14,0
181	mtsr	15,0
182	sync
183
184/*
185 * Enable caches on 603e/604e
186 */
187	mfspr	3,1008
188	ori	3,3,HID0_ICE|HID0_DCE|HID0_SGE|HID0_BHT
189	ori	4,3,HID0_ICFI|HID0_DCFI
190	sync
191	mtspr	1008,4
192	sync
193	mtspr	1008,3
194	sync
195	isync
196
197/*
198 * Compute end-of-kernel memory
199 */
200	lis	8,_C_LABEL(end)@h
201	ori	8,8,_C_LABEL(end)@l
202	li	9,PGOFSET
203	add	8,8,9
204	andc	8,8,9		/* page alignment */
205
206	addi	8,8,USPACE	/* space for idle_u */
207	lis	9,_C_LABEL(proc0paddr)@ha
208	stw	8,_C_LABEL(proc0paddr)@l(9)
209	addi	1,8,USPACE-FRAMELEN	/* stack pointer for proc0 */
210	mr	4,1
211	xor	0,0,0
212	stwu	0,-16(1)
213
214	lis	3,__start@h
215	ori	3,3,__start@l
216	bl	_C_LABEL(initppc)
217
218
219/*
220 * Jump to main() (from kern/init_main.c)
221 * main() should call consinit(), uvm_init() and cpu_startup()
222 */
223	b	_C_LABEL(main)
224
225/*
226 * Colours on the screen
227 * For visual test purposes.
228 */
229	.globl	_C_LABEL(cpu_fail)
230_C_LABEL(cpu_fail):
231	li	3,0xb8b
232	li	4,0xa0a
233	li	5,0x000
234	lis	2,0xdff000@h
235	ori	2,2,0xdff000@l
236loop:	sth	3,0x180(2)
237	sth	4,0x180(2)
238	sth	5,0x180(2)
239	b	loop
240
241
242/*
243 * ADAM: fake interrupt handler
244 */
245	.globl	_C_LABEL(adamint),_C_LABEL(adamintsize)
246_C_LABEL(adamint):
247	mtsprg	2,2
248	mtsprg	3,3
249	lis	3,0xdff000@h
250	ori	3,3,0xdff000@l
2511:	li	2,0x00a
252	sth	2,0x180(3)
253	li	2,0xaaa
254	sth	2,0x180(3)
255	b	1b
256	mfsprg	3,3
257	mfsprg	2,2
258	rfi
259_C_LABEL(adamintsize) = .-_C_LABEL(adamint)
260
261/*
262 * No processes are runnable, so loop waiting for one.
263 * Separate label here for accounting purposes.
264 * When we get here, interrupts are off (MSR[EE]=0) and sched_lock is held.
265 */
266	.text
267ASENTRY(Idle)
268	lis	8,_C_LABEL(sched_whichqs)@ha
269	lwz	9,_C_LABEL(sched_whichqs)@l(8)
270
271	or.	9,9,9
272	bne-	.Lsw1			/* at least one queue non-empty */
273
274#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
275	bl	_C_LABEL(sched_unlock_idle)
276#endif
277
278	mfmsr	3
279	ori	3,3,PSL_EE@l		/* reenable ints again */
280	mtmsr	3
281	isync
282
283/* Check if we can use power saving mode */
284	lis	8,_C_LABEL(powersave)@ha
285	lwz	9,_C_LABEL(powersave)@l(8)
286
287	or.	9,9,9
288	beq	1f
289
290	sync
291	oris	3,3,PSL_POW@h		/* enter power saving mode */
292	mtmsr	3
293	isync
2941:
295	andi.	3,3,~PSL_EE@l		/* disable interrupts while
296					   manipulating runque */
297	mtmsr	3
298
299#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
300	bl	_C_LABEL(sched_lock_idle)
301#endif
302	b	_ASM_LABEL(Idle)
303
304/*
305 * switchexit gets called from cpu_exit to complete the exit procedure.
306 */
307ENTRY(switchexit)
308/* First switch to the idle pcb/kernel stack */
309	lis	6,idle_u@ha
310	lwz	6,idle_u@l(6)
311	lis	7,_C_LABEL(curpcb)@ha
312	stw	6,_C_LABEL(curpcb)@l(7)
313	addi	1,6,USPACE-16		/* 16 bytes are reserved at stack top */
314	/*
315	 * Schedule the vmspace and stack to be freed (the proc arg is
316	 * already in r3).
317	 */
318	bl	_C_LABEL(exit2)
319
320#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
321	bl	_C_LABEL(sched_lock_idle)
322#endif
323
324/* Fall through to cpu_switch to actually select another proc */
325	li	3,0			/* indicate exited process */
326
327/*
328 * void cpu_switch(struct proc *p)
329 * Find a runnable process and switch to it.
330 */
331/* XXX noprofile?  --thorpej@netbsd.org */
332ENTRY(cpu_switch)
333	mflr	0			/* save lr */
334	stw	0,4(1)
335	stwu	1,-16(1)
336	stw	31,12(1)
337	stw	30,8(1)
338
339	mr	30,3
340	lis	3,_C_LABEL(curproc)@ha
341	xor	31,31,31
342	stw	31,_C_LABEL(curproc)@l(3) /* Zero to not accumulate cpu time */
343	lis	3,_C_LABEL(curpcb)@ha
344	lwz	31,_C_LABEL(curpcb)@l(3)
345
346#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
347/* Release the sched_lock before processing interrupts. */
348	bl	_C_LABEL(sched_unlock_idle)
349#endif
350
351	xor	3,3,3
352	bl	_C_LABEL(lcsplx)
353	stw	3,PCB_SPL(31)		/* save spl */
354
355/* Lock the scheduler. */
356	mfmsr	3
357	andi.	3,3,~PSL_EE@l		/* disable interrupts while
358					   manipulating runque */
359	mtmsr	3
360	isync
361#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
362	bl	_C_LABEL(sched_lock_idle)
363#endif
364
365/* Find a new process */
366	lis	8,_C_LABEL(sched_whichqs)@ha
367	lwz	9,_C_LABEL(sched_whichqs)@l(8)
368
369	or.	9,9,9
370	beq-	_ASM_LABEL(Idle)	/* all queues empty */
371.Lsw1:
372	cntlzw	10,9
373	lis	4,_C_LABEL(sched_qs)@ha
374	addi	4,4,_C_LABEL(sched_qs)@l
375	slwi	3,10,3
376	add	3,3,4			/* select queue */
377
378	lwz	31,P_FORW(3)		/* unlink first proc from queue */
379	lwz	4,P_FORW(31)
380	stw	4,P_FORW(3)
381	stw	3,P_BACK(4)
382
383	cmpl	0,3,4			/* queue empty? */
384	bne	1f
385
386	lis	3,0x80000000@h
387	srw	3,3,10
388	andc	9,9,3
389	stw	9,_C_LABEL(sched_whichqs)@l(8) /* mark it empty */
390
3911:
392	/* just did this resched thing */
393	xor	3,3,3
394	lis	4,_C_LABEL(want_resched)@ha
395	stw	3,_C_LABEL(want_resched)@l(4)
396
397	stw	3,P_BACK(31)		/* probably superfluous */
398
399#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
400	/* Unlock the sched_lock, but leave interrupts off, for now. */
401	bl	_C_LABEL(sched_unlock_idle)
402#endif
403
404	/* p->p_cpu initialized in fork1() for single-processor */
405
406	li	3,SONPROC		/* p->p_stat = SONPROC */
407	stb	3,P_STAT(31)
408
409	/* record new process */
410	lis	4,_C_LABEL(curproc)@ha
411	stw	31,_C_LABEL(curproc)@l(4)
412
413	mfmsr	3
414	ori	3,3,PSL_EE@l		/* Now we can interrupt again */
415	mtmsr	3
416
417	cmpl	0,31,30			/* is it the same process? */
418	beq	switch_return
419
420	or.	30,30,30		/* old process was exiting? */
421	beq	switch_exited
422
423	mfsr	10,USER_SR		/* save USER_SR for copyin/copyout */
424	mfcr	11			/* save cr */
425	mr	12,2			/* save r2 */
426	stwu	1,-SFRAMELEN(1)		/* still running on old stack */
427	stmw	10,8(1)
428	lwz	3,P_ADDR(30)
429	stw	1,PCB_SP(3)		/* save SP */
430
431switch_exited:
432	mfmsr	3
433	andi.	3,3,~PSL_EE@l		/* disable interrupts while
434					   actually switching */
435	mtmsr	3
436
437	/* indicate new pcb */
438	lwz	4,P_ADDR(31)
439	lis	5,_C_LABEL(curpcb)@ha
440	stw	4,_C_LABEL(curpcb)@l(5)
441
442	/* save real pmap pointer for spill fill */
443	lwz	5,PCB_PMR(4)
444	lis	6,_C_LABEL(curpm)@ha
445	stwu	5,_C_LABEL(curpm)@l(6)
446	stwcx.	5,0,6			/* clear possible reservation */
447
448	addic.	5,5,64
449	li	6,0
450	mfsr	8,KERNEL_SR		/* save kernel SR */
4511:
452	addis	6,6,-0x10000000@ha	/* set new procs segment registers */
453	or.	6,6,6			/* This is done from the real
454					   address pmap */
455	lwzu	7,-4(5)			/* so we don't have to worry */
456	mtsrin	7,6			/* about accessibility */
457	bne	1b
458	mtsr	KERNEL_SR,8		/* restore kernel SR */
459	isync
460
461	lwz	1,PCB_SP(4)		/* get new procs SP */
462
463	ori	3,3,PSL_EE@l		/* interrupts are okay again */
464	mtmsr	3
465
466	lmw	10,8(1)			/* get other regs */
467	lwz	1,0(1)			/* get saved SP */
468	mr	2,12			/* get saved r2 */
469	mtcr	11			/* get saved cr */
470	isync
471	mtsr	USER_SR,10		/* get saved USER_SR */
472	isync
473
474switch_return:
475	mr	30,7			/* save proc pointer */
476	lwz	3,PCB_SPL(4)
477	bl	_C_LABEL(lcsplx)
478
479	mr	3,30			/* get curproc for special fork
480					   returns */
481
482	lwz	31,12(1)
483	lwz	30,8(1)
484	addi	1,1,16
485	lwz	0,4(1)
486	mtlr	0
487	blr
488
489/*
490 * Data used during primary/secondary traps/interrupts
491 */
492#define	tempsave	0x2e0	/* primary save area for trap handling */
493#define	disisave	0x3e0	/* primary save area for dsi/isi traps */
494
495#define	INTSTK	(8*1024)	/* 8K interrupt stack */
496	.data
497	.align	4
498intstk:
499	.space	INTSTK		/* interrupt stack */
500
501GLOBAL(intr_depth)
502	.long	-1		/* in-use marker */
503
504#define	SPILLSTK 1024		/* 1K spill stack */
505
506	.comm	spillstk,SPILLSTK,8
507
508/*
509 * This code gets copied to all the trap vectors
510 * (except ISI/DSI, ALI, the interrupts, and possibly the debugging
511 * traps when using IPKDB).
512 */
513	.text
514	.globl	_C_LABEL(trapcode),_C_LABEL(trapsize)
515_C_LABEL(trapcode):
516	mtsprg	1,1			/* save SP */
517	stmw	28,tempsave(0)		/* free r28-r31 */
518	mflr	28			/* save LR */
519	mfcr	29			/* save CR */
520/* Test whether we already had PR set */
521	mfsrr1	31
522	mtcr	31
523	bc	4,17,1f			/* branch if PSL_PR is clear */
524	lis	1,_C_LABEL(curpcb)@ha
525	lwz	1,_C_LABEL(curpcb)@l(1)
526	addi	1,1,USPACE		/* stack is top of user struct */
5271:
528	bl	s_trap
529_C_LABEL(trapsize) = .-_C_LABEL(trapcode)
530
531/*
532 * For ALI: has to save DSISR and DAR
533 */
534	.globl	_C_LABEL(alitrap),_C_LABEL(alisize)
535_C_LABEL(alitrap):
536	mtsprg	1,1			/* save SP */
537	stmw	28,tempsave(0)		/* free r28-r31 */
538	mfdar	30
539	mfdsisr	31
540	stmw	30,tempsave+16(0)
541	mflr	28			/* save LR */
542	mfcr	29			/* save CR */
543/* Test whether we already had PR set */
544	mfsrr1	31
545	mtcr	31
546	bc	4,17,1f			/* branch if PSL_PR is clear */
547	lis	1,_C_LABEL(curpcb)@ha
548	lwz	1,_C_LABEL(curpcb)@l(1)
549	addi	1,1,USPACE		/* stack is top of user struct */
5501:
551	bl	s_trap
552_C_LABEL(alisize) = .-_C_LABEL(alitrap)
553
554/*
555 * Similar to the above for DSI
556 * Has to handle BAT spills
557 * and standard pagetable spills
558 */
559	.globl	_C_LABEL(dsitrap),_C_LABEL(dsisize)
560_C_LABEL(dsitrap):
561	stmw	28,disisave(0)		/* free r28-r31 */
562	mfcr	29			/* save CR */
563	mfxer	30			/* save XER */
564	mtsprg	2,30			/* in SPRG2 */
565	mfsrr1	31			/* test kernel mode */
566	mtcr	31
567	bc	12,17,1f		/* branch if PSL_PR is set */
568	mfdar	31			/* get fault address */
569	rlwinm	31,31,7,25,28		/* get segment * 8 */
570
571	/* get batu */
572	addis	31,31,_C_LABEL(battable)@ha
573	lwz	30,_C_LABEL(battable)@l(31)
574	mtcr	30
575	bc	4,30,1f			/* branch if supervisor valid is
576					   false */
577	/* get batl */
578	lwz	31,_C_LABEL(battable)+4@l(31)
579/* We randomly use the highest two bat registers here */
580	mftb	28
581	andi.	28,28,1
582	bne	2f
583	mtdbatu	2,30
584	mtdbatl	2,31
585	b	3f
5862:
587	mtdbatu	3,30
588	mtdbatl	3,31
5893:
590	mfsprg	30,2			/* restore XER */
591	mtxer	30
592	mtcr	29			/* restore CR */
593	lmw	28,disisave(0)		/* restore r28-r31 */
594	rfi				/* return to trapped code */
5951:
596	mflr	28			/* save LR */
597	b	s_dsitrap
598_C_LABEL(dsisize) = .-_C_LABEL(dsitrap)
599
600/*
601 * Similar to the above for ISI
602 */
603	.globl	_C_LABEL(isitrap),_C_LABEL(isisize)
604_C_LABEL(isitrap):
605	stmw	28,disisave(0)		/* free r28-r31 */
606	mflr	28			/* save LR */
607	mfcr	29			/* save CR */
608	mfsrr1	31			/* test kernel mode */
609	mtcr	31
610	bc	12,17,1f		/* branch if PSL_PR is set */
611	mfsrr0	31			/* get fault address */
612	rlwinm	31,31,7,25,28		/* get segment * 8 */
613
614	/* get batu */
615	addis	31,31,_C_LABEL(battable)@ha
616	lwz	30,_C_LABEL(battable)@l(31)
617	mtcr	30
618	bc	4,30,1f			/* branch if supervisor valid is
619					   false */
620	mtibatu	3,30
621
622	/* get batl */
623	lwz	30,_C_LABEL(battable)+4@l(31)
624	mtibatl	3,30
625
626	mtcr	29			/* restore CR */
627	lmw	28,disisave(0)		/* restore r28-r31 */
628	rfi				/* return to trapped code */
6291:
630	b	s_isitrap
631_C_LABEL(isisize)= .-_C_LABEL(isitrap)
632
633/*
634 * This one for the external interrupt handler.
635 */
636	.globl	_C_LABEL(extint),_C_LABEL(extsize)
637_C_LABEL(extint):
638	mtsprg	1,1			/* save SP */
639	stmw	28,tempsave(0)		/* free r28-r31 */
640	mflr	28			/* save LR */
641	mfcr	29			/* save CR */
642	mfxer	30			/* save XER */
643	lis	1,intstk+INTSTK@ha	/* get interrupt stack */
644	addi	1,1,intstk+INTSTK@l
645	lwz	31,0(1)			/* were we already running on intstk? */
646	addic.	31,31,1
647	stw	31,0(1)
648	beq	1f
649	mfsprg	1,1			/* yes, get old SP */
6501:
651	lis	0,extintr@h
652	ori	0,0,extintr@l
653	mtlr	0
654	blr
655/*	ba	extintr*/
656_C_LABEL(extsize) = .-_C_LABEL(extint)
657
658/*
659 * And this one for the decrementer interrupt handler.
660 */
661	.globl	_C_LABEL(decrint),_C_LABEL(decrsize)
662_C_LABEL(decrint):
663	mtsprg	1,1			/* save SP */
664	stmw	28,tempsave(0)		/* free r28-r31 */
665	mflr	28			/* save LR */
666	mfcr	29			/* save CR */
667	mfxer	30			/* save XER */
668	lis	1,intstk+INTSTK@ha	/* get interrupt stack */
669	addi	1,1,intstk+INTSTK@l
670	lwz	31,0(1)			/* were we already running on intstk? */
671	addic.	31,31,1
672	stw	31,0(1)
673	beq	1f
674	mfsprg	1,1			/* yes, get old SP */
6751:
676	lis	0,decrintr@h
677	ori	0,0,decrintr@l
678	mtlr	0
679	blr
680/*	ba	decrintr*/
681_C_LABEL(decrsize) = .-_C_LABEL(decrint)
682
683/*
684 * Now the tlb software load for 603 processors:
685 * (Code essentially from the 603e User Manual, Chapter 5, but
686 * corrected a lot.)
687 */
688#define	DMISS	976
689#define	DCMP	977
690#define	HASH1	978
691#define	HASH2	979
692#define	IMISS	980
693#define	ICMP	981
694#define	RPA	982
695
696	.globl	_C_LABEL(tlbimiss),_C_LABEL(tlbimsize)
697_C_LABEL(tlbimiss):
698	mfspr	2,HASH1			/* get first pointer */
699	li	1,8
700	mfctr	0			/* save counter */
701	mfspr	3,ICMP			/* get first compare value */
702	addi	2,2,-8			/* predec pointer */
7031:
704	mtctr	1			/* load counter */
7052:
706	lwzu	1,8(2)			/* get next pte */
707	cmpl	0,1,3			/* see if found pte */
708	bdneq	2b			/* loop if not eq */
709	bne	3f			/* not found */
710	lwz	1,4(2)			/* load tlb entry lower word */
711	andi.	3,1,8			/* check G-bit */
712	bne	4f			/* if guarded, take ISI */
713	mtctr	0			/* restore counter */
714	mfspr	0,IMISS			/* get the miss address for the tlbli */
715	mfsrr1	3			/* get the saved cr0 bits */
716	mtcrf	0x80,3			/* and restore */
717	ori	1,1,0x100		/* set the reference bit */
718	mtspr	RPA,1			/* set the pte */
719	srwi	1,1,8			/* get byte 7 of pte */
720	tlbli	0			/* load the itlb */
721	stb	1,6(2)			/* update page table */
722	rfi
723
7243:	/* not found in pteg */
725	andi.	1,3,0x40		/* have we already done second hash? */
726	bne	5f
727	mfspr	2,HASH2			/* get the second pointer */
728	ori	3,3,0x40		/* change the compare value */
729	li	1,8
730	addi	2,2,-8			/* predec pointer */
731	b	1b
7324:	/* guarded */
733	mfsrr1	3
734	andi.	2,3,0xffff		/* clean upper srr1 */
735	oris	2,2,0x8000000@h		/* set srr<4> to flag prot violation */
736	b	6f
7375:	/* not found anywhere */
738	mfsrr1	3
739	andi.	2,3,0xffff		/* clean upper srr1 */
740	oris	2,2,0x40000000@h	/* set srr1<1> to flag pte not found */
7416:
742	mtctr	0			/* restore counter */
743	mtsrr1	2
744	mfmsr	0
745	xoris	0,0,0x20000@h		/* flip the msr<tgpr> bit */
746	mtcrf	0x80,3			/* restore cr0 */
747	mtmsr	0			/* now with native gprs */
748	isync
749	ba	EXC_ISI
750_C_LABEL(tlbimsize) = .-_C_LABEL(tlbimiss)
751
752	.globl	_C_LABEL(tlbdlmiss),_C_LABEL(tlbdlmsize)
753_C_LABEL(tlbdlmiss):
754	mfspr	2,HASH1			/* get first pointer */
755	li	1,8
756	mfctr	0			/* save counter */
757	mfspr	3,DCMP			/* get first compare value */
758	addi	2,2,-8			/* predec pointer */
7591:
760	mtctr	1			/* load counter */
7612:
762	lwzu	1,8(2)			/* get next pte */
763	cmpl	0,1,3			/* see if found pte */
764	bdneq	2b			/* loop if not eq */
765	bne	3f			/* not found */
766	lwz	1,4(2)			/* load tlb entry lower word */
767	mtctr	0			/* restore counter */
768	mfspr	0,DMISS			/* get the miss address for the tlbld */
769	mfsrr1	3			/* get the saved cr0 bits */
770	mtcrf	0x80,3			/* and restore */
771	ori	1,1,0x100		/* set the reference bit */
772	mtspr	RPA,1			/* set the pte */
773	srwi	1,1,8			/* get byte 7 of pte */
774	tlbld	0			/* load the dtlb */
775	stb	1,6(2)			/* update page table */
776	rfi
777
7783:	/* not found in pteg */
779	andi.	1,3,0x40		/* have we already done second hash? */
780	bne	5f
781	mfspr	2,HASH2			/* get the second pointer */
782	ori	3,3,0x40		/* change the compare value */
783	li	1,8
784	addi	2,2,-8			/* predec pointer */
785	b	1b
7865:	/* not found anywhere */
787	mfsrr1	3
788	lis	1,0x40000000@h		/* set dsisr<1> to flag pte not found */
789	mtctr	0			/* restore counter */
790	andi.	2,3,0xffff		/* clean upper srr1 */
791	mtsrr1	2
792	mtdsisr	1			/* load the dsisr */
793	mfspr	1,DMISS			/* get the miss address */
794	mtdar	1			/* put in dar */
795	mfmsr	0
796	xoris	0,0,0x20000@h		/* flip the msr<tgpr> bit */
797	mtcrf	0x80,3			/* restore cr0 */
798	mtmsr	0			/* now with native gprs */
799	isync
800	ba	EXC_DSI
801_C_LABEL(tlbdlmsize) = .-_C_LABEL(tlbdlmiss)
802
803	.globl	_C_LABEL(tlbdsmiss),_C_LABEL(tlbdsmsize)
804_C_LABEL(tlbdsmiss):
805	mfspr	2,HASH1			/* get first pointer */
806	li	1,8
807	mfctr	0			/* save counter */
808	mfspr	3,DCMP			/* get first compare value */
809	addi	2,2,-8			/* predec pointer */
8101:
811	mtctr	1			/* load counter */
8122:
813	lwzu	1,8(2)			/* get next pte */
814	cmpl	0,1,3			/* see if found pte */
815	bdneq	2b			/* loop if not eq */
816	bne	3f			/* not found */
817	lwz	1,4(2)			/* load tlb entry lower word */
818	andi.	3,1,0x80		/* check the C-bit */
819	beq	4f
8205:
821	mtctr	0			/* restore counter */
822	mfspr	0,DMISS			/* get the miss address for the tlbld */
823	mfsrr1	3			/* get the saved cr0 bits */
824	mtcrf	0x80,3			/* and restore */
825	mtspr	RPA,1			/* set the pte */
826	tlbld	0			/* load the dtlb */
827	rfi
828
8293:	/* not found in pteg */
830	andi.	1,3,0x40		/* have we already done second hash? */
831	bne	5f
832	mfspr	2,HASH2			/* get the second pointer */
833	ori	3,3,0x40		/* change the compare value */
834	li	1,8
835	addi	2,2,-8			/* predec pointer */
836	b	1b
8374:	/* found, but C-bit = 0 */
838	rlwinm.	3,1,30,0,1		/* test PP */
839	bge-	7f
840	andi.	3,1,1
841	beq+	8f
8429:	/* found, but protection violation (PP==00)*/
843	mfsrr1	3
844	lis	1,0xa000000@h		/* indicate protection violation
845					   on store */
846	b	1f
8477:	/* found, PP=1x */
848	mfspr	3,DMISS			/* get the miss address */
849	mfsrin	1,3			/* get the segment register */
850	mfsrr1	3
851	rlwinm	3,3,18,31,31		/* get PR-bit */
852	rlwnm.	2,2,3,1,1		/* get the key */
853	bne-	9b			/* protection violation */
8548:	/* found, set reference/change bits */
855	lwz	1,4(2)			/* reload tlb entry */
856	ori	1,1,0x180
857	sth	1,6(2)
858	b	5b
8595:	/* not found anywhere */
860	mfsrr1	3
861	lis	1,0x42000000@h		/* set dsisr<1> to flag pte not found */
862					/* dsisr<6> to flag store */
8631:
864	mtctr	0			/* restore counter */
865	andi.	2,3,0xffff		/* clean upper srr1 */
866	mtsrr1	2
867	mtdsisr	1			/* load the dsisr */
868	mfspr	1,DMISS			/* get the miss address */
869	mtdar	1			/* put in dar */
870	mfmsr	0
871	xoris	0,0,0x20000@h		/* flip the msr<tgpr> bit */
872	mtcrf	0x80,3			/* restore cr0 */
873	mtmsr	0			/* now with native gprs */
874	isync
875	ba	EXC_DSI
876_C_LABEL(tlbdsmsize) = .-_C_LABEL(tlbdsmiss)
877
878#ifdef DDB
879#define	ddbsave	0xde0		/* primary save area for DDB */
880/*
881 * In case of DDB we want a separate trap catcher for it
882 */
883	.local	ddbstk
884	.comm	ddbstk,INTSTK,8		/* ddb stack */
885
886	.globl	_C_LABEL(ddblow),_C_LABEL(ddbsize)
887_C_LABEL(ddblow):
888	mtsprg	1,1			/* save SP */
889	stmw	28,ddbsave(0)		/* free r28-r31 */
890	mflr	28			/* save LR */
891	mfcr	29			/* save CR */
892	lis	1,ddbstk+INTSTK@ha	/* get new SP */
893	addi	1,1,ddbstk+INTSTK@l
894	b	ddbtrap
895_C_LABEL(ddbsize) = .-_C_LABEL(ddblow)
896#endif	/* DDB */
897
898#ifdef IPKDB
899#define	ipkdbsave	0xde0		/* primary save area for IPKDB */
900/*
901 * In case of IPKDB we want a separate trap catcher for it
902 */
903
904	.local	ipkdbstk
905	.comm	ipkdbstk,INTSTK,8		/* ipkdb stack */
906
907	.globl	_C_LABEL(ipkdblow),_C_LABEL(ipkdbsize)
908_C_LABEL(ipkdblow):
909	mtsprg	1,1			/* save SP */
910	stmw	28,ipkdbsave(0)		/* free r28-r31 */
911	mflr	28			/* save LR */
912	mfcr	29			/* save CR */
913	lis	1,ipkdbstk+INTSTK@ha	/* get new SP */
914	addi	1,1,ipkdbstk+INTSTK@l
915	bipkdbtrap
916_C_LABEL(ipkdbsize) = .-_C_LABEL(ipkdblow)
917#endif	/* IPKDB */
918
919/*
920 * FRAME_SETUP assumes:
921 *	SPRG1		SP (1)
922 *	savearea	r28-r31,DAR,DSISR	(DAR & DSISR only for DSI traps)
923 *	28		LR
924 *	29		CR
925 *	1		kernel stack
926 *	LR		trap type
927 *	SRR0/1		as at start of trap
928 */
929#define	FRAME_SETUP(savearea)						\
930/* Have to enable translation to allow access of kernel stack: */	\
931	mfsrr0	30;							\
932	mfsrr1	31;							\
933	stmw	30,savearea+24(0);					\
934	mfmsr	30;							\
935	ori	30,30,(PSL_DR|PSL_IR);					\
936	mtmsr	30;							\
937	isync;								\
938	mfsprg	31,1;							\
939	stwu	31,-FRAMELEN(1);					\
940	stw	0,FRAME_0+8(1);						\
941	stw	31,FRAME_1+8(1);					\
942	stw	28,FRAME_LR+8(1);					\
943	stw	29,FRAME_CR+8(1);					\
944	lmw	28,savearea(0);						\
945	stmw	2,FRAME_2+8(1);						\
946	lmw	28,savearea+16(0);					\
947	mfxer	3;							\
948	mfctr	4;							\
949	mflr	5;							\
950	andi.	5,5,0xff00;						\
951	stw	3,FRAME_XER+8(1);					\
952	stw	4,FRAME_CTR+8(1);					\
953	stw	5,FRAME_EXC+8(1);					\
954	stw	28,FRAME_DAR+8(1);					\
955	stw	29,FRAME_DSISR+8(1);					\
956	stw	30,FRAME_SRR0+8(1);					\
957	stw	31,FRAME_SRR1+8(1)
958
959#define	FRAME_LEAVE(savearea)						\
960/* Now restore regs: */							\
961	lwz	2,FRAME_SRR0+8(1);					\
962	lwz	3,FRAME_SRR1+8(1);					\
963	lwz	4,FRAME_CTR+8(1);					\
964	lwz	5,FRAME_XER+8(1);					\
965	lwz	6,FRAME_LR+8(1);					\
966	lwz	7,FRAME_CR+8(1);					\
967	stw	2,savearea(0);						\
968	stw	3,savearea+4(0);					\
969	mtctr	4;							\
970	mtxer	5;							\
971	mtlr	6;							\
972	mtsprg	1,7;			/* save cr */			\
973	lmw	2,FRAME_2+8(1);						\
974	lwz	0,FRAME_0+8(1);						\
975	lwz	1,FRAME_1+8(1);						\
976	mtsprg	2,2;			/* save r2 & r3 */		\
977	mtsprg	3,3;							\
978/* Disable translation, machine check and recoverability: */		\
979	mfmsr	2;							\
980	andi.	2,2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l;			\
981	mtmsr	2;							\
982	isync;								\
983/* Decide whether we return to user mode: */				\
984	lwz	3,savearea+4(0);					\
985	mtcr	3;							\
986	bc	4,17,1f;		/* branch if PSL_PR is false */	\
987/* Restore user & kernel access SR: */					\
988	lis	2,_C_LABEL(curpm)@ha;	/* get real address of pmap */	\
989	lwz	2,_C_LABEL(curpm)@l(2);					\
990	lwz	3,PM_USRSR(2);						\
991	mtsr	USER_SR,3;						\
992	lwz	3,PM_KERNELSR(2);					\
993	mtsr	KERNEL_SR,3;						\
9941:	mfsprg	2,1;			/* restore cr */		\
995	mtcr	2;							\
996	lwz	2,savearea(0);						\
997	lwz	3,savearea+4(0);					\
998	mtsrr0	2;							\
999	mtsrr1	3;							\
1000	mfsprg	2,2;			/* restore r2 & r3 */		\
1001	mfsprg	3,3
1002
1003/*
1004 * Preamble code for DSI/ISI traps
1005 */
1006disitrap:
1007	lmw	30,disisave(0)
1008	stmw	30,tempsave(0)
1009	lmw	30,disisave+8(0)
1010	stmw	30,tempsave+8(0)
1011	mfdar	30
1012	mfdsisr	31
1013	stmw	30,tempsave+16(0)
1014realtrap:
1015/* Test whether we already had PR set */
1016	mfsrr1	1
1017	mtcr	1
1018	mfsprg	1,1			/* restore SP (might have been
1019					   overwritten) */
1020	bc	4,17,s_trap		/* branch if PSL_PR is false */
1021	lis	1,_C_LABEL(curpcb)@ha
1022	lwz	1,_C_LABEL(curpcb)@l(1)
1023	addi	1,1,USPACE		/* stack is top of user struct */
1024
1025/*
1026 * Now the common trap catching code.
1027 */
1028s_trap:
1029/* First have to enable KERNEL mapping */
1030	lis	31,KERNEL_SEGMENT@h
1031	ori	31,31,KERNEL_SEGMENT@l
1032	mtsr	KERNEL_SR,31
1033	FRAME_SETUP(tempsave)
1034/* Now we can recover interrupts again: */
1035	mfmsr	7
1036	ori	7,7,(PSL_EE|PSL_ME|PSL_RI)@l
1037	mtmsr	7
1038	isync
1039/* Call C trap code: */
1040trapagain:
1041	addi	3,1,8
1042	bl	_C_LABEL(trap)
1043trapexit:
1044/* Disable interrupts: */
1045	mfmsr	3
1046	andi.	3,3,~PSL_EE@l
1047	mtmsr	3
1048/* Test AST pending: */
1049	lwz	5,FRAME_SRR1+8(1)
1050	mtcr	5
1051	bc	4,17,1f			/* branch if PSL_PR is false */
1052	lis	3,_C_LABEL(astpending)@ha
1053	lwz	4,_C_LABEL(astpending)@l(3)
1054	andi.	4,4,1
1055	beq	1f
1056	li	6,EXC_AST
1057	stw	6,FRAME_EXC+8(1)
1058	b	trapagain
10591:
1060	FRAME_LEAVE(tempsave)
1061	rfi
1062
1063/*
1064 * Child comes here at the end of a fork.
1065 * Mostly similar to the above.
1066 */
1067	.globl	_C_LABEL(fork_trampoline)
1068_C_LABEL(fork_trampoline):
1069	xor	3,3,3
1070	bl	_C_LABEL(lcsplx)
1071	mtlr	31
1072	mr	3,30
1073	blrl				/* jump indirect to r31 */
1074	b	trapexit
1075
1076/*
1077 * DSI second stage fault handler
1078 */
1079s_dsitrap:
1080	mfdsisr	31			/* test whether this may be a
1081					   spill fault */
1082	mtcr	31
1083	mtsprg	1,1			/* save SP */
1084	bc	4,1,disitrap		/* branch if table miss is false */
1085	lis	1,spillstk+SPILLSTK@ha
1086	addi	1,1,spillstk+SPILLSTK@l	/* get spill stack */
1087	stwu	1,-52(1)
1088	stw	0,48(1)			/* save non-volatile registers */
1089	stw	3,44(1)
1090	stw	4,40(1)
1091	stw	5,36(1)
1092	stw	6,32(1)
1093	stw	7,28(1)
1094	stw	8,24(1)
1095	stw	9,20(1)
1096	stw	10,16(1)
1097	stw	11,12(1)
1098	stw	12,8(1)
1099	mflr	30			/* save trap type */
1100	mfctr	31			/* & CTR */
1101	mfdar	3
1102s_pte_spill:
1103	bl	_C_LABEL(pmap_pte_spill) /* try a spill */
1104	or.	3,3,3
1105	mtctr	31			/* restore CTR */
1106	mtlr	30			/* and trap type */
1107	mfsprg	31,2			/* get saved XER */
1108	mtxer	31			/* restore XER */
1109	lwz	12,8(1)			/* restore non-volatile registers */
1110	lwz	11,12(1)
1111	lwz	10,16(1)
1112	lwz	9,20(1)
1113	lwz	8,24(1)
1114	lwz	7,28(1)
1115	lwz	6,32(1)
1116	lwz	5,36(1)
1117	lwz	4,40(1)
1118	lwz	3,44(1)
1119	lwz	0,48(1)
1120	beq	disitrap
1121	mfsprg	1,1			/* restore SP */
1122	mtcr	29			/* restore CR */
1123	mtlr	28			/* restore LR */
1124	lmw	28,disisave(0)		/* restore r28-r31 */
1125	rfi				/* return to trapped code */
1126
1127/*
1128 * ISI second stage fault handler
1129 */
1130s_isitrap:
1131	mfsrr1	31			/* test whether this may be a
1132					   spill fault */
1133	mtcr	31
1134	mtsprg	1,1			/* save SP */
1135	bc	4,1,disitrap		/* branch if table miss is false */
1136	lis	1,spillstk+SPILLSTK@ha
1137	addi	1,1,spillstk+SPILLSTK@l	/* get spill stack */
1138	stwu	1,-52(1)
1139	stw	0,48(1)			/* save non-volatile registers */
1140	stw	3,44(1)
1141	stw	4,40(1)
1142	stw	5,36(1)
1143	stw	6,32(1)
1144	stw	7,28(1)
1145	stw	8,24(1)
1146	stw	9,20(1)
1147	stw	10,16(1)
1148	stw	11,12(1)
1149	stw	12,8(1)
1150	mfxer	30			/* save XER */
1151	mtsprg	2,30
1152	mflr	30			/* save trap type */
1153	mfctr	31			/* & ctr */
1154	mfsrr0	3
1155	b	s_pte_spill		/* above */
1156
1157/*
1158 * External interrupt second level handler
1159 */
1160#define	INTRENTER							\
1161/* Save non-volatile registers: */					\
1162	stwu	1,-88(1);		/* temporarily */		\
1163	stw	0,84(1);						\
1164	mfsprg	0,1;			/* get original SP */		\
1165	stw	0,0(1);			/* and store it */		\
1166	stw	3,80(1);						\
1167	stw	4,76(1);						\
1168	stw	5,72(1);						\
1169	stw	6,68(1);						\
1170	stw	7,64(1);						\
1171	stw	8,60(1);						\
1172	stw	9,56(1);						\
1173	stw	10,52(1);						\
1174	stw	11,48(1);						\
1175	stw	12,44(1);						\
1176	stw	28,40(1);		/* saved LR */			\
1177	stw	29,36(1);		/* saved CR */			\
1178	stw	30,32(1);		/* saved XER */			\
1179	lmw	28,tempsave(0);		/* restore r28-r31 */		\
1180	mfctr	6;							\
1181	lis	5,_C_LABEL(intr_depth)@ha;				\
1182	lwz	5,_C_LABEL(intr_depth)@l(5);				\
1183	mfsrr0	4;							\
1184	mfsrr1	3;							\
1185	stw	6,28(1);						\
1186	stw	5,20(1);						\
1187	stw	4,12(1);						\
1188	stw	3,8(1);							\
1189/* interrupts are recoverable here, and enable translation */		\
1190	lis	3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@h;			\
1191	ori	3,3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@l;		\
1192	mtsr	KERNEL_SR,3;						\
1193	mfmsr	5;							\
1194	ori	5,5,(PSL_IR|PSL_DR|PSL_RI);				\
1195	mtmsr	5;							\
1196	isync
1197
1198	.globl	_C_LABEL(extint_call)
1199extintr:
1200	INTRENTER
1201_C_LABEL(extint_call):
1202/*
1203	lis	0,intrhand@h
1204	ori	0,0,intrhand@l
1205	mtlr	0
1206	blr*/
1207	bl	_C_LABEL(intrhand)
1208/*	bl	_C_LABEL(extint_call)*/	/* to be filled in later */
1209
1210intr_exit:
1211/* Disable interrupts (should already be disabled) and MMU here: */
1212	mfmsr	3
1213	andi.	3,3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l
1214	mtmsr	3
1215	isync
1216/* restore possibly overwritten registers: */
1217	lwz	12,44(1)
1218	lwz	11,48(1)
1219	lwz	10,52(1)
1220	lwz	9,56(1)
1221	lwz	8,60(1)
1222	lwz	7,64(1)
1223	lwz	6,8(1)
1224	lwz	5,12(1)
1225	lwz	4,28(1)
1226	lwz	3,32(1)
1227	mtsrr1	6
1228	mtsrr0	5
1229	mtctr	4
1230	mtxer	3
1231/* Returning to user mode? */
1232	mtcr	6			/* saved SRR1 */
1233	bc	4,17,1f			/* branch if PSL_PR is false */
1234	lis	3,_C_LABEL(curpm)@ha	/* get current pmap real address */
1235	lwz	3,_C_LABEL(curpm)@l(3)
1236	lwz	3,PM_KERNELSR(3)
1237	mtsr	KERNEL_SR,3		/* Restore kernel SR */
1238	lis	3,_C_LABEL(astpending)@ha /* Test AST pending */
1239	lwz	4,_C_LABEL(astpending)@l(3)
1240	andi.	4,4,1
1241	beq	1f
1242/* Setup for entry to realtrap: */
1243	lwz	3,0(1)			/* get saved SP */
1244	mtsprg	1,3
1245	li	6,EXC_AST
1246	stmw	28,tempsave(0)		/* establish tempsave again */
1247	mtlr	6
1248	lwz	28,40(1)		/* saved LR */
1249	lwz	29,36(1)		/* saved CR */
1250	lwz	6,68(1)
1251	lwz	5,72(1)
1252	lwz	4,76(1)
1253	lwz	3,80(1)
1254	lwz	0,84(1)
1255	lis	30,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */
1256	lwz	31,_C_LABEL(intr_depth)@l(30)
1257	addi	31,31,-1
1258	stw	31,_C_LABEL(intr_depth)@l(30)
1259	b	realtrap
12601:
1261/* Here is the normal exit of extintr: */
1262	lwz	5,36(1)
1263	lwz	6,40(1)
1264	mtcr	5
1265	mtlr	6
1266	lwz	6,68(1)
1267	lwz	5,72(1)
1268	lis	3,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */
1269	lwz	4,_C_LABEL(intr_depth)@l(3)
1270	addi	4,4,-1
1271	stw	4,_C_LABEL(intr_depth)@l(3)
1272	lwz	4,76(1)
1273	lwz	3,80(1)
1274	lwz	0,84(1)
1275	lwz	1,0(1)
1276	rfi
1277
1278/*
1279 * Decrementer interrupt second level handler
1280 */
1281decrintr:
1282	INTRENTER
1283	addi	3,1,8			/* intr frame */
1284	/*bl	_C_LABEL(decr_intr)*/
1285	b	intr_exit
1286
1287#ifdef DDB
1288/*
1289 * Deliberate entry to ddbtrap
1290 */
1291	.globl	_C_LABEL(ddb_trap)
1292_C_LABEL(ddb_trap):
1293	mtsprg	1,1
1294	mfmsr	3
1295	mtsrr1	3
1296	andi.	3,3,~(PSL_EE|PSL_ME)@l
1297	mtmsr	3			/* disable interrupts */
1298	isync
1299	stmw	28,ddbsave(0)
1300	mflr	28
1301	li	29,EXC_BPT
1302	mtlr	29
1303	mfcr	29
1304	mtsrr0	28
1305
1306/*
1307 * Now the ddb trap catching code.
1308 */
1309ddbtrap:
1310	FRAME_SETUP(ddbsave)
1311/* Call C trap code: */
1312	addi	3,1,8
1313	bl	_C_LABEL(ddb_trap_glue)
1314	or.	3,3,3
1315	bne	ddbleave
1316/* This wasn't for DDB, so switch to real trap: */
1317	lwz	3,FRAME_EXC+8(1)	/* save exception */
1318	stw	3,ddbsave+8(0)
1319	FRAME_LEAVE(ddbsave)
1320	mtsprg	1,1			/* prepare for entrance to realtrap */
1321	stmw	28,tempsave(0)
1322	mflr	28
1323	mfcr	29
1324	lwz	31,ddbsave+8(0)
1325	mtlr	31
1326	b	realtrap
1327ddbleave:
1328	FRAME_LEAVE(ddbsave)
1329	rfi
1330#endif /* DDB */
1331
1332#ifdef IPKDB
1333/*
1334 * Deliberate entry to ipkdbtrap
1335 */
1336	.globl	_C_LABEL(ipkdb_trap)
1337_C_LABEL(ipkdb_trap):
1338	mtsprg	1,1
1339	mfmsr	3
1340	mtsrr1	3
1341	andi.	3,3,~(PSL_EE|PSL_ME)@l
1342	mtmsr	3			/* disable interrupts */
1343	isync
1344	stmw	28,ipkdbsave(0)
1345	mflr	28
1346	li	29,EXC_BPT
1347	mtlr	29
1348	mfcr	29
1349	mtsrr0	28
1350
1351/*
1352 * Now the ipkdb trap catching code.
1353 */
1354ipkdbtrap:
1355	FRAME_SETUP(ipkdbsave)
1356/* Call C trap code: */
1357	addi	3,1,8
1358	bl	_C_LABEL(ipkdb_trap_glue)
1359	or.	3,3,3
1360	bne	ipkdbleave
1361/* This wasn't for IPKDB, so switch to real trap: */
1362	lwz	3,FRAME_EXC+8(1)	/* save exception */
1363	stw	3,ipkdbsave+8(0)
1364	FRAME_LEAVE(ipkdbsave)
1365	mtsprg	1,1			/* prepare for entrance to realtrap */
1366	stmw	28,tempsave(0)
1367	mflr	28
1368	mfcr	29
1369	lwz	31,ipkdbsave+8(0)
1370	mtlr	31
1371	b	realtrap
1372ipkdbleave:
1373	FRAME_LEAVE(ipkdbsave)
1374	rfi
1375
1376ipkdbfault:
1377	ba	_ipkdbfault
1378_ipkdbfault:
1379	mfsrr0	3
1380	addi	3,3,4
1381	mtsrr0	3
1382	li	3,-1
1383	rfi
1384
1385/*
1386 * int ipkdbfbyte(unsigned char *p)
1387 */
1388	.globl	_C_LABEL(ipkdbfbyte)
1389_C_LABEL(ipkdbfbyte):
1390	li	9,EXC_DSI		/* establish new fault routine */
1391	lwz	5,0(9)
1392	lis	6,ipkdbfault@ha
1393	lwz	6,ipkdbfault@l(6)
1394	stw	6,0(9)
1395#ifdef	IPKDBUSERHACK
1396	lis	8,_C_LABEL(ipkdbsr)@ha
1397	lwz	8,_C_LABEL(ipkdbsr)@l(8)
1398	mtsr	USER_SR,8
1399	isync
1400#endif
1401	dcbst	0,9			/* flush data... */
1402	sync
1403	icbi	0,9			/* and instruction caches */
1404	lbz	3,0(3)			/* fetch data */
1405	stw	5,0(9)			/* restore previous fault handler */
1406	dcbst	0,9			/* and flush data... */
1407	sync
1408	icbi	0,9			/* and instruction caches */
1409	blr
1410
1411/*
1412 * int ipkdbsbyte(unsigned char *p, int c)
1413 */
1414	.globl	_C_LABEL(ipkdbsbyte)
1415_C_LABEL(ipkdbsbyte):
1416	li	9,EXC_DSI		/* establish new fault routine */
1417	lwz	5,0(9)
1418	lis	6,ipkdbfault@ha
1419	lwz	6,ipkdbfault@l(6)
1420	stw	6,0(9)
1421#ifdef	IPKDBUSERHACK
1422	lis	8,_C_LABEL(ipkdbsr)@ha
1423	lwz	8,_C_LABEL(ipkdbsr)@l(8)
1424	mtsr	USER_SR,8
1425	isync
1426#endif
1427	dcbst	0,9			/* flush data... */
1428	sync
1429	icbi	0,9			/* and instruction caches */
1430	mr	6,3
1431	xor	3,3,3
1432	stb	4,0(6)
1433	dcbst	0,6			/* Now do appropriate flushes
1434					   to data... */
1435	sync
1436	icbi	0,6			/* and instruction caches */
1437	stw	5,0(9)			/* restore previous fault handler */
1438	dcbst	0,9			/* and flush data... */
1439	sync
1440	icbi	0,9			/* and instruction caches */
1441	blr
1442#endif	/* IPKDB */
1443
1444/*
1445 * int setfault()
1446 *
1447 * Similar to setjmp to setup for handling faults on accesses to user memory.
1448 * Any routine using this may only call bcopy, either the form below,
1449 * or the (currently used) C code optimized, so it doesn't use any non-volatile
1450 * registers.
1451 */
1452	.globl	_C_LABEL(setfault)
1453_C_LABEL(setfault):
1454	mflr	0
1455	mfcr	12
1456	lis	4,_C_LABEL(curpcb)@ha
1457	lwz	4,_C_LABEL(curpcb)@l(4)
1458	stw	3,PCB_FAULT(4)
1459	stw	0,0(3)
1460	stw	1,4(3)
1461	stw	2,8(3)
1462	stmw	12,12(3)
1463	xor	3,3,3
1464	blr
1465
1466