xref: /plan9/sys/src/cmd/ka/l.s (revision 3e12c5d1bb89fc02707907988834ef147769ddaf)
1/*
2 * Memory and machine-specific definitions.  Used in C and assembler.
3 */
4
5/*
6 * Sizes
7 */
8
9#define	BI2BY		8			/* bits per byte */
10#define BI2WD		32			/* bits per word */
11#define	BY2WD		4			/* bytes per word */
12#define	BY2PG		4096			/* bytes per page */
13#define	WD2PG		(BY2PG/BY2WD)		/* words per page */
14#define	PGSHIFT		12			/* log(BY2PG) */
15#define PGROUND(s)	(((s)+(BY2PG-1))&~(BY2PG-1))
16
17#define	MAXMACH		1			/* max # cpus system can run */
18
19/*
20 * Time
21 */
22#define	HZ		20			/* clock frequency */
23#define	MS2HZ		(1000/HZ)		/* millisec per clock tick */
24#define	TK2SEC(t)	((t)/HZ)		/* ticks to seconds */
25#define	TK2MS(t)	((((ulong)(t))*1000)/HZ)	/* ticks to milliseconds */
26#define	MS2TK(t)	((((ulong)(t))*HZ)/1000)	/* milliseconds to ticks */
27
28/*
29 * PSR bits
30 */
31#define	PSREC		0x00002000
32#define	PSREF		0x00001000
33#define PSRSUPER	0x00000080
34#define PSRPSUPER	0x00000040
35#define	PSRET		0x00000020
36#define SPL(n)		(n<<8)
37
38/*
39 * Magic registers
40 */
41
42#define	MACH		6		/* R6 is m-> */
43#define	USER		5		/* R5 is u-> */
44
45/*
46 * Fundamental addresses
47 */
48
49#define	USERADDR	0xE0000000
50#define	UREGADDR	(USERADDR+BY2PG-((32+6)*BY2WD))
51#define	BOOTSTACK	(KTZERO-0*BY2PG)
52#define	TRAPS		(KTZERO-2*BY2PG)
53
54/*
55 * MMU
56 */
57
58#define	VAMASK		0x3FFFFFFF
59#define	NPMEG		(1<<12)
60#define	BY2SEGM		(1<<18)
61#define	PG2SEGM		(1<<6)
62#define	NTLBPID		(1+NCONTEXT)	/* TLBPID 0 is unallocated */
63#define	NCONTEXT	8
64#define	CONTEXT		0x30000000	/* in ASI 2 */
65
66/*
67 * MMU regions
68 */
69#define	INVALIDSEGM	0xFFFC0000	/* highest seg of VA reserved as invalid */
70#define	INVALIDPMEG	0x7F
71#define	SCREENSEGM	0xFFF80000
72#define	SCREENPMEG	0x7E
73#define	ROMSEGM		0xFFE80000
74#define	ROMEND		0xFFEA0000
75#define	PG2ROM		((ROMEND-ROMSEGM)/BY2PG)
76#define	IOSEGM0		ROMSEGM		/* see mmuinit() */
77#define	NIOSEGM		((SCREENSEGM-ROMSEGM)/BY2SEGM)
78#define	IOPMEG0		(SCREENPMEG-NIOSEGM)
79#define	IOSEGM		ROMEND
80#define	IOEND		SCREENSEGM
81#define	TOPPMEG		IOPMEG0
82
83/*
84 * MMU entries
85 */
86#define	PTEVALID	(1<<31)
87#define	PTERONLY	(0<<30)
88#define	PTEWRITE	(1<<30)
89#define	PTEKERNEL	(1<<29)
90#define	PTENOCACHE	(1<<28)
91#define	PTEMAINMEM	(0<<26)
92#define	PTEIO		(1<<26)
93#define	PTEACCESS	(1<<25)
94#define	PTEMODIFY	(1<<24)
95#define PTEUNCACHED	0
96#define PTEMAPMEM	(1024*1024)
97#define	PTEPERTAB	(PTEMAPMEM/BY2PG)
98#define SEGMAPSIZE	16
99
100#define	INVALIDPTE	0
101#define	PPN(pa)		((pa>>12)&0xFFFF)
102
103/*
104 * Weird addresses in various ASI's
105 */
106#define	CACHETAGS	0x80000000		/* ASI 2 */
107#define	CACHEDATA	0x90000000		/* ASI 2 */
108#define	SER		0x60000000		/* ASI 2 */
109#define	SEVAR		0x60000004		/* ASI 2 */
110#define	ASER		0x60000008		/* ASI 2 */
111#define	ASEVAR		0x6000000C		/* ASI 2 */
112#define	ENAB		0x40000000		/* ASI 2 */
113#define	ENABCACHE	0x10
114#define	ENABRESET	0x04
115
116/*
117 * Virtual addresses
118 */
119#define	VTAG(va)	((va>>22)&0x03F)
120#define	VPN(va)		((va>>13)&0x1FF)
121
122#define	PARAM		((char*)0x40500000)
123#define	TLBFLUSH_	0x01
124
125/*
126 * Address spaces
127 */
128
129#define	UZERO	0x00000000		/* base of user address space */
130#define	UTZERO	(UZERO+BY2PG)		/* first address in user text */
131#define	TSTKTOP	0x10000000		/* end of new stack in sysexec */
132#define TSTKSIZ 32
133#define	USTKTOP	(TSTKTOP-TSTKSIZ*BY2PG)	/* byte just beyond user stack */
134#define	KZERO	0xE0000000		/* base of kernel address space */
135#define	KTZERO	(KZERO+4*BY2PG)		/* first address in kernel text */
136#define	USTKSIZE	(4*1024*1024)	/* size of user stack */
137
138#define	MACHSIZE	4096
139
140#define isphys(x) (((ulong)(x)&0xF0000000) == KZERO)
141
142#define	SYSPSR	(SPL(0x0)|PSREF|PSRSUPER|0)
143#define	NOOP	OR R0, R0; OR R0, R0; OR R0, R0
144
145TEXT	start(SB), $-4
146
147	/* get virtual, fast */
148	/* we are executing in segment 0, mapped to pmeg 0. stack is there too */
149	/* get virtual by mapping segment(KZERO) to pmeg 0., and next to 1 */
150	MOVW	$KZERO, R7
151	MOVB	R0, (R7, 3)
152	MOVW	$(KZERO+BY2SEGM), R7
153	MOVW	$1, R8
154	MOVB	R8, (R7, 3)
155	/* now mapped correctly.  jmpl to where we want to be */
156	MOVW	$setSB(SB), R2
157	MOVW	$startvirt(SB), R7
158	JMPL	(R7)
159	MOVW	$_mul(SB), R0	/* touch _mul etc.; doesn't need to execute */
160	RETURN			/* can't get here */
161
162TEXT	startvirt(SB), $-4
163
164	MOVW	$BOOTSTACK, R1
165
166	MOVW	$(SPL(0xF)|PSREF|PSRSUPER), R7
167	MOVW	R7, PSR
168
169	MOVW	$(0x35<<22), R7		/* NVM OFM DZM AU */
170	MOVW	R7, fsr+0(SB)
171	MOVW	fsr+0(SB), FSR
172	FMOVD	$0.5, F26		/* 0.5 -> F26 */
173	FSUBD	F26, F26, F24		/* 0.0 -> F24 */
174	FADDD	F26, F26, F28		/* 1.0 -> F28 */
175	FADDD	F28, F28, F30		/* 2.0 -> F30 */
176
177	FMOVD	F24, F0
178	FMOVD	F24, F2
179	FMOVD	F24, F4
180	FMOVD	F24, F6
181	FMOVD	F24, F8
182	FMOVD	F24, F10
183	FMOVD	F24, F12
184	FMOVD	F24, F14
185	FMOVD	F24, F16
186	FMOVD	F24, F18
187	FMOVD	F24, F20
188	FMOVD	F24, F22
189
190	MOVW	$mach0(SB), R(MACH)
191/*	MOVW	$0x8, R7 /**/
192	MOVW	R0, WIM
193	JMPL	main(SB)
194	MOVW	(R0), R0
195	RETURN
196
197TEXT	swap1(SB), $0
198
199	TAS	(R7), R7		/* LDSTUB, thank you ken */
200	RETURN
201
202TEXT	swap1_should_work(SB), $0
203
204	MOVW	R7, R8
205	MOVW	$1, R7
206	SWAP	(R8), R7
207	RETURN
208
209TEXT	swap1x(SB), $0
210
211	MOVW	PSR, R9
212	MOVW	R9, R10
213	AND	$~PSRET, R10		/* BUG: book says this is buggy */
214	MOVW	R10, PSR
215	NOOP
216	MOVW	(R7), R7
217	CMP	R7, R0
218	BNE	was1
219	MOVW	$1, R10
220	MOVW	R10, (R8)
221was1:
222	MOVW	R9, PSR
223	RETURN
224
225TEXT	spllo(SB), $0
226
227	MOVW	PSR, R7
228	MOVW	R7, R10
229	OR	$PSRET, R10
230	MOVW	R10, PSR
231	NOOP
232	RETURN
233
234TEXT	splhi(SB), $0
235
236	MOVW	R15, 4(R(MACH))	/* save PC in m->splpc */
237	MOVW	PSR, R7
238	MOVW	R7, R10
239	AND	$~PSRET, R10	/* BUG: book says this is buggy */
240	MOVW	R10, PSR
241	NOOP
242	RETURN
243
244TEXT	splx(SB), $0
245
246	MOVW	R15, 4(R(MACH))	/* save PC in m->splpc */
247	MOVW	R7, PSR		/* BUG: book says this is buggy */
248	NOOP
249	RETURN
250
251TEXT	spldone(SB), $0
252
253	RETURN
254
255TEXT	touser(SB), $0
256	MOVW	$(SYSPSR&~PSREF), R8
257	MOVW	R8, PSR
258	NOOP
259
260	MOVW	R7, R1
261	SAVE	R0, R0			/* RETT is implicit RESTORE */
262	MOVW	$(UTZERO+32), R7	/* PC; header appears in text */
263	MOVW	$(UTZERO+32+4), R8	/* nPC */
264	RETT	R7, R8
265
266TEXT	rfnote(SB), $0
267
268	MOVW	R7, R1			/* 1st arg is &uregpointer */
269	ADD	$4, R1			/* point at ureg */
270	JMP	restore
271
272TEXT	traplink(SB), $-4
273
274	/* R8 to R23 are free to play with */
275	/* R17 contains PC, R18 contains nPC */
276	/* R19 has PSR loaded from vector code */
277
278	ANDCC	$PSRPSUPER, R19, R0
279	BE	usertrap
280
281kerneltrap:
282	/*
283	 * Interrupt or fault from kernel
284	 */
285	ANDN	$7, R1, R20			/* dbl aligned */
286	MOVW	R1, (0-(4*(32+6))+(4*1))(R20)	/* save R1=SP */
287	/* really clumsy: store these in Ureg so can be restored below */
288	MOVW	R2, (0-(4*(32+6))+(4*2))(R20)	/* SB */
289	MOVW	R5, (0-(4*(32+6))+(4*5))(R20)	/* USER */
290	MOVW	R6, (0-(4*(32+6))+(4*6))(R20)	/* MACH */
291	SUB	$(4*(32+6)), R20, R1
292
293trap1:
294	MOVW	Y, R20
295	MOVW	R20, (4*(32+0))(R1)		/* Y */
296	MOVW	TBR, R20
297	MOVW	R20, (4*(32+1))(R1)		/* TBR */
298	AND	$~0x1F, R19			/* force CWP=0 */
299	MOVW	R19, (4*(32+2))(R1)		/* PSR */
300	MOVW	R18, (4*(32+3))(R1)		/* nPC */
301	MOVW	R17, (4*(32+4))(R1)		/* PC */
302	MOVW	R0, (4*0)(R1)
303	MOVW	R3, (4*3)(R1)
304	MOVW	R4, (4*4)(R1)
305	MOVW	R7, (4*7)(R1)
306	RESTORE	R0, R0
307	/* now our registers R8-R31 are same as before trap */
308	/* save registers two at a time */
309	MOVD	R8, (4*8)(R1)
310	MOVD	R10, (4*10)(R1)
311	MOVD	R12, (4*12)(R1)
312	MOVD	R14, (4*14)(R1)
313	MOVD	R16, (4*16)(R1)
314	MOVD	R18, (4*18)(R1)
315	MOVD	R20, (4*20)(R1)
316	MOVD	R22, (4*22)(R1)
317	MOVD	R24, (4*24)(R1)
318	MOVD	R26, (4*26)(R1)
319	MOVD	R28, (4*28)(R1)
320	MOVD	R30, (4*30)(R1)
321	/* SP and SB and u and m are already set; away we go */
322	MOVW	R1, R7		/* pointer to Ureg */
323	SUB	$8, R1
324	MOVW	$SYSPSR, R8
325	MOVW	R8, PSR
326	NOOP
327	JMPL	trap(SB)
328
329	ADD	$8, R1
330restore:
331	MOVW	(4*(32+2))(R1), R8		/* PSR */
332	MOVW	R8, PSR
333	NOOP
334
335	MOVD	(4*30)(R1), R30
336	MOVD	(4*28)(R1), R28
337	MOVD	(4*26)(R1), R26
338	MOVD	(4*24)(R1), R24
339	MOVD	(4*22)(R1), R22
340	MOVD	(4*20)(R1), R20
341	MOVD	(4*18)(R1), R18
342	MOVD	(4*16)(R1), R16
343	MOVD	(4*14)(R1), R14
344	MOVD	(4*12)(R1), R12
345	MOVD	(4*10)(R1), R10
346	MOVD	(4*8)(R1), R8
347	SAVE	R0, R0
348	MOVD	(4*6)(R1), R6
349	MOVD	(4*4)(R1), R4
350	MOVD	(4*2)(R1), R2
351	MOVW	(4*(32+0))(R1), R20		/* Y */
352	MOVW	R20, Y
353	MOVW	(4*(32+4))(R1), R17		/* PC */
354	MOVW	(4*(32+3))(R1), R18		/* nPC */
355	MOVW	(4*1)(R1), R1	/* restore R1=SP */
356	RETT	R17, R18
357
358usertrap:
359	/*
360	 * Interrupt or fault from user
361	 */
362	MOVW	R1, R8
363	MOVW	R2, R9
364	MOVW	$setSB(SB), R2
365	MOVW	$(USERADDR+BY2PG), R1
366	MOVW	R8, (0-(4*(32+6))+(4*1))(R1)	/* save R1=SP */
367	MOVW	R9, (0-(4*(32+6))+(4*2))(R1)	/* save R2=SB */
368	MOVW	R5, (0-(4*(32+6))+(4*5))(R1)	/* save R5=USER */
369	MOVW	R6, (0-(4*(32+6))+(4*6))(R1)	/* save R6=MACH */
370	MOVW	$USERADDR, R(USER)
371	MOVW	$mach0(SB), R(MACH)
372	SUB	$(4*(32+6)), R1
373	JMP	trap1
374
375TEXT	syslink(SB), $-4
376
377	/* R8 to R23 are free to play with */
378	/* R17 contains PC, R18 contains nPC */
379	/* R19 has PSR loaded from vector code */
380	/* assume user did it; syscall checks */
381
382	MOVW	R1, R8
383	MOVW	R2, R9
384	MOVW	$setSB(SB), R2
385	MOVW	$(USERADDR+BY2PG), R1
386	MOVW	R8, (0-(4*(32+6))+4)(R1)	/* save R1=SP */
387	SUB	$(4*(32+6)), R1
388	MOVW	R9, (4*2)(R1)			/* save R2=SB */
389	MOVW	R3, (4*3)(R1)			/* global register */
390	MOVD	R4, (4*4)(R1)			/* global register, R5=USER */
391	MOVD	R6, (4*6)(R1)			/* save R6=MACH, R7=syscall# */
392	MOVW	$USERADDR, R(USER)
393	MOVW	$mach0(SB), R(MACH)
394	MOVW	TBR, R20
395	MOVW	R20, (4*(32+1))(R1)		/* TBR */
396	AND	$~0x1F, R19
397	MOVW	R19, (4*(32+2))(R1)		/* PSR */
398	MOVW	R18, (4*(32+3))(R1)		/* nPC */
399	MOVW	R17, (4*(32+4))(R1)		/* PC */
400	RESTORE	R0, R0
401	/* now our registers R8-R31 are same as before trap */
402	MOVW	R15, (4*15)(R1)
403	/* SP and SB and u and m are already set; away we go */
404	MOVW	R1, R7			/* pointer to Ureg */
405	SUB	$8, R1
406	MOVW	$SYSPSR, R8
407	MOVW	R8, PSR
408	JMPL	syscall(SB)
409	/* R7 contains return value from syscall */
410
411	ADD	$8, R1
412	MOVW	(4*(32+2))(R1), R8		/* PSR */
413	MOVW	R8, PSR
414	NOOP
415
416	MOVW	(4*15)(R1), R15
417	SAVE	R0, R0
418	MOVW	(4*6)(R1), R6
419	MOVD	(4*4)(R1), R4
420	MOVD	(4*2)(R1), R2
421	MOVW	(4*(32+4))(R1), R17		/* PC */
422	MOVW	(4*(32+3))(R1), R18		/* nPC */
423	MOVW	(4*1)(R1), R1	/* restore R1=SP */
424	RETT	R17, R18
425
426TEXT	puttbr(SB), $0
427
428	MOVW	R7, TBR
429	NOOP
430	RETURN
431
432TEXT	gettbr(SB), $0
433
434	MOVW	TBR, R7
435	RETURN
436
437TEXT	r1(SB), $0
438
439	MOVW	R1, R7
440	RETURN
441
442TEXT	getwim(SB), $0
443
444	MOVW	WIM, R7
445	RETURN
446
447TEXT	setlabel(SB), $0
448
449	MOVW	R1, (R7)
450	MOVW	R15, 4(R7)
451	MOVW	$0, R7
452	RETURN
453
454TEXT	gotolabel(SB), $0
455
456	MOVW	(R7), R1
457	MOVW	4(R7), R15
458	MOVW	$1, R7
459	RETURN
460
461TEXT	putcxsegm(SB), $0
462
463	MOVW	R7, R8			/* context */
464	MOVW	4(FP), R9		/* segment addr */
465	MOVW	8(FP), R10		/* segment value */
466	MOVW	$0xFFE80118, R7
467	JMPL	(R7)
468	RETURN
469
470TEXT	getpsr(SB), $0
471
472	MOVW	PSR, R7
473	RETURN
474
475TEXT	putcxreg(SB), $0
476
477	MOVW	$CONTEXT, R8
478	MOVB	R7, (R8, 2)
479	RETURN
480
481TEXT	putb2(SB), $0
482
483	MOVW	4(FP), R8
484	MOVB	R8, (R7, 2)
485	RETURN
486
487TEXT	getb2(SB), $0
488
489	MOVB	(R7, 2), R7
490	RETURN
491
492TEXT	getw2(SB), $0
493
494	MOVW	(R7, 2), R7
495	RETURN
496
497TEXT	putw2(SB), $0
498
499	MOVW	4(FP), R8
500	MOVW	R8, (R7, 2)
501	RETURN
502
503TEXT	putw4(SB), $0
504
505	MOVW	4(FP), R8
506	MOVW	R8, (R7, 4)
507	RETURN
508
509TEXT	getw4(SB), $0
510
511	MOVW	(R7, 4), R7
512	RETURN
513
514TEXT	putwC(SB), $0
515
516	MOVW	4(FP), R8
517	MOVW	R8, (R7, 0xC)
518	RETURN
519
520TEXT	putwD(SB), $0
521
522	MOVW	4(FP), R8
523	MOVW	R8, (R7, 0xD)
524	RETURN
525
526TEXT	putwD16(SB), $0
527
528	MOVW	4(FP), R8
529	MOVW	R8, (R7, 0xD)
530	ADD	$(1<<4), R7
531	MOVW	R8, (R7, 0xD)
532	ADD	$(1<<4), R7
533	MOVW	R8, (R7, 0xD)
534	ADD	$(1<<4), R7
535	MOVW	R8, (R7, 0xD)
536	ADD	$(1<<4), R7
537	MOVW	R8, (R7, 0xD)
538	ADD	$(1<<4), R7
539	MOVW	R8, (R7, 0xD)
540	ADD	$(1<<4), R7
541	MOVW	R8, (R7, 0xD)
542	ADD	$(1<<4), R7
543	MOVW	R8, (R7, 0xD)
544	ADD	$(1<<4), R7
545	MOVW	R8, (R7, 0xD)
546	ADD	$(1<<4), R7
547	MOVW	R8, (R7, 0xD)
548	ADD	$(1<<4), R7
549	MOVW	R8, (R7, 0xD)
550	ADD	$(1<<4), R7
551	MOVW	R8, (R7, 0xD)
552	ADD	$(1<<4), R7
553	MOVW	R8, (R7, 0xD)
554	ADD	$(1<<4), R7
555	MOVW	R8, (R7, 0xD)
556	ADD	$(1<<4), R7
557	MOVW	R8, (R7, 0xD)
558	ADD	$(1<<4), R7
559	MOVW	R8, (R7, 0xD)
560	RETURN
561
562TEXT	putwE(SB), $0
563
564	MOVW	4(FP), R8
565	MOVW	R8, (R7, 0xE)
566	RETURN
567
568TEXT	putwE16(SB), $0
569
570	MOVW	4(FP), R8
571	MOVW	R8, (R7, 0xE)
572	ADD	$(1<<4), R7
573	MOVW	R8, (R7, 0xE)
574	ADD	$(1<<4), R7
575	MOVW	R8, (R7, 0xE)
576	ADD	$(1<<4), R7
577	MOVW	R8, (R7, 0xE)
578	ADD	$(1<<4), R7
579	MOVW	R8, (R7, 0xE)
580	ADD	$(1<<4), R7
581	MOVW	R8, (R7, 0xE)
582	ADD	$(1<<4), R7
583	MOVW	R8, (R7, 0xE)
584	ADD	$(1<<4), R7
585	MOVW	R8, (R7, 0xE)
586	ADD	$(1<<4), R7
587	MOVW	R8, (R7, 0xE)
588	ADD	$(1<<4), R7
589	MOVW	R8, (R7, 0xE)
590	ADD	$(1<<4), R7
591	MOVW	R8, (R7, 0xE)
592	ADD	$(1<<4), R7
593	MOVW	R8, (R7, 0xE)
594	ADD	$(1<<4), R7
595	MOVW	R8, (R7, 0xE)
596	ADD	$(1<<4), R7
597	MOVW	R8, (R7, 0xE)
598	ADD	$(1<<4), R7
599	MOVW	R8, (R7, 0xE)
600	ADD	$(1<<4), R7
601	MOVW	R8, (R7, 0xE)
602	RETURN
603
604TEXT	putsegm(SB), $0
605
606	MOVW	4(FP), R8
607	MOVW	R8, (R7, 3)
608	RETURN
609
610/*
611 * in savefpregs and restfpregs, incoming R7 points to doubleword
612 * below where F0 will go; doubleword align in and backfill FSR
613 */
614TEXT	savefpregs(SB), $0
615
616	ADD	$8, R7
617	ANDN	$7, R7		/* now MOVD-aligned */
618	MOVW	FSR, -4(R7)
619
620	MOVD	F0, (0*4)(R7)
621	MOVD	F2, (2*4)(R7)
622	MOVD	F4, (4*4)(R7)
623	MOVD	F6, (6*4)(R7)
624	MOVD	F8, (8*4)(R7)
625	MOVD	F10, (10*4)(R7)
626	MOVD	F12, (12*4)(R7)
627	MOVD	F14, (14*4)(R7)
628	MOVD	F16, (16*4)(R7)
629	MOVD	F18, (18*4)(R7)
630	MOVD	F20, (20*4)(R7)
631	MOVD	F22, (22*4)(R7)
632	MOVD	F24, (24*4)(R7)
633	MOVD	F26, (26*4)(R7)
634	MOVD	F28, (28*4)(R7)
635	MOVD	F30, (30*4)(R7)
636
637	MOVW	PSR, R8
638	ANDN	$PSREF, R8
639	MOVW	R8, PSR
640	RETURN
641
642TEXT	restfpregs(SB), $0
643
644	MOVW	PSR, R8
645	OR	$PSREF, R8
646	MOVW	R8, PSR
647
648	ADD	$8, R7
649	ANDN	$7, R7		/* now MOVD-aligned */
650	OR	R0, R0
651
652	MOVW	-4(R7), FSR
653
654	MOVD	(0*4)(R7), F0
655	MOVD	(2*4)(R7), F2
656	MOVD	(4*4)(R7), F4
657	MOVD	(6*4)(R7), F6
658	MOVD	(8*4)(R7), F8
659	MOVD	(10*4)(R7), F10
660	MOVD	(12*4)(R7), F12
661	MOVD	(14*4)(R7), F14
662	MOVD	(16*4)(R7), F16
663	MOVD	(18*4)(R7), F18
664	MOVD	(20*4)(R7), F20
665	MOVD	(22*4)(R7), F22
666	MOVD	(24*4)(R7), F24
667	MOVD	(26*4)(R7), F26
668	MOVD	(28*4)(R7), F28
669	MOVD	(30*4)(R7), F30
670
671	ANDN	$PSREF, R8
672	MOVW	R8, PSR
673	RETURN
674
675TEXT	clearfpintr(SB), $0
676
677	MOVW	$fpq+BY2WD(SB), R7
678	ANDN	$0x7, R7		/* must be D aligned */
679	MOVW	$fsr+0(SB), R9
680clrq:
681	MOVD	FQ, (R7)
682	MOVW	FSR, (R9)
683	MOVW	(R9), R8
684	AND	$(1<<13), R8		/* queue not empty? */
685	BNE	clrq
686	RETURN
687
688TEXT	getfsr(SB), $0
689	MOVW	$fsr+0(SB), R7
690	MOVW	FSR, (R7)
691	MOVW	(R7), R7
692	RETURN
693
694GLOBL	mach0+0(SB), $MACHSIZE
695GLOBL	fpq+0(SB), $(3*BY2WD)
696GLOBL	fsr+0(SB), $BY2WD
697