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