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, dspcontrol;
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 dspcontrol = rddsp(0x01);
108 if (dspcontrol >= 32) {
109 epc = epc + 4 + (insn.i_format.simmediate << 2);
118 * These are unconditional and in j_format.
121 regs->regs[31] = regs->cp0_epc + 8;
126 epc |= (insn.j_format.target << 2);
131 * These are conditional and in i_format.
135 if (regs->regs[insn.i_format.rs] ==
136 regs->regs[insn.i_format.rt])
137 epc = epc + 4 + (insn.i_format.simmediate << 2);
145 if (regs->regs[insn.i_format.rs] !=
146 regs->regs[insn.i_format.rt])
147 epc = epc + 4 + (insn.i_format.simmediate << 2);
153 case blez_op: /* not really i_format */
155 /* rt field assumed to be zero */
156 if ((long)regs->regs[insn.i_format.rs] <= 0)
157 epc = epc + 4 + (insn.i_format.simmediate << 2);
165 /* rt field assumed to be zero */
166 if ((long)regs->regs[insn.i_format.rs] > 0)
167 epc = epc + 4 + (insn.i_format.simmediate << 2);
174 * And now the FPA/cp1 branch instructions.
179 asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
181 fcr31 = current->thread.fpu.hard.fcr31;
184 bit = (insn.i_format.rt >> 2);
187 switch (insn.i_format.rt & 3) {
190 if (~fcr31 & (1 << bit))
191 epc = epc + 4 + (insn.i_format.simmediate << 2);
199 if (fcr31 & (1 << bit))
200 epc = epc + 4 + (insn.i_format.simmediate << 2);
212 printk("%s: unaligned epc - sending SIGBUS.\n", current->comm);
213 force_sig(SIGBUS, current);
217 printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm);
218 force_sig(SIGBUS, current);