diff options
Diffstat (limited to 'arch/powerpc/math-emu/math_efp.c')
| -rw-r--r-- | arch/powerpc/math-emu/math_efp.c | 100 |
1 files changed, 48 insertions, 52 deletions
diff --git a/arch/powerpc/math-emu/math_efp.c b/arch/powerpc/math-emu/math_efp.c index 62279200d965..a73f0884d358 100644 --- a/arch/powerpc/math-emu/math_efp.c +++ b/arch/powerpc/math-emu/math_efp.c | |||
| @@ -171,10 +171,6 @@ static unsigned long insn_type(unsigned long speinsn) | |||
| 171 | case EFDNABS: ret = XA; break; | 171 | case EFDNABS: ret = XA; break; |
| 172 | case EFDNEG: ret = XA; break; | 172 | case EFDNEG: ret = XA; break; |
| 173 | case EFDSUB: ret = AB; break; | 173 | case EFDSUB: ret = AB; break; |
| 174 | |||
| 175 | default: | ||
| 176 | printk(KERN_ERR "\nOoops! SPE instruction no type found."); | ||
| 177 | printk(KERN_ERR "\ninst code: %08lx\n", speinsn); | ||
| 178 | } | 174 | } |
| 179 | 175 | ||
| 180 | return ret; | 176 | return ret; |
| @@ -195,7 +191,7 @@ int do_spe_mathemu(struct pt_regs *regs) | |||
| 195 | 191 | ||
| 196 | type = insn_type(speinsn); | 192 | type = insn_type(speinsn); |
| 197 | if (type == NOTYPE) | 193 | if (type == NOTYPE) |
| 198 | return -ENOSYS; | 194 | goto illegal; |
| 199 | 195 | ||
| 200 | func = speinsn & 0x7ff; | 196 | func = speinsn & 0x7ff; |
| 201 | fc = (speinsn >> 21) & 0x1f; | 197 | fc = (speinsn >> 21) & 0x1f; |
| @@ -212,12 +208,10 @@ int do_spe_mathemu(struct pt_regs *regs) | |||
| 212 | 208 | ||
| 213 | __FPU_FPSCR = mfspr(SPRN_SPEFSCR); | 209 | __FPU_FPSCR = mfspr(SPRN_SPEFSCR); |
| 214 | 210 | ||
| 215 | #ifdef DEBUG | 211 | pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR); |
| 216 | printk("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR); | 212 | pr_debug("vc: %08x %08x\n", vc.wp[0], vc.wp[1]); |
| 217 | printk("vc: %08x %08x\n", vc.wp[0], vc.wp[1]); | 213 | pr_debug("va: %08x %08x\n", va.wp[0], va.wp[1]); |
| 218 | printk("va: %08x %08x\n", va.wp[0], va.wp[1]); | 214 | pr_debug("vb: %08x %08x\n", vb.wp[0], vb.wp[1]); |
| 219 | printk("vb: %08x %08x\n", vb.wp[0], vb.wp[1]); | ||
| 220 | #endif | ||
| 221 | 215 | ||
| 222 | switch (src) { | 216 | switch (src) { |
| 223 | case SPFP: { | 217 | case SPFP: { |
| @@ -235,10 +229,8 @@ int do_spe_mathemu(struct pt_regs *regs) | |||
| 235 | break; | 229 | break; |
| 236 | } | 230 | } |
| 237 | 231 | ||
| 238 | #ifdef DEBUG | 232 | pr_debug("SA: %ld %08lx %ld (%ld)\n", SA_s, SA_f, SA_e, SA_c); |
| 239 | printk("SA: %ld %08lx %ld (%ld)\n", SA_s, SA_f, SA_e, SA_c); | 233 | pr_debug("SB: %ld %08lx %ld (%ld)\n", SB_s, SB_f, SB_e, SB_c); |
| 240 | printk("SB: %ld %08lx %ld (%ld)\n", SB_s, SB_f, SB_e, SB_c); | ||
| 241 | #endif | ||
| 242 | 234 | ||
| 243 | switch (func) { | 235 | switch (func) { |
| 244 | case EFSABS: | 236 | case EFSABS: |
| @@ -305,10 +297,10 @@ int do_spe_mathemu(struct pt_regs *regs) | |||
| 305 | FP_DECL_D(DB); | 297 | FP_DECL_D(DB); |
| 306 | FP_CLEAR_EXCEPTIONS; | 298 | FP_CLEAR_EXCEPTIONS; |
| 307 | FP_UNPACK_DP(DB, vb.dp); | 299 | FP_UNPACK_DP(DB, vb.dp); |
| 308 | #ifdef DEBUG | 300 | |
| 309 | printk("DB: %ld %08lx %08lx %ld (%ld)\n", | 301 | pr_debug("DB: %ld %08lx %08lx %ld (%ld)\n", |
| 310 | DB_s, DB_f1, DB_f0, DB_e, DB_c); | 302 | DB_s, DB_f1, DB_f0, DB_e, DB_c); |
| 311 | #endif | 303 | |
| 312 | FP_CONV(S, D, 1, 2, SR, DB); | 304 | FP_CONV(S, D, 1, 2, SR, DB); |
| 313 | goto pack_s; | 305 | goto pack_s; |
| 314 | } | 306 | } |
| @@ -332,9 +324,8 @@ int do_spe_mathemu(struct pt_regs *regs) | |||
| 332 | break; | 324 | break; |
| 333 | 325 | ||
| 334 | pack_s: | 326 | pack_s: |
| 335 | #ifdef DEBUG | 327 | pr_debug("SR: %ld %08lx %ld (%ld)\n", SR_s, SR_f, SR_e, SR_c); |
| 336 | printk("SR: %ld %08lx %ld (%ld)\n", SR_s, SR_f, SR_e, SR_c); | 328 | |
| 337 | #endif | ||
| 338 | FP_PACK_SP(vc.wp + 1, SR); | 329 | FP_PACK_SP(vc.wp + 1, SR); |
| 339 | goto update_regs; | 330 | goto update_regs; |
| 340 | 331 | ||
| @@ -365,12 +356,10 @@ cmp_s: | |||
| 365 | break; | 356 | break; |
| 366 | } | 357 | } |
| 367 | 358 | ||
| 368 | #ifdef DEBUG | 359 | pr_debug("DA: %ld %08lx %08lx %ld (%ld)\n", |
| 369 | printk("DA: %ld %08lx %08lx %ld (%ld)\n", | ||
| 370 | DA_s, DA_f1, DA_f0, DA_e, DA_c); | 360 | DA_s, DA_f1, DA_f0, DA_e, DA_c); |
| 371 | printk("DB: %ld %08lx %08lx %ld (%ld)\n", | 361 | pr_debug("DB: %ld %08lx %08lx %ld (%ld)\n", |
| 372 | DB_s, DB_f1, DB_f0, DB_e, DB_c); | 362 | DB_s, DB_f1, DB_f0, DB_e, DB_c); |
| 373 | #endif | ||
| 374 | 363 | ||
| 375 | switch (func) { | 364 | switch (func) { |
| 376 | case EFDABS: | 365 | case EFDABS: |
| @@ -438,10 +427,10 @@ cmp_s: | |||
| 438 | FP_DECL_S(SB); | 427 | FP_DECL_S(SB); |
| 439 | FP_CLEAR_EXCEPTIONS; | 428 | FP_CLEAR_EXCEPTIONS; |
| 440 | FP_UNPACK_SP(SB, vb.wp + 1); | 429 | FP_UNPACK_SP(SB, vb.wp + 1); |
| 441 | #ifdef DEBUG | 430 | |
| 442 | printk("SB: %ld %08lx %ld (%ld)\n", | 431 | pr_debug("SB: %ld %08lx %ld (%ld)\n", |
| 443 | SB_s, SB_f, SB_e, SB_c); | 432 | SB_s, SB_f, SB_e, SB_c); |
| 444 | #endif | 433 | |
| 445 | FP_CONV(D, S, 2, 1, DR, SB); | 434 | FP_CONV(D, S, 2, 1, DR, SB); |
| 446 | goto pack_d; | 435 | goto pack_d; |
| 447 | } | 436 | } |
| @@ -471,10 +460,9 @@ cmp_s: | |||
| 471 | break; | 460 | break; |
| 472 | 461 | ||
| 473 | pack_d: | 462 | pack_d: |
| 474 | #ifdef DEBUG | 463 | pr_debug("DR: %ld %08lx %08lx %ld (%ld)\n", |
| 475 | printk("DR: %ld %08lx %08lx %ld (%ld)\n", | ||
| 476 | DR_s, DR_f1, DR_f0, DR_e, DR_c); | 464 | DR_s, DR_f1, DR_f0, DR_e, DR_c); |
| 477 | #endif | 465 | |
| 478 | FP_PACK_DP(vc.dp, DR); | 466 | FP_PACK_DP(vc.dp, DR); |
| 479 | goto update_regs; | 467 | goto update_regs; |
| 480 | 468 | ||
| @@ -511,12 +499,14 @@ cmp_d: | |||
| 511 | break; | 499 | break; |
| 512 | } | 500 | } |
| 513 | 501 | ||
| 514 | #ifdef DEBUG | 502 | pr_debug("SA0: %ld %08lx %ld (%ld)\n", |
| 515 | printk("SA0: %ld %08lx %ld (%ld)\n", SA0_s, SA0_f, SA0_e, SA0_c); | 503 | SA0_s, SA0_f, SA0_e, SA0_c); |
| 516 | printk("SA1: %ld %08lx %ld (%ld)\n", SA1_s, SA1_f, SA1_e, SA1_c); | 504 | pr_debug("SA1: %ld %08lx %ld (%ld)\n", |
| 517 | printk("SB0: %ld %08lx %ld (%ld)\n", SB0_s, SB0_f, SB0_e, SB0_c); | 505 | SA1_s, SA1_f, SA1_e, SA1_c); |
| 518 | printk("SB1: %ld %08lx %ld (%ld)\n", SB1_s, SB1_f, SB1_e, SB1_c); | 506 | pr_debug("SB0: %ld %08lx %ld (%ld)\n", |
| 519 | #endif | 507 | SB0_s, SB0_f, SB0_e, SB0_c); |
| 508 | pr_debug("SB1: %ld %08lx %ld (%ld)\n", | ||
| 509 | SB1_s, SB1_f, SB1_e, SB1_c); | ||
| 520 | 510 | ||
| 521 | switch (func) { | 511 | switch (func) { |
| 522 | case EVFSABS: | 512 | case EVFSABS: |
| @@ -605,10 +595,11 @@ cmp_d: | |||
| 605 | break; | 595 | break; |
| 606 | 596 | ||
| 607 | pack_vs: | 597 | pack_vs: |
| 608 | #ifdef DEBUG | 598 | pr_debug("SR0: %ld %08lx %ld (%ld)\n", |
| 609 | printk("SR0: %ld %08lx %ld (%ld)\n", SR0_s, SR0_f, SR0_e, SR0_c); | 599 | SR0_s, SR0_f, SR0_e, SR0_c); |
| 610 | printk("SR1: %ld %08lx %ld (%ld)\n", SR1_s, SR1_f, SR1_e, SR1_c); | 600 | pr_debug("SR1: %ld %08lx %ld (%ld)\n", |
| 611 | #endif | 601 | SR1_s, SR1_f, SR1_e, SR1_c); |
| 602 | |||
| 612 | FP_PACK_SP(vc.wp, SR0); | 603 | FP_PACK_SP(vc.wp, SR0); |
| 613 | FP_PACK_SP(vc.wp + 1, SR1); | 604 | FP_PACK_SP(vc.wp + 1, SR1); |
| 614 | goto update_regs; | 605 | goto update_regs; |
| @@ -646,14 +637,12 @@ update_regs: | |||
| 646 | current->thread.evr[fc] = vc.wp[0]; | 637 | current->thread.evr[fc] = vc.wp[0]; |
| 647 | regs->gpr[fc] = vc.wp[1]; | 638 | regs->gpr[fc] = vc.wp[1]; |
| 648 | 639 | ||
| 649 | #ifdef DEBUG | 640 | pr_debug("ccr = %08lx\n", regs->ccr); |
| 650 | printk("ccr = %08lx\n", regs->ccr); | 641 | pr_debug("cur exceptions = %08x spefscr = %08lx\n", |
| 651 | printk("cur exceptions = %08x spefscr = %08lx\n", | ||
| 652 | FP_CUR_EXCEPTIONS, __FPU_FPSCR); | 642 | FP_CUR_EXCEPTIONS, __FPU_FPSCR); |
| 653 | printk("vc: %08x %08x\n", vc.wp[0], vc.wp[1]); | 643 | pr_debug("vc: %08x %08x\n", vc.wp[0], vc.wp[1]); |
| 654 | printk("va: %08x %08x\n", va.wp[0], va.wp[1]); | 644 | pr_debug("va: %08x %08x\n", va.wp[0], va.wp[1]); |
| 655 | printk("vb: %08x %08x\n", vb.wp[0], vb.wp[1]); | 645 | pr_debug("vb: %08x %08x\n", vb.wp[0], vb.wp[1]); |
| 656 | #endif | ||
| 657 | 646 | ||
| 658 | return 0; | 647 | return 0; |
| 659 | 648 | ||
| @@ -661,9 +650,7 @@ illegal: | |||
| 661 | if (have_e500_cpu_a005_erratum) { | 650 | if (have_e500_cpu_a005_erratum) { |
| 662 | /* according to e500 cpu a005 erratum, reissue efp inst */ | 651 | /* according to e500 cpu a005 erratum, reissue efp inst */ |
| 663 | regs->nip -= 4; | 652 | regs->nip -= 4; |
| 664 | #ifdef DEBUG | 653 | pr_debug("re-issue efp inst: %08lx\n", speinsn); |
| 665 | printk(KERN_DEBUG "re-issue efp inst: %08lx\n", speinsn); | ||
| 666 | #endif | ||
| 667 | return 0; | 654 | return 0; |
| 668 | } | 655 | } |
| 669 | 656 | ||
| @@ -685,13 +672,20 @@ int speround_handler(struct pt_regs *regs) | |||
| 685 | type = insn_type(speinsn & 0x7ff); | 672 | type = insn_type(speinsn & 0x7ff); |
| 686 | if (type == XCR) return -ENOSYS; | 673 | if (type == XCR) return -ENOSYS; |
| 687 | 674 | ||
| 675 | __FPU_FPSCR = mfspr(SPRN_SPEFSCR); | ||
| 676 | pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR); | ||
| 677 | |||
| 678 | /* No need to round if the result is exact */ | ||
| 679 | if (!(__FPU_FPSCR & FP_EX_INEXACT)) | ||
| 680 | return 0; | ||
| 681 | |||
| 688 | fc = (speinsn >> 21) & 0x1f; | 682 | fc = (speinsn >> 21) & 0x1f; |
| 689 | s_lo = regs->gpr[fc] & SIGN_BIT_S; | 683 | s_lo = regs->gpr[fc] & SIGN_BIT_S; |
| 690 | s_hi = current->thread.evr[fc] & SIGN_BIT_S; | 684 | s_hi = current->thread.evr[fc] & SIGN_BIT_S; |
| 691 | fgpr.wp[0] = current->thread.evr[fc]; | 685 | fgpr.wp[0] = current->thread.evr[fc]; |
| 692 | fgpr.wp[1] = regs->gpr[fc]; | 686 | fgpr.wp[1] = regs->gpr[fc]; |
| 693 | 687 | ||
| 694 | __FPU_FPSCR = mfspr(SPRN_SPEFSCR); | 688 | pr_debug("round fgpr: %08x %08x\n", fgpr.wp[0], fgpr.wp[1]); |
| 695 | 689 | ||
| 696 | switch ((speinsn >> 5) & 0x7) { | 690 | switch ((speinsn >> 5) & 0x7) { |
| 697 | /* Since SPE instructions on E500 core can handle round to nearest | 691 | /* Since SPE instructions on E500 core can handle round to nearest |
| @@ -731,6 +725,8 @@ int speround_handler(struct pt_regs *regs) | |||
| 731 | current->thread.evr[fc] = fgpr.wp[0]; | 725 | current->thread.evr[fc] = fgpr.wp[0]; |
| 732 | regs->gpr[fc] = fgpr.wp[1]; | 726 | regs->gpr[fc] = fgpr.wp[1]; |
| 733 | 727 | ||
| 728 | pr_debug(" to fgpr: %08x %08x\n", fgpr.wp[0], fgpr.wp[1]); | ||
| 729 | |||
| 734 | return 0; | 730 | return 0; |
| 735 | } | 731 | } |
| 736 | 732 | ||
