11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public
31da177e4SLinus Torvalds * License. See the file "COPYING" in the main directory of this archive
41da177e4SLinus Torvalds * for more details.
51da177e4SLinus Torvalds *
61da177e4SLinus Torvalds * Copyright (C) 1996, 97, 2000, 2001 by Ralf Baechle
71da177e4SLinus Torvalds * Copyright (C) 2001 MIPS Technologies, Inc.
81da177e4SLinus Torvalds */
91da177e4SLinus Torvalds #include <linux/kernel.h>
103f07c014SIngo Molnar #include <linux/sched/signal.h>
111da177e4SLinus Torvalds #include <linux/signal.h>
12d9d54177SPaul Gortmaker #include <linux/export.h>
131da177e4SLinus Torvalds #include <asm/branch.h>
141da177e4SLinus Torvalds #include <asm/cpu.h>
151da177e4SLinus Torvalds #include <asm/cpu-features.h>
161d74f6bcSRalf Baechle #include <asm/fpu.h>
17fb6883e5SLeonid Yegoshin #include <asm/fpu_emulator.h>
181da177e4SLinus Torvalds #include <asm/inst.h>
19b0a668fbSLeonid Yegoshin #include <asm/mips-r2-to-r6-emul.h>
201da177e4SLinus Torvalds #include <asm/ptrace.h>
217c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
221da177e4SLinus Torvalds
23*6fa573a3SPujin Shi #include "probes-common.h"
24*6fa573a3SPujin Shi
25fb6883e5SLeonid Yegoshin /*
268508488fSSteven J. Hill * Calculate and return exception PC in case of branch delay slot
278508488fSSteven J. Hill * for microMIPS and MIPS16e. It does not clear the ISA mode bit.
28fb6883e5SLeonid Yegoshin */
__isa_exception_epc(struct pt_regs * regs)29fb6883e5SLeonid Yegoshin int __isa_exception_epc(struct pt_regs *regs)
30fb6883e5SLeonid Yegoshin {
31fb6883e5SLeonid Yegoshin unsigned short inst;
328508488fSSteven J. Hill long epc = regs->cp0_epc;
33fb6883e5SLeonid Yegoshin
34fb6883e5SLeonid Yegoshin /* Calculate exception PC in branch delay slot. */
35fb6883e5SLeonid Yegoshin if (__get_user(inst, (u16 __user *) msk_isa16_mode(epc))) {
36fb6883e5SLeonid Yegoshin /* This should never happen because delay slot was checked. */
373cf5d076SEric W. Biederman force_sig(SIGSEGV);
38fb6883e5SLeonid Yegoshin return epc;
39fb6883e5SLeonid Yegoshin }
408508488fSSteven J. Hill if (cpu_has_mips16) {
41e6baf0e0SToma Tabacu union mips16e_instruction inst_mips16e;
42e6baf0e0SToma Tabacu
43e6baf0e0SToma Tabacu inst_mips16e.full = inst;
44e6baf0e0SToma Tabacu if (inst_mips16e.ri.opcode == MIPS16e_jal_op)
458508488fSSteven J. Hill epc += 4;
468508488fSSteven J. Hill else
478508488fSSteven J. Hill epc += 2;
488508488fSSteven J. Hill } else if (mm_insn_16bit(inst))
49fb6883e5SLeonid Yegoshin epc += 2;
50fb6883e5SLeonid Yegoshin else
51fb6883e5SLeonid Yegoshin epc += 4;
52fb6883e5SLeonid Yegoshin
53fb6883e5SLeonid Yegoshin return epc;
54fb6883e5SLeonid Yegoshin }
55fb6883e5SLeonid Yegoshin
5676fbfc31SRalf Baechle /* (microMIPS) Convert 16-bit register encoding to 32-bit register encoding. */
5776fbfc31SRalf Baechle static const unsigned int reg16to32map[8] = {16, 17, 2, 3, 4, 5, 6, 7};
5876fbfc31SRalf Baechle
__mm_isBranchInstr(struct pt_regs * regs,struct mm_decoded_insn dec_insn,unsigned long * contpc)5976fbfc31SRalf Baechle int __mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
6076fbfc31SRalf Baechle unsigned long *contpc)
6176fbfc31SRalf Baechle {
6276fbfc31SRalf Baechle union mips_instruction insn = (union mips_instruction)dec_insn.insn;
63c2869aafSNathan Chancellor int __maybe_unused bc_false = 0;
6476fbfc31SRalf Baechle
6576fbfc31SRalf Baechle if (!cpu_has_mmips)
6676fbfc31SRalf Baechle return 0;
6776fbfc31SRalf Baechle
6876fbfc31SRalf Baechle switch (insn.mm_i_format.opcode) {
6976fbfc31SRalf Baechle case mm_pool32a_op:
7076fbfc31SRalf Baechle if ((insn.mm_i_format.simmediate & MM_POOL32A_MINOR_MASK) ==
7176fbfc31SRalf Baechle mm_pool32axf_op) {
7276fbfc31SRalf Baechle switch (insn.mm_i_format.simmediate >>
7376fbfc31SRalf Baechle MM_POOL32A_MINOR_SHIFT) {
7476fbfc31SRalf Baechle case mm_jalr_op:
7576fbfc31SRalf Baechle case mm_jalrhb_op:
7676fbfc31SRalf Baechle case mm_jalrs_op:
7776fbfc31SRalf Baechle case mm_jalrshb_op:
7876fbfc31SRalf Baechle if (insn.mm_i_format.rt != 0) /* Not mm_jr */
7976fbfc31SRalf Baechle regs->regs[insn.mm_i_format.rt] =
8076fbfc31SRalf Baechle regs->cp0_epc +
8176fbfc31SRalf Baechle dec_insn.pc_inc +
8276fbfc31SRalf Baechle dec_insn.next_pc_inc;
8376fbfc31SRalf Baechle *contpc = regs->regs[insn.mm_i_format.rs];
8476fbfc31SRalf Baechle return 1;
8576fbfc31SRalf Baechle }
8676fbfc31SRalf Baechle }
8776fbfc31SRalf Baechle break;
8876fbfc31SRalf Baechle case mm_pool32i_op:
8976fbfc31SRalf Baechle switch (insn.mm_i_format.rt) {
9076fbfc31SRalf Baechle case mm_bltzals_op:
9176fbfc31SRalf Baechle case mm_bltzal_op:
9276fbfc31SRalf Baechle regs->regs[31] = regs->cp0_epc +
9376fbfc31SRalf Baechle dec_insn.pc_inc +
9476fbfc31SRalf Baechle dec_insn.next_pc_inc;
95c9b02990SLiangliang Huang fallthrough;
9676fbfc31SRalf Baechle case mm_bltz_op:
9776fbfc31SRalf Baechle if ((long)regs->regs[insn.mm_i_format.rs] < 0)
9876fbfc31SRalf Baechle *contpc = regs->cp0_epc +
9976fbfc31SRalf Baechle dec_insn.pc_inc +
10076fbfc31SRalf Baechle (insn.mm_i_format.simmediate << 1);
10176fbfc31SRalf Baechle else
10276fbfc31SRalf Baechle *contpc = regs->cp0_epc +
10376fbfc31SRalf Baechle dec_insn.pc_inc +
10476fbfc31SRalf Baechle dec_insn.next_pc_inc;
10576fbfc31SRalf Baechle return 1;
10676fbfc31SRalf Baechle case mm_bgezals_op:
10776fbfc31SRalf Baechle case mm_bgezal_op:
10876fbfc31SRalf Baechle regs->regs[31] = regs->cp0_epc +
10976fbfc31SRalf Baechle dec_insn.pc_inc +
11076fbfc31SRalf Baechle dec_insn.next_pc_inc;
111c9b02990SLiangliang Huang fallthrough;
11276fbfc31SRalf Baechle case mm_bgez_op:
11376fbfc31SRalf Baechle if ((long)regs->regs[insn.mm_i_format.rs] >= 0)
11476fbfc31SRalf Baechle *contpc = regs->cp0_epc +
11576fbfc31SRalf Baechle dec_insn.pc_inc +
11676fbfc31SRalf Baechle (insn.mm_i_format.simmediate << 1);
11776fbfc31SRalf Baechle else
11876fbfc31SRalf Baechle *contpc = regs->cp0_epc +
11976fbfc31SRalf Baechle dec_insn.pc_inc +
12076fbfc31SRalf Baechle dec_insn.next_pc_inc;
12176fbfc31SRalf Baechle return 1;
12276fbfc31SRalf Baechle case mm_blez_op:
12376fbfc31SRalf Baechle if ((long)regs->regs[insn.mm_i_format.rs] <= 0)
12476fbfc31SRalf Baechle *contpc = regs->cp0_epc +
12576fbfc31SRalf Baechle dec_insn.pc_inc +
12676fbfc31SRalf Baechle (insn.mm_i_format.simmediate << 1);
12776fbfc31SRalf Baechle else
12876fbfc31SRalf Baechle *contpc = regs->cp0_epc +
12976fbfc31SRalf Baechle dec_insn.pc_inc +
13076fbfc31SRalf Baechle dec_insn.next_pc_inc;
13176fbfc31SRalf Baechle return 1;
13276fbfc31SRalf Baechle case mm_bgtz_op:
13376fbfc31SRalf Baechle if ((long)regs->regs[insn.mm_i_format.rs] <= 0)
13476fbfc31SRalf Baechle *contpc = regs->cp0_epc +
13576fbfc31SRalf Baechle dec_insn.pc_inc +
13676fbfc31SRalf Baechle (insn.mm_i_format.simmediate << 1);
13776fbfc31SRalf Baechle else
13876fbfc31SRalf Baechle *contpc = regs->cp0_epc +
13976fbfc31SRalf Baechle dec_insn.pc_inc +
14076fbfc31SRalf Baechle dec_insn.next_pc_inc;
14176fbfc31SRalf Baechle return 1;
1426a1cc218SPaul Burton #ifdef CONFIG_MIPS_FP_SUPPORT
14376fbfc31SRalf Baechle case mm_bc2f_op:
1446a1cc218SPaul Burton case mm_bc1f_op: {
1456a1cc218SPaul Burton unsigned int fcr31;
1466a1cc218SPaul Burton unsigned int bit;
1476a1cc218SPaul Burton
14876fbfc31SRalf Baechle bc_false = 1;
149c9b02990SLiangliang Huang fallthrough;
15076fbfc31SRalf Baechle case mm_bc2t_op:
15176fbfc31SRalf Baechle case mm_bc1t_op:
15276fbfc31SRalf Baechle preempt_disable();
15376fbfc31SRalf Baechle if (is_fpu_owner())
154842dfc11SManuel Lauss fcr31 = read_32bit_cp1_register(CP1_STATUS);
15576fbfc31SRalf Baechle else
15676fbfc31SRalf Baechle fcr31 = current->thread.fpu.fcr31;
15776fbfc31SRalf Baechle preempt_enable();
15876fbfc31SRalf Baechle
15976fbfc31SRalf Baechle if (bc_false)
16076fbfc31SRalf Baechle fcr31 = ~fcr31;
16176fbfc31SRalf Baechle
16276fbfc31SRalf Baechle bit = (insn.mm_i_format.rs >> 2);
16376fbfc31SRalf Baechle bit += (bit != 0);
16476fbfc31SRalf Baechle bit += 23;
16576fbfc31SRalf Baechle if (fcr31 & (1 << bit))
16676fbfc31SRalf Baechle *contpc = regs->cp0_epc +
16776fbfc31SRalf Baechle dec_insn.pc_inc +
16876fbfc31SRalf Baechle (insn.mm_i_format.simmediate << 1);
16976fbfc31SRalf Baechle else
17076fbfc31SRalf Baechle *contpc = regs->cp0_epc +
17176fbfc31SRalf Baechle dec_insn.pc_inc + dec_insn.next_pc_inc;
17276fbfc31SRalf Baechle return 1;
17376fbfc31SRalf Baechle }
1746a1cc218SPaul Burton #endif /* CONFIG_MIPS_FP_SUPPORT */
1756a1cc218SPaul Burton }
17676fbfc31SRalf Baechle break;
17776fbfc31SRalf Baechle case mm_pool16c_op:
17876fbfc31SRalf Baechle switch (insn.mm_i_format.rt) {
17976fbfc31SRalf Baechle case mm_jalr16_op:
18076fbfc31SRalf Baechle case mm_jalrs16_op:
18176fbfc31SRalf Baechle regs->regs[31] = regs->cp0_epc +
18276fbfc31SRalf Baechle dec_insn.pc_inc + dec_insn.next_pc_inc;
183c9b02990SLiangliang Huang fallthrough;
18476fbfc31SRalf Baechle case mm_jr16_op:
18576fbfc31SRalf Baechle *contpc = regs->regs[insn.mm_i_format.rs];
18676fbfc31SRalf Baechle return 1;
18776fbfc31SRalf Baechle }
18876fbfc31SRalf Baechle break;
18976fbfc31SRalf Baechle case mm_beqz16_op:
19076fbfc31SRalf Baechle if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] == 0)
19176fbfc31SRalf Baechle *contpc = regs->cp0_epc +
19276fbfc31SRalf Baechle dec_insn.pc_inc +
19376fbfc31SRalf Baechle (insn.mm_b1_format.simmediate << 1);
19476fbfc31SRalf Baechle else
19576fbfc31SRalf Baechle *contpc = regs->cp0_epc +
19676fbfc31SRalf Baechle dec_insn.pc_inc + dec_insn.next_pc_inc;
19776fbfc31SRalf Baechle return 1;
19876fbfc31SRalf Baechle case mm_bnez16_op:
19976fbfc31SRalf Baechle if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] != 0)
20076fbfc31SRalf Baechle *contpc = regs->cp0_epc +
20176fbfc31SRalf Baechle dec_insn.pc_inc +
20276fbfc31SRalf Baechle (insn.mm_b1_format.simmediate << 1);
20376fbfc31SRalf Baechle else
20476fbfc31SRalf Baechle *contpc = regs->cp0_epc +
20576fbfc31SRalf Baechle dec_insn.pc_inc + dec_insn.next_pc_inc;
20676fbfc31SRalf Baechle return 1;
20776fbfc31SRalf Baechle case mm_b16_op:
20876fbfc31SRalf Baechle *contpc = regs->cp0_epc + dec_insn.pc_inc +
20976fbfc31SRalf Baechle (insn.mm_b0_format.simmediate << 1);
21076fbfc31SRalf Baechle return 1;
21176fbfc31SRalf Baechle case mm_beq32_op:
21276fbfc31SRalf Baechle if (regs->regs[insn.mm_i_format.rs] ==
21376fbfc31SRalf Baechle regs->regs[insn.mm_i_format.rt])
21476fbfc31SRalf Baechle *contpc = regs->cp0_epc +
21576fbfc31SRalf Baechle dec_insn.pc_inc +
21676fbfc31SRalf Baechle (insn.mm_i_format.simmediate << 1);
21776fbfc31SRalf Baechle else
21876fbfc31SRalf Baechle *contpc = regs->cp0_epc +
21976fbfc31SRalf Baechle dec_insn.pc_inc +
22076fbfc31SRalf Baechle dec_insn.next_pc_inc;
22176fbfc31SRalf Baechle return 1;
22276fbfc31SRalf Baechle case mm_bne32_op:
22376fbfc31SRalf Baechle if (regs->regs[insn.mm_i_format.rs] !=
22476fbfc31SRalf Baechle regs->regs[insn.mm_i_format.rt])
22576fbfc31SRalf Baechle *contpc = regs->cp0_epc +
22676fbfc31SRalf Baechle dec_insn.pc_inc +
22776fbfc31SRalf Baechle (insn.mm_i_format.simmediate << 1);
22876fbfc31SRalf Baechle else
22976fbfc31SRalf Baechle *contpc = regs->cp0_epc +
23076fbfc31SRalf Baechle dec_insn.pc_inc + dec_insn.next_pc_inc;
23176fbfc31SRalf Baechle return 1;
23276fbfc31SRalf Baechle case mm_jalx32_op:
23376fbfc31SRalf Baechle regs->regs[31] = regs->cp0_epc +
23476fbfc31SRalf Baechle dec_insn.pc_inc + dec_insn.next_pc_inc;
23576fbfc31SRalf Baechle *contpc = regs->cp0_epc + dec_insn.pc_inc;
23676fbfc31SRalf Baechle *contpc >>= 28;
23776fbfc31SRalf Baechle *contpc <<= 28;
23876fbfc31SRalf Baechle *contpc |= (insn.j_format.target << 2);
23976fbfc31SRalf Baechle return 1;
24076fbfc31SRalf Baechle case mm_jals32_op:
24176fbfc31SRalf Baechle case mm_jal32_op:
24276fbfc31SRalf Baechle regs->regs[31] = regs->cp0_epc +
24376fbfc31SRalf Baechle dec_insn.pc_inc + dec_insn.next_pc_inc;
244c9b02990SLiangliang Huang fallthrough;
24576fbfc31SRalf Baechle case mm_j32_op:
24676fbfc31SRalf Baechle *contpc = regs->cp0_epc + dec_insn.pc_inc;
24776fbfc31SRalf Baechle *contpc >>= 27;
24876fbfc31SRalf Baechle *contpc <<= 27;
24976fbfc31SRalf Baechle *contpc |= (insn.j_format.target << 1);
25076fbfc31SRalf Baechle set_isa16_mode(*contpc);
25176fbfc31SRalf Baechle return 1;
25276fbfc31SRalf Baechle }
25376fbfc31SRalf Baechle return 0;
25476fbfc31SRalf Baechle }
25576fbfc31SRalf Baechle
256fb6883e5SLeonid Yegoshin /*
257fb6883e5SLeonid Yegoshin * Compute return address and emulate branch in microMIPS mode after an
258fb6883e5SLeonid Yegoshin * exception only. It does not handle compact branches/jumps and cannot
259fb6883e5SLeonid Yegoshin * be used in interrupt context. (Compact branches/jumps do not cause
260fb6883e5SLeonid Yegoshin * exceptions.)
261fb6883e5SLeonid Yegoshin */
__microMIPS_compute_return_epc(struct pt_regs * regs)262fb6883e5SLeonid Yegoshin int __microMIPS_compute_return_epc(struct pt_regs *regs)
263fb6883e5SLeonid Yegoshin {
264fb6883e5SLeonid Yegoshin u16 __user *pc16;
265fb6883e5SLeonid Yegoshin u16 halfword;
266fb6883e5SLeonid Yegoshin unsigned int word;
267fb6883e5SLeonid Yegoshin unsigned long contpc;
268fb6883e5SLeonid Yegoshin struct mm_decoded_insn mminsn = { 0 };
269fb6883e5SLeonid Yegoshin
270fb6883e5SLeonid Yegoshin mminsn.micro_mips_mode = 1;
271fb6883e5SLeonid Yegoshin
272fb6883e5SLeonid Yegoshin /* This load never faults. */
273fb6883e5SLeonid Yegoshin pc16 = (unsigned short __user *)msk_isa16_mode(regs->cp0_epc);
274fb6883e5SLeonid Yegoshin __get_user(halfword, pc16);
275fb6883e5SLeonid Yegoshin pc16++;
276fb6883e5SLeonid Yegoshin contpc = regs->cp0_epc + 2;
277fb6883e5SLeonid Yegoshin word = ((unsigned int)halfword << 16);
278fb6883e5SLeonid Yegoshin mminsn.pc_inc = 2;
279fb6883e5SLeonid Yegoshin
280fb6883e5SLeonid Yegoshin if (!mm_insn_16bit(halfword)) {
281fb6883e5SLeonid Yegoshin __get_user(halfword, pc16);
282fb6883e5SLeonid Yegoshin pc16++;
283fb6883e5SLeonid Yegoshin contpc = regs->cp0_epc + 4;
284fb6883e5SLeonid Yegoshin mminsn.pc_inc = 4;
285fb6883e5SLeonid Yegoshin word |= halfword;
286fb6883e5SLeonid Yegoshin }
287fb6883e5SLeonid Yegoshin mminsn.insn = word;
288fb6883e5SLeonid Yegoshin
289fb6883e5SLeonid Yegoshin if (get_user(halfword, pc16))
290fb6883e5SLeonid Yegoshin goto sigsegv;
291fb6883e5SLeonid Yegoshin mminsn.next_pc_inc = 2;
292fb6883e5SLeonid Yegoshin word = ((unsigned int)halfword << 16);
293fb6883e5SLeonid Yegoshin
294fb6883e5SLeonid Yegoshin if (!mm_insn_16bit(halfword)) {
295fb6883e5SLeonid Yegoshin pc16++;
296fb6883e5SLeonid Yegoshin if (get_user(halfword, pc16))
297fb6883e5SLeonid Yegoshin goto sigsegv;
298fb6883e5SLeonid Yegoshin mminsn.next_pc_inc = 4;
299fb6883e5SLeonid Yegoshin word |= halfword;
300fb6883e5SLeonid Yegoshin }
301fb6883e5SLeonid Yegoshin mminsn.next_insn = word;
302fb6883e5SLeonid Yegoshin
303fb6883e5SLeonid Yegoshin mm_isBranchInstr(regs, mminsn, &contpc);
304fb6883e5SLeonid Yegoshin
305fb6883e5SLeonid Yegoshin regs->cp0_epc = contpc;
306fb6883e5SLeonid Yegoshin
307fb6883e5SLeonid Yegoshin return 0;
308fb6883e5SLeonid Yegoshin
309fb6883e5SLeonid Yegoshin sigsegv:
3103cf5d076SEric W. Biederman force_sig(SIGSEGV);
311fb6883e5SLeonid Yegoshin return -EFAULT;
312fb6883e5SLeonid Yegoshin }
313fb6883e5SLeonid Yegoshin
3148508488fSSteven J. Hill /*
3158508488fSSteven J. Hill * Compute return address and emulate branch in MIPS16e mode after an
3168508488fSSteven J. Hill * exception only. It does not handle compact branches/jumps and cannot
3178508488fSSteven J. Hill * be used in interrupt context. (Compact branches/jumps do not cause
3188508488fSSteven J. Hill * exceptions.)
3198508488fSSteven J. Hill */
__MIPS16e_compute_return_epc(struct pt_regs * regs)3208508488fSSteven J. Hill int __MIPS16e_compute_return_epc(struct pt_regs *regs)
3218508488fSSteven J. Hill {
3228508488fSSteven J. Hill u16 __user *addr;
3238508488fSSteven J. Hill union mips16e_instruction inst;
3248508488fSSteven J. Hill u16 inst2;
3258508488fSSteven J. Hill u32 fullinst;
3268508488fSSteven J. Hill long epc;
3278508488fSSteven J. Hill
3288508488fSSteven J. Hill epc = regs->cp0_epc;
3298508488fSSteven J. Hill
3308508488fSSteven J. Hill /* Read the instruction. */
3318508488fSSteven J. Hill addr = (u16 __user *)msk_isa16_mode(epc);
3328508488fSSteven J. Hill if (__get_user(inst.full, addr)) {
3333cf5d076SEric W. Biederman force_sig(SIGSEGV);
3348508488fSSteven J. Hill return -EFAULT;
3358508488fSSteven J. Hill }
3368508488fSSteven J. Hill
3378508488fSSteven J. Hill switch (inst.ri.opcode) {
3388508488fSSteven J. Hill case MIPS16e_extend_op:
3398508488fSSteven J. Hill regs->cp0_epc += 4;
3408508488fSSteven J. Hill return 0;
3418508488fSSteven J. Hill
3428508488fSSteven J. Hill /*
3438508488fSSteven J. Hill * JAL and JALX in MIPS16e mode
3448508488fSSteven J. Hill */
3458508488fSSteven J. Hill case MIPS16e_jal_op:
3468508488fSSteven J. Hill addr += 1;
3478508488fSSteven J. Hill if (__get_user(inst2, addr)) {
3483cf5d076SEric W. Biederman force_sig(SIGSEGV);
3498508488fSSteven J. Hill return -EFAULT;
3508508488fSSteven J. Hill }
3518508488fSSteven J. Hill fullinst = ((unsigned)inst.full << 16) | inst2;
3528508488fSSteven J. Hill regs->regs[31] = epc + 6;
3538508488fSSteven J. Hill epc += 4;
3548508488fSSteven J. Hill epc >>= 28;
3558508488fSSteven J. Hill epc <<= 28;
3568508488fSSteven J. Hill /*
3578508488fSSteven J. Hill * JAL:5 X:1 TARGET[20-16]:5 TARGET[25:21]:5 TARGET[15:0]:16
3588508488fSSteven J. Hill *
3598508488fSSteven J. Hill * ......TARGET[15:0].................TARGET[20:16]...........
3608508488fSSteven J. Hill * ......TARGET[25:21]
3618508488fSSteven J. Hill */
3628508488fSSteven J. Hill epc |=
3638508488fSSteven J. Hill ((fullinst & 0xffff) << 2) | ((fullinst & 0x3e00000) >> 3) |
3648508488fSSteven J. Hill ((fullinst & 0x1f0000) << 7);
3658508488fSSteven J. Hill if (!inst.jal.x)
3668508488fSSteven J. Hill set_isa16_mode(epc); /* Set ISA mode bit. */
3678508488fSSteven J. Hill regs->cp0_epc = epc;
3688508488fSSteven J. Hill return 0;
3698508488fSSteven J. Hill
3708508488fSSteven J. Hill /*
3718508488fSSteven J. Hill * J(AL)R(C)
3728508488fSSteven J. Hill */
3738508488fSSteven J. Hill case MIPS16e_rr_op:
3748508488fSSteven J. Hill if (inst.rr.func == MIPS16e_jr_func) {
3758508488fSSteven J. Hill
3768508488fSSteven J. Hill if (inst.rr.ra)
3778508488fSSteven J. Hill regs->cp0_epc = regs->regs[31];
3788508488fSSteven J. Hill else
3798508488fSSteven J. Hill regs->cp0_epc =
3808508488fSSteven J. Hill regs->regs[reg16to32[inst.rr.rx]];
3818508488fSSteven J. Hill
3828508488fSSteven J. Hill if (inst.rr.l) {
3838508488fSSteven J. Hill if (inst.rr.nd)
3848508488fSSteven J. Hill regs->regs[31] = epc + 2;
3858508488fSSteven J. Hill else
3868508488fSSteven J. Hill regs->regs[31] = epc + 4;
3878508488fSSteven J. Hill }
3888508488fSSteven J. Hill return 0;
3898508488fSSteven J. Hill }
3908508488fSSteven J. Hill break;
3918508488fSSteven J. Hill }
3928508488fSSteven J. Hill
3938508488fSSteven J. Hill /*
3948508488fSSteven J. Hill * All other cases have no branch delay slot and are 16-bits.
3958508488fSSteven J. Hill * Branches do not cause an exception.
3968508488fSSteven J. Hill */
3978508488fSSteven J. Hill regs->cp0_epc += 2;
3988508488fSSteven J. Hill
3998508488fSSteven J. Hill return 0;
4008508488fSSteven J. Hill }
4018508488fSSteven J. Hill
402d8d4e3aeSManeesh Soni /**
403d8d4e3aeSManeesh Soni * __compute_return_epc_for_insn - Computes the return address and do emulate
404d8d4e3aeSManeesh Soni * branch simulation, if required.
405d8d4e3aeSManeesh Soni *
406d8d4e3aeSManeesh Soni * @regs: Pointer to pt_regs
407d8d4e3aeSManeesh Soni * @insn: branch instruction to decode
408cdf93470SMathieu Malaterre * Return: -EFAULT on error and forces SIGILL, and on success
409d8d4e3aeSManeesh Soni * returns 0 or BRANCH_LIKELY_TAKEN as appropriate after
410d8d4e3aeSManeesh Soni * evaluating the branch.
411a8ff66f5SMarkos Chandras *
412a8ff66f5SMarkos Chandras * MIPS R6 Compact branches and forbidden slots:
413a8ff66f5SMarkos Chandras * Compact branches do not throw exceptions because they do
414a8ff66f5SMarkos Chandras * not have delay slots. The forbidden slot instruction ($PC+4)
415a8ff66f5SMarkos Chandras * is only executed if the branch was not taken. Otherwise the
416a8ff66f5SMarkos Chandras * forbidden slot is skipped entirely. This means that the
417a8ff66f5SMarkos Chandras * only possible reason to be here because of a MIPS R6 compact
418a8ff66f5SMarkos Chandras * branch instruction is that the forbidden slot has thrown one.
419a8ff66f5SMarkos Chandras * In that case the branch was not taken, so the EPC can be safely
420a8ff66f5SMarkos Chandras * set to EPC + 8.
4211da177e4SLinus Torvalds */
__compute_return_epc_for_insn(struct pt_regs * regs,union mips_instruction insn)422d8d4e3aeSManeesh Soni int __compute_return_epc_for_insn(struct pt_regs *regs,
423d8d4e3aeSManeesh Soni union mips_instruction insn)
4241da177e4SLinus Torvalds {
425d8d4e3aeSManeesh Soni long epc = regs->cp0_epc;
4266a1cc218SPaul Burton unsigned int dspcontrol;
427d8d4e3aeSManeesh Soni int ret = 0;
4281da177e4SLinus Torvalds
4291da177e4SLinus Torvalds switch (insn.i_format.opcode) {
4301da177e4SLinus Torvalds /*
4311da177e4SLinus Torvalds * jr and jalr are in r_format format.
4321da177e4SLinus Torvalds */
4331da177e4SLinus Torvalds case spec_op:
4341da177e4SLinus Torvalds switch (insn.r_format.func) {
4351da177e4SLinus Torvalds case jalr_op:
4361da177e4SLinus Torvalds regs->regs[insn.r_format.rd] = epc + 8;
437c9b02990SLiangliang Huang fallthrough;
4381da177e4SLinus Torvalds case jr_op:
4395f9f41c4SMarkos Chandras if (NO_R6EMU && insn.r_format.func == jr_op)
4401f4edde4SMaciej W. Rozycki goto sigill_r2r6;
4411da177e4SLinus Torvalds regs->cp0_epc = regs->regs[insn.r_format.rs];
4421da177e4SLinus Torvalds break;
4431da177e4SLinus Torvalds }
4441da177e4SLinus Torvalds break;
4451da177e4SLinus Torvalds
4461da177e4SLinus Torvalds /*
4471da177e4SLinus Torvalds * This group contains:
4481da177e4SLinus Torvalds * bltz_op, bgez_op, bltzl_op, bgezl_op,
4491da177e4SLinus Torvalds * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
4501da177e4SLinus Torvalds */
4511da177e4SLinus Torvalds case bcond_op:
4521da177e4SLinus Torvalds switch (insn.i_format.rt) {
4531da177e4SLinus Torvalds case bltzl_op:
454319824eaSMarkos Chandras if (NO_R6EMU)
4551f4edde4SMaciej W. Rozycki goto sigill_r2r6;
456c9b02990SLiangliang Huang fallthrough;
457319824eaSMarkos Chandras case bltz_op:
458d8d4e3aeSManeesh Soni if ((long)regs->regs[insn.i_format.rs] < 0) {
4591da177e4SLinus Torvalds epc = epc + 4 + (insn.i_format.simmediate << 2);
460d8d4e3aeSManeesh Soni if (insn.i_format.rt == bltzl_op)
461d8d4e3aeSManeesh Soni ret = BRANCH_LIKELY_TAKEN;
462d8d4e3aeSManeesh Soni } else
4631da177e4SLinus Torvalds epc += 8;
4641da177e4SLinus Torvalds regs->cp0_epc = epc;
4651da177e4SLinus Torvalds break;
4661da177e4SLinus Torvalds
4671da177e4SLinus Torvalds case bgezl_op:
468319824eaSMarkos Chandras if (NO_R6EMU)
4691f4edde4SMaciej W. Rozycki goto sigill_r2r6;
470c9b02990SLiangliang Huang fallthrough;
471319824eaSMarkos Chandras case bgez_op:
472d8d4e3aeSManeesh Soni if ((long)regs->regs[insn.i_format.rs] >= 0) {
4731da177e4SLinus Torvalds epc = epc + 4 + (insn.i_format.simmediate << 2);
474d8d4e3aeSManeesh Soni if (insn.i_format.rt == bgezl_op)
475d8d4e3aeSManeesh Soni ret = BRANCH_LIKELY_TAKEN;
476d8d4e3aeSManeesh Soni } else
4771da177e4SLinus Torvalds epc += 8;
4781da177e4SLinus Torvalds regs->cp0_epc = epc;
4791da177e4SLinus Torvalds break;
4801da177e4SLinus Torvalds
4811da177e4SLinus Torvalds case bltzal_op:
4821da177e4SLinus Torvalds case bltzall_op:
483319824eaSMarkos Chandras if (NO_R6EMU && (insn.i_format.rs ||
484fef40be6SMaciej W. Rozycki insn.i_format.rt == bltzall_op))
485fef40be6SMaciej W. Rozycki goto sigill_r2r6;
4861da177e4SLinus Torvalds regs->regs[31] = epc + 8;
487319824eaSMarkos Chandras /*
488319824eaSMarkos Chandras * OK we are here either because we hit a NAL
489319824eaSMarkos Chandras * instruction or because we are emulating an
4904939788eSRalf Baechle * old bltzal{,l} one. Let's figure out what the
491319824eaSMarkos Chandras * case really is.
492319824eaSMarkos Chandras */
493319824eaSMarkos Chandras if (!insn.i_format.rs) {
494319824eaSMarkos Chandras /*
495319824eaSMarkos Chandras * NAL or BLTZAL with rs == 0
496319824eaSMarkos Chandras * Doesn't matter if we are R6 or not. The
497319824eaSMarkos Chandras * result is the same
498319824eaSMarkos Chandras */
499319824eaSMarkos Chandras regs->cp0_epc += 4 +
500319824eaSMarkos Chandras (insn.i_format.simmediate << 2);
501319824eaSMarkos Chandras break;
502319824eaSMarkos Chandras }
503319824eaSMarkos Chandras /* Now do the real thing for non-R6 BLTZAL{,L} */
504d8d4e3aeSManeesh Soni if ((long)regs->regs[insn.i_format.rs] < 0) {
5051da177e4SLinus Torvalds epc = epc + 4 + (insn.i_format.simmediate << 2);
506d8d4e3aeSManeesh Soni if (insn.i_format.rt == bltzall_op)
507d8d4e3aeSManeesh Soni ret = BRANCH_LIKELY_TAKEN;
508d8d4e3aeSManeesh Soni } else
5091da177e4SLinus Torvalds epc += 8;
5101da177e4SLinus Torvalds regs->cp0_epc = epc;
5111da177e4SLinus Torvalds break;
5121da177e4SLinus Torvalds
5131da177e4SLinus Torvalds case bgezal_op:
5141da177e4SLinus Torvalds case bgezall_op:
515319824eaSMarkos Chandras if (NO_R6EMU && (insn.i_format.rs ||
516fef40be6SMaciej W. Rozycki insn.i_format.rt == bgezall_op))
517fef40be6SMaciej W. Rozycki goto sigill_r2r6;
5181da177e4SLinus Torvalds regs->regs[31] = epc + 8;
519319824eaSMarkos Chandras /*
520319824eaSMarkos Chandras * OK we are here either because we hit a BAL
521319824eaSMarkos Chandras * instruction or because we are emulating an
5224939788eSRalf Baechle * old bgezal{,l} one. Let's figure out what the
523319824eaSMarkos Chandras * case really is.
524319824eaSMarkos Chandras */
525319824eaSMarkos Chandras if (!insn.i_format.rs) {
526319824eaSMarkos Chandras /*
527319824eaSMarkos Chandras * BAL or BGEZAL with rs == 0
528319824eaSMarkos Chandras * Doesn't matter if we are R6 or not. The
529319824eaSMarkos Chandras * result is the same
530319824eaSMarkos Chandras */
531319824eaSMarkos Chandras regs->cp0_epc += 4 +
532319824eaSMarkos Chandras (insn.i_format.simmediate << 2);
533319824eaSMarkos Chandras break;
534319824eaSMarkos Chandras }
535319824eaSMarkos Chandras /* Now do the real thing for non-R6 BGEZAL{,L} */
536d8d4e3aeSManeesh Soni if ((long)regs->regs[insn.i_format.rs] >= 0) {
5371da177e4SLinus Torvalds epc = epc + 4 + (insn.i_format.simmediate << 2);
538d8d4e3aeSManeesh Soni if (insn.i_format.rt == bgezall_op)
539d8d4e3aeSManeesh Soni ret = BRANCH_LIKELY_TAKEN;
540d8d4e3aeSManeesh Soni } else
5411da177e4SLinus Torvalds epc += 8;
5421da177e4SLinus Torvalds regs->cp0_epc = epc;
5431da177e4SLinus Torvalds break;
544d8d4e3aeSManeesh Soni
545e50c0a8fSRalf Baechle case bposge32_op:
546e50c0a8fSRalf Baechle if (!cpu_has_dsp)
5475f9f41c4SMarkos Chandras goto sigill_dsp;
548e50c0a8fSRalf Baechle
549e50c0a8fSRalf Baechle dspcontrol = rddsp(0x01);
550e50c0a8fSRalf Baechle
551e50c0a8fSRalf Baechle if (dspcontrol >= 32) {
552e50c0a8fSRalf Baechle epc = epc + 4 + (insn.i_format.simmediate << 2);
553e50c0a8fSRalf Baechle } else
554e50c0a8fSRalf Baechle epc += 8;
555e50c0a8fSRalf Baechle regs->cp0_epc = epc;
556e50c0a8fSRalf Baechle break;
5571da177e4SLinus Torvalds }
5581da177e4SLinus Torvalds break;
5591da177e4SLinus Torvalds
5601da177e4SLinus Torvalds /*
5611da177e4SLinus Torvalds * These are unconditional and in j_format.
5621da177e4SLinus Torvalds */
563a9db101bSMaciej W. Rozycki case jalx_op:
5641da177e4SLinus Torvalds case jal_op:
5651da177e4SLinus Torvalds regs->regs[31] = regs->cp0_epc + 8;
566c9b02990SLiangliang Huang fallthrough;
5671da177e4SLinus Torvalds case j_op:
5681da177e4SLinus Torvalds epc += 4;
5691da177e4SLinus Torvalds epc >>= 28;
5701da177e4SLinus Torvalds epc <<= 28;
5711da177e4SLinus Torvalds epc |= (insn.j_format.target << 2);
5721da177e4SLinus Torvalds regs->cp0_epc = epc;
573fb6883e5SLeonid Yegoshin if (insn.i_format.opcode == jalx_op)
574fb6883e5SLeonid Yegoshin set_isa16_mode(regs->cp0_epc);
5751da177e4SLinus Torvalds break;
5761da177e4SLinus Torvalds
5771da177e4SLinus Torvalds /*
5781da177e4SLinus Torvalds * These are conditional and in i_format.
5791da177e4SLinus Torvalds */
5801da177e4SLinus Torvalds case beql_op:
581319824eaSMarkos Chandras if (NO_R6EMU)
5821f4edde4SMaciej W. Rozycki goto sigill_r2r6;
583c9b02990SLiangliang Huang fallthrough;
584319824eaSMarkos Chandras case beq_op:
5851da177e4SLinus Torvalds if (regs->regs[insn.i_format.rs] ==
586d8d4e3aeSManeesh Soni regs->regs[insn.i_format.rt]) {
5871da177e4SLinus Torvalds epc = epc + 4 + (insn.i_format.simmediate << 2);
58841ca86e8SRalf Baechle if (insn.i_format.opcode == beql_op)
589d8d4e3aeSManeesh Soni ret = BRANCH_LIKELY_TAKEN;
590d8d4e3aeSManeesh Soni } else
5911da177e4SLinus Torvalds epc += 8;
5921da177e4SLinus Torvalds regs->cp0_epc = epc;
5931da177e4SLinus Torvalds break;
5941da177e4SLinus Torvalds
5951da177e4SLinus Torvalds case bnel_op:
596319824eaSMarkos Chandras if (NO_R6EMU)
5971f4edde4SMaciej W. Rozycki goto sigill_r2r6;
598c9b02990SLiangliang Huang fallthrough;
599319824eaSMarkos Chandras case bne_op:
6001da177e4SLinus Torvalds if (regs->regs[insn.i_format.rs] !=
601d8d4e3aeSManeesh Soni regs->regs[insn.i_format.rt]) {
6021da177e4SLinus Torvalds epc = epc + 4 + (insn.i_format.simmediate << 2);
60341ca86e8SRalf Baechle if (insn.i_format.opcode == bnel_op)
604d8d4e3aeSManeesh Soni ret = BRANCH_LIKELY_TAKEN;
605d8d4e3aeSManeesh Soni } else
6061da177e4SLinus Torvalds epc += 8;
6071da177e4SLinus Torvalds regs->cp0_epc = epc;
6081da177e4SLinus Torvalds break;
6091da177e4SLinus Torvalds
610319824eaSMarkos Chandras case blezl_op: /* not really i_format */
611e9d92d22SMarkos Chandras if (!insn.i_format.rt && NO_R6EMU)
6121f4edde4SMaciej W. Rozycki goto sigill_r2r6;
613c9b02990SLiangliang Huang fallthrough;
614319824eaSMarkos Chandras case blez_op:
615a8ff66f5SMarkos Chandras /*
616a8ff66f5SMarkos Chandras * Compact branches for R6 for the
617a8ff66f5SMarkos Chandras * blez and blezl opcodes.
618a8ff66f5SMarkos Chandras * BLEZ | rs = 0 | rt != 0 == BLEZALC
619a8ff66f5SMarkos Chandras * BLEZ | rs = rt != 0 == BGEZALC
620a8ff66f5SMarkos Chandras * BLEZ | rs != 0 | rt != 0 == BGEUC
621a8ff66f5SMarkos Chandras * BLEZL | rs = 0 | rt != 0 == BLEZC
622a8ff66f5SMarkos Chandras * BLEZL | rs = rt != 0 == BGEZC
623a8ff66f5SMarkos Chandras * BLEZL | rs != 0 | rt != 0 == BGEC
624a8ff66f5SMarkos Chandras *
625a8ff66f5SMarkos Chandras * For real BLEZ{,L}, rt is always 0.
626a8ff66f5SMarkos Chandras */
627a8ff66f5SMarkos Chandras
628a8ff66f5SMarkos Chandras if (cpu_has_mips_r6 && insn.i_format.rt) {
629a8ff66f5SMarkos Chandras if ((insn.i_format.opcode == blez_op) &&
630a8ff66f5SMarkos Chandras ((!insn.i_format.rs && insn.i_format.rt) ||
631a8ff66f5SMarkos Chandras (insn.i_format.rs == insn.i_format.rt)))
632a8ff66f5SMarkos Chandras regs->regs[31] = epc + 4;
633a8ff66f5SMarkos Chandras regs->cp0_epc += 8;
634a8ff66f5SMarkos Chandras break;
635a8ff66f5SMarkos Chandras }
6361da177e4SLinus Torvalds /* rt field assumed to be zero */
637d8d4e3aeSManeesh Soni if ((long)regs->regs[insn.i_format.rs] <= 0) {
6381da177e4SLinus Torvalds epc = epc + 4 + (insn.i_format.simmediate << 2);
63941ca86e8SRalf Baechle if (insn.i_format.opcode == blezl_op)
640d8d4e3aeSManeesh Soni ret = BRANCH_LIKELY_TAKEN;
641d8d4e3aeSManeesh Soni } else
6421da177e4SLinus Torvalds epc += 8;
6431da177e4SLinus Torvalds regs->cp0_epc = epc;
6441da177e4SLinus Torvalds break;
6451da177e4SLinus Torvalds
6461da177e4SLinus Torvalds case bgtzl_op:
647e9d92d22SMarkos Chandras if (!insn.i_format.rt && NO_R6EMU)
6481f4edde4SMaciej W. Rozycki goto sigill_r2r6;
649c9b02990SLiangliang Huang fallthrough;
650319824eaSMarkos Chandras case bgtz_op:
651f1b44067SMarkos Chandras /*
652f1b44067SMarkos Chandras * Compact branches for R6 for the
653f1b44067SMarkos Chandras * bgtz and bgtzl opcodes.
654f1b44067SMarkos Chandras * BGTZ | rs = 0 | rt != 0 == BGTZALC
655f1b44067SMarkos Chandras * BGTZ | rs = rt != 0 == BLTZALC
656f1b44067SMarkos Chandras * BGTZ | rs != 0 | rt != 0 == BLTUC
657f1b44067SMarkos Chandras * BGTZL | rs = 0 | rt != 0 == BGTZC
658f1b44067SMarkos Chandras * BGTZL | rs = rt != 0 == BLTZC
659f1b44067SMarkos Chandras * BGTZL | rs != 0 | rt != 0 == BLTC
660f1b44067SMarkos Chandras *
661f1b44067SMarkos Chandras * *ZALC varint for BGTZ &&& rt != 0
662f1b44067SMarkos Chandras * For real GTZ{,L}, rt is always 0.
663f1b44067SMarkos Chandras */
664f1b44067SMarkos Chandras if (cpu_has_mips_r6 && insn.i_format.rt) {
665f1b44067SMarkos Chandras if ((insn.i_format.opcode == blez_op) &&
666f1b44067SMarkos Chandras ((!insn.i_format.rs && insn.i_format.rt) ||
667f1b44067SMarkos Chandras (insn.i_format.rs == insn.i_format.rt)))
668f1b44067SMarkos Chandras regs->regs[31] = epc + 4;
669f1b44067SMarkos Chandras regs->cp0_epc += 8;
670f1b44067SMarkos Chandras break;
671f1b44067SMarkos Chandras }
672f1b44067SMarkos Chandras
6731da177e4SLinus Torvalds /* rt field assumed to be zero */
674d8d4e3aeSManeesh Soni if ((long)regs->regs[insn.i_format.rs] > 0) {
6751da177e4SLinus Torvalds epc = epc + 4 + (insn.i_format.simmediate << 2);
67641ca86e8SRalf Baechle if (insn.i_format.opcode == bgtzl_op)
677d8d4e3aeSManeesh Soni ret = BRANCH_LIKELY_TAKEN;
678d8d4e3aeSManeesh Soni } else
6791da177e4SLinus Torvalds epc += 8;
6801da177e4SLinus Torvalds regs->cp0_epc = epc;
6811da177e4SLinus Torvalds break;
6821da177e4SLinus Torvalds
6836a1cc218SPaul Burton #ifdef CONFIG_MIPS_FP_SUPPORT
6841da177e4SLinus Torvalds /*
6851da177e4SLinus Torvalds * And now the FPA/cp1 branch instructions.
6861da177e4SLinus Torvalds */
6876a1cc218SPaul Burton case cop1_op: {
6886a1cc218SPaul Burton unsigned int bit, fcr31, reg;
6896a1cc218SPaul Burton
690c8a34581SMarkos Chandras if (cpu_has_mips_r6 &&
691c8a34581SMarkos Chandras ((insn.i_format.rs == bc1eqz_op) ||
692c8a34581SMarkos Chandras (insn.i_format.rs == bc1nez_op))) {
693cc97ab23SPaul Burton if (!init_fp_ctx(current))
694cc97ab23SPaul Burton lose_fpu(1);
695c8a34581SMarkos Chandras reg = insn.i_format.rt;
696ac149698SPaul Burton bit = get_fpr32(¤t->thread.fpu.fpr[reg], 0) & 0x1;
697ac149698SPaul Burton if (insn.i_format.rs == bc1eqz_op)
698ac149698SPaul Burton bit = !bit;
699c8a34581SMarkos Chandras own_fpu(1);
700c8a34581SMarkos Chandras if (bit)
701c8a34581SMarkos Chandras epc = epc + 4 +
702c8a34581SMarkos Chandras (insn.i_format.simmediate << 2);
703c8a34581SMarkos Chandras else
704c8a34581SMarkos Chandras epc += 8;
705c8a34581SMarkos Chandras regs->cp0_epc = epc;
706c8a34581SMarkos Chandras
707c8a34581SMarkos Chandras break;
708c8a34581SMarkos Chandras } else {
709c8a34581SMarkos Chandras
7101d74f6bcSRalf Baechle preempt_disable();
7111d74f6bcSRalf Baechle if (is_fpu_owner())
712842dfc11SManuel Lauss fcr31 = read_32bit_cp1_register(CP1_STATUS);
7131d74f6bcSRalf Baechle else
714eae89076SAtsushi Nemoto fcr31 = current->thread.fpu.fcr31;
7151d74f6bcSRalf Baechle preempt_enable();
7161d74f6bcSRalf Baechle
7171da177e4SLinus Torvalds bit = (insn.i_format.rt >> 2);
7181da177e4SLinus Torvalds bit += (bit != 0);
7191da177e4SLinus Torvalds bit += 23;
720ee1cca1bSRalf Baechle switch (insn.i_format.rt & 3) {
7211da177e4SLinus Torvalds case 0: /* bc1f */
7221da177e4SLinus Torvalds case 2: /* bc1fl */
723d8d4e3aeSManeesh Soni if (~fcr31 & (1 << bit)) {
724c8a34581SMarkos Chandras epc = epc + 4 +
725c8a34581SMarkos Chandras (insn.i_format.simmediate << 2);
726d8d4e3aeSManeesh Soni if (insn.i_format.rt == 2)
727d8d4e3aeSManeesh Soni ret = BRANCH_LIKELY_TAKEN;
728d8d4e3aeSManeesh Soni } else
7291da177e4SLinus Torvalds epc += 8;
7301da177e4SLinus Torvalds regs->cp0_epc = epc;
7311da177e4SLinus Torvalds break;
7321da177e4SLinus Torvalds
7331da177e4SLinus Torvalds case 1: /* bc1t */
7341da177e4SLinus Torvalds case 3: /* bc1tl */
735d8d4e3aeSManeesh Soni if (fcr31 & (1 << bit)) {
736c8a34581SMarkos Chandras epc = epc + 4 +
737c8a34581SMarkos Chandras (insn.i_format.simmediate << 2);
738d8d4e3aeSManeesh Soni if (insn.i_format.rt == 3)
739d8d4e3aeSManeesh Soni ret = BRANCH_LIKELY_TAKEN;
740d8d4e3aeSManeesh Soni } else
7411da177e4SLinus Torvalds epc += 8;
7421da177e4SLinus Torvalds regs->cp0_epc = epc;
7431da177e4SLinus Torvalds break;
7441da177e4SLinus Torvalds }
7451da177e4SLinus Torvalds break;
746c8a34581SMarkos Chandras }
7476a1cc218SPaul Burton }
7486a1cc218SPaul Burton #endif /* CONFIG_MIPS_FP_SUPPORT */
7496a1cc218SPaul Burton
750126336f0SDavid Daney #ifdef CONFIG_CPU_CAVIUM_OCTEON
751126336f0SDavid Daney case lwc2_op: /* This is bbit0 on Octeon */
752126336f0SDavid Daney if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
753126336f0SDavid Daney == 0)
754126336f0SDavid Daney epc = epc + 4 + (insn.i_format.simmediate << 2);
755126336f0SDavid Daney else
756126336f0SDavid Daney epc += 8;
757126336f0SDavid Daney regs->cp0_epc = epc;
758126336f0SDavid Daney break;
759126336f0SDavid Daney case ldc2_op: /* This is bbit032 on Octeon */
760126336f0SDavid Daney if ((regs->regs[insn.i_format.rs] &
761126336f0SDavid Daney (1ull<<(insn.i_format.rt+32))) == 0)
762126336f0SDavid Daney epc = epc + 4 + (insn.i_format.simmediate << 2);
763126336f0SDavid Daney else
764126336f0SDavid Daney epc += 8;
765126336f0SDavid Daney regs->cp0_epc = epc;
766126336f0SDavid Daney break;
767126336f0SDavid Daney case swc2_op: /* This is bbit1 on Octeon */
768126336f0SDavid Daney if (regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
769126336f0SDavid Daney epc = epc + 4 + (insn.i_format.simmediate << 2);
770126336f0SDavid Daney else
771126336f0SDavid Daney epc += 8;
772126336f0SDavid Daney regs->cp0_epc = epc;
773126336f0SDavid Daney break;
774126336f0SDavid Daney case sdc2_op: /* This is bbit132 on Octeon */
775126336f0SDavid Daney if (regs->regs[insn.i_format.rs] &
776126336f0SDavid Daney (1ull<<(insn.i_format.rt+32)))
777126336f0SDavid Daney epc = epc + 4 + (insn.i_format.simmediate << 2);
778126336f0SDavid Daney else
779126336f0SDavid Daney epc += 8;
780126336f0SDavid Daney regs->cp0_epc = epc;
781126336f0SDavid Daney break;
7828467ca01SMarkos Chandras #else
7838467ca01SMarkos Chandras case bc6_op:
7848467ca01SMarkos Chandras /* Only valid for MIPS R6 */
785a60b1a5bSMaciej W. Rozycki if (!cpu_has_mips_r6)
786a60b1a5bSMaciej W. Rozycki goto sigill_r6;
7878467ca01SMarkos Chandras regs->cp0_epc += 8;
7888467ca01SMarkos Chandras break;
78984fef630SMarkos Chandras case balc6_op:
790a60b1a5bSMaciej W. Rozycki if (!cpu_has_mips_r6)
791a60b1a5bSMaciej W. Rozycki goto sigill_r6;
79284fef630SMarkos Chandras /* Compact branch: BALC */
79384fef630SMarkos Chandras regs->regs[31] = epc + 4;
79484fef630SMarkos Chandras epc += 4 + (insn.i_format.simmediate << 2);
79584fef630SMarkos Chandras regs->cp0_epc = epc;
79684fef630SMarkos Chandras break;
7971c66b79bSPaul Burton case pop66_op:
798a60b1a5bSMaciej W. Rozycki if (!cpu_has_mips_r6)
799a60b1a5bSMaciej W. Rozycki goto sigill_r6;
80069b9a2fdSMarkos Chandras /* Compact branch: BEQZC || JIC */
80169b9a2fdSMarkos Chandras regs->cp0_epc += 8;
80269b9a2fdSMarkos Chandras break;
8031c66b79bSPaul Burton case pop76_op:
804a60b1a5bSMaciej W. Rozycki if (!cpu_has_mips_r6)
805a60b1a5bSMaciej W. Rozycki goto sigill_r6;
80628d6f93dSMarkos Chandras /* Compact branch: BNEZC || JIALC */
8071a73d931SPaul Burton if (!insn.i_format.rs) {
8081a73d931SPaul Burton /* JIALC: set $31/ra */
80928d6f93dSMarkos Chandras regs->regs[31] = epc + 4;
8101a73d931SPaul Burton }
81128d6f93dSMarkos Chandras regs->cp0_epc += 8;
81228d6f93dSMarkos Chandras break;
813126336f0SDavid Daney #endif
8141b492600SPaul Burton case pop10_op:
8151b492600SPaul Burton case pop30_op:
816c893ce38SMarkos Chandras /* Only valid for MIPS R6 */
817a60b1a5bSMaciej W. Rozycki if (!cpu_has_mips_r6)
818a60b1a5bSMaciej W. Rozycki goto sigill_r6;
81910d962d5SMarkos Chandras /*
82010d962d5SMarkos Chandras * Compact branches:
82110d962d5SMarkos Chandras * bovc, beqc, beqzalc, bnvc, bnec, bnezlac
82210d962d5SMarkos Chandras */
823c893ce38SMarkos Chandras if (insn.i_format.rt && !insn.i_format.rs)
824c893ce38SMarkos Chandras regs->regs[31] = epc + 4;
825c893ce38SMarkos Chandras regs->cp0_epc += 8;
826c893ce38SMarkos Chandras break;
8271da177e4SLinus Torvalds }
8281da177e4SLinus Torvalds
829d8d4e3aeSManeesh Soni return ret;
830d8d4e3aeSManeesh Soni
8315f9f41c4SMarkos Chandras sigill_dsp:
832f259fe29SMaciej W. Rozycki pr_debug("%s: DSP branch but not DSP ASE - sending SIGILL.\n",
8337b82c105SMaciej W. Rozycki current->comm);
8343cf5d076SEric W. Biederman force_sig(SIGILL);
835d8d4e3aeSManeesh Soni return -EFAULT;
8361f4edde4SMaciej W. Rozycki sigill_r2r6:
837f259fe29SMaciej W. Rozycki pr_debug("%s: R2 branch but r2-to-r6 emulator is not present - sending SIGILL.\n",
8385f9f41c4SMarkos Chandras current->comm);
8393cf5d076SEric W. Biederman force_sig(SIGILL);
8405f9f41c4SMarkos Chandras return -EFAULT;
841a60b1a5bSMaciej W. Rozycki sigill_r6:
842f259fe29SMaciej W. Rozycki pr_debug("%s: R6 branch but no MIPSr6 ISA support - sending SIGILL.\n",
843a60b1a5bSMaciej W. Rozycki current->comm);
8443cf5d076SEric W. Biederman force_sig(SIGILL);
845a60b1a5bSMaciej W. Rozycki return -EFAULT;
846d8d4e3aeSManeesh Soni }
847d8d4e3aeSManeesh Soni EXPORT_SYMBOL_GPL(__compute_return_epc_for_insn);
848d8d4e3aeSManeesh Soni
__compute_return_epc(struct pt_regs * regs)849d8d4e3aeSManeesh Soni int __compute_return_epc(struct pt_regs *regs)
850d8d4e3aeSManeesh Soni {
851d8d4e3aeSManeesh Soni unsigned int __user *addr;
852d8d4e3aeSManeesh Soni long epc;
853d8d4e3aeSManeesh Soni union mips_instruction insn;
854d8d4e3aeSManeesh Soni
855d8d4e3aeSManeesh Soni epc = regs->cp0_epc;
856d8d4e3aeSManeesh Soni if (epc & 3)
857d8d4e3aeSManeesh Soni goto unaligned;
858d8d4e3aeSManeesh Soni
859d8d4e3aeSManeesh Soni /*
860d8d4e3aeSManeesh Soni * Read the instruction
861d8d4e3aeSManeesh Soni */
862d8d4e3aeSManeesh Soni addr = (unsigned int __user *) epc;
863d8d4e3aeSManeesh Soni if (__get_user(insn.word, addr)) {
8643cf5d076SEric W. Biederman force_sig(SIGSEGV);
865d8d4e3aeSManeesh Soni return -EFAULT;
866d8d4e3aeSManeesh Soni }
867d8d4e3aeSManeesh Soni
868d8d4e3aeSManeesh Soni return __compute_return_epc_for_insn(regs, insn);
8691da177e4SLinus Torvalds
8701da177e4SLinus Torvalds unaligned:
8711da177e4SLinus Torvalds printk("%s: unaligned epc - sending SIGBUS.\n", current->comm);
8723cf5d076SEric W. Biederman force_sig(SIGBUS);
8731da177e4SLinus Torvalds return -EFAULT;
8741da177e4SLinus Torvalds }
875d05c5130SMarcin Nowakowski
876d05c5130SMarcin Nowakowski #if (defined CONFIG_KPROBES) || (defined CONFIG_UPROBES)
877d05c5130SMarcin Nowakowski
__insn_is_compact_branch(union mips_instruction insn)878d05c5130SMarcin Nowakowski int __insn_is_compact_branch(union mips_instruction insn)
879d05c5130SMarcin Nowakowski {
880d05c5130SMarcin Nowakowski if (!cpu_has_mips_r6)
881d05c5130SMarcin Nowakowski return 0;
882d05c5130SMarcin Nowakowski
883d05c5130SMarcin Nowakowski switch (insn.i_format.opcode) {
884d05c5130SMarcin Nowakowski case blezl_op:
885d05c5130SMarcin Nowakowski case bgtzl_op:
886d05c5130SMarcin Nowakowski case blez_op:
887d05c5130SMarcin Nowakowski case bgtz_op:
888d05c5130SMarcin Nowakowski /*
889d05c5130SMarcin Nowakowski * blez[l] and bgtz[l] opcodes with non-zero rt
890d05c5130SMarcin Nowakowski * are MIPS R6 compact branches
891d05c5130SMarcin Nowakowski */
892d05c5130SMarcin Nowakowski if (insn.i_format.rt)
893d05c5130SMarcin Nowakowski return 1;
894d05c5130SMarcin Nowakowski break;
895d05c5130SMarcin Nowakowski case bc6_op:
896d05c5130SMarcin Nowakowski case balc6_op:
897d05c5130SMarcin Nowakowski case pop10_op:
898d05c5130SMarcin Nowakowski case pop30_op:
899d05c5130SMarcin Nowakowski case pop66_op:
900d05c5130SMarcin Nowakowski case pop76_op:
901d05c5130SMarcin Nowakowski return 1;
902d05c5130SMarcin Nowakowski }
903d05c5130SMarcin Nowakowski
904d05c5130SMarcin Nowakowski return 0;
905d05c5130SMarcin Nowakowski }
906d05c5130SMarcin Nowakowski EXPORT_SYMBOL_GPL(__insn_is_compact_branch);
907d05c5130SMarcin Nowakowski
908d05c5130SMarcin Nowakowski #endif /* CONFIG_KPROBES || CONFIG_UPROBES */
909