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