2 * Branch and jump emulation.
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
8 * Copyright (C) 1996, 97, 2000, 2001 by Ralf Baechle
9 * Copyright (C) 2001 MIPS Technologies, Inc.
11 #include <linux/kernel.h>
12 #include <linux/sched.h>
13 #include <linux/signal.h>
14 #include <asm/branch.h>
17 #include <asm/ptrace.h>
18 #include <asm/uaccess.h>
19 #include <asm/processor.h>
22 * Compute the return address and do emulate branch simulation, if required.
24 int __compute_return_epc(struct pt_regs *regs)
26 unsigned int *addr, bit, fcr31;
28 union mips_instruction insn;
35 * Read the instruction
37 addr = (unsigned int *) (unsigned long) epc;
38 if (__get_user(insn.word, addr)) {
39 force_sig(SIGSEGV, current);
44 switch (insn.i_format.opcode) {
46 * jr and jalr are in r_format format.
49 switch (insn.r_format.func) {
51 regs->regs[insn.r_format.rd] = epc + 8;
54 regs->cp0_epc = regs->regs[insn.r_format.rs];
60 * This group contains:
61 * bltz_op, bgez_op, bltzl_op, bgezl_op,
62 * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
65 switch (insn.i_format.rt) {
68 if ((long)regs->regs[insn.i_format.rs] < 0)
69 epc = epc + 4 + (insn.i_format.simmediate << 2);
77 if ((long)regs->regs[insn.i_format.rs] >= 0)
78 epc = epc + 4 + (insn.i_format.simmediate << 2);
86 regs->regs[31] = epc + 8;
87 if ((long)regs->regs[insn.i_format.rs] < 0)
88 epc = epc + 4 + (insn.i_format.simmediate << 2);
96 regs->regs[31] = epc + 8;
97 if ((long)regs->regs[insn.i_format.rs] >= 0)
98 epc = epc + 4 + (insn.i_format.simmediate << 2);
107 * These are unconditional and in j_format.
110 regs->regs[31] = regs->cp0_epc + 8;
115 epc |= (insn.j_format.target << 2);
120 * These are conditional and in i_format.
124 if (regs->regs[insn.i_format.rs] ==
125 regs->regs[insn.i_format.rt])
126 epc = epc + 4 + (insn.i_format.simmediate << 2);
134 if (regs->regs[insn.i_format.rs] !=
135 regs->regs[insn.i_format.rt])
136 epc = epc + 4 + (insn.i_format.simmediate << 2);
142 case blez_op: /* not really i_format */
144 /* rt field assumed to be zero */
145 if ((long)regs->regs[insn.i_format.rs] <= 0)
146 epc = epc + 4 + (insn.i_format.simmediate << 2);
154 /* rt field assumed to be zero */
155 if ((long)regs->regs[insn.i_format.rs] > 0)
156 epc = epc + 4 + (insn.i_format.simmediate << 2);
163 * And now the FPA/cp1 branch instructions.
167 fcr31 = current->thread.fpu.soft.sr;
169 asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
170 bit = (insn.i_format.rt >> 2);
173 switch (insn.i_format.rt) {
176 if (~fcr31 & (1 << bit))
177 epc = epc + 4 + (insn.i_format.simmediate << 2);
185 if (fcr31 & (1 << bit))
186 epc = epc + 4 + (insn.i_format.simmediate << 2);
198 printk("%s: unaligned epc - sending SIGBUS.\n", current->comm);
199 force_sig(SIGBUS, current);