|
@@ -635,6 +635,28 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
|
|
if (NO_R6EMU)
|
|
if (NO_R6EMU)
|
|
|
goto sigill_r6;
|
|
goto sigill_r6;
|
|
|
case bgtz_op:
|
|
case bgtz_op:
|
|
|
|
|
+ /*
|
|
|
|
|
+ * Compact branches for R6 for the
|
|
|
|
|
+ * bgtz and bgtzl opcodes.
|
|
|
|
|
+ * BGTZ | rs = 0 | rt != 0 == BGTZALC
|
|
|
|
|
+ * BGTZ | rs = rt != 0 == BLTZALC
|
|
|
|
|
+ * BGTZ | rs != 0 | rt != 0 == BLTUC
|
|
|
|
|
+ * BGTZL | rs = 0 | rt != 0 == BGTZC
|
|
|
|
|
+ * BGTZL | rs = rt != 0 == BLTZC
|
|
|
|
|
+ * BGTZL | rs != 0 | rt != 0 == BLTC
|
|
|
|
|
+ *
|
|
|
|
|
+ * *ZALC varint for BGTZ &&& rt != 0
|
|
|
|
|
+ * For real GTZ{,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] = epc + 4;
|
|
|
|
|
+ regs->cp0_epc += 8;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/* rt field assumed to be zero */
|
|
/* rt field assumed to be zero */
|
|
|
if ((long)regs->regs[insn.i_format.rs] > 0) {
|
|
if ((long)regs->regs[insn.i_format.rs] > 0) {
|
|
|
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
|
epc = epc + 4 + (insn.i_format.simmediate << 2);
|