xref: /freebsd/sys/powerpc/aim/locore.S (revision 5521ff5a4d1929056e7ffc982fac3341ca54df7c)
1/* $FreeBSD$ */
2/* $NetBSD: locore.S,v 1.24 2000/05/31 05:09:17 thorpej Exp $ */
3
4/*
5 * Copyright (C) 2001 Benno Rice
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 *
17 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28/*
29 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
30 * Copyright (C) 1995, 1996 TooLs GmbH.
31 * All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 *    notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 *    notice, this list of conditions and the following disclaimer in the
40 *    documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 *    must display the following acknowledgement:
43 *	This product includes software developed by TooLs GmbH.
44 * 4. The name of TooLs GmbH may not be used to endorse or promote products
45 *    derived from this software without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
49 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
51 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
52 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
53 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
54 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
55 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
56 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57 */
58
59#include "opt_ddb.h"
60#include "opt_ipkdb.h"
61#include "assym.s"
62
63#include <sys/syscall.h>
64
65#include <machine/trap.h>
66#include <machine/param.h>
67#include <machine/pmap.h>
68#include <machine/psl.h>
69#include <machine/asm.h>
70
71/*
72 * Some instructions gas doesn't understand (yet?)
73 */
74#define	bdneq	bdnzf 2,
75
76/*
77 * Globals
78 */
79	.data
80GLOBAL(tmpstk)
81	.space	8208
82GLOBAL(esym)
83	.long	0			/* end of symbol table */
84GLOBAL(proc0paddr)
85	.long	0			/* proc0 p_addr */
86GLOBAL(PTmap)
87	.long	0			/* PTmap */
88
89GLOBAL(intrnames)
90	.asciz	"irq0", "irq1", "irq2", "irq3"
91	.asciz	"irq4", "irq5", "irq6", "irq7"
92	.asciz	"irq8", "irq9", "irq10", "irq11"
93	.asciz	"irq12", "irq13", "irq14", "irq15"
94	.asciz	"irq16", "irq17", "irq18", "irq19"
95	.asciz	"irq20", "irq21", "irq22", "irq23"
96	.asciz	"irq24", "irq25", "irq26", "irq27"
97	.asciz	"irq28", "irq29", "irq30", "irq31"
98	.asciz	"irq32", "irq33", "irq34", "irq35"
99	.asciz	"irq36", "irq37", "irq38", "irq39"
100	.asciz	"irq40", "irq41", "irq42", "irq43"
101	.asciz	"irq44", "irq45", "irq46", "irq47"
102	.asciz	"irq48", "irq49", "irq50", "irq51"
103	.asciz	"irq52", "irq53", "irq54", "irq55"
104	.asciz	"irq56", "irq57", "irq58", "irq59"
105	.asciz	"irq60", "irq61", "irq62", "irq63"
106	.asciz	"clock", "softclock", "softnet", "softserial"
107GLOBAL(eintrnames)
108	.align	4
109GLOBAL(intrcnt)
110	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
111	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
112	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
113	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
114	.long	0,0,0,0
115GLOBAL(eintrcnt)
116
117GLOBAL(ofmsr)
118	.long	0			/* msr used in Open Firmware */
119
120GLOBAL(powersave)
121	.long	0
122
123/*
124 * File-scope for locore.S
125 */
126idle_u:
127	.long	0			/* fake uarea during idle after exit */
128openfirmware_entry:
129	.long	0			/* openfirmware entry point */
130srsave:
131	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
132
133/*
134 * This symbol is here for the benefit of kvm_mkdb, and is supposed to
135 * mark the start of kernel text.
136 */
137	.text
138	.globl	kernel_text
139kernel_text:
140
141/*
142 * Startup entry.  Note, this must be the first thing in the text
143 * segment!
144 */
145	.text
146	.globl	__start
147__start:
148#ifdef	FIRMWORKSBUGS
149	mfmsr	0
150	andi.	0,0,PSL_IR|PSL_DR
151	beq	1f
152
153	bl	ofwr_init
1541:
155#endif
156	li	8,0
157	li	9,0x100
158	mtctr	9
1591:
160	dcbf	0,8
161	icbi	0,8
162	addi	8,8,0x20
163	bdnz	1b
164	sync
165	isync
166
167	mtibatu	0,0
168	mtibatu	1,0
169	mtibatu	2,0
170	mtibatu	3,0
171	mtdbatu	0,0
172	mtdbatu	1,0
173	mtdbatu	2,0
174	mtdbatu	3,0
175
176	li	9,0x12
177	mtibatl	0,9
178	mtdbatl	0,9
179	li	9,0x1ffe
180	mtibatu	0,9
181	mtdbatu	0,9
182	isync
183
184	lis	8,openfirmware_entry@ha
185	stw	5,openfirmware_entry@l(8) /* save client interface handler */
186	mr	3,5
187
188	lis	1,tmpstk@ha
189	addi	1,1,tmpstk@l
190	addi	1,1,8192
191
192	mfmsr	0
193	lis	9,ofmsr@ha
194	stw	0,ofmsr@l(9)
195
196	bl	OF_init
197
198	lis	4,end@ha
199	addi	4,4,end@l
200	mr	5,4
201	li	9,PAGE_MASK
202	add	4,4,9
203	andc	4,4,9
204	lis	9,OF_buf@ha
205	stw	4,OF_buf@l(9)
206	addi	4,4,PAGE_SIZE
207	lis	9,proc0paddr@ha
208	stw	4,proc0paddr@l(9)
209	addi	4,4,USPACE-FRAMELEN
210	mr	1,4
211	xor	0,0,0
212	stwu	0,-16(1)
213
214	lis	3,kernel_text@ha
215	addi	3,3,kernel_text@l
216#if 0
217	mr	5,6
218#endif
219
220	bl	powerpc_init
221	bl	mi_startup
222	b	OF_exit
223
224#if 0 /* XXX: We may switch back to this in the future. */
225/*
226 * OpenFirmware entry point
227 */
228ENTRY(openfirmware)
229	mflr	0			/* save return address */
230	stw	0,4(1)
231	stwu	1,-16(1)		/* setup stack frame */
232
233	mfmsr	4			/* save msr */
234	stw	4,8(1)
235
236	lis	4,openfirmware_entry@ha	/* get firmware entry point */
237	lwz	4,openfirmware_entry@l(4)
238	mtlr	4
239
240	li	0,0			/* clear battable translations */
241	mtdbatu	2,0
242	mtdbatu	3,0
243	mtibatu	2,0
244	mtibatu	3,0
245
246	lis	4,ofmsr@ha		/* Open Firmware msr */
247	lwz	4,ofmsr@l(4)
248	mtmsr	4
249	isync
250
251	lis	4,srsave@ha		/* save old SR */
252	addi	4,4,srsave@l
253	li	5,0
2541:	mfsrin	0,5
255	stw	0,0(4)
256	addi	4,4,4
257	addis	5,5,0x10000000@h
258	cmpwi	5,0
259	bne	1b
260
261	lis	4,ofw_pmap@ha		/* load OFW SR */
262	addi	4,4,ofw_pmap@l
263	lwz	0,PM_KERNELSR(4)
264	cmpwi	0,0			/* pm_sr[KERNEL_SR] == 0? */
265	beq	2f			/* then skip (not initialized yet) */
266	li	5,0
2671:	lwz	0,0(4)
268	mtsrin	0,5
269	addi	4,4,4
270	addis	5,5,0x10000000@h
271	cmpwi	5,0
272	bne	1b
2732:
274	blrl				/* call Open Firmware */
275
276	mfmsr	4
277	li	5,PSL_IR|PSL_DR
278	andc 	4,4,5
279	mtmsr	4
280	isync
281
282	lis	4,srsave@ha		/* restore saved SR */
283	addi	4,4,srsave@l
284	li	5,0
2851:	lwz	0,0(4)
286	mtsrin	0,5
287	addi	4,4,4
288	addis	5,5,0x10000000@h
289	cmpwi	5,0
290	bne	1b
291
292	lwz	4,8(1)			/* restore msr */
293	mtmsr	4
294	isync
295
296	lwz	1,0(1)			/* and return */
297	lwz	0,4(1)
298	mtlr	0
299	blr
300#endif
301
302/*
303 * Switch to/from OpenFirmware real mode stack
304 *
305 * Note: has to be called as the very first thing in OpenFirmware interface
306 * routines.
307 * E.g.:
308 * int
309 * OF_xxx(arg1, arg2)
310 * type arg1, arg2;
311 * {
312 *	static struct {
313 *		char *name;
314 *		int nargs;
315 *		int nreturns;
316 *		char *method;
317 *		int arg1;
318 *		int arg2;
319 *		int ret;
320 *	} args = {
321 *		"xxx",
322 *		2,
323 *		1,
324 *	};
325 *
326 *	ofw_stack();
327 *	args.arg1 = arg1;
328 *	args.arg2 = arg2;
329 *	if (openfirmware(&args) < 0)
330 *		return -1;
331 *	return args.ret;
332 * }
333 */
334
335	.local	firmstk
336	.comm	firmstk,PAGE_SIZE,8
337
338ENTRY(ofw_stack)
339	mfmsr	8			/* turn off interrupts */
340	andi.	0,8,~(PSL_EE|PSL_RI)@l
341	mtmsr	0
342	stw	8,4(1)			/* abuse return address slot */
343
344	lwz	5,0(1)			/* get length of stack frame */
345	subf	5,1,5
346
347	lis	7,firmstk+PAGE_SIZE-8@ha
348	addi	7,7,firmstk+PAGE_SIZE-8@l
349	lis	6,ofw_back@ha
350	addi	6,6,ofw_back@l
351	subf	4,5,7			/* make room for stack frame on
352					   new stack */
353	stw	6,-4(7)			/* setup return pointer */
354	stwu	1,-8(7)
355
356	stw	7,-8(4)
357
358	addi	3,1,8
359	addi	1,4,-8
360	subi	5,5,8
361
362	cmpw	3,4
363	beqlr
364
365	mr	0,5
366	addi	5,5,-1
367	cmpwi	0,0
368	beqlr
369
3701:	lwz	0,0(3)
371	stw	0,0(4)
372	addi	3,3,1
373	addi	4,4,1
374	mr	0,5
375	addi	5,5,-1
376	cmpwi	0,0
377	bne	1b
378	blr
379
380ofw_back:
381	lwz	1,0(1)			/* get callers original stack pointer */
382
383	lwz	0,4(1)			/* get saved msr from abused slot */
384	mtmsr	0
385
386	lwz	1,0(1)			/* return */
387	lwz	0,4(1)
388	mtlr	0
389	blr
390
391/*
392 * Data used during primary/secondary traps/interrupts
393 */
394#define	tempsave	0x2e0	/* primary save area for trap handling */
395#define	disisave	0x3e0	/* primary save area for dsi/isi traps */
396
397#define	INTSTK	(8*1024)	/* 8K interrupt stack */
398	.data
399	.align	4
400intstk:
401	.space	INTSTK		/* interrupt stack */
402
403GLOBAL(intr_depth)
404	.long	-1		/* in-use marker */
405
406#define	SPILLSTK 1024		/* 1K spill stack */
407
408	.comm	spillstk,SPILLSTK,8
409
410/*
411 * This code gets copied to all the trap vectors
412 * (except ISI/DSI, ALI, the interrupts, and possibly the debugging
413 * traps when using IPKDB).
414 */
415	.text
416	.globl	trapcode,trapsize
417trapcode:
418	mtsprg	1,1			/* save SP */
419	stmw	28,tempsave(0)		/* free r28-r31 */
420	mflr	28			/* save LR */
421	mfcr	29			/* save CR */
422/* Test whether we already had PR set */
423	mfsrr1	31
424	mtcr	31
425	bc	4,17,1f			/* branch if PSL_PR is clear */
426	mfsprg	1,0
427	lwz	1,GD_CURPCB(1)
428	addi	1,1,USPACE		/* stack is top of user struct */
4291:
430	bla	s_trap
431trapsize = .-trapcode
432
433/*
434 * For ALI: has to save DSISR and DAR
435 */
436	.globl	alitrap,alisize
437alitrap:
438	mtsprg	1,1			/* save SP */
439	stmw	28,tempsave(0)		/* free r28-r31 */
440	mfdar	30
441	mfdsisr	31
442	stmw	30,tempsave+16(0)
443	mflr	28			/* save LR */
444	mfcr	29			/* save CR */
445/* Test whether we already had PR set */
446	mfsrr1	31
447	mtcr	31
448	bc	4,17,1f			/* branch if PSL_PR is clear */
449	mfsprg	1,0
450	lwz	1,GD_CURPCB(1)
451	addi	1,1,USPACE		/* stack is top of user struct */
4521:
453	bla	s_trap
454alisize = .-alitrap
455
456/*
457 * Similar to the above for DSI
458 * Has to handle BAT spills
459 * and standard pagetable spills
460 */
461	.globl	dsitrap,dsisize
462dsitrap:
463	stmw	28,disisave(0)		/* free r28-r31 */
464	mfcr	29			/* save CR */
465	mfxer	30			/* save XER */
466	mtsprg	2,30			/* in SPRG2 */
467	mfsrr1	31			/* test kernel mode */
468	mtcr	31
469	bc	12,17,1f		/* branch if PSL_PR is set */
470	mfdar	31			/* get fault address */
471	rlwinm	31,31,7,25,28		/* get segment * 8 */
472
473	/* get batu */
474	addis	31,31,battable@ha
475	lwz	30,battable@l(31)
476	mtcr	30
477	bc	4,30,1f			/* branch if supervisor valid is
478					   false */
479	/* get batl */
480	lwz	31,battable+4@l(31)
481/* We randomly use the highest two bat registers here */
482	mftb	28
483	andi.	28,28,1
484	bne	2f
485	mtdbatu	2,30
486	mtdbatl	2,31
487	b	3f
4882:
489	mtdbatu	3,30
490	mtdbatl	3,31
4913:
492	mfsprg	30,2			/* restore XER */
493	mtxer	30
494	mtcr	29			/* restore CR */
495	lmw	28,disisave(0)		/* restore r28-r31 */
496	rfi				/* return to trapped code */
4971:
498	mflr	28			/* save LR */
499	bla	s_dsitrap
500dsisize = .-dsitrap
501
502/*
503 * Similar to the above for ISI
504 */
505	.globl	isitrap,isisize
506isitrap:
507	stmw	28,disisave(0)		/* free r28-r31 */
508	mflr	28			/* save LR */
509	mfcr	29			/* save CR */
510	mfsrr1	31			/* test kernel mode */
511	mtcr	31
512	bc	12,17,1f		/* branch if PSL_PR is set */
513	mfsrr0	31			/* get fault address */
514	rlwinm	31,31,7,25,28		/* get segment * 8 */
515
516	/* get batu */
517	addis	31,31,battable@ha
518	lwz	30,battable@l(31)
519	mtcr	30
520	bc	4,30,1f			/* branch if supervisor valid is
521					   false */
522	mtibatu	3,30
523
524	/* get batl */
525	lwz	30,battable+4@l(31)
526	mtibatl	3,30
527
528	mtcr	29			/* restore CR */
529	lmw	28,disisave(0)		/* restore r28-r31 */
530	rfi				/* return to trapped code */
5311:
532	bla	s_isitrap
533isisize = .-isitrap
534
535/*
536 * This one for the external interrupt handler.
537 */
538	.globl	extint,extsize
539extint:
540	mtsprg	1,1			/* save SP */
541	stmw	28,tempsave(0)		/* free r28-r31 */
542	mflr	28			/* save LR */
543	mfcr	29			/* save CR */
544	mfxer	30			/* save XER */
545	lis	1,intstk+INTSTK@ha	/* get interrupt stack */
546	addi	1,1,intstk+INTSTK@l
547	lwz	31,0(1)			/* were we already running on intstk? */
548	addic.	31,31,1
549	stw	31,0(1)
550	beq	1f
551	mfsprg	1,1			/* yes, get old SP */
5521:
553	ba	extintr
554extsize = .-extint
555
556/*
557 * And this one for the decrementer interrupt handler.
558 */
559	.globl	decrint,decrsize
560decrint:
561	mtsprg	1,1			/* save SP */
562	stmw	28,tempsave(0)		/* free r28-r31 */
563	mflr	28			/* save LR */
564	mfcr	29			/* save CR */
565	mfxer	30			/* save XER */
566	lis	1,intstk+INTSTK@ha	/* get interrupt stack */
567	addi	1,1,intstk+INTSTK@l
568	lwz	31,0(1)			/* were we already running on intstk? */
569	addic.	31,31,1
570	stw	31,0(1)
571	beq	1f
572	mfsprg	1,1			/* yes, get old SP */
5731:
574	ba	decrintr
575decrsize = .-decrint
576
577/*
578 * Now the tlb software load for 603 processors:
579 * (Code essentially from the 603e User Manual, Chapter 5, but
580 * corrected a lot.)
581 */
582#define	DMISS	976
583#define	DCMP	977
584#define	HASH1	978
585#define	HASH2	979
586#define	IMISS	980
587#define	ICMP	981
588#define	RPA	982
589
590	.globl	tlbimiss,tlbimsize
591tlbimiss:
592	mfspr	2,HASH1			/* get first pointer */
593	li	1,8
594	mfctr	0			/* save counter */
595	mfspr	3,ICMP			/* get first compare value */
596	addi	2,2,-8			/* predec pointer */
5971:
598	mtctr	1			/* load counter */
5992:
600	lwzu	1,8(2)			/* get next pte */
601	cmpl	0,1,3			/* see if found pte */
602	bdneq	2b			/* loop if not eq */
603	bne	3f			/* not found */
604	lwz	1,4(2)			/* load tlb entry lower word */
605	andi.	3,1,8			/* check G-bit */
606	bne	4f			/* if guarded, take ISI */
607	mtctr	0			/* restore counter */
608	mfspr	0,IMISS			/* get the miss address for the tlbli */
609	mfsrr1	3			/* get the saved cr0 bits */
610	mtcrf	0x80,3			/* and restore */
611	ori	1,1,0x100		/* set the reference bit */
612	mtspr	RPA,1			/* set the pte */
613	srwi	1,1,8			/* get byte 7 of pte */
614	tlbli	0			/* load the itlb */
615	stb	1,6(2)			/* update page table */
616	rfi
617
6183:	/* not found in pteg */
619	andi.	1,3,0x40		/* have we already done second hash? */
620	bne	5f
621	mfspr	2,HASH2			/* get the second pointer */
622	ori	3,3,0x40		/* change the compare value */
623	li	1,8
624	addi	2,2,-8			/* predec pointer */
625	b	1b
6264:	/* guarded */
627	mfsrr1	3
628	andi.	2,3,0xffff		/* clean upper srr1 */
629	oris	2,2,0x8000000@h		/* set srr<4> to flag prot violation */
630	b	6f
6315:	/* not found anywhere */
632	mfsrr1	3
633	andi.	2,3,0xffff		/* clean upper srr1 */
634	oris	2,2,0x40000000@h	/* set srr1<1> to flag pte not found */
6356:
636	mtctr	0			/* restore counter */
637	mtsrr1	2
638	mfmsr	0
639	xoris	0,0,0x20000@h		/* flip the msr<tgpr> bit */
640	mtcrf	0x80,3			/* restore cr0 */
641	mtmsr	0			/* now with native gprs */
642	isync
643	ba	EXC_ISI
644tlbimsize = .-tlbimiss
645
646	.globl	tlbdlmiss,tlbdlmsize
647tlbdlmiss:
648	mfspr	2,HASH1			/* get first pointer */
649	li	1,8
650	mfctr	0			/* save counter */
651	mfspr	3,DCMP			/* get first compare value */
652	addi	2,2,-8			/* predec pointer */
6531:
654	mtctr	1			/* load counter */
6552:
656	lwzu	1,8(2)			/* get next pte */
657	cmpl	0,1,3			/* see if found pte */
658	bdneq	2b			/* loop if not eq */
659	bne	3f			/* not found */
660	lwz	1,4(2)			/* load tlb entry lower word */
661	mtctr	0			/* restore counter */
662	mfspr	0,DMISS			/* get the miss address for the tlbld */
663	mfsrr1	3			/* get the saved cr0 bits */
664	mtcrf	0x80,3			/* and restore */
665	ori	1,1,0x100		/* set the reference bit */
666	mtspr	RPA,1			/* set the pte */
667	srwi	1,1,8			/* get byte 7 of pte */
668	tlbld	0			/* load the dtlb */
669	stb	1,6(2)			/* update page table */
670	rfi
671
6723:	/* not found in pteg */
673	andi.	1,3,0x40		/* have we already done second hash? */
674	bne	5f
675	mfspr	2,HASH2			/* get the second pointer */
676	ori	3,3,0x40		/* change the compare value */
677	li	1,8
678	addi	2,2,-8			/* predec pointer */
679	b	1b
6805:	/* not found anywhere */
681	mfsrr1	3
682	lis	1,0x40000000@h		/* set dsisr<1> to flag pte not found */
683	mtctr	0			/* restore counter */
684	andi.	2,3,0xffff		/* clean upper srr1 */
685	mtsrr1	2
686	mtdsisr	1			/* load the dsisr */
687	mfspr	1,DMISS			/* get the miss address */
688	mtdar	1			/* put in dar */
689	mfmsr	0
690	xoris	0,0,0x20000@h		/* flip the msr<tgpr> bit */
691	mtcrf	0x80,3			/* restore cr0 */
692	mtmsr	0			/* now with native gprs */
693	isync
694	ba	EXC_DSI
695tlbdlmsize = .-tlbdlmiss
696
697	.globl	tlbdsmiss,tlbdsmsize
698tlbdsmiss:
699	mfspr	2,HASH1			/* get first pointer */
700	li	1,8
701	mfctr	0			/* save counter */
702	mfspr	3,DCMP			/* get first compare value */
703	addi	2,2,-8			/* predec pointer */
7041:
705	mtctr	1			/* load counter */
7062:
707	lwzu	1,8(2)			/* get next pte */
708	cmpl	0,1,3			/* see if found pte */
709	bdneq	2b			/* loop if not eq */
710	bne	3f			/* not found */
711	lwz	1,4(2)			/* load tlb entry lower word */
712	andi.	3,1,0x80		/* check the C-bit */
713	beq	4f
7145:
715	mtctr	0			/* restore counter */
716	mfspr	0,DMISS			/* get the miss address for the tlbld */
717	mfsrr1	3			/* get the saved cr0 bits */
718	mtcrf	0x80,3			/* and restore */
719	mtspr	RPA,1			/* set the pte */
720	tlbld	0			/* load the dtlb */
721	rfi
722
7233:	/* not found in pteg */
724	andi.	1,3,0x40		/* have we already done second hash? */
725	bne	5f
726	mfspr	2,HASH2			/* get the second pointer */
727	ori	3,3,0x40		/* change the compare value */
728	li	1,8
729	addi	2,2,-8			/* predec pointer */
730	b	1b
7314:	/* found, but C-bit = 0 */
732	rlwinm.	3,1,30,0,1		/* test PP */
733	bge-	7f
734	andi.	3,1,1
735	beq+	8f
7369:	/* found, but protection violation (PP==00)*/
737	mfsrr1	3
738	lis	1,0xa000000@h		/* indicate protection violation
739					   on store */
740	b	1f
7417:	/* found, PP=1x */
742	mfspr	3,DMISS			/* get the miss address */
743	mfsrin	1,3			/* get the segment register */
744	mfsrr1	3
745	rlwinm	3,3,18,31,31		/* get PR-bit */
746	rlwnm.	2,2,3,1,1		/* get the key */
747	bne-	9b			/* protection violation */
7488:	/* found, set reference/change bits */
749	lwz	1,4(2)			/* reload tlb entry */
750	ori	1,1,0x180
751	sth	1,6(2)
752	b	5b
7535:	/* not found anywhere */
754	mfsrr1	3
755	lis	1,0x42000000@h		/* set dsisr<1> to flag pte not found */
756					/* dsisr<6> to flag store */
7571:
758	mtctr	0			/* restore counter */
759	andi.	2,3,0xffff		/* clean upper srr1 */
760	mtsrr1	2
761	mtdsisr	1			/* load the dsisr */
762	mfspr	1,DMISS			/* get the miss address */
763	mtdar	1			/* put in dar */
764	mfmsr	0
765	xoris	0,0,0x20000@h		/* flip the msr<tgpr> bit */
766	mtcrf	0x80,3			/* restore cr0 */
767	mtmsr	0			/* now with native gprs */
768	isync
769	ba	EXC_DSI
770tlbdsmsize = .-tlbdsmiss
771
772#ifdef DDB
773#define	ddbsave	0xde0		/* primary save area for DDB */
774/*
775 * In case of DDB we want a separate trap catcher for it
776 */
777	.local	ddbstk
778	.comm	ddbstk,INTSTK,8		/* ddb stack */
779
780	.globl	ddblow,ddbsize
781ddblow:
782	mtsprg	1,1			/* save SP */
783	stmw	28,ddbsave(0)		/* free r28-r31 */
784	mflr	28			/* save LR */
785	mfcr	29			/* save CR */
786	lis	1,ddbstk+INTSTK@ha	/* get new SP */
787	addi	1,1,ddbstk+INTSTK@l
788	bla	ddbtrap
789ddbsize = .-ddblow
790#endif	/* DDB */
791
792#ifdef IPKDB
793#define	ipkdbsave	0xde0		/* primary save area for IPKDB */
794/*
795 * In case of IPKDB we want a separate trap catcher for it
796 */
797
798	.local	ipkdbstk
799	.comm	ipkdbstk,INTSTK,8		/* ipkdb stack */
800
801	.globl	ipkdblow,ipkdbsize
802ipkdblow:
803	mtsprg	1,1			/* save SP */
804	stmw	28,ipkdbsave(0)		/* free r28-r31 */
805	mflr	28			/* save LR */
806	mfcr	29			/* save CR */
807	lis	1,ipkdbstk+INTSTK@ha	/* get new SP */
808	addi	1,1,ipkdbstk+INTSTK@l
809	bla	ipkdbtrap
810ipkdbsize = .-ipkdblow
811#endif	/* IPKDB */
812
813/*
814 * FRAME_SETUP assumes:
815 *	SPRG1		SP (1)
816 *	savearea	r28-r31,DAR,DSISR	(DAR & DSISR only for DSI traps)
817 *	28		LR
818 *	29		CR
819 *	1		kernel stack
820 *	LR		trap type
821 *	SRR0/1		as at start of trap
822 */
823#define	FRAME_SETUP(savearea)						\
824/* Have to enable translation to allow access of kernel stack: */	\
825	mfsrr0	30;							\
826	mfsrr1	31;							\
827	stmw	30,savearea+24(0);					\
828	mfmsr	30;							\
829	ori	30,30,(PSL_DR|PSL_IR);					\
830	mtmsr	30;							\
831	isync;								\
832	mfsprg	31,1;							\
833	stwu	31,-FRAMELEN(1);					\
834	stw	0,FRAME_0+8(1);						\
835	stw	31,FRAME_1+8(1);					\
836	stw	28,FRAME_LR+8(1);					\
837	stw	29,FRAME_CR+8(1);					\
838	lmw	28,savearea(0);						\
839	stmw	2,FRAME_2+8(1);						\
840	lmw	28,savearea+16(0);					\
841	mfxer	3;							\
842	mfctr	4;							\
843	mflr	5;							\
844	andi.	5,5,0xff00;						\
845	stw	3,FRAME_XER+8(1);					\
846	stw	4,FRAME_CTR+8(1);					\
847	stw	5,FRAME_EXC+8(1);					\
848	stw	28,FRAME_DAR+8(1);					\
849	stw	29,FRAME_DSISR+8(1);					\
850	stw	30,FRAME_SRR0+8(1);					\
851	stw	31,FRAME_SRR1+8(1)
852
853#define	FRAME_LEAVE(savearea)						\
854/* Now restore regs: */							\
855	lwz	2,FRAME_SRR0+8(1);					\
856	lwz	3,FRAME_SRR1+8(1);					\
857	lwz	4,FRAME_CTR+8(1);					\
858	lwz	5,FRAME_XER+8(1);					\
859	lwz	6,FRAME_LR+8(1);					\
860	lwz	7,FRAME_CR+8(1);					\
861	stw	2,savearea(0);						\
862	stw	3,savearea+4(0);					\
863	mtctr	4;							\
864	mtxer	5;							\
865	mtlr	6;							\
866	mtsprg	1,7;			/* save cr */			\
867	lmw	2,FRAME_2+8(1);						\
868	lwz	0,FRAME_0+8(1);						\
869	lwz	1,FRAME_1+8(1);						\
870	mtsprg	2,2;			/* save r2 & r3 */		\
871	mtsprg	3,3;							\
872/* Disable translation, machine check and recoverability: */		\
873	mfmsr	2;							\
874	andi.	2,2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l;			\
875	mtmsr	2;							\
876	isync;								\
877/* Decide whether we return to user mode: */				\
878	lwz	3,savearea+4(0);					\
879	mtcr	3;							\
880	bc	4,17,1f;		/* branch if PSL_PR is false */	\
881/* Restore user & kernel access SR: */					\
882/*	lis	2,curpm@ha;		get real address of pmap */	\
883/*	lwz	2,curpm@l(2);					*/	\
884/*	lwz	3,PM_USRSR(2);					*/	\
885/*	mtsr	USER_SR,3;					*/	\
886/*	lwz	3,PM_KERNELSR(2);				*/	\
887/*	mtsr	KERNEL_SR,3;					*/	\
8881:	mfsprg	2,1;			/* restore cr */		\
889	mtcr	2;							\
890	lwz	2,savearea(0);						\
891	lwz	3,savearea+4(0);					\
892	mtsrr0	2;							\
893	mtsrr1	3;							\
894	mfsprg	2,2;			/* restore r2 & r3 */		\
895	mfsprg	3,3
896
897/*
898 * Preamble code for DSI/ISI traps
899 */
900disitrap:
901	lmw	30,disisave(0)
902	stmw	30,tempsave(0)
903	lmw	30,disisave+8(0)
904	stmw	30,tempsave+8(0)
905	mfdar	30
906	mfdsisr	31
907	stmw	30,tempsave+16(0)
908realtrap:
909/* Test whether we already had PR set */
910	mfsrr1	1
911	mtcr	1
912	mfsprg	1,1			/* restore SP (might have been
913					   overwritten) */
914	bc	4,17,s_trap		/* branch if PSL_PR is false */
915	mfsprg	1,0
916	lwz	1,GD_CURPCB(1)
917	addi	1,1,USPACE		/* stack is top of user struct */
918
919/*
920 * Now the common trap catching code.
921 */
922s_trap:
923/* First have to enable KERNEL mapping */
924	lis	31,KERNEL_SEGMENT@h
925	ori	31,31,KERNEL_SEGMENT@l
926	mtsr	KERNEL_SR,31
927	FRAME_SETUP(tempsave)
928/* Now we can recover interrupts again: */
929	mfmsr	7
930	ori	7,7,(PSL_EE|PSL_ME|PSL_RI)@l
931	mtmsr	7
932	isync
933/* Call C trap code: */
934trapagain:
935	addi	3,1,8
936	bl	trap
937trapexit:
938/* Disable interrupts: */
939	mfmsr	3
940	andi.	3,3,~PSL_EE@l
941	mtmsr	3
942/* Test AST pending: */
943	lwz	5,FRAME_SRR1+8(1)
944	mtcr	5
945	bc	4,17,1f			/* branch if PSL_PR is false */
946	lis	3,astpending@ha
947	lwz	4,astpending@l(3)
948	andi.	4,4,1
949	beq	1f
950#if 0 /* XXX */
951	li	6,EXC_AST
952#endif
953	stw	6,FRAME_EXC+8(1)
954	b	trapagain
9551:
956#if 0
957	FRAME_LEAVE(tempsave)
958#endif
959	rfi
960
961/*
962 * Child comes here at the end of a fork.
963 * Mostly similar to the above.
964 */
965	.globl	fork_trampoline
966fork_trampoline:
967	xor	3,3,3
968#if 0 /* XXX */
969	bl	lcsplx
970#endif
971	mtlr	31
972	mr	3,30
973	blrl				/* jump indirect to r31 */
974	b	trapexit
975
976/*
977 * DSI second stage fault handler
978 */
979s_dsitrap:
980	mfdsisr	31			/* test whether this may be a
981					   spill fault */
982	mtcr	31
983	mtsprg	1,1			/* save SP */
984	bc	4,1,disitrap		/* branch if table miss is false */
985	lis	1,spillstk+SPILLSTK@ha
986	addi	1,1,spillstk+SPILLSTK@l	/* get spill stack */
987	stwu	1,-52(1)
988	stw	0,48(1)			/* save non-volatile registers */
989	stw	3,44(1)
990	stw	4,40(1)
991	stw	5,36(1)
992	stw	6,32(1)
993	stw	7,28(1)
994	stw	8,24(1)
995	stw	9,20(1)
996	stw	10,16(1)
997	stw	11,12(1)
998	stw	12,8(1)
999	mflr	30			/* save trap type */
1000	mfctr	31			/* & CTR */
1001	mfdar	3
1002s_pte_spill:
1003	bl	pte_spill		/* try a spill */
1004	or.	3,3,3
1005	mtctr	31			/* restore CTR */
1006	mtlr	30			/* and trap type */
1007	mfsprg	31,2			/* get saved XER */
1008	mtxer	31			/* restore XER */
1009	lwz	12,8(1)			/* restore non-volatile registers */
1010	lwz	11,12(1)
1011	lwz	10,16(1)
1012	lwz	9,20(1)
1013	lwz	8,24(1)
1014	lwz	7,28(1)
1015	lwz	6,32(1)
1016	lwz	5,36(1)
1017	lwz	4,40(1)
1018	lwz	3,44(1)
1019	lwz	0,48(1)
1020	beq	disitrap
1021	mfsprg	1,1			/* restore SP */
1022	mtcr	29			/* restore CR */
1023	mtlr	28			/* restore LR */
1024	lmw	28,disisave(0)		/* restore r28-r31 */
1025	rfi				/* return to trapped code */
1026
1027/*
1028 * ISI second stage fault handler
1029 */
1030s_isitrap:
1031	mfsrr1	31			/* test whether this may be a
1032					   spill fault */
1033	mtcr	31
1034	mtsprg	1,1			/* save SP */
1035	bc	4,1,disitrap		/* branch if table miss is false */
1036	lis	1,spillstk+SPILLSTK@ha
1037	addi	1,1,spillstk+SPILLSTK@l	/* get spill stack */
1038	stwu	1,-52(1)
1039	stw	0,48(1)			/* save non-volatile registers */
1040	stw	3,44(1)
1041	stw	4,40(1)
1042	stw	5,36(1)
1043	stw	6,32(1)
1044	stw	7,28(1)
1045	stw	8,24(1)
1046	stw	9,20(1)
1047	stw	10,16(1)
1048	stw	11,12(1)
1049	stw	12,8(1)
1050	mfxer	30			/* save XER */
1051	mtsprg	2,30
1052	mflr	30			/* save trap type */
1053	mfctr	31			/* & ctr */
1054	mfsrr0	3
1055	b	s_pte_spill		/* above */
1056
1057/*
1058 * External interrupt second level handler
1059 */
1060#define	INTRENTER							\
1061/* Save non-volatile registers: */					\
1062	stwu	1,-88(1);		/* temporarily */		\
1063	stw	0,84(1);						\
1064	mfsprg	0,1;			/* get original SP */		\
1065	stw	0,0(1);			/* and store it */		\
1066	stw	3,80(1);						\
1067	stw	4,76(1);						\
1068	stw	5,72(1);						\
1069	stw	6,68(1);						\
1070	stw	7,64(1);						\
1071	stw	8,60(1);						\
1072	stw	9,56(1);						\
1073	stw	10,52(1);						\
1074	stw	11,48(1);						\
1075	stw	12,44(1);						\
1076	stw	28,40(1);		/* saved LR */			\
1077	stw	29,36(1);		/* saved CR */			\
1078	stw	30,32(1);		/* saved XER */			\
1079	lmw	28,tempsave(0);		/* restore r28-r31 */		\
1080	mfctr	6;							\
1081	lis	5,intr_depth@ha;					\
1082	lwz	5,intr_depth@l(5);					\
1083	mfsrr0	4;							\
1084	mfsrr1	3;							\
1085	stw	6,28(1);						\
1086	stw	5,20(1);						\
1087	stw	4,12(1);						\
1088	stw	3,8(1);							\
1089/* interrupts are recoverable here, and enable translation */		\
1090	lis	3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@h;			\
1091	ori	3,3,(KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY)@l;		\
1092	mtsr	KERNEL_SR,3;						\
1093	mfmsr	5;							\
1094	ori	5,5,(PSL_IR|PSL_DR|PSL_RI);				\
1095	mtmsr	5;							\
1096	isync
1097
1098	.globl	extint_call
1099extintr:
1100	INTRENTER
1101extint_call:
1102	bl	extint_call		/* to be filled in later */
1103
1104intr_exit:
1105/* Disable interrupts (should already be disabled) and MMU here: */
1106	mfmsr	3
1107	andi.	3,3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l
1108	mtmsr	3
1109	isync
1110/* restore possibly overwritten registers: */
1111	lwz	12,44(1)
1112	lwz	11,48(1)
1113	lwz	10,52(1)
1114	lwz	9,56(1)
1115	lwz	8,60(1)
1116	lwz	7,64(1)
1117	lwz	6,8(1)
1118	lwz	5,12(1)
1119	lwz	4,28(1)
1120	lwz	3,32(1)
1121	mtsrr1	6
1122	mtsrr0	5
1123	mtctr	4
1124	mtxer	3
1125/* Returning to user mode? */
1126	mtcr	6			/* saved SRR1 */
1127	bc	4,17,1f			/* branch if PSL_PR is false */
1128	mfsprg	3,0			/* get globaldata */
1129	lwz	3,GD_CURPCB(3)		/* get curpcb from globaldata */
1130	lwz	3,PCB_PMR(3)		/* get pmap real address from curpcb */
1131	mtsr	KERNEL_SR,3
1132	lis	3,astpending@ha		/* Test AST pending */
1133	lwz	4,astpending@l(3)
1134	andi.	4,4,1
1135	beq	1f
1136/* Setup for entry to realtrap: */
1137	lwz	3,0(1)			/* get saved SP */
1138	mtsprg	1,3
1139#if 0 /* XXX */
1140	li	6,EXC_AST
1141#endif
1142	stmw	28,tempsave(0)		/* establish tempsave again */
1143	mtlr	6
1144	lwz	28,40(1)		/* saved LR */
1145	lwz	29,36(1)		/* saved CR */
1146	lwz	6,68(1)
1147	lwz	5,72(1)
1148	lwz	4,76(1)
1149	lwz	3,80(1)
1150	lwz	0,84(1)
1151	lis	30,intr_depth@ha	 /* adjust reentrancy count */
1152	lwz	31,intr_depth@l(30)
1153	addi	31,31,-1
1154	stw	31,intr_depth@l(30)
1155	b	realtrap
11561:
1157/* Here is the normal exit of extintr: */
1158	lwz	5,36(1)
1159	lwz	6,40(1)
1160	mtcr	5
1161	mtlr	6
1162	lwz	6,68(1)
1163	lwz	5,72(1)
1164	lis	3,intr_depth@ha		/* adjust reentrancy count */
1165	lwz	4,intr_depth@l(3)
1166	addi	4,4,-1
1167	stw	4,intr_depth@l(3)
1168	lwz	4,76(1)
1169	lwz	3,80(1)
1170	lwz	0,84(1)
1171	lwz	1,0(1)
1172	rfi
1173
1174/*
1175 * Decrementer interrupt second level handler
1176 */
1177decrintr:
1178	INTRENTER
1179	addi	3,1,8			/* intr frame */
1180	bl	decr_intr
1181	b	intr_exit
1182
1183#ifdef DDB
1184/*
1185 * Deliberate entry to ddbtrap
1186 */
1187	.globl	ddb_trap
1188ddb_trap:
1189	mtsprg	1,1
1190	mfmsr	3
1191	mtsrr1	3
1192	andi.	3,3,~(PSL_EE|PSL_ME)@l
1193	mtmsr	3			/* disable interrupts */
1194	isync
1195	stmw	28,ddbsave(0)
1196	mflr	28
1197	li	29,EXC_BPT
1198	mtlr	29
1199	mfcr	29
1200	mtsrr0	28
1201
1202/*
1203 * Now the ddb trap catching code.
1204 */
1205ddbtrap:
1206	FRAME_SETUP(ddbsave)
1207/* Call C trap code: */
1208	addi	3,1,8
1209	bl	ddb_trap_glue
1210	or.	3,3,3
1211	bne	ddbleave
1212/* This wasn't for DDB, so switch to real trap: */
1213	lwz	3,FRAME_EXC+8(1)	/* save exception */
1214	stw	3,ddbsave+8(0)
1215	FRAME_LEAVE(ddbsave)
1216	mtsprg	1,1			/* prepare for entrance to realtrap */
1217	stmw	28,tempsave(0)
1218	mflr	28
1219	mfcr	29
1220	lwz	31,ddbsave+8(0)
1221	mtlr	31
1222	b	realtrap
1223ddbleave:
1224	FRAME_LEAVE(ddbsave)
1225	rfi
1226#endif /* DDB */
1227
1228#ifdef IPKDB
1229/*
1230 * Deliberate entry to ipkdbtrap
1231 */
1232	.globl	ipkdb_trap
1233ipkdb_trap:
1234	mtsprg	1,1
1235	mfmsr	3
1236	mtsrr1	3
1237	andi.	3,3,~(PSL_EE|PSL_ME)@l
1238	mtmsr	3			/* disable interrupts */
1239	isync
1240	stmw	28,ipkdbsave(0)
1241	mflr	28
1242	li	29,EXC_BPT
1243	mtlr	29
1244	mfcr	29
1245	mtsrr0	28
1246
1247/*
1248 * Now the ipkdb trap catching code.
1249 */
1250ipkdbtrap:
1251	FRAME_SETUP(ipkdbsave)
1252/* Call C trap code: */
1253	addi	3,1,8
1254	bl	ipkdb_trap_glue
1255	or.	3,3,3
1256	bne	ipkdbleave
1257/* This wasn't for IPKDB, so switch to real trap: */
1258	lwz	3,FRAME_EXC+8(1)	/* save exception */
1259	stw	3,ipkdbsave+8(0)
1260	FRAME_LEAVE(ipkdbsave)
1261	mtsprg	1,1			/* prepare for entrance to realtrap */
1262	stmw	28,tempsave(0)
1263	mflr	28
1264	mfcr	29
1265	lwz	31,ipkdbsave+8(0)
1266	mtlr	31
1267	b	realtrap
1268ipkdbleave:
1269	FRAME_LEAVE(ipkdbsave)
1270	rfi
1271
1272ipkdbfault:
1273	ba	_ipkdbfault
1274_ipkdbfault:
1275	mfsrr0	3
1276	addi	3,3,4
1277	mtsrr0	3
1278	li	3,-1
1279	rfi
1280
1281/*
1282 * int ipkdbfbyte(unsigned char *p)
1283 */
1284	.globl	ipkdbfbyte
1285ipkdbfbyte:
1286	li	9,EXC_DSI		/* establish new fault routine */
1287	lwz	5,0(9)
1288	lis	6,ipkdbfault@ha
1289	lwz	6,ipkdbfault@l(6)
1290	stw	6,0(9)
1291#ifdef	IPKDBUSERHACK
1292	lis	8,ipkdbsr@ha
1293	lwz	8,ipkdbsr@l(8)
1294	mtsr	USER_SR,8
1295	isync
1296#endif
1297	dcbst	0,9			/* flush data... */
1298	sync
1299	icbi	0,9			/* and instruction caches */
1300	lbz	3,0(3)			/* fetch data */
1301	stw	5,0(9)			/* restore previous fault handler */
1302	dcbst	0,9			/* and flush data... */
1303	sync
1304	icbi	0,9			/* and instruction caches */
1305	blr
1306
1307/*
1308 * int ipkdbsbyte(unsigned char *p, int c)
1309 */
1310	.globl	ipkdbsbyte
1311ipkdbsbyte:
1312	li	9,EXC_DSI		/* establish new fault routine */
1313	lwz	5,0(9)
1314	lis	6,ipkdbfault@ha
1315	lwz	6,ipkdbfault@l(6)
1316	stw	6,0(9)
1317#ifdef	IPKDBUSERHACK
1318	lis	8,ipkdbsr@ha
1319	lwz	8,ipkdbsr@l(8)
1320	mtsr	USER_SR,8
1321	isync
1322#endif
1323	dcbst	0,9			/* flush data... */
1324	sync
1325	icbi	0,9			/* and instruction caches */
1326	mr	6,3
1327	xor	3,3,3
1328	stb	4,0(6)
1329	dcbst	0,6			/* Now do appropriate flushes
1330					   to data... */
1331	sync
1332	icbi	0,6			/* and instruction caches */
1333	stw	5,0(9)			/* restore previous fault handler */
1334	dcbst	0,9			/* and flush data... */
1335	sync
1336	icbi	0,9			/* and instruction caches */
1337	blr
1338#endif	/* IPKDB */
1339
1340/*
1341 * int setfault()
1342 *
1343 * Similar to setjmp to setup for handling faults on accesses to user memory.
1344 * Any routine using this may only call bcopy, either the form below,
1345 * or the (currently used) C code optimized, so it doesn't use any non-volatile
1346 * registers.
1347 */
1348	.globl	setfault
1349setfault:
1350	mflr	0
1351	mfcr	12
1352	mfsprg	4,0
1353	lwz	4,GD_CURPCB(4)
1354	stw	3,PCB_FAULT(4)
1355	stw	0,0(3)
1356	stw	1,4(3)
1357	stw	2,8(3)
1358	stmw	12,12(3)
1359	xor	3,3,3
1360	blr
1361
1362/*
1363 * Signal "trampoline" code.
1364 */
1365	.globl	sigcode
1366sigcode:
1367	b	sys_exit
1368esigcode:
1369	.data
1370GLOBAL(szsigcode)
1371	.long	esigcode-sigcode
1372	.text
1373
1374