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