diff options
author | meissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-11-19 17:27:18 +0000 |
---|---|---|
committer | meissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-11-19 17:27:18 +0000 |
commit | 755fa783e823d11a964be88b24eab1bf7666368c (patch) | |
tree | 331042dabc400c80ac08ddae1835f9a3e6300ccc /gcc/config | |
parent | d7175aeff80486d3421f38002845779158ce107b (diff) | |
download | gcc-755fa783e823d11a964be88b24eab1bf7666368c.tar.gz |
Add PowerPC target attribute/pragma support
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166947 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/rs6000/aix.opt | 2 | ||||
-rw-r--r-- | gcc/config/rs6000/aix64.opt | 2 | ||||
-rw-r--r-- | gcc/config/rs6000/linux64.h | 9 | ||||
-rw-r--r-- | gcc/config/rs6000/linux64.opt | 2 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000-opts.h | 144 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000-protos.h | 3 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 1689 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.h | 151 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.opt | 187 | ||||
-rw-r--r-- | gcc/config/rs6000/sysv4.h | 14 | ||||
-rw-r--r-- | gcc/config/rs6000/sysv4.opt | 12 |
11 files changed, 1539 insertions, 676 deletions
diff --git a/gcc/config/rs6000/aix.opt b/gcc/config/rs6000/aix.opt index d00017298e9..ac2b6030c22 100644 --- a/gcc/config/rs6000/aix.opt +++ b/gcc/config/rs6000/aix.opt @@ -20,5 +20,5 @@ ; <http://www.gnu.org/licenses/>. mxl-compat -Target Var(has_xl_compat_option) +Target Var(has_xl_compat_option) Save Conform more closely to IBM XLC semantics diff --git a/gcc/config/rs6000/aix64.opt b/gcc/config/rs6000/aix64.opt index 2ffcff61eb7..230bb99a7d6 100644 --- a/gcc/config/rs6000/aix64.opt +++ b/gcc/config/rs6000/aix64.opt @@ -28,5 +28,5 @@ Target Report RejectNegative Negative(maix64) InverseMask(64BIT) Compile for 32-bit pointers mpe -Target Report RejectNegative Var(internal_nothing_1) +Target Report RejectNegative Var(internal_nothing_1) Save Support message passing with the Parallel Environment diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h index b233261286c..0bc774a1f0c 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -65,10 +65,9 @@ extern int dot_symbols; #define TARGET_USES_LINUX64_OPT 1 #ifdef HAVE_LD_LARGE_TOC -extern enum rs6000_cmodel cmodel; #undef TARGET_CMODEL -#define TARGET_CMODEL cmodel -#define SET_CMODEL(opt) cmodel = opt +#define TARGET_CMODEL rs6000_current_cmodel +#define SET_CMODEL(opt) rs6000_current_cmodel = opt #else #define SET_CMODEL(opt) do {} while (0) #endif @@ -127,7 +126,7 @@ extern enum rs6000_cmodel cmodel; if ((target_flags_explicit & MASK_MINIMAL_TOC) != 0) \ { \ if (rs6000_explicit_options.cmodel \ - && cmodel != CMODEL_SMALL) \ + && rs6000_current_cmodel != CMODEL_SMALL) \ error ("-mcmodel incompatible with other toc options"); \ SET_CMODEL (CMODEL_SMALL); \ } \ @@ -135,7 +134,7 @@ extern enum rs6000_cmodel cmodel; { \ if (!rs6000_explicit_options.cmodel) \ SET_CMODEL (CMODEL_MEDIUM); \ - if (cmodel != CMODEL_SMALL) \ + if (rs6000_current_cmodel != CMODEL_SMALL) \ { \ TARGET_NO_FP_IN_TOC = 0; \ TARGET_NO_SUM_IN_TOC = 0; \ diff --git a/gcc/config/rs6000/linux64.opt b/gcc/config/rs6000/linux64.opt index 9d0e26ace33..28177f1edca 100644 --- a/gcc/config/rs6000/linux64.opt +++ b/gcc/config/rs6000/linux64.opt @@ -20,7 +20,7 @@ ; <http://www.gnu.org/licenses/>. mprofile-kernel -Target Report Var(profile_kernel) +Target Report Var(profile_kernel) Save Call mcount for profiling before a function prologue mcmodel= diff --git a/gcc/config/rs6000/rs6000-opts.h b/gcc/config/rs6000/rs6000-opts.h new file mode 100644 index 00000000000..542fea79013 --- /dev/null +++ b/gcc/config/rs6000/rs6000-opts.h @@ -0,0 +1,144 @@ +/* Definitions of target machine needed for option handling for GNU compiler, + for IBM RS/6000. + Copyright (C) 2010 + Free Software Foundation, Inc. + Contributed by Michael Meissner (meissner@linux.vnet.ibm.com) + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef RS6000_OPTS_H +#define RS6000_OPTS_H + +/* Processor type. Order must match cpu attribute in MD file. */ +enum processor_type + { + PROCESSOR_RIOS1, + PROCESSOR_RIOS2, + PROCESSOR_RS64A, + PROCESSOR_MPCCORE, + PROCESSOR_PPC403, + PROCESSOR_PPC405, + PROCESSOR_PPC440, + PROCESSOR_PPC476, + PROCESSOR_PPC601, + PROCESSOR_PPC603, + PROCESSOR_PPC604, + PROCESSOR_PPC604e, + PROCESSOR_PPC620, + PROCESSOR_PPC630, + PROCESSOR_PPC750, + PROCESSOR_PPC7400, + PROCESSOR_PPC7450, + PROCESSOR_PPC8540, + PROCESSOR_PPCE300C2, + PROCESSOR_PPCE300C3, + PROCESSOR_PPCE500MC, + PROCESSOR_PPCE500MC64, + PROCESSOR_POWER4, + PROCESSOR_POWER5, + PROCESSOR_POWER6, + PROCESSOR_POWER7, + PROCESSOR_CELL, + PROCESSOR_PPCA2, + PROCESSOR_TITAN +}; + +/* FP processor type. */ +enum fpu_type_t +{ + FPU_NONE, /* No FPU */ + FPU_SF_LITE, /* Limited Single Precision FPU */ + FPU_DF_LITE, /* Limited Double Precision FPU */ + FPU_SF_FULL, /* Full Single Precision FPU */ + FPU_DF_FULL /* Full Double Single Precision FPU */ +}; + +/* Types of costly dependences. */ +enum rs6000_dependence_cost +{ + max_dep_latency = 1000, + no_dep_costly, + all_deps_costly, + true_store_to_load_dep_costly, + store_to_load_dep_costly +}; + +/* Types of nop insertion schemes in sched target hook sched_finish. */ +enum rs6000_nop_insertion +{ + sched_finish_regroup_exact = 1000, + sched_finish_pad_groups, + sched_finish_none +}; + +/* Dispatch group termination caused by an insn. */ +enum group_termination +{ + current_group, + previous_group +}; + +/* Enumeration to give which calling sequence to use. */ +enum rs6000_abi { + ABI_NONE, + ABI_AIX, /* IBM's AIX */ + ABI_V4, /* System V.4/eabi */ + ABI_DARWIN /* Apple's Darwin (OS X kernel) */ +}; + +/* Small data support types. */ +enum rs6000_sdata_type { + SDATA_NONE, /* No small data support. */ + SDATA_DATA, /* Just put data in .sbss/.sdata, don't use relocs. */ + SDATA_SYSV, /* Use r13 to point to .sdata/.sbss. */ + SDATA_EABI /* Use r13 like above, r2 points to .sdata2/.sbss2. */ +}; + +/* Type of traceback to use. */ +enum rs6000_traceback_type { + traceback_default = 0, + traceback_none, + traceback_part, + traceback_full +}; + +/* Code model for 64-bit linux. + small: 16-bit toc offsets. + medium: 32-bit toc offsets, static data and code within 2G of TOC pointer. + large: 32-bit toc offsets, no limit on static data and code. */ +enum rs6000_cmodel { + CMODEL_SMALL, + CMODEL_MEDIUM, + CMODEL_LARGE +}; + +/* Describe which vector unit to use for a given machine mode. */ +enum rs6000_vector { + VECTOR_NONE, /* Type is not a vector or not supported */ + VECTOR_ALTIVEC, /* Use altivec for vector processing */ + VECTOR_VSX, /* Use VSX for vector processing */ + VECTOR_PAIRED, /* Use paired floating point for vectors */ + VECTOR_SPE, /* Use SPE for vector processing */ + VECTOR_OTHER /* Some other vector unit */ +}; + +#endif diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 40e8acbd7c1..ebf896fb53e 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -175,6 +175,9 @@ extern void rs6000_aix_asm_output_dwarf_table_ref (char *); extern void rs6000_pragma_longcall (struct cpp_reader *); extern void rs6000_cpu_cpp_builtins (struct cpp_reader *); +#ifdef TREE_CODE +extern bool rs6000_pragma_target_parse (tree, tree); +#endif #if TARGET_MACHO char *output_call (rtx, rtx *, int, int); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index fe3d0db904a..cdc727230a1 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -139,7 +139,6 @@ typedef struct GTY(()) machine_function /* Target cpu type */ -enum processor_type rs6000_cpu; struct rs6000_cpu_select rs6000_select[3] = { /* switch name, tune arch */ @@ -148,50 +147,19 @@ struct rs6000_cpu_select rs6000_select[3] = { (const char *)0, "-mtune=", 1, 0 }, }; -/* Always emit branch hint bits. */ -static GTY(()) bool rs6000_always_hint; - -/* Schedule instructions for group formation. */ -static GTY(()) bool rs6000_sched_groups; - -/* Align branch targets. */ -static GTY(()) bool rs6000_align_branch_targets; - -/* Non-zero to allow overriding loop alignment. */ -static int can_override_loop_align = 0; - -/* Support for -msched-costly-dep option. */ -const char *rs6000_sched_costly_dep_str; -enum rs6000_dependence_cost rs6000_sched_costly_dep; +/* String variables to hold the various options. */ +static const char *rs6000_sched_insert_nops_str; +static const char *rs6000_sched_costly_dep_str; +static const char *rs6000_recip_name; -/* Support for -minsert-sched-nops option. */ -const char *rs6000_sched_insert_nops_str; -enum rs6000_nop_insertion rs6000_sched_insert_nops; +#ifdef USING_ELFOS_H +static const char *rs6000_abi_name; +static const char *rs6000_sdata_name; +#endif /* Support targetm.vectorize.builtin_mask_for_load. */ static GTY(()) tree altivec_builtin_mask_for_load; -/* Size of long double. */ -int rs6000_long_double_type_size; - -/* IEEE quad extended precision long double. */ -int rs6000_ieeequad; - -/* Nonzero to use AltiVec ABI. */ -int rs6000_altivec_abi; - -/* Nonzero if we want SPE SIMD instructions. */ -int rs6000_spe; - -/* Nonzero if we want SPE ABI extensions. */ -int rs6000_spe_abi; - -/* Nonzero if floating point operations are done in the GPRs. */ -int rs6000_float_gprs = 0; - -/* Nonzero if we want Darwin's struct-by-value-in-regs ABI. */ -int rs6000_darwin64_abi; - /* Set to nonzero once AIX common-mode calls have been defined. */ static GTY(()) int common_mode_defined; @@ -200,37 +168,13 @@ static GTY(()) int common_mode_defined; static int rs6000_pic_labelno; #ifdef USING_ELFOS_H -/* Which abi to adhere to */ -const char *rs6000_abi_name; - -/* Semantics of the small data area */ -enum rs6000_sdata_type rs6000_sdata = SDATA_DATA; - -/* Which small data model to use */ -const char *rs6000_sdata_name = (char *)0; - /* Counter for labels which are to be placed in .fixup. */ int fixuplabelno = 0; #endif -/* Bit size of immediate TLS offsets and string from which it is decoded. */ -int rs6000_tls_size = 32; -const char *rs6000_tls_size_string; - -/* ABI enumeration available for subtarget to use. */ -enum rs6000_abi rs6000_current_abi; - /* Whether to use variant of AIX ABI for PowerPC64 Linux. */ int dot_symbols; -/* Debug flags */ -const char *rs6000_debug_name; -int rs6000_debug_stack; /* debug stack applications */ -int rs6000_debug_arg; /* debug argument handling */ -int rs6000_debug_reg; /* debug register classes */ -int rs6000_debug_addr; /* debug memory addressing */ -int rs6000_debug_cost; /* debug rtx_costs */ - /* Specify the machine mode that pointers have. After generation of rtl, the compiler makes no further distinction between pointers and any other objects of this machine mode. The type is unsigned since not all things that @@ -260,14 +204,6 @@ static enum insn_code rs6000_vector_reload[NUM_MACHINE_MODES][2]; tree rs6000_builtin_types[RS6000_BTI_MAX]; tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT]; -const char *rs6000_traceback_name; -static enum { - traceback_default = 0, - traceback_none, - traceback_part, - traceback_full -} rs6000_traceback; - /* Flag to say the TOC is initialized */ int toc_initialized; char toc_label_name[10]; @@ -282,13 +218,6 @@ static GTY(()) section *read_only_private_data_section; static GTY(()) section *sdata2_section; static GTY(()) section *toc_section; -/* Control alignment for fields within structures. */ -/* String from -malign-XXXXX. */ -int rs6000_alignment_flags; - -/* Code model for 64-bit linux. */ -enum rs6000_cmodel cmodel; - /* True for any options that were explicitly set. */ static struct { bool aix_struct_ret; /* True if -maix-struct-ret was used. */ @@ -358,9 +287,6 @@ enum rs6000_recip_mask { RECIP_LOW_PRECISION = (RECIP_ALL & ~(RECIP_DF_RSQRT | RECIP_V2DF_RSQRT)) }; -static unsigned int rs6000_recip_control; -static const char *rs6000_recip_name; - /* -mrecip options. */ static struct { @@ -1145,7 +1071,6 @@ static void rs6000_option_init_struct (struct gcc_options *); static void rs6000_option_default_params (void); static bool rs6000_handle_option (size_t, const char *, int); static int rs6000_loop_align_max_skip (rtx); -static void rs6000_parse_tls_size_option (void); static void rs6000_parse_yes_no_option (const char *, const char *, int *); static int first_altivec_reg_to_save (void); static unsigned int compute_vrsave_mask (void); @@ -1302,6 +1227,15 @@ struct GTY(()) builtin_hash_struct }; static GTY ((param_is (struct builtin_hash_struct))) htab_t builtin_hash_table; + +static bool rs6000_valid_attribute_p (tree, tree, tree, int); +static void rs6000_function_specific_save (struct cl_target_option *); +static void rs6000_function_specific_restore (struct cl_target_option *); +static void rs6000_function_specific_print (FILE *, int, + struct cl_target_option *); +static bool rs6000_can_inline_p (tree, tree); +static void rs6000_set_current_function (tree); + /* Default register names. */ char rs6000_reg_names[][8] = @@ -1702,8 +1636,213 @@ static const struct default_options rs6000_option_optimization_table[] = #undef TARGET_FUNCTION_VALUE #define TARGET_FUNCTION_VALUE rs6000_function_value +#undef TARGET_OPTION_VALID_ATTRIBUTE_P +#define TARGET_OPTION_VALID_ATTRIBUTE_P rs6000_valid_attribute_p + +#undef TARGET_OPTION_SAVE +#define TARGET_OPTION_SAVE rs6000_function_specific_save + +#undef TARGET_OPTION_RESTORE +#define TARGET_OPTION_RESTORE rs6000_function_specific_restore + +#undef TARGET_OPTION_PRINT +#define TARGET_OPTION_PRINT rs6000_function_specific_print + +#undef TARGET_CAN_INLINE_P +#define TARGET_CAN_INLINE_P rs6000_can_inline_p + +#undef TARGET_SET_CURRENT_FUNCTION +#define TARGET_SET_CURRENT_FUNCTION rs6000_set_current_function + struct gcc_target targetm = TARGET_INITIALIZER; + +/* Simplifications for entries below. */ + +enum { + POWERPC_BASE_MASK = MASK_POWERPC | MASK_NEW_MNEMONICS, + POWERPC_7400_MASK = POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_ALTIVEC +}; + +/* Some OSs don't support saving the high part of 64-bit registers on context + switch. Other OSs don't support saving Altivec registers. On those OSs, we + don't touch the MASK_POWERPC64 or MASK_ALTIVEC settings; if the user wants + either, the user must explicitly specify them and we won't interfere with + the user's specification. */ + +enum { + POWER_MASKS = MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING, + POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT | MASK_STRICT_ALIGN + | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC + | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW + | MASK_DLMZB | MASK_CMPB | MASK_MFPGPR | MASK_DFP + | MASK_POPCNTD | MASK_VSX | MASK_ISEL | MASK_NO_UPDATE + | MASK_RECIP_PRECISION) +}; + +/* Masks for instructions set at various powerpc ISAs. */ +enum { + ISA_2_1_MASKS = MASK_MFCRF, + ISA_2_2_MASKS = (ISA_2_1_MASKS | MASK_POPCNTB), + ISA_2_4_MASKS = (ISA_2_2_MASKS | MASK_FPRND), + + /* For ISA 2.05, do not add MFPGPR, since it isn't in ISA 2.06, and don't add + ALTIVEC, since in general it isn't a win on power6. In ISA 2.04, fsel, + fre, fsqrt, etc. were no longer documented as optional. Group masks by + server and embedded. */ + ISA_2_5_MASKS_EMBEDDED = (ISA_2_2_MASKS | MASK_CMPB | MASK_RECIP_PRECISION + | MASK_PPC_GFXOPT | MASK_PPC_GPOPT), + ISA_2_5_MASKS_SERVER = (ISA_2_5_MASKS_EMBEDDED | MASK_DFP), + + /* For ISA 2.06, don't add ISEL, since in general it isn't a win, but + altivec is a win so enable it. */ + ISA_2_6_MASKS_EMBEDDED = (ISA_2_5_MASKS_EMBEDDED | MASK_POPCNTD), + ISA_2_6_MASKS_SERVER = (ISA_2_5_MASKS_SERVER | MASK_POPCNTD | MASK_ALTIVEC + | MASK_VSX) +}; + +/* This table occasionally claims that a processor does not support a + particular feature even though it does, but the feature is slower than the + alternative. Thus, it shouldn't be relied on as a complete description of + the processor's support. + + Please keep this list in order, and don't forget to update the documentation + in invoke.texi when adding a new processor or flag. */ + +struct rs6000_ptt +{ + const char *const name; /* Canonical processor name. */ + const enum processor_type processor; /* Processor type enum value. */ + const int target_enable; /* Target flags to enable. */ +}; + +static struct rs6000_ptt const processor_target_table[] = +{ + {"401", PROCESSOR_PPC403, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, + {"403", PROCESSOR_PPC403, + POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_STRICT_ALIGN}, + {"405", PROCESSOR_PPC405, + POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB}, + {"405fp", PROCESSOR_PPC405, + POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB}, + {"440", PROCESSOR_PPC440, + POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB}, + {"440fp", PROCESSOR_PPC440, + POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB}, + {"464", PROCESSOR_PPC440, + POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB}, + {"464fp", PROCESSOR_PPC440, + POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB}, + {"476", PROCESSOR_PPC476, + POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_PPC_GFXOPT | MASK_MFCRF + | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_MULHW | MASK_DLMZB}, + {"476fp", PROCESSOR_PPC476, + POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB + | MASK_FPRND | MASK_CMPB | MASK_MULHW | MASK_DLMZB}, + {"505", PROCESSOR_MPCCORE, POWERPC_BASE_MASK}, + {"601", PROCESSOR_PPC601, + MASK_POWER | POWERPC_BASE_MASK | MASK_MULTIPLE | MASK_STRING}, + {"602", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, + {"603", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, + {"603e", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, + {"604", PROCESSOR_PPC604, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, + {"604e", PROCESSOR_PPC604e, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, + {"620", PROCESSOR_PPC620, + POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}, + {"630", PROCESSOR_PPC630, + POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}, + {"740", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, + {"7400", PROCESSOR_PPC7400, POWERPC_7400_MASK}, + {"7450", PROCESSOR_PPC7450, POWERPC_7400_MASK}, + {"750", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, + {"801", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, + {"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, + {"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, + {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN + | MASK_ISEL}, + /* 8548 has a dummy entry for now. */ + {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN + | MASK_ISEL}, + {"a2", PROCESSOR_PPCA2, + POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_POPCNTB + | MASK_CMPB | MASK_NO_UPDATE }, + {"e300c2", PROCESSOR_PPCE300C2, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, + {"e300c3", PROCESSOR_PPCE300C3, POWERPC_BASE_MASK}, + {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT + | MASK_ISEL}, + {"e500mc64", PROCESSOR_PPCE500MC64, POWERPC_BASE_MASK | MASK_POWERPC64 + | MASK_PPC_GFXOPT | MASK_ISEL}, + {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, + {"970", PROCESSOR_POWER4, + POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64}, + {"cell", PROCESSOR_CELL, + POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64}, + {"common", PROCESSOR_COMMON, MASK_NEW_MNEMONICS}, + {"ec603e", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, + {"G3", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, + {"G4", PROCESSOR_PPC7450, POWERPC_7400_MASK}, + {"G5", PROCESSOR_POWER4, + POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64}, + {"titan", PROCESSOR_TITAN, + POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB}, + {"power", PROCESSOR_POWER, MASK_POWER | MASK_MULTIPLE | MASK_STRING}, + {"power2", PROCESSOR_POWER, + MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING}, + {"power3", PROCESSOR_PPC630, + POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}, + {"power4", PROCESSOR_POWER4, + POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT + | MASK_MFCRF}, + {"power5", PROCESSOR_POWER5, + POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT + | MASK_MFCRF | MASK_POPCNTB}, + {"power5+", PROCESSOR_POWER5, + POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT + | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND}, + {"power6", PROCESSOR_POWER6, + POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT + | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP + | MASK_RECIP_PRECISION}, + {"power6x", PROCESSOR_POWER6, + POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT + | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP + | MASK_MFPGPR | MASK_RECIP_PRECISION}, + {"power7", PROCESSOR_POWER7, /* Don't add MASK_ISEL by default */ + POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF + | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD + | MASK_VSX | MASK_RECIP_PRECISION}, + {"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK}, + {"powerpc64", PROCESSOR_POWERPC64, + POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}, + {"rios", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING}, + {"rios1", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING}, + {"rios2", PROCESSOR_RIOS2, + MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING}, + {"rsc", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING}, + {"rsc1", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING}, + {"rs64", PROCESSOR_RS64A, + POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64} +}; + +/* Look up a processor name for -mcpu=xxx and -mtune=xxx. Return -1 if the + name is invalid. */ + +static int +rs6000_cpu_name_lookup (const char *name) +{ + size_t i; + + if (name != NULL) + { + for (i = 0; i < ARRAY_SIZE (processor_target_table); i++) + if (! strcmp (name, processor_target_table[i].name)) + return (int)i; + } + + return -1; +} + + /* Return number of consecutive hard regs needed starting at reg REGNO to hold something of mode MODE. This is ordinarily the length in words of a value of mode MODE @@ -1886,16 +2025,23 @@ rs6000_debug_reg_print (int first_regno, int last_regno, const char *reg_name) } } +#define DEBUG_FMT_D "%-32s= %d\n" +#define DEBUG_FMT_S "%-32s= %s\n" + /* Print various interesting information with -mdebug=reg. */ static void rs6000_debug_reg_global (void) { + static const char *const tf[2] = { "false", "true" }; const char *nl = (const char *)0; int m; char costly_num[20]; char nop_num[20]; const char *costly_str; const char *nop_str; + const char *trace_str; + const char *abi_str; + const char *cmodel_str; /* Map enum rs6000_vector to string. */ static const char *rs6000_debug_vector_unit[] = { @@ -1975,6 +2121,14 @@ rs6000_debug_reg_global (void) fputs ("\n", stderr); } + if (rs6000_cpu_index >= 0) + fprintf (stderr, DEBUG_FMT_S, "cpu", + processor_target_table[rs6000_cpu_index].name); + + if (rs6000_tune_index >= 0) + fprintf (stderr, DEBUG_FMT_S, "tune", + processor_target_table[rs6000_tune_index].name); + switch (rs6000_sched_costly_dep) { case max_dep_latency: @@ -2003,6 +2157,8 @@ rs6000_debug_reg_global (void) break; } + fprintf (stderr, DEBUG_FMT_S, "sched_costly_dep", costly_str); + switch (rs6000_sched_insert_nops) { case sched_finish_regroup_exact: @@ -2023,21 +2179,85 @@ rs6000_debug_reg_global (void) break; } - fprintf (stderr, - "always_hint = %s\n" - "align_branch_targets = %s\n" - "sched_restricted_insns_priority = %d\n" - "sched_costly_dep = %s\n" - "sched_insert_nops = %s\n\n", - rs6000_always_hint ? "true" : "false", - rs6000_align_branch_targets ? "true" : "false", - (int)rs6000_sched_restricted_insns_priority, - costly_str, nop_str); + fprintf (stderr, DEBUG_FMT_S, "sched_insert_nops", nop_str); + + switch (rs6000_sdata) + { + default: + case SDATA_NONE: + break; + + case SDATA_DATA: + fprintf (stderr, DEBUG_FMT_S, "sdata", "data"); + break; + + case SDATA_SYSV: + fprintf (stderr, DEBUG_FMT_S, "sdata", "sysv"); + break; + + case SDATA_EABI: + fprintf (stderr, DEBUG_FMT_S, "sdata", "eabi"); + break; + + } + + switch (rs6000_traceback) + { + case traceback_default: trace_str = "default"; break; + case traceback_none: trace_str = "none"; break; + case traceback_part: trace_str = "part"; break; + case traceback_full: trace_str = "full"; break; + default: trace_str = "unknown"; break; + } + + fprintf (stderr, DEBUG_FMT_S, "traceback", trace_str); + + switch (rs6000_current_cmodel) + { + case CMODEL_SMALL: cmodel_str = "small"; break; + case CMODEL_MEDIUM: cmodel_str = "medium"; break; + case CMODEL_LARGE: cmodel_str = "large"; break; + default: cmodel_str = "unknown"; break; + } + + fprintf (stderr, DEBUG_FMT_S, "cmodel", cmodel_str); + + switch (rs6000_current_abi) + { + case ABI_NONE: abi_str = "none"; break; + case ABI_AIX: abi_str = "aix"; break; + case ABI_V4: abi_str = "V4"; break; + case ABI_DARWIN: abi_str = "darwin"; break; + default: abi_str = "unknown"; break; + } + + fprintf (stderr, DEBUG_FMT_S, "abi", abi_str); + + if (rs6000_altivec_abi) + fprintf (stderr, DEBUG_FMT_S, "altivec_abi", "true"); + + if (rs6000_spe_abi) + fprintf (stderr, DEBUG_FMT_S, "spe_abi", "true"); + + if (rs6000_darwin64_abi) + fprintf (stderr, DEBUG_FMT_S, "darwin64_abi", "true"); + + if (rs6000_float_gprs) + fprintf (stderr, DEBUG_FMT_S, "float_gprs", "true"); + + fprintf (stderr, DEBUG_FMT_S, "always_hint", tf[!!rs6000_always_hint]); + fprintf (stderr, DEBUG_FMT_S, "align_branch", + tf[!!rs6000_align_branch_targets]); + fprintf (stderr, DEBUG_FMT_D, "tls_size", rs6000_tls_size); + fprintf (stderr, DEBUG_FMT_D, "long_double_size", + rs6000_long_double_type_size); + fprintf (stderr, DEBUG_FMT_D, "sched_restricted_insns_priority", + (int)rs6000_sched_restricted_insns_priority); } /* Initialize the various global tables that are based on register size. */ static void -rs6000_init_hard_regno_mode_ok (void) +rs6000_init_hard_regno_mode_ok (bool global_init_p) { int r, m, c; int align64; @@ -2330,40 +2550,43 @@ rs6000_init_hard_regno_mode_ok (void) } } - if (TARGET_DEBUG_REG) - rs6000_debug_reg_global (); - - if (TARGET_DEBUG_COST || TARGET_DEBUG_REG) - fprintf (stderr, - "SImode variable mult cost = %d\n" - "SImode constant mult cost = %d\n" - "SImode short constant mult cost = %d\n" - "DImode multipliciation cost = %d\n" - "SImode division cost = %d\n" - "DImode division cost = %d\n" - "Simple fp operation cost = %d\n" - "DFmode multiplication cost = %d\n" - "SFmode division cost = %d\n" - "DFmode division cost = %d\n" - "cache line size = %d\n" - "l1 cache size = %d\n" - "l2 cache size = %d\n" - "simultaneous prefetches = %d\n" - "\n", - rs6000_cost->mulsi, - rs6000_cost->mulsi_const, - rs6000_cost->mulsi_const9, - rs6000_cost->muldi, - rs6000_cost->divsi, - rs6000_cost->divdi, - rs6000_cost->fp, - rs6000_cost->dmul, - rs6000_cost->sdiv, - rs6000_cost->ddiv, - rs6000_cost->cache_line_size, - rs6000_cost->l1_cache_size, - rs6000_cost->l2_cache_size, - rs6000_cost->simultaneous_prefetches); + if (global_init_p || TARGET_DEBUG_TARGET) + { + if (TARGET_DEBUG_REG) + rs6000_debug_reg_global (); + + if (TARGET_DEBUG_COST || TARGET_DEBUG_REG) + fprintf (stderr, + "SImode variable mult cost = %d\n" + "SImode constant mult cost = %d\n" + "SImode short constant mult cost = %d\n" + "DImode multipliciation cost = %d\n" + "SImode division cost = %d\n" + "DImode division cost = %d\n" + "Simple fp operation cost = %d\n" + "DFmode multiplication cost = %d\n" + "SFmode division cost = %d\n" + "DFmode division cost = %d\n" + "cache line size = %d\n" + "l1 cache size = %d\n" + "l2 cache size = %d\n" + "simultaneous prefetches = %d\n" + "\n", + rs6000_cost->mulsi, + rs6000_cost->mulsi_const, + rs6000_cost->mulsi_const9, + rs6000_cost->muldi, + rs6000_cost->divsi, + rs6000_cost->divdi, + rs6000_cost->fp, + rs6000_cost->dmul, + rs6000_cost->sdiv, + rs6000_cost->ddiv, + rs6000_cost->cache_line_size, + rs6000_cost->l1_cache_size, + rs6000_cost->l2_cache_size, + rs6000_cost->simultaneous_prefetches); + } } #if TARGET_MACHO @@ -2420,187 +2643,26 @@ darwin_rs6000_override_options (void) #define RS6000_DEFAULT_LONG_DOUBLE_SIZE 64 #endif -/* Override command line options. Mostly we process the processor - type and sometimes adjust other TARGET_ options. */ +/* Override command line options. Mostly we process the processor type and + sometimes adjust other TARGET_ options. */ -static void -rs6000_option_override_internal (const char *default_cpu) +static bool +rs6000_option_override_internal (bool global_init_p) { - size_t i, j; - struct rs6000_cpu_select *ptr; + bool ret = true; + const char *default_cpu = OPTION_TARGET_CPU_DEFAULT; int set_masks; - - /* Simplifications for entries below. */ - - enum { - POWERPC_BASE_MASK = MASK_POWERPC | MASK_NEW_MNEMONICS, - POWERPC_7400_MASK = POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_ALTIVEC - }; - - /* This table occasionally claims that a processor does not support - a particular feature even though it does, but the feature is slower - than the alternative. Thus, it shouldn't be relied on as a - complete description of the processor's support. - - Please keep this list in order, and don't forget to update the - documentation in invoke.texi when adding a new processor or - flag. */ - static struct ptt - { - const char *const name; /* Canonical processor name. */ - const enum processor_type processor; /* Processor type enum value. */ - const int target_enable; /* Target flags to enable. */ - } const processor_target_table[] - = {{"401", PROCESSOR_PPC403, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, - {"403", PROCESSOR_PPC403, - POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_STRICT_ALIGN}, - {"405", PROCESSOR_PPC405, - POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB}, - {"405fp", PROCESSOR_PPC405, - POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB}, - {"440", PROCESSOR_PPC440, - POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB}, - {"440fp", PROCESSOR_PPC440, - POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB}, - {"464", PROCESSOR_PPC440, - POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB}, - {"464fp", PROCESSOR_PPC440, - POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB}, - {"476", PROCESSOR_PPC476, - POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_PPC_GFXOPT | MASK_MFCRF - | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_MULHW | MASK_DLMZB}, - {"476fp", PROCESSOR_PPC476, - POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB - | MASK_FPRND | MASK_CMPB | MASK_MULHW | MASK_DLMZB}, - {"505", PROCESSOR_MPCCORE, POWERPC_BASE_MASK}, - {"601", PROCESSOR_PPC601, - MASK_POWER | POWERPC_BASE_MASK | MASK_MULTIPLE | MASK_STRING}, - {"602", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, - {"603", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, - {"603e", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, - {"604", PROCESSOR_PPC604, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, - {"604e", PROCESSOR_PPC604e, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, - {"620", PROCESSOR_PPC620, - POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}, - {"630", PROCESSOR_PPC630, - POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}, - {"740", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, - {"7400", PROCESSOR_PPC7400, POWERPC_7400_MASK}, - {"7450", PROCESSOR_PPC7450, POWERPC_7400_MASK}, - {"750", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, - {"801", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, - {"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, - {"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, - {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN - | MASK_ISEL}, - /* 8548 has a dummy entry for now. */ - {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN - | MASK_ISEL}, - {"a2", PROCESSOR_PPCA2, - POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_POPCNTB - | MASK_CMPB | MASK_NO_UPDATE }, - {"e300c2", PROCESSOR_PPCE300C2, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, - {"e300c3", PROCESSOR_PPCE300C3, POWERPC_BASE_MASK}, - {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT - | MASK_ISEL}, - {"e500mc64", PROCESSOR_PPCE500MC64, POWERPC_BASE_MASK | MASK_POWERPC64 - | MASK_PPC_GFXOPT | MASK_ISEL}, - {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, - {"970", PROCESSOR_POWER4, - POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64}, - {"cell", PROCESSOR_CELL, - POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64}, - {"common", PROCESSOR_COMMON, MASK_NEW_MNEMONICS}, - {"ec603e", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, - {"G3", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, - {"G4", PROCESSOR_PPC7450, POWERPC_7400_MASK}, - {"G5", PROCESSOR_POWER4, - POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64}, - {"titan", PROCESSOR_TITAN, - POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB}, - {"power", PROCESSOR_POWER, MASK_POWER | MASK_MULTIPLE | MASK_STRING}, - {"power2", PROCESSOR_POWER, - MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING}, - {"power3", PROCESSOR_PPC630, - POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}, - {"power4", PROCESSOR_POWER4, - POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT - | MASK_MFCRF}, - {"power5", PROCESSOR_POWER5, - POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT - | MASK_MFCRF | MASK_POPCNTB}, - {"power5+", PROCESSOR_POWER5, - POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT - | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND}, - {"power6", PROCESSOR_POWER6, - POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT - | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP - | MASK_RECIP_PRECISION}, - {"power6x", PROCESSOR_POWER6, - POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT - | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP - | MASK_MFPGPR | MASK_RECIP_PRECISION}, - {"power7", PROCESSOR_POWER7, /* Don't add MASK_ISEL by default */ - POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF - | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD - | MASK_VSX | MASK_RECIP_PRECISION}, - {"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK}, - {"powerpc64", PROCESSOR_POWERPC64, - POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}, - {"rios", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING}, - {"rios1", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING}, - {"rios2", PROCESSOR_RIOS2, - MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING}, - {"rsc", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING}, - {"rsc1", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING}, - {"rs64", PROCESSOR_RS64A, - POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64} - }; - - const size_t ptt_size = ARRAY_SIZE (processor_target_table); - - /* Some OSs don't support saving the high part of 64-bit registers on - context switch. Other OSs don't support saving Altivec registers. - On those OSs, we don't touch the MASK_POWERPC64 or MASK_ALTIVEC - settings; if the user wants either, the user must explicitly specify - them and we won't interfere with the user's specification. */ - - enum { - POWER_MASKS = MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING, - POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT | MASK_STRICT_ALIGN - | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC - | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW - | MASK_DLMZB | MASK_CMPB | MASK_MFPGPR | MASK_DFP - | MASK_POPCNTD | MASK_VSX | MASK_ISEL | MASK_NO_UPDATE - | MASK_RECIP_PRECISION) - }; - - /* Masks for instructions set at various powerpc ISAs. */ - enum { - ISA_2_1_MASKS = MASK_MFCRF, - ISA_2_2_MASKS = (ISA_2_1_MASKS | MASK_POPCNTB), - ISA_2_4_MASKS = (ISA_2_2_MASKS | MASK_FPRND), - - /* For ISA 2.05, do not add MFPGPR, since it isn't in ISA 2.06, and don't - add ALTIVEC, since in general it isn't a win on power6. In ISA 2.04, - fsel, fre, fsqrt, etc. were no longer documented as optional. Group - masks by server and embedded. */ - ISA_2_5_MASKS_EMBEDDED = (ISA_2_2_MASKS | MASK_CMPB | MASK_RECIP_PRECISION - | MASK_PPC_GFXOPT | MASK_PPC_GPOPT), - ISA_2_5_MASKS_SERVER = (ISA_2_5_MASKS_EMBEDDED | MASK_DFP), - - /* For ISA 2.06, don't add ISEL, since in general it isn't a win, but - altivec is a win so enable it. */ - ISA_2_6_MASKS_EMBEDDED = (ISA_2_5_MASKS_EMBEDDED | MASK_POPCNTD), - ISA_2_6_MASKS_SERVER = (ISA_2_5_MASKS_SERVER | MASK_POPCNTD | MASK_ALTIVEC - | MASK_VSX) - }; + int cpu_index; + int tune_index; + struct cl_target_option *main_target_opt + = ((global_init_p || target_option_default_node == NULL) + ? NULL : TREE_TARGET_OPTION (target_option_default_node)); /* Numerous experiment shows that IRA based loop pressure calculation works better for RTL loop invariant motion on targets with enough (>= 32) registers. It is an expensive optimization. So it is on only for peak performance. */ - if (optimize >= 3) + if (optimize >= 3 && global_init_p) flag_ira_loop_pressure = 1; /* Set the pointer size. */ @@ -2629,34 +2691,43 @@ rs6000_option_override_internal (const char *default_cpu) set_masks &= ~target_flags_explicit; /* Identify the processor type. */ - rs6000_select[0].string = default_cpu; - rs6000_cpu = TARGET_POWERPC64 ? PROCESSOR_DEFAULT64 : PROCESSOR_DEFAULT; - - for (i = 0; i < ARRAY_SIZE (rs6000_select); i++) - { - ptr = &rs6000_select[i]; - if (ptr->string != (char *)0 && ptr->string[0] != '\0') - { - for (j = 0; j < ptt_size; j++) - if (! strcmp (ptr->string, processor_target_table[j].name)) - { - if (ptr->set_tune_p) - rs6000_cpu = processor_target_table[j].processor; + if (!default_cpu) + { + if (TARGET_POWERPC64) + default_cpu = "powerpc64"; + else if (TARGET_POWERPC) + default_cpu = "powerpc"; + } + + /* Process the -mcpu=<xxx> and -mtune=<xxx> argument. If the user changed + the cpu in a target attribute or pragma, but did not specify a tuning + option, use the cpu for the tuning option rather than the option specified + with -mtune on the command line. */ + if (rs6000_cpu_index > 0) + cpu_index = rs6000_cpu_index; + else if (main_target_opt != NULL && main_target_opt->x_rs6000_cpu_index > 0) + rs6000_cpu_index = cpu_index = main_target_opt->x_rs6000_cpu_index; + else + rs6000_cpu_index = cpu_index = rs6000_cpu_name_lookup (default_cpu); - if (ptr->set_arch_p) - { - target_flags &= ~set_masks; - target_flags |= (processor_target_table[j].target_enable - & set_masks); - } - break; - } + if (rs6000_tune_index > 0) + tune_index = rs6000_tune_index; + else + rs6000_tune_index = tune_index = cpu_index; - if (j == ptt_size) - error ("bad value (%s) for %s switch", ptr->string, ptr->name); - } + if (cpu_index >= 0) + { + target_flags &= ~set_masks; + target_flags |= (processor_target_table[cpu_index].target_enable + & set_masks); } + rs6000_cpu = ((tune_index >= 0) + ? processor_target_table[tune_index].processor + : (TARGET_POWERPC64 + ? PROCESSOR_DEFAULT64 + : PROCESSOR_DEFAULT)); + if (rs6000_cpu == PROCESSOR_PPCE300C2 || rs6000_cpu == PROCESSOR_PPCE300C3 || rs6000_cpu == PROCESSOR_PPCE500MC || rs6000_cpu == PROCESSOR_PPCE500MC64) { @@ -2767,25 +2838,8 @@ rs6000_option_override_internal (const char *default_cpu) if (rs6000_block_move_inline_limit < (TARGET_POWERPC64 ? 64 : 32)) rs6000_block_move_inline_limit = (TARGET_POWERPC64 ? 64 : 32); - /* Set debug flags */ - if (rs6000_debug_name) - { - if (! strcmp (rs6000_debug_name, "all")) - rs6000_debug_stack = rs6000_debug_arg = rs6000_debug_reg - = rs6000_debug_addr = rs6000_debug_cost = 1; - else if (! strcmp (rs6000_debug_name, "stack")) - rs6000_debug_stack = 1; - else if (! strcmp (rs6000_debug_name, "arg")) - rs6000_debug_arg = 1; - else if (! strcmp (rs6000_debug_name, "reg")) - rs6000_debug_reg = 1; - else if (! strcmp (rs6000_debug_name, "addr")) - rs6000_debug_addr = 1; - else if (! strcmp (rs6000_debug_name, "cost")) - rs6000_debug_cost = 1; - else - error ("unknown -mdebug-%s switch", rs6000_debug_name); - + if (global_init_p) + { /* If the appropriate debug option is enabled, replace the target hooks with debug versions that call the real version and then prints debugging information. */ @@ -2813,41 +2867,50 @@ rs6000_option_override_internal (const char *default_cpu) rs6000_mode_dependent_address_ptr = rs6000_debug_mode_dependent_address; } - } - if (rs6000_traceback_name) - { - if (! strncmp (rs6000_traceback_name, "full", 4)) - rs6000_traceback = traceback_full; - else if (! strncmp (rs6000_traceback_name, "part", 4)) - rs6000_traceback = traceback_part; - else if (! strncmp (rs6000_traceback_name, "no", 2)) - rs6000_traceback = traceback_none; - else - error ("unknown -mtraceback arg %qs; expecting %<full%>, %<partial%> or %<none%>", - rs6000_traceback_name); + if (rs6000_veclibabi_name) + { + if (strcmp (rs6000_veclibabi_name, "mass") == 0) + rs6000_veclib_handler = rs6000_builtin_vectorized_libmass; + else + { + error ("unknown vectorization library ABI type (%s) for " + "-mveclibabi= switch", rs6000_veclibabi_name); + ret = false; + } + } } - if (rs6000_veclibabi_name) + if (!rs6000_explicit_options.long_double) { - if (strcmp (rs6000_veclibabi_name, "mass") == 0) - rs6000_veclib_handler = rs6000_builtin_vectorized_libmass; + if (main_target_opt != NULL + && (main_target_opt->x_rs6000_long_double_type_size + != RS6000_DEFAULT_LONG_DOUBLE_SIZE)) + error ("target attribute or pragma changes long double size"); else - error ("unknown vectorization library ABI type (%s) for " - "-mveclibabi= switch", rs6000_veclibabi_name); + rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE; } - if (!rs6000_explicit_options.long_double) - rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE; - #ifndef POWERPC_LINUX if (!rs6000_explicit_options.ieee) rs6000_ieeequad = 1; #endif + /* Disable VSX and Altivec silently if the user switched cpus to power7 in a + target attribute or pragma which automatically enables both options, + unless the altivec ABI was set. This is set by default for 64-bit, but + not for 32-bit. */ + if (main_target_opt != NULL && !main_target_opt->x_rs6000_altivec_abi) + target_flags &= ~((MASK_VSX | MASK_ALTIVEC) & ~target_flags_explicit); + /* Enable Altivec ABI for AIX -maltivec. */ if (TARGET_XCOFF && (TARGET_ALTIVEC || TARGET_VSX)) - rs6000_altivec_abi = 1; + { + if (main_target_opt != NULL && !main_target_opt->x_rs6000_altivec_abi) + error ("target attribute or pragma changes AltiVec ABI"); + else + rs6000_altivec_abi = 1; + } /* The AltiVec ABI is the default for PowerPC-64 GNU/Linux. For PowerPC-32 GNU/Linux, -maltivec implies the AltiVec ABI. It can @@ -2856,7 +2919,13 @@ rs6000_option_override_internal (const char *default_cpu) { if (!rs6000_explicit_options.altivec_abi && (TARGET_64BIT || TARGET_ALTIVEC || TARGET_VSX)) - rs6000_altivec_abi = 1; + { + if (main_target_opt != NULL && + !main_target_opt->x_rs6000_altivec_abi) + error ("target attribute or pragma changes AltiVec ABI"); + else + rs6000_altivec_abi = 1; + } /* Enable VRSAVE for AltiVec ABI, unless explicitly overridden. */ if (!rs6000_explicit_options.vrsave) @@ -2869,9 +2938,14 @@ rs6000_option_override_internal (const char *default_cpu) && DEFAULT_ABI == ABI_DARWIN && TARGET_64BIT) { - rs6000_darwin64_abi = 1; - /* Default to natural alignment, for better performance. */ - rs6000_alignment_flags = MASK_ALIGN_NATURAL; + if (main_target_opt != NULL && !main_target_opt->x_rs6000_darwin64_abi) + error ("target attribute or pragma changes darwin64 ABI"); + else + { + rs6000_darwin64_abi = 1; + /* Default to natural alignment, for better performance. */ + rs6000_alignment_flags = MASK_ALIGN_NATURAL; + } } /* Place FP constants in the constant pool instead of TOC @@ -2879,9 +2953,6 @@ rs6000_option_override_internal (const char *default_cpu) if (flag_section_anchors) TARGET_NO_FP_IN_TOC = 1; - /* Handle -mtls-size option. */ - rs6000_parse_tls_size_option (); - #ifdef SUBTARGET_OVERRIDE_OPTIONS SUBTARGET_OVERRIDE_OPTIONS; #endif @@ -2905,12 +2976,20 @@ rs6000_option_override_internal (const char *default_cpu) /* For the powerpc-eabispe configuration, we set all these by default, so let's unset them if we manually set another CPU that is not the E500. */ - if (!rs6000_explicit_options.spe_abi) - rs6000_spe_abi = 0; - if (!rs6000_explicit_options.spe) - rs6000_spe = 0; - if (!rs6000_explicit_options.float_gprs) - rs6000_float_gprs = 0; + if (main_target_opt != NULL + && ((main_target_opt->x_rs6000_spe_abi != rs6000_spe_abi) + || (main_target_opt->x_rs6000_spe != rs6000_spe) + || (main_target_opt->x_rs6000_float_gprs != rs6000_float_gprs))) + error ("target attribute or pragma changes SPE ABI"); + else + { + if (!rs6000_explicit_options.spe_abi) + rs6000_spe_abi = 0; + if (!rs6000_explicit_options.spe) + rs6000_spe = 0; + if (!rs6000_explicit_options.float_gprs) + rs6000_float_gprs = 0; + } if (!(target_flags_explicit & MASK_ISEL)) target_flags &= ~MASK_ISEL; } @@ -2983,79 +3062,83 @@ rs6000_option_override_internal (const char *default_cpu) atoi (rs6000_sched_insert_nops_str)); } + if (global_init_p) + { #ifdef TARGET_REGNAMES - /* If the user desires alternate register names, copy in the - alternate names now. */ - if (TARGET_REGNAMES) - memcpy (rs6000_reg_names, alt_reg_names, sizeof (rs6000_reg_names)); + /* If the user desires alternate register names, copy in the + alternate names now. */ + if (TARGET_REGNAMES) + memcpy (rs6000_reg_names, alt_reg_names, sizeof (rs6000_reg_names)); #endif - /* Set aix_struct_return last, after the ABI is determined. - If -maix-struct-return or -msvr4-struct-return was explicitly - used, don't override with the ABI default. */ - if (!rs6000_explicit_options.aix_struct_ret) - aix_struct_return = (DEFAULT_ABI != ABI_V4 || DRAFT_V4_STRUCT_RET); + /* Set aix_struct_return last, after the ABI is determined. + If -maix-struct-return or -msvr4-struct-return was explicitly + used, don't override with the ABI default. */ + if (!rs6000_explicit_options.aix_struct_ret) + aix_struct_return = (DEFAULT_ABI != ABI_V4 || DRAFT_V4_STRUCT_RET); #if 0 - /* IBM XL compiler defaults to unsigned bitfields. */ - if (TARGET_XL_COMPAT) - flag_signed_bitfields = 0; + /* IBM XL compiler defaults to unsigned bitfields. */ + if (TARGET_XL_COMPAT) + flag_signed_bitfields = 0; #endif - if (TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD) - REAL_MODE_FORMAT (TFmode) = &ibm_extended_format; - - if (TARGET_TOC) - ASM_GENERATE_INTERNAL_LABEL (toc_label_name, "LCTOC", 1); + if (TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD) + REAL_MODE_FORMAT (TFmode) = &ibm_extended_format; - /* We can only guarantee the availability of DI pseudo-ops when - assembling for 64-bit targets. */ - if (!TARGET_64BIT) - { - targetm.asm_out.aligned_op.di = NULL; - targetm.asm_out.unaligned_op.di = NULL; - } + if (TARGET_TOC) + ASM_GENERATE_INTERNAL_LABEL (toc_label_name, "LCTOC", 1); - /* Set branch target alignment, if not optimizing for size. */ - if (!optimize_size) - { - /* Cell wants to be aligned 8byte for dual issue. Titan wants to be - aligned 8byte to avoid misprediction by the branch predictor. */ - if (rs6000_cpu == PROCESSOR_TITAN - || rs6000_cpu == PROCESSOR_CELL) + /* We can only guarantee the availability of DI pseudo-ops when + assembling for 64-bit targets. */ + if (!TARGET_64BIT) { - if (align_functions <= 0) - align_functions = 8; - if (align_jumps <= 0) - align_jumps = 8; - if (align_loops <= 0) - align_loops = 8; - } - if (rs6000_align_branch_targets) + targetm.asm_out.aligned_op.di = NULL; + targetm.asm_out.unaligned_op.di = NULL; + } + + + /* Set branch target alignment, if not optimizing for size. */ + if (!optimize_size) { - if (align_functions <= 0) - align_functions = 16; - if (align_jumps <= 0) - align_jumps = 16; - if (align_loops <= 0) + /* Cell wants to be aligned 8byte for dual issue. Titan wants to be + aligned 8byte to avoid misprediction by the branch predictor. */ + if (rs6000_cpu == PROCESSOR_TITAN + || rs6000_cpu == PROCESSOR_CELL) { - can_override_loop_align = 1; - align_loops = 16; + if (align_functions <= 0) + align_functions = 8; + if (align_jumps <= 0) + align_jumps = 8; + if (align_loops <= 0) + align_loops = 8; } + if (rs6000_align_branch_targets) + { + if (align_functions <= 0) + align_functions = 16; + if (align_jumps <= 0) + align_jumps = 16; + if (align_loops <= 0) + { + can_override_loop_align = 1; + align_loops = 16; + } + } + if (align_jumps_max_skip <= 0) + align_jumps_max_skip = 15; + if (align_loops_max_skip <= 0) + align_loops_max_skip = 15; } - if (align_jumps_max_skip <= 0) - align_jumps_max_skip = 15; - if (align_loops_max_skip <= 0) - align_loops_max_skip = 15; - } - /* Arrange to save and restore machine status around nested functions. */ - init_machine_status = rs6000_init_machine_status; + /* Arrange to save and restore machine status around nested functions. */ + init_machine_status = rs6000_init_machine_status; - /* We should always be splitting complex arguments, but we can't break - Linux and Darwin ABIs at the moment. For now, only AIX is fixed. */ - if (DEFAULT_ABI != ABI_AIX) - targetm.calls.split_complex_arg = NULL; + /* We should always be splitting complex arguments, but we can't break + Linux and Darwin ABIs at the moment. For now, only AIX is fixed. */ + if (DEFAULT_ABI != ABI_AIX) + targetm.calls.split_complex_arg = NULL; + } /* Initialize rs6000_cost with the appropriate target costs. */ if (optimize_size) @@ -3174,25 +3257,29 @@ rs6000_option_override_internal (const char *default_cpu) gcc_unreachable (); } - maybe_set_param_value (PARAM_SIMULTANEOUS_PREFETCHES, - rs6000_cost->simultaneous_prefetches, - global_options.x_param_values, - global_options_set.x_param_values); - maybe_set_param_value (PARAM_L1_CACHE_SIZE, rs6000_cost->l1_cache_size, - global_options.x_param_values, - global_options_set.x_param_values); - maybe_set_param_value (PARAM_L1_CACHE_LINE_SIZE, - rs6000_cost->cache_line_size, - global_options.x_param_values, - global_options_set.x_param_values); - maybe_set_param_value (PARAM_L2_CACHE_SIZE, rs6000_cost->l2_cache_size, - global_options.x_param_values, - global_options_set.x_param_values); - - /* If using typedef char *va_list, signal that __builtin_va_start (&ap, 0) - can be optimized to ap = __builtin_next_arg (0). */ - if (DEFAULT_ABI != ABI_V4) - targetm.expand_builtin_va_start = NULL; + if (global_init_p) + { + maybe_set_param_value (PARAM_SIMULTANEOUS_PREFETCHES, + rs6000_cost->simultaneous_prefetches, + global_options.x_param_values, + global_options_set.x_param_values); + maybe_set_param_value (PARAM_L1_CACHE_SIZE, rs6000_cost->l1_cache_size, + global_options.x_param_values, + global_options_set.x_param_values); + maybe_set_param_value (PARAM_L1_CACHE_LINE_SIZE, + rs6000_cost->cache_line_size, + global_options.x_param_values, + global_options_set.x_param_values); + maybe_set_param_value (PARAM_L2_CACHE_SIZE, rs6000_cost->l2_cache_size, + global_options.x_param_values, + global_options_set.x_param_values); + + /* If using typedef char *va_list, signal that + __builtin_va_start (&ap, 0) can be optimized to + ap = __builtin_next_arg (0). */ + if (DEFAULT_ABI != ABI_V4) + targetm.expand_builtin_va_start = NULL; + } /* Set up single/double float flags. If TARGET_HARD_FLOAT is set, but neither single or double is set, @@ -3211,6 +3298,16 @@ rs6000_option_override_internal (const char *default_cpu) rs6000_single_float = rs6000_double_float = 1; } + if (main_target_opt) + { + if (main_target_opt->x_rs6000_single_float != rs6000_single_float) + error ("target attribute or pragma changes single precision floating " + "point"); + if (main_target_opt->x_rs6000_double_float != rs6000_double_float) + error ("target attribute or pragma changes double precision floating " + "point"); + } + /* If not explicitly specified via option, decide whether to generate indexed load/store instructions. */ if (TARGET_AVOID_XFORM == -1) @@ -3254,6 +3351,7 @@ rs6000_option_override_internal (const char *default_cpu) error ("unknown option for -mrecip=%s", q); invert = false; mask = 0; + ret = false; } } @@ -3264,7 +3362,14 @@ rs6000_option_override_internal (const char *default_cpu) } } - rs6000_init_hard_regno_mode_ok (); + rs6000_init_hard_regno_mode_ok (global_init_p); + + /* Save the initial options in case the user does function specific options */ + if (global_init_p) + target_option_default_node = target_option_current_node + = build_target_option_node (); + + return ret; } /* Implement TARGET_OPTION_OVERRIDE. On the RS/6000 this is used to @@ -3273,9 +3378,10 @@ rs6000_option_override_internal (const char *default_cpu) static void rs6000_option_override (void) { - rs6000_option_override_internal (OPTION_TARGET_CPU_DEFAULT); + (void) rs6000_option_override_internal (true); } + /* Implement targetm.vectorize.builtin_mask_for_load. */ static tree rs6000_builtin_mask_for_load (void) @@ -3712,23 +3818,6 @@ rs6000_parse_yes_no_option (const char *name, const char *value, int *flag) error ("unknown -m%s= option specified: '%s'", name, value); } -/* Validate and record the size specified with the -mtls-size option. */ - -static void -rs6000_parse_tls_size_option (void) -{ - if (rs6000_tls_size_string == 0) - return; - else if (strcmp (rs6000_tls_size_string, "16") == 0) - rs6000_tls_size = 16; - else if (strcmp (rs6000_tls_size_string, "32") == 0) - rs6000_tls_size = 32; - else if (strcmp (rs6000_tls_size_string, "64") == 0) - rs6000_tls_size = 64; - else - error ("bad value %qs for -mtls-size switch", rs6000_tls_size_string); -} - /* Implement TARGET_OPTION_INIT_STRUCT. */ static void @@ -4101,6 +4190,7 @@ rs6000_handle_option (size_t code, const char *arg, int value) { enum fpu_type_t fpu_type = FPU_NONE; int isel; + char *p, *q; switch (code) { @@ -4140,11 +4230,11 @@ rs6000_handle_option (size_t code, const char *arg, int value) #if defined (HAVE_LD_LARGE_TOC) && defined (TARGET_USES_LINUX64_OPT) case OPT_mcmodel_: if (strcmp (arg, "small") == 0) - cmodel = CMODEL_SMALL; + rs6000_current_cmodel = CMODEL_SMALL; else if (strcmp (arg, "medium") == 0) - cmodel = CMODEL_MEDIUM; + rs6000_current_cmodel = CMODEL_MEDIUM; else if (strcmp (arg, "large") == 0) - cmodel = CMODEL_LARGE; + rs6000_current_cmodel = CMODEL_LARGE; else { error ("invalid option for -mcmodel: '%s'", arg); @@ -4245,7 +4335,45 @@ rs6000_handle_option (size_t code, const char *arg, int value) break; case OPT_mdebug_: - rs6000_debug_name = arg; + p = ASTRDUP (arg); + rs6000_debug = 0; + + while ((q = strtok (p, ",")) != NULL) + { + unsigned mask = 0; + bool invert; + + p = NULL; + if (*q == '!') + { + invert = true; + q++; + } + else + invert = false; + + if (! strcmp (q, "all")) + mask = MASK_DEBUG_ALL; + else if (! strcmp (q, "stack")) + mask = MASK_DEBUG_STACK; + else if (! strcmp (q, "arg")) + mask = MASK_DEBUG_ARG; + else if (! strcmp (q, "reg")) + mask = MASK_DEBUG_REG; + else if (! strcmp (q, "addr")) + mask = MASK_DEBUG_ADDR; + else if (! strcmp (q, "cost")) + mask = MASK_DEBUG_COST; + else if (! strcmp (q, "target")) + mask = MASK_DEBUG_TARGET; + else + error ("unknown -mdebug-%s switch", q); + + if (invert) + rs6000_debug &= ~mask; + else + rs6000_debug |= mask; + } break; #ifdef TARGET_USES_SYSV4_OPT @@ -4258,7 +4386,14 @@ rs6000_handle_option (size_t code, const char *arg, int value) break; case OPT_mtls_size_: - rs6000_tls_size_string = arg; + if (strcmp (arg, "16") == 0) + rs6000_tls_size = 16; + else if (strcmp (arg, "32") == 0) + rs6000_tls_size = 32; + else if (strcmp (arg, "64") == 0) + rs6000_tls_size = 64; + else + error ("bad value %qs for -mtls-size switch", arg); break; case OPT_mrelocatable: @@ -4348,14 +4483,28 @@ rs6000_handle_option (size_t code, const char *arg, int value) case OPT_mcpu_: rs6000_select[1].string = arg; + rs6000_cpu_index = rs6000_cpu_name_lookup (arg); + if (rs6000_cpu_index < 0) + error ("bad value (%s) for -mcpu", arg); break; case OPT_mtune_: rs6000_select[2].string = arg; + rs6000_tune_index = rs6000_cpu_name_lookup (arg); + if (rs6000_tune_index < 0) + error ("bad value (%s) for -mtune", arg); break; case OPT_mtraceback_: - rs6000_traceback_name = arg; + if (! strncmp (arg, "full", 4)) + rs6000_traceback = traceback_full; + else if (! strncmp (arg, "part", 4)) + rs6000_traceback = traceback_part; + else if (! strncmp (arg, "no", 2)) + rs6000_traceback = traceback_none; + else + error ("unknown -mtraceback arg %qs; expecting %<full%>, " + "%<partial%> or %<none%>", arg); break; case OPT_mfloat_gprs_: @@ -6845,6 +6994,9 @@ rs6000_conditional_register_usage (void) { int i; + if (TARGET_DEBUG_TARGET) + fprintf (stderr, "rs6000_conditional_register_usage called\n"); + /* Set MQ register fixed (already call_used) if not POWER architecture (RIOS1, RIOS2, RSC, and PPC601) so that it will not be allocated. */ @@ -27145,6 +27297,585 @@ rs6000_final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED, } +/* Mask options that we want to support inside of attribute((target)) and + #pragma GCC target operations. Note, we do not include things like + 64/32-bit, endianess, hard/soft floating point, etc. that would have + different calling sequences. */ + +struct rs6000_opt_mask { + const char *name; /* option name */ + int mask; /* mask to set */ + bool invert; /* invert sense of mask */ + bool valid_target; /* option is a target option */ +}; + +static struct rs6000_opt_mask const rs6000_opt_masks[] = +{ + { "altivec", MASK_ALTIVEC, false, true }, + { "cmpb", MASK_CMPB, false, true }, + { "dlmzb", MASK_DLMZB, false, true }, + { "fprnd", MASK_FPRND, false, true }, + { "hard-dfp", MASK_DFP, false, true }, + { "isel", MASK_ISEL, false, true }, + { "mfcrf", MASK_MFCRF, false, true }, + { "mfpgpr", MASK_MFPGPR, false, true }, + { "mulhw", MASK_MULHW, false, true }, + { "multiple", MASK_MULTIPLE, false, true }, + { "update", MASK_NO_UPDATE, true , true }, + { "popcntb", MASK_POPCNTB, false, true }, + { "popcntd", MASK_POPCNTD, false, true }, + { "powerpc-gfxopt", MASK_PPC_GFXOPT, false, true }, + { "powerpc-gpopt", MASK_PPC_GPOPT, false, true }, + { "recip-precision", MASK_RECIP_PRECISION, false, true }, + { "string", MASK_STRING, false, true }, + { "vsx", MASK_VSX, false, true }, +#ifdef MASK_64BIT +#if TARGET_AIX_OS + { "aix64", MASK_64BIT, false, false }, + { "aix32", MASK_64BIT, true, false }, +#else + { "64", MASK_64BIT, false, false }, + { "32", MASK_64BIT, true, false }, +#endif +#endif +#ifdef MASK_EABI + { "eabi", MASK_EABI, false, false }, +#endif +#ifdef MASK_LITTLE_ENDIAN + { "little", MASK_LITTLE_ENDIAN, false, false }, + { "big", MASK_LITTLE_ENDIAN, true, false }, +#endif +#ifdef MASK_RELOCATABLE + { "relocatable", MASK_RELOCATABLE, false, false }, +#endif +#ifdef MASK_STRICT_ALIGN + { "strict-align", MASK_STRICT_ALIGN, false, false }, +#endif + { "power", MASK_POWER, false, false }, + { "power2", MASK_POWER2, false, false }, + { "powerpc", MASK_POWERPC, false, false }, + { "soft-float", MASK_SOFT_FLOAT, false, false }, + { "string", MASK_STRING, false, false }, +}; + +/* Option variables that we want to support inside attribute((target)) and + #pragma GCC target operations. */ + +struct rs6000_opt_var { + const char *name; /* option name */ + size_t global_offset; /* offset of the option in global_options. */ + size_t target_offset; /* offset of the option in target optiosn. */ +}; + +static struct rs6000_opt_var const rs6000_opt_vars[] = +{ + { "friz", + offsetof (struct gcc_options, x_TARGET_FRIZ), + offsetof (struct cl_target_option, x_TARGET_FRIZ), }, + { "avoid-indexed-addresses", + offsetof (struct gcc_options, x_TARGET_AVOID_XFORM), + offsetof (struct cl_target_option, x_TARGET_AVOID_XFORM) }, + { "paired", + offsetof (struct gcc_options, x_rs6000_paired_float), + offsetof (struct cl_target_option, x_rs6000_paired_float), }, + { "longcall", + offsetof (struct gcc_options, x_rs6000_default_long_calls), + offsetof (struct cl_target_option, x_rs6000_default_long_calls), }, +}; + +/* Inner function to handle attribute((target("..."))) and #pragma GCC target + parsing. Return true if there were no errors. */ + +static bool +rs6000_inner_target_options (tree args, bool attr_p) +{ + bool ret = true; + + if (args == NULL_TREE) + ; + + else if (TREE_CODE (args) == STRING_CST) + { + char *p = ASTRDUP (TREE_STRING_POINTER (args)); + char *q; + + while ((q = strtok (p, ",")) != NULL) + { + bool error_p = false; + bool not_valid_p = false; + const char *cpu_opt = NULL; + + p = NULL; + if (strncmp (q, "cpu=", 4) == 0) + { + int cpu_index = rs6000_cpu_name_lookup (q+4); + if (cpu_index >= 0) + rs6000_cpu_index = cpu_index; + else + { + error_p = true; + cpu_opt = q+4; + } + } + else if (strncmp (q, "tune=", 5) == 0) + { + int tune_index = rs6000_cpu_name_lookup (q+5); + if (tune_index >= 0) + rs6000_tune_index = tune_index; + else + { + error_p = true; + cpu_opt = q+5; + } + } + else + { + size_t i; + bool invert = false; + char *r = q; + + error_p = true; + if (strncmp (r, "no-", 3) == 0) + { + invert = true; + r += 3; + } + + for (i = 0; i < ARRAY_SIZE (rs6000_opt_masks); i++) + if (strcmp (r, rs6000_opt_masks[i].name) == 0) + { + int mask = rs6000_opt_masks[i].mask; + + if (!rs6000_opt_masks[i].valid_target) + not_valid_p = true; + else + { + error_p = false; + target_flags_explicit |= mask; + + if (rs6000_opt_masks[i].invert) + invert = !invert; + + if (invert) + target_flags &= ~mask; + else + target_flags |= mask; + } + break; + } + + if (error_p && !not_valid_p) + { + for (i = 0; i < ARRAY_SIZE (rs6000_opt_vars); i++) + if (strcmp (r, rs6000_opt_vars[i].name) == 0) + { + size_t j = rs6000_opt_vars[i].global_offset; + ((int *) &global_options)[j] = !invert; + error_p = false; + break; + } + } + } + + if (error_p) + { + const char *eprefix, *esuffix; + + ret = false; + if (attr_p) + { + eprefix = "__attribute__((__target__("; + esuffix = ")))"; + } + else + { + eprefix = "#pragma GCC target "; + esuffix = ""; + } + + if (cpu_opt) + error ("invalid cpu \"%s\" for %s\"%s\"%s", cpu_opt, eprefix, + q, esuffix); + else if (not_valid_p) + error ("%s\"%s\"%s is not allowed", eprefix, q, esuffix); + else + error ("%s\"%s\"%s is invalid", eprefix, q, esuffix); + } + } + } + + else if (TREE_CODE (args) == TREE_LIST) + { + do + { + tree value = TREE_VALUE (args); + if (value) + { + bool ret2 = rs6000_inner_target_options (value, attr_p); + if (!ret2) + ret = false; + } + args = TREE_CHAIN (args); + } + while (args != NULL_TREE); + } + + else + gcc_unreachable (); + + return ret; +} + +/* Print out the target options as a list for -mdebug=target. */ + +static void +rs6000_debug_target_options (tree args, const char *prefix) +{ + if (args == NULL_TREE) + fprintf (stderr, "%s<NULL>", prefix); + + else if (TREE_CODE (args) == STRING_CST) + { + char *p = ASTRDUP (TREE_STRING_POINTER (args)); + char *q; + + while ((q = strtok (p, ",")) != NULL) + { + p = NULL; + fprintf (stderr, "%s\"%s\"", prefix, q); + prefix = ", "; + } + } + + else if (TREE_CODE (args) == TREE_LIST) + { + do + { + tree value = TREE_VALUE (args); + if (value) + { + rs6000_debug_target_options (value, prefix); + prefix = ", "; + } + args = TREE_CHAIN (args); + } + while (args != NULL_TREE); + } + + else + gcc_unreachable (); + + return; +} + + +/* Hook to validate attribute((target("..."))). */ + +static bool +rs6000_valid_attribute_p (tree fndecl, + tree ARG_UNUSED (name), + tree args, + int flags) +{ + struct cl_target_option cur_target; + bool ret; + tree old_optimize = build_optimization_node (); + tree new_target, new_optimize; + tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); + + gcc_assert ((fndecl != NULL_TREE) && (args != NULL_TREE)); + + if (TARGET_DEBUG_TARGET) + { + tree tname = DECL_NAME (fndecl); + fprintf (stderr, "\n==================== rs6000_valid_attribute_p:\n"); + if (tname) + fprintf (stderr, "function: %.*s\n", + (int) IDENTIFIER_LENGTH (tname), + IDENTIFIER_POINTER (tname)); + else + fprintf (stderr, "function: unknown\n"); + + fprintf (stderr, "args:"); + rs6000_debug_target_options (args, " "); + fprintf (stderr, "\n"); + + if (flags) + fprintf (stderr, "flags: 0x%x\n", flags); + + fprintf (stderr, "--------------------\n"); + } + + old_optimize = build_optimization_node (); + func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); + + /* If the function changed the optimization levels as well as setting target + options, start with the optimizations specified. */ + if (func_optimize && func_optimize != old_optimize) + cl_optimization_restore (&global_options, + TREE_OPTIMIZATION (func_optimize)); + + /* The target attributes may also change some optimization flags, so update + the optimization options if necessary. */ + cl_target_option_save (&cur_target, &global_options); + rs6000_cpu_index = rs6000_tune_index = -1; + ret = rs6000_inner_target_options (args, true); + + /* Set up any additional state. */ + if (ret) + { + ret = rs6000_option_override_internal (false); + new_target = build_target_option_node (); + } + else + new_target = NULL; + + new_optimize = build_optimization_node (); + + if (!new_target) + ret = false; + + else if (fndecl) + { + DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target; + + if (old_optimize != new_optimize) + DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize; + } + + cl_target_option_restore (&global_options, &cur_target); + + if (old_optimize != new_optimize) + cl_optimization_restore (&global_options, + TREE_OPTIMIZATION (old_optimize)); + + return ret; +} + + +/* Hook to validate the current #pragma GCC target and set the state, and + update the macros based on what was changed. If ARGS is NULL, then + POP_TARGET is used to reset the options. */ + +bool +rs6000_pragma_target_parse (tree args, tree pop_target) +{ + tree cur_tree; + bool ret; + + if (TARGET_DEBUG_TARGET) + { + fprintf (stderr, "\n==================== rs6000_pragma_target_parse\n"); + fprintf (stderr, "args:"); + rs6000_debug_target_options (args, " "); + fprintf (stderr, "\n"); + + if (pop_target) + { + fprintf (stderr, "pop_target:\n"); + debug_tree (pop_target); + } + else + fprintf (stderr, "pop_target: <NULL>\n"); + + fprintf (stderr, "--------------------\n"); + } + + if (! args) + { + ret = true; + cur_tree = ((pop_target) + ? pop_target + : target_option_default_node); + cl_target_option_restore (&global_options, + TREE_TARGET_OPTION (cur_tree)); + } + else + { + rs6000_cpu_index = rs6000_tune_index = -1; + ret = rs6000_inner_target_options (args, false); + cur_tree = build_target_option_node (); + + if (!cur_tree) + ret = false; + } + + if (cur_tree) + target_option_current_node = cur_tree; + + return ret; +} + + +/* Remember the last target of rs6000_set_current_function. */ +static GTY(()) tree rs6000_previous_fndecl; + +/* Establish appropriate back-end context for processing the function + FNDECL. The argument might be NULL to indicate processing at top + level, outside of any function scope. */ +static void +rs6000_set_current_function (tree fndecl) +{ + tree old_tree = (rs6000_previous_fndecl + ? DECL_FUNCTION_SPECIFIC_TARGET (rs6000_previous_fndecl) + : NULL_TREE); + + tree new_tree = (fndecl + ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl) + : NULL_TREE); + + if (TARGET_DEBUG_TARGET) + { + bool print_final = false; + fprintf (stderr, "\n==================== rs6000_set_current_function"); + + if (fndecl) + fprintf (stderr, ", fndecl %s (%p)", + (DECL_NAME (fndecl) + ? IDENTIFIER_POINTER (DECL_NAME (fndecl)) + : "<unknown>"), (void *)fndecl); + + if (rs6000_previous_fndecl) + fprintf (stderr, ", prev_fndecl (%p)", (void *)rs6000_previous_fndecl); + + fprintf (stderr, "\n"); + if (new_tree) + { + fprintf (stderr, "\nnew fndecl target specific options:\n"); + debug_tree (new_tree); + print_final = true; + } + + if (old_tree) + { + fprintf (stderr, "\nold fndecl target specific options:\n"); + debug_tree (old_tree); + print_final = true; + } + + if (print_final) + fprintf (stderr, "--------------------\n"); + } + + /* Only change the context if the function changes. This hook is called + several times in the course of compiling a function, and we don't want to + slow things down too much or call target_reinit when it isn't safe. */ + if (fndecl && fndecl != rs6000_previous_fndecl) + { + rs6000_previous_fndecl = fndecl; + if (old_tree == new_tree) + ; + + else if (new_tree) + { + cl_target_option_restore (&global_options, + TREE_TARGET_OPTION (new_tree)); + target_reinit (); + } + + else if (old_tree) + { + struct cl_target_option *def + = TREE_TARGET_OPTION (target_option_current_node); + + cl_target_option_restore (&global_options, def); + target_reinit (); + } + } +} + + +/* Save the current options */ + +static void +rs6000_function_specific_save (struct cl_target_option *ptr) +{ + ptr->rs6000_target_flags_explicit = target_flags_explicit; +} + +/* Restore the current options */ + +static void +rs6000_function_specific_restore (struct cl_target_option *ptr) +{ + target_flags_explicit = ptr->rs6000_target_flags_explicit; + (void) rs6000_option_override_internal (false); +} + +/* Print the current options */ + +static void +rs6000_function_specific_print (FILE *file, int indent, + struct cl_target_option *ptr) +{ + size_t i; + int flags = ptr->x_target_flags; + + /* Print the various mask options. */ + for (i = 0; i < ARRAY_SIZE (rs6000_opt_masks); i++) + if ((flags & rs6000_opt_masks[i].mask) != 0) + { + flags &= ~ rs6000_opt_masks[i].mask; + fprintf (file, "%*s-m%s%s\n", indent, "", + rs6000_opt_masks[i].invert ? "no-" : "", + rs6000_opt_masks[i].name); + } + + /* Print the various options that are variables. */ + for (i = 0; i < ARRAY_SIZE (rs6000_opt_vars); i++) + { + size_t j = rs6000_opt_vars[i].target_offset; + if (((signed char *) ptr)[j]) + fprintf (file, "%*s-m%s\n", indent, "", + rs6000_opt_vars[i].name); + } +} + + +/* Hook to determine if one function can safely inline another. */ + +static bool +rs6000_can_inline_p (tree caller, tree callee) +{ + bool ret = false; + tree caller_tree = DECL_FUNCTION_SPECIFIC_TARGET (caller); + tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (callee); + + /* If callee has no option attributes, then it is ok to inline. */ + if (!callee_tree) + ret = true; + + /* If caller has no option attributes, but callee does then it is not ok to + inline. */ + else if (!caller_tree) + ret = false; + + else + { + struct cl_target_option *caller_opts = TREE_TARGET_OPTION (caller_tree); + struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree); + + /* Callee's options should a subset of the caller's, i.e. a vsx function + can inline an altivec function but a non-vsx function can't inline a + vsx function. */ + if ((caller_opts->x_target_flags & callee_opts->x_target_flags) + == callee_opts->x_target_flags) + ret = true; + } + + if (TARGET_DEBUG_TARGET) + fprintf (stderr, "rs6000_can_inline_p:, caller %s, callee %s, %s inline\n", + (DECL_NAME (caller) + ? IDENTIFIER_POINTER (DECL_NAME (caller)) + : "<unknown>"), + (DECL_NAME (callee) + ? IDENTIFIER_POINTER (DECL_NAME (callee)) + : "<unknown>"), + (ret ? "can" : "cannot")); + + return ret; +} + /* Allocate a stack temp and fixup the address so it meets the particular memory requirements (either offetable or REG+REG addressing). */ diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 9162e4fb057..7b4a27e54a0 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -29,6 +29,10 @@ /* Note that some other tm.h files include this one and then override many of the definitions. */ +#ifndef RS6000_OPTS_H +#include "config/rs6000/rs6000-opts.h" +#endif + /* Definitions for the object file format. These are set at compile-time. */ @@ -299,16 +303,6 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #define TARGET_SECURE_PLT 0 #endif -/* Code model for 64-bit linux. - small: 16-bit toc offsets. - medium: 32-bit toc offsets, static data and code within 2G of TOC pointer. - large: 32-bit toc offsets, no limit on static data and code. */ -enum rs6000_cmodel { - CMODEL_SMALL, - CMODEL_MEDIUM, - CMODEL_LARGE -}; - #ifndef TARGET_CMODEL #define TARGET_CMODEL CMODEL_SMALL #endif @@ -338,40 +332,6 @@ enum rs6000_cmodel { #define TARGET_DEFAULT (MASK_POWER | MASK_MULTIPLE | MASK_STRING) -/* Processor type. Order must match cpu attribute in MD file. */ -enum processor_type - { - PROCESSOR_RIOS1, - PROCESSOR_RIOS2, - PROCESSOR_RS64A, - PROCESSOR_MPCCORE, - PROCESSOR_PPC403, - PROCESSOR_PPC405, - PROCESSOR_PPC440, - PROCESSOR_PPC476, - PROCESSOR_PPC601, - PROCESSOR_PPC603, - PROCESSOR_PPC604, - PROCESSOR_PPC604e, - PROCESSOR_PPC620, - PROCESSOR_PPC630, - PROCESSOR_PPC750, - PROCESSOR_PPC7400, - PROCESSOR_PPC7450, - PROCESSOR_PPC8540, - PROCESSOR_PPCE300C2, - PROCESSOR_PPCE300C3, - PROCESSOR_PPCE500MC, - PROCESSOR_PPCE500MC64, - PROCESSOR_POWER4, - PROCESSOR_POWER5, - PROCESSOR_POWER6, - PROCESSOR_POWER7, - PROCESSOR_CELL, - PROCESSOR_PPCA2, - PROCESSOR_TITAN -}; - /* FPU operations supported. Each use of TARGET_SINGLE_FLOAT or TARGET_DOUBLE_FLOAT must also test TARGET_HARD_FLOAT. */ @@ -381,8 +341,6 @@ enum processor_type #define TARGET_SIMPLE_FPU 0 #define TARGET_XILINX_FPU 0 -extern enum processor_type rs6000_cpu; - /* Recast the processor type to the cpu attribute. */ #define rs6000_cpu_attr ((enum attr_cpu)rs6000_cpu) @@ -396,47 +354,12 @@ extern enum processor_type rs6000_cpu; #define PROCESSOR_DEFAULT PROCESSOR_RIOS1 #define PROCESSOR_DEFAULT64 PROCESSOR_RS64A -/* FP processor type. */ -enum fpu_type_t -{ - FPU_NONE, /* No FPU */ - FPU_SF_LITE, /* Limited Single Precision FPU */ - FPU_DF_LITE, /* Limited Double Precision FPU */ - FPU_SF_FULL, /* Full Single Precision FPU */ - FPU_DF_FULL /* Full Double Single Precision FPU */ -}; - extern enum fpu_type_t fpu_type; /* Specify the dialect of assembler to use. New mnemonics is dialect one and the old mnemonics are dialect zero. */ #define ASSEMBLER_DIALECT (TARGET_NEW_MNEMONICS ? 1 : 0) -/* Types of costly dependences. */ -enum rs6000_dependence_cost - { - max_dep_latency = 1000, - no_dep_costly, - all_deps_costly, - true_store_to_load_dep_costly, - store_to_load_dep_costly - }; - -/* Types of nop insertion schemes in sched target hook sched_finish. */ -enum rs6000_nop_insertion - { - sched_finish_regroup_exact = 1000, - sched_finish_pad_groups, - sched_finish_none - }; - -/* Dispatch group termination caused by an insn. */ -enum group_termination - { - current_group, - previous_group - }; - /* rs6000_select[0] is reserved for the default cpu defined via --with-cpu */ struct rs6000_cpu_select { @@ -449,42 +372,25 @@ struct rs6000_cpu_select extern struct rs6000_cpu_select rs6000_select[]; /* Debug support */ -extern const char *rs6000_debug_name; /* Name for -mdebug-xxxx option */ -extern int rs6000_debug_stack; /* debug stack applications */ -extern int rs6000_debug_arg; /* debug argument handling */ -extern int rs6000_debug_reg; /* debug register handling */ -extern int rs6000_debug_addr; /* debug memory addressing */ -extern int rs6000_debug_cost; /* debug rtx_costs */ - -#define TARGET_DEBUG_STACK rs6000_debug_stack -#define TARGET_DEBUG_ARG rs6000_debug_arg -#define TARGET_DEBUG_REG rs6000_debug_reg -#define TARGET_DEBUG_ADDR rs6000_debug_addr -#define TARGET_DEBUG_COST rs6000_debug_cost - -extern const char *rs6000_traceback_name; /* Type of traceback table. */ - -/* These are separate from target_flags because we've run out of bits - there. */ -extern int rs6000_long_double_type_size; -extern int rs6000_ieeequad; -extern int rs6000_altivec_abi; -extern int rs6000_spe_abi; -extern int rs6000_spe; -extern int rs6000_float_gprs; -extern int rs6000_alignment_flags; -extern const char *rs6000_sched_insert_nops_str; -extern enum rs6000_nop_insertion rs6000_sched_insert_nops; - -/* Describe which vector unit to use for a given machine mode. */ -enum rs6000_vector { - VECTOR_NONE, /* Type is not a vector or not supported */ - VECTOR_ALTIVEC, /* Use altivec for vector processing */ - VECTOR_VSX, /* Use VSX for vector processing */ - VECTOR_PAIRED, /* Use paired floating point for vectors */ - VECTOR_SPE, /* Use SPE for vector processing */ - VECTOR_OTHER /* Some other vector unit */ -}; +#define MASK_DEBUG_STACK 0x01 /* debug stack applications */ +#define MASK_DEBUG_ARG 0x02 /* debug argument handling */ +#define MASK_DEBUG_REG 0x04 /* debug register handling */ +#define MASK_DEBUG_ADDR 0x08 /* debug memory addressing */ +#define MASK_DEBUG_COST 0x10 /* debug rtx codes */ +#define MASK_DEBUG_TARGET 0x20 /* debug target attribute/pragma */ +#define MASK_DEBUG_ALL (MASK_DEBUG_STACK \ + | MASK_DEBUG_ARG \ + | MASK_DEBUG_REG \ + | MASK_DEBUG_ADDR \ + | MASK_DEBUG_COST \ + | MASK_DEBUG_TARGET) + +#define TARGET_DEBUG_STACK (rs6000_debug & MASK_DEBUG_STACK) +#define TARGET_DEBUG_ARG (rs6000_debug & MASK_DEBUG_ARG) +#define TARGET_DEBUG_REG (rs6000_debug & MASK_DEBUG_REG) +#define TARGET_DEBUG_ADDR (rs6000_debug & MASK_DEBUG_ADDR) +#define TARGET_DEBUG_COST (rs6000_debug & MASK_DEBUG_COST) +#define TARGET_DEBUG_TARGET (rs6000_debug & MASK_DEBUG_TARGET) extern enum rs6000_vector rs6000_vector_unit[]; @@ -628,6 +534,7 @@ extern unsigned char rs6000_recip_bits[]; /* Target pragma. */ #define REGISTER_TARGET_PRAGMAS() do { \ c_register_pragma (0, "longcall", rs6000_pragma_longcall); \ + targetm.target_option.pragma_parse = rs6000_pragma_target_parse; \ targetm.resolve_overloaded_builtin = altivec_resolve_overloaded_builtin; \ } while (0) @@ -1465,16 +1372,6 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX]; /* Stack layout; function entry, exit and calling. */ -/* Enumeration to give which calling sequence to use. */ -enum rs6000_abi { - ABI_NONE, - ABI_AIX, /* IBM's AIX */ - ABI_V4, /* System V.4/eabi */ - ABI_DARWIN /* Apple's Darwin (OS X kernel) */ -}; - -extern enum rs6000_abi rs6000_current_abi; /* available for use by subtarget */ - /* Define this if pushing a word on the stack makes the stack pointer a smaller address. */ #define STACK_GROWS_DOWNWARD diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt index 063036ac85c..2c6a861f84b 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -20,6 +20,109 @@ ; along with GCC; see the file COPYING3. If not see ; <http://www.gnu.org/licenses/>. +HeaderInclude +config/rs6000/rs6000-opts.h + +;; Current processor +TargetVariable +enum processor_type rs6000_cpu = PROCESSOR_RIOS1 + +;; Always emit branch hint bits. +TargetVariable +unsigned char rs6000_always_hint + +;; Schedule instructions for group formation. +TargetVariable +unsigned char rs6000_sched_groups + +;; Align branch targets. +TargetVariable +unsigned char rs6000_align_branch_targets + +;; Support for -msched-costly-dep option. +TargetVariable +enum rs6000_dependence_cost rs6000_sched_costly_dep = no_dep_costly + +;; Support for -minsert-sched-nops option. +TargetVariable +enum rs6000_nop_insertion rs6000_sched_insert_nops = sched_finish_none + +;; Size of long double. +TargetVariable +unsigned char rs6000_long_double_type_size + +;; IEEE quad extended precision long double. +TargetVariable +unsigned char rs6000_ieeequad + +;; Nonzero to use AltiVec ABI. +TargetVariable +unsigned char rs6000_altivec_abi + +;; Nonzero if we want SPE SIMD instructions. +TargetVariable +int rs6000_spe + +;; Nonzero if we want SPE ABI extensions. +TargetVariable +unsigned char rs6000_spe_abi + +;; Nonzero if floating point operations are done in the GPRs. +TargetVariable +unsigned char rs6000_float_gprs + +;; Nonzero if we want Darwin's struct-by-value-in-regs ABI. +TargetVariable +unsigned char rs6000_darwin64_abi + +;; Non-zero to allow overriding loop alignment. +TargetVariable +unsigned char can_override_loop_align + +;; Which small data model to use (for System V targets only) +TargetVariable +enum rs6000_sdata_type rs6000_sdata = SDATA_DATA + +;; Bit size of immediate TLS offsets and string from which it is decoded. +TargetVariable +int rs6000_tls_size = 32 + +;; ABI enumeration available for subtarget to use. +TargetVariable +enum rs6000_abi rs6000_current_abi = ABI_NONE + +;; Type of traceback to use. +TargetVariable +enum rs6000_traceback_type rs6000_traceback = traceback_default + +;; Control alignment for fields within structures. +TargetVariable +unsigned char rs6000_alignment_flags + +;; Code model for 64-bit linux. +TargetVariable +enum rs6000_cmodel rs6000_current_cmodel = CMODEL_SMALL + +;; What type of reciprocal estimation instructions to generate +TargetVariable +unsigned int rs6000_recip_control + +;; -mcpu=<xxx> as an index into the processor_target_table or -1 +TargetVariable +int rs6000_cpu_index = -1 + +;; -mtune=<xxx> as an index into the processor_target_table or -1 +TargetVariable +int rs6000_tune_index = -1 + +;; Debug flags +TargetVariable +unsigned int rs6000_debug + +;; Save for target_flags_explicit +TargetSave +int rs6000_target_flags_explicit + mpower Target Report RejectNegative Mask(POWER) Use POWER instruction set @@ -45,55 +148,55 @@ Target Report Mask(POWERPC64) Use PowerPC-64 instruction set mpowerpc-gpopt -Target Report Mask(PPC_GPOPT) +Target Report Mask(PPC_GPOPT) Save Use PowerPC General Purpose group optional instructions mpowerpc-gfxopt -Target Report Mask(PPC_GFXOPT) +Target Report Mask(PPC_GFXOPT) Save Use PowerPC Graphics group optional instructions mmfcrf -Target Report Mask(MFCRF) +Target Report Mask(MFCRF) Save Use PowerPC V2.01 single field mfcr instruction mpopcntb -Target Report Mask(POPCNTB) +Target Report Mask(POPCNTB) Save Use PowerPC V2.02 popcntb instruction mfprnd -Target Report Mask(FPRND) +Target Report Mask(FPRND) Save Use PowerPC V2.02 floating point rounding instructions mcmpb -Target Report Mask(CMPB) +Target Report Mask(CMPB) Save Use PowerPC V2.05 compare bytes instruction mmfpgpr -Target Report Mask(MFPGPR) +Target Report Mask(MFPGPR) Save Use extended PowerPC V2.05 move floating point to/from GPR instructions maltivec -Target Report Mask(ALTIVEC) +Target Report Mask(ALTIVEC) Save Use AltiVec instructions mhard-dfp -Target Report Mask(DFP) +Target Report Mask(DFP) Save Use decimal floating point instructions mmulhw -Target Report Mask(MULHW) +Target Report Mask(MULHW) Save Use 4xx half-word multiply instructions mdlmzb -Target Report Mask(DLMZB) +Target Report Mask(DLMZB) Save Use 4xx string-search dlmzb instruction mmultiple -Target Report Mask(MULTIPLE) +Target Report Mask(MULTIPLE) Save Generate load/store multiple instructions mstring -Target Report Mask(STRING) +Target Report Mask(STRING) Save Generate string instructions for block moves mnew-mnemonics @@ -113,11 +216,11 @@ Target Report RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT) Use hardware floating point mpopcntd -Target Report Mask(POPCNTD) +Target Report Mask(POPCNTD) Save Use PowerPC V2.06 popcntd instruction mfriz -Target Report Var(TARGET_FRIZ) Init(-1) +Target Report Var(TARGET_FRIZ) Init(-1) Save Under -ffast-math, generate a FRIZ instruction for (double)(long long) conversions mveclibabi= @@ -125,7 +228,7 @@ Target RejectNegative Joined Var(rs6000_veclibabi_name) Vector library ABI to use mvsx -Target Report Mask(VSX) +Target Report Mask(VSX) Save Use vector/scalar (VSX) instructions mvsx-scalar-double @@ -165,7 +268,7 @@ Target Undocumented Report Var(TARGET_VECTORIZE_BUILTINS) Init(-1) ; Explicitly control whether we vectorize the builtins or not. mno-update -Target Report RejectNegative Mask(NO_UPDATE) +Target Report RejectNegative Mask(NO_UPDATE) Save Do not generate load/store with update instructions mupdate @@ -173,30 +276,30 @@ Target Report RejectNegative InverseMask(NO_UPDATE, UPDATE) Generate load/store with update instructions mavoid-indexed-addresses -Target Report Var(TARGET_AVOID_XFORM) Init(-1) +Target Report Var(TARGET_AVOID_XFORM) Init(-1) Save Avoid generation of indexed load/store instructions when possible mtls-markers -Target Report Var(tls_markers) Init(1) +Target Report Var(tls_markers) Init(1) Save Mark __tls_get_addr calls with argument info msched-epilog -Target Undocumented Var(TARGET_SCHED_PROLOG) Init(1) +Target Undocumented Var(TARGET_SCHED_PROLOG) Init(1) Save msched-prolog -Target Report Var(TARGET_SCHED_PROLOG) +Target Report Var(TARGET_SCHED_PROLOG) Save Schedule the start and end of the procedure maix-struct-return -Target Report RejectNegative Var(aix_struct_return) +Target Report RejectNegative Var(aix_struct_return) Save Return all structures in memory (AIX default) msvr4-struct-return -Target Report RejectNegative Var(aix_struct_return,0) +Target Report RejectNegative Var(aix_struct_return,0) Save Return small structures in registers (SVR4 default) mxl-compat -Target Report Var(TARGET_XL_COMPAT) +Target Report Var(TARGET_XL_COMPAT) Save Conform more closely to IBM XLC semantics mrecip @@ -208,23 +311,23 @@ Target Report RejectNegative Joined Generate software reciprocal divide and square root for better throughput. mrecip-precision -Target Report Mask(RECIP_PRECISION) +Target Report Mask(RECIP_PRECISION) Save Assume that the reciprocal estimate instructions provide more accuracy. mno-fp-in-toc -Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC) +Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC) Save Do not place floating point constants in TOC mfp-in-toc -Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC,0) +Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC,0) Save Place floating point constants in TOC mno-sum-in-toc -Target RejectNegative Var(TARGET_NO_SUM_IN_TOC) +Target RejectNegative Var(TARGET_NO_SUM_IN_TOC) Save Do not place symbol+offset constants in TOC msum-in-toc -Target RejectNegative Var(TARGET_NO_SUM_IN_TOC,0) +Target RejectNegative Var(TARGET_NO_SUM_IN_TOC,0) Save Place symbol+offset constants in TOC ; Output only one TOC entry per module. Normally linking fails if @@ -243,7 +346,7 @@ Target Report Put everything in the regular TOC mvrsave -Target Report Var(TARGET_ALTIVEC_VRSAVE) +Target Report Var(TARGET_ALTIVEC_VRSAVE) Save Generate VRSAVE instructions when generating AltiVec code mvrsave= @@ -251,11 +354,11 @@ Target RejectNegative Joined -mvrsave=yes/no Deprecated option. Use -mvrsave/-mno-vrsave instead mblock-move-inline-limit= -Target Report Var(rs6000_block_move_inline_limit) Init(0) RejectNegative Joined UInteger +Target Report Var(rs6000_block_move_inline_limit) Init(0) RejectNegative Joined UInteger Save Specify how many bytes should be moved inline before calling out to memcpy/memmove misel -Target Report Mask(ISEL) +Target Report Mask(ISEL) Save Generate isel instructions misel= @@ -267,7 +370,7 @@ Target Generate SPE SIMD instructions on E500 mpaired -Target Var(rs6000_paired_float) +Target Var(rs6000_paired_float) Save Generate PPC750CL paired-single instructions mspe= @@ -295,19 +398,19 @@ Target RejectNegative Joined -mtraceback= Select full, part, or no traceback table mlongcall -Target Report Var(rs6000_default_long_calls) +Target Report Var(rs6000_default_long_calls) Save Avoid all range limits on call instructions mgen-cell-microcode -Target Report Var(rs6000_gen_cell_microcode) Init(-1) +Target Report Var(rs6000_gen_cell_microcode) Init(-1) Save Generate Cell microcode mwarn-cell-microcode -Target Var(rs6000_warn_cell_microcode) Init(0) Warning +Target Var(rs6000_warn_cell_microcode) Init(0) Warning Save Warn when a Cell microcoded instruction is emitted mwarn-altivec-long -Target Var(rs6000_warn_altivec_long) Init(1) +Target Var(rs6000_warn_altivec_long) Init(1) Save Warn about deprecated 'vector long ...' AltiVec type usage mfloat-gprs= @@ -331,19 +434,19 @@ Target RejectNegative Joined Specify alignment of structure fields default/natural mprioritize-restricted-insns= -Target RejectNegative Joined UInteger Var(rs6000_sched_restricted_insns_priority) +Target RejectNegative Joined UInteger Var(rs6000_sched_restricted_insns_priority) Save Specify scheduling priority for dispatch slot restricted insns msingle-float -Target RejectNegative Var(rs6000_single_float) +Target RejectNegative Var(rs6000_single_float) Save Single-precision floating point unit mdouble-float -Target RejectNegative Var(rs6000_double_float) +Target RejectNegative Var(rs6000_double_float) Save Double-precision floating point unit msimple-fpu -Target RejectNegative Var(rs6000_simple_fpu) +Target RejectNegative Var(rs6000_simple_fpu) Save Floating point unit does not support divide & sqrt mfpu= @@ -351,7 +454,7 @@ Target RejectNegative Joined -mfpu= Specify FP (sp, dp, sp-lite, dp-lite) (implies -mxilinx-fpu) mxilinx-fpu -Target Var(rs6000_xilinx_fpu) +Target Var(rs6000_xilinx_fpu) Save Specify Xilinx FPU. diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h index e82a1c6d34e..d557ce1626a 100644 --- a/gcc/config/rs6000/sysv4.h +++ b/gcc/config/rs6000/sysv4.h @@ -41,16 +41,6 @@ #undef ASM_DEFAULT_SPEC #define ASM_DEFAULT_SPEC "-mppc" -/* Small data support types. */ -enum rs6000_sdata_type { - SDATA_NONE, /* No small data support. */ - SDATA_DATA, /* Just put data in .sbss/.sdata, don't use relocs. */ - SDATA_SYSV, /* Use r13 to point to .sdata/.sbss. */ - SDATA_EABI /* Use r13 like above, r2 points to .sdata2/.sbss2. */ -}; - -extern enum rs6000_sdata_type rs6000_sdata; - #define TARGET_TOC ((target_flags & MASK_64BIT) \ || ((target_flags & (MASK_RELOCATABLE \ | MASK_MINIMAL_TOC)) \ @@ -70,10 +60,6 @@ extern enum rs6000_sdata_type rs6000_sdata; #define TARGET_SECURE_PLT secure_plt #endif -extern const char *rs6000_abi_name; -extern const char *rs6000_sdata_name; -extern const char *rs6000_tls_size_string; /* For -mtls-size= */ - #define SDATA_DEFAULT_SIZE 8 /* The macro SUBTARGET_OVERRIDE_OPTIONS is provided for subtargets, to diff --git a/gcc/config/rs6000/sysv4.opt b/gcc/config/rs6000/sysv4.opt index 29f3bdf75e9..f1f987d2238 100644 --- a/gcc/config/rs6000/sysv4.opt +++ b/gcc/config/rs6000/sysv4.opt @@ -32,7 +32,7 @@ Target RejectNegative Joined Specify bit size of immediate TLS offsets mbit-align -Target Report Var(TARGET_NO_BITFIELD_TYPE) +Target Report Var(TARGET_NO_BITFIELD_TYPE) Save Align to the base type of the bit-field mstrict-align @@ -74,7 +74,7 @@ Target RejectNegative no description yet mprototype -Target Var(target_prototype) +Target Var(target_prototype) Save Assume all variable arg functions are prototyped ;; FIXME: Does nothing. @@ -87,11 +87,11 @@ Target Report Mask(EABI) Use EABI mbit-word -Target Report Var(TARGET_NO_BITFIELD_WORD) +Target Report Var(TARGET_NO_BITFIELD_WORD) Save Allow bit-fields to cross word boundaries mregnames -Target Var(rs6000_regnames) +Target Var(rs6000_regnames) Save Use alternate register names ;; This option does nothing and only exists because the compiler @@ -137,9 +137,9 @@ Target RejectNegative no description yet msecure-plt -Target Report RejectNegative Var(secure_plt, 1) +Target Report RejectNegative Var(secure_plt, 1) Save Generate code to use a non-exec PLT and GOT mbss-plt -Target Report RejectNegative Var(secure_plt, 0) +Target Report RejectNegative Var(secure_plt, 0) Save Generate code for old exec BSS PLT |