Patchwork Fix 59828 - Broken assembly on ppc* with two -mcpu= options

login
register
mail settings
Submitter Alan Modra
Date Jan. 18, 2014, 3:58 a.m.
Message ID <20140118035811.GI5390@bubble.grove.modra.org>
Download mbox | patch
Permalink /patch/312262/
State New
Headers show

Comments

Alan Modra - Jan. 18, 2014, 3:58 a.m.
This patch cures PR59828 by translating all the -mcpu options at once,
in order, to their equivalent assembler -m options by using a new spec
function.  In the process this removes some duplication.

All the rhs of -mcpu= options from the command line can be extracted
with %{mcpu=*:%*}, and then passed to a spec function.  The new
function was mostly already there in driver-rs6000.c to support
-mcpu=native.  However, the new spec function must be called for
non-native configurations, so it's necessary to split driver-rs6000.c
into two files, one for native support, the other always compiled in.

I deliberately omitted converting over aix42.h, aix51.h and aix52.h
because ASM_CPU_SPEC in those files translates -mcpu to different
assembly options than the aix -mcpu=native support.  Presumably the
assembler on older versions of aix doesn't understand the newer
options..

Bootstrapped and regression tested powerpc64-linux natively, and
x86_64-linux to powerpc64-linux cross.  OK to apply?

	PR target/59828
	* config/rs6000/driver-rs6000.c (asm_names): Add entries for "native".
	(translate_cpu_to_asm): New function.
	Move everything else to..
	* config/rs6000/driver-nat-rs6000.c: ..here.  New file.
	(host_detect_local_cpu): Make use of translate_cpu_to_asm.
	* config/rs6000/rs6000.h (ASM_CPU_SPEC): Likewise.
	(translate_cpu_to_asm): Declare.
	(EXTRA_SPEC_FUNCTIONS): Add translate_cpu_to_asm.
	* config/rs6000/x-rs6000: Adjust for renamed file.
	* config/rs6000/t-rs6000: Add driver-rs6000.o rule.
	* config/rs6000/aix53.h (ASM_CPU_SPEC): Use translate_cpu_to_asm.
	* config/rs6000/aix61.h (ASM_CPU_SPEC): Likewise.
	* config.gcc (extra_gcc_objs): Add driver-rs6000.o.
	* config.host (host_extra_gcc_objs): Remove driver-rs6000.o, add
	driver-nat-rs6000.o.
David Edelsohn - Jan. 20, 2015, 3:43 a.m.
On Fri, Jan 17, 2014 at 10:58 PM, Alan Modra <amodra@gmail.com> wrote:
> This patch cures PR59828 by translating all the -mcpu options at once,
> in order, to their equivalent assembler -m options by using a new spec
> function.  In the process this removes some duplication.
>
> All the rhs of -mcpu= options from the command line can be extracted
> with %{mcpu=*:%*}, and then passed to a spec function.  The new
> function was mostly already there in driver-rs6000.c to support
> -mcpu=native.  However, the new spec function must be called for
> non-native configurations, so it's necessary to split driver-rs6000.c
> into two files, one for native support, the other always compiled in.
>
> I deliberately omitted converting over aix42.h, aix51.h and aix52.h
> because ASM_CPU_SPEC in those files translates -mcpu to different
> assembly options than the aix -mcpu=native support.  Presumably the
> assembler on older versions of aix doesn't understand the newer
> options..
>
> Bootstrapped and regression tested powerpc64-linux natively, and
> x86_64-linux to powerpc64-linux cross.  OK to apply?
>
>         PR target/59828
>         * config/rs6000/driver-rs6000.c (asm_names): Add entries for "native".
>         (translate_cpu_to_asm): New function.
>         Move everything else to..
>         * config/rs6000/driver-nat-rs6000.c: ..here.  New file.
>         (host_detect_local_cpu): Make use of translate_cpu_to_asm.
>         * config/rs6000/rs6000.h (ASM_CPU_SPEC): Likewise.
>         (translate_cpu_to_asm): Declare.
>         (EXTRA_SPEC_FUNCTIONS): Add translate_cpu_to_asm.
>         * config/rs6000/x-rs6000: Adjust for renamed file.
>         * config/rs6000/t-rs6000: Add driver-rs6000.o rule.
>         * config/rs6000/aix53.h (ASM_CPU_SPEC): Use translate_cpu_to_asm.
>         * config/rs6000/aix61.h (ASM_CPU_SPEC): Likewise.
>         * config.gcc (extra_gcc_objs): Add driver-rs6000.o.
>         * config.host (host_extra_gcc_objs): Remove driver-rs6000.o, add
>         driver-nat-rs6000.o.

Alan,

ASM_CPU_SPEC is too fragile a mechanism.  I would much prefer to
expand on the ".machine" directive that I added to
rs6000_file_start().  The initial implementation explicitly avoids
.machine when -mcpu= or --with-cpu= is present as a conservative
start.

It seems much better to select a .machine directive based on the
actual target ISA flag bits enabled than translating CPU command line
options to ASM options.  Patches to replace ASM_CPU_SPEC with .machine
and expand functionality for AIX are welcome.

Thanks, David
Alan Modra - Jan. 20, 2015, 5:41 a.m.
On Mon, Jan 19, 2015 at 10:43:29PM -0500, David Edelsohn wrote:
> On Fri, Jan 17, 2014 at 10:58 PM, Alan Modra <amodra@gmail.com> wrote:
> > This patch cures PR59828 by translating all the -mcpu options at once,
> > in order, to their equivalent assembler -m options by using a new spec
> > function.  In the process this removes some duplication.
> 
> ASM_CPU_SPEC is too fragile a mechanism.  I would much prefer to
> expand on the ".machine" directive that I added to
> rs6000_file_start().  The initial implementation explicitly avoids
> .machine when -mcpu= or --with-cpu= is present as a conservative
> start.
> 
> It seems much better to select a .machine directive based on the
> actual target ISA flag bits enabled than translating CPU command line
> options to ASM options.  Patches to replace ASM_CPU_SPEC with .machine
> and expand functionality for AIX are welcome.

This might make sense when looking only at gcc, but when considering
the whole toolchain I think you'll run into difficulty.  gas and other
powerpc assemblers have always been invoked with -m options to select
the cpu, so if you do away with ASM_CPU_SPEC and rely on .machine then
you will be exercising the assembler in a new way.  I am sure that
this will not work for all powerpc assemblers currently in use.
David Edelsohn - Jan. 20, 2015, 2:26 p.m.
On Tue, Jan 20, 2015 at 12:41 AM, Alan Modra <amodra@gmail.com> wrote:
> On Mon, Jan 19, 2015 at 10:43:29PM -0500, David Edelsohn wrote:
>> On Fri, Jan 17, 2014 at 10:58 PM, Alan Modra <amodra@gmail.com> wrote:
>> > This patch cures PR59828 by translating all the -mcpu options at once,
>> > in order, to their equivalent assembler -m options by using a new spec
>> > function.  In the process this removes some duplication.
>>
>> ASM_CPU_SPEC is too fragile a mechanism.  I would much prefer to
>> expand on the ".machine" directive that I added to
>> rs6000_file_start().  The initial implementation explicitly avoids
>> .machine when -mcpu= or --with-cpu= is present as a conservative
>> start.
>>
>> It seems much better to select a .machine directive based on the
>> actual target ISA flag bits enabled than translating CPU command line
>> options to ASM options.  Patches to replace ASM_CPU_SPEC with .machine
>> and expand functionality for AIX are welcome.
>
> This might make sense when looking only at gcc, but when considering
> the whole toolchain I think you'll run into difficulty.  gas and other
> powerpc assemblers have always been invoked with -m options to select
> the cpu, so if you do away with ASM_CPU_SPEC and rely on .machine then
> you will be exercising the assembler in a new way.  I am sure that
> this will not work for all powerpc assemblers currently in use.

It is stressing .machine more than that feature has been in the past,
but it is functionality that is suppose to work.  .machine already has
been stressed more with IFUNC pushing and popping ISAs.

Are you concerned about the fundamental functionality of the pseudo-op
or a particular GAS release missing support for a particular ISA?  AIX
supports .machine, but I think that it expects slightly different
processor names.  I am not certain about LLVM-AS, but it normally is
not fed external assembly language files.

Thanks, David
Alan Modra - Jan. 21, 2015, 12:02 a.m.
On Tue, Jan 20, 2015 at 09:26:12AM -0500, David Edelsohn wrote:
> On Tue, Jan 20, 2015 at 12:41 AM, Alan Modra <amodra@gmail.com> wrote:
> > On Mon, Jan 19, 2015 at 10:43:29PM -0500, David Edelsohn wrote:
> >> On Fri, Jan 17, 2014 at 10:58 PM, Alan Modra <amodra@gmail.com> wrote:
> >> > This patch cures PR59828 by translating all the -mcpu options at once,
> >> > in order, to their equivalent assembler -m options by using a new spec
> >> > function.  In the process this removes some duplication.
> >>
> >> ASM_CPU_SPEC is too fragile a mechanism.  I would much prefer to
> >> expand on the ".machine" directive that I added to
> >> rs6000_file_start().  The initial implementation explicitly avoids
> >> .machine when -mcpu= or --with-cpu= is present as a conservative
> >> start.
> >>
> >> It seems much better to select a .machine directive based on the
> >> actual target ISA flag bits enabled than translating CPU command line
> >> options to ASM options.  Patches to replace ASM_CPU_SPEC with .machine
> >> and expand functionality for AIX are welcome.
> >
> > This might make sense when looking only at gcc, but when considering
> > the whole toolchain I think you'll run into difficulty.  gas and other
> > powerpc assemblers have always been invoked with -m options to select
> > the cpu, so if you do away with ASM_CPU_SPEC and rely on .machine then
> > you will be exercising the assembler in a new way.  I am sure that
> > this will not work for all powerpc assemblers currently in use.
> 
> It is stressing .machine more than that feature has been in the past,
> but it is functionality that is suppose to work.  .machine already has
> been stressed more with IFUNC pushing and popping ISAs.
> 
> Are you concerned about the fundamental functionality of the pseudo-op
> or a particular GAS release missing support for a particular ISA?  AIX
> supports .machine, but I think that it expects slightly different
> processor names.  I am not certain about LLVM-AS, but it normally is
> not fed external assembly language files.

I'm concerned about initialisation that might happen based on a -m
option that doesn't happen with .machine.  A quick look over the
gas source showed we currently have at least one case like this:
ppc_dwarf2_line_min_insn_length is only set from command line -m
options.  This means that if you want debug with VLE insns, you cannot
currently invoke gas without -mvle.  ".machine vle" by itself won't
work.  I think there may be other similar problems with setting the
bfd arch/mach pair.
David Edelsohn - Jan. 21, 2015, 7:01 p.m.
On Tue, Jan 20, 2015 at 7:02 PM, Alan Modra <amodra@gmail.com> wrote:
> On Tue, Jan 20, 2015 at 09:26:12AM -0500, David Edelsohn wrote:
>> On Tue, Jan 20, 2015 at 12:41 AM, Alan Modra <amodra@gmail.com> wrote:
>> > On Mon, Jan 19, 2015 at 10:43:29PM -0500, David Edelsohn wrote:
>> >> On Fri, Jan 17, 2014 at 10:58 PM, Alan Modra <amodra@gmail.com> wrote:
>> >> > This patch cures PR59828 by translating all the -mcpu options at once,
>> >> > in order, to their equivalent assembler -m options by using a new spec
>> >> > function.  In the process this removes some duplication.
>> >>
>> >> ASM_CPU_SPEC is too fragile a mechanism.  I would much prefer to
>> >> expand on the ".machine" directive that I added to
>> >> rs6000_file_start().  The initial implementation explicitly avoids
>> >> .machine when -mcpu= or --with-cpu= is present as a conservative
>> >> start.
>> >>
>> >> It seems much better to select a .machine directive based on the
>> >> actual target ISA flag bits enabled than translating CPU command line
>> >> options to ASM options.  Patches to replace ASM_CPU_SPEC with .machine
>> >> and expand functionality for AIX are welcome.
>> >
>> > This might make sense when looking only at gcc, but when considering
>> > the whole toolchain I think you'll run into difficulty.  gas and other
>> > powerpc assemblers have always been invoked with -m options to select
>> > the cpu, so if you do away with ASM_CPU_SPEC and rely on .machine then
>> > you will be exercising the assembler in a new way.  I am sure that
>> > this will not work for all powerpc assemblers currently in use.
>>
>> It is stressing .machine more than that feature has been in the past,
>> but it is functionality that is suppose to work.  .machine already has
>> been stressed more with IFUNC pushing and popping ISAs.
>>
>> Are you concerned about the fundamental functionality of the pseudo-op
>> or a particular GAS release missing support for a particular ISA?  AIX
>> supports .machine, but I think that it expects slightly different
>> processor names.  I am not certain about LLVM-AS, but it normally is
>> not fed external assembly language files.
>
> I'm concerned about initialisation that might happen based on a -m
> option that doesn't happen with .machine.  A quick look over the
> gas source showed we currently have at least one case like this:
> ppc_dwarf2_line_min_insn_length is only set from command line -m
> options.  This means that if you want debug with VLE insns, you cannot
> currently invoke gas without -mvle.  ".machine vle" by itself won't
> work.  I think there may be other similar problems with setting the
> bfd arch/mach pair.

We can leave VLE unaffected and ensure that rs6000_file_start does not
emit a .machine directive for VLE or emits both .machine vle and the
driver retains the -mvle assembler command line option.

This does not need to be one extreme or the other.  We can remove as
much -mcpu=XXX as we can, which should avoid most of the conflicting
and duplicative directives.  In the mean time, GAS can be fixed.

I want to avoid duplicating the -mcpu parsing logic or the Rube
Goldberg mechanism to re-generate the -mXXX assembler directive.

Thanks, David
Alan Modra - Jan. 28, 2015, 12:27 a.m.
On Wed, Jan 21, 2015 at 02:01:44PM -0500, David Edelsohn wrote:
> I want to avoid duplicating the -mcpu parsing logic or the Rube
> Goldberg mechanism to re-generate the -mXXX assembler directive.

Oh well, I had fun writing the patch.  I thought it reasonably
elegant, meeting the goals you state above.  You think differently,
and I won't push my approach further.  The bug isn't important enough
to argue over.
David Edelsohn - Jan. 28, 2015, 12:53 a.m.
On Tue, Jan 27, 2015 at 7:27 PM, Alan Modra <amodra@gmail.com> wrote:
> On Wed, Jan 21, 2015 at 02:01:44PM -0500, David Edelsohn wrote:
>> I want to avoid duplicating the -mcpu parsing logic or the Rube
>> Goldberg mechanism to re-generate the -mXXX assembler directive.
>
> Oh well, I had fun writing the patch.  I thought it reasonably
> elegant, meeting the goals you state above.  You think differently,
> and I won't push my approach further.  The bug isn't important enough
> to argue over.

Alan,

I am sorry that you do not want to finish the patch.  I don't
understand why you find the command line argument so appealing when
the .machine pseudo-op was designed for this purpose.

Thanks, David

Patch

Index: gcc/config/rs6000/driver-rs6000.c
===================================================================
--- gcc/config/rs6000/driver-rs6000.c	(revision 206599)
+++ gcc/config/rs6000/driver-rs6000.c	(working copy)
@@ -21,325 +21,9 @@ 
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include <stdlib.h>
 
-#ifdef _AIX
-# include <sys/systemcfg.h>
-#endif
+/* Array to map -mcpu= names to the switches passed to the assembler.  */
 
-#ifdef __linux__
-# include <link.h>
-#endif
-
-#if defined (__APPLE__) || (__FreeBSD__)
-# include <sys/types.h>
-# include <sys/sysctl.h>
-#endif
-
-const char *host_detect_local_cpu (int argc, const char **argv);
-
-#if GCC_VERSION >= 0
-
-/* Returns parameters that describe L1_ASSOC associative cache of size
-   L1_SIZEKB with lines of size L1_LINE, and L2_SIZEKB.  */
-
-static char *
-describe_cache (unsigned l1_sizekb, unsigned l1_line,
-		unsigned l1_assoc ATTRIBUTE_UNUSED, unsigned l2_sizekb)
-{
-  char l1size[1000], line[1000], l2size[1000];
-
-  /* At the moment, gcc middle-end does not use the information about the
-     associativity of the cache.  */
-
-  sprintf (l1size, "--param l1-cache-size=%u", l1_sizekb);
-  sprintf (line, "--param l1-cache-line-size=%u", l1_line);
-  sprintf (l2size, "--param l2-cache-size=%u", l2_sizekb);
-
-  return concat (l1size, " ", line, " ", l2size, " ", NULL);
-}
-
-#ifdef __APPLE__
-
-/* Returns the description of caches on Darwin.  */
-
-static char *
-detect_caches_darwin (void)
-{
-  unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
-  size_t len = 4;
-  static int l1_size_name[2] = { CTL_HW, HW_L1DCACHESIZE };
-  static int l1_line_name[2] = { CTL_HW, HW_CACHELINE };
-  static int l2_size_name[2] = { CTL_HW, HW_L2CACHESIZE };
-
-  sysctl (l1_size_name, 2, &l1_sizekb, &len, NULL, 0);
-  sysctl (l1_line_name, 2, &l1_line, &len, NULL, 0);
-  sysctl (l2_size_name, 2, &l2_sizekb, &len, NULL, 0);
-  l1_assoc = 0;
-
-  return describe_cache (l1_sizekb / 1024, l1_line, l1_assoc,
-			 l2_sizekb / 1024);
-}
-
-static const char *
-detect_processor_darwin (void)
-{
-  unsigned int proc;
-  size_t len = 4;
-
-  sysctlbyname ("hw.cpusubtype", &proc, &len, NULL, 0);
-
-  if (len > 0)
-    switch (proc)
-      {
-      case 1:
-	return "601";
-      case 2:
-	return "602";
-      case 3:
-	return "603";
-      case 4:
-      case 5:
-	return "603e";
-      case 6:
-	return "604";
-      case 7:
-	return "604e";
-      case 8:
-	return "620";
-      case 9:
-	return "750";
-      case 10:
-	return "7400";
-      case 11:
-	return "7450";
-      case 100:
-	return "970";
-      default:
-	return "powerpc";
-      }
-
-  return "powerpc";
-}
-
-#endif /* __APPLE__ */
-
-#ifdef __FreeBSD__
-
-/* Returns the description of caches on FreeBSD PPC.  */
-
-static char *
-detect_caches_freebsd (void)
-{
-  unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
-  size_t len = 4;
-
-  /* Currently, as of FreeBSD-7.0, there is only the cacheline_size
-     available via sysctl.  */
-  sysctlbyname ("machdep.cacheline_size", &l1_line, &len, NULL, 0);
-
-  l1_sizekb = 32;
-  l1_assoc = 0;
-  l2_sizekb = 512;
-
-  return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb);
-}
-
-/* Currently returns default powerpc.  */
-static const char *
-detect_processor_freebsd (void)
-{
-  return "powerpc";
-}
-
-#endif /* __FreeBSD__  */
-
-#ifdef __linux__
-
-/* Returns AT_PLATFORM if present, otherwise generic PowerPC.  */
-
-static const char *
-elf_platform (void)
-{
-  int fd;
-
-  fd = open ("/proc/self/auxv", O_RDONLY);
-
-  if (fd != -1)
-    {
-      char buf[1024];
-      ElfW(auxv_t) *av;
-      ssize_t n;
-
-      n = read (fd, buf, sizeof (buf));
-      close (fd);
-
-      if (n > 0)
-	{
-	  for (av = (ElfW(auxv_t) *) buf; av->a_type != AT_NULL; ++av)
-	    switch (av->a_type)
-	      {
-	      case AT_PLATFORM:
-		return (const char *) av->a_un.a_val;
-
-	      default:
-		break;
-	      }
-	}
-    }
-  return NULL;
-}
-
-/* Returns AT_DCACHEBSIZE if present, otherwise generic 32.  */
-
-static int
-elf_dcachebsize (void)
-{
-  int fd;
-
-  fd = open ("/proc/self/auxv", O_RDONLY);
-
-  if (fd != -1)
-    {
-      char buf[1024];
-      ElfW(auxv_t) *av;
-      ssize_t n;
-
-      n = read (fd, buf, sizeof (buf));
-      close (fd);
-
-      if (n > 0)
-	{
-	  for (av = (ElfW(auxv_t) *) buf; av->a_type != AT_NULL; ++av)
-	    switch (av->a_type)
-	      {
-	      case AT_DCACHEBSIZE:
-		return av->a_un.a_val;
-
-	      default:
-		break;
-	      }
-	}
-    }
-  return 32;
-}
-
-/* Returns the description of caches on Linux.  */
-
-static char *
-detect_caches_linux (void)
-{
-  unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
-  const char *platform;
-
-  platform = elf_platform ();
-
-  if (platform != NULL)
-    {
-      l1_line = 128;
-
-      if (platform[5] == '6')
-	/* POWER6 and POWER6x */
-	l1_sizekb = 64;
-      else
-	l1_sizekb = 32;
-    }
-  else
-    {
-      l1_line = elf_dcachebsize ();
-      l1_sizekb = 32;
-    }
-
-  l1_assoc = 0;
-  l2_sizekb = 512;
-
-  return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb);
-}
-
-static const char *
-detect_processor_linux (void)
-{
-  const char *platform;
-
-  platform = elf_platform ();
-
-  if (platform != NULL)
-    return platform;
-  else
-    return "powerpc";
-}
-
-#endif /* __linux__ */
-
-#ifdef _AIX
-/* Returns the description of caches on AIX.  */
-
-static char *
-detect_caches_aix (void)
-{
-  unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
-
-  l1_sizekb = _system_configuration.dcache_size / 1024;
-  l1_line = _system_configuration.dcache_line;
-  l1_assoc = _system_configuration.dcache_asc;
-  l2_sizekb = _system_configuration.L2_cache_size / 1024;
-
-  return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb);
-}
-
-
-/* Returns the processor implementation on AIX.  */
-
-static const char *
-detect_processor_aix (void)
-{
-  switch (_system_configuration.implementation)
-    {
-    case 0x0008:
-      return "601";
-
-    case 0x0020:
-      return "603";
-
-    case 0x0010:
-      return "604";
-
-    case 0x0040:
-      return "620";
-
-    case 0x0080:
-      return "630";
-
-    case 0x0100:
-    case 0x0200:
-    case 0x0400:
-      return "rs64";
-
-    case 0x0800:
-      return "power4";
-
-    case 0x2000:
-      if (_system_configuration.version == 0x0F0000)
-	return "power5";
-      else
-	return "power5+";
-
-    case 0x4000:
-      return "power6";
-
-    default:
-      return "powerpc";
-    }
-}
-#endif /* _AIX */
-
-
-/*
- * Array to map -mcpu=native names to the switches passed to the assembler.
- * This list mirrors the specs in ASM_CPU_SPEC, and any changes made here
- * should be made there as well.
- */
-
 struct asm_name {
   const char *cpu;
   const char *asm_sw;
@@ -347,6 +31,7 @@ 
 
 static const struct asm_name asm_names[] = {
 #if defined (_AIX)
+  { "native",	"%(asm_cpu_native)" },
   { "power3",	"-m620" },
   { "power4",	"-mpwr4" },
   { "power5",	"-mpwr5" },
@@ -372,6 +57,7 @@ 
 %{!maltivec: %{!mpowerpc64: %(asm_default)}}}" },
 
 #else
+  { "native",	"%(asm_cpu_native)" },
   { "cell",	"-mcell" },
   { "power3",	"-mppc64" },
   { "power4",	"-mpower4" },
@@ -424,105 +110,24 @@ 
 #endif
 };
 
-/* This will be called by the spec parser in gcc.c when it sees
-   a %:local_cpu_detect(args) construct.  Currently it will be called
-   with either "arch" or "tune" as argument depending on if -march=native
-   or -mtune=native is to be substituted.
-
-   Additionally it will be called with "asm" to select the appropriate flags
-   for the assembler.
-
-   It returns a string containing new command line parameters to be
-   put at the place of the above two options, depending on what CPU
-   this is executed.
-
-   ARGC and ARGV are set depending on the actual arguments given
-   in the spec.  */
 const char *
-host_detect_local_cpu (int argc, const char **argv)
+translate_cpu_to_asm (int argc, const char **argv)
 {
-  const char *cpu = NULL;
-  const char *cache = "";
-  const char *options = "";
-  bool arch;
-  bool assembler;
-  size_t i;
+  const char *ret = NULL;
 
-  if (argc < 1)
-    return NULL;
-
-  arch = strcmp (argv[0], "cpu") == 0;
-  assembler = (!arch && strcmp (argv[0], "asm") == 0);
-  if (!arch && !assembler && strcmp (argv[0], "tune"))
-    return NULL;
-
-  if (! assembler)
+  while (argc-- > 0)
     {
-#if defined (_AIX)
-      cache = detect_caches_aix ();
-#elif defined (__APPLE__)
-      cache = detect_caches_darwin ();
-#elif defined (__FreeBSD__)
-      cache = detect_caches_freebsd ();
-      /* FreeBSD PPC does not provide any cache information yet.  */
-      cache = "";
-#elif defined (__linux__)
-      cache = detect_caches_linux ();
-      /* PPC Linux does not provide any cache information yet.  */
-      cache = "";
-#else
-      cache = "";
-#endif
-    }
+      unsigned int i;
+      const char *cpu = *argv++;
 
-#if defined (_AIX)
-  cpu = detect_processor_aix ();
-#elif defined (__APPLE__)
-  cpu = detect_processor_darwin ();
-#elif defined (__FreeBSD__)
-  cpu = detect_processor_freebsd ();
-#elif defined (__linux__)
-  cpu = detect_processor_linux ();
-#else
-  cpu = "powerpc";
-#endif
-
-  if (assembler)
-    {
-      for (i = 0; i < sizeof (asm_names) / sizeof (asm_names[0]); i++)
-	{
-	  if (!asm_names[i].cpu || !strcmp (asm_names[i].cpu, cpu))
-	    return asm_names[i].asm_sw;
-	}
-
-      return NULL;
+      for (i = 0; i < sizeof (asm_names) / sizeof (asm_names[0]) - 1; i++)
+	if (!strcmp (asm_names[i].cpu, cpu))
+	  break;
+      if (ret)
+	ret = concat (ret, " ", asm_names[i].asm_sw, (char *) 0);
+      else
+	ret = asm_names[i].asm_sw;
     }
 
-  return concat (cache, "-m", argv[0], "=", cpu, " ", options, NULL);
+  return ret;
 }
-
-#else /* GCC_VERSION */
-
-/* If we aren't compiling with GCC we just provide a minimal
-   default value.  */
-const char *
-host_detect_local_cpu (int argc, const char **argv)
-{
-  const char *cpu;
-  bool arch;
-
-  if (argc < 1)
-    return NULL;
-
-  arch = strcmp (argv[0], "cpu") == 0;
-  if (!arch && strcmp (argv[0], "tune"))
-    return NULL;
-  
-  if (arch)
-    cpu = "powerpc";
-
-  return concat ("-m", argv[0], "=", cpu, NULL);
-}
-
-#endif /* GCC_VERSION */
-
Index: gcc/config/rs6000/driver-nat-rs6000.c
===================================================================
--- gcc/config/rs6000/driver-nat-rs6000.c	(revision 0)
+++ gcc/config/rs6000/driver-nat-rs6000.c	(revision 0)
@@ -0,0 +1,425 @@ 
+/* Subroutines for the gcc driver, native targets only.
+   Copyright (C) 2007-2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include <stdlib.h>
+
+#ifdef _AIX
+# include <sys/systemcfg.h>
+#endif
+
+#ifdef __linux__
+# include <link.h>
+#endif
+
+#if defined (__APPLE__) || (__FreeBSD__)
+# include <sys/types.h>
+# include <sys/sysctl.h>
+#endif
+
+const char *host_detect_local_cpu (int argc, const char **argv);
+
+#if GCC_VERSION >= 0
+
+/* Returns parameters that describe L1_ASSOC associative cache of size
+   L1_SIZEKB with lines of size L1_LINE, and L2_SIZEKB.  */
+
+static char *
+describe_cache (unsigned l1_sizekb, unsigned l1_line,
+		unsigned l1_assoc ATTRIBUTE_UNUSED, unsigned l2_sizekb)
+{
+  char l1size[1000], line[1000], l2size[1000];
+
+  /* At the moment, gcc middle-end does not use the information about the
+     associativity of the cache.  */
+
+  sprintf (l1size, "--param l1-cache-size=%u", l1_sizekb);
+  sprintf (line, "--param l1-cache-line-size=%u", l1_line);
+  sprintf (l2size, "--param l2-cache-size=%u", l2_sizekb);
+
+  return concat (l1size, " ", line, " ", l2size, " ", NULL);
+}
+
+#ifdef __APPLE__
+
+/* Returns the description of caches on Darwin.  */
+
+static char *
+detect_caches_darwin (void)
+{
+  unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
+  size_t len = 4;
+  static int l1_size_name[2] = { CTL_HW, HW_L1DCACHESIZE };
+  static int l1_line_name[2] = { CTL_HW, HW_CACHELINE };
+  static int l2_size_name[2] = { CTL_HW, HW_L2CACHESIZE };
+
+  sysctl (l1_size_name, 2, &l1_sizekb, &len, NULL, 0);
+  sysctl (l1_line_name, 2, &l1_line, &len, NULL, 0);
+  sysctl (l2_size_name, 2, &l2_sizekb, &len, NULL, 0);
+  l1_assoc = 0;
+
+  return describe_cache (l1_sizekb / 1024, l1_line, l1_assoc,
+			 l2_sizekb / 1024);
+}
+
+static const char *
+detect_processor_darwin (void)
+{
+  unsigned int proc;
+  size_t len = 4;
+
+  sysctlbyname ("hw.cpusubtype", &proc, &len, NULL, 0);
+
+  if (len > 0)
+    switch (proc)
+      {
+      case 1:
+	return "601";
+      case 2:
+	return "602";
+      case 3:
+	return "603";
+      case 4:
+      case 5:
+	return "603e";
+      case 6:
+	return "604";
+      case 7:
+	return "604e";
+      case 8:
+	return "620";
+      case 9:
+	return "750";
+      case 10:
+	return "7400";
+      case 11:
+	return "7450";
+      case 100:
+	return "970";
+      default:
+	return "powerpc";
+      }
+
+  return "powerpc";
+}
+
+#endif /* __APPLE__ */
+
+#ifdef __FreeBSD__
+
+/* Returns the description of caches on FreeBSD PPC.  */
+
+static char *
+detect_caches_freebsd (void)
+{
+  unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
+  size_t len = 4;
+
+  /* Currently, as of FreeBSD-7.0, there is only the cacheline_size
+     available via sysctl.  */
+  sysctlbyname ("machdep.cacheline_size", &l1_line, &len, NULL, 0);
+
+  l1_sizekb = 32;
+  l1_assoc = 0;
+  l2_sizekb = 512;
+
+  return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb);
+}
+
+/* Currently returns default powerpc.  */
+static const char *
+detect_processor_freebsd (void)
+{
+  return "powerpc";
+}
+
+#endif /* __FreeBSD__  */
+
+#ifdef __linux__
+
+/* Returns AT_PLATFORM if present, otherwise generic PowerPC.  */
+
+static const char *
+elf_platform (void)
+{
+  int fd;
+
+  fd = open ("/proc/self/auxv", O_RDONLY);
+
+  if (fd != -1)
+    {
+      char buf[1024];
+      ElfW(auxv_t) *av;
+      ssize_t n;
+
+      n = read (fd, buf, sizeof (buf));
+      close (fd);
+
+      if (n > 0)
+	{
+	  for (av = (ElfW(auxv_t) *) buf; av->a_type != AT_NULL; ++av)
+	    switch (av->a_type)
+	      {
+	      case AT_PLATFORM:
+		return (const char *) av->a_un.a_val;
+
+	      default:
+		break;
+	      }
+	}
+    }
+  return NULL;
+}
+
+/* Returns AT_DCACHEBSIZE if present, otherwise generic 32.  */
+
+static int
+elf_dcachebsize (void)
+{
+  int fd;
+
+  fd = open ("/proc/self/auxv", O_RDONLY);
+
+  if (fd != -1)
+    {
+      char buf[1024];
+      ElfW(auxv_t) *av;
+      ssize_t n;
+
+      n = read (fd, buf, sizeof (buf));
+      close (fd);
+
+      if (n > 0)
+	{
+	  for (av = (ElfW(auxv_t) *) buf; av->a_type != AT_NULL; ++av)
+	    switch (av->a_type)
+	      {
+	      case AT_DCACHEBSIZE:
+		return av->a_un.a_val;
+
+	      default:
+		break;
+	      }
+	}
+    }
+  return 32;
+}
+
+/* Returns the description of caches on Linux.  */
+
+static char *
+detect_caches_linux (void)
+{
+  unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
+  const char *platform;
+
+  platform = elf_platform ();
+
+  if (platform != NULL)
+    {
+      l1_line = 128;
+
+      if (platform[5] == '6')
+	/* POWER6 and POWER6x */
+	l1_sizekb = 64;
+      else
+	l1_sizekb = 32;
+    }
+  else
+    {
+      l1_line = elf_dcachebsize ();
+      l1_sizekb = 32;
+    }
+
+  l1_assoc = 0;
+  l2_sizekb = 512;
+
+  return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb);
+}
+
+static const char *
+detect_processor_linux (void)
+{
+  const char *platform;
+
+  platform = elf_platform ();
+
+  if (platform != NULL)
+    return platform;
+  else
+    return "powerpc";
+}
+
+#endif /* __linux__ */
+
+#ifdef _AIX
+/* Returns the description of caches on AIX.  */
+
+static char *
+detect_caches_aix (void)
+{
+  unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
+
+  l1_sizekb = _system_configuration.dcache_size / 1024;
+  l1_line = _system_configuration.dcache_line;
+  l1_assoc = _system_configuration.dcache_asc;
+  l2_sizekb = _system_configuration.L2_cache_size / 1024;
+
+  return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb);
+}
+
+
+/* Returns the processor implementation on AIX.  */
+
+static const char *
+detect_processor_aix (void)
+{
+  switch (_system_configuration.implementation)
+    {
+    case 0x0008:
+      return "601";
+
+    case 0x0020:
+      return "603";
+
+    case 0x0010:
+      return "604";
+
+    case 0x0040:
+      return "620";
+
+    case 0x0080:
+      return "630";
+
+    case 0x0100:
+    case 0x0200:
+    case 0x0400:
+      return "rs64";
+
+    case 0x0800:
+      return "power4";
+
+    case 0x2000:
+      if (_system_configuration.version == 0x0F0000)
+	return "power5";
+      else
+	return "power5+";
+
+    case 0x4000:
+      return "power6";
+
+    default:
+      return "powerpc";
+    }
+}
+#endif /* _AIX */
+
+
+/* This will be called by the spec parser in gcc.c when it sees
+   a %:local_cpu_detect(args) construct.  Currently it will be called
+   with either "arch" or "tune" as argument depending on if -march=native
+   or -mtune=native is to be substituted.
+
+   Additionally it will be called with "asm" to select the appropriate flags
+   for the assembler.
+
+   It returns a string containing new command line parameters to be
+   put at the place of the above two options, depending on what CPU
+   this is executed.
+
+   ARGC and ARGV are set depending on the actual arguments given
+   in the spec.  */
+const char *
+host_detect_local_cpu (int argc, const char **argv)
+{
+  const char *cpu;
+  const char *cache ;
+  bool arch;
+  bool assembler;
+
+  if (argc < 1)
+    return NULL;
+
+  arch = strcmp (argv[0], "cpu") == 0;
+  assembler = (!arch && strcmp (argv[0], "asm") == 0);
+  if (!arch && !assembler && strcmp (argv[0], "tune"))
+    return NULL;
+
+#if defined (_AIX)
+  cpu = detect_processor_aix ();
+#elif defined (__APPLE__)
+  cpu = detect_processor_darwin ();
+#elif defined (__FreeBSD__)
+  cpu = detect_processor_freebsd ();
+#elif defined (__linux__)
+  cpu = detect_processor_linux ();
+#else
+  cpu = "powerpc";
+#endif
+
+  if (assembler)
+    return translate_cpu_to_asm (1, &cpu);
+
+#if defined (_AIX)
+  cache = detect_caches_aix ();
+#elif defined (__APPLE__)
+  cache = detect_caches_darwin ();
+#elif defined (__FreeBSD__)
+  cache = detect_caches_freebsd ();
+  /* FreeBSD PPC does not provide any cache information yet.  */
+  cache = "";
+#elif defined (__linux__)
+  cache = detect_caches_linux ();
+  /* PPC Linux does not provide any cache information yet.  */
+  cache = "";
+#else
+  cache = "";
+#endif
+
+  return concat (cache, "-m", argv[0], "=", cpu, NULL);
+}
+
+#else /* GCC_VERSION */
+
+/* If we aren't compiling with GCC we just provide a minimal
+   default value.  */
+const char *
+host_detect_local_cpu (int argc, const char **argv)
+{
+  const char *cpu;
+  bool arch;
+
+  if (argc < 1)
+    return NULL;
+
+  arch = strcmp (argv[0], "cpu") == 0;
+  if (!arch && strcmp (argv[0], "tune"))
+    return NULL;
+  
+  if (arch)
+    cpu = "powerpc";
+
+  return concat ("-m", argv[0], "=", cpu, NULL);
+}
+
+#endif /* GCC_VERSION */
+
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 206599)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -102,66 +102,12 @@ 
 #endif
 
 /* Common ASM definitions used by ASM_SPEC among the various targets for
-   handling -mcpu=xxx switches.  There is a parallel list in driver-rs6000.c to
-   provide the default assembler options if the user uses -mcpu=native, so if
-   you make changes here, make them also there.  */
+   handling -mcpu=xxx switches.  See the list in driver-rs6000.c.  */
 #define ASM_CPU_SPEC \
 "%{!mcpu*: \
   %{mpowerpc64*: -mppc64} \
   %{!mpowerpc64*: %(asm_default)}} \
-%{mcpu=native: %(asm_cpu_native)} \
-%{mcpu=cell: -mcell} \
-%{mcpu=power3: -mppc64} \
-%{mcpu=power4: -mpower4} \
-%{mcpu=power5: %(asm_cpu_power5)} \
-%{mcpu=power5+: %(asm_cpu_power5)} \
-%{mcpu=power6: %(asm_cpu_power6) -maltivec} \
-%{mcpu=power6x: %(asm_cpu_power6) -maltivec} \
-%{mcpu=power7: %(asm_cpu_power7)} \
-%{mcpu=power8: %(asm_cpu_power8)} \
-%{mcpu=a2: -ma2} \
-%{mcpu=powerpc: -mppc} \
-%{mcpu=rs64a: -mppc64} \
-%{mcpu=401: -mppc} \
-%{mcpu=403: -m403} \
-%{mcpu=405: -m405} \
-%{mcpu=405fp: -m405} \
-%{mcpu=440: -m440} \
-%{mcpu=440fp: -m440} \
-%{mcpu=464: -m440} \
-%{mcpu=464fp: -m440} \
-%{mcpu=476: %(asm_cpu_476)} \
-%{mcpu=476fp: %(asm_cpu_476)} \
-%{mcpu=505: -mppc} \
-%{mcpu=601: -m601} \
-%{mcpu=602: -mppc} \
-%{mcpu=603: -mppc} \
-%{mcpu=603e: -mppc} \
-%{mcpu=ec603e: -mppc} \
-%{mcpu=604: -mppc} \
-%{mcpu=604e: -mppc} \
-%{mcpu=620: -mppc64} \
-%{mcpu=630: -mppc64} \
-%{mcpu=740: -mppc} \
-%{mcpu=750: -mppc} \
-%{mcpu=G3: -mppc} \
-%{mcpu=7400: -mppc -maltivec} \
-%{mcpu=7450: -mppc -maltivec} \
-%{mcpu=G4: -mppc -maltivec} \
-%{mcpu=801: -mppc} \
-%{mcpu=821: -mppc} \
-%{mcpu=823: -mppc} \
-%{mcpu=860: -mppc} \
-%{mcpu=970: -mpower4 -maltivec} \
-%{mcpu=G5: -mpower4 -maltivec} \
-%{mcpu=8540: -me500} \
-%{mcpu=8548: -me500} \
-%{mcpu=e300c2: -me300} \
-%{mcpu=e300c3: -me300} \
-%{mcpu=e500mc: -me500mc} \
-%{mcpu=e500mc64: -me500mc64} \
-%{mcpu=e5500: -me5500} \
-%{mcpu=e6500: -me6500} \
+%{mcpu*:%:translate_cpu_to_asm(%{mcpu=*:%*})} \
 %{maltivec: -maltivec} \
 %{mvsx: -mvsx %{!maltivec: -maltivec} %{!mcpu*: %(asm_cpu_power7)}} \
 %{mpower8-vector|mcrypto|mdirect-move|mhtm: %{!mcpu*: %(asm_cpu_power8)}} \
@@ -196,6 +142,8 @@ 
   { "asm_cpu_476",		ASM_CPU_476_SPEC },			\
   SUBTARGET_EXTRA_SPECS
 
+extern const char *translate_cpu_to_asm (int argc, const char **argv);
+
 /* -mcpu=native handling only makes sense with compiler running on
    an PowerPC chip.  If changing this condition, also change
    the condition in driver-rs6000.c.  */
@@ -203,12 +151,15 @@ 
 /* In driver-rs6000.c.  */
 extern const char *host_detect_local_cpu (int argc, const char **argv);
 #define EXTRA_SPEC_FUNCTIONS \
-  { "local_cpu_detect", host_detect_local_cpu },
+  { "local_cpu_detect", host_detect_local_cpu },	\
+  { "translate_cpu_to_asm", translate_cpu_to_asm },
 #define HAVE_LOCAL_CPU_DETECT
 #define ASM_CPU_NATIVE_SPEC "%:local_cpu_detect(asm)"
 
 #else
 #define ASM_CPU_NATIVE_SPEC "%(asm_default)"
+#define EXTRA_SPEC_FUNCTIONS \
+  { "translate_cpu_to_asm", translate_cpu_to_asm },
 #endif
 
 #ifndef CC1_CPU_SPEC
Index: gcc/config/rs6000/x-rs6000
===================================================================
--- gcc/config/rs6000/x-rs6000	(revision 206599)
+++ gcc/config/rs6000/x-rs6000	(working copy)
@@ -1,3 +1,3 @@ 
-driver-rs6000.o : $(srcdir)/config/rs6000/driver-rs6000.c \
+driver-nat-rs6000.o : $(srcdir)/config/rs6000/driver-nat-rs6000.c \
   $(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
Index: gcc/config/rs6000/t-rs6000
===================================================================
--- gcc/config/rs6000/t-rs6000	(revision 206599)
+++ gcc/config/rs6000/t-rs6000	(working copy)
@@ -24,6 +24,10 @@ 
 	$(COMPILE) $<
 	$(POSTCOMPILE)
 
+driver-rs6000.o : $(srcdir)/config/rs6000/driver-rs6000.c \
+  $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+
 $(srcdir)/config/rs6000/rs6000-tables.opt: $(srcdir)/config/rs6000/genopt.sh \
   $(srcdir)/config/rs6000/rs6000-cpus.def
 	$(SHELL) $(srcdir)/config/rs6000/genopt.sh $(srcdir)/config/rs6000 > \
Index: gcc/config/rs6000/aix53.h
===================================================================
--- gcc/config/rs6000/aix53.h	(revision 206599)
+++ gcc/config/rs6000/aix53.h	(working copy)
@@ -54,25 +54,7 @@ 
   %{mpowerpc64: -mppc64} \
   %{maltivec: -m970} \
   %{!maltivec: %{!mpowerpc64: %(asm_default)}}}} \
-%{mcpu=native: %(asm_cpu_native)} \
-%{mcpu=power3: -m620} \
-%{mcpu=power4: -mpwr4} \
-%{mcpu=power5: -mpwr5} \
-%{mcpu=power5+: -mpwr5x} \
-%{mcpu=power6: -mpwr6} \
-%{mcpu=power6x: -mpwr6} \
-%{mcpu=power7: -mpwr7} \
-%{mcpu=power8: -mpwr8} \
-%{mcpu=powerpc: -mppc} \
-%{mcpu=rs64a: -mppc} \
-%{mcpu=603: -m603} \
-%{mcpu=603e: -m603} \
-%{mcpu=604: -m604} \
-%{mcpu=604e: -m604} \
-%{mcpu=620: -m620} \
-%{mcpu=630: -m620} \
-%{mcpu=970: -m970} \
-%{mcpu=G5: -m970}"
+%{mcpu*:%:translate_cpu_to_asm(%{mcpu=*:%*})}"
 
 #undef	ASM_DEFAULT_SPEC
 #define ASM_DEFAULT_SPEC "-mppc"
Index: gcc/config/rs6000/aix61.h
===================================================================
--- gcc/config/rs6000/aix61.h	(revision 206599)
+++ gcc/config/rs6000/aix61.h	(working copy)
@@ -71,25 +71,7 @@ 
   %{mpowerpc64: -mppc64} \
   %{maltivec: -m970} \
   %{!maltivec: %{!mpowerpc64: %(asm_default)}}}} \
-%{mcpu=native: %(asm_cpu_native)} \
-%{mcpu=power3: -m620} \
-%{mcpu=power4: -mpwr4} \
-%{mcpu=power5: -mpwr5} \
-%{mcpu=power5+: -mpwr5x} \
-%{mcpu=power6: -mpwr6} \
-%{mcpu=power6x: -mpwr6} \
-%{mcpu=power7: -mpwr7} \
-%{mcpu=power8: -mpwr8} \
-%{mcpu=powerpc: -mppc} \
-%{mcpu=rs64a: -mppc} \
-%{mcpu=603: -m603} \
-%{mcpu=603e: -m603} \
-%{mcpu=604: -m604} \
-%{mcpu=604e: -m604} \
-%{mcpu=620: -m620} \
-%{mcpu=630: -m620} \
-%{mcpu=970: -m970} \
-%{mcpu=G5: -m970} \
+%{mcpu*:%:translate_cpu_to_asm(%{mcpu=*:%*})} \
 %{mvsx: %{!mcpu*: -mpwr6}} \
 -many"
 
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 206599)
+++ gcc/config.gcc	(working copy)
@@ -445,10 +445,12 @@ 
 		cpu_is_64bit=yes
 		;;
 	esac
+	extra_gcc_objs="driver-rs6000.o"
 	extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
 	;;
 rs6000*-*-*)
 	need_64bit_hwint=yes
+	extra_gcc_objs="driver-rs6000.o"
 	extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
 	;;
 score*-*-*)
@@ -618,7 +620,7 @@ 
   fortran_target_objs="darwin-f.o"
   target_has_targetcm=yes
   extra_objs="darwin.o"
-  extra_gcc_objs="darwin-driver.o"
+  extra_gcc_objs="$extra_gcc_objs darwin-driver.o"
   default_use_cxa_atexit=yes
   use_gcc_stdint=wrap
   case ${enable_threads} in
Index: gcc/config.host
===================================================================
--- gcc/config.host	(revision 206599)
+++ gcc/config.host	(working copy)
@@ -138,7 +138,7 @@ 
     case ${target} in
       rs6000-*-* \
       | powerpc*-*-* )
-        host_extra_gcc_objs="driver-rs6000.o"
+        host_extra_gcc_objs="driver-nat-rs6000.o"
         host_xmake_file="${host_xmake_file} rs6000/x-rs6000"
         ;;
     esac