OSDN Git Service

Fix copyrights.
[pf3gnuchains/gcc-fork.git] / gcc / config / sparc / sparc.h
index f3dacd8..58b465a 100644 (file)
@@ -1,6 +1,6 @@
 /* Definitions of target machine for GNU compiler, for Sun SPARC.
-   Copyright (C) 1987, 88, 89, 92, 94, 95, 96, 1997 Free Software Foundation,
-   Inc.
+   Copyright (C) 1987, 1988, 1989, 1992, 1994, 1995, 1996, 1997, 1998, 1999
+   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.
@@ -23,105 +23,205 @@ 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!
-
-   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.
+   whatever definitions are necessary.  */
+
+/* Specify this in a cover file to provide bi-architecture (32/64) support.  */
+/* #define SPARC_BI_ARCH */
+
+/* Macro used later in this file to determine default architecture.  */
+#define DEFAULT_ARCH32_P ((TARGET_DEFAULT & MASK_64BIT) == 0)
+
+/* TARGET_ARCH{32,64} are the main macros to decide which of the two
+   architectures to compile for.  We allow targets to choose compile time or
+   runtime selection.  */
+#ifdef IN_LIBGCC2
+#if defined(__sparcv9) || defined(__arch64__)
+#define TARGET_ARCH32 0
+#else
+#define TARGET_ARCH32 1
+#endif /* sparc64 */
+#else
+#ifdef SPARC_BI_ARCH
+#define TARGET_ARCH32 (! TARGET_64BIT)
+#else
+#define TARGET_ARCH32 (DEFAULT_ARCH32_P)
+#endif /* SPARC_BI_ARCH */
+#endif /* IN_LIBGCC2 */
+#define TARGET_ARCH64 (! TARGET_ARCH32)
+
+/* Code model selection.
+   -mcmodel is used to select the v9 code model.
+   Different code models aren't supported for v7/8 code.
+
+   TARGET_CM_32:     32 bit address space, top 32 bits = 0,
+                    pointers are 32 bits.  Note that this isn't intended
+                     to imply a v7/8 abi.
+
+   TARGET_CM_MEDLOW: 32 bit address space, top 32 bits = 0,
+                     avoid generating %uhi and %ulo terms,
+                    pointers are 64 bits.
+
+   TARGET_CM_MEDMID: 64 bit address space.
+                     The executable must be in the low 16 TB of memory.
+                     This corresponds to the low 44 bits, and the %[hml]44
+                     relocs are used.  The text segment has a maximum size
+                     of 31 bits.
+
+   TARGET_CM_MEDANY: 64 bit address space.
+                     The text and data segments have a maximum size of 31
+                     bits and may be located anywhere.  The maximum offset
+                     from any instruction to the label _GLOBAL_OFFSET_TABLE_
+                     is 31 bits.
+
+   TARGET_CM_EMBMEDANY: 64 bit address space.
+                     The text and data segments have a maximum size of 31 bits
+                     and may be located anywhere.  Register %g4 contains
+                     the start address of the data segment.
 */
 
-#ifndef SPARC_V9
-#define SPARC_V9 0
-#endif
-#ifndef SPARC_ARCH64
-#define SPARC_ARCH64 0
-#endif
+enum cmodel {
+  CM_32,
+  CM_MEDLOW,
+  CM_MEDMID,
+  CM_MEDANY,
+  CM_EMBMEDANY
+};
+
+/* Value of -mcmodel specified by user.  */
+extern const char *sparc_cmodel_string;
+/* One of CM_FOO.  */
+extern enum cmodel sparc_cmodel;
 
-/* Values of TARGET_CPU_DEFAULT, set via -D in the Makefile.  */
+/* V9 code model selection.  */
+#define TARGET_CM_MEDLOW    (sparc_cmodel == CM_MEDLOW)
+#define TARGET_CM_MEDMID    (sparc_cmodel == CM_MEDMID)
+#define TARGET_CM_MEDANY    (sparc_cmodel == CM_MEDANY)
+#define TARGET_CM_EMBMEDANY (sparc_cmodel == CM_EMBMEDANY)
+
+#define SPARC_DEFAULT_CMODEL CM_32
+
+/* This is call-clobbered in the normal ABI, but is reserved in the
+   home grown (aka upward compatible) embedded ABI.  */
+#define EMBMEDANY_BASE_REG "%g4"
+\f
+/* Values of TARGET_CPU_DEFAULT, set via -D in the Makefile,
+   and specified by the user via --with-cpu=foo.
+   This specifies the cpu implementation, not the architecture size.  */
+/* Note that TARGET_CPU_v9 is assumed to start the list of 64-bit 
+   capable cpu's.  */
 #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_v8          3       /* generic v8 implementation */
 #define TARGET_CPU_supersparc  4
-#define TARGET_CPU_ultrasparc  5
-#define TARGET_CPU_sparc64     5       /* alias for ultrasparc */
+#define TARGET_CPU_hypersparc   5
+#define TARGET_CPU_sparc86x    6
+#define TARGET_CPU_sparclite86x        6
+#define TARGET_CPU_v9          7       /* generic v9 implementation */
+#define TARGET_CPU_sparcv9     7       /* alias */
+#define TARGET_CPU_sparc64     7       /* alias */
+#define TARGET_CPU_ultrasparc  8
 
-#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
+#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc
+
+#define CPP_CPU32_DEFAULT_SPEC ""
+#define ASM_CPU32_DEFAULT_SPEC ""
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_v9
 /* ??? What does Sun's CC pass?  */
-#define CPP_DEFAULT_SPEC "-D__sparc_v9__"
+#define CPP_CPU64_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.
+#define ASM_CPU64_DEFAULT_SPEC "-Av9"
 #endif
+#if TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc
+#define CPP_CPU64_DEFAULT_SPEC "-D__sparc_v9__"
+#define ASM_CPU64_DEFAULT_SPEC "-Av9a"
 #endif
+
+#else
+
+#define CPP_CPU64_DEFAULT_SPEC ""
+#define ASM_CPU64_DEFAULT_SPEC ""
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_sparc \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_v8
+#define CPP_CPU32_DEFAULT_SPEC ""
+#define ASM_CPU32_DEFAULT_SPEC ""
 #endif
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_sparclet
+#define CPP_CPU32_DEFAULT_SPEC "-D__sparclet__"
+#define ASM_CPU32_DEFAULT_SPEC "-Asparclet"
 #endif
 
-/* Names to predefine in the preprocessor for this target machine.  */
+#if TARGET_CPU_DEFAULT == TARGET_CPU_sparclite
+#define CPP_CPU32_DEFAULT_SPEC "-D__sparclite__"
+#define ASM_CPU32_DEFAULT_SPEC "-Asparclite"
+#endif
 
-/* ??? 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.  */
+#if TARGET_CPU_DEFAULT == TARGET_CPU_supersparc
+#define CPP_CPU32_DEFAULT_SPEC "-D__supersparc__ -D__sparc_v8__"
+#define ASM_CPU32_DEFAULT_SPEC ""
+#endif
 
-#if SPARC_ARCH64
-#define CPP_PREDEFINES \
-  "-Dsparc -Dsun -Dunix -D__arch64__ \
-   -Asystem(unix) -Asystem(bsd) -Acpu(sparc64) -Amachine(sparc64)"
-#else
-#define CPP_PREDEFINES \
-  "-Dsparc -Dsun -Dunix -D__GCC_NEW_VARARGS__ \
-   -Asystem(unix) -Asystem(bsd) -Acpu(sparc) -Amachine(sparc)"
+#if TARGET_CPU_DEFAULT == TARGET_CPU_hypersparc
+#define CPP_CPU32_DEFAULT_SPEC "-D__hypersparc__ -D__sparc_v8__"
+#define ASM_CPU32_DEFAULT_SPEC ""
 #endif
 
-/* Define macros to distinguish architectures.  */
+#if TARGET_CPU_DEFAULT == TARGET_CPU_sparclite86x
+#define CPP_CPU32_DEFAULT_SPEC "-D__sparclite86x__"
+#define ASM_CPU32_DEFAULT_SPEC "-Asparclite"
+#endif
 
-#if SPARC_ARCH64
-#define CPP_SPEC "\
-%{mint64:-D__INT_MAX__=9223372036854775807LL -D__LONG_MAX__=9223372036854775807LL} \
-%{mlong64:-D__LONG_MAX__=9223372036854775807LL} \
-"
-#else
-#define CPP_SPEC "%(cpp_cpu)"
 #endif
 
+#if !defined(CPP_CPU32_DEFAULT_SPEC) || !defined(CPP_CPU64_DEFAULT_SPEC)
+Unrecognized value in TARGET_CPU_DEFAULT.
+#endif
+
+#ifdef SPARC_BI_ARCH
+
+#define CPP_CPU_DEFAULT_SPEC \
+(DEFAULT_ARCH32_P ? "\
+%{m64:" CPP_CPU64_DEFAULT_SPEC "} \
+%{!m64:" CPP_CPU32_DEFAULT_SPEC "} \
+" : "\
+%{m32:" CPP_CPU32_DEFAULT_SPEC "} \
+%{!m32:" CPP_CPU64_DEFAULT_SPEC "} \
+")
+#define ASM_CPU_DEFAULT_SPEC \
+(DEFAULT_ARCH32_P ? "\
+%{m64:" ASM_CPU64_DEFAULT_SPEC "} \
+%{!m64:" ASM_CPU32_DEFAULT_SPEC "} \
+" : "\
+%{m32:" ASM_CPU32_DEFAULT_SPEC "} \
+%{!m32:" ASM_CPU64_DEFAULT_SPEC "} \
+")
+
+#else /* !SPARC_BI_ARCH */
+
+#define CPP_CPU_DEFAULT_SPEC (DEFAULT_ARCH32_P ? CPP_CPU32_DEFAULT_SPEC : CPP_CPU64_DEFAULT_SPEC)
+#define ASM_CPU_DEFAULT_SPEC (DEFAULT_ARCH32_P ? ASM_CPU32_DEFAULT_SPEC : ASM_CPU64_DEFAULT_SPEC)
+
+#endif /* !SPARC_BI_ARCH */
+
+/* Names to predefine in the preprocessor for this target machine.
+   ??? It would be nice to not include any subtarget specific values here,
+   however there's no way to portably provide subtarget values to
+   CPP_PREFINES.  Also, -D values in CPP_SUBTARGET_SPEC don't get turned into
+   foo, __foo and __foo__.  */
+
+#define CPP_PREDEFINES "-Dsparc -Dsun -Dunix -Asystem(unix) -Asystem(bsd)"
+
+/* Define macros to distinguish architectures.  */
+
 /* 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__} \
@@ -133,12 +233,52 @@ Unrecognized value in TARGET_CPU_DEFAULT.
 %{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=hypersparc:-D__hypersparc__ -D__sparc_v8__} \
+%{mcpu=sparclite86x:-D__sparclite86x__} \
 %{mcpu=v9:-D__sparc_v9__} \
 %{mcpu=ultrasparc:-D__sparc_v9__} \
-%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_default)}}}}}}} \
+%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}} \
 "
 
+/* ??? 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.  */
+
+#ifdef SPARC_BI_ARCH
+
+#define CPP_ARCH32_SPEC "-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int \
+-D__GCC_NEW_VARARGS__ -Acpu(sparc) -Amachine(sparc)"
+#define CPP_ARCH64_SPEC "-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int \
+-D__arch64__ -Acpu(sparc64) -Amachine(sparc64)"
+
+#else
+
+#define CPP_ARCH32_SPEC "-D__GCC_NEW_VARARGS__ -Acpu(sparc) -Amachine(sparc)"
+#define CPP_ARCH64_SPEC "-D__arch64__ -Acpu(sparc64) -Amachine(sparc64)"
+
+#endif
+
+#define CPP_ARCH_DEFAULT_SPEC \
+(DEFAULT_ARCH32_P ? CPP_ARCH32_SPEC : CPP_ARCH64_SPEC)
+
+#define CPP_ARCH_SPEC "\
+%{m32:%(cpp_arch32)} \
+%{m64:%(cpp_arch64)} \
+%{!m32:%{!m64:%(cpp_arch_default)}} \
+"
+
+/* Macros to distinguish endianness.  */
+#define CPP_ENDIAN_SPEC "\
+%{mlittle-endian:-D__LITTLE_ENDIAN__} \
+%{mlittle-endian-data:-D__LITTLE_ENDIAN_DATA__}"
+
+/* Macros to distinguish the particular subtarget.  */
+#define CPP_SUBTARGET_SPEC ""
+
+#define CPP_SPEC "%(cpp_cpu) %(cpp_arch) %(cpp_endian) %(cpp_subtarget)"
+
 /* 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.  */
@@ -152,13 +292,33 @@ Unrecognized value in TARGET_CPU_DEFAULT.
 %{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
 "
 
-#define LIB_SPEC "%{!shared:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} %{g:-lg}}"
+/* 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=sparclite86x:-Asparclite} \
+%{mcpu=f930:-Asparclite} %{mcpu=f934:-Asparclite} \
+%{mv8plus:-Av8plus} \
+%{mcpu=v9:-Av9} \
+%{mcpu=ultrasparc:%{!mv8plus:-Av9a}} \
+%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(asm_cpu_default)}}}}}}} \
+"
 
-/* Provide required defaults for linker -e and -d switches.  */
+/* Word size selection, among other things.
+   This is what GAS uses.  Add %(asm_arch) to ASM_SPEC to enable.  */
 
-#define LINK_SPEC \
- "%{!shared:%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp} %{static:-Bstatic} \
-  %{assert*} %{shared:%{!mimpure-text:-assert pure-text}}"
+#define ASM_ARCH32_SPEC "-32"
+#define ASM_ARCH64_SPEC "-64"
+#define ASM_ARCH_DEFAULT_SPEC \
+(DEFAULT_ARCH32_P ? ASM_ARCH32_SPEC : ASM_ARCH64_SPEC)
+
+#define ASM_ARCH_SPEC "\
+%{m32:%(asm_arch32)} \
+%{m64:%(asm_arch64)} \
+%{!m32:%{!m64:%(asm_arch_default)}} \
+"
 
 /* Special flags to the Sun-4 assembler when using pipe for input.  */
 
@@ -167,18 +327,13 @@ Unrecognized value in TARGET_CPU_DEFAULT.
 %(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)}}}}}}} \
-"
+#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}}"
 
 /* This macro defines names of additional specifications to put in the specs
    that can be used in various specifications like CC1_SPEC.  Its definition
@@ -190,22 +345,31 @@ Unrecognized value in TARGET_CPU_DEFAULT.
 
    Do not define this macro if it does not need to do anything.  */
 
-#define EXTRA_SPECS                                    \
-  { "cpp_cpu",         CPP_CPU_SPEC },                 \
-  { "cpp_default",     CPP_DEFAULT_SPEC },             \
-  { "asm_cpu",         ASM_CPU_SPEC },                 \
-  { "asm_default",     ASM_DEFAULT_SPEC },             \
+#define EXTRA_SPECS \
+  { "cpp_cpu",         CPP_CPU_SPEC },         \
+  { "cpp_cpu_default", CPP_CPU_DEFAULT_SPEC }, \
+  { "cpp_arch32",      CPP_ARCH32_SPEC },      \
+  { "cpp_arch64",      CPP_ARCH64_SPEC },      \
+  { "cpp_arch_default",        CPP_ARCH_DEFAULT_SPEC },\
+  { "cpp_arch",                CPP_ARCH_SPEC },        \
+  { "cpp_endian",      CPP_ENDIAN_SPEC },      \
+  { "cpp_subtarget",   CPP_SUBTARGET_SPEC },   \
+  { "asm_cpu",         ASM_CPU_SPEC },         \
+  { "asm_cpu_default", ASM_CPU_DEFAULT_SPEC }, \
+  { "asm_arch32",      ASM_ARCH32_SPEC },      \
+  { "asm_arch64",      ASM_ARCH64_SPEC },      \
+  { "asm_arch_default",        ASM_ARCH_DEFAULT_SPEC },\
+  { "asm_arch",                ASM_ARCH_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"
-/* The default value for SIZE_TYPE is "unsigned int" which is what we want.  */
+#ifdef SPARC_BI_ARCH
+#define NO_BUILTIN_PTRDIFF_TYPE
+#define NO_BUILTIN_SIZE_TYPE
 #endif
+#define PTRDIFF_TYPE (TARGET_ARCH64 ? "long int" : "int")
+#define SIZE_TYPE (TARGET_ARCH64 ? "long unsigned int" : "unsigned int")
 
 /* ??? This should be 32 bits for v9 but what can we do?  */
 #define WCHAR_TYPE "short unsigned int"
@@ -219,15 +383,13 @@ Unrecognized value in TARGET_CPU_DEFAULT.
    code into the rtl.  Also, if we are profiling, we cannot eliminate
    the frame pointer (because the return address will get smashed).  */
 
-void sparc_override_options ();
-
 #define OVERRIDE_OPTIONS \
   do {                                                                 \
     if (profile_flag || profile_block_flag || profile_arc_flag)                \
       {                                                                        \
        if (flag_pic)                                                   \
          {                                                             \
-           char *pic_string = (flag_pic == 1) ? "-fpic" : "-fPIC";     \
+           const char *pic_string = (flag_pic == 1) ? "-fpic" : "-fPIC";\
            warning ("%s and profiling conflict: disabling %s",         \
                     pic_string, pic_string);                           \
            flag_pic = 0;                                               \
@@ -336,48 +498,20 @@ extern int target_flags;
 #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.
-   This option is for v9 only.  */
-#define MASK_INT64 0x2000
-#define TARGET_INT64 (target_flags & MASK_INT64)
-
-/* Nonzero if longs are 64 bits.
-   This option is for v9 only.  */
-#define MASK_LONG64 0x4000
-#define TARGET_LONG64 (target_flags & MASK_LONG64)
+/* 0x2000, 0x4000 are unused */
 
 /* Nonzero if pointers are 64 bits.
-   This is not a user selectable option, though it may be one day -
-   so it is used to determine pointer size instead of an architecture flag.  */
+   At the moment it must follow architecture size flag.  */
 #define MASK_PTR64 0x8000
 #define TARGET_PTR64 (target_flags & MASK_PTR64)
 
-/* 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
-#define MASK_MEDANY 0x40000
-#define MASK_FULLANY 0x60000
-#define MASK_CODE_MODEL (MASK_MEDLOW + MASK_MEDANY)
-#define TARGET_MEDLOW ((target_flags & MASK_CODE_MODEL) == MASK_MEDLOW)
-#define TARGET_MEDANY ((target_flags & MASK_CODE_MODEL) == MASK_MEDANY)
-#define TARGET_FULLANY ((target_flags & MASK_CODE_MODEL) == MASK_FULLANY)
-
-/* ??? There are hardcoded references to this reg in the .md file.  */
-#define MEDANY_BASE_REG "%g4"
+/* Nonzero if generating code to run in a 64 bit environment.
+   This is intended to only be used by TARGET_ARCH{32,64} as they are the
+   mechanism used to control compile time or run time selection.  */
+#define MASK_64BIT 0x10000
+#define TARGET_64BIT (target_flags & MASK_64BIT)
+
+/* 0x20000,0x40000 unused */
 
 /* Non-zero means use a stack bias of 2047.  Stack offsets are obtained by
    adding 2047 to %sp.  This option is for v9 only and is the default.  */
@@ -394,8 +528,8 @@ extern int target_flags;
 /* 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.  */
+   trouble associated with an interrupt occurring after the `save' or trap
+   occurring during it.  */
 #define MASK_BROKEN_SAVERESTORE 0x200000
 #define TARGET_BROKEN_SAVERESTORE (target_flags & MASK_BROKEN_SAVERESTORE)
 
@@ -403,6 +537,35 @@ extern int target_flags;
 #define MASK_FPU_SET 0x400000
 #define TARGET_FPU_SET (target_flags & MASK_FPU_SET)
 
+/* Use the UltraSPARC Visual Instruction Set extensions.  */
+#define MASK_VIS 0x1000000          
+#define TARGET_VIS (target_flags & MASK_VIS)
+
+/* Compile for Solaris V8+.  32 bit Solaris preserves the high bits of
+   the current out and global registers and Linux 2.2+ as well.  */
+#define MASK_V8PLUS 0x2000000
+#define TARGET_V8PLUS (target_flags & MASK_V8PLUS)                            
+
+/* Force a the fastest alignment on structures to take advantage of
+   faster copies.  */
+#define MASK_FASTER_STRUCTS 0x4000000
+#define TARGET_FASTER_STRUCTS (target_flags & MASK_FASTER_STRUCTS)
+
+/* TARGET_HARD_MUL: Use hardware multiply instructions but not %y.
+   TARGET_HARD_MUL32: Use hardware multiply instructions with rd %y
+   to get high 32 bits.  False in V8+ or V9 because multiply stores
+   a 64 bit result in a register.  */
+
+#define TARGET_HARD_MUL32                              \
+  ((TARGET_V8 || TARGET_SPARCLITE                      \
+    || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS)  \
+   && ! TARGET_V8PLUS && TARGET_ARCH32)
+
+#define TARGET_HARD_MUL                                        \
+  (TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET    \
+   || TARGET_DEPRECATED_V8_INSNS || TARGET_V8PLUS)                        
+
+
 /* Macro to define tables used to set the flags.
    This is a list in braces of pairs in braces,
    each pair being { "NAME", VALUE }
@@ -410,34 +573,46 @@ extern int target_flags;
    An empty string NAME is used to identify the default VALUE.  */
 
 #define TARGET_SWITCHES  \
-  { {"fpu", MASK_FPU | MASK_FPU_SET},  \
-    {"no-fpu", -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}, \
-    {"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},                 \
+  { {"fpu", MASK_FPU | MASK_FPU_SET,                   "Use hardware fp" },            \
+    {"no-fpu", -MASK_FPU,                              "Do not use hardware fp" },     \
+    {"no-fpu", MASK_FPU_SET,                           NULL, },        \
+    {"hard-float", MASK_FPU | MASK_FPU_SET,            "Use hardware fp" },            \
+    {"soft-float", -MASK_FPU,                          "Do not use hardware fp" },     \
+    {"soft-float", MASK_FPU_SET,                       NULL }, \
+    {"epilogue", MASK_EPILOGUE,                                "Use FUNCTION_EPILOGUE" },      \
+    {"no-epilogue", -MASK_EPILOGUE,                    "Do not use FUNCTION_EPILOGUE" },       \
+    {"unaligned-doubles", MASK_UNALIGNED_DOUBLES,      "Assume possible double misalignment" },\
+    {"no-unaligned-doubles", -MASK_UNALIGNED_DOUBLES,  "Assume all doubles are aligned" }, \
+    {"impure-text", MASK_IMPURE_TEXT,                  "Pass -assert pure-text to linker" }, \
+    {"no-impure-text", -MASK_IMPURE_TEXT,              "Do not pass -assert pure-text to linker" }, \
+    {"flat", MASK_FLAT,                                        "Use flat register window model" }, \
+    {"no-flat", -MASK_FLAT,                            "Do not use flat register window model" }, \
+    {"app-regs", MASK_APP_REGS,                                "Use ABI reserved registers" }, \
+    {"no-app-regs", -MASK_APP_REGS,                    "Do not use ABI reserved registers" }, \
+    {"hard-quad-float", MASK_HARD_QUAD,                        "Use hardware quad fp instructions" }, \
+    {"soft-quad-float", -MASK_HARD_QUAD,               "Do not use hardware quad fp instructions" }, \
+    {"v8plus", MASK_V8PLUS,                            "Compile for v8plus ABI" },     \
+    {"no-v8plus", -MASK_V8PLUS,                                "Do not compile for v8plus ABI" }, \
+    {"vis", MASK_VIS,                                  "Utilize Visual Instruction Set" }, \
+    {"no-vis", -MASK_VIS,                              "Do not utilize Visual Instruction Set" }, \
+    /* ??? These are deprecated, coerced to -mcpu=.  Delete in 2.9.  */ \
+    {"cypress", 0,                                     "Optimize for Cypress processors" }, \
+    {"sparclite", 0,                                   "Optimize for SparcLite processors" }, \
+    {"f930", 0,                                                "Optimize for F930 processors" }, \
+    {"f934", 0,                                                "Optimize for F934 processors" }, \
+    {"v8", 0,                                          "Use V8 Sparc ISA" }, \
+    {"supersparc", 0,                                  "Optimize for SuperSparc processors" }, \
+    /* End of deprecated options.  */  \
+    {"ptr64", MASK_PTR64,                              "Pointers are 64-bit" }, \
+    {"ptr32", -MASK_PTR64,                             "Pointers are 32-bit" }, \
+    {"32", -MASK_64BIT,                                        "Use 32-bit ABI" }, \
+    {"64", MASK_64BIT,                                 "Use 64-bit ABI" }, \
+    {"stack-bias", MASK_STACK_BIAS,                    "Use stack bias" }, \
+    {"no-stack-bias", -MASK_STACK_BIAS,                        "Do not use stack bias" }, \
+    {"faster-structs", MASK_FASTER_STRUCTS,                    "Use structs on stronger alignment for double-word copies" }, \
+    {"no-faster-structs", -MASK_FASTER_STRUCTS,                "Do not use structs on stronger alignment for double-word copies" }, \
     SUBTARGET_SWITCHES                 \
-    ARCH64_SWITCHES                    \
-    { "", TARGET_DEFAULT}}
+    { "", TARGET_DEFAULT, ""}}
 
 /* MASK_APP_REGS must always be the default because that's what
    FIXED_REGISTERS is set to and -ffixed- is processed before
@@ -447,32 +622,6 @@ extern int target_flags;
 /* This is meant to be redefined in target specific files.  */
 #define SUBTARGET_SWITCHES
 
-/* ??? 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},            \
-    {"long64", -MASK_INT64},           \
-    {"long64", MASK_LONG64},           \
-    {"long32", -(MASK_INT64+MASK_LONG64)}, \
-/*  {"ptr64", MASK_PTR64}, */          \
-/*  {"ptr32", -MASK_PTR64}, */         \
-    {"stack-bias", MASK_STACK_BIAS},   \
-    {"no-stack-bias", -MASK_STACK_BIAS}, \
-    {"medlow", -MASK_CODE_MODEL},      \
-    {"medlow", MASK_MEDLOW},           \
-    {"medany", -MASK_CODE_MODEL},      \
-    {"medany", MASK_MEDANY},           \
-    {"fullany", -MASK_CODE_MODEL},     \
-    {"fullany", MASK_FULLANY},
-#else
-#define ARCH64_SWITCHES
-#endif
-
 /* Processor type.
    These must match the values for the cpu attribute in sparc.md.  */
 enum processor_type {
@@ -483,9 +632,10 @@ enum processor_type {
   PROCESSOR_SPARCLITE,
   PROCESSOR_F930,
   PROCESSOR_F934,
+  PROCESSOR_HYPERSPARC,
+  PROCESSOR_SPARCLITE86X,
   PROCESSOR_SPARCLET,
   PROCESSOR_TSC701,
-  PROCESSOR_V8PLUS,
   PROCESSOR_V9,
   PROCESSOR_ULTRASPARC
 };
@@ -515,10 +665,11 @@ extern enum processor_type sparc_cpu;
        #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } }  */
 
 #define TARGET_OPTIONS \
-{                                      \
-  {"cpu=",  &sparc_select[1].string},  \
-  {"tune=", &sparc_select[2].string},  \
-  SUBTARGET_OPTIONS \
+{                                                      \
+  { "cpu=",  &sparc_select[1].string, "Use features of and schedule code for given CPU" }, \
+  { "tune=", &sparc_select[2].string, "Schedule code for given CPU" }, \
+  { "cmodel=", &sparc_cmodel_string, "Use given Sparc code model" }, \
+  SUBTARGET_OPTIONS                                    \
 }
 
 /* This is meant to be redefined in target specific files.  */
@@ -527,8 +678,8 @@ extern enum processor_type sparc_cpu;
 /* sparc_select[0] is reserved for the default cpu.  */
 struct sparc_cpu_select
 {
-  char *string;
-  char *name;
+  const char *string;
+  const char *name;
   int set_tune_p;
   int set_arch_p;
 };
@@ -554,7 +705,7 @@ extern struct sparc_cpu_select sparc_select[];
 
 /* Define this to set the endianness to use in libgcc2.c, which can
    not depend on target_flags.  */
-#if defined (__LITTLE_ENDIAN__)
+#if defined (__LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN_DATA__)
 #define LIBGCC2_WORDS_BIG_ENDIAN 0
 #else
 #define LIBGCC2_WORDS_BIG_ENDIAN 1
@@ -577,16 +728,17 @@ extern struct sparc_cpu_select sparc_select[];
 /* Now define the sizes of the C data types.  */
 
 #define SHORT_TYPE_SIZE                16
-#define INT_TYPE_SIZE          (TARGET_INT64 ? 64 : 32)
-#define LONG_TYPE_SIZE         (TARGET_LONG64 ? 64 : 32)
+#define INT_TYPE_SIZE          32
+#define LONG_TYPE_SIZE         (TARGET_ARCH64 ? 64 : 32)
 #define LONG_LONG_TYPE_SIZE    64
 #define FLOAT_TYPE_SIZE                32
 #define DOUBLE_TYPE_SIZE       64
 
-#define MAX_INT_TYPE_SIZE      64
+#if defined (SPARC_BI_ARCH)
 #define MAX_LONG_TYPE_SIZE     64
+#endif
 
-#if SPARC_ARCH64
+#if 0
 /* ??? 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.
@@ -598,6 +750,46 @@ extern struct sparc_cpu_select sparc_select[];
    See also the macro `Pmode' defined below.  */
 #define POINTER_SIZE (TARGET_PTR64 ? 64 : 32)
 
+/* A macro to update MODE and UNSIGNEDP when an object whose type
+   is TYPE and which has the specified mode and signedness is to be
+   stored in a register.  This macro is only called when TYPE is a
+   scalar type.  */
+#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
+if (TARGET_ARCH64                              \
+    && GET_MODE_CLASS (MODE) == MODE_INT       \
+    && GET_MODE_SIZE (MODE) < UNITS_PER_WORD)  \
+{                                              \
+  (MODE) = DImode;                             \
+}
+
+/* Define this macro if the promotion described by PROMOTE_MODE
+   should also be done for outgoing function arguments.  */
+/* This is only needed for TARGET_ARCH64, but since PROMOTE_MODE is a no-op
+   for TARGET_ARCH32 this is ok.  Otherwise we'd need to add a runtime test
+   for this value.  */
+#define PROMOTE_FUNCTION_ARGS
+
+/* Define this macro if the promotion described by PROMOTE_MODE
+   should also be done for the return value of functions.
+   If this macro is defined, FUNCTION_VALUE must perform the same
+   promotions done by PROMOTE_MODE.  */
+/* This is only needed for TARGET_ARCH64, but since PROMOTE_MODE is a no-op
+   for TARGET_ARCH32 this is ok.  Otherwise we'd need to add a runtime test
+   for this value.  */
+#define PROMOTE_FUNCTION_RETURN
+
+/* Define this macro if the promotion described by PROMOTE_MODE
+   should _only_ be performed for outgoing function arguments or
+   function return values, as specified by PROMOTE_FUNCTION_ARGS
+   and PROMOTE_FUNCTION_RETURN, respectively.  */
+/* This is only needed for TARGET_ARCH64, but since PROMOTE_MODE is a no-op
+   for TARGET_ARCH32 this is ok.  Otherwise we'd need to add a runtime test
+   for this value.  For TARGET_ARCH64 we need it, as we don't have instructions
+   for arithmetic operations which do zero/sign extension at the same time,
+   so without this we end up with a srl/sra after every assignment to an
+   user variable,  which means very very bad code.  */
+#define PROMOTE_FOR_CALL_ONLY
+
 /* Allocation boundary (in *bits*) for storing arguments in argument list.  */
 #define PARM_BOUNDARY (TARGET_ARCH64 ? 64 : 32)
 
@@ -613,7 +805,6 @@ extern struct sparc_cpu_select sparc_select[];
 #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_ARCH64 ? 64 : 32)
 
 /* Every structure's size must be a multiple of this.  */
@@ -628,6 +819,23 @@ extern struct sparc_cpu_select sparc_select[];
 /* The best alignment to use in cases where we have a choice.  */
 #define FASTEST_ALIGNMENT 64
 
+/* Define this macro as an expression for the alignment of a structure
+   (given by STRUCT as a tree node) if the alignment computed in the
+   usual way is COMPUTED and the alignment explicitly specified was
+   SPECIFIED.
+
+   The default is to use SPECIFIED if it is larger; otherwise, use
+   the smaller of COMPUTED and `BIGGEST_ALIGNMENT' */
+#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED)  \
+ (TARGET_FASTER_STRUCTS ?                              \
+  ((TREE_CODE (STRUCT) == RECORD_TYPE                  \
+    || TREE_CODE (STRUCT) == UNION_TYPE                 \
+    || TREE_CODE (STRUCT) == QUAL_UNION_TYPE)           \
+   && TYPE_FIELDS (STRUCT) != 0                         \
+     ? MAX (MAX ((COMPUTED), (SPECIFIED)), BIGGEST_ALIGNMENT) \
+     : MAX ((COMPUTED), (SPECIFIED)))                  \
+   :  MAX ((COMPUTED), (SPECIFIED)))
+
 /* Make strings word-aligned so strcpy from constants will be faster.  */
 #define CONSTANT_ALIGNMENT(EXP, ALIGN)  \
   ((TREE_CODE (EXP) == STRING_CST      \
@@ -695,7 +903,7 @@ extern struct sparc_cpu_select sparc_select[];
 #define SELECT_RTX_SECTION(MODE, X)            \
 {                                              \
   if (GET_MODE_BITSIZE (MODE) <= MAX_TEXT_ALIGN \
-      && ! (flag_pic && (symbolic_operand (X) || SUNOS4_SHARED_LIBRARIES)))  \
+      && ! (flag_pic && (symbolic_operand ((X), (MODE)) || SUNOS4_SHARED_LIBRARIES)))  \
     text_section ();                           \
   else                                         \
     data_section ();                           \
@@ -718,9 +926,10 @@ extern struct sparc_cpu_select sparc_select[];
 
 #define FIRST_PSEUDO_REGISTER 101
 
+#define SPARC_FIRST_FP_REG     32
 /* Additional V9 fp regs.  */
-#define SPARC_FIRST_V9_FP_REG 64
-#define SPARC_LAST_V9_FP_REG  95
+#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
@@ -729,18 +938,33 @@ extern struct sparc_cpu_select sparc_select[];
 /* Integer CC reg.  We don't distinguish %icc from %xcc.  */
 #define SPARC_ICC_REG 100
 
+/* Nonzero if REGNO is an fp reg.  */
+#define SPARC_FP_REG_P(REGNO) \
+((REGNO) >= SPARC_FIRST_FP_REG && (REGNO) <= SPARC_LAST_V9_FP_REG)
+
+/* Argument passing regs.  */
+#define SPARC_OUTGOING_INT_ARG_FIRST 8
+#define SPARC_INCOMING_INT_ARG_FIRST (TARGET_FLAT ? 8 : 24)
+#define SPARC_FP_ARG_FIRST           32
+
 /* 1 for registers that have pervasive standard uses
    and are not available for the register allocator.
+
    On non-v9 systems:
    g1 is free to use as temporary.
    g2-g4 are reserved for applications.  Gcc normally uses them as
    temporaries, but this can be disabled via the -mno-app-regs option.
    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.  Gcc normally uses them as
+   g1,g5 are free to use as temporaries, and are free to use between calls
+   if the call is to an external function via the PLT.
+   g4 is free to use as a temporary in the non-embedded case.
+   g4 is reserved in the embedded case.
+   g2-g3 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.
+   g6-g7 are reserved for the operating system (or application in
+   embedded case).
    ??? 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
@@ -751,7 +975,7 @@ extern struct sparc_cpu_select sparc_select[];
 */
 
 #define FIXED_REGISTERS  \
- {1, 0, 0, 0, 0, 0, 1, 1,      \
+ {1, 0, 2, 2, 2, 2, 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,      \
@@ -799,18 +1023,19 @@ extern struct sparc_cpu_select sparc_select[];
 #define CONDITIONAL_REGISTER_USAGE                             \
 do                                                             \
   {                                                            \
-    if (! SPARC_ARCH64)                                                \
-      {                                                                \
-       fixed_regs[5] = 1;                                      \
-      }                                                                \
-    if (SPARC_ARCH64)                                          \
+    if (flag_pic)                                              \
       {                                                                \
-       int regno;                                              \
-       fixed_regs[1] = 1;                                      \
-       /* ??? We need to scan argv for -fcall-used-.  */       \
-       for (regno = 48; regno < 80; regno++)                   \
-         call_used_regs[regno] = 0;                            \
+       fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;                \
+       call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;            \
       }                                                                \
+    /* If the user has passed -f{fixed,call-{used,saved}}-g5 */        \
+    /* then honour it.  */                                     \
+    if (TARGET_ARCH32 && fixed_regs[5])                                \
+      fixed_regs[5] = 1;                                       \
+    else if (TARGET_ARCH64 && fixed_regs[5] == 2)              \
+      fixed_regs[5] = 0;                                       \
+    if (TARGET_LIVE_G0)                                                \
+      fixed_regs[0] = 0;                                       \
     if (! TARGET_V9)                                           \
       {                                                                \
        int regno;                                              \
@@ -830,10 +1055,18 @@ do                                                               \
        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 the user has passed -f{fixed,call-{used,saved}}-g2 */        \
+    /* then honour it.  Likewise with g3 and g4.  */           \
+    if (fixed_regs[2] == 2)                                    \
+      fixed_regs[2] = ! TARGET_APP_REGS;                       \
+    if (fixed_regs[3] == 2)                                    \
+      fixed_regs[3] = ! TARGET_APP_REGS;                       \
+    if (TARGET_ARCH32 && fixed_regs[4] == 2)                   \
+      fixed_regs[4] = ! TARGET_APP_REGS;                       \
+    else if (TARGET_CM_EMBMEDANY)                              \
+      fixed_regs[4] = 1;                                       \
+    else if (fixed_regs[4] == 2)                               \
+      fixed_regs[4] = 0;                                       \
     if (TARGET_FLAT)                                           \
       {                                                                \
        /* Let the compiler believe the frame pointer is still  \
@@ -845,10 +1078,10 @@ do                                                               \
       }                                                                \
     if (profile_block_flag)                                    \
       {                                                                \
-       /* %g1 and %g2 must be fixed, because BLOCK_PROFILER    \
-           uses them.  */                                      \
+       /* %g1 and %g2 (sparc32) resp. %g4 (sparc64) must be    \
+          fixed, because BLOCK_PROFILER uses them.  */         \
        fixed_regs[1] = 1;                                      \
-       fixed_regs[2] = 1;                                      \
+       fixed_regs[TARGET_ARCH64 ? 4 : 2] = 1;                  \
       }                                                                \
   }                                                            \
 while (0)
@@ -871,6 +1104,21 @@ while (0)
        : (GET_MODE_SIZE (MODE) + 3) / 4)                               \
    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
 
+/* A subreg in 64 bit mode will have the wrong offset for a floating point
+   register.  The least significant part is at offset 1, compared to 0 for
+   integer registers.  This only applies when FMODE is a larger mode.
+   We also need to handle a special case of TF-->DF conversions.  */
+#define ALTER_HARD_SUBREG(TMODE, WORD, FMODE, REGNO)                   \
+     (TARGET_ARCH64                                                    \
+      && (REGNO) >= SPARC_FIRST_FP_REG                                 \
+      && (REGNO) <= SPARC_LAST_V9_FP_REG                               \
+      && (TMODE) == SImode                                             \
+      && !((FMODE) == QImode || (FMODE) == HImode)                     \
+      ? ((REGNO) + 1)                                                  \
+      : ((TMODE) == DFmode && (FMODE) == TFmode)                       \
+        ? ((REGNO) + ((WORD) * 2))                                     \
+        : ((REGNO) + (WORD)))
+
 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
    See sparc.c for how we initialize this.  */
 extern int *hard_regno_mode_classes;
@@ -902,15 +1150,19 @@ extern int sparc_mode_class[];
 /* Register to use for pushing function arguments.  */
 #define STACK_POINTER_REGNUM 14
 
-/* Actual top-of-stack address is 92/136 greater than the contents of the
+/* Actual top-of-stack address is 92/176 greater than the contents of the
    stack pointer register for !v9/v9.  That is:
    - !v9: 64 bytes for the in and local registers, 4 bytes for structure return
-     address, and 24 bytes for the 6 register parameters.
-   - v9: 128 bytes for the in and local registers + 8 bytes reserved.  */
+     address, and 6*4 bytes for the 6 register parameters.
+   - v9: 128 bytes for the in and local registers + 6*8 bytes for the integer
+     parameter regs.  */
 #define STACK_POINTER_OFFSET FIRST_PARM_OFFSET(0)
 
 /* The stack bias (amount by which the hardware register is offset by).  */
-#define SPARC_STACK_BIAS (TARGET_STACK_BIAS ? 2047 : 0)
+#define SPARC_STACK_BIAS ((TARGET_ARCH64 && TARGET_STACK_BIAS) ? 2047 : 0)
+
+/* Is stack biased? */
+#define STACK_BIAS SPARC_STACK_BIAS
 
 /* Base register for access to local variables of the function.  */
 #define FRAME_POINTER_REGNUM 30
@@ -956,16 +1208,26 @@ extern int sparc_mode_class[];
 
 #define PIC_OFFSET_TABLE_REGNUM 23
 
-#define INITIALIZE_PIC initialize_pic ()
 #define FINALIZE_PIC finalize_pic ()
 
+/* Pick a default value we can notice from override_options:
+   !v9: Default is on.
+   v9: Default is off.  */
+
+#define DEFAULT_PCC_STRUCT_RETURN -1
+
 /* Sparc ABI says that quad-precision floats and all structures are returned
    in memory.
-   For v9, all aggregates are returned in memory.  */
+   For v9: unions <= 32 bytes in size are returned in int regs,
+   structures up to 32 bytes are returned in int and fp regs.  */
+
 #define RETURN_IN_MEMORY(TYPE)                         \
-  (TYPE_MODE (TYPE) == BLKmode                         \
-   || (! TARGET_ARCH64 && (TYPE_MODE (TYPE) == TFmode  \
-                           || TYPE_MODE (TYPE) == TCmode)))
+(TARGET_ARCH32                                         \
+ ? (TYPE_MODE (TYPE) == BLKmode                                \
+    || TYPE_MODE (TYPE) == TFmode                      \
+    || TYPE_MODE (TYPE) == TCmode)                     \
+ : (TYPE_MODE (TYPE) == BLKmode                                \
+    && int_size_in_bytes (TYPE) > 32))
 
 /* Functions which return large structures get the address
    to place the wanted value at offset 64 from the frame.
@@ -978,15 +1240,14 @@ extern int sparc_mode_class[];
 #define STRUCT_VALUE \
   (TARGET_ARCH64                                       \
    ? 0                                                 \
-   : gen_rtx (MEM, Pmode,                              \
-             gen_rtx (PLUS, Pmode, stack_pointer_rtx,  \
-                      gen_rtx (CONST_INT, VOIDmode, STRUCT_VALUE_OFFSET))))
+   : gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx, \
+                                       STRUCT_VALUE_OFFSET)))
+
 #define STRUCT_VALUE_INCOMING \
-  (TARGET_ARCH64                                       \
-   ? 0                                                 \
-   : gen_rtx (MEM, Pmode,                              \
-             gen_rtx (PLUS, Pmode, frame_pointer_rtx,  \
-                      gen_rtx (CONST_INT, VOIDmode, STRUCT_VALUE_OFFSET))))
+  (TARGET_ARCH64                                               \
+   ? 0                                                         \
+   : gen_rtx_MEM (Pmode, plus_constant (frame_pointer_rtx,     \
+                                       STRUCT_VALUE_OFFSET)))
 \f
 /* Define the classes of registers for register constraints in the
    machine description.  Also define ranges of constants.
@@ -1008,7 +1269,9 @@ extern int sparc_mode_class[];
    For any two classes, it is very desirable that there be another
    class that represents their union.  */
 
-/* The SPARC has two kinds of registers, general and floating point.
+/* The SPARC has various kinds of registers: general, floating point,
+   and condition codes [well, it has others as well, but none that we
+   care directly about].
 
    For v9 we must distinguish between the upper and lower floating point
    registers because the upper ones can't hold SFmode values.
@@ -1037,11 +1300,11 @@ extern int sparc_mode_class[];
 
    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?
+   ??? Should %fcc[0123] be handled similarly?
 */
 
-enum reg_class { NO_REGS, FPCC_REGS, GENERAL_REGS, FP_REGS, EXTRA_FP_REGS,
-                GENERAL_OR_FP_REGS, GENERAL_OR_EXTRA_FP_REGS,
+enum reg_class { NO_REGS, FPCC_REGS, I64_REGS, GENERAL_REGS, FP_REGS,
+                EXTRA_FP_REGS, GENERAL_OR_FP_REGS, GENERAL_OR_EXTRA_FP_REGS,
                 ALL_REGS, LIM_REG_CLASSES };
 
 #define N_REG_CLASSES (int) LIM_REG_CLASSES
@@ -1049,15 +1312,16 @@ enum reg_class { NO_REGS, FPCC_REGS, GENERAL_REGS, FP_REGS, EXTRA_FP_REGS,
 /* Give names of register classes as strings for dump file.   */
 
 #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" }
+  { "NO_REGS", "FPCC_REGS", "I64_REGS", "GENERAL_REGS", "FP_REGS",     \
+     "EXTRA_FP_REGS", "GENERAL_OR_FP_REGS", "GENERAL_OR_EXTRA_FP_REGS",        \
+     "ALL_REGS" }
 
 /* Define which registers fit in which classes.
    This is an initializer for a vector of HARD_REG_SET
    of length N_REG_CLASSES.  */
 
 #define REG_CLASS_CONTENTS \
-  {{0, 0, 0, 0}, {0, 0, 0, 0xf}, \
+  {{0, 0, 0, 0}, {0, 0, 0, 0xf}, {0xffff, 0, 0, 0}, \
    {-1, 0, 0, 0}, {0, -1, 0, 0}, {0, -1, -1, 0}, \
    {-1, -1, 0, 0}, {-1, -1, -1, 0}, {-1, -1, -1, 0x1f}}
 
@@ -1075,10 +1339,7 @@ extern enum reg_class sparc_regno_reg_class[];
    We put %f0/%f1 last among the float registers, so as to make it more
    likely that a pseudo-register which dies in the float return register
    will get allocated to the float return register, thus saving a move
-   instruction at the end of the function.
-
-   The float registers are ordered a little "funny" because in the 64 bit
-   architecture, some of them (%f16-%f47) are call-preserved.  */
+   instruction at the end of the function.  */
 
 #define REG_ALLOC_ORDER \
 { 8, 9, 10, 11, 12, 13, 2, 3,          \
@@ -1086,38 +1347,37 @@ extern enum reg_class sparc_regno_reg_class[];
   23, 24, 25, 26, 27, 28, 29, 31,      \
   34, 35, 36, 37, 38, 39,              /* %f2-%f7 */   \
   40, 41, 42, 43, 44, 45, 46, 47,      /* %f8-%f15 */  \
-  80, 81, 82, 83, 84, 85, 86, 87,      /* %f48-%f55 */ \
-  88, 89, 90, 91, 92, 93, 94, 95,      /* %f56-%f63 */ \
   48, 49, 50, 51, 52, 53, 54, 55,      /* %f16-%f23 */ \
   56, 57, 58, 59, 60, 61, 62, 63,      /* %f24-%f31 */ \
   64, 65, 66, 67, 68, 69, 70, 71,      /* %f32-%f39 */ \
   72, 73, 74, 75, 76, 77, 78, 79,      /* %f40-%f47 */ \
+  80, 81, 82, 83, 84, 85, 86, 87,      /* %f48-%f55 */ \
+  88, 89, 90, 91, 92, 93, 94, 95,      /* %f56-%f63 */ \
   32, 33,                              /* %f0,%f1 */   \
   96, 97, 98, 99, 100,                 /* %fcc0-3, %icc */ \
   1, 4, 5, 6, 7, 0, 14, 30}
 
 /* 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.
-   The floating point registers are ordered a little "funny" because in the
-   64 bit architecture some of them (%f16-%f47) are call-preserved.   */
+   leaf functions.  If all registers can fit in the "gi" registers,
+   then we have the possibility of having a leaf function.  */
 
 #define REG_LEAF_ALLOC_ORDER \
 { 2, 3, 24, 25, 26, 27, 28, 29,                \
+  4, 5, 6, 7, 1,                       \
   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,      \
-  80, 81, 82, 83, 84, 85, 86, 87,      \
-  88, 89, 90, 91, 92, 93, 94, 95,      \
   48, 49, 50, 51, 52, 53, 54, 55,      \
   56, 57, 58, 59, 60, 61, 62, 63,      \
   64, 65, 66, 67, 68, 69, 70, 71,      \
   72, 73, 74, 75, 76, 77, 78, 79,      \
+  80, 81, 82, 83, 84, 85, 86, 87,      \
+  88, 89, 90, 91, 92, 93, 94, 95,      \
   32, 33,                              \
   96, 97, 98, 99, 100,                 \
-  1, 4, 5, 6, 7, 0, 14, 30, 31}
-
+  0, 14, 30, 31}
+  
 #define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc ()
 
 /* ??? %g7 is not a leaf register to effectively #undef LEAF_REGISTERS when
@@ -1153,17 +1413,23 @@ extern char leaf_reg_remap[];
 
 /* 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.  */
-
-#define REG_CLASS_FROM_LETTER(C) \
-(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   \
+   .md file for v8 and v9.
+   'd' and 'b' are used for single and double precision VIS operations,
+   if TARGET_VIS.
+   'h' is used for V8+ 64 bit global and out registers. */
+
+#define REG_CLASS_FROM_LETTER(C)               \
+(TARGET_V9                                     \
+ ? ((C) == 'f' ? FP_REGS                       \
+    : (C) == 'e' ? EXTRA_FP_REGS               \
+    : (C) == 'c' ? FPCC_REGS                   \
+    : ((C) == 'd' && TARGET_VIS) ? FP_REGS\
+    : ((C) == 'b' && TARGET_VIS) ? EXTRA_FP_REGS\
+    : ((C) == 'h' && TARGET_V8PLUS) ? I64_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
@@ -1178,17 +1444,22 @@ extern char leaf_reg_remap[];
    `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 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)
+#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)))
+/* 13 bit immediate, considering only the low 32 bits */
+#define SMALL_INT32(X) (SPARC_SIMM13_P ((int)INTVAL (X) & 0xffffffff))
+#define SPARC_SETHI_P(X) \
+(((unsigned HOST_WIDE_INT) (X) & \
+  (TARGET_ARCH64 ? ~(unsigned HOST_WIDE_INT) 0xfffffc00 : 0x3ff)) == 0)
 
 #define CONST_OK_FOR_LETTER_P(VALUE, C)  \
   ((C) == 'I' ? SPARC_SIMM13_P (VALUE)                 \
    : (C) == 'J' ? (VALUE) == 0                         \
-   : (C) == 'K' ? ((VALUE) & 0x3ff) == 0               \
+   : (C) == 'K' ? SPARC_SETHI_P (VALUE)                        \
    : (C) == 'L' ? SPARC_SIMM11_P (VALUE)               \
    : (C) == 'M' ? SPARC_SIMM10_P (VALUE)               \
    : 0)
@@ -1197,45 +1468,68 @@ extern char leaf_reg_remap[];
    Here VALUE is the CONST_DOUBLE rtx itself.  */
 
 #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
-  ((C) == 'G' ? fp_zero_operand (VALUE)                        \
-   : (C) == 'H' ? arith_double_operand (VALUE, DImode) \
+  ((C) == 'G' ? fp_zero_operand (VALUE, GET_MODE (VALUE))      \
+   : (C) == 'H' ? arith_double_operand (VALUE, DImode)         \
    : 0)
 
 /* Given an rtx X being reloaded into a reg required to be
    in class CLASS, return the class of reg to actually use.
    In general this is just CLASS; but on some machines
    in some cases it is preferable to use a more restrictive class.  */
-/* We can't load constants into FP registers.  We can't load any FP constant
-   if an 'E' constraint fails to match it.  */
+/* - We can't load constants into FP registers.
+   - We can't load FP constants into integer registers when soft-float,
+     because there is no soft-float pattern with a r/F constraint.
+   - Try and reload integer constants (symbolic or otherwise) back into
+     registers directly, rather than having them dumped to memory.  */
+
 #define PREFERRED_RELOAD_CLASS(X,CLASS)                        \
   (CONSTANT_P (X)                                      \
-   && (FP_REG_CLASS_P (CLASS)                          \
+   ? ((FP_REG_CLASS_P (CLASS)                          \
        || (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
-          && (HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT   \
-              || HOST_BITS_PER_INT != BITS_PER_WORD))) \
-   ? NO_REGS : (CLASS))
+          && ! TARGET_FPU))                            \
+      ? NO_REGS                                                \
+      : (!FP_REG_CLASS_P (CLASS)                       \
+         && GET_MODE_CLASS (GET_MODE (X)) == MODE_INT) \
+      ? GENERAL_REGS                                   \
+      : (CLASS))                                       \
+   : (CLASS))
 
 /* Return the register class of a scratch register needed to load IN into
    a register of class CLASS in MODE.
 
-   On the SPARC, when PIC, we need a temporary when loading some addresses
-   into a register.
-
-   Also, we need a temporary when loading/storing a HImode/QImode value
+   We need a temporary when loading/storing a HImode/QImode value
    between memory and the FPU registers.  This can happen when combine puts
    a paradoxical subreg in a float/fix conversion insn.  */
 
 #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN)          \
-  ((FP_REG_CLASS_P (CLASS) && ((MODE) == HImode || (MODE) == QImode) \
+  ((FP_REG_CLASS_P (CLASS)                                     \
+    && ((MODE) == HImode || (MODE) == QImode)                  \
     && (GET_CODE (IN) == MEM                                   \
-       || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG)   \
-           && true_regnum (IN) == -1))) ? GENERAL_REGS : NO_REGS)
+        || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG)  \
+            && true_regnum (IN) == -1)))                       \
+   ? GENERAL_REGS                                              \
+   : (((TARGET_CM_MEDANY                                       \
+        && symbolic_operand ((IN), (MODE)))                    \
+       || (TARGET_CM_EMBMEDANY                                 \
+           && text_segment_operand ((IN), (MODE))))            \
+      && !flag_pic)                                            \
+     ? GENERAL_REGS                                            \
+     : NO_REGS)
 
 #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, IN)         \
-  ((FP_REG_CLASS_P (CLASS) && ((MODE) == HImode || (MODE) == QImode) \
-    && (GET_CODE (IN) == MEM                                   \
-       || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG)   \
-           && true_regnum (IN) == -1))) ? GENERAL_REGS : NO_REGS)
+   ((FP_REG_CLASS_P (CLASS)                                    \
+     && ((MODE) == HImode || (MODE) == QImode)                 \
+     && (GET_CODE (IN) == MEM                                  \
+         || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG) \
+             && true_regnum (IN) == -1)))                      \
+    ? GENERAL_REGS                                             \
+   : (((TARGET_CM_MEDANY                                       \
+        && symbolic_operand ((IN), (MODE)))                    \
+       || (TARGET_CM_EMBMEDANY                                 \
+           && text_segment_operand ((IN), (MODE))))            \
+      && !flag_pic)                                            \
+     ? GENERAL_REGS                                            \
+     : NO_REGS)
 
 /* On SPARC it is not possible to directly move data between 
    GENERAL_REGS and FP_REGS.  */
@@ -1249,10 +1543,10 @@ extern char leaf_reg_remap[];
 #define SECONDARY_MEMORY_NEEDED_RTX(MODE) \
   (get_frame_size () == 0                                              \
    ? assign_stack_local (MODE, GET_MODE_SIZE (MODE), 0)                        \
-   : gen_rtx (MEM, MODE, gen_rtx (PLUS, Pmode, frame_pointer_rtx,      \
-                                 GEN_INT (STARTING_FRAME_OFFSET))))
+   : gen_rtx_MEM (MODE, plus_constant (frame_pointer_rtx,              \
+                                      STARTING_FRAME_OFFSET)))
 
-/* Get_secondary_mem widens it's argument to BITS_PER_WORD which loses on v9
+/* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on v9
    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) \
@@ -1274,13 +1568,15 @@ extern char leaf_reg_remap[];
 /* Stack layout; function entry, exit and calling.  */
 
 /* Define the number of register that can hold parameters.
-   These two macros are used only in other macro definitions below.
+   This macro is only used in other macro definitions below and in sparc.c.
    MODE is the mode of the argument.
    !v9: All args are passed in %o0-%o5.
-   v9: Non-float args are passed in %o0-5 and float args are passed in
-   %f0-%f15.  */
+   v9: %o0-%o5 and %f0-%f31 are cumulatively used to pass values.
+   See the description in sparc.c.  */
 #define NPARM_REGS(MODE) \
-  (TARGET_ARCH64 ? (GET_MODE_CLASS (MODE) == MODE_FLOAT ? 16 : 6) : 6)
+(TARGET_ARCH64 \
+ ? (GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 : 6) \
+ : 6)
 
 /* Define this if pushing a word on the stack
    makes the stack pointer a smaller address.  */
@@ -1309,16 +1605,25 @@ extern char leaf_reg_remap[];
 /* Offset of first parameter from the argument pointer register value.
    !v9: This is 64 for the ins and locals, plus 4 for the struct-return reg
    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.  */
+   v9: This is 128 for the ins and locals.  */
 #define FIRST_PARM_OFFSET(FNDECL) \
-  (TARGET_ARCH64 ? (SPARC_STACK_BIAS + 136) \
+  (TARGET_ARCH64 ? (SPARC_STACK_BIAS + 16 * UNITS_PER_WORD) \
    : (STRUCT_VALUE_OFFSET + UNITS_PER_WORD))
 
+/* Offset from the argument pointer register value to the CFA.  */
+
+#define ARG_POINTER_CFA_OFFSET  SPARC_STACK_BIAS
+
 /* When a parameter is passed in a register, stack space is still
-   allocated for it.  */
-#if ! SPARC_ARCH64
-#define REG_PARM_STACK_SPACE(DECL) (NPARM_REGS (SImode) * UNITS_PER_WORD)
-#endif
+   allocated for it.
+   !v9: All 6 possible integer registers have backing store allocated.
+   v9: Only space for the arguments passed is allocated. */
+/* ??? Ideally, we'd use zero here (as the minimum), but zero has special
+   meaning to the backend.  Further, we need to be able to detect if a
+   varargs/unprototyped function is called, as they may want to spill more
+   registers than we've provided space.  Ugly, ugly.  So for now we retain
+   all 6 slots even for v9.  */
+#define REG_PARM_STACK_SPACE(DECL) (6 * UNITS_PER_WORD)
 
 /* Keep the stack pointer constant throughout the function.
    This is both an optimization and a necessity: longjmp
@@ -1338,24 +1643,28 @@ extern char leaf_reg_remap[];
 /* Some subroutine macros specific to this machine.
    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_ARCH64 \
-   ? (TARGET_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 : 8) \
+#define BASE_RETURN_VALUE_REG(MODE)                                    \
+  (TARGET_ARCH64                                                       \
+   ? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 8)                      \
    : (((MODE) == SFmode || (MODE) == DFmode) && TARGET_FPU ? 32 : 8))
-#define BASE_OUTGOING_VALUE_REG(MODE) \
-  (TARGET_ARCH64 \
-   ? (TARGET_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 \
-      : TARGET_FLAT ? 8 : 24) \
+
+#define BASE_OUTGOING_VALUE_REG(MODE)                          \
+  (TARGET_ARCH64                                               \
+   ? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32                   \
+      : TARGET_FLAT ? 8 : 24)                                  \
    : (((MODE) == SFmode || (MODE) == DFmode) && TARGET_FPU ? 32        \
       : (TARGET_FLAT ? 8 : 24)))
-#define BASE_PASSING_ARG_REG(MODE) \
-  (TARGET_ARCH64 \
-   ? (TARGET_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 : 8) \
+
+#define BASE_PASSING_ARG_REG(MODE)                             \
+  (TARGET_ARCH64                                               \
+   ? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 8)              \
    : 8)
-#define BASE_INCOMING_ARG_REG(MODE) \
-  (TARGET_ARCH64 \
-   ? (TARGET_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 \
-      : TARGET_FLAT ? 8 : 24) \
+
+/* ??? FIXME -- seems wrong for v9 structure passing... */
+#define BASE_INCOMING_ARG_REG(MODE)                            \
+  (TARGET_ARCH64                                               \
+   ? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32                   \
+      : TARGET_FLAT ? 8 : 24)                                  \
    : (TARGET_FLAT ? 8 : 24))
 
 /* Define this macro if the target machine has "register windows".  This
@@ -1381,19 +1690,19 @@ extern char leaf_reg_remap[];
 
 /* On SPARC the value is found in the first "output" register.  */
 
-#define FUNCTION_VALUE(VALTYPE, FUNC)  \
-  gen_rtx (REG, TYPE_MODE (VALTYPE), BASE_RETURN_VALUE_REG (TYPE_MODE (VALTYPE)))
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+  function_value ((VALTYPE), TYPE_MODE (VALTYPE), 1)
 
 /* But the called function leaves it in the first "input" register.  */
 
-#define FUNCTION_OUTGOING_VALUE(VALTYPE, FUNC)  \
-  gen_rtx (REG, TYPE_MODE (VALTYPE), BASE_OUTGOING_VALUE_REG (TYPE_MODE (VALTYPE)))
+#define FUNCTION_OUTGOING_VALUE(VALTYPE, FUNC) \
+  function_value ((VALTYPE), TYPE_MODE (VALTYPE), 0)
 
 /* Define how to find the value returned by a library function
    assuming the value has mode MODE.  */
 
-#define LIBCALL_VALUE(MODE)    \
-  gen_rtx (REG, MODE, BASE_RETURN_VALUE_REG (MODE))
+#define LIBCALL_VALUE(MODE) \
+  function_value (NULL_TREE, (MODE), 1)
 
 /* 1 if N is a possible register number for a function value
    as seen by the caller.
@@ -1408,11 +1717,12 @@ extern char leaf_reg_remap[];
 #define APPLY_RESULT_SIZE 16
 
 /* 1 if N is a possible register number for function argument passing.
-   On SPARC, these are the "output" registers.  v9 also uses %f0-%f15.  */
+   On SPARC, these are the "output" registers.  v9 also uses %f0-%f31.  */
 
 #define FUNCTION_ARG_REGNO_P(N) \
-  (TARGET_ARCH64 ? (((N) < 14 && (N) > 7) || (N) > 31 && (N) < 48) \
-   : ((N) < 14 && (N) > 7))
+(TARGET_ARCH64 \
+ ? (((N) >= 8 && (N) <= 13) || ((N) >= 32 && (N) <= 63)) \
+ : ((N) >= 8 && (N) <= 13))
 \f
 /* Define a data type for recording info about an argument list
    during the scan of that argument list.  This data type should
@@ -1425,129 +1735,35 @@ extern char leaf_reg_remap[];
    if any, which holds the structure-value-address).
    Thus 7 or more means all following args should go on the stack.
 
-   For v9, we record how many of each type has been passed.  Different
-   types get passed differently.
-
-       - Float args are passed in %f0-15, after which they go to the stack
-         where floats and doubles are passed 8 byte aligned and long doubles
-         are passed 16 byte aligned.
-       - All aggregates are passed by reference.  The callee copies
-         the structure if necessary, except if stdarg/varargs and the struct
-         matches the ellipse in which case the caller makes a copy.
-       - Any non-float argument might be split between memory and reg %o5.
-         ??? I don't think this can ever happen now that structs are no
-         longer passed in regs.
-
-   For v9 return values:
+   For v9, we also need to know whether a prototype is present.  */
 
-       - For all aggregates, the caller allocates space for the return value,
-          and passes the pointer as an implicit first argument, which is
-          allocated like all other arguments.
-       - The unimp instruction stuff for structure returns is gone.  */
-
-#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) */
+  int words;       /* number of words passed so far */
+  int prototype_p; /* non-zero if a prototype is present */
+  int libcall_p;   /* non-zero if a library call */
 };
 #define CUMULATIVE_ARGS struct sparc_args
 
-/* Return index into CUMULATIVE_ARGS.  */
-
-#define GET_SPARC_ARG_CLASS(MODE) \
-  (GET_MODE_CLASS (MODE) == MODE_FLOAT ? SPARC_ARG_FLOAT : SPARC_ARG_INT)
-
-/* Round a register number up to a proper boundary for an arg of mode MODE.
-   This macro is only used in this file.
-
-   The "& (0x10000 - ...)" is used to round up to the next appropriate reg.  */
-
-#define ROUND_REG(CUM, MODE)                           \
-  (GET_MODE_CLASS (MODE) != MODE_FLOAT                 \
-   ? (CUM).arg_count[(int) GET_SPARC_ARG_CLASS (MODE)] \
-   : ((CUM).arg_count[(int) GET_SPARC_ARG_CLASS (MODE)]        \
-      + GET_MODE_UNIT_SIZE (MODE) / 4 - 1)             \
-     & (0x10000 - GET_MODE_UNIT_SIZE (MODE) / 4))
-
-#define ROUND_ADVANCE(SIZE)    \
-  (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-#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 /* ! SPARC_ARCH64 */
-
 /* Initialize a variable CUM of type CUMULATIVE_ARGS
    for a call to a function whose data type is FNTYPE.
-   For a library call, FNTYPE is 0.
-
-   On SPARC, the offset always starts at 0: the first parm reg is always
-   the same reg.  */
+   For a library call, FNTYPE is 0.  */
 
-#if SPARC_ARCH64
-extern int sparc_arg_count,sparc_n_named_args;
-#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;                        \
-    sparc_arg_count = 0;                                       \
-    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,INDIRECT) ((CUM) = 0)
-#endif
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
+init_cumulative_args (& (CUM), (FNTYPE), (LIBNAME), (INDIRECT));
 
 /* 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.)  */
+   TYPE is null for libcalls where that information may not be available.  */
 
-#if SPARC_ARCH64
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)           \
-  do {                                                         \
-    (CUM).arg_count[(int) GET_SPARC_ARG_CLASS (MODE)] =                \
-      ROUND_REG ((CUM), (MODE))                                        \
-       + (GET_MODE_CLASS (MODE) == MODE_FLOAT                  \
-          ? GET_MODE_SIZE (MODE) / 4                           \
-          : ROUND_ADVANCE ((MODE) == BLKmode                   \
-                           ? GET_MODE_SIZE (Pmode)             \
-                           : GET_MODE_SIZE (MODE)));           \
-    sparc_arg_count++;                                         \
-  } while (0)
-#else
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)   \
-  ((CUM) += ((MODE) != BLKmode                         \
-            ? ROUND_ADVANCE (GET_MODE_SIZE (MODE))     \
-            : ROUND_ADVANCE (int_size_in_bytes (TYPE))))
-#endif
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+function_arg_advance (& (CUM), (MODE), (TYPE), (NAMED))
 
-/* Return boolean indicating arg of mode MODE will be passed in a reg.
-   This macro is only used in this file.  */
+/* Nonzero if we do not know how to pass TYPE solely in registers.  */
 
-#if SPARC_ARCH64
-#define PASS_IN_REG_P(CUM, MODE, TYPE)                         \
-  (ROUND_REG ((CUM), (MODE)) < NPARM_REGS (MODE)               \
-   && ((TYPE)==0 || ! TREE_ADDRESSABLE ((tree)(TYPE)))         \
-   && ((TYPE)==0 || (MODE) != BLKmode))
-#else
-#define PASS_IN_REG_P(CUM, MODE, TYPE)                         \
-  ((CUM) < NPARM_REGS (SImode)                                 \
-   && ((TYPE)==0 || ! TREE_ADDRESSABLE ((tree)(TYPE)))         \
-   && ((TYPE)==0 || (MODE) != BLKmode                          \
-       || (TYPE_ALIGN (TYPE) % PARM_BOUNDARY == 0)))
-#endif
+#define MUST_PASS_IN_STACK(MODE,TYPE)                  \
+  ((TYPE) != 0                                         \
+   && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST     \
+       || TREE_ADDRESSABLE (TYPE)))
 
 /* Determine where to put an argument to a function.
    Value is zero to push the argument on the stack,
@@ -1562,91 +1778,56 @@ extern int sparc_arg_count,sparc_n_named_args;
    NAMED is nonzero if this argument is a named parameter
     (otherwise it is an extra parameter matching an ellipsis).  */
 
-/* On SPARC the first six args are normally in registers
-   and the rest are pushed.  Any arg that starts within the first 6 words
-   is at least partially passed in a register unless its data type forbids.
-   For v9, the first 6 int args are passed in regs and the first N
-   float args are passed in regs (where N is such that %f0-15 are filled).
-   The rest are pushed.  Any arg that starts within the first 6 words
-   is at least partially passed in a register unless its data type forbids.  */
-
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED)                           \
-  (PASS_IN_REG_P ((CUM), (MODE), (TYPE))                               \
-   ? gen_rtx (REG, (MODE),                                             \
-             (BASE_PASSING_ARG_REG (MODE) + ROUND_REG ((CUM), (MODE))))\
-   : 0)
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+function_arg (& (CUM), (MODE), (TYPE), (NAMED), 0)
 
 /* Define where a function finds its arguments.
    This is different from FUNCTION_ARG because of register windows.  */
 
-#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED)                  \
-  (PASS_IN_REG_P ((CUM), (MODE), (TYPE))                               \
-   ? gen_rtx (REG, (MODE),                                             \
-             (BASE_INCOMING_ARG_REG (MODE) + ROUND_REG ((CUM), (MODE))))\
-   : 0)
+#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
+function_arg (& (CUM), (MODE), (TYPE), (NAMED), 1)
 
 /* For an arg passed partly in registers and partly in memory,
    this is the number of registers used.
-   For args passed entirely in registers or entirely in memory, zero.
-   Any arg that starts in the first 6 regs but won't entirely fit in them
-   needs partial registers on the Sparc (!v9).  On v9, there are no arguments
-   that are passed partially in registers (??? complex values?).  */
-
-#if ! SPARC_ARCH64
-#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED)             \
-  (PASS_IN_REG_P ((CUM), (MODE), (TYPE))                               \
-   && ((CUM) + ((MODE) == BLKmode                                      \
-               ? ROUND_ADVANCE (int_size_in_bytes (TYPE))              \
-               : ROUND_ADVANCE (GET_MODE_SIZE (MODE))) - NPARM_REGS (SImode) > 0)\
-   ? (NPARM_REGS (SImode) - (CUM))                                     \
-   : 0)
-#endif
-
-/* 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 && 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.
-   If the callee can determine that the argument won't be modified, it can
-   avoid the copy.  */
-/* ??? 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.  */
-
-#if SPARC_ARCH64
-#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \
-  (sparc_arg_count < sparc_n_named_args)
-#endif
+   For args passed entirely in registers or entirely in memory, zero.  */
+
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
+function_arg_partial_nregs (& (CUM), (MODE), (TYPE), (NAMED))
+
+/* A C expression that indicates when an argument must be passed by reference.
+   If nonzero for an argument, a copy of that argument is made in memory and a
+   pointer to the argument is passed instead of the argument itself.
+   The pointer is passed in whatever way is appropriate for passing a pointer
+   to that type.  */
+
+#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
+function_arg_pass_by_reference (& (CUM), (MODE), (TYPE), (NAMED))
+
+/* If defined, a C expression which determines whether, and in which direction,
+   to pad out an argument with extra space.  The value should be of type
+   `enum direction': either `upward' to pad above the argument,
+   `downward' to pad below, or `none' to inhibit padding.  */
+
+#define FUNCTION_ARG_PADDING(MODE, TYPE) \
+function_arg_padding ((MODE), (TYPE))
+
+/* If defined, a C expression that gives the alignment boundary, in bits,
+   of an argument with the specified mode and type.  If it is not defined,
+   PARM_BOUNDARY is used for all arguments.
+   For sparc64, objects requiring 16 byte alignment are passed that way.  */
+
+#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
+((TARGET_ARCH64                                        \
+  && (GET_MODE_ALIGNMENT (MODE) == 128         \
+      || ((TYPE) && TYPE_ALIGN (TYPE) == 128)))        \
+ ? 128 : PARM_BOUNDARY)
 \f
-/* Initialize data used by insn expanders.  This is called from
-   init_emit, once for each function, before code is generated.
-   For v9, clear the temp slot used by float/int DImode conversions.
-   ??? There is the 16 bytes at [%fp-16], however we'd like to delete this
-   space at some point.
-   ??? Use assign_stack_temp?  */
-
-extern void sparc64_init_expanders ();
-extern struct rtx_def *sparc64_fpconv_stack_temp ();
-#if SPARC_ARCH64
-#define INIT_EXPANDERS sparc64_init_expanders ()
-#endif
-
 /* Define the information needed to generate branch and scc insns.  This is
    stored from the compare operation.  Note that we can't use "rtx" here
    since it hasn't been defined!  */
 
 extern struct rtx_def *sparc_compare_op0, *sparc_compare_op1;
 
-/* Define the function that build the compare insn for scc and bcc.  */
-
-extern struct rtx_def *gen_compare_reg ();
-
-/* This function handles all v9 scc insns */
-
-extern int gen_v9_scc ();
 \f
 /* Generate the special assembly code needed to tell the assembler whatever
    it might need to know about the return value of a function.
@@ -1656,7 +1837,7 @@ extern int gen_v9_scc ();
    the assembler).  */
 
 #define ASM_DECLARE_RESULT(FILE, RESULT) \
-  fprintf ((FILE), "\t.proc\t0%o\n", sparc_type_code (TREE_TYPE (RESULT)))
+  fprintf ((FILE), "\t.proc\t0%lo\n", sparc_type_code (TREE_TYPE (RESULT)))
 
 /* Output the label for a function definition.  */
 
@@ -1666,6 +1847,44 @@ do {                                                                     \
   ASM_OUTPUT_LABEL (FILE, NAME);                                       \
 } while (0)
 
+/* Output the special assembly code needed to tell the assembler some
+   register is used as global register variable.  
+
+   SPARC 64bit psABI declares registers %g2 and %g3 as application
+   registers and %g6 and %g7 as OS registers.  Any object using them
+   should declare (for %g2/%g3 has to, for %g6/%g7 can) that it uses them
+   and how they are used (scratch or some global variable).
+   Linker will then refuse to link together objects which use those
+   registers incompatibly.
+
+   Unless the registers are used for scratch, two different global
+   registers cannot be declared to the same name, so in the unlikely
+   case of a global register variable occupying more than one register
+   we prefix the second and following registers with .gnu.part1. etc.  */
+
+extern char sparc_hard_reg_printed[8];
+
+#ifdef HAVE_AS_REGISTER_PSEUDO_OP
+#define ASM_DECLARE_REGISTER_GLOBAL(FILE, DECL, REGNO, NAME)           \
+do {                                                                   \
+  if (TARGET_ARCH64)                                                   \
+    {                                                                  \
+      int end = HARD_REGNO_NREGS ((REGNO), DECL_MODE (decl)) + (REGNO); \
+      int reg;                                                         \
+      for (reg = (REGNO); reg < 8 && reg < end; reg++)                 \
+       if ((reg & ~1) == 2 || (reg & ~1) == 6)                         \
+         {                                                             \
+           if (reg == (REGNO))                                         \
+             fprintf ((FILE), "\t.register\t%%g%d, %s\n", reg, (NAME)); \
+           else                                                        \
+             fprintf ((FILE), "\t.register\t%%g%d, .gnu.part%d.%s\n",  \
+                      reg, reg - (REGNO), (NAME));                     \
+           sparc_hard_reg_printed[reg] = 1;                            \
+         }                                                             \
+    }                                                                  \
+} while (0)
+#endif
+
 /* This macro generates the assembly code for function entry.
    FILE is a stdio stream to output the code to.
    SIZE is an int: how many units of temporary storage to allocate.
@@ -1682,264 +1901,40 @@ do {                                                                   \
    to do a "save" insn.  The decision about whether or not
    to do this is made in regclass.c.  */
 
-extern int leaf_function;
 #define FUNCTION_PROLOGUE(FILE, SIZE) \
-  (TARGET_FLAT ? sparc_flat_output_function_prologue (FILE, SIZE) \
-   : output_function_prologue (FILE, SIZE, leaf_function))
+  (TARGET_FLAT ? sparc_flat_output_function_prologue (FILE, (int)SIZE) \
+   : output_function_prologue (FILE, (int)SIZE, \
+                              current_function_uses_only_leaf_regs))
 \f
 /* Output assembler code to FILE to increment profiler label # LABELNO
-   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 {                                                         \
-    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 %o0,%lo(", FILE);             \
-    assemble_name (FILE, buf);                                 \
-    fputs ("),%o0\n", FILE);                                   \
-    if (! TARGET_ARCH64)                                       \
-      fputs ("\tld [%fp-4],%g2\n", FILE);                      \
-  } 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:
+   for profiling a function entry.  */
 
-      No profiling done.
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+  sparc_function_profiler(FILE, LABELNO)
 
-   profile_block_flag == 1, -a option used.
+/* Set the name of the mcount function for the system.  */
 
-      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'.
-
-*/
+#define MCOUNT_FUNCTION "*mcount"
 
 /* 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
+   to initialize basic-block profiling.  */
 
-    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)
+#define FUNCTION_BLOCK_PROFILER(FILE, BLOCK_OR_LABEL) \
+  sparc_function_block_profiler(FILE, BLOCK_OR_LABEL)
 
 /* 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.
+   to increment a counter associated with basic block number BLOCKNO.  */
 
-       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); \
-        break;                         \
-      }                                        \
-  }                                    \
-while(0)
+#define BLOCK_PROFILER(FILE, BLOCKNO) \
+  sparc_block_profiler (FILE, BLOCKNO)
 
 /* 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.
-*/
+   to indicate a return from function during basic-block profiling.  */
 
 #define FUNCTION_BLOCK_PROFILER_EXIT(FILE) \
-  fprintf (FILE, "\tcall ___bb_trace_ret\n\tnop\n" );
+  sparc_function_block_profiler_exit(FILE)
+
+#ifdef IN_LIBGCC2
 
 /* The function `__bb_trace_func' is called in every basic block
    and is not allowed to change the machine state. Saving (restoring)
@@ -1960,21 +1955,42 @@ while(0)
    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 ")]");
+   and hope that this is enough.
+   
+   On V9, life is much sweater:  there is a user accessible %ccr
+   register, but we use it for 64bit libraries only.  */
+
+#if TARGET_ARCH32
+
+#define MACHINE_STATE_SAVE(ID)                 \
+  int ms_flags, ms_saveret;                    \
+  asm volatile(                                        \
+       "mov %%g2,%1\n\
+       mov %%g0,%0\n\
+       be,a LFLGNZ"ID"\n\
+       or %0,4,%0\n\
+LFLGNZ"ID":\n\
+       bcs,a LFLGNC"ID"\n\
+       or %0,1,%0\n\
+LFLGNC"ID":\n\
+       bvs,a LFLGNV"ID"\n\
+       or %0,2,%0\n\
+LFLGNV"ID":\n\
+       bneg,a LFLGNN"ID"\n\
+       or %0,8,%0\n\
+LFLGNN"ID":"                                   \
+       : "=r"(ms_flags), "=r"(ms_saveret));
+
+#else
+
+#define MACHINE_STATE_SAVE(ID)                 \
+  unsigned long ms_flags, ms_saveret;          \
+  asm volatile(                                        \
+       "mov %%g4,%1\n\
+       rd %%ccr,%0"                            \
+       : "=r"(ms_flags), "=r"(ms_saveret));
+
+#endif
 
 /* On sparc MACHINE_STATE_RESTORE restores the psw register from memory.
    The psw register can be written in supervisor mode only,
@@ -1984,83 +2000,86 @@ while(0)
    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 ":");
+#if TARGET_ARCH32
+
+#define MACHINE_STATE_RESTORE(ID)                              \
+{ extern char flgtab[] __asm__("LFLGTAB"ID);                   \
+  int scratch;                                                 \
+  asm volatile (                                               \
+       "jmpl %2+%1,%%g0\n\
+    ! Do part of VC in the delay slot here, as it needs 3 insns.\n\
+        addcc 2,%3,%%g0\n\
+LFLGTAB" ID ":\n\
+    ! 0\n\
+       ba LFLGRET"ID"\n\
+        orcc 1,%%g0,%%g0\n\
+    ! C\n\
+       ba LFLGRET"ID"\n\
+        addcc 2,%3,%%g0\n\
+    ! V\n\
+       unimp\n\
+       nop\n\
+    ! VC\n\
+       ba LFLGRET"ID"\n\
+        addxcc %4,%4,%0\n\
+    ! Z\n\
+       ba LFLGRET"ID"\n\
+        subcc %%g0,%%g0,%%g0\n\
+    ! ZC\n\
+       ba LFLGRET"ID"\n\
+        addcc 1,%3,%0\n\
+    ! ZVC\n\
+       ba LFLGRET"ID"\n\
+        addcc %4,%4,%0\n\
+    ! N\n\
+       ba LFLGRET"ID"\n\
+        orcc %%g0,-1,%%g0\n\
+    ! NC\n\
+       ba LFLGRET"ID"\n\
+        addcc %%g0,%3,%%g0\n\
+    ! NV\n\
+       unimp\n\
+       nop\n\
+    ! NVC\n\
+       unimp\n\
+       nop\n\
+    ! NZ\n\
+       unimp\n\
+       nop\n\
+    ! NZC\n\
+       unimp\n\
+       nop\n\
+    ! NZV\n\
+       unimp\n\
+       nop\n\
+    ! NZVC\n\
+       unimp\n\
+       nop\n\
+LFLGRET"ID":\n\
+       mov %5,%%g2"                                            \
+       : "=r"(scratch)                                         \
+       : "r"(ms_flags*8), "r"(flgtab), "r"(-1),                \
+         "r"(0x80000000), "r"(ms_saveret)                      \
+       : "cc", "g2"); }
+
+#else
+
+#define MACHINE_STATE_RESTORE(ID)                              \
+  asm volatile (                                               \
+       "wr %0,0,%%ccr\n\
+       mov %1,%%g4"                                            \
+       : : "r"(ms_flags), "r"(ms_saveret)                      \
+       : "cc", "g4");
+
+#endif
+
+#endif /* IN_LIBGCC2 */
 \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.
    No definition is equivalent to always zero.  */
 
-extern int current_function_calls_alloca;
-extern int current_function_outgoing_args_size;
-
 #define EXIT_IGNORE_STACK      \
  (get_frame_size () != 0       \
   || current_function_calls_alloca || current_function_outgoing_args_size)
@@ -2075,14 +2094,10 @@ extern int current_function_outgoing_args_size;
    of alloca; we also take advantage of it to omit stack adjustments
    before returning.  */
 
-/* This declaration is needed due to traditional/ANSI
-   incompatibilities which cannot be #ifdefed away
-   because they occur inside of macros.  Sigh.  */
-extern union tree_node *current_function_decl;
-
 #define FUNCTION_EPILOGUE(FILE, SIZE) \
-  (TARGET_FLAT ? sparc_flat_output_function_epilogue (FILE, SIZE) \
-   : output_function_epilogue (FILE, SIZE, leaf_function))
+  (TARGET_FLAT ? sparc_flat_output_function_epilogue (FILE, (int)SIZE) \
+   : output_function_epilogue (FILE, (int)SIZE, \
+                              current_function_uses_only_leaf_regs))
 
 #define DELAY_SLOTS_FOR_EPILOGUE \
   (TARGET_FLAT ? sparc_flat_epilogue_delay_slots () : 1)
@@ -2094,72 +2109,46 @@ extern union tree_node *current_function_decl;
 #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 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
-
-  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 (TARGET_ARCH64 ? 40 : 20)
+#define TRAMPOLINE_SIZE (TARGET_ARCH64 ? 32 : 16)
+
+#define TRAMPOLINE_ALIGNMENT 128 /* 16 bytes */
 
 /* Emit RTL insns to initialize the variable parts of a trampoline.
    FNADDR is an RTX for the address of the function's pure code.
    CXT is an RTX for the static chain value for the function.  */
 
-void sparc_initialize_trampoline ();
-void sparc64_initialize_trampoline ();
 #define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
-  do {                                                         \
     if (TARGET_ARCH64)                                         \
       sparc64_initialize_trampoline (TRAMP, FNADDR, CXT);      \
     else                                                       \
-      sparc_initialize_trampoline (TRAMP, FNADDR, CXT);                \
-  } while (0)
+      sparc_initialize_trampoline (TRAMP, FNADDR, CXT)
 \f
-/* Generate necessary RTL for __builtin_saveregs().
-   ARGLIST is the argument list; see expr.c.  */
-extern struct rtx_def *sparc_builtin_saveregs ();
-#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) sparc_builtin_saveregs (ARGLIST)
+/* Generate necessary RTL for __builtin_saveregs().  */
+
+#define EXPAND_BUILTIN_SAVEREGS() sparc_builtin_saveregs ()
+
+/* Implement `va_start' for varargs and stdarg.  */
+#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
+  sparc_va_start (stdarg, valist, nextarg)
+
+/* Implement `va_arg'.  */
+#define EXPAND_BUILTIN_VA_ARG(valist, type) \
+  sparc_va_arg (valist, type)
+
+/* Define this macro if the location where a function argument is passed
+   depends on whether or not it is a named argument.
+
+   This macro controls how the NAMED argument to FUNCTION_ARG
+   is set for varargs and stdarg functions.  With this macro defined,
+   the NAMED argument is always true for named arguments, and false for
+   unnamed arguments.  If this is not defined, but SETUP_INCOMING_VARARGS
+   is defined, then all arguments are treated as named.  Otherwise, all named
+   arguments except the last are treated as named.
+   For the v9 we want NAMED to mean what it says it means.  */
+
+#define STRICT_ARGUMENT_NAMING TARGET_V9
 
 /* Generate RTL to flush the register windows so as to make arbitrary frames
    available.  */
@@ -2170,8 +2159,7 @@ extern struct rtx_def *sparc_builtin_saveregs ();
    return an rtx for the address of the word in the frame
    that holds the dynamic chain--the previous frame's address.
    ??? -mflat support? */
-#define DYNAMIC_CHAIN_ADDRESS(frame) \
-  gen_rtx (PLUS, Pmode, frame, gen_rtx (CONST_INT, VOIDmode, 14 * UNITS_PER_WORD))
+#define DYNAMIC_CHAIN_ADDRESS(frame) plus_constant (frame, 14 * UNITS_PER_WORD)
 
 /* The return address isn't on the stack, it is in a register, so we can't
    access it from the current frame pointer.  We can access it from the
@@ -2190,19 +2178,32 @@ extern struct rtx_def *sparc_builtin_saveregs ();
    returns, and +12 for structure returns.  */
 #define RETURN_ADDR_RTX(count, frame)          \
   ((count == -1)                               \
-   ? gen_rtx (REG, Pmode, 31)                  \
-   : gen_rtx (MEM, Pmode,                      \
-             memory_address (Pmode, plus_constant (frame, 15 * UNITS_PER_WORD))))
+   ? gen_rtx_REG (Pmode, 31)                   \
+   : gen_rtx_MEM (Pmode,                       \
+                 memory_address (Pmode, plus_constant (frame, \
+                                                       15 * UNITS_PER_WORD))))
+
+/* Before the prologue, the return address is %o7 + 8.  OK, sometimes it's
+   +12, but always using +8 is close enough for frame unwind purposes.
+   Actually, just using %o7 is close enough for unwinding, but %o7+8
+   is something you can return to.  */
+#define INCOMING_RETURN_ADDR_RTX \
+  plus_constant (gen_rtx_REG (word_mode, 15), 8)
+
+/* The offset from the incoming value of %sp to the top of the stack frame
+   for the current function.  On sparc64, we have to account for the stack
+   bias if present.  */
+#define INCOMING_FRAME_SP_OFFSET SPARC_STACK_BIAS
 
 #define DOESNT_NEED_UNWINDER (! TARGET_FLAT)
 \f
 /* Addressing modes, and classification of registers for them.  */
 
-/* #define HAVE_POST_INCREMENT */
-/* #define HAVE_POST_DECREMENT */
+/* #define HAVE_POST_INCREMENT */
+/* #define HAVE_POST_DECREMENT */
 
-/* #define HAVE_PRE_DECREMENT */
-/* #define HAVE_PRE_INCREMENT */
+/* #define HAVE_PRE_DECREMENT */
+/* #define HAVE_PRE_INCREMENT */
 
 /* Macros to check register numbers against specific register classes.  */
 
@@ -2213,16 +2214,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) < 32 || (unsigned) reg_renumber[REGNO] < (unsigned)32)
 #define REGNO_OK_FOR_BASE_P(REGNO) \
-((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)
+((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < (unsigned)32)
 #define REGNO_OK_FOR_FP_P(REGNO) \
-  (((unsigned) (REGNO) - 32 < (TARGET_V9 ? 64 : 32)) \
-   || ((unsigned) reg_renumber[REGNO] - 32 < (TARGET_V9 ? 64 : 32)))
+  (((unsigned) (REGNO) - 32 < (TARGET_V9 ? (unsigned)64 : (unsigned)32)) \
+   || ((unsigned) reg_renumber[REGNO] - 32 < (TARGET_V9 ? (unsigned)64 : (unsigned)32)))
 #define REGNO_OK_FOR_CCFP_P(REGNO) \
  (TARGET_V9 \
-  && (((unsigned) (REGNO) - 96 < 4) \
-      || ((unsigned) reg_renumber[REGNO] - 96 < 4)))
+  && (((unsigned) (REGNO) - 96 < (unsigned)4) \
+      || ((unsigned) reg_renumber[REGNO] - 96 < (unsigned)4)))
 
 /* Now macros that check whether X is a register and also,
    strictly, whether it is in a specified class.
@@ -2234,6 +2235,9 @@ extern struct rtx_def *sparc_builtin_saveregs ();
 /* 1 if X is an fp register.  */
 
 #define FP_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FP_P (REGNO (X)))
+
+/* Is X, a REG, an in or global register?  i.e. is regno 0..7 or 24..31 */
+#define IN_OR_GLOBAL_P(X) (REGNO (X) < 8 || (REGNO (X) >= 24 && REGNO (X) <= 31))
 \f
 /* Maximum number of registers that can appear in a valid memory address.  */
 
@@ -2255,10 +2259,15 @@ extern struct rtx_def *sparc_builtin_saveregs ();
 #define LEGITIMATE_PIC_OPERAND_P(X)  (! pic_address_needs_scratch (X))
 
 /* Nonzero if the constant value X is a legitimate general operand.
-   Anything can be made to work except floating point constants.  */
+   Anything can be made to work except floating point constants.
+   If TARGET_VIS, 0.0 can be made to work as well.  */
 
-#define LEGITIMATE_CONSTANT_P(X) \
-  (GET_CODE (X) != CONST_DOUBLE || GET_MODE (X) == VOIDmode)
+#define LEGITIMATE_CONSTANT_P(X)                                       \
+  (GET_CODE (X) != CONST_DOUBLE || GET_MODE (X) == VOIDmode ||                 \
+   (TARGET_VIS &&                                                      \
+    (GET_MODE (X) == SFmode || GET_MODE (X) == DFmode ||               \
+     GET_MODE (X) == TFmode) &&                                                \
+    fp_zero_operand (X, GET_MODE (X))))
 
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
@@ -2273,15 +2282,28 @@ extern struct rtx_def *sparc_builtin_saveregs ();
    After reload, it makes no difference, since pseudo regs have
    been eliminated by then.  */
 
-/* Optional extra constraints for this machine.  Borrowed from romp.h.
+/* Optional extra constraints for this machine.
 
-   For the SPARC, `Q' means that this is a memory operand but not a
-   symbolic memory operand.  Note that an unassigned pseudo register
-   is such a memory operand.  Needed because reload will generate
-   these things in insns and then not re-recognize the insns, causing
-   constrain_operands to fail.
+   'Q' handles floating point constants which can be moved into
+       an integer register with a single sethi instruction.
 
-   `S' handles constraints for calls.  ??? So where is it?  */
+   'R' handles floating point constants which can be moved into
+       an integer register with a single mov instruction.
+
+   'S' handles floating point constants which can be moved into
+       an integer register using a high/lo_sum sequence.
+
+   'T' handles memory addresses where the alignment is known to
+       be at least 8 bytes.
+
+   `U' handles all pseudo registers or a hard even numbered
+       integer register, needed for ldd/std instructions.  */
+
+#define EXTRA_CONSTRAINT_BASE(OP, C)   \
+   ((C) == 'Q' ? fp_sethi_p(OP)        \
+    : (C) == 'R' ? fp_mov_p(OP)        \
+    : (C) == 'S' ? fp_high_losum_p(OP) \
+    : 0)
 
 #ifndef REG_OK_STRICT
 
@@ -2297,18 +2319,13 @@ extern struct rtx_def *sparc_builtin_saveregs ();
 /* 'T', 'U' are for aligned memory loads which aren't needed for v9.  */
 
 #define EXTRA_CONSTRAINT(OP, C)                                \
-  ((C) == 'Q'                                          \
-   ? ((GET_CODE (OP) == MEM                            \
-       && memory_address_p (GET_MODE (OP), XEXP (OP, 0)) \
-       && ! symbolic_memory_operand (OP, VOIDmode))    \
-      || (reload_in_progress && GET_CODE (OP) == REG   \
-         && REGNO (OP) >= FIRST_PSEUDO_REGISTER))      \
-   : (! TARGET_ARCH64 && (C) == 'T')                   \
-   ? (mem_aligned_8 (OP))                              \
-   : (! TARGET_ARCH64 && (C) == 'U')                   \
-   ? (register_ok_for_ldd (OP))                                \
-   : 0)
+   (EXTRA_CONSTRAINT_BASE(OP, C)                        \
+    || ((! TARGET_ARCH64 && (C) == 'T')                        \
+        ? (mem_min_alignment (OP, 8))                  \
+        : ((! TARGET_ARCH64 && (C) == 'U')             \
+            ? (register_ok_for_ldd (OP))               \
+            : 0)))
+
 #else
 
 /* Nonzero if X is a hard reg that can be used as an index.  */
@@ -2317,19 +2334,24 @@ extern struct rtx_def *sparc_builtin_saveregs ();
 #define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
 
 #define EXTRA_CONSTRAINT(OP, C)                                \
-  ((C) == 'Q'                                          \
-   ? (GET_CODE (OP) == REG                             \
-      ? (REGNO (OP) >= FIRST_PSEUDO_REGISTER           \
-        && reg_renumber[REGNO (OP)] < 0)               \
-      : GET_CODE (OP) == MEM)                          \
-   : (! TARGET_ARCH64 && (C) == 'T')                   \
-   ? mem_aligned_8 (OP) && strict_memory_address_p (Pmode, XEXP (OP, 0)) \
-   : (! TARGET_ARCH64 && (C) == 'U')                   \
-   ? (GET_CODE (OP) == REG                             \
-      && (REGNO (OP) < FIRST_PSEUDO_REGISTER           \
-         || reg_renumber[REGNO (OP)] >= 0)             \
-      && register_ok_for_ldd (OP))                     \
-   : 0)
+   (EXTRA_CONSTRAINT_BASE(OP, C)                        \
+    || ((! TARGET_ARCH64 && (C) == 'T')                        \
+        ? mem_min_alignment (OP, 8) && strict_memory_address_p (Pmode, XEXP (OP, 0)) \
+        : ((! TARGET_ARCH64 && (C) == 'U')             \
+           ? (GET_CODE (OP) == REG                     \
+              && (REGNO (OP) < FIRST_PSEUDO_REGISTER   \
+                 || reg_renumber[REGNO (OP)] >= 0)     \
+              && register_ok_for_ldd (OP))             \
+           : 0)))
+
+#endif
+\f
+/* Should gcc use [%reg+%lo(xx)+offset] addresses?  */
+
+#ifdef HAVE_AS_OFFSETABLE_LO10
+#define USE_AS_OFFSETABLE_LO10 1
+#else
+#define USE_AS_OFFSETABLE_LO10 0
 #endif
 \f
 /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
@@ -2356,6 +2378,9 @@ extern struct rtx_def *sparc_builtin_saveregs ();
 
 #define RTX_OK_FOR_OFFSET_P(X)                                         \
   (GET_CODE (X) == CONST_INT && INTVAL (X) >= -0x1000 && INTVAL (X) < 0x1000)
+  
+#define RTX_OK_FOR_OLO10_P(X)                                          \
+  (GET_CODE (X) == CONST_INT && INTVAL (X) >= -0x1000 && INTVAL (X) < 0xc00 - 8)
 
 #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)                \
 { if (RTX_OK_FOR_BASE_P (X))                           \
@@ -2378,16 +2403,59 @@ extern struct rtx_def *sparc_builtin_saveregs ();
        }                                               \
       else if (RTX_OK_FOR_BASE_P (op0))                        \
        {                                               \
-         if (RTX_OK_FOR_INDEX_P (op1)                  \
+         if ((RTX_OK_FOR_INDEX_P (op1)                 \
+             /* We prohibit REG + REG for TFmode when  \
+                there are no instructions which accept \
+                REG+REG instructions.  We do this      \
+                because REG+REG is not an offsetable   \
+                address.  If we get the situation      \
+                in reload where source and destination \
+                of a movtf pattern are both MEMs with  \
+                REG+REG address, then only one of them \
+                gets converted to an offsetable        \
+                address. */                            \
+             && (MODE != TFmode                        \
+                 || (TARGET_FPU && TARGET_ARCH64       \
+                     && TARGET_V9                      \
+                     && TARGET_HARD_QUAD)))            \
              || RTX_OK_FOR_OFFSET_P (op1))             \
            goto ADDR;                                  \
        }                                               \
       else if (RTX_OK_FOR_BASE_P (op1))                        \
        {                                               \
-         if (RTX_OK_FOR_INDEX_P (op0)                  \
+         if ((RTX_OK_FOR_INDEX_P (op0)                 \
+             /* See the previous comment. */           \
+             && (MODE != TFmode                        \
+                 || (TARGET_FPU && TARGET_ARCH64       \
+                     && TARGET_V9                      \
+                     && TARGET_HARD_QUAD)))            \
              || RTX_OK_FOR_OFFSET_P (op0))             \
            goto ADDR;                                  \
        }                                               \
+      else if (USE_AS_OFFSETABLE_LO10                  \
+              && GET_CODE (op0) == LO_SUM              \
+              && TARGET_ARCH64                         \
+              && ! TARGET_CM_MEDMID                    \
+              && RTX_OK_FOR_OLO10_P (op1))             \
+       {                                               \
+         register rtx op00 = XEXP (op0, 0);            \
+         register rtx op01 = XEXP (op0, 1);            \
+         if (RTX_OK_FOR_BASE_P (op00)                  \
+             && CONSTANT_P (op01))                     \
+           goto ADDR;                                  \
+       }                                               \
+      else if (USE_AS_OFFSETABLE_LO10                  \
+              && GET_CODE (op1) == LO_SUM              \
+              && TARGET_ARCH64                         \
+              && ! TARGET_CM_MEDMID                    \
+              && RTX_OK_FOR_OLO10_P (op0))             \
+       {                                               \
+         register rtx op10 = XEXP (op1, 0);            \
+         register rtx op11 = XEXP (op1, 1);            \
+         if (RTX_OK_FOR_BASE_P (op10)                  \
+             && CONSTANT_P (op11))                     \
+           goto ADDR;                                  \
+       }                                               \
     }                                                  \
   else if (GET_CODE (X) == LO_SUM)                     \
     {                                                  \
@@ -2397,8 +2465,8 @@ extern struct rtx_def *sparc_builtin_saveregs ();
          && CONSTANT_P (op1)                           \
          /* We can't allow TFmode, because an offset   \
             greater than or equal to the alignment (8) \
-            may cause the LO_SUM to overflow.  */      \
-         && MODE != TFmode)                            \
+            may cause the LO_SUM to overflow if !v9. */\
+         && (MODE != TFmode || TARGET_V9))             \
        goto ADDR;                                      \
     }                                                  \
   else if (GET_CODE (X) == CONST_INT && SMALL_INT (X)) \
@@ -2419,37 +2487,68 @@ extern struct rtx_def *sparc_builtin_saveregs ();
    opportunities to optimize the output.  */
 
 /* On SPARC, change REG+N into REG+REG, and REG+(X*Y) into REG+REG.  */
-extern struct rtx_def *legitimize_pic_address ();
 #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)    \
 { rtx sparc_x = (X);                                           \
   if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == MULT)  \
-    (X) = gen_rtx (PLUS, Pmode, XEXP (X, 1),                   \
-                  force_operand (XEXP (X, 0), NULL_RTX));      \
+    (X) = gen_rtx_PLUS (Pmode, XEXP (X, 1),                    \
+                       force_operand (XEXP (X, 0), NULL_RTX)); \
   if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == MULT)  \
-    (X) = gen_rtx (PLUS, Pmode, XEXP (X, 0),                   \
-                  force_operand (XEXP (X, 1), NULL_RTX));      \
+    (X) = gen_rtx_PLUS (Pmode, XEXP (X, 0),                    \
+                       force_operand (XEXP (X, 1), NULL_RTX)); \
   if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == PLUS)  \
-    (X) = gen_rtx (PLUS, Pmode, force_operand (XEXP (X, 0), NULL_RTX),\
-                  XEXP (X, 1));                                \
+    (X) = gen_rtx_PLUS (Pmode, force_operand (XEXP (X, 0), NULL_RTX),\
+                       XEXP (X, 1));                           \
   if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == PLUS)  \
-    (X) = gen_rtx (PLUS, Pmode, XEXP (X, 0),                   \
-                  force_operand (XEXP (X, 1), NULL_RTX));      \
+    (X) = gen_rtx_PLUS (Pmode, XEXP (X, 0),                    \
+                       force_operand (XEXP (X, 1), NULL_RTX)); \
   if (sparc_x != (X) && memory_address_p (MODE, X))            \
     goto WIN;                                                  \
   if (flag_pic) (X) = legitimize_pic_address (X, MODE, 0);     \
   else if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 1)))   \
-    (X) = gen_rtx (PLUS, Pmode, XEXP (X, 0),                   \
-                  copy_to_mode_reg (Pmode, XEXP (X, 1)));      \
+    (X) = gen_rtx_PLUS (Pmode, XEXP (X, 0),                    \
+                       copy_to_mode_reg (Pmode, XEXP (X, 1))); \
   else if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 0)))   \
-    (X) = gen_rtx (PLUS, Pmode, XEXP (X, 1),                   \
-                  copy_to_mode_reg (Pmode, XEXP (X, 0)));      \
+    (X) = gen_rtx_PLUS (Pmode, XEXP (X, 1),                    \
+                       copy_to_mode_reg (Pmode, XEXP (X, 0))); \
   else if (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == CONST \
           || GET_CODE (X) == LABEL_REF)                        \
-    (X) = gen_rtx (LO_SUM, Pmode,                              \
-                  copy_to_mode_reg (Pmode, gen_rtx (HIGH, Pmode, X)), X); \
+    (X) = copy_to_suggested_reg (X, NULL_RTX, Pmode);          \
   if (memory_address_p (MODE, X))                              \
     goto WIN; }
 
+/* Try a machine-dependent way of reloading an illegitimate address
+   operand.  If we find one, push the reload and jump to WIN.  This
+   macro is used in only one place: `find_reloads_address' in reload.c.
+
+   For Sparc 32, we wish to handle addresses by splitting them into
+   HIGH+LO_SUM pairs, retaining the LO_SUM in the memory reference. 
+   This cuts the number of extra insns by one.
+
+   Do nothing when generating PIC code and the address is a
+   symbolic operand or requires a scratch register.  */
+
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN)     \
+do {                                                                    \
+  /* Decompose SImode constants into hi+lo_sum.  We do have to                 \
+     rerecognize what we produce, so be careful.  */                   \
+  if (CONSTANT_P (X)                                                   \
+      && (MODE != TFmode || TARGET_V9)                                 \
+      && GET_MODE (X) == SImode                                                \
+      && GET_CODE (X) != LO_SUM && GET_CODE (X) != HIGH                        \
+      && ! (flag_pic                                                   \
+           && (symbolic_operand (X, Pmode)                             \
+               || pic_address_needs_scratch (X))))                     \
+    {                                                                  \
+      X = gen_rtx_LO_SUM (GET_MODE (X),                                        \
+                         gen_rtx_HIGH (GET_MODE (X), X), X);           \
+      push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR,      \
+                   BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0,       \
+                   OPNUM, TYPE);                                       \
+      goto WIN;                                                                \
+    }                                                                  \
+  /* ??? 64-bit reloads.  */                                           \
+} while (0)
+
 /* Go to LABEL if ADDR (a legitimate address expression)
    has an effect that depends on the machine mode it is used for.
    On the SPARC this is never true.  */
@@ -2457,23 +2556,34 @@ extern struct rtx_def *legitimize_pic_address ();
 #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
 
 /* If we are referencing a function make the SYMBOL_REF special.
-   In the Medium/Anywhere code model, %g4 points to the data segment so we
-   must not add it to function addresses.  */
+   In the Embedded Medium/Anywhere code model, %g4 points to the data segment
+   so we must not add it to function addresses.  */
 
 #define ENCODE_SECTION_INFO(DECL) \
   do {                                                 \
-    if (TARGET_MEDANY && TREE_CODE (DECL) == FUNCTION_DECL) \
+    if (TARGET_CM_EMBMEDANY && TREE_CODE (DECL) == FUNCTION_DECL) \
       SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \
   } while (0)
 \f
 /* Specify the machine mode that this machine uses
    for the index in the tablejump instruction.  */
-#define CASE_VECTOR_MODE Pmode
+/* If we ever implement any of the full models (such as CM_FULLANY),
+   this has to be DImode in that case */
+#ifdef HAVE_GAS_SUBSECTION_ORDERING
+#define CASE_VECTOR_MODE \
+(! TARGET_PTR64 ? SImode : flag_pic ? SImode : TARGET_CM_MEDLOW ? SImode : DImode)
+#else
+/* If assembler does not have working .subsection -1, we use DImode for pic, as otherwise
+   we have to sign extend which slows things down. */
+#define CASE_VECTOR_MODE \
+(! TARGET_PTR64 ? SImode : flag_pic ? DImode : TARGET_CM_MEDLOW ? SImode : DImode)
+#endif
 
-/* Define this if the tablejump instruction expects the table
-   to contain offsets from the address of the table.
-   Do not define this if the table should contain absolute addresses.  */
-/* #define CASE_VECTOR_PC_RELATIVE */
+/* Define as C expression which evaluates to nonzero if the tablejump
+   instruction expects the table to contain offsets from the address of the
+   table.
+   Do not define this if the table should contain absolute addresses. */
+/* #define CASE_VECTOR_PC_RELATIVE 1 */
 
 /* Specify the tree operation to be used to convert reals to integers.  */
 #define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
@@ -2495,7 +2605,7 @@ extern struct rtx_def *legitimize_pic_address ();
 
 /* This is how to refer to the variable errno.  */
 #define GEN_ERRNO_RTX \
-  gen_rtx (MEM, SImode, gen_rtx (SYMBOL_REF, Pmode, "errno"))
+  gen_rtx_MEM (SImode, gen_rtx_SYMBOL_REF (Pmode, "errno"))
 #endif /* 0 */
 
 /* Define if operations between registers always perform the operation
@@ -2520,7 +2630,7 @@ extern struct rtx_def *legitimize_pic_address ();
 #define STORE_FLAG_VALUE 1
 
 /* When a prototype says `char' or `short', really pass an `int'.  */
-#define PROMOTE_PROTOTYPES
+#define PROMOTE_PROTOTYPES (TARGET_ARCH32)
 
 /* Define this to be nonzero if shift instructions ignore all but the low-order
    few bits. */
@@ -2551,29 +2661,24 @@ extern struct rtx_def *legitimize_pic_address ();
 
    CCXmode and CCX_NOOVmode are only used by v9.  */
 
-#define EXTRA_CC_MODES CCXmode, CC_NOOVmode, CCX_NOOVmode, CCFPmode, CCFPEmode
-
-/* Define the names for the modes specified above.  */
-
-#define EXTRA_CC_NAMES "CCX", "CC_NOOV", "CCX_NOOV", "CCFP", "CCFPE"
+#define EXTRA_CC_MODES                 \
+    CC(CCXmode,             "CCX")             \
+    CC(CC_NOOVmode,  "CC_NOOV")                \
+    CC(CCX_NOOVmode, "CCX_NOOV")       \
+    CC(CCFPmode,     "CCFP")           \
+    CC(CCFPEmode,    "CCFPE")
 
 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
    return the mode to be used for the comparison.  For floating-point,
-   CCFP[E]mode is used.  CC_NOOVmode should be used when the first operand is a
-   PLUS, MINUS, NEG, or ASHIFT.  CCmode should be used when no special
+   CCFP[E]mode is used.  CC_NOOVmode should be used when the first operand
+   is a PLUS, MINUS, NEG, or ASHIFT.  CCmode should be used when no special
    processing is needed.  */
-#define SELECT_CC_MODE(OP,X,Y) \
-  (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT                         \
-   ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode)                   \
-   : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS                   \
-       || GET_CODE (X) == NEG || GET_CODE (X) == ASHIFT)               \
-      ? (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.  */
+#define SELECT_CC_MODE(OP,X,Y)  select_cc_mode ((OP), (X), (Y))
 
-#define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode)
+/* Return non-zero if MODE implies a floating point inequality can be
+   reversed.  For Sparc this is always true because we have a full
+   compliment of ordered and unordered comparisons.  */
+#define REVERSIBLE_CC_MODE(MODE) 1
 
 /* A function address in a call instruction
    is a byte address (for indexing purposes)
@@ -2601,7 +2706,7 @@ extern struct rtx_def *legitimize_pic_address ();
 #define MULSI3_LIBCALL "*.umul"
 
 /* Define library calls for quad FP operations.  These are all part of the
-   SPARC ABI.  */
+   SPARC 32bit ABI.  */
 #define ADDTF3_LIBCALL "_Q_add"
 #define SUBTF3_LIBCALL "_Q_sub"
 #define NEGTF2_LIBCALL "_Q_neg"
@@ -2627,39 +2732,47 @@ extern struct rtx_def *legitimize_pic_address ();
    for calls to the builtin function sqrt, but this fails.  */
 #define INIT_TARGET_OPTABS                                             \
   do {                                                                 \
-    add_optab->handlers[(int) TFmode].libfunc                          \
-      = gen_rtx (SYMBOL_REF, Pmode, ADDTF3_LIBCALL);                   \
-    sub_optab->handlers[(int) TFmode].libfunc                          \
-      = gen_rtx (SYMBOL_REF, Pmode, SUBTF3_LIBCALL);                   \
-    neg_optab->handlers[(int) TFmode].libfunc                          \
-      = gen_rtx (SYMBOL_REF, Pmode, NEGTF2_LIBCALL);                   \
-    smul_optab->handlers[(int) TFmode].libfunc                         \
-      = gen_rtx (SYMBOL_REF, Pmode, MULTF3_LIBCALL);                   \
-    flodiv_optab->handlers[(int) TFmode].libfunc                       \
-      = gen_rtx (SYMBOL_REF, Pmode, DIVTF3_LIBCALL);                   \
-    eqtf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, EQTF2_LIBCALL);                \
-    netf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, NETF2_LIBCALL);                \
-    gttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, GTTF2_LIBCALL);                \
-    getf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, GETF2_LIBCALL);                \
-    lttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, LTTF2_LIBCALL);                \
-    letf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, LETF2_LIBCALL);                \
-    trunctfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, TRUNCTFSF2_LIBCALL);   \
-    trunctfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, TRUNCTFDF2_LIBCALL);   \
-    extendsftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, EXTENDSFTF2_LIBCALL); \
-    extenddftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, EXTENDDFTF2_LIBCALL); \
-    floatsitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, FLOATSITF2_LIBCALL);    \
-    fixtfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, FIX_TRUNCTFSI2_LIBCALL);  \
-    fixunstfsi_libfunc                                                 \
-      = gen_rtx (SYMBOL_REF, Pmode, FIXUNS_TRUNCTFSI2_LIBCALL);                \
-    if (TARGET_FPU)                                                    \
-      sqrt_optab->handlers[(int) TFmode].libfunc                       \
-       = gen_rtx (SYMBOL_REF, Pmode, "_Q_sqrt");                       \
+    if (TARGET_ARCH32)                                                 \
+      {                                                                        \
+       add_optab->handlers[(int) TFmode].libfunc                       \
+         = init_one_libfunc (ADDTF3_LIBCALL);                          \
+       sub_optab->handlers[(int) TFmode].libfunc                       \
+         = init_one_libfunc (SUBTF3_LIBCALL);                          \
+       neg_optab->handlers[(int) TFmode].libfunc                       \
+         = init_one_libfunc (NEGTF2_LIBCALL);                          \
+       smul_optab->handlers[(int) TFmode].libfunc                      \
+         = init_one_libfunc (MULTF3_LIBCALL);                          \
+       flodiv_optab->handlers[(int) TFmode].libfunc                    \
+         = init_one_libfunc (DIVTF3_LIBCALL);                          \
+       eqtf2_libfunc = init_one_libfunc (EQTF2_LIBCALL);               \
+       netf2_libfunc = init_one_libfunc (NETF2_LIBCALL);               \
+       gttf2_libfunc = init_one_libfunc (GTTF2_LIBCALL);               \
+       getf2_libfunc = init_one_libfunc (GETF2_LIBCALL);               \
+       lttf2_libfunc = init_one_libfunc (LTTF2_LIBCALL);               \
+       letf2_libfunc = init_one_libfunc (LETF2_LIBCALL);               \
+       trunctfsf2_libfunc = init_one_libfunc (TRUNCTFSF2_LIBCALL);     \
+       trunctfdf2_libfunc = init_one_libfunc (TRUNCTFDF2_LIBCALL);     \
+       extendsftf2_libfunc = init_one_libfunc (EXTENDSFTF2_LIBCALL);   \
+       extenddftf2_libfunc = init_one_libfunc (EXTENDDFTF2_LIBCALL);   \
+       floatsitf_libfunc = init_one_libfunc (FLOATSITF2_LIBCALL);      \
+       fixtfsi_libfunc = init_one_libfunc (FIX_TRUNCTFSI2_LIBCALL);    \
+       fixunstfsi_libfunc                                              \
+         = init_one_libfunc (FIXUNS_TRUNCTFSI2_LIBCALL);               \
+       if (TARGET_FPU)                                                 \
+         sqrt_optab->handlers[(int) TFmode].libfunc                    \
+           = init_one_libfunc ("_Q_sqrt");                             \
+      }                                                                        \
     INIT_SUBTARGET_OPTABS;                                             \
   } while (0)
 
 /* This is meant to be redefined in the host dependent files */
 #define INIT_SUBTARGET_OPTABS
 
+/* Nonzero if a floating point comparison library call for
+   mode MODE that will return a boolean value.  Zero if one
+   of the libgcc2 functions is used.  */
+#define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) ((MODE) == TFmode)
+
 /* Compute the cost of computing a constant rtl expression RTX
    whose rtx-code is CODE.  The body of this macro is a portion
    of a switch statement.  If the code is computed here,
@@ -2685,18 +2798,16 @@ extern struct rtx_def *legitimize_pic_address ();
        return 0;                                               \
     return 8;
 
-/* Compute the cost of an address.  For the sparc, all valid addresses are
-   the same cost.
-   ??? Is this true for v9?  */
-
 #define ADDRESS_COST(RTX)  1
 
 /* Compute extra cost of moving data between one register class
-   and another.
-   ??? v9: We ignore FPCC_REGS on the assumption they'll never be seen.  */
-#define REGISTER_MOVE_COST(CLASS1, CLASS2) \
-  (((FP_REG_CLASS_P (CLASS1) && (CLASS2) == GENERAL_REGS) \
-    || ((CLASS1) == GENERAL_REGS && FP_REG_CLASS_P (CLASS2))) ? 6 : 2)
+   and another.  */
+#define GENERAL_OR_I64(C) ((C) == GENERAL_REGS || (C) == I64_REGS)
+#define REGISTER_MOVE_COST(CLASS1, CLASS2)                     \
+  (((FP_REG_CLASS_P (CLASS1) && GENERAL_OR_I64 (CLASS2)) \
+    || (GENERAL_OR_I64 (CLASS1) && FP_REG_CLASS_P (CLASS2)) \
+    || (CLASS1) == FPCC_REGS || (CLASS2) == FPCC_REGS)         \
+   ? (sparc_cpu == PROCESSOR_ULTRASPARC ? 12 : 6) : 2)
 
 /* Provide the costs of a rtl expression.  This is in the body of a
    switch on CODE.  The purpose for the cost of MULT is to encourage
@@ -2707,12 +2818,17 @@ extern struct rtx_def *legitimize_pic_address ();
 
 #define RTX_COSTS(X,CODE,OUTER_CODE)                   \
   case MULT:                                           \
-    return (TARGET_V8 || TARGET_SPARCLITE)              \
-       ? COSTS_N_INSNS (5) : COSTS_N_INSNS (25);       \
+    if (sparc_cpu == PROCESSOR_ULTRASPARC)             \
+      return (GET_MODE (X) == DImode ?                 \
+              COSTS_N_INSNS (34) : COSTS_N_INSNS (19));        \
+    return TARGET_HARD_MUL ? COSTS_N_INSNS (5) : COSTS_N_INSNS (25); \
   case DIV:                                            \
   case UDIV:                                           \
   case MOD:                                            \
   case UMOD:                                           \
+    if (sparc_cpu == PROCESSOR_ULTRASPARC)             \
+      return (GET_MODE (X) == DImode ?                 \
+              COSTS_N_INSNS (68) : COSTS_N_INSNS (37));        \
     return COSTS_N_INSNS (25);                         \
   /* Make FLOAT and FIX more expensive than CONST_DOUBLE,\
      so that cse will favor the latter.  */            \
@@ -2720,16 +2836,38 @@ extern struct rtx_def *legitimize_pic_address ();
   case FIX:                                            \
     return 19;
 
+#define ISSUE_RATE  sparc_issue_rate()
+
 /* Adjust the cost of dependencies.  */
 #define ADJUST_COST(INSN,LINK,DEP,COST) \
-  if (sparc_cpu == PROCESSOR_SUPERSPARC) \
-    (COST) = supersparc_adjust_cost (INSN, LINK, DEP, COST)
+  (COST) = sparc_adjust_cost(INSN, LINK, DEP, COST)
+
+#define MD_SCHED_INIT(DUMP, SCHED_VERBOSE)                             \
+  if (sparc_cpu == PROCESSOR_ULTRASPARC)                               \
+    ultrasparc_sched_init (DUMP, SCHED_VERBOSE)
+
+#define MD_SCHED_REORDER(DUMP, SCHED_VERBOSE, READY, N_READY, CLOCK, CIM) \
+do {                                                                   \
+  if (sparc_cpu == PROCESSOR_ULTRASPARC)                               \
+    ultrasparc_sched_reorder (DUMP, SCHED_VERBOSE, READY, N_READY);    \
+  CIM = issue_rate;                                                    \
+} while (0)
+
+#define MD_SCHED_VARIABLE_ISSUE(DUMP, SCHED_VERBOSE, INSN, CAN_ISSUE_MORE) \
+do {                                                                   \
+  if (sparc_cpu == PROCESSOR_ULTRASPARC)                               \
+    (CAN_ISSUE_MORE) = ultrasparc_variable_issue (INSN);               \
+  else                                                                 \
+    (CAN_ISSUE_MORE)--;                                                        \
+} while (0)
 
 /* Conditional branches with empty delay slots have a length of two.  */
-#define ADJUST_INSN_LENGTH(INSN, LENGTH)       \
+#define ADJUST_INSN_LENGTH(INSN, LENGTH)                               \
+do {                                                                   \
   if (GET_CODE (INSN) == CALL_INSN                                     \
       || (GET_CODE (INSN) == JUMP_INSN && ! simplejump_p (insn)))      \
-    LENGTH += 1;
+    LENGTH += 1;                                                       \
+} while (0)
 \f
 /* Control the assembler format that we output.  */
 
@@ -2737,6 +2875,12 @@ extern struct rtx_def *legitimize_pic_address ();
 
 #define ASM_FILE_START(file)
 
+/* A C string constant describing how to begin a comment in the target
+   assembler language.  The compiler assumes that the comment will end at
+   the end of the line.  */
+
+#define ASM_COMMENT_START "!"
+
 /* Output to assembler file text saying following lines
    may contain character constants, extra white space, comments, etc.  */
 
@@ -2841,36 +2985,53 @@ extern struct rtx_def *legitimize_pic_address ();
    This is suitable for output with `assemble_name'.  */
 
 #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM)  \
-  sprintf (LABEL, "*%s%d", PREFIX, NUM)
+  sprintf ((LABEL), "*%s%ld", (PREFIX), (long)(NUM))
 
-/* This is how to output an assembler line defining a `double' constant.  */
+/* This is how to output an assembler line defining a `float' constant.
+   We always have to use a .long pseudo-op to do this because the native
+   SVR4 ELF assembler is buggy and it generates incorrect values when we
+   try to use the .float pseudo-op instead.  */
 
-#define ASM_OUTPUT_DOUBLE(FILE,VALUE)                                  \
-  {                                                                    \
-    long t[2];                                                         \
-    REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t);                          \
-    fprintf (FILE, "\t%s\t0x%lx\n\t%s\t0x%lx\n",                       \
-            ASM_LONG, t[0], ASM_LONG, t[1]);                           \
-  }
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+  {                                                            \
+    long t;                                                    \
+    char str[30];                                              \
+    REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t);                  \
+    REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str);             \
+    fprintf (FILE, "\t%s\t0x%lx %s ~%s\n", ASM_LONG, t,                \
+            ASM_COMMENT_START, str);                           \
+  }                                                            \
 
-/* This is how to output an assembler line defining a `float' constant.  */
+/* This is how to output an assembler line defining a `double' constant.
+   We always have to use a .long pseudo-op to do this because the native
+   SVR4 ELF assembler is buggy and it generates incorrect values when we
+   try to use the .float pseudo-op instead.  */
 
-#define ASM_OUTPUT_FLOAT(FILE,VALUE)                                   \
-  {                                                                    \
-    long t;                                                            \
-    REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t);                          \
-    fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t);                      \
-  }                                                                    \
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+  {                                                            \
+    long t[2];                                                 \
+    char str[30];                                              \
+    REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t);                  \
+    REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str);             \
+    fprintf (FILE, "\t%s\t0x%lx %s ~%s\n", ASM_LONG, t[0],     \
+            ASM_COMMENT_START, str);                           \
+    fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t[1]);           \
+  }
 
 /* This is how to output an assembler line defining a `long double'
    constant.  */
 
-#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE)                             \
-  {                                                                    \
-    long t[4];                                                         \
-    REAL_VALUE_TO_TARGET_LONG_DOUBLE ((VALUE), t);                     \
-    fprintf (FILE, "\t%s\t0x%lx\n\t%s\t0x%lx\n\t%s\t0x%lx\n\t%s\t0x%lx\n", \
-      ASM_LONG, t[0], ASM_LONG, t[1], ASM_LONG, t[2], ASM_LONG, t[3]); \
+#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
+  {                                                            \
+    long t[4];                                                 \
+    char str[30];                                              \
+    REAL_VALUE_TO_TARGET_LONG_DOUBLE ((VALUE), t);             \
+    REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str);             \
+    fprintf (FILE, "\t%s\t0x%lx %s ~%s\n", ASM_LONG, t[0],     \
+            ASM_COMMENT_START, str);                           \
+    fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t[1]);           \
+    fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t[2]);           \
+    fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t[3]);           \
   }
 
 /* This is how to output an assembler line defining an `int' constant.  */
@@ -2901,39 +3062,60 @@ extern struct rtx_def *legitimize_pic_address ();
 #define ASM_OUTPUT_BYTE(FILE,VALUE)  \
   fprintf (FILE, "\t%s\t0x%x\n", ASM_BYTE_OP, (VALUE))
 
+/* This is how we hook in and defer the case-vector until the end of
+   the function.  */
+#define ASM_OUTPUT_ADDR_VEC(LAB,VEC) \
+  sparc_defer_case_vector ((LAB),(VEC), 0)
+
+#define ASM_OUTPUT_ADDR_DIFF_VEC(LAB,VEC) \
+  sparc_defer_case_vector ((LAB),(VEC), 1)
+
 /* This is how to output an element of a case-vector that is absolute.  */
 
 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)  \
 do {                                                                   \
   char label[30];                                                      \
   ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE);                     \
-  if (Pmode == SImode)                                                 \
+  if (CASE_VECTOR_MODE == SImode)                                      \
     fprintf (FILE, "\t.word\t");                                       \
-  else if (TARGET_MEDLOW)                                              \
-    fprintf (FILE, "\t.word\t0\n\t.word\t");                           \
   else                                                                 \
     fprintf (FILE, "\t.xword\t");                                      \
   assemble_name (FILE, label);                                         \
-  fprintf (FILE, "\n");                                                        \
+  fputc ('\n', FILE);                                                  \
 } while (0)
 
 /* This is how to output an element of a case-vector that is relative.
    (SPARC uses such vectors only when generating PIC.)  */
 
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)                     \
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)               \
 do {                                                                   \
   char label[30];                                                      \
-  ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE);                     \
-  if (Pmode == SImode)                                                 \
+  ASM_GENERATE_INTERNAL_LABEL (label, "L", (VALUE));                   \
+  if (CASE_VECTOR_MODE == SImode)                                      \
     fprintf (FILE, "\t.word\t");                                       \
-  else if (TARGET_MEDLOW)                                              \
-    fprintf (FILE, "\t.word\t0\n\t.word\t");                           \
   else                                                                 \
     fprintf (FILE, "\t.xword\t");                                      \
   assemble_name (FILE, label);                                         \
-  fprintf (FILE, "-1b\n");                                             \
+  ASM_GENERATE_INTERNAL_LABEL (label, "L", (REL));                     \
+  fputc ('-', FILE);                                                   \
+  assemble_name (FILE, label);                                         \
+  fputc ('\n', FILE);                                                  \
 } while (0)
 
+/* This is what to output before and after case-vector (both
+   relative and absolute).  If .subsection -1 works, we put case-vectors
+   at the beginning of the current section.  */
+
+#ifdef HAVE_GAS_SUBSECTION_ORDERING
+
+#define ASM_OUTPUT_ADDR_VEC_START(FILE)                                        \
+  fprintf(FILE, "\t.subsection\t-1\n")
+
+#define ASM_OUTPUT_ADDR_VEC_END(FILE)                                  \
+  fprintf(FILE, "\t.previous\n")
+
+#endif
+
 /* This is how to output an assembler line
    that says to advance the location counter
    to a multiple of 2**LOG bytes.  */
@@ -2997,37 +3179,37 @@ do {                                                                    \
   int big_delta = (DELTA) >= 4096 || (DELTA) < -4096;                  \
   if (big_delta)                                                       \
     fprintf (FILE, "\tset %d,%%g1\n\tadd %%o0,%%g1,%%o0\n", (DELTA));  \
-  if (flag_pic)                                                                \
+  /* Don't use the jmp solution unless we know the target is local to  \
+     the application or shared object.                                 \
+     XXX: Wimp out and don't actually check anything except if this is \
+     an embedded target where we assume there are no shared libs.  */  \
+  if (!TARGET_CM_EMBMEDANY || flag_pic)                                        \
     {                                                                  \
       if (! big_delta)                                                 \
        fprintf (FILE, "\tadd %%o0,%d,%%o0\n", DELTA);                  \
-      fprintf (FILE, "\tsave %%sp,-112,%%sp\n");                       \
+      fprintf (FILE, "\tmov %%o7,%%g1\n");                             \
       fprintf (FILE, "\tcall ");                                       \
-      assemble_name                                                    \
-       (FILE, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION)));    \
+      assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));   \
       fprintf (FILE, ",0\n");                                          \
     }                                                                  \
-  else if (TARGET_MEDANY || TARGET_FULLANY)                            \
+  else if (TARGET_CM_EMBMEDANY)                                                \
     {                                                                  \
       fprintf (FILE, "\tsetx ");                                       \
-      assemble_name                                                    \
-       (FILE, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION)));    \
+      assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));   \
       fprintf (FILE, ",%%g5,%%g1\n\tjmp %%g1\n");                      \
     }                                                                  \
   else                                                                 \
     {                                                                  \
       fprintf (FILE, "\tsethi %%hi(");                                 \
-      assemble_name                                                    \
-       (FILE, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION)));    \
+      assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));   \
       fprintf (FILE, "),%%g1\n\tjmp %%g1+%%lo(");                      \
-      assemble_name                                                    \
-       (FILE, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION)));    \
+      assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));   \
       fprintf (FILE, ")\n");                                           \
     }                                                                  \
-  if (big_delta)                                                       \
+  if (!TARGET_CM_EMBMEDANY || flag_pic)                                        \
+    fprintf (FILE, "\tmov %%g1,%%o7\n");                               \
+  else if (big_delta)                                                  \
     fprintf (FILE, "\tnop\n");                                         \
-  else if (flag_pic)                                                   \
-    fprintf (FILE, "\trestore\n");                                     \
   else                                                                 \
     fprintf (FILE, "\tadd %%o0,%d,%%o0\n", DELTA);                     \
 } while (0)
@@ -3048,7 +3230,7 @@ do {                                                                      \
 #define TARGET_CR 015
 
 #define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
-  ((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR) == '(')
+  ((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR) == '(' || (CHAR) == '_')
 
 /* Print operand X (an rtx) in assembler syntax to file FILE.
    CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
@@ -3072,15 +3254,29 @@ do {                                                                    \
        offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0);\
       else                                                     \
        base = XEXP (addr, 0), index = XEXP (addr, 1);          \
-      fputs (reg_names[REGNO (base)], FILE);                   \
-      if (index == 0)                                          \
-       fprintf (FILE, "%+d", offset);                          \
-      else if (GET_CODE (index) == REG)                                \
-       fprintf (FILE, "+%s", reg_names[REGNO (index)]);        \
-      else if (GET_CODE (index) == SYMBOL_REF                  \
-              || GET_CODE (index) == CONST)                    \
-       fputc ('+', FILE), output_addr_const (FILE, index);     \
-      else abort ();                                           \
+      if (GET_CODE (base) == LO_SUM)                           \
+       {                                                       \
+         if (! USE_AS_OFFSETABLE_LO10                          \
+             || TARGET_ARCH32                                  \
+             || TARGET_CM_MEDMID)                              \
+           abort ();                                           \
+         output_operand (XEXP (base, 0), 0);                   \
+         fputs ("+%lo(", FILE);                                \
+         output_address (XEXP (base, 1));                      \
+         fprintf (FILE, ")+%d", offset);                       \
+       }                                                       \
+      else                                                     \
+       {                                                       \
+         fputs (reg_names[REGNO (base)], FILE);                \
+         if (index == 0)                                       \
+           fprintf (FILE, "%+d", offset);                      \
+         else if (GET_CODE (index) == REG)                     \
+           fprintf (FILE, "+%s", reg_names[REGNO (index)]);    \
+         else if (GET_CODE (index) == SYMBOL_REF               \
+                  || GET_CODE (index) == CONST)                \
+           fputc ('+', FILE), output_addr_const (FILE, index); \
+         else abort ();                                        \
+       }                                                       \
     }                                                          \
   else if (GET_CODE (addr) == MINUS                            \
           && GET_CODE (XEXP (addr, 1)) == LABEL_REF)           \
@@ -3093,7 +3289,10 @@ do {                                                                     \
   else if (GET_CODE (addr) == LO_SUM)                          \
     {                                                          \
       output_operand (XEXP (addr, 0), 0);                      \
-      fputs ("+%lo(", FILE);                                   \
+      if (TARGET_CM_MEDMID)                                    \
+        fputs ("+%l44(", FILE);                                        \
+      else                                                     \
+        fputs ("+%lo(", FILE);                                 \
       output_address (XEXP (addr, 1));                         \
       fputc (')', FILE);                                       \
     }                                                          \
@@ -3118,37 +3317,60 @@ do {                                                                    \
     }                                                          \
 }
 
+/* Define the codes that are matched by predicates in sparc.c.  */
+
+#define PREDICATE_CODES                                                        \
+{"reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}},          \
+{"fp_zero_operand", {CONST_DOUBLE}},                                   \
+{"fp_sethi_p", {CONST_DOUBLE}},                                                \
+{"fp_mov_p", {CONST_DOUBLE}},                                          \
+{"fp_high_losum_p", {CONST_DOUBLE}},                                   \
+{"intreg_operand", {SUBREG, REG}},                                     \
+{"fcc_reg_operand", {REG}},                                            \
+{"icc_or_fcc_reg_operand", {REG}},                                     \
+{"restore_operand", {REG}},                                            \
+{"call_operand", {MEM}},                                               \
+{"call_operand_address", {SYMBOL_REF, LABEL_REF, CONST, CONST_DOUBLE,  \
+       ADDRESSOF, SUBREG, REG, PLUS, LO_SUM, CONST_INT}},              \
+{"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}},                  \
+{"symbolic_memory_operand", {SUBREG, MEM}},                            \
+{"label_ref_operand", {LABEL_REF}},                                    \
+{"sp64_medium_pic_operand", {CONST}},                                  \
+{"data_segment_operand", {SYMBOL_REF, PLUS, CONST}},                   \
+{"text_segment_operand", {LABEL_REF, SYMBOL_REF, PLUS, CONST}},                \
+{"reg_or_nonsymb_mem_operand", {SUBREG, REG, MEM}},                    \
+{"splittable_symbolic_memory_operand", {MEM}},                         \
+{"splittable_immediate_memory_operand", {MEM}},                                \
+{"eq_or_neq", {EQ, NE}},                                               \
+{"normal_comp_operator", {GE, GT, LE, LT, GTU, LEU}},                  \
+{"noov_compare_op", {NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, LTU}},     \
+{"v9_regcmp_op", {EQ, NE, GE, LT, LE, GT}},                            \
+{"extend_op", {SIGN_EXTEND, ZERO_EXTEND}},                             \
+{"cc_arithop", {AND, IOR, XOR}},                                       \
+{"cc_arithopn", {AND, IOR}},                                           \
+{"arith_operand", {SUBREG, REG, CONST_INT}},                           \
+{"arith_add_operand", {SUBREG, REG, CONST_INT}},                       \
+{"arith11_operand", {SUBREG, REG, CONST_INT}},                         \
+{"arith10_operand", {SUBREG, REG, CONST_INT}},                         \
+{"arith_double_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}},      \
+{"arith_double_add_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}},  \
+{"arith11_double_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}},    \
+{"arith10_double_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}},    \
+{"small_int", {CONST_INT}},                                            \
+{"small_int_or_double", {CONST_INT, CONST_DOUBLE}},                    \
+{"uns_small_int", {CONST_INT}},                                                \
+{"uns_arith_operand", {SUBREG, REG, CONST_INT}},                       \
+{"clobbered_register", {REG}},                                         \
+{"input_operand", {SUBREG, REG, CONST_INT, MEM, CONST}},               \
+{"zero_operand", {CONST_INT}},                                         \
+{"const64_operand", {CONST_INT, CONST_DOUBLE}},                                \
+{"const64_high_operand", {CONST_INT, CONST_DOUBLE}},
+
 /* The number of Pmode words for the setjmp buffer.  */
 #define JMP_BUF_SIZE 12
 
 #define DONT_ACCESS_GBLS_AFTER_EPILOGUE (flag_pic)
 
-/* Declare functions defined in sparc.c and used in templates.  */
-
-extern char *singlemove_string ();
-extern char *output_move_double ();
-extern char *output_move_quad ();
-extern char *output_fp_move_double ();
-extern char *output_fp_move_quad ();
-extern char *output_block_move ();
-extern char *output_scc_insn ();
-extern char *output_cbranch ();
-extern char *output_v9branch ();
-extern char *output_return ();
-
 /* Defined in flags.h, but insn-emit.c does not include flags.h.  */
 
 extern int flag_pic;
-
-/* Before the prologue, the return address is %o7 + 8.  OK, sometimes it's
-   +12, but always using +8 is close enough for frame unwind purposes.
-   Actually, just using %o7 is close enough for unwinding, but %o7+8
-   is something you can return to.  */
-#define INCOMING_RETURN_ADDR_RTX \
-  gen_rtx (PLUS, word_mode, gen_rtx (REG, word_mode, 15), GEN_INT (8))
-
-/* The offset from the incoming value of %sp to the top of the stack frame
-   for the current function.  On sparc64, we have to account for the stack
-   bias if present.  */
-
-#define INCOMING_FRAME_SP_OFFSET SPARC_STACK_BIAS