MIPS: math-emu: Correct the emulation of microMIPS ADDIUPC instruction
Emulate the microMIPS ADDIUPC instruction directly in `mips_dsemul'. If executed in the emulation frame, this instruction produces an incorrect result, because the value of the PC there is not the same as where the instruction originated. Reshape code so as to handle all microMIPS cases together. Signed-off-by: Maciej W. Rozycki <macro@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/12175/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:

committed by
Ralf Baechle

parent
733b8bc183
commit
69a1e6cbdf
@@ -43,10 +43,30 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
|
||||
int err;
|
||||
|
||||
/* NOP is easy */
|
||||
if ((get_isa16_mode(regs->cp0_epc) && ((ir >> 16) == MM_NOP16)) ||
|
||||
(ir == 0))
|
||||
if (ir == 0)
|
||||
return -1;
|
||||
|
||||
/* microMIPS instructions */
|
||||
if (get_isa16_mode(regs->cp0_epc)) {
|
||||
union mips_instruction insn = { .word = ir };
|
||||
|
||||
/* NOP16 aka MOVE16 $0, $0 */
|
||||
if ((ir >> 16) == MM_NOP16)
|
||||
return -1;
|
||||
|
||||
/* ADDIUPC */
|
||||
if (insn.mm_a_format.opcode == mm_addiupc_op) {
|
||||
unsigned int rs;
|
||||
s32 v;
|
||||
|
||||
rs = (((insn.mm_a_format.rs + 0x1e) & 0xf) + 2);
|
||||
v = regs->cp0_epc & ~3;
|
||||
v += insn.mm_a_format.simmediate << 2;
|
||||
regs->regs[rs] = (long)v;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
pr_debug("dsemul %lx %lx\n", regs->cp0_epc, cpc);
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user