[ bfd/ChangeLog ]
[deliverable/binutils-gdb.git] / gas / config / tc-mips.c
index d19a14987c25f1e77b7dc65f9a45d1dbc2a6ab08..788a34b5ba6130f9be3bd02faff5909e5d74095d 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 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    Contributed by the OSF and Ralph Campbell.
    Written by Keith Knowles and Ralph Campbell, working independently.
    Modified for ECOFF and R4000 support by Ian Lance Taylor of Cygnus
@@ -28,8 +28,6 @@
 #include "subsegs.h"
 #include "safe-ctype.h"
 
-#include <stdarg.h>
-
 #include "opcode/mips.h"
 #include "itbl-ops.h"
 #include "dwarf2dbg.h"
@@ -262,6 +260,11 @@ static int file_mips_isa = ISA_UNKNOWN;
    command line (e.g., by -march).  */
 static int file_ase_mips16;
 
+#define ISA_SUPPORTS_MIPS16E (mips_opts.isa == ISA_MIPS32              \
+                             || mips_opts.isa == ISA_MIPS32R2          \
+                             || mips_opts.isa == ISA_MIPS64            \
+                             || mips_opts.isa == ISA_MIPS64R2)
+
 /* True if -mips3d was passed or implied by arguments passed on the
    command line (e.g., by -march).  */
 static int file_ase_mips3d;
@@ -284,6 +287,8 @@ static int file_ase_dsp;
 #define ISA_SUPPORTS_DSP_ASE (mips_opts.isa == ISA_MIPS32R2            \
                              || mips_opts.isa == ISA_MIPS64R2)
 
+#define ISA_SUPPORTS_DSP64_ASE (mips_opts.isa == ISA_MIPS64R2)
+
 /* True if -mmt was passed or implied by arguments passed on the
    command line (e.g., by -march).  */
 static int file_ase_mt;
@@ -401,22 +406,6 @@ static int mips_32bitmode = 0;
    (strncmp (TARGET_CPU, "mips16", sizeof ("mips16") - 1) == 0         \
     || strncmp (TARGET_CANONICAL, "mips-lsi-elf", sizeof ("mips-lsi-elf") - 1) == 0)
 
-/* Return true if the given CPU supports the MIPS3D ASE.  */
-#define CPU_HAS_MIPS3D(cpu)    ((cpu) == CPU_SB1      \
-                                )
-
-/* Return true if the given CPU supports the MDMX ASE.  */
-#define CPU_HAS_MDMX(cpu)      (FALSE                 \
-                                )
-
-/* Return true if the given CPU supports the DSP ASE.  */
-#define CPU_HAS_DSP(cpu)       (FALSE                 \
-                                )
-
-/* Return true if the given CPU supports the MT ASE.  */
-#define CPU_HAS_MT(cpu)                (FALSE                 \
-                                )
-
 /* True if CPU has a dror instruction.  */
 #define CPU_HAS_DROR(CPU)      ((CPU) == CPU_VR5400 || (CPU) == CPU_VR5500)
 
@@ -1114,6 +1103,8 @@ static const pseudo_typeS mips_pseudo_table[] =
   {"half", s_cons, 1},
   {"dword", s_cons, 3},
   {"weakext", s_mips_weakext, 0},
+  {"origin", s_org, 0},
+  {"repeat", s_rept, 0},
 
   /* These pseudo-ops are defined in read.c, but must be overridden
      here for one reason or another.  */
@@ -1177,8 +1168,8 @@ struct insn_label_list
   symbolS *label;
 };
 
-static struct insn_label_list *insn_labels;
 static struct insn_label_list *free_insn_labels;
+#define label_list tc_segment_info_data
 
 static void mips_clear_insn_labels (void);
 
@@ -1186,12 +1177,19 @@ static inline void
 mips_clear_insn_labels (void)
 {
   register struct insn_label_list **pl;
+  segment_info_type *si;
 
-  for (pl = &free_insn_labels; *pl != NULL; pl = &(*pl)->next)
-    ;
-  *pl = insn_labels;
-  insn_labels = NULL;
+  if (now_seg)
+    {
+      for (pl = &free_insn_labels; *pl != NULL; pl = &(*pl)->next)
+       ;
+      
+      si = seg_info (now_seg);
+      *pl = si->label_list;
+      si->label_list = NULL;
+    }
 }
+
 \f
 static char *expr_end;
 
@@ -1729,7 +1727,7 @@ reg_lookup (char **s, unsigned int types, unsigned int *regnop)
 void
 md_begin (void)
 {
-  register const char *retval = NULL;
+  const char *retval = NULL;
   int i = 0;
   int broken = 0;
 
@@ -1840,7 +1838,7 @@ md_begin (void)
   bfd_set_gp_size (stdoutput, g_switch_value);
 
 #ifdef OBJ_ELF
-  if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+  if (IS_ELF)
     {
       /* On a native system other than VxWorks, sections must be aligned
         to 16 byte boundaries.  When configured for an embedded ELF
@@ -1913,7 +1911,7 @@ md_begin (void)
                                          SEC_HAS_CONTENTS | SEC_READONLY);
            (void) bfd_set_section_alignment (stdoutput, sec, 2);
          }
-       else if (OUTPUT_FLAVOR == bfd_target_elf_flavour && mips_flag_pdr)
+       else if (mips_flag_pdr)
          {
            pdr_seg = subseg_new (".pdr", (subsegT) 0);
            (void) bfd_set_section_flags (stdoutput, pdr_seg,
@@ -2124,10 +2122,11 @@ reg_needs_delay (unsigned int reg)
 static void
 mips_move_labels (void)
 {
+  segment_info_type *si = seg_info (now_seg);
   struct insn_label_list *l;
   valueT val;
 
-  for (l = insn_labels; l != NULL; l = l->next)
+  for (l = si->label_list; l != NULL; l = l->next)
     {
       assert (S_GET_SEGMENT (l->label) == now_seg);
       symbol_set_frag (l->label, frag_now);
@@ -2139,6 +2138,28 @@ mips_move_labels (void)
     }
 }
 
+static bfd_boolean
+s_is_linkonce (symbolS *sym, segT from_seg)
+{
+  bfd_boolean linkonce = FALSE;
+  segT symseg = S_GET_SEGMENT (sym);
+
+  if (symseg != from_seg && !S_IS_LOCAL (sym))
+    {
+      if ((bfd_get_section_flags (stdoutput, symseg) & SEC_LINK_ONCE))
+       linkonce = TRUE;
+#ifdef OBJ_ELF
+      /* The GNU toolchain uses an extension for ELF: a section
+        beginning with the magic string .gnu.linkonce is a
+        linkonce section.  */
+      if (strncmp (segment_name (symseg), ".gnu.linkonce",
+                  sizeof ".gnu.linkonce" - 1) == 0)
+       linkonce = TRUE;
+#endif
+    }
+  return linkonce;
+}
+
 /* Mark instruction labels in mips16 mode.  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
@@ -2150,21 +2171,29 @@ mips_move_labels (void)
 static void
 mips16_mark_labels (void)
 {
-  if (mips_opts.mips16)
-    {
-      struct insn_label_list *l;
-      valueT val;
+  segment_info_type *si = seg_info (now_seg);
+  struct insn_label_list *l;
 
-      for (l = insn_labels; l != NULL; l = l->next)
-       {
-#ifdef OBJ_ELF
-         if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
-           S_SET_OTHER (l->label, STO_MIPS16);
+  if (!mips_opts.mips16)
+    return;
+
+  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)
+       S_SET_OTHER (label, STO_MIPS16);
 #endif
-         val = S_GET_VALUE (l->label);
-         if ((val & 1) == 0)
-           S_SET_VALUE (l->label, val + 1);
-       }
+      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.  */
+         && ! S_IS_WEAK (label)
+         && ! S_IS_EXTERNAL (label)
+         && ! s_is_linkonce (label, now_seg))
+       S_SET_VALUE (label, S_GET_VALUE (label) | 1);
     }
 }
 
@@ -2489,9 +2518,10 @@ static void
 append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
             bfd_reloc_code_real_type *reloc_type)
 {
-  register unsigned long prev_pinfo, pinfo;
+  unsigned long prev_pinfo, pinfo;
   relax_stateT prev_insn_frag_type = 0;
   bfd_boolean relaxed_branch = FALSE;
+  segment_info_type *si = seg_info (now_seg);
 
   /* Mark instruction labels in mips16 mode.  */
   mips16_mark_labels ();
@@ -2908,7 +2938,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
                 whether there is a label on this instruction.  If
                 there are any branches to anything other than a
                 label, users must use .set noreorder.  */
-             || insn_labels != NULL
+             || si->label_list != NULL
              /* If the previous instruction is in a variant frag
                 other than this branch's one, we cannot do the swap.
                 This does not apply to the mips16, which uses variant
@@ -3015,10 +3045,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
              if (mips_opts.mips16
                  && (pinfo & INSN_UNCOND_BRANCH_DELAY)
                  && (pinfo & (MIPS16_INSN_READ_X | MIPS16_INSN_READ_31))
-                 && (mips_opts.isa == ISA_MIPS32
-                     || mips_opts.isa == ISA_MIPS32R2
-                     || mips_opts.isa == ISA_MIPS64
-                     || mips_opts.isa == ISA_MIPS64R2))
+                 && ISA_SUPPORTS_MIPS16E)
                {
                  /* Convert MIPS16 jr/jalr into a "compact" jump.  */
                  ip->insn_opcode |= 0x0080;
@@ -3301,7 +3328,7 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
   assert (strcmp (name, mo->name) == 0);
 
   /* Search until we get a match for NAME.  It is assumed here that
-     macros will never generate MDMX or MIPS-3D instructions.  */
+     macros will never generate MDMX, MIPS-3D, DSP or MT instructions.  */
   while (strcmp (fmt, mo->args) != 0
         || mo->pinfo == INSN_MACRO
         || !OPCODE_IS_MEMBER (mo,
@@ -3488,11 +3515,11 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
          continue;
 
        case 'C':
-         insn.insn_opcode |= va_arg (args, unsigned long);
+         INSERT_OPERAND (COPZ, insn, va_arg (args, unsigned long));
          continue;
 
        case 'k':
-         insn.insn_opcode |= va_arg (args, unsigned long) << OP_SH_CACHE;
+         INSERT_OPERAND (CACHE, insn, va_arg (args, unsigned long));
          continue;
 
        default:
@@ -3576,7 +3603,7 @@ mips16_macro_build (expressionS *ep, const char *name, const char *fmt,
 
            regno = va_arg (args, int);
            regno = ((regno & 7) << 2) | ((regno & 0x18) >> 3);
-           insn.insn_opcode |= regno << MIPS16OP_SH_REG32R;
+           MIPS16_INSERT_OPERAND (REG32R, insn, regno);
          }
          continue;
 
@@ -4469,7 +4496,7 @@ add_got_offset_hilo (int dest, expressionS *local, int tmp)
 static void
 macro (struct mips_cl_insn *ip)
 {
-  register int treg, sreg, dreg, breg;
+  int treg, sreg, dreg, breg;
   int tempreg;
   int mask;
   int used_at = 0;
@@ -7073,7 +7100,7 @@ macro (struct mips_cl_insn *ip)
 static void
 macro2 (struct mips_cl_insn *ip)
 {
-  register int treg, sreg, dreg, breg;
+  int treg, sreg, dreg, breg;
   int tempreg;
   int mask;
   int used_at;
@@ -8371,6 +8398,8 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                             | (file_ase_mips16 ? INSN_MIPS16 : 0)
                             | (mips_opts.ase_mdmx ? INSN_MDMX : 0)
                             | (mips_opts.ase_dsp ? INSN_DSP : 0)
+                            | ((mips_opts.ase_dsp && ISA_SUPPORTS_DSP64_ASE)
+                               ? INSN_DSP64 : 0)
                             | (mips_opts.ase_mt ? INSN_MT : 0)
                             | (mips_opts.ase_mips3d ? INSN_MIPS3D : 0)
                             | (mips_opts.ase_smartmips ? INSN_SMARTMIPS : 0)),
@@ -8431,11 +8460,10 @@ mips_ip (char *str, struct mips_cl_insn *ip)
              check_absolute_expr (ip, &imm_expr);
              if (imm_expr.X_add_number & ~OP_MASK_SA3)
                {
-                 as_warn (_("DSP immediate not in range 0..%d (%lu)"),
-                          OP_MASK_SA3, (unsigned long) imm_expr.X_add_number);
-                 imm_expr.X_add_number &= OP_MASK_SA3;
+                 as_bad (_("DSP immediate not in range 0..%d (%lu)"),
+                         OP_MASK_SA3, (unsigned long) imm_expr.X_add_number);
                }
-             ip->insn_opcode |= imm_expr.X_add_number << OP_SH_SA3;
+             INSERT_OPERAND (SA3, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
              s = expr_end;
              continue;
@@ -8445,11 +8473,10 @@ mips_ip (char *str, struct mips_cl_insn *ip)
              check_absolute_expr (ip, &imm_expr);
              if (imm_expr.X_add_number & ~OP_MASK_SA4)
                {
-                 as_warn (_("DSP immediate not in range 0..%d (%lu)"),
-                          OP_MASK_SA4, (unsigned long) imm_expr.X_add_number);
-                 imm_expr.X_add_number &= OP_MASK_SA4;
+                 as_bad (_("DSP immediate not in range 0..%d (%lu)"),
+                         OP_MASK_SA4, (unsigned long) imm_expr.X_add_number);
                }
-             ip->insn_opcode |= imm_expr.X_add_number << OP_SH_SA4;
+             INSERT_OPERAND (SA4, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
              s = expr_end;
              continue;
@@ -8459,11 +8486,10 @@ mips_ip (char *str, struct mips_cl_insn *ip)
              check_absolute_expr (ip, &imm_expr);
              if (imm_expr.X_add_number & ~OP_MASK_IMM8)
                {
-                 as_warn (_("DSP immediate not in range 0..%d (%lu)"),
-                          OP_MASK_IMM8, (unsigned long) imm_expr.X_add_number);
-                 imm_expr.X_add_number &= OP_MASK_IMM8;
+                 as_bad (_("DSP immediate not in range 0..%d (%lu)"),
+                         OP_MASK_IMM8, (unsigned long) imm_expr.X_add_number);
                }
-             ip->insn_opcode |= imm_expr.X_add_number << OP_SH_IMM8;
+             INSERT_OPERAND (IMM8, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
              s = expr_end;
              continue;
@@ -8473,11 +8499,10 @@ mips_ip (char *str, struct mips_cl_insn *ip)
              check_absolute_expr (ip, &imm_expr);
              if (imm_expr.X_add_number & ~OP_MASK_RS)
                {
-                 as_warn (_("DSP immediate not in range 0..%d (%lu)"),
-                          OP_MASK_RS, (unsigned long) imm_expr.X_add_number);
-                 imm_expr.X_add_number &= OP_MASK_RS;
+                 as_bad (_("DSP immediate not in range 0..%d (%lu)"),
+                         OP_MASK_RS, (unsigned long) imm_expr.X_add_number);
                }
-             ip->insn_opcode |= imm_expr.X_add_number << OP_SH_RS;
+             INSERT_OPERAND (RS, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
              s = expr_end;
              continue;
@@ -8488,7 +8513,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                {
                  regno = s[3] - '0';
                  s += 4;
-                 ip->insn_opcode |= regno << OP_SH_DSPACC;
+                 INSERT_OPERAND (DSPACC, *ip, regno);
                  continue;
                }
              else
@@ -8500,12 +8525,11 @@ mips_ip (char *str, struct mips_cl_insn *ip)
              check_absolute_expr (ip, &imm_expr);
              if (imm_expr.X_add_number & ~OP_MASK_WRDSP)
                {
-                 as_warn (_("DSP immediate not in range 0..%d (%lu)"),
-                          OP_MASK_WRDSP,
-                          (unsigned long) imm_expr.X_add_number);
-                 imm_expr.X_add_number &= OP_MASK_WRDSP;
+                 as_bad (_("DSP immediate not in range 0..%d (%lu)"),
+                         OP_MASK_WRDSP,
+                         (unsigned long) imm_expr.X_add_number);
                }
-             ip->insn_opcode |= imm_expr.X_add_number << OP_SH_WRDSP;
+             INSERT_OPERAND (WRDSP, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
              s = expr_end;
              continue;
@@ -8516,7 +8540,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                {
                  regno = s[3] - '0';
                  s += 4;
-                 ip->insn_opcode |= regno << OP_SH_DSPACC_S;
+                 INSERT_OPERAND (DSPACC_S, *ip, regno);
                  continue;
                }
              else
@@ -8531,13 +8555,11 @@ mips_ip (char *str, struct mips_cl_insn *ip)
              if (imm_expr.X_add_number < min_range ||
                  imm_expr.X_add_number > max_range)
                {
-                 as_warn (_("DSP immediate not in range %ld..%ld (%ld)"),
-                          (long) min_range, (long) max_range,
-                          (long) imm_expr.X_add_number);
+                 as_bad (_("DSP immediate not in range %ld..%ld (%ld)"),
+                         (long) min_range, (long) max_range,
+                         (long) imm_expr.X_add_number);
                }
-             imm_expr.X_add_number &= OP_MASK_DSPSFT;
-             ip->insn_opcode |= ((unsigned long) imm_expr.X_add_number
-                                 << OP_SH_DSPSFT);
+             INSERT_OPERAND (DSPSFT, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
              s = expr_end;
              continue;
@@ -8547,12 +8569,11 @@ mips_ip (char *str, struct mips_cl_insn *ip)
              check_absolute_expr (ip, &imm_expr);
              if (imm_expr.X_add_number & ~OP_MASK_RDDSP)
                {
-                 as_warn (_("DSP immediate not in range 0..%d (%lu)"),
-                          OP_MASK_RDDSP,
-                          (unsigned long) imm_expr.X_add_number);
-                 imm_expr.X_add_number &= OP_MASK_RDDSP;
+                 as_bad (_("DSP immediate not in range 0..%d (%lu)"),
+                         OP_MASK_RDDSP,
+                         (unsigned long) imm_expr.X_add_number);
                }
-             ip->insn_opcode |= imm_expr.X_add_number << OP_SH_RDDSP;
+             INSERT_OPERAND (RDDSP, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
              s = expr_end;
              continue;
@@ -8565,13 +8586,11 @@ mips_ip (char *str, struct mips_cl_insn *ip)
              if (imm_expr.X_add_number < min_range ||
                  imm_expr.X_add_number > max_range)
                {
-                 as_warn (_("DSP immediate not in range %ld..%ld (%ld)"),
-                          (long) min_range, (long) max_range,
-                          (long) imm_expr.X_add_number);
+                 as_bad (_("DSP immediate not in range %ld..%ld (%ld)"),
+                         (long) min_range, (long) max_range,
+                         (long) imm_expr.X_add_number);
                }
-             imm_expr.X_add_number &= OP_MASK_DSPSFT_7;
-             ip->insn_opcode |= ((unsigned long) imm_expr.X_add_number
-                                 << OP_SH_DSPSFT_7);
+             INSERT_OPERAND (DSPSFT_7, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
              s = expr_end;
              continue;
@@ -8584,41 +8603,33 @@ mips_ip (char *str, struct mips_cl_insn *ip)
              if (imm_expr.X_add_number < min_range ||
                  imm_expr.X_add_number > max_range)
                {
-                 as_warn (_("DSP immediate not in range %ld..%ld (%ld)"),
-                          (long) min_range, (long) max_range,
-                          (long) imm_expr.X_add_number);
+                 as_bad (_("DSP immediate not in range %ld..%ld (%ld)"),
+                         (long) min_range, (long) max_range,
+                         (long) imm_expr.X_add_number);
                }
-             imm_expr.X_add_number &= OP_MASK_IMM10;
-             ip->insn_opcode |= ((unsigned long) imm_expr.X_add_number
-                                 << OP_SH_IMM10);
+             INSERT_OPERAND (IMM10, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
              s = expr_end;
              continue;
 
-            case '!': /* mt 1-bit unsigned immediate in bit 5 */
+            case '!': /* MT usermode flag bit.  */
              my_getExpression (&imm_expr, s);
              check_absolute_expr (ip, &imm_expr);
              if (imm_expr.X_add_number & ~OP_MASK_MT_U)
-               {
-                 as_warn (_("MT immediate not in range 0..%d (%lu)"),
-                          OP_MASK_MT_U, (unsigned long) imm_expr.X_add_number);
-                 imm_expr.X_add_number &= OP_MASK_MT_U;
-               }
-             ip->insn_opcode |= imm_expr.X_add_number << OP_SH_MT_U;
+               as_bad (_("MT usermode bit not 0 or 1 (%lu)"),
+                       (unsigned long) imm_expr.X_add_number);
+             INSERT_OPERAND (MT_U, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
              s = expr_end;
              continue;
 
-            case '$': /* mt 1-bit unsigned immediate in bit 4 */
+            case '$': /* MT load high flag bit.  */
              my_getExpression (&imm_expr, s);
              check_absolute_expr (ip, &imm_expr);
              if (imm_expr.X_add_number & ~OP_MASK_MT_H)
-               {
-                 as_warn (_("MT immediate not in range 0..%d (%lu)"),
-                          OP_MASK_MT_H, (unsigned long) imm_expr.X_add_number);
-                 imm_expr.X_add_number &= OP_MASK_MT_H;
-               }
-             ip->insn_opcode |= imm_expr.X_add_number << OP_SH_MT_H;
+               as_bad (_("MT load high bit not 0 or 1 (%lu)"),
+                       (unsigned long) imm_expr.X_add_number);
+             INSERT_OPERAND (MT_H, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
              s = expr_end;
              continue;
@@ -8629,7 +8640,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                {
                  regno = s[3] - '0';
                  s += 4;
-                 ip->insn_opcode |= regno << OP_SH_MTACC_T;
+                 INSERT_OPERAND (MTACC_T, *ip, regno);
                  continue;
                }
              else
@@ -8642,7 +8653,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
                {
                  regno = s[3] - '0';
                  s += 4;
-                 ip->insn_opcode |= regno << OP_SH_MTACC_D;
+                 INSERT_OPERAND (MTACC_D, *ip, regno);
                  continue;
                }
              else
@@ -8650,6 +8661,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
              break;
 
            case ',':
+             ++argnum;
              if (*s++ == *args)
                continue;
              s--;
@@ -8849,7 +8861,7 @@ do_msbd:
                        as_bad (_("Invalid register number (%d)"), regno);
                      else
                        {
-                         ip->insn_opcode |= regno << OP_SH_RT;
+                         INSERT_OPERAND (RT, *ip, regno);
                          continue;
                        }
                    }
@@ -8912,8 +8924,9 @@ do_msbd:
            case 'c':           /* break code */
              my_getExpression (&imm_expr, s);
              check_absolute_expr (ip, &imm_expr);
-             if ((unsigned long) imm_expr.X_add_number > 1023)
-               as_warn (_("Illegal break code (%lu)"),
+             if ((unsigned long) imm_expr.X_add_number > OP_MASK_CODE)
+               as_warn (_("Code for %s not in range 0..1023 (%lu)"),
+                        ip->insn_mo->name,
                         (unsigned long) imm_expr.X_add_number);
              INSERT_OPERAND (CODE, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
@@ -8923,8 +8936,9 @@ do_msbd:
            case 'q':           /* lower break code */
              my_getExpression (&imm_expr, s);
              check_absolute_expr (ip, &imm_expr);
-             if ((unsigned long) imm_expr.X_add_number > 1023)
-               as_warn (_("Illegal lower break code (%lu)"),
+             if ((unsigned long) imm_expr.X_add_number > OP_MASK_CODE2)
+               as_warn (_("Lower code for %s not in range 0..1023 (%lu)"),
+                        ip->insn_mo->name,
                         (unsigned long) imm_expr.X_add_number);
              INSERT_OPERAND (CODE2, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
@@ -8935,7 +8949,8 @@ do_msbd:
              my_getExpression (&imm_expr, s);
              check_absolute_expr (ip, &imm_expr);
              if ((unsigned long) imm_expr.X_add_number > OP_MASK_CODE20)
-               as_warn (_("Illegal 20-bit code (%lu)"),
+               as_warn (_("Code for %s not in range 0..1048575 (%lu)"),
+                        ip->insn_mo->name,
                         (unsigned long) imm_expr.X_add_number);
              INSERT_OPERAND (CODE20, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
@@ -8945,13 +8960,13 @@ do_msbd:
            case 'C':           /* Coprocessor code */
              my_getExpression (&imm_expr, s);
              check_absolute_expr (ip, &imm_expr);
-             if ((unsigned long) imm_expr.X_add_number >= (1 << 25))
+             if ((unsigned long) imm_expr.X_add_number > OP_MASK_COPZ)
                {
                  as_warn (_("Coproccesor code > 25 bits (%lu)"),
                           (unsigned long) imm_expr.X_add_number);
-                 imm_expr.X_add_number &= ((1 << 25) - 1);
+                 imm_expr.X_add_number &= OP_MASK_COPZ;
                }
-             ip->insn_opcode |= imm_expr.X_add_number;
+             INSERT_OPERAND (COPZ, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
              s = expr_end;
              continue;
@@ -8960,8 +8975,11 @@ do_msbd:
              my_getExpression (&imm_expr, s);
              check_absolute_expr (ip, &imm_expr);
              if ((unsigned long) imm_expr.X_add_number > OP_MASK_CODE19)
-               as_warn (_("Illegal 19-bit code (%lu)"),
-                        (unsigned long) imm_expr.X_add_number);
+               {
+                 as_warn (_("Illegal 19-bit code (%lu)"),
+                          (unsigned long) imm_expr.X_add_number);
+                 imm_expr.X_add_number &= OP_MASK_CODE19;
+               }
              INSERT_OPERAND (CODE19, *ip, imm_expr.X_add_number);
              imm_expr.X_op = O_absent;
              s = expr_end;
@@ -8983,7 +9001,7 @@ do_msbd:
                ok = reg_lookup (&s, RTYPE_NUM | RTYPE_CP0, &regno);
              else
                ok = reg_lookup (&s, RTYPE_NUM | RTYPE_GP, &regno);
-             ip->insn_opcode |= regno << OP_SH_RD;
+             INSERT_OPERAND (RD, *ip, regno);
              if (ok) 
                {
                  lastregno = regno;
@@ -9410,15 +9428,14 @@ do_msbd:
                        break;
                      }
                    new_seg = subseg_new (newname, (subsegT) 0);
-                   if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+                   if (IS_ELF)
                      bfd_set_section_flags (stdoutput, new_seg,
                                             (SEC_ALLOC
                                              | SEC_LOAD
                                              | SEC_READONLY
                                              | SEC_DATA));
                    frag_align (*args == 'l' ? 2 : 3, 0, 0);
-                   if (OUTPUT_FLAVOR == bfd_target_elf_flavour
-                       && strcmp (TARGET_OS, "elf") != 0)
+                   if (IS_ELF && strcmp (TARGET_OS, "elf") != 0)
                      record_alignment (new_seg, 4);
                    else
                      record_alignment (new_seg, *args == 'l' ? 2 : 3);
@@ -9857,9 +9874,9 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
                  if (c == 'v' || c == 'w')
                    {
                      if (c == 'v')
-                       ip->insn_opcode |= lastregno << MIPS16OP_SH_RX;
+                       MIPS16_INSERT_OPERAND (RX, *ip, lastregno);
                      else
-                       ip->insn_opcode |= lastregno << MIPS16OP_SH_RY;
+                       MIPS16_INSERT_OPERAND (RY, *ip, lastregno);
                      ++args;
                      continue;
                    }
@@ -10396,7 +10413,7 @@ mips16_immed (char *file, unsigned int line, int type, offsetT val,
              unsigned long *insn, bfd_boolean *use_extend,
              unsigned short *extend)
 {
-  register const struct mips16_immed_operand *op;
+  const struct mips16_immed_operand *op;
   int mintiny, maxtiny;
   bfd_boolean needext;
 
@@ -11153,7 +11170,7 @@ md_parse_option (int c, char *arg)
         select SVR4_PIC, and -non_shared to select no PIC.  This is
         intended to be compatible with Irix 5.  */
     case OPTION_CALL_SHARED:
-      if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+      if (!IS_ELF)
        {
          as_bad (_("-call_shared is supported only for ELF format"));
          return 0;
@@ -11163,7 +11180,7 @@ md_parse_option (int c, char *arg)
       break;
 
     case OPTION_NON_SHARED:
-      if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+      if (!IS_ELF)
        {
          as_bad (_("-non_shared is supported only for ELF format"));
          return 0;
@@ -11189,7 +11206,7 @@ md_parse_option (int c, char *arg)
       /* The -32, -n32 and -64 options are shortcuts for -mabi=32, -mabi=n32
         and -mabi=64.  */
     case OPTION_32:
-      if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+      if (!IS_ELF)
        {
          as_bad (_("-32 is supported for ELF format only"));
          return 0;
@@ -11198,7 +11215,7 @@ md_parse_option (int c, char *arg)
       break;
 
     case OPTION_N32:
-      if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+      if (!IS_ELF)
        {
          as_bad (_("-n32 is supported for ELF format only"));
          return 0;
@@ -11207,13 +11224,13 @@ md_parse_option (int c, char *arg)
       break;
 
     case OPTION_64:
-      if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+      if (!IS_ELF)
        {
          as_bad (_("-64 is supported for ELF format only"));
          return 0;
        }
       mips_abi = N64_ABI;
-      if (! support_64bit_objects())
+      if (!support_64bit_objects())
        as_fatal (_("No compiled in support for 64 bit object file format"));
       break;
 #endif /* OBJ_ELF */
@@ -11236,7 +11253,7 @@ md_parse_option (int c, char *arg)
 
 #ifdef OBJ_ELF
     case OPTION_MABI:
-      if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+      if (!IS_ELF)
        {
          as_bad (_("-mabi is supported for ELF format only"));
          return 0;
@@ -11463,15 +11480,13 @@ mips_after_parse_args (void)
   if (mips_opts.mips16 == -1)
     mips_opts.mips16 = (CPU_HAS_MIPS16 (file_mips_arch)) ? 1 : 0;
   if (mips_opts.ase_mips3d == -1)
-    mips_opts.ase_mips3d = ((CPU_HAS_MIPS3D (file_mips_arch)
-                            || (arch_info->flags & MIPS_CPU_ASE_MIPS3D))
+    mips_opts.ase_mips3d = ((arch_info->flags & MIPS_CPU_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 = ((CPU_HAS_MDMX (file_mips_arch)
-                          || (arch_info->flags & MIPS_CPU_ASE_MDMX))
+    mips_opts.ase_mdmx = ((arch_info->flags & MIPS_CPU_ASE_MDMX)
                          && file_mips_fp32 == 0) ? 1 : 0;
   if (mips_opts.ase_mdmx && file_mips_fp32 == 1)
     as_bad (_("-mfp32 used with -mdmx"));
@@ -11720,7 +11735,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 
   buf = (bfd_byte *) (fixP->fx_frag->fr_literal + fixP->fx_where);
 
-  assert (! fixP->fx_pcrel || fixP->fx_r_type == BFD_RELOC_16_PCREL_S2);
+  assert (!fixP->fx_pcrel || fixP->fx_r_type == BFD_RELOC_16_PCREL_S2);
 
   /* Don't treat parts of a composite relocation as done.  There are two
      reasons for this:
@@ -11732,7 +11747,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
         constants.  The easiest way of dealing with the pathological
         exceptions is to generate a relocation against STN_UNDEF and
         leave everything up to the linker.  */
-  if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel && fixP->fx_tcbit == 0)
+  if (fixP->fx_addsy == NULL && !fixP->fx_pcrel && fixP->fx_tcbit == 0)
     fixP->fx_done = 1;
 
   switch (fixP->fx_r_type)
@@ -11956,8 +11971,8 @@ mips_align (int to, int fill, symbolS *label)
 static void
 s_align (int x ATTRIBUTE_UNUSED)
 {
-  register int temp;
-  register long temp_fill;
+  int temp;
+  long temp_fill;
   long max_alignment = 15;
 
   /*
@@ -11989,9 +12004,11 @@ s_align (int x ATTRIBUTE_UNUSED)
     temp_fill = 0;
   if (temp)
     {
+      segment_info_type *si = seg_info (now_seg);
+      struct insn_label_list *l = si->label_list;
+      /* Auto alignment should be switched on by next section change */
       auto_align = 1;
-      mips_align (temp, (int) temp_fill,
-                 insn_labels != NULL ? insn_labels->label : NULL);
+      mips_align (temp, (int) temp_fill, l != NULL ? l->label : NULL);
     }
   else
     {
@@ -12013,7 +12030,8 @@ s_change_sec (int sec)
      as it would not be appropriate to use it in the section changing
      functions in read.c, since obj-elf.c intercepts those.  FIXME:
      This should be cleaner, somehow.  */
-  obj_elf_section_change_hook ();
+  if (IS_ELF)
+    obj_elf_section_change_hook ();
 #endif
 
   mips_emit_delays ();
@@ -12033,7 +12051,7 @@ s_change_sec (int sec)
     case 'r':
       seg = subseg_new (RDATA_SECTION_NAME,
                        (subsegT) get_absolute_expression ());
-      if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+      if (IS_ELF)
        {
          bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD
                                                  | SEC_READONLY | SEC_RELOC
@@ -12046,7 +12064,7 @@ s_change_sec (int sec)
 
     case 's':
       seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
-      if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+      if (IS_ELF)
        {
          bfd_set_section_flags (stdoutput, seg,
                                 SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
@@ -12072,7 +12090,7 @@ s_change_section (int ignore ATTRIBUTE_UNUSED)
   int section_entry_size;
   int section_alignment;
 
-  if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+  if (!IS_ELF)
     return;
 
   section_name = input_line_pointer;
@@ -12144,9 +12162,11 @@ mips_enable_auto_align (void)
 static void
 s_cons (int log_size)
 {
+  segment_info_type *si = seg_info (now_seg);
+  struct insn_label_list *l = si->label_list;
   symbolS *label;
 
-  label = insn_labels != NULL ? insn_labels->label : NULL;
+  label = l != NULL ? l->label : NULL;
   mips_emit_delays ();
   if (log_size > 0 && auto_align)
     mips_align (log_size, 0, label);
@@ -12157,9 +12177,11 @@ s_cons (int log_size)
 static void
 s_float_cons (int type)
 {
+  segment_info_type *si = seg_info (now_seg);
+  struct insn_label_list *l = si->label_list;
   symbolS *label;
 
-  label = insn_labels != NULL ? insn_labels->label : NULL;
+  label = l != NULL ? l->label : NULL;
 
   mips_emit_delays ();
 
@@ -12834,6 +12856,8 @@ s_gpvalue (int ignore ATTRIBUTE_UNUSED)
 static void
 s_gpword (int ignore ATTRIBUTE_UNUSED)
 {
+  segment_info_type *si;
+  struct insn_label_list *l;
   symbolS *label;
   expressionS ex;
   char *p;
@@ -12845,7 +12869,9 @@ s_gpword (int ignore ATTRIBUTE_UNUSED)
       return;
     }
 
-  label = insn_labels != NULL ? insn_labels->label : NULL;
+  si = seg_info (now_seg);
+  l = si->label_list;
+  label = l != NULL ? l->label : NULL;
   mips_emit_delays ();
   if (auto_align)
     mips_align (2, 0, label);
@@ -12870,6 +12896,8 @@ s_gpword (int ignore ATTRIBUTE_UNUSED)
 static void
 s_gpdword (int ignore ATTRIBUTE_UNUSED)
 {
+  segment_info_type *si;
+  struct insn_label_list *l;
   symbolS *label;
   expressionS ex;
   char *p;
@@ -12881,7 +12909,9 @@ s_gpdword (int ignore ATTRIBUTE_UNUSED)
       return;
     }
 
-  label = insn_labels != NULL ? insn_labels->label : NULL;
+  si = seg_info (now_seg);
+  l = si->label_list;
+  label = l != NULL ? l->label : NULL;
   mips_emit_delays ();
   if (auto_align)
     mips_align (3, 0, label);
@@ -13112,6 +13142,8 @@ nopic_need_relax (symbolS *sym, int before_relaxing)
          change = (strcmp (segname, ".sdata") != 0
                    && strcmp (segname, ".sbss") != 0
                    && strncmp (segname, ".sdata.", 7) != 0
+                   && strncmp (segname, ".sbss.", 6) != 0
+                   && strncmp (segname, ".gnu.linkonce.sb.", 17) != 0
                    && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
        }
       return change;
@@ -13128,15 +13160,13 @@ static bfd_boolean
 pic_need_relax (symbolS *sym, asection *segtype)
 {
   asection *symsec;
-  bfd_boolean linkonce;
 
   /* Handle the case of a symbol equated to another symbol.  */
   while (symbol_equated_reloc_p (sym))
     {
       symbolS *n;
 
-      /* It's possible to get a loop here in a badly written
-        program.  */
+      /* It's possible to get a loop here in a badly written program.  */
       n = symbol_get_value_expression (sym)->X_add_symbol;
       if (n == sym)
        break;
@@ -13145,31 +13175,14 @@ pic_need_relax (symbolS *sym, asection *segtype)
 
   symsec = S_GET_SEGMENT (sym);
 
-  /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
-  linkonce = FALSE;
-  if (symsec != segtype && ! S_IS_LOCAL (sym))
-    {
-      if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE)
-         != 0)
-       linkonce = TRUE;
-
-      /* The GNU toolchain uses an extension for ELF: a section
-        beginning with the magic string .gnu.linkonce is a linkonce
-        section.  */
-      if (strncmp (segment_name (symsec), ".gnu.linkonce",
-                  sizeof ".gnu.linkonce" - 1) == 0)
-       linkonce = TRUE;
-    }
-
   /* This must duplicate the test in adjust_reloc_syms.  */
   return (symsec != &bfd_und_section
          && symsec != &bfd_abs_section
-         && ! bfd_is_com_section (symsec)
-         && !linkonce
+         && !bfd_is_com_section (symsec)
+         && !s_is_linkonce (sym, segtype)
 #ifdef OBJ_ELF
          /* A global or weak symbol is treated as external.  */
-         && (OUTPUT_FLAVOR != bfd_target_elf_flavour
-             || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
+         && (!IS_ELF || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
 #endif
          );
 }
@@ -13182,7 +13195,7 @@ static int
 mips16_extended_frag (fragS *fragp, asection *sec, long stretch)
 {
   int type;
-  register const struct mips16_immed_operand *op;
+  const struct mips16_immed_operand *op;
   offsetT val;
   int mintiny, maxtiny;
   segT symsec;
@@ -13485,11 +13498,6 @@ md_estimate_size_before_relax (fragS *fragp, asection *segtype)
 int
 mips_fix_adjustable (fixS *fixp)
 {
-  /* Don't adjust MIPS16 jump relocations, so we don't have to worry
-     about the format of the offset in the .o file. */
-  if (fixp->fx_r_type == BFD_RELOC_MIPS16_JMP)
-    return 0;
-
   if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
       || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 0;
@@ -13521,7 +13529,7 @@ mips_fix_adjustable (fixS *fixp)
 #ifdef OBJ_ELF
   /* Don't adjust relocations against mips16 symbols, so that the linker
      can find them if it needs to set up a stub.  */
-  if (OUTPUT_FLAVOR == bfd_target_elf_flavour
+  if (IS_ELF
       && S_GET_OTHER (fixp->fx_addsy) == STO_MIPS16
       && fixp->fx_subsy == NULL)
     return 0;
@@ -13553,7 +13561,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
       /* At this point, fx_addnumber is "symbol offset - pcrel address".
         Relocations want only the symbol offset.  */
       reloc->addend = fixp->fx_addnumber + reloc->address;
-      if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+      if (!IS_ELF)
        {
          /* A gruesome hack which is a result of the gruesome gas
             reloc handling.  What's worse, for COFF (as opposed to
@@ -13565,6 +13573,10 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
   else
     reloc->addend = fixp->fx_addnumber;
 
+  /* Handle relocs adjusted against a section symbol.  */
+  if (fixp->fx_r_type == BFD_RELOC_MIPS16_JMP)
+    reloc->addend += fixp->fx_offset;
+
   /* Since the old MIPS ELF ABI uses Rel instead of Rela, encode the vtable
      entry to be used in the relocation's section offset.  */
   if (! HAVE_NEWABI && fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
@@ -13652,7 +13664,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
          exp.X_add_number = fragp->fr_offset;
 
          fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
-                             4, &exp, 1, BFD_RELOC_16_PCREL_S2);
+                             4, &exp, TRUE, BFD_RELOC_16_PCREL_S2);
          fixp->fx_file = fragp->fr_file;
          fixp->fx_line = fragp->fr_line;
 
@@ -13769,7 +13781,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
              exp.X_add_number = fragp->fr_offset;
 
              fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
-                                 4, &exp, 0, BFD_RELOC_MIPS_JMP);
+                                 4, &exp, FALSE, BFD_RELOC_MIPS_JMP);
              fixp->fx_file = fragp->fr_file;
              fixp->fx_line = fragp->fr_line;
 
@@ -13791,7 +13803,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
                }
 
              fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
-                                 4, &exp, 0, BFD_RELOC_MIPS_GOT16);
+                                 4, &exp, FALSE, BFD_RELOC_MIPS_GOT16);
              fixp->fx_file = fragp->fr_file;
              fixp->fx_line = fragp->fr_line;
 
@@ -13809,7 +13821,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
              insn = HAVE_64BIT_ADDRESSES ? 0x64210000 : 0x24210000;
 
              fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
-                                 4, &exp, 0, BFD_RELOC_LO16);
+                                 4, &exp, FALSE, BFD_RELOC_LO16);
              fixp->fx_file = fragp->fr_file;
              fixp->fx_line = fragp->fr_line;
 
@@ -13838,7 +13850,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
   if (RELAX_MIPS16_P (fragp->fr_subtype))
     {
       int type;
-      register const struct mips16_immed_operand *op;
+      const struct mips16_immed_operand *op;
       bfd_boolean small, ext;
       offsetT val;
       bfd_byte *buf;
@@ -13992,7 +14004,7 @@ mips_frob_file_after_relocs (void)
   asymbol **syms;
   unsigned int count, i;
 
-  if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+  if (!IS_ELF)
     return;
 
   syms = bfd_get_outsymbols (stdoutput);
@@ -14020,6 +14032,7 @@ mips_frob_file_after_relocs (void)
 void
 mips_define_label (symbolS *sym)
 {
+  segment_info_type *si = seg_info (now_seg);
   struct insn_label_list *l;
 
   if (free_insn_labels == NULL)
@@ -14031,8 +14044,8 @@ mips_define_label (symbolS *sym)
     }
 
   l->label = sym;
-  l->next = insn_labels;
-  insn_labels = l;
+  l->next = si->label_list;
+  si->label_list = l;
 
 #ifdef OBJ_ELF
   dwarf2_emit_label (sym);
@@ -14347,8 +14360,7 @@ s_mips_end (int x ATTRIBUTE_UNUSED)
     }
 
   /* Generate a .pdr section.  */
-  if (OUTPUT_FLAVOR == bfd_target_elf_flavour && ! ECOFF_DEBUGGING
-      && mips_flag_pdr)
+  if (IS_ELF && !ECOFF_DEBUGGING && mips_flag_pdr)
     {
       segT saved_seg = now_seg;
       subsegT saved_subseg = now_subseg;
@@ -14442,7 +14454,7 @@ static void
 s_mips_frame (int ignore ATTRIBUTE_UNUSED)
 {
 #ifdef OBJ_ELF
-  if (OUTPUT_FLAVOR == bfd_target_elf_flavour && ! ECOFF_DEBUGGING)
+  if (IS_ELF && !ECOFF_DEBUGGING)
     {
       long val;
 
@@ -14485,7 +14497,7 @@ static void
 s_mips_mask (int reg_type)
 {
 #ifdef OBJ_ELF
-  if (OUTPUT_FLAVOR == bfd_target_elf_flavour && ! ECOFF_DEBUGGING)
+  if (IS_ELF && !ECOFF_DEBUGGING)
     {
       long mask, off;
 
@@ -14600,11 +14612,11 @@ static const struct mips_cpu_info mips_cpu_info_table[] =
   { "24ke",           MIPS_CPU_ASE_DSP,                ISA_MIPS32R2,   CPU_MIPS32R2 },
   { "24kec",          MIPS_CPU_ASE_DSP,                ISA_MIPS32R2,   CPU_MIPS32R2 },
   { "24kef",          MIPS_CPU_ASE_DSP,                ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "24kex",         MIPS_CPU_ASE_DSP,         ISA_MIPS32R2,   CPU_MIPS32R2 },
+  { "24kex",          MIPS_CPU_ASE_DSP,                ISA_MIPS32R2,   CPU_MIPS32R2 },
   /* 34k is a 24k with MT ASE, other ASEs are optional.  */
   { "34kc",           MIPS_CPU_ASE_MT,         ISA_MIPS32R2,   CPU_MIPS32R2 },
   { "34kf",           MIPS_CPU_ASE_MT,         ISA_MIPS32R2,   CPU_MIPS32R2 },
-  { "34kx",          MIPS_CPU_ASE_MT,          ISA_MIPS32R2,   CPU_MIPS32R2 },
+  { "34kx",           MIPS_CPU_ASE_MT,         ISA_MIPS32R2,   CPU_MIPS32R2 },
 
   /* MIPS 64 */
   { "5kc",            0,                       ISA_MIPS64,     CPU_MIPS64 },
@@ -14615,7 +14627,11 @@ static const struct mips_cpu_info mips_cpu_info_table[] =
   { "25kf",           MIPS_CPU_ASE_MIPS3D,     ISA_MIPS64R2,   CPU_MIPS64R2 },
 
   /* Broadcom SB-1 CPU core */
-  { "sb1",            0,                       ISA_MIPS64,     CPU_SB1 },
+  { "sb1",            MIPS_CPU_ASE_MIPS3D | MIPS_CPU_ASE_MDMX,
+                                               ISA_MIPS64,     CPU_SB1 },
+  /* Broadcom SB-1A CPU core */
+  { "sb1a",           MIPS_CPU_ASE_MIPS3D | MIPS_CPU_ASE_MDMX,
+                                               ISA_MIPS64,     CPU_SB1 },
 
   /* End marker */
   { NULL, 0, 0, 0 }
This page took 0.043767 seconds and 4 git commands to generate.