Lines Matching +full:no +full:- +full:wp
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * arch/powerpc/math-emu/math_efp.c
5 * Copyright (C) 2006-2008, 2010 Freescale Semiconductor, Inc.
10 * Derived from arch/alpha/math-emu/math.c
11 * arch/powerpc/math-emu/math.c
15 * fully comply with IEEE-754 floating point standard.
26 #include <asm/sfp-machine.h>
28 #include <math-emu/soft-fp.h>
29 #include <math-emu/single.h>
30 #include <math-emu/double.h>
109 u32 wp[2]; member
185 if (get_user(speinsn, (unsigned int __user *) regs->nip)) in do_spe_mathemu()
186 return -EFAULT; in do_spe_mathemu()
188 return -EINVAL; /* not an spe instruction */ in do_spe_mathemu()
200 vc.wp[0] = current->thread.evr[fc]; in do_spe_mathemu()
201 vc.wp[1] = regs->gpr[fc]; in do_spe_mathemu()
202 va.wp[0] = current->thread.evr[fa]; in do_spe_mathemu()
203 va.wp[1] = regs->gpr[fa]; in do_spe_mathemu()
204 vb.wp[0] = current->thread.evr[fb]; in do_spe_mathemu()
205 vb.wp[1] = regs->gpr[fb]; in do_spe_mathemu()
210 pr_debug("vc: %08x %08x\n", vc.wp[0], vc.wp[1]); in do_spe_mathemu()
211 pr_debug("va: %08x %08x\n", va.wp[0], va.wp[1]); in do_spe_mathemu()
212 pr_debug("vb: %08x %08x\n", vb.wp[0], vb.wp[1]); in do_spe_mathemu()
221 FP_UNPACK_SP(SA, va.wp + 1); in do_spe_mathemu()
224 FP_UNPACK_SP(SB, vb.wp + 1); in do_spe_mathemu()
227 FP_UNPACK_SP(SA, va.wp + 1); in do_spe_mathemu()
236 vc.wp[1] = va.wp[1] & ~SIGN_BIT_S; in do_spe_mathemu()
240 vc.wp[1] = va.wp[1] | SIGN_BIT_S; in do_spe_mathemu()
244 vc.wp[1] = va.wp[1] ^ SIGN_BIT_S; in do_spe_mathemu()
272 cmp = -1; in do_spe_mathemu()
278 vc.wp[1] = 0; in do_spe_mathemu()
282 FP_TO_INT_ROUND_S(vc.wp[1], SB, 32, in do_spe_mathemu()
302 vc.wp[1] = 0; in do_spe_mathemu()
305 FP_TO_INT_ROUND_S(vc.wp[1], SB, 32, in do_spe_mathemu()
313 vc.wp[1] = 0; in do_spe_mathemu()
316 FP_TO_INT_S(vc.wp[1], SB, 32, in do_spe_mathemu()
329 FP_PACK_SP(vc.wp + 1, SR); in do_spe_mathemu()
403 cmp = -1; in do_spe_mathemu()
409 vc.wp[1] = 0; in do_spe_mathemu()
413 FP_TO_INT_ROUND_D(vc.wp[1], DB, 32, in do_spe_mathemu()
421 FP_UNPACK_SP(SB, vb.wp + 1); in do_spe_mathemu()
444 vc.wp[1] = 0; in do_spe_mathemu()
447 FP_TO_INT_ROUND_D(vc.wp[1], DB, 32, in do_spe_mathemu()
455 vc.wp[1] = 0; in do_spe_mathemu()
458 FP_TO_INT_D(vc.wp[1], DB, 32, in do_spe_mathemu()
496 FP_UNPACK_SP(SA0, va.wp); in do_spe_mathemu()
497 FP_UNPACK_SP(SA1, va.wp + 1); in do_spe_mathemu()
500 FP_UNPACK_SP(SB0, vb.wp); in do_spe_mathemu()
501 FP_UNPACK_SP(SB1, vb.wp + 1); in do_spe_mathemu()
504 FP_UNPACK_SP(SA0, va.wp); in do_spe_mathemu()
505 FP_UNPACK_SP(SA1, va.wp + 1); in do_spe_mathemu()
520 vc.wp[0] = va.wp[0] & ~SIGN_BIT_S; in do_spe_mathemu()
521 vc.wp[1] = va.wp[1] & ~SIGN_BIT_S; in do_spe_mathemu()
525 vc.wp[0] = va.wp[0] | SIGN_BIT_S; in do_spe_mathemu()
526 vc.wp[1] = va.wp[1] | SIGN_BIT_S; in do_spe_mathemu()
530 vc.wp[0] = va.wp[0] ^ SIGN_BIT_S; in do_spe_mathemu()
531 vc.wp[1] = va.wp[1] ^ SIGN_BIT_S; in do_spe_mathemu()
563 cmp = -1; in do_spe_mathemu()
569 vc.wp[0] = 0; in do_spe_mathemu()
573 FP_TO_INT_ROUND_S(vc.wp[0], SB0, 32, in do_spe_mathemu()
577 vc.wp[1] = 0; in do_spe_mathemu()
581 FP_TO_INT_ROUND_S(vc.wp[1], SB1, 32, in do_spe_mathemu()
589 vc.wp[0] = 0; in do_spe_mathemu()
592 FP_TO_INT_ROUND_S(vc.wp[0], SB0, 32, in do_spe_mathemu()
596 vc.wp[1] = 0; in do_spe_mathemu()
599 FP_TO_INT_ROUND_S(vc.wp[1], SB1, 32, in do_spe_mathemu()
607 vc.wp[0] = 0; in do_spe_mathemu()
610 FP_TO_INT_S(vc.wp[0], SB0, 32, in do_spe_mathemu()
614 vc.wp[1] = 0; in do_spe_mathemu()
617 FP_TO_INT_S(vc.wp[1], SB1, 32, in do_spe_mathemu()
633 FP_PACK_SP(vc.wp, SR0); in do_spe_mathemu()
634 FP_PACK_SP(vc.wp + 1, SR1); in do_spe_mathemu()
655 return -EINVAL; in do_spe_mathemu()
659 regs->ccr &= ~(15 << ((7 - ((speinsn >> 23) & 0x7)) << 2)); in do_spe_mathemu()
660 regs->ccr |= (IR << ((7 - ((speinsn >> 23) & 0x7)) << 2)); in do_spe_mathemu()
665 * processor for non-finite input, but was not set before the in do_spe_mathemu()
673 * instruction as they represent the user-visible sticky in do_spe_mathemu()
680 &= ~(FP_EX_INVALID | FP_EX_UNDERFLOW) | current->thread.spefscr_last; in do_spe_mathemu()
683 current->thread.spefscr_last = __FPU_FPSCR; in do_spe_mathemu()
685 current->thread.evr[fc] = vc.wp[0]; in do_spe_mathemu()
686 regs->gpr[fc] = vc.wp[1]; in do_spe_mathemu()
688 pr_debug("ccr = %08lx\n", regs->ccr); in do_spe_mathemu()
691 pr_debug("vc: %08x %08x\n", vc.wp[0], vc.wp[1]); in do_spe_mathemu()
692 pr_debug("va: %08x %08x\n", va.wp[0], va.wp[1]); in do_spe_mathemu()
693 pr_debug("vb: %08x %08x\n", vb.wp[0], vb.wp[1]); in do_spe_mathemu()
695 if (current->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE) { in do_spe_mathemu()
697 && (current->thread.fpexc_mode & PR_FP_EXC_DIV)) in do_spe_mathemu()
700 && (current->thread.fpexc_mode & PR_FP_EXC_OVF)) in do_spe_mathemu()
703 && (current->thread.fpexc_mode & PR_FP_EXC_UND)) in do_spe_mathemu()
706 && (current->thread.fpexc_mode & PR_FP_EXC_RES)) in do_spe_mathemu()
709 && (current->thread.fpexc_mode & PR_FP_EXC_INV)) in do_spe_mathemu()
717 regs_add_return_ip(regs, -4); in do_spe_mathemu()
718 pr_debug("re-issue efp inst: %08lx\n", speinsn); in do_spe_mathemu()
722 …printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst … in do_spe_mathemu()
723 return -ENOSYS; in do_spe_mathemu()
734 if (get_user(speinsn, (unsigned int __user *) regs->nip)) in speround_handler()
735 return -EFAULT; in speround_handler()
737 return -EINVAL; /* not an spe instruction */ in speround_handler()
741 if (type == XCR) return -ENOSYS; in speround_handler()
748 /* No need to round if the result is exact */ in speround_handler()
755 s_lo = regs->gpr[fc] & SIGN_BIT_S; in speround_handler()
756 s_hi = current->thread.evr[fc] & SIGN_BIT_S; in speround_handler()
757 fgpr.wp[0] = current->thread.evr[fc]; in speround_handler()
758 fgpr.wp[1] = regs->gpr[fc]; in speround_handler()
791 if (fgpr.wp[1] == 0) in speround_handler()
792 s_lo = regs->gpr[fb] & SIGN_BIT_S; in speround_handler()
799 if (fgpr.wp[1] == 0) in speround_handler()
800 s_lo = regs->gpr[fb] & SIGN_BIT_S; in speround_handler()
801 if (fgpr.wp[0] == 0) in speround_handler()
802 s_hi = current->thread.evr[fb] & SIGN_BIT_S; in speround_handler()
810 if (fgpr.wp[1] == 0) in speround_handler()
811 s_hi = current->thread.evr[fb] & SIGN_BIT_S; in speround_handler()
819 pr_debug("round fgpr: %08x %08x\n", fgpr.wp[0], fgpr.wp[1]); in speround_handler()
823 * and round toward zero with IEEE-754 complied, we just need in speround_handler()
824 * to handle round toward +Inf and round toward -Inf by software. in speround_handler()
828 if (!s_lo) fgpr.wp[1]++; /* Z > 0, choose Z1 */ in speround_handler()
829 } else { /* round to -Inf */ in speround_handler()
832 fgpr.wp[1]++; /* Z < 0, choose Z2 */ in speround_handler()
834 fgpr.wp[1]--; /* Z < 0, choose Z2 */ in speround_handler()
845 fgpr.wp[1]++; /* Z > 0, choose Z1 */ in speround_handler()
847 } else { /* round to -Inf */ in speround_handler()
852 fgpr.wp[1]--; /* Z < 0, choose Z2 */ in speround_handler()
860 fgpr.wp[1]++; /* Z_low > 0, choose Z1 */ in speround_handler()
862 fgpr.wp[0]++; /* Z_high word > 0, choose Z1 */ in speround_handler()
863 } else { /* round to -Inf */ in speround_handler()
866 fgpr.wp[1]++; /* Z_low < 0, choose Z2 */ in speround_handler()
868 fgpr.wp[1]--; /* Z_low < 0, choose Z2 */ in speround_handler()
872 fgpr.wp[0]++; /* Z_high < 0, choose Z2 */ in speround_handler()
874 fgpr.wp[0]--; /* Z_high < 0, choose Z2 */ in speround_handler()
880 return -EINVAL; in speround_handler()
883 current->thread.evr[fc] = fgpr.wp[0]; in speround_handler()
884 regs->gpr[fc] = fgpr.wp[1]; in speround_handler()
886 pr_debug(" to fgpr: %08x %08x\n", fgpr.wp[0], fgpr.wp[1]); in speround_handler()
888 if (current->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE) in speround_handler()
889 return (current->thread.fpexc_mode & PR_FP_EXC_RES) ? 1 : 0; in speround_handler()