* config/tc-mips.c (macro_build_jalr): Make sure we generate
[deliverable/binutils-gdb.git] / gas / config / tc-mips.c
index 8c6a2191692398444c82d443db16804cc91b3a13..c548ddec88075fde5c7e4e138bc370f33c008c60 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "opcode/mips.h"
 #include "itbl-ops.h"
+#include "dwarf2dbg.h"
 
 #ifdef DEBUG
 #define DBG(x) printf x
@@ -76,12 +77,15 @@ static int mips_output_flavor () { return OUTPUT_FLAVOR; }
 #define ECOFF_DEBUGGING 0
 #endif
 
+int mips_flag_mdebug = -1;
+
 #include "ecoff.h"
 
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
 static char *mips_regmask_frag;
 #endif
 
+#define ZERO 0
 #define AT  1
 #define TREG 24
 #define PIC_CALL_REG 25
@@ -125,7 +129,7 @@ enum mips_abi_level
 };
 
 /* MIPS ABI we are using for this output file.  */
-static enum mips_abi_level file_mips_abi = NO_ABI;
+static enum mips_abi_level mips_abi = NO_ABI;
 
 /* This is the set of options which may be modified by the .set
    pseudo-op.  We use a struct so that .set push and .set pop are more
@@ -173,9 +177,6 @@ struct mips_set_options
      is passed but can changed if the assembler code uses .set mipsN.  */
   int gp32;
   int fp32;
-  /* The ABI currently in use. This is changed by .set mipsN to loosen
-     restrictions and doesn't affect the whole file.  */
-  enum mips_abi_level abi;
 };
 
 /* True if -mgp32 was passed.  */
@@ -185,12 +186,12 @@ static int file_mips_gp32 = -1;
 static int file_mips_fp32 = -1;
 
 /* This is the struct we use to hold the current set of options.  Note
-   that we must set the isa field to ISA_UNKNOWN and the mips16 field to
+   that we must set the isa field to ISA_UNKNOWN and the ASE fields to
    -1 to indicate that they have not been initialized.  */
 
 static struct mips_set_options mips_opts =
 {
-  ISA_UNKNOWN, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, NO_ABI
+  ISA_UNKNOWN, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
 /* These variables are filled in with the masks of registers used.
@@ -202,6 +203,10 @@ unsigned long mips_cprmask[4];
 /* MIPS ISA we are using for this output file.  */
 static int file_mips_isa = ISA_UNKNOWN;
 
+/* True if -mips16 was passed or implied by arguments passed on the
+   command line (e.g., by -march).  */
+static int file_ase_mips16;
+
 /* True if -mips3d was passed or implied by arguments passed on the
    command line (e.g., by -march).  */
 static int file_ase_mips3d;
@@ -210,21 +215,18 @@ static int file_ase_mips3d;
    command line (e.g., by -march).  */
 static int file_ase_mdmx;
 
-/* The argument of the -mcpu= flag.  Historical for code generation.  */
-static int mips_cpu = CPU_UNKNOWN;
-
 /* The argument of the -march= flag.  The architecture we are assembling.  */
 static int mips_arch = CPU_UNKNOWN;
+static const char *mips_arch_string;
+static const struct mips_cpu_info *mips_arch_info;
 
 /* The argument of the -mtune= flag.  The architecture for which we
    are optimizing.  */
 static int mips_tune = CPU_UNKNOWN;
+static const char *mips_tune_string;
+static const struct mips_cpu_info *mips_tune_info;
 
-/* Whether we should mark the file EABI64 or EABI32.  */
-static int mips_eabi64 = 0;
-
-/* If they asked for mips1 or mips2 and a cpu that is
-   mips3 or greater, then mark the object file 32BITMODE.  */
+/* True when generating 32-bit code for a 64-bit processor.  */
 static int mips_32bitmode = 0;
 
 /* Some ISA's have delay slots for instructions which read or write
@@ -241,6 +243,15 @@ static int mips_32bitmode = 0;
    || (ISA) == ISA_MIPS3                    \
    )
 
+/* True if the given ABI requires 32-bit registers.  */
+#define ABI_NEEDS_32BIT_REGS(ABI) ((ABI) == O32_ABI)
+
+/* Likewise 64-bit registers.  */
+#define ABI_NEEDS_64BIT_REGS(ABI) \
+  ((ABI) == N32_ABI              \
+   || (ABI) == N64_ABI           \
+   || (ABI) == O64_ABI)
+
 /*  Return true if ISA supports 64 bit gp register instructions.  */
 #define ISA_HAS_64BIT_REGS(ISA) (    \
    (ISA) == ISA_MIPS3                \
@@ -250,21 +261,17 @@ static int mips_32bitmode = 0;
    )
 
 #define HAVE_32BIT_GPRS                                   \
-    (mips_opts.gp32                                \
-     || mips_opts.abi == O32_ABI                   \
-     || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
+    (mips_opts.gp32 || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
 
 #define HAVE_32BIT_FPRS                            \
-    (mips_opts.fp32                                \
-     || mips_opts.abi == O32_ABI                   \
-     || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
+    (mips_opts.fp32 || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
 
 #define HAVE_64BIT_GPRS (! HAVE_32BIT_GPRS)
 #define HAVE_64BIT_FPRS (! HAVE_32BIT_FPRS)
 
-#define HAVE_NEWABI (mips_opts.abi == N32_ABI || mips_opts.abi == N64_ABI)
+#define HAVE_NEWABI (mips_abi == N32_ABI || mips_abi == N64_ABI)
 
-#define HAVE_64BIT_OBJECTS (mips_opts.abi == N64_ABI)
+#define HAVE_64BIT_OBJECTS (mips_abi == N64_ABI)
 
 /* We can only have 64bit addresses if the object file format
    supports it.  */
@@ -276,12 +283,16 @@ static int mips_32bitmode = 0;
 
 #define HAVE_64BIT_ADDRESSES (! HAVE_32BIT_ADDRESSES)
 
+/* Return true if the given CPU supports the MIPS16 ASE.  */
+#define CPU_HAS_MIPS16(cpu)                            \
+   (strncmp (TARGET_CPU, "mips16", sizeof ("mips16") - 1) == 0)
+
 /* Return true if the given CPU supports the MIPS3D ASE.  */
 #define CPU_HAS_MIPS3D(cpu)    ((cpu) == CPU_SB1      \
                                 )
 
 /* Return true if the given CPU supports the MDMX ASE.  */
-#define CPU_HAS_MDMX(cpu)      (0                    \
+#define CPU_HAS_MDMX(cpu)      (false                 \
                                 )
 
 /* Whether the processor uses hardware interlocks to protect
@@ -316,10 +327,6 @@ enum mips_pic_level
   /* Do not generate PIC code.  */
   NO_PIC,
 
-  /* Generate PIC code as in Irix 4.  This is not implemented, and I'm
-     not sure what it is supposed to do.  */
-  IRIX4_PIC,
-
   /* Generate PIC code as in the SVR4 MIPS ABI.  */
   SVR4_PIC,
 
@@ -732,6 +739,7 @@ static void my_getExpression PARAMS ((expressionS *, char *));
 #ifdef OBJ_ELF
 static int support_64bit_objects PARAMS((void));
 #endif
+static void mips_set_option_string PARAMS ((const char **, const char *));
 static symbolS *get_symbol PARAMS ((void));
 static void mips_align PARAMS ((int to, int fill, symbolS *label));
 static void s_align PARAMS ((int));
@@ -760,12 +768,11 @@ static void s_mips_frame PARAMS ((int));
 static void s_mips_mask PARAMS ((int));
 static void s_mips_stab PARAMS ((int));
 static void s_mips_weakext PARAMS ((int));
-static void s_file PARAMS ((int));
+static void s_mips_file PARAMS ((int));
+static void s_mips_loc PARAMS ((int));
 static int mips16_extended_frag PARAMS ((fragS *, asection *, long));
-static const char *mips_isa_to_str PARAMS ((int));
-static const char *mips_cpu_to_str PARAMS ((int));
 static int validate_mips_insn PARAMS ((const struct mips_opcode *));
-static void show PARAMS ((FILE *, char *, int *, int *));
+static void show PARAMS ((FILE *, const char *, int *, int *));
 #ifdef OBJ_ELF
 static int mips_need_elf_addend_fixup PARAMS ((fixS *));
 #endif
@@ -807,9 +814,14 @@ struct mips_cpu_info
   int cpu;                    /* CPU number (default CPU if ISA).  */
 };
 
-static const struct mips_cpu_info *mips_cpu_info_from_name PARAMS ((const char *));
+static void mips_set_architecture PARAMS ((const struct mips_cpu_info *));
+static void mips_set_tune PARAMS ((const struct mips_cpu_info *));
+static boolean mips_strict_matching_cpu_name_p PARAMS ((const char *,
+                                                       const char *));
+static boolean mips_matching_cpu_name_p PARAMS ((const char *, const char *));
+static const struct mips_cpu_info *mips_parse_cpu PARAMS ((const char *,
+                                                          const char *));
 static const struct mips_cpu_info *mips_cpu_info_from_isa PARAMS ((int));
-static const struct mips_cpu_info *mips_cpu_info_from_cpu PARAMS ((int));
 \f
 /* Pseudo-op table.
 
@@ -877,9 +889,7 @@ static const pseudo_typeS mips_pseudo_table[] =
   {"text", s_change_sec, 't'},
   {"word", s_cons, 2},
 
-#ifdef MIPS_STABS_ELF
   { "extern", ecoff_directive_extern, 0},
-#endif
 
   { NULL, NULL, 0 },
 };
@@ -893,10 +903,10 @@ static const pseudo_typeS mips_nonecoff_pseudo_table[] =
   {"end", s_mips_end, 0},
   {"endb", s_ignore, 0},
   {"ent", s_mips_ent, 0},
-  {"file", s_file, 0},
+  {"file", s_mips_file, 0},
   {"fmask", s_mips_mask, 'F'},
   {"frame", s_mips_frame, 0},
-  {"loc", s_ignore, 0},
+  {"loc", s_mips_loc, 0},
   {"mask", s_mips_mask, 'R'},
   {"verstamp", s_ignore, 0},
   { NULL, NULL, 0 },
@@ -959,41 +969,10 @@ static boolean imm_unmatched_hi;
 
 static boolean mips16_small, mips16_ext;
 
-#ifdef MIPS_STABS_ELF
-/* The pdr segment for per procedure frame/regmask info */
+/* The pdr segment for per procedure frame/regmask info.  Not used for
+   ECOFF debugging.  */
 
 static segT pdr_seg;
-#endif
-
-static const char *
-mips_isa_to_str (isa)
-     int isa;
-{
-  const struct mips_cpu_info *ci;
-  static char s[20];
-
-  ci = mips_cpu_info_from_isa (isa);
-  if (ci != NULL)
-    return (ci->name);
-
-  sprintf (s, "ISA#%d", isa);
-  return s;
-}
-
-static const char *
-mips_cpu_to_str (cpu)
-     int cpu;
-{
-  const struct mips_cpu_info *ci;
-  static char s[16];
-
-  ci = mips_cpu_info_from_cpu (cpu);
-  if (ci != NULL)
-    return (ci->name);
-
-  sprintf (s, "CPU#%d", cpu);
-  return s;
-}
 
 /* The default target format to use.  */
 
@@ -1010,17 +989,26 @@ mips_target_format ()
       return "pe-mips";
     case bfd_target_elf_flavour:
 #ifdef TE_TMIPS
-      /* This is traditional mips */
+      /* This is traditional mips */
       return (target_big_endian
-             ? (HAVE_64BIT_OBJECTS ? "elf64-tradbigmips"
-                : "elf32-tradbigmips")
-             : (HAVE_64BIT_OBJECTS ? "elf64-tradlittlemips"
-                : "elf32-tradlittlemips"));
+             ? (HAVE_64BIT_OBJECTS
+                ? "elf64-tradbigmips"
+                : (HAVE_NEWABI
+                   ? "elf32-ntradbigmips" : "elf32-tradbigmips"))
+             : (HAVE_64BIT_OBJECTS
+                ? "elf64-tradlittlemips"
+                : (HAVE_NEWABI
+                   ? "elf32-ntradlittlemips" : "elf32-tradlittlemips")));
 #else
       return (target_big_endian
-             ? (HAVE_64BIT_OBJECTS ? "elf64-bigmips" : "elf32-bigmips")
-             : (HAVE_64BIT_OBJECTS ? "elf64-littlemips"
-                : "elf32-littlemips"));
+             ? (HAVE_64BIT_OBJECTS
+                ? "elf64-bigmips"
+                : (HAVE_NEWABI
+                   ? "elf32-nbigmips" : "elf32-bigmips"))
+             : (HAVE_64BIT_OBJECTS
+                ? "elf64-littlemips"
+                : (HAVE_NEWABI
+                   ? "elf32-nlittlemips" : "elf32-littlemips")));
 #endif
     default:
       abort ();
@@ -1036,241 +1024,11 @@ md_begin ()
 {
   register const char *retval = NULL;
   int i = 0;
-  const char *cpu;
-  char *a = NULL;
   int broken = 0;
-  int mips_isa_from_cpu;
-  int target_cpu_had_mips16 = 0;
-  const struct mips_cpu_info *ci;
-
-  /* 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)
-    {
-      a = xmalloc (sizeof TARGET_CPU);
-      strcpy (a, TARGET_CPU);
-      a[(sizeof TARGET_CPU) - 3] = '\0';
-      cpu = a;
-    }
-
-  if (strncmp (cpu, "mips16", sizeof "mips16" - 1) == 0)
-    {
-      target_cpu_had_mips16 = 1;
-      cpu += sizeof "mips16" - 1;
-    }
-
-  if (mips_opts.mips16 < 0)
-    mips_opts.mips16 = target_cpu_had_mips16;
-
-  /* Backward compatibility for historic -mcpu= option.  Check for
-     incompatible options, warn if -mcpu is used.  */
-  if (mips_cpu != CPU_UNKNOWN
-      && mips_arch != CPU_UNKNOWN
-      && mips_cpu != mips_arch)
-    {
-      as_fatal (_("The -mcpu option can't be used together with -march. "
-                 "Use -mtune instead of -mcpu."));
-    }
-
-  if (mips_cpu != CPU_UNKNOWN
-      && mips_tune != CPU_UNKNOWN
-      && mips_cpu != mips_tune)
-    {
-      as_fatal (_("The -mcpu option can't be used together with -mtune. "
-                 "Use -march instead of -mcpu."));
-    }
-
-#if 1
-  /* For backward compatibility, let -mipsN set various defaults.  */
-  /* This code should go away, to be replaced with something rather more
-     draconian.  Until GCC 3.1 has been released for some reasonable
-     amount of time, however, we need to support this.  */
-  if (mips_opts.isa != ISA_UNKNOWN)
-    {
-      /* Translate -mipsN to the appropriate settings of file_mips_gp32
-        and file_mips_fp32.  Tag binaries as using the mipsN ISA.  */
-      if (file_mips_gp32 < 0)
-       {
-         if (ISA_HAS_64BIT_REGS (mips_opts.isa))
-           file_mips_gp32 = 0;
-         else
-           file_mips_gp32 = 1;
-       }
-      if (file_mips_fp32 < 0)
-       {
-         if (ISA_HAS_64BIT_REGS (mips_opts.isa))
-           file_mips_fp32 = 0;
-         else
-           file_mips_fp32 = 1;
-       }
-
-      ci = mips_cpu_info_from_isa (mips_opts.isa);
-      assert (ci != NULL);
-      /* -mipsN has higher priority than -mcpu but lower than -march.  */
-      if (mips_arch == CPU_UNKNOWN)
-       mips_arch = ci->cpu;
-
-      /* Default mips_abi.  */
-      if (mips_opts.abi == NO_ABI)
-       {
-         if (mips_opts.isa == ISA_MIPS1 || mips_opts.isa == ISA_MIPS2)
-           mips_opts.abi = O32_ABI;
-         else if (mips_opts.isa == ISA_MIPS3 || mips_opts.isa == ISA_MIPS4)
-           mips_opts.abi = O64_ABI;
-       }
-    }
-
-  if (mips_arch == CPU_UNKNOWN && mips_cpu != CPU_UNKNOWN)
-    {
-      ci = mips_cpu_info_from_cpu (mips_cpu);
-      assert (ci != NULL);
-      mips_arch = ci->cpu;
-      as_warn (_("The -mcpu option is deprecated.  Please use -march and "
-                "-mtune instead."));
-    }
-
-  /* Set tune from -mcpu, not from -mipsN.  */
-  if (mips_tune == CPU_UNKNOWN && mips_cpu != CPU_UNKNOWN)
-    {
-      ci = mips_cpu_info_from_cpu (mips_cpu);
-      assert (ci != NULL);
-      mips_tune = ci->cpu;
-    }
-
-  /* At this point, mips_arch will either be CPU_UNKNOWN if no ARCH was
-     specified on the command line, or some other value if one was.
-     Similarly, mips_opts.isa will be ISA_UNKNOWN if not specified on
-     the command line, or will be set otherwise if one was.  */
-
-  if (mips_arch != CPU_UNKNOWN && mips_opts.isa != ISA_UNKNOWN)
-    /* Handled above.  */;
-#else
-  if (mips_arch == CPU_UNKNOWN && mips_cpu != CPU_UNKNOWN)
-    {
-      ci = mips_cpu_info_from_cpu (mips_cpu);
-      assert (ci != NULL);
-      mips_arch = ci->cpu;
-      as_warn (_("The -mcpu option is deprecated.  Please use -march and "
-                "-mtune instead."));
-    }
-
-  /* At this point, mips_arch will either be CPU_UNKNOWN if no ARCH was
-     specified on the command line, or some other value if one was.
-     Similarly, mips_opts.isa will be ISA_UNKNOWN if not specified on
-     the command line, or will be set otherwise if one was.  */
-
-  if (mips_arch != CPU_UNKNOWN && mips_opts.isa != ISA_UNKNOWN)
-    {
-      /* We have to check if the isa is the default isa of arch.  Otherwise
-         we'll get invalid object file headers.  */
-      ci = mips_cpu_info_from_cpu (mips_arch);
-      assert (ci != NULL);
-      if (mips_opts.isa != ci->isa)
-       {
-         /* This really should be an error instead of a warning, but old
-            compilers only have -mcpu which sets both arch and tune.  For
-            now, we discard arch and preserve tune.  */
-         as_warn (_("The -march option is incompatible to -mipsN and "
-                    "therefore ignored."));
-         if (mips_tune == CPU_UNKNOWN)
-           mips_tune = mips_arch;
-         ci = mips_cpu_info_from_isa (mips_opts.isa);
-         assert (ci != NULL);
-         mips_arch = ci->cpu;
-       }
-    }
-#endif
-  else if (mips_arch != CPU_UNKNOWN && mips_opts.isa == ISA_UNKNOWN)
-    {
-      /* We have ARCH, we need ISA.  */
-      ci = mips_cpu_info_from_cpu (mips_arch);
-      assert (ci != NULL);
-      mips_opts.isa = ci->isa;
-    }
-  else if (mips_arch == CPU_UNKNOWN && mips_opts.isa != ISA_UNKNOWN)
-    {
-      /* We have ISA, we need default ARCH.  */
-      ci = mips_cpu_info_from_isa (mips_opts.isa);
-      assert (ci != NULL);
-      mips_arch = ci->cpu;
-    }
-  else
-    {
-      /* We need to set both ISA and ARCH from target cpu.  */
-      ci = mips_cpu_info_from_name (cpu);
-      if (ci == NULL)
-       ci = mips_cpu_info_from_cpu (CPU_R3000);
-      assert (ci != NULL);
-      mips_opts.isa = ci->isa;
-      mips_arch = ci->cpu;
-    }
-
-  if (mips_tune == CPU_UNKNOWN)
-    mips_tune = mips_arch;
-
-  ci = mips_cpu_info_from_cpu (mips_arch);
-  assert (ci != NULL);
-  mips_isa_from_cpu = ci->isa;
-
-  /* End of TARGET_CPU processing, get rid of malloced memory
-     if necessary.  */
-  cpu = NULL;
-  if (a != NULL)
-    {
-      free (a);
-      a = NULL;
-    }
-
-  if (mips_opts.isa == ISA_MIPS1 && 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.  */
-  if (ISA_HAS_64BIT_REGS (mips_opts.isa)
-      && mips_opts.abi == EABI_ABI)
-    mips_eabi64 = 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 != ISA_UNKNOWN
-      && ! ISA_HAS_64BIT_REGS (mips_opts.isa)
-      && ISA_HAS_64BIT_REGS (mips_isa_from_cpu))
-    mips_32bitmode = 1;
-
-  /* If the selected architecture includes support for ASEs, enable
-     generation of code for them.  */
-  if (mips_opts.ase_mips3d == -1 && CPU_HAS_MIPS3D (mips_arch))
-    mips_opts.ase_mips3d = 1;
-  if (mips_opts.ase_mdmx == -1 && CPU_HAS_MDMX (mips_arch))
-    mips_opts.ase_mdmx = 1;
 
   if (! bfd_set_arch_mach (stdoutput, bfd_arch_mips, mips_arch))
     as_warn (_("Could not set architecture and machine"));
 
-  if (file_mips_gp32 < 0)
-    file_mips_gp32 = 0;
-  if (file_mips_fp32 < 0)
-    file_mips_fp32 = 0;
-
-  file_mips_isa = mips_opts.isa;
-  file_mips_abi = mips_opts.abi;
-  file_ase_mips3d = mips_opts.ase_mips3d;
-  file_ase_mdmx = mips_opts.ase_mdmx;
-  mips_opts.gp32 = file_mips_gp32;
-  mips_opts.fp32 = file_mips_fp32;
-
-  if (HAVE_NEWABI)
-    mips_big_got = 1;
-
   op_hash = hash_new ();
 
   for (i = 0; i < NUMOPCODES;)
@@ -1351,6 +1109,8 @@ md_begin ()
                                   &zero_address_frag));
   symbol_table_insert (symbol_new ("$kt1", reg_section, KT1,
                                   &zero_address_frag));
+  symbol_table_insert (symbol_new ("$zero", reg_section, ZERO,
+                                  &zero_address_frag));
   symbol_table_insert (symbol_new ("$pc", reg_section, -1,
                                   &zero_address_frag));
 
@@ -1398,7 +1158,7 @@ md_begin ()
        if (strcmp (TARGET_OS, "elf") != 0)
          flags |= SEC_ALLOC | SEC_LOAD;
 
-       if (file_mips_abi != N64_ABI)
+       if (mips_abi != N64_ABI)
          {
            sec = subseg_new (".reginfo", (subsegT) 0);
 
@@ -1444,12 +1204,15 @@ md_begin ()
                                          SEC_HAS_CONTENTS | SEC_READONLY);
            (void) bfd_set_section_alignment (stdoutput, sec, 2);
          }
-
-#ifdef MIPS_STABS_ELF
-       pdr_seg = subseg_new (".pdr", (subsegT) 0);
-       (void) bfd_set_section_flags (stdoutput, pdr_seg,
-                            SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
-       (void) bfd_set_section_alignment (stdoutput, pdr_seg, 2);
+#ifdef OBJ_ELF
+       else if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+         {
+           pdr_seg = subseg_new (".pdr", (subsegT) 0);
+           (void) bfd_set_section_flags (stdoutput, pdr_seg,
+                                         SEC_READONLY | SEC_RELOC
+                                         | SEC_DEBUGGING);
+           (void) bfd_set_section_alignment (stdoutput, pdr_seg, 2);
+         }
 #endif
 
        subseg_set (seg, subseg);
@@ -1534,8 +1297,8 @@ insn_uses_reg (ip, reg, class)
       class = MIPS_GR_REG;
     }
 
-  /* Don't report on general register 0, since it never changes.  */
-  if (class == MIPS_GR_REG && reg == 0)
+  /* Don't report on general register ZERO, since it never changes.  */
+  if (class == MIPS_GR_REG && reg == ZERO)
     return 0;
 
   if (class == MIPS_FP_REG)
@@ -2240,11 +2003,19 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
     }
 
   if (! mips_opts.mips16)
-    md_number_to_chars (f, ip->insn_opcode, 4);
+    {
+      md_number_to_chars (f, ip->insn_opcode, 4);
+#ifdef OBJ_ELF
+      dwarf2_emit_insn (4);
+#endif
+    }
   else if (*reloc_type == BFD_RELOC_MIPS16_JMP)
     {
       md_number_to_chars (f, ip->insn_opcode >> 16, 2);
       md_number_to_chars (f + 2, ip->insn_opcode & 0xffff, 2);
+#ifdef OBJ_ELF
+      dwarf2_emit_insn (4);
+#endif
     }
   else
     {
@@ -2254,6 +2025,9 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
          f += 2;
        }
       md_number_to_chars (f, ip->insn_opcode, 2);
+#ifdef OBJ_ELF
+      dwarf2_emit_insn (ip->use_extend ? 4 : 2);
+#endif
     }
 
   /* Update the register mask information.  */
@@ -2935,7 +2709,10 @@ macro_build (place, counter, ep, name, fmt, va_alist)
          MDMX or MIPS-3D instructions.  */
       if (strcmp (fmt, insn.insn_mo->args) == 0
          && insn.insn_mo->pinfo != INSN_MACRO
-         && OPCODE_IS_MEMBER (insn.insn_mo, mips_opts.isa, mips_arch)
+         && OPCODE_IS_MEMBER (insn.insn_mo,
+                              (mips_opts.isa
+                               | (mips_opts.mips16 ? INSN_MIPS16 : 0)),
+                              mips_arch)
          && (mips_arch != CPU_R4650 || (insn.insn_mo->pinfo & FP_D) == 0))
        break;
 
@@ -3232,12 +3009,18 @@ macro_build_jalr (icnt, ep)
      int icnt;
      expressionS *ep;
 {
+  char *f;
+  
   if (HAVE_NEWABI)
-    frag_more (0);
+    {
+      frag_grow (4);
+      f = frag_more (0);
+    }
   macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "jalr", "d,s",
               RA, PIC_CALL_REG);
   if (HAVE_NEWABI)
-    fix_new_exp (frag_now, 0, 0, ep, false, BFD_RELOC_MIPS_JALR);
+    fix_new_exp (frag_now, f - frag_now->fr_literal,
+                0, ep, false, BFD_RELOC_MIPS_JALR);
 }
 
 /*
@@ -3254,8 +3037,8 @@ macro_build_lui (place, counter, ep, regnum)
   struct mips_cl_insn insn;
   bfd_reloc_code_real_type r[3]
     = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
-  CONST char *name = "lui";
-  CONST char *fmt = "t,u";
+  const char *name = "lui";
+  const char *fmt = "t,u";
 
   assert (! mips_opts.mips16);
 
@@ -3735,7 +3518,7 @@ load_address (counter, reg, ep, used_at)
           daddiu       $reg,<sym>              (BFD_RELOC_MIPS_HIGHER)
           daddiu       $at,<sym>               (BFD_RELOC_LO16)
           dsll32       $reg,0
-          dadd         $reg,$reg,$at
+          daddu        $reg,$reg,$at
 
         If $at is already in use, we use an path which is suboptimal
         on superscalar processors.
@@ -3751,7 +3534,7 @@ load_address (counter, reg, ep, used_at)
          /* We don't do GP optimization for now because RELAX_ENCODE can't
             hold the data for such large chunks.  */
 
-         if (*used_at == 0)
+         if (*used_at == 0 && ! mips_opts.noat)
            {
              macro_build (p, counter, ep, "lui", "t,u",
                           reg, (int) BFD_RELOC_MIPS_HIGHEST);
@@ -3763,7 +3546,7 @@ load_address (counter, reg, ep, used_at)
                           AT, AT, (int) BFD_RELOC_LO16);
              macro_build (p, counter, (expressionS *) NULL, "dsll32",
                           "d,w,<", reg, reg, 0);
-             macro_build (p, counter, (expressionS *) NULL, "dadd",
+             macro_build (p, counter, (expressionS *) NULL, "daddu",
                           "d,v,t", reg, reg, AT);
              *used_at = 1;
            }
@@ -4463,7 +4246,7 @@ macro (ip)
          as_warn (_("Divide by zero."));
          if (mips_trap)
            macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq",
-                        "s,t", 0, 0);
+                        "s,t,q", 0, 0, 7);
          else
            macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
                         "c", 7);
@@ -4476,7 +4259,7 @@ macro (ip)
       if (mips_trap)
        {
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq",
-                      "s,t", treg, 0);
+                      "s,t,q", treg, 0, 7);
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                       dbl ? "ddiv" : "div", "z,s,t", sreg, treg);
        }
@@ -4512,7 +4295,7 @@ macro (ip)
       if (mips_trap)
        {
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq",
-                      "s,t", sreg, AT);
+                      "s,t,q", sreg, AT, 6);
          /* We want to close the noreorder block as soon as possible, so
             that later insns are available for delay slot filling.  */
          --mips_opts.noreorder;
@@ -4575,7 +4358,7 @@ macro (ip)
          as_warn (_("Divide by zero."));
          if (mips_trap)
            macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq",
-                        "s,t", 0, 0);
+                        "s,t,q", 0, 0, 7);
          else
            macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break",
                         "c", 7);
@@ -4631,7 +4414,7 @@ macro (ip)
       if (mips_trap)
        {
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq",
-                      "s,t", treg, 0);
+                      "s,t,q", treg, 0, 7);
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "z,s,t",
                       sreg, treg);
          /* We want to close the noreorder block as soon as possible, so
@@ -4666,6 +4449,16 @@ macro (ip)
       if (! dbl && HAVE_64BIT_OBJECTS)
        as_warn (_("la used to load 64-bit address"));
 
+      if (offset_expr.X_op == O_constant
+         && offset_expr.X_add_number >= -0x8000
+         && offset_expr.X_add_number < 0x8000)
+       {
+         macro_build ((char *) NULL, &icnt, &offset_expr,
+                      (dbl || HAVE_64BIT_ADDRESSES) ? "daddiu" : "addiu",
+                      "t,r,j", treg, sreg, (int) BFD_RELOC_LO16);
+         return;
+       }
+
       if (treg == breg)
        {
          tempreg = AT;
@@ -4749,7 +4542,7 @@ macro (ip)
              daddiu    $tempreg,<sym>          (BFD_RELOC_MIPS_HIGHER)
              daddiu    $at,<sym>               (BFD_RELOC_LO16)
              dsll32    $tempreg,0
-             dadd      $tempreg,$tempreg,$at
+             daddu     $tempreg,$tempreg,$at
 
            If $at is already in use, we use an path which is suboptimal
            on superscalar processors.
@@ -4766,7 +4559,7 @@ macro (ip)
              /* We don't do GP optimization for now because RELAX_ENCODE can't
                 hold the data for such large chunks.  */
 
-             if (used_at == 0)
+             if (used_at == 0 && ! mips_opts.noat)
                {
                  macro_build (p, &icnt, &offset_expr, "lui", "t,u",
                               tempreg, (int) BFD_RELOC_MIPS_HIGHEST);
@@ -4778,8 +4571,8 @@ macro (ip)
                               AT, AT, (int) BFD_RELOC_LO16);
                  macro_build (p, &icnt, (expressionS *) NULL, "dsll32",
                               "d,w,<", tempreg, tempreg, 0);
-                 macro_build (p, &icnt, (expressionS *) NULL, "dadd", "d,v,t",
-                              tempreg, tempreg, AT);
+                 macro_build (p, &icnt, (expressionS *) NULL, "daddu",
+                              "d,v,t", tempreg, tempreg, AT);
                  used_at = 1;
                }
              else
@@ -5704,20 +5497,22 @@ macro (ip)
             If we have 64-bit addresses, as an optimization, for
             addresses which are 32-bit constants (e.g. kseg0/kseg1
             addresses) we fall back to the 32-bit address generation
-            mechanism since it is more efficient.  This code should
+            mechanism since it is more efficient.  Note that due to
+            the signed offset used by memory operations, the 32-bit
+            range is shifted down by 32768 here.  This code should
             probably attempt to generate 64-bit constants more
             efficiently in general.
           */
          if (HAVE_64BIT_ADDRESSES
              && !(offset_expr.X_op == O_constant
-                  && IS_SEXT_32BIT_NUM (offset_expr.X_add_number)))
+                  && IS_SEXT_32BIT_NUM (offset_expr.X_add_number + 0x8000)))
            {
              p = NULL;
 
              /* We don't do GP optimization for now because RELAX_ENCODE can't
                 hold the data for such large chunks.  */
 
-             if (used_at == 0)
+             if (used_at == 0 && ! mips_opts.noat)
                {
                  macro_build (p, &icnt, &offset_expr, "lui", "t,u",
                               tempreg, (int) BFD_RELOC_MIPS_HIGHEST);
@@ -6778,8 +6573,8 @@ macro2 (ip)
       macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mfhi", "d",
                   AT);
       if (mips_trap)
-       macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "tne", "s,t",
-                    dreg, AT);
+       macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "tne",
+                    "s,t,q", dreg, AT, 6);
       else
        {
          expr1.X_add_number = 8;
@@ -6817,8 +6612,8 @@ macro2 (ip)
       macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "d",
                   dreg);
       if (mips_trap)
-       macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "tne", "s,t",
-                    AT, 0);
+       macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "tne",
+                    "s,t,q", AT, 0, 6);
       else
        {
          expr1.X_add_number = 8;
@@ -7938,6 +7733,7 @@ mips_ip (str, ip)
 
       if (OPCODE_IS_MEMBER (insn,
                            (mips_opts.isa
+                            | (mips_opts.mips16 ? INSN_MIPS16 : 0)
                             | (mips_opts.ase_mdmx ? INSN_MDMX : 0)
                             | (mips_opts.ase_mips3d ? INSN_MIPS3D : 0)),
                            mips_arch))
@@ -7964,11 +7760,15 @@ mips_ip (str, ip)
              if (!insn_error)
                {
                  static char buf[100];
-                 sprintf (buf,
-                          _("opcode not supported on this processor: %s (%s)"),
-                          mips_cpu_to_str (mips_arch),
-                          mips_isa_to_str (mips_opts.isa));
-
+                 if (mips_arch_info->is_isa)
+                   sprintf (buf,
+                            _("opcode not supported at this ISA level (%s)"),
+                            mips_cpu_info_from_isa (mips_opts.isa)->name);
+                 else
+                   sprintf (buf,
+                            _("opcode not supported on this processor: %s (%s)"),
+                            mips_arch_info->name,
+                            mips_cpu_info_from_isa (mips_opts.isa)->name);
                  insn_error = buf;
                }
              if (save_c)
@@ -8045,8 +7845,8 @@ mips_ip (str, ip)
              check_absolute_expr (ip, &imm_expr);
              if ((unsigned long) imm_expr.X_add_number > 31)
                {
-                 as_warn (_("Improper shift amount (%ld)"),
-                          (long) imm_expr.X_add_number);
+                 as_warn (_("Improper shift amount (%lu)"),
+                          (unsigned long) imm_expr.X_add_number);
                  imm_expr.X_add_number &= OP_MASK_SHAMT;
                }
              ip->insn_opcode |= imm_expr.X_add_number << OP_SH_SHAMT;
@@ -8087,10 +7887,10 @@ mips_ip (str, ip)
            case 'c':           /* break code */
              my_getExpression (&imm_expr, s);
              check_absolute_expr (ip, &imm_expr);
-             if ((unsigned) imm_expr.X_add_number > 1023)
+             if ((unsigned long) imm_expr.X_add_number > 1023)
                {
-                 as_warn (_("Illegal break code (%ld)"),
-                          (long) imm_expr.X_add_number);
+                 as_warn (_("Illegal break code (%lu)"),
+                          (unsigned long) imm_expr.X_add_number);
                  imm_expr.X_add_number &= OP_MASK_CODE;
                }
              ip->insn_opcode |= imm_expr.X_add_number << OP_SH_CODE;
@@ -8101,10 +7901,10 @@ mips_ip (str, ip)
            case 'q':           /* lower break code */
              my_getExpression (&imm_expr, s);
              check_absolute_expr (ip, &imm_expr);
-             if ((unsigned) imm_expr.X_add_number > 1023)
+             if ((unsigned long) imm_expr.X_add_number > 1023)
                {
-                 as_warn (_("Illegal lower break code (%ld)"),
-                          (long) imm_expr.X_add_number);
+                 as_warn (_("Illegal lower break code (%lu)"),
+                          (unsigned long) imm_expr.X_add_number);
                  imm_expr.X_add_number &= OP_MASK_CODE2;
                }
              ip->insn_opcode |= imm_expr.X_add_number << OP_SH_CODE2;
@@ -8115,9 +7915,9 @@ mips_ip (str, ip)
            case 'B':           /* 20-bit syscall/break code.  */
              my_getExpression (&imm_expr, s);
              check_absolute_expr (ip, &imm_expr);
-             if ((unsigned) imm_expr.X_add_number > OP_MASK_CODE20)
-               as_warn (_("Illegal 20-bit code (%ld)"),
-                        (long) imm_expr.X_add_number);
+             if ((unsigned long) imm_expr.X_add_number > OP_MASK_CODE20)
+               as_warn (_("Illegal 20-bit code (%lu)"),
+                        (unsigned long) imm_expr.X_add_number);
              ip->insn_opcode |= imm_expr.X_add_number << OP_SH_CODE20;
              imm_expr.X_op = O_absent;
              s = expr_end;
@@ -8128,8 +7928,8 @@ mips_ip (str, ip)
              check_absolute_expr (ip, &imm_expr);
              if ((unsigned long) imm_expr.X_add_number >= (1 << 25))
                {
-                 as_warn (_("Coproccesor code > 25 bits (%ld)"),
-                          (long) imm_expr.X_add_number);
+                 as_warn (_("Coproccesor code > 25 bits (%lu)"),
+                          (unsigned long) imm_expr.X_add_number);
                  imm_expr.X_add_number &= ((1 << 25) - 1);
                }
              ip->insn_opcode |= imm_expr.X_add_number;
@@ -8140,9 +7940,9 @@ mips_ip (str, ip)
            case 'J':           /* 19-bit wait code.  */
              my_getExpression (&imm_expr, s);
              check_absolute_expr (ip, &imm_expr);
-             if ((unsigned) imm_expr.X_add_number > OP_MASK_CODE19)
-               as_warn (_("Illegal 19-bit code (%ld)"),
-                        (long) imm_expr.X_add_number);
+             if ((unsigned long) imm_expr.X_add_number > OP_MASK_CODE19)
+               as_warn (_("Illegal 19-bit code (%lu)"),
+                        (unsigned long) imm_expr.X_add_number);
              ip->insn_opcode |= imm_expr.X_add_number << OP_SH_CODE19;
              imm_expr.X_op = O_absent;
              s = expr_end;
@@ -8153,8 +7953,8 @@ mips_ip (str, ip)
              check_absolute_expr (ip, &imm_expr);
              if (imm_expr.X_add_number != 0 && imm_expr.X_add_number != 1)
                {
-                 as_warn (_("Invalid performance register (%ld)"),
-                          (long) imm_expr.X_add_number);
+                 as_warn (_("Invalid performance register (%lu)"),
+                          (unsigned long) imm_expr.X_add_number);
                  imm_expr.X_add_number &= OP_MASK_PERFREG;
                }
              ip->insn_opcode |= (imm_expr.X_add_number << OP_SH_PERFREG);
@@ -8231,6 +8031,11 @@ mips_ip (str, ip)
                          s += 4;
                          regno = KT1;
                        }
+                     else if (s[1] == 'z' && s[2] == 'e' && s[3] == 'r' && s[4] == 'o')
+                       {
+                         s += 5;
+                         regno = ZERO;
+                       }
                      else if (itbl_have_entries)
                        {
                          char *p, *n;
@@ -8726,9 +8531,11 @@ mips_ip (str, ip)
                {
                  if (c != S_EX_LO)
                    {
-                     if (imm_expr.X_op == O_constant)
-                       imm_expr.X_add_number =
-                         (imm_expr.X_add_number >> 16) & 0xffff;
+                     if (c == S_EX_HI)
+                       {
+                         *imm_reloc = BFD_RELOC_HI16_S;
+                         imm_unmatched_hi = true;
+                       }
 #ifdef OBJ_ELF
                      else if (c == S_EX_HIGHEST)
                        *imm_reloc = BFD_RELOC_MIPS_HIGHEST;
@@ -8754,11 +8561,6 @@ mips_ip (str, ip)
                            }
                        }
 #endif
-                     else if (c == S_EX_HI)
-                       {
-                         *imm_reloc = BFD_RELOC_HI16_S;
-                         imm_unmatched_hi = true;
-                       }
                      else
                        *imm_reloc = BFD_RELOC_HI16;
                    }
@@ -8859,10 +8661,7 @@ mips_ip (str, ip)
                {
                  if (c != S_EX_LO)
                    {
-                     if (imm_expr.X_op == O_constant)
-                       imm_expr.X_add_number =
-                         (imm_expr.X_add_number >> 16) & 0xffff;
-                     else if (c == S_EX_HI)
+                     if (c == S_EX_HI)
                        {
                          *imm_reloc = BFD_RELOC_HI16_S;
                          imm_unmatched_hi = true;
@@ -8896,9 +8695,9 @@ mips_ip (str, ip)
                  else if (imm_expr.X_op == O_constant)
                    imm_expr.X_add_number &= 0xffff;
                }
-             if (imm_expr.X_op == O_constant
-                 && (imm_expr.X_add_number < 0
-                     || imm_expr.X_add_number >= 0x10000))
+             else if (imm_expr.X_op == O_constant
+                      && (imm_expr.X_add_number < 0
+                          || imm_expr.X_add_number >= 0x10000))
                as_bad (_("lui expression not in range 0..65535"));
              s = expr_end;
              continue;
@@ -9189,6 +8988,11 @@ mips16_ip (str, ip)
                      s += 4;
                      regno = KT1;
                    }
+                 else if (s[1] == 'z' && s[2] == 'e' && s[3] == 'r' && s[4] == 'o')
+                   {
+                     s += 5;
+                     regno = ZERO;
+                   }
                  else
                    break;
                }
@@ -10031,7 +9835,7 @@ static int support_64bit_objects(void)
 }
 #endif /* OBJ_ELF */
 
-CONST char *md_shortopts = "nO::g::G:";
+const char *md_shortopts = "nO::g::G:";
 
 struct option md_longopts[] =
 {
@@ -10083,8 +9887,8 @@ struct option md_longopts[] =
   {"march", required_argument, NULL, OPTION_MARCH},
 #define OPTION_MTUNE (OPTION_MD_BASE + 22)
   {"mtune", required_argument, NULL, OPTION_MTUNE},
-#define OPTION_MCPU (OPTION_MD_BASE + 23)
-  {"mcpu", required_argument, NULL, OPTION_MCPU},
+#define OPTION_FP64 (OPTION_MD_BASE + 23)
+  {"mfp64", no_argument, NULL, OPTION_FP64},
 #define OPTION_M4650 (OPTION_MD_BASE + 24)
   {"m4650", no_argument, NULL, OPTION_M4650},
 #define OPTION_NO_M4650 (OPTION_MD_BASE + 25)
@@ -10128,11 +9932,33 @@ struct option md_longopts[] =
   {"n32",         no_argument, NULL, OPTION_N32},
 #define OPTION_64          (OPTION_ELF_BASE + 6)
   {"64",          no_argument, NULL, OPTION_64},
+#define OPTION_MDEBUG      (OPTION_ELF_BASE + 7)
+  {"mdebug", no_argument, NULL, OPTION_MDEBUG},
+#define OPTION_NO_MDEBUG   (OPTION_ELF_BASE + 8)
+  {"no-mdebug", no_argument, NULL, OPTION_NO_MDEBUG},
 #endif /* OBJ_ELF */
   {NULL, no_argument, NULL, 0}
 };
 size_t md_longopts_size = sizeof (md_longopts);
 
+/* Set STRING_PTR (either &mips_arch_string or &mips_tune_string) to
+   NEW_VALUE.  Warn if another value was already specified.  Note:
+   we have to defer parsing the -march and -mtune arguments in order
+   to handle 'from-abi' correctly, since the ABI might be specified
+   in a later argument.  */
+
+static void
+mips_set_option_string (string_ptr, new_value)
+     const char **string_ptr, *new_value;
+{
+  if (*string_ptr != 0 && strcasecmp (*string_ptr, new_value) != 0)
+    as_warn (_("A different %s was already specified, is now %s"),
+            string_ptr == &mips_arch_string ? "-march" : "-mtune",
+            new_value);
+
+  *string_ptr = new_value;
+}
+
 int
 md_parse_option (c, arg)
      int c;
@@ -10188,130 +10014,68 @@ md_parse_option (c, arg)
       break;
 
     case OPTION_MIPS1:
-      mips_opts.isa = ISA_MIPS1;
+      file_mips_isa = ISA_MIPS1;
       break;
 
     case OPTION_MIPS2:
-      mips_opts.isa = ISA_MIPS2;
+      file_mips_isa = ISA_MIPS2;
       break;
 
     case OPTION_MIPS3:
-      mips_opts.isa = ISA_MIPS3;
+      file_mips_isa = ISA_MIPS3;
       break;
 
     case OPTION_MIPS4:
-      mips_opts.isa = ISA_MIPS4;
+      file_mips_isa = ISA_MIPS4;
       break;
 
     case OPTION_MIPS5:
-      mips_opts.isa = ISA_MIPS5;
+      file_mips_isa = ISA_MIPS5;
       break;
 
     case OPTION_MIPS32:
-      mips_opts.isa = ISA_MIPS32;
+      file_mips_isa = ISA_MIPS32;
       break;
 
     case OPTION_MIPS64:
-      mips_opts.isa = ISA_MIPS64;
+      file_mips_isa = ISA_MIPS64;
       break;
 
     case OPTION_MTUNE:
-    case OPTION_MARCH:
-    case OPTION_MCPU:
-      {
-       int cpu = CPU_UNKNOWN;
-
-       /* Identify the processor type.  */
-       if (strcasecmp (arg, "default") != 0)
-         {
-           const struct mips_cpu_info *ci;
-
-           ci = mips_cpu_info_from_name (arg);
-           if (ci == NULL || ci->is_isa)
-             {
-               switch (c)
-                 {
-                 case OPTION_MTUNE:
-                   as_fatal (_("invalid architecture -mtune=%s"), arg);
-                   break;
-                 case OPTION_MARCH:
-                   as_fatal (_("invalid architecture -march=%s"), arg);
-                   break;
-                 case OPTION_MCPU:
-                   as_fatal (_("invalid architecture -mcpu=%s"), arg);
-                   break;
-                 }
-             }
-           else
-             cpu = ci->cpu;
-         }
+      mips_set_option_string (&mips_tune_string, arg);
+      break;
 
-       switch (c)
-         {
-         case OPTION_MTUNE:
-           if (mips_tune != CPU_UNKNOWN && mips_tune != cpu)
-             as_warn (_("A different -mtune= was already specified, is now "
-                        "-mtune=%s"), arg);
-           mips_tune = cpu;
-           break;
-         case OPTION_MARCH:
-           if (mips_arch != CPU_UNKNOWN && mips_arch != cpu)
-             as_warn (_("A different -march= was already specified, is now "
-                        "-march=%s"), arg);
-           mips_arch = cpu;
-           break;
-         case OPTION_MCPU:
-           if (mips_cpu != CPU_UNKNOWN && mips_cpu != cpu)
-             as_warn (_("A different -mcpu= was already specified, is now "
-                        "-mcpu=%s"), arg);
-           mips_cpu = cpu;
-         }
-      }
+    case OPTION_MARCH:
+      mips_set_option_string (&mips_arch_string, arg);
       break;
 
     case OPTION_M4650:
-      if ((mips_arch != CPU_UNKNOWN && mips_arch != CPU_R4650)
-         || (mips_tune != CPU_UNKNOWN && mips_tune != CPU_R4650))
-       as_warn (_("A different -march= or -mtune= was already specified, "
-                  "is now -m4650"));
-      mips_arch = CPU_R4650;
-      mips_tune = CPU_R4650;
+      mips_set_option_string (&mips_arch_string, "4650");
+      mips_set_option_string (&mips_tune_string, "4650");
       break;
 
     case OPTION_NO_M4650:
       break;
 
     case OPTION_M4010:
-      if ((mips_arch != CPU_UNKNOWN && mips_arch != CPU_R4010)
-         || (mips_tune != CPU_UNKNOWN && mips_tune != CPU_R4010))
-       as_warn (_("A different -march= or -mtune= was already specified, "
-                  "is now -m4010"));
-      mips_arch = CPU_R4010;
-      mips_tune = CPU_R4010;
+      mips_set_option_string (&mips_arch_string, "4010");
+      mips_set_option_string (&mips_tune_string, "4010");
       break;
 
     case OPTION_NO_M4010:
       break;
 
     case OPTION_M4100:
-      if ((mips_arch != CPU_UNKNOWN && mips_arch != CPU_VR4100)
-         || (mips_tune != CPU_UNKNOWN && mips_tune != CPU_VR4100))
-       as_warn (_("A different -march= or -mtune= was already specified, "
-                  "is now -m4100"));
-      mips_arch = CPU_VR4100;
-      mips_tune = CPU_VR4100;
+      mips_set_option_string (&mips_arch_string, "4100");
+      mips_set_option_string (&mips_tune_string, "4100");
       break;
 
     case OPTION_NO_M4100:
       break;
 
     case OPTION_M3900:
-      if ((mips_arch != CPU_UNKNOWN && mips_arch != CPU_R3900)
-         || (mips_tune != CPU_UNKNOWN && mips_tune != CPU_R3900))
-       as_warn (_("A different -march= or -mtune= was already specified, "
-                  "is now -m3900"));
-      mips_arch = CPU_R3900;
-      mips_tune = CPU_R3900;
+      mips_set_option_string (&mips_arch_string, "3900");
+      mips_set_option_string (&mips_tune_string, "3900");
       break;
 
     case OPTION_NO_M3900:
@@ -10414,7 +10178,7 @@ md_parse_option (c, arg)
          as_bad (_("-32 is supported for ELF format only"));
          return 0;
        }
-      mips_opts.abi = O32_ABI;
+      mips_abi = O32_ABI;
       break;
 
     case OPTION_N32:
@@ -10423,7 +10187,7 @@ md_parse_option (c, arg)
          as_bad (_("-n32 is supported for ELF format only"));
          return 0;
        }
-      mips_opts.abi = N32_ABI;
+      mips_abi = N32_ABI;
       break;
 
     case OPTION_64:
@@ -10432,7 +10196,7 @@ md_parse_option (c, arg)
          as_bad (_("-64 is supported for ELF format only"));
          return 0;
        }
-      mips_opts.abi = N64_ABI;
+      mips_abi = N64_ABI;
       if (! support_64bit_objects())
        as_fatal (_("No compiled in support for 64 bit object file format"));
       break;
@@ -10440,20 +10204,18 @@ md_parse_option (c, arg)
 
     case OPTION_GP32:
       file_mips_gp32 = 1;
-      if (mips_opts.abi != O32_ABI)
-       mips_opts.abi = NO_ABI;
       break;
 
     case OPTION_GP64:
       file_mips_gp32 = 0;
-      if (mips_opts.abi == O32_ABI)
-       mips_opts.abi = NO_ABI;
       break;
 
     case OPTION_FP32:
       file_mips_fp32 = 1;
-      if (mips_opts.abi != O32_ABI)
-       mips_opts.abi = NO_ABI;
+      break;
+
+    case OPTION_FP64:
+      file_mips_fp32 = 0;
       break;
 
 #ifdef OBJ_ELF
@@ -10464,20 +10226,20 @@ md_parse_option (c, arg)
          return 0;
        }
       if (strcmp (arg, "32") == 0)
-       mips_opts.abi = O32_ABI;
+       mips_abi = O32_ABI;
       else if (strcmp (arg, "o64") == 0)
-       mips_opts.abi = O64_ABI;
+       mips_abi = O64_ABI;
       else if (strcmp (arg, "n32") == 0)
-       mips_opts.abi = N32_ABI;
+       mips_abi = N32_ABI;
       else if (strcmp (arg, "64") == 0)
        {
-         mips_opts.abi = N64_ABI;
+         mips_abi = N64_ABI;
          if (! support_64bit_objects())
            as_fatal (_("No compiled in support for 64 bit object file "
                        "format"));
        }
       else if (strcmp (arg, "eabi") == 0)
-       mips_opts.abi = EABI_ABI;
+       mips_abi = EABI_ABI;
       else
        {
          as_fatal (_("invalid abi -mabi=%s"), arg);
@@ -10494,140 +10256,175 @@ md_parse_option (c, arg)
       mips_7000_hilo_fix = false;
       break;
 
+#ifdef OBJ_ELF
+    case OPTION_MDEBUG:
+      mips_flag_mdebug = true;
+      break;
+
+    case OPTION_NO_MDEBUG:
+      mips_flag_mdebug = false;
+      break;
+#endif /* OBJ_ELF */
+
     default:
       return 0;
     }
 
   return 1;
 }
+\f
+/* Set up globals to generate code for the ISA or processor
+   described by INFO.  */
 
 static void
-show (stream, string, col_p, first_p)
-     FILE *stream;
-     char *string;
-     int *col_p;
-     int *first_p;
+mips_set_architecture (info)
+     const struct mips_cpu_info *info;
 {
-  if (*first_p)
-    {
-      fprintf (stream, "%24s", "");
-      *col_p = 24;
-    }
-  else
+  if (info != 0)
     {
-      fprintf (stream, ", ");
-      *col_p += 2;
+      mips_arch_info = info;
+      mips_arch = info->cpu;
+      mips_opts.isa = info->isa;
     }
+}
 
-  if (*col_p + strlen (string) > 72)
-    {
-      fprintf (stream, "\n%24s", "");
-      *col_p = 24;
-    }
 
-  fprintf (stream, "%s", string);
-  *col_p += strlen (string);
+/* Likewise for tuning.  */
 
-  *first_p = 0;
+static void
+mips_set_tune (info)
+     const struct mips_cpu_info *info;
+{
+  if (info != 0)
+    {
+      mips_tune_info = info;
+      mips_tune = info->cpu;
+    }
 }
 
+
 void
-md_show_usage (stream)
-     FILE *stream;
+mips_after_parse_args ()
 {
-  int column, first;
+  /* 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;
+    }
 
-  fprintf (stream, _("\
-MIPS options:\n\
--membedded-pic         generate embedded position independent code\n\
--EB                    generate big endian output\n\
--EL                    generate little endian output\n\
--g, -g2                        do not remove unneeded NOPs or swap branches\n\
--G NUM                 allow referencing objects up to NUM bytes\n\
-                       implicitly with the gp register [default 8]\n"));
-  fprintf (stream, _("\
--mips1                 generate MIPS ISA I instructions\n\
--mips2                 generate MIPS ISA II instructions\n\
--mips3                 generate MIPS ISA III instructions\n\
--mips4                 generate MIPS ISA IV instructions\n\
--mips5                  generate MIPS ISA V instructions\n\
--mips32                 generate MIPS32 ISA instructions\n\
--mips64                 generate MIPS64 ISA instructions\n\
--march=CPU/-mtune=CPU  generate code/schedule for CPU, where CPU is one of:\n"));
+  /* The following code determines the architecture and register size.
+     Similar code was added to GCC 3.3 (see override_options() in
+     config/mips/mips.c).  The GAS and GCC code should be kept in sync
+     as much as possible.  */
 
-  first = 1;
+  if (mips_arch_string != 0)
+    mips_set_architecture (mips_parse_cpu ("-march", mips_arch_string));
 
-  show (stream, "2000", &column, &first);
-  show (stream, "3000", &column, &first);
-  show (stream, "3900", &column, &first);
-  show (stream, "4000", &column, &first);
-  show (stream, "4010", &column, &first);
-  show (stream, "4100", &column, &first);
-  show (stream, "4111", &column, &first);
-  show (stream, "4300", &column, &first);
-  show (stream, "4400", &column, &first);
-  show (stream, "4600", &column, &first);
-  show (stream, "4650", &column, &first);
-  show (stream, "5000", &column, &first);
-  show (stream, "5200", &column, &first);
-  show (stream, "5230", &column, &first);
-  show (stream, "5231", &column, &first);
-  show (stream, "5261", &column, &first);
-  show (stream, "5721", &column, &first);
-  show (stream, "6000", &column, &first);
-  show (stream, "8000", &column, &first);
-  show (stream, "10000", &column, &first);
-  show (stream, "12000", &column, &first);
-  show (stream, "sb1", &column, &first);
-  fputc ('\n', stream);
+  if (mips_tune_string != 0)
+    mips_set_tune (mips_parse_cpu ("-mtune", mips_tune_string));
 
-  fprintf (stream, _("\
--mCPU                  equivalent to -march=CPU -mtune=CPU. Deprecated.\n\
--no-mCPU               don't generate code specific to CPU.\n\
-                       For -mCPU and -no-mCPU, CPU must be one of:\n"));
+  if (file_mips_isa != ISA_UNKNOWN)
+    {
+      /* Handle -mipsN.  At this point, file_mips_isa contains the
+        ISA level specified by -mipsN, while mips_opts.isa contains
+        the -march selection (if any).  */
+      if (mips_arch_info != 0)
+       {
+         /* -march takes precedence over -mipsN, since it is more descriptive.
+            There's no harm in specifying both as long as the ISA levels
+            are the same.  */
+         if (file_mips_isa != mips_opts.isa)
+           as_bad (_("-%s conflicts with the other architecture options, which imply -%s"),
+                   mips_cpu_info_from_isa (file_mips_isa)->name,
+                   mips_cpu_info_from_isa (mips_opts.isa)->name);
+       }
+      else
+       mips_set_architecture (mips_cpu_info_from_isa (file_mips_isa));
+    }
 
-  first = 1;
+  if (mips_arch_info == 0)
+    mips_set_architecture (mips_parse_cpu ("default CPU",
+                                          MIPS_CPU_STRING_DEFAULT));
 
-  show (stream, "3900", &column, &first);
-  show (stream, "4010", &column, &first);
-  show (stream, "4100", &column, &first);
-  show (stream, "4650", &column, &first);
-  fputc ('\n', stream);
+  if (ABI_NEEDS_64BIT_REGS (mips_abi) && !ISA_HAS_64BIT_REGS (mips_opts.isa))
+    as_bad ("-march=%s is not compatible with the selected ABI",
+           mips_arch_info->name);
 
-  fprintf (stream, _("\
--mips16                        generate mips16 instructions\n\
--no-mips16             do not generate mips16 instructions\n"));
-  fprintf (stream, _("\
--mgp32                 use 32-bit GPRs, regardless of the chosen ISA\n\
--mfp32                 use 32-bit FPRs, regardless of the chosen ISA\n\
--O0                    remove unneeded NOPs, do not swap branches\n\
--O                     remove unneeded NOPs and swap branches\n\
--n                     warn about NOPs generated from macros\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
-  fprintf (stream, _("\
--KPIC, -call_shared    generate SVR4 position independent code\n\
--non_shared            do not generate position independent code\n\
--xgot                  assume a 32 bit GOT\n\
--mabi=ABI              create ABI conformant object file for:\n"));
+  /* Optimize for mips_arch, unless -mtune selects a different processor.  */
+  if (mips_tune_info == 0)
+    mips_set_tune (mips_arch_info);
 
-  first = 1;
+  if (file_mips_gp32 >= 0)
+    {
+      /* The user specified the size of the integer registers.  Make sure
+        it agrees with the ABI and ISA.  */
+      if (file_mips_gp32 == 0 && !ISA_HAS_64BIT_REGS (mips_opts.isa))
+       as_bad (_("-mgp64 used with a 32-bit processor"));
+      else if (file_mips_gp32 == 1 && ABI_NEEDS_64BIT_REGS (mips_abi))
+       as_bad (_("-mgp32 used with a 64-bit ABI"));
+      else if (file_mips_gp32 == 0 && ABI_NEEDS_32BIT_REGS (mips_abi))
+       as_bad (_("-mgp64 used with a 32-bit ABI"));
+    }
+  else
+    {
+      /* Infer the integer register size from the ABI and processor.
+        Restrict ourselves to 32-bit registers if that's all the
+        processor has, or if the ABI cannot handle 64-bit registers.  */
+      file_mips_gp32 = (ABI_NEEDS_32BIT_REGS (mips_abi)
+                       || !ISA_HAS_64BIT_REGS (mips_opts.isa));
+    }
 
-  show (stream, "32", &column, &first);
-  show (stream, "o64", &column, &first);
-  show (stream, "n32", &column, &first);
-  show (stream, "64", &column, &first);
-  show (stream, "eabi", &column, &first);
+  /* ??? GAS treats single-float processors as though they had 64-bit
+     float registers (although it complains when double-precision
+     instructions are used).  As things stand, saying they have 32-bit
+     registers would lead to spurious "register must be even" messages.
+     So here we assume float registers are always the same size as
+     integer ones, unless the user says otherwise.  */
+  if (file_mips_fp32 < 0)
+    file_mips_fp32 = file_mips_gp32;
 
-  fputc ('\n', stream);
+  /* End of GCC-shared inference code.  */
 
-  fprintf (stream, _("\
--32                    create o32 ABI object file (default)\n\
--n32                   create n32 ABI object file\n\
--64                    create 64 ABI object file\n"));
-#endif
+  /* ??? When do we want this flag to be set?   Who uses it?  */
+  if (file_mips_gp32 == 1
+      && mips_abi == NO_ABI
+      && ISA_HAS_64BIT_REGS (mips_opts.isa))
+    mips_32bitmode = 1;
+
+  if (mips_opts.isa == ISA_MIPS1 && mips_trap)
+    as_bad (_("trap exception not supported at ISA 1"));
+
+  /* If the selected architecture includes support for ASEs, enable
+     generation of code for them.  */
+  if (mips_opts.mips16 == -1)
+    mips_opts.mips16 = (CPU_HAS_MIPS16 (mips_arch)) ? 1 : 0;
+  if (mips_opts.ase_mips3d == -1)
+    mips_opts.ase_mips3d = (CPU_HAS_MIPS3D (mips_arch)) ? 1 : 0;
+  if (mips_opts.ase_mdmx == -1)
+    mips_opts.ase_mdmx = (CPU_HAS_MDMX (mips_arch)) ? 1 : 0;
+
+  file_mips_isa = mips_opts.isa;
+  file_ase_mips16 = mips_opts.mips16;
+  file_ase_mips3d = mips_opts.ase_mips3d;
+  file_ase_mdmx = mips_opts.ase_mdmx;
+  mips_opts.gp32 = file_mips_gp32;
+  mips_opts.fp32 = file_mips_fp32;
+
+  if (HAVE_NEWABI)
+    mips_big_got = 1;
+
+  if (mips_flag_mdebug < 0)
+    {
+#ifdef OBJ_MAYBE_ECOFF
+      if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour)
+       mips_flag_mdebug = 1;
+      else
+#endif /* OBJ_MAYBE_ECOFF */
+       mips_flag_mdebug = 0;
+    }
 }
 \f
 void
@@ -10813,7 +10610,7 @@ mips_need_elf_addend_fixup (fixP)
     return 1;
   if (mips_pic != EMBEDDED_PIC
       && (S_IS_WEAK (fixP->fx_addsy)
-         || S_IS_EXTERN (fixP->fx_addsy))
+         || S_IS_EXTERNAL (fixP->fx_addsy))
       && !S_IS_COMMON (fixP->fx_addsy))
     return 1;
   if (symbol_used_in_reloc_p (fixP->fx_addsy)
@@ -10870,10 +10667,13 @@ md_apply_fix3 (fixP, valP, seg)
     {
       if (mips_need_elf_addend_fixup (fixP))
        {
+         reloc_howto_type *howto;
          valueT symval = S_GET_VALUE (fixP->fx_addsy);
 
          value -= symval;
-         if (value != 0 && ! fixP->fx_pcrel)
+
+         howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
+         if (value != 0 && howto->partial_inplace && ! fixP->fx_pcrel)
            {
              /* In this case, the bfd_install_relocation routine will
                 incorrectly add the symbol value back in.  We just want
@@ -10891,12 +10691,8 @@ md_apply_fix3 (fixP, valP, seg)
                     leave the matching HI16 in-place addends as zero.  */
                  if (fixP->fx_r_type != BFD_RELOC_HI16_S)
                    {
-                     reloc_howto_type *howto;
                      bfd_vma contents, mask, field;
 
-                     howto = bfd_reloc_type_lookup (stdoutput,
-                                                    fixP->fx_r_type);
-
                      contents = bfd_get_bits (fixP->fx_frag->fr_literal
                                               + fixP->fx_where,
                                               fixP->fx_size * 8,
@@ -11659,10 +11455,6 @@ s_mipsset (x)
     {
       mips_opts.nobopt = 1;
     }
-  else if (strcmp (name, "mdmx") == 0)
-    mips_opts.ase_mdmx = 1;
-  else if (strcmp (name, "nomdmx") == 0)
-    mips_opts.ase_mdmx = 0;
   else if (strcmp (name, "mips16") == 0
           || strcmp (name, "MIPS-16") == 0)
     mips_opts.mips16 = 1;
@@ -11673,6 +11465,10 @@ s_mipsset (x)
     mips_opts.ase_mips3d = 1;
   else if (strcmp (name, "nomips3d") == 0)
     mips_opts.ase_mips3d = 0;
+  else if (strcmp (name, "mdmx") == 0)
+    mips_opts.ase_mdmx = 1;
+  else if (strcmp (name, "nomdmx") == 0)
+    mips_opts.ase_mdmx = 0;
   else if (strncmp (name, "mips", 4) == 0)
     {
       int isa;
@@ -11685,7 +11481,6 @@ s_mipsset (x)
        case  0:
          mips_opts.gp32 = file_mips_gp32;
          mips_opts.fp32 = file_mips_fp32;
-         mips_opts.abi = file_mips_abi;
          break;
        case  1:
        case  2:
@@ -11697,9 +11492,6 @@ s_mipsset (x)
        case  4:
        case  5:
        case 64:
-         /* Loosen ABI register width restriction.  */
-         if (mips_opts.abi == O32_ABI)
-           mips_opts.abi = NO_ABI;
          mips_opts.gp32 = 0;
          mips_opts.fp32 = 0;
          break;
@@ -11841,15 +11633,15 @@ s_cpload (ignore)
    If offset is given, this results in:
      sd                $gp, offset($sp)
      lui       $gp, %hi(%neg(%gp_rel(label)))
-     daddiu    $gp, $gp, %lo(%neg(%gp_rel(label)))
-     addu      $gp, $gp, $reg1
+     addiu     $gp, $gp, %lo(%neg(%gp_rel(label)))
+     daddu     $gp, $gp, $reg1
 
    If $reg2 is given, this results in:
      daddu     $reg2, $gp, $0
      lui       $gp, %hi(%neg(%gp_rel(label)))
-     daddiu    $gp, $gp, %lo(%neg(%gp_rel(label)))
-     addu      $gp, $gp, $reg1
- */
+     addiu     $gp, $gp, %lo(%neg(%gp_rel(label)))
+     daddu     $gp, $gp, $reg1
  $reg1 is normally $25 == $t9.  */
 static void
 s_cpsetup (ignore)
      int ignore ATTRIBUTE_UNUSED;
@@ -11858,7 +11650,7 @@ s_cpsetup (ignore)
   expressionS ex_sym;
   int reg1;
   int icnt = 0;
-  char *sym;
+  char *f;
 
   /* If we are not generating SVR4 PIC code, .cpsetup is ignored.
      We also need NewABI support.  */
@@ -11876,12 +11668,18 @@ s_cpsetup (ignore)
       return;
     }
   else
-    input_line_pointer++;
+    ++input_line_pointer;
   SKIP_WHITESPACE ();
   if (*input_line_pointer == '$')
-    mips_cpreturn_register = tc_get_register (0);
+    {
+      mips_cpreturn_register = tc_get_register (0);
+      mips_cpreturn_offset = -1;
+    }
   else
-    mips_cpreturn_offset = get_absolute_expression ();
+    {
+      mips_cpreturn_offset = get_absolute_expression ();
+      mips_cpreturn_register = -1;
+    }
   SKIP_WHITESPACE ();
   if (*input_line_pointer != ',')
     {
@@ -11891,15 +11689,7 @@ s_cpsetup (ignore)
   else
     ++input_line_pointer;
   SKIP_WHITESPACE ();
-  sym = input_line_pointer;
-  while (ISALNUM (*input_line_pointer))
-    ++input_line_pointer;
-  *input_line_pointer = 0;
-
-  ex_sym.X_op = O_symbol;
-  ex_sym.X_add_symbol = symbol_find_or_make (sym);
-  ex_sym.X_op_symbol = NULL;
-  ex_sym.X_add_number = 0;
+  expression (&ex_sym);
 
   if (mips_cpreturn_register == -1)
     {
@@ -11915,14 +11705,25 @@ s_cpsetup (ignore)
     macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "daddu",
                 "d,v,t", mips_cpreturn_register, mips_gp_register, 0);
 
+  /* Ensure there's room for the next two instructions, so that `f'
+     doesn't end up with an address in the wrong frag.  */
+  frag_grow (8);
+  f = frag_more (0);
   macro_build ((char *) NULL, &icnt, &ex_sym, "lui", "t,u", mips_gp_register,
               (int) BFD_RELOC_GPREL16);
-  fix_new (frag_now, prev_insn_where, 0, NULL, 0, 0, BFD_RELOC_MIPS_SUB);
-  fix_new (frag_now, prev_insn_where, 0, NULL, 0, 0, BFD_RELOC_HI16_S);
+  fix_new (frag_now, f - frag_now->fr_literal,
+          0, NULL, 0, 0, BFD_RELOC_MIPS_SUB);
+  fix_new (frag_now, f - frag_now->fr_literal,
+          0, NULL, 0, 0, BFD_RELOC_HI16_S);
+
+  f = frag_more (0);
   macro_build ((char *) NULL, &icnt, &ex_sym, "addiu", "t,r,j",
               mips_gp_register, mips_gp_register, (int) BFD_RELOC_GPREL16);
-  fix_new (frag_now, prev_insn_where, 0, NULL, 0, 0, BFD_RELOC_MIPS_SUB);
-  fix_new (frag_now, prev_insn_where, 0, NULL, 0, 0, BFD_RELOC_LO16);
+  fix_new (frag_now, f - frag_now->fr_literal,
+          0, NULL, 0, 0, BFD_RELOC_MIPS_SUB);
+  fix_new (frag_now, f - frag_now->fr_literal,
+          0, NULL, 0, 0, BFD_RELOC_LO16);
+
   macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
               HAVE_64BIT_ADDRESSES ? "daddu" : "addu", "d,v,t",
               mips_gp_register, mips_gp_register, reg1);
@@ -11943,6 +11744,7 @@ s_cplocal (ignore)
     }
 
   mips_gp_register = tc_get_register (0);
+  demand_empty_rest_of_line ();
 }
 
 /* Handle the .cprestore pseudo-op.  This stores $gp into a given
@@ -12201,7 +12003,7 @@ tc_get_register (frame)
   if (*input_line_pointer++ != '$')
     {
       as_warn (_("expected `$'"));
-      reg = 0;
+      reg = ZERO;
     }
   else if (ISDIGIT (*input_line_pointer))
     {
@@ -12209,27 +12011,58 @@ tc_get_register (frame)
       if (reg < 0 || reg >= 32)
        {
          as_warn (_("Bad register number"));
-         reg = 0;
+         reg = ZERO;
        }
     }
   else
     {
       if (strncmp (input_line_pointer, "ra", 2) == 0)
-       reg = RA;
+       {
+         reg = RA;
+         input_line_pointer += 2;
+       }
       else if (strncmp (input_line_pointer, "fp", 2) == 0)
-       reg = FP;
+       {
+         reg = FP;
+         input_line_pointer += 2;
+       }
       else if (strncmp (input_line_pointer, "sp", 2) == 0)
-       reg = SP;
+       {
+         reg = SP;
+         input_line_pointer += 2;
+       }
       else if (strncmp (input_line_pointer, "gp", 2) == 0)
-       reg = GP;
+       {
+         reg = GP;
+         input_line_pointer += 2;
+       }
       else if (strncmp (input_line_pointer, "at", 2) == 0)
-       reg = AT;
+       {
+         reg = AT;
+         input_line_pointer += 2;
+       }
+      else if (strncmp (input_line_pointer, "kt0", 3) == 0)
+       {
+         reg = KT0;
+         input_line_pointer += 3;
+       }
+      else if (strncmp (input_line_pointer, "kt1", 3) == 0)
+       {
+         reg = KT1;
+         input_line_pointer += 3;
+       }
+      else if (strncmp (input_line_pointer, "zero", 4) == 0)
+       {
+         reg = ZERO;
+         input_line_pointer += 4;
+       }
       else
        {
          as_warn (_("Unrecognized register name"));
-         reg = 0;
+         reg = ZERO;
+         while (ISALNUM(*input_line_pointer))
+          input_line_pointer++;
        }
-      input_line_pointer += 2;
     }
   if (frame)
     {
@@ -12602,7 +12435,8 @@ md_estimate_size_before_relax (fragp, segtype)
                /* A global or weak symbol is treated as external.  */
                && (OUTPUT_FLAVOR != bfd_target_elf_flavour
                    || (! S_IS_WEAK (sym)
-                       && (! S_IS_EXTERN (sym) || mips_pic == EMBEDDED_PIC)))
+                       && (! S_IS_EXTERNAL (sym)
+                           || mips_pic == EMBEDDED_PIC)))
 #endif
                );
     }
@@ -12644,7 +12478,7 @@ mips_fix_adjustable (fixp)
   /* Prevent all adjustments to global symbols.  */
   if (OUTPUT_FLAVOR == bfd_target_elf_flavour
       && mips_pic != EMBEDDED_PIC
-      && (S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy)))
+      && (S_IS_EXTERNAL (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy)))
     return 0;
 #endif
   if (fixp->fx_r_type == BFD_RELOC_MIPS16_JMP)
@@ -12873,7 +12707,7 @@ tc_gen_reloc (section, fixp)
      stop md_apply_fix3 from subtracting twice in the first place since
      the fake addend is required for variant frags above.  */
   if (fixp->fx_addsy != NULL && OUTPUT_FLAVOR == bfd_target_elf_flavour
-      && code == BFD_RELOC_GPREL16
+      && (code == BFD_RELOC_GPREL16 || code == BFD_RELOC_MIPS16_GPREL)
       && reloc->addend != 0
       && mips_need_elf_addend_fixup (fixp))
     reloc->addend += S_GET_VALUE (fixp->fx_addsy);
@@ -13110,7 +12944,7 @@ void
 mips_elf_final_processing ()
 {
   /* Write out the register information.  */
-  if (file_mips_abi != N64_ABI)
+  if (mips_abi != N64_ABI)
     {
       Elf32_RegInfo s;
 
@@ -13150,6 +12984,8 @@ mips_elf_final_processing ()
     elf_elfheader (stdoutput)->e_flags |= EF_MIPS_PIC;
 
   /* Set MIPS ELF flags for ASEs.  */
+  if (file_ase_mips16)
+    elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ARCH_ASE_M16;
 #if 0 /* XXX FIXME */
   if (file_ase_mips3d)
     elf_elfheader (stdoutput)->e_flags |= ???;
@@ -13158,20 +12994,18 @@ mips_elf_final_processing ()
     elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ARCH_ASE_MDMX;
 
   /* Set the MIPS ELF ABI flags.  */
-  if (file_mips_abi == NO_ABI)
-    ;
-  else if (file_mips_abi == O32_ABI)
+  if (mips_abi == O32_ABI && USE_E_MIPS_ABI_O32)
     elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_O32;
-  else if (file_mips_abi == O64_ABI)
+  else if (mips_abi == O64_ABI)
     elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_O64;
-  else if (file_mips_abi == EABI_ABI)
+  else if (mips_abi == EABI_ABI)
     {
-      if (mips_eabi64)
+      if (!file_mips_gp32)
        elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_EABI64;
       else
        elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_EABI32;
     }
-  else if (file_mips_abi == N32_ABI)
+  else if (mips_abi == N32_ABI)
     elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ABI2;
 
   /* Nothing to do for N64_ABI.  */
@@ -13295,14 +13129,47 @@ get_number ()
 }
 
 /* The .file directive; just like the usual .file directive, but there
-   is an initial number which is the ECOFF file index.  */
+   is an initial number which is the ECOFF file index.  In the non-ECOFF
+   case .file implies DWARF-2.  */
+
+static void
+s_mips_file (x)
+     int x ATTRIBUTE_UNUSED;
+{
+  static int first_file_directive = 0;
+
+  if (ECOFF_DEBUGGING)
+    {
+      get_number ();
+      s_app_file (0);
+    }
+  else
+    {
+      char *filename;
+
+      filename = dwarf2_directive_file (0);
+
+      /* Versions of GCC up to 3.1 start files with a ".file"
+        directive even for stabs output.  Make sure that this
+        ".file" is handled.  Note that you need a version of GCC
+         after 3.1 in order to support DWARF-2 on MIPS.  */
+      if (filename != NULL && ! first_file_directive)
+       {
+         (void) new_logical_line (filename, -1);
+         s_app_file_string (filename);
+       }
+      first_file_directive = 1;
+    }
+}
+
+/* The .loc directive, implying DWARF-2.  */
 
 static void
-s_file (x)
+s_mips_loc (x)
      int x ATTRIBUTE_UNUSED;
 {
-  get_number ();
-  s_app_file (0);
+  if (!ECOFF_DEBUGGING)
+    dwarf2_directive_loc (0);
 }
 
 /* The .end directive.  */
@@ -13353,46 +13220,52 @@ s_mips_end (x)
       assert (S_GET_NAME (p));
       if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym)))
        as_warn (_(".end symbol does not match .ent symbol."));
+
+      if (debug_type == DEBUG_STABS)
+       stabs_generate_asm_endfunc (S_GET_NAME (p),
+                                   S_GET_NAME (p));
     }
   else
     as_warn (_(".end directive missing or unknown symbol"));
 
-#ifdef MIPS_STABS_ELF
-  {
-    segT saved_seg = now_seg;
-    subsegT saved_subseg = now_subseg;
-    valueT dot;
-    expressionS exp;
-    char *fragp;
+#ifdef OBJ_ELF
+  /* Generate a .pdr section.  */
+  if (OUTPUT_FLAVOR == bfd_target_elf_flavour && ! ECOFF_DEBUGGING)
+    {
+      segT saved_seg = now_seg;
+      subsegT saved_subseg = now_subseg;
+      valueT dot;
+      expressionS exp;
+      char *fragp;
 
-    dot = frag_now_fix ();
+      dot = frag_now_fix ();
 
 #ifdef md_flush_pending_output
-    md_flush_pending_output ();
+      md_flush_pending_output ();
 #endif
 
-    assert (pdr_seg);
-    subseg_set (pdr_seg, 0);
+      assert (pdr_seg);
+      subseg_set (pdr_seg, 0);
 
-    /* Write the symbol.  */
-    exp.X_op = O_symbol;
-    exp.X_add_symbol = p;
-    exp.X_add_number = 0;
-    emit_expr (&exp, 4);
+      /* Write the symbol.  */
+      exp.X_op = O_symbol;
+      exp.X_add_symbol = p;
+      exp.X_add_number = 0;
+      emit_expr (&exp, 4);
 
-    fragp = frag_more (7 * 4);
+      fragp = frag_more (7 * 4);
 
-    md_number_to_chars (fragp,      (valueT) cur_proc_ptr->reg_mask, 4);
-    md_number_to_chars (fragp +  4, (valueT) cur_proc_ptr->reg_offset, 4);
-    md_number_to_chars (fragp +  8, (valueT) cur_proc_ptr->fpreg_mask, 4);
-    md_number_to_chars (fragp + 12, (valueT) cur_proc_ptr->fpreg_offset, 4);
-    md_number_to_chars (fragp + 16, (valueT) cur_proc_ptr->frame_offset, 4);
-    md_number_to_chars (fragp + 20, (valueT) cur_proc_ptr->frame_reg, 4);
-    md_number_to_chars (fragp + 24, (valueT) cur_proc_ptr->pc_reg, 4);
+      md_number_to_chars (fragp,      (valueT) cur_proc_ptr->reg_mask, 4);
+      md_number_to_chars (fragp +  4, (valueT) cur_proc_ptr->reg_offset, 4);
+      md_number_to_chars (fragp +  8, (valueT) cur_proc_ptr->fpreg_mask, 4);
+      md_number_to_chars (fragp + 12, (valueT) cur_proc_ptr->fpreg_offset, 4);
+      md_number_to_chars (fragp + 16, (valueT) cur_proc_ptr->frame_offset, 4);
+      md_number_to_chars (fragp + 20, (valueT) cur_proc_ptr->frame_reg, 4);
+      md_number_to_chars (fragp + 24, (valueT) cur_proc_ptr->pc_reg, 4);
 
-    subseg_set (saved_seg, saved_subseg);
-  }
-#endif /* MIPS_STABS_ELF */
+      subseg_set (saved_seg, saved_subseg);
+    }
+#endif /* OBJ_ELF */
 
   cur_proc_ptr = NULL;
 }
@@ -13446,6 +13319,10 @@ s_mips_ent (aent)
       symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
 
       ++numprocs;
+
+      if (debug_type == DEBUG_STABS)
+        stabs_generate_asm_func (S_GET_NAME (symbolP),
+                                S_GET_NAME (symbolP));
     }
 
   demand_empty_rest_of_line ();
@@ -13461,36 +13338,38 @@ static void
 s_mips_frame (ignore)
      int ignore ATTRIBUTE_UNUSED;
 {
-#ifdef MIPS_STABS_ELF
+#ifdef OBJ_ELF
+  if (OUTPUT_FLAVOR == bfd_target_elf_flavour && ! ECOFF_DEBUGGING)
+    {
+      long val;
 
-  long val;
+      if (cur_proc_ptr == (procS *) NULL)
+       {
+         as_warn (_(".frame outside of .ent"));
+         demand_empty_rest_of_line ();
+         return;
+       }
 
-  if (cur_proc_ptr == (procS *) NULL)
-    {
-      as_warn (_(".frame outside of .ent"));
-      demand_empty_rest_of_line ();
-      return;
-    }
+      cur_proc_ptr->frame_reg = tc_get_register (1);
 
-  cur_proc_ptr->frame_reg = tc_get_register (1);
+      SKIP_WHITESPACE ();
+      if (*input_line_pointer++ != ','
+         || get_absolute_expression_and_terminator (&val) != ',')
+       {
+         as_warn (_("Bad .frame directive"));
+         --input_line_pointer;
+         demand_empty_rest_of_line ();
+         return;
+       }
+
+      cur_proc_ptr->frame_offset = val;
+      cur_proc_ptr->pc_reg = tc_get_register (0);
 
-  SKIP_WHITESPACE ();
-  if (*input_line_pointer++ != ','
-      || get_absolute_expression_and_terminator (&val) != ',')
-    {
-      as_warn (_("Bad .frame directive"));
-      --input_line_pointer;
       demand_empty_rest_of_line ();
-      return;
     }
-
-  cur_proc_ptr->frame_offset = val;
-  cur_proc_ptr->pc_reg = tc_get_register (0);
-
-  demand_empty_rest_of_line ();
-#else
-  s_ignore (ignore);
-#endif /* MIPS_STABS_ELF */
+  else
+#endif /* OBJ_ELF */
+    s_ignore (ignore);
 }
 
 /* The .fmask and .mask directives. If the mdebug section is present
@@ -13503,41 +13382,44 @@ static void
 s_mips_mask (reg_type)
      char reg_type;
 {
-#ifdef MIPS_STABS_ELF
-  long mask, off;
-
-  if (cur_proc_ptr == (procS *) NULL)
+#ifdef OBJ_ELF
+  if (OUTPUT_FLAVOR == bfd_target_elf_flavour && ! ECOFF_DEBUGGING)
     {
-      as_warn (_(".mask/.fmask outside of .ent"));
-      demand_empty_rest_of_line ();
-      return;
-    }
+      long mask, off;
 
-  if (get_absolute_expression_and_terminator (&mask) != ',')
-    {
-      as_warn (_("Bad .mask/.fmask directive"));
-      --input_line_pointer;
-      demand_empty_rest_of_line ();
-      return;
-    }
+      if (cur_proc_ptr == (procS *) NULL)
+       {
+         as_warn (_(".mask/.fmask outside of .ent"));
+         demand_empty_rest_of_line ();
+         return;
+       }
 
-  off = get_absolute_expression ();
+      if (get_absolute_expression_and_terminator (&mask) != ',')
+       {
+         as_warn (_("Bad .mask/.fmask directive"));
+         --input_line_pointer;
+         demand_empty_rest_of_line ();
+         return;
+       }
 
-  if (reg_type == 'F')
-    {
-      cur_proc_ptr->fpreg_mask = mask;
-      cur_proc_ptr->fpreg_offset = off;
+      off = get_absolute_expression ();
+
+      if (reg_type == 'F')
+       {
+         cur_proc_ptr->fpreg_mask = mask;
+         cur_proc_ptr->fpreg_offset = off;
+       }
+      else
+       {
+         cur_proc_ptr->reg_mask = mask;
+         cur_proc_ptr->reg_offset = off;
+       }
+
+      demand_empty_rest_of_line ();
     }
   else
-    {
-      cur_proc_ptr->reg_mask = mask;
-      cur_proc_ptr->reg_offset = off;
-    }
-
-  demand_empty_rest_of_line ();
-#else
-  s_ignore (reg_type);
-#endif /* MIPS_STABS_ELF */
+#endif /* OBJ_ELF */
+    s_ignore (reg_type);
 }
 
 /* The .loc directive.  */
@@ -13564,176 +13446,175 @@ s_loc (x)
 }
 #endif
 
-/* CPU name/ISA/number mapping table.
+/* A table describing all the processors gas knows about.  Names are
+   matched in the order listed.
 
-   Entries are grouped by type.  The first matching CPU or ISA entry
-   gets chosen by CPU or ISA, so it should be the 'canonical' name
-   for that type.  Entries after that within the type are sorted
-   alphabetically.
-
-   Case is ignored in comparison, so put the canonical entry in the
-   appropriate case but everything else in lower case to ease eye pain.  */
+   To ease comparison, please keep this table in the same order as
+   gcc's mips_cpu_info_table[].  */
 static const struct mips_cpu_info mips_cpu_info_table[] =
 {
-  /* MIPS1 ISA */
-  { "MIPS1",          1,      ISA_MIPS1,      CPU_R3000, },
-  { "mips",           1,      ISA_MIPS1,      CPU_R3000, },
+  /* Entries for generic ISAs */
+  { "mips1",          1,      ISA_MIPS1,      CPU_R3000 },
+  { "mips2",          1,      ISA_MIPS2,      CPU_R6000 },
+  { "mips3",          1,      ISA_MIPS3,      CPU_R4000 },
+  { "mips4",          1,      ISA_MIPS4,      CPU_R8000 },
+  { "mips5",          1,      ISA_MIPS5,      CPU_MIPS5 },
+  { "mips32",         1,      ISA_MIPS32,     CPU_MIPS32 },
+  { "mips64",         1,      ISA_MIPS64,     CPU_MIPS64 },
+
+  /* MIPS I */
+  { "r3000",          0,      ISA_MIPS1,      CPU_R3000 },
+  { "r2000",          0,      ISA_MIPS1,      CPU_R3000 },
+  { "r3900",          0,      ISA_MIPS1,      CPU_R3900 },
+
+  /* MIPS II */
+  { "r6000",          0,      ISA_MIPS2,      CPU_R6000 },
+
+  /* MIPS III */
+  { "r4000",          0,      ISA_MIPS3,      CPU_R4000 },
+  { "r4010",          0,      ISA_MIPS2,      CPU_R4010 },
+  { "vr4100",         0,      ISA_MIPS3,      CPU_VR4100 },
+  { "vr4111",         0,      ISA_MIPS3,      CPU_R4111 },
+  { "vr4300",         0,      ISA_MIPS3,      CPU_R4300 },
+  { "r4400",          0,      ISA_MIPS3,      CPU_R4400 },
+  { "r4600",          0,      ISA_MIPS3,      CPU_R4600 },
+  { "orion",          0,      ISA_MIPS3,      CPU_R4600 },
+  { "r4650",          0,      ISA_MIPS3,      CPU_R4650 },
+
+  /* MIPS IV */
+  { "r8000",          0,      ISA_MIPS4,      CPU_R8000 },
+  { "r10000",         0,      ISA_MIPS4,      CPU_R10000 },
+  { "r12000",         0,      ISA_MIPS4,      CPU_R12000 },
+  { "vr5000",         0,      ISA_MIPS4,      CPU_R5000 },
+  { "rm5200",         0,      ISA_MIPS4,      CPU_R5000 },
+  { "rm5230",         0,      ISA_MIPS4,      CPU_R5000 },
+  { "rm5231",         0,      ISA_MIPS4,      CPU_R5000 },
+  { "rm5261",         0,      ISA_MIPS4,      CPU_R5000 },
+  { "rm5721",         0,      ISA_MIPS4,      CPU_R5000 },
+  { "r7000",          0,      ISA_MIPS4,      CPU_R5000 },
+
+  /* MIPS 32 */
+  { "4kc",            0,      ISA_MIPS32,     CPU_MIPS32, },
+  { "4km",            0,      ISA_MIPS32,     CPU_MIPS32 },
+  { "4kp",            0,      ISA_MIPS32,     CPU_MIPS32 },
 
-  /* MIPS2 ISA */
-  { "MIPS2",          1,      ISA_MIPS2,      CPU_R6000, },
+  /* MIPS 64 */
+  { "5kc",            0,      ISA_MIPS64,     CPU_MIPS64 },
+  { "20kc",           0,      ISA_MIPS64,     CPU_MIPS64 },
 
-  /* MIPS3 ISA */
-  { "MIPS3",          1,      ISA_MIPS3,      CPU_R4000, },
+  /* Broadcom SB-1 CPU core */
+  { "sb1",            0,      ISA_MIPS64,     CPU_SB1 },
 
-  /* MIPS4 ISA */
-  { "MIPS4",          1,      ISA_MIPS4,      CPU_R8000, },
+  /* End marker */
+  { NULL, 0, 0, 0 }
+};
 
-  /* MIPS5 ISA */
-  { "MIPS5",          1,      ISA_MIPS5,      CPU_MIPS5, },
-  { "Generic-MIPS5",  0,      ISA_MIPS5,      CPU_MIPS5, },
 
-  /* MIPS32 ISA */
-  { "MIPS32",         1,      ISA_MIPS32,     CPU_MIPS32, },
-  { "mipsisa32",      0,      ISA_MIPS32,     CPU_MIPS32, },
-  { "Generic-MIPS32", 0,      ISA_MIPS32,     CPU_MIPS32, },
-  { "4kc",            0,      ISA_MIPS32,     CPU_MIPS32, },
-  { "4km",            0,      ISA_MIPS32,     CPU_MIPS32, },
-  { "4kp",            0,      ISA_MIPS32,     CPU_MIPS32, },
-
-  /* For historical reasons.  */
-  { "MIPS64",         1,      ISA_MIPS3,      CPU_R4000, },
-
-  /* MIPS64 ISA */
-  { "mipsisa64",      1,      ISA_MIPS64,     CPU_MIPS64, },
-  { "Generic-MIPS64", 0,      ISA_MIPS64,     CPU_MIPS64, },
-  { "5kc",            0,      ISA_MIPS64,     CPU_MIPS64, },
-  { "20kc",           0,      ISA_MIPS64,     CPU_MIPS64, },
-
-  /* R2000 CPU */
-  { "R2000",          0,      ISA_MIPS1,      CPU_R2000, },
-  { "2000",           0,      ISA_MIPS1,      CPU_R2000, },
-  { "2k",             0,      ISA_MIPS1,      CPU_R2000, },
-  { "r2k",            0,      ISA_MIPS1,      CPU_R2000, },
-
-  /* R3000 CPU */
-  { "R3000",          0,      ISA_MIPS1,      CPU_R3000, },
-  { "3000",           0,      ISA_MIPS1,      CPU_R3000, },
-  { "3k",             0,      ISA_MIPS1,      CPU_R3000, },
-  { "r3k",            0,      ISA_MIPS1,      CPU_R3000, },
-
-  /* TX3900 CPU */
-  { "R3900",          0,      ISA_MIPS1,      CPU_R3900, },
-  { "3900",           0,      ISA_MIPS1,      CPU_R3900, },
-  { "mipstx39",       0,      ISA_MIPS1,      CPU_R3900, },
-
-  /* R4000 CPU */
-  { "R4000",          0,      ISA_MIPS3,      CPU_R4000, },
-  { "4000",           0,      ISA_MIPS3,      CPU_R4000, },
-  { "4k",             0,      ISA_MIPS3,      CPU_R4000, },   /* beware */
-  { "r4k",            0,      ISA_MIPS3,      CPU_R4000, },
-
-  /* R4010 CPU */
-  { "R4010",          0,      ISA_MIPS2,      CPU_R4010, },
-  { "4010",           0,      ISA_MIPS2,      CPU_R4010, },
-
-  /* R4400 CPU */
-  { "R4400",          0,      ISA_MIPS3,      CPU_R4400, },
-  { "4400",           0,      ISA_MIPS3,      CPU_R4400, },
-
-  /* R4600 CPU */
-  { "R4600",          0,      ISA_MIPS3,      CPU_R4600, },
-  { "4600",           0,      ISA_MIPS3,      CPU_R4600, },
-  { "mips64orion",    0,      ISA_MIPS3,      CPU_R4600, },
-  { "orion",          0,      ISA_MIPS3,      CPU_R4600, },
-
-  /* R4650 CPU */
-  { "R4650",          0,      ISA_MIPS3,      CPU_R4650, },
-  { "4650",           0,      ISA_MIPS3,      CPU_R4650, },
-
-  /* R6000 CPU */
-  { "R6000",          0,      ISA_MIPS2,      CPU_R6000, },
-  { "6000",           0,      ISA_MIPS2,      CPU_R6000, },
-  { "6k",             0,      ISA_MIPS2,      CPU_R6000, },
-  { "r6k",            0,      ISA_MIPS2,      CPU_R6000, },
-
-  /* R8000 CPU */
-  { "R8000",          0,      ISA_MIPS4,      CPU_R8000, },
-  { "8000",           0,      ISA_MIPS4,      CPU_R8000, },
-  { "8k",             0,      ISA_MIPS4,      CPU_R8000, },
-  { "r8k",            0,      ISA_MIPS4,      CPU_R8000, },
-
-  /* R10000 CPU */
-  { "R10000",         0,      ISA_MIPS4,      CPU_R10000, },
-  { "10000",          0,      ISA_MIPS4,      CPU_R10000, },
-  { "10k",            0,      ISA_MIPS4,      CPU_R10000, },
-  { "r10k",           0,      ISA_MIPS4,      CPU_R10000, },
-
-  /* R12000 CPU */
-  { "R12000",         0,      ISA_MIPS4,      CPU_R12000, },
-  { "12000",          0,      ISA_MIPS4,      CPU_R12000, },
-  { "12k",            0,      ISA_MIPS4,      CPU_R12000, },
-  { "r12k",           0,      ISA_MIPS4,      CPU_R12000, },
-
-  /* VR4100 CPU */
-  { "VR4100",         0,      ISA_MIPS3,      CPU_VR4100, },
-  { "4100",           0,      ISA_MIPS3,      CPU_VR4100, },
-  { "mips64vr4100",   0,      ISA_MIPS3,      CPU_VR4100, },
-  { "r4100",          0,      ISA_MIPS3,      CPU_VR4100, },
-
-  /* VR4111 CPU */
-  { "VR4111",         0,      ISA_MIPS3,      CPU_R4111, },
-  { "4111",           0,      ISA_MIPS3,      CPU_R4111, },
-  { "mips64vr4111",   0,      ISA_MIPS3,      CPU_R4111, },
-  { "r4111",          0,      ISA_MIPS3,      CPU_R4111, },
-
-  /* VR4300 CPU */
-  { "VR4300",         0,      ISA_MIPS3,      CPU_R4300, },
-  { "4300",           0,      ISA_MIPS3,      CPU_R4300, },
-  { "mips64vr4300",   0,      ISA_MIPS3,      CPU_R4300, },
-  { "r4300",          0,      ISA_MIPS3,      CPU_R4300, },
-
-  /* VR5000 CPU */
-  { "VR5000",         0,      ISA_MIPS4,      CPU_R5000, },
-  { "5000",           0,      ISA_MIPS4,      CPU_R5000, },
-  { "5k",             0,      ISA_MIPS4,      CPU_R5000, },
-  { "mips64vr5000",   0,      ISA_MIPS4,      CPU_R5000, },
-  { "r5000",          0,      ISA_MIPS4,      CPU_R5000, },
-  { "r5200",          0,      ISA_MIPS4,      CPU_R5000, },
-  { "rm5200",         0,      ISA_MIPS4,      CPU_R5000, },
-  { "r5230",          0,      ISA_MIPS4,      CPU_R5000, },
-  { "rm5230",         0,      ISA_MIPS4,      CPU_R5000, },
-  { "r5231",          0,      ISA_MIPS4,      CPU_R5000, },
-  { "rm5231",         0,      ISA_MIPS4,      CPU_R5000, },
-  { "r5261",          0,      ISA_MIPS4,      CPU_R5000, },
-  { "rm5261",         0,      ISA_MIPS4,      CPU_R5000, },
-  { "r5721",          0,      ISA_MIPS4,      CPU_R5000, },
-  { "rm5721",         0,      ISA_MIPS4,      CPU_R5000, },
-  { "r5k",            0,      ISA_MIPS4,      CPU_R5000, },
-  { "r7000",          0,      ISA_MIPS4,      CPU_R5000, },
-
-  /* Broadcom SB-1 CPU */
-  { "SB-1",           0,      ISA_MIPS64,     CPU_SB1, },
-  { "sb-1250",        0,      ISA_MIPS64,     CPU_SB1, },
-  { "sb1",            0,      ISA_MIPS64,     CPU_SB1, },
-  { "sb1250",         0,      ISA_MIPS64,     CPU_SB1, },
-
-  /* End marker.  */
-  { NULL, 0, 0, 0, },
-};
+/* Return true if GIVEN is the same as CANONICAL, or if it is CANONICAL
+   with a final "000" replaced by "k".  Ignore case.
+
+   Note: this function is shared between GCC and GAS.  */
+
+static boolean
+mips_strict_matching_cpu_name_p (canonical, given)
+     const char *canonical, *given;
+{
+  while (*given != 0 && TOLOWER (*given) == TOLOWER (*canonical))
+    given++, canonical++;
+
+  return ((*given == 0 && *canonical == 0)
+         || (strcmp (canonical, "000") == 0 && strcasecmp (given, "k") == 0));
+}
+
+
+/* Return true if GIVEN matches CANONICAL, where GIVEN is a user-supplied
+   CPU name.  We've traditionally allowed a lot of variation here.
+
+   Note: this function is shared between GCC and GAS.  */
+
+static boolean
+mips_matching_cpu_name_p (canonical, given)
+     const char *canonical, *given;
+{
+  /* First see if the name matches exactly, or with a final "000"
+     turned into "k".  */
+  if (mips_strict_matching_cpu_name_p (canonical, given))
+    return true;
+
+  /* If not, try comparing based on numerical designation alone.
+     See if GIVEN is an unadorned number, or 'r' followed by a number.  */
+  if (TOLOWER (*given) == 'r')
+    given++;
+  if (!ISDIGIT (*given))
+    return false;
+
+  /* Skip over some well-known prefixes in the canonical name,
+     hoping to find a number there too.  */
+  if (TOLOWER (canonical[0]) == 'v' && TOLOWER (canonical[1]) == 'r')
+    canonical += 2;
+  else if (TOLOWER (canonical[0]) == 'r' && TOLOWER (canonical[1]) == 'm')
+    canonical += 2;
+  else if (TOLOWER (canonical[0]) == 'r')
+    canonical += 1;
+
+  return mips_strict_matching_cpu_name_p (canonical, given);
+}
+
+
+/* Parse an option that takes the name of a processor as its argument.
+   OPTION is the name of the option and CPU_STRING is the argument.
+   Return the corresponding processor enumeration if the CPU_STRING is
+   recognized, otherwise report an error and return null.
+
+   A similar function exists in GCC.  */
 
 static const struct mips_cpu_info *
-mips_cpu_info_from_name (name)
-     const char *name;
+mips_parse_cpu (option, cpu_string)
+     const char *option, *cpu_string;
 {
-  int i;
+  const struct mips_cpu_info *p;
 
-  for (i = 0; mips_cpu_info_table[i].name != NULL; i++)
-    if (strcasecmp (name, mips_cpu_info_table[i].name) == 0)
-      return (&mips_cpu_info_table[i]);
+  /* 'from-abi' selects the most compatible architecture for the given
+     ABI: MIPS I for 32-bit ABIs and MIPS III for 64-bit ABIs.  For the
+     EABIs, we have to decide whether we're using the 32-bit or 64-bit
+     version.  Look first at the -mgp options, if given, otherwise base
+     the choice on MIPS_DEFAULT_64BIT.
 
-  return NULL;
+     Treat NO_ABI like the EABIs.  One reason to do this is that the
+     plain 'mips' and 'mips64' configs have 'from-abi' as their default
+     architecture.  This code picks MIPS I for 'mips' and MIPS III for
+     'mips64', just as we did in the days before 'from-abi'.  */
+  if (strcasecmp (cpu_string, "from-abi") == 0)
+    {
+      if (ABI_NEEDS_32BIT_REGS (mips_abi))
+       return mips_cpu_info_from_isa (ISA_MIPS1);
+
+      if (ABI_NEEDS_64BIT_REGS (mips_abi))
+       return mips_cpu_info_from_isa (ISA_MIPS3);
+
+      if (file_mips_gp32 >= 0)
+       return mips_cpu_info_from_isa (file_mips_gp32 ? ISA_MIPS1 : ISA_MIPS3);
+
+      return mips_cpu_info_from_isa (MIPS_DEFAULT_64BIT
+                                    ? ISA_MIPS3
+                                    : ISA_MIPS1);
+    }
+
+  /* 'default' has traditionally been a no-op.  Probably not very useful.  */
+  if (strcasecmp (cpu_string, "default") == 0)
+    return 0;
+
+  for (p = mips_cpu_info_table; p->name != 0; p++)
+    if (mips_matching_cpu_name_p (p->name, cpu_string))
+      return p;
+
+  as_bad ("Bad value (%s) for %s", cpu_string, option);
+  return 0;
 }
 
+/* Return the canonical processor information for ISA (a member of the
+   ISA_MIPS* enumeration).  */
+
 static const struct mips_cpu_info *
 mips_cpu_info_from_isa (isa)
      int isa;
@@ -13742,22 +13623,119 @@ mips_cpu_info_from_isa (isa)
 
   for (i = 0; mips_cpu_info_table[i].name != NULL; i++)
     if (mips_cpu_info_table[i].is_isa
-      && isa == mips_cpu_info_table[i].isa)
+       && isa == mips_cpu_info_table[i].isa)
       return (&mips_cpu_info_table[i]);
 
   return NULL;
 }
+\f
+static void
+show (stream, string, col_p, first_p)
+     FILE *stream;
+     const char *string;
+     int *col_p;
+     int *first_p;
+{
+  if (*first_p)
+    {
+      fprintf (stream, "%24s", "");
+      *col_p = 24;
+    }
+  else
+    {
+      fprintf (stream, ", ");
+      *col_p += 2;
+    }
 
-static const struct mips_cpu_info *
-mips_cpu_info_from_cpu (cpu)
-     int cpu;
+  if (*col_p + strlen (string) > 72)
+    {
+      fprintf (stream, "\n%24s", "");
+      *col_p = 24;
+    }
+
+  fprintf (stream, "%s", string);
+  *col_p += strlen (string);
+
+  *first_p = 0;
+}
+
+void
+md_show_usage (stream)
+     FILE *stream;
 {
-  int i;
+  int column, first;
+  size_t i;
+
+  fprintf (stream, _("\
+MIPS options:\n\
+-membedded-pic         generate embedded position independent code\n\
+-EB                    generate big endian output\n\
+-EL                    generate little endian output\n\
+-g, -g2                        do not remove unneeded NOPs or swap branches\n\
+-G NUM                 allow referencing objects up to NUM bytes\n\
+                       implicitly with the gp register [default 8]\n"));
+  fprintf (stream, _("\
+-mips1                 generate MIPS ISA I instructions\n\
+-mips2                 generate MIPS ISA II instructions\n\
+-mips3                 generate MIPS ISA III instructions\n\
+-mips4                 generate MIPS ISA IV instructions\n\
+-mips5                  generate MIPS ISA V instructions\n\
+-mips32                 generate MIPS32 ISA instructions\n\
+-mips64                 generate MIPS64 ISA instructions\n\
+-march=CPU/-mtune=CPU  generate code/schedule for CPU, where CPU is one of:\n"));
+
+  first = 1;
 
   for (i = 0; mips_cpu_info_table[i].name != NULL; i++)
-    if (!mips_cpu_info_table[i].is_isa
-      && cpu == mips_cpu_info_table[i].cpu)
-      return (&mips_cpu_info_table[i]);
+    show (stream, mips_cpu_info_table[i].name, &column, &first);
+  show (stream, "from-abi", &column, &first);
+  fputc ('\n', stream);
 
-  return NULL;
+  fprintf (stream, _("\
+-mCPU                  equivalent to -march=CPU -mtune=CPU. Deprecated.\n\
+-no-mCPU               don't generate code specific to CPU.\n\
+                       For -mCPU and -no-mCPU, CPU must be one of:\n"));
+
+  first = 1;
+
+  show (stream, "3900", &column, &first);
+  show (stream, "4010", &column, &first);
+  show (stream, "4100", &column, &first);
+  show (stream, "4650", &column, &first);
+  fputc ('\n', stream);
+
+  fprintf (stream, _("\
+-mips16                        generate mips16 instructions\n\
+-no-mips16             do not generate mips16 instructions\n"));
+  fprintf (stream, _("\
+-mgp32                 use 32-bit GPRs, regardless of the chosen ISA\n\
+-mfp32                 use 32-bit FPRs, regardless of the chosen ISA\n\
+-O0                    remove unneeded NOPs, do not swap branches\n\
+-O                     remove unneeded NOPs and swap branches\n\
+-n                     warn about NOPs generated from macros\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
+  fprintf (stream, _("\
+-KPIC, -call_shared    generate SVR4 position independent code\n\
+-non_shared            do not generate position independent code\n\
+-xgot                  assume a 32 bit GOT\n\
+-mabi=ABI              create ABI conformant object file for:\n"));
+
+  first = 1;
+
+  show (stream, "32", &column, &first);
+  show (stream, "o64", &column, &first);
+  show (stream, "n32", &column, &first);
+  show (stream, "64", &column, &first);
+  show (stream, "eabi", &column, &first);
+
+  fputc ('\n', stream);
+
+  fprintf (stream, _("\
+-32                    create o32 ABI object file (default)\n\
+-n32                   create n32 ABI object file\n\
+-64                    create 64 ABI object file\n"));
+#endif
 }
This page took 0.062385 seconds and 4 git commands to generate.