X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fconfig%2Fsparc%2Fsparc.h;h=9d8f1a1a3b60b8cd3dec60d7a8e07383a33f1d07;hb=7672cfe1a585cad637a1c924d31fa7a1b38eb887;hp=f0a1c5c48cc1b34297c9e180c5f4bbc9a802ce5c;hpb=171a5cccb4b905b3f9dffc2d56dd3c1e45843f3f;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index f0a1c5c48cc..9d8f1a1a3b6 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -1,5 +1,5 @@ /* Definitions of target machine for GNU compiler, for Sun SPARC. - Copyright (C) 1987, 88, 89, 92, 94, 95, 1996 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 89, 92, 94-6, 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. @@ -22,98 +22,129 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Note that some other tm.h files include this one and then override - many of the definitions that relate to assembler syntax. */ - -/* Sparc64 support has been added by trying to allow for a day when one - compiler can handle both v8 and v9. There are a few cases where this - isn't doable, but keep them to a minimum! - - TARGET_V9 is used to select at runtime the sparc64 chip. - TARGET_ARCH64 is used to select at runtime a 64 bit environment. - SPARC_V9 is defined as 0 or 1 (so it may be used inside and outside - #define's), and says whether the cpu is a sparc64 chip (which may be - running in a 32 or 64 bit environment). - SPARC_ARCH64 is defined as 0 for a 32 bit environment and 1 for a 64 bit - environment. - - In places where it is possible to choose at runtime, use TARGET_V9 and - TARGET_ARCH64. In places where it is currently not possible to select - between the two at runtime use SPARC_{V9,ARCH64}. Again, keep uses of - SPARC_{V9,ARCH64} to a minimum. No attempt is made to support both v8 - and v9 in the v9 compiler. - - ??? All uses of SPARC_V9 have been removed. Try not to add new ones. -*/ + whatever definitions are necessary. */ -#ifndef SPARC_V9 -#define SPARC_V9 0 -#endif -#ifndef SPARC_ARCH64 -#define SPARC_ARCH64 0 -#endif +/* Specify this in a cover file to provide bi-architecture (32/64) support. */ +/* #define SPARC_BI_ARCH */ -/* Values of TARGET_CPU_DEFAULT, set via -D in the Makefile. */ -#define TARGET_CPU_sparc 0 -#define TARGET_CPU_sparclet 1 -#define TARGET_CPU_sparclite 2 -#define TARGET_CPU_sparc64 3 +/* Macro used later in this file to determine default architecture. */ +#define DEFAULT_ARCH32_P ((TARGET_DEFAULT & MASK_64BIT) == 0) -#if TARGET_CPU_DEFAULT == TARGET_CPU_sparc -#define CPP_DEFAULT_SPEC "" -#define ASM_DEFAULT_SPEC "" +/* TARGET_ARCH{32,64} are the main macros to decide which of the two + architectures to compile for. We allow targets to choose compile time or + runtime selection. */ +#ifdef SPARC_BI_ARCH +#define TARGET_ARCH32 (! TARGET_64BIT) #else +#define TARGET_ARCH32 (DEFAULT_ARCH32_P) +#endif +#define TARGET_ARCH64 (! TARGET_ARCH32) + +/* Code model selection. + -mcmodel is used to select the v9 code model. + Different code models aren't supported for v8 code. + + TARGET_CM_32: 32 bit address space, top 32 bits = 0, + pointers are 32 bits. Note that this isn't intended + to imply a v8 abi. + + TARGET_CM_MEDLOW: 32 bit address space, top 32 bits = 0, + avoid generating %uhi and %ulo terms, + pointers are 64 bits. + + TARGET_CM_MEDMID: 64 bit address space. + The executable must be in the low 16 TB of memory. + This corresponds to the low 44 bits, and the %[hml]44 + relocs are used. + + TARGET_CM_MEDANY: 64 bit address space. + The text and data segments have a maximum size of 31 + bits and may be located anywhere. The maximum offset + from any instruction to the label _GLOBAL_OFFSET_TABLE_ + is 31 bits. + + TARGET_CM_EMBMEDANY: 64 bit address space. + The text and data segments have a maximum size of 31 bits + and may be located anywhere. Register %g4 contains + the start address of the data segment. +*/ + +enum cmodel { + CM_32, + CM_MEDLOW, + CM_MEDMID, + CM_MEDANY, + CM_EMBMEDANY +}; + +/* Value of -mcmodel specified by user. */ +extern char *sparc_cmodel_string; +/* One of CM_FOO. */ +extern enum cmodel sparc_cmodel; + +/* V9 code model selection. */ +#define TARGET_CM_MEDLOW (sparc_cmodel == CM_MEDLOW) +#define TARGET_CM_MEDMID (sparc_cmodel == CM_MEDMID) +#define TARGET_CM_MEDANY (sparc_cmodel == CM_MEDANY) +#define TARGET_CM_EMBMEDANY (sparc_cmodel == CM_EMBMEDANY) + +#define SPARC_DEFAULT_CMODEL CM_MEDLOW + +/* This is call-clobbered in the normal ABI, but is reserved in the + home grown (aka upward compatible) embedded ABI. */ +#define EMBMEDANY_BASE_REG "%g4" + +/* Values of TARGET_CPU_DEFAULT, set via -D in the Makefile, + and specified by the user via --with-cpu=foo. + This specifies the cpu implementation, not the architecture size. */ +#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 /* generic v8 implementation */ +#define TARGET_CPU_supersparc 4 +#define TARGET_CPU_v9 5 /* generic v9 implementation */ +#define TARGET_CPU_sparc64 5 /* alias */ +#define TARGET_CPU_ultrasparc 6 + +#if TARGET_CPU_DEFAULT == TARGET_CPU_sparc || TARGET_CPU_DEFAULT == TARGET_CPU_v8 || TARGET_CPU_DEFAULT == TARGET_CPU_supersparc +#define CPP_CPU_DEFAULT_SPEC "" +#define ASM_CPU_DEFAULT_SPEC "" +#endif #if TARGET_CPU_DEFAULT == TARGET_CPU_sparclet -#define CPP_DEFAULT_SPEC "-D__sparclet__" -#define ASM_DEFAULT_SPEC "-Asparclet" -#else +#define CPP_CPU_DEFAULT_SPEC "-D__sparclet__" +#define ASM_CPU_DEFAULT_SPEC "-Asparclet" +#endif #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 +#define CPP_CPU_DEFAULT_SPEC "-D__sparclite__" +#define ASM_CPU_DEFAULT_SPEC "-Asparclite" +#endif +#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 /* ??? What does Sun's CC pass? */ -#define CPP_DEFAULT_SPEC "-D__sparc_v9__" +#define CPP_CPU_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 +#define ASM_CPU_DEFAULT_SPEC "-Av9" #endif +#if TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc +#define CPP_CPU_DEFAULT_SPEC "-D__sparc_v9__" +#define ASM_CPU_DEFAULT_SPEC "-Av9a" #endif +#ifndef CPP_CPU_DEFAULT_SPEC +Unrecognized value in TARGET_CPU_DEFAULT. #endif -/* Names to predefine in the preprocessor for this target machine. */ +/* Names to predefine in the preprocessor for this target machine. + ??? It would be nice to not include any subtarget specific values here, + however there's no way to portably provide subtarget values to + CPP_PREFINES. Also, -D values in CPP_SUBTARGET_SPEC don't get turned into + into foo, __foo and __foo__. */ -/* ??? The GCC_NEW_VARARGS macro is now obsolete, because gcc always uses - the right varags.h file when bootstrapping. */ -/* ??? It's not clear what value we want to use for -Acpu/machine for - sparc64 in 32 bit environments, so for now we only use `sparc64' in - 64 bit environments. */ -/* ??? __arch64__ is subject to change. */ - -#if SPARC_ARCH64 -#define CPP_PREDEFINES \ - "-Dsparc -Dsun -Dunix -D__arch64__ \ - -Asystem(unix) -Asystem(bsd) -Acpu(sparc64) -Amachine(sparc64)" -#else -#define CPP_PREDEFINES \ - "-Dsparc -Dsun -Dunix -D__GCC_NEW_VARARGS__ \ - -Asystem(unix) -Asystem(bsd) -Acpu(sparc) -Amachine(sparc)" -#endif +#define CPP_PREDEFINES "-Dsparc -Dsun -Dunix -Asystem(unix) -Asystem(bsd)" /* Define macros to distinguish architectures. */ -#if SPARC_ARCH64 -#define CPP_SPEC "\ -%{mint64:-D__INT_MAX__=9223372036854775807LL -D__LONG_MAX__=9223372036854775807LL} \ -%{mlong64:-D__LONG_MAX__=9223372036854775807LL} \ -" -#else -#define CPP_SPEC "%(cpp_cpu)" -#endif - /* Common CPP definitions used by CPP_SPEC amongst the various targets for handling -mcpu=xxx switches. */ #define CPP_CPU_SPEC "\ @@ -122,20 +153,47 @@ Unrecognized value in TARGET_CPU_DEFAULT. %{mf930:-D__sparclite__} %{mf934:-D__sparclite__} \ %{mv8:-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)}}}}}}} \ +%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}} \ +" + +/* ??? The GCC_NEW_VARARGS macro is now obsolete, because gcc always uses + the right varags.h file when bootstrapping. */ +/* ??? It's not clear what value we want to use for -Acpu/machine for + sparc64 in 32 bit environments, so for now we only use `sparc64' in + 64 bit environments. */ + +#define CPP_ARCH32_SPEC "-D__GCC_NEW_VARARGS__ -Acpu(sparc) -Amachine(sparc)" +#define CPP_ARCH64_SPEC "-D__arch64__ -Acpu(sparc64) -Amachine(sparc64)" +#define CPP_ARCH_DEFAULT_SPEC \ +(DEFAULT_ARCH32_P ? CPP_ARCH32_SPEC : CPP_ARCH64_SPEC) + +#define CPP_ARCH_SPEC "\ +%{m32:%(cpp_arch32)} \ +%{m64:%(cpp_arch64)} \ +%{!m32:%{!m64:%(cpp_arch_default)}} \ " +/* Macros to distinguish endianness. */ +#define CPP_ENDIAN_SPEC "%{mlittle-endian:-D__LITTLE_ENDIAN__}" + +/* Macros to distinguish the particular subtarget. */ +#define CPP_SUBTARGET_SPEC "" + +#define CPP_SPEC "%(cpp_cpu) %(cpp_arch) %(cpp_endian) %(cpp_subtarget)" + /* Prevent error on `-sun4' and `-target sun4' options. */ /* This used to translate -dalign to -malign, but that is no good because it can't turn off the usual meaning of making debugging dumps. */ /* Translate old style -m into new style -mcpu=. - At some point support for -m will be deleted. */ + ??? Delete support for -m for 2.9. */ #define CC1_SPEC "\ %{sun4:} %{target:} \ @@ -144,13 +202,32 @@ Unrecognized value in TARGET_CPU_DEFAULT. %{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \ " -#define LIB_SPEC "%{!shared:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} %{g:-lg}}" +/* Override in target specific files. */ +#define ASM_CPU_SPEC "\ +%{mcpu=sparclet:-Asparclet} %{mcpu=tsc701:-Asparclet} \ +%{msparclite:-Asparclite} \ +%{mf930:-Asparclite} %{mf934:-Asparclite} \ +%{mcpu=sparclite:-Asparclite} \ +%{mcpu=f930:-Asparclite} %{mcpu=f934:-Asparclite} \ +%{mcpu=v8plus:-Av8plus} \ +%{mcpu=v9:-Av9} \ +%{mcpu=ultrasparc:-Av9a} \ +%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(asm_cpu_default)}}}}}}} \ +" -/* Provide required defaults for linker -e and -d switches. */ +/* Word size selection, among other things. + This is what GAS uses. Add %(asm_arch) to ASM_SPEC to enable. */ -#define LINK_SPEC \ - "%{!shared:%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp} %{static:-Bstatic} \ - %{assert*} %{shared:%{!mimpure-text:-assert pure-text}}" +#define ASM_ARCH32_SPEC "-32" +#define ASM_ARCH64_SPEC "-64" +#define ASM_ARCH_DEFAULT_SPEC \ +(DEFAULT_ARCH32_P ? ASM_ARCH32_SPEC : ASM_ARCH64_SPEC) + +#define ASM_ARCH_SPEC "\ +%{m32:%(asm_arch32)} \ +%{m64:%(asm_arch64)} \ +%{!m32:%{!m64:%(asm_arch_default)}} \ +" /* Special flags to the Sun-4 assembler when using pipe for input. */ @@ -159,16 +236,13 @@ Unrecognized value in TARGET_CPU_DEFAULT. %(asm_cpu) \ " -/* Override in target specific files. */ -#define ASM_CPU_SPEC "\ -%{msparclite:-Asparclite} \ -%{mf930:-Asparclite} %{mf934:-Asparclite} \ -%{mcpu=sparclite:-Asparclite} \ -%{mcpu=f930:-Asparclite} %{mcpu=f934:-Asparclite} \ -%{mcpu=v9:-Av9} \ -%{mcpu=ultrasparc:-Av9} \ -%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(asm_default)}}}}}}} \ -" +#define LIB_SPEC "%{!shared:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} %{g:-lg}}" + +/* Provide required defaults for linker -e and -d switches. */ + +#define LINK_SPEC \ + "%{!shared:%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp} %{static:-Bstatic} \ + %{assert*} %{shared:%{!mimpure-text:-assert pure-text}}" /* This macro defines names of additional specifications to put in the specs that can be used in various specifications like CC1_SPEC. Its definition @@ -180,22 +254,31 @@ Unrecognized value in TARGET_CPU_DEFAULT. Do not define this macro if it does not need to do anything. */ -#define EXTRA_SPECS \ +#define EXTRA_SPECS \ { "cpp_cpu", CPP_CPU_SPEC }, \ - { "cpp_default", CPP_DEFAULT_SPEC }, \ + { "cpp_cpu_default", CPP_CPU_DEFAULT_SPEC }, \ + { "cpp_arch32", CPP_ARCH32_SPEC }, \ + { "cpp_arch64", CPP_ARCH64_SPEC }, \ + { "cpp_arch_default", CPP_ARCH_DEFAULT_SPEC }, \ + { "cpp_arch", CPP_ARCH_SPEC }, \ + { "cpp_endian", CPP_ENDIAN_SPEC }, \ + { "cpp_subtarget", CPP_SUBTARGET_SPEC }, \ { "asm_cpu", ASM_CPU_SPEC }, \ - { "asm_default", ASM_DEFAULT_SPEC }, \ + { "asm_cpu_default", ASM_CPU_DEFAULT_SPEC }, \ + { "asm_arch32", ASM_ARCH32_SPEC }, \ + { "asm_arch64", ASM_ARCH64_SPEC }, \ + { "asm_arch_default", ASM_ARCH_DEFAULT_SPEC }, \ + { "asm_arch", ASM_ARCH_SPEC }, \ SUBTARGET_EXTRA_SPECS #define SUBTARGET_EXTRA_SPECS -#if SPARC_ARCH64 -#define PTRDIFF_TYPE "long long int" -#define SIZE_TYPE "long long unsigned int" -#else -#define PTRDIFF_TYPE "int" -/* The default value for SIZE_TYPE is "unsigned int" which is what we want. */ +#ifdef SPARC_BI_ARCH +#define NO_BUILTIN_PTRDIFF_TYPE +#define NO_BUILTIN_SIZE_TYPE #endif +#define PTRDIFF_TYPE (TARGET_ARCH64 ? "long long int" : "int") +#define SIZE_TYPE (TARGET_ARCH64 ? "long long unsigned int" : "unsigned int") /* ??? This should be 32 bits for v9 but what can we do? */ #define WCHAR_TYPE "short unsigned int" @@ -213,7 +296,7 @@ void sparc_override_options (); #define OVERRIDE_OPTIONS \ do { \ - if (profile_flag || profile_block_flag) \ + if (profile_flag || profile_block_flag || profile_arc_flag) \ { \ if (flag_pic) \ { \ @@ -319,18 +402,14 @@ extern int target_flags; #define MASK_HARD_QUAD 0x800 #define TARGET_HARD_QUAD (target_flags & MASK_HARD_QUAD) -/* Bit 0x1000 currently unused. */ +/* 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. - This option is for v9 only. */ -#define MASK_INT64 0x2000 -#define TARGET_INT64 (target_flags & MASK_INT64) - -/* Nonzero if longs are 64 bits. - This option is for v9 only. */ -#define MASK_LONG64 0x4000 -#define TARGET_LONG64 (target_flags & MASK_LONG64) +/* 0x2000, 0x4000 are unused */ /* Nonzero if pointers are 64 bits. This is not a user selectable option, though it may be one day - @@ -338,31 +417,13 @@ extern int target_flags; #define MASK_PTR64 0x8000 #define TARGET_PTR64 (target_flags & MASK_PTR64) -/* Nonzero if generating code to run in a 64 bit environment. */ -#define MASK_ARCH64 0x10000 -#define TARGET_ARCH64 (target_flags & MASK_ARCH64) -#define TARGET_ARCH32 (! TARGET_ARCH64) - -/* SPARC64 memory models. - TARGET_MEDLOW: 32 bit address space, top 32 bits = 0, - avoid generating %uhi and %ulo terms. - (pointers can be 32 or 64 bits) - TARGET_MEDANY: 64 bit address space, data segment restricted to 4G, but - can be loaded anywhere (use %g4 as offset). - TARGET_FULLANY: 64 bit address space, no restrictions. - This option is not fully supported yet. - These options are for v9 only. All mask values are nonzero so the v8 - compiler can assume this stuff won't interfere. */ -#define MASK_MEDLOW 0x20000 -#define MASK_MEDANY 0x40000 -#define MASK_FULLANY 0x60000 -#define MASK_CODE_MODEL (MASK_MEDLOW + MASK_MEDANY) -#define TARGET_MEDLOW ((target_flags & MASK_CODE_MODEL) == MASK_MEDLOW) -#define TARGET_MEDANY ((target_flags & MASK_CODE_MODEL) == MASK_MEDANY) -#define TARGET_FULLANY ((target_flags & MASK_CODE_MODEL) == MASK_FULLANY) - -/* ??? There are hardcoded references to this reg in the .md file. */ -#define MEDANY_BASE_REG "%g4" +/* Nonzero if generating code to run in a 64 bit environment. + This is intended to only be used by TARGET_ARCH{32,64} as they are the + mechanism used to control compile time or run time selection. */ +#define MASK_64BIT 0x10000 +#define TARGET_64BIT (target_flags & MASK_64BIT) + +/* 0x20000,0x40000 unused */ /* Non-zero means use a stack bias of 2047. Stack offsets are obtained by adding 2047 to %sp. This option is for v9 only and is the default. */ @@ -376,6 +437,18 @@ extern int target_flags; #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 } @@ -383,10 +456,12 @@ extern int target_flags; An empty string NAME is used to identify the default VALUE. */ #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}, \ @@ -399,15 +474,22 @@ extern int target_flags; {"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. */ \ + /* ??? These are deprecated, coerced to -mcpu=. Delete in 2.9. */ \ {"cypress", 0}, \ {"sparclite", 0}, \ {"f930", 0}, \ {"f934", 0}, \ {"v8", 0}, \ {"supersparc", 0}, \ + /* End of deprecated options. */ \ + /* -mptrNN exists for *experimental* purposes. */ \ +/* {"ptr64", MASK_PTR64}, */ \ +/* {"ptr32", -MASK_PTR64}, */ \ + {"32", -MASK_64BIT}, \ + {"64", MASK_64BIT}, \ + {"stack-bias", MASK_STACK_BIAS}, \ + {"no-stack-bias", -MASK_STACK_BIAS}, \ SUBTARGET_SWITCHES \ - ARCH64_SWITCHES \ { "", TARGET_DEFAULT}} /* MASK_APP_REGS must always be the default because that's what @@ -418,32 +500,6 @@ extern int target_flags; /* This is meant to be redefined in target specific files. */ #define SUBTARGET_SWITCHES -/* ??? Until we support a combination 32/64 bit compiler, these options - are only defined for the v9 compiler in a true 64 bit environment. */ -#if SPARC_ARCH64 -#define ARCH64_SWITCHES \ -/* {"arch32", -MASK_ARCH64}, */ \ -/* {"arch64", MASK_ARCH64}, */ \ - {"int64", MASK_INT64+MASK_LONG64}, \ - {"int32", -MASK_INT64}, \ - {"int32", MASK_LONG64}, \ - {"long64", -MASK_INT64}, \ - {"long64", MASK_LONG64}, \ - {"long32", -(MASK_INT64+MASK_LONG64)}, \ -/* {"ptr64", MASK_PTR64}, */ \ -/* {"ptr32", -MASK_PTR64}, */ \ - {"stack-bias", MASK_STACK_BIAS}, \ - {"no-stack-bias", -MASK_STACK_BIAS}, \ - {"medlow", -MASK_CODE_MODEL}, \ - {"medlow", MASK_MEDLOW}, \ - {"medany", -MASK_CODE_MODEL}, \ - {"medany", MASK_MEDANY}, \ - {"fullany", -MASK_CODE_MODEL}, \ - {"fullany", MASK_FULLANY}, -#else -#define ARCH64_SWITCHES -#endif - /* Processor type. These must match the values for the cpu attribute in sparc.md. */ enum processor_type { @@ -455,7 +511,7 @@ enum processor_type { PROCESSOR_F930, PROCESSOR_F934, PROCESSOR_SPARCLET, - PROCESSOR_90C701, + PROCESSOR_TSC701, PROCESSOR_V8PLUS, PROCESSOR_V9, PROCESSOR_ULTRASPARC @@ -486,10 +542,14 @@ extern enum processor_type sparc_cpu; #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */ #define TARGET_OPTIONS \ -{ \ - {"cpu=", &sparc_select[1].string}, \ - {"tune=", &sparc_select[2].string}, \ - SUBTARGET_OPTIONS \ +{ \ + { "cpu=", &sparc_select[1].string }, \ + { "tune=", &sparc_select[2].string }, \ + { "cmodel=", &sparc_cmodel_string }, \ + { "align-loops=", &sparc_align_loops_string }, \ + { "align-jumps=", &sparc_align_jumps_string }, \ + { "align-functions=", &sparc_align_funcs_string }, \ + SUBTARGET_OPTIONS \ } /* This is meant to be redefined in target specific files. */ @@ -505,6 +565,18 @@ struct sparc_cpu_select }; extern struct sparc_cpu_select sparc_select[]; + +/* Variables to record values the user passes. */ +extern char *sparc_align_loops_string; +extern char *sparc_align_jumps_string; +extern char *sparc_align_funcs_string; +/* Parsed values as a power of two. */ +extern int sparc_align_loops; +extern int sparc_align_jumps; +extern int sparc_align_funcs; + +#define DEFAULT_SPARC_ALIGN_FUNCS \ +(sparc_cpu == PROCESSOR_ULTRASPARC ? 5 : 2) /* target machine storage layout */ @@ -517,15 +589,20 @@ extern struct sparc_cpu_select sparc_select[]; #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 @@ -543,16 +620,17 @@ extern struct sparc_cpu_select sparc_select[]; /* Now define the sizes of the C data types. */ #define SHORT_TYPE_SIZE 16 -#define INT_TYPE_SIZE (TARGET_INT64 ? 64 : 32) -#define LONG_TYPE_SIZE (TARGET_LONG64 ? 64 : 32) +#define INT_TYPE_SIZE 32 +#define LONG_TYPE_SIZE (TARGET_ARCH64 ? 64 : 32) #define LONG_LONG_TYPE_SIZE 64 #define FLOAT_TYPE_SIZE 32 #define DOUBLE_TYPE_SIZE 64 -#define MAX_INT_TYPE_SIZE 64 +#if defined (SPARC_BI_ARCH) #define MAX_LONG_TYPE_SIZE 64 +#endif -#if SPARC_ARCH64 +#if 0 /* ??? This does not work in SunOS 4.x, so it is not enabled here. Instead, it is enabled in sol2.h, because it does work under Solaris. */ /* Define for support of TFmode long double and REAL_ARITHMETIC. @@ -564,6 +642,34 @@ extern struct sparc_cpu_select sparc_select[]; See also the macro `Pmode' defined below. */ #define POINTER_SIZE (TARGET_PTR64 ? 64 : 32) +/* A macro to update MODE and UNSIGNEDP when an object whose type + is TYPE and which has the specified mode and signedness is to be + stored in a register. This macro is only called when TYPE is a + scalar type. */ +#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \ +if (TARGET_ARCH64 \ + && GET_MODE_CLASS (MODE) == MODE_INT \ + && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \ +{ \ + (MODE) = DImode; \ +} + +/* Define this macro if the promotion described by PROMOTE_MODE + should also be done for outgoing function arguments. */ +/* This is only needed for TARGET_ARCH64, but since PROMOTE_MODE is a no-op + for TARGET_ARCH32 this is ok. Otherwise we'd need to add a runtime test + for this value. */ +#define PROMOTE_FUNCTION_ARGS + +/* Define this macro if the promotion described by PROMOTE_MODE + should also be done for the return value of functions. + If this macro is defined, FUNCTION_VALUE must perform the same + promotions done by PROMOTE_MODE. */ +/* This is only needed for TARGET_ARCH64, but since PROMOTE_MODE is a no-op + for TARGET_ARCH32 this is ok. Otherwise we'd need to add a runtime test + for this value. */ +#define PROMOTE_FUNCTION_RETURN + /* Allocation boundary (in *bits*) for storing arguments in argument list. */ #define PARM_BOUNDARY (TARGET_ARCH64 ? 64 : 32) @@ -576,10 +682,9 @@ extern struct sparc_cpu_select sparc_select[]; (TARGET_ARCH64 ? (((LOC)+15) & ~15) : (((LOC)+7) & ~7)) /* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 32 +#define FUNCTION_BOUNDARY (1 << (sparc_align_funcs + 3)) /* Alignment of field after `int : 0' in a structure. */ -/* ??? Should this be based on TARGET_INT64? */ #define EMPTY_FIELD_BOUNDARY (TARGET_ARCH64 ? 64 : 32) /* Every structure's size must be a multiple of this. */ @@ -684,9 +789,10 @@ extern struct sparc_cpu_select sparc_select[]; #define FIRST_PSEUDO_REGISTER 101 +#define SPARC_FIRST_FP_REG 32 /* Additional V9 fp regs. */ -#define SPARC_FIRST_V9_FP_REG 64 -#define SPARC_LAST_V9_FP_REG 95 +#define SPARC_FIRST_V9_FP_REG 64 +#define SPARC_LAST_V9_FP_REG 95 /* V9 %fcc[0123]. V8 uses (figuratively) %fcc0. */ #define SPARC_FIRST_V9_FCC_REG 96 #define SPARC_LAST_V9_FCC_REG 99 @@ -695,18 +801,33 @@ extern struct sparc_cpu_select sparc_select[]; /* Integer CC reg. We don't distinguish %icc from %xcc. */ #define SPARC_ICC_REG 100 +/* Nonzero if REGNO is an fp reg. */ +#define SPARC_FP_REG_P(REGNO) \ +((REGNO) >= SPARC_FIRST_FP_REG && (REGNO) <= SPARC_LAST_V9_FP_REG) + +/* Argument passing regs. */ +#define SPARC_OUTGOING_INT_ARG_FIRST 8 +#define SPARC_INCOMING_INT_ARG_FIRST 24 +#define SPARC_FP_ARG_FIRST 32 + /* 1 for registers that have pervasive standard uses and are not available for the register allocator. + On non-v9 systems: g1 is free to use as temporary. g2-g4 are reserved for applications. Gcc normally uses them as temporaries, but this can be disabled via the -mno-app-regs option. g5 through g7 are reserved for the operating system. + On v9 systems: - g1 and g5 are free to use as temporaries. - g2-g4 are reserved for applications. Gcc normally uses them as + g1,g5 are free to use as temporaries, and are free to use between calls + if the call is to an external function via the PLT. + g4 is free to use as a temporary in the non-embedded case. + g4 is reserved in the embedded case. + g2-g3 are reserved for applications. Gcc normally uses them as temporaries, but this can be disabled via the -mno-app-regs option. - g6-g7 are reserved for the operating system. + g6-g7 are reserved for the operating system (or application in + embedded case). ??? Register 1 is used as a temporary by the 64 bit sethi pattern, so must currently be a fixed register until this pattern is rewritten. Register 1 is also used when restoring call-preserved registers in large @@ -765,17 +886,13 @@ extern struct sparc_cpu_select sparc_select[]; #define CONDITIONAL_REGISTER_USAGE \ do \ { \ - if (! SPARC_ARCH64) \ + if (TARGET_ARCH32) \ { \ fixed_regs[5] = 1; \ } \ - if (SPARC_ARCH64) \ + else \ { \ - int regno; \ fixed_regs[1] = 1; \ - /* ??? We need to scan argv for -fcall-used-. */ \ - for (regno = 48; regno < 80; regno++) \ - call_used_regs[regno] = 0; \ } \ if (! TARGET_V9) \ { \ @@ -799,7 +916,7 @@ do \ /* 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; \ + fixed_regs[4] |= ! TARGET_APP_REGS || TARGET_CM_EMBMEDANY; \ if (TARGET_FLAT) \ { \ /* Let the compiler believe the frame pointer is still \ @@ -868,21 +985,25 @@ extern int sparc_mode_class[]; /* Register to use for pushing function arguments. */ #define STACK_POINTER_REGNUM 14 -/* Actual top-of-stack address is 92/136 greater than the contents of the +/* Actual top-of-stack address is 92/176 greater than the contents of the stack pointer register for !v9/v9. That is: - !v9: 64 bytes for the in and local registers, 4 bytes for structure return - address, and 24 bytes for the 6 register parameters. - - v9: 128 bytes for the in and local registers + 8 bytes reserved. */ + address, and 6*4 bytes for the 6 register parameters. + - v9: 128 bytes for the in and local registers + 6*8 bytes for the integer + parameter regs. */ #define STACK_POINTER_OFFSET FIRST_PARM_OFFSET(0) /* The stack bias (amount by which the hardware register is offset by). */ -#define SPARC_STACK_BIAS (TARGET_STACK_BIAS ? 2047 : 0) +#define SPARC_STACK_BIAS ((TARGET_ARCH64 && TARGET_STACK_BIAS) ? 2047 : 0) + +/* Is stack biased? */ +#define STACK_BIAS SPARC_STACK_BIAS /* Base register for access to local variables of the function. */ #define FRAME_POINTER_REGNUM 30 #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 @@ -927,11 +1048,16 @@ extern int sparc_mode_class[]; /* Sparc ABI says that quad-precision floats and all structures are returned in memory. - For v9, all aggregates are returned in memory. */ + For v9: unions <= 32 bytes in size are returned in int regs, + structures up to 32 bytes are returned in int and fp regs. + FIXME: wip */ + #define RETURN_IN_MEMORY(TYPE) \ - (TYPE_MODE (TYPE) == BLKmode \ - || (! TARGET_ARCH64 && (TYPE_MODE (TYPE) == TFmode \ - || TYPE_MODE (TYPE) == TCmode))) +(TARGET_ARCH32 \ + ? (TYPE_MODE (TYPE) == BLKmode \ + || TYPE_MODE (TYPE) == TFmode \ + || TYPE_MODE (TYPE) == TCmode) \ + : TYPE_MODE (TYPE) == BLKmode) /* Functions which return large structures get the address to place the wanted value at offset 64 from the frame. @@ -974,7 +1100,9 @@ extern int sparc_mode_class[]; For any two classes, it is very desirable that there be another class that represents their union. */ -/* The SPARC has two kinds of registers, general and floating point. +/* The SPARC has various kinds of registers: general, floating point, + and condition codes [well, it has others as well, but none that we + care directly about]. For v9 we must distinguish between the upper and lower floating point registers because the upper ones can't hold SFmode values. @@ -1041,10 +1169,7 @@ extern enum reg_class sparc_regno_reg_class[]; We put %f0/%f1 last among the float registers, so as to make it more likely that a pseudo-register which dies in the float return register will get allocated to the float return register, thus saving a move - instruction at the end of the function. - - The float registers are ordered a little "funny" because in the 64 bit - architecture, some of them (%f16-%f47) are call-preserved. */ + instruction at the end of the function. */ #define REG_ALLOC_ORDER \ { 8, 9, 10, 11, 12, 13, 2, 3, \ @@ -1052,21 +1177,19 @@ extern enum reg_class sparc_regno_reg_class[]; 23, 24, 25, 26, 27, 28, 29, 31, \ 34, 35, 36, 37, 38, 39, /* %f2-%f7 */ \ 40, 41, 42, 43, 44, 45, 46, 47, /* %f8-%f15 */ \ - 80, 81, 82, 83, 84, 85, 86, 87, /* %f48-%f55 */ \ - 88, 89, 90, 91, 92, 93, 94, 95, /* %f56-%f63 */ \ 48, 49, 50, 51, 52, 53, 54, 55, /* %f16-%f23 */ \ 56, 57, 58, 59, 60, 61, 62, 63, /* %f24-%f31 */ \ 64, 65, 66, 67, 68, 69, 70, 71, /* %f32-%f39 */ \ 72, 73, 74, 75, 76, 77, 78, 79, /* %f40-%f47 */ \ + 80, 81, 82, 83, 84, 85, 86, 87, /* %f48-%f55 */ \ + 88, 89, 90, 91, 92, 93, 94, 95, /* %f56-%f63 */ \ 32, 33, /* %f0,%f1 */ \ 96, 97, 98, 99, 100, /* %fcc0-3, %icc */ \ 1, 4, 5, 6, 7, 0, 14, 30} /* This is the order in which to allocate registers for leaf functions. If all registers can fit in the "i" registers, - then we have the possibility of having a leaf function. - The floating point registers are ordered a little "funny" because in the - 64 bit architecture some of them (%f16-%f47) are call-preserved. */ + then we have the possibility of having a leaf function. */ #define REG_LEAF_ALLOC_ORDER \ { 2, 3, 24, 25, 26, 27, 28, 29, \ @@ -1074,12 +1197,12 @@ extern enum reg_class sparc_regno_reg_class[]; 16, 17, 18, 19, 20, 21, 22, 23, \ 34, 35, 36, 37, 38, 39, \ 40, 41, 42, 43, 44, 45, 46, 47, \ - 80, 81, 82, 83, 84, 85, 86, 87, \ - 88, 89, 90, 91, 92, 93, 94, 95, \ 48, 49, 50, 51, 52, 53, 54, 55, \ 56, 57, 58, 59, 60, 61, 62, 63, \ 64, 65, 66, 67, 68, 69, 70, 71, \ 72, 73, 74, 75, 76, 77, 78, 79, \ + 80, 81, 82, 83, 84, 85, 86, 87, \ + 88, 89, 90, 91, 92, 93, 94, 95, \ 32, 33, \ 96, 97, 98, 99, 100, \ 1, 4, 5, 6, 7, 0, 14, 30, 31} @@ -1138,17 +1261,27 @@ extern char leaf_reg_remap[]; C is the letter, and VALUE is a constant value. Return 1 if VALUE is in the range specified by C. - For SPARC, `I' is used for the range of constants an insn - can actually contain. + `I' is used for the range of constants an insn can actually contain. `J' is used for the range which is just zero (since that is R0). - `K' is used for constants which can be loaded with a single sethi insn. */ - -#define SMALL_INT(X) ((unsigned) (INTVAL (X) + 0x1000) < 0x2000) + `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 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 SPARC_SETHI_P(X) \ +(((unsigned HOST_WIDE_INT) (X) & ~(unsigned HOST_WIDE_INT) 0xfffffc00) == 0) #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) == 'K' ? SPARC_SETHI_P (VALUE) \ + : (C) == 'L' ? SPARC_SIMM11_P (VALUE) \ + : (C) == 'M' ? SPARC_SIMM10_P (VALUE) \ : 0) /* Similar, but for floating constants, and defining letters G and H. @@ -1232,13 +1365,15 @@ extern char leaf_reg_remap[]; /* Stack layout; function entry, exit and calling. */ /* Define the number of register that can hold parameters. - These two macros are used only in other macro definitions below. + This macro is only used in other macro definitions below and in sparc.c. MODE is the mode of the argument. !v9: All args are passed in %o0-%o5. - v9: Non-float args are passed in %o0-5 and float args are passed in - %f0-%f15. */ + v9: %o0-%o5 and %f0-%f31 are cumulatively used to pass values. + See the description in sparc.c. */ #define NPARM_REGS(MODE) \ - (TARGET_ARCH64 ? (GET_MODE_CLASS (MODE) == MODE_FLOAT ? 16 : 6) : 6) +(TARGET_ARCH64 \ + ? (GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 : 6) \ + : 6) /* Define this if pushing a word on the stack makes the stack pointer a smaller address. */ @@ -1267,16 +1402,16 @@ extern char leaf_reg_remap[]; /* Offset of first parameter from the argument pointer register value. !v9: This is 64 for the ins and locals, plus 4 for the struct-return reg even if this function isn't going to use it. - v9: This is 128 for the ins and locals, plus a reserved space of 8. */ + v9: This is 128 for the ins and locals. */ #define FIRST_PARM_OFFSET(FNDECL) \ - (TARGET_ARCH64 ? (SPARC_STACK_BIAS + 136) \ + (TARGET_ARCH64 ? (SPARC_STACK_BIAS + 16 * UNITS_PER_WORD) \ : (STRUCT_VALUE_OFFSET + UNITS_PER_WORD)) /* When a parameter is passed in a register, stack space is still allocated for it. */ -#if ! SPARC_ARCH64 -#define REG_PARM_STACK_SPACE(DECL) (NPARM_REGS (SImode) * UNITS_PER_WORD) -#endif +/* This only takes into account the int regs. + fp regs are handled elsewhere. */ +#define REG_PARM_STACK_SPACE(DECL) (6 * UNITS_PER_WORD) /* Keep the stack pointer constant throughout the function. This is both an optimization and a necessity: longjmp @@ -1366,11 +1501,12 @@ extern char leaf_reg_remap[]; #define APPLY_RESULT_SIZE 16 /* 1 if N is a possible register number for function argument passing. - On SPARC, these are the "output" registers. v9 also uses %f0-%f15. */ + On SPARC, these are the "output" registers. v9 also uses %f0-%f31. */ #define FUNCTION_ARG_REGNO_P(N) \ - (TARGET_ARCH64 ? (((N) < 14 && (N) > 7) || (N) > 31 && (N) < 48) \ - : ((N) < 14 && (N) > 7)) +(TARGET_ARCH64 \ + ? (((N) >= 8 && (N) <= 13) || ((N) >= 32 && (N) <= 63)) \ + : ((N) >= 8 && (N) <= 13)) /* Define a data type for recording info about an argument list during the scan of that argument list. This data type should @@ -1383,129 +1519,30 @@ extern char leaf_reg_remap[]; if any, which holds the structure-value-address). Thus 7 or more means all following args should go on the stack. - For v9, we record how many of each type has been passed. Different - types get passed differently. + For v9, we also need to know whether a prototype is present. */ - - Float args are passed in %f0-15, after which they go to the stack - where floats and doubles are passed 8 byte aligned and long doubles - are passed 16 byte aligned. - - All aggregates are passed by reference. The callee copies - the structure if necessary, except if stdarg/varargs and the struct - matches the ellipse in which case the caller makes a copy. - - Any non-float argument might be split between memory and reg %o5. - ??? I don't think this can ever happen now that structs are no - longer passed in regs. - - For v9 return values: - - - For all aggregates, the caller allocates space for the return value, - and passes the pointer as an implicit first argument, which is - allocated like all other arguments. - - The unimp instruction stuff for structure returns is gone. */ - -#if SPARC_ARCH64 -enum sparc_arg_class { SPARC_ARG_INT = 0, SPARC_ARG_FLOAT = 1 }; struct sparc_args { - int arg_count[2]; /* must be int! (for __builtin_args_info) */ + int words; /* number of words passed so far */ + int prototype_p; /* non-zero if a prototype is present */ + int libcall_p; /* non-zero if a library call */ }; #define CUMULATIVE_ARGS struct sparc_args -/* Return index into CUMULATIVE_ARGS. */ - -#define GET_SPARC_ARG_CLASS(MODE) \ - (GET_MODE_CLASS (MODE) == MODE_FLOAT ? SPARC_ARG_FLOAT : SPARC_ARG_INT) - -/* Round a register number up to a proper boundary for an arg of mode MODE. - This macro is only used in this file. - - The "& (0x10000 - ...)" is used to round up to the next appropriate reg. */ - -#define ROUND_REG(CUM, MODE) \ - (GET_MODE_CLASS (MODE) != MODE_FLOAT \ - ? (CUM).arg_count[(int) GET_SPARC_ARG_CLASS (MODE)] \ - : ((CUM).arg_count[(int) GET_SPARC_ARG_CLASS (MODE)] \ - + GET_MODE_UNIT_SIZE (MODE) / 4 - 1) \ - & (0x10000 - GET_MODE_UNIT_SIZE (MODE) / 4)) - -#define ROUND_ADVANCE(SIZE) \ - (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -#else /* ! SPARC_ARCH64 */ - -#define CUMULATIVE_ARGS int - -#define ROUND_REG(CUM, MODE) (CUM) - -#define ROUND_ADVANCE(SIZE) \ - ((SIZE + UNITS_PER_WORD - 1) / UNITS_PER_WORD) -#endif /* ! SPARC_ARCH64 */ - /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. - - On SPARC, the offset always starts at 0: the first parm reg is always - the same reg. */ + For a library call, FNTYPE is 0. */ -#if SPARC_ARCH64 -extern int sparc_arg_count,sparc_n_named_args; -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \ - do { \ - (CUM).arg_count[(int) SPARC_ARG_INT] = 0; \ - (CUM).arg_count[(int) SPARC_ARG_FLOAT] = 0; \ - sparc_arg_count = 0; \ - sparc_n_named_args = \ - ((FNTYPE) && TYPE_ARG_TYPES (FNTYPE) \ - ? (list_length (TYPE_ARG_TYPES (FNTYPE)) \ - + (TREE_CODE (TREE_TYPE (FNTYPE)) == RECORD_TYPE \ - || TREE_CODE (TREE_TYPE (FNTYPE)) == QUAL_UNION_TYPE\ - || TREE_CODE (TREE_TYPE (FNTYPE)) == SET_TYPE \ - || TREE_CODE (TREE_TYPE (FNTYPE)) == UNION_TYPE)) \ - /* Can't tell, treat 'em all as named. */ \ - : 10000); \ - } while (0) -#else -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) ((CUM) = 0) -#endif +extern void init_cumulative_args (); +#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \ +init_cumulative_args (& (CUM), (FNTYPE), (LIBNAME), (INDIRECT)); /* Update the data in CUM to advance over an argument of mode MODE and data type TYPE. - (TYPE is null for libcalls where that information may not be available.) */ - -#if SPARC_ARCH64 -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - do { \ - (CUM).arg_count[(int) GET_SPARC_ARG_CLASS (MODE)] = \ - ROUND_REG ((CUM), (MODE)) \ - + (GET_MODE_CLASS (MODE) == MODE_FLOAT \ - ? GET_MODE_SIZE (MODE) / 4 \ - : ROUND_ADVANCE ((MODE) == BLKmode \ - ? GET_MODE_SIZE (Pmode) \ - : GET_MODE_SIZE (MODE))); \ - sparc_arg_count++; \ - } while (0) -#else -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - ((CUM) += ((MODE) != BLKmode \ - ? ROUND_ADVANCE (GET_MODE_SIZE (MODE)) \ - : ROUND_ADVANCE (int_size_in_bytes (TYPE)))) -#endif - -/* Return boolean indicating arg of mode MODE will be passed in a reg. - This macro is only used in this file. */ + TYPE is null for libcalls where that information may not be available. */ -#if SPARC_ARCH64 -#define PASS_IN_REG_P(CUM, MODE, TYPE) \ - (ROUND_REG ((CUM), (MODE)) < NPARM_REGS (MODE) \ - && ((TYPE)==0 || ! TREE_ADDRESSABLE ((tree)(TYPE))) \ - && ((TYPE)==0 || (MODE) != BLKmode)) -#else -#define PASS_IN_REG_P(CUM, MODE, TYPE) \ - ((CUM) < NPARM_REGS (SImode) \ - && ((TYPE)==0 || ! TREE_ADDRESSABLE ((tree)(TYPE))) \ - && ((TYPE)==0 || (MODE) != BLKmode \ - || (TYPE_ALIGN (TYPE) % PARM_BOUNDARY == 0))) -#endif +extern void function_arg_advance (); +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ +function_arg_advance (& (CUM), (MODE), (TYPE), (NAMED)) /* Determine where to put an argument to a function. Value is zero to push the argument on the stack, @@ -1520,64 +1557,52 @@ extern int sparc_arg_count,sparc_n_named_args; NAMED is nonzero if this argument is a named parameter (otherwise it is an extra parameter matching an ellipsis). */ -/* On SPARC the first six args are normally in registers - and the rest are pushed. Any arg that starts within the first 6 words - is at least partially passed in a register unless its data type forbids. - For v9, the first 6 int args are passed in regs and the first N - float args are passed in regs (where N is such that %f0-15 are filled). - The rest are pushed. Any arg that starts within the first 6 words - is at least partially passed in a register unless its data type forbids. */ - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - (PASS_IN_REG_P ((CUM), (MODE), (TYPE)) \ - ? gen_rtx (REG, (MODE), \ - (BASE_PASSING_ARG_REG (MODE) + ROUND_REG ((CUM), (MODE))))\ - : 0) +extern struct rtx_def *function_arg (); +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ +function_arg (& (CUM), (MODE), (TYPE), (NAMED), 0) /* Define where a function finds its arguments. This is different from FUNCTION_ARG because of register windows. */ -#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \ - (PASS_IN_REG_P ((CUM), (MODE), (TYPE)) \ - ? gen_rtx (REG, (MODE), \ - (BASE_INCOMING_ARG_REG (MODE) + ROUND_REG ((CUM), (MODE))))\ - : 0) +#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \ +function_arg (& (CUM), (MODE), (TYPE), (NAMED), 1) /* For an arg passed partly in registers and partly in memory, this is the number of registers used. - For args passed entirely in registers or entirely in memory, zero. - Any arg that starts in the first 6 regs but won't entirely fit in them - needs partial registers on the Sparc (!v9). On v9, there are no arguments - that are passed partially in registers (??? complex values?). */ - -#if ! SPARC_ARCH64 -#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ - (PASS_IN_REG_P ((CUM), (MODE), (TYPE)) \ - && ((CUM) + ((MODE) == BLKmode \ - ? ROUND_ADVANCE (int_size_in_bytes (TYPE)) \ - : ROUND_ADVANCE (GET_MODE_SIZE (MODE))) - NPARM_REGS (SImode) > 0)\ - ? (NPARM_REGS (SImode) - (CUM)) \ - : 0) -#endif - -/* The SPARC ABI stipulates passing struct arguments (of any size) and - (!v9) quad-precision floats by invisible reference. - For Pascal, also pass arrays by reference. */ -#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ - ((TYPE && AGGREGATE_TYPE_P (TYPE)) \ - || (!TARGET_ARCH64 && MODE == TFmode)) - -/* A C expression that indicates when it is the called function's - responsibility to make copies of arguments passed by reference. - If the callee can determine that the argument won't be modified, it can - avoid the copy. */ -/* ??? We'd love to be able to use NAMED here. Unfortunately, it doesn't - include the last named argument so we keep track of the args ourselves. */ - -#if SPARC_ARCH64 -#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \ - (sparc_arg_count < sparc_n_named_args) -#endif + For args passed entirely in registers or entirely in memory, zero. */ + +extern int function_arg_partial_nregs (); +#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ +function_arg_partial_nregs (& (CUM), (MODE), (TYPE), (NAMED)) + +/* A C expression that indicates when an argument must be passed by reference. + If nonzero for an argument, a copy of that argument is made in memory and a + pointer to the argument is passed instead of the argument itself. + The pointer is passed in whatever way is appropriate for passing a pointer + to that type. */ + +extern int function_arg_pass_by_reference (); +#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ +function_arg_pass_by_reference (& (CUM), (MODE), (TYPE), (NAMED)) + +/* If defined, a C expression which determines whether, and in which direction, + to pad out an argument with extra space. The value should be of type + `enum direction': either `upward' to pad above the argument, + `downward' to pad below, or `none' to inhibit padding. */ +extern enum direction function_arg_padding (); +#define FUNCTION_ARG_PADDING(MODE, TYPE) \ +function_arg_padding ((MODE), (TYPE)) + +/* If defined, a C expression that gives the alignment boundary, in bits, + of an argument with the specified mode and type. If it is not defined, + PARM_BOUNDARY is used for all arguments. + For sparc64, objects requiring 16 byte alignment are passed that way. */ + +#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ +((TARGET_ARCH64 \ + && (GET_MODE_ALIGNMENT (MODE) == 128 \ + || ((TYPE) && TYPE_ALIGN (TYPE) == 128))) \ + ? 128 : PARM_BOUNDARY) /* Initialize data used by insn expanders. This is called from init_emit, once for each function, before code is generated. @@ -1586,11 +1611,9 @@ extern int sparc_arg_count,sparc_n_named_args; space at some point. ??? Use assign_stack_temp? */ -extern void sparc64_init_expanders (); +extern void sparc_init_expanders (); extern struct rtx_def *sparc64_fpconv_stack_temp (); -#if SPARC_ARCH64 -#define INIT_EXPANDERS sparc64_init_expanders () -#endif +#define INIT_EXPANDERS sparc_init_expanders () /* Define the information needed to generate branch and scc insns. This is stored from the compare operation. Note that we can't use "rtx" here @@ -1646,22 +1669,29 @@ extern int leaf_function; : output_function_prologue (FILE, SIZE, leaf_function)) /* 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)); \ - 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)); \ + 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); \ + 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. @@ -1754,20 +1784,12 @@ do \ 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); \ + 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); \ + 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; \ } \ } \ @@ -1845,21 +1867,13 @@ do \ 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); \ + 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\ + 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; \ } \ } \ @@ -2038,6 +2052,10 @@ extern union tree_node *current_function_decl; #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) /* Output assembler code for a block containing the constant parts of a trampoline, leaving space for the variable parts. */ @@ -2059,6 +2077,7 @@ extern union tree_node *current_function_decl; nop .xword context .xword function */ +/* ??? Stack is execute-protected in v9. */ #define TRAMPOLINE_TEMPLATE(FILE) \ do { \ @@ -2103,9 +2122,24 @@ void sparc64_initialize_trampoline (); /* Generate necessary RTL for __builtin_saveregs(). ARGLIST is the argument list; see expr.c. */ + extern struct rtx_def *sparc_builtin_saveregs (); #define EXPAND_BUILTIN_SAVEREGS(ARGLIST) sparc_builtin_saveregs (ARGLIST) +/* Define this macro if the location where a function argument is passed + depends on whether or not it is a named argument. + + This macro controls how the NAMED argument to FUNCTION_ARG + is set for varargs and stdarg functions. With this macro defined, + the NAMED argument is always true for named arguments, and false for + unnamed arguments. If this is not defined, but SETUP_INCOMING_VARARGS + is defined, then all arguments are treated as named. Otherwise, all named + arguments except the last are treated as named. + For the v9 we want NAMED to mean what it says it means. */ +/* ??? This needn't be set for v8, but I don't want to make this runtime + selectable if I don't have to. */ +#define STRICT_ARGUMENT_NAMING + /* Generate RTL to flush the register windows so as to make arbitrary frames available. */ #define SETUP_FRAME_ADDRESSES() \ @@ -2138,6 +2172,20 @@ extern struct rtx_def *sparc_builtin_saveregs (); ? gen_rtx (REG, Pmode, 31) \ : gen_rtx (MEM, Pmode, \ memory_address (Pmode, plus_constant (frame, 15 * UNITS_PER_WORD)))) + +/* Before the prologue, the return address is %o7 + 8. OK, sometimes it's + +12, but always using +8 is close enough for frame unwind purposes. + Actually, just using %o7 is close enough for unwinding, but %o7+8 + is something you can return to. */ +#define INCOMING_RETURN_ADDR_RTX \ + gen_rtx (PLUS, word_mode, gen_rtx (REG, word_mode, 15), GEN_INT (8)) + +/* The offset from the incoming value of %sp to the top of the stack frame + for the current function. On sparc64, we have to account for the stack + bias if present. */ +#define INCOMING_FRAME_SP_OFFSET SPARC_STACK_BIAS + +#define DOESNT_NEED_UNWINDER (! TARGET_FLAT) /* Addressing modes, and classification of registers for them. */ @@ -2400,12 +2448,12 @@ extern struct rtx_def *legitimize_pic_address (); #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) /* If we are referencing a function make the SYMBOL_REF special. - In the Medium/Anywhere code model, %g4 points to the data segment so we - must not add it to function addresses. */ + In the Embedded Medium/Anywhere code model, %g4 points to the data segment + so we must not add it to function addresses. */ #define ENCODE_SECTION_INFO(DECL) \ do { \ - if (TARGET_MEDANY && TREE_CODE (DECL) == FUNCTION_DECL) \ + if (TARGET_CM_EMBMEDANY && TREE_CODE (DECL) == FUNCTION_DECL) \ SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \ } while (0) @@ -2629,8 +2677,7 @@ extern struct rtx_def *legitimize_pic_address (); return 8; /* Compute the cost of an address. For the sparc, all valid addresses are - the same cost. - ??? Is this true for v9? */ + the same cost. */ #define ADDRESS_COST(RTX) 1 @@ -2650,7 +2697,7 @@ extern struct rtx_def *legitimize_pic_address (); #define RTX_COSTS(X,CODE,OUTER_CODE) \ case MULT: \ - return (TARGET_V8 || TARGET_SPARCLITE || TARGET_V9) \ + return (TARGET_V8 || TARGET_SPARCLITE) \ ? COSTS_N_INSNS (5) : COSTS_N_INSNS (25); \ case DIV: \ case UDIV: \ @@ -2680,6 +2727,12 @@ extern struct rtx_def *legitimize_pic_address (); #define ASM_FILE_START(file) +/* A C string constant describing how to begin a comment in the target + assembler language. The compiler assumes that the comment will end at + the end of the line. */ + +#define ASM_COMMENT_START "!" + /* Output to assembler file text saying following lines may contain character constants, extra white space, comments, etc. */ @@ -2731,13 +2784,19 @@ extern struct rtx_def *legitimize_pic_address (); #define ADDITIONAL_REGISTER_NAMES \ {{"ccr", SPARC_ICC_REG}, {"cc", SPARC_ICC_REG}} -/* How to renumber registers for dbx and gdb. */ +/* How to renumber registers for dbx and gdb. In the flat model, the frame + pointer is really %i7. */ -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) +#define DBX_REGISTER_NUMBER(REGNO) \ + (TARGET_FLAT && REGNO == FRAME_POINTER_REGNUM ? 31 : 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. @@ -2762,11 +2821,9 @@ extern struct rtx_def *legitimize_pic_address (); #define ASM_GLOBALIZE_LABEL(FILE,NAME) \ do { fputs ("\t.global ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) -/* This is how to output a reference to a user-level label named NAME. - `assemble_name' uses this. */ +/* The prefix to add to user-visible assembler symbols. */ -#define ASM_OUTPUT_LABELREF(FILE,NAME) \ - fprintf (FILE, "_%s", NAME) +#define USER_LABEL_PREFIX "_" /* This is how to output a definition of an internal numbered label where PREFIX is the class of label and NUM is the number within the class. */ @@ -2774,15 +2831,6 @@ extern struct rtx_def *legitimize_pic_address (); #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ fprintf (FILE, "%s%d:\n", PREFIX, NUM) -/* This is how to output a reference to an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. */ -/* FIXME: This should be used throughout gcc, and documented in the texinfo - files. There is no reason you should have to allocate a buffer and - `sprintf' to reference an internal label (as opposed to defining it). */ - -#define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM) \ - fprintf (FILE, "%s%d", PREFIX, NUM) - /* This is how to store into the string LABEL the symbol_ref name of an internal numbered label where PREFIX is the class of label and NUM is the number within the class. @@ -2791,34 +2839,51 @@ extern struct rtx_def *legitimize_pic_address (); #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ sprintf (LABEL, "*%s%d", PREFIX, NUM) -/* This is how to output an assembler line defining a `double' constant. */ +/* This is how to output an assembler line defining a `float' constant. + We always have to use a .long pseudo-op to do this because the native + SVR4 ELF assembler is buggy and it generates incorrect values when we + try to use the .float pseudo-op instead. */ -#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ - { \ - long t[2]; \ - REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \ - fprintf (FILE, "\t%s\t0x%lx\n\t%s\t0x%lx\n", \ - ASM_LONG, t[0], ASM_LONG, t[1]); \ - } +#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ + { \ + long t; \ + char str[30]; \ + REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ + fprintf (FILE, "\t%s\t0x%lx %s ~%s\n", ASM_LONG, t, \ + ASM_COMMENT_START, str); \ + } \ -/* This is how to output an assembler line defining a `float' constant. */ +/* This is how to output an assembler line defining a `double' constant. + We always have to use a .long pseudo-op to do this because the native + SVR4 ELF assembler is buggy and it generates incorrect values when we + try to use the .float pseudo-op instead. */ -#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ - { \ - long t; \ - REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ - fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t); \ - } \ +#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ + { \ + long t[2]; \ + char str[30]; \ + REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ + fprintf (FILE, "\t%s\t0x%lx %s ~%s\n", ASM_LONG, t[0], \ + ASM_COMMENT_START, str); \ + fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t[1]); \ + } /* This is how to output an assembler line defining a `long double' constant. */ -#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \ - { \ - long t[4]; \ - REAL_VALUE_TO_TARGET_LONG_DOUBLE ((VALUE), t); \ - fprintf (FILE, "\t%s\t0x%lx\n\t%s\t0x%lx\n\t%s\t0x%lx\n\t%s\t0x%lx\n", \ - ASM_LONG, t[0], ASM_LONG, t[1], ASM_LONG, t[2], ASM_LONG, t[3]); \ +#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \ + { \ + long t[4]; \ + char str[30]; \ + REAL_VALUE_TO_TARGET_LONG_DOUBLE ((VALUE), t); \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ + fprintf (FILE, "\t%s\t0x%lx %s ~%s\n", ASM_LONG, t[0], \ + ASM_COMMENT_START, str); \ + fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t[1]); \ + fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t[2]); \ + fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t[3]); \ } /* This is how to output an assembler line defining an `int' constant. */ @@ -2857,7 +2922,7 @@ do { \ ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \ if (Pmode == SImode) \ fprintf (FILE, "\t.word\t"); \ - else if (TARGET_MEDLOW) \ + else if (TARGET_CM_MEDLOW) \ fprintf (FILE, "\t.word\t0\n\t.word\t"); \ else \ fprintf (FILE, "\t.xword\t"); \ @@ -2874,7 +2939,7 @@ do { \ ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \ if (Pmode == SImode) \ fprintf (FILE, "\t.word\t"); \ - else if (TARGET_MEDLOW) \ + else if (TARGET_CM_MEDLOW) \ fprintf (FILE, "\t.word\t0\n\t.word\t"); \ else \ fprintf (FILE, "\t.xword\t"); \ @@ -2890,6 +2955,12 @@ do { \ if ((LOG) != 0) \ fprintf (FILE, "\t.align %d\n", (1<<(LOG))) +#define ASM_OUTPUT_ALIGN_CODE(FILE) \ + ASM_OUTPUT_ALIGN (FILE, sparc_align_jumps) + +#define ASM_OUTPUT_LOOP_ALIGN(FILE) \ + ASM_OUTPUT_ALIGN (FILE, sparc_align_loops) + #define ASM_OUTPUT_SKIP(FILE,SIZE) \ fprintf (FILE, "\t.skip %u\n", (SIZE)) @@ -2910,6 +2981,19 @@ do { \ fprintf ((FILE), ",%u,\"bss\",%u\n", \ (SIZE), ((ALIGNED) / BITS_PER_UNIT))) +/* A C statement (sans semicolon) to output to the stdio stream + FILE the assembler definition of uninitialized global DECL named + NAME whose size is SIZE bytes and alignment is ALIGN bytes. + Try to use asm_output_aligned_bss to implement this macro. */ + +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ + do { \ + fputs (".globl ", (FILE)); \ + assemble_name ((FILE), (NAME)); \ + fputs ("\n", (FILE)); \ + ASM_OUTPUT_ALIGNED_LOCAL (FILE, NAME, SIZE, ALIGN); \ + } while (0) + /* Store in OUTPUT a string (made with alloca) containing an assembler-name for a local static variable named NAME. LABELNO is an integer which is different for each call. */ @@ -2925,6 +3009,48 @@ do { \ #define ASM_OUTPUT_IDENT(FILE, NAME) \ fprintf (FILE, "\t%s\t\"%s\"\n", IDENT_ASM_OP, NAME); +/* Output code to add DELTA to the first argument, and then jump to FUNCTION. + Used for C++ multiple inheritance. */ +#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \ +do { \ + int big_delta = (DELTA) >= 4096 || (DELTA) < -4096; \ + if (big_delta) \ + fprintf (FILE, "\tset %d,%%g1\n\tadd %%o0,%%g1,%%o0\n", (DELTA)); \ + if (flag_pic) \ + { \ + if (! big_delta) \ + fprintf (FILE, "\tadd %%o0,%d,%%o0\n", DELTA); \ + fprintf (FILE, "\tsave %%sp,-112,%%sp\n"); \ + fprintf (FILE, "\tcall "); \ + assemble_name \ + (FILE, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION))); \ + fprintf (FILE, ",0\n"); \ + } \ + else if (TARGET_CM_EMBMEDANY) \ + { \ + 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 if (flag_pic) \ + fprintf (FILE, "\trestore\n"); \ + else \ + fprintf (FILE, "\tadd %%o0,%d,%%o0\n", DELTA); \ +} while (0) + /* Define the parentheses used to group arithmetic operations in assembler code. */ @@ -2941,7 +3067,7 @@ do { \ #define TARGET_CR 015 #define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \ - ((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR) == '(') + ((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR) == '(' || (CHAR) == '_') /* Print operand X (an rtx) in assembler syntax to file FILE. CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. @@ -3011,9 +3137,15 @@ do { \ } \ } +/* The number of Pmode words for the setjmp buffer. */ +#define JMP_BUF_SIZE 12 + +#define DONT_ACCESS_GBLS_AFTER_EPILOGUE (flag_pic) + /* Declare functions defined in sparc.c and used in templates. */ extern char *singlemove_string (); +extern char *doublemove_string (); extern char *output_move_double (); extern char *output_move_quad (); extern char *output_fp_move_double ();