MIPS: MIPS16e: Support handling of delay slots.
[firefly-linux-kernel-4.4.55.git] / arch / mips / include / asm / branch.h
index 40bb9ebcc7aab381875f602910ee6df83adf8cba..e28a3e0eb3cb6407b4ad6d6ac649e20a876ab69d 100644 (file)
@@ -16,6 +16,7 @@ extern int __compute_return_epc(struct pt_regs *regs);
 extern int __compute_return_epc_for_insn(struct pt_regs *regs,
                                         union mips_instruction insn);
 extern int __microMIPS_compute_return_epc(struct pt_regs *regs);
+extern int __MIPS16e_compute_return_epc(struct pt_regs *regs);
 
 
 static inline int delay_slot(struct pt_regs *regs)
@@ -41,6 +42,8 @@ static inline int compute_return_epc(struct pt_regs *regs)
        if (get_isa16_mode(regs->cp0_epc)) {
                if (cpu_has_mmips)
                        return __microMIPS_compute_return_epc(regs);
+               if (cpu_has_mips16)
+                       return __MIPS16e_compute_return_epc(regs);
                return regs->cp0_epc;
        }
 
@@ -52,4 +55,19 @@ static inline int compute_return_epc(struct pt_regs *regs)
        return __compute_return_epc(regs);
 }
 
+static inline int MIPS16e_compute_return_epc(struct pt_regs *regs,
+                                            union mips16e_instruction *inst)
+{
+       if (likely(!delay_slot(regs))) {
+               if (inst->ri.opcode == MIPS16e_extend_op) {
+                       regs->cp0_epc += 4;
+                       return 0;
+               }
+               regs->cp0_epc += 2;
+               return 0;
+       }
+
+       return __MIPS16e_compute_return_epc(regs);
+}
+
 #endif /* _ASM_BRANCH_H */