xref: /original-bsd/sys/pmax/pmax/fp.s (revision 3705696b)
1/*
2 * Copyright (c) 1992, 1993
3 *	The Regents of the University of California.  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	8.1 (Berkeley) 06/10/93
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
21#include "assym.h"
22
23#define SEXP_INF	0xff
24#define DEXP_INF	0x7ff
25#define SEXP_BIAS	127
26#define DEXP_BIAS	1023
27#define SEXP_MIN	-126
28#define DEXP_MIN	-1022
29#define SEXP_MAX	127
30#define DEXP_MAX	1023
31#define WEXP_MAX	30		/* maximum unbiased exponent for int */
32#define WEXP_MIN	-1		/* minimum unbiased exponent for int */
33#define SFRAC_BITS	23
34#define DFRAC_BITS	52
35#define SIMPL_ONE	0x00800000
36#define DIMPL_ONE	0x00100000
37#define SLEAD_ZEROS	31 - 23
38#define DLEAD_ZEROS	31 - 20
39#define STICKYBIT	1
40#define GUARDBIT	0x80000000
41#define SSIGNAL_NAN	0x00400000
42#define DSIGNAL_NAN	0x00080000
43#define SQUIET_NAN	0x003fffff
44#define DQUIET_NAN0	0x0007ffff
45#define DQUIET_NAN1	0xffffffff
46#define INT_MIN		0x80000000
47#define INT_MAX		0x7fffffff
48
49#define COND_UNORDERED	0x1
50#define COND_EQUAL	0x2
51#define COND_LESS	0x4
52#define COND_SIGNAL	0x8
53
54/*----------------------------------------------------------------------------
55 *
56 * MachEmulateFP --
57 *
58 *	Emulate unimplemented floating point operations.
59 *	This routine should only be called by MachFPInterrupt().
60 *
61 *	MachEmulateFP(instr)
62 *		unsigned instr;
63 *
64 * Results:
65 *	None.
66 *
67 * Side effects:
68 *	Floating point registers are modified according to instruction.
69 *
70 *----------------------------------------------------------------------------
71 */
72NON_LEAF(MachEmulateFP, STAND_FRAME_SIZE, ra)
73	subu	sp, sp, STAND_FRAME_SIZE
74	sw	ra, STAND_RA_OFFSET(sp)
75/*
76 * Decode the FMT field (bits 24-21) and FUNCTION field (bits 5-0).
77 */
78	srl	v0, a0, 21 - 2			# get FMT field
79	and	v0, v0, 0xF << 2		# mask FMT field
80	and	v1, a0, 0x3F			# mask FUNC field
81	sll	v1, v1, 5			# align for table lookup
82	bgt	v0, 4 << 2, ill			# illegal format
83
84	or	v1, v1, v0
85	cfc1	a1, MACH_FPC_CSR		# get exception register
86	lw	a3, func_fmt_tbl(v1)		# switch on FUNC & FMT
87	and	a1, a1, ~MACH_FPC_EXCEPTION_UNIMPL	# clear exception
88	ctc1	a1, MACH_FPC_CSR
89	j	a3
90
91	.rdata
92func_fmt_tbl:
93	.word	add_s		# 0
94	.word	add_d		# 0
95	.word	ill		# 0
96	.word	ill		# 0
97	.word	ill		# 0
98	.word	ill		# 0
99	.word	ill		# 0
100	.word	ill		# 0
101	.word	sub_s		# 1
102	.word	sub_d		# 1
103	.word	ill		# 1
104	.word	ill		# 1
105	.word	ill		# 1
106	.word	ill		# 1
107	.word	ill		# 1
108	.word	ill		# 1
109	.word	mul_s		# 2
110	.word	mul_d		# 2
111	.word	ill		# 2
112	.word	ill		# 2
113	.word	ill		# 2
114	.word	ill		# 2
115	.word	ill		# 2
116	.word	ill		# 2
117	.word	div_s		# 3
118	.word	div_d		# 3
119	.word	ill		# 3
120	.word	ill		# 3
121	.word	ill		# 3
122	.word	ill		# 3
123	.word	ill		# 3
124	.word	ill		# 3
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	ill		# 4
133	.word	abs_s		# 5
134	.word	abs_d		# 5
135	.word	ill		# 5
136	.word	ill		# 5
137	.word	ill		# 5
138	.word	ill		# 5
139	.word	ill		# 5
140	.word	ill		# 5
141	.word	mov_s		# 6
142	.word	mov_d		# 6
143	.word	ill		# 6
144	.word	ill		# 6
145	.word	ill		# 6
146	.word	ill		# 6
147	.word	ill		# 6
148	.word	ill		# 6
149	.word	neg_s		# 7
150	.word	neg_d		# 7
151	.word	ill		# 7
152	.word	ill		# 7
153	.word	ill		# 7
154	.word	ill		# 7
155	.word	ill		# 7
156	.word	ill		# 7
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		# 8
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		# 9
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		# 10
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		# 11
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		# 12
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		# 13
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		# 14
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		# 15
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		# 16
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		# 17
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		# 18
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		# 19
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		# 20
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		# 21
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		# 22
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		# 23
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		# 24
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		# 25
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		# 26
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		# 27
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		# 28
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		# 29
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		# 30
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		# 31
349	.word	ill		# 32
350	.word	cvt_s_d		# 32
351	.word	ill		# 32
352	.word	ill		# 32
353	.word	cvt_s_w		# 32
354	.word	ill		# 32
355	.word	ill		# 32
356	.word	ill		# 32
357	.word	cvt_d_s		# 33
358	.word	ill		# 33
359	.word	ill		# 33
360	.word	ill		# 33
361	.word	cvt_d_w		# 33
362	.word	ill		# 33
363	.word	ill		# 33
364	.word	ill		# 33
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		# 34
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	ill		# 35
381	.word	cvt_w_s		# 36
382	.word	cvt_w_d		# 36
383	.word	ill		# 36
384	.word	ill		# 36
385	.word	ill		# 36
386	.word	ill		# 36
387	.word	ill		# 36
388	.word	ill		# 36
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		# 37
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		# 38
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		# 39
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		# 40
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		# 41
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		# 42
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		# 43
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		# 44
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		# 45
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		# 46
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	ill		# 47
477	.word	cmp_s		# 48
478	.word	cmp_d		# 48
479	.word	ill		# 48
480	.word	ill		# 48
481	.word	ill		# 48
482	.word	ill		# 48
483	.word	ill		# 48
484	.word	ill		# 48
485	.word	cmp_s		# 49
486	.word	cmp_d		# 49
487	.word	ill		# 49
488	.word	ill		# 49
489	.word	ill		# 49
490	.word	ill		# 49
491	.word	ill		# 49
492	.word	ill		# 49
493	.word	cmp_s		# 50
494	.word	cmp_d		# 50
495	.word	ill		# 50
496	.word	ill		# 50
497	.word	ill		# 50
498	.word	ill		# 50
499	.word	ill		# 50
500	.word	ill		# 50
501	.word	cmp_s		# 51
502	.word	cmp_d		# 51
503	.word	ill		# 51
504	.word	ill		# 51
505	.word	ill		# 51
506	.word	ill		# 51
507	.word	ill		# 51
508	.word	ill		# 51
509	.word	cmp_s		# 52
510	.word	cmp_d		# 52
511	.word	ill		# 52
512	.word	ill		# 52
513	.word	ill		# 52
514	.word	ill		# 52
515	.word	ill		# 52
516	.word	ill		# 52
517	.word	cmp_s		# 53
518	.word	cmp_d		# 53
519	.word	ill		# 53
520	.word	ill		# 53
521	.word	ill		# 53
522	.word	ill		# 53
523	.word	ill		# 53
524	.word	ill		# 53
525	.word	cmp_s		# 54
526	.word	cmp_d		# 54
527	.word	ill		# 54
528	.word	ill		# 54
529	.word	ill		# 54
530	.word	ill		# 54
531	.word	ill		# 54
532	.word	ill		# 54
533	.word	cmp_s		# 55
534	.word	cmp_d		# 55
535	.word	ill		# 55
536	.word	ill		# 55
537	.word	ill		# 55
538	.word	ill		# 55
539	.word	ill		# 55
540	.word	ill		# 55
541	.word	cmp_s		# 56
542	.word	cmp_d		# 56
543	.word	ill		# 56
544	.word	ill		# 56
545	.word	ill		# 56
546	.word	ill		# 56
547	.word	ill		# 56
548	.word	ill		# 56
549	.word	cmp_s		# 57
550	.word	cmp_d		# 57
551	.word	ill		# 57
552	.word	ill		# 57
553	.word	ill		# 57
554	.word	ill		# 57
555	.word	ill		# 57
556	.word	ill		# 57
557	.word	cmp_s		# 58
558	.word	cmp_d		# 58
559	.word	ill		# 58
560	.word	ill		# 58
561	.word	ill		# 58
562	.word	ill		# 58
563	.word	ill		# 58
564	.word	ill		# 58
565	.word	cmp_s		# 59
566	.word	cmp_d		# 59
567	.word	ill		# 59
568	.word	ill		# 59
569	.word	ill		# 59
570	.word	ill		# 59
571	.word	ill		# 59
572	.word	ill		# 59
573	.word	cmp_s		# 60
574	.word	cmp_d		# 60
575	.word	ill		# 60
576	.word	ill		# 60
577	.word	ill		# 60
578	.word	ill		# 60
579	.word	ill		# 60
580	.word	ill		# 60
581	.word	cmp_s		# 61
582	.word	cmp_d		# 61
583	.word	ill		# 61
584	.word	ill		# 61
585	.word	ill		# 61
586	.word	ill		# 61
587	.word	ill		# 61
588	.word	ill		# 61
589	.word	cmp_s		# 62
590	.word	cmp_d		# 62
591	.word	ill		# 62
592	.word	ill		# 62
593	.word	ill		# 62
594	.word	ill		# 62
595	.word	ill		# 62
596	.word	ill		# 62
597	.word	cmp_s		# 63
598	.word	cmp_d		# 63
599	.word	ill		# 63
600	.word	ill		# 63
601	.word	ill		# 63
602	.word	ill		# 63
603	.word	ill		# 63
604	.word	ill		# 63
605	.text
606
607/*
608 * Single precision subtract.
609 */
610sub_s:
611	jal	get_ft_fs_s
612	xor	t4, t4, 1			# negate FT sign bit
613	b	add_sub_s
614/*
615 * Single precision add.
616 */
617add_s:
618	jal	get_ft_fs_s
619add_sub_s:
620	bne	t1, SEXP_INF, 1f		# is FS an infinity?
621	bne	t5, SEXP_INF, result_fs_s	# if FT is not inf, result=FS
622	bne	t2, zero, result_fs_s		# if FS is NAN, result is FS
623	bne	t6, zero, result_ft_s		# if FT is NAN, result is FT
624	bne	t0, t4, invalid_s		# both infinities same sign?
625	b	result_fs_s			# result is in FS
6261:
627	beq	t5, SEXP_INF, result_ft_s	# if FT is inf, result=FT
628	bne	t1, zero, 4f			# is FS a denormalized num?
629	beq	t2, zero, 3f			# is FS zero?
630	bne	t5, zero, 2f			# is FT a denormalized num?
631	beq	t6, zero, result_fs_s		# FT is zero, result=FS
632	jal	renorm_fs_s
633	jal	renorm_ft_s
634	b	5f
6352:
636	jal	renorm_fs_s
637	subu	t5, t5, SEXP_BIAS		# unbias FT exponent
638	or	t6, t6, SIMPL_ONE		# set implied one bit
639	b	5f
6403:
641	bne	t5, zero, result_ft_s		# if FT != 0, result=FT
642	bne	t6, zero, result_ft_s
643	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
644	bne	v0, MACH_FPC_ROUND_RM, 1f	# round to -infinity?
645	or	t0, t0, t4			# compute result sign
646	b	result_fs_s
6471:
648	and	t0, t0, t4			# compute result sign
649	b	result_fs_s
6504:
651	bne	t5, zero, 2f			# is FT a denormalized num?
652	beq	t6, zero, result_fs_s		# FT is zero, result=FS
653	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
654	or	t2, t2, SIMPL_ONE		# set implied one bit
655	jal	renorm_ft_s
656	b	5f
6572:
658	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
659	or	t2, t2, SIMPL_ONE		# set implied one bit
660	subu	t5, t5, SEXP_BIAS		# unbias FT exponent
661	or	t6, t6, SIMPL_ONE		# set implied one bit
662/*
663 * Perform the addition.
664 */
6655:
666	move	t8, zero			# no shifted bits (sticky reg)
667	beq	t1, t5, 4f			# no shift needed
668	subu	v0, t1, t5			# v0 = difference of exponents
669	move	v1, v0				# v1 = abs(difference)
670	bge	v0, zero, 1f
671	negu	v1
6721:
673	ble	v1, SFRAC_BITS+2, 2f		# is difference too great?
674	li	t8, STICKYBIT			# set the sticky bit
675	bge	v0, zero, 1f			# check which exp is larger
676	move	t1, t5				# result exp is FTs
677	move	t2, zero			# FSs fraction shifted is zero
678	b	4f
6791:
680	move	t6, zero			# FTs fraction shifted is zero
681	b	4f
6822:
683	li	t9, 32				# compute 32 - abs(exp diff)
684	subu	t9, t9, v1
685	bgt	v0, zero, 3f			# if FS > FT, shift FTs frac
686	move	t1, t5				# FT > FS, result exp is FTs
687	sll	t8, t2, t9			# save bits shifted out
688	srl	t2, t2, v1			# shift FSs fraction
689	b	4f
6903:
691	sll	t8, t6, t9			# save bits shifted out
692	srl	t6, t6, v1			# shift FTs fraction
6934:
694	bne	t0, t4, 1f			# if signs differ, subtract
695	addu	t2, t2, t6			# add fractions
696	b	norm_s
6971:
698	blt	t2, t6, 3f			# subtract larger from smaller
699	bne	t2, t6, 2f			# if same, result=0
700	move	t1, zero			# result=0
701	move	t2, zero
702	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
703	bne	v0, MACH_FPC_ROUND_RM, 1f	# round to -infinity?
704	or	t0, t0, t4			# compute result sign
705	b	result_fs_s
7061:
707	and	t0, t0, t4			# compute result sign
708	b	result_fs_s
7092:
710	sltu	t9, zero, t8			# compute t2:zero - t6:t8
711	subu	t8, zero, t8
712	subu	t2, t2, t6			# subtract fractions
713	subu	t2, t2, t9			# subtract barrow
714	b	norm_s
7153:
716	move	t0, t4				# sign of result = FTs
717	sltu	t9, zero, t8			# compute t6:zero - t2:t8
718	subu	t8, zero, t8
719	subu	t2, t6, t2			# subtract fractions
720	subu	t2, t2, t9			# subtract barrow
721	b	norm_s
722
723/*
724 * Double precision subtract.
725 */
726sub_d:
727	jal	get_ft_fs_d
728	xor	t4, t4, 1			# negate sign bit
729	b	add_sub_d
730/*
731 * Double precision add.
732 */
733add_d:
734	jal	get_ft_fs_d
735add_sub_d:
736	bne	t1, DEXP_INF, 1f		# is FS an infinity?
737	bne	t5, DEXP_INF, result_fs_d	# if FT is not inf, result=FS
738	bne	t2, zero, result_fs_d		# if FS is NAN, result is FS
739	bne	t3, zero, result_fs_d
740	bne	t6, zero, result_ft_d		# if FT is NAN, result is FT
741	bne	t7, zero, result_ft_d
742	bne	t0, t4, invalid_d		# both infinities same sign?
743	b	result_fs_d			# result is in FS
7441:
745	beq	t5, DEXP_INF, result_ft_d	# if FT is inf, result=FT
746	bne	t1, zero, 4f			# is FS a denormalized num?
747	bne	t2, zero, 1f			# is FS zero?
748	beq	t3, zero, 3f
7491:
750	bne	t5, zero, 2f			# is FT a denormalized num?
751	bne	t6, zero, 1f
752	beq	t7, zero, result_fs_d		# FT is zero, result=FS
7531:
754	jal	renorm_fs_d
755	jal	renorm_ft_d
756	b	5f
7572:
758	jal	renorm_fs_d
759	subu	t5, t5, DEXP_BIAS		# unbias FT exponent
760	or	t6, t6, DIMPL_ONE		# set implied one bit
761	b	5f
7623:
763	bne	t5, zero, result_ft_d		# if FT != 0, result=FT
764	bne	t6, zero, result_ft_d
765	bne	t7, zero, result_ft_d
766	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
767	bne	v0, MACH_FPC_ROUND_RM, 1f	# round to -infinity?
768	or	t0, t0, t4			# compute result sign
769	b	result_fs_d
7701:
771	and	t0, t0, t4			# compute result sign
772	b	result_fs_d
7734:
774	bne	t5, zero, 2f			# is FT a denormalized num?
775	bne	t6, zero, 1f
776	beq	t7, zero, result_fs_d		# FT is zero, result=FS
7771:
778	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
779	or	t2, t2, DIMPL_ONE		# set implied one bit
780	jal	renorm_ft_d
781	b	5f
7822:
783	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
784	or	t2, t2, DIMPL_ONE		# set implied one bit
785	subu	t5, t5, DEXP_BIAS		# unbias FT exponent
786	or	t6, t6, DIMPL_ONE		# set implied one bit
787/*
788 * Perform the addition.
789 */
7905:
791	move	t8, zero			# no shifted bits (sticky reg)
792	beq	t1, t5, 4f			# no shift needed
793	subu	v0, t1, t5			# v0 = difference of exponents
794	move	v1, v0				# v1 = abs(difference)
795	bge	v0, zero, 1f
796	negu	v1
7971:
798	ble	v1, DFRAC_BITS+2, 2f		# is difference too great?
799	li	t8, STICKYBIT			# set the sticky bit
800	bge	v0, zero, 1f			# check which exp is larger
801	move	t1, t5				# result exp is FTs
802	move	t2, zero			# FSs fraction shifted is zero
803	move	t3, zero
804	b	4f
8051:
806	move	t6, zero			# FTs fraction shifted is zero
807	move	t7, zero
808	b	4f
8092:
810	li	t9, 32
811	bge	v0, zero, 3f			# if FS > FT, shift FTs frac
812	move	t1, t5				# FT > FS, result exp is FTs
813	blt	v1, t9, 1f			# shift right by < 32?
814	subu	v1, v1, t9
815	subu	t9, t9, v1
816	sll	t8, t2, t9			# save bits shifted out
817	sltu	t9, zero, t3			# dont lose any one bits
818	or	t8, t8, t9			# save sticky bit
819	srl	t3, t2, v1			# shift FSs fraction
820	move	t2, zero
821	b	4f
8221:
823	subu	t9, t9, v1
824	sll	t8, t3, t9			# save bits shifted out
825	srl	t3, t3, v1			# shift FSs fraction
826	sll	t9, t2, t9			# save bits shifted out of t2
827	or	t3, t3, t9			# and put into t3
828	srl	t2, t2, v1
829	b	4f
8303:
831	blt	v1, t9, 1f			# shift right by < 32?
832	subu	v1, v1, t9
833	subu	t9, t9, v1
834	sll	t8, t6, t9			# save bits shifted out
835	srl	t7, t6, v1			# shift FTs fraction
836	move	t6, zero
837	b	4f
8381:
839	subu	t9, t9, v1
840	sll	t8, t7, t9			# save bits shifted out
841	srl	t7, t7, v1			# shift FTs fraction
842	sll	t9, t6, t9			# save bits shifted out of t2
843	or	t7, t7, t9			# and put into t3
844	srl	t6, t6, v1
8454:
846	bne	t0, t4, 1f			# if signs differ, subtract
847	addu	t3, t3, t7			# add fractions
848	sltu	t9, t3, t7			# compute carry
849	addu	t2, t2, t6			# add fractions
850	addu	t2, t2, t9			# add carry
851	b	norm_d
8521:
853	blt	t2, t6, 3f			# subtract larger from smaller
854	bne	t2, t6, 2f
855	bltu	t3, t7, 3f
856	bne	t3, t7, 2f			# if same, result=0
857	move	t1, zero			# result=0
858	move	t2, zero
859	move	t3, zero
860	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
861	bne	v0, MACH_FPC_ROUND_RM, 1f	# round to -infinity?
862	or	t0, t0, t4			# compute result sign
863	b	result_fs_d
8641:
865	and	t0, t0, t4			# compute result sign
866	b	result_fs_d
8672:
868	beq	t8, zero, 1f			# compute t2:t3:zero - t6:t7:t8
869	subu	t8, zero, t8
870	sltu	v0, t3, 1			# compute barrow out
871	subu	t3, t3, 1			# subtract barrow
872	subu	t2, t2, v0
8731:
874	sltu	v0, t3, t7
875	subu	t3, t3, t7			# subtract fractions
876	subu	t2, t2, t6			# subtract fractions
877	subu	t2, t2, v0			# subtract barrow
878	b	norm_d
8793:
880	move	t0, t4				# sign of result = FTs
881	beq	t8, zero, 1f			# compute t6:t7:zero - t2:t3:t8
882	subu	t8, zero, t8
883	sltu	v0, t7, 1			# compute barrow out
884	subu	t7, t7, 1			# subtract barrow
885	subu	t6, t6, v0
8861:
887	sltu	v0, t7, t3
888	subu	t3, t7, t3			# subtract fractions
889	subu	t2, t6, t2			# subtract fractions
890	subu	t2, t2, v0			# subtract barrow
891	b	norm_d
892
893/*
894 * Single precision multiply.
895 */
896mul_s:
897	jal	get_ft_fs_s
898	xor	t0, t0, t4			# compute sign of result
899	move	t4, t0
900	bne	t1, SEXP_INF, 2f		# is FS an infinity?
901	bne	t2, zero, result_fs_s		# if FS is a NAN, result=FS
902	bne	t5, SEXP_INF, 1f		# FS is inf, is FT an infinity?
903	bne	t6, zero, result_ft_s		# if FT is a NAN, result=FT
904	b	result_fs_s			# result is infinity
9051:
906	bne	t5, zero, result_fs_s		# inf * zero? if no, result=FS
907	bne	t6, zero, result_fs_s
908	b	invalid_s			# infinity * zero is invalid
9092:
910	bne	t5, SEXP_INF, 1f		# FS != inf, is FT an infinity?
911	bne	t1, zero, result_ft_s		# zero * inf? if no, result=FT
912	bne	t2, zero, result_ft_s
913	bne	t6, zero, result_ft_s		# if FT is a NAN, result=FT
914	b	invalid_s			# zero * infinity is invalid
9151:
916	bne	t1, zero, 1f			# is FS zero?
917	beq	t2, zero, result_fs_s		# result is zero
918	jal	renorm_fs_s
919	b	2f
9201:
921	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
922	or	t2, t2, SIMPL_ONE		# set implied one bit
9232:
924	bne	t5, zero, 1f			# is FT zero?
925	beq	t6, zero, result_ft_s		# result is zero
926	jal	renorm_ft_s
927	b	2f
9281:
929	subu	t5, t5, SEXP_BIAS		# unbias FT exponent
930	or	t6, t6, SIMPL_ONE		# set implied one bit
9312:
932	addu	t1, t1, t5			# compute result exponent
933	addu	t1, t1, 9			# account for binary point
934	multu	t2, t6				# multiply fractions
935	mflo	t8
936	mfhi	t2
937	b	norm_s
938
939/*
940 * Double precision multiply.
941 */
942mul_d:
943	jal	get_ft_fs_d
944	xor	t0, t0, t4			# compute sign of result
945	move	t4, t0
946	bne	t1, DEXP_INF, 2f		# is FS an infinity?
947	bne	t2, zero, result_fs_d		# if FS is a NAN, result=FS
948	bne	t3, zero, result_fs_d
949	bne	t5, DEXP_INF, 1f		# FS is inf, is FT an infinity?
950	bne	t6, zero, result_ft_d		# if FT is a NAN, result=FT
951	bne	t7, zero, result_ft_d
952	b	result_fs_d			# result is infinity
9531:
954	bne	t5, zero, result_fs_d		# inf * zero? if no, result=FS
955	bne	t6, zero, result_fs_d
956	bne	t7, zero, result_fs_d
957	b	invalid_d			# infinity * zero is invalid
9582:
959	bne	t5, DEXP_INF, 1f		# FS != inf, is FT an infinity?
960	bne	t1, zero, result_ft_d		# zero * inf? if no, result=FT
961	bne	t2, zero, result_ft_d		# if FS is a NAN, result=FS
962	bne	t3, zero, result_ft_d
963	bne	t6, zero, result_ft_d		# if FT is a NAN, result=FT
964	bne	t7, zero, result_ft_d
965	b	invalid_d			# zero * infinity is invalid
9661:
967	bne	t1, zero, 2f			# is FS zero?
968	bne	t2, zero, 1f
969	beq	t3, zero, result_fs_d		# result is zero
9701:
971	jal	renorm_fs_d
972	b	3f
9732:
974	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
975	or	t2, t2, DIMPL_ONE		# set implied one bit
9763:
977	bne	t5, zero, 2f			# is FT zero?
978	bne	t6, zero, 1f
979	beq	t7, zero, result_ft_d		# result is zero
9801:
981	jal	renorm_ft_d
982	b	3f
9832:
984	subu	t5, t5, DEXP_BIAS		# unbias FT exponent
985	or	t6, t6, DIMPL_ONE		# set implied one bit
9863:
987	addu	t1, t1, t5			# compute result exponent
988	addu	t1, t1, 12			# ???
989	multu	t3, t7				# multiply fractions (low * low)
990	move	t4, t2				# free up t2,t3 for result
991	move	t5, t3
992	mflo	a3				# save low order bits
993	mfhi	t8
994	not	v0, t8
995	multu	t4, t7				# multiply FS(high) * FT(low)
996	mflo	v1
997	mfhi	t3				# init low result
998	sltu	v0, v0, v1			# compute carry
999	addu	t8, v1
1000	multu	t5, t6				# multiply FS(low) * FT(high)
1001	addu	t3, t3, v0			# add carry
1002	not	v0, t8
1003	mflo	v1
1004	mfhi	t2
1005	sltu	v0, v0, v1
1006	addu	t8, v1
1007	multu	t4, t6				# multiply FS(high) * FT(high)
1008	addu	t3, v0
1009	not	v1, t3
1010	sltu	v1, v1, t2
1011	addu	t3, t2
1012	not	v0, t3
1013	mfhi	t2
1014	addu	t2, v1
1015	mflo	v1
1016	sltu	v0, v0, v1
1017	addu	t2, v0
1018	addu	t3, v1
1019	sltu	a3, zero, a3			# reduce t8,a3 to just t8
1020	or	t8, a3
1021	b	norm_d
1022
1023/*
1024 * Single precision divide.
1025 */
1026div_s:
1027	jal	get_ft_fs_s
1028	xor	t0, t0, t4			# compute sign of result
1029	move	t4, t0
1030	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1031	bne	t2, zero, result_fs_s		# if FS is NAN, result is FS
1032	bne	t5, SEXP_INF, result_fs_s	# is FT an infinity?
1033	bne	t6, zero, result_ft_s		# if FT is NAN, result is FT
1034	b	invalid_s			# infinity/infinity is invalid
10351:
1036	bne	t5, SEXP_INF, 1f		# is FT an infinity?
1037	bne	t6, zero, result_ft_s		# if FT is NAN, result is FT
1038	move	t1, zero			# x / infinity is zero
1039	move	t2, zero
1040	b	result_fs_s
10411:
1042	bne	t1, zero, 2f			# is FS zero?
1043	bne	t2, zero, 1f
1044	bne	t5, zero, result_fs_s		# FS=zero, is FT zero?
1045	beq	t6, zero, invalid_s		# 0 / 0
1046	b	result_fs_s			# result = zero
10471:
1048	jal	renorm_fs_s
1049	b	3f
10502:
1051	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
1052	or	t2, t2, SIMPL_ONE		# set implied one bit
10533:
1054	bne	t5, zero, 2f			# is FT zero?
1055	bne	t6, zero, 1f
1056	or	a1, a1, MACH_FPC_EXCEPTION_DIV0 | MACH_FPC_STICKY_DIV0
1057	and	v0, a1, MACH_FPC_ENABLE_DIV0	# trap enabled?
1058	bne	v0, zero, fpe_trap
1059	ctc1	a1, MACH_FPC_CSR		# save exceptions
1060	li	t1, SEXP_INF			# result is infinity
1061	move	t2, zero
1062	b	result_fs_s
10631:
1064	jal	renorm_ft_s
1065	b	3f
10662:
1067	subu	t5, t5, SEXP_BIAS		# unbias FT exponent
1068	or	t6, t6, SIMPL_ONE		# set implied one bit
10693:
1070	subu	t1, t1, t5			# compute exponent
1071	subu	t1, t1, 3			# compensate for result position
1072	li	v0, SFRAC_BITS+3		# number of bits to divide
1073	move	t8, t2				# init dividend
1074	move	t2, zero			# init result
10751:
1076	bltu	t8, t6, 3f			# is dividend >= divisor?
10772:
1078	subu	t8, t8, t6			# subtract divisor from dividend
1079	or	t2, t2, 1			# remember that we did
1080	bne	t8, zero, 3f			# if not done, continue
1081	sll	t2, t2, v0			# shift result to final position
1082	b	norm_s
10833:
1084	sll	t8, t8, 1			# shift dividend
1085	sll	t2, t2, 1			# shift result
1086	subu	v0, v0, 1			# are we done?
1087	bne	v0, zero, 1b			# no, continue
1088	b	norm_s
1089
1090/*
1091 * Double precision divide.
1092 */
1093div_d:
1094	jal	get_ft_fs_d
1095	xor	t0, t0, t4			# compute sign of result
1096	move	t4, t0
1097	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1098	bne	t2, zero, result_fs_d		# if FS is NAN, result is FS
1099	bne	t3, zero, result_fs_d
1100	bne	t5, DEXP_INF, result_fs_d	# is FT an infinity?
1101	bne	t6, zero, result_ft_d		# if FT is NAN, result is FT
1102	bne	t7, zero, result_ft_d
1103	b	invalid_d			# infinity/infinity is invalid
11041:
1105	bne	t5, DEXP_INF, 1f		# is FT an infinity?
1106	bne	t6, zero, result_ft_d		# if FT is NAN, result is FT
1107	bne	t7, zero, result_ft_d
1108	move	t1, zero			# x / infinity is zero
1109	move	t2, zero
1110	move	t3, zero
1111	b	result_fs_d
11121:
1113	bne	t1, zero, 2f			# is FS zero?
1114	bne	t2, zero, 1f
1115	bne	t3, zero, 1f
1116	bne	t5, zero, result_fs_d		# FS=zero, is FT zero?
1117	bne	t6, zero, result_fs_d
1118	beq	t7, zero, invalid_d		# 0 / 0
1119	b	result_fs_d			# result = zero
11201:
1121	jal	renorm_fs_d
1122	b	3f
11232:
1124	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
1125	or	t2, t2, DIMPL_ONE		# set implied one bit
11263:
1127	bne	t5, zero, 2f			# is FT zero?
1128	bne	t6, zero, 1f
1129	bne	t7, zero, 1f
1130	or	a1, a1, MACH_FPC_EXCEPTION_DIV0 | MACH_FPC_STICKY_DIV0
1131	and	v0, a1, MACH_FPC_ENABLE_DIV0	# trap enabled?
1132	bne	v0, zero, fpe_trap
1133	ctc1	a1, MACH_FPC_CSR		# Save exceptions
1134	li	t1, DEXP_INF			# result is infinity
1135	move	t2, zero
1136	move	t3, zero
1137	b	result_fs_d
11381:
1139	jal	renorm_ft_d
1140	b	3f
11412:
1142	subu	t5, t5, DEXP_BIAS		# unbias FT exponent
1143	or	t6, t6, DIMPL_ONE		# set implied one bit
11443:
1145	subu	t1, t1, t5			# compute exponent
1146	subu	t1, t1, 3			# compensate for result position
1147	li	v0, DFRAC_BITS+3		# number of bits to divide
1148	move	t8, t2				# init dividend
1149	move	t9, t3
1150	move	t2, zero			# init result
1151	move	t3, zero
11521:
1153	bltu	t8, t6, 3f			# is dividend >= divisor?
1154	bne	t8, t6, 2f
1155	bltu	t9, t7, 3f
11562:
1157	sltu	v1, t9, t7			# subtract divisor from dividend
1158	subu	t9, t9, t7
1159	subu	t8, t8, t6
1160	subu	t8, t8, v1
1161	or	t3, t3, 1			# remember that we did
1162	bne	t8, zero, 3f			# if not done, continue
1163	bne	t9, zero, 3f
1164	li	v1, 32				# shift result to final position
1165	blt	v0, v1, 2f			# shift < 32 bits?
1166	subu	v0, v0, v1			# shift by > 32 bits
1167	sll	t2, t3, v0			# shift upper part
1168	move	t3, zero
1169	b	norm_d
11702:
1171	subu	v1, v1, v0			# shift by < 32 bits
1172	sll	t2, t2, v0			# shift upper part
1173	srl	t9, t3, v1			# save bits shifted out
1174	or	t2, t2, t9			# and put into upper part
1175	sll	t3, t3, v0
1176	b	norm_d
11773:
1178	sll	t8, t8, 1			# shift dividend
1179	srl	v1, t9, 31			# save bit shifted out
1180	or	t8, t8, v1			# and put into upper part
1181	sll	t9, t9, 1
1182	sll	t2, t2, 1			# shift result
1183	srl	v1, t3, 31			# save bit shifted out
1184	or	t2, t2, v1			# and put into upper part
1185	sll	t3, t3, 1
1186	subu	v0, v0, 1			# are we done?
1187	bne	v0, zero, 1b			# no, continue
1188	sltu	v0, zero, t9			# be sure to save any one bits
1189	or	t8, t8, v0			# from the lower remainder
1190	b	norm_d
1191
1192/*
1193 * Single precision absolute value.
1194 */
1195abs_s:
1196	jal	get_fs_s
1197	move	t0, zero			# set sign positive
1198	b	result_fs_s
1199
1200/*
1201 * Double precision absolute value.
1202 */
1203abs_d:
1204	jal	get_fs_d
1205	move	t0, zero			# set sign positive
1206	b	result_fs_d
1207
1208/*
1209 * Single precision move.
1210 */
1211mov_s:
1212	jal	get_fs_s
1213	b	result_fs_s
1214
1215/*
1216 * Double precision move.
1217 */
1218mov_d:
1219	jal	get_fs_d
1220	b	result_fs_d
1221
1222/*
1223 * Single precision negate.
1224 */
1225neg_s:
1226	jal	get_fs_s
1227	xor	t0, t0, 1			# reverse sign
1228	b	result_fs_s
1229
1230/*
1231 * Double precision negate.
1232 */
1233neg_d:
1234	jal	get_fs_d
1235	xor	t0, t0, 1			# reverse sign
1236	b	result_fs_d
1237
1238/*
1239 * Convert double to single.
1240 */
1241cvt_s_d:
1242	jal	get_fs_d
1243	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1244	li	t1, SEXP_INF			# convert to single
1245	sll	t2, t2, 3			# convert D fraction to S
1246	srl	t8, t3, 32 - 3
1247	or	t2, t2, t8
1248	b	result_fs_s
12491:
1250	bne	t1, zero, 2f			# is FS zero?
1251	bne	t2, zero, 1f
1252	beq	t3, zero, result_fs_s		# result=0
12531:
1254	jal	renorm_fs_d
1255	subu	t1, t1, 3			# correct exp for shift below
1256	b	3f
12572:
1258	subu	t1, t1, DEXP_BIAS		# unbias exponent
1259	or	t2, t2, DIMPL_ONE		# add implied one bit
12603:
1261	sll	t2, t2, 3			# convert D fraction to S
1262	srl	t8, t3, 32 - 3
1263	or	t2, t2, t8
1264	sll	t8, t3, 3
1265	b	norm_noshift_s
1266
1267/*
1268 * Convert integer to single.
1269 */
1270cvt_s_w:
1271	jal	get_fs_int
1272	bne	t2, zero, 1f			# check for zero
1273	move	t1, zero
1274	b	result_fs_s
1275/*
1276 * Find out how many leading zero bits are in t2 and put in t9.
1277 */
12781:
1279	move	v0, t2
1280	move	t9, zero
1281	srl	v1, v0, 16
1282	bne	v1, zero, 1f
1283	addu	t9, 16
1284	sll	v0, 16
12851:
1286	srl	v1, v0, 24
1287	bne	v1, zero, 1f
1288	addu	t9, 8
1289	sll	v0, 8
12901:
1291	srl	v1, v0, 28
1292	bne	v1, zero, 1f
1293	addu	t9, 4
1294	sll	v0, 4
12951:
1296	srl	v1, v0, 30
1297	bne	v1, zero, 1f
1298	addu	t9, 2
1299	sll	v0, 2
13001:
1301	srl	v1, v0, 31
1302	bne	v1, zero, 1f
1303	addu	t9, 1
1304/*
1305 * Now shift t2 the correct number of bits.
1306 */
13071:
1308	subu	t9, t9, SLEAD_ZEROS		# dont count leading zeros
1309	li	t1, 23				# init exponent
1310	subu	t1, t1, t9			# compute exponent
1311	beq	t9, zero, 1f
1312	li	v0, 32
1313	blt	t9, zero, 2f			# if shift < 0, shift right
1314	subu	v0, v0, t9
1315	sll	t2, t2, t9			# shift left
13161:
1317	add	t1, t1, SEXP_BIAS		# bias exponent
1318	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1319	b	result_fs_s
13202:
1321	negu	t9				# shift right by t9
1322	subu	v0, v0, t9
1323	sll	t8, t2, v0			# save bits shifted out
1324	srl	t2, t2, t9
1325	b	norm_noshift_s
1326
1327/*
1328 * Convert single to double.
1329 */
1330cvt_d_s:
1331	jal	get_fs_s
1332	move	t3, zero
1333	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1334	li	t1, DEXP_INF			# convert to double
1335	b	result_fs_d
13361:
1337	bne	t1, zero, 2f			# is FS denormalized or zero?
1338	beq	t2, zero, result_fs_d		# is FS zero?
1339	jal	renorm_fs_s
1340	move	t8, zero
1341	b	norm_d
13422:
1343	addu	t1, t1, DEXP_BIAS - SEXP_BIAS	# bias exponent correctly
1344	sll	t3, t2, 32 - 3			# convert S fraction to D
1345	srl	t2, t2, 3
1346	b	result_fs_d
1347
1348/*
1349 * Convert integer to double.
1350 */
1351cvt_d_w:
1352	jal	get_fs_int
1353	bne	t2, zero, 1f			# check for zero
1354	move	t1, zero			# result=0
1355	move	t3, zero
1356	b	result_fs_d
1357/*
1358 * Find out how many leading zero bits are in t2 and put in t9.
1359 */
13601:
1361	move	v0, t2
1362	move	t9, zero
1363	srl	v1, v0, 16
1364	bne	v1, zero, 1f
1365	addu	t9, 16
1366	sll	v0, 16
13671:
1368	srl	v1, v0, 24
1369	bne	v1, zero, 1f
1370	addu	t9, 8
1371	sll	v0, 8
13721:
1373	srl	v1, v0, 28
1374	bne	v1, zero, 1f
1375	addu	t9, 4
1376	sll	v0, 4
13771:
1378	srl	v1, v0, 30
1379	bne	v1, zero, 1f
1380	addu	t9, 2
1381	sll	v0, 2
13821:
1383	srl	v1, v0, 31
1384	bne	v1, zero, 1f
1385	addu	t9, 1
1386/*
1387 * Now shift t2 the correct number of bits.
1388 */
13891:
1390	subu	t9, t9, DLEAD_ZEROS		# dont count leading zeros
1391	li	t1, DEXP_BIAS + 20		# init exponent
1392	subu	t1, t1, t9			# compute exponent
1393	beq	t9, zero, 1f
1394	li	v0, 32
1395	blt	t9, zero, 2f			# if shift < 0, shift right
1396	subu	v0, v0, t9
1397	sll	t2, t2, t9			# shift left
13981:
1399	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1400	move	t3, zero
1401	b	result_fs_d
14022:
1403	negu	t9				# shift right by t9
1404	subu	v0, v0, t9
1405	sll	t3, t2, v0
1406	srl	t2, t2, t9
1407	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1408	b	result_fs_d
1409
1410/*
1411 * Convert single to integer.
1412 */
1413cvt_w_s:
1414	jal	get_fs_s
1415	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1416	bne	t2, zero, invalid_w		# invalid conversion
14171:
1418	bne	t1, zero, 1f			# is FS zero?
1419	beq	t2, zero, result_fs_w		# result is zero
1420	move	t2, zero			# result is an inexact zero
1421	b	inexact_w
14221:
1423	subu	t1, t1, SEXP_BIAS		# unbias exponent
1424	or	t2, t2, SIMPL_ONE		# add implied one bit
1425	sll	t3, t2, 32 - 3			# convert S fraction to D
1426	srl	t2, t2, 3
1427	b	cvt_w
1428
1429/*
1430 * Convert double to integer.
1431 */
1432cvt_w_d:
1433	jal	get_fs_d
1434	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1435	bne	t2, zero, invalid_w		# invalid conversion
1436	bne	t3, zero, invalid_w		# invalid conversion
14371:
1438	bne	t1, zero, 2f			# is FS zero?
1439	bne	t2, zero, 1f
1440	beq	t3, zero, result_fs_w		# result is zero
14411:
1442	move	t2, zero			# result is an inexact zero
1443	b	inexact_w
14442:
1445	subu	t1, t1, DEXP_BIAS		# unbias exponent
1446	or	t2, t2, DIMPL_ONE		# add implied one bit
1447cvt_w:
1448	blt	t1, WEXP_MIN, underflow_w	# is exponent too small?
1449	li	v0, WEXP_MAX+1
1450	bgt	t1, v0, overflow_w		# is exponent too large?
1451	bne	t1, v0, 1f			# special check for INT_MIN
1452	beq	t0, zero, overflow_w		# if positive, overflow
1453	bne	t2, DIMPL_ONE, overflow_w
1454	bne	t3, zero, overflow_w
1455	li	t2, INT_MIN			# result is INT_MIN
1456	b	result_fs_w
14571:
1458	subu	v0, t1, 20			# compute amount to shift
1459	beq	v0, zero, 2f			# is shift needed?
1460	li	v1, 32
1461	blt	v0, zero, 1f			# if shift < 0, shift right
1462	subu	v1, v1, v0			# shift left
1463	sll	t2, t2, v0
1464	srl	t9, t3, v1			# save bits shifted out of t3
1465	or	t2, t2, t9			# and put into t2
1466	sll	t3, t3, v0			# shift FSs fraction
1467	b	2f
14681:
1469	negu	v0				# shift right by v0
1470	subu	v1, v1, v0
1471	sll	t8, t3, v1			# save bits shifted out
1472	sltu	t8, zero, t8			# dont lose any ones
1473	srl	t3, t3, v0			# shift FSs fraction
1474	or	t3, t3, t8
1475	sll	t9, t2, v1			# save bits shifted out of t2
1476	or	t3, t3, t9			# and put into t3
1477	srl	t2, t2, v0
1478/*
1479 * round result (t0 is sign, t2 is integer part, t3 is fractional part).
1480 */
14812:
1482	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1483	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1484	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
1485	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1486	beq	t0, zero, 5f			# if sign is positive, truncate
1487	b	2f
14881:
1489	bne	t0, zero, 5f			# if sign is negative, truncate
14902:
1491	beq	t3, zero, 5f			# if no fraction bits, continue
1492	addu	t2, t2, 1			# add rounding bit
1493	blt	t2, zero, overflow_w		# overflow?
1494	b	5f
14953:
1496	li	v0, GUARDBIT			# load guard bit for rounding
1497	addu	v0, v0, t3			# add remainder
1498	sltu	v1, v0, t3			# compute carry out
1499	beq	v1, zero, 4f			# if no carry, continue
1500	addu	t2, t2, 1			# add carry to result
1501	blt	t2, zero, overflow_w		# overflow?
15024:
1503	bne	v0, zero, 5f			# if rounded remainder is zero
1504	and	t2, t2, ~1			#  clear LSB (round to nearest)
15055:
1506	beq	t0, zero, 1f			# result positive?
1507	negu	t2				# convert to negative integer
15081:
1509	beq	t3, zero, result_fs_w		# is result exact?
1510/*
1511 * Handle inexact exception.
1512 */
1513inexact_w:
1514	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
1515	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1516	bne	v0, zero, fpe_trap
1517	ctc1	a1, MACH_FPC_CSR		# save exceptions
1518	b	result_fs_w
1519
1520/*
1521 * Conversions to integer which overflow will trap (if enabled),
1522 * or generate an inexact trap (if enabled),
1523 * or generate an invalid exception.
1524 */
1525overflow_w:
1526	or	a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW
1527	and	v0, a1, MACH_FPC_ENABLE_OVERFLOW
1528	bne	v0, zero, fpe_trap
1529	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1530	bne	v0, zero, inexact_w		# inexact traps enabled?
1531	b	invalid_w
1532
1533/*
1534 * Conversions to integer which underflow will trap (if enabled),
1535 * or generate an inexact trap (if enabled),
1536 * or generate an invalid exception.
1537 */
1538underflow_w:
1539	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
1540	and	v0, a1, MACH_FPC_ENABLE_UNDERFLOW
1541	bne	v0, zero, fpe_trap
1542	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1543	bne	v0, zero, inexact_w		# inexact traps enabled?
1544	b	invalid_w
1545
1546/*
1547 * Compare single.
1548 */
1549cmp_s:
1550	jal	get_cmp_s
1551	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1552	bne	t2, zero, unordered		# FS is a NAN
15531:
1554	bne	t5, SEXP_INF, 2f		# is FT an infinity?
1555	bne	t6, zero, unordered		# FT is a NAN
15562:
1557	sll	t1, t1, 23			# reassemble exp & frac
1558	or	t1, t1, t2
1559	sll	t5, t5, 23			# reassemble exp & frac
1560	or	t5, t5, t6
1561	beq	t0, zero, 1f			# is FS positive?
1562	negu	t1
15631:
1564	beq	t4, zero, 1f			# is FT positive?
1565	negu	t5
15661:
1567	li	v0, COND_LESS
1568	blt	t1, t5, test_cond		# is FS < FT?
1569	li	v0, COND_EQUAL
1570	beq	t1, t5, test_cond		# is FS == FT?
1571	move	v0, zero			# FS > FT
1572	b	test_cond
1573
1574/*
1575 * Compare double.
1576 */
1577cmp_d:
1578	jal	get_cmp_d
1579	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1580	bne	t2, zero, unordered
1581	bne	t3, zero, unordered		# FS is a NAN
15821:
1583	bne	t5, DEXP_INF, 2f		# is FT an infinity?
1584	bne	t6, zero, unordered
1585	bne	t7, zero, unordered		# FT is a NAN
15862:
1587	sll	t1, t1, 20			# reassemble exp & frac
1588	or	t1, t1, t2
1589	sll	t5, t5, 20			# reassemble exp & frac
1590	or	t5, t5, t6
1591	beq	t0, zero, 1f			# is FS positive?
1592	not	t3				# negate t1,t3
1593	not	t1
1594	addu	t3, t3, 1
1595	seq	v0, t3, zero			# compute carry
1596	addu	t1, t1, v0
15971:
1598	beq	t4, zero, 1f			# is FT positive?
1599	not	t7				# negate t5,t7
1600	not	t5
1601	addu	t7, t7, 1
1602	seq	v0, t7, zero			# compute carry
1603	addu	t5, t5, v0
16041:
1605	li	v0, COND_LESS
1606	blt	t1, t5, test_cond		# is FS(MSW) < FT(MSW)?
1607	move	v0, zero
1608	bne	t1, t5, test_cond		# is FS(MSW) > FT(MSW)?
1609	li	v0, COND_LESS
1610	bltu	t3, t7, test_cond		# is FS(LSW) < FT(LSW)?
1611	li	v0, COND_EQUAL
1612	beq	t3, t7, test_cond		# is FS(LSW) == FT(LSW)?
1613	move	v0, zero			# FS > FT
1614test_cond:
1615	and	v0, v0, a0			# condition match instruction?
1616set_cond:
1617	bne	v0, zero, 1f
1618	and	a1, a1, ~MACH_FPC_COND_BIT	# clear condition bit
1619	b	2f
16201:
1621	or	a1, a1, MACH_FPC_COND_BIT	# set condition bit
16222:
1623	ctc1	a1, MACH_FPC_CSR		# save condition bit
1624	b	done
1625
1626unordered:
1627	and	v0, a0, COND_UNORDERED		# this cmp match unordered?
1628	bne	v0, zero, 1f
1629	and	a1, a1, ~MACH_FPC_COND_BIT	# clear condition bit
1630	b	2f
16311:
1632	or	a1, a1, MACH_FPC_COND_BIT	# set condition bit
16332:
1634	and	v0, a0, COND_SIGNAL
1635	beq	v0, zero, 1f			# is this a signaling cmp?
1636	or	a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID
1637	and	v0, a1, MACH_FPC_ENABLE_INVALID
1638	bne	v0, zero, fpe_trap
16391:
1640	ctc1	a1, MACH_FPC_CSR		# save condition bit
1641	b	done
1642
1643/*
1644 * Determine the amount to shift the fraction in order to restore the
1645 * normalized position. After that, round and handle exceptions.
1646 */
1647norm_s:
1648	move	v0, t2
1649	move	t9, zero			# t9 = num of leading zeros
1650	bne	t2, zero, 1f
1651	move	v0, t8
1652	addu	t9, 32
16531:
1654	srl	v1, v0, 16
1655	bne	v1, zero, 1f
1656	addu	t9, 16
1657	sll	v0, 16
16581:
1659	srl	v1, v0, 24
1660	bne	v1, zero, 1f
1661	addu	t9, 8
1662	sll	v0, 8
16631:
1664	srl	v1, v0, 28
1665	bne	v1, zero, 1f
1666	addu	t9, 4
1667	sll	v0, 4
16681:
1669	srl	v1, v0, 30
1670	bne	v1, zero, 1f
1671	addu	t9, 2
1672	sll	v0, 2
16731:
1674	srl	v1, v0, 31
1675	bne	v1, zero, 1f
1676	addu	t9, 1
1677/*
1678 * Now shift t2,t8 the correct number of bits.
1679 */
16801:
1681	subu	t9, t9, SLEAD_ZEROS		# dont count leading zeros
1682	subu	t1, t1, t9			# adjust the exponent
1683	beq	t9, zero, norm_noshift_s
1684	li	v1, 32
1685	blt	t9, zero, 1f			# if shift < 0, shift right
1686	subu	v1, v1, t9
1687	sll	t2, t2, t9			# shift t2,t8 left
1688	srl	v0, t8, v1			# save bits shifted out
1689	or	t2, t2, v0
1690	sll	t8, t8, t9
1691	b	norm_noshift_s
16921:
1693	negu	t9				# shift t2,t8 right by t9
1694	subu	v1, v1, t9
1695	sll	v0, t8, v1			# save bits shifted out
1696	sltu	v0, zero, v0			# be sure to save any one bits
1697	srl	t8, t8, t9
1698	or	t8, t8, v0
1699	sll	v0, t2, v1			# save bits shifted out
1700	or	t8, t8, v0
1701	srl	t2, t2, t9
1702norm_noshift_s:
1703	move	t5, t1				# save unrounded exponent
1704	move	t6, t2				# save unrounded fraction
1705	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1706	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1707	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
1708	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1709	beq	t0, zero, 5f			# if sign is positive, truncate
1710	b	2f
17111:
1712	bne	t0, zero, 5f			# if sign is negative, truncate
17132:
1714	beq	t8, zero, 5f			# if exact, continue
1715	addu	t2, t2, 1			# add rounding bit
1716	bne	t2, SIMPL_ONE<<1, 5f		# need to adjust exponent?
1717	addu	t1, t1, 1			# adjust exponent
1718	srl	t2, t2, 1			# renormalize fraction
1719	b	5f
17203:
1721	li	v0, GUARDBIT			# load guard bit for rounding
1722	addu	v0, v0, t8			# add remainder
1723	sltu	v1, v0, t8			# compute carry out
1724	beq	v1, zero, 4f			# if no carry, continue
1725	addu	t2, t2, 1			# add carry to result
1726	bne	t2, SIMPL_ONE<<1, 4f		# need to adjust exponent?
1727	addu	t1, t1, 1			# adjust exponent
1728	srl	t2, t2, 1			# renormalize fraction
17294:
1730	bne	v0, zero, 5f			# if rounded remainder is zero
1731	and	t2, t2, ~1			#  clear LSB (round to nearest)
17325:
1733	bgt	t1, SEXP_MAX, overflow_s	# overflow?
1734	blt	t1, SEXP_MIN, underflow_s	# underflow?
1735	bne	t8, zero, inexact_s		# is result inexact?
1736	addu	t1, t1, SEXP_BIAS		# bias exponent
1737	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1738	b	result_fs_s
1739
1740/*
1741 * Handle inexact exception.
1742 */
1743inexact_s:
1744	addu	t1, t1, SEXP_BIAS		# bias exponent
1745	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1746inexact_nobias_s:
1747	jal	set_fd_s			# save result
1748	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
1749	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1750	bne	v0, zero, fpe_trap
1751	ctc1	a1, MACH_FPC_CSR		# save exceptions
1752	b	done
1753
1754/*
1755 * Overflow will trap (if enabled),
1756 * or generate an inexact trap (if enabled),
1757 * or generate an infinity.
1758 */
1759overflow_s:
1760	or	a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW
1761	and	v0, a1, MACH_FPC_ENABLE_OVERFLOW
1762	beq	v0, zero, 1f
1763	subu	t1, t1, 192			# bias exponent
1764	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1765	jal	set_fd_s			# save result
1766	b	fpe_trap
17671:
1768	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1769	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1770	beq	v0, MACH_FPC_ROUND_RZ, 1f	# round to zero (truncate)
1771	beq	v0, MACH_FPC_ROUND_RP, 2f	# round to +infinity
1772	bne	t0, zero, 3f
17731:
1774	li	t1, SEXP_MAX			# result is max finite
1775	li	t2, 0x007fffff
1776	b	inexact_s
17772:
1778	bne	t0, zero, 1b
17793:
1780	li	t1, SEXP_MAX + 1		# result is infinity
1781	move	t2, zero
1782	b	inexact_s
1783
1784/*
1785 * In this implementation, "tininess" is detected "after rounding" and
1786 * "loss of accuracy" is detected as "an inexact result".
1787 */
1788underflow_s:
1789	and	v0, a1, MACH_FPC_ENABLE_UNDERFLOW
1790	beq	v0, zero, 1f
1791/*
1792 * Underflow is enabled so compute the result and trap.
1793 */
1794	addu	t1, t1, 192			# bias exponent
1795	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1796	jal	set_fd_s			# save result
1797	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
1798	b	fpe_trap
1799/*
1800 * Underflow is not enabled so compute the result,
1801 * signal inexact result (if it is) and trap (if enabled).
1802 */
18031:
1804	move	t1, t5				# get unrounded exponent
1805	move	t2, t6				# get unrounded fraction
1806	li	t9, SEXP_MIN			# compute shift amount
1807	subu	t9, t9, t1			# shift t2,t8 right by t9
1808	blt	t9, SFRAC_BITS+2, 3f		# shift all the bits out?
1809	move	t1, zero			# result is inexact zero
1810	move	t2, zero
1811	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
1812/*
1813 * Now round the zero result.
1814 * Only need to worry about rounding to +- infinity when the sign matches.
1815 */
1816	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1817	beq	v0, MACH_FPC_ROUND_RN, inexact_nobias_s	# round to nearest
1818	beq	v0, MACH_FPC_ROUND_RZ, inexact_nobias_s	# round to zero
1819	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1820	beq	t0, zero, inexact_nobias_s	# if sign is positive, truncate
1821	b	2f
18221:
1823	bne	t0, zero, inexact_nobias_s	# if sign is negative, truncate
18242:
1825	addu	t2, t2, 1			# add rounding bit
1826	b	inexact_nobias_s
18273:
1828	li	v1, 32
1829	subu	v1, v1, t9
1830	sltu	v0, zero, t8			# be sure to save any one bits
1831	sll	t8, t2, v1			# save bits shifted out
1832	or	t8, t8, v0			# include sticky bits
1833	srl	t2, t2, t9
1834/*
1835 * Now round the denormalized result.
1836 */
1837	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1838	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1839	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
1840	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1841	beq	t0, zero, 5f			# if sign is positive, truncate
1842	b	2f
18431:
1844	bne	t0, zero, 5f			# if sign is negative, truncate
18452:
1846	beq	t8, zero, 5f			# if exact, continue
1847	addu	t2, t2, 1			# add rounding bit
1848	b	5f
18493:
1850	li	v0, GUARDBIT			# load guard bit for rounding
1851	addu	v0, v0, t8			# add remainder
1852	sltu	v1, v0, t8			# compute carry out
1853	beq	v1, zero, 4f			# if no carry, continue
1854	addu	t2, t2, 1			# add carry to result
18554:
1856	bne	v0, zero, 5f			# if rounded remainder is zero
1857	and	t2, t2, ~1			#  clear LSB (round to nearest)
18585:
1859	move	t1, zero			# denorm or zero exponent
1860	jal	set_fd_s			# save result
1861	beq	t8, zero, done			# check for exact result
1862	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
1863	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
1864	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1865	bne	v0, zero, fpe_trap
1866	ctc1	a1, MACH_FPC_CSR		# save exceptions
1867	b	done
1868
1869/*
1870 * Determine the amount to shift the fraction in order to restore the
1871 * normalized position. After that, round and handle exceptions.
1872 */
1873norm_d:
1874	move	v0, t2
1875	move	t9, zero			# t9 = num of leading zeros
1876	bne	t2, zero, 1f
1877	move	v0, t3
1878	addu	t9, 32
1879	bne	t3, zero, 1f
1880	move	v0, t8
1881	addu	t9, 32
18821:
1883	srl	v1, v0, 16
1884	bne	v1, zero, 1f
1885	addu	t9, 16
1886	sll	v0, 16
18871:
1888	srl	v1, v0, 24
1889	bne	v1, zero, 1f
1890	addu	t9, 8
1891	sll	v0, 8
18921:
1893	srl	v1, v0, 28
1894	bne	v1, zero, 1f
1895	addu	t9, 4
1896	sll	v0, 4
18971:
1898	srl	v1, v0, 30
1899	bne	v1, zero, 1f
1900	addu	t9, 2
1901	sll	v0, 2
19021:
1903	srl	v1, v0, 31
1904	bne	v1, zero, 1f
1905	addu	t9, 1
1906/*
1907 * Now shift t2,t3,t8 the correct number of bits.
1908 */
19091:
1910	subu	t9, t9, DLEAD_ZEROS		# dont count leading zeros
1911	subu	t1, t1, t9			# adjust the exponent
1912	beq	t9, zero, norm_noshift_d
1913	li	v1, 32
1914	blt	t9, zero, 2f			# if shift < 0, shift right
1915	blt	t9, v1, 1f			# shift by < 32?
1916	subu	t9, t9, v1			# shift by >= 32
1917	subu	v1, v1, t9
1918	sll	t2, t3, t9			# shift left by t9
1919	srl	v0, t8, v1			# save bits shifted out
1920	or	t2, t2, v0
1921	sll	t3, t8, t9
1922	move	t8, zero
1923	b	norm_noshift_d
19241:
1925	subu	v1, v1, t9
1926	sll	t2, t2, t9			# shift left by t9
1927	srl	v0, t3, v1			# save bits shifted out
1928	or	t2, t2, v0
1929	sll	t3, t3, t9
1930	srl	v0, t8, v1			# save bits shifted out
1931	or	t3, t3, v0
1932	sll	t8, t8, t9
1933	b	norm_noshift_d
19342:
1935	negu	t9				# shift right by t9
1936	subu	v1, v1, t9			#  (known to be < 32 bits)
1937	sll	v0, t8, v1			# save bits shifted out
1938	sltu	v0, zero, v0			# be sure to save any one bits
1939	srl	t8, t8, t9
1940	or	t8, t8, v0
1941	sll	v0, t3, v1			# save bits shifted out
1942	or	t8, t8, v0
1943	srl	t3, t3, t9
1944	sll	v0, t2, v1			# save bits shifted out
1945	or	t3, t3, v0
1946	srl	t2, t2, t9
1947norm_noshift_d:
1948	move	t5, t1				# save unrounded exponent
1949	move	t6, t2				# save unrounded fraction (MS)
1950	move	t7, t3				# save unrounded fraction (LS)
1951	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1952	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1953	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
1954	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1955	beq	t0, zero, 5f			# if sign is positive, truncate
1956	b	2f
19571:
1958	bne	t0, zero, 5f			# if sign is negative, truncate
19592:
1960	beq	t8, zero, 5f			# if exact, continue
1961	addu	t3, t3, 1			# add rounding bit
1962	bne	t3, zero, 5f			# branch if no carry
1963	addu	t2, t2, 1			# add carry
1964	bne	t2, DIMPL_ONE<<1, 5f		# need to adjust exponent?
1965	addu	t1, t1, 1			# adjust exponent
1966	srl	t2, t2, 1			# renormalize fraction
1967	b	5f
19683:
1969	li	v0, GUARDBIT			# load guard bit for rounding
1970	addu	v0, v0, t8			# add remainder
1971	sltu	v1, v0, t8			# compute carry out
1972	beq	v1, zero, 4f			# branch if no carry
1973	addu	t3, t3, 1			# add carry
1974	bne	t3, zero, 4f			# branch if no carry
1975	addu	t2, t2, 1			# add carry to result
1976	bne	t2, DIMPL_ONE<<1, 4f		# need to adjust exponent?
1977	addu	t1, t1, 1			# adjust exponent
1978	srl	t2, t2, 1			# renormalize fraction
19794:
1980	bne	v0, zero, 5f			# if rounded remainder is zero
1981	and	t3, t3, ~1			#  clear LSB (round to nearest)
19825:
1983	bgt	t1, DEXP_MAX, overflow_d	# overflow?
1984	blt	t1, DEXP_MIN, underflow_d	# underflow?
1985	bne	t8, zero, inexact_d		# is result inexact?
1986	addu	t1, t1, DEXP_BIAS		# bias exponent
1987	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1988	b	result_fs_d
1989
1990/*
1991 * Handle inexact exception.
1992 */
1993inexact_d:
1994	addu	t1, t1, DEXP_BIAS		# bias exponent
1995	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1996inexact_nobias_d:
1997	jal	set_fd_d			# save result
1998	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
1999	and	v0, a1, MACH_FPC_ENABLE_INEXACT
2000	bne	v0, zero, fpe_trap
2001	ctc1	a1, MACH_FPC_CSR		# save exceptions
2002	b	done
2003
2004/*
2005 * Overflow will trap (if enabled),
2006 * or generate an inexact trap (if enabled),
2007 * or generate an infinity.
2008 */
2009overflow_d:
2010	or	a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW
2011	and	v0, a1, MACH_FPC_ENABLE_OVERFLOW
2012	beq	v0, zero, 1f
2013	subu	t1, t1, 1536			# bias exponent
2014	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2015	jal	set_fd_d			# save result
2016	b	fpe_trap
20171:
2018	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
2019	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
2020	beq	v0, MACH_FPC_ROUND_RZ, 1f	# round to zero (truncate)
2021	beq	v0, MACH_FPC_ROUND_RP, 2f	# round to +infinity
2022	bne	t0, zero, 3f
20231:
2024	li	t1, DEXP_MAX			# result is max finite
2025	li	t2, 0x000fffff
2026	li	t3, 0xffffffff
2027	b	inexact_d
20282:
2029	bne	t0, zero, 1b
20303:
2031	li	t1, DEXP_MAX + 1		# result is infinity
2032	move	t2, zero
2033	move	t3, zero
2034	b	inexact_d
2035
2036/*
2037 * In this implementation, "tininess" is detected "after rounding" and
2038 * "loss of accuracy" is detected as "an inexact result".
2039 */
2040underflow_d:
2041	and	v0, a1, MACH_FPC_ENABLE_UNDERFLOW
2042	beq	v0, zero, 1f
2043/*
2044 * Underflow is enabled so compute the result and trap.
2045 */
2046	addu	t1, t1, 1536			# bias exponent
2047	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2048	jal	set_fd_d			# save result
2049	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
2050	b	fpe_trap
2051/*
2052 * Underflow is not enabled so compute the result,
2053 * signal inexact result (if it is) and trap (if enabled).
2054 */
20551:
2056	move	t1, t5				# get unrounded exponent
2057	move	t2, t6				# get unrounded fraction (MS)
2058	move	t3, t7				# get unrounded fraction (LS)
2059	li	t9, DEXP_MIN			# compute shift amount
2060	subu	t9, t9, t1			# shift t2,t8 right by t9
2061	blt	t9, DFRAC_BITS+2, 3f		# shift all the bits out?
2062	move	t1, zero			# result is inexact zero
2063	move	t2, zero
2064	move	t3, zero
2065	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
2066/*
2067 * Now round the zero result.
2068 * Only need to worry about rounding to +- infinity when the sign matches.
2069 */
2070	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
2071	beq	v0, MACH_FPC_ROUND_RN, inexact_nobias_d	# round to nearest
2072	beq	v0, MACH_FPC_ROUND_RZ, inexact_nobias_d	# round to zero
2073	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
2074	beq	t0, zero, inexact_nobias_d	# if sign is positive, truncate
2075	b	2f
20761:
2077	bne	t0, zero, inexact_nobias_d	# if sign is negative, truncate
20782:
2079	addu	t3, t3, 1			# add rounding bit
2080	b	inexact_nobias_d
20813:
2082	li	v1, 32
2083	blt	t9, v1, 1f			# shift by < 32?
2084	subu	t9, t9, v1			# shift right by >= 32
2085	subu	v1, v1, t9
2086	sltu	v0, zero, t8			# be sure to save any one bits
2087	sll	t8, t2, v1			# save bits shifted out
2088	or	t8, t8, v0			# include sticky bits
2089	srl	t3, t2, t9
2090	move	t2, zero
2091	b	2f
20921:
2093	subu	v1, v1, t9			# shift right by t9
2094	sltu	v0, zero, t8			# be sure to save any one bits
2095	sll	t8, t3, v1			# save bits shifted out
2096	or	t8, t8, v0			# include sticky bits
2097	srl	t3, t3, t9
2098	sll	v0, t2, v1			# save bits shifted out
2099	or	t3, t3, v0
2100	srl	t2, t2, t9
2101/*
2102 * Now round the denormalized result.
2103 */
21042:
2105	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
2106	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
2107	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
2108	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
2109	beq	t0, zero, 5f			# if sign is positive, truncate
2110	b	2f
21111:
2112	bne	t0, zero, 5f			# if sign is negative, truncate
21132:
2114	beq	t8, zero, 5f			# if exact, continue
2115	addu	t3, t3, 1			# add rounding bit
2116	bne	t3, zero, 5f			# if no carry, continue
2117	addu	t2, t2, 1			# add carry
2118	b	5f
21193:
2120	li	v0, GUARDBIT			# load guard bit for rounding
2121	addu	v0, v0, t8			# add remainder
2122	sltu	v1, v0, t8			# compute carry out
2123	beq	v1, zero, 4f			# if no carry, continue
2124	addu	t3, t3, 1			# add rounding bit
2125	bne	t3, zero, 4f			# if no carry, continue
2126	addu	t2, t2, 1			# add carry
21274:
2128	bne	v0, zero, 5f			# if rounded remainder is zero
2129	and	t3, t3, ~1			#  clear LSB (round to nearest)
21305:
2131	move	t1, zero			# denorm or zero exponent
2132	jal	set_fd_d			# save result
2133	beq	t8, zero, done			# check for exact result
2134	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
2135	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
2136	and	v0, a1, MACH_FPC_ENABLE_INEXACT
2137	bne	v0, zero, fpe_trap
2138	ctc1	a1, MACH_FPC_CSR		# save exceptions
2139	b	done
2140
2141/*
2142 * Signal an invalid operation if the trap is enabled; otherwise,
2143 * the result is a quiet NAN.
2144 */
2145invalid_s:					# trap invalid operation
2146	or	a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID
2147	and	v0, a1, MACH_FPC_ENABLE_INVALID
2148	bne	v0, zero, fpe_trap
2149	ctc1	a1, MACH_FPC_CSR		# save exceptions
2150	move	t0, zero			# result is a quiet NAN
2151	li	t1, SEXP_INF
2152	li	t2, SQUIET_NAN
2153	jal	set_fd_s			# save result (in t0,t1,t2)
2154	b	done
2155
2156/*
2157 * Signal an invalid operation if the trap is enabled; otherwise,
2158 * the result is a quiet NAN.
2159 */
2160invalid_d:					# trap invalid operation
2161	or	a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID
2162	and	v0, a1, MACH_FPC_ENABLE_INVALID
2163	bne	v0, zero, fpe_trap
2164	ctc1	a1, MACH_FPC_CSR		# save exceptions
2165	move	t0, zero			# result is a quiet NAN
2166	li	t1, DEXP_INF
2167	li	t2, DQUIET_NAN0
2168	li	t3, DQUIET_NAN1
2169	jal	set_fd_d			# save result (in t0,t1,t2,t3)
2170	b	done
2171
2172/*
2173 * Signal an invalid operation if the trap is enabled; otherwise,
2174 * the result is INT_MAX or INT_MIN.
2175 */
2176invalid_w:					# trap invalid operation
2177	or	a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID
2178	and	v0, a1, MACH_FPC_ENABLE_INVALID
2179	bne	v0, zero, fpe_trap
2180	ctc1	a1, MACH_FPC_CSR		# save exceptions
2181	bne	t0, zero, 1f
2182	li	t2, INT_MAX			# result is INT_MAX
2183	b	result_fs_w
21841:
2185	li	t2, INT_MIN			# result is INT_MIN
2186	b	result_fs_w
2187
2188/*
2189 * Trap if the hardware should have handled this case.
2190 */
2191fpe_trap:
2192	move	a2, a1				# code = FP CSR
2193	ctc1	a1, MACH_FPC_CSR		# save exceptions
2194	break	0
2195
2196/*
2197 * Send an illegal instruction signal to the current process.
2198 */
2199ill:
2200	ctc1	a1, MACH_FPC_CSR		# save exceptions
2201	move	a2, a0				# code = FP instruction
2202	break	0
2203
2204result_ft_s:
2205	move	t0, t4				# result is FT
2206	move	t1, t5
2207	move	t2, t6
2208result_fs_s:					# result is FS
2209	jal	set_fd_s			# save result (in t0,t1,t2)
2210	b	done
2211
2212result_fs_w:
2213	jal	set_fd_word			# save result (in t2)
2214	b	done
2215
2216result_ft_d:
2217	move	t0, t4				# result is FT
2218	move	t1, t5
2219	move	t2, t6
2220	move	t3, t7
2221result_fs_d:					# result is FS
2222	jal	set_fd_d			# save result (in t0,t1,t2,t3)
2223
2224done:
2225	lw	ra, STAND_RA_OFFSET(sp)
2226	addu	sp, sp, STAND_FRAME_SIZE
2227	j	ra
2228END(MachEmulateFP)
2229
2230/*----------------------------------------------------------------------------
2231 * get_fs_int --
2232 *
2233 *	Read (integer) the FS register (bits 15-11).
2234 *	This is an internal routine used by MachEmulateFP only.
2235 *
2236 * Results:
2237 *	t0	contains the sign
2238 *	t2	contains the fraction
2239 *
2240 *----------------------------------------------------------------------------
2241 */
2242LEAF(get_fs_int)
2243	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2244	and	a3, a3, 0xF << 2		# mask FS field
2245	lw	a3, get_fs_int_tbl(a3)		# switch on register number
2246	j	a3
2247
2248	.rdata
2249get_fs_int_tbl:
2250	.word	get_fs_int_f0
2251	.word	get_fs_int_f2
2252	.word	get_fs_int_f4
2253	.word	get_fs_int_f6
2254	.word	get_fs_int_f8
2255	.word	get_fs_int_f10
2256	.word	get_fs_int_f12
2257	.word	get_fs_int_f14
2258	.word	get_fs_int_f16
2259	.word	get_fs_int_f18
2260	.word	get_fs_int_f20
2261	.word	get_fs_int_f22
2262	.word	get_fs_int_f24
2263	.word	get_fs_int_f26
2264	.word	get_fs_int_f28
2265	.word	get_fs_int_f30
2266	.text
2267
2268get_fs_int_f0:
2269	mfc1	t2, $f0
2270	b	get_fs_int_done
2271get_fs_int_f2:
2272	mfc1	t2, $f2
2273	b	get_fs_int_done
2274get_fs_int_f4:
2275	mfc1	t2, $f4
2276	b	get_fs_int_done
2277get_fs_int_f6:
2278	mfc1	t2, $f6
2279	b	get_fs_int_done
2280get_fs_int_f8:
2281	mfc1	t2, $f8
2282	b	get_fs_int_done
2283get_fs_int_f10:
2284	mfc1	t2, $f10
2285	b	get_fs_int_done
2286get_fs_int_f12:
2287	mfc1	t2, $f12
2288	b	get_fs_int_done
2289get_fs_int_f14:
2290	mfc1	t2, $f14
2291	b	get_fs_int_done
2292get_fs_int_f16:
2293	mfc1	t2, $f16
2294	b	get_fs_int_done
2295get_fs_int_f18:
2296	mfc1	t2, $f18
2297	b	get_fs_int_done
2298get_fs_int_f20:
2299	mfc1	t2, $f20
2300	b	get_fs_int_done
2301get_fs_int_f22:
2302	mfc1	t2, $f22
2303	b	get_fs_int_done
2304get_fs_int_f24:
2305	mfc1	t2, $f24
2306	b	get_fs_int_done
2307get_fs_int_f26:
2308	mfc1	t2, $f26
2309	b	get_fs_int_done
2310get_fs_int_f28:
2311	mfc1	t2, $f28
2312	b	get_fs_int_done
2313get_fs_int_f30:
2314	mfc1	t2, $f30
2315get_fs_int_done:
2316	srl	t0, t2, 31		# init the sign bit
2317	bge	t2, zero, 1f
2318	negu	t2
23191:
2320	j	ra
2321END(get_fs_int)
2322
2323/*----------------------------------------------------------------------------
2324 * get_ft_fs_s --
2325 *
2326 *	Read (single precision) the FT register (bits 20-16) and
2327 *	the FS register (bits 15-11) and break up into fields.
2328 *	This is an internal routine used by MachEmulateFP only.
2329 *
2330 * Results:
2331 *	t0	contains the FS sign
2332 *	t1	contains the FS (biased) exponent
2333 *	t2	contains the FS fraction
2334 *	t4	contains the FT sign
2335 *	t5	contains the FT (biased) exponent
2336 *	t6	contains the FT fraction
2337 *
2338 *----------------------------------------------------------------------------
2339 */
2340LEAF(get_ft_fs_s)
2341	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2342	and	a3, a3, 0xF << 2		# mask FT field
2343	lw	a3, get_ft_s_tbl(a3)		# switch on register number
2344	j	a3
2345
2346	.rdata
2347get_ft_s_tbl:
2348	.word	get_ft_s_f0
2349	.word	get_ft_s_f2
2350	.word	get_ft_s_f4
2351	.word	get_ft_s_f6
2352	.word	get_ft_s_f8
2353	.word	get_ft_s_f10
2354	.word	get_ft_s_f12
2355	.word	get_ft_s_f14
2356	.word	get_ft_s_f16
2357	.word	get_ft_s_f18
2358	.word	get_ft_s_f20
2359	.word	get_ft_s_f22
2360	.word	get_ft_s_f24
2361	.word	get_ft_s_f26
2362	.word	get_ft_s_f28
2363	.word	get_ft_s_f30
2364	.text
2365
2366get_ft_s_f0:
2367	mfc1	t4, $f0
2368	b	get_ft_s_done
2369get_ft_s_f2:
2370	mfc1	t4, $f2
2371	b	get_ft_s_done
2372get_ft_s_f4:
2373	mfc1	t4, $f4
2374	b	get_ft_s_done
2375get_ft_s_f6:
2376	mfc1	t4, $f6
2377	b	get_ft_s_done
2378get_ft_s_f8:
2379	mfc1	t4, $f8
2380	b	get_ft_s_done
2381get_ft_s_f10:
2382	mfc1	t4, $f10
2383	b	get_ft_s_done
2384get_ft_s_f12:
2385	mfc1	t4, $f12
2386	b	get_ft_s_done
2387get_ft_s_f14:
2388	mfc1	t4, $f14
2389	b	get_ft_s_done
2390get_ft_s_f16:
2391	mfc1	t4, $f16
2392	b	get_ft_s_done
2393get_ft_s_f18:
2394	mfc1	t4, $f18
2395	b	get_ft_s_done
2396get_ft_s_f20:
2397	mfc1	t4, $f20
2398	b	get_ft_s_done
2399get_ft_s_f22:
2400	mfc1	t4, $f22
2401	b	get_ft_s_done
2402get_ft_s_f24:
2403	mfc1	t4, $f24
2404	b	get_ft_s_done
2405get_ft_s_f26:
2406	mfc1	t4, $f26
2407	b	get_ft_s_done
2408get_ft_s_f28:
2409	mfc1	t4, $f28
2410	b	get_ft_s_done
2411get_ft_s_f30:
2412	mfc1	t4, $f30
2413get_ft_s_done:
2414	srl	t5, t4, 23			# get exponent
2415	and	t5, t5, 0xFF
2416	and	t6, t4, 0x7FFFFF		# get fraction
2417	srl	t4, t4, 31			# get sign
2418	bne	t5, SEXP_INF, 1f		# is it a signaling NAN?
2419	and	v0, t6, SSIGNAL_NAN
2420	bne	v0, zero, invalid_s
24211:
2422	/* fall through to get FS */
2423
2424/*----------------------------------------------------------------------------
2425 * get_fs_s --
2426 *
2427 *	Read (single precision) the FS register (bits 15-11) and
2428 *	break up into fields.
2429 *	This is an internal routine used by MachEmulateFP only.
2430 *
2431 * Results:
2432 *	t0	contains the sign
2433 *	t1	contains the (biased) exponent
2434 *	t2	contains the fraction
2435 *
2436 *----------------------------------------------------------------------------
2437 */
2438ALEAF(get_fs_s)
2439	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2440	and	a3, a3, 0xF << 2		# mask FS field
2441	lw	a3, get_fs_s_tbl(a3)		# switch on register number
2442	j	a3
2443
2444	.rdata
2445get_fs_s_tbl:
2446	.word	get_fs_s_f0
2447	.word	get_fs_s_f2
2448	.word	get_fs_s_f4
2449	.word	get_fs_s_f6
2450	.word	get_fs_s_f8
2451	.word	get_fs_s_f10
2452	.word	get_fs_s_f12
2453	.word	get_fs_s_f14
2454	.word	get_fs_s_f16
2455	.word	get_fs_s_f18
2456	.word	get_fs_s_f20
2457	.word	get_fs_s_f22
2458	.word	get_fs_s_f24
2459	.word	get_fs_s_f26
2460	.word	get_fs_s_f28
2461	.word	get_fs_s_f30
2462	.text
2463
2464get_fs_s_f0:
2465	mfc1	t0, $f0
2466	b	get_fs_s_done
2467get_fs_s_f2:
2468	mfc1	t0, $f2
2469	b	get_fs_s_done
2470get_fs_s_f4:
2471	mfc1	t0, $f4
2472	b	get_fs_s_done
2473get_fs_s_f6:
2474	mfc1	t0, $f6
2475	b	get_fs_s_done
2476get_fs_s_f8:
2477	mfc1	t0, $f8
2478	b	get_fs_s_done
2479get_fs_s_f10:
2480	mfc1	t0, $f10
2481	b	get_fs_s_done
2482get_fs_s_f12:
2483	mfc1	t0, $f12
2484	b	get_fs_s_done
2485get_fs_s_f14:
2486	mfc1	t0, $f14
2487	b	get_fs_s_done
2488get_fs_s_f16:
2489	mfc1	t0, $f16
2490	b	get_fs_s_done
2491get_fs_s_f18:
2492	mfc1	t0, $f18
2493	b	get_fs_s_done
2494get_fs_s_f20:
2495	mfc1	t0, $f20
2496	b	get_fs_s_done
2497get_fs_s_f22:
2498	mfc1	t0, $f22
2499	b	get_fs_s_done
2500get_fs_s_f24:
2501	mfc1	t0, $f24
2502	b	get_fs_s_done
2503get_fs_s_f26:
2504	mfc1	t0, $f26
2505	b	get_fs_s_done
2506get_fs_s_f28:
2507	mfc1	t0, $f28
2508	b	get_fs_s_done
2509get_fs_s_f30:
2510	mfc1	t0, $f30
2511get_fs_s_done:
2512	srl	t1, t0, 23			# get exponent
2513	and	t1, t1, 0xFF
2514	and	t2, t0, 0x7FFFFF		# get fraction
2515	srl	t0, t0, 31			# get sign
2516	bne	t1, SEXP_INF, 1f		# is it a signaling NAN?
2517	and	v0, t2, SSIGNAL_NAN
2518	bne	v0, zero, invalid_s
25191:
2520	j	ra
2521END(get_ft_fs_s)
2522
2523/*----------------------------------------------------------------------------
2524 * get_ft_fs_d --
2525 *
2526 *	Read (double precision) the FT register (bits 20-16) and
2527 *	the FS register (bits 15-11) and break up into fields.
2528 *	This is an internal routine used by MachEmulateFP only.
2529 *
2530 * Results:
2531 *	t0	contains the FS sign
2532 *	t1	contains the FS (biased) exponent
2533 *	t2	contains the FS fraction
2534 *	t3	contains the FS remaining fraction
2535 *	t4	contains the FT sign
2536 *	t5	contains the FT (biased) exponent
2537 *	t6	contains the FT fraction
2538 *	t7	contains the FT remaining fraction
2539 *
2540 *----------------------------------------------------------------------------
2541 */
2542LEAF(get_ft_fs_d)
2543	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2544	and	a3, a3, 0xF << 2		# mask FT field
2545	lw	a3, get_ft_d_tbl(a3)		# switch on register number
2546	j	a3
2547
2548	.rdata
2549get_ft_d_tbl:
2550	.word	get_ft_d_f0
2551	.word	get_ft_d_f2
2552	.word	get_ft_d_f4
2553	.word	get_ft_d_f6
2554	.word	get_ft_d_f8
2555	.word	get_ft_d_f10
2556	.word	get_ft_d_f12
2557	.word	get_ft_d_f14
2558	.word	get_ft_d_f16
2559	.word	get_ft_d_f18
2560	.word	get_ft_d_f20
2561	.word	get_ft_d_f22
2562	.word	get_ft_d_f24
2563	.word	get_ft_d_f26
2564	.word	get_ft_d_f28
2565	.word	get_ft_d_f30
2566	.text
2567
2568get_ft_d_f0:
2569	mfc1	t7, $f0
2570	mfc1	t4, $f1
2571	b	get_ft_d_done
2572get_ft_d_f2:
2573	mfc1	t7, $f2
2574	mfc1	t4, $f3
2575	b	get_ft_d_done
2576get_ft_d_f4:
2577	mfc1	t7, $f4
2578	mfc1	t4, $f5
2579	b	get_ft_d_done
2580get_ft_d_f6:
2581	mfc1	t7, $f6
2582	mfc1	t4, $f7
2583	b	get_ft_d_done
2584get_ft_d_f8:
2585	mfc1	t7, $f8
2586	mfc1	t4, $f9
2587	b	get_ft_d_done
2588get_ft_d_f10:
2589	mfc1	t7, $f10
2590	mfc1	t4, $f11
2591	b	get_ft_d_done
2592get_ft_d_f12:
2593	mfc1	t7, $f12
2594	mfc1	t4, $f13
2595	b	get_ft_d_done
2596get_ft_d_f14:
2597	mfc1	t7, $f14
2598	mfc1	t4, $f15
2599	b	get_ft_d_done
2600get_ft_d_f16:
2601	mfc1	t7, $f16
2602	mfc1	t4, $f17
2603	b	get_ft_d_done
2604get_ft_d_f18:
2605	mfc1	t7, $f18
2606	mfc1	t4, $f19
2607	b	get_ft_d_done
2608get_ft_d_f20:
2609	mfc1	t7, $f20
2610	mfc1	t4, $f21
2611	b	get_ft_d_done
2612get_ft_d_f22:
2613	mfc1	t7, $f22
2614	mfc1	t4, $f23
2615	b	get_ft_d_done
2616get_ft_d_f24:
2617	mfc1	t7, $f24
2618	mfc1	t4, $f25
2619	b	get_ft_d_done
2620get_ft_d_f26:
2621	mfc1	t7, $f26
2622	mfc1	t4, $f27
2623	b	get_ft_d_done
2624get_ft_d_f28:
2625	mfc1	t7, $f28
2626	mfc1	t4, $f29
2627	b	get_ft_d_done
2628get_ft_d_f30:
2629	mfc1	t7, $f30
2630	mfc1	t4, $f31
2631get_ft_d_done:
2632	srl	t5, t4, 20			# get exponent
2633	and	t5, t5, 0x7FF
2634	and	t6, t4, 0xFFFFF			# get fraction
2635	srl	t4, t4, 31			# get sign
2636	bne	t5, DEXP_INF, 1f		# is it a signaling NAN?
2637	and	v0, t6, DSIGNAL_NAN
2638	bne	v0, zero, invalid_d
26391:
2640	/* fall through to get FS */
2641
2642/*----------------------------------------------------------------------------
2643 * get_fs_d --
2644 *
2645 *	Read (double precision) the FS register (bits 15-11) and
2646 *	break up into fields.
2647 *	This is an internal routine used by MachEmulateFP only.
2648 *
2649 * Results:
2650 *	t0	contains the sign
2651 *	t1	contains the (biased) exponent
2652 *	t2	contains the fraction
2653 *	t3	contains the remaining fraction
2654 *
2655 *----------------------------------------------------------------------------
2656 */
2657ALEAF(get_fs_d)
2658	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2659	and	a3, a3, 0xF << 2		# mask FS field
2660	lw	a3, get_fs_d_tbl(a3)		# switch on register number
2661	j	a3
2662
2663	.rdata
2664get_fs_d_tbl:
2665	.word	get_fs_d_f0
2666	.word	get_fs_d_f2
2667	.word	get_fs_d_f4
2668	.word	get_fs_d_f6
2669	.word	get_fs_d_f8
2670	.word	get_fs_d_f10
2671	.word	get_fs_d_f12
2672	.word	get_fs_d_f14
2673	.word	get_fs_d_f16
2674	.word	get_fs_d_f18
2675	.word	get_fs_d_f20
2676	.word	get_fs_d_f22
2677	.word	get_fs_d_f24
2678	.word	get_fs_d_f26
2679	.word	get_fs_d_f28
2680	.word	get_fs_d_f30
2681	.text
2682
2683get_fs_d_f0:
2684	mfc1	t3, $f0
2685	mfc1	t0, $f1
2686	b	get_fs_d_done
2687get_fs_d_f2:
2688	mfc1	t3, $f2
2689	mfc1	t0, $f3
2690	b	get_fs_d_done
2691get_fs_d_f4:
2692	mfc1	t3, $f4
2693	mfc1	t0, $f5
2694	b	get_fs_d_done
2695get_fs_d_f6:
2696	mfc1	t3, $f6
2697	mfc1	t0, $f7
2698	b	get_fs_d_done
2699get_fs_d_f8:
2700	mfc1	t3, $f8
2701	mfc1	t0, $f9
2702	b	get_fs_d_done
2703get_fs_d_f10:
2704	mfc1	t3, $f10
2705	mfc1	t0, $f11
2706	b	get_fs_d_done
2707get_fs_d_f12:
2708	mfc1	t3, $f12
2709	mfc1	t0, $f13
2710	b	get_fs_d_done
2711get_fs_d_f14:
2712	mfc1	t3, $f14
2713	mfc1	t0, $f15
2714	b	get_fs_d_done
2715get_fs_d_f16:
2716	mfc1	t3, $f16
2717	mfc1	t0, $f17
2718	b	get_fs_d_done
2719get_fs_d_f18:
2720	mfc1	t3, $f18
2721	mfc1	t0, $f19
2722	b	get_fs_d_done
2723get_fs_d_f20:
2724	mfc1	t3, $f20
2725	mfc1	t0, $f21
2726	b	get_fs_d_done
2727get_fs_d_f22:
2728	mfc1	t3, $f22
2729	mfc1	t0, $f23
2730	b	get_fs_d_done
2731get_fs_d_f24:
2732	mfc1	t3, $f24
2733	mfc1	t0, $f25
2734	b	get_fs_d_done
2735get_fs_d_f26:
2736	mfc1	t3, $f26
2737	mfc1	t0, $f27
2738	b	get_fs_d_done
2739get_fs_d_f28:
2740	mfc1	t3, $f28
2741	mfc1	t0, $f29
2742	b	get_fs_d_done
2743get_fs_d_f30:
2744	mfc1	t3, $f30
2745	mfc1	t0, $f31
2746get_fs_d_done:
2747	srl	t1, t0, 20			# get exponent
2748	and	t1, t1, 0x7FF
2749	and	t2, t0, 0xFFFFF			# get fraction
2750	srl	t0, t0, 31			# get sign
2751	bne	t1, DEXP_INF, 1f		# is it a signaling NAN?
2752	and	v0, t2, DSIGNAL_NAN
2753	bne	v0, zero, invalid_d
27541:
2755	j	ra
2756END(get_ft_fs_d)
2757
2758/*----------------------------------------------------------------------------
2759 * get_cmp_s --
2760 *
2761 *	Read (single precision) the FS register (bits 15-11) and
2762 *	the FT register (bits 20-16) and break up into fields.
2763 *	This is an internal routine used by MachEmulateFP only.
2764 *
2765 * Results:
2766 *	t0	contains the sign
2767 *	t1	contains the (biased) exponent
2768 *	t2	contains the fraction
2769 *	t4	contains the sign
2770 *	t5	contains the (biased) exponent
2771 *	t6	contains the fraction
2772 *
2773 *----------------------------------------------------------------------------
2774 */
2775LEAF(get_cmp_s)
2776	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2777	and	a3, a3, 0xF << 2		# mask FS field
2778	lw	a3, cmp_fs_s_tbl(a3)		# switch on register number
2779	j	a3
2780
2781	.rdata
2782cmp_fs_s_tbl:
2783	.word	cmp_fs_s_f0
2784	.word	cmp_fs_s_f2
2785	.word	cmp_fs_s_f4
2786	.word	cmp_fs_s_f6
2787	.word	cmp_fs_s_f8
2788	.word	cmp_fs_s_f10
2789	.word	cmp_fs_s_f12
2790	.word	cmp_fs_s_f14
2791	.word	cmp_fs_s_f16
2792	.word	cmp_fs_s_f18
2793	.word	cmp_fs_s_f20
2794	.word	cmp_fs_s_f22
2795	.word	cmp_fs_s_f24
2796	.word	cmp_fs_s_f26
2797	.word	cmp_fs_s_f28
2798	.word	cmp_fs_s_f30
2799	.text
2800
2801cmp_fs_s_f0:
2802	mfc1	t0, $f0
2803	b	cmp_fs_s_done
2804cmp_fs_s_f2:
2805	mfc1	t0, $f2
2806	b	cmp_fs_s_done
2807cmp_fs_s_f4:
2808	mfc1	t0, $f4
2809	b	cmp_fs_s_done
2810cmp_fs_s_f6:
2811	mfc1	t0, $f6
2812	b	cmp_fs_s_done
2813cmp_fs_s_f8:
2814	mfc1	t0, $f8
2815	b	cmp_fs_s_done
2816cmp_fs_s_f10:
2817	mfc1	t0, $f10
2818	b	cmp_fs_s_done
2819cmp_fs_s_f12:
2820	mfc1	t0, $f12
2821	b	cmp_fs_s_done
2822cmp_fs_s_f14:
2823	mfc1	t0, $f14
2824	b	cmp_fs_s_done
2825cmp_fs_s_f16:
2826	mfc1	t0, $f16
2827	b	cmp_fs_s_done
2828cmp_fs_s_f18:
2829	mfc1	t0, $f18
2830	b	cmp_fs_s_done
2831cmp_fs_s_f20:
2832	mfc1	t0, $f20
2833	b	cmp_fs_s_done
2834cmp_fs_s_f22:
2835	mfc1	t0, $f22
2836	b	cmp_fs_s_done
2837cmp_fs_s_f24:
2838	mfc1	t0, $f24
2839	b	cmp_fs_s_done
2840cmp_fs_s_f26:
2841	mfc1	t0, $f26
2842	b	cmp_fs_s_done
2843cmp_fs_s_f28:
2844	mfc1	t0, $f28
2845	b	cmp_fs_s_done
2846cmp_fs_s_f30:
2847	mfc1	t0, $f30
2848cmp_fs_s_done:
2849	srl	t1, t0, 23			# get exponent
2850	and	t1, t1, 0xFF
2851	and	t2, t0, 0x7FFFFF		# get fraction
2852	srl	t0, t0, 31			# get sign
2853
2854	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2855	and	a3, a3, 0xF << 2		# mask FT field
2856	lw	a3, cmp_ft_s_tbl(a3)		# switch on register number
2857	j	a3
2858
2859	.rdata
2860cmp_ft_s_tbl:
2861	.word	cmp_ft_s_f0
2862	.word	cmp_ft_s_f2
2863	.word	cmp_ft_s_f4
2864	.word	cmp_ft_s_f6
2865	.word	cmp_ft_s_f8
2866	.word	cmp_ft_s_f10
2867	.word	cmp_ft_s_f12
2868	.word	cmp_ft_s_f14
2869	.word	cmp_ft_s_f16
2870	.word	cmp_ft_s_f18
2871	.word	cmp_ft_s_f20
2872	.word	cmp_ft_s_f22
2873	.word	cmp_ft_s_f24
2874	.word	cmp_ft_s_f26
2875	.word	cmp_ft_s_f28
2876	.word	cmp_ft_s_f30
2877	.text
2878
2879cmp_ft_s_f0:
2880	mfc1	t4, $f0
2881	b	cmp_ft_s_done
2882cmp_ft_s_f2:
2883	mfc1	t4, $f2
2884	b	cmp_ft_s_done
2885cmp_ft_s_f4:
2886	mfc1	t4, $f4
2887	b	cmp_ft_s_done
2888cmp_ft_s_f6:
2889	mfc1	t4, $f6
2890	b	cmp_ft_s_done
2891cmp_ft_s_f8:
2892	mfc1	t4, $f8
2893	b	cmp_ft_s_done
2894cmp_ft_s_f10:
2895	mfc1	t4, $f10
2896	b	cmp_ft_s_done
2897cmp_ft_s_f12:
2898	mfc1	t4, $f12
2899	b	cmp_ft_s_done
2900cmp_ft_s_f14:
2901	mfc1	t4, $f14
2902	b	cmp_ft_s_done
2903cmp_ft_s_f16:
2904	mfc1	t4, $f16
2905	b	cmp_ft_s_done
2906cmp_ft_s_f18:
2907	mfc1	t4, $f18
2908	b	cmp_ft_s_done
2909cmp_ft_s_f20:
2910	mfc1	t4, $f20
2911	b	cmp_ft_s_done
2912cmp_ft_s_f22:
2913	mfc1	t4, $f22
2914	b	cmp_ft_s_done
2915cmp_ft_s_f24:
2916	mfc1	t4, $f24
2917	b	cmp_ft_s_done
2918cmp_ft_s_f26:
2919	mfc1	t4, $f26
2920	b	cmp_ft_s_done
2921cmp_ft_s_f28:
2922	mfc1	t4, $f28
2923	b	cmp_ft_s_done
2924cmp_ft_s_f30:
2925	mfc1	t4, $f30
2926cmp_ft_s_done:
2927	srl	t5, t4, 23			# get exponent
2928	and	t5, t5, 0xFF
2929	and	t6, t4, 0x7FFFFF		# get fraction
2930	srl	t4, t4, 31			# get sign
2931	j	ra
2932END(get_cmp_s)
2933
2934/*----------------------------------------------------------------------------
2935 * get_cmp_d --
2936 *
2937 *	Read (double precision) the FS register (bits 15-11) and
2938 *	the FT register (bits 20-16) and break up into fields.
2939 *	This is an internal routine used by MachEmulateFP only.
2940 *
2941 * Results:
2942 *	t0	contains the sign
2943 *	t1	contains the (biased) exponent
2944 *	t2	contains the fraction
2945 *	t3	contains the remaining fraction
2946 *	t4	contains the sign
2947 *	t5	contains the (biased) exponent
2948 *	t6	contains the fraction
2949 *	t7	contains the remaining fraction
2950 *
2951 *----------------------------------------------------------------------------
2952 */
2953LEAF(get_cmp_d)
2954	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2955	and	a3, a3, 0xF << 2		# mask FS field
2956	lw	a3, cmp_fs_d_tbl(a3)		# switch on register number
2957	j	a3
2958
2959	.rdata
2960cmp_fs_d_tbl:
2961	.word	cmp_fs_d_f0
2962	.word	cmp_fs_d_f2
2963	.word	cmp_fs_d_f4
2964	.word	cmp_fs_d_f6
2965	.word	cmp_fs_d_f8
2966	.word	cmp_fs_d_f10
2967	.word	cmp_fs_d_f12
2968	.word	cmp_fs_d_f14
2969	.word	cmp_fs_d_f16
2970	.word	cmp_fs_d_f18
2971	.word	cmp_fs_d_f20
2972	.word	cmp_fs_d_f22
2973	.word	cmp_fs_d_f24
2974	.word	cmp_fs_d_f26
2975	.word	cmp_fs_d_f28
2976	.word	cmp_fs_d_f30
2977	.text
2978
2979cmp_fs_d_f0:
2980	mfc1	t3, $f0
2981	mfc1	t0, $f1
2982	b	cmp_fs_d_done
2983cmp_fs_d_f2:
2984	mfc1	t3, $f2
2985	mfc1	t0, $f3
2986	b	cmp_fs_d_done
2987cmp_fs_d_f4:
2988	mfc1	t3, $f4
2989	mfc1	t0, $f5
2990	b	cmp_fs_d_done
2991cmp_fs_d_f6:
2992	mfc1	t3, $f6
2993	mfc1	t0, $f7
2994	b	cmp_fs_d_done
2995cmp_fs_d_f8:
2996	mfc1	t3, $f8
2997	mfc1	t0, $f9
2998	b	cmp_fs_d_done
2999cmp_fs_d_f10:
3000	mfc1	t3, $f10
3001	mfc1	t0, $f11
3002	b	cmp_fs_d_done
3003cmp_fs_d_f12:
3004	mfc1	t3, $f12
3005	mfc1	t0, $f13
3006	b	cmp_fs_d_done
3007cmp_fs_d_f14:
3008	mfc1	t3, $f14
3009	mfc1	t0, $f15
3010	b	cmp_fs_d_done
3011cmp_fs_d_f16:
3012	mfc1	t3, $f16
3013	mfc1	t0, $f17
3014	b	cmp_fs_d_done
3015cmp_fs_d_f18:
3016	mfc1	t3, $f18
3017	mfc1	t0, $f19
3018	b	cmp_fs_d_done
3019cmp_fs_d_f20:
3020	mfc1	t3, $f20
3021	mfc1	t0, $f21
3022	b	cmp_fs_d_done
3023cmp_fs_d_f22:
3024	mfc1	t3, $f22
3025	mfc1	t0, $f23
3026	b	cmp_fs_d_done
3027cmp_fs_d_f24:
3028	mfc1	t3, $f24
3029	mfc1	t0, $f25
3030	b	cmp_fs_d_done
3031cmp_fs_d_f26:
3032	mfc1	t3, $f26
3033	mfc1	t0, $f27
3034	b	cmp_fs_d_done
3035cmp_fs_d_f28:
3036	mfc1	t3, $f28
3037	mfc1	t0, $f29
3038	b	cmp_fs_d_done
3039cmp_fs_d_f30:
3040	mfc1	t3, $f30
3041	mfc1	t0, $f31
3042cmp_fs_d_done:
3043	srl	t1, t0, 20			# get exponent
3044	and	t1, t1, 0x7FF
3045	and	t2, t0, 0xFFFFF			# get fraction
3046	srl	t0, t0, 31			# get sign
3047
3048	srl	a3, a0, 17 - 2			# get FT field (even regs only)
3049	and	a3, a3, 0xF << 2		# mask FT field
3050	lw	a3, cmp_ft_d_tbl(a3)		# switch on register number
3051	j	a3
3052
3053	.rdata
3054cmp_ft_d_tbl:
3055	.word	cmp_ft_d_f0
3056	.word	cmp_ft_d_f2
3057	.word	cmp_ft_d_f4
3058	.word	cmp_ft_d_f6
3059	.word	cmp_ft_d_f8
3060	.word	cmp_ft_d_f10
3061	.word	cmp_ft_d_f12
3062	.word	cmp_ft_d_f14
3063	.word	cmp_ft_d_f16
3064	.word	cmp_ft_d_f18
3065	.word	cmp_ft_d_f20
3066	.word	cmp_ft_d_f22
3067	.word	cmp_ft_d_f24
3068	.word	cmp_ft_d_f26
3069	.word	cmp_ft_d_f28
3070	.word	cmp_ft_d_f30
3071	.text
3072
3073cmp_ft_d_f0:
3074	mfc1	t7, $f0
3075	mfc1	t4, $f1
3076	b	cmp_ft_d_done
3077cmp_ft_d_f2:
3078	mfc1	t7, $f2
3079	mfc1	t4, $f3
3080	b	cmp_ft_d_done
3081cmp_ft_d_f4:
3082	mfc1	t7, $f4
3083	mfc1	t4, $f5
3084	b	cmp_ft_d_done
3085cmp_ft_d_f6:
3086	mfc1	t7, $f6
3087	mfc1	t4, $f7
3088	b	cmp_ft_d_done
3089cmp_ft_d_f8:
3090	mfc1	t7, $f8
3091	mfc1	t4, $f9
3092	b	cmp_ft_d_done
3093cmp_ft_d_f10:
3094	mfc1	t7, $f10
3095	mfc1	t4, $f11
3096	b	cmp_ft_d_done
3097cmp_ft_d_f12:
3098	mfc1	t7, $f12
3099	mfc1	t4, $f13
3100	b	cmp_ft_d_done
3101cmp_ft_d_f14:
3102	mfc1	t7, $f14
3103	mfc1	t4, $f15
3104	b	cmp_ft_d_done
3105cmp_ft_d_f16:
3106	mfc1	t7, $f16
3107	mfc1	t4, $f17
3108	b	cmp_ft_d_done
3109cmp_ft_d_f18:
3110	mfc1	t7, $f18
3111	mfc1	t4, $f19
3112	b	cmp_ft_d_done
3113cmp_ft_d_f20:
3114	mfc1	t7, $f20
3115	mfc1	t4, $f21
3116	b	cmp_ft_d_done
3117cmp_ft_d_f22:
3118	mfc1	t7, $f22
3119	mfc1	t4, $f23
3120	b	cmp_ft_d_done
3121cmp_ft_d_f24:
3122	mfc1	t7, $f24
3123	mfc1	t4, $f25
3124	b	cmp_ft_d_done
3125cmp_ft_d_f26:
3126	mfc1	t7, $f26
3127	mfc1	t4, $f27
3128	b	cmp_ft_d_done
3129cmp_ft_d_f28:
3130	mfc1	t7, $f28
3131	mfc1	t4, $f29
3132	b	cmp_ft_d_done
3133cmp_ft_d_f30:
3134	mfc1	t7, $f30
3135	mfc1	t4, $f31
3136cmp_ft_d_done:
3137	srl	t5, t4, 20			# get exponent
3138	and	t5, t5, 0x7FF
3139	and	t6, t4, 0xFFFFF			# get fraction
3140	srl	t4, t4, 31			# get sign
3141	j	ra
3142END(get_cmp_d)
3143
3144/*----------------------------------------------------------------------------
3145 * set_fd_s --
3146 *
3147 *	Write (single precision) the FD register (bits 10-6).
3148 *	This is an internal routine used by MachEmulateFP only.
3149 *
3150 * Arguments:
3151 *	a0	contains the FP instruction
3152 *	t0	contains the sign
3153 *	t1	contains the (biased) exponent
3154 *	t2	contains the fraction
3155 *
3156 * set_fd_word --
3157 *
3158 *	Write (integer) the FD register (bits 10-6).
3159 *	This is an internal routine used by MachEmulateFP only.
3160 *
3161 * Arguments:
3162 *	a0	contains the FP instruction
3163 *	t2	contains the integer
3164 *
3165 *----------------------------------------------------------------------------
3166 */
3167LEAF(set_fd_s)
3168	sll	t0, t0, 31			# position sign
3169	sll	t1, t1, 23			# position exponent
3170	or	t2, t2, t0
3171	or	t2, t2, t1
3172ALEAF(set_fd_word)
3173	srl	a3, a0, 7 - 2			# get FD field (even regs only)
3174	and	a3, a3, 0xF << 2		# mask FT field
3175	lw	a3, set_fd_s_tbl(a3)		# switch on register number
3176	j	a3
3177
3178	.rdata
3179set_fd_s_tbl:
3180	.word	set_fd_s_f0
3181	.word	set_fd_s_f2
3182	.word	set_fd_s_f4
3183	.word	set_fd_s_f6
3184	.word	set_fd_s_f8
3185	.word	set_fd_s_f10
3186	.word	set_fd_s_f12
3187	.word	set_fd_s_f14
3188	.word	set_fd_s_f16
3189	.word	set_fd_s_f18
3190	.word	set_fd_s_f20
3191	.word	set_fd_s_f22
3192	.word	set_fd_s_f24
3193	.word	set_fd_s_f26
3194	.word	set_fd_s_f28
3195	.word	set_fd_s_f30
3196	.text
3197
3198set_fd_s_f0:
3199	mtc1	t2, $f0
3200	j	ra
3201set_fd_s_f2:
3202	mtc1	t2, $f2
3203	j	ra
3204set_fd_s_f4:
3205	mtc1	t2, $f4
3206	j	ra
3207set_fd_s_f6:
3208	mtc1	t2, $f6
3209	j	ra
3210set_fd_s_f8:
3211	mtc1	t2, $f8
3212	j	ra
3213set_fd_s_f10:
3214	mtc1	t2, $f10
3215	j	ra
3216set_fd_s_f12:
3217	mtc1	t2, $f12
3218	j	ra
3219set_fd_s_f14:
3220	mtc1	t2, $f14
3221	j	ra
3222set_fd_s_f16:
3223	mtc1	t2, $f16
3224	j	ra
3225set_fd_s_f18:
3226	mtc1	t2, $f18
3227	j	ra
3228set_fd_s_f20:
3229	mtc1	t2, $f20
3230	j	ra
3231set_fd_s_f22:
3232	mtc1	t2, $f22
3233	j	ra
3234set_fd_s_f24:
3235	mtc1	t2, $f24
3236	j	ra
3237set_fd_s_f26:
3238	mtc1	t2, $f26
3239	j	ra
3240set_fd_s_f28:
3241	mtc1	t2, $f28
3242	j	ra
3243set_fd_s_f30:
3244	mtc1	t2, $f30
3245	j	ra
3246END(set_fd_s)
3247
3248/*----------------------------------------------------------------------------
3249 * set_fd_d --
3250 *
3251 *	Write (double precision) the FT register (bits 10-6).
3252 *	This is an internal routine used by MachEmulateFP only.
3253 *
3254 * Arguments:
3255 *	a0	contains the FP instruction
3256 *	t0	contains the sign
3257 *	t1	contains the (biased) exponent
3258 *	t2	contains the fraction
3259 *	t3	contains the remaining fraction
3260 *
3261 *----------------------------------------------------------------------------
3262 */
3263LEAF(set_fd_d)
3264	sll	t0, t0, 31			# set sign
3265	sll	t1, t1, 20			# set exponent
3266	or	t0, t0, t1
3267	or	t0, t0, t2			# set fraction
3268	srl	a3, a0, 7 - 2			# get FD field (even regs only)
3269	and	a3, a3, 0xF << 2		# mask FD field
3270	lw	a3, set_fd_d_tbl(a3)		# switch on register number
3271	j	a3
3272
3273	.rdata
3274set_fd_d_tbl:
3275	.word	set_fd_d_f0
3276	.word	set_fd_d_f2
3277	.word	set_fd_d_f4
3278	.word	set_fd_d_f6
3279	.word	set_fd_d_f8
3280	.word	set_fd_d_f10
3281	.word	set_fd_d_f12
3282	.word	set_fd_d_f14
3283	.word	set_fd_d_f16
3284	.word	set_fd_d_f18
3285	.word	set_fd_d_f20
3286	.word	set_fd_d_f22
3287	.word	set_fd_d_f24
3288	.word	set_fd_d_f26
3289	.word	set_fd_d_f28
3290	.word	set_fd_d_f30
3291	.text
3292
3293set_fd_d_f0:
3294	mtc1	t3, $f0
3295	mtc1	t0, $f1
3296	j	ra
3297set_fd_d_f2:
3298	mtc1	t3, $f2
3299	mtc1	t0, $f3
3300	j	ra
3301set_fd_d_f4:
3302	mtc1	t3, $f4
3303	mtc1	t0, $f5
3304	j	ra
3305set_fd_d_f6:
3306	mtc1	t3, $f6
3307	mtc1	t0, $f7
3308	j	ra
3309set_fd_d_f8:
3310	mtc1	t3, $f8
3311	mtc1	t0, $f9
3312	j	ra
3313set_fd_d_f10:
3314	mtc1	t3, $f10
3315	mtc1	t0, $f11
3316	j	ra
3317set_fd_d_f12:
3318	mtc1	t3, $f12
3319	mtc1	t0, $f13
3320	j	ra
3321set_fd_d_f14:
3322	mtc1	t3, $f14
3323	mtc1	t0, $f15
3324	j	ra
3325set_fd_d_f16:
3326	mtc1	t3, $f16
3327	mtc1	t0, $f17
3328	j	ra
3329set_fd_d_f18:
3330	mtc1	t3, $f18
3331	mtc1	t0, $f19
3332	j	ra
3333set_fd_d_f20:
3334	mtc1	t3, $f20
3335	mtc1	t0, $f21
3336	j	ra
3337set_fd_d_f22:
3338	mtc1	t3, $f22
3339	mtc1	t0, $f23
3340	j	ra
3341set_fd_d_f24:
3342	mtc1	t3, $f24
3343	mtc1	t0, $f25
3344	j	ra
3345set_fd_d_f26:
3346	mtc1	t3, $f26
3347	mtc1	t0, $f27
3348	j	ra
3349set_fd_d_f28:
3350	mtc1	t3, $f28
3351	mtc1	t0, $f29
3352	j	ra
3353set_fd_d_f30:
3354	mtc1	t3, $f30
3355	mtc1	t0, $f31
3356	j	ra
3357END(set_fd_d)
3358
3359/*----------------------------------------------------------------------------
3360 * renorm_fs_s --
3361 *
3362 * Results:
3363 *	t1	unbiased exponent
3364 *	t2	normalized fraction
3365 *
3366 *----------------------------------------------------------------------------
3367 */
3368LEAF(renorm_fs_s)
3369/*
3370 * Find out how many leading zero bits are in t2 and put in t9.
3371 */
3372	move	v0, t2
3373	move	t9, zero
3374	srl	v1, v0, 16
3375	bne	v1, zero, 1f
3376	addu	t9, 16
3377	sll	v0, 16
33781:
3379	srl	v1, v0, 24
3380	bne	v1, zero, 1f
3381	addu	t9, 8
3382	sll	v0, 8
33831:
3384	srl	v1, v0, 28
3385	bne	v1, zero, 1f
3386	addu	t9, 4
3387	sll	v0, 4
33881:
3389	srl	v1, v0, 30
3390	bne	v1, zero, 1f
3391	addu	t9, 2
3392	sll	v0, 2
33931:
3394	srl	v1, v0, 31
3395	bne	v1, zero, 1f
3396	addu	t9, 1
3397/*
3398 * Now shift t2 the correct number of bits.
3399 */
34001:
3401	subu	t9, t9, SLEAD_ZEROS	# dont count normal leading zeros
3402	li	t1, SEXP_MIN
3403	subu	t1, t1, t9		# adjust exponent
3404	sll	t2, t2, t9
3405	j	ra
3406END(renorm_fs_s)
3407
3408/*----------------------------------------------------------------------------
3409 * renorm_fs_d --
3410 *
3411 * Results:
3412 *	t1	unbiased exponent
3413 *	t2,t3	normalized fraction
3414 *
3415 *----------------------------------------------------------------------------
3416 */
3417LEAF(renorm_fs_d)
3418/*
3419 * Find out how many leading zero bits are in t2,t3 and put in t9.
3420 */
3421	move	v0, t2
3422	move	t9, zero
3423	bne	t2, zero, 1f
3424	move	v0, t3
3425	addu	t9, 32
34261:
3427	srl	v1, v0, 16
3428	bne	v1, zero, 1f
3429	addu	t9, 16
3430	sll	v0, 16
34311:
3432	srl	v1, v0, 24
3433	bne	v1, zero, 1f
3434	addu	t9, 8
3435	sll	v0, 8
34361:
3437	srl	v1, v0, 28
3438	bne	v1, zero, 1f
3439	addu	t9, 4
3440	sll	v0, 4
34411:
3442	srl	v1, v0, 30
3443	bne	v1, zero, 1f
3444	addu	t9, 2
3445	sll	v0, 2
34461:
3447	srl	v1, v0, 31
3448	bne	v1, zero, 1f
3449	addu	t9, 1
3450/*
3451 * Now shift t2,t3 the correct number of bits.
3452 */
34531:
3454	subu	t9, t9, DLEAD_ZEROS	# dont count normal leading zeros
3455	li	t1, DEXP_MIN
3456	subu	t1, t1, t9		# adjust exponent
3457	li	v0, 32
3458	blt	t9, v0, 1f
3459	subu	t9, t9, v0		# shift fraction left >= 32 bits
3460	sll	t2, t3, t9
3461	move	t3, zero
3462	j	ra
34631:
3464	subu	v0, v0, t9		# shift fraction left < 32 bits
3465	sll	t2, t2, t9
3466	srl	v1, t3, v0
3467	or	t2, t2, v1
3468	sll	t3, t3, t9
3469	j	ra
3470END(renorm_fs_d)
3471
3472/*----------------------------------------------------------------------------
3473 * renorm_ft_s --
3474 *
3475 * Results:
3476 *	t5	unbiased exponent
3477 *	t6	normalized fraction
3478 *
3479 *----------------------------------------------------------------------------
3480 */
3481LEAF(renorm_ft_s)
3482/*
3483 * Find out how many leading zero bits are in t6 and put in t9.
3484 */
3485	move	v0, t6
3486	move	t9, zero
3487	srl	v1, v0, 16
3488	bne	v1, zero, 1f
3489	addu	t9, 16
3490	sll	v0, 16
34911:
3492	srl	v1, v0, 24
3493	bne	v1, zero, 1f
3494	addu	t9, 8
3495	sll	v0, 8
34961:
3497	srl	v1, v0, 28
3498	bne	v1, zero, 1f
3499	addu	t9, 4
3500	sll	v0, 4
35011:
3502	srl	v1, v0, 30
3503	bne	v1, zero, 1f
3504	addu	t9, 2
3505	sll	v0, 2
35061:
3507	srl	v1, v0, 31
3508	bne	v1, zero, 1f
3509	addu	t9, 1
3510/*
3511 * Now shift t6 the correct number of bits.
3512 */
35131:
3514	subu	t9, t9, SLEAD_ZEROS	# dont count normal leading zeros
3515	li	t5, SEXP_MIN
3516	subu	t5, t5, t9		# adjust exponent
3517	sll	t6, t6, t9
3518	j	ra
3519END(renorm_ft_s)
3520
3521/*----------------------------------------------------------------------------
3522 * renorm_ft_d --
3523 *
3524 * Results:
3525 *	t5	unbiased exponent
3526 *	t6,t7	normalized fraction
3527 *
3528 *----------------------------------------------------------------------------
3529 */
3530LEAF(renorm_ft_d)
3531/*
3532 * Find out how many leading zero bits are in t6,t7 and put in t9.
3533 */
3534	move	v0, t6
3535	move	t9, zero
3536	bne	t6, zero, 1f
3537	move	v0, t7
3538	addu	t9, 32
35391:
3540	srl	v1, v0, 16
3541	bne	v1, zero, 1f
3542	addu	t9, 16
3543	sll	v0, 16
35441:
3545	srl	v1, v0, 24
3546	bne	v1, zero, 1f
3547	addu	t9, 8
3548	sll	v0, 8
35491:
3550	srl	v1, v0, 28
3551	bne	v1, zero, 1f
3552	addu	t9, 4
3553	sll	v0, 4
35541:
3555	srl	v1, v0, 30
3556	bne	v1, zero, 1f
3557	addu	t9, 2
3558	sll	v0, 2
35591:
3560	srl	v1, v0, 31
3561	bne	v1, zero, 1f
3562	addu	t9, 1
3563/*
3564 * Now shift t6,t7 the correct number of bits.
3565 */
35661:
3567	subu	t9, t9, DLEAD_ZEROS	# dont count normal leading zeros
3568	li	t5, DEXP_MIN
3569	subu	t5, t5, t9		# adjust exponent
3570	li	v0, 32
3571	blt	t9, v0, 1f
3572	subu	t9, t9, v0		# shift fraction left >= 32 bits
3573	sll	t6, t7, t9
3574	move	t7, zero
3575	j	ra
35761:
3577	subu	v0, v0, t9		# shift fraction left < 32 bits
3578	sll	t6, t6, t9
3579	srl	v1, t7, v0
3580	or	t6, t6, v1
3581	sll	t7, t7, t9
3582	j	ra
3583END(renorm_ft_d)
3584