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