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