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/fpu.h>
16 #include <asm/inst.h>
17 #include <asm/ptrace.h>
18 #include <asm/uaccess.h>
19 
20 /*
21  * Compute the return address and do emulate branch simulation, if required.
22  */
__compute_return_epc(struct pt_regs * regs)23 int __compute_return_epc(struct pt_regs *regs)
24 {
25 	unsigned int __user *addr;
26 	unsigned int bit, fcr31, dspcontrol;
27 	long epc;
28 	union mips_instruction insn;
29 
30 	epc = regs->cp0_epc;
31 	if (epc & 3)
32 		goto unaligned;
33 
34 	/*
35 	 * Read the instruction
36 	 */
37 	addr = (unsigned int __user *) epc;
38 	if (__get_user(insn.word, addr)) {
39 		force_sig(SIGSEGV, current);
40 		return -EFAULT;
41 	}
42 
43 	switch (insn.i_format.opcode) {
44 	/*
45 	 * jr and jalr are in r_format format.
46 	 */
47 	case spec_op:
48 		switch (insn.r_format.func) {
49 		case jalr_op:
50 			regs->regs[insn.r_format.rd] = epc + 8;
51 			/* Fall through */
52 		case jr_op:
53 			regs->cp0_epc = regs->regs[insn.r_format.rs];
54 			break;
55 		}
56 		break;
57 
58 	/*
59 	 * This group contains:
60 	 * bltz_op, bgez_op, bltzl_op, bgezl_op,
61 	 * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
62 	 */
63 	case bcond_op:
64 		switch (insn.i_format.rt) {
65 	 	case bltz_op:
66 		case bltzl_op:
67 			if ((long)regs->regs[insn.i_format.rs] < 0)
68 				epc = epc + 4 + (insn.i_format.simmediate << 2);
69 			else
70 				epc += 8;
71 			regs->cp0_epc = epc;
72 			break;
73 
74 		case bgez_op:
75 		case bgezl_op:
76 			if ((long)regs->regs[insn.i_format.rs] >= 0)
77 				epc = epc + 4 + (insn.i_format.simmediate << 2);
78 			else
79 				epc += 8;
80 			regs->cp0_epc = epc;
81 			break;
82 
83 		case bltzal_op:
84 		case bltzall_op:
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);
88 			else
89 				epc += 8;
90 			regs->cp0_epc = epc;
91 			break;
92 
93 		case bgezal_op:
94 		case bgezall_op:
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);
98 			else
99 				epc += 8;
100 			regs->cp0_epc = epc;
101 			break;
102 		case bposge32_op:
103 			if (!cpu_has_dsp)
104 				goto sigill;
105 
106 			dspcontrol = rddsp(0x01);
107 
108 			if (dspcontrol >= 32) {
109 				epc = epc + 4 + (insn.i_format.simmediate << 2);
110 			} else
111 				epc += 8;
112 			regs->cp0_epc = epc;
113 			break;
114 		}
115 		break;
116 
117 	/*
118 	 * These are unconditional and in j_format.
119 	 */
120 	case jal_op:
121 		regs->regs[31] = regs->cp0_epc + 8;
122 	case j_op:
123 		epc += 4;
124 		epc >>= 28;
125 		epc <<= 28;
126 		epc |= (insn.j_format.target << 2);
127 		regs->cp0_epc = epc;
128 		break;
129 
130 	/*
131 	 * These are conditional and in i_format.
132 	 */
133 	case beq_op:
134 	case beql_op:
135 		if (regs->regs[insn.i_format.rs] ==
136 		    regs->regs[insn.i_format.rt])
137 			epc = epc + 4 + (insn.i_format.simmediate << 2);
138 		else
139 			epc += 8;
140 		regs->cp0_epc = epc;
141 		break;
142 
143 	case bne_op:
144 	case bnel_op:
145 		if (regs->regs[insn.i_format.rs] !=
146 		    regs->regs[insn.i_format.rt])
147 			epc = epc + 4 + (insn.i_format.simmediate << 2);
148 		else
149 			epc += 8;
150 		regs->cp0_epc = epc;
151 		break;
152 
153 	case blez_op: /* not really i_format */
154 	case blezl_op:
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);
158 		else
159 			epc += 8;
160 		regs->cp0_epc = epc;
161 		break;
162 
163 	case bgtz_op:
164 	case bgtzl_op:
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);
168 		else
169 			epc += 8;
170 		regs->cp0_epc = epc;
171 		break;
172 
173 	/*
174 	 * And now the FPA/cp1 branch instructions.
175 	 */
176 	case cop1_op:
177 		preempt_disable();
178 		if (is_fpu_owner())
179 			asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
180 		else
181 			fcr31 = current->thread.fpu.fcr31;
182 		preempt_enable();
183 
184 		bit = (insn.i_format.rt >> 2);
185 		bit += (bit != 0);
186 		bit += 23;
187 		switch (insn.i_format.rt & 3) {
188 		case 0:	/* bc1f */
189 		case 2:	/* bc1fl */
190 			if (~fcr31 & (1 << bit))
191 				epc = epc + 4 + (insn.i_format.simmediate << 2);
192 			else
193 				epc += 8;
194 			regs->cp0_epc = epc;
195 			break;
196 
197 		case 1:	/* bc1t */
198 		case 3:	/* bc1tl */
199 			if (fcr31 & (1 << bit))
200 				epc = epc + 4 + (insn.i_format.simmediate << 2);
201 			else
202 				epc += 8;
203 			regs->cp0_epc = epc;
204 			break;
205 		}
206 		break;
207 #ifdef CONFIG_CPU_CAVIUM_OCTEON
208 	case lwc2_op: /* This is bbit0 on Octeon */
209 		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
210 		     == 0)
211 			epc = epc + 4 + (insn.i_format.simmediate << 2);
212 		else
213 			epc += 8;
214 		regs->cp0_epc = epc;
215 		break;
216 	case ldc2_op: /* This is bbit032 on Octeon */
217 		if ((regs->regs[insn.i_format.rs] &
218 		    (1ull<<(insn.i_format.rt+32))) == 0)
219 			epc = epc + 4 + (insn.i_format.simmediate << 2);
220 		else
221 			epc += 8;
222 		regs->cp0_epc = epc;
223 		break;
224 	case swc2_op: /* This is bbit1 on Octeon */
225 		if (regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
226 			epc = epc + 4 + (insn.i_format.simmediate << 2);
227 		else
228 			epc += 8;
229 		regs->cp0_epc = epc;
230 		break;
231 	case sdc2_op: /* This is bbit132 on Octeon */
232 		if (regs->regs[insn.i_format.rs] &
233 		    (1ull<<(insn.i_format.rt+32)))
234 			epc = epc + 4 + (insn.i_format.simmediate << 2);
235 		else
236 			epc += 8;
237 		regs->cp0_epc = epc;
238 		break;
239 #endif
240 	}
241 
242 	return 0;
243 
244 unaligned:
245 	printk("%s: unaligned epc - sending SIGBUS.\n", current->comm);
246 	force_sig(SIGBUS, current);
247 	return -EFAULT;
248 
249 sigill:
250 	printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm);
251 	force_sig(SIGBUS, current);
252 	return -EFAULT;
253 }
254