[PATCH v2 04/15] MIPS: Branch mapping support (pre-R6 to R6).
Jovan Dmitrovic
jovan.dmitrovic@htecgroup.com
Wed Oct 29 14:09:27 GMT 2025
From: Robert Suchanek <Robert.Suchanek@imgtec.com>
Restrict mapping pre-R6 branches to R6 compact branches if there
is a non-NOP instruction in the delay slot, as compact branches in
microMIPS R6 do not have delay slots.
Signed-off-by: Robert Suchanek <Robert.Suchanek@imgtec.com>
Signed-off-by: Faraz Shahbazker <fshahbazker@wavecomp.com>
Signed-off-by: Milica Matic <milica.matic@htecgroup.com>
gas/ChangeLog:
* config/tc-mips.c (append_insn): Disable converting from pre-R6 to R6
compact branch instruction if delay slot is filled with non-NOP instruction.
include/ChangeLog:
* opcode/mips.h (INSN2_CONVERTED_TO_COMPACT): New macro.
opcodes/ChangeLog:
* mips-dis.c (is_isa_r6): New function.
(print_insn_mips): Always dissasemble R6 converted compact branch.
---
gas/config/tc-mips.c | 34 +++++++++++++++++++++++++++++++++-
include/opcode/mips.h | 2 ++
opcodes/mips-dis.c | 19 +++++++++++++++----
3 files changed, 50 insertions(+), 5 deletions(-)
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 8cd9f31c492..c7b677a213b 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -7750,6 +7750,37 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
address_expr->X_add_number);
*reloc_type = BFD_RELOC_UNUSED;
}
+ else if (mips_opts.micromips
+ && ISA_IS_R6 (mips_opts.isa)
+ /* microMIPS pre-R6 to R6 branch/jump instruction mapping in
+ noreorder block is restricted to have only a nop in the delay
+ slot. */
+ && compact_branch_p (&history[0])
+ && (history[0].insn_mo->pinfo2 & INSN2_CONVERTED_TO_COMPACT)
+ && history[0].noreorder_p
+ && strcmp (ip->insn_mo->name, "nop") != 0)
+ {
+ as_bad (_("unable to convert `%s' to its compact form because it has a non NOP "
+ "instruction (`%s') in its delay slot. Please move the delay slot "
+ "instruction before the branch and disable noreorder."),
+ history[0].insn_mo->name, ip->insn_mo->name);
+ add_fixed_insn (ip);
+ }
+ else if (mips_opts.micromips
+ && ISA_IS_R6 (mips_opts.isa)
+ && history[0].noreorder_p
+ && (strcmp (history[0].insn_mo->name, "bal") == 0
+ || strcmp (history[0].insn_mo->name, "jal") == 0
+ || strcmp (history[0].insn_mo->name, "jalr") == 0
+ || strcmp (history[0].insn_mo->name, "bgezal") == 0
+ || strcmp (history[0].insn_mo->name, "bltzal") == 0))
+ {
+ as_bad (_("unable to convert `%s' to its compact form because the link register "
+ "would have a different value. Please move the delay slot instruction "
+ "before the branch and disable noreorder."),
+ history[0].insn_mo->name);
+ add_fixed_insn (ip);
+ }
else if (mips_opts.micromips
&& address_expr
&& ((relax32 && *reloc_type == BFD_RELOC_16_PCREL_S2)
@@ -8083,8 +8114,9 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
}
/* If we have just completed an unconditional branch, clear the history. */
- if ((delayed_branch_p (&history[1]) && uncond_branch_p (&history[1]))
+ if (((delayed_branch_p (&history[1]) && uncond_branch_p (&history[1]))
|| (compact_branch_p (&history[0]) && uncond_branch_p (&history[0])))
+ && !(history[0].insn_mo->pinfo2 & INSN2_CONVERTED_TO_COMPACT))
{
unsigned int i;
diff --git a/include/opcode/mips.h b/include/opcode/mips.h
index e5d9ef38177..a615cfdf2b4 100644
--- a/include/opcode/mips.h
+++ b/include/opcode/mips.h
@@ -887,6 +887,8 @@ mips_opcode_32bit_p (const struct mips_opcode *mo)
encoding is needed or otherwise the final EXTEND entry will apply,
for the disassembly of the prefix only. */
#define INSN2_SHORT_ONLY 0x00010000
+/* This indicates pre-R6 instructions mapped to R6 ones. */
+#define INSN2_CONVERTED_TO_COMPACT 0x00020000
/* Masks used to mark instructions to indicate which MIPS ISA level
they were introduced in. INSN_ISA_MASK masks an enumeration that
diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c
index a4cff73e268..b47b78c84fe 100644
--- a/opcodes/mips-dis.c
+++ b/opcodes/mips-dis.c
@@ -845,6 +845,17 @@ is_micromips (Elf_Internal_Ehdr *header)
return 0;
}
+/* Check if ISA is R6. */
+
+static inline int
+is_isa_r6 (unsigned long isa)
+{
+ if ((isa & INSN_ISA_MASK) == ISA_MIPS32R6
+ || ((isa & INSN_ISA_MASK) == ISA_MIPS64R6))
+ return 1;
+ return 0;
+}
+
/* Convert ASE flags from .MIPS.abiflags to internal values. */
static unsigned long
@@ -2068,10 +2079,10 @@ print_insn_mips (bfd_vma memaddr,
&& (word & op->mask) == op->match)
{
/* We always disassemble the jalx instruction, except for MIPS r6. */
- if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
- && (strcmp (op->name, "jalx")
- || (mips_isa & INSN_ISA_MASK) == ISA_MIPS32R6
- || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6))
+ if ((!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
+ && (strcmp (op->name, "jalx") || is_isa_r6 (mips_isa)))
+ || (is_isa_r6 (op->membership)
+ && (op->pinfo2 & INSN2_CONVERTED_TO_COMPACT)))
continue;
/* Figure out instruction type and branch delay information. */
--
2.34.1
More information about the Binutils
mailing list