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 <linux/module.h>
13 #include <asm/branch.h>
15 #include <asm/cpu-features.h>
17 #include <asm/fpu_emulator.h>
19 #include <asm/ptrace.h>
20 #include <asm/uaccess.h>
23 * Calculate and return exception PC in case of branch delay slot
24 * for microMIPS and MIPS16e. It does not clear the ISA mode bit.
26 int __isa_exception_epc(struct pt_regs
*regs
)
29 long epc
= regs
->cp0_epc
;
31 /* Calculate exception PC in branch delay slot. */
32 if (__get_user(inst
, (u16 __user
*) msk_isa16_mode(epc
))) {
33 /* This should never happen because delay slot was checked. */
34 force_sig(SIGSEGV
, current
);
38 if (((union mips16e_instruction
)inst
).ri
.opcode
43 } else if (mm_insn_16bit(inst
))
52 * Compute return address and emulate branch in microMIPS mode after an
53 * exception only. It does not handle compact branches/jumps and cannot
54 * be used in interrupt context. (Compact branches/jumps do not cause
57 int __microMIPS_compute_return_epc(struct pt_regs
*regs
)
63 struct mm_decoded_insn mminsn
= { 0 };
65 mminsn
.micro_mips_mode
= 1;
67 /* This load never faults. */
68 pc16
= (unsigned short __user
*)msk_isa16_mode(regs
->cp0_epc
);
69 __get_user(halfword
, pc16
);
71 contpc
= regs
->cp0_epc
+ 2;
72 word
= ((unsigned int)halfword
<< 16);
75 if (!mm_insn_16bit(halfword
)) {
76 __get_user(halfword
, pc16
);
78 contpc
= regs
->cp0_epc
+ 4;
84 if (get_user(halfword
, pc16
))
86 mminsn
.next_pc_inc
= 2;
87 word
= ((unsigned int)halfword
<< 16);
89 if (!mm_insn_16bit(halfword
)) {
91 if (get_user(halfword
, pc16
))
93 mminsn
.next_pc_inc
= 4;
96 mminsn
.next_insn
= word
;
98 mm_isBranchInstr(regs
, mminsn
, &contpc
);
100 regs
->cp0_epc
= contpc
;
105 force_sig(SIGSEGV
, current
);
110 * Compute return address and emulate branch in MIPS16e mode after an
111 * exception only. It does not handle compact branches/jumps and cannot
112 * be used in interrupt context. (Compact branches/jumps do not cause
115 int __MIPS16e_compute_return_epc(struct pt_regs
*regs
)
118 union mips16e_instruction inst
;
125 /* Read the instruction. */
126 addr
= (u16 __user
*)msk_isa16_mode(epc
);
127 if (__get_user(inst
.full
, addr
)) {
128 force_sig(SIGSEGV
, current
);
132 switch (inst
.ri
.opcode
) {
133 case MIPS16e_extend_op
:
138 * JAL and JALX in MIPS16e mode
142 if (__get_user(inst2
, addr
)) {
143 force_sig(SIGSEGV
, current
);
146 fullinst
= ((unsigned)inst
.full
<< 16) | inst2
;
147 regs
->regs
[31] = epc
+ 6;
152 * JAL:5 X:1 TARGET[20-16]:5 TARGET[25:21]:5 TARGET[15:0]:16
154 * ......TARGET[15:0].................TARGET[20:16]...........
155 * ......TARGET[25:21]
158 ((fullinst
& 0xffff) << 2) | ((fullinst
& 0x3e00000) >> 3) |
159 ((fullinst
& 0x1f0000) << 7);
161 set_isa16_mode(epc
); /* Set ISA mode bit. */
169 if (inst
.rr
.func
== MIPS16e_jr_func
) {
172 regs
->cp0_epc
= regs
->regs
[31];
175 regs
->regs
[reg16to32
[inst
.rr
.rx
]];
179 regs
->regs
[31] = epc
+ 2;
181 regs
->regs
[31] = epc
+ 4;
189 * All other cases have no branch delay slot and are 16-bits.
190 * Branches do not cause an exception.
198 * __compute_return_epc_for_insn - Computes the return address and do emulate
199 * branch simulation, if required.
201 * @regs: Pointer to pt_regs
202 * @insn: branch instruction to decode
203 * @returns: -EFAULT on error and forces SIGBUS, and on success
204 * returns 0 or BRANCH_LIKELY_TAKEN as appropriate after
205 * evaluating the branch.
207 int __compute_return_epc_for_insn(struct pt_regs
*regs
,
208 union mips_instruction insn
)
210 unsigned int bit
, fcr31
, dspcontrol
;
211 long epc
= regs
->cp0_epc
;
214 switch (insn
.i_format
.opcode
) {
216 * jr and jalr are in r_format format.
219 switch (insn
.r_format
.func
) {
221 regs
->regs
[insn
.r_format
.rd
] = epc
+ 8;
224 regs
->cp0_epc
= regs
->regs
[insn
.r_format
.rs
];
230 * This group contains:
231 * bltz_op, bgez_op, bltzl_op, bgezl_op,
232 * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
235 switch (insn
.i_format
.rt
) {
238 if ((long)regs
->regs
[insn
.i_format
.rs
] < 0) {
239 epc
= epc
+ 4 + (insn
.i_format
.simmediate
<< 2);
240 if (insn
.i_format
.rt
== bltzl_op
)
241 ret
= BRANCH_LIKELY_TAKEN
;
249 if ((long)regs
->regs
[insn
.i_format
.rs
] >= 0) {
250 epc
= epc
+ 4 + (insn
.i_format
.simmediate
<< 2);
251 if (insn
.i_format
.rt
== bgezl_op
)
252 ret
= BRANCH_LIKELY_TAKEN
;
260 regs
->regs
[31] = epc
+ 8;
261 if ((long)regs
->regs
[insn
.i_format
.rs
] < 0) {
262 epc
= epc
+ 4 + (insn
.i_format
.simmediate
<< 2);
263 if (insn
.i_format
.rt
== bltzall_op
)
264 ret
= BRANCH_LIKELY_TAKEN
;
272 regs
->regs
[31] = epc
+ 8;
273 if ((long)regs
->regs
[insn
.i_format
.rs
] >= 0) {
274 epc
= epc
+ 4 + (insn
.i_format
.simmediate
<< 2);
275 if (insn
.i_format
.rt
== bgezall_op
)
276 ret
= BRANCH_LIKELY_TAKEN
;
286 dspcontrol
= rddsp(0x01);
288 if (dspcontrol
>= 32) {
289 epc
= epc
+ 4 + (insn
.i_format
.simmediate
<< 2);
298 * These are unconditional and in j_format.
301 regs
->regs
[31] = regs
->cp0_epc
+ 8;
306 epc
|= (insn
.j_format
.target
<< 2);
308 if (insn
.i_format
.opcode
== jalx_op
)
309 set_isa16_mode(regs
->cp0_epc
);
313 * These are conditional and in i_format.
317 if (regs
->regs
[insn
.i_format
.rs
] ==
318 regs
->regs
[insn
.i_format
.rt
]) {
319 epc
= epc
+ 4 + (insn
.i_format
.simmediate
<< 2);
320 if (insn
.i_format
.rt
== beql_op
)
321 ret
= BRANCH_LIKELY_TAKEN
;
329 if (regs
->regs
[insn
.i_format
.rs
] !=
330 regs
->regs
[insn
.i_format
.rt
]) {
331 epc
= epc
+ 4 + (insn
.i_format
.simmediate
<< 2);
332 if (insn
.i_format
.rt
== bnel_op
)
333 ret
= BRANCH_LIKELY_TAKEN
;
339 case blez_op
: /* not really i_format */
341 /* rt field assumed to be zero */
342 if ((long)regs
->regs
[insn
.i_format
.rs
] <= 0) {
343 epc
= epc
+ 4 + (insn
.i_format
.simmediate
<< 2);
344 if (insn
.i_format
.rt
== bnel_op
)
345 ret
= BRANCH_LIKELY_TAKEN
;
353 /* rt field assumed to be zero */
354 if ((long)regs
->regs
[insn
.i_format
.rs
] > 0) {
355 epc
= epc
+ 4 + (insn
.i_format
.simmediate
<< 2);
356 if (insn
.i_format
.rt
== bnel_op
)
357 ret
= BRANCH_LIKELY_TAKEN
;
364 * And now the FPA/cp1 branch instructions.
369 asm volatile("cfc1\t%0,$31" : "=r" (fcr31
));
371 fcr31
= current
->thread
.fpu
.fcr31
;
374 bit
= (insn
.i_format
.rt
>> 2);
377 switch (insn
.i_format
.rt
& 3) {
380 if (~fcr31
& (1 << bit
)) {
381 epc
= epc
+ 4 + (insn
.i_format
.simmediate
<< 2);
382 if (insn
.i_format
.rt
== 2)
383 ret
= BRANCH_LIKELY_TAKEN
;
391 if (fcr31
& (1 << bit
)) {
392 epc
= epc
+ 4 + (insn
.i_format
.simmediate
<< 2);
393 if (insn
.i_format
.rt
== 3)
394 ret
= BRANCH_LIKELY_TAKEN
;
401 #ifdef CONFIG_CPU_CAVIUM_OCTEON
402 case lwc2_op
: /* This is bbit0 on Octeon */
403 if ((regs
->regs
[insn
.i_format
.rs
] & (1ull<<insn
.i_format
.rt
))
405 epc
= epc
+ 4 + (insn
.i_format
.simmediate
<< 2);
410 case ldc2_op
: /* This is bbit032 on Octeon */
411 if ((regs
->regs
[insn
.i_format
.rs
] &
412 (1ull<<(insn
.i_format
.rt
+32))) == 0)
413 epc
= epc
+ 4 + (insn
.i_format
.simmediate
<< 2);
418 case swc2_op
: /* This is bbit1 on Octeon */
419 if (regs
->regs
[insn
.i_format
.rs
] & (1ull<<insn
.i_format
.rt
))
420 epc
= epc
+ 4 + (insn
.i_format
.simmediate
<< 2);
425 case sdc2_op
: /* This is bbit132 on Octeon */
426 if (regs
->regs
[insn
.i_format
.rs
] &
427 (1ull<<(insn
.i_format
.rt
+32)))
428 epc
= epc
+ 4 + (insn
.i_format
.simmediate
<< 2);
439 printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current
->comm
);
440 force_sig(SIGBUS
, current
);
443 EXPORT_SYMBOL_GPL(__compute_return_epc_for_insn
);
445 int __compute_return_epc(struct pt_regs
*regs
)
447 unsigned int __user
*addr
;
449 union mips_instruction insn
;
456 * Read the instruction
458 addr
= (unsigned int __user
*) epc
;
459 if (__get_user(insn
.word
, addr
)) {
460 force_sig(SIGSEGV
, current
);
464 return __compute_return_epc_for_insn(regs
, insn
);
467 printk("%s: unaligned epc - sending SIGBUS.\n", current
->comm
);
468 force_sig(SIGBUS
, current
);