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/module.h> 39 #include <linux/debugfs.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 MIPS_FPU_EMU_INC_STATS(emulated); 263 switch (MIPSInst_OPCODE(ir)) { 264 case ldc1_op:{ 265 u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + 266 MIPSInst_SIMM(ir)); 267 u64 val; 268 269 MIPS_FPU_EMU_INC_STATS(loads); 270 if (get_user(val, va)) { 271 MIPS_FPU_EMU_INC_STATS(errors); 272 return SIGBUS; 273 } 274 DITOREG(val, MIPSInst_RT(ir)); 275 break; 276 } 277 278 case sdc1_op:{ 279 u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + 280 MIPSInst_SIMM(ir)); 281 u64 val; 282 283 MIPS_FPU_EMU_INC_STATS(stores); 284 DIFROMREG(val, MIPSInst_RT(ir)); 285 if (put_user(val, va)) { 286 MIPS_FPU_EMU_INC_STATS(errors); 287 return SIGBUS; 288 } 289 break; 290 } 291 292 case lwc1_op:{ 293 u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] + 294 MIPSInst_SIMM(ir)); 295 u32 val; 296 297 MIPS_FPU_EMU_INC_STATS(loads); 298 if (get_user(val, va)) { 299 MIPS_FPU_EMU_INC_STATS(errors); 300 return SIGBUS; 301 } 302 SITOREG(val, MIPSInst_RT(ir)); 303 break; 304 } 305 306 case swc1_op:{ 307 u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] + 308 MIPSInst_SIMM(ir)); 309 u32 val; 310 311 MIPS_FPU_EMU_INC_STATS(stores); 312 SIFROMREG(val, MIPSInst_RT(ir)); 313 if (put_user(val, va)) { 314 MIPS_FPU_EMU_INC_STATS(errors); 315 return SIGBUS; 316 } 317 break; 318 } 319 320 case cop1_op: 321 switch (MIPSInst_RS(ir)) { 322 323 #if defined(__mips64) 324 case dmfc_op: 325 /* copregister fs -> gpr[rt] */ 326 if (MIPSInst_RT(ir) != 0) { 327 DIFROMREG(xcp->regs[MIPSInst_RT(ir)], 328 MIPSInst_RD(ir)); 329 } 330 break; 331 332 case dmtc_op: 333 /* copregister fs <- rt */ 334 DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir)); 335 break; 336 #endif 337 338 case mfc_op: 339 /* copregister rd -> gpr[rt] */ 340 if (MIPSInst_RT(ir) != 0) { 341 SIFROMREG(xcp->regs[MIPSInst_RT(ir)], 342 MIPSInst_RD(ir)); 343 } 344 break; 345 346 case mtc_op: 347 /* copregister rd <- rt */ 348 SITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir)); 349 break; 350 351 case cfc_op:{ 352 /* cop control register rd -> gpr[rt] */ 353 u32 value; 354 355 if (MIPSInst_RD(ir) == FPCREG_CSR) { 356 value = ctx->fcr31; 357 value = (value & ~FPU_CSR_RM) | 358 mips_rm[modeindex(value)]; 359 #ifdef CSRTRACE 360 printk("%p gpr[%d]<-csr=%08x\n", 361 (void *) (xcp->cp0_epc), 362 MIPSInst_RT(ir), value); 363 #endif 364 } 365 else if (MIPSInst_RD(ir) == FPCREG_RID) 366 value = 0; 367 else 368 value = 0; 369 if (MIPSInst_RT(ir)) 370 xcp->regs[MIPSInst_RT(ir)] = value; 371 break; 372 } 373 374 case ctc_op:{ 375 /* copregister rd <- rt */ 376 u32 value; 377 378 if (MIPSInst_RT(ir) == 0) 379 value = 0; 380 else 381 value = xcp->regs[MIPSInst_RT(ir)]; 382 383 /* we only have one writable control reg 384 */ 385 if (MIPSInst_RD(ir) == FPCREG_CSR) { 386 #ifdef CSRTRACE 387 printk("%p gpr[%d]->csr=%08x\n", 388 (void *) (xcp->cp0_epc), 389 MIPSInst_RT(ir), value); 390 #endif 391 392 /* 393 * Don't write reserved bits, 394 * and convert to ieee library modes 395 */ 396 ctx->fcr31 = (value & 397 ~(FPU_CSR_RSVD | FPU_CSR_RM)) | 398 ieee_rm[modeindex(value)]; 399 } 400 if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { 401 return SIGFPE; 402 } 403 break; 404 } 405 406 case bc_op:{ 407 int likely = 0; 408 409 if (xcp->cp0_cause & CAUSEF_BD) 410 return SIGILL; 411 412 #if __mips >= 4 413 cond = ctx->fcr31 & fpucondbit[MIPSInst_RT(ir) >> 2]; 414 #else 415 cond = ctx->fcr31 & FPU_CSR_COND; 416 #endif 417 switch (MIPSInst_RT(ir) & 3) { 418 case bcfl_op: 419 likely = 1; 420 case bcf_op: 421 cond = !cond; 422 break; 423 case bctl_op: 424 likely = 1; 425 case bct_op: 426 break; 427 default: 428 /* thats an illegal instruction */ 429 return SIGILL; 430 } 431 432 xcp->cp0_cause |= CAUSEF_BD; 433 if (cond) { 434 /* branch taken: emulate dslot 435 * instruction 436 */ 437 xcp->cp0_epc += 4; 438 contpc = (xcp->cp0_epc + 439 (MIPSInst_SIMM(ir) << 2)); 440 441 if (get_user(ir, 442 (mips_instruction __user *) xcp->cp0_epc)) { 443 MIPS_FPU_EMU_INC_STATS(errors); 444 return SIGBUS; 445 } 446 447 switch (MIPSInst_OPCODE(ir)) { 448 case lwc1_op: 449 case swc1_op: 450 #if (__mips >= 2 || defined(__mips64)) 451 case ldc1_op: 452 case sdc1_op: 453 #endif 454 case cop1_op: 455 #if __mips >= 4 && __mips != 32 456 case cop1x_op: 457 #endif 458 /* its one of ours */ 459 goto emul; 460 #if __mips >= 4 461 case spec_op: 462 if (MIPSInst_FUNC(ir) == movc_op) 463 goto emul; 464 break; 465 #endif 466 } 467 468 /* 469 * Single step the non-cp1 470 * instruction in the dslot 471 */ 472 return mips_dsemul(xcp, ir, contpc); 473 } 474 else { 475 /* branch not taken */ 476 if (likely) { 477 /* 478 * branch likely nullifies 479 * dslot if not taken 480 */ 481 xcp->cp0_epc += 4; 482 contpc += 4; 483 /* 484 * else continue & execute 485 * dslot as normal insn 486 */ 487 } 488 } 489 break; 490 } 491 492 default: 493 if (!(MIPSInst_RS(ir) & 0x10)) 494 return SIGILL; 495 { 496 int sig; 497 498 /* a real fpu computation instruction */ 499 if ((sig = fpu_emu(xcp, ctx, ir))) 500 return sig; 501 } 502 } 503 break; 504 505 #if __mips >= 4 && __mips != 32 506 case cop1x_op:{ 507 int sig; 508 509 if ((sig = fpux_emu(xcp, ctx, ir))) 510 return sig; 511 break; 512 } 513 #endif 514 515 #if __mips >= 4 516 case spec_op: 517 if (MIPSInst_FUNC(ir) != movc_op) 518 return SIGILL; 519 cond = fpucondbit[MIPSInst_RT(ir) >> 2]; 520 if (((ctx->fcr31 & cond) != 0) == ((MIPSInst_RT(ir) & 1) != 0)) 521 xcp->regs[MIPSInst_RD(ir)] = 522 xcp->regs[MIPSInst_RS(ir)]; 523 break; 524 #endif 525 526 default: 527 return SIGILL; 528 } 529 530 /* we did it !! */ 531 xcp->cp0_epc = contpc; 532 xcp->cp0_cause &= ~CAUSEF_BD; 533 534 return 0; 535 } 536 537 /* 538 * Conversion table from MIPS compare ops 48-63 539 * cond = ieee754dp_cmp(x,y,IEEE754_UN,sig); 540 */ 541 static const unsigned char cmptab[8] = { 542 0, /* cmp_0 (sig) cmp_sf */ 543 IEEE754_CUN, /* cmp_un (sig) cmp_ngle */ 544 IEEE754_CEQ, /* cmp_eq (sig) cmp_seq */ 545 IEEE754_CEQ | IEEE754_CUN, /* cmp_ueq (sig) cmp_ngl */ 546 IEEE754_CLT, /* cmp_olt (sig) cmp_lt */ 547 IEEE754_CLT | IEEE754_CUN, /* cmp_ult (sig) cmp_nge */ 548 IEEE754_CLT | IEEE754_CEQ, /* cmp_ole (sig) cmp_le */ 549 IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */ 550 }; 551 552 553 #if __mips >= 4 && __mips != 32 554 555 /* 556 * Additional MIPS4 instructions 557 */ 558 559 #define DEF3OP(name, p, f1, f2, f3) \ 560 static ieee754##p fpemu_##p##_##name(ieee754##p r, ieee754##p s, \ 561 ieee754##p t) \ 562 { \ 563 struct _ieee754_csr ieee754_csr_save; \ 564 s = f1(s, t); \ 565 ieee754_csr_save = ieee754_csr; \ 566 s = f2(s, r); \ 567 ieee754_csr_save.cx |= ieee754_csr.cx; \ 568 ieee754_csr_save.sx |= ieee754_csr.sx; \ 569 s = f3(s); \ 570 ieee754_csr.cx |= ieee754_csr_save.cx; \ 571 ieee754_csr.sx |= ieee754_csr_save.sx; \ 572 return s; \ 573 } 574 575 static ieee754dp fpemu_dp_recip(ieee754dp d) 576 { 577 return ieee754dp_div(ieee754dp_one(0), d); 578 } 579 580 static ieee754dp fpemu_dp_rsqrt(ieee754dp d) 581 { 582 return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d)); 583 } 584 585 static ieee754sp fpemu_sp_recip(ieee754sp s) 586 { 587 return ieee754sp_div(ieee754sp_one(0), s); 588 } 589 590 static ieee754sp fpemu_sp_rsqrt(ieee754sp s) 591 { 592 return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s)); 593 } 594 595 DEF3OP(madd, sp, ieee754sp_mul, ieee754sp_add, ); 596 DEF3OP(msub, sp, ieee754sp_mul, ieee754sp_sub, ); 597 DEF3OP(nmadd, sp, ieee754sp_mul, ieee754sp_add, ieee754sp_neg); 598 DEF3OP(nmsub, sp, ieee754sp_mul, ieee754sp_sub, ieee754sp_neg); 599 DEF3OP(madd, dp, ieee754dp_mul, ieee754dp_add, ); 600 DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub, ); 601 DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg); 602 DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg); 603 604 static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, 605 mips_instruction ir) 606 { 607 unsigned rcsr = 0; /* resulting csr */ 608 609 MIPS_FPU_EMU_INC_STATS(cp1xops); 610 611 switch (MIPSInst_FMA_FFMT(ir)) { 612 case s_fmt:{ /* 0 */ 613 614 ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp); 615 ieee754sp fd, fr, fs, ft; 616 u32 __user *va; 617 u32 val; 618 619 switch (MIPSInst_FUNC(ir)) { 620 case lwxc1_op: 621 va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] + 622 xcp->regs[MIPSInst_FT(ir)]); 623 624 MIPS_FPU_EMU_INC_STATS(loads); 625 if (get_user(val, va)) { 626 MIPS_FPU_EMU_INC_STATS(errors); 627 return SIGBUS; 628 } 629 SITOREG(val, MIPSInst_FD(ir)); 630 break; 631 632 case swxc1_op: 633 va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] + 634 xcp->regs[MIPSInst_FT(ir)]); 635 636 MIPS_FPU_EMU_INC_STATS(stores); 637 638 SIFROMREG(val, MIPSInst_FS(ir)); 639 if (put_user(val, va)) { 640 MIPS_FPU_EMU_INC_STATS(errors); 641 return SIGBUS; 642 } 643 break; 644 645 case madd_s_op: 646 handler = fpemu_sp_madd; 647 goto scoptop; 648 case msub_s_op: 649 handler = fpemu_sp_msub; 650 goto scoptop; 651 case nmadd_s_op: 652 handler = fpemu_sp_nmadd; 653 goto scoptop; 654 case nmsub_s_op: 655 handler = fpemu_sp_nmsub; 656 goto scoptop; 657 658 scoptop: 659 SPFROMREG(fr, MIPSInst_FR(ir)); 660 SPFROMREG(fs, MIPSInst_FS(ir)); 661 SPFROMREG(ft, MIPSInst_FT(ir)); 662 fd = (*handler) (fr, fs, ft); 663 SPTOREG(fd, MIPSInst_FD(ir)); 664 665 copcsr: 666 if (ieee754_cxtest(IEEE754_INEXACT)) 667 rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; 668 if (ieee754_cxtest(IEEE754_UNDERFLOW)) 669 rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S; 670 if (ieee754_cxtest(IEEE754_OVERFLOW)) 671 rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; 672 if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) 673 rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S; 674 675 ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr; 676 if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { 677 /*printk ("SIGFPE: fpu csr = %08x\n", 678 ctx->fcr31); */ 679 return SIGFPE; 680 } 681 682 break; 683 684 default: 685 return SIGILL; 686 } 687 break; 688 } 689 690 case d_fmt:{ /* 1 */ 691 ieee754dp(*handler) (ieee754dp, ieee754dp, ieee754dp); 692 ieee754dp fd, fr, fs, ft; 693 u64 __user *va; 694 u64 val; 695 696 switch (MIPSInst_FUNC(ir)) { 697 case ldxc1_op: 698 va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] + 699 xcp->regs[MIPSInst_FT(ir)]); 700 701 MIPS_FPU_EMU_INC_STATS(loads); 702 if (get_user(val, va)) { 703 MIPS_FPU_EMU_INC_STATS(errors); 704 return SIGBUS; 705 } 706 DITOREG(val, MIPSInst_FD(ir)); 707 break; 708 709 case sdxc1_op: 710 va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] + 711 xcp->regs[MIPSInst_FT(ir)]); 712 713 MIPS_FPU_EMU_INC_STATS(stores); 714 DIFROMREG(val, MIPSInst_FS(ir)); 715 if (put_user(val, va)) { 716 MIPS_FPU_EMU_INC_STATS(errors); 717 return SIGBUS; 718 } 719 break; 720 721 case madd_d_op: 722 handler = fpemu_dp_madd; 723 goto dcoptop; 724 case msub_d_op: 725 handler = fpemu_dp_msub; 726 goto dcoptop; 727 case nmadd_d_op: 728 handler = fpemu_dp_nmadd; 729 goto dcoptop; 730 case nmsub_d_op: 731 handler = fpemu_dp_nmsub; 732 goto dcoptop; 733 734 dcoptop: 735 DPFROMREG(fr, MIPSInst_FR(ir)); 736 DPFROMREG(fs, MIPSInst_FS(ir)); 737 DPFROMREG(ft, MIPSInst_FT(ir)); 738 fd = (*handler) (fr, fs, ft); 739 DPTOREG(fd, MIPSInst_FD(ir)); 740 goto copcsr; 741 742 default: 743 return SIGILL; 744 } 745 break; 746 } 747 748 case 0x7: /* 7 */ 749 if (MIPSInst_FUNC(ir) != pfetch_op) { 750 return SIGILL; 751 } 752 /* ignore prefx operation */ 753 break; 754 755 default: 756 return SIGILL; 757 } 758 759 return 0; 760 } 761 #endif 762 763 764 765 /* 766 * Emulate a single COP1 arithmetic instruction. 767 */ 768 static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, 769 mips_instruction ir) 770 { 771 int rfmt; /* resulting format */ 772 unsigned rcsr = 0; /* resulting csr */ 773 unsigned cond; 774 union { 775 ieee754dp d; 776 ieee754sp s; 777 int w; 778 #ifdef __mips64 779 s64 l; 780 #endif 781 } rv; /* resulting value */ 782 783 MIPS_FPU_EMU_INC_STATS(cp1ops); 784 switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) { 785 case s_fmt:{ /* 0 */ 786 union { 787 ieee754sp(*b) (ieee754sp, ieee754sp); 788 ieee754sp(*u) (ieee754sp); 789 } handler; 790 791 switch (MIPSInst_FUNC(ir)) { 792 /* binary ops */ 793 case fadd_op: 794 handler.b = ieee754sp_add; 795 goto scopbop; 796 case fsub_op: 797 handler.b = ieee754sp_sub; 798 goto scopbop; 799 case fmul_op: 800 handler.b = ieee754sp_mul; 801 goto scopbop; 802 case fdiv_op: 803 handler.b = ieee754sp_div; 804 goto scopbop; 805 806 /* unary ops */ 807 #if __mips >= 2 || defined(__mips64) 808 case fsqrt_op: 809 handler.u = ieee754sp_sqrt; 810 goto scopuop; 811 #endif 812 #if __mips >= 4 && __mips != 32 813 case frsqrt_op: 814 handler.u = fpemu_sp_rsqrt; 815 goto scopuop; 816 case frecip_op: 817 handler.u = fpemu_sp_recip; 818 goto scopuop; 819 #endif 820 #if __mips >= 4 821 case fmovc_op: 822 cond = fpucondbit[MIPSInst_FT(ir) >> 2]; 823 if (((ctx->fcr31 & cond) != 0) != 824 ((MIPSInst_FT(ir) & 1) != 0)) 825 return 0; 826 SPFROMREG(rv.s, MIPSInst_FS(ir)); 827 break; 828 case fmovz_op: 829 if (xcp->regs[MIPSInst_FT(ir)] != 0) 830 return 0; 831 SPFROMREG(rv.s, MIPSInst_FS(ir)); 832 break; 833 case fmovn_op: 834 if (xcp->regs[MIPSInst_FT(ir)] == 0) 835 return 0; 836 SPFROMREG(rv.s, MIPSInst_FS(ir)); 837 break; 838 #endif 839 case fabs_op: 840 handler.u = ieee754sp_abs; 841 goto scopuop; 842 case fneg_op: 843 handler.u = ieee754sp_neg; 844 goto scopuop; 845 case fmov_op: 846 /* an easy one */ 847 SPFROMREG(rv.s, MIPSInst_FS(ir)); 848 goto copcsr; 849 850 /* binary op on handler */ 851 scopbop: 852 { 853 ieee754sp fs, ft; 854 855 SPFROMREG(fs, MIPSInst_FS(ir)); 856 SPFROMREG(ft, MIPSInst_FT(ir)); 857 858 rv.s = (*handler.b) (fs, ft); 859 goto copcsr; 860 } 861 scopuop: 862 { 863 ieee754sp fs; 864 865 SPFROMREG(fs, MIPSInst_FS(ir)); 866 rv.s = (*handler.u) (fs); 867 goto copcsr; 868 } 869 copcsr: 870 if (ieee754_cxtest(IEEE754_INEXACT)) 871 rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; 872 if (ieee754_cxtest(IEEE754_UNDERFLOW)) 873 rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S; 874 if (ieee754_cxtest(IEEE754_OVERFLOW)) 875 rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; 876 if (ieee754_cxtest(IEEE754_ZERO_DIVIDE)) 877 rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S; 878 if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) 879 rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S; 880 break; 881 882 /* unary conv ops */ 883 case fcvts_op: 884 return SIGILL; /* not defined */ 885 case fcvtd_op:{ 886 ieee754sp fs; 887 888 SPFROMREG(fs, MIPSInst_FS(ir)); 889 rv.d = ieee754dp_fsp(fs); 890 rfmt = d_fmt; 891 goto copcsr; 892 } 893 case fcvtw_op:{ 894 ieee754sp fs; 895 896 SPFROMREG(fs, MIPSInst_FS(ir)); 897 rv.w = ieee754sp_tint(fs); 898 rfmt = w_fmt; 899 goto copcsr; 900 } 901 902 #if __mips >= 2 || defined(__mips64) 903 case fround_op: 904 case ftrunc_op: 905 case fceil_op: 906 case ffloor_op:{ 907 unsigned int oldrm = ieee754_csr.rm; 908 ieee754sp fs; 909 910 SPFROMREG(fs, MIPSInst_FS(ir)); 911 ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; 912 rv.w = ieee754sp_tint(fs); 913 ieee754_csr.rm = oldrm; 914 rfmt = w_fmt; 915 goto copcsr; 916 } 917 #endif /* __mips >= 2 */ 918 919 #if defined(__mips64) 920 case fcvtl_op:{ 921 ieee754sp fs; 922 923 SPFROMREG(fs, MIPSInst_FS(ir)); 924 rv.l = ieee754sp_tlong(fs); 925 rfmt = l_fmt; 926 goto copcsr; 927 } 928 929 case froundl_op: 930 case ftruncl_op: 931 case fceill_op: 932 case ffloorl_op:{ 933 unsigned int oldrm = ieee754_csr.rm; 934 ieee754sp fs; 935 936 SPFROMREG(fs, MIPSInst_FS(ir)); 937 ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; 938 rv.l = ieee754sp_tlong(fs); 939 ieee754_csr.rm = oldrm; 940 rfmt = l_fmt; 941 goto copcsr; 942 } 943 #endif /* defined(__mips64) */ 944 945 default: 946 if (MIPSInst_FUNC(ir) >= fcmp_op) { 947 unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; 948 ieee754sp fs, ft; 949 950 SPFROMREG(fs, MIPSInst_FS(ir)); 951 SPFROMREG(ft, MIPSInst_FT(ir)); 952 rv.w = ieee754sp_cmp(fs, ft, 953 cmptab[cmpop & 0x7], cmpop & 0x8); 954 rfmt = -1; 955 if ((cmpop & 0x8) && ieee754_cxtest 956 (IEEE754_INVALID_OPERATION)) 957 rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S; 958 else 959 goto copcsr; 960 961 } 962 else { 963 return SIGILL; 964 } 965 break; 966 } 967 break; 968 } 969 970 case d_fmt:{ 971 union { 972 ieee754dp(*b) (ieee754dp, ieee754dp); 973 ieee754dp(*u) (ieee754dp); 974 } handler; 975 976 switch (MIPSInst_FUNC(ir)) { 977 /* binary ops */ 978 case fadd_op: 979 handler.b = ieee754dp_add; 980 goto dcopbop; 981 case fsub_op: 982 handler.b = ieee754dp_sub; 983 goto dcopbop; 984 case fmul_op: 985 handler.b = ieee754dp_mul; 986 goto dcopbop; 987 case fdiv_op: 988 handler.b = ieee754dp_div; 989 goto dcopbop; 990 991 /* unary ops */ 992 #if __mips >= 2 || defined(__mips64) 993 case fsqrt_op: 994 handler.u = ieee754dp_sqrt; 995 goto dcopuop; 996 #endif 997 #if __mips >= 4 && __mips != 32 998 case frsqrt_op: 999 handler.u = fpemu_dp_rsqrt; 1000 goto dcopuop; 1001 case frecip_op: 1002 handler.u = fpemu_dp_recip; 1003 goto dcopuop; 1004 #endif 1005 #if __mips >= 4 1006 case fmovc_op: 1007 cond = fpucondbit[MIPSInst_FT(ir) >> 2]; 1008 if (((ctx->fcr31 & cond) != 0) != 1009 ((MIPSInst_FT(ir) & 1) != 0)) 1010 return 0; 1011 DPFROMREG(rv.d, MIPSInst_FS(ir)); 1012 break; 1013 case fmovz_op: 1014 if (xcp->regs[MIPSInst_FT(ir)] != 0) 1015 return 0; 1016 DPFROMREG(rv.d, MIPSInst_FS(ir)); 1017 break; 1018 case fmovn_op: 1019 if (xcp->regs[MIPSInst_FT(ir)] == 0) 1020 return 0; 1021 DPFROMREG(rv.d, MIPSInst_FS(ir)); 1022 break; 1023 #endif 1024 case fabs_op: 1025 handler.u = ieee754dp_abs; 1026 goto dcopuop; 1027 1028 case fneg_op: 1029 handler.u = ieee754dp_neg; 1030 goto dcopuop; 1031 1032 case fmov_op: 1033 /* an easy one */ 1034 DPFROMREG(rv.d, MIPSInst_FS(ir)); 1035 goto copcsr; 1036 1037 /* binary op on handler */ 1038 dcopbop:{ 1039 ieee754dp fs, ft; 1040 1041 DPFROMREG(fs, MIPSInst_FS(ir)); 1042 DPFROMREG(ft, MIPSInst_FT(ir)); 1043 1044 rv.d = (*handler.b) (fs, ft); 1045 goto copcsr; 1046 } 1047 dcopuop:{ 1048 ieee754dp fs; 1049 1050 DPFROMREG(fs, MIPSInst_FS(ir)); 1051 rv.d = (*handler.u) (fs); 1052 goto copcsr; 1053 } 1054 1055 /* unary conv ops */ 1056 case fcvts_op:{ 1057 ieee754dp fs; 1058 1059 DPFROMREG(fs, MIPSInst_FS(ir)); 1060 rv.s = ieee754sp_fdp(fs); 1061 rfmt = s_fmt; 1062 goto copcsr; 1063 } 1064 case fcvtd_op: 1065 return SIGILL; /* not defined */ 1066 1067 case fcvtw_op:{ 1068 ieee754dp fs; 1069 1070 DPFROMREG(fs, MIPSInst_FS(ir)); 1071 rv.w = ieee754dp_tint(fs); /* wrong */ 1072 rfmt = w_fmt; 1073 goto copcsr; 1074 } 1075 1076 #if __mips >= 2 || defined(__mips64) 1077 case fround_op: 1078 case ftrunc_op: 1079 case fceil_op: 1080 case ffloor_op:{ 1081 unsigned int oldrm = ieee754_csr.rm; 1082 ieee754dp fs; 1083 1084 DPFROMREG(fs, MIPSInst_FS(ir)); 1085 ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; 1086 rv.w = ieee754dp_tint(fs); 1087 ieee754_csr.rm = oldrm; 1088 rfmt = w_fmt; 1089 goto copcsr; 1090 } 1091 #endif 1092 1093 #if defined(__mips64) 1094 case fcvtl_op:{ 1095 ieee754dp fs; 1096 1097 DPFROMREG(fs, MIPSInst_FS(ir)); 1098 rv.l = ieee754dp_tlong(fs); 1099 rfmt = l_fmt; 1100 goto copcsr; 1101 } 1102 1103 case froundl_op: 1104 case ftruncl_op: 1105 case fceill_op: 1106 case ffloorl_op:{ 1107 unsigned int oldrm = ieee754_csr.rm; 1108 ieee754dp fs; 1109 1110 DPFROMREG(fs, MIPSInst_FS(ir)); 1111 ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; 1112 rv.l = ieee754dp_tlong(fs); 1113 ieee754_csr.rm = oldrm; 1114 rfmt = l_fmt; 1115 goto copcsr; 1116 } 1117 #endif /* __mips >= 3 */ 1118 1119 default: 1120 if (MIPSInst_FUNC(ir) >= fcmp_op) { 1121 unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; 1122 ieee754dp fs, ft; 1123 1124 DPFROMREG(fs, MIPSInst_FS(ir)); 1125 DPFROMREG(ft, MIPSInst_FT(ir)); 1126 rv.w = ieee754dp_cmp(fs, ft, 1127 cmptab[cmpop & 0x7], cmpop & 0x8); 1128 rfmt = -1; 1129 if ((cmpop & 0x8) 1130 && 1131 ieee754_cxtest 1132 (IEEE754_INVALID_OPERATION)) 1133 rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S; 1134 else 1135 goto copcsr; 1136 1137 } 1138 else { 1139 return SIGILL; 1140 } 1141 break; 1142 } 1143 break; 1144 } 1145 1146 case w_fmt:{ 1147 ieee754sp fs; 1148 1149 switch (MIPSInst_FUNC(ir)) { 1150 case fcvts_op: 1151 /* convert word to single precision real */ 1152 SPFROMREG(fs, MIPSInst_FS(ir)); 1153 rv.s = ieee754sp_fint(fs.bits); 1154 rfmt = s_fmt; 1155 goto copcsr; 1156 case fcvtd_op: 1157 /* convert word to double precision real */ 1158 SPFROMREG(fs, MIPSInst_FS(ir)); 1159 rv.d = ieee754dp_fint(fs.bits); 1160 rfmt = d_fmt; 1161 goto copcsr; 1162 default: 1163 return SIGILL; 1164 } 1165 break; 1166 } 1167 1168 #if defined(__mips64) 1169 case l_fmt:{ 1170 switch (MIPSInst_FUNC(ir)) { 1171 case fcvts_op: 1172 /* convert long to single precision real */ 1173 rv.s = ieee754sp_flong(ctx->fpr[MIPSInst_FS(ir)]); 1174 rfmt = s_fmt; 1175 goto copcsr; 1176 case fcvtd_op: 1177 /* convert long to double precision real */ 1178 rv.d = ieee754dp_flong(ctx->fpr[MIPSInst_FS(ir)]); 1179 rfmt = d_fmt; 1180 goto copcsr; 1181 default: 1182 return SIGILL; 1183 } 1184 break; 1185 } 1186 #endif 1187 1188 default: 1189 return SIGILL; 1190 } 1191 1192 /* 1193 * Update the fpu CSR register for this operation. 1194 * If an exception is required, generate a tidy SIGFPE exception, 1195 * without updating the result register. 1196 * Note: cause exception bits do not accumulate, they are rewritten 1197 * for each op; only the flag/sticky bits accumulate. 1198 */ 1199 ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr; 1200 if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { 1201 /*printk ("SIGFPE: fpu csr = %08x\n",ctx->fcr31); */ 1202 return SIGFPE; 1203 } 1204 1205 /* 1206 * Now we can safely write the result back to the register file. 1207 */ 1208 switch (rfmt) { 1209 case -1:{ 1210 #if __mips >= 4 1211 cond = fpucondbit[MIPSInst_FD(ir) >> 2]; 1212 #else 1213 cond = FPU_CSR_COND; 1214 #endif 1215 if (rv.w) 1216 ctx->fcr31 |= cond; 1217 else 1218 ctx->fcr31 &= ~cond; 1219 break; 1220 } 1221 case d_fmt: 1222 DPTOREG(rv.d, MIPSInst_FD(ir)); 1223 break; 1224 case s_fmt: 1225 SPTOREG(rv.s, MIPSInst_FD(ir)); 1226 break; 1227 case w_fmt: 1228 SITOREG(rv.w, MIPSInst_FD(ir)); 1229 break; 1230 #if defined(__mips64) 1231 case l_fmt: 1232 DITOREG(rv.l, MIPSInst_FD(ir)); 1233 break; 1234 #endif 1235 default: 1236 return SIGILL; 1237 } 1238 1239 return 0; 1240 } 1241 1242 int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, 1243 int has_fpu) 1244 { 1245 unsigned long oldepc, prevepc; 1246 mips_instruction insn; 1247 int sig = 0; 1248 1249 oldepc = xcp->cp0_epc; 1250 do { 1251 prevepc = xcp->cp0_epc; 1252 1253 if (get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) { 1254 MIPS_FPU_EMU_INC_STATS(errors); 1255 return SIGBUS; 1256 } 1257 if (insn == 0) 1258 xcp->cp0_epc += 4; /* skip nops */ 1259 else { 1260 /* 1261 * The 'ieee754_csr' is an alias of 1262 * ctx->fcr31. No need to copy ctx->fcr31 to 1263 * ieee754_csr. But ieee754_csr.rm is ieee 1264 * library modes. (not mips rounding mode) 1265 */ 1266 /* convert to ieee library modes */ 1267 ieee754_csr.rm = ieee_rm[ieee754_csr.rm]; 1268 sig = cop1Emulate(xcp, ctx); 1269 /* revert to mips rounding mode */ 1270 ieee754_csr.rm = mips_rm[ieee754_csr.rm]; 1271 } 1272 1273 if (has_fpu) 1274 break; 1275 if (sig) 1276 break; 1277 1278 cond_resched(); 1279 } while (xcp->cp0_epc > prevepc); 1280 1281 /* SIGILL indicates a non-fpu instruction */ 1282 if (sig == SIGILL && xcp->cp0_epc != oldepc) 1283 /* but if epc has advanced, then ignore it */ 1284 sig = 0; 1285 1286 return sig; 1287 } 1288 1289 #ifdef CONFIG_DEBUG_FS 1290 1291 static int fpuemu_stat_get(void *data, u64 *val) 1292 { 1293 int cpu; 1294 unsigned long sum = 0; 1295 for_each_online_cpu(cpu) { 1296 struct mips_fpu_emulator_stats *ps; 1297 local_t *pv; 1298 ps = &per_cpu(fpuemustats, cpu); 1299 pv = (void *)ps + (unsigned long)data; 1300 sum += local_read(pv); 1301 } 1302 *val = sum; 1303 return 0; 1304 } 1305 DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n"); 1306 1307 extern struct dentry *mips_debugfs_dir; 1308 static int __init debugfs_fpuemu(void) 1309 { 1310 struct dentry *d, *dir; 1311 1312 if (!mips_debugfs_dir) 1313 return -ENODEV; 1314 dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir); 1315 if (!dir) 1316 return -ENOMEM; 1317 1318 #define FPU_STAT_CREATE(M) \ 1319 do { \ 1320 d = debugfs_create_file(#M , S_IRUGO, dir, \ 1321 (void *)offsetof(struct mips_fpu_emulator_stats, M), \ 1322 &fops_fpuemu_stat); \ 1323 if (!d) \ 1324 return -ENOMEM; \ 1325 } while (0) 1326 1327 FPU_STAT_CREATE(emulated); 1328 FPU_STAT_CREATE(loads); 1329 FPU_STAT_CREATE(stores); 1330 FPU_STAT_CREATE(cp1ops); 1331 FPU_STAT_CREATE(cp1xops); 1332 FPU_STAT_CREATE(errors); 1333 1334 return 0; 1335 } 1336 __initcall(debugfs_fpuemu); 1337 #endif 1338