2010-10-09  Jie Zhang  <jie@codesourcery.com>

	Backport from mainline:

	gcc/
	2010-06-03  Paul Brook  <paul@codesourcery.com>
	* config/arm/arm.c (FL_TUNE): Define.
	(arm_default_cpu, arm_cpu_select): Remove.
	(all_cores): Populate core field.
	(arm_selected_arch, arm_selected_cpu, arm_selected_tune): New.
	(arm_find_cpu): New function.
	(arm_handle_option): Lookup cpu/architecture names.
	(arm_override_options): Cleanup mcpu/march/mtune handling.
	(arm_file_start): Ditto.

=== modified file 'gcc/config/arm/arm.c'
Index: gcc-4.5/gcc/config/arm/arm.c
===================================================================
--- gcc-4.5.orig/gcc/config/arm/arm.c
+++ gcc-4.5/gcc/config/arm/arm.c
@@ -550,9 +550,6 @@ enum processor_type arm_tune = arm_none;
 /* The current tuning set.  */
 const struct tune_params *current_tune;
 
-/* The default processor used if not overridden by commandline.  */
-static enum processor_type arm_default_cpu = arm_none;
-
 /* Which floating point hardware to schedule for.  */
 int arm_fpu_attr;
 
@@ -608,6 +605,10 @@ static int thumb_call_reg_needed;
 
 #define FL_IWMMXT     (1 << 29)	      /* XScale v2 or "Intel Wireless MMX technology".  */
 
+/* Flags that only effect tuning, not available instructions.  */
+#define FL_TUNE		(FL_WBUF | FL_VFPV2 | FL_STRONG | FL_LDSCHED \
+			 | FL_CO_PROC)
+
 #define FL_FOR_ARCH2	FL_NOTM
 #define FL_FOR_ARCH3	(FL_FOR_ARCH2 | FL_MODE32)
 #define FL_FOR_ARCH3M	(FL_FOR_ARCH3 | FL_ARCH3M)
@@ -808,7 +809,7 @@ static const struct processors all_cores
 {
   /* ARM Cores */
 #define ARM_CORE(NAME, IDENT, ARCH, FLAGS, COSTS) \
-  {NAME, arm_none, #ARCH, FLAGS | FL_FOR_ARCH##ARCH, &arm_##COSTS##_tune},
+  {NAME, IDENT, #ARCH, FLAGS | FL_FOR_ARCH##ARCH, &arm_##COSTS##_tune},
 #include "arm-cores.def"
 #undef ARM_CORE
   {NULL, arm_none, NULL, 0, NULL}
@@ -850,29 +851,12 @@ static const struct processors all_archi
   {NULL, arm_none, NULL, 0 , NULL}
 };
 
-struct arm_cpu_select
-{
-  const char *              string;
-  const char *              name;
-  const struct processors * processors;
-};
-
-/* This is a magic structure.  The 'string' field is magically filled in
-   with a pointer to the value specified by the user on the command line
-   assuming that the user has specified such a value.  */
-
-static struct arm_cpu_select arm_select[] =
-{
-  /* string	  name            processors  */
-  { NULL,	"-mcpu=",	all_cores  },
-  { NULL,	"-march=",	all_architectures },
-  { NULL,	"-mtune=",	all_cores }
-};
 
-/* Defines representing the indexes into the above table.  */
-#define ARM_OPT_SET_CPU 0
-#define ARM_OPT_SET_ARCH 1
-#define ARM_OPT_SET_TUNE 2
+/* These are populated as commandline arguments are processed, or NULL
+   if not specified.  */
+static const struct processors *arm_selected_arch;
+static const struct processors *arm_selected_cpu;
+static const struct processors *arm_selected_tune;
 
 /* The name of the preprocessor macro to define for this architecture.  */
 
@@ -1234,6 +1218,24 @@ arm_gimplify_va_arg_expr (tree valist, t
   return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
 }
 
+/* Lookup NAME in SEL.  */
+
+static const struct processors *
+arm_find_cpu (const char *name, const struct processors *sel, const char *desc)
+{
+  if (!(name && *name))
+    return NULL;
+
+  for (; sel->name != NULL; sel++)
+    {
+      if (streq (name, sel->name))
+	return sel;
+    }
+
+  error ("bad value (%s) for %s switch", name, desc);
+  return NULL;
+}
+
 /* Implement TARGET_HANDLE_OPTION.  */
 
 static bool
@@ -1242,11 +1244,11 @@ arm_handle_option (size_t code, const ch
   switch (code)
     {
     case OPT_march_:
-      arm_select[1].string = arg;
+      arm_selected_arch = arm_find_cpu(arg, all_architectures, "-march");
       return true;
 
     case OPT_mcpu_:
-      arm_select[0].string = arg;
+      arm_selected_cpu = arm_find_cpu(arg, all_cores, "-mcpu");
       return true;
 
     case OPT_mhard_float:
@@ -1258,7 +1260,7 @@ arm_handle_option (size_t code, const ch
       return true;
 
     case OPT_mtune_:
-      arm_select[2].string = arg;
+      arm_selected_tune = arm_find_cpu(arg, all_cores, "-mtune");
       return true;
 
     default:
@@ -1358,88 +1360,52 @@ void
 arm_override_options (void)
 {
   unsigned i;
-  enum processor_type target_arch_cpu = arm_none;
-  enum processor_type selected_cpu = arm_none;
 
-  /* Set up the flags based on the cpu/architecture selected by the user.  */
-  for (i = ARRAY_SIZE (arm_select); i--;)
+  if (arm_selected_arch)
     {
-      struct arm_cpu_select * ptr = arm_select + i;
-
-      if (ptr->string != NULL && ptr->string[0] != '\0')
-        {
-	  const struct processors * sel;
-
-          for (sel = ptr->processors; sel->name != NULL; sel++)
-            if (streq (ptr->string, sel->name))
-              {
-		/* Set the architecture define.  */
-		if (i != ARM_OPT_SET_TUNE)
-		  sprintf (arm_arch_name, "__ARM_ARCH_%s__", sel->arch);
-
-		/* Determine the processor core for which we should
-		   tune code-generation.  */
-		if (/* -mcpu= is a sensible default.  */
-		    i == ARM_OPT_SET_CPU
-		    /* -mtune= overrides -mcpu= and -march=.  */
-		    || i == ARM_OPT_SET_TUNE)
-		  arm_tune = (enum processor_type) (sel - ptr->processors);
-
-		/* Remember the CPU associated with this architecture.
-		   If no other option is used to set the CPU type,
-		   we'll use this to guess the most suitable tuning
-		   options.  */
-		if (i == ARM_OPT_SET_ARCH)
-		  target_arch_cpu = sel->core;
-
-		if (i == ARM_OPT_SET_CPU)
-		  selected_cpu = (enum processor_type) (sel - ptr->processors);
-		  
-		if (i != ARM_OPT_SET_TUNE)
-		  {
-		    /* If we have been given an architecture and a processor
-		       make sure that they are compatible.  We only generate
-		       a warning though, and we prefer the CPU over the
-		       architecture.  */
-		    if (insn_flags != 0 && (insn_flags ^ sel->flags))
-		      warning (0, "switch -mcpu=%s conflicts with -march= switch",
-			       ptr->string);
-
-		    insn_flags = sel->flags;
-		  }
-
-                break;
-              }
+      if (arm_selected_cpu)
+	{
+	  /* Check for conflict between mcpu and march */
+	  if ((arm_selected_cpu->flags ^ arm_selected_arch->flags) & ~FL_TUNE)
+	    {
+	      warning (0, "switch -mcpu=%s conflicts with -march=%s switch",
+		       arm_selected_cpu->name, arm_selected_arch->name);
+	      /* -march wins for code generation.
+	         -mcpu wins for default tuning.  */
+	      if (!arm_selected_tune)
+		arm_selected_tune = arm_selected_cpu;
 
-          if (sel->name == NULL)
-            error ("bad value (%s) for %s switch", ptr->string, ptr->name);
-        }
+	      arm_selected_cpu = arm_selected_arch;
+	    }
+	  else
+	    /* -mcpu wins.  */
+	    arm_selected_arch = NULL;
+	}
+      else
+	/* Pick a CPU based on the architecture.  */
+	arm_selected_cpu = arm_selected_arch;
     }
 
-  /* Guess the tuning options from the architecture if necessary.  */
-  if (arm_tune == arm_none)
-    arm_tune = target_arch_cpu;
-
   /* If the user did not specify a processor, choose one for them.  */
-  if (insn_flags == 0)
+  if (!arm_selected_cpu)
     {
       const struct processors * sel;
       unsigned int        sought;
 
-      selected_cpu = (enum processor_type) TARGET_CPU_DEFAULT;
-      if (selected_cpu == arm_none)
+      arm_selected_cpu = &all_cores[TARGET_CPU_DEFAULT];
+      if (!arm_selected_cpu->name)
 	{
 #ifdef SUBTARGET_CPU_DEFAULT
 	  /* Use the subtarget default CPU if none was specified by
 	     configure.  */
-	  selected_cpu = (enum processor_type) SUBTARGET_CPU_DEFAULT;
+	  arm_selected_cpu = &all_cores[SUBTARGET_CPU_DEFAULT];
 #endif
 	  /* Default to ARM6.  */
-	  if (selected_cpu == arm_none)
-	    selected_cpu = arm6;
+	  if (arm_selected_cpu->name)
+	    arm_selected_cpu = &all_cores[arm6];
 	}
-      sel = &all_cores[selected_cpu];
 
+      sel = arm_selected_cpu;
       insn_flags = sel->flags;
 
       /* Now check to see if the user has specified some command line
@@ -1500,17 +1466,21 @@ arm_override_options (void)
 	      sel = best_fit;
 	    }
 
-	  insn_flags = sel->flags;
+	  arm_selected_cpu = sel;
 	}
-      sprintf (arm_arch_name, "__ARM_ARCH_%s__", sel->arch);
-      arm_default_cpu = (enum processor_type) (sel - all_cores);
-      if (arm_tune == arm_none)
-	arm_tune = arm_default_cpu;
     }
 
-  /* The processor for which we should tune should now have been
-     chosen.  */
-  gcc_assert (arm_tune != arm_none);
+  gcc_assert (arm_selected_cpu);
+  /* The selected cpu may be an architecture, so lookup tuning by core ID.  */
+  if (!arm_selected_tune)
+    arm_selected_tune = &all_cores[arm_selected_cpu->core];
+
+  sprintf (arm_arch_name, "__ARM_ARCH_%s__", arm_selected_cpu->arch);
+  insn_flags = arm_selected_cpu->flags;
+
+  arm_tune = arm_selected_tune->core;
+  tune_flags = arm_selected_tune->flags;
+  current_tune = arm_selected_tune->tune;
 
   if (arm_tune == cortexa8 && optimize >= 3)
     {
@@ -1522,9 +1492,6 @@ arm_override_options (void)
 	align_jumps = 16;
     }
 
-  tune_flags = all_cores[(int)arm_tune].flags;
-  current_tune = all_cores[(int)arm_tune].tune;
-
   if (target_fp16_format_name)
     {
       for (i = 0; i < ARRAY_SIZE (all_fp16_formats); i++)
@@ -1907,7 +1874,7 @@ arm_override_options (void)
   /* Enable -mfix-cortex-m3-ldrd by default for Cortex-M3 cores.  */
   if (fix_cm3_ldrd == 2)
     {
-      if (selected_cpu == cortexm3)
+      if (arm_selected_cpu->core == cortexm3)
 	fix_cm3_ldrd = 1;
       else
 	fix_cm3_ldrd = 0;
@@ -21235,13 +21202,10 @@ arm_file_start (void)
   if (TARGET_BPABI)
     {
       const char *fpu_name;
-      if (arm_select[0].string)
-	asm_fprintf (asm_out_file, "\t.cpu %s\n", arm_select[0].string);
-      else if (arm_select[1].string)
-	asm_fprintf (asm_out_file, "\t.arch %s\n", arm_select[1].string);
+      if (arm_selected_arch)
+	asm_fprintf (asm_out_file, "\t.arch %s\n", arm_selected_arch->name);
       else
-	asm_fprintf (asm_out_file, "\t.cpu %s\n",
-		     all_cores[arm_default_cpu].name);
+	asm_fprintf (asm_out_file, "\t.cpu %s\n", arm_selected_cpu->name);
 
       if (TARGET_SOFT_FLOAT)
 	{
