@@ -403,7 +403,7 @@ int __MIPS16e_compute_return_epc(struct pt_regs *regs)
403
403
int __compute_return_epc_for_insn (struct pt_regs * regs ,
404
404
union mips_instruction insn )
405
405
{
406
- unsigned int bit , fcr31 , dspcontrol ;
406
+ unsigned int bit , fcr31 , dspcontrol , reg ;
407
407
long epc = regs -> cp0_epc ;
408
408
int ret = 0 ;
409
409
@@ -618,40 +618,83 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
618
618
* And now the FPA/cp1 branch instructions.
619
619
*/
620
620
case cop1_op :
621
- preempt_disable ();
622
- if (is_fpu_owner ())
623
- fcr31 = read_32bit_cp1_register (CP1_STATUS );
624
- else
625
- fcr31 = current -> thread .fpu .fcr31 ;
626
- preempt_enable ();
627
-
628
- bit = (insn .i_format .rt >> 2 );
629
- bit += (bit != 0 );
630
- bit += 23 ;
631
- switch (insn .i_format .rt & 3 ) {
632
- case 0 : /* bc1f */
633
- case 2 : /* bc1fl */
634
- if (~fcr31 & (1 << bit )) {
635
- epc = epc + 4 + (insn .i_format .simmediate << 2 );
636
- if (insn .i_format .rt == 2 )
637
- ret = BRANCH_LIKELY_TAKEN ;
638
- } else
621
+ if (cpu_has_mips_r6 &&
622
+ ((insn .i_format .rs == bc1eqz_op ) ||
623
+ (insn .i_format .rs == bc1nez_op ))) {
624
+ if (!used_math ()) { /* First time FPU user */
625
+ ret = init_fpu ();
626
+ if (ret && NO_R6EMU ) {
627
+ ret = - ret ;
628
+ break ;
629
+ }
630
+ ret = 0 ;
631
+ set_used_math ();
632
+ }
633
+ lose_fpu (1 ); /* Save FPU state for the emulator. */
634
+ reg = insn .i_format .rt ;
635
+ bit = 0 ;
636
+ switch (insn .i_format .rs ) {
637
+ case bc1eqz_op :
638
+ /* Test bit 0 */
639
+ if (get_fpr32 (& current -> thread .fpu .fpr [reg ], 0 )
640
+ & 0x1 )
641
+ bit = 1 ;
642
+ break ;
643
+ case bc1nez_op :
644
+ /* Test bit 0 */
645
+ if (!(get_fpr32 (& current -> thread .fpu .fpr [reg ], 0 )
646
+ & 0x1 ))
647
+ bit = 1 ;
648
+ break ;
649
+ }
650
+ own_fpu (1 );
651
+ if (bit )
652
+ epc = epc + 4 +
653
+ (insn .i_format .simmediate << 2 );
654
+ else
639
655
epc += 8 ;
640
656
regs -> cp0_epc = epc ;
657
+
641
658
break ;
659
+ } else {
642
660
643
- case 1 : /* bc1t */
644
- case 3 : /* bc1tl */
645
- if (fcr31 & (1 << bit )) {
646
- epc = epc + 4 + (insn .i_format .simmediate << 2 );
647
- if (insn .i_format .rt == 3 )
648
- ret = BRANCH_LIKELY_TAKEN ;
649
- } else
650
- epc += 8 ;
651
- regs -> cp0_epc = epc ;
661
+ preempt_disable ();
662
+ if (is_fpu_owner ())
663
+ fcr31 = read_32bit_cp1_register (CP1_STATUS );
664
+ else
665
+ fcr31 = current -> thread .fpu .fcr31 ;
666
+ preempt_enable ();
667
+
668
+ bit = (insn .i_format .rt >> 2 );
669
+ bit += (bit != 0 );
670
+ bit += 23 ;
671
+ switch (insn .i_format .rt & 3 ) {
672
+ case 0 : /* bc1f */
673
+ case 2 : /* bc1fl */
674
+ if (~fcr31 & (1 << bit )) {
675
+ epc = epc + 4 +
676
+ (insn .i_format .simmediate << 2 );
677
+ if (insn .i_format .rt == 2 )
678
+ ret = BRANCH_LIKELY_TAKEN ;
679
+ } else
680
+ epc += 8 ;
681
+ regs -> cp0_epc = epc ;
682
+ break ;
683
+
684
+ case 1 : /* bc1t */
685
+ case 3 : /* bc1tl */
686
+ if (fcr31 & (1 << bit )) {
687
+ epc = epc + 4 +
688
+ (insn .i_format .simmediate << 2 );
689
+ if (insn .i_format .rt == 3 )
690
+ ret = BRANCH_LIKELY_TAKEN ;
691
+ } else
692
+ epc += 8 ;
693
+ regs -> cp0_epc = epc ;
694
+ break ;
695
+ }
652
696
break ;
653
697
}
654
- break ;
655
698
#ifdef CONFIG_CPU_CAVIUM_OCTEON
656
699
case lwc2_op : /* This is bbit0 on Octeon */
657
700
if ((regs -> regs [insn .i_format .rs ] & (1ull <<insn .i_format .rt ))
0 commit comments