diff options
| author | Markos Chandras <markos.chandras@imgtec.com> | 2014-11-26 08:05:09 -0500 |
|---|---|---|
| committer | Markos Chandras <markos.chandras@imgtec.com> | 2015-02-17 10:37:33 -0500 |
| commit | f1b44067c19258b7614e3cd09dfe8d8e12ff5895 (patch) | |
| tree | eb23ac6695fecc5d565e3c21106ead25d9e672ea /arch | |
| parent | a8ff66f52d3f17b5ae793955270675c197f73d6c (diff) | |
MIPS: Emulate the new MIPS R6 B{L,G}T{Z,}{AL,}C instructions
MIPS R6 added the following four instructions which share the
BGTZ and BGTZL opcode:
BLTZALC: Compact branch-and-link if GPR rt is < to zero
BGTZALC: Compact branch-and-link if GPR rt is > to zero
BLTZL : Compact branch if GPR rt is < to zero
BGTZL : Compact branch if GPR rt is > to zero
BLTC : Compact branch if GPR rs is less than GPR rt
BLTUC : Similar to BLTC but unsigned
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/mips/kernel/branch.c | 22 | ||||
| -rw-r--r-- | arch/mips/math-emu/cp1emu.c | 25 |
2 files changed, 47 insertions, 0 deletions
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index a1fd8786d716..cd880b91f092 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c | |||
| @@ -635,6 +635,28 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, | |||
| 635 | if (NO_R6EMU) | 635 | if (NO_R6EMU) |
| 636 | goto sigill_r6; | 636 | goto sigill_r6; |
| 637 | case bgtz_op: | 637 | case bgtz_op: |
| 638 | /* | ||
| 639 | * Compact branches for R6 for the | ||
| 640 | * bgtz and bgtzl opcodes. | ||
| 641 | * BGTZ | rs = 0 | rt != 0 == BGTZALC | ||
| 642 | * BGTZ | rs = rt != 0 == BLTZALC | ||
| 643 | * BGTZ | rs != 0 | rt != 0 == BLTUC | ||
| 644 | * BGTZL | rs = 0 | rt != 0 == BGTZC | ||
| 645 | * BGTZL | rs = rt != 0 == BLTZC | ||
| 646 | * BGTZL | rs != 0 | rt != 0 == BLTC | ||
| 647 | * | ||
| 648 | * *ZALC varint for BGTZ &&& rt != 0 | ||
| 649 | * For real GTZ{,L}, rt is always 0. | ||
| 650 | */ | ||
| 651 | if (cpu_has_mips_r6 && insn.i_format.rt) { | ||
| 652 | if ((insn.i_format.opcode == blez_op) && | ||
| 653 | ((!insn.i_format.rs && insn.i_format.rt) || | ||
| 654 | (insn.i_format.rs == insn.i_format.rt))) | ||
| 655 | regs->regs[31] = epc + 4; | ||
| 656 | regs->cp0_epc += 8; | ||
| 657 | break; | ||
| 658 | } | ||
| 659 | |||
| 638 | /* rt field assumed to be zero */ | 660 | /* rt field assumed to be zero */ |
| 639 | if ((long)regs->regs[insn.i_format.rs] > 0) { | 661 | if ((long)regs->regs[insn.i_format.rs] > 0) { |
| 640 | epc = epc + 4 + (insn.i_format.simmediate << 2); | 662 | epc = epc + 4 + (insn.i_format.simmediate << 2); |
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index c770617dc340..d6d67e2a0434 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c | |||
| @@ -589,6 +589,31 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, | |||
| 589 | if (NO_R6EMU) | 589 | if (NO_R6EMU) |
| 590 | break; | 590 | break; |
| 591 | case bgtz_op: | 591 | case bgtz_op: |
| 592 | /* | ||
| 593 | * Compact branches for R6 for the | ||
| 594 | * bgtz and bgtzl opcodes. | ||
| 595 | * BGTZ | rs = 0 | rt != 0 == BGTZALC | ||
| 596 | * BGTZ | rs = rt != 0 == BLTZALC | ||
| 597 | * BGTZ | rs != 0 | rt != 0 == BLTUC | ||
| 598 | * BGTZL | rs = 0 | rt != 0 == BGTZC | ||
| 599 | * BGTZL | rs = rt != 0 == BLTZC | ||
| 600 | * BGTZL | rs != 0 | rt != 0 == BLTC | ||
| 601 | * | ||
| 602 | * *ZALC varint for BGTZ &&& rt != 0 | ||
| 603 | * For real GTZ{,L}, rt is always 0. | ||
| 604 | */ | ||
| 605 | if (cpu_has_mips_r6 && insn.i_format.rt) { | ||
| 606 | if ((insn.i_format.opcode == blez_op) && | ||
| 607 | ((!insn.i_format.rs && insn.i_format.rt) || | ||
| 608 | (insn.i_format.rs == insn.i_format.rt))) | ||
| 609 | regs->regs[31] = regs->cp0_epc + | ||
| 610 | dec_insn.pc_inc; | ||
| 611 | *contpc = regs->cp0_epc + dec_insn.pc_inc + | ||
| 612 | dec_insn.next_pc_inc; | ||
| 613 | |||
| 614 | return 1; | ||
| 615 | } | ||
| 616 | |||
| 592 | if ((long)regs->regs[insn.i_format.rs] > 0) | 617 | if ((long)regs->regs[insn.i_format.rs] > 0) |
| 593 | *contpc = regs->cp0_epc + | 618 | *contpc = regs->cp0_epc + |
| 594 | dec_insn.pc_inc + | 619 | dec_insn.pc_inc + |
