/* Definitions of target machine for GNU compiler, for Sun SPARC.
- Copyright (C) 1987, 88, 89, 92, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92, 94, 95, 96, 1997 Free Software Foundation,
+ Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com).
64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
at Cygnus Support.
/* 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 "%{!shared:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} %{g:-lg}}"
-
-/* Provide required defaults for linker -e and -d switches. */
-
-#define LINK_SPEC \
- "%{!shared:%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp} %{static:-Bstatic} \
- %{assert*} %{shared:-assert pure-text}"
-
-/* Special flags to the Sun-4 assembler when using pipe for input. */
-
-#define ASM_SPEC \
- " %| %{R} %{!pg:%{!p:%{fpic:-k} %{fPIC:-k}}} %{keep-local-as-symbols:-L}"
-
/* Define macros to distinguish architectures. */
-#ifdef SPARCV9
+#if SPARC_ARCH64
#define CPP_SPEC "\
%{mint64:-D__INT_MAX__=9223372036854775807LL -D__LONG_MAX__=9223372036854775807LL} \
%{mlong64:-D__LONG_MAX__=9223372036854775807LL} \
"
#else
-#define CPP_SPEC "\
+#define CPP_SPEC "%(cpp_cpu)"
+#endif
+
+/* Common CPP definitions used by CPP_SPEC amongst the various targets
+ for handling -mcpu=xxx switches. */
+/* ??? v8plus/v9/ultrasparc handling is tentative */
+#define CPP_CPU_SPEC "\
+%{mcypress:} \
%{msparclite:-D__sparclite__} \
%{mf930:-D__sparclite__} %{mf934:-D__sparclite__} \
%{mv8:-D__sparc_v8__} \
-%{msupersparc:-D__supersparc__ -D__sparc_v8__} \
+%{msupersparc:-D__supersparc__ -D__sparc_v8__} \
+%{mcpu=sparclet:-D__sparclet__} %{mcpu=tsc701:-D__sparclet__} \
+%{mcpu=sparclite:-D__sparclite__} \
+%{mcpu=f930:-D__sparclite__} %{mcpu=f934:-D__sparclite__} \
+%{mcpu=v8:-D__sparc_v8__} \
+%{mcpu=supersparc:-D__supersparc__ -D__sparc_v8__} \
+%{mcpu=v8plus:-D__sparc_v9__} \
+%{mcpu=v9:-D__sparc_v9__} \
+%{mcpu=ultrasparc:-D__sparc_v9__} \
+%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_default)}}}}}}} \
"
-#endif
/* Prevent error on `-sun4' and `-target sun4' options. */
/* This used to translate -dalign to -malign, but that is no good
because it can't turn off the usual meaning of making debugging dumps. */
+/* Translate old style -m<cpu> into new style -mcpu=<cpu>.
+ ??? Delete support for -m<cpu> for 2.9. */
+
+#define CC1_SPEC "\
+%{sun4:} %{target:} \
+%{mcypress:-mcpu=cypress} \
+%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \
+%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
+"
+
+#define LIB_SPEC "%{!shared:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} %{g:-lg}}"
+
+/* Provide required defaults for linker -e and -d switches. */
+
+#define LINK_SPEC \
+ "%{!shared:%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp} %{static:-Bstatic} \
+ %{assert*} %{shared:%{!mimpure-text:-assert pure-text}}"
+
+/* Special flags to the Sun-4 assembler when using pipe for input. */
+
+#define ASM_SPEC "\
+%| %{R} %{!pg:%{!p:%{fpic:-k} %{fPIC:-k}}} %{keep-local-as-symbols:-L} \
+%(asm_cpu) \
+"
-#define CC1_SPEC "%{sun4:} %{target:}"
+/* 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. */
-#ifdef SPARCV9
+#define EXTRA_SPECS \
+ { "cpp_cpu", CPP_CPU_SPEC }, \
+ { "cpp_default", CPP_DEFAULT_SPEC }, \
+ { "asm_cpu", ASM_CPU_SPEC }, \
+ { "asm_default", ASM_DEFAULT_SPEC }, \
+ SUBTARGET_EXTRA_SPECS
+
+#define SUBTARGET_EXTRA_SPECS
+\f
+#if SPARC_ARCH64
#define PTRDIFF_TYPE "long long int"
#define SIZE_TYPE "long long unsigned int"
#else
#define PTRDIFF_TYPE "int"
-/* In 2.4 it should work to delete this.
- #define SIZE_TYPE "int" */
+/* The default value for SIZE_TYPE is "unsigned int" which is what we want. */
#endif
/* ??? This should be 32 bits for v9 but what can we do? */
#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. */
#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 -mmedlow. */
-#define MASK_ENV32 0x10000
-#define TARGET_ENV32 (target_flags & MASK_ENV32)
-
-/* Memory models.
- Two memory models are supported:
- TARGET_MEDLOW: 32 bit address space, top 32 bits = 0
- (pointers still 64 bits)
- TARGET_MEDANY: 32 bit address space, data segment loaded anywhere
- (use %g4 as offset).
- TARGET_FULLANY: not supported yet.
+/* Nonzero if generating code to run in a 64 bit environment. */
+#define MASK_ARCH64 0x10000
+#define TARGET_ARCH64 (target_flags & MASK_ARCH64)
+#define TARGET_ARCH32 (! TARGET_ARCH64)
+
+/* SPARC64 memory models.
+ TARGET_MEDLOW: 32 bit address space, top 32 bits = 0,
+ avoid generating %uhi and %ulo terms.
+ (pointers can be 32 or 64 bits)
+ TARGET_MEDANY: 64 bit address space, data segment restricted to 4G, but
+ can be loaded anywhere (use %g4 as offset).
+ TARGET_FULLANY: 64 bit address space, no restrictions.
+ This option is not fully supported yet.
These options are for v9 only. All mask values are nonzero so the v8
compiler can assume this stuff won't interfere. */
#define MASK_MEDLOW 0x20000
#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}, \
{"medlow", -MASK_CODE_MODEL}, \
{"medlow", MASK_MEDLOW}, \
{"medany", -MASK_CODE_MODEL}, \
- {"medany", MASK_MEDANY},
+ {"medany", MASK_MEDANY}, \
+ {"fullany", -MASK_CODE_MODEL}, \
+ {"fullany", MASK_FULLANY},
#else
-#define V9_SWITCHES
+#define ARCH64_SWITCHES
#endif
+
+/* Processor type.
+ These must match the values for the cpu attribute in sparc.md. */
+enum processor_type {
+ PROCESSOR_V7,
+ PROCESSOR_CYPRESS,
+ PROCESSOR_V8,
+ PROCESSOR_SUPERSPARC,
+ PROCESSOR_SPARCLITE,
+ PROCESSOR_F930,
+ PROCESSOR_F934,
+ PROCESSOR_SPARCLET,
+ PROCESSOR_TSC701,
+ PROCESSOR_V8PLUS,
+ PROCESSOR_V9,
+ PROCESSOR_ULTRASPARC
+};
+
+/* This is set from -m{cpu,tune}=xxx. */
+extern enum processor_type sparc_cpu;
+
+/* Recast the cpu class to be the cpu attribute.
+ Every file includes us, but not every file includes insn-attr.h. */
+#define sparc_cpu_attr ((enum attr_cpu) sparc_cpu)
+
+/* This macro is similar to `TARGET_SWITCHES' but defines names of
+ command options that have values. Its definition is an
+ initializer with a subgrouping for each command option.
+
+ Each subgrouping contains a string constant, that defines the
+ fixed part of the option name, and the address of a variable.
+ The variable, type `char *', is set to the variable part of the
+ given option if the fixed part matches. The actual option name
+ is made by appending `-m' to the specified name.
+
+ Here is an example which defines `-mshort-data-NUMBER'. If the
+ given option is `-mshort-data-512', the variable `m88k_short_data'
+ will be set to the string `"512"'.
+
+ extern char *m88k_short_data;
+ #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */
+
+#define TARGET_OPTIONS \
+{ \
+ {"cpu=", &sparc_select[1].string}, \
+ {"tune=", &sparc_select[2].string}, \
+ SUBTARGET_OPTIONS \
+}
+
+/* This is meant to be redefined in target specific files. */
+#define SUBTARGET_OPTIONS
+
+/* sparc_select[0] is reserved for the default cpu. */
+struct sparc_cpu_select
+{
+ char *string;
+ char *name;
+ int set_tune_p;
+ int set_arch_p;
+};
+
+extern struct sparc_cpu_select sparc_select[];
\f
/* target machine storage layout */
#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 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
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] = TARGET_MEDANY != 0; \
+ int regno; \
+ for (regno = 32; regno < SPARC_LAST_V9_FCC_REG; regno++) \
+ fixed_regs[regno] = 1; \
} \
+ /* Don't unfix g2-g4 if they were fixed with -ffixed-. */ \
+ fixed_regs[2] |= ! TARGET_APP_REGS; \
+ fixed_regs[3] |= ! TARGET_APP_REGS; \
+ fixed_regs[4] |= ! TARGET_APP_REGS || TARGET_MEDANY; \
if (TARGET_FLAT) \
{ \
/* Let the compiler believe the frame pointer is still \
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
flat window model. However, the debugger won't be able to backtrace through
us with out it. */
#define FRAME_POINTER_REQUIRED \
- (TARGET_FRW ? (current_function_calls_alloca || current_function_varargs \
- || !leaf_function_p ()) \
+ (TARGET_FLAT ? (current_function_calls_alloca || current_function_varargs \
+ || !leaf_function_p ()) \
: ! (leaf_function_p () && only_leaf_regs_used ()))
/* C statement to store the difference between the frame pointer
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. */
/* Register in which static-chain is passed to a function. This must
not be a register used by the prologue. */
-#define STATIC_CHAIN_REGNUM (TARGET_V9 ? 5 : 2)
+#define STATIC_CHAIN_REGNUM (TARGET_ARCH64 ? 5 : 2)
/* Register which holds offset table for position-independent
data references. */
For v9, all aggregates are returned in memory. */
#define RETURN_IN_MEMORY(TYPE) \
(TYPE_MODE (TYPE) == BLKmode \
- || (! TARGET_V9 && (TYPE_MODE (TYPE) == TFmode \
- || TYPE_MODE (TYPE) == TCmode)))
+ || (! TARGET_ARCH64 && (TYPE_MODE (TYPE) == TFmode \
+ || TYPE_MODE (TYPE) == TCmode)))
/* Functions which return large structures get the address
to place the wanted value at offset 64 from the frame.
#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, \
have a class that is the union of FPCC_REGS with either of the others,
it is important that it appear first. Otherwise the compiler will die
trying to compile _fixunsdfsi because fix_truncdfsi2 won't match its
- constraints. */
+ constraints.
+
+ It is important that SPARC_ICC_REG have class NO_REGS. Otherwise combine
+ may try to use it to hold an SImode value. See register_operand.
+ ??? Should %fcc[0123] be handled similarily?
+*/
-#ifdef SPARCV9
enum reg_class { NO_REGS, FPCC_REGS, GENERAL_REGS, FP_REGS, EXTRA_FP_REGS,
GENERAL_OR_FP_REGS, GENERAL_OR_EXTRA_FP_REGS,
ALL_REGS, LIM_REG_CLASSES };
-#else
-enum reg_class { NO_REGS, GENERAL_REGS, FP_REGS, ALL_REGS, LIM_REG_CLASSES };
-#endif
#define N_REG_CLASSES (int) LIM_REG_CLASSES
/* Give names of register classes as strings for dump file. */
-#ifdef SPARCV9
#define REG_CLASS_NAMES \
{ "NO_REGS", "FPCC_REGS", "GENERAL_REGS", "FP_REGS", "EXTRA_FP_REGS", \
"GENERAL_OR_FP_REGS", "GENERAL_OR_EXTRA_FP_REGS", "ALL_REGS" }
-#else
-#define REG_CLASS_NAMES \
- { "NO_REGS", "GENERAL_REGS", "FP_REGS", "ALL_REGS" }
-#endif
/* Define which registers fit in which classes.
This is an initializer for a vector of HARD_REG_SET
of length N_REG_CLASSES. */
-#ifdef SPARCV9
#define REG_CLASS_CONTENTS \
- {{0, 0, 0, 0}, {0, 0, 0, 0xf}, {-2, 0, 0, 0}, \
- {0, -1, 0, 0}, {0, -1, -1, 0}, {-2, -1, 0, 0}, {-2, -1, -1, 0}, \
- {-2, -1, -1, 0xf}}
-#else
-#if 0 && defined (__GNUC__)
-#define REG_CLASS_CONTENTS {0LL, 0xfffffffeLL, 0xffffffff00000000LL, 0xfffffffffffffffeLL}
-#else
-#define REG_CLASS_CONTENTS {{0, 0}, {-2, 0}, {0, -1}, {-2, -1}}
-#endif
-#endif
+ {{0, 0, 0, 0}, {0, 0, 0, 0xf}, \
+ {-1, 0, 0, 0}, {0, -1, 0, 0}, {0, -1, -1, 0}, \
+ {-1, -1, 0, 0}, {-1, -1, -1, 0}, {-1, -1, -1, 0x1f}}
/* The same information, inverted:
Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression
or could index an array. */
-#ifdef SPARCV9
-#define REGNO_REG_CLASS(REGNO) \
- ((REGNO) == 0 ? NO_REGS \
- : (REGNO) < 32 ? GENERAL_REGS \
- : (REGNO) < 64 ? FP_REGS \
- : (REGNO) < 96 ? EXTRA_FP_REGS \
- : FPCC_REGS)
-#else
-#define REGNO_REG_CLASS(REGNO) \
- ((REGNO) >= 32 ? FP_REGS : (REGNO) == 0 ? NO_REGS : GENERAL_REGS)
-#endif
+extern enum reg_class sparc_regno_reg_class[];
+
+#define REGNO_REG_CLASS(REGNO) sparc_regno_reg_class[(REGNO)]
/* This is the order in which to allocate registers normally.
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 BASE_REG_CLASS GENERAL_REGS
/* Local macro to handle the two v9 classes of FP regs. */
-#ifdef SPARCV9
#define FP_REG_CLASS_P(CLASS) ((CLASS) == FP_REGS || (CLASS) == EXTRA_FP_REGS)
-#else
-#define FP_REG_CLASS_P(CLASS) ((CLASS) == FP_REGS)
-#endif
-/* Get reg_class from a letter such as appears in the machine description. */
+/* Get reg_class from a letter such as appears in the machine description.
+ In the not-v9 case, coerce v9's 'e' class to 'f', so we can use 'e' in the
+ .md file for v8 and v9. */
-#ifdef SPARCV9
-#define REG_CLASS_FROM_LETTER(C) \
- ((C) == 'f' ? FP_REGS \
- : (C) == 'e' ? EXTRA_FP_REGS \
- : (C) == 'c' ? FPCC_REGS \
- : NO_REGS)
-#else
-/* Coerce v9's 'e' class to 'f', so we can use 'e' in the .md file for
- v8 and v9. */
#define REG_CLASS_FROM_LETTER(C) \
- ((C) == 'f' ? FP_REGS : (C) == 'e' ? FP_REGS : NO_REGS)
-#endif
+(TARGET_V9 \
+ ? ((C) == 'f' ? FP_REGS \
+ : (C) == 'e' ? EXTRA_FP_REGS \
+ : (C) == 'c' ? FPCC_REGS \
+ : NO_REGS) \
+ : ((C) == 'f' ? FP_REGS \
+ : (C) == 'e' ? FP_REGS \
+ : (C) == 'c' ? FPCC_REGS \
+ : NO_REGS))
/* The letters I, J, K, L and M in a register constraint string
can be used to stand for particular ranges of immediate operands.
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.
because the movsi and movsf patterns don't handle r/f moves.
For v8 we copy the default definition. */
#define SECONDARY_MEMORY_NEEDED_MODE(MODE) \
- (TARGET_V9 \
+ (TARGET_ARCH64 \
? (GET_MODE_BITSIZE (MODE) < 32 \
? mode_for_size (32, GET_MODE_CLASS (MODE), 0) \
: MODE) \
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
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)) == 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 \
For Pascal, also pass arrays by reference. */
#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
((TYPE && AGGREGATE_TYPE_P (TYPE)) \
- || (!TARGET_V9 && MODE == TFmode))
+ || (!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
to do this is made in regclass.c. */
extern int leaf_function;
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
- (TARGET_FRW ? sparc_flat_output_function_prologue (FILE, SIZE) \
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+ (TARGET_FLAT ? sparc_flat_output_function_prologue (FILE, SIZE) \
: output_function_prologue (FILE, SIZE, leaf_function))
-
+\f
/* Output assembler code to FILE to increment profiler label # LABELNO
- for profiling a function entry. */
+ for profiling a function entry.
+
+ 32 bit sparc uses %g2 as the STATIC_CHAIN_REGNUM which gets clobbered
+ during profiling so we need to save/restore it around the call to mcount.
+ We're guaranteed that a save has just been done, and we use the space
+ allocated for intreg/fpreg value passing. */
#define FUNCTION_PROFILER(FILE, LABELNO) \
do { \
- fputs ("\tsethi %hi(", (FILE)); \
- ASM_OUTPUT_INTERNAL_LABELREF (FILE, "LP", LABELNO); \
- fputs ("),%o0\n", (FILE)); \
+ char buf[20]; \
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LP", (LABELNO)); \
+ if (! TARGET_ARCH64) \
+ fputs ("\tst %g2,[%fp-4]\n", FILE); \
+ fputs ("\tsethi %hi(", FILE); \
+ assemble_name (FILE, buf); \
+ fputs ("),%o0\n", FILE); \
if (TARGET_MEDANY) \
- fprintf (FILE, "\tadd %%o0,%s,%%o0\n", \
- MEDANY_BASE_REG); \
- fputs ("\tcall mcount\n\tadd %lo(", (FILE)); \
- ASM_OUTPUT_INTERNAL_LABELREF (FILE, "LP", LABELNO); \
- fputs ("),%o0,%o0\n", (FILE)); \
+ fprintf (FILE, "\tadd %o0,%s,%o0\n", MEDANY_BASE_REG); \
+ fputs ("\tcall mcount\n\tadd %o0,%lo(", FILE); \
+ assemble_name (FILE, buf); \
+ fputs ("),%o0\n", FILE); \
+ if (! TARGET_ARCH64) \
+ fputs ("\tld [%fp-4],%g2\n", FILE); \
} while (0)
-
/* 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.
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. */
#define TRAMPOLINE_TEMPLATE(FILE) \
do { \
- if (TARGET_V9) \
+ if (TARGET_ARCH64) \
{ \
fprintf (FILE, "\trd %%pc,%%g1\n"); \
fprintf (FILE, "\tldx [%%g1+24],%%g5\n"); \
/* Length in units of the trampoline for entering a nested function. */
-#define TRAMPOLINE_SIZE (TARGET_V9 ? 40 : 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); \
/* 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_V9 && current_function_returns_struct))
+#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]. */
? gen_rtx (REG, Pmode, 31) \
: 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
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. */
#define RTX_COSTS(X,CODE,OUTER_CODE) \
case MULT: \
- return (TARGET_V8 || TARGET_SPARCLITE || 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. */
} \
}
+/* 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 ();