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