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