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