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 | ||