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/*----------------------------------------------------------------------------
80 *
81 * MipsEmulateFP --
82 *
83 *	Emulate unimplemented floating point operations.
84 *	This routine should only be called by MipsFPInterrupt().
85 *
86 *	MipsEmulateFP(instr)
87 *		unsigned instr;
88 *
89 * Results:
90 *	None.
91 *
92 * Side effects:
93 *	Floating point registers are modified according to instruction.
94 *
95 *----------------------------------------------------------------------------
96 */
97NON_LEAF(MipsEmulateFP, CALLFRAME_SIZ, ra)
98	subu	sp, sp, CALLFRAME_SIZ
99	sw	ra, CALLFRAME_RA(sp)
100/*
101 * Decode the FMT field (bits 24-21) and FUNCTION field (bits 5-0).
102 */
103	srl	v0, a0, 21 - 2			# get FMT field
104	and	v0, v0, 0xF << 2		# mask FMT field
105	and	v1, a0, 0x3F			# mask FUNC field
106	sll	v1, v1, 5			# align for table lookup
107	bgt	v0, 4 << 2, ill			# illegal format
108
109	or	v1, v1, v0
110	cfc1	a1, MIPS_FPU_CSR		# get exception register
111	lw	a3, func_fmt_tbl(v1)		# switch on FUNC & FMT
112	and	a1, a1, ~MIPS_FPU_EXCEPTION_UNIMPL # clear exception
113	ctc1	a1, MIPS_FPU_CSR
114	j	a3
115
116	.rdata
117func_fmt_tbl:
118	.word	add_s		# 0
119	.word	add_d		# 0
120	.word	ill		# 0
121	.word	ill		# 0
122	.word	ill		# 0
123	.word	ill		# 0
124	.word	ill		# 0
125	.word	ill		# 0
126	.word	sub_s		# 1
127	.word	sub_d		# 1
128	.word	ill		# 1
129	.word	ill		# 1
130	.word	ill		# 1
131	.word	ill		# 1
132	.word	ill		# 1
133	.word	ill		# 1
134	.word	mul_s		# 2
135	.word	mul_d		# 2
136	.word	ill		# 2
137	.word	ill		# 2
138	.word	ill		# 2
139	.word	ill		# 2
140	.word	ill		# 2
141	.word	ill		# 2
142	.word	div_s		# 3
143	.word	div_d		# 3
144	.word	ill		# 3
145	.word	ill		# 3
146	.word	ill		# 3
147	.word	ill		# 3
148	.word	ill		# 3
149	.word	ill		# 3
150	.word	ill		# 4
151	.word	ill		# 4
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	abs_s		# 5
159	.word	abs_d		# 5
160	.word	ill		# 5
161	.word	ill		# 5
162	.word	ill		# 5
163	.word	ill		# 5
164	.word	ill		# 5
165	.word	ill		# 5
166	.word	mov_s		# 6
167	.word	mov_d		# 6
168	.word	ill		# 6
169	.word	ill		# 6
170	.word	ill		# 6
171	.word	ill		# 6
172	.word	ill		# 6
173	.word	ill		# 6
174	.word	neg_s		# 7
175	.word	neg_d		# 7
176	.word	ill		# 7
177	.word	ill		# 7
178	.word	ill		# 7
179	.word	ill		# 7
180	.word	ill		# 7
181	.word	ill		# 7
182	.word	ill		# 8
183	.word	ill		# 8
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		# 9
191	.word	ill		# 9
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		# 10
199	.word	ill		# 10
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		# 11
207	.word	ill		# 11
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		# 12
215	.word	ill		# 12
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		# 13
223	.word	ill		# 13
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		# 14
231	.word	ill		# 14
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		# 15
239	.word	ill		# 15
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		# 16
247	.word	ill		# 16
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		# 17
255	.word	ill		# 17
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		# 18
263	.word	ill		# 18
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		# 19
271	.word	ill		# 19
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		# 20
279	.word	ill		# 20
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		# 21
287	.word	ill		# 21
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		# 22
295	.word	ill		# 22
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		# 23
303	.word	ill		# 23
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		# 24
311	.word	ill		# 24
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		# 25
319	.word	ill		# 25
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		# 26
327	.word	ill		# 26
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		# 27
335	.word	ill		# 27
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		# 28
343	.word	ill		# 28
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		# 29
351	.word	ill		# 29
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		# 30
359	.word	ill		# 30
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		# 31
367	.word	ill		# 31
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		# 32
375	.word	cvt_s_d		# 32
376	.word	ill		# 32
377	.word	ill		# 32
378	.word	cvt_s_w		# 32
379	.word	ill		# 32
380	.word	ill		# 32
381	.word	ill		# 32
382	.word	cvt_d_s		# 33
383	.word	ill		# 33
384	.word	ill		# 33
385	.word	ill		# 33
386	.word	cvt_d_w		# 33
387	.word	ill		# 33
388	.word	ill		# 33
389	.word	ill		# 33
390	.word	ill		# 34
391	.word	ill		# 34
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		# 35
399	.word	ill		# 35
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	cvt_w_s		# 36
407	.word	cvt_w_d		# 36
408	.word	ill		# 36
409	.word	ill		# 36
410	.word	ill		# 36
411	.word	ill		# 36
412	.word	ill		# 36
413	.word	ill		# 36
414	.word	ill		# 37
415	.word	ill		# 37
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		# 38
423	.word	ill		# 38
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		# 39
431	.word	ill		# 39
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		# 40
439	.word	ill		# 40
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		# 41
447	.word	ill		# 41
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		# 42
455	.word	ill		# 42
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		# 43
463	.word	ill		# 43
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		# 44
471	.word	ill		# 44
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		# 45
479	.word	ill		# 45
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		# 46
487	.word	ill		# 46
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		# 47
495	.word	ill		# 47
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	cmp_s		# 48
503	.word	cmp_d		# 48
504	.word	ill		# 48
505	.word	ill		# 48
506	.word	ill		# 48
507	.word	ill		# 48
508	.word	ill		# 48
509	.word	ill		# 48
510	.word	cmp_s		# 49
511	.word	cmp_d		# 49
512	.word	ill		# 49
513	.word	ill		# 49
514	.word	ill		# 49
515	.word	ill		# 49
516	.word	ill		# 49
517	.word	ill		# 49
518	.word	cmp_s		# 50
519	.word	cmp_d		# 50
520	.word	ill		# 50
521	.word	ill		# 50
522	.word	ill		# 50
523	.word	ill		# 50
524	.word	ill		# 50
525	.word	ill		# 50
526	.word	cmp_s		# 51
527	.word	cmp_d		# 51
528	.word	ill		# 51
529	.word	ill		# 51
530	.word	ill		# 51
531	.word	ill		# 51
532	.word	ill		# 51
533	.word	ill		# 51
534	.word	cmp_s		# 52
535	.word	cmp_d		# 52
536	.word	ill		# 52
537	.word	ill		# 52
538	.word	ill		# 52
539	.word	ill		# 52
540	.word	ill		# 52
541	.word	ill		# 52
542	.word	cmp_s		# 53
543	.word	cmp_d		# 53
544	.word	ill		# 53
545	.word	ill		# 53
546	.word	ill		# 53
547	.word	ill		# 53
548	.word	ill		# 53
549	.word	ill		# 53
550	.word	cmp_s		# 54
551	.word	cmp_d		# 54
552	.word	ill		# 54
553	.word	ill		# 54
554	.word	ill		# 54
555	.word	ill		# 54
556	.word	ill		# 54
557	.word	ill		# 54
558	.word	cmp_s		# 55
559	.word	cmp_d		# 55
560	.word	ill		# 55
561	.word	ill		# 55
562	.word	ill		# 55
563	.word	ill		# 55
564	.word	ill		# 55
565	.word	ill		# 55
566	.word	cmp_s		# 56
567	.word	cmp_d		# 56
568	.word	ill		# 56
569	.word	ill		# 56
570	.word	ill		# 56
571	.word	ill		# 56
572	.word	ill		# 56
573	.word	ill		# 56
574	.word	cmp_s		# 57
575	.word	cmp_d		# 57
576	.word	ill		# 57
577	.word	ill		# 57
578	.word	ill		# 57
579	.word	ill		# 57
580	.word	ill		# 57
581	.word	ill		# 57
582	.word	cmp_s		# 58
583	.word	cmp_d		# 58
584	.word	ill		# 58
585	.word	ill		# 58
586	.word	ill		# 58
587	.word	ill		# 58
588	.word	ill		# 58
589	.word	ill		# 58
590	.word	cmp_s		# 59
591	.word	cmp_d		# 59
592	.word	ill		# 59
593	.word	ill		# 59
594	.word	ill		# 59
595	.word	ill		# 59
596	.word	ill		# 59
597	.word	ill		# 59
598	.word	cmp_s		# 60
599	.word	cmp_d		# 60
600	.word	ill		# 60
601	.word	ill		# 60
602	.word	ill		# 60
603	.word	ill		# 60
604	.word	ill		# 60
605	.word	ill		# 60
606	.word	cmp_s		# 61
607	.word	cmp_d		# 61
608	.word	ill		# 61
609	.word	ill		# 61
610	.word	ill		# 61
611	.word	ill		# 61
612	.word	ill		# 61
613	.word	ill		# 61
614	.word	cmp_s		# 62
615	.word	cmp_d		# 62
616	.word	ill		# 62
617	.word	ill		# 62
618	.word	ill		# 62
619	.word	ill		# 62
620	.word	ill		# 62
621	.word	ill		# 62
622	.word	cmp_s		# 63
623	.word	cmp_d		# 63
624	.word	ill		# 63
625	.word	ill		# 63
626	.word	ill		# 63
627	.word	ill		# 63
628	.word	ill		# 63
629	.word	ill		# 63
630	.text
631
632/*
633 * Single precision subtract.
634 */
635sub_s:
636	jal	get_ft_fs_s
637	xor	ta0, ta0, 1			# negate FT sign bit
638	b	add_sub_s
639/*
640 * Single precision add.
641 */
642add_s:
643	jal	get_ft_fs_s
644add_sub_s:
645	bne	t1, SEXP_INF, 1f		# is FS an infinity?
646	bne	ta1, SEXP_INF, result_fs_s	# if FT is not inf, result=FS
647	bne	t2, zero, result_fs_s		# if FS is NAN, result is FS
648	bne	ta2, zero, result_ft_s		# if FT is NAN, result is FT
649	bne	t0, ta0, invalid_s		# both infinities same sign?
650	b	result_fs_s			# result is in FS
6511:
652	beq	ta1, SEXP_INF, result_ft_s	# if FT is inf, result=FT
653	bne	t1, zero, 4f			# is FS a denormalized num?
654	beq	t2, zero, 3f			# is FS zero?
655	bne	ta1, zero, 2f			# is FT a denormalized num?
656	beq	ta2, zero, result_fs_s		# FT is zero, result=FS
657	jal	renorm_fs_s
658	jal	renorm_ft_s
659	b	5f
6602:
661	jal	renorm_fs_s
662	subu	ta1, ta1, SEXP_BIAS		# unbias FT exponent
663	or	ta2, ta2, SIMPL_ONE		# set implied one bit
664	b	5f
6653:
666	bne	ta1, zero, result_ft_s		# if FT != 0, result=FT
667	bne	ta2, zero, result_ft_s
668	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
669	bne	v0, MIPS_FPU_ROUND_RM, 1f	# round to -infinity?
670	or	t0, t0, ta0			# compute result sign
671	b	result_fs_s
6721:
673	and	t0, t0, ta0			# compute result sign
674	b	result_fs_s
6754:
676	bne	ta1, zero, 2f			# is FT a denormalized num?
677	beq	ta2, zero, result_fs_s		# FT is zero, result=FS
678	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
679	or	t2, t2, SIMPL_ONE		# set implied one bit
680	jal	renorm_ft_s
681	b	5f
6822:
683	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
684	or	t2, t2, SIMPL_ONE		# set implied one bit
685	subu	ta1, ta1, SEXP_BIAS		# unbias FT exponent
686	or	ta2, ta2, SIMPL_ONE		# set implied one bit
687/*
688 * Perform the addition.
689 */
6905:
691	move	t8, zero			# no shifted bits (sticky reg)
692	beq	t1, ta1, 4f			# no shift needed
693	subu	v0, t1, ta1			# v0 = difference of exponents
694	move	v1, v0				# v1 = abs(difference)
695	bge	v0, zero, 1f
696	negu	v1
6971:
698	ble	v1, SFRAC_BITS+2, 2f		# is difference too great?
699	li	t8, STICKYBIT			# set the sticky bit
700	bge	v0, zero, 1f			# check which exp is larger
701	move	t1, ta1				# result exp is FTs
702	move	t2, zero			# FSs fraction shifted is zero
703	b	4f
7041:
705	move	ta2, zero			# FTs fraction shifted is zero
706	b	4f
7072:
708	li	t9, 32				# compute 32 - abs(exp diff)
709	subu	t9, t9, v1
710	bgt	v0, zero, 3f			# if FS > FT, shift FTs frac
711	move	t1, ta1				# FT > FS, result exp is FTs
712	sll	t8, t2, t9			# save bits shifted out
713	srl	t2, t2, v1			# shift FSs fraction
714	b	4f
7153:
716	sll	t8, ta2, t9			# save bits shifted out
717	srl	ta2, ta2, v1			# shift FTs fraction
7184:
719	bne	t0, ta0, 1f			# if signs differ, subtract
720	addu	t2, t2, ta2			# add fractions
721	b	norm_s
7221:
723	blt	t2, ta2, 3f			# subtract larger from smaller
724	bne	t2, ta2, 2f			# if same, result=0
725	move	t1, zero			# result=0
726	move	t2, zero
727	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
728	bne	v0, MIPS_FPU_ROUND_RM, 1f	# round to -infinity?
729	or	t0, t0, ta0			# compute result sign
730	b	result_fs_s
7311:
732	and	t0, t0, ta0			# compute result sign
733	b	result_fs_s
7342:
735	sltu	t9, zero, t8			# compute t2:zero - ta2:t8
736	subu	t8, zero, t8
737	subu	t2, t2, ta2			# subtract fractions
738	subu	t2, t2, t9			# subtract barrow
739	b	norm_s
7403:
741	move	t0, ta0				# sign of result = FTs
742	sltu	t9, zero, t8			# compute ta2:zero - t2:t8
743	subu	t8, zero, t8
744	subu	t2, ta2, t2			# subtract fractions
745	subu	t2, t2, t9			# subtract barrow
746	b	norm_s
747
748/*
749 * Double precision subtract.
750 */
751sub_d:
752	jal	get_ft_fs_d
753	xor	ta0, ta0, 1			# negate sign bit
754	b	add_sub_d
755/*
756 * Double precision add.
757 */
758add_d:
759	jal	get_ft_fs_d
760add_sub_d:
761	bne	t1, DEXP_INF, 1f		# is FS an infinity?
762	bne	ta1, DEXP_INF, result_fs_d	# if FT is not inf, result=FS
763	bne	t2, zero, result_fs_d		# if FS is NAN, result is FS
764	bne	t3, zero, result_fs_d
765	bne	ta2, zero, result_ft_d		# if FT is NAN, result is FT
766	bne	ta3, zero, result_ft_d
767	bne	t0, ta0, invalid_d		# both infinities same sign?
768	b	result_fs_d			# result is in FS
7691:
770	beq	ta1, DEXP_INF, result_ft_d	# if FT is inf, result=FT
771	bne	t1, zero, 4f			# is FS a denormalized num?
772	bne	t2, zero, 1f			# is FS zero?
773	beq	t3, zero, 3f
7741:
775	bne	ta1, zero, 2f			# is FT a denormalized num?
776	bne	ta2, zero, 1f
777	beq	ta3, zero, result_fs_d		# FT is zero, result=FS
7781:
779	jal	renorm_fs_d
780	jal	renorm_ft_d
781	b	5f
7822:
783	jal	renorm_fs_d
784	subu	ta1, ta1, DEXP_BIAS		# unbias FT exponent
785	or	ta2, ta2, DIMPL_ONE		# set implied one bit
786	b	5f
7873:
788	bne	ta1, zero, result_ft_d		# if FT != 0, result=FT
789	bne	ta2, zero, result_ft_d
790	bne	ta3, zero, result_ft_d
791	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
792	bne	v0, MIPS_FPU_ROUND_RM, 1f	# round to -infinity?
793	or	t0, t0, ta0			# compute result sign
794	b	result_fs_d
7951:
796	and	t0, t0, ta0			# compute result sign
797	b	result_fs_d
7984:
799	bne	ta1, zero, 2f			# is FT a denormalized num?
800	bne	ta2, zero, 1f
801	beq	ta3, zero, result_fs_d		# FT is zero, result=FS
8021:
803	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
804	or	t2, t2, DIMPL_ONE		# set implied one bit
805	jal	renorm_ft_d
806	b	5f
8072:
808	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
809	or	t2, t2, DIMPL_ONE		# set implied one bit
810	subu	ta1, ta1, DEXP_BIAS		# unbias FT exponent
811	or	ta2, ta2, DIMPL_ONE		# set implied one bit
812/*
813 * Perform the addition.
814 */
8155:
816	move	t8, zero			# no shifted bits (sticky reg)
817	beq	t1, ta1, 4f			# no shift needed
818	subu	v0, t1, ta1			# v0 = difference of exponents
819	move	v1, v0				# v1 = abs(difference)
820	bge	v0, zero, 1f
821	negu	v1
8221:
823	ble	v1, DFRAC_BITS+2, 2f		# is difference too great?
824	li	t8, STICKYBIT			# set the sticky bit
825	bge	v0, zero, 1f			# check which exp is larger
826	move	t1, ta1				# result exp is FTs
827	move	t2, zero			# FSs fraction shifted is zero
828	move	t3, zero
829	b	4f
8301:
831	move	ta2, zero			# FTs fraction shifted is zero
832	move	ta3, zero
833	b	4f
8342:
835	li	t9, 32
836	bge	v0, zero, 3f			# if FS > FT, shift FTs frac
837	move	t1, ta1				# FT > FS, result exp is FTs
838	blt	v1, t9, 1f			# shift right by < 32?
839	subu	v1, v1, t9
840	subu	t9, t9, v1
841	sll	t8, t2, t9			# save bits shifted out
842	sltu	t9, zero, t3			# dont lose any one bits
843	or	t8, t8, t9			# save sticky bit
844	srl	t3, t2, v1			# shift FSs fraction
845	move	t2, zero
846	b	4f
8471:
848	subu	t9, t9, v1
849	sll	t8, t3, t9			# save bits shifted out
850	srl	t3, t3, v1			# shift FSs fraction
851	sll	t9, t2, t9			# save bits shifted out of t2
852	or	t3, t3, t9			# and put into t3
853	srl	t2, t2, v1
854	b	4f
8553:
856	blt	v1, t9, 1f			# shift right by < 32?
857	subu	v1, v1, t9
858	subu	t9, t9, v1
859	sll	t8, ta2, t9			# save bits shifted out
860	srl	ta3, ta2, v1			# shift FTs fraction
861	move	ta2, zero
862	b	4f
8631:
864	subu	t9, t9, v1
865	sll	t8, ta3, t9			# save bits shifted out
866	srl	ta3, ta3, v1			# shift FTs fraction
867	sll	t9, ta2, t9			# save bits shifted out of t2
868	or	ta3, ta3, t9			# and put into t3
869	srl	ta2, ta2, v1
8704:
871	bne	t0, ta0, 1f			# if signs differ, subtract
872	addu	t3, t3, ta3			# add fractions
873	sltu	t9, t3, ta3			# compute carry
874	addu	t2, t2, ta2			# add fractions
875	addu	t2, t2, t9			# add carry
876	b	norm_d
8771:
878	blt	t2, ta2, 3f			# subtract larger from smaller
879	bne	t2, ta2, 2f
880	bltu	t3, ta3, 3f
881	bne	t3, ta3, 2f			# if same, result=0
882	move	t1, zero			# result=0
883	move	t2, zero
884	move	t3, zero
885	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
886	bne	v0, MIPS_FPU_ROUND_RM, 1f	# round to -infinity?
887	or	t0, t0, ta0			# compute result sign
888	b	result_fs_d
8891:
890	and	t0, t0, ta0			# compute result sign
891	b	result_fs_d
8922:
893	beq	t8, zero, 1f			# compute t2:t3:zero - ta2:ta3:t8
894	subu	t8, zero, t8
895	sltu	v0, t3, 1			# compute barrow out
896	subu	t3, t3, 1			# subtract barrow
897	subu	t2, t2, v0
8981:
899	sltu	v0, t3, ta3
900	subu	t3, t3, ta3			# subtract fractions
901	subu	t2, t2, ta2			# subtract fractions
902	subu	t2, t2, v0			# subtract barrow
903	b	norm_d
9043:
905	move	t0, ta0				# sign of result = FTs
906	beq	t8, zero, 1f			# compute ta2:ta3:zero - t2:t3:t8
907	subu	t8, zero, t8
908	sltu	v0, ta3, 1			# compute barrow out
909	subu	ta3, ta3, 1			# subtract barrow
910	subu	ta2, ta2, v0
9111:
912	sltu	v0, ta3, t3
913	subu	t3, ta3, t3			# subtract fractions
914	subu	t2, ta2, t2			# subtract fractions
915	subu	t2, t2, v0			# subtract barrow
916	b	norm_d
917
918/*
919 * Single precision multiply.
920 */
921mul_s:
922	jal	get_ft_fs_s
923	xor	t0, t0, ta0			# compute sign of result
924	move	ta0, t0
925	bne	t1, SEXP_INF, 2f		# is FS an infinity?
926	bne	t2, zero, result_fs_s		# if FS is a NAN, result=FS
927	bne	ta1, SEXP_INF, 1f		# FS is inf, is FT an infinity?
928	bne	ta2, zero, result_ft_s		# if FT is a NAN, result=FT
929	b	result_fs_s			# result is infinity
9301:
931	bne	ta1, zero, result_fs_s		# inf * zero? if no, result=FS
932	bne	ta2, zero, result_fs_s
933	b	invalid_s			# infinity * zero is invalid
9342:
935	bne	ta1, SEXP_INF, 1f		# FS != inf, is FT an infinity?
936	bne	t1, zero, result_ft_s		# zero * inf? if no, result=FT
937	bne	t2, zero, result_ft_s
938	bne	ta2, zero, result_ft_s		# if FT is a NAN, result=FT
939	b	invalid_s			# zero * infinity is invalid
9401:
941	bne	t1, zero, 1f			# is FS zero?
942	beq	t2, zero, result_fs_s		# result is zero
943	jal	renorm_fs_s
944	b	2f
9451:
946	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
947	or	t2, t2, SIMPL_ONE		# set implied one bit
9482:
949	bne	ta1, zero, 1f			# is FT zero?
950	beq	ta2, zero, result_ft_s		# result is zero
951	jal	renorm_ft_s
952	b	2f
9531:
954	subu	ta1, ta1, SEXP_BIAS		# unbias FT exponent
955	or	ta2, ta2, SIMPL_ONE		# set implied one bit
9562:
957	addu	t1, t1, ta1			# compute result exponent
958	addu	t1, t1, 9			# account for binary point
959	multu	t2, ta2				# multiply fractions
960	mflo	t8
961	mfhi	t2
962	b	norm_s
963
964/*
965 * Double precision multiply.
966 */
967mul_d:
968	jal	get_ft_fs_d
969	xor	t0, t0, ta0			# compute sign of result
970	move	ta0, t0
971	bne	t1, DEXP_INF, 2f		# is FS an infinity?
972	bne	t2, zero, result_fs_d		# if FS is a NAN, result=FS
973	bne	t3, zero, result_fs_d
974	bne	ta1, DEXP_INF, 1f		# FS is inf, is FT an infinity?
975	bne	ta2, zero, result_ft_d		# if FT is a NAN, result=FT
976	bne	ta3, zero, result_ft_d
977	b	result_fs_d			# result is infinity
9781:
979	bne	ta1, zero, result_fs_d		# inf * zero? if no, result=FS
980	bne	ta2, zero, result_fs_d
981	bne	ta3, zero, result_fs_d
982	b	invalid_d			# infinity * zero is invalid
9832:
984	bne	ta1, DEXP_INF, 1f		# FS != inf, is FT an infinity?
985	bne	t1, zero, result_ft_d		# zero * inf? if no, result=FT
986	bne	t2, zero, result_ft_d		# if FS is a NAN, result=FS
987	bne	t3, zero, result_ft_d
988	bne	ta2, zero, result_ft_d		# if FT is a NAN, result=FT
989	bne	ta3, zero, result_ft_d
990	b	invalid_d			# zero * infinity is invalid
9911:
992	bne	t1, zero, 2f			# is FS zero?
993	bne	t2, zero, 1f
994	beq	t3, zero, result_fs_d		# result is zero
9951:
996	jal	renorm_fs_d
997	b	3f
9982:
999	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
1000	or	t2, t2, DIMPL_ONE		# set implied one bit
10013:
1002	bne	ta1, zero, 2f			# is FT zero?
1003	bne	ta2, zero, 1f
1004	beq	ta3, zero, result_ft_d		# result is zero
10051:
1006	jal	renorm_ft_d
1007	b	3f
10082:
1009	subu	ta1, ta1, DEXP_BIAS		# unbias FT exponent
1010	or	ta2, ta2, DIMPL_ONE		# set implied one bit
10113:
1012	addu	t1, t1, ta1			# compute result exponent
1013	addu	t1, t1, 12			# ???
1014	multu	t3, ta3				# multiply fractions (low * low)
1015	move	ta0, t2				# free up t2,t3 for result
1016	move	ta1, t3
1017	mflo	a3				# save low order bits
1018	mfhi	t8
1019	not	v0, t8
1020	multu	ta0, ta3			# multiply FS(high) * FT(low)
1021	mflo	v1
1022	mfhi	t3				# init low result
1023	sltu	v0, v0, v1			# compute carry
1024	addu	t8, v1
1025	multu	ta1, ta2			# multiply FS(low) * FT(high)
1026	addu	t3, t3, v0			# add carry
1027	not	v0, t8
1028	mflo	v1
1029	mfhi	t2
1030	sltu	v0, v0, v1
1031	addu	t8, v1
1032	multu	ta0, ta2			# multiply FS(high) * FT(high)
1033	addu	t3, v0
1034	not	v1, t3
1035	sltu	v1, v1, t2
1036	addu	t3, t2
1037	not	v0, t3
1038	mfhi	t2
1039	addu	t2, v1
1040	mflo	v1
1041	sltu	v0, v0, v1
1042	addu	t2, v0
1043	addu	t3, v1
1044	sltu	a3, zero, a3			# reduce t8,a3 to just t8
1045	or	t8, a3
1046	b	norm_d
1047
1048/*
1049 * Single precision divide.
1050 */
1051div_s:
1052	jal	get_ft_fs_s
1053	xor	t0, t0, ta0			# compute sign of result
1054	move	ta0, t0
1055	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1056	bne	t2, zero, result_fs_s		# if FS is NAN, result is FS
1057	bne	ta1, SEXP_INF, result_fs_s	# is FT an infinity?
1058	bne	ta2, zero, result_ft_s		# if FT is NAN, result is FT
1059	b	invalid_s			# infinity/infinity is invalid
10601:
1061	bne	ta1, SEXP_INF, 1f		# is FT an infinity?
1062	bne	ta2, zero, result_ft_s		# if FT is NAN, result is FT
1063	move	t1, zero			# x / infinity is zero
1064	move	t2, zero
1065	b	result_fs_s
10661:
1067	bne	t1, zero, 2f			# is FS zero?
1068	bne	t2, zero, 1f
1069	bne	ta1, zero, result_fs_s		# FS=zero, is FT zero?
1070	beq	ta2, zero, invalid_s		# 0 / 0
1071	b	result_fs_s			# result = zero
10721:
1073	jal	renorm_fs_s
1074	b	3f
10752:
1076	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
1077	or	t2, t2, SIMPL_ONE		# set implied one bit
10783:
1079	bne	ta1, zero, 2f			# is FT zero?
1080	bne	ta2, zero, 1f
1081	or	a1, a1, MIPS_FPU_EXCEPTION_DIV0 | MIPS_FPU_STICKY_DIV0
1082	and	v0, a1, MIPS_FPU_ENABLE_DIV0 	# trap enabled?
1083	bne	v0, zero, fpe_trap
1084	ctc1	a1, MIPS_FPU_CSR		# save exceptions
1085	li	t1, SEXP_INF			# result is infinity
1086	move	t2, zero
1087	b	result_fs_s
10881:
1089	jal	renorm_ft_s
1090	b	3f
10912:
1092	subu	ta1, ta1, SEXP_BIAS		# unbias FT exponent
1093	or	ta2, ta2, SIMPL_ONE		# set implied one bit
10943:
1095	subu	t1, t1, ta1			# compute exponent
1096	subu	t1, t1, 3			# compensate for result position
1097	li	v0, SFRAC_BITS+3		# number of bits to divide
1098	move	t8, t2				# init dividend
1099	move	t2, zero			# init result
11001:
1101	bltu	t8, ta2, 3f			# is dividend >= divisor?
11022:
1103	subu	t8, t8, ta2			# subtract divisor from dividend
1104	or	t2, t2, 1			# remember that we did
1105	bne	t8, zero, 3f			# if not done, continue
1106	sll	t2, t2, v0			# shift result to final position
1107	b	norm_s
11083:
1109	sll	t8, t8, 1			# shift dividend
1110	sll	t2, t2, 1			# shift result
1111	subu	v0, v0, 1			# are we done?
1112	bne	v0, zero, 1b			# no, continue
1113	b	norm_s
1114
1115/*
1116 * Double precision divide.
1117 */
1118div_d:
1119	jal	get_ft_fs_d
1120	xor	t0, t0, ta0			# compute sign of result
1121	move	ta0, t0
1122	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1123	bne	t2, zero, result_fs_d		# if FS is NAN, result is FS
1124	bne	t3, zero, result_fs_d
1125	bne	ta1, DEXP_INF, result_fs_d	# is FT an infinity?
1126	bne	ta2, zero, result_ft_d		# if FT is NAN, result is FT
1127	bne	ta3, zero, result_ft_d
1128	b	invalid_d			# infinity/infinity is invalid
11291:
1130	bne	ta1, DEXP_INF, 1f		# is FT an infinity?
1131	bne	ta2, zero, result_ft_d		# if FT is NAN, result is FT
1132	bne	ta3, zero, result_ft_d
1133	move	t1, zero			# x / infinity is zero
1134	move	t2, zero
1135	move	t3, zero
1136	b	result_fs_d
11371:
1138	bne	t1, zero, 2f			# is FS zero?
1139	bne	t2, zero, 1f
1140	bne	t3, zero, 1f
1141	bne	ta1, zero, result_fs_d		# FS=zero, is FT zero?
1142	bne	ta2, zero, result_fs_d
1143	beq	ta3, zero, invalid_d		# 0 / 0
1144	b	result_fs_d			# result = zero
11451:
1146	jal	renorm_fs_d
1147	b	3f
11482:
1149	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
1150	or	t2, t2, DIMPL_ONE		# set implied one bit
11513:
1152	bne	ta1, zero, 2f			# is FT zero?
1153	bne	ta2, zero, 1f
1154	bne	ta3, zero, 1f
1155	or	a1, a1, MIPS_FPU_EXCEPTION_DIV0 | MIPS_FPU_STICKY_DIV0
1156	and	v0, a1, MIPS_FPU_ENABLE_DIV0	# trap enabled?
1157	bne	v0, zero, fpe_trap
1158	ctc1	a1, MIPS_FPU_CSR		# Save exceptions
1159	li	t1, DEXP_INF			# result is infinity
1160	move	t2, zero
1161	move	t3, zero
1162	b	result_fs_d
11631:
1164	jal	renorm_ft_d
1165	b	3f
11662:
1167	subu	ta1, ta1, DEXP_BIAS		# unbias FT exponent
1168	or	ta2, ta2, DIMPL_ONE		# set implied one bit
11693:
1170	subu	t1, t1, ta1			# compute exponent
1171	subu	t1, t1, 3			# compensate for result position
1172	li	v0, DFRAC_BITS+3		# number of bits to divide
1173	move	t8, t2				# init dividend
1174	move	t9, t3
1175	move	t2, zero			# init result
1176	move	t3, zero
11771:
1178	bltu	t8, ta2, 3f			# is dividend >= divisor?
1179	bne	t8, ta2, 2f
1180	bltu	t9, ta3, 3f
11812:
1182	sltu	v1, t9, ta3			# subtract divisor from dividend
1183	subu	t9, t9, ta3
1184	subu	t8, t8, ta2
1185	subu	t8, t8, v1
1186	or	t3, t3, 1			# remember that we did
1187	bne	t8, zero, 3f			# if not done, continue
1188	bne	t9, zero, 3f
1189	li	v1, 32				# shift result to final position
1190	blt	v0, v1, 2f			# shift < 32 bits?
1191	subu	v0, v0, v1			# shift by > 32 bits
1192	sll	t2, t3, v0			# shift upper part
1193	move	t3, zero
1194	b	norm_d
11952:
1196	subu	v1, v1, v0			# shift by < 32 bits
1197	sll	t2, t2, v0			# shift upper part
1198	srl	t9, t3, v1			# save bits shifted out
1199	or	t2, t2, t9			# and put into upper part
1200	sll	t3, t3, v0
1201	b	norm_d
12023:
1203	sll	t8, t8, 1			# shift dividend
1204	srl	v1, t9, 31			# save bit shifted out
1205	or	t8, t8, v1			# and put into upper part
1206	sll	t9, t9, 1
1207	sll	t2, t2, 1			# shift result
1208	srl	v1, t3, 31			# save bit shifted out
1209	or	t2, t2, v1			# and put into upper part
1210	sll	t3, t3, 1
1211	subu	v0, v0, 1			# are we done?
1212	bne	v0, zero, 1b			# no, continue
1213	sltu	v0, zero, t9			# be sure to save any one bits
1214	or	t8, t8, v0			# from the lower remainder
1215	b	norm_d
1216
1217/*
1218 * Single precision absolute value.
1219 */
1220abs_s:
1221	jal	get_fs_s
1222	move	t0, zero			# set sign positive
1223	b	result_fs_s
1224
1225/*
1226 * Double precision absolute value.
1227 */
1228abs_d:
1229	jal	get_fs_d
1230	move	t0, zero			# set sign positive
1231	b	result_fs_d
1232
1233/*
1234 * Single precision move.
1235 */
1236mov_s:
1237	jal	get_fs_s
1238	b	result_fs_s
1239
1240/*
1241 * Double precision move.
1242 */
1243mov_d:
1244	jal	get_fs_d
1245	b	result_fs_d
1246
1247/*
1248 * Single precision negate.
1249 */
1250neg_s:
1251	jal	get_fs_s
1252	xor	t0, t0, 1			# reverse sign
1253	b	result_fs_s
1254
1255/*
1256 * Double precision negate.
1257 */
1258neg_d:
1259	jal	get_fs_d
1260	xor	t0, t0, 1			# reverse sign
1261	b	result_fs_d
1262
1263/*
1264 * Convert double to single.
1265 */
1266cvt_s_d:
1267	jal	get_fs_d
1268	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1269	li	t1, SEXP_INF			# convert to single
1270	sll	t2, t2, 3			# convert D fraction to S
1271	srl	t8, t3, 32 - 3
1272	or	t2, t2, t8
1273	b	result_fs_s
12741:
1275	bne	t1, zero, 2f			# is FS zero?
1276	bne	t2, zero, 1f
1277	beq	t3, zero, result_fs_s		# result=0
12781:
1279	jal	renorm_fs_d
1280	subu	t1, t1, 3			# correct exp for shift below
1281	b	3f
12822:
1283	subu	t1, t1, DEXP_BIAS		# unbias exponent
1284	or	t2, t2, DIMPL_ONE		# add implied one bit
12853:
1286	sll	t2, t2, 3			# convert D fraction to S
1287	srl	t8, t3, 32 - 3
1288	or	t2, t2, t8
1289	sll	t8, t3, 3
1290	b	norm_noshift_s
1291
1292/*
1293 * Convert integer to single.
1294 */
1295cvt_s_w:
1296	jal	get_fs_int
1297	bne	t2, zero, 1f			# check for zero
1298	move	t1, zero
1299	b	result_fs_s
1300/*
1301 * Find out how many leading zero bits are in t2 and put in t9.
1302 */
13031:
1304	move	v0, t2
1305	move	t9, zero
1306	srl	v1, v0, 16
1307	bne	v1, zero, 1f
1308	addu	t9, 16
1309	sll	v0, 16
13101:
1311	srl	v1, v0, 24
1312	bne	v1, zero, 1f
1313	addu	t9, 8
1314	sll	v0, 8
13151:
1316	srl	v1, v0, 28
1317	bne	v1, zero, 1f
1318	addu	t9, 4
1319	sll	v0, 4
13201:
1321	srl	v1, v0, 30
1322	bne	v1, zero, 1f
1323	addu	t9, 2
1324	sll	v0, 2
13251:
1326	srl	v1, v0, 31
1327	bne	v1, zero, 1f
1328	addu	t9, 1
1329/*
1330 * Now shift t2 the correct number of bits.
1331 */
13321:
1333	subu	t9, t9, SLEAD_ZEROS		# dont count leading zeros
1334	li	t1, 23				# init exponent
1335	subu	t1, t1, t9			# compute exponent
1336	beq	t9, zero, 1f
1337	li	v0, 32
1338	blt	t9, zero, 2f			# if shift < 0, shift right
1339	subu	v0, v0, t9
1340	sll	t2, t2, t9			# shift left
13411:
1342	add	t1, t1, SEXP_BIAS		# bias exponent
1343	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1344	b	result_fs_s
13452:
1346	negu	t9				# shift right by t9
1347	subu	v0, v0, t9
1348	sll	t8, t2, v0			# save bits shifted out
1349	srl	t2, t2, t9
1350	b	norm_noshift_s
1351
1352/*
1353 * Convert single to double.
1354 */
1355cvt_d_s:
1356	jal	get_fs_s
1357	move	t3, zero
1358	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1359	li	t1, DEXP_INF			# convert to double
1360	b	result_fs_d
13611:
1362	bne	t1, zero, 2f			# is FS denormalized or zero?
1363	beq	t2, zero, result_fs_d		# is FS zero?
1364	jal	renorm_fs_s
1365	move	t8, zero
1366	b	norm_d
13672:
1368	addu	t1, t1, DEXP_BIAS - SEXP_BIAS	# bias exponent correctly
1369	sll	t3, t2, 32 - 3			# convert S fraction to D
1370	srl	t2, t2, 3
1371	b	result_fs_d
1372
1373/*
1374 * Convert integer to double.
1375 */
1376cvt_d_w:
1377	jal	get_fs_int
1378	bne	t2, zero, 1f			# check for zero
1379	move	t1, zero			# result=0
1380	move	t3, zero
1381	b	result_fs_d
1382/*
1383 * Find out how many leading zero bits are in t2 and put in t9.
1384 */
13851:
1386	move	v0, t2
1387	move	t9, zero
1388	srl	v1, v0, 16
1389	bne	v1, zero, 1f
1390	addu	t9, 16
1391	sll	v0, 16
13921:
1393	srl	v1, v0, 24
1394	bne	v1, zero, 1f
1395	addu	t9, 8
1396	sll	v0, 8
13971:
1398	srl	v1, v0, 28
1399	bne	v1, zero, 1f
1400	addu	t9, 4
1401	sll	v0, 4
14021:
1403	srl	v1, v0, 30
1404	bne	v1, zero, 1f
1405	addu	t9, 2
1406	sll	v0, 2
14071:
1408	srl	v1, v0, 31
1409	bne	v1, zero, 1f
1410	addu	t9, 1
1411/*
1412 * Now shift t2 the correct number of bits.
1413 */
14141:
1415	subu	t9, t9, DLEAD_ZEROS		# dont count leading zeros
1416	li	t1, DEXP_BIAS + 20		# init exponent
1417	subu	t1, t1, t9			# compute exponent
1418	beq	t9, zero, 1f
1419	li	v0, 32
1420	blt	t9, zero, 2f			# if shift < 0, shift right
1421	subu	v0, v0, t9
1422	sll	t2, t2, t9			# shift left
14231:
1424	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1425	move	t3, zero
1426	b	result_fs_d
14272:
1428	negu	t9				# shift right by t9
1429	subu	v0, v0, t9
1430	sll	t3, t2, v0
1431	srl	t2, t2, t9
1432	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1433	b	result_fs_d
1434
1435/*
1436 * Convert single to integer.
1437 */
1438cvt_w_s:
1439	jal	get_fs_s
1440	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1441	bne	t2, zero, invalid_w		# invalid conversion
14421:
1443	bne	t1, zero, 1f			# is FS zero?
1444	beq	t2, zero, result_fs_w		# result is zero
1445	move	t2, zero			# result is an inexact zero
1446	b	inexact_w
14471:
1448	subu	t1, t1, SEXP_BIAS		# unbias exponent
1449	or	t2, t2, SIMPL_ONE		# add implied one bit
1450	sll	t3, t2, 32 - 3			# convert S fraction to D
1451	srl	t2, t2, 3
1452	b	cvt_w
1453
1454/*
1455 * Convert double to integer.
1456 */
1457cvt_w_d:
1458	jal	get_fs_d
1459	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1460	bne	t2, zero, invalid_w		# invalid conversion
1461	bne	t3, zero, invalid_w		# invalid conversion
14621:
1463	bne	t1, zero, 2f			# is FS zero?
1464	bne	t2, zero, 1f
1465	beq	t3, zero, result_fs_w		# result is zero
14661:
1467	move	t2, zero			# result is an inexact zero
1468	b	inexact_w
14692:
1470	subu	t1, t1, DEXP_BIAS		# unbias exponent
1471	or	t2, t2, DIMPL_ONE		# add implied one bit
1472cvt_w:
1473	blt	t1, WEXP_MIN, underflow_w	# is exponent too small?
1474	li	v0, WEXP_MAX+1
1475	bgt	t1, v0, overflow_w		# is exponent too large?
1476	bne	t1, v0, 1f			# special check for INT_MIN
1477	beq	t0, zero, overflow_w		# if positive, overflow
1478	bne	t2, DIMPL_ONE, overflow_w
1479	bne	t3, zero, overflow_w
1480	li	t2, INT_MIN			# result is INT_MIN
1481	b	result_fs_w
14821:
1483	subu	v0, t1, 20			# compute amount to shift
1484	beq	v0, zero, 2f			# is shift needed?
1485	li	v1, 32
1486	blt	v0, zero, 1f			# if shift < 0, shift right
1487	subu	v1, v1, v0			# shift left
1488	sll	t2, t2, v0
1489	srl	t9, t3, v1			# save bits shifted out of t3
1490	or	t2, t2, t9			# and put into t2
1491	sll	t3, t3, v0			# shift FSs fraction
1492	b	2f
14931:
1494	negu	v0				# shift right by v0
1495	subu	v1, v1, v0
1496	sll	t8, t3, v1			# save bits shifted out
1497	sltu	t8, zero, t8			# dont lose any ones
1498	srl	t3, t3, v0			# shift FSs fraction
1499	or	t3, t3, t8
1500	sll	t9, t2, v1			# save bits shifted out of t2
1501	or	t3, t3, t9			# and put into t3
1502	srl	t2, t2, v0
1503/*
1504 * round result (t0 is sign, t2 is integer part, t3 is fractional part).
1505 */
15062:
1507	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
1508	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
1509	beq	v0, MIPS_FPU_ROUND_RZ, 5f	# round to zero (truncate)
1510	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
1511	beq	t0, zero, 5f			# if sign is positive, truncate
1512	b	2f
15131:
1514	bne	t0, zero, 5f			# if sign is negative, truncate
15152:
1516	beq	t3, zero, 5f			# if no fraction bits, continue
1517	addu	t2, t2, 1			# add rounding bit
1518	blt	t2, zero, overflow_w		# overflow?
1519	b	5f
15203:
1521	li	v0, GUARDBIT			# load guard bit for rounding
1522	addu	v0, v0, t3			# add remainder
1523	sltu	v1, v0, t3			# compute carry out
1524	beq	v1, zero, 4f			# if no carry, continue
1525	addu	t2, t2, 1			# add carry to result
1526	blt	t2, zero, overflow_w		# overflow?
15274:
1528	bne	v0, zero, 5f			# if rounded remainder is zero
1529	and	t2, t2, ~1			#  clear LSB (round to nearest)
15305:
1531	beq	t0, zero, 1f			# result positive?
1532	negu	t2				# convert to negative integer
15331:
1534	beq	t3, zero, result_fs_w		# is result exact?
1535/*
1536 * Handle inexact exception.
1537 */
1538inexact_w:
1539	or	a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
1540	and	v0, a1, MIPS_FPU_ENABLE_INEXACT
1541	bne	v0, zero, fpe_trap
1542	ctc1	a1, MIPS_FPU_CSR		# save exceptions
1543	b	result_fs_w
1544
1545/*
1546 * Conversions to integer which overflow will trap (if enabled),
1547 * or generate an inexact trap (if enabled),
1548 * or generate an invalid exception.
1549 */
1550overflow_w:
1551	or	a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
1552	and	v0, a1, MIPS_FPU_ENABLE_OVERFLOW
1553	bne	v0, zero, fpe_trap
1554	and	v0, a1, MIPS_FPU_ENABLE_INEXACT
1555	bne	v0, zero, inexact_w		# inexact traps enabled?
1556	b	invalid_w
1557
1558/*
1559 * Conversions to integer which underflow will trap (if enabled),
1560 * or generate an inexact trap (if enabled),
1561 * or generate an invalid exception.
1562 */
1563underflow_w:
1564	or	a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1565	and	v0, a1, MIPS_FPU_ENABLE_UNDERFLOW
1566	bne	v0, zero, fpe_trap
1567	and	v0, a1, MIPS_FPU_ENABLE_INEXACT
1568	bne	v0, zero, inexact_w		# inexact traps enabled?
1569	b	invalid_w
1570
1571/*
1572 * Compare single.
1573 */
1574cmp_s:
1575	jal	get_cmp_s
1576	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1577	bne	t2, zero, unordered		# FS is a NAN
15781:
1579	bne	ta1, SEXP_INF, 2f		# is FT an infinity?
1580	bne	ta2, zero, unordered		# FT is a NAN
15812:
1582	sll	t1, t1, 23			# reassemble exp & frac
1583	or	t1, t1, t2
1584	sll	ta1, ta1, 23			# reassemble exp & frac
1585	or	ta1, ta1, ta2
1586	beq	t0, zero, 1f			# is FS positive?
1587	negu	t1
15881:
1589	beq	ta0, zero, 1f			# is FT positive?
1590	negu	ta1
15911:
1592	li	v0, COND_LESS
1593	blt	t1, ta1, test_cond		# is FS < FT?
1594	li	v0, COND_EQUAL
1595	beq	t1, ta1, test_cond		# is FS == FT?
1596	move	v0, zero			# FS > FT
1597	b	test_cond
1598
1599/*
1600 * Compare double.
1601 */
1602cmp_d:
1603	jal	get_cmp_d
1604	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1605	bne	t2, zero, unordered
1606	bne	t3, zero, unordered		# FS is a NAN
16071:
1608	bne	ta1, DEXP_INF, 2f		# is FT an infinity?
1609	bne	ta2, zero, unordered
1610	bne	ta3, zero, unordered		# FT is a NAN
16112:
1612	sll	t1, t1, 20			# reassemble exp & frac
1613	or	t1, t1, t2
1614	sll	ta1, ta1, 20			# reassemble exp & frac
1615	or	ta1, ta1, ta2
1616	beq	t0, zero, 1f			# is FS positive?
1617	not	t3				# negate t1,t3
1618	not	t1
1619	addu	t3, t3, 1
1620	seq	v0, t3, zero			# compute carry
1621	addu	t1, t1, v0
16221:
1623	beq	ta0, zero, 1f			# is FT positive?
1624	not	ta3				# negate ta1,ta3
1625	not	ta1
1626	addu	ta3, ta3, 1
1627	seq	v0, ta3, zero			# compute carry
1628	addu	ta1, ta1, v0
16291:
1630	li	v0, COND_LESS
1631	blt	t1, ta1, test_cond		# is FS(MSW) < FT(MSW)?
1632	move	v0, zero
1633	bne	t1, ta1, test_cond		# is FS(MSW) > FT(MSW)?
1634	li	v0, COND_LESS
1635	bltu	t3, ta3, test_cond		# is FS(LSW) < FT(LSW)?
1636	li	v0, COND_EQUAL
1637	beq	t3, ta3, test_cond		# is FS(LSW) == FT(LSW)?
1638	move	v0, zero			# FS > FT
1639test_cond:
1640	and	v0, v0, a0			# condition match instruction?
1641set_cond:
1642	bne	v0, zero, 1f
1643	and	a1, a1, ~MIPS_FPU_COND_BIT	# clear condition bit
1644	b	2f
16451:
1646	or	a1, a1, MIPS_FPU_COND_BIT	# set condition bit
16472:
1648	ctc1	a1, MIPS_FPU_CSR		# save condition bit
1649	b	done
1650
1651unordered:
1652	and	v0, a0, COND_UNORDERED		# this cmp match unordered?
1653	bne	v0, zero, 1f
1654	and	a1, a1, ~MIPS_FPU_COND_BIT	# clear condition bit
1655	b	2f
16561:
1657	or	a1, a1, MIPS_FPU_COND_BIT	# set condition bit
16582:
1659	and	v0, a0, COND_SIGNAL
1660	beq	v0, zero, 1f			# is this a signaling cmp?
1661	or	a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
1662	and	v0, a1, MIPS_FPU_ENABLE_INVALID
1663	bne	v0, zero, fpe_trap
16641:
1665	ctc1	a1, MIPS_FPU_CSR		# save condition bit
1666	b	done
1667
1668/*
1669 * Determine the amount to shift the fraction in order to restore the
1670 * normalized position. After that, round and handle exceptions.
1671 */
1672norm_s:
1673	move	v0, t2
1674	move	t9, zero			# t9 = num of leading zeros
1675	bne	t2, zero, 1f
1676	move	v0, t8
1677	addu	t9, 32
16781:
1679	srl	v1, v0, 16
1680	bne	v1, zero, 1f
1681	addu	t9, 16
1682	sll	v0, 16
16831:
1684	srl	v1, v0, 24
1685	bne	v1, zero, 1f
1686	addu	t9, 8
1687	sll	v0, 8
16881:
1689	srl	v1, v0, 28
1690	bne	v1, zero, 1f
1691	addu	t9, 4
1692	sll	v0, 4
16931:
1694	srl	v1, v0, 30
1695	bne	v1, zero, 1f
1696	addu	t9, 2
1697	sll	v0, 2
16981:
1699	srl	v1, v0, 31
1700	bne	v1, zero, 1f
1701	addu	t9, 1
1702/*
1703 * Now shift t2,t8 the correct number of bits.
1704 */
17051:
1706	subu	t9, t9, SLEAD_ZEROS		# dont count leading zeros
1707	subu	t1, t1, t9			# adjust the exponent
1708	beq	t9, zero, norm_noshift_s
1709	li	v1, 32
1710	blt	t9, zero, 1f			# if shift < 0, shift right
1711	subu	v1, v1, t9
1712	sll	t2, t2, t9			# shift t2,t8 left
1713	srl	v0, t8, v1			# save bits shifted out
1714	or	t2, t2, v0
1715	sll	t8, t8, t9
1716	b	norm_noshift_s
17171:
1718	negu	t9				# shift t2,t8 right by t9
1719	subu	v1, v1, t9
1720	sll	v0, t8, v1			# save bits shifted out
1721	sltu	v0, zero, v0			# be sure to save any one bits
1722	srl	t8, t8, t9
1723	or	t8, t8, v0
1724	sll	v0, t2, v1			# save bits shifted out
1725	or	t8, t8, v0
1726	srl	t2, t2, t9
1727norm_noshift_s:
1728	move	ta1, t1				# save unrounded exponent
1729	move	ta2, t2				# save unrounded fraction
1730	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
1731	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
1732	beq	v0, MIPS_FPU_ROUND_RZ, 5f	# round to zero (truncate)
1733	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
1734	beq	t0, zero, 5f			# if sign is positive, truncate
1735	b	2f
17361:
1737	bne	t0, zero, 5f			# if sign is negative, truncate
17382:
1739	beq	t8, zero, 5f			# if exact, continue
1740	addu	t2, t2, 1			# add rounding bit
1741	bne	t2, SIMPL_ONE<<1, 5f		# need to adjust exponent?
1742	addu	t1, t1, 1			# adjust exponent
1743	srl	t2, t2, 1			# renormalize fraction
1744	b	5f
17453:
1746	li	v0, GUARDBIT			# load guard bit for rounding
1747	addu	v0, v0, t8			# add remainder
1748	sltu	v1, v0, t8			# compute carry out
1749	beq	v1, zero, 4f			# if no carry, continue
1750	addu	t2, t2, 1			# add carry to result
1751	bne	t2, SIMPL_ONE<<1, 4f		# need to adjust exponent?
1752	addu	t1, t1, 1			# adjust exponent
1753	srl	t2, t2, 1			# renormalize fraction
17544:
1755	bne	v0, zero, 5f			# if rounded remainder is zero
1756	and	t2, t2, ~1			#  clear LSB (round to nearest)
17575:
1758	bgt	t1, SEXP_MAX, overflow_s	# overflow?
1759	blt	t1, SEXP_MIN, underflow_s	# underflow?
1760	bne	t8, zero, inexact_s		# is result inexact?
1761	addu	t1, t1, SEXP_BIAS		# bias exponent
1762	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1763	b	result_fs_s
1764
1765/*
1766 * Handle inexact exception.
1767 */
1768inexact_s:
1769	addu	t1, t1, SEXP_BIAS		# bias exponent
1770	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1771inexact_nobias_s:
1772	jal	set_fd_s			# save result
1773	or	a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
1774	and	v0, a1, MIPS_FPU_ENABLE_INEXACT
1775	bne	v0, zero, fpe_trap
1776	ctc1	a1, MIPS_FPU_CSR		# save exceptions
1777	b	done
1778
1779/*
1780 * Overflow will trap (if enabled),
1781 * or generate an inexact trap (if enabled),
1782 * or generate an infinity.
1783 */
1784overflow_s:
1785	or	a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
1786	and	v0, a1, MIPS_FPU_ENABLE_OVERFLOW
1787	beq	v0, zero, 1f
1788	subu	t1, t1, 192			# bias exponent
1789	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1790	jal	set_fd_s			# save result
1791	b	fpe_trap
17921:
1793	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
1794	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
1795	beq	v0, MIPS_FPU_ROUND_RZ, 1f	# round to zero (truncate)
1796	beq	v0, MIPS_FPU_ROUND_RP, 2f	# round to +infinity
1797	bne	t0, zero, 3f
17981:
1799	li	t1, SEXP_MAX			# result is max finite
1800	li	t2, 0x007fffff
1801	b	inexact_s
18022:
1803	bne	t0, zero, 1b
18043:
1805	li	t1, SEXP_MAX + 1		# result is infinity
1806	move	t2, zero
1807	b	inexact_s
1808
1809/*
1810 * In this implementation, "tininess" is detected "after rounding" and
1811 * "loss of accuracy" is detected as "an inexact result".
1812 */
1813underflow_s:
1814	and	v0, a1, MIPS_FPU_ENABLE_UNDERFLOW
1815	beq	v0, zero, 1f
1816/*
1817 * Underflow is enabled so compute the result and trap.
1818 */
1819	addu	t1, t1, 192			# bias exponent
1820	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1821	jal	set_fd_s			# save result
1822	or	a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1823	b	fpe_trap
1824/*
1825 * Underflow is not enabled so compute the result,
1826 * signal inexact result (if it is) and trap (if enabled).
1827 */
18281:
1829	move	t1, ta1				# get unrounded exponent
1830	move	t2, ta2				# get unrounded fraction
1831	li	t9, SEXP_MIN			# compute shift amount
1832	subu	t9, t9, t1			# shift t2,t8 right by t9
1833	blt	t9, SFRAC_BITS+2, 3f		# shift all the bits out?
1834	move	t1, zero			# result is inexact zero
1835	move	t2, zero
1836	or	a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1837/*
1838 * Now round the zero result.
1839 * Only need to worry about rounding to +- infinity when the sign matches.
1840 */
1841	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
1842	beq	v0, MIPS_FPU_ROUND_RN, inexact_nobias_s # round to nearest
1843	beq	v0, MIPS_FPU_ROUND_RZ, inexact_nobias_s # round to zero
1844	beq	v0, MIPS_FPU_ROUND_RP, 1f		# round to +infinity
1845	beq	t0, zero, inexact_nobias_s	# if sign is positive, truncate
1846	b	2f
18471:
1848	bne	t0, zero, inexact_nobias_s	# if sign is negative, truncate
18492:
1850	addu	t2, t2, 1			# add rounding bit
1851	b	inexact_nobias_s
18523:
1853	li	v1, 32
1854	subu	v1, v1, t9
1855	sltu	v0, zero, t8			# be sure to save any one bits
1856	sll	t8, t2, v1			# save bits shifted out
1857	or	t8, t8, v0			# include sticky bits
1858	srl	t2, t2, t9
1859/*
1860 * Now round the denormalized result.
1861 */
1862	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
1863	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
1864	beq	v0, MIPS_FPU_ROUND_RZ, 5f	# round to zero (truncate)
1865	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
1866	beq	t0, zero, 5f			# if sign is positive, truncate
1867	b	2f
18681:
1869	bne	t0, zero, 5f			# if sign is negative, truncate
18702:
1871	beq	t8, zero, 5f			# if exact, continue
1872	addu	t2, t2, 1			# add rounding bit
1873	b	5f
18743:
1875	li	v0, GUARDBIT			# load guard bit for rounding
1876	addu	v0, v0, t8			# add remainder
1877	sltu	v1, v0, t8			# compute carry out
1878	beq	v1, zero, 4f			# if no carry, continue
1879	addu	t2, t2, 1			# add carry to result
18804:
1881	bne	v0, zero, 5f			# if rounded remainder is zero
1882	and	t2, t2, ~1			#  clear LSB (round to nearest)
18835:
1884	move	t1, zero			# denorm or zero exponent
1885	jal	set_fd_s			# save result
1886	beq	t8, zero, done			# check for exact result
1887	or	a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1888	or	a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
1889	and	v0, a1, MIPS_FPU_ENABLE_INEXACT
1890	bne	v0, zero, fpe_trap
1891	ctc1	a1, MIPS_FPU_CSR		# save exceptions
1892	b	done
1893
1894/*
1895 * Determine the amount to shift the fraction in order to restore the
1896 * normalized position. After that, round and handle exceptions.
1897 */
1898norm_d:
1899	move	v0, t2
1900	move	t9, zero			# t9 = num of leading zeros
1901	bne	t2, zero, 1f
1902	move	v0, t3
1903	addu	t9, 32
1904	bne	t3, zero, 1f
1905	move	v0, t8
1906	addu	t9, 32
19071:
1908	srl	v1, v0, 16
1909	bne	v1, zero, 1f
1910	addu	t9, 16
1911	sll	v0, 16
19121:
1913	srl	v1, v0, 24
1914	bne	v1, zero, 1f
1915	addu	t9, 8
1916	sll	v0, 8
19171:
1918	srl	v1, v0, 28
1919	bne	v1, zero, 1f
1920	addu	t9, 4
1921	sll	v0, 4
19221:
1923	srl	v1, v0, 30
1924	bne	v1, zero, 1f
1925	addu	t9, 2
1926	sll	v0, 2
19271:
1928	srl	v1, v0, 31
1929	bne	v1, zero, 1f
1930	addu	t9, 1
1931/*
1932 * Now shift t2,t3,t8 the correct number of bits.
1933 */
19341:
1935	subu	t9, t9, DLEAD_ZEROS		# dont count leading zeros
1936	subu	t1, t1, t9			# adjust the exponent
1937	beq	t9, zero, norm_noshift_d
1938	li	v1, 32
1939	blt	t9, zero, 2f			# if shift < 0, shift right
1940	blt	t9, v1, 1f			# shift by < 32?
1941	subu	t9, t9, v1			# shift by >= 32
1942	subu	v1, v1, t9
1943	sll	t2, t3, t9			# shift left by t9
1944	srl	v0, t8, v1			# save bits shifted out
1945	or	t2, t2, v0
1946	sll	t3, t8, t9
1947	move	t8, zero
1948	b	norm_noshift_d
19491:
1950	subu	v1, v1, t9
1951	sll	t2, t2, t9			# shift left by t9
1952	srl	v0, t3, v1			# save bits shifted out
1953	or	t2, t2, v0
1954	sll	t3, t3, t9
1955	srl	v0, t8, v1			# save bits shifted out
1956	or	t3, t3, v0
1957	sll	t8, t8, t9
1958	b	norm_noshift_d
19592:
1960	negu	t9				# shift right by t9
1961	subu	v1, v1, t9			#  (known to be < 32 bits)
1962	sll	v0, t8, v1			# save bits shifted out
1963	sltu	v0, zero, v0			# be sure to save any one bits
1964	srl	t8, t8, t9
1965	or	t8, t8, v0
1966	sll	v0, t3, v1			# save bits shifted out
1967	or	t8, t8, v0
1968	srl	t3, t3, t9
1969	sll	v0, t2, v1			# save bits shifted out
1970	or	t3, t3, v0
1971	srl	t2, t2, t9
1972norm_noshift_d:
1973	move	ta1, t1				# save unrounded exponent
1974	move	ta2, t2				# save unrounded fraction (MS)
1975	move	ta3, t3				# save unrounded fraction (LS)
1976	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
1977	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
1978	beq	v0, MIPS_FPU_ROUND_RZ, 5f	# round to zero (truncate)
1979	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
1980	beq	t0, zero, 5f			# if sign is positive, truncate
1981	b	2f
19821:
1983	bne	t0, zero, 5f			# if sign is negative, truncate
19842:
1985	beq	t8, zero, 5f			# if exact, continue
1986	addu	t3, t3, 1			# add rounding bit
1987	bne	t3, zero, 5f			# branch if no carry
1988	addu	t2, t2, 1			# add carry
1989	bne	t2, DIMPL_ONE<<1, 5f		# need to adjust exponent?
1990	addu	t1, t1, 1			# adjust exponent
1991	srl	t2, t2, 1			# renormalize fraction
1992	b	5f
19933:
1994	li	v0, GUARDBIT			# load guard bit for rounding
1995	addu	v0, v0, t8			# add remainder
1996	sltu	v1, v0, t8			# compute carry out
1997	beq	v1, zero, 4f			# branch if no carry
1998	addu	t3, t3, 1			# add carry
1999	bne	t3, zero, 4f			# branch if no carry
2000	addu	t2, t2, 1			# add carry to result
2001	bne	t2, DIMPL_ONE<<1, 4f		# need to adjust exponent?
2002	addu	t1, t1, 1			# adjust exponent
2003	srl	t2, t2, 1			# renormalize fraction
20044:
2005	bne	v0, zero, 5f			# if rounded remainder is zero
2006	and	t3, t3, ~1			#  clear LSB (round to nearest)
20075:
2008	bgt	t1, DEXP_MAX, overflow_d	# overflow?
2009	blt	t1, DEXP_MIN, underflow_d	# underflow?
2010	bne	t8, zero, inexact_d		# is result inexact?
2011	addu	t1, t1, DEXP_BIAS		# bias exponent
2012	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2013	b	result_fs_d
2014
2015/*
2016 * Handle inexact exception.
2017 */
2018inexact_d:
2019	addu	t1, t1, DEXP_BIAS		# bias exponent
2020	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2021inexact_nobias_d:
2022	jal	set_fd_d			# save result
2023	or	a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
2024	and	v0, a1, MIPS_FPU_ENABLE_INEXACT
2025	bne	v0, zero, fpe_trap
2026	ctc1	a1, MIPS_FPU_CSR		# save exceptions
2027	b	done
2028
2029/*
2030 * Overflow will trap (if enabled),
2031 * or generate an inexact trap (if enabled),
2032 * or generate an infinity.
2033 */
2034overflow_d:
2035	or	a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
2036	and	v0, a1, MIPS_FPU_ENABLE_OVERFLOW
2037	beq	v0, zero, 1f
2038	subu	t1, t1, 1536			# bias exponent
2039	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2040	jal	set_fd_d			# save result
2041	b	fpe_trap
20421:
2043	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
2044	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
2045	beq	v0, MIPS_FPU_ROUND_RZ, 1f	# round to zero (truncate)
2046	beq	v0, MIPS_FPU_ROUND_RP, 2f	# round to +infinity
2047	bne	t0, zero, 3f
20481:
2049	li	t1, DEXP_MAX			# result is max finite
2050	li	t2, 0x000fffff
2051	li	t3, 0xffffffff
2052	b	inexact_d
20532:
2054	bne	t0, zero, 1b
20553:
2056	li	t1, DEXP_MAX + 1		# result is infinity
2057	move	t2, zero
2058	move	t3, zero
2059	b	inexact_d
2060
2061/*
2062 * In this implementation, "tininess" is detected "after rounding" and
2063 * "loss of accuracy" is detected as "an inexact result".
2064 */
2065underflow_d:
2066	and	v0, a1, MIPS_FPU_ENABLE_UNDERFLOW
2067	beq	v0, zero, 1f
2068/*
2069 * Underflow is enabled so compute the result and trap.
2070 */
2071	addu	t1, t1, 1536			# bias exponent
2072	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2073	jal	set_fd_d			# save result
2074	or	a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2075	b	fpe_trap
2076/*
2077 * Underflow is not enabled so compute the result,
2078 * signal inexact result (if it is) and trap (if enabled).
2079 */
20801:
2081	move	t1, ta1				# get unrounded exponent
2082	move	t2, ta2				# get unrounded fraction (MS)
2083	move	t3, ta3				# get unrounded fraction (LS)
2084	li	t9, DEXP_MIN			# compute shift amount
2085	subu	t9, t9, t1			# shift t2,t8 right by t9
2086	blt	t9, DFRAC_BITS+2, 3f		# shift all the bits out?
2087	move	t1, zero			# result is inexact zero
2088	move	t2, zero
2089	move	t3, zero
2090	or	a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2091/*
2092 * Now round the zero result.
2093 * Only need to worry about rounding to +- infinity when the sign matches.
2094 */
2095	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
2096	beq	v0, MIPS_FPU_ROUND_RN, inexact_nobias_d  # round to nearest
2097	beq	v0, MIPS_FPU_ROUND_RZ, inexact_nobias_d  # round to zero
2098	beq	v0, MIPS_FPU_ROUND_RP, 1f		# round to +infinity
2099	beq	t0, zero, inexact_nobias_d	# if sign is positive, truncate
2100	b	2f
21011:
2102	bne	t0, zero, inexact_nobias_d	# if sign is negative, truncate
21032:
2104	addu	t3, t3, 1			# add rounding bit
2105	b	inexact_nobias_d
21063:
2107	li	v1, 32
2108	blt	t9, v1, 1f			# shift by < 32?
2109	subu	t9, t9, v1			# shift right by >= 32
2110	subu	v1, v1, t9
2111	sltu	v0, zero, t8			# be sure to save any one bits
2112	sll	t8, t2, v1			# save bits shifted out
2113	or	t8, t8, v0			# include sticky bits
2114	srl	t3, t2, t9
2115	move	t2, zero
2116	b	2f
21171:
2118	subu	v1, v1, t9			# shift right by t9
2119	sltu	v0, zero, t8			# be sure to save any one bits
2120	sll	t8, t3, v1			# save bits shifted out
2121	or	t8, t8, v0			# include sticky bits
2122	srl	t3, t3, t9
2123	sll	v0, t2, v1			# save bits shifted out
2124	or	t3, t3, v0
2125	srl	t2, t2, t9
2126/*
2127 * Now round the denormalized result.
2128 */
21292:
2130	and	v0, a1, MIPS_FPU_ROUNDING_BITS	# get rounding mode
2131	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
2132	beq	v0, MIPS_FPU_ROUND_RZ, 5f	# round to zero (truncate)
2133	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
2134	beq	t0, zero, 5f			# if sign is positive, truncate
2135	b	2f
21361:
2137	bne	t0, zero, 5f			# if sign is negative, truncate
21382:
2139	beq	t8, zero, 5f			# if exact, continue
2140	addu	t3, t3, 1			# add rounding bit
2141	bne	t3, zero, 5f			# if no carry, continue
2142	addu	t2, t2, 1			# add carry
2143	b	5f
21443:
2145	li	v0, GUARDBIT			# load guard bit for rounding
2146	addu	v0, v0, t8			# add remainder
2147	sltu	v1, v0, t8			# compute carry out
2148	beq	v1, zero, 4f			# if no carry, continue
2149	addu	t3, t3, 1			# add rounding bit
2150	bne	t3, zero, 4f			# if no carry, continue
2151	addu	t2, t2, 1			# add carry
21524:
2153	bne	v0, zero, 5f			# if rounded remainder is zero
2154	and	t3, t3, ~1			#  clear LSB (round to nearest)
21555:
2156	move	t1, zero			# denorm or zero exponent
2157	jal	set_fd_d			# save result
2158	beq	t8, zero, done			# check for exact result
2159	or	a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2160	or	a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
2161	and	v0, a1, MIPS_FPU_ENABLE_INEXACT
2162	bne	v0, zero, fpe_trap
2163	ctc1	a1, MIPS_FPU_CSR		# save exceptions
2164	b	done
2165
2166/*
2167 * Signal an invalid operation if the trap is enabled; otherwise,
2168 * the result is a quiet NAN.
2169 */
2170invalid_s:					# trap invalid operation
2171	or	a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
2172	and	v0, a1, MIPS_FPU_ENABLE_INVALID
2173	bne	v0, zero, fpe_trap
2174	ctc1	a1, MIPS_FPU_CSR		# save exceptions
2175	move	t0, zero			# result is a quiet NAN
2176	li	t1, SEXP_INF
2177	li	t2, SQUIET_NAN
2178	jal	set_fd_s			# save result (in t0,t1,t2)
2179	b	done
2180
2181/*
2182 * Signal an invalid operation if the trap is enabled; otherwise,
2183 * the result is a quiet NAN.
2184 */
2185invalid_d:					# trap invalid operation
2186	or	a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
2187	and	v0, a1, MIPS_FPU_ENABLE_INVALID
2188	bne	v0, zero, fpe_trap
2189	ctc1	a1, MIPS_FPU_CSR		# save exceptions
2190	move	t0, zero			# result is a quiet NAN
2191	li	t1, DEXP_INF
2192	li	t2, DQUIET_NAN0
2193	li	t3, DQUIET_NAN1
2194	jal	set_fd_d			# save result (in t0,t1,t2,t3)
2195	b	done
2196
2197/*
2198 * Signal an invalid operation if the trap is enabled; otherwise,
2199 * the result is INT_MAX or INT_MIN.
2200 */
2201invalid_w:					# trap invalid operation
2202	or	a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
2203	and	v0, a1, MIPS_FPU_ENABLE_INVALID
2204	bne	v0, zero, fpe_trap
2205	ctc1	a1, MIPS_FPU_CSR		# save exceptions
2206	bne	t0, zero, 1f
2207	li	t2, INT_MAX			# result is INT_MAX
2208	b	result_fs_w
22091:
2210	li	t2, INT_MIN			# result is INT_MIN
2211	b	result_fs_w
2212
2213/*
2214 * Trap if the hardware should have handled this case.
2215 */
2216fpe_trap:
2217	move	a2, a1				# code = FP CSR
2218	ctc1	a1, MIPS_FPU_CSR		# save exceptions
2219	break	0
2220
2221/*
2222 * Send an illegal instruction signal to the current process.
2223 */
2224ill:
2225	ctc1	a1, MIPS_FPU_CSR		# save exceptions
2226	move	a2, a0				# code = FP instruction
2227	break	0
2228
2229result_ft_s:
2230	move	t0, ta0				# result is FT
2231	move	t1, ta1
2232	move	t2, ta2
2233result_fs_s:					# result is FS
2234	jal	set_fd_s			# save result (in t0,t1,t2)
2235	b	done
2236
2237result_fs_w:
2238	jal	set_fd_word			# save result (in t2)
2239	b	done
2240
2241result_ft_d:
2242	move	t0, ta0				# result is FT
2243	move	t1, ta1
2244	move	t2, ta2
2245	move	t3, ta3
2246result_fs_d:					# result is FS
2247	jal	set_fd_d			# save result (in t0,t1,t2,t3)
2248
2249done:
2250	lw	ra, CALLFRAME_RA(sp)
2251	addu	sp, sp, CALLFRAME_SIZ
2252	j	ra
2253END(MipsEmulateFP)
2254
2255/*----------------------------------------------------------------------------
2256 * get_fs_int --
2257 *
2258 *	Read (integer) the FS register (bits 15-11).
2259 *	This is an internal routine used by MipsEmulateFP only.
2260 *
2261 * Results:
2262 *	t0	contains the sign
2263 *	t2	contains the fraction
2264 *
2265 *----------------------------------------------------------------------------
2266 */
2267LEAF(get_fs_int)
2268	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2269	and	a3, a3, 0xF << 2		# mask FS field
2270	lw	a3, get_fs_int_tbl(a3)		# switch on register number
2271	j	a3
2272
2273	.rdata
2274get_fs_int_tbl:
2275	.word	get_fs_int_f0
2276	.word	get_fs_int_f2
2277	.word	get_fs_int_f4
2278	.word	get_fs_int_f6
2279	.word	get_fs_int_f8
2280	.word	get_fs_int_f10
2281	.word	get_fs_int_f12
2282	.word	get_fs_int_f14
2283	.word	get_fs_int_f16
2284	.word	get_fs_int_f18
2285	.word	get_fs_int_f20
2286	.word	get_fs_int_f22
2287	.word	get_fs_int_f24
2288	.word	get_fs_int_f26
2289	.word	get_fs_int_f28
2290	.word	get_fs_int_f30
2291	.text
2292
2293get_fs_int_f0:
2294	mfc1	t2, $f0
2295	b	get_fs_int_done
2296get_fs_int_f2:
2297	mfc1	t2, $f2
2298	b	get_fs_int_done
2299get_fs_int_f4:
2300	mfc1	t2, $f4
2301	b	get_fs_int_done
2302get_fs_int_f6:
2303	mfc1	t2, $f6
2304	b	get_fs_int_done
2305get_fs_int_f8:
2306	mfc1	t2, $f8
2307	b	get_fs_int_done
2308get_fs_int_f10:
2309	mfc1	t2, $f10
2310	b	get_fs_int_done
2311get_fs_int_f12:
2312	mfc1	t2, $f12
2313	b	get_fs_int_done
2314get_fs_int_f14:
2315	mfc1	t2, $f14
2316	b	get_fs_int_done
2317get_fs_int_f16:
2318	mfc1	t2, $f16
2319	b	get_fs_int_done
2320get_fs_int_f18:
2321	mfc1	t2, $f18
2322	b	get_fs_int_done
2323get_fs_int_f20:
2324	mfc1	t2, $f20
2325	b	get_fs_int_done
2326get_fs_int_f22:
2327	mfc1	t2, $f22
2328	b	get_fs_int_done
2329get_fs_int_f24:
2330	mfc1	t2, $f24
2331	b	get_fs_int_done
2332get_fs_int_f26:
2333	mfc1	t2, $f26
2334	b	get_fs_int_done
2335get_fs_int_f28:
2336	mfc1	t2, $f28
2337	b	get_fs_int_done
2338get_fs_int_f30:
2339	mfc1	t2, $f30
2340get_fs_int_done:
2341	srl	t0, t2, 31			# init the sign bit
2342	bge	t2, zero, 1f
2343	negu	t2
23441:
2345	j	ra
2346END(get_fs_int)
2347
2348/*----------------------------------------------------------------------------
2349 * get_ft_fs_s --
2350 *
2351 *	Read (single precision) the FT register (bits 20-16) and
2352 *	the FS register (bits 15-11) and break up into fields.
2353 *	This is an internal routine used by MipsEmulateFP only.
2354 *
2355 * Results:
2356 *	t0	contains the FS sign
2357 *	t1	contains the FS (biased) exponent
2358 *	t2	contains the FS fraction
2359 *	ta0	contains the FT sign
2360 *	ta1	contains the FT (biased) exponent
2361 *	ta2	contains the FT fraction
2362 *
2363 *----------------------------------------------------------------------------
2364 */
2365LEAF(get_ft_fs_s)
2366	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2367	and	a3, a3, 0xF << 2		# mask FT field
2368	lw	a3, get_ft_s_tbl(a3)		# switch on register number
2369	j	a3
2370
2371	.rdata
2372get_ft_s_tbl:
2373	.word	get_ft_s_f0
2374	.word	get_ft_s_f2
2375	.word	get_ft_s_f4
2376	.word	get_ft_s_f6
2377	.word	get_ft_s_f8
2378	.word	get_ft_s_f10
2379	.word	get_ft_s_f12
2380	.word	get_ft_s_f14
2381	.word	get_ft_s_f16
2382	.word	get_ft_s_f18
2383	.word	get_ft_s_f20
2384	.word	get_ft_s_f22
2385	.word	get_ft_s_f24
2386	.word	get_ft_s_f26
2387	.word	get_ft_s_f28
2388	.word	get_ft_s_f30
2389	.text
2390
2391get_ft_s_f0:
2392	mfc1	ta0, $f0
2393	b	get_ft_s_done
2394get_ft_s_f2:
2395	mfc1	ta0, $f2
2396	b	get_ft_s_done
2397get_ft_s_f4:
2398	mfc1	ta0, $f4
2399	b	get_ft_s_done
2400get_ft_s_f6:
2401	mfc1	ta0, $f6
2402	b	get_ft_s_done
2403get_ft_s_f8:
2404	mfc1	ta0, $f8
2405	b	get_ft_s_done
2406get_ft_s_f10:
2407	mfc1	ta0, $f10
2408	b	get_ft_s_done
2409get_ft_s_f12:
2410	mfc1	ta0, $f12
2411	b	get_ft_s_done
2412get_ft_s_f14:
2413	mfc1	ta0, $f14
2414	b	get_ft_s_done
2415get_ft_s_f16:
2416	mfc1	ta0, $f16
2417	b	get_ft_s_done
2418get_ft_s_f18:
2419	mfc1	ta0, $f18
2420	b	get_ft_s_done
2421get_ft_s_f20:
2422	mfc1	ta0, $f20
2423	b	get_ft_s_done
2424get_ft_s_f22:
2425	mfc1	ta0, $f22
2426	b	get_ft_s_done
2427get_ft_s_f24:
2428	mfc1	ta0, $f24
2429	b	get_ft_s_done
2430get_ft_s_f26:
2431	mfc1	ta0, $f26
2432	b	get_ft_s_done
2433get_ft_s_f28:
2434	mfc1	ta0, $f28
2435	b	get_ft_s_done
2436get_ft_s_f30:
2437	mfc1	ta0, $f30
2438get_ft_s_done:
2439	srl	ta1, ta0, 23			# get exponent
2440	and	ta1, ta1, 0xFF
2441	and	ta2, ta0, 0x7FFFFF		# get fraction
2442	srl	ta0, ta0, 31			# get sign
2443	bne	ta1, SEXP_INF, 1f		# is it a signaling NAN?
2444	and	v0, ta2, SSIGNAL_NAN
2445	bne	v0, zero, invalid_s
24461:
2447	/* fall through to get FS */
2448
2449/*----------------------------------------------------------------------------
2450 * get_fs_s --
2451 *
2452 *	Read (single precision) the FS register (bits 15-11) and
2453 *	break up into fields.
2454 *	This is an internal routine used by MipsEmulateFP only.
2455 *
2456 * Results:
2457 *	t0	contains the sign
2458 *	t1	contains the (biased) exponent
2459 *	t2	contains the fraction
2460 *
2461 *----------------------------------------------------------------------------
2462 */
2463ALEAF(get_fs_s)
2464	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2465	and	a3, a3, 0xF << 2		# mask FS field
2466	lw	a3, get_fs_s_tbl(a3)		# switch on register number
2467	j	a3
2468
2469	.rdata
2470get_fs_s_tbl:
2471	.word	get_fs_s_f0
2472	.word	get_fs_s_f2
2473	.word	get_fs_s_f4
2474	.word	get_fs_s_f6
2475	.word	get_fs_s_f8
2476	.word	get_fs_s_f10
2477	.word	get_fs_s_f12
2478	.word	get_fs_s_f14
2479	.word	get_fs_s_f16
2480	.word	get_fs_s_f18
2481	.word	get_fs_s_f20
2482	.word	get_fs_s_f22
2483	.word	get_fs_s_f24
2484	.word	get_fs_s_f26
2485	.word	get_fs_s_f28
2486	.word	get_fs_s_f30
2487	.text
2488
2489get_fs_s_f0:
2490	mfc1	t0, $f0
2491	b	get_fs_s_done
2492get_fs_s_f2:
2493	mfc1	t0, $f2
2494	b	get_fs_s_done
2495get_fs_s_f4:
2496	mfc1	t0, $f4
2497	b	get_fs_s_done
2498get_fs_s_f6:
2499	mfc1	t0, $f6
2500	b	get_fs_s_done
2501get_fs_s_f8:
2502	mfc1	t0, $f8
2503	b	get_fs_s_done
2504get_fs_s_f10:
2505	mfc1	t0, $f10
2506	b	get_fs_s_done
2507get_fs_s_f12:
2508	mfc1	t0, $f12
2509	b	get_fs_s_done
2510get_fs_s_f14:
2511	mfc1	t0, $f14
2512	b	get_fs_s_done
2513get_fs_s_f16:
2514	mfc1	t0, $f16
2515	b	get_fs_s_done
2516get_fs_s_f18:
2517	mfc1	t0, $f18
2518	b	get_fs_s_done
2519get_fs_s_f20:
2520	mfc1	t0, $f20
2521	b	get_fs_s_done
2522get_fs_s_f22:
2523	mfc1	t0, $f22
2524	b	get_fs_s_done
2525get_fs_s_f24:
2526	mfc1	t0, $f24
2527	b	get_fs_s_done
2528get_fs_s_f26:
2529	mfc1	t0, $f26
2530	b	get_fs_s_done
2531get_fs_s_f28:
2532	mfc1	t0, $f28
2533	b	get_fs_s_done
2534get_fs_s_f30:
2535	mfc1	t0, $f30
2536get_fs_s_done:
2537	srl	t1, t0, 23			# get exponent
2538	and	t1, t1, 0xFF
2539	and	t2, t0, 0x7FFFFF		# get fraction
2540	srl	t0, t0, 31			# get sign
2541	bne	t1, SEXP_INF, 1f		# is it a signaling NAN?
2542	and	v0, t2, SSIGNAL_NAN
2543	bne	v0, zero, invalid_s
25441:
2545	j	ra
2546END(get_ft_fs_s)
2547
2548/*----------------------------------------------------------------------------
2549 * get_ft_fs_d --
2550 *
2551 *	Read (double precision) the FT register (bits 20-16) and
2552 *	the FS register (bits 15-11) and break up into fields.
2553 *	This is an internal routine used by MipsEmulateFP only.
2554 *
2555 * Results:
2556 *	t0	contains the FS sign
2557 *	t1	contains the FS (biased) exponent
2558 *	t2	contains the FS fraction
2559 *	t3	contains the FS remaining fraction
2560 *	ta0	contains the FT sign
2561 *	ta1	contains the FT (biased) exponent
2562 *	ta2	contains the FT fraction
2563 *	ta3	contains the FT remaining fraction
2564 *
2565 *----------------------------------------------------------------------------
2566 */
2567LEAF(get_ft_fs_d)
2568	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2569	and	a3, a3, 0xF << 2		# mask FT field
2570	lw	a3, get_ft_d_tbl(a3)		# switch on register number
2571	j	a3
2572
2573	.rdata
2574get_ft_d_tbl:
2575	.word	get_ft_d_f0
2576	.word	get_ft_d_f2
2577	.word	get_ft_d_f4
2578	.word	get_ft_d_f6
2579	.word	get_ft_d_f8
2580	.word	get_ft_d_f10
2581	.word	get_ft_d_f12
2582	.word	get_ft_d_f14
2583	.word	get_ft_d_f16
2584	.word	get_ft_d_f18
2585	.word	get_ft_d_f20
2586	.word	get_ft_d_f22
2587	.word	get_ft_d_f24
2588	.word	get_ft_d_f26
2589	.word	get_ft_d_f28
2590	.word	get_ft_d_f30
2591	.text
2592
2593get_ft_d_f0:
2594	mfc1	ta3, $f0
2595	mfc1	ta0, $f1
2596	b	get_ft_d_done
2597get_ft_d_f2:
2598	mfc1	ta3, $f2
2599	mfc1	ta0, $f3
2600	b	get_ft_d_done
2601get_ft_d_f4:
2602	mfc1	ta3, $f4
2603	mfc1	ta0, $f5
2604	b	get_ft_d_done
2605get_ft_d_f6:
2606	mfc1	ta3, $f6
2607	mfc1	ta0, $f7
2608	b	get_ft_d_done
2609get_ft_d_f8:
2610	mfc1	ta3, $f8
2611	mfc1	ta0, $f9
2612	b	get_ft_d_done
2613get_ft_d_f10:
2614	mfc1	ta3, $f10
2615	mfc1	ta0, $f11
2616	b	get_ft_d_done
2617get_ft_d_f12:
2618	mfc1	ta3, $f12
2619	mfc1	ta0, $f13
2620	b	get_ft_d_done
2621get_ft_d_f14:
2622	mfc1	ta3, $f14
2623	mfc1	ta0, $f15
2624	b	get_ft_d_done
2625get_ft_d_f16:
2626	mfc1	ta3, $f16
2627	mfc1	ta0, $f17
2628	b	get_ft_d_done
2629get_ft_d_f18:
2630	mfc1	ta3, $f18
2631	mfc1	ta0, $f19
2632	b	get_ft_d_done
2633get_ft_d_f20:
2634	mfc1	ta3, $f20
2635	mfc1	ta0, $f21
2636	b	get_ft_d_done
2637get_ft_d_f22:
2638	mfc1	ta3, $f22
2639	mfc1	ta0, $f23
2640	b	get_ft_d_done
2641get_ft_d_f24:
2642	mfc1	ta3, $f24
2643	mfc1	ta0, $f25
2644	b	get_ft_d_done
2645get_ft_d_f26:
2646	mfc1	ta3, $f26
2647	mfc1	ta0, $f27
2648	b	get_ft_d_done
2649get_ft_d_f28:
2650	mfc1	ta3, $f28
2651	mfc1	ta0, $f29
2652	b	get_ft_d_done
2653get_ft_d_f30:
2654	mfc1	ta3, $f30
2655	mfc1	ta0, $f31
2656get_ft_d_done:
2657	srl	ta1, ta0, 20			# get exponent
2658	and	ta1, ta1, 0x7FF
2659	and	ta2, ta0, 0xFFFFF		# get fraction
2660	srl	ta0, ta0, 31			# get sign
2661	bne	ta1, DEXP_INF, 1f		# is it a signaling NAN?
2662	and	v0, ta2, DSIGNAL_NAN
2663	bne	v0, zero, invalid_d
26641:
2665	/* fall through to get FS */
2666
2667/*----------------------------------------------------------------------------
2668 * get_fs_d --
2669 *
2670 *	Read (double precision) the FS register (bits 15-11) and
2671 *	break up into fields.
2672 *	This is an internal routine used by MipsEmulateFP only.
2673 *
2674 * Results:
2675 *	t0	contains the sign
2676 *	t1	contains the (biased) exponent
2677 *	t2	contains the fraction
2678 *	t3	contains the remaining fraction
2679 *
2680 *----------------------------------------------------------------------------
2681 */
2682ALEAF(get_fs_d)
2683	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2684	and	a3, a3, 0xF << 2		# mask FS field
2685	lw	a3, get_fs_d_tbl(a3)		# switch on register number
2686	j	a3
2687
2688	.rdata
2689get_fs_d_tbl:
2690	.word	get_fs_d_f0
2691	.word	get_fs_d_f2
2692	.word	get_fs_d_f4
2693	.word	get_fs_d_f6
2694	.word	get_fs_d_f8
2695	.word	get_fs_d_f10
2696	.word	get_fs_d_f12
2697	.word	get_fs_d_f14
2698	.word	get_fs_d_f16
2699	.word	get_fs_d_f18
2700	.word	get_fs_d_f20
2701	.word	get_fs_d_f22
2702	.word	get_fs_d_f24
2703	.word	get_fs_d_f26
2704	.word	get_fs_d_f28
2705	.word	get_fs_d_f30
2706	.text
2707
2708get_fs_d_f0:
2709	mfc1	t3, $f0
2710	mfc1	t0, $f1
2711	b	get_fs_d_done
2712get_fs_d_f2:
2713	mfc1	t3, $f2
2714	mfc1	t0, $f3
2715	b	get_fs_d_done
2716get_fs_d_f4:
2717	mfc1	t3, $f4
2718	mfc1	t0, $f5
2719	b	get_fs_d_done
2720get_fs_d_f6:
2721	mfc1	t3, $f6
2722	mfc1	t0, $f7
2723	b	get_fs_d_done
2724get_fs_d_f8:
2725	mfc1	t3, $f8
2726	mfc1	t0, $f9
2727	b	get_fs_d_done
2728get_fs_d_f10:
2729	mfc1	t3, $f10
2730	mfc1	t0, $f11
2731	b	get_fs_d_done
2732get_fs_d_f12:
2733	mfc1	t3, $f12
2734	mfc1	t0, $f13
2735	b	get_fs_d_done
2736get_fs_d_f14:
2737	mfc1	t3, $f14
2738	mfc1	t0, $f15
2739	b	get_fs_d_done
2740get_fs_d_f16:
2741	mfc1	t3, $f16
2742	mfc1	t0, $f17
2743	b	get_fs_d_done
2744get_fs_d_f18:
2745	mfc1	t3, $f18
2746	mfc1	t0, $f19
2747	b	get_fs_d_done
2748get_fs_d_f20:
2749	mfc1	t3, $f20
2750	mfc1	t0, $f21
2751	b	get_fs_d_done
2752get_fs_d_f22:
2753	mfc1	t3, $f22
2754	mfc1	t0, $f23
2755	b	get_fs_d_done
2756get_fs_d_f24:
2757	mfc1	t3, $f24
2758	mfc1	t0, $f25
2759	b	get_fs_d_done
2760get_fs_d_f26:
2761	mfc1	t3, $f26
2762	mfc1	t0, $f27
2763	b	get_fs_d_done
2764get_fs_d_f28:
2765	mfc1	t3, $f28
2766	mfc1	t0, $f29
2767	b	get_fs_d_done
2768get_fs_d_f30:
2769	mfc1	t3, $f30
2770	mfc1	t0, $f31
2771get_fs_d_done:
2772	srl	t1, t0, 20			# get exponent
2773	and	t1, t1, 0x7FF
2774	and	t2, t0, 0xFFFFF			# get fraction
2775	srl	t0, t0, 31			# get sign
2776	bne	t1, DEXP_INF, 1f		# is it a signaling NAN?
2777	and	v0, t2, DSIGNAL_NAN
2778	bne	v0, zero, invalid_d
27791:
2780	j	ra
2781END(get_ft_fs_d)
2782
2783/*----------------------------------------------------------------------------
2784 * get_cmp_s --
2785 *
2786 *	Read (single precision) the FS register (bits 15-11) and
2787 *	the FT register (bits 20-16) and break up into fields.
2788 *	This is an internal routine used by MipsEmulateFP only.
2789 *
2790 * Results:
2791 *	t0	contains the sign
2792 *	t1	contains the (biased) exponent
2793 *	t2	contains the fraction
2794 *	ta0	contains the sign
2795 *	ta1	contains the (biased) exponent
2796 *	ta2	contains the fraction
2797 *
2798 *----------------------------------------------------------------------------
2799 */
2800LEAF(get_cmp_s)
2801	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2802	and	a3, a3, 0xF << 2		# mask FS field
2803	lw	a3, cmp_fs_s_tbl(a3)		# switch on register number
2804	j	a3
2805
2806	.rdata
2807cmp_fs_s_tbl:
2808	.word	cmp_fs_s_f0
2809	.word	cmp_fs_s_f2
2810	.word	cmp_fs_s_f4
2811	.word	cmp_fs_s_f6
2812	.word	cmp_fs_s_f8
2813	.word	cmp_fs_s_f10
2814	.word	cmp_fs_s_f12
2815	.word	cmp_fs_s_f14
2816	.word	cmp_fs_s_f16
2817	.word	cmp_fs_s_f18
2818	.word	cmp_fs_s_f20
2819	.word	cmp_fs_s_f22
2820	.word	cmp_fs_s_f24
2821	.word	cmp_fs_s_f26
2822	.word	cmp_fs_s_f28
2823	.word	cmp_fs_s_f30
2824	.text
2825
2826cmp_fs_s_f0:
2827	mfc1	t0, $f0
2828	b	cmp_fs_s_done
2829cmp_fs_s_f2:
2830	mfc1	t0, $f2
2831	b	cmp_fs_s_done
2832cmp_fs_s_f4:
2833	mfc1	t0, $f4
2834	b	cmp_fs_s_done
2835cmp_fs_s_f6:
2836	mfc1	t0, $f6
2837	b	cmp_fs_s_done
2838cmp_fs_s_f8:
2839	mfc1	t0, $f8
2840	b	cmp_fs_s_done
2841cmp_fs_s_f10:
2842	mfc1	t0, $f10
2843	b	cmp_fs_s_done
2844cmp_fs_s_f12:
2845	mfc1	t0, $f12
2846	b	cmp_fs_s_done
2847cmp_fs_s_f14:
2848	mfc1	t0, $f14
2849	b	cmp_fs_s_done
2850cmp_fs_s_f16:
2851	mfc1	t0, $f16
2852	b	cmp_fs_s_done
2853cmp_fs_s_f18:
2854	mfc1	t0, $f18
2855	b	cmp_fs_s_done
2856cmp_fs_s_f20:
2857	mfc1	t0, $f20
2858	b	cmp_fs_s_done
2859cmp_fs_s_f22:
2860	mfc1	t0, $f22
2861	b	cmp_fs_s_done
2862cmp_fs_s_f24:
2863	mfc1	t0, $f24
2864	b	cmp_fs_s_done
2865cmp_fs_s_f26:
2866	mfc1	t0, $f26
2867	b	cmp_fs_s_done
2868cmp_fs_s_f28:
2869	mfc1	t0, $f28
2870	b	cmp_fs_s_done
2871cmp_fs_s_f30:
2872	mfc1	t0, $f30
2873cmp_fs_s_done:
2874	srl	t1, t0, 23			# get exponent
2875	and	t1, t1, 0xFF
2876	and	t2, t0, 0x7FFFFF		# get fraction
2877	srl	t0, t0, 31			# get sign
2878
2879	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2880	and	a3, a3, 0xF << 2		# mask FT field
2881	lw	a3, cmp_ft_s_tbl(a3)		# switch on register number
2882	j	a3
2883
2884	.rdata
2885cmp_ft_s_tbl:
2886	.word	cmp_ft_s_f0
2887	.word	cmp_ft_s_f2
2888	.word	cmp_ft_s_f4
2889	.word	cmp_ft_s_f6
2890	.word	cmp_ft_s_f8
2891	.word	cmp_ft_s_f10
2892	.word	cmp_ft_s_f12
2893	.word	cmp_ft_s_f14
2894	.word	cmp_ft_s_f16
2895	.word	cmp_ft_s_f18
2896	.word	cmp_ft_s_f20
2897	.word	cmp_ft_s_f22
2898	.word	cmp_ft_s_f24
2899	.word	cmp_ft_s_f26
2900	.word	cmp_ft_s_f28
2901	.word	cmp_ft_s_f30
2902	.text
2903
2904cmp_ft_s_f0:
2905	mfc1	ta0, $f0
2906	b	cmp_ft_s_done
2907cmp_ft_s_f2:
2908	mfc1	ta0, $f2
2909	b	cmp_ft_s_done
2910cmp_ft_s_f4:
2911	mfc1	ta0, $f4
2912	b	cmp_ft_s_done
2913cmp_ft_s_f6:
2914	mfc1	ta0, $f6
2915	b	cmp_ft_s_done
2916cmp_ft_s_f8:
2917	mfc1	ta0, $f8
2918	b	cmp_ft_s_done
2919cmp_ft_s_f10:
2920	mfc1	ta0, $f10
2921	b	cmp_ft_s_done
2922cmp_ft_s_f12:
2923	mfc1	ta0, $f12
2924	b	cmp_ft_s_done
2925cmp_ft_s_f14:
2926	mfc1	ta0, $f14
2927	b	cmp_ft_s_done
2928cmp_ft_s_f16:
2929	mfc1	ta0, $f16
2930	b	cmp_ft_s_done
2931cmp_ft_s_f18:
2932	mfc1	ta0, $f18
2933	b	cmp_ft_s_done
2934cmp_ft_s_f20:
2935	mfc1	ta0, $f20
2936	b	cmp_ft_s_done
2937cmp_ft_s_f22:
2938	mfc1	ta0, $f22
2939	b	cmp_ft_s_done
2940cmp_ft_s_f24:
2941	mfc1	ta0, $f24
2942	b	cmp_ft_s_done
2943cmp_ft_s_f26:
2944	mfc1	ta0, $f26
2945	b	cmp_ft_s_done
2946cmp_ft_s_f28:
2947	mfc1	ta0, $f28
2948	b	cmp_ft_s_done
2949cmp_ft_s_f30:
2950	mfc1	ta0, $f30
2951cmp_ft_s_done:
2952	srl	ta1, ta0, 23			# get exponent
2953	and	ta1, ta1, 0xFF
2954	and	ta2, ta0, 0x7FFFFF		# get fraction
2955	srl	ta0, ta0, 31			# get sign
2956	j	ra
2957END(get_cmp_s)
2958
2959/*----------------------------------------------------------------------------
2960 * get_cmp_d --
2961 *
2962 *	Read (double precision) the FS register (bits 15-11) and
2963 *	the FT register (bits 20-16) and break up into fields.
2964 *	This is an internal routine used by MipsEmulateFP only.
2965 *
2966 * Results:
2967 *	t0	contains the sign
2968 *	t1	contains the (biased) exponent
2969 *	t2	contains the fraction
2970 *	t3	contains the remaining fraction
2971 *	ta0	contains the sign
2972 *	ta1	contains the (biased) exponent
2973 *	ta2	contains the fraction
2974 *	ta3	contains the remaining fraction
2975 *
2976 *----------------------------------------------------------------------------
2977 */
2978LEAF(get_cmp_d)
2979	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2980	and	a3, a3, 0xF << 2		# mask FS field
2981	lw	a3, cmp_fs_d_tbl(a3)		# switch on register number
2982	j	a3
2983
2984	.rdata
2985cmp_fs_d_tbl:
2986	.word	cmp_fs_d_f0
2987	.word	cmp_fs_d_f2
2988	.word	cmp_fs_d_f4
2989	.word	cmp_fs_d_f6
2990	.word	cmp_fs_d_f8
2991	.word	cmp_fs_d_f10
2992	.word	cmp_fs_d_f12
2993	.word	cmp_fs_d_f14
2994	.word	cmp_fs_d_f16
2995	.word	cmp_fs_d_f18
2996	.word	cmp_fs_d_f20
2997	.word	cmp_fs_d_f22
2998	.word	cmp_fs_d_f24
2999	.word	cmp_fs_d_f26
3000	.word	cmp_fs_d_f28
3001	.word	cmp_fs_d_f30
3002	.text
3003
3004cmp_fs_d_f0:
3005	mfc1	t3, $f0
3006	mfc1	t0, $f1
3007	b	cmp_fs_d_done
3008cmp_fs_d_f2:
3009	mfc1	t3, $f2
3010	mfc1	t0, $f3
3011	b	cmp_fs_d_done
3012cmp_fs_d_f4:
3013	mfc1	t3, $f4
3014	mfc1	t0, $f5
3015	b	cmp_fs_d_done
3016cmp_fs_d_f6:
3017	mfc1	t3, $f6
3018	mfc1	t0, $f7
3019	b	cmp_fs_d_done
3020cmp_fs_d_f8:
3021	mfc1	t3, $f8
3022	mfc1	t0, $f9
3023	b	cmp_fs_d_done
3024cmp_fs_d_f10:
3025	mfc1	t3, $f10
3026	mfc1	t0, $f11
3027	b	cmp_fs_d_done
3028cmp_fs_d_f12:
3029	mfc1	t3, $f12
3030	mfc1	t0, $f13
3031	b	cmp_fs_d_done
3032cmp_fs_d_f14:
3033	mfc1	t3, $f14
3034	mfc1	t0, $f15
3035	b	cmp_fs_d_done
3036cmp_fs_d_f16:
3037	mfc1	t3, $f16
3038	mfc1	t0, $f17
3039	b	cmp_fs_d_done
3040cmp_fs_d_f18:
3041	mfc1	t3, $f18
3042	mfc1	t0, $f19
3043	b	cmp_fs_d_done
3044cmp_fs_d_f20:
3045	mfc1	t3, $f20
3046	mfc1	t0, $f21
3047	b	cmp_fs_d_done
3048cmp_fs_d_f22:
3049	mfc1	t3, $f22
3050	mfc1	t0, $f23
3051	b	cmp_fs_d_done
3052cmp_fs_d_f24:
3053	mfc1	t3, $f24
3054	mfc1	t0, $f25
3055	b	cmp_fs_d_done
3056cmp_fs_d_f26:
3057	mfc1	t3, $f26
3058	mfc1	t0, $f27
3059	b	cmp_fs_d_done
3060cmp_fs_d_f28:
3061	mfc1	t3, $f28
3062	mfc1	t0, $f29
3063	b	cmp_fs_d_done
3064cmp_fs_d_f30:
3065	mfc1	t3, $f30
3066	mfc1	t0, $f31
3067cmp_fs_d_done:
3068	srl	t1, t0, 20			# get exponent
3069	and	t1, t1, 0x7FF
3070	and	t2, t0, 0xFFFFF			# get fraction
3071	srl	t0, t0, 31			# get sign
3072
3073	srl	a3, a0, 17 - 2			# get FT field (even regs only)
3074	and	a3, a3, 0xF << 2		# mask FT field
3075	lw	a3, cmp_ft_d_tbl(a3)		# switch on register number
3076	j	a3
3077
3078	.rdata
3079cmp_ft_d_tbl:
3080	.word	cmp_ft_d_f0
3081	.word	cmp_ft_d_f2
3082	.word	cmp_ft_d_f4
3083	.word	cmp_ft_d_f6
3084	.word	cmp_ft_d_f8
3085	.word	cmp_ft_d_f10
3086	.word	cmp_ft_d_f12
3087	.word	cmp_ft_d_f14
3088	.word	cmp_ft_d_f16
3089	.word	cmp_ft_d_f18
3090	.word	cmp_ft_d_f20
3091	.word	cmp_ft_d_f22
3092	.word	cmp_ft_d_f24
3093	.word	cmp_ft_d_f26
3094	.word	cmp_ft_d_f28
3095	.word	cmp_ft_d_f30
3096	.text
3097
3098cmp_ft_d_f0:
3099	mfc1	ta3, $f0
3100	mfc1	ta0, $f1
3101	b	cmp_ft_d_done
3102cmp_ft_d_f2:
3103	mfc1	ta3, $f2
3104	mfc1	ta0, $f3
3105	b	cmp_ft_d_done
3106cmp_ft_d_f4:
3107	mfc1	ta3, $f4
3108	mfc1	ta0, $f5
3109	b	cmp_ft_d_done
3110cmp_ft_d_f6:
3111	mfc1	ta3, $f6
3112	mfc1	ta0, $f7
3113	b	cmp_ft_d_done
3114cmp_ft_d_f8:
3115	mfc1	ta3, $f8
3116	mfc1	ta0, $f9
3117	b	cmp_ft_d_done
3118cmp_ft_d_f10:
3119	mfc1	ta3, $f10
3120	mfc1	ta0, $f11
3121	b	cmp_ft_d_done
3122cmp_ft_d_f12:
3123	mfc1	ta3, $f12
3124	mfc1	ta0, $f13
3125	b	cmp_ft_d_done
3126cmp_ft_d_f14:
3127	mfc1	ta3, $f14
3128	mfc1	ta0, $f15
3129	b	cmp_ft_d_done
3130cmp_ft_d_f16:
3131	mfc1	ta3, $f16
3132	mfc1	ta0, $f17
3133	b	cmp_ft_d_done
3134cmp_ft_d_f18:
3135	mfc1	ta3, $f18
3136	mfc1	ta0, $f19
3137	b	cmp_ft_d_done
3138cmp_ft_d_f20:
3139	mfc1	ta3, $f20
3140	mfc1	ta0, $f21
3141	b	cmp_ft_d_done
3142cmp_ft_d_f22:
3143	mfc1	ta3, $f22
3144	mfc1	ta0, $f23
3145	b	cmp_ft_d_done
3146cmp_ft_d_f24:
3147	mfc1	ta3, $f24
3148	mfc1	ta0, $f25
3149	b	cmp_ft_d_done
3150cmp_ft_d_f26:
3151	mfc1	ta3, $f26
3152	mfc1	ta0, $f27
3153	b	cmp_ft_d_done
3154cmp_ft_d_f28:
3155	mfc1	ta3, $f28
3156	mfc1	ta0, $f29
3157	b	cmp_ft_d_done
3158cmp_ft_d_f30:
3159	mfc1	ta3, $f30
3160	mfc1	ta0, $f31
3161cmp_ft_d_done:
3162	srl	ta1, ta0, 20			# get exponent
3163	and	ta1, ta1, 0x7FF
3164	and	ta2, ta0, 0xFFFFF		# get fraction
3165	srl	ta0, ta0, 31			# get sign
3166	j	ra
3167END(get_cmp_d)
3168
3169/*----------------------------------------------------------------------------
3170 * set_fd_s --
3171 *
3172 *	Write (single precision) the FD register (bits 10-6).
3173 *	This is an internal routine used by MipsEmulateFP only.
3174 *
3175 * Arguments:
3176 *	a0	contains the FP instruction
3177 *	t0	contains the sign
3178 *	t1	contains the (biased) exponent
3179 *	t2	contains the fraction
3180 *
3181 * set_fd_word --
3182 *
3183 *	Write (integer) the FD register (bits 10-6).
3184 *	This is an internal routine used by MipsEmulateFP only.
3185 *
3186 * Arguments:
3187 *	a0	contains the FP instruction
3188 *	t2	contains the integer
3189 *
3190 *----------------------------------------------------------------------------
3191 */
3192LEAF(set_fd_s)
3193	sll	t0, t0, 31			# position sign
3194	sll	t1, t1, 23			# position exponent
3195	or	t2, t2, t0
3196	or	t2, t2, t1
3197ALEAF(set_fd_word)
3198	srl	a3, a0, 7 - 2			# get FD field (even regs only)
3199	and	a3, a3, 0xF << 2		# mask FT field
3200	lw	a3, set_fd_s_tbl(a3)		# switch on register number
3201	j	a3
3202
3203	.rdata
3204set_fd_s_tbl:
3205	.word	set_fd_s_f0
3206	.word	set_fd_s_f2
3207	.word	set_fd_s_f4
3208	.word	set_fd_s_f6
3209	.word	set_fd_s_f8
3210	.word	set_fd_s_f10
3211	.word	set_fd_s_f12
3212	.word	set_fd_s_f14
3213	.word	set_fd_s_f16
3214	.word	set_fd_s_f18
3215	.word	set_fd_s_f20
3216	.word	set_fd_s_f22
3217	.word	set_fd_s_f24
3218	.word	set_fd_s_f26
3219	.word	set_fd_s_f28
3220	.word	set_fd_s_f30
3221	.text
3222
3223set_fd_s_f0:
3224	mtc1	t2, $f0
3225	j	ra
3226set_fd_s_f2:
3227	mtc1	t2, $f2
3228	j	ra
3229set_fd_s_f4:
3230	mtc1	t2, $f4
3231	j	ra
3232set_fd_s_f6:
3233	mtc1	t2, $f6
3234	j	ra
3235set_fd_s_f8:
3236	mtc1	t2, $f8
3237	j	ra
3238set_fd_s_f10:
3239	mtc1	t2, $f10
3240	j	ra
3241set_fd_s_f12:
3242	mtc1	t2, $f12
3243	j	ra
3244set_fd_s_f14:
3245	mtc1	t2, $f14
3246	j	ra
3247set_fd_s_f16:
3248	mtc1	t2, $f16
3249	j	ra
3250set_fd_s_f18:
3251	mtc1	t2, $f18
3252	j	ra
3253set_fd_s_f20:
3254	mtc1	t2, $f20
3255	j	ra
3256set_fd_s_f22:
3257	mtc1	t2, $f22
3258	j	ra
3259set_fd_s_f24:
3260	mtc1	t2, $f24
3261	j	ra
3262set_fd_s_f26:
3263	mtc1	t2, $f26
3264	j	ra
3265set_fd_s_f28:
3266	mtc1	t2, $f28
3267	j	ra
3268set_fd_s_f30:
3269	mtc1	t2, $f30
3270	j	ra
3271END(set_fd_s)
3272
3273/*----------------------------------------------------------------------------
3274 * set_fd_d --
3275 *
3276 *	Write (double precision) the FT register (bits 10-6).
3277 *	This is an internal routine used by MipsEmulateFP only.
3278 *
3279 * Arguments:
3280 *	a0	contains the FP instruction
3281 *	t0	contains the sign
3282 *	t1	contains the (biased) exponent
3283 *	t2	contains the fraction
3284 *	t3	contains the remaining fraction
3285 *
3286 *----------------------------------------------------------------------------
3287 */
3288LEAF(set_fd_d)
3289	sll	t0, t0, 31			# set sign
3290	sll	t1, t1, 20			# set exponent
3291	or	t0, t0, t1
3292	or	t0, t0, t2			# set fraction
3293	srl	a3, a0, 7 - 2			# get FD field (even regs only)
3294	and	a3, a3, 0xF << 2		# mask FD field
3295	lw	a3, set_fd_d_tbl(a3)		# switch on register number
3296	j	a3
3297
3298	.rdata
3299set_fd_d_tbl:
3300	.word	set_fd_d_f0
3301	.word	set_fd_d_f2
3302	.word	set_fd_d_f4
3303	.word	set_fd_d_f6
3304	.word	set_fd_d_f8
3305	.word	set_fd_d_f10
3306	.word	set_fd_d_f12
3307	.word	set_fd_d_f14
3308	.word	set_fd_d_f16
3309	.word	set_fd_d_f18
3310	.word	set_fd_d_f20
3311	.word	set_fd_d_f22
3312	.word	set_fd_d_f24
3313	.word	set_fd_d_f26
3314	.word	set_fd_d_f28
3315	.word	set_fd_d_f30
3316	.text
3317
3318set_fd_d_f0:
3319	mtc1	t3, $f0
3320	mtc1	t0, $f1
3321	j	ra
3322set_fd_d_f2:
3323	mtc1	t3, $f2
3324	mtc1	t0, $f3
3325	j	ra
3326set_fd_d_f4:
3327	mtc1	t3, $f4
3328	mtc1	t0, $f5
3329	j	ra
3330set_fd_d_f6:
3331	mtc1	t3, $f6
3332	mtc1	t0, $f7
3333	j	ra
3334set_fd_d_f8:
3335	mtc1	t3, $f8
3336	mtc1	t0, $f9
3337	j	ra
3338set_fd_d_f10:
3339	mtc1	t3, $f10
3340	mtc1	t0, $f11
3341	j	ra
3342set_fd_d_f12:
3343	mtc1	t3, $f12
3344	mtc1	t0, $f13
3345	j	ra
3346set_fd_d_f14:
3347	mtc1	t3, $f14
3348	mtc1	t0, $f15
3349	j	ra
3350set_fd_d_f16:
3351	mtc1	t3, $f16
3352	mtc1	t0, $f17
3353	j	ra
3354set_fd_d_f18:
3355	mtc1	t3, $f18
3356	mtc1	t0, $f19
3357	j	ra
3358set_fd_d_f20:
3359	mtc1	t3, $f20
3360	mtc1	t0, $f21
3361	j	ra
3362set_fd_d_f22:
3363	mtc1	t3, $f22
3364	mtc1	t0, $f23
3365	j	ra
3366set_fd_d_f24:
3367	mtc1	t3, $f24
3368	mtc1	t0, $f25
3369	j	ra
3370set_fd_d_f26:
3371	mtc1	t3, $f26
3372	mtc1	t0, $f27
3373	j	ra
3374set_fd_d_f28:
3375	mtc1	t3, $f28
3376	mtc1	t0, $f29
3377	j	ra
3378set_fd_d_f30:
3379	mtc1	t3, $f30
3380	mtc1	t0, $f31
3381	j	ra
3382END(set_fd_d)
3383
3384/*----------------------------------------------------------------------------
3385 * renorm_fs_s --
3386 *
3387 * Results:
3388 *	t1	unbiased exponent
3389 *	t2	normalized fraction
3390 *
3391 *----------------------------------------------------------------------------
3392 */
3393LEAF(renorm_fs_s)
3394/*
3395 * Find out how many leading zero bits are in t2 and put in t9.
3396 */
3397	move	v0, t2
3398	move	t9, zero
3399	srl	v1, v0, 16
3400	bne	v1, zero, 1f
3401	addu	t9, 16
3402	sll	v0, 16
34031:
3404	srl	v1, v0, 24
3405	bne	v1, zero, 1f
3406	addu	t9, 8
3407	sll	v0, 8
34081:
3409	srl	v1, v0, 28
3410	bne	v1, zero, 1f
3411	addu	t9, 4
3412	sll	v0, 4
34131:
3414	srl	v1, v0, 30
3415	bne	v1, zero, 1f
3416	addu	t9, 2
3417	sll	v0, 2
34181:
3419	srl	v1, v0, 31
3420	bne	v1, zero, 1f
3421	addu	t9, 1
3422/*
3423 * Now shift t2 the correct number of bits.
3424 */
34251:
3426	subu	t9, t9, SLEAD_ZEROS	# dont count normal leading zeros
3427	li	t1, SEXP_MIN
3428	subu	t1, t1, t9		# adjust exponent
3429	sll	t2, t2, t9
3430	j	ra
3431END(renorm_fs_s)
3432
3433/*----------------------------------------------------------------------------
3434 * renorm_fs_d --
3435 *
3436 * Results:
3437 *	t1	unbiased exponent
3438 *	t2,t3	normalized fraction
3439 *
3440 *----------------------------------------------------------------------------
3441 */
3442LEAF(renorm_fs_d)
3443/*
3444 * Find out how many leading zero bits are in t2,t3 and put in t9.
3445 */
3446	move	v0, t2
3447	move	t9, zero
3448	bne	t2, zero, 1f
3449	move	v0, t3
3450	addu	t9, 32
34511:
3452	srl	v1, v0, 16
3453	bne	v1, zero, 1f
3454	addu	t9, 16
3455	sll	v0, 16
34561:
3457	srl	v1, v0, 24
3458	bne	v1, zero, 1f
3459	addu	t9, 8
3460	sll	v0, 8
34611:
3462	srl	v1, v0, 28
3463	bne	v1, zero, 1f
3464	addu	t9, 4
3465	sll	v0, 4
34661:
3467	srl	v1, v0, 30
3468	bne	v1, zero, 1f
3469	addu	t9, 2
3470	sll	v0, 2
34711:
3472	srl	v1, v0, 31
3473	bne	v1, zero, 1f
3474	addu	t9, 1
3475/*
3476 * Now shift t2,t3 the correct number of bits.
3477 */
34781:
3479	subu	t9, t9, DLEAD_ZEROS	# dont count normal leading zeros
3480	li	t1, DEXP_MIN
3481	subu	t1, t1, t9		# adjust exponent
3482	li	v0, 32
3483	blt	t9, v0, 1f
3484	subu	t9, t9, v0		# shift fraction left >= 32 bits
3485	sll	t2, t3, t9
3486	move	t3, zero
3487	j	ra
34881:
3489	subu	v0, v0, t9		# shift fraction left < 32 bits
3490	sll	t2, t2, t9
3491	srl	v1, t3, v0
3492	or	t2, t2, v1
3493	sll	t3, t3, t9
3494	j	ra
3495END(renorm_fs_d)
3496
3497/*----------------------------------------------------------------------------
3498 * renorm_ft_s --
3499 *
3500 * Results:
3501 *	ta1	unbiased exponent
3502 *	ta2	normalized fraction
3503 *
3504 *----------------------------------------------------------------------------
3505 */
3506LEAF(renorm_ft_s)
3507/*
3508 * Find out how many leading zero bits are in ta2 and put in t9.
3509 */
3510	move	v0, ta2
3511	move	t9, zero
3512	srl	v1, v0, 16
3513	bne	v1, zero, 1f
3514	addu	t9, 16
3515	sll	v0, 16
35161:
3517	srl	v1, v0, 24
3518	bne	v1, zero, 1f
3519	addu	t9, 8
3520	sll	v0, 8
35211:
3522	srl	v1, v0, 28
3523	bne	v1, zero, 1f
3524	addu	t9, 4
3525	sll	v0, 4
35261:
3527	srl	v1, v0, 30
3528	bne	v1, zero, 1f
3529	addu	t9, 2
3530	sll	v0, 2
35311:
3532	srl	v1, v0, 31
3533	bne	v1, zero, 1f
3534	addu	t9, 1
3535/*
3536 * Now shift ta2 the correct number of bits.
3537 */
35381:
3539	subu	t9, t9, SLEAD_ZEROS	# dont count normal leading zeros
3540	li	ta1, SEXP_MIN
3541	subu	ta1, ta1, t9		# adjust exponent
3542	sll	ta2, ta2, t9
3543	j	ra
3544END(renorm_ft_s)
3545
3546/*----------------------------------------------------------------------------
3547 * renorm_ft_d --
3548 *
3549 * Results:
3550 *	ta1	unbiased exponent
3551 *	ta2,ta3	normalized fraction
3552 *
3553 *----------------------------------------------------------------------------
3554 */
3555LEAF(renorm_ft_d)
3556/*
3557 * Find out how many leading zero bits are in ta2,ta3 and put in t9.
3558 */
3559	move	v0, ta2
3560	move	t9, zero
3561	bne	ta2, zero, 1f
3562	move	v0, ta3
3563	addu	t9, 32
35641:
3565	srl	v1, v0, 16
3566	bne	v1, zero, 1f
3567	addu	t9, 16
3568	sll	v0, 16
35691:
3570	srl	v1, v0, 24
3571	bne	v1, zero, 1f
3572	addu	t9, 8
3573	sll	v0, 8
35741:
3575	srl	v1, v0, 28
3576	bne	v1, zero, 1f
3577	addu	t9, 4
3578	sll	v0, 4
35791:
3580	srl	v1, v0, 30
3581	bne	v1, zero, 1f
3582	addu	t9, 2
3583	sll	v0, 2
35841:
3585	srl	v1, v0, 31
3586	bne	v1, zero, 1f
3587	addu	t9, 1
3588/*
3589 * Now shift ta2,ta3 the correct number of bits.
3590 */
35911:
3592	subu	t9, t9, DLEAD_ZEROS	# dont count normal leading zeros
3593	li	ta1, DEXP_MIN
3594	subu	ta1, ta1, t9		# adjust exponent
3595	li	v0, 32
3596	blt	t9, v0, 1f
3597	subu	t9, t9, v0		# shift fraction left >= 32 bits
3598	sll	ta2, ta3, t9
3599	move	ta3, zero
3600	j	ra
36011:
3602	subu	v0, v0, t9		# shift fraction left < 32 bits
3603	sll	ta2, ta2, t9
3604	srl	v1, ta3, v0
3605	or	ta2, ta2, v1
3606	sll	ta3, ta3, t9
3607	j	ra
3608END(renorm_ft_d)
3609