1 /* 2 * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator 3 * 4 * MIPS floating point support 5 * Copyright (C) 1994-2000 Algorithmics Ltd. 6 * http://www.algor.co.uk 7 * 8 * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com 9 * Copyright (C) 2000 MIPS Technologies, Inc. 10 * 11 * This program is free software; you can distribute it and/or modify it 12 * under the terms of the GNU General Public License (Version 2) as 13 * published by the Free Software Foundation. 14 * 15 * This program is distributed in the hope it will be useful, but WITHOUT 16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 18 * for more details. 19 * 20 * You should have received a copy of the GNU General Public License along 21 * with this program; if not, write to the Free Software Foundation, Inc., 22 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 23 * 24 * A complete emulator for MIPS coprocessor 1 instructions. This is 25 * required for #float(switch) or #float(trap), where it catches all 26 * COP1 instructions via the "CoProcessor Unusable" exception. 27 * 28 * More surprisingly it is also required for #float(ieee), to help out 29 * the hardware fpu at the boundaries of the IEEE-754 representation 30 * (denormalised values, infinities, underflow, etc). It is made 31 * quite nasty because emulation of some non-COP1 instructions is 32 * required, e.g. in branch delay slots. 33 * 34 * Note if you know that you won't have an fpu, then you'll get much 35 * better performance by compiling with -msoft-float! 36 */ 37 #include <linux/sched.h> 38 39 #include <asm/inst.h> 40 #include <asm/bootinfo.h> 41 #include <asm/cpu.h> 42 #include <asm/cpu-features.h> 43 #include <asm/processor.h> 44 #include <asm/ptrace.h> 45 #include <asm/signal.h> 46 #include <asm/mipsregs.h> 47 #include <asm/fpu_emulator.h> 48 #include <asm/uaccess.h> 49 #include <asm/branch.h> 50 51 #include "ieee754.h" 52 #include "dsemul.h" 53 54 /* Strap kernel emulator for full MIPS IV emulation */ 55 56 #ifdef __mips 57 #undef __mips 58 #endif 59 #define __mips 4 60 61 /* Function which emulates a floating point instruction. */ 62 63 static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *, 64 mips_instruction); 65 66 #if __mips >= 4 && __mips != 32 67 static int fpux_emu(struct pt_regs *, 68 struct mips_fpu_soft_struct *, mips_instruction); 69 #endif 70 71 /* Further private data for which no space exists in mips_fpu_soft_struct */ 72 73 struct mips_fpu_emulator_private fpuemuprivate; 74 75 /* Control registers */ 76 77 #define FPCREG_RID 0 /* $0 = revision id */ 78 #define FPCREG_CSR 31 /* $31 = csr */ 79 80 /* Convert Mips rounding mode (0..3) to IEEE library modes. */ 81 static const unsigned char ieee_rm[4] = { 82 IEEE754_RN, IEEE754_RZ, IEEE754_RU, IEEE754_RD 83 }; 84 85 #if __mips >= 4 86 /* convert condition code register number to csr bit */ 87 static const unsigned int fpucondbit[8] = { 88 FPU_CSR_COND0, 89 FPU_CSR_COND1, 90 FPU_CSR_COND2, 91 FPU_CSR_COND3, 92 FPU_CSR_COND4, 93 FPU_CSR_COND5, 94 FPU_CSR_COND6, 95 FPU_CSR_COND7 96 }; 97 #endif 98 99 100 /* 101 * Redundant with logic already in kernel/branch.c, 102 * embedded in compute_return_epc. At some point, 103 * a single subroutine should be used across both 104 * modules. 105 */ 106 static int isBranchInstr(mips_instruction * i) 107 { 108 switch (MIPSInst_OPCODE(*i)) { 109 case spec_op: 110 switch (MIPSInst_FUNC(*i)) { 111 case jalr_op: 112 case jr_op: 113 return 1; 114 } 115 break; 116 117 case bcond_op: 118 switch (MIPSInst_RT(*i)) { 119 case bltz_op: 120 case bgez_op: 121 case bltzl_op: 122 case bgezl_op: 123 case bltzal_op: 124 case bgezal_op: 125 case bltzall_op: 126 case bgezall_op: 127 return 1; 128 } 129 break; 130 131 case j_op: 132 case jal_op: 133 case jalx_op: 134 case beq_op: 135 case bne_op: 136 case blez_op: 137 case bgtz_op: 138 case beql_op: 139 case bnel_op: 140 case blezl_op: 141 case bgtzl_op: 142 return 1; 143 144 case cop0_op: 145 case cop1_op: 146 case cop2_op: 147 case cop1x_op: 148 if (MIPSInst_RS(*i) == bc_op) 149 return 1; 150 break; 151 } 152 153 return 0; 154 } 155 156 /* 157 * In the Linux kernel, we support selection of FPR format on the 158 * basis of the Status.FR bit. This does imply that, if a full 32 159 * FPRs are desired, there needs to be a flip-flop that can be written 160 * to one at that bit position. In any case, O32 MIPS ABI uses 161 * only the even FPRs (Status.FR = 0). 162 */ 163 164 #define CP0_STATUS_FR_SUPPORT 165 166 #ifdef CP0_STATUS_FR_SUPPORT 167 #define FR_BIT ST0_FR 168 #else 169 #define FR_BIT 0 170 #endif 171 172 #define SIFROMREG(si,x) ((si) = \ 173 (xcp->cp0_status & FR_BIT) || !(x & 1) ? \ 174 (int)ctx->fpr[x] : \ 175 (int)(ctx->fpr[x & ~1] >> 32 )) 176 #define SITOREG(si,x) (ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)] = \ 177 (xcp->cp0_status & FR_BIT) || !(x & 1) ? \ 178 ctx->fpr[x & ~1] >> 32 << 32 | (u32)(si) : \ 179 ctx->fpr[x & ~1] << 32 >> 32 | (u64)(si) << 32) 180 181 #define DIFROMREG(di,x) ((di) = \ 182 ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)]) 183 #define DITOREG(di,x) (ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)] \ 184 = (di)) 185 186 #define SPFROMREG(sp,x) SIFROMREG((sp).bits,x) 187 #define SPTOREG(sp,x) SITOREG((sp).bits,x) 188 #define DPFROMREG(dp,x) DIFROMREG((dp).bits,x) 189 #define DPTOREG(dp,x) DITOREG((dp).bits,x) 190 191 /* 192 * Emulate the single floating point instruction pointed at by EPC. 193 * Two instructions if the instruction is in a branch delay slot. 194 */ 195 196 static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx) 197 { 198 mips_instruction ir; 199 vaddr_t emulpc, contpc; 200 unsigned int cond; 201 202 if (get_user(ir, (mips_instruction *) xcp->cp0_epc)) { 203 fpuemuprivate.stats.errors++; 204 return SIGBUS; 205 } 206 207 /* XXX NEC Vr54xx bug workaround */ 208 if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir)) 209 xcp->cp0_cause &= ~CAUSEF_BD; 210 211 if (xcp->cp0_cause & CAUSEF_BD) { 212 /* 213 * The instruction to be emulated is in a branch delay slot 214 * which means that we have to emulate the branch instruction 215 * BEFORE we do the cop1 instruction. 216 * 217 * This branch could be a COP1 branch, but in that case we 218 * would have had a trap for that instruction, and would not 219 * come through this route. 220 * 221 * Linux MIPS branch emulator operates on context, updating the 222 * cp0_epc. 223 */ 224 emulpc = REG_TO_VA(xcp->cp0_epc + 4); /* Snapshot emulation target */ 225 226 if (__compute_return_epc(xcp)) { 227 #ifdef CP1DBG 228 printk("failed to emulate branch at %p\n", 229 REG_TO_VA(xcp->cp0_epc)); 230 #endif 231 return SIGILL; 232 } 233 if (get_user(ir, (mips_instruction *) emulpc)) { 234 fpuemuprivate.stats.errors++; 235 return SIGBUS; 236 } 237 /* __compute_return_epc() will have updated cp0_epc */ 238 contpc = REG_TO_VA xcp->cp0_epc; 239 /* In order not to confuse ptrace() et al, tweak context */ 240 xcp->cp0_epc = VA_TO_REG emulpc - 4; 241 } 242 else { 243 emulpc = REG_TO_VA xcp->cp0_epc; 244 contpc = REG_TO_VA(xcp->cp0_epc + 4); 245 } 246 247 emul: 248 fpuemuprivate.stats.emulated++; 249 switch (MIPSInst_OPCODE(ir)) { 250 #ifndef SINGLE_ONLY_FPU 251 case ldc1_op:{ 252 u64 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] + 253 MIPSInst_SIMM(ir)); 254 u64 val; 255 256 fpuemuprivate.stats.loads++; 257 if (get_user(val, va)) { 258 fpuemuprivate.stats.errors++; 259 return SIGBUS; 260 } 261 DITOREG(val, MIPSInst_RT(ir)); 262 break; 263 } 264 265 case sdc1_op:{ 266 u64 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] + 267 MIPSInst_SIMM(ir)); 268 u64 val; 269 270 fpuemuprivate.stats.stores++; 271 DIFROMREG(val, MIPSInst_RT(ir)); 272 if (put_user(val, va)) { 273 fpuemuprivate.stats.errors++; 274 return SIGBUS; 275 } 276 break; 277 } 278 #endif 279 280 case lwc1_op:{ 281 u32 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] + 282 MIPSInst_SIMM(ir)); 283 u32 val; 284 285 fpuemuprivate.stats.loads++; 286 if (get_user(val, va)) { 287 fpuemuprivate.stats.errors++; 288 return SIGBUS; 289 } 290 #ifdef SINGLE_ONLY_FPU 291 if (MIPSInst_RT(ir) & 1) { 292 /* illegal register in single-float mode */ 293 return SIGILL; 294 } 295 #endif 296 SITOREG(val, MIPSInst_RT(ir)); 297 break; 298 } 299 300 case swc1_op:{ 301 u32 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] + 302 MIPSInst_SIMM(ir)); 303 u32 val; 304 305 fpuemuprivate.stats.stores++; 306 #ifdef SINGLE_ONLY_FPU 307 if (MIPSInst_RT(ir) & 1) { 308 /* illegal register in single-float mode */ 309 return SIGILL; 310 } 311 #endif 312 SIFROMREG(val, MIPSInst_RT(ir)); 313 if (put_user(val, va)) { 314 fpuemuprivate.stats.errors++; 315 return SIGBUS; 316 } 317 break; 318 } 319 320 case cop1_op: 321 switch (MIPSInst_RS(ir)) { 322 323 #if defined(__mips64) && !defined(SINGLE_ONLY_FPU) 324 case dmfc_op: 325 /* copregister fs -> gpr[rt] */ 326 if (MIPSInst_RT(ir) != 0) { 327 DIFROMREG(xcp->regs[MIPSInst_RT(ir)], 328 MIPSInst_RD(ir)); 329 } 330 break; 331 332 case dmtc_op: 333 /* copregister fs <- rt */ 334 DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir)); 335 break; 336 #endif 337 338 case mfc_op: 339 /* copregister rd -> gpr[rt] */ 340 #ifdef SINGLE_ONLY_FPU 341 if (MIPSInst_RD(ir) & 1) { 342 /* illegal register in single-float mode */ 343 return SIGILL; 344 } 345 #endif 346 if (MIPSInst_RT(ir) != 0) { 347 SIFROMREG(xcp->regs[MIPSInst_RT(ir)], 348 MIPSInst_RD(ir)); 349 } 350 break; 351 352 case mtc_op: 353 /* copregister rd <- rt */ 354 #ifdef SINGLE_ONLY_FPU 355 if (MIPSInst_RD(ir) & 1) { 356 /* illegal register in single-float mode */ 357 return SIGILL; 358 } 359 #endif 360 SITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir)); 361 break; 362 363 case cfc_op:{ 364 /* cop control register rd -> gpr[rt] */ 365 u32 value; 366 367 if (ir == CP1UNDEF) { 368 return do_dsemulret(xcp); 369 } 370 if (MIPSInst_RD(ir) == FPCREG_CSR) { 371 value = ctx->fcr31; 372 #ifdef CSRTRACE 373 printk("%p gpr[%d]<-csr=%08x\n", 374 REG_TO_VA(xcp->cp0_epc), 375 MIPSInst_RT(ir), value); 376 #endif 377 } 378 else if (MIPSInst_RD(ir) == FPCREG_RID) 379 value = 0; 380 else 381 value = 0; 382 if (MIPSInst_RT(ir)) 383 xcp->regs[MIPSInst_RT(ir)] = value; 384 break; 385 } 386 387 case ctc_op:{ 388 /* copregister rd <- rt */ 389 u32 value; 390 391 if (MIPSInst_RT(ir) == 0) 392 value = 0; 393 else 394 value = xcp->regs[MIPSInst_RT(ir)]; 395 396 /* we only have one writable control reg 397 */ 398 if (MIPSInst_RD(ir) == FPCREG_CSR) { 399 #ifdef CSRTRACE 400 printk("%p gpr[%d]->csr=%08x\n", 401 REG_TO_VA(xcp->cp0_epc), 402 MIPSInst_RT(ir), value); 403 #endif 404 ctx->fcr31 = value; 405 /* copy new rounding mode and 406 flush bit to ieee library state! */ 407 ieee754_csr.nod = (ctx->fcr31 & 0x1000000) != 0; 408 ieee754_csr.rm = ieee_rm[value & 0x3]; 409 } 410 if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { 411 return SIGFPE; 412 } 413 break; 414 } 415 416 case bc_op:{ 417 int likely = 0; 418 419 if (xcp->cp0_cause & CAUSEF_BD) 420 return SIGILL; 421 422 #if __mips >= 4 423 cond = ctx->fcr31 & fpucondbit[MIPSInst_RT(ir) >> 2]; 424 #else 425 cond = ctx->fcr31 & FPU_CSR_COND; 426 #endif 427 switch (MIPSInst_RT(ir) & 3) { 428 case bcfl_op: 429 likely = 1; 430 case bcf_op: 431 cond = !cond; 432 break; 433 case bctl_op: 434 likely = 1; 435 case bct_op: 436 break; 437 default: 438 /* thats an illegal instruction */ 439 return SIGILL; 440 } 441 442 xcp->cp0_cause |= CAUSEF_BD; 443 if (cond) { 444 /* branch taken: emulate dslot 445 * instruction 446 */ 447 xcp->cp0_epc += 4; 448 contpc = REG_TO_VA 449 (xcp->cp0_epc + 450 (MIPSInst_SIMM(ir) << 2)); 451 452 if (get_user(ir, (mips_instruction *) 453 REG_TO_VA xcp->cp0_epc)) { 454 fpuemuprivate.stats.errors++; 455 return SIGBUS; 456 } 457 458 switch (MIPSInst_OPCODE(ir)) { 459 case lwc1_op: 460 case swc1_op: 461 #if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU) 462 case ldc1_op: 463 case sdc1_op: 464 #endif 465 case cop1_op: 466 #if __mips >= 4 && __mips != 32 467 case cop1x_op: 468 #endif 469 /* its one of ours */ 470 goto emul; 471 #if __mips >= 4 472 case spec_op: 473 if (MIPSInst_FUNC(ir) == movc_op) 474 goto emul; 475 break; 476 #endif 477 } 478 479 /* 480 * Single step the non-cp1 481 * instruction in the dslot 482 */ 483 return mips_dsemul(xcp, ir, VA_TO_REG contpc); 484 } 485 else { 486 /* branch not taken */ 487 if (likely) { 488 /* 489 * branch likely nullifies 490 * dslot if not taken 491 */ 492 xcp->cp0_epc += 4; 493 contpc += 4; 494 /* 495 * else continue & execute 496 * dslot as normal insn 497 */ 498 } 499 } 500 break; 501 } 502 503 default: 504 if (!(MIPSInst_RS(ir) & 0x10)) 505 return SIGILL; 506 { 507 int sig; 508 509 /* a real fpu computation instruction */ 510 if ((sig = fpu_emu(xcp, ctx, ir))) 511 return sig; 512 } 513 } 514 break; 515 516 #if __mips >= 4 && __mips != 32 517 case cop1x_op:{ 518 int sig; 519 520 if ((sig = fpux_emu(xcp, ctx, ir))) 521 return sig; 522 break; 523 } 524 #endif 525 526 #if __mips >= 4 527 case spec_op: 528 if (MIPSInst_FUNC(ir) != movc_op) 529 return SIGILL; 530 cond = fpucondbit[MIPSInst_RT(ir) >> 2]; 531 if (((ctx->fcr31 & cond) != 0) == ((MIPSInst_RT(ir) & 1) != 0)) 532 xcp->regs[MIPSInst_RD(ir)] = 533 xcp->regs[MIPSInst_RS(ir)]; 534 break; 535 #endif 536 537 default: 538 return SIGILL; 539 } 540 541 /* we did it !! */ 542 xcp->cp0_epc = VA_TO_REG(contpc); 543 xcp->cp0_cause &= ~CAUSEF_BD; 544 return 0; 545 } 546 547 /* 548 * Conversion table from MIPS compare ops 48-63 549 * cond = ieee754dp_cmp(x,y,IEEE754_UN,sig); 550 */ 551 static const unsigned char cmptab[8] = { 552 0, /* cmp_0 (sig) cmp_sf */ 553 IEEE754_CUN, /* cmp_un (sig) cmp_ngle */ 554 IEEE754_CEQ, /* cmp_eq (sig) cmp_seq */ 555 IEEE754_CEQ | IEEE754_CUN, /* cmp_ueq (sig) cmp_ngl */ 556 IEEE754_CLT, /* cmp_olt (sig) cmp_lt */ 557 IEEE754_CLT | IEEE754_CUN, /* cmp_ult (sig) cmp_nge */ 558 IEEE754_CLT | IEEE754_CEQ, /* cmp_ole (sig) cmp_le */ 559 IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */ 560 }; 561 562 563 #if __mips >= 4 && __mips != 32 564 565 /* 566 * Additional MIPS4 instructions 567 */ 568 569 #define DEF3OP(name, p, f1, f2, f3) \ 570 static ieee754##p fpemu_##p##_##name (ieee754##p r, ieee754##p s, \ 571 ieee754##p t) \ 572 { \ 573 struct ieee754_csr ieee754_csr_save; \ 574 s = f1 (s, t); \ 575 ieee754_csr_save = ieee754_csr; \ 576 s = f2 (s, r); \ 577 ieee754_csr_save.cx |= ieee754_csr.cx; \ 578 ieee754_csr_save.sx |= ieee754_csr.sx; \ 579 s = f3 (s); \ 580 ieee754_csr.cx |= ieee754_csr_save.cx; \ 581 ieee754_csr.sx |= ieee754_csr_save.sx; \ 582 return s; \ 583 } 584 585 static ieee754dp fpemu_dp_recip(ieee754dp d) 586 { 587 return ieee754dp_div(ieee754dp_one(0), d); 588 } 589 590 static ieee754dp fpemu_dp_rsqrt(ieee754dp d) 591 { 592 return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d)); 593 } 594 595 static ieee754sp fpemu_sp_recip(ieee754sp s) 596 { 597 return ieee754sp_div(ieee754sp_one(0), s); 598 } 599 600 static ieee754sp fpemu_sp_rsqrt(ieee754sp s) 601 { 602 return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s)); 603 } 604 605 DEF3OP(madd, sp, ieee754sp_mul, ieee754sp_add,); 606 DEF3OP(msub, sp, ieee754sp_mul, ieee754sp_sub,); 607 DEF3OP(nmadd, sp, ieee754sp_mul, ieee754sp_add, ieee754sp_neg); 608 DEF3OP(nmsub, sp, ieee754sp_mul, ieee754sp_sub, ieee754sp_neg); 609 DEF3OP(madd, dp, ieee754dp_mul, ieee754dp_add,); 610 DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub,); 611 DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg); 612 DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg); 613 614 static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, 615 mips_instruction ir) 616 { 617 unsigned rcsr = 0; /* resulting csr */ 618 619 fpuemuprivate.stats.cp1xops++; 620 621 switch (MIPSInst_FMA_FFMT(ir)) { 622 case s_fmt:{ /* 0 */ 623 624 ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp); 625 ieee754sp fd, fr, fs, ft; 626 u32 *va; 627 u32 val; 628 629 switch (MIPSInst_FUNC(ir)) { 630 case lwxc1_op: 631 va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] + 632 xcp->regs[MIPSInst_FT(ir)]); 633 634 fpuemuprivate.stats.loads++; 635 if (get_user(val, va)) { 636 fpuemuprivate.stats.errors++; 637 return SIGBUS; 638 } 639 #ifdef SINGLE_ONLY_FPU 640 if (MIPSInst_FD(ir) & 1) { 641 /* illegal register in single-float 642 * mode 643 */ 644 return SIGILL; 645 } 646 #endif 647 SITOREG(val, MIPSInst_FD(ir)); 648 break; 649 650 case swxc1_op: 651 va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] + 652 xcp->regs[MIPSInst_FT(ir)]); 653 654 fpuemuprivate.stats.stores++; 655 #ifdef SINGLE_ONLY_FPU 656 if (MIPSInst_FS(ir) & 1) { 657 /* illegal register in single-float 658 * mode 659 */ 660 return SIGILL; 661 } 662 #endif 663 664 SIFROMREG(val, MIPSInst_FS(ir)); 665 if (put_user(val, va)) { 666 fpuemuprivate.stats.errors++; 667 return SIGBUS; 668 } 669 break; 670 671 case madd_s_op: 672 handler = fpemu_sp_madd; 673 goto scoptop; 674 case msub_s_op: 675 handler = fpemu_sp_msub; 676 goto scoptop; 677 case nmadd_s_op: 678 handler = fpemu_sp_nmadd; 679 goto scoptop; 680 case nmsub_s_op: 681 handler = fpemu_sp_nmsub; 682 goto scoptop; 683 684 scoptop: 685 SPFROMREG(fr, MIPSInst_FR(ir)); 686 SPFROMREG(fs, MIPSInst_FS(ir)); 687 SPFROMREG(ft, MIPSInst_FT(ir)); 688 fd = (*handler) (fr, fs, ft); 689 SPTOREG(fd, MIPSInst_FD(ir)); 690 691 copcsr: 692 if (ieee754_cxtest(IEEE754_INEXACT)) 693 rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; 694 if (ieee754_cxtest(IEEE754_UNDERFLOW)) 695 rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S; 696 if (ieee754_cxtest(IEEE754_OVERFLOW)) 697 rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; 698 if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) 699 rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S; 700 701 ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr; 702 if (ieee754_csr.nod) 703 ctx->fcr31 |= 0x1000000; 704 if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { 705 /*printk ("SIGFPE: fpu csr = %08x\n", 706 ctx->fcr31); */ 707 return SIGFPE; 708 } 709 710 break; 711 712 default: 713 return SIGILL; 714 } 715 break; 716 } 717 718 #ifndef SINGLE_ONLY_FPU 719 case d_fmt:{ /* 1 */ 720 ieee754dp(*handler) (ieee754dp, ieee754dp, ieee754dp); 721 ieee754dp fd, fr, fs, ft; 722 u64 *va; 723 u64 val; 724 725 switch (MIPSInst_FUNC(ir)) { 726 case ldxc1_op: 727 va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] + 728 xcp->regs[MIPSInst_FT(ir)]); 729 730 fpuemuprivate.stats.loads++; 731 if (get_user(val, va)) { 732 fpuemuprivate.stats.errors++; 733 return SIGBUS; 734 } 735 DITOREG(val, MIPSInst_FD(ir)); 736 break; 737 738 case sdxc1_op: 739 va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] + 740 xcp->regs[MIPSInst_FT(ir)]); 741 742 fpuemuprivate.stats.stores++; 743 DIFROMREG(val, MIPSInst_FS(ir)); 744 if (put_user(val, va)) { 745 fpuemuprivate.stats.errors++; 746 return SIGBUS; 747 } 748 break; 749 750 case madd_d_op: 751 handler = fpemu_dp_madd; 752 goto dcoptop; 753 case msub_d_op: 754 handler = fpemu_dp_msub; 755 goto dcoptop; 756 case nmadd_d_op: 757 handler = fpemu_dp_nmadd; 758 goto dcoptop; 759 case nmsub_d_op: 760 handler = fpemu_dp_nmsub; 761 goto dcoptop; 762 763 dcoptop: 764 DPFROMREG(fr, MIPSInst_FR(ir)); 765 DPFROMREG(fs, MIPSInst_FS(ir)); 766 DPFROMREG(ft, MIPSInst_FT(ir)); 767 fd = (*handler) (fr, fs, ft); 768 DPTOREG(fd, MIPSInst_FD(ir)); 769 goto copcsr; 770 771 default: 772 return SIGILL; 773 } 774 break; 775 } 776 #endif 777 778 case 0x7: /* 7 */ 779 if (MIPSInst_FUNC(ir) != pfetch_op) { 780 return SIGILL; 781 } 782 /* ignore prefx operation */ 783 break; 784 785 default: 786 return SIGILL; 787 } 788 789 return 0; 790 } 791 #endif 792 793 794 795 /* 796 * Emulate a single COP1 arithmetic instruction. 797 */ 798 static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, 799 mips_instruction ir) 800 { 801 int rfmt; /* resulting format */ 802 unsigned rcsr = 0; /* resulting csr */ 803 unsigned cond; 804 union { 805 ieee754dp d; 806 ieee754sp s; 807 int w; 808 #ifdef __mips64 809 s64 l; 810 #endif 811 } rv; /* resulting value */ 812 813 fpuemuprivate.stats.cp1ops++; 814 switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) { 815 case s_fmt:{ /* 0 */ 816 union { 817 ieee754sp(*b) (ieee754sp, ieee754sp); 818 ieee754sp(*u) (ieee754sp); 819 } handler; 820 821 switch (MIPSInst_FUNC(ir)) { 822 /* binary ops */ 823 case fadd_op: 824 handler.b = ieee754sp_add; 825 goto scopbop; 826 case fsub_op: 827 handler.b = ieee754sp_sub; 828 goto scopbop; 829 case fmul_op: 830 handler.b = ieee754sp_mul; 831 goto scopbop; 832 case fdiv_op: 833 handler.b = ieee754sp_div; 834 goto scopbop; 835 836 /* unary ops */ 837 #if __mips >= 2 || __mips64 838 case fsqrt_op: 839 handler.u = ieee754sp_sqrt; 840 goto scopuop; 841 #endif 842 #if __mips >= 4 && __mips != 32 843 case frsqrt_op: 844 handler.u = fpemu_sp_rsqrt; 845 goto scopuop; 846 case frecip_op: 847 handler.u = fpemu_sp_recip; 848 goto scopuop; 849 #endif 850 #if __mips >= 4 851 case fmovc_op: 852 cond = fpucondbit[MIPSInst_FT(ir) >> 2]; 853 if (((ctx->fcr31 & cond) != 0) != 854 ((MIPSInst_FT(ir) & 1) != 0)) 855 return 0; 856 SPFROMREG(rv.s, MIPSInst_FS(ir)); 857 break; 858 case fmovz_op: 859 if (xcp->regs[MIPSInst_FT(ir)] != 0) 860 return 0; 861 SPFROMREG(rv.s, MIPSInst_FS(ir)); 862 break; 863 case fmovn_op: 864 if (xcp->regs[MIPSInst_FT(ir)] == 0) 865 return 0; 866 SPFROMREG(rv.s, MIPSInst_FS(ir)); 867 break; 868 #endif 869 case fabs_op: 870 handler.u = ieee754sp_abs; 871 goto scopuop; 872 case fneg_op: 873 handler.u = ieee754sp_neg; 874 goto scopuop; 875 case fmov_op: 876 /* an easy one */ 877 SPFROMREG(rv.s, MIPSInst_FS(ir)); 878 goto copcsr; 879 880 /* binary op on handler */ 881 scopbop: 882 { 883 ieee754sp fs, ft; 884 885 SPFROMREG(fs, MIPSInst_FS(ir)); 886 SPFROMREG(ft, MIPSInst_FT(ir)); 887 888 rv.s = (*handler.b) (fs, ft); 889 goto copcsr; 890 } 891 scopuop: 892 { 893 ieee754sp fs; 894 895 SPFROMREG(fs, MIPSInst_FS(ir)); 896 rv.s = (*handler.u) (fs); 897 goto copcsr; 898 } 899 copcsr: 900 if (ieee754_cxtest(IEEE754_INEXACT)) 901 rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; 902 if (ieee754_cxtest(IEEE754_UNDERFLOW)) 903 rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S; 904 if (ieee754_cxtest(IEEE754_OVERFLOW)) 905 rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; 906 if (ieee754_cxtest(IEEE754_ZERO_DIVIDE)) 907 rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S; 908 if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) 909 rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S; 910 break; 911 912 /* unary conv ops */ 913 case fcvts_op: 914 return SIGILL; /* not defined */ 915 case fcvtd_op:{ 916 #ifdef SINGLE_ONLY_FPU 917 return SIGILL; /* not defined */ 918 #else 919 ieee754sp fs; 920 921 SPFROMREG(fs, MIPSInst_FS(ir)); 922 rv.d = ieee754dp_fsp(fs); 923 rfmt = d_fmt; 924 goto copcsr; 925 } 926 #endif 927 case fcvtw_op:{ 928 ieee754sp fs; 929 930 SPFROMREG(fs, MIPSInst_FS(ir)); 931 rv.w = ieee754sp_tint(fs); 932 rfmt = w_fmt; 933 goto copcsr; 934 } 935 936 #if __mips >= 2 || __mips64 937 case fround_op: 938 case ftrunc_op: 939 case fceil_op: 940 case ffloor_op:{ 941 unsigned int oldrm = ieee754_csr.rm; 942 ieee754sp fs; 943 944 SPFROMREG(fs, MIPSInst_FS(ir)); 945 ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; 946 rv.w = ieee754sp_tint(fs); 947 ieee754_csr.rm = oldrm; 948 rfmt = w_fmt; 949 goto copcsr; 950 } 951 #endif /* __mips >= 2 */ 952 953 #if defined(__mips64) && !defined(SINGLE_ONLY_FPU) 954 case fcvtl_op:{ 955 ieee754sp fs; 956 957 SPFROMREG(fs, MIPSInst_FS(ir)); 958 rv.l = ieee754sp_tlong(fs); 959 rfmt = l_fmt; 960 goto copcsr; 961 } 962 963 case froundl_op: 964 case ftruncl_op: 965 case fceill_op: 966 case ffloorl_op:{ 967 unsigned int oldrm = ieee754_csr.rm; 968 ieee754sp fs; 969 970 SPFROMREG(fs, MIPSInst_FS(ir)); 971 ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; 972 rv.l = ieee754sp_tlong(fs); 973 ieee754_csr.rm = oldrm; 974 rfmt = l_fmt; 975 goto copcsr; 976 } 977 #endif /* __mips64 && !fpu(single) */ 978 979 default: 980 if (MIPSInst_FUNC(ir) >= fcmp_op) { 981 unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; 982 ieee754sp fs, ft; 983 984 SPFROMREG(fs, MIPSInst_FS(ir)); 985 SPFROMREG(ft, MIPSInst_FT(ir)); 986 rv.w = ieee754sp_cmp(fs, ft, 987 cmptab[cmpop & 0x7], cmpop & 0x8); 988 rfmt = -1; 989 if ((cmpop & 0x8) && ieee754_cxtest 990 (IEEE754_INVALID_OPERATION)) 991 rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S; 992 else 993 goto copcsr; 994 995 } 996 else { 997 return SIGILL; 998 } 999 break; 1000 } 1001 break; 1002 } 1003 1004 #ifndef SINGLE_ONLY_FPU 1005 case d_fmt:{ 1006 union { 1007 ieee754dp(*b) (ieee754dp, ieee754dp); 1008 ieee754dp(*u) (ieee754dp); 1009 } handler; 1010 1011 switch (MIPSInst_FUNC(ir)) { 1012 /* binary ops */ 1013 case fadd_op: 1014 handler.b = ieee754dp_add; 1015 goto dcopbop; 1016 case fsub_op: 1017 handler.b = ieee754dp_sub; 1018 goto dcopbop; 1019 case fmul_op: 1020 handler.b = ieee754dp_mul; 1021 goto dcopbop; 1022 case fdiv_op: 1023 handler.b = ieee754dp_div; 1024 goto dcopbop; 1025 1026 /* unary ops */ 1027 #if __mips >= 2 || __mips64 1028 case fsqrt_op: 1029 handler.u = ieee754dp_sqrt; 1030 goto dcopuop; 1031 #endif 1032 #if __mips >= 4 && __mips != 32 1033 case frsqrt_op: 1034 handler.u = fpemu_dp_rsqrt; 1035 goto dcopuop; 1036 case frecip_op: 1037 handler.u = fpemu_dp_recip; 1038 goto dcopuop; 1039 #endif 1040 #if __mips >= 4 1041 case fmovc_op: 1042 cond = fpucondbit[MIPSInst_FT(ir) >> 2]; 1043 if (((ctx->fcr31 & cond) != 0) != 1044 ((MIPSInst_FT(ir) & 1) != 0)) 1045 return 0; 1046 DPFROMREG(rv.d, MIPSInst_FS(ir)); 1047 break; 1048 case fmovz_op: 1049 if (xcp->regs[MIPSInst_FT(ir)] != 0) 1050 return 0; 1051 DPFROMREG(rv.d, MIPSInst_FS(ir)); 1052 break; 1053 case fmovn_op: 1054 if (xcp->regs[MIPSInst_FT(ir)] == 0) 1055 return 0; 1056 DPFROMREG(rv.d, MIPSInst_FS(ir)); 1057 break; 1058 #endif 1059 case fabs_op: 1060 handler.u = ieee754dp_abs; 1061 goto dcopuop; 1062 1063 case fneg_op: 1064 handler.u = ieee754dp_neg; 1065 goto dcopuop; 1066 1067 case fmov_op: 1068 /* an easy one */ 1069 DPFROMREG(rv.d, MIPSInst_FS(ir)); 1070 goto copcsr; 1071 1072 /* binary op on handler */ 1073 dcopbop:{ 1074 ieee754dp fs, ft; 1075 1076 DPFROMREG(fs, MIPSInst_FS(ir)); 1077 DPFROMREG(ft, MIPSInst_FT(ir)); 1078 1079 rv.d = (*handler.b) (fs, ft); 1080 goto copcsr; 1081 } 1082 dcopuop:{ 1083 ieee754dp fs; 1084 1085 DPFROMREG(fs, MIPSInst_FS(ir)); 1086 rv.d = (*handler.u) (fs); 1087 goto copcsr; 1088 } 1089 1090 /* unary conv ops */ 1091 case fcvts_op:{ 1092 ieee754dp fs; 1093 1094 DPFROMREG(fs, MIPSInst_FS(ir)); 1095 rv.s = ieee754sp_fdp(fs); 1096 rfmt = s_fmt; 1097 goto copcsr; 1098 } 1099 case fcvtd_op: 1100 return SIGILL; /* not defined */ 1101 1102 case fcvtw_op:{ 1103 ieee754dp fs; 1104 1105 DPFROMREG(fs, MIPSInst_FS(ir)); 1106 rv.w = ieee754dp_tint(fs); /* wrong */ 1107 rfmt = w_fmt; 1108 goto copcsr; 1109 } 1110 1111 #if __mips >= 2 || __mips64 1112 case fround_op: 1113 case ftrunc_op: 1114 case fceil_op: 1115 case ffloor_op:{ 1116 unsigned int oldrm = ieee754_csr.rm; 1117 ieee754dp fs; 1118 1119 DPFROMREG(fs, MIPSInst_FS(ir)); 1120 ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; 1121 rv.w = ieee754dp_tint(fs); 1122 ieee754_csr.rm = oldrm; 1123 rfmt = w_fmt; 1124 goto copcsr; 1125 } 1126 #endif 1127 1128 #if defined(__mips64) && !defined(SINGLE_ONLY_FPU) 1129 case fcvtl_op:{ 1130 ieee754dp fs; 1131 1132 DPFROMREG(fs, MIPSInst_FS(ir)); 1133 rv.l = ieee754dp_tlong(fs); 1134 rfmt = l_fmt; 1135 goto copcsr; 1136 } 1137 1138 case froundl_op: 1139 case ftruncl_op: 1140 case fceill_op: 1141 case ffloorl_op:{ 1142 unsigned int oldrm = ieee754_csr.rm; 1143 ieee754dp fs; 1144 1145 DPFROMREG(fs, MIPSInst_FS(ir)); 1146 ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; 1147 rv.l = ieee754dp_tlong(fs); 1148 ieee754_csr.rm = oldrm; 1149 rfmt = l_fmt; 1150 goto copcsr; 1151 } 1152 #endif /* __mips >= 3 && !fpu(single) */ 1153 1154 default: 1155 if (MIPSInst_FUNC(ir) >= fcmp_op) { 1156 unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; 1157 ieee754dp fs, ft; 1158 1159 DPFROMREG(fs, MIPSInst_FS(ir)); 1160 DPFROMREG(ft, MIPSInst_FT(ir)); 1161 rv.w = ieee754dp_cmp(fs, ft, 1162 cmptab[cmpop & 0x7], cmpop & 0x8); 1163 rfmt = -1; 1164 if ((cmpop & 0x8) 1165 && 1166 ieee754_cxtest 1167 (IEEE754_INVALID_OPERATION)) 1168 rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S; 1169 else 1170 goto copcsr; 1171 1172 } 1173 else { 1174 return SIGILL; 1175 } 1176 break; 1177 } 1178 break; 1179 } 1180 #endif /* ifndef SINGLE_ONLY_FPU */ 1181 1182 case w_fmt:{ 1183 ieee754sp fs; 1184 1185 switch (MIPSInst_FUNC(ir)) { 1186 case fcvts_op: 1187 /* convert word to single precision real */ 1188 SPFROMREG(fs, MIPSInst_FS(ir)); 1189 rv.s = ieee754sp_fint(fs.bits); 1190 rfmt = s_fmt; 1191 goto copcsr; 1192 #ifndef SINGLE_ONLY_FPU 1193 case fcvtd_op: 1194 /* convert word to double precision real */ 1195 SPFROMREG(fs, MIPSInst_FS(ir)); 1196 rv.d = ieee754dp_fint(fs.bits); 1197 rfmt = d_fmt; 1198 goto copcsr; 1199 #endif 1200 default: 1201 return SIGILL; 1202 } 1203 break; 1204 } 1205 1206 #if defined(__mips64) && !defined(SINGLE_ONLY_FPU) 1207 case l_fmt:{ 1208 switch (MIPSInst_FUNC(ir)) { 1209 case fcvts_op: 1210 /* convert long to single precision real */ 1211 rv.s = ieee754sp_flong(ctx->fpr[MIPSInst_FS(ir)]); 1212 rfmt = s_fmt; 1213 goto copcsr; 1214 case fcvtd_op: 1215 /* convert long to double precision real */ 1216 rv.d = ieee754dp_flong(ctx->fpr[MIPSInst_FS(ir)]); 1217 rfmt = d_fmt; 1218 goto copcsr; 1219 default: 1220 return SIGILL; 1221 } 1222 break; 1223 } 1224 #endif 1225 1226 default: 1227 return SIGILL; 1228 } 1229 1230 /* 1231 * Update the fpu CSR register for this operation. 1232 * If an exception is required, generate a tidy SIGFPE exception, 1233 * without updating the result register. 1234 * Note: cause exception bits do not accumulate, they are rewritten 1235 * for each op; only the flag/sticky bits accumulate. 1236 */ 1237 ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr; 1238 if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { 1239 /*printk ("SIGFPE: fpu csr = %08x\n",ctx->fcr31); */ 1240 return SIGFPE; 1241 } 1242 1243 /* 1244 * Now we can safely write the result back to the register file. 1245 */ 1246 switch (rfmt) { 1247 case -1:{ 1248 #if __mips >= 4 1249 cond = fpucondbit[MIPSInst_FD(ir) >> 2]; 1250 #else 1251 cond = FPU_CSR_COND; 1252 #endif 1253 if (rv.w) 1254 ctx->fcr31 |= cond; 1255 else 1256 ctx->fcr31 &= ~cond; 1257 break; 1258 } 1259 #ifndef SINGLE_ONLY_FPU 1260 case d_fmt: 1261 DPTOREG(rv.d, MIPSInst_FD(ir)); 1262 break; 1263 #endif 1264 case s_fmt: 1265 SPTOREG(rv.s, MIPSInst_FD(ir)); 1266 break; 1267 case w_fmt: 1268 SITOREG(rv.w, MIPSInst_FD(ir)); 1269 break; 1270 #if defined(__mips64) && !defined(SINGLE_ONLY_FPU) 1271 case l_fmt: 1272 DITOREG(rv.l, MIPSInst_FD(ir)); 1273 break; 1274 #endif 1275 default: 1276 return SIGILL; 1277 } 1278 1279 return 0; 1280 } 1281 1282 int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp, 1283 struct mips_fpu_soft_struct *ctx) 1284 { 1285 gpreg_t oldepc, prevepc; 1286 mips_instruction insn; 1287 int sig = 0; 1288 1289 oldepc = xcp->cp0_epc; 1290 do { 1291 prevepc = xcp->cp0_epc; 1292 1293 if (get_user(insn, (mips_instruction *) xcp->cp0_epc)) { 1294 fpuemuprivate.stats.errors++; 1295 return SIGBUS; 1296 } 1297 if (insn == 0) 1298 xcp->cp0_epc += 4; /* skip nops */ 1299 else { 1300 /* Update ieee754_csr. Only relevant if we have a 1301 h/w FPU */ 1302 ieee754_csr.nod = (ctx->fcr31 & 0x1000000) != 0; 1303 ieee754_csr.rm = ieee_rm[ctx->fcr31 & 0x3]; 1304 ieee754_csr.cx = (ctx->fcr31 >> 12) & 0x1f; 1305 sig = cop1Emulate(xcp, ctx); 1306 } 1307 1308 if (cpu_has_fpu) 1309 break; 1310 if (sig) 1311 break; 1312 1313 cond_resched(); 1314 } while (xcp->cp0_epc > prevepc); 1315 1316 /* SIGILL indicates a non-fpu instruction */ 1317 if (sig == SIGILL && xcp->cp0_epc != oldepc) 1318 /* but if epc has advanced, then ignore it */ 1319 sig = 0; 1320 1321 return sig; 1322 } 1323