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