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