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