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]

[Revised patch] Rework MIPS command-line handling


First, thanks to everyone who responded to my first message.
I've tried to incorporate the feedback into the patch below.

Brief summary of changes:

1) both gcc & gas now accept -march=mipsN
2) gcc defines _MIPS_ARCH and _MIPS_TUNE
3) ELF gccs will always pass an ABI option to the assembler
4) all configs now support -mabi
5) there is now a special 'from-abi' architecture
6) -mabi doesn't change the default architecture (but see below)
7) -march doesn't change the ABI (modulo 32/64-bit selection for EABIs)

More details:

1) Internally, gcc treats -mips1 and -march=mips1 like -march=r2000,
   and similarly for the other ISA levels.

   Question is, what are right values for _MIPS_ARCH and _MIPS_TUNE when
   you use a generic ISA?  It doesn't seem right for them to name a
   processor when the command line and configuration don't specify one.
   So in the patch I've just set them to 0.  It gives users a way of
   distinguishing between -march=mipsN and -march=<processor>, should
   they want to.

2) Each processor has a macro of the form _MIPS_<name>.  As suggested,
   each known processor has distinct macro, even if GCC treats them
   the same way internally.  So there's both a _MIPS_R2000 and
   a _MIPS_R3000, for example.

   Not the biggest issue, I know, but is _MIPS_<foo> OK for the
   processor macros?  I guess other alternatives would be
   _MIPS_PROCESSOR_<foo> or _PROCESSOR_<foo>.

   I guess the values of these macros ought not to change between
   releases, just in case someone stores _MIPS_ARCH in a variable
   in one compilation unit and reads it in another, compiled with
   a different version of gcc.  So I've used a (lame!) convention
   for giving each entry a unique value.  See comment above
   mips_cpu_info_table[] in mips.c for details.

   This should also make it easier to check for a range of
   processors, such as members of a family that have different
   tuning characteristics but the same basic ISA.

3) There seemed to be general agreement that we should record the
   default ABI in ELF objects.  We could teach GAS about the default
   ABI for each target (I left this option open in my earlier patch).
   But I'd really rather not do it that way: it would mean duplicating
   a whole load of config.gcc logic, and it could lead to subtle
   incompatabilities between GCC and GAS in future.

   In this case, I'd rather use gcc specs.  This stands more chance of
   working with non-GAS targets and earlier binutils releases.  It's
   also much cleaner code-wise.  All I'm talking about is

	%{!mabi=*: %(asm_abi_default_spec)}

   in ASM_SPEC (see comments in patch for why ASM_SPEC instead of
   the others).

   There's still the problem that some OSes don't understand
   E_MIPS_ABI_O32.  I've added a way of disabling it for specific
   targets.  So far, irix is the only one to take advantage.

4) After these changes, there doesn't seem any reason to limit
   -mabi to the current handful of targets.  I often hack it in
   to the other targets for testing, and I'm sure others do too.

   Safety might be one concern.  But since ELF targets will always
   pass an ABI flag to the assembler, there should be little chance of
   accidents there.  For COFF targets, the user will get an error if
   they use -mabi with an assembler that doesn't support it (see
   changes to ASM_SPEC).

5) I prefer '-march=from-abi' over '-mstrict-abi' and '-mdeduce-arch'
   (which were the other suggestions I saw).  For one thing, it brings
   all architecture-changing stuff under -march, but more importantly,
   a configuration can then have "from-abi" as its default architecture.
   Which leads on to...

6) The consensus seemed to be that, when using a configuration associated
   with a particular ISA or processor, we should try to stick to the
   default where possible.  So "mips64orion-elf-gcc -mabi=32" would
   generate 32-bit 4600 code rather than than MIPS I code.

   Then, we would only deviate from the default architecture when that
   architecture is a 32-bit one, and the selected ABI requires 64-bit
   registers.  For example, "mipstx39-elf -mabi=o64".  For configs
   like mipstx39-elf that are associated with a particular ISA, I
   think specifying an incompatible ABI should be a hard error.
   The user can of course say "mipstx39-elf -mabi=o64 -mips3" if
   that's what they truly mean.

   The question is, how do people see configs like mips-elf and
   mips64-elf?  Is mips-elf "a target for generating MIPS I code",
   or (by a weaker definition) "a target that generates 32-bit code
   by default".  Similarly mips64-elf, MIPS III and 64-bit code.

   According to the stronger definition, mips-elf-gcc would give
   an error if you pass -mabi=o64 without changing the architecture.
   According to the weaker definition, it should switch to MIPS III,
   since -mabi=o64 obviously overrides the "32-bit" default.  The
   stronger definition implies the default should be -march=mips1,
   while the weaker one implies it should be -march=from-abi.

   Same sort of question for mips64-elf.

   At the moment I'm leaning towards the weaker definition, so the patch
   makes "from-abi" the default for both.  Specifically, instead of
   setting MIPS_ISA_DEFAULT to 3 in elf64.h and 1 in mips.h, there is
   just a default definition of MIPS_CPU_STRING_DEFAULT as "from-abi".
   That means the default behaviour is to select the "most compatible"
   architecture for the given ABI, as Thiemo suggested.

7) [Changing ABI based on architecture.]  This time round there's no
   logic to impliclty switch between {n32,n64,o64} and {o32}.  The
   consensus seemed to be that it should at least produce a warning.
   But if we pass the default ABI to GAS using specs, we would
   also have to use specs to override the default, since GAS can't
   tell the difference between a user-supplied or gcc-supplied option.
   So this time I've removed that functionality entirely.

   The behaviour for the EABIs is the same as before: selecting a 64-bit
   architecture implicitly selects 64-bit code, but you can use -mgp32
   to get 32-bit code instead.  Thus 'mipsisa32-elf-gcc -mips64' selects
   64-bit MEABI and "mipsisa64-elf-gcc -mips32" selects 32-bit MEABI.

GAS patch tested as before.  GCC patch tested on mips64-elf with
and without patched GAS.  Irix bootstrap still ongoing.

How does this version look?

Richard

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

[gas/]
	* doc/c-mips.texi: Remove -mcpu.  Document -mabi.
	* configure.in (MIPS_CPU_STRING_DEFAULT): New configuration macro.
	(USE_E_MIPS_ABI_O32, MIPS_DEFAULT_64BIT): New configuration macros.
	* configure, config.in: Regenerate.
	* config/tc-mips.c (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_cpu): Remove.
	(mips_arch_string, mips_arch_info): New vars.
	(mips_tune_string, mips_tune_info): New vars.
	(ABI_NEEDS_32BIT_REGS, ABI_NEEDS_64BIT_REGS): New macros.
	(HAVE_32BIT_GPRS, HAVE_32BIT_FPRS): Don't check the ABI.
	(mips_isa_to_str, mips_cpu_to_str): Remove.
	(mips_ip): If the selected architecture is a generic ISA rather
	than a processor, only mention the ISA level in error messages.
	(OPTION_MCPU): Remove.
	(OPTION_FP64): New.
	(md_longopts): Add -mfp64, remove -mcpu.
	(mips_set_option_string): New fn.
	(md_parse_option): Make -mipsN update file_mips_isa rather than
	mips_opts.isa.  Use mips_set_option_string to set -march or -mtune.
	Don't let -mgp32 and -mfp32 change the ABI.
	(show): Move to end of file.  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.  -mipsN
	is an alias for -march=mipsN.  Don't change the ABI based on other
	flags.  Infer the register size from the ABI as	well as the
	architecture.  Complain about more conflicting arguments.
	[Logic unified with gcc 3.2.]
	(s_mipsset): Don't change the ABI.
	(mips_elf_final_processing): Check USE_E_MIPS_ABI_O32.
	(mips_cpu_info_table): Remove Generic-MIPS* entries, keeping just
	"mipsN"-type 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_strict_matching_cpu_name_p, mips_matching_cpu_name_p): New fns.
	(mips_parse_cpu): New fn.
	(mips_cpu_info_from_name, mips_cpu_info_from_cpu): Remove.
	(mips_cpu_info_from_isa): Minor formatting tweak.

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

[gcc/]
	* doc/invoke.texi: Document -mabi=meabi, and expand on the EABI
	description.  Document -mips32, -mips64, and the associated -march
	values.  Describe the "mipsN" arguments to -march.  Say that the
	-mipsN options are equivalent to -march.  Reword the description
	of default type sizes.
	* toplev.h (target_flags_explicit): Declare.
	* toplev.c (target_flags_explicit): New var.
	(set_target_switch): Update target_flags_explicit.
	* config/mips/abi64.h (SUBTARGET_TARGET_OPTIONS): Undefine.
	* config/mips/elf64.h (MIPS_ISA_DEFAULT): Undefine.
	* config/mips/iris6.h (SUBTARGET_ASM_SPEC): -mabi=64 implies -mips3.
	* config/mips/isa3264.h (MIPS_ENABLE_EMBEDDED_O32): Undefine.
	* config/mips/mips.h (mips_cpu_info): New struct.
	(mips_cpu_string, mips_explicit_type_size_string): Remove.
	(mips_cpu_info_table, mips_arch_info, mips_tune_info): Declare.
	(MIPS_CPP_SET_PROCESSOR): New macro.
	(TARGET_CPP_BUILTINS): Declare a macro for each supported processor.
	Define _MIPS_ARCH and _MIPS_TUNE.
	(MIPS_ISA_DEFAULT): Don't provide a default value.  Instead...
	(MIPS_CPU_STRING_DEFAULT): Set to "from-abi" if neither it nor
	MIPS_ISA_DEFAULT were already defined.
	(MULTILIB_DEFAULTS): Add MULTILIB_ABI_DEFAULT.
	(TARGET_OPTIONS): Remove -mcpu and -mexplicit-type-size.
	(ABI_NEEDS_32BIT_REGS, ABI_NEEDS_64BIT_REGS): New.
	(GAS_ASM_SPEC): Remove -march, -mcpu, -mgp* and -mabi rules.
	(ABI_GAS_ASM_SPEC): Remove.
	(MULTILIB_ABI_DEFAULT, ASM_ABI_DEFAULT_SPEC): New macros.
	(ASM_SPEC): Add -mgp32, -mgp64, -march, -mabi=eabi and -mabi=o64.
	Invoke %(asm_abi_default_spec) if no ABI was specified.
	(CC1_SPEC): Remove ISA -> register-size rules.
	(EXTRA_SPECS): Remove abi_gas_asm_spec.  Add asm_abi_default_spec.
	* config/mips/mips.c (mips_arch_info, mips_tune_info): New vars.
	(mips_cpu_string, mips_explicit_type_size_string): Remove.
	(mips_cpu_info_table): New array.
	(mips_set_architecture, mips_set_tune): New fns.
	(override_options): Rework to make -mipsN equivalent to -march.
	Detect more erroneous cases, including those removed from CC1_SPEC.
	Don't change the ABI based on architecture, or vice versa.
	Unify logic with GAS 2.14.
	(mips_asm_file_start): Get architecture name from mips_arch_info.
	(mips_strict_matching_cpu_name_p, mips_matching_cpu_name_p): New fns.
	(mips_parse_cpu): Take the name of the option as argument.  Handle
	'from-abi'.  Raise an error if the option is wrong.
	(mips_cpu_info_from_isa): New fn.

[gcc/testsuite]
	* gcc.dg/mips-args-[123].c: New tests.

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	18 Jul 2002 13:59:27 -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	18 Jul 2002 13:59:27 -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	18 Jul 2002 13:59:27 -0000
*************** changequote([,])dnl
*** 555,560 ****
--- 555,615 ----
  
  # Other random stuff.
  
+     case ${cpu_type} in
+       mips)
+ 	# Set mips_cpu to the name of the default CPU.
+ 	case ${target_cpu} in
+ 	  mips | mipsbe | mipseb | mipsle | mipsel | mips64 | mips64el)
+ 	    mips_cpu=from-abi
+ 	    ;;
+ 	  mipsisa32 | mipsisa32el)
+ 	    mips_cpu=mips32
+ 	    ;;
+ 	  mipsisa64 | mipsisa64el)
+ 	    mips_cpu=mips64
+ 	    ;;
+ 	  mipstx39 | mipstx39el)
+ 	    mips_cpu=r3900
+ 	    ;;
+ 	  mips64* | mipsisa64*)
+ changequote(,)dnl
+ 	    mips_cpu=`echo $target_cpu | sed -e 's/[a-z]*64//' -e 's/el$//'`
+ changequote([,])dnl
+ 	    ;;
+ 	  *)
+ 	    AC_ERROR($target_cpu isn't a supported MIPS CPU name)
+ 	    ;;
+ 	esac
+ 	# See whether it's appropriate to set E_MIPS_ABI_O32 for o32
+ 	# binaries.  It's a GNU extension that some OSes don't understand.
+ 	# The value only matters on ELF targets.
+ 	case ${target} in
+ 	  *-*-irix*)
+ 	    use_e_mips_abi_o32=0
+ 	    ;;
+ 	  *)
+ 	    use_e_mips_abi_o32=1
+ 	    ;;
+ 	esac
+ 	# Decide whether to generate 32-bit or 64-bit code by default.
+ 	# Used to resolve -march=from-abi when an embedded ABI is selected.
+ 	case ${target_cpu} in
+ 	  mips64* | mipsisa64*)
+ 	    mips_default_64bit=1
+ 	    ;;
+ 	  *)
+ 	    mips_default_64bit=0
+ 	    ;;
+ 	esac
+ 	AC_DEFINE_UNQUOTED(MIPS_CPU_STRING_DEFAULT, "$mips_cpu",
+ 			   [Default CPU for MIPS targets. ])
+ 	AC_DEFINE_UNQUOTED(USE_E_MIPS_ABI_O32, $use_e_mips_abi_o32,
+ 			   [Allow use of E_MIPS_ABI_O32 on MIPS targets. ])
+ 	AC_DEFINE_UNQUOTED(MIPS_DEFAULT_64BIT, $mips_default_64bit,
+ 			   [Generate 64-bit code by default on MIPS targets. ])
+ 	;;
+     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	18 Jul 2002 13:59:28 -0000
*************** 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
--- 129,135 ----
  };
  
  /* MIPS ABI we are using for this output file.  */
! static enum mips_abi_level mips_abi = NO_ABI;
  
  /* This is the set of options which may be modified by the .set
     pseudo-op.  We use a struct so that .set push and .set pop are more
*************** 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.  */
--- 177,182 ----
*************** 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.
--- 191,197 ----
  
  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
--- 215,232 ----
     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;
+ static const char *mips_arch_string;
+ static const struct mips_cpu_info *mips_arch_info;
  
  /* The argument of the -mtune= flag.  The architecture for which we
     are optimizing.  */
  static int mips_tune = CPU_UNKNOWN;
+ static const char *mips_tune_string;
+ static const struct mips_cpu_info *mips_tune_info;
  
! /* 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 ****
--- 243,257 ----
     || (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.  */
--- 261,277 ----
     )
  
  #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 my_getExpression PARAMS ((ex
*** 741,746 ****
--- 743,749 ----
  #ifdef OBJ_ELF
  static int support_64bit_objects PARAMS((void));
  #endif
+ static void mips_set_option_string PARAMS ((const char **, const char *));
  static symbolS *get_symbol PARAMS ((void));
  static void mips_align PARAMS ((int to, int fill, symbolS *label));
  static void s_align PARAMS ((int));
*************** 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
--- 775,782 ----
  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
*************** struct mips_cpu_info
*** 817,825 ****
    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.
  
--- 818,831 ----
    int cpu;                    /* CPU number (default CPU if ISA).  */
  };
  
! static void mips_set_architecture PARAMS ((const struct mips_cpu_info *));
! static void mips_set_tune PARAMS ((const struct mips_cpu_info *));
! static boolean mips_strict_matching_cpu_name_p PARAMS ((const char *,
! 							const char *));
! static boolean mips_matching_cpu_name_p PARAMS ((const char *, const char *));
! static const struct mips_cpu_info *mips_parse_cpu PARAMS ((const char *,
! 							   const char *));
  static const struct mips_cpu_info *mips_cpu_info_from_isa PARAMS ((int));
  
  /* 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 *
--- 978,983 ----
*************** 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);
  
--- 1153,1159 ----
  	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)
*** 7763,7773 ****
  	      if (!insn_error)
  		{
  		  static char buf[100];
! 		  sprintf (buf,
! 			   _("opcode not supported on this processor: %s (%s)"),
! 			   mips_cpu_to_str (mips_arch),
! 			   mips_isa_to_str (mips_opts.isa));
! 
  		  insn_error = buf;
  		}
  	      if (save_c)
--- 7739,7753 ----
  	      if (!insn_error)
  		{
  		  static char buf[100];
! 		  if (mips_arch_info->is_isa)
! 		    sprintf (buf,
! 			     _("opcode not supported at this ISA level (%s)"),
! 			     mips_cpu_info_from_isa (mips_opts.isa)->name);
! 		  else
! 		    sprintf (buf,
! 			     _("opcode not supported on this processor: %s (%s)"),
! 			     mips_arch_info->name,
! 			     mips_cpu_info_from_isa (mips_opts.isa)->name);
  		  insn_error = buf;
  		}
  	      if (save_c)
*************** 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)
--- 9872,9879 ----
    {"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)
*************** struct option md_longopts[] =
*** 9946,9951 ****
--- 9926,9949 ----
  };
  size_t md_longopts_size = sizeof (md_longopts);
  
+ /* Set STRING_PTR (either &mips_arch_string or &mips_tune_string) to
+    NEW_VALUE.  Warn if another value was already specified.  Note:
+    we have to defer parsing the -march and -mtune arguments in order
+    to handle 'from-abi' correctly, since the ABI might be specified
+    in a later argument.  */
+ 
+ static void
+ mips_set_option_string (string_ptr, new_value)
+      const char **string_ptr, *new_value;
+ {
+   if (*string_ptr != 0 && strcasecmp (*string_ptr, new_value) != 0)
+     as_warn (_("A different %s was already specified, is now %s"),
+ 	     string_ptr == &mips_arch_string ? "-march" : "-mtune",
+ 	     new_value);
+ 
+   *string_ptr = new_value;
+ }
+ 
  int
  md_parse_option (c, arg)
       int c;
*************** md_parse_option (c, arg)
*** 10001,10130 ****
        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:
!       if ((mips_arch != CPU_UNKNOWN && mips_arch != CPU_R4650)
! 	  || (mips_tune != CPU_UNKNOWN && mips_tune != CPU_R4650))
! 	as_warn (_("A different -march= or -mtune= was already specified, "
! 		   "is now -m4650"));
!       mips_arch = CPU_R4650;
!       mips_tune = CPU_R4650;
        break;
  
      case OPTION_NO_M4650:
        break;
  
      case OPTION_M4010:
!       if ((mips_arch != CPU_UNKNOWN && mips_arch != CPU_R4010)
! 	  || (mips_tune != CPU_UNKNOWN && mips_tune != CPU_R4010))
! 	as_warn (_("A different -march= or -mtune= was already specified, "
! 		   "is now -m4010"));
!       mips_arch = CPU_R4010;
!       mips_tune = CPU_R4010;
        break;
  
      case OPTION_NO_M4010:
        break;
  
      case OPTION_M4100:
!       if ((mips_arch != CPU_UNKNOWN && mips_arch != CPU_VR4100)
! 	  || (mips_tune != CPU_UNKNOWN && mips_tune != CPU_VR4100))
! 	as_warn (_("A different -march= or -mtune= was already specified, "
! 		   "is now -m4100"));
!       mips_arch = CPU_VR4100;
!       mips_tune = CPU_VR4100;
        break;
  
      case OPTION_NO_M4100:
        break;
  
      case OPTION_M3900:
!       if ((mips_arch != CPU_UNKNOWN && mips_arch != CPU_R3900)
! 	  || (mips_tune != CPU_UNKNOWN && mips_tune != CPU_R3900))
! 	as_warn (_("A different -march= or -mtune= was already specified, "
! 		   "is now -m3900"));
!       mips_arch = CPU_R3900;
!       mips_tune = CPU_R3900;
        break;
  
      case OPTION_NO_M3900:
--- 9999,10066 ----
        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_set_option_string (&mips_tune_string, arg);
!       break;
  
!     case OPTION_MARCH:
!       mips_set_option_string (&mips_arch_string, arg);
        break;
  
      case OPTION_M4650:
!       mips_set_option_string (&mips_arch_string, "4650");
!       mips_set_option_string (&mips_tune_string, "4650");
        break;
  
      case OPTION_NO_M4650:
        break;
  
      case OPTION_M4010:
!       mips_set_option_string (&mips_arch_string, "4010");
!       mips_set_option_string (&mips_tune_string, "4010");
        break;
  
      case OPTION_NO_M4010:
        break;
  
      case OPTION_M4100:
!       mips_set_option_string (&mips_arch_string, "4100");
!       mips_set_option_string (&mips_tune_string, "4100");
        break;
  
      case OPTION_NO_M4100:
        break;
  
      case OPTION_M3900:
!       mips_set_option_string (&mips_arch_string, "3900");
!       mips_set_option_string (&mips_tune_string, "3900");
        break;
  
      case OPTION_NO_M3900:
*************** 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:
--- 10163,10169 ----
  	  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:
--- 10172,10178 ----
  	  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;
--- 10181,10187 ----
  	  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
--- 10189,10206 ----
  
      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);
--- 10211,10230 ----
  	  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)
*** 10323,10466 ****
  
    return 1;
  }
  
  static void
! show (stream, string, col_p, first_p)
!      FILE *stream;
!      char *string;
!      int *col_p;
!      int *first_p;
  {
!   if (*first_p)
!     {
!       fprintf (stream, "%24s", "");
!       *col_p = 24;
!     }
!   else
!     {
!       fprintf (stream, ", ");
!       *col_p += 2;
!     }
! 
!   if (*col_p + strlen (string) > 72)
      {
!       fprintf (stream, "\n%24s", "");
!       *col_p = 24;
      }
- 
-   fprintf (stream, "%s", string);
-   *col_p += strlen (string);
- 
-   *first_p = 0;
  }
  
- void
- md_show_usage (stream)
-      FILE *stream;
- {
-   int 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)
--- 10257,10296 ----
  
    return 1;
  }
+ 
+ /* Set up globals to generate code for the ISA or processor
+    described by INFO.  */
  
  static void
! mips_set_architecture (info)
!      const struct mips_cpu_info *info;
  {
!   if (info != 0)
      {
!       mips_arch_info = info;
!       mips_arch = info->cpu;
!       mips_opts.isa = info->isa;
      }
  }
  
  
! /* Likewise for tuning.  */
  
! static void
! mips_set_tune (info)
!      const struct mips_cpu_info *info;
! {
!   if (info != 0)
!     {
!       mips_tune_info = info;
!       mips_tune = info->cpu;
!     }
! }
  
  
  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)
--- 10300,10387 ----
        g_switch_value = 0;
      }
  
!   /* The following code determines the architecture, ABI and register
!      size.  Similar code was added to GCC 3.2 (see override_options()
!      in config/mips/mips.c).  The GAS and GCC code should be kept in
!      sync as much as possible.  */
  
!   if (mips_arch_string != 0)
!     mips_set_architecture (mips_parse_cpu ("-march", mips_arch_string));
  
!   if (mips_tune_string != 0)
!     mips_set_tune (mips_parse_cpu ("-mtune", mips_tune_string));
  
!   if (file_mips_isa != ISA_UNKNOWN)
      {
!       /* Handle -mipsN.  At this point, file_mips_isa contains the
! 	 ISA level specified by -mipsN, while mips_opts.isa contains
! 	 the -march selection (if any).  */
!       if (mips_arch_info != 0)
  	{
! 	  /* -march takes precedence over -mipsN, since it is more descriptive.
! 	     There's no harm in specifying both as long as the ISA levels
! 	     are the same.  */
! 	  if (file_mips_isa != mips_opts.isa)
! 	    as_bad (_("-%s conflicts with the other architecture options, which imply -%s"),
! 		    mips_cpu_info_from_isa (file_mips_isa)->name,
! 		    mips_cpu_info_from_isa (mips_opts.isa)->name);
  	}
+       else
+ 	mips_set_architecture (mips_cpu_info_from_isa (file_mips_isa));
      }
  
!   if (mips_arch_info == 0)
!     mips_set_architecture (mips_parse_cpu ("default CPU",
! 					   MIPS_CPU_STRING_DEFAULT));
  
!   if (ABI_NEEDS_64BIT_REGS (mips_abi) && !ISA_HAS_64BIT_REGS (mips_opts.isa))
!     as_bad ("-march=%s is not compatible with the selected ABI",
! 	    mips_arch_info->name);
  
!   /* Optimize for mips_arch, unless -mtune selects a different processor.  */
!   if (mips_tune_info == 0)
!     mips_set_tune (mips_arch_info);
  
!   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.  */
  
!   /* ??? When do we want this flag to be set?   Who uses it?  */
!   if (file_mips_gp32 == 1
!       && mips_abi == NO_ABI
!       && ISA_HAS_64BIT_REGS (mips_opts.isa))
!     mips_32bitmode = 1;
  
    if (mips_opts.isa == ISA_MIPS1 && mips_trap)
      as_bad (_("trap exception not supported at ISA 1"));
  
    /* If the selected architecture includes support for ASEs, enable
       generation of code for them.  */
    if (mips_opts.mips16 == -1)
*************** mips_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;
--- 10391,10397 ----
*************** 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:
--- 11466,11471 ----
*************** 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;
--- 11477,11482 ----
*************** void
*** 13201,13207 ****
  mips_elf_final_processing ()
  {
    /* Write out the register information.  */
!   if (file_mips_abi != N64_ABI)
      {
        Elf32_RegInfo s;
  
--- 12925,12931 ----
  mips_elf_final_processing ()
  {
    /* Write out the register information.  */
!   if (mips_abi != N64_ABI)
      {
        Elf32_RegInfo s;
  
*************** mips_elf_final_processing ()
*** 13251,13272 ****
      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.  */
!       if (ISA_HAS_64BIT_REGS (file_mips_isa))
  	elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_EABI64;
        else
  	elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_EABI32;
      }
!   else if (file_mips_abi == N32_ABI)
      elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ABI2;
  
    /* Nothing to do for N64_ABI.  */
--- 12975,12992 ----
      elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ARCH_ASE_MDMX;
  
    /* Set the MIPS ELF ABI flags.  */
!   if (mips_abi == O32_ABI && USE_E_MIPS_ABI_O32)
      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)
      {
!       if (!file_mips_gp32)
  	elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_EABI64;
        else
  	elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_EABI32;
      }
!   else if (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;
--- 13429,13603 ----
  
  /* 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[] =
  {
!   /* Entries for generic ISAs */
!   { "mips1",          1,      ISA_MIPS1,      CPU_R3000 },
!   { "mips2",          1,      ISA_MIPS2,      CPU_R6000 },
!   { "mips3",          1,      ISA_MIPS3,      CPU_R4000 },
!   { "mips4",          1,      ISA_MIPS4,      CPU_R8000 },
!   { "mips5",          1,      ISA_MIPS5,      CPU_MIPS5 },
!   { "mips32",         1,      ISA_MIPS32,     CPU_MIPS32 },
!   { "mips64",         1,      ISA_MIPS64,     CPU_MIPS64 },
  
!   /* MIPS I */
!   { "r3000",          0,      ISA_MIPS1,      CPU_R3000 },
!   { "r2000",          0,      ISA_MIPS1,      CPU_R3000 },
!   { "r3900",          0,      ISA_MIPS1,      CPU_R3900 },
  
!   /* MIPS II */
!   { "r6000",          0,      ISA_MIPS2,      CPU_R6000 },
  
!   /* MIPS III */
!   { "r4000",          0,      ISA_MIPS3,      CPU_R4000 },
!   { "r4010",          0,      ISA_MIPS2,      CPU_R4010 },
!   { "vr4100",         0,      ISA_MIPS3,      CPU_VR4100 },
!   { "vr4111",         0,      ISA_MIPS3,      CPU_R4111 },
!   { "vr4300",         0,      ISA_MIPS3,      CPU_R4300 },
!   { "r4400",          0,      ISA_MIPS3,      CPU_R4400 },
!   { "r4600",          0,      ISA_MIPS3,      CPU_R4600 },
!   { "orion",          0,      ISA_MIPS3,      CPU_R4600 },
!   { "r4650",          0,      ISA_MIPS3,      CPU_R4650 },
  
!   /* MIPS IV */
!   { "r8000",          0,      ISA_MIPS4,      CPU_R8000 },
!   { "r10000",         0,      ISA_MIPS4,      CPU_R10000 },
!   { "r12000",         0,      ISA_MIPS4,      CPU_R12000 },
!   { "vr5000",         0,      ISA_MIPS4,      CPU_R5000 },
!   { "rm5200",         0,      ISA_MIPS4,      CPU_R5000 },
!   { "rm5230",         0,      ISA_MIPS4,      CPU_R5000 },
!   { "rm5231",         0,      ISA_MIPS4,      CPU_R5000 },
!   { "rm5261",         0,      ISA_MIPS4,      CPU_R5000 },
!   { "rm5721",         0,      ISA_MIPS4,      CPU_R5000 },
!   { "r7000",          0,      ISA_MIPS4,      CPU_R5000 },
  
!   /* MIPS 32 */
    { "4kc",            0,      ISA_MIPS32,     CPU_MIPS32, },
!   { "4km",            0,      ISA_MIPS32,     CPU_MIPS32 },
!   { "4kp",            0,      ISA_MIPS32,     CPU_MIPS32 },
  
!   /* MIPS 64 */
!   { "5kc",            0,      ISA_MIPS64,     CPU_MIPS64 },
!   { "20kc",           0,      ISA_MIPS64,     CPU_MIPS64 },
  
!   /* Broadcom SB-1 CPU */
!   { "SB-1",           0,      ISA_MIPS64,     CPU_SB1 },
!   { "sb-1250",        0,      ISA_MIPS64,     CPU_SB1 },
!   { "sb1",            0,      ISA_MIPS64,     CPU_SB1 },
!   { "sb1250",         0,      ISA_MIPS64,     CPU_SB1 },
  
!   /* End marker.  */
!   { NULL, 0, 0, 0 }
! };
  
  
! /* Return true if GIVEN is the same as CANONICAL, or if it is CANONICAL
!    with a final "000" replaced by "k".  Ignore case.
  
!    Note: this function is shared between GCC and GAS.  */
  
! static boolean
! mips_strict_matching_cpu_name_p (canonical, given)
!      const char *canonical, *given;
! {
!   while (*given != 0 && TOLOWER (*given) == TOLOWER (*canonical))
!     given++, canonical++;
  
!   return ((*given == 0 && *canonical == 0)
! 	  || (strcmp (canonical, "000") == 0 && strcasecmp (given, "k") == 0));
! }
  
  
! /* Return true if GIVEN matches CANONICAL, where GIVEN is a user-supplied
!    CPU name.  We've traditionally allowed a lot of variation here.
  
!    Note: this function is shared between GCC and GAS.  */
  
! static boolean
! mips_matching_cpu_name_p (canonical, given)
!      const char *canonical, *given;
! {
!   /* First see if the name matches exactly, or with a final "000"
!      turned into "k".  */
!   if (mips_strict_matching_cpu_name_p (canonical, given))
!     return true;
  
!   /* If not, try comparing based on numerical designation alone.
!      See if GIVEN is an unadorned number, or 'r' followed by a number.  */
!   if (TOLOWER (*given) == 'r')
!     given++;
!   if (!ISDIGIT (*given))
!     return false;
  
!   /* Skip over some well-known prefixes in the canonical name,
!      hoping to find a number there too.  */
!   if (TOLOWER (canonical[0]) == 'v' && TOLOWER (canonical[1]) == 'r')
!     canonical += 2;
!   else if (TOLOWER (canonical[0]) == 'r' && TOLOWER (canonical[1]) == 'm')
!     canonical += 2;
!   else if (TOLOWER (canonical[0]) == 'r')
!     canonical += 1;
  
!   return mips_strict_matching_cpu_name_p (canonical, given);
! }
  
  
! /* Parse an option that takes the name of a processor as its argument.
!    OPTION is the name of the option and CPU_STRING is the argument.
!    Return the corresponding processor enumeration if the CPU_STRING is
!    recognized, otherwise report an error and return null.
  
!    A similar function exists in GCC.  */
  
  static const struct mips_cpu_info *
! mips_parse_cpu (option, cpu_string)
!      const char *option, *cpu_string;
  {
!   const struct mips_cpu_info *p;
  
!   /* 'from-abi' selects the most compatible architecture for the given
!      ABI: MIPS I for 32-bit ABIs and MIPS III for 64-bit ABIs.  For the
!      EABIs, we have to decide whether we're using the 32-bit or 64-bit
!      version.  Look first at the -mgp options, if given, otherwise base
!      the choice on MIPS_DEFAULT_64BIT.
  
!      Treat NO_ABI like the EABIs.  One reason to do this is that the
!      plain 'mips' and 'mips64' configs have 'from-abi' as their default
!      architecture.  This code picks MIPS I for 'mips' and MIPS III for
!      'mips64', just as we did in the days before 'from-abi'.  */
!   if (strcasecmp (cpu_string, "from-abi") == 0)
!     {
!       if (ABI_NEEDS_32BIT_REGS (mips_abi))
! 	return mips_cpu_info_from_isa (ISA_MIPS1);
! 
!       if (ABI_NEEDS_64BIT_REGS (mips_abi))
! 	return mips_cpu_info_from_isa (ISA_MIPS3);
! 
!       if (file_mips_gp32 >= 0)
! 	return mips_cpu_info_from_isa (file_mips_gp32 ? ISA_MIPS1 : ISA_MIPS3);
! 
!       return mips_cpu_info_from_isa (MIPS_DEFAULT_64BIT
! 				     ? ISA_MIPS3
! 				     : ISA_MIPS1);
!     }
! 
!   /* 'default' has traditionally been a no-op.  Probably not very useful.  */
!   if (strcasecmp (cpu_string, "default") == 0)
!     return 0;
! 
!   for (p = mips_cpu_info_table; p->name != 0; p++)
!     if (mips_matching_cpu_name_p (p->name, cpu_string))
!       return p;
! 
!   as_bad ("Bad value (%s) for %s", cpu_string, option);
!   return 0;
  }
  
+ /* Return the canonical processor information for ISA (a member of the
+    ISA_MIPS* enumeration).  */
+ 
  static const struct mips_cpu_info *
  mips_cpu_info_from_isa (isa)
       int isa;
*************** mips_cpu_info_from_isa (isa)
*** 13885,13906 ****
  
    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;
  {
!   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;
  }
--- 13606,13724 ----
  
    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 void
+ show (stream, string, col_p, first_p)
+      FILE *stream;
+      const char *string;
+      int *col_p;
+      int *first_p;
+ {
+   if (*first_p)
+     {
+       fprintf (stream, "%24s", "");
+       *col_p = 24;
+     }
+   else
+     {
+       fprintf (stream, ", ");
+       *col_p += 2;
+     }
+ 
+   if (*col_p + strlen (string) > 72)
+     {
+       fprintf (stream, "\n%24s", "");
+       *col_p = 24;
+     }
+ 
+   fprintf (stream, "%s", string);
+   *col_p += strlen (string);
+ 
+   *first_p = 0;
+ }
  
! void
! md_show_usage (stream)
!      FILE *stream;
  {
!   int 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);
!   show (stream, "from-abi", &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	18 Jul 2002 13:59:28 -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	18 Jul 2002 13:59:28 -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.158
diff -c -d -p -r1.158 invoke.texi
*** doc/invoke.texi	16 Jul 2002 17:46:33 -0000	1.158
--- doc/invoke.texi	18 Jul 2002 15:13:24 -0000
*************** These @samp{-m} options are defined for 
*** 6959,7023 ****
  
  @table @gcctabopt
  
! @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
--- 6959,7017 ----
  
  @table @gcctabopt
  
! @item -march=@var{arch}
  @opindex march
! Generate code that will run on @var{arch}, which can be the name of a
! generic MIPS ISA, or the name of a particular processor.  The recognized
! generic ISAs are: @samp{mips1}, @samp{mips2}, @samp{mips3}, @samp{mips4},
! @samp{mips32} and @samp{mips64}.  Recognized processors are: @samp{r2000},
! @samp{r3000}, @samp{r3900}, @samp{r4000}, @samp{vr4100}, @samp{vr4300},
! @samp{r4400}, @samp{r4600}, @samp{r4650}, @samp{vr5000}, @samp{r6000},
! @samp{r8000}, @samp{4kc}, @samp{4kp}, @samp{5kc}, @samp{20kc}
! and @samp{orion}.  The special value @samp{from-abi} selects the
! most compatible architecture for the selected ABI (MIPS I for 32-bit
! ABIs and MIPS III for 64-bit ABIs)@.
  
! In processor names, a final @samp{000} can be abbreviated as @samp{k}
! (for example, @samp{-march=r2k}).  Prefixes are optional, and
! @samp{vr} may be written @samp{r}.
! 
! @item -mtune=@var{arch}
  @opindex mtune
! Optimize for @var{arch}.  Among other things, this option controls
! the way instructions are scheduled, and the perceived cost of arithmetic
! operations.  The list of @var{arch} values is the same as for
! @option{-march}.
  
! When this option is not used, GCC will optimize for the processor
! specified by @option{-march}, or (failing that) for the default
! processor.  By using @option{-march} and @option{-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=mips1}.
  
  @item -mips2
  @opindex mips2
! Equivalent to @samp{-march=mips2}.
  
  @item -mips3
  @opindex mips3
! Equivalent to @samp{-march=mips3}.
  
  @item -mips4
  @opindex mips4
! Equivalent to @samp{-march=mips4}.
  
! @item -mips32
! @opindex mips32
! Equivalent to @samp{-march=mips32}.
  
! @item -mips64
! @opindex mips64
! Equivalent to @samp{-march=mips64}.
  
  @item -mfused-madd
  @itemx -mno-fused-madd
*************** in the mode where denormals are rounded 
*** 7031,7045 ****
  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
--- 7025,7045 ----
  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
*************** explanation of the default, and the widt
*** 7055,7085 ****
  @opindex mlong32
  Force long, int, and pointer types to be 32 bits wide.
  
! If none of @option{-mlong32}, @option{-mlong64}, or @option{-mint64} are set,
! the size of ints, longs, and pointers depends on the ABI and ISA chosen.
! For @option{-mabi=32}, and @option{-mabi=n32}, ints and longs are 32 bits
! wide.  For @option{-mabi=64}, ints are 32 bits, and longs are 64 bits wide.
! For @option{-mabi=eabi} and either @option{-mips1} or @option{-mips2}, ints
! and longs are 32 bits wide.  For @option{-mabi=eabi} and higher ISAs, ints
! are 32 bits, and longs are 64 bits wide.  The width of pointer types is
! the smaller of the width of longs or the width of general purpose
! registers (which in turn depends on the ISA)@.
  
  @item -mabi=32
  @itemx -mabi=o64
  @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
--- 7055,7086 ----
  @opindex mlong32
  Force long, int, and pointer types to be 32 bits wide.
  
! The default size of ints, longs and pointers depends on the ABI@.
! All the supported ABIs use 32-bit ints.  n64 uses 64-bit longs, as does
! the 64-bit Cygnus EABI; the others use 32-bit longs.  Pointers are
! the same size as longs, or the same size as integer registers,
! whichever is smaller.
  
  @item -mabi=32
  @itemx -mabi=o64
  @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 given ABI@.
! 
! Note that there are two embedded ABIs: @option{-mabi=eabi}
! selects the one defined by Cygnus while @option{-meabi=meabi}
! selects the one defined by MIPS@.  Both these ABIs have
! 32-bit and 64-bit variants.  Normally, GCC will generate
! 64-bit code when you select a 64-bit architecture, but you
! can use @option{-mgp32} to get 32-bit code instead.
  
  @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	18 Jul 2002 15:13:24 -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.658
diff -c -d -p -r1.658 toplev.c
*** toplev.c	17 Jul 2002 03:03:40 -0000	1.658
--- toplev.c	18 Jul 2002 15:13:25 -0000
*************** const char *dump_base_name;
*** 180,185 ****
--- 180,190 ----
  
  extern int target_flags;
  
+ /* A mask of target_flags that includes bit X if X was set or cleared
+    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)
*** 4409,4414 ****
--- 4414,4426 ----
  	  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/abi64.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/abi64.h,v
retrieving revision 1.26
diff -c -d -p -r1.26 abi64.h
*** config/mips/abi64.h	16 Apr 2002 03:01:17 -0000	1.26
--- config/mips/abi64.h	18 Jul 2002 15:13:25 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 21,31 ****
  /* Macros to implement the 64 bit ABI.  This file is meant to be included
     after mips.h.  */
  
- #undef SUBTARGET_TARGET_OPTIONS
- #define SUBTARGET_TARGET_OPTIONS \
-   { "abi=", &mips_abi_string,						\
-       "Specify ABI to use"},
- 
  #undef STACK_BOUNDARY
  #define STACK_BOUNDARY \
    ((mips_abi == ABI_32 || mips_abi == ABI_O64 || mips_abi == ABI_EABI) \
--- 21,26 ----
Index: config/mips/elf64.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/elf64.h,v
retrieving revision 1.43
diff -c -d -p -r1.43 elf64.h
*** config/mips/elf64.h	11 Jun 2002 07:26:37 -0000	1.43
--- config/mips/elf64.h	18 Jul 2002 15:13:25 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 22,34 ****
  
  #define OBJECT_FORMAT_ELF
  
! /* Default to -mips3.  */
  #ifndef TARGET_DEFAULT
  #define TARGET_DEFAULT MASK_FLOAT64|MASK_64BIT
- #endif
- 
- #ifndef MIPS_ISA_DEFAULT
- #define MIPS_ISA_DEFAULT 3
  #endif
  
  /* This should change to n32 when it is supported in gas.  */
--- 22,31 ----
  
  #define OBJECT_FORMAT_ELF
  
! /* If an embedded ABI is selected, prefer to generate 64-bit code.
!    Implies -mips3 in such cases.  */
  #ifndef TARGET_DEFAULT
  #define TARGET_DEFAULT MASK_FLOAT64|MASK_64BIT
  #endif
  
  /* This should change to n32 when it is supported in gas.  */
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	18 Jul 2002 15:13:25 -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/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	18 Jul 2002 15:13:25 -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/mips.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.h,v
retrieving revision 1.200
diff -c -d -p -r1.200 mips.h
*** config/mips/mips.h	17 Jul 2002 21:31:39 -0000	1.200
--- config/mips/mips.h	18 Jul 2002 15:13:25 -0000
*************** enum block_move_type {
*** 118,123 ****
--- 118,151 ----
    BLOCK_MOVE_LAST			/* generate just the last store */
  };
  
+ /* Information about one recognised processor.  Defined here for the
+    benefit of TARGET_CPU_CPP_BUILTINS.  */
+ struct mips_cpu_info {
+   /* The 'canonical' name of the processor as far as GCC is concerned.
+      It's typically a manufacturer's prefix followed by a numerical
+      designation.  It should be lower case.  */
+   const char *name;
+ 
+   /* A macro used to identify the processor, used as a possible value
+      for _MIPS_ARCH and _MIPS_TUNE.  Null if this entry describes a
+      generic ISA rather than a specific processor.  */
+   const char *macro;
+ 
+   /* The value of MACRO.  For compatability reasons, the macros
+      mustn't change value between releases, so we don't generate
+      them automatically.  Null if MACRO is null, or if the value
+      is defined in another entry.  */
+   const char *macro_value;
+ 
+   /* The internal processor number that most closely matches this
+      entry.  Several processors can have the same value, if there's no
+      difference between them from GCC's point of view.  */
+   enum processor_type cpu;
+ 
+   /* The ISA level that the processor implements.  */
+   int isa;
+ };
+ 
  extern char mips_reg_names[][8];	/* register names (a0 vs. $4).  */
  extern char mips_print_operand_punct[256]; /* print_operand punctuation chars */
  extern const char *current_function_file; /* filename current function is in */
*************** extern int mips_isa;			/* architectural 
*** 146,159 ****
  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 */
--- 174,185 ----
*************** extern GTY(()) rtx mips_load_reg2;	/* 2n
*** 167,172 ****
--- 193,201 ----
  extern GTY(()) rtx mips_load_reg3;	/* 3rd reg to check for load delay */
  extern GTY(()) rtx mips_load_reg4;	/* 4th reg to check for load delay */
  extern int mips_string_length;		/* length of strings for mips16 */
+ extern const struct mips_cpu_info mips_cpu_info_table[];
+ extern const struct mips_cpu_info *mips_arch_info;
+ extern const struct mips_cpu_info *mips_tune_info;
  
  /* Functions to change what output section we are using.  */
  extern void		sdata_section PARAMS ((void));
*************** extern void		sbss_section PARAMS ((void)
*** 342,351 ****
--- 371,388 ----
  #define TUNE_MIPS5000               (mips_tune == PROCESSOR_R5000)
  #define TUNE_MIPS6000               (mips_tune == PROCESSOR_R6000)
  
+ /* Set a preprocessor macro NAME to PROC's macro, or to 0 if PROC
+    represents a generic ISA.  */
+ #define MIPS_CPP_SET_PROCESSOR(NAME, PROC)			\
+   builtin_define_with_value					\
+     ((NAME), (PROC)->macro == 0? "0" : (PROC)->macro, 0)
+ 
  /* Target CPU builtins.  */
  #define TARGET_CPU_CPP_BUILTINS()				\
    do								\
      {								\
+       const struct mips_cpu_info *p;				\
+ 								\
        builtin_assert ("cpu=mips");				\
        builtin_define ("__mips__");     				\
        builtin_define ("_mips");					\
*************** extern void		sbss_section PARAMS ((void)
*** 355,370 ****
        if (!flag_iso)						\
  	  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");				\
  	}							\
--- 392,407 ----
        if (!flag_iso)						\
  	  builtin_define ("mips");				\
  								\
+       /* Treat _R3000 and _R4000 like register-size defines,	\
+ 	 which is how they've historically been used.  */	\
        if (TARGET_64BIT)						\
  	{							\
  	  builtin_define ("__mips64");     			\
  	  builtin_define_std ("R4000");				\
  	  builtin_define ("_R4000");				\
  	}							\
        else							\
  	{							\
  	  builtin_define_std ("R3000");				\
  	  builtin_define ("_R3000");				\
  	}							\
*************** extern void		sbss_section PARAMS ((void)
*** 376,381 ****
--- 413,426 ----
        if (TARGET_MIPS16)					\
  	  builtin_define ("__mips16");				\
  								\
+       /* Define a macro for each recognized processor.  */	\
+       for (p = mips_cpu_info_table; p->name != 0; p++)		\
+ 	if (p->macro_value != 0)				\
+ 	  builtin_define_with_value (p->macro, p->macro_value, 0); \
+ 								\
+       MIPS_CPP_SET_PROCESSOR ("_MIPS_ARCH", mips_arch_info);	\
+       MIPS_CPP_SET_PROCESSOR ("_MIPS_TUNE", mips_tune_info);	\
+ 								\
        if (ISA_MIPS1)						\
  	{							\
  	  builtin_define ("__mips=1");				\
*************** extern void		sbss_section PARAMS ((void)
*** 605,612 ****
  #define TARGET_ENDIAN_DEFAULT MASK_BIG_ENDIAN
  #endif
  
  #ifndef MIPS_ISA_DEFAULT
! #define MIPS_ISA_DEFAULT 1
  #endif
  
  #ifdef IN_LIBGCC2
--- 650,660 ----
  #define TARGET_ENDIAN_DEFAULT MASK_BIG_ENDIAN
  #endif
  
+ /* 'from-abi' makes a good default: you get whatever the ABI requires.  */
  #ifndef MIPS_ISA_DEFAULT
! #ifndef MIPS_CPU_STRING_DEFAULT
! #define MIPS_CPU_STRING_DEFAULT "from-abi"
! #endif
  #endif
  
  #ifdef IN_LIBGCC2
*************** extern void		sbss_section PARAMS ((void)
*** 656,662 ****
  #endif
  
  #ifndef MULTILIB_DEFAULTS
! #define MULTILIB_DEFAULTS { MULTILIB_ENDIAN_DEFAULT, MULTILIB_ISA_DEFAULT }
  #endif
  
  /* We must pass -EL to the linker by default for little endian embedded
--- 704,711 ----
  #endif
  
  #ifndef MULTILIB_DEFAULTS
! #define MULTILIB_DEFAULTS \
!     { MULTILIB_ENDIAN_DEFAULT, MULTILIB_ISA_DEFAULT, MULTILIB_ABI_DEFAULT }
  #endif
  
  /* We must pass -EL to the linker by default for little endian embedded
*************** extern void		sbss_section PARAMS ((void)
*** 675,694 ****
  #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,                                      \
        N_("Specify CPU for code generation purposes")},                  \
    { "ips",	&mips_isa_string,					\
        N_("Specify a Standard MIPS ISA")},				\
    { "entry",	&mips_entry_string,					\
        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,				\
--- 724,741 ----
  #define TARGET_OPTIONS							\
  {									\
    SUBTARGET_TARGET_OPTIONS						\
    { "tune=",    &mips_tune_string,			                \
        N_("Specify CPU for scheduling purposes")},                       \
    { "arch=",    &mips_arch_string,                                      \
        N_("Specify CPU for code generation purposes")},                  \
+   { "abi=", &mips_abi_string,						\
+       N_("Specify an ABI")},						\
    { "ips",	&mips_isa_string,					\
        N_("Specify a Standard MIPS ISA")},				\
    { "entry",	&mips_entry_string,					\
        N_("Use mips16 entry/exit psuedo ops")},				\
    { "no-mips16", &mips_no_mips16_string,				\
        N_("Don't use MIPS16 instructions")},				\
    { "no-flush-func", &mips_cache_flush_func,				\
        N_("Don't call any cache flush functions")},			\
    { "flush-func=", &mips_cache_flush_func,				\
*************** extern void		sbss_section PARAMS ((void)
*** 716,721 ****
--- 763,778 ----
  #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)
*** 911,917 ****
  /* 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;
--- 968,974 ----
  /* GAS_ASM_SPEC is passed when using gas, rather than the MIPS
     assembler.  */
  
! #define GAS_ASM_SPEC "%{mtune=*} %{v}"
  
  
  extern int mips_abi;
*************** extern int mips_abi;
*** 920,927 ****
  #define MIPS_ABI_DEFAULT ABI_32
  #endif
  
! #ifndef ABI_GAS_ASM_SPEC
! #define ABI_GAS_ASM_SPEC ""
  #endif
  
  /* TARGET_ASM_SPEC is used to select either MIPS_AS_ASM_SPEC or
--- 977,1019 ----
  #define MIPS_ABI_DEFAULT ABI_32
  #endif
  
! /* Use the most portable ABI flag for the ASM specs.  */
! 
! #if MIPS_ABI_DEFAULT == ABI_32
! #define MULTILIB_ABI_DEFAULT "-mabi=32"
! #define ASM_ABI_DEFAULT_SPEC "-32"
! #endif
! 
! #if MIPS_ABI_DEFAULT == ABI_O64
! #define MULTILIB_ABI_DEFAULT "-mabi=o64"
! #define ASM_ABI_DEFAULT_SPEC "-mabi=o64"
! #endif
! 
! #if MIPS_ABI_DEFAULT == ABI_N32
! #define MULTILIB_ABI_DEFAULT "-mabi=n32"
! #define ASM_ABI_DEFAULT_SPEC "-n32"
! #endif
! 
! #if MIPS_ABI_DEFAULT == ABI_64
! #define MULTILIB_ABI_DEFAULT "-mabi=64"
! #define ASM_ABI_DEFAULT_SPEC "-64"
! #endif
! 
! #if MIPS_ABI_DEFAULT == ABI_EABI
! #define MULTILIB_ABI_DEFAULT "-mabi=eabi"
! #define ASM_ABI_DEFAULT_SPEC "-mabi=eabi"
! #endif
! 
! #if MIPS_ABI_DEFAULT == ABI_MEABI
! /* Most GAS don't know about MEABI.  */
! #define MULTILIB_ABI_DEFAULT "-mabi=meabi"
! #define ASM_ABI_DEFAULT_SPEC ""
! #endif
! 
! /* Only ELF targets can switch the ABI.  */
! #ifndef OBJECT_FORMAT_ELF
! #undef ASM_ABI_DEFAULT_SPEC
! #define ASM_ABI_DEFAULT_SPEC ""
  #endif
  
  /* TARGET_ASM_SPEC is used to select either MIPS_AS_ASM_SPEC or
*************** extern int mips_abi;
*** 969,975 ****
  #define SUBTARGET_ASM_SPEC ""
  #endif
  
! /* ASM_SPEC is the set of arguments to pass to the assembler.  */
  
  #undef ASM_SPEC
  #define ASM_SPEC "\
--- 1061,1071 ----
  #define SUBTARGET_ASM_SPEC ""
  #endif
  
! /* ASM_SPEC is the set of arguments to pass to the assembler.  Note: we
!    pass -mgp32, -mgp64, -march, -mabi=eabi and -meabi=o64 regardless of
!    whether we're using GAS.  These options can only be used properly
!    with GAS, and it is better to get an error from a non-GAS assembler
!    than to silently generate bad code.  */
  
  #undef ASM_SPEC
  #define ASM_SPEC "\
*************** extern int mips_abi;
*** 978,984 ****
  %(subtarget_asm_optimizing_spec) \
  %(subtarget_asm_debugging_spec) \
  %{membedded-pic} \
! %{mabi=32:-32}%{mabi=o32:-32}%{mabi=n32:-n32}%{mabi=64:-64}%{mabi=n64:-64} \
  %(target_asm_spec) \
  %(subtarget_asm_spec)"
  
--- 1074,1082 ----
  %(subtarget_asm_optimizing_spec) \
  %(subtarget_asm_debugging_spec) \
  %{membedded-pic} \
! %{mabi=32:-32}%{mabi=n32:-n32}%{mabi=64:-64}%{mabi=n64:-64} \
! %{mabi=eabi} %{mabi=o64} %{!mabi*: %(asm_abi_default_spec)} \
! %{mgp32} %{mgp64} %{march=*} \
  %(target_asm_spec) \
  %(subtarget_asm_spec)"
  
*************** extern int mips_abi;
*** 1049,1063 ****
  #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)"
--- 1147,1152 ----
*************** extern int mips_abi;
*** 1088,1099 ****
    { "subtarget_cpp_spec", SUBTARGET_CPP_SPEC },				\
    { "mips_as_asm_spec", MIPS_AS_ASM_SPEC },				\
    { "gas_asm_spec", GAS_ASM_SPEC },					\
-   { "abi_gas_asm_spec", ABI_GAS_ASM_SPEC },                             \
    { "target_asm_spec", TARGET_ASM_SPEC },				\
    { "subtarget_mips_as_asm_spec", SUBTARGET_MIPS_AS_ASM_SPEC }, 	\
    { "subtarget_asm_optimizing_spec", SUBTARGET_ASM_OPTIMIZING_SPEC },	\
    { "subtarget_asm_debugging_spec", SUBTARGET_ASM_DEBUGGING_SPEC },	\
    { "subtarget_asm_spec", SUBTARGET_ASM_SPEC },				\
    { "endian_spec", ENDIAN_SPEC },					\
    SUBTARGET_EXTRA_SPECS
  
--- 1177,1188 ----
    { "subtarget_cpp_spec", SUBTARGET_CPP_SPEC },				\
    { "mips_as_asm_spec", MIPS_AS_ASM_SPEC },				\
    { "gas_asm_spec", GAS_ASM_SPEC },					\
    { "target_asm_spec", TARGET_ASM_SPEC },				\
    { "subtarget_mips_as_asm_spec", SUBTARGET_MIPS_AS_ASM_SPEC }, 	\
    { "subtarget_asm_optimizing_spec", SUBTARGET_ASM_OPTIMIZING_SPEC },	\
    { "subtarget_asm_debugging_spec", SUBTARGET_ASM_DEBUGGING_SPEC },	\
    { "subtarget_asm_spec", SUBTARGET_ASM_SPEC },				\
+   { "asm_abi_default_spec", ASM_ABI_DEFAULT_SPEC },			\
    { "endian_spec", ENDIAN_SPEC },					\
    SUBTARGET_EXTRA_SPECS
  
Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.217
diff -c -d -p -r1.217 mips.c
*** config/mips/mips.c	17 Jul 2002 09:24:08 -0000	1.217
--- config/mips/mips.c	18 Jul 2002 15:13:26 -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 ((const struct mips_cpu_info *));
! static void mips_set_tune	     PARAMS ((const struct mips_cpu_info *));
! 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 const struct mips_cpu_info *mips_parse_cpu   PARAMS ((const char *,
! 							      const char *));
! static const struct mips_cpu_info *mips_cpu_info_from_isa PARAMS ((int));
  static 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;
*** 294,302 ****
--- 302,312 ----
  
  /* The target cpu for code generation.  */
  enum processor_type mips_arch;
+ const struct mips_cpu_info *mips_arch_info;
  
  /* The target cpu for optimization and scheduling.  */
  enum processor_type mips_tune;
+ const struct mips_cpu_info *mips_tune_info;
  
  /* which instruction set architecture to use.  */
  int mips_isa;
*************** int mips_isa;
*** 305,311 ****
  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} */
--- 315,320 ----
*************** 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
--- 329,334 ----
*************** enum reg_class mips_char_to_class[256] =
*** 562,567 ****
--- 566,627 ----
    NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,
  };
  
+ /* A table describing all the processors gcc knows about.  The canonical
+    names will be matched in the order listed.  The first mention of an
+    ISA level is taken as the canonical name for that ISA.
+ 
+    It's probably not a good idea to use a straight 1, 2, 3 ... enumeration
+    for the processor macros, since it might lead to clashes when new ports
+    are contributed.  So the convention used here is that the five least
+    significant decimal digits are the processor's numerical designation.
+    Since several processors have the same designation, the next four
+    decimal digits can describe up to two letters.  As a prefix 'a' = 01,
+    'b' = 02, etc.  If the letter is a suffix, add 30 to this number.
+    For example, 'vr5000' = 221805000 and '4kp' = 4604000.  There's
+    no need to use prefixes for generic "r<number>" entries.
+ 
+    To ease comparison, please keep this table in the same order as
+    gas's mips_cpu_info_table[].  */
+ const struct mips_cpu_info mips_cpu_info_table[] = {
+   /* Entries for generic ISAs */
+   { "mips1", 0, 0, PROCESSOR_R3000, 1 },
+   { "mips2", 0, 0, PROCESSOR_R6000, 2 },
+   { "mips3", 0, 0, PROCESSOR_R4000, 3 },
+   { "mips4", 0, 0, PROCESSOR_R8000, 4 },
+   { "mips32", 0, 0, PROCESSOR_R4KC, 32 },
+   { "mips64", 0, 0, PROCESSOR_R5KC, 64 },
+ 
+   /* MIPS I */
+   { "r3000", "_MIPS_R3000", "3000", PROCESSOR_R3000, 1 },
+   { "r2000", "_MIPS_R2000", "2000", PROCESSOR_R3000, 1 }, /* = r3000 */
+   { "r3900", "_MIPS_R3900", "3900", PROCESSOR_R3900, 1 },
+ 
+   /* MIPS II */
+   { "r6000", "_MIPS_R6000", "6000", PROCESSOR_R6000, 2 },
+ 
+   /* MIPS III */
+   { "r4000", "_MIPS_R4000", "4000", PROCESSOR_R4000, 3 },
+   { "vr4100", "_MIPS_VR4100", "221804100", PROCESSOR_R4100, 3 },
+   { "vr4300", "_MIPS_VR4300", "221804300", PROCESSOR_R4300, 3 },
+   { "r4400", "_MIPS_R4400", "4400", PROCESSOR_R4000, 3 }, /* = r4000 */
+   { "r4600", "_MIPS_R4600", "4600", PROCESSOR_R4600, 3 },
+   { "orion", "_MIPS_R4600", 0, PROCESSOR_R4600, 3 }, /* = r4600 */
+   { "r4650", "_MIPS_R4650", "4650", PROCESSOR_R4650, 3 },
+ 
+   /* MIPS IV */
+   { "r8000", "_MIPS_R8000", "8000", PROCESSOR_R8000, 4 },
+   { "vr5000", "_MIPS_VR5000", "221805000", PROCESSOR_R5000, 4 },
+ 
+   /* MIPS 32 */
+   { "4kc", "_MIPS_4KC", "3304000", PROCESSOR_R4KC, 32 },
+   { "4kp", "_MIPS_4KP", "4604000", PROCESSOR_R4KC, 32 }, /* = 4kc */
+ 
+   /* MIPS 64 */
+   { "5kc", "_MIPS_5KC", "3305000", PROCESSOR_R5KC, 64 },
+   { "20kc", "_MIPS_20KC", "3320000", PROCESSOR_R20KC, 64 },
+   { 0, 0, 0, 0, 0 }
+ };
+ 
  /* 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)
*** 4931,4946 ****
    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;
  
--- 4991,5034 ----
    abort ();
  }
  
+ /* Set up globals to generate code for the ISA or processor
+    described by INFO.  */
+ 
+ static void
+ mips_set_architecture (info)
+      const struct mips_cpu_info *info;
+ {
+   if (info != 0)
+     {
+       mips_arch_info = info;
+       mips_arch = info->cpu;
+       mips_isa = info->isa;
+     }
+ }
+ 
+ 
+ /* Likewise for tuning.  */
+ 
+ static void
+ mips_set_tune (info)
+      const struct mips_cpu_info *info;
+ {
+   if (info != 0)
+     {
+       mips_tune_info = info;
+       mips_tune = info->cpu;
+     }
+ }
+ 
+ 
  /* 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 ()
*** 4958,5207 ****
      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)
--- 5046,5183 ----
      target_flags &= ~((TARGET_DEFAULT) & (MASK_SOFT_FLOAT | MASK_SINGLE_FLOAT));
  #endif
  
!   /* Interpret -mabi.  */
!   mips_abi = MIPS_ABI_DEFAULT;
!   if (mips_abi_string != 0)
!     {
!       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
! 	fatal_error ("bad value (%s) for -mabi= switch", mips_abi_string);
!     }
  
!   /* The following code determines the architecture, ABI and register size.
!      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.  */
  
!   if (mips_arch_string != 0)
!     mips_set_architecture (mips_parse_cpu ("-march", mips_arch_string));
! 
!   if (mips_tune_string != 0)
!     mips_set_tune (mips_parse_cpu ("-mtune", mips_tune_string));
! 
!   if (mips_isa_string != 0)
      {
!       /* Handle -mipsN.  */
!       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 (mips_arch_info != 0)
  	{
! 	  /* -march takes precedence over -mipsN, since it is more descriptive.
! 	     There's no harm in specifying both as long as the ISA levels
! 	     are the same.  */
! 	  if (mips_isa != level)
! 	    error ("-mips%d conflicts with the other architecture options, which specify a MIPS%d processor",
! 		   level, mips_isa);
  	}
        else
  	{
! 	  mips_set_architecture (mips_cpu_info_from_isa (level));
! 	  if (mips_arch_info == 0)
! 	    error ("bad value (%s) for -mips switch", mips_isa_string);
  	}
      }
  
!   if (mips_arch_info == 0)
      {
!       /* Provisionally select the default processor or ISA level.  */
  #ifdef MIPS_CPU_STRING_DEFAULT
!       mips_set_architecture (mips_parse_cpu ("default CPU",
! 					     MIPS_CPU_STRING_DEFAULT));
! #else
!       mips_set_architecture (mips_cpu_info_from_isa (MIPS_ISA_DEFAULT));
  #endif
+     }
  
!   if (ABI_NEEDS_64BIT_REGS && !ISA_HAS_64BIT_REGS)
!     error ("-march=%s is not compatible with the selected ABI",
! 	   mips_arch_info->name);
  
!   /* Optimize for mips_arch, unless -mtune selects a different processor.  */
!   if (mips_tune_info == 0)
!     mips_set_tune (mips_arch_info);
  
!   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_asm_file_start (stream)
*** 6361,6367 ****
    if (flag_verbose_asm)
      fprintf (stream, "\n%s -G value = %d, Arch = %s, ISA = %d\n",
  	     ASM_COMMENT_START,
! 	     mips_section_threshold, mips_arch_string, mips_isa);
  }
  
  /* If we are optimizing the global pointer, emit the text section now and any
--- 6337,6343 ----
    if (flag_verbose_asm)
      fprintf (stream, "\n%s -G value = %d, Arch = %s, ISA = %d\n",
  	     ASM_COMMENT_START,
! 	     mips_section_threshold, mips_arch_info->name, mips_isa);
  }
  
  /* If we are optimizing the global pointer, emit the text section now and any
*************** 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.
--- 10142,10261 ----
    /* 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 null.
  
!    A similar function exists in GAS.  */
  
! static const struct mips_cpu_info *
! mips_parse_cpu (option, cpu_string)
!      const char *option, *cpu_string;
! {
!   const struct mips_cpu_info *p;
!   const char *s;
  
!   /* In the past, we allowed upper-case CPU names, but it doesn't
!      work well with the multilib machinery.  */
!   for (s = cpu_string; *s != 0; s++)
!     if (ISUPPER (*s))
!       {
! 	warning ("the cpu name must be lower case");
! 	break;
!       }
! 
!   /* 'from-abi' selects the most compatible architecture for the given
!      ABI: MIPS I for 32-bit ABIs and MIPS III for 64-bit ABIs.  For the
!      EABIs, we have to decide whether we're using the 32-bit or 64-bit
!      version.  Look first at the -mgp options, if given, otherwise base
!      the choice on MASK_64BIT in TARGET_DEFAULT.  */
!   if (strcasecmp (cpu_string, "from-abi") == 0)
!     return mips_cpu_info_from_isa (ABI_NEEDS_32BIT_REGS ? 1
! 				   : ABI_NEEDS_64BIT_REGS ? 3
! 				   : (TARGET_64BIT ? 3 : 1));
! 
!   /* 'default' has traditionally been a no-op.  Probably not very useful.  */
!   if (strcasecmp (cpu_string, "default") == 0)
!     return 0;
! 
!   for (p = mips_cpu_info_table; p->name != 0; p++)
!     if (mips_matching_cpu_name_p (p->name, cpu_string))
!       return p;
! 
!   error ("bad value (%s) for %s", cpu_string, option);
!   return 0;
  }
  
+ 
+ /* Return the processor associated with the given ISA level, or null
+    if the ISA isn't valid.  */
+ 
+ static const struct mips_cpu_info *
+ mips_cpu_info_from_isa (isa)
+      int isa;
+ {
+   const struct mips_cpu_info *p;
+ 
+   for (p = mips_cpu_info_table; p->name != 0; p++)
+     if (p->isa == isa)
+       return p;
+ 
+   return 0;
+ }
+ 
  /* 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.
*** /dev/null	Tue Nov 14 21:44:43 2000
--- testsuite/gcc.dg/mips-args-1.c	Thu Jul 18 14:28:46 2002
***************
*** 0 ****
--- 1,53 ----
+ /* Check that certain preprocessor macros are defined, and do some
+    consistency checks.  */
+ /* { dg-do compile { target mips*-*-* } } */
+ 
+ /* Exactly one of these conditions must be true for ARCH, where ARCH
+    is _MIPS_ARCH or _MIPS_TUNE.  Add new checks as appropriate.  */
+ #define MIPS_ADD(ARCH)			\
+   (((ARCH) == 0)			\
+    + ((ARCH) == _MIPS_R2000)		\
+    + ((ARCH) == _MIPS_R3000)		\
+    + ((ARCH) == _MIPS_R3900)		\
+    + ((ARCH) == _MIPS_R6000)		\
+    + ((ARCH) == _MIPS_R4000)		\
+    + ((ARCH) == _MIPS_VR4100)		\
+    + ((ARCH) == _MIPS_VR4300)		\
+    + ((ARCH) == _MIPS_R4400)		\
+    + ((ARCH) == _MIPS_R4600)		\
+    + ((ARCH) == _MIPS_R4650)		\
+    + ((ARCH) == _MIPS_VR5000)		\
+    + ((ARCH) == _MIPS_R8000)		\
+    + ((ARCH) == _MIPS_4KC)		\
+    + ((ARCH) == _MIPS_4KP)		\
+    + ((ARCH) == _MIPS_5KC)		\
+    + ((ARCH) == _MIPS_20KC))
+ 
+ int f1[MIPS_ADD (_MIPS_ARCH) == 1 ? 1 : -1];
+ int f2[MIPS_ADD (_MIPS_TUNE) == 1 ? 1 : -1];
+ int f3[__mips_fpr == 32 || __mips_fpr == 64 ? 1 : -1];
+ 
+ /* Test complementary macro pairs: exactly one of each pair
+    must be defined.  */
+ 
+ #if defined (_R3000) == defined (_R4000)
+ #error _R3000 / _R4000 mismatch
+ #endif
+ 
+ #if defined (__mips_hard_float) == defined (__mips_soft_float)
+ #error __mips_hard_float / __mips_soft_float mismatch
+ #endif
+ 
+ #if defined (_MIPSEL) == defined (_MIPSEB)
+ #error _MIPSEL / _MIPSEB mismatch
+ #endif
+ 
+ /* Check for __mips64 consistency.  */
+ 
+ #if defined (__mips64) != defined (_R4000)
+ #error __mips64 / _R4000 mismatch
+ #endif
+ 
+ #if defined (__mips64) && __mips != 3 && __mips != 4 && __mips != 64
+ #error __mips64 / __mips mismatch
+ #endif
*** /dev/null	Tue Nov 14 21:44:43 2000
--- testsuite/gcc.dg/mips-args-2.c	Thu Jul 18 14:24:43 2002
***************
*** 0 ****
--- 1,15 ----
+ /* Check the _MIPSEB and _MIPSEL macros are accurate.  */
+ /* { dg-do run { target mips*-*-* } } */
+ short foo = 1;
+ int main ()
+ {
+   char *p = (char *) &foo;
+ 
+ #ifdef _MIPSEB
+   if (p[0] != 0 || p[1] != 1)
+ #else
+   if (p[0] != 1 || p[1] != 0)
+ #endif
+     abort ();
+   exit (0);
+ }
*** /dev/null	Tue Nov 14 21:44:43 2000
--- testsuite/gcc.dg/mips-args-3.c	Thu Jul 18 14:31:42 2002
***************
*** 0 ****
--- 1,35 ----
+ /* __mips, and related defines, guarantee that certain assembly
+    instructions can be used.  Check a few examples.  */
+ /* { dg-do run { target mips*-*-* } } */
+ typedef int int32 __attribute__ ((mode (SI)));
+ typedef int int64 __attribute__ ((mode (DI)));
+ int foo (float inf, int64 in64, int32 in32)
+ {
+   int64 res64;
+   int32 res32;
+ 
+ #if __mips != 1 && defined (__mips_hard_float)
+   __asm__ ("trunc.w.s %0, %1" : "=f" (res32) : "f" (inf));
+   if (res32 != 11)
+     abort ();
+ #endif
+ 
+ #if defined (__mips64)
+   __asm__ ("daddu %0, %1, %1" : "=r" (res64) : "r" (in64));
+   if (res64 != 50)
+     abort ();
+ #endif
+ 
+ #if (__mips == 4 || __mips == 32 || __mips == 64) && !defined (__mips16)
+   __asm__ ("move %0,%.\n\tmovn %0,%1,%2"
+ 	   : "=&r" (res32) : "r" (in32), "r" (in64 != 0));
+   if (res32 != 60)
+     abort ();
+ #endif
+ }
+ 
+ int main ()
+ {
+   foo (11.4f, 25, 60);
+   exit (0);
+ }

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