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