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