xref: /netbsd/sys/arch/mips/mips/fp.S (revision c4a72b64)
1/*	$NetBSD: fp.S,v 1.23 2002/11/04 18:54:13 thorpej Exp $	*/
2
3/*
4 * Copyright (c) 1992, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Ralph Campbell.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the University of
21 *	California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 *	@(#)fp.s	8.1 (Berkeley) 6/10/93
39 */
40
41#include <sys/cdefs.h>
42
43#include <mips/asm.h>
44#include <mips/cpuregs.h>
45#include <mips/trap.h>
46
47#include "assym.h"
48
49#define SEXP_INF	0xff
50#define DEXP_INF	0x7ff
51#define SEXP_BIAS	127
52#define DEXP_BIAS	1023
53#define SEXP_MIN	-126
54#define DEXP_MIN	-1022
55#define SEXP_MAX	127
56#define DEXP_MAX	1023
57#define WEXP_MAX	30		/* maximum unbiased exponent for int */
58#define WEXP_MIN	-1		/* minimum unbiased exponent for int */
59#define SFRAC_BITS	23
60#define DFRAC_BITS	52
61#define SIMPL_ONE	0x00800000
62#define DIMPL_ONE	0x00100000
63#define SLEAD_ZEROS	31 - 23
64#define DLEAD_ZEROS	31 - 20
65#define STICKYBIT	1
66#define GUARDBIT	0x80000000
67#define SSIGNAL_NAN	0x00400000
68#define DSIGNAL_NAN	0x00080000
69#define SQUIET_NAN	0x003fffff
70#define DQUIET_NAN0	0x0007ffff
71#define DQUIET_NAN1	0xffffffff
72#define INT_MIN		0x80000000
73#define INT_MAX		0x7fffffff
74
75#define COND_UNORDERED	0x1
76#define COND_EQUAL	0x2
77#define COND_LESS	0x4
78#define COND_SIGNAL	0x8
79
80#if SZREG == 8
81#define SZREG_SHFT	3
82#define SZREG_MASK	0x00f8
83#else
84#define SZREG_SHFT	2
85#define SZREG_MASK	0x007c
86#endif
87
88/* insns are reordered in the way as MIPS architecture imposes */
89	.set	reorder
90
91/*----------------------------------------------------------------------------
92 *
93 * MachEmulateFP --
94 *
95 *	Emulate unimplemented floating point operations.
96 *	This routine should only be called by MachFPInterrupt().
97 *
98 *	MachEmulateFP(instr, frame, cause)
99 *		u_int32_t instr;
100 *		struct frame *frame;
101 *		u_int32_t cause;
102 *
103 * Results:
104 *	None.
105 *
106 * Side effects:
107 *	Floating point registers are modified according to instruction.
108 *
109 *----------------------------------------------------------------------------
110 */
111NESTED(MachEmulateFP, CALLFRAME_SIZ, ra)
112	subu	sp, sp, CALLFRAME_SIZ
113	sw	ra, CALLFRAME_RA(sp)
114	sw	a1, CALLFRAME_SIZ + 16(sp)
115	sw	a2, CALLFRAME_SIZ + 8(sp)
116/*
117 * Decode the FMT field (bits 25-21) and FUNCTION field (bits 5-0).
118 */
119	srl	v0, a0, 21 - 2			# get FMT field
120	andi	v0, v0, 0x1F << 2		# mask FMT field
121#ifdef SOFTFLOAT
122	lw	t0, _C_LABEL(curpcb)		# get pcb of current process
123	lw	a3, fmt_tbl(v0)			# switch on FUNC & FMT
124	lw	a2, U_PCB_FPREGS+FRAME_FSR(t0)
125#else
126	cfc1	a2, MIPS_FPU_CSR		# get exception register
127	lw	a3, fmt_tbl(v0)			# switch on FUNC & FMT
128	and	a2, a2, ~MIPS_FPU_EXCEPTION_UNIMPL	# clear exception
129	ctc1	a2, MIPS_FPU_CSR
130#endif
131	j	a3
132
133single_op:
134	andi	v0, a0, 0x3F		# get FUNC field
135	sll	v0, v0, 2
136	lw	v0, func_single_tbl(v0)
137	j	v0
138double_op:
139	andi	v0, a0, 0x3F		# get FUNC field
140	sll	v0, v0, 2
141	lw	v0, func_double_tbl(v0)
142	j	v0
143single_fixed_op:
144	andi	v0, a0, 0x3F		# get FUNC field
145	sll	v0, v0, 2
146	lw	v0, func_single_fixed_tbl(v0)
147	j	v0
148long_fixed_op:
149	andi	v0, a0, 0x3F		# get FUNC field
150	sll	v0, v0, 2
151	lw	v0, func_long_fixed_tbl(v0)
152	j	v0
153
154	.rdata
155fmt_tbl:
156#ifdef SOFTFLOAT
157	.word	mfromc1		# sub 0
158#else
159	.word	ill		# sub 0
160#endif
161	.word	ill		# sub 1
162#ifdef SOFTFLOAT
163	.word	cfromc1		# sub 2
164#else
165	.word	ill		# sub 2
166#endif
167	.word	ill		# sub 3
168#ifdef SOFTFLOAT
169	.word	mtoc1		# sub 4
170#else
171	.word	ill		# sub 4
172#endif
173	.word	ill		# sub 5
174#ifdef SOFTFLOAT
175	.word	ctoc1		# sub 6
176#else
177	.word	ill		# sub 6
178#endif
179	.word	ill		# sub 7
180#ifdef SOFTFLOAT
181	.word	branchc1	# sub 8
182#else
183	.word	ill		# sub 8
184#endif
185	.word	ill		# sub 9
186	.word	ill		# sub 10
187	.word	ill		# sub 11
188	.word	ill		# sub 12
189	.word	ill		# sub 13
190	.word	ill		# sub 14
191	.word	ill		# sub 15
192	.word	single_op	# sub 16
193	.word	double_op	# sub 17
194	.word	ill		# sub 18
195	.word	ill		# sub 19
196	.word	single_fixed_op	# sub 20
197	.word	long_fixed_op	# sub 21
198	.word	ill		# sub 22
199	.word	ill		# sub 23
200	.word	ill		# sub 24
201	.word	ill		# sub 25
202	.word	ill		# sub 26
203	.word	ill		# sub 27
204	.word	ill		# sub 28
205	.word	ill		# sub 29
206	.word	ill		# sub 30
207	.word	ill		# sub 31
208
209func_single_tbl:
210	.word	add_s		# func 0
211	.word	sub_s		# func 1
212	.word	mul_s		# func 2
213	.word	div_s		# func 3
214#ifdef MIPS3_PLUS
215	.word	sqrt_s		# func 4
216#else
217	.word	ill		# func 4
218#endif
219	.word	abs_s		# func 5
220	.word	mov_s		# func 6
221	.word	neg_s		# func 7
222	.word	ill		# func 8
223	.word	ill		# func 9
224	.word	ill		# func 10
225	.word	ill		# func 11
226#ifdef MIPS3_PLUS
227	.word	round_w_s	# func 12 /* MIPS2 FP instructions */
228	.word	trunc_w_s	# func 13
229	.word	ceil_w_s	# func 14
230	.word	floor_w_s	# func 15
231#else
232	.word	ill		# func 12
233	.word	ill		# func 13
234	.word	ill		# func 14
235	.word	ill		# func 15
236#endif
237	.word	ill		# func 16
238	.word	ill		# func 17
239	.word	ill		# func 18
240	.word	ill		# func 19
241	.word	ill		# func 20
242	.word	ill		# func 21
243	.word	ill		# func 22
244	.word	ill		# func 23
245	.word	ill		# func 24
246	.word	ill		# func 25
247	.word	ill		# func 26
248	.word	ill		# func 27
249	.word	ill		# func 28
250	.word	ill		# func 29
251	.word	ill		# func 30
252	.word	ill		# func 31
253	.word	ill		# func 32
254	.word	cvt_d_s		# func 33
255	.word	ill		# func 34
256	.word	ill		# func 35
257	.word	cvt_w_s		# func 36
258	.word	ill		# func 37
259	.word	ill		# func 38
260	.word	ill		# func 39
261	.word	ill		# func 40
262	.word	ill		# func 41
263	.word	ill		# func 42
264	.word	ill		# func 43
265	.word	ill		# func 44
266	.word	ill		# func 45
267	.word	ill		# func 46
268	.word	ill		# func 47
269	.word	cmp_s		# func 48
270	.word	cmp_s		# func 49
271	.word	cmp_s		# func 50
272	.word	cmp_s		# func 51
273	.word	cmp_s		# func 52
274	.word	cmp_s		# func 53
275	.word	cmp_s		# func 54
276	.word	cmp_s		# func 55
277	.word	cmp_s		# func 56
278	.word	cmp_s		# func 57
279	.word	cmp_s		# func 58
280	.word	cmp_s		# func 59
281	.word	cmp_s		# func 60
282	.word	cmp_s		# func 61
283	.word	cmp_s		# func 62
284	.word	cmp_s		# func 63
285
286func_double_tbl:
287	.word	add_d		# func 0
288	.word	sub_d		# func 1
289	.word	mul_d		# func 2
290	.word	div_d		# func 3
291#ifdef MIPS3_PLUS
292	.word	sqrt_d		# func 4
293#else
294	.word	ill		# func 4
295#endif
296	.word	abs_d		# func 5
297	.word	mov_d		# func 6
298	.word	neg_d		# func 7
299	.word	ill		# func 8
300	.word	ill		# func 9
301	.word	ill		# func 10
302	.word	ill		# func 11
303#ifdef MIPS3_PLUS
304	.word	round_w_d	# func 12 /* MIPS2 FP instructions */
305	.word	trunc_w_d	# func 13
306	.word	ceil_w_d	# func 14
307	.word	floor_w_d	# func 15
308#else
309	.word	ill		# func 12
310	.word	ill		# func 13
311	.word	ill		# func 14
312	.word	ill		# func 15
313#endif
314	.word	ill		# func 16
315	.word	ill		# func 17
316	.word	ill		# func 18
317	.word	ill		# func 19
318	.word	ill		# func 20
319	.word	ill		# func 21
320	.word	ill		# func 22
321	.word	ill		# func 23
322	.word	ill		# func 24
323	.word	ill		# func 25
324	.word	ill		# func 26
325	.word	ill		# func 27
326	.word	ill		# func 28
327	.word	ill		# func 29
328	.word	ill		# func 30
329	.word	ill		# func 31
330	.word	cvt_s_d		# func 32
331	.word	ill		# func 33
332	.word	ill		# func 34
333	.word	ill		# func 35
334	.word	cvt_w_d		# func 36
335	.word	ill		# func 37
336	.word	ill		# func 38
337	.word	ill		# func 39
338	.word	ill		# func 40
339	.word	ill		# func 41
340	.word	ill		# func 42
341	.word	ill		# func 43
342	.word	ill		# func 44
343	.word	ill		# func 45
344	.word	ill		# func 46
345	.word	ill		# func 47
346	.word	cmp_d		# func 48
347	.word	cmp_d		# func 49
348	.word	cmp_d		# func 50
349	.word	cmp_d		# func 51
350	.word	cmp_d		# func 52
351	.word	cmp_d		# func 53
352	.word	cmp_d		# func 54
353	.word	cmp_d		# func 55
354	.word	cmp_d		# func 56
355	.word	cmp_d		# func 57
356	.word	cmp_d		# func 58
357	.word	cmp_d		# func 59
358	.word	cmp_d		# func 60
359	.word	cmp_d		# func 61
360	.word	cmp_d		# func 62
361	.word	cmp_d		# func 63
362
363func_single_fixed_tbl:
364	.word	ill		# func 0
365	.word	ill		# func 1
366	.word	ill		# func 2
367	.word	ill		# func 3
368	.word	ill		# func 4
369	.word	ill		# func 5
370	.word	ill		# func 6
371	.word	ill		# func 7
372	.word	ill		# func 8
373	.word	ill		# func 9
374	.word	ill		# func 10
375	.word	ill		# func 11
376	.word	ill		# func 12
377	.word	ill		# func 13
378	.word	ill		# func 14
379	.word	ill		# func 15
380	.word	ill		# func 16
381	.word	ill		# func 17
382	.word	ill		# func 18
383	.word	ill		# func 19
384	.word	ill		# func 20
385	.word	ill		# func 21
386	.word	ill		# func 22
387	.word	ill		# func 23
388	.word	ill		# func 24
389	.word	ill		# func 25
390	.word	ill		# func 26
391	.word	ill		# func 27
392	.word	ill		# func 28
393	.word	ill		# func 29
394	.word	ill		# func 30
395	.word	ill		# func 31
396	.word	cvt_s_w		# func 32
397	.word	cvt_d_w		# func 33
398	.word	ill		# func 34
399	.word	ill		# func 35
400	.word	ill		# func 36
401	.word	ill		# func 37
402	.word	ill		# func 38
403	.word	ill		# func 39
404	.word	ill		# func 40
405	.word	ill		# func 41
406	.word	ill		# func 42
407	.word	ill		# func 43
408	.word	ill		# func 44
409	.word	ill		# func 45
410	.word	ill		# func 46
411	.word	ill		# func 47
412	.word	ill		# func 48
413	.word	ill		# func 49
414	.word	ill		# func 50
415	.word	ill		# func 51
416	.word	ill		# func 52
417	.word	ill		# func 53
418	.word	ill		# func 54
419	.word	ill		# func 55
420	.word	ill		# func 56
421	.word	ill		# func 57
422	.word	ill		# func 58
423	.word	ill		# func 59
424	.word	ill		# func 60
425	.word	ill		# func 61
426	.word	ill		# func 62
427	.word	ill		# func 63
428
429func_long_fixed_tbl:
430	.word	ill		# func 0
431	.word	ill		# func 1
432	.word	ill		# func 2
433	.word	ill		# func 3
434	.word	ill		# func 4
435	.word	ill		# func 5
436	.word	ill		# func 6
437	.word	ill		# func 7
438	.word	ill		# func 8
439	.word	ill		# func 9
440	.word	ill		# func 10
441	.word	ill		# func 11
442	.word	ill		# func 12
443	.word	ill		# func 13
444	.word	ill		# func 14
445	.word	ill		# func 15
446	.word	ill		# func 16
447	.word	ill		# func 17
448	.word	ill		# func 18
449	.word	ill		# func 19
450	.word	ill		# func 20
451	.word	ill		# func 21
452	.word	ill		# func 22
453	.word	ill		# func 23
454	.word	ill		# func 24
455	.word	ill		# func 25
456	.word	ill		# func 26
457	.word	ill		# func 27
458	.word	ill		# func 28
459	.word	ill		# func 29
460	.word	ill		# func 30
461	.word	ill		# func 31
462	.word	ill		# func 32
463	.word	ill		# func 33
464	.word	ill		# func 34
465	.word	ill		# func 35
466	.word	ill		# func 36
467	.word	ill		# func 37
468	.word	ill		# func 38
469	.word	ill		# func 39
470	.word	ill		# func 40
471	.word	ill		# func 41
472	.word	ill		# func 42
473	.word	ill		# func 43
474	.word	ill		# func 44
475	.word	ill		# func 45
476	.word	ill		# func 46
477	.word	ill		# func 47
478	.word	ill		# func 48
479	.word	ill		# func 49
480	.word	ill		# func 50
481	.word	ill		# func 51
482	.word	ill		# func 52
483	.word	ill		# func 53
484	.word	ill		# func 54
485	.word	ill		# func 55
486	.word	ill		# func 56
487	.word	ill		# func 57
488	.word	ill		# func 58
489	.word	ill		# func 59
490	.word	ill		# func 60
491	.word	ill		# func 61
492	.word	ill		# func 62
493	.word	ill		# func 63
494
495	.text
496
497#ifdef SOFTFLOAT
498mfromc1:
499	srl	t1, a0, 11-2
500	lw	t0, _C_LABEL(curpcb)		# get pcb of current process
501	andi	t1, t1, 0x007C
502	addu	t0, t0, t1
503
504	lw	v0, U_PCB_FPREGS+FRAME_FP0(t0)
505
506	srl	t0, a0, 16-SZREG_SHFT
507	andi	t0, t0, SZREG_MASK
508	addu	t0, t0, a1
509
510	REG_PROLOGUE
511	REG_S	v0, FRAME_ZERO(t0)
512	REG_EPILOGUE
513
514	b	done
515
516mtoc1:
517	REG_PROLOGUE
518	REG_S	zero, FRAME_ZERO(a1)		# ensure zero has value 0
519	srl	t0, a0, 16-SZREG_SHFT
520	andi	t0, t0, SZREG_MASK
521	addu	v0, a1, t0
522	REG_L	v0, FRAME_ZERO(v0)
523	REG_EPILOGUE
524
525	srl	t1, a0, 11-2
526	lw	t0, _C_LABEL(curpcb)		# get pcb of current process
527	andi	t1, t1, 0x007C
528	addu	t0, t0, t1
529
530	sw	v0, U_PCB_FPREGS+FRAME_FP0(t0)
531
532	b	done
533
534cfromc1:
535	srl	t1, a0, 11
536	lw	t0, _C_LABEL(curpcb)		# get pcb of current process
537	andi	t1, t1, 0x001F
538	li	t2, 0x1F
539	move	v0, zero
540	bne	t1, t2, cfinvalid
541
542	lw	v0, U_PCB_FPREGS+FRAME_FSR(t0)
543
544cfinvalid:
545
546	srl	t0, a0, 16-SZREG_SHFT
547	andi	t0, t0, SZREG_MASK
548	addu	t0, t0, a1
549
550	REG_PROLOGUE
551	REG_S	v0, FRAME_ZERO(t0)
552	REG_EPILOGUE
553
554	b	done
555
556ctoc1:
557	REG_PROLOGUE
558	REG_S	zero, FRAME_ZERO(a1)		# ensure zero has value 0
559	REG_EPILOGUE
560
561	srl	t0, a0, 11
562	andi	t0, t0, 0x001F
563	li	t1, 0x1F
564	bne	t0, t1, done
565
566	srl	t0, a0, 16-SZREG_SHFT
567	andi	t0, t0, SZREG_MASK
568	addu	v0, a1, t0
569	REG_PROLOGUE
570	REG_L	v0, FRAME_ZERO(v0)
571	REG_EPILOGUE
572	lw	t0, _C_LABEL(curpcb)		# get pcb of current process
573	#nop
574	sw	v0, U_PCB_FPREGS+FRAME_FSR(t0)
575
576	b	done
577
578branchc1:
579	srl	v0, a0, 16-2
580	andi	v0, v0, 0x007C
581	lw	v0, branchc1_tbl(v0)
582	j	v0
583
584	.rdata
585branchc1_tbl:
586	.word	bcfalse		# br 0
587	.word	bctrue		# br 1
588	.word	bcfalse_l	# br 2
589	.word	bctrue_l	# br 3
590	.word	ill		# br 4
591	.word	ill		# br 5
592	.word	ill		# br 6
593	.word	ill		# br 7
594	.word	ill		# br 8
595	.word	ill		# br 9
596	.word	ill		# br 10
597	.word	ill		# br 11
598	.word	ill		# br 12
599	.word	ill		# br 13
600	.word	ill		# br 14
601	.word	ill		# br 15
602	.word	ill		# br 16
603	.word	ill		# br 17
604	.word	ill		# br 18
605	.word	ill		# br 19
606	.word	ill		# br 20
607	.word	ill		# br 21
608	.word	ill		# br 22
609	.word	ill		# br 23
610	.word	ill		# br 24
611	.word	ill		# br 25
612	.word	ill		# br 26
613	.word	ill		# br 27
614	.word	ill		# br 28
615	.word	ill		# br 29
616	.word	ill		# br 30
617	.word	ill		# br 31
618
619	.text
620
621bcfalse:
622	li	v0, MIPS_FPU_COND_BIT
623	and	v0, v0, a2
624	beq	v0, zero, bcemul_branch
625	b	done
626bctrue:
627	li	v0, MIPS_FPU_COND_BIT
628	and	v0, v0, a2
629	bne	v0, zero, bcemul_branch
630	b	done
631bcfalse_l:
632	li	v0, MIPS_FPU_COND_BIT
633	and	v0, v0, a2
634	beq	v0, zero, bcemul_branch
635	REG_PROLOGUE
636	REG_L	v0, FRAME_EPC(a1)
637	addiu	v0, v0, 4
638	REG_S	v0, FRAME_EPC(a1)
639	REG_EPILOGUE
640	b	done
641bctrue_l:
642	li	v0, MIPS_FPU_COND_BIT
643	and	v0, v0, a2
644	bne	v0, zero, bcemul_branch
645	REG_PROLOGUE
646	REG_L	v0, FRAME_EPC(a1)
647	addiu	v0, v0, 4
648	REG_S	v0, FRAME_EPC(a1)
649	REG_EPILOGUE
650	b	done
651
652bcemul_branch:
653	/* Fetch delay slot instruction */
654	sw	a1, CALLFRAME_SIZ + 4(sp)
655	REG_PROLOGUE
656	REG_L	a0, FRAME_EPC(a1)
657	REG_EPILOGUE
658	addiu	a0, a0, 4
659	jal	_C_LABEL(fuiword)
660
661	move	a0, v0
662	lw	a1, CALLFRAME_SIZ + 4(sp)
663	lw	a2, CALLFRAME_SIZ + 8(sp)
664
665	/* Update cause */
666	li	t0, MIPS_CR_BR_DELAY
667	or	a2, a2, t0
668
669	/* Free MachEmulateFP call frame */
670	lw	ra, CALLFRAME_RA(sp)
671	addu	sp, sp, CALLFRAME_SIZ
672
673	j	_C_LABEL(bcemul_delay_slot)
674#endif
675
676/*
677 * Single precision subtract.
678 */
679sub_s:
680	jal	_C_LABEL(get_ft_fs_s)
681	xor	ta0, ta0, 1			# negate FT sign bit
682	b	add_sub_s
683/*
684 * Single precision add.
685 */
686add_s:
687	jal	_C_LABEL(get_ft_fs_s)
688add_sub_s:
689	bne	t1, SEXP_INF, 1f		# is FS an infinity?
690	bne	ta1, SEXP_INF, result_fs_s	# if FT is not inf, result=FS
691	bne	t2, zero, result_fs_s		# if FS is NAN, result is FS
692	bne	ta2, zero, result_ft_s		# if FT is NAN, result is FT
693	bne	t0, ta0, invalid_s		# both infinities same sign?
694	b	result_fs_s			# result is in FS
6951:
696	beq	ta1, SEXP_INF, result_ft_s	# if FT is inf, result=FT
697	bne	t1, zero, 4f			# is FS a denormalized num?
698	beq	t2, zero, 3f			# is FS zero?
699	bne	ta1, zero, 2f			# is FT a denormalized num?
700	beq	ta2, zero, result_fs_s		# FT is zero, result=FS
701	jal	_C_LABEL(renorm_fs_s)
702	jal	_C_LABEL(renorm_ft_s)
703	b	5f
7042:
705	jal	_C_LABEL(renorm_fs_s)
706	subu	ta1, ta1, SEXP_BIAS		# unbias FT exponent
707	or	ta2, ta2, SIMPL_ONE		# set implied one bit
708	b	5f
7093:
710	bne	ta1, zero, result_ft_s		# if FT != 0, result=FT
711	bne	ta2, zero, result_ft_s
712	and	v0, a2, MIPS_FPU_ROUNDING_BITS	# get rounding mode
713	bne	v0, MIPS_FPU_ROUND_RM, 1f	# round to -infinity?
714	or	t0, t0, ta0			# compute result sign
715	b	result_fs_s
7161:
717	and	t0, t0, ta0			# compute result sign
718	b	result_fs_s
7194:
720	bne	ta1, zero, 2f			# is FT a denormalized num?
721	beq	ta2, zero, result_fs_s		# FT is zero, result=FS
722	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
723	or	t2, t2, SIMPL_ONE		# set implied one bit
724	jal	_C_LABEL(renorm_ft_s)
725	b	5f
7262:
727	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
728	or	t2, t2, SIMPL_ONE		# set implied one bit
729	subu	ta1, ta1, SEXP_BIAS		# unbias FT exponent
730	or	ta2, ta2, SIMPL_ONE		# set implied one bit
731/*
732 * Perform the addition.
733 */
7345:
735	move	t8, zero			# no shifted bits (sticky reg)
736	beq	t1, ta1, 4f			# no shift needed
737	subu	v0, t1, ta1			# v0 = difference of exponents
738	move	v1, v0				# v1 = abs(difference)
739	bge	v0, zero, 1f
740	negu	v1
7411:
742	ble	v1, SFRAC_BITS+2, 2f		# is difference too great?
743	li	t8, STICKYBIT			# set the sticky bit
744	bge	v0, zero, 1f			# check which exp is larger
745	move	t1, ta1				# result exp is FTs
746	move	t2, zero			# FSs fraction shifted is zero
747	b	4f
7481:
749	move	ta2, zero			# FTs fraction shifted is zero
750	b	4f
7512:
752	li	t9, 32				# compute 32 - abs(exp diff)
753	subu	t9, t9, v1
754	bgt	v0, zero, 3f			# if FS > FT, shift FTs frac
755	move	t1, ta1				# FT > FS, result exp is FTs
756	sll	t8, t2, t9			# save bits shifted out
757	srl	t2, t2, v1			# shift FSs fraction
758	b	4f
7593:
760	sll	t8, ta2, t9			# save bits shifted out
761	srl	ta2, ta2, v1			# shift FTs fraction
7624:
763	bne	t0, ta0, 1f			# if signs differ, subtract
764	addu	t2, t2, ta2			# add fractions
765	b	norm_s
7661:
767	blt	t2, ta2, 3f			# subtract larger from smaller
768	bne	t2, ta2, 2f			# if same, result=0
769	move	t1, zero			# result=0
770	move	t2, zero
771	and	v0, a2, MIPS_FPU_ROUNDING_BITS	# get rounding mode
772	bne	v0, MIPS_FPU_ROUND_RM, 1f	# round to -infinity?
773	or	t0, t0, ta0			# compute result sign
774	b	result_fs_s
7751:
776	and	t0, t0, ta0			# compute result sign
777	b	result_fs_s
7782:
779	sltu	t9, zero, t8			# compute t2:zero - ta2:t8
780	subu	t8, zero, t8
781	subu	t2, t2, ta2			# subtract fractions
782	subu	t2, t2, t9			# subtract barrow
783	b	norm_s
7843:
785	move	t0, ta0				# sign of result = FTs
786	sltu	t9, zero, t8			# compute ta2:zero - t2:t8
787	subu	t8, zero, t8
788	subu	t2, ta2, t2			# subtract fractions
789	subu	t2, t2, t9			# subtract barrow
790	b	norm_s
791
792/*
793 * Double precision subtract.
794 */
795sub_d:
796	jal	_C_LABEL(get_ft_fs_d)
797	xor	ta0, ta0, 1			# negate sign bit
798	b	add_sub_d
799/*
800 * Double precision add.
801 */
802add_d:
803	jal	_C_LABEL(get_ft_fs_d)
804add_sub_d:
805	bne	t1, DEXP_INF, 1f		# is FS an infinity?
806	bne	ta1, DEXP_INF, result_fs_d	# if FT is not inf, result=FS
807	bne	t2, zero, result_fs_d		# if FS is NAN, result is FS
808	bne	t3, zero, result_fs_d
809	bne	ta2, zero, result_ft_d		# if FT is NAN, result is FT
810	bne	ta3, zero, result_ft_d
811	bne	t0, ta0, invalid_d		# both infinities same sign?
812	b	result_fs_d			# result is in FS
8131:
814	beq	ta1, DEXP_INF, result_ft_d	# if FT is inf, result=FT
815	bne	t1, zero, 4f			# is FS a denormalized num?
816	bne	t2, zero, 1f			# is FS zero?
817	beq	t3, zero, 3f
8181:
819	bne	ta1, zero, 2f			# is FT a denormalized num?
820	bne	ta2, zero, 1f
821	beq	ta3, zero, result_fs_d		# FT is zero, result=FS
8221:
823	jal	_C_LABEL(renorm_fs_d)
824	jal	_C_LABEL(renorm_ft_d)
825	b	5f
8262:
827	jal	_C_LABEL(renorm_fs_d)
828	subu	ta1, ta1, DEXP_BIAS		# unbias FT exponent
829	or	ta2, ta2, DIMPL_ONE		# set implied one bit
830	b	5f
8313:
832	bne	ta1, zero, result_ft_d		# if FT != 0, result=FT
833	bne	ta2, zero, result_ft_d
834	bne	ta3, zero, result_ft_d
835	and	v0, a2, MIPS_FPU_ROUNDING_BITS	# get rounding mode
836	bne	v0, MIPS_FPU_ROUND_RM, 1f	# round to -infinity?
837	or	t0, t0, ta0			# compute result sign
838	b	result_fs_d
8391:
840	and	t0, t0, ta0			# compute result sign
841	b	result_fs_d
8424:
843	bne	ta1, zero, 2f			# is FT a denormalized num?
844	bne	ta2, zero, 1f
845	beq	ta3, zero, result_fs_d		# FT is zero, result=FS
8461:
847	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
848	or	t2, t2, DIMPL_ONE		# set implied one bit
849	jal	_C_LABEL(renorm_ft_d)
850	b	5f
8512:
852	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
853	or	t2, t2, DIMPL_ONE		# set implied one bit
854	subu	ta1, ta1, DEXP_BIAS		# unbias FT exponent
855	or	ta2, ta2, DIMPL_ONE		# set implied one bit
856/*
857 * Perform the addition.
858 */
8595:
860	move	t8, zero			# no shifted bits (sticky reg)
861	beq	t1, ta1, 4f			# no shift needed
862	subu	v0, t1, ta1			# v0 = difference of exponents
863	move	v1, v0				# v1 = abs(difference)
864	bge	v0, zero, 1f
865	negu	v1
8661:
867	ble	v1, DFRAC_BITS+2, 2f		# is difference too great?
868	li	t8, STICKYBIT			# set the sticky bit
869	bge	v0, zero, 1f			# check which exp is larger
870	move	t1, ta1				# result exp is FTs
871	move	t2, zero			# FSs fraction shifted is zero
872	move	t3, zero
873	b	4f
8741:
875	move	ta2, zero			# FTs fraction shifted is zero
876	move	ta3, zero
877	b	4f
8782:
879	li	t9, 32
880	bge	v0, zero, 3f			# if FS > FT, shift FTs frac
881	move	t1, ta1				# FT > FS, result exp is FTs
882	blt	v1, t9, 1f			# shift right by < 32?
883	subu	v1, v1, t9
884	subu	t9, t9, v1
885	sll	t8, t2, t9			# save bits shifted out
886	sltu	t9, zero, t3			# dont lose any one bits
887	or	t8, t8, t9			# save sticky bit
888	srl	t3, t2, v1			# shift FSs fraction
889	move	t2, zero
890	b	4f
8911:
892	subu	t9, t9, v1
893	sll	t8, t3, t9			# save bits shifted out
894	srl	t3, t3, v1			# shift FSs fraction
895	sll	t9, t2, t9			# save bits shifted out of t2
896	or	t3, t3, t9			# and put into t3
897	srl	t2, t2, v1
898	b	4f
8993:
900	blt	v1, t9, 1f			# shift right by < 32?
901	subu	v1, v1, t9
902	subu	t9, t9, v1
903	sll	t8, ta2, t9			# save bits shifted out
904	srl	ta3, ta2, v1			# shift FTs fraction
905	move	ta2, zero
906	b	4f
9071:
908	subu	t9, t9, v1
909	sll	t8, ta3, t9			# save bits shifted out
910	srl	ta3, ta3, v1			# shift FTs fraction
911	sll	t9, ta2, t9			# save bits shifted out of t2
912	or	ta3, ta3, t9			# and put into t3
913	srl	ta2, ta2, v1
9144:
915	bne	t0, ta0, 1f			# if signs differ, subtract
916	addu	t3, t3, ta3			# add fractions
917	sltu	t9, t3, ta3			# compute carry
918	addu	t2, t2, ta2			# add fractions
919	addu	t2, t2, t9			# add carry
920	b	norm_d
9211:
922	blt	t2, ta2, 3f			# subtract larger from smaller
923	bne	t2, ta2, 2f
924	bltu	t3, ta3, 3f
925	bne	t3, ta3, 2f			# if same, result=0
926	move	t1, zero			# result=0
927	move	t2, zero
928	move	t3, zero
929	and	v0, a2, MIPS_FPU_ROUNDING_BITS	# get rounding mode
930	bne	v0, MIPS_FPU_ROUND_RM, 1f	# round to -infinity?
931	or	t0, t0, ta0			# compute result sign
932	b	result_fs_d
9331:
934	and	t0, t0, ta0			# compute result sign
935	b	result_fs_d
9362:
937	beq	t8, zero, 1f			# compute t2:t3:zero - ta2:ta3:t8
938	subu	t8, zero, t8
939	sltu	v0, t3, 1			# compute barrow out
940	subu	t3, t3, 1			# subtract barrow
941	subu	t2, t2, v0
9421:
943	sltu	v0, t3, ta3
944	subu	t3, t3, ta3			# subtract fractions
945	subu	t2, t2, ta2			# subtract fractions
946	subu	t2, t2, v0			# subtract barrow
947	b	norm_d
9483:
949	move	t0, ta0				# sign of result = FTs
950	beq	t8, zero, 1f			# compute ta2:ta3:zero - t2:t3:t8
951	subu	t8, zero, t8
952	sltu	v0, ta3, 1			# compute barrow out
953	subu	ta3, ta3, 1			# subtract barrow
954	subu	ta2, ta2, v0
9551:
956	sltu	v0, ta3, t3
957	subu	t3, ta3, t3			# subtract fractions
958	subu	t2, ta2, t2			# subtract fractions
959	subu	t2, t2, v0			# subtract barrow
960	b	norm_d
961
962/*
963 * Single precision multiply.
964 */
965mul_s:
966	jal	_C_LABEL(get_ft_fs_s)
967	xor	t0, t0, ta0			# compute sign of result
968	move	ta0, t0
969	bne	t1, SEXP_INF, 2f		# is FS an infinity?
970	bne	t2, zero, result_fs_s		# if FS is a NAN, result=FS
971	bne	ta1, SEXP_INF, 1f		# FS is inf, is FT an infinity?
972	bne	ta2, zero, result_ft_s		# if FT is a NAN, result=FT
973	b	result_fs_s			# result is infinity
9741:
975	bne	ta1, zero, result_fs_s		# inf * zero? if no, result=FS
976	bne	ta2, zero, result_fs_s
977	b	invalid_s			# infinity * zero is invalid
9782:
979	bne	ta1, SEXP_INF, 1f		# FS != inf, is FT an infinity?
980	bne	t1, zero, result_ft_s		# zero * inf? if no, result=FT
981	bne	t2, zero, result_ft_s
982	bne	ta2, zero, result_ft_s		# if FT is a NAN, result=FT
983	b	invalid_s			# zero * infinity is invalid
9841:
985	bne	t1, zero, 1f			# is FS zero?
986	beq	t2, zero, result_fs_s		# result is zero
987	jal	_C_LABEL(renorm_fs_s)
988	b	2f
9891:
990	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
991	or	t2, t2, SIMPL_ONE		# set implied one bit
9922:
993	bne	ta1, zero, 1f			# is FT zero?
994	beq	ta2, zero, result_ft_s		# result is zero
995	jal	_C_LABEL(renorm_ft_s)
996	b	2f
9971:
998	subu	ta1, ta1, SEXP_BIAS		# unbias FT exponent
999	or	ta2, ta2, SIMPL_ONE		# set implied one bit
10002:
1001	addu	t1, t1, ta1			# compute result exponent
1002	addu	t1, t1, 9			# account for binary point
1003	multu	t2, ta2				# multiply fractions
1004	mflo	t8
1005	mfhi	t2
1006	b	norm_s
1007
1008/*
1009 * Double precision multiply.
1010 */
1011mul_d:
1012	jal	_C_LABEL(get_ft_fs_d)
1013	xor	t0, t0, ta0			# compute sign of result
1014	move	ta0, t0
1015	bne	t1, DEXP_INF, 2f		# is FS an infinity?
1016	bne	t2, zero, result_fs_d		# if FS is a NAN, result=FS
1017	bne	t3, zero, result_fs_d
1018	bne	ta1, DEXP_INF, 1f		# FS is inf, is FT an infinity?
1019	bne	ta2, zero, result_ft_d		# if FT is a NAN, result=FT
1020	bne	ta3, zero, result_ft_d
1021	b	result_fs_d			# result is infinity
10221:
1023	bne	ta1, zero, result_fs_d		# inf * zero? if no, result=FS
1024	bne	ta2, zero, result_fs_d
1025	bne	ta3, zero, result_fs_d
1026	b	invalid_d			# infinity * zero is invalid
10272:
1028	bne	ta1, DEXP_INF, 1f		# FS != inf, is FT an infinity?
1029	bne	t1, zero, result_ft_d		# zero * inf? if no, result=FT
1030	bne	t2, zero, result_ft_d		# if FS is a NAN, result=FS
1031	bne	t3, zero, result_ft_d
1032	bne	ta2, zero, result_ft_d		# if FT is a NAN, result=FT
1033	bne	ta3, zero, result_ft_d
1034	b	invalid_d			# zero * infinity is invalid
10351:
1036	bne	t1, zero, 2f			# is FS zero?
1037	bne	t2, zero, 1f
1038	beq	t3, zero, result_fs_d		# result is zero
10391:
1040	jal	_C_LABEL(renorm_fs_d)
1041	b	3f
10422:
1043	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
1044	or	t2, t2, DIMPL_ONE		# set implied one bit
10453:
1046	bne	ta1, zero, 2f			# is FT zero?
1047	bne	ta2, zero, 1f
1048	beq	ta3, zero, result_ft_d		# result is zero
10491:
1050	jal	_C_LABEL(renorm_ft_d)
1051	b	3f
10522:
1053	subu	ta1, ta1, DEXP_BIAS		# unbias FT exponent
1054	or	ta2, ta2, DIMPL_ONE		# set implied one bit
10553:
1056	addu	t1, t1, ta1			# compute result exponent
1057	addu	t1, t1, 12			# ???
1058	multu	t3, ta3				# multiply fractions (low * low)
1059	move	ta0, t2				# free up t2,t3 for result
1060	move	ta1, t3
1061	mflo	a3				# save low order bits
1062	mfhi	t8
1063	not	v0, t8
1064	multu	ta0, ta3				# multiply FS(high) * FT(low)
1065	mflo	v1
1066	mfhi	t3				# init low result
1067	sltu	v0, v0, v1			# compute carry
1068	addu	t8, v1
1069	multu	ta1, ta2				# multiply FS(low) * FT(high)
1070	addu	t3, t3, v0			# add carry
1071	not	v0, t8
1072	mflo	v1
1073	mfhi	t2
1074	sltu	v0, v0, v1
1075	addu	t8, v1
1076	multu	ta0, ta2				# multiply FS(high) * FT(high)
1077	addu	t3, v0
1078	not	v1, t3
1079	sltu	v1, v1, t2
1080	addu	t3, t2
1081	not	v0, t3
1082	mfhi	t2
1083	addu	t2, v1
1084	mflo	v1
1085	sltu	v0, v0, v1
1086	addu	t2, v0
1087	addu	t3, v1
1088	sltu	a3, zero, a3			# reduce t8,a3 to just t8
1089	or	t8, a3
1090	b	norm_d
1091
1092/*
1093 * Single precision divide.
1094 */
1095div_s:
1096	jal	_C_LABEL(get_ft_fs_s)
1097	xor	t0, t0, ta0			# compute sign of result
1098	move	ta0, t0
1099	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1100	bne	t2, zero, result_fs_s		# if FS is NAN, result is FS
1101	bne	ta1, SEXP_INF, result_fs_s	# is FT an infinity?
1102	bne	ta2, zero, result_ft_s		# if FT is NAN, result is FT
1103	b	invalid_s			# infinity/infinity is invalid
11041:
1105	bne	ta1, SEXP_INF, 1f		# is FT an infinity?
1106	bne	ta2, zero, result_ft_s		# if FT is NAN, result is FT
1107	move	t1, zero			# x / infinity is zero
1108	move	t2, zero
1109	b	result_fs_s
11101:
1111	bne	t1, zero, 2f			# is FS zero?
1112	bne	t2, zero, 1f
1113	bne	ta1, zero, result_fs_s		# FS=zero, is FT zero?
1114	beq	ta2, zero, invalid_s		# 0 / 0
1115	b	result_fs_s			# result = zero
11161:
1117	jal	_C_LABEL(renorm_fs_s)
1118	b	3f
11192:
1120	subu	t1, t1, SEXP_BIAS		# unbias FS exponent
1121	or	t2, t2, SIMPL_ONE		# set implied one bit
11223:
1123	bne	ta1, zero, 2f			# is FT zero?
1124	bne	ta2, zero, 1f
1125	or	a2, a2, MIPS_FPU_EXCEPTION_DIV0 | MIPS_FPU_STICKY_DIV0
1126	and	v0, a2, MIPS_FPU_ENABLE_DIV0	# trap enabled?
1127	bne	v0, zero, fpe_trap
1128#ifdef SOFTFLOAT
1129	lw	t1, _C_LABEL(curpcb)		# get pcb of current process
1130	#nop
1131	sw	a2, U_PCB_FPREGS+FRAME_FSR(t1)
1132#else
1133	ctc1	a2, MIPS_FPU_CSR		# save exceptions
1134#endif
1135	li	t1, SEXP_INF			# result is infinity
1136	move	t2, zero
1137	b	result_fs_s
11381:
1139	jal	_C_LABEL(renorm_ft_s)
1140	b	3f
11412:
1142	subu	ta1, ta1, SEXP_BIAS		# unbias FT exponent
1143	or	ta2, ta2, SIMPL_ONE		# set implied one bit
11443:
1145	subu	t1, t1, ta1			# compute exponent
1146	subu	t1, t1, 3			# compensate for result position
1147	li	v0, SFRAC_BITS+3		# number of bits to divide
1148	move	t8, t2				# init dividend
1149	move	t2, zero			# init result
11501:
1151	bltu	t8, ta2, 3f			# is dividend >= divisor?
11522:
1153	subu	t8, t8, ta2			# subtract divisor from dividend
1154	or	t2, t2, 1			# remember that we did
1155	bne	t8, zero, 3f			# if not done, continue
1156	sll	t2, t2, v0			# shift result to final position
1157	b	norm_s
11583:
1159	sll	t8, t8, 1			# shift dividend
1160	sll	t2, t2, 1			# shift result
1161	subu	v0, v0, 1			# are we done?
1162	bne	v0, zero, 1b			# no, continue
1163	b	norm_s
1164
1165/*
1166 * Double precision divide.
1167 */
1168div_d:
1169	jal	_C_LABEL(get_ft_fs_d)
1170	xor	t0, t0, ta0			# compute sign of result
1171	move	ta0, t0
1172	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1173	bne	t2, zero, result_fs_d		# if FS is NAN, result is FS
1174	bne	t3, zero, result_fs_d
1175	bne	ta1, DEXP_INF, result_fs_d	# is FT an infinity?
1176	bne	ta2, zero, result_ft_d		# if FT is NAN, result is FT
1177	bne	ta3, zero, result_ft_d
1178	b	invalid_d			# infinity/infinity is invalid
11791:
1180	bne	ta1, DEXP_INF, 1f		# is FT an infinity?
1181	bne	ta2, zero, result_ft_d		# if FT is NAN, result is FT
1182	bne	ta3, zero, result_ft_d
1183	move	t1, zero			# x / infinity is zero
1184	move	t2, zero
1185	move	t3, zero
1186	b	result_fs_d
11871:
1188	bne	t1, zero, 2f			# is FS zero?
1189	bne	t2, zero, 1f
1190	bne	t3, zero, 1f
1191	bne	ta1, zero, result_fs_d		# FS=zero, is FT zero?
1192	bne	ta2, zero, result_fs_d
1193	beq	ta3, zero, invalid_d		# 0 / 0
1194	b	result_fs_d			# result = zero
11951:
1196	jal	_C_LABEL(renorm_fs_d)
1197	b	3f
11982:
1199	subu	t1, t1, DEXP_BIAS		# unbias FS exponent
1200	or	t2, t2, DIMPL_ONE		# set implied one bit
12013:
1202	bne	ta1, zero, 2f			# is FT zero?
1203	bne	ta2, zero, 1f
1204	bne	ta3, zero, 1f
1205	or	a2, a2, MIPS_FPU_EXCEPTION_DIV0 | MIPS_FPU_STICKY_DIV0
1206	and	v0, a2, MIPS_FPU_ENABLE_DIV0	# trap enabled?
1207	bne	v0, zero, fpe_trap
1208#ifdef SOFTFLOAT
1209	lw	t1, _C_LABEL(curpcb)		# get pcb of current process
1210	#nop
1211	sw	a2, U_PCB_FPREGS+FRAME_FSR(t1)
1212#else
1213	ctc1	a2, MIPS_FPU_CSR		# save exceptions
1214#endif
1215	li	t1, DEXP_INF			# result is infinity
1216	move	t2, zero
1217	move	t3, zero
1218	b	result_fs_d
12191:
1220	jal	_C_LABEL(renorm_ft_d)
1221	b	3f
12222:
1223	subu	ta1, ta1, DEXP_BIAS		# unbias FT exponent
1224	or	ta2, ta2, DIMPL_ONE		# set implied one bit
12253:
1226	subu	t1, t1, ta1			# compute exponent
1227	subu	t1, t1, 3			# compensate for result position
1228	li	v0, DFRAC_BITS+3		# number of bits to divide
1229	move	t8, t2				# init dividend
1230	move	t9, t3
1231	move	t2, zero			# init result
1232	move	t3, zero
12331:
1234	bltu	t8, ta2, 3f			# is dividend >= divisor?
1235	bne	t8, ta2, 2f
1236	bltu	t9, ta3, 3f
12372:
1238	sltu	v1, t9, ta3			# subtract divisor from dividend
1239	subu	t9, t9, ta3
1240	subu	t8, t8, ta2
1241	subu	t8, t8, v1
1242	or	t3, t3, 1			# remember that we did
1243	bne	t8, zero, 3f			# if not done, continue
1244	bne	t9, zero, 3f
1245	li	v1, 32				# shift result to final position
1246	blt	v0, v1, 2f			# shift < 32 bits?
1247	subu	v0, v0, v1			# shift by > 32 bits
1248	sll	t2, t3, v0			# shift upper part
1249	move	t3, zero
1250	b	norm_d
12512:
1252	subu	v1, v1, v0			# shift by < 32 bits
1253	sll	t2, t2, v0			# shift upper part
1254	srl	t9, t3, v1			# save bits shifted out
1255	or	t2, t2, t9			# and put into upper part
1256	sll	t3, t3, v0
1257	b	norm_d
12583:
1259	sll	t8, t8, 1			# shift dividend
1260	srl	v1, t9, 31			# save bit shifted out
1261	or	t8, t8, v1			# and put into upper part
1262	sll	t9, t9, 1
1263	sll	t2, t2, 1			# shift result
1264	srl	v1, t3, 31			# save bit shifted out
1265	or	t2, t2, v1			# and put into upper part
1266	sll	t3, t3, 1
1267	subu	v0, v0, 1			# are we done?
1268	bne	v0, zero, 1b			# no, continue
1269	sltu	v0, zero, t9			# be sure to save any one bits
1270	or	t8, t8, v0			# from the lower remainder
1271	b	norm_d
1272
1273#ifdef MIPS3_PLUS
1274sqrt_s:
1275	jal	_C_LABEL(get_fs_s)
1276
1277	/* Take care of zero, negative, inf, and NaN special cases */
1278	or	v0, t1, t2			# sqrt(+-0) == +-0
1279	beq	v0, zero, result_fs_s		# ...
1280	bne	t0, zero, 1f			# sqrt(-val) == sNaN
1281	bne	t1, SEXP_INF, 2f		# skip forward if not infinity
1282	b	result_fs_s			# sqrt(NaN,+inf) == itself
12831:	move	t0, zero			# result is a quiet NAN
1284	li	t1, SEXP_INF			# sqrt(-inf,-val) == sNaN
1285	li	t2, SQUIET_NAN
1286	b	result_fs_s
12872:
1288	/* normalize FS if needed */
1289	bne	t1, zero, 2f
1290	jal	_C_LABEL(renorm_fs_s)
12912:	and	t2, t2, (SIMPL_ONE-1)		# ix &= 0x007fffff;
1292	or	t2, t2, SIMPL_ONE		# ix |= 0x00800000;
1293	and	v0, t1, 1			# if (m & 1)
1294	beq	v0, zero, 1f			# ...
1295	add	t2, t2, t2			#	ix += ix;
12961:	sra	t1, t1, 1			# m = m / 2;
1297
1298	/* generate sqrt(FS) bit by bit */
1299	add	t2, t2, t2			# ix += ix;
1300	move	ta0, zero			# q = 0; (result)
1301	li	t8, SIMPL_ONE<<1		# r = 0x01000000;
1302	move	ta2, zero			# s = 0;
13031:	beq	t8, zero, 3f			# while (r != 0) {
1304	add	t9, ta2, t8			#	t = s + r;
1305	bgt	t9, t2, 2f			#	if (t <= ix)
1306	add	ta2, t9, t8			#		s = t + r;
1307	sub	t2, t2, t9			#		ix -= t;
1308	add	ta0, ta0, t8			#		q += r;
13092:	add	t2, t2, t2			#	ix += ix;
1310	srl	t8, t8, 1			# 	r >>= 1;
1311	b	1b				# }
13123:
1313	/* rounding -- all mips rounding modes use the same rounding here */
1314	beq	t2, zero, 1f			# if (ix != 0)
1315	and	v0, ta0, 1			# q += q&1;
1316	add	ta0, ta0, v0			# ...
1317
1318	/* calculate result */
13191:	srl	t2, ta0, 1			# ix = (q >> 1);
1320	add	t1, t1, SEXP_BIAS 		# m += 127; (re-bias)
1321	li	v1, SIMPL_ONE
1322	and	v0, t2, v1			# keep extra exponent bit
1323	bne	v0, zero, 1f			# if it is there.
1324	sub	t1, t1, 1			# ...
13251:
1326	nor	v1, v1, v1			# ~SIMP_ONE
1327	and	t2, t2, v1			# ix &= ~SIMPL_ONE
1328	b	result_fs_s			# store result (already normal)
1329
1330sqrt_d:
1331	jal	_C_LABEL(get_fs_d)
1332
1333	/* Take care of zero, negative, inf, and NaN special cases */
1334	or	v0, t1, t2			# sqrt(+-0) == +- 0
1335	or	v0, v0, t3			# ...
1336	beq	v0, zero, result_fs_d		# ...
1337	bne	t0, zero, 1f			# sqrt(-val) == sNaN
1338	bne	t1, DEXP_INF, 2f		# skip forward if not infinity
1339	b	result_fs_d			# sqrt(NaN,+inf) == itself
13401:	move	t0, zero			# sqrt(-inf,-val) == sNaN
1341	li	t1, DEXP_INF
1342	li	t2, DQUIET_NAN0
1343	li	t3, DQUIET_NAN1
1344	b	result_fs_d
13452:
1346	/* normalize FS if needed */
1347	bne	t1, zero, 2f
1348	jal	_C_LABEL(renorm_fs_d)
13492:	and	t2, t2, (DIMPL_ONE-1)		# ix0 &= 0x000fffff
1350	or	t2, t2, DIMPL_ONE		# ix0 |= 0x00100000
1351	and	v0, t1, 1			# if (m & 1)
1352	beq	v0, zero, 1f			# ...
1353	add	t2, t2, t2			# ix0 += ix0
1354	srl	v0, t3, 31			# ix0 += (ix1&sign)>>31)
1355	and	v0, v0, 1			# ...
1356	add	t2, t2, v0			# ...
1357	addu	t3, t3, t3			# ix1 += ix1;
13581:	sra	t1, t1, 1			# m = m / 2;
1359
1360	/* generate sqrt(FS) bit by bit -- first upper */
1361	addu	t2, t2, t2			# ix0 += ix0;
1362	srl	v0, t3, 31			# ix0 += (ix1&sign)>>31)
1363	and	v0, v0, 1			# ...
1364	add	t2, t2, v0			# ...
1365	addu	t3, t3, t3			# ix1 += ix1;
1366
1367	move	ta0, zero			# q = 0;	(result)
1368	move	ta1, zero			# q1 = 0;	(result)
1369	move	ta2, zero			# s0 = 0;
1370	move	ta3, zero			# s1 = 0;
1371	li	t8, DIMPL_ONE<<1		# t = 0x00200000;
13721:	beq	t8, zero, 3f			# while (r != 0) {
1373	add	t9, ta2, t8			#	t = s0+r;
1374	bgt	t9, t2, 2f			#	if (t <= ix0)
1375	add	ta2, t9, t8			#		s0 = t + r;
1376	sub	t2, t2, t9			#		ix0 -= t;
1377	add	ta0, ta0, t8			#		q += r;
13782:	add	t2, t2, t2			#	ix0 += ix0;
1379	srl	v0, t3, 31			# 	ix0 += (ix1&sign)>>31)
1380	and	v0, v0, 1			# 	...
1381	add	t2, t2, v0			# 	...
1382	addu	t3, t3, t3			#	ix1 += ix1;
1383	srl	t8, t8, 1			#	r >>= 1;
1384	b	1b				# }
13853:
1386	/* then lower bits */
1387	li	t8, 1<<31			# r = sign;
13881:	beq	t8, zero, 4f			# while (r != 0) {
1389	addu	v1, ta3, t8			#    t1 = s1 + r;
1390	move	t9, ta2				#    t = s0;
1391	blt	t9, t2, 2f			#    if ( (t<ix0) ||
1392	bne	t9, t2, 3f			#         ((t == ix0) &&
1393	bgtu	v1, t3, 3f			#          (t1 <= ix1)))
13942:	addu	ta3, v1, t8			#	s1 = t1 + r;
1395	srl	v0, v1, 31			#	if (((t1&sign)==sign) &&
1396	and	v0, v0, 1			#	...
1397	beq	v0, zero, 2f			#	...
1398	srl	v0, ta3, 31			#	    (s1&sign) == 0)
1399	and	v0, v0, 1			#	    ...
1400	bne	v0, zero, 2f			#	    ...
1401	add	ta2, ta2, 1			#	    s0 += 1;
14022:	sub	t2, t2, t9			#	ix0 -= t;
1403	bgeu	t3, v1, 2f			#	if (ix1 < t1)
1404	sub	t2, t2, 1			#	    ix0 -= 1;
14052:	subu	t3, t3, v1			#	ix1 -= t1;
1406	addu	ta1, ta1, t8			#	q1 += r;
14073:	add	t2, t2, t2			#    ix0 += ix0;
1408	srl	v0, t3, 31			#    ix0 += (ix1&sign)>>31)
1409	and	v0, v0, 1			#    ...
1410	add	t2, t2, v0			#    ...
1411	addu	t3, t3, t3			#    ix1 += ix1;
1412	srl	t8, t8, 1			#    r >>= 1;
1413	b	1b				# }
14144:
1415
1416	/* rounding -- all mips rounding modes use the same rounding here */
1417	or	v0, t2, t3			# if (ix0 | ix1)
1418	beq	v0, zero, 2f			# ...
1419	li	v0, 0xffffffff			#    if (q1 == 0xffffffff)
1420	and	v1, t2, v0			#    ...
1421	bne	v1, v0, 1f			#    ...
1422	move	ta1, zero			#	q1 = 0;
1423	add	ta0, ta0, 1			#	q += 1;
1424	b	2f				#    else
14251:	and	v0, ta1, 1			#       q1 += q1 & 1;
1426	addu	ta1, ta1, v0			#       ...
1427
1428	/* calculate result */
14292:	srl	t2, ta0, 1			# ix0 = q >> 1;
1430	srl	t3, ta1, 1			# ix1 = q1 >> 1;
1431	and	v0, ta0, 1			# if ((q & 1) == 1)
1432	beq	v0, zero, 1f			# ...
1433	or	t3, (1<<31)			#	ix1 |= sign;
14341:	add	t1, t1, DEXP_BIAS		# m += 1023;
1435	li	v1, DIMPL_ONE
1436	and	v0, t2, v1			# keep extra exponent bit
1437	bne	v0, zero, 1f			# if it is there.
1438	sub	t1, t1, 1			# ...
14391:
1440	nor	v1, v1, v1			# ~DIMPL_ONE
1441	and	t2, t2, v1			# ix0 &= ~DIMPL_ONE
1442	b	result_fs_d			# store result (already normal)
1443#endif	/* MIPS3_PLUS */
1444
1445/*
1446 * Single precision absolute value.
1447 */
1448abs_s:
1449	jal	_C_LABEL(get_fs_s)
1450	move	t0, zero			# set sign positive
1451	b	result_fs_s
1452
1453/*
1454 * Double precision absolute value.
1455 */
1456abs_d:
1457	jal	_C_LABEL(get_fs_d)
1458	move	t0, zero			# set sign positive
1459	b	result_fs_d
1460
1461/*
1462 * Single precision move.
1463 */
1464mov_s:
1465	jal	_C_LABEL(get_fs_s)
1466	b	result_fs_s
1467
1468/*
1469 * Double precision move.
1470 */
1471mov_d:
1472	jal	_C_LABEL(get_fs_d)
1473	b	result_fs_d
1474
1475/*
1476 * Single precision negate.
1477 */
1478neg_s:
1479	jal	_C_LABEL(get_fs_s)
1480	xor	t0, t0, 1			# reverse sign
1481	b	result_fs_s
1482
1483/*
1484 * Double precision negate.
1485 */
1486neg_d:
1487	jal	_C_LABEL(get_fs_d)
1488	xor	t0, t0, 1			# reverse sign
1489	b	result_fs_d
1490
1491/*
1492 * Single precision mips2 rounding.  Explicit case of cvt_w_s.
1493 */
1494round_w_s:
1495	li	v1,0
1496	b	_cvt_w_s
1497trunc_w_s:
1498	li	v1,1
1499	b	_cvt_w_s
1500ceil_w_s:
1501	li	v1,2
1502	b	_cvt_w_s
1503floor_w_s:
1504	li	v1,3
1505	b	_cvt_w_s
1506
1507/*
1508 * Double precision mips2 rounding.  Explicit case of cvt_w_d.
1509 */
1510round_w_d:
1511	li	v1,0
1512	b	_cvt_w_d
1513trunc_w_d:
1514	li	v1,1
1515	b	_cvt_w_d
1516ceil_w_d:
1517	li	v1,2
1518	b	_cvt_w_d
1519floor_w_d:
1520	li	v1,3
1521	b	_cvt_w_d
1522
1523/*
1524 * Convert double to single.
1525 */
1526cvt_s_d:
1527	jal	_C_LABEL(get_fs_d)
1528	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1529	li	t1, SEXP_INF			# convert to single
1530	sll	t2, t2, 3			# convert D fraction to S
1531	srl	t8, t3, 32 - 3
1532	or	t2, t2, t8
1533	b	result_fs_s
15341:
1535	bne	t1, zero, 2f			# is FS zero?
1536	bne	t2, zero, 1f
1537	beq	t3, zero, result_fs_s		# result=0
15381:
1539	jal	_C_LABEL(renorm_fs_d)
1540	subu	t1, t1, 3			# correct exp for shift below
1541	b	3f
15422:
1543	subu	t1, t1, DEXP_BIAS		# unbias exponent
1544	or	t2, t2, DIMPL_ONE		# add implied one bit
15453:
1546	sll	t2, t2, 3			# convert D fraction to S
1547	srl	t8, t3, 32 - 3
1548	or	t2, t2, t8
1549	sll	t8, t3, 3
1550	b	norm_noshift_s
1551
1552/*
1553 * Convert integer to single.
1554 */
1555cvt_s_w:
1556	jal	_C_LABEL(get_fs_int)
1557	bne	t2, zero, 1f			# check for zero
1558	move	t1, zero
1559	b	result_fs_s
1560/*
1561 * Find out how many leading zero bits are in t2 and put in t9.
1562 */
15631:
1564	move	v0, t2
1565	move	t9, zero
1566	srl	v1, v0, 16
1567	bne	v1, zero, 1f
1568	addu	t9, 16
1569	sll	v0, 16
15701:
1571	srl	v1, v0, 24
1572	bne	v1, zero, 1f
1573	addu	t9, 8
1574	sll	v0, 8
15751:
1576	srl	v1, v0, 28
1577	bne	v1, zero, 1f
1578	addu	t9, 4
1579	sll	v0, 4
15801:
1581	srl	v1, v0, 30
1582	bne	v1, zero, 1f
1583	addu	t9, 2
1584	sll	v0, 2
15851:
1586	srl	v1, v0, 31
1587	bne	v1, zero, 1f
1588	addu	t9, 1
1589/*
1590 * Now shift t2 the correct number of bits.
1591 */
15921:
1593	subu	t9, t9, SLEAD_ZEROS		# dont count leading zeros
1594	li	t1, 23				# init exponent
1595	subu	t1, t1, t9			# compute exponent
1596	beq	t9, zero, 1f
1597	li	v0, 32
1598	blt	t9, zero, 2f			# if shift < 0, shift right
1599	subu	v0, v0, t9
1600	sll	t2, t2, t9			# shift left
16011:
1602	add	t1, t1, SEXP_BIAS		# bias exponent
1603	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
1604	b	result_fs_s
16052:
1606	negu	t9				# shift right by t9
1607	subu	v0, v0, t9
1608	sll	t8, t2, v0			# save bits shifted out
1609	srl	t2, t2, t9
1610	b	norm_noshift_s
1611
1612/*
1613 * Convert single to double.
1614 */
1615cvt_d_s:
1616	jal	_C_LABEL(get_fs_s)
1617	move	t3, zero
1618	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1619	li	t1, DEXP_INF			# convert to double
1620	b	result_fs_d
16211:
1622	bne	t1, zero, 2f			# is FS denormalized or zero?
1623	beq	t2, zero, result_fs_d		# is FS zero?
1624	jal	_C_LABEL(renorm_fs_s)
1625	move	t8, zero
1626	b	norm_d
16272:
1628	addu	t1, t1, DEXP_BIAS - SEXP_BIAS	# bias exponent correctly
1629	sll	t3, t2, 32 - 3			# convert S fraction to D
1630	srl	t2, t2, 3
1631	b	result_fs_d
1632
1633/*
1634 * Convert integer to double.
1635 */
1636cvt_d_w:
1637	jal	_C_LABEL(get_fs_int)
1638	bne	t2, zero, 1f			# check for zero
1639	move	t1, zero			# result=0
1640	move	t3, zero
1641	b	result_fs_d
1642/*
1643 * Find out how many leading zero bits are in t2 and put in t9.
1644 */
16451:
1646	move	v0, t2
1647	move	t9, zero
1648	srl	v1, v0, 16
1649	bne	v1, zero, 1f
1650	addu	t9, 16
1651	sll	v0, 16
16521:
1653	srl	v1, v0, 24
1654	bne	v1, zero, 1f
1655	addu	t9, 8
1656	sll	v0, 8
16571:
1658	srl	v1, v0, 28
1659	bne	v1, zero, 1f
1660	addu	t9, 4
1661	sll	v0, 4
16621:
1663	srl	v1, v0, 30
1664	bne	v1, zero, 1f
1665	addu	t9, 2
1666	sll	v0, 2
16671:
1668	srl	v1, v0, 31
1669	bne	v1, zero, 1f
1670	addu	t9, 1
1671/*
1672 * Now shift t2 the correct number of bits.
1673 */
16741:
1675	subu	t9, t9, DLEAD_ZEROS		# dont count leading zeros
1676	li	t1, DEXP_BIAS + 20		# init exponent
1677	subu	t1, t1, t9			# compute exponent
1678	beq	t9, zero, 1f
1679	li	v0, 32
1680	blt	t9, zero, 2f			# if shift < 0, shift right
1681	subu	v0, v0, t9
1682	sll	t2, t2, t9			# shift left
16831:
1684	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1685	move	t3, zero
1686	b	result_fs_d
16872:
1688	negu	t9				# shift right by t9
1689	subu	v0, v0, t9
1690	sll	t3, t2, v0
1691	srl	t2, t2, t9
1692	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
1693	b	result_fs_d
1694
1695/*
1696 * Convert single to integer.
1697 */
1698cvt_w_s:
1699	and	v1, a2, MIPS_FPU_ROUNDING_BITS	# get rounding mode
1700_cvt_w_s:
1701	jal	_C_LABEL(get_fs_s)
1702	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1703	bne	t2, zero, invalid_w		# invalid conversion
17041:
1705	bne	t1, zero, 1f			# is FS zero?
1706	beq	t2, zero, result_fs_w		# result is zero
1707	move	t2, zero			# result is an inexact zero
1708	b	inexact_w
17091:
1710	subu	t1, t1, SEXP_BIAS		# unbias exponent
1711	or	t2, t2, SIMPL_ONE		# add implied one bit
1712	sll	t3, t2, 32 - 3			# convert S fraction to D
1713	srl	t2, t2, 3
1714	b	cvt_w
1715
1716/*
1717 * Convert double to integer.
1718 */
1719cvt_w_d:
1720	and	v1, a2, MIPS_FPU_ROUNDING_BITS	# get rounding mode
1721_cvt_w_d:
1722	jal	_C_LABEL(get_fs_d)
1723	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1724	bne	t2, zero, invalid_w		# invalid conversion
1725	bne	t3, zero, invalid_w		# invalid conversion
17261:
1727	bne	t1, zero, 2f			# is FS zero?
1728	bne	t2, zero, 1f
1729	beq	t3, zero, result_fs_w		# result is zero
17301:
1731	move	t2, zero			# result is an inexact zero
1732	b	inexact_w
17332:
1734	subu	t1, t1, DEXP_BIAS		# unbias exponent
1735	or	t2, t2, DIMPL_ONE		# add implied one bit
1736cvt_w:
1737#if 0
1738	blt	t1, WEXP_MIN, underflow_w	# is exponent too small?
1739#else
1740	bge	t1, WEXP_MIN, 3f		# is exponent too small?
1741	beq	v1, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
1742	beq	v1, MIPS_FPU_ROUND_RM, 2f	# round to -infinity
1743
1744	move	t2, zero
1745	b	result_fs_w
17461:
1747	xori	t2, t0, 1
1748	b	result_fs_w
17492:
1750	sll	t2, t0, 31
1751	sra	t2, t2, 31
1752	b	result_fs_w
1753
17543:
1755#endif
1756	li	v0, WEXP_MAX+1
1757	bgt	t1, v0, overflow_w		# is exponent too large?
1758	bne	t1, v0, 1f			# special check for INT_MIN
1759	beq	t0, zero, overflow_w		# if positive, overflow
1760	bne	t2, DIMPL_ONE, overflow_w
1761	bne	t3, zero, overflow_w
1762	li	t2, INT_MIN			# result is INT_MIN
1763	b	result_fs_w
17641:
1765	subu	v0, t1, 20			# compute amount to shift
1766	beq	v0, zero, 2f			# is shift needed?
1767	li	v1, 32
1768	blt	v0, zero, 1f			# if shift < 0, shift right
1769	subu	v1, v1, v0			# shift left
1770	sll	t2, t2, v0
1771	srl	t9, t3, v1			# save bits shifted out of t3
1772	or	t2, t2, t9			# and put into t2
1773	sll	t3, t3, v0			# shift FSs fraction
1774	b	2f
17751:
1776	negu	v0				# shift right by v0
1777	subu	v1, v1, v0
1778	sll	t8, t3, v1			# save bits shifted out
1779	sltu	t8, zero, t8			# dont lose any ones
1780	srl	t3, t3, v0			# shift FSs fraction
1781	or	t3, t3, t8
1782	sll	t9, t2, v1			# save bits shifted out of t2
1783	or	t3, t3, t9			# and put into t3
1784	srl	t2, t2, v0
1785/*
1786 * round result (t0 is sign, t2 is integer part, t3 is fractional part).
1787 */
17882:
1789	and	v0, a2, MIPS_FPU_ROUNDING_BITS	# get rounding mode
1790	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
1791	beq	v0, MIPS_FPU_ROUND_RZ, 5f	# round to zero (truncate)
1792	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
1793	beq	t0, zero, 5f			# if sign is positive, truncate
1794	b	2f
17951:
1796	bne	t0, zero, 5f			# if sign is negative, truncate
17972:
1798	beq	t3, zero, 5f			# if no fraction bits, continue
1799	addu	t2, t2, 1			# add rounding bit
1800	blt	t2, zero, overflow_w		# overflow?
1801	b	5f
18023:
1803	li	v0, GUARDBIT			# load guard bit for rounding
1804	addu	v0, v0, t3			# add remainder
1805	sltu	v1, v0, t3			# compute carry out
1806	beq	v1, zero, 4f			# if no carry, continue
1807	addu	t2, t2, 1			# add carry to result
1808	blt	t2, zero, overflow_w		# overflow?
18094:
1810	bne	v0, zero, 5f			# if rounded remainder is zero
1811	and	t2, t2, ~1			#  clear LSB (round to nearest)
18125:
1813	beq	t0, zero, 1f			# result positive?
1814	negu	t2				# convert to negative integer
18151:
1816	beq	t3, zero, result_fs_w		# is result exact?
1817/*
1818 * Handle inexact exception.
1819 */
1820inexact_w:
1821	or	a2, a2, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
1822	and	v0, a2, MIPS_FPU_ENABLE_INEXACT
1823	bne	v0, zero, fpe_trap
1824#ifdef SOFTFLOAT
1825	lw	v0, _C_LABEL(curpcb)		# get pcb of current process
1826	#nop
1827	sw	a2, U_PCB_FPREGS+FRAME_FSR(v0)
1828#else
1829	ctc1	a2, MIPS_FPU_CSR		# save exceptions
1830#endif
1831	b	result_fs_w
1832
1833/*
1834 * Conversions to integer which overflow will trap (if enabled),
1835 * or generate an inexact trap (if enabled),
1836 * or generate an invalid exception.
1837 */
1838overflow_w:
1839	or	a2, a2, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
1840	and	v0, a2, MIPS_FPU_ENABLE_OVERFLOW
1841	bne	v0, zero, fpe_trap
1842	and	v0, a2, MIPS_FPU_ENABLE_INEXACT
1843	bne	v0, zero, inexact_w		# inexact traps enabled?
1844	b	invalid_w
1845
1846/*
1847 * Conversions to integer which underflow will trap (if enabled),
1848 * or generate an inexact trap (if enabled),
1849 * or generate an invalid exception.
1850 */
1851underflow_w:
1852	or	a2, a2, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1853	and	v0, a2, MIPS_FPU_ENABLE_UNDERFLOW
1854	bne	v0, zero, fpe_trap
1855	and	v0, a2, MIPS_FPU_ENABLE_INEXACT
1856	bne	v0, zero, inexact_w		# inexact traps enabled?
1857	b	invalid_w
1858
1859/*
1860 * Compare single.
1861 */
1862cmp_s:
1863	jal	_C_LABEL(get_cmp_s)
1864	bne	t1, SEXP_INF, 1f		# is FS an infinity?
1865	bne	t2, zero, unordered		# FS is a NAN
18661:
1867	bne	ta1, SEXP_INF, 2f		# is FT an infinity?
1868	bne	ta2, zero, unordered		# FT is a NAN
18692:
1870	sll	t1, t1, 23			# reassemble exp & frac
1871	or	t1, t1, t2
1872	sll	ta1, ta1, 23			# reassemble exp & frac
1873	or	ta1, ta1, ta2
1874	beq	t0, zero, 1f			# is FS positive?
1875	negu	t1
18761:
1877	beq	ta0, zero, 1f			# is FT positive?
1878	negu	ta1
18791:
1880	li	v0, COND_LESS
1881	blt	t1, ta1, test_cond		# is FS < FT?
1882	li	v0, COND_EQUAL
1883	beq	t1, ta1, test_cond		# is FS == FT?
1884	move	v0, zero			# FS > FT
1885	b	test_cond
1886
1887/*
1888 * Compare double.
1889 */
1890cmp_d:
1891	jal	_C_LABEL(get_cmp_d)
1892	bne	t1, DEXP_INF, 1f		# is FS an infinity?
1893	bne	t2, zero, unordered
1894	bne	t3, zero, unordered		# FS is a NAN
18951:
1896	bne	ta1, DEXP_INF, 2f		# is FT an infinity?
1897	bne	ta2, zero, unordered
1898	bne	ta3, zero, unordered		# FT is a NAN
18992:
1900	sll	t1, t1, 20			# reassemble exp & frac
1901	or	t1, t1, t2
1902	sll	ta1, ta1, 20			# reassemble exp & frac
1903	or	ta1, ta1, ta2
1904	beq	t0, zero, 1f			# is FS positive?
1905	not	t3				# negate t1,t3
1906	not	t1
1907	addu	t3, t3, 1
1908	seq	v0, t3, zero			# compute carry
1909	addu	t1, t1, v0
19101:
1911	beq	ta0, zero, 1f			# is FT positive?
1912	not	ta3				# negate ta1,ta3
1913	not	ta1
1914	addu	ta3, ta3, 1
1915	seq	v0, ta3, zero			# compute carry
1916	addu	ta1, ta1, v0
19171:
1918	li	v0, COND_LESS
1919	blt	t1, ta1, test_cond		# is FS(MSW) < FT(MSW)?
1920	move	v0, zero
1921	bne	t1, ta1, test_cond		# is FS(MSW) > FT(MSW)?
1922	li	v0, COND_LESS
1923	bltu	t3, ta3, test_cond		# is FS(LSW) < FT(LSW)?
1924	li	v0, COND_EQUAL
1925	beq	t3, ta3, test_cond		# is FS(LSW) == FT(LSW)?
1926	move	v0, zero			# FS > FT
1927test_cond:
1928	and	v0, v0, a0			# condition match instruction?
1929set_cond:
1930	bne	v0, zero, 1f
1931	and	a2, a2, ~MIPS_FPU_COND_BIT	# clear condition bit
1932	b	2f
19331:
1934	or	a2, a2, MIPS_FPU_COND_BIT	# set condition bit
19352:
1936#ifdef SOFTFLOAT
1937	lw	v0, _C_LABEL(curpcb)		# get pcb of current process
1938	#nop
1939	sw	a2, U_PCB_FPREGS+FRAME_FSR(v0)
1940#else
1941	ctc1	a2, MIPS_FPU_CSR		# save condition bit
1942#endif
1943	b	done
1944
1945unordered:
1946	and	v0, a0, COND_UNORDERED		# this cmp match unordered?
1947	bne	v0, zero, 1f
1948	and	a2, a2, ~MIPS_FPU_COND_BIT	# clear condition bit
1949	b	2f
19501:
1951	or	a2, a2, MIPS_FPU_COND_BIT	# set condition bit
19522:
1953	and	v0, a0, COND_SIGNAL
1954	beq	v0, zero, 1f			# is this a signaling cmp?
1955	or	a2, a2, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
1956	and	v0, a2, MIPS_FPU_ENABLE_INVALID
1957	bne	v0, zero, fpe_trap
19581:
1959#ifdef SOFTFLOAT
1960	lw	v0, _C_LABEL(curpcb)		# get pcb of current process
1961	#nop
1962	sw	a2, U_PCB_FPREGS+FRAME_FSR(v0)
1963#else
1964	ctc1	a2, MIPS_FPU_CSR		# save condition bit
1965#endif
1966	b	done
1967
1968/*
1969 * Determine the amount to shift the fraction in order to restore the
1970 * normalized position. After that, round and handle exceptions.
1971 */
1972norm_s:
1973	move	v0, t2
1974	move	t9, zero			# t9 = num of leading zeros
1975	bne	t2, zero, 1f
1976	move	v0, t8
1977	addu	t9, 32
19781:
1979	srl	v1, v0, 16
1980	bne	v1, zero, 1f
1981	addu	t9, 16
1982	sll	v0, 16
19831:
1984	srl	v1, v0, 24
1985	bne	v1, zero, 1f
1986	addu	t9, 8
1987	sll	v0, 8
19881:
1989	srl	v1, v0, 28
1990	bne	v1, zero, 1f
1991	addu	t9, 4
1992	sll	v0, 4
19931:
1994	srl	v1, v0, 30
1995	bne	v1, zero, 1f
1996	addu	t9, 2
1997	sll	v0, 2
19981:
1999	srl	v1, v0, 31
2000	bne	v1, zero, 1f
2001	addu	t9, 1
2002/*
2003 * Now shift t2,t8 the correct number of bits.
2004 */
20051:
2006	subu	t9, t9, SLEAD_ZEROS		# dont count leading zeros
2007	subu	t1, t1, t9			# adjust the exponent
2008	beq	t9, zero, norm_noshift_s
2009	li	v1, 32
2010	blt	t9, zero, 1f			# if shift < 0, shift right
2011	subu	v1, v1, t9
2012	sll	t2, t2, t9			# shift t2,t8 left
2013	srl	v0, t8, v1			# save bits shifted out
2014	or	t2, t2, v0
2015	sll	t8, t8, t9
2016	b	norm_noshift_s
20171:
2018	negu	t9				# shift t2,t8 right by t9
2019	subu	v1, v1, t9
2020	sll	v0, t8, v1			# save bits shifted out
2021	sltu	v0, zero, v0			# be sure to save any one bits
2022	srl	t8, t8, t9
2023	or	t8, t8, v0
2024	sll	v0, t2, v1			# save bits shifted out
2025	or	t8, t8, v0
2026	srl	t2, t2, t9
2027norm_noshift_s:
2028	move	ta1, t1				# save unrounded exponent
2029	move	ta2, t2				# save unrounded fraction
2030	and	v0, a2, MIPS_FPU_ROUNDING_BITS	# get rounding mode
2031	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
2032	beq	v0, MIPS_FPU_ROUND_RZ, 5f	# round to zero (truncate)
2033	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
2034	beq	t0, zero, 5f			# if sign is positive, truncate
2035	b	2f
20361:
2037	bne	t0, zero, 5f			# if sign is negative, truncate
20382:
2039	beq	t8, zero, 5f			# if exact, continue
2040	addu	t2, t2, 1			# add rounding bit
2041	bne	t2, SIMPL_ONE<<1, 5f		# need to adjust exponent?
2042	addu	t1, t1, 1			# adjust exponent
2043	srl	t2, t2, 1			# renormalize fraction
2044	b	5f
20453:
2046	li	v0, GUARDBIT			# load guard bit for rounding
2047	addu	v0, v0, t8			# add remainder
2048	sltu	v1, v0, t8			# compute carry out
2049	beq	v1, zero, 4f			# if no carry, continue
2050	addu	t2, t2, 1			# add carry to result
2051	bne	t2, SIMPL_ONE<<1, 4f		# need to adjust exponent?
2052	addu	t1, t1, 1			# adjust exponent
2053	srl	t2, t2, 1			# renormalize fraction
20544:
2055	bne	v0, zero, 5f			# if rounded remainder is zero
2056	and	t2, t2, ~1			#  clear LSB (round to nearest)
20575:
2058	bgt	t1, SEXP_MAX, overflow_s	# overflow?
2059	blt	t1, SEXP_MIN, underflow_s	# underflow?
2060	bne	t8, zero, inexact_s		# is result inexact?
2061	addu	t1, t1, SEXP_BIAS		# bias exponent
2062	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
2063	b	result_fs_s
2064
2065/*
2066 * Handle inexact exception.
2067 */
2068inexact_s:
2069	addu	t1, t1, SEXP_BIAS		# bias exponent
2070	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
2071inexact_nobias_s:
2072	jal	_C_LABEL(set_fd_s)		# save result
2073	or	a2, a2, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
2074	and	v0, a2, MIPS_FPU_ENABLE_INEXACT
2075	bne	v0, zero, fpe_trap
2076#ifdef SOFTFLOAT
2077	lw	v0, _C_LABEL(curpcb)		# get pcb of current process
2078	#nop
2079	sw	a2, U_PCB_FPREGS+FRAME_FSR(v0)
2080#else
2081	ctc1	a2, MIPS_FPU_CSR		# save exceptions
2082#endif
2083	b	done
2084
2085/*
2086 * Overflow will trap (if enabled),
2087 * or generate an inexact trap (if enabled),
2088 * or generate an infinity.
2089 */
2090overflow_s:
2091	or	a2, a2, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
2092	and	v0, a2, MIPS_FPU_ENABLE_OVERFLOW
2093	beq	v0, zero, 1f
2094	subu	t1, t1, 192			# bias exponent
2095	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
2096	jal	_C_LABEL(set_fd_s)		# save result
2097	b	fpe_trap
20981:
2099	and	v0, a2, MIPS_FPU_ROUNDING_BITS	# get rounding mode
2100	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
2101	beq	v0, MIPS_FPU_ROUND_RZ, 1f	# round to zero (truncate)
2102	beq	v0, MIPS_FPU_ROUND_RP, 2f	# round to +infinity
2103	bne	t0, zero, 3f
21041:
2105	li	t1, SEXP_MAX			# result is max finite
2106	li	t2, 0x007fffff
2107	b	inexact_s
21082:
2109	bne	t0, zero, 1b
21103:
2111	li	t1, SEXP_MAX + 1		# result is infinity
2112	move	t2, zero
2113	b	inexact_s
2114
2115/*
2116 * In this implementation, "tininess" is detected "after rounding" and
2117 * "loss of accuracy" is detected as "an inexact result".
2118 */
2119underflow_s:
2120	and	v0, a2, MIPS_FPU_ENABLE_UNDERFLOW
2121	beq	v0, zero, 1f
2122/*
2123 * Underflow is enabled so compute the result and trap.
2124 */
2125	addu	t1, t1, 192			# bias exponent
2126	and	t2, t2, ~SIMPL_ONE		# clear implied one bit
2127	jal	_C_LABEL(set_fd_s)		# save result
2128	or	a2, a2, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2129	b	fpe_trap
2130/*
2131 * Underflow is not enabled so compute the result,
2132 * signal inexact result (if it is) and trap (if enabled).
2133 */
21341:
2135	move	t1, ta1				# get unrounded exponent
2136	move	t2, ta2				# get unrounded fraction
2137	li	t9, SEXP_MIN			# compute shift amount
2138	subu	t9, t9, t1			# shift t2,t8 right by t9
2139	blt	t9, SFRAC_BITS+2, 3f		# shift all the bits out?
2140	move	t1, zero			# result is inexact zero
2141	move	t2, zero
2142	or	a2, a2, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2143/*
2144 * Now round the zero result.
2145 * Only need to worry about rounding to +- infinity when the sign matches.
2146 */
2147	and	v0, a2, MIPS_FPU_ROUNDING_BITS	# get rounding mode
2148	beq	v0, MIPS_FPU_ROUND_RN, inexact_nobias_s	# round to nearest
2149	beq	v0, MIPS_FPU_ROUND_RZ, inexact_nobias_s	# round to zero
2150	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
2151	beq	t0, zero, inexact_nobias_s	# if sign is positive, truncate
2152	b	2f
21531:
2154	bne	t0, zero, inexact_nobias_s	# if sign is negative, truncate
21552:
2156	addu	t2, t2, 1			# add rounding bit
2157	b	inexact_nobias_s
21583:
2159	li	v1, 32
2160	subu	v1, v1, t9
2161	sltu	v0, zero, t8			# be sure to save any one bits
2162	sll	t8, t2, v1			# save bits shifted out
2163	or	t8, t8, v0			# include sticky bits
2164	srl	t2, t2, t9
2165/*
2166 * Now round the denormalized result.
2167 */
2168	and	v0, a2, MIPS_FPU_ROUNDING_BITS	# get rounding mode
2169	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
2170	beq	v0, MIPS_FPU_ROUND_RZ, 5f	# round to zero (truncate)
2171	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
2172	beq	t0, zero, 5f			# if sign is positive, truncate
2173	b	2f
21741:
2175	bne	t0, zero, 5f			# if sign is negative, truncate
21762:
2177	beq	t8, zero, 5f			# if exact, continue
2178	addu	t2, t2, 1			# add rounding bit
2179	b	5f
21803:
2181	li	v0, GUARDBIT			# load guard bit for rounding
2182	addu	v0, v0, t8			# add remainder
2183	sltu	v1, v0, t8			# compute carry out
2184	beq	v1, zero, 4f			# if no carry, continue
2185	addu	t2, t2, 1			# add carry to result
21864:
2187	bne	v0, zero, 5f			# if rounded remainder is zero
2188	and	t2, t2, ~1			#  clear LSB (round to nearest)
21895:
2190	move	t1, zero			# denorm or zero exponent
2191	jal	_C_LABEL(set_fd_s)		# save result
2192	beq	t8, zero, done			# check for exact result
2193	or	a2, a2, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2194	or	a2, a2, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
2195	and	v0, a2, MIPS_FPU_ENABLE_INEXACT
2196	bne	v0, zero, fpe_trap
2197#ifdef SOFTFLOAT
2198	lw	v0, _C_LABEL(curpcb)		# get pcb of current process
2199	#nop
2200	sw	a2, U_PCB_FPREGS+FRAME_FSR(v0)
2201#else
2202	ctc1	a2, MIPS_FPU_CSR		# save exceptions
2203#endif
2204	b	done
2205
2206/*
2207 * Determine the amount to shift the fraction in order to restore the
2208 * normalized position. After that, round and handle exceptions.
2209 */
2210norm_d:
2211	move	v0, t2
2212	move	t9, zero			# t9 = num of leading zeros
2213	bne	t2, zero, 1f
2214	move	v0, t3
2215	addu	t9, 32
2216	bne	t3, zero, 1f
2217	move	v0, t8
2218	addu	t9, 32
22191:
2220	srl	v1, v0, 16
2221	bne	v1, zero, 1f
2222	addu	t9, 16
2223	sll	v0, 16
22241:
2225	srl	v1, v0, 24
2226	bne	v1, zero, 1f
2227	addu	t9, 8
2228	sll	v0, 8
22291:
2230	srl	v1, v0, 28
2231	bne	v1, zero, 1f
2232	addu	t9, 4
2233	sll	v0, 4
22341:
2235	srl	v1, v0, 30
2236	bne	v1, zero, 1f
2237	addu	t9, 2
2238	sll	v0, 2
22391:
2240	srl	v1, v0, 31
2241	bne	v1, zero, 1f
2242	addu	t9, 1
2243/*
2244 * Now shift t2,t3,t8 the correct number of bits.
2245 */
22461:
2247	subu	t9, t9, DLEAD_ZEROS		# dont count leading zeros
2248	subu	t1, t1, t9			# adjust the exponent
2249	beq	t9, zero, norm_noshift_d
2250	li	v1, 32
2251	blt	t9, zero, 2f			# if shift < 0, shift right
2252	blt	t9, v1, 1f			# shift by < 32?
2253	subu	t9, t9, v1			# shift by >= 32
2254	subu	v1, v1, t9
2255	sll	t2, t3, t9			# shift left by t9
2256	srl	v0, t8, v1			# save bits shifted out
2257	or	t2, t2, v0
2258	sll	t3, t8, t9
2259	move	t8, zero
2260	b	norm_noshift_d
22611:
2262	subu	v1, v1, t9
2263	sll	t2, t2, t9			# shift left by t9
2264	srl	v0, t3, v1			# save bits shifted out
2265	or	t2, t2, v0
2266	sll	t3, t3, t9
2267	srl	v0, t8, v1			# save bits shifted out
2268	or	t3, t3, v0
2269	sll	t8, t8, t9
2270	b	norm_noshift_d
22712:
2272	negu	t9				# shift right by t9
2273	subu	v1, v1, t9			#  (known to be < 32 bits)
2274	sll	v0, t8, v1			# save bits shifted out
2275	sltu	v0, zero, v0			# be sure to save any one bits
2276	srl	t8, t8, t9
2277	or	t8, t8, v0
2278	sll	v0, t3, v1			# save bits shifted out
2279	or	t8, t8, v0
2280	srl	t3, t3, t9
2281	sll	v0, t2, v1			# save bits shifted out
2282	or	t3, t3, v0
2283	srl	t2, t2, t9
2284norm_noshift_d:
2285	move	ta1, t1				# save unrounded exponent
2286	move	ta2, t2				# save unrounded fraction (MS)
2287	move	ta3, t3				# save unrounded fraction (LS)
2288	and	v0, a2, MIPS_FPU_ROUNDING_BITS	# get rounding mode
2289	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
2290	beq	v0, MIPS_FPU_ROUND_RZ, 5f	# round to zero (truncate)
2291	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
2292	beq	t0, zero, 5f			# if sign is positive, truncate
2293	b	2f
22941:
2295	bne	t0, zero, 5f			# if sign is negative, truncate
22962:
2297	beq	t8, zero, 5f			# if exact, continue
2298	addu	t3, t3, 1			# add rounding bit
2299	bne	t3, zero, 5f			# branch if no carry
2300	addu	t2, t2, 1			# add carry
2301	bne	t2, DIMPL_ONE<<1, 5f		# need to adjust exponent?
2302	addu	t1, t1, 1			# adjust exponent
2303	srl	t2, t2, 1			# renormalize fraction
2304	b	5f
23053:
2306	li	v0, GUARDBIT			# load guard bit for rounding
2307	addu	v0, v0, t8			# add remainder
2308	sltu	v1, v0, t8			# compute carry out
2309	beq	v1, zero, 4f			# branch if no carry
2310	addu	t3, t3, 1			# add carry
2311	bne	t3, zero, 4f			# branch if no carry
2312	addu	t2, t2, 1			# add carry to result
2313	bne	t2, DIMPL_ONE<<1, 4f		# need to adjust exponent?
2314	addu	t1, t1, 1			# adjust exponent
2315	srl	t2, t2, 1			# renormalize fraction
23164:
2317	bne	v0, zero, 5f			# if rounded remainder is zero
2318	and	t3, t3, ~1			#  clear LSB (round to nearest)
23195:
2320	bgt	t1, DEXP_MAX, overflow_d	# overflow?
2321	blt	t1, DEXP_MIN, underflow_d	# underflow?
2322	bne	t8, zero, inexact_d		# is result inexact?
2323	addu	t1, t1, DEXP_BIAS		# bias exponent
2324	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2325	b	result_fs_d
2326
2327/*
2328 * Handle inexact exception.
2329 */
2330inexact_d:
2331	addu	t1, t1, DEXP_BIAS		# bias exponent
2332	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2333inexact_nobias_d:
2334	jal	_C_LABEL(set_fd_d)		# save result
2335	or	a2, a2, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
2336	and	v0, a2, MIPS_FPU_ENABLE_INEXACT
2337	bne	v0, zero, fpe_trap
2338#ifdef SOFTFLOAT
2339	lw	v0, _C_LABEL(curpcb)		# get pcb of current process
2340	#nop
2341	sw	a2, U_PCB_FPREGS+FRAME_FSR(v0)
2342#else
2343	ctc1	a2, MIPS_FPU_CSR		# save exceptions
2344#endif
2345	b	done
2346
2347/*
2348 * Overflow will trap (if enabled),
2349 * or generate an inexact trap (if enabled),
2350 * or generate an infinity.
2351 */
2352overflow_d:
2353	or	a2, a2, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
2354	and	v0, a2, MIPS_FPU_ENABLE_OVERFLOW
2355	beq	v0, zero, 1f
2356	subu	t1, t1, 1536			# bias exponent
2357	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2358	jal	_C_LABEL(set_fd_d)		# save result
2359	b	fpe_trap
23601:
2361	and	v0, a2, MIPS_FPU_ROUNDING_BITS	# get rounding mode
2362	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
2363	beq	v0, MIPS_FPU_ROUND_RZ, 1f	# round to zero (truncate)
2364	beq	v0, MIPS_FPU_ROUND_RP, 2f	# round to +infinity
2365	bne	t0, zero, 3f
23661:
2367	li	t1, DEXP_MAX			# result is max finite
2368	li	t2, 0x000fffff
2369	li	t3, 0xffffffff
2370	b	inexact_d
23712:
2372	bne	t0, zero, 1b
23733:
2374	li	t1, DEXP_MAX + 1		# result is infinity
2375	move	t2, zero
2376	move	t3, zero
2377	b	inexact_d
2378
2379/*
2380 * In this implementation, "tininess" is detected "after rounding" and
2381 * "loss of accuracy" is detected as "an inexact result".
2382 */
2383underflow_d:
2384	and	v0, a2, MIPS_FPU_ENABLE_UNDERFLOW
2385	beq	v0, zero, 1f
2386/*
2387 * Underflow is enabled so compute the result and trap.
2388 */
2389	addu	t1, t1, 1536			# bias exponent
2390	and	t2, t2, ~DIMPL_ONE		# clear implied one bit
2391	jal	_C_LABEL(set_fd_d)		# save result
2392	or	a2, a2, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2393	b	fpe_trap
2394/*
2395 * Underflow is not enabled so compute the result,
2396 * signal inexact result (if it is) and trap (if enabled).
2397 */
23981:
2399	move	t1, ta1				# get unrounded exponent
2400	move	t2, ta2				# get unrounded fraction (MS)
2401	move	t3, ta3				# get unrounded fraction (LS)
2402	li	t9, DEXP_MIN			# compute shift amount
2403	subu	t9, t9, t1			# shift t2,t8 right by t9
2404	blt	t9, DFRAC_BITS+2, 3f		# shift all the bits out?
2405	move	t1, zero			# result is inexact zero
2406	move	t2, zero
2407	move	t3, zero
2408	or	a2, a2, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2409/*
2410 * Now round the zero result.
2411 * Only need to worry about rounding to +- infinity when the sign matches.
2412 */
2413	and	v0, a2, MIPS_FPU_ROUNDING_BITS	# get rounding mode
2414	beq	v0, MIPS_FPU_ROUND_RN, inexact_nobias_d	# round to nearest
2415	beq	v0, MIPS_FPU_ROUND_RZ, inexact_nobias_d	# round to zero
2416	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
2417	beq	t0, zero, inexact_nobias_d	# if sign is positive, truncate
2418	b	2f
24191:
2420	bne	t0, zero, inexact_nobias_d	# if sign is negative, truncate
24212:
2422	addu	t3, t3, 1			# add rounding bit
2423	b	inexact_nobias_d
24243:
2425	li	v1, 32
2426	blt	t9, v1, 1f			# shift by < 32?
2427	subu	t9, t9, v1			# shift right by >= 32
2428	subu	v1, v1, t9
2429	sltu	v0, zero, t8			# be sure to save any one bits
2430	sll	t8, t2, v1			# save bits shifted out
2431	or	t8, t8, v0			# include sticky bits
2432	srl	t3, t2, t9
2433	move	t2, zero
2434	b	2f
24351:
2436	subu	v1, v1, t9			# shift right by t9
2437	sltu	v0, zero, t8			# be sure to save any one bits
2438	sll	t8, t3, v1			# save bits shifted out
2439	or	t8, t8, v0			# include sticky bits
2440	srl	t3, t3, t9
2441	sll	v0, t2, v1			# save bits shifted out
2442	or	t3, t3, v0
2443	srl	t2, t2, t9
2444/*
2445 * Now round the denormalized result.
2446 */
24472:
2448	and	v0, a2, MIPS_FPU_ROUNDING_BITS	# get rounding mode
2449	beq	v0, MIPS_FPU_ROUND_RN, 3f	# round to nearest
2450	beq	v0, MIPS_FPU_ROUND_RZ, 5f	# round to zero (truncate)
2451	beq	v0, MIPS_FPU_ROUND_RP, 1f	# round to +infinity
2452	beq	t0, zero, 5f			# if sign is positive, truncate
2453	b	2f
24541:
2455	bne	t0, zero, 5f			# if sign is negative, truncate
24562:
2457	beq	t8, zero, 5f			# if exact, continue
2458	addu	t3, t3, 1			# add rounding bit
2459	bne	t3, zero, 5f			# if no carry, continue
2460	addu	t2, t2, 1			# add carry
2461	b	5f
24623:
2463	li	v0, GUARDBIT			# load guard bit for rounding
2464	addu	v0, v0, t8			# add remainder
2465	sltu	v1, v0, t8			# compute carry out
2466	beq	v1, zero, 4f			# if no carry, continue
2467	addu	t3, t3, 1			# add rounding bit
2468	bne	t3, zero, 4f			# if no carry, continue
2469	addu	t2, t2, 1			# add carry
24704:
2471	bne	v0, zero, 5f			# if rounded remainder is zero
2472	and	t3, t3, ~1			#  clear LSB (round to nearest)
24735:
2474	move	t1, zero			# denorm or zero exponent
2475	jal	_C_LABEL(set_fd_d)		# save result
2476	beq	t8, zero, done			# check for exact result
2477	or	a2, a2, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2478	or	a2, a2, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
2479	and	v0, a2, MIPS_FPU_ENABLE_INEXACT
2480	bne	v0, zero, fpe_trap
2481#ifdef SOFTFLOAT
2482	lw	v0, _C_LABEL(curpcb)		# get pcb of current process
2483	#nop
2484	sw	a2, U_PCB_FPREGS+FRAME_FSR(v0)
2485#else
2486	ctc1	a2, MIPS_FPU_CSR		# save exceptions
2487#endif
2488	b	done
2489
2490/*
2491 * Signal an invalid operation if the trap is enabled; otherwise,
2492 * the result is a quiet NAN.
2493 */
2494invalid_s:					# trap invalid operation
2495	or	a2, a2, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
2496	and	v0, a2, MIPS_FPU_ENABLE_INVALID
2497	bne	v0, zero, fpe_trap
2498#ifdef SOFTFLOAT
2499	lw	v0, _C_LABEL(curpcb)		# get pcb of current process
2500	#nop
2501	sw	a2, U_PCB_FPREGS+FRAME_FSR(v0)
2502#else
2503	ctc1	a2, MIPS_FPU_CSR		# save exceptions
2504#endif
2505	move	t0, zero			# result is a quiet NAN
2506	li	t1, SEXP_INF
2507	li	t2, SQUIET_NAN
2508	jal	_C_LABEL(set_fd_s)		# save result (in t0,t1,t2)
2509	b	done
2510
2511/*
2512 * Signal an invalid operation if the trap is enabled; otherwise,
2513 * the result is a quiet NAN.
2514 */
2515invalid_d:					# trap invalid operation
2516	or	a2, a2, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
2517	and	v0, a2, MIPS_FPU_ENABLE_INVALID
2518	bne	v0, zero, fpe_trap
2519#ifdef SOFTFLOAT
2520	lw	v0, _C_LABEL(curpcb)		# get pcb of current process
2521	#nop
2522	sw	a2, U_PCB_FPREGS+FRAME_FSR(v0)
2523#else
2524	ctc1	a2, MIPS_FPU_CSR		# save exceptions
2525#endif
2526	move	t0, zero			# result is a quiet NAN
2527	li	t1, DEXP_INF
2528	li	t2, DQUIET_NAN0
2529	li	t3, DQUIET_NAN1
2530	jal	_C_LABEL(set_fd_d)		# save result (in t0,t1,t2,t3)
2531	b	done
2532
2533/*
2534 * Signal an invalid operation if the trap is enabled; otherwise,
2535 * the result is INT_MAX or INT_MIN.
2536 */
2537invalid_w:					# trap invalid operation
2538	or	a2, a2, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
2539	and	v0, a2, MIPS_FPU_ENABLE_INVALID
2540	bne	v0, zero, fpe_trap
2541#ifdef SOFTFLOAT
2542	lw	v0, _C_LABEL(curpcb)		# get pcb of current process
2543	#nop
2544	sw	a2, U_PCB_FPREGS+FRAME_FSR(v0)
2545#else
2546	ctc1	a2, MIPS_FPU_CSR		# save exceptions
2547#endif
2548	bne	t0, zero, 1f
2549	li	t2, INT_MAX			# result is INT_MAX
2550	b	result_fs_w
25511:
2552	li	t2, INT_MIN			# result is INT_MIN
2553	b	result_fs_w
2554
2555/*
2556 * Trap if the hardware should have handled this case.
2557 */
2558fpe_trap:
2559#ifdef SOFTFLOAT
2560	lw	v0, _C_LABEL(curpcb)		# get pcb of current process
2561	#nop
2562	sw	a2, U_PCB_FPREGS+FRAME_FSR(v0)
2563#else
2564	/*
2565	 * ctc1 with fpe bits set causes FPE in kernel mode panic on 5231.
2566	 */
2567	sw	a2, CALLFRAME_SIZ + 12(sp)
2568	lw	a0, _C_LABEL(fpcurproc)
2569	jal	_C_LABEL(savefpregs)		# on RM5231
2570
2571	lw	a2, CALLFRAME_SIZ + 12(sp)
2572
2573	lw	v0, _C_LABEL(curpcb)		# get pcb of current process
2574	#nop
2575	sw	a2, U_PCB_FPREGS+FRAME_FSR(v0)
2576#endif
2577	lw	a1, CALLFRAME_SIZ + 16(sp)	# frame
2578	lw	a2, CALLFRAME_SIZ + 8(sp)	# cause
2579	lw	ra, CALLFRAME_RA(sp)
2580	addu	sp, sp, CALLFRAME_SIZ
2581	j	_C_LABEL(fpemul_sigfpe)
2582
2583/*
2584 * Send an illegal instruction signal to the current process.
2585 */
2586ill:
2587#ifdef SOFTFLOAT
2588	lw	v0, _C_LABEL(curpcb)		# get pcb of current process
2589	#nop
2590	sw	a2, U_PCB_FPREGS+FRAME_FSR(v0)
2591#else
2592	ctc1	a2, MIPS_FPU_CSR		# save exceptions
2593#endif
2594	lw	a1, CALLFRAME_SIZ + 16(sp)	# frame
2595	lw	a2, CALLFRAME_SIZ + 8(sp)	# cause
2596	lw	ra, CALLFRAME_RA(sp)
2597	addu	sp, sp, CALLFRAME_SIZ
2598	j	_C_LABEL(fpemul_sigill)
2599
2600result_ft_s:
2601	move	t0, ta0				# result is FT
2602	move	t1, ta1
2603	move	t2, ta2
2604result_fs_s:					# result is FS
2605	jal	_C_LABEL(set_fd_s)		# save result (in t0,t1,t2)
2606	b	done
2607
2608result_fs_w:
2609	jal	_C_LABEL(set_fd_word)		# save result (in t2)
2610	b	done
2611
2612result_ft_d:
2613	move	t0, ta0				# result is FT
2614	move	t1, ta1
2615	move	t2, ta2
2616	move	t3, ta3
2617result_fs_d:					# result is FS
2618	jal	_C_LABEL(set_fd_d)		# save result (in t0,t1,t2,t3)
2619
2620done:
2621/*
2622 * Succeeded to emulate instruction with no error
2623 * so compute the next PC.
2624 */
2625	lw	t0, CALLFRAME_SIZ + 8(sp)
2626	REG_PROLOGUE
2627	REG_L	v0, FRAME_EPC(a1)
2628	REG_EPILOGUE
2629	bgez	t0, 1f				# Check the branch delay bit.
2630/*
2631 * The instruction is in the branch delay slot so the branch will have to
2632 * be emulated to get the resulting PC.
2633 */
2634	sw	a1, CALLFRAME_SIZ + 4(sp)
2635	move	a0, a1				# 1st arg is p. to trapframe
2636	move	a1, v0				# 2nd arg is instruction PC
2637						# 3rd arg is FP CSR
2638	move	a3, zero			# 4th arg is FALSE
2639	jal	_C_LABEL(MachEmulateBranch)	# compute PC after branch
2640
2641	lw	a1, CALLFRAME_SIZ + 4(sp)
2642	b	2f
2643/*
2644 * This is not in the branch delay slot so calculate the resulting
2645 * PC (epc + 4) into v0.
2646 */
26471:
2648	addiu	v0, v0, 4			# v0 = next pc
26492:
2650	REG_PROLOGUE
2651	REG_S	v0, FRAME_EPC(a1)		# save new pc
2652	REG_EPILOGUE
2653
2654	lw	ra, CALLFRAME_RA(sp)
2655	addu	sp, sp, CALLFRAME_SIZ
2656	j	ra
2657END(MachEmulateFP)
2658
2659/*----------------------------------------------------------------------------
2660 * get_fs_int --
2661 *
2662 *	Read (integer) the FS register (bits 15-11).
2663 *	This is an internal routine used by MachEmulateFP only.
2664 *
2665 * Results:
2666 *	t0	contains the sign
2667 *	t2	contains the fraction
2668 *
2669 *----------------------------------------------------------------------------
2670 */
2671LEAF(get_fs_int)
2672#ifdef SOFTFLOAT
2673	srl	t2, a0, 11-2
2674	lw	t0, _C_LABEL(curpcb)		# get pcb of current process
2675	andi	t2, t2, 0x0078			# Even regs only
2676	addu	t0, t0, t2
2677
2678	lw	t2, U_PCB_FPREGS+FRAME_FP0(t0)
2679
2680	srl	t0, t2, 31		# init the sign bit
2681	bge	t2, zero, 1f
2682	negu	t2
26831:
2684	j	ra
2685#else
2686	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2687	and	a3, a3, 0xF << 2		# mask FS field
2688	lw	a3, get_fs_int_tbl(a3)		# switch on register number
2689	j	a3
2690
2691	.rdata
2692get_fs_int_tbl:
2693	.word	get_fs_int_f0
2694	.word	get_fs_int_f2
2695	.word	get_fs_int_f4
2696	.word	get_fs_int_f6
2697	.word	get_fs_int_f8
2698	.word	get_fs_int_f10
2699	.word	get_fs_int_f12
2700	.word	get_fs_int_f14
2701	.word	get_fs_int_f16
2702	.word	get_fs_int_f18
2703	.word	get_fs_int_f20
2704	.word	get_fs_int_f22
2705	.word	get_fs_int_f24
2706	.word	get_fs_int_f26
2707	.word	get_fs_int_f28
2708	.word	get_fs_int_f30
2709	.text
2710
2711get_fs_int_f0:
2712	mfc1	t2, $f0
2713	b	get_fs_int_done
2714get_fs_int_f2:
2715	mfc1	t2, $f2
2716	b	get_fs_int_done
2717get_fs_int_f4:
2718	mfc1	t2, $f4
2719	b	get_fs_int_done
2720get_fs_int_f6:
2721	mfc1	t2, $f6
2722	b	get_fs_int_done
2723get_fs_int_f8:
2724	mfc1	t2, $f8
2725	b	get_fs_int_done
2726get_fs_int_f10:
2727	mfc1	t2, $f10
2728	b	get_fs_int_done
2729get_fs_int_f12:
2730	mfc1	t2, $f12
2731	b	get_fs_int_done
2732get_fs_int_f14:
2733	mfc1	t2, $f14
2734	b	get_fs_int_done
2735get_fs_int_f16:
2736	mfc1	t2, $f16
2737	b	get_fs_int_done
2738get_fs_int_f18:
2739	mfc1	t2, $f18
2740	b	get_fs_int_done
2741get_fs_int_f20:
2742	mfc1	t2, $f20
2743	b	get_fs_int_done
2744get_fs_int_f22:
2745	mfc1	t2, $f22
2746	b	get_fs_int_done
2747get_fs_int_f24:
2748	mfc1	t2, $f24
2749	b	get_fs_int_done
2750get_fs_int_f26:
2751	mfc1	t2, $f26
2752	b	get_fs_int_done
2753get_fs_int_f28:
2754	mfc1	t2, $f28
2755	b	get_fs_int_done
2756get_fs_int_f30:
2757	mfc1	t2, $f30
2758get_fs_int_done:
2759	srl	t0, t2, 31		# init the sign bit
2760	bge	t2, zero, 1f
2761	negu	t2
27621:
2763	j	ra
2764#endif
2765END(get_fs_int)
2766
2767/*----------------------------------------------------------------------------
2768 * get_ft_fs_s --
2769 *
2770 *	Read (single precision) the FT register (bits 20-16) and
2771 *	the FS register (bits 15-11) and break up into fields.
2772 *	This is an internal routine used by MachEmulateFP only.
2773 *
2774 * Results:
2775 *	t0	contains the FS sign
2776 *	t1	contains the FS (biased) exponent
2777 *	t2	contains the FS fraction
2778 *	ta0	contains the FT sign
2779 *	ta1	contains the FT (biased) exponent
2780 *	ta2	contains the FT fraction
2781 *
2782 *----------------------------------------------------------------------------
2783 */
2784LEAF(get_ft_fs_s)
2785#ifdef SOFTFLOAT
2786	srl	ta0, a0, 16-2
2787	lw	ta1, _C_LABEL(curpcb)		# get pcb of current process
2788	andi	ta0, ta0, 0x0078			# Even regs only
2789	addu	ta1, ta1, ta0
2790
2791	lw	ta0, U_PCB_FPREGS+FRAME_FP0(ta1)
2792
2793	srl	ta1, ta0, 23			# get exponent
2794	and	ta1, ta1, 0xFF
2795	and	ta2, ta0, 0x7FFFFF		# get fraction
2796	srl	ta0, ta0, 31			# get sign
2797	bne	ta1, SEXP_INF, 1f		# is it a signaling NAN?
2798	and	v0, ta2, SSIGNAL_NAN
2799	bne	v0, zero, invalid_s
28001:
2801	/* fall through to get FS */
2802#else
2803	srl	a3, a0, 17 - 2			# get FT field (even regs only)
2804	and	a3, a3, 0xF << 2		# mask FT field
2805	lw	a3, get_ft_s_tbl(a3)		# switch on register number
2806	j	a3
2807
2808	.rdata
2809get_ft_s_tbl:
2810	.word	get_ft_s_f0
2811	.word	get_ft_s_f2
2812	.word	get_ft_s_f4
2813	.word	get_ft_s_f6
2814	.word	get_ft_s_f8
2815	.word	get_ft_s_f10
2816	.word	get_ft_s_f12
2817	.word	get_ft_s_f14
2818	.word	get_ft_s_f16
2819	.word	get_ft_s_f18
2820	.word	get_ft_s_f20
2821	.word	get_ft_s_f22
2822	.word	get_ft_s_f24
2823	.word	get_ft_s_f26
2824	.word	get_ft_s_f28
2825	.word	get_ft_s_f30
2826	.text
2827
2828get_ft_s_f0:
2829	mfc1	ta0, $f0
2830	b	get_ft_s_done
2831get_ft_s_f2:
2832	mfc1	ta0, $f2
2833	b	get_ft_s_done
2834get_ft_s_f4:
2835	mfc1	ta0, $f4
2836	b	get_ft_s_done
2837get_ft_s_f6:
2838	mfc1	ta0, $f6
2839	b	get_ft_s_done
2840get_ft_s_f8:
2841	mfc1	ta0, $f8
2842	b	get_ft_s_done
2843get_ft_s_f10:
2844	mfc1	ta0, $f10
2845	b	get_ft_s_done
2846get_ft_s_f12:
2847	mfc1	ta0, $f12
2848	b	get_ft_s_done
2849get_ft_s_f14:
2850	mfc1	ta0, $f14
2851	b	get_ft_s_done
2852get_ft_s_f16:
2853	mfc1	ta0, $f16
2854	b	get_ft_s_done
2855get_ft_s_f18:
2856	mfc1	ta0, $f18
2857	b	get_ft_s_done
2858get_ft_s_f20:
2859	mfc1	ta0, $f20
2860	b	get_ft_s_done
2861get_ft_s_f22:
2862	mfc1	ta0, $f22
2863	b	get_ft_s_done
2864get_ft_s_f24:
2865	mfc1	ta0, $f24
2866	b	get_ft_s_done
2867get_ft_s_f26:
2868	mfc1	ta0, $f26
2869	b	get_ft_s_done
2870get_ft_s_f28:
2871	mfc1	ta0, $f28
2872	b	get_ft_s_done
2873get_ft_s_f30:
2874	mfc1	ta0, $f30
2875get_ft_s_done:
2876	srl	ta1, ta0, 23			# get exponent
2877	and	ta1, ta1, 0xFF
2878	and	ta2, ta0, 0x7FFFFF		# get fraction
2879	srl	ta0, ta0, 31			# get sign
2880	bne	ta1, SEXP_INF, 1f		# is it a signaling NAN?
2881	and	v0, ta2, SSIGNAL_NAN
2882	bne	v0, zero, invalid_s
28831:
2884	/* fall through to get FS */
2885#endif
2886
2887/*----------------------------------------------------------------------------
2888 * get_fs_s --
2889 *
2890 *	Read (single precision) the FS register (bits 15-11) and
2891 *	break up into fields.
2892 *	This is an internal routine used by MachEmulateFP only.
2893 *
2894 * Results:
2895 *	t0	contains the sign
2896 *	t1	contains the (biased) exponent
2897 *	t2	contains the fraction
2898 *
2899 *----------------------------------------------------------------------------
2900 */
2901XLEAF(get_fs_s)
2902#ifdef SOFTFLOAT
2903	srl	t0, a0, 11-2
2904	lw	t1, _C_LABEL(curpcb)		# get pcb of current process
2905	andi	t0, t0, 0x0078			# Even regs only
2906	addu	t1, t1, t0
2907
2908	lw	t0, U_PCB_FPREGS+FRAME_FP0(t1)
2909
2910	srl	t1, t0, 23			# get exponent
2911	and	t1, t1, 0xFF
2912	and	t2, t0, 0x7FFFFF		# get fraction
2913	srl	t0, t0, 31			# get sign
2914	bne	t1, SEXP_INF, 1f		# is it a signaling NAN?
2915	and	v0, t2, SSIGNAL_NAN
2916	bne	v0, zero, invalid_s
29171:
2918	j	ra
2919#else
2920	srl	a3, a0, 12 - 2			# get FS field (even regs only)
2921	and	a3, a3, 0xF << 2		# mask FS field
2922	lw	a3, get_fs_s_tbl(a3)		# switch on register number
2923	j	a3
2924
2925	.rdata
2926get_fs_s_tbl:
2927	.word	get_fs_s_f0
2928	.word	get_fs_s_f2
2929	.word	get_fs_s_f4
2930	.word	get_fs_s_f6
2931	.word	get_fs_s_f8
2932	.word	get_fs_s_f10
2933	.word	get_fs_s_f12
2934	.word	get_fs_s_f14
2935	.word	get_fs_s_f16
2936	.word	get_fs_s_f18
2937	.word	get_fs_s_f20
2938	.word	get_fs_s_f22
2939	.word	get_fs_s_f24
2940	.word	get_fs_s_f26
2941	.word	get_fs_s_f28
2942	.word	get_fs_s_f30
2943	.text
2944
2945get_fs_s_f0:
2946	mfc1	t0, $f0
2947	b	get_fs_s_done
2948get_fs_s_f2:
2949	mfc1	t0, $f2
2950	b	get_fs_s_done
2951get_fs_s_f4:
2952	mfc1	t0, $f4
2953	b	get_fs_s_done
2954get_fs_s_f6:
2955	mfc1	t0, $f6
2956	b	get_fs_s_done
2957get_fs_s_f8:
2958	mfc1	t0, $f8
2959	b	get_fs_s_done
2960get_fs_s_f10:
2961	mfc1	t0, $f10
2962	b	get_fs_s_done
2963get_fs_s_f12:
2964	mfc1	t0, $f12
2965	b	get_fs_s_done
2966get_fs_s_f14:
2967	mfc1	t0, $f14
2968	b	get_fs_s_done
2969get_fs_s_f16:
2970	mfc1	t0, $f16
2971	b	get_fs_s_done
2972get_fs_s_f18:
2973	mfc1	t0, $f18
2974	b	get_fs_s_done
2975get_fs_s_f20:
2976	mfc1	t0, $f20
2977	b	get_fs_s_done
2978get_fs_s_f22:
2979	mfc1	t0, $f22
2980	b	get_fs_s_done
2981get_fs_s_f24:
2982	mfc1	t0, $f24
2983	b	get_fs_s_done
2984get_fs_s_f26:
2985	mfc1	t0, $f26
2986	b	get_fs_s_done
2987get_fs_s_f28:
2988	mfc1	t0, $f28
2989	b	get_fs_s_done
2990get_fs_s_f30:
2991	mfc1	t0, $f30
2992get_fs_s_done:
2993	srl	t1, t0, 23			# get exponent
2994	and	t1, t1, 0xFF
2995	and	t2, t0, 0x7FFFFF		# get fraction
2996	srl	t0, t0, 31			# get sign
2997	bne	t1, SEXP_INF, 1f		# is it a signaling NAN?
2998	and	v0, t2, SSIGNAL_NAN
2999	bne	v0, zero, invalid_s
30001:
3001	j	ra
3002#endif
3003END(get_ft_fs_s)
3004
3005/*----------------------------------------------------------------------------
3006 * get_ft_fs_d --
3007 *
3008 *	Read (double precision) the FT register (bits 20-16) and
3009 *	the FS register (bits 15-11) and break up into fields.
3010 *	This is an internal routine used by MachEmulateFP only.
3011 *
3012 * Results:
3013 *	t0	contains the FS sign
3014 *	t1	contains the FS (biased) exponent
3015 *	t2	contains the FS fraction
3016 *	t3	contains the FS remaining fraction
3017 *	ta0	contains the FT sign
3018 *	ta1	contains the FT (biased) exponent
3019 *	ta2	contains the FT fraction
3020 *	ta3	contains the FT remaining fraction
3021 *
3022 *----------------------------------------------------------------------------
3023 */
3024LEAF(get_ft_fs_d)
3025#ifdef SOFTFLOAT
3026	srl	ta3, a0, 16-2
3027	lw	ta0, _C_LABEL(curpcb)		# get pcb of current process
3028	andi	ta3, ta3, 0x0078			# Even regs only
3029	addu	ta0, ta0, ta3
3030
3031	lw	ta3, U_PCB_FPREGS+FRAME_FP0(ta0)
3032	lw	ta0, U_PCB_FPREGS+FRAME_FP0+4(ta0)
3033
3034	srl	ta1, ta0, 20			# get exponent
3035	and	ta1, ta1, 0x7FF
3036	and	ta2, ta0, 0xFFFFF			# get fraction
3037	srl	ta0, ta0, 31			# get sign
3038	bne	ta1, DEXP_INF, 1f		# is it a signaling NAN?
3039	and	v0, ta2, DSIGNAL_NAN
3040	bne	v0, zero, invalid_d
30411:
3042	/* fall through to get FS */
3043#else
3044	srl	a3, a0, 17 - 2			# get FT field (even regs only)
3045	and	a3, a3, 0xF << 2		# mask FT field
3046	lw	a3, get_ft_d_tbl(a3)		# switch on register number
3047	j	a3
3048
3049	.rdata
3050get_ft_d_tbl:
3051	.word	get_ft_d_f0
3052	.word	get_ft_d_f2
3053	.word	get_ft_d_f4
3054	.word	get_ft_d_f6
3055	.word	get_ft_d_f8
3056	.word	get_ft_d_f10
3057	.word	get_ft_d_f12
3058	.word	get_ft_d_f14
3059	.word	get_ft_d_f16
3060	.word	get_ft_d_f18
3061	.word	get_ft_d_f20
3062	.word	get_ft_d_f22
3063	.word	get_ft_d_f24
3064	.word	get_ft_d_f26
3065	.word	get_ft_d_f28
3066	.word	get_ft_d_f30
3067	.text
3068
3069get_ft_d_f0:
3070	mfc1	ta3, $f0
3071	mfc1	ta0, $f1
3072	b	get_ft_d_done
3073get_ft_d_f2:
3074	mfc1	ta3, $f2
3075	mfc1	ta0, $f3
3076	b	get_ft_d_done
3077get_ft_d_f4:
3078	mfc1	ta3, $f4
3079	mfc1	ta0, $f5
3080	b	get_ft_d_done
3081get_ft_d_f6:
3082	mfc1	ta3, $f6
3083	mfc1	ta0, $f7
3084	b	get_ft_d_done
3085get_ft_d_f8:
3086	mfc1	ta3, $f8
3087	mfc1	ta0, $f9
3088	b	get_ft_d_done
3089get_ft_d_f10:
3090	mfc1	ta3, $f10
3091	mfc1	ta0, $f11
3092	b	get_ft_d_done
3093get_ft_d_f12:
3094	mfc1	ta3, $f12
3095	mfc1	ta0, $f13
3096	b	get_ft_d_done
3097get_ft_d_f14:
3098	mfc1	ta3, $f14
3099	mfc1	ta0, $f15
3100	b	get_ft_d_done
3101get_ft_d_f16:
3102	mfc1	ta3, $f16
3103	mfc1	ta0, $f17
3104	b	get_ft_d_done
3105get_ft_d_f18:
3106	mfc1	ta3, $f18
3107	mfc1	ta0, $f19
3108	b	get_ft_d_done
3109get_ft_d_f20:
3110	mfc1	ta3, $f20
3111	mfc1	ta0, $f21
3112	b	get_ft_d_done
3113get_ft_d_f22:
3114	mfc1	ta3, $f22
3115	mfc1	ta0, $f23
3116	b	get_ft_d_done
3117get_ft_d_f24:
3118	mfc1	ta3, $f24
3119	mfc1	ta0, $f25
3120	b	get_ft_d_done
3121get_ft_d_f26:
3122	mfc1	ta3, $f26
3123	mfc1	ta0, $f27
3124	b	get_ft_d_done
3125get_ft_d_f28:
3126	mfc1	ta3, $f28
3127	mfc1	ta0, $f29
3128	b	get_ft_d_done
3129get_ft_d_f30:
3130	mfc1	ta3, $f30
3131	mfc1	ta0, $f31
3132get_ft_d_done:
3133	srl	ta1, ta0, 20			# get exponent
3134	and	ta1, ta1, 0x7FF
3135	and	ta2, ta0, 0xFFFFF			# get fraction
3136	srl	ta0, ta0, 31			# get sign
3137	bne	ta1, DEXP_INF, 1f		# is it a signaling NAN?
3138	and	v0, ta2, DSIGNAL_NAN
3139	bne	v0, zero, invalid_d
31401:
3141	/* fall through to get FS */
3142#endif
3143
3144/*----------------------------------------------------------------------------
3145 * get_fs_d --
3146 *
3147 *	Read (double precision) the FS register (bits 15-11) and
3148 *	break up into fields.
3149 *	This is an internal routine used by MachEmulateFP only.
3150 *
3151 * Results:
3152 *	t0	contains the sign
3153 *	t1	contains the (biased) exponent
3154 *	t2	contains the fraction
3155 *	t3	contains the remaining fraction
3156 *
3157 *----------------------------------------------------------------------------
3158 */
3159XLEAF(get_fs_d)
3160#ifdef SOFTFLOAT
3161	srl	t3, a0, 11-2
3162	lw	t0, _C_LABEL(curpcb)		# get pcb of current process
3163	andi	t3, t3, 0x0078			# Even regs only
3164	addu	t0, t0, t3
3165
3166	lw	t3, U_PCB_FPREGS+FRAME_FP0(t0)
3167	lw	t0, U_PCB_FPREGS+FRAME_FP0+4(t0)
3168
3169	srl	t1, t0, 20			# get exponent
3170	and	t1, t1, 0x7FF
3171	and	t2, t0, 0xFFFFF			# get fraction
3172	srl	t0, t0, 31			# get sign
3173	bne	t1, DEXP_INF, 1f		# is it a signaling NAN?
3174	and	v0, t2, DSIGNAL_NAN
3175	bne	v0, zero, invalid_d
31761:
3177	j	ra
3178#else
3179	srl	a3, a0, 12 - 2			# get FS field (even regs only)
3180	and	a3, a3, 0xF << 2		# mask FS field
3181	lw	a3, get_fs_d_tbl(a3)		# switch on register number
3182	j	a3
3183
3184	.rdata
3185get_fs_d_tbl:
3186	.word	get_fs_d_f0
3187	.word	get_fs_d_f2
3188	.word	get_fs_d_f4
3189	.word	get_fs_d_f6
3190	.word	get_fs_d_f8
3191	.word	get_fs_d_f10
3192	.word	get_fs_d_f12
3193	.word	get_fs_d_f14
3194	.word	get_fs_d_f16
3195	.word	get_fs_d_f18
3196	.word	get_fs_d_f20
3197	.word	get_fs_d_f22
3198	.word	get_fs_d_f24
3199	.word	get_fs_d_f26
3200	.word	get_fs_d_f28
3201	.word	get_fs_d_f30
3202	.text
3203
3204get_fs_d_f0:
3205	mfc1	t3, $f0
3206	mfc1	t0, $f1
3207	b	get_fs_d_done
3208get_fs_d_f2:
3209	mfc1	t3, $f2
3210	mfc1	t0, $f3
3211	b	get_fs_d_done
3212get_fs_d_f4:
3213	mfc1	t3, $f4
3214	mfc1	t0, $f5
3215	b	get_fs_d_done
3216get_fs_d_f6:
3217	mfc1	t3, $f6
3218	mfc1	t0, $f7
3219	b	get_fs_d_done
3220get_fs_d_f8:
3221	mfc1	t3, $f8
3222	mfc1	t0, $f9
3223	b	get_fs_d_done
3224get_fs_d_f10:
3225	mfc1	t3, $f10
3226	mfc1	t0, $f11
3227	b	get_fs_d_done
3228get_fs_d_f12:
3229	mfc1	t3, $f12
3230	mfc1	t0, $f13
3231	b	get_fs_d_done
3232get_fs_d_f14:
3233	mfc1	t3, $f14
3234	mfc1	t0, $f15
3235	b	get_fs_d_done
3236get_fs_d_f16:
3237	mfc1	t3, $f16
3238	mfc1	t0, $f17
3239	b	get_fs_d_done
3240get_fs_d_f18:
3241	mfc1	t3, $f18
3242	mfc1	t0, $f19
3243	b	get_fs_d_done
3244get_fs_d_f20:
3245	mfc1	t3, $f20
3246	mfc1	t0, $f21
3247	b	get_fs_d_done
3248get_fs_d_f22:
3249	mfc1	t3, $f22
3250	mfc1	t0, $f23
3251	b	get_fs_d_done
3252get_fs_d_f24:
3253	mfc1	t3, $f24
3254	mfc1	t0, $f25
3255	b	get_fs_d_done
3256get_fs_d_f26:
3257	mfc1	t3, $f26
3258	mfc1	t0, $f27
3259	b	get_fs_d_done
3260get_fs_d_f28:
3261	mfc1	t3, $f28
3262	mfc1	t0, $f29
3263	b	get_fs_d_done
3264get_fs_d_f30:
3265	mfc1	t3, $f30
3266	mfc1	t0, $f31
3267get_fs_d_done:
3268	srl	t1, t0, 20			# get exponent
3269	and	t1, t1, 0x7FF
3270	and	t2, t0, 0xFFFFF			# get fraction
3271	srl	t0, t0, 31			# get sign
3272	bne	t1, DEXP_INF, 1f		# is it a signaling NAN?
3273	and	v0, t2, DSIGNAL_NAN
3274	bne	v0, zero, invalid_d
32751:
3276	j	ra
3277#endif
3278END(get_ft_fs_d)
3279
3280/*----------------------------------------------------------------------------
3281 * get_cmp_s --
3282 *
3283 *	Read (single precision) the FS register (bits 15-11) and
3284 *	the FT register (bits 20-16) and break up into fields.
3285 *	This is an internal routine used by MachEmulateFP only.
3286 *
3287 * Results:
3288 *	t0	contains the sign
3289 *	t1	contains the (biased) exponent
3290 *	t2	contains the fraction
3291 *	ta0	contains the sign
3292 *	ta1	contains the (biased) exponent
3293 *	ta2	contains the fraction
3294 *
3295 *----------------------------------------------------------------------------
3296 */
3297LEAF(get_cmp_s)
3298#ifdef SOFTFLOAT
3299	srl	t1, a0, 11-2
3300	lw	ta2, _C_LABEL(curpcb)		# get pcb of current process
3301	andi	t1, t1, 0x0078			# Even regs only
3302	addu	t0, ta2, t1
3303
3304	lw	t0, U_PCB_FPREGS+FRAME_FP0(t0)
3305
3306	srl	t1, t0, 23			# get exponent
3307	and	t1, t1, 0xFF
3308	and	t2, t0, 0x7FFFFF		# get fraction
3309	srl	t0, t0, 31			# get sign
3310
3311	srl	ta0, a0, 16-2
3312	andi	ta0, ta0, 0x0078			# Even regs only
3313	addu	ta2, ta2, ta0
3314
3315	lw	ta0, U_PCB_FPREGS+FRAME_FP0(ta2)
3316
3317	srl	ta1, ta0, 23			# get exponent
3318	and	ta1, ta1, 0xFF
3319	and	ta2, ta0, 0x7FFFFF		# get fraction
3320	srl	ta0, ta0, 31			# get sign
3321	j	ra
3322#else
3323	srl	a3, a0, 12 - 2			# get FS field (even regs only)
3324	and	a3, a3, 0xF << 2		# mask FS field
3325	lw	a3, cmp_fs_s_tbl(a3)		# switch on register number
3326	j	a3
3327
3328	.rdata
3329cmp_fs_s_tbl:
3330	.word	cmp_fs_s_f0
3331	.word	cmp_fs_s_f2
3332	.word	cmp_fs_s_f4
3333	.word	cmp_fs_s_f6
3334	.word	cmp_fs_s_f8
3335	.word	cmp_fs_s_f10
3336	.word	cmp_fs_s_f12
3337	.word	cmp_fs_s_f14
3338	.word	cmp_fs_s_f16
3339	.word	cmp_fs_s_f18
3340	.word	cmp_fs_s_f20
3341	.word	cmp_fs_s_f22
3342	.word	cmp_fs_s_f24
3343	.word	cmp_fs_s_f26
3344	.word	cmp_fs_s_f28
3345	.word	cmp_fs_s_f30
3346	.text
3347
3348cmp_fs_s_f0:
3349	mfc1	t0, $f0
3350	b	cmp_fs_s_done
3351cmp_fs_s_f2:
3352	mfc1	t0, $f2
3353	b	cmp_fs_s_done
3354cmp_fs_s_f4:
3355	mfc1	t0, $f4
3356	b	cmp_fs_s_done
3357cmp_fs_s_f6:
3358	mfc1	t0, $f6
3359	b	cmp_fs_s_done
3360cmp_fs_s_f8:
3361	mfc1	t0, $f8
3362	b	cmp_fs_s_done
3363cmp_fs_s_f10:
3364	mfc1	t0, $f10
3365	b	cmp_fs_s_done
3366cmp_fs_s_f12:
3367	mfc1	t0, $f12
3368	b	cmp_fs_s_done
3369cmp_fs_s_f14:
3370	mfc1	t0, $f14
3371	b	cmp_fs_s_done
3372cmp_fs_s_f16:
3373	mfc1	t0, $f16
3374	b	cmp_fs_s_done
3375cmp_fs_s_f18:
3376	mfc1	t0, $f18
3377	b	cmp_fs_s_done
3378cmp_fs_s_f20:
3379	mfc1	t0, $f20
3380	b	cmp_fs_s_done
3381cmp_fs_s_f22:
3382	mfc1	t0, $f22
3383	b	cmp_fs_s_done
3384cmp_fs_s_f24:
3385	mfc1	t0, $f24
3386	b	cmp_fs_s_done
3387cmp_fs_s_f26:
3388	mfc1	t0, $f26
3389	b	cmp_fs_s_done
3390cmp_fs_s_f28:
3391	mfc1	t0, $f28
3392	b	cmp_fs_s_done
3393cmp_fs_s_f30:
3394	mfc1	t0, $f30
3395cmp_fs_s_done:
3396	srl	t1, t0, 23			# get exponent
3397	and	t1, t1, 0xFF
3398	and	t2, t0, 0x7FFFFF		# get fraction
3399	srl	t0, t0, 31			# get sign
3400
3401	srl	a3, a0, 17 - 2			# get FT field (even regs only)
3402	and	a3, a3, 0xF << 2		# mask FT field
3403	lw	a3, cmp_ft_s_tbl(a3)		# switch on register number
3404	j	a3
3405
3406	.rdata
3407cmp_ft_s_tbl:
3408	.word	cmp_ft_s_f0
3409	.word	cmp_ft_s_f2
3410	.word	cmp_ft_s_f4
3411	.word	cmp_ft_s_f6
3412	.word	cmp_ft_s_f8
3413	.word	cmp_ft_s_f10
3414	.word	cmp_ft_s_f12
3415	.word	cmp_ft_s_f14
3416	.word	cmp_ft_s_f16
3417	.word	cmp_ft_s_f18
3418	.word	cmp_ft_s_f20
3419	.word	cmp_ft_s_f22
3420	.word	cmp_ft_s_f24
3421	.word	cmp_ft_s_f26
3422	.word	cmp_ft_s_f28
3423	.word	cmp_ft_s_f30
3424	.text
3425
3426cmp_ft_s_f0:
3427	mfc1	ta0, $f0
3428	b	cmp_ft_s_done
3429cmp_ft_s_f2:
3430	mfc1	ta0, $f2
3431	b	cmp_ft_s_done
3432cmp_ft_s_f4:
3433	mfc1	ta0, $f4
3434	b	cmp_ft_s_done
3435cmp_ft_s_f6:
3436	mfc1	ta0, $f6
3437	b	cmp_ft_s_done
3438cmp_ft_s_f8:
3439	mfc1	ta0, $f8
3440	b	cmp_ft_s_done
3441cmp_ft_s_f10:
3442	mfc1	ta0, $f10
3443	b	cmp_ft_s_done
3444cmp_ft_s_f12:
3445	mfc1	ta0, $f12
3446	b	cmp_ft_s_done
3447cmp_ft_s_f14:
3448	mfc1	ta0, $f14
3449	b	cmp_ft_s_done
3450cmp_ft_s_f16:
3451	mfc1	ta0, $f16
3452	b	cmp_ft_s_done
3453cmp_ft_s_f18:
3454	mfc1	ta0, $f18
3455	b	cmp_ft_s_done
3456cmp_ft_s_f20:
3457	mfc1	ta0, $f20
3458	b	cmp_ft_s_done
3459cmp_ft_s_f22:
3460	mfc1	ta0, $f22
3461	b	cmp_ft_s_done
3462cmp_ft_s_f24:
3463	mfc1	ta0, $f24
3464	b	cmp_ft_s_done
3465cmp_ft_s_f26:
3466	mfc1	ta0, $f26
3467	b	cmp_ft_s_done
3468cmp_ft_s_f28:
3469	mfc1	ta0, $f28
3470	b	cmp_ft_s_done
3471cmp_ft_s_f30:
3472	mfc1	ta0, $f30
3473cmp_ft_s_done:
3474	srl	ta1, ta0, 23			# get exponent
3475	and	ta1, ta1, 0xFF
3476	and	ta2, ta0, 0x7FFFFF		# get fraction
3477	srl	ta0, ta0, 31			# get sign
3478	j	ra
3479#endif
3480END(get_cmp_s)
3481
3482/*----------------------------------------------------------------------------
3483 * get_cmp_d --
3484 *
3485 *	Read (double precision) the FS register (bits 15-11) and
3486 *	the FT register (bits 20-16) and break up into fields.
3487 *	This is an internal routine used by MachEmulateFP only.
3488 *
3489 * Results:
3490 *	t0	contains the sign
3491 *	t1	contains the (biased) exponent
3492 *	t2	contains the fraction
3493 *	t3	contains the remaining fraction
3494 *	ta0	contains the sign
3495 *	ta1	contains the (biased) exponent
3496 *	ta2	contains the fraction
3497 *	ta3	contains the remaining fraction
3498 *
3499 *----------------------------------------------------------------------------
3500 */
3501LEAF(get_cmp_d)
3502#ifdef SOFTFLOAT
3503	srl	t1, a0, 11-2
3504	lw	ta2, _C_LABEL(curpcb)		# get pcb of current process
3505	andi	t1, t1, 0x0078			# Even regs only
3506	addu	t0, ta2, t1
3507
3508	lw	t3, U_PCB_FPREGS+FRAME_FP0(t0)
3509	lw	t0, U_PCB_FPREGS+FRAME_FP0+4(t0)
3510
3511	srl	t1, t0, 20			# get exponent
3512	and	t1, t1, 0x7FF
3513	and	t2, t0, 0xFFFFF			# get fraction
3514	srl	t0, t0, 31			# get sign
3515
3516	srl	ta0, a0, 16-2
3517	andi	ta0, ta0, 0x0078			# Even regs only
3518	addu	ta2, ta2, ta0
3519
3520	lw	ta3, U_PCB_FPREGS+FRAME_FP0(ta2)
3521	lw	ta0, U_PCB_FPREGS+FRAME_FP0+4(ta2)
3522
3523	srl	ta1, ta0, 20			# get exponent
3524	and	ta1, ta1, 0x7FF
3525	and	ta2, ta0, 0xFFFFF			# get fraction
3526	srl	ta0, ta0, 31			# get sign
3527	j	ra
3528#else
3529	srl	a3, a0, 12 - 2			# get FS field (even regs only)
3530	and	a3, a3, 0xF << 2		# mask FS field
3531	lw	a3, cmp_fs_d_tbl(a3)		# switch on register number
3532	j	a3
3533
3534	.rdata
3535cmp_fs_d_tbl:
3536	.word	cmp_fs_d_f0
3537	.word	cmp_fs_d_f2
3538	.word	cmp_fs_d_f4
3539	.word	cmp_fs_d_f6
3540	.word	cmp_fs_d_f8
3541	.word	cmp_fs_d_f10
3542	.word	cmp_fs_d_f12
3543	.word	cmp_fs_d_f14
3544	.word	cmp_fs_d_f16
3545	.word	cmp_fs_d_f18
3546	.word	cmp_fs_d_f20
3547	.word	cmp_fs_d_f22
3548	.word	cmp_fs_d_f24
3549	.word	cmp_fs_d_f26
3550	.word	cmp_fs_d_f28
3551	.word	cmp_fs_d_f30
3552	.text
3553
3554cmp_fs_d_f0:
3555	mfc1	t3, $f0
3556	mfc1	t0, $f1
3557	b	cmp_fs_d_done
3558cmp_fs_d_f2:
3559	mfc1	t3, $f2
3560	mfc1	t0, $f3
3561	b	cmp_fs_d_done
3562cmp_fs_d_f4:
3563	mfc1	t3, $f4
3564	mfc1	t0, $f5
3565	b	cmp_fs_d_done
3566cmp_fs_d_f6:
3567	mfc1	t3, $f6
3568	mfc1	t0, $f7
3569	b	cmp_fs_d_done
3570cmp_fs_d_f8:
3571	mfc1	t3, $f8
3572	mfc1	t0, $f9
3573	b	cmp_fs_d_done
3574cmp_fs_d_f10:
3575	mfc1	t3, $f10
3576	mfc1	t0, $f11
3577	b	cmp_fs_d_done
3578cmp_fs_d_f12:
3579	mfc1	t3, $f12
3580	mfc1	t0, $f13
3581	b	cmp_fs_d_done
3582cmp_fs_d_f14:
3583	mfc1	t3, $f14
3584	mfc1	t0, $f15
3585	b	cmp_fs_d_done
3586cmp_fs_d_f16:
3587	mfc1	t3, $f16
3588	mfc1	t0, $f17
3589	b	cmp_fs_d_done
3590cmp_fs_d_f18:
3591	mfc1	t3, $f18
3592	mfc1	t0, $f19
3593	b	cmp_fs_d_done
3594cmp_fs_d_f20:
3595	mfc1	t3, $f20
3596	mfc1	t0, $f21
3597	b	cmp_fs_d_done
3598cmp_fs_d_f22:
3599	mfc1	t3, $f22
3600	mfc1	t0, $f23
3601	b	cmp_fs_d_done
3602cmp_fs_d_f24:
3603	mfc1	t3, $f24
3604	mfc1	t0, $f25
3605	b	cmp_fs_d_done
3606cmp_fs_d_f26:
3607	mfc1	t3, $f26
3608	mfc1	t0, $f27
3609	b	cmp_fs_d_done
3610cmp_fs_d_f28:
3611	mfc1	t3, $f28
3612	mfc1	t0, $f29
3613	b	cmp_fs_d_done
3614cmp_fs_d_f30:
3615	mfc1	t3, $f30
3616	mfc1	t0, $f31
3617cmp_fs_d_done:
3618	srl	t1, t0, 20			# get exponent
3619	and	t1, t1, 0x7FF
3620	and	t2, t0, 0xFFFFF			# get fraction
3621	srl	t0, t0, 31			# get sign
3622
3623	srl	a3, a0, 17 - 2			# get FT field (even regs only)
3624	and	a3, a3, 0xF << 2		# mask FT field
3625	lw	a3, cmp_ft_d_tbl(a3)		# switch on register number
3626	j	a3
3627
3628	.rdata
3629cmp_ft_d_tbl:
3630	.word	cmp_ft_d_f0
3631	.word	cmp_ft_d_f2
3632	.word	cmp_ft_d_f4
3633	.word	cmp_ft_d_f6
3634	.word	cmp_ft_d_f8
3635	.word	cmp_ft_d_f10
3636	.word	cmp_ft_d_f12
3637	.word	cmp_ft_d_f14
3638	.word	cmp_ft_d_f16
3639	.word	cmp_ft_d_f18
3640	.word	cmp_ft_d_f20
3641	.word	cmp_ft_d_f22
3642	.word	cmp_ft_d_f24
3643	.word	cmp_ft_d_f26
3644	.word	cmp_ft_d_f28
3645	.word	cmp_ft_d_f30
3646	.text
3647
3648cmp_ft_d_f0:
3649	mfc1	ta3, $f0
3650	mfc1	ta0, $f1
3651	b	cmp_ft_d_done
3652cmp_ft_d_f2:
3653	mfc1	ta3, $f2
3654	mfc1	ta0, $f3
3655	b	cmp_ft_d_done
3656cmp_ft_d_f4:
3657	mfc1	ta3, $f4
3658	mfc1	ta0, $f5
3659	b	cmp_ft_d_done
3660cmp_ft_d_f6:
3661	mfc1	ta3, $f6
3662	mfc1	ta0, $f7
3663	b	cmp_ft_d_done
3664cmp_ft_d_f8:
3665	mfc1	ta3, $f8
3666	mfc1	ta0, $f9
3667	b	cmp_ft_d_done
3668cmp_ft_d_f10:
3669	mfc1	ta3, $f10
3670	mfc1	ta0, $f11
3671	b	cmp_ft_d_done
3672cmp_ft_d_f12:
3673	mfc1	ta3, $f12
3674	mfc1	ta0, $f13
3675	b	cmp_ft_d_done
3676cmp_ft_d_f14:
3677	mfc1	ta3, $f14
3678	mfc1	ta0, $f15
3679	b	cmp_ft_d_done
3680cmp_ft_d_f16:
3681	mfc1	ta3, $f16
3682	mfc1	ta0, $f17
3683	b	cmp_ft_d_done
3684cmp_ft_d_f18:
3685	mfc1	ta3, $f18
3686	mfc1	ta0, $f19
3687	b	cmp_ft_d_done
3688cmp_ft_d_f20:
3689	mfc1	ta3, $f20
3690	mfc1	ta0, $f21
3691	b	cmp_ft_d_done
3692cmp_ft_d_f22:
3693	mfc1	ta3, $f22
3694	mfc1	ta0, $f23
3695	b	cmp_ft_d_done
3696cmp_ft_d_f24:
3697	mfc1	ta3, $f24
3698	mfc1	ta0, $f25
3699	b	cmp_ft_d_done
3700cmp_ft_d_f26:
3701	mfc1	ta3, $f26
3702	mfc1	ta0, $f27
3703	b	cmp_ft_d_done
3704cmp_ft_d_f28:
3705	mfc1	ta3, $f28
3706	mfc1	ta0, $f29
3707	b	cmp_ft_d_done
3708cmp_ft_d_f30:
3709	mfc1	ta3, $f30
3710	mfc1	ta0, $f31
3711cmp_ft_d_done:
3712	srl	ta1, ta0, 20			# get exponent
3713	and	ta1, ta1, 0x7FF
3714	and	ta2, ta0, 0xFFFFF			# get fraction
3715	srl	ta0, ta0, 31			# get sign
3716	j	ra
3717#endif
3718END(get_cmp_d)
3719
3720/*----------------------------------------------------------------------------
3721 * set_fd_s --
3722 *
3723 *	Write (single precision) the FD register (bits 10-6).
3724 *	This is an internal routine used by MachEmulateFP only.
3725 *
3726 * Arguments:
3727 *	a0	contains the FP instruction
3728 *	t0	contains the sign
3729 *	t1	contains the (biased) exponent
3730 *	t2	contains the fraction
3731 *
3732 * set_fd_word --
3733 *
3734 *	Write (integer) the FD register (bits 10-6).
3735 *	This is an internal routine used by MachEmulateFP only.
3736 *
3737 * Arguments:
3738 *	a0	contains the FP instruction
3739 *	t2	contains the integer
3740 *
3741 *----------------------------------------------------------------------------
3742 */
3743LEAF(set_fd_s)
3744	sll	t0, t0, 31			# position sign
3745	sll	t1, t1, 23			# position exponent
3746	or	t2, t2, t0
3747	or	t2, t2, t1
3748XLEAF(set_fd_word)
3749#ifdef SOFTFLOAT
3750	srl	t1, a0, 6-2
3751	lw	t0, _C_LABEL(curpcb)		# get pcb of current process
3752	andi	t1, t1, 0x0078			# Even regs only
3753	addu	t0, t0, t1
3754
3755	sw	t2, U_PCB_FPREGS+FRAME_FP0(t0)
3756	j	ra
3757#else
3758	srl	a3, a0, 7 - 2			# get FD field (even regs only)
3759	and	a3, a3, 0xF << 2		# mask FT field
3760	lw	a3, set_fd_s_tbl(a3)		# switch on register number
3761	j	a3
3762
3763	.rdata
3764set_fd_s_tbl:
3765	.word	set_fd_s_f0
3766	.word	set_fd_s_f2
3767	.word	set_fd_s_f4
3768	.word	set_fd_s_f6
3769	.word	set_fd_s_f8
3770	.word	set_fd_s_f10
3771	.word	set_fd_s_f12
3772	.word	set_fd_s_f14
3773	.word	set_fd_s_f16
3774	.word	set_fd_s_f18
3775	.word	set_fd_s_f20
3776	.word	set_fd_s_f22
3777	.word	set_fd_s_f24
3778	.word	set_fd_s_f26
3779	.word	set_fd_s_f28
3780	.word	set_fd_s_f30
3781	.text
3782
3783set_fd_s_f0:
3784	mtc1	t2, $f0
3785	j	ra
3786set_fd_s_f2:
3787	mtc1	t2, $f2
3788	j	ra
3789set_fd_s_f4:
3790	mtc1	t2, $f4
3791	j	ra
3792set_fd_s_f6:
3793	mtc1	t2, $f6
3794	j	ra
3795set_fd_s_f8:
3796	mtc1	t2, $f8
3797	j	ra
3798set_fd_s_f10:
3799	mtc1	t2, $f10
3800	j	ra
3801set_fd_s_f12:
3802	mtc1	t2, $f12
3803	j	ra
3804set_fd_s_f14:
3805	mtc1	t2, $f14
3806	j	ra
3807set_fd_s_f16:
3808	mtc1	t2, $f16
3809	j	ra
3810set_fd_s_f18:
3811	mtc1	t2, $f18
3812	j	ra
3813set_fd_s_f20:
3814	mtc1	t2, $f20
3815	j	ra
3816set_fd_s_f22:
3817	mtc1	t2, $f22
3818	j	ra
3819set_fd_s_f24:
3820	mtc1	t2, $f24
3821	j	ra
3822set_fd_s_f26:
3823	mtc1	t2, $f26
3824	j	ra
3825set_fd_s_f28:
3826	mtc1	t2, $f28
3827	j	ra
3828set_fd_s_f30:
3829	mtc1	t2, $f30
3830	j	ra
3831#endif
3832END(set_fd_s)
3833
3834/*----------------------------------------------------------------------------
3835 * set_fd_d --
3836 *
3837 *	Write (double precision) the FT register (bits 10-6).
3838 *	This is an internal routine used by MachEmulateFP only.
3839 *
3840 * Arguments:
3841 *	a0	contains the FP instruction
3842 *	t0	contains the sign
3843 *	t1	contains the (biased) exponent
3844 *	t2	contains the fraction
3845 *	t3	contains the remaining fraction
3846 *
3847 *----------------------------------------------------------------------------
3848 */
3849LEAF(set_fd_d)
3850#ifdef SOFTFLOAT
3851	sll	t0, t0, 31			# set sign
3852	sll	t1, t1, 20			# set exponent
3853	or	t0, t0, t1
3854	or	t0, t0, t2			# set fraction
3855
3856	srl	t1, a0, 6-2
3857	lw	t2, _C_LABEL(curpcb)		# get pcb of current process
3858	andi	t1, t1, 0x0078			# Even regs only
3859	addu	t2, t2, t1
3860
3861	sw	t3, U_PCB_FPREGS+FRAME_FP0(t2)
3862	sw	t0, U_PCB_FPREGS+FRAME_FP0+4(t2)
3863	j	ra
3864#else
3865	sll	t0, t0, 31			# set sign
3866	sll	t1, t1, 20			# set exponent
3867	or	t0, t0, t1
3868	or	t0, t0, t2			# set fraction
3869	srl	a3, a0, 7 - 2			# get FD field (even regs only)
3870	and	a3, a3, 0xF << 2		# mask FD field
3871	lw	a3, set_fd_d_tbl(a3)		# switch on register number
3872	j	a3
3873
3874	.rdata
3875set_fd_d_tbl:
3876	.word	set_fd_d_f0
3877	.word	set_fd_d_f2
3878	.word	set_fd_d_f4
3879	.word	set_fd_d_f6
3880	.word	set_fd_d_f8
3881	.word	set_fd_d_f10
3882	.word	set_fd_d_f12
3883	.word	set_fd_d_f14
3884	.word	set_fd_d_f16
3885	.word	set_fd_d_f18
3886	.word	set_fd_d_f20
3887	.word	set_fd_d_f22
3888	.word	set_fd_d_f24
3889	.word	set_fd_d_f26
3890	.word	set_fd_d_f28
3891	.word	set_fd_d_f30
3892	.text
3893
3894set_fd_d_f0:
3895	mtc1	t3, $f0
3896	mtc1	t0, $f1
3897	j	ra
3898set_fd_d_f2:
3899	mtc1	t3, $f2
3900	mtc1	t0, $f3
3901	j	ra
3902set_fd_d_f4:
3903	mtc1	t3, $f4
3904	mtc1	t0, $f5
3905	j	ra
3906set_fd_d_f6:
3907	mtc1	t3, $f6
3908	mtc1	t0, $f7
3909	j	ra
3910set_fd_d_f8:
3911	mtc1	t3, $f8
3912	mtc1	t0, $f9
3913	j	ra
3914set_fd_d_f10:
3915	mtc1	t3, $f10
3916	mtc1	t0, $f11
3917	j	ra
3918set_fd_d_f12:
3919	mtc1	t3, $f12
3920	mtc1	t0, $f13
3921	j	ra
3922set_fd_d_f14:
3923	mtc1	t3, $f14
3924	mtc1	t0, $f15
3925	j	ra
3926set_fd_d_f16:
3927	mtc1	t3, $f16
3928	mtc1	t0, $f17
3929	j	ra
3930set_fd_d_f18:
3931	mtc1	t3, $f18
3932	mtc1	t0, $f19
3933	j	ra
3934set_fd_d_f20:
3935	mtc1	t3, $f20
3936	mtc1	t0, $f21
3937	j	ra
3938set_fd_d_f22:
3939	mtc1	t3, $f22
3940	mtc1	t0, $f23
3941	j	ra
3942set_fd_d_f24:
3943	mtc1	t3, $f24
3944	mtc1	t0, $f25
3945	j	ra
3946set_fd_d_f26:
3947	mtc1	t3, $f26
3948	mtc1	t0, $f27
3949	j	ra
3950set_fd_d_f28:
3951	mtc1	t3, $f28
3952	mtc1	t0, $f29
3953	j	ra
3954set_fd_d_f30:
3955	mtc1	t3, $f30
3956	mtc1	t0, $f31
3957	j	ra
3958#endif
3959END(set_fd_d)
3960
3961/*----------------------------------------------------------------------------
3962 * renorm_fs_s --
3963 *
3964 * Results:
3965 *	t1	unbiased exponent
3966 *	t2	normalized fraction
3967 *
3968 *----------------------------------------------------------------------------
3969 */
3970LEAF(renorm_fs_s)
3971/*
3972 * Find out how many leading zero bits are in t2 and put in t9.
3973 */
3974	move	v0, t2
3975	move	t9, zero
3976	srl	v1, v0, 16
3977	bne	v1, zero, 1f
3978	addu	t9, 16
3979	sll	v0, 16
39801:
3981	srl	v1, v0, 24
3982	bne	v1, zero, 1f
3983	addu	t9, 8
3984	sll	v0, 8
39851:
3986	srl	v1, v0, 28
3987	bne	v1, zero, 1f
3988	addu	t9, 4
3989	sll	v0, 4
39901:
3991	srl	v1, v0, 30
3992	bne	v1, zero, 1f
3993	addu	t9, 2
3994	sll	v0, 2
39951:
3996	srl	v1, v0, 31
3997	bne	v1, zero, 1f
3998	addu	t9, 1
3999/*
4000 * Now shift t2 the correct number of bits.
4001 */
40021:
4003	subu	t9, t9, SLEAD_ZEROS	# dont count normal leading zeros
4004	li	t1, SEXP_MIN
4005	subu	t1, t1, t9		# adjust exponent
4006	sll	t2, t2, t9
4007	j	ra
4008END(renorm_fs_s)
4009
4010/*----------------------------------------------------------------------------
4011 * renorm_fs_d --
4012 *
4013 * Results:
4014 *	t1	unbiased exponent
4015 *	t2,t3	normalized fraction
4016 *
4017 *----------------------------------------------------------------------------
4018 */
4019LEAF(renorm_fs_d)
4020/*
4021 * Find out how many leading zero bits are in t2,t3 and put in t9.
4022 */
4023	move	v0, t2
4024	move	t9, zero
4025	bne	t2, zero, 1f
4026	move	v0, t3
4027	addu	t9, 32
40281:
4029	srl	v1, v0, 16
4030	bne	v1, zero, 1f
4031	addu	t9, 16
4032	sll	v0, 16
40331:
4034	srl	v1, v0, 24
4035	bne	v1, zero, 1f
4036	addu	t9, 8
4037	sll	v0, 8
40381:
4039	srl	v1, v0, 28
4040	bne	v1, zero, 1f
4041	addu	t9, 4
4042	sll	v0, 4
40431:
4044	srl	v1, v0, 30
4045	bne	v1, zero, 1f
4046	addu	t9, 2
4047	sll	v0, 2
40481:
4049	srl	v1, v0, 31
4050	bne	v1, zero, 1f
4051	addu	t9, 1
4052/*
4053 * Now shift t2,t3 the correct number of bits.
4054 */
40551:
4056	subu	t9, t9, DLEAD_ZEROS	# dont count normal leading zeros
4057	li	t1, DEXP_MIN
4058	subu	t1, t1, t9		# adjust exponent
4059	li	v0, 32
4060	blt	t9, v0, 1f
4061	subu	t9, t9, v0		# shift fraction left >= 32 bits
4062	sll	t2, t3, t9
4063	move	t3, zero
4064	j	ra
40651:
4066	subu	v0, v0, t9		# shift fraction left < 32 bits
4067	sll	t2, t2, t9
4068	srl	v1, t3, v0
4069	or	t2, t2, v1
4070	sll	t3, t3, t9
4071	j	ra
4072END(renorm_fs_d)
4073
4074/*----------------------------------------------------------------------------
4075 * renorm_ft_s --
4076 *
4077 * Results:
4078 *	ta1	unbiased exponent
4079 *	ta2	normalized fraction
4080 *
4081 *----------------------------------------------------------------------------
4082 */
4083LEAF(renorm_ft_s)
4084/*
4085 * Find out how many leading zero bits are in ta2 and put in t9.
4086 */
4087	move	v0, ta2
4088	move	t9, zero
4089	srl	v1, v0, 16
4090	bne	v1, zero, 1f
4091	addu	t9, 16
4092	sll	v0, 16
40931:
4094	srl	v1, v0, 24
4095	bne	v1, zero, 1f
4096	addu	t9, 8
4097	sll	v0, 8
40981:
4099	srl	v1, v0, 28
4100	bne	v1, zero, 1f
4101	addu	t9, 4
4102	sll	v0, 4
41031:
4104	srl	v1, v0, 30
4105	bne	v1, zero, 1f
4106	addu	t9, 2
4107	sll	v0, 2
41081:
4109	srl	v1, v0, 31
4110	bne	v1, zero, 1f
4111	addu	t9, 1
4112/*
4113 * Now shift ta2 the correct number of bits.
4114 */
41151:
4116	subu	t9, t9, SLEAD_ZEROS	# dont count normal leading zeros
4117	li	ta1, SEXP_MIN
4118	subu	ta1, ta1, t9		# adjust exponent
4119	sll	ta2, ta2, t9
4120	j	ra
4121END(renorm_ft_s)
4122
4123/*----------------------------------------------------------------------------
4124 * renorm_ft_d --
4125 *
4126 * Results:
4127 *	ta1	unbiased exponent
4128 *	ta2,ta3	normalized fraction
4129 *
4130 *----------------------------------------------------------------------------
4131 */
4132LEAF(renorm_ft_d)
4133/*
4134 * Find out how many leading zero bits are in ta2,ta3 and put in t9.
4135 */
4136	move	v0, ta2
4137	move	t9, zero
4138	bne	ta2, zero, 1f
4139	move	v0, ta3
4140	addu	t9, 32
41411:
4142	srl	v1, v0, 16
4143	bne	v1, zero, 1f
4144	addu	t9, 16
4145	sll	v0, 16
41461:
4147	srl	v1, v0, 24
4148	bne	v1, zero, 1f
4149	addu	t9, 8
4150	sll	v0, 8
41511:
4152	srl	v1, v0, 28
4153	bne	v1, zero, 1f
4154	addu	t9, 4
4155	sll	v0, 4
41561:
4157	srl	v1, v0, 30
4158	bne	v1, zero, 1f
4159	addu	t9, 2
4160	sll	v0, 2
41611:
4162	srl	v1, v0, 31
4163	bne	v1, zero, 1f
4164	addu	t9, 1
4165/*
4166 * Now shift ta2,ta3 the correct number of bits.
4167 */
41681:
4169	subu	t9, t9, DLEAD_ZEROS	# dont count normal leading zeros
4170	li	ta1, DEXP_MIN
4171	subu	ta1, ta1, t9		# adjust exponent
4172	li	v0, 32
4173	blt	t9, v0, 1f
4174	subu	t9, t9, v0		# shift fraction left >= 32 bits
4175	sll	ta2, ta3, t9
4176	move	ta3, zero
4177	j	ra
41781:
4179	subu	v0, v0, t9		# shift fraction left < 32 bits
4180	sll	ta2, ta2, t9
4181	srl	v1, ta3, v0
4182	or	ta2, ta2, v1
4183	sll	ta3, ta3, t9
4184	j	ra
4185END(renorm_ft_d)
4186
4187#ifdef SOFTFLOAT
4188/*
4189 * Emulate branch delay slot CPU instruction.
4190 * Enter from BC1x emulation.
4191 * These instructions are not implemented and causes SIGILL.
4192 *  jump/branch
4193 *  COP0
4194 *  64bit operation
4195 *  trap/syscall/break
4196 *
4197 * Args are same as MachEmulateFP.
4198 * It should be used to emulate instruction in branch delay slot.
4199 */
4200LEAF(bcemul_delay_slot)
4201	REG_PROLOGUE
4202	REG_S	zero, FRAME_ZERO(a1)		# ensure zero has value 0
4203	REG_EPILOGUE
4204
4205	srl	t0, a0, 26-2
4206	andi	t0, t0, 0x00FC
4207	lw	t0, bcemul_optbl(t0)
4208	j	t0
4209
4210bcemul_special:
4211	sll	t0, a0, 2
4212	andi	t0, t0, 0x00FC
4213	lw	t0, bcemul_specialtbl(t0)
4214	j	t0
4215
4216	.rdata
4217bcemul_optbl:
4218	.word	bcemul_special		# 0
4219	.word	_C_LABEL(bcemul_sigill)	# 1
4220	.word	_C_LABEL(bcemul_sigill)	# 2
4221	.word	_C_LABEL(bcemul_sigill)	# 3
4222	.word	_C_LABEL(bcemul_sigill)	# 4
4223	.word	_C_LABEL(bcemul_sigill)	# 5
4224	.word	_C_LABEL(bcemul_sigill)	# 6
4225	.word	_C_LABEL(bcemul_sigill)	# 7
4226	.word	bcemul_addi		# 8
4227	.word	bcemul_addiu		# 9
4228	.word	bcemul_slti		# 10
4229	.word	bcemul_sltiu		# 11
4230	.word	bcemul_andi		# 12
4231	.word	bcemul_ori		# 13
4232	.word	bcemul_xori		# 14
4233	.word	bcemul_lui		# 15
4234	.word	_C_LABEL(bcemul_sigill)	# 16
4235	.word	_C_LABEL(MachEmulateFP)	# 17
4236	.word	_C_LABEL(bcemul_sigill)	# 18
4237	.word	_C_LABEL(bcemul_sigill)	# 19
4238	.word	_C_LABEL(bcemul_sigill)	# 20
4239	.word	_C_LABEL(bcemul_sigill)	# 21
4240	.word	_C_LABEL(bcemul_sigill)	# 22
4241	.word	_C_LABEL(bcemul_sigill)	# 23
4242	.word	_C_LABEL(bcemul_sigill)	# 24
4243	.word	_C_LABEL(bcemul_sigill)	# 25
4244	.word	_C_LABEL(bcemul_sigill)	# 26
4245	.word	_C_LABEL(bcemul_sigill)	# 27
4246	.word	_C_LABEL(bcemul_sigill)	# 28
4247	.word	_C_LABEL(bcemul_sigill)	# 29
4248	.word	_C_LABEL(bcemul_sigill)	# 30
4249	.word	_C_LABEL(bcemul_sigill)	# 31
4250	.word	_C_LABEL(bcemul_lb)	# 32
4251	.word	_C_LABEL(bcemul_lh)	# 33
4252	.word	_C_LABEL(bcemul_lwl)	# 34
4253	.word	_C_LABEL(bcemul_lw)	# 35
4254	.word	_C_LABEL(bcemul_lbu)	# 36
4255	.word	_C_LABEL(bcemul_lhu)	# 37
4256	.word	_C_LABEL(bcemul_lwr)	# 38
4257	.word	_C_LABEL(bcemul_sigill)	# 39
4258	.word	_C_LABEL(bcemul_sb)	# 40
4259	.word	_C_LABEL(bcemul_sh)	# 41
4260	.word	_C_LABEL(bcemul_swl)	# 42
4261	.word	_C_LABEL(bcemul_sw)	# 43
4262	.word	_C_LABEL(bcemul_sigill)	# 44
4263	.word	_C_LABEL(bcemul_sigill)	# 45
4264	.word	_C_LABEL(bcemul_swr)	# 46
4265	.word	_C_LABEL(bcemul_sigill)	# 47
4266	.word	_C_LABEL(bcemul_sigill)	# 48
4267	.word	_C_LABEL(MachEmulateLWC1) # 49
4268	.word	_C_LABEL(bcemul_sigill)	# 50
4269	.word	_C_LABEL(bcemul_sigill)	# 51
4270	.word	_C_LABEL(bcemul_sigill)	# 52
4271	.word	_C_LABEL(MachEmulateLDC1) # 53
4272	.word	_C_LABEL(bcemul_sigill)	# 54
4273	.word	_C_LABEL(bcemul_sigill)	# 55
4274	.word	_C_LABEL(bcemul_sigill)	# 56
4275	.word	_C_LABEL(MachEmulateSWC1) # 57
4276	.word	_C_LABEL(bcemul_sigill)	# 58
4277	.word	_C_LABEL(bcemul_sigill)	# 59
4278	.word	_C_LABEL(bcemul_sigill)	# 60
4279	.word	_C_LABEL(MachEmulateSDC1) # 61
4280	.word	_C_LABEL(bcemul_sigill)	# 62
4281	.word	_C_LABEL(bcemul_sigill)	# 63
4282
4283bcemul_specialtbl:
4284	.word	bcemul_sll		# 0
4285	.word	_C_LABEL(bcemul_sigill)	# 1
4286	.word	bcemul_srl		# 2
4287	.word	bcemul_sra		# 3
4288	.word	bcemul_sllv		# 4
4289	.word	_C_LABEL(bcemul_sigill)	# 5
4290	.word	bcemul_srlv		# 6
4291	.word	bcemul_srav		# 7
4292	.word	_C_LABEL(bcemul_sigill)	# 8
4293	.word	_C_LABEL(bcemul_sigill)	# 9
4294	.word	_C_LABEL(bcemul_sigill)	# 10
4295	.word	_C_LABEL(bcemul_sigill)	# 11
4296	.word	_C_LABEL(bcemul_sigill)	# 12
4297	.word	_C_LABEL(bcemul_sigill)	# 13
4298	.word	_C_LABEL(bcemul_sigill)	# 14
4299	.word	bcemul_sync		# 15
4300	.word	bcemul_mfhi		# 16
4301	.word	bcemul_mthi		# 17
4302	.word	bcemul_mflo		# 18
4303	.word	bcemul_mtlo		# 19
4304	.word	_C_LABEL(bcemul_sigill)	# 20
4305	.word	_C_LABEL(bcemul_sigill)	# 21
4306	.word	_C_LABEL(bcemul_sigill)	# 22
4307	.word	_C_LABEL(bcemul_sigill)	# 23
4308	.word	bcemul_mult		# 24
4309	.word	bcemul_multu		# 25
4310	.word	bcemul_div		# 26
4311	.word	bcemul_divu		# 27
4312	.word	_C_LABEL(bcemul_sigill)	# 28
4313	.word	_C_LABEL(bcemul_sigill)	# 29
4314	.word	_C_LABEL(bcemul_sigill)	# 30
4315	.word	_C_LABEL(bcemul_sigill)	# 31
4316	.word	bcemul_add		# 32
4317	.word	bcemul_addu		# 33
4318	.word	bcemul_sub		# 34
4319	.word	bcemul_subu		# 35
4320	.word	bcemul_and		# 36
4321	.word	bcemul_or		# 37
4322	.word	bcemul_xor		# 38
4323	.word	bcemul_nor		# 39
4324	.word	_C_LABEL(bcemul_sigill)	# 40
4325	.word	_C_LABEL(bcemul_sigill)	# 41
4326	.word	bcemul_slt		# 42
4327	.word	bcemul_sltu		# 43
4328	.word	_C_LABEL(bcemul_sigill)	# 44
4329	.word	_C_LABEL(bcemul_sigill)	# 45
4330	.word	_C_LABEL(bcemul_sigill)	# 46
4331	.word	_C_LABEL(bcemul_sigill)	# 47
4332	.word	_C_LABEL(bcemul_sigill)	# 48
4333	.word	_C_LABEL(bcemul_sigill)	# 49
4334	.word	_C_LABEL(bcemul_sigill)	# 50
4335	.word	_C_LABEL(bcemul_sigill)	# 51
4336	.word	_C_LABEL(bcemul_sigill)	# 52
4337	.word	_C_LABEL(bcemul_sigill)	# 53
4338	.word	_C_LABEL(bcemul_sigill)	# 54
4339	.word	_C_LABEL(bcemul_sigill)	# 55
4340	.word	_C_LABEL(bcemul_sigill)	# 56
4341	.word	_C_LABEL(bcemul_sigill)	# 57
4342	.word	_C_LABEL(bcemul_sigill)	# 58
4343	.word	_C_LABEL(bcemul_sigill)	# 59
4344	.word	_C_LABEL(bcemul_sigill)	# 60
4345	.word	_C_LABEL(bcemul_sigill)	# 61
4346	.word	_C_LABEL(bcemul_sigill)	# 62
4347	.word	_C_LABEL(bcemul_sigill)	# 63
4348
4349	.text
4350
4351bcemul_addi:
4352	srl	t0, a0, 21-SZREG_SHFT	# rs
4353	srl	t1, a0, 16-SZREG_SHFT	# rt
4354	andi	t0, t0, SZREG_MASK
4355	andi	t1, t1, SZREG_MASK
4356	addu	t0, a1, t0
4357	addu	t1, a1, t1
4358	sll	t2, a0, 16
4359	sra	t2, t2, 16
4360	REG_PROLOGUE
4361	REG_L	v0, FRAME_ZERO(t0)
4362	REG_EPILOGUE
4363	addu	t0, v0, t2
4364
4365	/* Overflow check */
4366	xor	t2, v0, t2
4367	srl	t2, t2, 31
4368	bne	t2, zero, addiok
4369
4370	xor	v0, v0, t0
4371	srl	v0, v0, 31
4372	beq	v0, zero, addiok
4373
4374	j	_C_LABEL(bcemul_sigfpe)
4375
4376addiok:
4377	REG_PROLOGUE
4378	REG_S	t0, FRAME_ZERO(t1)
4379	REG_EPILOGUE
4380	b	bcemul_done
4381
4382bcemul_addiu:
4383	srl	t0, a0, 21-SZREG_SHFT	# rs
4384	srl	t1, a0, 16-SZREG_SHFT	# rt
4385	andi	t0, t0, SZREG_MASK
4386	andi	t1, t1, SZREG_MASK
4387	addu	t0, a1, t0
4388	addu	t1, a1, t1
4389	sll	t2, a0, 16
4390	sra	t2, t2, 16
4391	REG_PROLOGUE
4392	REG_L	v0, FRAME_ZERO(t0)
4393	addu	v0, v0, t2
4394	REG_S	v0, FRAME_ZERO(t1)
4395	REG_EPILOGUE
4396	b	bcemul_done
4397
4398bcemul_slti:
4399	srl	t0, a0, 21-SZREG_SHFT	# rs
4400	srl	t1, a0, 16-SZREG_SHFT	# rt
4401	andi	t0, t0, SZREG_MASK
4402	andi	t1, t1, SZREG_MASK
4403	addu	t0, a1, t0
4404	addu	t1, a1, t1
4405	sll	t2, a0, 16
4406	sra	t2, t2, 16
4407	REG_PROLOGUE
4408	REG_L	v0, FRAME_ZERO(t0)
4409	slt	v0, v0, t2
4410	REG_S	v0, FRAME_ZERO(t1)
4411	REG_EPILOGUE
4412	b	bcemul_done
4413
4414bcemul_sltiu:
4415	srl	t0, a0, 21-SZREG_SHFT	# rs
4416	srl	t1, a0, 16-SZREG_SHFT	# rt
4417	andi	t0, t0, SZREG_MASK
4418	andi	t1, t1, SZREG_MASK
4419	addu	t0, a1, t0
4420	addu	t1, a1, t1
4421	sll	t2, a0, 16
4422	sra	t2, t2, 16
4423	REG_PROLOGUE
4424	REG_L	v0, FRAME_ZERO(t0)
4425	sltu	v0, v0, t2
4426	REG_S	v0, FRAME_ZERO(t1)
4427	REG_EPILOGUE
4428	b	bcemul_done
4429
4430bcemul_andi:
4431	srl	t0, a0, 21-SZREG_SHFT	# rs
4432	srl	t1, a0, 16-SZREG_SHFT	# rt
4433	andi	t0, t0, SZREG_MASK
4434	andi	t1, t1, SZREG_MASK
4435	addu	t0, a1, t0
4436	addu	t1, a1, t1
4437	andi	t2, a0, 0xFFFF
4438	REG_PROLOGUE
4439	REG_L	v0, FRAME_ZERO(t0)
4440	and	v0, v0, t2
4441	REG_S	v0, FRAME_ZERO(t1)
4442	REG_EPILOGUE
4443	b	bcemul_done
4444
4445bcemul_ori:
4446	srl	t0, a0, 21-SZREG_SHFT	# rs
4447	srl	t1, a0, 16-SZREG_SHFT	# rt
4448	andi	t0, t0, SZREG_MASK
4449	andi	t1, t1, SZREG_MASK
4450	addu	t0, a1, t0
4451	addu	t1, a1, t1
4452	andi	t2, a0, 0xFFFF
4453	REG_PROLOGUE
4454	REG_L	v0, FRAME_ZERO(t0)
4455	or	v0, v0, t2
4456	REG_S	v0, FRAME_ZERO(t1)
4457	REG_EPILOGUE
4458	b	bcemul_done
4459
4460bcemul_xori:
4461	srl	t0, a0, 21-SZREG_SHFT	# rs
4462	srl	t1, a0, 16-SZREG_SHFT	# rt
4463	andi	t0, t0, SZREG_MASK
4464	andi	t1, t1, SZREG_MASK
4465	addu	t0, a1, t0
4466	addu	t1, a1, t1
4467	andi	t2, a0, 0xFFFF
4468	REG_PROLOGUE
4469	REG_L	v0, FRAME_ZERO(t0)
4470	xor	v0, v0, t2
4471	REG_S	v0, FRAME_ZERO(t1)
4472	REG_EPILOGUE
4473	b	bcemul_done
4474
4475bcemul_lui:
4476	srl	t0, a0, 16-SZREG_SHFT	# rt
4477	andi	t0, t0, SZREG_MASK
4478	addu	t0, a1, t0
4479	sll	v0, a0, 16
4480	REG_PROLOGUE
4481	REG_S	v0, FRAME_ZERO(t0)
4482	REG_EPILOGUE
4483	b	bcemul_done
4484
4485bcemul_sll:
4486	srl	t0, a0, 16-SZREG_SHFT	# rt
4487	srl	t1, a0, 11-SZREG_SHFT	# rd
4488	srl	t2, a0, 6		# sa
4489	andi	t0, t0, SZREG_MASK
4490	andi	t1, t1, SZREG_MASK
4491	andi	t2, t2, 0x001F
4492	addu	t0, a1, t0
4493	addu	t1, a1, t1
4494	REG_PROLOGUE
4495	REG_L	v0, FRAME_ZERO(t0)
4496	sllv	v0, v0, t2
4497	REG_S	v0, FRAME_ZERO(t1)
4498	REG_EPILOGUE
4499	b	bcemul_done
4500
4501bcemul_srl:
4502	srl	t0, a0, 16-SZREG_SHFT	# rt
4503	srl	t1, a0, 11-SZREG_SHFT	# rd
4504	srl	t2, a0, 6		# sa
4505	andi	t0, t0, SZREG_MASK
4506	andi	t1, t1, SZREG_MASK
4507	andi	t2, t2, 0x001F
4508	addu	t0, a1, t0
4509	addu	t1, a1, t1
4510	REG_PROLOGUE
4511	REG_L	v0, FRAME_ZERO(t0)
4512	srlv	v0, v0, t2
4513	REG_S	v0, FRAME_ZERO(t1)
4514	REG_EPILOGUE
4515	b	bcemul_done
4516
4517bcemul_sra:
4518	srl	t0, a0, 16-SZREG_SHFT	# rt
4519	srl	t1, a0, 11-SZREG_SHFT	# rd
4520	srl	t2, a0, 6		# sa
4521	andi	t0, t0, SZREG_MASK
4522	andi	t1, t1, SZREG_MASK
4523	andi	t2, t2, 0x001F
4524	addu	t0, a1, t0
4525	addu	t1, a1, t1
4526	REG_PROLOGUE
4527	REG_L	v0, FRAME_ZERO(t0)
4528	srav	v0, v0, t2
4529	REG_S	v0, FRAME_ZERO(t1)
4530	REG_EPILOGUE
4531	b	bcemul_done
4532
4533bcemul_sllv:
4534	srl	t0, a0, 21-SZREG_SHFT	# rs
4535	srl	t1, a0, 16-SZREG_SHFT	# rt
4536	srl	t2, a0, 11-SZREG_SHFT	# rd
4537	andi	t0, t0, SZREG_MASK
4538	andi	t1, t1, SZREG_MASK
4539	andi	t2, t2, SZREG_MASK
4540	addu	t0, a1, t0
4541	addu	t1, a1, t1
4542	addu	t2, a1, t2
4543	REG_PROLOGUE
4544	REG_L	v0, FRAME_ZERO(t0)
4545	REG_L	v1, FRAME_ZERO(t1)
4546	sllv	v0, v1, v0
4547	REG_S	v0, FRAME_ZERO(t2)
4548	REG_EPILOGUE
4549	b	bcemul_done
4550
4551bcemul_srlv:
4552	srl	t0, a0, 21-SZREG_SHFT	# rs
4553	srl	t1, a0, 16-SZREG_SHFT	# rt
4554	srl	t2, a0, 11-SZREG_SHFT	# rd
4555	andi	t0, t0, SZREG_MASK
4556	andi	t1, t1, SZREG_MASK
4557	andi	t2, t2, SZREG_MASK
4558	addu	t0, a1, t0
4559	addu	t1, a1, t1
4560	addu	t2, a1, t2
4561	REG_PROLOGUE
4562	REG_L	v0, FRAME_ZERO(t0)
4563	REG_L	v1, FRAME_ZERO(t1)
4564	srlv	v0, v1, v0
4565	REG_S	v0, FRAME_ZERO(t2)
4566	REG_EPILOGUE
4567	b	bcemul_done
4568
4569bcemul_srav:
4570	srl	t0, a0, 21-SZREG_SHFT	# rs
4571	srl	t1, a0, 16-SZREG_SHFT	# rt
4572	srl	t2, a0, 11-SZREG_SHFT	# rd
4573	andi	t0, t0, SZREG_MASK
4574	andi	t1, t1, SZREG_MASK
4575	andi	t2, t2, SZREG_MASK
4576	addu	t0, a1, t0
4577	addu	t1, a1, t1
4578	addu	t2, a1, t2
4579	REG_PROLOGUE
4580	REG_L	v0, FRAME_ZERO(t0)
4581	REG_L	v1, FRAME_ZERO(t1)
4582	srav	v0, v1, v0
4583	REG_S	v0, FRAME_ZERO(t2)
4584	REG_EPILOGUE
4585	b	bcemul_done
4586
4587bcemul_sync:
4588	b	bcemul_done
4589
4590bcemul_mfhi:
4591	srl	t0, a0, 11-SZREG_SHFT	# rd
4592	andi	t0, t0, SZREG_MASK
4593	addu	t0, a1, t0
4594	REG_PROLOGUE
4595	REG_L	v0, FRAME_MULHI(a1)
4596	REG_S	v0, FRAME_ZERO(t0)
4597	REG_EPILOGUE
4598	b	bcemul_done
4599
4600bcemul_mthi:
4601	srl	t0, a0, 21-SZREG_SHFT	# rs
4602	andi	t0, t0, SZREG_MASK
4603	addu	t0, a1, t0
4604	REG_PROLOGUE
4605	REG_L	v0, FRAME_ZERO(t0)
4606	REG_S	v0, FRAME_MULHI(a1)
4607	REG_EPILOGUE
4608	b	bcemul_done
4609
4610bcemul_mflo:
4611	srl	t0, a0, 11-SZREG_SHFT	# rd
4612	andi	t0, t0, SZREG_MASK
4613	addu	t0, a1, t0
4614	REG_PROLOGUE
4615	REG_L	v0, FRAME_MULLO(a1)
4616	REG_S	v0, FRAME_ZERO(t0)
4617	REG_EPILOGUE
4618	b	bcemul_done
4619
4620bcemul_mtlo:
4621	srl	t0, a0, 21-SZREG_SHFT	# rs
4622	andi	t0, t0, SZREG_MASK
4623	addu	t0, a1, t0
4624	REG_PROLOGUE
4625	REG_L	v0, FRAME_ZERO(t0)
4626	REG_S	v0, FRAME_MULLO(a1)
4627	REG_EPILOGUE
4628	b	bcemul_done
4629
4630bcemul_mult:
4631	srl	t0, a0, 21-SZREG_SHFT	# rs
4632	srl	t1, a0, 16-SZREG_SHFT	# rt
4633	andi	t0, t0, SZREG_MASK
4634	andi	t1, t1, SZREG_MASK
4635	addu	t0, a1, t0
4636	addu	t1, a1, t1
4637	REG_PROLOGUE
4638	REG_L	v0, FRAME_ZERO(t0)
4639	REG_L	v1, FRAME_ZERO(t1)
4640	REG_EPILOGUE
4641	mult	v0, v1
4642	mflo	v0
4643	mfhi	v1
4644	REG_PROLOGUE
4645	REG_S	v0, FRAME_MULLO(a1)
4646	REG_S	v1, FRAME_MULHI(a1)
4647	REG_EPILOGUE
4648	b	bcemul_done
4649
4650bcemul_multu:
4651	srl	t0, a0, 21-SZREG_SHFT	# rs
4652	srl	t1, a0, 16-SZREG_SHFT	# rt
4653	andi	t0, t0, SZREG_MASK
4654	andi	t1, t1, SZREG_MASK
4655	addu	t0, a1, t0
4656	addu	t1, a1, t1
4657	REG_PROLOGUE
4658	REG_L	v0, FRAME_ZERO(t0)
4659	REG_L	v1, FRAME_ZERO(t1)
4660	REG_EPILOGUE
4661	multu	v0, v1
4662	mflo	v0
4663	mfhi	v1
4664	REG_PROLOGUE
4665	REG_S	v0, FRAME_MULLO(a1)
4666	REG_S	v1, FRAME_MULHI(a1)
4667	REG_EPILOGUE
4668	b	bcemul_done
4669
4670bcemul_div:
4671	srl	t0, a0, 21-SZREG_SHFT	# rs
4672	srl	t1, a0, 16-SZREG_SHFT	# rt
4673	andi	t0, t0, SZREG_MASK
4674	andi	t1, t1, SZREG_MASK
4675	addu	t0, a1, t0
4676	addu	t1, a1, t1
4677	REG_PROLOGUE
4678	REG_L	v0, FRAME_ZERO(t0)
4679	REG_L	v1, FRAME_ZERO(t1)
4680	REG_EPILOGUE
4681	div	v0, v1
4682	mflo	v0
4683	mfhi	v1
4684	REG_PROLOGUE
4685	REG_S	v0, FRAME_MULLO(a1)
4686	REG_S	v1, FRAME_MULHI(a1)
4687	REG_EPILOGUE
4688	b	bcemul_done
4689
4690bcemul_divu:
4691	srl	t0, a0, 21-SZREG_SHFT	# rs
4692	srl	t1, a0, 16-SZREG_SHFT	# rt
4693	andi	t0, t0, SZREG_MASK
4694	andi	t1, t1, SZREG_MASK
4695	addu	t0, a1, t0
4696	addu	t1, a1, t1
4697	REG_PROLOGUE
4698	REG_L	v0, FRAME_ZERO(t0)
4699	REG_L	v1, FRAME_ZERO(t1)
4700	REG_EPILOGUE
4701	divu	v0, v1
4702	mflo	v0
4703	mfhi	v1
4704	REG_PROLOGUE
4705	REG_S	v0, FRAME_MULLO(a1)
4706	REG_S	v1, FRAME_MULHI(a1)
4707	REG_EPILOGUE
4708	b	bcemul_done
4709
4710bcemul_add:
4711	srl	t0, a0, 21-SZREG_SHFT	# rs
4712	srl	t1, a0, 16-SZREG_SHFT	# rt
4713	srl	t2, a0, 11-SZREG_SHFT	# rd
4714	andi	t0, t0, SZREG_MASK
4715	andi	t1, t1, SZREG_MASK
4716	andi	t2, t2, SZREG_MASK
4717	addu	t0, a1, t0
4718	addu	t1, a1, t1
4719	addu	t2, a1, t2
4720	REG_PROLOGUE
4721	REG_L	v0, FRAME_ZERO(t0)
4722	REG_L	v1, FRAME_ZERO(t1)
4723	REG_EPILOGUE
4724	addu	t0, v0, v1
4725
4726	/* Overflow check */
4727	xor	v1, v0, v1
4728	srl	v1, v1, 31
4729	bne	v1, zero, addok
4730
4731	xor	v0, v0, t0
4732	srl	v0, v0, 31
4733	beq	v0, zero, addok
4734
4735	j	_C_LABEL(bcemul_sigfpe)
4736
4737addok:
4738	REG_PROLOGUE
4739	REG_S	t0, FRAME_ZERO(t2)
4740	REG_EPILOGUE
4741	b	bcemul_done
4742
4743bcemul_addu:
4744	srl	t0, a0, 21-SZREG_SHFT	# rs
4745	srl	t1, a0, 16-SZREG_SHFT	# rt
4746	srl	t2, a0, 11-SZREG_SHFT	# rd
4747	andi	t0, t0, SZREG_MASK
4748	andi	t1, t1, SZREG_MASK
4749	andi	t2, t2, SZREG_MASK
4750	addu	t0, a1, t0
4751	addu	t1, a1, t1
4752	addu	t2, a1, t2
4753	REG_PROLOGUE
4754	REG_L	v0, FRAME_ZERO(t0)
4755	REG_L	v1, FRAME_ZERO(t1)
4756	addu	v0, v0, v1
4757	REG_S	v0, FRAME_ZERO(t2)
4758	REG_EPILOGUE
4759	b	bcemul_done
4760
4761bcemul_sub:
4762	srl	t0, a0, 21-SZREG_SHFT	# rs
4763	srl	t1, a0, 16-SZREG_SHFT	# rt
4764	srl	t2, a0, 11-SZREG_SHFT	# rd
4765	andi	t0, t0, SZREG_MASK
4766	andi	t1, t1, SZREG_MASK
4767	andi	t2, t2, SZREG_MASK
4768	addu	t0, a1, t0
4769	addu	t1, a1, t1
4770	addu	t2, a1, t2
4771	REG_PROLOGUE
4772	REG_L	v0, FRAME_ZERO(t0)
4773	REG_L	v1, FRAME_ZERO(t1)
4774	REG_EPILOGUE
4775	subu	t0, v0, v1
4776
4777	/* Overflow check */
4778	xor	v1, v0, v1
4779	srl	v1, v1, 31
4780	beq	v1, zero, subok
4781
4782	xor	v0, v0, t0
4783	srl	v0, v0, 31
4784	beq	v0, zero, subok
4785
4786	j	_C_LABEL(bcemul_sigfpe)
4787
4788subok:
4789	REG_PROLOGUE
4790	REG_S	t0, FRAME_ZERO(t2)
4791	REG_EPILOGUE
4792	b	bcemul_done
4793
4794bcemul_subu:
4795	srl	t0, a0, 21-SZREG_SHFT	# rs
4796	srl	t1, a0, 16-SZREG_SHFT	# rt
4797	srl	t2, a0, 11-SZREG_SHFT	# rd
4798	andi	t0, t0, SZREG_MASK
4799	andi	t1, t1, SZREG_MASK
4800	andi	t2, t2, SZREG_MASK
4801	addu	t0, a1, t0
4802	addu	t1, a1, t1
4803	addu	t2, a1, t2
4804	REG_PROLOGUE
4805	REG_L	v0, FRAME_ZERO(t0)
4806	REG_L	v1, FRAME_ZERO(t1)
4807	subu	v0, v0, v1
4808	REG_S	v0, FRAME_ZERO(t2)
4809	REG_EPILOGUE
4810	b	bcemul_done
4811
4812bcemul_and:
4813	srl	t0, a0, 21-SZREG_SHFT	# rs
4814	srl	t1, a0, 16-SZREG_SHFT	# rt
4815	srl	t2, a0, 11-SZREG_SHFT	# rd
4816	andi	t0, t0, SZREG_MASK
4817	andi	t1, t1, SZREG_MASK
4818	andi	t2, t2, SZREG_MASK
4819	addu	t0, a1, t0
4820	addu	t1, a1, t1
4821	addu	t2, a1, t2
4822	REG_PROLOGUE
4823	REG_L	v0, FRAME_ZERO(t0)
4824	REG_L	v1, FRAME_ZERO(t1)
4825	and	v0, v0, v1
4826	REG_S	v0, FRAME_ZERO(t2)
4827	REG_EPILOGUE
4828	b	bcemul_done
4829
4830bcemul_or:
4831	srl	t0, a0, 21-SZREG_SHFT	# rs
4832	srl	t1, a0, 16-SZREG_SHFT	# rt
4833	srl	t2, a0, 11-SZREG_SHFT	# rd
4834	andi	t0, t0, SZREG_MASK
4835	andi	t1, t1, SZREG_MASK
4836	andi	t2, t2, SZREG_MASK
4837	addu	t0, a1, t0
4838	addu	t1, a1, t1
4839	addu	t2, a1, t2
4840	REG_PROLOGUE
4841	REG_L	v0, FRAME_ZERO(t0)
4842	REG_L	v1, FRAME_ZERO(t1)
4843	or	v0, v0, v1
4844	REG_S	v0, FRAME_ZERO(t2)
4845	REG_EPILOGUE
4846	b	bcemul_done
4847
4848bcemul_xor:
4849	srl	t0, a0, 21-SZREG_SHFT	# rs
4850	srl	t1, a0, 16-SZREG_SHFT	# rt
4851	srl	t2, a0, 11-SZREG_SHFT	# rd
4852	andi	t0, t0, SZREG_MASK
4853	andi	t1, t1, SZREG_MASK
4854	andi	t2, t2, SZREG_MASK
4855	addu	t0, a1, t0
4856	addu	t1, a1, t1
4857	addu	t2, a1, t2
4858	REG_PROLOGUE
4859	REG_L	v0, FRAME_ZERO(t0)
4860	REG_L	v1, FRAME_ZERO(t1)
4861	xor	v0, v0, v1
4862	REG_S	v0, FRAME_ZERO(t2)
4863	REG_EPILOGUE
4864	b	bcemul_done
4865
4866bcemul_nor:
4867	srl	t0, a0, 21-SZREG_SHFT	# rs
4868	srl	t1, a0, 16-SZREG_SHFT	# rt
4869	srl	t2, a0, 11-SZREG_SHFT	# rd
4870	andi	t0, t0, SZREG_MASK
4871	andi	t1, t1, SZREG_MASK
4872	andi	t2, t2, SZREG_MASK
4873	addu	t0, a1, t0
4874	addu	t1, a1, t1
4875	addu	t2, a1, t2
4876	REG_PROLOGUE
4877	REG_L	v0, FRAME_ZERO(t0)
4878	REG_L	v1, FRAME_ZERO(t1)
4879	nor	v0, v0, v1
4880	REG_S	v0, FRAME_ZERO(t2)
4881	REG_EPILOGUE
4882	b	bcemul_done
4883
4884bcemul_slt:
4885	srl	t0, a0, 21-SZREG_SHFT	# rs
4886	srl	t1, a0, 16-SZREG_SHFT	# rt
4887	srl	t2, a0, 11-SZREG_SHFT	# rd
4888	andi	t0, t0, SZREG_MASK
4889	andi	t1, t1, SZREG_MASK
4890	andi	t2, t2, SZREG_MASK
4891	addu	t0, a1, t0
4892	addu	t1, a1, t1
4893	addu	t2, a1, t2
4894	REG_PROLOGUE
4895	REG_L	v0, FRAME_ZERO(t0)
4896	REG_L	v1, FRAME_ZERO(t1)
4897	slt	v0, v0, v1
4898	REG_S	v0, FRAME_ZERO(t2)
4899	REG_EPILOGUE
4900	b	bcemul_done
4901
4902bcemul_sltu:
4903	srl	t0, a0, 21-SZREG_SHFT	# rs
4904	srl	t1, a0, 16-SZREG_SHFT	# rt
4905	srl	t2, a0, 11-SZREG_SHFT	# rd
4906	andi	t0, t0, SZREG_MASK
4907	andi	t1, t1, SZREG_MASK
4908	andi	t2, t2, SZREG_MASK
4909	addu	t0, a1, t0
4910	addu	t1, a1, t1
4911	addu	t2, a1, t2
4912	REG_PROLOGUE
4913	REG_L	v0, FRAME_ZERO(t0)
4914	REG_L	v1, FRAME_ZERO(t1)
4915	sltu	v0, v0, v1
4916	REG_S	v0, FRAME_ZERO(t2)
4917	REG_EPILOGUE
4918	sw	v0, FRAME_ZERO(t2)
4919#	b	bcemul_done		# fall through to bcemul_done
4920
4921bcemul_done:
4922/*
4923 * Succeeded to emulate instruction with no error
4924 * so compute the next PC.
4925 */
4926	subu	sp, sp, CALLFRAME_SIZ
4927	sw	ra, CALLFRAME_RA(sp)
4928	sw	a1, CALLFRAME_SIZ + 4(sp)
4929
4930	/* Fetch previous branch instruction */
4931	REG_PROLOGUE
4932	REG_L	a0, FRAME_EPC(a1)
4933	REG_EPILOGUE
4934	jal	_C_LABEL(fuiword)
4935
4936	lw	a1, CALLFRAME_SIZ + 4(sp)
4937
4938	/* Calculate branch destination */
4939	sll	t0, v0, 16
4940	sra	t0, t0, 16-2
4941	REG_PROLOGUE
4942	REG_L	t1, FRAME_EPC(a1)
4943	addiu	t0, t0, 4
4944	addu	t1, t1, t0
4945	REG_S	t1, FRAME_EPC(a1)
4946	REG_EPILOGUE
4947
4948	lw	ra, CALLFRAME_RA(sp)
4949	addu	sp, sp, CALLFRAME_SIZ
4950	j	ra
4951
4952END(bcemul_delay_slot)
4953
4954#endif
4955
4956/*
4957 * Send SIGILL, SIGFPE.
4958 * Args are same as MachEmulateFP.
4959 */
4960LEAF(fpemul_sigill)
4961#ifdef SOFTFLOAT
4962XLEAF(bcemul_sigill)
4963#endif
4964	li	t0, 0xFFFFFF00
4965	and	a2, a2, t0
4966	ori	a2, a2, T_RES_INST << MIPS_CR_EXC_CODE_SHIFT
4967	REG_PROLOGUE
4968	REG_S	a2, FRAME_CAUSE(a1)
4969	REG_EPILOGUE
4970
4971	move	a2, a0				# code = instruction
4972	lw	a0, _C_LABEL(curproc)		# get current process
4973	li	a1, SIGILL
4974	j	_C_LABEL(trapsignal)
4975END(fpemul_sigill)
4976
4977LEAF(fpemul_sigfpe)
4978	li	t0, 0xFFFFFF00
4979	and	a2, a2, t0
4980	ori	a2, a2, T_FPE << MIPS_CR_EXC_CODE_SHIFT
4981	REG_PROLOGUE
4982	REG_S	a2, FRAME_CAUSE(a1)
4983	REG_EPILOGUE
4984
4985	move	a2, a0				# code = instruction
4986	lw	a0, _C_LABEL(curproc)		# get current process
4987	li	a1, SIGFPE
4988	j	_C_LABEL(trapsignal)
4989END(fpemul_sigfpe)
4990
4991#ifdef SOFTFLOAT
4992LEAF(bcemul_sigfpe)
4993	li	t0, 0xFFFFFF00
4994	and	a2, a2, t0
4995	ori	a2, a2, T_OVFLOW << MIPS_CR_EXC_CODE_SHIFT
4996	REG_PROLOGUE
4997	REG_S	a2, FRAME_CAUSE(a1)
4998	REG_EPILOGUE
4999
5000	move	a2, a0				# code = instruction
5001	lw	a0, _C_LABEL(curproc)		# get current process
5002	li	a1, SIGFPE
5003	j	_C_LABEL(trapsignal)
5004END(bcemul_sigfpe)
5005#endif
5006