xref: /openbsd/sys/arch/macppc/macppc/locore.S (revision d8417bd7)
1/*	$OpenBSD: locore.S,v 1.64 2023/12/12 07:37:21 deraadt Exp $	*/
2/*	$NetBSD: locore.S,v 1.2 1996/10/16 19:33:09 ws Exp $	*/
3
4/*
5 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
6 * Copyright (C) 1995, 1996 TooLs GmbH.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed by TooLs GmbH.
20 * 4. The name of TooLs GmbH may not be used to endorse or promote products
21 *    derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include "assym.h"
36
37#include <sys/syscall.h>
38
39#include <machine/asm.h>
40#include <machine/param.h>
41#include <machine/pmap.h>
42#include <machine/psl.h>
43#include <machine/trap.h>
44
45#define GET_CPUINFO(r)	mfsprg r,0
46
47#define	INTSTK		(8*1024)	/* 8K interrupt stack */
48#define	SPILLSTK	(1*1024)
49#define	DDBSTK		(7*1024)
50
51	.text
52
53#ifdef MULTIPROCESSOR
54_ENTRY(cpu_spinup_trampoline)
55	lis	%r3,cpu_hatch_stack@ha
56	lwz	%r1,cpu_hatch_stack@l(%r3)
57
58	b	cpu_hatch
59	/* NOTREACHED */
60#endif
61
62/*
63 * void cpu_switchto(struct proc *old, struct proc *new)
64 * Switch from "old" proc to "new".
65 */
66_ENTRY(cpu_switchto_asm)
67	mflr	%r0			/* save lr */
68	stw	%r0,4(%r1)
69	stwu	%r1,(-SFRAMELEN - 16)(%r1)
70	stw	%r31,(SFRAMELEN + 12)(%r1)
71	stw	%r30,(SFRAMELEN + 8)(%r1)
72
73/*
74 * r3 - old proc
75 * r4 -	new proc
76 * r5 - cpuinfo
77 */
78	GET_CPUINFO(%r5)
79
80	li	%r31,SONPROC
81	stb	%r31,P_STAT(%r4)
82
83	or.	%r3,%r3,%r3		/* old process was exiting? */
84	beq	switch_exited
85
86	mfsr	%r10,PPC_USER_SR	/* save PPC_USER_SR for copyin/copyout*/
87	mfcr	%r11			/* save cr */
88	mr	%r12,%r2		/* save r2 */
89	stmw	%r10,8(%r1)
90	lwz	%r31,P_ADDR(%r3)
91	stw	%r1,PCB_SP(%r31)	/* save SP */
92
93switch_exited:
94	/* disable interrupts while actually switching */
95	mfmsr	%r30
96	andi.	%r30,%r30,~PSL_EE@l
97	mtmsr	%r30
98	isync
99
100	stw	%r4,CI_CURPROC(%r5)	/* record new process */
101
102#ifdef MULTIPROCESSOR
103	stw	%r5,P_CPU(%r4)
104#endif
105
106	lwz	%r31,P_ADDR(%r4)
107	stw	%r31,CI_CURPCB(%r5)	/* indicate new pcb */
108
109	lwz	%r6,PCB_PMR(%r31)
110
111	/* save real pmap pointer for spill fill */
112	stwu	%r6,CI_CURPM(%r5)
113	stwcx.	%r6,%r0,%r5		/* clear possible reservation */
114
115	addic.	%r6,%r6,64
116	li	%r5,0
117
118	lwz	%r1,PCB_SP(%r31)	/* get new procs SP */
119	lwz	%r0,(SFRAMELEN + 16 + 4)(%r1)
120	RETGUARD_SETUP_LATE(cpu_switchto_asm, %r9, %r0)
121
122	ori	%r30,%r30,PSL_EE	/* interrupts are okay again */
123	mtmsr	%r30
124
125	lmw	%r10,8(%r1)		/* get other regs */
126	mr	%r2,%r12		/* get saved r2 */
127	mtcr	%r11			/* get saved cr */
128	isync
129	mtsr	PPC_USER_SR,%r10	/* get saved PPC_USER_SR */
130	isync
131
132	lwz	%r31,(SFRAMELEN + 12)(%r1)
133	lwz	%r30,(SFRAMELEN + 8)(%r1)
134	addi	%r1,%r1,SFRAMELEN + 16
135	mtlr	%r0
136	RETGUARD_CHECK(cpu_switchto_asm, %r9, %r0)
137	blr
138
139_ENTRY(cpu_idle_enter)
140	RETGUARD_SETUP(cpu_idle_enter, %r11, %r12)
141	lis	%r4, ppc_cpuidle@ha
142	lwz	%r4, ppc_cpuidle@l(%r4)
143	cmpwi	%r4, 0
144	beq	1f
145	/* must disable external interrupts during idle queue checking */
146	mfmsr	%r3
147	andi.	%r3,%r3,~PSL_EE@l
148	mtmsr	%r3
149	isync
1501:
151	RETGUARD_CHECK(cpu_idle_enter, %r11, %r12)
152	blr
153
154_ENTRY(cpu_idle_cycle)
155	RETGUARD_SETUP(cpu_idle_cycle, %r11, %r12)
156	lis	%r4, ppc_cpuidle@ha
157	lwz	%r4, ppc_cpuidle@l(%r4)
158	cmpwi	%r4, 0
159	beq	idledone
160
161	/*
162	 * Interrupts were disabled in cpu_idle_enter, but must be
163	 * enabled for sleeping, but before that indicate that we
164	 * are entering sleep mode.
165	 */
166	GET_CPUINFO(%r4)
167	lwz	%r6,CI_FLAGS(%r4)
168	ori	%r6,%r6,CI_FLAGS_SLEEPING@l
169	stw	%r6,CI_FLAGS(%r4)
170
171	/* enable interrupts, required before setting POW */
172	mfmsr	%r3
173	ori	%r5,%r3,PSL_EE@l
174	mtmsr	%r5
175	oris	%r5, %r5, PSL_POW@h
176	sync
177	/* low power mode */
178	mtmsr	%r5
179	sync
180	isync
181
182	/*
183	 * restore interrupts to disabled, so CI_FLAGS is only modified
184	 * with interrupts disabled.
185	 */
186	mtmsr %r3
187	isync
188
189	/* clear CI_FLAGS_SLEEPING since sleeping is over */
190	andi.	%r6,%r6,~CI_FLAGS_SLEEPING@l
191	stw	%r6,CI_FLAGS(%r4)
192idledone:
193	RETGUARD_CHECK(cpu_idle_cycle, %r11, %r12)
194	blr
195
196_ENTRY(cpu_idle_leave)
197	RETGUARD_SETUP(cpu_idle_leave, %r11, %r12)
198	lis	%r4, ppc_cpuidle@ha
199	lwz	%r4, ppc_cpuidle@l(%r4)
200	cmpwi	%r4, 0
201	beq	1f
202	/* enable interrupts disabled in cpu_idle_enter. */
203	mfmsr	%r3
204	ori	%r3,%r3,PSL_EE@l
205	mtmsr	%r3
2061:
207	RETGUARD_CHECK(cpu_idle_leave, %r11, %r12)
208	blr
209
210/*
211 * This code gets copied to all the trap vectors
212 * except ISI/DSI, ALI, and the interrupts
213 */
214	.text
215	.globl	trapcode,trapsize
216	.type	trapcode,@function
217	.type	trapsize,@object
218trapcode:
219	mtsprg	1,%r1			/* save SP */
220nop32_1s:
221	mfmsr	%r1
222	clrldi	%r1,%r1,1
223	mtmsrd	%r1
224nop32_1e:
225	GET_CPUINFO(%r1)
226	stmw	%r28,CI_TEMPSAVE(%r1)	/* free r28-r31 */
227	mflr	%r28			/* save LR */
228	mfcr	%r29			/* save CR */
229	mfsprg	%r1,1			/* restore SP */
230
231	/* Test whether we already had PR set */
232	mfsrr1	%r31
233	mtcr	%r31
234	bc	4,17,1f			/* branch if PSL_PR is clear */
235	GET_CPUINFO(%r1)
236	lwz	%r1,CI_CURPCB(%r1)
237	addi	%r1,%r1,USPACE		/* stack is top of user struct */
2381:
239	bla	s_trap
240trapsize =		.-trapcode
241
242/*
243 * For ALI: has to save DSISR and DAR
244 */
245	.globl	alitrap,alisize
246alitrap:
247	mtsprg	1,%r1			/* save SP */
248nop32_2s:
249	mfmsr	%r1
250	clrldi	%r1,%r1,1
251	mtmsrd	%r1
252nop32_2e:
253	GET_CPUINFO(%r1)
254	stmw	%r28,CI_TEMPSAVE(%r1)	/* free r28-r31 */
255	mfdar	%r30
256	mfdsisr	%r31
257	stmw	%r30,CI_TEMPSAVE+16(%r1)
258	mflr	%r28			/* save LR */
259	mfcr	%r29			/* save CR */
260	mfsprg	%r1,1			/* restore SP */
261
262	/* Test whether we already had PR set */
263	mfsrr1	%r31
264	mtcr	%r31
265	bc	4,17,1f			/* branch if PSL_PR is clear */
266	GET_CPUINFO(%r1)
267	lwz	%r1,CI_CURPCB(%r1)
268	addi	%r1,%r1,USPACE		/* stack is top of user struct */
2691:
270	bla	s_trap
271alisize =		.-alitrap
272
273/*
274 * Similar to the above for DSI
275 * Has to handle BAT spills
276 * and standard pagetable spills
277 */
278	.globl	dsitrap,dsisize
279	.type	dsitrap,@function
280	.type	dsisize,@object
281dsitrap:
282	mtsprg	1,%r1
283	GET_CPUINFO(%r1)
284	stmw	%r28,CI_DISISAVE(%r1)	/* free r28-r31 */
285nop32_3s:
286	mfmsr	%r28
287	clrldi	%r28,%r28,1
288	mtmsrd	%r28
289nop32_3e:
290	mfsprg	%r1,1
291	mfcr	%r29			/* save CR */
292	mfxer	%r30			/* save XER */
293	mtsprg	2,%r30			/* in SPRG2 */
294	mfsrr1	%r31			/* test kernel mode */
295nopbat_1s:
296	mtcr	%r31
297	bc	12,17,1f		/* branch if PSL_PR is set */
298	mfdar	%r31			/* get fault address */
299	rlwinm	%r31,%r31,7,25,28	/* get segment * 8 */
300	addis	%r31,%r31,battable@ha
301	lwz	%r30,battable@l(%r31)		/* get batu */
302	mtcr	%r30
303	bc	4,30,1f			/* branch if supervisor valid is false */
304	lwz	%r31,battable+4@l(%r31)			/* get batl */
305/* We randomly use the highest two bat registers here */
306	mftb	%r28
307	andi.	%r28,%r28,1
308	bne	2f
309	mtdbatu	2,%r30
310	mtdbatl	2,%r31
311	b	3f
3122:
313	mtdbatu	3,%r30
314	mtdbatl	3,%r31
3153:
316	mfsprg	%r30,2			/* restore XER */
317	mtxer	%r30
318	mtcr	%r29			/* restore CR */
319	mtsprg	1,%r1
320	GET_CPUINFO(%r1)
321	lmw	%r28,CI_DISISAVE(%r1)	/* restore r28-r31 */
322	mfsprg	1,%r1
323	rfi				/* return to trapped code */
3241:
325nopbat_1e:
326	mflr	%r28			/* save LR */
327	bla	s_dsitrap
328dsisize =		.-dsitrap
329
330/*
331 * Similar to the above for ISI
332 */
333	.globl	isitrap,isisize
334	.type	isitrap,@function
335	.type	isisize,@object
336isitrap:
337	mtsprg	1,%r1                   /* save SP */
338nop32_4s:
339	mfmsr	%r1
340	clrldi	%r1,%r1,1
341	mtmsrd	%r1
342nop32_4e:
343	GET_CPUINFO(%r1)
344	stmw	%r28,CI_DISISAVE(%r1)	/* free r28-r31 */
345	mflr	%r28			/* save LR */
346	mfcr	%r29			/* save CR */
347	mfsrr1	%r31			/* test kernel mode */
348	mfsprg	%r1,1                   /* restore SP */
349	bla	s_isitrap
350isisize =		.-isitrap
351
352/*
353 * This one for the external interrupt handler.
354 */
355	.globl	extint,extsize
356	.type	extint,@function
357	.type	extsize,@object
358extint:
359	mtsprg	1,%r1			/* save SP */
360nop32_5s:
361	mfmsr	%r1
362	clrldi	%r1,%r1,1
363	mtmsrd	%r1
364nop32_5e:
365	GET_CPUINFO(%r1)
366	stmw	%r28,CI_TEMPSAVE(%r1)	/* free r28-r31 */
367	mflr	%r28			/* save LR */
368	mfcr	%r29			/* save CR */
369	mfxer	%r30			/* save XER */
370	lwz	%r31,CI_INTRDEPTH(%r1)	/* were we already running on intstk? */
371	addic.	%r31,%r31,1
372	stw	%r31,CI_INTRDEPTH(%r1)
373	lwz	%r1,CI_INTSTK(%r1)	/* get interrupt stack */
374	beq	1f
375	mfsprg	%r1,1			/* yes, get old SP */
3761:
377	ba	extintr
378extsize =		.-extint
379
380/*
381 * And this one for the decrementer interrupt handler.
382 */
383	.globl	decrint,decrsize
384	.type	decrint,@function
385	.type	decrsize,@object
386decrint:
387	mtsprg	1,%r1			/* save SP */
388nop32_6s:
389	mfmsr	%r1
390	clrldi	%r1,%r1,1
391	mtmsrd	%r1
392nop32_6e:
393	GET_CPUINFO(%r1)
394	stmw	%r28,CI_TEMPSAVE(%r1)	/* free r28-r31 */
395	mflr	%r28			/* save LR */
396	mfcr	%r29			/* save CR */
397	mfxer	%r30			/* save XER */
398	lwz	%r31,CI_INTRDEPTH(%r1)	/* were we already running on intstk? */
399	addic.	%r31,%r31,1
400	stw	%r31,CI_INTRDEPTH(%r1)
401	lwz	%r1,CI_INTSTK(%r1)	/* get interrupt stack */
402	beq	1f
403	mfsprg	%r1,1			/* yes, get old SP */
4041:
405	ba	decrintr
406decrsize =		.-decrint
407
408/*
409 * Now the tlb software load for 603 processors:
410 * (Code essentially from the 603e User Manual, Chapter 5)
411 */
412#define	DMISS	976
413#define	DCMP	977
414#define	HASH1	978
415#define	HASH2	979
416#define	IMISS	980
417#define	ICMP	981
418#define	RPA	982
419
420#define	bdneq	bdnzf 2,
421#define	tlbli	.long	0x7c0007e4+0x800*
422#define	tlbld	.long	0x7c0007a4+0x800*
423
424	.globl	tlbimiss,tlbimsize
425	.type	tlbimiss,@function
426	.type	tlbimsize,@object
427tlbimiss:
428	mfspr	%r2,HASH1		/* get first pointer */
429	li	%r1,8
430	mfctr	%r0			/* save counter */
431	mfspr	%r3,ICMP		/* get first compare value */
432	addi	%r2,%r2,-8		/* predec pointer */
4331:
434	mtctr	%r1			/* load counter */
4352:
436	lwzu	%r1,8(%r2)		/* get next pte */
437	cmplw	0,%r1,%r3		/* see if found pte */
438	bdneq	2b			/* loop if not eq */
439	bne	3f			/* not found */
440	lwz	%r1,4(%r2)		/* load tlb entry lower word */
441	andi.	%r3,%r1,8		/* check G-bit */
442	bne	4f			/* if guarded, take ISI */
443	mtctr	%r0			/* restore counter */
444	mfspr	%r0,IMISS		/* get the miss address for the tlbli */
445	mfsrr1	%r3			/* get the saved cr0 bits */
446	mtcrf	0x80,%r3		/* and restore */
447	ori	%r1,%r1,0x100		/* set the reference bit */
448	mtspr	RPA,%r1			/* set the pte */
449	srwi	%r1,%r1,8		/* get byte 7 of pte */
450	tlbli	0			/* load the itlb */
451	stb	%r1,6(%r2)		/* update page table */
452	rfi
453
4543:	/* not found in pteg */
455	andi.	%r1,%r3,0x40		/* have we already done second hash? */
456	bne	5f
457	mfspr	%r2,HASH2		/* get the second pointer */
458	ori	%r3,%r3,0x40		/* change the compare value */
459	li	%r1,8
460	addi	%r2,%r2,-8		/* predec pointer */
461	b	1b
4624:	/* guarded */
463	mfsrr1	%r3
464	andi.	%r2,%r3,0xffff		/* clean upper srr1 */
465	addis	%r2,%r2,0x800		/* set srr<4> to flag prot violation */
466	b	6f
4675:	/* not found anywhere */
468	mfsrr1	%r3
469	andi.	%r2,%r3,0xffff		/* clean upper srr1 */
470	addis	%r2,%r2,0x4000		/* set srr1<1> to flag pte not found */
4716:
472	mtctr	%r0			/* restore counter */
473	mtsrr1	%r2
474	mfmsr	%r0
475	xoris	%r0,%r0,2		/* flip the msr<tgpr> bit */
476	mtcrf	0x80,%r3		/* restore cr0 */
477	mtmsr	%r0			/* now with native gprs */
478	isync
479	ba	EXC_ISI
480tlbimsize =		.-tlbimiss
481
482	.globl	tlbdlmiss,tlbdlmsize
483	.type	tlbdlmiss,@function
484	.type	tlbdlmsize,@object
485tlbdlmiss:
486	mfspr	%r2,HASH1		/* get first pointer */
487	li	%r1,8
488	mfctr	%r0			/* save counter */
489	mfspr	%r3,DCMP		/* get first compare value */
490	addi	%r2,%r2,-8		/* predec pointer */
4911:
492	mtctr	%r1			/* load counter */
4932:
494	lwzu	%r1,8(%r2)		/* get next pte */
495	cmplw	0,%r1,%r3		/* see if found pte */
496	bdneq	2b			/* loop if not eq */
497	bne	3f			/* not found */
498	lwz	%r1,4(%r2)		/* load tlb entry lower word */
499	mtctr	%r0			/* restore counter */
500	mfspr	%r0,DMISS		/* get the miss address for the tlbld */
501	mfsrr1	%r3			/* get the saved cr0 bits */
502	mtcrf	0x80,%r3		/* and restore */
503	ori	%r1,%r1,0x100		/* set the reference bit */
504	mtspr	RPA,%r1			/* set the pte */
505	srwi	%r1,%r1,8		/* get byte 7 of pte */
506	tlbld	0			/* load the dtlb */
507	stb	%r1,6(%r2)		/* update page table */
508	rfi
509
5103:	/* not found in pteg */
511	andi.	%r1,%r3,0x40		/* have we already done second hash? */
512	bne	5f
513	mfspr	%r2,HASH2		/* get the second pointer */
514	ori	%r3,%r3,0x40		/* change the compare value */
515	li	%r1,8
516	addi	%r2,%r2,-8		/* predec pointer */
517	b	1b
5185:	/* not found anywhere */
519	mfsrr1	%r3
520	lis	%r1,0x4000		/* set dsisr<1> to flag pte not found */
521	mtctr	%r0			/* restore counter */
522	andi.	%r2,%r3,0xffff		/* clean upper srr1 */
523	mtsrr1	%r2
524	mtdsisr	%r1			/* load the dsisr */
525	mfspr	%r1,DMISS		/* get the miss address */
526	mtdar	%r1			/* put in dar */
527	mfmsr	%r0
528	xoris	%r0,%r0,2		/* flip the msr<tgpr> bit */
529	mtcrf	0x80,%r3		/* restore cr0 */
530	mtmsr	%r0			/* now with native gprs */
531	isync
532	ba	EXC_DSI
533tlbdlmsize =		.-tlbdlmiss
534
535	.globl	tlbdsmiss,tlbdsmsize
536	.type	tlbdsmiss,@function
537	.type	tlbdsmsize,@object
538tlbdsmiss:
539	mfspr	%r2,HASH1		/* get first pointer */
540	li	%r1,8
541	mfctr	%r0			/* save counter */
542	mfspr	%r3,DCMP		/* get first compare value */
543	addi	%r2,%r2,-8		/* predec pointer */
5441:
545	mtctr	%r1			/* load counter */
5462:
547	lwzu	%r1,8(%r2)		/* get next pte */
548	cmplw	0,%r1,%r3		/* see if found pte */
549	bdneq	2b			/* loop if not eq */
550	bne	3f			/* not found */
551	lwz	%r1,4(%r2)		/* load tlb entry lower word */
552	andi.	%r3,%r1,0x80		/* check the C-bit */
553	beq	4f
5545:
555	mtctr	%r0			/* restore counter */
556	mfspr	%r0,DMISS		/* get the miss address for the tlbld */
557	mfsrr1	%r3			/* get the saved cr0 bits */
558	mtcrf	0x80,%r3		/* and restore */
559	mtspr	RPA,%r1			/* set the pte */
560	tlbld	0			/* load the dtlb */
561	rfi
562
5633:	/* not found in pteg */
564	andi.	%r1,%r3,0x40		/* have we already done second hash? */
565	bne	5f
566	mfspr	%r2,HASH2		/* get the second pointer */
567	ori	%r3,%r3,0x40		/* change the compare value */
568	li	%r1,8
569	addi	%r2,%r2,-8		/* predec pointer */
570	b	1b
5714:	/* found, but C-bit = 0 */
572	rlwinm.	%r3,%r1,30,0,1		/* test PP */
573	bge-	7f
574	andi.	%r3,%r1,1
575	beq+	8f
5769:	/* found, but protection violation (PP==00)*/
577	mfsrr1	%r3
578	lis	%r1,0xa00	/* indicate protection violation on store */
579	b	1f
5807:	/* found, PP=1x */
581	mfspr	%r3,DMISS		/* get the miss address */
582	mfsrin	%r1,%r3			/* get the segment register */
583	mfsrr1	%r3
584	rlwinm	%r3,%r3,18,31,31	/* get PR-bit */
585	rlwnm.	%r1,%r1,%r3,1,1		/* get the key */
586	bne-	9b			/* protection violation */
5878:	/* found, set reference/change bits */
588	lwz	%r1,4(%r2)		/* reload tlb entry */
589	ori	%r1,%r1,0x180
590	sth	%r1,6(%r2)
591	b	5b
5925:	/* not found anywhere */
593	mfsrr1	%r3
594	lis	%r1,0x4200		/* set dsisr<1> to flag pte not found */
595					/* dsisr<6> to flag store */
5961:
597	mtctr	%r0			/* restore counter */
598	andi.	%r2,%r3,0xffff		/* clean upper srr1 */
599	mtsrr1	%r2
600	mtdsisr	%r1			/* load the dsisr */
601	mfspr	%r1,DMISS		/* get the miss address */
602	mtdar	%r1			/* put in dar */
603	mfmsr	%r0
604	xoris	%r0,%r0,2		/* flip the msr<tgpr> bit */
605	mtcrf	0x80,%r3		/* restore cr0 */
606	mtmsr	%r0			/* now with native gprs */
607	isync
608	ba	EXC_DSI
609tlbdsmsize =		.-tlbdsmiss
610
611#ifdef DDB
612/*
613 * In case of DDB we want a separate trap catcher for it
614 */
615	.globl	ddblow,ddbsize
616ddblow:
617	mtsprg	1,%r1			/* save SP */
618nop32_7s:
619	mfmsr	%r1
620	clrldi	%r1,%r1,1
621	mtmsrd	%r1
622nop32_7e:
623	GET_CPUINFO(%r1)
624	stmw	%r28,CI_DDBSAVE(%r1)	/* free r28-r31 */
625	mflr	%r28			/* save LR */
626	mfcr	%r29			/* save CR */
627	GET_CPUINFO(%r30)
628	lwz	%r30,CI_INTSTK(%r30)	/* get interrupt stack */
629	addi	%r1,%r30,(SPILLSTK+DDBSTK)
630	bla	ddbtrap
631ddbsize =		.-ddblow
632#endif  /* DDB */
633
634/*
635 * If this interrupt occurred between the runqueue check and the setting
636 * of the POW bit, do no enter to sleep.  We do that in order to process
637 * the result of this interrupt directly and not when coming back from
638 * sleep, when the next clock tick or interrupt will fire.
639 */
640#define CPU_IDLE_CHECK(sr1,sr2,sr3,rSRR0,flag)				\
641	GET_CPUINFO(sr1);						\
642	lwz	sr2,CI_FLAGS(sr1);					\
643	andi.	sr3,sr2,flag@l;						\
644	beq	1f;							\
645	andi.	sr2,sr2,~flag@l;					\
646	stw	sr2,CI_FLAGS(sr1);					\
647	lis	rSRR0,idledone@ha;					\
648	addi	rSRR0,rSRR0,idledone@l;					\
6491:
650
651/*
652 * FRAME_SETUP assumes:
653 *	SPRG1		SP (1)
654 *	savearea	r28-r31,DAR,DSISR	(DAR & DSISR only for DSI traps)
655 *	28		LR
656 *	29		CR
657 *	1		kernel stack
658 *	LR		trap type
659 *	SRR0/1		as at start of trap
660 */
661#define FRAME_SETUP(savearea)	FRAME_SETUP_FLAG(savearea, CI_FLAGS_SLEEPING)
662
663#define	FRAME_SETUP_FLAG(savearea, flag)				\
664/* Have to enable translation to allow access of kernel stack: */	\
665	GET_CPUINFO(%r31);						\
666	mfsrr0	%r30;							\
667	stw	%r30,savearea+24(%r31);					\
668	mfsrr1	%r30;							\
669	stw	%r30,savearea+28(%r31);					\
670	/* load all kernel segment registers. */			\
671	lis	%r31,kernel_pmap_@ha;					\
672	addi	%r31,%r31,kernel_pmap_@l;				\
673	lwz	%r30,0(%r31);	mtsr	0,%r30;				\
674	lwz	%r30,4(%r31);	mtsr	1,%r30;				\
675	lwz	%r30,8(%r31);	mtsr	2,%r30;				\
676	lwz	%r30,12(%r31);	mtsr	3,%r30;				\
677	lwz	%r30,16(%r31);	mtsr	4,%r30;				\
678	lwz	%r30,20(%r31);	mtsr	5,%r30;				\
679	lwz	%r30,24(%r31);	mtsr	6,%r30;				\
680	lwz	%r30,28(%r31);	mtsr	7,%r30;				\
681	lwz	%r30,32(%r31);	mtsr	8,%r30;				\
682	lwz	%r30,36(%r31);	mtsr	9,%r30;				\
683	lwz	%r30,40(%r31);	mtsr	10,%r30;			\
684	lwz	%r30,44(%r31);	mtsr	11,%r30;			\
685	lwz	%r30,48(%r31);	mtsr	12,%r30;			\
686/*	lwz	%r30,52(%r31);	mtsr 13,%r30; - dont load user SR - XXX? */ \
687	lwz	%r30,56(%r31);	mtsr	14,%r30;			\
688	lwz	%r30,60(%r31);	mtsr	15,%r30;			\
689	mfmsr	%r30;							\
690	ori	%r30,%r30,(PSL_DR|PSL_IR);				\
691	mtmsr	%r30;							\
692	isync;								\
693	mfsprg	%r31,1;							\
694	stwu	%r31,-FRAMELEN(%r1);					\
695	stw	%r0,FRAME_0+8(%r1);					\
696	stw	%r31,FRAME_1+8(%r1);					\
697	stw	%r2,FRAME_2+8(%r1);					\
698	stw	%r28,FRAME_LR+8(%r1);					\
699	stw	%r29,FRAME_CR+8(%r1);					\
700	GET_CPUINFO(%r2);						\
701	lmw	%r28,savearea(%r2);					\
702	stmw	%r3,FRAME_3+8(%r1);					\
703	lmw	%r28,savearea+16(%r2);					\
704	mfxer	%r3;							\
705	mfctr	%r4;							\
706	mflr	%r5;							\
707	andi.	%r5,%r5,0xff00;						\
708	stw	%r3,FRAME_XER+8(%r1);					\
709	stw	%r4,FRAME_CTR+8(%r1);					\
710	stw	%r5,FRAME_EXC+8(%r1);					\
711	stw	%r28,FRAME_DAR+8(%r1);					\
712	stw	%r29,FRAME_DSISR+8(%r1);				\
713	CPU_IDLE_CHECK(%r5,%r6,%r0,%r30,flag)				\
714	stw	%r30,FRAME_SRR0+8(%r1);					\
715	stw	%r31,FRAME_SRR1+8(%r1)
716
717#define	FRAME_LEAVE(savearea)						\
718/* Now restore regs: */							\
719	lwz	%r2,FRAME_SRR0+8(%r1);					\
720	lwz	%r3,FRAME_SRR1+8(%r1);					\
721	lwz	%r4,FRAME_CTR+8(%r1);					\
722	lwz	%r5,FRAME_XER+8(%r1);					\
723	lwz	%r6,FRAME_LR+8(%r1);					\
724	GET_CPUINFO(%r7);						\
725	stw	%r2,savearea(%r7);					\
726	stw	%r3,savearea+4(%r7);					\
727	lwz	%r7,FRAME_CR+8(%r1);					\
728	mtctr	%r4;							\
729	mtxer	%r5;							\
730	mtlr	%r6;							\
731	mtsprg	1,%r7;			/* save cr */			\
732	lmw	%r2,FRAME_2+8(%r1);					\
733	lwz	%r0,FRAME_0+8(%r1);					\
734	lwz	%r1,FRAME_1+8(%r1);					\
735	mtsprg	2,%r2;			/* save r2 & r3 */		\
736	mtsprg	3,%r3;							\
737/* Disable translation, machine check and recoverability: */		\
738	mfmsr	%r2;							\
739	lis	%r3,(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@ha;			\
740	addi	%r3,%r3,(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l;		\
741	andc	%r2,%r2,%r3;						\
742	mtmsr	%r2;							\
743	isync;								\
744/* Decide whether we return to user mode: */				\
745	GET_CPUINFO(%r2);						\
746	lwz	%r3,savearea+4(%r2);					\
747	mtcr	%r3;							\
748	bc	4,17,1f;		/* branch if PSL_PR is false */	\
749/* Restore user & kernel access SR: */					\
750	lwz	%r2,CI_CURPM(%r2);	/* get real address of pmap */	\
751	lwz	%r3,0(%r2);	mtsr	0,%r3;				\
752	lwz	%r3,4(%r2);	mtsr	1,%r3;				\
753	lwz	%r3,8(%r2);	mtsr	2,%r3;				\
754	lwz	%r3,12(%r2);	mtsr	3,%r3;				\
755	lwz	%r3,16(%r2);	mtsr	4,%r3;				\
756	lwz	%r3,20(%r2);	mtsr	5,%r3;				\
757	lwz	%r3,24(%r2);	mtsr	6,%r3;				\
758	lwz	%r3,28(%r2);	mtsr	7,%r3;				\
759	lwz	%r3,32(%r2);	mtsr	8,%r3;				\
760	lwz	%r3,36(%r2);	mtsr	9,%r3;				\
761	lwz	%r3,40(%r2);	mtsr	10,%r3;				\
762	lwz	%r3,44(%r2);	mtsr	11,%r3;				\
763	lwz	%r3,48(%r2);	mtsr	12,%r3;				\
764	lwz	%r3,52(%r2);	mtsr	13,%r3;				\
765	lwz	%r3,56(%r2);	mtsr	14,%r3;				\
766	lwz	%r3,60(%r2);	mtsr	15,%r3;				\
7671:	mfsprg	%r2,1;			/* restore cr */		\
768	mtcr	%r2;							\
769	GET_CPUINFO(%r2);						\
770	lwz	%r3,savearea(%r2);					\
771	mtsrr0	%r3;							\
772	lwz	%r3,savearea+4(%r2);					\
773	mtsrr1	%r3;							\
774	mfsprg	%r2,2;			/* restore r2 & r3 */		\
775	mfsprg	%r3,3
776
777/*
778 * Preamble code for DSI/ISI traps
779 */
780disitrap:
781	GET_CPUINFO(%r1)
782	lmw	%r30,CI_DISISAVE(%r1)
783	stmw	%r30,CI_TEMPSAVE(%r1)
784	lmw	%r30,CI_DISISAVE+8(%r1)
785	stmw	%r30,CI_TEMPSAVE+8(%r1)
786	mfdar	%r30
787	mfdsisr	%r31
788	stmw	%r30,CI_TEMPSAVE+16(%r1)
789realtrap:
790	/* Test whether we already had PR set */
791	mfsrr1	%r1
792	mtcr	%r1
793	/* restore SP (might have been overwritten) */
794	mfsprg	%r1,1
795	bc	4,17,s_trap		/* branch if PSL_PR is false */
796	GET_CPUINFO(%r1)
797	lwz	%r1,CI_CURPCB(%r1)
798	addi	%r1,%r1,USPACE		/* stack is top of user struct */
799/*
800 * Now the common trap catching code.
801 */
802	.globl	s_trap
803s_trap:
804	FRAME_SETUP(CI_TEMPSAVE)
805/* Now we can recover interrupts again: */
806	mfmsr	%r7
807	mfsrr1	%r31
808	andi.	%r31,%r31,PSL_EE	/* restore EE from previous context */
809	or	%r7,%r7,%r31
810	ori	%r7,%r7,(PSL_ME|PSL_RI)
811	mtmsr	%r7
812	isync
813/* Call C trap code: */
814trapagain:
815	addi	%r3,%r1,8
816	bl	trap
817
818	.globl	trapexit
819trapexit:
820/* Disable interrupts: */
821	mfmsr	%r3
822	andi.	%r3,%r3,~PSL_EE@l
823	mtmsr	%r3
824	isync
825/* Test AST pending: */
826	lwz	%r5,FRAME_SRR1+8(%r1)
827	mtcr	%r5
828	bc	4,17,1f			/* branch if PSL_PR is false */
829	GET_CPUINFO(%r3)
830	lwz	%r4,CI_CURPROC(%r3)
831	lwz	%r4,P_MD_ASTPENDING(%r4)
832	andi.	%r4,%r4,1
833	beq	1f
834	li	%r6,EXC_AST
835	stw	%r6,FRAME_EXC+8(%r1)
836	b	trapagain
8371:
838	FRAME_LEAVE(CI_TEMPSAVE)
839rfi1:	rfi
840
841/*
842 * Child comes here at the end of a fork.
843 * Mostly similar to the above.
844 */
845	.globl	proc_trampoline
846	.type	proc_trampoline,@function
847proc_trampoline:
848	bl	proc_trampoline_mi
849	mtlr	%r31
850	mr	%r3,%r30
851	blrl				/* jump indirect to r31 */
852	b	trapexit
853
854/*
855 * DSI second stage fault handler
856 */
857s_dsitrap:
858	mfdsisr	%r31			/* test if this is spill fault */
859	mtcr	%r31
860	mtsprg	1,%r1			/* save SP */
861	bc	4,1,disitrap		/* branch if table miss is false */
862	GET_CPUINFO(%r30)
863	lwz	%r30,CI_INTSTK(%r30)	/* get interrupt stack */
864	addi	%r1,%r30,SPILLSTK
865	stwu	%r1,-52(%r1)
866	stw	%r0,48(%r1)		/* save non-volatile registers */
867	stw	%r3,44(%r1)
868	stw	%r4,40(%r1)
869	stw	%r5,36(%r1)
870	stw	%r6,32(%r1)
871	stw	%r7,28(%r1)
872	stw	%r8,24(%r1)
873	stw	%r9,20(%r1)
874	stw	%r10,16(%r1)
875	stw	%r11,12(%r1)
876	stw	%r12,8(%r1)
877	mfxer	%r30			/* save XER */
878	mtsprg	2,%r30
879	mflr	%r30			/* save trap type */
880	mfctr	%r31			/* & CTR */
881	mfdar	%r7
882	mfsrr1	%r4
883	mfdsisr	%r5
884	li	%r6, 0
885s_pte_spill:
886	andi.	%r0,%r4,PSL_PR
887	li	%r3,0
888	bne	1f
889	mr	%r3,%r7
890	bl	pte_spill_r		/* try a spill */
8911:
892	cmpwi	0,%r3,0
893	mtctr	%r31			/* restore CTR */
894	mtlr	%r30			/* and trap type */
895	mfsprg	%r31,2			/* get saved XER */
896	mtxer	%r31			/* restore XER */
897	lwz	%r12,8(%r1)		/* restore non-volatile registers */
898	lwz	%r11,12(%r1)
899	lwz	%r10,16(%r1)
900	lwz	%r9,20(%r1)
901	lwz	%r8,24(%r1)
902	lwz	%r7,28(%r1)
903	lwz	%r6,32(%r1)
904	lwz	%r5,36(%r1)
905	lwz	%r4,40(%r1)
906	lwz	%r3,44(%r1)
907	lwz	%r0,48(%r1)
908	beq	disitrap
909	mtcr	%r29			/* restore CR */
910	mtlr	%r28			/* restore LR */
911	GET_CPUINFO(%r1)
912	lmw	%r28,CI_DISISAVE(%r1)	/* restore r28-r31 */
913	mfsprg	%r1,1			/* restore SP */
914rfi2:	rfi				/* return to trapped code */
915
916/*
917 * ISI second stage fault handler
918 */
919s_isitrap:
920	mfsrr1	%r31			/* test if this may be a spill fault */
921	mtcr	%r31
922	mtsprg	1,%r1			/* save SP */
923	bc	4,1,disitrap		/* branch if table miss is false */
924	GET_CPUINFO(%r30)
925	lwz	%r30,CI_INTSTK(%r30)	/* get interrupt stack */
926	addi	%r1,%r30,SPILLSTK
927	stwu	%r1,-52(%r1)
928	stw	%r0,48(%r1)		/* save non-volatile registers */
929	stw	%r3,44(%r1)
930	stw	%r4,40(%r1)
931	stw	%r5,36(%r1)
932	stw	%r6,32(%r1)
933	stw	%r7,28(%r1)
934	stw	%r8,24(%r1)
935	stw	%r9,20(%r1)
936	stw	%r10,16(%r1)
937	stw	%r11,12(%r1)
938	stw	%r12,8(%r1)
939	mfxer	%r30			/* save XER */
940	mtsprg	2,%r30
941	mflr	%r30			/* save trap type */
942	mfctr	%r31			/* & ctr */
943	mfsrr0	%r7
944	mfsrr1	%r4
945	li	%r5, 0
946	li	%r6, 1
947	b	s_pte_spill		/* above */
948
949/*
950 * External interrupt second level handler
951 */
952#define	INTRENTER							\
953/* Save non-volatile registers: */					\
954	stwu	%r1,-88(%r1);		/* temporarily */		\
955	stw	%r0,84(%r1);						\
956	mfsprg	%r0,1;			/* get original SP */		\
957	stw	%r0,0(%r1);		/* and store it */		\
958	stw	%r3,80(%r1);						\
959	stw	%r4,76(%r1);						\
960	stw	%r5,72(%r1);						\
961	stw	%r6,68(%r1);						\
962	stw	%r7,64(%r1);						\
963	stw	%r8,60(%r1);						\
964	stw	%r9,56(%r1);						\
965	stw	%r10,52(%r1);						\
966	stw	%r11,48(%r1);						\
967	stw	%r12,44(%r1);						\
968	stw	%r28,40(%r1);		/* saved LR */			\
969	stw	%r29,36(%r1);		/* saved CR */			\
970	stw	%r30,32(%r1);		/* saved XER */			\
971	GET_CPUINFO(%r4);						\
972	lmw	%r28,CI_TEMPSAVE(%r4);	/* restore r28-r31 */		\
973	mfctr	%r6;							\
974	lwz	%r5,CI_INTRDEPTH(%r4);			\
975	mfsrr0	%r4;							\
976	mfsrr1	%r3;							\
977	stw	%r6,28(%r1);						\
978	stw	%r5,20(%r1);						\
979	stw	%r4,12(%r1);						\
980	stw	%r3,8(%r1);						\
981/* load all kernel segment registers. */				\
982	lis	3,kernel_pmap_@ha;					\
983	addi	3,3,kernel_pmap_@l;					\
984	lwz	%r5,0(%r3);	mtsr 0,%r5;				\
985	lwz	%r5,4(%r3);	mtsr 1,%r5;				\
986	lwz	%r5,8(%r3);	mtsr 2,%r5;				\
987	lwz	%r5,12(%r3);	mtsr 3,%r5;				\
988	lwz	%r5,16(%r3);	mtsr 4,%r5;				\
989	lwz	%r5,20(%r3);	mtsr 5,%r5;				\
990	lwz	%r5,24(%r3);	mtsr 6,%r5;				\
991	lwz	%r5,28(%r3);	mtsr 7,%r5;				\
992	lwz	%r5,32(%r3);	mtsr 8,%r5;				\
993	lwz	%r5,36(%r3);	mtsr 9,%r5;				\
994	lwz	%r5,40(%r3);	mtsr 10,%r5;				\
995	lwz	%r5,44(%r3);	mtsr 11,%r5;				\
996	lwz	%r5,48(%r3);	mtsr 12,%r5;				\
997/*	lwz	%r5,52(%r3);	mtsr 13,%r5;	- dont load user SR - XXX? */ \
998	lwz	%r5,56(%r3);	mtsr 14,%r5;				\
999	lwz	%r5,60(%r3);	mtsr 15,%r5;				\
1000/* interrupts are recoverable here, and enable translation */		\
1001	mfmsr	%r5;							\
1002	ori	%r5,%r5,(PSL_IR|PSL_DR|PSL_RI);				\
1003	mtmsr	%r5;							\
1004	isync
1005
1006	.globl	extint_call
1007	.type	extint_call,@function
1008extintr:
1009	INTRENTER
1010extint_call:
1011	bl	extint_call			/* to be filled in later */
1012intr_exit:
1013/* Disable interrupts (should already be disabled) and MMU here: */
1014	mfmsr	%r3
1015	andi.	%r3,%r3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l
1016	mtmsr	%r3
1017	isync
1018/* restore possibly overwritten registers: */
1019	lwz	%r12,44(%r1)
1020	lwz	%r11,48(%r1)
1021	lwz	%r10,52(%r1)
1022	lwz	%r9,56(%r1)
1023	lwz	%r8,60(%r1)
1024	lwz	%r7,64(%r1)
1025	lwz	%r6,8(%r1)
1026	lwz	%r5,12(%r1)
1027	lwz	%r4,28(%r1)
1028	lwz	%r3,32(%r1)
1029	mtsrr1	%r6
1030	mtsrr0	%r5
1031	mtctr	%r4
1032	mtxer	%r3
1033
1034	GET_CPUINFO(%r5)
1035	lwz	%r4,CI_INTRDEPTH(%r5)
1036	addi	%r4,%r4,-1		/* adjust reentrancy count */
1037	stw	%r4,CI_INTRDEPTH(%r5)
1038
1039/* Returning to user mode? */
1040	mtcr	%r6			/* saved SRR1 */
1041	bc	4,17,1f			/* branch if PSL_PR is false */
1042	lwz	%r3,CI_CURPM(%r5)	/* get current pmap real address */
1043	/* reload all segment registers. */
1044	lwz	%r4,0(3);	mtsr 0,%r4;
1045	lwz	%r4,4(3);	mtsr 1,%r4;
1046	lwz	%r4,8(3);	mtsr 2,%r4;
1047	lwz	%r4,12(3);	mtsr 3,%r4;
1048	lwz	%r4,16(3);	mtsr 4,%r4;
1049	lwz	%r4,20(3);	mtsr 5,%r4;
1050	lwz	%r4,24(3);	mtsr 6,%r4;
1051	lwz	%r4,28(3);	mtsr 7,%r4;
1052	lwz	%r4,32(3);	mtsr 8,%r4;
1053	lwz	%r4,36(3);	mtsr 9,%r4;
1054	lwz	%r4,40(3);	mtsr 10,%r4;
1055	lwz	%r4,44(3);	mtsr 11,%r4;
1056	lwz	%r4,48(3);	mtsr 12,%r4;
1057	lwz	%r4,52(3);	mtsr 13,%r4;
1058	lwz	%r4,56(3);	mtsr 14,%r4;
1059	lwz	%r4,60(3);	mtsr 15,%r4;
1060	lwz	%r4,CI_CURPROC(%r5)
1061	lwz	%r4,P_MD_ASTPENDING(%r4)	/* Test AST pending */
1062	andi.	%r4,%r4,1
1063	beq	1f
1064/* Setup for entry to realtrap: */
1065	lwz	%r3,0(%r1)		/* get saved SP */
1066	mtsprg	1,%r3
1067	li	%r6,EXC_AST
1068	stmw	%r28,CI_TEMPSAVE(%r5)	/* establish tempsave again */
1069	mtlr	%r6
1070	lwz	%r28,40(%r1)		/* saved LR */
1071	lwz	%r29,36(%r1)		/* saved CR */
1072	lwz	%r6,68(%r1)
1073	lwz	%r5,72(%r1)
1074	lwz	%r4,76(%r1)
1075	lwz	%r3,80(%r1)
1076	lwz	%r0,84(%r1)
1077	b	realtrap
10781:
1079/* Here is the normal exit of extintr: */
1080	lwz	%r5,36(%r1)
1081	lwz	%r6,40(%r1)
1082	mtcr	%r5
1083	mtlr	%r6
1084	lwz	%r6,68(%r1)
1085	lwz	%r5,72(%r1)
1086	lwz	%r4,76(%r1)
1087	lwz	%r3,80(%r1)
1088	lwz	%r0,84(%r1)
1089	lwz	%r1,0(%r1)
1090rfi3:	rfi
1091
1092/*
1093 * Decrementer interrupt second level handler
1094 */
1095	.globl	decrintr
1096decrintr:
1097	INTRENTER
1098	addi	%r3,%r1,8			/* intr frame */
1099	bl	decr_intr
1100	b	intr_exit
1101
1102
1103/*
1104 * int setfault()
1105 *
1106 * Similar to setjmp to setup for handling faults on accesses to user memory.
1107 * Any routine using this may only call bcopy, either the form below,
1108 * or the (currently used) C code optimized, so it doesn't use any non-volatile
1109 * registers.
1110 */
1111	.globl	setfault
1112	.type	setfault,@function
1113setfault:
1114	mflr	%r0
1115	RETGUARD_SETUP_LATE(setfault, %r11, %r0)
1116	mfcr	%r12
1117	GET_CPUINFO(%r4)
1118	lwz	%r4,CI_CURPCB(%r4)
1119	stw	%r3,PCB_FAULT(%r4)
1120	stw	%r0,0(%r3)
1121	stw	%r1,4(%r3)
1122	stmw	%r12,8(%r3)
1123	li	%r3,0
1124	RETGUARD_CHECK(setfault, %r11, %r0)
1125	blr
1126
1127/*
1128 * The following code gets copied to the top of the user stack on process
1129 * execution.  It does signal trampolining on signal delivery.
1130 *
1131 * On entry r1 points to a struct sigframe at bottom of current stack.
1132 * All other registers are unchanged.
1133 */
1134	.section .rodata
1135	.globl	sigcode,esigcode
1136	.type	sigcode,@function
1137	.type	esigcode,@function
1138sigcode:
1139	addi	%r1,%r1,-((16+FPSIG_SIZEOF+15)& ~0xf)		/* reserved space for callee */
1140	addi	%r6,%r1,8
1141	stfd	%f0,0(%r6)
1142	stfd	%f1,8(%r6)
1143	stfd	%f2,16(%r6)
1144	stfd	%f3,24(%r6)
1145	stfd	%f4,32(%r6)
1146	stfd	%f5,40(%r6)
1147	stfd	%f6,48(%r6)
1148	stfd	%f7,56(%r6)
1149	stfd	%f8,64(%r6)
1150	stfd	%f9,72(%r6)
1151	stfd	%f10,80(%r6)
1152	stfd	%f11,88(%r6)
1153	stfd	%f12,96(%r6)
1154	stfd	%f13,104(%r6)
1155	mffs	%f0
1156	stfd	%f0,112(%r6)
1157	lfd	%f0,0(%r6)	/* restore the clobbered register */
1158	blrl
1159	addi	%r6,%r1,8
1160	lfd	%f0,112(%r6)
1161	mtfsf	0xff,%f0
1162	lfd	%f0,0(%r6)
1163	lfd	%f1,8(%r6)
1164	lfd	%f2,16(%r6)
1165	lfd	%f3,24(%r6)
1166	lfd	%f4,32(%r6)
1167	lfd	%f5,40(%r6)
1168	lfd	%f6,48(%r6)
1169	lfd	%f7,56(%r6)
1170	lfd	%f8,64(%r6)
1171	lfd	%f9,72(%r6)
1172	lfd	%f10,80(%r6)
1173	lfd	%f11,88(%r6)
1174	lfd	%f12,96(%r6)
1175	lfd	%f13,104(%r6)
1176	addi	%r3,%r1,((16+FPSIG_SIZEOF+15)&~0xf)+SF_SC	/* compute &sf_sc */
1177	li	%r0,SYS_sigreturn
1178	.globl	sigcodecall
1179sigcodecall:
1180	sc				/* sigreturn(scp) */
1181	.globl	sigcoderet
1182sigcoderet:
1183esigcode:
1184	/* FALLTHROUGH */
1185	.globl	sigfill
1186sigfill:
1187	.long	0		# illegal
1188esigfill:
1189	.align	4
1190	.globl	sigfillsiz
1191sigfillsiz:
1192	.long	esigfill - sigfill
1193
1194	.text
1195
1196#ifdef DDB
1197/*
1198 * Deliberate entry to ddbtrap
1199 */
1200	.globl	ddb_trap
1201ddb_trap:
1202	mtsprg	1,%r1
1203	mfmsr	%r3
1204	mtsrr1	%r3
1205	andi.	%r3,%r3,~(PSL_EE|PSL_ME)@l
1206	mtmsr	%r3				/* disable interrupts */
1207	isync
1208	GET_CPUINFO(%r3)
1209	stmw	%r28,CI_DDBSAVE(%r3)
1210
1211	mflr	%r28
1212	li	%r29,EXC_BPT
1213	mtlr	%r29
1214	mfcr	%r29
1215	mtsrr0	%r28
1216
1217/*
1218 * Now the ddb trap catching code.
1219 */
1220ddbtrap:
1221	/*
1222	 * Do not let FRAME_SETUP() change the return address of, and
1223	 * corrupt, this frame.
1224	 */
1225	FRAME_SETUP_FLAG(CI_DDBSAVE, 0)
1226/* Call C trap code: */
1227	addi	%r3,%r1,8
1228	bl	db_trap_glue
1229	or.	%r3,%r3,%r3
1230	bne	ddbleave
1231/* This wasn't for DDB, so switch to real trap: */
1232	lwz	%r3,FRAME_EXC+8(%r1)	/* save exception */
1233	GET_CPUINFO(%r4)
1234	stw	%r3,CI_DDBSAVE+8(%r4)
1235	FRAME_LEAVE(CI_DDBSAVE)
1236	mtsprg	1,%r1			/* prepare for entrance to realtrap */
1237	GET_CPUINFO(%r1)
1238	stmw	%r28,CI_TEMPSAVE(%r1)
1239	mflr	%r28
1240	mfcr	%r29
1241	lwz	%r31,CI_DDBSAVE+8(%r1)
1242	mtlr	%r31
1243	b	realtrap
1244ddbleave:
1245	FRAME_LEAVE(CI_DDBSAVE)
1246rfi4:	rfi
1247#endif /* DDB */
1248
1249	.globl	rfi_inst
1250rfi_inst:
1251	rfi
1252	.globl	rfid_inst
1253rfid_inst:
1254	rfid
1255	.globl	nop_inst
1256 nop_inst:
1257	nop
1258
1259	.globl	rfi_start
1260rfi_start:
1261	.long	rfi1, rfi1 + 4
1262	.long	rfi2, rfi2 + 4
1263	.long	rfi3, rfi3 + 4
1264#ifdef DDB
1265	.long	rfi4, rfi4 + 4
1266#endif
1267	.long	0, 0
1268
1269
1270	.globl	nopbat_start
1271nopbat_start:
1272	.long	nopbat_1s, nopbat_1e
1273	.long	0, 0
1274
1275	.globl	nop32_start
1276nop32_start:
1277	.long	nop32_1s, nop32_1e
1278	.long	nop32_2s, nop32_2e
1279	.long	nop32_3s, nop32_3e
1280	.long	nop32_4s, nop32_4e
1281	.long	nop32_5s, nop32_5e
1282	.long	nop32_6s, nop32_6e
1283#ifdef DDB
1284	.long	nop32_7s, nop32_7e
1285#endif
1286	.long	0, 0
1287