2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 1996, 97, 2000, 2001 by Ralf Baechle
7 * Copyright (C) 2001 MIPS Technologies, Inc.
9 #include <linux/kernel.h>
10 #include <linux/sched.h>
11 #include <linux/signal.h>
12 #include <asm/branch.h>
14 #include <asm/cpu-features.h>
17 #include <asm/ptrace.h>
18 #include <asm/uaccess.h>
21 * Compute the return address and do emulate branch simulation, if required.
23 int __compute_return_epc(struct pt_regs *regs)
25 unsigned int *addr, bit, fcr31;
27 union mips_instruction insn;
34 * Read the instruction
36 addr = (unsigned int *) epc;
37 if (__get_user(insn.word, addr)) {
38 force_sig(SIGSEGV, current);
43 switch (insn.i_format.opcode) {
45 * jr and jalr are in r_format format.
48 switch (insn.r_format.func) {
50 regs->regs[insn.r_format.rd] = epc + 8;
53 regs->cp0_epc = regs->regs[insn.r_format.rs];
59 * This group contains:
60 * bltz_op, bgez_op, bltzl_op, bgezl_op,
61 * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
64 switch (insn.i_format.rt) {
67 if ((long)regs->regs[insn.i_format.rs] < 0)
68 epc = epc + 4 + (insn.i_format.simmediate << 2);
76 if ((long)regs->regs[insn.i_format.rs] >= 0)
77 epc = epc + 4 + (insn.i_format.simmediate << 2);
85 regs->regs[31] = epc + 8;
86 if ((long)regs->regs[insn.i_format.rs] < 0)
87 epc = epc + 4 + (insn.i_format.simmediate << 2);
95 regs->regs[31] = epc + 8;
96 if ((long)regs->regs[insn.i_format.rs] >= 0)
97 epc = epc + 4 + (insn.i_format.simmediate << 2);
106 * These are unconditional and in j_format.
109 regs->regs[31] = regs->cp0_epc + 8;
114 epc |= (insn.j_format.target << 2);
119 * These are conditional and in i_format.
123 if (regs->regs[insn.i_format.rs] ==
124 regs->regs[insn.i_format.rt])
125 epc = epc + 4 + (insn.i_format.simmediate << 2);
133 if (regs->regs[insn.i_format.rs] !=
134 regs->regs[insn.i_format.rt])
135 epc = epc + 4 + (insn.i_format.simmediate << 2);
141 case blez_op: /* not really i_format */
143 /* rt field assumed to be zero */
144 if ((long)regs->regs[insn.i_format.rs] <= 0)
145 epc = epc + 4 + (insn.i_format.simmediate << 2);
153 /* rt field assumed to be zero */
154 if ((long)regs->regs[insn.i_format.rs] > 0)
155 epc = epc + 4 + (insn.i_format.simmediate << 2);
162 * And now the FPA/cp1 branch instructions.
167 asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
169 fcr31 = current->thread.fpu.hard.fcr31;
172 bit = (insn.i_format.rt >> 2);
175 switch (insn.i_format.rt) {
178 if (~fcr31 & (1 << bit))
179 epc = epc + 4 + (insn.i_format.simmediate << 2);
187 if (fcr31 & (1 << bit))
188 epc = epc + 4 + (insn.i_format.simmediate << 2);
200 printk("%s: unaligned epc - sending SIGBUS.\n", current->comm);
201 force_sig(SIGBUS, current);