xref: /original-bsd/sys/pmax/pmax/fp.s (revision 68d9582f)
1/*
2 * Copyright (c) 1992 Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Ralph Campbell.
7 *
8 * %sccs.include.redist.c%
9 *
10 *	@(#)fp.s	7.2 (Berkeley) 05/25/92
11 */
12
13/*
14 * Standard header stuff.
15 */
16
17#include "machine/regdef.h"
18#include "machine/machAsmDefs.h"
19#include "machine/machConst.h"
20#include "assym.h"
21
22#define SEXP_INF	0xff
23#define DEXP_INF	0x7ff
24#define SEXP_BIAS	127
25#define DEXP_BIAS	1023
26#define SEXP_MIN	-126
27#define DEXP_MIN	-1022
28#define SEXP_MAX	127
29#define DEXP_MAX	1023
30#define WEXP_MAX	30		/* maximum unbiased exponent for int */
31#define WEXP_MIN	-1		/* minimum unbiased exponent for int */
32#define SFRAC_BITS	23
33#define DFRAC_BITS	52
34#define SIMPL_ONE	0x00800000
35#define DIMPL_ONE	0x00100000
36#define SLEAD_ZEROS	31 - 23
37#define DLEAD_ZEROS	31 - 20
38#define STICKYBIT	1
39#define GUARDBIT	0x80000000
40#define SSIGNAL_NAN	0x00400000
41#define DSIGNAL_NAN	0x00080000
42#define SQUIET_NAN	0x003fffff
43#define DQUIET_NAN0	0x0007ffff
44#define DQUIET_NAN1	0xffffffff
45#define INT_MIN		0x80000000
46#define INT_MAX		0x7fffffff
47
48#define COND_UNORDERED	0x1
49#define COND_EQUAL	0x2
50#define COND_LESS	0x4
51#define COND_SIGNAL	0x8
52
53/*----------------------------------------------------------------------------
54 *
55 * MachEmulateFP --
56 *
57 *	Emulate unimplemented floating point operations.
58 *	This routine should only be called by MachFPInterrupt().
59 *
60 *	MachEmulateFP(instr)
61 *		unsigned instr;
62 *
63 * Results:
64 *	None.
65 *
66 * Side effects:
67 *	Floating point registers are modified according to instruction.
68 *
69 *----------------------------------------------------------------------------
70 */
71NON_LEAF(MachEmulateFP, STAND_FRAME_SIZE, ra)
72	subu	sp, sp, STAND_FRAME_SIZE
73	sw	ra, STAND_RA_OFFSET(sp)
74/*
75 * Decode the FMT field (bits 24-21) and FUNCTION field (bits 5-0).
76 */
77	srl	v0, a0, 21 - 2			# get FMT field
78	and	v0, v0, 0xF << 2		# mask FMT field
79	and	v1, a0, 0x3F			# mask FUNC field
80	sll	v1, v1, 5			# align for table lookup
81	bgt	v0, 4 << 2, ill			# illegal format
82
83	or	v1, v1, v0
84	cfc1	a1, MACH_FPC_CSR		# get exception register
85	lw	a3, func_fmt_tbl(v1)		# switch on FUNC & FMT
86	and	a1, a1, ~MACH_FPC_EXCEPTION_UNIMPL	# clear exception
87	ctc1	a1, MACH_FPC_CSR
88	j	a3
89
90	.rdata
91func_fmt_tbl:
92	.word	add_s		# 0
93	.word	add_d		# 0
94	.word	ill		# 0
95	.word	ill		# 0
96	.word	ill		# 0
97	.word	ill		# 0
98	.word	ill		# 0
99	.word	ill		# 0
100	.word	sub_s		# 1
101	.word	sub_d		# 1
102	.word	ill		# 1
103	.word	ill		# 1
104	.word	ill		# 1
105	.word	ill		# 1
106	.word	ill		# 1
107	.word	ill		# 1
108	.word	mul_s		# 2
109	.word	mul_d		# 2
110	.word	ill		# 2
111	.word	ill		# 2
112	.word	ill		# 2
113	.word	ill		# 2
114	.word	ill		# 2
115	.word	ill		# 2
116	.word	div_s		# 3
117	.word	div_d		# 3
118	.word	ill		# 3
119	.word	ill		# 3
120	.word	ill		# 3
121	.word	ill		# 3
122	.word	ill		# 3
123	.word	ill		# 3
124	.word	ill		# 4
125	.word	ill		# 4
126	.word	ill		# 4
127	.word	ill		# 4
128	.word	ill		# 4
129	.word	ill		# 4
130	.word	ill		# 4
131	.word	ill		# 4
132	.word	abs_s		# 5
133	.word	abs_d		# 5
134	.word	ill		# 5
135	.word	ill		# 5
136	.word	ill		# 5
137	.word	ill		# 5
138	.word	ill		# 5
139	.word	ill		# 5
140	.word	mov_s		# 6
141	.word	mov_d		# 6
142	.word	ill		# 6
143	.word	ill		# 6
144	.word	ill		# 6
145	.word	ill		# 6
146	.word	ill		# 6
147	.word	ill		# 6
148	.word	neg_s		# 7
149	.word	neg_d		# 7
150	.word	ill		# 7
151	.word	ill		# 7
152	.word	ill		# 7
153	.word	ill		# 7
154	.word	ill		# 7
155	.word	ill		# 7
156	.word	ill		# 8
157	.word	ill		# 8
158	.word	ill		# 8
159	.word	ill		# 8
160	.word	ill		# 8
161	.word	ill		# 8
162	.word	ill		# 8
163	.word	ill		# 8
164	.word	ill		# 9
165	.word	ill		# 9
166	.word	ill		# 9
167	.word	ill		# 9
168	.word	ill		# 9
169	.word	ill		# 9
170	.word	ill		# 9
171	.word	ill		# 9
172	.word	ill		# 10
173	.word	ill		# 10
174	.word	ill		# 10
175	.word	ill		# 10
176	.word	ill		# 10
177	.word	ill		# 10
178	.word	ill		# 10
179	.word	ill		# 10
180	.word	ill		# 11
181	.word	ill		# 11
182	.word	ill		# 11
183	.word	ill		# 11
184	.word	ill		# 11
185	.word	ill		# 11
186	.word	ill		# 11
187	.word	ill		# 11
188	.word	ill		# 12
189	.word	ill		# 12
190	.word	ill		# 12
191	.word	ill		# 12
192	.word	ill		# 12
193	.word	ill		# 12
194	.word	ill		# 12
195	.word	ill		# 12
196	.word	ill		# 13
197	.word	ill		# 13
198	.word	ill		# 13
199	.word	ill		# 13
200	.word	ill		# 13
201	.word	ill		# 13
202	.word	ill		# 13
203	.word	ill		# 13
204	.word	ill		# 14
205	.word	ill		# 14
206	.word	ill		# 14
207	.word	ill		# 14
208	.word	ill		# 14
209	.word	ill		# 14
210	.word	ill		# 14
211	.word	ill		# 14
212	.word	ill		# 15
213	.word	ill		# 15
214	.word	ill		# 15
215	.word	ill		# 15
216	.word	ill		# 15
217	.word	ill		# 15
218	.word	ill		# 15
219	.word	ill		# 15
220	.word	ill		# 16
221	.word	ill		# 16
222	.word	ill		# 16
223	.word	ill		# 16
224	.word	ill		# 16
225	.word	ill		# 16
226	.word	ill		# 16
227	.word	ill		# 16
228	.word	ill		# 17
229	.word	ill		# 17
230	.word	ill		# 17
231	.word	ill		# 17
232	.word	ill		# 17
233	.word	ill		# 17
234	.word	ill		# 17
235	.word	ill		# 17
236	.word	ill		# 18
237	.word	ill		# 18
238	.word	ill		# 18
239	.word	ill		# 18
240	.word	ill		# 18
241	.word	ill		# 18
242	.word	ill		# 18
243	.word	ill		# 18
244	.word	ill		# 19
245	.word	ill		# 19
246	.word	ill		# 19
247	.word	ill		# 19
248	.word	ill		# 19
249	.word	ill		# 19
250	.word	ill		# 19
251	.word	ill		# 19
252	.word	ill		# 20
253	.word	ill		# 20
254	.word	ill		# 20
255	.word	ill		# 20
256	.word	ill		# 20
257	.word	ill		# 20
258	.word	ill		# 20
259	.word	ill		# 20
260	.word	ill		# 21
261	.word	ill		# 21
262	.word	ill		# 21
263	.word	ill		# 21
264	.word	ill		# 21
265	.word	ill		# 21
266	.word	ill		# 21
267	.word	ill		# 21
268	.word	ill		# 22
269	.word	ill		# 22
270	.word	ill		# 22
271	.word	ill		# 22
272	.word	ill		# 22
273	.word	ill		# 22
274	.word	ill		# 22
275	.word	ill		# 22
276	.word	ill		# 23
277	.word	ill		# 23
278	.word	ill		# 23
279	.word	ill		# 23
280	.word	ill		# 23
281	.word	ill		# 23
282	.word	ill		# 23
283	.word	ill		# 23
284	.word	ill		# 24
285	.word	ill		# 24
286	.word	ill		# 24
287	.word	ill		# 24
288	.word	ill		# 24
289	.word	ill		# 24
290	.word	ill		# 24
291	.word	ill		# 24
292	.word	ill		# 25
293	.word	ill		# 25
294	.word	ill		# 25
295	.word	ill		# 25
296	.word	ill		# 25
297	.word	ill		# 25
298	.word	ill		# 25
299	.word	ill		# 25
300	.word	ill		# 26
301	.word	ill		# 26
302	.word	ill		# 26
303	.word	ill		# 26
304	.word	ill		# 26
305	.word	ill		# 26
306	.word	ill		# 26
307	.word	ill		# 26
308	.word	ill		# 27
309	.word	ill		# 27
310	.word	ill		# 27
311	.word	ill		# 27
312	.word	ill		# 27
313	.word	ill		# 27
314	.word	ill		# 27
315	.word	ill		# 27
316	.word	ill		# 28
317	.word	ill		# 28
318	.word	ill		# 28
319	.word	ill		# 28
320	.word	ill		# 28
321	.word	ill		# 28
322	.word	ill		# 28
323	.word	ill		# 28
324	.word	ill		# 29
325	.word	ill		# 29
326	.word	ill		# 29
327	.word	ill		# 29
328	.word	ill		# 29
329	.word	ill		# 29
330	.word	ill		# 29
331	.word	ill		# 29
332	.word	ill		# 30
333	.word	ill		# 30
334	.word	ill		# 30
335	.word	ill		# 30
336	.word	ill		# 30
337	.word	ill		# 30
338	.word	ill		# 30
339	.word	ill		# 30
340	.word	ill		# 31
341	.word	ill		# 31
342	.word	ill		# 31
343	.word	ill		# 31
344	.word	ill		# 31
345	.word	ill		# 31
346	.word	ill		# 31
347	.word	ill		# 31
348	.word	ill		# 32
349	.word	cvt_s_d		# 32
350	.word	ill		# 32
351	.word	ill		# 32
352	.word	cvt_s_w		# 32
353	.word	ill		# 32
354	.word	ill		# 32
355	.word	ill		# 32
356	.word	cvt_d_s		# 33
357	.word	ill		# 33
358	.word	ill		# 33
359	.word	ill		# 33
360	.word	cvt_d_w		# 33
361	.word	ill		# 33
362	.word	ill		# 33
363	.word	ill		# 33
364	.word	ill		# 34
365	.word	ill		# 34
366	.word	ill		# 34
367	.word	ill		# 34
368	.word	ill		# 34
369	.word	ill		# 34
370	.word	ill		# 34
371	.word	ill		# 34
372	.word	ill		# 35
373	.word	ill		# 35
374	.word	ill		# 35
375	.word	ill		# 35
376	.word	ill		# 35
377	.word	ill		# 35
378	.word	ill		# 35
379	.word	ill		# 35
380	.word	cvt_w_s		# 36
381	.word	cvt_w_d		# 36
382	.word	ill		# 36
383	.word	ill		# 36
384	.word	ill		# 36
385	.word	ill		# 36
386	.word	ill		# 36
387	.word	ill		# 36
388	.word	ill		# 37
389	.word	ill		# 37
390	.word	ill		# 37
391	.word	ill		# 37
392	.word	ill		# 37
393	.word	ill		# 37
394	.word	ill		# 37
395	.word	ill		# 37
396	.word	ill		# 38
397	.word	ill		# 38
398	.word	ill		# 38
399	.word	ill		# 38
400	.word	ill		# 38
401	.word	ill		# 38
402	.word	ill		# 38
403	.word	ill		# 38
404	.word	ill		# 39
405	.word	ill		# 39
406	.word	ill		# 39
407	.word	ill		# 39
408	.word	ill		# 39
409	.word	ill		# 39
410	.word	ill		# 39
411	.word	ill		# 39
412	.word	ill		# 40
413	.word	ill		# 40
414	.word	ill		# 40
415	.word	ill		# 40
416	.word	ill		# 40
417	.word	ill		# 40
418	.word	ill		# 40
419	.word	ill		# 40
420	.word	ill		# 41
421	.word	ill		# 41
422	.word	ill		# 41
423	.word	ill		# 41
424	.word	ill		# 41
425	.word	ill		# 41
426	.word	ill		# 41
427	.word	ill		# 41
428	.word	ill		# 42
429	.word	ill		# 42
430	.word	ill		# 42
431	.word	ill		# 42
432	.word	ill		# 42
433	.word	ill		# 42
434	.word	ill		# 42
435	.word	ill		# 42
436	.word	ill		# 43
437	.word	ill		# 43
438	.word	ill		# 43
439	.word	ill		# 43
440	.word	ill		# 43
441	.word	ill		# 43
442	.word	ill		# 43
443	.word	ill		# 43
444	.word	ill		# 44
445	.word	ill		# 44
446	.word	ill		# 44
447	.word	ill		# 44
448	.word	ill		# 44
449	.word	ill		# 44
450	.word	ill		# 44
451	.word	ill		# 44
452	.word	ill		# 45
453	.word	ill		# 45
454	.word	ill		# 45
455	.word	ill		# 45
456	.word	ill		# 45
457	.word	ill		# 45
458	.word	ill		# 45
459	.word	ill		# 45
460	.word	ill		# 46
461	.word	ill		# 46
462	.word	ill		# 46
463	.word	ill		# 46
464	.word	ill		# 46
465	.word	ill		# 46
466	.word	ill		# 46
467	.word	ill		# 46
468	.word	ill		# 47
469	.word	ill		# 47
470	.word	ill		# 47
471	.word	ill		# 47
472	.word	ill		# 47
473	.word	ill		# 47
474	.word	ill		# 47
475	.word	ill		# 47
476	.word	cmp_s		# 48
477	.word	cmp_d		# 48
478	.word	ill		# 48
479	.word	ill		# 48
480	.word	ill		# 48
481	.word	ill		# 48
482	.word	ill		# 48
483	.word	ill		# 48
484	.word	cmp_s		# 49
485	.word	cmp_d		# 49
486	.word	ill		# 49
487	.word	ill		# 49
488	.word	ill		# 49
489	.word	ill		# 49
490	.word	ill		# 49
491	.word	ill		# 49
492	.word	cmp_s		# 50
493	.word	cmp_d		# 50
494	.word	ill		# 50
495	.word	ill		# 50
496	.word	ill		# 50
497	.word	ill		# 50
498	.word	ill		# 50
499	.word	ill		# 50
500	.word	cmp_s		# 51
501	.word	cmp_d		# 51
502	.word	ill		# 51
503	.word	ill		# 51
504	.word	ill		# 51
505	.word	ill		# 51
506	.word	ill		# 51
507	.word	ill		# 51
508	.word	cmp_s		# 52
509	.word	cmp_d		# 52
510	.word	ill		# 52
511	.word	ill		# 52
512	.word	ill		# 52
513	.word	ill		# 52
514	.word	ill		# 52
515	.word	ill		# 52
516	.word	cmp_s		# 53
517	.word	cmp_d		# 53
518	.word	ill		# 53
519	.word	ill		# 53
520	.word	ill		# 53
521	.word	ill		# 53
522	.word	ill		# 53
523	.word	ill		# 53
524	.word	cmp_s		# 54
525	.word	cmp_d		# 54
526	.word	ill		# 54
527	.word	ill		# 54
528	.word	ill		# 54
529	.word	ill		# 54
530	.word	ill		# 54
531	.word	ill		# 54
532	.word	cmp_s		# 55
533	.word	cmp_d		# 55
534	.word	ill		# 55
535	.word	ill		# 55
536	.word	ill		# 55
537	.word	ill		# 55
538	.word	ill		# 55
539	.word	ill		# 55
540	.word	cmp_s		# 56
541	.word	cmp_d		# 56
542	.word	ill		# 56
543	.word	ill		# 56
544	.word	ill		# 56
545	.word	ill		# 56
546	.word	ill		# 56
547	.word	ill		# 56
548	.word	cmp_s		# 57
549	.word	cmp_d		# 57
550	.word	ill		# 57
551	.word	ill		# 57
552	.word	ill		# 57
553	.word	ill		# 57
554	.word	ill		# 57
555	.word	ill		# 57
556	.word	cmp_s		# 58
557	.word	cmp_d		# 58
558	.word	ill		# 58
559	.word	ill		# 58
560	.word	ill		# 58
561	.word	ill		# 58
562	.word	ill		# 58
563	.word	ill		# 58
564	.word	cmp_s		# 59
565	.word	cmp_d		# 59
566	.word	ill		# 59
567	.word	ill		# 59
568	.word	ill		# 59
569	.word	ill		# 59
570	.word	ill		# 59
571	.word	ill		# 59
572	.word	cmp_s		# 60
573	.word	cmp_d		# 60
574	.word	ill		# 60
575	.word	ill		# 60
576	.word	ill		# 60
577	.word	ill		# 60
578	.word	ill		# 60
579	.word	ill		# 60
580	.word	cmp_s		# 61
581	.word	cmp_d		# 61
582	.word	ill		# 61
583	.word	ill		# 61
584	.word	ill		# 61
585	.word	ill		# 61
586	.word	ill		# 61
587	.word	ill		# 61
588	.word	cmp_s		# 62
589	.word	cmp_d		# 62
590	.word	ill		# 62
591	.word	ill		# 62
592	.word	ill		# 62
593	.word	ill		# 62
594	.word	ill		# 62
595	.word	ill		# 62
596	.word	cmp_s		# 63
597	.word	cmp_d		# 63
598	.word	ill		# 63
599	.word	ill		# 63
600	.word	ill		# 63
601	.word	ill		# 63
602	.word	ill		# 63
603	.word	ill		# 63
604	.text
605
606/*
607 * Single precision subtract.
608 */
609sub_s:
610	jal	get_ft_fs_s
611	xor	t4, t4, 1			# negate FT sign bit
612	b	add_sub_s
613/*
614 * Single precision add.
615 */
616add_s:
617	jal	get_ft_fs_s
618add_sub_s:
619	bne	t1, SEXP_INF, 1f		# is FS an infinity?
620	bne	t5, SEXP_INF, result_fs_s	# if FT is not inf, result=FS
621	bne	t2, zero, result_fs_s		# if FS is NAN, result is FS
622	bne	t6, zero, result_ft_s		# if FT is NAN, result is FT
623	bne	t0, t4, invalid_s		# both infinities same sign?
624	b	result_fs_s			# result is in FS
6251:
626	beq	t5, SEXP_INF, result_ft_s	# if FT is inf, result=FT
627	bne	t1, zero, 4f			# is FS a denormalized num?
628	beq	t2, zero, 3f			# is FS zero?
629	bne	t5, zero, 2f			# is FT a denormalized num?
630	beq	t6, zero, result_fs_s		# FT is zero, result=FS
631	jal	renorm_fs_s
632	jal	renorm_ft_s
633	b	5f
6342:
635	jal	renorm_fs_s
636	subu	t5, t5, SEXP_BIAS		# unbias FT exponent
637	or	t6, t6, SIMPL_ONE		# set implied one bit
638	b	5f
6393:
640	bne	t5, zero, result_ft_s		# if FT != 0, result=FT
641	bne	t6, zero, result_ft_s
642	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
643	bne	v0, MACH_FPC_ROUND_RM, 1f	# round to -infinity?
644	or	t0, t0, t4			# compute result sign
645	b	result_fs_s
6461:
647	and	t0, t0, t4			# compute result sign
648	b	result_fs_s
6494:
650	bne	t5, zero, 2f			# is FT a denormalized num?
651	beq	t6, zero, result_fs_s		# FT is zero, result=FS
652	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
653	or	t2, t2, SIMPL_ONE		# set implied one bit
654	jal	renorm_ft_s
655	b	5f
6562:
657	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
658	or	t2, t2, SIMPL_ONE		# set implied one bit
659	subu	t5, t5, SEXP_BIAS		# unbias FT exponent
660	or	t6, t6, SIMPL_ONE		# set implied one bit
661/*
662 * Perform the addition.
663 */
6645:
665	move	t8, zero			# no shifted bits (sticky reg)
666	beq	t1, t5, 4f			# no shift needed
667	subu	v0, t1, t5			# v0 = difference of exponents
668	move	v1, v0				# v1 = abs(difference)
669	bge	v0, zero, 1f
670	negu	v1
6711:
672	ble	v1, SFRAC_BITS+2, 2f		# is difference too great?
673	li	t8, STICKYBIT			# set the sticky bit
674	bge	v0, zero, 1f			# check which exp is larger
675	move	t1, t5				# result exp is FT's
676	move	t2, zero			# FS's fraction shifted is zero
677	b	4f
6781:
679	move	t6, zero			# FT's fraction shifted is zero
680	b	4f
6812:
682	li	t9, 32				# compute 32 - abs(exp diff)
683	subu	t9, t9, v1
684	bgt	v0, zero, 3f			# if FS > FT, shift FT's frac
685	move	t1, t5				# FT > FS, result exp is FT's
686	sll	t8, t2, t9			# save bits shifted out
687	srl	t2, t2, v1			# shift FS's fraction
688	b	4f
6893:
690	sll	t8, t6, t9			# save bits shifted out
691	srl	t6, t6, v1			# shift FT's fraction
6924:
693	bne	t0, t4, 1f			# if signs differ, subtract
694	addu	t2, t2, t6			# add fractions
695	b	norm_s
6961:
697	blt	t2, t6, 3f			# subtract larger from smaller
698	bne	t2, t6, 2f			# if same, result=0
699	move	t1, zero			# result=0
700	move	t2, zero
701	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
702	bne	v0, MACH_FPC_ROUND_RM, 1f	# round to -infinity?
703	or	t0, t0, t4			# compute result sign
704	b	result_fs_s
7051:
706	and	t0, t0, t4			# compute result sign
707	b	result_fs_s
7082:
709	sltu	t9, zero, t8			# compute t2:zero - t6:t8
710	subu	t8, zero, t8
711	subu	t2, t2, t6			# subtract fractions
712	subu	t2, t2, t9			# subtract barrow
713	b	norm_s
7143:
715	move	t0, t4				# sign of result = FT's
716	sltu	t9, zero, t8			# compute t6:zero - t2:t8
717	subu	t8, zero, t8
718	subu	t2, t6, t2			# subtract fractions
719	subu	t2, t2, t9			# subtract barrow
720	b	norm_s
721
722/*
723 * Double precision subtract.
724 */
725sub_d:
726	jal	get_ft_fs_d
727	xor	t4, t4, 1			# negate sign bit
728	b	add_sub_d
729/*
730 * Double precision add.
731 */
732add_d:
733	jal	get_ft_fs_d
734add_sub_d:
735	bne	t1, DEXP_INF, 1f		# is FS an infinity?
736	bne	t5, DEXP_INF, result_fs_d	# if FT is not inf, result=FS
737	bne	t2, zero, result_fs_d		# if FS is NAN, result is FS
738	bne	t3, zero, result_fs_d
739	bne	t6, zero, result_ft_d		# if FT is NAN, result is FT
740	bne	t7, zero, result_ft_d
741	bne	t0, t4, invalid_d		# both infinities same sign?
742	b	result_fs_d			# result is in FS
7431:
744	beq	t5, DEXP_INF, result_ft_d	# if FT is inf, result=FT
745	bne	t1, zero, 4f			# is FS a denormalized num?
746	bne	t2, zero, 1f			# is FS zero?
747	beq	t3, zero, 3f
7481:
749	bne	t5, zero, 2f			# is FT a denormalized num?
750	bne	t6, zero, 1f
751	beq	t7, zero, result_fs_d		# FT is zero, result=FS
7521:
753	jal	renorm_fs_d
754	jal	renorm_ft_d
755	b	5f
7562:
757	jal	renorm_fs_d
758	subu	t5, t5, DEXP_BIAS		# unbias FT exponent
759	or	t6, t6, DIMPL_ONE		# set implied one bit
760	b	5f
7613:
762	bne	t5, zero, result_ft_d		# if FT != 0, result=FT
763	bne	t6, zero, result_ft_d
764	bne	t7, zero, result_ft_d
765	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
766	bne	v0, MACH_FPC_ROUND_RM, 1f	# round to -infinity?
767	or	t0, t0, t4			# compute result sign
768	b	result_fs_d
7691:
770	and	t0, t0, t4			# compute result sign
771	b	result_fs_d
7724:
773	bne	t5, zero, 2f			# is FT a denormalized num?
774	bne	t6, zero, 1f
775	beq	t7, zero, result_fs_d		# FT is zero, result=FS
7761:
777	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
778	or	t2, t2, DIMPL_ONE		# set implied one bit
779	jal	renorm_ft_d
780	b	5f
7812:
782	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
783	or	t2, t2, DIMPL_ONE		# set implied one bit
784	subu	t5, t5, DEXP_BIAS		# unbias FT exponent
785	or	t6, t6, DIMPL_ONE		# set implied one bit
786/*
787 * Perform the addition.
788 */
7895:
790	move	t8, zero			# no shifted bits (sticky reg)
791	beq	t1, t5, 4f			# no shift needed
792	subu	v0, t1, t5			# v0 = difference of exponents
793	move	v1, v0				# v1 = abs(difference)
794	bge	v0, zero, 1f
795	negu	v1
7961:
797	ble	v1, DFRAC_BITS+2, 2f		# is difference too great?
798	li	t8, STICKYBIT			# set the sticky bit
799	bge	v0, zero, 1f			# check which exp is larger
800	move	t1, t5				# result exp is FT's
801	move	t2, zero			# FS's fraction shifted is zero
802	move	t3, zero
803	b	4f
8041:
805	move	t6, zero			# FT's fraction shifted is zero
806	move	t7, zero
807	b	4f
8082:
809	li	t9, 32
810	bge	v0, zero, 3f			# if FS > FT, shift FT's frac
811	move	t1, t5				# FT > FS, result exp is FT's
812	blt	v1, t9, 1f			# shift right by < 32?
813	subu	v1, v1, t9
814	subu	t9, t9, v1
815	sll	t8, t2, t9			# save bits shifted out
816	sltu	t9, zero, t3			# don't lose any one bits
817	or	t8, t8, t9			# save sticky bit
818	srl	t3, t2, v1			# shift FS's fraction
819	move	t2, zero
820	b	4f
8211:
822	subu	t9, t9, v1
823	sll	t8, t3, t9			# save bits shifted out
824	srl	t3, t3, v1			# shift FS's fraction
825	sll	t9, t2, t9			# save bits shifted out of t2
826	or	t3, t3, t9			# and put into t3
827	srl	t2, t2, v1
828	b	4f
8293:
830	blt	v1, t9, 1f			# shift right by < 32?
831	subu	v1, v1, t9
832	subu	t9, t9, v1
833	sll	t8, t6, t9			# save bits shifted out
834	srl	t7, t6, v1			# shift FT's fraction
835	move	t6, zero
836	b	4f
8371:
838	subu	t9, t9, v1
839	sll	t8, t7, t9			# save bits shifted out
840	srl	t7, t7, v1			# shift FT's fraction
841	sll	t9, t6, t9			# save bits shifted out of t2
842	or	t7, t7, t9			# and put into t3
843	srl	t6, t6, v1
8444:
845	bne	t0, t4, 1f			# if signs differ, subtract
846	addu	t3, t3, t7			# add fractions
847	sltu	t9, t3, t7			# compute carry
848	addu	t2, t2, t6			# add fractions
849	addu	t2, t2, t9			# add carry
850	b	norm_d
8511:
852	blt	t2, t6, 3f			# subtract larger from smaller
853	bne	t2, t6, 2f
854	bltu	t3, t7, 3f
855	bne	t3, t7, 2f			# if same, result=0
856	move	t1, zero			# result=0
857	move	t2, zero
858	move	t3, zero
859	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
860	bne	v0, MACH_FPC_ROUND_RM, 1f	# round to -infinity?
861	or	t0, t0, t4			# compute result sign
862	b	result_fs_d
8631:
864	and	t0, t0, t4			# compute result sign
865	b	result_fs_d
8662:
867	beq	t8, zero, 1f			# compute t2:t3:zero - t6:t7:t8
868	subu	t8, zero, t8
869	sltu	v0, t3, 1			# compute barrow out
870	subu	t3, t3, 1			# subtract barrow
871	subu	t2, t2, v0
8721:
873	sltu	v0, t3, t7
874	subu	t3, t3, t7			# subtract fractions
875	subu	t2, t2, t6			# subtract fractions
876	subu	t2, t2, v0			# subtract barrow
877	b	norm_d
8783:
879	move	t0, t4				# sign of result = FT's
880	beq	t8, zero, 1f			# compute t6:t7:zero - t2:t3:t8
881	subu	t8, zero, t8
882	sltu	v0, t7, 1			# compute barrow out
883	subu	t7, t7, 1			# subtract barrow
884	subu	t6, t6, v0
8851:
886	sltu	v0, t7, t3
887	subu	t3, t7, t3			# subtract fractions
888	subu	t2, t6, t2			# subtract fractions
889	subu	t2, t2, v0			# subtract barrow
890	b	norm_d
891
892/*
893 * Single precision multiply.
894 */
895mul_s:
896	jal	get_ft_fs_s
897	xor	t0, t0, t4			# compute sign of result
898	move	t4, t0
899	bne	t1, SEXP_INF, 2f		# is FS an infinity?
900	bne	t2, zero, result_fs_s		# if FS is a NAN, result=FS
901	bne	t5, SEXP_INF, 1f		# FS is inf, is FT an infinity?
902	bne	t6, zero, result_ft_s		# if FT is a NAN, result=FT
903	b	result_fs_s			# result is infinity
9041:
905	bne	t5, zero, result_fs_s		# inf * zero? if no, result=FS
906	bne	t6, zero, result_fs_s
907	b	invalid_s			# infinity * zero is invalid
9082:
909	bne	t5, SEXP_INF, 1f		# FS != inf, is FT an infinity?
910	bne	t1, zero, result_ft_s		# zero * inf? if no, result=FT
911	bne	t2, zero, result_ft_s
912	bne	t6, zero, result_ft_s		# if FT is a NAN, result=FT
913	b	invalid_s			# zero * infinity is invalid
9141:
915	bne	t1, zero, 1f			# is FS zero?
916	beq	t2, zero, result_fs_s		# result is zero
917	jal	renorm_fs_s
918	b	2f
9191:
920	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
921	or	t2, t2, SIMPL_ONE		# set implied one bit
9222:
923	bne	t5, zero, 1f			# is FT zero?
924	beq	t6, zero, result_ft_s		# result is zero
925	jal	renorm_ft_s
926	b	2f
9271:
928	subu	t5, t5, SEXP_BIAS		# unbias FT exponent
929	or	t6, t6, SIMPL_ONE		# set implied one bit
9302:
931	addu	t1, t1, t5			# compute result exponent
932	addu	t1, t1, 9			# account for binary point
933	multu	t2, t6				# multiply fractions
934	mflo	t8
935	mfhi	t2
936	b	norm_s
937
938/*
939 * Double precision multiply.
940 */
941mul_d:
942	jal	get_ft_fs_d
943	xor	t0, t0, t4			# compute sign of result
944	move	t4, t0
945	bne	t1, DEXP_INF, 2f		# is FS an infinity?
946	bne	t2, zero, result_fs_d		# if FS is a NAN, result=FS
947	bne	t3, zero, result_fs_d
948	bne	t5, DEXP_INF, 1f		# FS is inf, is FT an infinity?
949	bne	t6, zero, result_ft_d		# if FT is a NAN, result=FT
950	bne	t7, zero, result_ft_d
951	b	result_fs_d			# result is infinity
9521:
953	bne	t5, zero, result_fs_d		# inf * zero? if no, result=FS
954	bne	t6, zero, result_fs_d
955	bne	t7, zero, result_fs_d
956	b	invalid_d			# infinity * zero is invalid
9572:
958	bne	t5, DEXP_INF, 1f		# FS != inf, is FT an infinity?
959	bne	t1, zero, result_ft_d		# zero * inf? if no, result=FT
960	bne	t2, zero, result_ft_d		# if FS is a NAN, result=FS
961	bne	t3, zero, result_ft_d
962	bne	t6, zero, result_ft_d		# if FT is a NAN, result=FT
963	bne	t7, zero, result_ft_d
964	b	invalid_d			# zero * infinity is invalid
9651:
966	bne	t1, zero, 2f			# is FS zero?
967	bne	t2, zero, 1f
968	beq	t3, zero, result_fs_d		# result is zero
9691:
970	jal	renorm_fs_d
971	b	3f
9722:
973	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
974	or	t2, t2, DIMPL_ONE		# set implied one bit
9753:
976	bne	t5, zero, 2f			# is FT zero?
977	bne	t6, zero, 1f
978	beq	t7, zero, result_ft_d		# result is zero
9791:
980	jal	renorm_ft_d
981	b	3f
9822:
983	subu	t5, t5, DEXP_BIAS		# unbias FT exponent
984	or	t6, t6, DIMPL_ONE		# set implied one bit
9853:
986	addu	t1, t1, t5			# compute result exponent
987	addu	t1, t1, 12			# ???
988	multu	t3, t7				# multiply fractions (low * low)
989	move	t4, t2				# free up t2,t3 for result
990	move	t5, t3
991	mflo	a3				# save low order bits
992	mfhi	t8
993	not	v0, t8
994	multu	t4, t7				# multiply FS(high) * FT(low)
995	mflo	v1
996	mfhi	t3				# init low result
997	sltu	v0, v0, v1			# compute carry
998	addu	t8, v1
999	multu	t5, t6				# multiply FS(low) * FT(high)
1000	addu	t3, t3, v0			# add carry
1001	not	v0, t8
1002	mflo	v1
1003	mfhi	t2
1004	sltu	v0, v0, v1
1005	addu	t8, v1
1006	multu	t4, t6				# multiply FS(high) * FT(high)
1007	addu	t3, v0
1008	not	v1, t3
1009	sltu	v1, v1, t2
1010	addu	t3, t2
1011	not	v0, t3
1012	mfhi	t2
1013	addu	t2, v1
1014	mflo	v1
1015	sltu	v0, v0, v1
1016	addu	t2, v0
1017	addu	t3, v1
1018	sltu	a3, zero, a3			# reduce t8,a3 to just t8
1019	or	t8, a3
1020	b	norm_d
1021
1022/*
1023 * Single precision divide.
1024 */
1025div_s:
1026	jal	get_ft_fs_s
1027	xor	t0, t0, t4			# compute sign of result
1028	move	t4, t0
1029	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1030	bne	t2, zero, result_fs_s		# if FS is NAN, result is FS
1031	bne	t5, SEXP_INF, result_fs_s	# is FT an infinity?
1032	bne	t6, zero, result_ft_s		# if FT is NAN, result is FT
1033	b	invalid_s			# infinity/infinity is invalid
10341:
1035	bne	t5, SEXP_INF, 1f		# is FT an infinity?
1036	bne	t6, zero, result_ft_s		# if FT is NAN, result is FT
1037	move	t1, zero			# x / infinity is zero
1038	move	t2, zero
1039	b	result_fs_s
10401:
1041	bne	t1, zero, 2f			# is FS zero?
1042	bne	t2, zero, 1f
1043	bne	t5, zero, result_fs_s		# FS=zero, is FT zero?
1044	beq	t6, zero, invalid_s		# 0 / 0
1045	b	result_fs_s			# result = zero
10461:
1047	jal	renorm_fs_s
1048	b	3f
10492:
1050	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
1051	or	t2, t2, SIMPL_ONE		# set implied one bit
10523:
1053	bne	t5, zero, 2f			# is FT zero?
1054	bne	t6, zero, 1f
1055	or	a1, a1, MACH_FPC_EXCEPTION_DIV0 | MACH_FPC_STICKY_DIV0
1056	and	v0, a1, MACH_FPC_ENABLE_DIV0	# trap enabled?
1057	bne	v0, zero, fpe_trap
1058	ctc1	a1, MACH_FPC_CSR		# save exceptions
1059	li	t1, SEXP_INF			# result is infinity
1060	move	t2, zero
1061	b	result_fs_s
10621:
1063	jal	renorm_ft_s
1064	b	3f
10652:
1066	subu	t5, t5, SEXP_BIAS		# unbias FT exponent
1067	or	t6, t6, SIMPL_ONE		# set implied one bit
10683:
1069	subu	t1, t1, t5			# compute exponent
1070	subu	t1, t1, 3			# compensate for result position
1071	li	v0, SFRAC_BITS+3		# number of bits to divide
1072	move	t8, t2				# init dividend
1073	move	t2, zero			# init result
10741:
1075	bltu	t8, t6, 3f			# is dividend >= divisor?
10762:
1077	subu	t8, t8, t6			# subtract divisor from dividend
1078	or	t2, t2, 1			# remember that we did
1079	bne	t8, zero, 3f			# if not done, continue
1080	sll	t2, t2, v0			# shift result to final position
1081	b	norm_s
10823:
1083	sll	t8, t8, 1			# shift dividend
1084	sll	t2, t2, 1			# shift result
1085	subu	v0, v0, 1			# are we done?
1086	bne	v0, zero, 1b			# no, continue
1087	b	norm_s
1088
1089/*
1090 * Double precision divide.
1091 */
1092div_d:
1093	jal	get_ft_fs_d
1094	xor	t0, t0, t4			# compute sign of result
1095	move	t4, t0
1096	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1097	bne	t2, zero, result_fs_d		# if FS is NAN, result is FS
1098	bne	t3, zero, result_fs_d
1099	bne	t5, DEXP_INF, result_fs_d	# is FT an infinity?
1100	bne	t6, zero, result_ft_d		# if FT is NAN, result is FT
1101	bne	t7, zero, result_ft_d
1102	b	invalid_d			# infinity/infinity is invalid
11031:
1104	bne	t5, DEXP_INF, 1f		# is FT an infinity?
1105	bne	t6, zero, result_ft_d		# if FT is NAN, result is FT
1106	bne	t7, zero, result_ft_d
1107	move	t1, zero			# x / infinity is zero
1108	move	t2, zero
1109	move	t3, zero
1110	b	result_fs_d
11111:
1112	bne	t1, zero, 2f			# is FS zero?
1113	bne	t2, zero, 1f
1114	bne	t3, zero, 1f
1115	bne	t5, zero, result_fs_d		# FS=zero, is FT zero?
1116	bne	t6, zero, result_fs_d
1117	beq	t7, zero, invalid_d		# 0 / 0
1118	b	result_fs_d			# result = zero
11191:
1120	jal	renorm_fs_d
1121	b	3f
11222:
1123	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
1124	or	t2, t2, DIMPL_ONE		# set implied one bit
11253:
1126	bne	t5, zero, 2f			# is FT zero?
1127	bne	t6, zero, 1f
1128	bne	t7, zero, 1f
1129	or	a1, a1, MACH_FPC_EXCEPTION_DIV0 | MACH_FPC_STICKY_DIV0
1130	and	v0, a1, MACH_FPC_ENABLE_DIV0	# trap enabled?
1131	bne	v0, zero, fpe_trap
1132	ctc1	a1, MACH_FPC_CSR		# Save exceptions
1133	li	t1, DEXP_INF			# result is infinity
1134	move	t2, zero
1135	move	t3, zero
1136	b	result_fs_d
11371:
1138	jal	renorm_ft_d
1139	b	3f
11402:
1141	subu	t5, t5, DEXP_BIAS		# unbias FT exponent
1142	or	t6, t6, DIMPL_ONE		# set implied one bit
11433:
1144	subu	t1, t1, t5			# compute exponent
1145	subu	t1, t1, 3			# compensate for result position
1146	li	v0, DFRAC_BITS+3		# number of bits to divide
1147	move	t8, t2				# init dividend
1148	move	t9, t3
1149	move	t2, zero			# init result
1150	move	t3, zero
11511:
1152	bltu	t8, t6, 3f			# is dividend >= divisor?
1153	bne	t8, t6, 2f
1154	bltu	t9, t7, 3f
11552:
1156	sltu	v1, t9, t7			# subtract divisor from dividend
1157	subu	t9, t9, t7
1158	subu	t8, t8, t6
1159	subu	t8, t8, v1
1160	or	t3, t3, 1			# remember that we did
1161	bne	t8, zero, 3f			# if not done, continue
1162	bne	t9, zero, 3f
1163	li	v1, 32				# shift result to final position
1164	blt	v0, v1, 2f			# shift < 32 bits?
1165	subu	v0, v0, v1			# shift by > 32 bits
1166	sll	t2, t3, v0			# shift upper part
1167	move	t3, zero
1168	b	norm_d
11692:
1170	subu	v1, v1, v0			# shift by < 32 bits
1171	sll	t2, t2, v0			# shift upper part
1172	srl	t9, t3, v1			# save bits shifted out
1173	or	t2, t2, t9			# and put into upper part
1174	sll	t3, t3, v0
1175	b	norm_d
11763:
1177	sll	t8, t8, 1			# shift dividend
1178	srl	v1, t9, 31			# save bit shifted out
1179	or	t8, t8, v1			# and put into upper part
1180	sll	t9, t9, 1
1181	sll	t2, t2, 1			# shift result
1182	srl	v1, t3, 31			# save bit shifted out
1183	or	t2, t2, v1			# and put into upper part
1184	sll	t3, t3, 1
1185	subu	v0, v0, 1			# are we done?
1186	bne	v0, zero, 1b			# no, continue
1187	sltu	v0, zero, t9			# be sure to save any one bits
1188	or	t8, t8, v0			# from the lower remainder
1189	b	norm_d
1190
1191/*
1192 * Single precision absolute value.
1193 */
1194abs_s:
1195	jal	get_fs_s
1196	move	t0, zero			# set sign positive
1197	b	result_fs_s
1198
1199/*
1200 * Double precision absolute value.
1201 */
1202abs_d:
1203	jal	get_fs_d
1204	move	t0, zero			# set sign positive
1205	b	result_fs_d
1206
1207/*
1208 * Single precision move.
1209 */
1210mov_s:
1211	jal	get_fs_s
1212	b	result_fs_s
1213
1214/*
1215 * Double precision move.
1216 */
1217mov_d:
1218	jal	get_fs_d
1219	b	result_fs_d
1220
1221/*
1222 * Single precision negate.
1223 */
1224neg_s:
1225	jal	get_fs_s
1226	xor	t0, t0, 1			# reverse sign
1227	b	result_fs_s
1228
1229/*
1230 * Double precision negate.
1231 */
1232neg_d:
1233	jal	get_fs_d
1234	xor	t0, t0, 1			# reverse sign
1235	b	result_fs_d
1236
1237/*
1238 * Convert double to single.
1239 */
1240cvt_s_d:
1241	jal	get_fs_d
1242	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1243	li	t1, SEXP_INF			# convert to single
1244	sll	t2, t2, 3			# convert D fraction to S
1245	srl	t8, t3, 32 - 3
1246	or	t2, t2, t8
1247	b	result_fs_s
12481:
1249	bne	t1, zero, 2f			# is FS zero?
1250	bne	t2, zero, 1f
1251	beq	t3, zero, result_fs_s		# result=0
12521:
1253	jal	renorm_fs_d
1254	subu	t1, t1, 3			# correct exp for shift below
1255	b	3f
12562:
1257	subu	t1, t1, DEXP_BIAS		# unbias exponent
1258	or	t2, t2, DIMPL_ONE		# add implied one bit
12593:
1260	sll	t2, t2, 3			# convert D fraction to S
1261	srl	t8, t3, 32 - 3
1262	or	t2, t2, t8
1263	sll	t8, t3, 3
1264	b	norm_noshift_s
1265
1266/*
1267 * Convert integer to single.
1268 */
1269cvt_s_w:
1270	jal	get_fs_int
1271	bne	t2, zero, 1f			# check for zero
1272	move	t1, zero
1273	b	result_fs_s
1274/*
1275 * Find out how many leading zero bits are in t2 and put in t9.
1276 */
12771:
1278	move	v0, t2
1279	move	t9, zero
1280	srl	v1, v0, 16
1281	bne	v1, zero, 1f
1282	addu	t9, 16
1283	sll	v0, 16
12841:
1285	srl	v1, v0, 24
1286	bne	v1, zero, 1f
1287	addu	t9, 8
1288	sll	v0, 8
12891:
1290	srl	v1, v0, 28
1291	bne	v1, zero, 1f
1292	addu	t9, 4
1293	sll	v0, 4
12941:
1295	srl	v1, v0, 30
1296	bne	v1, zero, 1f
1297	addu	t9, 2
1298	sll	v0, 2
12991:
1300	srl	v1, v0, 31
1301	bne	v1, zero, 1f
1302	addu	t9, 1
1303/*
1304 * Now shift t2 the correct number of bits.
1305 */
13061:
1307	subu	t9, t9, SLEAD_ZEROS		# don't count leading zeros
1308	li	t1, 23				# init exponent
1309	subu	t1, t1, t9			# compute exponent
1310	beq	t9, zero, 1f
1311	li	v0, 32
1312	blt	t9, zero, 2f			# if shift < 0, shift right
1313	subu	v0, v0, t9
1314	sll	t2, t2, t9			# shift left
13151:
1316	add	t1, t1, SEXP_BIAS		# bias exponent
1317	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1318	b	result_fs_s
13192:
1320	negu	t9				# shift right by t9
1321	subu	v0, v0, t9
1322	sll	t8, t2, v0			# save bits shifted out
1323	srl	t2, t2, t9
1324	b	norm_noshift_s
1325
1326/*
1327 * Convert single to double.
1328 */
1329cvt_d_s:
1330	jal	get_fs_s
1331	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1332	li	t1, DEXP_INF			# convert to double
1333	b	2f
13341:
1335	bne	t1, zero, 2f			# is FS denormalized or zero?
1336	beq	t2, zero, result_fs_d		# is FS zero?
1337	jal	renorm_fs_s
1338	move	t8, zero
1339	b	norm_d
13402:
1341	addu	t1, t1, DEXP_BIAS - SEXP_BIAS	# bias exponent correctly
1342	sll	t3, t2, 32 - 3			# convert S fraction to D
1343	srl	t2, t2, 3
1344	b	result_fs_d
1345
1346/*
1347 * Convert integer to double.
1348 */
1349cvt_d_w:
1350	jal	get_fs_int
1351	bne	t2, zero, 1f			# check for zero
1352	move	t1, zero			# result=0
1353	move	t3, zero
1354	b	result_fs_d
1355/*
1356 * Find out how many leading zero bits are in t2 and put in t9.
1357 */
13581:
1359	move	v0, t2
1360	move	t9, zero
1361	srl	v1, v0, 16
1362	bne	v1, zero, 1f
1363	addu	t9, 16
1364	sll	v0, 16
13651:
1366	srl	v1, v0, 24
1367	bne	v1, zero, 1f
1368	addu	t9, 8
1369	sll	v0, 8
13701:
1371	srl	v1, v0, 28
1372	bne	v1, zero, 1f
1373	addu	t9, 4
1374	sll	v0, 4
13751:
1376	srl	v1, v0, 30
1377	bne	v1, zero, 1f
1378	addu	t9, 2
1379	sll	v0, 2
13801:
1381	srl	v1, v0, 31
1382	bne	v1, zero, 1f
1383	addu	t9, 1
1384/*
1385 * Now shift t2 the correct number of bits.
1386 */
13871:
1388	subu	t9, t9, DLEAD_ZEROS		# don't count leading zeros
1389	li	t1, DEXP_BIAS + 23		# init exponent
1390	subu	t1, t1, t9			# compute exponent
1391	beq	t9, zero, 1f
1392	li	v0, 32
1393	blt	t9, zero, 2f			# if shift < 0, shift right
1394	subu	v0, v0, t9
1395	sll	t2, t2, t9			# shift left
13961:
1397	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1398	b	result_fs_d
13992:
1400	negu	t9				# shift right by t9
1401	subu	v0, v0, t9
1402	sll	t3, t2, v0
1403	srl	t2, t2, t9
1404	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1405	b	result_fs_d
1406
1407/*
1408 * Convert single to integer.
1409 */
1410cvt_w_s:
1411	jal	get_fs_s
1412	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1413	bne	t2, zero, invalid_w		# invalid conversion
14141:
1415	bne	t1, zero, 1f			# is FS zero?
1416	beq	t2, zero, result_fs_w		# result is zero
1417	move	t2, zero			# result is an inexact zero
1418	b	inexact_w
14191:
1420	subu	t1, t1, SEXP_BIAS		# unbias exponent
1421	or	t2, t2, SIMPL_ONE		# add implied one bit
1422	sll	t3, t2, 32 - 3			# convert S fraction to D
1423	srl	t2, t2, 3
1424	b	cvt_w
1425
1426/*
1427 * Convert double to integer.
1428 */
1429cvt_w_d:
1430	jal	get_fs_d
1431	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1432	bne	t2, zero, invalid_w		# invalid conversion
1433	bne	t3, zero, invalid_w		# invalid conversion
14341:
1435	bne	t1, zero, 2f			# is FS zero?
1436	bne	t2, zero, 1f
1437	beq	t3, zero, result_fs_w		# result is zero
14381:
1439	move	t2, zero			# result is an inexact zero
1440	b	inexact_w
14412:
1442	subu	t1, t1, DEXP_BIAS		# unbias exponent
1443	or	t2, t2, DIMPL_ONE		# add implied one bit
1444cvt_w:
1445	blt	t1, WEXP_MIN, underflow_w	# is exponent too small?
1446	li	v0, WEXP_MAX+1
1447	bgt	t1, v0, overflow_w		# is exponent too large?
1448	bne	t1, v0, 1f			# special check for INT_MIN
1449	beq	t0, zero, overflow_w		# if positive, overflow
1450	bne	t2, DIMPL_ONE, overflow_w
1451	bne	t3, zero, overflow_w
1452	li	t2, INT_MIN			# result is INT_MIN
1453	b	result_fs_w
14541:
1455	subu	v0, t1, 20			# compute amount to shift
1456	beq	v0, zero, 2f			# is shift needed?
1457	li	v1, 32
1458	blt	v0, zero, 1f			# if shift < 0, shift right
1459	subu	v1, v1, v0			# shift left
1460	sll	t2, t2, v0
1461	srl	t9, t3, v1			# save bits shifted out of t3
1462	or	t2, t2, t9			# and put into t2
1463	sll	t3, t3, v0			# shift FS's fraction
1464	b	2f
14651:
1466	negu	v0				# shift right by v0
1467	subu	v1, v1, v0
1468	sll	t8, t3, v1			# save bits shifted out
1469	sltu	t8, zero, t8			# don't lose any one's
1470	srl	t3, t3, v0			# shift FS's fraction
1471	or	t3, t3, t8
1472	sll	t9, t2, v1			# save bits shifted out of t2
1473	or	t3, t3, t9			# and put into t3
1474	srl	t2, t2, v0
1475/*
1476 * round result (t0 is sign, t2 is integer part, t3 is fractional part).
1477 */
14782:
1479	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1480	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1481	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
1482	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1483	beq	t0, zero, 5f			# if sign is positive, truncate
1484	b	2f
14851:
1486	bne	t0, zero, 5f			# if sign is negative, truncate
14872:
1488	beq	t3, zero, 5f			# if no fraction bits, continue
1489	addu	t2, t2, 1			# add rounding bit
1490	blt	t2, zero, overflow_w		# overflow?
1491	b	5f
14923:
1493	li	v0, GUARDBIT			# load guard bit for rounding
1494	addu	v0, v0, t3			# add remainder
1495	sltu	v1, v0, t3			# compute carry out
1496	beq	v1, zero, 4f			# if no carry, continue
1497	addu	t2, t2, 1			# add carry to result
1498	blt	t2, zero, overflow_w		# overflow?
14994:
1500	bne	v0, zero, 5f			# if rounded remainder is zero
1501	and	t2, t2, ~1			#  clear LSB (round to nearest)
15025:
1503	beq	t0, zero, 1f			# result positive?
1504	negu	t2				# convert to negative integer
15051:
1506	beq	t3, zero, result_fs_w		# is result exact?
1507/*
1508 * Handle inexact exception.
1509 */
1510inexact_w:
1511	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
1512	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1513	bne	v0, zero, fpe_trap
1514	ctc1	a1, MACH_FPC_CSR		# save exceptions
1515	b	result_fs_w
1516
1517/*
1518 * Conversions to integer which overflow will trap (if enabled),
1519 * or generate an inexact trap (if enabled),
1520 * or generate an invalid exception.
1521 */
1522overflow_w:
1523	or	a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW
1524	and	v0, a1, MACH_FPC_ENABLE_OVERFLOW
1525	bne	v0, zero, fpe_trap
1526	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1527	bne	v0, zero, inexact_w		# inexact traps enabled?
1528	b	invalid_w
1529
1530/*
1531 * Conversions to integer which underflow will trap (if enabled),
1532 * or generate an inexact trap (if enabled),
1533 * or generate an invalid exception.
1534 */
1535underflow_w:
1536	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
1537	and	v0, a1, MACH_FPC_ENABLE_UNDERFLOW
1538	bne	v0, zero, fpe_trap
1539	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1540	bne	v0, zero, inexact_w		# inexact traps enabled?
1541	b	invalid_w
1542
1543/*
1544 * Compare single.
1545 */
1546cmp_s:
1547	jal	get_cmp_s
1548	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1549	bne	t2, zero, unordered		# FS is a NAN
15501:
1551	bne	t5, SEXP_INF, 2f		# is FT an infinity?
1552	bne	t6, zero, unordered		# FT is a NAN
15532:
1554	sll	t1, t1, 23			# reassemble exp & frac
1555	or	t1, t1, t2
1556	sll	t5, t5, 23			# reassemble exp & frac
1557	or	t5, t5, t6
1558	beq	t0, zero, 1f			# is FS positive?
1559	negu	t1
15601:
1561	beq	t4, zero, 1f			# is FT positive?
1562	negu	t5
15631:
1564	li	v0, COND_LESS
1565	blt	t1, t5, test_cond		# is FS < FT?
1566	li	v0, COND_EQUAL
1567	beq	t1, t5, test_cond		# is FS == FT?
1568	move	v0, zero			# FS > FT
1569	b	test_cond
1570
1571/*
1572 * Compare double.
1573 */
1574cmp_d:
1575	jal	get_cmp_d
1576	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1577	bne	t2, zero, unordered
1578	bne	t3, zero, unordered		# FS is a NAN
15791:
1580	bne	t5, DEXP_INF, 2f		# is FT an infinity?
1581	bne	t6, zero, unordered
1582	bne	t7, zero, unordered		# FT is a NAN
15832:
1584	sll	t1, t1, 20			# reassemble exp & frac
1585	or	t1, t1, t2
1586	sll	t5, t5, 20			# reassemble exp & frac
1587	or	t5, t5, t6
1588	beq	t0, zero, 1f			# is FS positive?
1589	not	t3				# negate t1,t3
1590	not	t1
1591	addu	t3, t3, 1
1592	seq	v0, t3, zero			# compute carry
1593	addu	t1, t1, v0
15941:
1595	beq	t4, zero, 1f			# is FT positive?
1596	not	t7				# negate t5,t7
1597	not	t5
1598	addu	t7, t7, 1
1599	seq	v0, t7, zero			# compute carry
1600	addu	t5, t5, v0
16011:
1602	li	v0, COND_LESS
1603	blt	t1, t5, test_cond		# is FS(MSW) < FT(MSW)?
1604	move	v0, zero
1605	bne	t1, t5, test_cond		# is FS(MSW) > FT(MSW)?
1606	li	v0, COND_LESS
1607	bltu	t3, t7, test_cond		# is FS(LSW) < FT(LSW)?
1608	li	v0, COND_EQUAL
1609	beq	t3, t7, test_cond		# is FS(LSW) == FT(LSW)?
1610	move	v0, zero			# FS > FT
1611test_cond:
1612	and	v0, v0, a0			# condition match instruction?
1613set_cond:
1614	bne	v0, zero, 1f
1615	and	a1, a1, ~MACH_FPC_COND_BIT	# clear condition bit
1616	b	2f
16171:
1618	or	a1, a1, MACH_FPC_COND_BIT	# set condition bit
16192:
1620	ctc1	a1, MACH_FPC_CSR		# save condition bit
1621	b	done
1622
1623unordered:
1624	and	v0, a0, COND_UNORDERED		# this cmp match unordered?
1625	bne	v0, zero, 1f
1626	and	a1, a1, ~MACH_FPC_COND_BIT	# clear condition bit
1627	b	2f
16281:
1629	or	a1, a1, MACH_FPC_COND_BIT	# set condition bit
16302:
1631	and	v0, a0, COND_SIGNAL
1632	beq	v0, zero, 1f			# is this a signaling cmp?
1633	or	a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID
1634	and	v0, a1, MACH_FPC_ENABLE_INVALID
1635	bne	v0, zero, fpe_trap
16361:
1637	ctc1	a1, MACH_FPC_CSR		# save condition bit
1638	b	done
1639
1640/*
1641 * Determine the amount to shift the fraction in order to restore the
1642 * normalized position. After that, round and handle exceptions.
1643 */
1644norm_s:
1645	move	v0, t2
1646	move	t9, zero			# t9 = num of leading zeros
1647	bne	t2, zero, 1f
1648	move	v0, t8
1649	addu	t9, 32
16501:
1651	srl	v1, v0, 16
1652	bne	v1, zero, 1f
1653	addu	t9, 16
1654	sll	v0, 16
16551:
1656	srl	v1, v0, 24
1657	bne	v1, zero, 1f
1658	addu	t9, 8
1659	sll	v0, 8
16601:
1661	srl	v1, v0, 28
1662	bne	v1, zero, 1f
1663	addu	t9, 4
1664	sll	v0, 4
16651:
1666	srl	v1, v0, 30
1667	bne	v1, zero, 1f
1668	addu	t9, 2
1669	sll	v0, 2
16701:
1671	srl	v1, v0, 31
1672	bne	v1, zero, 1f
1673	addu	t9, 1
1674/*
1675 * Now shift t2,t8 the correct number of bits.
1676 */
16771:
1678	subu	t9, t9, SLEAD_ZEROS		# don't count leading zeros
1679	subu	t1, t1, t9			# adjust the exponent
1680	beq	t9, zero, norm_noshift_s
1681	li	v1, 32
1682	blt	t9, zero, 1f			# if shift < 0, shift right
1683	subu	v1, v1, t9
1684	sll	t2, t2, t9			# shift t2,t8 left
1685	srl	v0, t8, v1			# save bits shifted out
1686	or	t2, t2, v0
1687	sll	t8, t8, t9
1688	b	norm_noshift_s
16891:
1690	negu	t9				# shift t2,t8 right by t9
1691	subu	v1, v1, t9
1692	sll	v0, t8, v1			# save bits shifted out
1693	sltu	v0, zero, v0			# be sure to save any one bits
1694	srl	t8, t8, t9
1695	or	t8, t8, v0
1696	sll	v0, t2, v1			# save bits shifted out
1697	or	t8, t8, v0
1698	srl	t2, t2, t9
1699norm_noshift_s:
1700	move	t5, t1				# save unrounded exponent
1701	move	t6, t2				# save unrounded fraction
1702	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1703	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1704	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
1705	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1706	beq	t0, zero, 5f			# if sign is positive, truncate
1707	b	2f
17081:
1709	bne	t0, zero, 5f			# if sign is negative, truncate
17102:
1711	beq	t8, zero, 5f			# if exact, continue
1712	addu	t2, t2, 1			# add rounding bit
1713	bne	t2, SIMPL_ONE<<1, 5f		# need to adjust exponent?
1714	addu	t1, t1, 1			# adjust exponent
1715	srl	t2, t2, 1			# renormalize fraction
1716	b	5f
17173:
1718	li	v0, GUARDBIT			# load guard bit for rounding
1719	addu	v0, v0, t8			# add remainder
1720	sltu	v1, v0, t8			# compute carry out
1721	beq	v1, zero, 4f			# if no carry, continue
1722	addu	t2, t2, 1			# add carry to result
1723	bne	t2, SIMPL_ONE<<1, 4f		# need to adjust exponent?
1724	addu	t1, t1, 1			# adjust exponent
1725	srl	t2, t2, 1			# renormalize fraction
17264:
1727	bne	v0, zero, 5f			# if rounded remainder is zero
1728	and	t2, t2, ~1			#  clear LSB (round to nearest)
17295:
1730	bgt	t1, SEXP_MAX, overflow_s	# overflow?
1731	blt	t1, SEXP_MIN, underflow_s	# underflow?
1732	bne	t8, zero, inexact_s		# is result inexact?
1733	addu	t1, t1, SEXP_BIAS		# bias exponent
1734	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1735	b	result_fs_s
1736
1737/*
1738 * Handle inexact exception.
1739 */
1740inexact_s:
1741	addu	t1, t1, SEXP_BIAS		# bias exponent
1742	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1743inexact_nobias_s:
1744	jal	set_fd_s			# save result
1745	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
1746	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1747	bne	v0, zero, fpe_trap
1748	ctc1	a1, MACH_FPC_CSR		# save exceptions
1749	b	done
1750
1751/*
1752 * Overflow will trap (if enabled),
1753 * or generate an inexact trap (if enabled),
1754 * or generate an infinity.
1755 */
1756overflow_s:
1757	or	a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW
1758	and	v0, a1, MACH_FPC_ENABLE_OVERFLOW
1759	beq	v0, zero, 1f
1760	subu	t1, t1, 192			# bias exponent
1761	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1762	jal	set_fd_s			# save result
1763	b	fpe_trap
17641:
1765	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1766	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1767	beq	v0, MACH_FPC_ROUND_RZ, 1f	# round to zero (truncate)
1768	beq	v0, MACH_FPC_ROUND_RP, 2f	# round to +infinity
1769	bne	t0, zero, 3f
17701:
1771	li	t1, SEXP_MAX			# result is max finite
1772	li	t2, 0x007fffff
1773	b	inexact_s
17742:
1775	bne	t0, zero, 1b
17763:
1777	li	t1, SEXP_MAX + 1		# result is infinity
1778	move	t2, zero
1779	b	inexact_s
1780
1781/*
1782 * In this implementation, "tininess" is detected "after rounding" and
1783 * "loss of accuracy" is detected as "an inexact result".
1784 */
1785underflow_s:
1786	and	v0, a1, MACH_FPC_ENABLE_UNDERFLOW
1787	beq	v0, zero, 1f
1788/*
1789 * Underflow is enabled so compute the result and trap.
1790 */
1791	addu	t1, t1, 192			# bias exponent
1792	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1793	jal	set_fd_s			# save result
1794	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
1795	b	fpe_trap
1796/*
1797 * Underflow is not enabled so compute the result,
1798 * signal inexact result (if it is) and trap (if enabled).
1799 */
18001:
1801	move	t1, t5				# get unrounded exponent
1802	move	t2, t6				# get unrounded fraction
1803	li	t9, SEXP_MIN			# compute shift amount
1804	subu	t9, t9, t1			# shift t2,t8 right by t9
1805	blt	t9, SFRAC_BITS+2, 3f		# shift all the bits out?
1806	move	t1, zero			# result is inexact zero
1807	move	t2, zero
1808	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
1809/*
1810 * Now round the zero result.
1811 * Only need to worry about rounding to +- infinity when the sign matches.
1812 */
1813	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1814	beq	v0, MACH_FPC_ROUND_RN, inexact_nobias_s	# round to nearest
1815	beq	v0, MACH_FPC_ROUND_RZ, inexact_nobias_s	# round to zero
1816	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1817	beq	t0, zero, inexact_nobias_s	# if sign is positive, truncate
1818	b	2f
18191:
1820	bne	t0, zero, inexact_nobias_s	# if sign is negative, truncate
18212:
1822	addu	t2, t2, 1			# add rounding bit
1823	b	inexact_nobias_s
18243:
1825	li	v1, 32
1826	subu	v1, v1, t9
1827	sltu	v0, zero, t8			# be sure to save any one bits
1828	sll	t8, t2, v1			# save bits shifted out
1829	or	t8, t8, v0			# include sticky bits
1830	srl	t2, t2, t9
1831/*
1832 * Now round the denormalized result.
1833 */
1834	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1835	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1836	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
1837	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1838	beq	t0, zero, 5f			# if sign is positive, truncate
1839	b	2f
18401:
1841	bne	t0, zero, 5f			# if sign is negative, truncate
18422:
1843	beq	t8, zero, 5f			# if exact, continue
1844	addu	t2, t2, 1			# add rounding bit
1845	b	5f
18463:
1847	li	v0, GUARDBIT			# load guard bit for rounding
1848	addu	v0, v0, t8			# add remainder
1849	sltu	v1, v0, t8			# compute carry out
1850	beq	v1, zero, 4f			# if no carry, continue
1851	addu	t2, t2, 1			# add carry to result
18524:
1853	bne	v0, zero, 5f			# if rounded remainder is zero
1854	and	t2, t2, ~1			#  clear LSB (round to nearest)
18555:
1856	move	t1, zero			# denorm or zero exponent
1857	jal	set_fd_s			# save result
1858	beq	t8, zero, done			# check for exact result
1859	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
1860	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
1861	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1862	bne	v0, zero, fpe_trap
1863	ctc1	a1, MACH_FPC_CSR		# save exceptions
1864	b	done
1865
1866/*
1867 * Determine the amount to shift the fraction in order to restore the
1868 * normalized position. After that, round and handle exceptions.
1869 */
1870norm_d:
1871	move	v0, t2
1872	move	t9, zero			# t9 = num of leading zeros
1873	bne	t2, zero, 1f
1874	move	v0, t3
1875	addu	t9, 32
1876	bne	t3, zero, 1f
1877	move	v0, t8
1878	addu	t9, 32
18791:
1880	srl	v1, v0, 16
1881	bne	v1, zero, 1f
1882	addu	t9, 16
1883	sll	v0, 16
18841:
1885	srl	v1, v0, 24
1886	bne	v1, zero, 1f
1887	addu	t9, 8
1888	sll	v0, 8
18891:
1890	srl	v1, v0, 28
1891	bne	v1, zero, 1f
1892	addu	t9, 4
1893	sll	v0, 4
18941:
1895	srl	v1, v0, 30
1896	bne	v1, zero, 1f
1897	addu	t9, 2
1898	sll	v0, 2
18991:
1900	srl	v1, v0, 31
1901	bne	v1, zero, 1f
1902	addu	t9, 1
1903/*
1904 * Now shift t2,t3,t8 the correct number of bits.
1905 */
19061:
1907	subu	t9, t9, DLEAD_ZEROS		# don't count leading zeros
1908	subu	t1, t1, t9			# adjust the exponent
1909	beq	t9, zero, norm_noshift_d
1910	li	v1, 32
1911	blt	t9, zero, 2f			# if shift < 0, shift right
1912	blt	t9, v1, 1f			# shift by < 32?
1913	subu	t9, t9, v1			# shift by >= 32
1914	subu	v1, v1, t9
1915	sll	t2, t3, t9			# shift left by t9
1916	srl	v0, t8, v1			# save bits shifted out
1917	or	t2, t2, v0
1918	sll	t3, t8, t9
1919	move	t8, zero
1920	b	norm_noshift_d
19211:
1922	subu	v1, v1, t9
1923	sll	t2, t2, t9			# shift left by t9
1924	srl	v0, t3, v1			# save bits shifted out
1925	or	t2, t2, v0
1926	sll	t3, t3, t9
1927	srl	v0, t8, v1			# save bits shifted out
1928	or	t3, t3, v0
1929	sll	t8, t8, t9
1930	b	norm_noshift_d
19312:
1932	negu	t9				# shift right by t9
1933	subu	v1, v1, t9			#  (known to be < 32 bits)
1934	sll	v0, t8, v1			# save bits shifted out
1935	sltu	v0, zero, v0			# be sure to save any one bits
1936	srl	t8, t8, t9
1937	or	t8, t8, v0
1938	sll	v0, t3, v1			# save bits shifted out
1939	or	t8, t8, v0
1940	srl	t3, t3, t9
1941	sll	v0, t2, v1			# save bits shifted out
1942	or	t3, t3, v0
1943	srl	t2, t2, t9
1944norm_noshift_d:
1945	move	t5, t1				# save unrounded exponent
1946	move	t6, t2				# save unrounded fraction (MS)
1947	move	t7, t3				# save unrounded fraction (LS)
1948	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1949	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1950	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
1951	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1952	beq	t0, zero, 5f			# if sign is positive, truncate
1953	b	2f
19541:
1955	bne	t0, zero, 5f			# if sign is negative, truncate
19562:
1957	beq	t8, zero, 5f			# if exact, continue
1958	addu	t3, t3, 1			# add rounding bit
1959	bne	t3, zero, 5f			# branch if no carry
1960	addu	t2, t2, 1			# add carry
1961	bne	t2, DIMPL_ONE<<1, 5f		# need to adjust exponent?
1962	addu	t1, t1, 1			# adjust exponent
1963	srl	t2, t2, 1			# renormalize fraction
1964	b	5f
19653:
1966	li	v0, GUARDBIT			# load guard bit for rounding
1967	addu	v0, v0, t8			# add remainder
1968	sltu	v1, v0, t8			# compute carry out
1969	beq	v1, zero, 4f			# branch if no carry
1970	addu	t3, t3, 1			# add carry
1971	bne	t3, zero, 4f			# branch if no carry
1972	addu	t2, t2, 1			# add carry to result
1973	bne	t2, DIMPL_ONE<<1, 4f		# need to adjust exponent?
1974	addu	t1, t1, 1			# adjust exponent
1975	srl	t2, t2, 1			# renormalize fraction
19764:
1977	bne	v0, zero, 5f			# if rounded remainder is zero
1978	and	t3, t3, ~1			#  clear LSB (round to nearest)
19795:
1980	bgt	t1, DEXP_MAX, overflow_d	# overflow?
1981	blt	t1, DEXP_MIN, underflow_d	# underflow?
1982	bne	t8, zero, inexact_d		# is result inexact?
1983	addu	t1, t1, DEXP_BIAS		# bias exponent
1984	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1985	b	result_fs_d
1986
1987/*
1988 * Handle inexact exception.
1989 */
1990inexact_d:
1991	addu	t1, t1, DEXP_BIAS		# bias exponent
1992	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1993inexact_nobias_d:
1994	jal	set_fd_d			# save result
1995	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
1996	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1997	bne	v0, zero, fpe_trap
1998	ctc1	a1, MACH_FPC_CSR		# save exceptions
1999	b	done
2000
2001/*
2002 * Overflow will trap (if enabled),
2003 * or generate an inexact trap (if enabled),
2004 * or generate an infinity.
2005 */
2006overflow_d:
2007	or	a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW
2008	and	v0, a1, MACH_FPC_ENABLE_OVERFLOW
2009	beq	v0, zero, 1f
2010	subu	t1, t1, 1536			# bias exponent
2011	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2012	jal	set_fd_d			# save result
2013	b	fpe_trap
20141:
2015	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
2016	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
2017	beq	v0, MACH_FPC_ROUND_RZ, 1f	# round to zero (truncate)
2018	beq	v0, MACH_FPC_ROUND_RP, 2f	# round to +infinity
2019	bne	t0, zero, 3f
20201:
2021	li	t1, DEXP_MAX			# result is max finite
2022	li	t2, 0x000fffff
2023	li	t3, 0xffffffff
2024	b	inexact_d
20252:
2026	bne	t0, zero, 1b
20273:
2028	li	t1, DEXP_MAX + 1		# result is infinity
2029	move	t2, zero
2030	move	t3, zero
2031	b	inexact_d
2032
2033/*
2034 * In this implementation, "tininess" is detected "after rounding" and
2035 * "loss of accuracy" is detected as "an inexact result".
2036 */
2037underflow_d:
2038	and	v0, a1, MACH_FPC_ENABLE_UNDERFLOW
2039	beq	v0, zero, 1f
2040/*
2041 * Underflow is enabled so compute the result and trap.
2042 */
2043	addu	t1, t1, 1536			# bias exponent
2044	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2045	jal	set_fd_d			# save result
2046	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
2047	b	fpe_trap
2048/*
2049 * Underflow is not enabled so compute the result,
2050 * signal inexact result (if it is) and trap (if enabled).
2051 */
20521:
2053	move	t1, t5				# get unrounded exponent
2054	move	t2, t6				# get unrounded fraction (MS)
2055	move	t3, t7				# get unrounded fraction (LS)
2056	li	t9, DEXP_MIN			# compute shift amount
2057	subu	t9, t9, t1			# shift t2,t8 right by t9
2058	blt	t9, DFRAC_BITS+2, 3f		# shift all the bits out?
2059	move	t1, zero			# result is inexact zero
2060	move	t2, zero
2061	move	t3, zero
2062	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
2063/*
2064 * Now round the zero result.
2065 * Only need to worry about rounding to +- infinity when the sign matches.
2066 */
2067	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
2068	beq	v0, MACH_FPC_ROUND_RN, inexact_nobias_d	# round to nearest
2069	beq	v0, MACH_FPC_ROUND_RZ, inexact_nobias_d	# round to zero
2070	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
2071	beq	t0, zero, inexact_nobias_d	# if sign is positive, truncate
2072	b	2f
20731:
2074	bne	t0, zero, inexact_nobias_d	# if sign is negative, truncate
20752:
2076	addu	t3, t3, 1			# add rounding bit
2077	b	inexact_nobias_d
20783:
2079	li	v1, 32
2080	blt	t9, v1, 1f			# shift by < 32?
2081	subu	t9, t9, v1			# shift right by >= 32
2082	subu	v1, v1, t9
2083	sltu	v0, zero, t8			# be sure to save any one bits
2084	sll	t8, t2, v1			# save bits shifted out
2085	or	t8, t8, v0			# include sticky bits
2086	srl	t3, t2, t9
2087	move	t2, zero
2088	b	2f
20891:
2090	subu	v1, v1, t9			# shift right by t9
2091	sltu	v0, zero, t8			# be sure to save any one bits
2092	sll	t8, t3, v1			# save bits shifted out
2093	or	t8, t8, v0			# include sticky bits
2094	srl	t3, t3, t9
2095	sll	v0, t2, v1			# save bits shifted out
2096	or	t3, t3, v0
2097	srl	t2, t2, t9
2098/*
2099 * Now round the denormalized result.
2100 */
21012:
2102	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
2103	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
2104	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
2105	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
2106	beq	t0, zero, 5f			# if sign is positive, truncate
2107	b	2f
21081:
2109	bne	t0, zero, 5f			# if sign is negative, truncate
21102:
2111	beq	t8, zero, 5f			# if exact, continue
2112	addu	t3, t3, 1			# add rounding bit
2113	bne	t3, zero, 5f			# if no carry, continue
2114	addu	t2, t2, 1			# add carry
2115	b	5f
21163:
2117	li	v0, GUARDBIT			# load guard bit for rounding
2118	addu	v0, v0, t8			# add remainder
2119	sltu	v1, v0, t8			# compute carry out
2120	beq	v1, zero, 4f			# if no carry, continue
2121	addu	t3, t3, 1			# add rounding bit
2122	bne	t3, zero, 4f			# if no carry, continue
2123	addu	t2, t2, 1			# add carry
21244:
2125	bne	v0, zero, 5f			# if rounded remainder is zero
2126	and	t3, t3, ~1			#  clear LSB (round to nearest)
21275:
2128	move	t1, zero			# denorm or zero exponent
2129	jal	set_fd_d			# save result
2130	beq	t8, zero, done			# check for exact result
2131	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
2132	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
2133	and	v0, a1, MACH_FPC_ENABLE_INEXACT
2134	bne	v0, zero, fpe_trap
2135	ctc1	a1, MACH_FPC_CSR		# save exceptions
2136	b	done
2137
2138/*
2139 * Signal an invalid operation if the trap is enabled; otherwise,
2140 * the result is a quiet NAN.
2141 */
2142invalid_s:					# trap invalid operation
2143	or	a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID
2144	and	v0, a1, MACH_FPC_ENABLE_INVALID
2145	bne	v0, zero, fpe_trap
2146	ctc1	a1, MACH_FPC_CSR		# save exceptions
2147	move	t0, zero			# result is a quiet NAN
2148	li	t1, SEXP_INF
2149	li	t2, SQUIET_NAN
2150	jal	set_fd_s			# save result (in t0,t1,t2)
2151	b	done
2152
2153/*
2154 * Signal an invalid operation if the trap is enabled; otherwise,
2155 * the result is a quiet NAN.
2156 */
2157invalid_d:					# trap invalid operation
2158	or	a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID
2159	and	v0, a1, MACH_FPC_ENABLE_INVALID
2160	bne	v0, zero, fpe_trap
2161	ctc1	a1, MACH_FPC_CSR		# save exceptions
2162	move	t0, zero			# result is a quiet NAN
2163	li	t1, DEXP_INF
2164	li	t2, DQUIET_NAN0
2165	li	t3, DQUIET_NAN1
2166	jal	set_fd_d			# save result (in t0,t1,t2,t3)
2167	b	done
2168
2169/*
2170 * Signal an invalid operation if the trap is enabled; otherwise,
2171 * the result is INT_MAX or INT_MIN.
2172 */
2173invalid_w:					# trap invalid operation
2174	or	a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID
2175	and	v0, a1, MACH_FPC_ENABLE_INVALID
2176	bne	v0, zero, fpe_trap
2177	ctc1	a1, MACH_FPC_CSR		# save exceptions
2178	bne	t0, zero, 1f
2179	li	t2, INT_MAX			# result is INT_MAX
2180	b	result_fs_w
21811:
2182	li	t2, INT_MIN			# result is INT_MIN
2183	b	result_fs_w
2184
2185/*
2186 * Trap if the hardware should have handled this case.
2187 */
2188fpe_trap:
2189	move	a2, a1				# code = FP CSR
2190	ctc1	a1, MACH_FPC_CSR		# save exceptions
2191	break	0
2192
2193/*
2194 * Send an illegal instruction signal to the current process.
2195 */
2196ill:
2197	ctc1	a1, MACH_FPC_CSR		# save exceptions
2198	move	a2, a0				# code = FP instruction
2199	break	0
2200
2201result_ft_s:
2202	move	t0, t4				# result is FT
2203	move	t1, t5
2204	move	t2, t6
2205result_fs_s:					# result is FS
2206	jal	set_fd_s			# save result (in t0,t1,t2)
2207	b	done
2208
2209result_fs_w:
2210	jal	set_fd_word			# save result (in t2)
2211	b	done
2212
2213result_ft_d:
2214	move	t0, t4				# result is FT
2215	move	t1, t5
2216	move	t2, t6
2217	move	t3, t7
2218result_fs_d:					# result is FS
2219	jal	set_fd_d			# save result (in t0,t1,t2,t3)
2220
2221done:
2222	lw	ra, STAND_RA_OFFSET(sp)
2223	addu	sp, sp, STAND_FRAME_SIZE
2224	j	ra
2225END(MachEmulateFP)
2226
2227/*----------------------------------------------------------------------------
2228 * get_fs_int --
2229 *
2230 *	Read (integer) the FS register (bits 15-11).
2231 *	This is an internal routine used by MachEmulateFP only.
2232 *
2233 * Results:
2234 *	t0	contains the sign
2235 *	t2	contains the fraction
2236 *
2237 *----------------------------------------------------------------------------
2238 */
2239LEAF(get_fs_int)
2240	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2241	and	a3, a3, 0xF << 2		# mask FS field
2242	lw	a3, get_fs_int_tbl(a3)		# switch on register number
2243	j	a3
2244
2245	.rdata
2246get_fs_int_tbl:
2247	.word	get_fs_int_f0
2248	.word	get_fs_int_f2
2249	.word	get_fs_int_f4
2250	.word	get_fs_int_f6
2251	.word	get_fs_int_f8
2252	.word	get_fs_int_f10
2253	.word	get_fs_int_f12
2254	.word	get_fs_int_f14
2255	.word	get_fs_int_f16
2256	.word	get_fs_int_f18
2257	.word	get_fs_int_f20
2258	.word	get_fs_int_f22
2259	.word	get_fs_int_f24
2260	.word	get_fs_int_f26
2261	.word	get_fs_int_f28
2262	.word	get_fs_int_f30
2263	.text
2264
2265get_fs_int_f0:
2266	mfc1	t2, $f0
2267	b	get_fs_int_done
2268get_fs_int_f2:
2269	mfc1	t2, $f2
2270	b	get_fs_int_done
2271get_fs_int_f4:
2272	mfc1	t2, $f4
2273	b	get_fs_int_done
2274get_fs_int_f6:
2275	mfc1	t2, $f6
2276	b	get_fs_int_done
2277get_fs_int_f8:
2278	mfc1	t2, $f8
2279	b	get_fs_int_done
2280get_fs_int_f10:
2281	mfc1	t2, $f10
2282	b	get_fs_int_done
2283get_fs_int_f12:
2284	mfc1	t2, $f12
2285	b	get_fs_int_done
2286get_fs_int_f14:
2287	mfc1	t2, $f14
2288	b	get_fs_int_done
2289get_fs_int_f16:
2290	mfc1	t2, $f16
2291	b	get_fs_int_done
2292get_fs_int_f18:
2293	mfc1	t2, $f18
2294	b	get_fs_int_done
2295get_fs_int_f20:
2296	mfc1	t2, $f20
2297	b	get_fs_int_done
2298get_fs_int_f22:
2299	mfc1	t2, $f22
2300	b	get_fs_int_done
2301get_fs_int_f24:
2302	mfc1	t2, $f24
2303	b	get_fs_int_done
2304get_fs_int_f26:
2305	mfc1	t2, $f26
2306	b	get_fs_int_done
2307get_fs_int_f28:
2308	mfc1	t2, $f28
2309	b	get_fs_int_done
2310get_fs_int_f30:
2311	mfc1	t2, $f30
2312get_fs_int_done:
2313	srl	t0, t2, 31		# init the sign bit
2314	bge	t2, zero, 1f
2315	negu	t2
23161:
2317	j	ra
2318END(get_fs_int)
2319
2320/*----------------------------------------------------------------------------
2321 * get_ft_fs_s --
2322 *
2323 *	Read (single precision) the FT register (bits 20-16) and
2324 *	the FS register (bits 15-11) and break up into fields.
2325 *	This is an internal routine used by MachEmulateFP only.
2326 *
2327 * Results:
2328 *	t0	contains the FS sign
2329 *	t1	contains the FS (biased) exponent
2330 *	t2	contains the FS fraction
2331 *	t4	contains the FT sign
2332 *	t5	contains the FT (biased) exponent
2333 *	t6	contains the FT fraction
2334 *
2335 *----------------------------------------------------------------------------
2336 */
2337LEAF(get_ft_fs_s)
2338	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2339	and	a3, a3, 0xF << 2		# mask FT field
2340	lw	a3, get_ft_s_tbl(a3)		# switch on register number
2341	j	a3
2342
2343	.rdata
2344get_ft_s_tbl:
2345	.word	get_ft_s_f0
2346	.word	get_ft_s_f2
2347	.word	get_ft_s_f4
2348	.word	get_ft_s_f6
2349	.word	get_ft_s_f8
2350	.word	get_ft_s_f10
2351	.word	get_ft_s_f12
2352	.word	get_ft_s_f14
2353	.word	get_ft_s_f16
2354	.word	get_ft_s_f18
2355	.word	get_ft_s_f20
2356	.word	get_ft_s_f22
2357	.word	get_ft_s_f24
2358	.word	get_ft_s_f26
2359	.word	get_ft_s_f28
2360	.word	get_ft_s_f30
2361	.text
2362
2363get_ft_s_f0:
2364	mfc1	t4, $f0
2365	b	get_ft_s_done
2366get_ft_s_f2:
2367	mfc1	t4, $f2
2368	b	get_ft_s_done
2369get_ft_s_f4:
2370	mfc1	t4, $f4
2371	b	get_ft_s_done
2372get_ft_s_f6:
2373	mfc1	t4, $f6
2374	b	get_ft_s_done
2375get_ft_s_f8:
2376	mfc1	t4, $f8
2377	b	get_ft_s_done
2378get_ft_s_f10:
2379	mfc1	t4, $f10
2380	b	get_ft_s_done
2381get_ft_s_f12:
2382	mfc1	t4, $f12
2383	b	get_ft_s_done
2384get_ft_s_f14:
2385	mfc1	t4, $f14
2386	b	get_ft_s_done
2387get_ft_s_f16:
2388	mfc1	t4, $f16
2389	b	get_ft_s_done
2390get_ft_s_f18:
2391	mfc1	t4, $f18
2392	b	get_ft_s_done
2393get_ft_s_f20:
2394	mfc1	t4, $f20
2395	b	get_ft_s_done
2396get_ft_s_f22:
2397	mfc1	t4, $f22
2398	b	get_ft_s_done
2399get_ft_s_f24:
2400	mfc1	t4, $f24
2401	b	get_ft_s_done
2402get_ft_s_f26:
2403	mfc1	t4, $f26
2404	b	get_ft_s_done
2405get_ft_s_f28:
2406	mfc1	t4, $f28
2407	b	get_ft_s_done
2408get_ft_s_f30:
2409	mfc1	t4, $f30
2410get_ft_s_done:
2411	srl	t5, t4, 23			# get exponent
2412	and	t5, t5, 0xFF
2413	and	t6, t4, 0x7FFFFF		# get fraction
2414	srl	t4, t4, 31			# get sign
2415	bne	t5, SEXP_INF, 1f		# is it a signaling NAN?
2416	and	v0, t6, SSIGNAL_NAN
2417	bne	v0, zero, invalid_s
24181:
2419	/* fall through to get FS */
2420
2421/*----------------------------------------------------------------------------
2422 * get_fs_s --
2423 *
2424 *	Read (single precision) the FS register (bits 15-11) and
2425 *	break up into fields.
2426 *	This is an internal routine used by MachEmulateFP only.
2427 *
2428 * Results:
2429 *	t0	contains the sign
2430 *	t1	contains the (biased) exponent
2431 *	t2	contains the fraction
2432 *
2433 *----------------------------------------------------------------------------
2434 */
2435ALEAF(get_fs_s)
2436	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2437	and	a3, a3, 0xF << 2		# mask FS field
2438	lw	a3, get_fs_s_tbl(a3)		# switch on register number
2439	j	a3
2440
2441	.rdata
2442get_fs_s_tbl:
2443	.word	get_fs_s_f0
2444	.word	get_fs_s_f2
2445	.word	get_fs_s_f4
2446	.word	get_fs_s_f6
2447	.word	get_fs_s_f8
2448	.word	get_fs_s_f10
2449	.word	get_fs_s_f12
2450	.word	get_fs_s_f14
2451	.word	get_fs_s_f16
2452	.word	get_fs_s_f18
2453	.word	get_fs_s_f20
2454	.word	get_fs_s_f22
2455	.word	get_fs_s_f24
2456	.word	get_fs_s_f26
2457	.word	get_fs_s_f28
2458	.word	get_fs_s_f30
2459	.text
2460
2461get_fs_s_f0:
2462	mfc1	t0, $f0
2463	b	get_fs_s_done
2464get_fs_s_f2:
2465	mfc1	t0, $f2
2466	b	get_fs_s_done
2467get_fs_s_f4:
2468	mfc1	t0, $f4
2469	b	get_fs_s_done
2470get_fs_s_f6:
2471	mfc1	t0, $f6
2472	b	get_fs_s_done
2473get_fs_s_f8:
2474	mfc1	t0, $f8
2475	b	get_fs_s_done
2476get_fs_s_f10:
2477	mfc1	t0, $f10
2478	b	get_fs_s_done
2479get_fs_s_f12:
2480	mfc1	t0, $f12
2481	b	get_fs_s_done
2482get_fs_s_f14:
2483	mfc1	t0, $f14
2484	b	get_fs_s_done
2485get_fs_s_f16:
2486	mfc1	t0, $f16
2487	b	get_fs_s_done
2488get_fs_s_f18:
2489	mfc1	t0, $f18
2490	b	get_fs_s_done
2491get_fs_s_f20:
2492	mfc1	t0, $f20
2493	b	get_fs_s_done
2494get_fs_s_f22:
2495	mfc1	t0, $f22
2496	b	get_fs_s_done
2497get_fs_s_f24:
2498	mfc1	t0, $f24
2499	b	get_fs_s_done
2500get_fs_s_f26:
2501	mfc1	t0, $f26
2502	b	get_fs_s_done
2503get_fs_s_f28:
2504	mfc1	t0, $f28
2505	b	get_fs_s_done
2506get_fs_s_f30:
2507	mfc1	t0, $f30
2508get_fs_s_done:
2509	srl	t1, t0, 23			# get exponent
2510	and	t1, t1, 0xFF
2511	and	t2, t0, 0x7FFFFF		# get fraction
2512	srl	t0, t0, 31			# get sign
2513	bne	t1, SEXP_INF, 1f		# is it a signaling NAN?
2514	and	v0, t2, SSIGNAL_NAN
2515	bne	v0, zero, invalid_s
25161:
2517	j	ra
2518END(get_ft_fs_s)
2519
2520/*----------------------------------------------------------------------------
2521 * get_ft_fs_d --
2522 *
2523 *	Read (double precision) the FT register (bits 20-16) and
2524 *	the FS register (bits 15-11) and break up into fields.
2525 *	This is an internal routine used by MachEmulateFP only.
2526 *
2527 * Results:
2528 *	t0	contains the FS sign
2529 *	t1	contains the FS (biased) exponent
2530 *	t2	contains the FS fraction
2531 *	t3	contains the FS remaining fraction
2532 *	t4	contains the FT sign
2533 *	t5	contains the FT (biased) exponent
2534 *	t6	contains the FT fraction
2535 *	t7	contains the FT remaining fraction
2536 *
2537 *----------------------------------------------------------------------------
2538 */
2539LEAF(get_ft_fs_d)
2540	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2541	and	a3, a3, 0xF << 2		# mask FT field
2542	lw	a3, get_ft_d_tbl(a3)		# switch on register number
2543	j	a3
2544
2545	.rdata
2546get_ft_d_tbl:
2547	.word	get_ft_d_f0
2548	.word	get_ft_d_f2
2549	.word	get_ft_d_f4
2550	.word	get_ft_d_f6
2551	.word	get_ft_d_f8
2552	.word	get_ft_d_f10
2553	.word	get_ft_d_f12
2554	.word	get_ft_d_f14
2555	.word	get_ft_d_f16
2556	.word	get_ft_d_f18
2557	.word	get_ft_d_f20
2558	.word	get_ft_d_f22
2559	.word	get_ft_d_f24
2560	.word	get_ft_d_f26
2561	.word	get_ft_d_f28
2562	.word	get_ft_d_f30
2563	.text
2564
2565get_ft_d_f0:
2566	mfc1	t7, $f0
2567	mfc1	t4, $f1
2568	b	get_ft_d_done
2569get_ft_d_f2:
2570	mfc1	t7, $f2
2571	mfc1	t4, $f3
2572	b	get_ft_d_done
2573get_ft_d_f4:
2574	mfc1	t7, $f4
2575	mfc1	t4, $f5
2576	b	get_ft_d_done
2577get_ft_d_f6:
2578	mfc1	t7, $f6
2579	mfc1	t4, $f7
2580	b	get_ft_d_done
2581get_ft_d_f8:
2582	mfc1	t7, $f8
2583	mfc1	t4, $f9
2584	b	get_ft_d_done
2585get_ft_d_f10:
2586	mfc1	t7, $f10
2587	mfc1	t4, $f11
2588	b	get_ft_d_done
2589get_ft_d_f12:
2590	mfc1	t7, $f12
2591	mfc1	t4, $f13
2592	b	get_ft_d_done
2593get_ft_d_f14:
2594	mfc1	t7, $f14
2595	mfc1	t4, $f15
2596	b	get_ft_d_done
2597get_ft_d_f16:
2598	mfc1	t7, $f16
2599	mfc1	t4, $f17
2600	b	get_ft_d_done
2601get_ft_d_f18:
2602	mfc1	t7, $f18
2603	mfc1	t4, $f19
2604	b	get_ft_d_done
2605get_ft_d_f20:
2606	mfc1	t7, $f20
2607	mfc1	t4, $f21
2608	b	get_ft_d_done
2609get_ft_d_f22:
2610	mfc1	t7, $f22
2611	mfc1	t4, $f23
2612	b	get_ft_d_done
2613get_ft_d_f24:
2614	mfc1	t7, $f24
2615	mfc1	t4, $f25
2616	b	get_ft_d_done
2617get_ft_d_f26:
2618	mfc1	t7, $f26
2619	mfc1	t4, $f27
2620	b	get_ft_d_done
2621get_ft_d_f28:
2622	mfc1	t7, $f28
2623	mfc1	t4, $f29
2624	b	get_ft_d_done
2625get_ft_d_f30:
2626	mfc1	t7, $f30
2627	mfc1	t4, $f31
2628get_ft_d_done:
2629	srl	t5, t4, 20			# get exponent
2630	and	t5, t5, 0x7FF
2631	and	t6, t4, 0xFFFFF			# get fraction
2632	srl	t4, t4, 31			# get sign
2633	bne	t5, DEXP_INF, 1f		# is it a signaling NAN?
2634	and	v0, t6, DSIGNAL_NAN
2635	bne	v0, zero, invalid_d
26361:
2637	/* fall through to get FS */
2638
2639/*----------------------------------------------------------------------------
2640 * get_fs_d --
2641 *
2642 *	Read (double precision) the FS register (bits 15-11) and
2643 *	break up into fields.
2644 *	This is an internal routine used by MachEmulateFP only.
2645 *
2646 * Results:
2647 *	t0	contains the sign
2648 *	t1	contains the (biased) exponent
2649 *	t2	contains the fraction
2650 *	t3	contains the remaining fraction
2651 *
2652 *----------------------------------------------------------------------------
2653 */
2654ALEAF(get_fs_d)
2655	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2656	and	a3, a3, 0xF << 2		# mask FS field
2657	lw	a3, get_fs_d_tbl(a3)		# switch on register number
2658	j	a3
2659
2660	.rdata
2661get_fs_d_tbl:
2662	.word	get_fs_d_f0
2663	.word	get_fs_d_f2
2664	.word	get_fs_d_f4
2665	.word	get_fs_d_f6
2666	.word	get_fs_d_f8
2667	.word	get_fs_d_f10
2668	.word	get_fs_d_f12
2669	.word	get_fs_d_f14
2670	.word	get_fs_d_f16
2671	.word	get_fs_d_f18
2672	.word	get_fs_d_f20
2673	.word	get_fs_d_f22
2674	.word	get_fs_d_f24
2675	.word	get_fs_d_f26
2676	.word	get_fs_d_f28
2677	.word	get_fs_d_f30
2678	.text
2679
2680get_fs_d_f0:
2681	mfc1	t3, $f0
2682	mfc1	t0, $f1
2683	b	get_fs_d_done
2684get_fs_d_f2:
2685	mfc1	t3, $f2
2686	mfc1	t0, $f3
2687	b	get_fs_d_done
2688get_fs_d_f4:
2689	mfc1	t3, $f4
2690	mfc1	t0, $f5
2691	b	get_fs_d_done
2692get_fs_d_f6:
2693	mfc1	t3, $f6
2694	mfc1	t0, $f7
2695	b	get_fs_d_done
2696get_fs_d_f8:
2697	mfc1	t3, $f8
2698	mfc1	t0, $f9
2699	b	get_fs_d_done
2700get_fs_d_f10:
2701	mfc1	t3, $f10
2702	mfc1	t0, $f11
2703	b	get_fs_d_done
2704get_fs_d_f12:
2705	mfc1	t3, $f12
2706	mfc1	t0, $f13
2707	b	get_fs_d_done
2708get_fs_d_f14:
2709	mfc1	t3, $f14
2710	mfc1	t0, $f15
2711	b	get_fs_d_done
2712get_fs_d_f16:
2713	mfc1	t3, $f16
2714	mfc1	t0, $f17
2715	b	get_fs_d_done
2716get_fs_d_f18:
2717	mfc1	t3, $f18
2718	mfc1	t0, $f19
2719	b	get_fs_d_done
2720get_fs_d_f20:
2721	mfc1	t3, $f20
2722	mfc1	t0, $f21
2723	b	get_fs_d_done
2724get_fs_d_f22:
2725	mfc1	t3, $f22
2726	mfc1	t0, $f23
2727	b	get_fs_d_done
2728get_fs_d_f24:
2729	mfc1	t3, $f24
2730	mfc1	t0, $f25
2731	b	get_fs_d_done
2732get_fs_d_f26:
2733	mfc1	t3, $f26
2734	mfc1	t0, $f27
2735	b	get_fs_d_done
2736get_fs_d_f28:
2737	mfc1	t3, $f28
2738	mfc1	t0, $f29
2739	b	get_fs_d_done
2740get_fs_d_f30:
2741	mfc1	t3, $f30
2742	mfc1	t0, $f31
2743get_fs_d_done:
2744	srl	t1, t0, 20			# get exponent
2745	and	t1, t1, 0x7FF
2746	and	t2, t0, 0xFFFFF			# get fraction
2747	srl	t0, t0, 31			# get sign
2748	bne	t1, DEXP_INF, 1f		# is it a signaling NAN?
2749	and	v0, t2, DSIGNAL_NAN
2750	bne	v0, zero, invalid_d
27511:
2752	j	ra
2753END(get_ft_fs_d)
2754
2755/*----------------------------------------------------------------------------
2756 * get_cmp_s --
2757 *
2758 *	Read (single precision) the FS register (bits 15-11) and
2759 *	the FT register (bits 20-16) and break up into fields.
2760 *	This is an internal routine used by MachEmulateFP only.
2761 *
2762 * Results:
2763 *	t0	contains the sign
2764 *	t1	contains the (biased) exponent
2765 *	t2	contains the fraction
2766 *	t4	contains the sign
2767 *	t5	contains the (biased) exponent
2768 *	t6	contains the fraction
2769 *
2770 *----------------------------------------------------------------------------
2771 */
2772LEAF(get_cmp_s)
2773	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2774	and	a3, a3, 0xF << 2		# mask FS field
2775	lw	a3, cmp_fs_s_tbl(a3)		# switch on register number
2776	j	a3
2777
2778	.rdata
2779cmp_fs_s_tbl:
2780	.word	cmp_fs_s_f0
2781	.word	cmp_fs_s_f2
2782	.word	cmp_fs_s_f4
2783	.word	cmp_fs_s_f6
2784	.word	cmp_fs_s_f8
2785	.word	cmp_fs_s_f10
2786	.word	cmp_fs_s_f12
2787	.word	cmp_fs_s_f14
2788	.word	cmp_fs_s_f16
2789	.word	cmp_fs_s_f18
2790	.word	cmp_fs_s_f20
2791	.word	cmp_fs_s_f22
2792	.word	cmp_fs_s_f24
2793	.word	cmp_fs_s_f26
2794	.word	cmp_fs_s_f28
2795	.word	cmp_fs_s_f30
2796	.text
2797
2798cmp_fs_s_f0:
2799	mfc1	t0, $f0
2800	b	cmp_fs_s_done
2801cmp_fs_s_f2:
2802	mfc1	t0, $f2
2803	b	cmp_fs_s_done
2804cmp_fs_s_f4:
2805	mfc1	t0, $f4
2806	b	cmp_fs_s_done
2807cmp_fs_s_f6:
2808	mfc1	t0, $f6
2809	b	cmp_fs_s_done
2810cmp_fs_s_f8:
2811	mfc1	t0, $f8
2812	b	cmp_fs_s_done
2813cmp_fs_s_f10:
2814	mfc1	t0, $f10
2815	b	cmp_fs_s_done
2816cmp_fs_s_f12:
2817	mfc1	t0, $f12
2818	b	cmp_fs_s_done
2819cmp_fs_s_f14:
2820	mfc1	t0, $f14
2821	b	cmp_fs_s_done
2822cmp_fs_s_f16:
2823	mfc1	t0, $f16
2824	b	cmp_fs_s_done
2825cmp_fs_s_f18:
2826	mfc1	t0, $f18
2827	b	cmp_fs_s_done
2828cmp_fs_s_f20:
2829	mfc1	t0, $f20
2830	b	cmp_fs_s_done
2831cmp_fs_s_f22:
2832	mfc1	t0, $f22
2833	b	cmp_fs_s_done
2834cmp_fs_s_f24:
2835	mfc1	t0, $f24
2836	b	cmp_fs_s_done
2837cmp_fs_s_f26:
2838	mfc1	t0, $f26
2839	b	cmp_fs_s_done
2840cmp_fs_s_f28:
2841	mfc1	t0, $f28
2842	b	cmp_fs_s_done
2843cmp_fs_s_f30:
2844	mfc1	t0, $f30
2845cmp_fs_s_done:
2846	srl	t1, t0, 23			# get exponent
2847	and	t1, t1, 0xFF
2848	and	t2, t0, 0x7FFFFF		# get fraction
2849	srl	t0, t0, 31			# get sign
2850
2851	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2852	and	a3, a3, 0xF << 2		# mask FT field
2853	lw	a3, cmp_ft_s_tbl(a3)		# switch on register number
2854	j	a3
2855
2856	.rdata
2857cmp_ft_s_tbl:
2858	.word	cmp_ft_s_f0
2859	.word	cmp_ft_s_f2
2860	.word	cmp_ft_s_f4
2861	.word	cmp_ft_s_f6
2862	.word	cmp_ft_s_f8
2863	.word	cmp_ft_s_f10
2864	.word	cmp_ft_s_f12
2865	.word	cmp_ft_s_f14
2866	.word	cmp_ft_s_f16
2867	.word	cmp_ft_s_f18
2868	.word	cmp_ft_s_f20
2869	.word	cmp_ft_s_f22
2870	.word	cmp_ft_s_f24
2871	.word	cmp_ft_s_f26
2872	.word	cmp_ft_s_f28
2873	.word	cmp_ft_s_f30
2874	.text
2875
2876cmp_ft_s_f0:
2877	mfc1	t4, $f0
2878	b	cmp_ft_s_done
2879cmp_ft_s_f2:
2880	mfc1	t4, $f2
2881	b	cmp_ft_s_done
2882cmp_ft_s_f4:
2883	mfc1	t4, $f4
2884	b	cmp_ft_s_done
2885cmp_ft_s_f6:
2886	mfc1	t4, $f6
2887	b	cmp_ft_s_done
2888cmp_ft_s_f8:
2889	mfc1	t4, $f8
2890	b	cmp_ft_s_done
2891cmp_ft_s_f10:
2892	mfc1	t4, $f10
2893	b	cmp_ft_s_done
2894cmp_ft_s_f12:
2895	mfc1	t4, $f12
2896	b	cmp_ft_s_done
2897cmp_ft_s_f14:
2898	mfc1	t4, $f14
2899	b	cmp_ft_s_done
2900cmp_ft_s_f16:
2901	mfc1	t4, $f16
2902	b	cmp_ft_s_done
2903cmp_ft_s_f18:
2904	mfc1	t4, $f18
2905	b	cmp_ft_s_done
2906cmp_ft_s_f20:
2907	mfc1	t4, $f20
2908	b	cmp_ft_s_done
2909cmp_ft_s_f22:
2910	mfc1	t4, $f22
2911	b	cmp_ft_s_done
2912cmp_ft_s_f24:
2913	mfc1	t4, $f24
2914	b	cmp_ft_s_done
2915cmp_ft_s_f26:
2916	mfc1	t4, $f26
2917	b	cmp_ft_s_done
2918cmp_ft_s_f28:
2919	mfc1	t4, $f28
2920	b	cmp_ft_s_done
2921cmp_ft_s_f30:
2922	mfc1	t4, $f30
2923cmp_ft_s_done:
2924	srl	t5, t4, 23			# get exponent
2925	and	t5, t5, 0xFF
2926	and	t6, t4, 0x7FFFFF		# get fraction
2927	srl	t4, t4, 31			# get sign
2928	j	ra
2929END(get_cmp_s)
2930
2931/*----------------------------------------------------------------------------
2932 * get_cmp_d --
2933 *
2934 *	Read (double precision) the FS register (bits 15-11) and
2935 *	the FT register (bits 20-16) and break up into fields.
2936 *	This is an internal routine used by MachEmulateFP only.
2937 *
2938 * Results:
2939 *	t0	contains the sign
2940 *	t1	contains the (biased) exponent
2941 *	t2	contains the fraction
2942 *	t3	contains the remaining fraction
2943 *	t4	contains the sign
2944 *	t5	contains the (biased) exponent
2945 *	t6	contains the fraction
2946 *	t7	contains the remaining fraction
2947 *
2948 *----------------------------------------------------------------------------
2949 */
2950LEAF(get_cmp_d)
2951	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2952	and	a3, a3, 0xF << 2		# mask FS field
2953	lw	a3, cmp_fs_d_tbl(a3)		# switch on register number
2954	j	a3
2955
2956	.rdata
2957cmp_fs_d_tbl:
2958	.word	cmp_fs_d_f0
2959	.word	cmp_fs_d_f2
2960	.word	cmp_fs_d_f4
2961	.word	cmp_fs_d_f6
2962	.word	cmp_fs_d_f8
2963	.word	cmp_fs_d_f10
2964	.word	cmp_fs_d_f12
2965	.word	cmp_fs_d_f14
2966	.word	cmp_fs_d_f16
2967	.word	cmp_fs_d_f18
2968	.word	cmp_fs_d_f20
2969	.word	cmp_fs_d_f22
2970	.word	cmp_fs_d_f24
2971	.word	cmp_fs_d_f26
2972	.word	cmp_fs_d_f28
2973	.word	cmp_fs_d_f30
2974	.text
2975
2976cmp_fs_d_f0:
2977	mfc1	t3, $f0
2978	mfc1	t0, $f1
2979	b	cmp_fs_d_done
2980cmp_fs_d_f2:
2981	mfc1	t3, $f2
2982	mfc1	t0, $f3
2983	b	cmp_fs_d_done
2984cmp_fs_d_f4:
2985	mfc1	t3, $f4
2986	mfc1	t0, $f5
2987	b	cmp_fs_d_done
2988cmp_fs_d_f6:
2989	mfc1	t3, $f6
2990	mfc1	t0, $f7
2991	b	cmp_fs_d_done
2992cmp_fs_d_f8:
2993	mfc1	t3, $f8
2994	mfc1	t0, $f9
2995	b	cmp_fs_d_done
2996cmp_fs_d_f10:
2997	mfc1	t3, $f10
2998	mfc1	t0, $f11
2999	b	cmp_fs_d_done
3000cmp_fs_d_f12:
3001	mfc1	t3, $f12
3002	mfc1	t0, $f13
3003	b	cmp_fs_d_done
3004cmp_fs_d_f14:
3005	mfc1	t3, $f14
3006	mfc1	t0, $f15
3007	b	cmp_fs_d_done
3008cmp_fs_d_f16:
3009	mfc1	t3, $f16
3010	mfc1	t0, $f17
3011	b	cmp_fs_d_done
3012cmp_fs_d_f18:
3013	mfc1	t3, $f18
3014	mfc1	t0, $f19
3015	b	cmp_fs_d_done
3016cmp_fs_d_f20:
3017	mfc1	t3, $f20
3018	mfc1	t0, $f21
3019	b	cmp_fs_d_done
3020cmp_fs_d_f22:
3021	mfc1	t3, $f22
3022	mfc1	t0, $f23
3023	b	cmp_fs_d_done
3024cmp_fs_d_f24:
3025	mfc1	t3, $f24
3026	mfc1	t0, $f25
3027	b	cmp_fs_d_done
3028cmp_fs_d_f26:
3029	mfc1	t3, $f26
3030	mfc1	t0, $f27
3031	b	cmp_fs_d_done
3032cmp_fs_d_f28:
3033	mfc1	t3, $f28
3034	mfc1	t0, $f29
3035	b	cmp_fs_d_done
3036cmp_fs_d_f30:
3037	mfc1	t3, $f30
3038	mfc1	t0, $f31
3039cmp_fs_d_done:
3040	srl	t1, t0, 20			# get exponent
3041	and	t1, t1, 0x7FF
3042	and	t2, t0, 0xFFFFF			# get fraction
3043	srl	t0, t0, 31			# get sign
3044
3045	srl	a3, a0, 17 - 2			# get FT field (even regs only)
3046	and	a3, a3, 0xF << 2		# mask FT field
3047	lw	a3, cmp_ft_d_tbl(a3)		# switch on register number
3048	j	a3
3049
3050	.rdata
3051cmp_ft_d_tbl:
3052	.word	cmp_ft_d_f0
3053	.word	cmp_ft_d_f2
3054	.word	cmp_ft_d_f4
3055	.word	cmp_ft_d_f6
3056	.word	cmp_ft_d_f8
3057	.word	cmp_ft_d_f10
3058	.word	cmp_ft_d_f12
3059	.word	cmp_ft_d_f14
3060	.word	cmp_ft_d_f16
3061	.word	cmp_ft_d_f18
3062	.word	cmp_ft_d_f20
3063	.word	cmp_ft_d_f22
3064	.word	cmp_ft_d_f24
3065	.word	cmp_ft_d_f26
3066	.word	cmp_ft_d_f28
3067	.word	cmp_ft_d_f30
3068	.text
3069
3070cmp_ft_d_f0:
3071	mfc1	t7, $f0
3072	mfc1	t4, $f1
3073	b	cmp_ft_d_done
3074cmp_ft_d_f2:
3075	mfc1	t7, $f2
3076	mfc1	t4, $f3
3077	b	cmp_ft_d_done
3078cmp_ft_d_f4:
3079	mfc1	t7, $f4
3080	mfc1	t4, $f5
3081	b	cmp_ft_d_done
3082cmp_ft_d_f6:
3083	mfc1	t7, $f6
3084	mfc1	t4, $f7
3085	b	cmp_ft_d_done
3086cmp_ft_d_f8:
3087	mfc1	t7, $f8
3088	mfc1	t4, $f9
3089	b	cmp_ft_d_done
3090cmp_ft_d_f10:
3091	mfc1	t7, $f10
3092	mfc1	t4, $f11
3093	b	cmp_ft_d_done
3094cmp_ft_d_f12:
3095	mfc1	t7, $f12
3096	mfc1	t4, $f13
3097	b	cmp_ft_d_done
3098cmp_ft_d_f14:
3099	mfc1	t7, $f14
3100	mfc1	t4, $f15
3101	b	cmp_ft_d_done
3102cmp_ft_d_f16:
3103	mfc1	t7, $f16
3104	mfc1	t4, $f17
3105	b	cmp_ft_d_done
3106cmp_ft_d_f18:
3107	mfc1	t7, $f18
3108	mfc1	t4, $f19
3109	b	cmp_ft_d_done
3110cmp_ft_d_f20:
3111	mfc1	t7, $f20
3112	mfc1	t4, $f21
3113	b	cmp_ft_d_done
3114cmp_ft_d_f22:
3115	mfc1	t7, $f22
3116	mfc1	t4, $f23
3117	b	cmp_ft_d_done
3118cmp_ft_d_f24:
3119	mfc1	t7, $f24
3120	mfc1	t4, $f25
3121	b	cmp_ft_d_done
3122cmp_ft_d_f26:
3123	mfc1	t7, $f26
3124	mfc1	t4, $f27
3125	b	cmp_ft_d_done
3126cmp_ft_d_f28:
3127	mfc1	t7, $f28
3128	mfc1	t4, $f29
3129	b	cmp_ft_d_done
3130cmp_ft_d_f30:
3131	mfc1	t7, $f30
3132	mfc1	t4, $f31
3133cmp_ft_d_done:
3134	srl	t5, t4, 20			# get exponent
3135	and	t5, t5, 0x7FF
3136	and	t6, t4, 0xFFFFF			# get fraction
3137	srl	t4, t4, 31			# get sign
3138	j	ra
3139END(get_cmp_d)
3140
3141/*----------------------------------------------------------------------------
3142 * set_fd_s --
3143 *
3144 *	Write (single precision) the FD register (bits 10-6).
3145 *	This is an internal routine used by MachEmulateFP only.
3146 *
3147 * Arguments:
3148 *	a0	contains the FP instruction
3149 *	t0	contains the sign
3150 *	t1	contains the (biased) exponent
3151 *	t2	contains the fraction
3152 *
3153 * set_fd_word --
3154 *
3155 *	Write (integer) the FD register (bits 10-6).
3156 *	This is an internal routine used by MachEmulateFP only.
3157 *
3158 * Arguments:
3159 *	a0	contains the FP instruction
3160 *	t2	contains the integer
3161 *
3162 *----------------------------------------------------------------------------
3163 */
3164LEAF(set_fd_s)
3165	sll	t0, t0, 31			# position sign
3166	sll	t1, t1, 23			# position exponent
3167	or	t2, t2, t0
3168	or	t2, t2, t1
3169ALEAF(set_fd_word)
3170	srl	a3, a0, 7 - 2			# get FD field (even regs only)
3171	and	a3, a3, 0xF << 2		# mask FT field
3172	lw	a3, set_fd_s_tbl(a3)		# switch on register number
3173	j	a3
3174
3175	.rdata
3176set_fd_s_tbl:
3177	.word	set_fd_s_f0
3178	.word	set_fd_s_f2
3179	.word	set_fd_s_f4
3180	.word	set_fd_s_f6
3181	.word	set_fd_s_f8
3182	.word	set_fd_s_f10
3183	.word	set_fd_s_f12
3184	.word	set_fd_s_f14
3185	.word	set_fd_s_f16
3186	.word	set_fd_s_f18
3187	.word	set_fd_s_f20
3188	.word	set_fd_s_f22
3189	.word	set_fd_s_f24
3190	.word	set_fd_s_f26
3191	.word	set_fd_s_f28
3192	.word	set_fd_s_f30
3193	.text
3194
3195set_fd_s_f0:
3196	mtc1	t2, $f0
3197	j	ra
3198set_fd_s_f2:
3199	mtc1	t2, $f2
3200	j	ra
3201set_fd_s_f4:
3202	mtc1	t2, $f4
3203	j	ra
3204set_fd_s_f6:
3205	mtc1	t2, $f6
3206	j	ra
3207set_fd_s_f8:
3208	mtc1	t2, $f8
3209	j	ra
3210set_fd_s_f10:
3211	mtc1	t2, $f10
3212	j	ra
3213set_fd_s_f12:
3214	mtc1	t2, $f12
3215	j	ra
3216set_fd_s_f14:
3217	mtc1	t2, $f14
3218	j	ra
3219set_fd_s_f16:
3220	mtc1	t2, $f16
3221	j	ra
3222set_fd_s_f18:
3223	mtc1	t2, $f18
3224	j	ra
3225set_fd_s_f20:
3226	mtc1	t2, $f20
3227	j	ra
3228set_fd_s_f22:
3229	mtc1	t2, $f22
3230	j	ra
3231set_fd_s_f24:
3232	mtc1	t2, $f24
3233	j	ra
3234set_fd_s_f26:
3235	mtc1	t2, $f26
3236	j	ra
3237set_fd_s_f28:
3238	mtc1	t2, $f28
3239	j	ra
3240set_fd_s_f30:
3241	mtc1	t2, $f30
3242	j	ra
3243END(set_fd_s)
3244
3245/*----------------------------------------------------------------------------
3246 * set_fd_d --
3247 *
3248 *	Write (double precision) the FT register (bits 10-6).
3249 *	This is an internal routine used by MachEmulateFP only.
3250 *
3251 * Arguments:
3252 *	a0	contains the FP instruction
3253 *	t0	contains the sign
3254 *	t1	contains the (biased) exponent
3255 *	t2	contains the fraction
3256 *	t3	contains the remaining fraction
3257 *
3258 *----------------------------------------------------------------------------
3259 */
3260LEAF(set_fd_d)
3261	sll	t0, t0, 31			# set sign
3262	sll	t1, t1, 20			# set exponent
3263	or	t0, t0, t1
3264	or	t0, t0, t2			# set fraction
3265	srl	a3, a0, 7 - 2			# get FD field (even regs only)
3266	and	a3, a3, 0xF << 2		# mask FD field
3267	lw	a3, set_fd_d_tbl(a3)		# switch on register number
3268	j	a3
3269
3270	.rdata
3271set_fd_d_tbl:
3272	.word	set_fd_d_f0
3273	.word	set_fd_d_f2
3274	.word	set_fd_d_f4
3275	.word	set_fd_d_f6
3276	.word	set_fd_d_f8
3277	.word	set_fd_d_f10
3278	.word	set_fd_d_f12
3279	.word	set_fd_d_f14
3280	.word	set_fd_d_f16
3281	.word	set_fd_d_f18
3282	.word	set_fd_d_f20
3283	.word	set_fd_d_f22
3284	.word	set_fd_d_f24
3285	.word	set_fd_d_f26
3286	.word	set_fd_d_f28
3287	.word	set_fd_d_f30
3288	.text
3289
3290set_fd_d_f0:
3291	mtc1	t3, $f0
3292	mtc1	t0, $f1
3293	j	ra
3294set_fd_d_f2:
3295	mtc1	t3, $f2
3296	mtc1	t0, $f3
3297	j	ra
3298set_fd_d_f4:
3299	mtc1	t3, $f4
3300	mtc1	t0, $f5
3301	j	ra
3302set_fd_d_f6:
3303	mtc1	t3, $f6
3304	mtc1	t0, $f7
3305	j	ra
3306set_fd_d_f8:
3307	mtc1	t3, $f8
3308	mtc1	t0, $f9
3309	j	ra
3310set_fd_d_f10:
3311	mtc1	t3, $f10
3312	mtc1	t0, $f11
3313	j	ra
3314set_fd_d_f12:
3315	mtc1	t3, $f12
3316	mtc1	t0, $f13
3317	j	ra
3318set_fd_d_f14:
3319	mtc1	t3, $f14
3320	mtc1	t0, $f15
3321	j	ra
3322set_fd_d_f16:
3323	mtc1	t3, $f16
3324	mtc1	t0, $f17
3325	j	ra
3326set_fd_d_f18:
3327	mtc1	t3, $f18
3328	mtc1	t0, $f19
3329	j	ra
3330set_fd_d_f20:
3331	mtc1	t3, $f20
3332	mtc1	t0, $f21
3333	j	ra
3334set_fd_d_f22:
3335	mtc1	t3, $f22
3336	mtc1	t0, $f23
3337	j	ra
3338set_fd_d_f24:
3339	mtc1	t3, $f24
3340	mtc1	t0, $f25
3341	j	ra
3342set_fd_d_f26:
3343	mtc1	t3, $f26
3344	mtc1	t0, $f27
3345	j	ra
3346set_fd_d_f28:
3347	mtc1	t3, $f28
3348	mtc1	t0, $f29
3349	j	ra
3350set_fd_d_f30:
3351	mtc1	t3, $f30
3352	mtc1	t0, $f31
3353	j	ra
3354END(set_fd_d)
3355
3356/*----------------------------------------------------------------------------
3357 * renorm_fs_s --
3358 *
3359 * Results:
3360 *	t1	unbiased exponent
3361 *	t2	normalized fraction
3362 *
3363 *----------------------------------------------------------------------------
3364 */
3365LEAF(renorm_fs_s)
3366/*
3367 * Find out how many leading zero bits are in t2 and put in t9.
3368 */
3369	move	v0, t2
3370	move	t9, zero
3371	srl	v1, v0, 16
3372	bne	v1, zero, 1f
3373	addu	t9, 16
3374	sll	v0, 16
33751:
3376	srl	v1, v0, 24
3377	bne	v1, zero, 1f
3378	addu	t9, 8
3379	sll	v0, 8
33801:
3381	srl	v1, v0, 28
3382	bne	v1, zero, 1f
3383	addu	t9, 4
3384	sll	v0, 4
33851:
3386	srl	v1, v0, 30
3387	bne	v1, zero, 1f
3388	addu	t9, 2
3389	sll	v0, 2
33901:
3391	srl	v1, v0, 31
3392	bne	v1, zero, 1f
3393	addu	t9, 1
3394/*
3395 * Now shift t2 the correct number of bits.
3396 */
33971:
3398	subu	t9, t9, SLEAD_ZEROS	# don't count normal leading zeros
3399	li	t1, SEXP_MIN
3400	subu	t1, t1, t9		# adjust exponent
3401	sll	t2, t2, t9
3402	j	ra
3403END(renorm_fs_s)
3404
3405/*----------------------------------------------------------------------------
3406 * renorm_fs_d --
3407 *
3408 * Results:
3409 *	t1	unbiased exponent
3410 *	t2,t3	normalized fraction
3411 *
3412 *----------------------------------------------------------------------------
3413 */
3414LEAF(renorm_fs_d)
3415/*
3416 * Find out how many leading zero bits are in t2,t3 and put in t9.
3417 */
3418	move	v0, t2
3419	move	t9, zero
3420	bne	t2, zero, 1f
3421	move	v0, t3
3422	addu	t9, 32
34231:
3424	srl	v1, v0, 16
3425	bne	v1, zero, 1f
3426	addu	t9, 16
3427	sll	v0, 16
34281:
3429	srl	v1, v0, 24
3430	bne	v1, zero, 1f
3431	addu	t9, 8
3432	sll	v0, 8
34331:
3434	srl	v1, v0, 28
3435	bne	v1, zero, 1f
3436	addu	t9, 4
3437	sll	v0, 4
34381:
3439	srl	v1, v0, 30
3440	bne	v1, zero, 1f
3441	addu	t9, 2
3442	sll	v0, 2
34431:
3444	srl	v1, v0, 31
3445	bne	v1, zero, 1f
3446	addu	t9, 1
3447/*
3448 * Now shift t2,t3 the correct number of bits.
3449 */
34501:
3451	subu	t9, t9, DLEAD_ZEROS	# don't count normal leading zeros
3452	li	t1, DEXP_MIN
3453	subu	t1, t1, t9		# adjust exponent
3454	li	v0, 32
3455	blt	t9, v0, 1f
3456	subu	t9, t9, v0		# shift fraction left >= 32 bits
3457	sll	t2, t3, t9
3458	move	t3, zero
3459	j	ra
34601:
3461	subu	v0, v0, t9		# shift fraction left < 32 bits
3462	sll	t2, t2, t9
3463	srl	v1, t3, v0
3464	or	t2, t2, v1
3465	sll	t3, t3, t9
3466	j	ra
3467END(renorm_fs_d)
3468
3469/*----------------------------------------------------------------------------
3470 * renorm_ft_s --
3471 *
3472 * Results:
3473 *	t5	unbiased exponent
3474 *	t6	normalized fraction
3475 *
3476 *----------------------------------------------------------------------------
3477 */
3478LEAF(renorm_ft_s)
3479/*
3480 * Find out how many leading zero bits are in t6 and put in t9.
3481 */
3482	move	v0, t6
3483	move	t9, zero
3484	srl	v1, v0, 16
3485	bne	v1, zero, 1f
3486	addu	t9, 16
3487	sll	v0, 16
34881:
3489	srl	v1, v0, 24
3490	bne	v1, zero, 1f
3491	addu	t9, 8
3492	sll	v0, 8
34931:
3494	srl	v1, v0, 28
3495	bne	v1, zero, 1f
3496	addu	t9, 4
3497	sll	v0, 4
34981:
3499	srl	v1, v0, 30
3500	bne	v1, zero, 1f
3501	addu	t9, 2
3502	sll	v0, 2
35031:
3504	srl	v1, v0, 31
3505	bne	v1, zero, 1f
3506	addu	t9, 1
3507/*
3508 * Now shift t6 the correct number of bits.
3509 */
35101:
3511	subu	t9, t9, SLEAD_ZEROS	# don't count normal leading zeros
3512	li	t5, SEXP_MIN
3513	subu	t5, t5, t9		# adjust exponent
3514	sll	t6, t6, t9
3515	j	ra
3516END(renorm_ft_s)
3517
3518/*----------------------------------------------------------------------------
3519 * renorm_ft_d --
3520 *
3521 * Results:
3522 *	t5	unbiased exponent
3523 *	t6,t7	normalized fraction
3524 *
3525 *----------------------------------------------------------------------------
3526 */
3527LEAF(renorm_ft_d)
3528/*
3529 * Find out how many leading zero bits are in t6,t7 and put in t9.
3530 */
3531	move	v0, t6
3532	move	t9, zero
3533	bne	t6, zero, 1f
3534	move	v0, t7
3535	addu	t9, 32
35361:
3537	srl	v1, v0, 16
3538	bne	v1, zero, 1f
3539	addu	t9, 16
3540	sll	v0, 16
35411:
3542	srl	v1, v0, 24
3543	bne	v1, zero, 1f
3544	addu	t9, 8
3545	sll	v0, 8
35461:
3547	srl	v1, v0, 28
3548	bne	v1, zero, 1f
3549	addu	t9, 4
3550	sll	v0, 4
35511:
3552	srl	v1, v0, 30
3553	bne	v1, zero, 1f
3554	addu	t9, 2
3555	sll	v0, 2
35561:
3557	srl	v1, v0, 31
3558	bne	v1, zero, 1f
3559	addu	t9, 1
3560/*
3561 * Now shift t6,t7 the correct number of bits.
3562 */
35631:
3564	subu	t9, t9, DLEAD_ZEROS	# don't count normal leading zeros
3565	li	t5, DEXP_MIN
3566	subu	t5, t5, t9		# adjust exponent
3567	li	v0, 32
3568	blt	t9, v0, 1f
3569	subu	t9, t9, v0		# shift fraction left >= 32 bits
3570	sll	t6, t7, t9
3571	move	t7, zero
3572	j	ra
35731:
3574	subu	v0, v0, t9		# shift fraction left < 32 bits
3575	sll	t6, t6, t9
3576	srl	v1, t7, v0
3577	or	t6, t6, v1
3578	sll	t7, t7, t9
3579	j	ra
3580END(renorm_ft_d)
3581