···1616extern int __compute_return_epc_for_insn(struct pt_regs *regs,1717 union mips_instruction insn);1818extern int __microMIPS_compute_return_epc(struct pt_regs *regs);1919+extern int __MIPS16e_compute_return_epc(struct pt_regs *regs);192020212122static inline int delay_slot(struct pt_regs *regs)···4241 if (get_isa16_mode(regs->cp0_epc)) {4342 if (cpu_has_mmips)4443 return __microMIPS_compute_return_epc(regs);4444+ if (cpu_has_mips16)4545+ return __MIPS16e_compute_return_epc(regs);4546 return regs->cp0_epc;4647 }4748···5350 }54515552 return __compute_return_epc(regs);5353+}5454+5555+static inline int MIPS16e_compute_return_epc(struct pt_regs *regs,5656+ union mips16e_instruction *inst)5757+{5858+ if (likely(!delay_slot(regs))) {5959+ if (inst->ri.opcode == MIPS16e_extend_op) {6060+ regs->cp0_epc += 4;6161+ return 0;6262+ }6363+ regs->cp0_epc += 2;6464+ return 0;6565+ }6666+6767+ return __MIPS16e_compute_return_epc(regs);5668}57695870#endif /* _ASM_BRANCH_H */
+3
arch/mips/include/asm/inst.h
···8282 int micro_mips_mode;8383};84848585+/* Recode table from 16-bit register notation to 32-bit GPR. Do NOT export!!! */8686+extern const int reg16to32[];8787+8588#endif /* _ASM_INST_H */
+98-5
arch/mips/kernel/branch.c
···2020#include <asm/uaccess.h>21212222/*2323- * Calculate and return exception PC in case of branch delay2424- * slot for microMIPS. It does not clear the ISA mode bit.2323+ * Calculate and return exception PC in case of branch delay slot2424+ * for microMIPS and MIPS16e. It does not clear the ISA mode bit.2525 */2626int __isa_exception_epc(struct pt_regs *regs)2727{2828- long epc = regs->cp0_epc;2928 unsigned short inst;2929+ long epc = regs->cp0_epc;30303131 /* Calculate exception PC in branch delay slot. */3232 if (__get_user(inst, (u16 __user *) msk_isa16_mode(epc))) {···3434 force_sig(SIGSEGV, current);3535 return epc;3636 }3737-3838- if (mm_insn_16bit(inst))3737+ if (cpu_has_mips16) {3838+ if (((union mips16e_instruction)inst).ri.opcode3939+ == MIPS16e_jal_op)4040+ epc += 4;4141+ else4242+ epc += 2;4343+ } else if (mm_insn_16bit(inst))3944 epc += 2;4045 else4146 epc += 4;···10499sigsegv:105100 force_sig(SIGSEGV, current);106101 return -EFAULT;102102+}103103+104104+/*105105+ * Compute return address and emulate branch in MIPS16e mode after an106106+ * exception only. It does not handle compact branches/jumps and cannot107107+ * be used in interrupt context. (Compact branches/jumps do not cause108108+ * exceptions.)109109+ */110110+int __MIPS16e_compute_return_epc(struct pt_regs *regs)111111+{112112+ u16 __user *addr;113113+ union mips16e_instruction inst;114114+ u16 inst2;115115+ u32 fullinst;116116+ long epc;117117+118118+ epc = regs->cp0_epc;119119+120120+ /* Read the instruction. */121121+ addr = (u16 __user *)msk_isa16_mode(epc);122122+ if (__get_user(inst.full, addr)) {123123+ force_sig(SIGSEGV, current);124124+ return -EFAULT;125125+ }126126+127127+ switch (inst.ri.opcode) {128128+ case MIPS16e_extend_op:129129+ regs->cp0_epc += 4;130130+ return 0;131131+132132+ /*133133+ * JAL and JALX in MIPS16e mode134134+ */135135+ case MIPS16e_jal_op:136136+ addr += 1;137137+ if (__get_user(inst2, addr)) {138138+ force_sig(SIGSEGV, current);139139+ return -EFAULT;140140+ }141141+ fullinst = ((unsigned)inst.full << 16) | inst2;142142+ regs->regs[31] = epc + 6;143143+ epc += 4;144144+ epc >>= 28;145145+ epc <<= 28;146146+ /*147147+ * JAL:5 X:1 TARGET[20-16]:5 TARGET[25:21]:5 TARGET[15:0]:16148148+ *149149+ * ......TARGET[15:0].................TARGET[20:16]...........150150+ * ......TARGET[25:21]151151+ */152152+ epc |=153153+ ((fullinst & 0xffff) << 2) | ((fullinst & 0x3e00000) >> 3) |154154+ ((fullinst & 0x1f0000) << 7);155155+ if (!inst.jal.x)156156+ set_isa16_mode(epc); /* Set ISA mode bit. */157157+ regs->cp0_epc = epc;158158+ return 0;159159+160160+ /*161161+ * J(AL)R(C)162162+ */163163+ case MIPS16e_rr_op:164164+ if (inst.rr.func == MIPS16e_jr_func) {165165+166166+ if (inst.rr.ra)167167+ regs->cp0_epc = regs->regs[31];168168+ else169169+ regs->cp0_epc =170170+ regs->regs[reg16to32[inst.rr.rx]];171171+172172+ if (inst.rr.l) {173173+ if (inst.rr.nd)174174+ regs->regs[31] = epc + 2;175175+ else176176+ regs->regs[31] = epc + 4;177177+ }178178+ return 0;179179+ }180180+ break;181181+ }182182+183183+ /*184184+ * All other cases have no branch delay slot and are 16-bits.185185+ * Branches do not cause an exception.186186+ */187187+ regs->cp0_epc += 2;188188+189189+ return 0;107190}108191109192/**