xref: /openbsd/sys/arch/macppc/macppc/locore.S (revision ab14eefc)
1/*	$OpenBSD: locore.S,v 1.66 2024/10/24 17:37:06 gkoehler 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_IDEPTH(%r1)	/* were we already running on intstk? */
371	cmpwi	%r31,0
372	addi  	%r31,%r31,1
373	stw	%r31,CI_IDEPTH(%r1)
374	lwz	%r1,CI_INTSTK(%r1)	/* get interrupt stack */
375	beq	1f
376	mfsprg	%r1,1			/* yes, get old SP */
3771:
378	ba	extintr
379extsize =		.-extint
380
381/*
382 * And this one for the decrementer interrupt handler.
383 */
384	.globl	decrint,decrsize
385	.type	decrint,@function
386	.type	decrsize,@object
387decrint:
388	mtsprg	1,%r1			/* save SP */
389nop32_6s:
390	mfmsr	%r1
391	clrldi	%r1,%r1,1
392	mtmsrd	%r1
393nop32_6e:
394	GET_CPUINFO(%r1)
395	stmw	%r28,CI_TEMPSAVE(%r1)	/* free r28-r31 */
396	mflr	%r28			/* save LR */
397	mfcr	%r29			/* save CR */
398	mfxer	%r30			/* save XER */
399	lwz	%r31,CI_IDEPTH(%r1)	/* were we already running on intstk? */
400	cmpwi	%r31,0
401	addi  	%r31,%r31,1
402	stw	%r31,CI_IDEPTH(%r1)
403	lwz	%r1,CI_INTSTK(%r1)	/* get interrupt stack */
404	beq	1f
405	mfsprg	%r1,1			/* yes, get old SP */
4061:
407	ba	decrintr
408decrsize =		.-decrint
409
410/*
411 * Now the tlb software load for 603 processors:
412 * (Code essentially from the 603e User Manual, Chapter 5)
413 */
414#define	DMISS	976
415#define	DCMP	977
416#define	HASH1	978
417#define	HASH2	979
418#define	IMISS	980
419#define	ICMP	981
420#define	RPA	982
421
422#define	bdneq	bdnzf 2,
423#define	tlbli	.long	0x7c0007e4+0x800*
424#define	tlbld	.long	0x7c0007a4+0x800*
425
426	.globl	tlbimiss,tlbimsize
427	.type	tlbimiss,@function
428	.type	tlbimsize,@object
429tlbimiss:
430	mfspr	%r2,HASH1		/* get first pointer */
431	li	%r1,8
432	mfctr	%r0			/* save counter */
433	mfspr	%r3,ICMP		/* get first compare value */
434	addi	%r2,%r2,-8		/* predec pointer */
4351:
436	mtctr	%r1			/* load counter */
4372:
438	lwzu	%r1,8(%r2)		/* get next pte */
439	cmplw	0,%r1,%r3		/* see if found pte */
440	bdneq	2b			/* loop if not eq */
441	bne	3f			/* not found */
442	lwz	%r1,4(%r2)		/* load tlb entry lower word */
443	andi.	%r3,%r1,8		/* check G-bit */
444	bne	4f			/* if guarded, take ISI */
445	mtctr	%r0			/* restore counter */
446	mfspr	%r0,IMISS		/* get the miss address for the tlbli */
447	mfsrr1	%r3			/* get the saved cr0 bits */
448	mtcrf	0x80,%r3		/* and restore */
449	ori	%r1,%r1,0x100		/* set the reference bit */
450	mtspr	RPA,%r1			/* set the pte */
451	srwi	%r1,%r1,8		/* get byte 7 of pte */
452	tlbli	0			/* load the itlb */
453	stb	%r1,6(%r2)		/* update page table */
454	rfi
455
4563:	/* not found in pteg */
457	andi.	%r1,%r3,0x40		/* have we already done second hash? */
458	bne	5f
459	mfspr	%r2,HASH2		/* get the second pointer */
460	ori	%r3,%r3,0x40		/* change the compare value */
461	li	%r1,8
462	addi	%r2,%r2,-8		/* predec pointer */
463	b	1b
4644:	/* guarded */
465	mfsrr1	%r3
466	andi.	%r2,%r3,0xffff		/* clean upper srr1 */
467	addis	%r2,%r2,0x800		/* set srr<4> to flag prot violation */
468	b	6f
4695:	/* not found anywhere */
470	mfsrr1	%r3
471	andi.	%r2,%r3,0xffff		/* clean upper srr1 */
472	addis	%r2,%r2,0x4000		/* set srr1<1> to flag pte not found */
4736:
474	mtctr	%r0			/* restore counter */
475	mtsrr1	%r2
476	mfmsr	%r0
477	xoris	%r0,%r0,2		/* flip the msr<tgpr> bit */
478	mtcrf	0x80,%r3		/* restore cr0 */
479	mtmsr	%r0			/* now with native gprs */
480	isync
481	ba	EXC_ISI
482tlbimsize =		.-tlbimiss
483
484	.globl	tlbdlmiss,tlbdlmsize
485	.type	tlbdlmiss,@function
486	.type	tlbdlmsize,@object
487tlbdlmiss:
488	mfspr	%r2,HASH1		/* get first pointer */
489	li	%r1,8
490	mfctr	%r0			/* save counter */
491	mfspr	%r3,DCMP		/* get first compare value */
492	addi	%r2,%r2,-8		/* predec pointer */
4931:
494	mtctr	%r1			/* load counter */
4952:
496	lwzu	%r1,8(%r2)		/* get next pte */
497	cmplw	0,%r1,%r3		/* see if found pte */
498	bdneq	2b			/* loop if not eq */
499	bne	3f			/* not found */
500	lwz	%r1,4(%r2)		/* load tlb entry lower word */
501	mtctr	%r0			/* restore counter */
502	mfspr	%r0,DMISS		/* get the miss address for the tlbld */
503	mfsrr1	%r3			/* get the saved cr0 bits */
504	mtcrf	0x80,%r3		/* and restore */
505	ori	%r1,%r1,0x100		/* set the reference bit */
506	mtspr	RPA,%r1			/* set the pte */
507	srwi	%r1,%r1,8		/* get byte 7 of pte */
508	tlbld	0			/* load the dtlb */
509	stb	%r1,6(%r2)		/* update page table */
510	rfi
511
5123:	/* not found in pteg */
513	andi.	%r1,%r3,0x40		/* have we already done second hash? */
514	bne	5f
515	mfspr	%r2,HASH2		/* get the second pointer */
516	ori	%r3,%r3,0x40		/* change the compare value */
517	li	%r1,8
518	addi	%r2,%r2,-8		/* predec pointer */
519	b	1b
5205:	/* not found anywhere */
521	mfsrr1	%r3
522	lis	%r1,0x4000		/* set dsisr<1> to flag pte not found */
523	mtctr	%r0			/* restore counter */
524	andi.	%r2,%r3,0xffff		/* clean upper srr1 */
525	mtsrr1	%r2
526	mtdsisr	%r1			/* load the dsisr */
527	mfspr	%r1,DMISS		/* get the miss address */
528	mtdar	%r1			/* put in dar */
529	mfmsr	%r0
530	xoris	%r0,%r0,2		/* flip the msr<tgpr> bit */
531	mtcrf	0x80,%r3		/* restore cr0 */
532	mtmsr	%r0			/* now with native gprs */
533	isync
534	ba	EXC_DSI
535tlbdlmsize =		.-tlbdlmiss
536
537	.globl	tlbdsmiss,tlbdsmsize
538	.type	tlbdsmiss,@function
539	.type	tlbdsmsize,@object
540tlbdsmiss:
541	mfspr	%r2,HASH1		/* get first pointer */
542	li	%r1,8
543	mfctr	%r0			/* save counter */
544	mfspr	%r3,DCMP		/* get first compare value */
545	addi	%r2,%r2,-8		/* predec pointer */
5461:
547	mtctr	%r1			/* load counter */
5482:
549	lwzu	%r1,8(%r2)		/* get next pte */
550	cmplw	0,%r1,%r3		/* see if found pte */
551	bdneq	2b			/* loop if not eq */
552	bne	3f			/* not found */
553	lwz	%r1,4(%r2)		/* load tlb entry lower word */
554	andi.	%r3,%r1,0x80		/* check the C-bit */
555	beq	4f
5565:
557	mtctr	%r0			/* restore counter */
558	mfspr	%r0,DMISS		/* get the miss address for the tlbld */
559	mfsrr1	%r3			/* get the saved cr0 bits */
560	mtcrf	0x80,%r3		/* and restore */
561	mtspr	RPA,%r1			/* set the pte */
562	tlbld	0			/* load the dtlb */
563	rfi
564
5653:	/* not found in pteg */
566	andi.	%r1,%r3,0x40		/* have we already done second hash? */
567	bne	5f
568	mfspr	%r2,HASH2		/* get the second pointer */
569	ori	%r3,%r3,0x40		/* change the compare value */
570	li	%r1,8
571	addi	%r2,%r2,-8		/* predec pointer */
572	b	1b
5734:	/* found, but C-bit = 0 */
574	rlwinm.	%r3,%r1,30,0,1		/* test PP */
575	bge-	7f
576	andi.	%r3,%r1,1
577	beq+	8f
5789:	/* found, but protection violation (PP==00)*/
579	mfsrr1	%r3
580	lis	%r1,0xa00	/* indicate protection violation on store */
581	b	1f
5827:	/* found, PP=1x */
583	mfspr	%r3,DMISS		/* get the miss address */
584	mfsrin	%r1,%r3			/* get the segment register */
585	mfsrr1	%r3
586	rlwinm	%r3,%r3,18,31,31	/* get PR-bit */
587	rlwnm.	%r1,%r1,%r3,1,1		/* get the key */
588	bne-	9b			/* protection violation */
5898:	/* found, set reference/change bits */
590	lwz	%r1,4(%r2)		/* reload tlb entry */
591	ori	%r1,%r1,0x180
592	sth	%r1,6(%r2)
593	b	5b
5945:	/* not found anywhere */
595	mfsrr1	%r3
596	lis	%r1,0x4200		/* set dsisr<1> to flag pte not found */
597					/* dsisr<6> to flag store */
5981:
599	mtctr	%r0			/* restore counter */
600	andi.	%r2,%r3,0xffff		/* clean upper srr1 */
601	mtsrr1	%r2
602	mtdsisr	%r1			/* load the dsisr */
603	mfspr	%r1,DMISS		/* get the miss address */
604	mtdar	%r1			/* put in dar */
605	mfmsr	%r0
606	xoris	%r0,%r0,2		/* flip the msr<tgpr> bit */
607	mtcrf	0x80,%r3		/* restore cr0 */
608	mtmsr	%r0			/* now with native gprs */
609	isync
610	ba	EXC_DSI
611tlbdsmsize =		.-tlbdsmiss
612
613#ifdef DDB
614/*
615 * In case of DDB we want a separate trap catcher for it
616 */
617	.globl	ddblow,ddbsize
618ddblow:
619	mtsprg	1,%r1			/* save SP */
620nop32_7s:
621	mfmsr	%r1
622	clrldi	%r1,%r1,1
623	mtmsrd	%r1
624nop32_7e:
625	GET_CPUINFO(%r1)
626	stmw	%r28,CI_DDBSAVE(%r1)	/* free r28-r31 */
627	mflr	%r28			/* save LR */
628	mfcr	%r29			/* save CR */
629	GET_CPUINFO(%r30)
630	lwz	%r30,CI_INTSTK(%r30)	/* get interrupt stack */
631	addi	%r1,%r30,(SPILLSTK+DDBSTK)
632	bla	ddbtrap
633ddbsize =		.-ddblow
634#endif  /* DDB */
635
636/*
637 * If this interrupt occurred between the runqueue check and the setting
638 * of the POW bit, do no enter to sleep.  We do that in order to process
639 * the result of this interrupt directly and not when coming back from
640 * sleep, when the next clock tick or interrupt will fire.
641 */
642#define CPU_IDLE_CHECK(sr1,sr2,sr3,rSRR0,flag)				\
643	GET_CPUINFO(sr1);						\
644	lwz	sr2,CI_FLAGS(sr1);					\
645	andi.	sr3,sr2,flag@l;						\
646	beq	1f;							\
647	andi.	sr2,sr2,~flag@l;					\
648	stw	sr2,CI_FLAGS(sr1);					\
649	lis	rSRR0,idledone@ha;					\
650	addi	rSRR0,rSRR0,idledone@l;					\
6511:
652
653/*
654 * FRAME_SETUP assumes:
655 *	SPRG1		SP (1)
656 *	savearea	r28-r31,DAR,DSISR	(DAR & DSISR only for DSI traps)
657 *	28		LR
658 *	29		CR
659 *	1		kernel stack
660 *	LR		trap type
661 *	SRR0/1		as at start of trap
662 */
663#define FRAME_SETUP(savearea)	FRAME_SETUP_FLAG(savearea, CI_FLAGS_SLEEPING)
664
665#define	FRAME_SETUP_FLAG(savearea, flag)				\
666/* Have to enable translation to allow access of kernel stack: */	\
667	GET_CPUINFO(%r31);						\
668	mfsrr0	%r30;							\
669	stw	%r30,savearea+24(%r31);					\
670	mfsrr1	%r30;							\
671	stw	%r30,savearea+28(%r31);					\
672	/* load all kernel segment registers. */			\
673	lis	%r31,kernel_pmap_@ha;					\
674	addi	%r31,%r31,kernel_pmap_@l;				\
675	lwz	%r30,0(%r31);	mtsr	0,%r30;				\
676	lwz	%r30,4(%r31);	mtsr	1,%r30;				\
677	lwz	%r30,8(%r31);	mtsr	2,%r30;				\
678	lwz	%r30,12(%r31);	mtsr	3,%r30;				\
679	lwz	%r30,16(%r31);	mtsr	4,%r30;				\
680	lwz	%r30,20(%r31);	mtsr	5,%r30;				\
681	lwz	%r30,24(%r31);	mtsr	6,%r30;				\
682	lwz	%r30,28(%r31);	mtsr	7,%r30;				\
683	lwz	%r30,32(%r31);	mtsr	8,%r30;				\
684	lwz	%r30,36(%r31);	mtsr	9,%r30;				\
685	lwz	%r30,40(%r31);	mtsr	10,%r30;			\
686	lwz	%r30,44(%r31);	mtsr	11,%r30;			\
687	lwz	%r30,48(%r31);	mtsr	12,%r30;			\
688/*	lwz	%r30,52(%r31);	mtsr 13,%r30; - dont load user SR - XXX? */ \
689	lwz	%r30,56(%r31);	mtsr	14,%r30;			\
690	lwz	%r30,60(%r31);	mtsr	15,%r30;			\
691	mfmsr	%r30;							\
692	ori	%r30,%r30,(PSL_DR|PSL_IR);				\
693	mtmsr	%r30;							\
694	isync;								\
695	mfsprg	%r31,1;							\
696	stwu	%r31,-FRAMELEN(%r1);					\
697	stw	%r0,FRAME_0+8(%r1);					\
698	stw	%r31,FRAME_1+8(%r1);					\
699	stw	%r2,FRAME_2+8(%r1);					\
700	stw	%r28,FRAME_LR+8(%r1);					\
701	stw	%r29,FRAME_CR+8(%r1);					\
702	GET_CPUINFO(%r2);						\
703	lmw	%r28,savearea(%r2);					\
704	stmw	%r3,FRAME_3+8(%r1);					\
705	lmw	%r28,savearea+16(%r2);					\
706	mfxer	%r3;							\
707	mfctr	%r4;							\
708	mflr	%r5;							\
709	andi.	%r5,%r5,0xff00;						\
710	stw	%r3,FRAME_XER+8(%r1);					\
711	stw	%r4,FRAME_CTR+8(%r1);					\
712	stw	%r5,FRAME_EXC+8(%r1);					\
713	stw	%r28,FRAME_DAR+8(%r1);					\
714	stw	%r29,FRAME_DSISR+8(%r1);				\
715	CPU_IDLE_CHECK(%r5,%r6,%r0,%r30,flag)				\
716	stw	%r30,FRAME_SRR0+8(%r1);					\
717	stw	%r31,FRAME_SRR1+8(%r1)
718
719#define	FRAME_LEAVE(savearea)						\
720/* Now restore regs: */							\
721	lwz	%r2,FRAME_SRR0+8(%r1);					\
722	lwz	%r3,FRAME_SRR1+8(%r1);					\
723	lwz	%r4,FRAME_CTR+8(%r1);					\
724	lwz	%r5,FRAME_XER+8(%r1);					\
725	lwz	%r6,FRAME_LR+8(%r1);					\
726	GET_CPUINFO(%r7);						\
727	stw	%r2,savearea(%r7);					\
728	stw	%r3,savearea+4(%r7);					\
729	lwz	%r7,FRAME_CR+8(%r1);					\
730	mtctr	%r4;							\
731	mtxer	%r5;							\
732	mtlr	%r6;							\
733	mtsprg	1,%r7;			/* save cr */			\
734	lmw	%r2,FRAME_2+8(%r1);					\
735	lwz	%r0,FRAME_0+8(%r1);					\
736	lwz	%r1,FRAME_1+8(%r1);					\
737	mtsprg	2,%r2;			/* save r2 & r3 */		\
738	mtsprg	3,%r3;							\
739/* Disable translation, machine check and recoverability: */		\
740	mfmsr	%r2;							\
741	lis	%r3,(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@ha;			\
742	addi	%r3,%r3,(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l;		\
743	andc	%r2,%r2,%r3;						\
744	mtmsr	%r2;							\
745	isync;								\
746/* Decide whether we return to user mode: */				\
747	GET_CPUINFO(%r2);						\
748	lwz	%r3,savearea+4(%r2);					\
749	mtcr	%r3;							\
750	bc	4,17,1f;		/* branch if PSL_PR is false */	\
751/* Restore user & kernel access SR: */					\
752	lwz	%r2,CI_CURPM(%r2);	/* get real address of pmap */	\
753	lwz	%r3,0(%r2);	mtsr	0,%r3;				\
754	lwz	%r3,4(%r2);	mtsr	1,%r3;				\
755	lwz	%r3,8(%r2);	mtsr	2,%r3;				\
756	lwz	%r3,12(%r2);	mtsr	3,%r3;				\
757	lwz	%r3,16(%r2);	mtsr	4,%r3;				\
758	lwz	%r3,20(%r2);	mtsr	5,%r3;				\
759	lwz	%r3,24(%r2);	mtsr	6,%r3;				\
760	lwz	%r3,28(%r2);	mtsr	7,%r3;				\
761	lwz	%r3,32(%r2);	mtsr	8,%r3;				\
762	lwz	%r3,36(%r2);	mtsr	9,%r3;				\
763	lwz	%r3,40(%r2);	mtsr	10,%r3;				\
764	lwz	%r3,44(%r2);	mtsr	11,%r3;				\
765	lwz	%r3,48(%r2);	mtsr	12,%r3;				\
766	lwz	%r3,52(%r2);	mtsr	13,%r3;				\
767	lwz	%r3,56(%r2);	mtsr	14,%r3;				\
768	lwz	%r3,60(%r2);	mtsr	15,%r3;				\
7691:	mfsprg	%r2,1;			/* restore cr */		\
770	mtcr	%r2;							\
771	GET_CPUINFO(%r2);						\
772	lwz	%r3,savearea(%r2);					\
773	mtsrr0	%r3;							\
774	lwz	%r3,savearea+4(%r2);					\
775	mtsrr1	%r3;							\
776	mfsprg	%r2,2;			/* restore r2 & r3 */		\
777	mfsprg	%r3,3
778
779/*
780 * Preamble code for DSI/ISI traps
781 */
782disitrap:
783	GET_CPUINFO(%r1)
784	lmw	%r30,CI_DISISAVE(%r1)
785	stmw	%r30,CI_TEMPSAVE(%r1)
786	lmw	%r30,CI_DISISAVE+8(%r1)
787	stmw	%r30,CI_TEMPSAVE+8(%r1)
788	mfdar	%r30
789	mfdsisr	%r31
790	stmw	%r30,CI_TEMPSAVE+16(%r1)
791realtrap:
792	/* Test whether we already had PR set */
793	mfsrr1	%r1
794	mtcr	%r1
795	/* restore SP (might have been overwritten) */
796	mfsprg	%r1,1
797	bc	4,17,s_trap		/* branch if PSL_PR is false */
798	GET_CPUINFO(%r1)
799	lwz	%r1,CI_CURPCB(%r1)
800	addi	%r1,%r1,USPACE		/* stack is top of user struct */
801/*
802 * Now the common trap catching code.
803 */
804	.globl	s_trap
805s_trap:
806	FRAME_SETUP(CI_TEMPSAVE)
807/* Now we can recover interrupts again: */
808	mfmsr	%r7
809	mfsrr1	%r31
810	andi.	%r31,%r31,PSL_EE	/* restore EE from previous context */
811	or	%r7,%r7,%r31
812	ori	%r7,%r7,(PSL_ME|PSL_RI)
813	mtmsr	%r7
814	isync
815/* Call C trap code: */
816trapagain:
817	addi	%r3,%r1,8
818	bl	trap
819
820	.globl	trapexit
821trapexit:
822/* Disable interrupts: */
823	mfmsr	%r3
824	andi.	%r3,%r3,~PSL_EE@l
825	mtmsr	%r3
826	isync
827/* Test AST pending: */
828	lwz	%r5,FRAME_SRR1+8(%r1)
829	mtcr	%r5
830	bc	4,17,1f			/* branch if PSL_PR is false */
831	GET_CPUINFO(%r3)
832	lwz	%r4,CI_CURPROC(%r3)
833	lwz	%r4,P_MD_ASTPENDING(%r4)
834	andi.	%r4,%r4,1
835	beq	1f
836	li	%r6,EXC_AST
837	stw	%r6,FRAME_EXC+8(%r1)
838	b	trapagain
8391:
840	FRAME_LEAVE(CI_TEMPSAVE)
841rfi1:	rfi
842
843/*
844 * Child comes here at the end of a fork.
845 * Mostly similar to the above.
846 */
847	.globl	proc_trampoline
848	.type	proc_trampoline,@function
849proc_trampoline:
850	bl	proc_trampoline_mi
851	mtlr	%r31
852	mr	%r3,%r30
853	blrl				/* jump indirect to r31 */
854	b	trapexit
855
856/*
857 * DSI second stage fault handler
858 */
859s_dsitrap:
860	mfdsisr	%r31			/* test if this is spill fault */
861	mtcr	%r31
862	mtsprg	1,%r1			/* save SP */
863	bc	4,1,disitrap		/* branch if table miss is false */
864	GET_CPUINFO(%r30)
865	lwz	%r30,CI_INTSTK(%r30)	/* get interrupt stack */
866	addi	%r1,%r30,SPILLSTK
867	stwu	%r1,-52(%r1)
868	stw	%r0,48(%r1)		/* save non-volatile registers */
869	stw	%r3,44(%r1)
870	stw	%r4,40(%r1)
871	stw	%r5,36(%r1)
872	stw	%r6,32(%r1)
873	stw	%r7,28(%r1)
874	stw	%r8,24(%r1)
875	stw	%r9,20(%r1)
876	stw	%r10,16(%r1)
877	stw	%r11,12(%r1)
878	stw	%r12,8(%r1)
879	mfxer	%r30			/* save XER */
880	mtsprg	2,%r30
881	mflr	%r30			/* save trap type */
882	mfctr	%r31			/* & CTR */
883	mfdar	%r7
884	mfsrr1	%r4
885	mfdsisr	%r5
886	li	%r6, 0
887s_pte_spill:
888	andi.	%r0,%r4,PSL_PR
889	li	%r3,0
890	bne	1f
891	mr	%r3,%r7
892	bl	pte_spill_r		/* try a spill */
8931:
894	cmpwi	0,%r3,0
895	mtctr	%r31			/* restore CTR */
896	mtlr	%r30			/* and trap type */
897	mfsprg	%r31,2			/* get saved XER */
898	mtxer	%r31			/* restore XER */
899	lwz	%r12,8(%r1)		/* restore non-volatile registers */
900	lwz	%r11,12(%r1)
901	lwz	%r10,16(%r1)
902	lwz	%r9,20(%r1)
903	lwz	%r8,24(%r1)
904	lwz	%r7,28(%r1)
905	lwz	%r6,32(%r1)
906	lwz	%r5,36(%r1)
907	lwz	%r4,40(%r1)
908	lwz	%r3,44(%r1)
909	lwz	%r0,48(%r1)
910	beq	disitrap
911	mtcr	%r29			/* restore CR */
912	mtlr	%r28			/* restore LR */
913	GET_CPUINFO(%r1)
914	lmw	%r28,CI_DISISAVE(%r1)	/* restore r28-r31 */
915	mfsprg	%r1,1			/* restore SP */
916rfi2:	rfi				/* return to trapped code */
917
918/*
919 * ISI second stage fault handler
920 */
921s_isitrap:
922	mfsrr1	%r31			/* test if this may be a spill fault */
923	mtcr	%r31
924	mtsprg	1,%r1			/* save SP */
925	bc	4,1,disitrap		/* branch if table miss is false */
926	GET_CPUINFO(%r30)
927	lwz	%r30,CI_INTSTK(%r30)	/* get interrupt stack */
928	addi	%r1,%r30,SPILLSTK
929	stwu	%r1,-52(%r1)
930	stw	%r0,48(%r1)		/* save non-volatile registers */
931	stw	%r3,44(%r1)
932	stw	%r4,40(%r1)
933	stw	%r5,36(%r1)
934	stw	%r6,32(%r1)
935	stw	%r7,28(%r1)
936	stw	%r8,24(%r1)
937	stw	%r9,20(%r1)
938	stw	%r10,16(%r1)
939	stw	%r11,12(%r1)
940	stw	%r12,8(%r1)
941	mfxer	%r30			/* save XER */
942	mtsprg	2,%r30
943	mflr	%r30			/* save trap type */
944	mfctr	%r31			/* & ctr */
945	mfsrr0	%r7
946	mfsrr1	%r4
947	li	%r5, 0
948	li	%r6, 1
949	b	s_pte_spill		/* above */
950
951/*
952 * External interrupt second level handler
953 */
954#define	INTRENTER							\
955/* Save non-volatile registers: */					\
956	stwu	%r1,-88(%r1);		/* temporarily */		\
957	stw	%r0,84(%r1);						\
958	mfsprg	%r0,1;			/* get original SP */		\
959	stw	%r0,0(%r1);		/* and store it */		\
960	stw	%r3,80(%r1);						\
961	stw	%r4,76(%r1);						\
962	stw	%r5,72(%r1);						\
963	stw	%r6,68(%r1);						\
964	stw	%r7,64(%r1);						\
965	stw	%r8,60(%r1);						\
966	stw	%r9,56(%r1);						\
967	stw	%r10,52(%r1);						\
968	stw	%r11,48(%r1);						\
969	stw	%r12,44(%r1);						\
970	stw	%r28,40(%r1);		/* saved LR */			\
971	stw	%r29,36(%r1);		/* saved CR */			\
972	stw	%r30,32(%r1);		/* saved XER */			\
973	GET_CPUINFO(%r4);						\
974	lmw	%r28,CI_TEMPSAVE(%r4);	/* restore r28-r31 */		\
975	mfctr	%r6;							\
976	lwz	%r5,CI_IDEPTH(%r4);			\
977	mfsrr0	%r4;							\
978	mfsrr1	%r3;							\
979	stw	%r6,28(%r1);						\
980	stw	%r5,20(%r1);						\
981	stw	%r4,12(%r1);						\
982	stw	%r3,8(%r1);						\
983/* load all kernel segment registers. */				\
984	lis	3,kernel_pmap_@ha;					\
985	addi	3,3,kernel_pmap_@l;					\
986	lwz	%r5,0(%r3);	mtsr 0,%r5;				\
987	lwz	%r5,4(%r3);	mtsr 1,%r5;				\
988	lwz	%r5,8(%r3);	mtsr 2,%r5;				\
989	lwz	%r5,12(%r3);	mtsr 3,%r5;				\
990	lwz	%r5,16(%r3);	mtsr 4,%r5;				\
991	lwz	%r5,20(%r3);	mtsr 5,%r5;				\
992	lwz	%r5,24(%r3);	mtsr 6,%r5;				\
993	lwz	%r5,28(%r3);	mtsr 7,%r5;				\
994	lwz	%r5,32(%r3);	mtsr 8,%r5;				\
995	lwz	%r5,36(%r3);	mtsr 9,%r5;				\
996	lwz	%r5,40(%r3);	mtsr 10,%r5;				\
997	lwz	%r5,44(%r3);	mtsr 11,%r5;				\
998	lwz	%r5,48(%r3);	mtsr 12,%r5;				\
999/*	lwz	%r5,52(%r3);	mtsr 13,%r5;	- dont load user SR - XXX? */ \
1000	lwz	%r5,56(%r3);	mtsr 14,%r5;				\
1001	lwz	%r5,60(%r3);	mtsr 15,%r5;				\
1002/* interrupts are recoverable here, and enable translation */		\
1003	mfmsr	%r5;							\
1004	ori	%r5,%r5,(PSL_IR|PSL_DR|PSL_RI);				\
1005	mtmsr	%r5;							\
1006	isync
1007
1008	.globl	extint_call
1009	.type	extint_call,@function
1010extintr:
1011	INTRENTER
1012extint_call:
1013	bl	extint_call			/* to be filled in later */
1014intr_exit:
1015/* Disable interrupts (should already be disabled) and MMU here: */
1016	mfmsr	%r3
1017	andi.	%r3,%r3,~(PSL_EE|PSL_ME|PSL_RI|PSL_DR|PSL_IR)@l
1018	mtmsr	%r3
1019	isync
1020/* restore possibly overwritten registers: */
1021	lwz	%r12,44(%r1)
1022	lwz	%r11,48(%r1)
1023	lwz	%r10,52(%r1)
1024	lwz	%r9,56(%r1)
1025	lwz	%r8,60(%r1)
1026	lwz	%r7,64(%r1)
1027	lwz	%r6,8(%r1)
1028	lwz	%r5,12(%r1)
1029	lwz	%r4,28(%r1)
1030	lwz	%r3,32(%r1)
1031	mtsrr1	%r6
1032	mtsrr0	%r5
1033	mtctr	%r4
1034	mtxer	%r3
1035
1036	GET_CPUINFO(%r5)
1037	lwz	%r4,CI_IDEPTH(%r5)
1038	addi	%r4,%r4,-1		/* adjust reentrancy count */
1039	stw	%r4,CI_IDEPTH(%r5)
1040
1041/* Returning to user mode? */
1042	mtcr	%r6			/* saved SRR1 */
1043	bc	4,17,1f			/* branch if PSL_PR is false */
1044	lwz	%r3,CI_CURPM(%r5)	/* get current pmap real address */
1045	/* reload all segment registers. */
1046	lwz	%r4,0(3);	mtsr 0,%r4;
1047	lwz	%r4,4(3);	mtsr 1,%r4;
1048	lwz	%r4,8(3);	mtsr 2,%r4;
1049	lwz	%r4,12(3);	mtsr 3,%r4;
1050	lwz	%r4,16(3);	mtsr 4,%r4;
1051	lwz	%r4,20(3);	mtsr 5,%r4;
1052	lwz	%r4,24(3);	mtsr 6,%r4;
1053	lwz	%r4,28(3);	mtsr 7,%r4;
1054	lwz	%r4,32(3);	mtsr 8,%r4;
1055	lwz	%r4,36(3);	mtsr 9,%r4;
1056	lwz	%r4,40(3);	mtsr 10,%r4;
1057	lwz	%r4,44(3);	mtsr 11,%r4;
1058	lwz	%r4,48(3);	mtsr 12,%r4;
1059	lwz	%r4,52(3);	mtsr 13,%r4;
1060	lwz	%r4,56(3);	mtsr 14,%r4;
1061	lwz	%r4,60(3);	mtsr 15,%r4;
1062	lwz	%r4,CI_CURPROC(%r5)
1063	lwz	%r4,P_MD_ASTPENDING(%r4)	/* Test AST pending */
1064	andi.	%r4,%r4,1
1065	beq	1f
1066/* Setup for entry to realtrap: */
1067	lwz	%r3,0(%r1)		/* get saved SP */
1068	mtsprg	1,%r3
1069	li	%r6,EXC_AST
1070	stmw	%r28,CI_TEMPSAVE(%r5)	/* establish tempsave again */
1071	mtlr	%r6
1072	lwz	%r28,40(%r1)		/* saved LR */
1073	lwz	%r29,36(%r1)		/* saved CR */
1074	lwz	%r6,68(%r1)
1075	lwz	%r5,72(%r1)
1076	lwz	%r4,76(%r1)
1077	lwz	%r3,80(%r1)
1078	lwz	%r0,84(%r1)
1079	b	realtrap
10801:
1081/* Here is the normal exit of extintr: */
1082	lwz	%r5,36(%r1)
1083	lwz	%r6,40(%r1)
1084	mtcr	%r5
1085	mtlr	%r6
1086	lwz	%r6,68(%r1)
1087	lwz	%r5,72(%r1)
1088	lwz	%r4,76(%r1)
1089	lwz	%r3,80(%r1)
1090	lwz	%r0,84(%r1)
1091	lwz	%r1,0(%r1)
1092rfi3:	rfi
1093
1094/*
1095 * Decrementer interrupt second level handler
1096 */
1097	.globl	decrintr
1098decrintr:
1099	INTRENTER
1100	addi	%r3,%r1,8			/* intr frame */
1101	bl	decr_intr
1102	b	intr_exit
1103
1104
1105/*
1106 * int setfault()
1107 *
1108 * Similar to setjmp to setup for handling faults on accesses to user memory.
1109 * Any routine using this may only call bcopy, either the form below,
1110 * or the (currently used) C code optimized, so it doesn't use any non-volatile
1111 * registers.
1112 */
1113	.globl	setfault
1114	.type	setfault,@function
1115setfault:
1116	mflr	%r0
1117	RETGUARD_SETUP_LATE(setfault, %r11, %r0)
1118	mfcr	%r12
1119	GET_CPUINFO(%r4)
1120	lwz	%r4,CI_CURPCB(%r4)
1121	stw	%r3,PCB_FAULT(%r4)
1122	stw	%r0,0(%r3)
1123	stw	%r1,4(%r3)
1124	stmw	%r12,8(%r3)
1125	li	%r3,0
1126	RETGUARD_CHECK(setfault, %r11, %r0)
1127	blr
1128
1129/*
1130 * The following code gets copied to the top of the user stack on process
1131 * execution.  It does signal trampolining on signal delivery.
1132 *
1133 * On entry r1 points to a struct sigframe at bottom of current stack.
1134 * All other registers are unchanged.
1135 */
1136	.section .rodata
1137	.globl	sigcode,esigcode
1138	.type	sigcode,@function
1139	.type	esigcode,@function
1140sigcode:
1141	addi	%r1,%r1,-((16+FPSIG_SIZEOF+15)& ~0xf)		/* reserved space for callee */
1142	addi	%r6,%r1,8
1143	stfd	%f0,0(%r6)
1144	stfd	%f1,8(%r6)
1145	stfd	%f2,16(%r6)
1146	stfd	%f3,24(%r6)
1147	stfd	%f4,32(%r6)
1148	stfd	%f5,40(%r6)
1149	stfd	%f6,48(%r6)
1150	stfd	%f7,56(%r6)
1151	stfd	%f8,64(%r6)
1152	stfd	%f9,72(%r6)
1153	stfd	%f10,80(%r6)
1154	stfd	%f11,88(%r6)
1155	stfd	%f12,96(%r6)
1156	stfd	%f13,104(%r6)
1157	mffs	%f0
1158	stfd	%f0,112(%r6)
1159	lfd	%f0,0(%r6)	/* restore the clobbered register */
1160	blrl
1161	addi	%r6,%r1,8
1162	lfd	%f0,112(%r6)
1163	mtfsf	0xff,%f0
1164	lfd	%f0,0(%r6)
1165	lfd	%f1,8(%r6)
1166	lfd	%f2,16(%r6)
1167	lfd	%f3,24(%r6)
1168	lfd	%f4,32(%r6)
1169	lfd	%f5,40(%r6)
1170	lfd	%f6,48(%r6)
1171	lfd	%f7,56(%r6)
1172	lfd	%f8,64(%r6)
1173	lfd	%f9,72(%r6)
1174	lfd	%f10,80(%r6)
1175	lfd	%f11,88(%r6)
1176	lfd	%f12,96(%r6)
1177	lfd	%f13,104(%r6)
1178	addi	%r3,%r1,((16+FPSIG_SIZEOF+15)&~0xf)+SF_SC	/* compute &sf_sc */
1179	li	%r0,SYS_sigreturn
1180	.globl	sigcodecall
1181sigcodecall:
1182	sc				/* sigreturn(scp) */
1183	.globl	sigcoderet
1184sigcoderet:
1185esigcode:
1186	/* FALLTHROUGH */
1187	.globl	sigfill
1188sigfill:
1189	.long	0		# illegal
1190esigfill:
1191	.align	4
1192	.globl	sigfillsiz
1193sigfillsiz:
1194	.long	esigfill - sigfill
1195
1196	.text
1197
1198#ifdef DDB
1199/*
1200 * Deliberate entry to ddbtrap
1201 */
1202	.globl	ddb_trap
1203ddb_trap:
1204	mtsprg	1,%r1
1205	mfmsr	%r3
1206	mtsrr1	%r3
1207	andi.	%r3,%r3,~(PSL_EE|PSL_ME)@l
1208	mtmsr	%r3				/* disable interrupts */
1209	isync
1210	GET_CPUINFO(%r3)
1211	stmw	%r28,CI_DDBSAVE(%r3)
1212
1213	mflr	%r28
1214	li	%r29,EXC_BPT
1215	mtlr	%r29
1216	mfcr	%r29
1217	mtsrr0	%r28
1218
1219/*
1220 * Now the ddb trap catching code.
1221 */
1222ddbtrap:
1223	/*
1224	 * Do not let FRAME_SETUP() change the return address of, and
1225	 * corrupt, this frame.
1226	 */
1227	FRAME_SETUP_FLAG(CI_DDBSAVE, 0)
1228/* Call C trap code: */
1229	addi	%r3,%r1,8
1230	bl	db_trap_glue
1231	or.	%r3,%r3,%r3
1232	bne	ddbleave
1233/* This wasn't for DDB, so switch to real trap: */
1234	lwz	%r3,FRAME_EXC+8(%r1)	/* save exception */
1235	GET_CPUINFO(%r4)
1236	stw	%r3,CI_DDBSAVE+8(%r4)
1237	FRAME_LEAVE(CI_DDBSAVE)
1238	mtsprg	1,%r1			/* prepare for entrance to realtrap */
1239	GET_CPUINFO(%r1)
1240	stmw	%r28,CI_TEMPSAVE(%r1)
1241	mflr	%r28
1242	mfcr	%r29
1243	lwz	%r31,CI_DDBSAVE+8(%r1)
1244	mtlr	%r31
1245	b	realtrap
1246ddbleave:
1247	FRAME_LEAVE(CI_DDBSAVE)
1248rfi4:	rfi
1249#endif /* DDB */
1250
1251	.globl	rfi_inst
1252rfi_inst:
1253	rfi
1254	.globl	rfid_inst
1255rfid_inst:
1256	rfid
1257	.globl	nop_inst
1258 nop_inst:
1259	nop
1260
1261	.globl	rfi_start
1262rfi_start:
1263	.long	rfi1, rfi1 + 4
1264	.long	rfi2, rfi2 + 4
1265	.long	rfi3, rfi3 + 4
1266#ifdef DDB
1267	.long	rfi4, rfi4 + 4
1268#endif
1269	.long	0, 0
1270
1271
1272	.globl	nopbat_start
1273nopbat_start:
1274	.long	nopbat_1s, nopbat_1e
1275	.long	0, 0
1276
1277	.globl	nop32_start
1278nop32_start:
1279	.long	nop32_1s, nop32_1e
1280	.long	nop32_2s, nop32_2e
1281	.long	nop32_3s, nop32_3e
1282	.long	nop32_4s, nop32_4e
1283	.long	nop32_5s, nop32_5e
1284	.long	nop32_6s, nop32_6e
1285#ifdef DDB
1286	.long	nop32_7s, nop32_7e
1287#endif
1288	.long	0, 0
1289