OSDN Git Service

FPEMUL fix
[openbsd-octeon/openbsd-octeon.git] / src / sys / arch / mips64 / mips64 / fp.S
1 /*      $OpenBSD: fp.S,v 1.9 2010/02/08 19:26:46 miod Exp $     */
2 /*
3  * Copyright (c) 1992, 1993
4  *      The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Ralph Campbell.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by the University of
20  *      California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *      from: @(#)fp.s  8.1 (Berkeley) 6/10/93
38  *      $Id: fp.S,v 1.9 2010/02/08 19:26:46 miod Exp $
39  */
40
41 /*
42  * Standard header stuff.
43  */
44
45 #include <machine/regdef.h>
46 #include <machine/asm.h>
47 #include <machine/regnum.h>
48 #include <machine/cpu.h>
49
50 #include "assym.h"
51
52 #define SEXP_INF        0xff
53 #define DEXP_INF        0x7ff
54 #define SEXP_BIAS       127
55 #define DEXP_BIAS       1023
56 #define SEXP_MIN        -126
57 #define DEXP_MIN        -1022
58 #define SEXP_MAX        127
59 #define DEXP_MAX        1023
60 #define WEXP_MAX        30              /* maximum unbiased exponent for int */
61 #define WEXP_MIN        -1              /* minimum unbiased exponent for int */
62 #define LEXP_MAX        62              /* maximum unbiased exponent for long */
63 #define LEXP_MIN        -1              /* minimum unbiased exponent for long */
64 #define SFRAC_BITS      23
65 #define DFRAC_BITS      52
66 #define SIMPL_ONE       0x00800000
67 #define DIMPL_ONE       0x0010000000000000
68 #define SLEAD_ZEROS     63 - 55
69 #define DLEAD_ZEROS     63 - 52
70 #define STICKYBIT       1
71 #define GUARDBIT        0x0000000080000000
72 #define DGUARDBIT       0x8000000000000000
73
74 #define SSIGNAL_NAN     0x00400000
75 #define DSIGNAL_NAN     0x00080000
76 #define SQUIET_NAN      0x003fffff
77 #define DQUIET_NAN      0x0007ffffffffffff
78 #define INT_MIN         0x80000000
79 #define INT_MAX         0x7fffffff
80 #define LONG_MIN        0x8000000000000000
81 #define LONG_MAX        0x7fffffffffffffff
82
83 #define COND_UNORDERED  0x1
84 #define COND_EQUAL      0x2
85 #define COND_LESS       0x4
86 #define COND_SIGNAL     0x8
87
88 /*----------------------------------------------------------------------------
89  *
90  * MipsEmulateFP --
91  *
92  *      Emulate unimplemented floating point operations.
93  *      This routine should only be called by MipsFPInterrupt()
94  *      and only if this is a COP1 instruction.
95  *
96  *      MipsEmulateFP(instr)
97  *              unsigned instr;
98  *
99  * Results:
100  *      None.
101  *
102  * Side effects:
103  *      Floating point registers are modified according to instruction.
104  *
105  *----------------------------------------------------------------------------
106  */
107 NON_LEAF(MipsEmulateFP, FRAMESZ(CF_SZ), ra)
108         PTR_SUB sp, sp, FRAMESZ(CF_SZ)
109         PTR_S   ra, CF_RA_OFFS(sp)
110
111         srl     v0, a0, 21                      # get FMT field
112         and     v0, v0, 0x1f                    # mask FMT field
113         dla     a3, func_s
114         beq     v0, 0x10, 1f
115         dla     a3, func_d
116         beq     v0, 0x11, 1f
117         dla     a3, func_w
118         beq     v0, 0x14, 1f
119         dla     a3, func_l
120         beq     v0, 0x15, 1f
121         b       ill                             # illegal format
122
123 1:
124         and     v1, a0, 0x3f                    # mask FUNC field
125         sll     v1, v1, 3                       # align for table lookup
126         daddu   v1, a3
127 #ifdef FPEMUL
128         GET_CPU_INFO(a1, a3)
129         PTR_L   a1, CI_CURPROCPADDR(a1)
130         REG_L   a1, PCB_FPREGS+(32 * REGSZ)(a1)
131         ld      a3, (v1)
132 #else
133         cfc1    a1, FPC_CSR                     # get exception register
134         ld      a3, (v1)                        # switch on FUNC & FMT
135         and     a1, a1, ~FPC_EXCEPTION_UNIMPL   # clear exception
136         ctc1    a1, FPC_CSR
137 #endif
138         j       a3
139
140         .rdata
141 fmt_tbl:
142         .dword mfromc1  # sub 0         mfc1
143         .dword dmfromc1 # sub 1         dmfc1
144         .dword cfromc1  # sub 2         cfc1
145         .dword ill              # sub 3         mfhc1
146         .dword mtoc1            # sub 4         mtc1
147         .dword dmtoc1           # sub 5         dmtc1
148         .dword ctoc1            # sub 6         ctc1
149         .dword ill              # sub 7         mthc1
150         .dword branchc1 # sub 8         bc1
151         .dword branchc1any2     # sub 9         bc1any2
152         .dword branchc1any4     # sub 10        bc1any4
153         .dword ill              # sub 11
154         .dword ill              # sub 12
155         .dword ill              # sub 13
156         .dword ill              # sub 14
157         .dword ill              # sub 15
158         .dword single_op        # sub 16        S
159         .dword double_op        # sub 17        D
160         .dword ill              # sub 18
161         .dword ill              # sub 19
162         .dword single_fixed_op # sub 20 W
163         .dword long_fixed_op    # sub 21        L
164         .dword ill              # sub 22        PS
165         .dword ill              # sub 23
166         .dword ill              # sub 24
167         .dword ill              # sub 25
168         .dword ill              # sub 26
169         .dword ill              # sub 27
170         .dword ill              # sub 28
171         .dword ill              # sub 29
172         .dword ill              # sub 30
173         .dword ill              # sub 31
174
175 func_s:
176         .dword  add_s           # 0
177         .dword  sub_s           # 1
178         .dword  mul_s           # 2
179         .dword  div_s           # 3
180         .dword  ill             # 4 (sqrt)
181         .dword  abs_s           # 5
182         .dword  mov_s           # 6
183         .dword  neg_s           # 7
184         .dword  round_l_s       # 8
185         .dword  trunc_l_s       # 9
186         .dword  ceil_l_s        # 10
187         .dword  floor_l_s       # 11
188         .dword  round_w_s       # 12
189         .dword  trunc_w_s       # 13
190         .dword  ceil_w_s        # 14
191         .dword  floor_w_s       # 15
192         .dword  ill             # 16
193         .dword  ill             # 17
194         .dword  ill             # 18
195         .dword  ill             # 19
196         .dword  ill             # 20
197         .dword  ill             # 21
198         .dword  ill             # 22
199         .dword  ill             # 23
200         .dword  ill             # 24
201         .dword  ill             # 25
202         .dword  ill             # 26
203         .dword  ill             # 27
204         .dword  ill             # 28
205         .dword  ill             # 29
206         .dword  ill             # 30
207         .dword  ill             # 31
208         .dword  ill             # 32
209         .dword  cvt_d_s         # 33
210         .dword  ill             # 34
211         .dword  ill             # 35
212         .dword  cvt_w_s         # 36
213         .dword  cvt_l_s         # 37
214         .dword  ill             # 38
215         .dword  ill             # 39
216         .dword  ill             # 40
217         .dword  ill             # 41
218         .dword  ill             # 42
219         .dword  ill             # 43
220         .dword  ill             # 44
221         .dword  ill             # 45
222         .dword  ill             # 46
223         .dword  ill             # 47
224         .dword  cmp_s           # 48
225         .dword  cmp_s           # 49
226         .dword  cmp_s           # 50
227         .dword  cmp_s           # 51
228         .dword  cmp_s           # 52
229         .dword  cmp_s           # 53
230         .dword  cmp_s           # 54
231         .dword  cmp_s           # 55
232         .dword  cmp_s           # 56
233         .dword  cmp_s           # 57
234         .dword  cmp_s           # 58
235         .dword  cmp_s           # 59
236         .dword  cmp_s           # 60
237         .dword  cmp_s           # 61
238         .dword  cmp_s           # 62
239         .dword  cmp_s           # 63
240
241 func_d:
242         .dword  add_d           # 0
243         .dword  sub_d           # 1
244         .dword  mul_d           # 2
245         .dword  div_d           # 3
246         .dword  ill             # 4 (sqrt)
247         .dword  abs_d           # 5
248         .dword  mov_d           # 6
249         .dword  neg_d           # 7
250         .dword  round_l_d       # 8
251         .dword  trunc_l_d       # 9
252         .dword  ceil_l_d        # 10
253         .dword  floor_l_d       # 11
254         .dword  round_w_d       # 12
255         .dword  trunc_w_d       # 13
256         .dword  ceil_w_d        # 14
257         .dword  floor_w_d       # 15
258         .dword  ill             # 16
259         .dword  ill             # 17
260         .dword  ill             # 18
261         .dword  ill             # 19
262         .dword  ill             # 20
263         .dword  ill             # 21
264         .dword  ill             # 22
265         .dword  ill             # 23
266         .dword  ill             # 24
267         .dword  ill             # 25
268         .dword  ill             # 26
269         .dword  ill             # 27
270         .dword  ill             # 28
271         .dword  ill             # 29
272         .dword  ill             # 30
273         .dword  ill             # 31
274         .dword  cvt_s_d         # 32
275         .dword  ill             # 33
276         .dword  ill             # 34
277         .dword  ill             # 35
278         .dword  cvt_w_d         # 36
279         .dword  cvt_l_d         # 37
280         .dword  ill             # 38
281         .dword  ill             # 39
282         .dword  ill             # 40
283         .dword  ill             # 41
284         .dword  ill             # 42
285         .dword  ill             # 43
286         .dword  ill             # 44
287         .dword  ill             # 45
288         .dword  ill             # 46
289         .dword  ill             # 47
290         .dword  cmp_d           # 48
291         .dword  cmp_d           # 49
292         .dword  cmp_d           # 50
293         .dword  cmp_d           # 51
294         .dword  cmp_d           # 52
295         .dword  cmp_d           # 53
296         .dword  cmp_d           # 54
297         .dword  cmp_d           # 55
298         .dword  cmp_d           # 56
299         .dword  cmp_d           # 57
300         .dword  cmp_d           # 58
301         .dword  cmp_d           # 59
302         .dword  cmp_d           # 60
303         .dword  cmp_d           # 61
304         .dword  cmp_d           # 62
305         .dword  cmp_d           # 63
306
307 func_w:
308         .dword  ill             # 0
309         .dword  ill             # 1
310         .dword  ill             # 2
311         .dword  ill             # 3
312         .dword  ill             # 4
313         .dword  ill             # 5
314         .dword  ill             # 6
315         .dword  ill             # 7
316         .dword  ill             # 8
317         .dword  ill             # 9
318         .dword  ill             # 10
319         .dword  ill             # 11
320         .dword  ill             # 12
321         .dword  ill             # 13
322         .dword  ill             # 14
323         .dword  ill             # 15
324         .dword  ill             # 16
325         .dword  ill             # 17
326         .dword  ill             # 18
327         .dword  ill             # 19
328         .dword  ill             # 20
329         .dword  ill             # 21
330         .dword  ill             # 22
331         .dword  ill             # 23
332         .dword  ill             # 24
333         .dword  ill             # 25
334         .dword  ill             # 26
335         .dword  ill             # 27
336         .dword  ill             # 28
337         .dword  ill             # 29
338         .dword  ill             # 30
339         .dword  ill             # 31
340         .dword  cvt_s_w         # 32
341         .dword  cvt_d_w         # 33
342         .dword  ill             # 34
343         .dword  ill             # 35
344         .dword  ill             # 36
345         .dword  ill             # 37
346         .dword  ill             # 38
347         .dword  ill             # 39
348         .dword  ill             # 40
349         .dword  ill             # 41
350         .dword  ill             # 42
351         .dword  ill             # 43
352         .dword  ill             # 44
353         .dword  ill             # 45
354         .dword  ill             # 46
355         .dword  ill             # 47
356         .dword  ill             # 48
357         .dword  ill             # 49
358         .dword  ill             # 50
359         .dword  ill             # 51
360         .dword  ill             # 52
361         .dword  ill             # 53
362         .dword  ill             # 54
363         .dword  ill             # 55
364         .dword  ill             # 56
365         .dword  ill             # 57
366         .dword  ill             # 58
367         .dword  ill             # 59
368         .dword  ill             # 60
369         .dword  ill             # 61
370         .dword  ill             # 62
371         .dword  ill             # 63
372
373 func_l:
374         .dword  ill             # 0
375         .dword  ill             # 1
376         .dword  ill             # 2
377         .dword  ill             # 3
378         .dword  ill             # 4
379         .dword  ill             # 5
380         .dword  ill             # 6
381         .dword  ill             # 7
382         .dword  ill             # 8
383         .dword  ill             # 9
384         .dword  ill             # 10
385         .dword  ill             # 11
386         .dword  ill             # 12
387         .dword  ill             # 13
388         .dword  ill             # 14
389         .dword  ill             # 15
390         .dword  ill             # 16
391         .dword  ill             # 17
392         .dword  ill             # 18
393         .dword  ill             # 19
394         .dword  ill             # 20
395         .dword  ill             # 21
396         .dword  ill             # 22
397         .dword  ill             # 23
398         .dword  ill             # 24
399         .dword  ill             # 25
400         .dword  ill             # 26
401         .dword  ill             # 27
402         .dword  ill             # 28
403         .dword  ill             # 29
404         .dword  ill             # 30
405         .dword  ill             # 31
406         .dword  cvt_s_l         # 32
407         .dword  cvt_d_l         # 33
408         .dword  ill             # 34
409         .dword  ill             # 35
410         .dword  ill             # 36
411         .dword  ill             # 37
412         .dword  ill             # 38
413         .dword  ill             # 39
414         .dword  ill             # 40
415         .dword  ill             # 41
416         .dword  ill             # 42
417         .dword  ill             # 43
418         .dword  ill             # 44
419         .dword  ill             # 45
420         .dword  ill             # 46
421         .dword  ill             # 47
422         .dword  ill             # 48
423         .dword  ill             # 49
424         .dword  ill             # 50
425         .dword  ill             # 51
426         .dword  ill             # 52
427         .dword  ill             # 53
428         .dword  ill             # 54
429         .dword  ill             # 55
430         .dword  ill             # 56
431         .dword  ill             # 57
432         .dword  ill             # 58
433         .dword  ill             # 59
434         .dword  ill             # 60
435         .dword  ill             # 61
436         .dword  ill             # 62
437         .dword  ill             # 63
438
439         .text
440
441 /*
442  * Single precision subtract.
443  */
444 sub_s:
445         jal     get_ft_fs_s
446         xor     ta0, 1                          # negate FT sign bit
447         b       add_sub_s
448 /*
449  * Single precision add.
450  */
451 add_s:
452         jal     get_ft_fs_s
453 add_sub_s:
454         bne     t1, SEXP_INF, 1f                # is FS an infinity?
455         bne     ta1, SEXP_INF, result_fs_s      # if FT is not inf, result=FS
456         bne     t2, zero, result_fs_s           # if FS is NAN, result is FS
457         bne     ta2, zero, result_ft_s          # if FT is NAN, result is FT
458         bne     t0, ta0, invalid_s              # both infinities same sign?
459         b       result_fs_s                     # result is in FS
460 1:
461         beq     ta1, SEXP_INF, result_ft_s      # if FT is inf, result=FT
462         bne     t1, zero, 4f                    # is FS a denormalized num?
463         beq     t2, zero, 3f                    # is FS zero?
464         bne     ta1, zero, 2f                   # is FT a denormalized num?
465         beq     ta2, zero, result_fs_s          # FT is zero, result=FS
466         jal     renorm_fs_s
467         jal     renorm_ft_s
468         b       5f
469 2:
470         jal     renorm_fs_s
471         subu    ta1, ta1, SEXP_BIAS             # unbias FT exponent
472         or      ta2, ta2, SIMPL_ONE             # set implied one bit
473         b       5f
474 3:
475         bne     ta1, zero, result_ft_s          # if FT != 0, result=FT
476         bne     ta2, zero, result_ft_s
477         and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
478         bne     v0, FPC_ROUND_RM, 1f    # round to -infinity?
479         or      t0, t0, ta0                     # compute result sign
480         b       result_fs_s
481 1:
482         and     t0, ta0                         # compute result sign
483         b       result_fs_s
484 4:
485         bne     ta1, zero, 2f                   # is FT a denormalized num?
486         beq     ta2, zero, result_fs_s          # FT is zero, result=FS
487         subu    t1, SEXP_BIAS                   # unbias FS exponent
488         or      t2, SIMPL_ONE                   # set implied one bit
489         jal     renorm_ft_s
490         b       5f
491 2:
492         subu    t1, SEXP_BIAS                   # unbias FS exponent
493         or      t2, SIMPL_ONE                   # set implied one bit
494         subu    ta1, SEXP_BIAS                  # unbias FT exponent
495         or      ta2, SIMPL_ONE                  # set implied one bit
496 /*
497  * Perform the addition.
498  */
499 5:
500         move    t8, zero                        # no shifted bits (sticky reg)
501         beq     t1, ta1, 4f                     # exp equal, no shift needed
502         subu    v0, t1, ta1                     # v0 = difference of exponents
503         move    v1, v0                          # v1 = abs(difference)
504         bge     v0, zero, 1f
505         negu    v1
506 1:
507         ble     v1, SFRAC_BITS+2, 2f            # is difference too great?
508         li      t8, STICKYBIT                   # set the sticky bit
509         bge     v0, zero, 1f                    # check which exp is larger
510         move    t1, ta1                         # result exp is FTs
511         move    t2, zero                        # FSs fraction shifted is zero
512         b       4f
513 1:
514         move    ta2, zero                       # FTs fraction shifted is zero
515         b       4f
516 2:
517         li      t9, 32                          # compute 32 - abs(exp diff)
518         subu    t9, t9, v1
519         bgt     v0, zero, 3f                    # if FS > FT, shift FTs frac
520         move    t1, ta1                         # FT > FS, result exp is FTs
521         sll     t8, t2, t9                      # save bits shifted out
522         srl     t2, t2, v1                      # shift FSs fraction
523         b       4f
524 3:
525         sll     t8, ta2, t9                     # save bits shifted out
526         srl     ta2, ta2, v1                    # shift FTs fraction
527 4:
528         bne     t0, ta0, 1f                     # if signs differ, subtract
529         addu    t2, t2, ta2                     # add fractions
530         b       norm_s
531 1:
532         blt     t2, ta2, 3f                     # subtract larger from smaller
533         bne     t2, ta2, 2f                     # if same, result=0
534         move    t1, zero                        # result=0
535         move    t2, zero
536         and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
537         bne     v0, FPC_ROUND_RM, 1f    # round to -infinity?
538         or      t0, t0, ta0                     # compute result sign
539         b       result_fs_s
540 1:
541         and     t0, t0, ta0                     # compute result sign
542         b       result_fs_s
543 2:
544         sltu    t9, zero, t8                    # compute t2:zero - ta2:t8
545         subu    t8, zero, t8
546         subu    t2, t2, ta2                     # subtract fractions
547         subu    t2, t2, t9                      # subtract barrow
548         b       norm_s
549 3:
550         move    t0, ta0                         # sign of result = FTs
551         sltu    t9, zero, t8                    # compute ta2:zero - t2:t8
552         subu    t8, zero, t8
553         subu    t2, ta2, t2                     # subtract fractions
554         subu    t2, t2, t9                      # subtract barrow
555         b       norm_s
556
557 /*
558  * Double precision subtract.
559  */
560 sub_d:
561         jal     get_ft_fs_d
562         xor     ta0, ta0, 1                     # negate sign bit
563         b       add_sub_d
564 /*
565  * Double precision add.
566  */
567 add_d:
568         jal     get_ft_fs_d
569 add_sub_d:
570         bne     t1, DEXP_INF, 1f                # is FS an infinity?
571         bne     ta1, DEXP_INF, result_fs_d      # if FT is not inf, result=FS
572         bne     t2, zero, result_fs_d           # if FS is NAN, result is FS
573         bne     ta2, zero, result_ft_d          # if FT is NAN, result is FT
574         bne     t0, ta0, invalid_d              # both infinities same sign?
575         b       result_fs_d                     # result is in FS
576 1:
577         beq     ta1, DEXP_INF, result_ft_d      # if FT is inf, result=FT
578         bne     t1, zero, 4f                    # is FS a denormalized num?
579         beq     t2, zero, 3f                    # is FS zero?
580         bne     ta1, zero, 2f                   # is FT a denormalized num?
581         beq     ta2, zero, result_fs_d          # FT is zero, result=FS
582         jal     renorm_fs_d
583         jal     renorm_ft_d
584         b       5f
585 2:
586         jal     renorm_fs_d
587         subu    ta1, ta1, DEXP_BIAS             # unbias FT exponent
588         or      ta2, ta2, DIMPL_ONE             # set implied one bit
589         b       5f
590 3:
591         bne     ta1, zero, result_ft_d          # if FT != 0, result=FT
592         bne     ta2, zero, result_ft_d
593         and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
594         bne     v0, FPC_ROUND_RM, 1f    # round to -infinity?
595         or      t0, t0, ta0                     # compute result sign
596         b       result_fs_d
597 1:
598         and     t0, t0, ta0                     # compute result sign
599         b       result_fs_d
600 4:
601         bne     ta1, zero, 2f                   # is FT a denormalized num?
602         beq     ta2, zero, result_fs_d          # FT is zero, result=FS
603         subu    t1, t1, DEXP_BIAS               # unbias FS exponent
604         or      t2, t2, DIMPL_ONE               # set implied one bit
605         jal     renorm_ft_d
606         b       5f
607 2:
608         subu    t1, t1, DEXP_BIAS               # unbias FS exponent
609         or      t2, t2, DIMPL_ONE               # set implied one bit
610         subu    ta1, ta1, DEXP_BIAS             # unbias FT exponent
611         or      ta2, ta2, DIMPL_ONE             # set implied one bit
612 /*
613  * Perform the addition.
614  */
615 5:
616         move    t8, zero                        # no shifted bits (sticky reg)
617         beq     t1, ta1, 4f                     # no shift needed
618         subu    v0, t1, ta1                     # v0 = difference of exponents
619         move    v1, v0                          # v1 = abs(difference)
620         bge     v0, zero, 1f
621         negu    v1
622 1:
623         ble     v1, DFRAC_BITS+2, 2f            # is difference too great?
624         li      t8, STICKYBIT                   # set the sticky bit
625         bge     v0, zero, 1f                    # check which exp is larger
626         move    t1, ta1                         # result exp is FTs
627         move    t2, zero                        # FSs fraction shifted is zero
628         b       4f
629 1:
630         move    ta2, zero                       # FTs fraction shifted is zero
631         b       4f
632 2:
633         li      t9, 64
634         subu    t9, t9, v1
635         bge     v0, zero, 3f                    # if FS > FT, shift FTs frac
636         move    t1, ta1                         # FT > FS, result exp is FTs
637         dsll    t8, t2, t9                      # save bits shifted out
638         dsrl    t2, t2, v1
639         b       4f
640 3:
641         dsll    t8, ta2, t9                     # save bits shifted out
642         dsrl    ta2, ta2, v1
643 4:
644         bne     t0, ta0, 1f                     # if signs differ, subtract
645         daddu   t2, ta2                         # add fractions
646         b       norm_d
647 1:
648         blt     t2, ta2, 3f                     # subtract larger from smaller
649         bne     t2, ta2, 2f
650         move    t1, zero                        # result=0
651         move    t2, zero
652         and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
653         bne     v0, FPC_ROUND_RM, 1f    # round to -infinity?
654         or      t0, t0, ta0                     # compute result sign
655         b       result_fs_d
656 1:
657         and     t0, t0, ta0                     # compute result sign
658         b       result_fs_d
659 2:
660         sltu    t9, zero, t8                    # compute t2:zero - ta2:t8
661         dsubu   t8, zero, t8
662         dsubu   t2, t2, ta2                     # subtract fractions
663         dsubu   t2, t2, t9                      # subtract barrow
664         b       norm_d
665 3:
666         move    t0, ta0                         # sign of result = FTs
667         sltu    t9, zero, t8
668         dsubu   t2, ta2, t2                     # subtract fractions
669         dsubu   t2, t2, t9                      # subtract barrow
670         b       norm_d
671
672 /*
673  * Single precision multiply.
674  */
675 mul_s:
676         jal     get_ft_fs_s
677         xor     t0, t0, ta0                     # compute sign of result
678         move    ta0, t0
679         bne     t1, SEXP_INF, 2f                # is FS an infinity?
680         bne     t2, zero, result_fs_s           # if FS is a NAN, result=FS
681         bne     ta1, SEXP_INF, 1f               # FS is inf, is FT an infinity?
682         bne     ta2, zero, result_ft_s          # if FT is a NAN, result=FT
683         b       result_fs_s                     # result is infinity
684 1:
685         bne     ta1, zero, result_fs_s          # inf * zero? if no, result=FS
686         bne     ta2, zero, result_fs_s
687         b       invalid_s                       # infinity * zero is invalid
688 2:
689         bne     ta1, SEXP_INF, 1f               # FS != inf, is FT an infinity?
690         bne     t1, zero, result_ft_s           # zero * inf? if no, result=FT
691         bne     t2, zero, result_ft_s
692         bne     ta2, zero, result_ft_s          # if FT is a NAN, result=FT
693         b       invalid_s                       # zero * infinity is invalid
694 1:
695         bne     t1, zero, 1f                    # is FS zero?
696         beq     t2, zero, result_fs_s           # result is zero
697         jal     renorm_fs_s
698         b       2f
699 1:
700         subu    t1, t1, SEXP_BIAS               # unbias FS exponent
701         or      t2, t2, SIMPL_ONE               # set implied one bit
702 2:
703         bne     ta1, zero, 1f                   # is FT zero?
704         beq     ta2, zero, result_ft_s          # result is zero
705         jal     renorm_ft_s
706         b       2f
707 1:
708         subu    ta1, ta1, SEXP_BIAS             # unbias FT exponent
709         or      ta2, ta2, SIMPL_ONE             # set implied one bit
710 2:
711         addu    t1, t1, ta1                     # compute result exponent
712         addu    t1, t1, 9                       # account for binary point
713         multu   t2, ta2                         # multiply fractions
714         mflo    t8
715         mfhi    t2
716         b       norm_s
717
718 /*
719  * Double precision multiply.
720  */
721 mul_d:
722         jal     get_ft_fs_d
723         xor     t0, t0, ta0                     # compute sign of result
724         move    ta0, t0
725         bne     t1, DEXP_INF, 2f                # is FS an infinity?
726         bne     t2, zero, result_fs_d           # if FS is a NAN, result=FS
727         bne     ta1, DEXP_INF, 1f               # FS is inf, is FT an infinity?
728         bne     ta2, zero, result_ft_d          # if FT is a NAN, result=FT
729         b       result_fs_d                     # result is infinity
730 1:
731         bne     ta1, zero, result_fs_d          # inf * zero? if no, result=FS
732         bne     ta2, zero, result_fs_d
733         b       invalid_d                       # infinity * zero is invalid
734 2:
735         bne     ta1, DEXP_INF, 1f               # FS != inf, is FT an infinity?
736         bne     t1, zero, result_ft_d           # zero * inf? if no, result=FT
737         bne     t2, zero, result_ft_d           # if FS is a NAN, result=FS
738         bne     ta2, zero, result_ft_d          # if FT is a NAN, result=FT
739         b       invalid_d                       # zero * infinity is invalid
740 1:
741         bne     t1, zero, 2f                    # is FS zero?
742         beq     t2, zero, result_fs_d           # result is zero
743         jal     renorm_fs_d
744         b       3f
745 2:
746         subu    t1, t1, DEXP_BIAS               # unbias FS exponent
747         or      t2, t2, DIMPL_ONE               # set implied one bit
748 3:
749         bne     ta1, zero, 2f                   # is FT zero?
750         beq     ta2, zero, result_ft_d          # result is zero
751         jal     renorm_ft_d
752         b       3f
753 2:
754         subu    ta1, ta1, DEXP_BIAS             # unbias FT exponent
755         or      ta2, ta2, DIMPL_ONE             # set implied one bit
756 3:
757         addu    t1, t1, ta1                     # compute result exponent
758         addu    t1, t1, 12                      # ???
759         dmultu  t2, ta2                         # multiply fractions
760         mflo    t8
761         mfhi    t2
762         b       norm_d
763
764 /*
765  * Single precision divide.
766  */
767 div_s:
768         jal     get_ft_fs_s
769         xor     t0, t0, ta0                     # compute sign of result
770         move    ta0, t0
771         bne     t1, SEXP_INF, 1f                # is FS an infinity?
772         bne     t2, zero, result_fs_s           # if FS is NAN, result is FS
773         bne     ta1, SEXP_INF, result_fs_s      # is FT an infinity?
774         bne     ta2, zero, result_ft_s          # if FT is NAN, result is FT
775         b       invalid_s                       # infinity/infinity is invalid
776 1:
777         bne     ta1, SEXP_INF, 1f               # is FT an infinity?
778         bne     ta2, zero, result_ft_s          # if FT is NAN, result is FT
779         move    t1, zero                        # x / infinity is zero
780         move    t2, zero
781         b       result_fs_s
782 1:
783         bne     t1, zero, 2f                    # is FS zero?
784         bne     t2, zero, 1f
785         bne     ta1, zero, result_fs_s          # FS=zero, is FT zero?
786         beq     ta2, zero, invalid_s            # 0 / 0
787         b       result_fs_s                     # result = zero
788 1:
789         jal     renorm_fs_s
790         b       3f
791 2:
792         subu    t1, t1, SEXP_BIAS               # unbias FS exponent
793         or      t2, t2, SIMPL_ONE               # set implied one bit
794 3:
795         bne     ta1, zero, 2f                   # is FT zero?
796         bne     ta2, zero, 1f
797         or      a1, a1, FPC_EXCEPTION_DIV0 | FPC_STICKY_DIV0
798         and     v0, a1, FPC_ENABLE_DIV0 # trap enabled?
799         bne     v0, zero, fpe_trap
800         ctc1    a1, FPC_CSR             # save exceptions
801         li      t1, SEXP_INF                    # result is infinity
802         move    t2, zero
803         b       result_fs_s
804 1:
805         jal     renorm_ft_s
806         b       3f
807 2:
808         subu    ta1, ta1, SEXP_BIAS             # unbias FT exponent
809         or      ta2, ta2, SIMPL_ONE             # set implied one bit
810 3:
811         subu    t1, t1, ta1                     # compute exponent
812         subu    t1, t1, 3                       # compensate for result position
813         li      v0, SFRAC_BITS+3                # number of bits to divide
814         move    t8, t2                          # init dividend
815         move    t2, zero                        # init result
816 1:
817         bltu    t8, ta2, 3f                     # is dividend >= divisor?
818 2:
819         subu    t8, t8, ta2                     # subtract divisor from dividend
820         or      t2, t2, 1                       # remember that we did
821         bne     t8, zero, 3f                    # if not done, continue
822         sll     t2, t2, v0                      # shift result to final position
823         b       norm_s
824 3:
825         sll     t8, t8, 1                       # shift dividend
826         sll     t2, t2, 1                       # shift result
827         subu    v0, v0, 1                       # are we done?
828         bne     v0, zero, 1b                    # no, continue
829         b       norm_s
830
831 /*
832  * Double precision divide.
833  */
834 div_d:
835         jal     get_ft_fs_d
836         xor     t0, t0, ta0                     # compute sign of result
837         move    ta0, t0
838         bne     t1, DEXP_INF, 1f                # is FS an infinity?
839         bne     t2, zero, result_fs_d           # if FS is NAN, result is FS
840         bne     ta1, DEXP_INF, result_fs_d      # is FT an infinity?
841         bne     ta2, zero, result_ft_d          # if FT is NAN, result is FT
842         b       invalid_d                       # infinity/infinity is invalid
843 1:
844         bne     ta1, DEXP_INF, 1f               # is FT an infinity?
845         bne     ta2, zero, result_ft_d          # if FT is NAN, result is FT
846         move    t1, zero                        # x / infinity is zero
847         move    t2, zero
848         b       result_fs_d
849 1:
850         bne     t1, zero, 2f                    # is FS zero?
851         bne     t2, zero, 1f
852         bne     ta1, zero, result_fs_d          # FS=zero, is FT zero?
853         beq     ta2, zero, invalid_d            # 0 / 0
854         b       result_fs_d                     # result = zero
855 1:
856         jal     renorm_fs_d
857         b       3f
858 2:
859         subu    t1, t1, DEXP_BIAS               # unbias FS exponent
860         or      t2, t2, DIMPL_ONE               # set implied one bit
861 3:
862         bne     ta1, zero, 2f                   # is FT zero?
863         bne     ta2, zero, 1f
864         or      a1, a1, FPC_EXCEPTION_DIV0 | FPC_STICKY_DIV0
865         and     v0, a1, FPC_ENABLE_DIV0 # trap enabled?
866         bne     v0, zero, fpe_trap
867         ctc1    a1, FPC_CSR                     # Save exceptions
868         li      t1, DEXP_INF                    # result is infinity
869         move    t2, zero
870         b       result_fs_d
871 1:
872         jal     renorm_ft_d
873         b       3f
874 2:
875         subu    ta1, ta1, DEXP_BIAS             # unbias FT exponent
876         or      ta2, ta2, DIMPL_ONE             # set implied one bit
877 3:
878         subu    t1, t1, ta1                     # compute exponent
879         subu    t1, t1, 3                       # compensate for result position
880         li      v0, DFRAC_BITS+3                # number of bits to divide
881         move    t8, t2                          # init dividend
882         move    t2, zero                        # init result
883 1:
884         bltu    t8, ta2, 3f                     # is dividend >= divisor?
885 2:
886         dsubu   t8, t8, ta2                     # subtract divisor from dividend
887         or      t2, t2, 1                       # remember that we did
888         bne     t8, zero, 3f                    # if not done, continue
889         dsll    t2, t2, v0                      # shift upper part
890         b       norm_d
891 3:
892         dsll    t8, t8, 1                       # shift dividend
893         dsll    t2, t2, 1                       # shift result
894         subu    v0, v0, 1                       # are we done?
895         bne     v0, zero, 1b                    # no, continue
896         b       norm_d
897
898 /*
899  * Single precision absolute value.
900  */
901 abs_s:
902         jal     get_fs_s
903         move    t0, zero                        # set sign positive
904         b       result_fs_s
905
906 /*
907  * Double precision absolute value.
908  */
909 abs_d:
910         jal     get_fs_d
911         move    t0, zero                        # set sign positive
912         b       result_fs_d
913
914 /*
915  * Single precision move.
916  */
917 mov_s:
918         jal     get_fs_s
919         b       result_fs_s
920
921 /*
922  * Double precision move.
923  */
924 mov_d:
925         jal     get_fs_d
926         b       result_fs_d
927
928 /*
929  * Single precision negate.
930  */
931 neg_s:
932         jal     get_fs_s
933         xor     t0, t0, 1                       # reverse sign
934         b       result_fs_s
935
936 /*
937  * Double precision negate.
938  */
939 neg_d:
940         jal     get_fs_d
941         xor     t0, t0, 1                       # reverse sign
942         b       result_fs_d
943
944 /*
945  * Convert double to single.
946  */
947 cvt_s_d:
948         jal     get_fs_d
949         bne     t1, DEXP_INF, 1f                # is FS an infinity?
950         li      t1, SEXP_INF                    # convert to single
951         dsll    t2, t2, 3                       # convert D fraction to S
952         b       result_fs_s
953 1:
954         bne     t1, zero, 2f                    # is FS zero?
955         beq     t2, zero, result_fs_s           # result=0
956         jal     renorm_fs_d
957         subu    t1, t1, 3                       # correct exp for shift below
958         b       3f
959 2:
960         subu    t1, t1, DEXP_BIAS               # unbias exponent
961         or      t2, t2, DIMPL_ONE               # add implied one bit
962 3:
963         dsll    t2, t2, 3                       # convert D fraction to S
964         b       norm_noshift_s
965
966 /*
967  * Convert long integer to single.
968  */
969 cvt_s_l:
970         jal     get_fs_long
971         b       cvt_s_int
972 /*
973  * Convert integer to single.
974  */
975 cvt_s_w:
976         jal     get_fs_int
977 cvt_s_int:
978         bne     t2, zero, 1f                    # check for zero
979         move    t1, zero
980         b       result_fs_s
981 /*
982  * Find out how many leading zero bits are in t2 and put in t9.
983  */
984 1:
985         move    v0, t2
986         move    t9, zero
987         dsrl    v1, v0, 32
988         bne     v1, zero, 1f
989         addu    t9, 32
990         dsll    v0, 32
991 1:
992         dsrl    v1, v0, 16
993         bne     v1, zero, 1f
994         addu    t9, 16
995         dsll    v0, 16
996 1:
997         dsrl    v1, v0, 24
998         bne     v1, zero, 1f
999         addu    t9, 8
1000         dsll    v0, 8
1001 1:
1002         dsrl    v1, v0, 28
1003         bne     v1, zero, 1f
1004         addu    t9, 4
1005         dsll    v0, 4
1006 1:
1007         dsrl    v1, v0, 30
1008         bne     v1, zero, 1f
1009         addu    t9, 2
1010         dsll    v0, 2
1011 1:
1012         dsrl    v1, v0, 31
1013         bne     v1, zero, 1f
1014         addu    t9, 1
1015 /*
1016  * Now shift t2 the correct number of bits.
1017  */
1018 1:
1019         subu    t9, SLEAD_ZEROS                 # dont count leading zeros
1020         li      t1, 23+32                       # init exponent
1021         subu    t1, t1, t9                      # compute exponent
1022         beq     t9, zero, 1f
1023         li      v0, 32
1024         blt     t9, zero, 2f                    # if shift < 0, shift right
1025         subu    v0, v0, t9
1026         sll     t2, t2, t9                      # shift left
1027 1:
1028         add     t1, t1, SEXP_BIAS               # bias exponent
1029         and     t2, t2, ~SIMPL_ONE              # clear implied one bit
1030         b       result_fs_s
1031 2:
1032         negu    t9                              # shift right by t9
1033         subu    v0, v0, t9
1034         sll     t8, t2, v0                      # save bits shifted out
1035         srl     t2, t2, t9
1036         b       norm_noshift_s
1037
1038 /*
1039  * Convert single to double.
1040  */
1041 cvt_d_s:
1042         jal     get_fs_s
1043         dsll    t2, 32
1044         bne     t1, SEXP_INF, 1f                # is FS an infinity?
1045         li      t1, DEXP_INF                    # convert to double
1046         b       result_fs_d
1047 1:
1048         bne     t1, zero, 2f                    # is FS denormalized or zero?
1049         beq     t2, zero, result_fs_d           # is FS zero?
1050         jal     renorm_fs_s
1051         move    t8, zero
1052         b       norm_d
1053 2:
1054         addu    t1, t1, DEXP_BIAS - SEXP_BIAS   # bias exponent correctly
1055         dsrl    t2, t2, 3
1056         b       result_fs_d
1057
1058 /*
1059  * Convert long integer to double.
1060  */
1061 cvt_d_l:
1062         jal     get_fs_long
1063         b       cvt_d_int
1064 /*
1065  * Convert integer to double.
1066  */
1067 cvt_d_w:
1068         jal     get_fs_int
1069 cvt_d_int:
1070         bne     t2, zero, 1f                    # check for zero
1071         move    t1, zero                        # result=0
1072         b       result_fs_d
1073 /*
1074  * Find out how many leading zero bits are in t2 and put in t9.
1075  */
1076 1:
1077         move    v0, t2
1078         move    t9, zero
1079         dsrl    v1, v0, 32
1080         bne     v1, zero, 1f
1081         addu    t9, 32
1082         dsll    v0, 32
1083 1:
1084         dsrl    v1, v0, 16
1085         bne     v1, zero, 1f
1086         addu    t9, 16
1087         dsll    v0, 16
1088 1:
1089         dsrl    v1, v0, 24
1090         bne     v1, zero, 1f
1091         addu    t9, 8
1092         dsll    v0, 8
1093 1:
1094         dsrl    v1, v0, 28
1095         bne     v1, zero, 1f
1096         addu    t9, 4
1097         dsll    v0, 4
1098 1:
1099         dsrl    v1, v0, 30
1100         bne     v1, zero, 1f
1101         addu    t9, 2
1102         dsll    v0, 2
1103 1:
1104         dsrl    v1, v0, 31
1105         bne     v1, zero, 1f
1106         addu    t9, 1
1107 /*
1108  * Now shift t2 the correct number of bits.
1109  */
1110 1:
1111         subu    t9, t9, DLEAD_ZEROS             # dont count leading zeros
1112         li      t1, DEXP_BIAS + 20              # init exponent
1113         subu    t1, t1, t9                      # compute exponent
1114         beq     t9, zero, 1f
1115         li      v0, 64
1116         blt     t9, zero, 2f                    # if shift < 0, shift right
1117         subu    v0, v0, t9
1118         dsll    t2, t2, t9                      # shift left
1119 1:
1120         and     t2, t2, ~DIMPL_ONE              # clear implied one bit
1121         b       result_fs_d
1122 2:
1123         negu    t9                              # shift right by t9
1124         subu    v0, v0, t9
1125         dsrl    t2, t2, t9
1126         and     t2, t2, ~DIMPL_ONE              # clear implied one bit
1127         b       result_fs_d
1128
1129 /*
1130  * Convert single to integer with specific rounding.
1131  */
1132 round_w_s:
1133         li      t3, FPC_ROUND_RN
1134         b       do_cvt_w_s
1135 trunc_w_s:
1136         li      t3, FPC_ROUND_RZ
1137         b       do_cvt_w_s
1138 ceil_w_s:
1139         li      t3, FPC_ROUND_RP
1140         b       do_cvt_w_s
1141 floor_w_s:
1142         li      t3, FPC_ROUND_RM
1143         b       do_cvt_w_s
1144
1145 /*
1146  * Convert single to integer.
1147  */
1148 cvt_w_s:
1149         and     t3, a1, FPC_ROUNDING_BITS       # get rounding mode
1150 do_cvt_w_s:
1151         jal     get_fs_s
1152         bne     t1, SEXP_INF, 1f                # is FS an infinity?
1153         bne     t2, zero, invalid_w             # invalid conversion
1154 1:
1155         bne     t1, zero, 1f                    # is FS zero?
1156         beq     t2, zero, result_fs_w           # result is zero
1157         move    t2, zero                        # result is an inexact zero
1158         b       inexact_w
1159 1:
1160         subu    t1, t1, SEXP_BIAS               # unbias exponent
1161         or      t2, t2, SIMPL_ONE               # add implied one bit
1162         dsll    t2, t2, DFRAC_BITS - SFRAC_BITS # convert S fraction to D
1163         b       cvt_w
1164
1165 /*
1166  * Convert double to integer with specific rounding.
1167  */
1168 round_w_d:
1169         li      t3, FPC_ROUND_RN
1170         b       do_cvt_w_d
1171 trunc_w_d:
1172         li      t3, FPC_ROUND_RZ
1173         b       do_cvt_w_d
1174 ceil_w_d:
1175         li      t3, FPC_ROUND_RP
1176         b       do_cvt_w_d
1177 floor_w_d:
1178         li      t3, FPC_ROUND_RM
1179         b       do_cvt_w_d
1180
1181 /*
1182  * Convert double to integer.
1183  */
1184 cvt_w_d:
1185         and     t3, a1, FPC_ROUNDING_BITS       # get rounding mode
1186 do_cvt_w_d:
1187         jal     get_fs_d
1188         bne     t1, DEXP_INF, 1f                # is FS an infinity?
1189         bne     t2, zero, invalid_w             # invalid conversion
1190 1:
1191         bne     t1, zero, 2f                    # is FS zero?
1192         beq     t2, zero, result_fs_w           # result is zero
1193         move    t2, zero                        # result is an inexact zero
1194         b       inexact_w
1195 2:
1196         subu    t1, t1, DEXP_BIAS               # unbias exponent
1197         or      t2, t2, DIMPL_ONE               # add implied one bit
1198 cvt_w:
1199         blt     t1, WEXP_MIN, underflow_w       # is exponent too small?
1200         li      v0, WEXP_MAX+1
1201         bgt     t1, v0, overflow_w              # is exponent too large?
1202         bne     t1, v0, 1f                      # special check for INT_MIN
1203         beq     t0, zero, overflow_w            # if positive, overflow
1204         bne     t2, DIMPL_ONE, overflow_w
1205         li      t2, INT_MIN                     # result is INT_MIN
1206         b       result_fs_w
1207 1:
1208         subu    v0, t1, 20                      # compute amount to shift
1209         beq     v0, zero, 2f                    # is shift needed?
1210         li      v1, 64
1211         blt     v0, zero, 1f                    # if shift < 0, shift right
1212         subu    v1, v1, v0                      # shift left
1213         dsll    t2, t2, v0
1214         b       2f
1215 1:
1216         negu    v0                              # shift right by v0
1217         subu    v1, v1, v0
1218         dsll    t8, t2, v1                      # save bits shifted out
1219         sltu    t8, zero, t8                    # dont lose any ones
1220         dsrl    t2, t2, v0
1221 /*
1222  * round (t0 is sign, t2:63-32 is integer part, t2:31-0 is fractional part).
1223  */
1224 2:
1225         beq     t3, FPC_ROUND_RN, 3f            # round to nearest
1226         beq     t3, FPC_ROUND_RZ, 5f            # round to zero (truncate)
1227         beq     t3, FPC_ROUND_RP, 1f            # round to +infinity
1228         beq     t0, zero, 5f                    # if sign is positive, truncate
1229         b       2f
1230 1:
1231         bne     t0, zero, 5f                    # if sign is negative, truncate
1232 2:
1233         daddu   t2, t2, GUARDBIT                # add in fractional
1234         blt     t2, zero, overflow_w            # overflow?
1235         b       5f
1236 3:
1237         daddu   t2, t2, GUARDBIT                # add in fractional
1238         blt     t2, zero, overflow_w            # overflow?
1239 4:
1240         bne     v0, zero, 5f                    # if rounded remainder is zero
1241         and     t2, 0xfffffffe00000000          #  clear LSB (round to nearest)
1242 5:
1243         beq     t0, zero, 1f                    # result positive?
1244         negu    t2                              # convert to negative integer
1245 1:
1246         dsll    v0, 32                          # save fraction
1247         dsrl    t2, 32                          # shift out fractional part
1248         beq     v0, zero, result_fs_w           # is result exact?
1249 /*
1250  * Handle inexact exception.
1251  */
1252 inexact_w:
1253         or      a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
1254         and     v0, a1, FPC_ENABLE_INEXACT
1255         bne     v0, zero, fpe_trap
1256         ctc1    a1, FPC_CSR             # save exceptions
1257         b       result_fs_w
1258
1259 /*
1260  * Conversions to integer which overflow will trap (if enabled),
1261  * or generate an inexact trap (if enabled),
1262  * or generate an invalid exception.
1263  */
1264 overflow_w:
1265         or      a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW
1266         and     v0, a1, FPC_ENABLE_OVERFLOW
1267         bne     v0, zero, fpe_trap
1268         and     v0, a1, FPC_ENABLE_INEXACT
1269         bne     v0, zero, inexact_w             # inexact traps enabled?
1270         b       invalid_w
1271
1272 /*
1273  * Conversions to integer which underflow will trap (if enabled),
1274  * or generate an inexact trap (if enabled),
1275  * or generate an invalid exception.
1276  */
1277 underflow_w:
1278         or      a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
1279         and     v0, a1, FPC_ENABLE_UNDERFLOW
1280         bne     v0, zero, fpe_trap
1281         and     v0, a1, FPC_ENABLE_INEXACT
1282         bne     v0, zero, inexact_w             # inexact traps enabled?
1283         b       invalid_w
1284
1285 /*
1286  * Convert single to long integer with specific rounding.
1287  */
1288 round_l_s:
1289         li      t3, FPC_ROUND_RN
1290         b       do_cvt_l_s
1291 trunc_l_s:
1292         li      t3, FPC_ROUND_RZ
1293         b       do_cvt_l_s
1294 ceil_l_s:
1295         li      t3, FPC_ROUND_RP
1296         b       do_cvt_l_s
1297 floor_l_s:
1298         li      t3, FPC_ROUND_RM
1299         b       do_cvt_l_s
1300
1301 /*
1302  * Convert single to long integer.
1303  */
1304 cvt_l_s:
1305         and     t3, a1, FPC_ROUNDING_BITS       # get rounding mode
1306 do_cvt_l_s:
1307         jal     get_fs_s
1308         bne     t1, SEXP_INF, 1f                # is FS an infinity?
1309         bne     t2, zero, invalid_l             # invalid conversion
1310 1:
1311         bne     t1, zero, 1f                    # is FS zero?
1312         beq     t2, zero, result_fs_l           # result is zero
1313         move    t2, zero                        # result is an inexact zero
1314         b       inexact_l
1315 1:
1316         subu    t1, t1, SEXP_BIAS               # unbias exponent
1317         or      t2, t2, SIMPL_ONE               # add implied one bit
1318         dsll    t2, t2, DFRAC_BITS - SFRAC_BITS # convert S fraction to D
1319         b       cvt_l
1320
1321 /*
1322  * Convert double to long integer with specific rounding.
1323  */
1324 round_l_d:
1325         li      t3, FPC_ROUND_RN
1326         b       do_cvt_l_d
1327 trunc_l_d:
1328         li      t3, FPC_ROUND_RZ
1329         b       do_cvt_l_d
1330 ceil_l_d:
1331         li      t3, FPC_ROUND_RP
1332         b       do_cvt_l_d
1333 floor_l_d:
1334         li      t3, FPC_ROUND_RM
1335         b       do_cvt_l_d
1336
1337 /*
1338  * Convert double to long integer.
1339  */
1340 cvt_l_d:
1341         and     t3, a1, FPC_ROUNDING_BITS       # get rounding mode
1342 do_cvt_l_d:
1343         jal     get_fs_d
1344         bne     t1, DEXP_INF, 1f                # is FS an infinity?
1345         bne     t2, zero, invalid_l             # invalid conversion
1346 1:
1347         bne     t1, zero, 2f                    # is FS zero?
1348         beq     t2, zero, result_fs_l           # result is zero
1349         move    t2, zero                        # result is an inexact zero
1350         b       inexact_l
1351 2:
1352         subu    t1, t1, DEXP_BIAS               # unbias exponent
1353         or      t2, t2, DIMPL_ONE               # add implied one bit
1354 cvt_l:
1355         blt     t1, LEXP_MIN, underflow_l       # is exponent too small?
1356         li      v0, LEXP_MAX+1
1357         bgt     t1, v0, overflow_l              # is exponent too large?
1358         bne     t1, v0, 1f                      # special check for LONG_MIN
1359         beq     t0, zero, overflow_l            # if positive, overflow
1360         bne     t2, DIMPL_ONE, overflow_l
1361         dli     t2, LONG_MIN                    # result is LONG_MIN
1362         b       result_fs_l
1363 1:
1364         subu    v0, t1, DFRAC_BITS              # compute amount to shift
1365         beq     v0, zero, 2f                    # is shift needed?
1366         li      v1, 64
1367         blt     v0, zero, 1f                    # if shift < 0, shift right
1368         subu    v1, v1, v0                      # shift left
1369         dsll    t2, t2, v0
1370         b       2f
1371 1:
1372         negu    v0                              # shift right by v0
1373         subu    v1, v1, v0
1374         dsll    t8, t2, v1                      # save bits shifted out
1375         sltu    t8, zero, t8                    # dont lose any ones
1376         dsrl    t2, t2, v0
1377 /*
1378  * round (t0 is sign, t2 is integer part).
1379  */
1380 2:
1381         beq     t3, FPC_ROUND_RN, 3f            # round to nearest
1382         beq     t3, FPC_ROUND_RZ, 5f            # round to zero (truncate)
1383         beq     t3, FPC_ROUND_RP, 1f            # round to +infinity
1384         beq     t0, zero, 5f                    # if sign is positive, truncate
1385         b       2f
1386 1:
1387         bne     t0, zero, 5f                    # if sign is negative, truncate
1388 2:
1389         daddu   t2, t2, DGUARDBIT               # add in fractional
1390         blt     t2, zero, overflow_l            # overflow?
1391         b       5f
1392 3:
1393         daddu   t2, t2, DGUARDBIT               # add in fractional
1394         blt     t2, zero, overflow_l            # overflow?
1395 4:
1396         bne     v0, zero, 5f                    # if rounded remainder is zero
1397         and     t2, 0xe000000000000000          #  clear LSB (round to nearest)
1398 5:
1399         beq     t0, zero, 1f                    # result positive?
1400         negu    t2                              # convert to negative integer
1401 1:
1402         b       result_fs_l
1403         nop
1404 /*
1405  * Handle inexact exception.
1406  */
1407 inexact_l:
1408         or      a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
1409         and     v0, a1, FPC_ENABLE_INEXACT
1410         bne     v0, zero, fpe_trap
1411         ctc1    a1, FPC_CSR             # save exceptions
1412         b       result_fs_l
1413
1414 /*
1415  * Conversions to integer which overflow will trap (if enabled),
1416  * or generate an inexact trap (if enabled),
1417  * or generate an invalid exception.
1418  */
1419 overflow_l:
1420         or      a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW
1421         and     v0, a1, FPC_ENABLE_OVERFLOW
1422         bne     v0, zero, fpe_trap
1423         and     v0, a1, FPC_ENABLE_INEXACT
1424         bne     v0, zero, inexact_l             # inexact traps enabled?
1425         b       invalid_l
1426
1427 /*
1428  * Conversions to integer which underflow will trap (if enabled),
1429  * or generate an inexact trap (if enabled),
1430  * or generate an invalid exception.
1431  */
1432 underflow_l:
1433         or      a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
1434         and     v0, a1, FPC_ENABLE_UNDERFLOW
1435         bne     v0, zero, fpe_trap
1436         and     v0, a1, FPC_ENABLE_INEXACT
1437         bne     v0, zero, inexact_l             # inexact traps enabled?
1438         b       invalid_l
1439
1440 /*
1441  * Compare single.
1442  */
1443 cmp_s:
1444         jal     get_cmp_s
1445         bne     t1, SEXP_INF, 1f                # is FS an infinity?
1446         bne     t2, zero, unordered             # FS is a NAN
1447 1:
1448         bne     ta1, SEXP_INF, 2f               # is FT an infinity?
1449         bne     ta2, zero, unordered            # FT is a NAN
1450 2:
1451         sll     t1, t1, SFRAC_BITS              # reassemble exp & frac
1452         or      t1, t1, t2
1453         sll     ta1, ta1, SFRAC_BITS            # reassemble exp & frac
1454         or      ta1, ta1, ta2
1455         beq     t0, zero, 1f                    # is FS positive?
1456         negu    t1
1457 1:
1458         beq     ta0, zero, 1f                   # is FT positive?
1459         negu    ta1
1460 1:
1461         li      v0, COND_LESS
1462         blt     t1, ta1, test_cond              # is FS < FT?
1463         li      v0, COND_EQUAL
1464         beq     t1, ta1, test_cond              # is FS == FT?
1465         move    v0, zero                        # FS > FT
1466         b       test_cond
1467
1468 /*
1469  * Compare double.
1470  */
1471 cmp_d:
1472         jal     get_cmp_d
1473         bne     t1, DEXP_INF, 1f                # is FS an infinity?
1474         bne     t2, zero, unordered             # FS is a NAN
1475 1:
1476         bne     ta1, DEXP_INF, 2f               # is FT an infinity?
1477         bne     ta2, zero, unordered            # FT is a NAN
1478 2:
1479         dsll    t1, t1, DFRAC_BITS              # reassemble exp & frac
1480         or      t1, t1, t2
1481         dsll    ta1, ta1, DFRAC_BITS            # reassemble exp & frac
1482         or      ta1, ta1, ta2
1483         beq     t0, zero, 1f                    # is FS positive?
1484         dnegu   t1                              # negate t1
1485 1:
1486         beq     ta0, zero, 1f                   # is FT positive?
1487         dnegu   ta1
1488 1:
1489         li      v0, COND_LESS
1490         blt     t1, ta1, test_cond              # is FS(MSW) < FT(MSW)?
1491         li      v0, COND_EQUAL
1492         beq     t1, ta1, test_cond              # is FS(LSW) == FT(LSW)?
1493         move    v0, zero                        # FS > FT
1494 test_cond:
1495         and     v0, v0, a0                      # condition match instruction?
1496 set_cond:
1497         bne     v0, zero, 1f
1498         and     a1, a1, ~FPC_COND_BIT   # clear condition bit
1499         b       2f
1500 1:
1501         or      a1, a1, FPC_COND_BIT    # set condition bit
1502 2:
1503         ctc1    a1, FPC_CSR             # save condition bit
1504         b       done
1505
1506 unordered:
1507         and     v0, a0, COND_UNORDERED          # this cmp match unordered?
1508         bne     v0, zero, 1f
1509         and     a1, a1, ~FPC_COND_BIT   # clear condition bit
1510         b       2f
1511 1:
1512         or      a1, a1, FPC_COND_BIT    # set condition bit
1513 2:
1514         and     v0, a0, COND_SIGNAL
1515         beq     v0, zero, 1f                    # is this a signaling cmp?
1516         or      a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
1517         and     v0, a1, FPC_ENABLE_INVALID
1518         bne     v0, zero, fpe_trap
1519 1:
1520         ctc1    a1, FPC_CSR             # save condition bit
1521         b       done
1522
1523 /*
1524  * Determine the amount to shift the fraction in order to restore the
1525  * normalized position. After that, round and handle exceptions.
1526  */
1527 norm_s:
1528         move    v0, t2
1529         move    t9, zero                        # t9 = num of leading zeros
1530         bne     t2, zero, 1f
1531         move    v0, t8
1532         addu    t9, 32
1533 1:
1534         srl     v1, v0, 16
1535         bne     v1, zero, 1f
1536         addu    t9, 16
1537         sll     v0, 16
1538 1:
1539         srl     v1, v0, 24
1540         bne     v1, zero, 1f
1541         addu    t9, 8
1542         sll     v0, 8
1543 1:
1544         srl     v1, v0, 28
1545         bne     v1, zero, 1f
1546         addu    t9, 4
1547         sll     v0, 4
1548 1:
1549         srl     v1, v0, 30
1550         bne     v1, zero, 1f
1551         addu    t9, 2
1552         sll     v0, 2
1553 1:
1554         srl     v1, v0, 31
1555         bne     v1, zero, 1f
1556         addu    t9, 1
1557 /*
1558  * Now shift t2,t8 the correct number of bits.
1559  */
1560 1:
1561         subu    t9, t9, SLEAD_ZEROS             # dont count leading zeros
1562         subu    t1, t1, t9                      # adjust the exponent
1563         beq     t9, zero, norm_noshift_s
1564         li      v1, 32
1565         blt     t9, zero, 1f                    # if shift < 0, shift right
1566         subu    v1, v1, t9
1567         sll     t2, t2, t9                      # shift t2,t8 left
1568         srl     v0, t8, v1                      # save bits shifted out
1569         or      t2, t2, v0
1570         sll     t8, t8, t9
1571         b       norm_noshift_s
1572 1:
1573         negu    t9                              # shift t2,t8 right by t9
1574         subu    v1, v1, t9
1575         sll     v0, t8, v1                      # save bits shifted out
1576         sltu    v0, zero, v0                    # be sure to save any one bits
1577         srl     t8, t8, t9
1578         or      t8, t8, v0
1579         sll     v0, t2, v1                      # save bits shifted out
1580         or      t8, t8, v0
1581         srl     t2, t2, t9
1582 norm_noshift_s:
1583         move    ta1, t1                         # save unrounded exponent
1584         move    ta2, t2                         # save unrounded fraction
1585         and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
1586         beq     v0, FPC_ROUND_RN, 3f    # round to nearest
1587         beq     v0, FPC_ROUND_RZ, 5f    # round to zero (truncate)
1588         beq     v0, FPC_ROUND_RP, 1f    # round to +infinity
1589         beq     t0, zero, 5f                    # if sign is positive, truncate
1590         b       2f
1591 1:
1592         bne     t0, zero, 5f                    # if sign is negative, truncate
1593 2:
1594         beq     t8, zero, 5f                    # if exact, continue
1595         addu    t2, t2, 1                       # add rounding bit
1596         bne     t2, SIMPL_ONE<<1, 5f            # need to adjust exponent?
1597         addu    t1, t1, 1                       # adjust exponent
1598         srl     t2, t2, 1                       # renormalize fraction
1599         b       5f
1600 3:
1601         li      v0, GUARDBIT                    # load guard bit for rounding
1602         addu    v0, v0, t8                      # add remainder
1603         sltu    v1, v0, t8                      # compute carry out
1604         beq     v1, zero, 4f                    # if no carry, continue
1605         addu    t2, t2, 1                       # add carry to result
1606         bne     t2, SIMPL_ONE<<1, 4f            # need to adjust exponent?
1607         addu    t1, t1, 1                       # adjust exponent
1608         srl     t2, t2, 1                       # renormalize fraction
1609 4:
1610         bne     v0, zero, 5f                    # if rounded remainder is zero
1611         and     t2, t2, ~1                      #  clear LSB (round to nearest)
1612 5:
1613         bgt     t1, SEXP_MAX, overflow_s        # overflow?
1614         blt     t1, SEXP_MIN, underflow_s       # underflow?
1615         bne     t8, zero, inexact_s             # is result inexact?
1616         addu    t1, t1, SEXP_BIAS               # bias exponent
1617         and     t2, t2, ~SIMPL_ONE              # clear implied one bit
1618         b       result_fs_s
1619
1620 /*
1621  * Handle inexact exception.
1622  */
1623 inexact_s:
1624         addu    t1, t1, SEXP_BIAS               # bias exponent
1625         and     t2, t2, ~SIMPL_ONE              # clear implied one bit
1626 inexact_nobias_s:
1627         jal     set_fd_s                        # save result
1628         or      a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
1629         and     v0, a1, FPC_ENABLE_INEXACT
1630         bne     v0, zero, fpe_trap
1631         ctc1    a1, FPC_CSR             # save exceptions
1632         b       done
1633
1634 /*
1635  * Overflow will trap (if enabled),
1636  * or generate an inexact trap (if enabled),
1637  * or generate an infinity.
1638  */
1639 overflow_s:
1640         or      a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW
1641         and     v0, a1, FPC_ENABLE_OVERFLOW
1642         beq     v0, zero, 1f
1643         subu    t1, t1, 192                     # bias exponent
1644         and     t2, t2, ~SIMPL_ONE              # clear implied one bit
1645         jal     set_fd_s                        # save result
1646         b       fpe_trap
1647 1:
1648         and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
1649         beq     v0, FPC_ROUND_RN, 3f    # round to nearest
1650         beq     v0, FPC_ROUND_RZ, 1f    # round to zero (truncate)
1651         beq     v0, FPC_ROUND_RP, 2f    # round to +infinity
1652         bne     t0, zero, 3f
1653 1:
1654         li      t1, SEXP_MAX                    # result is max finite
1655         li      t2, 0x007fffff
1656         b       inexact_s
1657 2:
1658         bne     t0, zero, 1b
1659 3:
1660         li      t1, SEXP_MAX + 1                # result is infinity
1661         move    t2, zero
1662         b       inexact_s
1663
1664 /*
1665  * In this implementation, "tininess" is detected "after rounding" and
1666  * "loss of accuracy" is detected as "an inexact result".
1667  */
1668 underflow_s:
1669         and     v0, a1, FPC_ENABLE_UNDERFLOW
1670         beq     v0, zero, 1f
1671 /*
1672  * Underflow is enabled so compute the result and trap.
1673  */
1674         addu    t1, t1, 192                     # bias exponent
1675         and     t2, t2, ~SIMPL_ONE              # clear implied one bit
1676         jal     set_fd_s                        # save result
1677         or      a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
1678         b       fpe_trap
1679 /*
1680  * Underflow is not enabled so compute the result,
1681  * signal inexact result (if it is) and trap (if enabled).
1682  */
1683 1:
1684         move    t1, ta1                         # get unrounded exponent
1685         move    t2, ta2                         # get unrounded fraction
1686         li      t9, SEXP_MIN                    # compute shift amount
1687         subu    t9, t9, t1                      # shift t2,t8 right by t9
1688         blt     t9, SFRAC_BITS+2, 3f            # shift all the bits out?
1689         move    t1, zero                        # result is inexact zero
1690         move    t2, zero
1691         or      a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
1692 /*
1693  * Now round the zero result.
1694  * Only need to worry about rounding to +- infinity when the sign matches.
1695  */
1696         and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
1697         beq     v0, FPC_ROUND_RN, inexact_nobias_s      # round to nearest
1698         beq     v0, FPC_ROUND_RZ, inexact_nobias_s      # round to zero
1699         beq     v0, FPC_ROUND_RP, 1f    # round to +infinity
1700         beq     t0, zero, inexact_nobias_s      # if sign is positive, truncate
1701         b       2f
1702 1:
1703         bne     t0, zero, inexact_nobias_s      # if sign is negative, truncate
1704 2:
1705         addu    t2, t2, 1                       # add rounding bit
1706         b       inexact_nobias_s
1707 3:
1708         li      v1, 32
1709         subu    v1, v1, t9
1710         sltu    v0, zero, t8                    # be sure to save any one bits
1711         sll     t8, t2, v1                      # save bits shifted out
1712         or      t8, t8, v0                      # include sticky bits
1713         srl     t2, t2, t9
1714 /*
1715  * Now round the denormalized result.
1716  */
1717         and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
1718         beq     v0, FPC_ROUND_RN, 3f    # round to nearest
1719         beq     v0, FPC_ROUND_RZ, 5f    # round to zero (truncate)
1720         beq     v0, FPC_ROUND_RP, 1f    # round to +infinity
1721         beq     t0, zero, 5f                    # if sign is positive, truncate
1722         b       2f
1723 1:
1724         bne     t0, zero, 5f                    # if sign is negative, truncate
1725 2:
1726         beq     t8, zero, 5f                    # if exact, continue
1727         addu    t2, t2, 1                       # add rounding bit
1728         b       5f
1729 3:
1730         li      v0, GUARDBIT                    # load guard bit for rounding
1731         addu    v0, v0, t8                      # add remainder
1732         sltu    v1, v0, t8                      # compute carry out
1733         beq     v1, zero, 4f                    # if no carry, continue
1734         addu    t2, t2, 1                       # add carry to result
1735 4:
1736         bne     v0, zero, 5f                    # if rounded remainder is zero
1737         and     t2, t2, ~1                      #  clear LSB (round to nearest)
1738 5:
1739         move    t1, zero                        # denorm or zero exponent
1740         jal     set_fd_s                        # save result
1741         beq     t8, zero, done                  # check for exact result
1742         or      a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
1743         or      a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
1744         and     v0, a1, FPC_ENABLE_INEXACT
1745         bne     v0, zero, fpe_trap
1746         ctc1    a1, FPC_CSR             # save exceptions
1747         b       done
1748
1749 /*
1750  * Determine the amount to shift the fraction in order to restore the
1751  * normalized position. After that, round and handle exceptions.
1752  */
1753 norm_d:
1754         move    v0, t2
1755         move    t9, zero                        # t9 = num of leading zeros
1756         dsrl    v1, v0, 32
1757         bne     v1, zero, 1f
1758         addu    t9, 32
1759         dsll    v0, 32
1760 1:
1761         dsrl    v1, v0, 16
1762         bne     v1, zero, 1f
1763         addu    t9, 16
1764         dsll    v0, 16
1765 1:
1766         dsrl    v1, v0, 24
1767         bne     v1, zero, 1f
1768         addu    t9, 8
1769         dsll    v0, 8
1770 1:
1771         dsrl    v1, v0, 28
1772         bne     v1, zero, 1f
1773         addu    t9, 4
1774         dsll    v0, 4
1775 1:
1776         dsrl    v1, v0, 30
1777         bne     v1, zero, 1f
1778         addu    t9, 2
1779         dsll    v0, 2
1780 1:
1781         dsrl    v1, v0, 31
1782         bne     v1, zero, 1f
1783         addu    t9, 1
1784 /*
1785  * Now shift t2,t8 the correct number of bits.
1786  */
1787 1:
1788         subu    t9, t9, DLEAD_ZEROS             # dont count leading zeros
1789         subu    t1, t1, t9                      # adjust the exponent
1790         beq     t9, zero, norm_noshift_d
1791         li      v1, 64
1792         blt     t9, zero, 2f                    # if shift < 0, shift right
1793         subu    v1, v1, t9
1794         dsll    t2, t2, t9                      # shift left by t9
1795         dsrl    v0, t8, v1                      # save bits shifted out
1796         or      t2, t2, v0
1797         dsll    t8, t8, t9
1798         b       norm_noshift_d
1799 2:
1800         negu    t9                              # shift right by t9
1801         subu    v1, v1, t9                      #  (known to be < 32 bits)
1802         dsll    v0, t8, v1                      # save bits shifted out
1803         sltu    v0, zero, v0                    # be sure to save any one bits
1804         dsrl    t8, t8, t9
1805         or      t8, t8, v0
1806         dsll    v0, t2, v1                      # save bits shifted out
1807         or      t8, t8, v0
1808         dsrl    t2, t2, t9
1809 norm_noshift_d:
1810         move    ta1, t1                         # save unrounded exponent
1811         move    ta2, t2                         # save unrounded fraction (MS)
1812         and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
1813         beq     v0, FPC_ROUND_RN, 3f    # round to nearest
1814         beq     v0, FPC_ROUND_RZ, 5f    # round to zero (truncate)
1815         beq     v0, FPC_ROUND_RP, 1f    # round to +infinity
1816         beq     t0, zero, 5f                    # if sign is positive, truncate
1817         b       2f
1818 1:
1819         bne     t0, zero, 5f                    # if sign is negative, truncate
1820 2:
1821         beq     t8, zero, 5f                    # if exact, continue
1822         daddu   t2, t2, 1                       # add rounding bit
1823         bne     t2, DIMPL_ONE<<1, 5f            # need to adjust exponent?
1824         addu    t1, t1, 1                       # adjust exponent
1825         dsrl    t2, t2, 1                       # renormalize fraction
1826         b       5f
1827 3:
1828         dli     v0, DGUARDBIT                   # load guard bit for rounding
1829         addu    v0, v0, t8                      # add remainder
1830         sltu    v1, v0, t8                      # compute carry out
1831         beq     v1, zero, 4f                    # branch if no carry
1832         daddu   t2, t2, 1                       # add carry to result
1833         bne     t2, DIMPL_ONE<<1, 4f            # need to adjust exponent?
1834         addu    t1, t1, 1                       # adjust exponent
1835         srl     t2, t2, 1                       # renormalize fraction
1836 4:
1837         bne     v0, zero, 5f                    # if rounded remainder is zero
1838         and     t2, t2, ~1                      #  clear LSB (round to nearest)
1839 5:
1840         bgt     t1, DEXP_MAX, overflow_d        # overflow?
1841         blt     t1, DEXP_MIN, underflow_d       # underflow?
1842         bne     t8, zero, inexact_d             # is result inexact?
1843         addu    t1, t1, DEXP_BIAS               # bias exponent
1844         and     t2, t2, ~DIMPL_ONE              # clear implied one bit
1845         b       result_fs_d
1846
1847 /*
1848  * Handle inexact exception.
1849  */
1850 inexact_d:
1851         addu    t1, t1, DEXP_BIAS               # bias exponent
1852         and     t2, t2, ~DIMPL_ONE              # clear implied one bit
1853 inexact_nobias_d:
1854         jal     set_fd_d                        # save result
1855         or      a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
1856         and     v0, a1, FPC_ENABLE_INEXACT
1857         bne     v0, zero, fpe_trap
1858         ctc1    a1, FPC_CSR             # save exceptions
1859         b       done
1860
1861 /*
1862  * Overflow will trap (if enabled),
1863  * or generate an inexact trap (if enabled),
1864  * or generate an infinity.
1865  */
1866 overflow_d:
1867         or      a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW
1868         and     v0, a1, FPC_ENABLE_OVERFLOW
1869         beq     v0, zero, 1f
1870         subu    t1, t1, 1536                    # bias exponent
1871         and     t2, t2, ~DIMPL_ONE              # clear implied one bit
1872         jal     set_fd_d                        # save result
1873         b       fpe_trap
1874 1:
1875         and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
1876         beq     v0, FPC_ROUND_RN, 3f    # round to nearest
1877         beq     v0, FPC_ROUND_RZ, 1f    # round to zero (truncate)
1878         beq     v0, FPC_ROUND_RP, 2f    # round to +infinity
1879         bne     t0, zero, 3f
1880 1:
1881         li      t1, DEXP_MAX                    # result is max finite
1882         dli     t2, 0x000fffffffffffff
1883         b       inexact_d
1884 2:
1885         bne     t0, zero, 1b
1886 3:
1887         li      t1, DEXP_MAX + 1                # result is infinity
1888         move    t2, zero
1889         b       inexact_d
1890
1891 /*
1892  * In this implementation, "tininess" is detected "after rounding" and
1893  * "loss of accuracy" is detected as "an inexact result".
1894  */
1895 underflow_d:
1896         and     v0, a1, FPC_ENABLE_UNDERFLOW
1897         beq     v0, zero, 1f
1898 /*
1899  * Underflow is enabled so compute the result and trap.
1900  */
1901         addu    t1, t1, 1536                    # bias exponent
1902         and     t2, t2, ~DIMPL_ONE              # clear implied one bit
1903         jal     set_fd_d                        # save result
1904         or      a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
1905         b       fpe_trap
1906 /*
1907  * Underflow is not enabled so compute the result,
1908  * signal inexact result (if it is) and trap (if enabled).
1909  */
1910 1:
1911         move    t1, ta1                         # get unrounded exponent
1912         move    t2, ta2                         # get unrounded fraction (MS)
1913         li      t9, DEXP_MIN                    # compute shift amount
1914         subu    t9, t9, t1                      # shift t2,t8 right by t9
1915         blt     t9, DFRAC_BITS+2, 3f            # shift all the bits out?
1916         move    t1, zero                        # result is inexact zero
1917         move    t2, zero
1918         or      a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
1919 /*
1920  * Now round the zero result.
1921  * Only need to worry about rounding to +- infinity when the sign matches.
1922  */
1923         and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
1924         beq     v0, FPC_ROUND_RN, inexact_nobias_d      # round to nearest
1925         beq     v0, FPC_ROUND_RZ, inexact_nobias_d      # round to zero
1926         beq     v0, FPC_ROUND_RP, 1f    # round to +infinity
1927         beq     t0, zero, inexact_nobias_d      # if sign is positive, truncate
1928         b       2f
1929 1:
1930         bne     t0, zero, inexact_nobias_d      # if sign is negative, truncate
1931 2:
1932         daddu   t2, t2, 1                       # add rounding bit
1933         b       inexact_nobias_d
1934 3:
1935         li      v1, 64
1936         subu    v1, v1, t9
1937         sltu    v0, zero, t8                    # be sure to save any one bits
1938         dsll    t8, t2, v1                      # save bits shifted out
1939         or      t8, t8, v0                      # include sticky bits
1940         dsrl    t2, t2, t9
1941 /*
1942  * Now round the denormalized result.
1943  */
1944         and     v0, a1, FPC_ROUNDING_BITS       # get rounding mode
1945         beq     v0, FPC_ROUND_RN, 3f    # round to nearest
1946         beq     v0, FPC_ROUND_RZ, 5f    # round to zero (truncate)
1947         beq     v0, FPC_ROUND_RP, 1f    # round to +infinity
1948         beq     t0, zero, 5f                    # if sign is positive, truncate
1949         b       2f
1950 1:
1951         bne     t0, zero, 5f                    # if sign is negative, truncate
1952 2:
1953         beq     t8, zero, 5f                    # if exact, continue
1954         daddu   t2, t2, 1                       # add rounding bit
1955         b       5f
1956 3:
1957         dli     v0, DGUARDBIT                   # load guard bit for rounding
1958         daddu   v0, v0, t8                      # add remainder
1959         sltu    v1, v0, t8                      # compute carry out
1960         beq     v1, zero, 4f                    # if no carry, continue
1961         daddu   t2, t2, 1                       # add carry
1962 4:
1963         bne     v0, zero, 5f                    # if rounded remainder is zero
1964         and     t2, t2, ~1                      #  clear LSB (round to nearest)
1965 5:
1966         move    t1, zero                        # denorm or zero exponent
1967         jal     set_fd_d                        # save result
1968         beq     t8, zero, done                  # check for exact result
1969         or      a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
1970         or      a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
1971         and     v0, a1, FPC_ENABLE_INEXACT
1972         bne     v0, zero, fpe_trap
1973         ctc1    a1, FPC_CSR             # save exceptions
1974         b       done
1975
1976 /*
1977  * Signal an invalid operation if the trap is enabled; otherwise,
1978  * the result is a quiet NAN.
1979  */
1980 invalid_s:                                      # trap invalid operation
1981         or      a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
1982         and     v0, a1, FPC_ENABLE_INVALID
1983         bne     v0, zero, fpe_trap
1984         ctc1    a1, FPC_CSR             # save exceptions
1985         move    t0, zero                        # result is a quiet NAN
1986         li      t1, SEXP_INF
1987         li      t2, SQUIET_NAN
1988         jal     set_fd_s                        # save result (in t0,t1,t2)
1989         b       done
1990
1991 /*
1992  * Signal an invalid operation if the trap is enabled; otherwise,
1993  * the result is a quiet NAN.
1994  */
1995 invalid_d:                                      # trap invalid operation
1996         or      a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
1997         and     v0, a1, FPC_ENABLE_INVALID
1998         bne     v0, zero, fpe_trap
1999         ctc1    a1, FPC_CSR             # save exceptions
2000         move    t0, zero                        # result is a quiet NAN
2001         li      t1, DEXP_INF
2002         dli     t2, DQUIET_NAN
2003         jal     set_fd_d                        # save result (in t0,t1,t2)
2004         b       done
2005
2006 /*
2007  * Signal an invalid operation if the trap is enabled; otherwise,
2008  * the result is INT_MAX or INT_MIN.
2009  */
2010 invalid_w:                                      # trap invalid operation
2011         or      a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
2012         and     v0, a1, FPC_ENABLE_INVALID
2013         bne     v0, zero, fpe_trap
2014         ctc1    a1, FPC_CSR                     # save exceptions
2015         bne     t0, zero, 1f
2016         li      t2, INT_MAX                     # result is INT_MAX
2017         b       result_fs_w
2018 1:
2019         li      t2, INT_MIN                     # result is INT_MIN
2020         b       result_fs_w
2021
2022 /*
2023  * Signal an invalid operation if the trap is enabled; otherwise,
2024  * the result is LONG_MAX or LONG_MIN.
2025  */
2026 invalid_l:                                      # trap invalid operation
2027         or      a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
2028         and     v0, a1, FPC_ENABLE_INVALID
2029         bne     v0, zero, fpe_trap
2030         ctc1    a1, FPC_CSR                     # save exceptions
2031         bne     t0, zero, 1f
2032         dli     t2, LONG_MAX                    # result is INT_MAX
2033         b       result_fs_l
2034 1:
2035         dli     t2, LONG_MIN                    # result is INT_MIN
2036         b       result_fs_l
2037
2038 /*
2039  * Trap if the hardware should have handled this case.
2040  */
2041 fpe_trap:
2042         move    a2, a1                          # code = FP CSR
2043         ctc1    a1, FPC_CSR                     # save exceptions
2044         li      v0, 1
2045         b       done_err
2046
2047 /*
2048  * Send an illegal instruction signal to the current process.
2049  */
2050 ill:
2051         ctc1    a1, FPC_CSR                     # save exceptions
2052         move    a2, a0                          # code = FP instruction
2053         li      v0, 1
2054         b       done_err
2055
2056 result_ft_s:
2057         move    t0, ta0                         # result is FT
2058         move    t1, ta1
2059         move    t2, ta2
2060 result_fs_s:                                    # result is FS
2061         jal     set_fd_s                        # save result (in t0,t1,t2)
2062         b       done
2063
2064 result_fs_w:
2065         jal     set_fd_word                     # save result (in t2)
2066         b       done
2067
2068 result_fs_l:
2069         move    t0, t2
2070         jal     set_fd_dword                    # save result (in t0)
2071         b       done
2072
2073 result_ft_d:
2074         move    t0, ta0                         # result is FT
2075         move    t1, ta1
2076         move    t2, ta2
2077 result_fs_d:                                    # result is FS
2078         jal     set_fd_d                        # save result (in t0,t1,t2)
2079
2080 done:
2081         li      v0, 0
2082 done_err:
2083         PTR_L   ra, CF_RA_OFFS(sp)
2084         PTR_ADD sp, sp, FRAMESZ(CF_SZ)
2085         j       ra
2086 END(MipsEmulateFP)
2087
2088 /*----------------------------------------------------------------------------
2089  * get_fs_int --
2090  *
2091  *      Read (integer) the FS register (bits 15-11).
2092  *      This is an internal routine used by MipsEmulateFP only.
2093  *
2094  * Results:
2095  *      t0      contains the sign
2096  *      t2      contains the fraction
2097  *
2098  *----------------------------------------------------------------------------
2099  */
2100 #define GET_FS_INT(n) \
2101         .rdata;                         \
2102         .dword  get_fs_int_ ## n;       \
2103         .text;                          \
2104 get_fs_int_ ## n:                       \
2105         mfc1    t2, $ ## n;             \
2106         b       get_fs_int_done
2107
2108 LEAF(get_fs_int, 0)
2109         srl     a3, a0, 11 - 3                  # get FS field
2110         and     a3, a3, 0x1f << 3               # mask FS field
2111         ld      a3, get_fs_int_tbl(a3)          # switch on register number
2112         j       a3
2113
2114         .rdata
2115 get_fs_int_tbl:
2116         .text
2117
2118         GET_FS_INT(f0)
2119         GET_FS_INT(f1)
2120         GET_FS_INT(f2)
2121         GET_FS_INT(f3)
2122         GET_FS_INT(f4)
2123         GET_FS_INT(f5)
2124         GET_FS_INT(f6)
2125         GET_FS_INT(f7)
2126         GET_FS_INT(f8)
2127         GET_FS_INT(f9)
2128         GET_FS_INT(f10)
2129         GET_FS_INT(f11)
2130         GET_FS_INT(f12)
2131         GET_FS_INT(f13)
2132         GET_FS_INT(f14)
2133         GET_FS_INT(f15)
2134         GET_FS_INT(f16)
2135         GET_FS_INT(f17)
2136         GET_FS_INT(f18)
2137         GET_FS_INT(f19)
2138         GET_FS_INT(f20)
2139         GET_FS_INT(f21)
2140         GET_FS_INT(f22)
2141         GET_FS_INT(f23)
2142         GET_FS_INT(f24)
2143         GET_FS_INT(f25)
2144         GET_FS_INT(f26)
2145         GET_FS_INT(f27)
2146         GET_FS_INT(f28)
2147         GET_FS_INT(f29)
2148         GET_FS_INT(f30)
2149         GET_FS_INT(f31)
2150
2151 get_fs_int_done:
2152         srl     t0, t2, 31              # init the sign bit
2153         bge     t2, zero, 1f
2154         negu    t2
2155         dsll    t2, 33
2156         dsrl    t2, 33
2157 1:
2158         j       ra
2159 END(get_fs_int)
2160
2161 /*----------------------------------------------------------------------------
2162  * get_fs_long --
2163  *
2164  *      Read (long integer) the FS register (bits 15-11).
2165  *      This is an internal routine used by MipsEmulateFP only.
2166  *
2167  * Results:
2168  *      t0      contains the sign
2169  *      t2      contains the fraction
2170  *
2171  *----------------------------------------------------------------------------
2172  */
2173 #define GET_FS_LONG(n) \
2174         .rdata;                         \
2175         .dword  get_fs_long_ ## n;      \
2176         .text;                          \
2177 get_fs_long_ ## n:                      \
2178         dmfc1   t2, $ ## n;             \
2179         b       get_fs_long_done
2180
2181 LEAF(get_fs_long, 0)
2182         srl     a3, a0, 11 - 3                  # get FS field
2183         and     a3, a3, 0x1f << 3               # mask FS field
2184         ld      a3, get_fs_long_tbl(a3)         # switch on register number
2185         j       a3
2186
2187         .rdata
2188 get_fs_long_tbl:
2189         .text
2190
2191         GET_FS_LONG(f0)
2192         GET_FS_LONG(f1)
2193         GET_FS_LONG(f2)
2194         GET_FS_LONG(f3)
2195         GET_FS_LONG(f4)
2196         GET_FS_LONG(f5)
2197         GET_FS_LONG(f6)
2198         GET_FS_LONG(f7)
2199         GET_FS_LONG(f8)
2200         GET_FS_LONG(f9)
2201         GET_FS_LONG(f10)
2202         GET_FS_LONG(f11)
2203         GET_FS_LONG(f12)
2204         GET_FS_LONG(f13)
2205         GET_FS_LONG(f14)
2206         GET_FS_LONG(f15)
2207         GET_FS_LONG(f16)
2208         GET_FS_LONG(f17)
2209         GET_FS_LONG(f18)
2210         GET_FS_LONG(f19)
2211         GET_FS_LONG(f20)
2212         GET_FS_LONG(f21)
2213         GET_FS_LONG(f22)
2214         GET_FS_LONG(f23)
2215         GET_FS_LONG(f24)
2216         GET_FS_LONG(f25)
2217         GET_FS_LONG(f26)
2218         GET_FS_LONG(f27)
2219         GET_FS_LONG(f28)
2220         GET_FS_LONG(f29)
2221         GET_FS_LONG(f30)
2222         GET_FS_LONG(f31)
2223
2224 get_fs_long_done:
2225         dsrl    t0, t2, 63              # init the sign bit
2226         bge     t2, zero, 1f
2227         dnegu   t2
2228 1:
2229         j       ra
2230 END(get_fs_long)
2231
2232 /*----------------------------------------------------------------------------
2233  * get_ft_fs_s --
2234  *
2235  *      Read (single precision) the FT register (bits 20-16) and
2236  *      the FS register (bits 15-11) and break up into fields.
2237  *      This is an internal routine used by MipsEmulateFP only.
2238  *
2239  * Results:
2240  *      t0      contains the FS sign
2241  *      t1      contains the FS (biased) exponent
2242  *      t2      contains the FS fraction
2243  *      ta0     contains the FT sign
2244  *      ta1     contains the FT (biased) exponent
2245  *      ta2     contains the FT fraction
2246  *
2247  *----------------------------------------------------------------------------
2248  */
2249 #define GET_FT_S(n) \
2250         .rdata;                         \
2251         .dword  get_ft_s_ ## n;         \
2252         .text;                          \
2253 get_ft_s_ ## n:                         \
2254         mfc1    ta0, $ ## n;            \
2255         b       get_ft_s_done
2256
2257 LEAF(get_ft_fs_s, 0)
2258         srl     a3, a0, 16 - 3                  # get FT field
2259         and     a3, a3, 0x1f << 3               # mask FT field
2260         ld      a3, get_ft_s_tbl(a3)            # switch on register number
2261         j       a3
2262
2263         .rdata
2264 get_ft_s_tbl:
2265         .text
2266
2267         GET_FT_S(f0)
2268         GET_FT_S(f1)
2269         GET_FT_S(f2)
2270         GET_FT_S(f3)
2271         GET_FT_S(f4)
2272         GET_FT_S(f5)
2273         GET_FT_S(f6)
2274         GET_FT_S(f7)
2275         GET_FT_S(f8)
2276         GET_FT_S(f9)
2277         GET_FT_S(f10)
2278         GET_FT_S(f11)
2279         GET_FT_S(f12)
2280         GET_FT_S(f13)
2281         GET_FT_S(f14)
2282         GET_FT_S(f15)
2283         GET_FT_S(f16)
2284         GET_FT_S(f17)
2285         GET_FT_S(f18)
2286         GET_FT_S(f19)
2287         GET_FT_S(f20)
2288         GET_FT_S(f21)
2289         GET_FT_S(f22)
2290         GET_FT_S(f23)
2291         GET_FT_S(f24)
2292         GET_FT_S(f25)
2293         GET_FT_S(f26)
2294         GET_FT_S(f27)
2295         GET_FT_S(f28)
2296         GET_FT_S(f29)
2297         GET_FT_S(f30)
2298         GET_FT_S(f31)
2299
2300 get_ft_s_done:
2301         srl     ta1, ta0, SFRAC_BITS            # get exponent
2302         and     ta1, ta1, 0xFF
2303         and     ta2, ta0, 0x7FFFFF              # get fraction
2304         srl     ta0, ta0, 31                    # get sign
2305         bne     ta1, SEXP_INF, 1f               # is it a signaling NAN?
2306         and     v0, ta2, SSIGNAL_NAN
2307         bne     v0, zero, invalid_s
2308 1:
2309         /* fall through to get FS */
2310
2311 /*----------------------------------------------------------------------------
2312  * get_fs_s --
2313  *
2314  *      Read (single precision) the FS register (bits 15-11) and
2315  *      break up into fields.
2316  *      This is an internal routine used by MipsEmulateFP only.
2317  *
2318  * Results:
2319  *      t0      contains the sign
2320  *      t1      contains the (biased) exponent
2321  *      t2      contains the fraction
2322  *
2323  *----------------------------------------------------------------------------
2324  */
2325 #define GET_FS_S(n) \
2326         .rdata;                         \
2327         .dword  get_fs_s_ ## n;         \
2328         .text;                          \
2329 get_fs_s_ ## n:                         \
2330         mfc1    t0, $ ## n;             \
2331         b       get_fs_s_done
2332
2333 ALEAF(get_fs_s)
2334         srl     a3, a0, 11 - 3                  # get FS field
2335         and     a3, a3, 0x1f << 3               # mask FS field
2336         ld      a3, get_fs_s_tbl(a3)            # switch on register number
2337         j       a3
2338
2339         .rdata
2340 get_fs_s_tbl:
2341         .text
2342
2343         GET_FS_S(f0)
2344         GET_FS_S(f1)
2345         GET_FS_S(f2)
2346         GET_FS_S(f3)
2347         GET_FS_S(f4)
2348         GET_FS_S(f5)
2349         GET_FS_S(f6)
2350         GET_FS_S(f7)
2351         GET_FS_S(f8)
2352         GET_FS_S(f9)
2353         GET_FS_S(f10)
2354         GET_FS_S(f11)
2355         GET_FS_S(f12)
2356         GET_FS_S(f13)
2357         GET_FS_S(f14)
2358         GET_FS_S(f15)
2359         GET_FS_S(f16)
2360         GET_FS_S(f17)
2361         GET_FS_S(f18)
2362         GET_FS_S(f19)
2363         GET_FS_S(f20)
2364         GET_FS_S(f21)
2365         GET_FS_S(f22)
2366         GET_FS_S(f23)
2367         GET_FS_S(f24)
2368         GET_FS_S(f25)
2369         GET_FS_S(f26)
2370         GET_FS_S(f27)
2371         GET_FS_S(f28)
2372         GET_FS_S(f29)
2373         GET_FS_S(f30)
2374         GET_FS_S(f31)
2375
2376 get_fs_s_done:
2377         srl     t1, t0, SFRAC_BITS              # get exponent
2378         and     t1, t1, 0xFF
2379         and     t2, t0, 0x7FFFFF                # get fraction
2380         srl     t0, t0, 31                      # get sign
2381         bne     t1, SEXP_INF, 1f                # is it a signaling NAN?
2382         and     v0, t2, SSIGNAL_NAN
2383         bne     v0, zero, invalid_s
2384 1:
2385         j       ra
2386 END(get_ft_fs_s)
2387
2388 /*----------------------------------------------------------------------------
2389  * get_ft_fs_d --
2390  *
2391  *      Read (double precision) the FT register (bits 20-16) and
2392  *      the FS register (bits 15-11) and break up into fields.
2393  *      This is an internal routine used by MipsEmulateFP only.
2394  *
2395  * Results:
2396  *      t0      contains the FS sign
2397  *      t1      contains the FS (biased) exponent
2398  *      t2      contains the FS fraction
2399  *      ta0     contains the FT sign
2400  *      ta1     contains the FT (biased) exponent
2401  *      ta2     contains the FT fraction
2402  *
2403  *----------------------------------------------------------------------------
2404  */
2405 #define GET_FT_FS_D(n) \
2406         .rdata;                         \
2407         .dword  get_ft_fs_d_ ## n;      \
2408         .text;                          \
2409 get_ft_fs_d_ ## n:                      \
2410         dmfc1   ta2, $ ## n;            \
2411         b       get_ft_d_done
2412
2413 LEAF(get_ft_fs_d, 0)
2414         srl     a3, a0, 16 - 3                  # get FT field
2415         and     a3, a3, 0x1f << 3               # mask FT field
2416         ld      a3, get_ft_d_tbl(a3)            # switch on register number
2417         j       a3
2418
2419         .rdata
2420 get_ft_d_tbl:
2421         .text
2422
2423         GET_FT_FS_D(f0)
2424         GET_FT_FS_D(f1)
2425         GET_FT_FS_D(f2)
2426         GET_FT_FS_D(f3)
2427         GET_FT_FS_D(f4)
2428         GET_FT_FS_D(f5)
2429         GET_FT_FS_D(f6)
2430         GET_FT_FS_D(f7)
2431         GET_FT_FS_D(f8)
2432         GET_FT_FS_D(f9)
2433         GET_FT_FS_D(f10)
2434         GET_FT_FS_D(f11)
2435         GET_FT_FS_D(f12)
2436         GET_FT_FS_D(f13)
2437         GET_FT_FS_D(f14)
2438         GET_FT_FS_D(f15)
2439         GET_FT_FS_D(f16)
2440         GET_FT_FS_D(f17)
2441         GET_FT_FS_D(f18)
2442         GET_FT_FS_D(f19)
2443         GET_FT_FS_D(f20)
2444         GET_FT_FS_D(f21)
2445         GET_FT_FS_D(f22)
2446         GET_FT_FS_D(f23)
2447         GET_FT_FS_D(f24)
2448         GET_FT_FS_D(f25)
2449         GET_FT_FS_D(f26)
2450         GET_FT_FS_D(f27)
2451         GET_FT_FS_D(f28)
2452         GET_FT_FS_D(f29)
2453         GET_FT_FS_D(f30)
2454         GET_FT_FS_D(f31)
2455
2456 get_ft_d_done:
2457         dsrl    ta0, ta2, 63                    # get sign
2458         dsrl    ta1, ta2, DFRAC_BITS            # get exponent
2459         and     ta1, ta1, 0x7FF
2460         dsll    ta2, 12
2461         dsrl    ta2, 12                         # get fraction
2462         bne     ta1, DEXP_INF, 1f               # is it a signaling NAN?
2463         and     v0, ta2, DSIGNAL_NAN
2464         bne     v0, zero, invalid_d
2465 1:
2466         /* fall through to get FS */
2467
2468 /*----------------------------------------------------------------------------
2469  * get_fs_d --
2470  *
2471  *      Read (double precision) the FS register (bits 15-11) and
2472  *      break up into fields.
2473  *      This is an internal routine used by MipsEmulateFP only.
2474  *
2475  * Results:
2476  *      t0      contains the sign
2477  *      t1      contains the (biased) exponent
2478  *      t2      contains the fraction
2479  *
2480  *----------------------------------------------------------------------------
2481  */
2482 #define GET_FS_D(n) \
2483         .rdata;                         \
2484         .dword  get_fs_d_ ## n;         \
2485         .text;                          \
2486 get_fs_d_ ## n:                         \
2487         dmfc1   t2, $ ## n;             \
2488         b       get_fs_d_done
2489
2490 ALEAF(get_fs_d)
2491         srl     a3, a0, 11 - 3                  # get FS field
2492         and     a3, a3, 0x1f << 3               # mask FS field
2493         ld      a3, get_fs_d_tbl(a3)            # switch on register number
2494         j       a3
2495
2496         .rdata
2497 get_fs_d_tbl:
2498         .text
2499
2500         GET_FS_D(f0)
2501         GET_FS_D(f1)
2502         GET_FS_D(f2)
2503         GET_FS_D(f3)
2504         GET_FS_D(f4)
2505         GET_FS_D(f5)
2506         GET_FS_D(f6)
2507         GET_FS_D(f7)
2508         GET_FS_D(f8)
2509         GET_FS_D(f9)
2510         GET_FS_D(f10)
2511         GET_FS_D(f11)
2512         GET_FS_D(f12)
2513         GET_FS_D(f13)
2514         GET_FS_D(f14)
2515         GET_FS_D(f15)
2516         GET_FS_D(f16)
2517         GET_FS_D(f17)
2518         GET_FS_D(f18)
2519         GET_FS_D(f19)
2520         GET_FS_D(f20)
2521         GET_FS_D(f21)
2522         GET_FS_D(f22)
2523         GET_FS_D(f23)
2524         GET_FS_D(f24)
2525         GET_FS_D(f25)
2526         GET_FS_D(f26)
2527         GET_FS_D(f27)
2528         GET_FS_D(f28)
2529         GET_FS_D(f29)
2530         GET_FS_D(f30)
2531         GET_FS_D(f31)
2532
2533 get_fs_d_done:
2534         dsrl    t0, t2, 63                      # get sign
2535         dsrl    t1, t2, DFRAC_BITS              # get exponent
2536         and     t1, t1, 0x7FF
2537         dsll    t2, 12
2538         dsrl    t2, 12                          # get fraction
2539         bne     t1, DEXP_INF, 1f                # is it a signaling NAN?
2540         and     v0, t2, DSIGNAL_NAN
2541         bne     v0, zero, invalid_d
2542 1:
2543         j       ra
2544 END(get_ft_fs_d)
2545
2546 /*----------------------------------------------------------------------------
2547  * get_cmp_s --
2548  *
2549  *      Read (single precision) the FS register (bits 15-11) and
2550  *      the FT register (bits 20-16) and break up into fields.
2551  *      This is an internal routine used by MipsEmulateFP only.
2552  *
2553  * Results:
2554  *      t0      contains the sign
2555  *      t1      contains the (biased) exponent
2556  *      t2      contains the fraction
2557  *      ta0     contains the sign
2558  *      ta1     contains the (biased) exponent
2559  *      ta2     contains the fraction
2560  *
2561  *----------------------------------------------------------------------------
2562  */
2563 #define CMP_FS_S(n) \
2564         .rdata;                         \
2565         .dword  cmp_fs_s_ ## n;         \
2566         .text;                          \
2567 cmp_fs_s_ ## n:                         \
2568         mfc1    t0, $ ## n;             \
2569         b       cmp_fs_s_done
2570
2571 LEAF(get_cmp_s, 0)
2572         srl     a3, a0, 11 - 3                  # get FS field
2573         and     a3, a3, 0x1f << 3               # mask FS field
2574         ld      a3, cmp_fs_s_tbl(a3)            # switch on register number
2575         j       a3
2576
2577         .rdata
2578 cmp_fs_s_tbl:
2579         .text
2580
2581         CMP_FS_S(f0)
2582         CMP_FS_S(f1)
2583         CMP_FS_S(f2)
2584         CMP_FS_S(f3)
2585         CMP_FS_S(f4)
2586         CMP_FS_S(f5)
2587         CMP_FS_S(f6)
2588         CMP_FS_S(f7)
2589         CMP_FS_S(f8)
2590         CMP_FS_S(f9)
2591         CMP_FS_S(f10)
2592         CMP_FS_S(f11)
2593         CMP_FS_S(f12)
2594         CMP_FS_S(f13)
2595         CMP_FS_S(f14)
2596         CMP_FS_S(f15)
2597         CMP_FS_S(f16)
2598         CMP_FS_S(f17)
2599         CMP_FS_S(f18)
2600         CMP_FS_S(f19)
2601         CMP_FS_S(f20)
2602         CMP_FS_S(f21)
2603         CMP_FS_S(f22)
2604         CMP_FS_S(f23)
2605         CMP_FS_S(f24)
2606         CMP_FS_S(f25)
2607         CMP_FS_S(f26)
2608         CMP_FS_S(f27)
2609         CMP_FS_S(f28)
2610         CMP_FS_S(f29)
2611         CMP_FS_S(f30)
2612         CMP_FS_S(f31)
2613
2614 cmp_fs_s_done:
2615         srl     t1, t0, SFRAC_BITS              # get exponent
2616         and     t1, t1, 0xFF
2617         and     t2, t0, 0x7FFFFF                # get fraction
2618         srl     t0, t0, 31                      # get sign
2619
2620 #define CMP_FT_S(n) \
2621         .rdata;                         \
2622         .dword  cmp_ft_s_ ## n;         \
2623         .text;                          \
2624 cmp_ft_s_ ## n:                         \
2625         mfc1    ta0, $ ## n;            \
2626         b       cmp_ft_s_done
2627
2628         srl     a3, a0, 16 - 3                  # get FT field
2629         and     a3, a3, 0x1f << 3               # mask FT field
2630         ld      a3, cmp_ft_s_tbl(a3)            # switch on register number
2631         j       a3
2632
2633         .rdata
2634 cmp_ft_s_tbl:
2635         .text
2636
2637         CMP_FT_S(f0)
2638         CMP_FT_S(f1)
2639         CMP_FT_S(f2)
2640         CMP_FT_S(f3)
2641         CMP_FT_S(f4)
2642         CMP_FT_S(f5)
2643         CMP_FT_S(f6)
2644         CMP_FT_S(f7)
2645         CMP_FT_S(f8)
2646         CMP_FT_S(f9)
2647         CMP_FT_S(f10)
2648         CMP_FT_S(f11)
2649         CMP_FT_S(f12)
2650         CMP_FT_S(f13)
2651         CMP_FT_S(f14)
2652         CMP_FT_S(f15)
2653         CMP_FT_S(f16)
2654         CMP_FT_S(f17)
2655         CMP_FT_S(f18)
2656         CMP_FT_S(f19)
2657         CMP_FT_S(f20)
2658         CMP_FT_S(f21)
2659         CMP_FT_S(f22)
2660         CMP_FT_S(f23)
2661         CMP_FT_S(f24)
2662         CMP_FT_S(f25)
2663         CMP_FT_S(f26)
2664         CMP_FT_S(f27)
2665         CMP_FT_S(f28)
2666         CMP_FT_S(f29)
2667         CMP_FT_S(f30)
2668
2669 cmp_ft_s_done:
2670         srl     ta1, ta0, SFRAC_BITS            # get exponent
2671         and     ta1, ta1, 0xFF
2672         and     ta2, ta0, 0x7FFFFF              # get fraction
2673         srl     ta0, ta0, 31                    # get sign
2674         j       ra
2675 END(get_cmp_s)
2676
2677 /*----------------------------------------------------------------------------
2678  * get_cmp_d --
2679  *
2680  *      Read (double precision) the FS register (bits 15-11) and
2681  *      the FT register (bits 20-16) and break up into fields.
2682  *      This is an internal routine used by MipsEmulateFP only.
2683  *
2684  * Results:
2685  *      t0      contains the sign
2686  *      t1      contains the (biased) exponent
2687  *      t2      contains the fraction
2688  *      ta0     contains the sign
2689  *      ta1     contains the (biased) exponent
2690  *      ta2     contains the fraction
2691  *
2692  *----------------------------------------------------------------------------
2693  */
2694 #define CMP_FS_D(n) \
2695         .rdata;                         \
2696         .dword  cmp_fs_d_ ## n;         \
2697         .text;                          \
2698 cmp_fs_d_ ## n:                         \
2699         dmfc1   t2, $ ## n;             \
2700         b       cmp_fs_d_done
2701
2702 LEAF(get_cmp_d, 0)
2703         srl     a3, a0, 11 - 3                  # get FS field
2704         and     a3, a3, 0x1f << 3               # mask FS field
2705         ld      a3, cmp_fs_d_tbl(a3)            # switch on register number
2706         j       a3
2707
2708         .rdata
2709 cmp_fs_d_tbl:
2710         .text
2711
2712         CMP_FS_D(f0)
2713         CMP_FS_D(f1)
2714         CMP_FS_D(f2)
2715         CMP_FS_D(f3)
2716         CMP_FS_D(f4)
2717         CMP_FS_D(f5)
2718         CMP_FS_D(f6)
2719         CMP_FS_D(f7)
2720         CMP_FS_D(f8)
2721         CMP_FS_D(f9)
2722         CMP_FS_D(f10)
2723         CMP_FS_D(f11)
2724         CMP_FS_D(f12)
2725         CMP_FS_D(f13)
2726         CMP_FS_D(f14)
2727         CMP_FS_D(f15)
2728         CMP_FS_D(f16)
2729         CMP_FS_D(f17)
2730         CMP_FS_D(f18)
2731         CMP_FS_D(f19)
2732         CMP_FS_D(f20)
2733         CMP_FS_D(f21)
2734         CMP_FS_D(f22)
2735         CMP_FS_D(f23)
2736         CMP_FS_D(f24)
2737         CMP_FS_D(f25)
2738         CMP_FS_D(f26)
2739         CMP_FS_D(f27)
2740         CMP_FS_D(f28)
2741         CMP_FS_D(f29)
2742         CMP_FS_D(f30)
2743         CMP_FS_D(f31)
2744
2745 cmp_fs_d_done:
2746         dsrl    t0, t2, 63                      # get sign
2747         dsrl    t1, t2, DFRAC_BITS              # get exponent
2748         and     t1, t1, 0x7FF
2749         dsll    t2, 12
2750         dsrl    t2, 12                          # get fraction
2751
2752 #define CMP_FT_D(n) \
2753         .rdata;                         \
2754         .dword  cmp_ft_d_ ## n;         \
2755         .text;                          \
2756 cmp_ft_d_ ## n:                         \
2757         dmfc1   ta2, $ ## n;            \
2758         b       cmp_ft_d_done
2759
2760         srl     a3, a0, 16 - 3                  # get FT field
2761         and     a3, a3, 0x1f << 3               # mask FT field
2762         ld      a3, cmp_ft_d_tbl(a3)            # switch on register number
2763         j       a3
2764
2765         .rdata
2766 cmp_ft_d_tbl:
2767         .text
2768
2769         CMP_FT_D(f0)
2770         CMP_FT_D(f1)
2771         CMP_FT_D(f2)
2772         CMP_FT_D(f3)
2773         CMP_FT_D(f4)
2774         CMP_FT_D(f5)
2775         CMP_FT_D(f6)
2776         CMP_FT_D(f7)
2777         CMP_FT_D(f8)
2778         CMP_FT_D(f9)
2779         CMP_FT_D(f10)
2780         CMP_FT_D(f11)
2781         CMP_FT_D(f12)
2782         CMP_FT_D(f13)
2783         CMP_FT_D(f14)
2784         CMP_FT_D(f15)
2785         CMP_FT_D(f16)
2786         CMP_FT_D(f17)
2787         CMP_FT_D(f18)
2788         CMP_FT_D(f19)
2789         CMP_FT_D(f20)
2790         CMP_FT_D(f21)
2791         CMP_FT_D(f22)
2792         CMP_FT_D(f23)
2793         CMP_FT_D(f24)
2794         CMP_FT_D(f25)
2795         CMP_FT_D(f26)
2796         CMP_FT_D(f27)
2797         CMP_FT_D(f28)
2798         CMP_FT_D(f29)
2799         CMP_FT_D(f30)
2800         CMP_FT_D(f31)
2801
2802 cmp_ft_d_done:
2803         dsrl    ta0, ta2, 63                    # get sign
2804         dsrl    ta1, ta2, DFRAC_BITS            # get exponent
2805         and     ta1, ta1, 0x7FF
2806         dsll    ta2, 12
2807         dsrl    ta2, 12                         # get fraction
2808         j       ra
2809 END(get_cmp_d)
2810
2811 /*----------------------------------------------------------------------------
2812  * set_fd_s --
2813  *
2814  *      Write (single precision) the FD register (bits 10-6).
2815  *      This is an internal routine used by MipsEmulateFP only.
2816  *
2817  * Arguments:
2818  *      a0      contains the FP instruction
2819  *      t0      contains the sign
2820  *      t1      contains the (biased) exponent
2821  *      t2      contains the fraction
2822  *
2823  * set_fd_word --
2824  *
2825  *      Write (integer) the FD register (bits 10-6).
2826  *      This is an internal routine used by MipsEmulateFP only.
2827  *
2828  * Arguments:
2829  *      a0      contains the FP instruction
2830  *      t2      contains the integer
2831  *
2832  *----------------------------------------------------------------------------
2833  */
2834 #define SET_FD_S(n) \
2835         .rdata;                         \
2836         .dword  set_fd_s_ ## n;         \
2837         .text;                          \
2838 set_fd_s_ ## n:                         \
2839         mtc1    t2, $ ## n;             \
2840         j       ra
2841
2842 LEAF(set_fd_s, 0)
2843         sll     t0, t0, 31                      # position sign
2844         sll     t1, t1, SFRAC_BITS              # position exponent
2845         or      t2, t2, t0
2846         or      t2, t2, t1
2847 ALEAF(set_fd_word)
2848         srl     a3, a0, 6 - 3                   # get FD field
2849         and     a3, a3, 0x1f << 3               # mask FT field
2850         ld      a3, set_fd_s_tbl(a3)            # switch on register number
2851         j       a3
2852
2853         .rdata
2854 set_fd_s_tbl:
2855         .text
2856
2857         SET_FD_S(f0)
2858         SET_FD_S(f1)
2859         SET_FD_S(f2)
2860         SET_FD_S(f3)
2861         SET_FD_S(f4)
2862         SET_FD_S(f5)
2863         SET_FD_S(f6)
2864         SET_FD_S(f7)
2865         SET_FD_S(f8)
2866         SET_FD_S(f9)
2867         SET_FD_S(f10)
2868         SET_FD_S(f11)
2869         SET_FD_S(f12)
2870         SET_FD_S(f13)
2871         SET_FD_S(f14)
2872         SET_FD_S(f15)
2873         SET_FD_S(f16)
2874         SET_FD_S(f17)
2875         SET_FD_S(f18)
2876         SET_FD_S(f19)
2877         SET_FD_S(f20)
2878         SET_FD_S(f21)
2879         SET_FD_S(f22)
2880         SET_FD_S(f23)
2881         SET_FD_S(f24)
2882         SET_FD_S(f25)
2883         SET_FD_S(f26)
2884         SET_FD_S(f27)
2885         SET_FD_S(f28)
2886         SET_FD_S(f29)
2887         SET_FD_S(f30)
2888         SET_FD_S(f31)
2889
2890 END(set_fd_s)
2891
2892 /*----------------------------------------------------------------------------
2893  * set_fd_d --
2894  *
2895  *      Write (double precision) the FT register (bits 10-6).
2896  *      This is an internal routine used by MipsEmulateFP only.
2897  *
2898  * Arguments:
2899  *      a0      contains the FP instruction
2900  *      t0      contains the sign
2901  *      t1      contains the (biased) exponent
2902  *      t2      contains the fraction
2903  *
2904  *----------------------------------------------------------------------------
2905  */
2906 #define SET_FD_D(n) \
2907         .rdata;                         \
2908         .dword  set_fd_d_ ## n;         \
2909         .text;                          \
2910 set_fd_d_ ## n:                         \
2911         dmtc1   t0, $ ## n;             \
2912         j       ra
2913
2914 LEAF(set_fd_d, 0)
2915         dsll    t0, 63                          # set sign
2916         dsll    t1, t1, DFRAC_BITS              # set exponent
2917         or      t0, t0, t1
2918         or      t0, t0, t2                      # set fraction
2919 ALEAF(set_fd_dword)
2920         srl     a3, a0, 6 - 3                   # get FD field
2921         and     a3, a3, 0x1f << 3               # mask FD field
2922         ld      a3, set_fd_d_tbl(a3)            # switch on register number
2923         j       a3
2924
2925         .rdata
2926 set_fd_d_tbl:
2927         .text
2928
2929         SET_FD_D(f0)
2930         SET_FD_D(f1)
2931         SET_FD_D(f2)
2932         SET_FD_D(f3)
2933         SET_FD_D(f4)
2934         SET_FD_D(f5)
2935         SET_FD_D(f6)
2936         SET_FD_D(f7)
2937         SET_FD_D(f8)
2938         SET_FD_D(f9)
2939         SET_FD_D(f10)
2940         SET_FD_D(f11)
2941         SET_FD_D(f12)
2942         SET_FD_D(f13)
2943         SET_FD_D(f14)
2944         SET_FD_D(f15)
2945         SET_FD_D(f16)
2946         SET_FD_D(f17)
2947         SET_FD_D(f18)
2948         SET_FD_D(f19)
2949         SET_FD_D(f20)
2950         SET_FD_D(f21)
2951         SET_FD_D(f22)
2952         SET_FD_D(f23)
2953         SET_FD_D(f24)
2954         SET_FD_D(f25)
2955         SET_FD_D(f26)
2956         SET_FD_D(f27)
2957         SET_FD_D(f28)
2958         SET_FD_D(f29)
2959         SET_FD_D(f30)
2960         SET_FD_D(f31)
2961
2962 END(set_fd_d)
2963
2964 /*----------------------------------------------------------------------------
2965  * renorm_fs_s --
2966  *
2967  * Results:
2968  *      t1      unbiased exponent
2969  *      t2      normalized fraction
2970  *
2971  *----------------------------------------------------------------------------
2972  */
2973 LEAF(renorm_fs_s, 0)
2974 /*
2975  * Find out how many leading zero bits are in t2 and put in t9.
2976  */
2977         move    v0, t2
2978         move    t9, zero
2979         srl     v1, v0, 16
2980         bne     v1, zero, 1f
2981         addu    t9, 16
2982         sll     v0, 16
2983 1:
2984         srl     v1, v0, 24
2985         bne     v1, zero, 1f
2986         addu    t9, 8
2987         sll     v0, 8
2988 1:
2989         srl     v1, v0, 28
2990         bne     v1, zero, 1f
2991         addu    t9, 4
2992         sll     v0, 4
2993 1:
2994         srl     v1, v0, 30
2995         bne     v1, zero, 1f
2996         addu    t9, 2
2997         sll     v0, 2
2998 1:
2999         srl     v1, v0, 31
3000         bne     v1, zero, 1f
3001         addu    t9, 1
3002 /*
3003  * Now shift t2 the correct number of bits.
3004  */
3005 1:
3006         subu    t9, t9, SLEAD_ZEROS     # dont count normal leading zeros
3007         li      t1, SEXP_MIN
3008         subu    t1, t1, t9              # adjust exponent
3009         sll     t2, t2, t9
3010         j       ra
3011 END(renorm_fs_s)
3012
3013 /*----------------------------------------------------------------------------
3014  * renorm_fs_d --
3015  *
3016  * Results:
3017  *      t1      unbiased exponent
3018  *      t2      normalized fraction
3019  *
3020  *----------------------------------------------------------------------------
3021  */
3022 LEAF(renorm_fs_d, 0)
3023 /*
3024  * Find out how many leading zero bits are in t2 and put in t9.
3025  */
3026         move    v0, t2
3027         move    t9, zero
3028         dsrl    v1, v0, 32
3029         bne     v1, zero, 1f
3030         addu    t9, 32
3031         dsll    v0, 32
3032 1:
3033         dsrl    v1, v0, 16
3034         bne     v1, zero, 1f
3035         addu    t9, 16
3036         dsll    v0, 16
3037 1:
3038         dsrl    v1, v0, 24
3039         bne     v1, zero, 1f
3040         addu    t9, 8
3041         dsll    v0, 8
3042 1:
3043         dsrl    v1, v0, 28
3044         bne     v1, zero, 1f
3045         addu    t9, 4
3046         dsll    v0, 4
3047 1:
3048         dsrl    v1, v0, 30
3049         bne     v1, zero, 1f
3050         addu    t9, 2
3051         dsll    v0, 2
3052 1:
3053         dsrl    v1, v0, 31
3054         bne     v1, zero, 1f
3055         addu    t9, 1
3056 /*
3057  * Now shift t2 the correct number of bits.
3058  */
3059 1:
3060         subu    t9, t9, DLEAD_ZEROS     # dont count normal leading zeros
3061         li      t1, DEXP_MIN
3062         subu    t1, t9                  # adjust exponent
3063         dsll    t2, t9
3064         j       ra
3065 END(renorm_fs_d)
3066
3067 /*----------------------------------------------------------------------------
3068  * renorm_ft_s --
3069  *
3070  * Results:
3071  *      ta1     unbiased exponent
3072  *      ta2     normalized fraction
3073  *
3074  *----------------------------------------------------------------------------
3075  */
3076 LEAF(renorm_ft_s, 0)
3077 /*
3078  * Find out how many leading zero bits are in ta2 and put in t9.
3079  */
3080         move    v0, ta2
3081         move    t9, zero
3082         srl     v1, v0, 16
3083         bne     v1, zero, 1f
3084         addu    t9, 16
3085         sll     v0, 16
3086 1:
3087         srl     v1, v0, 24
3088         bne     v1, zero, 1f
3089         addu    t9, 8
3090         sll     v0, 8
3091 1:
3092         srl     v1, v0, 28
3093         bne     v1, zero, 1f
3094         addu    t9, 4
3095         sll     v0, 4
3096 1:
3097         srl     v1, v0, 30
3098         bne     v1, zero, 1f
3099         addu    t9, 2
3100         sll     v0, 2
3101 1:
3102         srl     v1, v0, 31
3103         bne     v1, zero, 1f
3104         addu    t9, 1
3105 /*
3106  * Now shift ta2 the correct number of bits.
3107  */
3108 1:
3109         subu    t9, t9, SLEAD_ZEROS     # dont count normal leading zeros
3110         li      ta1, SEXP_MIN
3111         subu    ta1, t9                 # adjust exponent
3112         sll     ta2, t9
3113         j       ra
3114 END(renorm_ft_s)
3115
3116 /*----------------------------------------------------------------------------
3117  * renorm_ft_d --
3118  *
3119  * Results:
3120  *      ta1     unbiased exponent
3121  *      ta2     normalized fraction
3122  *
3123  *----------------------------------------------------------------------------
3124  */
3125 LEAF(renorm_ft_d, 0)
3126 /*
3127  * Find out how many leading zero bits are in ta2 and put in t9.
3128  */
3129         move    v0, ta2
3130         move    t9, zero
3131         dsrl    v1, v0, 32
3132         bne     v1, zero, 1f
3133         addu    t9, 32
3134         dsll    v0, 32
3135 1:
3136         dsrl    v1, v0, 16
3137         bne     v1, zero, 1f
3138         addu    t9, 16
3139         dsll    v0, 16
3140 1:
3141         dsrl    v1, v0, 24
3142         bne     v1, zero, 1f
3143         addu    t9, 8
3144         dsll    v0, 8
3145 1:
3146         dsrl    v1, v0, 28
3147         bne     v1, zero, 1f
3148         addu    t9, 4
3149         dsll    v0, 4
3150 1:
3151         dsrl    v1, v0, 30
3152         bne     v1, zero, 1f
3153         addu    t9, 2
3154         dsll    v0, 2
3155 1:
3156         dsrl    v1, v0, 31
3157         bne     v1, zero, 1f
3158         addu    t9, 1
3159 /*
3160  * Now shift ta2 the correct number of bits.
3161  */
3162 1:
3163         subu    t9, t9, DLEAD_ZEROS     # dont count normal leading zeros
3164         li      ta1, DEXP_MIN
3165         subu    ta1, t9                 # adjust exponent
3166         dsll    ta2, t9
3167         j       ra
3168 END(renorm_ft_d)