summaryrefslogtreecommitdiff
path: root/arch/mips/math-emu/cp1emu.c
diff options
context:
space:
mode:
authorMarkos Chandras <markos.chandras@imgtec.com>2014-11-26 12:57:54 +0000
committerMarkos Chandras <markos.chandras@imgtec.com>2015-02-17 15:37:33 +0000
commita8ff66f52d3f17b5ae793955270675c197f73d6c (patch)
treeae86a8dfde65eecdcd9bd7591034ef5f65a65997 /arch/mips/math-emu/cp1emu.c
parentc8a34581ec09a5ee11dd833d6c5cf41fdbef706f (diff)
MIPS: Emulate the new MIPS R6 B{L,G}Ε{Z,}{AL,}C instructions
MIPS R6 added the following four instructions which share the BLEZ and BLEZL opcodes: BLEZALC: Compact branch-and-link if GPR rt is <= to zero BGEZALC: Compact branch-and-link if GPR rt is >= to zero BLEZC : Compact branch if GPR rt is <= to zero BGEZC : Compact branch if GPR rt is >= to zero BGEC : Compact branch if GPR rs is less than or equal to GPR rt BGEUC : Similar to BGEC but unsigned. Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
Diffstat (limited to 'arch/mips/math-emu/cp1emu.c')
-rw-r--r--arch/mips/math-emu/cp1emu.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 798204e492fc..c770617dc340 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -552,6 +552,30 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
if (NO_R6EMU)
break;
case blez_op:
+
+ /*
+ * Compact branches for R6 for the
+ * blez and blezl opcodes.
+ * BLEZ | rs = 0 | rt != 0 == BLEZALC
+ * BLEZ | rs = rt != 0 == BGEZALC
+ * BLEZ | rs != 0 | rt != 0 == BGEUC
+ * BLEZL | rs = 0 | rt != 0 == BLEZC
+ * BLEZL | rs = rt != 0 == BGEZC
+ * BLEZL | rs != 0 | rt != 0 == BGEC
+ *
+ * For real BLEZ{,L}, rt is always 0.
+ */
+ if (cpu_has_mips_r6 && insn.i_format.rt) {
+ if ((insn.i_format.opcode == blez_op) &&
+ ((!insn.i_format.rs && insn.i_format.rt) ||
+ (insn.i_format.rs == insn.i_format.rt)))
+ regs->regs[31] = regs->cp0_epc +
+ dec_insn.pc_inc;
+ *contpc = regs->cp0_epc + dec_insn.pc_inc +
+ dec_insn.next_pc_inc;
+
+ return 1;
+ }
if ((long)regs->regs[insn.i_format.rs] <= 0)
*contpc = regs->cp0_epc +
dec_insn.pc_inc +