diff mbox

RFC, start to add attribute target support to powerpc

Message ID 20101007171830.GA4572@hungry-tiger.westford.ibm.com
State New
Headers show

Commit Message

Michael Meissner Oct. 7, 2010, 5:18 p.m. UTC
I am starting the work to add the target attribute/pragma to the PowerPC.  One
of the steps along the way is to group together all of the random globals that
are set in the switch handling.  I have done it in this patch, which bootstraps
fine on my Sles11 SP1 system, and make check has no regressions.

However, this patch is somewhat invasive, as I needed to change every reference
of the global, such as rs6000_cpu to rs6000_opts.cpu, and so there are a lot of
changes from the various sub-port files to change all of these references.

I would like an opinion from David, as what he would prefer in terms of final
patches:

    1)	We could bite the bullet and use this patch which changes all of the
	references, and then fixup any problems afterwards.  Note, this patch
	may make it harder to backport changes to older compilers.

    2)	Group the variables into a common structure, but use #define's to map
	the new name into the old.  Possibly over time, change the varioius
	files, but this isn't required.  A little part of me doesn't like using
	the preprocessor this way, but we do use it quite frequently in the
	compiler.

    3)	Keep the current variables as scalars, and just copy the individual
	variables one at a time.

Also if embedded, AIX, and darwin powerpc users could try the current patches
out to see whether they build on their systems, it would be appreciated.

Comments

Joseph Myers Oct. 7, 2010, 7 p.m. UTC | #1
On Thu, 7 Oct 2010, Michael Meissner wrote:

> I am starting the work to add the target attribute/pragma to the PowerPC.  One
> of the steps along the way is to group together all of the random globals that
> are set in the switch handling.  I have done it in this patch, which bootstraps
> fine on my Sles11 SP1 system, and make check has no regressions.

Globals used in switch handling now should go in the global gcc_options 
structure.  If for whatever reason you need to handle the rs6000 subset 
separately as a group, I'd suggest enhancing the .opt machinery so you can 
say Var(rs6000_opts.whatever) and have it automatically create a 
substructure.  (In that it would be possible to have

Variable
struct rs6000_options rs6000_opts

in a .opt file, your patch shouldn't actually make it any harder to 
continue to move away from separate globals, and to having hooks such as 
the option override one taking pointers to gcc_options structures rather 
than manipulating globals directly.  But it would seem better to work more 
directly with the common machinery.)

I do however hope that once there is a clean separation between operations 
on gcc_options structures in the course of option processing, finalization 
of such structures after all options have been processed, and subsequent 
setup based on such structures, it will be possible for target attributes 
to work more cleanly on the basis I described in 
<http://gcc.gnu.org/ml/gcc-patches/2010-10/msg00606.html> and 
<http://gcc.gnu.org/ml/gcc-patches/2010-06/msg02689.html> of acting as if 
options were placed at the end of the command line without so much 
target-specific logic being needed.
Michael Meissner Oct. 7, 2010, 8:25 p.m. UTC | #2
On Thu, Oct 07, 2010 at 07:00:14PM +0000, Joseph S. Myers wrote:
> On Thu, 7 Oct 2010, Michael Meissner wrote:
> 
> > I am starting the work to add the target attribute/pragma to the PowerPC.  One
> > of the steps along the way is to group together all of the random globals that
> > are set in the switch handling.  I have done it in this patch, which bootstraps
> > fine on my Sles11 SP1 system, and make check has no regressions.
> 
> Globals used in switch handling now should go in the global gcc_options 
> structure.  If for whatever reason you need to handle the rs6000 subset 
> separately as a group, I'd suggest enhancing the .opt machinery so you can 
> say Var(rs6000_opts.whatever) and have it automatically create a 
> substructure.  (In that it would be possible to have

I'm not sure I follow this.

What I'm trying to do is group the current globals/statics that describe the
current cpu target options into a single structure (there are about 20 of
these), so that they can easily be switched out in TARGET_OPITON_SAVED, and
restored in TARGET_OPTION_RESTORE.  This is to support the target attribute:

I.e. if you compile the file with -mcpu=power5, and then

     extern void p5_func (void);
     extern void p6_func (void) __attribute__((__target__("cpu=power6")));
     extern void p7_func (void) __attribute__((__target__("cpu=power7")));

     void p5_func (void) { ... }
     void p6_func (void) { ... }
     void p7_func (void) { ... }

And then when p5_func is compiled, it gets compiled with the power5 options
specified on the command line, when p6_func is compiled, it gets compiled
targetting the power6 cpu, and when p7_func is compiled, it gets compiled
targetting the power7 cpu.

> Variable
> struct rs6000_options rs6000_opts
> 
> in a .opt file, your patch shouldn't actually make it any harder to 
> continue to move away from separate globals, and to having hooks such as 
> the option override one taking pointers to gcc_options structures rather 
> than manipulating globals directly.  But it would seem better to work more 
> directly with the common machinery.)

Unfortunately declaring structs in the .opt file in the TargetSave section
doesn't work because the generator files don't include the md *.h files.
Declarating it as a pointer, does work.  Or generating each field, but I really
wanted to get away from having the same information in several places.

> I do however hope that once there is a clean separation between operations 
> on gcc_options structures in the course of option processing, finalization 
> of such structures after all options have been processed, and subsequent 
> setup based on such structures, it will be possible for target attributes 
> to work more cleanly on the basis I described in 
> <http://gcc.gnu.org/ml/gcc-patches/2010-10/msg00606.html> and 
> <http://gcc.gnu.org/ml/gcc-patches/2010-06/msg02689.html> of acting as if 
> options were placed at the end of the command line without so much 
> target-specific logic being needed.

Is all of your stuff now checked in, or is the tree still expected to be
changing in terms of options?
Joseph Myers Oct. 7, 2010, 9:25 p.m. UTC | #3
On Thu, 7 Oct 2010, Michael Meissner wrote:

> On Thu, Oct 07, 2010 at 07:00:14PM +0000, Joseph S. Myers wrote:
> > On Thu, 7 Oct 2010, Michael Meissner wrote:
> > 
> > > I am starting the work to add the target attribute/pragma to the PowerPC.  One
> > > of the steps along the way is to group together all of the random globals that
> > > are set in the switch handling.  I have done it in this patch, which bootstraps
> > > fine on my Sles11 SP1 system, and make check has no regressions.
> > 
> > Globals used in switch handling now should go in the global gcc_options 
> > structure.  If for whatever reason you need to handle the rs6000 subset 
> > separately as a group, I'd suggest enhancing the .opt machinery so you can 
> > say Var(rs6000_opts.whatever) and have it automatically create a 
> > substructure.  (In that it would be possible to have
> 
> I'm not sure I follow this.
> 
> What I'm trying to do is group the current globals/statics that describe the
> current cpu target options into a single structure (there are about 20 of
> these), so that they can easily be switched out in TARGET_OPITON_SAVED, and
> restored in TARGET_OPTION_RESTORE.  This is to support the target attribute:

And what I am saying is:

* You should not have a global variable of that structure type.  You 
should have a field in the gcc_options structure with that type instead.  
Putting state in gcc_options is preferred to having it in separate 
globals; only that way will it be possible to use that state as part of 
multilib selection, because only the state in gcc_options will exist for 
each multilib when the comparison of gcc_options structures, instead of 
textual matching of options, becomes how multilib selection is done as 
described at <http://gcc.gnu.org/ml/gcc/2010-01/msg00063.html>.

* It's preferable for options to be handled purely through the 
datastructures in the .opt file rather than needing custom code if 
possible.  There are quite a few options that rs6000_handle_option covers 
that look like they could (and so should) be handled through the .opt 
file, and more that could be so handled when there is generic support for 
enumerated string arguments.  So you should avoid making it any harder to 
handle these options through the .opt file.

Taken together, these mean that instead of a manually generated structure 
and variable you should aim for a structure and associated gcc_options 
field generated automatically from the .opt file.

> Unfortunately declaring structs in the .opt file in the TargetSave section
> doesn't work because the generator files don't include the md *.h files.

Note that options.h has conditions that adjust the declarations depending 
on whether it is included in a generator file.

> Declarating it as a pointer, does work.  Or generating each field, but I really
> wanted to get away from having the same information in several places.

I'd like the information about options and the datastructures they set in 
one place as far as possible: the .opt file, not special code in .c and .h 
files.

> > I do however hope that once there is a clean separation between operations 
> > on gcc_options structures in the course of option processing, finalization 
> > of such structures after all options have been processed, and subsequent 
> > setup based on such structures, it will be possible for target attributes 
> > to work more cleanly on the basis I described in 
> > <http://gcc.gnu.org/ml/gcc-patches/2010-10/msg00606.html> and 
> > <http://gcc.gnu.org/ml/gcc-patches/2010-06/msg02689.html> of acting as if 
> > options were placed at the end of the command line without so much 
> > target-specific logic being needed.
> 
> Is all of your stuff now checked in, or is the tree still expected to be
> changing in terms of options?

It is expected to continue changing through the rest of stage 1.  By my 
list there are so far 57 logical patches since May in this series, the 
last one pending review (some logical patches correspond to more than one 
commit because of fixes to problems with the original commit), with plenty 
more to come.
Michael Meissner Oct. 7, 2010, 9:35 p.m. UTC | #4
On Thu, Oct 07, 2010 at 09:25:33PM +0000, Joseph S. Myers wrote:
> On Thu, 7 Oct 2010, Michael Meissner wrote:
> 
> > On Thu, Oct 07, 2010 at 07:00:14PM +0000, Joseph S. Myers wrote:
> > > On Thu, 7 Oct 2010, Michael Meissner wrote:
> > > 
> > > > I am starting the work to add the target attribute/pragma to the PowerPC.  One
> > > > of the steps along the way is to group together all of the random globals that
> > > > are set in the switch handling.  I have done it in this patch, which bootstraps
> > > > fine on my Sles11 SP1 system, and make check has no regressions.
> > > 
> > > Globals used in switch handling now should go in the global gcc_options 
> > > structure.  If for whatever reason you need to handle the rs6000 subset 
> > > separately as a group, I'd suggest enhancing the .opt machinery so you can 
> > > say Var(rs6000_opts.whatever) and have it automatically create a 
> > > substructure.  (In that it would be possible to have
> > 
> > I'm not sure I follow this.
> > 
> > What I'm trying to do is group the current globals/statics that describe the
> > current cpu target options into a single structure (there are about 20 of
> > these), so that they can easily be switched out in TARGET_OPITON_SAVED, and
> > restored in TARGET_OPTION_RESTORE.  This is to support the target attribute:
> 
> And what I am saying is:
> 
> * You should not have a global variable of that structure type.  You 
> should have a field in the gcc_options structure with that type instead.  
> Putting state in gcc_options is preferred to having it in separate 
> globals; only that way will it be possible to use that state as part of 
> multilib selection, because only the state in gcc_options will exist for 
> each multilib when the comparison of gcc_options structures, instead of 
> textual matching of options, becomes how multilib selection is done as 
> described at <http://gcc.gnu.org/ml/gcc/2010-01/msg00063.html>.

However, the target specific stuff has nothing to do with multilib, since on
power, we don't have multilibs for each cpu type on the linux side of things.
The distros tend to only want 32-bit and 64-bit multilibs.  On the eabi side of
things, I recall there were more multilibs for the different options.

> * It's preferable for options to be handled purely through the 
> datastructures in the .opt file rather than needing custom code if 
> possible.  There are quite a few options that rs6000_handle_option covers 
> that look like they could (and so should) be handled through the .opt 
> file, and more that could be so handled when there is generic support for 
> enumerated string arguments.  So you should avoid making it any harder to 
> handle these options through the .opt file.
> 
> Taken together, these mean that instead of a manually generated structure 
> and variable you should aim for a structure and associated gcc_options 
> field generated automatically from the .opt file.

Sounds reasonable.  I need to dig deeper, as it has changed greatly since I
last looked at options in the 4.3 time frame.

Part of the problem with the rs6000 is many of the options were split off when
we've run out of bits multiple times, as well as variables set in the various
different config files.
Joseph Myers Oct. 7, 2010, 11:26 p.m. UTC | #5
On Thu, 7 Oct 2010, Michael Meissner wrote:

> > * You should not have a global variable of that structure type.  You 
> > should have a field in the gcc_options structure with that type instead.  
> > Putting state in gcc_options is preferred to having it in separate 
> > globals; only that way will it be possible to use that state as part of 
> > multilib selection, because only the state in gcc_options will exist for 
> > each multilib when the comparison of gcc_options structures, instead of 
> > textual matching of options, becomes how multilib selection is done as 
> > described at <http://gcc.gnu.org/ml/gcc/2010-01/msg00063.html>.
> 
> However, the target specific stuff has nothing to do with multilib, since on
> power, we don't have multilibs for each cpu type on the linux side of things.
> The distros tend to only want 32-bit and 64-bit multilibs.  On the eabi side of
> things, I recall there were more multilibs for the different options.

Multilibs are used just as much for embedded GNU/Linux on Power as for 
other architectures, so this is just as relevant there - for example, 
given a toolchain with both SPE and non-SPE multilibs, to select the right 
multilib for the features enabled whatever combination of options is used 
to enable those features.  (Thus, having the flag for SPE in the 
gcc_options structure is desirable; it could well be used for selecting a 
multilib.)

It's generally expected that complicated multilib configurations will not 
be those in the FSF sources, although some complicated configurations are 
present there.  Some targets (in particular SH) do have configure options 
to determine a multilib configuration at configure time, and it would be 
natural to extend those to other targets; doing so is not in my plans, 
which deal with how the compiler selects from the installed multilibs 
rather than how the installed set is configured in the first place.  The 
multilib machinery is very much providing infrastructure to allow users 
and distributors to build compilers for their particular use cases, with 
the particular configurations in the FSF sources often just being examples 
of what someone might want.

It's probably true that different sets of users will use multilibs and 
target-specific functions - if you are building libraries for a particular 
CPU, you are probably also building applications for one CPU rather than 
including multiple variants.  However, I have tried to make sure that the 
infrastructure I have designed for multilibs is also usable for 
target-specific attributes and will make it possible for people working on 
target and optimize attributes to make those features work more reliably 
(they are notoriously unreliable at present, sufficiently so that some 
people keep arguing for their removal).

Both features run into the same underlying problem at present: an 
insufficiently structured notion of option handling and the state 
generated by that handling.  I am seeking to address this so it becomes 
very clear just what needs to be done to make the attributes act just as 
if options were added at the end of the command line when compiling a 
particular function (a notion that is simple, well-defined and 
comprehensible to users).  Back ends shouldn't need to deal with saving 
and restoring option variables at all; that should be done with swapping 
whole gcc_options structures or parts thereof in machine-independent code.  
What back ends should need to do is provide option handlers and 
initialization code (like they do at present, but better factored), ensure 
the initialization code can be rerun as needed when options are changed, 
and deal with the complications such as changes in supported machine modes 
and built-in functions during compilation.

It may not be possible to achieve all that just yet, but it would be good 
to keep the model of swapping gcc_options structures in mind, and when 
rearranging state variables that are more or less directly set by options 
aim for them to move into the gcc_options structure where they belong.

(When you get into the target reinitialization, dealing with data not 
contained in the gcc_options structure, the work done for the mips16 
attribute and Richard Sandiford's recent changes to make that faster and 
more robust are also relevant - the basic idea seems closely related to 
target attributes.)
diff mbox

Patch

Index: gcc/config/rs6000/aix53.h
===================================================================
--- gcc/config/rs6000/aix53.h	(revision 165044)
+++ gcc/config/rs6000/aix53.h	(working copy)
@@ -38,7 +38,7 @@  do {									\
     }									\
   if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128)			\
     {									\
-      rs6000_long_double_type_size = 64;				\
+      rs6000_opts.long_double_type_size = 64;				\
       if (rs6000_explicit_options.long_double)				\
 	warning (0, "soft-float and long-double-128 are incompatible");	\
     }									\
Index: gcc/config/rs6000/linuxspe.h
===================================================================
--- gcc/config/rs6000/linuxspe.h	(revision 165044)
+++ gcc/config/rs6000/linuxspe.h	(working copy)
@@ -30,13 +30,13 @@ 
 #undef  SUBSUBTARGET_OVERRIDE_OPTIONS
 #define SUBSUBTARGET_OVERRIDE_OPTIONS \
   if (rs6000_select[1].string == NULL) \
-    rs6000_cpu = PROCESSOR_PPC8540; \
+    rs6000_opts.cpu = PROCESSOR_PPC8540; \
   if (!rs6000_explicit_options.spe_abi) \
-    rs6000_spe_abi = 1; \
+    rs6000_opts.spe_abi = 1; \
   if (!rs6000_explicit_options.float_gprs) \
-    rs6000_float_gprs = 1; \
+    rs6000_opts.float_gprs = 1; \
   if (!rs6000_explicit_options.spe) \
-    rs6000_spe = 1; \
+    rs6000_opts.spe = 1; \
   if (target_flags & MASK_64BIT) \
     error ("-m64 not supported in this configuration")
 
Index: gcc/config/rs6000/eabialtivec.h
===================================================================
--- gcc/config/rs6000/eabialtivec.h	(revision 165044)
+++ gcc/config/rs6000/eabialtivec.h	(working copy)
@@ -27,4 +27,4 @@ 
 #define TARGET_VERSION fprintf (stderr, " (PowerPC Embedded with AltiVec)");
 
 #undef  SUBSUBTARGET_OVERRIDE_OPTIONS
-#define SUBSUBTARGET_OVERRIDE_OPTIONS	rs6000_altivec_abi = 1
+#define SUBSUBTARGET_OVERRIDE_OPTIONS	rs6000_opts.altivec_abi = 1
Index: gcc/config/rs6000/aix43.h
===================================================================
--- gcc/config/rs6000/aix43.h	(revision 165044)
+++ gcc/config/rs6000/aix43.h	(working copy)
@@ -38,7 +38,7 @@  do {									\
     }									\
   if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128)			\
     {									\
-      rs6000_long_double_type_size = 64;				\
+      rs6000_opts.long_double_type_size = 64;				\
       if (rs6000_explicit_options.long_double)				\
 	warning (0, "soft-float and long-double-128 are incompatible");	\
     }									\
Index: gcc/config/rs6000/rs6000-c.c
===================================================================
--- gcc/config/rs6000/rs6000-c.c	(revision 165044)
+++ gcc/config/rs6000/rs6000-c.c	(working copy)
@@ -312,7 +312,7 @@  rs6000_cpu_cpp_builtins (cpp_reader *pfi
 	  cpp_get_callbacks (pfile)->macro_to_expand = rs6000_macro_to_expand;
 	}
     }
-  if (rs6000_cpu == PROCESSOR_CELL)
+  if (rs6000_opts.cpu == PROCESSOR_CELL)
     builtin_define ("__PPU__");
   if (TARGET_SPE)
     builtin_define ("__SPE__");
@@ -324,7 +324,7 @@  rs6000_cpu_cpp_builtins (cpp_reader *pfi
       ||(TARGET_HARD_FLOAT && TARGET_FPRS && !TARGET_DOUBLE_FLOAT))
     builtin_define ("_SOFT_DOUBLE");
   /* Used by lwarx/stwcx. errata work-around.  */
-  if (rs6000_cpu == PROCESSOR_PPC405)
+  if (rs6000_opts.cpu == PROCESSOR_PPC405)
     builtin_define ("__PPC405__");
   /* Used by libstdc++.  */
   if (TARGET_NO_LWSYNC)
@@ -386,7 +386,7 @@  rs6000_cpu_cpp_builtins (cpp_reader *pfi
       builtin_define ("__LONGDOUBLE128");
     }
 
-  switch (rs6000_current_abi)
+  switch (rs6000_opts.abi)
     {
     case ABI_V4:
       builtin_define ("_CALL_SYSV");
Index: gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc/config/rs6000/rs6000.opt	(revision 165044)
+++ gcc/config/rs6000/rs6000.opt	(working copy)
@@ -20,8 +20,14 @@ 
 ; along with GCC; see the file COPYING3.  If not see
 ; <http://www.gnu.org/licenses/>.
 
+;; Definitions to add to the cl_target_option structure
+;; All of the useful target information
+TargetSave
+struct rs6000_options *options
+
+;; Options
 mpower
-Target Report RejectNegative Mask(POWER)
+Target Report RejectNegative Mask(POWER) Save
 Use POWER instruction set
 
 mno-power
@@ -29,11 +35,11 @@  Target Report RejectNegative
 Do not use POWER instruction set
 
 mpower2
-Target Report Mask(POWER2)
+Target Report Mask(POWER2) Save
 Use POWER2 instruction set
 
 mpowerpc
-Target Report RejectNegative Mask(POWERPC)
+Target Report RejectNegative Mask(POWERPC) Save
 Use PowerPC instruction set
 
 mno-powerpc
@@ -45,59 +51,59 @@  Target Report Mask(POWERPC64)
 Use PowerPC-64 instruction set
 
 mpowerpc-gpopt
-Target Report Mask(PPC_GPOPT)
+Target Report Mask(PPC_GPOPT) Save
 Use PowerPC General Purpose group optional instructions
 
 mpowerpc-gfxopt
-Target Report Mask(PPC_GFXOPT)
+Target Report Mask(PPC_GFXOPT) Save
 Use PowerPC Graphics group optional instructions
 
 mmfcrf
-Target Report Mask(MFCRF)
+Target Report Mask(MFCRF) Save
 Use PowerPC V2.01 single field mfcr instruction
 
 mpopcntb
-Target Report Mask(POPCNTB)
+Target Report Mask(POPCNTB) Save
 Use PowerPC V2.02 popcntb instruction
 
 mfprnd
-Target Report Mask(FPRND)
+Target Report Mask(FPRND) Save
 Use PowerPC V2.02 floating point rounding instructions
 
 mcmpb
-Target Report Mask(CMPB)
+Target Report Mask(CMPB) Save
 Use PowerPC V2.05 compare bytes instruction
 
 mmfpgpr
-Target Report Mask(MFPGPR)
+Target Report Mask(MFPGPR) Save
 Use extended PowerPC V2.05 move floating point to/from GPR instructions
 
 maltivec
-Target Report Mask(ALTIVEC)
+Target Report Mask(ALTIVEC) Save
 Use AltiVec instructions
 
 mhard-dfp
-Target Report Mask(DFP)
+Target Report Mask(DFP) Save
 Use decimal floating point instructions
 
 mmulhw
-Target Report Mask(MULHW)
+Target Report Mask(MULHW) Save
 Use 4xx half-word multiply instructions
 
 mdlmzb
-Target Report Mask(DLMZB)
+Target Report Mask(DLMZB) Save
 Use 4xx string-search dlmzb instruction
 
 mmultiple
-Target Report Mask(MULTIPLE)
+Target Report Mask(MULTIPLE) Save
 Generate load/store multiple instructions
 
 mstring
-Target Report Mask(STRING)
+Target Report Mask(STRING) Save
 Generate string instructions for block moves
 
 mnew-mnemonics
-Target Report RejectNegative Mask(NEW_MNEMONICS)
+Target Report RejectNegative Mask(NEW_MNEMONICS) Save
 Use new mnemonics for PowerPC architecture
 
 mold-mnemonics
@@ -105,7 +111,7 @@  Target Report RejectNegative InverseMask
 Use old mnemonics for PowerPC architecture
 
 msoft-float
-Target Report RejectNegative Mask(SOFT_FLOAT)
+Target Report RejectNegative Mask(SOFT_FLOAT) Save
 Do not use hardware floating point
 
 mhard-float
@@ -113,11 +119,11 @@  Target Report RejectNegative InverseMask
 Use hardware floating point
 
 mpopcntd
-Target Report Mask(POPCNTD)
+Target Report Mask(POPCNTD) Save
 Use PowerPC V2.06 popcntd instruction
 
 mfriz
-Target Report Var(TARGET_FRIZ) Init(-1)
+Target Report Var(TARGET_FRIZ) Init(-1) Save
 Under -ffast-math, generate a FRIZ instruction for (double)(long long) conversions
 
 mveclibabi=
@@ -125,7 +131,7 @@  Target RejectNegative Joined Var(rs6000_
 Vector library ABI to use
 
 mvsx
-Target Report Mask(VSX)
+Target Report Mask(VSX) Save
 Use vector/scalar (VSX) instructions
 
 mvsx-scalar-double
@@ -165,7 +171,7 @@  Target Undocumented Report Var(TARGET_VE
 ; Explicitly control whether we vectorize the builtins or not.
 
 mno-update
-Target Report RejectNegative Mask(NO_UPDATE)
+Target Report RejectNegative Mask(NO_UPDATE) Save
 Do not generate load/store with update instructions
 
 mupdate
@@ -173,26 +179,26 @@  Target Report RejectNegative InverseMask
 Generate load/store with update instructions
 
 mavoid-indexed-addresses
-Target Report Var(TARGET_AVOID_XFORM) Init(-1)
+Target Report Var(TARGET_AVOID_XFORM) Init(-1) Save
 Avoid generation of indexed load/store instructions when possible
 
 mfused-madd
-Target Report Var(TARGET_FUSED_MADD) Init(1)
+Target Report Var(TARGET_FUSED_MADD) Init(1) Save
 Generate fused multiply/add instructions
 
 mtls-markers
-Target Report Var(tls_markers) Init(1)
+Target Report Var(tls_markers) Init(1) Save
 Mark __tls_get_addr calls with argument info
 
 msched-epilog
-Target Undocumented Var(TARGET_SCHED_PROLOG) Init(1)
+Target Undocumented Var(TARGET_SCHED_PROLOG) Init(1) Save
 
 msched-prolog
-Target Report Var(TARGET_SCHED_PROLOG)
+Target Report Var(TARGET_SCHED_PROLOG) Save
 Schedule the start and end of the procedure
 
 maix-struct-return
-Target Report RejectNegative Var(aix_struct_return)
+Target Report RejectNegative Var(aix_struct_return) Save
 Return all structures in memory (AIX default)
 
 msvr4-struct-return
@@ -212,11 +218,11 @@  Target Report RejectNegative Joined
 Generate software reciprocal divide and square root for better throughput.
 
 mrecip-precision
-Target Report Mask(RECIP_PRECISION)
+Target Report Mask(RECIP_PRECISION) Save
 Assume that the reciprocal estimate instructions provide more accuracy.
 
 mno-fp-in-toc
-Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC)
+Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC) Save
 Do not place floating point constants in TOC
 
 mfp-in-toc
@@ -224,7 +230,7 @@  Target Report RejectNegative Var(TARGET_
 Place floating point constants in TOC
 
 mno-sum-in-toc
-Target RejectNegative Var(TARGET_NO_SUM_IN_TOC)
+Target RejectNegative Var(TARGET_NO_SUM_IN_TOC) Save
 Do not place symbol+offset constants in TOC
 
 msum-in-toc
@@ -239,7 +245,7 @@  Place symbol+offset constants in TOC
 ;   This is at the cost of having 2 extra loads and one extra store per
 ;   function, and one less allocable register.
 mminimal-toc
-Target Report Mask(MINIMAL_TOC)
+Target Report Mask(MINIMAL_TOC) Save
 Use only one TOC entry per procedure
 
 mfull-toc
@@ -247,7 +253,7 @@  Target Report
 Put everything in the regular TOC
 
 mvrsave
-Target Report Var(TARGET_ALTIVEC_VRSAVE)
+Target Report Var(TARGET_ALTIVEC_VRSAVE) Save
 Generate VRSAVE instructions when generating AltiVec code
 
 mvrsave=
@@ -255,11 +261,11 @@  Target RejectNegative Joined
 -mvrsave=yes/no	Deprecated option.  Use -mvrsave/-mno-vrsave instead
 
 mblock-move-inline-limit=
-Target Report Var(rs6000_block_move_inline_limit) Init(0) RejectNegative Joined UInteger
+Target Report Var(rs6000_block_move_inline_limit) Init(0) RejectNegative Joined UInteger Save
 Specify how many bytes should be moved inline before calling out to memcpy/memmove
 
 misel
-Target Report Mask(ISEL)
+Target Report Mask(ISEL) Save
 Generate isel instructions
 
 misel=
@@ -267,11 +273,11 @@  Target RejectNegative Joined
 -misel=yes/no	Deprecated option.  Use -misel/-mno-isel instead
 
 mspe
-Target
+Target Save
 Generate SPE SIMD instructions on E500
 
 mpaired
-Target Var(rs6000_paired_float)
+Target Var(rs6000_paired_float) Save
 Generate PPC750CL paired-single instructions
 
 mspe=
@@ -299,19 +305,19 @@  Target RejectNegative Joined
 -mtraceback=	Select full, part, or no traceback table
 
 mlongcall
-Target Report Var(rs6000_default_long_calls)
+Target Report Var(rs6000_default_long_calls) Save
 Avoid all range limits on call instructions
 
 mgen-cell-microcode
-Target Report Var(rs6000_gen_cell_microcode) Init(-1)
+Target Report Var(rs6000_gen_cell_microcode) Init(-1) Save
 Generate Cell microcode
 
 mwarn-cell-microcode
-Target Var(rs6000_warn_cell_microcode) Init(0) Warning
+Target Var(rs6000_warn_cell_microcode) Init(0) Warning Save
 Warn when a Cell microcoded instruction is emitted
 
 mwarn-altivec-long
-Target Var(rs6000_warn_altivec_long) Init(1)
+Target Var(rs6000_warn_altivec_long) Init(1) Save
 Warn about deprecated 'vector long ...' AltiVec type usage
 
 mfloat-gprs=
@@ -335,19 +341,19 @@  Target RejectNegative Joined
 Specify alignment of structure fields default/natural
 
 mprioritize-restricted-insns=
-Target RejectNegative Joined UInteger Var(rs6000_sched_restricted_insns_priority)
+Target RejectNegative Joined UInteger Var(rs6000_sched_restricted_insns_priority) Save
 Specify scheduling priority for dispatch slot restricted insns
 
 msingle-float
-Target RejectNegative Var(rs6000_single_float)
+Target RejectNegative Var(rs6000_single_float) Save
 Single-precision floating point unit
 
 mdouble-float
-Target RejectNegative Var(rs6000_double_float)
+Target RejectNegative Var(rs6000_double_float) Save
 Double-precision floating point unit
 
 msimple-fpu
-Target RejectNegative Var(rs6000_simple_fpu)
+Target RejectNegative Var(rs6000_simple_fpu) Save
 Floating point unit does not support divide & sqrt
 
 mfpu=
@@ -355,7 +361,7 @@  Target RejectNegative Joined 
 -mfpu=	Specify FP (sp, dp, sp-lite, dp-lite) (implies -mxilinx-fpu)
 
 mxilinx-fpu
-Target Var(rs6000_xilinx_fpu)
+Target Var(rs6000_xilinx_fpu) Save
 Specify Xilinx FPU.
 
 
Index: gcc/config/rs6000/linuxaltivec.h
===================================================================
--- gcc/config/rs6000/linuxaltivec.h	(revision 165044)
+++ gcc/config/rs6000/linuxaltivec.h	(working copy)
@@ -27,4 +27,4 @@ 
 #define	TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_ALTIVEC)
 
 #undef  SUBSUBTARGET_OVERRIDE_OPTIONS
-#define SUBSUBTARGET_OVERRIDE_OPTIONS rs6000_altivec_abi = 1
+#define SUBSUBTARGET_OVERRIDE_OPTIONS rs6000_opts.altivec_abi = 1
Index: gcc/config/rs6000/linux64.h
===================================================================
--- gcc/config/rs6000/linux64.h	(revision 165044)
+++ gcc/config/rs6000/linux64.h	(working copy)
@@ -65,10 +65,9 @@  extern int dot_symbols;
 
 #define TARGET_USES_LINUX64_OPT 1
 #ifdef HAVE_LD_LARGE_TOC
-extern enum rs6000_cmodel cmodel;
 #undef TARGET_CMODEL
-#define TARGET_CMODEL cmodel
-#define SET_CMODEL(opt) cmodel = opt
+#define TARGET_CMODEL rs6000_opts.cmodel
+#define SET_CMODEL(opt) rs6000_opts.cmodel = opt
 #else
 #define SET_CMODEL(opt) do {} while (0)
 #endif
@@ -95,15 +94,16 @@  extern enum rs6000_cmodel cmodel;
   do								\
     {								\
       if (!rs6000_explicit_options.alignment)			\
-	rs6000_alignment_flags = MASK_ALIGN_NATURAL;		\
+	rs6000_opts.alignment_flags = MASK_ALIGN_NATURAL;	\
       if (TARGET_64BIT)						\
 	{							\
 	  if (DEFAULT_ABI != ABI_AIX)				\
 	    {							\
-	      rs6000_current_abi = ABI_AIX;			\
+	      rs6000_opts.abi = ABI_AIX;			\
 	      error (INVALID_64BIT, "call");			\
 	    }							\
-	  dot_symbols = !strcmp (rs6000_abi_name, "aixdesc");	\
+	  dot_symbols = !strcmp (rs6000_opts_str.abi_name,	\
+				 "aixdesc");			\
 	  if (target_flags & MASK_RELOCATABLE)			\
 	    {							\
 	      target_flags &= ~MASK_RELOCATABLE;		\
@@ -127,7 +127,7 @@  extern enum rs6000_cmodel cmodel;
 	  if ((target_flags_explicit & MASK_MINIMAL_TOC) != 0)	\
 	    {							\
 	      if (rs6000_explicit_options.cmodel		\
-		  && cmodel != CMODEL_SMALL)			\
+		  && rs6000_opts.cmodel != CMODEL_SMALL)	\
 		error ("-mcmodel incompatible with other toc options"); \
 	      SET_CMODEL (CMODEL_SMALL);			\
 	    }							\
@@ -135,7 +135,7 @@  extern enum rs6000_cmodel cmodel;
 	    {							\
 	      if (!rs6000_explicit_options.cmodel)		\
 		SET_CMODEL (CMODEL_MEDIUM);			\
-	      if (cmodel != CMODEL_SMALL)			\
+	      if (rs6000_opts.cmodel != CMODEL_SMALL)		\
 		{						\
 		  TARGET_NO_FP_IN_TOC = 0;			\
 		  TARGET_NO_SUM_IN_TOC = 0;			\
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 165044)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -71,6 +71,16 @@ 
 #define min(A,B)	((A) < (B) ? (A) : (B))
 #define max(A,B)	((A) > (B) ? (A) : (B))
 
+/* Target specific variables, flags, etc.  These are all grouped in a structure
+   so that it can be copied and restored if functions are compiled with
+   different target options.  */
+struct rs6000_options rs6000_opts;
+
+/* Option strings that are processed in rs6000_handle_option and then dealt
+   with in rs6000_override_options.  Don't use GTY(()) for these, since
+   the strings are not allocated.  */
+struct rs6000_option_strings rs6000_opts_str;
+
 /* Structure used to define the rs6000 stack */
 typedef struct rs6000_stack {
   int first_gp_reg_save;	/* first callee saved GP register used */
@@ -136,7 +146,6 @@  typedef struct GTY(()) machine_function
 
 /* Target cpu type */
 
-enum processor_type rs6000_cpu;
 struct rs6000_cpu_select rs6000_select[3] =
 {
   /* switch		name,			tune	arch */
@@ -145,47 +154,9 @@  struct rs6000_cpu_select rs6000_select[3
   { (const char *)0,	"-mtune=",		1,	0 },
 };
 
-/* Always emit branch hint bits.  */
-static GTY(()) bool rs6000_always_hint;
-
-/* Schedule instructions for group formation.  */
-static GTY(()) bool rs6000_sched_groups;
-
-/* Align branch targets.  */
-static GTY(()) bool rs6000_align_branch_targets;
-
-/* Support for -msched-costly-dep option.  */
-const char *rs6000_sched_costly_dep_str;
-enum rs6000_dependence_cost rs6000_sched_costly_dep;
-
-/* Support for -minsert-sched-nops option.  */
-const char *rs6000_sched_insert_nops_str;
-enum rs6000_nop_insertion rs6000_sched_insert_nops;
-
 /* Support targetm.vectorize.builtin_mask_for_load.  */
 static GTY(()) tree altivec_builtin_mask_for_load;
 
-/* Size of long double.  */
-int rs6000_long_double_type_size;
-
-/* IEEE quad extended precision long double. */
-int rs6000_ieeequad;
-
-/* Nonzero to use AltiVec ABI.  */
-int rs6000_altivec_abi;
-
-/* Nonzero if we want SPE SIMD instructions.  */
-int rs6000_spe;
-
-/* Nonzero if we want SPE ABI extensions.  */
-int rs6000_spe_abi;
-
-/* Nonzero if floating point operations are done in the GPRs.  */
-int rs6000_float_gprs = 0;
-
-/* Nonzero if we want Darwin's struct-by-value-in-regs ABI.  */
-int rs6000_darwin64_abi;
-
 /* Set to nonzero once AIX common-mode calls have been defined.  */
 static GTY(()) int common_mode_defined;
 
@@ -194,37 +165,13 @@  static GTY(()) int common_mode_defined;
 int rs6000_pic_labelno;
 
 #ifdef USING_ELFOS_H
-/* Which abi to adhere to */
-const char *rs6000_abi_name;
-
-/* Semantics of the small data area */
-enum rs6000_sdata_type rs6000_sdata = SDATA_DATA;
-
-/* Which small data model to use */
-const char *rs6000_sdata_name = (char *)0;
-
 /* Counter for labels which are to be placed in .fixup.  */
 int fixuplabelno = 0;
 #endif
 
-/* Bit size of immediate TLS offsets and string from which it is decoded.  */
-int rs6000_tls_size = 32;
-const char *rs6000_tls_size_string;
-
-/* ABI enumeration available for subtarget to use.  */
-enum rs6000_abi rs6000_current_abi;
-
 /* Whether to use variant of AIX ABI for PowerPC64 Linux.  */
 int dot_symbols;
 
-/* Debug flags */
-const char *rs6000_debug_name;
-int rs6000_debug_stack;		/* debug stack applications */
-int rs6000_debug_arg;		/* debug argument handling */
-int rs6000_debug_reg;		/* debug register classes */
-int rs6000_debug_addr;		/* debug memory addressing */
-int rs6000_debug_cost;		/* debug rtx_costs */
-
 /* Specify the machine mode that pointers have.  After generation of rtl, the
    compiler makes no further distinction between pointers and any other objects
    of this machine mode.  The type is unsigned since not all things that
@@ -254,13 +201,8 @@  static enum insn_code rs6000_vector_relo
 tree rs6000_builtin_types[RS6000_BTI_MAX];
 tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
 
-const char *rs6000_traceback_name;
-static enum {
-  traceback_default = 0,
-  traceback_none,
-  traceback_part,
-  traceback_full
-} rs6000_traceback;
+/* Type of traceback to use.  */
+static const char *rs6000_traceback_name;
 
 /* Flag to say the TOC is initialized */
 int toc_initialized;
@@ -276,13 +218,6 @@  static GTY(()) section *read_only_privat
 static GTY(()) section *sdata2_section;
 static GTY(()) section *toc_section;
 
-/* Control alignment for fields within structures.  */
-/* String from -malign-XXXXX.  */
-int rs6000_alignment_flags;
-
-/* Code model for 64-bit linux.  */
-enum rs6000_cmodel cmodel;
-
 /* True for any options that were explicitly set.  */
 static struct {
   bool aix_struct_ret;		/* True if -maix-struct-ret was used.  */
@@ -352,9 +287,6 @@  enum rs6000_recip_mask {
   RECIP_LOW_PRECISION	= (RECIP_ALL & ~(RECIP_DF_RSQRT | RECIP_V2DF_RSQRT))
 };
 
-static unsigned int rs6000_recip_control;
-static const char *rs6000_recip_name;
-
 /* -mrecip options.  */
 static struct
 {
@@ -1927,9 +1859,10 @@  rs6000_debug_reg_global (void)
   if (nl)
     fputs (nl, stderr);
 
-  if (rs6000_recip_control)
+  if (rs6000_opts.recip_control)
     {
-      fprintf (stderr, "\nReciprocal mask = 0x%x\n", rs6000_recip_control);
+      fprintf (stderr, "\nReciprocal mask = 0x%x\n",
+	       rs6000_opts.recip_control);
 
       for (m = 0; m < NUM_MACHINE_MODES; ++m)
 	if (rs6000_recip_bits[m])
@@ -1948,7 +1881,7 @@  rs6000_debug_reg_global (void)
       fputs ("\n", stderr);
     }
 
-  switch (rs6000_sched_costly_dep)
+  switch (rs6000_opts.sched_costly_dep)
     {
     case max_dep_latency:
       costly_str = "max_dep_latency";
@@ -1972,11 +1905,11 @@  rs6000_debug_reg_global (void)
 
     default:
       costly_str = costly_num;
-      sprintf (costly_num, "%d", (int)rs6000_sched_costly_dep);
+      sprintf (costly_num, "%d", (int)rs6000_opts.sched_costly_dep);
       break;
     }
 
-  switch (rs6000_sched_insert_nops)
+  switch (rs6000_opts.insert_nops)
     {
     case sched_finish_regroup_exact:
       nop_str = "sched_finish_regroup_exact";
@@ -1992,7 +1925,7 @@  rs6000_debug_reg_global (void)
 
     default:
       nop_str = nop_num;
-      sprintf (nop_num, "%d", (int)rs6000_sched_insert_nops);
+      sprintf (nop_num, "%d", (int)rs6000_opts.insert_nops);
       break;
     }
 
@@ -2002,8 +1935,8 @@  rs6000_debug_reg_global (void)
 	   "sched_restricted_insns_priority = %d\n"
 	   "sched_costly_dep                = %s\n"
 	   "sched_insert_nops               = %s\n\n",
-	   rs6000_always_hint ? "true" : "false",
-	   rs6000_align_branch_targets ? "true" : "false",
+	   rs6000_opts.always_hint ? "true" : "false",
+	   rs6000_opts.align_branch_targets ? "true" : "false",
 	   (int)rs6000_sched_restricted_insns_priority,
 	   costly_str, nop_str);
 }
@@ -2259,7 +2192,7 @@  rs6000_init_hard_regno_mode_ok (void)
   if (VECTOR_UNIT_VSX_P (V2DFmode))
     rs6000_recip_bits[V2DFmode] |= RS6000_RECIP_MASK_HAVE_RSQRTE;
 
-  if (rs6000_recip_control)
+  if (rs6000_opts.recip_control)
     {
       if (!TARGET_FUSED_MADD)
 	warning (0, "-mrecip requires -mfused-madd");
@@ -2273,35 +2206,35 @@  rs6000_init_hard_regno_mode_ok (void)
 	  && flag_reciprocal_math)
 	{
 	  if (RS6000_RECIP_HAVE_RE_P (SFmode)
-	      && (rs6000_recip_control & RECIP_SF_DIV) != 0)
+	      && (rs6000_opts.recip_control & RECIP_SF_DIV) != 0)
 	    rs6000_recip_bits[SFmode] |= RS6000_RECIP_MASK_AUTO_RE;
 
 	  if (RS6000_RECIP_HAVE_RE_P (DFmode)
-	      && (rs6000_recip_control & RECIP_DF_DIV) != 0)
+	      && (rs6000_opts.recip_control & RECIP_DF_DIV) != 0)
 	    rs6000_recip_bits[DFmode] |= RS6000_RECIP_MASK_AUTO_RE;
 
 	  if (RS6000_RECIP_HAVE_RE_P (V4SFmode)
-	      && (rs6000_recip_control & RECIP_V4SF_DIV) != 0)
+	      && (rs6000_opts.recip_control & RECIP_V4SF_DIV) != 0)
 	    rs6000_recip_bits[V4SFmode] |= RS6000_RECIP_MASK_AUTO_RE;
 
 	  if (RS6000_RECIP_HAVE_RE_P (V2DFmode)
-	      && (rs6000_recip_control & RECIP_V2DF_DIV) != 0)
+	      && (rs6000_opts.recip_control & RECIP_V2DF_DIV) != 0)
 	    rs6000_recip_bits[V2DFmode] |= RS6000_RECIP_MASK_AUTO_RE;
 
 	  if (RS6000_RECIP_HAVE_RSQRTE_P (SFmode)
-	      && (rs6000_recip_control & RECIP_SF_RSQRT) != 0)
+	      && (rs6000_opts.recip_control & RECIP_SF_RSQRT) != 0)
 	    rs6000_recip_bits[SFmode] |= RS6000_RECIP_MASK_AUTO_RSQRTE;
 
 	  if (RS6000_RECIP_HAVE_RSQRTE_P (DFmode)
-	      && (rs6000_recip_control & RECIP_DF_RSQRT) != 0)
+	      && (rs6000_opts.recip_control & RECIP_DF_RSQRT) != 0)
 	    rs6000_recip_bits[DFmode] |= RS6000_RECIP_MASK_AUTO_RSQRTE;
 
 	  if (RS6000_RECIP_HAVE_RSQRTE_P (V4SFmode)
-	      && (rs6000_recip_control & RECIP_V4SF_RSQRT) != 0)
+	      && (rs6000_opts.recip_control & RECIP_V4SF_RSQRT) != 0)
 	    rs6000_recip_bits[V4SFmode] |= RS6000_RECIP_MASK_AUTO_RSQRTE;
 
 	  if (RS6000_RECIP_HAVE_RSQRTE_P (V2DFmode)
-	      && (rs6000_recip_control & RECIP_V2DF_RSQRT) != 0)
+	      && (rs6000_opts.recip_control & RECIP_V2DF_RSQRT) != 0)
 	    rs6000_recip_bits[V2DFmode] |= RS6000_RECIP_MASK_AUTO_RSQRTE;
 	}
     }
@@ -2350,7 +2283,7 @@  darwin_rs6000_override_options (void)
 {
   /* The Darwin ABI always includes AltiVec, can't be (validly) turned
      off.  */
-  rs6000_altivec_abi = 1;
+  rs6000_opts.altivec_abi = 1;
   TARGET_ALTIVEC_VRSAVE = 1;
   if (DEFAULT_ABI == ABI_DARWIN)
   {
@@ -2615,7 +2548,7 @@  rs6000_option_override_internal (const c
 
   /* Identify the processor type.  */
   rs6000_select[0].string = default_cpu;
-  rs6000_cpu = TARGET_POWERPC64 ? PROCESSOR_DEFAULT64 : PROCESSOR_DEFAULT;
+  rs6000_opts.cpu = TARGET_POWERPC64 ? PROCESSOR_DEFAULT64 : PROCESSOR_DEFAULT;
 
   for (i = 0; i < ARRAY_SIZE (rs6000_select); i++)
     {
@@ -2626,7 +2559,7 @@  rs6000_option_override_internal (const c
 	    if (! strcmp (ptr->string, processor_target_table[j].name))
 	      {
 		if (ptr->set_tune_p)
-		  rs6000_cpu = processor_target_table[j].processor;
+		  rs6000_opts.cpu = processor_target_table[j].processor;
 
 		if (ptr->set_arch_p)
 		  {
@@ -2642,8 +2575,10 @@  rs6000_option_override_internal (const c
 	}
     }
 
-  if (rs6000_cpu == PROCESSOR_PPCE300C2 || rs6000_cpu == PROCESSOR_PPCE300C3
-      || rs6000_cpu == PROCESSOR_PPCE500MC || rs6000_cpu == PROCESSOR_PPCE500MC64)
+  if (rs6000_opts.cpu == PROCESSOR_PPCE300C2
+      || rs6000_opts.cpu == PROCESSOR_PPCE300C3
+      || rs6000_opts.cpu == PROCESSOR_PPCE500MC
+      || rs6000_opts.cpu == PROCESSOR_PPCE500MC64)
     {
       if (TARGET_ALTIVEC)
 	error ("AltiVec not supported in this target");
@@ -2654,7 +2589,7 @@  rs6000_option_override_internal (const c
   /* Disable Cell microcode if we are optimizing for the Cell
      and not optimizing for size.  */
   if (rs6000_gen_cell_microcode == -1)
-    rs6000_gen_cell_microcode = !(rs6000_cpu == PROCESSOR_CELL
+    rs6000_gen_cell_microcode = !(rs6000_opts.cpu == PROCESSOR_CELL
                                   && !optimize_size);
 
   /* If we are optimizing big endian systems for space and it's OK to
@@ -2669,7 +2604,7 @@  rs6000_option_override_internal (const c
      trap.  The 750 does not cause an alignment trap (except when the
      target is unaligned).  */
 
-  if (!BYTES_BIG_ENDIAN && rs6000_cpu != PROCESSOR_PPC750)
+  if (!BYTES_BIG_ENDIAN && rs6000_opts.cpu != PROCESSOR_PPC750)
     {
       if (TARGET_MULTIPLE)
 	{
@@ -2741,8 +2676,8 @@  rs6000_option_override_internal (const c
   /* E500mc does "better" if we inline more aggressively.  Respect the
      user's opinion, though.  */
   if (rs6000_block_move_inline_limit == 0
-      && (rs6000_cpu == PROCESSOR_PPCE500MC
-	  || rs6000_cpu == PROCESSOR_PPCE500MC64))
+      && (rs6000_opts.cpu == PROCESSOR_PPCE500MC
+	  || rs6000_opts.cpu == PROCESSOR_PPCE500MC64))
     rs6000_block_move_inline_limit = 128;
 
   /* store_one_arg depends on expand_block_move to handle at least the
@@ -2751,23 +2686,29 @@  rs6000_option_override_internal (const c
     rs6000_block_move_inline_limit = (TARGET_POWERPC64 ? 64 : 32);
 
   /* Set debug flags */
-  if (rs6000_debug_name)
+  if (rs6000_opts_str.debug_name)
     {
-      if (! strcmp (rs6000_debug_name, "all"))
-	rs6000_debug_stack = rs6000_debug_arg = rs6000_debug_reg
-	  = rs6000_debug_addr = rs6000_debug_cost = 1;
-      else if (! strcmp (rs6000_debug_name, "stack"))
-	rs6000_debug_stack = 1;
-      else if (! strcmp (rs6000_debug_name, "arg"))
-	rs6000_debug_arg = 1;
-      else if (! strcmp (rs6000_debug_name, "reg"))
-	rs6000_debug_reg = 1;
-      else if (! strcmp (rs6000_debug_name, "addr"))
-	rs6000_debug_addr = 1;
-      else if (! strcmp (rs6000_debug_name, "cost"))
-	rs6000_debug_cost = 1;
-      else
-	error ("unknown -mdebug-%s switch", rs6000_debug_name);
+      char *p = ASTRDUP (rs6000_opts_str.debug_name);
+      char *q;
+      rs6000_opts.debug = 0;
+
+      while ((q = strtok (p, ",")) != NULL)
+	{
+	  if (! strcmp (q, "all"))
+	    rs6000_opts.debug |= MASK_DEBUG_ALL;
+	  else if (! strcmp (q, "stack"))
+	    rs6000_opts.debug |= MASK_DEBUG_STACK;
+	  else if (! strcmp (q, "arg"))
+	    rs6000_opts.debug |= MASK_DEBUG_ARG;
+	  else if (! strcmp (q, "reg"))
+	    rs6000_opts.debug |= MASK_DEBUG_REG;
+	  else if (! strcmp (q, "addr"))
+	    rs6000_opts.debug |= MASK_DEBUG_ADDR;
+	  else if (! strcmp (q, "cost"))
+	    rs6000_opts.debug |= MASK_DEBUG_COST;
+	  else
+	    error ("unknown -mdebug-%s switch", q);
+	}
 
       /* If the appropriate debug option is enabled, replace the target hooks
 	 with debug versions that call the real version and then prints
@@ -2801,11 +2742,11 @@  rs6000_option_override_internal (const c
   if (rs6000_traceback_name)
     {
       if (! strncmp (rs6000_traceback_name, "full", 4))
-	rs6000_traceback = traceback_full;
+	rs6000_opts.traceback = traceback_full;
       else if (! strncmp (rs6000_traceback_name, "part", 4))
-	rs6000_traceback = traceback_part;
+	rs6000_opts.traceback = traceback_part;
       else if (! strncmp (rs6000_traceback_name, "no", 2))
-	rs6000_traceback = traceback_none;
+	rs6000_opts.traceback = traceback_none;
       else
 	error ("unknown -mtraceback arg %qs; expecting %<full%>, %<partial%> or %<none%>",
 	       rs6000_traceback_name);
@@ -2821,16 +2762,16 @@  rs6000_option_override_internal (const c
     }
 
   if (!rs6000_explicit_options.long_double)
-    rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
+    rs6000_opts.long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
 
 #ifndef POWERPC_LINUX
   if (!rs6000_explicit_options.ieee)
-    rs6000_ieeequad = 1;
+    rs6000_opts.ieeequad = 1;
 #endif
 
   /* Enable Altivec ABI for AIX -maltivec.  */
   if (TARGET_XCOFF && (TARGET_ALTIVEC || TARGET_VSX))
-    rs6000_altivec_abi = 1;
+    rs6000_opts.altivec_abi = 1;
 
   /* The AltiVec ABI is the default for PowerPC-64 GNU/Linux.  For
      PowerPC-32 GNU/Linux, -maltivec implies the AltiVec ABI.  It can
@@ -2839,11 +2780,11 @@  rs6000_option_override_internal (const c
     {
       if (!rs6000_explicit_options.altivec_abi
 	  && (TARGET_64BIT || TARGET_ALTIVEC || TARGET_VSX))
-	rs6000_altivec_abi = 1;
+	rs6000_opts.altivec_abi = 1;
 
       /* Enable VRSAVE for AltiVec ABI, unless explicitly overridden.  */
       if (!rs6000_explicit_options.vrsave)
-	TARGET_ALTIVEC_VRSAVE = rs6000_altivec_abi;
+	TARGET_ALTIVEC_VRSAVE = rs6000_opts.altivec_abi;
     }
 
   /* Set the Darwin64 ABI as default for 64-bit Darwin.  
@@ -2852,9 +2793,9 @@  rs6000_option_override_internal (const c
       && DEFAULT_ABI == ABI_DARWIN 
       && TARGET_64BIT)
     {
-      rs6000_darwin64_abi = 1;
+      rs6000_opts.darwin64_abi = 1;
       /* Default to natural alignment, for better performance.  */
-      rs6000_alignment_flags = MASK_ALIGN_NATURAL;
+      rs6000_opts.alignment_flags = MASK_ALIGN_NATURAL;
     }
 
   /* Place FP constants in the constant pool instead of TOC
@@ -2875,8 +2816,8 @@  rs6000_option_override_internal (const c
   SUB3TARGET_OVERRIDE_OPTIONS;
 #endif
 
-  if (TARGET_E500 || rs6000_cpu == PROCESSOR_PPCE500MC
-      || rs6000_cpu == PROCESSOR_PPCE500MC64)
+  if (TARGET_E500 || rs6000_opts.cpu == PROCESSOR_PPCE500MC
+      || rs6000_opts.cpu == PROCESSOR_PPCE500MC64)
     {
       /* The e500 and e500mc do not have string instructions, and we set
 	 MASK_STRING above when optimizing for size.  */
@@ -2889,11 +2830,11 @@  rs6000_option_override_internal (const c
 	 default, so let's unset them if we manually set another
 	 CPU that is not the E500.  */
       if (!rs6000_explicit_options.spe_abi)
-	rs6000_spe_abi = 0;
+	rs6000_opts.spe_abi = 0;
       if (!rs6000_explicit_options.spe)
-	rs6000_spe = 0;
+	rs6000_opts.spe = 0;
       if (!rs6000_explicit_options.float_gprs)
-	rs6000_float_gprs = 0;
+	rs6000_opts.float_gprs = 0;
       if (!(target_flags_explicit & MASK_ISEL))
 	target_flags &= ~MASK_ISEL;
     }
@@ -2901,69 +2842,75 @@  rs6000_option_override_internal (const c
   /* Detect invalid option combinations with E500.  */
   CHECK_E500_OPTIONS;
 
-  rs6000_always_hint = (rs6000_cpu != PROCESSOR_POWER4
-			&& rs6000_cpu != PROCESSOR_POWER5
-			&& rs6000_cpu != PROCESSOR_POWER6
-			&& rs6000_cpu != PROCESSOR_POWER7
-			&& rs6000_cpu != PROCESSOR_PPCA2
-			&& rs6000_cpu != PROCESSOR_CELL);
-  rs6000_sched_groups = (rs6000_cpu == PROCESSOR_POWER4
-			 || rs6000_cpu == PROCESSOR_POWER5
-			 || rs6000_cpu == PROCESSOR_POWER7);
-  rs6000_align_branch_targets = (rs6000_cpu == PROCESSOR_POWER4
-				 || rs6000_cpu == PROCESSOR_POWER5
-				 || rs6000_cpu == PROCESSOR_POWER6
-				 || rs6000_cpu == PROCESSOR_POWER7
-				 || rs6000_cpu == PROCESSOR_PPCE500MC
-				 || rs6000_cpu == PROCESSOR_PPCE500MC64);
+  rs6000_opts.always_hint = (rs6000_opts.cpu != PROCESSOR_POWER4
+			     && rs6000_opts.cpu != PROCESSOR_POWER5
+			     && rs6000_opts.cpu != PROCESSOR_POWER6
+			     && rs6000_opts.cpu != PROCESSOR_POWER7
+			     && rs6000_opts.cpu != PROCESSOR_PPCA2
+			     && rs6000_opts.cpu != PROCESSOR_CELL);
+  rs6000_opts.sched_groups = (rs6000_opts.cpu == PROCESSOR_POWER4
+			      || rs6000_opts.cpu == PROCESSOR_POWER5
+			      || rs6000_opts.cpu == PROCESSOR_POWER7);
+  rs6000_opts.align_branch_targets
+    = (rs6000_opts.cpu == PROCESSOR_POWER4
+       || rs6000_opts.cpu == PROCESSOR_POWER5
+       || rs6000_opts.cpu == PROCESSOR_POWER6
+       || rs6000_opts.cpu == PROCESSOR_POWER7
+       || rs6000_opts.cpu == PROCESSOR_PPCE500MC
+       || rs6000_opts.cpu == PROCESSOR_PPCE500MC64);
 
   /* Allow debug switches to override the above settings.  */
   if (TARGET_ALWAYS_HINT > 0)
-    rs6000_always_hint = TARGET_ALWAYS_HINT;
+    rs6000_opts.always_hint = TARGET_ALWAYS_HINT;
 
   if (TARGET_SCHED_GROUPS > 0)
-    rs6000_sched_groups = TARGET_SCHED_GROUPS;
+    rs6000_opts.sched_groups = TARGET_SCHED_GROUPS;
 
   if (TARGET_ALIGN_BRANCH_TARGETS > 0)
-    rs6000_align_branch_targets = TARGET_ALIGN_BRANCH_TARGETS;
+    rs6000_opts.align_branch_targets = TARGET_ALIGN_BRANCH_TARGETS;
 
   rs6000_sched_restricted_insns_priority
-    = (rs6000_sched_groups ? 1 : 0);
+    = (rs6000_opts.sched_groups ? 1 : 0);
 
   /* Handle -msched-costly-dep option.  */
-  rs6000_sched_costly_dep
-    = (rs6000_sched_groups ? store_to_load_dep_costly : no_dep_costly);
+  rs6000_opts.sched_costly_dep
+    = (rs6000_opts.sched_groups ? store_to_load_dep_costly : no_dep_costly);
 
-  if (rs6000_sched_costly_dep_str)
+  if (rs6000_opts_str.sched_costly_dep_str)
     {
-      if (! strcmp (rs6000_sched_costly_dep_str, "no"))
-	rs6000_sched_costly_dep = no_dep_costly;
-      else if (! strcmp (rs6000_sched_costly_dep_str, "all"))
-	rs6000_sched_costly_dep = all_deps_costly;
-      else if (! strcmp (rs6000_sched_costly_dep_str, "true_store_to_load"))
-	rs6000_sched_costly_dep = true_store_to_load_dep_costly;
-      else if (! strcmp (rs6000_sched_costly_dep_str, "store_to_load"))
-	rs6000_sched_costly_dep = store_to_load_dep_costly;
-      else
-	rs6000_sched_costly_dep = ((enum rs6000_dependence_cost)
-				   atoi (rs6000_sched_costly_dep_str));
+      if (! strcmp (rs6000_opts_str.sched_costly_dep_str, "no"))
+	rs6000_opts.sched_costly_dep = no_dep_costly;
+      else if (! strcmp (rs6000_opts_str.sched_costly_dep_str, "all"))
+	rs6000_opts.sched_costly_dep = all_deps_costly;
+      else if (! strcmp (rs6000_opts_str.sched_costly_dep_str,
+			 "true_store_to_load"))
+	rs6000_opts.sched_costly_dep = true_store_to_load_dep_costly;
+      else if (! strcmp (rs6000_opts_str.sched_costly_dep_str,
+			 "store_to_load"))
+	rs6000_opts.sched_costly_dep = store_to_load_dep_costly;
+      else
+	rs6000_opts.sched_costly_dep
+	  = ((enum rs6000_dependence_cost)
+	     atoi (rs6000_opts_str.sched_costly_dep_str));
     }
 
   /* Handle -minsert-sched-nops option.  */
-  rs6000_sched_insert_nops
-    = (rs6000_sched_groups ? sched_finish_regroup_exact : sched_finish_none);
+  rs6000_opts.insert_nops
+    = (rs6000_opts.sched_groups ? sched_finish_regroup_exact : sched_finish_none);
 
-  if (rs6000_sched_insert_nops_str)
+  if (rs6000_opts_str.sched_insert_nops_str)
     {
-      if (! strcmp (rs6000_sched_insert_nops_str, "no"))
-	rs6000_sched_insert_nops = sched_finish_none;
-      else if (! strcmp (rs6000_sched_insert_nops_str, "pad"))
-	rs6000_sched_insert_nops = sched_finish_pad_groups;
-      else if (! strcmp (rs6000_sched_insert_nops_str, "regroup_exact"))
-	rs6000_sched_insert_nops = sched_finish_regroup_exact;
-      else
-	rs6000_sched_insert_nops = ((enum rs6000_nop_insertion)
-				    atoi (rs6000_sched_insert_nops_str));
+      if (! strcmp (rs6000_opts_str.sched_insert_nops_str, "no"))
+	rs6000_opts.insert_nops = sched_finish_none;
+      else if (! strcmp (rs6000_opts_str.sched_insert_nops_str, "pad"))
+	rs6000_opts.insert_nops = sched_finish_pad_groups;
+      else if (! strcmp (rs6000_opts_str.sched_insert_nops_str,
+			 "regroup_exact"))
+	rs6000_opts.insert_nops = sched_finish_regroup_exact;
+      else
+	rs6000_opts.insert_nops
+	  = ((enum rs6000_nop_insertion)
+	     atoi (rs6000_opts_str.sched_insert_nops_str));
     }
 
 #ifdef TARGET_REGNAMES
@@ -3004,8 +2951,8 @@  rs6000_option_override_internal (const c
     {
       /* Cell wants to be aligned 8byte for dual issue.  Titan wants to be
 	 aligned 8byte to avoid misprediction by the branch predictor.  */
-      if (rs6000_cpu == PROCESSOR_TITAN
-	  || rs6000_cpu == PROCESSOR_CELL)
+      if (rs6000_opts.cpu == PROCESSOR_TITAN
+	  || rs6000_opts.cpu == PROCESSOR_CELL)
 	{
 	  if (align_functions <= 0)
 	    align_functions = 8;
@@ -3014,7 +2961,7 @@  rs6000_option_override_internal (const c
 	  if (align_loops <= 0)
 	    align_loops = 8;
  	}
-      if (rs6000_align_branch_targets)
+      if (rs6000_opts.align_branch_targets)
 	{
 	  if (align_functions <= 0)
 	    align_functions = 16;
@@ -3041,7 +2988,7 @@  rs6000_option_override_internal (const c
   if (optimize_size)
     rs6000_cost = TARGET_POWERPC64 ? &size64_cost : &size32_cost;
   else
-    switch (rs6000_cpu)
+    switch (rs6000_opts.cpu)
       {
       case PROCESSOR_RIOS1:
 	rs6000_cost = &rios1_cost;
@@ -3191,12 +3138,12 @@  rs6000_option_override_internal (const c
   if (TARGET_AVOID_XFORM == -1)
     /* Avoid indexed addressing when targeting Power6 in order to avoid
      the DERAT mispredict penalty.  */
-    TARGET_AVOID_XFORM = (rs6000_cpu == PROCESSOR_POWER6 && TARGET_CMPB);
+    TARGET_AVOID_XFORM = (rs6000_opts.cpu == PROCESSOR_POWER6 && TARGET_CMPB);
 
   /* Set the -mrecip options.  */
-  if (rs6000_recip_name)
+  if (rs6000_opts_str.recip_name)
     {
-      char *p = ASTRDUP (rs6000_recip_name);
+      char *p = ASTRDUP (rs6000_opts_str.recip_name);
       char *q;
       unsigned int mask, i;
       bool invert;
@@ -3233,9 +3180,9 @@  rs6000_option_override_internal (const c
 	    }
 
 	  if (invert)
-	    rs6000_recip_control &= ~mask;
+	    rs6000_opts.recip_control &= ~mask;
 	  else
-	    rs6000_recip_control |= mask;
+	    rs6000_opts.recip_control |= mask;
 	}
     }
 
@@ -3248,6 +3195,12 @@  rs6000_option_override_internal (const c
 static void
 rs6000_option_override (void)
 {
+#ifdef USING_ELFOS_H
+  rs6000_opts.sdata = SDATA_DATA;
+#else
+  rs6000_opts.sdata = SDATA_NONE;
+#endif
+
   rs6000_option_override_internal (OPTION_TARGET_CPU_DEFAULT);
 }
 
@@ -3383,10 +3336,10 @@  rs6000_vector_alignment_reachable (const
 
   if (TARGET_32BIT)
     {
-      if (rs6000_alignment_flags == MASK_ALIGN_NATURAL)
+      if (rs6000_opts.alignment_flags == MASK_ALIGN_NATURAL)
         return true;
 
-      if (rs6000_alignment_flags ==  MASK_ALIGN_POWER)
+      if (rs6000_opts.alignment_flags ==  MASK_ALIGN_POWER)
         return true;
 
       return false;
@@ -3630,16 +3583,18 @@  rs6000_parse_yes_no_option (const char *
 static void
 rs6000_parse_tls_size_option (void)
 {
-  if (rs6000_tls_size_string == 0)
+  rs6000_opts.tls_size = 32;
+  if (rs6000_opts_str.tls_size_string == 0)
     return;
-  else if (strcmp (rs6000_tls_size_string, "16") == 0)
-    rs6000_tls_size = 16;
-  else if (strcmp (rs6000_tls_size_string, "32") == 0)
-    rs6000_tls_size = 32;
-  else if (strcmp (rs6000_tls_size_string, "64") == 0)
-    rs6000_tls_size = 64;
+  else if (strcmp (rs6000_opts_str.tls_size_string, "16") == 0)
+    rs6000_opts.tls_size = 16;
+  else if (strcmp (rs6000_opts_str.tls_size_string, "32") == 0)
+    rs6000_opts.tls_size = 32;
+  else if (strcmp (rs6000_opts_str.tls_size_string, "64") == 0)
+    rs6000_opts.tls_size = 64;
   else
-    error ("bad value %qs for -mtls-size switch", rs6000_tls_size_string);
+    error ("bad value %qs for -mtls-size switch",
+	   rs6000_opts_str.tls_size_string);
 }
 
 static void
@@ -4032,11 +3987,11 @@  rs6000_handle_option (size_t code, const
 #if defined (HAVE_LD_LARGE_TOC) && defined (TARGET_USES_LINUX64_OPT)
     case OPT_mcmodel_:
       if (strcmp (arg, "small") == 0)
-	cmodel = CMODEL_SMALL;
+	rs6000_opts.cmodel = CMODEL_SMALL;
       else if (strcmp (arg, "medium") == 0)
-	cmodel = CMODEL_MEDIUM;
+	rs6000_opts.cmodel = CMODEL_MEDIUM;
       else if (strcmp (arg, "large") == 0)
-	cmodel = CMODEL_LARGE;
+	rs6000_opts.cmodel = CMODEL_LARGE;
       else
 	{
 	  error ("invalid option for -mcmodel: '%s'", arg);
@@ -4065,7 +4020,7 @@  rs6000_handle_option (size_t code, const
       break;
 
     case OPT_minsert_sched_nops_:
-      rs6000_sched_insert_nops_str = arg;
+      rs6000_opts_str.sched_insert_nops_str = arg;
       break;
 
     case OPT_mminimal_toc:
@@ -4128,29 +4083,29 @@  rs6000_handle_option (size_t code, const
 
     case OPT_mspe:
       rs6000_explicit_options.spe = true;
-      rs6000_spe = value;
+      rs6000_opts.spe = value;
       break;
 
     case OPT_mspe_:
       rs6000_explicit_options.spe = true;
-      rs6000_parse_yes_no_option ("spe", arg, &(rs6000_spe));
+      rs6000_parse_yes_no_option ("spe", arg, &(rs6000_opts.spe));
       break;
 
     case OPT_mdebug_:
-      rs6000_debug_name = arg;
+      rs6000_opts_str.debug_name = arg;
       break;
 
 #ifdef TARGET_USES_SYSV4_OPT
     case OPT_mcall_:
-      rs6000_abi_name = arg;
+      rs6000_opts_str.abi_name = arg;
       break;
 
     case OPT_msdata_:
-      rs6000_sdata_name = arg;
+      rs6000_opts_str.sdata_name = arg;
       break;
 
     case OPT_mtls_size_:
-      rs6000_tls_size_string = arg;
+      rs6000_opts_str.tls_size_string = arg;
       break;
 
     case OPT_mrelocatable:
@@ -4181,53 +4136,53 @@  rs6000_handle_option (size_t code, const
       if (!strcmp (arg, "altivec"))
 	{
 	  rs6000_explicit_options.altivec_abi = true;
-	  rs6000_altivec_abi = 1;
+	  rs6000_opts.altivec_abi = 1;
 
 	  /* Enabling the AltiVec ABI turns off the SPE ABI.  */
-	  rs6000_spe_abi = 0;
+	  rs6000_opts.spe_abi = 0;
 	}
       else if (! strcmp (arg, "no-altivec"))
 	{
 	  rs6000_explicit_options.altivec_abi = true;
-	  rs6000_altivec_abi = 0;
+	  rs6000_opts.altivec_abi = 0;
 	}
       else if (! strcmp (arg, "spe"))
 	{
 	  rs6000_explicit_options.spe_abi = true;
-	  rs6000_spe_abi = 1;
-	  rs6000_altivec_abi = 0;
+	  rs6000_opts.spe_abi = 1;
+	  rs6000_opts.altivec_abi = 0;
 	  if (!TARGET_SPE_ABI)
 	    error ("not configured for ABI: '%s'", arg);
 	}
       else if (! strcmp (arg, "no-spe"))
 	{
 	  rs6000_explicit_options.spe_abi = true;
-	  rs6000_spe_abi = 0;
+	  rs6000_opts.spe_abi = 0;
 	}
 
       /* These are here for testing during development only, do not
 	 document in the manual please.  */
       else if (! strcmp (arg, "d64"))
 	{
-	  rs6000_darwin64_abi = 1;
+	  rs6000_opts.darwin64_abi = 1;
 	  warning (0, "Using darwin64 ABI");
 	}
       else if (! strcmp (arg, "d32"))
 	{
-	  rs6000_darwin64_abi = 0;
+	  rs6000_opts.darwin64_abi = 0;
 	  warning (0, "Using old darwin ABI");
 	}
 
       else if (! strcmp (arg, "ibmlongdouble"))
 	{
 	  rs6000_explicit_options.ieee = true;
-	  rs6000_ieeequad = 0;
+	  rs6000_opts.ieeequad = 0;
 	  warning (0, "Using IBM extended precision long double");
 	}
       else if (! strcmp (arg, "ieeelongdouble"))
 	{
 	  rs6000_explicit_options.ieee = true;
-	  rs6000_ieeequad = 1;
+	  rs6000_opts.ieeequad = 1;
 	  warning (0, "Using IEEE extended precision long double");
 	}
 
@@ -4253,11 +4208,11 @@  rs6000_handle_option (size_t code, const
     case OPT_mfloat_gprs_:
       rs6000_explicit_options.float_gprs = true;
       if (! strcmp (arg, "yes") || ! strcmp (arg, "single"))
-	rs6000_float_gprs = 1;
+	rs6000_opts.float_gprs = 1;
       else if (! strcmp (arg, "double"))
-	rs6000_float_gprs = 2;
+	rs6000_opts.float_gprs = 2;
       else if (! strcmp (arg, "no"))
-	rs6000_float_gprs = 0;
+	rs6000_opts.float_gprs = 0;
       else
 	{
 	  error ("invalid option for -mfloat-gprs: '%s'", arg);
@@ -4267,19 +4222,19 @@  rs6000_handle_option (size_t code, const
 
     case OPT_mlong_double_:
       rs6000_explicit_options.long_double = true;
-      rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
+      rs6000_opts.long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
       if (value != 64 && value != 128)
 	{
 	  error ("Unknown switch -mlong-double-%s", arg);
-	  rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
+	  rs6000_opts.long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
 	  return false;
 	}
       else
-	rs6000_long_double_type_size = value;
+	rs6000_opts.long_double_type_size = value;
       break;
 
     case OPT_msched_costly_dep_:
-      rs6000_sched_costly_dep_str = arg;
+      rs6000_opts_str.sched_costly_dep_str = arg;
       break;
 
     case OPT_malign_:
@@ -4293,10 +4248,10 @@  rs6000_handle_option (size_t code, const
 	  if (DEFAULT_ABI == ABI_DARWIN && TARGET_64BIT)
 	    warning (0, "-malign-power is not supported for 64-bit Darwin;"
 		     " it is incompatible with the installed C and C++ libraries");
-	  rs6000_alignment_flags = MASK_ALIGN_POWER;
+	  rs6000_opts.alignment_flags = MASK_ALIGN_POWER;
 	}
       else if (! strcmp (arg, "natural"))
-	rs6000_alignment_flags = MASK_ALIGN_NATURAL;
+	rs6000_opts.alignment_flags = MASK_ALIGN_NATURAL;
       else
 	{
 	  error ("unknown -malign-XXXXX option specified: '%s'", arg);
@@ -4359,11 +4314,11 @@  rs6000_handle_option (size_t code, const
       }
 
     case OPT_mrecip:
-      rs6000_recip_name = (value) ? "default" : "none";
+      rs6000_opts_str.recip_name = (value) ? "default" : "none";
       break;
 
     case OPT_mrecip_:
-      rs6000_recip_name = arg;
+      rs6000_opts_str.recip_name = arg;
       break;
     }
   return true;
@@ -4410,7 +4365,7 @@  rs6000_file_start (void)
 	}
 
 #ifdef USING_ELFOS_H
-      switch (rs6000_sdata)
+      switch (rs6000_opts.sdata)
 	{
 	case SDATA_NONE: fprintf (file, "%s -msdata=none", start); start = ""; break;
 	case SDATA_DATA: fprintf (file, "%s -msdata=data", start); start = ""; break;
@@ -4418,7 +4373,7 @@  rs6000_file_start (void)
 	case SDATA_EABI: fprintf (file, "%s -msdata=eabi", start); start = ""; break;
 	}
 
-      if (rs6000_sdata && g_switch_value)
+      if (rs6000_opts.sdata && g_switch_value)
 	{
 	  fprintf (file, "%s -G %d", start,
 		   g_switch_value);
@@ -5381,7 +5336,7 @@  small_data_operand (rtx op ATTRIBUTE_UNU
 #if TARGET_ELF
   rtx sym_ref;
 
-  if (rs6000_sdata == SDATA_NONE || rs6000_sdata == SDATA_DATA)
+  if (rs6000_opts.sdata == SDATA_NONE || rs6000_opts.sdata == SDATA_DATA)
     return 0;
 
   if (DEFAULT_ABI != ABI_V4)
@@ -6059,7 +6014,7 @@  rs6000_legitimize_tls_address (rtx addr,
   rtx dest, insn;
 
   dest = gen_reg_rtx (Pmode);
-  if (model == TLS_MODEL_LOCAL_EXEC && rs6000_tls_size == 16)
+  if (model == TLS_MODEL_LOCAL_EXEC && rs6000_opts.tls_size == 16)
     {
       rtx tlsreg;
 
@@ -6075,7 +6030,7 @@  rs6000_legitimize_tls_address (rtx addr,
 	}
       emit_insn (insn);
     }
-  else if (model == TLS_MODEL_LOCAL_EXEC && rs6000_tls_size == 32)
+  else if (model == TLS_MODEL_LOCAL_EXEC && rs6000_opts.tls_size == 32)
     {
       rtx tlsreg, tmp;
 
@@ -6176,14 +6131,14 @@  rs6000_legitimize_tls_address (rtx addr,
 	    use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn),
 		     pic_offset_table_rtx);
 
-	  if (rs6000_tls_size == 16)
+	  if (rs6000_opts.tls_size == 16)
 	    {
 	      if (TARGET_64BIT)
 		insn = gen_tls_dtprel_64 (dest, tmp1, addr);
 	      else
 		insn = gen_tls_dtprel_32 (dest, tmp1, addr);
 	    }
-	  else if (rs6000_tls_size == 32)
+	  else if (rs6000_opts.tls_size == 32)
 	    {
 	      tmp2 = gen_reg_rtx (Pmode);
 	      if (TARGET_64BIT)
@@ -7548,7 +7503,7 @@  rs6000_return_in_memory (const_tree type
 {
   /* For the Darwin64 ABI, test if we can fit the return value in regs.  */
   if (TARGET_MACHO
-      && rs6000_darwin64_abi
+      && rs6000_opts.darwin64_abi
       && TREE_CODE (type) == RECORD_TYPE
       && int_size_in_bytes (type) > 0)
     {
@@ -7762,7 +7717,7 @@  function_arg_boundary (enum machine_mode
 	       && int_size_in_bytes (type) >= 16))
     return 128;
   else if (TARGET_MACHO
- 	   && rs6000_darwin64_abi
+ 	   && rs6000_opts.darwin64_abi
  	   && mode == BLKmode
 	   && type && TYPE_ALIGN (type) > 64)
     return 128;
@@ -7946,7 +7901,7 @@  rs6000_darwin64_record_arg_advance_recur
 static int
 rs6000_darwin64_struct_check_p (enum machine_mode mode, const_tree type)
 {
-  return rs6000_darwin64_abi
+  return rs6000_opts.darwin64_abi
 	 && ((mode == BLKmode 
 	      && TREE_CODE (type) == RECORD_TYPE 
 	      && int_size_in_bytes (type) > 0)
@@ -9286,7 +9241,7 @@  rs6000_gimplify_va_arg (tree valist, tre
      We can return a simplifed answer, since we know there's no offset to add.  */
 
   if (TARGET_MACHO
-      && rs6000_darwin64_abi 
+      && rs6000_opts.darwin64_abi 
       && integer_zerop (TYPE_SIZE (type)))
     {
       unsigned HOST_WIDE_INT align, boundary;
@@ -12773,7 +12728,7 @@  altivec_init_builtins (void)
   def_builtin (MASK_ALTIVEC, "__builtin_vec_stvebx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEBX);
   def_builtin (MASK_ALTIVEC, "__builtin_vec_stvehx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEHX);
 
-  if (rs6000_cpu == PROCESSOR_CELL)
+  if (rs6000_opts.cpu == PROCESSOR_CELL)
     {
       def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvlx",  v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVLX);
       def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvlxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVLXL);
@@ -15245,8 +15200,9 @@  rs6000_output_function_entry (FILE *file
 /* Print an operand.  Recognize special options, documented below.  */
 
 #if TARGET_ELF
-#define SMALL_DATA_RELOC ((rs6000_sdata == SDATA_EABI) ? "sda21" : "sdarel")
-#define SMALL_DATA_REG ((rs6000_sdata == SDATA_EABI) ? 0 : 13)
+#define SMALL_DATA_RELOC \
+  ((rs6000_opts.sdata == SDATA_EABI) ? "sda21" : "sdarel")
+#define SMALL_DATA_REG ((rs6000_opts.sdata == SDATA_EABI) ? 0 : 13)
 #else
 #define SMALL_DATA_RELOC "sda21"
 #define SMALL_DATA_REG 0
@@ -16589,7 +16545,7 @@  output_cbranch (rtx op, const char *labe
 	 assume not taken for branches that are very close to 50% as a
 	 mispredicted taken branch is more expensive than a
 	 mispredicted not-taken branch.  */
-      if (rs6000_always_hint
+      if (rs6000_opts.always_hint
 	  || (abs (prob) > REG_BR_PROB_BASE / 100 * 48
 	      && br_prob_note_reliable_p (note)))
 	{
@@ -20617,9 +20573,9 @@  rs6000_emit_epilogue (int sibcall)
   using_load_multiple = strategy & SAVRES_MULTIPLE;
   restoring_FPRs_inline = strategy & SAVRES_INLINE_FPRS;
   restoring_GPRs_inline = strategy & SAVRES_INLINE_GPRS;
-  using_mtcr_multiple = (rs6000_cpu == PROCESSOR_PPC601
-			 || rs6000_cpu == PROCESSOR_PPC603
-			 || rs6000_cpu == PROCESSOR_PPC750
+  using_mtcr_multiple = (rs6000_opts.cpu == PROCESSOR_PPC601
+			 || rs6000_opts.cpu == PROCESSOR_PPC603
+			 || rs6000_opts.cpu == PROCESSOR_PPC750
 			 || optimize_size);
   /* Restore via the backchain when we have a large frame, since this
      is more efficient than an addis, addi pair.  The second condition
@@ -21395,7 +21351,7 @@  rs6000_output_function_epilogue (FILE *f
      System V.4 Powerpc's (and the embedded ABI derived from it) use a
      different traceback table.  */
   if (DEFAULT_ABI == ABI_AIX && ! flag_inhibit_size_directive
-      && rs6000_traceback != traceback_none && !cfun->is_thunk)
+      && rs6000_opts.traceback != traceback_none && !cfun->is_thunk)
     {
       const char *fname = NULL;
       const char *language_string = lang_hooks.name;
@@ -21404,9 +21360,9 @@  rs6000_output_function_epilogue (FILE *f
       int optional_tbtab;
       rs6000_stack_t *info = rs6000_stack_info ();
 
-      if (rs6000_traceback == traceback_full)
+      if (rs6000_opts.traceback == traceback_full)
 	optional_tbtab = 1;
-      else if (rs6000_traceback == traceback_part)
+      else if (rs6000_opts.traceback == traceback_part)
 	optional_tbtab = 0;
       else
 	optional_tbtab = !optimize_size && !TARGET_ELF;
@@ -22557,7 +22513,7 @@  rs6000_variable_issue_1 (rtx insn, int m
   if (recog_memoized (insn) < 0)
     return more;
 
-  if (rs6000_sched_groups)
+  if (rs6000_opts.sched_groups)
     {
       if (is_microcoded_insn (insn))
         cached_can_issue_more = 0;
@@ -22604,7 +22560,7 @@  rs6000_adjust_cost (rtx insn, rtx link, 
 	   some cycles later.  */
 
 	/* Separate a load from a narrower, dependent store.  */
-	if (rs6000_sched_groups
+	if (rs6000_opts.sched_groups
 	    && GET_CODE (PATTERN (insn)) == SET
 	    && GET_CODE (PATTERN (dep_insn)) == SET
 	    && GET_CODE (XEXP (PATTERN (insn), 1)) == MEM
@@ -22664,7 +22620,7 @@  rs6000_adjust_cost (rtx insn, rtx link, 
           case TYPE_FPSTORE:
           case TYPE_FPSTORE_U:
           case TYPE_FPSTORE_UX:
-            if ((rs6000_cpu == PROCESSOR_POWER6)
+            if ((rs6000_opts.cpu == PROCESSOR_POWER6)
                 && recog_memoized (dep_insn)
                 && (INSN_CODE (dep_insn) >= 0))
               {
@@ -22751,7 +22707,7 @@  rs6000_adjust_cost (rtx insn, rtx link, 
           case TYPE_LOAD_EXT:
           case TYPE_LOAD_EXT_U:
           case TYPE_LOAD_EXT_UX:
-            if ((rs6000_cpu == PROCESSOR_POWER6)
+            if ((rs6000_opts.cpu == PROCESSOR_POWER6)
                 && recog_memoized (dep_insn)
                 && (INSN_CODE (dep_insn) >= 0))
               {
@@ -22828,7 +22784,7 @@  rs6000_adjust_cost (rtx insn, rtx link, 
             break;
 
           case TYPE_FPLOAD:
-            if ((rs6000_cpu == PROCESSOR_POWER6)
+            if ((rs6000_opts.cpu == PROCESSOR_POWER6)
                 && recog_memoized (dep_insn)
                 && (INSN_CODE (dep_insn) >= 0)
                 && (get_attr_type (dep_insn) == TYPE_MFFGPR))
@@ -22845,7 +22801,7 @@  rs6000_adjust_cost (rtx insn, rtx link, 
     case REG_DEP_OUTPUT:
       /* Output dependency; DEP_INSN writes a register that INSN writes some
 	 cycles later.  */
-      if ((rs6000_cpu == PROCESSOR_POWER6)
+      if ((rs6000_opts.cpu == PROCESSOR_POWER6)
           && recog_memoized (dep_insn)
           && (INSN_CODE (dep_insn) >= 0))
         {
@@ -22920,7 +22876,7 @@  is_microcoded_insn (rtx insn)
   if (rs6000_cpu_attr == CPU_CELL)
     return get_attr_cell_micro (insn) == CELL_MICRO_ALWAYS;
 
-  if (rs6000_sched_groups)
+  if (rs6000_opts.sched_groups)
     {
       enum attr_type type = get_attr_type (insn);
       if (type == TYPE_LOAD_EXT_U
@@ -22945,7 +22901,7 @@  is_cracked_insn (rtx insn)
       || GET_CODE (PATTERN (insn)) == CLOBBER)
     return false;
 
-  if (rs6000_sched_groups)
+  if (rs6000_opts.sched_groups)
     {
       enum attr_type type = get_attr_type (insn);
       if (type == TYPE_LOAD_U || type == TYPE_STORE_U
@@ -22973,7 +22929,7 @@  is_branch_slot_insn (rtx insn)
       || GET_CODE (PATTERN (insn)) == CLOBBER)
     return false;
 
-  if (rs6000_sched_groups)
+  if (rs6000_opts.sched_groups)
     {
       enum attr_type type = get_attr_type (insn);
       if (type == TYPE_BRANCH || type == TYPE_JMPREG)
@@ -23110,7 +23066,7 @@  rs6000_adjust_priority (rtx insn ATTRIBU
 	return (priority + 1);
     }
 
-  if (rs6000_cpu == PROCESSOR_POWER6
+  if (rs6000_opts.cpu == PROCESSOR_POWER6
       && ((load_store_pendulum == -2 && is_load_insn (insn))
           || (load_store_pendulum == 2 && is_store_insn (insn))))
     /* Attach highest priority to insn if the scheduler has just issued two
@@ -23370,25 +23326,25 @@  rs6000_is_costly_dependence (dep_t dep, 
   /* If the flag is not enabled - no dependence is considered costly;
      allow all dependent insns in the same group.
      This is the most aggressive option.  */
-  if (rs6000_sched_costly_dep == no_dep_costly)
+  if (rs6000_opts.sched_costly_dep == no_dep_costly)
     return false;
 
   /* If the flag is set to 1 - a dependence is always considered costly;
      do not allow dependent instructions in the same group.
      This is the most conservative option.  */
-  if (rs6000_sched_costly_dep == all_deps_costly)
+  if (rs6000_opts.sched_costly_dep == all_deps_costly)
     return true;
 
   insn = DEP_PRO (dep);
   next = DEP_CON (dep);
 
-  if (rs6000_sched_costly_dep == store_to_load_dep_costly
+  if (rs6000_opts.sched_costly_dep == store_to_load_dep_costly
       && is_load_insn (next)
       && is_store_insn (insn))
     /* Prevent load after store in the same group.  */
     return true;
 
-  if (rs6000_sched_costly_dep == true_store_to_load_dep_costly
+  if (rs6000_opts.sched_costly_dep == true_store_to_load_dep_costly
       && is_load_insn (next)
       && is_store_insn (insn)
       && DEP_TYPE (dep) == REG_DEP_TRUE)
@@ -23398,8 +23354,8 @@  rs6000_is_costly_dependence (dep_t dep, 
 
   /* The flag is set to X; dependences with latency >= X are considered costly,
      and will not be scheduled in the same group.  */
-  if (rs6000_sched_costly_dep <= max_dep_latency
-      && ((cost - distance) >= (int)rs6000_sched_costly_dep))
+  if (rs6000_opts.sched_costly_dep <= max_dep_latency
+      && ((cost - distance) >= (int)rs6000_opts.sched_costly_dep))
     return true;
 
   return false;
@@ -23459,7 +23415,7 @@  rs6000_sched_reorder (FILE *dump ATTRIBU
       }
   }
 
-  if (rs6000_cpu == PROCESSOR_POWER6)
+  if (rs6000_opts.cpu == PROCESSOR_POWER6)
     load_store_pendulum = 0;
 
   return rs6000_issue_rate ();
@@ -23514,7 +23470,7 @@  rs6000_sched_reorder2 (FILE *dump, int s
              of the machine.  Those instructions are currently unaccounted
              for to help minimize compile time overhead of this code.
    */
-  if (rs6000_cpu == PROCESSOR_POWER6 && last_scheduled_insn)
+  if (rs6000_opts.cpu == PROCESSOR_POWER6 && last_scheduled_insn)
     {
       int pos;
       int i;
@@ -23716,7 +23672,7 @@  insn_must_be_first_in_group (rtx insn)
       || GET_CODE (PATTERN (insn)) == CLOBBER)
     return false;
 
-  switch (rs6000_cpu)
+  switch (rs6000_opts.cpu)
     {
     case PROCESSOR_POWER5:
       if (is_cracked_insn (insn))
@@ -23725,7 +23681,7 @@  insn_must_be_first_in_group (rtx insn)
       if (is_microcoded_insn (insn))
         return true;
 
-      if (!rs6000_sched_groups)
+      if (!rs6000_opts.sched_groups)
         return false;
 
       type = get_attr_type (insn);
@@ -23847,7 +23803,7 @@  insn_must_be_last_in_group (rtx insn)
       || GET_CODE (PATTERN (insn)) == CLOBBER)
     return false;
 
-  switch (rs6000_cpu) {
+  switch (rs6000_opts.cpu) {
   case PROCESSOR_POWER4:
   case PROCESSOR_POWER5:
     if (is_microcoded_insn (insn))
@@ -23971,7 +23927,7 @@  force_new_group (int sched_verbose, FILE
   if (next_insn == NULL_RTX || DEBUG_INSN_P (next_insn))
     return can_issue_more;
 
-  if (rs6000_sched_insert_nops > sched_finish_regroup_exact)
+  if (rs6000_opts.insert_nops > sched_finish_regroup_exact)
     return can_issue_more;
 
   force = is_costly_group (group_insns, next_insn);
@@ -23982,7 +23938,7 @@  force_new_group (int sched_verbose, FILE
     fprintf (dump,"force: group count = %d, can_issue_more = %d\n",
 	     *group_count ,can_issue_more);
 
-  if (rs6000_sched_insert_nops == sched_finish_regroup_exact)
+  if (rs6000_opts.insert_nops == sched_finish_regroup_exact)
     {
       if (*group_end)
 	can_issue_more = 0;
@@ -24006,9 +23962,9 @@  force_new_group (int sched_verbose, FILE
       return 0;
     }
 
-  if (rs6000_sched_insert_nops < sched_finish_regroup_exact)
+  if (rs6000_opts.insert_nops < sched_finish_regroup_exact)
     {
-      int n_nops = rs6000_sched_insert_nops;
+      int n_nops = rs6000_opts.insert_nops;
 
       /* Nops can't be issued from the branch slot, so the effective
 	 issue_rate for nops is 'issue_rate - 1'.  */
@@ -24207,7 +24163,7 @@  pad_groups (FILE *dump, int sched_verbos
 	     force group termination, pad the group with nops to force group
 	     termination.  */
 	  if (can_issue_more
-	      && (rs6000_sched_insert_nops == sched_finish_pad_groups)
+	      && (rs6000_opts.insert_nops == sched_finish_pad_groups)
 	      && !insn_terminates_group_p (insn, current_group)
 	      && !insn_terminates_group_p (next_insn, previous_group))
 	    {
@@ -24255,16 +24211,16 @@  rs6000_sched_finish (FILE *dump, int sch
   if (sched_verbose)
     fprintf (dump, "=== Finishing schedule.\n");
 
-  if (reload_completed && rs6000_sched_groups)
+  if (reload_completed && rs6000_opts.sched_groups)
     {
       /* Do not run sched_finish hook when selective scheduling enabled.  */
       if (sel_sched_p ())
 	return;
 
-      if (rs6000_sched_insert_nops == sched_finish_none)
+      if (rs6000_opts.insert_nops == sched_finish_none)
 	return;
 
-      if (rs6000_sched_insert_nops == sched_finish_pad_groups)
+      if (rs6000_opts.insert_nops == sched_finish_pad_groups)
 	n_groups = pad_groups (dump, sched_verbose,
 			       current_sched_info->prev_head,
 			       current_sched_info->next_tail);
@@ -24802,7 +24758,7 @@  compare_section_name (const char *sectio
 bool
 rs6000_elf_in_small_data_p (const_tree decl)
 {
-  if (rs6000_sdata == SDATA_NONE)
+  if (rs6000_opts.sdata == SDATA_NONE)
     return false;
 
   /* We want to merge strings, so we never consider them small data.  */
@@ -24834,7 +24790,7 @@  rs6000_elf_in_small_data_p (const_tree d
 	  && size <= g_switch_value
 	  /* If it's not public, and we're not going to reference it there,
 	     there's no need to put it in the small data section.  */
-	  && (rs6000_sdata != SDATA_DATA || TREE_PUBLIC (decl)))
+	  && (rs6000_opts.sdata != SDATA_DATA || TREE_PUBLIC (decl)))
 	return true;
     }
 
@@ -26102,7 +26058,7 @@  rs6000_register_move_cost (enum machine_
 
       /* Power6 has slower LR/CTR moves so make them more expensive than
 	 memory in order to bias spills to memory .*/
-      else if (rs6000_cpu == PROCESSOR_POWER6
+      else if (rs6000_opts.cpu == PROCESSOR_POWER6
 	       && reg_classes_intersect_p (from, LINK_OR_CTR_REGS))
         ret = 6 * hard_regno_nregs[0][mode];
 
@@ -26993,7 +26949,7 @@  rs6000_vector_mode_supported_p (enum mac
 static const char *
 invalid_arg_for_unprototyped_fn (const_tree typelist, const_tree funcdecl, const_tree val)
 {
-  return (!rs6000_darwin64_abi
+  return (!rs6000_opts.darwin64_abi
 	  && typelist == 0
           && TREE_CODE (TREE_TYPE (val)) == VECTOR_TYPE
           && (funcdecl == NULL_TREE
Index: gcc/config/rs6000/aix52.h
===================================================================
--- gcc/config/rs6000/aix52.h	(revision 165044)
+++ gcc/config/rs6000/aix52.h	(working copy)
@@ -38,7 +38,7 @@  do {									\
     }									\
   if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128)			\
     {									\
-      rs6000_long_double_type_size = 64;				\
+      rs6000_opts.long_double_type_size = 64;				\
       if (rs6000_explicit_options.long_double)				\
 	warning (0, "soft-float and long-double-128 are incompatible");	\
     }									\
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 165044)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -61,7 +61,7 @@ 
 
 /* If configured for PPC405, support PPC405CR Erratum77.  */
 #ifdef CONFIG_PPC405CR
-#define PPC405_ERRATUM77 (rs6000_cpu == PROCESSOR_PPC405)
+#define PPC405_ERRATUM77 (rs6000_opts.cpu == PROCESSOR_PPC405)
 #else
 #define PPC405_ERRATUM77 0
 #endif
@@ -381,11 +381,6 @@  enum processor_type
 #define TARGET_SIMPLE_FPU   0
 #define TARGET_XILINX_FPU   0
 
-extern enum processor_type rs6000_cpu;
-
-/* Recast the processor type to the cpu attribute.  */
-#define rs6000_cpu_attr ((enum attr_cpu)rs6000_cpu)
-
 /* Define generic processor types based upon current deployment.  */
 #define PROCESSOR_COMMON    PROCESSOR_PPC601
 #define PROCESSOR_POWER     PROCESSOR_RIOS1
@@ -406,8 +401,6 @@  enum fpu_type_t
 	FPU_DF_FULL		/* Full Double Single Precision FPU */
 };
 
-extern enum fpu_type_t fpu_type;
-
 /* Specify the dialect of assembler to use.  New mnemonics is dialect one
    and the old mnemonics are dialect zero.  */
 #define ASSEMBLER_DIALECT (TARGET_NEW_MNEMONICS ? 1 : 0)
@@ -449,32 +442,22 @@  struct rs6000_cpu_select
 extern struct rs6000_cpu_select rs6000_select[];
 
 /* Debug support */
-extern const char *rs6000_debug_name;	/* Name for -mdebug-xxxx option */
-extern int rs6000_debug_stack;		/* debug stack applications */
-extern int rs6000_debug_arg;		/* debug argument handling */
-extern int rs6000_debug_reg;		/* debug register handling */
-extern int rs6000_debug_addr;		/* debug memory addressing */
-extern int rs6000_debug_cost;		/* debug rtx_costs */
-
-#define	TARGET_DEBUG_STACK	rs6000_debug_stack
-#define	TARGET_DEBUG_ARG	rs6000_debug_arg
-#define TARGET_DEBUG_REG	rs6000_debug_reg
-#define TARGET_DEBUG_ADDR	rs6000_debug_addr
-#define TARGET_DEBUG_COST	rs6000_debug_cost
-
-extern const char *rs6000_traceback_name; /* Type of traceback table.  */
-
-/* These are separate from target_flags because we've run out of bits
-   there.  */
-extern int rs6000_long_double_type_size;
-extern int rs6000_ieeequad;
-extern int rs6000_altivec_abi;
-extern int rs6000_spe_abi;
-extern int rs6000_spe;
-extern int rs6000_float_gprs;
-extern int rs6000_alignment_flags;
-extern const char *rs6000_sched_insert_nops_str;
-extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
+#define MASK_DEBUG_STACK	0x01	/* debug stack applications */
+#define	MASK_DEBUG_ARG		0x02	/* debug argument handling */
+#define MASK_DEBUG_REG		0x04	/* debug register handling */
+#define MASK_DEBUG_ADDR		0x08	/* debug memory addressing */
+#define MASK_DEBUG_COST		0x10	/* debug rtx codes */
+#define MASK_DEBUG_ALL		(MASK_DEBUG_STACK \
+				 | MASK_DEBUG_ARG \
+				 | MASK_DEBUG_REG \
+				 | MASK_DEBUG_ADDR \
+				 | MASK_DEBUG_COST)
+
+#define	TARGET_DEBUG_STACK	(rs6000_opts.debug & MASK_DEBUG_STACK)
+#define	TARGET_DEBUG_ARG	(rs6000_opts.debug & MASK_DEBUG_ARG)
+#define TARGET_DEBUG_REG	(rs6000_opts.debug & MASK_DEBUG_REG)
+#define TARGET_DEBUG_ADDR	(rs6000_opts.debug & MASK_DEBUG_ADDR)
+#define TARGET_DEBUG_COST	(rs6000_opts.debug & MASK_DEBUG_COST)
 
 /* Describe which vector unit to use for a given machine mode.  */
 enum rs6000_vector {
@@ -535,21 +518,21 @@  extern int rs6000_vector_align[];
    ALIGN_NATURAL doubleword-aligns FP doubles (align to object size).
 
    Override the macro definitions when compiling libobjc to avoid undefined
-   reference to rs6000_alignment_flags due to library's use of GCC alignment
-   macros which use the macros below.  */
+   reference to rs6000_opts.alignment_flags due to library's use of GCC
+   alignment macros which use the macros below.  */
 
 #ifndef IN_TARGET_LIBS
 #define MASK_ALIGN_POWER   0x00000000
 #define MASK_ALIGN_NATURAL 0x00000001
-#define TARGET_ALIGN_NATURAL (rs6000_alignment_flags & MASK_ALIGN_NATURAL)
+#define TARGET_ALIGN_NATURAL (rs6000_opts.alignment_flags & MASK_ALIGN_NATURAL)
 #else
 #define TARGET_ALIGN_NATURAL 0
 #endif
 
-#define TARGET_LONG_DOUBLE_128 (rs6000_long_double_type_size == 128)
-#define TARGET_IEEEQUAD rs6000_ieeequad
-#define TARGET_ALTIVEC_ABI rs6000_altivec_abi
-#define TARGET_LDBRX (TARGET_POPCNTD || rs6000_cpu == PROCESSOR_CELL)
+#define TARGET_LONG_DOUBLE_128 (rs6000_opts.long_double_type_size == 128)
+#define TARGET_IEEEQUAD rs6000_opts.ieeequad
+#define TARGET_ALTIVEC_ABI rs6000_opts.altivec_abi
+#define TARGET_LDBRX (TARGET_POPCNTD || rs6000_opts.cpu == PROCESSOR_CELL)
 
 #define TARGET_SPE_ABI 0
 #define TARGET_SPE 0
@@ -748,7 +731,7 @@  extern unsigned char rs6000_recip_bits[]
 /* A C expression for the size in bits of the type `long double' on
    the target machine.  If you don't define this, the default is two
    words.  */
-#define LONG_DOUBLE_TYPE_SIZE rs6000_long_double_type_size
+#define LONG_DOUBLE_TYPE_SIZE rs6000_opts.long_double_type_size
 
 /* Define this to set long double type size to use in libgcc2.c, which can
    not depend on target_flags.  */
@@ -1476,8 +1459,6 @@  enum rs6000_abi {
   ABI_DARWIN			/* Apple's Darwin (OS X kernel) */
 };
 
-extern enum rs6000_abi rs6000_current_abi;	/* available for use by subtarget */
-
 /* Define this if pushing a word on the stack
    makes the stack pointer a smaller address.  */
 #define STACK_GROWS_DOWNWARD
@@ -2422,6 +2403,116 @@  extern char rs6000_reg_names[][8];	/* re
 /* General flags.  */
 extern int frame_pointer_needed;
 
+/* Type of traceback to use.  */
+enum rs6000_traceback {
+  traceback_default = 0,
+  traceback_none,
+  traceback_part,
+  traceback_full
+};
+
+/* Small data support types.  */
+enum rs6000_sdata_type {
+  SDATA_NONE,			/* No small data support.  */
+  SDATA_DATA,			/* Just put data in .sbss/.sdata, don't use relocs.  */
+  SDATA_SYSV,			/* Use r13 to point to .sdata/.sbss.  */
+  SDATA_EABI			/* Use r13 like above, r2 points to .sdata2/.sbss2.  */
+};
+
+/* Option strings that are processed in rs6000_handle_option and then dealt
+   with in rs6000_override_options.  Don't use GTY(()) for these, since
+   the strings are not allocated.  */
+
+struct rs6000_option_strings {
+  const char *sched_costly_dep_str;
+  const char *sched_insert_nops_str;
+  const char *abi_name;
+  const char *sdata_name;
+  const char *debug_name;
+  const char *recip_name;
+  const char *tls_size_string;
+};
+
+extern struct rs6000_option_strings rs6000_opts_str;
+
+/* Target specific variables, flags, etc.  These are all grouped in a structure
+   so that it can be copied and restored if functions are compiled with
+   different target options.  */
+
+typedef struct GTY(()) rs6000_options
+{
+  /* cpu we are generating code for */
+  enum processor_type cpu;
+
+  /* whether to schedule nops */
+  enum rs6000_nop_insertion insert_nops;
+
+  /* Code model for 64-bit linux.  */
+  enum rs6000_cmodel cmodel;
+
+  /* Support for -msched-costly-dep option.  */
+  enum rs6000_dependence_cost sched_costly_dep;
+
+  /* ABI enumeration available for subtarget to use.  */
+  enum rs6000_abi abi;
+
+  /* Type of traceback to use.  */
+  enum rs6000_traceback traceback;
+
+  /* Small data support types.  */
+  enum rs6000_sdata_type sdata;
+
+  /* Control alignment for fields within structures.  */
+  /* String from -malign-XXXXX.  */
+  int alignment_flags;
+
+  /* Size of long double.  */
+  int long_double_type_size;
+
+  /* IEEE quad extended precision long double. */
+  int ieeequad;
+
+  /* Nonzero to use AltiVec ABI.  */
+  int altivec_abi;
+
+  /* Nonzero if we want SPE ABI extensions.  */
+  int spe_abi;
+
+  /* Nonzero if we want SPE SIMD instructions.  */
+  int spe;
+
+  /* Nonzero if floating point operations are done in the GPRs.  */
+  int float_gprs;
+
+  /* Always emit branch hint bits.  */
+  int always_hint;
+
+  /* Schedule instructions for group formation.  */
+  int sched_groups;
+
+  /* Align branch targets.  */
+  int align_branch_targets;
+
+  /* Nonzero if we want Darwin's struct-by-value-in-regs ABI.  */
+  int darwin64_abi;
+
+  /* Bit size of immediate TLS offsets and string from which it is decoded.  */
+  int tls_size;
+
+  /* Various debug flags.  */
+  unsigned int debug;
+
+  /* reciprocl divide/square root estimate options.  */
+  unsigned int recip_control;
+
+} rs6000_options_t;
+
+extern GTY(()) rs6000_options_t rs6000_opts;
+
+/* Recast the processor type to the cpu attribute.  */
+#define rs6000_cpu_attr ((enum attr_cpu)rs6000_opts.cpu)
+
+
 /* Classification of the builtin functions to properly set the declaration tree
    flags.  */
 enum rs6000_btc
Index: gcc/config/rs6000/altivec.md
===================================================================
--- gcc/config/rs6000/altivec.md	(revision 165044)
+++ gcc/config/rs6000/altivec.md	(working copy)
@@ -2419,7 +2419,7 @@  (define_insn "altivec_lvlx"
   [(set (match_operand:V16QI 0 "register_operand" "=v")
         (unspec:V16QI [(match_operand 1 "memory_operand" "Z")] 
 		      UNSPEC_LVLX))]
-  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
+  "TARGET_ALTIVEC && rs6000_opts.cpu == PROCESSOR_CELL"
   "lvlx %0,%y1"
   [(set_attr "type" "vecload")])
 
@@ -2427,7 +2427,7 @@  (define_insn "altivec_lvlxl"
   [(set (match_operand:V16QI 0 "register_operand" "=v")
         (unspec:V16QI [(match_operand 1 "memory_operand" "Z")] 
 		      UNSPEC_LVLXL))]
-  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
+  "TARGET_ALTIVEC && rs6000_opts.cpu == PROCESSOR_CELL"
   "lvlxl %0,%y1"
   [(set_attr "type" "vecload")])
 
@@ -2435,7 +2435,7 @@  (define_insn "altivec_lvrx"
   [(set (match_operand:V16QI 0 "register_operand" "=v")
         (unspec:V16QI [(match_operand 1 "memory_operand" "Z")] 
 		      UNSPEC_LVRX))]
-  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
+  "TARGET_ALTIVEC && rs6000_opts.cpu == PROCESSOR_CELL"
   "lvrx %0,%y1"
   [(set_attr "type" "vecload")])
 
@@ -2443,7 +2443,7 @@  (define_insn "altivec_lvrxl"
   [(set (match_operand:V16QI 0 "register_operand" "=v")
         (unspec:V16QI [(match_operand 1 "memory_operand" "Z")] 
 		      UNSPEC_LVRXL))]
-  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
+  "TARGET_ALTIVEC && rs6000_opts.cpu == PROCESSOR_CELL"
   "lvrxl %0,%y1"
   [(set_attr "type" "vecload")])
 
@@ -2452,7 +2452,7 @@  (define_insn "altivec_stvlx"
     [(set (match_operand:V4SI 0 "memory_operand" "=Z")
 	  (match_operand:V4SI 1 "register_operand" "v"))
      (unspec [(const_int 0)] UNSPEC_STVLX)])]
-  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
+  "TARGET_ALTIVEC && rs6000_opts.cpu == PROCESSOR_CELL"
   "stvlx %1,%y0"
   [(set_attr "type" "vecstore")])
 
@@ -2461,7 +2461,7 @@  (define_insn "altivec_stvlxl"
     [(set (match_operand:V4SI 0 "memory_operand" "=Z")
 	  (match_operand:V4SI 1 "register_operand" "v"))
      (unspec [(const_int 0)] UNSPEC_STVLXL)])]
-  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
+  "TARGET_ALTIVEC && rs6000_opts.cpu == PROCESSOR_CELL"
   "stvlxl %1,%y0"
   [(set_attr "type" "vecstore")])
 
@@ -2470,7 +2470,7 @@  (define_insn "altivec_stvrx"
     [(set (match_operand:V4SI 0 "memory_operand" "=Z")
 	  (match_operand:V4SI 1 "register_operand" "v"))
      (unspec [(const_int 0)] UNSPEC_STVRX)])]
-  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
+  "TARGET_ALTIVEC && rs6000_opts.cpu == PROCESSOR_CELL"
   "stvrx %1,%y0"
   [(set_attr "type" "vecstore")])
 
@@ -2479,7 +2479,7 @@  (define_insn "altivec_stvrxl"
     [(set (match_operand:V4SI 0 "memory_operand" "=Z")
 	  (match_operand:V4SI 1 "register_operand" "v"))
      (unspec [(const_int 0)] UNSPEC_STVRXL)])]
-  "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
+  "TARGET_ALTIVEC && rs6000_opts.cpu == PROCESSOR_CELL"
   "stvrxl %1,%y0"
   [(set_attr "type" "vecstore")])
 
Index: gcc/config/rs6000/aix61.h
===================================================================
--- gcc/config/rs6000/aix61.h	(revision 165044)
+++ gcc/config/rs6000/aix61.h	(working copy)
@@ -38,7 +38,7 @@  do {									\
     }									\
   if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128)			\
     {									\
-      rs6000_long_double_type_size = 64;				\
+      rs6000_opts.long_double_type_size = 64;				\
       if (rs6000_explicit_options.long_double)				\
 	warning (0, "soft-float and long-double-128 are incompatible");	\
     }									\
Index: gcc/config/rs6000/eabispe.h
===================================================================
--- gcc/config/rs6000/eabispe.h	(revision 165044)
+++ gcc/config/rs6000/eabispe.h	(working copy)
@@ -30,13 +30,13 @@ 
 #undef  SUBSUBTARGET_OVERRIDE_OPTIONS
 #define SUBSUBTARGET_OVERRIDE_OPTIONS \
   if (rs6000_select[1].string == NULL) \
-    rs6000_cpu = PROCESSOR_PPC8540; \
+    rs6000_opts.cpu = PROCESSOR_PPC8540; \
   if (!rs6000_explicit_options.spe_abi) \
-    rs6000_spe_abi = 1; \
+    rs6000_opts.spe_abi = 1; \
   if (!rs6000_explicit_options.float_gprs) \
-    rs6000_float_gprs = 1; \
+    rs6000_opts.float_gprs = 1; \
   if (!rs6000_explicit_options.spe) \
-    rs6000_spe = 1; \
+    rs6000_opts.spe = 1; \
   if (target_flags & MASK_64BIT) \
     error ("-m64 not supported in this configuration")
 
Index: gcc/config/rs6000/e500.h
===================================================================
--- gcc/config/rs6000/e500.h	(revision 165044)
+++ gcc/config/rs6000/e500.h	(working copy)
@@ -25,12 +25,12 @@ 
 #undef TARGET_E500_DOUBLE
 #undef CHECK_E500_OPTIONS
 
-#define TARGET_SPE_ABI rs6000_spe_abi
-#define TARGET_SPE rs6000_spe
-#define TARGET_E500 (rs6000_cpu == PROCESSOR_PPC8540)
-#define TARGET_FPRS (rs6000_float_gprs == 0)
-#define TARGET_E500_SINGLE (TARGET_HARD_FLOAT && rs6000_float_gprs == 1)
-#define TARGET_E500_DOUBLE (TARGET_HARD_FLOAT && rs6000_float_gprs == 2)
+#define TARGET_SPE_ABI rs6000_opts.spe_abi
+#define TARGET_SPE rs6000_opts.spe
+#define TARGET_E500 (rs6000_opts.cpu == PROCESSOR_PPC8540)
+#define TARGET_FPRS (rs6000_opts.float_gprs == 0)
+#define TARGET_E500_SINGLE (TARGET_HARD_FLOAT && rs6000_opts.float_gprs == 1)
+#define TARGET_E500_DOUBLE (TARGET_HARD_FLOAT && rs6000_opts.float_gprs == 2)
 #define CHECK_E500_OPTIONS						\
   do {									\
     if (TARGET_E500 || TARGET_SPE || TARGET_SPE_ABI			\
Index: gcc/config/rs6000/e500-double.h
===================================================================
--- gcc/config/rs6000/e500-double.h	(revision 165044)
+++ gcc/config/rs6000/e500-double.h	(working copy)
@@ -21,4 +21,4 @@ 
 #undef  SUB3TARGET_OVERRIDE_OPTIONS
 #define SUB3TARGET_OVERRIDE_OPTIONS \
   if (!rs6000_explicit_options.float_gprs) \
-    rs6000_float_gprs = 2;
+    rs6000_opts.float_gprs = 2;
Index: gcc/config/rs6000/vxworks.h
===================================================================
--- gcc/config/rs6000/vxworks.h	(revision 165044)
+++ gcc/config/rs6000/vxworks.h	(working copy)
@@ -134,9 +134,9 @@  VXWORKS_ADDITIONAL_CPP_SPEC
   do {						\
     if (TARGET_E500)				\
       {						\
-	rs6000_spe = 1;				\
-	rs6000_spe_abi = 1;			\
-	rs6000_float_gprs = 1;			\
+	rs6000_opts.spe = 1;			\
+	rs6000_opts.spe_abi = 1;		\
+	rs6000_opts.float_gprs = 1;		\
       }						\
 						\
   if (!global_options_set.x_g_switch_value)	\
Index: gcc/config/rs6000/sysv4.h
===================================================================
--- gcc/config/rs6000/sysv4.h	(revision 165044)
+++ gcc/config/rs6000/sysv4.h	(working copy)
@@ -32,7 +32,7 @@ 
 #define	TARGET_OBJECT_FORMAT OBJECT_ELF
 
 /* Default ABI to compile code for.  */
-#define DEFAULT_ABI rs6000_current_abi
+#define DEFAULT_ABI rs6000_opts.abi
 
 /* Default ABI to use.  */
 #define RS6000_ABI_NAME "sysv"
@@ -41,16 +41,6 @@ 
 #undef	ASM_DEFAULT_SPEC
 #define	ASM_DEFAULT_SPEC "-mppc"
 
-/* Small data support types.  */
-enum rs6000_sdata_type {
-  SDATA_NONE,			/* No small data support.  */
-  SDATA_DATA,			/* Just put data in .sbss/.sdata, don't use relocs.  */
-  SDATA_SYSV,			/* Use r13 to point to .sdata/.sbss.  */
-  SDATA_EABI			/* Use r13 like above, r2 points to .sdata2/.sbss2.  */
-};
-
-extern enum rs6000_sdata_type rs6000_sdata;
-
 #define	TARGET_TOC		((target_flags & MASK_64BIT)		\
 				 || ((target_flags & (MASK_RELOCATABLE	\
 						      | MASK_MINIMAL_TOC)) \
@@ -70,10 +60,6 @@  extern enum rs6000_sdata_type rs6000_sda
 #define TARGET_SECURE_PLT	secure_plt
 #endif
 
-extern const char *rs6000_abi_name;
-extern const char *rs6000_sdata_name;
-extern const char *rs6000_tls_size_string; /* For -mtls-size= */
-
 #define SDATA_DEFAULT_SIZE 8
 
 /* The macro SUBTARGET_OVERRIDE_OPTIONS is provided for subtargets, to
@@ -84,105 +70,105 @@  do {									\
   if (!global_options_set.x_g_switch_value)				\
     g_switch_value = SDATA_DEFAULT_SIZE;				\
 									\
-  if (rs6000_abi_name == NULL)						\
-    rs6000_abi_name = RS6000_ABI_NAME;					\
+  if (rs6000_opts_str.abi_name == NULL)					\
+    rs6000_opts_str.abi_name = RS6000_ABI_NAME;				\
 									\
-  if (!strcmp (rs6000_abi_name, "sysv"))				\
-    rs6000_current_abi = ABI_V4;					\
-  else if (!strcmp (rs6000_abi_name, "sysv-noeabi"))			\
+  if (!strcmp (rs6000_opts_str.abi_name, "sysv"))			\
+    rs6000_opts.abi = ABI_V4;						\
+  else if (!strcmp (rs6000_opts_str.abi_name, "sysv-noeabi"))		\
     {									\
-      rs6000_current_abi = ABI_V4;					\
+      rs6000_opts.abi = ABI_V4;						\
       target_flags &= ~ MASK_EABI;					\
     }									\
-  else if (!strcmp (rs6000_abi_name, "sysv-eabi")			\
-	   || !strcmp (rs6000_abi_name, "eabi"))			\
+  else if (!strcmp (rs6000_opts_str.abi_name, "sysv-eabi")		\
+	   || !strcmp (rs6000_opts_str.abi_name, "eabi"))		\
     {									\
-      rs6000_current_abi = ABI_V4;					\
+      rs6000_opts.abi = ABI_V4;						\
       target_flags |= MASK_EABI;					\
     }									\
-  else if (!strcmp (rs6000_abi_name, "aixdesc"))			\
-    rs6000_current_abi = ABI_AIX;					\
-  else if (!strcmp (rs6000_abi_name, "freebsd"))			\
-    rs6000_current_abi = ABI_V4;					\
-  else if (!strcmp (rs6000_abi_name, "linux"))				\
+  else if (!strcmp (rs6000_opts_str.abi_name, "aixdesc"))		\
+    rs6000_opts.abi = ABI_AIX;						\
+  else if (!strcmp (rs6000_opts_str.abi_name, "freebsd"))		\
+    rs6000_opts.abi = ABI_V4;						\
+  else if (!strcmp (rs6000_opts_str.abi_name, "linux"))			\
     {									\
       if (TARGET_64BIT)							\
-	rs6000_current_abi = ABI_AIX;					\
+	rs6000_opts.abi = ABI_AIX;					\
       else								\
-	rs6000_current_abi = ABI_V4;					\
+	rs6000_opts.abi = ABI_V4;					\
     }									\
-  else if (!strcmp (rs6000_abi_name, "gnu"))				\
-    rs6000_current_abi = ABI_V4;					\
-  else if (!strcmp (rs6000_abi_name, "netbsd"))				\
-    rs6000_current_abi = ABI_V4;					\
-  else if (!strcmp (rs6000_abi_name, "openbsd"))			\
-    rs6000_current_abi = ABI_V4;					\
-  else if (!strcmp (rs6000_abi_name, "i960-old"))			\
+  else if (!strcmp (rs6000_opts_str.abi_name, "gnu"))			\
+    rs6000_opts.abi = ABI_V4;						\
+  else if (!strcmp (rs6000_opts_str.abi_name, "netbsd"))		\
+    rs6000_opts.abi = ABI_V4;						\
+  else if (!strcmp (rs6000_opts_str.abi_name, "openbsd"))		\
+    rs6000_opts.abi = ABI_V4;						\
+  else if (!strcmp (rs6000_opts_str.abi_name, "i960-old"))		\
     {									\
-      rs6000_current_abi = ABI_V4;					\
+      rs6000_opts.abi = ABI_V4;						\
       target_flags |= (MASK_LITTLE_ENDIAN | MASK_EABI);			\
       target_flags &= ~MASK_STRICT_ALIGN;				\
       TARGET_NO_BITFIELD_WORD = 1;					\
     }									\
   else									\
     {									\
-      rs6000_current_abi = ABI_V4;					\
-      error ("bad value for -mcall-%s", rs6000_abi_name);		\
+      rs6000_opts.abi = ABI_V4;						\
+      error ("bad value for -mcall-%s", rs6000_opts_str.abi_name);	\
     }									\
 									\
-  if (rs6000_sdata_name)						\
+  if (rs6000_opts_str.sdata_name)					\
     {									\
-      if (!strcmp (rs6000_sdata_name, "none"))				\
-	rs6000_sdata = SDATA_NONE;					\
-      else if (!strcmp (rs6000_sdata_name, "data"))			\
-	rs6000_sdata = SDATA_DATA;					\
-      else if (!strcmp (rs6000_sdata_name, "default"))			\
-	rs6000_sdata = (TARGET_EABI) ? SDATA_EABI : SDATA_SYSV;		\
-      else if (!strcmp (rs6000_sdata_name, "sysv"))			\
-	rs6000_sdata = SDATA_SYSV;					\
-      else if (!strcmp (rs6000_sdata_name, "eabi"))			\
-	rs6000_sdata = SDATA_EABI;					\
+      if (!strcmp (rs6000_opts_str.sdata_name, "none"))			\
+	rs6000_opts.sdata = SDATA_NONE;					\
+      else if (!strcmp (rs6000_opts_str.sdata_name, "data"))		\
+	rs6000_opts.sdata = SDATA_DATA;					\
+      else if (!strcmp (rs6000_opts_str.sdata_name, "default"))		\
+	rs6000_opts.sdata = (TARGET_EABI) ? SDATA_EABI : SDATA_SYSV;	\
+      else if (!strcmp (rs6000_opts_str.sdata_name, "sysv"))		\
+	rs6000_opts.sdata = SDATA_SYSV;					\
+      else if (!strcmp (rs6000_opts_str.sdata_name, "eabi"))		\
+	rs6000_opts.sdata = SDATA_EABI;					\
       else								\
-	error ("bad value for -msdata=%s", rs6000_sdata_name);		\
+	error ("bad value for -msdata=%s", rs6000_opts_str.sdata_name);	\
     }									\
   else if (DEFAULT_ABI == ABI_V4)					\
     {									\
-      rs6000_sdata = SDATA_DATA;					\
-      rs6000_sdata_name = "data";					\
+      rs6000_opts.sdata = SDATA_DATA;					\
+      rs6000_opts_str.sdata_name = "data";				\
     }									\
   else									\
     {									\
-      rs6000_sdata = SDATA_NONE;					\
-      rs6000_sdata_name = "none";					\
+      rs6000_opts.sdata = SDATA_NONE;					\
+      rs6000_opts_str.sdata_name = "none";				\
     }									\
 									\
   if (TARGET_RELOCATABLE &&						\
-      (rs6000_sdata == SDATA_EABI || rs6000_sdata == SDATA_SYSV))	\
+      (rs6000_opts.sdata == SDATA_EABI || rs6000_opts.sdata == SDATA_SYSV)) \
     {									\
-      rs6000_sdata = SDATA_DATA;					\
+      rs6000_opts.sdata = SDATA_DATA;					\
       error ("-mrelocatable and -msdata=%s are incompatible",		\
-	     rs6000_sdata_name);					\
+	     rs6000_opts_str.sdata_name);				\
     }									\
 									\
   else if (flag_pic && DEFAULT_ABI != ABI_AIX				\
-	   && (rs6000_sdata == SDATA_EABI				\
-	       || rs6000_sdata == SDATA_SYSV))				\
+	   && (rs6000_opts.sdata == SDATA_EABI				\
+	       || rs6000_opts.sdata == SDATA_SYSV))			\
     {									\
-      rs6000_sdata = SDATA_DATA;					\
+      rs6000_opts.sdata = SDATA_DATA;					\
       error ("-f%s and -msdata=%s are incompatible",			\
 	     (flag_pic > 1) ? "PIC" : "pic",				\
-	     rs6000_sdata_name);					\
+	     rs6000_opts_str.sdata_name);				\
     }									\
 									\
-  if ((rs6000_sdata != SDATA_NONE && DEFAULT_ABI != ABI_V4)		\
-      || (rs6000_sdata == SDATA_EABI && !TARGET_EABI))			\
+  if ((rs6000_opts.sdata != SDATA_NONE && DEFAULT_ABI != ABI_V4)	\
+      || (rs6000_opts.sdata == SDATA_EABI && !TARGET_EABI))		\
     {									\
-      rs6000_sdata = SDATA_NONE;					\
+      rs6000_opts.sdata = SDATA_NONE;					\
       error ("-msdata=%s and -mcall-%s are incompatible",		\
-	     rs6000_sdata_name, rs6000_abi_name);			\
+	     rs6000_opts_str.sdata_name, rs6000_opts_str.abi_name);	\
     }									\
 									\
-  targetm.have_srodata_section = rs6000_sdata == SDATA_EABI;		\
+  targetm.have_srodata_section = rs6000_opts.sdata == SDATA_EABI;	\
 									\
   if (TARGET_RELOCATABLE && !TARGET_MINIMAL_TOC)			\
     {									\
@@ -190,21 +176,21 @@  do {									\
       error ("-mrelocatable and -mno-minimal-toc are incompatible");	\
     }									\
 									\
-  if (TARGET_RELOCATABLE && rs6000_current_abi == ABI_AIX)		\
+  if (TARGET_RELOCATABLE && rs6000_opts.abi == ABI_AIX)			\
     {									\
       target_flags &= ~MASK_RELOCATABLE;				\
       error ("-mrelocatable and -mcall-%s are incompatible",		\
-	     rs6000_abi_name);						\
+	     rs6000_opts_str.abi_name);					\
     }									\
 									\
-  if (!TARGET_64BIT && flag_pic > 1 && rs6000_current_abi == ABI_AIX)	\
+  if (!TARGET_64BIT && flag_pic > 1 && rs6000_opts.abi == ABI_AIX)	\
     {									\
       flag_pic = 0;							\
       error ("-fPIC and -mcall-%s are incompatible",			\
-	     rs6000_abi_name);						\
+	     rs6000_opts_str.abi_name);					\
     }									\
 									\
-  if (rs6000_current_abi == ABI_AIX && TARGET_LITTLE_ENDIAN)		\
+  if (rs6000_opts.abi == ABI_AIX && TARGET_LITTLE_ENDIAN)		\
     {									\
       target_flags &= ~MASK_LITTLE_ENDIAN;				\
       error ("-mcall-aixdesc must be big endian");			\