1 /* 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 4 * for more details. 5 * 6 * Copyright (C) 1996, 97, 2000, 2001 by Ralf Baechle 7 * Copyright (C) 2001 MIPS Technologies, Inc. 8 */ 9 #include <linux/kernel.h> 10 #include <linux/sched.h> 11 #include <linux/signal.h> 12 #include <asm/branch.h> 13 #include <asm/cpu.h> 14 #include <asm/cpu-features.h> 15 #include <asm/inst.h> 16 #include <asm/ptrace.h> 17 #include <asm/uaccess.h> 18 19 /* 20 * Compute the return address and do emulate branch simulation, if required. 21 */ 22 int __compute_return_epc(struct pt_regs *regs) 23 { 24 unsigned int *addr, bit, fcr31; 25 long epc; 26 union mips_instruction insn; 27 28 epc = regs->cp0_epc; 29 if (epc & 3) 30 goto unaligned; 31 32 /* 33 * Read the instruction 34 */ 35 addr = (unsigned int *) epc; 36 if (__get_user(insn.word, addr)) { 37 force_sig(SIGSEGV, current); 38 return -EFAULT; 39 } 40 41 regs->regs[0] = 0; 42 switch (insn.i_format.opcode) { 43 /* 44 * jr and jalr are in r_format format. 45 */ 46 case spec_op: 47 switch (insn.r_format.func) { 48 case jalr_op: 49 regs->regs[insn.r_format.rd] = epc + 8; 50 /* Fall through */ 51 case jr_op: 52 regs->cp0_epc = regs->regs[insn.r_format.rs]; 53 break; 54 } 55 break; 56 57 /* 58 * This group contains: 59 * bltz_op, bgez_op, bltzl_op, bgezl_op, 60 * bltzal_op, bgezal_op, bltzall_op, bgezall_op. 61 */ 62 case bcond_op: 63 switch (insn.i_format.rt) { 64 case bltz_op: 65 case bltzl_op: 66 if ((long)regs->regs[insn.i_format.rs] < 0) 67 epc = epc + 4 + (insn.i_format.simmediate << 2); 68 else 69 epc += 8; 70 regs->cp0_epc = epc; 71 break; 72 73 case bgez_op: 74 case bgezl_op: 75 if ((long)regs->regs[insn.i_format.rs] >= 0) 76 epc = epc + 4 + (insn.i_format.simmediate << 2); 77 else 78 epc += 8; 79 regs->cp0_epc = epc; 80 break; 81 82 case bltzal_op: 83 case bltzall_op: 84 regs->regs[31] = epc + 8; 85 if ((long)regs->regs[insn.i_format.rs] < 0) 86 epc = epc + 4 + (insn.i_format.simmediate << 2); 87 else 88 epc += 8; 89 regs->cp0_epc = epc; 90 break; 91 92 case bgezal_op: 93 case bgezall_op: 94 regs->regs[31] = epc + 8; 95 if ((long)regs->regs[insn.i_format.rs] >= 0) 96 epc = epc + 4 + (insn.i_format.simmediate << 2); 97 else 98 epc += 8; 99 regs->cp0_epc = epc; 100 break; 101 } 102 break; 103 104 /* 105 * These are unconditional and in j_format. 106 */ 107 case jal_op: 108 regs->regs[31] = regs->cp0_epc + 8; 109 case j_op: 110 epc += 4; 111 epc >>= 28; 112 epc <<= 28; 113 epc |= (insn.j_format.target << 2); 114 regs->cp0_epc = epc; 115 break; 116 117 /* 118 * These are conditional and in i_format. 119 */ 120 case beq_op: 121 case beql_op: 122 if (regs->regs[insn.i_format.rs] == 123 regs->regs[insn.i_format.rt]) 124 epc = epc + 4 + (insn.i_format.simmediate << 2); 125 else 126 epc += 8; 127 regs->cp0_epc = epc; 128 break; 129 130 case bne_op: 131 case bnel_op: 132 if (regs->regs[insn.i_format.rs] != 133 regs->regs[insn.i_format.rt]) 134 epc = epc + 4 + (insn.i_format.simmediate << 2); 135 else 136 epc += 8; 137 regs->cp0_epc = epc; 138 break; 139 140 case blez_op: /* not really i_format */ 141 case blezl_op: 142 /* rt field assumed to be zero */ 143 if ((long)regs->regs[insn.i_format.rs] <= 0) 144 epc = epc + 4 + (insn.i_format.simmediate << 2); 145 else 146 epc += 8; 147 regs->cp0_epc = epc; 148 break; 149 150 case bgtz_op: 151 case bgtzl_op: 152 /* rt field assumed to be zero */ 153 if ((long)regs->regs[insn.i_format.rs] > 0) 154 epc = epc + 4 + (insn.i_format.simmediate << 2); 155 else 156 epc += 8; 157 regs->cp0_epc = epc; 158 break; 159 160 /* 161 * And now the FPA/cp1 branch instructions. 162 */ 163 case cop1_op: 164 if (!cpu_has_fpu) 165 fcr31 = current->thread.fpu.soft.fcr31; 166 else 167 asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); 168 bit = (insn.i_format.rt >> 2); 169 bit += (bit != 0); 170 bit += 23; 171 switch (insn.i_format.rt) { 172 case 0: /* bc1f */ 173 case 2: /* bc1fl */ 174 if (~fcr31 & (1 << bit)) 175 epc = epc + 4 + (insn.i_format.simmediate << 2); 176 else 177 epc += 8; 178 regs->cp0_epc = epc; 179 break; 180 181 case 1: /* bc1t */ 182 case 3: /* bc1tl */ 183 if (fcr31 & (1 << bit)) 184 epc = epc + 4 + (insn.i_format.simmediate << 2); 185 else 186 epc += 8; 187 regs->cp0_epc = epc; 188 break; 189 } 190 break; 191 } 192 193 return 0; 194 195 unaligned: 196 printk("%s: unaligned epc - sending SIGBUS.\n", current->comm); 197 force_sig(SIGBUS, current); 198 return -EFAULT; 199 } 200