Lines Matching +full:ch +full:- +full:func
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>
182 unsigned long type, func, fc, fa, fb, src, speinsn; in do_spe_mathemu() local
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()
194 func = speinsn & 0x7ff; 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()
233 switch (func) { in do_spe_mathemu()
271 cmp = -1; in do_spe_mathemu()
280 SB_e += (func == EFSCTSF ? 31 : 32); in do_spe_mathemu()
282 (func == EFSCTSF)); in do_spe_mathemu()
305 ((func & 0x3) != 0)); in do_spe_mathemu()
316 ((func & 0x3) != 0)); in do_spe_mathemu()
363 switch (func) { in do_spe_mathemu()
401 cmp = -1; in do_spe_mathemu()
410 DB_e += (func == EFDCTSF ? 31 : 32); in do_spe_mathemu()
412 (func == EFDCTSF)); in do_spe_mathemu()
435 ((func & 0x1) == 0)); in do_spe_mathemu()
446 ((func & 0x3) != 0)); in do_spe_mathemu()
457 ((func & 0x3) != 0)); in do_spe_mathemu()
515 switch (func) { in do_spe_mathemu()
560 cmp = -1; in do_spe_mathemu()
569 SB0_e += (func == EVFSCTSF ? 31 : 32); in do_spe_mathemu()
571 (func == EVFSCTSF)); in do_spe_mathemu()
577 SB1_e += (func == EVFSCTSF ? 31 : 32); in do_spe_mathemu()
579 (func == EVFSCTSF)); in do_spe_mathemu()
590 ((func & 0x3) != 0)); in do_spe_mathemu()
597 ((func & 0x3) != 0)); in do_spe_mathemu()
608 ((func & 0x3) != 0)); in do_spe_mathemu()
615 ((func & 0x3) != 0)); in do_spe_mathemu()
636 int ch, cl; in do_spe_mathemu() local
644 ch = (IR0 == cmp) ? 1 : 0; in do_spe_mathemu()
646 IR = (ch << 3) | (cl << 2) | ((ch | cl) << 1) | in do_spe_mathemu()
647 ((ch & cl) << 0); in do_spe_mathemu()
652 return -EINVAL; in do_spe_mathemu()
656 regs->ccr &= ~(15 << ((7 - ((speinsn >> 23) & 0x7)) << 2)); in do_spe_mathemu()
657 regs->ccr |= (IR << ((7 - ((speinsn >> 23) & 0x7)) << 2)); in do_spe_mathemu()
662 * processor for non-finite input, but was not set before the in do_spe_mathemu()
670 * instruction as they represent the user-visible sticky in do_spe_mathemu()
677 &= ~(FP_EX_INVALID | FP_EX_UNDERFLOW) | current->thread.spefscr_last; in do_spe_mathemu()
680 current->thread.spefscr_last = __FPU_FPSCR; in do_spe_mathemu()
682 current->thread.evr[fc] = vc.wp[0]; in do_spe_mathemu()
683 regs->gpr[fc] = vc.wp[1]; in do_spe_mathemu()
685 pr_debug("ccr = %08lx\n", regs->ccr); in do_spe_mathemu()
692 if (current->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE) { in do_spe_mathemu()
694 && (current->thread.fpexc_mode & PR_FP_EXC_DIV)) in do_spe_mathemu()
697 && (current->thread.fpexc_mode & PR_FP_EXC_OVF)) in do_spe_mathemu()
700 && (current->thread.fpexc_mode & PR_FP_EXC_UND)) in do_spe_mathemu()
703 && (current->thread.fpexc_mode & PR_FP_EXC_RES)) in do_spe_mathemu()
706 && (current->thread.fpexc_mode & PR_FP_EXC_INV)) in do_spe_mathemu()
714 regs->nip -= 4; in do_spe_mathemu()
715 pr_debug("re-issue efp inst: %08lx\n", speinsn); in do_spe_mathemu()
719 …printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst … in do_spe_mathemu()
720 return -ENOSYS; in do_spe_mathemu()
729 unsigned long speinsn, type, fb, fc, fptype, func; in speround_handler() local
731 if (get_user(speinsn, (unsigned int __user *) regs->nip)) in speround_handler()
732 return -EFAULT; in speround_handler()
734 return -EINVAL; /* not an spe instruction */ in speround_handler()
736 func = speinsn & 0x7ff; in speround_handler()
737 type = insn_type(func); in speround_handler()
738 if (type == XCR) return -ENOSYS; in speround_handler()
752 s_lo = regs->gpr[fc] & SIGN_BIT_S; in speround_handler()
753 s_hi = current->thread.evr[fc] & SIGN_BIT_S; in speround_handler()
754 fgpr.wp[0] = current->thread.evr[fc]; in speround_handler()
755 fgpr.wp[1] = regs->gpr[fc]; in speround_handler()
758 switch (func) { in speround_handler()
789 s_lo = regs->gpr[fb] & SIGN_BIT_S; in speround_handler()
797 s_lo = regs->gpr[fb] & SIGN_BIT_S; in speround_handler()
799 s_hi = current->thread.evr[fb] & SIGN_BIT_S; in speround_handler()
808 s_hi = current->thread.evr[fb] & SIGN_BIT_S; in speround_handler()
820 * and round toward zero with IEEE-754 complied, we just need in speround_handler()
821 * to handle round toward +Inf and round toward -Inf by software. in speround_handler()
826 } else { /* round to -Inf */ in speround_handler()
831 fgpr.wp[1]--; /* Z < 0, choose Z2 */ in speround_handler()
844 } else { /* round to -Inf */ in speround_handler()
849 fgpr.wp[1]--; /* Z < 0, choose Z2 */ in speround_handler()
860 } else { /* round to -Inf */ in speround_handler()
865 fgpr.wp[1]--; /* Z_low < 0, choose Z2 */ in speround_handler()
871 fgpr.wp[0]--; /* Z_high < 0, choose Z2 */ in speround_handler()
877 return -EINVAL; in speround_handler()
880 current->thread.evr[fc] = fgpr.wp[0]; in speround_handler()
881 regs->gpr[fc] = fgpr.wp[1]; in speround_handler()
885 if (current->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE) in speround_handler()
886 return (current->thread.fpexc_mode & PR_FP_EXC_RES) ? 1 : 0; in speround_handler()