xref: /original-bsd/sys/pmax/pmax/fp.s (revision e59fb703)
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.1 (Berkeley) 01/07/92
11 */
12
13/*
14 * Standard header stuff.
15 */
16
17#include "machine/regdef.h"
18#include "machine/machAsmDefs.h"
19#include "machine/machConst.h"
20#include "assym.h"
21
22#define SEXP_INF	0xff
23#define DEXP_INF	0x7ff
24#define SEXP_BIAS	127
25#define DEXP_BIAS	1023
26#define SEXP_MIN	-126
27#define DEXP_MIN	-1022
28#define SEXP_MAX	127
29#define DEXP_MAX	1023
30#define WEXP_MAX	30		/* maximum unbiased exponent for int */
31#define WEXP_MIN	-1		/* minimum unbiased exponent for int */
32#define SFRAC_BITS	23
33#define DFRAC_BITS	52
34#define SIMPL_ONE	0x00800000
35#define DIMPL_ONE	0x00100000
36#define SLEAD_ZEROS	31 - 23
37#define DLEAD_ZEROS	31 - 20
38#define STICKYBIT	1
39#define GUARDBIT	0x80000000
40#define SSIGNAL_NAN	0x00400000
41#define DSIGNAL_NAN	0x00040000
42#define SQUIET_NAN	0x003fffff
43#define DQUIET_NAN0	0x0007ffff
44#define DQUIET_NAN1	0xffffffff
45#define INT_MIN		0x80000000
46#define INT_MAX		0x7fffffff
47
48#define COND_UNORDERED	0x1
49#define COND_EQUAL	0x2
50#define COND_LESS	0x4
51#define COND_SIGNAL	0x8
52
53/*----------------------------------------------------------------------------
54 *
55 * MachEmulateFP --
56 *
57 *	Emulate unimplemented floating point operations.
58 *	This routine should only be called by MachFPInterrupt().
59 *
60 *	MachEmulateFP(instr)
61 *		unsigned instr;
62 *
63 * Results:
64 *	None.
65 *
66 * Side effects:
67 *	Floating point registers are modified according to instruction.
68 *
69 *----------------------------------------------------------------------------
70 */
71NON_LEAF(MachEmulateFP, STAND_FRAME_SIZE, ra)
72	subu	sp, sp, STAND_FRAME_SIZE
73	sw	ra, STAND_RA_OFFSET(sp)
74/*
75 * Decode the FMT field (bits 24-21) and FUNCTION field (bits 5-0).
76 */
77	srl	v0, a0, 21 - 2			# get FMT field
78	and	v0, v0, 0xF << 2		# mask FMT field
79	and	v1, a0, 0x3F			# mask FUNC field
80	sll	v1, v1, 5			# align for table lookup
81	bgt	v0, 4 << 2, ill			# illegal format
82
83	or	v1, v1, v0
84	cfc1	a1, MACH_FPC_CSR		# get exception register
85	lw	a3, func_fmt_tbl(v1)		# switch on FUNC & FMT
86	and	a1, a1, ~MACH_FPC_EXCEPTION_UNIMPL	# clear exception
87	ctc1	a1, MACH_FPC_CSR
88	j	a3
89
90	.rdata
91func_fmt_tbl:
92	.word	add_s		# 0
93	.word	add_d		# 0
94	.word	ill		# 0
95	.word	ill		# 0
96	.word	ill		# 0
97	.word	ill		# 0
98	.word	ill		# 0
99	.word	ill		# 0
100	.word	sub_s		# 1
101	.word	sub_d		# 1
102	.word	ill		# 1
103	.word	ill		# 1
104	.word	ill		# 1
105	.word	ill		# 1
106	.word	ill		# 1
107	.word	ill		# 1
108	.word	mul_s		# 2
109	.word	mul_d		# 2
110	.word	ill		# 2
111	.word	ill		# 2
112	.word	ill		# 2
113	.word	ill		# 2
114	.word	ill		# 2
115	.word	ill		# 2
116	.word	div_s		# 3
117	.word	div_d		# 3
118	.word	ill		# 3
119	.word	ill		# 3
120	.word	ill		# 3
121	.word	ill		# 3
122	.word	ill		# 3
123	.word	ill		# 3
124	.word	ill		# 4
125	.word	ill		# 4
126	.word	ill		# 4
127	.word	ill		# 4
128	.word	ill		# 4
129	.word	ill		# 4
130	.word	ill		# 4
131	.word	ill		# 4
132	.word	abs_s		# 5
133	.word	abs_d		# 5
134	.word	ill		# 5
135	.word	ill		# 5
136	.word	ill		# 5
137	.word	ill		# 5
138	.word	ill		# 5
139	.word	ill		# 5
140	.word	mov_s		# 6
141	.word	mov_d		# 6
142	.word	ill		# 6
143	.word	ill		# 6
144	.word	ill		# 6
145	.word	ill		# 6
146	.word	ill		# 6
147	.word	ill		# 6
148	.word	neg_s		# 7
149	.word	neg_d		# 7
150	.word	ill		# 7
151	.word	ill		# 7
152	.word	ill		# 7
153	.word	ill		# 7
154	.word	ill		# 7
155	.word	ill		# 7
156	.word	ill		# 8
157	.word	ill		# 8
158	.word	ill		# 8
159	.word	ill		# 8
160	.word	ill		# 8
161	.word	ill		# 8
162	.word	ill		# 8
163	.word	ill		# 8
164	.word	ill		# 9
165	.word	ill		# 9
166	.word	ill		# 9
167	.word	ill		# 9
168	.word	ill		# 9
169	.word	ill		# 9
170	.word	ill		# 9
171	.word	ill		# 9
172	.word	ill		# 10
173	.word	ill		# 10
174	.word	ill		# 10
175	.word	ill		# 10
176	.word	ill		# 10
177	.word	ill		# 10
178	.word	ill		# 10
179	.word	ill		# 10
180	.word	ill		# 11
181	.word	ill		# 11
182	.word	ill		# 11
183	.word	ill		# 11
184	.word	ill		# 11
185	.word	ill		# 11
186	.word	ill		# 11
187	.word	ill		# 11
188	.word	ill		# 12
189	.word	ill		# 12
190	.word	ill		# 12
191	.word	ill		# 12
192	.word	ill		# 12
193	.word	ill		# 12
194	.word	ill		# 12
195	.word	ill		# 12
196	.word	ill		# 13
197	.word	ill		# 13
198	.word	ill		# 13
199	.word	ill		# 13
200	.word	ill		# 13
201	.word	ill		# 13
202	.word	ill		# 13
203	.word	ill		# 13
204	.word	ill		# 14
205	.word	ill		# 14
206	.word	ill		# 14
207	.word	ill		# 14
208	.word	ill		# 14
209	.word	ill		# 14
210	.word	ill		# 14
211	.word	ill		# 14
212	.word	ill		# 15
213	.word	ill		# 15
214	.word	ill		# 15
215	.word	ill		# 15
216	.word	ill		# 15
217	.word	ill		# 15
218	.word	ill		# 15
219	.word	ill		# 15
220	.word	ill		# 16
221	.word	ill		# 16
222	.word	ill		# 16
223	.word	ill		# 16
224	.word	ill		# 16
225	.word	ill		# 16
226	.word	ill		# 16
227	.word	ill		# 16
228	.word	ill		# 17
229	.word	ill		# 17
230	.word	ill		# 17
231	.word	ill		# 17
232	.word	ill		# 17
233	.word	ill		# 17
234	.word	ill		# 17
235	.word	ill		# 17
236	.word	ill		# 18
237	.word	ill		# 18
238	.word	ill		# 18
239	.word	ill		# 18
240	.word	ill		# 18
241	.word	ill		# 18
242	.word	ill		# 18
243	.word	ill		# 18
244	.word	ill		# 19
245	.word	ill		# 19
246	.word	ill		# 19
247	.word	ill		# 19
248	.word	ill		# 19
249	.word	ill		# 19
250	.word	ill		# 19
251	.word	ill		# 19
252	.word	ill		# 20
253	.word	ill		# 20
254	.word	ill		# 20
255	.word	ill		# 20
256	.word	ill		# 20
257	.word	ill		# 20
258	.word	ill		# 20
259	.word	ill		# 20
260	.word	ill		# 21
261	.word	ill		# 21
262	.word	ill		# 21
263	.word	ill		# 21
264	.word	ill		# 21
265	.word	ill		# 21
266	.word	ill		# 21
267	.word	ill		# 21
268	.word	ill		# 22
269	.word	ill		# 22
270	.word	ill		# 22
271	.word	ill		# 22
272	.word	ill		# 22
273	.word	ill		# 22
274	.word	ill		# 22
275	.word	ill		# 22
276	.word	ill		# 23
277	.word	ill		# 23
278	.word	ill		# 23
279	.word	ill		# 23
280	.word	ill		# 23
281	.word	ill		# 23
282	.word	ill		# 23
283	.word	ill		# 23
284	.word	ill		# 24
285	.word	ill		# 24
286	.word	ill		# 24
287	.word	ill		# 24
288	.word	ill		# 24
289	.word	ill		# 24
290	.word	ill		# 24
291	.word	ill		# 24
292	.word	ill		# 25
293	.word	ill		# 25
294	.word	ill		# 25
295	.word	ill		# 25
296	.word	ill		# 25
297	.word	ill		# 25
298	.word	ill		# 25
299	.word	ill		# 25
300	.word	ill		# 26
301	.word	ill		# 26
302	.word	ill		# 26
303	.word	ill		# 26
304	.word	ill		# 26
305	.word	ill		# 26
306	.word	ill		# 26
307	.word	ill		# 26
308	.word	ill		# 27
309	.word	ill		# 27
310	.word	ill		# 27
311	.word	ill		# 27
312	.word	ill		# 27
313	.word	ill		# 27
314	.word	ill		# 27
315	.word	ill		# 27
316	.word	ill		# 28
317	.word	ill		# 28
318	.word	ill		# 28
319	.word	ill		# 28
320	.word	ill		# 28
321	.word	ill		# 28
322	.word	ill		# 28
323	.word	ill		# 28
324	.word	ill		# 29
325	.word	ill		# 29
326	.word	ill		# 29
327	.word	ill		# 29
328	.word	ill		# 29
329	.word	ill		# 29
330	.word	ill		# 29
331	.word	ill		# 29
332	.word	ill		# 30
333	.word	ill		# 30
334	.word	ill		# 30
335	.word	ill		# 30
336	.word	ill		# 30
337	.word	ill		# 30
338	.word	ill		# 30
339	.word	ill		# 30
340	.word	ill		# 31
341	.word	ill		# 31
342	.word	ill		# 31
343	.word	ill		# 31
344	.word	ill		# 31
345	.word	ill		# 31
346	.word	ill		# 31
347	.word	ill		# 31
348	.word	ill		# 32
349	.word	cvt_s_d		# 32
350	.word	ill		# 32
351	.word	ill		# 32
352	.word	cvt_s_w		# 32
353	.word	ill		# 32
354	.word	ill		# 32
355	.word	ill		# 32
356	.word	cvt_d_s		# 33
357	.word	ill		# 33
358	.word	ill		# 33
359	.word	ill		# 33
360	.word	cvt_d_w		# 33
361	.word	ill		# 33
362	.word	ill		# 33
363	.word	ill		# 33
364	.word	ill		# 34
365	.word	ill		# 34
366	.word	ill		# 34
367	.word	ill		# 34
368	.word	ill		# 34
369	.word	ill		# 34
370	.word	ill		# 34
371	.word	ill		# 34
372	.word	ill		# 35
373	.word	ill		# 35
374	.word	ill		# 35
375	.word	ill		# 35
376	.word	ill		# 35
377	.word	ill		# 35
378	.word	ill		# 35
379	.word	ill		# 35
380	.word	cvt_w_s		# 36
381	.word	cvt_w_d		# 36
382	.word	ill		# 36
383	.word	ill		# 36
384	.word	ill		# 36
385	.word	ill		# 36
386	.word	ill		# 36
387	.word	ill		# 36
388	.word	ill		# 37
389	.word	ill		# 37
390	.word	ill		# 37
391	.word	ill		# 37
392	.word	ill		# 37
393	.word	ill		# 37
394	.word	ill		# 37
395	.word	ill		# 37
396	.word	ill		# 38
397	.word	ill		# 38
398	.word	ill		# 38
399	.word	ill		# 38
400	.word	ill		# 38
401	.word	ill		# 38
402	.word	ill		# 38
403	.word	ill		# 38
404	.word	ill		# 39
405	.word	ill		# 39
406	.word	ill		# 39
407	.word	ill		# 39
408	.word	ill		# 39
409	.word	ill		# 39
410	.word	ill		# 39
411	.word	ill		# 39
412	.word	ill		# 40
413	.word	ill		# 40
414	.word	ill		# 40
415	.word	ill		# 40
416	.word	ill		# 40
417	.word	ill		# 40
418	.word	ill		# 40
419	.word	ill		# 40
420	.word	ill		# 41
421	.word	ill		# 41
422	.word	ill		# 41
423	.word	ill		# 41
424	.word	ill		# 41
425	.word	ill		# 41
426	.word	ill		# 41
427	.word	ill		# 41
428	.word	ill		# 42
429	.word	ill		# 42
430	.word	ill		# 42
431	.word	ill		# 42
432	.word	ill		# 42
433	.word	ill		# 42
434	.word	ill		# 42
435	.word	ill		# 42
436	.word	ill		# 43
437	.word	ill		# 43
438	.word	ill		# 43
439	.word	ill		# 43
440	.word	ill		# 43
441	.word	ill		# 43
442	.word	ill		# 43
443	.word	ill		# 43
444	.word	ill		# 44
445	.word	ill		# 44
446	.word	ill		# 44
447	.word	ill		# 44
448	.word	ill		# 44
449	.word	ill		# 44
450	.word	ill		# 44
451	.word	ill		# 44
452	.word	ill		# 45
453	.word	ill		# 45
454	.word	ill		# 45
455	.word	ill		# 45
456	.word	ill		# 45
457	.word	ill		# 45
458	.word	ill		# 45
459	.word	ill		# 45
460	.word	ill		# 46
461	.word	ill		# 46
462	.word	ill		# 46
463	.word	ill		# 46
464	.word	ill		# 46
465	.word	ill		# 46
466	.word	ill		# 46
467	.word	ill		# 46
468	.word	ill		# 47
469	.word	ill		# 47
470	.word	ill		# 47
471	.word	ill		# 47
472	.word	ill		# 47
473	.word	ill		# 47
474	.word	ill		# 47
475	.word	ill		# 47
476	.word	cmp_s		# 48
477	.word	cmp_d		# 48
478	.word	ill		# 48
479	.word	ill		# 48
480	.word	ill		# 48
481	.word	ill		# 48
482	.word	ill		# 48
483	.word	ill		# 48
484	.word	cmp_s		# 49
485	.word	cmp_d		# 49
486	.word	ill		# 49
487	.word	ill		# 49
488	.word	ill		# 49
489	.word	ill		# 49
490	.word	ill		# 49
491	.word	ill		# 49
492	.word	cmp_s		# 50
493	.word	cmp_d		# 50
494	.word	ill		# 50
495	.word	ill		# 50
496	.word	ill		# 50
497	.word	ill		# 50
498	.word	ill		# 50
499	.word	ill		# 50
500	.word	cmp_s		# 51
501	.word	cmp_d		# 51
502	.word	ill		# 51
503	.word	ill		# 51
504	.word	ill		# 51
505	.word	ill		# 51
506	.word	ill		# 51
507	.word	ill		# 51
508	.word	cmp_s		# 52
509	.word	cmp_d		# 52
510	.word	ill		# 52
511	.word	ill		# 52
512	.word	ill		# 52
513	.word	ill		# 52
514	.word	ill		# 52
515	.word	ill		# 52
516	.word	cmp_s		# 53
517	.word	cmp_d		# 53
518	.word	ill		# 53
519	.word	ill		# 53
520	.word	ill		# 53
521	.word	ill		# 53
522	.word	ill		# 53
523	.word	ill		# 53
524	.word	cmp_s		# 54
525	.word	cmp_d		# 54
526	.word	ill		# 54
527	.word	ill		# 54
528	.word	ill		# 54
529	.word	ill		# 54
530	.word	ill		# 54
531	.word	ill		# 54
532	.word	cmp_s		# 55
533	.word	cmp_d		# 55
534	.word	ill		# 55
535	.word	ill		# 55
536	.word	ill		# 55
537	.word	ill		# 55
538	.word	ill		# 55
539	.word	ill		# 55
540	.word	cmp_s		# 56
541	.word	cmp_d		# 56
542	.word	ill		# 56
543	.word	ill		# 56
544	.word	ill		# 56
545	.word	ill		# 56
546	.word	ill		# 56
547	.word	ill		# 56
548	.word	cmp_s		# 57
549	.word	cmp_d		# 57
550	.word	ill		# 57
551	.word	ill		# 57
552	.word	ill		# 57
553	.word	ill		# 57
554	.word	ill		# 57
555	.word	ill		# 57
556	.word	cmp_s		# 58
557	.word	cmp_d		# 58
558	.word	ill		# 58
559	.word	ill		# 58
560	.word	ill		# 58
561	.word	ill		# 58
562	.word	ill		# 58
563	.word	ill		# 58
564	.word	cmp_s		# 59
565	.word	cmp_d		# 59
566	.word	ill		# 59
567	.word	ill		# 59
568	.word	ill		# 59
569	.word	ill		# 59
570	.word	ill		# 59
571	.word	ill		# 59
572	.word	cmp_s		# 60
573	.word	cmp_d		# 60
574	.word	ill		# 60
575	.word	ill		# 60
576	.word	ill		# 60
577	.word	ill		# 60
578	.word	ill		# 60
579	.word	ill		# 60
580	.word	cmp_s		# 61
581	.word	cmp_d		# 61
582	.word	ill		# 61
583	.word	ill		# 61
584	.word	ill		# 61
585	.word	ill		# 61
586	.word	ill		# 61
587	.word	ill		# 61
588	.word	cmp_s		# 62
589	.word	cmp_d		# 62
590	.word	ill		# 62
591	.word	ill		# 62
592	.word	ill		# 62
593	.word	ill		# 62
594	.word	ill		# 62
595	.word	ill		# 62
596	.word	cmp_s		# 63
597	.word	cmp_d		# 63
598	.word	ill		# 63
599	.word	ill		# 63
600	.word	ill		# 63
601	.word	ill		# 63
602	.word	ill		# 63
603	.word	ill		# 63
604	.text
605
606/*
607 * Single precision subtract.
608 */
609sub_s:
610	jal	get_fs_sgl
611	jal	get_ft_sgl
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_fs_sgl
619	jal	get_ft_sgl
620add_sub_s:
621	bne	t1, SEXP_INF, 1f		# is FS an infinity?
622	bne	t5, SEXP_INF, result_fs_s	# if FT is not inf, result=FS
623	bne	t0, t4, invalid_s		# both infinities same sign?
624	b	result_fs_s			# result is in FS
6251:
626	beq	t5, SEXP_INF, result_ft_s	# if FT is inf, result=FT
627	bne	t1, zero, 4f			# is FS a denormalized num?
628	beq	t2, zero, 3f			# is FS zero?
629	bne	t5, zero, 2f			# is FT a denormalized num?
630	beq	t6, zero, result_fs_s		# FT is zero, result=FS
631	jal	renorm_fs_s
632	jal	renorm_ft_s
633	b	5f
6342:
635	jal	renorm_fs_s
636	subu	t5, t5, SEXP_BIAS		# unbias FT exponent
637	or	t6, t6, SIMPL_ONE		# set implied one bit
638	b	5f
6393:
640	bne	t5, zero, result_ft_s		# if FT != 0, result=FT
641	bne	t6, zero, result_ft_s
642	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
643	bne	v0, MACH_FPC_ROUND_RM, 1f	# round to -infinity?
644	or	t0, t0, t4			# compute result sign
645	b	result_fs_s
6461:
647	and	t0, t0, t4			# compute result sign
648	b	result_fs_s
6494:
650	bne	t5, zero, 2f			# is FT a denormalized num?
651	beq	t6, zero, result_fs_s		# FT is zero, result=FS
652	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
653	or	t2, t2, SIMPL_ONE		# set implied one bit
654	jal	renorm_ft_s
655	b	5f
6562:
657	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
658	or	t2, t2, SIMPL_ONE		# set implied one bit
659	subu	t5, t5, SEXP_BIAS		# unbias FT exponent
660	or	t6, t6, SIMPL_ONE		# set implied one bit
661/*
662 * Perform the addition.
663 */
6645:
665	move	t8, zero			# no shifted bits (sticky reg)
666	beq	t1, t5, 4f			# no shift needed
667	subu	v0, t1, t5			# v0 = difference of exponents
668	move	v1, v0				# v1 = abs(difference)
669	bge	v0, zero, 1f
670	negu	v1
6711:
672	ble	v1, SFRAC_BITS+2, 2f		# is difference too great?
673	li	t8, STICKYBIT			# set the sticky bit
674	bge	v0, zero, 1f			# check which exp is larger
675	move	t1, t5				# result exp is FT's
676	move	t2, zero			# FS's fraction shifted is zero
677	b	4f
6781:
679	move	t6, zero			# FT's fraction shifted is zero
680	b	4f
6812:
682	li	t9, 32				# compute 32 - abs(exp diff)
683	subu	t9, t9, v1
684	bgt	v0, zero, 3f			# if FS > FT, shift FT's frac
685	move	t1, t5				# FT > FS, result exp is FT's
686	sll	t8, t2, t9			# save bits shifted out
687	srl	t2, t2, v1			# shift FS's fraction
688	b	4f
6893:
690	sll	t8, t6, t9			# save bits shifted out
691	srl	t6, t6, v1			# shift FT's fraction
6924:
693	bne	t0, t4, 1f			# if signs differ, subtract
694	addu	t2, t2, t6			# add fractions
695	b	norm_s
6961:
697	blt	t2, t6, 3f			# subtract larger from smaller
698	bne	t2, t6, 2f			# if same, result=0
699	move	t1, zero			# result=0
700	move	t2, zero
701	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
702	bne	v0, MACH_FPC_ROUND_RM, 1f	# round to -infinity?
703	or	t0, t0, t4			# compute result sign
704	b	result_fs_s
7051:
706	and	t0, t0, t4			# compute result sign
707	b	result_fs_s
7082:
709	sltu	t9, zero, t8			# compute t2:zero - t6:t8
710	subu	t8, zero, t8
711	subu	t2, t2, t6			# subtract fractions
712	subu	t2, t2, t9			# subtract barrow
713	b	norm_s
7143:
715	move	t0, t4				# sign of result = FT's
716	sltu	t9, zero, t8			# compute t6:zero - t2:t8
717	subu	t8, zero, t8
718	subu	t2, t6, t2			# subtract fractions
719	subu	t2, t2, t9			# subtract barrow
720	b	norm_s
721
722/*
723 * Double precision subtract.
724 */
725sub_d:
726	jal	get_fs_dbl
727	jal	get_ft_dbl
728	xor	t4, t4, 1			# negate sign bit
729	b	add_sub_d
730/*
731 * Double precision add.
732 */
733add_d:
734	jal	get_fs_dbl
735	jal	get_ft_dbl
736add_sub_d:
737	bne	t1, DEXP_INF, 1f		# is FS an infinity?
738	bne	t5, DEXP_INF, result_fs_d	# if FT is not inf, result=FS
739	bne	t0, t4, invalid_d		# both infinities same sign?
740	b	result_fs_d			# result is in FS
7411:
742	beq	t5, DEXP_INF, result_ft_d	# if FT is inf, result=FT
743	bne	t1, zero, 4f			# is FS a denormalized num?
744	bne	t2, zero, 1f			# is FS zero?
745	beq	t3, zero, 3f
7461:
747	bne	t5, zero, 2f			# is FT a denormalized num?
748	bne	t6, zero, 1f
749	beq	t7, zero, result_fs_d		# FT is zero, result=FS
7501:
751	jal	renorm_fs_d
752	jal	renorm_ft_d
753	b	5f
7542:
755	jal	renorm_fs_d
756	subu	t5, t5, DEXP_BIAS		# unbias FT exponent
757	or	t6, t6, DIMPL_ONE		# set implied one bit
758	b	5f
7593:
760	bne	t5, zero, result_ft_d		# if FT != 0, result=FT
761	bne	t6, zero, result_ft_d
762	bne	t7, zero, result_ft_d
763	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
764	bne	v0, MACH_FPC_ROUND_RM, 1f	# round to -infinity?
765	or	t0, t0, t4			# compute result sign
766	b	result_fs_d
7671:
768	and	t0, t0, t4			# compute result sign
769	b	result_fs_d
7704:
771	bne	t5, zero, 2f			# is FT a denormalized num?
772	bne	t6, zero, 1f
773	beq	t7, zero, result_fs_d		# FT is zero, result=FS
7741:
775	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
776	or	t2, t2, DIMPL_ONE		# set implied one bit
777	jal	renorm_ft_d
778	b	5f
7792:
780	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
781	or	t2, t2, DIMPL_ONE		# set implied one bit
782	subu	t5, t5, DEXP_BIAS		# unbias FT exponent
783	or	t6, t6, DIMPL_ONE		# set implied one bit
784/*
785 * Perform the addition.
786 */
7875:
788	move	t8, zero			# no shifted bits (sticky reg)
789	beq	t1, t5, 4f			# no shift needed
790	subu	v0, t1, t5			# v0 = difference of exponents
791	move	v1, v0				# v1 = abs(difference)
792	bge	v0, zero, 1f
793	negu	v1
7941:
795	ble	v1, DFRAC_BITS+2, 2f		# is difference too great?
796	li	t8, STICKYBIT			# set the sticky bit
797	bge	v0, zero, 1f			# check which exp is larger
798	move	t1, t5				# result exp is FT's
799	move	t2, zero			# FS's fraction shifted is zero
800	move	t3, zero
801	b	4f
8021:
803	move	t6, zero			# FT's fraction shifted is zero
804	move	t7, zero
805	b	4f
8062:
807	li	t9, 32
808	bge	v0, zero, 3f			# if FS > FT, shift FT's frac
809	move	t1, t5				# FT > FS, result exp is FT's
810	blt	v1, t9, 1f			# shift right by < 32?
811	subu	v1, v1, t9
812	subu	t9, t9, v1
813	sll	t8, t2, t9			# save bits shifted out
814	sltu	t9, zero, t3			# don't lose any one bits
815	or	t8, t8, t9			# save sticky bit
816	srl	t3, t2, v1			# shift FS's fraction
817	move	t2, zero
818	b	4f
8191:
820	subu	t9, t9, v1
821	sll	t8, t3, t9			# save bits shifted out
822	srl	t3, t3, v1			# shift FS's fraction
823	sll	t9, t2, t9			# save bits shifted out of t2
824	or	t3, t3, t9			# and put into t3
825	srl	t2, t2, v1
826	b	4f
8273:
828	blt	v1, t9, 1f			# shift right by < 32?
829	subu	v1, v1, t9
830	subu	t9, t9, v1
831	sll	t8, t6, t9			# save bits shifted out
832	srl	t7, t6, v1			# shift FT's fraction
833	move	t6, zero
834	b	4f
8351:
836	subu	t9, t9, v1
837	sll	t8, t7, t9			# save bits shifted out
838	srl	t7, t7, v1			# shift FT's fraction
839	sll	t9, t6, t9			# save bits shifted out of t2
840	or	t7, t7, t9			# and put into t3
841	srl	t6, t6, v1
8424:
843	bne	t0, t4, 1f			# if signs differ, subtract
844	addu	t3, t3, t7			# add fractions
845	sltu	t9, t3, t7			# compute carry
846	addu	t2, t2, t6			# add fractions
847	addu	t2, t2, t9			# add carry
848	b	norm_d
8491:
850	blt	t2, t6, 3f			# subtract larger from smaller
851	bne	t2, t6, 2f
852	bltu	t3, t7, 3f
853	bne	t3, t7, 2f			# if same, result=0
854	move	t1, zero			# result=0
855	move	t2, zero
856	move	t3, zero
857	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
858	bne	v0, MACH_FPC_ROUND_RM, 1f	# round to -infinity?
859	or	t0, t0, t4			# compute result sign
860	b	result_fs_d
8611:
862	and	t0, t0, t4			# compute result sign
863	b	result_fs_d
8642:
865	beq	t8, zero, 1f			# compute t2:t3:zero - t6:t7:t8
866	subu	t8, zero, t8
867	sltu	v0, t3, 1			# compute barrow out
868	subu	t3, t3, 1			# subtract barrow
869	subu	t2, t2, v0
8701:
871	sltu	v0, t3, t7
872	subu	t3, t3, t7			# subtract fractions
873	subu	t2, t2, t6			# subtract fractions
874	subu	t2, t2, v0			# subtract barrow
875	b	norm_d
8763:
877	move	t0, t4				# sign of result = FT's
878	beq	t8, zero, 1f			# compute t6:t7:zero - t2:t3:t8
879	subu	t8, zero, t8
880	sltu	v0, t7, 1			# compute barrow out
881	subu	t7, t7, 1			# subtract barrow
882	subu	t6, t6, v0
8831:
884	sltu	v0, t7, t3
885	subu	t3, t7, t3			# subtract fractions
886	subu	t2, t6, t2			# subtract fractions
887	subu	t2, t2, v0			# subtract barrow
888	b	norm_d
889
890/*
891 * Single precision multiply.
892 */
893mul_s:
894	jal	get_fs_sgl
895	jal	get_ft_sgl
896	xor	t0, t0, t4			# compute sign of result
897	move	t4, t0				# put in FT too
898	bne	t1, SEXP_INF, 1f		# is FS an infinity?
899	beq	t5, SEXP_INF, result_fs_s	# FS is inf, is FT an infinity?
900	bne	t5, zero, result_fs_s		# inf * zero? if no, result=FS
901	beq	t6, zero, invalid_s		# if yes, invalid operation
902	b	result_fs_s
9031:
904	bne	t5, SEXP_INF, 1f		# FS != inf, is FT an infinity?
905	bne	t1, zero, result_ft_s		# zero * inf? if no, result=FT
906	beq	t2, zero, invalid_s		# if yes, invalid operation
907	b	result_ft_s
9081:
909	bne	t1, zero, 1f			# is FS zero?
910	beq	t2, zero, result_fs_s		# result is zero
911	jal	renorm_fs_s
912	b	2f
9131:
914	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
915	or	t2, t2, SIMPL_ONE		# set implied one bit
9162:
917	bne	t5, zero, 1f			# is FT zero?
918	beq	t6, zero, result_ft_s		# result is zero
919	jal	renorm_ft_s
920	b	2f
9211:
922	subu	t5, t5, SEXP_BIAS		# unbias FT exponent
923	or	t6, t6, SIMPL_ONE		# set implied one bit
9242:
925	addu	t1, t1, t5			# compute result exponent
926	addu	t1, t1, 9			# ???
927	multu	t2, t6				# multiply fractions
928	mflo	t8
929	mfhi	t2
930	b	norm_s
931
932/*
933 * Double precision multiply.
934 */
935mul_d:
936	jal	get_fs_dbl
937	jal	get_ft_dbl
938	xor	t0, t0, t4			# compute sign of result
939	move	t4, t0				# put in FT too
940	bne	t1, DEXP_INF, 1f		# is FS an infinity?
941	beq	t5, DEXP_INF, result_fs_d	# FS is inf, is FT an infinity?
942	bne	t5, zero, result_fs_d		# inf * zero? if no, result=FS
943	bne	t6, zero, result_fs_d
944	beq	t7, zero, invalid_d		# if yes, invalid operation
945	b	result_fs_d
9461:
947	bne	t5, DEXP_INF, 1f		# FS != inf, is FT an infinity?
948	bne	t1, zero, result_ft_d		# zero * inf? if no, result=FT
949	bne	t2, zero, result_ft_d
950	beq	t3, zero, invalid_d		# if yes, invalid operation
951	b	result_ft_d
9521:
953	bne	t1, zero, 2f			# is FS zero?
954	bne	t2, zero, 1f
955	beq	t3, zero, result_fs_d		# result is zero
9561:
957	jal	renorm_fs_d
958	b	3f
9592:
960	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
961	or	t2, t2, DIMPL_ONE		# set implied one bit
9623:
963	bne	t5, zero, 2f			# is FT zero?
964	bne	t6, zero, 1f
965	beq	t7, zero, result_ft_d		# result is zero
9661:
967	jal	renorm_ft_d
968	b	3f
9692:
970	subu	t5, t5, DEXP_BIAS		# unbias FT exponent
971	or	t6, t6, DIMPL_ONE		# set implied one bit
9723:
973	addu	t1, t1, t5			# compute result exponent
974	addu	t1, t1, 12			# ???
975	multu	t3, t7				# multiply fractions (low * low)
976	move	t4, t2				# free up t2,t3 for result
977	move	t5, t3
978	mflo	a3				# save low order bits
979	mfhi	t8
980	not	v0, t8
981	multu	t4, t7				# multiply FS(high) * FT(low)
982	mflo	v1
983	mfhi	t3				# init low result
984	sltu	v0, v0, v1			# compute carry
985	addu	t8, v1
986	multu	t5, t6				# multiply FS(low) * FT(high)
987	addu	t3, t3, v0			# add carry
988	not	v0, t8
989	mflo	v1
990	mfhi	t2
991	sltu	v0, v0, v1
992	addu	t8, v1
993	multu	t4, t6				# multiply FS(high) * FT(high)
994	addu	t3, v0
995	not	v1, t3
996	sltu	v1, v1, t2
997	addu	t3, t2
998	not	v0, t3
999	mfhi	t2
1000	addu	t2, v1
1001	mflo	v1
1002	sltu	v0, v0, v1
1003	addu	t2, v0
1004	addu	t3, v1
1005	sltu	a3, zero, a3			# reduce t8,a3 to just t8
1006	or	t8, a3
1007	b	norm_d
1008
1009/*
1010 * Single precision divide.
1011 */
1012div_s:
1013	jal	get_fs_sgl
1014	jal	get_ft_sgl
1015	xor	t0, t0, t4			# compute sign of result
1016	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1017	beq	t5, SEXP_INF, invalid_s		# is FT an infinity?
1018	b	result_fs_s			# result=infinity
10191:
1020	bne	t5, SEXP_INF, 1f		# is FT an infinity?
1021	move	t2, zero			# result = zero
1022	b	result_fs_s
10231:
1024	bne	t1, zero, 2f			# is FS zero?
1025	bne	t2, zero, 1f
1026	bne	t5, zero, result_fs_s		# FS=zero, is FT zero?
1027	beq	t6, zero, invalid_s		# 0 / 0
1028	b	result_fs_s			# result = zero
10291:
1030	jal	renorm_fs_s
1031	b	3f
10322:
1033	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
1034	or	t2, t2, SIMPL_ONE		# set implied one bit
10353:
1036	bne	t5, zero, 2f			# is FT zero?
1037	bne	t6, zero, 1f
1038	or	a1, a1, MACH_FPC_EXCEPTION_DIV0 | MACH_FPC_STICKY_DIV0
1039	and	v0, a1, MACH_FPC_ENABLE_DIV0	# trap enabled?
1040	bne	v0, zero, fpe_trap
1041	ctc1	a1, MACH_FPC_CSR		# save exceptions
1042	li	t1, SEXP_INF			# result is infinity
1043	move	t2, zero
1044	b	result_fs_s
10451:
1046	jal	renorm_ft_s
1047	b	3f
10482:
1049	subu	t5, t5, SEXP_BIAS		# unbias FT exponent
1050	or	t6, t6, SIMPL_ONE		# set implied one bit
10513:
1052	subu	t1, t1, t5			# compute exponent
1053	subu	t1, t1, 3			# compensate for result position
1054	li	v0, SFRAC_BITS+3		# number of bits to divide
1055	move	t8, t2				# init dividend
1056	move	t2, zero			# init result
10571:
1058	bltu	t8, t6, 3f			# is dividend >= divisor?
10592:
1060	subu	t8, t8, t6			# subtract divisor from dividend
1061	or	t2, t2, 1			# remember that we did
1062	bne	t8, zero, 3f			# if not done, continue
1063	sll	t2, t2, v0			# shift result to final position
1064	b	norm_s
10653:
1066	sll	t8, t8, 1			# shift dividend
1067	sll	t2, t2, 1			# shift result
1068	subu	v0, v0, 1			# are we done?
1069	bne	v0, zero, 1b			# no, continue
1070	b	norm_s
1071
1072/*
1073 * Double precision divide.
1074 */
1075div_d:
1076	jal	get_fs_dbl
1077	jal	get_ft_dbl
1078	xor	t0, t0, t4			# compute sign of result
1079	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1080	beq	t5, DEXP_INF, invalid_d		# is FT an infinity?
1081	b	result_fs_d			# result=infinity
10821:
1083	bne	t5, DEXP_INF, 1f		# is FT an infinity?
1084	move	t2, zero			# x / infinity == zero
1085	move	t3, zero
1086	b	result_fs_d
10871:
1088	bne	t1, zero, 2f			# is FS zero?
1089	bne	t2, zero, 1f
1090	bne	t3, zero, 1f
1091	bne	t5, zero, result_fs_d		# FS=zero, is FT zero?
1092	bne	t6, zero, result_fs_d
1093	beq	t7, zero, invalid_d		# 0 / 0
1094	b	result_fs_d			# result = zero
10951:
1096	jal	renorm_fs_d
1097	b	3f
10982:
1099	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
1100	or	t2, t2, DIMPL_ONE		# set implied one bit
11013:
1102	bne	t5, zero, 2f			# is FT zero?
1103	bne	t6, zero, 1f
1104	bne	t7, zero, 1f
1105	or	a1, a1, MACH_FPC_EXCEPTION_DIV0 | MACH_FPC_STICKY_DIV0
1106	and	v0, a1, MACH_FPC_ENABLE_DIV0	# trap enabled?
1107	bne	v0, zero, fpe_trap
1108	ctc1	a1, MACH_FPC_CSR		# Save exceptions
1109	li	t1, DEXP_INF			# result is infinity
1110	move	t2, zero
1111	move	t3, zero
1112	b	result_fs_d
11131:
1114	jal	renorm_ft_d
1115	b	3f
11162:
1117	subu	t5, t5, DEXP_BIAS		# unbias FT exponent
1118	or	t6, t6, DIMPL_ONE		# set implied one bit
11193:
1120	subu	t1, t1, t5			# compute exponent
1121	subu	t1, t1, 3			# compensate for result position
1122	li	v0, DFRAC_BITS+3		# number of bits to divide
1123	move	t8, t2				# init dividend
1124	move	t9, t3
1125	move	t2, zero			# init result
1126	move	t3, zero
11271:
1128	bltu	t8, t6, 3f			# is dividend >= divisor?
1129	bne	t8, t6, 2f
1130	bltu	t9, t7, 3f
11312:
1132	sltu	v1, t9, t7			# subtract divisor from dividend
1133	subu	t9, t9, t7
1134	subu	t8, t8, t6
1135	subu	t8, t8, v1
1136	or	t3, t3, 1			# remember that we did
1137	bne	t8, zero, 3f			# if not done, continue
1138	bne	t9, zero, 3f
1139	li	v1, 32				# shift result to final position
1140	subu	v1, v1, v0
1141	sll	t2, t2, v0			# shift upper part
1142	srl	t9, t3, v1			# save bits shifted out
1143	or	t2, t2, t9			# and put into upper part
1144	sll	t3, t3, v0
1145	b	norm_d
11463:
1147	sll	t8, t8, 1			# shift dividend
1148	srl	v1, t9, 31			# save bit shifted out
1149	or	t8, t8, v1			# and put into upper part
1150	sll	t9, t9, 1
1151	sll	t2, t2, 1			# shift result
1152	srl	v1, t3, 31			# save bit shifted out
1153	or	t2, t2, v1			# and put into upper part
1154	sll	t3, t3, 1
1155	subu	v0, v0, 1			# are we done?
1156	bne	v0, zero, 1b			# no, continue
1157	b	norm_d
1158
1159/*
1160 * Single precision absolute value.
1161 */
1162abs_s:
1163	jal	get_fs_sgl
1164	move	t0, zero			# set sign positive
1165	b	result_fs_s
1166
1167/*
1168 * Double precision absolute value.
1169 */
1170abs_d:
1171	jal	get_fs_dbl
1172	move	t0, zero			# set sign positive
1173	b	result_fs_d
1174
1175/*
1176 * Single precision move.
1177 */
1178mov_s:
1179	jal	get_fs_sgl
1180	b	result_fs_s
1181
1182/*
1183 * Double precision move.
1184 */
1185mov_d:
1186	jal	get_fs_dbl
1187	b	result_fs_d
1188
1189/*
1190 * Single precision negate.
1191 */
1192neg_s:
1193	jal	get_fs_sgl
1194	xor	t0, t0, 1			# reverse sign
1195	b	result_fs_s
1196
1197/*
1198 * Double precision negate.
1199 */
1200neg_d:
1201	jal	get_fs_dbl
1202	xor	t0, t0, 1			# reverse sign
1203	b	result_fs_d
1204
1205/*
1206 * Convert double to single.
1207 */
1208cvt_s_d:
1209	jal	get_fs_dbl
1210	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1211	li	t1, SEXP_INF			# convert to single
1212	sll	t2, t2, 3			# convert D fraction to S
1213	srl	t8, t3, 32 - 3
1214	or	t2, t2, t8
1215	b	result_fs_s
12161:
1217	bne	t1, zero, 2f			# is FS zero?
1218	bne	t2, zero, 1f
1219	beq	t3, zero, result_fs_s		# result=0
12201:
1221	jal	renorm_fs_d
1222	subu	t1, t1, 3			# correct exp for shift below
1223	b	3f
12242:
1225	subu	t1, t1, DEXP_BIAS		# unbias exponent
1226	or	t2, t2, DIMPL_ONE		# add implied one bit
12273:
1228	sll	t2, t2, 3			# convert D fraction to S
1229	srl	t8, t3, 32 - 3
1230	or	t2, t2, t8
1231	sll	t8, t3, 3
1232	b	norm_noshift_s
1233
1234/*
1235 * Convert integer to single.
1236 */
1237cvt_s_w:
1238	jal	get_fs_int
1239	bne	t2, zero, 1f			# check for zero
1240	move	t1, zero
1241	b	result_fs_s
1242/*
1243 * Find out how many leading zero bits are in t2 and put in t9.
1244 */
12451:
1246	move	v0, t2
1247	move	t9, zero
1248	srl	v1, v0, 16
1249	bne	v1, zero, 1f
1250	addu	t9, 16
1251	sll	v0, 16
12521:
1253	srl	v1, v0, 24
1254	bne	v1, zero, 1f
1255	addu	t9, 8
1256	sll	v0, 8
12571:
1258	srl	v1, v0, 28
1259	bne	v1, zero, 1f
1260	addu	t9, 4
1261	sll	v0, 4
12621:
1263	srl	v1, v0, 30
1264	bne	v1, zero, 1f
1265	addu	t9, 2
1266	sll	v0, 2
12671:
1268	srl	v1, v0, 31
1269	bne	v1, zero, 1f
1270	addu	t9, 1
1271/*
1272 * Now shift t2 the correct number of bits.
1273 */
12741:
1275	subu	t9, t9, SLEAD_ZEROS		# don't count leading zeros
1276	li	t1, 23				# init exponent
1277	subu	t1, t1, t9			# compute exponent
1278	beq	t9, zero, 1f
1279	li	v0, 32
1280	blt	t9, zero, 2f			# if shift < 0, shift right
1281	subu	v0, v0, t9
1282	sll	t2, t2, t9			# shift left
12831:
1284	add	t1, t1, SEXP_BIAS		# bias exponent
1285	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1286	b	result_fs_s
12872:
1288	negu	t9				# shift right by t9
1289	subu	v0, v0, t9
1290	sll	t8, t2, v0			# save bits shifted out
1291	srl	t2, t2, t9
1292	b	norm_noshift_s
1293
1294/*
1295 * Convert single to double.
1296 */
1297cvt_d_s:
1298	jal	get_fs_sgl
1299	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1300	li	t1, DEXP_INF			# convert to double
1301	b	2f
13021:
1303	bne	t1, zero, 2f			# is FS denormalized or zero?
1304	beq	t2, zero, result_fs_d		# is FS zero?
1305	jal	renorm_fs_s
1306	move	t8, zero
1307	b	norm_d
13082:
1309	addu	t1, t1, DEXP_BIAS - SEXP_BIAS	# bias exponent correctly
1310	sll	t3, t2, 32 - 3			# convert S fraction to D
1311	srl	t2, t2, 3
1312	b	result_fs_d
1313
1314/*
1315 * Convert integer to double.
1316 */
1317cvt_d_w:
1318	jal	get_fs_int
1319	bne	t2, zero, 1f			# check for zero
1320	move	t1, zero			# result=0
1321	move	t3, zero
1322	b	result_fs_d
1323/*
1324 * Find out how many leading zero bits are in t2 and put in t9.
1325 */
13261:
1327	move	v0, t2
1328	move	t9, zero
1329	srl	v1, v0, 16
1330	bne	v1, zero, 1f
1331	addu	t9, 16
1332	sll	v0, 16
13331:
1334	srl	v1, v0, 24
1335	bne	v1, zero, 1f
1336	addu	t9, 8
1337	sll	v0, 8
13381:
1339	srl	v1, v0, 28
1340	bne	v1, zero, 1f
1341	addu	t9, 4
1342	sll	v0, 4
13431:
1344	srl	v1, v0, 30
1345	bne	v1, zero, 1f
1346	addu	t9, 2
1347	sll	v0, 2
13481:
1349	srl	v1, v0, 31
1350	bne	v1, zero, 1f
1351	addu	t9, 1
1352/*
1353 * Now shift t2 the correct number of bits.
1354 */
13551:
1356	subu	t9, t9, DLEAD_ZEROS		# don't count leading zeros
1357	li	t1, DEXP_BIAS + 23		# init exponent
1358	subu	t1, t1, t9			# compute exponent
1359	beq	t9, zero, 1f
1360	li	v0, 32
1361	blt	t9, zero, 2f			# if shift < 0, shift right
1362	subu	v0, v0, t9
1363	sll	t2, t2, t9			# shift left
13641:
1365	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1366	b	result_fs_d
13672:
1368	negu	t9				# shift right by t9
1369	subu	v0, v0, t9
1370	sll	t3, t2, v0
1371	srl	t2, t2, t9
1372	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1373	b	result_fs_d
1374
1375/*
1376 * Convert single to integer.
1377 */
1378cvt_w_s:
1379	jal	get_fs_sgl
1380	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1381	bne	t2, zero, invalid_w		# invalid conversion
13821:
1383	bne	t1, zero, 1f			# is FS zero?
1384	beq	t2, zero, result_fs_w		# result is zero
1385	move	t2, zero			# result is an inexact zero
1386	b	inexact_w
13871:
1388	subu	t1, t1, SEXP_BIAS		# unbias exponent
1389	or	t2, t2, SIMPL_ONE		# add implied one bit
1390	sll	t3, t2, 32 - 3			# convert S fraction to D
1391	srl	t2, t2, 3
1392	b	cvt_w
1393
1394/*
1395 * Convert double to integer.
1396 */
1397cvt_w_d:
1398	jal	get_fs_dbl
1399	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1400	bne	t2, zero, invalid_w		# invalid conversion
1401	bne	t3, zero, invalid_w		# invalid conversion
14021:
1403	bne	t1, zero, 2f			# is FS zero?
1404	bne	t2, zero, 1f
1405	beq	t3, zero, result_fs_w		# result is zero
14061:
1407	move	t2, zero			# result is an inexact zero
1408	b	inexact_w
14092:
1410	subu	t1, t1, DEXP_BIAS		# unbias exponent
1411	or	t2, t2, DIMPL_ONE		# add implied one bit
1412cvt_w:
1413	blt	t1, WEXP_MIN, underflow_w	# is exponent too small?
1414	li	v0, WEXP_MAX+1
1415	bgt	t1, v0, overflow_w		# is exponent too large?
1416	bne	t1, v0, 1f			# special check for INT_MIN
1417	beq	t0, zero, overflow_w		# if positive, overflow
1418	bne	t2, DIMPL_ONE, overflow_w
1419	bne	t3, zero, overflow_w
1420	li	t2, INT_MIN			# result is INT_MIN
1421	b	result_fs_w
14221:
1423	subu	v0, t1, 20			# compute amount to shift
1424	beq	v0, zero, 2f			# is shift needed?
1425	li	v1, 32
1426	blt	v0, zero, 1f			# if shift < 0, shift right
1427	subu	v1, v1, v0			# shift left
1428	sll	t2, t2, v0
1429	srl	t9, t3, v1			# save bits shifted out of t3
1430	or	t2, t2, t9			# and put into t2
1431	sll	t3, t3, v0			# shift FS's fraction
1432	b	2f
14331:
1434	negu	v0				# shift right by v0
1435	subu	v1, v1, v0
1436	sll	t8, t3, v1			# save bits shifted out
1437	sltu	t8, zero, t8			# don't lose any one's
1438	srl	t3, t3, v0			# shift FS's fraction
1439	or	t3, t3, t8
1440	sll	t9, t2, v1			# save bits shifted out of t2
1441	or	t3, t3, t9			# and put into t3
1442	srl	t2, t2, v0
1443/*
1444 * round result (t0 is sign, t2 is integer part, t3 is fractional part).
1445 */
14462:
1447	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1448	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1449	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
1450	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1451	beq	t0, zero, 5f			# if sign is positive, truncate
1452	b	2f
14531:
1454	bne	t0, zero, 5f			# if sign is negative, truncate
14552:
1456	beq	t3, zero, 5f			# if no fraction bits, continue
1457	addu	t2, t2, 1			# add rounding bit
1458	blt	t2, zero, overflow_w		# overflow?
1459	b	5f
14603:
1461	li	v0, GUARDBIT			# load guard bit for rounding
1462	addu	v0, v0, t3			# add remainder
1463	sltu	v1, v0, t3			# compute carry out
1464	beq	v1, zero, 4f			# if no carry, continue
1465	addu	t2, t2, 1			# add carry to result
1466	blt	t2, zero, overflow_w		# overflow?
14674:
1468	bne	v0, zero, 5f			# if rounded remainder is zero
1469	and	t2, t2, ~1			#  clear LSB (round to nearest)
14705:
1471	beq	t0, zero, 1f			# result positive?
1472	negu	t2				# convert to negative integer
14731:
1474	beq	t3, zero, result_fs_w		# is result exact?
1475/*
1476 * Handle inexact exception.
1477 */
1478inexact_w:
1479	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
1480	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1481	bne	v0, zero, fpe_trap
1482	ctc1	a1, MACH_FPC_CSR		# save exceptions
1483	b	result_fs_w
1484
1485/*
1486 * Conversions to integer which overflow will trap (if enabled),
1487 * or generate an inexact trap (if enabled),
1488 * or generate an invalid exception.
1489 */
1490overflow_w:
1491	or	a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW
1492	and	v0, a1, MACH_FPC_ENABLE_OVERFLOW
1493	bne	v0, zero, fpe_trap
1494	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1495	bne	v0, zero, inexact_w		# inexact traps enabled?
1496	b	invalid_w
1497
1498/*
1499 * Conversions to integer which underflow will trap (if enabled),
1500 * or generate an inexact trap (if enabled),
1501 * or generate an invalid exception.
1502 */
1503underflow_w:
1504	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
1505	and	v0, a1, MACH_FPC_ENABLE_UNDERFLOW
1506	bne	v0, zero, fpe_trap
1507	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1508	bne	v0, zero, inexact_w		# inexact traps enabled?
1509	b	invalid_w
1510
1511/*
1512 * Compare single.
1513 */
1514cmp_s:
1515	jal	get_fs_sgl
1516	jal	get_ft_sgl
1517	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1518	bne	t2, zero, unordered		# FS is a NAN
1519	b	2f
15201:
1521	bne	t5, SEXP_INF, 2f		# is FT an infinity?
1522	bne	t6, zero, unordered		# FT is a NAN
15232:
1524	sll	t1, t1, 23			# reassemble exp & frac
1525	or	t1, t1, t2
1526	sll	t5, t5, 23			# reassemble exp & frac
1527	or	t5, t5, t6
1528	beq	t0, zero, 1f			# is FS positive?
1529	negu	t1
15301:
1531	beq	t4, zero, 1f			# is FT positive?
1532	negu	t5
15331:
1534	li	v0, COND_LESS
1535	blt	t1, t5, test_cond		# is FS < FT?
1536	li	v0, COND_EQUAL
1537	beq	t1, t5, test_cond		# is FS == FT?
1538	move	v0, zero			# FS > FT
1539	b	test_cond
1540
1541/*
1542 * Compare double.
1543 */
1544cmp_d:
1545	jal	get_fs_dbl
1546	jal	get_ft_dbl
1547	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1548	bne	t2, zero, unordered
1549	bne	t3, zero, unordered		# FS is a NAN
1550	b	2f
15511:
1552	bne	t5, DEXP_INF, 2f		# is FT an infinity?
1553	bne	t6, zero, unordered
1554	bne	t7, zero, unordered		# FT is a NAN
15552:
1556	sll	t1, t1, 20			# reassemble exp & frac
1557	or	t1, t1, t2
1558	sll	t5, t5, 20			# reassemble exp & frac
1559	or	t5, t5, t6
1560	beq	t0, zero, 1f			# is FS positive?
1561	not	t3				# negate t1,t3
1562	not	t1
1563	addu	t3, t3, 1
1564	seq	v0, t3, zero			# compute carry
1565	addu	t1, t1, v0
15661:
1567	beq	t4, zero, 1f			# is FT positive?
1568	not	t7				# negate t5,t7
1569	not	t5
1570	addu	t7, t7, 1
1571	seq	v0, t7, zero			# compute carry
1572	addu	t5, t5, v0
15731:
1574	li	v0, COND_LESS
1575	blt	t1, t5, test_cond		# is FS(MSW) < FT(MSW)?
1576	move	v0, zero
1577	bne	t1, t5, test_cond		# is FS(MSW) > FT(MSW)?
1578	li	v0, COND_LESS
1579	bltu	t3, t7, test_cond		# is FS(LSW) < FT(LSW)?
1580	li	v0, COND_EQUAL
1581	beq	t3, t7, test_cond		# is FS(LSW) == FT(LSW)?
15821:
1583	move	v0, zero			# FS > FT
1584
1585test_cond:
1586	and	v0, v0, a0			# condition match instruction?
1587	b	set_cond
1588unordered:
1589	and	v0, a0, COND_SIGNAL
1590	beq	v0, zero, 1f			# is this a signalling cmp?
1591	or	a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID
1592	and	v0, a1, MACH_FPC_ENABLE_INVALID
1593	bne	v0, zero, fpe_trap
15941:
1595	and	v0, a0, COND_UNORDERED		# this cmp match unordered?
1596set_cond:
1597	bne	v0, zero, 1f
1598	and	a1, a1, ~MACH_FPC_COND_BIT	# clear condition bit
1599	b	2f
16001:
1601	or	a1, a1, MACH_FPC_COND_BIT	# set condition bit
16022:
1603	ctc1	a1, MACH_FPC_CSR		# save condition bit
1604	b	done
1605
1606/*
1607 * Determine the amount to shift the fraction in order to restore the
1608 * normalized position. After that, round and handle exceptions.
1609 */
1610norm_s:
1611	move	v0, t2
1612	move	t9, zero			# t9 = num of leading zeros
1613	bne	t2, zero, 1f
1614	move	v0, t8
1615	addu	t9, 32
16161:
1617	srl	v1, v0, 16
1618	bne	v1, zero, 1f
1619	addu	t9, 16
1620	sll	v0, 16
16211:
1622	srl	v1, v0, 24
1623	bne	v1, zero, 1f
1624	addu	t9, 8
1625	sll	v0, 8
16261:
1627	srl	v1, v0, 28
1628	bne	v1, zero, 1f
1629	addu	t9, 4
1630	sll	v0, 4
16311:
1632	srl	v1, v0, 30
1633	bne	v1, zero, 1f
1634	addu	t9, 2
1635	sll	v0, 2
16361:
1637	srl	v1, v0, 31
1638	bne	v1, zero, 1f
1639	addu	t9, 1
1640/*
1641 * Now shift t2,t8 the correct number of bits.
1642 */
16431:
1644	subu	t9, t9, SLEAD_ZEROS		# don't count leading zeros
1645	subu	t1, t1, t9			# adjust the exponent
1646	beq	t9, zero, norm_noshift_s
1647	li	v1, 32
1648	blt	t9, zero, 1f			# if shift < 0, shift right
1649	subu	v1, v1, t9
1650	sll	t2, t2, t9			# shift t2,t8 left
1651	srl	v0, t8, v1			# save bits shifted out
1652	or	t2, t2, v0
1653	sll	t8, t8, t9
1654	b	norm_noshift_s
16551:
1656	negu	t9				# shift t2,t8 right by t9
1657	subu	v1, v1, t9
1658	sll	v0, t8, v1			# save bits shifted out
1659	sltu	v0, zero, v0			# be sure to save any one bits
1660	srl	t8, t8, t9
1661	or	t8, t8, v0
1662	sll	v0, t2, v1			# save bits shifted out
1663	or	t8, t8, v0
1664	srl	t2, t2, t9
1665norm_noshift_s:
1666	move	t5, t1				# save unrounded exponent
1667	move	t6, t2				# save unrounded fraction
1668	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1669	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1670	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
1671	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1672	beq	t0, zero, 5f			# if sign is positive, truncate
1673	b	2f
16741:
1675	bne	t0, zero, 5f			# if sign is negative, truncate
16762:
1677	beq	t8, zero, 5f			# if exact, continue
1678	addu	t2, t2, 1			# add rounding bit
1679	bne	t2, SIMPL_ONE<<1, 5f		# need to adjust exponent?
1680	addu	t1, t1, 1			# adjust exponent
1681	srl	t2, t2, 1			# renormalize fraction
1682	b	5f
16833:
1684	li	v0, GUARDBIT			# load guard bit for rounding
1685	addu	v0, v0, t8			# add remainder
1686	sltu	v1, v0, t8			# compute carry out
1687	beq	v1, zero, 4f			# if no carry, continue
1688	addu	t2, t2, 1			# add carry to result
1689	bne	t2, SIMPL_ONE<<1, 4f		# need to adjust exponent?
1690	addu	t1, t1, 1			# adjust exponent
1691	srl	t2, t2, 1			# renormalize fraction
16924:
1693	bne	v0, zero, 5f			# if rounded remainder is zero
1694	and	t2, t2, ~1			#  clear LSB (round to nearest)
16955:
1696	bgt	t1, SEXP_MAX, overflow_s	# overflow?
1697	blt	t1, SEXP_MIN, underflow_s	# underflow?
1698	bne	t8, zero, inexact_s		# is result inexact?
1699	addu	t1, t1, SEXP_BIAS		# bias exponent
1700	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1701	b	result_fs_s
1702
1703/*
1704 * Handle inexact exception.
1705 */
1706inexact_s:
1707	addu	t1, t1, SEXP_BIAS		# bias exponent
1708	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1709inexact_nobias_s:
1710	jal	set_fd_sgl			# save result
1711	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
1712	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1713	bne	v0, zero, fpe_trap
1714	ctc1	a1, MACH_FPC_CSR		# save exceptions
1715	b	done
1716
1717/*
1718 * Overflow will trap (if enabled),
1719 * or generate an inexact trap (if enabled),
1720 * or generate an infinity.
1721 */
1722overflow_s:
1723	or	a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW
1724	and	v0, a1, MACH_FPC_ENABLE_OVERFLOW
1725	beq	v0, zero, 1f
1726	subu	t1, t1, 192			# bias exponent
1727	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1728	jal	set_fd_sgl			# save result
1729	b	fpe_trap
17301:
1731	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1732	beq	v0, MACH_FPC_ROUND_RN, 5f	# round to nearest
1733	beq	v0, MACH_FPC_ROUND_RZ, 1f	# round to zero (truncate)
1734	beq	v0, MACH_FPC_ROUND_RP, 3f	# round to +infinity
1735	bne	t0, zero, 2f
17361:
1737	li	t1, SEXP_MAX			# result is max finite
1738	li	t2, 0x007fffff
1739	b	inexact_s
17402:
1741	li	t1, SEXP_MIN - 1		# result is -infinity
1742	move	t2, zero
1743	b	inexact_s
17443:
1745	bne	t0, zero, 1b
17464:
1747	li	t1, SEXP_MAX + 1		# result is +infinity
1748	move	t2, zero
1749	b	inexact_s
17505:
1751	bne	t0, zero, 2b
1752	b	4b
1753
1754/*
1755 * In this implementation, "tininess" is detected "after rounding" and
1756 * "loss of accuracy" is detected as "an inexact result".
1757 */
1758underflow_s:
1759	and	v0, a1, MACH_FPC_ENABLE_UNDERFLOW
1760	beq	v0, zero, 1f
1761/*
1762 * Underflow is enabled so compute the result and trap.
1763 */
1764	addu	t1, t1, 192			# bias exponent
1765	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1766	jal	set_fd_sgl			# save result
1767	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
1768	b	fpe_trap
1769/*
1770 * Underflow is not enabled so compute the result,
1771 * signal inexact result (if it is) and trap (if enabled).
1772 */
17731:
1774	move	t1, t5				# get unrounded exponent
1775	move	t2, t6				# get unrounded fraction
1776	li	t9, SEXP_MIN			# compute shift amount
1777	subu	t9, t9, t1			# shift t2,t8 right by t9
1778	blt	t9, SFRAC_BITS+2, 1f		# shift all the bits out?
1779	move	t1, zero			# result is inexact zero
1780	move	t2, zero
1781	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
1782	b	inexact_nobias_s
17831:
1784	li	v1, 32
1785	subu	v1, v1, t9
1786	sll	t8, t2, v1			# save bits shifted out
1787	srl	t2, t2, t9
1788/*
1789 * Now round the denormalized result.
1790 */
1791	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1792	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1793	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
1794	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1795	beq	t0, zero, 5f			# if sign is positive, truncate
1796	b	2f
17971:
1798	bne	t0, zero, 5f			# if sign is negative, truncate
17992:
1800	beq	t8, zero, 5f			# if exact, continue
1801	addu	t2, t2, 1			# add rounding bit
1802	b	5f
18033:
1804	li	v0, GUARDBIT			# load guard bit for rounding
1805	addu	v0, v0, t8			# add remainder
1806	sltu	v1, v0, t8			# compute carry out
1807	beq	v1, zero, 4f			# if no carry, continue
1808	addu	t2, t2, 1			# add carry to result
18094:
1810	bne	v0, zero, 5f			# if rounded remainder is zero
1811	and	t2, t2, ~1			#  clear LSB (round to nearest)
18125:
1813	move	t1, zero			# denorm or zero exponent
1814	jal	set_fd_sgl			# save result
1815	beq	t8, zero, done			# check for exact result
1816	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
1817	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
1818	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1819	bne	v0, zero, fpe_trap
1820	ctc1	a1, MACH_FPC_CSR		# save exceptions
1821	b	done
1822
1823/*
1824 * Determine the amount to shift the fraction in order to restore the
1825 * normalized position. After that, round and handle exceptions.
1826 */
1827norm_d:
1828	move	v0, t2
1829	move	t9, zero			# t9 = num of leading zeros
1830	bne	t2, zero, 1f
1831	move	v0, t3
1832	addu	t9, 32
1833	bne	t3, zero, 1f
1834	move	v0, t8
1835	addu	t9, 32
18361:
1837	srl	v1, v0, 16
1838	bne	v1, zero, 1f
1839	addu	t9, 16
1840	sll	v0, 16
18411:
1842	srl	v1, v0, 24
1843	bne	v1, zero, 1f
1844	addu	t9, 8
1845	sll	v0, 8
18461:
1847	srl	v1, v0, 28
1848	bne	v1, zero, 1f
1849	addu	t9, 4
1850	sll	v0, 4
18511:
1852	srl	v1, v0, 30
1853	bne	v1, zero, 1f
1854	addu	t9, 2
1855	sll	v0, 2
18561:
1857	srl	v1, v0, 31
1858	bne	v1, zero, 1f
1859	addu	t9, 1
1860/*
1861 * Now shift t2,t3,t8 the correct number of bits.
1862 */
18631:
1864	subu	t9, t9, DLEAD_ZEROS		# don't count leading zeros
1865	subu	t1, t1, t9			# adjust the exponent
1866	beq	t9, zero, norm_noshift_d
1867	li	v1, 32
1868	blt	t9, zero, 2f			# if shift < 0, shift right
1869	blt	t9, v1, 1f			# shift by < 32?
1870	subu	t9, t9, v1			# shift by >= 32
1871	subu	v1, v1, t9
1872	sll	t2, t3, t9			# shift left by t9
1873	srl	v0, t8, v1			# save bits shifted out
1874	or	t2, t2, v0
1875	sll	t3, t8, t9
1876	move	t8, zero
1877	b	norm_noshift_d
18781:
1879	subu	v1, v1, t9
1880	sll	t2, t2, t9			# shift left by t9
1881	srl	v0, t3, v1			# save bits shifted out
1882	or	t2, t2, v0
1883	sll	t3, t3, t9
1884	srl	v0, t8, v1			# save bits shifted out
1885	or	t3, t3, v0
1886	sll	t8, t8, t9
1887	b	norm_noshift_d
18882:
1889	negu	t9				# shift right by t9
1890	subu	v1, v1, t9			#  (known to be < 32 bits)
1891	sll	v0, t8, v1			# save bits shifted out
1892	sltu	v0, zero, v0			# be sure to save any one bits
1893	srl	t8, t8, t9
1894	or	t8, t8, v0
1895	sll	v0, t3, v1			# save bits shifted out
1896	or	t8, t8, v0
1897	srl	t3, t3, t9
1898	sll	v0, t2, v1			# save bits shifted out
1899	or	t3, t3, v0
1900	srl	t2, t2, t9
1901norm_noshift_d:
1902	move	t5, t1				# save unrounded exponent
1903	move	t6, t2				# save unrounded fraction (MS)
1904	move	t7, t3				# save unrounded fraction (LS)
1905	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1906	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
1907	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
1908	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
1909	beq	t0, zero, 5f			# if sign is positive, truncate
1910	b	2f
19111:
1912	bne	t0, zero, 5f			# if sign is negative, truncate
19132:
1914	beq	t8, zero, 5f			# if exact, continue
1915	addu	t3, t3, 1			# add rounding bit
1916	bne	t3, zero, 5f			# branch if no carry
1917	addu	t2, t2, 1			# add carry
1918	bne	t2, DIMPL_ONE<<1, 5f		# need to adjust exponent?
1919	addu	t1, t1, 1			# adjust exponent
1920	srl	t2, t2, 1			# renormalize fraction
1921	b	5f
19223:
1923	li	v0, GUARDBIT			# load guard bit for rounding
1924	addu	v0, v0, t8			# add remainder
1925	sltu	v1, v0, t8			# compute carry out
1926	beq	v1, zero, 4f			# branch if no carry
1927	addu	t3, t3, 1			# add carry
1928	bne	t3, zero, 4f			# branch if no carry
1929	addu	t2, t2, 1			# add carry to result
1930	bne	t2, DIMPL_ONE<<1, 4f		# need to adjust exponent?
1931	addu	t1, t1, 1			# adjust exponent
1932	srl	t2, t2, 1			# renormalize fraction
19334:
1934	bne	v0, zero, 5f			# if rounded remainder is zero
1935	and	t3, t3, ~1			#  clear LSB (round to nearest)
19365:
1937	bgt	t1, DEXP_MAX, overflow_d	# overflow?
1938	blt	t1, DEXP_MIN, underflow_d	# underflow?
1939	bne	t8, zero, inexact_d		# is result inexact?
1940	addu	t1, t1, DEXP_BIAS		# bias exponent
1941	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1942	b	result_fs_d
1943
1944/*
1945 * Handle inexact exception.
1946 */
1947inexact_d:
1948	addu	t1, t1, DEXP_BIAS		# bias exponent
1949	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1950inexact_nobias_d:
1951	jal	set_fd_dbl			# save result
1952	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
1953	and	v0, a1, MACH_FPC_ENABLE_INEXACT
1954	bne	v0, zero, fpe_trap
1955	ctc1	a1, MACH_FPC_CSR		# save exceptions
1956	b	done
1957
1958/*
1959 * Overflow will trap (if enabled),
1960 * or generate an inexact trap (if enabled),
1961 * or generate an infinity.
1962 */
1963overflow_d:
1964	or	a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW
1965	and	v0, a1, MACH_FPC_ENABLE_OVERFLOW
1966	beq	v0, zero, 1f
1967	subu	t1, t1, 1536			# bias exponent
1968	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1969	jal	set_fd_dbl			# save result
1970	b	fpe_trap
19711:
1972	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
1973	beq	v0, MACH_FPC_ROUND_RN, 5f	# round to nearest
1974	beq	v0, MACH_FPC_ROUND_RZ, 1f	# round to zero (truncate)
1975	beq	v0, MACH_FPC_ROUND_RP, 3f	# round to +infinity
1976	bne	t0, zero, 2f
19771:
1978	li	t1, DEXP_MAX			# result is max finite
1979	li	t2, 0x000fffff
1980	li	t3, 0xffffffff
1981	b	inexact_d
19822:
1983	li	t1, DEXP_MIN - 1		# result is -infinity
1984	move	t2, zero
1985	move	t3, zero
1986	b	inexact_d
19873:
1988	bne	t0, zero, 1b
19894:
1990	li	t1, DEXP_MAX + 1		# result is +infinity
1991	move	t2, zero
1992	move	t3, zero
1993	b	inexact_d
19945:
1995	bne	t0, zero, 2b
1996	b	4b
1997
1998/*
1999 * In this implementation, "tininess" is detected "after rounding" and
2000 * "loss of accuracy" is detected as "an inexact result".
2001 */
2002underflow_d:
2003	and	v0, a1, MACH_FPC_ENABLE_UNDERFLOW
2004	beq	v0, zero, 1f
2005/*
2006 * Underflow is enabled so compute the result and trap.
2007 */
2008	addu	t1, t1, 1536			# bias exponent
2009	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2010	jal	set_fd_dbl			# save result
2011	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
2012	b	fpe_trap
2013/*
2014 * Underflow is not enabled so compute the result,
2015 * signal inexact result (if it is) and trap (if enabled).
2016 */
20171:
2018	move	t1, t5				# get unrounded exponent
2019	move	t2, t6				# get unrounded fraction (MS)
2020	move	t3, t7				# get unrounded fraction (LS)
2021	li	t9, DEXP_MIN			# compute shift amount
2022	subu	t9, t9, t1			# shift t2,t8 right by t9
2023	blt	t9, DFRAC_BITS+2, 1f		# shift all the bits out?
2024	move	t1, zero			# result is inexact zero
2025	move	t2, zero
2026	move	t3, zero
2027	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
2028	b	inexact_nobias_d
20291:
2030	li	v1, 32
2031	blt	t9, v1, 1f			# shift by < 32?
2032	subu	t9, t9, v1			# shift right by >= 32
2033	subu	v1, v1, t9
2034	sll	t8, t2, v1			# save bits shifted out
2035	srl	t3, t2, t9
2036	move	t2, zero
2037	b	2f
20381:
2039	subu	v1, v1, t9			# shift right by t9
2040	sll	t8, t3, v1			# save bits shifted out
2041	srl	t3, t3, t9
2042	sll	v0, t2, v1			# save bits shifted out
2043	or	t3, t3, v0
2044	srl	t2, t2, t9
2045/*
2046 * Now round the denormalized result.
2047 */
20482:
2049	and	v0, a1, MACH_FPC_ROUNDING_BITS	# get rounding mode
2050	beq	v0, MACH_FPC_ROUND_RN, 3f	# round to nearest
2051	beq	v0, MACH_FPC_ROUND_RZ, 5f	# round to zero (truncate)
2052	beq	v0, MACH_FPC_ROUND_RP, 1f	# round to +infinity
2053	beq	t0, zero, 5f			# if sign is positive, truncate
2054	b	2f
20551:
2056	bne	t0, zero, 5f			# if sign is negative, truncate
20572:
2058	beq	t8, zero, 5f			# if exact, continue
2059	addu	t3, t3, 1			# add rounding bit
2060	bne	t3, zero, 5f			# if no carry, continue
2061	addu	t2, t2, 1			# add carry
2062	b	5f
20633:
2064	li	v0, GUARDBIT			# load guard bit for rounding
2065	addu	v0, v0, t8			# add remainder
2066	sltu	v1, v0, t8			# compute carry out
2067	beq	v1, zero, 4f			# if no carry, continue
2068	addu	t3, t3, 1			# add rounding bit
2069	bne	t3, zero, 4f			# if no carry, continue
2070	addu	t2, t2, 1			# add carry
20714:
2072	bne	v0, zero, 5f			# if rounded remainder is zero
2073	and	t3, t3, ~1			#  clear LSB (round to nearest)
20745:
2075	move	t1, zero			# denorm or zero exponent
2076	jal	set_fd_dbl			# save result
2077	beq	t8, zero, done			# check for exact result
2078	or	a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW
2079	or	a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT
2080	and	v0, a1, MACH_FPC_ENABLE_INEXACT
2081	bne	v0, zero, fpe_trap
2082	ctc1	a1, MACH_FPC_CSR		# save exceptions
2083	b	done
2084
2085/*
2086 * Signal an invalid operation if the trap is enabled; otherwise,
2087 * the result is a quiet NAN.
2088 */
2089invalid_s:					# trap invalid operation
2090	or	a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID
2091	and	v0, a1, MACH_FPC_ENABLE_INVALID
2092	bne	v0, zero, fpe_trap
2093	ctc1	a1, MACH_FPC_CSR		# save exceptions
2094	move	t0, zero			# result is a quiet NAN
2095	li	t1, SEXP_INF
2096	li	t2, SQUIET_NAN
2097	jal	set_fd_sgl			# save result (in t0,t1,t2)
2098	b	done
2099
2100/*
2101 * Signal an invalid operation if the trap is enabled; otherwise,
2102 * the result is a quiet NAN.
2103 */
2104invalid_d:					# trap invalid operation
2105	or	a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID
2106	and	v0, a1, MACH_FPC_ENABLE_INVALID
2107	bne	v0, zero, fpe_trap
2108	ctc1	a1, MACH_FPC_CSR		# save exceptions
2109	move	t0, zero			# result is a quiet NAN
2110	li	t1, DEXP_INF
2111	li	t2, DQUIET_NAN0
2112	li	t3, DQUIET_NAN1
2113	jal	set_fd_dbl			# save result (in t0,t1,t2,t3)
2114	b	done
2115
2116/*
2117 * Signal an invalid operation if the trap is enabled; otherwise,
2118 * the result is INT_MAX or INT_MIN.
2119 */
2120invalid_w:					# trap invalid operation
2121	or	a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID
2122	and	v0, a1, MACH_FPC_ENABLE_INVALID
2123	bne	v0, zero, fpe_trap
2124	ctc1	a1, MACH_FPC_CSR		# save exceptions
2125	bne	t0, zero, 1f
2126	li	t2, INT_MAX			# result is INT_MAX
2127	b	result_fs_w
21281:
2129	li	t2, INT_MIN			# result is INT_MIN
2130	b	result_fs_w
2131
2132/*
2133 * Trap if the hardware should have handled this case.
2134 */
2135fpe_trap:
2136	move	a2, a1				# code = FP CSR
2137	ctc1	a1, MACH_FPC_CSR		# save exceptions
2138	lw	a0, curproc			# get current process
2139	li	a1, SIGFPE
2140	jal	trapsignal
2141	b	done
2142
2143/*
2144 * Send an illegal instruction signal to the current process.
2145 */
2146ill:
2147	ctc1	a1, MACH_FPC_CSR		# save exceptions
2148	move	a2, a0				# code = FP instruction
2149	lw	a0, curproc			# get current process
2150	li	a1, SIGILL
2151	jal	trapsignal
2152	b	done
2153
2154result_ft_s:
2155	move	t0, t4				# result is FT
2156	move	t1, t5
2157	move	t2, t6
2158result_fs_s:					# result is FS
2159	jal	set_fd_sgl			# save result (in t0,t1,t2)
2160	b	done
2161
2162result_fs_w:
2163	jal	set_fd_word			# save result (in t2)
2164	b	done
2165
2166result_ft_d:
2167	move	t0, t4				# result is FT
2168	move	t1, t5
2169	move	t2, t6
2170	move	t3, t7
2171result_fs_d:					# result is FS
2172	jal	set_fd_dbl			# save result (in t0,t1,t2,t3)
2173
2174done:
2175	lw	ra, STAND_RA_OFFSET(sp)
2176	addu	sp, sp, STAND_FRAME_SIZE
2177	j	ra
2178END(MachEmulateFP)
2179
2180/*----------------------------------------------------------------------------
2181 * get_fs_sgl --
2182 *
2183 *	Read (single precision) the FS register (bits 15-11) and
2184 *	break up into fields.
2185 *	This is an internal routine used by MachEmulateFP only.
2186 *
2187 * Results:
2188 *	t0	contains the sign
2189 *	t1	contains the (biased) exponent
2190 *	t2	contains the fraction
2191 *
2192 *----------------------------------------------------------------------------
2193 */
2194LEAF(get_fs_sgl)
2195	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2196	and	a3, a3, 0xF << 2		# mask FS field
2197	lw	a3, get_fs_sgl_tbl(a3)		# switch on register number
2198	j	a3
2199
2200	.rdata
2201get_fs_sgl_tbl:
2202	.word	get_fs_sgl_f0
2203	.word	get_fs_sgl_f2
2204	.word	get_fs_sgl_f4
2205	.word	get_fs_sgl_f6
2206	.word	get_fs_sgl_f8
2207	.word	get_fs_sgl_f10
2208	.word	get_fs_sgl_f12
2209	.word	get_fs_sgl_f14
2210	.word	get_fs_sgl_f16
2211	.word	get_fs_sgl_f18
2212	.word	get_fs_sgl_f20
2213	.word	get_fs_sgl_f22
2214	.word	get_fs_sgl_f24
2215	.word	get_fs_sgl_f26
2216	.word	get_fs_sgl_f28
2217	.word	get_fs_sgl_f30
2218	.text
2219
2220get_fs_sgl_f0:
2221	mfc1	t0, $f0
2222	b	get_fs_sgl_done
2223get_fs_sgl_f2:
2224	mfc1	t0, $f2
2225	b	get_fs_sgl_done
2226get_fs_sgl_f4:
2227	mfc1	t0, $f4
2228	b	get_fs_sgl_done
2229get_fs_sgl_f6:
2230	mfc1	t0, $f6
2231	b	get_fs_sgl_done
2232get_fs_sgl_f8:
2233	mfc1	t0, $f8
2234	b	get_fs_sgl_done
2235get_fs_sgl_f10:
2236	mfc1	t0, $f10
2237	b	get_fs_sgl_done
2238get_fs_sgl_f12:
2239	mfc1	t0, $f12
2240	b	get_fs_sgl_done
2241get_fs_sgl_f14:
2242	mfc1	t0, $f14
2243	b	get_fs_sgl_done
2244get_fs_sgl_f16:
2245	mfc1	t0, $f16
2246	b	get_fs_sgl_done
2247get_fs_sgl_f18:
2248	mfc1	t0, $f18
2249	b	get_fs_sgl_done
2250get_fs_sgl_f20:
2251	mfc1	t0, $f20
2252	b	get_fs_sgl_done
2253get_fs_sgl_f22:
2254	mfc1	t0, $f22
2255	b	get_fs_sgl_done
2256get_fs_sgl_f24:
2257	mfc1	t0, $f24
2258	b	get_fs_sgl_done
2259get_fs_sgl_f26:
2260	mfc1	t0, $f26
2261	b	get_fs_sgl_done
2262get_fs_sgl_f28:
2263	mfc1	t0, $f28
2264	b	get_fs_sgl_done
2265get_fs_sgl_f30:
2266	mfc1	t0, $f30
2267get_fs_sgl_done:
2268	srl	t1, t0, 23			# get exponent
2269	and	t1, t1, 0xFF
2270	and	t2, t0, 0x7FFFFF		# get fraction
2271	srl	t0, t0, 31			# get sign
2272	bne	t1, SEXP_INF, 1f		# is it a signalling NAN?
2273	and	v0, t2, SSIGNAL_NAN
2274	bne	v0, zero, invalid_s
22751:
2276	j	ra
2277END(get_fs_sgl)
2278
2279/*----------------------------------------------------------------------------
2280 * get_fs_dbl --
2281 *
2282 *	Read (double precision) the FS register (bits 15-11) and
2283 *	break up into fields.
2284 *	This is an internal routine used by MachEmulateFP only.
2285 *
2286 * Results:
2287 *	t0	contains the sign
2288 *	t1	contains the (biased) exponent
2289 *	t2	contains the fraction
2290 *	t3	contains the remaining fraction
2291 *
2292 *----------------------------------------------------------------------------
2293 */
2294LEAF(get_fs_dbl)
2295	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2296	and	a3, a3, 0xF << 2		# mask FS field
2297	lw	a3, get_fs_dbl_tbl(a3)		# switch on register number
2298	j	a3
2299
2300	.rdata
2301get_fs_dbl_tbl:
2302	.word	get_fs_dbl_f0
2303	.word	get_fs_dbl_f2
2304	.word	get_fs_dbl_f4
2305	.word	get_fs_dbl_f6
2306	.word	get_fs_dbl_f8
2307	.word	get_fs_dbl_f10
2308	.word	get_fs_dbl_f12
2309	.word	get_fs_dbl_f14
2310	.word	get_fs_dbl_f16
2311	.word	get_fs_dbl_f18
2312	.word	get_fs_dbl_f20
2313	.word	get_fs_dbl_f22
2314	.word	get_fs_dbl_f24
2315	.word	get_fs_dbl_f26
2316	.word	get_fs_dbl_f28
2317	.word	get_fs_dbl_f30
2318	.text
2319
2320get_fs_dbl_f0:
2321	mfc1	t3, $f0
2322	mfc1	t0, $f1
2323	b	get_fs_dbl_done
2324get_fs_dbl_f2:
2325	mfc1	t3, $f2
2326	mfc1	t0, $f3
2327	b	get_fs_dbl_done
2328get_fs_dbl_f4:
2329	mfc1	t3, $f4
2330	mfc1	t0, $f5
2331	b	get_fs_dbl_done
2332get_fs_dbl_f6:
2333	mfc1	t3, $f6
2334	mfc1	t0, $f7
2335	b	get_fs_dbl_done
2336get_fs_dbl_f8:
2337	mfc1	t3, $f8
2338	mfc1	t0, $f9
2339	b	get_fs_dbl_done
2340get_fs_dbl_f10:
2341	mfc1	t3, $f10
2342	mfc1	t0, $f11
2343	b	get_fs_dbl_done
2344get_fs_dbl_f12:
2345	mfc1	t3, $f12
2346	mfc1	t0, $f13
2347	b	get_fs_dbl_done
2348get_fs_dbl_f14:
2349	mfc1	t3, $f14
2350	mfc1	t0, $f15
2351	b	get_fs_dbl_done
2352get_fs_dbl_f16:
2353	mfc1	t3, $f16
2354	mfc1	t0, $f17
2355	b	get_fs_dbl_done
2356get_fs_dbl_f18:
2357	mfc1	t3, $f18
2358	mfc1	t0, $f19
2359	b	get_fs_dbl_done
2360get_fs_dbl_f20:
2361	mfc1	t3, $f20
2362	mfc1	t0, $f21
2363	b	get_fs_dbl_done
2364get_fs_dbl_f22:
2365	mfc1	t3, $f22
2366	mfc1	t0, $f23
2367	b	get_fs_dbl_done
2368get_fs_dbl_f24:
2369	mfc1	t3, $f24
2370	mfc1	t0, $f25
2371	b	get_fs_dbl_done
2372get_fs_dbl_f26:
2373	mfc1	t3, $f26
2374	mfc1	t0, $f27
2375	b	get_fs_dbl_done
2376get_fs_dbl_f28:
2377	mfc1	t3, $f28
2378	mfc1	t0, $f29
2379	b	get_fs_dbl_done
2380get_fs_dbl_f30:
2381	mfc1	t3, $f30
2382	mfc1	t0, $f31
2383get_fs_dbl_done:
2384	srl	t1, t0, 20			# get exponent
2385	and	t1, t1, 0x7FF
2386	and	t2, t0, 0xFFFFF			# get fraction
2387	srl	t0, t0, 31			# get sign
2388	bne	t1, DEXP_INF, 1f		# is it a signalling NAN?
2389	and	v0, t2, DSIGNAL_NAN
2390	bne	v0, zero, invalid_d
23911:
2392	j	ra
2393END(get_fs_dbl)
2394
2395/*----------------------------------------------------------------------------
2396 * get_fs_int --
2397 *
2398 *	Read (integer) the FS register (bits 15-11).
2399 *	This is an internal routine used by MachEmulateFP only.
2400 *
2401 * Results:
2402 *	t0	contains the sign
2403 *	t2	contains the fraction
2404 *
2405 *----------------------------------------------------------------------------
2406 */
2407LEAF(get_fs_int)
2408	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2409	and	a3, a3, 0xF << 2		# mask FS field
2410	lw	a3, get_fs_int_tbl(a3)		# switch on register number
2411	j	a3
2412
2413	.rdata
2414get_fs_int_tbl:
2415	.word	get_fs_int_f0
2416	.word	get_fs_int_f2
2417	.word	get_fs_int_f4
2418	.word	get_fs_int_f6
2419	.word	get_fs_int_f8
2420	.word	get_fs_int_f10
2421	.word	get_fs_int_f12
2422	.word	get_fs_int_f14
2423	.word	get_fs_int_f16
2424	.word	get_fs_int_f18
2425	.word	get_fs_int_f20
2426	.word	get_fs_int_f22
2427	.word	get_fs_int_f24
2428	.word	get_fs_int_f26
2429	.word	get_fs_int_f28
2430	.word	get_fs_int_f30
2431	.text
2432
2433get_fs_int_f0:
2434	mfc1	t2, $f0
2435	b	get_fs_int_done
2436get_fs_int_f2:
2437	mfc1	t2, $f2
2438	b	get_fs_int_done
2439get_fs_int_f4:
2440	mfc1	t2, $f4
2441	b	get_fs_int_done
2442get_fs_int_f6:
2443	mfc1	t2, $f6
2444	b	get_fs_int_done
2445get_fs_int_f8:
2446	mfc1	t2, $f8
2447	b	get_fs_int_done
2448get_fs_int_f10:
2449	mfc1	t2, $f10
2450	b	get_fs_int_done
2451get_fs_int_f12:
2452	mfc1	t2, $f12
2453	b	get_fs_int_done
2454get_fs_int_f14:
2455	mfc1	t2, $f14
2456	b	get_fs_int_done
2457get_fs_int_f16:
2458	mfc1	t2, $f16
2459	b	get_fs_int_done
2460get_fs_int_f18:
2461	mfc1	t2, $f18
2462	b	get_fs_int_done
2463get_fs_int_f20:
2464	mfc1	t2, $f20
2465	b	get_fs_int_done
2466get_fs_int_f22:
2467	mfc1	t2, $f22
2468	b	get_fs_int_done
2469get_fs_int_f24:
2470	mfc1	t2, $f24
2471	b	get_fs_int_done
2472get_fs_int_f26:
2473	mfc1	t2, $f26
2474	b	get_fs_int_done
2475get_fs_int_f28:
2476	mfc1	t2, $f28
2477	b	get_fs_int_done
2478get_fs_int_f30:
2479	mfc1	t2, $f30
2480get_fs_int_done:
2481	srl	t0, t2, 31		# init the sign bit
2482	bge	t2, zero, 1f
2483	negu	t2
24841:
2485	j	ra
2486END(get_fs_int)
2487
2488/*----------------------------------------------------------------------------
2489 * get_ft_sgl --
2490 *
2491 *	Read (single precision) the FT register (bits 20-16) and
2492 *	break up into fields.
2493 *	This is an internal routine used by MachEmulateFP only.
2494 *
2495 * Results:
2496 *	t4	contains the sign
2497 *	t5	contains the (biased) exponent
2498 *	t6	contains the fraction
2499 *
2500 *----------------------------------------------------------------------------
2501 */
2502LEAF(get_ft_sgl)
2503	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2504	and	a3, a3, 0xF << 2		# mask FT field
2505	lw	a3, get_ft_sgl_tbl(a3)		# switch on register number
2506	j	a3
2507
2508	.rdata
2509get_ft_sgl_tbl:
2510	.word	get_ft_sgl_f0
2511	.word	get_ft_sgl_f2
2512	.word	get_ft_sgl_f4
2513	.word	get_ft_sgl_f6
2514	.word	get_ft_sgl_f8
2515	.word	get_ft_sgl_f10
2516	.word	get_ft_sgl_f12
2517	.word	get_ft_sgl_f14
2518	.word	get_ft_sgl_f16
2519	.word	get_ft_sgl_f18
2520	.word	get_ft_sgl_f20
2521	.word	get_ft_sgl_f22
2522	.word	get_ft_sgl_f24
2523	.word	get_ft_sgl_f26
2524	.word	get_ft_sgl_f28
2525	.word	get_ft_sgl_f30
2526	.text
2527
2528get_ft_sgl_f0:
2529	mfc1	t4, $f0
2530	b	get_ft_sgl_done
2531get_ft_sgl_f2:
2532	mfc1	t4, $f2
2533	b	get_ft_sgl_done
2534get_ft_sgl_f4:
2535	mfc1	t4, $f4
2536	b	get_ft_sgl_done
2537get_ft_sgl_f6:
2538	mfc1	t4, $f6
2539	b	get_ft_sgl_done
2540get_ft_sgl_f8:
2541	mfc1	t4, $f8
2542	b	get_ft_sgl_done
2543get_ft_sgl_f10:
2544	mfc1	t4, $f10
2545	b	get_ft_sgl_done
2546get_ft_sgl_f12:
2547	mfc1	t4, $f12
2548	b	get_ft_sgl_done
2549get_ft_sgl_f14:
2550	mfc1	t4, $f14
2551	b	get_ft_sgl_done
2552get_ft_sgl_f16:
2553	mfc1	t4, $f16
2554	b	get_ft_sgl_done
2555get_ft_sgl_f18:
2556	mfc1	t4, $f18
2557	b	get_ft_sgl_done
2558get_ft_sgl_f20:
2559	mfc1	t4, $f20
2560	b	get_ft_sgl_done
2561get_ft_sgl_f22:
2562	mfc1	t4, $f22
2563	b	get_ft_sgl_done
2564get_ft_sgl_f24:
2565	mfc1	t4, $f24
2566	b	get_ft_sgl_done
2567get_ft_sgl_f26:
2568	mfc1	t4, $f26
2569	b	get_ft_sgl_done
2570get_ft_sgl_f28:
2571	mfc1	t4, $f28
2572	b	get_ft_sgl_done
2573get_ft_sgl_f30:
2574	mfc1	t4, $f30
2575get_ft_sgl_done:
2576	srl	t5, t4, 23			# get exponent
2577	and	t5, t5, 0xFF
2578	and	t6, t4, 0x7FFFFF		# get fraction
2579	srl	t4, t4, 31			# get sign
2580	bne	t5, SEXP_INF, 1f		# is it a signalling NAN?
2581	and	v0, t6, SSIGNAL_NAN
2582	bne	v0, zero, invalid_s
25831:
2584	j	ra
2585END(get_ft_sgl)
2586
2587/*----------------------------------------------------------------------------
2588 * get_ft_dbl --
2589 *
2590 *	Read (double precision) the FT register (bits 20-16) and
2591 *	break up into fields.
2592 *	This is an internal routine used by MachEmulateFP only.
2593 *
2594 * Results:
2595 *	t4	contains the sign
2596 *	t5	contains the (biased) exponent
2597 *	t6	contains the fraction
2598 *	t7	contains the remaining fraction
2599 *
2600 *----------------------------------------------------------------------------
2601 */
2602LEAF(get_ft_dbl)
2603	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2604	and	a3, a3, 0xF << 2		# mask FT field
2605	lw	a3, get_ft_dbl_tbl(a3)		# switch on register number
2606	j	a3
2607
2608	.rdata
2609get_ft_dbl_tbl:
2610	.word	get_ft_dbl_f0
2611	.word	get_ft_dbl_f2
2612	.word	get_ft_dbl_f4
2613	.word	get_ft_dbl_f6
2614	.word	get_ft_dbl_f8
2615	.word	get_ft_dbl_f10
2616	.word	get_ft_dbl_f12
2617	.word	get_ft_dbl_f14
2618	.word	get_ft_dbl_f16
2619	.word	get_ft_dbl_f18
2620	.word	get_ft_dbl_f20
2621	.word	get_ft_dbl_f22
2622	.word	get_ft_dbl_f24
2623	.word	get_ft_dbl_f26
2624	.word	get_ft_dbl_f28
2625	.word	get_ft_dbl_f30
2626	.text
2627
2628get_ft_dbl_f0:
2629	mfc1	t7, $f0
2630	mfc1	t4, $f1
2631	b	get_ft_dbl_done
2632get_ft_dbl_f2:
2633	mfc1	t7, $f2
2634	mfc1	t4, $f3
2635	b	get_ft_dbl_done
2636get_ft_dbl_f4:
2637	mfc1	t7, $f4
2638	mfc1	t4, $f5
2639	b	get_ft_dbl_done
2640get_ft_dbl_f6:
2641	mfc1	t7, $f6
2642	mfc1	t4, $f7
2643	b	get_ft_dbl_done
2644get_ft_dbl_f8:
2645	mfc1	t7, $f8
2646	mfc1	t4, $f9
2647	b	get_ft_dbl_done
2648get_ft_dbl_f10:
2649	mfc1	t7, $f10
2650	mfc1	t4, $f11
2651	b	get_ft_dbl_done
2652get_ft_dbl_f12:
2653	mfc1	t7, $f12
2654	mfc1	t4, $f13
2655	b	get_ft_dbl_done
2656get_ft_dbl_f14:
2657	mfc1	t7, $f14
2658	mfc1	t4, $f15
2659	b	get_ft_dbl_done
2660get_ft_dbl_f16:
2661	mfc1	t7, $f16
2662	mfc1	t4, $f17
2663	b	get_ft_dbl_done
2664get_ft_dbl_f18:
2665	mfc1	t7, $f18
2666	mfc1	t4, $f19
2667	b	get_ft_dbl_done
2668get_ft_dbl_f20:
2669	mfc1	t7, $f20
2670	mfc1	t4, $f21
2671	b	get_ft_dbl_done
2672get_ft_dbl_f22:
2673	mfc1	t7, $f22
2674	mfc1	t4, $f23
2675	b	get_ft_dbl_done
2676get_ft_dbl_f24:
2677	mfc1	t7, $f24
2678	mfc1	t4, $f25
2679	b	get_ft_dbl_done
2680get_ft_dbl_f26:
2681	mfc1	t7, $f26
2682	mfc1	t4, $f27
2683	b	get_ft_dbl_done
2684get_ft_dbl_f28:
2685	mfc1	t7, $f28
2686	mfc1	t4, $f29
2687	b	get_ft_dbl_done
2688get_ft_dbl_f30:
2689	mfc1	t7, $f30
2690	mfc1	t4, $f31
2691get_ft_dbl_done:
2692	srl	t5, t4, 20			# get exponent
2693	and	t5, t5, 0x7FF
2694	and	t6, t4, 0xFFFFF			# get fraction
2695	srl	t4, t4, 31			# get sign
2696	bne	t5, DEXP_INF, 1f		# is it a signalling NAN?
2697	and	v0, t6, DSIGNAL_NAN
2698	bne	v0, zero, invalid_d
26991:
2700	j	ra
2701END(get_ft_dbl)
2702
2703/*----------------------------------------------------------------------------
2704 * set_fd_sgl --
2705 *
2706 *	Write (single precision) the FD register (bits 10-6).
2707 *	This is an internal routine used by MachEmulateFP only.
2708 *
2709 * Arguments:
2710 *	a0	contains the FP instruction
2711 *	t0	contains the sign
2712 *	t1	contains the (biased) exponent
2713 *	t2	contains the fraction
2714 *
2715 * set_fd_word --
2716 *
2717 *	Write (integer) the FD register (bits 10-6).
2718 *	This is an internal routine used by MachEmulateFP only.
2719 *
2720 * Arguments:
2721 *	a0	contains the FP instruction
2722 *	t2	contains the integer
2723 *
2724 *----------------------------------------------------------------------------
2725 */
2726LEAF(set_fd_sgl)
2727	sll	t0, t0, 31			# position sign
2728	sll	t1, t1, 23			# position exponent
2729	or	t2, t2, t0
2730	or	t2, t2, t1
2731ALEAF(set_fd_word)
2732	srl	a3, a0, 7 - 2			# get FD field (even regs only)
2733	and	a3, a3, 0xF << 2		# mask FT field
2734	lw	a3, set_fd_sgl_tbl(a3)		# switch on register number
2735	j	a3
2736
2737	.rdata
2738set_fd_sgl_tbl:
2739	.word	set_fd_sgl_f0
2740	.word	set_fd_sgl_f2
2741	.word	set_fd_sgl_f4
2742	.word	set_fd_sgl_f6
2743	.word	set_fd_sgl_f8
2744	.word	set_fd_sgl_f10
2745	.word	set_fd_sgl_f12
2746	.word	set_fd_sgl_f14
2747	.word	set_fd_sgl_f16
2748	.word	set_fd_sgl_f18
2749	.word	set_fd_sgl_f20
2750	.word	set_fd_sgl_f22
2751	.word	set_fd_sgl_f24
2752	.word	set_fd_sgl_f26
2753	.word	set_fd_sgl_f28
2754	.word	set_fd_sgl_f30
2755	.text
2756
2757set_fd_sgl_f0:
2758	mtc1	t2, $f0
2759	j	ra
2760set_fd_sgl_f2:
2761	mtc1	t2, $f2
2762	j	ra
2763set_fd_sgl_f4:
2764	mtc1	t2, $f4
2765	j	ra
2766set_fd_sgl_f6:
2767	mtc1	t2, $f6
2768	j	ra
2769set_fd_sgl_f8:
2770	mtc1	t2, $f8
2771	j	ra
2772set_fd_sgl_f10:
2773	mtc1	t2, $f10
2774	j	ra
2775set_fd_sgl_f12:
2776	mtc1	t2, $f12
2777	j	ra
2778set_fd_sgl_f14:
2779	mtc1	t2, $f14
2780	j	ra
2781set_fd_sgl_f16:
2782	mtc1	t2, $f16
2783	j	ra
2784set_fd_sgl_f18:
2785	mtc1	t2, $f18
2786	j	ra
2787set_fd_sgl_f20:
2788	mtc1	t2, $f20
2789	j	ra
2790set_fd_sgl_f22:
2791	mtc1	t2, $f22
2792	j	ra
2793set_fd_sgl_f24:
2794	mtc1	t2, $f24
2795	j	ra
2796set_fd_sgl_f26:
2797	mtc1	t2, $f26
2798	j	ra
2799set_fd_sgl_f28:
2800	mtc1	t2, $f28
2801	j	ra
2802set_fd_sgl_f30:
2803	mtc1	t2, $f30
2804	j	ra
2805END(set_fd_sgl)
2806
2807/*----------------------------------------------------------------------------
2808 * set_fd_dbl --
2809 *
2810 *	Write (double precision) the FT register (bits 10-6).
2811 *	This is an internal routine used by MachEmulateFP only.
2812 *
2813 * Arguments:
2814 *	a0	contains the FP instruction
2815 *	t0	contains the sign
2816 *	t1	contains the (biased) exponent
2817 *	t2	contains the fraction
2818 *	t3	contains the remaining fraction
2819 *
2820 *----------------------------------------------------------------------------
2821 */
2822LEAF(set_fd_dbl)
2823	sll	t0, t0, 31			# set sign
2824	sll	t1, t1, 20			# set exponent
2825	or	t0, t0, t1
2826	or	t0, t0, t2			# set fraction
2827	srl	a3, a0, 7 - 2			# get FD field (even regs only)
2828	and	a3, a3, 0xF << 2		# mask FD field
2829	lw	a3, set_fd_dbl_tbl(a3)		# switch on register number
2830	j	a3
2831
2832	.rdata
2833set_fd_dbl_tbl:
2834	.word	set_fd_dbl_f0
2835	.word	set_fd_dbl_f2
2836	.word	set_fd_dbl_f4
2837	.word	set_fd_dbl_f6
2838	.word	set_fd_dbl_f8
2839	.word	set_fd_dbl_f10
2840	.word	set_fd_dbl_f12
2841	.word	set_fd_dbl_f14
2842	.word	set_fd_dbl_f16
2843	.word	set_fd_dbl_f18
2844	.word	set_fd_dbl_f20
2845	.word	set_fd_dbl_f22
2846	.word	set_fd_dbl_f24
2847	.word	set_fd_dbl_f26
2848	.word	set_fd_dbl_f28
2849	.word	set_fd_dbl_f30
2850	.text
2851
2852set_fd_dbl_f0:
2853	mtc1	t3, $f0
2854	mfc1	t0, $f1
2855	j	ra
2856set_fd_dbl_f2:
2857	mtc1	t3, $f2
2858	mfc1	t0, $f3
2859	j	ra
2860set_fd_dbl_f4:
2861	mtc1	t3, $f4
2862	mfc1	t0, $f5
2863	j	ra
2864set_fd_dbl_f6:
2865	mtc1	t3, $f6
2866	mfc1	t0, $f7
2867	j	ra
2868set_fd_dbl_f8:
2869	mtc1	t3, $f8
2870	mfc1	t0, $f9
2871	j	ra
2872set_fd_dbl_f10:
2873	mtc1	t3, $f10
2874	mfc1	t0, $f11
2875	j	ra
2876set_fd_dbl_f12:
2877	mtc1	t3, $f12
2878	mfc1	t0, $f13
2879	j	ra
2880set_fd_dbl_f14:
2881	mtc1	t3, $f14
2882	mfc1	t0, $f15
2883	j	ra
2884set_fd_dbl_f16:
2885	mtc1	t3, $f16
2886	mfc1	t0, $f17
2887	j	ra
2888set_fd_dbl_f18:
2889	mtc1	t3, $f18
2890	mfc1	t0, $f19
2891	j	ra
2892set_fd_dbl_f20:
2893	mtc1	t3, $f20
2894	mfc1	t0, $f21
2895	j	ra
2896set_fd_dbl_f22:
2897	mtc1	t3, $f22
2898	mfc1	t0, $f23
2899	j	ra
2900set_fd_dbl_f24:
2901	mtc1	t3, $f24
2902	mfc1	t0, $f25
2903	j	ra
2904set_fd_dbl_f26:
2905	mtc1	t3, $f26
2906	mfc1	t0, $f27
2907	j	ra
2908set_fd_dbl_f28:
2909	mtc1	t3, $f28
2910	mfc1	t0, $f29
2911	j	ra
2912set_fd_dbl_f30:
2913	mtc1	t3, $f30
2914	mfc1	t0, $f31
2915	j	ra
2916END(set_fd_dbl)
2917
2918/*----------------------------------------------------------------------------
2919 * renorm_fs_s --
2920 *
2921 * Results:
2922 *	t1	unbiased exponent
2923 *	t2	normalized fraction
2924 *
2925 *----------------------------------------------------------------------------
2926 */
2927LEAF(renorm_fs_s)
2928/*
2929 * Find out how many leading zero bits are in t2 and put in t9.
2930 */
2931	move	v0, t2
2932	move	t9, zero
2933	srl	v1, v0, 16
2934	bne	v1, zero, 1f
2935	addu	t9, 16
2936	sll	v0, 16
29371:
2938	srl	v1, v0, 24
2939	bne	v1, zero, 1f
2940	addu	t9, 8
2941	sll	v0, 8
29421:
2943	srl	v1, v0, 28
2944	bne	v1, zero, 1f
2945	addu	t9, 4
2946	sll	v0, 4
29471:
2948	srl	v1, v0, 30
2949	bne	v1, zero, 1f
2950	addu	t9, 2
2951	sll	v0, 2
29521:
2953	srl	v1, v0, 31
2954	bne	v1, zero, 1f
2955	addu	t9, 1
2956/*
2957 * Now shift t2 the correct number of bits.
2958 */
29591:
2960	subu	t9, t9, SLEAD_ZEROS	# don't count normal leading zeros
2961	li	t1, SEXP_MIN
2962	subu	t1, t1, t9		# adjust exponent
2963	sll	t2, t2, t9
2964	j	ra
2965END(renorm_fs_s)
2966
2967/*----------------------------------------------------------------------------
2968 * renorm_fs_d --
2969 *
2970 * Results:
2971 *	t1	unbiased exponent
2972 *	t2,t3	normalized fraction
2973 *
2974 *----------------------------------------------------------------------------
2975 */
2976LEAF(renorm_fs_d)
2977/*
2978 * Find out how many leading zero bits are in t2,t3 and put in t9.
2979 */
2980	move	v0, t2
2981	move	t9, zero
2982	bne	t2, zero, 1f
2983	move	v0, t3
2984	addu	t9, 32
29851:
2986	srl	v1, v0, 16
2987	bne	v1, zero, 1f
2988	addu	t9, 16
2989	sll	v0, 16
29901:
2991	srl	v1, v0, 24
2992	bne	v1, zero, 1f
2993	addu	t9, 8
2994	sll	v0, 8
29951:
2996	srl	v1, v0, 28
2997	bne	v1, zero, 1f
2998	addu	t9, 4
2999	sll	v0, 4
30001:
3001	srl	v1, v0, 30
3002	bne	v1, zero, 1f
3003	addu	t9, 2
3004	sll	v0, 2
30051:
3006	srl	v1, v0, 31
3007	bne	v1, zero, 1f
3008	addu	t9, 1
3009/*
3010 * Now shift t2,t3 the correct number of bits.
3011 */
30121:
3013	subu	t9, t9, DLEAD_ZEROS	# don't count normal leading zeros
3014	li	t1, DEXP_MIN
3015	subu	t1, t1, t9		# adjust exponent
3016	li	v0, 32
3017	blt	t9, v0, 1f
3018	subu	t9, t9, v0		# shift fraction left >= 32 bits
3019	sll	t2, t3, t9
3020	move	t3, zero
3021	j	ra
30221:
3023	subu	v0, v0, t9		# shift fraction left < 32 bits
3024	sll	t2, t2, t9
3025	srl	v1, t3, v0
3026	or	t2, t2, v1
3027	sll	t3, t3, t9
3028	j	ra
3029END(renorm_fs_d)
3030
3031/*----------------------------------------------------------------------------
3032 * renorm_ft_s --
3033 *
3034 * Results:
3035 *	t5	unbiased exponent
3036 *	t6	normalized fraction
3037 *
3038 *----------------------------------------------------------------------------
3039 */
3040LEAF(renorm_ft_s)
3041/*
3042 * Find out how many leading zero bits are in t6 and put in t9.
3043 */
3044	move	v0, t6
3045	move	t9, zero
3046	srl	v1, v0, 16
3047	bne	v1, zero, 1f
3048	addu	t9, 16
3049	sll	v0, 16
30501:
3051	srl	v1, v0, 24
3052	bne	v1, zero, 1f
3053	addu	t9, 8
3054	sll	v0, 8
30551:
3056	srl	v1, v0, 28
3057	bne	v1, zero, 1f
3058	addu	t9, 4
3059	sll	v0, 4
30601:
3061	srl	v1, v0, 30
3062	bne	v1, zero, 1f
3063	addu	t9, 2
3064	sll	v0, 2
30651:
3066	srl	v1, v0, 31
3067	bne	v1, zero, 1f
3068	addu	t9, 1
3069/*
3070 * Now shift t6 the correct number of bits.
3071 */
30721:
3073	subu	t9, t9, SLEAD_ZEROS	# don't count normal leading zeros
3074	li	t5, SEXP_MIN
3075	subu	t5, t5, t9		# adjust exponent
3076	sll	t6, t6, t9
3077	j	ra
3078END(renorm_ft_s)
3079
3080/*----------------------------------------------------------------------------
3081 * renorm_ft_d --
3082 *
3083 * Results:
3084 *	t5	unbiased exponent
3085 *	t6,t7	normalized fraction
3086 *
3087 *----------------------------------------------------------------------------
3088 */
3089LEAF(renorm_ft_d)
3090/*
3091 * Find out how many leading zero bits are in t6,t7 and put in t9.
3092 */
3093	move	v0, t6
3094	move	t9, zero
3095	bne	t6, zero, 1f
3096	move	v0, t7
3097	addu	t9, 32
30981:
3099	srl	v1, v0, 16
3100	bne	v1, zero, 1f
3101	addu	t9, 16
3102	sll	v0, 16
31031:
3104	srl	v1, v0, 24
3105	bne	v1, zero, 1f
3106	addu	t9, 8
3107	sll	v0, 8
31081:
3109	srl	v1, v0, 28
3110	bne	v1, zero, 1f
3111	addu	t9, 4
3112	sll	v0, 4
31131:
3114	srl	v1, v0, 30
3115	bne	v1, zero, 1f
3116	addu	t9, 2
3117	sll	v0, 2
31181:
3119	srl	v1, v0, 31
3120	bne	v1, zero, 1f
3121	addu	t9, 1
3122/*
3123 * Now shift t6,t7 the correct number of bits.
3124 */
31251:
3126	subu	t9, t9, DLEAD_ZEROS	# don't count normal leading zeros
3127	li	t5, DEXP_MIN
3128	subu	t5, t5, t9		# adjust exponent
3129	li	v0, 32
3130	blt	t9, v0, 1f
3131	subu	t9, t9, v0		# shift fraction left >= 32 bits
3132	sll	t6, t7, t9
3133	move	t7, zero
3134	j	ra
31351:
3136	subu	v0, v0, t9		# shift fraction left < 32 bits
3137	sll	t6, t6, t9
3138	srl	v1, t7, v0
3139	or	t6, t6, v1
3140	sll	t7, t7, t9
3141	j	ra
3142END(renorm_ft_d)
3143