MIPS: BREAK instruction interpretation corrections
Add the missing microMIPS BREAK16 instruction code interpretation and reshape code removing instruction fetching duplication and the separate call to `do_trap_or_bp' in the MIPS16 path. Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/9696/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
68893e0051
commit
f6a31da501
|
@ -901,10 +901,9 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
|
||||||
|
|
||||||
asmlinkage void do_bp(struct pt_regs *regs)
|
asmlinkage void do_bp(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
unsigned long epc = msk_isa16_mode(exception_epc(regs));
|
||||||
unsigned int opcode, bcode;
|
unsigned int opcode, bcode;
|
||||||
enum ctx_state prev_state;
|
enum ctx_state prev_state;
|
||||||
unsigned long epc;
|
|
||||||
u16 instr[2];
|
|
||||||
mm_segment_t seg;
|
mm_segment_t seg;
|
||||||
|
|
||||||
seg = get_fs();
|
seg = get_fs();
|
||||||
|
@ -913,26 +912,28 @@ asmlinkage void do_bp(struct pt_regs *regs)
|
||||||
|
|
||||||
prev_state = exception_enter();
|
prev_state = exception_enter();
|
||||||
if (get_isa16_mode(regs->cp0_epc)) {
|
if (get_isa16_mode(regs->cp0_epc)) {
|
||||||
/* Calculate EPC. */
|
u16 instr[2];
|
||||||
epc = exception_epc(regs);
|
|
||||||
if (cpu_has_mmips) {
|
if (__get_user(instr[0], (u16 __user *)epc))
|
||||||
if ((__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc)) ||
|
goto out_sigsegv;
|
||||||
(__get_user(instr[1], (u16 __user *)msk_isa16_mode(epc + 2)))))
|
|
||||||
|
if (!cpu_has_mmips) {
|
||||||
|
/* MIPS16e mode */
|
||||||
|
bcode = (instr[0] >> 5) & 0x3f;
|
||||||
|
} else if (mm_insn_16bit(instr[0])) {
|
||||||
|
/* 16-bit microMIPS BREAK */
|
||||||
|
bcode = instr[0] & 0xf;
|
||||||
|
} else {
|
||||||
|
/* 32-bit microMIPS BREAK */
|
||||||
|
if (__get_user(instr[1], (u16 __user *)(epc + 2)))
|
||||||
goto out_sigsegv;
|
goto out_sigsegv;
|
||||||
opcode = (instr[0] << 16) | instr[1];
|
opcode = (instr[0] << 16) | instr[1];
|
||||||
} else {
|
bcode = (opcode >> 6) & ((1 << 20) - 1);
|
||||||
/* MIPS16e mode */
|
|
||||||
if (__get_user(instr[0],
|
|
||||||
(u16 __user *)msk_isa16_mode(epc)))
|
|
||||||
goto out_sigsegv;
|
|
||||||
bcode = (instr[0] >> 5) & 0x3f;
|
|
||||||
do_trap_or_bp(regs, bcode, "Break");
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (__get_user(opcode,
|
if (__get_user(opcode, (unsigned int __user *)epc))
|
||||||
(unsigned int __user *) exception_epc(regs)))
|
|
||||||
goto out_sigsegv;
|
goto out_sigsegv;
|
||||||
|
bcode = (opcode >> 6) & ((1 << 20) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -941,7 +942,6 @@ asmlinkage void do_bp(struct pt_regs *regs)
|
||||||
* Gas is bug-compatible, but not always, grrr...
|
* Gas is bug-compatible, but not always, grrr...
|
||||||
* We handle both cases with a simple heuristics. --macro
|
* We handle both cases with a simple heuristics. --macro
|
||||||
*/
|
*/
|
||||||
bcode = ((opcode >> 6) & ((1 << 20) - 1));
|
|
||||||
if (bcode >= (1 << 10))
|
if (bcode >= (1 << 10))
|
||||||
bcode >>= 10;
|
bcode >>= 10;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue