Support R_SPARC_WDISP10 and R_SPARC_H34.
[external/binutils.git] / gas / config / tc-mips.c
index 66f0f46..449d8c3 100644 (file)
@@ -1,6 +1,6 @@
 /* tc-mips.c -- assemble code for a MIPS chip.
    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by the OSF and Ralph Campbell.
    Written by Keith Knowles and Ralph Campbell, working independently.
@@ -218,6 +218,7 @@ struct mips_set_options
   int ase_dsp;
   int ase_dspr2;
   int ase_mt;
+  int ase_mcu;
   /* Whether we are assembling for the mips16 processor.  0 if we are
      not, 1 if we are, and -1 if the value has not been initialized.
      Changed by `.set mips16' and `.set nomips16', and the -mips16 and
@@ -292,8 +293,8 @@ static struct mips_set_options mips_opts =
 {
   /* isa */ ISA_UNKNOWN, /* ase_mips3d */ -1, /* ase_mdmx */ -1,
   /* ase_smartmips */ 0, /* ase_dsp */ -1, /* ase_dspr2 */ -1, /* ase_mt */ -1,
-  /* mips16 */ -1, /* micromips */ -1, /* noreorder */ 0, /* at */ ATREG,
-  /* warn_about_macros */ 0, /* nomove */ 0, /* nobopt */ 0,
+  /* ase_mcu */ -1, /* mips16 */ -1, /* micromips */ -1, /* noreorder */ 0,
+  /* at */ ATREG, /* warn_about_macros */ 0, /* nomove */ 0, /* nobopt */ 0,
   /* noautoextend */ 0, /* gp32 */ 0, /* fp32 */ 0, /* arch */ CPU_UNKNOWN,
   /* sym32 */ FALSE, /* soft_float */ FALSE, /* single_float */ FALSE
 };
@@ -368,6 +369,10 @@ static int file_ase_mt;
 #define ISA_SUPPORTS_MT_ASE (mips_opts.isa == ISA_MIPS32R2             \
                             || mips_opts.isa == ISA_MIPS64R2)
 
+#define ISA_SUPPORTS_MCU_ASE (mips_opts.isa == ISA_MIPS32R2            \
+                             || mips_opts.isa == ISA_MIPS64R2          \
+                             || mips_opts.micromips)
+
 /* The argument of the -march= flag.  The architecture we are assembling.  */
 static int file_mips_arch = CPU_UNKNOWN;
 static const char *mips_arch_string;
@@ -492,13 +497,16 @@ static int mips_32bitmode = 0;
 /* True if CPU has a ror instruction.  */
 #define CPU_HAS_ROR(CPU)       CPU_HAS_DROR (CPU)
 
+/* True if CPU is in the Octeon family */
+#define CPU_IS_OCTEON(CPU) ((CPU) == CPU_OCTEON || (CPU) == CPU_OCTEONP || (CPU) == CPU_OCTEON2)
+
 /* True if CPU has seq/sne and seqi/snei instructions.  */
-#define CPU_HAS_SEQ(CPU)       ((CPU) == CPU_OCTEON)
+#define CPU_HAS_SEQ(CPU)       (CPU_IS_OCTEON (CPU))
 
 /* True if CPU does not implement the all the coprocessor insns.  For these
    CPUs only those COP insns are accepted that are explicitly marked to be
    available on the CPU.  ISA membership for COP insns is ignored.  */
-#define NO_ISA_COP(CPU)                ((CPU) == CPU_OCTEON)
+#define NO_ISA_COP(CPU)                (CPU_IS_OCTEON (CPU))
 
 /* True if mflo and mfhi can be immediately followed by instructions
    which write to the HI and LO registers.
@@ -1153,40 +1161,37 @@ static int mips_relax_branch;
 
    The information we store for this type of relaxation is the argument
    code found in the opcode file for this relocation, the register
-   selected as the assembler temporary, whether the user explicitly
-   requested a 16-bit form, whether the branch is unconditional, whether
-   it is compact, whether it stores the link address implicitly in $ra,
-   whether relaxation of out-of-range 32-bit branches to a sequence of
-   instructions is enabled, and whether the displacement of a branch is
-   too large to fit as an immediate argument of a 16-bit and a 32-bit
-   branch, respectively.  */
-#define RELAX_MICROMIPS_ENCODE(type, at, u16bit, uncond, compact, link,        \
-                              relax32, toofar16, toofar32)             \
-  (0x40000000                                                          \
-   | ((type) & 0xff)                                                   \
-   | (((at) & 0x1f) << 8)                                              \
-   | ((u16bit) ? 0x2000 : 0)                                           \
-   | ((uncond) ? 0x4000 : 0)                                           \
-   | ((compact) ? 0x8000 : 0)                                          \
-   | ((link) ? 0x10000 : 0)                                            \
-   | ((relax32) ? 0x20000 : 0)                                         \
-   | ((toofar16) ? 0x40000 : 0)                                                \
-   | ((toofar32) ? 0x80000 : 0))
+   selected as the assembler temporary, whether the branch is
+   unconditional, whether it is compact, whether it stores the link
+   address implicitly in $ra, whether relaxation of out-of-range 32-bit
+   branches to a sequence of instructions is enabled, and whether the
+   displacement of a branch is too large to fit as an immediate argument
+   of a 16-bit and a 32-bit branch, respectively.  */
+#define RELAX_MICROMIPS_ENCODE(type, at, uncond, compact, link,        \
+                              relax32, toofar16, toofar32)     \
+  (0x40000000                                                  \
+   | ((type) & 0xff)                                           \
+   | (((at) & 0x1f) << 8)                                      \
+   | ((uncond) ? 0x2000 : 0)                                   \
+   | ((compact) ? 0x4000 : 0)                                  \
+   | ((link) ? 0x8000 : 0)                                     \
+   | ((relax32) ? 0x10000 : 0)                                 \
+   | ((toofar16) ? 0x20000 : 0)                                        \
+   | ((toofar32) ? 0x40000 : 0))
 #define RELAX_MICROMIPS_P(i) (((i) & 0xc0000000) == 0x40000000)
 #define RELAX_MICROMIPS_TYPE(i) ((i) & 0xff)
 #define RELAX_MICROMIPS_AT(i) (((i) >> 8) & 0x1f)
-#define RELAX_MICROMIPS_U16BIT(i) (((i) & 0x2000) != 0)
-#define RELAX_MICROMIPS_UNCOND(i) (((i) & 0x4000) != 0)
-#define RELAX_MICROMIPS_COMPACT(i) (((i) & 0x8000) != 0)
-#define RELAX_MICROMIPS_LINK(i) (((i) & 0x10000) != 0)
-#define RELAX_MICROMIPS_RELAX32(i) (((i) & 0x20000) != 0)
-
-#define RELAX_MICROMIPS_TOOFAR16(i) (((i) & 0x40000) != 0)
-#define RELAX_MICROMIPS_MARK_TOOFAR16(i) ((i) | 0x40000)
-#define RELAX_MICROMIPS_CLEAR_TOOFAR16(i) ((i) & ~0x40000)
-#define RELAX_MICROMIPS_TOOFAR32(i) (((i) & 0x80000) != 0)
-#define RELAX_MICROMIPS_MARK_TOOFAR32(i) ((i) | 0x80000)
-#define RELAX_MICROMIPS_CLEAR_TOOFAR32(i) ((i) & ~0x80000)
+#define RELAX_MICROMIPS_UNCOND(i) (((i) & 0x2000) != 0)
+#define RELAX_MICROMIPS_COMPACT(i) (((i) & 0x4000) != 0)
+#define RELAX_MICROMIPS_LINK(i) (((i) & 0x8000) != 0)
+#define RELAX_MICROMIPS_RELAX32(i) (((i) & 0x10000) != 0)
+
+#define RELAX_MICROMIPS_TOOFAR16(i) (((i) & 0x20000) != 0)
+#define RELAX_MICROMIPS_MARK_TOOFAR16(i) ((i) | 0x20000)
+#define RELAX_MICROMIPS_CLEAR_TOOFAR16(i) ((i) & ~0x20000)
+#define RELAX_MICROMIPS_TOOFAR32(i) (((i) & 0x40000) != 0)
+#define RELAX_MICROMIPS_MARK_TOOFAR32(i) ((i) | 0x40000)
+#define RELAX_MICROMIPS_CLEAR_TOOFAR32(i) ((i) & ~0x40000)
 
 /* Is the given value a sign-extended 32-bit value?  */
 #define IS_SEXT_32BIT_NUM(x)                                           \
@@ -1351,6 +1356,8 @@ static void s_cprestore (int);
 static void s_cpreturn (int);
 static void s_dtprelword (int);
 static void s_dtpreldword (int);
+static void s_tprelword (int);
+static void s_tpreldword (int);
 static void s_gpvalue (int);
 static void s_gpword (int);
 static void s_gpdword (int);
@@ -1391,6 +1398,7 @@ struct mips_cpu_info
 #define MIPS_CPU_ASE_MIPS3D    0x0010  /* CPU implements MIPS-3D ASE */
 #define MIPS_CPU_ASE_MDMX      0x0020  /* CPU implements MDMX ASE */
 #define MIPS_CPU_ASE_DSPR2     0x0040  /* CPU implements DSP R2 ASE */
+#define MIPS_CPU_ASE_MCU       0x0080  /* CPU implements MCU ASE */
 
 static const struct mips_cpu_info *mips_parse_cpu (const char *, const char *);
 static const struct mips_cpu_info *mips_cpu_info_from_isa (int);
@@ -1429,6 +1437,8 @@ static const pseudo_typeS mips_pseudo_table[] =
   {"cpreturn", s_cpreturn, 0},
   {"dtprelword", s_dtprelword, 0},
   {"dtpreldword", s_dtpreldword, 0},
+  {"tprelword", s_tprelword, 0},
+  {"tpreldword", s_tpreldword, 0},
   {"gpvalue", s_gpvalue, 0},
   {"gpword", s_gpword, 0},
   {"gpdword", s_gpdword, 0},
@@ -1785,15 +1795,6 @@ insert_into_history (unsigned int first, unsigned int n,
     }
 }
 
-/* Emit a nop instruction, recording it in the history buffer.  */
-
-static void
-emit_nop (void)
-{
-  add_fixed_insn (NOP_INSN);
-  insert_into_history (0, 1, NOP_INSN);
-}
-
 /* Initialize vr4120_conflicts.  There is a bit of duplication here:
    the idea is to make it obvious at a glance that each errata is
    included.  */
@@ -2215,6 +2216,8 @@ is_opcode_valid (const struct mips_opcode *mo)
     isa |= INSN_MIPS3D;
   if (mips_opts.ase_smartmips)
     isa |= INSN_SMARTMIPS;
+  if (mips_opts.ase_mcu)
+    isa |= INSN_MCU;
 
   /* Don't accept instructions based on the ISA if the CPU does not implement
      all the coprocessor insns. */
@@ -2758,27 +2761,36 @@ reg_needs_delay (unsigned int reg)
   return 0;
 }
 
-/* Move all labels in insn_labels to the current insertion point.  */
+/* Move all labels in LABELS to the current insertion point.  TEXT_P
+   says whether the labels refer to text or data.  */
 
 static void
-mips_move_labels (void)
+mips_move_labels (struct insn_label_list *labels, bfd_boolean text_p)
 {
-  segment_info_type *si = seg_info (now_seg);
   struct insn_label_list *l;
   valueT val;
 
-  for (l = si->label_list; l != NULL; l = l->next)
+  for (l = labels; l != NULL; l = l->next)
     {
       gas_assert (S_GET_SEGMENT (l->label) == now_seg);
       symbol_set_frag (l->label, frag_now);
       val = (valueT) frag_now_fix ();
       /* MIPS16/microMIPS text labels are stored as odd.  */
-      if (HAVE_CODE_COMPRESSION)
+      if (text_p && HAVE_CODE_COMPRESSION)
        ++val;
       S_SET_VALUE (l->label, val);
     }
 }
 
+/* Move all labels in insn_labels to the current insertion point
+   and treat them as text labels.  */
+
+static void
+mips_move_text_labels (void)
+{
+  mips_move_labels (seg_info (now_seg)->label_list, TRUE);
+}
+
 static bfd_boolean
 s_is_linkonce (symbolS *sym, segT from_seg)
 {
@@ -2888,6 +2900,60 @@ relax_end (void)
   mips_relax.sequence = 0;
 }
 
+/* Return true if IP is a delayed branch or jump.  */
+
+static inline bfd_boolean
+delayed_branch_p (const struct mips_cl_insn *ip)
+{
+  return (ip->insn_mo->pinfo & (INSN_UNCOND_BRANCH_DELAY
+                               | INSN_COND_BRANCH_DELAY
+                               | INSN_COND_BRANCH_LIKELY)) != 0;
+}
+
+/* Return true if IP is a compact branch or jump.  */
+
+static inline bfd_boolean
+compact_branch_p (const struct mips_cl_insn *ip)
+{
+  if (mips_opts.mips16)
+    return (ip->insn_mo->pinfo & (MIPS16_INSN_UNCOND_BRANCH
+                                 | MIPS16_INSN_COND_BRANCH)) != 0;
+  else
+    return (ip->insn_mo->pinfo2 & (INSN2_UNCOND_BRANCH
+                                  | INSN2_COND_BRANCH)) != 0;
+}
+
+/* Return true if IP is an unconditional branch or jump.  */
+
+static inline bfd_boolean
+uncond_branch_p (const struct mips_cl_insn *ip)
+{
+  return ((ip->insn_mo->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0
+         || (mips_opts.mips16
+             ? (ip->insn_mo->pinfo & MIPS16_INSN_UNCOND_BRANCH) != 0
+             : (ip->insn_mo->pinfo2 & INSN2_UNCOND_BRANCH) != 0));
+}
+
+/* Return true if IP is a branch-likely instruction.  */
+
+static inline bfd_boolean
+branch_likely_p (const struct mips_cl_insn *ip)
+{
+  return (ip->insn_mo->pinfo & INSN_COND_BRANCH_LIKELY) != 0;
+}
+
+/* Return the type of nop that should be used to fill the delay slot
+   of delayed branch IP.  */
+
+static struct mips_cl_insn *
+get_delay_slot_nop (const struct mips_cl_insn *ip)
+{
+  if (mips_opts.micromips
+      && (ip->insn_mo->pinfo2 & INSN2_BRANCH_DELAY_32BIT))
+    return &micromips_nop32_insn;
+  return NOP_INSN;
+}
+
 /* Return the mask of core registers that IP reads or writes.  */
 
 static unsigned int
@@ -2900,33 +2966,10 @@ gpr_mod_mask (const struct mips_cl_insn *ip)
   pinfo2 = ip->insn_mo->pinfo2;
   if (mips_opts.micromips)
     {
-      if (pinfo2 & INSN2_MOD_GPR_MB)
-       mask |= 1 << micromips_to_32_reg_b_map[EXTRACT_OPERAND (1, MB, *ip)];
-      if (pinfo2 & INSN2_MOD_GPR_MC)
-       mask |= 1 << micromips_to_32_reg_c_map[EXTRACT_OPERAND (1, MC, *ip)];
       if (pinfo2 & INSN2_MOD_GPR_MD)
        mask |= 1 << micromips_to_32_reg_d_map[EXTRACT_OPERAND (1, MD, *ip)];
-      if (pinfo2 & INSN2_MOD_GPR_ME)
-       mask |= 1 << micromips_to_32_reg_e_map[EXTRACT_OPERAND (1, ME, *ip)];
       if (pinfo2 & INSN2_MOD_GPR_MF)
        mask |= 1 << micromips_to_32_reg_f_map[EXTRACT_OPERAND (1, MF, *ip)];
-      if (pinfo2 & INSN2_MOD_GPR_MG)
-       mask |= 1 << micromips_to_32_reg_g_map[EXTRACT_OPERAND (1, MG, *ip)];
-      if (pinfo2 & INSN2_MOD_GPR_MHI)
-       {
-         mask |= 1 << micromips_to_32_reg_h_map[EXTRACT_OPERAND (1, MH, *ip)];
-         mask |= 1 << micromips_to_32_reg_i_map[EXTRACT_OPERAND (1, MI, *ip)];
-       }
-      if (pinfo2 & INSN2_MOD_GPR_MJ)
-       mask |= 1 << EXTRACT_OPERAND (1, MJ, *ip);
-      if (pinfo2 & INSN2_MOD_GPR_MM)
-       mask |= 1 << micromips_to_32_reg_m_map[EXTRACT_OPERAND (1, MM, *ip)];
-      if (pinfo2 & INSN2_MOD_GPR_MN)
-       mask |= 1 << micromips_to_32_reg_n_map[EXTRACT_OPERAND (1, MN, *ip)];
-      if (pinfo2 & INSN2_MOD_GPR_MP)
-       mask |= 1 << EXTRACT_OPERAND (1, MP, *ip);
-      if (pinfo2 & INSN2_MOD_GPR_MQ)
-       mask |= 1 << micromips_to_32_reg_q_map[EXTRACT_OPERAND (1, MQ, *ip)];
       if (pinfo2 & INSN2_MOD_SP)
        mask |= 1 << SP;
     }
@@ -2977,6 +3020,26 @@ gpr_read_mask (const struct mips_cl_insn *ip)
       if (pinfo2 & INSN2_READ_GPR_Z)
        mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RZ, *ip);
     }
+  if (mips_opts.micromips)
+    {
+      if (pinfo2 & INSN2_READ_GPR_MC)
+       mask |= 1 << micromips_to_32_reg_c_map[EXTRACT_OPERAND (1, MC, *ip)];
+      if (pinfo2 & INSN2_READ_GPR_ME)
+       mask |= 1 << micromips_to_32_reg_e_map[EXTRACT_OPERAND (1, ME, *ip)];
+      if (pinfo2 & INSN2_READ_GPR_MG)
+       mask |= 1 << micromips_to_32_reg_g_map[EXTRACT_OPERAND (1, MG, *ip)];
+      if (pinfo2 & INSN2_READ_GPR_MJ)
+       mask |= 1 << EXTRACT_OPERAND (1, MJ, *ip);
+      if (pinfo2 & INSN2_READ_GPR_MMN)
+       {
+         mask |= 1 << micromips_to_32_reg_m_map[EXTRACT_OPERAND (1, MM, *ip)];
+         mask |= 1 << micromips_to_32_reg_n_map[EXTRACT_OPERAND (1, MN, *ip)];
+       }
+      if (pinfo2 & INSN2_READ_GPR_MP)
+       mask |= 1 << EXTRACT_OPERAND (1, MP, *ip);
+      if (pinfo2 & INSN2_READ_GPR_MQ)
+       mask |= 1 << micromips_to_32_reg_q_map[EXTRACT_OPERAND (1, MQ, *ip)];
+    }
   /* Don't include register 0.  */
   return mask & ~1;
 }
@@ -3015,13 +3078,27 @@ gpr_write_mask (const struct mips_cl_insn *ip)
        mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RD, *ip);
       if (pinfo & INSN_WRITE_GPR_T)
        mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RT, *ip);
-      if (pinfo2 & INSN2_WRITE_GPR_S)
+      if (pinfo & INSN_WRITE_GPR_S)
        mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RS, *ip);
       if (pinfo & INSN_WRITE_GPR_31)
        mask |= 1 << RA;
       if (pinfo2 & INSN2_WRITE_GPR_Z)
        mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RZ, *ip);
     }
+  if (mips_opts.micromips)
+    {
+      if (pinfo2 & INSN2_WRITE_GPR_MB)
+       mask |= 1 << micromips_to_32_reg_b_map[EXTRACT_OPERAND (1, MB, *ip)];
+      if (pinfo2 & INSN2_WRITE_GPR_MHI)
+       {
+         mask |= 1 << micromips_to_32_reg_h_map[EXTRACT_OPERAND (1, MH, *ip)];
+         mask |= 1 << micromips_to_32_reg_i_map[EXTRACT_OPERAND (1, MI, *ip)];
+       }
+      if (pinfo2 & INSN2_WRITE_GPR_MJ)
+       mask |= 1 << EXTRACT_OPERAND (1, MJ, *ip);
+      if (pinfo2 & INSN2_WRITE_GPR_MP)
+       mask |= 1 << EXTRACT_OPERAND (1, MP, *ip);
+    }
   /* Don't include register 0.  */
   return mask & ~1;
 }
@@ -3160,10 +3237,7 @@ insns_between (const struct mips_cl_insn *insn1,
          if (insn2 == NULL
              || insn2->insn_opcode == INSN_ERET
              || insn2->insn_opcode == INSN_DERET
-             || (insn2->insn_mo->pinfo
-                 & (INSN_UNCOND_BRANCH_DELAY
-                    | INSN_COND_BRANCH_DELAY
-                    | INSN_COND_BRANCH_LIKELY)) != 0)
+             || delayed_branch_p (insn2))
            return 1;
        }
     }
@@ -3554,18 +3628,14 @@ nops_for_insn_or_target (int ignore, const struct mips_cl_insn *hist,
   int nops, tmp_nops;
 
   nops = nops_for_insn (ignore, hist, insn);
-  if (insn->insn_mo->pinfo & (INSN_UNCOND_BRANCH_DELAY
-                             | INSN_COND_BRANCH_DELAY
-                             | INSN_COND_BRANCH_LIKELY))
+  if (delayed_branch_p (insn))
     {
       tmp_nops = nops_for_sequence (2, ignore ? ignore + 2 : 0,
-                                   hist, insn, NOP_INSN);
+                                   hist, insn, get_delay_slot_nop (insn));
       if (tmp_nops > nops)
        nops = tmp_nops;
     }
-  else if (mips_opts.mips16
-          && (insn->insn_mo->pinfo & (MIPS16_INSN_UNCOND_BRANCH
-                                      | MIPS16_INSN_COND_BRANCH)))
+  else if (compact_branch_p (insn))
     {
       tmp_nops = nops_for_sequence (1, ignore ? ignore + 1 : 0, hist, insn);
       if (tmp_nops > nops)
@@ -3631,13 +3701,9 @@ fix_loongson2f (struct mips_cl_insn * ip)
 static bfd_boolean
 can_swap_branch_p (struct mips_cl_insn *ip)
 {
-  unsigned long pinfo, pinfo2, prev_pinfo;
+  unsigned long pinfo, pinfo2, prev_pinfo, prev_pinfo2;
   unsigned int gpr_read, gpr_write, prev_gpr_read, prev_gpr_write;
 
-  /* For microMIPS, disable reordering.  */
-  if (mips_opts.micromips)
-    return FALSE;
-
   /* -O2 and above is required for this optimization.  */
   if (mips_optimize < 2)
     return FALSE;
@@ -3665,9 +3731,8 @@ can_swap_branch_p (struct mips_cl_insn *ip)
   if (history[1].noreorder_p)
     return FALSE;
 
-  /* If the previous instruction had a fixup in mips16 mode, we can not
-     swap.  This normally means that the previous instruction was a 4
-     byte branch anyhow.  */
+  /* If the previous instruction had a fixup in mips16 mode, we can not swap.
+     This means that the previous instruction was a 4-byte one anyhow.  */
   if (mips_opts.mips16 && history[0].fixp[0])
     return FALSE;
 
@@ -3680,9 +3745,8 @@ can_swap_branch_p (struct mips_cl_insn *ip)
 
   /* If the previous instruction is in a variant frag other than this
      branch's one, we cannot do the swap.  This does not apply to
-     MIPS16/microMIPS code, which uses variant frags for different
-     purposes.  */
-  if (!HAVE_CODE_COMPRESSION
+     MIPS16 code, which uses variant frags for different purposes.  */
+  if (!mips_opts.mips16
       && history[0].frag
       && history[0].frag->fr_type == rs_machine_dependent)
     return FALSE;
@@ -3736,8 +3800,11 @@ can_swap_branch_p (struct mips_cl_insn *ip)
     return FALSE;
 
   /* If the previous instruction uses the PC, we can not swap.  */
+  prev_pinfo2 = history[0].insn_mo->pinfo2;
   if (mips_opts.mips16 && (prev_pinfo & MIPS16_INSN_READ_PC))
     return FALSE;
+  if (mips_opts.micromips && (prev_pinfo2 & INSN2_READ_PC))
+    return FALSE;
 
   /* If the previous instruction has an incorrect size for a fixed
      branch delay slot in microMIPS mode, we cannot swap.  */
@@ -3771,27 +3838,20 @@ get_append_method (struct mips_cl_insn *ip)
     return APPEND_ADD;
 
   /* Otherwise, it's our responsibility to fill branch delay slots.  */
-  pinfo = ip->insn_mo->pinfo;
-  if ((pinfo & INSN_UNCOND_BRANCH_DELAY)
-      || (pinfo & INSN_COND_BRANCH_DELAY))
+  if (delayed_branch_p (ip))
     {
-      if (can_swap_branch_p (ip))
+      if (!branch_likely_p (ip) && can_swap_branch_p (ip))
        return APPEND_SWAP;
 
+      pinfo = ip->insn_mo->pinfo;
       if (mips_opts.mips16
          && ISA_SUPPORTS_MIPS16E
-         && (pinfo & INSN_UNCOND_BRANCH_DELAY)
          && (pinfo & (MIPS16_INSN_READ_X | MIPS16_INSN_READ_31)))
        return APPEND_ADD_COMPACT;
 
       return APPEND_ADD_WITH_NOP;
     }
 
-  /* We don't bother trying to track the target of branches, so there's
-     nothing we can use to fill a branch-likely slot.  */
-  if (pinfo & INSN_COND_BRANCH_LIKELY)
-    return APPEND_ADD_WITH_NOP;
-
   return APPEND_ADD;
 }
 
@@ -3875,6 +3935,8 @@ micromips_add_label (void)
 #if defined(OBJ_ELF) || defined(OBJ_MAYBE_ELF)
   if (IS_ELF)
     S_SET_OTHER (s, ELF_ST_SET_MICROMIPS (S_GET_OTHER (s)));
+#else
+  (void) s;
 #endif
 }
 
@@ -3941,10 +4003,11 @@ static void
 append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
             bfd_reloc_code_real_type *reloc_type, bfd_boolean expansionp)
 {
-  unsigned long prev_pinfo, prev_pinfo2, pinfo, pinfo2;
+  unsigned long prev_pinfo2, pinfo;
   bfd_boolean relaxed_branch = FALSE;
   enum append_method method;
   bfd_boolean relax32;
+  int branch_disp;
 
   if (mips_fix_loongson2f && !HAVE_CODE_COMPRESSION)
     fix_loongson2f (ip);
@@ -3954,10 +4017,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
   file_ase_mips16 |= mips_opts.mips16;
   file_ase_micromips |= mips_opts.micromips;
 
-  prev_pinfo = history[0].insn_mo->pinfo;
   prev_pinfo2 = history[0].insn_mo->pinfo2;
   pinfo = ip->insn_mo->pinfo;
-  pinfo2 = ip->insn_mo->pinfo2;
 
   if (mips_opts.micromips
       && !expansionp
@@ -4080,7 +4141,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
          old_frag_offset = frag_now_fix ();
 
          for (i = 0; i < nops; i++)
-           emit_nop ();
+           add_fixed_insn (NOP_INSN);
+         insert_into_history (0, nops, NOP_INSN);
 
          if (listing)
            {
@@ -4096,7 +4158,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
              frag_grow (40);
            }
 
-         mips_move_labels ();
+         mips_move_text_labels ();
 
 #ifndef NO_ECOFF_DEBUGGING
          if (ECOFF_DEBUGGING)
@@ -4137,6 +4199,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
     }
 
   method = get_append_method (ip);
+  branch_disp = method == APPEND_SWAP ? insn_length (history) : 0;
 
 #ifdef OBJ_ELF
   /* The value passed to dwarf2_emit_insn is the distance between
@@ -4154,8 +4217,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
      and for MIPS16/microMIPS code also prevents a debugger from
      placing a breakpoint in the middle of the branch (and corrupting
      code if software breakpoints are used).  */
-  dwarf2_emit_insn ((HAVE_CODE_COMPRESSION ? -1 : 0)
-                   + (method == APPEND_SWAP ? insn_length (history) : 0));
+  dwarf2_emit_insn ((HAVE_CODE_COMPRESSION ? -1 : 0) + branch_disp);
 #endif
 
   relax32 = (mips_relax_branch
@@ -4166,28 +4228,24 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
             && (mips_opts.at || mips_pic == NO_PIC)
             /* Don't relax BPOSGE32/64 as they have no complementing
                branches.  */
-            && !(ip->insn_mo->membership & (INSN_DSP64 | INSN_DSP))
-            /* Don't try 32-bit branch relaxation when users specify
-               16-bit/32-bit instructions.  */
-            && !forced_insn_length);
+            && !(ip->insn_mo->membership & (INSN_DSP64 | INSN_DSP)));
 
   if (!HAVE_CODE_COMPRESSION
       && address_expr
       && relax32
       && *reloc_type == BFD_RELOC_16_PCREL_S2
-      && (pinfo & INSN_UNCOND_BRANCH_DELAY || pinfo & INSN_COND_BRANCH_DELAY
-         || pinfo & INSN_COND_BRANCH_LIKELY))
+      && delayed_branch_p (ip))
     {
       relaxed_branch = TRUE;
       add_relaxed_insn (ip, (relaxed_branch_length
                             (NULL, NULL,
-                             (pinfo & INSN_UNCOND_BRANCH_DELAY) ? -1
-                             : (pinfo & INSN_COND_BRANCH_LIKELY) ? 1
+                             uncond_branch_p (ip) ? -1
+                             : branch_likely_p (ip) ? 1
                              : 0)), 4,
                        RELAX_BRANCH_ENCODE
                        (AT,
-                        pinfo & INSN_UNCOND_BRANCH_DELAY,
-                        pinfo & INSN_COND_BRANCH_LIKELY,
+                        uncond_branch_p (ip),
+                        branch_likely_p (ip),
                         pinfo & INSN_WRITE_GPR_31,
                         0),
                        address_expr->X_add_symbol,
@@ -4198,28 +4256,26 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
           && address_expr
           && ((relax32 && *reloc_type == BFD_RELOC_16_PCREL_S2)
               || *reloc_type > BFD_RELOC_UNUSED)
-          && (pinfo & INSN_UNCOND_BRANCH_DELAY
-              || pinfo & INSN_COND_BRANCH_DELAY
-              || (pinfo2 & ~INSN2_ALIAS) == INSN2_UNCOND_BRANCH
-              || pinfo2 & INSN2_COND_BRANCH))
+          && (delayed_branch_p (ip) || compact_branch_p (ip))
+          /* Don't try branch relaxation when users specify
+             16-bit/32-bit instructions.  */
+          && !forced_insn_length)
     {
       bfd_boolean relax16 = *reloc_type > BFD_RELOC_UNUSED;
       int type = relax16 ? *reloc_type - BFD_RELOC_UNUSED : 0;
-      int uncond = (pinfo & INSN_UNCOND_BRANCH_DELAY
-                   || pinfo2 & INSN2_UNCOND_BRANCH) ? -1 : 0;
-      int compact = pinfo2 & (INSN2_COND_BRANCH | INSN2_UNCOND_BRANCH);
+      int uncond = uncond_branch_p (ip) ? -1 : 0;
+      int compact = compact_branch_p (ip);
       int al = pinfo & INSN_WRITE_GPR_31;
       int length32;
 
       gas_assert (address_expr != NULL);
       gas_assert (!mips_relax.sequence);
 
+      relaxed_branch = TRUE;
       length32 = relaxed_micromips_32bit_branch_length (NULL, NULL, uncond);
       add_relaxed_insn (ip, relax32 ? length32 : 4, relax16 ? 2 : 4,
-                       RELAX_MICROMIPS_ENCODE (type, AT,
-                                               forced_insn_length == 2,
-                                               uncond, compact, al, relax32,
-                                               0, 0),
+                       RELAX_MICROMIPS_ENCODE (type, AT, uncond, compact, al,
+                                               relax32, 0, 0),
                        address_expr->X_add_symbol,
                        address_expr->X_add_number);
       *reloc_type = BFD_RELOC_UNUSED;
@@ -4232,7 +4288,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
                        RELAX_MIPS16_ENCODE
                        (*reloc_type - BFD_RELOC_UNUSED,
                         forced_insn_length == 2, forced_insn_length == 4,
-                        prev_pinfo & INSN_UNCOND_BRANCH_DELAY,
+                        delayed_branch_p (&history[0]),
                         history[0].mips16_absolute_jump_p),
                        make_expr_symbol (address_expr), 0);
     }
@@ -4240,7 +4296,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
           && ! ip->use_extend
           && *reloc_type != BFD_RELOC_MIPS16_JMP)
     {
-      if ((pinfo & INSN_UNCOND_BRANCH_DELAY) == 0)
+      if (!delayed_branch_p (ip))
        /* Make sure there is enough room to swap this instruction with
           a following jump instruction.  */
        frag_grow (6);
@@ -4250,7 +4306,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
     {
       if (mips_opts.mips16
          && mips_opts.noreorder
-         && (prev_pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
+         && delayed_branch_p (&history[0]))
        as_warn (_("extended instruction in delay slot"));
 
       if (mips_relax.sequence)
@@ -4400,21 +4456,16 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
       break;
 
     case APPEND_ADD_WITH_NOP:
-      insert_into_history (0, 1, ip);
-      if (mips_opts.micromips
-         && (pinfo2 & INSN2_BRANCH_DELAY_32BIT))
-       {
-         add_fixed_insn (&micromips_nop32_insn);
-         insert_into_history (0, 1, &micromips_nop32_insn);
-         if (mips_relax.sequence)
-           mips_relax.sizes[mips_relax.sequence - 1] += 4;
-       }
-      else
-       {
-         emit_nop ();
-         if (mips_relax.sequence)
-           mips_relax.sizes[mips_relax.sequence - 1] += NOP_INSN_SIZE;
-       }
+      {
+       struct mips_cl_insn *nop;
+
+       insert_into_history (0, 1, ip);
+       nop = get_delay_slot_nop (ip);
+       add_fixed_insn (nop);
+       insert_into_history (0, 1, nop);
+       if (mips_relax.sequence)
+         mips_relax.sizes[mips_relax.sequence - 1] += insn_length (nop);
+      }
       break;
 
     case APPEND_ADD_COMPACT:
@@ -4435,25 +4486,21 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
            move_insn (ip, delay.frag, delay.where);
            move_insn (&delay, ip->frag, ip->where + insn_length (ip));
          }
-       else if (mips_opts.micromips)
-         {
-           /* We don't reorder for micromips.  */
-           abort ();
-         }
        else if (relaxed_branch)
          {
            /* Add the delay slot instruction to the end of the
               current frag and shrink the fixed part of the
               original frag.  If the branch occupies the tail of
               the latter, move it backwards to cover the gap.  */
-           delay.frag->fr_fix -= 4;
+           delay.frag->fr_fix -= branch_disp;
            if (delay.frag == ip->frag)
-             move_insn (ip, ip->frag, ip->where - 4);
+             move_insn (ip, ip->frag, ip->where - branch_disp);
            add_fixed_insn (&delay);
          }
        else
          {
-           move_insn (&delay, ip->frag, ip->where);
+           move_insn (&delay, ip->frag,
+                      ip->where - branch_disp + insn_length (ip));
            move_insn (ip, history[0].frag, history[0].where);
          }
        history[0] = *ip;
@@ -4464,9 +4511,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
     }
 
   /* If we have just completed an unconditional branch, clear the history.  */
-  if ((history[1].insn_mo->pinfo & INSN_UNCOND_BRANCH_DELAY)
-      || (mips_opts.mips16
-         && (history[0].insn_mo->pinfo & MIPS16_INSN_UNCOND_BRANCH)))
+  if ((delayed_branch_p (&history[1]) && uncond_branch_p (&history[1]))
+      || (compact_branch_p (&history[0]) && uncond_branch_p (&history[0])))
     mips_no_prev_insn ();
 
   /* We need to emit a label at the end of branch-likely macros.  */
@@ -4504,7 +4550,7 @@ mips_emit_delays (void)
        {
          while (nops-- > 0)
            add_fixed_insn (NOP_INSN);
-         mips_move_labels ();
+         mips_move_text_labels ();
        }
     }
   mips_no_prev_insn ();
@@ -4548,7 +4594,7 @@ start_noreorder (void)
             decrease the size of prev_nop_frag.  */
          frag_wane (frag_now);
          frag_new (0);
-         mips_move_labels ();
+         mips_move_text_labels ();
        }
       mips_mark_labels ();
       mips_clear_insn_labels ();
@@ -4562,7 +4608,6 @@ start_noreorder (void)
 static void
 end_noreorder (void)
 {
-
   mips_opts.noreorder--;
   if (mips_opts.noreorder == 0 && prev_nop_frag != NULL)
     {
@@ -4586,10 +4631,7 @@ macro_start (void)
          sizeof (mips_macro_warning.first_insn_sizes));
   memset (&mips_macro_warning.insns, 0, sizeof (mips_macro_warning.insns));
   mips_macro_warning.delay_slot_p = (mips_opts.noreorder
-                                    && (history[0].insn_mo->pinfo
-                                        & (INSN_UNCOND_BRANCH_DELAY
-                                           | INSN_COND_BRANCH_DELAY
-                                           | INSN_COND_BRANCH_LIKELY)) != 0);
+                                    && delayed_branch_p (&history[0]));
   switch (history[0].insn_mo->pinfo2
          & (INSN2_BRANCH_DELAY_32BIT | INSN2_BRANCH_DELAY_16BIT))
     {
@@ -5024,9 +5066,14 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
          INSERT_OPERAND (1, OFFSET10, insn, va_arg (args, int));
          continue;
 
+       case '\\':
+         INSERT_OPERAND (mips_opts.micromips,
+                         3BITPOS, insn, va_arg (args, unsigned int));
+         continue;
+
        case '~':
-         gas_assert (mips_opts.micromips);
-         INSERT_OPERAND (1, OFFSET12, insn, va_arg (args, unsigned long));
+         INSERT_OPERAND (mips_opts.micromips,
+                         OFFSET12, insn, va_arg (args, unsigned long));
          continue;
 
        case 'N':
@@ -5230,9 +5277,7 @@ macro_build_jalr (expressionS *ep, int cprestore)
       frag_grow (8);
       f = frag_more (0);
     }
-  if (!mips_opts.micromips)
-    macro_build (NULL, "jalr", "d,s", RA, PIC_CALL_REG);
-  else
+  if (mips_opts.micromips)
     {
       jalr = mips_opts.noreorder && !cprestore ? "jalr" : "jalrs";
       if (MIPS_JALR_HINT_P (ep))
@@ -5240,6 +5285,8 @@ macro_build_jalr (expressionS *ep, int cprestore)
       else
        macro_build (NULL, jalr, "mj", PIC_CALL_REG);
     }
+  else
+    macro_build (NULL, "jalr", "d,s", RA, PIC_CALL_REG);
   if (MIPS_JALR_HINT_P (ep))
     fix_new_exp (frag_now, f - frag_now->fr_literal, 4, ep, FALSE, jalr_reloc);
 }
@@ -5914,7 +5961,7 @@ move_register (int dest, int source)
      instruction specifically requires a 32-bit one.  */
   if (mips_opts.micromips
       && !(history[0].insn_mo->pinfo2 & INSN2_BRANCH_DELAY_32BIT))
-    macro_build (NULL, "move", "mp,mj", dest, source );
+    macro_build (NULL, "move", "mp,mj", dest, source);
   else
     macro_build (NULL, HAVE_32BIT_GPRS ? "addu" : "daddu", "d,v,t",
                 dest, source, 0);
@@ -6230,6 +6277,7 @@ macro (struct mips_cl_insn *ip)
   int ust = 0;
   int lp = 0;
   int ab = 0;
+  int off0 = 0;
   int off;
   offsetT maxnum;
   bfd_reloc_code_real_type r;
@@ -7861,6 +7909,22 @@ macro (struct mips_cl_insn *ip)
 
       break;
 
+    case M_ACLR_AB:
+      ab = 1;
+    case M_ACLR_OB:
+      s = "aclr";
+      treg = EXTRACT_OPERAND (mips_opts.micromips, 3BITPOS, *ip);
+      fmt = "\\,~(b)";
+      off12 = 1;
+      goto ld_st;
+    case M_ASET_AB:
+      ab = 1;
+    case M_ASET_OB:
+      s = "aset";
+      treg = EXTRACT_OPERAND (mips_opts.micromips, 3BITPOS, *ip);
+      fmt = "\\,~(b)";
+      off12 = 1;
+      goto ld_st;
     case M_LB_AB:
       ab = 1;
       s = "lb";
@@ -8248,20 +8312,29 @@ macro (struct mips_cl_insn *ip)
                             tempreg, tempreg, breg);
              breg = tempreg;
            }
-         if (!off12)
+         if (off0)
+           {
+             if (offset_expr.X_add_number == 0)
+               tempreg = breg;
+             else
+               macro_build (&offset_expr, ADDRESS_ADDI_INSN,
+                            "t,r,j", tempreg, breg, BFD_RELOC_LO16);
+             macro_build (NULL, s, fmt, treg, tempreg);
+           }
+         else if (!off12)
            macro_build (&offset_expr, s, fmt, treg, BFD_RELOC_LO16, breg);
          else
            macro_build (NULL, s, fmt,
                         treg, (unsigned long) offset_expr.X_add_number, breg);
        }
-      else if (off12)
+      else if (off12 || off0)
        {
-         /* A 12-bit offset field is too narrow to be used for a low-part
-            relocation, so load the whole address into the auxillary
-            register.  In the case of "A(b)" addresses, we first load
-            absolute address "A" into the register and then add base
-            register "b".  In the case of "o(b)" addresses, we simply
-            need to add 16-bit offset "o" to base register "b", and
+         /* A 12-bit or 0-bit offset field is too narrow to be used
+            for a low-part relocation, so load the whole address into
+            the auxillary register.  In the case of "A(b)" addresses,
+            we first load absolute address "A" into the register and
+            then add base register "b".  In the case of "o(b)" addresses,
+            we simply need to add 16-bit offset "o" to base register "b", and
             offset_reloc already contains the relocations associated
             with "o".  */
          if (ab)
@@ -8276,8 +8349,11 @@ macro (struct mips_cl_insn *ip)
                         tempreg, breg, -1,
                         offset_reloc[0], offset_reloc[1], offset_reloc[2]);
          expr1.X_add_number = 0;
-         macro_build (NULL, s, fmt,
-                      treg, (unsigned long) expr1.X_add_number, tempreg);
+         if (off0)
+           macro_build (NULL, s, fmt, treg, tempreg);
+         else
+           macro_build (NULL, s, fmt,
+                        treg, (unsigned long) expr1.X_add_number, tempreg);
        }
       else if (mips_pic == NO_PIC)
        {
@@ -9071,6 +9147,22 @@ macro (struct mips_cl_insn *ip)
        }
       break;
 
+       
+    case M_SAA_AB:
+      ab = 1;
+    case M_SAA_OB:
+      s = "saa";
+      off0 = 1;
+      fmt = "t,(b)";
+      goto ld_st;
+    case M_SAAD_AB:
+      ab = 1;
+    case M_SAAD_OB:
+      s = "saad";
+      off0 = 1;
+      fmt = "t,(b)";
+      goto ld_st;
+
    /* New code added to support COPZ instructions.
       This code builds table entries out of the macros in mip_opcodes.
       R4000 uses interlocks to handle coproc delays.
@@ -9104,7 +9196,7 @@ macro (struct mips_cl_insn *ip)
       if (NO_ISA_COP (mips_opts.arch)
          && (ip->insn_mo->pinfo2 & INSN2_M_FP_S) == 0)
        {
-         as_bad (_("opcode not supported on this processor: %s"),
+         as_bad (_("Opcode not supported on this processor: %s"),
                  mips_cpu_info_from_arch (mips_opts.arch)->name);
          break;
        }
@@ -10250,6 +10342,8 @@ validate_mips_insn (const struct mips_opcode *opc)
       case '$': USE_BITS (OP_MASK_MT_H,                OP_SH_MT_H);    break;
       case '*': USE_BITS (OP_MASK_MTACC_T,     OP_SH_MTACC_T); break;
       case '&': USE_BITS (OP_MASK_MTACC_D,     OP_SH_MTACC_D); break;
+      case '\\': USE_BITS (OP_MASK_3BITPOS,    OP_SH_3BITPOS); break;
+      case '~': USE_BITS (OP_MASK_OFFSET12,    OP_SH_OFFSET12); break;
       case 'g': USE_BITS (OP_MASK_RD,          OP_SH_RD);      break;
       default:
        as_bad (_("internal: bad mips opcode (unknown operand type `%c'): %s %s"),
@@ -10399,7 +10493,7 @@ validate_micromips_insn (const struct mips_opcode *opc)
       case 'D': USE_BITS (FD);         break;
       case 'E': USE_BITS (RT);         break;
       case 'G': USE_BITS (RS);         break;
-      case 'H': USE_BITS (SEL);        break;
+      case 'H': USE_BITS (SEL);                break;
       case 'K': USE_BITS (RS);         break;
       case 'M': USE_BITS (CCC);                break;
       case 'N': USE_BITS (BCC);                break;
@@ -10407,6 +10501,7 @@ validate_micromips_insn (const struct mips_opcode *opc)
       case 'S': USE_BITS (FS);         break;
       case 'T': USE_BITS (FT);         break;
       case 'V': USE_BITS (FS);         break;
+      case '\\': USE_BITS (3BITPOS);   break;
       case 'a': USE_BITS (TARGET);     break;
       case 'b': USE_BITS (RS);         break;
       case 'c': USE_BITS (CODE);       break;
@@ -10650,7 +10745,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
            return;
 
          if (!ok)
-           sprintf (buf, _("opcode not supported on this processor: %s (%s)"),
+           sprintf (buf, _("Opcode not supported on this processor: %s (%s)"),
                     mips_cpu_info_from_arch (mips_opts.arch)->name,
                     mips_cpu_info_from_isa (mips_opts.isa)->name);
          else
@@ -10913,6 +11008,25 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                as_bad (_("Invalid dsp/smartmips acc register"));
              break;
 
+           case '\\':          /* 3-bit bit position.  */
+             {
+               unsigned long mask = (mips_opts.micromips
+                                     ? MICROMIPSOP_MASK_3BITPOS
+                                     : OP_MASK_3BITPOS);
+
+               my_getExpression (&imm_expr, s);
+               check_absolute_expr (ip, &imm_expr);
+               if ((unsigned long) imm_expr.X_add_number > mask)
+                 as_warn (_("Bit position for %s not in range 0..%lu (%lu)"),
+                          ip->insn_mo->name,
+                          mask, (unsigned long) imm_expr.X_add_number);
+               INSERT_OPERAND (mips_opts.micromips,
+                               3BITPOS, *ip, imm_expr.X_add_number);
+               imm_expr.X_op = O_absent;
+               s = expr_end;
+             }
+             continue;
+
            case ',':
              ++argnum;
              if (*s++ == *args)
@@ -11351,8 +11465,8 @@ mips_ip (char *str, struct mips_cl_insn *ip)
              break;
 
            case '.':           /* 10-bit offset.  */
-           case '~':           /* 12-bit offset.  */
              gas_assert (mips_opts.micromips);
+           case '~':           /* 12-bit offset.  */
              {
                int shift = *args == '.' ? 9 : 11;
                size_t i;
@@ -11378,7 +11492,8 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                if (shift == 9)
                  INSERT_OPERAND (1, OFFSET10, *ip, imm_expr.X_add_number);
                else
-                 INSERT_OPERAND (1, OFFSET12, *ip, imm_expr.X_add_number);
+                 INSERT_OPERAND (mips_opts.micromips,
+                                 OFFSET12, *ip, imm_expr.X_add_number);
                imm_expr.X_op = O_absent;
                s = expr_end;
              }
@@ -12660,7 +12775,12 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                  if (offset_expr.X_op == O_register)
                    break;
 
-                 *offset_reloc = (int) BFD_RELOC_UNUSED + c;
+                 if (!forced_insn_length)
+                   *offset_reloc = (int) BFD_RELOC_UNUSED + c;
+                 else if (c == 'D')
+                   *offset_reloc = BFD_RELOC_MICROMIPS_10_PCREL_S1;
+                 else
+                   *offset_reloc = BFD_RELOC_MICROMIPS_7_PCREL_S1;
                  s = expr_end;
                  continue;
 
@@ -13154,7 +13274,7 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
                {
                  static char buf[100];
                  sprintf (buf,
-                          _("opcode not supported on this processor: %s (%s)"),
+                          _("Opcode not supported on this processor: %s (%s)"),
                           mips_cpu_info_from_arch (mips_opts.arch)->name,
                           mips_cpu_info_from_isa (mips_opts.isa)->name);
                  insn_error = buf;
@@ -13966,7 +14086,14 @@ static const struct percent_op_match mips16_percent_op[] =
   {"%gprel", BFD_RELOC_MIPS16_GPREL},
   {"%got", BFD_RELOC_MIPS16_GOT16},
   {"%call16", BFD_RELOC_MIPS16_CALL16},
-  {"%hi", BFD_RELOC_MIPS16_HI16_S}
+  {"%hi", BFD_RELOC_MIPS16_HI16_S},
+  {"%tlsgd", BFD_RELOC_MIPS16_TLS_GD},
+  {"%tlsldm", BFD_RELOC_MIPS16_TLS_LDM},
+  {"%dtprel_hi", BFD_RELOC_MIPS16_TLS_DTPREL_HI16},
+  {"%dtprel_lo", BFD_RELOC_MIPS16_TLS_DTPREL_LO16},
+  {"%tprel_hi", BFD_RELOC_MIPS16_TLS_TPREL_HI16},
+  {"%tprel_lo", BFD_RELOC_MIPS16_TLS_TPREL_LO16},
+  {"%gottprel", BFD_RELOC_MIPS16_TLS_GOTTPREL}
 };
 
 
@@ -14151,6 +14278,8 @@ enum options
     OPTION_NO_DSPR2,
     OPTION_MICROMIPS,
     OPTION_NO_MICROMIPS,
+    OPTION_MCU,
+    OPTION_NO_MCU,
     OPTION_COMPAT_ARCH_BASE,
     OPTION_M4650,
     OPTION_NO_M4650,
@@ -14245,6 +14374,8 @@ struct option md_longopts[] =
   {"mno-dspr2", no_argument, NULL, OPTION_NO_DSPR2},
   {"mmicromips", no_argument, NULL, OPTION_MICROMIPS},
   {"mno-micromips", no_argument, NULL, OPTION_NO_MICROMIPS},
+  {"mmcu", no_argument, NULL, OPTION_MCU},
+  {"mno-mcu", no_argument, NULL, OPTION_NO_MCU},
 
   /* Old-style architecture options.  Don't add more of these.  */
   {"m4650", no_argument, NULL, OPTION_M4650},
@@ -14499,6 +14630,14 @@ md_parse_option (int c, char *arg)
       mips_opts.ase_mt = 0;
       break;
 
+    case OPTION_MCU:
+      mips_opts.ase_mcu = 1;
+      break;
+
+    case OPTION_NO_MCU:
+      mips_opts.ase_mcu = 0;
+      break;
+
     case OPTION_MICROMIPS:
       if (mips_opts.mips16 == 1)
        {
@@ -14998,6 +15137,12 @@ mips_after_parse_args (void)
     as_warn (_("%s ISA does not support MT ASE"),
             mips_cpu_info_from_isa (mips_opts.isa)->name);
 
+  if (mips_opts.ase_mcu == -1)
+    mips_opts.ase_mcu = (arch_info->flags & MIPS_CPU_ASE_MCU) ? 1 : 0;
+  if (mips_opts.ase_mcu && !ISA_SUPPORTS_MCU_ASE)
+      as_warn (_("%s ISA does not support MCU ASE"),
+              mips_cpu_info_from_isa (mips_opts.isa)->name);
+
   file_mips_isa = mips_opts.isa;
   file_ase_mips3d = mips_opts.ase_mips3d;
   file_ase_mdmx = mips_opts.ase_mdmx;
@@ -15277,6 +15422,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
     case BFD_RELOC_MIPS_TLS_DTPREL_HI16:
     case BFD_RELOC_MIPS_TLS_DTPREL_LO16:
     case BFD_RELOC_MIPS_TLS_GOTTPREL:
+    case BFD_RELOC_MIPS_TLS_TPREL32:
+    case BFD_RELOC_MIPS_TLS_TPREL64:
     case BFD_RELOC_MIPS_TLS_TPREL_HI16:
     case BFD_RELOC_MIPS_TLS_TPREL_LO16:
     case BFD_RELOC_MICROMIPS_TLS_GD:
@@ -15286,6 +15433,13 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
     case BFD_RELOC_MICROMIPS_TLS_GOTTPREL:
     case BFD_RELOC_MICROMIPS_TLS_TPREL_HI16:
     case BFD_RELOC_MICROMIPS_TLS_TPREL_LO16:
+    case BFD_RELOC_MIPS16_TLS_GD:
+    case BFD_RELOC_MIPS16_TLS_LDM:
+    case BFD_RELOC_MIPS16_TLS_DTPREL_HI16:
+    case BFD_RELOC_MIPS16_TLS_DTPREL_LO16:
+    case BFD_RELOC_MIPS16_TLS_GOTTPREL:
+    case BFD_RELOC_MIPS16_TLS_TPREL_HI16:
+    case BFD_RELOC_MIPS16_TLS_TPREL_LO16:
       S_SET_THREAD_LOCAL (fixP->fx_addsy);
       /* fall through */
 
@@ -15504,11 +15658,18 @@ get_symbol (void)
    fill byte should be used, FILL points to an integer that contains
    that byte, otherwise FILL is null.
 
-   The MIPS assembler also automatically adjusts any preceding
-   label.  */
+   This function used to have the comment:
+
+      The MIPS assembler also automatically adjusts any preceding label.
+
+   The implementation therefore applied the adjustment to a maximum of
+   one label.  However, other label adjustments are applied to batches
+   of labels, and adjusting just one caused problems when new labels
+   were added for the sake of debugging or unwind information.
+   We therefore adjust all preceding labels (given as LABELS) instead.  */
 
 static void
-mips_align (int to, int *fill, symbolS *label)
+mips_align (int to, int *fill, struct insn_label_list *labels)
 {
   mips_emit_delays ();
   mips_record_compressed_mode ();
@@ -15517,12 +15678,7 @@ mips_align (int to, int *fill, symbolS *label)
   else
     frag_align (to, fill ? *fill : 0, 0);
   record_alignment (now_seg, to);
-  if (label != NULL)
-    {
-      gas_assert (S_GET_SEGMENT (label) == now_seg);
-      symbol_set_frag (label, frag_now);
-      S_SET_VALUE (label, (valueT) frag_now_fix ());
-    }
+  mips_move_labels (labels, FALSE);
 }
 
 /* Align to a given power of two.  .align 0 turns off the automatic
@@ -15564,7 +15720,7 @@ s_align (int x ATTRIBUTE_UNUSED)
       struct insn_label_list *l = si->label_list;
       /* Auto alignment should be switched on by next section change.  */
       auto_align = 1;
-      mips_align (temp, fill_ptr, l != NULL ? l->label : NULL);
+      mips_align (temp, fill_ptr, l);
     }
   else
     {
@@ -15734,12 +15890,10 @@ s_cons (int log_size)
 {
   segment_info_type *si = seg_info (now_seg);
   struct insn_label_list *l = si->label_list;
-  symbolS *label;
 
-  label = l != NULL ? l->label : NULL;
   mips_emit_delays ();
   if (log_size > 0 && auto_align)
-    mips_align (log_size, 0, label);
+    mips_align (log_size, 0, l);
   cons (1 << log_size);
   mips_clear_insn_labels ();
 }
@@ -15749,18 +15903,15 @@ s_float_cons (int type)
 {
   segment_info_type *si = seg_info (now_seg);
   struct insn_label_list *l = si->label_list;
-  symbolS *label;
-
-  label = l != NULL ? l->label : NULL;
 
   mips_emit_delays ();
 
   if (auto_align)
     {
       if (type == 'd')
-       mips_align (3, 0, label);
+       mips_align (3, 0, l);
       else
-       mips_align (2, 0, label);
+       mips_align (2, 0, l);
     }
 
   float_cons (type);
@@ -15850,7 +16001,7 @@ s_option (int x ATTRIBUTE_UNUSED)
        mips_pic = NO_PIC;
       else if (i == 2)
        {
-       mips_pic = SVR4_PIC;
+         mips_pic = SVR4_PIC;
          mips_abicalls = TRUE;
        }
       else
@@ -16044,6 +16195,10 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
     }
   else if (strcmp (name, "nomt") == 0)
     mips_opts.ase_mt = 0;
+  else if (strcmp (name, "mcu") == 0)
+    mips_opts.ase_mcu = 1;
+  else if (strcmp (name, "nomcu") == 0)
+    mips_opts.ase_mcu = 0;
   else if (strncmp (name, "mips", 4) == 0 || strncmp (name, "arch=", 5) == 0)
     {
       int reset = 0;
@@ -16451,12 +16606,14 @@ s_cpreturn (int ignore ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 }
 
-/* Handle the .dtprelword and .dtpreldword pseudo-ops.  They generate
-   a 32-bit or 64-bit DTP-relative relocation (BYTES says which) for
-   use in DWARF debug information.  */
+/* Handle a .dtprelword, .dtpreldword, .tprelword, or .tpreldword
+   pseudo-op; DIRSTR says which. The pseudo-op generates a BYTES-size
+   DTP- or TP-relative relocation of type RTYPE, for use in either DWARF
+   debug information or MIPS16 TLS.  */
 
 static void
-s_dtprel_internal (size_t bytes)
+s_tls_rel_directive (const size_t bytes, const char *dirstr,
+                    bfd_reloc_code_real_type rtype)
 {
   expressionS ex;
   char *p;
@@ -16465,20 +16622,15 @@ s_dtprel_internal (size_t bytes)
 
   if (ex.X_op != O_symbol)
     {
-      as_bad (_("Unsupported use of %s"), (bytes == 8
-                                          ? ".dtpreldword"
-                                          : ".dtprelword"));
+      as_bad (_("Unsupported use of %s"), dirstr);
       ignore_rest_of_line ();
     }
 
   p = frag_more (bytes);
   md_number_to_chars (p, 0, bytes);
-  fix_new_exp (frag_now, p - frag_now->fr_literal, bytes, &ex, FALSE,
-              (bytes == 8
-               ? BFD_RELOC_MIPS_TLS_DTPREL64
-               : BFD_RELOC_MIPS_TLS_DTPREL32));
-
+  fix_new_exp (frag_now, p - frag_now->fr_literal, bytes, &ex, FALSE, rtype);
   demand_empty_rest_of_line ();
+  mips_clear_insn_labels ();
 }
 
 /* Handle .dtprelword.  */
@@ -16486,7 +16638,7 @@ s_dtprel_internal (size_t bytes)
 static void
 s_dtprelword (int ignore ATTRIBUTE_UNUSED)
 {
-  s_dtprel_internal (4);
+  s_tls_rel_directive (4, ".dtprelword", BFD_RELOC_MIPS_TLS_DTPREL32);
 }
 
 /* Handle .dtpreldword.  */
@@ -16494,7 +16646,23 @@ s_dtprelword (int ignore ATTRIBUTE_UNUSED)
 static void
 s_dtpreldword (int ignore ATTRIBUTE_UNUSED)
 {
-  s_dtprel_internal (8);
+  s_tls_rel_directive (8, ".dtpreldword", BFD_RELOC_MIPS_TLS_DTPREL64);
+}
+
+/* Handle .tprelword.  */
+
+static void
+s_tprelword (int ignore ATTRIBUTE_UNUSED)
+{
+  s_tls_rel_directive (4, ".tprelword", BFD_RELOC_MIPS_TLS_TPREL32);
+}
+
+/* Handle .tpreldword.  */
+
+static void
+s_tpreldword (int ignore ATTRIBUTE_UNUSED)
+{
+  s_tls_rel_directive (8, ".tpreldword", BFD_RELOC_MIPS_TLS_TPREL64);
 }
 
 /* Handle the .gpvalue pseudo-op.  This is used when generating NewABI PIC
@@ -16524,7 +16692,6 @@ s_gpword (int ignore ATTRIBUTE_UNUSED)
 {
   segment_info_type *si;
   struct insn_label_list *l;
-  symbolS *label;
   expressionS ex;
   char *p;
 
@@ -16537,10 +16704,9 @@ s_gpword (int ignore ATTRIBUTE_UNUSED)
 
   si = seg_info (now_seg);
   l = si->label_list;
-  label = l != NULL ? l->label : NULL;
   mips_emit_delays ();
   if (auto_align)
-    mips_align (2, 0, label);
+    mips_align (2, 0, l);
 
   expression (&ex);
   mips_clear_insn_labels ();
@@ -16564,7 +16730,6 @@ s_gpdword (int ignore ATTRIBUTE_UNUSED)
 {
   segment_info_type *si;
   struct insn_label_list *l;
-  symbolS *label;
   expressionS ex;
   char *p;
 
@@ -16577,10 +16742,9 @@ s_gpdword (int ignore ATTRIBUTE_UNUSED)
 
   si = seg_info (now_seg);
   l = si->label_list;
-  label = l != NULL ? l->label : NULL;
   mips_emit_delays ();
   if (auto_align)
-    mips_align (3, 0, label);
+    mips_align (3, 0, l);
 
   expression (&ex);
   mips_clear_insn_labels ();
@@ -17226,9 +17390,6 @@ relaxed_micromips_16bit_branch_length (fragS *fragp, asection *sec, int update)
 {
   bfd_boolean toofar;
 
-  if (RELAX_MICROMIPS_U16BIT (fragp->fr_subtype))
-    return 2;
-
   if (fragp
       && S_IS_DEFINED (fragp->fr_symbol)
       && sec == S_GET_SEGMENT (fragp->fr_symbol))
@@ -18134,7 +18295,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
                         | RELAX_DELAY_SLOT_SIZE_SECOND);
          msg = macro_warning (s);
          if (msg != NULL)
-           as_warn_where (fragp->fr_file, fragp->fr_line, msg);
+           as_warn_where (fragp->fr_file, fragp->fr_line, "%s", msg);
          subtype &= ~s;
        }
 
@@ -18148,7 +18309,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
               & (RELAX_SECOND_LONGER | RELAX_NOMACRO | RELAX_DELAY_SLOT));
          msg = macro_warning (s);
          if (msg != NULL)
-           as_warn_where (fragp->fr_file, fragp->fr_line, msg);
+           as_warn_where (fragp->fr_file, fragp->fr_line, "%s", msg);
          subtype &= ~s;
        }
 
@@ -18304,7 +18465,7 @@ mips_elf_final_processing (void)
     elf_elfheader (stdoutput)->e_flags |= EF_MIPS_NOREORDER;
   if (mips_pic != NO_PIC)
     {
-    elf_elfheader (stdoutput)->e_flags |= EF_MIPS_PIC;
+      elf_elfheader (stdoutput)->e_flags |= EF_MIPS_PIC;
       elf_elfheader (stdoutput)->e_flags |= EF_MIPS_CPIC;
     }
   if (mips_abicalls)
@@ -18868,6 +19029,12 @@ static const struct mips_cpu_info mips_cpu_info_table[] =
   { "4ksd",           MIPS_CPU_ASE_SMARTMIPS,  ISA_MIPS32R2,   CPU_MIPS32R2 },
   { "m4k",            0,                       ISA_MIPS32R2,   CPU_MIPS32R2 },
   { "m4kp",           0,                       ISA_MIPS32R2,   CPU_MIPS32R2 },
+  { "m14k",           MIPS_CPU_ASE_MCU,                ISA_MIPS32R2,   CPU_MIPS32R2 },
+  { "m14kc",          MIPS_CPU_ASE_MCU,                ISA_MIPS32R2,   CPU_MIPS32R2 },
+  { "m14ke",          MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_DSPR2 | MIPS_CPU_ASE_MCU,
+                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
+  { "m14kec",         MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_DSPR2 | MIPS_CPU_ASE_MCU,
+                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
   { "24kc",           0,                       ISA_MIPS32R2,   CPU_MIPS32R2 },
   { "24kf2_1",        0,                       ISA_MIPS32R2,   CPU_MIPS32R2 },
   { "24kf",           0,                       ISA_MIPS32R2,   CPU_MIPS32R2 },
@@ -18942,10 +19109,17 @@ static const struct mips_cpu_info mips_cpu_info_table[] =
 
   /* Cavium Networks Octeon CPU core */
   { "octeon",        0,      ISA_MIPS64R2,   CPU_OCTEON },
+  { "octeon+",       0,      ISA_MIPS64R2,   CPU_OCTEONP },
+  { "octeon2",       0,      ISA_MIPS64R2,   CPU_OCTEON2 },
 
   /* RMI Xlr */
   { "xlr",           0,      ISA_MIPS64,     CPU_XLR },
 
+  /* Broadcom XLP.
+     XLP is mostly like XLR, with the prominent exception that it is
+     MIPS64R2 rather than MIPS64.  */
+  { "xlp",           0,      ISA_MIPS64R2,     CPU_XLR },
+
   /* End marker */
   { NULL, 0, 0, 0 }
 };
@@ -19168,6 +19342,9 @@ MIPS options:\n\
 -mmt                   generate MT instructions\n\
 -mno-mt                        do not generate MT instructions\n"));
   fprintf (stream, _("\
+-mmcu                  generate MCU instructions\n\
+-mno-mcu               do not generate MCU instructions\n"));
+  fprintf (stream, _("\
 -mfix-loongson2f-jump  work around Loongson2F JUMP instructions\n\
 -mfix-loongson2f-nop   work around Loongson2F NOP errata\n\
 -mfix-vr4120           work around certain VR4120 errata\n\