xref: /original-bsd/sys/pmax/pmax/fp.s (revision 942cfc3b)
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.3 (Berkeley) 10/11/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
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 FT's
677	move	t2, zero			# FS's fraction shifted is zero
678	b	4f
6791:
680	move	t6, zero			# FT's 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 FT's frac
686	move	t1, t5				# FT > FS, result exp is FT's
687	sll	t8, t2, t9			# save bits shifted out
688	srl	t2, t2, v1			# shift FS's fraction
689	b	4f
6903:
691	sll	t8, t6, t9			# save bits shifted out
692	srl	t6, t6, v1			# shift FT's 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 = FT's
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 FT's
802	move	t2, zero			# FS's fraction shifted is zero
803	move	t3, zero
804	b	4f
8051:
806	move	t6, zero			# FT's 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 FT's frac
812	move	t1, t5				# FT > FS, result exp is FT's
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			# don't lose any one bits
818	or	t8, t8, t9			# save sticky bit
819	srl	t3, t2, v1			# shift FS's 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 FS's 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 FT's 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 FT's 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 = FT's
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		# don't 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	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1333	li	t1, DEXP_INF			# convert to double
1334	b	2f
13351:
1336	bne	t1, zero, 2f			# is FS denormalized or zero?
1337	beq	t2, zero, result_fs_d		# is FS zero?
1338	jal	renorm_fs_s
1339	move	t8, zero
1340	b	norm_d
13412:
1342	addu	t1, t1, DEXP_BIAS - SEXP_BIAS	# bias exponent correctly
1343	sll	t3, t2, 32 - 3			# convert S fraction to D
1344	srl	t2, t2, 3
1345	b	result_fs_d
1346
1347/*
1348 * Convert integer to double.
1349 */
1350cvt_d_w:
1351	jal	get_fs_int
1352	bne	t2, zero, 1f			# check for zero
1353	move	t1, zero			# result=0
1354	move	t3, zero
1355	b	result_fs_d
1356/*
1357 * Find out how many leading zero bits are in t2 and put in t9.
1358 */
13591:
1360	move	v0, t2
1361	move	t9, zero
1362	srl	v1, v0, 16
1363	bne	v1, zero, 1f
1364	addu	t9, 16
1365	sll	v0, 16
13661:
1367	srl	v1, v0, 24
1368	bne	v1, zero, 1f
1369	addu	t9, 8
1370	sll	v0, 8
13711:
1372	srl	v1, v0, 28
1373	bne	v1, zero, 1f
1374	addu	t9, 4
1375	sll	v0, 4
13761:
1377	srl	v1, v0, 30
1378	bne	v1, zero, 1f
1379	addu	t9, 2
1380	sll	v0, 2
13811:
1382	srl	v1, v0, 31
1383	bne	v1, zero, 1f
1384	addu	t9, 1
1385/*
1386 * Now shift t2 the correct number of bits.
1387 */
13881:
1389	subu	t9, t9, DLEAD_ZEROS		# don't count leading zeros
1390	li	t1, DEXP_BIAS + 23		# init exponent
1391	subu	t1, t1, t9			# compute exponent
1392	beq	t9, zero, 1f
1393	li	v0, 32
1394	blt	t9, zero, 2f			# if shift < 0, shift right
1395	subu	v0, v0, t9
1396	sll	t2, t2, t9			# shift left
13971:
1398	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1399	b	result_fs_d
14002:
1401	negu	t9				# shift right by t9
1402	subu	v0, v0, t9
1403	sll	t3, t2, v0
1404	srl	t2, t2, t9
1405	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1406	b	result_fs_d
1407
1408/*
1409 * Convert single to integer.
1410 */
1411cvt_w_s:
1412	jal	get_fs_s
1413	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1414	bne	t2, zero, invalid_w		# invalid conversion
14151:
1416	bne	t1, zero, 1f			# is FS zero?
1417	beq	t2, zero, result_fs_w		# result is zero
1418	move	t2, zero			# result is an inexact zero
1419	b	inexact_w
14201:
1421	subu	t1, t1, SEXP_BIAS		# unbias exponent
1422	or	t2, t2, SIMPL_ONE		# add implied one bit
1423	sll	t3, t2, 32 - 3			# convert S fraction to D
1424	srl	t2, t2, 3
1425	b	cvt_w
1426
1427/*
1428 * Convert double to integer.
1429 */
1430cvt_w_d:
1431	jal	get_fs_d
1432	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1433	bne	t2, zero, invalid_w		# invalid conversion
1434	bne	t3, zero, invalid_w		# invalid conversion
14351:
1436	bne	t1, zero, 2f			# is FS zero?
1437	bne	t2, zero, 1f
1438	beq	t3, zero, result_fs_w		# result is zero
14391:
1440	move	t2, zero			# result is an inexact zero
1441	b	inexact_w
14422:
1443	subu	t1, t1, DEXP_BIAS		# unbias exponent
1444	or	t2, t2, DIMPL_ONE		# add implied one bit
1445cvt_w:
1446	blt	t1, WEXP_MIN, underflow_w	# is exponent too small?
1447	li	v0, WEXP_MAX+1
1448	bgt	t1, v0, overflow_w		# is exponent too large?
1449	bne	t1, v0, 1f			# special check for INT_MIN
1450	beq	t0, zero, overflow_w		# if positive, overflow
1451	bne	t2, DIMPL_ONE, overflow_w
1452	bne	t3, zero, overflow_w
1453	li	t2, INT_MIN			# result is INT_MIN
1454	b	result_fs_w
14551:
1456	subu	v0, t1, 20			# compute amount to shift
1457	beq	v0, zero, 2f			# is shift needed?
1458	li	v1, 32
1459	blt	v0, zero, 1f			# if shift < 0, shift right
1460	subu	v1, v1, v0			# shift left
1461	sll	t2, t2, v0
1462	srl	t9, t3, v1			# save bits shifted out of t3
1463	or	t2, t2, t9			# and put into t2
1464	sll	t3, t3, v0			# shift FS's fraction
1465	b	2f
14661:
1467	negu	v0				# shift right by v0
1468	subu	v1, v1, v0
1469	sll	t8, t3, v1			# save bits shifted out
1470	sltu	t8, zero, t8			# don't lose any one's
1471	srl	t3, t3, v0			# shift FS's fraction
1472	or	t3, t3, t8
1473	sll	t9, t2, v1			# save bits shifted out of t2
1474	or	t3, t3, t9			# and put into t3
1475	srl	t2, t2, v0
1476/*
1477 * round result (t0 is sign, t2 is integer part, t3 is fractional part).
1478 */
14792:
1480	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1481	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1482	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
1483	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1484	beq	t0, zero, 5f			# if sign is positive, truncate
1485	b	2f
14861:
1487	bne	t0, zero, 5f			# if sign is negative, truncate
14882:
1489	beq	t3, zero, 5f			# if no fraction bits, continue
1490	addu	t2, t2, 1			# add rounding bit
1491	blt	t2, zero, overflow_w		# overflow?
1492	b	5f
14933:
1494	li	v0, GUARDBIT			# load guard bit for rounding
1495	addu	v0, v0, t3			# add remainder
1496	sltu	v1, v0, t3			# compute carry out
1497	beq	v1, zero, 4f			# if no carry, continue
1498	addu	t2, t2, 1			# add carry to result
1499	blt	t2, zero, overflow_w		# overflow?
15004:
1501	bne	v0, zero, 5f			# if rounded remainder is zero
1502	and	t2, t2, ~1			#  clear LSB (round to nearest)
15035:
1504	beq	t0, zero, 1f			# result positive?
1505	negu	t2				# convert to negative integer
15061:
1507	beq	t3, zero, result_fs_w		# is result exact?
1508/*
1509 * Handle inexact exception.
1510 */
1511inexact_w:
1512	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
1513	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1514	bne	v0, zero, fpe_trap
1515	ctc1	a1, MACH_FPC_CSR		# save exceptions
1516	b	result_fs_w
1517
1518/*
1519 * Conversions to integer which overflow will trap (if enabled),
1520 * or generate an inexact trap (if enabled),
1521 * or generate an invalid exception.
1522 */
1523overflow_w:
1524	or	a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW
1525	and	v0, a1, MACH_FPC_ENABLE_OVERFLOW
1526	bne	v0, zero, fpe_trap
1527	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1528	bne	v0, zero, inexact_w		# inexact traps enabled?
1529	b	invalid_w
1530
1531/*
1532 * Conversions to integer which underflow will trap (if enabled),
1533 * or generate an inexact trap (if enabled),
1534 * or generate an invalid exception.
1535 */
1536underflow_w:
1537	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
1538	and	v0, a1, MACH_FPC_ENABLE_UNDERFLOW
1539	bne	v0, zero, fpe_trap
1540	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1541	bne	v0, zero, inexact_w		# inexact traps enabled?
1542	b	invalid_w
1543
1544/*
1545 * Compare single.
1546 */
1547cmp_s:
1548	jal	get_cmp_s
1549	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1550	bne	t2, zero, unordered		# FS is a NAN
15511:
1552	bne	t5, SEXP_INF, 2f		# is FT an infinity?
1553	bne	t6, zero, unordered		# FT is a NAN
15542:
1555	sll	t1, t1, 23			# reassemble exp & frac
1556	or	t1, t1, t2
1557	sll	t5, t5, 23			# reassemble exp & frac
1558	or	t5, t5, t6
1559	beq	t0, zero, 1f			# is FS positive?
1560	negu	t1
15611:
1562	beq	t4, zero, 1f			# is FT positive?
1563	negu	t5
15641:
1565	li	v0, COND_LESS
1566	blt	t1, t5, test_cond		# is FS < FT?
1567	li	v0, COND_EQUAL
1568	beq	t1, t5, test_cond		# is FS == FT?
1569	move	v0, zero			# FS > FT
1570	b	test_cond
1571
1572/*
1573 * Compare double.
1574 */
1575cmp_d:
1576	jal	get_cmp_d
1577	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1578	bne	t2, zero, unordered
1579	bne	t3, zero, unordered		# FS is a NAN
15801:
1581	bne	t5, DEXP_INF, 2f		# is FT an infinity?
1582	bne	t6, zero, unordered
1583	bne	t7, zero, unordered		# FT is a NAN
15842:
1585	sll	t1, t1, 20			# reassemble exp & frac
1586	or	t1, t1, t2
1587	sll	t5, t5, 20			# reassemble exp & frac
1588	or	t5, t5, t6
1589	beq	t0, zero, 1f			# is FS positive?
1590	not	t3				# negate t1,t3
1591	not	t1
1592	addu	t3, t3, 1
1593	seq	v0, t3, zero			# compute carry
1594	addu	t1, t1, v0
15951:
1596	beq	t4, zero, 1f			# is FT positive?
1597	not	t7				# negate t5,t7
1598	not	t5
1599	addu	t7, t7, 1
1600	seq	v0, t7, zero			# compute carry
1601	addu	t5, t5, v0
16021:
1603	li	v0, COND_LESS
1604	blt	t1, t5, test_cond		# is FS(MSW) < FT(MSW)?
1605	move	v0, zero
1606	bne	t1, t5, test_cond		# is FS(MSW) > FT(MSW)?
1607	li	v0, COND_LESS
1608	bltu	t3, t7, test_cond		# is FS(LSW) < FT(LSW)?
1609	li	v0, COND_EQUAL
1610	beq	t3, t7, test_cond		# is FS(LSW) == FT(LSW)?
1611	move	v0, zero			# FS > FT
1612test_cond:
1613	and	v0, v0, a0			# condition match instruction?
1614set_cond:
1615	bne	v0, zero, 1f
1616	and	a1, a1, ~MACH_FPC_COND_BIT	# clear condition bit
1617	b	2f
16181:
1619	or	a1, a1, MACH_FPC_COND_BIT	# set condition bit
16202:
1621	ctc1	a1, MACH_FPC_CSR		# save condition bit
1622	b	done
1623
1624unordered:
1625	and	v0, a0, COND_UNORDERED		# this cmp match unordered?
1626	bne	v0, zero, 1f
1627	and	a1, a1, ~MACH_FPC_COND_BIT	# clear condition bit
1628	b	2f
16291:
1630	or	a1, a1, MACH_FPC_COND_BIT	# set condition bit
16312:
1632	and	v0, a0, COND_SIGNAL
1633	beq	v0, zero, 1f			# is this a signaling cmp?
1634	or	a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID
1635	and	v0, a1, MACH_FPC_ENABLE_INVALID
1636	bne	v0, zero, fpe_trap
16371:
1638	ctc1	a1, MACH_FPC_CSR		# save condition bit
1639	b	done
1640
1641/*
1642 * Determine the amount to shift the fraction in order to restore the
1643 * normalized position. After that, round and handle exceptions.
1644 */
1645norm_s:
1646	move	v0, t2
1647	move	t9, zero			# t9 = num of leading zeros
1648	bne	t2, zero, 1f
1649	move	v0, t8
1650	addu	t9, 32
16511:
1652	srl	v1, v0, 16
1653	bne	v1, zero, 1f
1654	addu	t9, 16
1655	sll	v0, 16
16561:
1657	srl	v1, v0, 24
1658	bne	v1, zero, 1f
1659	addu	t9, 8
1660	sll	v0, 8
16611:
1662	srl	v1, v0, 28
1663	bne	v1, zero, 1f
1664	addu	t9, 4
1665	sll	v0, 4
16661:
1667	srl	v1, v0, 30
1668	bne	v1, zero, 1f
1669	addu	t9, 2
1670	sll	v0, 2
16711:
1672	srl	v1, v0, 31
1673	bne	v1, zero, 1f
1674	addu	t9, 1
1675/*
1676 * Now shift t2,t8 the correct number of bits.
1677 */
16781:
1679	subu	t9, t9, SLEAD_ZEROS		# don't count leading zeros
1680	subu	t1, t1, t9			# adjust the exponent
1681	beq	t9, zero, norm_noshift_s
1682	li	v1, 32
1683	blt	t9, zero, 1f			# if shift < 0, shift right
1684	subu	v1, v1, t9
1685	sll	t2, t2, t9			# shift t2,t8 left
1686	srl	v0, t8, v1			# save bits shifted out
1687	or	t2, t2, v0
1688	sll	t8, t8, t9
1689	b	norm_noshift_s
16901:
1691	negu	t9				# shift t2,t8 right by t9
1692	subu	v1, v1, t9
1693	sll	v0, t8, v1			# save bits shifted out
1694	sltu	v0, zero, v0			# be sure to save any one bits
1695	srl	t8, t8, t9
1696	or	t8, t8, v0
1697	sll	v0, t2, v1			# save bits shifted out
1698	or	t8, t8, v0
1699	srl	t2, t2, t9
1700norm_noshift_s:
1701	move	t5, t1				# save unrounded exponent
1702	move	t6, t2				# save unrounded fraction
1703	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1704	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1705	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
1706	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1707	beq	t0, zero, 5f			# if sign is positive, truncate
1708	b	2f
17091:
1710	bne	t0, zero, 5f			# if sign is negative, truncate
17112:
1712	beq	t8, zero, 5f			# if exact, continue
1713	addu	t2, t2, 1			# add rounding bit
1714	bne	t2, SIMPL_ONE<<1, 5f		# need to adjust exponent?
1715	addu	t1, t1, 1			# adjust exponent
1716	srl	t2, t2, 1			# renormalize fraction
1717	b	5f
17183:
1719	li	v0, GUARDBIT			# load guard bit for rounding
1720	addu	v0, v0, t8			# add remainder
1721	sltu	v1, v0, t8			# compute carry out
1722	beq	v1, zero, 4f			# if no carry, continue
1723	addu	t2, t2, 1			# add carry to result
1724	bne	t2, SIMPL_ONE<<1, 4f		# need to adjust exponent?
1725	addu	t1, t1, 1			# adjust exponent
1726	srl	t2, t2, 1			# renormalize fraction
17274:
1728	bne	v0, zero, 5f			# if rounded remainder is zero
1729	and	t2, t2, ~1			#  clear LSB (round to nearest)
17305:
1731	bgt	t1, SEXP_MAX, overflow_s	# overflow?
1732	blt	t1, SEXP_MIN, underflow_s	# underflow?
1733	bne	t8, zero, inexact_s		# is result inexact?
1734	addu	t1, t1, SEXP_BIAS		# bias exponent
1735	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1736	b	result_fs_s
1737
1738/*
1739 * Handle inexact exception.
1740 */
1741inexact_s:
1742	addu	t1, t1, SEXP_BIAS		# bias exponent
1743	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1744inexact_nobias_s:
1745	jal	set_fd_s			# save result
1746	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
1747	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1748	bne	v0, zero, fpe_trap
1749	ctc1	a1, MACH_FPC_CSR		# save exceptions
1750	b	done
1751
1752/*
1753 * Overflow will trap (if enabled),
1754 * or generate an inexact trap (if enabled),
1755 * or generate an infinity.
1756 */
1757overflow_s:
1758	or	a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW
1759	and	v0, a1, MACH_FPC_ENABLE_OVERFLOW
1760	beq	v0, zero, 1f
1761	subu	t1, t1, 192			# bias exponent
1762	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1763	jal	set_fd_s			# save result
1764	b	fpe_trap
17651:
1766	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1767	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1768	beq	v0, MACH_FPC_ROUND_RZ, 1f	# round to zero (truncate)
1769	beq	v0, MACH_FPC_ROUND_RP, 2f	# round to +infinity
1770	bne	t0, zero, 3f
17711:
1772	li	t1, SEXP_MAX			# result is max finite
1773	li	t2, 0x007fffff
1774	b	inexact_s
17752:
1776	bne	t0, zero, 1b
17773:
1778	li	t1, SEXP_MAX + 1		# result is infinity
1779	move	t2, zero
1780	b	inexact_s
1781
1782/*
1783 * In this implementation, "tininess" is detected "after rounding" and
1784 * "loss of accuracy" is detected as "an inexact result".
1785 */
1786underflow_s:
1787	and	v0, a1, MACH_FPC_ENABLE_UNDERFLOW
1788	beq	v0, zero, 1f
1789/*
1790 * Underflow is enabled so compute the result and trap.
1791 */
1792	addu	t1, t1, 192			# bias exponent
1793	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1794	jal	set_fd_s			# save result
1795	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
1796	b	fpe_trap
1797/*
1798 * Underflow is not enabled so compute the result,
1799 * signal inexact result (if it is) and trap (if enabled).
1800 */
18011:
1802	move	t1, t5				# get unrounded exponent
1803	move	t2, t6				# get unrounded fraction
1804	li	t9, SEXP_MIN			# compute shift amount
1805	subu	t9, t9, t1			# shift t2,t8 right by t9
1806	blt	t9, SFRAC_BITS+2, 3f		# shift all the bits out?
1807	move	t1, zero			# result is inexact zero
1808	move	t2, zero
1809	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
1810/*
1811 * Now round the zero result.
1812 * Only need to worry about rounding to +- infinity when the sign matches.
1813 */
1814	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1815	beq	v0, MACH_FPC_ROUND_RN, inexact_nobias_s	# round to nearest
1816	beq	v0, MACH_FPC_ROUND_RZ, inexact_nobias_s	# round to zero
1817	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1818	beq	t0, zero, inexact_nobias_s	# if sign is positive, truncate
1819	b	2f
18201:
1821	bne	t0, zero, inexact_nobias_s	# if sign is negative, truncate
18222:
1823	addu	t2, t2, 1			# add rounding bit
1824	b	inexact_nobias_s
18253:
1826	li	v1, 32
1827	subu	v1, v1, t9
1828	sltu	v0, zero, t8			# be sure to save any one bits
1829	sll	t8, t2, v1			# save bits shifted out
1830	or	t8, t8, v0			# include sticky bits
1831	srl	t2, t2, t9
1832/*
1833 * Now round the denormalized result.
1834 */
1835	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1836	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1837	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
1838	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1839	beq	t0, zero, 5f			# if sign is positive, truncate
1840	b	2f
18411:
1842	bne	t0, zero, 5f			# if sign is negative, truncate
18432:
1844	beq	t8, zero, 5f			# if exact, continue
1845	addu	t2, t2, 1			# add rounding bit
1846	b	5f
18473:
1848	li	v0, GUARDBIT			# load guard bit for rounding
1849	addu	v0, v0, t8			# add remainder
1850	sltu	v1, v0, t8			# compute carry out
1851	beq	v1, zero, 4f			# if no carry, continue
1852	addu	t2, t2, 1			# add carry to result
18534:
1854	bne	v0, zero, 5f			# if rounded remainder is zero
1855	and	t2, t2, ~1			#  clear LSB (round to nearest)
18565:
1857	move	t1, zero			# denorm or zero exponent
1858	jal	set_fd_s			# save result
1859	beq	t8, zero, done			# check for exact result
1860	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
1861	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
1862	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1863	bne	v0, zero, fpe_trap
1864	ctc1	a1, MACH_FPC_CSR		# save exceptions
1865	b	done
1866
1867/*
1868 * Determine the amount to shift the fraction in order to restore the
1869 * normalized position. After that, round and handle exceptions.
1870 */
1871norm_d:
1872	move	v0, t2
1873	move	t9, zero			# t9 = num of leading zeros
1874	bne	t2, zero, 1f
1875	move	v0, t3
1876	addu	t9, 32
1877	bne	t3, zero, 1f
1878	move	v0, t8
1879	addu	t9, 32
18801:
1881	srl	v1, v0, 16
1882	bne	v1, zero, 1f
1883	addu	t9, 16
1884	sll	v0, 16
18851:
1886	srl	v1, v0, 24
1887	bne	v1, zero, 1f
1888	addu	t9, 8
1889	sll	v0, 8
18901:
1891	srl	v1, v0, 28
1892	bne	v1, zero, 1f
1893	addu	t9, 4
1894	sll	v0, 4
18951:
1896	srl	v1, v0, 30
1897	bne	v1, zero, 1f
1898	addu	t9, 2
1899	sll	v0, 2
19001:
1901	srl	v1, v0, 31
1902	bne	v1, zero, 1f
1903	addu	t9, 1
1904/*
1905 * Now shift t2,t3,t8 the correct number of bits.
1906 */
19071:
1908	subu	t9, t9, DLEAD_ZEROS		# don't count leading zeros
1909	subu	t1, t1, t9			# adjust the exponent
1910	beq	t9, zero, norm_noshift_d
1911	li	v1, 32
1912	blt	t9, zero, 2f			# if shift < 0, shift right
1913	blt	t9, v1, 1f			# shift by < 32?
1914	subu	t9, t9, v1			# shift by >= 32
1915	subu	v1, v1, t9
1916	sll	t2, t3, t9			# shift left by t9
1917	srl	v0, t8, v1			# save bits shifted out
1918	or	t2, t2, v0
1919	sll	t3, t8, t9
1920	move	t8, zero
1921	b	norm_noshift_d
19221:
1923	subu	v1, v1, t9
1924	sll	t2, t2, t9			# shift left by t9
1925	srl	v0, t3, v1			# save bits shifted out
1926	or	t2, t2, v0
1927	sll	t3, t3, t9
1928	srl	v0, t8, v1			# save bits shifted out
1929	or	t3, t3, v0
1930	sll	t8, t8, t9
1931	b	norm_noshift_d
19322:
1933	negu	t9				# shift right by t9
1934	subu	v1, v1, t9			#  (known to be < 32 bits)
1935	sll	v0, t8, v1			# save bits shifted out
1936	sltu	v0, zero, v0			# be sure to save any one bits
1937	srl	t8, t8, t9
1938	or	t8, t8, v0
1939	sll	v0, t3, v1			# save bits shifted out
1940	or	t8, t8, v0
1941	srl	t3, t3, t9
1942	sll	v0, t2, v1			# save bits shifted out
1943	or	t3, t3, v0
1944	srl	t2, t2, t9
1945norm_noshift_d:
1946	move	t5, t1				# save unrounded exponent
1947	move	t6, t2				# save unrounded fraction (MS)
1948	move	t7, t3				# save unrounded fraction (LS)
1949	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1950	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1951	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
1952	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1953	beq	t0, zero, 5f			# if sign is positive, truncate
1954	b	2f
19551:
1956	bne	t0, zero, 5f			# if sign is negative, truncate
19572:
1958	beq	t8, zero, 5f			# if exact, continue
1959	addu	t3, t3, 1			# add rounding bit
1960	bne	t3, zero, 5f			# branch if no carry
1961	addu	t2, t2, 1			# add carry
1962	bne	t2, DIMPL_ONE<<1, 5f		# need to adjust exponent?
1963	addu	t1, t1, 1			# adjust exponent
1964	srl	t2, t2, 1			# renormalize fraction
1965	b	5f
19663:
1967	li	v0, GUARDBIT			# load guard bit for rounding
1968	addu	v0, v0, t8			# add remainder
1969	sltu	v1, v0, t8			# compute carry out
1970	beq	v1, zero, 4f			# branch if no carry
1971	addu	t3, t3, 1			# add carry
1972	bne	t3, zero, 4f			# branch if no carry
1973	addu	t2, t2, 1			# add carry to result
1974	bne	t2, DIMPL_ONE<<1, 4f		# need to adjust exponent?
1975	addu	t1, t1, 1			# adjust exponent
1976	srl	t2, t2, 1			# renormalize fraction
19774:
1978	bne	v0, zero, 5f			# if rounded remainder is zero
1979	and	t3, t3, ~1			#  clear LSB (round to nearest)
19805:
1981	bgt	t1, DEXP_MAX, overflow_d	# overflow?
1982	blt	t1, DEXP_MIN, underflow_d	# underflow?
1983	bne	t8, zero, inexact_d		# is result inexact?
1984	addu	t1, t1, DEXP_BIAS		# bias exponent
1985	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1986	b	result_fs_d
1987
1988/*
1989 * Handle inexact exception.
1990 */
1991inexact_d:
1992	addu	t1, t1, DEXP_BIAS		# bias exponent
1993	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1994inexact_nobias_d:
1995	jal	set_fd_d			# save result
1996	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
1997	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1998	bne	v0, zero, fpe_trap
1999	ctc1	a1, MACH_FPC_CSR		# save exceptions
2000	b	done
2001
2002/*
2003 * Overflow will trap (if enabled),
2004 * or generate an inexact trap (if enabled),
2005 * or generate an infinity.
2006 */
2007overflow_d:
2008	or	a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW
2009	and	v0, a1, MACH_FPC_ENABLE_OVERFLOW
2010	beq	v0, zero, 1f
2011	subu	t1, t1, 1536			# bias exponent
2012	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2013	jal	set_fd_d			# save result
2014	b	fpe_trap
20151:
2016	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
2017	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
2018	beq	v0, MACH_FPC_ROUND_RZ, 1f	# round to zero (truncate)
2019	beq	v0, MACH_FPC_ROUND_RP, 2f	# round to +infinity
2020	bne	t0, zero, 3f
20211:
2022	li	t1, DEXP_MAX			# result is max finite
2023	li	t2, 0x000fffff
2024	li	t3, 0xffffffff
2025	b	inexact_d
20262:
2027	bne	t0, zero, 1b
20283:
2029	li	t1, DEXP_MAX + 1		# result is infinity
2030	move	t2, zero
2031	move	t3, zero
2032	b	inexact_d
2033
2034/*
2035 * In this implementation, "tininess" is detected "after rounding" and
2036 * "loss of accuracy" is detected as "an inexact result".
2037 */
2038underflow_d:
2039	and	v0, a1, MACH_FPC_ENABLE_UNDERFLOW
2040	beq	v0, zero, 1f
2041/*
2042 * Underflow is enabled so compute the result and trap.
2043 */
2044	addu	t1, t1, 1536			# bias exponent
2045	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2046	jal	set_fd_d			# save result
2047	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
2048	b	fpe_trap
2049/*
2050 * Underflow is not enabled so compute the result,
2051 * signal inexact result (if it is) and trap (if enabled).
2052 */
20531:
2054	move	t1, t5				# get unrounded exponent
2055	move	t2, t6				# get unrounded fraction (MS)
2056	move	t3, t7				# get unrounded fraction (LS)
2057	li	t9, DEXP_MIN			# compute shift amount
2058	subu	t9, t9, t1			# shift t2,t8 right by t9
2059	blt	t9, DFRAC_BITS+2, 3f		# shift all the bits out?
2060	move	t1, zero			# result is inexact zero
2061	move	t2, zero
2062	move	t3, zero
2063	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
2064/*
2065 * Now round the zero result.
2066 * Only need to worry about rounding to +- infinity when the sign matches.
2067 */
2068	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
2069	beq	v0, MACH_FPC_ROUND_RN, inexact_nobias_d	# round to nearest
2070	beq	v0, MACH_FPC_ROUND_RZ, inexact_nobias_d	# round to zero
2071	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
2072	beq	t0, zero, inexact_nobias_d	# if sign is positive, truncate
2073	b	2f
20741:
2075	bne	t0, zero, inexact_nobias_d	# if sign is negative, truncate
20762:
2077	addu	t3, t3, 1			# add rounding bit
2078	b	inexact_nobias_d
20793:
2080	li	v1, 32
2081	blt	t9, v1, 1f			# shift by < 32?
2082	subu	t9, t9, v1			# shift right by >= 32
2083	subu	v1, v1, t9
2084	sltu	v0, zero, t8			# be sure to save any one bits
2085	sll	t8, t2, v1			# save bits shifted out
2086	or	t8, t8, v0			# include sticky bits
2087	srl	t3, t2, t9
2088	move	t2, zero
2089	b	2f
20901:
2091	subu	v1, v1, t9			# shift right by t9
2092	sltu	v0, zero, t8			# be sure to save any one bits
2093	sll	t8, t3, v1			# save bits shifted out
2094	or	t8, t8, v0			# include sticky bits
2095	srl	t3, t3, t9
2096	sll	v0, t2, v1			# save bits shifted out
2097	or	t3, t3, v0
2098	srl	t2, t2, t9
2099/*
2100 * Now round the denormalized result.
2101 */
21022:
2103	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
2104	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
2105	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
2106	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
2107	beq	t0, zero, 5f			# if sign is positive, truncate
2108	b	2f
21091:
2110	bne	t0, zero, 5f			# if sign is negative, truncate
21112:
2112	beq	t8, zero, 5f			# if exact, continue
2113	addu	t3, t3, 1			# add rounding bit
2114	bne	t3, zero, 5f			# if no carry, continue
2115	addu	t2, t2, 1			# add carry
2116	b	5f
21173:
2118	li	v0, GUARDBIT			# load guard bit for rounding
2119	addu	v0, v0, t8			# add remainder
2120	sltu	v1, v0, t8			# compute carry out
2121	beq	v1, zero, 4f			# if no carry, continue
2122	addu	t3, t3, 1			# add rounding bit
2123	bne	t3, zero, 4f			# if no carry, continue
2124	addu	t2, t2, 1			# add carry
21254:
2126	bne	v0, zero, 5f			# if rounded remainder is zero
2127	and	t3, t3, ~1			#  clear LSB (round to nearest)
21285:
2129	move	t1, zero			# denorm or zero exponent
2130	jal	set_fd_d			# save result
2131	beq	t8, zero, done			# check for exact result
2132	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
2133	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
2134	and	v0, a1, MACH_FPC_ENABLE_INEXACT
2135	bne	v0, zero, fpe_trap
2136	ctc1	a1, MACH_FPC_CSR		# save exceptions
2137	b	done
2138
2139/*
2140 * Signal an invalid operation if the trap is enabled; otherwise,
2141 * the result is a quiet NAN.
2142 */
2143invalid_s:					# trap invalid operation
2144	or	a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID
2145	and	v0, a1, MACH_FPC_ENABLE_INVALID
2146	bne	v0, zero, fpe_trap
2147	ctc1	a1, MACH_FPC_CSR		# save exceptions
2148	move	t0, zero			# result is a quiet NAN
2149	li	t1, SEXP_INF
2150	li	t2, SQUIET_NAN
2151	jal	set_fd_s			# save result (in t0,t1,t2)
2152	b	done
2153
2154/*
2155 * Signal an invalid operation if the trap is enabled; otherwise,
2156 * the result is a quiet NAN.
2157 */
2158invalid_d:					# trap invalid operation
2159	or	a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID
2160	and	v0, a1, MACH_FPC_ENABLE_INVALID
2161	bne	v0, zero, fpe_trap
2162	ctc1	a1, MACH_FPC_CSR		# save exceptions
2163	move	t0, zero			# result is a quiet NAN
2164	li	t1, DEXP_INF
2165	li	t2, DQUIET_NAN0
2166	li	t3, DQUIET_NAN1
2167	jal	set_fd_d			# save result (in t0,t1,t2,t3)
2168	b	done
2169
2170/*
2171 * Signal an invalid operation if the trap is enabled; otherwise,
2172 * the result is INT_MAX or INT_MIN.
2173 */
2174invalid_w:					# trap invalid operation
2175	or	a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID
2176	and	v0, a1, MACH_FPC_ENABLE_INVALID
2177	bne	v0, zero, fpe_trap
2178	ctc1	a1, MACH_FPC_CSR		# save exceptions
2179	bne	t0, zero, 1f
2180	li	t2, INT_MAX			# result is INT_MAX
2181	b	result_fs_w
21821:
2183	li	t2, INT_MIN			# result is INT_MIN
2184	b	result_fs_w
2185
2186/*
2187 * Trap if the hardware should have handled this case.
2188 */
2189fpe_trap:
2190	move	a2, a1				# code = FP CSR
2191	ctc1	a1, MACH_FPC_CSR		# save exceptions
2192	break	0
2193
2194/*
2195 * Send an illegal instruction signal to the current process.
2196 */
2197ill:
2198	ctc1	a1, MACH_FPC_CSR		# save exceptions
2199	move	a2, a0				# code = FP instruction
2200	break	0
2201
2202result_ft_s:
2203	move	t0, t4				# result is FT
2204	move	t1, t5
2205	move	t2, t6
2206result_fs_s:					# result is FS
2207	jal	set_fd_s			# save result (in t0,t1,t2)
2208	b	done
2209
2210result_fs_w:
2211	jal	set_fd_word			# save result (in t2)
2212	b	done
2213
2214result_ft_d:
2215	move	t0, t4				# result is FT
2216	move	t1, t5
2217	move	t2, t6
2218	move	t3, t7
2219result_fs_d:					# result is FS
2220	jal	set_fd_d			# save result (in t0,t1,t2,t3)
2221
2222done:
2223	lw	ra, STAND_RA_OFFSET(sp)
2224	addu	sp, sp, STAND_FRAME_SIZE
2225	j	ra
2226END(MachEmulateFP)
2227
2228/*----------------------------------------------------------------------------
2229 * get_fs_int --
2230 *
2231 *	Read (integer) the FS register (bits 15-11).
2232 *	This is an internal routine used by MachEmulateFP only.
2233 *
2234 * Results:
2235 *	t0	contains the sign
2236 *	t2	contains the fraction
2237 *
2238 *----------------------------------------------------------------------------
2239 */
2240LEAF(get_fs_int)
2241	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2242	and	a3, a3, 0xF << 2		# mask FS field
2243	lw	a3, get_fs_int_tbl(a3)		# switch on register number
2244	j	a3
2245
2246	.rdata
2247get_fs_int_tbl:
2248	.word	get_fs_int_f0
2249	.word	get_fs_int_f2
2250	.word	get_fs_int_f4
2251	.word	get_fs_int_f6
2252	.word	get_fs_int_f8
2253	.word	get_fs_int_f10
2254	.word	get_fs_int_f12
2255	.word	get_fs_int_f14
2256	.word	get_fs_int_f16
2257	.word	get_fs_int_f18
2258	.word	get_fs_int_f20
2259	.word	get_fs_int_f22
2260	.word	get_fs_int_f24
2261	.word	get_fs_int_f26
2262	.word	get_fs_int_f28
2263	.word	get_fs_int_f30
2264	.text
2265
2266get_fs_int_f0:
2267	mfc1	t2, $f0
2268	b	get_fs_int_done
2269get_fs_int_f2:
2270	mfc1	t2, $f2
2271	b	get_fs_int_done
2272get_fs_int_f4:
2273	mfc1	t2, $f4
2274	b	get_fs_int_done
2275get_fs_int_f6:
2276	mfc1	t2, $f6
2277	b	get_fs_int_done
2278get_fs_int_f8:
2279	mfc1	t2, $f8
2280	b	get_fs_int_done
2281get_fs_int_f10:
2282	mfc1	t2, $f10
2283	b	get_fs_int_done
2284get_fs_int_f12:
2285	mfc1	t2, $f12
2286	b	get_fs_int_done
2287get_fs_int_f14:
2288	mfc1	t2, $f14
2289	b	get_fs_int_done
2290get_fs_int_f16:
2291	mfc1	t2, $f16
2292	b	get_fs_int_done
2293get_fs_int_f18:
2294	mfc1	t2, $f18
2295	b	get_fs_int_done
2296get_fs_int_f20:
2297	mfc1	t2, $f20
2298	b	get_fs_int_done
2299get_fs_int_f22:
2300	mfc1	t2, $f22
2301	b	get_fs_int_done
2302get_fs_int_f24:
2303	mfc1	t2, $f24
2304	b	get_fs_int_done
2305get_fs_int_f26:
2306	mfc1	t2, $f26
2307	b	get_fs_int_done
2308get_fs_int_f28:
2309	mfc1	t2, $f28
2310	b	get_fs_int_done
2311get_fs_int_f30:
2312	mfc1	t2, $f30
2313get_fs_int_done:
2314	srl	t0, t2, 31		# init the sign bit
2315	bge	t2, zero, 1f
2316	negu	t2
23171:
2318	j	ra
2319END(get_fs_int)
2320
2321/*----------------------------------------------------------------------------
2322 * get_ft_fs_s --
2323 *
2324 *	Read (single precision) the FT register (bits 20-16) and
2325 *	the FS register (bits 15-11) and break up into fields.
2326 *	This is an internal routine used by MachEmulateFP only.
2327 *
2328 * Results:
2329 *	t0	contains the FS sign
2330 *	t1	contains the FS (biased) exponent
2331 *	t2	contains the FS fraction
2332 *	t4	contains the FT sign
2333 *	t5	contains the FT (biased) exponent
2334 *	t6	contains the FT fraction
2335 *
2336 *----------------------------------------------------------------------------
2337 */
2338LEAF(get_ft_fs_s)
2339	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2340	and	a3, a3, 0xF << 2		# mask FT field
2341	lw	a3, get_ft_s_tbl(a3)		# switch on register number
2342	j	a3
2343
2344	.rdata
2345get_ft_s_tbl:
2346	.word	get_ft_s_f0
2347	.word	get_ft_s_f2
2348	.word	get_ft_s_f4
2349	.word	get_ft_s_f6
2350	.word	get_ft_s_f8
2351	.word	get_ft_s_f10
2352	.word	get_ft_s_f12
2353	.word	get_ft_s_f14
2354	.word	get_ft_s_f16
2355	.word	get_ft_s_f18
2356	.word	get_ft_s_f20
2357	.word	get_ft_s_f22
2358	.word	get_ft_s_f24
2359	.word	get_ft_s_f26
2360	.word	get_ft_s_f28
2361	.word	get_ft_s_f30
2362	.text
2363
2364get_ft_s_f0:
2365	mfc1	t4, $f0
2366	b	get_ft_s_done
2367get_ft_s_f2:
2368	mfc1	t4, $f2
2369	b	get_ft_s_done
2370get_ft_s_f4:
2371	mfc1	t4, $f4
2372	b	get_ft_s_done
2373get_ft_s_f6:
2374	mfc1	t4, $f6
2375	b	get_ft_s_done
2376get_ft_s_f8:
2377	mfc1	t4, $f8
2378	b	get_ft_s_done
2379get_ft_s_f10:
2380	mfc1	t4, $f10
2381	b	get_ft_s_done
2382get_ft_s_f12:
2383	mfc1	t4, $f12
2384	b	get_ft_s_done
2385get_ft_s_f14:
2386	mfc1	t4, $f14
2387	b	get_ft_s_done
2388get_ft_s_f16:
2389	mfc1	t4, $f16
2390	b	get_ft_s_done
2391get_ft_s_f18:
2392	mfc1	t4, $f18
2393	b	get_ft_s_done
2394get_ft_s_f20:
2395	mfc1	t4, $f20
2396	b	get_ft_s_done
2397get_ft_s_f22:
2398	mfc1	t4, $f22
2399	b	get_ft_s_done
2400get_ft_s_f24:
2401	mfc1	t4, $f24
2402	b	get_ft_s_done
2403get_ft_s_f26:
2404	mfc1	t4, $f26
2405	b	get_ft_s_done
2406get_ft_s_f28:
2407	mfc1	t4, $f28
2408	b	get_ft_s_done
2409get_ft_s_f30:
2410	mfc1	t4, $f30
2411get_ft_s_done:
2412	srl	t5, t4, 23			# get exponent
2413	and	t5, t5, 0xFF
2414	and	t6, t4, 0x7FFFFF		# get fraction
2415	srl	t4, t4, 31			# get sign
2416	bne	t5, SEXP_INF, 1f		# is it a signaling NAN?
2417	and	v0, t6, SSIGNAL_NAN
2418	bne	v0, zero, invalid_s
24191:
2420	/* fall through to get FS */
2421
2422/*----------------------------------------------------------------------------
2423 * get_fs_s --
2424 *
2425 *	Read (single precision) the FS register (bits 15-11) and
2426 *	break up into fields.
2427 *	This is an internal routine used by MachEmulateFP only.
2428 *
2429 * Results:
2430 *	t0	contains the sign
2431 *	t1	contains the (biased) exponent
2432 *	t2	contains the fraction
2433 *
2434 *----------------------------------------------------------------------------
2435 */
2436ALEAF(get_fs_s)
2437	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2438	and	a3, a3, 0xF << 2		# mask FS field
2439	lw	a3, get_fs_s_tbl(a3)		# switch on register number
2440	j	a3
2441
2442	.rdata
2443get_fs_s_tbl:
2444	.word	get_fs_s_f0
2445	.word	get_fs_s_f2
2446	.word	get_fs_s_f4
2447	.word	get_fs_s_f6
2448	.word	get_fs_s_f8
2449	.word	get_fs_s_f10
2450	.word	get_fs_s_f12
2451	.word	get_fs_s_f14
2452	.word	get_fs_s_f16
2453	.word	get_fs_s_f18
2454	.word	get_fs_s_f20
2455	.word	get_fs_s_f22
2456	.word	get_fs_s_f24
2457	.word	get_fs_s_f26
2458	.word	get_fs_s_f28
2459	.word	get_fs_s_f30
2460	.text
2461
2462get_fs_s_f0:
2463	mfc1	t0, $f0
2464	b	get_fs_s_done
2465get_fs_s_f2:
2466	mfc1	t0, $f2
2467	b	get_fs_s_done
2468get_fs_s_f4:
2469	mfc1	t0, $f4
2470	b	get_fs_s_done
2471get_fs_s_f6:
2472	mfc1	t0, $f6
2473	b	get_fs_s_done
2474get_fs_s_f8:
2475	mfc1	t0, $f8
2476	b	get_fs_s_done
2477get_fs_s_f10:
2478	mfc1	t0, $f10
2479	b	get_fs_s_done
2480get_fs_s_f12:
2481	mfc1	t0, $f12
2482	b	get_fs_s_done
2483get_fs_s_f14:
2484	mfc1	t0, $f14
2485	b	get_fs_s_done
2486get_fs_s_f16:
2487	mfc1	t0, $f16
2488	b	get_fs_s_done
2489get_fs_s_f18:
2490	mfc1	t0, $f18
2491	b	get_fs_s_done
2492get_fs_s_f20:
2493	mfc1	t0, $f20
2494	b	get_fs_s_done
2495get_fs_s_f22:
2496	mfc1	t0, $f22
2497	b	get_fs_s_done
2498get_fs_s_f24:
2499	mfc1	t0, $f24
2500	b	get_fs_s_done
2501get_fs_s_f26:
2502	mfc1	t0, $f26
2503	b	get_fs_s_done
2504get_fs_s_f28:
2505	mfc1	t0, $f28
2506	b	get_fs_s_done
2507get_fs_s_f30:
2508	mfc1	t0, $f30
2509get_fs_s_done:
2510	srl	t1, t0, 23			# get exponent
2511	and	t1, t1, 0xFF
2512	and	t2, t0, 0x7FFFFF		# get fraction
2513	srl	t0, t0, 31			# get sign
2514	bne	t1, SEXP_INF, 1f		# is it a signaling NAN?
2515	and	v0, t2, SSIGNAL_NAN
2516	bne	v0, zero, invalid_s
25171:
2518	j	ra
2519END(get_ft_fs_s)
2520
2521/*----------------------------------------------------------------------------
2522 * get_ft_fs_d --
2523 *
2524 *	Read (double precision) the FT register (bits 20-16) and
2525 *	the FS register (bits 15-11) and break up into fields.
2526 *	This is an internal routine used by MachEmulateFP only.
2527 *
2528 * Results:
2529 *	t0	contains the FS sign
2530 *	t1	contains the FS (biased) exponent
2531 *	t2	contains the FS fraction
2532 *	t3	contains the FS remaining fraction
2533 *	t4	contains the FT sign
2534 *	t5	contains the FT (biased) exponent
2535 *	t6	contains the FT fraction
2536 *	t7	contains the FT remaining fraction
2537 *
2538 *----------------------------------------------------------------------------
2539 */
2540LEAF(get_ft_fs_d)
2541	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2542	and	a3, a3, 0xF << 2		# mask FT field
2543	lw	a3, get_ft_d_tbl(a3)		# switch on register number
2544	j	a3
2545
2546	.rdata
2547get_ft_d_tbl:
2548	.word	get_ft_d_f0
2549	.word	get_ft_d_f2
2550	.word	get_ft_d_f4
2551	.word	get_ft_d_f6
2552	.word	get_ft_d_f8
2553	.word	get_ft_d_f10
2554	.word	get_ft_d_f12
2555	.word	get_ft_d_f14
2556	.word	get_ft_d_f16
2557	.word	get_ft_d_f18
2558	.word	get_ft_d_f20
2559	.word	get_ft_d_f22
2560	.word	get_ft_d_f24
2561	.word	get_ft_d_f26
2562	.word	get_ft_d_f28
2563	.word	get_ft_d_f30
2564	.text
2565
2566get_ft_d_f0:
2567	mfc1	t7, $f0
2568	mfc1	t4, $f1
2569	b	get_ft_d_done
2570get_ft_d_f2:
2571	mfc1	t7, $f2
2572	mfc1	t4, $f3
2573	b	get_ft_d_done
2574get_ft_d_f4:
2575	mfc1	t7, $f4
2576	mfc1	t4, $f5
2577	b	get_ft_d_done
2578get_ft_d_f6:
2579	mfc1	t7, $f6
2580	mfc1	t4, $f7
2581	b	get_ft_d_done
2582get_ft_d_f8:
2583	mfc1	t7, $f8
2584	mfc1	t4, $f9
2585	b	get_ft_d_done
2586get_ft_d_f10:
2587	mfc1	t7, $f10
2588	mfc1	t4, $f11
2589	b	get_ft_d_done
2590get_ft_d_f12:
2591	mfc1	t7, $f12
2592	mfc1	t4, $f13
2593	b	get_ft_d_done
2594get_ft_d_f14:
2595	mfc1	t7, $f14
2596	mfc1	t4, $f15
2597	b	get_ft_d_done
2598get_ft_d_f16:
2599	mfc1	t7, $f16
2600	mfc1	t4, $f17
2601	b	get_ft_d_done
2602get_ft_d_f18:
2603	mfc1	t7, $f18
2604	mfc1	t4, $f19
2605	b	get_ft_d_done
2606get_ft_d_f20:
2607	mfc1	t7, $f20
2608	mfc1	t4, $f21
2609	b	get_ft_d_done
2610get_ft_d_f22:
2611	mfc1	t7, $f22
2612	mfc1	t4, $f23
2613	b	get_ft_d_done
2614get_ft_d_f24:
2615	mfc1	t7, $f24
2616	mfc1	t4, $f25
2617	b	get_ft_d_done
2618get_ft_d_f26:
2619	mfc1	t7, $f26
2620	mfc1	t4, $f27
2621	b	get_ft_d_done
2622get_ft_d_f28:
2623	mfc1	t7, $f28
2624	mfc1	t4, $f29
2625	b	get_ft_d_done
2626get_ft_d_f30:
2627	mfc1	t7, $f30
2628	mfc1	t4, $f31
2629get_ft_d_done:
2630	srl	t5, t4, 20			# get exponent
2631	and	t5, t5, 0x7FF
2632	and	t6, t4, 0xFFFFF			# get fraction
2633	srl	t4, t4, 31			# get sign
2634	bne	t5, DEXP_INF, 1f		# is it a signaling NAN?
2635	and	v0, t6, DSIGNAL_NAN
2636	bne	v0, zero, invalid_d
26371:
2638	/* fall through to get FS */
2639
2640/*----------------------------------------------------------------------------
2641 * get_fs_d --
2642 *
2643 *	Read (double precision) the FS register (bits 15-11) and
2644 *	break up into fields.
2645 *	This is an internal routine used by MachEmulateFP only.
2646 *
2647 * Results:
2648 *	t0	contains the sign
2649 *	t1	contains the (biased) exponent
2650 *	t2	contains the fraction
2651 *	t3	contains the remaining fraction
2652 *
2653 *----------------------------------------------------------------------------
2654 */
2655ALEAF(get_fs_d)
2656	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2657	and	a3, a3, 0xF << 2		# mask FS field
2658	lw	a3, get_fs_d_tbl(a3)		# switch on register number
2659	j	a3
2660
2661	.rdata
2662get_fs_d_tbl:
2663	.word	get_fs_d_f0
2664	.word	get_fs_d_f2
2665	.word	get_fs_d_f4
2666	.word	get_fs_d_f6
2667	.word	get_fs_d_f8
2668	.word	get_fs_d_f10
2669	.word	get_fs_d_f12
2670	.word	get_fs_d_f14
2671	.word	get_fs_d_f16
2672	.word	get_fs_d_f18
2673	.word	get_fs_d_f20
2674	.word	get_fs_d_f22
2675	.word	get_fs_d_f24
2676	.word	get_fs_d_f26
2677	.word	get_fs_d_f28
2678	.word	get_fs_d_f30
2679	.text
2680
2681get_fs_d_f0:
2682	mfc1	t3, $f0
2683	mfc1	t0, $f1
2684	b	get_fs_d_done
2685get_fs_d_f2:
2686	mfc1	t3, $f2
2687	mfc1	t0, $f3
2688	b	get_fs_d_done
2689get_fs_d_f4:
2690	mfc1	t3, $f4
2691	mfc1	t0, $f5
2692	b	get_fs_d_done
2693get_fs_d_f6:
2694	mfc1	t3, $f6
2695	mfc1	t0, $f7
2696	b	get_fs_d_done
2697get_fs_d_f8:
2698	mfc1	t3, $f8
2699	mfc1	t0, $f9
2700	b	get_fs_d_done
2701get_fs_d_f10:
2702	mfc1	t3, $f10
2703	mfc1	t0, $f11
2704	b	get_fs_d_done
2705get_fs_d_f12:
2706	mfc1	t3, $f12
2707	mfc1	t0, $f13
2708	b	get_fs_d_done
2709get_fs_d_f14:
2710	mfc1	t3, $f14
2711	mfc1	t0, $f15
2712	b	get_fs_d_done
2713get_fs_d_f16:
2714	mfc1	t3, $f16
2715	mfc1	t0, $f17
2716	b	get_fs_d_done
2717get_fs_d_f18:
2718	mfc1	t3, $f18
2719	mfc1	t0, $f19
2720	b	get_fs_d_done
2721get_fs_d_f20:
2722	mfc1	t3, $f20
2723	mfc1	t0, $f21
2724	b	get_fs_d_done
2725get_fs_d_f22:
2726	mfc1	t3, $f22
2727	mfc1	t0, $f23
2728	b	get_fs_d_done
2729get_fs_d_f24:
2730	mfc1	t3, $f24
2731	mfc1	t0, $f25
2732	b	get_fs_d_done
2733get_fs_d_f26:
2734	mfc1	t3, $f26
2735	mfc1	t0, $f27
2736	b	get_fs_d_done
2737get_fs_d_f28:
2738	mfc1	t3, $f28
2739	mfc1	t0, $f29
2740	b	get_fs_d_done
2741get_fs_d_f30:
2742	mfc1	t3, $f30
2743	mfc1	t0, $f31
2744get_fs_d_done:
2745	srl	t1, t0, 20			# get exponent
2746	and	t1, t1, 0x7FF
2747	and	t2, t0, 0xFFFFF			# get fraction
2748	srl	t0, t0, 31			# get sign
2749	bne	t1, DEXP_INF, 1f		# is it a signaling NAN?
2750	and	v0, t2, DSIGNAL_NAN
2751	bne	v0, zero, invalid_d
27521:
2753	j	ra
2754END(get_ft_fs_d)
2755
2756/*----------------------------------------------------------------------------
2757 * get_cmp_s --
2758 *
2759 *	Read (single precision) the FS register (bits 15-11) and
2760 *	the FT register (bits 20-16) and break up into fields.
2761 *	This is an internal routine used by MachEmulateFP only.
2762 *
2763 * Results:
2764 *	t0	contains the sign
2765 *	t1	contains the (biased) exponent
2766 *	t2	contains the fraction
2767 *	t4	contains the sign
2768 *	t5	contains the (biased) exponent
2769 *	t6	contains the fraction
2770 *
2771 *----------------------------------------------------------------------------
2772 */
2773LEAF(get_cmp_s)
2774	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2775	and	a3, a3, 0xF << 2		# mask FS field
2776	lw	a3, cmp_fs_s_tbl(a3)		# switch on register number
2777	j	a3
2778
2779	.rdata
2780cmp_fs_s_tbl:
2781	.word	cmp_fs_s_f0
2782	.word	cmp_fs_s_f2
2783	.word	cmp_fs_s_f4
2784	.word	cmp_fs_s_f6
2785	.word	cmp_fs_s_f8
2786	.word	cmp_fs_s_f10
2787	.word	cmp_fs_s_f12
2788	.word	cmp_fs_s_f14
2789	.word	cmp_fs_s_f16
2790	.word	cmp_fs_s_f18
2791	.word	cmp_fs_s_f20
2792	.word	cmp_fs_s_f22
2793	.word	cmp_fs_s_f24
2794	.word	cmp_fs_s_f26
2795	.word	cmp_fs_s_f28
2796	.word	cmp_fs_s_f30
2797	.text
2798
2799cmp_fs_s_f0:
2800	mfc1	t0, $f0
2801	b	cmp_fs_s_done
2802cmp_fs_s_f2:
2803	mfc1	t0, $f2
2804	b	cmp_fs_s_done
2805cmp_fs_s_f4:
2806	mfc1	t0, $f4
2807	b	cmp_fs_s_done
2808cmp_fs_s_f6:
2809	mfc1	t0, $f6
2810	b	cmp_fs_s_done
2811cmp_fs_s_f8:
2812	mfc1	t0, $f8
2813	b	cmp_fs_s_done
2814cmp_fs_s_f10:
2815	mfc1	t0, $f10
2816	b	cmp_fs_s_done
2817cmp_fs_s_f12:
2818	mfc1	t0, $f12
2819	b	cmp_fs_s_done
2820cmp_fs_s_f14:
2821	mfc1	t0, $f14
2822	b	cmp_fs_s_done
2823cmp_fs_s_f16:
2824	mfc1	t0, $f16
2825	b	cmp_fs_s_done
2826cmp_fs_s_f18:
2827	mfc1	t0, $f18
2828	b	cmp_fs_s_done
2829cmp_fs_s_f20:
2830	mfc1	t0, $f20
2831	b	cmp_fs_s_done
2832cmp_fs_s_f22:
2833	mfc1	t0, $f22
2834	b	cmp_fs_s_done
2835cmp_fs_s_f24:
2836	mfc1	t0, $f24
2837	b	cmp_fs_s_done
2838cmp_fs_s_f26:
2839	mfc1	t0, $f26
2840	b	cmp_fs_s_done
2841cmp_fs_s_f28:
2842	mfc1	t0, $f28
2843	b	cmp_fs_s_done
2844cmp_fs_s_f30:
2845	mfc1	t0, $f30
2846cmp_fs_s_done:
2847	srl	t1, t0, 23			# get exponent
2848	and	t1, t1, 0xFF
2849	and	t2, t0, 0x7FFFFF		# get fraction
2850	srl	t0, t0, 31			# get sign
2851
2852	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2853	and	a3, a3, 0xF << 2		# mask FT field
2854	lw	a3, cmp_ft_s_tbl(a3)		# switch on register number
2855	j	a3
2856
2857	.rdata
2858cmp_ft_s_tbl:
2859	.word	cmp_ft_s_f0
2860	.word	cmp_ft_s_f2
2861	.word	cmp_ft_s_f4
2862	.word	cmp_ft_s_f6
2863	.word	cmp_ft_s_f8
2864	.word	cmp_ft_s_f10
2865	.word	cmp_ft_s_f12
2866	.word	cmp_ft_s_f14
2867	.word	cmp_ft_s_f16
2868	.word	cmp_ft_s_f18
2869	.word	cmp_ft_s_f20
2870	.word	cmp_ft_s_f22
2871	.word	cmp_ft_s_f24
2872	.word	cmp_ft_s_f26
2873	.word	cmp_ft_s_f28
2874	.word	cmp_ft_s_f30
2875	.text
2876
2877cmp_ft_s_f0:
2878	mfc1	t4, $f0
2879	b	cmp_ft_s_done
2880cmp_ft_s_f2:
2881	mfc1	t4, $f2
2882	b	cmp_ft_s_done
2883cmp_ft_s_f4:
2884	mfc1	t4, $f4
2885	b	cmp_ft_s_done
2886cmp_ft_s_f6:
2887	mfc1	t4, $f6
2888	b	cmp_ft_s_done
2889cmp_ft_s_f8:
2890	mfc1	t4, $f8
2891	b	cmp_ft_s_done
2892cmp_ft_s_f10:
2893	mfc1	t4, $f10
2894	b	cmp_ft_s_done
2895cmp_ft_s_f12:
2896	mfc1	t4, $f12
2897	b	cmp_ft_s_done
2898cmp_ft_s_f14:
2899	mfc1	t4, $f14
2900	b	cmp_ft_s_done
2901cmp_ft_s_f16:
2902	mfc1	t4, $f16
2903	b	cmp_ft_s_done
2904cmp_ft_s_f18:
2905	mfc1	t4, $f18
2906	b	cmp_ft_s_done
2907cmp_ft_s_f20:
2908	mfc1	t4, $f20
2909	b	cmp_ft_s_done
2910cmp_ft_s_f22:
2911	mfc1	t4, $f22
2912	b	cmp_ft_s_done
2913cmp_ft_s_f24:
2914	mfc1	t4, $f24
2915	b	cmp_ft_s_done
2916cmp_ft_s_f26:
2917	mfc1	t4, $f26
2918	b	cmp_ft_s_done
2919cmp_ft_s_f28:
2920	mfc1	t4, $f28
2921	b	cmp_ft_s_done
2922cmp_ft_s_f30:
2923	mfc1	t4, $f30
2924cmp_ft_s_done:
2925	srl	t5, t4, 23			# get exponent
2926	and	t5, t5, 0xFF
2927	and	t6, t4, 0x7FFFFF		# get fraction
2928	srl	t4, t4, 31			# get sign
2929	j	ra
2930END(get_cmp_s)
2931
2932/*----------------------------------------------------------------------------
2933 * get_cmp_d --
2934 *
2935 *	Read (double precision) the FS register (bits 15-11) and
2936 *	the FT register (bits 20-16) and break up into fields.
2937 *	This is an internal routine used by MachEmulateFP only.
2938 *
2939 * Results:
2940 *	t0	contains the sign
2941 *	t1	contains the (biased) exponent
2942 *	t2	contains the fraction
2943 *	t3	contains the remaining fraction
2944 *	t4	contains the sign
2945 *	t5	contains the (biased) exponent
2946 *	t6	contains the fraction
2947 *	t7	contains the remaining fraction
2948 *
2949 *----------------------------------------------------------------------------
2950 */
2951LEAF(get_cmp_d)
2952	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2953	and	a3, a3, 0xF << 2		# mask FS field
2954	lw	a3, cmp_fs_d_tbl(a3)		# switch on register number
2955	j	a3
2956
2957	.rdata
2958cmp_fs_d_tbl:
2959	.word	cmp_fs_d_f0
2960	.word	cmp_fs_d_f2
2961	.word	cmp_fs_d_f4
2962	.word	cmp_fs_d_f6
2963	.word	cmp_fs_d_f8
2964	.word	cmp_fs_d_f10
2965	.word	cmp_fs_d_f12
2966	.word	cmp_fs_d_f14
2967	.word	cmp_fs_d_f16
2968	.word	cmp_fs_d_f18
2969	.word	cmp_fs_d_f20
2970	.word	cmp_fs_d_f22
2971	.word	cmp_fs_d_f24
2972	.word	cmp_fs_d_f26
2973	.word	cmp_fs_d_f28
2974	.word	cmp_fs_d_f30
2975	.text
2976
2977cmp_fs_d_f0:
2978	mfc1	t3, $f0
2979	mfc1	t0, $f1
2980	b	cmp_fs_d_done
2981cmp_fs_d_f2:
2982	mfc1	t3, $f2
2983	mfc1	t0, $f3
2984	b	cmp_fs_d_done
2985cmp_fs_d_f4:
2986	mfc1	t3, $f4
2987	mfc1	t0, $f5
2988	b	cmp_fs_d_done
2989cmp_fs_d_f6:
2990	mfc1	t3, $f6
2991	mfc1	t0, $f7
2992	b	cmp_fs_d_done
2993cmp_fs_d_f8:
2994	mfc1	t3, $f8
2995	mfc1	t0, $f9
2996	b	cmp_fs_d_done
2997cmp_fs_d_f10:
2998	mfc1	t3, $f10
2999	mfc1	t0, $f11
3000	b	cmp_fs_d_done
3001cmp_fs_d_f12:
3002	mfc1	t3, $f12
3003	mfc1	t0, $f13
3004	b	cmp_fs_d_done
3005cmp_fs_d_f14:
3006	mfc1	t3, $f14
3007	mfc1	t0, $f15
3008	b	cmp_fs_d_done
3009cmp_fs_d_f16:
3010	mfc1	t3, $f16
3011	mfc1	t0, $f17
3012	b	cmp_fs_d_done
3013cmp_fs_d_f18:
3014	mfc1	t3, $f18
3015	mfc1	t0, $f19
3016	b	cmp_fs_d_done
3017cmp_fs_d_f20:
3018	mfc1	t3, $f20
3019	mfc1	t0, $f21
3020	b	cmp_fs_d_done
3021cmp_fs_d_f22:
3022	mfc1	t3, $f22
3023	mfc1	t0, $f23
3024	b	cmp_fs_d_done
3025cmp_fs_d_f24:
3026	mfc1	t3, $f24
3027	mfc1	t0, $f25
3028	b	cmp_fs_d_done
3029cmp_fs_d_f26:
3030	mfc1	t3, $f26
3031	mfc1	t0, $f27
3032	b	cmp_fs_d_done
3033cmp_fs_d_f28:
3034	mfc1	t3, $f28
3035	mfc1	t0, $f29
3036	b	cmp_fs_d_done
3037cmp_fs_d_f30:
3038	mfc1	t3, $f30
3039	mfc1	t0, $f31
3040cmp_fs_d_done:
3041	srl	t1, t0, 20			# get exponent
3042	and	t1, t1, 0x7FF
3043	and	t2, t0, 0xFFFFF			# get fraction
3044	srl	t0, t0, 31			# get sign
3045
3046	srl	a3, a0, 17 - 2			# get FT field (even regs only)
3047	and	a3, a3, 0xF << 2		# mask FT field
3048	lw	a3, cmp_ft_d_tbl(a3)		# switch on register number
3049	j	a3
3050
3051	.rdata
3052cmp_ft_d_tbl:
3053	.word	cmp_ft_d_f0
3054	.word	cmp_ft_d_f2
3055	.word	cmp_ft_d_f4
3056	.word	cmp_ft_d_f6
3057	.word	cmp_ft_d_f8
3058	.word	cmp_ft_d_f10
3059	.word	cmp_ft_d_f12
3060	.word	cmp_ft_d_f14
3061	.word	cmp_ft_d_f16
3062	.word	cmp_ft_d_f18
3063	.word	cmp_ft_d_f20
3064	.word	cmp_ft_d_f22
3065	.word	cmp_ft_d_f24
3066	.word	cmp_ft_d_f26
3067	.word	cmp_ft_d_f28
3068	.word	cmp_ft_d_f30
3069	.text
3070
3071cmp_ft_d_f0:
3072	mfc1	t7, $f0
3073	mfc1	t4, $f1
3074	b	cmp_ft_d_done
3075cmp_ft_d_f2:
3076	mfc1	t7, $f2
3077	mfc1	t4, $f3
3078	b	cmp_ft_d_done
3079cmp_ft_d_f4:
3080	mfc1	t7, $f4
3081	mfc1	t4, $f5
3082	b	cmp_ft_d_done
3083cmp_ft_d_f6:
3084	mfc1	t7, $f6
3085	mfc1	t4, $f7
3086	b	cmp_ft_d_done
3087cmp_ft_d_f8:
3088	mfc1	t7, $f8
3089	mfc1	t4, $f9
3090	b	cmp_ft_d_done
3091cmp_ft_d_f10:
3092	mfc1	t7, $f10
3093	mfc1	t4, $f11
3094	b	cmp_ft_d_done
3095cmp_ft_d_f12:
3096	mfc1	t7, $f12
3097	mfc1	t4, $f13
3098	b	cmp_ft_d_done
3099cmp_ft_d_f14:
3100	mfc1	t7, $f14
3101	mfc1	t4, $f15
3102	b	cmp_ft_d_done
3103cmp_ft_d_f16:
3104	mfc1	t7, $f16
3105	mfc1	t4, $f17
3106	b	cmp_ft_d_done
3107cmp_ft_d_f18:
3108	mfc1	t7, $f18
3109	mfc1	t4, $f19
3110	b	cmp_ft_d_done
3111cmp_ft_d_f20:
3112	mfc1	t7, $f20
3113	mfc1	t4, $f21
3114	b	cmp_ft_d_done
3115cmp_ft_d_f22:
3116	mfc1	t7, $f22
3117	mfc1	t4, $f23
3118	b	cmp_ft_d_done
3119cmp_ft_d_f24:
3120	mfc1	t7, $f24
3121	mfc1	t4, $f25
3122	b	cmp_ft_d_done
3123cmp_ft_d_f26:
3124	mfc1	t7, $f26
3125	mfc1	t4, $f27
3126	b	cmp_ft_d_done
3127cmp_ft_d_f28:
3128	mfc1	t7, $f28
3129	mfc1	t4, $f29
3130	b	cmp_ft_d_done
3131cmp_ft_d_f30:
3132	mfc1	t7, $f30
3133	mfc1	t4, $f31
3134cmp_ft_d_done:
3135	srl	t5, t4, 20			# get exponent
3136	and	t5, t5, 0x7FF
3137	and	t6, t4, 0xFFFFF			# get fraction
3138	srl	t4, t4, 31			# get sign
3139	j	ra
3140END(get_cmp_d)
3141
3142/*----------------------------------------------------------------------------
3143 * set_fd_s --
3144 *
3145 *	Write (single precision) the FD register (bits 10-6).
3146 *	This is an internal routine used by MachEmulateFP only.
3147 *
3148 * Arguments:
3149 *	a0	contains the FP instruction
3150 *	t0	contains the sign
3151 *	t1	contains the (biased) exponent
3152 *	t2	contains the fraction
3153 *
3154 * set_fd_word --
3155 *
3156 *	Write (integer) the FD register (bits 10-6).
3157 *	This is an internal routine used by MachEmulateFP only.
3158 *
3159 * Arguments:
3160 *	a0	contains the FP instruction
3161 *	t2	contains the integer
3162 *
3163 *----------------------------------------------------------------------------
3164 */
3165LEAF(set_fd_s)
3166	sll	t0, t0, 31			# position sign
3167	sll	t1, t1, 23			# position exponent
3168	or	t2, t2, t0
3169	or	t2, t2, t1
3170ALEAF(set_fd_word)
3171	srl	a3, a0, 7 - 2			# get FD field (even regs only)
3172	and	a3, a3, 0xF << 2		# mask FT field
3173	lw	a3, set_fd_s_tbl(a3)		# switch on register number
3174	j	a3
3175
3176	.rdata
3177set_fd_s_tbl:
3178	.word	set_fd_s_f0
3179	.word	set_fd_s_f2
3180	.word	set_fd_s_f4
3181	.word	set_fd_s_f6
3182	.word	set_fd_s_f8
3183	.word	set_fd_s_f10
3184	.word	set_fd_s_f12
3185	.word	set_fd_s_f14
3186	.word	set_fd_s_f16
3187	.word	set_fd_s_f18
3188	.word	set_fd_s_f20
3189	.word	set_fd_s_f22
3190	.word	set_fd_s_f24
3191	.word	set_fd_s_f26
3192	.word	set_fd_s_f28
3193	.word	set_fd_s_f30
3194	.text
3195
3196set_fd_s_f0:
3197	mtc1	t2, $f0
3198	j	ra
3199set_fd_s_f2:
3200	mtc1	t2, $f2
3201	j	ra
3202set_fd_s_f4:
3203	mtc1	t2, $f4
3204	j	ra
3205set_fd_s_f6:
3206	mtc1	t2, $f6
3207	j	ra
3208set_fd_s_f8:
3209	mtc1	t2, $f8
3210	j	ra
3211set_fd_s_f10:
3212	mtc1	t2, $f10
3213	j	ra
3214set_fd_s_f12:
3215	mtc1	t2, $f12
3216	j	ra
3217set_fd_s_f14:
3218	mtc1	t2, $f14
3219	j	ra
3220set_fd_s_f16:
3221	mtc1	t2, $f16
3222	j	ra
3223set_fd_s_f18:
3224	mtc1	t2, $f18
3225	j	ra
3226set_fd_s_f20:
3227	mtc1	t2, $f20
3228	j	ra
3229set_fd_s_f22:
3230	mtc1	t2, $f22
3231	j	ra
3232set_fd_s_f24:
3233	mtc1	t2, $f24
3234	j	ra
3235set_fd_s_f26:
3236	mtc1	t2, $f26
3237	j	ra
3238set_fd_s_f28:
3239	mtc1	t2, $f28
3240	j	ra
3241set_fd_s_f30:
3242	mtc1	t2, $f30
3243	j	ra
3244END(set_fd_s)
3245
3246/*----------------------------------------------------------------------------
3247 * set_fd_d --
3248 *
3249 *	Write (double precision) the FT register (bits 10-6).
3250 *	This is an internal routine used by MachEmulateFP only.
3251 *
3252 * Arguments:
3253 *	a0	contains the FP instruction
3254 *	t0	contains the sign
3255 *	t1	contains the (biased) exponent
3256 *	t2	contains the fraction
3257 *	t3	contains the remaining fraction
3258 *
3259 *----------------------------------------------------------------------------
3260 */
3261LEAF(set_fd_d)
3262	sll	t0, t0, 31			# set sign
3263	sll	t1, t1, 20			# set exponent
3264	or	t0, t0, t1
3265	or	t0, t0, t2			# set fraction
3266	srl	a3, a0, 7 - 2			# get FD field (even regs only)
3267	and	a3, a3, 0xF << 2		# mask FD field
3268	lw	a3, set_fd_d_tbl(a3)		# switch on register number
3269	j	a3
3270
3271	.rdata
3272set_fd_d_tbl:
3273	.word	set_fd_d_f0
3274	.word	set_fd_d_f2
3275	.word	set_fd_d_f4
3276	.word	set_fd_d_f6
3277	.word	set_fd_d_f8
3278	.word	set_fd_d_f10
3279	.word	set_fd_d_f12
3280	.word	set_fd_d_f14
3281	.word	set_fd_d_f16
3282	.word	set_fd_d_f18
3283	.word	set_fd_d_f20
3284	.word	set_fd_d_f22
3285	.word	set_fd_d_f24
3286	.word	set_fd_d_f26
3287	.word	set_fd_d_f28
3288	.word	set_fd_d_f30
3289	.text
3290
3291set_fd_d_f0:
3292	mtc1	t3, $f0
3293	mtc1	t0, $f1
3294	j	ra
3295set_fd_d_f2:
3296	mtc1	t3, $f2
3297	mtc1	t0, $f3
3298	j	ra
3299set_fd_d_f4:
3300	mtc1	t3, $f4
3301	mtc1	t0, $f5
3302	j	ra
3303set_fd_d_f6:
3304	mtc1	t3, $f6
3305	mtc1	t0, $f7
3306	j	ra
3307set_fd_d_f8:
3308	mtc1	t3, $f8
3309	mtc1	t0, $f9
3310	j	ra
3311set_fd_d_f10:
3312	mtc1	t3, $f10
3313	mtc1	t0, $f11
3314	j	ra
3315set_fd_d_f12:
3316	mtc1	t3, $f12
3317	mtc1	t0, $f13
3318	j	ra
3319set_fd_d_f14:
3320	mtc1	t3, $f14
3321	mtc1	t0, $f15
3322	j	ra
3323set_fd_d_f16:
3324	mtc1	t3, $f16
3325	mtc1	t0, $f17
3326	j	ra
3327set_fd_d_f18:
3328	mtc1	t3, $f18
3329	mtc1	t0, $f19
3330	j	ra
3331set_fd_d_f20:
3332	mtc1	t3, $f20
3333	mtc1	t0, $f21
3334	j	ra
3335set_fd_d_f22:
3336	mtc1	t3, $f22
3337	mtc1	t0, $f23
3338	j	ra
3339set_fd_d_f24:
3340	mtc1	t3, $f24
3341	mtc1	t0, $f25
3342	j	ra
3343set_fd_d_f26:
3344	mtc1	t3, $f26
3345	mtc1	t0, $f27
3346	j	ra
3347set_fd_d_f28:
3348	mtc1	t3, $f28
3349	mtc1	t0, $f29
3350	j	ra
3351set_fd_d_f30:
3352	mtc1	t3, $f30
3353	mtc1	t0, $f31
3354	j	ra
3355END(set_fd_d)
3356
3357/*----------------------------------------------------------------------------
3358 * renorm_fs_s --
3359 *
3360 * Results:
3361 *	t1	unbiased exponent
3362 *	t2	normalized fraction
3363 *
3364 *----------------------------------------------------------------------------
3365 */
3366LEAF(renorm_fs_s)
3367/*
3368 * Find out how many leading zero bits are in t2 and put in t9.
3369 */
3370	move	v0, t2
3371	move	t9, zero
3372	srl	v1, v0, 16
3373	bne	v1, zero, 1f
3374	addu	t9, 16
3375	sll	v0, 16
33761:
3377	srl	v1, v0, 24
3378	bne	v1, zero, 1f
3379	addu	t9, 8
3380	sll	v0, 8
33811:
3382	srl	v1, v0, 28
3383	bne	v1, zero, 1f
3384	addu	t9, 4
3385	sll	v0, 4
33861:
3387	srl	v1, v0, 30
3388	bne	v1, zero, 1f
3389	addu	t9, 2
3390	sll	v0, 2
33911:
3392	srl	v1, v0, 31
3393	bne	v1, zero, 1f
3394	addu	t9, 1
3395/*
3396 * Now shift t2 the correct number of bits.
3397 */
33981:
3399	subu	t9, t9, SLEAD_ZEROS	# don't count normal leading zeros
3400	li	t1, SEXP_MIN
3401	subu	t1, t1, t9		# adjust exponent
3402	sll	t2, t2, t9
3403	j	ra
3404END(renorm_fs_s)
3405
3406/*----------------------------------------------------------------------------
3407 * renorm_fs_d --
3408 *
3409 * Results:
3410 *	t1	unbiased exponent
3411 *	t2,t3	normalized fraction
3412 *
3413 *----------------------------------------------------------------------------
3414 */
3415LEAF(renorm_fs_d)
3416/*
3417 * Find out how many leading zero bits are in t2,t3 and put in t9.
3418 */
3419	move	v0, t2
3420	move	t9, zero
3421	bne	t2, zero, 1f
3422	move	v0, t3
3423	addu	t9, 32
34241:
3425	srl	v1, v0, 16
3426	bne	v1, zero, 1f
3427	addu	t9, 16
3428	sll	v0, 16
34291:
3430	srl	v1, v0, 24
3431	bne	v1, zero, 1f
3432	addu	t9, 8
3433	sll	v0, 8
34341:
3435	srl	v1, v0, 28
3436	bne	v1, zero, 1f
3437	addu	t9, 4
3438	sll	v0, 4
34391:
3440	srl	v1, v0, 30
3441	bne	v1, zero, 1f
3442	addu	t9, 2
3443	sll	v0, 2
34441:
3445	srl	v1, v0, 31
3446	bne	v1, zero, 1f
3447	addu	t9, 1
3448/*
3449 * Now shift t2,t3 the correct number of bits.
3450 */
34511:
3452	subu	t9, t9, DLEAD_ZEROS	# don't count normal leading zeros
3453	li	t1, DEXP_MIN
3454	subu	t1, t1, t9		# adjust exponent
3455	li	v0, 32
3456	blt	t9, v0, 1f
3457	subu	t9, t9, v0		# shift fraction left >= 32 bits
3458	sll	t2, t3, t9
3459	move	t3, zero
3460	j	ra
34611:
3462	subu	v0, v0, t9		# shift fraction left < 32 bits
3463	sll	t2, t2, t9
3464	srl	v1, t3, v0
3465	or	t2, t2, v1
3466	sll	t3, t3, t9
3467	j	ra
3468END(renorm_fs_d)
3469
3470/*----------------------------------------------------------------------------
3471 * renorm_ft_s --
3472 *
3473 * Results:
3474 *	t5	unbiased exponent
3475 *	t6	normalized fraction
3476 *
3477 *----------------------------------------------------------------------------
3478 */
3479LEAF(renorm_ft_s)
3480/*
3481 * Find out how many leading zero bits are in t6 and put in t9.
3482 */
3483	move	v0, t6
3484	move	t9, zero
3485	srl	v1, v0, 16
3486	bne	v1, zero, 1f
3487	addu	t9, 16
3488	sll	v0, 16
34891:
3490	srl	v1, v0, 24
3491	bne	v1, zero, 1f
3492	addu	t9, 8
3493	sll	v0, 8
34941:
3495	srl	v1, v0, 28
3496	bne	v1, zero, 1f
3497	addu	t9, 4
3498	sll	v0, 4
34991:
3500	srl	v1, v0, 30
3501	bne	v1, zero, 1f
3502	addu	t9, 2
3503	sll	v0, 2
35041:
3505	srl	v1, v0, 31
3506	bne	v1, zero, 1f
3507	addu	t9, 1
3508/*
3509 * Now shift t6 the correct number of bits.
3510 */
35111:
3512	subu	t9, t9, SLEAD_ZEROS	# don't count normal leading zeros
3513	li	t5, SEXP_MIN
3514	subu	t5, t5, t9		# adjust exponent
3515	sll	t6, t6, t9
3516	j	ra
3517END(renorm_ft_s)
3518
3519/*----------------------------------------------------------------------------
3520 * renorm_ft_d --
3521 *
3522 * Results:
3523 *	t5	unbiased exponent
3524 *	t6,t7	normalized fraction
3525 *
3526 *----------------------------------------------------------------------------
3527 */
3528LEAF(renorm_ft_d)
3529/*
3530 * Find out how many leading zero bits are in t6,t7 and put in t9.
3531 */
3532	move	v0, t6
3533	move	t9, zero
3534	bne	t6, zero, 1f
3535	move	v0, t7
3536	addu	t9, 32
35371:
3538	srl	v1, v0, 16
3539	bne	v1, zero, 1f
3540	addu	t9, 16
3541	sll	v0, 16
35421:
3543	srl	v1, v0, 24
3544	bne	v1, zero, 1f
3545	addu	t9, 8
3546	sll	v0, 8
35471:
3548	srl	v1, v0, 28
3549	bne	v1, zero, 1f
3550	addu	t9, 4
3551	sll	v0, 4
35521:
3553	srl	v1, v0, 30
3554	bne	v1, zero, 1f
3555	addu	t9, 2
3556	sll	v0, 2
35571:
3558	srl	v1, v0, 31
3559	bne	v1, zero, 1f
3560	addu	t9, 1
3561/*
3562 * Now shift t6,t7 the correct number of bits.
3563 */
35641:
3565	subu	t9, t9, DLEAD_ZEROS	# don't count normal leading zeros
3566	li	t5, DEXP_MIN
3567	subu	t5, t5, t9		# adjust exponent
3568	li	v0, 32
3569	blt	t9, v0, 1f
3570	subu	t9, t9, v0		# shift fraction left >= 32 bits
3571	sll	t6, t7, t9
3572	move	t7, zero
3573	j	ra
35741:
3575	subu	v0, v0, t9		# shift fraction left < 32 bits
3576	sll	t6, t6, t9
3577	srl	v1, t7, v0
3578	or	t6, t6, v1
3579	sll	t7, t7, t9
3580	j	ra
3581END(renorm_ft_d)
3582