This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[committed] Update insn_mo when converting to a MIPS16e compact jump
- From: Richard Sandiford <rdsandiford at googlemail dot com>
- To: binutils at sourceware dot org
- Date: Wed, 29 Jun 2011 21:42:34 +0100
- Subject: [committed] Update insn_mo when converting to a MIPS16e compact jump
While working on this patch series, I noticed that we don't set insn_mo
when converting to a MIPS16e compact jump. This probably doesn't cause
any problems in practice, but it's still wrong in principle: things like
the nop insertion code should be able to rely on insn_mo being accurate.
Tested on:
mips64-elf mips64el-unknown-kfreebsd-gnu mips64-linux-gnu
mips64octeon-linux-gnu mips64-unknown-kfreebsd-gnu
mipsel-unknown-kfreebsd-gnu mipsisa32el-linux-gnu
mipsisa64-elf mips-linux-gnu mips-sgi-irix6.5
mips-unknown-kfreebsd-gnu mips-wrs-vxworks
and applied.
Richard
gas/
* config/tc-mips.c (find_altered_mips16_opcode): New function.
(append_insn): Use it.
opcodes/
* mips16-opc.c (jalrc, jrc): Move earlier in file.
Index: gas/config/tc-mips.c
===================================================================
--- gas/config/tc-mips.c 2011-06-29 19:55:57.000000000 +0100
+++ gas/config/tc-mips.c 2011-06-29 19:56:09.000000000 +0100
@@ -3072,6 +3072,24 @@ fix_loongson2f (struct mips_cl_insn * ip
fix_loongson2f_jump (ip);
}
+/* IP is a MIPS16 instruction whose opcode we have just changed.
+ Point IP->insn_mo to the new opcode's definition. */
+
+static void
+find_altered_mips16_opcode (struct mips_cl_insn *ip)
+{
+ const struct mips_opcode *mo, *end;
+
+ end = &mips16_opcodes[bfd_mips16_num_opcodes];
+ for (mo = ip->insn_mo; mo < end; mo++)
+ if ((ip->insn_opcode & mo->mask) == mo->match)
+ {
+ ip->insn_mo = mo;
+ return;
+ }
+ abort ();
+}
+
/* Output an instruction. IP is the instruction information.
ADDRESS_EXPR is an operand of the instruction to be used with
RELOC_TYPE. */
@@ -3544,6 +3562,7 @@ append_insn (struct mips_cl_insn *ip, ex
{
/* Convert MIPS16 jr/jalr into a "compact" jump. */
ip->insn_opcode |= 0x0080;
+ find_altered_mips16_opcode (ip);
install_insn (ip);
insert_into_history (0, 1, ip);
}
Index: opcodes/mips16-opc.c
===================================================================
--- opcodes/mips16-opc.c 2011-06-25 21:00:14.000000000 +0100
+++ opcodes/mips16-opc.c 2011-06-29 19:56:09.000000000 +0100
@@ -171,6 +171,13 @@ const struct mips_opcode mips16_opcodes[
{"jr", "R", 0xe820, 0xffff, UBD|RD_31, 0, I1 },
{"j", "x", 0xe800, 0xf8ff, UBD|RD_x, 0, I1 },
{"j", "R", 0xe820, 0xffff, UBD|RD_31, 0, I1 },
+/* MIPS16e compact branches. We keep them near the ordinary branches
+ so that we easily find them when converting a normal branch to a
+ compact one. */
+{"jalrc", "x", 0xe8c0, 0xf8ff, UBR|WR_31|RD_x|TRAP, 0, I32 },
+{"jalrc", "R,x", 0xe8c0, 0xf8ff, UBR|WR_31|RD_x|TRAP, 0, I32 },
+{"jrc", "x", 0xe880, 0xf8ff, UBR|RD_x|TRAP, 0, I32 },
+{"jrc", "R", 0xe8a0, 0xffff, UBR|RD_31|TRAP, 0, I32 },
{"lb", "y,5(x)", 0x8000, 0xf800, WR_y|RD_x, 0, I1 },
{"lbu", "y,5(x)", 0xa000, 0xf800, WR_y|RD_x, 0, I1 },
{"ld", "y,D(x)", 0x3800, 0xf800, WR_y|RD_x, 0, I3 },
@@ -227,10 +234,6 @@ const struct mips_opcode mips16_opcodes[
{"sw", "R,V(S)", 0x6200, 0xff00, RD_31|RD_SP, 0, I1 },
{"xor", "x,y", 0xe80e, 0xf81f, WR_x|RD_x|RD_y, 0, I1 },
/* MIPS16e additions */
-{"jalrc", "x", 0xe8c0, 0xf8ff, UBR|WR_31|RD_x|TRAP, 0, I32 },
-{"jalrc", "R,x", 0xe8c0, 0xf8ff, UBR|WR_31|RD_x|TRAP, 0, I32 },
-{"jrc", "x", 0xe880, 0xf8ff, UBR|RD_x|TRAP, 0, I32 },
-{"jrc", "R", 0xe8a0, 0xffff, UBR|RD_31|TRAP, 0, I32 },
{"restore", "M", 0x6400, 0xff80, WR_31|RD_SP|WR_SP|TRAP, 0, I32 },
{"save", "m", 0x6480, 0xff80, RD_31|RD_SP|WR_SP|TRAP, 0, I32 },
{"sdbbp", "6", 0xe801, 0xf81f, TRAP, 0, I32 },