From ceb94aa50d68ec7393fac7e2b239aff8ec656f85 Mon Sep 17 00:00:00 2001
From: Richard Sandiford <rdsandiford@googlemail.com>
Date: Wed, 29 Jun 2011 20:42:48 +0000
Subject: [PATCH] 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.
---
 gas/ChangeLog        |  5 +++++
 gas/config/tc-mips.c | 19 +++++++++++++++++++
 opcodes/ChangeLog    |  4 ++++
 opcodes/mips16-opc.c | 11 +++++++----
 4 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index a2ddcda3d2c..40f56222fd4 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,8 @@
+2011-06-29  Richard Sandiford  <rdsandiford@googlemail.com>
+
+	* config/tc-mips.c (find_altered_mips16_opcode): New function.
+	(append_insn): Use it.
+
 2011-06-29  Richard Sandiford  <rdsandiford@googlemail.com>
 
 	* config/tc-mips.c (insn_uses_reg): Delete.
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 345d6d0df4c..d8da3d73800 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -3073,6 +3073,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.  */
@@ -3545,6 +3563,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
 		{
 		  /* 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);
 		} 
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 158d456309b..6cc01c74dbc 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,7 @@
+2011-06-29  Richard Sandiford  <rdsandiford@googlemail.com>
+
+	* mips16-opc.c (jalrc, jrc): Move earlier in file.
+
 2011-06-21  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* i386-dis.c (prefix_table): Re-indent PREFIX_VEX_0F388C and
diff --git a/opcodes/mips16-opc.c b/opcodes/mips16-opc.c
index c42ab272f84..0e50aec0ef4 100644
--- a/opcodes/mips16-opc.c
+++ b/opcodes/mips16-opc.c
@@ -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 },