aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/math-emu/cp1emu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/math-emu/cp1emu.c')
-rw-r--r--arch/mips/math-emu/cp1emu.c934
1 files changed, 340 insertions, 594 deletions
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 7b3c9acae689..736c17a226e9 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator 2 * cp1emu.c: a MIPS coprocessor 1 (FPU) instruction emulator
3 * 3 *
4 * MIPS floating point support 4 * MIPS floating point support
5 * Copyright (C) 1994-2000 Algorithmics Ltd. 5 * Copyright (C) 1994-2000 Algorithmics Ltd.
@@ -18,61 +18,46 @@
18 * 18 *
19 * You should have received a copy of the GNU General Public License along 19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc., 20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 21 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22 * 22 *
23 * A complete emulator for MIPS coprocessor 1 instructions. This is 23 * A complete emulator for MIPS coprocessor 1 instructions. This is
24 * required for #float(switch) or #float(trap), where it catches all 24 * required for #float(switch) or #float(trap), where it catches all
25 * COP1 instructions via the "CoProcessor Unusable" exception. 25 * COP1 instructions via the "CoProcessor Unusable" exception.
26 * 26 *
27 * More surprisingly it is also required for #float(ieee), to help out 27 * More surprisingly it is also required for #float(ieee), to help out
28 * the hardware fpu at the boundaries of the IEEE-754 representation 28 * the hardware FPU at the boundaries of the IEEE-754 representation
29 * (denormalised values, infinities, underflow, etc). It is made 29 * (denormalised values, infinities, underflow, etc). It is made
30 * quite nasty because emulation of some non-COP1 instructions is 30 * quite nasty because emulation of some non-COP1 instructions is
31 * required, e.g. in branch delay slots. 31 * required, e.g. in branch delay slots.
32 * 32 *
33 * Note if you know that you won't have an fpu, then you'll get much 33 * Note if you know that you won't have an FPU, then you'll get much
34 * better performance by compiling with -msoft-float! 34 * better performance by compiling with -msoft-float!
35 */ 35 */
36#include <linux/sched.h> 36#include <linux/sched.h>
37#include <linux/module.h>
38#include <linux/debugfs.h> 37#include <linux/debugfs.h>
38#include <linux/kconfig.h>
39#include <linux/percpu-defs.h>
39#include <linux/perf_event.h> 40#include <linux/perf_event.h>
40 41
42#include <asm/branch.h>
41#include <asm/inst.h> 43#include <asm/inst.h>
42#include <asm/bootinfo.h>
43#include <asm/processor.h>
44#include <asm/ptrace.h> 44#include <asm/ptrace.h>
45#include <asm/signal.h> 45#include <asm/signal.h>
46#include <asm/mipsregs.h> 46#include <asm/uaccess.h>
47
48#include <asm/processor.h>
47#include <asm/fpu_emulator.h> 49#include <asm/fpu_emulator.h>
48#include <asm/fpu.h> 50#include <asm/fpu.h>
49#include <asm/uaccess.h>
50#include <asm/branch.h>
51 51
52#include "ieee754.h" 52#include "ieee754.h"
53 53
54/* Strap kernel emulator for full MIPS IV emulation */
55
56#ifdef __mips
57#undef __mips
58#endif
59#define __mips 4
60
61/* Function which emulates a floating point instruction. */ 54/* Function which emulates a floating point instruction. */
62 55
63static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *, 56static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
64 mips_instruction); 57 mips_instruction);
65 58
66#if __mips >= 4 && __mips != 32
67static int fpux_emu(struct pt_regs *, 59static int fpux_emu(struct pt_regs *,
68 struct mips_fpu_struct *, mips_instruction, void *__user *); 60 struct mips_fpu_struct *, mips_instruction, void *__user *);
69#endif
70
71/* Further private data for which no space exists in mips_fpu_struct */
72
73#ifdef CONFIG_DEBUG_FS
74DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
75#endif
76 61
77/* Control registers */ 62/* Control registers */
78 63
@@ -82,27 +67,6 @@ DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
82/* Determine rounding mode from the RM bits of the FCSR */ 67/* Determine rounding mode from the RM bits of the FCSR */
83#define modeindex(v) ((v) & FPU_CSR_RM) 68#define modeindex(v) ((v) & FPU_CSR_RM)
84 69
85/* microMIPS bitfields */
86#define MM_POOL32A_MINOR_MASK 0x3f
87#define MM_POOL32A_MINOR_SHIFT 0x6
88#define MM_MIPS32_COND_FC 0x30
89
90/* Convert Mips rounding mode (0..3) to IEEE library modes. */
91static const unsigned char ieee_rm[4] = {
92 [FPU_CSR_RN] = IEEE754_RN,
93 [FPU_CSR_RZ] = IEEE754_RZ,
94 [FPU_CSR_RU] = IEEE754_RU,
95 [FPU_CSR_RD] = IEEE754_RD,
96};
97/* Convert IEEE library modes to Mips rounding mode (0..3). */
98static const unsigned char mips_rm[4] = {
99 [IEEE754_RN] = FPU_CSR_RN,
100 [IEEE754_RZ] = FPU_CSR_RZ,
101 [IEEE754_RD] = FPU_CSR_RD,
102 [IEEE754_RU] = FPU_CSR_RU,
103};
104
105#if __mips >= 4
106/* convert condition code register number to csr bit */ 70/* convert condition code register number to csr bit */
107static const unsigned int fpucondbit[8] = { 71static const unsigned int fpucondbit[8] = {
108 FPU_CSR_COND0, 72 FPU_CSR_COND0,
@@ -114,10 +78,6 @@ static const unsigned int fpucondbit[8] = {
114 FPU_CSR_COND6, 78 FPU_CSR_COND6,
115 FPU_CSR_COND7 79 FPU_CSR_COND7
116}; 80};
117#endif
118
119/* (microMIPS) Convert 16-bit register encoding to 32-bit register encoding. */
120static const unsigned int reg16to32map[8] = {16, 17, 2, 3, 4, 5, 6, 7};
121 81
122/* (microMIPS) Convert certain microMIPS instructions to MIPS32 format. */ 82/* (microMIPS) Convert certain microMIPS instructions to MIPS32 format. */
123static const int sd_format[] = {16, 17, 0, 0, 0, 0, 0, 0}; 83static const int sd_format[] = {16, 17, 0, 0, 0, 0, 0, 0};
@@ -466,199 +426,6 @@ static int microMIPS32_to_MIPS32(union mips_instruction *insn_ptr)
466 return 0; 426 return 0;
467} 427}
468 428
469int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
470 unsigned long *contpc)
471{
472 union mips_instruction insn = (union mips_instruction)dec_insn.insn;
473 int bc_false = 0;
474 unsigned int fcr31;
475 unsigned int bit;
476
477 if (!cpu_has_mmips)
478 return 0;
479
480 switch (insn.mm_i_format.opcode) {
481 case mm_pool32a_op:
482 if ((insn.mm_i_format.simmediate & MM_POOL32A_MINOR_MASK) ==
483 mm_pool32axf_op) {
484 switch (insn.mm_i_format.simmediate >>
485 MM_POOL32A_MINOR_SHIFT) {
486 case mm_jalr_op:
487 case mm_jalrhb_op:
488 case mm_jalrs_op:
489 case mm_jalrshb_op:
490 if (insn.mm_i_format.rt != 0) /* Not mm_jr */
491 regs->regs[insn.mm_i_format.rt] =
492 regs->cp0_epc +
493 dec_insn.pc_inc +
494 dec_insn.next_pc_inc;
495 *contpc = regs->regs[insn.mm_i_format.rs];
496 return 1;
497 }
498 }
499 break;
500 case mm_pool32i_op:
501 switch (insn.mm_i_format.rt) {
502 case mm_bltzals_op:
503 case mm_bltzal_op:
504 regs->regs[31] = regs->cp0_epc +
505 dec_insn.pc_inc +
506 dec_insn.next_pc_inc;
507 /* Fall through */
508 case mm_bltz_op:
509 if ((long)regs->regs[insn.mm_i_format.rs] < 0)
510 *contpc = regs->cp0_epc +
511 dec_insn.pc_inc +
512 (insn.mm_i_format.simmediate << 1);
513 else
514 *contpc = regs->cp0_epc +
515 dec_insn.pc_inc +
516 dec_insn.next_pc_inc;
517 return 1;
518 case mm_bgezals_op:
519 case mm_bgezal_op:
520 regs->regs[31] = regs->cp0_epc +
521 dec_insn.pc_inc +
522 dec_insn.next_pc_inc;
523 /* Fall through */
524 case mm_bgez_op:
525 if ((long)regs->regs[insn.mm_i_format.rs] >= 0)
526 *contpc = regs->cp0_epc +
527 dec_insn.pc_inc +
528 (insn.mm_i_format.simmediate << 1);
529 else
530 *contpc = regs->cp0_epc +
531 dec_insn.pc_inc +
532 dec_insn.next_pc_inc;
533 return 1;
534 case mm_blez_op:
535 if ((long)regs->regs[insn.mm_i_format.rs] <= 0)
536 *contpc = regs->cp0_epc +
537 dec_insn.pc_inc +
538 (insn.mm_i_format.simmediate << 1);
539 else
540 *contpc = regs->cp0_epc +
541 dec_insn.pc_inc +
542 dec_insn.next_pc_inc;
543 return 1;
544 case mm_bgtz_op:
545 if ((long)regs->regs[insn.mm_i_format.rs] <= 0)
546 *contpc = regs->cp0_epc +
547 dec_insn.pc_inc +
548 (insn.mm_i_format.simmediate << 1);
549 else
550 *contpc = regs->cp0_epc +
551 dec_insn.pc_inc +
552 dec_insn.next_pc_inc;
553 return 1;
554 case mm_bc2f_op:
555 case mm_bc1f_op:
556 bc_false = 1;
557 /* Fall through */
558 case mm_bc2t_op:
559 case mm_bc1t_op:
560 preempt_disable();
561 if (is_fpu_owner())
562 asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
563 else
564 fcr31 = current->thread.fpu.fcr31;
565 preempt_enable();
566
567 if (bc_false)
568 fcr31 = ~fcr31;
569
570 bit = (insn.mm_i_format.rs >> 2);
571 bit += (bit != 0);
572 bit += 23;
573 if (fcr31 & (1 << bit))
574 *contpc = regs->cp0_epc +
575 dec_insn.pc_inc +
576 (insn.mm_i_format.simmediate << 1);
577 else
578 *contpc = regs->cp0_epc +
579 dec_insn.pc_inc + dec_insn.next_pc_inc;
580 return 1;
581 }
582 break;
583 case mm_pool16c_op:
584 switch (insn.mm_i_format.rt) {
585 case mm_jalr16_op:
586 case mm_jalrs16_op:
587 regs->regs[31] = regs->cp0_epc +
588 dec_insn.pc_inc + dec_insn.next_pc_inc;
589 /* Fall through */
590 case mm_jr16_op:
591 *contpc = regs->regs[insn.mm_i_format.rs];
592 return 1;
593 }
594 break;
595 case mm_beqz16_op:
596 if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] == 0)
597 *contpc = regs->cp0_epc +
598 dec_insn.pc_inc +
599 (insn.mm_b1_format.simmediate << 1);
600 else
601 *contpc = regs->cp0_epc +
602 dec_insn.pc_inc + dec_insn.next_pc_inc;
603 return 1;
604 case mm_bnez16_op:
605 if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] != 0)
606 *contpc = regs->cp0_epc +
607 dec_insn.pc_inc +
608 (insn.mm_b1_format.simmediate << 1);
609 else
610 *contpc = regs->cp0_epc +
611 dec_insn.pc_inc + dec_insn.next_pc_inc;
612 return 1;
613 case mm_b16_op:
614 *contpc = regs->cp0_epc + dec_insn.pc_inc +
615 (insn.mm_b0_format.simmediate << 1);
616 return 1;
617 case mm_beq32_op:
618 if (regs->regs[insn.mm_i_format.rs] ==
619 regs->regs[insn.mm_i_format.rt])
620 *contpc = regs->cp0_epc +
621 dec_insn.pc_inc +
622 (insn.mm_i_format.simmediate << 1);
623 else
624 *contpc = regs->cp0_epc +
625 dec_insn.pc_inc +
626 dec_insn.next_pc_inc;
627 return 1;
628 case mm_bne32_op:
629 if (regs->regs[insn.mm_i_format.rs] !=
630 regs->regs[insn.mm_i_format.rt])
631 *contpc = regs->cp0_epc +
632 dec_insn.pc_inc +
633 (insn.mm_i_format.simmediate << 1);
634 else
635 *contpc = regs->cp0_epc +
636 dec_insn.pc_inc + dec_insn.next_pc_inc;
637 return 1;
638 case mm_jalx32_op:
639 regs->regs[31] = regs->cp0_epc +
640 dec_insn.pc_inc + dec_insn.next_pc_inc;
641 *contpc = regs->cp0_epc + dec_insn.pc_inc;
642 *contpc >>= 28;
643 *contpc <<= 28;
644 *contpc |= (insn.j_format.target << 2);
645 return 1;
646 case mm_jals32_op:
647 case mm_jal32_op:
648 regs->regs[31] = regs->cp0_epc +
649 dec_insn.pc_inc + dec_insn.next_pc_inc;
650 /* Fall through */
651 case mm_j32_op:
652 *contpc = regs->cp0_epc + dec_insn.pc_inc;
653 *contpc >>= 27;
654 *contpc <<= 27;
655 *contpc |= (insn.j_format.target << 1);
656 set_isa16_mode(*contpc);
657 return 1;
658 }
659 return 0;
660}
661
662/* 429/*
663 * Redundant with logic already in kernel/branch.c, 430 * Redundant with logic already in kernel/branch.c,
664 * embedded in compute_return_epc. At some point, 431 * embedded in compute_return_epc. At some point,
@@ -817,7 +584,11 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
817 if (insn.i_format.rs == bc_op) { 584 if (insn.i_format.rs == bc_op) {
818 preempt_disable(); 585 preempt_disable();
819 if (is_fpu_owner()) 586 if (is_fpu_owner())
820 asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); 587 asm volatile(
588 ".set push\n"
589 "\t.set mips1\n"
590 "\tcfc1\t%0,$31\n"
591 "\t.set pop" : "=r" (fcr31));
821 else 592 else
822 fcr31 = current->thread.fpu.fcr31; 593 fcr31 = current->thread.fpu.fcr31;
823 preempt_enable(); 594 preempt_enable();
@@ -867,23 +638,25 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
867 */ 638 */
868static inline int cop1_64bit(struct pt_regs *xcp) 639static inline int cop1_64bit(struct pt_regs *xcp)
869{ 640{
870#if defined(CONFIG_64BIT) && !defined(CONFIG_MIPS32_O32) 641 if (config_enabled(CONFIG_64BIT) && !config_enabled(CONFIG_MIPS32_O32))
871 return 1; 642 return 1;
872#elif defined(CONFIG_32BIT) && !defined(CONFIG_MIPS_O32_FP64_SUPPORT) 643 else if (config_enabled(CONFIG_32BIT) &&
873 return 0; 644 !config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
874#else 645 return 0;
646
875 return !test_thread_flag(TIF_32BIT_FPREGS); 647 return !test_thread_flag(TIF_32BIT_FPREGS);
876#endif
877} 648}
878 649
879#define SIFROMREG(si, x) do { \ 650#define SIFROMREG(si, x) \
651do { \
880 if (cop1_64bit(xcp)) \ 652 if (cop1_64bit(xcp)) \
881 (si) = get_fpr32(&ctx->fpr[x], 0); \ 653 (si) = get_fpr32(&ctx->fpr[x], 0); \
882 else \ 654 else \
883 (si) = get_fpr32(&ctx->fpr[(x) & ~1], (x) & 1); \ 655 (si) = get_fpr32(&ctx->fpr[(x) & ~1], (x) & 1); \
884} while (0) 656} while (0)
885 657
886#define SITOREG(si, x) do { \ 658#define SITOREG(si, x) \
659do { \
887 if (cop1_64bit(xcp)) { \ 660 if (cop1_64bit(xcp)) { \
888 unsigned i; \ 661 unsigned i; \
889 set_fpr32(&ctx->fpr[x], 0, si); \ 662 set_fpr32(&ctx->fpr[x], 0, si); \
@@ -896,17 +669,19 @@ static inline int cop1_64bit(struct pt_regs *xcp)
896 669
897#define SIFROMHREG(si, x) ((si) = get_fpr32(&ctx->fpr[x], 1)) 670#define SIFROMHREG(si, x) ((si) = get_fpr32(&ctx->fpr[x], 1))
898 671
899#define SITOHREG(si, x) do { \ 672#define SITOHREG(si, x) \
673do { \
900 unsigned i; \ 674 unsigned i; \
901 set_fpr32(&ctx->fpr[x], 1, si); \ 675 set_fpr32(&ctx->fpr[x], 1, si); \
902 for (i = 2; i < ARRAY_SIZE(ctx->fpr[x].val32); i++) \ 676 for (i = 2; i < ARRAY_SIZE(ctx->fpr[x].val32); i++) \
903 set_fpr32(&ctx->fpr[x], i, 0); \ 677 set_fpr32(&ctx->fpr[x], i, 0); \
904} while (0) 678} while (0)
905 679
906#define DIFROMREG(di, x) \ 680#define DIFROMREG(di, x) \
907 ((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0)) 681 ((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0))
908 682
909#define DITOREG(di, x) do { \ 683#define DITOREG(di, x) \
684do { \
910 unsigned fpr, i; \ 685 unsigned fpr, i; \
911 fpr = (x) & ~(cop1_64bit(xcp) == 0); \ 686 fpr = (x) & ~(cop1_64bit(xcp) == 0); \
912 set_fpr64(&ctx->fpr[fpr], 0, di); \ 687 set_fpr64(&ctx->fpr[fpr], 0, di); \
@@ -927,23 +702,36 @@ static inline int cop1_64bit(struct pt_regs *xcp)
927static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, 702static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
928 struct mm_decoded_insn dec_insn, void *__user *fault_addr) 703 struct mm_decoded_insn dec_insn, void *__user *fault_addr)
929{ 704{
930 mips_instruction ir;
931 unsigned long contpc = xcp->cp0_epc + dec_insn.pc_inc; 705 unsigned long contpc = xcp->cp0_epc + dec_insn.pc_inc;
932 unsigned int cond; 706 unsigned int cond, cbit;
933 int pc_inc; 707 mips_instruction ir;
708 int likely, pc_inc;
709 u32 __user *wva;
710 u64 __user *dva;
711 u32 value;
712 u32 wval;
713 u64 dval;
714 int sig;
715
716 /*
717 * These are giving gcc a gentle hint about what to expect in
718 * dec_inst in order to do better optimization.
719 */
720 if (!cpu_has_mmips && dec_insn.micro_mips_mode)
721 unreachable();
934 722
935 /* XXX NEC Vr54xx bug workaround */ 723 /* XXX NEC Vr54xx bug workaround */
936 if (xcp->cp0_cause & CAUSEF_BD) { 724 if (delay_slot(xcp)) {
937 if (dec_insn.micro_mips_mode) { 725 if (dec_insn.micro_mips_mode) {
938 if (!mm_isBranchInstr(xcp, dec_insn, &contpc)) 726 if (!mm_isBranchInstr(xcp, dec_insn, &contpc))
939 xcp->cp0_cause &= ~CAUSEF_BD; 727 clear_delay_slot(xcp);
940 } else { 728 } else {
941 if (!isBranchInstr(xcp, dec_insn, &contpc)) 729 if (!isBranchInstr(xcp, dec_insn, &contpc))
942 xcp->cp0_cause &= ~CAUSEF_BD; 730 clear_delay_slot(xcp);
943 } 731 }
944 } 732 }
945 733
946 if (xcp->cp0_cause & CAUSEF_BD) { 734 if (delay_slot(xcp)) {
947 /* 735 /*
948 * The instruction to be emulated is in a branch delay slot 736 * The instruction to be emulated is in a branch delay slot
949 * which means that we have to emulate the branch instruction 737 * which means that we have to emulate the branch instruction
@@ -985,96 +773,85 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
985 return SIGILL; 773 return SIGILL;
986 } 774 }
987 775
988 emul: 776emul:
989 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, xcp, 0); 777 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, xcp, 0);
990 MIPS_FPU_EMU_INC_STATS(emulated); 778 MIPS_FPU_EMU_INC_STATS(emulated);
991 switch (MIPSInst_OPCODE(ir)) { 779 switch (MIPSInst_OPCODE(ir)) {
992 case ldc1_op:{ 780 case ldc1_op:
993 u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + 781 dva = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
994 MIPSInst_SIMM(ir)); 782 MIPSInst_SIMM(ir));
995 u64 val;
996
997 MIPS_FPU_EMU_INC_STATS(loads); 783 MIPS_FPU_EMU_INC_STATS(loads);
998 784
999 if (!access_ok(VERIFY_READ, va, sizeof(u64))) { 785 if (!access_ok(VERIFY_READ, dva, sizeof(u64))) {
1000 MIPS_FPU_EMU_INC_STATS(errors); 786 MIPS_FPU_EMU_INC_STATS(errors);
1001 *fault_addr = va; 787 *fault_addr = dva;
1002 return SIGBUS; 788 return SIGBUS;
1003 } 789 }
1004 if (__get_user(val, va)) { 790 if (__get_user(dval, dva)) {
1005 MIPS_FPU_EMU_INC_STATS(errors); 791 MIPS_FPU_EMU_INC_STATS(errors);
1006 *fault_addr = va; 792 *fault_addr = dva;
1007 return SIGSEGV; 793 return SIGSEGV;
1008 } 794 }
1009 DITOREG(val, MIPSInst_RT(ir)); 795 DITOREG(dval, MIPSInst_RT(ir));
1010 break; 796 break;
1011 }
1012
1013 case sdc1_op:{
1014 u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
1015 MIPSInst_SIMM(ir));
1016 u64 val;
1017 797
798 case sdc1_op:
799 dva = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
800 MIPSInst_SIMM(ir));
1018 MIPS_FPU_EMU_INC_STATS(stores); 801 MIPS_FPU_EMU_INC_STATS(stores);
1019 DIFROMREG(val, MIPSInst_RT(ir)); 802 DIFROMREG(dval, MIPSInst_RT(ir));
1020 if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) { 803 if (!access_ok(VERIFY_WRITE, dva, sizeof(u64))) {
1021 MIPS_FPU_EMU_INC_STATS(errors); 804 MIPS_FPU_EMU_INC_STATS(errors);
1022 *fault_addr = va; 805 *fault_addr = dva;
1023 return SIGBUS; 806 return SIGBUS;
1024 } 807 }
1025 if (__put_user(val, va)) { 808 if (__put_user(dval, dva)) {
1026 MIPS_FPU_EMU_INC_STATS(errors); 809 MIPS_FPU_EMU_INC_STATS(errors);
1027 *fault_addr = va; 810 *fault_addr = dva;
1028 return SIGSEGV; 811 return SIGSEGV;
1029 } 812 }
1030 break; 813 break;
1031 }
1032
1033 case lwc1_op:{
1034 u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] +
1035 MIPSInst_SIMM(ir));
1036 u32 val;
1037 814
815 case lwc1_op:
816 wva = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] +
817 MIPSInst_SIMM(ir));
1038 MIPS_FPU_EMU_INC_STATS(loads); 818 MIPS_FPU_EMU_INC_STATS(loads);
1039 if (!access_ok(VERIFY_READ, va, sizeof(u32))) { 819 if (!access_ok(VERIFY_READ, wva, sizeof(u32))) {
1040 MIPS_FPU_EMU_INC_STATS(errors); 820 MIPS_FPU_EMU_INC_STATS(errors);
1041 *fault_addr = va; 821 *fault_addr = wva;
1042 return SIGBUS; 822 return SIGBUS;
1043 } 823 }
1044 if (__get_user(val, va)) { 824 if (__get_user(wval, wva)) {
1045 MIPS_FPU_EMU_INC_STATS(errors); 825 MIPS_FPU_EMU_INC_STATS(errors);
1046 *fault_addr = va; 826 *fault_addr = wva;
1047 return SIGSEGV; 827 return SIGSEGV;
1048 } 828 }
1049 SITOREG(val, MIPSInst_RT(ir)); 829 SITOREG(wval, MIPSInst_RT(ir));
1050 break; 830 break;
1051 }
1052
1053 case swc1_op:{
1054 u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] +
1055 MIPSInst_SIMM(ir));
1056 u32 val;
1057 831
832 case swc1_op:
833 wva = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] +
834 MIPSInst_SIMM(ir));
1058 MIPS_FPU_EMU_INC_STATS(stores); 835 MIPS_FPU_EMU_INC_STATS(stores);
1059 SIFROMREG(val, MIPSInst_RT(ir)); 836 SIFROMREG(wval, MIPSInst_RT(ir));
1060 if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) { 837 if (!access_ok(VERIFY_WRITE, wva, sizeof(u32))) {
1061 MIPS_FPU_EMU_INC_STATS(errors); 838 MIPS_FPU_EMU_INC_STATS(errors);
1062 *fault_addr = va; 839 *fault_addr = wva;
1063 return SIGBUS; 840 return SIGBUS;
1064 } 841 }
1065 if (__put_user(val, va)) { 842 if (__put_user(wval, wva)) {
1066 MIPS_FPU_EMU_INC_STATS(errors); 843 MIPS_FPU_EMU_INC_STATS(errors);
1067 *fault_addr = va; 844 *fault_addr = wva;
1068 return SIGSEGV; 845 return SIGSEGV;
1069 } 846 }
1070 break; 847 break;
1071 }
1072 848
1073 case cop1_op: 849 case cop1_op:
1074 switch (MIPSInst_RS(ir)) { 850 switch (MIPSInst_RS(ir)) {
1075
1076#if defined(__mips64)
1077 case dmfc_op: 851 case dmfc_op:
852 if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
853 return SIGILL;
854
1078 /* copregister fs -> gpr[rt] */ 855 /* copregister fs -> gpr[rt] */
1079 if (MIPSInst_RT(ir) != 0) { 856 if (MIPSInst_RT(ir) != 0) {
1080 DIFROMREG(xcp->regs[MIPSInst_RT(ir)], 857 DIFROMREG(xcp->regs[MIPSInst_RT(ir)],
@@ -1083,10 +860,12 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1083 break; 860 break;
1084 861
1085 case dmtc_op: 862 case dmtc_op:
863 if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
864 return SIGILL;
865
1086 /* copregister fs <- rt */ 866 /* copregister fs <- rt */
1087 DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir)); 867 DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
1088 break; 868 break;
1089#endif
1090 869
1091 case mfhc_op: 870 case mfhc_op:
1092 if (!cpu_has_mips_r2) 871 if (!cpu_has_mips_r2)
@@ -1120,19 +899,14 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1120 SITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir)); 899 SITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
1121 break; 900 break;
1122 901
1123 case cfc_op:{ 902 case cfc_op:
1124 /* cop control register rd -> gpr[rt] */ 903 /* cop control register rd -> gpr[rt] */
1125 u32 value;
1126
1127 if (MIPSInst_RD(ir) == FPCREG_CSR) { 904 if (MIPSInst_RD(ir) == FPCREG_CSR) {
1128 value = ctx->fcr31; 905 value = ctx->fcr31;
1129 value = (value & ~FPU_CSR_RM) | 906 value = (value & ~FPU_CSR_RM) | modeindex(value);
1130 mips_rm[modeindex(value)]; 907 pr_debug("%p gpr[%d]<-csr=%08x\n",
1131#ifdef CSRTRACE 908 (void *) (xcp->cp0_epc),
1132 printk("%p gpr[%d]<-csr=%08x\n", 909 MIPSInst_RT(ir), value);
1133 (void *) (xcp->cp0_epc),
1134 MIPSInst_RT(ir), value);
1135#endif
1136 } 910 }
1137 else if (MIPSInst_RD(ir) == FPCREG_RID) 911 else if (MIPSInst_RD(ir) == FPCREG_RID)
1138 value = 0; 912 value = 0;
@@ -1141,12 +915,9 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1141 if (MIPSInst_RT(ir)) 915 if (MIPSInst_RT(ir))
1142 xcp->regs[MIPSInst_RT(ir)] = value; 916 xcp->regs[MIPSInst_RT(ir)] = value;
1143 break; 917 break;
1144 }
1145 918
1146 case ctc_op:{ 919 case ctc_op:
1147 /* copregister rd <- rt */ 920 /* copregister rd <- rt */
1148 u32 value;
1149
1150 if (MIPSInst_RT(ir) == 0) 921 if (MIPSInst_RT(ir) == 0)
1151 value = 0; 922 value = 0;
1152 else 923 else
@@ -1155,37 +926,33 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1155 /* we only have one writable control reg 926 /* we only have one writable control reg
1156 */ 927 */
1157 if (MIPSInst_RD(ir) == FPCREG_CSR) { 928 if (MIPSInst_RD(ir) == FPCREG_CSR) {
1158#ifdef CSRTRACE 929 pr_debug("%p gpr[%d]->csr=%08x\n",
1159 printk("%p gpr[%d]->csr=%08x\n", 930 (void *) (xcp->cp0_epc),
1160 (void *) (xcp->cp0_epc), 931 MIPSInst_RT(ir), value);
1161 MIPSInst_RT(ir), value);
1162#endif
1163 932
1164 /* 933 /*
1165 * Don't write reserved bits, 934 * Don't write reserved bits,
1166 * and convert to ieee library modes 935 * and convert to ieee library modes
1167 */ 936 */
1168 ctx->fcr31 = (value & 937 ctx->fcr31 = (value & ~(FPU_CSR_RSVD | FPU_CSR_RM)) |
1169 ~(FPU_CSR_RSVD | FPU_CSR_RM)) | 938 modeindex(value);
1170 ieee_rm[modeindex(value)];
1171 } 939 }
1172 if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { 940 if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
1173 return SIGFPE; 941 return SIGFPE;
1174 } 942 }
1175 break; 943 break;
1176 }
1177 944
1178 case bc_op:{ 945 case bc_op:
1179 int likely = 0; 946 if (delay_slot(xcp))
1180
1181 if (xcp->cp0_cause & CAUSEF_BD)
1182 return SIGILL; 947 return SIGILL;
1183 948
1184#if __mips >= 4 949 if (cpu_has_mips_4_5_r)
1185 cond = ctx->fcr31 & fpucondbit[MIPSInst_RT(ir) >> 2]; 950 cbit = fpucondbit[MIPSInst_RT(ir) >> 2];
1186#else 951 else
1187 cond = ctx->fcr31 & FPU_CSR_COND; 952 cbit = FPU_CSR_COND;
1188#endif 953 cond = ctx->fcr31 & cbit;
954
955 likely = 0;
1189 switch (MIPSInst_RT(ir) & 3) { 956 switch (MIPSInst_RT(ir) & 3) {
1190 case bcfl_op: 957 case bcfl_op:
1191 likely = 1; 958 likely = 1;
@@ -1201,10 +968,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1201 return SIGILL; 968 return SIGILL;
1202 } 969 }
1203 970
1204 xcp->cp0_cause |= CAUSEF_BD; 971 set_delay_slot(xcp);
1205 if (cond) { 972 if (cond) {
1206 /* branch taken: emulate dslot 973 /*
1207 * instruction 974 * Branch taken: emulate dslot instruction
1208 */ 975 */
1209 xcp->cp0_epc += dec_insn.pc_inc; 976 xcp->cp0_epc += dec_insn.pc_inc;
1210 977
@@ -1238,23 +1005,37 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1238 1005
1239 switch (MIPSInst_OPCODE(ir)) { 1006 switch (MIPSInst_OPCODE(ir)) {
1240 case lwc1_op: 1007 case lwc1_op:
1008 goto emul;
1009
1241 case swc1_op: 1010 case swc1_op:
1242#if (__mips >= 2 || defined(__mips64)) 1011 goto emul;
1012
1243 case ldc1_op: 1013 case ldc1_op:
1244 case sdc1_op: 1014 case sdc1_op:
1245#endif 1015 if (cpu_has_mips_2_3_4_5 ||
1016 cpu_has_mips64)
1017 goto emul;
1018
1019 return SIGILL;
1020 goto emul;
1021
1246 case cop1_op: 1022 case cop1_op:
1247#if __mips >= 4 && __mips != 32
1248 case cop1x_op:
1249#endif
1250 /* its one of ours */
1251 goto emul; 1023 goto emul;
1252#if __mips >= 4 1024
1025 case cop1x_op:
1026 if (cpu_has_mips_4_5 || cpu_has_mips64)
1027 /* its one of ours */
1028 goto emul;
1029
1030 return SIGILL;
1031
1253 case spec_op: 1032 case spec_op:
1033 if (!cpu_has_mips_4_5_r)
1034 return SIGILL;
1035
1254 if (MIPSInst_FUNC(ir) == movc_op) 1036 if (MIPSInst_FUNC(ir) == movc_op)
1255 goto emul; 1037 goto emul;
1256 break; 1038 break;
1257#endif
1258 } 1039 }
1259 1040
1260 /* 1041 /*
@@ -1262,10 +1043,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1262 * instruction in the dslot 1043 * instruction in the dslot
1263 */ 1044 */
1264 return mips_dsemul(xcp, ir, contpc); 1045 return mips_dsemul(xcp, ir, contpc);
1265 } 1046 } else if (likely) { /* branch not taken */
1266 else {
1267 /* branch not taken */
1268 if (likely) {
1269 /* 1047 /*
1270 * branch likely nullifies 1048 * branch likely nullifies
1271 * dslot if not taken 1049 * dslot if not taken
@@ -1277,34 +1055,31 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1277 * dslot as normal insn 1055 * dslot as normal insn
1278 */ 1056 */
1279 } 1057 }
1280 }
1281 break; 1058 break;
1282 }
1283 1059
1284 default: 1060 default:
1285 if (!(MIPSInst_RS(ir) & 0x10)) 1061 if (!(MIPSInst_RS(ir) & 0x10))
1286 return SIGILL; 1062 return SIGILL;
1287 {
1288 int sig;
1289 1063
1290 /* a real fpu computation instruction */ 1064 /* a real fpu computation instruction */
1291 if ((sig = fpu_emu(xcp, ctx, ir))) 1065 if ((sig = fpu_emu(xcp, ctx, ir)))
1292 return sig; 1066 return sig;
1293 }
1294 } 1067 }
1295 break; 1068 break;
1296 1069
1297#if __mips >= 4 && __mips != 32 1070 case cop1x_op:
1298 case cop1x_op:{ 1071 if (!cpu_has_mips_4_5 && !cpu_has_mips64)
1299 int sig = fpux_emu(xcp, ctx, ir, fault_addr); 1072 return SIGILL;
1073
1074 sig = fpux_emu(xcp, ctx, ir, fault_addr);
1300 if (sig) 1075 if (sig)
1301 return sig; 1076 return sig;
1302 break; 1077 break;
1303 }
1304#endif
1305 1078
1306#if __mips >= 4
1307 case spec_op: 1079 case spec_op:
1080 if (!cpu_has_mips_4_5_r)
1081 return SIGILL;
1082
1308 if (MIPSInst_FUNC(ir) != movc_op) 1083 if (MIPSInst_FUNC(ir) != movc_op)
1309 return SIGILL; 1084 return SIGILL;
1310 cond = fpucondbit[MIPSInst_RT(ir) >> 2]; 1085 cond = fpucondbit[MIPSInst_RT(ir) >> 2];
@@ -1312,8 +1087,6 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1312 xcp->regs[MIPSInst_RD(ir)] = 1087 xcp->regs[MIPSInst_RD(ir)] =
1313 xcp->regs[MIPSInst_RS(ir)]; 1088 xcp->regs[MIPSInst_RS(ir)];
1314 break; 1089 break;
1315#endif
1316
1317 default: 1090 default:
1318sigill: 1091sigill:
1319 return SIGILL; 1092 return SIGILL;
@@ -1321,7 +1094,7 @@ sigill:
1321 1094
1322 /* we did it !! */ 1095 /* we did it !! */
1323 xcp->cp0_epc = contpc; 1096 xcp->cp0_epc = contpc;
1324 xcp->cp0_cause &= ~CAUSEF_BD; 1097 clear_delay_slot(xcp);
1325 1098
1326 return 0; 1099 return 0;
1327} 1100}
@@ -1342,44 +1115,42 @@ static const unsigned char cmptab[8] = {
1342}; 1115};
1343 1116
1344 1117
1345#if __mips >= 4 && __mips != 32
1346
1347/* 1118/*
1348 * Additional MIPS4 instructions 1119 * Additional MIPS4 instructions
1349 */ 1120 */
1350 1121
1351#define DEF3OP(name, p, f1, f2, f3) \ 1122#define DEF3OP(name, p, f1, f2, f3) \
1352static ieee754##p fpemu_##p##_##name(ieee754##p r, ieee754##p s, \ 1123static union ieee754##p fpemu_##p##_##name(union ieee754##p r, \
1353 ieee754##p t) \ 1124 union ieee754##p s, union ieee754##p t) \
1354{ \ 1125{ \
1355 struct _ieee754_csr ieee754_csr_save; \ 1126 struct _ieee754_csr ieee754_csr_save; \
1356 s = f1(s, t); \ 1127 s = f1(s, t); \
1357 ieee754_csr_save = ieee754_csr; \ 1128 ieee754_csr_save = ieee754_csr; \
1358 s = f2(s, r); \ 1129 s = f2(s, r); \
1359 ieee754_csr_save.cx |= ieee754_csr.cx; \ 1130 ieee754_csr_save.cx |= ieee754_csr.cx; \
1360 ieee754_csr_save.sx |= ieee754_csr.sx; \ 1131 ieee754_csr_save.sx |= ieee754_csr.sx; \
1361 s = f3(s); \ 1132 s = f3(s); \
1362 ieee754_csr.cx |= ieee754_csr_save.cx; \ 1133 ieee754_csr.cx |= ieee754_csr_save.cx; \
1363 ieee754_csr.sx |= ieee754_csr_save.sx; \ 1134 ieee754_csr.sx |= ieee754_csr_save.sx; \
1364 return s; \ 1135 return s; \
1365} 1136}
1366 1137
1367static ieee754dp fpemu_dp_recip(ieee754dp d) 1138static union ieee754dp fpemu_dp_recip(union ieee754dp d)
1368{ 1139{
1369 return ieee754dp_div(ieee754dp_one(0), d); 1140 return ieee754dp_div(ieee754dp_one(0), d);
1370} 1141}
1371 1142
1372static ieee754dp fpemu_dp_rsqrt(ieee754dp d) 1143static union ieee754dp fpemu_dp_rsqrt(union ieee754dp d)
1373{ 1144{
1374 return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d)); 1145 return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d));
1375} 1146}
1376 1147
1377static ieee754sp fpemu_sp_recip(ieee754sp s) 1148static union ieee754sp fpemu_sp_recip(union ieee754sp s)
1378{ 1149{
1379 return ieee754sp_div(ieee754sp_one(0), s); 1150 return ieee754sp_div(ieee754sp_one(0), s);
1380} 1151}
1381 1152
1382static ieee754sp fpemu_sp_rsqrt(ieee754sp s) 1153static union ieee754sp fpemu_sp_rsqrt(union ieee754sp s)
1383{ 1154{
1384 return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s)); 1155 return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s));
1385} 1156}
@@ -1403,8 +1174,8 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1403 switch (MIPSInst_FMA_FFMT(ir)) { 1174 switch (MIPSInst_FMA_FFMT(ir)) {
1404 case s_fmt:{ /* 0 */ 1175 case s_fmt:{ /* 0 */
1405 1176
1406 ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp); 1177 union ieee754sp(*handler) (union ieee754sp, union ieee754sp, union ieee754sp);
1407 ieee754sp fd, fr, fs, ft; 1178 union ieee754sp fd, fr, fs, ft;
1408 u32 __user *va; 1179 u32 __user *va;
1409 u32 val; 1180 u32 val;
1410 1181
@@ -1467,18 +1238,26 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1467 SPTOREG(fd, MIPSInst_FD(ir)); 1238 SPTOREG(fd, MIPSInst_FD(ir));
1468 1239
1469 copcsr: 1240 copcsr:
1470 if (ieee754_cxtest(IEEE754_INEXACT)) 1241 if (ieee754_cxtest(IEEE754_INEXACT)) {
1242 MIPS_FPU_EMU_INC_STATS(ieee754_inexact);
1471 rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; 1243 rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
1472 if (ieee754_cxtest(IEEE754_UNDERFLOW)) 1244 }
1245 if (ieee754_cxtest(IEEE754_UNDERFLOW)) {
1246 MIPS_FPU_EMU_INC_STATS(ieee754_underflow);
1473 rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S; 1247 rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
1474 if (ieee754_cxtest(IEEE754_OVERFLOW)) 1248 }
1249 if (ieee754_cxtest(IEEE754_OVERFLOW)) {
1250 MIPS_FPU_EMU_INC_STATS(ieee754_overflow);
1475 rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; 1251 rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
1476 if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) 1252 }
1253 if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) {
1254 MIPS_FPU_EMU_INC_STATS(ieee754_invalidop);
1477 rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S; 1255 rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S;
1256 }
1478 1257
1479 ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr; 1258 ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr;
1480 if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { 1259 if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
1481 /*printk ("SIGFPE: fpu csr = %08x\n", 1260 /*printk ("SIGFPE: FPU csr = %08x\n",
1482 ctx->fcr31); */ 1261 ctx->fcr31); */
1483 return SIGFPE; 1262 return SIGFPE;
1484 } 1263 }
@@ -1492,8 +1271,8 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1492 } 1271 }
1493 1272
1494 case d_fmt:{ /* 1 */ 1273 case d_fmt:{ /* 1 */
1495 ieee754dp(*handler) (ieee754dp, ieee754dp, ieee754dp); 1274 union ieee754dp(*handler) (union ieee754dp, union ieee754dp, union ieee754dp);
1496 ieee754dp fd, fr, fs, ft; 1275 union ieee754dp fd, fr, fs, ft;
1497 u64 __user *va; 1276 u64 __user *va;
1498 u64 val; 1277 u64 val;
1499 1278
@@ -1574,7 +1353,6 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1574 1353
1575 return 0; 1354 return 0;
1576} 1355}
1577#endif
1578 1356
1579 1357
1580 1358
@@ -1586,23 +1364,25 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1586{ 1364{
1587 int rfmt; /* resulting format */ 1365 int rfmt; /* resulting format */
1588 unsigned rcsr = 0; /* resulting csr */ 1366 unsigned rcsr = 0; /* resulting csr */
1367 unsigned int oldrm;
1368 unsigned int cbit;
1589 unsigned cond; 1369 unsigned cond;
1590 union { 1370 union {
1591 ieee754dp d; 1371 union ieee754dp d;
1592 ieee754sp s; 1372 union ieee754sp s;
1593 int w; 1373 int w;
1594#ifdef __mips64
1595 s64 l; 1374 s64 l;
1596#endif
1597 } rv; /* resulting value */ 1375 } rv; /* resulting value */
1376 u64 bits;
1598 1377
1599 MIPS_FPU_EMU_INC_STATS(cp1ops); 1378 MIPS_FPU_EMU_INC_STATS(cp1ops);
1600 switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) { 1379 switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
1601 case s_fmt:{ /* 0 */ 1380 case s_fmt: { /* 0 */
1602 union { 1381 union {
1603 ieee754sp(*b) (ieee754sp, ieee754sp); 1382 union ieee754sp(*b) (union ieee754sp, union ieee754sp);
1604 ieee754sp(*u) (ieee754sp); 1383 union ieee754sp(*u) (union ieee754sp);
1605 } handler; 1384 } handler;
1385 union ieee754sp fs, ft;
1606 1386
1607 switch (MIPSInst_FUNC(ir)) { 1387 switch (MIPSInst_FUNC(ir)) {
1608 /* binary ops */ 1388 /* binary ops */
@@ -1620,148 +1400,167 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1620 goto scopbop; 1400 goto scopbop;
1621 1401
1622 /* unary ops */ 1402 /* unary ops */
1623#if __mips >= 2 || defined(__mips64)
1624 case fsqrt_op: 1403 case fsqrt_op:
1404 if (!cpu_has_mips_4_5_r)
1405 return SIGILL;
1406
1625 handler.u = ieee754sp_sqrt; 1407 handler.u = ieee754sp_sqrt;
1626 goto scopuop; 1408 goto scopuop;
1627#endif 1409
1628#if __mips >= 4 && __mips != 32 1410 /*
1411 * Note that on some MIPS IV implementations such as the
1412 * R5000 and R8000 the FSQRT and FRECIP instructions do not
1413 * achieve full IEEE-754 accuracy - however this emulator does.
1414 */
1629 case frsqrt_op: 1415 case frsqrt_op:
1416 if (!cpu_has_mips_4_5_r2)
1417 return SIGILL;
1418
1630 handler.u = fpemu_sp_rsqrt; 1419 handler.u = fpemu_sp_rsqrt;
1631 goto scopuop; 1420 goto scopuop;
1421
1632 case frecip_op: 1422 case frecip_op:
1423 if (!cpu_has_mips_4_5_r2)
1424 return SIGILL;
1425
1633 handler.u = fpemu_sp_recip; 1426 handler.u = fpemu_sp_recip;
1634 goto scopuop; 1427 goto scopuop;
1635#endif 1428
1636#if __mips >= 4
1637 case fmovc_op: 1429 case fmovc_op:
1430 if (!cpu_has_mips_4_5_r)
1431 return SIGILL;
1432
1638 cond = fpucondbit[MIPSInst_FT(ir) >> 2]; 1433 cond = fpucondbit[MIPSInst_FT(ir) >> 2];
1639 if (((ctx->fcr31 & cond) != 0) != 1434 if (((ctx->fcr31 & cond) != 0) !=
1640 ((MIPSInst_FT(ir) & 1) != 0)) 1435 ((MIPSInst_FT(ir) & 1) != 0))
1641 return 0; 1436 return 0;
1642 SPFROMREG(rv.s, MIPSInst_FS(ir)); 1437 SPFROMREG(rv.s, MIPSInst_FS(ir));
1643 break; 1438 break;
1439
1644 case fmovz_op: 1440 case fmovz_op:
1441 if (!cpu_has_mips_4_5_r)
1442 return SIGILL;
1443
1645 if (xcp->regs[MIPSInst_FT(ir)] != 0) 1444 if (xcp->regs[MIPSInst_FT(ir)] != 0)
1646 return 0; 1445 return 0;
1647 SPFROMREG(rv.s, MIPSInst_FS(ir)); 1446 SPFROMREG(rv.s, MIPSInst_FS(ir));
1648 break; 1447 break;
1448
1649 case fmovn_op: 1449 case fmovn_op:
1450 if (!cpu_has_mips_4_5_r)
1451 return SIGILL;
1452
1650 if (xcp->regs[MIPSInst_FT(ir)] == 0) 1453 if (xcp->regs[MIPSInst_FT(ir)] == 0)
1651 return 0; 1454 return 0;
1652 SPFROMREG(rv.s, MIPSInst_FS(ir)); 1455 SPFROMREG(rv.s, MIPSInst_FS(ir));
1653 break; 1456 break;
1654#endif 1457
1655 case fabs_op: 1458 case fabs_op:
1656 handler.u = ieee754sp_abs; 1459 handler.u = ieee754sp_abs;
1657 goto scopuop; 1460 goto scopuop;
1461
1658 case fneg_op: 1462 case fneg_op:
1659 handler.u = ieee754sp_neg; 1463 handler.u = ieee754sp_neg;
1660 goto scopuop; 1464 goto scopuop;
1465
1661 case fmov_op: 1466 case fmov_op:
1662 /* an easy one */ 1467 /* an easy one */
1663 SPFROMREG(rv.s, MIPSInst_FS(ir)); 1468 SPFROMREG(rv.s, MIPSInst_FS(ir));
1664 goto copcsr; 1469 goto copcsr;
1665 1470
1666 /* binary op on handler */ 1471 /* binary op on handler */
1667 scopbop: 1472scopbop:
1668 { 1473 SPFROMREG(fs, MIPSInst_FS(ir));
1669 ieee754sp fs, ft; 1474 SPFROMREG(ft, MIPSInst_FT(ir));
1670
1671 SPFROMREG(fs, MIPSInst_FS(ir));
1672 SPFROMREG(ft, MIPSInst_FT(ir));
1673
1674 rv.s = (*handler.b) (fs, ft);
1675 goto copcsr;
1676 }
1677 scopuop:
1678 {
1679 ieee754sp fs;
1680 1475
1681 SPFROMREG(fs, MIPSInst_FS(ir)); 1476 rv.s = (*handler.b) (fs, ft);
1682 rv.s = (*handler.u) (fs); 1477 goto copcsr;
1683 goto copcsr; 1478scopuop:
1684 } 1479 SPFROMREG(fs, MIPSInst_FS(ir));
1685 copcsr: 1480 rv.s = (*handler.u) (fs);
1686 if (ieee754_cxtest(IEEE754_INEXACT)) 1481 goto copcsr;
1482copcsr:
1483 if (ieee754_cxtest(IEEE754_INEXACT)) {
1484 MIPS_FPU_EMU_INC_STATS(ieee754_inexact);
1687 rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; 1485 rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
1688 if (ieee754_cxtest(IEEE754_UNDERFLOW)) 1486 }
1487 if (ieee754_cxtest(IEEE754_UNDERFLOW)) {
1488 MIPS_FPU_EMU_INC_STATS(ieee754_underflow);
1689 rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S; 1489 rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
1690 if (ieee754_cxtest(IEEE754_OVERFLOW)) 1490 }
1491 if (ieee754_cxtest(IEEE754_OVERFLOW)) {
1492 MIPS_FPU_EMU_INC_STATS(ieee754_overflow);
1691 rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; 1493 rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
1692 if (ieee754_cxtest(IEEE754_ZERO_DIVIDE)) 1494 }
1495 if (ieee754_cxtest(IEEE754_ZERO_DIVIDE)) {
1496 MIPS_FPU_EMU_INC_STATS(ieee754_zerodiv);
1693 rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S; 1497 rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S;
1694 if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) 1498 }
1499 if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) {
1500 MIPS_FPU_EMU_INC_STATS(ieee754_invalidop);
1695 rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S; 1501 rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S;
1502 }
1696 break; 1503 break;
1697 1504
1698 /* unary conv ops */ 1505 /* unary conv ops */
1699 case fcvts_op: 1506 case fcvts_op:
1700 return SIGILL; /* not defined */ 1507 return SIGILL; /* not defined */
1701 case fcvtd_op:{
1702 ieee754sp fs;
1703 1508
1509 case fcvtd_op:
1704 SPFROMREG(fs, MIPSInst_FS(ir)); 1510 SPFROMREG(fs, MIPSInst_FS(ir));
1705 rv.d = ieee754dp_fsp(fs); 1511 rv.d = ieee754dp_fsp(fs);
1706 rfmt = d_fmt; 1512 rfmt = d_fmt;
1707 goto copcsr; 1513 goto copcsr;
1708 }
1709 case fcvtw_op:{
1710 ieee754sp fs;
1711 1514
1515 case fcvtw_op:
1712 SPFROMREG(fs, MIPSInst_FS(ir)); 1516 SPFROMREG(fs, MIPSInst_FS(ir));
1713 rv.w = ieee754sp_tint(fs); 1517 rv.w = ieee754sp_tint(fs);
1714 rfmt = w_fmt; 1518 rfmt = w_fmt;
1715 goto copcsr; 1519 goto copcsr;
1716 }
1717 1520
1718#if __mips >= 2 || defined(__mips64)
1719 case fround_op: 1521 case fround_op:
1720 case ftrunc_op: 1522 case ftrunc_op:
1721 case fceil_op: 1523 case fceil_op:
1722 case ffloor_op:{ 1524 case ffloor_op:
1723 unsigned int oldrm = ieee754_csr.rm; 1525 if (!cpu_has_mips_2_3_4_5 && !cpu_has_mips64)
1724 ieee754sp fs; 1526 return SIGILL;
1725 1527
1528 oldrm = ieee754_csr.rm;
1726 SPFROMREG(fs, MIPSInst_FS(ir)); 1529 SPFROMREG(fs, MIPSInst_FS(ir));
1727 ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; 1530 ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir));
1728 rv.w = ieee754sp_tint(fs); 1531 rv.w = ieee754sp_tint(fs);
1729 ieee754_csr.rm = oldrm; 1532 ieee754_csr.rm = oldrm;
1730 rfmt = w_fmt; 1533 rfmt = w_fmt;
1731 goto copcsr; 1534 goto copcsr;
1732 }
1733#endif /* __mips >= 2 */
1734 1535
1735#if defined(__mips64) 1536 case fcvtl_op:
1736 case fcvtl_op:{ 1537 if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
1737 ieee754sp fs; 1538 return SIGILL;
1738 1539
1739 SPFROMREG(fs, MIPSInst_FS(ir)); 1540 SPFROMREG(fs, MIPSInst_FS(ir));
1740 rv.l = ieee754sp_tlong(fs); 1541 rv.l = ieee754sp_tlong(fs);
1741 rfmt = l_fmt; 1542 rfmt = l_fmt;
1742 goto copcsr; 1543 goto copcsr;
1743 }
1744 1544
1745 case froundl_op: 1545 case froundl_op:
1746 case ftruncl_op: 1546 case ftruncl_op:
1747 case fceill_op: 1547 case fceill_op:
1748 case ffloorl_op:{ 1548 case ffloorl_op:
1749 unsigned int oldrm = ieee754_csr.rm; 1549 if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
1750 ieee754sp fs; 1550 return SIGILL;
1751 1551
1552 oldrm = ieee754_csr.rm;
1752 SPFROMREG(fs, MIPSInst_FS(ir)); 1553 SPFROMREG(fs, MIPSInst_FS(ir));
1753 ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; 1554 ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir));
1754 rv.l = ieee754sp_tlong(fs); 1555 rv.l = ieee754sp_tlong(fs);
1755 ieee754_csr.rm = oldrm; 1556 ieee754_csr.rm = oldrm;
1756 rfmt = l_fmt; 1557 rfmt = l_fmt;
1757 goto copcsr; 1558 goto copcsr;
1758 }
1759#endif /* defined(__mips64) */
1760 1559
1761 default: 1560 default:
1762 if (MIPSInst_FUNC(ir) >= fcmp_op) { 1561 if (MIPSInst_FUNC(ir) >= fcmp_op) {
1763 unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; 1562 unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
1764 ieee754sp fs, ft; 1563 union ieee754sp fs, ft;
1765 1564
1766 SPFROMREG(fs, MIPSInst_FS(ir)); 1565 SPFROMREG(fs, MIPSInst_FS(ir));
1767 SPFROMREG(ft, MIPSInst_FT(ir)); 1566 SPFROMREG(ft, MIPSInst_FT(ir));
@@ -1774,19 +1573,18 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1774 else 1573 else
1775 goto copcsr; 1574 goto copcsr;
1776 1575
1777 } 1576 } else
1778 else {
1779 return SIGILL; 1577 return SIGILL;
1780 }
1781 break; 1578 break;
1782 } 1579 }
1783 break; 1580 break;
1784 } 1581 }
1785 1582
1786 case d_fmt:{ 1583 case d_fmt: {
1584 union ieee754dp fs, ft;
1787 union { 1585 union {
1788 ieee754dp(*b) (ieee754dp, ieee754dp); 1586 union ieee754dp(*b) (union ieee754dp, union ieee754dp);
1789 ieee754dp(*u) (ieee754dp); 1587 union ieee754dp(*u) (union ieee754dp);
1790 } handler; 1588 } handler;
1791 1589
1792 switch (MIPSInst_FUNC(ir)) { 1590 switch (MIPSInst_FUNC(ir)) {
@@ -1805,21 +1603,33 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1805 goto dcopbop; 1603 goto dcopbop;
1806 1604
1807 /* unary ops */ 1605 /* unary ops */
1808#if __mips >= 2 || defined(__mips64)
1809 case fsqrt_op: 1606 case fsqrt_op:
1607 if (!cpu_has_mips_2_3_4_5_r)
1608 return SIGILL;
1609
1810 handler.u = ieee754dp_sqrt; 1610 handler.u = ieee754dp_sqrt;
1811 goto dcopuop; 1611 goto dcopuop;
1812#endif 1612 /*
1813#if __mips >= 4 && __mips != 32 1613 * Note that on some MIPS IV implementations such as the
1614 * R5000 and R8000 the FSQRT and FRECIP instructions do not
1615 * achieve full IEEE-754 accuracy - however this emulator does.
1616 */
1814 case frsqrt_op: 1617 case frsqrt_op:
1618 if (!cpu_has_mips_4_5_r2)
1619 return SIGILL;
1620
1815 handler.u = fpemu_dp_rsqrt; 1621 handler.u = fpemu_dp_rsqrt;
1816 goto dcopuop; 1622 goto dcopuop;
1817 case frecip_op: 1623 case frecip_op:
1624 if (!cpu_has_mips_4_5_r2)
1625 return SIGILL;
1626
1818 handler.u = fpemu_dp_recip; 1627 handler.u = fpemu_dp_recip;
1819 goto dcopuop; 1628 goto dcopuop;
1820#endif
1821#if __mips >= 4
1822 case fmovc_op: 1629 case fmovc_op:
1630 if (!cpu_has_mips_4_5_r)
1631 return SIGILL;
1632
1823 cond = fpucondbit[MIPSInst_FT(ir) >> 2]; 1633 cond = fpucondbit[MIPSInst_FT(ir) >> 2];
1824 if (((ctx->fcr31 & cond) != 0) != 1634 if (((ctx->fcr31 & cond) != 0) !=
1825 ((MIPSInst_FT(ir) & 1) != 0)) 1635 ((MIPSInst_FT(ir) & 1) != 0))
@@ -1827,16 +1637,21 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1827 DPFROMREG(rv.d, MIPSInst_FS(ir)); 1637 DPFROMREG(rv.d, MIPSInst_FS(ir));
1828 break; 1638 break;
1829 case fmovz_op: 1639 case fmovz_op:
1640 if (!cpu_has_mips_4_5_r)
1641 return SIGILL;
1642
1830 if (xcp->regs[MIPSInst_FT(ir)] != 0) 1643 if (xcp->regs[MIPSInst_FT(ir)] != 0)
1831 return 0; 1644 return 0;
1832 DPFROMREG(rv.d, MIPSInst_FS(ir)); 1645 DPFROMREG(rv.d, MIPSInst_FS(ir));
1833 break; 1646 break;
1834 case fmovn_op: 1647 case fmovn_op:
1648 if (!cpu_has_mips_4_5_r)
1649 return SIGILL;
1650
1835 if (xcp->regs[MIPSInst_FT(ir)] == 0) 1651 if (xcp->regs[MIPSInst_FT(ir)] == 0)
1836 return 0; 1652 return 0;
1837 DPFROMREG(rv.d, MIPSInst_FS(ir)); 1653 DPFROMREG(rv.d, MIPSInst_FS(ir));
1838 break; 1654 break;
1839#endif
1840 case fabs_op: 1655 case fabs_op:
1841 handler.u = ieee754dp_abs; 1656 handler.u = ieee754dp_abs;
1842 goto dcopuop; 1657 goto dcopuop;
@@ -1851,91 +1666,78 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1851 goto copcsr; 1666 goto copcsr;
1852 1667
1853 /* binary op on handler */ 1668 /* binary op on handler */
1854 dcopbop:{ 1669dcopbop:
1855 ieee754dp fs, ft; 1670 DPFROMREG(fs, MIPSInst_FS(ir));
1856 1671 DPFROMREG(ft, MIPSInst_FT(ir));
1857 DPFROMREG(fs, MIPSInst_FS(ir));
1858 DPFROMREG(ft, MIPSInst_FT(ir));
1859
1860 rv.d = (*handler.b) (fs, ft);
1861 goto copcsr;
1862 }
1863 dcopuop:{
1864 ieee754dp fs;
1865
1866 DPFROMREG(fs, MIPSInst_FS(ir));
1867 rv.d = (*handler.u) (fs);
1868 goto copcsr;
1869 }
1870 1672
1871 /* unary conv ops */ 1673 rv.d = (*handler.b) (fs, ft);
1872 case fcvts_op:{ 1674 goto copcsr;
1873 ieee754dp fs; 1675dcopuop:
1676 DPFROMREG(fs, MIPSInst_FS(ir));
1677 rv.d = (*handler.u) (fs);
1678 goto copcsr;
1874 1679
1680 /*
1681 * unary conv ops
1682 */
1683 case fcvts_op:
1875 DPFROMREG(fs, MIPSInst_FS(ir)); 1684 DPFROMREG(fs, MIPSInst_FS(ir));
1876 rv.s = ieee754sp_fdp(fs); 1685 rv.s = ieee754sp_fdp(fs);
1877 rfmt = s_fmt; 1686 rfmt = s_fmt;
1878 goto copcsr; 1687 goto copcsr;
1879 } 1688
1880 case fcvtd_op: 1689 case fcvtd_op:
1881 return SIGILL; /* not defined */ 1690 return SIGILL; /* not defined */
1882 1691
1883 case fcvtw_op:{ 1692 case fcvtw_op:
1884 ieee754dp fs;
1885
1886 DPFROMREG(fs, MIPSInst_FS(ir)); 1693 DPFROMREG(fs, MIPSInst_FS(ir));
1887 rv.w = ieee754dp_tint(fs); /* wrong */ 1694 rv.w = ieee754dp_tint(fs); /* wrong */
1888 rfmt = w_fmt; 1695 rfmt = w_fmt;
1889 goto copcsr; 1696 goto copcsr;
1890 }
1891 1697
1892#if __mips >= 2 || defined(__mips64)
1893 case fround_op: 1698 case fround_op:
1894 case ftrunc_op: 1699 case ftrunc_op:
1895 case fceil_op: 1700 case fceil_op:
1896 case ffloor_op:{ 1701 case ffloor_op:
1897 unsigned int oldrm = ieee754_csr.rm; 1702 if (!cpu_has_mips_2_3_4_5_r)
1898 ieee754dp fs; 1703 return SIGILL;
1899 1704
1705 oldrm = ieee754_csr.rm;
1900 DPFROMREG(fs, MIPSInst_FS(ir)); 1706 DPFROMREG(fs, MIPSInst_FS(ir));
1901 ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; 1707 ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir));
1902 rv.w = ieee754dp_tint(fs); 1708 rv.w = ieee754dp_tint(fs);
1903 ieee754_csr.rm = oldrm; 1709 ieee754_csr.rm = oldrm;
1904 rfmt = w_fmt; 1710 rfmt = w_fmt;
1905 goto copcsr; 1711 goto copcsr;
1906 }
1907#endif
1908 1712
1909#if defined(__mips64) 1713 case fcvtl_op:
1910 case fcvtl_op:{ 1714 if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
1911 ieee754dp fs; 1715 return SIGILL;
1912 1716
1913 DPFROMREG(fs, MIPSInst_FS(ir)); 1717 DPFROMREG(fs, MIPSInst_FS(ir));
1914 rv.l = ieee754dp_tlong(fs); 1718 rv.l = ieee754dp_tlong(fs);
1915 rfmt = l_fmt; 1719 rfmt = l_fmt;
1916 goto copcsr; 1720 goto copcsr;
1917 }
1918 1721
1919 case froundl_op: 1722 case froundl_op:
1920 case ftruncl_op: 1723 case ftruncl_op:
1921 case fceill_op: 1724 case fceill_op:
1922 case ffloorl_op:{ 1725 case ffloorl_op:
1923 unsigned int oldrm = ieee754_csr.rm; 1726 if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
1924 ieee754dp fs; 1727 return SIGILL;
1925 1728
1729 oldrm = ieee754_csr.rm;
1926 DPFROMREG(fs, MIPSInst_FS(ir)); 1730 DPFROMREG(fs, MIPSInst_FS(ir));
1927 ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; 1731 ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir));
1928 rv.l = ieee754dp_tlong(fs); 1732 rv.l = ieee754dp_tlong(fs);
1929 ieee754_csr.rm = oldrm; 1733 ieee754_csr.rm = oldrm;
1930 rfmt = l_fmt; 1734 rfmt = l_fmt;
1931 goto copcsr; 1735 goto copcsr;
1932 }
1933#endif /* __mips >= 3 */
1934 1736
1935 default: 1737 default:
1936 if (MIPSInst_FUNC(ir) >= fcmp_op) { 1738 if (MIPSInst_FUNC(ir) >= fcmp_op) {
1937 unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; 1739 unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
1938 ieee754dp fs, ft; 1740 union ieee754dp fs, ft;
1939 1741
1940 DPFROMREG(fs, MIPSInst_FS(ir)); 1742 DPFROMREG(fs, MIPSInst_FS(ir));
1941 DPFROMREG(ft, MIPSInst_FT(ir)); 1743 DPFROMREG(ft, MIPSInst_FT(ir));
@@ -1957,11 +1759,8 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1957 break; 1759 break;
1958 } 1760 }
1959 break; 1761 break;
1960 }
1961
1962 case w_fmt:{
1963 ieee754sp fs;
1964 1762
1763 case w_fmt:
1965 switch (MIPSInst_FUNC(ir)) { 1764 switch (MIPSInst_FUNC(ir)) {
1966 case fcvts_op: 1765 case fcvts_op:
1967 /* convert word to single precision real */ 1766 /* convert word to single precision real */
@@ -1981,9 +1780,11 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
1981 break; 1780 break;
1982 } 1781 }
1983 1782
1984#if defined(__mips64) 1783 case l_fmt:
1985 case l_fmt:{ 1784
1986 u64 bits; 1785 if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
1786 return SIGILL;
1787
1987 DIFROMREG(bits, MIPSInst_FS(ir)); 1788 DIFROMREG(bits, MIPSInst_FS(ir));
1988 1789
1989 switch (MIPSInst_FUNC(ir)) { 1790 switch (MIPSInst_FUNC(ir)) {
@@ -2001,8 +1802,6 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
2001 return SIGILL; 1802 return SIGILL;
2002 } 1803 }
2003 break; 1804 break;
2004 }
2005#endif
2006 1805
2007 default: 1806 default:
2008 return SIGILL; 1807 return SIGILL;
@@ -2017,7 +1816,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
2017 */ 1816 */
2018 ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr; 1817 ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr;
2019 if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { 1818 if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
2020 /*printk ("SIGFPE: fpu csr = %08x\n",ctx->fcr31); */ 1819 /*printk ("SIGFPE: FPU csr = %08x\n",ctx->fcr31); */
2021 return SIGFPE; 1820 return SIGFPE;
2022 } 1821 }
2023 1822
@@ -2025,18 +1824,18 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
2025 * Now we can safely write the result back to the register file. 1824 * Now we can safely write the result back to the register file.
2026 */ 1825 */
2027 switch (rfmt) { 1826 switch (rfmt) {
2028 case -1:{ 1827 case -1:
2029#if __mips >= 4 1828
2030 cond = fpucondbit[MIPSInst_FD(ir) >> 2]; 1829 if (cpu_has_mips_4_5_r)
2031#else 1830 cbit = fpucondbit[MIPSInst_RT(ir) >> 2];
2032 cond = FPU_CSR_COND; 1831 else
2033#endif 1832 cbit = FPU_CSR_COND;
2034 if (rv.w) 1833 if (rv.w)
2035 ctx->fcr31 |= cond; 1834 ctx->fcr31 |= cbit;
2036 else 1835 else
2037 ctx->fcr31 &= ~cond; 1836 ctx->fcr31 &= ~cbit;
2038 break; 1837 break;
2039 } 1838
2040 case d_fmt: 1839 case d_fmt:
2041 DPTOREG(rv.d, MIPSInst_FD(ir)); 1840 DPTOREG(rv.d, MIPSInst_FD(ir));
2042 break; 1841 break;
@@ -2046,11 +1845,12 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
2046 case w_fmt: 1845 case w_fmt:
2047 SITOREG(rv.w, MIPSInst_FD(ir)); 1846 SITOREG(rv.w, MIPSInst_FD(ir));
2048 break; 1847 break;
2049#if defined(__mips64)
2050 case l_fmt: 1848 case l_fmt:
1849 if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
1850 return SIGILL;
1851
2051 DITOREG(rv.l, MIPSInst_FD(ir)); 1852 DITOREG(rv.l, MIPSInst_FD(ir));
2052 break; 1853 break;
2053#endif
2054 default: 1854 default:
2055 return SIGILL; 1855 return SIGILL;
2056 } 1856 }
@@ -2138,11 +1938,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
2138 * ieee754_csr. But ieee754_csr.rm is ieee 1938 * ieee754_csr. But ieee754_csr.rm is ieee
2139 * library modes. (not mips rounding mode) 1939 * library modes. (not mips rounding mode)
2140 */ 1940 */
2141 /* convert to ieee library modes */
2142 ieee754_csr.rm = ieee_rm[ieee754_csr.rm];
2143 sig = cop1Emulate(xcp, ctx, dec_insn, fault_addr); 1941 sig = cop1Emulate(xcp, ctx, dec_insn, fault_addr);
2144 /* revert to mips rounding mode */
2145 ieee754_csr.rm = mips_rm[ieee754_csr.rm];
2146 } 1942 }
2147 1943
2148 if (has_fpu) 1944 if (has_fpu)
@@ -2155,58 +1951,8 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
2155 1951
2156 /* SIGILL indicates a non-fpu instruction */ 1952 /* SIGILL indicates a non-fpu instruction */
2157 if (sig == SIGILL && xcp->cp0_epc != oldepc) 1953 if (sig == SIGILL && xcp->cp0_epc != oldepc)
2158 /* but if epc has advanced, then ignore it */ 1954 /* but if EPC has advanced, then ignore it */
2159 sig = 0; 1955 sig = 0;
2160 1956
2161 return sig; 1957 return sig;
2162} 1958}
2163
2164#ifdef CONFIG_DEBUG_FS
2165
2166static int fpuemu_stat_get(void *data, u64 *val)
2167{
2168 int cpu;
2169 unsigned long sum = 0;
2170 for_each_online_cpu(cpu) {
2171 struct mips_fpu_emulator_stats *ps;
2172 local_t *pv;
2173 ps = &per_cpu(fpuemustats, cpu);
2174 pv = (void *)ps + (unsigned long)data;
2175 sum += local_read(pv);
2176 }
2177 *val = sum;
2178 return 0;
2179}
2180DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n");
2181
2182extern struct dentry *mips_debugfs_dir;
2183static int __init debugfs_fpuemu(void)
2184{
2185 struct dentry *d, *dir;
2186
2187 if (!mips_debugfs_dir)
2188 return -ENODEV;
2189 dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
2190 if (!dir)
2191 return -ENOMEM;
2192
2193#define FPU_STAT_CREATE(M) \
2194 do { \
2195 d = debugfs_create_file(#M , S_IRUGO, dir, \
2196 (void *)offsetof(struct mips_fpu_emulator_stats, M), \
2197 &fops_fpuemu_stat); \
2198 if (!d) \
2199 return -ENOMEM; \
2200 } while (0)
2201
2202 FPU_STAT_CREATE(emulated);
2203 FPU_STAT_CREATE(loads);
2204 FPU_STAT_CREATE(stores);
2205 FPU_STAT_CREATE(cp1ops);
2206 FPU_STAT_CREATE(cp1xops);
2207 FPU_STAT_CREATE(errors);
2208
2209 return 0;
2210}
2211__initcall(debugfs_fpuemu);
2212#endif