Add new command line switch --no-construct-floats
[deliverable/binutils-gdb.git] / gas / config / tc-mips.c
index 3d865fd9777227b5bf4ac740b18a631a6699c589..1333d058a3a0aca3309529ba238a34cb26a7ef61 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-mips.c -- assemble code for a MIPS chip.
 /* tc-mips.c -- assemble code for a MIPS chip.
-   Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1993, 94, 95, 96, 97, 98, 1999, 2000 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
    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
@@ -54,7 +54,6 @@ static int mips_output_flavor () { return OUTPUT_FLAVOR; }
 #undef S_GET_SIZE
 #undef S_SET_ALIGN
 #undef S_SET_SIZE
 #undef S_GET_SIZE
 #undef S_SET_ALIGN
 #undef S_SET_SIZE
-#undef TARGET_SYMBOL_FIELDS
 #undef obj_frob_file
 #undef obj_frob_file_after_relocs
 #undef obj_frob_symbol
 #undef obj_frob_file
 #undef obj_frob_file_after_relocs
 #undef obj_frob_symbol
@@ -119,10 +118,18 @@ mips_target_format ()
       return target_big_endian ? "a.out-mips-big" : "a.out-mips-little";
     case bfd_target_ecoff_flavour:
       return target_big_endian ? "ecoff-bigmips" : ECOFF_LITTLE_FORMAT;
       return target_big_endian ? "a.out-mips-big" : "a.out-mips-little";
     case bfd_target_ecoff_flavour:
       return target_big_endian ? "ecoff-bigmips" : ECOFF_LITTLE_FORMAT;
+    case bfd_target_coff_flavour:
+      return "pe-mips";
     case bfd_target_elf_flavour:
     case bfd_target_elf_flavour:
+#ifdef TE_TMIPS
+      /* This is traditional mips */
+      return (target_big_endian
+              ? "elf32-tradbigmips" : "elf32-tradlittlemips");
+#else
       return (target_big_endian
              ? (mips_64 ? "elf64-bigmips" : "elf32-bigmips")
              : (mips_64 ? "elf64-littlemips" : "elf32-littlemips"));
       return (target_big_endian
              ? (mips_64 ? "elf64-bigmips" : "elf32-bigmips")
              : (mips_64 ? "elf64-littlemips" : "elf32-littlemips"));
+#endif
     default:
       abort ();
       return NULL;
     default:
       abort ();
       return NULL;
@@ -134,6 +141,8 @@ mips_target_format ()
                            ? ".data" \
                            : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
                            ? ".rdata" \
                            ? ".data" \
                            : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
                            ? ".rdata" \
+                           : OUTPUT_FLAVOR == bfd_target_coff_flavour \
+                           ? ".rdata" \
                            : OUTPUT_FLAVOR == bfd_target_elf_flavour \
                            ? ".rodata" \
                            : (abort (), ""))
                            : OUTPUT_FLAVOR == bfd_target_elf_flavour \
                            ? ".rodata" \
                            : (abort (), ""))
@@ -180,7 +189,7 @@ struct mips_set_options
    that we must set the isa and mips16 fields to -1 to indicate that
    they have not been initialized.  */
 
    that we must set the isa and mips16 fields to -1 to indicate that
    they have not been initialized.  */
 
-static struct mips_set_options mips_opts = { -1, -1 };
+static struct mips_set_options mips_opts = { -1, -1, 0, 0, 0, 0, 0, 0 };
 
 /* These variables are filled in with the masks of registers used.
    The object format code reads them and puts them in the appropriate
 
 /* These variables are filled in with the masks of registers used.
    The object format code reads them and puts them in the appropriate
@@ -204,6 +213,29 @@ static int mips_eabi64 = 0;
    mips3 or greater, then mark the object file 32BITMODE. */
 static int mips_32bitmode = 0;
 
    mips3 or greater, then mark the object file 32BITMODE. */
 static int mips_32bitmode = 0;
 
+/* True if -mgp32 was passed. */
+static int mips_gp32 = 0;
+
+/* Some ISA's have delay slots for instructions which read or write
+   from a coprocessor (eg. mips1-mips3); some don't (eg mips4).
+   Return true if instructions marked INSN_LOAD_COPROC_DELAY, 
+   INSN_COPROC_MOVE_DELAY, or INSN_WRITE_COND_CODE actually have a
+   delay slot in this ISA.  The uses of this macro assume that any
+   ISA that has delay slots for one of these, has them for all.  They
+   also assume that ISAs which don't have delays for these insns, don't
+   have delays for the INSN_LOAD_MEMORY_DELAY instructions either. */
+#define ISA_HAS_COPROC_DELAYS(ISA) (        \
+   (ISA) == 1                               \
+   || (ISA) == 2                            \
+   || (ISA) == 3                            \
+   )
+
+/*  Return true if ISA supports 64 bit gp register instructions. */
+#define ISA_HAS_64BIT_REGS(ISA) (    \
+   (ISA) == 3                        \
+   || (ISA) == 4                     \
+   )
+
 /* Whether the processor uses hardware interlocks to protect 
    reads from the HI and LO registers, and thus does not
    require nops to be inserted.
 /* Whether the processor uses hardware interlocks to protect 
    reads from the HI and LO registers, and thus does not
    require nops to be inserted.
@@ -237,7 +269,7 @@ static int mips_32bitmode = 0;
 /* Whether the processor uses hardware interlocks to protect reads
    from the GPRs, and thus does not require nops to be inserted.  */
 #define gpr_interlocks \
 /* Whether the processor uses hardware interlocks to protect reads
    from the GPRs, and thus does not require nops to be inserted.  */
 #define gpr_interlocks \
-  (mips_opts.isa >= 2  \
+  (mips_opts.isa != 1  \
    || mips_cpu == 3900)
 
 /* As with other "interlocks" this is used by hardware that has FP
    || mips_cpu == 3900)
 
 /* As with other "interlocks" this is used by hardware that has FP
@@ -246,6 +278,10 @@ static int mips_32bitmode = 0;
 #define cop_interlocks (mips_cpu == 4300                            \
                        )
 
 #define cop_interlocks (mips_cpu == 4300                            \
                        )
 
+/* Is this a mfhi or mflo instruction?  */
+#define MF_HILO_INSN(PINFO) \
+          ((PINFO & INSN_READ_HI) || (PINFO & INSN_READ_LO))
+
 /* MIPS PIC level.  */
 
 enum mips_pic_level
 /* MIPS PIC level.  */
 
 enum mips_pic_level
@@ -277,10 +313,22 @@ static int mips_big_got;
    instructions.  */
 static int mips_trap;
 
    instructions.  */
 static int mips_trap;
 
+/* 1 if double width floating point constants should not be constructed
+   by a assembling two single width halves into two single width floating
+   point registers which just happen to alias the double width destination
+   register.  On some architectures this aliasing can be disabled by a bit
+   in the status register, and the settin gof this bit cannot be determined
+   automatically at assemble time.  */
+static int mips_disable_float_construction;
+
 /* Non-zero if any .set noreorder directives were used.  */
 
 static int mips_any_noreorder;
 
 /* Non-zero if any .set noreorder directives were used.  */
 
 static int mips_any_noreorder;
 
+/* Non-zero if nops should be inserted when the register referenced in
+   an mfhi/mflo instruction is read in the next two instructions.  */
+static int mips_7000_hilo_fix;
+
 /* The size of the small data section.  */
 static int g_switch_value = 8;
 /* Whether the -G option was used.  */
 /* The size of the small data section.  */
 static int g_switch_value = 8;
 /* Whether the -G option was used.  */
@@ -295,8 +343,9 @@ static int g_switch_seen = 0;
    better.
 
    This function can only provide a guess, but it seems to work for
    better.
 
    This function can only provide a guess, but it seems to work for
-   gcc output.  If it guesses wrong, the only loss should be in
-   efficiency; it shouldn't introduce any bugs.
+   gcc output.  It needs to guess right for gcc, otherwise gcc
+   will put what it thinks is a GP-relative instruction in a branch
+   delay slot.
 
    I don't know if a fix is needed for the SVR4_PIC mode.  I've only
    fixed it for the non-PIC mode.  KR 95/04/07  */
 
    I don't know if a fix is needed for the SVR4_PIC mode.  I've only
    fixed it for the non-PIC mode.  KR 95/04/07  */
@@ -322,7 +371,7 @@ const char comment_chars[] = "#";
 const char line_comment_chars[] = "#";
 
 /* This array holds machine specific line separator characters. */
 const char line_comment_chars[] = "#";
 
 /* This array holds machine specific line separator characters. */
-const char line_separator_chars[] = "";
+const char line_separator_chars[] = ";";
 
 /* Chars that can be used to separate mant from exp in floating point nums */
 const char EXP_CHARS[] = "eE";
 
 /* Chars that can be used to separate mant from exp in floating point nums */
 const char EXP_CHARS[] = "eE";
@@ -372,7 +421,7 @@ static struct mips_cl_insn prev_prev_insn;
 
 /* If we don't want information for prev_insn or prev_prev_insn, we
    point the insn_mo field at this dummy integer.  */
 
 /* If we don't want information for prev_insn or prev_prev_insn, we
    point the insn_mo field at this dummy integer.  */
-static const struct mips_opcode dummy_opcode = { 0 };
+static const struct mips_opcode dummy_opcode = { NULL, NULL, 0, 0, 0, 0 };
 
 /* Non-zero if prev_insn is valid.  */
 static int prev_insn_valid;
 
 /* Non-zero if prev_insn is valid.  */
 static int prev_insn_valid;
@@ -721,7 +770,7 @@ static const pseudo_typeS mips_pseudo_table[] =
   {"stabn", s_mips_stab, 'n'},
   {"text", s_change_sec, 't'},
   {"word", s_cons, 2},
   {"stabn", s_mips_stab, 'n'},
   {"text", s_change_sec, 't'},
   {"word", s_cons, 2},
-  { 0 },
+  { NULL, NULL, 0 },
 };
 
 static const pseudo_typeS mips_nonecoff_pseudo_table[] = {
 };
 
 static const pseudo_typeS mips_nonecoff_pseudo_table[] = {
@@ -738,7 +787,7 @@ static const pseudo_typeS mips_nonecoff_pseudo_table[] = {
   {"loc", s_ignore, 0},
   {"mask", s_mips_mask, 'R'},
   {"verstamp", s_ignore, 0},
   {"loc", s_ignore, 0},
   {"mask", s_mips_mask, 'R'},
   {"verstamp", s_ignore, 0},
-  { 0 },
+  { NULL, NULL, 0 },
 };
 
 extern void pop_insert PARAMS ((const pseudo_typeS *));
 };
 
 extern void pop_insert PARAMS ((const pseudo_typeS *));
@@ -817,6 +866,15 @@ md_begin ()
   int broken = 0;
   int mips_isa_from_cpu;
 
   int broken = 0;
   int mips_isa_from_cpu;
 
+  /* GP relative stuff not working for PE */
+  if (strncmp (TARGET_OS, "pe", 2) == 0
+      && g_switch_value != 0)
+    {
+      if (g_switch_seen)
+       as_bad (_("-G not supported in this configuration."));
+      g_switch_value = 0;
+    }
+
   cpu = TARGET_CPU;
   if (strcmp (cpu + (sizeof TARGET_CPU) - 3, "el") == 0)
     {
   cpu = TARGET_CPU;
   if (strcmp (cpu + (sizeof TARGET_CPU) - 3, "el") == 0)
     {
@@ -834,10 +892,10 @@ md_begin ()
 
       if (strcmp (cpu, "mips") == 0)
         {
 
       if (strcmp (cpu, "mips") == 0)
         {
-          if (mips_opts.isa < 0)
-            mips_cpu = 3000;   
+         if (mips_opts.isa < 0)
+           mips_cpu = 3000;   
 
 
-          else if (mips_opts.isa == 2)
+         else if (mips_opts.isa == 2)
             mips_cpu = 6000;
 
           else if (mips_opts.isa == 3)
             mips_cpu = 6000;
 
           else if (mips_opts.isa == 3)
@@ -957,13 +1015,13 @@ md_begin ()
     a = NULL;
     }
 
     a = NULL;
     }
 
-  if (mips_opts.isa < 2 && mips_trap)
+  if (mips_opts.isa == 1 && mips_trap)
     as_bad (_("trap exception not supported at ISA 1"));
 
   /* Set the EABI kind based on the ISA before the user gets
      to change the ISA with directives.  This isn't really
      the best, but then neither is basing the abi on the isa. */     
     as_bad (_("trap exception not supported at ISA 1"));
 
   /* Set the EABI kind based on the ISA before the user gets
      to change the ISA with directives.  This isn't really
      the best, but then neither is basing the abi on the isa. */     
-  if (mips_opts.isa > 2 
+  if (ISA_HAS_64BIT_REGS (mips_opts.isa)
       && mips_abi_string
       && 0 == strcmp (mips_abi_string,"eabi"))
     mips_eabi64 = 1;
       && mips_abi_string
       && 0 == strcmp (mips_abi_string,"eabi"))
     mips_eabi64 = 1;
@@ -971,11 +1029,12 @@ md_begin ()
   if (mips_cpu != 0 && mips_cpu != -1)
     {
       ok = bfd_set_arch_mach (stdoutput, bfd_arch_mips, mips_cpu);
   if (mips_cpu != 0 && mips_cpu != -1)
     {
       ok = bfd_set_arch_mach (stdoutput, bfd_arch_mips, mips_cpu);
-
+      
       /* If they asked for mips1 or mips2 and a cpu that is
         mips3 or greater, then mark the object file 32BITMODE. */
       if (mips_isa_from_cpu != -1
       /* If they asked for mips1 or mips2 and a cpu that is
         mips3 or greater, then mark the object file 32BITMODE. */
       if (mips_isa_from_cpu != -1
-         && mips_opts.isa <= 2 && mips_isa_from_cpu > 2)
+         && ! ISA_HAS_64BIT_REGS (mips_opts.isa) 
+         && ISA_HAS_64BIT_REGS (mips_isa_from_cpu))
        mips_32bitmode = 1;
     }
   else
        mips_32bitmode = 1;
     }
   else
@@ -1334,7 +1393,7 @@ reg_needs_delay (reg)
 
   prev_pinfo = prev_insn.insn_mo->pinfo;
   if (! mips_opts.noreorder
 
   prev_pinfo = prev_insn.insn_mo->pinfo;
   if (! mips_opts.noreorder
-      && mips_opts.isa < 4
+      && ISA_HAS_COPROC_DELAYS (mips_opts.isa)
       && ((prev_pinfo & INSN_LOAD_COPROC_DELAY)
          || (! gpr_interlocks
              && (prev_pinfo & INSN_LOAD_MEMORY_DELAY))))
       && ((prev_pinfo & INSN_LOAD_COPROC_DELAY)
          || (! gpr_interlocks
              && (prev_pinfo & INSN_LOAD_MEMORY_DELAY))))
@@ -1373,8 +1432,8 @@ mips16_mark_labels ()
          if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
            S_SET_OTHER (l->label, STO_MIPS16);
 #endif
          if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
            S_SET_OTHER (l->label, STO_MIPS16);
 #endif
-         if ((l->label->sy_value.X_add_number & 1) == 0)
-           ++l->label->sy_value.X_add_number;
+         if ((S_GET_VALUE (l->label) & 1) == 0)
+           S_SET_VALUE (l->label, S_GET_VALUE (l->label) + 1);
        }
     }
 }
        }
     }
 }
@@ -1437,7 +1496,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
       /* The previous insn might require a delay slot, depending upon
         the contents of the current insn.  */
       if (! mips_opts.mips16
       /* The previous insn might require a delay slot, depending upon
         the contents of the current insn.  */
       if (! mips_opts.mips16
-         && mips_opts.isa < 4
+         && ISA_HAS_COPROC_DELAYS (mips_opts.isa)
          && (((prev_pinfo & INSN_LOAD_COPROC_DELAY)
                && ! cop_interlocks)
              || (! gpr_interlocks
          && (((prev_pinfo & INSN_LOAD_COPROC_DELAY)
                && ! cop_interlocks)
              || (! gpr_interlocks
@@ -1457,10 +1516,10 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
            ++nops;
        }
       else if (! mips_opts.mips16
            ++nops;
        }
       else if (! mips_opts.mips16
-              && mips_opts.isa < 4
+              && ISA_HAS_COPROC_DELAYS (mips_opts.isa)
               && (((prev_pinfo & INSN_COPROC_MOVE_DELAY)
                     && ! cop_interlocks)
               && (((prev_pinfo & INSN_COPROC_MOVE_DELAY)
                     && ! cop_interlocks)
-                  || (mips_opts.isa < 2
+                  || (mips_opts.isa == 1
                       && (prev_pinfo & INSN_COPROC_MEMORY_DELAY))))
        {
          /* A generic coprocessor delay.  The previous instruction
                       && (prev_pinfo & INSN_COPROC_MEMORY_DELAY))))
        {
          /* A generic coprocessor delay.  The previous instruction
@@ -1516,7 +1575,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
            }
        }
       else if (! mips_opts.mips16
            }
        }
       else if (! mips_opts.mips16
-              && mips_opts.isa < 4
+              && ISA_HAS_COPROC_DELAYS (mips_opts.isa)
               && (prev_pinfo & INSN_WRITE_COND_CODE)
                && ! cop_interlocks)
        {
               && (prev_pinfo & INSN_WRITE_COND_CODE)
                && ! cop_interlocks)
        {
@@ -1530,6 +1589,37 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
              || (pinfo & INSN_READ_COND_CODE))
            ++nops;
        }
              || (pinfo & INSN_READ_COND_CODE))
            ++nops;
        }
+
+      /* If we're fixing up mfhi/mflo for the r7000 and the
+        previous insn was an mfhi/mflo and the current insn
+        reads the register that the mfhi/mflo wrote to, then
+        insert two nops.  */
+
+      else if (mips_7000_hilo_fix
+              && MF_HILO_INSN (prev_pinfo)
+              && insn_uses_reg (ip, ((prev_insn.insn_opcode >> OP_SH_RD)
+                                       & OP_MASK_RD),
+                                    MIPS_GR_REG))
+
+       {
+         nops += 2;
+       }
+
+      /* If we're fixing up mfhi/mflo for the r7000 and the
+        2nd previous insn was an mfhi/mflo and the current insn
+        reads the register that the mfhi/mflo wrote to, then
+        insert one nop.  */
+
+      else if (mips_7000_hilo_fix
+              && MF_HILO_INSN (prev_prev_insn.insn_opcode)
+              && insn_uses_reg (ip, ((prev_prev_insn.insn_opcode >> OP_SH_RD)
+                                       & OP_MASK_RD),
+                                    MIPS_GR_REG))
+     
+       {
+         nops += 1;
+       }
       else if (prev_pinfo & INSN_READ_LO)
        {
          /* The previous instruction reads the LO register; if the
       else if (prev_pinfo & INSN_READ_LO)
        {
          /* The previous instruction reads the LO register; if the
@@ -1593,7 +1683,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
         instruction, we must check for these cases compared to the
         instruction previous to the previous instruction.  */
       if ((! mips_opts.mips16
         instruction, we must check for these cases compared to the
         instruction previous to the previous instruction.  */
       if ((! mips_opts.mips16
-          && mips_opts.isa < 4
+          && ISA_HAS_COPROC_DELAYS (mips_opts.isa)
           && (prev_prev_insn.insn_mo->pinfo & INSN_COPROC_MOVE_DELAY)
           && (prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
           && (pinfo & INSN_READ_COND_CODE)
           && (prev_prev_insn.insn_mo->pinfo & INSN_COPROC_MOVE_DELAY)
           && (prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
           && (pinfo & INSN_READ_COND_CODE)
@@ -1656,11 +1746,11 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
          for (l = insn_labels; l != NULL; l = l->next)
            {
              assert (S_GET_SEGMENT (l->label) == now_seg);
          for (l = insn_labels; l != NULL; l = l->next)
            {
              assert (S_GET_SEGMENT (l->label) == now_seg);
-             l->label->sy_frag = frag_now;
+             symbol_set_frag (l->label, frag_now);
              S_SET_VALUE (l->label, (valueT) frag_now_fix ());
              /* mips16 text labels are stored as odd.  */
              if (mips_opts.mips16)
              S_SET_VALUE (l->label, (valueT) frag_now_fix ());
              /* mips16 text labels are stored as odd.  */
              if (mips_opts.mips16)
-               ++l->label->sy_value.X_add_number;
+               S_SET_VALUE (l->label, S_GET_VALUE (l->label) + 1);
            }
 
 #ifndef NO_ECOFF_DEBUGGING
            }
 
 #ifndef NO_ECOFF_DEBUGGING
@@ -1943,13 +2033,13 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
                 we can not swap, and I don't feel like handling that
                 case.  */
              || (! mips_opts.mips16
                 we can not swap, and I don't feel like handling that
                 case.  */
              || (! mips_opts.mips16
-                 && mips_opts.isa < 4
+                 && ISA_HAS_COPROC_DELAYS (mips_opts.isa)
                  && (pinfo & INSN_READ_COND_CODE))
              /* We can not swap with an instruction that requires a
                 delay slot, becase the target of the branch might
                 interfere with that instruction.  */
              || (! mips_opts.mips16
                  && (pinfo & INSN_READ_COND_CODE))
              /* We can not swap with an instruction that requires a
                 delay slot, becase the target of the branch might
                 interfere with that instruction.  */
              || (! mips_opts.mips16
-                 && mips_opts.isa < 4
+                 && ISA_HAS_COPROC_DELAYS (mips_opts.isa)
                  && (prev_pinfo
               /* Itbl support may require additional care here. */
                      & (INSN_LOAD_COPROC_DELAY
                  && (prev_pinfo
               /* Itbl support may require additional care here. */
                      & (INSN_LOAD_COPROC_DELAY
@@ -1964,7 +2054,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
                  && ! gpr_interlocks
                  && (prev_pinfo & INSN_LOAD_MEMORY_DELAY))
              || (! mips_opts.mips16
                  && ! gpr_interlocks
                  && (prev_pinfo & INSN_LOAD_MEMORY_DELAY))
              || (! mips_opts.mips16
-                 && mips_opts.isa < 2
+                 && mips_opts.isa == 1
                   /* Itbl support may require additional care here. */
                  && (prev_pinfo & INSN_COPROC_MEMORY_DELAY))
              /* We can not swap with a branch instruction.  */
                   /* Itbl support may require additional care here. */
                  && (prev_pinfo & INSN_COPROC_MEMORY_DELAY))
              /* We can not swap with a branch instruction.  */
@@ -2069,7 +2159,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
                 delay, and sets a register that the branch reads, we
                 can not swap.  */
              || (! mips_opts.mips16
                 delay, and sets a register that the branch reads, we
                 can not swap.  */
              || (! mips_opts.mips16
-                 && mips_opts.isa < 4
+                 && ISA_HAS_COPROC_DELAYS (mips_opts.isa)
               /* Itbl support may require additional care here. */
                  && ((prev_prev_insn.insn_mo->pinfo & INSN_LOAD_COPROC_DELAY)
                      || (! gpr_interlocks
               /* Itbl support may require additional care here. */
                  && ((prev_prev_insn.insn_mo->pinfo & INSN_LOAD_COPROC_DELAY)
                      || (! gpr_interlocks
@@ -2098,7 +2188,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
              || (mips_opts.mips16 && prev_insn_fixp)
              /* If the previous instruction is a sync, sync.l, or 
                 sync.p, we can not swap. */
              || (mips_opts.mips16 && prev_insn_fixp)
              /* If the previous instruction is a sync, sync.l, or 
                 sync.p, we can not swap. */
-             || (prev_pinfo && INSN_SYNC))
+             || (prev_pinfo & INSN_SYNC))
            {
              /* We could do even better for unconditional branches to
                 portions of this object file; we could pick up the
            {
              /* We could do even better for unconditional branches to
                 portions of this object file; we could pick up the
@@ -2285,7 +2375,7 @@ mips_emit_delays (insns)
 
       nops = 0;
       if ((! mips_opts.mips16
 
       nops = 0;
       if ((! mips_opts.mips16
-          && mips_opts.isa < 4
+          && ISA_HAS_COPROC_DELAYS (mips_opts.isa)
           && (! cop_interlocks
                && (prev_insn.insn_mo->pinfo
                    & (INSN_LOAD_COPROC_DELAY
           && (! cop_interlocks
                && (prev_insn.insn_mo->pinfo
                    & (INSN_LOAD_COPROC_DELAY
@@ -2300,14 +2390,14 @@ mips_emit_delays (insns)
              && (prev_insn.insn_mo->pinfo 
                   & INSN_LOAD_MEMORY_DELAY))
          || (! mips_opts.mips16
              && (prev_insn.insn_mo->pinfo 
                   & INSN_LOAD_MEMORY_DELAY))
          || (! mips_opts.mips16
-             && mips_opts.isa < 2
+             && mips_opts.isa == 1
              && (prev_insn.insn_mo->pinfo
                  & INSN_COPROC_MEMORY_DELAY)))
        {
           /* Itbl support may require additional care here. */
          ++nops;
          if ((! mips_opts.mips16
              && (prev_insn.insn_mo->pinfo
                  & INSN_COPROC_MEMORY_DELAY)))
        {
           /* Itbl support may require additional care here. */
          ++nops;
          if ((! mips_opts.mips16
-              && mips_opts.isa < 4
+              && ISA_HAS_COPROC_DELAYS (mips_opts.isa)
               && (! cop_interlocks
                    && prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE))
              || (! hilo_interlocks
               && (! cop_interlocks
                    && prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE))
              || (! hilo_interlocks
@@ -2319,7 +2409,7 @@ mips_emit_delays (insns)
            nops = 0;
        }
       else if ((! mips_opts.mips16
            nops = 0;
        }
       else if ((! mips_opts.mips16
-               && mips_opts.isa < 4
+               && ISA_HAS_COPROC_DELAYS (mips_opts.isa)
                && (! cop_interlocks
                     && prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE))
               || (! hilo_interlocks
                && (! cop_interlocks
                     && prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE))
               || (! hilo_interlocks
@@ -2360,11 +2450,11 @@ mips_emit_delays (insns)
          for (l = insn_labels; l != NULL; l = l->next)
            {
              assert (S_GET_SEGMENT (l->label) == now_seg);
          for (l = insn_labels; l != NULL; l = l->next)
            {
              assert (S_GET_SEGMENT (l->label) == now_seg);
-             l->label->sy_frag = frag_now;
+             symbol_set_frag (l->label, frag_now);
              S_SET_VALUE (l->label, (valueT) frag_now_fix ());
              /* mips16 text labels are stored as odd.  */
              if (mips_opts.mips16)
              S_SET_VALUE (l->label, (valueT) frag_now_fix ());
              /* mips16 text labels are stored as odd.  */
              if (mips_opts.mips16)
-               ++l->label->sy_value.X_add_number;
+               S_SET_VALUE (l->label, S_GET_VALUE (l->label) + 1);
            }
        }
     }
            }
        }
     }
@@ -2403,7 +2493,6 @@ macro_build (place, counter, ep, name, fmt, va_alist)
   struct mips_cl_insn insn;
   bfd_reloc_code_real_type r;
   va_list args;
   struct mips_cl_insn insn;
   bfd_reloc_code_real_type r;
   va_list args;
-  int insn_isa;
 
 #ifdef USE_STDARG
   va_start (args, fmt);
 
 #ifdef USE_STDARG
   va_start (args, fmt);
@@ -2437,30 +2526,10 @@ macro_build (place, counter, ep, name, fmt, va_alist)
   /* Search until we get a match for NAME.  */
   while (1)
     {
   /* Search until we get a match for NAME.  */
   while (1)
     {
-      if ((insn.insn_mo->membership & INSN_ISA) == INSN_ISA1)
-       insn_isa = 1;
-      else if ((insn.insn_mo->membership & INSN_ISA) == INSN_ISA2)
-       insn_isa = 2;
-      else if ((insn.insn_mo->membership & INSN_ISA) == INSN_ISA3)
-       insn_isa = 3;
-      else if ((insn.insn_mo->membership & INSN_ISA) == INSN_ISA4)
-       insn_isa = 4;
-      else
-       insn_isa = 15;
-
       if (strcmp (fmt, insn.insn_mo->args) == 0
          && insn.insn_mo->pinfo != INSN_MACRO
       if (strcmp (fmt, insn.insn_mo->args) == 0
          && insn.insn_mo->pinfo != INSN_MACRO
-         && (insn_isa <= mips_opts.isa
-             || (mips_cpu == 4650
-                 && (insn.insn_mo->membership & INSN_4650) != 0)
-             || (mips_cpu == 4010
-                 && (insn.insn_mo->membership & INSN_4010) != 0)
-             || ((mips_cpu == 4100
-                  || mips_cpu == 4111
-                  )
-                 && (insn.insn_mo->membership & INSN_4100) != 0)
-             || (mips_cpu == 3900
-                 && (insn.insn_mo->membership & INSN_3900) != 0))
+         && OPCODE_IS_MEMBER (insn.insn_mo, mips_opts.isa, mips_cpu, 
+                              mips_gp32)
          && (mips_cpu != 4650 || (insn.insn_mo->pinfo & FP_D) == 0))
        break;
 
          && (mips_cpu != 4650 || (insn.insn_mo->pinfo & FP_D) == 0))
        break;
 
@@ -2542,7 +2611,6 @@ macro_build (place, counter, ep, name, fmt, va_alist)
                  || r == BFD_RELOC_MIPS_GOT_LO16
                  || r == BFD_RELOC_MIPS_CALL_LO16
                  || (ep->X_op == O_subtract
                  || r == BFD_RELOC_MIPS_GOT_LO16
                  || r == BFD_RELOC_MIPS_CALL_LO16
                  || (ep->X_op == O_subtract
-                     && now_seg == text_section
                      && r == BFD_RELOC_PCREL_LO16));
          continue;
 
                      && r == BFD_RELOC_PCREL_LO16));
          continue;
 
@@ -2556,7 +2624,6 @@ macro_build (place, counter, ep, name, fmt, va_alist)
                              || r == BFD_RELOC_MIPS_GOT_HI16
                              || r == BFD_RELOC_MIPS_CALL_HI16))
                      || (ep->X_op == O_subtract
                              || r == BFD_RELOC_MIPS_GOT_HI16
                              || r == BFD_RELOC_MIPS_CALL_HI16))
                      || (ep->X_op == O_subtract
-                         && now_seg == text_section
                          && r == BFD_RELOC_PCREL_HI16_S)));
          if (ep->X_op == O_constant)
            {
                          && r == BFD_RELOC_PCREL_HI16_S)));
          if (ep->X_op == O_constant)
            {
@@ -2607,7 +2674,7 @@ macro_build (place, counter, ep, name, fmt, va_alist)
 static void
 mips16_macro_build (place, counter, ep, name, fmt, args)
      char *place;
 static void
 mips16_macro_build (place, counter, ep, name, fmt, args)
      char *place;
-     int *counter;
+     int *counter ATTRIBUTE_UNUSED;
      expressionS *ep;
      const char *name;
      const char *fmt;
      expressionS *ep;
      const char *name;
      const char *fmt;
@@ -2960,9 +3027,9 @@ load_register (counter, reg, ep, dbl)
                    || ! ep->X_unsigned
                    || sizeof (ep->X_add_number) > 4
                    || (ep->X_add_number & 0x80000000) == 0))
                    || ! ep->X_unsigned
                    || sizeof (ep->X_add_number) > 4
                    || (ep->X_add_number & 0x80000000) == 0))
-              || ((mips_opts.isa < 3 || ! dbl)
+              || ((! ISA_HAS_64BIT_REGS (mips_opts.isa) || ! dbl)
                   && (ep->X_add_number &~ (offsetT) 0xffffffff) == 0)
                   && (ep->X_add_number &~ (offsetT) 0xffffffff) == 0)
-              || (mips_opts.isa < 3
+              || (! ISA_HAS_64BIT_REGS (mips_opts.isa)
                   && ! dbl
                   && ((ep->X_add_number &~ (offsetT) 0xffffffff)
                       == ~ (offsetT) 0xffffffff)))
                   && ! dbl
                   && ((ep->X_add_number &~ (offsetT) 0xffffffff)
                       == ~ (offsetT) 0xffffffff)))
@@ -2979,7 +3046,7 @@ load_register (counter, reg, ep, dbl)
 
   /* The value is larger than 32 bits.  */
 
 
   /* The value is larger than 32 bits.  */
 
-  if (mips_opts.isa < 3)
+  if (! ISA_HAS_64BIT_REGS (mips_opts.isa))
     {
       as_bad (_("Number larger than 32 bits"));
       macro_build ((char *) NULL, counter, ep, "addiu", "t,r,j", reg, 0,
     {
       as_bad (_("Number larger than 32 bits"));
       macro_build ((char *) NULL, counter, ep, "addiu", "t,r,j", reg, 0,
@@ -3220,7 +3287,7 @@ load_address (counter, reg, ep)
          frag_grow (20);
          macro_build ((char *) NULL, counter, ep,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
          frag_grow (20);
          macro_build ((char *) NULL, counter, ep,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "addiu" : "daddiu"),
                       "t,r,j", reg, GP, (int) BFD_RELOC_MIPS_GPREL);
          p = frag_var (rs_machine_dependent, 8, 0,
                        ? "addiu" : "daddiu"),
                       "t,r,j", reg, GP, (int) BFD_RELOC_MIPS_GPREL);
          p = frag_var (rs_machine_dependent, 8, 0,
@@ -3233,7 +3300,7 @@ load_address (counter, reg, ep)
        p += 4;
       macro_build (p, counter, ep,
                   ((bfd_arch_bits_per_address (stdoutput) == 32
        p += 4;
       macro_build (p, counter, ep,
                   ((bfd_arch_bits_per_address (stdoutput) == 32
-                    || mips_opts.isa < 3)
+                    || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                    ? "addiu" : "daddiu"),
                   "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
     }
                    ? "addiu" : "daddiu"),
                   "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
     }
@@ -3253,7 +3320,7 @@ load_address (counter, reg, ep)
       frag_grow (20);
       macro_build ((char *) NULL, counter, ep,
                   ((bfd_arch_bits_per_address (stdoutput) == 32
       frag_grow (20);
       macro_build ((char *) NULL, counter, ep,
                   ((bfd_arch_bits_per_address (stdoutput) == 32
-                    || mips_opts.isa  < 3)
+                    || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                    ? "lw" : "ld"),
                   "t,o(b)", reg, (int) BFD_RELOC_MIPS_GOT16, GP);
       macro_build ((char *) NULL, counter, (expressionS *) NULL, "nop", "");
                    ? "lw" : "ld"),
                   "t,o(b)", reg, (int) BFD_RELOC_MIPS_GOT16, GP);
       macro_build ((char *) NULL, counter, (expressionS *) NULL, "nop", "");
@@ -3262,7 +3329,7 @@ load_address (counter, reg, ep)
                    ep->X_add_symbol, (offsetT) 0, (char *) NULL);
       macro_build (p, counter, ep,
                   ((bfd_arch_bits_per_address (stdoutput) == 32
                    ep->X_add_symbol, (offsetT) 0, (char *) NULL);
       macro_build (p, counter, ep,
                   ((bfd_arch_bits_per_address (stdoutput) == 32
-                    || mips_opts.isa  < 3)
+                    || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                    ? "addiu" : "daddiu"),
                   "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
       if (ex.X_add_number != 0)
                    ? "addiu" : "daddiu"),
                   "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
       if (ex.X_add_number != 0)
@@ -3272,7 +3339,7 @@ load_address (counter, reg, ep)
          ex.X_op = O_constant;
          macro_build ((char *) NULL, counter, &ex,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
          ex.X_op = O_constant;
          macro_build ((char *) NULL, counter, &ex,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa  < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "addiu" : "daddiu"),
                       "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
        }
                        ? "addiu" : "daddiu"),
                       "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
        }
@@ -3303,12 +3370,12 @@ load_address (counter, reg, ep)
                   (int) BFD_RELOC_MIPS_GOT_HI16);
       macro_build ((char *) NULL, counter, (expressionS *) NULL,
                   ((bfd_arch_bits_per_address (stdoutput) == 32
                   (int) BFD_RELOC_MIPS_GOT_HI16);
       macro_build ((char *) NULL, counter, (expressionS *) NULL,
                   ((bfd_arch_bits_per_address (stdoutput) == 32
-                    || mips_opts.isa  < 3)
+                    || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                    ? "addu" : "daddu"),
                   "d,v,t", reg, reg, GP);
       macro_build ((char *) NULL, counter, ep,
                   ((bfd_arch_bits_per_address (stdoutput) == 32
                    ? "addu" : "daddu"),
                   "d,v,t", reg, reg, GP);
       macro_build ((char *) NULL, counter, ep,
                   ((bfd_arch_bits_per_address (stdoutput) == 32
-                    || mips_opts.isa  < 3)
+                    || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                    ? "lw" : "ld"),
                   "t,o(b)", reg, (int) BFD_RELOC_MIPS_GOT_LO16, reg);
       p = frag_var (rs_machine_dependent, 12 + off, 0,
                    ? "lw" : "ld"),
                   "t,o(b)", reg, (int) BFD_RELOC_MIPS_GOT_LO16, reg);
       p = frag_var (rs_machine_dependent, 12 + off, 0,
@@ -3326,7 +3393,7 @@ load_address (counter, reg, ep)
        }
       macro_build (p, counter, ep,
                   ((bfd_arch_bits_per_address (stdoutput) == 32
        }
       macro_build (p, counter, ep,
                   ((bfd_arch_bits_per_address (stdoutput) == 32
-                    || mips_opts.isa  < 3)
+                    || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                    ? "lw" : "ld"),
                   "t,o(b)", reg, (int) BFD_RELOC_MIPS_GOT16, GP);
       p += 4;
                    ? "lw" : "ld"),
                   "t,o(b)", reg, (int) BFD_RELOC_MIPS_GOT16, GP);
       p += 4;
@@ -3334,7 +3401,7 @@ load_address (counter, reg, ep)
       p += 4;
       macro_build (p, counter, ep,
                   ((bfd_arch_bits_per_address (stdoutput) == 32
       p += 4;
       macro_build (p, counter, ep,
                   ((bfd_arch_bits_per_address (stdoutput) == 32
-                    || mips_opts.isa  < 3)
+                    || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                    ? "addiu" : "daddiu"),
                   "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
       if (ex.X_add_number != 0)
                    ? "addiu" : "daddiu"),
                   "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
       if (ex.X_add_number != 0)
@@ -3344,7 +3411,7 @@ load_address (counter, reg, ep)
          ex.X_op = O_constant;
          macro_build ((char *) NULL, counter, &ex,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
          ex.X_op = O_constant;
          macro_build ((char *) NULL, counter, &ex,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa  < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "addiu" : "daddiu"),
                       "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
        }
                        ? "addiu" : "daddiu"),
                       "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
        }
@@ -3356,7 +3423,7 @@ load_address (counter, reg, ep)
         */
       macro_build ((char *) NULL, counter, ep,
                   ((bfd_arch_bits_per_address (stdoutput) == 32
         */
       macro_build ((char *) NULL, counter, ep,
                   ((bfd_arch_bits_per_address (stdoutput) == 32
-                    || mips_opts.isa  < 3)
+                    || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                    ? "addiu" : "daddiu"),
                   "t,r,j", reg, GP, (int) BFD_RELOC_MIPS_GPREL);
     }
                    ? "addiu" : "daddiu"),
                   "t,r,j", reg, GP, (int) BFD_RELOC_MIPS_GPREL);
     }
@@ -3390,7 +3457,7 @@ macro (ip)
   int tempreg;
   int mask;
   int icnt = 0;
   int tempreg;
   int mask;
   int icnt = 0;
-  int used_at;
+  int used_at = 0;
   expressionS expr1;
   const char *s;
   const char *s2;
   expressionS expr1;
   const char *s;
   const char *s2;
@@ -3564,7 +3631,7 @@ macro (ip)
     case M_BGT_I:
       /* check for > max integer */
       maxnum = 0x7fffffff;
     case M_BGT_I:
       /* check for > max integer */
       maxnum = 0x7fffffff;
-      if (mips_opts.isa >= 3 && sizeof (maxnum) > 4)
+      if (ISA_HAS_64BIT_REGS (mips_opts.isa) && sizeof (maxnum) > 4)
        {
          maxnum <<= 16;
          maxnum |= 0xffff;
        {
          maxnum <<= 16;
          maxnum |= 0xffff;
@@ -3573,7 +3640,7 @@ macro (ip)
        }
       if (imm_expr.X_op == O_constant
          && imm_expr.X_add_number >= maxnum
        }
       if (imm_expr.X_op == O_constant
          && imm_expr.X_add_number >= maxnum
-         && (mips_opts.isa < 3 || sizeof (maxnum) > 4))
+         && (! ISA_HAS_64BIT_REGS (mips_opts.isa) || sizeof (maxnum) > 4))
        {
        do_false:
          /* result is always false */
        {
        do_false:
          /* result is always false */
@@ -3613,7 +3680,7 @@ macro (ip)
          return;
        }
       maxnum = 0x7fffffff;
          return;
        }
       maxnum = 0x7fffffff;
-      if (mips_opts.isa >= 3 && sizeof (maxnum) > 4)
+      if (ISA_HAS_64BIT_REGS (mips_opts.isa) && sizeof (maxnum) > 4)
        {
          maxnum <<= 16;
          maxnum |= 0xffff;
        {
          maxnum <<= 16;
          maxnum |= 0xffff;
@@ -3623,7 +3690,7 @@ macro (ip)
       maxnum = - maxnum - 1;
       if (imm_expr.X_op == O_constant
          && imm_expr.X_add_number <= maxnum
       maxnum = - maxnum - 1;
       if (imm_expr.X_op == O_constant
          && imm_expr.X_add_number <= maxnum
-         && (mips_opts.isa < 3 || sizeof (maxnum) > 4))
+         && (! ISA_HAS_64BIT_REGS (mips_opts.isa) || sizeof (maxnum) > 4))
        {
        do_true:
          /* result is always true */
        {
        do_true:
          /* result is always true */
@@ -3660,7 +3727,7 @@ macro (ip)
       likely = 1;
     case M_BGTU_I:
       if (sreg == 0
       likely = 1;
     case M_BGTU_I:
       if (sreg == 0
-         || (mips_opts.isa < 3
+         || (! ISA_HAS_64BIT_REGS (mips_opts.isa)
              && imm_expr.X_op == O_constant
              && imm_expr.X_add_number == 0xffffffff))
        goto do_false;
              && imm_expr.X_op == O_constant
              && imm_expr.X_add_number == 0xffffffff))
        goto do_false;
@@ -3756,7 +3823,7 @@ macro (ip)
       likely = 1;
     case M_BLE_I:
       maxnum = 0x7fffffff;
       likely = 1;
     case M_BLE_I:
       maxnum = 0x7fffffff;
-      if (mips_opts.isa >= 3 && sizeof (maxnum) > 4)
+      if (ISA_HAS_64BIT_REGS (mips_opts.isa) && sizeof (maxnum) > 4)
        {
          maxnum <<= 16;
          maxnum |= 0xffff;
        {
          maxnum <<= 16;
          maxnum |= 0xffff;
@@ -3765,7 +3832,7 @@ macro (ip)
        }
       if (imm_expr.X_op == O_constant
          && imm_expr.X_add_number >= maxnum
        }
       if (imm_expr.X_op == O_constant
          && imm_expr.X_add_number >= maxnum
-         && (mips_opts.isa < 3 || sizeof (maxnum) > 4))
+         && (! ISA_HAS_64BIT_REGS (mips_opts.isa) || sizeof (maxnum) > 4))
        goto do_true;
       if (imm_expr.X_op != O_constant)
        as_bad (_("Unsupported large constant"));
        goto do_true;
       if (imm_expr.X_op != O_constant)
        as_bad (_("Unsupported large constant"));
@@ -3818,7 +3885,7 @@ macro (ip)
       likely = 1;
     case M_BLEU_I:
       if (sreg == 0
       likely = 1;
     case M_BLEU_I:
       if (sreg == 0
-         || (mips_opts.isa < 3
+         || (! ISA_HAS_64BIT_REGS (mips_opts.isa)
              && imm_expr.X_op == O_constant
              && imm_expr.X_add_number == 0xffffffff))
        goto do_true;
              && imm_expr.X_op == O_constant
              && imm_expr.X_add_number == 0xffffffff))
        goto do_true;
@@ -4095,28 +4162,29 @@ macro (ip)
       /* When generating embedded PIC code, we permit expressions of
         the form
           la   $4,foo-bar
       /* When generating embedded PIC code, we permit expressions of
         the form
           la   $4,foo-bar
-        where bar is an address in the .text section.  These are used
+        where bar is an address in the current section.  These are used
         when getting the addresses of functions.  We don't permit
         X_add_number to be non-zero, because if the symbol is
         external the relaxing code needs to know that any addend is
         purely the offset to X_op_symbol.  */
       if (mips_pic == EMBEDDED_PIC
          && offset_expr.X_op == O_subtract
         when getting the addresses of functions.  We don't permit
         X_add_number to be non-zero, because if the symbol is
         external the relaxing code needs to know that any addend is
         purely the offset to X_op_symbol.  */
       if (mips_pic == EMBEDDED_PIC
          && offset_expr.X_op == O_subtract
-         && now_seg == text_section
-         && (offset_expr.X_op_symbol->sy_value.X_op == O_constant
-             ? S_GET_SEGMENT (offset_expr.X_op_symbol) == text_section
-             : (offset_expr.X_op_symbol->sy_value.X_op == O_symbol
-                && (S_GET_SEGMENT (offset_expr.X_op_symbol
-                                   ->sy_value.X_add_symbol)
-                    == text_section)))
+         && (symbol_constant_p (offset_expr.X_op_symbol)
+             ? S_GET_SEGMENT (offset_expr.X_op_symbol) == now_seg
+             : (symbol_equated_p (offset_expr.X_op_symbol)
+                && (S_GET_SEGMENT
+                    (symbol_get_value_expression (offset_expr.X_op_symbol)
+                     ->X_add_symbol)
+                    == now_seg)))
          && breg == 0
          && breg == 0
-         && offset_expr.X_add_number == 0)
+         && (offset_expr.X_add_number == 0
+             || OUTPUT_FLAVOR == bfd_target_elf_flavour))
        {
          macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
                       treg, (int) BFD_RELOC_PCREL_HI16_S);
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
        {
          macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
                       treg, (int) BFD_RELOC_PCREL_HI16_S);
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa  < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "addiu" : "daddiu"),
                       "t,r,j", treg, treg, (int) BFD_RELOC_PCREL_LO16);
          return;
                        ? "addiu" : "daddiu"),
                       "t,r,j", treg, treg, (int) BFD_RELOC_PCREL_LO16);
          return;
@@ -4159,7 +4227,7 @@ macro (ip)
              frag_grow (20);
              macro_build ((char *) NULL, &icnt, &offset_expr,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
              frag_grow (20);
              macro_build ((char *) NULL, &icnt, &offset_expr,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa  < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addiu" : "daddiu"),
                           "t,r,j", tempreg, GP, (int) BFD_RELOC_MIPS_GPREL);
              p = frag_var (rs_machine_dependent, 8, 0,
                            ? "addiu" : "daddiu"),
                           "t,r,j", tempreg, GP, (int) BFD_RELOC_MIPS_GPREL);
              p = frag_var (rs_machine_dependent, 8, 0,
@@ -4173,7 +4241,7 @@ macro (ip)
            p += 4;
          macro_build (p, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
            p += 4;
          macro_build (p, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa  < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "addiu" : "daddiu"),
                       "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
        }
                        ? "addiu" : "daddiu"),
                       "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
        }
@@ -4240,7 +4308,7 @@ macro (ip)
                }
              macro_build (p, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
                }
              macro_build (p, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addiu" : "daddiu"),
                           "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
              /* FIXME: If breg == 0, and the next instruction uses
                            ? "addiu" : "daddiu"),
                           "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
              /* FIXME: If breg == 0, and the next instruction uses
@@ -4254,7 +4322,7 @@ macro (ip)
                           "nop", "");
              macro_build ((char *) NULL, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
                           "nop", "");
              macro_build ((char *) NULL, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addiu" : "daddiu"),
                           "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
              (void) frag_var (rs_machine_dependent, 0, 0,
                            ? "addiu" : "daddiu"),
                           "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
              (void) frag_var (rs_machine_dependent, 0, 0,
@@ -4281,7 +4349,7 @@ macro (ip)
                               "nop", "");
                  macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                               ((bfd_arch_bits_per_address (stdoutput) == 32
                               "nop", "");
                  macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                               ((bfd_arch_bits_per_address (stdoutput) == 32
-                                || mips_opts.isa < 3)
+                                || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                                ? "addu" : "daddu"),
                               "d,v,t", treg, AT, breg);
                  breg = 0;
                                ? "addu" : "daddu"),
                               "d,v,t", treg, AT, breg);
                  breg = 0;
@@ -4298,12 +4366,12 @@ macro (ip)
 
              macro_build ((char *) NULL, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
 
              macro_build ((char *) NULL, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addiu" : "daddiu"),
                           "t,r,j", AT, AT, (int) BFD_RELOC_LO16);
              macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
                            ? "addiu" : "daddiu"),
                           "t,r,j", AT, AT, (int) BFD_RELOC_LO16);
              macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addu" : "daddu"),
                           "d,v,t", tempreg, tempreg, AT);
              (void) frag_var (rs_machine_dependent, 0, 0,
                            ? "addu" : "daddu"),
                           "d,v,t", tempreg, tempreg, AT);
              (void) frag_var (rs_machine_dependent, 0, 0,
@@ -4364,7 +4432,7 @@ macro (ip)
                       tempreg, (int) BFD_RELOC_MIPS_GOT_HI16);
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
                       tempreg, (int) BFD_RELOC_MIPS_GOT_HI16);
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "addu" : "daddu"),
                       "d,v,t", tempreg, tempreg, GP);
          macro_build ((char *) NULL, &icnt, &offset_expr,
                        ? "addu" : "daddu"),
                       "d,v,t", tempreg, tempreg, GP);
          macro_build ((char *) NULL, &icnt, &offset_expr,
@@ -4403,7 +4471,7 @@ macro (ip)
                           "nop", "");
              macro_build ((char *) NULL, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
                           "nop", "");
              macro_build ((char *) NULL, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addiu" : "daddiu"),
                           "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
 
                            ? "addiu" : "daddiu"),
                           "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
 
@@ -4438,7 +4506,7 @@ macro (ip)
                               "nop", "");
                  macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                               ((bfd_arch_bits_per_address (stdoutput) == 32
                               "nop", "");
                  macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                               ((bfd_arch_bits_per_address (stdoutput) == 32
-                                || mips_opts.isa < 3)
+                                || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                                ? "addu" : "daddu"),
                               "d,v,t", treg, AT, breg);
                  dreg = treg;
                                ? "addu" : "daddu"),
                               "d,v,t", treg, AT, breg);
                  dreg = treg;
@@ -4454,12 +4522,12 @@ macro (ip)
 
              macro_build ((char *) NULL, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
 
              macro_build ((char *) NULL, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addiu" : "daddiu"),
                           "t,r,j", AT, AT, (int) BFD_RELOC_LO16);
              macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
                            ? "addiu" : "daddiu"),
                           "t,r,j", AT, AT, (int) BFD_RELOC_LO16);
              macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addu" : "daddu"),
                           "d,v,t", dreg, dreg, AT);
 
                            ? "addu" : "daddu"),
                           "d,v,t", dreg, dreg, AT);
 
@@ -4493,7 +4561,7 @@ macro (ip)
              p += 4;
              macro_build (p, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
              p += 4;
              macro_build (p, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addiu" : "daddiu"),
                           "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
              /* FIXME: If add_number is 0, and there was no base
                            ? "addiu" : "daddiu"),
                           "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
              /* FIXME: If add_number is 0, and there was no base
@@ -4513,7 +4581,7 @@ macro (ip)
                  p += 4;
                  macro_build (p, &icnt, (expressionS *) NULL,
                               ((bfd_arch_bits_per_address (stdoutput) == 32
                  p += 4;
                  macro_build (p, &icnt, (expressionS *) NULL,
                               ((bfd_arch_bits_per_address (stdoutput) == 32
-                                || mips_opts.isa < 3)
+                                || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                                ? "addu" : "daddu"),
                               "d,v,t", treg, AT, breg);
                  p += 4;
                                ? "addu" : "daddu"),
                               "d,v,t", treg, AT, breg);
                  p += 4;
@@ -4527,13 +4595,13 @@ macro (ip)
              p += 4;
              macro_build (p, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
              p += 4;
              macro_build (p, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addiu" : "daddiu"),
                           "t,r,j", AT, AT, (int) BFD_RELOC_LO16);
              p += 4;
              macro_build (p, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
                            ? "addiu" : "daddiu"),
                           "t,r,j", AT, AT, (int) BFD_RELOC_LO16);
              p += 4;
              macro_build (p, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addu" : "daddu"),
                           "d,v,t", tempreg, tempreg, AT);
              p += 4;
                            ? "addu" : "daddu"),
                           "d,v,t", tempreg, tempreg, AT);
              p += 4;
@@ -4546,7 +4614,7 @@ macro (ip)
             */
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
             */
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "addiu" : "daddiu"),
                       "t,r,j", tempreg, GP, (int) BFD_RELOC_MIPS_GPREL);
        }
                        ? "addiu" : "daddiu"),
                       "t,r,j", tempreg, GP, (int) BFD_RELOC_MIPS_GPREL);
        }
@@ -4556,7 +4624,7 @@ macro (ip)
       if (breg != 0)
        macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                     ((bfd_arch_bits_per_address (stdoutput) == 32
       if (breg != 0)
        macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                     ((bfd_arch_bits_per_address (stdoutput) == 32
-                      || mips_opts.isa < 3)
+                      || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                      ? "addu" : "daddu"),
                     "d,v,t", treg, tempreg, breg);
 
                      ? "addu" : "daddu"),
                     "d,v,t", treg, tempreg, breg);
 
@@ -4600,7 +4668,7 @@ macro (ip)
              expr1.X_add_number = mips_cprestore_offset;
              macro_build ((char *) NULL, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
              expr1.X_add_number = mips_cprestore_offset;
              macro_build ((char *) NULL, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "lw" : "ld"),
                           "t,o(b)", GP, (int) BFD_RELOC_LO16, mips_frame_reg);
            }
                            ? "lw" : "ld"),
                           "t,o(b)", GP, (int) BFD_RELOC_LO16, mips_frame_reg);
            }
@@ -4643,7 +4711,7 @@ macro (ip)
            {
              macro_build ((char *) NULL, &icnt, &offset_expr,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
            {
              macro_build ((char *) NULL, &icnt, &offset_expr,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "lw" : "ld"),
                           "t,o(b)", PIC_CALL_REG,
                           (int) BFD_RELOC_MIPS_CALL16, GP);
                            ? "lw" : "ld"),
                           "t,o(b)", PIC_CALL_REG,
                           (int) BFD_RELOC_MIPS_CALL16, GP);
@@ -4666,12 +4734,12 @@ macro (ip)
                           PIC_CALL_REG, (int) BFD_RELOC_MIPS_CALL_HI16);
              macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
                           PIC_CALL_REG, (int) BFD_RELOC_MIPS_CALL_HI16);
              macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addu" : "daddu"),
                           "d,v,t", PIC_CALL_REG, PIC_CALL_REG, GP);
              macro_build ((char *) NULL, &icnt, &offset_expr,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
                            ? "addu" : "daddu"),
                           "d,v,t", PIC_CALL_REG, PIC_CALL_REG, GP);
              macro_build ((char *) NULL, &icnt, &offset_expr,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "lw" : "ld"),
                           "t,o(b)", PIC_CALL_REG,
                           (int) BFD_RELOC_MIPS_CALL_LO16, PIC_CALL_REG);
                            ? "lw" : "ld"),
                           "t,o(b)", PIC_CALL_REG,
                           (int) BFD_RELOC_MIPS_CALL_LO16, PIC_CALL_REG);
@@ -4689,7 +4757,7 @@ macro (ip)
                }
              macro_build (p, &icnt, &offset_expr,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
                }
              macro_build (p, &icnt, &offset_expr,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "lw" : "ld"),
                           "t,o(b)", PIC_CALL_REG,
                           (int) BFD_RELOC_MIPS_GOT16, GP);
                            ? "lw" : "ld"),
                           "t,o(b)", PIC_CALL_REG,
                           (int) BFD_RELOC_MIPS_GOT16, GP);
@@ -4699,7 +4767,7 @@ macro (ip)
            }                      
          macro_build (p, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
            }                      
          macro_build (p, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "addiu" : "daddiu"),
                       "t,r,j", PIC_CALL_REG, PIC_CALL_REG,
                       (int) BFD_RELOC_LO16);
                        ? "addiu" : "daddiu"),
                       "t,r,j", PIC_CALL_REG, PIC_CALL_REG,
                       (int) BFD_RELOC_LO16);
@@ -4715,7 +4783,7 @@ macro (ip)
              expr1.X_add_number = mips_cprestore_offset;
              macro_build ((char *) NULL, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
              expr1.X_add_number = mips_cprestore_offset;
              macro_build ((char *) NULL, &icnt, &expr1,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "lw" : "ld"),
                           "t,o(b)", GP, (int) BFD_RELOC_LO16,
                           mips_frame_reg);
                            ? "lw" : "ld"),
                           "t,o(b)", GP, (int) BFD_RELOC_LO16,
                           mips_frame_reg);
@@ -4972,7 +5040,7 @@ macro (ip)
                  frag_grow (28);
                  macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                               ((bfd_arch_bits_per_address (stdoutput) == 32
                  frag_grow (28);
                  macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                               ((bfd_arch_bits_per_address (stdoutput) == 32
-                                || mips_opts.isa < 3)
+                                || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                                ? "addu" : "daddu"),
                               "d,v,t", tempreg, breg, GP);
                  macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
                                ? "addu" : "daddu"),
                               "d,v,t", tempreg, breg, GP);
                  macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
@@ -4987,7 +5055,7 @@ macro (ip)
                p += 4;
              macro_build (p, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
                p += 4;
              macro_build (p, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addu" : "daddu"),
                           "d,v,t", tempreg, tempreg, breg);
              if (p != NULL)
                            ? "addu" : "daddu"),
                           "d,v,t", tempreg, tempreg, breg);
              if (p != NULL)
@@ -5022,7 +5090,7 @@ macro (ip)
          frag_grow (20);
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
          frag_grow (20);
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "lw" : "ld"),
                       "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16, GP);
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
                        ? "lw" : "ld"),
                       "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16, GP);
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
@@ -5032,13 +5100,13 @@ macro (ip)
                        (char *) NULL);
          macro_build (p, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
                        (char *) NULL);
          macro_build (p, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "addiu" : "daddiu"),
                       "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
          if (breg != 0)
            macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                         ((bfd_arch_bits_per_address (stdoutput) == 32
                        ? "addiu" : "daddiu"),
                       "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
          if (breg != 0)
            macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                         ((bfd_arch_bits_per_address (stdoutput) == 32
-                          || mips_opts.isa < 3)
+                          || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                          ? "addu" : "daddu"),
                         "d,v,t", tempreg, tempreg, breg);
          macro_build ((char *) NULL, &icnt, &expr1, s, fmt, treg,
                          ? "addu" : "daddu"),
                         "d,v,t", tempreg, tempreg, breg);
          macro_build ((char *) NULL, &icnt, &expr1, s, fmt, treg,
@@ -5079,12 +5147,12 @@ macro (ip)
                       tempreg, (int) BFD_RELOC_MIPS_GOT_HI16);
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
                       tempreg, (int) BFD_RELOC_MIPS_GOT_HI16);
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "addu" : "daddu"),
                       "d,v,t", tempreg, tempreg, GP);
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
                        ? "addu" : "daddu"),
                       "d,v,t", tempreg, tempreg, GP);
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "lw" : "ld"),
                       "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT_LO16,
                       tempreg);
                        ? "lw" : "ld"),
                       "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT_LO16,
                       tempreg);
@@ -5098,7 +5166,7 @@ macro (ip)
            }
          macro_build (p, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
            }
          macro_build (p, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "lw" : "ld"),
                       "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16, GP);
          p += 4;
                        ? "lw" : "ld"),
                       "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16, GP);
          p += 4;
@@ -5106,13 +5174,13 @@ macro (ip)
          p += 4;
          macro_build (p, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
          p += 4;
          macro_build (p, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "addiu" : "daddiu"),
                       "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
          if (breg != 0)
            macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                         ((bfd_arch_bits_per_address (stdoutput) == 32
                        ? "addiu" : "daddiu"),
                       "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
          if (breg != 0)
            macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                         ((bfd_arch_bits_per_address (stdoutput) == 32
-                          || mips_opts.isa < 3)
+                          || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                          ? "addu" : "daddu"),
                         "d,v,t", tempreg, tempreg, breg);
          macro_build ((char *) NULL, &icnt, &expr1, s, fmt, treg,
                          ? "addu" : "daddu"),
                         "d,v,t", tempreg, tempreg, breg);
          macro_build ((char *) NULL, &icnt, &expr1, s, fmt, treg,
@@ -5137,7 +5205,7 @@ macro (ip)
            {
              macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
            {
              macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addu" : "daddu"),
                           "d,v,t", tempreg, breg, GP);
              macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
                            ? "addu" : "daddu"),
                           "d,v,t", tempreg, breg, GP);
              macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
@@ -5188,7 +5256,7 @@ macro (ip)
          or in offset_expr.  */
       if (imm_expr.X_op == O_constant || imm_expr.X_op == O_big)
        {
          or in offset_expr.  */
       if (imm_expr.X_op == O_constant || imm_expr.X_op == O_big)
        {
-         if (mips_opts.isa >= 3)
+         if (ISA_HAS_64BIT_REGS (mips_opts.isa))
            load_register (&icnt, treg, &imm_expr, 1);
          else
            {
            load_register (&icnt, treg, &imm_expr, 1);
          else
            {
@@ -5233,7 +5301,7 @@ macro (ip)
        {
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
        {
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "lw" : "ld"),
                       "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16, GP);
        }
                        ? "lw" : "ld"),
                       "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16, GP);
        }
@@ -5243,7 +5311,7 @@ macro (ip)
             a single instruction.  */
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
             a single instruction.  */
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "addiu" : "daddiu"),
                       "t,r,j", AT, GP, (int) BFD_RELOC_MIPS_GPREL);
          offset_expr.X_op = O_constant;
                        ? "addiu" : "daddiu"),
                       "t,r,j", AT, GP, (int) BFD_RELOC_MIPS_GPREL);
          offset_expr.X_op = O_constant;
@@ -5253,7 +5321,7 @@ macro (ip)
        abort ();
        
       /* Now we load the register(s).  */
        abort ();
        
       /* Now we load the register(s).  */
-      if (mips_opts.isa >= 3)
+      if (ISA_HAS_64BIT_REGS (mips_opts.isa))
        macro_build ((char *) NULL, &icnt, &offset_expr, "ld", "t,o(b)",
                     treg, (int) BFD_RELOC_LO16, AT);
       else
        macro_build ((char *) NULL, &icnt, &offset_expr, "ld", "t,o(b)",
                     treg, (int) BFD_RELOC_LO16, AT);
       else
@@ -5284,8 +5352,8 @@ macro (ip)
          or in offset_expr.  */
       if (imm_expr.X_op == O_constant || imm_expr.X_op == O_big)
        {
          or in offset_expr.  */
       if (imm_expr.X_op == O_constant || imm_expr.X_op == O_big)
        {
-         load_register (&icnt, AT, &imm_expr, mips_opts.isa >= 3);
-         if (mips_opts.isa >= 3)
+         load_register (&icnt, AT, &imm_expr, ISA_HAS_64BIT_REGS (mips_opts.isa));
+         if (ISA_HAS_64BIT_REGS (mips_opts.isa))
            macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                         "dmtc1", "t,S", AT, treg);
          else
            macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                         "dmtc1", "t,S", AT, treg);
          else
@@ -5311,7 +5379,7 @@ macro (ip)
       s = segment_name (S_GET_SEGMENT (offset_expr.X_add_symbol));
       if (strcmp (s, ".lit8") == 0)
        {
       s = segment_name (S_GET_SEGMENT (offset_expr.X_add_symbol));
       if (strcmp (s, ".lit8") == 0)
        {
-         if (mips_opts.isa >= 2)
+         if (mips_opts.isa != 1)
            {
              macro_build ((char *) NULL, &icnt, &offset_expr, "ldc1",
                           "T,o(b)", treg, (int) BFD_RELOC_MIPS_LITERAL, GP);
            {
              macro_build ((char *) NULL, &icnt, &offset_expr, "ldc1",
                           "T,o(b)", treg, (int) BFD_RELOC_MIPS_LITERAL, GP);
@@ -5327,7 +5395,7 @@ macro (ip)
          if (mips_pic == SVR4_PIC)
            macro_build ((char *) NULL, &icnt, &offset_expr,
                         ((bfd_arch_bits_per_address (stdoutput) == 32
          if (mips_pic == SVR4_PIC)
            macro_build ((char *) NULL, &icnt, &offset_expr,
                         ((bfd_arch_bits_per_address (stdoutput) == 32
-                          || mips_opts.isa < 3)
+                          || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                          ? "lw" : "ld"),
                         "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16, GP);
          else
                          ? "lw" : "ld"),
                         "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16, GP);
          else
@@ -5336,7 +5404,7 @@ macro (ip)
              macro_build_lui ((char *) NULL, &icnt, &offset_expr, AT);
            }
              
              macro_build_lui ((char *) NULL, &icnt, &offset_expr, AT);
            }
              
-         if (mips_opts.isa >= 2)
+         if (mips_opts.isa != 1)
            {
              macro_build ((char *) NULL, &icnt, &offset_expr, "ldc1",
                           "T,o(b)", treg, (int) BFD_RELOC_LO16, AT);
            {
              macro_build ((char *) NULL, &icnt, &offset_expr, "ldc1",
                           "T,o(b)", treg, (int) BFD_RELOC_LO16, AT);
@@ -5363,7 +5431,7 @@ macro (ip)
         to adjust when loading from memory.  */
       r = BFD_RELOC_LO16;
     dob:
         to adjust when loading from memory.  */
       r = BFD_RELOC_LO16;
     dob:
-      assert (mips_opts.isa < 2);
+      assert (mips_opts.isa == 1);
       macro_build ((char *) NULL, &icnt, &offset_expr, "lwc1", "T,o(b)",
                   target_big_endian ? treg + 1 : treg,
                   (int) r, breg);
       macro_build ((char *) NULL, &icnt, &offset_expr, "lwc1", "T,o(b)",
                   target_big_endian ? treg + 1 : treg,
                   (int) r, breg);
@@ -5402,7 +5470,7 @@ macro (ip)
        }
       /* Itbl support may require additional care here. */
       coproc = 1;
        }
       /* Itbl support may require additional care here. */
       coproc = 1;
-      if (mips_opts.isa >= 2)
+      if (mips_opts.isa != 1)
        {
          s = "ldc1";
          goto ld;
        {
          s = "ldc1";
          goto ld;
@@ -5419,7 +5487,7 @@ macro (ip)
          return;
        }
 
          return;
        }
 
-      if (mips_opts.isa >= 2)
+      if (mips_opts.isa != 1)
        {
          s = "sdc1";
          goto st;
        {
          s = "sdc1";
          goto st;
@@ -5432,7 +5500,7 @@ macro (ip)
       goto ldd_std;
 
     case M_LD_AB:
       goto ldd_std;
 
     case M_LD_AB:
-      if (mips_opts.isa >= 3)
+      if (ISA_HAS_64BIT_REGS (mips_opts.isa))
        {
          s = "ld";
          goto ld;
        {
          s = "ld";
          goto ld;
@@ -5443,7 +5511,7 @@ macro (ip)
       goto ldd_std;
 
     case M_SD_AB:
       goto ldd_std;
 
     case M_SD_AB:
-      if (mips_opts.isa >= 3)
+      if (ISA_HAS_64BIT_REGS (mips_opts.isa))
        {
          s = "sd";
          goto st;
        {
          s = "sd";
          goto st;
@@ -5506,7 +5574,7 @@ macro (ip)
                  frag_grow (36);
                  macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                               ((bfd_arch_bits_per_address (stdoutput) == 32
                  frag_grow (36);
                  macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                               ((bfd_arch_bits_per_address (stdoutput) == 32
-                                || mips_opts.isa < 3)
+                                || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                                ? "addu" : "daddu"),
                               "d,v,t", AT, breg, GP);
                  tempreg = AT;
                                ? "addu" : "daddu"),
                               "d,v,t", AT, breg, GP);
                  tempreg = AT;
@@ -5564,7 +5632,7 @@ macro (ip)
            {
              macro_build (p, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
            {
              macro_build (p, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addu" : "daddu"),
                           "d,v,t", AT, breg, AT);
              if (p != NULL)
                            ? "addu" : "daddu"),
                           "d,v,t", AT, breg, AT);
              if (p != NULL)
@@ -5613,14 +5681,14 @@ macro (ip)
          frag_grow (24 + off);
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
          frag_grow (24 + off);
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "lw" : "ld"),
                       "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16, GP);
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
          if (breg != 0)
            macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                         ((bfd_arch_bits_per_address (stdoutput) == 32
                        ? "lw" : "ld"),
                       "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16, GP);
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
          if (breg != 0)
            macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                         ((bfd_arch_bits_per_address (stdoutput) == 32
-                          || mips_opts.isa < 3)
+                          || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                          ? "addu" : "daddu"),
                         "d,v,t", AT, breg, AT);
           /* Itbl support may require additional care here. */
                          ? "addu" : "daddu"),
                         "d,v,t", AT, breg, AT);
           /* Itbl support may require additional care here. */
@@ -5682,19 +5750,19 @@ macro (ip)
                       AT, (int) BFD_RELOC_MIPS_GOT_HI16);
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
                       AT, (int) BFD_RELOC_MIPS_GOT_HI16);
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "addu" : "daddu"),
                       "d,v,t", AT, AT, GP);
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
                        ? "addu" : "daddu"),
                       "d,v,t", AT, AT, GP);
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "lw" : "ld"),
                       "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT_LO16, AT);
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
          if (breg != 0)
            macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                         ((bfd_arch_bits_per_address (stdoutput) == 32
                        ? "lw" : "ld"),
                       "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT_LO16, AT);
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
          if (breg != 0)
            macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                         ((bfd_arch_bits_per_address (stdoutput) == 32
-                          || mips_opts.isa < 3)
+                          || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                          ? "addu" : "daddu"),
                         "d,v,t", AT, breg, AT);
           /* Itbl support may require additional care here. */
                          ? "addu" : "daddu"),
                         "d,v,t", AT, breg, AT);
           /* Itbl support may require additional care here. */
@@ -5726,7 +5794,7 @@ macro (ip)
            }
          macro_build (p, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
            }
          macro_build (p, &icnt, &offset_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "lw" : "ld"),
                       "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16, GP);
          p += 4;
                        ? "lw" : "ld"),
                       "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16, GP);
          p += 4;
@@ -5736,7 +5804,7 @@ macro (ip)
            {
              macro_build (p, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
            {
              macro_build (p, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addu" : "daddu"),
                           "d,v,t", AT, breg, AT);
              p += 4;
                            ? "addu" : "daddu"),
                           "d,v,t", AT, breg, AT);
              p += 4;
@@ -5777,7 +5845,7 @@ macro (ip)
            {
              macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
            {
              macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                           ((bfd_arch_bits_per_address (stdoutput) == 32
-                            || mips_opts.isa < 3)
+                            || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                            ? "addu" : "daddu"),
                           "d,v,t", AT, breg, GP);
              tempreg = AT;
                            ? "addu" : "daddu"),
                           "d,v,t", AT, breg, GP);
              tempreg = AT;
@@ -5808,7 +5876,8 @@ macro (ip)
     case M_SD_OB:
       s = "sw";
     sd_ob:
     case M_SD_OB:
       s = "sw";
     sd_ob:
-      assert (bfd_arch_bits_per_address (stdoutput) == 32 || mips_opts.isa < 3);
+      assert (bfd_arch_bits_per_address (stdoutput) == 32 
+             || ! ISA_HAS_64BIT_REGS (mips_opts.isa));
       macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg,
                   (int) BFD_RELOC_LO16, breg);
       offset_expr.X_add_number += 4;
       macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg,
                   (int) BFD_RELOC_LO16, breg);
       offset_expr.X_add_number += 4;
@@ -6046,7 +6115,7 @@ macro2 (ip)
          as_bad (_("opcode not supported on this processor"));
          return;
        }
          as_bad (_("opcode not supported on this processor"));
          return;
        }
-      assert (mips_opts.isa < 2);
+      assert (mips_opts.isa == 1);
       /* Even on a big endian machine $fn comes before $fn+1.  We have
         to adjust when storing to memory.  */
       macro_build ((char *) NULL, &icnt, &offset_expr, "swc1", "T,o(b)",
       /* Even on a big endian machine $fn comes before $fn+1.  We have
         to adjust when storing to memory.  */
       macro_build ((char *) NULL, &icnt, &offset_expr, "swc1", "T,o(b)",
@@ -6103,7 +6172,7 @@ macro2 (ip)
          imm_expr.X_add_number = -imm_expr.X_add_number;
          macro_build ((char *) NULL, &icnt, &imm_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
          imm_expr.X_add_number = -imm_expr.X_add_number;
          macro_build ((char *) NULL, &icnt, &imm_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "addiu" : "daddiu"),
                       "t,r,j", dreg, sreg,
                       (int) BFD_RELOC_LO16);
                        ? "addiu" : "daddiu"),
                       "t,r,j", dreg, sreg,
                       (int) BFD_RELOC_LO16);
@@ -6256,7 +6325,7 @@ macro2 (ip)
                   ip->insn_mo->name);
          macro_build ((char *) NULL, &icnt, &expr1,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
                   ip->insn_mo->name);
          macro_build ((char *) NULL, &icnt, &expr1,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "addiu" : "daddiu"),
                       "t,r,j", dreg, 0, (int) BFD_RELOC_LO16);
          return;
                        ? "addiu" : "daddiu"),
                       "t,r,j", dreg, 0, (int) BFD_RELOC_LO16);
          return;
@@ -6276,7 +6345,7 @@ macro2 (ip)
          imm_expr.X_add_number = -imm_expr.X_add_number;
          macro_build ((char *) NULL, &icnt, &imm_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
          imm_expr.X_add_number = -imm_expr.X_add_number;
          macro_build ((char *) NULL, &icnt, &imm_expr,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
-                        || mips_opts.isa < 3)
+                        || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                        ? "addiu" : "daddiu"),
                       "t,r,j", dreg, sreg, (int) BFD_RELOC_LO16);
          used_at = 0;
                        ? "addiu" : "daddiu"),
                       "t,r,j", dreg, sreg, (int) BFD_RELOC_LO16);
          used_at = 0;
@@ -6353,9 +6422,9 @@ macro2 (ip)
       macro_build ((char *) NULL, &icnt, NULL, s, "s,t", sreg, AT);
       break;
 
       macro_build ((char *) NULL, &icnt, NULL, s, "s,t", sreg, AT);
       break;
 
-    case M_TRUNCWD:
     case M_TRUNCWS:
     case M_TRUNCWS:
-      assert (mips_opts.isa < 2);
+    case M_TRUNCWD:
+      assert (mips_opts.isa == 1);
       sreg = (ip->insn_opcode >> 11) & 0x1f;   /* floating reg */
       dreg = (ip->insn_opcode >> 06) & 0x1f;   /* floating reg */
 
       sreg = (ip->insn_opcode >> 11) & 0x1f;   /* floating reg */
       dreg = (ip->insn_opcode >> 06) & 0x1f;   /* floating reg */
 
@@ -6445,7 +6514,7 @@ macro2 (ip)
       if (breg != 0)
        macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                     ((bfd_arch_bits_per_address (stdoutput) == 32
       if (breg != 0)
        macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                     ((bfd_arch_bits_per_address (stdoutput) == 32
-                      || mips_opts.isa < 3)
+                      || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                      ? "addu" : "daddu"),
                     "d,v,t", AT, AT, breg);
       if (! target_big_endian)
                      ? "addu" : "daddu"),
                     "d,v,t", AT, AT, breg);
       if (! target_big_endian)
@@ -6468,7 +6537,7 @@ macro2 (ip)
       if (breg != 0)
        macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                     ((bfd_arch_bits_per_address (stdoutput) == 32
       if (breg != 0)
        macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                     ((bfd_arch_bits_per_address (stdoutput) == 32
-                      || mips_opts.isa < 3)
+                      || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                      ? "addu" : "daddu"),
                     "d,v,t", AT, AT, breg);
       if (target_big_endian)
                      ? "addu" : "daddu"),
                     "d,v,t", AT, AT, breg);
       if (target_big_endian)
@@ -6542,7 +6611,7 @@ macro2 (ip)
       if (breg != 0)
        macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                     ((bfd_arch_bits_per_address (stdoutput) == 32
       if (breg != 0)
        macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                     ((bfd_arch_bits_per_address (stdoutput) == 32
-                      || mips_opts.isa < 3)
+                      || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                      ? "addu" : "daddu"),
                     "d,v,t", AT, AT, breg);
       if (! target_big_endian)
                      ? "addu" : "daddu"),
                     "d,v,t", AT, AT, breg);
       if (! target_big_endian)
@@ -6564,7 +6633,7 @@ macro2 (ip)
       if (breg != 0)
        macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                     ((bfd_arch_bits_per_address (stdoutput) == 32
       if (breg != 0)
        macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                     ((bfd_arch_bits_per_address (stdoutput) == 32
-                      || mips_opts.isa < 3)
+                      || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                      ? "addu" : "daddu"),
                     "d,v,t", AT, AT, breg);
       if (! target_big_endian)
                      ? "addu" : "daddu"),
                     "d,v,t", AT, AT, breg);
       if (! target_big_endian)
@@ -6942,7 +7011,7 @@ mips_ip (str, ip)
 {
   char *s;
   const char *args;
 {
   char *s;
   const char *args;
-  char c;
+  char c = 0;
   struct mips_opcode *insn;
   char *argsStart;
   unsigned int regno;
   struct mips_opcode *insn;
   char *argsStart;
   unsigned int regno;
@@ -6956,13 +7025,13 @@ mips_ip (str, ip)
   /* If the instruction contains a '.', we first try to match an instruction
      including the '.'.  Then we try again without the '.'.  */
   insn = NULL;
   /* If the instruction contains a '.', we first try to match an instruction
      including the '.'.  Then we try again without the '.'.  */
   insn = NULL;
-  for (s = str; *s != '\0' && !isspace(*s); ++s)
+  for (s = str; *s != '\0' && !isspace ((unsigned char) *s); ++s)
     continue;
 
   /* If we stopped on whitespace, then replace the whitespace with null for
      the call to hash_find.  Save the character we replaced just in case we
      have to re-parse the instruction.  */
     continue;
 
   /* If we stopped on whitespace, then replace the whitespace with null for
      the call to hash_find.  Save the character we replaced just in case we
      have to re-parse the instruction.  */
-  if (isspace (*s))
+  if (isspace ((unsigned char) *s))
     {
       save_c = *s;
       *s++ = '\0';
     {
       save_c = *s;
       *s++ = '\0';
@@ -6980,7 +7049,7 @@ mips_ip (str, ip)
        *(--s) = save_c;
 
       /* Scan up to the first '.' or whitespace.  */
        *(--s) = save_c;
 
       /* Scan up to the first '.' or whitespace.  */
-      for (s = str; *s != '\0' && *s != '.' && !isspace (*s); ++s)
+      for (s = str; *s != '\0' && *s != '.' && !isspace ((unsigned char) *s); ++s)
        continue;
 
       /* If we did not find a '.', then we can quit now.  */
        continue;
 
       /* If we did not find a '.', then we can quit now.  */
@@ -7004,37 +7073,15 @@ mips_ip (str, ip)
   argsStart = s;
   for (;;)
     {
   argsStart = s;
   for (;;)
     {
-      int insn_isa;
       boolean ok;
 
       assert (strcmp (insn->name, str) == 0);
 
       boolean ok;
 
       assert (strcmp (insn->name, str) == 0);
 
-      if ((insn->membership & INSN_ISA) == INSN_ISA1)
-       insn_isa = 1;
-      else if ((insn->membership & INSN_ISA) == INSN_ISA2)
-       insn_isa = 2;
-      else if ((insn->membership & INSN_ISA) == INSN_ISA3)
-       insn_isa = 3;
-      else if ((insn->membership & INSN_ISA) == INSN_ISA4)
-       insn_isa = 4;
-      else
-       insn_isa = 15;
-
-      if (insn_isa <= mips_opts.isa)
-       ok = true;
-      else if (insn->pinfo == INSN_MACRO)
-       ok = false;
-      else if ((mips_cpu == 4650 && (insn->membership & INSN_4650) != 0)
-              || (mips_cpu == 4010 && (insn->membership & INSN_4010) != 0)
-              || ((mips_cpu == 4100
-                   || mips_cpu == 4111
-                   )
-                  && (insn->membership & INSN_4100) != 0)
-              || (mips_cpu == 3900 && (insn->membership & INSN_3900) != 0))
+      if (OPCODE_IS_MEMBER (insn, mips_opts.isa, mips_cpu, mips_gp32))
        ok = true;
        ok = true;
-      else
+      else 
        ok = false;
        ok = false;
-
+      
       if (insn->pinfo != INSN_MACRO)
        {
          if (mips_cpu == 4650 && (insn->pinfo & FP_D) != 0)
       if (insn->pinfo != INSN_MACRO)
        {
          if (mips_cpu == 4650 && (insn->pinfo & FP_D) != 0)
@@ -7049,17 +7096,16 @@ mips_ip (str, ip)
              ++insn;
              continue;
            }
              ++insn;
              continue;
            }
-         if (insn_isa == 15 
-              || insn_isa <= mips_opts.isa)
-           insn_error = _("opcode not supported on this processor");
          else
          else
-           {
+           {
              static char buf[100];
              static char buf[100];
-
-             sprintf (buf, _("opcode requires -mips%d or greater"), insn_isa);
+             sprintf (buf, 
+                      _("opcode not supported on this processor: %d (MIPS%d)"),
+                      mips_cpu, mips_opts.isa);
+                      
              insn_error = buf;
              insn_error = buf;
+             return;
            }
            }
-         return;
        }
 
       ip->insn_mo = insn;
        }
 
       ip->insn_mo = insn;
@@ -7246,7 +7292,7 @@ mips_ip (str, ip)
              if (s[0] == '$')
                {
 
              if (s[0] == '$')
                {
 
-                 if (isdigit (s[1]))
+                 if (isdigit ((unsigned char) s[1]))
                    {
                      ++s;
                      regno = 0;
                    {
                      ++s;
                      regno = 0;
@@ -7256,7 +7302,7 @@ mips_ip (str, ip)
                          regno += *s - '0';
                          ++s;
                        }
                          regno += *s - '0';
                          ++s;
                        }
-                     while (isdigit (*s));
+                     while (isdigit ((unsigned char) *s));
                      if (regno > 31)
                        as_bad (_("Invalid register number (%d)"), regno);
                    }
                      if (regno > 31)
                        as_bad (_("Invalid register number (%d)"), regno);
                    }
@@ -7297,23 +7343,22 @@ mips_ip (str, ip)
                      else if (itbl_have_entries)
                        {
                          char *p, *n;
                      else if (itbl_have_entries)
                        {
                          char *p, *n;
-                         int r;
+                         unsigned long r;
 
 
-                         p = s+1;      /* advance past '$' */
+                         p = s + 1;    /* advance past '$' */
                          n = itbl_get_field (&p);  /* n is name */
 
                          n = itbl_get_field (&p);  /* n is name */
 
-                         /* See if this is a register defined in an 
-                            itbl entry */
-                         r = itbl_get_reg_val (n);
-                         if (r)
+                         /* See if this is a register defined in an
+                            itbl entry.  */
+                         if (itbl_get_reg_val (n, &r))
                            {
                              /* Get_field advances to the start of
                                 the next field, so we need to back
                            {
                              /* Get_field advances to the start of
                                 the next field, so we need to back
-                                rack to the end of the last field. */
+                                rack to the end of the last field.  */
                              if (p) 
                                s = p - 1;
                              else 
                              if (p) 
                                s = p - 1;
                              else 
-                               s = strchr (s,'\0');
+                               s = strchr (s, '\0');
                              regno = r;
                            }
                          else
                              regno = r;
                            }
                          else
@@ -7406,7 +7451,7 @@ mips_ip (str, ip)
            case 'V':
            case 'W':
              s_reset = s;
            case 'V':
            case 'W':
              s_reset = s;
-             if (s[0] == '$' && s[1] == 'f' && isdigit (s[2]))
+             if (s[0] == '$' && s[1] == 'f' && isdigit ((unsigned char) s[2]))
                {
                  s += 2;
                  regno = 0;
                {
                  s += 2;
                  regno = 0;
@@ -7416,13 +7461,13 @@ mips_ip (str, ip)
                      regno += *s - '0';
                      ++s;
                    }
                      regno += *s - '0';
                      ++s;
                    }
-                 while (isdigit (*s));
+                 while (isdigit ((unsigned char) *s));
 
                  if (regno > 31)
                    as_bad (_("Invalid float register number (%d)"), regno);
 
                  if ((regno & 1) != 0
 
                  if (regno > 31)
                    as_bad (_("Invalid float register number (%d)"), regno);
 
                  if ((regno & 1) != 0
-                     && mips_opts.isa < 3
+                     && ! ISA_HAS_64BIT_REGS (mips_opts.isa)
                      && ! (strcmp (str, "mtc1") == 0
                            || strcmp (str, "mfc1") == 0
                            || strcmp (str, "lwc1") == 0
                      && ! (strcmp (str, "mtc1") == 0
                            || strcmp (str, "mfc1") == 0
                            || strcmp (str, "lwc1") == 0
@@ -7564,6 +7609,7 @@ mips_ip (str, ip)
                      imm_expr.X_add_number = bfd_getb32 (temp);
                  }
                else if (length > 4
                      imm_expr.X_add_number = bfd_getb32 (temp);
                  }
                else if (length > 4
+                        && ! mips_disable_float_construction
                         && ((temp[0] == 0 && temp[1] == 0)
                             || (temp[2] == 0 && temp[3] == 0))
                         && ((temp[4] == 0 && temp[5] == 0)
                         && ((temp[0] == 0 && temp[1] == 0)
                             || (temp[2] == 0 && temp[3] == 0))
                         && ((temp[4] == 0 && temp[5] == 0)
@@ -7575,7 +7621,7 @@ mips_ip (str, ip)
                        offset_expr to the low order 32 bits.
                        Otherwise, set imm_expr to the entire 64 bit
                        constant.  */
                        offset_expr to the low order 32 bits.
                        Otherwise, set imm_expr to the entire 64 bit
                        constant.  */
-                   if (mips_opts.isa < 3)
+                   if (! ISA_HAS_64BIT_REGS (mips_opts.isa))
                      {
                        imm_expr.X_op = O_constant;
                        offset_expr.X_op = O_constant;
                      {
                        imm_expr.X_op = O_constant;
                        offset_expr.X_op = O_constant;
@@ -7633,11 +7679,15 @@ mips_ip (str, ip)
                      default: /* unused default case avoids warnings.  */
                      case 'L':
                        newname = RDATA_SECTION_NAME;
                      default: /* unused default case avoids warnings.  */
                      case 'L':
                        newname = RDATA_SECTION_NAME;
-                       if (USE_GLOBAL_POINTER_OPT && g_switch_value >= 8)
+                       if ((USE_GLOBAL_POINTER_OPT && g_switch_value >= 8)
+                           || mips_pic == EMBEDDED_PIC)
                          newname = ".lit8";
                        break;
                      case 'F':
                          newname = ".lit8";
                        break;
                      case 'F':
-                       newname = RDATA_SECTION_NAME;
+                       if (mips_pic == EMBEDDED_PIC)
+                         newname = ".lit8";
+                       else
+                         newname = RDATA_SECTION_NAME;
                        break;
                      case 'l':
                        assert (!USE_GLOBAL_POINTER_OPT
                        break;
                      case 'l':
                        assert (!USE_GLOBAL_POINTER_OPT
@@ -7711,10 +7761,8 @@ mips_ip (str, ip)
                      if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
                          !strcmp (insn->name, insn[1].name))
                        break;
                      if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
                          !strcmp (insn->name, insn[1].name))
                        break;
-                     if (imm_expr.X_op != O_constant
-                         && imm_expr.X_op != O_big)
-                       insn_error = _("absolute expression required");
-                     else
+                     if (imm_expr.X_op == O_constant
+                         || imm_expr.X_op == O_big)
                        as_bad (_("16 bit expression not in range 0..65535"));
                    }
                }
                        as_bad (_("16 bit expression not in range 0..65535"));
                    }
                }
@@ -7744,16 +7792,14 @@ mips_ip (str, ip)
                           && imm_expr.X_op == O_constant)
                      || (more
                          && imm_expr.X_add_number < 0
                           && imm_expr.X_op == O_constant)
                      || (more
                          && imm_expr.X_add_number < 0
-                         && mips_opts.isa >= 3
+                         && ISA_HAS_64BIT_REGS (mips_opts.isa)
                          && imm_expr.X_unsigned
                          && sizeof (imm_expr.X_add_number) <= 4))
                    {
                      if (more)
                        break;
                          && imm_expr.X_unsigned
                          && sizeof (imm_expr.X_add_number) <= 4))
                    {
                      if (more)
                        break;
-                     if (imm_expr.X_op != O_constant
-                         && imm_expr.X_op != O_big)
-                       insn_error = _("absolute expression required");
-                     else
+                     if (imm_expr.X_op == O_constant
+                         || imm_expr.X_op == O_big)
                        as_bad (_("16 bit expression not in range -32768..32767"));
                    }
                }
                        as_bad (_("16 bit expression not in range -32768..32767"));
                    }
                }
@@ -7780,9 +7826,8 @@ mips_ip (str, ip)
                      || offset_expr.X_add_number < -0x8000)
                  && (mips_pic != EMBEDDED_PIC
                      || offset_expr.X_op != O_subtract
                      || offset_expr.X_add_number < -0x8000)
                  && (mips_pic != EMBEDDED_PIC
                      || offset_expr.X_op != O_subtract
-                     || now_seg != text_section
                      || (S_GET_SEGMENT (offset_expr.X_op_symbol)
                      || (S_GET_SEGMENT (offset_expr.X_op_symbol)
-                         != text_section)))
+                         != now_seg)))
                break;
 
              if (c == 'h' || c == 'H')
                break;
 
              if (c == 'h' || c == 'H')
@@ -7848,7 +7893,7 @@ mips_ip (str, ip)
                  regno += *s - '0';
                  ++s;
                }
                  regno += *s - '0';
                  ++s;
                }
-             while (isdigit (*s));
+             while (isdigit ((unsigned char) *s));
              if (regno > 7)
                as_bad (_("invalid condition code register $fcc%d"), regno);
              if (*args == 'N')
              if (regno > 7)
                as_bad (_("invalid condition code register $fcc%d"), regno);
              if (*args == 'N')
@@ -7901,7 +7946,7 @@ mips16_ip (str, ip)
   mips16_small = false;
   mips16_ext = false;
 
   mips16_small = false;
   mips16_ext = false;
 
-  for (s = str; islower (*s); ++s)
+  for (s = str; islower ((unsigned char) *s); ++s)
     ;
   switch (*s)
     {
     ;
   switch (*s)
     {
@@ -8034,7 +8079,7 @@ mips16_ip (str, ip)
              if (s[0] != '$')
                break;
              s_reset = s;
              if (s[0] != '$')
                break;
              s_reset = s;
-             if (isdigit (s[1]))
+             if (isdigit ((unsigned char) s[1]))
                {
                  ++s;
                  regno = 0;
                {
                  ++s;
                  regno = 0;
@@ -8044,7 +8089,7 @@ mips16_ip (str, ip)
                      regno += *s - '0';
                      ++s;
                    }
                      regno += *s - '0';
                      ++s;
                    }
-                 while (isdigit (*s));
+                 while (isdigit ((unsigned char) *s));
                  if (regno > 31)
                    {
                      as_bad (_("invalid register number (%d)"), regno);
                  if (regno > 31)
                    {
                      as_bad (_("invalid register number (%d)"), regno);
@@ -8315,7 +8360,7 @@ mips16_ip (str, ip)
                        ++s;
                      }
                    reg1 = 0;
                        ++s;
                      }
                    reg1 = 0;
-                   while (isdigit (*s))
+                   while (isdigit ((unsigned char) *s))
                      {
                        reg1 *= 10;
                        reg1 += *s - '0';
                      {
                        reg1 *= 10;
                        reg1 += *s - '0';
@@ -8342,7 +8387,7 @@ mips16_ip (str, ip)
                              }
                          }
                        reg2 = 0;
                              }
                          }
                        reg2 = 0;
-                       while (isdigit (*s))
+                       while (isdigit ((unsigned char) *s))
                          {
                            reg2 *= 10;
                            reg2 += *s - '0';
                          {
                            reg2 *= 10;
                            reg2 += *s - '0';
@@ -8626,9 +8671,9 @@ my_getSmallExpression (ep, str)
        ;
       if (sp - 4 >= str && sp[-1] == RP)
        {
        ;
       if (sp - 4 >= str && sp[-1] == RP)
        {
-         if (isdigit (sp[-2]))
+         if (isdigit ((unsigned char) sp[-2]))
            {
            {
-             for (sp -= 3; sp >= str && isdigit (*sp); sp--)
+             for (sp -= 3; sp >= str && isdigit ((unsigned char) *sp); sp--)
                ;
              if (*sp == '$' && sp > str && sp[-1] == LP)
                {
                ;
              if (*sp == '$' && sp > str && sp[-1] == LP)
                {
@@ -8699,15 +8744,15 @@ my_getExpression (ep, str)
       && ep->X_op == O_symbol
       && strcmp (S_GET_NAME (ep->X_add_symbol), FAKE_LABEL_NAME) == 0
       && S_GET_SEGMENT (ep->X_add_symbol) == now_seg
       && ep->X_op == O_symbol
       && strcmp (S_GET_NAME (ep->X_add_symbol), FAKE_LABEL_NAME) == 0
       && S_GET_SEGMENT (ep->X_add_symbol) == now_seg
-      && ep->X_add_symbol->sy_frag == frag_now
-      && ep->X_add_symbol->sy_value.X_op == O_constant
-      && ep->X_add_symbol->sy_value.X_add_number == frag_now_fix ())
-    ++ep->X_add_symbol->sy_value.X_add_number;
+      && symbol_get_frag (ep->X_add_symbol) == frag_now
+      && symbol_constant_p (ep->X_add_symbol)
+      && S_GET_VALUE (ep->X_add_symbol) == frag_now_fix ())
+    S_SET_VALUE (ep->X_add_symbol, S_GET_VALUE (ep->X_add_symbol) + 1);
 }
 
 /* Turn a string in input_line_pointer into a floating point constant
 }
 
 /* Turn a string in input_line_pointer into a floating point constant
-   of type type, and store the appropriate bytes in *litP.  The number
-   of LITTLENUMS emitted is stored in *sizeP .  An error message is
+   of type TYPE, and store the appropriate bytes in *LITP.  The number
+   of LITTLENUMS emitted is stored in *SIZEP.  An error message is
    returned, or NULL on OK.  */
 
 char *
    returned, or NULL on OK.  */
 
 char *
@@ -8790,6 +8835,10 @@ struct option md_longopts[] = {
   {"mcpu", required_argument, NULL, OPTION_MCPU},
 #define OPTION_MEMBEDDED_PIC (OPTION_MD_BASE + 6)
   {"membedded-pic", no_argument, NULL, OPTION_MEMBEDDED_PIC},
   {"mcpu", required_argument, NULL, OPTION_MCPU},
 #define OPTION_MEMBEDDED_PIC (OPTION_MD_BASE + 6)
   {"membedded-pic", no_argument, NULL, OPTION_MEMBEDDED_PIC},
+
+#define OPTION_CALL_SHARED (OPTION_MD_BASE + 7)
+#define OPTION_NON_SHARED (OPTION_MD_BASE + 8)
+
 #define OPTION_TRAP (OPTION_MD_BASE + 9)
   {"trap", no_argument, NULL, OPTION_TRAP},
   {"no-break", no_argument, NULL, OPTION_TRAP},
 #define OPTION_TRAP (OPTION_MD_BASE + 9)
   {"trap", no_argument, NULL, OPTION_TRAP},
   {"no-break", no_argument, NULL, OPTION_TRAP},
@@ -8812,24 +8861,29 @@ struct option md_longopts[] = {
   {"m4100", no_argument, NULL, OPTION_M4100},
 #define OPTION_NO_M4100 (OPTION_MD_BASE + 18)
   {"no-m4100", no_argument, NULL, OPTION_NO_M4100},
   {"m4100", no_argument, NULL, OPTION_M4100},
 #define OPTION_NO_M4100 (OPTION_MD_BASE + 18)
   {"no-m4100", no_argument, NULL, OPTION_NO_M4100},
+
+#define OPTION_XGOT (OPTION_MD_BASE + 19)
+#define OPTION_32 (OPTION_MD_BASE + 20)
+#define OPTION_64 (OPTION_MD_BASE + 21)
+  
 #define OPTION_MIPS16 (OPTION_MD_BASE + 22)
   {"mips16", no_argument, NULL, OPTION_MIPS16},
 #define OPTION_NO_MIPS16 (OPTION_MD_BASE + 23)
   {"no-mips16", no_argument, NULL, OPTION_NO_MIPS16},
 #define OPTION_MIPS16 (OPTION_MD_BASE + 22)
   {"mips16", no_argument, NULL, OPTION_MIPS16},
 #define OPTION_NO_MIPS16 (OPTION_MD_BASE + 23)
   {"no-mips16", no_argument, NULL, OPTION_NO_MIPS16},
+
 #define OPTION_M3900 (OPTION_MD_BASE + 26)
   {"m3900", no_argument, NULL, OPTION_M3900},
 #define OPTION_NO_M3900 (OPTION_MD_BASE + 27)
   {"no-m3900", no_argument, NULL, OPTION_NO_M3900},
 
 #define OPTION_M3900 (OPTION_MD_BASE + 26)
   {"m3900", no_argument, NULL, OPTION_M3900},
 #define OPTION_NO_M3900 (OPTION_MD_BASE + 27)
   {"no-m3900", no_argument, NULL, OPTION_NO_M3900},
 
-
 #define OPTION_MABI (OPTION_MD_BASE + 38)
   {"mabi", required_argument, NULL, OPTION_MABI},
 
 #define OPTION_MABI (OPTION_MD_BASE + 38)
   {"mabi", required_argument, NULL, OPTION_MABI},
 
-#define OPTION_CALL_SHARED (OPTION_MD_BASE + 7)
-#define OPTION_NON_SHARED (OPTION_MD_BASE + 8)
-#define OPTION_XGOT (OPTION_MD_BASE + 19)
-#define OPTION_32 (OPTION_MD_BASE + 20)
-#define OPTION_64 (OPTION_MD_BASE + 21)
+#define OPTION_M7000_HILO_FIX (OPTION_MD_BASE + 39)
+  {"mfix7000", no_argument, NULL, OPTION_M7000_HILO_FIX},
+#define OPTION_NO_M7000_HILO_FIX (OPTION_MD_BASE + 40)
+  {"no-fix-7000", no_argument, NULL, OPTION_NO_M7000_HILO_FIX},
+
 #ifdef OBJ_ELF
   {"KPIC", no_argument, NULL, OPTION_CALL_SHARED},
   {"xgot", no_argument, NULL, OPTION_XGOT},
 #ifdef OBJ_ELF
   {"KPIC", no_argument, NULL, OPTION_CALL_SHARED},
   {"xgot", no_argument, NULL, OPTION_XGOT},
@@ -8839,6 +8893,17 @@ struct option md_longopts[] = {
   {"64", no_argument, NULL, OPTION_64},
 #endif
 
   {"64", no_argument, NULL, OPTION_64},
 #endif
 
+#define OPTION_GP32 (OPTION_MD_BASE + 41)
+#define OPTION_GP64 (OPTION_MD_BASE + 42)
+  {"mgp32", no_argument, NULL, OPTION_GP32},
+  {"mgp64", no_argument, NULL, OPTION_GP64},
+
+#define OPTION_CONSTRUCT_FLOATS (OPTION_MD_BASE + 43)
+  {"construct-floats", no_argument, NULL, OPTION_CONSTRUCT_FLOATS},
+
+#define OPTION_NO_CONSTRUCT_FLOATS (OPTION_MD_BASE + 44)
+  {"no-construct-floats", no_argument, NULL, OPTION_NO_CONSTRUCT_FLOATS},
+
   {NULL, no_argument, NULL, 0}
 };
 size_t md_longopts_size = sizeof(md_longopts);
   {NULL, no_argument, NULL, 0}
 };
 size_t md_longopts_size = sizeof(md_longopts);
@@ -8850,6 +8915,14 @@ md_parse_option (c, arg)
 {
   switch (c)
     {
 {
   switch (c)
     {
+    case OPTION_CONSTRUCT_FLOATS:
+      mips_disable_float_construction = 0;
+      break;
+      
+    case OPTION_NO_CONSTRUCT_FLOATS:
+      mips_disable_float_construction = 1;
+      break;
+      
     case OPTION_TRAP:
       mips_trap = 1;
       break;
     case OPTION_TRAP:
       mips_trap = 1;
       break;
@@ -8997,8 +9070,24 @@ md_parse_option (c, arg)
                if (strcmp (p, "orion") == 0)
                  mips_cpu = 4600;
                break;
                if (strcmp (p, "orion") == 0)
                  mips_cpu = 4600;
                break;
-             }
 
 
+             case 'm':
+             case 'M':
+               switch (atoi (p + 1))
+                 {
+                 case 5200:
+                 case 5230:
+                 case 5231:
+                 case 5261:
+                 case 5721:
+                 case 7000:
+                   mips_cpu = 5000;
+                   break;
+                 default:
+                   break;
+                 }
+             }
+           
            if (sv
                && (mips_cpu != 4300
                    && mips_cpu != 4100
            if (sv
                && (mips_cpu != 4300
                    && mips_cpu != 4100
@@ -9139,6 +9228,27 @@ md_parse_option (c, arg)
       }
       break;
 
       }
       break;
 
+    case OPTION_GP32:
+      mips_gp32 = 1;
+      mips_64 = 0;
+
+      /* We deliberately don't allow "-gp32" to set the MIPS_32BITMODE
+        flag in object files because to do so would make it
+        impossible to link with libraries compiled without "-gp32".
+        This is unnecessarily restrictive.  
+
+        We could solve this problem by adding "-gp32" multilibs to
+        gcc, but to set this flag before gcc is built with such
+        multilibs will break too many systems. */
+
+/*    mips_32bitmode = 1; */
+      break;
+
+    case OPTION_GP64:
+      mips_gp32 = 0;
+      mips_64 = 1;
+/*    mips_32bitmode = 0; */
+      break;
 
     case OPTION_MABI:
       if (strcmp (arg,"32") == 0
 
     case OPTION_MABI:
       if (strcmp (arg,"32") == 0
@@ -9149,6 +9259,14 @@ md_parse_option (c, arg)
        mips_abi_string = arg;
       break;
 
        mips_abi_string = arg;
       break;
 
+    case OPTION_M7000_HILO_FIX:
+      mips_7000_hilo_fix = true;
+      break;
+
+    case OPTION_NO_M7000_HILO_FIX:
+      mips_7000_hilo_fix = false;
+      break;
+
     default:
       return 0;
     }
     default:
       return 0;
     }
@@ -9247,6 +9365,7 @@ MIPS options:\n\
   fprintf(stream, _("\
 -O0                    remove unneeded NOPs, do not swap branches\n\
 -O                     remove unneeded NOPs and swap branches\n\
   fprintf(stream, _("\
 -O0                    remove unneeded NOPs, do not swap branches\n\
 -O                     remove unneeded NOPs and swap branches\n\
+--[no-]construct-floats [dis]allow floating point values to be constructed\n\
 --trap, --no-break     trap exception on div by 0 and mult overflow\n\
 --break, --no-trap     break exception on div by 0 and mult overflow\n"));
 #ifdef OBJ_ELF
 --trap, --no-break     trap exception on div by 0 and mult overflow\n\
 --break, --no-trap     break exception on div by 0 and mult overflow\n"));
 #ifdef OBJ_ELF
@@ -9290,7 +9409,7 @@ md_pcrel_from (fixP)
 
 void
 cons_fix_new_mips (frag, where, nbytes, exp)
 
 void
 cons_fix_new_mips (frag, where, nbytes, exp)
-     fragS *frag;
+     fragS *frag ATTRIBUTE_UNUSED;
      int where;
      unsigned int nbytes;
      expressionS *exp;
      int where;
      unsigned int nbytes;
      expressionS *exp;
@@ -9423,6 +9542,7 @@ mips_frob_file ()
    fixup requires the special reloc.  */
 #define SWITCH_TABLE(fixp) \
   ((fixp)->fx_r_type == BFD_RELOC_32 \
    fixup requires the special reloc.  */
 #define SWITCH_TABLE(fixp) \
   ((fixp)->fx_r_type == BFD_RELOC_32 \
+   && OUTPUT_FLAVOR != bfd_target_elf_flavour \
    && (fixp)->fx_addsy != NULL \
    && (fixp)->fx_subsy != NULL \
    && S_GET_SEGMENT ((fixp)->fx_addsy) == text_section \
    && (fixp)->fx_addsy != NULL \
    && (fixp)->fx_subsy != NULL \
    && S_GET_SEGMENT ((fixp)->fx_addsy) == text_section \
@@ -9470,15 +9590,16 @@ md_apply_fix (fixP, valueP)
      symbol, we need to adjust the value.  */
 #ifdef OBJ_ELF
   if (fixP->fx_addsy != NULL && OUTPUT_FLAVOR == bfd_target_elf_flavour)
      symbol, we need to adjust the value.  */
 #ifdef OBJ_ELF
   if (fixP->fx_addsy != NULL && OUTPUT_FLAVOR == bfd_target_elf_flavour)
+    {
     if (S_GET_OTHER (fixP->fx_addsy) == STO_MIPS16 
         || S_IS_WEAK (fixP->fx_addsy)
     if (S_GET_OTHER (fixP->fx_addsy) == STO_MIPS16 
         || S_IS_WEAK (fixP->fx_addsy)
-        || (fixP->fx_addsy->sy_used_in_reloc
-            && (bfd_get_section_flags (stdoutput,
-                                       S_GET_SEGMENT (fixP->fx_addsy))
-                & SEC_LINK_ONCE != 0)
-               || !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
-                            ".gnu.linkonce",
-                            sizeof (".gnu.linkonce") - 1)))
+        || (symbol_used_in_reloc_p (fixP->fx_addsy)
+            && (((bfd_get_section_flags (stdoutput,
+                                         S_GET_SEGMENT (fixP->fx_addsy))
+                  & SEC_LINK_ONCE) != 0)
+                || !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
+                             ".gnu.linkonce",
+                             sizeof (".gnu.linkonce") - 1))))
 
       {
         value -= S_GET_VALUE (fixP->fx_addsy);
 
       {
         value -= S_GET_VALUE (fixP->fx_addsy);
@@ -9486,12 +9607,29 @@ md_apply_fix (fixP, valueP)
           {
             /* In this case, the bfd_install_relocation routine will
                incorrectly add the symbol value back in.  We just want
           {
             /* In this case, the bfd_install_relocation routine will
                incorrectly add the symbol value back in.  We just want
-               the addend to appear in the object file.  */
+               the addend to appear in the object file.  
+              FIXME: If this makes VALUE zero, we're toast.  */
             value -= S_GET_VALUE (fixP->fx_addsy);
           }
       }
             value -= S_GET_VALUE (fixP->fx_addsy);
           }
       }
-#endif
 
 
+      /* This code was generated using trial and error and so is
+        fragile and not trustworthy.  If you change it, you should
+        rerun the elf-rel, elf-rel2, and empic testcases and ensure
+        they still pass.  */
+      if (fixP->fx_pcrel || fixP->fx_subsy != NULL)
+       {
+         value += fixP->fx_frag->fr_address + fixP->fx_where;
+
+         /* BFD's REL handling, for MIPS, is _very_ weird.
+            This gives the right results, but it can't possibly
+            be the way things are supposed to work.  */
+         if (fixP->fx_r_type != BFD_RELOC_16_PCREL_S2
+             || S_GET_SEGMENT (fixP->fx_addsy) != undefined_section)
+           value += fixP->fx_frag->fr_address + fixP->fx_where;
+       }
+    }
+#endif
 
   fixP->fx_addnumber = value;  /* Remember value for tc_gen_reloc */
 
 
   fixP->fx_addnumber = value;  /* Remember value for tc_gen_reloc */
 
@@ -9529,7 +9667,12 @@ md_apply_fix (fixP, valueP)
     case BFD_RELOC_PCREL_HI16_S:
       /* The addend for this is tricky if it is internal, so we just
         do everything here rather than in bfd_install_relocation.  */
     case BFD_RELOC_PCREL_HI16_S:
       /* The addend for this is tricky if it is internal, so we just
         do everything here rather than in bfd_install_relocation.  */
-      if ((fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) == 0)
+      if (OUTPUT_FLAVOR == bfd_target_elf_flavour 
+         && !fixP->fx_done
+         && value != 0)
+       break;
+      if (fixP->fx_addsy
+         && (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0)
        {
          /* For an external symbol adjust by the address to make it
             pcrel_offset.  We use the address of the RELLO reloc
        {
          /* For an external symbol adjust by the address to make it
             pcrel_offset.  We use the address of the RELLO reloc
@@ -9549,7 +9692,12 @@ md_apply_fix (fixP, valueP)
     case BFD_RELOC_PCREL_LO16:
       /* The addend for this is tricky if it is internal, so we just
         do everything here rather than in bfd_install_relocation.  */
     case BFD_RELOC_PCREL_LO16:
       /* The addend for this is tricky if it is internal, so we just
         do everything here rather than in bfd_install_relocation.  */
-      if ((fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) == 0)
+      if (OUTPUT_FLAVOR == bfd_target_elf_flavour 
+         && !fixP->fx_done
+         && value != 0)
+       break;
+      if (fixP->fx_addsy
+         && (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0)
        value += fixP->fx_frag->fr_address + fixP->fx_where;
       buf = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
       if (target_big_endian)
        value += fixP->fx_frag->fr_address + fixP->fx_where;
       buf = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
       if (target_big_endian)
@@ -9586,6 +9734,7 @@ md_apply_fix (fixP, valueP)
        }
       break;
 
        }
       break;
 
+    case BFD_RELOC_RVA:
     case BFD_RELOC_32:
       /* 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
     case BFD_RELOC_32:
       /* 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
@@ -9631,6 +9780,15 @@ md_apply_fix (fixP, valueP)
       if ((value & 0x3) != 0)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("Branch to odd address (%lx)"), value);
       if ((value & 0x3) != 0)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("Branch to odd address (%lx)"), value);
+
+      if (!fixP->fx_done && value != 0)
+       break;
+      /* If 'value' is zero, the remaining reloc code won't actually
+        do the store, so it must be done here.  This is probably
+        a bug somewhere.  */
+      if (!fixP->fx_done)
+       value -= fixP->fx_frag->fr_address + fixP->fx_where;
+      
       value >>= 2;
 
       /* update old instruction data */
       value >>= 2;
 
       /* update old instruction data */
@@ -9818,7 +9976,7 @@ mips_align (to, fill, label)
   if (label != NULL)
     {
       assert (S_GET_SEGMENT (label) == now_seg);
   if (label != NULL)
     {
       assert (S_GET_SEGMENT (label) == now_seg);
-      label->sy_frag = frag_now;
+      symbol_set_frag (label, frag_now);
       S_SET_VALUE (label, (valueT) frag_now_fix ());
     }
 }
       S_SET_VALUE (label, (valueT) frag_now_fix ());
     }
 }
@@ -9828,7 +9986,7 @@ mips_align (to, fill, label)
 
 static void
 s_align (x)
 
 static void
 s_align (x)
-     int x;
+     int x ATTRIBUTE_UNUSED;
 {
   register int temp;
   register long temp_fill;
 {
   register int temp;
   register long temp_fill;
@@ -9933,7 +10091,7 @@ s_change_sec (sec)
                                      | SEC_RELOC
                                      | SEC_DATA));
              if (strcmp (TARGET_OS, "elf") != 0)
                                      | SEC_RELOC
                                      | SEC_DATA));
              if (strcmp (TARGET_OS, "elf") != 0)
-               bfd_set_section_alignment (stdoutput, seg, 4);
+               record_alignment (seg, 4);
            }
          demand_empty_rest_of_line ();
        }
            }
          demand_empty_rest_of_line ();
        }
@@ -9955,7 +10113,7 @@ s_change_sec (sec)
                                     SEC_ALLOC | SEC_LOAD | SEC_RELOC
                                     | SEC_DATA);
              if (strcmp (TARGET_OS, "elf") != 0)
                                     SEC_ALLOC | SEC_LOAD | SEC_RELOC
                                     | SEC_DATA);
              if (strcmp (TARGET_OS, "elf") != 0)
-               bfd_set_section_alignment (stdoutput, seg, 4);
+               record_alignment (seg, 4);
            }
          demand_empty_rest_of_line ();
          break;
            }
          demand_empty_rest_of_line ();
          break;
@@ -10002,10 +10160,12 @@ s_float_cons (type)
   mips_emit_delays (false);
 
   if (auto_align)
   mips_emit_delays (false);
 
   if (auto_align)
-    if (type == 'd')
-      mips_align (3, 0, label);
-    else
-      mips_align (2, 0, label);
+    {
+      if (type == 'd')
+       mips_align (3, 0, label);
+      else
+       mips_align (2, 0, label);
+    }
 
   mips_clear_insn_labels ();
 
 
   mips_clear_insn_labels ();
 
@@ -10020,7 +10180,7 @@ s_float_cons (type)
 
 static void
 s_mips_globl (x)
 
 static void
 s_mips_globl (x)
-     int x;
+     int x ATTRIBUTE_UNUSED;
 {
   char *name;
   int c;
 {
   char *name;
   int c;
@@ -10053,7 +10213,7 @@ s_mips_globl (x)
        flag = BSF_FUNCTION;
     }
 
        flag = BSF_FUNCTION;
     }
 
-  symbolP->bsym->flags |= flag;
+  symbol_get_bfdsym (symbolP)->flags |= flag;
 
   S_SET_EXTERNAL (symbolP);
   demand_empty_rest_of_line ();
 
   S_SET_EXTERNAL (symbolP);
   demand_empty_rest_of_line ();
@@ -10061,7 +10221,7 @@ s_mips_globl (x)
 
 static void
 s_option (x)
 
 static void
 s_option (x)
-     int x;
+     int x ATTRIBUTE_UNUSED;
 {
   char *opt;
   char c;
 {
   char *opt;
   char c;
@@ -10114,7 +10274,7 @@ static struct mips_option_stack *mips_opts_stack;
 
 static void
 s_mipsset (x)
 
 static void
 s_mipsset (x)
-     int x;
+     int x ATTRIBUTE_UNUSED;
 {
   char *name = input_line_pointer, ch;
 
 {
   char *name = input_line_pointer, ch;
 
@@ -10250,7 +10410,7 @@ s_mipsset (x)
 
 static void
 s_abicalls (ignore)
 
 static void
 s_abicalls (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   mips_pic = SVR4_PIC;
   if (USE_GLOBAL_POINTER_OPT)
 {
   mips_pic = SVR4_PIC;
   if (USE_GLOBAL_POINTER_OPT)
@@ -10275,7 +10435,7 @@ s_abicalls (ignore)
 
 static void
 s_cpload (ignore)
 
 static void
 s_cpload (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   expressionS ex;
   int icnt = 0;
 {
   expressionS ex;
   int icnt = 0;
@@ -10297,7 +10457,7 @@ s_cpload (ignore)
   ex.X_add_number = 0;
 
   /* In ELF, this symbol is implicitly an STT_OBJECT symbol.  */
   ex.X_add_number = 0;
 
   /* In ELF, this symbol is implicitly an STT_OBJECT symbol.  */
-  ex.X_add_symbol->bsym->flags |= BSF_OBJECT;
+  symbol_get_bfdsym (ex.X_add_symbol)->flags |= BSF_OBJECT;
 
   macro_build_lui ((char *) NULL, &icnt, &ex, GP);
   macro_build ((char *) NULL, &icnt, &ex, "addiu", "t,r,j", GP, GP,
 
   macro_build_lui ((char *) NULL, &icnt, &ex, GP);
   macro_build ((char *) NULL, &icnt, &ex, "addiu", "t,r,j", GP, GP,
@@ -10315,7 +10475,7 @@ s_cpload (ignore)
 
 static void
 s_cprestore (ignore)
 
 static void
 s_cprestore (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   expressionS ex;
   int icnt = 0;
 {
   expressionS ex;
   int icnt = 0;
@@ -10336,7 +10496,7 @@ s_cprestore (ignore)
 
   macro_build ((char *) NULL, &icnt, &ex,
               ((bfd_arch_bits_per_address (stdoutput) == 32
 
   macro_build ((char *) NULL, &icnt, &ex,
               ((bfd_arch_bits_per_address (stdoutput) == 32
-                || mips_opts.isa < 3)
+                || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                ? "sw" : "sd"),
               "t,o(b)", GP, (int) BFD_RELOC_LO16, SP);
 
                ? "sw" : "sd"),
               "t,o(b)", GP, (int) BFD_RELOC_LO16, SP);
 
@@ -10348,7 +10508,7 @@ s_cprestore (ignore)
 
 static void
 s_gpword (ignore)
 
 static void
 s_gpword (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   symbolS *label;
   expressionS ex;
 {
   symbolS *label;
   expressionS ex;
@@ -10388,7 +10548,7 @@ s_gpword (ignore)
 
 static void
 s_cpadd (ignore)
 
 static void
 s_cpadd (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   int icnt = 0;
   int reg;
 {
   int icnt = 0;
   int reg;
@@ -10404,7 +10564,7 @@ s_cpadd (ignore)
   reg = tc_get_register (0);
   macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
               ((bfd_arch_bits_per_address (stdoutput) == 32
   reg = tc_get_register (0);
   macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
               ((bfd_arch_bits_per_address (stdoutput) == 32
-                || mips_opts.isa < 3)
+                || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
                ? "addu" : "daddu"),
               "d,v,t", reg, reg, GP);
 
                ? "addu" : "daddu"),
               "d,v,t", reg, reg, GP);
 
@@ -10422,7 +10582,7 @@ s_cpadd (ignore)
 
 static void
 s_insn (ignore)
 
 static void
 s_insn (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   if (mips_opts.mips16)
     mips16_mark_labels ();
 {
   if (mips_opts.mips16)
     mips16_mark_labels ();
@@ -10451,7 +10611,7 @@ s_mips_stab (type)
 
 static void
 s_mips_weakext (ignore)
 
 static void
 s_mips_weakext (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   char *name;
   int c;
 {
   char *name;
   int c;
@@ -10489,7 +10649,7 @@ s_mips_weakext (ignore)
          ignore_rest_of_line();
          return;
        }
          ignore_rest_of_line();
          return;
        }
-      symbolP->sy_value = exp;
+      symbol_set_value_expression (symbolP, &exp);
     }
 
   demand_empty_rest_of_line ();
     }
 
   demand_empty_rest_of_line ();
@@ -10601,15 +10761,16 @@ nopic_need_relax (sym, before_relaxing)
       else if ((! S_IS_DEFINED (sym) || S_IS_COMMON (sym))
               && (0
 #ifndef NO_ECOFF_DEBUGGING
       else if ((! S_IS_DEFINED (sym) || S_IS_COMMON (sym))
               && (0
 #ifndef NO_ECOFF_DEBUGGING
-                  || (sym->ecoff_extern_size != 0
-                      && sym->ecoff_extern_size <= g_switch_value)
+                  || (symbol_get_obj (sym)->ecoff_extern_size != 0
+                      && (symbol_get_obj (sym)->ecoff_extern_size
+                          <= g_switch_value))
 #endif
                   /* We must defer this decision until after the whole
                      file has been read, since there might be a .extern
                      after the first use of this symbol.  */
                   || (before_relaxing
 #ifndef NO_ECOFF_DEBUGGING
 #endif
                   /* We must defer this decision until after the whole
                      file has been read, since there might be a .extern
                      after the first use of this symbol.  */
                   || (before_relaxing
 #ifndef NO_ECOFF_DEBUGGING
-                      && sym->ecoff_extern_size == 0
+                      && symbol_get_obj (sym)->ecoff_extern_size == 0
 #endif
                       && S_GET_VALUE (sym) == 0)
                   || (S_GET_VALUE (sym) != 0
 #endif
                       && S_GET_VALUE (sym) == 0)
                   || (S_GET_VALUE (sym) != 0
@@ -10623,7 +10784,9 @@ nopic_need_relax (sym, before_relaxing)
          assert (strcmp (segname, ".lit8") != 0
                  && strcmp (segname, ".lit4") != 0);
          change = (strcmp (segname, ".sdata") != 0
          assert (strcmp (segname, ".lit8") != 0
                  && strcmp (segname, ".lit4") != 0);
          change = (strcmp (segname, ".sdata") != 0
-                   && strcmp (segname, ".sbss") != 0);
+                   && strcmp (segname, ".sbss") != 0
+                   && strncmp (segname, ".sdata.", 7) != 0
+                   && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
        }
       return change;
     }
        }
       return change;
     }
@@ -10679,23 +10842,26 @@ mips16_extended_frag (fragp, sec, stretch)
       maxtiny = (1 << (op->nbits - 1)) - 1;
     }
 
       maxtiny = (1 << (op->nbits - 1)) - 1;
     }
 
-  /* We can't call S_GET_VALUE here, because we don't want to lock in
-     a particular frag address.  */
-  if (fragp->fr_symbol->sy_value.X_op == O_constant)
+  /* We can't always call S_GET_VALUE here, because we don't want to
+     lock in a particular frag address.  */
+  if (symbol_constant_p (fragp->fr_symbol))
     {
     {
-      val = (fragp->fr_symbol->sy_value.X_add_number
-            + fragp->fr_symbol->sy_frag->fr_address);
+      val = (S_GET_VALUE (fragp->fr_symbol)
+            + symbol_get_frag (fragp->fr_symbol)->fr_address);
       symsec = S_GET_SEGMENT (fragp->fr_symbol);
     }
       symsec = S_GET_SEGMENT (fragp->fr_symbol);
     }
-  else if (fragp->fr_symbol->sy_value.X_op == O_symbol
-          && (fragp->fr_symbol->sy_value.X_add_symbol->sy_value.X_op
-              == O_constant))
+  else if (symbol_equated_p (fragp->fr_symbol)
+          && (symbol_constant_p
+              (symbol_get_value_expression (fragp->fr_symbol)->X_add_symbol)))
     {
     {
-      val = (fragp->fr_symbol->sy_value.X_add_symbol->sy_value.X_add_number
-            + fragp->fr_symbol->sy_value.X_add_symbol->sy_frag->fr_address
-            + fragp->fr_symbol->sy_value.X_add_number
-            + fragp->fr_symbol->sy_frag->fr_address);
-      symsec = S_GET_SEGMENT (fragp->fr_symbol->sy_value.X_add_symbol);
+      symbolS *eqsym;
+
+      eqsym = symbol_get_value_expression (fragp->fr_symbol)->X_add_symbol;
+      val = (S_GET_VALUE (eqsym)
+            + symbol_get_frag (eqsym)->fr_address
+            + symbol_get_value_expression (fragp->fr_symbol)->X_add_number
+            + symbol_get_frag (fragp->fr_symbol)->fr_address);
+      symsec = S_GET_SEGMENT (eqsym);
     }
   else
     return 1;
     }
   else
     return 1;
@@ -10737,7 +10903,8 @@ mips16_extended_frag (fragp, sec, stretch)
         in STRETCH in order to get a better estimate of the address.
         This particularly matters because of the shift bits.  */
       if (stretch != 0
         in STRETCH in order to get a better estimate of the address.
         This particularly matters because of the shift bits.  */
       if (stretch != 0
-         && fragp->fr_symbol->sy_frag->fr_address >= fragp->fr_address)
+         && (symbol_get_frag (fragp->fr_symbol)->fr_address
+             >= fragp->fr_address))
        {
          fragS *f;
 
        {
          fragS *f;
 
@@ -10748,7 +10915,7 @@ mips16_extended_frag (fragp, sec, stretch)
              a maximum number of bytes to skip when doing an
              alignment.  */
          for (f = fragp;
              a maximum number of bytes to skip when doing an
              alignment.  */
          for (f = fragp;
-              f != NULL && f != fragp->fr_symbol->sy_frag;
+              f != NULL && f != symbol_get_frag (fragp->fr_symbol);
               f = f->fr_next)
            {
              if (f->fr_type == rs_align || f->fr_type == rs_align_code)
               f = f->fr_next)
            {
              if (f->fr_type == rs_align || f->fr_type == rs_align_code)
@@ -10854,7 +11021,8 @@ md_estimate_size_before_relax (fragp, segtype)
      fragS *fragp;
      asection *segtype;
 {
      fragS *fragp;
      asection *segtype;
 {
-  int change;
+  int change = 0;
+  boolean linkonce = false;
 
   if (RELAX_MIPS16_P (fragp->fr_subtype))
     {
 
   if (RELAX_MIPS16_P (fragp->fr_subtype))
     {
@@ -10882,14 +11050,14 @@ md_estimate_size_before_relax (fragp, segtype)
       sym = fragp->fr_symbol;
 
       /* Handle the case of a symbol equated to another symbol.  */
       sym = fragp->fr_symbol;
 
       /* Handle the case of a symbol equated to another symbol.  */
-      while (sym->sy_value.X_op == O_symbol
+      while (symbol_equated_p (sym)
             && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
        {
          symbolS *n;
 
          /* It's possible to get a loop here in a badly written
              program.  */
             && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
        {
          symbolS *n;
 
          /* It's possible to get a loop here in a badly written
              program.  */
-         n = sym->sy_value.X_add_symbol;
+         n = symbol_get_value_expression (sym)->X_add_symbol;
          if (n == sym)
            break;
          sym = n;
          if (n == sym)
            break;
          sym = n;
@@ -10897,10 +11065,31 @@ md_estimate_size_before_relax (fragp, segtype)
 
       symsec = S_GET_SEGMENT (sym);
 
 
       symsec = S_GET_SEGMENT (sym);
 
+      /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
+      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.  */
       change = (symsec != &bfd_und_section
                && symsec != &bfd_abs_section
       /* This must duplicate the test in adjust_reloc_syms.  */
       change = (symsec != &bfd_und_section
                && symsec != &bfd_abs_section
-               && ! bfd_is_com_section (symsec));
+               && ! bfd_is_com_section (symsec)
+               && !linkonce
+#ifdef OBJ_ELF
+               /* A weak symbol is treated as external.  */
+               && ! S_IS_WEAK (sym)
+#endif
+               );
     }
   else
     abort ();
     }
   else
     abort ();
@@ -10957,7 +11146,7 @@ mips_fix_adjustable (fixp)
 
 arelent **
 tc_gen_reloc (section, fixp)
 
 arelent **
 tc_gen_reloc (section, fixp)
-     asection *section;
+     asection *section ATTRIBUTE_UNUSED;
      fixS *fixp;
 {
   static arelent *retval[4];
      fixS *fixp;
 {
   static arelent *retval[4];
@@ -10967,7 +11156,8 @@ tc_gen_reloc (section, fixp)
   reloc = retval[0] = (arelent *) xmalloc (sizeof (arelent));
   retval[1] = NULL;
 
   reloc = retval[0] = (arelent *) xmalloc (sizeof (arelent));
   retval[1] = NULL;
 
-  reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
 
   if (mips_pic == EMBEDDED_PIC
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
 
   if (mips_pic == EMBEDDED_PIC
@@ -10981,10 +11171,12 @@ tc_gen_reloc (section, fixp)
        as_fatal (_("Double check fx_r_type in tc-mips.c:tc_gen_reloc"));
       fixp->fx_r_type = BFD_RELOC_GPREL32;
     }
        as_fatal (_("Double check fx_r_type in tc-mips.c:tc_gen_reloc"));
       fixp->fx_r_type = BFD_RELOC_GPREL32;
     }
+  else if (fixp->fx_pcrel == 0 || OUTPUT_FLAVOR == bfd_target_elf_flavour)
+    reloc->addend = fixp->fx_addnumber;
   else if (fixp->fx_r_type == BFD_RELOC_PCREL_LO16)
     {
       /* We use a special addend for an internal RELLO reloc.  */
   else if (fixp->fx_r_type == BFD_RELOC_PCREL_LO16)
     {
       /* We use a special addend for an internal RELLO reloc.  */
-      if (fixp->fx_addsy->bsym->flags & BSF_SECTION_SYM)
+      if (symbol_section_p (fixp->fx_addsy))
        reloc->addend = reloc->address - S_GET_VALUE (fixp->fx_subsy);
       else
        reloc->addend = fixp->fx_addnumber + reloc->address;
        reloc->addend = reloc->address - S_GET_VALUE (fixp->fx_subsy);
       else
        reloc->addend = fixp->fx_addnumber + reloc->address;
@@ -10996,7 +11188,7 @@ tc_gen_reloc (section, fixp)
       /* We use a special addend for an internal RELHI reloc.  The
         reloc is relative to the RELLO; adjust the addend
         accordingly.  */
       /* We use a special addend for an internal RELHI reloc.  The
         reloc is relative to the RELLO; adjust the addend
         accordingly.  */
-      if (fixp->fx_addsy->bsym->flags & BSF_SECTION_SYM)
+      if (symbol_section_p (fixp->fx_addsy))
        reloc->addend = (fixp->fx_next->fx_frag->fr_address
                         + fixp->fx_next->fx_where
                         - S_GET_VALUE (fixp->fx_subsy));
        reloc->addend = (fixp->fx_next->fx_frag->fr_address
                         + fixp->fx_next->fx_where
                         - S_GET_VALUE (fixp->fx_subsy));
@@ -11005,8 +11197,6 @@ tc_gen_reloc (section, fixp)
                         + fixp->fx_next->fx_frag->fr_address
                         + fixp->fx_next->fx_where);
     }
                         + fixp->fx_next->fx_frag->fr_address
                         + fixp->fx_next->fx_where);
     }
-  else if (fixp->fx_pcrel == 0)
-    reloc->addend = fixp->fx_addnumber;
   else
     {
       if (OUTPUT_FLAVOR != bfd_target_aout_flavour)
   else
     {
       if (OUTPUT_FLAVOR != bfd_target_aout_flavour)
@@ -11055,7 +11245,8 @@ tc_gen_reloc (section, fixp)
       reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
       reloc2 = retval[1] = (arelent *) xmalloc (sizeof (arelent));
       retval[2] = NULL;
       reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
       reloc2 = retval[1] = (arelent *) xmalloc (sizeof (arelent));
       retval[2] = NULL;
-      reloc2->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+      reloc2->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+      *reloc2->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
       reloc2->address = (reloc->address
                         + (RELAX_RELOC2 (fixp->fx_frag->fr_subtype)
                            - RELAX_RELOC1 (fixp->fx_frag->fr_subtype)));
       reloc2->address = (reloc->address
                         + (RELAX_RELOC2 (fixp->fx_frag->fr_subtype)
                            - RELAX_RELOC1 (fixp->fx_frag->fr_subtype)));
@@ -11144,7 +11335,8 @@ tc_gen_reloc (section, fixp)
   /* To support a PC relative reloc when generating embedded PIC code
      for ECOFF, we use a Cygnus extension.  We check for that here to
      make sure that we don't let such a reloc escape normally.  */
   /* To support a PC relative reloc when generating embedded PIC code
      for ECOFF, we use a Cygnus extension.  We check for that here to
      make sure that we don't let such a reloc escape normally.  */
-  if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
+  if ((OUTPUT_FLAVOR == bfd_target_ecoff_flavour
+       || OUTPUT_FLAVOR == bfd_target_elf_flavour)
       && code == BFD_RELOC_16_PCREL_S2
       && mips_pic != EMBEDDED_PIC)
     reloc->howto = NULL;
       && code == BFD_RELOC_16_PCREL_S2
       && mips_pic != EMBEDDED_PIC)
     reloc->howto = NULL;
@@ -11195,7 +11387,7 @@ mips_relax_frag (fragp, stretch)
 
 void
 md_convert_frag (abfd, asec, fragp)
 
 void
 md_convert_frag (abfd, asec, fragp)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      segT asec;
      fragS *fragp;
 {
      segT asec;
      fragS *fragp;
 {
@@ -11433,7 +11625,7 @@ mips_elf_final_processing ()
 \f
 typedef struct proc
   {
 \f
 typedef struct proc
   {
-    struct symbol *isym;
+    symbolS *isym;
     unsigned long reg_mask;
     unsigned long reg_offset;
     unsigned long fpreg_mask;
     unsigned long reg_mask;
     unsigned long reg_offset;
     unsigned long fpreg_mask;
@@ -11448,6 +11640,36 @@ static procS cur_proc;
 static procS *cur_proc_ptr;
 static int numprocs;
 
 static procS *cur_proc_ptr;
 static int numprocs;
 
+/* When we align code in the .text section of mips16, use the correct two
+   byte nop pattern of 0x6500 (move $0,$0) */
+
+int
+mips_do_align (n, fill, len, max)
+     int n;
+     const char *fill;
+     int len ATTRIBUTE_UNUSED;
+     int max;
+{
+  if (fill == NULL
+      && subseg_text_p (now_seg)
+      && n > 1
+      && mips_opts.mips16)
+    {
+      static const unsigned char be_nop[] = { 0x65, 0x00 };
+      static const unsigned char le_nop[] = { 0x00, 0x65 };
+
+      frag_align (1, 0, 0);
+
+      if (target_big_endian)
+       frag_align_pattern (n, be_nop, 2, max);      
+      else
+       frag_align_pattern (n, le_nop, 2, max);      
+      return 1;
+    }
+
+  return 0;
+}
+
 static void
 md_obj_begin ()
 {
 static void
 md_obj_begin ()
 {
@@ -11472,14 +11694,14 @@ get_number ()
       ++input_line_pointer;
       negative = 1;
     }
       ++input_line_pointer;
       negative = 1;
     }
-  if (!isdigit (*input_line_pointer))
+  if (!isdigit ((unsigned char) *input_line_pointer))
     as_bad (_("Expected simple number."));
   if (input_line_pointer[0] == '0')
     {
       if (input_line_pointer[1] == 'x')
        {
          input_line_pointer += 2;
     as_bad (_("Expected simple number."));
   if (input_line_pointer[0] == '0')
     {
       if (input_line_pointer[1] == 'x')
        {
          input_line_pointer += 2;
-         while (isxdigit (*input_line_pointer))
+         while (isxdigit ((unsigned char) *input_line_pointer))
            {
              val <<= 4;
              val |= hex_value (*input_line_pointer++);
            {
              val <<= 4;
              val |= hex_value (*input_line_pointer++);
@@ -11489,7 +11711,7 @@ get_number ()
       else
        {
          ++input_line_pointer;
       else
        {
          ++input_line_pointer;
-         while (isdigit (*input_line_pointer))
+         while (isdigit ((unsigned char) *input_line_pointer))
            {
              val <<= 3;
              val |= *input_line_pointer++ - '0';
            {
              val <<= 3;
              val |= *input_line_pointer++ - '0';
@@ -11497,14 +11719,14 @@ get_number ()
          return negative ? -val : val;
        }
     }
          return negative ? -val : val;
        }
     }
-  if (!isdigit (*input_line_pointer))
+  if (!isdigit ((unsigned char) *input_line_pointer))
     {
       printf (_(" *input_line_pointer == '%c' 0x%02x\n"),
              *input_line_pointer, *input_line_pointer);
       as_warn (_("Invalid number"));
       return -1;
     }
     {
       printf (_(" *input_line_pointer == '%c' 0x%02x\n"),
              *input_line_pointer, *input_line_pointer);
       as_warn (_("Invalid number"));
       return -1;
     }
-  while (isdigit (*input_line_pointer))
+  while (isdigit ((unsigned char) *input_line_pointer))
     {
       val *= 10;
       val += *input_line_pointer++ - '0';
     {
       val *= 10;
       val += *input_line_pointer++ - '0';
@@ -11517,7 +11739,7 @@ get_number ()
 
 static void
 s_file (x)
 
 static void
 s_file (x)
-     int x;
+     int x ATTRIBUTE_UNUSED;
 {
   int line;
 
 {
   int line;
 
@@ -11530,7 +11752,7 @@ s_file (x)
 
 static void
 s_mips_end (x)
 
 static void
 s_mips_end (x)
-     int x;
+     int x ATTRIBUTE_UNUSED;
 {
   symbolS *p;
   int maybe_text;
 {
   symbolS *p;
   int maybe_text;
@@ -11630,7 +11852,8 @@ s_mips_ent (aent)
   if (*input_line_pointer == ',')
     input_line_pointer++;
   SKIP_WHITESPACE ();
   if (*input_line_pointer == ',')
     input_line_pointer++;
   SKIP_WHITESPACE ();
-  if (isdigit (*input_line_pointer) || *input_line_pointer == '-')
+  if (isdigit ((unsigned char) *input_line_pointer)
+      || *input_line_pointer == '-')
     number = get_number ();
 
 #ifdef BFD_ASSEMBLER
     number = get_number ();
 
 #ifdef BFD_ASSEMBLER
@@ -11658,7 +11881,7 @@ s_mips_ent (aent)
 
       cur_proc_ptr->isym = symbolP;
 
 
       cur_proc_ptr->isym = symbolP;
 
-      symbolP->bsym->flags |= BSF_FUNCTION;
+      symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
 
       numprocs++;
     }
 
       numprocs++;
     }
@@ -11778,6 +12001,3 @@ s_loc (x)
   symbolP->sy_segment = now_seg;
 }
 #endif
   symbolP->sy_segment = now_seg;
 }
 #endif
-
-
-  
This page took 0.066119 seconds and 4 git commands to generate.