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