xref: /plan9/sys/src/9/ppc/l.s (revision 5d9de2d38d2503efca29e12e0e32036368a7a75f)
1#include	"mem.h"
2
3/* use of SPRG registers in save/restore */
4#define	SAVER0	SPRG0
5#define	SAVER1	SPRG1
6#define	SAVELR	SPRG2
7#define	SAVEXX	SPRG3
8
9#ifdef ucuconf
10/* These only exist on the PPC 755: */
11#define	SAVER4	SPRG4
12#define	SAVER5	SPRG5
13#define	SAVER6	SPRG6
14#define	SAVER7	SPRG7
15#endif /* ucuconf */
16
17/* special instruction definitions */
18#define	BDNZ		BC	16, 0,
19#define	BDNE		BC	0, 2,
20#define	MTCRF(r, crm)	WORD	$((31<<26)|((r)<<21)|(crm<<12)|(144<<1))
21
22/* #define	TLBIA	WORD	$((31<<26)|(370<<1)) Not implemented on the 603e */
23#define	TLBSYNC		WORD	$((31<<26)|(566<<1))
24#define	TLBLI(n)	WORD	$((31<<26)|((n)<<11)|(1010<<1))
25#define	TLBLD(n)	WORD	$((31<<26)|((n)<<11)|(978<<1))
26
27/* on some models mtmsr doesn't synchronise enough (eg, 603e) */
28#define	MSRSYNC	SYNC
29
30#define	UREGSPACE	(UREGSIZE+8)
31
32TEXT start(SB), $-4
33
34	/*
35	 * setup MSR
36	 * turn off interrupts
37	 * use 0x000 as exception prefix
38	 * enable machine check
39	 */
40	MOVW	MSR, R3
41	MOVW	$(MSR_ME|MSR_EE|MSR_IP), R4
42	ANDN	R4, R3
43	SYNC
44	MOVW	R3, MSR
45	MSRSYNC
46
47	/* except during trap handling, R0 is zero from now on */
48	MOVW	$0, R0
49
50	/* setup SB for pre mmu */
51	MOVW	$setSB(SB), R2
52	MOVW	$KZERO, R3
53	ANDN	R3, R2
54
55	/* before this we're not running above KZERO */
56	BL	mmuinit0(SB)
57	/* after this we are */
58
59#ifdef ucuconf
60	MOVW	$0x2000000, R4		/* size */
61	MOVW	$0, R3			/* base address */
62	RLWNM	$0, R3, $~(CACHELINESZ-1), R5
63	CMP	R4, $0
64	BLE	_dcf1
65	SUB	R5, R3
66	ADD	R3, R4
67	ADD	$(CACHELINESZ-1), R4
68	SRAW	$CACHELINELOG, R4
69	MOVW	R4, CTR
70_dcf0:	DCBF	(R5)
71	ADD	$CACHELINESZ, R5
72	BDNZ	_dcf0
73_dcf1:
74	SYNC
75
76	/* BAT0, 3 unused, copy of BAT2 */
77	MOVW	SPR(IBATL(2)), R3
78	MOVW	R3, SPR(IBATL(0))
79	MOVW	SPR(IBATU(2)), R3
80	MOVW	R3, SPR(IBATU(0))
81	MOVW	SPR(DBATL(2)), R3
82	MOVW	R3, SPR(DBATL(0))
83	MOVW	SPR(DBATU(2)), R3
84	MOVW	R3, SPR(DBATU(0))
85
86	MOVW	SPR(IBATL(2)), R3
87	MOVW	R3, SPR(IBATL(3))
88	MOVW	SPR(IBATU(2)), R3
89	MOVW	R3, SPR(IBATU(3))
90	MOVW	SPR(DBATL(2)), R3
91	MOVW	R3, SPR(DBATL(3))
92	MOVW	SPR(DBATU(2)), R3
93	MOVW	R3, SPR(DBATU(3))
94#endif /* ucuconf */
95
96	/* running with MMU on!! */
97
98	/* set R2 to correct value */
99	MOVW	$setSB(SB), R2
100
101	/* set up Mach */
102	MOVW	$MACHADDR, R(MACH)
103	ADD	$(MACHSIZE-8), R(MACH), R1	/* set stack */
104
105	MOVW	R0, R(USER)		/* up-> set to zero */
106	MOVW	R0, 0(R(MACH))		/* machno set to zero */
107
108	BL	main(SB)
109
110	RETURN				/* not reached */
111
112/*
113 * on return from this function we will be running in virtual mode.
114 * We set up the Block Address Translation (BAT) registers thus:
115 * 1) first 3 BATs are 256M blocks, starting from KZERO->0
116 * 2) remaining BAT maps last 256M directly
117 */
118TEXT mmuinit0(SB), $0
119	/* reset all the tlbs */
120	MOVW	$64, R3
121	MOVW	R3, CTR
122	MOVW	$0, R4
123
124tlbloop:
125	TLBIE	R4
126	SYNC
127	ADD	$BIT(19), R4
128	BDNZ	tlbloop
129	TLBSYNC
130
131#ifndef ucuconf
132	/* BATs 0 and 1 cover memory from 0x00000000 to 0x20000000 */
133
134	/* KZERO -> 0, IBAT and DBAT, 256 MB */
135	MOVW	$(KZERO|(0x7ff<<2)|2), R3
136	MOVW	$(PTEVALID|PTEWRITE), R4	/* PTEVALID => Cache coherency on */
137	MOVW	R3, SPR(IBATU(0))
138	MOVW	R4, SPR(IBATL(0))
139	MOVW	R3, SPR(DBATU(0))
140	MOVW	R4, SPR(DBATL(0))
141
142	/* KZERO+256M -> 256M, IBAT and DBAT, 256 MB */
143	ADD	$(1<<28), R3
144	ADD	$(1<<28), R4
145	MOVW	R3, SPR(IBATU(1))
146	MOVW	R4, SPR(IBATL(1))
147	MOVW	R3, SPR(DBATU(1))
148	MOVW	R4, SPR(DBATL(1))
149
150	/* FPGABASE -> FPGABASE, DBAT, 16 MB */
151	MOVW	$(FPGABASE|(0x7f<<2)|2), R3
152	MOVW	$(FPGABASE|PTEWRITE|PTEUNCACHED), R4	/* FPGA memory, don't cache */
153	MOVW	R3, SPR(DBATU(2))
154	MOVW	R4, SPR(DBATL(2))
155
156	/* IBAT 2 unused */
157	MOVW	R0, SPR(IBATU(2))
158	MOVW	R0, SPR(IBATL(2))
159
160	/* direct map last block, uncached, (not guarded, doesn't work for BAT), DBAT only */
161	MOVW	$(INTMEM|(0x7ff<<2)|2), R3
162	MOVW	$(INTMEM|PTEWRITE|PTEUNCACHED), R4	/* Don't set PTEVALID here */
163	MOVW	R3, SPR(DBATU(3))
164	MOVW	R4, SPR(DBATL(3))
165
166	/* IBAT 3 unused */
167	MOVW	R0, SPR(IBATU(3))
168	MOVW	R0, SPR(IBATL(3))
169#else /* ucuconf */
170	/* BAT 2 covers memory from 0x00000000 to 0x10000000 */
171
172	/* KZERO -> 0, IBAT2 and DBAT2, 256 MB */
173	MOVW	$(KZERO|(0x7ff<<2)|2), R3
174	MOVW	$(PTEVALID|PTEWRITE), R4	/* PTEVALID => Cache coherency on */
175	MOVW	R3, SPR(DBATU(2))
176	MOVW	R4, SPR(DBATL(2))
177	MOVW	R3, SPR(IBATU(2))
178	MOVW	R4, SPR(IBATL(2))
179#endif /* ucuconf */
180
181	/* enable MMU */
182	MOVW	LR, R3
183	OR	$KZERO, R3
184	MOVW	R3, SPR(SRR0)		/* Stored PC for RFI instruction */
185	MOVW	MSR, R4
186	OR	$(MSR_IR|MSR_DR|MSR_RI|MSR_FP), R4
187	MOVW	R4, SPR(SRR1)
188	RFI				/* resume in kernel mode in caller */
189
190	RETURN
191
192TEXT kfpinit(SB), $0
193	MOVFL	$0, FPSCR(7)
194	MOVFL	$0xD, FPSCR(6)		/* VE, OE, ZE */
195	MOVFL	$0, FPSCR(5)
196	MOVFL	$0, FPSCR(3)
197	MOVFL	$0, FPSCR(2)
198	MOVFL	$0, FPSCR(1)
199	MOVFL	$0, FPSCR(0)
200
201	FMOVD	$4503601774854144.0, F27
202	FMOVD	$0.5, F29
203	FSUB	F29, F29, F28
204	FADD	F29, F29, F30
205	FADD	F30, F30, F31
206	FMOVD	F28, F0
207	FMOVD	F28, F1
208	FMOVD	F28, F2
209	FMOVD	F28, F3
210	FMOVD	F28, F4
211	FMOVD	F28, F5
212	FMOVD	F28, F6
213	FMOVD	F28, F7
214	FMOVD	F28, F8
215	FMOVD	F28, F9
216	FMOVD	F28, F10
217	FMOVD	F28, F11
218	FMOVD	F28, F12
219	FMOVD	F28, F13
220	FMOVD	F28, F14
221	FMOVD	F28, F15
222	FMOVD	F28, F16
223	FMOVD	F28, F17
224	FMOVD	F28, F18
225	FMOVD	F28, F19
226	FMOVD	F28, F20
227	FMOVD	F28, F21
228	FMOVD	F28, F22
229	FMOVD	F28, F23
230	FMOVD	F28, F24
231	FMOVD	F28, F25
232	FMOVD	F28, F26
233	RETURN
234
235TEXT splhi(SB), $0
236	MOVW	LR, R31
237	MOVW	R31, 4(R(MACH))		/* save PC in m->splpc */
238	MOVW	MSR, R3
239	RLWNM	$0, R3, $~MSR_EE, R4
240	SYNC
241	MOVW	R4, MSR
242	MSRSYNC
243	RETURN
244
245TEXT splx(SB), $0
246	/* fall though */
247
248TEXT splxpc(SB), $0
249	MOVW	LR, R31
250	MOVW	R31, 4(R(MACH))		/* save PC in m->splpc */
251	MOVW	MSR, R4
252	RLWMI	$0, R3, $MSR_EE, R4
253	SYNC
254	MOVW	R4, MSR
255	MSRSYNC
256	RETURN
257
258TEXT spllo(SB), $0
259	MOVW	MSR, R3
260	OR	$MSR_EE, R3, R4
261	SYNC
262	MOVW	R4, MSR
263	MSRSYNC
264	RETURN
265
266TEXT spldone(SB), $0
267	RETURN
268
269TEXT islo(SB), $0
270	MOVW	MSR, R3
271	RLWNM	$0, R3, $MSR_EE, R3
272	RETURN
273
274TEXT setlabel(SB), $-4
275	MOVW	LR, R31
276	MOVW	R1, 0(R3)
277	MOVW	R31, 4(R3)
278	MOVW	$0, R3
279	RETURN
280
281TEXT gotolabel(SB), $-4
282	MOVW	4(R3), R31
283	MOVW	R31, LR
284	MOVW	0(R3), R1
285	MOVW	$1, R3
286	RETURN
287
288TEXT touser(SB), $-4
289	MOVW	$(UTZERO+32), R5	/* header appears in text */
290	MOVW	$(MSR_EE|MSR_PR|MSR_IR|MSR_DR|MSR_RI), R4
291	MOVW	R4, SPR(SRR1)
292	MOVW	R3, R1
293	MOVW	R5, SPR(SRR0)
294	RFI
295
296TEXT dczap(SB), $-4			/* dczap(virtaddr, count) */
297	MOVW	n+4(FP), R4
298	RLWNM	$0, R3, $~(CACHELINESZ-1), R5
299	CMP	R4, $0
300	BLE	dcz1
301	SUB	R5, R3
302	ADD	R3, R4
303	ADD	$(CACHELINESZ-1), R4
304	SRAW	$CACHELINELOG, R4
305	MOVW	R4, CTR
306dcz0:
307	DCBI	(R5)
308	ADD	$CACHELINESZ, R5
309	BDNZ	dcz0
310dcz1:
311	SYNC
312	RETURN
313
314TEXT dcflush(SB), $-4			/* dcflush(virtaddr, count) */
315	MOVW	n+4(FP), R4
316	RLWNM	$0, R3, $~(CACHELINESZ-1), R5
317	CMP	R4, $0
318	BLE	dcf1
319	SUB	R5, R3
320	ADD	R3, R4
321	ADD	$(CACHELINESZ-1), R4
322	SRAW	$CACHELINELOG, R4
323	MOVW	R4, CTR
324dcf0:	DCBST	(R5)
325	ADD	$CACHELINESZ, R5
326	BDNZ	dcf0
327dcf1:
328	SYNC
329	RETURN
330
331TEXT icflush(SB), $-4			/* icflush(virtaddr, count) */
332	MOVW	n+4(FP), R4
333	RLWNM	$0, R3, $~(CACHELINESZ-1), R5
334	CMP	R4, $0
335	BLE	icf1
336	SUB	R5, R3
337	ADD	R3, R4
338	ADD	$(CACHELINESZ-1), R4
339	SRAW	$CACHELINELOG, R4
340	MOVW	R4, CTR
341icf0:	ICBI	(R5)			/* invalidate the instruction cache */
342	ADD	$CACHELINESZ, R5
343	BDNZ	icf0
344	ISYNC
345icf1:
346	RETURN
347
348TEXT tas(SB), $0
349	MOVW	R3, R4
350	MOVW	$0xdead, R5
351tas1:
352	DCBF	(R4)			/* fix for 603x bug */
353	SYNC
354	LWAR	(R4), R3
355	CMP	R3, $0
356	BNE	tas0
357	STWCCC	R5, (R4)
358	BNE	tas1
359	EIEIO
360tas0:
361	SYNC
362	RETURN
363
364TEXT _xinc(SB), $0			/* void _xinc(long *); */
365	MOVW	R3, R4
366xincloop:
367	DCBF	(R4)			/* fix for 603x bug */
368	LWAR	(R4), R3
369	ADD	$1, R3
370	STWCCC	R3, (R4)
371	BNE	xincloop
372	RETURN
373
374TEXT _xdec(SB), $0			/* long _xdec(long *); */
375	MOVW	R3, R4
376xdecloop:
377	DCBF	(R4)			/* fix for 603x bug */
378	LWAR	(R4), R3
379	ADD	$-1, R3
380	STWCCC	R3, (R4)
381	BNE	xdecloop
382	RETURN
383
384TEXT cmpswap(SB),$0	/* int cmpswap(long*, long, long) */
385	MOVW	R3, R4	/* addr */
386	MOVW	old+4(FP), R5
387	MOVW	new+8(FP), R6
388	DCBF	(R4)		/* fix for 603x bug? */
389	LWAR	(R4), R3
390	CMP	R3, R5
391	BNE fail
392	STWCCC	R6, (R4)
393	BNE fail
394	MOVW $1, R3
395	RETURN
396fail:
397	MOVW $0, R3
398	RETURN
399
400TEXT tlbflushall(SB), $0
401	MOVW	$TLBENTRIES, R3
402	MOVW	R3, CTR
403	MOVW	$0, R4
404	ISYNC
405tlbflushall0:
406	TLBIE	R4
407	SYNC
408	ADD	$BIT(19), R4
409	BDNZ	tlbflushall0
410	TLBSYNC
411	RETURN
412
413TEXT tlbflush(SB), $0
414	ISYNC
415	TLBIE	R3
416	SYNC
417	TLBSYNC
418	RETURN
419
420TEXT gotopc(SB), $0
421	MOVW	R3, CTR
422	MOVW	LR, R31			/* for trace back */
423	BR	(CTR)
424
425/* On an imiss, we get here.  If we can resolve it, we do.
426 * Otherwise take the real trap.  The code at the vector is
427 *	MOVW	R0, SPR(SAVER0)	No point to this, of course
428 *	MOVW	LR, R0
429 *	MOVW	R0, SPR(SAVELR)
430 *	BL	imiss(SB)		or dmiss, as the case may be
431 *	BL	tlbvec(SB)
432 */
433TEXT imiss(SB), $-4
434	/* Statistics */
435	MOVW	$MACHPADDR, R1
436	MOVW	0xc(R1), R3		/* count m->tlbfault */
437	ADD	$1, R3
438	MOVW	R3, 0xc(R1)
439	MOVW	0x10(R1), R3		/* count m->imiss */
440	ADD	$1, R3
441	MOVW	R3, 0x10(R1)
442
443	/* Real work */
444	MOVW	SPR(HASH1), R1		/* (phys) pointer into the hash table */
445	ADD	$BY2PTEG, R1, R2	/* end pointer */
446	MOVW	SPR(iCMP), R3		/* pattern to look for */
447imiss1:
448	MOVW	(R1), R0
449	CMP	R3, R0
450	BEQ	imiss2			/* found the entry */
451	ADD	$8, R1
452	CMP	R1, R2			/* test end of loop */
453	BNE	imiss1			/* Loop */
454	/* Failed to find an entry; take the full trap */
455	MOVW	SPR(SRR1), R1
456	MTCRF(1, 0x80)			/* restore CR0 bits (they're auto saved in SRR1) */
457	RETURN
458imiss2:
459	/* Found the entry */
460	MOVW	4(R1), R2		/* Phys addr */
461	MOVW	R2, SPR(RPA)
462	MOVW	SPR(IMISS), R3
463	TLBLI(3)
464
465	/* Restore Registers */
466	MOVW	SPR(SRR1), R1		/* Restore the CR0 field of the CR register from SRR1 */
467	MTCRF(1, 0x80)
468	MOVW	SPR(SAVELR), R0
469	MOVW	R0, LR
470	RFI
471
472/* On a data load or store miss, we get here.  If we can resolve it, we do.
473 * Otherwise take the real trap
474 */
475TEXT dmiss(SB), $-4
476	/* Statistics */
477	MOVW	$MACHPADDR, R1
478	MOVW	0xc(R1), R3		/* count m->tlbfault */
479	ADD	$1, R3
480	MOVW	R3, 0xc(R1)
481	MOVW	0x14(R1), R3		/* count m->dmiss */
482	ADD	$1, R3
483	MOVW	R3, 0x14(R1)
484	/* Real work */
485	MOVW	SPR(HASH1), R1		/* (phys) pointer into the hash table */
486	ADD	$BY2PTEG, R1, R2	/* end pointer */
487	MOVW	SPR(DCMP), R3		/* pattern to look for */
488dmiss1:
489	MOVW	(R1), R0
490	CMP	R3, R0
491	BEQ	dmiss2			/* found the entry */
492	ADD	$8, R1
493	CMP	R1, R2			/* test end of loop */
494	BNE	dmiss1			/* Loop */
495	/* Failed to find an entry; take the full trap */
496	MOVW	SPR(SRR1), R1
497	MTCRF(1, 0x80)			/* restore CR0 bits (they're auto saved in SRR1) */
498	RETURN
499dmiss2:
500	/* Found the entry */
501	MOVW	4(R1), R2		/* Phys addr */
502	MOVW	R2, SPR(RPA)
503	MOVW	SPR(DMISS), R3
504	TLBLD(3)
505	/* Restore Registers */
506	MOVW	SPR(SRR1), R1		/* Restore the CR0 field of the CR register from SRR1 */
507	MTCRF(1, 0x80)
508	MOVW	SPR(SAVELR), R0
509	MOVW	R0, LR
510	RFI
511
512/*
513 * When a trap sets the TGPR bit (TLB miss traps do this),
514 * registers get remapped: R0-R31 are temporarily inaccessible,
515 * and Temporary Registers TR0-TR3 are mapped onto R0-R3.
516 * While this bit is set, R4-R31 cannot be used.
517 * The code at the vector has executed this code before
518 * coming to tlbvec:
519 *	MOVW	R0, SPR(SAVER0)	No point to this, of course
520 *	MOVW	LR, R0
521 *	MOVW	R0, SPR(SAVELR)
522 *	BL	tlbvec(SB)
523 * SAVER0 can be reused.  We're not interested in the value of TR0
524 */
525TEXT tlbvec(SB), $-4
526 	MOVW	MSR, R1
527	RLWNM	$0, R1, $~MSR_TGPR, R1	/* Clear the dreaded TGPR bit in the MSR */
528	SYNC
529	MOVW	R1, MSR
530	MSRSYNC
531	/* Now the GPRs are what they're supposed to be, save R0 again */
532	MOVW	R0, SPR(SAVER0)
533	/* Fall through to trapvec */
534
535/*
536 * traps force memory mapping off.
537 * the following code has been executed at the exception
538 * vector location
539 *	MOVW	R0, SPR(SAVER0)
540 *	MOVW	LR, R0
541 *	MOVW	R0, SPR(SAVELR)
542 *	bl	trapvec(SB)
543 *
544 */
545TEXT trapvec(SB), $-4
546	MOVW	LR, R0
547	MOVW	R1, SPR(SAVER1)
548	MOVW	R0, SPR(SAVEXX)		/* vector */
549
550	/* did we come from user space */
551	MOVW	SPR(SRR1), R0
552	MOVW	CR, R1
553	MOVW	R0, CR
554	BC	4, 17, ktrap
555
556	/* switch to kernel stack */
557	MOVW	R1, CR
558	MOVW	$MACHPADDR, R1		/* PADDR(m->) */
559	MOVW	8(R1), R1		/* m->proc */
560	RLWNM	$0, R1, $~KZERO, R1	/* PADDR(m->proc) */
561	MOVW	8(R1), R1		/* m->proc->kstack */
562	RLWNM	$0, R1, $~KZERO, R1	/* PADDR(m->proc->kstack) */
563	ADD	$(KSTACK-UREGSIZE), R1	/* make room on stack */
564
565	BL	saveureg(SB)
566	BL	trap(SB)
567	BR	restoreureg
568
569ktrap:
570	MOVW	R1, CR
571	MOVW	SPR(SAVER1), R1
572	RLWNM	$0, R1, $~KZERO, R1	/* set stack pointer */
573	SUB	$UREGSPACE, R1
574
575	BL	saveureg(SB)		/* addressed relative to PC */
576	BL	trap(SB)
577	BR	restoreureg
578
579/*
580 * enter with stack set and mapped.
581 * on return, SB (R2) has been set, and R3 has the Ureg*,
582 * the MMU has been re-enabled, kernel text and PC are in KSEG,
583 * R(MACH) has been set, and R0 contains 0.
584 *
585 */
586TEXT saveureg(SB), $-4
587/*
588 * save state
589 */
590	MOVMW	R2, 48(R1)		/* save r2 .. r31 in 48(R1) .. 164(R1) */
591	MOVW	$MACHPADDR, R(MACH)	/* PADDR(m->) */
592	MOVW	8(R(MACH)), R(USER)	/* up-> */
593	MOVW	$MACHADDR, R(MACH)	/* m-> */
594	MOVW	SPR(SAVER1), R4
595	MOVW	R4, 44(R1)
596	MOVW	SPR(SAVER0), R5
597	MOVW	R5, 40(R1)
598	MOVW	CTR, R6
599	MOVW	R6, 36(R1)
600	MOVW	XER, R4
601	MOVW	R4, 32(R1)
602	MOVW	CR, R5
603	MOVW	R5, 28(R1)
604	MOVW	SPR(SAVELR), R6		/* LR */
605	MOVW	R6, 24(R1)
606	/* pad at 20(R1) */
607	MOVW	SPR(SRR0), R0
608	MOVW	R0, 16(R1)		/* old PC */
609	MOVW	SPR(SRR1), R0
610	MOVW	R0, 12(R1)		/* old status */
611	MOVW	SPR(SAVEXX), R0
612	MOVW	R0, 8(R1)		/* cause/vector */
613	MOVW	SPR(DCMP), R0
614	MOVW	R0, (160+8)(R1)
615	MOVW	SPR(iCMP), R0
616	MOVW	R0, (164+8)(R1)
617	MOVW	SPR(DMISS), R0
618	MOVW	R0, (168+8)(R1)
619	MOVW	SPR(IMISS), R0
620	MOVW	R0, (172+8)(R1)
621	MOVW	SPR(HASH1), R0
622	MOVW	R0, (176+8)(R1)
623	MOVW	SPR(HASH2), R0
624	MOVW	R0, (180+8)(R1)
625	MOVW	SPR(DAR), R0
626	MOVW	R0, (184+8)(R1)
627	MOVW	SPR(DSISR), R0
628	MOVW	R0, (188+8)(R1)
629	ADD	$8, R1, R3		/* Ureg* */
630	OR	$KZERO, R3		/* fix ureg */
631	STWCCC	R3, (R1)		/* break any pending reservations */
632	MOVW	$0, R0			/* compiler/linker expect R0 to be zero */
633	MOVW	$setSB(SB), R2		/* SB register */
634
635	MOVW	MSR, R5
636	OR	$(MSR_IR|MSR_DR|MSR_FP|MSR_RI), R5	/* enable MMU */
637	MOVW	R5, SPR(SRR1)
638	MOVW	LR, R31
639	OR	$KZERO, R31		/* return PC in KSEG0 */
640	MOVW	R31, SPR(SRR0)
641	OR	$KZERO, R1		/* fix stack pointer */
642	RFI				/* returns to trap handler */
643
644/*
645 * restore state from Ureg and return from trap/interrupt
646 */
647TEXT forkret(SB), $0
648	BR	restoreureg
649
650restoreureg:
651	MOVMW	48(R1), R2		/* restore r2 through r31 */
652	/* defer R1 */
653	MOVW	40(R1), R0
654	MOVW	R0, SPR(SAVER0)		/* resave saved R0 */
655	MOVW	36(R1), R0
656	MOVW	R0, CTR
657	MOVW	32(R1), R0
658	MOVW	R0, XER
659	MOVW	28(R1), R0
660	MOVW	R0, CR			/* Condition register*/
661	MOVW	24(R1), R0
662	MOVW	R0, LR
663	/* pad, skip */
664	MOVW	16(R1), R0
665	MOVW	R0, SPR(SRR0)		/* old PC */
666	MOVW	12(R1), R0
667	MOVW	R0, SPR(SRR1)		/* old MSR */
668	/* cause, skip */
669	MOVW	44(R1), R1		/* old SP */
670	MOVW	SPR(SAVER0), R0
671	RFI
672
673TEXT getpvr(SB), $0
674	MOVW	SPR(PVR), R3
675	RETURN
676
677TEXT getdec(SB), $0
678	MOVW	SPR(DEC), R3
679	RETURN
680
681TEXT putdec(SB), $0
682	MOVW	R3, SPR(DEC)
683	RETURN
684
685TEXT getdar(SB), $0
686	MOVW	SPR(DAR), R3
687	RETURN
688
689TEXT getdsisr(SB), $0
690	MOVW	SPR(DSISR), R3
691	RETURN
692
693TEXT getmsr(SB), $0
694	MOVW	MSR, R3
695	RETURN
696
697TEXT putmsr(SB), $0
698	MOVW	R3, MSR
699	MSRSYNC
700	RETURN
701
702TEXT putsdr1(SB), $0
703	SYNC
704	MOVW	R3, SPR(SDR1)
705	ISYNC
706	RETURN
707
708TEXT putsr(SB), $0
709	MOVW	4(FP), R4
710	SYNC
711	MOVW	R4, SEG(R3)
712	MSRSYNC
713	RETURN
714
715TEXT getsr(SB), $0
716	MOVW	SEG(R3), R3
717	RETURN
718
719TEXT gethid0(SB), $0
720	MOVW	SPR(HID0), R3
721	RETURN
722
723TEXT puthid0(SB), $0
724	SYNC
725	ISYNC
726	MOVW	R3, SPR(HID0)
727	SYNC
728	RETURN
729
730TEXT gethid1(SB), $0
731	MOVW	SPR(HID1), R3
732	RETURN
733
734TEXT gethid2(SB), $0
735	MOVW	SPR(HID2), R3
736	RETURN
737
738TEXT puthid2(SB), $0
739	MOVW	R3, SPR(HID2)
740	RETURN
741
742TEXT eieio(SB), $0
743	EIEIO
744	RETURN
745
746TEXT sync(SB), $0
747	SYNC
748	RETURN
749
750/* Power PC 603e specials */
751TEXT getimiss(SB), $0
752	MOVW	SPR(IMISS), R3
753	RETURN
754
755TEXT geticmp(SB), $0
756	MOVW	SPR(iCMP), R3
757	RETURN
758
759TEXT puticmp(SB), $0
760	MOVW	R3, SPR(iCMP)
761	RETURN
762
763TEXT getdmiss(SB), $0
764	MOVW	SPR(DMISS), R3
765	RETURN
766
767TEXT getdcmp(SB), $0
768	MOVW	SPR(DCMP), R3
769	RETURN
770
771TEXT putdcmp(SB), $0
772	MOVW	R3, SPR(DCMP)
773	RETURN
774
775TEXT getsdr1(SB), $0
776	MOVW	SPR(SDR1), R3
777	RETURN
778
779TEXT gethash1(SB), $0
780	MOVW	SPR(HASH1), R3
781	RETURN
782
783TEXT puthash1(SB), $0
784	MOVW	R3, SPR(HASH1)
785	RETURN
786
787TEXT gethash2(SB), $0
788	MOVW	SPR(HASH2), R3
789	RETURN
790
791TEXT puthash2(SB), $0
792	MOVW	R3, SPR(HASH2)
793	RETURN
794
795TEXT getrpa(SB), $0
796	MOVW	SPR(RPA), R3
797	RETURN
798
799TEXT putrpa(SB), $0
800	MOVW	R3, SPR(RPA)
801	RETURN
802
803TEXT tlbli(SB), $0
804	TLBLI(3)
805	ISYNC
806	RETURN
807
808TEXT tlbld(SB), $0
809	SYNC
810	TLBLD(3)
811	ISYNC
812	RETURN
813
814TEXT getsrr1(SB), $0
815	MOVW	SPR(SRR1), R3
816	RETURN
817
818TEXT putsrr1(SB), $0
819	MOVW	R3, SPR(SRR1)
820	RETURN
821
822TEXT fpsave(SB), $0
823	FMOVD	F0, (0*8)(R3)
824	FMOVD	F1, (1*8)(R3)
825	FMOVD	F2, (2*8)(R3)
826	FMOVD	F3, (3*8)(R3)
827	FMOVD	F4, (4*8)(R3)
828	FMOVD	F5, (5*8)(R3)
829	FMOVD	F6, (6*8)(R3)
830	FMOVD	F7, (7*8)(R3)
831	FMOVD	F8, (8*8)(R3)
832	FMOVD	F9, (9*8)(R3)
833	FMOVD	F10, (10*8)(R3)
834	FMOVD	F11, (11*8)(R3)
835	FMOVD	F12, (12*8)(R3)
836	FMOVD	F13, (13*8)(R3)
837	FMOVD	F14, (14*8)(R3)
838	FMOVD	F15, (15*8)(R3)
839	FMOVD	F16, (16*8)(R3)
840	FMOVD	F17, (17*8)(R3)
841	FMOVD	F18, (18*8)(R3)
842	FMOVD	F19, (19*8)(R3)
843	FMOVD	F20, (20*8)(R3)
844	FMOVD	F21, (21*8)(R3)
845	FMOVD	F22, (22*8)(R3)
846	FMOVD	F23, (23*8)(R3)
847	FMOVD	F24, (24*8)(R3)
848	FMOVD	F25, (25*8)(R3)
849	FMOVD	F26, (26*8)(R3)
850	FMOVD	F27, (27*8)(R3)
851	FMOVD	F28, (28*8)(R3)
852	FMOVD	F29, (29*8)(R3)
853	FMOVD	F30, (30*8)(R3)
854	FMOVD	F31, (31*8)(R3)
855	MOVFL	FPSCR, F0
856	FMOVD	F0, (32*8)(R3)
857	RETURN
858
859TEXT fprestore(SB), $0
860	FMOVD	(32*8)(R3), F0
861	MOVFL	F0, FPSCR
862	FMOVD	(0*8)(R3), F0
863	FMOVD	(1*8)(R3), F1
864	FMOVD	(2*8)(R3), F2
865	FMOVD	(3*8)(R3), F3
866	FMOVD	(4*8)(R3), F4
867	FMOVD	(5*8)(R3), F5
868	FMOVD	(6*8)(R3), F6
869	FMOVD	(7*8)(R3), F7
870	FMOVD	(8*8)(R3), F8
871	FMOVD	(9*8)(R3), F9
872	FMOVD	(10*8)(R3), F10
873	FMOVD	(11*8)(R3), F11
874	FMOVD	(12*8)(R3), F12
875	FMOVD	(13*8)(R3), F13
876	FMOVD	(14*8)(R3), F14
877	FMOVD	(15*8)(R3), F15
878	FMOVD	(16*8)(R3), F16
879	FMOVD	(17*8)(R3), F17
880	FMOVD	(18*8)(R3), F18
881	FMOVD	(19*8)(R3), F19
882	FMOVD	(20*8)(R3), F20
883	FMOVD	(21*8)(R3), F21
884	FMOVD	(22*8)(R3), F22
885	FMOVD	(23*8)(R3), F23
886	FMOVD	(24*8)(R3), F24
887	FMOVD	(25*8)(R3), F25
888	FMOVD	(26*8)(R3), F26
889	FMOVD	(27*8)(R3), F27
890	FMOVD	(28*8)(R3), F28
891	FMOVD	(29*8)(R3), F29
892	FMOVD	(30*8)(R3), F30
893	FMOVD	(31*8)(R3), F31
894	RETURN
895
896TEXT dcacheenb(SB), $0
897	SYNC
898	MOVW	SPR(HID0), R4		/* Get HID0 and clear unwanted bits */
899	RLWNM	$0, R4, $~(HID_DLOCK), R4
900	MOVW	$(HID_DCFI|HID_DCE), R5
901	OR	R4, R5
902	MOVW	$HID_DCE, R3
903	OR	R4, R3
904	SYNC
905//	MOVW	R5, SPR(HID0)		/* Cache enable and flash invalidate */
906	MOVW	R3, SPR(HID0)		/* Cache enable */
907	SYNC
908	RETURN
909
910TEXT icacheenb(SB), $0
911	SYNC
912	MOVW	SPR(HID0), R4		/* Get HID0 and clear unwanted bits */
913	RLWNM	$0, R4, $~(HID_ILOCK), R4
914	MOVW	$(HID_ICFI|HID_ICE), R5
915	OR	R4, R5
916	MOVW	$HID_ICE, R3
917	OR	R4, R3
918	SYNC
919	MOVW	R5, SPR(HID0)		/* Cache enable and flash invalidate */
920	MOVW	R3, SPR(HID0)		/* Cache enable */
921	SYNC
922	RETURN
923
924#ifdef ucuconf
925TEXT getpll(SB), $0
926	MOVW	SPR(1009), R3
927	ISYNC
928	RETURN
929
930TEXT getl2pm(SB), $0
931	MOVW	SPR(1016), R3
932	RETURN
933
934TEXT getl2cr(SB), $0
935	MOVW	SPR(1017), R3
936	RETURN
937
938TEXT putl2cr(SB), $0
939	MOVW	R3, SPR(1017)
940	RETURN
941
942TEXT dcachedis(SB), $0
943	SYNC
944/*	MOVW	SPR(HID0), R4
945	RLWNM	$0, R4, $~(HID_DCE), R4
946	MOVW	R4, SPR(HID0)		/* L1 Cache disable */
947
948	MOVW	SPR(1017), R4
949	RLWNM	$0, R4, $~(0x80000000), R4
950	MOVW	R4, SPR(1017)		/* L2 Cache disable */
951
952	SYNC
953	RETURN
954
955TEXT l2disable(SB), $0
956	SYNC
957	MOVW	SPR(1017), R4
958	RLWNM	$0, R4, $~(0x80000000), R4
959	MOVW	R4, SPR(1017)		/* L2 Cache disable */
960	SYNC
961	RETURN
962
963TEXT getbats(SB), $0
964	MOVW	SPR(DBATU(0)), R4
965	MOVW	R4, 0(R3)
966	MOVW	SPR(DBATL(0)), R4
967	MOVW	R4, 4(R3)
968	MOVW	SPR(IBATU(0)), R4
969	MOVW	R4, 8(R3)
970	MOVW	SPR(IBATL(0)), R4
971	MOVW	R4, 12(R3)
972	MOVW	SPR(DBATU(1)), R4
973	MOVW	R4, 16(R3)
974	MOVW	SPR(DBATL(1)), R4
975	MOVW	R4, 20(R3)
976	MOVW	SPR(IBATU(1)), R4
977	MOVW	R4, 24(R3)
978	MOVW	SPR(IBATL(1)), R4
979	MOVW	R4, 28(R3)
980	MOVW	SPR(DBATU(2)), R4
981	MOVW	R4, 32(R3)
982	MOVW	SPR(DBATL(2)), R4
983	MOVW	R4, 36(R3)
984	MOVW	SPR(IBATU(2)), R4
985	MOVW	R4, 40(R3)
986	MOVW	SPR(IBATL(2)), R4
987	MOVW	R4, 44(R3)
988	MOVW	SPR(DBATU(3)), R4
989	MOVW	R4, 48(R3)
990	MOVW	SPR(DBATL(3)), R4
991	MOVW	R4, 52(R3)
992	MOVW	SPR(IBATU(3)), R4
993	MOVW	R4, 56(R3)
994	MOVW	SPR(IBATL(3)), R4
995	MOVW	R4, 60(R3)
996	RETURN
997
998TEXT setdbat0(SB), $0
999	MOVW	0(R3), R4
1000	MOVW	R4, SPR(DBATU(0))
1001	MOVW	4(R3), R4
1002	MOVW	R4, SPR(DBATL(0))
1003	RETURN
1004#endif /* ucuconf */
1005
1006TEXT mmudisable(SB), $0
1007	/* disable MMU */
1008	MOVW	LR, R4
1009	MOVW	$KZERO, R5
1010	ANDN	R5, R4
1011	MOVW	R4, SPR(SRR0)		/* Stored PC for RFI instruction */
1012
1013	MOVW	MSR, R4
1014	MOVW	$(MSR_IR|MSR_DR|MSR_RI|MSR_FP), R5
1015	ANDN	R5, R4
1016	MOVW	R4, SPR(SRR1)
1017
1018	MOVW	SPR(HID0), R4		/* Get HID0 and clear unwanted bits */
1019	MOVW	$(HID_ICE|HID_DCE), R5
1020	ANDN	R5, R4
1021	MOVW	R4, SPR(HID0)		/* Cache disable */
1022	RFI				/* resume caller with MMU off */
1023	RETURN
1024
1025TEXT kreboot(SB), $0
1026	BL	mmudisable(SB)
1027	MOVW	R3, LR
1028	RETURN
1029
1030TEXT mul64fract(SB), $0
1031	MOVW	a0+8(FP), R9
1032	MOVW	a1+4(FP), R10
1033	MOVW	b0+16(FP), R4
1034	MOVW	b1+12(FP), R5
1035
1036	MULLW	R10, R5, R13		/* c2 = lo(a1*b1) */
1037
1038	MULLW	R10, R4, R12		/* c1 = lo(a1*b0) */
1039	MULHWU	R10, R4, R7		/* hi(a1*b0) */
1040	ADD	R7, R13			/* c2 += hi(a1*b0) */
1041
1042	MULLW	R9, R5, R6		/* lo(a0*b1) */
1043	MULHWU	R9, R5, R7		/* hi(a0*b1) */
1044	ADDC	R6, R12			/* c1 += lo(a0*b1) */
1045	ADDE	R7, R13			/* c2 += hi(a0*b1) + carry */
1046
1047	MULHWU	R9, R4, R7		/* hi(a0*b0) */
1048	ADDC	R7, R12			/* c1 += hi(a0*b0) */
1049	ADDE	R0, R13			/* c2 += carry */
1050
1051	MOVW	R12, 4(R3)
1052	MOVW	R13, 0(R3)
1053	RETURN
1054