cp1emu.c revision e04582b7bc70b40c57287cdc24f81964ee88f565
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 61static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *, 62 mips_instruction); 63 64#if __mips >= 4 && __mips != 32 65static 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 71struct 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. */ 79static 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). */ 86static 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 */ 95static 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 */ 114static 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 204static 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 */ 533static 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) \ 552static 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 567static ieee754dp fpemu_dp_recip(ieee754dp d) 568{ 569 return ieee754dp_div(ieee754dp_one(0), d); 570} 571 572static ieee754dp fpemu_dp_rsqrt(ieee754dp d) 573{ 574 return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d)); 575} 576 577static ieee754sp fpemu_sp_recip(ieee754sp s) 578{ 579 return ieee754sp_div(ieee754sp_one(0), s); 580} 581 582static ieee754sp fpemu_sp_rsqrt(ieee754sp s) 583{ 584 return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s)); 585} 586 587DEF3OP(madd, sp, ieee754sp_mul, ieee754sp_add,); 588DEF3OP(msub, sp, ieee754sp_mul, ieee754sp_sub,); 589DEF3OP(nmadd, sp, ieee754sp_mul, ieee754sp_add, ieee754sp_neg); 590DEF3OP(nmsub, sp, ieee754sp_mul, ieee754sp_sub, ieee754sp_neg); 591DEF3OP(madd, dp, ieee754dp_mul, ieee754dp_add,); 592DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub,); 593DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg); 594DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg); 595 596static 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 */ 760static 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 1234int 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