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