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 39 #include <asm/inst.h> 40 #include <asm/bootinfo.h> 41 #include <asm/processor.h> 42 #include <asm/ptrace.h> 43 #include <asm/signal.h> 44 #include <asm/mipsregs.h> 45 #include <asm/fpu_emulator.h> 46 #include <asm/uaccess.h> 47 #include <asm/branch.h> 48 49 #include "ieee754.h" 50 #include "dsemul.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. This does imply that, if a full 32 167 * FPRs are desired, there needs to be a flip-flop that can be written 168 * to one at that bit position. In any case, O32 MIPS ABI uses 169 * only the even FPRs (Status.FR = 0). 170 */ 171 172 #define CP0_STATUS_FR_SUPPORT 173 174 #ifdef CP0_STATUS_FR_SUPPORT 175 #define FR_BIT ST0_FR 176 #else 177 #define FR_BIT 0 178 #endif 179 180 #define SIFROMREG(si,x) ((si) = \ 181 (xcp->cp0_status & FR_BIT) || !(x & 1) ? \ 182 (int)ctx->fpr[x] : \ 183 (int)(ctx->fpr[x & ~1] >> 32 )) 184 #define SITOREG(si,x) (ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)] = \ 185 (xcp->cp0_status & FR_BIT) || !(x & 1) ? \ 186 ctx->fpr[x & ~1] >> 32 << 32 | (u32)(si) : \ 187 ctx->fpr[x & ~1] << 32 >> 32 | (u64)(si) << 32) 188 189 #define DIFROMREG(di,x) ((di) = \ 190 ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)]) 191 #define DITOREG(di,x) (ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)] \ 192 = (di)) 193 194 #define SPFROMREG(sp,x) SIFROMREG((sp).bits,x) 195 #define SPTOREG(sp,x) SITOREG((sp).bits,x) 196 #define DPFROMREG(dp,x) DIFROMREG((dp).bits,x) 197 #define DPTOREG(dp,x) DITOREG((dp).bits,x) 198 199 /* 200 * Emulate the single floating point instruction pointed at by EPC. 201 * Two instructions if the instruction is in a branch delay slot. 202 */ 203 204 static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) 205 { 206 mips_instruction ir; 207 void * emulpc, *contpc; 208 unsigned int cond; 209 210 if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) { 211 fpuemustats.errors++; 212 return SIGBUS; 213 } 214 215 /* XXX NEC Vr54xx bug workaround */ 216 if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir)) 217 xcp->cp0_cause &= ~CAUSEF_BD; 218 219 if (xcp->cp0_cause & CAUSEF_BD) { 220 /* 221 * The instruction to be emulated is in a branch delay slot 222 * which means that we have to emulate the branch instruction 223 * BEFORE we do the cop1 instruction. 224 * 225 * This branch could be a COP1 branch, but in that case we 226 * would have had a trap for that instruction, and would not 227 * come through this route. 228 * 229 * Linux MIPS branch emulator operates on context, updating the 230 * cp0_epc. 231 */ 232 emulpc = (void *) (xcp->cp0_epc + 4); /* Snapshot emulation target */ 233 234 if (__compute_return_epc(xcp)) { 235 #ifdef CP1DBG 236 printk("failed to emulate branch at %p\n", 237 (void *) (xcp->cp0_epc)); 238 #endif 239 return SIGILL; 240 } 241 if (get_user(ir, (mips_instruction __user *) emulpc)) { 242 fpuemustats.errors++; 243 return SIGBUS; 244 } 245 /* __compute_return_epc() will have updated cp0_epc */ 246 contpc = (void *) xcp->cp0_epc; 247 /* In order not to confuse ptrace() et al, tweak context */ 248 xcp->cp0_epc = (unsigned long) emulpc - 4; 249 } else { 250 emulpc = (void *) xcp->cp0_epc; 251 contpc = (void *) (xcp->cp0_epc + 4); 252 } 253 254 emul: 255 fpuemustats.emulated++; 256 switch (MIPSInst_OPCODE(ir)) { 257 case ldc1_op:{ 258 u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + 259 MIPSInst_SIMM(ir)); 260 u64 val; 261 262 fpuemustats.loads++; 263 if (get_user(val, va)) { 264 fpuemustats.errors++; 265 return SIGBUS; 266 } 267 DITOREG(val, MIPSInst_RT(ir)); 268 break; 269 } 270 271 case sdc1_op:{ 272 u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + 273 MIPSInst_SIMM(ir)); 274 u64 val; 275 276 fpuemustats.stores++; 277 DIFROMREG(val, MIPSInst_RT(ir)); 278 if (put_user(val, va)) { 279 fpuemustats.errors++; 280 return SIGBUS; 281 } 282 break; 283 } 284 285 case lwc1_op:{ 286 u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] + 287 MIPSInst_SIMM(ir)); 288 u32 val; 289 290 fpuemustats.loads++; 291 if (get_user(val, va)) { 292 fpuemustats.errors++; 293 return SIGBUS; 294 } 295 SITOREG(val, MIPSInst_RT(ir)); 296 break; 297 } 298 299 case swc1_op:{ 300 u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] + 301 MIPSInst_SIMM(ir)); 302 u32 val; 303 304 fpuemustats.stores++; 305 SIFROMREG(val, MIPSInst_RT(ir)); 306 if (put_user(val, va)) { 307 fpuemustats.errors++; 308 return SIGBUS; 309 } 310 break; 311 } 312 313 case cop1_op: 314 switch (MIPSInst_RS(ir)) { 315 316 #if defined(__mips64) 317 case dmfc_op: 318 /* copregister fs -> gpr[rt] */ 319 if (MIPSInst_RT(ir) != 0) { 320 DIFROMREG(xcp->regs[MIPSInst_RT(ir)], 321 MIPSInst_RD(ir)); 322 } 323 break; 324 325 case dmtc_op: 326 /* copregister fs <- rt */ 327 DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir)); 328 break; 329 #endif 330 331 case mfc_op: 332 /* copregister rd -> gpr[rt] */ 333 if (MIPSInst_RT(ir) != 0) { 334 SIFROMREG(xcp->regs[MIPSInst_RT(ir)], 335 MIPSInst_RD(ir)); 336 } 337 break; 338 339 case mtc_op: 340 /* copregister rd <- rt */ 341 SITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir)); 342 break; 343 344 case cfc_op:{ 345 /* cop control register rd -> gpr[rt] */ 346 u32 value; 347 348 if (ir == CP1UNDEF) { 349 return do_dsemulret(xcp); 350 } 351 if (MIPSInst_RD(ir) == FPCREG_CSR) { 352 value = ctx->fcr31; 353 value = (value & ~0x3) | mips_rm[value & 0x3]; 354 #ifdef CSRTRACE 355 printk("%p gpr[%d]<-csr=%08x\n", 356 (void *) (xcp->cp0_epc), 357 MIPSInst_RT(ir), value); 358 #endif 359 } 360 else if (MIPSInst_RD(ir) == FPCREG_RID) 361 value = 0; 362 else 363 value = 0; 364 if (MIPSInst_RT(ir)) 365 xcp->regs[MIPSInst_RT(ir)] = value; 366 break; 367 } 368 369 case ctc_op:{ 370 /* copregister rd <- rt */ 371 u32 value; 372 373 if (MIPSInst_RT(ir) == 0) 374 value = 0; 375 else 376 value = xcp->regs[MIPSInst_RT(ir)]; 377 378 /* we only have one writable control reg 379 */ 380 if (MIPSInst_RD(ir) == FPCREG_CSR) { 381 #ifdef CSRTRACE 382 printk("%p gpr[%d]->csr=%08x\n", 383 (void *) (xcp->cp0_epc), 384 MIPSInst_RT(ir), value); 385 #endif 386 value &= (FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03); 387 ctx->fcr31 &= ~(FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03); 388 /* convert to ieee library modes */ 389 ctx->fcr31 |= (value & ~0x3) | ieee_rm[value & 0x3]; 390 } 391 if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { 392 return SIGFPE; 393 } 394 break; 395 } 396 397 case bc_op:{ 398 int likely = 0; 399 400 if (xcp->cp0_cause & CAUSEF_BD) 401 return SIGILL; 402 403 #if __mips >= 4 404 cond = ctx->fcr31 & fpucondbit[MIPSInst_RT(ir) >> 2]; 405 #else 406 cond = ctx->fcr31 & FPU_CSR_COND; 407 #endif 408 switch (MIPSInst_RT(ir) & 3) { 409 case bcfl_op: 410 likely = 1; 411 case bcf_op: 412 cond = !cond; 413 break; 414 case bctl_op: 415 likely = 1; 416 case bct_op: 417 break; 418 default: 419 /* thats an illegal instruction */ 420 return SIGILL; 421 } 422 423 xcp->cp0_cause |= CAUSEF_BD; 424 if (cond) { 425 /* branch taken: emulate dslot 426 * instruction 427 */ 428 xcp->cp0_epc += 4; 429 contpc = (void *) 430 (xcp->cp0_epc + 431 (MIPSInst_SIMM(ir) << 2)); 432 433 if (get_user(ir, 434 (mips_instruction __user *) xcp->cp0_epc)) { 435 fpuemustats.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, (unsigned long) 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 = (unsigned long) 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 fpuemustats.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 fpuemustats.loads++; 617 if (get_user(val, va)) { 618 fpuemustats.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 fpuemustats.stores++; 629 630 SIFROMREG(val, MIPSInst_FS(ir)); 631 if (put_user(val, va)) { 632 fpuemustats.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 fpuemustats.loads++; 694 if (get_user(val, va)) { 695 fpuemustats.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 fpuemustats.stores++; 706 DIFROMREG(val, MIPSInst_FS(ir)); 707 if (put_user(val, va)) { 708 fpuemustats.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 fpuemustats.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 fpuemustats.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