OSDN Git Service

Add setjmp/longjmp exception handling.
[pf3gnuchains/gcc-fork.git] / gcc / config / sparc / sparc.h
index 7089b65..708060f 100644 (file)
@@ -1,5 +1,6 @@
 /* Definitions of target machine for GNU compiler, for Sun SPARC.
-   Copyright (C) 1987, 88, 89, 92, 94, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 89, 92, 94, 95, 96, 1997 Free Software Foundation,
+   Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com).
    64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
    at Cygnus Support.
@@ -18,41 +19,88 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 /* Note that some other tm.h files include this one and then override
    many of the definitions that relate to assembler syntax.  */
 
 /* Sparc64 support has been added by trying to allow for a day when one
    compiler can handle both v8 and v9.  There are a few cases where this
-   isn't doable, but keep them to a minimum!  Two macros are used to help out:
-   TARGET_V9 is used to select (at runtime) !v9-ness or v9-ness.
-   SPARCV9 is defined when compiling for sparc64 only.
-   In places where it is possible to choose between the two at runtime, use
-   TARGET_V9.  In places where it is currently not possible to select
-   between the two at runtime use SPARCV9.  Again, keep uses of SPARCV9 to a
-   minimum.  No attempt is made to support both v8 and v9 in the v9 compiler.
-
-   If a combination v8/v9 compiler is too slow, it should always be possible
-   to #define TARGET_V9 as 0 (and potentially other v9-only options), and
-   #undef SPARCV9.  */
-
-/* What architecture we're compiling for.  This must coincide with the
-   `arch_type' attribute in the .md file.  The names were chosen to avoid
-   potential misunderstandings with the various 32 bit flavors (v7, v8, etc.):
-   if we used ARCH_V9 then we'd want to use something like ARCH_V8 but that
-   could be misleading and ARCH_NOTV9 sounds klunky.  */
-enum arch_type { ARCH_32BIT, ARCH_64BIT };
-extern enum arch_type sparc_arch_type;
+   isn't doable, but keep them to a minimum!
+
+   TARGET_V9 is used to select at runtime the sparc64 chip.
+   TARGET_ARCH64 is used to select at runtime a 64 bit environment.
+   SPARC_V9 is defined as 0 or 1 (so it may be used inside and outside
+   #define's), and says whether the cpu is a sparc64 chip (which may be
+   running in a 32 or 64 bit environment).
+   SPARC_ARCH64 is defined as 0 for a 32 bit environment and 1 for a 64 bit
+   environment.
+
+   In places where it is possible to choose at runtime, use TARGET_V9 and
+   TARGET_ARCH64.  In places where it is currently not possible to select
+   between the two at runtime use SPARC_{V9,ARCH64}.  Again, keep uses of
+   SPARC_{V9,ARCH64} to a minimum.  No attempt is made to support both v8
+   and v9 in the v9 compiler.
+
+   ??? All uses of SPARC_V9 have been removed.  Try not to add new ones.
+*/
+
+#ifndef SPARC_V9
+#define SPARC_V9 0
+#endif
+#ifndef SPARC_ARCH64
+#define SPARC_ARCH64 0
+#endif
+
+/* Values of TARGET_CPU_DEFAULT, set via -D in the Makefile.  */
+#define TARGET_CPU_sparc       0
+#define TARGET_CPU_v7          0       /* alias for previous */
+#define TARGET_CPU_sparclet    1
+#define TARGET_CPU_sparclite   2
+#define TARGET_CPU_v8          3
+#define TARGET_CPU_supersparc  4
+#define TARGET_CPU_ultrasparc  5
+#define TARGET_CPU_sparc64     5       /* alias for ultrasparc */
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_sparc || TARGET_CPU_DEFAULT == TARGET_CPU_v8 || TARGET_CPU_DEFAULT == TARGET_CPU_supersparc
+#define CPP_DEFAULT_SPEC ""
+#define ASM_DEFAULT_SPEC ""
+#else
+#if TARGET_CPU_DEFAULT == TARGET_CPU_sparclet
+#define CPP_DEFAULT_SPEC "-D__sparclet__"
+#define ASM_DEFAULT_SPEC "-Asparclet"
+#else
+#if TARGET_CPU_DEFAULT == TARGET_CPU_sparclite
+#define CPP_DEFAULT_SPEC "-D__sparclite__"
+#define ASM_DEFAULT_SPEC "-Asparclite"
+#else
+#if TARGET_CPU_DEFAULT == TARGET_CPU_sparc64
+/* ??? What does Sun's CC pass?  */
+#define CPP_DEFAULT_SPEC "-D__sparc_v9__"
+/* ??? It's not clear how other assemblers will handle this, so by default
+   use GAS.  Sun's Solaris assembler recognizes -xarch=v8plus, but this case
+   is handled in sol2.h.  */
+#define ASM_DEFAULT_SPEC "-Av9"
+#else
+Unrecognized value in TARGET_CPU_DEFAULT.
+#endif
+#endif
+#endif
+#endif
 
 /* Names to predefine in the preprocessor for this target machine.  */
 
 /* ??? The GCC_NEW_VARARGS macro is now obsolete, because gcc always uses
    the right varags.h file when bootstrapping.  */
+/* ??? It's not clear what value we want to use for -Acpu/machine for
+   sparc64 in 32 bit environments, so for now we only use `sparc64' in
+   64 bit environments.  */
+/* ??? __arch64__ is subject to change.  */
 
-#ifdef SPARCV9
+#if SPARC_ARCH64
 #define CPP_PREDEFINES \
-  "-Dsparc -Dsun -Dunix -D__sparc_v9__ \
+  "-Dsparc -Dsun -Dunix -D__arch64__ \
    -Asystem(unix) -Asystem(bsd) -Acpu(sparc64) -Amachine(sparc64)"
 #else
 #define CPP_PREDEFINES \
@@ -60,48 +108,103 @@ extern enum arch_type sparc_arch_type;
    -Asystem(unix) -Asystem(bsd) -Acpu(sparc) -Amachine(sparc)"
 #endif
 
-#define LIB_SPEC "%{!shared:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} %{g:-lg}}"
-
-/* Provide required defaults for linker -e and -d switches.  */
-
-#define LINK_SPEC \
- "%{!shared:%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp} %{static:-Bstatic} \
-  %{assert*} %{shared:-assert pure-text}"
-
-/* Special flags to the Sun-4 assembler when using pipe for input.  */
-
-#define ASM_SPEC \
-  " %| %{R} %{!pg:%{!p:%{fpic:-k} %{fPIC:-k}}} %{keep-local-as-symbols:-L}"
-
 /* Define macros to distinguish architectures.  */
 
-#ifdef SPARCV9
+#if SPARC_ARCH64
 #define CPP_SPEC "\
 %{mint64:-D__INT_MAX__=9223372036854775807LL -D__LONG_MAX__=9223372036854775807LL} \
 %{mlong64:-D__LONG_MAX__=9223372036854775807LL} \
 "
 #else
-#define CPP_SPEC "\
+#define CPP_SPEC "%(cpp_cpu)"
+#endif
+
+/* Common CPP definitions used by CPP_SPEC amongst the various targets
+   for handling -mcpu=xxx switches.  */
+/* ??? v8plus/v9/ultrasparc handling is tentative */
+#define CPP_CPU_SPEC "\
+%{mcypress:} \
 %{msparclite:-D__sparclite__} \
 %{mf930:-D__sparclite__} %{mf934:-D__sparclite__} \
 %{mv8:-D__sparc_v8__} \
-%{msupersparc:-D__supersparc__ -D__sparc_v8__} \
+%{msupersparc:-D__supersparc__ -D__sparc_v8__} \
+%{mcpu=sparclet:-D__sparclet__} %{mcpu=tsc701:-D__sparclet__} \
+%{mcpu=sparclite:-D__sparclite__} \
+%{mcpu=f930:-D__sparclite__} %{mcpu=f934:-D__sparclite__} \
+%{mcpu=v8:-D__sparc_v8__} \
+%{mcpu=supersparc:-D__supersparc__ -D__sparc_v8__} \
+%{mcpu=v8plus:-D__sparc_v9__} \
+%{mcpu=v9:-D__sparc_v9__} \
+%{mcpu=ultrasparc:-D__sparc_v9__} \
+%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_default)}}}}}}} \
 "
-#endif
 
 /* Prevent error on `-sun4' and `-target sun4' options.  */
 /* This used to translate -dalign to -malign, but that is no good
    because it can't turn off the usual meaning of making debugging dumps.  */
+/* Translate old style -m<cpu> into new style -mcpu=<cpu>.
+   ??? Delete support for -m<cpu> for 2.9.  */
+
+#define CC1_SPEC "\
+%{sun4:} %{target:} \
+%{mcypress:-mcpu=cypress} \
+%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \
+%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
+"
+
+#define LIB_SPEC "%{!shared:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} %{g:-lg}}"
+
+/* Provide required defaults for linker -e and -d switches.  */
+
+#define LINK_SPEC \
+ "%{!shared:%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp} %{static:-Bstatic} \
+  %{assert*} %{shared:%{!mimpure-text:-assert pure-text}}"
+
+/* Special flags to the Sun-4 assembler when using pipe for input.  */
+
+#define ASM_SPEC "\
+%| %{R} %{!pg:%{!p:%{fpic:-k} %{fPIC:-k}}} %{keep-local-as-symbols:-L} \
+%(asm_cpu) \
+"
+
+/* Override in target specific files.  */
+#define ASM_CPU_SPEC "\
+%{mcpu=sparclet:-Asparclet} %{mcpu=tsc701:-Asparclet} \
+%{msparclite:-Asparclite} \
+%{mf930:-Asparclite} %{mf934:-Asparclite} \
+%{mcpu=sparclite:-Asparclite} \
+%{mcpu=f930:-Asparclite} %{mcpu=f934:-Asparclite} \
+%{mcpu=v8plus:-Av9} \
+%{mcpu=v9:-Av9} \
+%{mcpu=ultrasparc:-Av9} \
+%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(asm_default)}}}}}}} \
+"
+
+/* This macro defines names of additional specifications to put in the specs
+   that can be used in various specifications like CC1_SPEC.  Its definition
+   is an initializer with a subgrouping for each command option.
+
+   Each subgrouping contains a string constant, that defines the
+   specification name, and a string constant that used by the GNU CC driver
+   program.
 
-#define CC1_SPEC "%{sun4:} %{target:}"
+   Do not define this macro if it does not need to do anything.  */
 
-#ifdef SPARCV9
+#define EXTRA_SPECS                                    \
+  { "cpp_cpu",         CPP_CPU_SPEC },                 \
+  { "cpp_default",     CPP_DEFAULT_SPEC },             \
+  { "asm_cpu",         ASM_CPU_SPEC },                 \
+  { "asm_default",     ASM_DEFAULT_SPEC },             \
+  SUBTARGET_EXTRA_SPECS
+
+#define SUBTARGET_EXTRA_SPECS
+\f
+#if SPARC_ARCH64
 #define PTRDIFF_TYPE "long long int"
 #define SIZE_TYPE "long long unsigned int"
 #else
 #define PTRDIFF_TYPE "int"
-/* In 2.4 it should work to delete this.
-   #define SIZE_TYPE "int"  */
+/* The default value for SIZE_TYPE is "unsigned int" which is what we want.  */
 #endif
 
 /* ??? This should be 32 bits for v9 but what can we do?  */
@@ -120,7 +223,7 @@ void sparc_override_options ();
 
 #define OVERRIDE_OPTIONS \
   do {                                                                 \
-    if (profile_flag || profile_block_flag)                            \
+    if (profile_flag || profile_block_flag || profile_arc_flag)                \
       {                                                                        \
        if (flag_pic)                                                   \
          {                                                             \
@@ -131,8 +234,8 @@ void sparc_override_options ();
          }                                                             \
        flag_omit_frame_pointer = 0;                                    \
       }                                                                        \
-    SUBTARGET_OVERRIDE_OPTIONS;                                                \
     sparc_override_options ();                                         \
+    SUBTARGET_OVERRIDE_OPTIONS;                                                \
   } while (0)
 
 /* This is meant to be redefined in the host dependent files.  */
@@ -171,55 +274,67 @@ extern int target_flags;
 #define MASK_UNALIGNED_DOUBLES 4
 #define TARGET_UNALIGNED_DOUBLES (target_flags & MASK_UNALIGNED_DOUBLES)
 
-/* ??? Bits 0x18 are currently unused.  */
-
-/* Nonzero means we should schedule code for the TMS390Z55 SuperSparc chip.  */
-#define MASK_SUPERSPARC 0x20
-#define TARGET_SUPERSPARC (target_flags & MASK_SUPERSPARC)
-
 /* Nonzero means that we should generate code for a v8 sparc.  */
-#define MASK_V8 0x40
+#define MASK_V8 0x8
 #define TARGET_V8 (target_flags & MASK_V8)
 
 /* Nonzero means that we should generate code for a sparclite.
    This enables the sparclite specific instructions, but does not affect
    whether FPU instructions are emitted.  */
-#define MASK_SPARCLITE 0x80
+#define MASK_SPARCLITE 0x10
 #define TARGET_SPARCLITE (target_flags & MASK_SPARCLITE)
 
-/* Nonzero means that we should generate code using a flat register window
-   model, i.e. no save/restore instructions are generated, in the most
-   efficient manner.  This code is not compatible with normal sparc code.  */
-/* This is not a user selectable option yet, because it requires changes
-   that are not yet switchable via command line arguments.  */
-/* ??? This flag is deprecated and may disappear at some point.  */
-#define MASK_FRW 0x100
-#define TARGET_FRW (target_flags & MASK_FRW)
+/* Nonzero if we're compiling for the sparclet.  */
+#define MASK_SPARCLET 0x20
+#define TARGET_SPARCLET (target_flags & MASK_SPARCLET)
+
+/* Nonzero if we're compiling for v9 sparc.
+   Note that v9's can run in 32 bit mode so this doesn't necessarily mean
+   the word size is 64.  */
+#define MASK_V9 0x40
+#define TARGET_V9 (target_flags & MASK_V9)
+
+/* Non-zero to generate code that uses the instructions deprecated in
+   the v9 architecture.  This option only applies to v9 systems.  */
+/* ??? This isn't user selectable yet.  It's used to enable such insns
+   on 32 bit v9 systems and for the moment they're permanently disabled
+   on 64 bit v9 systems.  */
+#define MASK_DEPRECATED_V8_INSNS 0x80
+#define TARGET_DEPRECATED_V8_INSNS (target_flags & MASK_DEPRECATED_V8_INSNS)
+
+/* Mask of all CPU selection flags.  */
+#define MASK_ISA \
+(MASK_V8 + MASK_SPARCLITE + MASK_SPARCLET + MASK_V9 + MASK_DEPRECATED_V8_INSNS)
+
+/* Non-zero means don't pass `-assert pure-text' to the linker.  */
+#define MASK_IMPURE_TEXT 0x100
+#define TARGET_IMPURE_TEXT (target_flags & MASK_IMPURE_TEXT)
 
 /* Nonzero means that we should generate code using a flat register window
-   model, i.e. no save/restore instructions are generated, but which is
-   compatible with normal sparc code.   This is the same as above, except
-   that the frame pointer is %i7 instead of %fp.  */
-/* ??? This use to be named TARGET_FRW_COMPAT.  At some point TARGET_FRW will
-   go away, but until that time only use this one when necessary.
-   -mflat sets both.  */
+   model, i.e. no save/restore instructions are generated, which is
+   compatible with normal sparc code.
+   The frame pointer is %i7 instead of %fp.  */
 #define MASK_FLAT 0x200
 #define TARGET_FLAT (target_flags & MASK_FLAT)
 
 /* Nonzero means use the registers that the Sparc ABI reserves for
-   application software.  This is the default for v8, but not v9.  */
+   application software.  This must be the default to coincide with the
+   setting in FIXED_REGISTERS.  */
 #define MASK_APP_REGS 0x400
 #define TARGET_APP_REGS (target_flags & MASK_APP_REGS)
 
-/*  Option to select how quad word floating point is implemented.
-    When TARGET_HARD_QUAD is true, we use the hardware quad instructions.
-    Otherwise, we use the SPARC ABI quad library functions.  */
+/* Option to select how quad word floating point is implemented.
+   When TARGET_HARD_QUAD is true, we use the hardware quad instructions.
+   Otherwise, we use the SPARC ABI quad library functions.  */
 #define MASK_HARD_QUAD 0x800
 #define TARGET_HARD_QUAD (target_flags & MASK_HARD_QUAD)
 
-/* Nonzero if we're compiling for 64 bit sparc.  */
-#define MASK_V9 0x1000
-#define TARGET_V9 (target_flags & MASK_V9)
+/* Non-zero on little-endian machines.  */
+/* ??? Little endian support currently only exists for sparclet-aout and
+   sparc64-elf configurations.  May eventually want to expand the support
+   to all targets, but for now it's kept local to only those two.  */
+#define MASK_LITTLE_ENDIAN 0x1000
+#define TARGET_LITTLE_ENDIAN (target_flags & MASK_LITTLE_ENDIAN)
 
 /* Nonzero if ints are 64 bits.
    This automatically implies longs are 64 bits too.
@@ -238,21 +353,19 @@ extern int target_flags;
 #define MASK_PTR64 0x8000
 #define TARGET_PTR64 (target_flags & MASK_PTR64)
 
-/* Nonzero if we are generating code to be tested in a 32 bit environment.
-   Hence, we assume the upper 32 bits of symbolic addresses are zero, and
-   avoid generating %uhi and %ulo terms.
-   Pointers are still 64 bits though!  This option is for v9 only.  */
-/* ??? This option is deprecated.  Try to use -mmedlow.  */
-#define MASK_ENV32 0x10000
-#define TARGET_ENV32 (target_flags & MASK_ENV32)
-
-/* Memory models.
-   Two memory models are supported:
-   TARGET_MEDLOW: 32 bit address space, top 32 bits = 0
-                  (pointers still 64 bits)
-   TARGET_MEDANY: 32 bit address space, data segment loaded anywhere
-                  (use %g4 as offset).
-   TARGET_FULLANY: not supported yet.
+/* Nonzero if generating code to run in a 64 bit environment.  */
+#define MASK_ARCH64 0x10000
+#define TARGET_ARCH64 (target_flags & MASK_ARCH64)
+#define TARGET_ARCH32 (! TARGET_ARCH64)
+
+/* SPARC64 memory models.
+   TARGET_MEDLOW: 32 bit address space, top 32 bits = 0,
+                  avoid generating %uhi and %ulo terms.
+                  (pointers can be 32 or 64 bits)
+   TARGET_MEDANY: 64 bit address space, data segment restricted to 4G, but
+                  can be loaded anywhere (use %g4 as offset).
+   TARGET_FULLANY: 64 bit address space, no restrictions.
+                   This option is not fully supported yet.
    These options are for v9 only.  All mask values are nonzero so the v8
    compiler can assume this stuff won't interfere.  */
 #define MASK_MEDLOW 0x20000
@@ -271,55 +384,75 @@ extern int target_flags;
 #define MASK_STACK_BIAS 0x80000
 #define TARGET_STACK_BIAS (target_flags & MASK_STACK_BIAS)
 
+/* Non-zero means %g0 is a normal register.
+   We still clobber it as necessary, but we can't rely on it always having
+   a zero value.
+   We don't bother to support this in true 64 bit mode.  */
+#define MASK_LIVE_G0 0x100000
+#define TARGET_LIVE_G0 (target_flags & MASK_LIVE_G0)
+
+/* Non-zero means the cpu has broken `save' and `restore' insns, only
+   the trivial versions work (save %g0,%g0,%g0; restore %g0,%g0,%g0).
+   We assume the environment will properly handle or otherwise avoid
+   trouble associated with an interrupt occuring after the `save' or trap
+   occuring during it.  */
+#define MASK_BROKEN_SAVERESTORE 0x200000
+#define TARGET_BROKEN_SAVERESTORE (target_flags & MASK_BROKEN_SAVERESTORE)
+
+/* Non-zero means -m{,no-}fpu was passed on the command line.  */
+#define MASK_FPU_SET 0x400000
+#define TARGET_FPU_SET (target_flags & MASK_FPU_SET)
+
 /* Macro to define tables used to set the flags.
    This is a list in braces of pairs in braces,
    each pair being { "NAME", VALUE }
    where VALUE is the bits to set or minus the bits to clear.
    An empty string NAME is used to identify the default VALUE.  */
 
-/* The Fujitsu MB86930 is the original sparclite chip, with no fpu.
-   The Fujitsu MB86934 is the recent sparclite chip, with an fpu.
-   We use -mf930 and -mf934 options to choose which.
-   ??? These should perhaps be -mcpu= options.  */
-
 #define TARGET_SWITCHES  \
-  { {"fpu", MASK_FPU},                 \
+  { {"fpu", MASK_FPU | MASK_FPU_SET},  \
     {"no-fpu", -MASK_FPU},             \
-    {"hard-float", MASK_FPU},          \
+    {"no-fpu", MASK_FPU_SET},          \
+    {"hard-float", MASK_FPU | MASK_FPU_SET}, \
     {"soft-float", -MASK_FPU},         \
+    {"soft-float", MASK_FPU_SET},      \
     {"epilogue", MASK_EPILOGUE},       \
     {"no-epilogue", -MASK_EPILOGUE},   \
     {"unaligned-doubles", MASK_UNALIGNED_DOUBLES}, \
     {"no-unaligned-doubles", -MASK_UNALIGNED_DOUBLES}, \
-    {"supersparc", MASK_SUPERSPARC+MASK_V8},   \
-    {"cypress", -MASK_SUPERSPARC-MASK_V8},     \
-    {"v8", MASK_V8},                   \
-    {"no-v8", -MASK_V8},               \
-    {"sparclite", MASK_SPARCLITE},     \
-    {"no-sparclite", -MASK_SPARCLITE}, \
-    {"f930", MASK_SPARCLITE},          \
-    {"f930", -MASK_FPU},               \
-    {"f934", MASK_SPARCLITE},          \
-    {"flat", MASK_FRW+MASK_FLAT},      \
-    {"no-flat", -(MASK_FRW+MASK_FLAT)},        \
+    {"impure-text", MASK_IMPURE_TEXT}, \
+    {"no-impure-text", -MASK_IMPURE_TEXT}, \
+    {"flat", MASK_FLAT},               \
+    {"no-flat", -MASK_FLAT},           \
     {"app-regs", MASK_APP_REGS},       \
     {"no-app-regs", -MASK_APP_REGS},   \
     {"hard-quad-float", MASK_HARD_QUAD}, \
     {"soft-quad-float", -MASK_HARD_QUAD}, \
+    /* ??? These are coerced to -mcpu=.  Delete in 2.9.  */ \
+    {"cypress", 0},                    \
+    {"sparclite", 0},                  \
+    {"f930", 0},                       \
+    {"f934", 0},                       \
+    {"v8", 0},                         \
+    {"supersparc", 0},                 \
     SUBTARGET_SWITCHES                 \
-    V9_SWITCHES                                \
+    ARCH64_SWITCHES                    \
     { "", TARGET_DEFAULT}}
 
+/* MASK_APP_REGS must always be the default because that's what
+   FIXED_REGISTERS is set to and -ffixed- is processed before
+   CONDITIONAL_REGISTER_USAGE is called (where we process -mno-app-regs).  */
 #define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU)
 
-/* This is meant to be redefined in the host dependent files */
+/* This is meant to be redefined in target specific files.  */
 #define SUBTARGET_SWITCHES
 
-/* ??? Until we support a combination v8/v9 compiler, the v9 specific options
-   are only defined for the v9 compiler.  */
-#ifdef SPARCV9
-#define V9_SWITCHES \
-/*  {"v9", MASK_V9}, */                        \
+/* ??? Until we support a combination 32/64 bit compiler, these options
+   are only defined for the v9 compiler in a true 64 bit environment.  */
+#if SPARC_ARCH64
+#define ARCH64_SWITCHES \
+/*  {"arch32", -MASK_ARCH64}, */       \
+/*  {"arch64", MASK_ARCH64}, */                \
     {"int64", MASK_INT64+MASK_LONG64}, \
     {"int32", -MASK_INT64},            \
     {"int32", MASK_LONG64},            \
@@ -333,10 +466,74 @@ extern int target_flags;
     {"medlow", -MASK_CODE_MODEL},      \
     {"medlow", MASK_MEDLOW},           \
     {"medany", -MASK_CODE_MODEL},      \
-    {"medany", MASK_MEDANY},
+    {"medany", MASK_MEDANY},           \
+    {"fullany", -MASK_CODE_MODEL},     \
+    {"fullany", MASK_FULLANY},
 #else
-#define V9_SWITCHES
+#define ARCH64_SWITCHES
 #endif
+
+/* Processor type.
+   These must match the values for the cpu attribute in sparc.md.  */
+enum processor_type {
+  PROCESSOR_V7,
+  PROCESSOR_CYPRESS,
+  PROCESSOR_V8,
+  PROCESSOR_SUPERSPARC,
+  PROCESSOR_SPARCLITE,
+  PROCESSOR_F930,
+  PROCESSOR_F934,
+  PROCESSOR_SPARCLET,
+  PROCESSOR_TSC701,
+  PROCESSOR_V8PLUS,
+  PROCESSOR_V9,
+  PROCESSOR_ULTRASPARC
+};
+
+/* This is set from -m{cpu,tune}=xxx.  */
+extern enum processor_type sparc_cpu;
+
+/* Recast the cpu class to be the cpu attribute.
+   Every file includes us, but not every file includes insn-attr.h.  */
+#define sparc_cpu_attr ((enum attr_cpu) sparc_cpu)
+
+/* This macro is similar to `TARGET_SWITCHES' but defines names of
+   command options that have values.  Its definition is an
+   initializer with a subgrouping for each command option.
+
+   Each subgrouping contains a string constant, that defines the
+   fixed part of the option name, and the address of a variable. 
+   The variable, type `char *', is set to the variable part of the
+   given option if the fixed part matches.  The actual option name
+   is made by appending `-m' to the specified name.
+
+   Here is an example which defines `-mshort-data-NUMBER'.  If the
+   given option is `-mshort-data-512', the variable `m88k_short_data'
+   will be set to the string `"512"'.
+
+       extern char *m88k_short_data;
+       #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } }  */
+
+#define TARGET_OPTIONS \
+{                                      \
+  {"cpu=",  &sparc_select[1].string},  \
+  {"tune=", &sparc_select[2].string},  \
+  SUBTARGET_OPTIONS \
+}
+
+/* This is meant to be redefined in target specific files.  */
+#define SUBTARGET_OPTIONS
+
+/* sparc_select[0] is reserved for the default cpu.  */
+struct sparc_cpu_select
+{
+  char *string;
+  char *name;
+  int set_tune_p;
+  int set_arch_p;
+};
+
+extern struct sparc_cpu_select sparc_select[];
 \f
 /* target machine storage layout */
 
@@ -349,15 +546,20 @@ extern int target_flags;
 #define BITS_BIG_ENDIAN 1
 
 /* Define this if most significant byte of a word is the lowest numbered.  */
-/* This is true on the SPARC.  */
 #define BYTES_BIG_ENDIAN 1
 
 /* Define this if most significant word of a multiword number is the lowest
    numbered.  */
-/* Doubles are stored in memory with the high order word first.  This
-   matters when cross-compiling.  */
 #define WORDS_BIG_ENDIAN 1
 
+/* Define this to set the endianness to use in libgcc2.c, which can
+   not depend on target_flags.  */
+#if defined (__LITTLE_ENDIAN__)
+#define LIBGCC2_WORDS_BIG_ENDIAN 0
+#else
+#define LIBGCC2_WORDS_BIG_ENDIAN 1
+#endif
+
 /* number of bits in an addressable storage unit */
 #define BITS_PER_UNIT 8
 
@@ -365,11 +567,11 @@ extern int target_flags;
    Note that this is not necessarily the width of data type `int';
    if using 16-bit ints on a 68000, this would still be 32.
    But on a machine with 16-bit registers, this would be 16.  */
-#define BITS_PER_WORD          (TARGET_V9 ? 64 : 32)
+#define BITS_PER_WORD          (TARGET_ARCH64 ? 64 : 32)
 #define MAX_BITS_PER_WORD      64
 
 /* Width of a word, in units (bytes).  */
-#define UNITS_PER_WORD         (TARGET_V9 ? 8 : 4)
+#define UNITS_PER_WORD         (TARGET_ARCH64 ? 8 : 4)
 #define MIN_UNITS_PER_WORD     4
 
 /* Now define the sizes of the C data types.  */
@@ -384,7 +586,7 @@ extern int target_flags;
 #define MAX_INT_TYPE_SIZE      64
 #define MAX_LONG_TYPE_SIZE     64
 
-#ifdef SPARCV9
+#if SPARC_ARCH64
 /* ??? This does not work in SunOS 4.x, so it is not enabled here.
    Instead, it is enabled in sol2.h, because it does work under Solaris.  */
 /* Define for support of TFmode long double and REAL_ARITHMETIC.
@@ -397,22 +599,22 @@ extern int target_flags;
 #define POINTER_SIZE (TARGET_PTR64 ? 64 : 32)
 
 /* Allocation boundary (in *bits*) for storing arguments in argument list.  */
-#define PARM_BOUNDARY (TARGET_V9 ? 64 : 32)
+#define PARM_BOUNDARY (TARGET_ARCH64 ? 64 : 32)
 
 /* Boundary (in *bits*) on which stack pointer should be aligned.  */
-#define STACK_BOUNDARY (TARGET_V9 ? 128 : 64)
+#define STACK_BOUNDARY (TARGET_ARCH64 ? 128 : 64)
 
 /* ALIGN FRAMES on double word boundaries */
 
 #define SPARC_STACK_ALIGN(LOC) \
-  (TARGET_V9 ? (((LOC)+15) & ~15) : (((LOC)+7) & ~7))
+  (TARGET_ARCH64 ? (((LOC)+15) & ~15) : (((LOC)+7) & ~7))
 
 /* Allocation boundary (in *bits*) for the code of a function.  */
 #define FUNCTION_BOUNDARY 32
 
 /* Alignment of field after `int : 0' in a structure.  */
 /* ??? Should this be based on TARGET_INT64?  */
-#define EMPTY_FIELD_BOUNDARY (TARGET_V9 ? 64 : 32)
+#define EMPTY_FIELD_BOUNDARY (TARGET_ARCH64 ? 64 : 32)
 
 /* Every structure's size must be a multiple of this.  */
 #define STRUCTURE_SIZE_BOUNDARY 8
@@ -421,7 +623,7 @@ extern int target_flags;
 #define PCC_BITFIELD_TYPE_MATTERS 1
 
 /* No data type wants to be aligned rounder than this.  */
-#define BIGGEST_ALIGNMENT (TARGET_V9 ? 128 : 64)
+#define BIGGEST_ALIGNMENT (TARGET_ARCH64 ? 128 : 64)
 
 /* The best alignment to use in cases where we have a choice.  */
 #define FASTEST_ALIGNMENT 64
@@ -476,7 +678,7 @@ extern int target_flags;
       if (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES))            \
        data_section ();                                                \
     }                                                                  \
-  else if (*tree_code_type[(int) TREE_CODE (T)] == 'c')                        \
+  else if (TREE_CODE_CLASS (TREE_CODE (T)) == 'c')                     \
     {                                                                  \
       if ((TREE_CODE (T) == STRING_CST && flag_writable_strings)       \
          || TYPE_ALIGN (TREE_TYPE (T)) > MAX_TEXT_ALIGN                \
@@ -512,18 +714,23 @@ extern int target_flags;
    accessible.  We still account for them to simplify register computations
    (eg: in CLASS_MAX_NREGS).  There are also 4 fp condition code registers, so
    32+32+32+4 == 100.
-   Register 0 is used as the integer condition code register.  */
+   Register 100 is used as the integer condition code register.  */
 
-#ifdef SPARCV9
-#define FIRST_PSEUDO_REGISTER 100
-#else
-#define FIRST_PSEUDO_REGISTER 64
-#endif
+#define FIRST_PSEUDO_REGISTER 101
+
+/* Additional V9 fp regs.  */
+#define SPARC_FIRST_V9_FP_REG 64
+#define SPARC_LAST_V9_FP_REG  95
+/* V9 %fcc[0123].  V8 uses (figuratively) %fcc0.  */
+#define SPARC_FIRST_V9_FCC_REG 96
+#define SPARC_LAST_V9_FCC_REG  99
+/* V8 fcc reg.  */
+#define SPARC_FCC_REG 96
+/* Integer CC reg.  We don't distinguish %icc from %xcc.  */
+#define SPARC_ICC_REG 100
 
 /* 1 for registers that have pervasive standard uses
    and are not available for the register allocator.
-   g0 is used for the condition code and not to represent %g0, which is
-   hardwired to 0, so reg 0 is *not* fixed.
    On non-v9 systems:
    g1 is free to use as temporary.
    g2-g4 are reserved for applications.  Gcc normally uses them as
@@ -531,17 +738,20 @@ extern int target_flags;
    g5 through g7 are reserved for the operating system.
    On v9 systems:
    g1 and g5 are free to use as temporaries.
-   g2-g4 are reserved for applications (the compiler will not normally use
-   them, but they can be used as temporaries with -mapp-regs).
+   g2-g4 are reserved for applications.  Gcc normally uses them as
+   temporaries, but this can be disabled via the -mno-app-regs option.
    g6-g7 are reserved for the operating system.
    ??? Register 1 is used as a temporary by the 64 bit sethi pattern, so must
    currently be a fixed register until this pattern is rewritten.
    Register 1 is also used when restoring call-preserved registers in large
-   stack frames.  */
+   stack frames.
+
+   Registers fixed in arch32 and not arch64 (or vice-versa) are marked in
+   CONDITIONAL_REGISTER_USAGE in order to properly handle -ffixed-.
+*/
 
-#ifdef SPARCV9
 #define FIXED_REGISTERS  \
- {0, 1, 1, 1, 1, 0, 1, 1,      \
+ {1, 0, 0, 0, 0, 0, 1, 1,      \
   0, 0, 0, 0, 0, 0, 1, 0,      \
   0, 0, 0, 0, 0, 0, 0, 0,      \
   0, 0, 0, 0, 0, 0, 1, 1,      \
@@ -556,19 +766,7 @@ extern int target_flags;
   0, 0, 0, 0, 0, 0, 0, 0,      \
   0, 0, 0, 0, 0, 0, 0, 0,      \
                                \
-  0, 0, 0, 0}
-#else
-#define FIXED_REGISTERS  \
- {0, 0, 0, 0, 0, 1, 1, 1,      \
-  0, 0, 0, 0, 0, 0, 1, 0,      \
-  0, 0, 0, 0, 0, 0, 0, 0,      \
-  0, 0, 0, 0, 0, 0, 1, 1,      \
-                               \
-  0, 0, 0, 0, 0, 0, 0, 0,      \
-  0, 0, 0, 0, 0, 0, 0, 0,      \
-  0, 0, 0, 0, 0, 0, 0, 0,      \
-  0, 0, 0, 0, 0, 0, 0, 0}
-#endif
+  0, 0, 0, 0, 0}
 
 /* 1 for registers not available across function calls.
    These must include the FIXED_REGISTERS and also any
@@ -577,7 +775,6 @@ extern int target_flags;
    and the register where structure-value addresses are passed.
    Aside from that, you can include as many other registers as you like.  */
 
-#ifdef SPARCV9
 #define CALL_USED_REGISTERS  \
  {1, 1, 1, 1, 1, 1, 1, 1,      \
   1, 1, 1, 1, 1, 1, 1, 1,      \
@@ -586,52 +783,57 @@ extern int target_flags;
                                \
   1, 1, 1, 1, 1, 1, 1, 1,      \
   1, 1, 1, 1, 1, 1, 1, 1,      \
-  0, 0, 0, 0, 0, 0, 0, 0,      \
-  0, 0, 0, 0, 0, 0, 0, 0,      \
-                               \
-  0, 0, 0, 0, 0, 0, 0, 0,      \
-  0, 0, 0, 0, 0, 0, 0, 0,      \
   1, 1, 1, 1, 1, 1, 1, 1,      \
   1, 1, 1, 1, 1, 1, 1, 1,      \
                                \
-  1, 1, 1, 1}
-#else
-#define CALL_USED_REGISTERS  \
- {1, 1, 1, 1, 1, 1, 1, 1,      \
   1, 1, 1, 1, 1, 1, 1, 1,      \
-  0, 0, 0, 0, 0, 0, 0, 0,      \
-  0, 0, 0, 0, 0, 0, 1, 1,      \
-                               \
   1, 1, 1, 1, 1, 1, 1, 1,      \
   1, 1, 1, 1, 1, 1, 1, 1,      \
   1, 1, 1, 1, 1, 1, 1, 1,      \
-  1, 1, 1, 1, 1, 1, 1, 1}
-#endif
+                               \
+  1, 1, 1, 1, 1}
 
-/* If !TARGET_FPU, then make the fp registers fixed so that they won't
-   be allocated.  On v9, also make the fp cc regs fixed.  */
+/* If !TARGET_FPU, then make the fp registers and fp cc regs fixed so that
+   they won't be allocated.  */
 
 #define CONDITIONAL_REGISTER_USAGE                             \
 do                                                             \
   {                                                            \
-    if (! TARGET_FPU)                                          \
+    if (! SPARC_ARCH64)                                                \
+      {                                                                \
+       fixed_regs[5] = 1;                                      \
+      }                                                                \
+    if (SPARC_ARCH64)                                          \
       {                                                                \
        int regno;                                              \
-       for (regno = 32; regno < FIRST_PSEUDO_REGISTER; regno++) \
-         fixed_regs[regno] = 1;                                \
+       fixed_regs[1] = 1;                                      \
+       /* ??? We need to scan argv for -fcall-used-.  */       \
+       for (regno = 48; regno < 80; regno++)                   \
+         call_used_regs[regno] = 0;                            \
       }                                                                \
-    if (! TARGET_APP_REGS)                                     \
+    if (! TARGET_V9)                                           \
       {                                                                \
-       fixed_regs[2] = 1;                                      \
-       fixed_regs[3] = 1;                                      \
-       fixed_regs[4] = 1;                                      \
+       int regno;                                              \
+       for (regno = SPARC_FIRST_V9_FP_REG;                     \
+            regno <= SPARC_LAST_V9_FP_REG;                     \
+            regno++)                                           \
+         fixed_regs[regno] = 1;                                \
+       /* %fcc0 is used by v8 and v9.  */                      \
+       for (regno = SPARC_FIRST_V9_FCC_REG + 1;                \
+            regno <= SPARC_LAST_V9_FCC_REG;                    \
+            regno++)                                           \
+         fixed_regs[regno] = 1;                                \
       }                                                                \
-    else                                                       \
+    if (! TARGET_FPU)                                          \
       {                                                                \
-       fixed_regs[2] = 0;                                      \
-       fixed_regs[3] = 0;                                      \
-       fixed_regs[4] = TARGET_MEDANY != 0;                     \
+       int regno;                                              \
+       for (regno = 32; regno < SPARC_LAST_V9_FCC_REG; regno++) \
+         fixed_regs[regno] = 1;                                \
       }                                                                \
+    /* Don't unfix g2-g4 if they were fixed with -ffixed-.  */ \
+    fixed_regs[2] |= ! TARGET_APP_REGS;                                \
+    fixed_regs[3] |= ! TARGET_APP_REGS;                                \
+    fixed_regs[4] |= ! TARGET_APP_REGS || TARGET_MEDANY;       \
     if (TARGET_FLAT)                                           \
       {                                                                \
        /* Let the compiler believe the frame pointer is still  \
@@ -663,7 +865,7 @@ while (0)
    included in the hard register count).  */
 
 #define HARD_REGNO_NREGS(REGNO, MODE) \
-  (TARGET_V9                                                           \
+  (TARGET_ARCH64                                                       \
    ?  ((REGNO) < 32                                                    \
        ? (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD  \
        : (GET_MODE_SIZE (MODE) + 3) / 4)                               \
@@ -714,7 +916,7 @@ extern int sparc_mode_class[];
 #define FRAME_POINTER_REGNUM 30
 
 #if 0
-/* Register that is used for the return address.  */
+/* Register that is used for the return address for the flat model.  */
 #define RETURN_ADDR_REGNUM 15
 #endif
 
@@ -728,8 +930,8 @@ extern int sparc_mode_class[];
    flat window model.  However, the debugger won't be able to backtrace through
    us with out it.  */
 #define FRAME_POINTER_REQUIRED \
-  (TARGET_FRW ? (current_function_calls_alloca || current_function_varargs \
-                || !leaf_function_p ()) \
+  (TARGET_FLAT ? (current_function_calls_alloca || current_function_varargs \
+                 || !leaf_function_p ()) \
    : ! (leaf_function_p () && only_leaf_regs_used ()))
 
 /* C statement to store the difference between the frame pointer
@@ -739,16 +941,15 @@ extern int sparc_mode_class[];
    it's not, there's no point in trying to eliminate the
    frame pointer.  If it is a leaf function, we guessed right!  */
 #define INITIAL_FRAME_POINTER_OFFSET(VAR) \
-  ((VAR) = (TARGET_FRW ? sparc_flat_compute_frame_size (get_frame_size ()) \
+  ((VAR) = (TARGET_FLAT ? sparc_flat_compute_frame_size (get_frame_size ()) \
            : compute_frame_size (get_frame_size (), 1)))
 
 /* Base register for access to arguments of the function.  */
 #define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM
 
 /* Register in which static-chain is passed to a function.  This must
-   not be a register used by the prologue.
-   ??? v9: Since %g2 is reserved but %g5 is available, perhaps use %g5.  */
-#define STATIC_CHAIN_REGNUM 2
+   not be a register used by the prologue.  */
+#define STATIC_CHAIN_REGNUM (TARGET_ARCH64 ? 5 : 2)
 
 /* Register which holds offset table for position-independent
    data references.  */
@@ -763,8 +964,8 @@ extern int sparc_mode_class[];
    For v9, all aggregates are returned in memory.  */
 #define RETURN_IN_MEMORY(TYPE)                         \
   (TYPE_MODE (TYPE) == BLKmode                         \
-   || (! TARGET_V9 && (TYPE_MODE (TYPE) == TFmode      \
-                      || TYPE_MODE (TYPE) == TCmode)))
+   || (! TARGET_ARCH64 && (TYPE_MODE (TYPE) == TFmode  \
+                           || TYPE_MODE (TYPE) == TCmode)))
 
 /* Functions which return large structures get the address
    to place the wanted value at offset 64 from the frame.
@@ -775,13 +976,13 @@ extern int sparc_mode_class[];
 #define STRUCT_VALUE_OFFSET 64
 
 #define STRUCT_VALUE \
-  (TARGET_V9                                           \
+  (TARGET_ARCH64                                       \
    ? 0                                                 \
    : gen_rtx (MEM, Pmode,                              \
              gen_rtx (PLUS, Pmode, stack_pointer_rtx,  \
                       gen_rtx (CONST_INT, VOIDmode, STRUCT_VALUE_OFFSET))))
 #define STRUCT_VALUE_INCOMING \
-  (TARGET_V9                                           \
+  (TARGET_ARCH64                                       \
    ? 0                                                 \
    : gen_rtx (MEM, Pmode,                              \
              gen_rtx (PLUS, Pmode, frame_pointer_rtx,  \
@@ -832,62 +1033,42 @@ extern int sparc_mode_class[];
    have a class that is the union of FPCC_REGS with either of the others,
    it is important that it appear first.  Otherwise the compiler will die
    trying to compile _fixunsdfsi because fix_truncdfsi2 won't match its
-   constraints.  */
+   constraints.
+
+   It is important that SPARC_ICC_REG have class NO_REGS.  Otherwise combine
+   may try to use it to hold an SImode value.  See register_operand.
+   ??? Should %fcc[0123] be handled similarily?
+*/
 
-#ifdef SPARCV9
 enum reg_class { NO_REGS, FPCC_REGS, GENERAL_REGS, FP_REGS, EXTRA_FP_REGS,
                 GENERAL_OR_FP_REGS, GENERAL_OR_EXTRA_FP_REGS,
                 ALL_REGS, LIM_REG_CLASSES };
-#else
-enum reg_class { NO_REGS, GENERAL_REGS, FP_REGS, ALL_REGS, LIM_REG_CLASSES };
-#endif
 
 #define N_REG_CLASSES (int) LIM_REG_CLASSES
 
 /* Give names of register classes as strings for dump file.   */
 
-#ifdef SPARCV9
 #define REG_CLASS_NAMES \
   { "NO_REGS", "FPCC_REGS", "GENERAL_REGS", "FP_REGS", "EXTRA_FP_REGS", \
     "GENERAL_OR_FP_REGS", "GENERAL_OR_EXTRA_FP_REGS", "ALL_REGS" }
-#else
-#define REG_CLASS_NAMES \
-  { "NO_REGS", "GENERAL_REGS", "FP_REGS", "ALL_REGS" }
-#endif
 
 /* Define which registers fit in which classes.
    This is an initializer for a vector of HARD_REG_SET
    of length N_REG_CLASSES.  */
 
-#ifdef SPARCV9
 #define REG_CLASS_CONTENTS \
-  {{0, 0, 0, 0}, {0, 0, 0, 0xf}, {-2, 0, 0, 0}, \
-   {0, -1, 0, 0}, {0, -1, -1, 0}, {-2, -1, 0, 0}, {-2, -1, -1, 0}, \
-   {-2, -1, -1, 0xf}}
-#else
-#if 0 && defined (__GNUC__)
-#define REG_CLASS_CONTENTS {0LL, 0xfffffffeLL, 0xffffffff00000000LL, 0xfffffffffffffffeLL}
-#else
-#define REG_CLASS_CONTENTS {{0, 0}, {-2, 0}, {0, -1}, {-2, -1}}
-#endif
-#endif
+  {{0, 0, 0, 0}, {0, 0, 0, 0xf}, \
+   {-1, 0, 0, 0}, {0, -1, 0, 0}, {0, -1, -1, 0}, \
+   {-1, -1, 0, 0}, {-1, -1, -1, 0}, {-1, -1, -1, 0x1f}}
 
 /* The same information, inverted:
    Return the class number of the smallest class containing
    reg number REGNO.  This could be a conditional expression
    or could index an array.  */
 
-#ifdef SPARCV9
-#define REGNO_REG_CLASS(REGNO) \
-  ((REGNO) == 0 ? NO_REGS              \
-   : (REGNO) < 32 ? GENERAL_REGS       \
-   : (REGNO) < 64 ? FP_REGS            \
-   : (REGNO) < 96 ? EXTRA_FP_REGS      \
-   : FPCC_REGS)
-#else
-#define REGNO_REG_CLASS(REGNO) \
-  ((REGNO) >= 32 ? FP_REGS : (REGNO) == 0 ? NO_REGS : GENERAL_REGS)
-#endif
+extern enum reg_class sparc_regno_reg_class[];
+
+#define REGNO_REG_CLASS(REGNO) sparc_regno_reg_class[(REGNO)]
 
 /* This is the order in which to allocate registers normally.  
    
@@ -896,11 +1077,11 @@ enum reg_class { NO_REGS, GENERAL_REGS, FP_REGS, ALL_REGS, LIM_REG_CLASSES };
    will get allocated to the float return register, thus saving a move
    instruction at the end of the function.
 
-   On v9, the float registers are ordered a little "funny" because some
-   of them (%f16-%f47) are call-preserved.  */
-#ifdef SPARCV9
+   The float registers are ordered a little "funny" because in the 64 bit
+   architecture, some of them (%f16-%f47) are call-preserved.  */
+
 #define REG_ALLOC_ORDER \
-{ 8, 9, 10, 11, 12, 13,                        \
+{ 8, 9, 10, 11, 12, 13, 2, 3,          \
   15, 16, 17, 18, 19, 20, 21, 22,      \
   23, 24, 25, 26, 27, 28, 29, 31,      \
   34, 35, 36, 37, 38, 39,              /* %f2-%f7 */   \
@@ -912,29 +1093,17 @@ enum reg_class { NO_REGS, GENERAL_REGS, FP_REGS, ALL_REGS, LIM_REG_CLASSES };
   64, 65, 66, 67, 68, 69, 70, 71,      /* %f32-%f39 */ \
   72, 73, 74, 75, 76, 77, 78, 79,      /* %f40-%f47 */ \
   32, 33,                              /* %f0,%f1 */   \
-  96, 97, 98, 99,                      /* %fcc0-3 */   \
-  1, 5, 2, 3, 4, 6, 7, 0, 14, 30}
-#else
-#define REG_ALLOC_ORDER \
-{ 8, 9, 10, 11, 12, 13, 2, 3,          \
-  15, 16, 17, 18, 19, 20, 21, 22,      \
-  23, 24, 25, 26, 27, 28, 29, 31,      \
-  34, 35, 36, 37, 38, 39,              \
-  40, 41, 42, 43, 44, 45, 46, 47,      \
-  48, 49, 50, 51, 52, 53, 54, 55,      \
-  56, 57, 58, 59, 60, 61, 62, 63,      \
-  32, 33,                              \
+  96, 97, 98, 99, 100,                 /* %fcc0-3, %icc */ \
   1, 4, 5, 6, 7, 0, 14, 30}
-#endif
 
 /* This is the order in which to allocate registers for
    leaf functions.  If all registers can fit in the "i" registers,
    then we have the possibility of having a leaf function.
-   v9: The floating point registers are ordered a little "funny" because some
-   of them (%f16-%f47) are call-preserved.   */
-#ifdef SPARCV9
+   The floating point registers are ordered a little "funny" because in the
+   64 bit architecture some of them (%f16-%f47) are call-preserved.   */
+
 #define REG_LEAF_ALLOC_ORDER \
-{ 24, 25, 26, 27, 28, 29,              \
+{ 2, 3, 24, 25, 26, 27, 28, 29,                \
   15, 8, 9, 10, 11, 12, 13,            \
   16, 17, 18, 19, 20, 21, 22, 23,      \
   34, 35, 36, 37, 38, 39,              \
@@ -946,20 +1115,8 @@ enum reg_class { NO_REGS, GENERAL_REGS, FP_REGS, ALL_REGS, LIM_REG_CLASSES };
   64, 65, 66, 67, 68, 69, 70, 71,      \
   72, 73, 74, 75, 76, 77, 78, 79,      \
   32, 33,                              \
-  96, 97, 98, 99,                      \
-  1, 5, 2, 3, 4, 6, 7, 0, 14, 30, 31}
-#else
-#define REG_LEAF_ALLOC_ORDER \
-{ 2, 3, 24, 25, 26, 27, 28, 29,                \
-  15, 8, 9, 10, 11, 12, 13,            \
-  16, 17, 18, 19, 20, 21, 22, 23,      \
-  34, 35, 36, 37, 38, 39,              \
-  40, 41, 42, 43, 44, 45, 46, 47,      \
-  48, 49, 50, 51, 52, 53, 54, 55,      \
-  56, 57, 58, 59, 60, 61, 62, 63,      \
-  32, 33,                              \
+  96, 97, 98, 99, 100,                 \
   1, 4, 5, 6, 7, 0, 14, 30, 31}
-#endif
 
 #define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc ()
 
@@ -968,7 +1125,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, FP_REGS, ALL_REGS, LIM_REG_CLASSES };
    register is used and is not permitted in a leaf function.  We make %g7
    a global reg if -mflat and voila.  Since %g7 is a system register and is
    fixed it won't be used by gcc anyway.  */
-#ifdef SPARCV9
+
 #define LEAF_REGISTERS \
 { 1, 1, 1, 1, 1, 1, 1, 0,      \
   0, 0, 0, 0, 0, 0, 1, 0,      \
@@ -982,18 +1139,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, FP_REGS, ALL_REGS, LIM_REG_CLASSES };
   1, 1, 1, 1, 1, 1, 1, 1,      \
   1, 1, 1, 1, 1, 1, 1, 1,      \
   1, 1, 1, 1, 1, 1, 1, 1,      \
-  1, 1, 1, 1}
-#else
-#define LEAF_REGISTERS \
-{ 1, 1, 1, 1, 1, 1, 1, 0,      \
-  0, 0, 0, 0, 0, 0, 1, 0,      \
-  0, 0, 0, 0, 0, 0, 0, 0,      \
-  1, 1, 1, 1, 1, 1, 0, 1,      \
-  1, 1, 1, 1, 1, 1, 1, 1,      \
-  1, 1, 1, 1, 1, 1, 1, 1,      \
-  1, 1, 1, 1, 1, 1, 1, 1,      \
-  1, 1, 1, 1, 1, 1, 1, 1}
-#endif
+  1, 1, 1, 1, 1}
 
 extern char leaf_reg_remap[];
 #define LEAF_REG_REMAP(REGNO) (leaf_reg_remap[REGNO])
@@ -1003,26 +1149,22 @@ extern char leaf_reg_remap[];
 #define BASE_REG_CLASS GENERAL_REGS
 
 /* Local macro to handle the two v9 classes of FP regs.  */
-#ifdef SPARCV9
 #define FP_REG_CLASS_P(CLASS) ((CLASS) == FP_REGS || (CLASS) == EXTRA_FP_REGS)
-#else
-#define FP_REG_CLASS_P(CLASS) ((CLASS) == FP_REGS)
-#endif
 
-/* Get reg_class from a letter such as appears in the machine description.  */
+/* Get reg_class from a letter such as appears in the machine description.
+   In the not-v9 case, coerce v9's 'e' class to 'f', so we can use 'e' in the
+   .md file for v8 and v9.  */
 
-#ifdef SPARCV9
 #define REG_CLASS_FROM_LETTER(C) \
-  ((C) == 'f' ? FP_REGS                \
-   : (C) == 'e' ? EXTRA_FP_REGS        \
-   : (C) == 'c' ? FPCC_REGS    \
-   : NO_REGS)
-#else
-/* Coerce v9's 'e' class to 'f', so we can use 'e' in the .md file for
-   v8 and v9.  */
-#define REG_CLASS_FROM_LETTER(C) \
-  ((C) == 'f' ? FP_REGS : (C) == 'e' ? FP_REGS : NO_REGS)
-#endif
+(TARGET_V9                     \
+ ? ((C) == 'f' ? FP_REGS       \
+    : (C) == 'e' ? EXTRA_FP_REGS \
+    : (C) == 'c' ? FPCC_REGS   \
+    : NO_REGS)                 \
+ : ((C) == 'f' ? FP_REGS       \
+    : (C) == 'e' ? FP_REGS     \
+    : (C) == 'c' ? FPCC_REGS   \
+    : NO_REGS))
 
 /* The letters I, J, K, L and M in a register constraint string
    can be used to stand for particular ranges of immediate operands.
@@ -1030,17 +1172,25 @@ extern char leaf_reg_remap[];
    C is the letter, and VALUE is a constant value.
    Return 1 if VALUE is in the range specified by C.
 
-   For SPARC, `I' is used for the range of constants an insn
-   can actually contain.
+   `I' is used for the range of constants an insn can actually contain.
    `J' is used for the range which is just zero (since that is R0).
-   `K' is used for constants which can be loaded with a single sethi insn.  */
+   `K' is used for constants which can be loaded with a single sethi insn.
+   `L' is used for the range of constants supported by the movcc insns.
+   `M' is used for the range of constants supported by the movrcc insns.  */
 
-#define SMALL_INT(X) ((unsigned) (INTVAL (X) + 0x1000) < 0x2000)
+#define SPARC_SIMM10_P(X) ((unsigned HOST_WIDE_INT) ((X) + 0x200) < 0x400)
+#define SPARC_SIMM11_P(X) ((unsigned HOST_WIDE_INT) ((X) + 0x400) < 0x800)
+#define SPARC_SIMM13_P(X) ((unsigned HOST_WIDE_INT) ((X) + 0x1000) < 0x2000)
+/* 10 and 11 bit immediates are only used for a few specific insns.
+   SMALL_INT is used throughout the port so we continue to use it.  */
+#define SMALL_INT(X) (SPARC_SIMM13_P (INTVAL (X)))
 
 #define CONST_OK_FOR_LETTER_P(VALUE, C)  \
-  ((C) == 'I' ? (unsigned) ((VALUE) + 0x1000) < 0x2000 \
+  ((C) == 'I' ? SPARC_SIMM13_P (VALUE)                 \
    : (C) == 'J' ? (VALUE) == 0                         \
    : (C) == 'K' ? ((VALUE) & 0x3ff) == 0               \
+   : (C) == 'L' ? SPARC_SIMM11_P (VALUE)               \
+   : (C) == 'M' ? SPARC_SIMM10_P (VALUE)               \
    : 0)
 
 /* Similar, but for floating constants, and defining letters G and H.
@@ -1106,7 +1256,7 @@ extern char leaf_reg_remap[];
    because the movsi and movsf patterns don't handle r/f moves.
    For v8 we copy the default definition.  */
 #define SECONDARY_MEMORY_NEEDED_MODE(MODE) \
-  (TARGET_V9                                                   \
+  (TARGET_ARCH64                                               \
    ? (GET_MODE_BITSIZE (MODE) < 32                             \
       ? mode_for_size (32, GET_MODE_CLASS (MODE), 0)           \
       : MODE)                                                  \
@@ -1130,7 +1280,7 @@ extern char leaf_reg_remap[];
    v9: Non-float args are passed in %o0-5 and float args are passed in
    %f0-%f15.  */
 #define NPARM_REGS(MODE) \
-  (TARGET_V9 ? (GET_MODE_CLASS (MODE) == MODE_FLOAT ? 16 : 6) : 6)
+  (TARGET_ARCH64 ? (GET_MODE_CLASS (MODE) == MODE_FLOAT ? 16 : 6) : 6)
 
 /* Define this if pushing a word on the stack
    makes the stack pointer a smaller address.  */
@@ -1148,7 +1298,7 @@ extern char leaf_reg_remap[];
    of the first local allocated.  */
 /* This allows space for one TFmode floating point value.  */
 #define STARTING_FRAME_OFFSET \
-  (TARGET_V9 ? (SPARC_STACK_BIAS - 16) \
+  (TARGET_ARCH64 ? (SPARC_STACK_BIAS - 16) \
    : (-SPARC_STACK_ALIGN (LONG_DOUBLE_TYPE_SIZE / BITS_PER_UNIT)))
 
 /* If we generate an insn to push BYTES bytes,
@@ -1161,12 +1311,12 @@ extern char leaf_reg_remap[];
    even if this function isn't going to use it.
    v9: This is 128 for the ins and locals, plus a reserved space of 8.  */
 #define FIRST_PARM_OFFSET(FNDECL) \
-  (TARGET_V9 ? (SPARC_STACK_BIAS + 136) \
+  (TARGET_ARCH64 ? (SPARC_STACK_BIAS + 136) \
    : (STRUCT_VALUE_OFFSET + UNITS_PER_WORD))
 
 /* When a parameter is passed in a register, stack space is still
    allocated for it.  */
-#ifndef SPARCV9
+#if ! SPARC_ARCH64
 #define REG_PARM_STACK_SPACE(DECL) (NPARM_REGS (SImode) * UNITS_PER_WORD)
 #endif
 
@@ -1189,20 +1339,24 @@ extern char leaf_reg_remap[];
    When !TARGET_FPU, put float return values in the general registers,
    since we don't have any fp registers.  */
 #define BASE_RETURN_VALUE_REG(MODE) \
-  (TARGET_V9 ? (TARGET_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 : 8) \
+  (TARGET_ARCH64 \
+   ? (TARGET_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 : 8) \
    : (((MODE) == SFmode || (MODE) == DFmode) && TARGET_FPU ? 32 : 8))
 #define BASE_OUTGOING_VALUE_REG(MODE) \
-  (TARGET_V9 ? (TARGET_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 \
-               : TARGET_FRW ? 8 : 24) \
+  (TARGET_ARCH64 \
+   ? (TARGET_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 \
+      : TARGET_FLAT ? 8 : 24) \
    : (((MODE) == SFmode || (MODE) == DFmode) && TARGET_FPU ? 32        \
-      : (TARGET_FRW ? 8 : 24)))
+      : (TARGET_FLAT ? 8 : 24)))
 #define BASE_PASSING_ARG_REG(MODE) \
-  (TARGET_V9 ? (TARGET_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 : 8) \
-   : (8))
+  (TARGET_ARCH64 \
+   ? (TARGET_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 : 8) \
+   : 8)
 #define BASE_INCOMING_ARG_REG(MODE) \
-  (TARGET_V9 ? (TARGET_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 \
-               : TARGET_FRW ? 8 : 24) \
-   : (TARGET_FRW ? 8 : 24))
+  (TARGET_ARCH64 \
+   ? (TARGET_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 \
+      : TARGET_FLAT ? 8 : 24) \
+   : (TARGET_FLAT ? 8 : 24))
 
 /* Define this macro if the target machine has "register windows".  This
    C expression returns the register number as seen by the called function
@@ -1210,7 +1364,7 @@ extern char leaf_reg_remap[];
    Return OUT if register number OUT is not an outbound register.  */
 
 #define INCOMING_REGNO(OUT) \
- ((TARGET_FRW || (OUT) < 8 || (OUT) > 15) ? (OUT) : (OUT) + 16)
+ ((TARGET_FLAT || (OUT) < 8 || (OUT) > 15) ? (OUT) : (OUT) + 16)
 
 /* Define this macro if the target machine has "register windows".  This
    C expression returns the register number as seen by the calling function
@@ -1218,7 +1372,7 @@ extern char leaf_reg_remap[];
    Return IN if register number IN is not an inbound register.  */
 
 #define OUTGOING_REGNO(IN) \
- ((TARGET_FRW || (IN) < 24 || (IN) > 31) ? (IN) : (IN) - 16)
+ ((TARGET_FLAT || (IN) < 24 || (IN) > 31) ? (IN) : (IN) - 16)
 
 /* Define how to find the value returned by a function.
    VALTYPE is the data type of the value (as a tree).
@@ -1257,7 +1411,7 @@ extern char leaf_reg_remap[];
    On SPARC, these are the "output" registers.  v9 also uses %f0-%f15.  */
 
 #define FUNCTION_ARG_REGNO_P(N) \
-  (TARGET_V9 ? (((N) < 14 && (N) > 7) || (N) > 31 && (N) < 48) \
+  (TARGET_ARCH64 ? (((N) < 14 && (N) > 7) || (N) > 31 && (N) < 48) \
    : ((N) < 14 && (N) > 7))
 \f
 /* Define a data type for recording info about an argument list
@@ -1291,7 +1445,7 @@ extern char leaf_reg_remap[];
           allocated like all other arguments.
        - The unimp instruction stuff for structure returns is gone.  */
 
-#ifdef SPARCV9
+#if SPARC_ARCH64
 enum sparc_arg_class { SPARC_ARG_INT = 0, SPARC_ARG_FLOAT = 1 };
 struct sparc_args {
     int arg_count[2];  /* must be int! (for __builtin_args_info) */
@@ -1318,14 +1472,15 @@ struct sparc_args {
 #define ROUND_ADVANCE(SIZE)    \
   (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-#else /* ! SPARCV9 */
+#else /* ! SPARC_ARCH64 */
+
 #define CUMULATIVE_ARGS int
 
 #define ROUND_REG(CUM, MODE) (CUM)
 
 #define ROUND_ADVANCE(SIZE)    \
   ((SIZE + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-#endif /* ! SPARCV9 */
+#endif /* ! SPARC_ARCH64 */
 
 /* Initialize a variable CUM of type CUMULATIVE_ARGS
    for a call to a function whose data type is FNTYPE.
@@ -1334,9 +1489,9 @@ struct sparc_args {
    On SPARC, the offset always starts at 0: the first parm reg is always
    the same reg.  */
 
-#ifdef SPARCV9
+#if SPARC_ARCH64
 extern int sparc_arg_count,sparc_n_named_args;
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME)               \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT)      \
   do {                                                         \
     (CUM).arg_count[(int) SPARC_ARG_INT] = 0;                  \
     (CUM).arg_count[(int) SPARC_ARG_FLOAT] = 0;                        \
@@ -1345,19 +1500,21 @@ extern int sparc_arg_count,sparc_n_named_args;
       ((FNTYPE) && TYPE_ARG_TYPES (FNTYPE)                     \
        ? (list_length (TYPE_ARG_TYPES (FNTYPE))                        \
          + (TREE_CODE (TREE_TYPE (FNTYPE)) == RECORD_TYPE      \
+            || TREE_CODE (TREE_TYPE (FNTYPE)) == QUAL_UNION_TYPE\
+            || TREE_CODE (TREE_TYPE (FNTYPE)) == SET_TYPE      \
             || TREE_CODE (TREE_TYPE (FNTYPE)) == UNION_TYPE))  \
        /* Can't tell, treat 'em all as named.  */              \
        : 10000);                                               \
   } while (0)
 #else
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) ((CUM) = 0)
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) ((CUM) = 0)
 #endif
 
 /* Update the data in CUM to advance over an argument
    of mode MODE and data type TYPE.
    (TYPE is null for libcalls where that information may not be available.)  */
 
-#ifdef SPARCV9
+#if SPARC_ARCH64
 #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)           \
   do {                                                         \
     (CUM).arg_count[(int) GET_SPARC_ARG_CLASS (MODE)] =                \
@@ -1379,7 +1536,7 @@ extern int sparc_arg_count,sparc_n_named_args;
 /* Return boolean indicating arg of mode MODE will be passed in a reg.
    This macro is only used in this file.  */
 
-#ifdef SPARCV9
+#if SPARC_ARCH64
 #define PASS_IN_REG_P(CUM, MODE, TYPE)                         \
   (ROUND_REG ((CUM), (MODE)) < NPARM_REGS (MODE)               \
    && ((TYPE)==0 || ! TREE_ADDRESSABLE ((tree)(TYPE)))         \
@@ -1435,7 +1592,7 @@ extern int sparc_arg_count,sparc_n_named_args;
    needs partial registers on the Sparc (!v9).  On v9, there are no arguments
    that are passed partially in registers (??? complex values?).  */
 
-#ifndef SPARCV9
+#if ! SPARC_ARCH64
 #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED)             \
   (PASS_IN_REG_P ((CUM), (MODE), (TYPE))                               \
    && ((CUM) + ((MODE) == BLKmode                                      \
@@ -1448,11 +1605,9 @@ extern int sparc_arg_count,sparc_n_named_args;
 /* The SPARC ABI stipulates passing struct arguments (of any size) and
    (!v9) quad-precision floats by invisible reference.
    For Pascal, also pass arrays by reference.  */
-#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED)         \
-  ((TYPE && (TREE_CODE (TYPE) == RECORD_TYPE                           \
-           || TREE_CODE (TYPE) == UNION_TYPE                           \
-           || TREE_CODE (TYPE) == ARRAY_TYPE))                         \
-   || (!TARGET_V9 && MODE == TFmode))
+#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
+  ((TYPE && AGGREGATE_TYPE_P (TYPE))                           \
+   || (!TARGET_ARCH64 && MODE == TFmode))
 
 /* A C expression that indicates when it is the called function's
    responsibility to make copies of arguments passed by reference.
@@ -1461,7 +1616,7 @@ extern int sparc_arg_count,sparc_n_named_args;
 /* ??? We'd love to be able to use NAMED here.  Unfortunately, it doesn't
    include the last named argument so we keep track of the args ourselves.  */
 
-#ifdef SPARCV9
+#if SPARC_ARCH64
 #define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \
   (sparc_arg_count < sparc_n_named_args)
 #endif
@@ -1475,7 +1630,7 @@ extern int sparc_arg_count,sparc_n_named_args;
 
 extern void sparc64_init_expanders ();
 extern struct rtx_def *sparc64_fpconv_stack_temp ();
-#ifdef SPARCV9
+#if SPARC_ARCH64
 #define INIT_EXPANDERS sparc64_init_expanders ()
 #endif
 
@@ -1528,54 +1683,376 @@ do {                                                                   \
    to do this is made in regclass.c.  */
 
 extern int leaf_function;
-#define FUNCTION_PROLOGUE(FILE, SIZE)                          \
-  (TARGET_FRW ? sparc_flat_output_function_prologue (FILE, SIZE) \
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+  (TARGET_FLAT ? sparc_flat_output_function_prologue (FILE, SIZE) \
    : output_function_prologue (FILE, SIZE, leaf_function))
-
+\f
 /* Output assembler code to FILE to increment profiler label # LABELNO
-   for profiling a function entry.  */
+   for profiling a function entry.
+
+   32 bit sparc uses %g2 as the STATIC_CHAIN_REGNUM which gets clobbered
+   during profiling so we need to save/restore it around the call to mcount.
+   We're guaranteed that a save has just been done, and we use the space
+   allocated for intreg/fpreg value passing.  */
 
 #define FUNCTION_PROFILER(FILE, LABELNO)                       \
   do {                                                         \
-    fputs ("\tsethi %hi(", (FILE));                            \
-    ASM_OUTPUT_INTERNAL_LABELREF (FILE, "LP", LABELNO);                \
-    fputs ("),%o0\n", (FILE));                                 \
+    char buf[20];                                              \
+    ASM_GENERATE_INTERNAL_LABEL (buf, "LP", (LABELNO));                \
+    if (! TARGET_ARCH64)                                       \
+      fputs ("\tst %g2,[%fp-4]\n", FILE);                      \
+    fputs ("\tsethi %hi(", FILE);                              \
+    assemble_name (FILE, buf);                                 \
+    fputs ("),%o0\n", FILE);                                   \
     if (TARGET_MEDANY)                                         \
-      fprintf (FILE, "\tadd %%o0,%s,%%o0\n",                   \
-              MEDANY_BASE_REG);                                \
-    fputs ("\tcall mcount\n\tadd %lo(", (FILE));               \
-    ASM_OUTPUT_INTERNAL_LABELREF (FILE, "LP", LABELNO);                \
-    fputs ("),%o0,%o0\n", (FILE));                             \
+      fprintf (FILE, "\tadd %o0,%s,%o0\n", MEDANY_BASE_REG);   \
+    fputs ("\tcall mcount\n\tadd %o0,%lo(", FILE);             \
+    assemble_name (FILE, buf);                                 \
+    fputs ("),%o0\n", FILE);                                   \
+    if (! TARGET_ARCH64)                                       \
+      fputs ("\tld [%fp-4],%g2\n", FILE);                      \
   } while (0)
 
-/* Output assembler code to FILE to initialize this source file's
-   basic block profiling info, if that has not already been done.  */
-
-#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO)  \
-  do { \
-    if (TARGET_MEDANY) \
-      fprintf (FILE, "\tsethi %%hi(LPBX0),%%o0\n\tor %%0,%%lo(LPBX0),%%o0\n\tld [%s+%%o0],%%o1\n\ttst %%o1\n\tbne LPY%d\n\tadd %%o0,%s,%%o0\n\tcall ___bb_init_func\n\tnop\nLPY%d:\n", \
-              MEDANY_BASE_REG, (LABELNO), MEDANY_BASE_REG, (LABELNO)); \
-    else \
-      fprintf (FILE, "\tsethi %%hi(LPBX0),%%o0\n\tld [%%lo(LPBX0)+%%o0],%%o1\n\ttst %%o1\n\tbne LPY%d\n\tadd %%o0,%%lo(LPBX0),%%o0\n\tcall ___bb_init_func\n\tnop\nLPY%d:\n", \
-              (LABELNO), (LABELNO)); \
-  } while (0)
+/* There are three profiling modes for basic blocks available.
+   The modes are selected at compile time by using the options
+   -a or -ax of the gnu compiler.
+   The variable `profile_block_flag' will be set according to the
+   selected option.
+
+   profile_block_flag == 0, no option used:
+
+      No profiling done.
+
+   profile_block_flag == 1, -a option used.
+
+      Count frequency of execution of every basic block.
+
+   profile_block_flag == 2, -ax option used.
+
+      Generate code to allow several different profiling modes at run time. 
+      Available modes are:
+             Produce a trace of all basic blocks.
+             Count frequency of jump instructions executed.
+      In every mode it is possible to start profiling upon entering
+      certain functions and to disable profiling of some other functions.
+
+    The result of basic-block profiling will be written to a file `bb.out'.
+    If the -ax option is used parameters for the profiling will be read
+    from file `bb.in'.
+
+*/
+
+/* The following macro shall output assembler code to FILE
+   to initialize basic-block profiling.
+
+   If profile_block_flag == 2
+
+       Output code to call the subroutine `__bb_init_trace_func'
+       and pass two parameters to it. The first parameter is
+       the address of a block allocated in the object module.
+       The second parameter is the number of the first basic block
+       of the function.
+
+       The name of the block is a local symbol made with this statement:
+       
+           ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0);
+
+       Of course, since you are writing the definition of
+       `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you
+       can take a short cut in the definition of this macro and use the
+       name that you know will result.
+
+       The number of the first basic block of the function is
+       passed to the macro in BLOCK_OR_LABEL.
+
+       If described in a virtual assembler language the code to be
+       output looks like:
+
+               parameter1 <- LPBX0
+               parameter2 <- BLOCK_OR_LABEL
+               call __bb_init_trace_func
+
+    else if profile_block_flag != 0
+
+       Output code to call the subroutine `__bb_init_func'
+       and pass one single parameter to it, which is the same
+       as the first parameter to `__bb_init_trace_func'.
+
+       The first word of this parameter is a flag which will be nonzero if
+       the object module has already been initialized.  So test this word
+       first, and do not call `__bb_init_func' if the flag is nonzero.
+       Note: When profile_block_flag == 2 the test need not be done
+       but `__bb_init_trace_func' *must* be called.
+
+       BLOCK_OR_LABEL may be used to generate a label number as a
+       branch destination in case `__bb_init_func' will not be called.
+
+       If described in a virtual assembler language the code to be
+       output looks like:
+
+               cmp (LPBX0),0
+               jne local_label
+               parameter1 <- LPBX0
+               call __bb_init_func
+local_label:
+
+*/
+
+#define FUNCTION_BLOCK_PROFILER(FILE, BLOCK_OR_LABEL)  \
+do                                                     \
+  {                                                    \
+    int bol = (BLOCK_OR_LABEL);                                \
+    switch (profile_block_flag)                                \
+      {                                                        \
+      case 2:                                          \
+        if (TARGET_MEDANY)                             \
+          fprintf (FILE, "\tsethi %%hi(LPBX0),%%o0\n\tor %%0,%%lo(LPBX0),%%o0\n\tadd %%o0,%s,%%o0\n\tsethi %%hi(%d),%%o1\n\tcall ___bb_init_trace_func\n\tadd %g0,%%lo(%d),%%o1\n",\
+                   MEDANY_BASE_REG, bol, bol);         \
+        else                                           \
+          fprintf (FILE, "\tsethi %%hi(LPBX0),%%o0\n\tor %%o0,%%lo(LPBX0),%%o0\n\tsethi %%hi(%d),%%o1\n\tcall ___bb_init_trace_func\n\tor %%o1,%%lo(%d),%%o1\n",\
+                   bol, bol);                          \
+        break;                                         \
+      default:                                         \
+        if (TARGET_MEDANY)                             \
+          fprintf (FILE, "\tsethi %%hi(LPBX0),%%o0\n\tor %%0,%%lo(LPBX0),%%o0\n\tld [%s+%%o0],%%o1\n\ttst %%o1\n\tbne LPY%d\n\tadd %%o0,%s,%%o0\n\tcall ___bb_init_func\n\tnop\nLPY%d:\n",\
+                   MEDANY_BASE_REG, bol, MEDANY_BASE_REG, bol);\
+        else                                           \
+          fprintf (FILE, "\tsethi %%hi(LPBX0),%%o0\n\tld [%%lo(LPBX0)+%%o0],%%o1\n\ttst %%o1\n\tbne LPY%d\n\tadd %%o0,%%lo(LPBX0),%%o0\n\tcall ___bb_init_func\n\tnop\nLPY%d:\n",\
+                   bol, bol);                          \
+        break;                                         \
+      }                                                        \
+  }                                                    \
+while (0)
 
-/* Output assembler code to FILE to increment the entry-count for
-   the BLOCKNO'th basic block in this source file.  */
-
-#define BLOCK_PROFILER(FILE, BLOCKNO) \
-{ \
-  int blockn = (BLOCKNO); \
-  if (TARGET_MEDANY) \
-    fprintf (FILE, "\tsethi %%hi(LPBX2+%d),%%g1\n\tor %%g1,%%lo(LPBX2+%d),%%g1\n\tld [%%g1+%s],%%g2\n\tadd %%g2,1,%%g2\n\tst %%g2,[%%g1+%s]\n", \
-            4 * blockn, 4 * blockn, MEDANY_BASE_REG, MEDANY_BASE_REG); \
-  else \
-    fprintf (FILE, "\tsethi %%hi(LPBX2+%d),%%g1\n\tld [%%lo(LPBX2+%d)+%%g1],%%g2\n\
+/* The following macro shall output assembler code to FILE
+   to increment a counter associated with basic block number BLOCKNO.
+
+   If profile_block_flag == 2
+
+       Output code to initialize the global structure `__bb' and
+       call the function `__bb_trace_func' which will increment the
+       counter.
+
+       `__bb' consists of two words. In the first word the number
+       of the basic block has to be stored. In the second word
+       the address of a block allocated in the object module 
+       has to be stored.
+
+       The basic block number is given by BLOCKNO.
+
+       The address of the block is given by the label created with 
+
+           ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0);
+
+       by FUNCTION_BLOCK_PROFILER.
+
+       Of course, since you are writing the definition of
+       `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you
+       can take a short cut in the definition of this macro and use the
+       name that you know will result.
+
+       If described in a virtual assembler language the code to be
+       output looks like:
+
+               move BLOCKNO -> (__bb)
+               move LPBX0 -> (__bb+4)
+               call __bb_trace_func
+
+       Note that function `__bb_trace_func' must not change the
+       machine state, especially the flag register. To grant
+       this, you must output code to save and restore registers
+       either in this macro or in the macros MACHINE_STATE_SAVE
+       and MACHINE_STATE_RESTORE. The last two macros will be
+       used in the function `__bb_trace_func', so you must make
+       sure that the function prologue does not change any 
+       register prior to saving it with MACHINE_STATE_SAVE.
+
+   else if profile_block_flag != 0
+
+       Output code to increment the counter directly.
+       Basic blocks are numbered separately from zero within each
+       compiled object module. The count associated with block number
+       BLOCKNO is at index BLOCKNO in an array of words; the name of 
+       this array is a local symbol made with this statement:
+
+           ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 2);
+
+       Of course, since you are writing the definition of
+       `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you
+       can take a short cut in the definition of this macro and use the
+       name that you know will result. 
+
+       If described in a virtual assembler language, the code to be
+       output looks like:
+
+               inc (LPBX2+4*BLOCKNO)
+
+*/
+
+#define BLOCK_PROFILER(FILE, BLOCKNO)  \
+do                                     \
+  {                                    \
+    int blockn = (BLOCKNO);            \
+    switch (profile_block_flag)                \
+      {                                        \
+      case 2:                          \
+        if (TARGET_MEDANY)             \
+          fprintf (FILE, "\tsethi %%hi(___bb),%%g1\n\tor %%0,%%lo(___bb),%%g1\n\tsethi %%hi(%d),%%g2\n\tor %%g2,%%lo(%d),%%g2\n\tst %%g2,[%s+%%g1]\n\tsethi %%hi(LPBX0),%%g2\n\tor %%0,%%lo(LPBX0),%%g2\n\tadd %%g2,%s,%%g2\n\tadd 4,%%g1,%%g1\n\tst %%g2,[%%g1+%%lo(___bb)]\n\tmov %%o7,%%g2\n\tcall ___bb_trace_func\n\tnop\n\tmov %%g2,%%o7\n",\
+                   blockn, blockn, MEDANY_BASE_REG, MEDANY_BASE_REG); \
+        else                           \
+          fprintf (FILE, "\tsethi %%hi(___bb),%%g1\n\tsethi %%hi(%d),%%g2\n\tor %%g2,%%lo(%d),%%g2\n\tst %%g2,[%%lo(___bb)+%%g1]\n\tsethi %%hi(LPBX0),%%g2\n\tor %%g2,%%lo(LPBX0),%%g2\n\tadd 4,%%g1,%%g1\n\tst %%g2,[%%lo(___bb)+%%g1]\n\tmov %%o7,%%g2\n\tcall ___bb_trace_func\n\tnop\n\tmov %%g2,%%o7\n",\
+                   blockn, blockn); \
+        break;                         \
+      default:                         \
+        if (TARGET_MEDANY)             \
+          fprintf (FILE, "\tsethi %%hi(LPBX2+%d),%%g1\n\tor %%g1,%%lo(LPBX2+%d),%%g1\n\tld [%%g1+%s],%%g2\n\tadd %%g2,1,%%g2\n\tst %%g2,[%%g1+%s]\n", \
+                         4 * blockn, 4 * blockn, MEDANY_BASE_REG, MEDANY_BASE_REG); \
+        else                           \
+          fprintf (FILE, "\tsethi %%hi(LPBX2+%d),%%g1\n\tld [%%lo(LPBX2+%d)+%%g1],%%g2\n\
 \tadd %%g2,1,%%g2\n\tst %%g2,[%%lo(LPBX2+%d)+%%g1]\n", \
-            4 * blockn, 4 * blockn, 4 * blockn); \
-}
-
+                   4 * blockn, 4 * blockn, 4 * blockn); \
+        break;                         \
+      }                                        \
+  }                                    \
+while(0)
+
+/* The following macro shall output assembler code to FILE
+   to indicate a return from function during basic-block profiling.
+
+   If profiling_block_flag == 2:
+
+       Output assembler code to call function `__bb_trace_ret'.
+
+       Note that function `__bb_trace_ret' must not change the
+       machine state, especially the flag register. To grant
+       this, you must output code to save and restore registers
+       either in this macro or in the macros MACHINE_STATE_SAVE_RET
+       and MACHINE_STATE_RESTORE_RET. The last two macros will be
+       used in the function `__bb_trace_ret', so you must make
+       sure that the function prologue does not change any 
+       register prior to saving it with MACHINE_STATE_SAVE_RET.
+
+   else if profiling_block_flag != 0:
+
+       The macro will not be used, so it need not distinguish
+       these cases.
+*/
+
+#define FUNCTION_BLOCK_PROFILER_EXIT(FILE) \
+  fprintf (FILE, "\tcall ___bb_trace_ret\n\tnop\n" );
+
+/* The function `__bb_trace_func' is called in every basic block
+   and is not allowed to change the machine state. Saving (restoring)
+   the state can either be done in the BLOCK_PROFILER macro,
+   before calling function (rsp. after returning from function)
+   `__bb_trace_func', or it can be done inside the function by
+   defining the macros:
+
+       MACHINE_STATE_SAVE(ID)
+       MACHINE_STATE_RESTORE(ID)
+
+   In the latter case care must be taken, that the prologue code
+   of function `__bb_trace_func' does not already change the
+   state prior to saving it with MACHINE_STATE_SAVE.
+
+   The parameter `ID' is a string identifying a unique macro use.
+
+   On sparc it is sufficient to save the psw register to memory.
+   Unfortunately the psw register can be read in supervisor mode only,
+   so we read only the condition codes by using branch instructions
+   and hope that this is enough. */
+
+#define MACHINE_STATE_SAVE(ID) \
+  asm ("       mov %g0,%l0");\
+  asm ("       be,a LFLGNZ" ID);\
+  asm ("       or %l0,4,%l0");\
+  asm ("LFLGNZ" ID ":  bcs,a LFLGNC" ID);\
+  asm ("       or %l0,1,%l0");\
+  asm ("LFLGNC" ID ":  bvs,a LFLGNV" ID);\
+  asm ("       or %l0,2,%l0");\
+  asm ("LFLGNV" ID ":  bneg,a LFLGNN" ID);\
+  asm ("       or %l0,8,%l0");\
+  asm ("LFLGNN" ID ": sethi %hi(LFLAGS" ID "),%l1");\
+  asm ("       st %l0,[%l1+%lo(LFLAGS" ID ")]"); \
+  asm ("       st %g2,[%l1+%lo(LSAVRET" ID ")]");
+
+/* On sparc MACHINE_STATE_RESTORE restores the psw register from memory.
+   The psw register can be written in supervisor mode only,
+   which is true even for simple condition codes.
+   We use some combination of instructions to produce the
+   proper condition codes, but some flag combinations can not
+   be generated in this way. If this happens an unimplemented
+   instruction will be executed to abort the program. */
+
+#define MACHINE_STATE_RESTORE(ID) \
+  asm ("       sethi %hi(LFLGTAB" ID "),%l1");\
+  asm ("       ld [%l1+%lo(LFLGTAB" ID "-(LFLGTAB" ID "-LFLAGS" ID "))],%l0");\
+  asm ("       ld [%l1+%lo(LFLGTAB" ID "-(LFLGTAB" ID "-LSAVRET" ID "))],%g2");\
+  asm ("       sll %l0,2,%l0");\
+  asm ("       add %l0,%l1,%l0");\
+  asm ("       ld [%l0+%lo(LFLGTAB" ID ")],%l1");\
+  asm ("       jmp %l1");\
+  asm (" nop");\
+  asm (".data");\
+  asm ("       .align 4");\
+  asm ("LFLAGS" ID ":");\
+  asm ("       .word 0");\
+  asm ("LSAVRET" ID ":");\
+  asm (" .word 0");\
+  asm ("LFLGTAB" ID ": ");\
+  asm ("       .word LSFLG0" ID);\
+  asm ("       .word LSFLGC" ID);\
+  asm ("       .word LSFLGV" ID);\
+  asm ("       .word LSFLGVC" ID);\
+  asm ("       .word LSFLGZ" ID);\
+  asm ("       .word LSFLGZC" ID);\
+  asm ("       .word LSFLGZV" ID);\
+  asm ("       .word LSFLGZVC" ID);\
+  asm ("       .word LSFLGN" ID);\
+  asm ("       .word LSFLGNC" ID);\
+  asm ("       .word LSFLGNV" ID);\
+  asm ("       .word LSFLGNVC" ID);\
+  asm ("       .word LSFLGNZ" ID);\
+  asm ("       .word LSFLGNZC" ID);\
+  asm ("       .word LSFLGNZV" ID);\
+  asm ("       .word LSFLGNZVC" ID);\
+  asm (".text");\
+  asm ("LSFLGVC" ID ": mov -1,%l0");\
+  asm ("       addcc 2,%l0,%g0");\
+  asm ("       sethi %hi(0x80000000),%l0");\
+  asm ("       mov %l0,%l1");\
+  asm ("       ba LFLGRET" ID);\
+  asm ("       addxcc %l0,%l1,%l0");\
+  asm ("LSFLGC" ID ":  mov -1,%l0");\
+  asm ("       ba LFLGRET" ID);\
+  asm ("       addcc 2,%l0,%g0");\
+  asm ("LSFLGZC" ID ": mov -1,%l0");\
+  asm ("       ba LFLGRET" ID);\
+  asm ("       addcc 1,%l0,%l0");\
+  asm ("LSFLGZVC" ID ": sethi %hi(0x80000000),%l0");\
+  asm ("       mov %l0,%l1");\
+  asm ("       ba LFLGRET" ID);\
+  asm ("       addcc %l0,%l1,%l0");\
+  asm ("LSFLGZ" ID ":  ba LFLGRET" ID);\
+  asm ("       subcc %g0,%g0,%g0");\
+  asm ("LSFLGNC" ID ": add %g0,1,%l0");\
+  asm ("       ba LFLGRET" ID);\
+  asm ("       subcc %g0,%l0,%g0");\
+  asm ("LSFLG0" ID ":  ba LFLGRET" ID);\
+  asm ("       orcc 1,%g0,%g0");\
+  asm ("LSFLGN" ID ":  ba LFLGRET" ID);\
+  asm (" orcc -1,%g0,%g0");\
+  asm ("LSFLGV" ID ":");\
+  asm ("LSFLGZV" ID ":");\
+  asm ("LSFLGNV" ID ":");\
+  asm ("LSFLGNVC" ID ":");\
+  asm ("LSFLGNZ" ID ":");\
+  asm ("LSFLGNZC" ID ":");\
+  asm ("LSFLGNZV" ID ":");\
+  asm ("LSFLGNZVC" ID ":");\
+  asm ("       unimp");\
+  asm ("LFLGRET" ID ":");
+\f
 /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
    the stack pointer does not matter.  The value is tested only in
    functions that have frame pointers.
@@ -1603,37 +2080,67 @@ extern int current_function_outgoing_args_size;
    because they occur inside of macros.  Sigh.  */
 extern union tree_node *current_function_decl;
 
-#define FUNCTION_EPILOGUE(FILE, SIZE)                          \
-  (TARGET_FRW ? sparc_flat_output_function_epilogue (FILE, SIZE) \
+#define FUNCTION_EPILOGUE(FILE, SIZE) \
+  (TARGET_FLAT ? sparc_flat_output_function_epilogue (FILE, SIZE) \
    : output_function_epilogue (FILE, SIZE, leaf_function))
 
-#define DELAY_SLOTS_FOR_EPILOGUE       \
-  (TARGET_FRW ? sparc_flat_epilogue_delay_slots () : 1)
-#define ELIGIBLE_FOR_EPILOGUE_DELAY(trial, slots_filled)       \
-  (TARGET_FRW ? sparc_flat_eligible_for_epilogue_delay (trial, slots_filled) \
+#define DELAY_SLOTS_FOR_EPILOGUE \
+  (TARGET_FLAT ? sparc_flat_epilogue_delay_slots () : 1)
+#define ELIGIBLE_FOR_EPILOGUE_DELAY(trial, slots_filled) \
+  (TARGET_FLAT ? sparc_flat_eligible_for_epilogue_delay (trial, slots_filled) \
    : eligible_for_epilogue_delay (trial, slots_filled))
+
+/* Define registers used by the epilogue and return instruction.  */
+#define EPILOGUE_USES(REGNO) \
+  (!TARGET_FLAT && REGNO == 31)
 \f
 /* Output assembler code for a block containing the constant parts
    of a trampoline, leaving space for the variable parts.  */
 
-/* On the sparc, the trampoline contains five instructions:
+/* On 32 bit sparcs, the trampoline contains five instructions:
      sethi #TOP_OF_FUNCTION,%g1
      or #BOTTOM_OF_FUNCTION,%g1,%g1
      sethi #TOP_OF_STATIC,%g2
      jmp g1
-     or #BOTTOM_OF_STATIC,%g2,%g2  */
-#define TRAMPOLINE_TEMPLATE(FILE)                                      \
-{                                                                      \
-  ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x00000000));    \
-  ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x00000000));    \
-  ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x00000000));    \
-  ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x81C04000));    \
-  ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x00000000));    \
-}
+     or #BOTTOM_OF_STATIC,%g2,%g2
+
+  On 64 bit sparcs, the trampoline contains 4 insns and two pseudo-immediate
+  constants (plus some padding):
+     rd %pc,%g1
+     ldx[%g1+20],%g5
+     ldx[%g1+28],%g1
+     jmp %g1
+     nop
+     nop
+     .xword context
+     .xword function  */
+
+#define TRAMPOLINE_TEMPLATE(FILE) \
+do {                                                                   \
+  if (TARGET_ARCH64)                                                   \
+    {                                                                  \
+      fprintf (FILE, "\trd %%pc,%%g1\n");                              \
+      fprintf (FILE, "\tldx [%%g1+24],%%g5\n");                                \
+      fprintf (FILE, "\tldx [%%g1+32],%%g1\n");                                \
+      fprintf (FILE, "\tjmp %%g1\n");                                  \
+      fprintf (FILE, "\tnop\n");                                       \
+      fprintf (FILE, "\tnop\n");                                       \
+      /* -mmedlow shouldn't generate .xwords, so don't use them at all */ \
+      fprintf (FILE, "\t.word 0,0,0,0\n");                             \
+    }                                                                  \
+  else                                                                 \
+    {                                                                  \
+      ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x00000000));        \
+      ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x00000000));        \
+      ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x00000000));        \
+      ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x81C04000));        \
+      ASM_OUTPUT_INT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x00000000));        \
+    }                                                                  \
+} while (0)
 
 /* Length in units of the trampoline for entering a nested function.  */
 
-#define TRAMPOLINE_SIZE 20
+#define TRAMPOLINE_SIZE (TARGET_ARCH64 ? 40 : 20)
 
 /* Emit RTL insns to initialize the variable parts of a trampoline.
    FNADDR is an RTX for the address of the function's pure code.
@@ -1643,7 +2150,7 @@ void sparc_initialize_trampoline ();
 void sparc64_initialize_trampoline ();
 #define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
   do {                                                         \
-    if (TARGET_V9)                                             \
+    if (TARGET_ARCH64)                                         \
       sparc64_initialize_trampoline (TRAMP, FNADDR, CXT);      \
     else                                                       \
       sparc_initialize_trampoline (TRAMP, FNADDR, CXT);                \
@@ -1672,6 +2179,11 @@ extern struct rtx_def *sparc_builtin_saveregs ();
    save area.  */
 #define RETURN_ADDR_IN_PREVIOUS_FRAME
 
+/* This is the offset of the return address to the true next instruction to be
+   executed for the current function. */
+#define RETURN_ADDR_OFFSET \
+  (8 + 4 * (! TARGET_ARCH64 && current_function_returns_struct))
+
 /* The current return address is in %i7.  The return address of anything
    farther back is in the register window save area at [%fp+60].  */
 /* ??? This ignores the fact that the actual return address is +8 for normal
@@ -1679,8 +2191,10 @@ extern struct rtx_def *sparc_builtin_saveregs ();
 #define RETURN_ADDR_RTX(count, frame)          \
   ((count == -1)                               \
    ? gen_rtx (REG, Pmode, 31)                  \
-   : copy_to_reg (gen_rtx (MEM, Pmode,         \
-                          memory_address (Pmode, plus_constant (frame, 15 * UNITS_PER_WORD)))))
+   : gen_rtx (MEM, Pmode,                      \
+             memory_address (Pmode, plus_constant (frame, 15 * UNITS_PER_WORD))))
+
+#define DOESNT_NEED_UNWINDER (! TARGET_FLAT)
 \f
 /* Addressing modes, and classification of registers for them.  */
 
@@ -1699,15 +2213,16 @@ extern struct rtx_def *sparc_builtin_saveregs ();
    has been allocated, which happens in local-alloc.c.  */
 
 #define REGNO_OK_FOR_INDEX_P(REGNO) \
-(((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32) && (REGNO) != 0)
+((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)
 #define REGNO_OK_FOR_BASE_P(REGNO) \
-(((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32) && (REGNO) != 0)
+((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)
 #define REGNO_OK_FOR_FP_P(REGNO) \
   (((unsigned) (REGNO) - 32 < (TARGET_V9 ? 64 : 32)) \
    || ((unsigned) reg_renumber[REGNO] - 32 < (TARGET_V9 ? 64 : 32)))
 #define REGNO_OK_FOR_CCFP_P(REGNO) \
  (TARGET_V9 \
-  && ((unsigned) (REGNO) - 96 < 4) || ((unsigned) reg_renumber[REGNO] - 96 < 4))
+  && (((unsigned) (REGNO) - 96 < 4) \
+      || ((unsigned) reg_renumber[REGNO] - 96 < 4)))
 
 /* Now macros that check whether X is a register and also,
    strictly, whether it is in a specified class.
@@ -1773,11 +2288,11 @@ extern struct rtx_def *sparc_builtin_saveregs ();
 /* Nonzero if X is a hard reg that can be used as an index
    or if it is a pseudo reg.  */
 #define REG_OK_FOR_INDEX_P(X) \
-  (((unsigned) REGNO (X)) - 32 >= (FIRST_PSEUDO_REGISTER - 32) && REGNO (X) != 0)
+  (((unsigned) REGNO (X)) - 32 >= (FIRST_PSEUDO_REGISTER - 32))
 /* Nonzero if X is a hard reg that can be used as a base reg
    or if it is a pseudo reg.  */
 #define REG_OK_FOR_BASE_P(X) \
-  (((unsigned) REGNO (X)) - 32 >= (FIRST_PSEUDO_REGISTER - 32) && REGNO (X) != 0)
+  (((unsigned) REGNO (X)) - 32 >= (FIRST_PSEUDO_REGISTER - 32))
 
 /* 'T', 'U' are for aligned memory loads which aren't needed for v9.  */
 
@@ -1788,9 +2303,9 @@ extern struct rtx_def *sparc_builtin_saveregs ();
        && ! symbolic_memory_operand (OP, VOIDmode))    \
       || (reload_in_progress && GET_CODE (OP) == REG   \
          && REGNO (OP) >= FIRST_PSEUDO_REGISTER))      \
-   : ! TARGET_V9 && (C) == 'T'                 \
+   : (! TARGET_ARCH64 && (C) == 'T')                   \
    ? (mem_aligned_8 (OP))                              \
-   : ! TARGET_V9 && (C) == 'U'                                         \
+   : (! TARGET_ARCH64 && (C) == 'U')                   \
    ? (register_ok_for_ldd (OP))                                \
    : 0)
  
@@ -1807,13 +2322,14 @@ extern struct rtx_def *sparc_builtin_saveregs ();
       ? (REGNO (OP) >= FIRST_PSEUDO_REGISTER           \
         && reg_renumber[REGNO (OP)] < 0)               \
       : GET_CODE (OP) == MEM)                          \
-   : ! TARGET_V9 && (C) == 'T'                 \
+   : (! TARGET_ARCH64 && (C) == 'T')                   \
    ? mem_aligned_8 (OP) && strict_memory_address_p (Pmode, XEXP (OP, 0)) \
-   : ! TARGET_V9 && (C) == 'U'                 \
+   : (! TARGET_ARCH64 && (C) == 'U')                   \
    ? (GET_CODE (OP) == REG                             \
       && (REGNO (OP) < FIRST_PSEUDO_REGISTER           \
-         || reg_renumber[REGNO (OP)] > 0)              \
-      && register_ok_for_ldd (OP)) : 0)
+         || reg_renumber[REGNO (OP)] >= 0)             \
+      && register_ok_for_ldd (OP))                     \
+   : 0)
 #endif
 \f
 /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
@@ -2031,8 +2547,7 @@ extern struct rtx_def *legitimize_pic_address ();
    We also have two modes to indicate that the relevant condition code is
    in the floating-point condition code register.  One for comparisons which
    will generate an exception if the result is unordered (CCFPEmode) and
-   one for comparisons which will never trap (CCFPmode).  This really should
-   be a separate register, but we don't want to go to 65 registers.
+   one for comparisons which will never trap (CCFPmode).
 
    CCXmode and CCX_NOOVmode are only used by v9.  */
 
@@ -2052,8 +2567,8 @@ extern struct rtx_def *legitimize_pic_address ();
    ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode)                   \
    : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS                   \
        || GET_CODE (X) == NEG || GET_CODE (X) == ASHIFT)               \
-      ? (TARGET_V9 && GET_MODE (X) == DImode ? CCX_NOOVmode : CC_NOOVmode) \
-      : (TARGET_V9 && GET_MODE (X) == DImode ? CCXmode : CCmode)))
+      ? (TARGET_ARCH64 && GET_MODE (X) == DImode ? CCX_NOOVmode : CC_NOOVmode) \
+      : (TARGET_ARCH64 && GET_MODE (X) == DImode ? CCXmode : CCmode)))
 
 /* Return non-zero if SELECT_CC_MODE will never return MODE for a
    floating point inequality comparison.  */
@@ -2112,7 +2627,6 @@ extern struct rtx_def *legitimize_pic_address ();
    for calls to the builtin function sqrt, but this fails.  */
 #define INIT_TARGET_OPTABS                                             \
   do {                                                                 \
-    INIT_SUBTARGET_OPTABS;                                             \
     add_optab->handlers[(int) TFmode].libfunc                          \
       = gen_rtx (SYMBOL_REF, Pmode, ADDTF3_LIBCALL);                   \
     sub_optab->handlers[(int) TFmode].libfunc                          \
@@ -2140,6 +2654,7 @@ extern struct rtx_def *legitimize_pic_address ();
     if (TARGET_FPU)                                                    \
       sqrt_optab->handlers[(int) TFmode].libfunc                       \
        = gen_rtx (SYMBOL_REF, Pmode, "_Q_sqrt");                       \
+    INIT_SUBTARGET_OPTABS;                                             \
   } while (0)
 
 /* This is meant to be redefined in the host dependent files */
@@ -2192,7 +2707,8 @@ extern struct rtx_def *legitimize_pic_address ();
 
 #define RTX_COSTS(X,CODE,OUTER_CODE)                   \
   case MULT:                                           \
-    return (TARGET_V8 || TARGET_V9) ? COSTS_N_INSNS (5) : COSTS_N_INSNS (25);  \
+    return (TARGET_V8 || TARGET_SPARCLITE || TARGET_V9) \
+       ? COSTS_N_INSNS (5) : COSTS_N_INSNS (25);       \
   case DIV:                                            \
   case UDIV:                                           \
   case MOD:                                            \
@@ -2206,8 +2722,8 @@ extern struct rtx_def *legitimize_pic_address ();
 
 /* Adjust the cost of dependencies.  */
 #define ADJUST_COST(INSN,LINK,DEP,COST) \
-  if (TARGET_SUPERSPARC) \
-  (COST) = supersparc_adjust_cost (INSN, LINK, DEP, COST)
+  if (sparc_cpu == PROCESSOR_SUPERSPARC) \
+    (COST) = supersparc_adjust_cost (INSN, LINK, DEP, COST)
 
 /* Conditional branches with empty delay slots have a length of two.  */
 #define ADJUST_INSN_LENGTH(INSN, LENGTH)       \
@@ -2252,7 +2768,6 @@ extern struct rtx_def *legitimize_pic_address ();
 /* How to refer to registers in assembler output.
    This sequence is indexed by compiler's hard-register-number (see above).  */
 
-#ifdef SPARCV9
 #define REGISTER_NAMES \
 {"%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7",               \
  "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7",               \
@@ -2266,35 +2781,24 @@ extern struct rtx_def *legitimize_pic_address ();
  "%f40", "%f41", "%f42", "%f43", "%f44", "%f45", "%f46", "%f47",       \
  "%f48", "%f49", "%f50", "%f51", "%f52", "%f53", "%f54", "%f55",       \
  "%f56", "%f57", "%f58", "%f59", "%f60", "%f61", "%f62", "%f63",       \
- "%fcc0", "%fcc1", "%fcc2", "%fcc3"}
-#else
-#define REGISTER_NAMES \
-{"%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7",               \
- "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7",               \
- "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7",               \
- "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7",               \
- "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",               \
- "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",         \
- "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",       \
- "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31"}
-#endif
+ "%fcc0", "%fcc1", "%fcc2", "%fcc3", "%icc"}
 
-/* Define additional names for use in asm clobbers and asm declarations.
+/* Define additional names for use in asm clobbers and asm declarations.  */
 
-   We define the fake Condition Code register as an alias for reg 0 (which
-   is our `condition code' register), so that condition codes can easily
-   be clobbered by an asm.  No such register actually exists.  Condition
-   codes are partly stored in the PSR and partly in the FSR.  */
-
-#define ADDITIONAL_REGISTER_NAMES      {"ccr", 0, "cc", 0}
+#define ADDITIONAL_REGISTER_NAMES \
+{{"ccr", SPARC_ICC_REG}, {"cc", SPARC_ICC_REG}}
 
 /* How to renumber registers for dbx and gdb.  */
 
 #define DBX_REGISTER_NUMBER(REGNO) (REGNO)
 
-/* On Sun 4, this limit is 2048.  We use 1500 to be safe,
-   since the length can run past this up to a continuation point.  */
-#define DBX_CONTIN_LENGTH 1500
+/* On Sun 4, this limit is 2048.  We use 1000 to be safe, since the length
+   can run past this up to a continuation point.  Once we used 1500, but
+   a single entry in C++ can run more than 500 bytes, due to the length of
+   mangled symbol names.  dbxout.c should really be fixed to do
+   continuations when they are actually needed instead of trying to
+   guess...  */
+#define DBX_CONTIN_LENGTH 1000
 
 /* This is how to output a note to DBX telling it the line number
    to which the following sequence of instructions corresponds.
@@ -2319,11 +2823,9 @@ extern struct rtx_def *legitimize_pic_address ();
 #define ASM_GLOBALIZE_LABEL(FILE,NAME) \
   do { fputs ("\t.global ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
 
-/* This is how to output a reference to a user-level label named NAME.
-   `assemble_name' uses this.  */
+/* The prefix to add to user-visible assembler symbols. */
 
-#define ASM_OUTPUT_LABELREF(FILE,NAME) \
-  fprintf (FILE, "_%s", NAME)
+#define USER_LABEL_PREFIX "_"
 
 /* This is how to output a definition of an internal numbered label where
    PREFIX is the class of label and NUM is the number within the class.  */
@@ -2331,15 +2833,6 @@ extern struct rtx_def *legitimize_pic_address ();
 #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM)     \
   fprintf (FILE, "%s%d:\n", PREFIX, NUM)
 
-/* This is how to output a reference to an internal numbered label where
-   PREFIX is the class of label and NUM is the number within the class.  */
-/* FIXME:  This should be used throughout gcc, and documented in the texinfo
-   files.  There is no reason you should have to allocate a buffer and
-   `sprintf' to reference an internal label (as opposed to defining it).  */
-
-#define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM)  \
-  fprintf (FILE, "%s%d", PREFIX, NUM)
-
 /* This is how to store into the string LABEL
    the symbol_ref name of an internal numbered label where
    PREFIX is the class of label and NUM is the number within the class.
@@ -2414,7 +2907,7 @@ do {                                                                      \
   ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE);                     \
   if (Pmode == SImode)                                                 \
     fprintf (FILE, "\t.word\t");                                       \
-  else if (TARGET_ENV32)                                               \
+  else if (TARGET_MEDLOW)                                              \
     fprintf (FILE, "\t.word\t0\n\t.word\t");                           \
   else                                                                 \
     fprintf (FILE, "\t.xword\t");                                      \
@@ -2431,7 +2924,7 @@ do {                                                                      \
   ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE);                     \
   if (Pmode == SImode)                                                 \
     fprintf (FILE, "\t.word\t");                                       \
-  else if (TARGET_ENV32)                                               \
+  else if (TARGET_MEDLOW)                                              \
     fprintf (FILE, "\t.word\t0\n\t.word\t");                           \
   else                                                                 \
     fprintf (FILE, "\t.xword\t");                                      \
@@ -2482,6 +2975,34 @@ do {                                                                     \
 #define ASM_OUTPUT_IDENT(FILE, NAME) \
   fprintf (FILE, "\t%s\t\"%s\"\n", IDENT_ASM_OP, NAME);
 
+/* Output code to add DELTA to the first argument, and then jump to FUNCTION.
+   Used for C++ multiple inheritance.  */
+#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION)       \
+do {                                                                   \
+  int big_delta = (DELTA) >= 4096 || (DELTA) < -4096;                  \
+  if (big_delta)                                                       \
+    fprintf (FILE, "\tset %d,%%g1\n\tadd %%o0,%%g1,%%o0\n", (DELTA));  \
+  if (TARGET_MEDANY || TARGET_FULLANY)                                 \
+    {                                                                  \
+      fprintf (FILE, "\tsetx ");                                       \
+      assemble_name                                                    \
+       (FILE, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION)));    \
+      fprintf (FILE, ",%%g5,%%g1\n\tjmp %%g1\n");                      \
+    }                                                                  \
+  else                                                                 \
+    {                                                                  \
+      fprintf (FILE, "\tsethi %%hi(");                                 \
+      assemble_name                                                    \
+       (FILE, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION)));    \
+      fprintf (FILE, "),%%g1\n\tjmp %%g1+%%lo(");                      \
+      assemble_name                                                    \
+       (FILE, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION)));    \
+      fprintf (FILE, ")\n");                                           \
+    }                                                                  \
+  if (big_delta) fprintf (FILE, "\tnop\n");                            \
+  else fprintf (FILE, "\tadd %%o0,%d,%%o0\n", DELTA);                  \
+} while (0)
+
 /* Define the parentheses used to group arithmetic operations
    in assembler code.  */
 
@@ -2527,7 +3048,8 @@ do {                                                                      \
        fprintf (FILE, "%+d", offset);                          \
       else if (GET_CODE (index) == REG)                                \
        fprintf (FILE, "+%s", reg_names[REGNO (index)]);        \
-      else if (GET_CODE (index) == SYMBOL_REF)                 \
+      else if (GET_CODE (index) == SYMBOL_REF                  \
+              || GET_CODE (index) == CONST)                    \
        fputc ('+', FILE), output_addr_const (FILE, index);     \
       else abort ();                                           \
     }                                                          \
@@ -2567,6 +3089,9 @@ do {                                                                      \
     }                                                          \
 }
 
+/* The number of Pmode words for the setjmp buffer.  */
+#define JMP_BUF_SIZE 12
+
 /* Declare functions defined in sparc.c and used in templates.  */
 
 extern char *singlemove_string ();