This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFC & patch: Rework MIPS command-line handling


[cross-posted to binutils & gcc]

The patch below tries to make MIPS GCC and GAS more consistent in
the way they handle command-line options.  This message is really a
RFC on whether it's the right way to go, although the patch has
been tested in the usual way.

I'll use numbers to break things up...

(1) The main discrepancy I see with the current set-up is in the handling
    of -march.  In GAS, it fully controls the ISA, much like -mipsN does,
    but in GCC it only controls the use of processor-specific extensions.
    So, for example,

	mips-elf-as -march=r8000

    selects MIPS IV code but

	mips-elf-gcc -march=r8000

    selects MIPS I code.  I'd like to make it so that both cc1 and gas treat
    -march like a more descriptive version of -mipsN.  -march=r8000 would
    be equivalent to -mips4, -march=r4000 would be equivalent to -mips3,
    and so on.

(2) Traditionally, GCC has tried to infer sensible things from a sparse
    command line.  Passing -mipsN would select a suitable ABI for ISA N,
    passing -mabi=FOO would select a suitable ISA for ABI FOO, and so on.
    Lately, gas has done the same thing, although the assumptions are
    slightly different (more later).

    If -march is going to act like -mipsN, then it ought to choose the
    ABI as well.  For example, if "mips64-elf-gcc -mips1" chooses o32 code
    (as it does now) then "mips64-elf-gcc -march=r3000" should do the same.

(3) The GCC code to infer an ABI from an ISA looks like this:

	/* A specified ISA defaults the ABI if it was not specified.  */
	if (mips_abi_string == 0 && mips_isa_string
	    && mips_abi != ABI_EABI
	    && mips_abi != ABI_O64
	    && mips_abi != ABI_MEABI)
	  {
	    if (mips_isa == 64)
	      mips_abi = ABI_O64;
	    else
	      {
		if (! ISA_HAS_64BIT_REGS)
		  mips_abi = ABI_32;
		else
		  mips_abi = ABI_64;
	      }
	  }

    Some problems here:

    (a) The o64 exclusion seems strange.  Passing -mips1 or -mips2 to
	an o64-configured GCC will generate "32-bit o64" code (we get
	the 32-bit register size from CC1_SPEC).  It turns out to be
	almost the same as O32 code, except you get an .mdebug.abiO64
	section instead of an .mdebug.abi32 section.

    (b) Passing -mips3 to an n32 MIPS III config (e.g. mips-sgi-irix6)
	will select n64, which seems counter-intuitive.

    (c) The code takes no account of the -mgp32 option.  "-mips4 -mgp32"
	will set the ABI to n64 without complaint, but generate odd code.
	o32 would be a more sensible choice, especially in cases where
	o32 is the default anyway.

    (d) GAS 2.12 selects o64 (not n64) for -mips3 and -mips4.

    The proposed new rule is:

    (i) If the default ABI requires 32-bit registers [o32 only] then
	switch to o64 when generating 64-bit code.

    (ii) If the default ABI requires 64-bit registers [o64, n32 and 64]
	 then switch to o32 when generating 32-bit code.

    Here, "generating X-bit code" takes into account the ISA and
    -mgp32 option.

    For (i), o64 seems a better choice than n64.  Historical precedent
    might be one reason to keep n64, but GAS prior to 2.12 didn't support
    it and (like (d) says) gas 2.12 would assume you meant o64 instead
    of n64.  So I can't see the n64 choice would ever have worked
    well when using GAS.

    Choosing o64 shouldn't hurt mips-sgi-irix6.  Since its default ABI
    is n32, (i) would mean you still get n32 code after passing -mips3
    or -mips4.  You can switch to n64 using -mabi=64 in the usual way.

(4) The code to infer an ISA from an ABI is:

	/* A specified ABI defaults the ISA if it was not specified.  */
	else if (mips_isa_string == 0 && mips_abi_string
		 && mips_abi != ABI_EABI && mips_abi != ABI_O64)
	  {
	    if (mips_abi == ABI_32)
	      mips_isa = 1;
	    else if (mips_abi == ABI_N32)
	      mips_isa = 3;
	    else
	      mips_isa = 4;
	  }

    Problems here:

    (a) It seems counter-intuitive for -mabi to override the default
        architecture even when that default was compatible.  For
        example, "mipsisa32-elf-gcc -mabi=o32" would generate
	MIPS I code rather than MIPS 32 code.

    (b) MIPS III and MIPS IV processors can run o32 too, and you can
	sometimes get the benefit of extra instructions	(like
	conditional moves, and sometimes multiply-add).  It seems
	more appropriate to generate 32-bit code for the default
	architecture when passed -mabi=o32, rather than blindly
	switching to MIPS I.

    (b) There seems no good reason why we should choose MIPS IV over
	MIPS III for n64.  People have complained: see PR #5938.

    Proposed rule in this case:

    (i) If the default architecture is 64-bit, -mabi=32 selects
	32-bit registers, but keeps the current architecture.

    (ii) If the default architecture is MIPS I or MIPS II, selecting
	 a 64-bit ABI will switch to MIPS III.

    (iii) If the default architecture is MIPS 32, selecting a 64-bit
	  ABI will switch to MIPS 64.

(5) GCC has some code to infer register size from the architecture
    and ABI, but it's spread over specs and override_options.  I've
    moved it all to override_options so that the register size can
    depend on -march too.

A few other sundry things:

- -mcpu was deprecated in the last GCC and GAS releases.  This
  patch removes it.

- Both GCC and GAS could be better at detecting meaningless
  combinations.  I've tried to catch a few more.

- include/opcode/mips.h defines CPU_R2000, but there's no associated
  BFD arch, so -march=r2000 doesn't work.  It seems daft to add a 2000
  entry at this stage, so I've just mapped it to CPU_R3000 (like GCC).

- There's interim code in TARGET_CPP_BUILTINS that defines _R4000
  for 64-bit code and _R3000 for 32-bit code.  The patch tries to
  fix it.

- GAS and GCC didn't have quite the same -march arguments.  For
  example, GCC accepts -march=r4kc, but GAS insists on -march=4kc.
  To avoid that sort of thing in future, I've written a function
  that tries all the variations, using a table of just the
  "canonical" names.


I've tried to give the same structure to the GAS and GCC code,
so it's easy to compare and update.  A lot of the code is shared
outright.


A few other notes about the GAS changes:

With (5), it's no longer necessary for GAS to check the ABI in
the HAVE_32BIT_* macros, since the register size is always set.
That means we can remove the ABI field from mips_opts.  Also, the
new error checking means we can get rid of the ABI-killing code
for -mgp32, -mgp64 and -mfp32:

    case OPTION_GP32:
      file_mips_gp32 = 1;
      if (mips_opts.abi != O32_ABI)
	mips_opts.abi = NO_ABI;
      break;

This code seems suspect anyway: it's order-dependent, it silently
ignores incompatible options, and it means we ignore "-mabi=eabi" if
followed by "-mgp32" (despite it being a valid combination).

I'd prefer to choose the default CPU in configure: that way, we'd
get a compile-time error over missing entries, plus we can use globs.

Before 2.12, we only set EF_MIPS_ABI when -mabi was given on
the command line.  Since EF_MIPS_ABI is a GNU extension, the
onus seems to be on proving that it's safe to use it by default,
rather than the other way about.  So the patch uses NO_ABI as
the default for all configurations, but leaves open the possibility
of setting the default to something else on a per-configuration
basis.

And if you read all that, thanks for your patience.

The GAS part was tested on: mips-ecoff, mipsel-ecoff, mips-elf,
mipstx39-elf, mips64-elf, mips64orion-elf, mipsisa32-elf,
mipsisa64-elf, mipsel-linux-gnu and mips-sgi-irix6.5.  No
regressions.

GCC part was bootstrapped on mips-sgi-irix6.5, no regressions.
Also tested on mips64-elf, both with and without the GAS part
applied.

One part needs the other, really.  If the GCC patch is OK, I was
hoping to apply it before 3.2.  The GAS stuff is probably too
invasive for 2.13, though.

Thoughts?

Richard



[include/]
	* opcode/mips.h (CPU_R2000): Remove.

[gas/]
	* doc/c-mips.texi: Remove -mcpu.  Document -mabi.
	* configure.in: Work out the default MIPS ABI and architecture.
	* configure, config.in: Regenerate.
	* config/tc-mips.c (UNSET_ABI): New mips_abi_level.
	(file_mips_abi): Rename to mips_abi.
	(mips_set_options): Remove "abi" field.
	(mips_opts): Update accordingly.  Replace all uses of mips_opts.abi
	with mips_abi.
	(mips_arch_string, user_selected_mips_arch_p): New vars.
	(ABI_NEEDS_32BIT_REGS, ABI_NEEDS_64BIT_REGS): New macros.
	(HAVE_32BIT_GPRS, HAVE_32BIT_FPRS): Don't check the ABI.
	(mips_cpu_info): Remove "is_isa" field.
	(mips_isa_to_str, mips_cpu_to_str): Remove.
	(mips_ip): Read the processor name from mips_arch_string.  Use
	mips_isa_level to get the current ISA level.
	(OPTION_MCPU): Remove.
	(OPTION_FP64): New.
	(md_longopts): Add -mfp64, remove -mcpu.
	(md_parse_option): Make -mipsN update file_mips_isa rather than
	mips_opts.isa.  Use mips_parse_cpu.  Don't let -mgp32 and -mfp32
	change the ABI here.
	(show): Constify string argument.
	(md_show_usage): Move to the end of the file.  Read available
	architectures from mips_cpu_info_table.
	(mips_set_architecture): New fn.
	(mips_after_parse_args): Rework.  Remove -mcpu handling.  Treat
	-march and -mipsN equally when inferring an ABI or register size.
	Look at the register size when inferring the ABI, and vice versa.
	Complain about more conflicting arguments.  (Logic unified
	with gcc 3.2.)
	(s_mipsset): Don't change the ABI.
	(mips_cpu_info_table): Remove is_isa field.  Remove ISA-level
	entries.  Remove entries that vary only in the manufacturer's prefix,
	or that have "000" replaced by "k".  Remove TARGET_CPU entries.
	Make r2000 entry use CPU_R3000.
	(mips_cpu_info_from_name): Remove.
	(mips_strict_matching_cpu_name_p, mips_matching_cpu_name_p): New fns.
	(mips_parse_cpu, mips_isa_level): New fns.

[gas/testsuite]
	* gas/mips-gp32-fp64.d,
	* gas/mips-gp32-fp64-pic.d: Add -mfp64.


[gcc/]
	* doc/invoke.texi: Document -mabi=meabi.  Document -mips32, -mips64,
	and the associated -march values.  Be more careful about what the
	default is.  Mention the side-effects of -march and -mabi.  Say
	that the -mipsN options are equivalent to -march.
	* toplev.h (target_flags_explicit): Declare.
	* toplev.c (target_flags_explicit): New var.
	(set_target_switch): Update target_flags_explicit.
	* config/mips/isa3264.h (MIPS_ENABLE_EMBEDDED_O32): Undefine.
	* config/mips/iris6.h (SUBTARGET_ASM_SPEC): -mabi=64 implies
	-mips3 instead of -mips4.
	* config/mips/elforion.h, config/mips/r3900.h: Define
	MIPS_CPU_DEFAULT instead of MIPS_CPU_STRING_DEFAULT.
	* config/mips/mips.h (mips_cpu_string): Remove.
	(mips_explicit_type_size_string): Remove.
	(mips_cpp_processor_macro): Declare.
	(TARGET_CPP_BUILTINS): Use mips_cpp_processor_macro.
	(TARGET_OPTIONS): Remove -mcpu and -mexplicit-type-size.
	(ABI_NEEDS_32BIT_REGS, ABI_NEEDS_64BIT_REGS): New.
	(GAS_ASM_SPEC): Remove -mabi=32 -> -mipsN rule.
	(CC1_SPEC): Remove ISA -> register-size rules.
	* config/mips/mips.c (user_selected_mips_arch_p): New var.
	(mips_cpu_string, mips_explicit_type_size_string): Remove.
	(mips_cpp_processor_macro): New var.
	(struct mips_processor): New.
	(mips_processors): New array.
	(mips_set_architecture): New fn.
	(override_options): Rework to make -mipsN equivalent to -march.
	Detect more erroneous cases, including those removed from CC1_SPEC.
	Make o64 the default 64-bit ABI when selecting a 64-bit processor
	for a 32-bit config.  Make -mips3 the default for -mabi=64.
	Unify logic with GAS 2.14.
	(mips_strict_matching_cpu_name_p, mips_matching_cpu_name_p): New fns.
	(mips_parse_cpu): Take the name of the option as argument.  Raise
	an error if the option is wrong.
	(mips_cpu_from_isa_level): New fn.

Index: include/opcode/mips.h
===================================================================
RCS file: /cvs/src/src/include/opcode/mips.h,v
retrieving revision 1.27
diff -c -d -p -r1.27 mips.h
*** include/opcode/mips.h	9 Jul 2002 14:21:40 -0000	1.27
--- include/opcode/mips.h	12 Jul 2002 15:19:07 -0000
*************** struct mips_opcode
*** 377,383 ****
  /* CPU defines, use instead of hardcoding processor number. Keep this
     in sync with bfd/archures.c in order for machine selection to work.  */
  #define CPU_UNKNOWN	0               /* Gas internal use.  */
- #define CPU_R2000	2000
  #define CPU_R3000	3000
  #define CPU_R3900	3900
  #define CPU_R4000	4000
--- 377,382 ----
Index: gas/doc/c-mips.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/c-mips.texi,v
retrieving revision 1.22
diff -c -d -p -r1.22 c-mips.texi
*** gas/doc/c-mips.texi	31 May 2002 01:17:15 -0000	1.22
--- gas/doc/c-mips.texi	12 Jul 2002 15:19:07 -0000
*************** sb1
*** 175,186 ****
  Schedule and tune for a particular MIPS cpu.  Valid @var{cpu} values are
  identical to @samp{-march=@var{cpu}}.
  
! @item -mcpu=@var{cpu}
! Generate code and schedule for a particular MIPS cpu.  This is exactly
! equivalent to @samp{-march=@var{cpu}} and @samp{-mtune=@var{cpu}}.  Valid
! @var{cpu} values are identical to @samp{-march=@var{cpu}}.
! Use of this option is discouraged.
! 
  
  @cindex @code{-nocpp} ignored (MIPS)
  @item -nocpp
--- 175,183 ----
  Schedule and tune for a particular MIPS cpu.  Valid @var{cpu} values are
  identical to @samp{-march=@var{cpu}}.
  
! @item -mabi=@var{abi}
! Record which ABI the source code uses.  The recognized arguments
! are: @samp{32}, @samp{n32}, @samp{o64}, @samp{64} and @samp{eabi}.
  
  @cindex @code{-nocpp} ignored (MIPS)
  @item -nocpp
Index: gas/configure.in
===================================================================
RCS file: /cvs/src/src/gas/configure.in,v
retrieving revision 1.110
diff -c -d -p -r1.110 configure.in
*** gas/configure.in	9 Jul 2002 02:41:16 -0000	1.110
--- gas/configure.in	12 Jul 2002 15:19:07 -0000
*************** changequote([,])dnl
*** 555,560 ****
--- 555,626 ----
  
  # Other random stuff.
  
+     case ${cpu_type} in
+       mips)
+ 	# Translate the full CPU name, setting mips_cpu if it's associated
+ 	# with a particular processor model, or mips_isa if it's more
+ 	# generic.
+ 	case ${target_cpu} in
+ 	  mips | mipsbe | mipseb | mipsle | mipsel)
+ 	    mips_isa=ISA_MIPS1
+ 	    ;;
+ 	  mipstx39 | mipstx39el)
+ 	    mips_cpu=CPU_R3900
+ 	    ;;
+ 	  mips64 | mips64el)
+ 	    mips_isa=ISA_MIPS3
+ 	    ;;
+ 	  mips64vr4100 | mips64vr4100el)
+ 	    mips_cpu=CPU_VR4100
+ 	    ;;
+ 	  mips64vr4300 | mips64vr4300el)
+ 	    mips_cpu=CPU_R4300
+ 	    ;;
+ 	  mips64orion | mips64orionel)
+ 	    mips_cpu=CPU_R4600
+ 	    ;;
+ 	  mips64vr5000 | mips64vr5000el)
+ 	    mips_cpu=CPU_R5000
+ 	    ;;
+ 	  mipsisa32 | mipsisa32el)
+ 	    mips_isa=ISA_MIPS32
+ 	    ;;
+ 	  mipsisa64 | mipsisa64el)
+ 	    mips_isa=ISA_MIPS64
+ 	    ;;
+ 	esac
+ 	# Try to figure out the default ABI.  As far as GAS is concerned,
+ 	# this logic just selects the default setting of the EF_MIPS_ABI
+ 	# and EF_MIPS_ABI2 bits.
+ 
+ 	# Traditionally, we have only used EF_MIPS_ABI when the user gave
+ 	# -mabi on the command line.  We certainly don't want to use it
+ 	# ubiquitously because it's a GNU extension that many OSes and
+ 	# tools don't recognize.  Thus NO_ABI makes a sensible default.
+ 
+ 	# If a configuration does want a particular ABI to be the default,
+ 	# both GAS and GCC must agree on what that default is.  GAS tries
+ 	# to use the same logic as GCC when changing the ABI based on
+ 	# command line flags.
+ 	case ${target} in
+ 	  *)
+ 	    mips_abi=NO_ABI
+ 	    ;;
+ 	esac
+ 	if test -n "$mips_cpu"; then
+ 	  AC_DEFINE_UNQUOTED(TARGET_CPU_DEFAULT, $mips_cpu,
+ 			     [Default CPU (MIPS only)])
+ 	elif test -n "$mips_isa"; then
+ 	  AC_DEFINE_UNQUOTED(TARGET_ISA_DEFAULT, $mips_isa,
+ 			     [Default ISA (MIPS only)])
+ 	else
+ 	  AC_ERROR($target_cpu isn't a supported MIPS CPU name)
+ 	fi
+ 	AC_DEFINE_UNQUOTED(TARGET_ABI_DEFAULT, $mips_abi,
+ 			   [Default ABI (MIPS only)])
+ 	;;
+     esac
+ 
      # Do we need the opcodes library?
      case ${cpu_type} in
        vax | i386 | tic30)
Index: gas/config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.147
diff -c -d -p -r1.147 tc-mips.c
*** gas/config/tc-mips.c	9 Jul 2002 14:21:40 -0000	1.147
--- gas/config/tc-mips.c	12 Jul 2002 15:19:07 -0000
*************** extern int target_big_endian;
*** 120,126 ****
  /* The ABI to use.  */
  enum mips_abi_level
  {
!   NO_ABI = 0,
    O32_ABI,
    O64_ABI,
    N32_ABI,
--- 120,127 ----
  /* The ABI to use.  */
  enum mips_abi_level
  {
!   UNSET_ABI = 0,
!   NO_ABI,
    O32_ABI,
    O64_ABI,
    N32_ABI,
*************** enum mips_abi_level
*** 129,135 ****
  };
  
  /* MIPS ABI we are using for this output file.  */
! static enum mips_abi_level file_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
--- 130,136 ----
  };
  
  /* MIPS ABI we are using for this output file.  */
! static enum mips_abi_level mips_abi = UNSET_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
*************** struct mips_set_options
*** 177,185 ****
       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.  */
--- 178,183 ----
*************** static int file_mips_fp32 = -1;
*** 194,200 ****
  
  static struct mips_set_options mips_opts =
  {
!   ISA_UNKNOWN, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, NO_ABI
  };
  
  /* These variables are filled in with the masks of registers used.
--- 192,198 ----
  
  static struct mips_set_options mips_opts =
  {
!   ISA_UNKNOWN, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0
  };
  
  /* These variables are filled in with the masks of registers used.
*************** static int file_ase_mips3d;
*** 218,235 ****
     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;
  
  /* The argument of the -mtune= flag.  The architecture for which we
     are optimizing.  */
  static int mips_tune = CPU_UNKNOWN;
  
! /* If they asked for mips1 or mips2 and a cpu that is
!    mips3 or greater, then mark the object file 32BITMODE.  */
  static int mips_32bitmode = 0;
  
  /* Some ISA's have delay slots for instructions which read or write
--- 216,235 ----
     command line (e.g., by -march).  */
  static int file_ase_mdmx;
  
  /* The argument of the -march= flag.  The architecture we are assembling.  */
  static int mips_arch = CPU_UNKNOWN;
  
+ /* The same, as a string.  Always non-null after argument processing.  */
+ static const char *mips_arch_string;
+ 
+ /* True if mips_arch was set on the command line.  */
+ static boolean user_selected_mips_arch_p;
+ 
  /* The argument of the -mtune= flag.  The architecture for which we
     are optimizing.  */
  static int mips_tune = CPU_UNKNOWN;
  
! /* 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
*************** static int mips_32bitmode = 0;
*** 246,251 ****
--- 246,260 ----
     || (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                \
*************** static int mips_32bitmode = 0;
*** 255,275 ****
     )
  
  #define HAVE_32BIT_GPRS		                   \
!     (mips_opts.gp32                                \
!      || mips_opts.abi == O32_ABI                   \
!      || ! 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))
  
  #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_64BIT_OBJECTS (mips_opts.abi == N64_ABI)
  
  /* We can only have 64bit addresses if the object file format
     supports it.  */
--- 264,280 ----
     )
  
  #define HAVE_32BIT_GPRS		                   \
!     (mips_opts.gp32 || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
  
  #define HAVE_32BIT_FPRS                            \
!     (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_abi == N32_ABI || mips_abi == N64_ABI)
  
! #define HAVE_64BIT_OBJECTS (mips_abi == N64_ABI)
  
  /* We can only have 64bit addresses if the object file format
     supports it.  */
*************** static void s_mips_weakext PARAMS ((int)
*** 772,781 ****
  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 *));
  #ifdef OBJ_ELF
  static int mips_need_elf_addend_fixup PARAMS ((fixS *));
  #endif
--- 777,784 ----
  static void s_mips_file PARAMS ((int));
  static void s_mips_loc PARAMS ((int));
  static int mips16_extended_frag PARAMS ((fragS *, asection *, long));
  static int validate_mips_insn PARAMS ((const struct mips_opcode *));
! static void show PARAMS ((FILE *, const char *, int *, int *));
  #ifdef OBJ_ELF
  static int mips_need_elf_addend_fixup PARAMS ((fixS *));
  #endif
*************** enum small_ex_type
*** 812,825 ****
  struct mips_cpu_info
  {
    const char *name;           /* CPU or ISA name.  */
-   int is_isa;                 /* Is this an ISA?  (If 0, a CPU.) */
    int isa;                    /* ISA level.  */
    int cpu;                    /* CPU number (default CPU if ISA).  */
  };
  
! static const struct mips_cpu_info *mips_cpu_info_from_name PARAMS ((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));
  
  /* Pseudo-op table.
  
--- 815,832 ----
  struct mips_cpu_info
  {
    const char *name;           /* CPU or ISA name.  */
    int isa;                    /* ISA level.  */
    int cpu;                    /* CPU number (default CPU if ISA).  */
  };
  
! static void mips_set_architecture PARAMS ((const struct mips_cpu_info *, int));
! 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 void mips_parse_cpu PARAMS ((const char *, const char *, int *));
  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));
+ static int mips_isa_level PARAMS ((int));
  
  /* Pseudo-op table.
  
*************** static boolean mips16_small, mips16_ext;
*** 972,1007 ****
  
  static segT pdr_seg;
  
- 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.  */
  
  const char *
--- 979,984 ----
*************** md_begin ()
*** 1177,1183 ****
  	if (strcmp (TARGET_OS, "elf") != 0)
  	  flags |= SEC_ALLOC | SEC_LOAD;
  
! 	if (file_mips_abi != N64_ABI)
  	  {
  	    sec = subseg_new (".reginfo", (subsegT) 0);
  
--- 1154,1160 ----
  	if (strcmp (TARGET_OS, "elf") != 0)
  	  flags |= SEC_ALLOC | SEC_LOAD;
  
! 	if (mips_abi != N64_ABI)
  	  {
  	    sec = subseg_new (".reginfo", (subsegT) 0);
  
*************** mips_ip (str, ip)
*** 7764,7772 ****
  		{
  		  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));
  
  		  insn_error = buf;
  		}
--- 7741,7748 ----
  		{
  		  static char buf[100];
  		  sprintf (buf,
! 			   _("opcode not supported on this processor: %s (MIPS%d)"),
! 			   mips_arch_string, mips_isa_level (mips_opts.isa));
  
  		  insn_error = buf;
  		}
*************** struct option md_longopts[] =
*** 9892,9899 ****
    {"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_M4650 (OPTION_MD_BASE + 24)
    {"m4650", no_argument, NULL, OPTION_M4650},
  #define OPTION_NO_M4650 (OPTION_MD_BASE + 25)
--- 9868,9875 ----
    {"march", required_argument, NULL, OPTION_MARCH},
  #define OPTION_MTUNE (OPTION_MD_BASE + 22)
    {"mtune", required_argument, NULL, OPTION_MTUNE},
! #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)
*************** md_parse_option (c, arg)
*** 10001,10085 ****
        break;
  
      case OPTION_MIPS1:
!       mips_opts.isa = ISA_MIPS1;
        break;
  
      case OPTION_MIPS2:
!       mips_opts.isa = ISA_MIPS2;
        break;
  
      case OPTION_MIPS3:
!       mips_opts.isa = ISA_MIPS3;
        break;
  
      case OPTION_MIPS4:
!       mips_opts.isa = ISA_MIPS4;
        break;
  
      case OPTION_MIPS5:
!       mips_opts.isa = ISA_MIPS5;
        break;
  
      case OPTION_MIPS32:
!       mips_opts.isa = ISA_MIPS32;
        break;
  
      case OPTION_MIPS64:
!       mips_opts.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;
! 	  }
  
! 	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;
! 	  }
!       }
        break;
  
      case OPTION_M4650:
--- 9977,10017 ----
        break;
  
      case OPTION_MIPS1:
!       file_mips_isa = ISA_MIPS1;
        break;
  
      case OPTION_MIPS2:
!       file_mips_isa = ISA_MIPS2;
        break;
  
      case OPTION_MIPS3:
!       file_mips_isa = ISA_MIPS3;
        break;
  
      case OPTION_MIPS4:
!       file_mips_isa = ISA_MIPS4;
        break;
  
      case OPTION_MIPS5:
!       file_mips_isa = ISA_MIPS5;
        break;
  
      case OPTION_MIPS32:
!       file_mips_isa = ISA_MIPS32;
        break;
  
      case OPTION_MIPS64:
!       file_mips_isa = ISA_MIPS64;
        break;
  
      case OPTION_MTUNE:
!       mips_parse_cpu ("-mtune", arg, &mips_tune);
!       break;
  
!     case OPTION_MARCH:
!       mips_parse_cpu ("-march", arg, &mips_arch);
!       if (mips_arch != CPU_UNKNOWN)
! 	mips_arch_string = arg;
        break;
  
      case OPTION_M4650:
*************** md_parse_option (c, arg)
*** 10227,10233 ****
  	  as_bad (_("-32 is supported for ELF format only"));
  	  return 0;
  	}
!       mips_opts.abi = O32_ABI;
        break;
  
      case OPTION_N32:
--- 10159,10165 ----
  	  as_bad (_("-32 is supported for ELF format only"));
  	  return 0;
  	}
!       mips_abi = O32_ABI;
        break;
  
      case OPTION_N32:
*************** md_parse_option (c, arg)
*** 10236,10242 ****
  	  as_bad (_("-n32 is supported for ELF format only"));
  	  return 0;
  	}
!       mips_opts.abi = N32_ABI;
        break;
  
      case OPTION_64:
--- 10168,10174 ----
  	  as_bad (_("-n32 is supported for ELF format only"));
  	  return 0;
  	}
!       mips_abi = N32_ABI;
        break;
  
      case OPTION_64:
*************** md_parse_option (c, arg)
*** 10245,10251 ****
  	  as_bad (_("-64 is supported for ELF format only"));
  	  return 0;
  	}
!       mips_opts.abi = N64_ABI;
        if (! support_64bit_objects())
  	as_fatal (_("No compiled in support for 64 bit object file format"));
        break;
--- 10177,10183 ----
  	  as_bad (_("-64 is supported for ELF format only"));
  	  return 0;
  	}
!       mips_abi = N64_ABI;
        if (! support_64bit_objects())
  	as_fatal (_("No compiled in support for 64 bit object file format"));
        break;
*************** md_parse_option (c, arg)
*** 10253,10272 ****
  
      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;
  
  #ifdef OBJ_ELF
--- 10185,10202 ----
  
      case OPTION_GP32:
        file_mips_gp32 = 1;
        break;
  
      case OPTION_GP64:
        file_mips_gp32 = 0;
        break;
  
      case OPTION_FP32:
        file_mips_fp32 = 1;
!       break;
! 
!     case OPTION_FP64:
!       file_mips_fp32 = 0;
        break;
  
  #ifdef OBJ_ELF
*************** md_parse_option (c, arg)
*** 10277,10296 ****
  	  return 0;
  	}
        if (strcmp (arg, "32") == 0)
! 	mips_opts.abi = O32_ABI;
        else if (strcmp (arg, "o64") == 0)
! 	mips_opts.abi = O64_ABI;
        else if (strcmp (arg, "n32") == 0)
! 	mips_opts.abi = N32_ABI;
        else if (strcmp (arg, "64") == 0)
  	{
! 	  mips_opts.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;
        else
  	{
  	  as_fatal (_("invalid abi -mabi=%s"), arg);
--- 10207,10226 ----
  	  return 0;
  	}
        if (strcmp (arg, "32") == 0)
! 	mips_abi = O32_ABI;
        else if (strcmp (arg, "o64") == 0)
! 	mips_abi = O64_ABI;
        else if (strcmp (arg, "n32") == 0)
! 	mips_abi = N32_ABI;
        else if (strcmp (arg, "64") == 0)
  	{
! 	  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_abi = EABI_ABI;
        else
  	{
  	  as_fatal (_("invalid abi -mabi=%s"), arg);
*************** md_parse_option (c, arg)
*** 10327,10333 ****
  static void
  show (stream, string, col_p, first_p)
       FILE *stream;
!      char *string;
       int *col_p;
       int *first_p;
  {
--- 10257,10263 ----
  static void
  show (stream, string, col_p, first_p)
       FILE *stream;
!      const char *string;
       int *col_p;
       int *first_p;
  {
*************** show (stream, string, col_p, first_p)
*** 10353,10466 ****
  
    *first_p = 0;
  }
  
! void
! md_show_usage (stream)
!      FILE *stream;
  {
!   int column, first;
! 
!   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;
! 
!   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);
! 
!   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
- }
- 
  void
  mips_after_parse_args ()
  {
-   const char *cpu;
-   char *a = NULL;
-   int mips_isa_from_cpu;
-   const struct mips_cpu_info *ci;
- 
    /* GP relative stuff not working for PE */
    if (strncmp (TARGET_OS, "pe", 2) == 0
        && g_switch_value != 0)
--- 10283,10306 ----
  
    *first_p = 0;
  }
+ 
+ /* Set up globals to generate code for ARCH.  USER_SELECTED_P is true
+    if the user selected this architecture explicitly.  */
  
! static void
! mips_set_architecture (info, user_selected_p)
!      const struct mips_cpu_info *info;
!      int user_selected_p;
  {
!   mips_arch = info->cpu;
!   mips_opts.isa = info->isa;
!   user_selected_mips_arch_p = user_selected_p;
! }
  
  
  void
  mips_after_parse_args ()
  {
    /* GP relative stuff not working for PE */
    if (strncmp (TARGET_OS, "pe", 2) == 0
        && g_switch_value != 0)
*************** mips_after_parse_args ()
*** 10470,10653 ****
        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;
!     }
  
!   /* 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"));
  
-   /* 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.mips16 == -1)
--- 10310,10450 ----
        g_switch_value = 0;
      }
  
!   /* The following code determines the architecture, ABI and register size.
!      Much of the complexity is in infering complete information when some
!      flags are not given.  Some of the details are historical.
  
!      Similar code was added to GCC 3.2 (see config/mips/mips.c:
!      override_options()).  The GAS and GCC code should be kept in sync
!      as much as possible.  */
  
  
!   /* -march is more descriptive than -mipsN, so check it first.  */
!   if (mips_arch != CPU_UNKNOWN)
      {
!       mips_set_architecture (mips_cpu_info_from_cpu (mips_arch), true);
!       if (file_mips_isa != ISA_UNKNOWN)
  	{
! 	  /* The user specified both -mipsN and -march.  There's no
! 	     harm in it if the two arguments agree, just as there's
! 	     no harm in giving redundant register size options.  Only
! 	     complain if the arguments contradict one another.  */
! 	  if (file_mips_isa != mips_opts.isa)
! 	    as_bad (_("-mips%d conflicts with the other architecture options, which specify a MIPS%d processor"),
! 		    mips_isa_level (file_mips_isa),
! 		    mips_isa_level (mips_opts.isa));
  	}
+     }
+   else if (file_mips_isa != ISA_UNKNOWN)
+     mips_set_architecture (mips_cpu_info_from_isa (file_mips_isa), true);
+   else
+ #ifdef TARGET_CPU_DEFAULT
+     mips_set_architecture (mips_cpu_info_from_cpu (TARGET_CPU_DEFAULT), false);
+ #else
+     mips_set_architecture (mips_cpu_info_from_isa (TARGET_ISA_DEFAULT), false);
+ #endif
  
  
!   if (mips_abi != UNSET_ABI)
!     {
!       if (!ISA_HAS_64BIT_REGS (mips_opts.isa)
! 	  && ABI_NEEDS_64BIT_REGS (mips_abi))
  	{
! 	  if (user_selected_mips_arch_p)
! 	    as_bad (_("Command line selects a 64-bit ABI and a 32-bit processor"));
! 	  else
! 	    {
! 	      /* The user specified an ABI but not an ISA.  The ABI needs
! 		 64-bit registers, but the default architecture is 32-bit.
! 		 GCC has historically "upgraded" to a 64-bit ISA.  */
! 	      int level = (mips_opts.isa == 32 ? 64 : 3);
! 	      mips_set_architecture (mips_cpu_info_from_isa (level), false);
! 	    }
  	}
      }
!   else if (file_mips_gp32 == 1)
      {
!       /* The user didn't specify an ABI, but used -mgp32.
! 	 Force a 32-bit ABI.  */
!       if (ABI_NEEDS_64BIT_REGS (TARGET_ABI_DEFAULT))
! 	mips_abi = O32_ABI;
      }
!   else if (user_selected_mips_arch_p)
      {
!       /* The user specified a processor but not an ABI.  We've already
! 	 handled the -mgp32 case, so either the register size was not
! 	 specified explicitly, or it is expected to match the processor's.
! 	 If the processor's register size doesn't match the ABI, switch
! 	 to another ABI.  */
!       if (!ISA_HAS_64BIT_REGS (mips_opts.isa)
! 	  && ABI_NEEDS_64BIT_REGS (TARGET_ABI_DEFAULT))
! 	mips_abi = O32_ABI;
!       else if (ISA_HAS_64BIT_REGS (mips_opts.isa)
! 	       && ABI_NEEDS_32BIT_REGS (TARGET_ABI_DEFAULT))
! 	mips_abi = O64_ABI;
      }
  
!   if (mips_abi == UNSET_ABI)
      {
!       /* The user took no action that implied an ABI change.  */
!       mips_abi = TARGET_ABI_DEFAULT;
      }
  
!   /* At this point, we know the architecture and ABI.  We've also
!      avoided the case that ABI_NEEDS_64BIT_REGS && !ISA_HAS_64BIT_REGS,
!      unless the user selected it explicitly, in which case we've
!      complained.  */
  
!   /* Make sure we have an architecture name.  Prefer to use the
!      argument to -march, if given, since it's what the user might
!      expect to see in error messages.  Otherwise use the canonical
!      name for this architecture.  */
!   if (mips_arch_string == 0)
!     mips_arch_string = mips_cpu_info_from_cpu (mips_arch)->name;
! 
!   /* Optimize for mips_arch, unless -mtune selects a different processor.  */
!   if (mips_tune == CPU_UNKNOWN)
!     mips_tune = mips_arch;
! 
!   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));
      }
  
!   /* ??? 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;
  
!   /* End of GCC-shared inference code.  */
  
!   /* ??? Under what conditions do we want this flag to be set?
!      Who uses it?  */
!   if (file_mips_gp32 == 1 && 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_after_parse_args ()
*** 10657,10669 ****
    if (mips_opts.ase_mdmx == -1)
      mips_opts.ase_mdmx = (CPU_HAS_MDMX (mips_arch)) ? 1 : 0;
  
-   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_mips16 = mips_opts.mips16;
    file_ase_mips3d = mips_opts.ase_mips3d;
    file_ase_mdmx = mips_opts.ase_mdmx;
--- 10454,10460 ----
*************** s_mipsset (x)
*** 11738,11744 ****
  	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:
--- 11529,11534 ----
*************** s_mipsset (x)
*** 11750,11758 ****
  	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;
--- 11540,11545 ----
*************** void
*** 13201,13207 ****
  mips_elf_final_processing ()
  {
    /* Write out the register information.  */
!   if (file_mips_abi != N64_ABI)
      {
        Elf32_RegInfo s;
  
--- 12988,12994 ----
  mips_elf_final_processing ()
  {
    /* Write out the register information.  */
!   if (mips_abi != N64_ABI)
      {
        Elf32_RegInfo s;
  
*************** mips_elf_final_processing ()
*** 13251,13263 ****
      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)
      elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_O32;
!   else if (file_mips_abi == O64_ABI)
      elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_O64;
!   else if (file_mips_abi == EABI_ABI)
      {
        /* Set the EABI kind based on the ISA.  This isn't really
  	 the best, but then neither is basing the abi on the isa.  */
--- 13038,13050 ----
      elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ARCH_ASE_MDMX;
  
    /* Set the MIPS ELF ABI flags.  */
!   if (mips_abi == NO_ABI)
      ;
!   else if (mips_abi == O32_ABI)
      elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_O32;
!   else if (mips_abi == O64_ABI)
      elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_O64;
!   else if (mips_abi == EABI_ABI)
      {
        /* Set the EABI kind based on the ISA.  This isn't really
  	 the best, but then neither is basing the abi on the isa.  */
*************** mips_elf_final_processing ()
*** 13266,13272 ****
        else
  	elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_EABI32;
      }
!   else if (file_mips_abi == N32_ABI)
      elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ABI2;
  
    /* Nothing to do for N64_ABI.  */
--- 13053,13059 ----
        else
  	elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_EABI32;
      }
!   else if (mips_abi == N32_ABI)
      elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ABI2;
  
    /* Nothing to do for N64_ABI.  */
*************** s_loc (x)
*** 13709,13882 ****
  
  /* CPU name/ISA/number mapping table.
  
!    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.  */
  static const struct mips_cpu_info mips_cpu_info_table[] =
  {
!   /* MIPS1 ISA */
!   { "MIPS1",          1,      ISA_MIPS1,      CPU_R3000, },
!   { "mips",           1,      ISA_MIPS1,      CPU_R3000, },
! 
!   /* MIPS2 ISA */
!   { "MIPS2",          1,      ISA_MIPS2,      CPU_R6000, },
! 
!   /* MIPS3 ISA */
!   { "MIPS3",          1,      ISA_MIPS3,      CPU_R4000, },
! 
!   /* MIPS4 ISA */
!   { "MIPS4",          1,      ISA_MIPS4,      CPU_R8000, },
! 
!   /* 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, },
! };
  
! static const struct mips_cpu_info *
! mips_cpu_info_from_name (name)
!      const char *name;
  {
    int i;
  
    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]);
  
!   return NULL;
  }
  
  static const struct mips_cpu_info *
  mips_cpu_info_from_isa (isa)
       int isa;
--- 13496,13644 ----
  
  /* CPU name/ISA/number mapping table.
  
!    Entries are grouped by type.  The first mention of a CPU_* value
!    is taken to be the canonical entry for that CPU.  */
  static const struct mips_cpu_info mips_cpu_info_table[] =
  {
!   { "Generic-MIPS5",  ISA_MIPS5,      CPU_MIPS5, },
!   { "Generic-MIPS32", ISA_MIPS32,     CPU_MIPS32, },
!   { "Generic-MIPS64", ISA_MIPS64,     CPU_MIPS64, },
  
!   /* We also accept the names of specific MIPS 32 processors, although
!      the differences between them don't matter to us.  */
!   { "R4KC",           ISA_MIPS32,     CPU_MIPS32, },
!   { "R4KM",           ISA_MIPS32,     CPU_MIPS32, },
!   { "R4KP",           ISA_MIPS32,     CPU_MIPS32, },
  
!   /* Likewise for some MIPS 64 processors...  */
!   { "R5KC",           ISA_MIPS64,     CPU_MIPS64, },
!   { "R20KC",          ISA_MIPS64,     CPU_MIPS64, },
  
!   /* Various names for the Broadcom SB-1.  */
!   { "SB-1",           ISA_MIPS64,     CPU_SB1, },
!   { "sb-1250",        ISA_MIPS64,     CPU_SB1, },
!   { "sb1",            ISA_MIPS64,     CPU_SB1, },
!   { "sb1250",         ISA_MIPS64,     CPU_SB1, },
  
!   /* The canonical entries for the other ISA levels.  */
!   { "R3000",          ISA_MIPS1,      CPU_R3000, },
!   { "R6000",          ISA_MIPS2,      CPU_R6000, },
!   { "R4000",          ISA_MIPS3,      CPU_R4000, },
!   { "R8000",          ISA_MIPS4,      CPU_R8000, },
  
!   /* ??? Use the r3000 bfd arch for r2000.  */
!   { "R2000",          ISA_MIPS1,      CPU_R3000, },
!   { "R3900",          ISA_MIPS1,      CPU_R3900, },
!   { "R4010",          ISA_MIPS2,      CPU_R4010, },
!   { "R4400",          ISA_MIPS3,      CPU_R4400, },
!   { "R4600",          ISA_MIPS3,      CPU_R4600, },
!   { "orion",          ISA_MIPS3,      CPU_R4600, },
!   { "R4650",          ISA_MIPS3,      CPU_R4650, },
!   { "R10000",         ISA_MIPS4,      CPU_R10000, },
!   { "R12000",         ISA_MIPS4,      CPU_R12000, },
!   { "VR4100",         ISA_MIPS3,      CPU_VR4100, },
!   { "VR4111",         ISA_MIPS3,      CPU_R4111, },
!   { "VR4300",         ISA_MIPS3,      CPU_R4300, },
!   { "VR5000",         ISA_MIPS4,      CPU_R5000, },
!   { "RM5200",         ISA_MIPS4,      CPU_R5000, },
!   { "RM5230",         ISA_MIPS4,      CPU_R5000, },
!   { "RM5231",         ISA_MIPS4,      CPU_R5000, },
!   { "RM5261",         ISA_MIPS4,      CPU_R5000, },
!   { "RM5721",         ISA_MIPS4,      CPU_R5000, },
!   { "R7000",          ISA_MIPS4,      CPU_R5000, },
  
!   /* End marker.  */
!   { NULL, 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.
!    If CPU_STRING is a recognized processor, store its CPU_* enumeration
!    in *CPU_PTR, otherwise report an error.  Warn if the same option
!    is used twice.  */
  
! static void
! mips_parse_cpu (option, cpu_string, cpu_ptr)
!      const char *option, *cpu_string;
!      int *cpu_ptr;
  {
    int i;
  
+   if (*cpu_ptr != CPU_UNKNOWN)
+     as_warn (_("Duplicate %s options: using %s"), option, cpu_string);
+ 
    for (i = 0; mips_cpu_info_table[i].name != NULL; i++)
!     if (mips_matching_cpu_name_p (mips_cpu_info_table[i].name, cpu_string))
!       {
! 	*cpu_ptr = mips_cpu_info_table[i].cpu;
! 	return;
!       }
  
!   if (strcasecmp (cpu_string, "default") == 0)
!     {
!       *cpu_ptr = CPU_UNKNOWN;
!       return;
!     }
! 
!   as_bad (_("Unrecognised argument (%s) to %s"), cpu_string, option);
  }
  
+ 
+ /* 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;
*************** mips_cpu_info_from_isa (isa)
*** 13884,13896 ****
    int i;
  
    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)
        return (&mips_cpu_info_table[i]);
  
    return NULL;
  }
  
  static const struct mips_cpu_info *
  mips_cpu_info_from_cpu (cpu)
       int cpu;
--- 13646,13660 ----
    int i;
  
    for (i = 0; mips_cpu_info_table[i].name != NULL; i++)
!     if (isa == mips_cpu_info_table[i].isa)
        return (&mips_cpu_info_table[i]);
  
    return NULL;
  }
  
+ 
+ /* Likewise CPU (a member of the CPU_* enumeration).  */
+ 
  static const struct mips_cpu_info *
  mips_cpu_info_from_cpu (cpu)
       int cpu;
*************** mips_cpu_info_from_cpu (cpu)
*** 13898,13906 ****
    int i;
  
    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]);
  
    return NULL;
  }
--- 13662,13770 ----
    int i;
  
    for (i = 0; mips_cpu_info_table[i].name != NULL; i++)
!     if (cpu == mips_cpu_info_table[i].cpu)
        return (&mips_cpu_info_table[i]);
  
    return NULL;
+ }
+ 
+ 
+ /* Convert one of the internal ISA_MIPS* values into an integer ISA level.
+    Used mainly for diagnostics.  */
+ 
+ static int
+ mips_isa_level (bfd_encoding)
+      int bfd_encoding;
+ {
+   switch (bfd_encoding)
+     {
+     case ISA_MIPS1: return 1;
+     case ISA_MIPS2: return 2;
+     case ISA_MIPS3: return 3;
+     case ISA_MIPS4: return 4;
+     case ISA_MIPS5: return 5;
+     case ISA_MIPS32: return 32;
+     case ISA_MIPS64: return 64;
+     default: abort ();
+     }
+ }
+ 
+ void
+ md_show_usage (stream)
+      FILE *stream;
+ {
+   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++)
+     show (stream, mips_cpu_info_table[i].name, &column, &first);
+   fputc ('\n', stream);
+ 
+   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
  }
Index: gas/testsuite/gas/mips/mips-gp32-fp64.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips-gp32-fp64.d,v
retrieving revision 1.3
diff -c -d -p -r1.3 mips-gp32-fp64.d
*** gas/testsuite/gas/mips/mips-gp32-fp64.d	10 Aug 2001 16:28:04 -0000	1.3
--- gas/testsuite/gas/mips/mips-gp32-fp64.d	12 Jul 2002 15:19:07 -0000
***************
*** 1,5 ****
  #objdump: -d -mmips:8000
! #as: -march=8000 -EB -mgp32
  #name: MIPS -mgp32 -mfp64
  
  .*: +file format.*
--- 1,5 ----
  #objdump: -d -mmips:8000
! #as: -march=8000 -EB -mgp32 -mfp64
  #name: MIPS -mgp32 -mfp64
  
  .*: +file format.*
Index: gas/testsuite/gas/mips/mips-gp32-fp64-pic.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips-gp32-fp64-pic.d,v
retrieving revision 1.3
diff -c -d -p -r1.3 mips-gp32-fp64-pic.d
*** gas/testsuite/gas/mips/mips-gp32-fp64-pic.d	10 Aug 2001 16:28:04 -0000	1.3
--- gas/testsuite/gas/mips/mips-gp32-fp64-pic.d	12 Jul 2002 15:19:07 -0000
***************
*** 1,5 ****
  #objdump: -d -mmips:8000
! #as: -march=8000 -EB -mgp32 -KPIC
  #name: MIPS -mgp32 -mfp64 (SVR4 PIC)
  
  .*: +file format.*
--- 1,5 ----
  #objdump: -d -mmips:8000
! #as: -march=8000 -EB -mgp32 -mfp64 -KPIC
  #name: MIPS -mgp32 -mfp64 (SVR4 PIC)
  
  .*: +file format.*
Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.155
diff -c -d -p -r1.155 invoke.texi
*** doc/invoke.texi	10 Jul 2002 19:17:51 -0000	1.155
--- doc/invoke.texi	12 Jul 2002 15:47:52 -0000
*************** These @samp{-m} options are defined for 
*** 6956,7018 ****
  
  @item -march=@var{cpu-type}
  @opindex march
! Assume the defaults for the machine type @var{cpu-type} when generating
! instructions.  The choices for @var{cpu-type} are  @samp{r2000}, @samp{r3000},
! @samp{r3900}, @samp{r4000}, @samp{r4100}, @samp{r4300}, @samp{r4400},
! @samp{r4600}, @samp{r4650}, @samp{r5000}, @samp{r6000}, @samp{r8000},
! and @samp{orion}.  Additionally, the @samp{r2000}, @samp{r3000},
! @samp{r4000}, @samp{r5000}, and @samp{r6000} can be abbreviated as
! @samp{r2k} (or @samp{r2K}), @samp{r3k}, etc.
  
  @item -mtune=@var{cpu-type}
  @opindex mtune
! Assume the defaults for the machine type @var{cpu-type} when scheduling
! instructions.  The choices for @var{cpu-type} are @samp{r2000}, @samp{r3000},
! @samp{r3900}, @samp{r4000}, @samp{r4100}, @samp{r4300}, @samp{r4400},
! @samp{r4600}, @samp{r4650}, @samp{r5000}, @samp{r6000}, @samp{r8000},
! and @samp{orion}.  Additionally, the @samp{r2000}, @samp{r3000},
! @samp{r4000}, @samp{r5000}, and @samp{r6000} can be abbreviated as
! @samp{r2k} (or @samp{r2K}), @samp{r3k}, etc.  While picking a specific
! @var{cpu-type} will schedule things appropriately for that particular
! chip, the compiler will not generate any code that does not meet level 1
! of the MIPS ISA (instruction set architecture) without a @option{-mipsX}
! or @option{-mabi} switch being used.
  
! @item -mcpu=@var{cpu-type}
! @opindex mcpu
! This is identical to specifying both @option{-march} and @option{-mtune}.
  
  @item -mips1
  @opindex mips1
! Issue instructions from level 1 of the MIPS ISA@.  This is the default.
! @samp{r3000} is the default @var{cpu-type} at this ISA level.
  
  @item -mips2
  @opindex mips2
! Issue instructions from level 2 of the MIPS ISA (branch likely, square
! root instructions).  @samp{r6000} is the default @var{cpu-type} at this
! ISA level.
  
  @item -mips3
  @opindex mips3
! Issue instructions from level 3 of the MIPS ISA (64-bit instructions).
! @samp{r4000} is the default @var{cpu-type} at this ISA level.
  
  @item -mips4
  @opindex mips4
! Issue instructions from level 4 of the MIPS ISA (conditional move,
! prefetch, enhanced FPU instructions).  @samp{r8000} is the default
! @var{cpu-type} at this ISA level.
  
! @item -mfp32
! @opindex mfp32
! Assume that 32 32-bit floating point registers are available.  This is
! the default.
  
! @item -mfp64
! @opindex mfp64
! Assume that 32 64-bit floating point registers are available.  This is
! the default when the @option{-mips3} option is used.
  
  @item -mfused-madd
  @itemx -mno-fused-madd
--- 6956,7015 ----
  
  @item -march=@var{cpu-type}
  @opindex march
! Generate code that will run on @var{cpu-type}.  GCC might use
! any instruction that the processor understands, subject to the
! options described below.  @var{cpu-type} can be @samp{r2000},
! @samp{r3000}, @samp{r3900}, @samp{r4000}, @samp{r4100}, @samp{r4300},
! @samp{r4400}, @samp{r4600}, @samp{r4650}, @samp{r5000}, @samp{r6000},
! @samp{r8000}, @samp{r4kc}, @samp{r4kp}, @samp{r5kc}, @samp{r20kc}
! or @samp{orion}.  @samp{r@var{x}000} can be abbreviated as
! @samp{r@var{x}k} (for example, @samp{-march=r2k}).  The initial
! @samp{r} is optional.
! 
! If your configuration uses the o32 ABI by default, selecting a 64-bit
! processor will implicitly select the o64 ABI@.  You can continue to use
! the o32 ABI by adding @samp{-mgp32} to the command line (for example,
! @samp{-march=r4000 -mgp32}).
! 
! If your configuration uses a 64-bit ABI by default, selecting a 32-bit
! processor will implicitly select the o32 ABI@.
  
  @item -mtune=@var{cpu-type}
  @opindex mtune
! Optimize for @var{cpu-type}.  Among other things, this option controls
! the way instructions are scheduled, and the perceived cost of arithmetic
! operations.  The list of @var{cpu-type} values is the same as for
! @samp{-march}.
  
! When this option is not used, GCC will optimize for the processor
! specified by @samp{-march}, or (failing that) for the default
! processor.  By using @samp{-march} and @samp{-mtune} together, it is
! possible to generate code that will run on a family of processors, but
! optimize the code for one particular member of that family.
  
  @item -mips1
  @opindex mips1
! Equivalent to @samp{-march=r2000}.
  
  @item -mips2
  @opindex mips2
! Equivalent to @samp{-march=r6000}.
  
  @item -mips3
  @opindex mips3
! Equivalent to @samp{-march=r4000}.
  
  @item -mips4
  @opindex mips4
! Equivalent to @samp{-march=r8000}.
  
! @item -mips32
! @opindex mips32
! Equivalent to @samp{-march=r4kc}.
  
! @item -mips64
! @opindex mips64
! Equivalent to @samp{-march=r5kc}.
  
  @item -mfused-madd
  @itemx -mno-fused-madd
*************** in the mode where denormals are rounded 
*** 7026,7040 ****
  generated by multiply and accumulate instructions cause exceptions
  anyway.
  
  @item -mgp32
  @opindex mgp32
! Assume that 32 32-bit general purpose registers are available.  This is
! the default.
  
  @item -mgp64
  @opindex mgp64
! Assume that 32 64-bit general purpose registers are available.  This is
! the default when the @option{-mips3} option is used.
  
  @item -mint64
  @opindex mint64
--- 7023,7043 ----
  generated by multiply and accumulate instructions cause exceptions
  anyway.
  
+ @item -mfp32
+ @opindex mfp32
+ Assume that floating point registers are 32 bits wide.
+ 
+ @item -mfp64
+ @opindex mfp64
+ Assume that floating point registers are 64 bits wide.
+ 
  @item -mgp32
  @opindex mgp32
! Assume that general purpose registers are 32 bits wide.
  
  @item -mgp64
  @opindex mgp64
! Assume that general purpose registers are 64 bits wide.
  
  @item -mint64
  @opindex mint64
*************** registers (which in turn depends on the 
*** 7065,7080 ****
  @itemx -mabi=n32
  @itemx -mabi=64
  @itemx -mabi=eabi
  @opindex mabi=32
  @opindex mabi=o64
  @opindex mabi=n32
  @opindex mabi=64
  @opindex mabi=eabi
! Generate code for the indicated ABI@.  The default instruction level is
! @option{-mips1} for @samp{32}, @option{-mips3} for @samp{n32}, and
! @option{-mips4} otherwise.  Conversely, with @option{-mips1} or
! @option{-mips2}, the default ABI is @samp{32}; otherwise, the default ABI
! is @samp{64}.
  
  @item -mmips-as
  @opindex mmips-as
--- 7068,7092 ----
  @itemx -mabi=n32
  @itemx -mabi=64
  @itemx -mabi=eabi
+ @itemx -mabi=meabi
  @opindex mabi=32
  @opindex mabi=o64
  @opindex mabi=n32
  @opindex mabi=64
  @opindex mabi=eabi
! @opindex mabi=meabi
! Generate code for the indicated ABI@.  Not all configurations support
! this option.
! 
! If your configuration generates MIPS I or MIPS II code by default,
! selecting @samp{o64}, @samp{n32} or @samp{64} will switch to
! MIPS III code.  If it generates MIPS 32 code by default, the same
! options will switch to MIPS 64 code.  You can override this behavior
! using the options @samp{-mips@var{N}} or @samp{-march}.
! 
! Note that there are two embedded ABIs: @samp{-mabi=eabi}
! selects the one defined by Cygnus while @samp{-meabi=meabi}
! selects the one defined by MIPS@.
  
  @item -mmips-as
  @opindex mmips-as
Index: toplev.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.h,v
retrieving revision 1.87
diff -c -d -p -r1.87 toplev.h
*** toplev.h	5 Jun 2002 19:35:32 -0000	1.87
--- toplev.h	12 Jul 2002 15:47:52 -0000
*************** extern void check_global_declarations   
*** 108,113 ****
--- 108,114 ----
  
  extern const char *progname;
  extern const char *dump_base_name;
+ extern int target_flags_explicit;
  
  /* The hashtable, so that the C front ends can pass it to cpplib.  */
  extern struct ht *ident_hash;
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.656
diff -c -d -p -r1.656 toplev.c
*** toplev.c	7 Jul 2002 22:10:17 -0000	1.656
--- toplev.c	12 Jul 2002 15:47:52 -0000
*************** const char *dump_base_name;
*** 178,183 ****
--- 178,188 ----
  
  extern int target_flags;
  
+ /* A mask of target_flags that includes bit X if X was specified
+    explicitly on the command line.  */
+ 
+ int target_flags_explicit;
+ 
  /* Debug hooks - dependent upon command line options.  */
  
  const struct gcc_debug_hooks *debug_hooks = &do_nothing_debug_hooks;
*************** set_target_switch (name)
*** 4361,4366 ****
--- 4366,4378 ----
  	  target_flags &= ~-target_switches[j].value;
  	else
  	  target_flags |= target_switches[j].value;
+ 	if (name[0] != 0)
+ 	  {
+ 	    if (target_switches[j].value < 0)
+ 	      target_flags_explicit |= -target_switches[j].value;
+ 	    else
+ 	      target_flags_explicit |= target_switches[j].value;
+ 	  }
  	valid_target_option = 1;
        }
  
Index: config/mips/isa3264.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/isa3264.h,v
retrieving revision 1.5
diff -c -d -p -r1.5 isa3264.h
*** config/mips/isa3264.h	17 Jan 2002 07:53:55 -0000	1.5
--- config/mips/isa3264.h	12 Jul 2002 15:47:52 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 27,36 ****
  #define MIPS_ABI_DEFAULT ABI_MEABI
  #endif
  
- #ifndef MIPS_ENABLE_EMBEDDED_O32
- #define MIPS_ENABLE_EMBEDDED_O32 1
- #endif
- 
  #ifndef PREFERRED_DEBUGGING_TYPE
  #define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
  #endif
--- 27,32 ----
Index: config/mips/elforion.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/elforion.h,v
retrieving revision 1.2
diff -c -d -p -r1.2 elforion.h
*** config/mips/elforion.h	16 Dec 1998 21:09:02 -0000	1.2
--- config/mips/elforion.h	12 Jul 2002 15:47:52 -0000
*************** along with GNU CC; see the file COPYING.
*** 19,22 ****
  the Free Software Foundation, 59 Temple Place - Suite 330,
  Boston, MA 02111-1307, USA.  */
  
! #define MIPS_CPU_STRING_DEFAULT "orion"
--- 19,22 ----
  the Free Software Foundation, 59 Temple Place - Suite 330,
  Boston, MA 02111-1307, USA.  */
  
! #define MIPS_CPU_DEFAULT PROCESSOR_4600
Index: config/mips/iris6.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/iris6.h,v
retrieving revision 1.50
diff -c -d -p -r1.50 iris6.h
*** config/mips/iris6.h	11 Jul 2002 18:56:56 -0000	1.50
--- config/mips/iris6.h	12 Jul 2002 15:47:52 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 238,244 ****
     on the mipsX option.  */
  /* If no mips[3,4] option given, give the appropriate default for mabi=X */
  #undef SUBTARGET_ASM_SPEC
! #define SUBTARGET_ASM_SPEC "%{!mabi*:-n32} %{!mips*: %{!mabi*:-mips3} %{mabi=n32:-mips3} %{mabi=64:-mips4}}"
  
  /* Must pass -g0 to the assembler, otherwise it may overwrite our
     debug info with its own debug info.  */
--- 238,244 ----
     on the mipsX option.  */
  /* If no mips[3,4] option given, give the appropriate default for mabi=X */
  #undef SUBTARGET_ASM_SPEC
! #define SUBTARGET_ASM_SPEC "%{!mabi*:-n32} %{!mips*: %{!mabi*:-mips3} %{mabi=n32|mabi=64:-mips3}}"
  
  /* Must pass -g0 to the assembler, otherwise it may overwrite our
     debug info with its own debug info.  */
Index: config/mips/r3900.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/r3900.h,v
retrieving revision 1.14
diff -c -d -p -r1.14 r3900.h
*** config/mips/r3900.h	13 Jun 2002 10:14:12 -0000	1.14
--- config/mips/r3900.h	12 Jul 2002 15:47:52 -0000
*************** along with GNU CC; see the file COPYING.
*** 22,28 ****
  the Free Software Foundation, 59 Temple Place - Suite 330,
  Boston, MA 02111-1307, USA.  */
  
! #define MIPS_CPU_STRING_DEFAULT "r3900"
  #define MIPS_ISA_DEFAULT 1
  
  #define MULTILIB_DEFAULTS { MULTILIB_ENDIAN_DEFAULT, "msoft-float" }
--- 22,28 ----
  the Free Software Foundation, 59 Temple Place - Suite 330,
  Boston, MA 02111-1307, USA.  */
  
! #define MIPS_CPU_DEFAULT PROCESSOR_R3900
  #define MIPS_ISA_DEFAULT 1
  
  #define MULTILIB_DEFAULTS { MULTILIB_ENDIAN_DEFAULT, "msoft-float" }
Index: config/mips/mips.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.h,v
retrieving revision 1.197
diff -c -d -p -r1.197 mips.h
*** config/mips/mips.h	11 Jul 2002 18:56:56 -0000	1.197
--- config/mips/mips.h	12 Jul 2002 15:47:52 -0000
*************** enum delay_type {
*** 54,60 ****
  /* Which processor to schedule for.  Since there is no difference between
     a R2000 and R3000 in terms of the scheduler, we collapse them into
     just an R3000.  The elements of the enumeration must match exactly
!    the cpu attribute in the mips.md machine description.  */
  
  enum processor_type {
    PROCESSOR_DEFAULT,
--- 54,61 ----
  /* Which processor to schedule for.  Since there is no difference between
     a R2000 and R3000 in terms of the scheduler, we collapse them into
     just an R3000.  The elements of the enumeration must match exactly
!    the cpu attribute in the mips.md machine description and mips_processors[]
!    in mips.c.  */
  
  enum processor_type {
    PROCESSOR_DEFAULT,
*************** extern int mips_isa;			/* architectural 
*** 146,160 ****
  extern int mips16;			/* whether generating mips16 code */
  extern int mips16_hard_float;		/* mips16 without -msoft-float */
  extern int mips_entry;			/* generate entry/exit for mips16 */
- extern const char *mips_cpu_string;	/* for -mcpu=<xxx> */
  extern const char *mips_arch_string;    /* for -march=<xxx> */
  extern const char *mips_tune_string;    /* for -mtune=<xxx> */
  extern const char *mips_isa_string;	/* for -mips{1,2,3,4} */
  extern const char *mips_abi_string;	/* for -mabi={32,n32,64} */
  extern const char *mips_entry_string;	/* for -mentry */
  extern const char *mips_no_mips16_string;/* for -mno-mips16 */
- extern const char *mips_explicit_type_size_string;/* for -mexplicit-type-size */
  extern const char *mips_cache_flush_func;/* for -mflush-func= and -mno-flush-func */
  extern int mips_split_addresses;	/* perform high/lo_sum support */
  extern int dslots_load_total;		/* total # load related delay slots */
  extern int dslots_load_filled;		/* # filled load delay slots */
--- 147,160 ----
  extern int mips16;			/* whether generating mips16 code */
  extern int mips16_hard_float;		/* mips16 without -msoft-float */
  extern int mips_entry;			/* generate entry/exit for mips16 */
  extern const char *mips_arch_string;    /* for -march=<xxx> */
  extern const char *mips_tune_string;    /* for -mtune=<xxx> */
  extern const char *mips_isa_string;	/* for -mips{1,2,3,4} */
  extern const char *mips_abi_string;	/* for -mabi={32,n32,64} */
  extern const char *mips_entry_string;	/* for -mentry */
  extern const char *mips_no_mips16_string;/* for -mno-mips16 */
  extern const char *mips_cache_flush_func;/* for -mflush-func= and -mno-flush-func */
+ extern const char *mips_cpp_processor_macro;
  extern int mips_split_addresses;	/* perform high/lo_sum support */
  extern int dslots_load_total;		/* total # load related delay slots */
  extern int dslots_load_filled;		/* # filled load delay slots */
*************** extern void		sbss_section PARAMS ((void)
*** 358,375 ****
  	  builtin_define ("mips");				\
  								\
        if (TARGET_64BIT)						\
! 	{							\
! 	  builtin_define ("__mips64");     			\
! 	  /* Silly, but will do until processor defines.  */	\
! 	  builtin_define_std ("R4000");				\
! 	  builtin_define ("_R4000");				\
! 	}							\
!       else							\
! 	{							\
! 	  /* Ditto.  */						\
! 	  builtin_define_std ("R3000");				\
! 	  builtin_define ("_R3000");				\
! 	}							\
        if (TARGET_FLOAT64)					\
  	  builtin_define ("__mips_fpr=64");			\
        else							\
--- 358,365 ----
  	  builtin_define ("mips");				\
  								\
        if (TARGET_64BIT)						\
! 	builtin_define ("__mips64");     			\
! 								\
        if (TARGET_FLOAT64)					\
  	  builtin_define ("__mips_fpr=64");			\
        else							\
*************** extern void		sbss_section PARAMS ((void)
*** 378,383 ****
--- 368,376 ----
        if (TARGET_MIPS16)					\
  	  builtin_define ("__mips16");				\
  								\
+       builtin_define_std (&mips_cpp_processor_macro[1]);	\
+       builtin_define (mips_cpp_processor_macro);		\
+ 								\
        if (ISA_MIPS1)						\
  	{							\
  	  builtin_define ("__mips=1");				\
*************** extern void		sbss_section PARAMS ((void)
*** 679,686 ****
  #define TARGET_OPTIONS							\
  {									\
    SUBTARGET_TARGET_OPTIONS						\
-   { "cpu=",	&mips_cpu_string,					\
-       N_("Specify CPU for scheduling purposes")},			\
    { "tune=",    &mips_tune_string,			                \
        N_("Specify CPU for scheduling purposes")},                       \
    { "arch=",    &mips_arch_string,                                      \
--- 672,677 ----
*************** extern void		sbss_section PARAMS ((void)
*** 691,698 ****
        N_("Use mips16 entry/exit psuedo ops")},				\
    { "no-mips16", &mips_no_mips16_string,				\
        N_("Don't use MIPS16 instructions")},				\
-   { "explicit-type-size", &mips_explicit_type_size_string,		\
-       NULL},								\
    { "no-flush-func", &mips_cache_flush_func,				\
        N_("Don't call any cache flush functions")},			\
    { "flush-func=", &mips_cache_flush_func,				\
--- 682,687 ----
*************** extern void		sbss_section PARAMS ((void)
*** 720,725 ****
--- 709,724 ----
  #define BRANCH_LIKELY_P()	GENERATE_BRANCHLIKELY
  #define HAVE_SQRT_P()		(!ISA_MIPS1)
  
+ /* True if the ABI can only work with 64-bit integer registers.  We
+    generally allow ad-hoc variations for TARGET_SINGLE_FLOAT, but
+    otherwise floating-point registers must also be 64-bit.  */
+ #define ABI_NEEDS_64BIT_REGS	(mips_abi == ABI_64			\
+ 				 || mips_abi == ABI_O64			\
+ 				 || mips_abi == ABI_N32)
+ 
+ /* Likewise for 32-bit regs.  */
+ #define ABI_NEEDS_32BIT_REGS	(mips_abi == ABI_32)
+ 
  /* ISA has instructions for managing 64 bit fp and gp regs (eg. mips3).  */
  #define ISA_HAS_64BIT_REGS	(ISA_MIPS3				\
  				 || ISA_MIPS4				\
*************** while (0)
*** 910,916 ****
  /* GAS_ASM_SPEC is passed when using gas, rather than the MIPS
     assembler.  */
  
! #define GAS_ASM_SPEC "%{march=*} %{mtune=*} %{mcpu=*} %{m4650} %{mmad:-m4650} %{m3900} %{v} %{mgp32} %{mgp64} %(abi_gas_asm_spec) %{mabi=32:%{!mips*:-mips1}}"
  
  
  extern int mips_abi;
--- 909,915 ----
  /* GAS_ASM_SPEC is passed when using gas, rather than the MIPS
     assembler.  */
  
! #define GAS_ASM_SPEC "%{march=*} %{mtune=*} %{mcpu=*} %{m4650} %{mmad:-m4650} %{m3900} %{v} %{mgp32} %{mgp64} %(abi_gas_asm_spec)"
  
  
  extern int mips_abi;
*************** extern int mips_abi;
*** 1048,1062 ****
  #ifndef CC1_SPEC
  #define CC1_SPEC "\
  %{gline:%{!g:%{!g0:%{!g1:%{!g2: -g1}}}}} \
- %{mips1:-mfp32 -mgp32} %{mips2:-mfp32 -mgp32}\
- %{mips3:%{!msingle-float:%{!m4650:-mfp64}} -mgp64} \
- %{mips4:%{!msingle-float:%{!m4650:-mfp64}} -mgp64} \
- %{mips32:-mfp32 -mgp32} \
- %{mips64:%{!msingle-float:-mfp64} -mgp64} \
- %{mfp64:%{msingle-float:%emay not use both -mfp64 and -msingle-float}} \
- %{mfp64:%{m4650:%emay not use both -mfp64 and -m4650}} \
- %{mint64|mlong64|mlong32:-mexplicit-type-size }\
- %{mgp32: %{mfp64:%emay not use both -mgp32 and -mfp64} %{!mfp32: -mfp32}} \
  %{G*} %{EB:-meb} %{EL:-mel} %{EB:%{EL:%emay not use both -EB and -EL}} \
  %{save-temps: } \
  %(subtarget_cc1_spec)"
--- 1047,1052 ----
Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.214
diff -c -d -p -r1.214 mips.c
*** config/mips/mips.c	11 Jul 2002 18:56:56 -0000	1.214
--- config/mips/mips.c	12 Jul 2002 15:47:53 -0000
*************** static int symbolic_expression_p        
*** 119,125 ****
  static bool mips_assemble_integer	  PARAMS ((rtx, unsigned int, int));
  static void mips_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
  static void mips_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
! static enum processor_type mips_parse_cpu       PARAMS ((const char *));
  static void copy_file_data			PARAMS ((FILE *, FILE *));
  #ifdef TARGET_IRIX6
  static void iris6_asm_named_section_1		PARAMS ((const char *,
--- 119,133 ----
  static bool mips_assemble_integer	  PARAMS ((rtx, unsigned int, int));
  static void mips_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
  static void mips_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
! static void mips_set_architecture		PARAMS ((enum processor_type,
! 							 int));
! static bool mips_strict_matching_cpu_name_p	PARAMS ((const char *,
! 							 const char *));
! static bool mips_matching_cpu_name_p		PARAMS ((const char *,
! 							 const char *));
! static enum processor_type mips_parse_cpu       PARAMS ((const char *,
! 							 const char *));
! static enum processor_type mips_cpu_from_isa_level PARAMS ((int));
  static void copy_file_data			PARAMS ((FILE *, FILE *));
  #ifdef TARGET_IRIX6
  static void iris6_asm_named_section_1		PARAMS ((const char *,
*************** enum cmp_type branch_type;
*** 295,300 ****
--- 303,311 ----
  /* The target cpu for code generation.  */
  enum processor_type mips_arch;
  
+ /* True if the user selected the architecture on the command line.  */
+ static bool user_selected_mips_arch_p;
+ 
  /* The target cpu for optimization and scheduling.  */
  enum processor_type mips_tune;
  
*************** int mips_isa;
*** 305,316 ****
  int mips_abi;
  
  /* Strings to hold which cpu and instruction set architecture to use.  */
- const char *mips_cpu_string;	/* for -mcpu=<xxx> */
  const char *mips_arch_string;   /* for -march=<xxx> */
  const char *mips_tune_string;   /* for -mtune=<xxx> */
  const char *mips_isa_string;	/* for -mips{1,2,3,4} */
  const char *mips_abi_string;	/* for -mabi={32,n32,64,eabi} */
  
  /* Whether we are generating mips16 code.  This is a synonym for
     TARGET_MIPS16, and exists for use as an attribute.  */
  int mips16;
--- 316,329 ----
  int mips_abi;
  
  /* Strings to hold which cpu and instruction set architecture to use.  */
  const char *mips_arch_string;   /* for -march=<xxx> */
  const char *mips_tune_string;   /* for -mtune=<xxx> */
  const char *mips_isa_string;	/* for -mips{1,2,3,4} */
  const char *mips_abi_string;	/* for -mabi={32,n32,64,eabi} */
  
+ /* The name of target processor, with a leading underscore.  */
+ const char *mips_cpp_processor_macro;
+ 
  /* Whether we are generating mips16 code.  This is a synonym for
     TARGET_MIPS16, and exists for use as an attribute.  */
  int mips16;
*************** int mips16;
*** 320,330 ****
     just a way to avoid using up another bit in target_flags.  */
  const char *mips_no_mips16_string;
  
- /* This is only used to determine if an type size setting option was
-    explicitly specified (-mlong64, -mint64, -mlong32).  The specs
-    set this option if such an option is used.  */
- const char *mips_explicit_type_size_string;
- 
  /* Whether we are generating mips16 hard float code.  In mips16 mode
     we always set TARGET_SOFT_FLOAT; this variable is nonzero if
     -msoft-float was not specified by the user, which means that we
--- 333,338 ----
*************** enum reg_class mips_char_to_class[256] =
*** 562,567 ****
--- 570,613 ----
    NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,
  };
  
+ /* Information about one member of enum processor_type.  */
+ struct mips_processor {
+   /* The name of the processor, in lower case.  If the processor is
+      a recognised member of the NEC VR range, the name should start
+      with 'vr', otherwise it typically starts with 'r'.  */
+   const char *name;
+ 
+   /* The preprocessor macro that should be defined when generating
+      code for this processor.  It typically starts with "_R", followed
+      by the numerical designation.  We also define the macro with two
+      leading underscores, and sometimes with none.  */
+   const char *cpp_macro;
+ 
+   /* The ISA level most closely associated with the processor.
+      Sometimes the processor has extra instructions that aren't
+      defined at this ISA level.  Sometimes the ISA level defines
+      instructions that the processor doesn't implement.  */
+   int isa_level;
+ };
+ 
+ /* This array must have the same order as enum processor_type.  */
+ static const struct mips_processor mips_processors[] = {
+   { "default", 0, 1 },
+   { "r3000", "_R3000", 1 },
+   { "r3900", "_R3900", 1 },
+   { "r6000", "_R6000", 2 },
+   { "r4000", "_R4000", 3 },
+   { "vr4100", "_R4100", 3 },
+   { "vr4300", "_R4300", 3 },
+   { "r4600", "_R4600", 3 },
+   { "r4650", "_R4650", 3 },
+   { "vr5000", "_R5000", 4 },
+   { "r8000", "_R8000", 4 },
+   { "r4kc", "_R4KC", 32 },
+   { "r5kc", "_R5KC", 64 },
+   { "r20kc", "_R20KC", 64 }
+ };
+ 
  /* Initialize the GCC target structure.  */
  #undef TARGET_ASM_ALIGNED_HI_OP
  #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
*************** abort_with_insn (insn, reason)
*** 4976,4991 ****
    abort ();
  }
  
  /* Set up the threshold for data to go into the small data area, instead
     of the normal data area, and detect any conflicts in the switches.  */
  
  void
  override_options ()
  {
!   register int i, start;
!   register int regno;
!   register enum machine_mode mode;
!   register enum processor_type mips_cpu;
  
    mips_section_threshold = g_switch_set ? g_switch_value : MIPS_DEFAULT_GVALUE;
  
--- 5022,5053 ----
    abort ();
  }
  
+ /* Set up globals to generate code for ARCH.  USER_SELECTED_P is true
+    if the user selected this architecture explicitly.  */
+ 
+ static void
+ mips_set_architecture (arch, user_selected_p)
+      enum processor_type arch;
+      int user_selected_p;
+ {
+   if (arch != PROCESSOR_DEFAULT)
+     {
+       mips_arch = arch;
+       mips_isa = mips_processors[arch].isa_level;
+       mips_cpp_processor_macro = mips_processors[arch].cpp_macro;
+       user_selected_mips_arch_p = user_selected_p;
+     }
+ }
+ 
+ 
  /* Set up the threshold for data to go into the small data area, instead
     of the normal data area, and detect any conflicts in the switches.  */
  
  void
  override_options ()
  {
!   int i, start, regno;
!   enum machine_mode mode;
  
    mips_section_threshold = g_switch_set ? g_switch_value : MIPS_DEFAULT_GVALUE;
  
*************** override_options ()
*** 5003,5252 ****
      target_flags &= ~((TARGET_DEFAULT) & (MASK_SOFT_FLOAT | MASK_SINGLE_FLOAT));
  #endif
  
!   /* Get the architectural level.  */
!   if (mips_isa_string == 0)
!     mips_isa = MIPS_ISA_DEFAULT;
  
!   else if (mips_isa_string != 0
! 	   && mips_arch_string != 0)
!       warning ("The -march option is incompatible to -mipsN and therefore ignored.");
  
!   else if (ISDIGIT (*mips_isa_string))
      {
!       mips_isa = atoi (mips_isa_string);
!       if (mips_isa == 16)
  	{
! 	  /* -mno-mips16 overrides -mips16.  */
  	  if (mips_no_mips16_string == NULL)
! 	    {
! 	      target_flags |= MASK_MIPS16;
! 	      if (TARGET_64BIT)
! 		mips_isa = 3;
! 	      else
! 		mips_isa = MIPS_ISA_DEFAULT;
! 	    }
! 	  else
! 	    {
! 	      mips_isa = MIPS_ISA_DEFAULT;
! 	    }
  	}
!       else if (mips_isa < 1
! 	       || (mips_isa > 4
! 		   && mips_isa != 32
! 		   && mips_isa != 64))
  	{
! 	  error ("-mips%d not supported", mips_isa);
! 	  mips_isa = 1;
  	}
      }
  
!   else
!     {
!       error ("bad value (%s) for -mips switch", mips_isa_string);
!       mips_isa = 1;
!     }
! 
! #ifdef MIPS_ABI_DEFAULT
!   /* Get the ABI to use.  */
!   if (mips_abi_string == (char *) 0)
!     mips_abi = MIPS_ABI_DEFAULT;
!   else if (! strcmp (mips_abi_string, "32"))
!     mips_abi = ABI_32;
!   else if (! strcmp (mips_abi_string, "o64"))
!     mips_abi = ABI_O64;
!   else if (! strcmp (mips_abi_string, "n32"))
!     mips_abi = ABI_N32;
!   else if (! strcmp (mips_abi_string, "64"))
!     mips_abi = ABI_64;
!   else if (! strcmp (mips_abi_string, "eabi"))
!     mips_abi = ABI_EABI;
!   else if (! strcmp (mips_abi_string, "meabi"))
!     mips_abi = ABI_MEABI;
!   else
!     error ("bad value (%s) for -mabi= switch", mips_abi_string);
! 
!   /* A specified ISA defaults the ABI if it was not specified.  */
!   if (mips_abi_string == 0 && mips_isa_string
!       && mips_abi != ABI_EABI
!       && mips_abi != ABI_O64
!       && mips_abi != ABI_MEABI)
      {
!       if (mips_isa == 64)
  	mips_abi = ABI_O64;
        else
  	{
! 	  if (! ISA_HAS_64BIT_REGS)
! 	    mips_abi = ABI_32;
! 	  else if (mips_abi != ABI_N32)
! 	    mips_abi = ABI_64;
  	}
      }
! 
! #ifdef MIPS_CPU_STRING_DEFAULT
!   /* A specified ABI defaults the ISA if it was not specified.  */
!   else if (mips_isa_string == 0 && mips_abi_string
! 	   && mips_abi != ABI_EABI && mips_abi != ABI_O64)
      {
!       if (mips_abi == ABI_32)
! 	mips_isa = 1;
!       else if (mips_abi == ABI_N32)
! 	mips_isa = 3;
!       else
! 	mips_isa = 4;
      }
! #endif
! 
!   /* If both ABI and ISA were specified, check for conflicts.  */
!   else if (mips_isa_string && mips_abi_string)
      {
!       if (! ISA_HAS_64BIT_REGS && (mips_abi == ABI_N32 || mips_abi == ABI_64
! 			     || mips_abi == ABI_O64))
! 	error ("-mabi=%s does not support -mips%d", mips_abi_string, mips_isa);
      }
  
!   /* Override TARGET_DEFAULT if necessary.  */
!   if (mips_abi == ABI_32)
!     target_flags &= ~ (MASK_FLOAT64|MASK_64BIT);
! 
!   /* If no type size setting options (-mlong64,-mint64,-mlong32) were used
!      then set the type sizes.  In the EABI in 64 bit mode, longs and
!      pointers are 64 bits.  Likewise for the SGI Irix6 N64 ABI.  */
!   if (mips_explicit_type_size_string == NULL
!       && ((mips_abi == ABI_EABI && TARGET_64BIT)
! 	  || mips_abi == ABI_64))
!     target_flags |= MASK_LONG64;
! 
! #else
!   if (mips_abi_string)
!     error ("this target does not support the -mabi switch");
! #endif
  
! #ifdef MIPS_CPU_STRING_DEFAULT
!   /* ??? There is a minor inconsistency here.  If the user specifies an ISA
!      greater than that supported by the default processor, then the user gets
!      an error.  Normally, the compiler will just default to the base level cpu
!      for the indicated isa.  */
    if (mips_arch_string == 0)
!     mips_arch_string = MIPS_CPU_STRING_DEFAULT;
!   if (mips_tune_string == 0)
!     mips_tune_string = MIPS_CPU_STRING_DEFAULT;
! #endif
! 
!   /* Identify the processor type.  */
  
!   if (mips_cpu_string != 0)
      {
!       mips_cpu = mips_parse_cpu (mips_cpu_string);
!       if (mips_cpu == PROCESSOR_DEFAULT)
! 	{
! 	  error ("bad value (%s) for -mcpu= switch", mips_cpu_string);
! 	  mips_cpu_string = "default";
! 	}
!       mips_arch = mips_cpu;
!       mips_tune = mips_cpu;
      }
  
!   if (mips_arch_string == 0
!       || ! strcmp (mips_arch_string, "default")
!       || ! strcmp (mips_arch_string, "DEFAULT"))
      {
!       switch (mips_isa)
! 	{
! 	default:
! 	  mips_arch_string = "3000";
! 	  mips_arch = PROCESSOR_R3000;
! 	  break;
! 	case 2:
! 	  mips_arch_string = "6000";
! 	  mips_arch = PROCESSOR_R6000;
! 	  break;
! 	case 3:
! 	  mips_arch_string = "4000";
! 	  mips_arch = PROCESSOR_R4000;
! 	  break;
! 	case 4:
! 	  mips_arch_string = "8000";
! 	  mips_arch = PROCESSOR_R8000;
! 	  break;
! 	case 32:
!           mips_arch_string = "4kc";
!           mips_arch = PROCESSOR_R4KC;
!           break;
!         case 64:
!           mips_arch_string = "5kc";
!           mips_arch = PROCESSOR_R5KC;
!           break;
! 	}
      }
    else
      {
!       mips_arch = mips_parse_cpu (mips_arch_string);
!       if (mips_arch == PROCESSOR_DEFAULT)
! 	{
! 	  error ("bad value (%s) for -march= switch", mips_arch_string);
! 	  mips_arch_string = "default";
! 	}
!     }
!   if (mips_tune_string == 0
!       || ! strcmp (mips_tune_string, "default")
!       || ! strcmp (mips_tune_string, "DEFAULT"))
!     {
!       if (mips_arch != PROCESSOR_DEFAULT)
! 	mips_tune = mips_arch;
        else
!       switch (mips_isa)
! 	{
! 	default:
! 	  mips_tune_string = "3000";
! 	  mips_tune = PROCESSOR_R3000;
! 	  break;
! 	case 2:
! 	  mips_tune_string = "6000";
! 	  mips_tune = PROCESSOR_R6000;
! 	  break;
! 	case 3:
! 	  mips_tune_string = "4000";
! 	  mips_tune = PROCESSOR_R4000;
! 	  break;
! 	case 4:
! 	  mips_tune_string = "8000";
! 	  mips_tune = PROCESSOR_R8000;
! 	  break;
! 	case 32:
! 	  mips_tune_string = "4kc";
! 	  mips_tune = PROCESSOR_R4KC;
! 	  break;
! 	case 64:
! 	  mips_tune_string = "5kc";
! 	  mips_tune = PROCESSOR_R5KC;
! 	  break;
! 	}
  
      }
    else
      {
!        mips_tune = mips_parse_cpu (mips_tune_string);
!       if (mips_tune == PROCESSOR_DEFAULT)
! 	{
! 	  error ("bad value (%s) for -mtune= switch", mips_tune_string);
! 	  mips_tune_string = "default";
! 	}
      }
  
!   /* make sure sizes of ints/longs/etc. are ok */
!   if (! ISA_HAS_64BIT_REGS)
!     {
!       if (TARGET_FLOAT64)
! 	{
! 	  error ("-mips%d does not support 64 bit fp registers", mips_isa);
! 	  target_flags &= ~ MASK_FLOAT64;
! 	}
  
!       else if (TARGET_64BIT)
! 	{
! 	  error ("-mips%d does not support 64 bit gp registers", mips_isa);
! 	  target_flags &= ~MASK_64BIT;
! 	}
      }
  
    if (mips_abi != ABI_32 && mips_abi != ABI_O64)
--- 5065,5246 ----
      target_flags &= ~((TARGET_DEFAULT) & (MASK_SOFT_FLOAT | MASK_SINGLE_FLOAT));
  #endif
  
!   /* The following code determines the architecture, ABI and register size.
!      Much of the complexity is in infering complete information when some
!      flags are not given.  Some of the details are historical.
  
!      Similar code was added to GAS 2.14 (see tc-mips.c:md_after_parse_args()).
!      The GAS and GCC code should be kept in sync as much as possible.  */
  
!   /* First select the default architecture.  */
! #ifdef MIPS_CPU_DEFAULT
!   mips_set_architecture (MIPS_CPU_DEFAULT, false);
! #else
!   mips_set_architecture (mips_cpu_from_isa_level (MIPS_ISA_DEFAULT), false);
! #endif
! 
!   /* -march is more descriptive than -mipsN, so check it first.  */
!   if (mips_arch_string != 0)
!     mips_set_architecture (mips_parse_cpu ("-march", mips_arch_string), true);
! 
!   if (mips_isa_string != 0)
      {
!       int level = atoi (mips_isa_string);
!       if (level == 16)
  	{
! 	  /* -mips16 specifies an ASE rather than a processor, so don't
! 	     change mips_arch here.  -mno-mips16 overrides -mips16.  */
  	  if (mips_no_mips16_string == NULL)
! 	    target_flags |= MASK_MIPS16;
  	}
!       else if (user_selected_mips_arch_p)
  	{
! 	  /* The user specified both -mipsN and -march.  There's no
! 	     harm in it if the two arguments agree, just as there's
! 	     no harm in giving redundant register size options.  Only
! 	     complain if the arguments contradict one another.  */
! 	  if (mips_isa != level)
! 	    error ("-mips%d conflicts with the other architecture options, which specify a MIPS%d processor",
! 		   level, mips_isa);
! 	}
!       else
! 	{
! 	  /* -mipsN selects the base-line processor for ISA level N.  */
! 	  mips_set_architecture (mips_cpu_from_isa_level (level), true);
! 	  if (!user_selected_mips_arch_p)
! 	    error ("bad value (%s) for -mips switch", mips_isa_string);
  	}
      }
  
!   mips_abi = MIPS_ABI_DEFAULT;
!   if (mips_abi_string != 0)
      {
!       /* Interpret -mabi.  */
!       if (strcmp (mips_abi_string, "32") == 0)
! 	mips_abi = ABI_32;
!       else if (strcmp (mips_abi_string, "o64") == 0)
  	mips_abi = ABI_O64;
+       else if (strcmp (mips_abi_string, "n32") == 0)
+ 	mips_abi = ABI_N32;
+       else if (strcmp (mips_abi_string, "64") == 0)
+ 	mips_abi = ABI_64;
+       else if (strcmp (mips_abi_string, "eabi") == 0)
+ 	mips_abi = ABI_EABI;
+       else if (strcmp (mips_abi_string, "meabi") == 0)
+ 	mips_abi = ABI_MEABI;
        else
+ 	error ("bad value (%s) for -mabi= switch", mips_abi_string);
+ 
+       if (ABI_NEEDS_64BIT_REGS && !ISA_HAS_64BIT_REGS)
  	{
! 	  if (user_selected_mips_arch_p)
! 	    error ("-mabi=%s used with a 32-bit processor", mips_abi_string);
! 	  else
! 	    {
! 	      /* The user specified an ABI but not an ISA.  The ABI needs
! 		 64-bit registers, but the default architecture is 32-bit.
! 		 GCC has historically "upgraded" to a 64-bit ISA.  */
! 	      int level = (mips_isa == 32 ? 64 : 3);
! 	      mips_set_architecture (mips_cpu_from_isa_level (level), false);
! 	    }
  	}
      }
!   else if ((target_flags_explicit & MASK_64BIT) != 0 && !TARGET_64BIT)
      {
!       /* The user didn't specify an ABI, but used -mgp32.
! 	 Force a 32-bit ABI.  */
!       if (ABI_NEEDS_64BIT_REGS)
! 	mips_abi = ABI_32;
      }
!   else if (user_selected_mips_arch_p)
      {
!       /* The user specified a processor but not an ABI.  We've already
! 	 handled the -mgp32 case, so either the register size was not
! 	 specified explicitly, or it is expected to match the processor's.
! 	 If the processor's register size doesn't match the ABI, switch
! 	 to another ABI.  */
!       if (!ISA_HAS_64BIT_REGS && ABI_NEEDS_64BIT_REGS)
! 	mips_abi = ABI_32;
!       else if (ISA_HAS_64BIT_REGS && ABI_NEEDS_32BIT_REGS)
! 	mips_abi = ABI_O64;
      }
  
!   /* At this point, we know the architecture and ABI.  We've also
!      avoided the case that ABI_NEEDS_64BIT_REGS && !ISA_HAS_64BIT_REGS,
!      unless the user selected it explicitly, in which case we've
!      complained.  */
  
!   /* Make sure we have an architecture name.  Prefer to use the
!      argument to -march, if given, since it's what the user might
!      expect to see in error messages.  Otherwise use the canonical
!      name for this architecture.  */
    if (mips_arch_string == 0)
!     mips_arch_string = mips_processors[mips_arch].name;
  
!   /* Optimize for mips_arch, unless -mtune selects a different processor.  */
!   if (mips_tune_string == 0)
      {
!       mips_tune = mips_arch;
!       mips_tune_string = mips_arch_string;
      }
+   else
+     mips_tune = mips_parse_cpu ("-mtune", mips_tune_string);
  
!   if ((target_flags_explicit & MASK_64BIT) != 0)
      {
!       /* The user specified the size of the integer registers.  Make sure
! 	 it agrees with the ABI and ISA.  */
!       if (TARGET_64BIT && !ISA_HAS_64BIT_REGS)
! 	error ("-mgp64 used with a 32-bit processor");
!       else if (!TARGET_64BIT && ABI_NEEDS_64BIT_REGS)
! 	error ("-mgp32 used with a 64-bit ABI");
!       else if (TARGET_64BIT && ABI_NEEDS_32BIT_REGS)
! 	error ("-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.  */
!       if (ABI_NEEDS_32BIT_REGS || !ISA_HAS_64BIT_REGS)
! 	target_flags &= ~MASK_64BIT;
        else
! 	target_flags |= MASK_64BIT;
!     }
  
+   if ((target_flags_explicit & MASK_FLOAT64) != 0)
+     {
+       /* Really, -mfp32 and -mfp64 are ornamental options.  There's
+ 	 only one right answer here.  */
+       if (TARGET_64BIT && TARGET_DOUBLE_FLOAT && !TARGET_FLOAT64)
+ 	error ("unsupported combination: %s", "-mgp64 -mfp32 -mdouble-float");
+       else if (!TARGET_64BIT && TARGET_FLOAT64)
+ 	error ("unsupported combination: %s", "-mgp32 -mfp64");
+       else if (TARGET_SINGLE_FLOAT && TARGET_FLOAT64)
+ 	error ("unsupported combination: %s", "-mfp64 -msingle-float");
      }
    else
      {
!       /* -msingle-float selects 32-bit float registers.  Otherwise the
! 	 float registers should be the same size as the integer ones.  */
!       if (TARGET_64BIT && TARGET_DOUBLE_FLOAT)
! 	target_flags |= MASK_FLOAT64;
!       else
! 	target_flags &= ~MASK_FLOAT64;
      }
  
!   /* End of code shared with GAS.  */
  
!   if ((target_flags_explicit & MASK_LONG64) == 0)
!     {
!       /* If no type size setting options (-mlong64,-mint64,-mlong32)
! 	 were used, then set the type sizes.  In the EABI in 64 bit mode,
! 	 longs and pointers are 64 bits.  Likewise for the SGI Irix6 N64
! 	 ABI.  */
!       if ((mips_abi == ABI_EABI && TARGET_64BIT) || mips_abi == ABI_64)
! 	target_flags |= MASK_LONG64;
!       else
! 	target_flags &= ~MASK_LONG64;
      }
  
    if (mips_abi != ABI_32 && mips_abi != ABI_O64)
*************** mips_output_conditional_branch (insn,
*** 10166,10280 ****
    /* NOTREACHED */
    return 0;
  }
  
! static enum processor_type
! mips_parse_cpu (cpu_string)
!      const char *cpu_string;
  {
!   const char *p = cpu_string;
!   int seen_v = 0;
!   enum processor_type cpu;
!   int warn_upper_case = 0;
  
!   /* We need to cope with the various "vr" prefixes for the NEC 4300
!      and 4100 processors.  */
!   if (*p == 'v' || *p == 'V')
!     {
!       if (*p == 'V')
! 	warn_upper_case = 1;
!       seen_v = 1, p++;
!     }
  
-   if (*p == 'r' || *p == 'R')
-     {
-       if (*p == 'R')
- 	warn_upper_case = 1;
-       p++;
-     }
  
!   if (warn_upper_case)
!     warning ("the cpu name must be lower case");
  
!   /* Since there is no difference between a R2000 and R3000 in
!      terms of the scheduler, we collapse them into just an R3000.  */
  
!   cpu = PROCESSOR_DEFAULT;
!   switch (*p)
!     {
!     case '2':
!       if (!strcmp (p, "2000") || !strcmp (p, "2k") || !strcmp (p, "2K"))
! 	cpu = PROCESSOR_R3000;
!       else if (!strcmp (p, "20kc") || !strcmp (p, "20Kc") )
!         cpu = PROCESSOR_R20KC;
!       break;
  
!     case '3':
!       if (!strcmp (p, "3000") || !strcmp (p, "3k") || !strcmp (p, "3K"))
! 	cpu = PROCESSOR_R3000;
!       else if (!strcmp (p, "3900"))
! 	cpu = PROCESSOR_R3900;
!       break;
  
!     case '4':
!       if (!strcmp (p, "4000") || !strcmp (p, "4k") || !strcmp (p, "4K"))
! 	cpu = PROCESSOR_R4000;
!       /* The vr4100 is a non-FP ISA III processor with some extra
! 	 instructions.  */
!       else if (!strcmp (p, "4100"))
! 	  cpu = PROCESSOR_R4100;
!       /* The vr4300 is a standard ISA III processor, but with a different
! 	 pipeline.  */
!       else if (!strcmp (p, "4300"))
! 	cpu = PROCESSOR_R4300;
!       /* The r4400 is exactly the same as the r4000 from the compiler's
! 	 viewpoint.  */
!       else if (!strcmp (p, "4400"))
! 	cpu = PROCESSOR_R4000;
!       else if (!strcmp (p, "4600"))
! 	cpu = PROCESSOR_R4600;
!       else if (!strcmp (p, "4650"))
! 	cpu = PROCESSOR_R4650;
!       /* The 4kc and 4kp processor cores are the same for
! 	 scheduling purposes; they both implement the MIPS32
! 	 ISA and only differ in their memory management
! 	 methods.  */
!       else if (!strcmp (p, "4kc") || !strcmp (p, "4Kc")
!                || !strcmp (p, "4kp") || !strcmp (p, "4Kp") )
! 	cpu = PROCESSOR_R4KC;
!       break;
  
!     case '5':
!       if (!strcmp (p, "5000") || !strcmp (p, "5k") || !strcmp (p, "5K"))
! 	cpu = PROCESSOR_R5000;
!       else if (!strcmp (p, "5kc") || !strcmp (p, "5Kc") )
!           cpu = PROCESSOR_R5KC;
!       break;
  
-     case '6':
-       if (!strcmp (p, "6000") || !strcmp (p, "6k") || !strcmp (p, "6K"))
- 	cpu = PROCESSOR_R6000;
-       break;
  
!     case '8':
!       if (!strcmp (p, "8000"))
! 	cpu = PROCESSOR_R8000;
!       break;
  
!     case 'o':
!       if (!strcmp (p, "orion"))
! 	cpu = PROCESSOR_R4600;
!       break;
!     }
  
!   if (seen_v
!       && cpu != PROCESSOR_R4300
!       && cpu != PROCESSOR_R4100
!       && cpu != PROCESSOR_R5000)
!     cpu = PROCESSOR_DEFAULT;
  
!   return cpu;
  }
  
  /* Adjust the cost of INSN based on the relationship between INSN that
     is dependent on DEP_INSN through the dependence LINK.  The default
     is to make no adjustment to COST.
--- 10160,10286 ----
    /* NOTREACHED */
    return 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 bool
! 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 bool
! 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 PROCESSOR_DEFAULT.  */
  
! static enum processor_type
! mips_parse_cpu (option, cpu_string)
!      const char *option;
!      const char *cpu_string;
! {
!   static const struct {
!     const char *name;
!     enum processor_type processor;
!   } aliases[] = {
!     { "r2000", PROCESSOR_R3000 },
!     { "r4400", PROCESSOR_R4000 },
!     { "orion", PROCESSOR_R4600 },
!     /* The 4kc and 4kp processor cores are the same for scheduling
!        purposes; they both implement the MIPS32 ISA and only differ
!        in their memory management methods.  */
!     { "r4kp", PROCESSOR_R4KC }
!   };
  
!   const char *p;
!   size_t i;
  
!   /* In the past, we allowed upper-case CPU names, but it doesn't
!      work well with the multilib machinery.  */
!   for (p = cpu_string; *p != 0; p++)
!     if (ISUPPER (*p))
!       {
! 	warning ("the cpu name must be lower case");
! 	break;
!       }
! 
!   /* First search the processor array for a matching name.  */
!   for (i = 0; i < ARRAY_SIZE (mips_processors); i++)
!     if (mips_matching_cpu_name_p (mips_processors[i].name, cpu_string))
!       return (enum processor_type) i;
! 
!   /* If that doesn't work, check for a few well-known aliases.  */
!   for (i = 0; i < ARRAY_SIZE (aliases); i++)
!     if (mips_matching_cpu_name_p (aliases[i].name, cpu_string))
!       return aliases[i].processor;
! 
!   error ("bad value (%s) for %s", cpu_string, option);
!   return PROCESSOR_DEFAULT;
  }
  
+ 
+ /* Return the processor associated with the given ISA level, or
+    PROCESSOR_DEFAULT if the level is invalid.  */
+ 
+ static enum processor_type
+ mips_cpu_from_isa_level (isa_level)
+      int isa_level;
+ {
+   switch (isa_level)
+     {
+     case 1: return PROCESSOR_R3000;
+     case 2: return PROCESSOR_R6000;
+     case 3: return PROCESSOR_R4000;
+     case 4: return PROCESSOR_R8000;
+     case 32: return PROCESSOR_R4KC;
+     case 64: return PROCESSOR_R5KC;
+     default: return PROCESSOR_DEFAULT;
+     }
+ }
+ 
  /* Adjust the cost of INSN based on the relationship between INSN that
     is dependent on DEP_INSN through the dependence LINK.  The default
     is to make no adjustment to COST.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]