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