gas/
[deliverable/binutils-gdb.git] / gas / config / tc-mips.c
index 35bea8b9fc64fbfeb14d945e603cd97cf8be20ca..5ba0faf4b7b0e911027681835dbe46b107a77795 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, 2011, 2012
+   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
    Free Software Foundation, Inc.
    Contributed by the OSF and Ralph Campbell.
    Written by Keith Knowles and Ralph Campbell, working independently.
@@ -171,6 +171,10 @@ struct mips_cl_insn
 
   /* True if this instruction is complete.  */
   unsigned int complete_p : 1;
+
+  /* True if this instruction is cleared from history by unconditional
+     branch.  */
+  unsigned int cleared_p : 1;
 };
 
 /* The ABI to use.  */
@@ -212,8 +216,10 @@ struct mips_set_options
   int ase_smartmips;
   int ase_dsp;
   int ase_dspr2;
+  int ase_eva;
   int ase_mt;
   int ase_mcu;
+  int ase_virt;
   /* 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
@@ -287,11 +293,13 @@ static int file_mips_single_float = 0;
 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,
-  /* 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
+  /* ase_smartmips */ 0, /* ase_dsp */ -1, /* ase_dspr2 */ -1,
+  /* ase_eva */ -1, /* ase_mt */ -1, /* ase_mcu */ -1,
+  /* ase_virt */ -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
 };
 
 /* These variables are filled in with the masks of registers used.
@@ -359,6 +367,14 @@ static int file_ase_dspr2;
                                || mips_opts.isa == ISA_MIPS64R2        \
                                || mips_opts.micromips)
 
+/* True if -meva was passed or implied by arguments passed on the
+   command line (e.g., by -march).  */
+static int file_ase_eva;
+
+#define ISA_SUPPORTS_EVA_ASE (mips_opts.isa == ISA_MIPS32R2            \
+                             || mips_opts.isa == ISA_MIPS64R2          \
+                             || mips_opts.micromips)
+
 /* True if -mmt was passed or implied by arguments passed on the
    command line (e.g., by -march).  */
 static int file_ase_mt;
@@ -370,6 +386,18 @@ static int file_ase_mt;
                              || mips_opts.isa == ISA_MIPS64R2          \
                              || mips_opts.micromips)
 
+/* True if -mvirt was passed or implied by arguments passed on the
+   command line (e.g., by -march). */
+static int file_ase_virt;
+
+#define ISA_SUPPORTS_VIRT_ASE (mips_opts.isa == ISA_MIPS32R2           \
+                              || mips_opts.isa == ISA_MIPS64R2         \
+                              || mips_opts.micromips)
+
+#define ISA_SUPPORTS_VIRT64_ASE (mips_opts.isa == ISA_MIPS64R2         \
+                                || (mips_opts.micromips                \
+                                    && ISA_HAS_64BIT_REGS (mips_opts.isa)))
+
 /* The argument of the -march= flag.  The architecture we are assembling.  */
 static int file_mips_arch = CPU_UNKNOWN;
 static const char *mips_arch_string;
@@ -500,6 +528,10 @@ static int mips_32bitmode = 0;
 /* True if CPU has seq/sne and seqi/snei instructions.  */
 #define CPU_HAS_SEQ(CPU)       (CPU_IS_OCTEON (CPU))
 
+/* True, if CPU has support for ldc1 and sdc1. */
+#define CPU_HAS_LDC1_SDC1(CPU) \
+   ((mips_opts.isa != ISA_MIPS1) && ((CPU) != CPU_R5900))
+
 /* True if mflo and mfhi can be immediately followed by instructions
    which write to the HI and LO registers.
 
@@ -518,6 +550,7 @@ static int mips_32bitmode = 0;
    || mips_opts.isa == ISA_MIPS64                     \
    || mips_opts.isa == ISA_MIPS64R2                   \
    || mips_opts.arch == CPU_R4010                     \
+   || mips_opts.arch == CPU_R5900                     \
    || mips_opts.arch == CPU_R10000                    \
    || mips_opts.arch == CPU_R12000                    \
    || mips_opts.arch == CPU_R14000                    \
@@ -535,6 +568,7 @@ static int mips_32bitmode = 0;
 #define gpr_interlocks                                \
   (mips_opts.isa != ISA_MIPS1                         \
    || mips_opts.arch == CPU_R3900                     \
+   || mips_opts.arch == CPU_R5900                     \
    || mips_opts.micromips                             \
    )
 
@@ -1193,6 +1227,10 @@ static int mips_relax_branch;
 #define IS_SEXT_12BIT_NUM(x)                                           \
   (((((x) & 0xfff) ^ 0x800LL) - 0x800LL) == (x))
 
+/* Is the given value a sign-extended 9-bit value?  */
+#define IS_SEXT_9BIT_NUM(x)                                            \
+  (((((x) & 0x1ff) ^ 0x100LL) - 0x100LL) == (x))
+
 /* Is the given value a zero-extended 32-bit value?  Or a negated one?  */
 #define IS_ZEXT_32BIT_NUM(x)                                           \
   (((x) &~ (offsetT) 0xffffffff) == 0                                  \
@@ -1304,9 +1342,6 @@ static struct {
 \f
 /* Prototypes for static functions.  */
 
-#define internalError()                                                        \
-    as_fatal (_("internal Error, line %d, %s"), __LINE__, __FILE__)
-
 enum mips_regclass { MIPS_GR_REG, MIPS_FP_REG, MIPS16_REG };
 
 static void append_insn
@@ -1350,6 +1385,7 @@ static void s_tpreldword (int);
 static void s_gpvalue (int);
 static void s_gpword (int);
 static void s_gpdword (int);
+static void s_ehword (int);
 static void s_cpadd (int);
 static void s_insn (int);
 static void md_obj_begin (void);
@@ -1375,19 +1411,13 @@ static int relaxed_micromips_32bit_branch_length (fragS *, asection *, int);
 struct mips_cpu_info
 {
   const char *name;           /* CPU or ISA name.  */
-  int flags;                  /* ASEs available, or ISA flag.  */
+  int flags;                  /* MIPS_CPU_* flags.  */
+  int ase;                    /* Set of ASEs implemented by the CPU.  */
   int isa;                    /* ISA level.  */
   int cpu;                    /* CPU number (default CPU if ISA).  */
 };
 
 #define MIPS_CPU_IS_ISA                0x0001  /* Is this an ISA?  (If 0, a CPU.) */
-#define MIPS_CPU_ASE_SMARTMIPS 0x0002  /* CPU implements SmartMIPS ASE */
-#define MIPS_CPU_ASE_DSP       0x0004  /* CPU implements DSP ASE */
-#define MIPS_CPU_ASE_MT                0x0008  /* CPU implements MT ASE */
-#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);
@@ -1431,6 +1461,7 @@ static const pseudo_typeS mips_pseudo_table[] =
   {"gpvalue", s_gpvalue, 0},
   {"gpword", s_gpword, 0},
   {"gpdword", s_gpdword, 0},
+  {"ehword", s_ehword, 0},
   {"cpadd", s_cpadd, 0},
   {"insn", s_insn, 0},
 
@@ -1465,7 +1496,9 @@ static const pseudo_typeS mips_pseudo_table[] =
   {"section", s_change_section, 0},
   {"short", s_cons, 1},
   {"single", s_float_cons, 'f'},
+  {"stabd", s_mips_stab, 'd'},
   {"stabn", s_mips_stab, 'n'},
+  {"stabs", s_mips_stab, 's'},
   {"text", s_change_sec, 't'},
   {"word", s_cons, 2},
 
@@ -1574,6 +1607,11 @@ static bfd_reloc_code_real_type offset_reloc[3]
 
 static unsigned int forced_insn_length;
 
+/* True if we are assembling an instruction.  All dot symbols defined during
+   this time should be treated as code labels.  */
+
+static bfd_boolean mips_assembling_insn;
+
 #ifdef OBJ_ELF
 /* The pdr segment for per procedure frame/regmask info.  Not used for
    ECOFF debugging.  */
@@ -1674,6 +1712,7 @@ create_insn (struct mips_cl_insn *insn, const struct mips_opcode *mo)
   insn->noreorder_p = (mips_opts.noreorder > 0);
   insn->mips16_absolute_jump_p = 0;
   insn->complete_p = 0;
+  insn->cleared_p = 0;
 }
 
 /* Record the current MIPS16/microMIPS mode in now_seg.  */
@@ -2218,33 +2257,40 @@ reglist_lookup (char **s, unsigned int types, unsigned int *reglistp)
   return ok && reglist != 0;
 }
 
-/* Return TRUE if opcode MO is valid on the currently selected ISA and
-   architecture.  Use is_opcode_valid_16 for MIPS16 opcodes.  */
+/* Return TRUE if opcode MO is valid on the currently selected ISA, ASE
+   and architecture.  Use is_opcode_valid_16 for MIPS16 opcodes.  */
 
 static bfd_boolean
 is_opcode_valid (const struct mips_opcode *mo)
 {
   int isa = mips_opts.isa;
+  int ase = 0;
   int fp_s, fp_d;
 
   if (mips_opts.ase_mdmx)
-    isa |= INSN_MDMX;
+    ase |= ASE_MDMX;
   if (mips_opts.ase_dsp)
-    isa |= INSN_DSP;
+    ase |= ASE_DSP;
   if (mips_opts.ase_dsp && ISA_SUPPORTS_DSP64_ASE)
-    isa |= INSN_DSP64;
+    ase |= ASE_DSP64;
   if (mips_opts.ase_dspr2)
-    isa |= INSN_DSPR2;
+    ase |= ASE_DSPR2;
+  if (mips_opts.ase_eva)
+    ase |= ASE_EVA;
   if (mips_opts.ase_mt)
-    isa |= INSN_MT;
+    ase |= ASE_MT;
   if (mips_opts.ase_mips3d)
-    isa |= INSN_MIPS3D;
+    ase |= ASE_MIPS3D;
   if (mips_opts.ase_smartmips)
-    isa |= INSN_SMARTMIPS;
+    ase |= ASE_SMARTMIPS;
   if (mips_opts.ase_mcu)
-    isa |= INSN_MCU;
+    ase |= ASE_MCU;
+  if (mips_opts.ase_virt)
+    ase |= ASE_VIRT;
+  if (mips_opts.ase_virt && ISA_SUPPORTS_VIRT64_ASE)
+    ase |= ASE_VIRT64;
 
-  if (!opcode_is_member (mo, isa, mips_opts.arch))
+  if (!opcode_is_member (mo, isa, ase, mips_opts.arch))
     return FALSE;
 
   /* Check whether the instruction or macro requires single-precision or
@@ -2276,7 +2322,7 @@ is_opcode_valid (const struct mips_opcode *mo)
 static bfd_boolean
 is_opcode_valid_16 (const struct mips_opcode *mo)
 {
-  return opcode_is_member (mo, mips_opts.isa, mips_opts.arch);
+  return opcode_is_member (mo, mips_opts.isa, 0, mips_opts.arch);
 }
 
 /* Return TRUE if the size of the microMIPS opcode MO matches one
@@ -2296,7 +2342,18 @@ is_size_valid (const struct mips_opcode *mo)
 }
 
 /* Return TRUE if the microMIPS opcode MO is valid for the delay slot
-   of the preceding instruction.  Always TRUE in the standard MIPS mode.  */
+   of the preceding instruction.  Always TRUE in the standard MIPS mode.
+
+   We don't accept macros in 16-bit delay slots to avoid a case where
+   a macro expansion fails because it relies on a preceding 32-bit real
+   instruction to have matched and does not handle the operands correctly.
+   The only macros that may expand to 16-bit instructions are JAL that
+   cannot be placed in a delay slot anyway, and corner cases of BALIGN
+   and BGT (that likewise cannot be placed in a delay slot) that decay to
+   a NOP.  In all these cases the macros precede any corresponding real
+   instruction definitions in the opcode table, so they will match in the
+   second pass where the size of the delay slot is ignored and therefore
+   produce correct code.  */
 
 static bfd_boolean
 is_delay_slot_valid (const struct mips_opcode *mo)
@@ -2305,7 +2362,7 @@ is_delay_slot_valid (const struct mips_opcode *mo)
     return TRUE;
 
   if (mo->pinfo == INSN_MACRO)
-    return TRUE;
+    return (history[0].insn_mo->pinfo2 & INSN2_BRANCH_DELAY_16BIT) == 0;
   if ((history[0].insn_mo->pinfo2 & INSN2_BRANCH_DELAY_32BIT) != 0
       && micromips_insn_length (mo) != 4)
     return FALSE;
@@ -2592,6 +2649,9 @@ md_assemble (char *str)
   offset_reloc[1] = BFD_RELOC_UNUSED;
   offset_reloc[2] = BFD_RELOC_UNUSED;
 
+  mips_mark_labels ();
+  mips_assembling_insn = TRUE;
+
   if (mips_opts.mips16)
     mips16_ip (str, &insn);
   else
@@ -2602,12 +2662,8 @@ md_assemble (char *str)
     }
 
   if (insn_error)
-    {
-      as_bad ("%s `%s'", insn_error, str);
-      return;
-    }
-
-  if (insn.insn_mo->pinfo == INSN_MACRO)
+    as_bad ("%s `%s'", insn_error, str);
+  else if (insn.insn_mo->pinfo == INSN_MACRO)
     {
       macro_start ();
       if (mips_opts.mips16)
@@ -2625,6 +2681,8 @@ md_assemble (char *str)
       else
        append_insn (&insn, NULL, unused_reloc, FALSE);
     }
+
+  mips_assembling_insn = FALSE;
 }
 
 /* Convenience functions for abstracting away the differences between
@@ -2717,6 +2775,28 @@ jalr_reloc_p (bfd_reloc_code_real_type reloc)
   return reloc == BFD_RELOC_MIPS_JALR || reloc == BFD_RELOC_MICROMIPS_JALR;
 }
 
+/* Return true if RELOC is a PC-relative relocation that does not have
+   full address range.  */
+
+static inline bfd_boolean
+limited_pcrel_reloc_p (bfd_reloc_code_real_type reloc)
+{
+  switch (reloc)
+    {
+    case BFD_RELOC_16_PCREL_S2:
+    case BFD_RELOC_MICROMIPS_7_PCREL_S1:
+    case BFD_RELOC_MICROMIPS_10_PCREL_S1:
+    case BFD_RELOC_MICROMIPS_16_PCREL_S1:
+      return TRUE;
+
+    case BFD_RELOC_32_PCREL:
+      return HAVE_64BIT_ADDRESSES;
+
+    default:
+      return FALSE;
+    }
+}
+
 /* Return true if the given relocation might need a matching %lo().
    This is only "might" because SVR4 R_MIPS_GOT16 relocations only
    need a matching %lo() when applied to local symbols.  */
@@ -2832,7 +2912,7 @@ s_is_linkonce (symbolS *sym, segT from_seg)
   return linkonce;
 }
 
-/* Mark instruction labels in MIPS16/microMIPS mode.  This permits the
+/* Mark MIPS16 or microMIPS instruction label LABEL.  This permits the
    linker to handle them specially, such as generating jalx instructions
    when needed.  We also make them odd for the duration of the assembly,
    in order to generate the right sort of code.  We will make them even
@@ -2841,36 +2921,39 @@ s_is_linkonce (symbolS *sym, segT from_seg)
    to make them odd again.  */
 
 static void
-mips_compressed_mark_labels (void)
+mips_compressed_mark_label (symbolS *label)
 {
-  segment_info_type *si = seg_info (now_seg);
-  struct insn_label_list *l;
-
   gas_assert (HAVE_CODE_COMPRESSION);
 
-  for (l = si->label_list; l != NULL; l = l->next)
-   {
-      symbolS *label = l->label;
-
 #if defined(OBJ_ELF) || defined(OBJ_MAYBE_ELF)
-      if (IS_ELF)
-       {
-         if (mips_opts.mips16)
-           S_SET_OTHER (label, ELF_ST_SET_MIPS16 (S_GET_OTHER (label)));
-         else
-           S_SET_OTHER (label, ELF_ST_SET_MICROMIPS (S_GET_OTHER (label)));
-       }
-#endif
-      if ((S_GET_VALUE (label) & 1) == 0
-       /* Don't adjust the address if the label is global or weak, or
-          in a link-once section, since we'll be emitting symbol reloc
-          references to it which will be patched up by the linker, and
-          the final value of the symbol may or may not be MIPS16/microMIPS.  */
-         && ! S_IS_WEAK (label)
-         && ! S_IS_EXTERNAL (label)
-         && ! s_is_linkonce (label, now_seg))
-       S_SET_VALUE (label, S_GET_VALUE (label) | 1);
+  if (IS_ELF)
+    {
+      if (mips_opts.mips16)
+       S_SET_OTHER (label, ELF_ST_SET_MIPS16 (S_GET_OTHER (label)));
+      else
+       S_SET_OTHER (label, ELF_ST_SET_MICROMIPS (S_GET_OTHER (label)));
     }
+#endif
+  if ((S_GET_VALUE (label) & 1) == 0
+      /* Don't adjust the address if the label is global or weak, or
+        in a link-once section, since we'll be emitting symbol reloc
+        references to it which will be patched up by the linker, and
+        the final value of the symbol may or may not be MIPS16/microMIPS.  */
+      && !S_IS_WEAK (label)
+      && !S_IS_EXTERNAL (label)
+      && !s_is_linkonce (label, now_seg))
+    S_SET_VALUE (label, S_GET_VALUE (label) | 1);
+}
+
+/* Mark preceding MIPS16 or microMIPS instruction labels.  */
+
+static void
+mips_compressed_mark_labels (void)
+{
+  struct insn_label_list *l;
+
+  for (l = seg_info (now_seg)->label_list; l != NULL; l = l->next)
+    mips_compressed_mark_label (l->label);
 }
 
 /* End the current frag.  Make it a variant frag and record the
@@ -3715,10 +3798,13 @@ fix_loongson2f (struct mips_cl_insn * ip)
 
 /* IP is a branch that has a delay slot, and we need to fill it
    automatically.   Return true if we can do that by swapping IP
-   with the previous instruction.  */
+   with the previous instruction.
+   ADDRESS_EXPR is an operand of the instruction to be used with
+   RELOC_TYPE.  */
 
 static bfd_boolean
-can_swap_branch_p (struct mips_cl_insn *ip)
+can_swap_branch_p (struct mips_cl_insn *ip, expressionS *address_expr,
+  bfd_reloc_code_real_type *reloc_type)
 {
   unsigned long pinfo, pinfo2, prev_pinfo, prev_pinfo2;
   unsigned int gpr_read, gpr_write, prev_gpr_read, prev_gpr_write;
@@ -3837,13 +3923,64 @@ can_swap_branch_p (struct mips_cl_insn *ip)
       && insn_length (history) != 4)
     return FALSE;
 
+  /* On R5900 short loops need to be fixed by inserting a nop in
+     the branch delay slots.
+     A short loop can be terminated too early.  */
+  if (mips_opts.arch == CPU_R5900
+      /* Check if instruction has a parameter, ignore "j $31". */
+      && (address_expr != NULL)
+      /* Parameter must be 16 bit. */
+      && (*reloc_type == BFD_RELOC_16_PCREL_S2)
+      /* Branch to same segment. */
+      && (S_GET_SEGMENT(address_expr->X_add_symbol) == now_seg)
+      /* Branch to same code fragment. */
+      && (symbol_get_frag(address_expr->X_add_symbol) == frag_now)
+      /* Can only calculate branch offset if value is known. */
+      && symbol_constant_p(address_expr->X_add_symbol)
+      /* Check if branch is really conditional. */
+      && !((ip->insn_opcode & 0xffff0000) == 0x10000000   /* beq $0,$0 */
+       || (ip->insn_opcode & 0xffff0000) == 0x04010000   /* bgez $0 */
+       || (ip->insn_opcode & 0xffff0000) == 0x04110000)) /* bgezal $0 */
+    {
+      int distance;
+      /* Check if loop is shorter than 6 instructions including
+         branch and delay slot.  */
+      distance = frag_now_fix() - S_GET_VALUE(address_expr->X_add_symbol);
+      if (distance <= 20)
+        {
+          int i;
+          int rv;
+
+          rv = FALSE;
+          /* When the loop includes branches or jumps,
+             it is not a short loop. */
+          for (i = 0; i < (distance / 4); i++)
+            {
+              if ((history[i].cleared_p)
+                  || delayed_branch_p(&history[i]))
+                {
+                  rv = TRUE;
+                  break;
+                }
+            }
+          if (rv == FALSE)
+            {
+              /* Insert nop after branch to fix short loop. */
+              return FALSE;
+            }
+        }
+    }
+
   return TRUE;
 }
 
-/* Decide how we should add IP to the instruction stream.  */
+/* Decide how we should add IP to the instruction stream.
+   ADDRESS_EXPR is an operand of the instruction to be used with
+   RELOC_TYPE.  */
 
 static enum append_method
-get_append_method (struct mips_cl_insn *ip)
+get_append_method (struct mips_cl_insn *ip, expressionS *address_expr,
+  bfd_reloc_code_real_type *reloc_type)
 {
   unsigned long pinfo;
 
@@ -3859,7 +3996,8 @@ get_append_method (struct mips_cl_insn *ip)
   /* Otherwise, it's our responsibility to fill branch delay slots.  */
   if (delayed_branch_p (ip))
     {
-      if (!branch_likely_p (ip) && can_swap_branch_p (ip))
+      if (!branch_likely_p (ip)
+         && can_swap_branch_p (ip, address_expr, reloc_type))
        return APPEND_SWAP;
 
       pinfo = ip->insn_mo->pinfo;
@@ -4013,6 +4151,52 @@ micromips_map_reloc (bfd_reloc_code_real_type reloc)
   return reloc;
 }
 
+/* Try to resolve relocation RELOC against constant OPERAND at assembly time.
+   Return true on success, storing the resolved value in RESULT.  */
+
+static bfd_boolean
+calculate_reloc (bfd_reloc_code_real_type reloc, offsetT operand,
+                offsetT *result)
+{
+  switch (reloc)
+    {
+    case BFD_RELOC_MIPS_HIGHEST:
+    case BFD_RELOC_MICROMIPS_HIGHEST:
+      *result = ((operand + 0x800080008000ull) >> 48) & 0xffff;
+      return TRUE;
+
+    case BFD_RELOC_MIPS_HIGHER:
+    case BFD_RELOC_MICROMIPS_HIGHER:
+      *result = ((operand + 0x80008000ull) >> 32) & 0xffff;
+      return TRUE;
+
+    case BFD_RELOC_HI16_S:
+    case BFD_RELOC_MICROMIPS_HI16_S:
+    case BFD_RELOC_MIPS16_HI16_S:
+      *result = ((operand + 0x8000) >> 16) & 0xffff;
+      return TRUE;
+
+    case BFD_RELOC_HI16:
+    case BFD_RELOC_MICROMIPS_HI16:
+    case BFD_RELOC_MIPS16_HI16:
+      *result = (operand >> 16) & 0xffff;
+      return TRUE;
+
+    case BFD_RELOC_LO16:
+    case BFD_RELOC_MICROMIPS_LO16:
+    case BFD_RELOC_MIPS16_LO16:
+      *result = operand & 0xffff;
+      return TRUE;
+
+    case BFD_RELOC_UNUSED:
+      *result = operand;
+      return TRUE;
+
+    default:
+      return FALSE;
+    }
+}
+
 /* Output an instruction.  IP is the instruction information.
    ADDRESS_EXPR is an operand of the instruction to be used with
    RELOC_TYPE.  EXPANSIONP is true if the instruction is part of
@@ -4031,8 +4215,6 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
   if (mips_fix_loongson2f && !HAVE_CODE_COMPRESSION)
     fix_loongson2f (ip);
 
-  mips_mark_labels ();
-
   file_ase_mips16 |= mips_opts.mips16;
   file_ase_micromips |= mips_opts.micromips;
 
@@ -4050,43 +4232,13 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
 
   if (address_expr == NULL)
     ip->complete_p = 1;
-  else if (*reloc_type <= BFD_RELOC_UNUSED
+  else if (reloc_type[0] <= BFD_RELOC_UNUSED
+          && reloc_type[1] == BFD_RELOC_UNUSED
+          && reloc_type[2] == BFD_RELOC_UNUSED
           && address_expr->X_op == O_constant)
     {
-      unsigned int tmp;
-
-      ip->complete_p = 1;
       switch (*reloc_type)
        {
-       case BFD_RELOC_32:
-         ip->insn_opcode |= address_expr->X_add_number;
-         break;
-
-       case BFD_RELOC_MIPS_HIGHEST:
-         tmp = (address_expr->X_add_number + 0x800080008000ull) >> 48;
-         ip->insn_opcode |= tmp & 0xffff;
-         break;
-
-       case BFD_RELOC_MIPS_HIGHER:
-         tmp = (address_expr->X_add_number + 0x80008000ull) >> 32;
-         ip->insn_opcode |= tmp & 0xffff;
-         break;
-
-       case BFD_RELOC_HI16_S:
-         tmp = (address_expr->X_add_number + 0x8000) >> 16;
-         ip->insn_opcode |= tmp & 0xffff;
-         break;
-
-       case BFD_RELOC_HI16:
-         ip->insn_opcode |= (address_expr->X_add_number >> 16) & 0xffff;
-         break;
-
-       case BFD_RELOC_UNUSED:
-       case BFD_RELOC_LO16:
-       case BFD_RELOC_MIPS_GOT_DISP:
-         ip->insn_opcode |= address_expr->X_add_number & 0xffff;
-         break;
-
        case BFD_RELOC_MIPS_JMP:
          {
            int shift;
@@ -4097,7 +4249,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
                      (unsigned long) address_expr->X_add_number);
            ip->insn_opcode |= ((address_expr->X_add_number >> shift)
                                & 0x3ffffff);
-           ip->complete_p = 0;
+           ip->complete_p = 1;
          }
          break;
 
@@ -4109,7 +4261,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
            (((address_expr->X_add_number & 0x7c0000) << 3)
               | ((address_expr->X_add_number & 0xf800000) >> 7)
               | ((address_expr->X_add_number & 0x3fffc) >> 2));
-         ip->complete_p = 0;
+         ip->complete_p = 1;
          break;
 
        case BFD_RELOC_16_PCREL_S2:
@@ -4129,13 +4281,22 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
                ip->insn_opcode |= ((address_expr->X_add_number >> shift)
                                    & 0xffff);
              }
-           ip->complete_p = 0;
          }
          break;
 
        default:
-         internalError ();
-       }       
+         {
+           offsetT value;
+
+           if (calculate_reloc (*reloc_type, address_expr->X_add_number,
+                                &value))
+             {
+               ip->insn_opcode |= value & 0xffff;
+               ip->complete_p = 1;
+             }
+         }
+         break;
+       }
     }
 
   if (mips_relax.sequence != 2 && !mips_opts.noreorder)
@@ -4217,26 +4378,23 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
        }
     }
 
-  method = get_append_method (ip);
+  method = get_append_method (ip, address_expr, reloc_type);
   branch_disp = method == APPEND_SWAP ? insn_length (history) : 0;
 
 #ifdef OBJ_ELF
-  /* The value passed to dwarf2_emit_insn is the distance between
-     the beginning of the current instruction and the address that
-     should be recorded in the debug tables.  This is normally the
-     current address.
-
-     For MIPS16/microMIPS debug info we want to use ISA-encoded
-     addresses, so we use -1 for an address higher by one than the
-     current one.
-
-     If the instruction produced is a branch that we will swap with
-     the preceding instruction, then we add the displacement by which
-     the branch will be moved backwards.  This is more appropriate
-     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) + branch_disp);
+  dwarf2_emit_insn (0);
+  /* We want MIPS16 and microMIPS debug info to use ISA-encoded addresses,
+     so "move" the instruction address accordingly.
+
+     Also, it doesn't seem appropriate for the assembler to reorder .loc
+     entries.  If this instruction is a branch that we are going to swap
+     with the previous instruction, the two instructions should be
+     treated as a unit, and the debug information for both instructions
+     should refer to the start of the branch sequence.  Using the
+     current position is certainly wrong when swapping a 32-bit branch
+     and a 16-bit delay slot, since the current position would then be
+     in the middle of a branch.  */
+  dwarf2_move_insn ((HAVE_CODE_COMPRESSION ? 1 : 0) - branch_disp);
 #endif
 
   relax32 = (mips_relax_branch
@@ -4245,9 +4403,9 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
                out that the branch was out-of-range, we'll get an error.  */
             && !mips_opts.warn_about_macros
             && (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 relax BPOSGE32/64 or BC1ANY2T/F and BC1ANY4T/F
+               as they have no complementing branches.  */
+            && !(ip->insn_mo->ase & (ASE_MIPS3D | ASE_DSP64 | ASE_DSP)));
 
   if (!HAVE_CODE_COMPRESSION
       && address_expr
@@ -4420,6 +4578,11 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
              || lo16_reloc_p (reloc_type[0])))
        ip->fixp[0]->fx_no_overflow = 1;
 
+      /* These relocations can have an addend that won't fit in 2 octets.  */
+      if (reloc_type[0] == BFD_RELOC_MICROMIPS_7_PCREL_S1
+         || reloc_type[0] == BFD_RELOC_MICROMIPS_10_PCREL_S1)
+       ip->fixp[0]->fx_no_overflow = 1;
+
       if (mips_relax.sequence)
        {
          if (mips_relax.first_fixup == 0)
@@ -4530,7 +4693,14 @@ 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]))
       || (compact_branch_p (&history[0]) && uncond_branch_p (&history[0])))
-    mips_no_prev_insn ();
+    {
+      unsigned int i;
+
+      mips_no_prev_insn ();
+
+      for (i = 0; i < ARRAY_SIZE (history); i++)
+       history[i].cleared_p = 1;
+    }
 
   /* We need to emit a label at the end of branch-likely macros.  */
   if (emit_branch_likely_macro)
@@ -4543,7 +4713,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
   mips_clear_insn_labels ();
 }
 
-/* Forget that there was any previous instruction or label.  */
+/* Forget that there was any previous instruction or label.
+   When BRANCH is true, the branch history is also flushed.  */
 
 static void
 mips_no_prev_insn (void)
@@ -4893,6 +5064,11 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
                              INSMSB, insn, va_arg (args, int));
              continue;
 
+           case 'J':
+             gas_assert (!mips_opts.micromips);
+             INSERT_OPERAND (0, CODE10, insn, va_arg (args, int));
+             continue;
+
            case 'C':
            case 'G':
            case 'H':
@@ -4909,8 +5085,12 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
              INSERT_OPERAND (0, SEQI, insn, va_arg (args, int));
              continue;
 
+           case 'j':
+             INSERT_OPERAND (mips_opts.micromips, EVAOFFSET, insn, va_arg (args, int));
+             continue;
+
            default:
-             internalError ();
+             abort ();
            }
          continue;
 
@@ -5114,12 +5294,12 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
              break;
 
            default:
-             internalError ();
+             abort ();
            }
          continue;
 
        default:
-         internalError ();
+         abort ();
        }
       break;
     }
@@ -5220,14 +5400,15 @@ mips16_macro_build (expressionS *ep, const char *name, const char *fmt,
        case 'p':
        case 'q':
          {
+           offsetT value;
+
            gas_assert (ep != NULL);
 
            if (ep->X_op != O_constant)
              *r = (int) BFD_RELOC_UNUSED + c;
-           else
+           else if (calculate_reloc (*r, ep->X_add_number, &value))
              {
-               mips16_immed (NULL, 0, c, *r, ep->X_add_number,
-                             0, &insn.insn_opcode);
+               mips16_immed (NULL, 0, c, *r, value, 0, &insn.insn_opcode);
                ep = NULL;
                *r = BFD_RELOC_UNUSED;
              }
@@ -5295,7 +5476,8 @@ macro_build_jalr (expressionS *ep, int cprestore)
   if (mips_opts.micromips)
     {
       jalr = mips_opts.noreorder && !cprestore ? "jalr" : "jalrs";
-      if (MIPS_JALR_HINT_P (ep))
+      if (MIPS_JALR_HINT_P (ep)
+         || (history[0].insn_mo->pinfo2 & INSN2_BRANCH_DELAY_32BIT))
        macro_build (NULL, jalr, "t,s", RA, PIC_CALL_REG);
       else
        macro_build (NULL, jalr, "mj", PIC_CALL_REG);
@@ -6284,7 +6466,7 @@ macro (struct mips_cl_insn *ip)
   const char *fmt;
   int likely = 0;
   int coproc = 0;
-  int off12 = 0;
+  int offbits = 16;
   int call = 0;
   int jals = 0;
   int dbl = 0;
@@ -6292,7 +6474,6 @@ 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;
@@ -7735,7 +7916,9 @@ macro (struct mips_cl_insn *ip)
       if (mips_pic == NO_PIC)
        {
          s = jals ? "jalrs" : "jalr";
-         if (mips_opts.micromips && dreg == RA)
+         if (mips_opts.micromips
+             && dreg == RA
+             && !(history[0].insn_mo->pinfo2 & INSN2_BRANCH_DELAY_32BIT))
            macro_build (NULL, s, "mj", sreg);
          else
            macro_build (NULL, s, JALR_FMT, dreg, sreg);
@@ -7750,7 +7933,9 @@ macro (struct mips_cl_insn *ip)
 
          s = (mips_opts.micromips && (!mips_opts.noreorder || cprestore)
               ? "jalrs" : "jalr");
-         if (mips_opts.micromips && dreg == RA)
+         if (mips_opts.micromips
+             && dreg == RA
+             && !(history[0].insn_mo->pinfo2 & INSN2_BRANCH_DELAY_32BIT))
            macro_build (NULL, s, "mj", sreg);
          else
            macro_build (NULL, s, JALR_FMT, dreg, sreg);
@@ -7928,13 +8113,111 @@ macro (struct mips_cl_insn *ip)
 
       break;
 
+    case M_LBUE_AB:
+      ab = 1;
+    case M_LBUE_OB:
+      s = "lbue";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_LHUE_AB:
+      ab = 1;
+    case M_LHUE_OB:
+      s = "lhue";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_LBE_AB:
+      ab = 1;
+    case M_LBE_OB:
+      s = "lbe";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_LHE_AB:
+      ab = 1;
+    case M_LHE_OB:
+      s = "lhe";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_LLE_AB:
+      ab = 1;
+    case M_LLE_OB:
+      s = "lle";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_LWE_AB:
+      ab = 1;
+    case M_LWE_OB:
+      s = "lwe";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_LWLE_AB:
+      ab = 1;
+    case M_LWLE_OB:
+      s = "lwle";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_LWRE_AB:
+      ab = 1;
+    case M_LWRE_OB:
+      s = "lwre";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_SBE_AB:
+      ab = 1;
+    case M_SBE_OB:
+      s = "sbe";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_SCE_AB:
+      ab = 1;
+    case M_SCE_OB:
+      s = "sce";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_SHE_AB:
+      ab = 1;
+    case M_SHE_OB:
+      s = "she";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_SWE_AB:
+      ab = 1;
+    case M_SWE_OB:
+      s = "swe";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_SWLE_AB:
+      ab = 1;
+    case M_SWLE_OB:
+      s = "swle";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
+    case M_SWRE_AB:
+      ab = 1;
+    case M_SWRE_OB:
+      s = "swre";
+      fmt = "t,+j(b)";
+      offbits = 9;
+      goto ld_st;
     case M_ACLR_AB:
       ab = 1;
     case M_ACLR_OB:
       s = "aclr";
       treg = EXTRACT_OPERAND (mips_opts.micromips, 3BITPOS, *ip);
       fmt = "\\,~(b)";
-      off12 = 1;
+      offbits = 12;
       goto ld_st;
     case M_ASET_AB:
       ab = 1;
@@ -7942,7 +8225,7 @@ macro (struct mips_cl_insn *ip)
       s = "aset";
       treg = EXTRACT_OPERAND (mips_opts.micromips, 3BITPOS, *ip);
       fmt = "\\,~(b)";
-      off12 = 1;
+      offbits = 12;
       goto ld_st;
     case M_LB_AB:
       ab = 1;
@@ -7989,7 +8272,7 @@ macro (struct mips_cl_insn *ip)
     case M_LWC2_OB:
       s = "lwc2";
       fmt = COP12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       /* Itbl support may require additional care here.  */
       coproc = 1;
       goto ld_st;
@@ -8006,14 +8289,14 @@ macro (struct mips_cl_insn *ip)
     case M_LWL_OB:
       s = "lwl";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_LWR_AB:
       ab = 1;
     case M_LWR_OB:
       s = "lwr";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_LDC1_AB:
       ab = 1;
@@ -8027,7 +8310,14 @@ macro (struct mips_cl_insn *ip)
     case M_LDC2_OB:
       s = "ldc2";
       fmt = COP12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
+      /* Itbl support may require additional care here.  */
+      coproc = 1;
+      goto ld_st;
+    case M_LQC2_AB:
+      ab = 1;
+      s = "lqc2";
+      fmt = "E,o(b)";
       /* Itbl support may require additional care here.  */
       coproc = 1;
       goto ld_st;
@@ -8043,35 +8333,35 @@ macro (struct mips_cl_insn *ip)
     case M_LDL_OB:
       s = "ldl";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_LDR_AB:
       ab = 1;
     case M_LDR_OB:
       s = "ldr";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_LL_AB:
       ab = 1;
     case M_LL_OB:
       s = "ll";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld;
     case M_LLD_AB:
       ab = 1;
     case M_LLD_OB:
       s = "lld";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld;
     case M_LWU_AB:
       ab = 1;
     case M_LWU_OB:
       s = "lwu";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld;
     case M_LWP_AB:
       ab = 1;
@@ -8079,7 +8369,7 @@ macro (struct mips_cl_insn *ip)
       gas_assert (mips_opts.micromips);
       s = "lwp";
       fmt = "t,~(b)";
-      off12 = 1;
+      offbits = 12;
       lp = 1;
       goto ld;
     case M_LDP_AB:
@@ -8088,7 +8378,7 @@ macro (struct mips_cl_insn *ip)
       gas_assert (mips_opts.micromips);
       s = "ldp";
       fmt = "t,~(b)";
-      off12 = 1;
+      offbits = 12;
       lp = 1;
       goto ld;
     case M_LWM_AB:
@@ -8097,7 +8387,7 @@ macro (struct mips_cl_insn *ip)
       gas_assert (mips_opts.micromips);
       s = "lwm";
       fmt = "n,~(b)";
-      off12 = 1;
+      offbits = 12;
       goto ld_st;
     case M_LDM_AB:
       ab = 1;
@@ -8105,11 +8395,12 @@ macro (struct mips_cl_insn *ip)
       gas_assert (mips_opts.micromips);
       s = "ldm";
       fmt = "n,~(b)";
-      off12 = 1;
+      offbits = 12;
       goto ld_st;
 
     ld:
-      if (breg == treg + lp)
+      /* We don't want to use $0 as tempreg.  */
+      if (breg == treg + lp || treg + lp == ZERO)
        goto ld_st;
       else
        tempreg = treg + lp;
@@ -8150,7 +8441,7 @@ macro (struct mips_cl_insn *ip)
     case M_SWC2_OB:
       s = "swc2";
       fmt = COP12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       /* Itbl support may require additional care here.  */
       coproc = 1;
       goto ld_st;
@@ -8167,42 +8458,56 @@ macro (struct mips_cl_insn *ip)
     case M_SWL_OB:
       s = "swl";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_SWR_AB:
       ab = 1;
     case M_SWR_OB:
       s = "swr";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_SC_AB:
       ab = 1;
     case M_SC_OB:
       s = "sc";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_SCD_AB:
       ab = 1;
     case M_SCD_OB:
       s = "scd";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_CACHE_AB:
       ab = 1;
     case M_CACHE_OB:
       s = "cache";
       fmt = mips_opts.micromips ? "k,~(b)" : "k,o(b)";
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
+      goto ld_st;
+    case M_CACHEE_AB:
+      ab = 1;
+    case M_CACHEE_OB:
+      s = "cachee";
+      fmt = "k,+j(b)";
+      offbits = 9;
       goto ld_st;
     case M_PREF_AB:
       ab = 1;
     case M_PREF_OB:
       s = "pref";
       fmt = !mips_opts.micromips ? "k,o(b)" : "k,~(b)";
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
+      goto ld_st;
+    case M_PREFE_AB:
+      ab = 1;
+    case M_PREFE_OB:
+      s = "prefe";
+      fmt = "k,+j(b)";
+      offbits = 9;
       goto ld_st;
     case M_SDC1_AB:
       ab = 1;
@@ -8216,7 +8521,14 @@ macro (struct mips_cl_insn *ip)
     case M_SDC2_OB:
       s = "sdc2";
       fmt = COP12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
+      /* Itbl support may require additional care here.  */
+      coproc = 1;
+      goto ld_st;
+    case M_SQC2_AB:
+      ab = 1;
+      s = "sqc2";
+      fmt = "E,o(b)";
       /* Itbl support may require additional care here.  */
       coproc = 1;
       goto ld_st;
@@ -8233,14 +8545,14 @@ macro (struct mips_cl_insn *ip)
     case M_SDL_OB:
       s = "sdl";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_SDR_AB:
       ab = 1;
     case M_SDR_OB:
       s = "sdr";
       fmt = MEM12_FMT;
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       goto ld_st;
     case M_SWP_AB:
       ab = 1;
@@ -8248,7 +8560,7 @@ macro (struct mips_cl_insn *ip)
       gas_assert (mips_opts.micromips);
       s = "swp";
       fmt = "t,~(b)";
-      off12 = 1;
+      offbits = 12;
       goto ld_st;
     case M_SDP_AB:
       ab = 1;
@@ -8256,7 +8568,7 @@ macro (struct mips_cl_insn *ip)
       gas_assert (mips_opts.micromips);
       s = "sdp";
       fmt = "t,~(b)";
-      off12 = 1;
+      offbits = 12;
       goto ld_st;
     case M_SWM_AB:
       ab = 1;
@@ -8264,7 +8576,7 @@ macro (struct mips_cl_insn *ip)
       gas_assert (mips_opts.micromips);
       s = "swm";
       fmt = "n,~(b)";
-      off12 = 1;
+      offbits = 12;
       goto ld_st;
     case M_SDM_AB:
       ab = 1;
@@ -8272,7 +8584,7 @@ macro (struct mips_cl_insn *ip)
       gas_assert (mips_opts.micromips);
       s = "sdm";
       fmt = "n,~(b)";
-      off12 = 1;
+      offbits = 12;
 
     ld_st:
       tempreg = AT;
@@ -8302,18 +8614,25 @@ macro (struct mips_cl_insn *ip)
 
          expr1.X_add_number = offset_expr.X_add_number;
          normalize_address_expr (&expr1);
-         if (!off12 && !IS_SEXT_16BIT_NUM (expr1.X_add_number))
+         if ((offbits == 0 || offbits == 16)
+             && !IS_SEXT_16BIT_NUM (expr1.X_add_number))
            {
              expr1.X_add_number = ((expr1.X_add_number + 0x8000)
                                    & ~(bfd_vma) 0xffff);
              hipart = 1;
            }
-         else if (off12 && !IS_SEXT_12BIT_NUM (expr1.X_add_number))
+         else if (offbits == 12 && !IS_SEXT_12BIT_NUM (expr1.X_add_number))
            {
              expr1.X_add_number = ((expr1.X_add_number + 0x800)
                                    & ~(bfd_vma) 0xfff);
              hipart = 1;
            }
+         else if (offbits == 9 && !IS_SEXT_9BIT_NUM (expr1.X_add_number))
+           {
+             expr1.X_add_number = ((expr1.X_add_number + 0x100)
+                                   & ~(bfd_vma) 0x1ff);
+             hipart = 1;
+           }
          if (hipart)
            {
              load_register (tempreg, &expr1, HAVE_64BIT_ADDRESSES);
@@ -8322,7 +8641,7 @@ macro (struct mips_cl_insn *ip)
                             tempreg, tempreg, breg);
              breg = tempreg;
            }
-         if (off0)
+         if (offbits == 0)
            {
              if (offset_expr.X_add_number == 0)
                tempreg = breg;
@@ -8331,20 +8650,20 @@ macro (struct mips_cl_insn *ip)
                             "t,r,j", tempreg, breg, BFD_RELOC_LO16);
              macro_build (NULL, s, fmt, treg, tempreg);
            }
-         else if (!off12)
+         else if (offbits == 16)
            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 || off0)
+      else if (offbits != 16)
        {
-         /* 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
+         /* The 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)
@@ -8359,7 +8678,7 @@ macro (struct mips_cl_insn *ip)
                         tempreg, breg, -1,
                         offset_reloc[0], offset_reloc[1], offset_reloc[2]);
          expr1.X_add_number = 0;
-         if (off0)
+         if (offbits == 0)
            macro_build (NULL, s, fmt, treg, tempreg);
          else
            macro_build (NULL, s, fmt,
@@ -8804,7 +9123,7 @@ macro (struct mips_cl_insn *ip)
       s = segment_name (S_GET_SEGMENT (offset_expr.X_add_symbol));
       if (strcmp (s, ".lit8") == 0)
        {
-         if (mips_opts.isa != ISA_MIPS1 || mips_opts.micromips)
+         if (CPU_HAS_LDC1_SDC1 (mips_opts.arch) || mips_opts.micromips)
            {
              macro_build (&offset_expr, "ldc1", "T,o(b)", treg,
                           BFD_RELOC_MIPS_LITERAL, mips_gp_register);
@@ -8827,7 +9146,7 @@ macro (struct mips_cl_insn *ip)
              macro_build_lui (&offset_expr, AT);
            }
 
-         if (mips_opts.isa != ISA_MIPS1 || mips_opts.micromips)
+         if (CPU_HAS_LDC1_SDC1 (mips_opts.arch) || mips_opts.micromips)
            {
              macro_build (&offset_expr, "ldc1", "T,o(b)",
                           treg, BFD_RELOC_LO16, AT);
@@ -8844,7 +9163,7 @@ macro (struct mips_cl_insn *ip)
       r = BFD_RELOC_LO16;
     dob:
       gas_assert (!mips_opts.micromips);
-      gas_assert (mips_opts.isa == ISA_MIPS1);
+      gas_assert (!CPU_HAS_LDC1_SDC1 (mips_opts.arch));
       macro_build (&offset_expr, "lwc1", "T,o(b)",
                   target_big_endian ? treg + 1 : treg, r, breg);
       /* FIXME: A possible overflow which I don't know how to deal
@@ -8856,7 +9175,7 @@ macro (struct mips_cl_insn *ip)
 
     case M_S_DOB:
       gas_assert (!mips_opts.micromips);
-      gas_assert (mips_opts.isa == ISA_MIPS1);
+      gas_assert (!CPU_HAS_LDC1_SDC1 (mips_opts.arch));
       /* Even on a big endian machine $fn comes before $fn+1.  We have
         to adjust when storing to memory.  */
       macro_build (&offset_expr, "swc1", "T,o(b)",
@@ -8882,7 +9201,7 @@ macro (struct mips_cl_insn *ip)
       /* Itbl support may require additional care here.  */
       coproc = 1;
       fmt = "T,o(b)";
-      if (mips_opts.isa != ISA_MIPS1)
+      if (CPU_HAS_LDC1_SDC1 (mips_opts.arch))
        {
          s = "ldc1";
          goto ld_st;
@@ -8895,7 +9214,7 @@ macro (struct mips_cl_insn *ip)
       /* Itbl support may require additional care here.  */
       coproc = 1;
       fmt = "T,o(b)";
-      if (mips_opts.isa != ISA_MIPS1)
+      if (CPU_HAS_LDC1_SDC1 (mips_opts.arch))
        {
          s = "sdc1";
          goto ld_st;
@@ -8903,6 +9222,16 @@ macro (struct mips_cl_insn *ip)
       s = "swc1";
       goto ldd_std;
 
+    case M_LQ_AB:
+      fmt = "t,o(b)";
+      s = "lq";
+      goto ld;
+
+    case M_SQ_AB:
+      fmt = "t,o(b)";
+      s = "sq";
+      goto ld_st;
+
     case M_LD_AB:
       fmt = "t,o(b)";
       if (HAVE_64BIT_GPRS)
@@ -9162,14 +9491,14 @@ macro (struct mips_cl_insn *ip)
       ab = 1;
     case M_SAA_OB:
       s = "saa";
-      off0 = 1;
+      offbits = 0;
       fmt = "t,(b)";
       goto ld_st;
     case M_SAAD_AB:
       ab = 1;
     case M_SAAD_OB:
       s = "saad";
-      off0 = 1;
+      offbits = 0;
       fmt = "t,(b)";
       goto ld_st;
 
@@ -9215,8 +9544,15 @@ macro (struct mips_cl_insn *ip)
     case M_DMUL:
       dbl = 1;
     case M_MUL:
+      if (mips_opts.arch == CPU_R5900)
+        {
+          macro_build (NULL, dbl ? "dmultu" : "multu", "d,s,t", dreg, sreg, treg);
+        }
+      else
+        {
       macro_build (NULL, dbl ? "dmultu" : "multu", "s,t", sreg, treg);
       macro_build (NULL, "mflo", MFHL_FMT, dreg);
+        }
       break;
 
     case M_DMUL_I:
@@ -9824,7 +10160,7 @@ macro (struct mips_cl_insn *ip)
     case M_ULW:
       s = "lwl";
       s2 = "lwr";
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       off = 3;
       goto uld_st;
     case M_ULD_A:
@@ -9832,7 +10168,7 @@ macro (struct mips_cl_insn *ip)
     case M_ULD:
       s = "ldl";
       s2 = "ldr";
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       off = 7;
       goto uld_st;
     case M_USH_A:
@@ -9848,7 +10184,7 @@ macro (struct mips_cl_insn *ip)
     case M_USW:
       s = "swl";
       s2 = "swr";
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       off = 3;
       ust = 1;
       goto uld_st;
@@ -9857,7 +10193,7 @@ macro (struct mips_cl_insn *ip)
     case M_USD:
       s = "sdl";
       s2 = "sdr";
-      off12 = mips_opts.micromips;
+      offbits = (mips_opts.micromips ? 12 : 16);
       off = 7;
       ust = 1;
 
@@ -9879,7 +10215,7 @@ macro (struct mips_cl_insn *ip)
          tempreg = treg;
          ep = &expr1;
        }
-      else if (off12
+      else if (offbits == 12
               && (offset_expr.X_op != O_constant
                   || !IS_SEXT_12BIT_NUM (offset_expr.X_add_number)
                   || !IS_SEXT_12BIT_NUM (offset_expr.X_add_number + off)))
@@ -9905,7 +10241,7 @@ macro (struct mips_cl_insn *ip)
 
       if (!target_big_endian)
        ep->X_add_number += off;
-      if (!off12)
+      if (offbits != 12)
        macro_build (ep, s, "t,o(b)", tempreg, BFD_RELOC_LO16, breg);
       else
        macro_build (NULL, s, "t,~(b)",
@@ -9915,7 +10251,7 @@ macro (struct mips_cl_insn *ip)
        ep->X_add_number -= off;
       else
        ep->X_add_number += off;
-      if (!off12)
+      if (offbits != 12)
        macro_build (ep, s2, "t,o(b)", tempreg, BFD_RELOC_LO16, breg);
       else
        macro_build (NULL, s2, "t,~(b)",
@@ -10006,7 +10342,7 @@ mips16_macro (struct mips_cl_insn *ip)
   switch (mask)
     {
     default:
-      internalError ();
+      abort ();
 
     case M_DDIV_3:
       dbl = 1;
@@ -10250,6 +10586,7 @@ validate_mips_insn (const struct mips_opcode *opc)
          case 'G': USE_BITS (OP_MASK_EXTMSBD,  OP_SH_EXTMSBD); break;
          case 'H': USE_BITS (OP_MASK_EXTMSBD,  OP_SH_EXTMSBD); break;
          case 'I': break;
+         case 'J': USE_BITS (OP_MASK_CODE10,   OP_SH_CODE10);  break;
          case 't': USE_BITS (OP_MASK_RT,       OP_SH_RT);      break;
          case 'T': USE_BITS (OP_MASK_RT,       OP_SH_RT);
                    USE_BITS (OP_MASK_SEL,      OP_SH_SEL);     break;
@@ -10265,6 +10602,7 @@ validate_mips_insn (const struct mips_opcode *opc)
          case 'a': USE_BITS (OP_MASK_OFFSET_A, OP_SH_OFFSET_A); break;
          case 'b': USE_BITS (OP_MASK_OFFSET_B, OP_SH_OFFSET_B); break;
          case 'c': USE_BITS (OP_MASK_OFFSET_C, OP_SH_OFFSET_C); break;
+         case 'j': USE_BITS (OP_MASK_EVAOFFSET, OP_SH_EVAOFFSET); break;
 
          default:
            as_bad (_("internal: bad mips opcode (unknown extension operand type `+%c'): %s %s"),
@@ -10426,6 +10764,7 @@ validate_micromips_insn (const struct mips_opcode *opc)
          case 'F': USE_BITS (INSMSB);  break;
          case 'G': USE_BITS (EXTMSBD); break;
          case 'H': USE_BITS (EXTMSBD); break;
+         case 'j': USE_BITS (EVAOFFSET);       break;
          default:
            as_bad (_("Internal error: bad mips opcode "
                      "(unknown extension operand type `%c%c'): %s %s"),
@@ -10584,7 +10923,7 @@ mips_oddfpreg_ok (const struct mips_opcode *insn, int argnum)
     /* Let a macro pass, we'll catch it later when it is expanded.  */
     return 1;
 
-  if (ISA_HAS_ODD_SINGLE_FPR (mips_opts.isa))
+  if (ISA_HAS_ODD_SINGLE_FPR (mips_opts.isa) || (mips_opts.arch == CPU_R5900))
     {
       /* Allow odd registers for single-precision ops.  */
       switch (insn->pinfo & (FP_S | FP_D))
@@ -10648,6 +10987,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
   unsigned int destregno = 0;
   unsigned int lastpos = 0;
   unsigned int limlo, limhi;
+  int sizelo;
   char *s_reset;
   offsetT min_range, max_range;
   long opend;
@@ -11154,7 +11494,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                    while (imm->type && imm->type != *args)
                      ++imm;
                    if (! imm->type)
-                     internalError ();
+                     abort ();
                    my_getExpression (&imm_expr, s);
                    check_absolute_expr (ip, &imm_expr);
                    if ((unsigned long) imm_expr.X_add_number & ~imm->mask)
@@ -11172,6 +11512,23 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                  }
                  continue;
 
+               case 'J':               /* 10-bit hypcall code.  */
+                 gas_assert (!mips_opts.micromips);
+                 {
+                   unsigned long mask = OP_MASK_CODE10;
+
+                   my_getExpression (&imm_expr, s);
+                   check_absolute_expr (ip, &imm_expr);
+                   if ((unsigned long) imm_expr.X_add_number > mask)
+                     as_warn (_("Code for %s not in range 0..%lu (%lu)"),
+                              ip->insn_mo->name,
+                              mask, (unsigned long) imm_expr.X_add_number);
+                   INSERT_OPERAND (0, CODE10, *ip, imm_expr.X_add_number);
+                   imm_expr.X_op = O_absent;
+                   s = expr_end;
+                 }
+                 continue;
+
                case 'A':               /* ins/ext position, becomes LSB.  */
                  limlo = 0;
                  limhi = 31;
@@ -11232,23 +11589,25 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                case 'C':               /* ext size, becomes MSBD.  */
                  limlo = 1;
                  limhi = 32;
+                 sizelo = 1;
                  goto do_msbd;
                case 'G':
                  limlo = 33;
                  limhi = 64;
+                 sizelo = 33;
                  goto do_msbd;
                case 'H':
                  limlo = 33;
                  limhi = 64;
+                 sizelo = 1;
                  goto do_msbd;
                do_msbd:
                  my_getExpression (&imm_expr, s);
                  check_absolute_expr (ip, &imm_expr);
-                 /* Check for negative input so that small negative numbers
-                    will not succeed incorrectly.  The checks against
-                    (pos+size) transitively check "size" itself,
-                    assuming that "pos" is reasonable.  */
-                 if ((long) imm_expr.X_add_number < 0
+                 /* The checks against (pos+size) don't transitively check
+                    "size" itself, assuming that "pos" is reasonable.
+                    We also need to check the lower bound of "size".  */
+                 if ((long) imm_expr.X_add_number < sizelo
                      || ((unsigned long) imm_expr.X_add_number
                          + lastpos) < limlo
                      || ((unsigned long) imm_expr.X_add_number
@@ -11513,6 +11872,35 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                  INSERT_OPERAND (0, FZ, *ip, regno);
                  continue;
 
+               case 'j':
+                 {
+                   int shift = 8;
+                   size_t i;
+                   /* Check whether there is only a single bracketed expression
+                      left.  If so, it must be the base register and the
+                      constant must be zero.  */
+                   if (*s == '(' && strchr (s + 1, '(') == 0)
+                     continue;
+
+                   /* If this value won't fit into the offset, then go find
+                      a macro that will generate a 16- or 32-bit offset code
+                      pattern.  */
+                   i = my_getSmallExpression (&imm_expr, imm_reloc, s);
+                   if ((i == 0 && (imm_expr.X_op != O_constant
+                                   || imm_expr.X_add_number >= 1 << shift
+                                   || imm_expr.X_add_number < -1 << shift))
+                       || i > 0)
+                     {
+                       imm_expr.X_op = O_absent;
+                       break;
+                     }
+                   INSERT_OPERAND (mips_opts.micromips, EVAOFFSET, *ip,
+                                   imm_expr.X_add_number);
+                   imm_expr.X_op = O_absent;
+                   s = expr_end;
+                 }
+                 continue;
+
                default:
                  as_bad (_("Internal error: bad %s opcode "
                            "(unknown extension operand type `+%c'): %s %s"),
@@ -11735,6 +12123,10 @@ mips_ip (char *str, struct mips_cl_insn *ip)
              if (imm_expr.X_add_number != 0 && imm_expr.X_add_number != 1)
                as_warn (_("Invalid performance register (%lu)"),
                         (unsigned long) imm_expr.X_add_number);
+             if (imm_expr.X_add_number != 0 && mips_opts.arch == CPU_R5900
+               && (!strcmp(insn->name,"mfps") || !strcmp(insn->name,"mtps")))
+               as_warn (_("Invalid performance register (%lu)"),
+                 (unsigned long) imm_expr.X_add_number);
              INSERT_OPERAND (0, PERFREG, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
              s = expr_end;
@@ -12359,6 +12751,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
              continue;
 
            case 'u':           /* Upper 16 bits.  */
+             *imm_reloc = BFD_RELOC_LO16;
              if (my_getSmallExpression (&imm_expr, imm_reloc, s) == 0
                  && imm_expr.X_op == O_constant
                  && (imm_expr.X_add_number < 0
@@ -12684,7 +13077,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                        break;
 
                      default:
-                       internalError ();
+                       abort ();
                    }
 
                  if (regno == ILLEGAL_REG)
@@ -12757,7 +13150,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                        break;
 
                      default:
-                       internalError ();
+                       abort ();
                    }
                  continue;
 
@@ -13221,7 +13614,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
 
            default:
              as_bad (_("Bad char = '%c'\n"), *args);
-             internalError ();
+             abort ();
            }
          break;
        }
@@ -13369,40 +13762,17 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
            case '\0':
              if (*s == '\0')
                {
+                 offsetT value;
+
                  /* Stuff the immediate value in now, if we can.  */
                  if (imm_expr.X_op == O_constant
                      && *imm_reloc > BFD_RELOC_UNUSED
-                     && *imm_reloc != BFD_RELOC_MIPS16_GOT16
-                     && *imm_reloc != BFD_RELOC_MIPS16_CALL16
-                     && insn->pinfo != INSN_MACRO)
+                     && insn->pinfo != INSN_MACRO
+                     && calculate_reloc (*offset_reloc,
+                                         imm_expr.X_add_number, &value))
                    {
-                     valueT tmp;
-
-                     switch (*offset_reloc)
-                       {
-                         case BFD_RELOC_MIPS16_HI16_S:
-                           tmp = (imm_expr.X_add_number + 0x8000) >> 16;
-                           break;
-
-                         case BFD_RELOC_MIPS16_HI16:
-                           tmp = imm_expr.X_add_number >> 16;
-                           break;
-
-                         case BFD_RELOC_MIPS16_LO16:
-                           tmp = ((imm_expr.X_add_number + 0x8000) & 0xffff)
-                                 - 0x8000;
-                           break;
-
-                         case BFD_RELOC_UNUSED:
-                           tmp = imm_expr.X_add_number;
-                           break;
-
-                         default:
-                           internalError ();
-                       }
-
                      mips16_immed (NULL, 0, *imm_reloc - BFD_RELOC_UNUSED,
-                                   *offset_reloc, tmp, forced_insn_length,
+                                   *offset_reloc, value, forced_insn_length,
                                    &ip->insn_opcode);
                      imm_expr.X_op = O_absent;
                      *imm_reloc = BFD_RELOC_UNUSED;
@@ -13521,7 +13891,7 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
                  break;
 
                default:
-                 internalError ();
+                 abort ();
                }
 
              if (regno == ILLEGAL_REG)
@@ -13554,7 +13924,7 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
                  MIPS16_INSERT_OPERAND (REG32R, *ip, regno);
                  break;
                default:
-                 internalError ();
+                 abort ();
                }
 
              lastregno = regno;
@@ -13913,7 +14283,7 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
              continue;
 
            default:
-             internalError ();
+             abort ();
            }
          break;
        }
@@ -13988,6 +14358,31 @@ static const struct mips16_immed_operand mips16_immed_operands[] =
 #define MIPS16_NUM_IMMED \
   (sizeof mips16_immed_operands / sizeof mips16_immed_operands[0])
 
+/* Marshal immediate value VAL for an extended MIPS16 instruction.
+   NBITS is the number of significant bits in VAL.  */
+
+static unsigned long
+mips16_immed_extend (offsetT val, unsigned int nbits)
+{
+  int extval;
+  if (nbits == 16)
+    {
+      extval = ((val >> 11) & 0x1f) | (val & 0x7e0);
+      val &= 0x1f;
+    }
+  else if (nbits == 15)
+    {
+      extval = ((val >> 11) & 0xf) | (val & 0x7f0);
+      val &= 0xf;
+    }
+  else
+    {
+      extval = ((val & 0x1f) << 6) | (val & 0x20);
+      val = 0;
+    }
+  return (extval << 16) | val;
+}
+
 /* Install immediate value VAL into MIPS16 instruction *INSN,
    extending it if necessary.  The instruction in *INSN may
    already be extended.
@@ -14071,7 +14466,6 @@ mips16_immed (char *file, unsigned int line, int type,
   else
     {
       long minext, maxext;
-      int extval;
 
       if (reloc == BFD_RELOC_UNUSED)
        {
@@ -14090,23 +14484,7 @@ mips16_immed (char *file, unsigned int line, int type,
                          _("operand value out of range for instruction"));
        }
 
-      if (op->extbits == 16)
-       {
-         extval = ((val >> 11) & 0x1f) | (val & 0x7e0);
-         val &= 0x1f;
-       }
-      else if (op->extbits == 15)
-       {
-         extval = ((val >> 11) & 0xf) | (val & 0x7f0);
-         val &= 0xf;
-       }
-      else
-       {
-         extval = ((val & 0x1f) << 6) | (val & 0x20);
-         val = 0;
-       }
-
-      *insn |= (extval << 16) | val;
+      *insn |= mips16_immed_extend (val, op->extbits);
     }
 }
 \f
@@ -14337,10 +14715,14 @@ enum options
     OPTION_NO_DSP,
     OPTION_MT,
     OPTION_NO_MT,
+    OPTION_VIRT,
+    OPTION_NO_VIRT,
     OPTION_SMARTMIPS,
     OPTION_NO_SMARTMIPS,
     OPTION_DSPR2,
     OPTION_NO_DSPR2,
+    OPTION_EVA,
+    OPTION_NO_EVA,
     OPTION_MICROMIPS,
     OPTION_NO_MICROMIPS,
     OPTION_MCU,
@@ -14437,10 +14819,14 @@ struct option md_longopts[] =
   {"mno-smartmips", no_argument, NULL, OPTION_NO_SMARTMIPS},
   {"mdspr2", no_argument, NULL, OPTION_DSPR2},
   {"mno-dspr2", no_argument, NULL, OPTION_NO_DSPR2},
+  {"meva", no_argument, NULL, OPTION_EVA},
+  {"mno-eva", no_argument, NULL, OPTION_NO_EVA},
   {"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},
+  {"mvirt", no_argument, NULL, OPTION_VIRT},
+  {"mno-virt", no_argument, NULL, OPTION_NO_VIRT},
 
   /* Old-style architecture options.  Don't add more of these.  */
   {"m4650", no_argument, NULL, OPTION_M4650},
@@ -14687,6 +15073,14 @@ md_parse_option (int c, char *arg)
       mips_opts.ase_dsp = 0;
       break;
 
+    case OPTION_EVA:
+      mips_opts.ase_eva = 1;
+      break;
+
+    case OPTION_NO_EVA:
+      mips_opts.ase_eva = 0;
+      break;
+
     case OPTION_MT:
       mips_opts.ase_mt = 1;
       break;
@@ -14718,6 +15112,14 @@ md_parse_option (int c, char *arg)
       mips_no_prev_insn ();
       break;
 
+    case OPTION_VIRT:
+      mips_opts.ase_virt = 1;
+      break;
+
+    case OPTION_NO_VIRT:
+      mips_opts.ase_virt = 0;
+      break;
+
     case OPTION_MIPS16:
       if (mips_opts.micromips == 1)
        {
@@ -15167,57 +15569,71 @@ mips_after_parse_args (void)
   if (mips_opts.micromips == -1)
     mips_opts.micromips = (CPU_HAS_MICROMIPS (file_mips_arch)) ? 1 : 0;
   if (mips_opts.ase_mips3d == -1)
-    mips_opts.ase_mips3d = ((arch_info->flags & MIPS_CPU_ASE_MIPS3D)
+    mips_opts.ase_mips3d = ((arch_info->ase & ASE_MIPS3D)
                            && file_mips_fp32 == 0) ? 1 : 0;
   if (mips_opts.ase_mips3d && file_mips_fp32 == 1)
     as_bad (_("-mfp32 used with -mips3d"));
 
   if (mips_opts.ase_mdmx == -1)
-    mips_opts.ase_mdmx = ((arch_info->flags & MIPS_CPU_ASE_MDMX)
+    mips_opts.ase_mdmx = ((arch_info->ase & ASE_MDMX)
                          && file_mips_fp32 == 0) ? 1 : 0;
   if (mips_opts.ase_mdmx && file_mips_fp32 == 1)
     as_bad (_("-mfp32 used with -mdmx"));
 
   if (mips_opts.ase_smartmips == -1)
-    mips_opts.ase_smartmips = (arch_info->flags & MIPS_CPU_ASE_SMARTMIPS) ? 1 : 0;
+    mips_opts.ase_smartmips = (arch_info->ase & ASE_SMARTMIPS) ? 1 : 0;
   if (mips_opts.ase_smartmips && !ISA_SUPPORTS_SMARTMIPS)
     as_warn (_("%s ISA does not support SmartMIPS"), 
             mips_cpu_info_from_isa (mips_opts.isa)->name);
 
   if (mips_opts.ase_dsp == -1)
-    mips_opts.ase_dsp = (arch_info->flags & MIPS_CPU_ASE_DSP) ? 1 : 0;
+    mips_opts.ase_dsp = (arch_info->ase & ASE_DSP) ? 1 : 0;
   if (mips_opts.ase_dsp && !ISA_SUPPORTS_DSP_ASE)
     as_warn (_("%s ISA does not support DSP ASE"), 
             mips_cpu_info_from_isa (mips_opts.isa)->name);
 
   if (mips_opts.ase_dspr2 == -1)
     {
-      mips_opts.ase_dspr2 = (arch_info->flags & MIPS_CPU_ASE_DSPR2) ? 1 : 0;
-      mips_opts.ase_dsp = (arch_info->flags & MIPS_CPU_ASE_DSP) ? 1 : 0;
+      mips_opts.ase_dspr2 = (arch_info->ase & ASE_DSPR2) ? 1 : 0;
+      mips_opts.ase_dsp = (arch_info->ase & ASE_DSP) ? 1 : 0;
     }
   if (mips_opts.ase_dspr2 && !ISA_SUPPORTS_DSPR2_ASE)
     as_warn (_("%s ISA does not support DSP R2 ASE"),
             mips_cpu_info_from_isa (mips_opts.isa)->name);
 
+  if (mips_opts.ase_eva == -1)
+     mips_opts.ase_eva = (arch_info->ase & ASE_EVA) ? 1 : 0;
+  if (mips_opts.ase_eva && !ISA_SUPPORTS_EVA_ASE)
+    as_warn (_("%s ISA does not support EVA ASE"),
+            mips_cpu_info_from_isa (mips_opts.isa)->name);
+
   if (mips_opts.ase_mt == -1)
-    mips_opts.ase_mt = (arch_info->flags & MIPS_CPU_ASE_MT) ? 1 : 0;
+    mips_opts.ase_mt = (arch_info->ase & ASE_MT) ? 1 : 0;
   if (mips_opts.ase_mt && !ISA_SUPPORTS_MT_ASE)
     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;
+    mips_opts.ase_mcu = (arch_info->ase & 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);
 
+  if (mips_opts.ase_virt == -1)
+    mips_opts.ase_virt = (arch_info->ase & ASE_VIRT) ? 1 : 0;
+  if (mips_opts.ase_virt && !ISA_SUPPORTS_VIRT_ASE)
+    as_warn (_("%s ISA does not support Virtualization 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;
   file_ase_smartmips = mips_opts.ase_smartmips;
   file_ase_dsp = mips_opts.ase_dsp;
   file_ase_dspr2 = mips_opts.ase_dspr2;
+  file_ase_eva = mips_opts.ase_eva;
   file_ase_mt = mips_opts.ase_mt;
+  file_ase_virt = mips_opts.ase_virt;
   mips_opts.gp32 = file_mips_gp32;
   mips_opts.fp32 = file_mips_fp32;
   mips_opts.soft_float = file_mips_soft_float;
@@ -15260,6 +15676,9 @@ md_pcrel_from (fixS *fixP)
       /* Return the address of the delay slot.  */
       return addr + 4;
 
+    case BFD_RELOC_32_PCREL:
+      return addr;
+
     default:
       /* We have no relocation type for PC relative MIPS16 instructions.  */
       if (fixP->fx_addsy && S_GET_SEGMENT (fixP->fx_addsy) != now_seg)
@@ -15350,9 +15769,11 @@ mips_frob_file (void)
       gas_assert (reloc_needs_lo_p (l->fixp->fx_r_type));
 
       /* If a GOT16 relocation turns out to be against a global symbol,
-        there isn't supposed to be a matching LO.  */
+        there isn't supposed to be a matching LO.  Ignore %gots against
+        constants; we'll report an error for those later.  */
       if (got16_reloc_p (l->fixp->fx_r_type)
-         && !pic_need_relax (l->fixp->fx_addsy, l->seg))
+         && !(l->fixp->fx_addsy
+              && pic_need_relax (l->fixp->fx_addsy, l->seg)))
        continue;
 
       /* Check quickly whether the next fixup happens to be a matching %lo.  */
@@ -15410,9 +15831,6 @@ mips_frob_file (void)
     }
 }
 
-/* We may have combined relocations without symbols in the N32/N64 ABI.
-   We have to prevent gas from dropping them.  */
-
 int
 mips_force_relocation (fixS *fixp)
 {
@@ -15426,23 +15844,40 @@ mips_force_relocation (fixS *fixp)
       || fixp->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1)
     return 1;
 
-  if (HAVE_NEWABI
-      && S_GET_SEGMENT (fixp->fx_addsy) == bfd_abs_section_ptr
-      && (fixp->fx_r_type == BFD_RELOC_MIPS_SUB
-         || hi16_reloc_p (fixp->fx_r_type)
-         || lo16_reloc_p (fixp->fx_r_type)))
-    return 1;
-
   return 0;
 }
 
+/* Read the instruction associated with RELOC from BUF.  */
+
+static unsigned int
+read_reloc_insn (char *buf, bfd_reloc_code_real_type reloc)
+{
+  if (mips16_reloc_p (reloc) || micromips_reloc_p (reloc))
+    return read_compressed_insn (buf, 4);
+  else
+    return read_insn (buf);
+}
+
+/* Write instruction INSN to BUF, given that it has been relocated
+   by RELOC.  */
+
+static void
+write_reloc_insn (char *buf, bfd_reloc_code_real_type reloc,
+                 unsigned long insn)
+{
+  if (mips16_reloc_p (reloc) || micromips_reloc_p (reloc))
+    write_compressed_insn (buf, insn, 4);
+  else
+    write_insn (buf, insn);
+}
+
 /* Apply a fixup to the object file.  */
 
 void
 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 {
   char *buf;
-  long insn;
+  unsigned long insn;
   reloc_howto_type *howto;
 
   /* We ignore generic BFD relocations we don't know about.  */
@@ -15466,7 +15901,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
   gas_assert (!fixP->fx_pcrel || fixP->fx_r_type == BFD_RELOC_16_PCREL_S2
              || fixP->fx_r_type == BFD_RELOC_MICROMIPS_7_PCREL_S1
              || fixP->fx_r_type == BFD_RELOC_MICROMIPS_10_PCREL_S1
-             || fixP->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1);
+             || fixP->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1
+             || fixP->fx_r_type == BFD_RELOC_32_PCREL);
 
   /* Don't treat parts of a composite relocation as done.  There are two
      reasons for this:
@@ -15508,6 +15944,12 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
     case BFD_RELOC_MIPS16_TLS_GOTTPREL:
     case BFD_RELOC_MIPS16_TLS_TPREL_HI16:
     case BFD_RELOC_MIPS16_TLS_TPREL_LO16:
+      if (!fixP->fx_addsy)
+       {
+         as_bad_where (fixP->fx_file, fixP->fx_line,
+                       _("TLS relocation against a constant"));
+         break;
+       }
       S_SET_THREAD_LOCAL (fixP->fx_addsy);
       /* fall through */
 
@@ -15529,6 +15971,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
     case BFD_RELOC_MIPS_JALR:
     case BFD_RELOC_HI16:
     case BFD_RELOC_HI16_S:
+    case BFD_RELOC_LO16:
     case BFD_RELOC_GPREL16:
     case BFD_RELOC_MIPS_LITERAL:
     case BFD_RELOC_MIPS_CALL16:
@@ -15543,6 +15986,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
     case BFD_RELOC_MIPS16_CALL16:
     case BFD_RELOC_MIPS16_HI16:
     case BFD_RELOC_MIPS16_HI16_S:
+    case BFD_RELOC_MIPS16_LO16:
     case BFD_RELOC_MIPS16_JMP:
     case BFD_RELOC_MICROMIPS_JMP:
     case BFD_RELOC_MICROMIPS_GOT_DISP:
@@ -15555,6 +15999,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
     case BFD_RELOC_MICROMIPS_JALR:
     case BFD_RELOC_MICROMIPS_HI16:
     case BFD_RELOC_MICROMIPS_HI16_S:
+    case BFD_RELOC_MICROMIPS_LO16:
     case BFD_RELOC_MICROMIPS_GPREL16:
     case BFD_RELOC_MICROMIPS_LITERAL:
     case BFD_RELOC_MICROMIPS_CALL16:
@@ -15563,7 +16008,24 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
     case BFD_RELOC_MICROMIPS_GOT_LO16:
     case BFD_RELOC_MICROMIPS_CALL_HI16:
     case BFD_RELOC_MICROMIPS_CALL_LO16:
-      /* Nothing needed to do.  The value comes from the reloc entry.  */
+    case BFD_RELOC_MIPS_EH:
+      if (fixP->fx_done)
+       {
+         offsetT value;
+
+         if (calculate_reloc (fixP->fx_r_type, *valP, &value))
+           {
+             insn = read_reloc_insn (buf, fixP->fx_r_type);
+             if (mips16_reloc_p (fixP->fx_r_type))
+               insn |= mips16_immed_extend (value, 16);
+             else
+               insn |= (value & 0xffff);
+             write_reloc_insn (buf, fixP->fx_r_type, insn);
+           }
+         else
+           as_bad_where (fixP->fx_file, fixP->fx_line,
+                         _("Unsupported constant in relocation"));
+       }
       break;
 
     case BFD_RELOC_64:
@@ -15589,6 +16051,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 
     case BFD_RELOC_RVA:
     case BFD_RELOC_32:
+    case BFD_RELOC_32_PCREL:
     case BFD_RELOC_16:
       /* If we are deleting this reloc entry, we must fill in the
         value now.  This can happen if we have a .word which is not
@@ -15597,27 +16060,6 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
        md_number_to_chars (buf, *valP, fixP->fx_size);
       break;
 
-    case BFD_RELOC_LO16:
-    case BFD_RELOC_MIPS16_LO16:
-    case BFD_RELOC_MICROMIPS_LO16:
-      /* FIXME: Now that embedded-PIC is gone, some of this code/comment
-        may be safe to remove, but if so it's not obvious.  */
-      /* When handling an embedded PIC switch statement, we can wind
-        up deleting a LO16 reloc.  See the 'o' case in mips_ip.  */
-      if (fixP->fx_done)
-       {
-         if (*valP + 0x8000 > 0xffff)
-           as_bad_where (fixP->fx_file, fixP->fx_line,
-                         _("relocation overflow"));
-         /* 32-bit microMIPS instructions are divided into two halfwords.
-            Relocations always refer to the second halfword, regardless
-            of endianness.  */
-         if (target_big_endian || fixP->fx_r_type == BFD_RELOC_MICROMIPS_LO16)
-           buf += 2;
-         md_number_to_chars (buf, *valP, 2);
-       }
-      break;
-
     case BFD_RELOC_16_PCREL_S2:
       if ((*valP & 0x3) != 0)
        as_bad_where (fixP->fx_file, fixP->fx_line,
@@ -15696,7 +16138,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
       break;
 
     default:
-      internalError ();
+      abort ();
     }
 
   /* Remember value for tc_gen_reloc.  */
@@ -16249,6 +16691,15 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
       mips_opts.ase_dspr2 = 0;
       mips_opts.ase_dsp = 0;
     }
+  else if (strcmp (name, "eva") == 0)
+    {
+      if (!ISA_SUPPORTS_EVA_ASE)
+       as_warn (_("%s ISA does not support EVA ASE"),
+                mips_cpu_info_from_isa (mips_opts.isa)->name);
+      mips_opts.ase_eva = 1;
+    }
+  else if (strcmp (name, "noeva") == 0)
+    mips_opts.ase_eva = 0;
   else if (strcmp (name, "mt") == 0)
     {
       if (!ISA_SUPPORTS_MT_ASE)
@@ -16262,6 +16713,15 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
     mips_opts.ase_mcu = 1;
   else if (strcmp (name, "nomcu") == 0)
     mips_opts.ase_mcu = 0;
+  else if (strcmp (name, "virt") == 0)
+    {
+      if (!ISA_SUPPORTS_VIRT_ASE)
+       as_warn (_("%s ISA does not support Virtualization ASE"), 
+                mips_cpu_info_from_isa (mips_opts.isa)->name);
+      mips_opts.ase_virt = 1;
+    }
+  else if (strcmp (name, "novirt") == 0)
+    mips_opts.ase_virt = 0;
   else if (strncmp (name, "mips", 4) == 0 || strncmp (name, "arch=", 5) == 0)
     {
       int reset = 0;
@@ -16320,7 +16780,14 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
        case ISA_MIPS64:
        case ISA_MIPS64R2:
          mips_opts.gp32 = 0;
+         if (mips_opts.arch == CPU_R5900)
+           {
+               mips_opts.fp32 = 1;
+           }
+         else
+           {
          mips_opts.fp32 = 0;
+           }
          break;
        default:
          as_bad (_("unknown ISA level %s"), name + 4);
@@ -16462,6 +16929,9 @@ s_cpload (int ignore ATTRIBUTE_UNUSED)
   /* In ELF, this symbol is implicitly an STT_OBJECT symbol.  */
   symbol_get_bfdsym (ex.X_add_symbol)->flags |= BSF_OBJECT;
 
+  mips_mark_labels ();
+  mips_assembling_insn = TRUE;
+
   macro_start ();
   macro_build_lui (&ex, mips_gp_register);
   macro_build (&ex, "addiu", "t,r,j", mips_gp_register,
@@ -16471,6 +16941,7 @@ s_cpload (int ignore ATTRIBUTE_UNUSED)
                 mips_gp_register, reg);
   macro_end ();
 
+  mips_assembling_insn = FALSE;
   demand_empty_rest_of_line ();
 }
 
@@ -16547,6 +17018,9 @@ s_cpsetup (int ignore ATTRIBUTE_UNUSED)
   SKIP_WHITESPACE ();
   expression (&ex_sym);
 
+  mips_mark_labels ();
+  mips_assembling_insn = TRUE;
+
   macro_start ();
   if (mips_cpreturn_register == -1)
     {
@@ -16594,6 +17068,7 @@ s_cpsetup (int ignore ATTRIBUTE_UNUSED)
 
   macro_end ();
 
+  mips_assembling_insn = FALSE;
   demand_empty_rest_of_line ();
 }
 
@@ -16651,11 +17126,15 @@ s_cprestore (int ignore ATTRIBUTE_UNUSED)
   ex.X_op_symbol = NULL;
   ex.X_add_number = mips_cprestore_offset;
 
+  mips_mark_labels ();
+  mips_assembling_insn = TRUE;
+
   macro_start ();
   macro_build_ldst_constoffset (&ex, ADDRESS_STORE_INSN, mips_gp_register,
                                SP, HAVE_64BIT_ADDRESSES);
   macro_end ();
 
+  mips_assembling_insn = FALSE;
   demand_empty_rest_of_line ();
 }
 
@@ -16686,6 +17165,9 @@ s_cpreturn (int ignore ATTRIBUTE_UNUSED)
       return;
     }
 
+  mips_mark_labels ();
+  mips_assembling_insn = TRUE;
+
   macro_start ();
   if (mips_cpreturn_register == -1)
     {
@@ -16701,6 +17183,7 @@ s_cpreturn (int ignore ATTRIBUTE_UNUSED)
                 mips_cpreturn_register, 0);
   macro_end ();
 
+  mips_assembling_insn = FALSE;
   demand_empty_rest_of_line ();
 }
 
@@ -16865,6 +17348,34 @@ s_gpdword (int ignore ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 }
 
+/* Handle the .ehword pseudo-op.  This is used when generating unwinding
+   tables.  It generates a R_MIPS_EH reloc.  */
+
+static void
+s_ehword (int ignore ATTRIBUTE_UNUSED)
+{
+  expressionS ex;
+  char *p;
+
+  mips_emit_delays ();
+
+  expression (&ex);
+  mips_clear_insn_labels ();
+
+  if (ex.X_op != O_symbol || ex.X_add_number != 0)
+    {
+      as_bad (_("Unsupported use of .ehword"));
+      ignore_rest_of_line ();
+    }
+
+  p = frag_more (4);
+  md_number_to_chars (p, 0, 4);
+  fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE,
+              BFD_RELOC_MIPS_EH);
+
+  demand_empty_rest_of_line ();
+}
+
 /* Handle the .cpadd pseudo-op.  This is used when dealing with switch
    tables in SVR4 PIC code.  */
 
@@ -16880,12 +17391,16 @@ s_cpadd (int ignore ATTRIBUTE_UNUSED)
       return;
     }
 
+  mips_mark_labels ();
+  mips_assembling_insn = TRUE;
+
   /* Add $gp to the register named as an argument.  */
   macro_start ();
   reg = tc_get_register (0);
   macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", reg, reg, mips_gp_register);
   macro_end ();
 
+  mips_assembling_insn = FALSE;
   demand_empty_rest_of_line ();
 }
 
@@ -16906,18 +17421,24 @@ s_insn (int ignore ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 }
 
-/* Handle a .stabn directive.  We need these in order to mark a label
-   as being a mips16 text label correctly.  Sometimes the compiler
-   will emit a label, followed by a .stabn, and then switch sections.
-   If the label and .stabn are in mips16 mode, then the label is
-   really a mips16 text label.  */
+/* Handle a .stab[snd] directive.  Ideally these directives would be
+   implemented in a transparent way, so that removing them would not
+   have any effect on the generated instructions.  However, s_stab
+   internally changes the section, so in practice we need to decide
+   now whether the preceding label marks compressed code.  We do not
+   support changing the compression mode of a label after a .stab*
+   directive, such as in:
+
+   foo:
+       .stabs ...
+       .set mips16
+
+   so the current mode wins.  */
 
 static void
 s_mips_stab (int type)
 {
-  if (type == 'n')
-    mips_mark_labels ();
-
+  mips_mark_labels ();
   s_stab (type);
 }
 
@@ -17624,11 +18145,12 @@ mips_fix_adjustable (fixS *fixp)
     return 0;
 
   /* There is no place to store an in-place offset for JALR relocations.
-     Likewise an in-range offset of PC-relative relocations may overflow
-     the in-place relocatable field if recalculated against the start
-     address of the symbol's containing section.  */
+     Likewise an in-range offset of limited PC-relative relocations may
+     overflow the in-place relocatable field if recalculated against the
+     start address of the symbol's containing section.  */
   if (HAVE_IN_PLACE_ADDENDS
-      && (fixp->fx_pcrel || jalr_reloc_p (fixp->fx_r_type)))
+      && (limited_pcrel_reloc_p (fixp->fx_r_type)
+         || jalr_reloc_p (fixp->fx_r_type)))
     return 0;
 
 #ifdef OBJ_ELF
@@ -17708,7 +18230,8 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
       gas_assert (fixp->fx_r_type == BFD_RELOC_16_PCREL_S2
                  || fixp->fx_r_type == BFD_RELOC_MICROMIPS_7_PCREL_S1
                  || fixp->fx_r_type == BFD_RELOC_MICROMIPS_10_PCREL_S1
-                 || fixp->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1);
+                 || fixp->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1
+                 || fixp->fx_r_type == BFD_RELOC_32_PCREL);
 
       /* At this point, fx_addnumber is "symbol offset - pcrel address".
         Relocations want only the symbol offset.  */
@@ -17844,10 +18367,10 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
              switch ((insn >> 28) & 0xf)
                {
                case 4:
-                 /* bc[0-3][tf]l? and bc1any[24][ft] instructions can
-                    have the condition reversed by tweaking a single
-                    bit, and their opcodes all have 0x4???????.  */
-                 gas_assert ((insn & 0xf1000000) == 0x41000000);
+                 /* bc[0-3][tf]l? instructions can have the condition
+                    reversed by tweaking a single TF bit, and their
+                    opcodes all have 0x4???????.  */
+                 gas_assert ((insn & 0xf3e00000) == 0x41000000);
                  insn ^= 0x00010000;
                  break;
 
@@ -18405,7 +18928,7 @@ mips_frob_file_after_relocs (void)
    move it.  This also bumps the value of the symbol by 1 in compressed
    code.  */
 
-void
+static void
 mips_record_label (symbolS *sym)
 {
   segment_info_type *si = seg_info (now_seg);
@@ -18435,6 +18958,17 @@ mips_define_label (symbolS *sym)
   dwarf2_emit_label (sym);
 #endif
 }
+
+/* This function is called by tc_new_dot_label whenever a new dot symbol
+   is defined.  */
+
+void
+mips_add_dot_label (symbolS *sym)
+{
+  mips_record_label (sym);
+  if (mips_assembling_insn && HAVE_CODE_COMPRESSION)
+    mips_compressed_mark_label (sym);
+}
 \f
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
 
@@ -18488,12 +19022,8 @@ mips_elf_final_processing (void)
   if (mips_abicalls)
     elf_elfheader (stdoutput)->e_flags |= EF_MIPS_CPIC;
 
-  /* Set MIPS ELF flags for ASEs.  */
-  /* We may need to define a new flag for DSP ASE, and set this flag when
-     file_ase_dsp is true.  */
-  /* Same for DSP R2.  */
-  /* We may need to define a new flag for MT ASE, and set this flag when
-     file_ase_mt is true.  */
+  /* Set MIPS ELF flags for ASEs.  Note that not all ASEs have flags
+     defined at present; this might need to change in future.  */
   if (file_ase_mips16)
     elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ARCH_ASE_M16;
   if (file_ase_micromips)
@@ -18980,166 +19510,148 @@ s_mips_mask (int reg_type)
 static const struct mips_cpu_info mips_cpu_info_table[] =
 {
   /* Entries for generic ISAs */
-  { "mips1",          MIPS_CPU_IS_ISA,         ISA_MIPS1,      CPU_R3000 },
-  { "mips2",          MIPS_CPU_IS_ISA,         ISA_MIPS2,      CPU_R6000 },
-  { "mips3",          MIPS_CPU_IS_ISA,         ISA_MIPS3,      CPU_R4000 },
-  { "mips4",          MIPS_CPU_IS_ISA,         ISA_MIPS4,      CPU_R8000 },
-  { "mips5",          MIPS_CPU_IS_ISA,         ISA_MIPS5,      CPU_MIPS5 },
-  { "mips32",         MIPS_CPU_IS_ISA,         ISA_MIPS32,     CPU_MIPS32 },
-  { "mips32r2",       MIPS_CPU_IS_ISA,         ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "mips64",         MIPS_CPU_IS_ISA,         ISA_MIPS64,     CPU_MIPS64 },
-  { "mips64r2",       MIPS_CPU_IS_ISA,         ISA_MIPS64R2,   CPU_MIPS64R2 },
+  { "mips1",          MIPS_CPU_IS_ISA, 0,      ISA_MIPS1,    CPU_R3000 },
+  { "mips2",          MIPS_CPU_IS_ISA, 0,      ISA_MIPS2,    CPU_R6000 },
+  { "mips3",          MIPS_CPU_IS_ISA, 0,      ISA_MIPS3,    CPU_R4000 },
+  { "mips4",          MIPS_CPU_IS_ISA, 0,      ISA_MIPS4,    CPU_R8000 },
+  { "mips5",          MIPS_CPU_IS_ISA, 0,      ISA_MIPS5,    CPU_MIPS5 },
+  { "mips32",         MIPS_CPU_IS_ISA, 0,      ISA_MIPS32,   CPU_MIPS32 },
+  { "mips32r2",       MIPS_CPU_IS_ISA, 0,      ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "mips64",         MIPS_CPU_IS_ISA, 0,      ISA_MIPS64,   CPU_MIPS64 },
+  { "mips64r2",       MIPS_CPU_IS_ISA, 0,      ISA_MIPS64R2, CPU_MIPS64R2 },
 
   /* MIPS I */
-  { "r3000",          0,                       ISA_MIPS1,      CPU_R3000 },
-  { "r2000",          0,                       ISA_MIPS1,      CPU_R3000 },
-  { "r3900",          0,                       ISA_MIPS1,      CPU_R3900 },
+  { "r3000",          0, 0,                    ISA_MIPS1,    CPU_R3000 },
+  { "r2000",          0, 0,                    ISA_MIPS1,    CPU_R3000 },
+  { "r3900",          0, 0,                    ISA_MIPS1,    CPU_R3900 },
 
   /* MIPS II */
-  { "r6000",          0,                       ISA_MIPS2,      CPU_R6000 },
+  { "r6000",          0, 0,                    ISA_MIPS2,    CPU_R6000 },
 
   /* MIPS III */
-  { "r4000",          0,                       ISA_MIPS3,      CPU_R4000 },
-  { "r4010",          0,                       ISA_MIPS2,      CPU_R4010 },
-  { "vr4100",         0,                       ISA_MIPS3,      CPU_VR4100 },
-  { "vr4111",         0,                       ISA_MIPS3,      CPU_R4111 },
-  { "vr4120",         0,                       ISA_MIPS3,      CPU_VR4120 },
-  { "vr4130",         0,                       ISA_MIPS3,      CPU_VR4120 },
-  { "vr4181",         0,                       ISA_MIPS3,      CPU_R4111 },
-  { "vr4300",         0,                       ISA_MIPS3,      CPU_R4300 },
-  { "r4400",          0,                       ISA_MIPS3,      CPU_R4400 },
-  { "r4600",          0,                       ISA_MIPS3,      CPU_R4600 },
-  { "orion",          0,                       ISA_MIPS3,      CPU_R4600 },
-  { "r4650",          0,                       ISA_MIPS3,      CPU_R4650 },
+  { "r4000",          0, 0,                    ISA_MIPS3,    CPU_R4000 },
+  { "r4010",          0, 0,                    ISA_MIPS2,    CPU_R4010 },
+  { "vr4100",         0, 0,                    ISA_MIPS3,    CPU_VR4100 },
+  { "vr4111",         0, 0,                    ISA_MIPS3,    CPU_R4111 },
+  { "vr4120",         0, 0,                    ISA_MIPS3,    CPU_VR4120 },
+  { "vr4130",         0, 0,                    ISA_MIPS3,    CPU_VR4120 },
+  { "vr4181",         0, 0,                    ISA_MIPS3,    CPU_R4111 },
+  { "vr4300",         0, 0,                    ISA_MIPS3,    CPU_R4300 },
+  { "r4400",          0, 0,                    ISA_MIPS3,    CPU_R4400 },
+  { "r4600",          0, 0,                    ISA_MIPS3,    CPU_R4600 },
+  { "orion",          0, 0,                    ISA_MIPS3,    CPU_R4600 },
+  { "r4650",          0, 0,                    ISA_MIPS3,    CPU_R4650 },
+  { "r5900",          0, 0,                    ISA_MIPS3,    CPU_R5900 },
   /* ST Microelectronics Loongson 2E and 2F cores */
-  { "loongson2e",     0,                       ISA_MIPS3,   CPU_LOONGSON_2E },
-  { "loongson2f",     0,                       ISA_MIPS3,   CPU_LOONGSON_2F },
+  { "loongson2e",     0, 0,                    ISA_MIPS3,    CPU_LOONGSON_2E },
+  { "loongson2f",     0, 0,                    ISA_MIPS3,    CPU_LOONGSON_2F },
 
   /* MIPS IV */
-  { "r8000",          0,                       ISA_MIPS4,      CPU_R8000 },
-  { "r10000",         0,                       ISA_MIPS4,      CPU_R10000 },
-  { "r12000",         0,                       ISA_MIPS4,      CPU_R12000 },
-  { "r14000",         0,                       ISA_MIPS4,      CPU_R14000 },
-  { "r16000",         0,                       ISA_MIPS4,      CPU_R16000 },
-  { "vr5000",         0,                       ISA_MIPS4,      CPU_R5000 },
-  { "vr5400",         0,                       ISA_MIPS4,      CPU_VR5400 },
-  { "vr5500",         0,                       ISA_MIPS4,      CPU_VR5500 },
-  { "rm5200",         0,                       ISA_MIPS4,      CPU_R5000 },
-  { "rm5230",         0,                       ISA_MIPS4,      CPU_R5000 },
-  { "rm5231",         0,                       ISA_MIPS4,      CPU_R5000 },
-  { "rm5261",         0,                       ISA_MIPS4,      CPU_R5000 },
-  { "rm5721",         0,                       ISA_MIPS4,      CPU_R5000 },
-  { "rm7000",         0,                       ISA_MIPS4,      CPU_RM7000 },
-  { "rm9000",         0,                       ISA_MIPS4,      CPU_RM9000 },
+  { "r8000",          0, 0,                    ISA_MIPS4,    CPU_R8000 },
+  { "r10000",         0, 0,                    ISA_MIPS4,    CPU_R10000 },
+  { "r12000",         0, 0,                    ISA_MIPS4,    CPU_R12000 },
+  { "r14000",         0, 0,                    ISA_MIPS4,    CPU_R14000 },
+  { "r16000",         0, 0,                    ISA_MIPS4,    CPU_R16000 },
+  { "vr5000",         0, 0,                    ISA_MIPS4,    CPU_R5000 },
+  { "vr5400",         0, 0,                    ISA_MIPS4,    CPU_VR5400 },
+  { "vr5500",         0, 0,                    ISA_MIPS4,    CPU_VR5500 },
+  { "rm5200",         0, 0,                    ISA_MIPS4,    CPU_R5000 },
+  { "rm5230",         0, 0,                    ISA_MIPS4,    CPU_R5000 },
+  { "rm5231",         0, 0,                    ISA_MIPS4,    CPU_R5000 },
+  { "rm5261",         0, 0,                    ISA_MIPS4,    CPU_R5000 },
+  { "rm5721",         0, 0,                    ISA_MIPS4,    CPU_R5000 },
+  { "rm7000",         0, 0,                    ISA_MIPS4,    CPU_RM7000 },
+  { "rm9000",         0, 0,                    ISA_MIPS4,    CPU_RM9000 },
 
   /* MIPS 32 */
-  { "4kc",            0,                       ISA_MIPS32,     CPU_MIPS32 },
-  { "4km",            0,                       ISA_MIPS32,     CPU_MIPS32 },
-  { "4kp",            0,                       ISA_MIPS32,     CPU_MIPS32 },
-  { "4ksc",           MIPS_CPU_ASE_SMARTMIPS,  ISA_MIPS32,     CPU_MIPS32 },
+  { "4kc",            0, 0,                    ISA_MIPS32,   CPU_MIPS32 },
+  { "4km",            0, 0,                    ISA_MIPS32,   CPU_MIPS32 },
+  { "4kp",            0, 0,                    ISA_MIPS32,   CPU_MIPS32 },
+  { "4ksc",           0, ASE_SMARTMIPS,                ISA_MIPS32,   CPU_MIPS32 },
 
   /* MIPS 32 Release 2 */
-  { "4kec",           0,                       ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "4kem",           0,                       ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "4kep",           0,                       ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "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 },
-  { "24kf1_1",        0,                       ISA_MIPS32R2,   CPU_MIPS32R2 },
+  { "4kec",           0, 0,                    ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "4kem",           0, 0,                    ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "4kep",           0, 0,                    ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "4ksd",           0, ASE_SMARTMIPS,                ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "m4k",            0, 0,                    ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "m4kp",           0, 0,                    ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "m14k",           0, ASE_MCU,              ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "m14kc",          0, ASE_MCU,              ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "m14ke",          0, ASE_DSP | ASE_DSPR2 | ASE_MCU,
+                                               ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "m14kec",         0, ASE_DSP | ASE_DSPR2 | ASE_MCU,
+                                               ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "24kc",           0, 0,                    ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "24kf2_1",        0, 0,                    ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "24kf",           0, 0,                    ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "24kf1_1",        0, 0,                    ISA_MIPS32R2, CPU_MIPS32R2 },
   /* Deprecated forms of the above.  */
-  { "24kfx",          0,                       ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "24kx",           0,                       ISA_MIPS32R2,   CPU_MIPS32R2 },
+  { "24kfx",          0, 0,                    ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "24kx",           0, 0,                    ISA_MIPS32R2, CPU_MIPS32R2 },
   /* 24KE is a 24K with DSP ASE, other ASEs are optional.  */
-  { "24kec",          MIPS_CPU_ASE_DSP,                ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "24kef2_1",       MIPS_CPU_ASE_DSP,                ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "24kef",          MIPS_CPU_ASE_DSP,                ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "24kef1_1",       MIPS_CPU_ASE_DSP,                ISA_MIPS32R2,   CPU_MIPS32R2 },
+  { "24kec",          0, ASE_DSP,              ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "24kef2_1",       0, ASE_DSP,              ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "24kef",          0, ASE_DSP,              ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "24kef1_1",       0, ASE_DSP,              ISA_MIPS32R2, CPU_MIPS32R2 },
   /* Deprecated forms of the above.  */
-  { "24kefx",         MIPS_CPU_ASE_DSP,                ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "24kex",          MIPS_CPU_ASE_DSP,                ISA_MIPS32R2,   CPU_MIPS32R2 },
+  { "24kefx",         0, ASE_DSP,              ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "24kex",          0, ASE_DSP,              ISA_MIPS32R2, CPU_MIPS32R2 },
   /* 34K is a 24K with DSP and MT ASE, other ASEs are optional.  */
-  { "34kc",           MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_MT,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "34kf2_1",        MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_MT,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "34kf",           MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_MT,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "34kf1_1",        MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_MT,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
+  { "34kc",           0, ASE_DSP | ASE_MT,     ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "34kf2_1",        0, ASE_DSP | ASE_MT,     ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "34kf",           0, ASE_DSP | ASE_MT,     ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "34kf1_1",        0, ASE_DSP | ASE_MT,     ISA_MIPS32R2, CPU_MIPS32R2 },
   /* Deprecated forms of the above.  */
-  { "34kfx",          MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_MT,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "34kx",           MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_MT,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
+  { "34kfx",          0, ASE_DSP | ASE_MT,     ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "34kx",           0, ASE_DSP | ASE_MT,     ISA_MIPS32R2, CPU_MIPS32R2 },
   /* 34Kn is a 34kc without DSP.  */
-  { "34kn",           MIPS_CPU_ASE_MT,         ISA_MIPS32R2,   CPU_MIPS32R2 },
+  { "34kn",           0, ASE_MT,               ISA_MIPS32R2, CPU_MIPS32R2 },
   /* 74K with DSP and DSPR2 ASE, other ASEs are optional.  */
-  { "74kc",           MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_DSPR2,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "74kf2_1",        MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_DSPR2,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "74kf",           MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_DSPR2,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "74kf1_1",        MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_DSPR2,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "74kf3_2",        MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_DSPR2,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
+  { "74kc",           0, ASE_DSP | ASE_DSPR2,  ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "74kf2_1",        0, ASE_DSP | ASE_DSPR2,  ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "74kf",           0, ASE_DSP | ASE_DSPR2,  ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "74kf1_1",        0, ASE_DSP | ASE_DSPR2,  ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "74kf3_2",        0, ASE_DSP | ASE_DSPR2,  ISA_MIPS32R2, CPU_MIPS32R2 },
   /* Deprecated forms of the above.  */
-  { "74kfx",          MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_DSPR2,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "74kx",           MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_DSPR2,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
+  { "74kfx",          0, ASE_DSP | ASE_DSPR2,  ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "74kx",           0, ASE_DSP | ASE_DSPR2,  ISA_MIPS32R2, CPU_MIPS32R2 },
   /* 1004K cores are multiprocessor versions of the 34K.  */
-  { "1004kc",         MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_MT,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "1004kf2_1",      MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_MT,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "1004kf",         MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_MT,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "1004kf1_1",      MIPS_CPU_ASE_DSP | MIPS_CPU_ASE_MT,
-                                               ISA_MIPS32R2,   CPU_MIPS32R2 },
+  { "1004kc",         0, ASE_DSP | ASE_MT,     ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "1004kf2_1",      0, ASE_DSP | ASE_MT,     ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "1004kf",         0, ASE_DSP | ASE_MT,     ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "1004kf1_1",      0, ASE_DSP | ASE_MT,     ISA_MIPS32R2, CPU_MIPS32R2 },
 
   /* MIPS 64 */
-  { "5kc",            0,                       ISA_MIPS64,     CPU_MIPS64 },
-  { "5kf",            0,                       ISA_MIPS64,     CPU_MIPS64 },
-  { "20kc",           MIPS_CPU_ASE_MIPS3D,     ISA_MIPS64,     CPU_MIPS64 },
-  { "25kf",           MIPS_CPU_ASE_MIPS3D,     ISA_MIPS64,     CPU_MIPS64 },
+  { "5kc",            0, 0,                    ISA_MIPS64,   CPU_MIPS64 },
+  { "5kf",            0, 0,                    ISA_MIPS64,   CPU_MIPS64 },
+  { "20kc",           0, ASE_MIPS3D,           ISA_MIPS64,   CPU_MIPS64 },
+  { "25kf",           0, ASE_MIPS3D,           ISA_MIPS64,   CPU_MIPS64 },
 
   /* Broadcom SB-1 CPU core */
-  { "sb1",            MIPS_CPU_ASE_MIPS3D | MIPS_CPU_ASE_MDMX,
-                                               ISA_MIPS64,     CPU_SB1 },
+  { "sb1",            0, ASE_MIPS3D | ASE_MDMX,        ISA_MIPS64,   CPU_SB1 },
   /* Broadcom SB-1A CPU core */
-  { "sb1a",           MIPS_CPU_ASE_MIPS3D | MIPS_CPU_ASE_MDMX,
-                                               ISA_MIPS64,     CPU_SB1 },
+  { "sb1a",           0, ASE_MIPS3D | ASE_MDMX,        ISA_MIPS64,   CPU_SB1 },
   
-  { "loongson3a",     0,                       ISA_MIPS64,     CPU_LOONGSON_3A },
+  { "loongson3a",     0, 0,                    ISA_MIPS64,   CPU_LOONGSON_3A },
 
   /* MIPS 64 Release 2 */
 
   /* Cavium Networks Octeon CPU core */
-  { "octeon",        0,      ISA_MIPS64R2,   CPU_OCTEON },
-  { "octeon+",       0,      ISA_MIPS64R2,   CPU_OCTEONP },
-  { "octeon2",       0,      ISA_MIPS64R2,   CPU_OCTEON2 },
+  { "octeon",        0, 0,                     ISA_MIPS64R2, CPU_OCTEON },
+  { "octeon+",       0, 0,                     ISA_MIPS64R2, CPU_OCTEONP },
+  { "octeon2",       0, 0,                     ISA_MIPS64R2, CPU_OCTEON2 },
 
   /* RMI Xlr */
-  { "xlr",           0,      ISA_MIPS64,     CPU_XLR },
+  { "xlr",           0, 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 },
+  { "xlp",           0, 0,                     ISA_MIPS64R2, CPU_XLR },
 
   /* End marker */
-  { NULL, 0, 0, 0 }
+  { NULL, 0, 0, 0, 0 }
 };
 
 
@@ -19363,6 +19875,9 @@ MIPS options:\n\
 -mmcu                  generate MCU instructions\n\
 -mno-mcu               do not generate MCU instructions\n"));
   fprintf (stream, _("\
+-mvirt                 generate Virtualization instructions\n\
+-mno-virt              do not generate Virtualization 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\
@@ -19381,7 +19896,8 @@ MIPS options:\n\
 -msoft-float           do not allow floating-point instructions\n\
 -msingle-float         only allow 32-bit floating-point operations\n\
 -mdouble-float         allow 32-bit and 64-bit floating-point operations\n\
---[no-]construct-floats [dis]allow floating point values to be constructed\n"
+--[no-]construct-floats        [dis]allow floating point values to be constructed\n\
+--[no-]relax-branch    [dis]allow out-of-range branches to be relaxed\n"
                     ));
 #ifdef OBJ_ELF
   fprintf (stream, _("\
This page took 0.066007 seconds and 4 git commands to generate.