1/*	$OpenBSD: fp.S,v 1.2 1998/03/16 09:03:31 pefo Exp $	*/
2/*-
3 * Copyright (c) 1992, 1993
4 *	The Regents of the University of California.  All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Ralph Campbell.
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 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *	from: @(#)fp.s	8.1 (Berkeley) 6/10/93
34 *	JNPR: fp.S,v 1.1 2006/08/07 05:38:57 katta
35 * $FreeBSD$
36 */
37
38/*
39 * Standard header stuff.
40 */
41
42#include <machine/asm.h>
43#include <machine/regnum.h>
44#include <machine/cpuregs.h>
45
46#include "assym.s"
47
48#define	SEXP_INF	0xff
49#define	DEXP_INF	0x7ff
50#define	SEXP_BIAS	127
51#define	DEXP_BIAS	1023
52#define	SEXP_MIN	-126
53#define	DEXP_MIN	-1022
54#define	SEXP_MAX	127
55#define	DEXP_MAX	1023
56#define	WEXP_MAX	30		/* maximum unbiased exponent for int */
57#define	WEXP_MIN	-1		/* minimum unbiased exponent for int */
58#define	SFRAC_BITS	23
59#define	DFRAC_BITS	52
60#define	SIMPL_ONE	0x00800000
61#define	DIMPL_ONE	0x00100000
62#define	SLEAD_ZEROS	31 - 23
63#define	DLEAD_ZEROS	31 - 20
64#define	STICKYBIT	1
65#define	GUARDBIT	0x80000000
66#define	SSIGNAL_NAN	0x00400000
67#define	DSIGNAL_NAN	0x00080000
68#define	SQUIET_NAN	0x003fffff
69#define	DQUIET_NAN0	0x0007ffff
70#define	DQUIET_NAN1	0xffffffff
71#define	INT_MIN		0x80000000
72#define	INT_MAX		0x7fffffff
73
74#define	COND_UNORDERED	0x1
75#define	COND_EQUAL	0x2
76#define	COND_LESS	0x4
77#define	COND_SIGNAL	0x8
78
79.set hardfloat
80
81/*----------------------------------------------------------------------------
82 *
83 * MipsEmulateFP --
84 *
85 *	Emulate unimplemented floating point operations.
86 *	This routine should only be called by MipsFPInterrupt().
87 *
88 *	MipsEmulateFP(instr)
89 *		unsigned instr;
90 *
91 * Results:
92 *	None.
93 *
94 * Side effects:
95 *	Floating point registers are modified according to instruction.
96 *
97 *----------------------------------------------------------------------------
98 */
99NESTED(MipsEmulateFP, CALLFRAME_SIZ, ra)
100	subu	sp, sp, CALLFRAME_SIZ
101	sw	ra, CALLFRAME_RA(sp)
102/*
103 * Decode the FMT field (bits 24-21) and FUNCTION field (bits 5-0).
104 */
105	srl	v0, a0, 21 - 2			# get FMT field
106	and	v0, v0, 0xF << 2		# mask FMT field
107	and	v1, a0, 0x3F			# mask FUNC field
108	sll	v1, v1, 5			# align for table lookup
109	bgt	v0, 4 << 2, ill			# illegal format
110
111	or	v1, v1, v0
112	cfc1	a1, MIPS_FPU_CSR		# get exception register
113	lw	a3, func_fmt_tbl(v1)		# switch on FUNC & FMT
114	and	a1, a1, ~MIPS_FPU_EXCEPTION_UNIMPL # clear exception
115	ctc1	a1, MIPS_FPU_CSR
116	j	a3
117
118	.rdata
119func_fmt_tbl:
120	.word	add_s		# 0
121	.word	add_d		# 0
122	.word	ill		# 0
123	.word	ill		# 0
124	.word	ill		# 0
125	.word	ill		# 0
126	.word	ill		# 0
127	.word	ill		# 0
128	.word	sub_s		# 1
129	.word	sub_d		# 1
130	.word	ill		# 1
131	.word	ill		# 1
132	.word	ill		# 1
133	.word	ill		# 1
134	.word	ill		# 1
135	.word	ill		# 1
136	.word	mul_s		# 2
137	.word	mul_d		# 2
138	.word	ill		# 2
139	.word	ill		# 2
140	.word	ill		# 2
141	.word	ill		# 2
142	.word	ill		# 2
143	.word	ill		# 2
144	.word	div_s		# 3
145	.word	div_d		# 3
146	.word	ill		# 3
147	.word	ill		# 3
148	.word	ill		# 3
149	.word	ill		# 3
150	.word	ill		# 3
151	.word	ill		# 3
152	.word	ill		# 4
153	.word	ill		# 4
154	.word	ill		# 4
155	.word	ill		# 4
156	.word	ill		# 4
157	.word	ill		# 4
158	.word	ill		# 4
159	.word	ill		# 4
160	.word	abs_s		# 5
161	.word	abs_d		# 5
162	.word	ill		# 5
163	.word	ill		# 5
164	.word	ill		# 5
165	.word	ill		# 5
166	.word	ill		# 5
167	.word	ill		# 5
168	.word	mov_s		# 6
169	.word	mov_d		# 6
170	.word	ill		# 6
171	.word	ill		# 6
172	.word	ill		# 6
173	.word	ill		# 6
174	.word	ill		# 6
175	.word	ill		# 6
176	.word	neg_s		# 7
177	.word	neg_d		# 7
178	.word	ill		# 7
179	.word	ill		# 7
180	.word	ill		# 7
181	.word	ill		# 7
182	.word	ill		# 7
183	.word	ill		# 7
184	.word	ill		# 8
185	.word	ill		# 8
186	.word	ill		# 8
187	.word	ill		# 8
188	.word	ill		# 8
189	.word	ill		# 8
190	.word	ill		# 8
191	.word	ill		# 8
192	.word	ill		# 9
193	.word	ill		# 9
194	.word	ill		# 9
195	.word	ill		# 9
196	.word	ill		# 9
197	.word	ill		# 9
198	.word	ill		# 9
199	.word	ill		# 9
200	.word	ill		# 10
201	.word	ill		# 10
202	.word	ill		# 10
203	.word	ill		# 10
204	.word	ill		# 10
205	.word	ill		# 10
206	.word	ill		# 10
207	.word	ill		# 10
208	.word	ill		# 11
209	.word	ill		# 11
210	.word	ill		# 11
211	.word	ill		# 11
212	.word	ill		# 11
213	.word	ill		# 11
214	.word	ill		# 11
215	.word	ill		# 11
216	.word	ill		# 12
217	.word	ill		# 12
218	.word	ill		# 12
219	.word	ill		# 12
220	.word	ill		# 12
221	.word	ill		# 12
222	.word	ill		# 12
223	.word	ill		# 12
224	.word	ill		# 13
225	.word	ill		# 13
226	.word	ill		# 13
227	.word	ill		# 13
228	.word	ill		# 13
229	.word	ill		# 13
230	.word	ill		# 13
231	.word	ill		# 13
232	.word	ill		# 14
233	.word	ill		# 14
234	.word	ill		# 14
235	.word	ill		# 14
236	.word	ill		# 14
237	.word	ill		# 14
238	.word	ill		# 14
239	.word	ill		# 14
240	.word	ill		# 15
241	.word	ill		# 15
242	.word	ill		# 15
243	.word	ill		# 15
244	.word	ill		# 15
245	.word	ill		# 15
246	.word	ill		# 15
247	.word	ill		# 15
248	.word	ill		# 16
249	.word	ill		# 16
250	.word	ill		# 16
251	.word	ill		# 16
252	.word	ill		# 16
253	.word	ill		# 16
254	.word	ill		# 16
255	.word	ill		# 16
256	.word	ill		# 17
257	.word	ill		# 17
258	.word	ill		# 17
259	.word	ill		# 17
260	.word	ill		# 17
261	.word	ill		# 17
262	.word	ill		# 17
263	.word	ill		# 17
264	.word	ill		# 18
265	.word	ill		# 18
266	.word	ill		# 18
267	.word	ill		# 18
268	.word	ill		# 18
269	.word	ill		# 18
270	.word	ill		# 18
271	.word	ill		# 18
272	.word	ill		# 19
273	.word	ill		# 19
274	.word	ill		# 19
275	.word	ill		# 19
276	.word	ill		# 19
277	.word	ill		# 19
278	.word	ill		# 19
279	.word	ill		# 19
280	.word	ill		# 20
281	.word	ill		# 20
282	.word	ill		# 20
283	.word	ill		# 20
284	.word	ill		# 20
285	.word	ill		# 20
286	.word	ill		# 20
287	.word	ill		# 20
288	.word	ill		# 21
289	.word	ill		# 21
290	.word	ill		# 21
291	.word	ill		# 21
292	.word	ill		# 21
293	.word	ill		# 21
294	.word	ill		# 21
295	.word	ill		# 21
296	.word	ill		# 22
297	.word	ill		# 22
298	.word	ill		# 22
299	.word	ill		# 22
300	.word	ill		# 22
301	.word	ill		# 22
302	.word	ill		# 22
303	.word	ill		# 22
304	.word	ill		# 23
305	.word	ill		# 23
306	.word	ill		# 23
307	.word	ill		# 23
308	.word	ill		# 23
309	.word	ill		# 23
310	.word	ill		# 23
311	.word	ill		# 23
312	.word	ill		# 24
313	.word	ill		# 24
314	.word	ill		# 24
315	.word	ill		# 24
316	.word	ill		# 24
317	.word	ill		# 24
318	.word	ill		# 24
319	.word	ill		# 24
320	.word	ill		# 25
321	.word	ill		# 25
322	.word	ill		# 25
323	.word	ill		# 25
324	.word	ill		# 25
325	.word	ill		# 25
326	.word	ill		# 25
327	.word	ill		# 25
328	.word	ill		# 26
329	.word	ill		# 26
330	.word	ill		# 26
331	.word	ill		# 26
332	.word	ill		# 26
333	.word	ill		# 26
334	.word	ill		# 26
335	.word	ill		# 26
336	.word	ill		# 27
337	.word	ill		# 27
338	.word	ill		# 27
339	.word	ill		# 27
340	.word	ill		# 27
341	.word	ill		# 27
342	.word	ill		# 27
343	.word	ill		# 27
344	.word	ill		# 28
345	.word	ill		# 28
346	.word	ill		# 28
347	.word	ill		# 28
348	.word	ill		# 28
349	.word	ill		# 28
350	.word	ill		# 28
351	.word	ill		# 28
352	.word	ill		# 29
353	.word	ill		# 29
354	.word	ill		# 29
355	.word	ill		# 29
356	.word	ill		# 29
357	.word	ill		# 29
358	.word	ill		# 29
359	.word	ill		# 29
360	.word	ill		# 30
361	.word	ill		# 30
362	.word	ill		# 30
363	.word	ill		# 30
364	.word	ill		# 30
365	.word	ill		# 30
366	.word	ill		# 30
367	.word	ill		# 30
368	.word	ill		# 31
369	.word	ill		# 31
370	.word	ill		# 31
371	.word	ill		# 31
372	.word	ill		# 31
373	.word	ill		# 31
374	.word	ill		# 31
375	.word	ill		# 31
376	.word	ill		# 32
377	.word	cvt_s_d		# 32
378	.word	ill		# 32
379	.word	ill		# 32
380	.word	cvt_s_w		# 32
381	.word	ill		# 32
382	.word	ill		# 32
383	.word	ill		# 32
384	.word	cvt_d_s		# 33
385	.word	ill		# 33
386	.word	ill		# 33
387	.word	ill		# 33
388	.word	cvt_d_w		# 33
389	.word	ill		# 33
390	.word	ill		# 33
391	.word	ill		# 33
392	.word	ill		# 34
393	.word	ill		# 34
394	.word	ill		# 34
395	.word	ill		# 34
396	.word	ill		# 34
397	.word	ill		# 34
398	.word	ill		# 34
399	.word	ill		# 34
400	.word	ill		# 35
401	.word	ill		# 35
402	.word	ill		# 35
403	.word	ill		# 35
404	.word	ill		# 35
405	.word	ill		# 35
406	.word	ill		# 35
407	.word	ill		# 35
408	.word	cvt_w_s		# 36
409	.word	cvt_w_d		# 36
410	.word	ill		# 36
411	.word	ill		# 36
412	.word	ill		# 36
413	.word	ill		# 36
414	.word	ill		# 36
415	.word	ill		# 36
416	.word	ill		# 37
417	.word	ill		# 37
418	.word	ill		# 37
419	.word	ill		# 37
420	.word	ill		# 37
421	.word	ill		# 37
422	.word	ill		# 37
423	.word	ill		# 37
424	.word	ill		# 38
425	.word	ill		# 38
426	.word	ill		# 38
427	.word	ill		# 38
428	.word	ill		# 38
429	.word	ill		# 38
430	.word	ill		# 38
431	.word	ill		# 38
432	.word	ill		# 39
433	.word	ill		# 39
434	.word	ill		# 39
435	.word	ill		# 39
436	.word	ill		# 39
437	.word	ill		# 39
438	.word	ill		# 39
439	.word	ill		# 39
440	.word	ill		# 40
441	.word	ill		# 40
442	.word	ill		# 40
443	.word	ill		# 40
444	.word	ill		# 40
445	.word	ill		# 40
446	.word	ill		# 40
447	.word	ill		# 40
448	.word	ill		# 41
449	.word	ill		# 41
450	.word	ill		# 41
451	.word	ill		# 41
452	.word	ill		# 41
453	.word	ill		# 41
454	.word	ill		# 41
455	.word	ill		# 41
456	.word	ill		# 42
457	.word	ill		# 42
458	.word	ill		# 42
459	.word	ill		# 42
460	.word	ill		# 42
461	.word	ill		# 42
462	.word	ill		# 42
463	.word	ill		# 42
464	.word	ill		# 43
465	.word	ill		# 43
466	.word	ill		# 43
467	.word	ill		# 43
468	.word	ill		# 43
469	.word	ill		# 43
470	.word	ill		# 43
471	.word	ill		# 43
472	.word	ill		# 44
473	.word	ill		# 44
474	.word	ill		# 44
475	.word	ill		# 44
476	.word	ill		# 44
477	.word	ill		# 44
478	.word	ill		# 44
479	.word	ill		# 44
480	.word	ill		# 45
481	.word	ill		# 45
482	.word	ill		# 45
483	.word	ill		# 45
484	.word	ill		# 45
485	.word	ill		# 45
486	.word	ill		# 45
487	.word	ill		# 45
488	.word	ill		# 46
489	.word	ill		# 46
490	.word	ill		# 46
491	.word	ill		# 46
492	.word	ill		# 46
493	.word	ill		# 46
494	.word	ill		# 46
495	.word	ill		# 46
496	.word	ill		# 47
497	.word	ill		# 47
498	.word	ill		# 47
499	.word	ill		# 47
500	.word	ill		# 47
501	.word	ill		# 47
502	.word	ill		# 47
503	.word	ill		# 47
504	.word	cmp_s		# 48
505	.word	cmp_d		# 48
506	.word	ill		# 48
507	.word	ill		# 48
508	.word	ill		# 48
509	.word	ill		# 48
510	.word	ill		# 48
511	.word	ill		# 48
512	.word	cmp_s		# 49
513	.word	cmp_d		# 49
514	.word	ill		# 49
515	.word	ill		# 49
516	.word	ill		# 49
517	.word	ill		# 49
518	.word	ill		# 49
519	.word	ill		# 49
520	.word	cmp_s		# 50
521	.word	cmp_d		# 50
522	.word	ill		# 50
523	.word	ill		# 50
524	.word	ill		# 50
525	.word	ill		# 50
526	.word	ill		# 50
527	.word	ill		# 50
528	.word	cmp_s		# 51
529	.word	cmp_d		# 51
530	.word	ill		# 51
531	.word	ill		# 51
532	.word	ill		# 51
533	.word	ill		# 51
534	.word	ill		# 51
535	.word	ill		# 51
536	.word	cmp_s		# 52
537	.word	cmp_d		# 52
538	.word	ill		# 52
539	.word	ill		# 52
540	.word	ill		# 52
541	.word	ill		# 52
542	.word	ill		# 52
543	.word	ill		# 52
544	.word	cmp_s		# 53
545	.word	cmp_d		# 53
546	.word	ill		# 53
547	.word	ill		# 53
548	.word	ill		# 53
549	.word	ill		# 53
550	.word	ill		# 53
551	.word	ill		# 53
552	.word	cmp_s		# 54
553	.word	cmp_d		# 54
554	.word	ill		# 54
555	.word	ill		# 54
556	.word	ill		# 54
557	.word	ill		# 54
558	.word	ill		# 54
559	.word	ill		# 54
560	.word	cmp_s		# 55
561	.word	cmp_d		# 55
562	.word	ill		# 55
563	.word	ill		# 55
564	.word	ill		# 55
565	.word	ill		# 55
566	.word	ill		# 55
567	.word	ill		# 55
568	.word	cmp_s		# 56
569	.word	cmp_d		# 56
570	.word	ill		# 56
571	.word	ill		# 56
572	.word	ill		# 56
573	.word	ill		# 56
574	.word	ill		# 56
575	.word	ill		# 56
576	.word	cmp_s		# 57
577	.word	cmp_d		# 57
578	.word	ill		# 57
579	.word	ill		# 57
580	.word	ill		# 57
581	.word	ill		# 57
582	.word	ill		# 57
583	.word	ill		# 57
584	.word	cmp_s		# 58
585	.word	cmp_d		# 58
586	.word	ill		# 58
587	.word	ill		# 58
588	.word	ill		# 58
589	.word	ill		# 58
590	.word	ill		# 58
591	.word	ill		# 58
592	.word	cmp_s		# 59
593	.word	cmp_d		# 59
594	.word	ill		# 59
595	.word	ill		# 59
596	.word	ill		# 59
597	.word	ill		# 59
598	.word	ill		# 59
599	.word	ill		# 59
600	.word	cmp_s		# 60
601	.word	cmp_d		# 60
602	.word	ill		# 60
603	.word	ill		# 60
604	.word	ill		# 60
605	.word	ill		# 60
606	.word	ill		# 60
607	.word	ill		# 60
608	.word	cmp_s		# 61
609	.word	cmp_d		# 61
610	.word	ill		# 61
611	.word	ill		# 61
612	.word	ill		# 61
613	.word	ill		# 61
614	.word	ill		# 61
615	.word	ill		# 61
616	.word	cmp_s		# 62
617	.word	cmp_d		# 62
618	.word	ill		# 62
619	.word	ill		# 62
620	.word	ill		# 62
621	.word	ill		# 62
622	.word	ill		# 62
623	.word	ill		# 62
624	.word	cmp_s		# 63
625	.word	cmp_d		# 63
626	.word	ill		# 63
627	.word	ill		# 63
628	.word	ill		# 63
629	.word	ill		# 63
630	.word	ill		# 63
631	.word	ill		# 63
632	.text
633
634/*
635 * Single precision subtract.
636 */
637sub_s:
638	jal	get_ft_fs_s
639	xor	ta0, ta0, 1			# negate FT sign bit
640	b	add_sub_s
641/*
642 * Single precision add.
643 */
644add_s:
645	jal	get_ft_fs_s
646add_sub_s:
647	bne	t1, SEXP_INF, 1f		# is FS an infinity?
648	bne	ta1, SEXP_INF, result_fs_s	# if FT is not inf, result=FS
649	bne	t2, zero, result_fs_s		# if FS is NAN, result is FS
650	bne	ta2, zero, result_ft_s		# if FT is NAN, result is FT
651	bne	t0, ta0, invalid_s		# both infinities same sign?
652	b	result_fs_s			# result is in FS
6531:
654	beq	ta1, SEXP_INF, result_ft_s	# if FT is inf, result=FT
655	bne	t1, zero, 4f			# is FS a denormalized num?
656	beq	t2, zero, 3f			# is FS zero?
657	bne	ta1, zero, 2f			# is FT a denormalized num?
658	beq	ta2, zero, result_fs_s		# FT is zero, result=FS
659	jal	renorm_fs_s
660	jal	renorm_ft_s
661	b	5f
6622:
663	jal	renorm_fs_s
664	subu	ta1, ta1, SEXP_BIAS		# unbias FT exponent
665	or	ta2, ta2, SIMPL_ONE		# set implied one bit
666	b	5f
6673:
668	bne	ta1, zero, result_ft_s		# if FT != 0, result=FT
669	bne	ta2, zero, result_ft_s
670	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
671	bne	v0, MIPS_FPU_ROUND_RM, 1f	# round to -infinity?
672	or	t0, t0, ta0			# compute result sign
673	b	result_fs_s
6741:
675	and	t0, t0, ta0			# compute result sign
676	b	result_fs_s
6774:
678	bne	ta1, zero, 2f			# is FT a denormalized num?
679	beq	ta2, zero, result_fs_s		# FT is zero, result=FS
680	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
681	or	t2, t2, SIMPL_ONE		# set implied one bit
682	jal	renorm_ft_s
683	b	5f
6842:
685	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
686	or	t2, t2, SIMPL_ONE		# set implied one bit
687	subu	ta1, ta1, SEXP_BIAS		# unbias FT exponent
688	or	ta2, ta2, SIMPL_ONE		# set implied one bit
689/*
690 * Perform the addition.
691 */
6925:
693	move	t8, zero			# no shifted bits (sticky reg)
694	beq	t1, ta1, 4f			# no shift needed
695	subu	v0, t1, ta1			# v0 = difference of exponents
696	move	v1, v0				# v1 = abs(difference)
697	bge	v0, zero, 1f
698	negu	v1
6991:
700	ble	v1, SFRAC_BITS+2, 2f		# is difference too great?
701	li	t8, STICKYBIT			# set the sticky bit
702	bge	v0, zero, 1f			# check which exp is larger
703	move	t1, ta1				# result exp is FTs
704	move	t2, zero			# FSs fraction shifted is zero
705	b	4f
7061:
707	move	ta2, zero			# FTs fraction shifted is zero
708	b	4f
7092:
710	li	t9, 32				# compute 32 - abs(exp diff)
711	subu	t9, t9, v1
712	bgt	v0, zero, 3f			# if FS > FT, shift FTs frac
713	move	t1, ta1				# FT > FS, result exp is FTs
714	sll	t8, t2, t9			# save bits shifted out
715	srl	t2, t2, v1			# shift FSs fraction
716	b	4f
7173:
718	sll	t8, ta2, t9			# save bits shifted out
719	srl	ta2, ta2, v1			# shift FTs fraction
7204:
721	bne	t0, ta0, 1f			# if signs differ, subtract
722	addu	t2, t2, ta2			# add fractions
723	b	norm_s
7241:
725	blt	t2, ta2, 3f			# subtract larger from smaller
726	bne	t2, ta2, 2f			# if same, result=0
727	move	t1, zero			# result=0
728	move	t2, zero
729	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
730	bne	v0, MIPS_FPU_ROUND_RM, 1f	# round to -infinity?
731	or	t0, t0, ta0			# compute result sign
732	b	result_fs_s
7331:
734	and	t0, t0, ta0			# compute result sign
735	b	result_fs_s
7362:
737	sltu	t9, zero, t8			# compute t2:zero - ta2:t8
738	subu	t8, zero, t8
739	subu	t2, t2, ta2			# subtract fractions
740	subu	t2, t2, t9			# subtract barrow
741	b	norm_s
7423:
743	move	t0, ta0				# sign of result = FTs
744	sltu	t9, zero, t8			# compute ta2:zero - t2:t8
745	subu	t8, zero, t8
746	subu	t2, ta2, t2			# subtract fractions
747	subu	t2, t2, t9			# subtract barrow
748	b	norm_s
749
750/*
751 * Double precision subtract.
752 */
753sub_d:
754	jal	get_ft_fs_d
755	xor	ta0, ta0, 1			# negate sign bit
756	b	add_sub_d
757/*
758 * Double precision add.
759 */
760add_d:
761	jal	get_ft_fs_d
762add_sub_d:
763	bne	t1, DEXP_INF, 1f		# is FS an infinity?
764	bne	ta1, DEXP_INF, result_fs_d	# if FT is not inf, result=FS
765	bne	t2, zero, result_fs_d		# if FS is NAN, result is FS
766	bne	t3, zero, result_fs_d
767	bne	ta2, zero, result_ft_d		# if FT is NAN, result is FT
768	bne	ta3, zero, result_ft_d
769	bne	t0, ta0, invalid_d		# both infinities same sign?
770	b	result_fs_d			# result is in FS
7711:
772	beq	ta1, DEXP_INF, result_ft_d	# if FT is inf, result=FT
773	bne	t1, zero, 4f			# is FS a denormalized num?
774	bne	t2, zero, 1f			# is FS zero?
775	beq	t3, zero, 3f
7761:
777	bne	ta1, zero, 2f			# is FT a denormalized num?
778	bne	ta2, zero, 1f
779	beq	ta3, zero, result_fs_d		# FT is zero, result=FS
7801:
781	jal	renorm_fs_d
782	jal	renorm_ft_d
783	b	5f
7842:
785	jal	renorm_fs_d
786	subu	ta1, ta1, DEXP_BIAS		# unbias FT exponent
787	or	ta2, ta2, DIMPL_ONE		# set implied one bit
788	b	5f
7893:
790	bne	ta1, zero, result_ft_d		# if FT != 0, result=FT
791	bne	ta2, zero, result_ft_d
792	bne	ta3, zero, result_ft_d
793	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
794	bne	v0, MIPS_FPU_ROUND_RM, 1f	# round to -infinity?
795	or	t0, t0, ta0			# compute result sign
796	b	result_fs_d
7971:
798	and	t0, t0, ta0			# compute result sign
799	b	result_fs_d
8004:
801	bne	ta1, zero, 2f			# is FT a denormalized num?
802	bne	ta2, zero, 1f
803	beq	ta3, zero, result_fs_d		# FT is zero, result=FS
8041:
805	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
806	or	t2, t2, DIMPL_ONE		# set implied one bit
807	jal	renorm_ft_d
808	b	5f
8092:
810	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
811	or	t2, t2, DIMPL_ONE		# set implied one bit
812	subu	ta1, ta1, DEXP_BIAS		# unbias FT exponent
813	or	ta2, ta2, DIMPL_ONE		# set implied one bit
814/*
815 * Perform the addition.
816 */
8175:
818	move	t8, zero			# no shifted bits (sticky reg)
819	beq	t1, ta1, 4f			# no shift needed
820	subu	v0, t1, ta1			# v0 = difference of exponents
821	move	v1, v0				# v1 = abs(difference)
822	bge	v0, zero, 1f
823	negu	v1
8241:
825	ble	v1, DFRAC_BITS+2, 2f		# is difference too great?
826	li	t8, STICKYBIT			# set the sticky bit
827	bge	v0, zero, 1f			# check which exp is larger
828	move	t1, ta1				# result exp is FTs
829	move	t2, zero			# FSs fraction shifted is zero
830	move	t3, zero
831	b	4f
8321:
833	move	ta2, zero			# FTs fraction shifted is zero
834	move	ta3, zero
835	b	4f
8362:
837	li	t9, 32
838	bge	v0, zero, 3f			# if FS > FT, shift FTs frac
839	move	t1, ta1				# FT > FS, result exp is FTs
840	blt	v1, t9, 1f			# shift right by < 32?
841	subu	v1, v1, t9
842	subu	t9, t9, v1
843	sll	t8, t2, t9			# save bits shifted out
844	sltu	t9, zero, t3			# dont lose any one bits
845	or	t8, t8, t9			# save sticky bit
846	srl	t3, t2, v1			# shift FSs fraction
847	move	t2, zero
848	b	4f
8491:
850	subu	t9, t9, v1
851	sll	t8, t3, t9			# save bits shifted out
852	srl	t3, t3, v1			# shift FSs fraction
853	sll	t9, t2, t9			# save bits shifted out of t2
854	or	t3, t3, t9			# and put into t3
855	srl	t2, t2, v1
856	b	4f
8573:
858	blt	v1, t9, 1f			# shift right by < 32?
859	subu	v1, v1, t9
860	subu	t9, t9, v1
861	sll	t8, ta2, t9			# save bits shifted out
862	srl	ta3, ta2, v1			# shift FTs fraction
863	move	ta2, zero
864	b	4f
8651:
866	subu	t9, t9, v1
867	sll	t8, ta3, t9			# save bits shifted out
868	srl	ta3, ta3, v1			# shift FTs fraction
869	sll	t9, ta2, t9			# save bits shifted out of t2
870	or	ta3, ta3, t9			# and put into t3
871	srl	ta2, ta2, v1
8724:
873	bne	t0, ta0, 1f			# if signs differ, subtract
874	addu	t3, t3, ta3			# add fractions
875	sltu	t9, t3, ta3			# compute carry
876	addu	t2, t2, ta2			# add fractions
877	addu	t2, t2, t9			# add carry
878	b	norm_d
8791:
880	blt	t2, ta2, 3f			# subtract larger from smaller
881	bne	t2, ta2, 2f
882	bltu	t3, ta3, 3f
883	bne	t3, ta3, 2f			# if same, result=0
884	move	t1, zero			# result=0
885	move	t2, zero
886	move	t3, zero
887	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
888	bne	v0, MIPS_FPU_ROUND_RM, 1f	# round to -infinity?
889	or	t0, t0, ta0			# compute result sign
890	b	result_fs_d
8911:
892	and	t0, t0, ta0			# compute result sign
893	b	result_fs_d
8942:
895	beq	t8, zero, 1f			# compute t2:t3:zero - ta2:ta3:t8
896	subu	t8, zero, t8
897	sltu	v0, t3, 1			# compute barrow out
898	subu	t3, t3, 1			# subtract barrow
899	subu	t2, t2, v0
9001:
901	sltu	v0, t3, ta3
902	subu	t3, t3, ta3			# subtract fractions
903	subu	t2, t2, ta2			# subtract fractions
904	subu	t2, t2, v0			# subtract barrow
905	b	norm_d
9063:
907	move	t0, ta0				# sign of result = FTs
908	beq	t8, zero, 1f			# compute ta2:ta3:zero - t2:t3:t8
909	subu	t8, zero, t8
910	sltu	v0, ta3, 1			# compute barrow out
911	subu	ta3, ta3, 1			# subtract barrow
912	subu	ta2, ta2, v0
9131:
914	sltu	v0, ta3, t3
915	subu	t3, ta3, t3			# subtract fractions
916	subu	t2, ta2, t2			# subtract fractions
917	subu	t2, t2, v0			# subtract barrow
918	b	norm_d
919
920/*
921 * Single precision multiply.
922 */
923mul_s:
924	jal	get_ft_fs_s
925	xor	t0, t0, ta0			# compute sign of result
926	move	ta0, t0
927	bne	t1, SEXP_INF, 2f		# is FS an infinity?
928	bne	t2, zero, result_fs_s		# if FS is a NAN, result=FS
929	bne	ta1, SEXP_INF, 1f		# FS is inf, is FT an infinity?
930	bne	ta2, zero, result_ft_s		# if FT is a NAN, result=FT
931	b	result_fs_s			# result is infinity
9321:
933	bne	ta1, zero, result_fs_s		# inf * zero? if no, result=FS
934	bne	ta2, zero, result_fs_s
935	b	invalid_s			# infinity * zero is invalid
9362:
937	bne	ta1, SEXP_INF, 1f		# FS != inf, is FT an infinity?
938	bne	t1, zero, result_ft_s		# zero * inf? if no, result=FT
939	bne	t2, zero, result_ft_s
940	bne	ta2, zero, result_ft_s		# if FT is a NAN, result=FT
941	b	invalid_s			# zero * infinity is invalid
9421:
943	bne	t1, zero, 1f			# is FS zero?
944	beq	t2, zero, result_fs_s		# result is zero
945	jal	renorm_fs_s
946	b	2f
9471:
948	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
949	or	t2, t2, SIMPL_ONE		# set implied one bit
9502:
951	bne	ta1, zero, 1f			# is FT zero?
952	beq	ta2, zero, result_ft_s		# result is zero
953	jal	renorm_ft_s
954	b	2f
9551:
956	subu	ta1, ta1, SEXP_BIAS		# unbias FT exponent
957	or	ta2, ta2, SIMPL_ONE		# set implied one bit
9582:
959	addu	t1, t1, ta1			# compute result exponent
960	addu	t1, t1, 9			# account for binary point
961	multu	t2, ta2				# multiply fractions
962	mflo	t8
963	mfhi	t2
964	b	norm_s
965
966/*
967 * Double precision multiply.
968 */
969mul_d:
970	jal	get_ft_fs_d
971	xor	t0, t0, ta0			# compute sign of result
972	move	ta0, t0
973	bne	t1, DEXP_INF, 2f		# is FS an infinity?
974	bne	t2, zero, result_fs_d		# if FS is a NAN, result=FS
975	bne	t3, zero, result_fs_d
976	bne	ta1, DEXP_INF, 1f		# FS is inf, is FT an infinity?
977	bne	ta2, zero, result_ft_d		# if FT is a NAN, result=FT
978	bne	ta3, zero, result_ft_d
979	b	result_fs_d			# result is infinity
9801:
981	bne	ta1, zero, result_fs_d		# inf * zero? if no, result=FS
982	bne	ta2, zero, result_fs_d
983	bne	ta3, zero, result_fs_d
984	b	invalid_d			# infinity * zero is invalid
9852:
986	bne	ta1, DEXP_INF, 1f		# FS != inf, is FT an infinity?
987	bne	t1, zero, result_ft_d		# zero * inf? if no, result=FT
988	bne	t2, zero, result_ft_d		# if FS is a NAN, result=FS
989	bne	t3, zero, result_ft_d
990	bne	ta2, zero, result_ft_d		# if FT is a NAN, result=FT
991	bne	ta3, zero, result_ft_d
992	b	invalid_d			# zero * infinity is invalid
9931:
994	bne	t1, zero, 2f			# is FS zero?
995	bne	t2, zero, 1f
996	beq	t3, zero, result_fs_d		# result is zero
9971:
998	jal	renorm_fs_d
999	b	3f
10002:
1001	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
1002	or	t2, t2, DIMPL_ONE		# set implied one bit
10033:
1004	bne	ta1, zero, 2f			# is FT zero?
1005	bne	ta2, zero, 1f
1006	beq	ta3, zero, result_ft_d		# result is zero
10071:
1008	jal	renorm_ft_d
1009	b	3f
10102:
1011	subu	ta1, ta1, DEXP_BIAS		# unbias FT exponent
1012	or	ta2, ta2, DIMPL_ONE		# set implied one bit
10133:
1014	addu	t1, t1, ta1			# compute result exponent
1015	addu	t1, t1, 12			# ???
1016	multu	t3, ta3				# multiply fractions (low * low)
1017	move	ta0, t2				# free up t2,t3 for result
1018	move	ta1, t3
1019	mflo	a3				# save low order bits
1020	mfhi	t8
1021	not	v0, t8
1022	multu	ta0, ta3			# multiply FS(high) * FT(low)
1023	mflo	v1
1024	mfhi	t3				# init low result
1025	sltu	v0, v0, v1			# compute carry
1026	addu	t8, v1
1027	multu	ta1, ta2			# multiply FS(low) * FT(high)
1028	addu	t3, t3, v0			# add carry
1029	not	v0, t8
1030	mflo	v1
1031	mfhi	t2
1032	sltu	v0, v0, v1
1033	addu	t8, v1
1034	multu	ta0, ta2			# multiply FS(high) * FT(high)
1035	addu	t3, v0
1036	not	v1, t3
1037	sltu	v1, v1, t2
1038	addu	t3, t2
1039	not	v0, t3
1040	mfhi	t2
1041	addu	t2, v1
1042	mflo	v1
1043	sltu	v0, v0, v1
1044	addu	t2, v0
1045	addu	t3, v1
1046	sltu	a3, zero, a3			# reduce t8,a3 to just t8
1047	or	t8, a3
1048	b	norm_d
1049
1050/*
1051 * Single precision divide.
1052 */
1053div_s:
1054	jal	get_ft_fs_s
1055	xor	t0, t0, ta0			# compute sign of result
1056	move	ta0, t0
1057	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1058	bne	t2, zero, result_fs_s		# if FS is NAN, result is FS
1059	bne	ta1, SEXP_INF, result_fs_s	# is FT an infinity?
1060	bne	ta2, zero, result_ft_s		# if FT is NAN, result is FT
1061	b	invalid_s			# infinity/infinity is invalid
10621:
1063	bne	ta1, SEXP_INF, 1f		# is FT an infinity?
1064	bne	ta2, zero, result_ft_s		# if FT is NAN, result is FT
1065	move	t1, zero			# x / infinity is zero
1066	move	t2, zero
1067	b	result_fs_s
10681:
1069	bne	t1, zero, 2f			# is FS zero?
1070	bne	t2, zero, 1f
1071	bne	ta1, zero, result_fs_s		# FS=zero, is FT zero?
1072	beq	ta2, zero, invalid_s		# 0 / 0
1073	b	result_fs_s			# result = zero
10741:
1075	jal	renorm_fs_s
1076	b	3f
10772:
1078	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
1079	or	t2, t2, SIMPL_ONE		# set implied one bit
10803:
1081	bne	ta1, zero, 2f			# is FT zero?
1082	bne	ta2, zero, 1f
1083	or	a1, a1, MIPS_FPU_EXCEPTION_DIV0 | MIPS_FPU_STICKY_DIV0
1084	and	v0, a1, MIPS_FPU_ENABLE_DIV0 	# trap enabled?
1085	bne	v0, zero, fpe_trap
1086	ctc1	a1, MIPS_FPU_CSR		# save exceptions
1087	li	t1, SEXP_INF			# result is infinity
1088	move	t2, zero
1089	b	result_fs_s
10901:
1091	jal	renorm_ft_s
1092	b	3f
10932:
1094	subu	ta1, ta1, SEXP_BIAS		# unbias FT exponent
1095	or	ta2, ta2, SIMPL_ONE		# set implied one bit
10963:
1097	subu	t1, t1, ta1			# compute exponent
1098	subu	t1, t1, 3			# compensate for result position
1099	li	v0, SFRAC_BITS+3		# number of bits to divide
1100	move	t8, t2				# init dividend
1101	move	t2, zero			# init result
11021:
1103	bltu	t8, ta2, 3f			# is dividend >= divisor?
11042:
1105	subu	t8, t8, ta2			# subtract divisor from dividend
1106	or	t2, t2, 1			# remember that we did
1107	bne	t8, zero, 3f			# if not done, continue
1108	sll	t2, t2, v0			# shift result to final position
1109	b	norm_s
11103:
1111	sll	t8, t8, 1			# shift dividend
1112	sll	t2, t2, 1			# shift result
1113	subu	v0, v0, 1			# are we done?
1114	bne	v0, zero, 1b			# no, continue
1115	b	norm_s
1116
1117/*
1118 * Double precision divide.
1119 */
1120div_d:
1121	jal	get_ft_fs_d
1122	xor	t0, t0, ta0			# compute sign of result
1123	move	ta0, t0
1124	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1125	bne	t2, zero, result_fs_d		# if FS is NAN, result is FS
1126	bne	t3, zero, result_fs_d
1127	bne	ta1, DEXP_INF, result_fs_d	# is FT an infinity?
1128	bne	ta2, zero, result_ft_d		# if FT is NAN, result is FT
1129	bne	ta3, zero, result_ft_d
1130	b	invalid_d			# infinity/infinity is invalid
11311:
1132	bne	ta1, DEXP_INF, 1f		# is FT an infinity?
1133	bne	ta2, zero, result_ft_d		# if FT is NAN, result is FT
1134	bne	ta3, zero, result_ft_d
1135	move	t1, zero			# x / infinity is zero
1136	move	t2, zero
1137	move	t3, zero
1138	b	result_fs_d
11391:
1140	bne	t1, zero, 2f			# is FS zero?
1141	bne	t2, zero, 1f
1142	bne	t3, zero, 1f
1143	bne	ta1, zero, result_fs_d		# FS=zero, is FT zero?
1144	bne	ta2, zero, result_fs_d
1145	beq	ta3, zero, invalid_d		# 0 / 0
1146	b	result_fs_d			# result = zero
11471:
1148	jal	renorm_fs_d
1149	b	3f
11502:
1151	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
1152	or	t2, t2, DIMPL_ONE		# set implied one bit
11533:
1154	bne	ta1, zero, 2f			# is FT zero?
1155	bne	ta2, zero, 1f
1156	bne	ta3, zero, 1f
1157	or	a1, a1, MIPS_FPU_EXCEPTION_DIV0 | MIPS_FPU_STICKY_DIV0
1158	and	v0, a1, MIPS_FPU_ENABLE_DIV0	# trap enabled?
1159	bne	v0, zero, fpe_trap
1160	ctc1	a1, MIPS_FPU_CSR		# Save exceptions
1161	li	t1, DEXP_INF			# result is infinity
1162	move	t2, zero
1163	move	t3, zero
1164	b	result_fs_d
11651:
1166	jal	renorm_ft_d
1167	b	3f
11682:
1169	subu	ta1, ta1, DEXP_BIAS		# unbias FT exponent
1170	or	ta2, ta2, DIMPL_ONE		# set implied one bit
11713:
1172	subu	t1, t1, ta1			# compute exponent
1173	subu	t1, t1, 3			# compensate for result position
1174	li	v0, DFRAC_BITS+3		# number of bits to divide
1175	move	t8, t2				# init dividend
1176	move	t9, t3
1177	move	t2, zero			# init result
1178	move	t3, zero
11791:
1180	bltu	t8, ta2, 3f			# is dividend >= divisor?
1181	bne	t8, ta2, 2f
1182	bltu	t9, ta3, 3f
11832:
1184	sltu	v1, t9, ta3			# subtract divisor from dividend
1185	subu	t9, t9, ta3
1186	subu	t8, t8, ta2
1187	subu	t8, t8, v1
1188	or	t3, t3, 1			# remember that we did
1189	bne	t8, zero, 3f			# if not done, continue
1190	bne	t9, zero, 3f
1191	li	v1, 32				# shift result to final position
1192	blt	v0, v1, 2f			# shift < 32 bits?
1193	subu	v0, v0, v1			# shift by > 32 bits
1194	sll	t2, t3, v0			# shift upper part
1195	move	t3, zero
1196	b	norm_d
11972:
1198	subu	v1, v1, v0			# shift by < 32 bits
1199	sll	t2, t2, v0			# shift upper part
1200	srl	t9, t3, v1			# save bits shifted out
1201	or	t2, t2, t9			# and put into upper part
1202	sll	t3, t3, v0
1203	b	norm_d
12043:
1205	sll	t8, t8, 1			# shift dividend
1206	srl	v1, t9, 31			# save bit shifted out
1207	or	t8, t8, v1			# and put into upper part
1208	sll	t9, t9, 1
1209	sll	t2, t2, 1			# shift result
1210	srl	v1, t3, 31			# save bit shifted out
1211	or	t2, t2, v1			# and put into upper part
1212	sll	t3, t3, 1
1213	subu	v0, v0, 1			# are we done?
1214	bne	v0, zero, 1b			# no, continue
1215	sltu	v0, zero, t9			# be sure to save any one bits
1216	or	t8, t8, v0			# from the lower remainder
1217	b	norm_d
1218
1219/*
1220 * Single precision absolute value.
1221 */
1222abs_s:
1223	jal	get_fs_s
1224	move	t0, zero			# set sign positive
1225	b	result_fs_s
1226
1227/*
1228 * Double precision absolute value.
1229 */
1230abs_d:
1231	jal	get_fs_d
1232	move	t0, zero			# set sign positive
1233	b	result_fs_d
1234
1235/*
1236 * Single precision move.
1237 */
1238mov_s:
1239	jal	get_fs_s
1240	b	result_fs_s
1241
1242/*
1243 * Double precision move.
1244 */
1245mov_d:
1246	jal	get_fs_d
1247	b	result_fs_d
1248
1249/*
1250 * Single precision negate.
1251 */
1252neg_s:
1253	jal	get_fs_s
1254	xor	t0, t0, 1			# reverse sign
1255	b	result_fs_s
1256
1257/*
1258 * Double precision negate.
1259 */
1260neg_d:
1261	jal	get_fs_d
1262	xor	t0, t0, 1			# reverse sign
1263	b	result_fs_d
1264
1265/*
1266 * Convert double to single.
1267 */
1268cvt_s_d:
1269	jal	get_fs_d
1270	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1271	li	t1, SEXP_INF			# convert to single
1272	sll	t2, t2, 3			# convert D fraction to S
1273	srl	t8, t3, 32 - 3
1274	or	t2, t2, t8
1275	b	result_fs_s
12761:
1277	bne	t1, zero, 2f			# is FS zero?
1278	bne	t2, zero, 1f
1279	beq	t3, zero, result_fs_s		# result=0
12801:
1281	jal	renorm_fs_d
1282	subu	t1, t1, 3			# correct exp for shift below
1283	b	3f
12842:
1285	subu	t1, t1, DEXP_BIAS		# unbias exponent
1286	or	t2, t2, DIMPL_ONE		# add implied one bit
12873:
1288	sll	t2, t2, 3			# convert D fraction to S
1289	srl	t8, t3, 32 - 3
1290	or	t2, t2, t8
1291	sll	t8, t3, 3
1292	b	norm_noshift_s
1293
1294/*
1295 * Convert integer to single.
1296 */
1297cvt_s_w:
1298	jal	get_fs_int
1299	bne	t2, zero, 1f			# check for zero
1300	move	t1, zero
1301	b	result_fs_s
1302/*
1303 * Find out how many leading zero bits are in t2 and put in t9.
1304 */
13051:
1306	move	v0, t2
1307	move	t9, zero
1308	srl	v1, v0, 16
1309	bne	v1, zero, 1f
1310	addu	t9, 16
1311	sll	v0, 16
13121:
1313	srl	v1, v0, 24
1314	bne	v1, zero, 1f
1315	addu	t9, 8
1316	sll	v0, 8
13171:
1318	srl	v1, v0, 28
1319	bne	v1, zero, 1f
1320	addu	t9, 4
1321	sll	v0, 4
13221:
1323	srl	v1, v0, 30
1324	bne	v1, zero, 1f
1325	addu	t9, 2
1326	sll	v0, 2
13271:
1328	srl	v1, v0, 31
1329	bne	v1, zero, 1f
1330	addu	t9, 1
1331/*
1332 * Now shift t2 the correct number of bits.
1333 */
13341:
1335	subu	t9, t9, SLEAD_ZEROS		# dont count leading zeros
1336	li	t1, 23				# init exponent
1337	subu	t1, t1, t9			# compute exponent
1338	beq	t9, zero, 1f
1339	li	v0, 32
1340	blt	t9, zero, 2f			# if shift < 0, shift right
1341	subu	v0, v0, t9
1342	sll	t2, t2, t9			# shift left
13431:
1344	add	t1, t1, SEXP_BIAS		# bias exponent
1345	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1346	b	result_fs_s
13472:
1348	negu	t9				# shift right by t9
1349	subu	v0, v0, t9
1350	sll	t8, t2, v0			# save bits shifted out
1351	srl	t2, t2, t9
1352	b	norm_noshift_s
1353
1354/*
1355 * Convert single to double.
1356 */
1357cvt_d_s:
1358	jal	get_fs_s
1359	move	t3, zero
1360	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1361	li	t1, DEXP_INF			# convert to double
1362	b	result_fs_d
13631:
1364	bne	t1, zero, 2f			# is FS denormalized or zero?
1365	beq	t2, zero, result_fs_d		# is FS zero?
1366	jal	renorm_fs_s
1367	move	t8, zero
1368	b	norm_d
13692:
1370	addu	t1, t1, DEXP_BIAS - SEXP_BIAS	# bias exponent correctly
1371	sll	t3, t2, 32 - 3			# convert S fraction to D
1372	srl	t2, t2, 3
1373	b	result_fs_d
1374
1375/*
1376 * Convert integer to double.
1377 */
1378cvt_d_w:
1379	jal	get_fs_int
1380	bne	t2, zero, 1f			# check for zero
1381	move	t1, zero			# result=0
1382	move	t3, zero
1383	b	result_fs_d
1384/*
1385 * Find out how many leading zero bits are in t2 and put in t9.
1386 */
13871:
1388	move	v0, t2
1389	move	t9, zero
1390	srl	v1, v0, 16
1391	bne	v1, zero, 1f
1392	addu	t9, 16
1393	sll	v0, 16
13941:
1395	srl	v1, v0, 24
1396	bne	v1, zero, 1f
1397	addu	t9, 8
1398	sll	v0, 8
13991:
1400	srl	v1, v0, 28
1401	bne	v1, zero, 1f
1402	addu	t9, 4
1403	sll	v0, 4
14041:
1405	srl	v1, v0, 30
1406	bne	v1, zero, 1f
1407	addu	t9, 2
1408	sll	v0, 2
14091:
1410	srl	v1, v0, 31
1411	bne	v1, zero, 1f
1412	addu	t9, 1
1413/*
1414 * Now shift t2 the correct number of bits.
1415 */
14161:
1417	subu	t9, t9, DLEAD_ZEROS		# dont count leading zeros
1418	li	t1, DEXP_BIAS + 20		# init exponent
1419	subu	t1, t1, t9			# compute exponent
1420	beq	t9, zero, 1f
1421	li	v0, 32
1422	blt	t9, zero, 2f			# if shift < 0, shift right
1423	subu	v0, v0, t9
1424	sll	t2, t2, t9			# shift left
14251:
1426	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1427	move	t3, zero
1428	b	result_fs_d
14292:
1430	negu	t9				# shift right by t9
1431	subu	v0, v0, t9
1432	sll	t3, t2, v0
1433	srl	t2, t2, t9
1434	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1435	b	result_fs_d
1436
1437/*
1438 * Convert single to integer.
1439 */
1440cvt_w_s:
1441	jal	get_fs_s
1442	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1443	bne	t2, zero, invalid_w		# invalid conversion
14441:
1445	bne	t1, zero, 1f			# is FS zero?
1446	beq	t2, zero, result_fs_w		# result is zero
1447	move	t2, zero			# result is an inexact zero
1448	b	inexact_w
14491:
1450	subu	t1, t1, SEXP_BIAS		# unbias exponent
1451	or	t2, t2, SIMPL_ONE		# add implied one bit
1452	sll	t3, t2, 32 - 3			# convert S fraction to D
1453	srl	t2, t2, 3
1454	b	cvt_w
1455
1456/*
1457 * Convert double to integer.
1458 */
1459cvt_w_d:
1460	jal	get_fs_d
1461	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1462	bne	t2, zero, invalid_w		# invalid conversion
1463	bne	t3, zero, invalid_w		# invalid conversion
14641:
1465	bne	t1, zero, 2f			# is FS zero?
1466	bne	t2, zero, 1f
1467	beq	t3, zero, result_fs_w		# result is zero
14681:
1469	move	t2, zero			# result is an inexact zero
1470	b	inexact_w
14712:
1472	subu	t1, t1, DEXP_BIAS		# unbias exponent
1473	or	t2, t2, DIMPL_ONE		# add implied one bit
1474cvt_w:
1475	blt	t1, WEXP_MIN, underflow_w	# is exponent too small?
1476	li	v0, WEXP_MAX+1
1477	bgt	t1, v0, overflow_w		# is exponent too large?
1478	bne	t1, v0, 1f			# special check for INT_MIN
1479	beq	t0, zero, overflow_w		# if positive, overflow
1480	bne	t2, DIMPL_ONE, overflow_w
1481	bne	t3, zero, overflow_w
1482	li	t2, INT_MIN			# result is INT_MIN
1483	b	result_fs_w
14841:
1485	subu	v0, t1, 20			# compute amount to shift
1486	beq	v0, zero, 2f			# is shift needed?
1487	li	v1, 32
1488	blt	v0, zero, 1f			# if shift < 0, shift right
1489	subu	v1, v1, v0			# shift left
1490	sll	t2, t2, v0
1491	srl	t9, t3, v1			# save bits shifted out of t3
1492	or	t2, t2, t9			# and put into t2
1493	sll	t3, t3, v0			# shift FSs fraction
1494	b	2f
14951:
1496	negu	v0				# shift right by v0
1497	subu	v1, v1, v0
1498	sll	t8, t3, v1			# save bits shifted out
1499	sltu	t8, zero, t8			# dont lose any ones
1500	srl	t3, t3, v0			# shift FSs fraction
1501	or	t3, t3, t8
1502	sll	t9, t2, v1			# save bits shifted out of t2
1503	or	t3, t3, t9			# and put into t3
1504	srl	t2, t2, v0
1505/*
1506 * round result (t0 is sign, t2 is integer part, t3 is fractional part).
1507 */
15082:
1509	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
1510	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
1511	beq	v0, MIPS_FPU_ROUND_RZ, 5f	# round to zero (truncate)
1512	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
1513	beq	t0, zero, 5f			# if sign is positive, truncate
1514	b	2f
15151:
1516	bne	t0, zero, 5f			# if sign is negative, truncate
15172:
1518	beq	t3, zero, 5f			# if no fraction bits, continue
1519	addu	t2, t2, 1			# add rounding bit
1520	blt	t2, zero, overflow_w		# overflow?
1521	b	5f
15223:
1523	li	v0, GUARDBIT			# load guard bit for rounding
1524	addu	v0, v0, t3			# add remainder
1525	sltu	v1, v0, t3			# compute carry out
1526	beq	v1, zero, 4f			# if no carry, continue
1527	addu	t2, t2, 1			# add carry to result
1528	blt	t2, zero, overflow_w		# overflow?
15294:
1530	bne	v0, zero, 5f			# if rounded remainder is zero
1531	and	t2, t2, ~1			#  clear LSB (round to nearest)
15325:
1533	beq	t0, zero, 1f			# result positive?
1534	negu	t2				# convert to negative integer
15351:
1536	beq	t3, zero, result_fs_w		# is result exact?
1537/*
1538 * Handle inexact exception.
1539 */
1540inexact_w:
1541	or	a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
1542	and	v0, a1, MIPS_FPU_ENABLE_INEXACT
1543	bne	v0, zero, fpe_trap
1544	ctc1	a1, MIPS_FPU_CSR		# save exceptions
1545	b	result_fs_w
1546
1547/*
1548 * Conversions to integer which overflow will trap (if enabled),
1549 * or generate an inexact trap (if enabled),
1550 * or generate an invalid exception.
1551 */
1552overflow_w:
1553	or	a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
1554	and	v0, a1, MIPS_FPU_ENABLE_OVERFLOW
1555	bne	v0, zero, fpe_trap
1556	and	v0, a1, MIPS_FPU_ENABLE_INEXACT
1557	bne	v0, zero, inexact_w		# inexact traps enabled?
1558	b	invalid_w
1559
1560/*
1561 * Conversions to integer which underflow will trap (if enabled),
1562 * or generate an inexact trap (if enabled),
1563 * or generate an invalid exception.
1564 */
1565underflow_w:
1566	or	a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1567	and	v0, a1, MIPS_FPU_ENABLE_UNDERFLOW
1568	bne	v0, zero, fpe_trap
1569	and	v0, a1, MIPS_FPU_ENABLE_INEXACT
1570	bne	v0, zero, inexact_w		# inexact traps enabled?
1571	b	invalid_w
1572
1573/*
1574 * Compare single.
1575 */
1576cmp_s:
1577	jal	get_cmp_s
1578	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1579	bne	t2, zero, unordered		# FS is a NAN
15801:
1581	bne	ta1, SEXP_INF, 2f		# is FT an infinity?
1582	bne	ta2, zero, unordered		# FT is a NAN
15832:
1584	sll	t1, t1, 23			# reassemble exp & frac
1585	or	t1, t1, t2
1586	sll	ta1, ta1, 23			# reassemble exp & frac
1587	or	ta1, ta1, ta2
1588	beq	t0, zero, 1f			# is FS positive?
1589	negu	t1
15901:
1591	beq	ta0, zero, 1f			# is FT positive?
1592	negu	ta1
15931:
1594	li	v0, COND_LESS
1595	blt	t1, ta1, test_cond		# is FS < FT?
1596	li	v0, COND_EQUAL
1597	beq	t1, ta1, test_cond		# is FS == FT?
1598	move	v0, zero			# FS > FT
1599	b	test_cond
1600
1601/*
1602 * Compare double.
1603 */
1604cmp_d:
1605	jal	get_cmp_d
1606	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1607	bne	t2, zero, unordered
1608	bne	t3, zero, unordered		# FS is a NAN
16091:
1610	bne	ta1, DEXP_INF, 2f		# is FT an infinity?
1611	bne	ta2, zero, unordered
1612	bne	ta3, zero, unordered		# FT is a NAN
16132:
1614	sll	t1, t1, 20			# reassemble exp & frac
1615	or	t1, t1, t2
1616	sll	ta1, ta1, 20			# reassemble exp & frac
1617	or	ta1, ta1, ta2
1618	beq	t0, zero, 1f			# is FS positive?
1619	not	t3				# negate t1,t3
1620	not	t1
1621	addu	t3, t3, 1
1622	seq	v0, t3, zero			# compute carry
1623	addu	t1, t1, v0
16241:
1625	beq	ta0, zero, 1f			# is FT positive?
1626	not	ta3				# negate ta1,ta3
1627	not	ta1
1628	addu	ta3, ta3, 1
1629	seq	v0, ta3, zero			# compute carry
1630	addu	ta1, ta1, v0
16311:
1632	li	v0, COND_LESS
1633	blt	t1, ta1, test_cond		# is FS(MSW) < FT(MSW)?
1634	move	v0, zero
1635	bne	t1, ta1, test_cond		# is FS(MSW) > FT(MSW)?
1636	li	v0, COND_LESS
1637	bltu	t3, ta3, test_cond		# is FS(LSW) < FT(LSW)?
1638	li	v0, COND_EQUAL
1639	beq	t3, ta3, test_cond		# is FS(LSW) == FT(LSW)?
1640	move	v0, zero			# FS > FT
1641test_cond:
1642	and	v0, v0, a0			# condition match instruction?
1643set_cond:
1644	bne	v0, zero, 1f
1645	and	a1, a1, ~MIPS_FPU_COND_BIT	# clear condition bit
1646	b	2f
16471:
1648	or	a1, a1, MIPS_FPU_COND_BIT	# set condition bit
16492:
1650	ctc1	a1, MIPS_FPU_CSR		# save condition bit
1651	b	done
1652
1653unordered:
1654	and	v0, a0, COND_UNORDERED		# this cmp match unordered?
1655	bne	v0, zero, 1f
1656	and	a1, a1, ~MIPS_FPU_COND_BIT	# clear condition bit
1657	b	2f
16581:
1659	or	a1, a1, MIPS_FPU_COND_BIT	# set condition bit
16602:
1661	and	v0, a0, COND_SIGNAL
1662	beq	v0, zero, 1f			# is this a signaling cmp?
1663	or	a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
1664	and	v0, a1, MIPS_FPU_ENABLE_INVALID
1665	bne	v0, zero, fpe_trap
16661:
1667	ctc1	a1, MIPS_FPU_CSR		# save condition bit
1668	b	done
1669
1670/*
1671 * Determine the amount to shift the fraction in order to restore the
1672 * normalized position. After that, round and handle exceptions.
1673 */
1674norm_s:
1675	move	v0, t2
1676	move	t9, zero			# t9 = num of leading zeros
1677	bne	t2, zero, 1f
1678	move	v0, t8
1679	addu	t9, 32
16801:
1681	srl	v1, v0, 16
1682	bne	v1, zero, 1f
1683	addu	t9, 16
1684	sll	v0, 16
16851:
1686	srl	v1, v0, 24
1687	bne	v1, zero, 1f
1688	addu	t9, 8
1689	sll	v0, 8
16901:
1691	srl	v1, v0, 28
1692	bne	v1, zero, 1f
1693	addu	t9, 4
1694	sll	v0, 4
16951:
1696	srl	v1, v0, 30
1697	bne	v1, zero, 1f
1698	addu	t9, 2
1699	sll	v0, 2
17001:
1701	srl	v1, v0, 31
1702	bne	v1, zero, 1f
1703	addu	t9, 1
1704/*
1705 * Now shift t2,t8 the correct number of bits.
1706 */
17071:
1708	subu	t9, t9, SLEAD_ZEROS		# dont count leading zeros
1709	subu	t1, t1, t9			# adjust the exponent
1710	beq	t9, zero, norm_noshift_s
1711	li	v1, 32
1712	blt	t9, zero, 1f			# if shift < 0, shift right
1713	subu	v1, v1, t9
1714	sll	t2, t2, t9			# shift t2,t8 left
1715	srl	v0, t8, v1			# save bits shifted out
1716	or	t2, t2, v0
1717	sll	t8, t8, t9
1718	b	norm_noshift_s
17191:
1720	negu	t9				# shift t2,t8 right by t9
1721	subu	v1, v1, t9
1722	sll	v0, t8, v1			# save bits shifted out
1723	sltu	v0, zero, v0			# be sure to save any one bits
1724	srl	t8, t8, t9
1725	or	t8, t8, v0
1726	sll	v0, t2, v1			# save bits shifted out
1727	or	t8, t8, v0
1728	srl	t2, t2, t9
1729norm_noshift_s:
1730	move	ta1, t1				# save unrounded exponent
1731	move	ta2, t2				# save unrounded fraction
1732	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
1733	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
1734	beq	v0, MIPS_FPU_ROUND_RZ, 5f	# round to zero (truncate)
1735	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
1736	beq	t0, zero, 5f			# if sign is positive, truncate
1737	b	2f
17381:
1739	bne	t0, zero, 5f			# if sign is negative, truncate
17402:
1741	beq	t8, zero, 5f			# if exact, continue
1742	addu	t2, t2, 1			# add rounding bit
1743	bne	t2, SIMPL_ONE<<1, 5f		# need to adjust exponent?
1744	addu	t1, t1, 1			# adjust exponent
1745	srl	t2, t2, 1			# renormalize fraction
1746	b	5f
17473:
1748	li	v0, GUARDBIT			# load guard bit for rounding
1749	addu	v0, v0, t8			# add remainder
1750	sltu	v1, v0, t8			# compute carry out
1751	beq	v1, zero, 4f			# if no carry, continue
1752	addu	t2, t2, 1			# add carry to result
1753	bne	t2, SIMPL_ONE<<1, 4f		# need to adjust exponent?
1754	addu	t1, t1, 1			# adjust exponent
1755	srl	t2, t2, 1			# renormalize fraction
17564:
1757	bne	v0, zero, 5f			# if rounded remainder is zero
1758	and	t2, t2, ~1			#  clear LSB (round to nearest)
17595:
1760	bgt	t1, SEXP_MAX, overflow_s	# overflow?
1761	blt	t1, SEXP_MIN, underflow_s	# underflow?
1762	bne	t8, zero, inexact_s		# is result inexact?
1763	addu	t1, t1, SEXP_BIAS		# bias exponent
1764	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1765	b	result_fs_s
1766
1767/*
1768 * Handle inexact exception.
1769 */
1770inexact_s:
1771	addu	t1, t1, SEXP_BIAS		# bias exponent
1772	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1773inexact_nobias_s:
1774	jal	set_fd_s			# save result
1775	or	a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
1776	and	v0, a1, MIPS_FPU_ENABLE_INEXACT
1777	bne	v0, zero, fpe_trap
1778	ctc1	a1, MIPS_FPU_CSR		# save exceptions
1779	b	done
1780
1781/*
1782 * Overflow will trap (if enabled),
1783 * or generate an inexact trap (if enabled),
1784 * or generate an infinity.
1785 */
1786overflow_s:
1787	or	a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
1788	and	v0, a1, MIPS_FPU_ENABLE_OVERFLOW
1789	beq	v0, zero, 1f
1790	subu	t1, t1, 192			# bias exponent
1791	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1792	jal	set_fd_s			# save result
1793	b	fpe_trap
17941:
1795	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
1796	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
1797	beq	v0, MIPS_FPU_ROUND_RZ, 1f	# round to zero (truncate)
1798	beq	v0, MIPS_FPU_ROUND_RP, 2f	# round to +infinity
1799	bne	t0, zero, 3f
18001:
1801	li	t1, SEXP_MAX			# result is max finite
1802	li	t2, 0x007fffff
1803	b	inexact_s
18042:
1805	bne	t0, zero, 1b
18063:
1807	li	t1, SEXP_MAX + 1		# result is infinity
1808	move	t2, zero
1809	b	inexact_s
1810
1811/*
1812 * In this implementation, "tininess" is detected "after rounding" and
1813 * "loss of accuracy" is detected as "an inexact result".
1814 */
1815underflow_s:
1816	and	v0, a1, MIPS_FPU_ENABLE_UNDERFLOW
1817	beq	v0, zero, 1f
1818/*
1819 * Underflow is enabled so compute the result and trap.
1820 */
1821	addu	t1, t1, 192			# bias exponent
1822	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1823	jal	set_fd_s			# save result
1824	or	a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1825	b	fpe_trap
1826/*
1827 * Underflow is not enabled so compute the result,
1828 * signal inexact result (if it is) and trap (if enabled).
1829 */
18301:
1831	move	t1, ta1				# get unrounded exponent
1832	move	t2, ta2				# get unrounded fraction
1833	li	t9, SEXP_MIN			# compute shift amount
1834	subu	t9, t9, t1			# shift t2,t8 right by t9
1835	blt	t9, SFRAC_BITS+2, 3f		# shift all the bits out?
1836	move	t1, zero			# result is inexact zero
1837	move	t2, zero
1838	or	a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1839/*
1840 * Now round the zero result.
1841 * Only need to worry about rounding to +- infinity when the sign matches.
1842 */
1843	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
1844	beq	v0, MIPS_FPU_ROUND_RN, inexact_nobias_s # round to nearest
1845	beq	v0, MIPS_FPU_ROUND_RZ, inexact_nobias_s # round to zero
1846	beq	v0, MIPS_FPU_ROUND_RP, 1f		# round to +infinity
1847	beq	t0, zero, inexact_nobias_s	# if sign is positive, truncate
1848	b	2f
18491:
1850	bne	t0, zero, inexact_nobias_s	# if sign is negative, truncate
18512:
1852	addu	t2, t2, 1			# add rounding bit
1853	b	inexact_nobias_s
18543:
1855	li	v1, 32
1856	subu	v1, v1, t9
1857	sltu	v0, zero, t8			# be sure to save any one bits
1858	sll	t8, t2, v1			# save bits shifted out
1859	or	t8, t8, v0			# include sticky bits
1860	srl	t2, t2, t9
1861/*
1862 * Now round the denormalized result.
1863 */
1864	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
1865	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
1866	beq	v0, MIPS_FPU_ROUND_RZ, 5f	# round to zero (truncate)
1867	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
1868	beq	t0, zero, 5f			# if sign is positive, truncate
1869	b	2f
18701:
1871	bne	t0, zero, 5f			# if sign is negative, truncate
18722:
1873	beq	t8, zero, 5f			# if exact, continue
1874	addu	t2, t2, 1			# add rounding bit
1875	b	5f
18763:
1877	li	v0, GUARDBIT			# load guard bit for rounding
1878	addu	v0, v0, t8			# add remainder
1879	sltu	v1, v0, t8			# compute carry out
1880	beq	v1, zero, 4f			# if no carry, continue
1881	addu	t2, t2, 1			# add carry to result
18824:
1883	bne	v0, zero, 5f			# if rounded remainder is zero
1884	and	t2, t2, ~1			#  clear LSB (round to nearest)
18855:
1886	move	t1, zero			# denorm or zero exponent
1887	jal	set_fd_s			# save result
1888	beq	t8, zero, done			# check for exact result
1889	or	a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1890	or	a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
1891	and	v0, a1, MIPS_FPU_ENABLE_INEXACT
1892	bne	v0, zero, fpe_trap
1893	ctc1	a1, MIPS_FPU_CSR		# save exceptions
1894	b	done
1895
1896/*
1897 * Determine the amount to shift the fraction in order to restore the
1898 * normalized position. After that, round and handle exceptions.
1899 */
1900norm_d:
1901	move	v0, t2
1902	move	t9, zero			# t9 = num of leading zeros
1903	bne	t2, zero, 1f
1904	move	v0, t3
1905	addu	t9, 32
1906	bne	t3, zero, 1f
1907	move	v0, t8
1908	addu	t9, 32
19091:
1910	srl	v1, v0, 16
1911	bne	v1, zero, 1f
1912	addu	t9, 16
1913	sll	v0, 16
19141:
1915	srl	v1, v0, 24
1916	bne	v1, zero, 1f
1917	addu	t9, 8
1918	sll	v0, 8
19191:
1920	srl	v1, v0, 28
1921	bne	v1, zero, 1f
1922	addu	t9, 4
1923	sll	v0, 4
19241:
1925	srl	v1, v0, 30
1926	bne	v1, zero, 1f
1927	addu	t9, 2
1928	sll	v0, 2
19291:
1930	srl	v1, v0, 31
1931	bne	v1, zero, 1f
1932	addu	t9, 1
1933/*
1934 * Now shift t2,t3,t8 the correct number of bits.
1935 */
19361:
1937	subu	t9, t9, DLEAD_ZEROS		# dont count leading zeros
1938	subu	t1, t1, t9			# adjust the exponent
1939	beq	t9, zero, norm_noshift_d
1940	li	v1, 32
1941	blt	t9, zero, 2f			# if shift < 0, shift right
1942	blt	t9, v1, 1f			# shift by < 32?
1943	subu	t9, t9, v1			# shift by >= 32
1944	subu	v1, v1, t9
1945	sll	t2, t3, t9			# shift left by t9
1946	srl	v0, t8, v1			# save bits shifted out
1947	or	t2, t2, v0
1948	sll	t3, t8, t9
1949	move	t8, zero
1950	b	norm_noshift_d
19511:
1952	subu	v1, v1, t9
1953	sll	t2, t2, t9			# shift left by t9
1954	srl	v0, t3, v1			# save bits shifted out
1955	or	t2, t2, v0
1956	sll	t3, t3, t9
1957	srl	v0, t8, v1			# save bits shifted out
1958	or	t3, t3, v0
1959	sll	t8, t8, t9
1960	b	norm_noshift_d
19612:
1962	negu	t9				# shift right by t9
1963	subu	v1, v1, t9			#  (known to be < 32 bits)
1964	sll	v0, t8, v1			# save bits shifted out
1965	sltu	v0, zero, v0			# be sure to save any one bits
1966	srl	t8, t8, t9
1967	or	t8, t8, v0
1968	sll	v0, t3, v1			# save bits shifted out
1969	or	t8, t8, v0
1970	srl	t3, t3, t9
1971	sll	v0, t2, v1			# save bits shifted out
1972	or	t3, t3, v0
1973	srl	t2, t2, t9
1974norm_noshift_d:
1975	move	ta1, t1				# save unrounded exponent
1976	move	ta2, t2				# save unrounded fraction (MS)
1977	move	ta3, t3				# save unrounded fraction (LS)
1978	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
1979	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
1980	beq	v0, MIPS_FPU_ROUND_RZ, 5f	# round to zero (truncate)
1981	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
1982	beq	t0, zero, 5f			# if sign is positive, truncate
1983	b	2f
19841:
1985	bne	t0, zero, 5f			# if sign is negative, truncate
19862:
1987	beq	t8, zero, 5f			# if exact, continue
1988	addu	t3, t3, 1			# add rounding bit
1989	bne	t3, zero, 5f			# branch if no carry
1990	addu	t2, t2, 1			# add carry
1991	bne	t2, DIMPL_ONE<<1, 5f		# need to adjust exponent?
1992	addu	t1, t1, 1			# adjust exponent
1993	srl	t2, t2, 1			# renormalize fraction
1994	b	5f
19953:
1996	li	v0, GUARDBIT			# load guard bit for rounding
1997	addu	v0, v0, t8			# add remainder
1998	sltu	v1, v0, t8			# compute carry out
1999	beq	v1, zero, 4f			# branch if no carry
2000	addu	t3, t3, 1			# add carry
2001	bne	t3, zero, 4f			# branch if no carry
2002	addu	t2, t2, 1			# add carry to result
2003	bne	t2, DIMPL_ONE<<1, 4f		# need to adjust exponent?
2004	addu	t1, t1, 1			# adjust exponent
2005	srl	t2, t2, 1			# renormalize fraction
20064:
2007	bne	v0, zero, 5f			# if rounded remainder is zero
2008	and	t3, t3, ~1			#  clear LSB (round to nearest)
20095:
2010	bgt	t1, DEXP_MAX, overflow_d	# overflow?
2011	blt	t1, DEXP_MIN, underflow_d	# underflow?
2012	bne	t8, zero, inexact_d		# is result inexact?
2013	addu	t1, t1, DEXP_BIAS		# bias exponent
2014	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2015	b	result_fs_d
2016
2017/*
2018 * Handle inexact exception.
2019 */
2020inexact_d:
2021	addu	t1, t1, DEXP_BIAS		# bias exponent
2022	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2023inexact_nobias_d:
2024	jal	set_fd_d			# save result
2025	or	a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
2026	and	v0, a1, MIPS_FPU_ENABLE_INEXACT
2027	bne	v0, zero, fpe_trap
2028	ctc1	a1, MIPS_FPU_CSR		# save exceptions
2029	b	done
2030
2031/*
2032 * Overflow will trap (if enabled),
2033 * or generate an inexact trap (if enabled),
2034 * or generate an infinity.
2035 */
2036overflow_d:
2037	or	a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
2038	and	v0, a1, MIPS_FPU_ENABLE_OVERFLOW
2039	beq	v0, zero, 1f
2040	subu	t1, t1, 1536			# bias exponent
2041	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2042	jal	set_fd_d			# save result
2043	b	fpe_trap
20441:
2045	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
2046	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
2047	beq	v0, MIPS_FPU_ROUND_RZ, 1f	# round to zero (truncate)
2048	beq	v0, MIPS_FPU_ROUND_RP, 2f	# round to +infinity
2049	bne	t0, zero, 3f
20501:
2051	li	t1, DEXP_MAX			# result is max finite
2052	li	t2, 0x000fffff
2053	li	t3, 0xffffffff
2054	b	inexact_d
20552:
2056	bne	t0, zero, 1b
20573:
2058	li	t1, DEXP_MAX + 1		# result is infinity
2059	move	t2, zero
2060	move	t3, zero
2061	b	inexact_d
2062
2063/*
2064 * In this implementation, "tininess" is detected "after rounding" and
2065 * "loss of accuracy" is detected as "an inexact result".
2066 */
2067underflow_d:
2068	and	v0, a1, MIPS_FPU_ENABLE_UNDERFLOW
2069	beq	v0, zero, 1f
2070/*
2071 * Underflow is enabled so compute the result and trap.
2072 */
2073	addu	t1, t1, 1536			# bias exponent
2074	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2075	jal	set_fd_d			# save result
2076	or	a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2077	b	fpe_trap
2078/*
2079 * Underflow is not enabled so compute the result,
2080 * signal inexact result (if it is) and trap (if enabled).
2081 */
20821:
2083	move	t1, ta1				# get unrounded exponent
2084	move	t2, ta2				# get unrounded fraction (MS)
2085	move	t3, ta3				# get unrounded fraction (LS)
2086	li	t9, DEXP_MIN			# compute shift amount
2087	subu	t9, t9, t1			# shift t2,t8 right by t9
2088	blt	t9, DFRAC_BITS+2, 3f		# shift all the bits out?
2089	move	t1, zero			# result is inexact zero
2090	move	t2, zero
2091	move	t3, zero
2092	or	a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2093/*
2094 * Now round the zero result.
2095 * Only need to worry about rounding to +- infinity when the sign matches.
2096 */
2097	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
2098	beq	v0, MIPS_FPU_ROUND_RN, inexact_nobias_d  # round to nearest
2099	beq	v0, MIPS_FPU_ROUND_RZ, inexact_nobias_d  # round to zero
2100	beq	v0, MIPS_FPU_ROUND_RP, 1f		# round to +infinity
2101	beq	t0, zero, inexact_nobias_d	# if sign is positive, truncate
2102	b	2f
21031:
2104	bne	t0, zero, inexact_nobias_d	# if sign is negative, truncate
21052:
2106	addu	t3, t3, 1			# add rounding bit
2107	b	inexact_nobias_d
21083:
2109	li	v1, 32
2110	blt	t9, v1, 1f			# shift by < 32?
2111	subu	t9, t9, v1			# shift right by >= 32
2112	subu	v1, v1, t9
2113	sltu	v0, zero, t8			# be sure to save any one bits
2114	sll	t8, t2, v1			# save bits shifted out
2115	or	t8, t8, v0			# include sticky bits
2116	srl	t3, t2, t9
2117	move	t2, zero
2118	b	2f
21191:
2120	subu	v1, v1, t9			# shift right by t9
2121	sltu	v0, zero, t8			# be sure to save any one bits
2122	sll	t8, t3, v1			# save bits shifted out
2123	or	t8, t8, v0			# include sticky bits
2124	srl	t3, t3, t9
2125	sll	v0, t2, v1			# save bits shifted out
2126	or	t3, t3, v0
2127	srl	t2, t2, t9
2128/*
2129 * Now round the denormalized result.
2130 */
21312:
2132	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
2133	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
2134	beq	v0, MIPS_FPU_ROUND_RZ, 5f	# round to zero (truncate)
2135	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
2136	beq	t0, zero, 5f			# if sign is positive, truncate
2137	b	2f
21381:
2139	bne	t0, zero, 5f			# if sign is negative, truncate
21402:
2141	beq	t8, zero, 5f			# if exact, continue
2142	addu	t3, t3, 1			# add rounding bit
2143	bne	t3, zero, 5f			# if no carry, continue
2144	addu	t2, t2, 1			# add carry
2145	b	5f
21463:
2147	li	v0, GUARDBIT			# load guard bit for rounding
2148	addu	v0, v0, t8			# add remainder
2149	sltu	v1, v0, t8			# compute carry out
2150	beq	v1, zero, 4f			# if no carry, continue
2151	addu	t3, t3, 1			# add rounding bit
2152	bne	t3, zero, 4f			# if no carry, continue
2153	addu	t2, t2, 1			# add carry
21544:
2155	bne	v0, zero, 5f			# if rounded remainder is zero
2156	and	t3, t3, ~1			#  clear LSB (round to nearest)
21575:
2158	move	t1, zero			# denorm or zero exponent
2159	jal	set_fd_d			# save result
2160	beq	t8, zero, done			# check for exact result
2161	or	a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2162	or	a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
2163	and	v0, a1, MIPS_FPU_ENABLE_INEXACT
2164	bne	v0, zero, fpe_trap
2165	ctc1	a1, MIPS_FPU_CSR		# save exceptions
2166	b	done
2167
2168/*
2169 * Signal an invalid operation if the trap is enabled; otherwise,
2170 * the result is a quiet NAN.
2171 */
2172invalid_s:					# trap invalid operation
2173	or	a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
2174	and	v0, a1, MIPS_FPU_ENABLE_INVALID
2175	bne	v0, zero, fpe_trap
2176	ctc1	a1, MIPS_FPU_CSR		# save exceptions
2177	move	t0, zero			# result is a quiet NAN
2178	li	t1, SEXP_INF
2179	li	t2, SQUIET_NAN
2180	jal	set_fd_s			# save result (in t0,t1,t2)
2181	b	done
2182
2183/*
2184 * Signal an invalid operation if the trap is enabled; otherwise,
2185 * the result is a quiet NAN.
2186 */
2187invalid_d:					# trap invalid operation
2188	or	a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
2189	and	v0, a1, MIPS_FPU_ENABLE_INVALID
2190	bne	v0, zero, fpe_trap
2191	ctc1	a1, MIPS_FPU_CSR		# save exceptions
2192	move	t0, zero			# result is a quiet NAN
2193	li	t1, DEXP_INF
2194	li	t2, DQUIET_NAN0
2195	li	t3, DQUIET_NAN1
2196	jal	set_fd_d			# save result (in t0,t1,t2,t3)
2197	b	done
2198
2199/*
2200 * Signal an invalid operation if the trap is enabled; otherwise,
2201 * the result is INT_MAX or INT_MIN.
2202 */
2203invalid_w:					# trap invalid operation
2204	or	a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
2205	and	v0, a1, MIPS_FPU_ENABLE_INVALID
2206	bne	v0, zero, fpe_trap
2207	ctc1	a1, MIPS_FPU_CSR		# save exceptions
2208	bne	t0, zero, 1f
2209	li	t2, INT_MAX			# result is INT_MAX
2210	b	result_fs_w
22111:
2212	li	t2, INT_MIN			# result is INT_MIN
2213	b	result_fs_w
2214
2215/*
2216 * Trap if the hardware should have handled this case.
2217 */
2218fpe_trap:
2219	move	a2, a1				# code = FP CSR
2220	ctc1	a1, MIPS_FPU_CSR		# save exceptions
2221	break	0
2222
2223/*
2224 * Send an illegal instruction signal to the current process.
2225 */
2226ill:
2227	ctc1	a1, MIPS_FPU_CSR		# save exceptions
2228	move	a2, a0				# code = FP instruction
2229	break	0
2230
2231result_ft_s:
2232	move	t0, ta0				# result is FT
2233	move	t1, ta1
2234	move	t2, ta2
2235result_fs_s:					# result is FS
2236	jal	set_fd_s			# save result (in t0,t1,t2)
2237	b	done
2238
2239result_fs_w:
2240	jal	set_fd_word			# save result (in t2)
2241	b	done
2242
2243result_ft_d:
2244	move	t0, ta0				# result is FT
2245	move	t1, ta1
2246	move	t2, ta2
2247	move	t3, ta3
2248result_fs_d:					# result is FS
2249	jal	set_fd_d			# save result (in t0,t1,t2,t3)
2250
2251done:
2252	lw	ra, CALLFRAME_RA(sp)
2253	addu	sp, sp, CALLFRAME_SIZ
2254	j	ra
2255END(MipsEmulateFP)
2256
2257/*----------------------------------------------------------------------------
2258 * get_fs_int --
2259 *
2260 *	Read (integer) the FS register (bits 15-11).
2261 *	This is an internal routine used by MipsEmulateFP only.
2262 *
2263 * Results:
2264 *	t0	contains the sign
2265 *	t2	contains the fraction
2266 *
2267 *----------------------------------------------------------------------------
2268 */
2269LEAF(get_fs_int)
2270	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2271	and	a3, a3, 0xF << 2		# mask FS field
2272	lw	a3, get_fs_int_tbl(a3)		# switch on register number
2273	j	a3
2274
2275	.rdata
2276get_fs_int_tbl:
2277	.word	get_fs_int_f0
2278	.word	get_fs_int_f2
2279	.word	get_fs_int_f4
2280	.word	get_fs_int_f6
2281	.word	get_fs_int_f8
2282	.word	get_fs_int_f10
2283	.word	get_fs_int_f12
2284	.word	get_fs_int_f14
2285	.word	get_fs_int_f16
2286	.word	get_fs_int_f18
2287	.word	get_fs_int_f20
2288	.word	get_fs_int_f22
2289	.word	get_fs_int_f24
2290	.word	get_fs_int_f26
2291	.word	get_fs_int_f28
2292	.word	get_fs_int_f30
2293	.text
2294
2295get_fs_int_f0:
2296	mfc1	t2, $f0
2297	b	get_fs_int_done
2298get_fs_int_f2:
2299	mfc1	t2, $f2
2300	b	get_fs_int_done
2301get_fs_int_f4:
2302	mfc1	t2, $f4
2303	b	get_fs_int_done
2304get_fs_int_f6:
2305	mfc1	t2, $f6
2306	b	get_fs_int_done
2307get_fs_int_f8:
2308	mfc1	t2, $f8
2309	b	get_fs_int_done
2310get_fs_int_f10:
2311	mfc1	t2, $f10
2312	b	get_fs_int_done
2313get_fs_int_f12:
2314	mfc1	t2, $f12
2315	b	get_fs_int_done
2316get_fs_int_f14:
2317	mfc1	t2, $f14
2318	b	get_fs_int_done
2319get_fs_int_f16:
2320	mfc1	t2, $f16
2321	b	get_fs_int_done
2322get_fs_int_f18:
2323	mfc1	t2, $f18
2324	b	get_fs_int_done
2325get_fs_int_f20:
2326	mfc1	t2, $f20
2327	b	get_fs_int_done
2328get_fs_int_f22:
2329	mfc1	t2, $f22
2330	b	get_fs_int_done
2331get_fs_int_f24:
2332	mfc1	t2, $f24
2333	b	get_fs_int_done
2334get_fs_int_f26:
2335	mfc1	t2, $f26
2336	b	get_fs_int_done
2337get_fs_int_f28:
2338	mfc1	t2, $f28
2339	b	get_fs_int_done
2340get_fs_int_f30:
2341	mfc1	t2, $f30
2342get_fs_int_done:
2343	srl	t0, t2, 31			# init the sign bit
2344	bge	t2, zero, 1f
2345	negu	t2
23461:
2347	j	ra
2348END(get_fs_int)
2349
2350/*----------------------------------------------------------------------------
2351 * get_ft_fs_s --
2352 *
2353 *	Read (single precision) the FT register (bits 20-16) and
2354 *	the FS register (bits 15-11) and break up into fields.
2355 *	This is an internal routine used by MipsEmulateFP only.
2356 *
2357 * Results:
2358 *	t0	contains the FS sign
2359 *	t1	contains the FS (biased) exponent
2360 *	t2	contains the FS fraction
2361 *	ta0	contains the FT sign
2362 *	ta1	contains the FT (biased) exponent
2363 *	ta2	contains the FT fraction
2364 *
2365 *----------------------------------------------------------------------------
2366 */
2367LEAF(get_ft_fs_s)
2368	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2369	and	a3, a3, 0xF << 2		# mask FT field
2370	lw	a3, get_ft_s_tbl(a3)		# switch on register number
2371	j	a3
2372
2373	.rdata
2374get_ft_s_tbl:
2375	.word	get_ft_s_f0
2376	.word	get_ft_s_f2
2377	.word	get_ft_s_f4
2378	.word	get_ft_s_f6
2379	.word	get_ft_s_f8
2380	.word	get_ft_s_f10
2381	.word	get_ft_s_f12
2382	.word	get_ft_s_f14
2383	.word	get_ft_s_f16
2384	.word	get_ft_s_f18
2385	.word	get_ft_s_f20
2386	.word	get_ft_s_f22
2387	.word	get_ft_s_f24
2388	.word	get_ft_s_f26
2389	.word	get_ft_s_f28
2390	.word	get_ft_s_f30
2391	.text
2392
2393get_ft_s_f0:
2394	mfc1	ta0, $f0
2395	b	get_ft_s_done
2396get_ft_s_f2:
2397	mfc1	ta0, $f2
2398	b	get_ft_s_done
2399get_ft_s_f4:
2400	mfc1	ta0, $f4
2401	b	get_ft_s_done
2402get_ft_s_f6:
2403	mfc1	ta0, $f6
2404	b	get_ft_s_done
2405get_ft_s_f8:
2406	mfc1	ta0, $f8
2407	b	get_ft_s_done
2408get_ft_s_f10:
2409	mfc1	ta0, $f10
2410	b	get_ft_s_done
2411get_ft_s_f12:
2412	mfc1	ta0, $f12
2413	b	get_ft_s_done
2414get_ft_s_f14:
2415	mfc1	ta0, $f14
2416	b	get_ft_s_done
2417get_ft_s_f16:
2418	mfc1	ta0, $f16
2419	b	get_ft_s_done
2420get_ft_s_f18:
2421	mfc1	ta0, $f18
2422	b	get_ft_s_done
2423get_ft_s_f20:
2424	mfc1	ta0, $f20
2425	b	get_ft_s_done
2426get_ft_s_f22:
2427	mfc1	ta0, $f22
2428	b	get_ft_s_done
2429get_ft_s_f24:
2430	mfc1	ta0, $f24
2431	b	get_ft_s_done
2432get_ft_s_f26:
2433	mfc1	ta0, $f26
2434	b	get_ft_s_done
2435get_ft_s_f28:
2436	mfc1	ta0, $f28
2437	b	get_ft_s_done
2438get_ft_s_f30:
2439	mfc1	ta0, $f30
2440get_ft_s_done:
2441	srl	ta1, ta0, 23			# get exponent
2442	and	ta1, ta1, 0xFF
2443	and	ta2, ta0, 0x7FFFFF		# get fraction
2444	srl	ta0, ta0, 31			# get sign
2445	bne	ta1, SEXP_INF, 1f		# is it a signaling NAN?
2446	and	v0, ta2, SSIGNAL_NAN
2447	bne	v0, zero, invalid_s
24481:
2449	/* fall through to get FS */
2450
2451/*----------------------------------------------------------------------------
2452 * get_fs_s --
2453 *
2454 *	Read (single precision) the FS register (bits 15-11) and
2455 *	break up into fields.
2456 *	This is an internal routine used by MipsEmulateFP only.
2457 *
2458 * Results:
2459 *	t0	contains the sign
2460 *	t1	contains the (biased) exponent
2461 *	t2	contains the fraction
2462 *
2463 *----------------------------------------------------------------------------
2464 */
2465XLEAF(get_fs_s)
2466	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2467	and	a3, a3, 0xF << 2		# mask FS field
2468	lw	a3, get_fs_s_tbl(a3)		# switch on register number
2469	j	a3
2470
2471	.rdata
2472get_fs_s_tbl:
2473	.word	get_fs_s_f0
2474	.word	get_fs_s_f2
2475	.word	get_fs_s_f4
2476	.word	get_fs_s_f6
2477	.word	get_fs_s_f8
2478	.word	get_fs_s_f10
2479	.word	get_fs_s_f12
2480	.word	get_fs_s_f14
2481	.word	get_fs_s_f16
2482	.word	get_fs_s_f18
2483	.word	get_fs_s_f20
2484	.word	get_fs_s_f22
2485	.word	get_fs_s_f24
2486	.word	get_fs_s_f26
2487	.word	get_fs_s_f28
2488	.word	get_fs_s_f30
2489	.text
2490
2491get_fs_s_f0:
2492	mfc1	t0, $f0
2493	b	get_fs_s_done
2494get_fs_s_f2:
2495	mfc1	t0, $f2
2496	b	get_fs_s_done
2497get_fs_s_f4:
2498	mfc1	t0, $f4
2499	b	get_fs_s_done
2500get_fs_s_f6:
2501	mfc1	t0, $f6
2502	b	get_fs_s_done
2503get_fs_s_f8:
2504	mfc1	t0, $f8
2505	b	get_fs_s_done
2506get_fs_s_f10:
2507	mfc1	t0, $f10
2508	b	get_fs_s_done
2509get_fs_s_f12:
2510	mfc1	t0, $f12
2511	b	get_fs_s_done
2512get_fs_s_f14:
2513	mfc1	t0, $f14
2514	b	get_fs_s_done
2515get_fs_s_f16:
2516	mfc1	t0, $f16
2517	b	get_fs_s_done
2518get_fs_s_f18:
2519	mfc1	t0, $f18
2520	b	get_fs_s_done
2521get_fs_s_f20:
2522	mfc1	t0, $f20
2523	b	get_fs_s_done
2524get_fs_s_f22:
2525	mfc1	t0, $f22
2526	b	get_fs_s_done
2527get_fs_s_f24:
2528	mfc1	t0, $f24
2529	b	get_fs_s_done
2530get_fs_s_f26:
2531	mfc1	t0, $f26
2532	b	get_fs_s_done
2533get_fs_s_f28:
2534	mfc1	t0, $f28
2535	b	get_fs_s_done
2536get_fs_s_f30:
2537	mfc1	t0, $f30
2538get_fs_s_done:
2539	srl	t1, t0, 23			# get exponent
2540	and	t1, t1, 0xFF
2541	and	t2, t0, 0x7FFFFF		# get fraction
2542	srl	t0, t0, 31			# get sign
2543	bne	t1, SEXP_INF, 1f		# is it a signaling NAN?
2544	and	v0, t2, SSIGNAL_NAN
2545	bne	v0, zero, invalid_s
25461:
2547	j	ra
2548END(get_ft_fs_s)
2549
2550/*----------------------------------------------------------------------------
2551 * get_ft_fs_d --
2552 *
2553 *	Read (double precision) the FT register (bits 20-16) and
2554 *	the FS register (bits 15-11) and break up into fields.
2555 *	This is an internal routine used by MipsEmulateFP only.
2556 *
2557 * Results:
2558 *	t0	contains the FS sign
2559 *	t1	contains the FS (biased) exponent
2560 *	t2	contains the FS fraction
2561 *	t3	contains the FS remaining fraction
2562 *	ta0	contains the FT sign
2563 *	ta1	contains the FT (biased) exponent
2564 *	ta2	contains the FT fraction
2565 *	ta3	contains the FT remaining fraction
2566 *
2567 *----------------------------------------------------------------------------
2568 */
2569LEAF(get_ft_fs_d)
2570	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2571	and	a3, a3, 0xF << 2		# mask FT field
2572	lw	a3, get_ft_d_tbl(a3)		# switch on register number
2573	j	a3
2574
2575	.rdata
2576get_ft_d_tbl:
2577	.word	get_ft_d_f0
2578	.word	get_ft_d_f2
2579	.word	get_ft_d_f4
2580	.word	get_ft_d_f6
2581	.word	get_ft_d_f8
2582	.word	get_ft_d_f10
2583	.word	get_ft_d_f12
2584	.word	get_ft_d_f14
2585	.word	get_ft_d_f16
2586	.word	get_ft_d_f18
2587	.word	get_ft_d_f20
2588	.word	get_ft_d_f22
2589	.word	get_ft_d_f24
2590	.word	get_ft_d_f26
2591	.word	get_ft_d_f28
2592	.word	get_ft_d_f30
2593	.text
2594
2595get_ft_d_f0:
2596	mfc1	ta3, $f0
2597	mfc1	ta0, $f1
2598	b	get_ft_d_done
2599get_ft_d_f2:
2600	mfc1	ta3, $f2
2601	mfc1	ta0, $f3
2602	b	get_ft_d_done
2603get_ft_d_f4:
2604	mfc1	ta3, $f4
2605	mfc1	ta0, $f5
2606	b	get_ft_d_done
2607get_ft_d_f6:
2608	mfc1	ta3, $f6
2609	mfc1	ta0, $f7
2610	b	get_ft_d_done
2611get_ft_d_f8:
2612	mfc1	ta3, $f8
2613	mfc1	ta0, $f9
2614	b	get_ft_d_done
2615get_ft_d_f10:
2616	mfc1	ta3, $f10
2617	mfc1	ta0, $f11
2618	b	get_ft_d_done
2619get_ft_d_f12:
2620	mfc1	ta3, $f12
2621	mfc1	ta0, $f13
2622	b	get_ft_d_done
2623get_ft_d_f14:
2624	mfc1	ta3, $f14
2625	mfc1	ta0, $f15
2626	b	get_ft_d_done
2627get_ft_d_f16:
2628	mfc1	ta3, $f16
2629	mfc1	ta0, $f17
2630	b	get_ft_d_done
2631get_ft_d_f18:
2632	mfc1	ta3, $f18
2633	mfc1	ta0, $f19
2634	b	get_ft_d_done
2635get_ft_d_f20:
2636	mfc1	ta3, $f20
2637	mfc1	ta0, $f21
2638	b	get_ft_d_done
2639get_ft_d_f22:
2640	mfc1	ta3, $f22
2641	mfc1	ta0, $f23
2642	b	get_ft_d_done
2643get_ft_d_f24:
2644	mfc1	ta3, $f24
2645	mfc1	ta0, $f25
2646	b	get_ft_d_done
2647get_ft_d_f26:
2648	mfc1	ta3, $f26
2649	mfc1	ta0, $f27
2650	b	get_ft_d_done
2651get_ft_d_f28:
2652	mfc1	ta3, $f28
2653	mfc1	ta0, $f29
2654	b	get_ft_d_done
2655get_ft_d_f30:
2656	mfc1	ta3, $f30
2657	mfc1	ta0, $f31
2658get_ft_d_done:
2659	srl	ta1, ta0, 20			# get exponent
2660	and	ta1, ta1, 0x7FF
2661	and	ta2, ta0, 0xFFFFF		# get fraction
2662	srl	ta0, ta0, 31			# get sign
2663	bne	ta1, DEXP_INF, 1f		# is it a signaling NAN?
2664	and	v0, ta2, DSIGNAL_NAN
2665	bne	v0, zero, invalid_d
26661:
2667	/* fall through to get FS */
2668
2669/*----------------------------------------------------------------------------
2670 * get_fs_d --
2671 *
2672 *	Read (double precision) the FS register (bits 15-11) and
2673 *	break up into fields.
2674 *	This is an internal routine used by MipsEmulateFP only.
2675 *
2676 * Results:
2677 *	t0	contains the sign
2678 *	t1	contains the (biased) exponent
2679 *	t2	contains the fraction
2680 *	t3	contains the remaining fraction
2681 *
2682 *----------------------------------------------------------------------------
2683 */
2684XLEAF(get_fs_d)
2685	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2686	and	a3, a3, 0xF << 2		# mask FS field
2687	lw	a3, get_fs_d_tbl(a3)		# switch on register number
2688	j	a3
2689
2690	.rdata
2691get_fs_d_tbl:
2692	.word	get_fs_d_f0
2693	.word	get_fs_d_f2
2694	.word	get_fs_d_f4
2695	.word	get_fs_d_f6
2696	.word	get_fs_d_f8
2697	.word	get_fs_d_f10
2698	.word	get_fs_d_f12
2699	.word	get_fs_d_f14
2700	.word	get_fs_d_f16
2701	.word	get_fs_d_f18
2702	.word	get_fs_d_f20
2703	.word	get_fs_d_f22
2704	.word	get_fs_d_f24
2705	.word	get_fs_d_f26
2706	.word	get_fs_d_f28
2707	.word	get_fs_d_f30
2708	.text
2709
2710get_fs_d_f0:
2711	mfc1	t3, $f0
2712	mfc1	t0, $f1
2713	b	get_fs_d_done
2714get_fs_d_f2:
2715	mfc1	t3, $f2
2716	mfc1	t0, $f3
2717	b	get_fs_d_done
2718get_fs_d_f4:
2719	mfc1	t3, $f4
2720	mfc1	t0, $f5
2721	b	get_fs_d_done
2722get_fs_d_f6:
2723	mfc1	t3, $f6
2724	mfc1	t0, $f7
2725	b	get_fs_d_done
2726get_fs_d_f8:
2727	mfc1	t3, $f8
2728	mfc1	t0, $f9
2729	b	get_fs_d_done
2730get_fs_d_f10:
2731	mfc1	t3, $f10
2732	mfc1	t0, $f11
2733	b	get_fs_d_done
2734get_fs_d_f12:
2735	mfc1	t3, $f12
2736	mfc1	t0, $f13
2737	b	get_fs_d_done
2738get_fs_d_f14:
2739	mfc1	t3, $f14
2740	mfc1	t0, $f15
2741	b	get_fs_d_done
2742get_fs_d_f16:
2743	mfc1	t3, $f16
2744	mfc1	t0, $f17
2745	b	get_fs_d_done
2746get_fs_d_f18:
2747	mfc1	t3, $f18
2748	mfc1	t0, $f19
2749	b	get_fs_d_done
2750get_fs_d_f20:
2751	mfc1	t3, $f20
2752	mfc1	t0, $f21
2753	b	get_fs_d_done
2754get_fs_d_f22:
2755	mfc1	t3, $f22
2756	mfc1	t0, $f23
2757	b	get_fs_d_done
2758get_fs_d_f24:
2759	mfc1	t3, $f24
2760	mfc1	t0, $f25
2761	b	get_fs_d_done
2762get_fs_d_f26:
2763	mfc1	t3, $f26
2764	mfc1	t0, $f27
2765	b	get_fs_d_done
2766get_fs_d_f28:
2767	mfc1	t3, $f28
2768	mfc1	t0, $f29
2769	b	get_fs_d_done
2770get_fs_d_f30:
2771	mfc1	t3, $f30
2772	mfc1	t0, $f31
2773get_fs_d_done:
2774	srl	t1, t0, 20			# get exponent
2775	and	t1, t1, 0x7FF
2776	and	t2, t0, 0xFFFFF			# get fraction
2777	srl	t0, t0, 31			# get sign
2778	bne	t1, DEXP_INF, 1f		# is it a signaling NAN?
2779	and	v0, t2, DSIGNAL_NAN
2780	bne	v0, zero, invalid_d
27811:
2782	j	ra
2783END(get_ft_fs_d)
2784
2785/*----------------------------------------------------------------------------
2786 * get_cmp_s --
2787 *
2788 *	Read (single precision) the FS register (bits 15-11) and
2789 *	the FT register (bits 20-16) and break up into fields.
2790 *	This is an internal routine used by MipsEmulateFP only.
2791 *
2792 * Results:
2793 *	t0	contains the sign
2794 *	t1	contains the (biased) exponent
2795 *	t2	contains the fraction
2796 *	ta0	contains the sign
2797 *	ta1	contains the (biased) exponent
2798 *	ta2	contains the fraction
2799 *
2800 *----------------------------------------------------------------------------
2801 */
2802LEAF(get_cmp_s)
2803	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2804	and	a3, a3, 0xF << 2		# mask FS field
2805	lw	a3, cmp_fs_s_tbl(a3)		# switch on register number
2806	j	a3
2807
2808	.rdata
2809cmp_fs_s_tbl:
2810	.word	cmp_fs_s_f0
2811	.word	cmp_fs_s_f2
2812	.word	cmp_fs_s_f4
2813	.word	cmp_fs_s_f6
2814	.word	cmp_fs_s_f8
2815	.word	cmp_fs_s_f10
2816	.word	cmp_fs_s_f12
2817	.word	cmp_fs_s_f14
2818	.word	cmp_fs_s_f16
2819	.word	cmp_fs_s_f18
2820	.word	cmp_fs_s_f20
2821	.word	cmp_fs_s_f22
2822	.word	cmp_fs_s_f24
2823	.word	cmp_fs_s_f26
2824	.word	cmp_fs_s_f28
2825	.word	cmp_fs_s_f30
2826	.text
2827
2828cmp_fs_s_f0:
2829	mfc1	t0, $f0
2830	b	cmp_fs_s_done
2831cmp_fs_s_f2:
2832	mfc1	t0, $f2
2833	b	cmp_fs_s_done
2834cmp_fs_s_f4:
2835	mfc1	t0, $f4
2836	b	cmp_fs_s_done
2837cmp_fs_s_f6:
2838	mfc1	t0, $f6
2839	b	cmp_fs_s_done
2840cmp_fs_s_f8:
2841	mfc1	t0, $f8
2842	b	cmp_fs_s_done
2843cmp_fs_s_f10:
2844	mfc1	t0, $f10
2845	b	cmp_fs_s_done
2846cmp_fs_s_f12:
2847	mfc1	t0, $f12
2848	b	cmp_fs_s_done
2849cmp_fs_s_f14:
2850	mfc1	t0, $f14
2851	b	cmp_fs_s_done
2852cmp_fs_s_f16:
2853	mfc1	t0, $f16
2854	b	cmp_fs_s_done
2855cmp_fs_s_f18:
2856	mfc1	t0, $f18
2857	b	cmp_fs_s_done
2858cmp_fs_s_f20:
2859	mfc1	t0, $f20
2860	b	cmp_fs_s_done
2861cmp_fs_s_f22:
2862	mfc1	t0, $f22
2863	b	cmp_fs_s_done
2864cmp_fs_s_f24:
2865	mfc1	t0, $f24
2866	b	cmp_fs_s_done
2867cmp_fs_s_f26:
2868	mfc1	t0, $f26
2869	b	cmp_fs_s_done
2870cmp_fs_s_f28:
2871	mfc1	t0, $f28
2872	b	cmp_fs_s_done
2873cmp_fs_s_f30:
2874	mfc1	t0, $f30
2875cmp_fs_s_done:
2876	srl	t1, t0, 23			# get exponent
2877	and	t1, t1, 0xFF
2878	and	t2, t0, 0x7FFFFF		# get fraction
2879	srl	t0, t0, 31			# get sign
2880
2881	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2882	and	a3, a3, 0xF << 2		# mask FT field
2883	lw	a3, cmp_ft_s_tbl(a3)		# switch on register number
2884	j	a3
2885
2886	.rdata
2887cmp_ft_s_tbl:
2888	.word	cmp_ft_s_f0
2889	.word	cmp_ft_s_f2
2890	.word	cmp_ft_s_f4
2891	.word	cmp_ft_s_f6
2892	.word	cmp_ft_s_f8
2893	.word	cmp_ft_s_f10
2894	.word	cmp_ft_s_f12
2895	.word	cmp_ft_s_f14
2896	.word	cmp_ft_s_f16
2897	.word	cmp_ft_s_f18
2898	.word	cmp_ft_s_f20
2899	.word	cmp_ft_s_f22
2900	.word	cmp_ft_s_f24
2901	.word	cmp_ft_s_f26
2902	.word	cmp_ft_s_f28
2903	.word	cmp_ft_s_f30
2904	.text
2905
2906cmp_ft_s_f0:
2907	mfc1	ta0, $f0
2908	b	cmp_ft_s_done
2909cmp_ft_s_f2:
2910	mfc1	ta0, $f2
2911	b	cmp_ft_s_done
2912cmp_ft_s_f4:
2913	mfc1	ta0, $f4
2914	b	cmp_ft_s_done
2915cmp_ft_s_f6:
2916	mfc1	ta0, $f6
2917	b	cmp_ft_s_done
2918cmp_ft_s_f8:
2919	mfc1	ta0, $f8
2920	b	cmp_ft_s_done
2921cmp_ft_s_f10:
2922	mfc1	ta0, $f10
2923	b	cmp_ft_s_done
2924cmp_ft_s_f12:
2925	mfc1	ta0, $f12
2926	b	cmp_ft_s_done
2927cmp_ft_s_f14:
2928	mfc1	ta0, $f14
2929	b	cmp_ft_s_done
2930cmp_ft_s_f16:
2931	mfc1	ta0, $f16
2932	b	cmp_ft_s_done
2933cmp_ft_s_f18:
2934	mfc1	ta0, $f18
2935	b	cmp_ft_s_done
2936cmp_ft_s_f20:
2937	mfc1	ta0, $f20
2938	b	cmp_ft_s_done
2939cmp_ft_s_f22:
2940	mfc1	ta0, $f22
2941	b	cmp_ft_s_done
2942cmp_ft_s_f24:
2943	mfc1	ta0, $f24
2944	b	cmp_ft_s_done
2945cmp_ft_s_f26:
2946	mfc1	ta0, $f26
2947	b	cmp_ft_s_done
2948cmp_ft_s_f28:
2949	mfc1	ta0, $f28
2950	b	cmp_ft_s_done
2951cmp_ft_s_f30:
2952	mfc1	ta0, $f30
2953cmp_ft_s_done:
2954	srl	ta1, ta0, 23			# get exponent
2955	and	ta1, ta1, 0xFF
2956	and	ta2, ta0, 0x7FFFFF		# get fraction
2957	srl	ta0, ta0, 31			# get sign
2958	j	ra
2959END(get_cmp_s)
2960
2961/*----------------------------------------------------------------------------
2962 * get_cmp_d --
2963 *
2964 *	Read (double precision) the FS register (bits 15-11) and
2965 *	the FT register (bits 20-16) and break up into fields.
2966 *	This is an internal routine used by MipsEmulateFP only.
2967 *
2968 * Results:
2969 *	t0	contains the sign
2970 *	t1	contains the (biased) exponent
2971 *	t2	contains the fraction
2972 *	t3	contains the remaining fraction
2973 *	ta0	contains the sign
2974 *	ta1	contains the (biased) exponent
2975 *	ta2	contains the fraction
2976 *	ta3	contains the remaining fraction
2977 *
2978 *----------------------------------------------------------------------------
2979 */
2980LEAF(get_cmp_d)
2981	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2982	and	a3, a3, 0xF << 2		# mask FS field
2983	lw	a3, cmp_fs_d_tbl(a3)		# switch on register number
2984	j	a3
2985
2986	.rdata
2987cmp_fs_d_tbl:
2988	.word	cmp_fs_d_f0
2989	.word	cmp_fs_d_f2
2990	.word	cmp_fs_d_f4
2991	.word	cmp_fs_d_f6
2992	.word	cmp_fs_d_f8
2993	.word	cmp_fs_d_f10
2994	.word	cmp_fs_d_f12
2995	.word	cmp_fs_d_f14
2996	.word	cmp_fs_d_f16
2997	.word	cmp_fs_d_f18
2998	.word	cmp_fs_d_f20
2999	.word	cmp_fs_d_f22
3000	.word	cmp_fs_d_f24
3001	.word	cmp_fs_d_f26
3002	.word	cmp_fs_d_f28
3003	.word	cmp_fs_d_f30
3004	.text
3005
3006cmp_fs_d_f0:
3007	mfc1	t3, $f0
3008	mfc1	t0, $f1
3009	b	cmp_fs_d_done
3010cmp_fs_d_f2:
3011	mfc1	t3, $f2
3012	mfc1	t0, $f3
3013	b	cmp_fs_d_done
3014cmp_fs_d_f4:
3015	mfc1	t3, $f4
3016	mfc1	t0, $f5
3017	b	cmp_fs_d_done
3018cmp_fs_d_f6:
3019	mfc1	t3, $f6
3020	mfc1	t0, $f7
3021	b	cmp_fs_d_done
3022cmp_fs_d_f8:
3023	mfc1	t3, $f8
3024	mfc1	t0, $f9
3025	b	cmp_fs_d_done
3026cmp_fs_d_f10:
3027	mfc1	t3, $f10
3028	mfc1	t0, $f11
3029	b	cmp_fs_d_done
3030cmp_fs_d_f12:
3031	mfc1	t3, $f12
3032	mfc1	t0, $f13
3033	b	cmp_fs_d_done
3034cmp_fs_d_f14:
3035	mfc1	t3, $f14
3036	mfc1	t0, $f15
3037	b	cmp_fs_d_done
3038cmp_fs_d_f16:
3039	mfc1	t3, $f16
3040	mfc1	t0, $f17
3041	b	cmp_fs_d_done
3042cmp_fs_d_f18:
3043	mfc1	t3, $f18
3044	mfc1	t0, $f19
3045	b	cmp_fs_d_done
3046cmp_fs_d_f20:
3047	mfc1	t3, $f20
3048	mfc1	t0, $f21
3049	b	cmp_fs_d_done
3050cmp_fs_d_f22:
3051	mfc1	t3, $f22
3052	mfc1	t0, $f23
3053	b	cmp_fs_d_done
3054cmp_fs_d_f24:
3055	mfc1	t3, $f24
3056	mfc1	t0, $f25
3057	b	cmp_fs_d_done
3058cmp_fs_d_f26:
3059	mfc1	t3, $f26
3060	mfc1	t0, $f27
3061	b	cmp_fs_d_done
3062cmp_fs_d_f28:
3063	mfc1	t3, $f28
3064	mfc1	t0, $f29
3065	b	cmp_fs_d_done
3066cmp_fs_d_f30:
3067	mfc1	t3, $f30
3068	mfc1	t0, $f31
3069cmp_fs_d_done:
3070	srl	t1, t0, 20			# get exponent
3071	and	t1, t1, 0x7FF
3072	and	t2, t0, 0xFFFFF			# get fraction
3073	srl	t0, t0, 31			# get sign
3074
3075	srl	a3, a0, 17 - 2			# get FT field (even regs only)
3076	and	a3, a3, 0xF << 2		# mask FT field
3077	lw	a3, cmp_ft_d_tbl(a3)		# switch on register number
3078	j	a3
3079
3080	.rdata
3081cmp_ft_d_tbl:
3082	.word	cmp_ft_d_f0
3083	.word	cmp_ft_d_f2
3084	.word	cmp_ft_d_f4
3085	.word	cmp_ft_d_f6
3086	.word	cmp_ft_d_f8
3087	.word	cmp_ft_d_f10
3088	.word	cmp_ft_d_f12
3089	.word	cmp_ft_d_f14
3090	.word	cmp_ft_d_f16
3091	.word	cmp_ft_d_f18
3092	.word	cmp_ft_d_f20
3093	.word	cmp_ft_d_f22
3094	.word	cmp_ft_d_f24
3095	.word	cmp_ft_d_f26
3096	.word	cmp_ft_d_f28
3097	.word	cmp_ft_d_f30
3098	.text
3099
3100cmp_ft_d_f0:
3101	mfc1	ta3, $f0
3102	mfc1	ta0, $f1
3103	b	cmp_ft_d_done
3104cmp_ft_d_f2:
3105	mfc1	ta3, $f2
3106	mfc1	ta0, $f3
3107	b	cmp_ft_d_done
3108cmp_ft_d_f4:
3109	mfc1	ta3, $f4
3110	mfc1	ta0, $f5
3111	b	cmp_ft_d_done
3112cmp_ft_d_f6:
3113	mfc1	ta3, $f6
3114	mfc1	ta0, $f7
3115	b	cmp_ft_d_done
3116cmp_ft_d_f8:
3117	mfc1	ta3, $f8
3118	mfc1	ta0, $f9
3119	b	cmp_ft_d_done
3120cmp_ft_d_f10:
3121	mfc1	ta3, $f10
3122	mfc1	ta0, $f11
3123	b	cmp_ft_d_done
3124cmp_ft_d_f12:
3125	mfc1	ta3, $f12
3126	mfc1	ta0, $f13
3127	b	cmp_ft_d_done
3128cmp_ft_d_f14:
3129	mfc1	ta3, $f14
3130	mfc1	ta0, $f15
3131	b	cmp_ft_d_done
3132cmp_ft_d_f16:
3133	mfc1	ta3, $f16
3134	mfc1	ta0, $f17
3135	b	cmp_ft_d_done
3136cmp_ft_d_f18:
3137	mfc1	ta3, $f18
3138	mfc1	ta0, $f19
3139	b	cmp_ft_d_done
3140cmp_ft_d_f20:
3141	mfc1	ta3, $f20
3142	mfc1	ta0, $f21
3143	b	cmp_ft_d_done
3144cmp_ft_d_f22:
3145	mfc1	ta3, $f22
3146	mfc1	ta0, $f23
3147	b	cmp_ft_d_done
3148cmp_ft_d_f24:
3149	mfc1	ta3, $f24
3150	mfc1	ta0, $f25
3151	b	cmp_ft_d_done
3152cmp_ft_d_f26:
3153	mfc1	ta3, $f26
3154	mfc1	ta0, $f27
3155	b	cmp_ft_d_done
3156cmp_ft_d_f28:
3157	mfc1	ta3, $f28
3158	mfc1	ta0, $f29
3159	b	cmp_ft_d_done
3160cmp_ft_d_f30:
3161	mfc1	ta3, $f30
3162	mfc1	ta0, $f31
3163cmp_ft_d_done:
3164	srl	ta1, ta0, 20			# get exponent
3165	and	ta1, ta1, 0x7FF
3166	and	ta2, ta0, 0xFFFFF		# get fraction
3167	srl	ta0, ta0, 31			# get sign
3168	j	ra
3169END(get_cmp_d)
3170
3171/*----------------------------------------------------------------------------
3172 * set_fd_s --
3173 *
3174 *	Write (single precision) the FD register (bits 10-6).
3175 *	This is an internal routine used by MipsEmulateFP only.
3176 *
3177 * Arguments:
3178 *	a0	contains the FP instruction
3179 *	t0	contains the sign
3180 *	t1	contains the (biased) exponent
3181 *	t2	contains the fraction
3182 *
3183 * set_fd_word --
3184 *
3185 *	Write (integer) the FD register (bits 10-6).
3186 *	This is an internal routine used by MipsEmulateFP only.
3187 *
3188 * Arguments:
3189 *	a0	contains the FP instruction
3190 *	t2	contains the integer
3191 *
3192 *----------------------------------------------------------------------------
3193 */
3194LEAF(set_fd_s)
3195	sll	t0, t0, 31			# position sign
3196	sll	t1, t1, 23			# position exponent
3197	or	t2, t2, t0
3198	or	t2, t2, t1
3199XLEAF(set_fd_word)
3200	srl	a3, a0, 7 - 2			# get FD field (even regs only)
3201	and	a3, a3, 0xF << 2		# mask FT field
3202	lw	a3, set_fd_s_tbl(a3)		# switch on register number
3203	j	a3
3204
3205	.rdata
3206set_fd_s_tbl:
3207	.word	set_fd_s_f0
3208	.word	set_fd_s_f2
3209	.word	set_fd_s_f4
3210	.word	set_fd_s_f6
3211	.word	set_fd_s_f8
3212	.word	set_fd_s_f10
3213	.word	set_fd_s_f12
3214	.word	set_fd_s_f14
3215	.word	set_fd_s_f16
3216	.word	set_fd_s_f18
3217	.word	set_fd_s_f20
3218	.word	set_fd_s_f22
3219	.word	set_fd_s_f24
3220	.word	set_fd_s_f26
3221	.word	set_fd_s_f28
3222	.word	set_fd_s_f30
3223	.text
3224
3225set_fd_s_f0:
3226	mtc1	t2, $f0
3227	j	ra
3228set_fd_s_f2:
3229	mtc1	t2, $f2
3230	j	ra
3231set_fd_s_f4:
3232	mtc1	t2, $f4
3233	j	ra
3234set_fd_s_f6:
3235	mtc1	t2, $f6
3236	j	ra
3237set_fd_s_f8:
3238	mtc1	t2, $f8
3239	j	ra
3240set_fd_s_f10:
3241	mtc1	t2, $f10
3242	j	ra
3243set_fd_s_f12:
3244	mtc1	t2, $f12
3245	j	ra
3246set_fd_s_f14:
3247	mtc1	t2, $f14
3248	j	ra
3249set_fd_s_f16:
3250	mtc1	t2, $f16
3251	j	ra
3252set_fd_s_f18:
3253	mtc1	t2, $f18
3254	j	ra
3255set_fd_s_f20:
3256	mtc1	t2, $f20
3257	j	ra
3258set_fd_s_f22:
3259	mtc1	t2, $f22
3260	j	ra
3261set_fd_s_f24:
3262	mtc1	t2, $f24
3263	j	ra
3264set_fd_s_f26:
3265	mtc1	t2, $f26
3266	j	ra
3267set_fd_s_f28:
3268	mtc1	t2, $f28
3269	j	ra
3270set_fd_s_f30:
3271	mtc1	t2, $f30
3272	j	ra
3273END(set_fd_s)
3274
3275/*----------------------------------------------------------------------------
3276 * set_fd_d --
3277 *
3278 *	Write (double precision) the FT register (bits 10-6).
3279 *	This is an internal routine used by MipsEmulateFP only.
3280 *
3281 * Arguments:
3282 *	a0	contains the FP instruction
3283 *	t0	contains the sign
3284 *	t1	contains the (biased) exponent
3285 *	t2	contains the fraction
3286 *	t3	contains the remaining fraction
3287 *
3288 *----------------------------------------------------------------------------
3289 */
3290LEAF(set_fd_d)
3291	sll	t0, t0, 31			# set sign
3292	sll	t1, t1, 20			# set exponent
3293	or	t0, t0, t1
3294	or	t0, t0, t2			# set fraction
3295	srl	a3, a0, 7 - 2			# get FD field (even regs only)
3296	and	a3, a3, 0xF << 2		# mask FD field
3297	lw	a3, set_fd_d_tbl(a3)		# switch on register number
3298	j	a3
3299
3300	.rdata
3301set_fd_d_tbl:
3302	.word	set_fd_d_f0
3303	.word	set_fd_d_f2
3304	.word	set_fd_d_f4
3305	.word	set_fd_d_f6
3306	.word	set_fd_d_f8
3307	.word	set_fd_d_f10
3308	.word	set_fd_d_f12
3309	.word	set_fd_d_f14
3310	.word	set_fd_d_f16
3311	.word	set_fd_d_f18
3312	.word	set_fd_d_f20
3313	.word	set_fd_d_f22
3314	.word	set_fd_d_f24
3315	.word	set_fd_d_f26
3316	.word	set_fd_d_f28
3317	.word	set_fd_d_f30
3318	.text
3319
3320set_fd_d_f0:
3321	mtc1	t3, $f0
3322	mtc1	t0, $f1
3323	j	ra
3324set_fd_d_f2:
3325	mtc1	t3, $f2
3326	mtc1	t0, $f3
3327	j	ra
3328set_fd_d_f4:
3329	mtc1	t3, $f4
3330	mtc1	t0, $f5
3331	j	ra
3332set_fd_d_f6:
3333	mtc1	t3, $f6
3334	mtc1	t0, $f7
3335	j	ra
3336set_fd_d_f8:
3337	mtc1	t3, $f8
3338	mtc1	t0, $f9
3339	j	ra
3340set_fd_d_f10:
3341	mtc1	t3, $f10
3342	mtc1	t0, $f11
3343	j	ra
3344set_fd_d_f12:
3345	mtc1	t3, $f12
3346	mtc1	t0, $f13
3347	j	ra
3348set_fd_d_f14:
3349	mtc1	t3, $f14
3350	mtc1	t0, $f15
3351	j	ra
3352set_fd_d_f16:
3353	mtc1	t3, $f16
3354	mtc1	t0, $f17
3355	j	ra
3356set_fd_d_f18:
3357	mtc1	t3, $f18
3358	mtc1	t0, $f19
3359	j	ra
3360set_fd_d_f20:
3361	mtc1	t3, $f20
3362	mtc1	t0, $f21
3363	j	ra
3364set_fd_d_f22:
3365	mtc1	t3, $f22
3366	mtc1	t0, $f23
3367	j	ra
3368set_fd_d_f24:
3369	mtc1	t3, $f24
3370	mtc1	t0, $f25
3371	j	ra
3372set_fd_d_f26:
3373	mtc1	t3, $f26
3374	mtc1	t0, $f27
3375	j	ra
3376set_fd_d_f28:
3377	mtc1	t3, $f28
3378	mtc1	t0, $f29
3379	j	ra
3380set_fd_d_f30:
3381	mtc1	t3, $f30
3382	mtc1	t0, $f31
3383	j	ra
3384END(set_fd_d)
3385
3386/*----------------------------------------------------------------------------
3387 * renorm_fs_s --
3388 *
3389 * Results:
3390 *	t1	unbiased exponent
3391 *	t2	normalized fraction
3392 *
3393 *----------------------------------------------------------------------------
3394 */
3395LEAF(renorm_fs_s)
3396/*
3397 * Find out how many leading zero bits are in t2 and put in t9.
3398 */
3399	move	v0, t2
3400	move	t9, zero
3401	srl	v1, v0, 16
3402	bne	v1, zero, 1f
3403	addu	t9, 16
3404	sll	v0, 16
34051:
3406	srl	v1, v0, 24
3407	bne	v1, zero, 1f
3408	addu	t9, 8
3409	sll	v0, 8
34101:
3411	srl	v1, v0, 28
3412	bne	v1, zero, 1f
3413	addu	t9, 4
3414	sll	v0, 4
34151:
3416	srl	v1, v0, 30
3417	bne	v1, zero, 1f
3418	addu	t9, 2
3419	sll	v0, 2
34201:
3421	srl	v1, v0, 31
3422	bne	v1, zero, 1f
3423	addu	t9, 1
3424/*
3425 * Now shift t2 the correct number of bits.
3426 */
34271:
3428	subu	t9, t9, SLEAD_ZEROS	# dont count normal leading zeros
3429	li	t1, SEXP_MIN
3430	subu	t1, t1, t9		# adjust exponent
3431	sll	t2, t2, t9
3432	j	ra
3433END(renorm_fs_s)
3434
3435/*----------------------------------------------------------------------------
3436 * renorm_fs_d --
3437 *
3438 * Results:
3439 *	t1	unbiased exponent
3440 *	t2,t3	normalized fraction
3441 *
3442 *----------------------------------------------------------------------------
3443 */
3444LEAF(renorm_fs_d)
3445/*
3446 * Find out how many leading zero bits are in t2,t3 and put in t9.
3447 */
3448	move	v0, t2
3449	move	t9, zero
3450	bne	t2, zero, 1f
3451	move	v0, t3
3452	addu	t9, 32
34531:
3454	srl	v1, v0, 16
3455	bne	v1, zero, 1f
3456	addu	t9, 16
3457	sll	v0, 16
34581:
3459	srl	v1, v0, 24
3460	bne	v1, zero, 1f
3461	addu	t9, 8
3462	sll	v0, 8
34631:
3464	srl	v1, v0, 28
3465	bne	v1, zero, 1f
3466	addu	t9, 4
3467	sll	v0, 4
34681:
3469	srl	v1, v0, 30
3470	bne	v1, zero, 1f
3471	addu	t9, 2
3472	sll	v0, 2
34731:
3474	srl	v1, v0, 31
3475	bne	v1, zero, 1f
3476	addu	t9, 1
3477/*
3478 * Now shift t2,t3 the correct number of bits.
3479 */
34801:
3481	subu	t9, t9, DLEAD_ZEROS	# dont count normal leading zeros
3482	li	t1, DEXP_MIN
3483	subu	t1, t1, t9		# adjust exponent
3484	li	v0, 32
3485	blt	t9, v0, 1f
3486	subu	t9, t9, v0		# shift fraction left >= 32 bits
3487	sll	t2, t3, t9
3488	move	t3, zero
3489	j	ra
34901:
3491	subu	v0, v0, t9		# shift fraction left < 32 bits
3492	sll	t2, t2, t9
3493	srl	v1, t3, v0
3494	or	t2, t2, v1
3495	sll	t3, t3, t9
3496	j	ra
3497END(renorm_fs_d)
3498
3499/*----------------------------------------------------------------------------
3500 * renorm_ft_s --
3501 *
3502 * Results:
3503 *	ta1	unbiased exponent
3504 *	ta2	normalized fraction
3505 *
3506 *----------------------------------------------------------------------------
3507 */
3508LEAF(renorm_ft_s)
3509/*
3510 * Find out how many leading zero bits are in ta2 and put in t9.
3511 */
3512	move	v0, ta2
3513	move	t9, zero
3514	srl	v1, v0, 16
3515	bne	v1, zero, 1f
3516	addu	t9, 16
3517	sll	v0, 16
35181:
3519	srl	v1, v0, 24
3520	bne	v1, zero, 1f
3521	addu	t9, 8
3522	sll	v0, 8
35231:
3524	srl	v1, v0, 28
3525	bne	v1, zero, 1f
3526	addu	t9, 4
3527	sll	v0, 4
35281:
3529	srl	v1, v0, 30
3530	bne	v1, zero, 1f
3531	addu	t9, 2
3532	sll	v0, 2
35331:
3534	srl	v1, v0, 31
3535	bne	v1, zero, 1f
3536	addu	t9, 1
3537/*
3538 * Now shift ta2 the correct number of bits.
3539 */
35401:
3541	subu	t9, t9, SLEAD_ZEROS	# dont count normal leading zeros
3542	li	ta1, SEXP_MIN
3543	subu	ta1, ta1, t9		# adjust exponent
3544	sll	ta2, ta2, t9
3545	j	ra
3546END(renorm_ft_s)
3547
3548/*----------------------------------------------------------------------------
3549 * renorm_ft_d --
3550 *
3551 * Results:
3552 *	ta1	unbiased exponent
3553 *	ta2,ta3	normalized fraction
3554 *
3555 *----------------------------------------------------------------------------
3556 */
3557LEAF(renorm_ft_d)
3558/*
3559 * Find out how many leading zero bits are in ta2,ta3 and put in t9.
3560 */
3561	move	v0, ta2
3562	move	t9, zero
3563	bne	ta2, zero, 1f
3564	move	v0, ta3
3565	addu	t9, 32
35661:
3567	srl	v1, v0, 16
3568	bne	v1, zero, 1f
3569	addu	t9, 16
3570	sll	v0, 16
35711:
3572	srl	v1, v0, 24
3573	bne	v1, zero, 1f
3574	addu	t9, 8
3575	sll	v0, 8
35761:
3577	srl	v1, v0, 28
3578	bne	v1, zero, 1f
3579	addu	t9, 4
3580	sll	v0, 4
35811:
3582	srl	v1, v0, 30
3583	bne	v1, zero, 1f
3584	addu	t9, 2
3585	sll	v0, 2
35861:
3587	srl	v1, v0, 31
3588	bne	v1, zero, 1f
3589	addu	t9, 1
3590/*
3591 * Now shift ta2,ta3 the correct number of bits.
3592 */
35931:
3594	subu	t9, t9, DLEAD_ZEROS	# dont count normal leading zeros
3595	li	ta1, DEXP_MIN
3596	subu	ta1, ta1, t9		# adjust exponent
3597	li	v0, 32
3598	blt	t9, v0, 1f
3599	subu	t9, t9, v0		# shift fraction left >= 32 bits
3600	sll	ta2, ta3, t9
3601	move	ta3, zero
3602	j	ra
36031:
3604	subu	v0, v0, t9		# shift fraction left < 32 bits
3605	sll	ta2, ta2, t9
3606	srl	v1, ta3, v0
3607	or	ta2, ta2, v1
3608	sll	ta3, ta3, t9
3609	j	ra
3610END(renorm_ft_d)
3611