/* Subroutines used for code generation on IBM RS/6000.
Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
+ 2012
Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
#include "tm_p.h"
#include "target.h"
#include "target-def.h"
+#include "common/common-target.h"
#include "langhooks.h"
#include "reload.h"
#include "cfglayout.h"
#include "intl.h"
#include "params.h"
#include "tm-constrs.h"
+#include "opts.h"
#if TARGET_XCOFF
#include "xcoffout.h" /* get declarations of xcoff_*_section_name */
#endif
int ra_need_lr;
/* Cache lr_save_p after expansion of builtin_eh_return. */
int lr_save_state;
+ /* Whether we need to save the TOC to the reserved stack location in the
+ function prologue. */
+ bool save_toc_in_prologue;
/* Offset from virtual_stack_vars_rtx to the start of the ABI_V4
varargs save area. */
HOST_WIDE_INT varargs_save_offset;
rtx sdmode_stack_slot;
} machine_function;
-/* Target cpu type */
-
-struct rs6000_cpu_select rs6000_select[3] =
-{
- /* switch name, tune arch */
- { (const char *)0, "--with-cpu=", 1, 1 },
- { (const char *)0, "-mcpu=", 1, 1 },
- { (const char *)0, "-mtune=", 1, 0 },
-};
-
-/* 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;
-
-#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;
/* Reload functions based on the type and the vector unit. */
static enum insn_code rs6000_vector_reload[NUM_MACHINE_MODES][2];
+static int dbg_cost_ctrl;
+
/* Built in types. */
tree rs6000_builtin_types[RS6000_BTI_MAX];
tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
static GTY(()) section *sdata2_section;
static GTY(()) section *toc_section;
-/* True for any options that were explicitly set. */
-static struct {
- bool aix_struct_ret; /* True if -maix-struct-ret was used. */
- bool alignment; /* True if -malign- was used. */
- bool spe_abi; /* True if -mabi=spe/no-spe was used. */
- bool altivec_abi; /* True if -mabi=altivec/no-altivec used. */
- bool spe; /* True if -mspe= was used. */
- bool float_gprs; /* True if -mfloat-gprs= was used. */
- bool long_double; /* True if -mlong-double- was used. */
- bool ieee; /* True if -mabi=ieee/ibmlongdouble used. */
- bool vrsave; /* True if -mvrsave was used. */
- bool cmodel; /* True if -mcmodel was used. */
-} rs6000_explicit_options;
-
struct builtin_description
{
- /* mask is not const because we're going to alter it below. This
- nonsense will go away when we rewrite the -march infrastructure
- to give us more target flag bits. */
- unsigned int mask;
+ const unsigned int mask;
const enum insn_code icode;
const char *const name;
const enum rs6000_builtins code;
/* 2 argument gen function typedef. */
typedef rtx (*gen_2arg_fn_t) (rtx, rtx, rtx);
+/* Pointer to function (in rs6000-c.c) that can define or undefine target
+ macros that have changed. Languages that don't support the preprocessor
+ don't link in rs6000-c.c, so we can't call it directly. */
+void (*rs6000_target_modify_macros_ptr) (bool, int, unsigned);
+
\f
/* Target cpu costs. */
\f
/* Table that classifies rs6000 builtin functions (pure, const, etc.). */
-#undef RS6000_BUILTIN
-#undef RS6000_BUILTIN_EQUATE
-#define RS6000_BUILTIN(NAME, TYPE) TYPE,
-#define RS6000_BUILTIN_EQUATE(NAME, VALUE)
+#undef RS6000_BUILTIN_1
+#undef RS6000_BUILTIN_2
+#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_A
+#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_P
+#undef RS6000_BUILTIN_Q
+#undef RS6000_BUILTIN_S
+#undef RS6000_BUILTIN_X
+
+#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) \
+ { NAME, ICODE, MASK, ATTR },
+
+#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) \
+ { NAME, ICODE, MASK, ATTR },
+
+#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) \
+ { NAME, ICODE, MASK, ATTR },
+
+#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) \
+ { NAME, ICODE, MASK, ATTR },
-static const enum rs6000_btc builtin_classify[(int)RS6000_BUILTIN_COUNT] =
+#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) \
+ { NAME, ICODE, MASK, ATTR },
+
+#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) \
+ { NAME, ICODE, MASK, ATTR },
+
+#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) \
+ { NAME, ICODE, MASK, ATTR },
+
+#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE) \
+ { NAME, ICODE, MASK, ATTR },
+
+#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE) \
+ { NAME, ICODE, MASK, ATTR },
+
+#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) \
+ { NAME, ICODE, MASK, ATTR },
+
+struct rs6000_builtin_info_type {
+ const char *name;
+ const enum insn_code icode;
+ const unsigned mask;
+ const unsigned attr;
+};
+
+static const struct rs6000_builtin_info_type rs6000_builtin_info[] =
{
#include "rs6000-builtin.def"
};
-#undef RS6000_BUILTIN
-#undef RS6000_BUILTIN_EQUATE
+#undef RS6000_BUILTIN_1
+#undef RS6000_BUILTIN_2
+#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_A
+#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_P
+#undef RS6000_BUILTIN_Q
+#undef RS6000_BUILTIN_S
+#undef RS6000_BUILTIN_X
/* Support for -mveclibabi=<xxx> to control which vector library to use. */
static tree (*rs6000_veclib_handler) (tree, tree, tree);
static bool rs6000_debug_legitimate_address_p (enum machine_mode, rtx, bool);
static rtx rs6000_generate_compare (rtx, enum machine_mode);
static void rs6000_emit_stack_tie (void);
-static void rs6000_frame_related (rtx, rtx, HOST_WIDE_INT, rtx, rtx);
static bool spe_func_has_64bit_regs_p (void);
-static void emit_frame_save (rtx, rtx, enum machine_mode, unsigned int,
- int, HOST_WIDE_INT);
static rtx gen_frame_mem_offset (enum machine_mode, rtx, int);
static unsigned rs6000_hash_constant (rtx);
static unsigned toc_hash_function (const void *);
static struct machine_function * rs6000_init_machine_status (void);
static bool rs6000_assemble_integer (rtx, unsigned int, int);
static bool no_global_regs_above (int, bool);
-#ifdef HAVE_GAS_HIDDEN
+#if defined (HAVE_GAS_HIDDEN) && !TARGET_MACHO
static void rs6000_assemble_visibility (tree, int);
#endif
static int rs6000_ra_ever_killed (void);
static void rs6000_set_default_type_attributes (tree);
static rtx rs6000_savres_routine_sym (rs6000_stack_t *, bool, bool, bool);
static rtx rs6000_emit_stack_reset (rs6000_stack_t *, rtx, rtx, int, bool);
-static rtx rs6000_make_savres_rtx (rs6000_stack_t *, rtx, int,
- enum machine_mode, bool, bool, bool);
static bool rs6000_reg_live_or_pic_offset_p (int);
static tree rs6000_builtin_vectorized_libmass (tree, tree, tree);
static tree rs6000_builtin_vectorized_function (tree, tree, tree);
static int rs6000_register_move_cost (enum machine_mode,
reg_class_t, reg_class_t);
static int rs6000_memory_move_cost (enum machine_mode, reg_class_t, bool);
-static bool rs6000_rtx_costs (rtx, int, int, int *, bool);
-static bool rs6000_debug_rtx_costs (rtx, int, int, int *, bool);
+static bool rs6000_rtx_costs (rtx, int, int, int, int *, bool);
+static bool rs6000_debug_rtx_costs (rtx, int, int, int, int *, bool);
static int rs6000_debug_address_cost (rtx, bool);
static int rs6000_adjust_cost (rtx, rtx, rtx, int);
static int rs6000_debug_adjust_cost (rtx, rtx, rtx, int);
static tree rs6000_builtin_mask_for_load (void);
static tree rs6000_builtin_mul_widen_even (tree);
static tree rs6000_builtin_mul_widen_odd (tree);
-static tree rs6000_builtin_conversion (unsigned int, tree, tree);
-static tree rs6000_builtin_vec_perm (tree, tree *);
static bool rs6000_builtin_support_vector_misalignment (enum
machine_mode,
const_tree,
tree, int);
static enum machine_mode rs6000_preferred_simd_mode (enum machine_mode);
-static void def_builtin (int, const char *, tree, int);
+static void def_builtin (const char *, tree, enum rs6000_builtins);
static bool rs6000_vector_alignment_reachable (const_tree, bool);
static void rs6000_init_builtins (void);
static tree rs6000_builtin_decl (unsigned, bool);
static rtx paired_expand_stv_builtin (enum insn_code, tree);
static rtx paired_expand_predicate_builtin (enum insn_code, tree, rtx);
-static void enable_mask_for_builtins (struct builtin_description *, int,
- enum rs6000_builtins,
- enum rs6000_builtins);
static void spe_init_builtins (void);
static rtx spe_expand_builtin (tree, rtx, bool *);
static rtx spe_expand_stv_builtin (enum insn_code, tree);
static rtx altivec_expand_vec_ext_builtin (tree, rtx);
static int get_element_number (tree, tree);
static void rs6000_option_override (void);
-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_yes_no_option (const char *, const char *, int *);
static int first_altivec_reg_to_save (void);
static unsigned int compute_vrsave_mask (void);
static void compute_save_world_info (rs6000_stack_t *info_ptr);
static rtx rs6000_legitimize_tls_address (rtx, enum tls_model);
static void rs6000_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
static rtx rs6000_delegitimize_address (rtx);
+static bool rs6000_const_not_ok_for_debug_p (rtx);
static rtx rs6000_tls_get_addr (void);
static rtx rs6000_got_sym (void);
static int rs6000_tls_symbol_ref_1 (rtx *, void *);
rtx[], int *);
static rtx rs6000_darwin64_record_arg (CUMULATIVE_ARGS *, const_tree, bool, bool);
static rtx rs6000_mixed_function_arg (enum machine_mode, const_tree, int);
-static void rs6000_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+static void rs6000_function_arg_advance (cumulative_args_t, enum machine_mode,
const_tree, bool);
-static rtx rs6000_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+static rtx rs6000_function_arg (cumulative_args_t, enum machine_mode,
const_tree, bool);
static unsigned int rs6000_function_arg_boundary (enum machine_mode,
const_tree);
static void rs6000_move_block_from_reg (int regno, rtx x, int nregs);
-static void setup_incoming_varargs (CUMULATIVE_ARGS *,
+static void setup_incoming_varargs (cumulative_args_t,
enum machine_mode, tree,
int *, int);
-static bool rs6000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
+static bool rs6000_pass_by_reference (cumulative_args_t, enum machine_mode,
const_tree, bool);
-static int rs6000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
+static int rs6000_arg_partial_bytes (cumulative_args_t, enum machine_mode,
tree, bool);
static const char *invalid_arg_for_unprototyped_fn (const_tree, const_tree, const_tree);
#if TARGET_MACHO
enum machine_mode,
struct secondary_reload_info *);
-static const reg_class_t *rs6000_ira_cover_classes (void);
-
const int INSN_NOT_AVAILABLE = -1;
static enum machine_mode rs6000_eh_return_filter_mode (void);
static bool rs6000_can_eliminate (const int, const int);
static void rs6000_conditional_register_usage (void);
static void rs6000_trampoline_init (rtx, tree, rtx);
+static bool rs6000_cannot_force_const_mem (enum machine_mode, rtx);
+static bool rs6000_legitimate_constant_p (enum machine_mode, rtx);
+static bool rs6000_save_toc_in_prologue_p (void);
+static void rs6000_code_end (void) ATTRIBUTE_UNUSED;
+static void rs6000_set_up_by_prologue (struct hard_reg_set_container *);
/* Hash table stuff for keeping track of TOC entries. */
static const struct attribute_spec rs6000_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
- { "altivec", 1, 1, false, true, false, rs6000_handle_altivec_attribute },
- { "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute },
- { "shortcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute },
- { "ms_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute },
- { "gcc_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute },
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+ affects_type_identity } */
+ { "altivec", 1, 1, false, true, false, rs6000_handle_altivec_attribute,
+ false },
+ { "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute,
+ false },
+ { "shortcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute,
+ false },
+ { "ms_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute,
+ false },
+ { "gcc_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute,
+ false },
#ifdef SUBTARGET_ATTRIBUTE_TABLE
SUBTARGET_ATTRIBUTE_TABLE,
#endif
- { NULL, 0, 0, false, false, false, NULL }
+ { NULL, 0, 0, false, false, false, NULL, false }
};
-
-/* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */
-static const struct default_options rs6000_option_optimization_table[] =
- {
- { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
- { OPT_LEVELS_NONE, 0, NULL, 0 }
- };
\f
#ifndef MASK_STRICT_ALIGN
#define MASK_STRICT_ALIGN 0
#undef TARGET_ASM_INTEGER
#define TARGET_ASM_INTEGER rs6000_assemble_integer
-#ifdef HAVE_GAS_HIDDEN
+#if defined (HAVE_GAS_HIDDEN) && !TARGET_MACHO
#undef TARGET_ASM_ASSEMBLE_VISIBILITY
#define TARGET_ASM_ASSEMBLE_VISIBILITY rs6000_assemble_visibility
#endif
+#undef TARGET_SET_UP_BY_PROLOGUE
+#define TARGET_SET_UP_BY_PROLOGUE rs6000_set_up_by_prologue
+
#undef TARGET_HAVE_TLS
#define TARGET_HAVE_TLS HAVE_AS_TLS
#undef TARGET_CANNOT_FORCE_CONST_MEM
-#define TARGET_CANNOT_FORCE_CONST_MEM rs6000_tls_referenced_p
+#define TARGET_CANNOT_FORCE_CONST_MEM rs6000_cannot_force_const_mem
#undef TARGET_DELEGITIMIZE_ADDRESS
#define TARGET_DELEGITIMIZE_ADDRESS rs6000_delegitimize_address
+#undef TARGET_CONST_NOT_OK_FOR_DEBUG_P
+#define TARGET_CONST_NOT_OK_FOR_DEBUG_P rs6000_const_not_ok_for_debug_p
+
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE rs6000_output_function_prologue
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN rs6000_builtin_mul_widen_even
#undef TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD
#define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD rs6000_builtin_mul_widen_odd
-#undef TARGET_VECTORIZE_BUILTIN_CONVERSION
-#define TARGET_VECTORIZE_BUILTIN_CONVERSION rs6000_builtin_conversion
-#undef TARGET_VECTORIZE_BUILTIN_VEC_PERM
-#define TARGET_VECTORIZE_BUILTIN_VEC_PERM rs6000_builtin_vec_perm
#undef TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT
#define TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT \
rs6000_builtin_support_vector_misalignment
#undef TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN
#define TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN invalid_arg_for_unprototyped_fn
-#undef TARGET_HANDLE_OPTION
-#define TARGET_HANDLE_OPTION rs6000_handle_option
-
#undef TARGET_ASM_LOOP_ALIGN_MAX_SKIP
#define TARGET_ASM_LOOP_ALIGN_MAX_SKIP rs6000_loop_align_max_skip
#undef TARGET_OPTION_OVERRIDE
#define TARGET_OPTION_OVERRIDE rs6000_option_override
-#undef TARGET_OPTION_INIT_STRUCT
-#define TARGET_OPTION_INIT_STRUCT rs6000_option_init_struct
-
-#undef TARGET_OPTION_DEFAULT_PARAMS
-#define TARGET_OPTION_DEFAULT_PARAMS rs6000_option_default_params
-
-#undef TARGET_OPTION_OPTIMIZATION_TABLE
-#define TARGET_OPTION_OPTIMIZATION_TABLE rs6000_option_optimization_table
-
#undef TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION
#define TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION \
rs6000_builtin_vectorized_function
-#undef TARGET_DEFAULT_TARGET_FLAGS
-#define TARGET_DEFAULT_TARGET_FLAGS \
- (TARGET_DEFAULT)
-
+#if !TARGET_MACHO
#undef TARGET_STACK_PROTECT_FAIL
#define TARGET_STACK_PROTECT_FAIL rs6000_stack_protect_fail
+#endif
/* MPC604EUM 3.5.2 Weak Consistency between Multiple Processors
The PowerPC architecture requires only weak consistency among
#undef TARGET_SECONDARY_RELOAD
#define TARGET_SECONDARY_RELOAD rs6000_secondary_reload
-#undef TARGET_IRA_COVER_CLASSES
-#define TARGET_IRA_COVER_CLASSES rs6000_ira_cover_classes
-
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P rs6000_legitimate_address_p
#undef TARGET_SET_CURRENT_FUNCTION
#define TARGET_SET_CURRENT_FUNCTION rs6000_set_current_function
-struct gcc_target targetm = TARGET_INITIALIZER;
+#undef TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P rs6000_legitimate_constant_p
+
+#undef TARGET_VECTORIZE_VEC_PERM_CONST_OK
+#define TARGET_VECTORIZE_VEC_PERM_CONST_OK rs6000_vectorize_vec_perm_const_ok
\f
/* Simplifications for entries below. */
| 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. */
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}
+#define RS6000_CPU(NAME, CPU, FLAGS) { NAME, CPU, FLAGS },
+#include "rs6000-cpus.def"
+#undef RS6000_CPU
};
/* Look up a processor name for -mcpu=xxx and -mtune=xxx. Return -1 if the
}
#define DEBUG_FMT_D "%-32s= %d\n"
+#define DEBUG_FMT_X "%-32s= 0x%x\n"
#define DEBUG_FMT_S "%-32s= %s\n"
/* Print various interesting information with -mdebug=reg. */
rs6000_long_double_type_size);
fprintf (stderr, DEBUG_FMT_D, "sched_restricted_insns_priority",
(int)rs6000_sched_restricted_insns_priority);
+ fprintf (stderr, DEBUG_FMT_D, "Number of standard builtins",
+ (int)END_BUILTINS);
+ fprintf (stderr, DEBUG_FMT_D, "Number of rs6000 builtins",
+ (int)RS6000_BUILTIN_COUNT);
+ fprintf (stderr, DEBUG_FMT_X, "Builtin mask", rs6000_builtin_mask);
}
/* Initialize the various global tables that are based on register size. */
rs6000_vector_reload[V4SFmode][1] = CODE_FOR_reload_v4sf_di_load;
rs6000_vector_reload[V2DFmode][0] = CODE_FOR_reload_v2df_di_store;
rs6000_vector_reload[V2DFmode][1] = CODE_FOR_reload_v2df_di_load;
+ if (TARGET_VSX && TARGET_VSX_SCALAR_MEMORY)
+ {
+ rs6000_vector_reload[DFmode][0] = CODE_FOR_reload_df_di_store;
+ rs6000_vector_reload[DFmode][1] = CODE_FOR_reload_df_di_load;
+ }
}
else
{
rs6000_vector_reload[V4SFmode][1] = CODE_FOR_reload_v4sf_si_load;
rs6000_vector_reload[V2DFmode][0] = CODE_FOR_reload_v2df_si_store;
rs6000_vector_reload[V2DFmode][1] = CODE_FOR_reload_v2df_si_load;
+ if (TARGET_VSX && TARGET_VSX_SCALAR_MEMORY)
+ {
+ rs6000_vector_reload[DFmode][0] = CODE_FOR_reload_df_si_store;
+ rs6000_vector_reload[DFmode][1] = CODE_FOR_reload_df_si_load;
+ }
}
}
off. */
rs6000_altivec_abi = 1;
TARGET_ALTIVEC_VRSAVE = 1;
+ rs6000_current_abi = ABI_DARWIN;
if (DEFAULT_ABI == ABI_DARWIN
&& TARGET_64BIT)
&& !flag_apple_kext
&& strverscmp (darwin_macosx_version_min, "10.5") >= 0
&& ! (target_flags_explicit & MASK_ALTIVEC)
- && ! rs6000_select[1].string)
+ && ! global_options_set.x_rs6000_cpu_index)
{
target_flags |= MASK_ALTIVEC;
}
#define RS6000_DEFAULT_LONG_DOUBLE_SIZE 64
#endif
+/* Return the builtin mask of the various options used that could affect which
+ builtins were used. In the past we used target_flags, but we've run out of
+ bits, and some options like SPE and PAIRED are no longer in
+ target_flags. */
+
+unsigned
+rs6000_builtin_mask_calculate (void)
+{
+ return (((TARGET_ALTIVEC) ? RS6000_BTM_ALTIVEC : 0)
+ | ((TARGET_VSX) ? RS6000_BTM_VSX : 0)
+ | ((TARGET_SPE) ? RS6000_BTM_SPE : 0)
+ | ((TARGET_PAIRED_FLOAT) ? RS6000_BTM_PAIRED : 0)
+ | ((TARGET_FRE) ? RS6000_BTM_FRE : 0)
+ | ((TARGET_FRES) ? RS6000_BTM_FRES : 0)
+ | ((TARGET_FRSQRTE) ? RS6000_BTM_FRSQRTE : 0)
+ | ((TARGET_FRSQRTES) ? RS6000_BTM_FRSQRTES : 0)
+ | ((TARGET_POPCNTD) ? RS6000_BTM_POPCNTD : 0)
+ | ((TARGET_POWERPC) ? RS6000_BTM_POWERPC : 0)
+ | ((rs6000_cpu == PROCESSOR_CELL) ? RS6000_BTM_CELL : 0));
+}
+
/* Override command line options. Mostly we process the processor type and
sometimes adjust other TARGET_ options. */
= ((global_init_p || target_option_default_node == NULL)
? NULL : TREE_TARGET_OPTION (target_option_default_node));
+ /* On 64-bit Darwin, power alignment is ABI-incompatible with some C
+ library functions, so warn about it. The flag may be useful for
+ performance studies from time to time though, so don't disable it
+ entirely. */
+ if (global_options_set.x_rs6000_alignment_flags
+ && rs6000_alignment_flags == MASK_ALIGN_POWER
+ && DEFAULT_ABI == ABI_DARWIN
+ && TARGET_64BIT)
+ warning (0, "-malign-power is not supported for 64-bit Darwin;"
+ " it is incompatible with the installed C and C++ libraries");
+
+ if (global_options_set.x_rs6000_spe_abi
+ && rs6000_spe_abi
+ && !TARGET_SPE_ABI)
+ error ("not configured for SPE ABI");
+
/* 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.
}
}
- if (!rs6000_explicit_options.long_double)
+ if (!global_options_set.x_rs6000_long_double_type_size)
{
if (main_target_opt != NULL
&& (main_target_opt->x_rs6000_long_double_type_size
}
#ifndef POWERPC_LINUX
- if (!rs6000_explicit_options.ieee)
+ if (!global_options_set.x_rs6000_ieeequad)
rs6000_ieeequad = 1;
#endif
be explicitly overridden in either case. */
if (TARGET_ELF)
{
- if (!rs6000_explicit_options.altivec_abi
+ if (!global_options_set.x_rs6000_altivec_abi
&& (TARGET_64BIT || TARGET_ALTIVEC || TARGET_VSX))
{
if (main_target_opt != NULL &&
}
/* Enable VRSAVE for AltiVec ABI, unless explicitly overridden. */
- if (!rs6000_explicit_options.vrsave)
+ if (!global_options_set.x_TARGET_ALTIVEC_VRSAVE)
TARGET_ALTIVEC_VRSAVE = rs6000_altivec_abi;
}
if ((target_flags & MASK_STRING) != 0)
target_flags = target_flags & ~MASK_STRING;
}
- else if (rs6000_select[1].string != NULL)
+ else if (global_options_set.x_rs6000_cpu_index)
{
/* For the powerpc-eabispe configuration, we set all these by
default, so let's unset them if we manually set another
error ("target attribute or pragma changes SPE ABI");
else
{
- if (!rs6000_explicit_options.spe_abi)
+ if (!global_options_set.x_rs6000_spe_abi)
rs6000_spe_abi = 0;
- if (!rs6000_explicit_options.spe)
+ if (!global_options_set.x_rs6000_spe)
rs6000_spe = 0;
- if (!rs6000_explicit_options.float_gprs)
+ if (!global_options_set.x_rs6000_float_gprs)
rs6000_float_gprs = 0;
}
if (!(target_flags_explicit & MASK_ISEL))
&& rs6000_cpu != PROCESSOR_POWER6
&& rs6000_cpu != PROCESSOR_POWER7
&& rs6000_cpu != PROCESSOR_PPCA2
- && rs6000_cpu != PROCESSOR_CELL);
+ && rs6000_cpu != PROCESSOR_CELL
+ && rs6000_cpu != PROCESSOR_PPC476);
rs6000_sched_groups = (rs6000_cpu == PROCESSOR_POWER4
|| rs6000_cpu == PROCESSOR_POWER5
|| rs6000_cpu == PROCESSOR_POWER7);
/* 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)
+ if (!global_options_set.x_aix_struct_return)
aix_struct_return = (DEFAULT_ABI != ABI_V4 || DRAFT_V4_STRUCT_RET);
#if 0
}
}
+ /* Set the builtin mask of the various options used that could affect which
+ builtins were used. In the past we used target_flags, but we've run out
+ of bits, and some options like SPE and PAIRED are no longer in
+ target_flags. */
+ rs6000_builtin_mask = rs6000_builtin_mask_calculate ();
+ if (TARGET_DEBUG_BUILTIN || TARGET_DEBUG_TARGET)
+ fprintf (stderr, "new builtin mask = 0x%x%s%s%s%s\n", rs6000_builtin_mask,
+ (rs6000_builtin_mask & RS6000_BTM_ALTIVEC) ? ", altivec" : "",
+ (rs6000_builtin_mask & RS6000_BTM_VSX) ? ", vsx" : "",
+ (rs6000_builtin_mask & RS6000_BTM_PAIRED) ? ", paired" : "",
+ (rs6000_builtin_mask & RS6000_BTM_SPE) ? ", spe" : "");
+
+ /* Initialize all of the registers. */
rs6000_init_hard_regno_mode_ok (global_init_p);
/* Save the initial options in case the user does function specific options */
target_option_default_node = target_option_current_node
= build_target_option_node ();
+ /* If not explicitly specified via option, decide whether to generate the
+ extra blr's required to preserve the link stack on some cpus (eg, 476). */
+ if (TARGET_LINK_STACK == -1)
+ SET_TARGET_LINK_STACK (rs6000_cpu == PROCESSOR_PPC476 && flag_pic);
+
return ret;
}
return (1 << rs6000_loop_align (label)) - 1;
}
-/* Implement targetm.vectorize.builtin_conversion.
- Returns a decl of a function that implements conversion of an integer vector
- into a floating-point vector, or vice-versa. DEST_TYPE is the
- destination type and SRC_TYPE the source type of the conversion.
- Return NULL_TREE if it is not available. */
-static tree
-rs6000_builtin_conversion (unsigned int tcode, tree dest_type, tree src_type)
-{
- enum tree_code code = (enum tree_code) tcode;
-
- switch (code)
- {
- case FIX_TRUNC_EXPR:
- switch (TYPE_MODE (dest_type))
- {
- case V2DImode:
- if (!VECTOR_UNIT_VSX_P (V2DFmode))
- return NULL_TREE;
-
- return TYPE_UNSIGNED (dest_type)
- ? rs6000_builtin_decls[VSX_BUILTIN_XVCVDPUXDS_UNS]
- : rs6000_builtin_decls[VSX_BUILTIN_XVCVDPSXDS];
-
- case V4SImode:
- if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
- return NULL_TREE;
-
- return TYPE_UNSIGNED (dest_type)
- ? rs6000_builtin_decls[VECTOR_BUILTIN_FIXUNS_V4SF_V4SI]
- : rs6000_builtin_decls[VECTOR_BUILTIN_FIX_V4SF_V4SI];
-
- default:
- return NULL_TREE;
- }
-
- case FLOAT_EXPR:
- switch (TYPE_MODE (src_type))
- {
- case V2DImode:
- if (!VECTOR_UNIT_VSX_P (V2DFmode))
- return NULL_TREE;
-
- return TYPE_UNSIGNED (src_type)
- ? rs6000_builtin_decls[VSX_BUILTIN_XVCVUXDDP]
- : rs6000_builtin_decls[VSX_BUILTIN_XVCVSXDDP];
-
- case V4SImode:
- if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
- return NULL_TREE;
-
- return TYPE_UNSIGNED (src_type)
- ? rs6000_builtin_decls[VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF]
- : rs6000_builtin_decls[VECTOR_BUILTIN_FLOAT_V4SI_V4SF];
-
- default:
- return NULL_TREE;
- }
-
- default:
- return NULL_TREE;
- }
-}
-
/* Implement targetm.vectorize.builtin_mul_widen_even. */
static tree
rs6000_builtin_mul_widen_even (tree type)
return false;
}
-/* Implement targetm.vectorize.builtin_vec_perm. */
-tree
-rs6000_builtin_vec_perm (tree type, tree *mask_element_type)
-{
- tree inner_type = TREE_TYPE (type);
- bool uns_p = TYPE_UNSIGNED (inner_type);
- tree d;
-
- *mask_element_type = unsigned_char_type_node;
-
- switch (TYPE_MODE (type))
- {
- case V16QImode:
- d = (uns_p
- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_16QI_UNS]
- : rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_16QI]);
- break;
-
- case V8HImode:
- d = (uns_p
- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_8HI_UNS]
- : rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_8HI]);
- break;
-
- case V4SImode:
- d = (uns_p
- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SI_UNS]
- : rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SI]);
- break;
-
- case V4SFmode:
- d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SF];
- break;
-
- case V2DFmode:
- if (!TARGET_ALLOW_DF_PERMUTE)
- return NULL_TREE;
-
- d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DF];
- break;
-
- case V2DImode:
- if (!TARGET_ALLOW_DF_PERMUTE)
- return NULL_TREE;
-
- d = (uns_p
- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DI_UNS]
- : rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DI]);
- break;
-
- default:
- return NULL_TREE;
- }
-
- gcc_assert (d);
- return d;
-}
-
-
/* Implement targetm.vectorize.builtin_vectorization_cost. */
static int
rs6000_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
case vec_to_scalar:
case scalar_to_vec:
case cond_branch_not_taken:
- case vec_perm:
return 1;
+ case vec_perm:
+ if (!TARGET_VSX)
+ return 1;
+ return 2;
+
case cond_branch_taken:
return 3;
return word_mode;
}
-/* Handle generic options of the form -mfoo=yes/no.
- NAME is the option name.
- VALUE is the option value.
- FLAG is the pointer to the flag where to store a 1 or 0, depending on
- whether the option value is 'yes' or 'no' respectively. */
-static void
-rs6000_parse_yes_no_option (const char *name, const char *value, int *flag)
-{
- if (value == 0)
- return;
- else if (!strcmp (value, "yes"))
- *flag = 1;
- else if (!strcmp (value, "no"))
- *flag = 0;
- else
- error ("unknown -m%s= option specified: '%s'", name, value);
-}
-
-/* Implement TARGET_OPTION_INIT_STRUCT. */
-
-static void
-rs6000_option_init_struct (struct gcc_options *opts)
-{
- if (DEFAULT_ABI == ABI_DARWIN)
- /* The Darwin libraries never set errno, so we might as well
- avoid calling them when that's the only reason we would. */
- opts->x_flag_errno_math = 0;
-
- /* Enable section anchors by default. */
- if (!TARGET_MACHO)
- opts->x_flag_section_anchors = 1;
-}
-
-/* Implement TARGET_OPTION_DEFAULT_PARAMS. */
-
-static void
-rs6000_option_default_params (void)
-{
- /* Double growth factor to counter reduced min jump length. */
- set_default_param_value (PARAM_MAX_GROW_COPY_BB_INSNS, 16);
-}
-
-static enum fpu_type_t
-rs6000_parse_fpu_option (const char *option)
-{
- if (!strcmp("none", option)) return FPU_NONE;
- if (!strcmp("sp_lite", option)) return FPU_SF_LITE;
- if (!strcmp("dp_lite", option)) return FPU_DF_LITE;
- if (!strcmp("sp_full", option)) return FPU_SF_FULL;
- if (!strcmp("dp_full", option)) return FPU_DF_FULL;
- error("unknown value %s for -mfpu", option);
- return FPU_NONE;
-}
-
-
/* Handler for the Mathematical Acceleration Subsystem (mass) interface to a
library with vectorized intrinsics. */
case BUILT_IN_SQRT:
case BUILT_IN_TAN:
case BUILT_IN_TANH:
- bdecl = implicit_built_in_decls[fn];
+ bdecl = builtin_decl_implicit (fn);
suffix = "d2"; /* pow -> powd2 */
if (el_mode != DFmode
|| n != 2)
case BUILT_IN_SQRTF:
case BUILT_IN_TANF:
case BUILT_IN_TANHF:
- bdecl = implicit_built_in_decls[fn];
+ bdecl = builtin_decl_implicit (fn);
suffix = "4"; /* powf -> powf4 */
if (el_mode != SFmode
|| n != 4)
enum machine_mode in_mode, out_mode;
int in_n, out_n;
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr, "rs6000_builtin_vectorized_function (%s, %s, %s)\n",
+ IDENTIFIER_POINTER (DECL_NAME (fndecl)),
+ GET_MODE_NAME (TYPE_MODE (type_out)),
+ GET_MODE_NAME (TYPE_MODE (type_in)));
+
if (TREE_CODE (type_out) != VECTOR_TYPE
|| TREE_CODE (type_in) != VECTOR_TYPE
|| !TARGET_VECTORIZE_BUILTINS)
if (VECTOR_UNIT_VSX_P (V2DFmode)
&& out_mode == DFmode && out_n == 2
&& in_mode == DFmode && in_n == 2)
- return rs6000_builtin_decls[VSX_BUILTIN_VEC_RSQRT_V2DF];
+ return rs6000_builtin_decls[VSX_BUILTIN_RSQRT_2DF];
break;
case RS6000_BUILTIN_RECIPF:
if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
return NULL_TREE;
}
+\f
+/* Default CPU string for rs6000*_file_start functions. */
+static const char *rs6000_default_cpu;
+/* Do anything needed at the start of the asm file. */
-/* Implement TARGET_HANDLE_OPTION. */
-
-static bool
-rs6000_handle_option (size_t code, const char *arg, int value)
+static void
+rs6000_file_start (void)
{
- enum fpu_type_t fpu_type = FPU_NONE;
- int isel;
- char *p, *q;
+ char buffer[80];
+ const char *start = buffer;
+ FILE *file = asm_out_file;
- switch (code)
- {
- case OPT_mno_power:
- target_flags &= ~(MASK_POWER | MASK_POWER2
- | MASK_MULTIPLE | MASK_STRING);
- target_flags_explicit |= (MASK_POWER | MASK_POWER2
- | MASK_MULTIPLE | MASK_STRING);
- break;
- case OPT_mno_powerpc:
- target_flags &= ~(MASK_POWERPC | MASK_PPC_GPOPT
- | MASK_PPC_GFXOPT | MASK_POWERPC64);
- target_flags_explicit |= (MASK_POWERPC | MASK_PPC_GPOPT
- | MASK_PPC_GFXOPT | MASK_POWERPC64);
- break;
- case OPT_mfull_toc:
- target_flags &= ~MASK_MINIMAL_TOC;
- TARGET_NO_FP_IN_TOC = 0;
- TARGET_NO_SUM_IN_TOC = 0;
- target_flags_explicit |= MASK_MINIMAL_TOC;
-#ifdef TARGET_USES_SYSV4_OPT
- /* Note, V.4 no longer uses a normal TOC, so make -mfull-toc, be
- just the same as -mminimal-toc. */
- target_flags |= MASK_MINIMAL_TOC;
- target_flags_explicit |= MASK_MINIMAL_TOC;
-#endif
- break;
+ rs6000_default_cpu = TARGET_CPU_DEFAULT;
-#ifdef TARGET_USES_SYSV4_OPT
- case OPT_mtoc:
- /* Make -mtoc behave like -mminimal-toc. */
- target_flags |= MASK_MINIMAL_TOC;
- target_flags_explicit |= MASK_MINIMAL_TOC;
- break;
-#endif
+ default_file_start ();
-#if defined (HAVE_LD_LARGE_TOC) && defined (TARGET_USES_LINUX64_OPT)
- case OPT_mcmodel_:
- if (strcmp (arg, "small") == 0)
- rs6000_current_cmodel = CMODEL_SMALL;
- else if (strcmp (arg, "medium") == 0)
- rs6000_current_cmodel = CMODEL_MEDIUM;
- else if (strcmp (arg, "large") == 0)
- rs6000_current_cmodel = CMODEL_LARGE;
- else
- {
- error ("invalid option for -mcmodel: '%s'", arg);
- return false;
- }
- rs6000_explicit_options.cmodel = true;
+#ifdef TARGET_BI_ARCH
+ if ((TARGET_DEFAULT ^ target_flags) & MASK_64BIT)
+ rs6000_default_cpu = 0;
#endif
-#ifdef TARGET_USES_AIX64_OPT
- case OPT_maix64:
-#else
- case OPT_m64:
-#endif
- target_flags |= MASK_POWERPC64 | MASK_POWERPC;
- target_flags |= ~target_flags_explicit & MASK_PPC_GFXOPT;
- target_flags_explicit |= MASK_POWERPC64 | MASK_POWERPC;
- break;
+ if (flag_verbose_asm)
+ {
+ sprintf (buffer, "\n%s rs6000/powerpc options:", ASM_COMMENT_START);
-#ifdef TARGET_USES_AIX64_OPT
- case OPT_maix32:
-#else
- case OPT_m32:
-#endif
- target_flags &= ~MASK_POWERPC64;
- target_flags_explicit |= MASK_POWERPC64;
- break;
+ if (rs6000_default_cpu != 0 && rs6000_default_cpu[0] != '\0')
+ {
+ fprintf (file, "%s --with-cpu=%s", start, rs6000_default_cpu);
+ start = "";
+ }
- case OPT_minsert_sched_nops_:
- rs6000_sched_insert_nops_str = arg;
- break;
+ if (global_options_set.x_rs6000_cpu_index)
+ {
+ fprintf (file, "%s -mcpu=%s", start,
+ processor_target_table[rs6000_cpu_index].name);
+ start = "";
+ }
- case OPT_mminimal_toc:
- if (value == 1)
+ if (global_options_set.x_rs6000_tune_index)
{
- TARGET_NO_FP_IN_TOC = 0;
- TARGET_NO_SUM_IN_TOC = 0;
+ fprintf (file, "%s -mtune=%s", start,
+ processor_target_table[rs6000_tune_index].name);
+ start = "";
}
- break;
- case OPT_mpower:
- if (value == 1)
+ if (PPC405_ERRATUM77)
{
- target_flags |= (MASK_MULTIPLE | MASK_STRING);
- target_flags_explicit |= (MASK_MULTIPLE | MASK_STRING);
+ fprintf (file, "%s PPC405CR_ERRATUM77", start);
+ start = "";
}
- break;
- case OPT_mpower2:
- if (value == 1)
+#ifdef USING_ELFOS_H
+ switch (rs6000_sdata)
{
- target_flags |= (MASK_POWER | MASK_MULTIPLE | MASK_STRING);
- target_flags_explicit |= (MASK_POWER | MASK_MULTIPLE | MASK_STRING);
+ case SDATA_NONE: fprintf (file, "%s -msdata=none", start); start = ""; break;
+ case SDATA_DATA: fprintf (file, "%s -msdata=data", start); start = ""; break;
+ case SDATA_SYSV: fprintf (file, "%s -msdata=sysv", start); start = ""; break;
+ case SDATA_EABI: fprintf (file, "%s -msdata=eabi", start); start = ""; break;
}
- break;
- case OPT_mpowerpc_gpopt:
- case OPT_mpowerpc_gfxopt:
- if (value == 1)
+ if (rs6000_sdata && g_switch_value)
{
- target_flags |= MASK_POWERPC;
- target_flags_explicit |= MASK_POWERPC;
+ fprintf (file, "%s -G %d", start,
+ g_switch_value);
+ start = "";
}
- break;
+#endif
- case OPT_maix_struct_return:
- case OPT_msvr4_struct_return:
- rs6000_explicit_options.aix_struct_ret = true;
- break;
+ if (*start == '\0')
+ putc ('\n', file);
+ }
- case OPT_mvrsave:
- rs6000_explicit_options.vrsave = true;
- TARGET_ALTIVEC_VRSAVE = value;
- break;
+ if (DEFAULT_ABI == ABI_AIX || (TARGET_ELF && flag_pic == 2))
+ {
+ switch_to_section (toc_section);
+ switch_to_section (text_section);
+ }
+}
- case OPT_mvrsave_:
- rs6000_explicit_options.vrsave = true;
- rs6000_parse_yes_no_option ("vrsave", arg, &(TARGET_ALTIVEC_VRSAVE));
- break;
+\f
+/* Return nonzero if this function is known to have a null epilogue. */
- case OPT_misel_:
- target_flags_explicit |= MASK_ISEL;
- isel = 0;
- rs6000_parse_yes_no_option ("isel", arg, &isel);
- if (isel)
- target_flags |= MASK_ISEL;
- else
- target_flags &= ~MASK_ISEL;
- break;
+int
+direct_return (void)
+{
+ if (reload_completed)
+ {
+ rs6000_stack_t *info = rs6000_stack_info ();
- case OPT_mspe:
- rs6000_explicit_options.spe = true;
- rs6000_spe = value;
- break;
+ if (info->first_gp_reg_save == 32
+ && info->first_fp_reg_save == 64
+ && info->first_altivec_reg_save == LAST_ALTIVEC_REGNO + 1
+ && ! info->lr_save_p
+ && ! info->cr_save_p
+ && info->vrsave_mask == 0
+ && ! info->push_p)
+ return 1;
+ }
- case OPT_mspe_:
- rs6000_explicit_options.spe = true;
- rs6000_parse_yes_no_option ("spe", arg, &(rs6000_spe));
- break;
+ return 0;
+}
- case OPT_mdebug_:
- 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
- case OPT_mcall_:
- rs6000_abi_name = arg;
- break;
-
- case OPT_msdata_:
- rs6000_sdata_name = arg;
- break;
-
- case OPT_mtls_size_:
- 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:
- if (value == 1)
- {
- target_flags |= MASK_MINIMAL_TOC;
- target_flags_explicit |= MASK_MINIMAL_TOC;
- TARGET_NO_FP_IN_TOC = 1;
- }
- break;
-
- case OPT_mrelocatable_lib:
- if (value == 1)
- {
- target_flags |= MASK_RELOCATABLE | MASK_MINIMAL_TOC;
- target_flags_explicit |= MASK_RELOCATABLE | MASK_MINIMAL_TOC;
- TARGET_NO_FP_IN_TOC = 1;
- }
- else
- {
- target_flags &= ~MASK_RELOCATABLE;
- target_flags_explicit |= MASK_RELOCATABLE;
- }
- break;
-#endif
-
- case OPT_mabi_:
- if (!strcmp (arg, "altivec"))
- {
- rs6000_explicit_options.altivec_abi = true;
- rs6000_altivec_abi = 1;
-
- /* Enabling the AltiVec ABI turns off the SPE ABI. */
- rs6000_spe_abi = 0;
- }
- else if (! strcmp (arg, "no-altivec"))
- {
- rs6000_explicit_options.altivec_abi = true;
- rs6000_altivec_abi = 0;
- }
- else if (! strcmp (arg, "spe"))
- {
- rs6000_explicit_options.spe_abi = true;
- rs6000_spe_abi = 1;
- rs6000_altivec_abi = 0;
- if (!TARGET_SPE_ABI)
- error ("not configured for ABI: '%s'", arg);
- }
- else if (! strcmp (arg, "no-spe"))
- {
- rs6000_explicit_options.spe_abi = true;
- rs6000_spe_abi = 0;
- }
-
- /* These are here for testing during development only, do not
- document in the manual please. */
- else if (! strcmp (arg, "d64"))
- {
- rs6000_darwin64_abi = 1;
- warning (0, "using darwin64 ABI");
- }
- else if (! strcmp (arg, "d32"))
- {
- rs6000_darwin64_abi = 0;
- warning (0, "using old darwin ABI");
- }
-
- else if (! strcmp (arg, "ibmlongdouble"))
- {
- rs6000_explicit_options.ieee = true;
- rs6000_ieeequad = 0;
- warning (0, "using IBM extended precision long double");
- }
- else if (! strcmp (arg, "ieeelongdouble"))
- {
- rs6000_explicit_options.ieee = true;
- rs6000_ieeequad = 1;
- warning (0, "using IEEE extended precision long double");
- }
-
- else
- {
- error ("unknown ABI specified: '%s'", arg);
- return false;
- }
- break;
-
- 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_:
- 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_:
- rs6000_explicit_options.float_gprs = true;
- if (! strcmp (arg, "yes") || ! strcmp (arg, "single"))
- rs6000_float_gprs = 1;
- else if (! strcmp (arg, "double"))
- rs6000_float_gprs = 2;
- else if (! strcmp (arg, "no"))
- rs6000_float_gprs = 0;
- else
- {
- error ("invalid option for -mfloat-gprs: '%s'", arg);
- return false;
- }
- break;
-
- case OPT_mlong_double_:
- rs6000_explicit_options.long_double = true;
- rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
- if (value != 64 && value != 128)
- {
- error ("unknown switch -mlong-double-%s", arg);
- rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
- return false;
- }
- else
- rs6000_long_double_type_size = value;
- break;
-
- case OPT_msched_costly_dep_:
- rs6000_sched_costly_dep_str = arg;
- break;
-
- case OPT_malign_:
- rs6000_explicit_options.alignment = true;
- if (! strcmp (arg, "power"))
- {
- /* On 64-bit Darwin, power alignment is ABI-incompatible with
- some C library functions, so warn about it. The flag may be
- useful for performance studies from time to time though, so
- don't disable it entirely. */
- if (DEFAULT_ABI == ABI_DARWIN && TARGET_64BIT)
- warning (0, "-malign-power is not supported for 64-bit Darwin;"
- " it is incompatible with the installed C and C++ libraries");
- rs6000_alignment_flags = MASK_ALIGN_POWER;
- }
- else if (! strcmp (arg, "natural"))
- rs6000_alignment_flags = MASK_ALIGN_NATURAL;
- else
- {
- error ("unknown -malign-XXXXX option specified: '%s'", arg);
- return false;
- }
- break;
-
- case OPT_msingle_float:
- if (!TARGET_SINGLE_FPU)
- warning (0, "-msingle-float option equivalent to -mhard-float");
- /* -msingle-float implies -mno-double-float and TARGET_HARD_FLOAT. */
- rs6000_double_float = 0;
- target_flags &= ~MASK_SOFT_FLOAT;
- target_flags_explicit |= MASK_SOFT_FLOAT;
- break;
-
- case OPT_mdouble_float:
- /* -mdouble-float implies -msingle-float and TARGET_HARD_FLOAT. */
- rs6000_single_float = 1;
- target_flags &= ~MASK_SOFT_FLOAT;
- target_flags_explicit |= MASK_SOFT_FLOAT;
- break;
-
- case OPT_msimple_fpu:
- if (!TARGET_SINGLE_FPU)
- warning (0, "-msimple-fpu option ignored");
- break;
-
- case OPT_mhard_float:
- /* -mhard_float implies -msingle-float and -mdouble-float. */
- rs6000_single_float = rs6000_double_float = 1;
- break;
-
- case OPT_msoft_float:
- /* -msoft_float implies -mnosingle-float and -mnodouble-float. */
- rs6000_single_float = rs6000_double_float = 0;
- break;
-
- case OPT_mfpu_:
- fpu_type = rs6000_parse_fpu_option(arg);
- if (fpu_type != FPU_NONE)
- /* If -mfpu is not none, then turn off SOFT_FLOAT, turn on HARD_FLOAT. */
- {
- target_flags &= ~MASK_SOFT_FLOAT;
- target_flags_explicit |= MASK_SOFT_FLOAT;
- rs6000_xilinx_fpu = 1;
- if (fpu_type == FPU_SF_LITE || fpu_type == FPU_SF_FULL)
- rs6000_single_float = 1;
- if (fpu_type == FPU_DF_LITE || fpu_type == FPU_DF_FULL)
- rs6000_single_float = rs6000_double_float = 1;
- if (fpu_type == FPU_SF_LITE || fpu_type == FPU_DF_LITE)
- rs6000_simple_fpu = 1;
- }
- else
- {
- /* -mfpu=none is equivalent to -msoft-float */
- target_flags |= MASK_SOFT_FLOAT;
- target_flags_explicit |= MASK_SOFT_FLOAT;
- rs6000_single_float = rs6000_double_float = 0;
- }
-
- case OPT_mrecip:
- rs6000_recip_name = (value) ? "default" : "none";
- break;
-
- case OPT_mrecip_:
- rs6000_recip_name = arg;
- break;
- }
- return true;
-}
-\f
-/* Do anything needed at the start of the asm file. */
-
-static void
-rs6000_file_start (void)
-{
- size_t i;
- char buffer[80];
- const char *start = buffer;
- struct rs6000_cpu_select *ptr;
- const char *default_cpu = TARGET_CPU_DEFAULT;
- FILE *file = asm_out_file;
-
- default_file_start ();
-
-#ifdef TARGET_BI_ARCH
- if ((TARGET_DEFAULT ^ target_flags) & MASK_64BIT)
- default_cpu = 0;
-#endif
-
- if (flag_verbose_asm)
- {
- sprintf (buffer, "\n%s rs6000/powerpc options:", ASM_COMMENT_START);
- rs6000_select[0].string = default_cpu;
-
- for (i = 0; i < ARRAY_SIZE (rs6000_select); i++)
- {
- ptr = &rs6000_select[i];
- if (ptr->string != (char *)0 && ptr->string[0] != '\0')
- {
- fprintf (file, "%s %s%s", start, ptr->name, ptr->string);
- start = "";
- }
- }
-
- if (PPC405_ERRATUM77)
- {
- fprintf (file, "%s PPC405CR_ERRATUM77", start);
- start = "";
- }
-
-#ifdef USING_ELFOS_H
- switch (rs6000_sdata)
- {
- case SDATA_NONE: fprintf (file, "%s -msdata=none", start); start = ""; break;
- case SDATA_DATA: fprintf (file, "%s -msdata=data", start); start = ""; break;
- case SDATA_SYSV: fprintf (file, "%s -msdata=sysv", start); start = ""; break;
- case SDATA_EABI: fprintf (file, "%s -msdata=eabi", start); start = ""; break;
- }
-
- if (rs6000_sdata && g_switch_value)
- {
- fprintf (file, "%s -G %d", start,
- g_switch_value);
- start = "";
- }
-#endif
-
- if (*start == '\0')
- putc ('\n', file);
- }
-
- if (DEFAULT_ABI == ABI_AIX || (TARGET_ELF && flag_pic == 2))
- {
- switch_to_section (toc_section);
- switch_to_section (text_section);
- }
-}
-
-\f
-/* Return nonzero if this function is known to have a null epilogue. */
-
-int
-direct_return (void)
-{
- if (reload_completed)
- {
- rs6000_stack_t *info = rs6000_stack_info ();
-
- if (info->first_gp_reg_save == 32
- && info->first_fp_reg_save == 64
- && info->first_altivec_reg_save == LAST_ALTIVEC_REGNO + 1
- && ! info->lr_save_p
- && ! info->cr_save_p
- && info->vrsave_mask == 0
- && ! info->push_p)
- return 1;
- }
-
- return 0;
-}
-
-/* Return the number of instructions it takes to form a constant in an
- integer register. */
+/* Return the number of instructions it takes to form a constant in an
+ integer register. */
int
num_insns_constant_wide (HOST_WIDE_INT value)
for (i = 0; i < n_elts; ++i)
{
x = XVECEXP (vals, 0, i);
- if (!CONSTANT_P (x))
+ if (!(CONST_INT_P (x)
+ || GET_CODE (x) == CONST_DOUBLE
+ || GET_CODE (x) == CONST_FIXED))
++n_var;
}
if (n_var == 0)
for (i = 0; i < n_elts; ++i)
{
x = XVECEXP (vals, 0, i);
- if (!CONSTANT_P (x))
+ if (!(CONST_INT_P (x)
+ || GET_CODE (x) == CONST_DOUBLE
+ || GET_CODE (x) == CONST_FIXED))
++n_var, one_var = i;
else if (x != CONST0_RTX (inner_mode))
all_const_zero = false;
copy_to_reg (XVECEXP (vals, 0, 3))));
emit_insn (gen_vsx_xvcvdpsp (flt_even, dbl_even));
emit_insn (gen_vsx_xvcvdpsp (flt_odd, dbl_odd));
- emit_insn (gen_vec_extract_evenv4sf (target, flt_even, flt_odd));
+ rs6000_expand_extract_even (target, flt_even, flt_odd);
}
return;
}
/* Store value to stack temp. Load vector element. Splat. However, splat
of 64-bit items is not supported on Altivec. */
- if (all_same && GET_MODE_SIZE (mode) <= 4)
+ if (all_same && GET_MODE_SIZE (inner_mode) <= 4)
{
mem = assign_stack_temp (mode, GET_MODE_SIZE (inner_mode), 0);
emit_move_insn (adjust_address_nv (mem, inner_mode, 0),
enum machine_mode inner_mode = GET_MODE_INNER (mode);
rtx mem;
- if (VECTOR_MEM_VSX_P (mode) && (mode == V2DFmode || mode == V2DImode))
+ if (VECTOR_MEM_VSX_P (mode))
{
- rtx (*extract_func) (rtx, rtx, rtx)
- = ((mode == V2DFmode) ? gen_vsx_extract_v2df : gen_vsx_extract_v2di);
- emit_insn (extract_func (target, vec, GEN_INT (elt)));
- return;
+ switch (mode)
+ {
+ default:
+ break;
+ case V2DFmode:
+ emit_insn (gen_vsx_extract_v2df (target, vec, GEN_INT (elt)));
+ return;
+ case V2DImode:
+ emit_insn (gen_vsx_extract_v2di (target, vec, GEN_INT (elt)));
+ return;
+ case V4SFmode:
+ emit_insn (gen_vsx_extract_v4sf (target, vec, GEN_INT (elt)));
+ return;
+ }
}
/* Allocate mode-sized buffer. */
&& regnum <= LAST_VIRTUAL_POINTER_REGISTER);
}
+/* Return true if memory accesses to OP are known to never straddle
+ a 32k boundary. */
+
+static bool
+offsettable_ok_by_alignment (rtx op, HOST_WIDE_INT offset,
+ enum machine_mode mode)
+{
+ tree decl, type;
+ unsigned HOST_WIDE_INT dsize, dalign;
+
+ if (GET_CODE (op) != SYMBOL_REF)
+ return false;
+
+ decl = SYMBOL_REF_DECL (op);
+ if (!decl)
+ {
+ if (GET_MODE_SIZE (mode) == 0)
+ return false;
+
+ /* -fsection-anchors loses the original SYMBOL_REF_DECL when
+ replacing memory addresses with an anchor plus offset. We
+ could find the decl by rummaging around in the block->objects
+ VEC for the given offset but that seems like too much work. */
+ dalign = 1;
+ if (SYMBOL_REF_HAS_BLOCK_INFO_P (op)
+ && SYMBOL_REF_ANCHOR_P (op)
+ && SYMBOL_REF_BLOCK (op) != NULL)
+ {
+ struct object_block *block = SYMBOL_REF_BLOCK (op);
+ HOST_WIDE_INT lsb, mask;
+
+ /* Given the alignment of the block.. */
+ dalign = block->alignment;
+ mask = dalign / BITS_PER_UNIT - 1;
+
+ /* ..and the combined offset of the anchor and any offset
+ to this block object.. */
+ offset += SYMBOL_REF_BLOCK_OFFSET (op);
+ lsb = offset & -offset;
+
+ /* ..find how many bits of the alignment we know for the
+ object. */
+ mask &= lsb - 1;
+ dalign = mask + 1;
+ }
+ return dalign >= GET_MODE_SIZE (mode);
+ }
+
+ if (DECL_P (decl))
+ {
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ return true;
+
+ if (!DECL_SIZE_UNIT (decl))
+ return false;
+
+ if (!host_integerp (DECL_SIZE_UNIT (decl), 1))
+ return false;
+
+ dsize = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
+ if (dsize > 32768)
+ return false;
+
+ dalign = DECL_ALIGN_UNIT (decl);
+ return dalign >= dsize;
+ }
+
+ type = TREE_TYPE (decl);
+
+ if (TREE_CODE (decl) == STRING_CST)
+ dsize = TREE_STRING_LENGTH (decl);
+ else if (TYPE_SIZE_UNIT (type)
+ && host_integerp (TYPE_SIZE_UNIT (type), 1))
+ dsize = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
+ else
+ return false;
+ if (dsize > 32768)
+ return false;
+
+ dalign = TYPE_ALIGN (type);
+ if (CONSTANT_CLASS_P (decl))
+ dalign = CONSTANT_ALIGNMENT (decl, dalign);
+ else
+ dalign = DATA_ALIGNMENT (decl, dalign);
+ dalign /= BITS_PER_UNIT;
+ return dalign >= dsize;
+}
+
static bool
constant_pool_expr_p (rtx op)
{
&& XINT (tocrel_base, 1) == UNSPEC_TOCREL);
}
+/* Return true if X is a constant pool address, and also for cmodel=medium
+ if X is a toc-relative address known to be offsettable within MODE. */
+
bool
-legitimate_constant_pool_address_p (const_rtx x, bool strict)
+legitimate_constant_pool_address_p (const_rtx x, enum machine_mode mode,
+ bool strict)
{
return (TARGET_TOC
&& (GET_CODE (x) == PLUS || GET_CODE (x) == LO_SUM)
|| ((TARGET_MINIMAL_TOC
|| TARGET_CMODEL != CMODEL_SMALL)
&& INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict)))
- && toc_relative_expr_p (XEXP (x, 1)));
+ && toc_relative_expr_p (XEXP (x, 1))
+ && (TARGET_CMODEL != CMODEL_MEDIUM
+ || constant_pool_expr_p (XVECEXP (tocrel_base, 0, 0))
+ || mode == QImode
+ || offsettable_ok_by_alignment (XVECEXP (tocrel_base, 0, 0),
+ INTVAL (tocrel_offset), mode)));
}
static bool
return false;
if (!reg_offset_addressing_ok_p (mode))
return virtual_stack_registers_memory_p (x);
- if (legitimate_constant_pool_address_p (x, strict))
+ if (legitimate_constant_pool_address_p (x, mode, strict))
return true;
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
return false;
}
offset += 0x8000;
- return (offset < 0x10000) && (offset + extra < 0x10000);
+ return offset < 0x10000 - extra;
}
bool
if (GET_CODE (x) == (TARGET_CMODEL != CMODEL_SMALL ? LO_SUM : PLUS)
&& GET_CODE (XEXP (x, 1)) == CONST)
{
+ rtx offset = NULL_RTX;
+
y = XEXP (XEXP (x, 1), 0);
- if (GET_CODE (y) == UNSPEC
+ if (GET_CODE (y) == PLUS
+ && GET_MODE (y) == Pmode
+ && CONST_INT_P (XEXP (y, 1)))
+ {
+ offset = XEXP (y, 1);
+ y = XEXP (y, 0);
+ }
+ if (GET_CODE (y) == UNSPEC
&& XINT (y, 1) == UNSPEC_TOCREL
&& ((GET_CODE (XEXP (x, 0)) == REG
&& (REGNO (XEXP (x, 0)) == TOC_REGISTER
|| TARGET_MINIMAL_TOC
|| TARGET_CMODEL != CMODEL_SMALL))
|| (TARGET_CMODEL != CMODEL_SMALL
- && GET_CODE (XEXP (x, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
- && REGNO (XEXP (XEXP (x, 0), 0)) == TOC_REGISTER
- && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH
+ && GET_CODE (XEXP (x, 0)) == CONST
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == REG
+ && REGNO (XEXP (XEXP (XEXP (x, 0), 0), 0)) == TOC_REGISTER
+ && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == HIGH
&& rtx_equal_p (XEXP (x, 1),
- XEXP (XEXP (XEXP (x, 0), 1), 0)))))
+ XEXP (XEXP (XEXP (XEXP (x, 0), 0), 1), 0)))))
{
y = XVECEXP (y, 0, 0);
+ if (offset != NULL_RTX)
+ y = gen_rtx_PLUS (Pmode, y, offset);
if (!MEM_P (orig_x))
return y;
else
if (TARGET_MACHO
&& GET_CODE (orig_x) == LO_SUM
- && GET_CODE (XEXP (x, 1)) == CONST)
+ && GET_CODE (XEXP (orig_x, 1)) == CONST)
{
- y = XEXP (XEXP (x, 1), 0);
+ y = XEXP (XEXP (orig_x, 1), 0);
if (GET_CODE (y) == UNSPEC
&& XINT (y, 1) == UNSPEC_MACHOPIC_OFFSET)
return XVECEXP (y, 0, 0);
return orig_x;
}
+/* Return true if X shouldn't be emitted into the debug info.
+ The linker doesn't like .toc section references from
+ .debug_* sections, so reject .toc section symbols. */
+
+static bool
+rs6000_const_not_ok_for_debug_p (rtx x)
+{
+ if (GET_CODE (x) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (x))
+ {
+ rtx c = get_pool_constant (x);
+ enum machine_mode cmode = get_pool_mode (x);
+ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (c, cmode))
+ return true;
+ }
+
+ return false;
+}
+
/* Construct the SYMBOL_REF for the tls_get_addr function. */
static GTY(()) rtx rs6000_tls_symbol;
lab = gen_label_rtx ();
emit_insn (gen_load_toc_v4_PIC_1b (gsym, lab));
emit_move_insn (tmp1, gen_rtx_REG (Pmode, LR_REGNO));
+ if (TARGET_LINK_STACK)
+ emit_insn (gen_addsi3 (tmp1, tmp1, GEN_INT (4)));
emit_move_insn (tmp2, mem);
last = emit_insn (gen_addsi3 (got, tmp1, tmp2));
set_unique_reg_note (last, REG_EQUAL, gsym);
if (model == TLS_MODEL_GLOBAL_DYNAMIC)
{
- r3 = gen_rtx_REG (Pmode, 3);
tga = rs6000_tls_get_addr ();
- emit_library_call_value (tga, dest, LCT_CONST, Pmode, 1, r3, Pmode);
+ emit_library_call_value (tga, dest, LCT_CONST, Pmode,
+ 1, const0_rtx, Pmode);
+ r3 = gen_rtx_REG (Pmode, 3);
if (DEFAULT_ABI == ABI_AIX && TARGET_64BIT)
insn = gen_tls_gd_aix64 (r3, got, addr, tga, const0_rtx);
else if (DEFAULT_ABI == ABI_AIX && !TARGET_64BIT)
}
else if (model == TLS_MODEL_LOCAL_DYNAMIC)
{
- r3 = gen_rtx_REG (Pmode, 3);
tga = rs6000_tls_get_addr ();
tmp1 = gen_reg_rtx (Pmode);
- emit_library_call_value (tga, tmp1, LCT_CONST, Pmode, 1, r3, Pmode);
+ emit_library_call_value (tga, tmp1, LCT_CONST, Pmode,
+ 1, const0_rtx, Pmode);
+ r3 = gen_rtx_REG (Pmode, 3);
if (DEFAULT_ABI == ABI_AIX && TARGET_64BIT)
insn = gen_tls_ld_aix64 (r3, got, tga, const0_rtx);
else if (DEFAULT_ABI == ABI_AIX && !TARGET_64BIT)
/* Return 1 if X contains a thread-local symbol. */
-bool
+static bool
rs6000_tls_referenced_p (rtx x)
{
if (! TARGET_HAVE_TLS)
return for_each_rtx (&x, &rs6000_tls_symbol_ref_1, 0);
}
+/* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
+
+static bool
+rs6000_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+ if (GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH)
+ return true;
+
+ return rs6000_tls_referenced_p (x);
+}
+
/* Return 1 if *X is a thread-local symbol. This is the same as
rs6000_tls_symbol_ref except for the type of the unused argument. */
{
bool reg_offset_p = reg_offset_addressing_ok_p (mode);
+ /* Nasty hack for vsx_splat_V2DF/V2DI load from mem, which takes a
+ DFmode/DImode MEM. */
+ if (reg_offset_p
+ && opnum == 1
+ && ((mode == DFmode && recog_data.operand_mode[0] == V2DFmode)
+ || (mode == DImode && recog_data.operand_mode[0] == V2DImode)))
+ reg_offset_p = false;
+
/* We must recognize output that we have already generated ourselves. */
if (GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
&& REGNO (XEXP (XEXP (x, 0), 0)) == TOC_REGISTER
- && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST
+ && GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 0)) == HIGH
&& GET_CODE (XEXP (x, 1)) == CONST
&& GET_CODE (XEXP (XEXP (x, 1), 0)) == UNSPEC
&& XINT (XEXP (XEXP (x, 1), 0), 1) == UNSPEC_TOCREL
- && rtx_equal_p (XEXP (XEXP (XEXP (x, 0), 1), 0), XEXP (x, 1)))
+ && rtx_equal_p (XEXP (XEXP (XEXP (XEXP (x, 0), 1), 0), 0), XEXP (x, 1)))
{
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
#if TARGET_MACHO
&& DEFAULT_ABI == ABI_DARWIN
&& (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
+ && machopic_symbol_defined_p (x)
#else
&& DEFAULT_ABI == ABI_V4
&& !flag_pic
return 1;
if (reg_offset_p && legitimate_small_data_p (mode, x))
return 1;
- if (reg_offset_p && legitimate_constant_pool_address_p (x, reg_ok_strict))
+ if (reg_offset_p
+ && legitimate_constant_pool_address_p (x, mode, reg_ok_strict))
return 1;
/* If not REG_OK_STRICT (before reload) let pass any stack offset. */
if (! reg_ok_strict
case LO_SUM:
/* Anything in the constant pool is sufficiently aligned that
all bytes have the same high part address. */
- return !legitimate_constant_pool_address_p (addr, false);
+ return !legitimate_constant_pool_address_p (addr, QImode, false);
/* Auto-increment cases are now treated generically in recog.c. */
case PRE_MODIFY:
if (GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) != REG
- && ! legitimate_constant_pool_address_p (XEXP (operands[0], 0), false))
+ && ! legitimate_constant_pool_address_p (XEXP (operands[0], 0),
+ GET_MODE (operands[0]), false))
operands[0]
= replace_equiv_address (operands[0],
copy_addr_to_reg (XEXP (operands[0], 0)));
if (GET_CODE (operands[1]) == MEM
&& GET_CODE (XEXP (operands[1], 0)) != REG
- && ! legitimate_constant_pool_address_p (XEXP (operands[1], 0), false))
+ && ! legitimate_constant_pool_address_p (XEXP (operands[1], 0),
+ GET_MODE (operands[1]), false))
operands[1]
= replace_equiv_address (operands[1],
copy_addr_to_reg (XEXP (operands[1], 0)));
}
-/* Return true if memory accesses to DECL are known to never straddle
- a 32k boundary. */
-
-static bool
-offsettable_ok_by_alignment (tree decl)
-{
- unsigned HOST_WIDE_INT dsize, dalign;
-
- /* Presume any compiler generated symbol_ref is suitably aligned. */
- if (!decl)
- return true;
-
- if (TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != PARM_DECL
- && TREE_CODE (decl) != RESULT_DECL
- && TREE_CODE (decl) != FIELD_DECL)
- return true;
-
- if (!DECL_SIZE_UNIT (decl))
- return false;
-
- if (!host_integerp (DECL_SIZE_UNIT (decl), 1))
- return false;
-
- dsize = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
- if (dsize <= 1)
- return true;
- if (dsize > 32768)
- return false;
-
- dalign = DECL_ALIGN_UNIT (decl);
- return dalign >= dsize;
-}
-
/* Emit a move from SOURCE to DEST in mode MODE. */
void
rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
if (!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
&& mode == TFmode && GET_CODE (operands[1]) == CONST_DOUBLE)
{
- /* DImode is used, not DFmode, because simplify_gen_subreg doesn't
- know how to get a DFmode SUBREG of a TFmode. */
- enum machine_mode imode = (TARGET_E500_DOUBLE ? DFmode : DImode);
- rs6000_emit_move (simplify_gen_subreg (imode, operands[0], mode, 0),
- simplify_gen_subreg (imode, operands[1], mode, 0),
- imode);
- rs6000_emit_move (simplify_gen_subreg (imode, operands[0], mode,
- GET_MODE_SIZE (imode)),
- simplify_gen_subreg (imode, operands[1], mode,
- GET_MODE_SIZE (imode)),
- imode);
+ rs6000_emit_move (simplify_gen_subreg (DFmode, operands[0], mode, 0),
+ simplify_gen_subreg (DFmode, operands[1], mode, 0),
+ DFmode);
+ rs6000_emit_move (simplify_gen_subreg (DFmode, operands[0], mode,
+ GET_MODE_SIZE (DFmode)),
+ simplify_gen_subreg (DFmode, operands[1], mode,
+ GET_MODE_SIZE (DFmode)),
+ DFmode);
return;
}
|| (TARGET_CMODEL == CMODEL_MEDIUM
&& GET_CODE (operands[1]) == SYMBOL_REF
&& !CONSTANT_POOL_ADDRESS_P (operands[1])
- && SYMBOL_REF_LOCAL_P (operands[1])
- && offsettable_ok_by_alignment (SYMBOL_REF_DECL (operands[1]))))
+ && SYMBOL_REF_LOCAL_P (operands[1])))
{
rtx reg = NULL_RTX;
if (TARGET_CMODEL != CMODEL_SMALL)
}
else if (mode == Pmode
&& CONSTANT_P (operands[1])
+ && GET_CODE (operands[1]) != HIGH
+ && !(TARGET_CMODEL != CMODEL_SMALL
+ && GET_CODE (operands[1]) == CONST
+ && GET_CODE (XEXP (operands[1], 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == HIGH)
&& ((GET_CODE (operands[1]) != CONST_INT
&& ! easy_fp_constant (operands[1], mode))
|| (GET_CODE (operands[1]) == CONST_INT
> (TARGET_CMODEL != CMODEL_SMALL ? 3 : 2)))
|| (GET_CODE (operands[0]) == REG
&& FP_REGNO_P (REGNO (operands[0]))))
- && GET_CODE (operands[1]) != HIGH
- && ! legitimate_constant_pool_address_p (operands[1], false)
+ && ! legitimate_constant_pool_address_p (operands[1], mode,
+ false)
&& ! toc_relative_expr_p (operands[1])
&& (TARGET_CMODEL == CMODEL_SMALL
|| can_create_pseudo_p ()
/* Nonzero if we can use an AltiVec register to pass this arg. */
#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE,NAMED) \
- ((ALTIVEC_VECTOR_MODE (MODE) || VSX_VECTOR_MODE (MODE)) \
+ (ALTIVEC_OR_VSX_VECTOR_MODE (MODE) \
&& (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \
&& TARGET_ALTIVEC_ABI \
&& (NAMED))
return true;
/* Interesting functions that we are emitting in this object file. */
- c_node = cgraph_node (fndecl);
+ c_node = cgraph_get_node (fndecl);
+ c_node = cgraph_function_or_thunk_node (c_node, NULL);
return !cgraph_only_called_directly_p (c_node);
}
return false;
}
if (SCALAR_FLOAT_MODE_P (return_mode))
rs6000_passes_float = true;
- else if (ALTIVEC_VECTOR_MODE (return_mode)
- || VSX_VECTOR_MODE (return_mode)
+ else if (ALTIVEC_OR_VSX_VECTOR_MODE (return_mode)
|| SPE_VECTOR_MODE (return_mode))
rs6000_passes_vector = true;
}
existing library interfaces.
Doubleword align SPE vectors.
- Quadword align Altivec vectors.
+ Quadword align Altivec/VSX vectors.
Quadword align large synthetic vector types. */
static unsigned int
&& int_size_in_bytes (type) >= 8
&& int_size_in_bytes (type) < 16))
return 64;
- else if ((ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode))
+ else if (ALTIVEC_OR_VSX_VECTOR_MODE (mode)
|| (type && TREE_CODE (type) == VECTOR_TYPE
&& int_size_in_bytes (type) >= 16))
return 128;
{
if (SCALAR_FLOAT_MODE_P (mode))
rs6000_passes_float = true;
- else if (named && (ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode)))
+ else if (named && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
rs6000_passes_vector = true;
else if (SPE_VECTOR_MODE (mode)
&& !cum->stdarg
#endif
if (TARGET_ALTIVEC_ABI
- && (ALTIVEC_VECTOR_MODE (mode)
- || VSX_VECTOR_MODE (mode)
+ && (ALTIVEC_OR_VSX_VECTOR_MODE (mode)
|| (type && TREE_CODE (type) == VECTOR_TYPE
&& int_size_in_bytes (type) == 16)))
{
}
static void
-rs6000_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+rs6000_function_arg_advance (cumulative_args_t cum, enum machine_mode mode,
const_tree type, bool named)
{
- rs6000_function_arg_advance_1 (cum, mode, type, named, 0);
+ rs6000_function_arg_advance_1 (get_cumulative_args (cum), mode, type, named,
+ 0);
}
static rtx
itself. */
static rtx
-rs6000_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+rs6000_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
const_tree type, bool named)
{
+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
enum rs6000_abi abi = DEFAULT_ABI;
/* Return a marker to indicate whether CR1 needs to set or clear the
: CALL_V4_CLEAR_FP_ARGS));
}
- return GEN_INT (cum->call_cookie);
+ return GEN_INT (cum->call_cookie & ~CALL_LIBCALL);
}
if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type))
else
return gen_rtx_REG (mode, cum->vregno);
else if (TARGET_ALTIVEC_ABI
- && (ALTIVEC_VECTOR_MODE (mode)
- || VSX_VECTOR_MODE (mode)
+ && (ALTIVEC_OR_VSX_VECTOR_MODE (mode)
|| (type && TREE_CODE (type) == VECTOR_TYPE
&& int_size_in_bytes (type) == 16)))
{
returns the number of bytes used by the first element of the PARALLEL. */
static int
-rs6000_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+rs6000_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode,
tree type, bool named)
{
+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
int ret = 0;
int align_words;
reference. */
static bool
-rs6000_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
+rs6000_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
enum machine_mode mode, const_tree type,
bool named ATTRIBUTE_UNUSED)
{
stack and set PRETEND_SIZE to the length of the registers pushed. */
static void
-setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+setup_incoming_varargs (cumulative_args_t cum, enum machine_mode mode,
tree type, int *pretend_size ATTRIBUTE_UNUSED,
int no_rtl)
{
alias_set_type set;
/* Skip the last named argument. */
- next_cum = *cum;
+ next_cum = *get_cumulative_args (cum);
rs6000_function_arg_advance_1 (&next_cum, mode, type, true, 0);
if (DEFAULT_ABI == ABI_V4)
/* Find the overflow area. */
t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
if (words != 0)
- t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (ovf), t,
- size_int (words * UNITS_PER_WORD));
+ t = fold_build_pointer_plus_hwi (t, words * UNITS_PER_WORD);
t = build2 (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
/* Find the register save area. */
t = make_tree (TREE_TYPE (sav), virtual_stack_vars_rtx);
if (cfun->machine->varargs_save_offset)
- t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (sav), t,
- size_int (cfun->machine->varargs_save_offset));
+ t = fold_build_pointer_plus_hwi (t, cfun->machine->varargs_save_offset);
t = build2 (MODIFY_EXPR, TREE_TYPE (sav), sav, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
/* This updates arg ptr by the amount that would be necessary
to align the zero-sized (but not zero-alignment) item. */
t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
- fold_build2 (POINTER_PLUS_EXPR,
- TREE_TYPE (valist),
- valist_tmp, size_int (boundary - 1)));
+ fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
gimplify_and_add (t, pre_p);
t = fold_convert (sizetype, valist_tmp);
t = sav;
if (sav_ofs)
- t = build2 (POINTER_PLUS_EXPR, ptr_type_node, sav, size_int (sav_ofs));
+ t = fold_build_pointer_plus_hwi (sav, sav_ofs);
u = build2 (POSTINCREMENT_EXPR, TREE_TYPE (reg), unshare_expr (reg),
build_int_cst (TREE_TYPE (reg), n_reg));
u = fold_convert (sizetype, u);
u = build2 (MULT_EXPR, sizetype, u, size_int (sav_scale));
- t = build2 (POINTER_PLUS_EXPR, ptr_type_node, t, u);
+ t = fold_build_pointer_plus (t, u);
/* _Decimal32 varargs are located in the second word of the 64-bit
FP register for 32-bit binaries. */
if (!TARGET_POWERPC64
&& TARGET_HARD_FLOAT && TARGET_FPRS
&& TYPE_MODE (type) == SDmode)
- t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t, size_int (size));
+ t = fold_build_pointer_plus_hwi (t, size);
gimplify_assign (addr, t, pre_p);
t = ovf;
if (align != 1)
{
- t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t, size_int (align - 1));
- t = fold_convert (sizetype, t);
+ t = fold_build_pointer_plus_hwi (t, align - 1);
t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
- size_int (-align));
- t = fold_convert (TREE_TYPE (ovf), t);
+ build_int_cst (TREE_TYPE (t), -align));
}
gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
gimplify_assign (unshare_expr (addr), t, pre_p);
- t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t, size_int (size));
+ t = fold_build_pointer_plus_hwi (t, size);
gimplify_assign (unshare_expr (ovf), t, pre_p);
if (lab_over)
tree tmp = create_tmp_var (type, "va_arg_tmp");
tree dest_addr = build_fold_addr_expr (tmp);
- tree copy = build_call_expr (implicit_built_in_decls[BUILT_IN_MEMCPY],
+ tree copy = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMCPY),
3, dest_addr, addr, size_int (rsize * 4));
gimplify_and_add (copy, pre_p);
/* Builtins. */
static void
-def_builtin (int mask, const char *name, tree type, int code)
+def_builtin (const char *name, tree type, enum rs6000_builtins code)
{
- if ((mask & target_flags) || TARGET_PAIRED_FLOAT)
- {
- tree t;
- if (rs6000_builtin_decls[code])
- fatal_error ("internal error: builtin function to %s already processed",
- name);
-
- rs6000_builtin_decls[code] = t =
- add_builtin_function (name, type, code, BUILT_IN_MD,
- NULL, NULL_TREE);
+ tree t;
+ unsigned classify = rs6000_builtin_info[(int)code].attr;
+ const char *attr_string = "";
- gcc_assert (code >= 0 && code < (int)RS6000_BUILTIN_COUNT);
- switch (builtin_classify[code])
- {
- default:
- gcc_unreachable ();
+ gcc_assert (name != NULL);
+ gcc_assert (IN_RANGE ((int)code, 0, (int)RS6000_BUILTIN_COUNT));
- /* assume builtin can do anything. */
- case RS6000_BTC_MISC:
- break;
+ if (rs6000_builtin_decls[(int)code])
+ fatal_error ("internal error: builtin function %s already processed", name);
- /* const function, function only depends on the inputs. */
- case RS6000_BTC_CONST:
- TREE_READONLY (t) = 1;
- TREE_NOTHROW (t) = 1;
- break;
+ rs6000_builtin_decls[(int)code] = t =
+ add_builtin_function (name, type, (int)code, BUILT_IN_MD, NULL, NULL_TREE);
- /* pure function, function can read global memory. */
- case RS6000_BTC_PURE:
+ /* Set any special attributes. */
+ if ((classify & RS6000_BTC_CONST) != 0)
+ {
+ /* const function, function only depends on the inputs. */
+ TREE_READONLY (t) = 1;
+ TREE_NOTHROW (t) = 1;
+ attr_string = ", pure";
+ }
+ else if ((classify & RS6000_BTC_PURE) != 0)
+ {
+ /* pure function, function can read global memory, but does not set any
+ external state. */
+ DECL_PURE_P (t) = 1;
+ TREE_NOTHROW (t) = 1;
+ attr_string = ", const";
+ }
+ else if ((classify & RS6000_BTC_FP) != 0)
+ {
+ /* Function is a math function. If rounding mode is on, then treat the
+ function as not reading global memory, but it can have arbitrary side
+ effects. If it is off, then assume the function is a const function.
+ This mimics the ATTR_MATHFN_FPROUNDING attribute in
+ builtin-attribute.def that is used for the math functions. */
+ TREE_NOTHROW (t) = 1;
+ if (flag_rounding_math)
+ {
DECL_PURE_P (t) = 1;
- TREE_NOTHROW (t) = 1;
- break;
-
- /* Function is a math function. If rounding mode is on, then treat
- the function as not reading global memory, but it can have
- arbitrary side effects. If it is off, then assume the function is
- a const function. This mimics the ATTR_MATHFN_FPROUNDING
- attribute in builtin-attribute.def that is used for the math
- functions. */
- case RS6000_BTC_FP_PURE:
- TREE_NOTHROW (t) = 1;
- if (flag_rounding_math)
- {
- DECL_PURE_P (t) = 1;
- DECL_IS_NOVOPS (t) = 1;
- }
- else
- TREE_READONLY (t) = 1;
- break;
+ DECL_IS_NOVOPS (t) = 1;
+ attr_string = ", fp, pure";
+ }
+ else
+ {
+ TREE_READONLY (t) = 1;
+ attr_string = ", fp, const";
}
}
+ else if ((classify & RS6000_BTC_ATTR_MASK) != 0)
+ gcc_unreachable ();
+
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr, "rs6000_builtin, code = %4d, %s%s\n",
+ (int)code, name, attr_string);
}
/* Simple ternary operations: VECd = foo (VECa, VECb, VECc). */
+#undef RS6000_BUILTIN_1
+#undef RS6000_BUILTIN_2
+#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_A
+#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_P
+#undef RS6000_BUILTIN_Q
+#undef RS6000_BUILTIN_S
+#undef RS6000_BUILTIN_X
+
+#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) \
+ { MASK, ICODE, NAME, ENUM },
+
+#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE)
+
static const struct builtin_description bdesc_3arg[] =
{
- { MASK_ALTIVEC, CODE_FOR_fmav4sf4, "__builtin_altivec_vmaddfp", ALTIVEC_BUILTIN_VMADDFP },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmhaddshs, "__builtin_altivec_vmhaddshs", ALTIVEC_BUILTIN_VMHADDSHS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmhraddshs, "__builtin_altivec_vmhraddshs", ALTIVEC_BUILTIN_VMHRADDSHS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmladduhm, "__builtin_altivec_vmladduhm", ALTIVEC_BUILTIN_VMLADDUHM},
- { MASK_ALTIVEC, CODE_FOR_altivec_vmsumubm, "__builtin_altivec_vmsumubm", ALTIVEC_BUILTIN_VMSUMUBM },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmsummbm, "__builtin_altivec_vmsummbm", ALTIVEC_BUILTIN_VMSUMMBM },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmsumuhm, "__builtin_altivec_vmsumuhm", ALTIVEC_BUILTIN_VMSUMUHM },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmsumshm, "__builtin_altivec_vmsumshm", ALTIVEC_BUILTIN_VMSUMSHM },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmsumuhs, "__builtin_altivec_vmsumuhs", ALTIVEC_BUILTIN_VMSUMUHS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmsumshs, "__builtin_altivec_vmsumshs", ALTIVEC_BUILTIN_VMSUMSHS },
- { MASK_ALTIVEC, CODE_FOR_nfmsv4sf4, "__builtin_altivec_vnmsubfp", ALTIVEC_BUILTIN_VNMSUBFP },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2df, "__builtin_altivec_vperm_2df", ALTIVEC_BUILTIN_VPERM_2DF },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2di, "__builtin_altivec_vperm_2di", ALTIVEC_BUILTIN_VPERM_2DI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4sf, "__builtin_altivec_vperm_4sf", ALTIVEC_BUILTIN_VPERM_4SF },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4si, "__builtin_altivec_vperm_4si", ALTIVEC_BUILTIN_VPERM_4SI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v8hi, "__builtin_altivec_vperm_8hi", ALTIVEC_BUILTIN_VPERM_8HI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v16qi_uns, "__builtin_altivec_vperm_16qi", ALTIVEC_BUILTIN_VPERM_16QI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v2di_uns, "__builtin_altivec_vperm_2di_uns", ALTIVEC_BUILTIN_VPERM_2DI_UNS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4si_uns, "__builtin_altivec_vperm_4si_uns", ALTIVEC_BUILTIN_VPERM_4SI_UNS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v8hi_uns, "__builtin_altivec_vperm_8hi_uns", ALTIVEC_BUILTIN_VPERM_8HI_UNS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v16qi_uns, "__builtin_altivec_vperm_16qi_uns", ALTIVEC_BUILTIN_VPERM_16QI_UNS },
- { MASK_ALTIVEC, CODE_FOR_vector_select_v4sf, "__builtin_altivec_vsel_4sf", ALTIVEC_BUILTIN_VSEL_4SF },
- { MASK_ALTIVEC, CODE_FOR_vector_select_v4si, "__builtin_altivec_vsel_4si", ALTIVEC_BUILTIN_VSEL_4SI },
- { MASK_ALTIVEC, CODE_FOR_vector_select_v8hi, "__builtin_altivec_vsel_8hi", ALTIVEC_BUILTIN_VSEL_8HI },
- { MASK_ALTIVEC, CODE_FOR_vector_select_v16qi, "__builtin_altivec_vsel_16qi", ALTIVEC_BUILTIN_VSEL_16QI },
- { MASK_ALTIVEC, CODE_FOR_vector_select_v2df, "__builtin_altivec_vsel_2df", ALTIVEC_BUILTIN_VSEL_2DF },
- { MASK_ALTIVEC, CODE_FOR_vector_select_v2di, "__builtin_altivec_vsel_2di", ALTIVEC_BUILTIN_VSEL_2DI },
- { MASK_ALTIVEC, CODE_FOR_vector_select_v4si_uns, "__builtin_altivec_vsel_4si_uns", ALTIVEC_BUILTIN_VSEL_4SI_UNS },
- { MASK_ALTIVEC, CODE_FOR_vector_select_v8hi_uns, "__builtin_altivec_vsel_8hi_uns", ALTIVEC_BUILTIN_VSEL_8HI_UNS },
- { MASK_ALTIVEC, CODE_FOR_vector_select_v16qi_uns, "__builtin_altivec_vsel_16qi_uns", ALTIVEC_BUILTIN_VSEL_16QI_UNS },
- { MASK_ALTIVEC, CODE_FOR_vector_select_v2di_uns, "__builtin_altivec_vsel_2di_uns", ALTIVEC_BUILTIN_VSEL_2DI_UNS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v16qi, "__builtin_altivec_vsldoi_16qi", ALTIVEC_BUILTIN_VSLDOI_16QI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v8hi, "__builtin_altivec_vsldoi_8hi", ALTIVEC_BUILTIN_VSLDOI_8HI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v4si, "__builtin_altivec_vsldoi_4si", ALTIVEC_BUILTIN_VSLDOI_4SI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v4sf, "__builtin_altivec_vsldoi_4sf", ALTIVEC_BUILTIN_VSLDOI_4SF },
-
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_madd", ALTIVEC_BUILTIN_VEC_MADD },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_madds", ALTIVEC_BUILTIN_VEC_MADDS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mladd", ALTIVEC_BUILTIN_VEC_MLADD },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mradds", ALTIVEC_BUILTIN_VEC_MRADDS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_msum", ALTIVEC_BUILTIN_VEC_MSUM },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsumshm", ALTIVEC_BUILTIN_VEC_VMSUMSHM },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsumuhm", ALTIVEC_BUILTIN_VEC_VMSUMUHM },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsummbm", ALTIVEC_BUILTIN_VEC_VMSUMMBM },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsumubm", ALTIVEC_BUILTIN_VEC_VMSUMUBM },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_msums", ALTIVEC_BUILTIN_VEC_MSUMS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsumshs", ALTIVEC_BUILTIN_VEC_VMSUMSHS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsumuhs", ALTIVEC_BUILTIN_VEC_VMSUMUHS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_nmsub", ALTIVEC_BUILTIN_VEC_NMSUB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_perm", ALTIVEC_BUILTIN_VEC_PERM },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sel", ALTIVEC_BUILTIN_VEC_SEL },
-
- { MASK_VSX, CODE_FOR_fmav2df4, "__builtin_vsx_xvmadddp", VSX_BUILTIN_XVMADDDP },
- { MASK_VSX, CODE_FOR_fmsv2df4, "__builtin_vsx_xvmsubdp", VSX_BUILTIN_XVMSUBDP },
- { MASK_VSX, CODE_FOR_nfmav2df4, "__builtin_vsx_xvnmadddp", VSX_BUILTIN_XVNMADDDP },
- { MASK_VSX, CODE_FOR_nfmsv2df4, "__builtin_vsx_xvnmsubdp", VSX_BUILTIN_XVNMSUBDP },
-
- { MASK_VSX, CODE_FOR_fmav4sf4, "__builtin_vsx_xvmaddsp", VSX_BUILTIN_XVMADDSP },
- { MASK_VSX, CODE_FOR_fmsv4sf4, "__builtin_vsx_xvmsubsp", VSX_BUILTIN_XVMSUBSP },
- { MASK_VSX, CODE_FOR_nfmav4sf4, "__builtin_vsx_xvnmaddsp", VSX_BUILTIN_XVNMADDSP },
- { MASK_VSX, CODE_FOR_nfmsv4sf4, "__builtin_vsx_xvnmsubsp", VSX_BUILTIN_XVNMSUBSP },
-
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_msub", VSX_BUILTIN_VEC_MSUB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_nmadd", VSX_BUILTIN_VEC_NMADD },
-
- { MASK_VSX, CODE_FOR_vector_select_v2di, "__builtin_vsx_xxsel_2di", VSX_BUILTIN_XXSEL_2DI },
- { MASK_VSX, CODE_FOR_vector_select_v2df, "__builtin_vsx_xxsel_2df", VSX_BUILTIN_XXSEL_2DF },
- { MASK_VSX, CODE_FOR_vector_select_v4sf, "__builtin_vsx_xxsel_4sf", VSX_BUILTIN_XXSEL_4SF },
- { MASK_VSX, CODE_FOR_vector_select_v4si, "__builtin_vsx_xxsel_4si", VSX_BUILTIN_XXSEL_4SI },
- { MASK_VSX, CODE_FOR_vector_select_v8hi, "__builtin_vsx_xxsel_8hi", VSX_BUILTIN_XXSEL_8HI },
- { MASK_VSX, CODE_FOR_vector_select_v16qi, "__builtin_vsx_xxsel_16qi", VSX_BUILTIN_XXSEL_16QI },
- { MASK_VSX, CODE_FOR_vector_select_v2di_uns, "__builtin_vsx_xxsel_2di_uns", VSX_BUILTIN_XXSEL_2DI_UNS },
- { MASK_VSX, CODE_FOR_vector_select_v4si_uns, "__builtin_vsx_xxsel_4si_uns", VSX_BUILTIN_XXSEL_4SI_UNS },
- { MASK_VSX, CODE_FOR_vector_select_v8hi_uns, "__builtin_vsx_xxsel_8hi_uns", VSX_BUILTIN_XXSEL_8HI_UNS },
- { MASK_VSX, CODE_FOR_vector_select_v16qi_uns, "__builtin_vsx_xxsel_16qi_uns", VSX_BUILTIN_XXSEL_16QI_UNS },
-
- { MASK_VSX, CODE_FOR_altivec_vperm_v2di, "__builtin_vsx_vperm_2di", VSX_BUILTIN_VPERM_2DI },
- { MASK_VSX, CODE_FOR_altivec_vperm_v2df, "__builtin_vsx_vperm_2df", VSX_BUILTIN_VPERM_2DF },
- { MASK_VSX, CODE_FOR_altivec_vperm_v4sf, "__builtin_vsx_vperm_4sf", VSX_BUILTIN_VPERM_4SF },
- { MASK_VSX, CODE_FOR_altivec_vperm_v4si, "__builtin_vsx_vperm_4si", VSX_BUILTIN_VPERM_4SI },
- { MASK_VSX, CODE_FOR_altivec_vperm_v8hi, "__builtin_vsx_vperm_8hi", VSX_BUILTIN_VPERM_8HI },
- { MASK_VSX, CODE_FOR_altivec_vperm_v16qi, "__builtin_vsx_vperm_16qi", VSX_BUILTIN_VPERM_16QI },
- { MASK_VSX, CODE_FOR_altivec_vperm_v2di_uns, "__builtin_vsx_vperm_2di_uns", VSX_BUILTIN_VPERM_2DI_UNS },
- { MASK_VSX, CODE_FOR_altivec_vperm_v4si_uns, "__builtin_vsx_vperm_4si_uns", VSX_BUILTIN_VPERM_4SI_UNS },
- { MASK_VSX, CODE_FOR_altivec_vperm_v8hi_uns, "__builtin_vsx_vperm_8hi_uns", VSX_BUILTIN_VPERM_8HI_UNS },
- { MASK_VSX, CODE_FOR_altivec_vperm_v16qi_uns, "__builtin_vsx_vperm_16qi_uns", VSX_BUILTIN_VPERM_16QI_UNS },
-
- { MASK_VSX, CODE_FOR_vsx_xxpermdi_v2df, "__builtin_vsx_xxpermdi_2df", VSX_BUILTIN_XXPERMDI_2DF },
- { MASK_VSX, CODE_FOR_vsx_xxpermdi_v2di, "__builtin_vsx_xxpermdi_2di", VSX_BUILTIN_XXPERMDI_2DI },
- { MASK_VSX, CODE_FOR_vsx_xxpermdi_v4sf, "__builtin_vsx_xxpermdi_4sf", VSX_BUILTIN_XXPERMDI_4SF },
- { MASK_VSX, CODE_FOR_vsx_xxpermdi_v4si, "__builtin_vsx_xxpermdi_4si", VSX_BUILTIN_XXPERMDI_4SI },
- { MASK_VSX, CODE_FOR_vsx_xxpermdi_v8hi, "__builtin_vsx_xxpermdi_8hi", VSX_BUILTIN_XXPERMDI_8HI },
- { MASK_VSX, CODE_FOR_vsx_xxpermdi_v16qi, "__builtin_vsx_xxpermdi_16qi", VSX_BUILTIN_XXPERMDI_16QI },
- { MASK_VSX, CODE_FOR_nothing, "__builtin_vsx_xxpermdi", VSX_BUILTIN_VEC_XXPERMDI },
- { MASK_VSX, CODE_FOR_vsx_set_v2df, "__builtin_vsx_set_2df", VSX_BUILTIN_SET_2DF },
- { MASK_VSX, CODE_FOR_vsx_set_v2di, "__builtin_vsx_set_2di", VSX_BUILTIN_SET_2DI },
-
- { MASK_VSX, CODE_FOR_vsx_xxsldwi_v2di, "__builtin_vsx_xxsldwi_2di", VSX_BUILTIN_XXSLDWI_2DI },
- { MASK_VSX, CODE_FOR_vsx_xxsldwi_v2df, "__builtin_vsx_xxsldwi_2df", VSX_BUILTIN_XXSLDWI_2DF },
- { MASK_VSX, CODE_FOR_vsx_xxsldwi_v4sf, "__builtin_vsx_xxsldwi_4sf", VSX_BUILTIN_XXSLDWI_4SF },
- { MASK_VSX, CODE_FOR_vsx_xxsldwi_v4si, "__builtin_vsx_xxsldwi_4si", VSX_BUILTIN_XXSLDWI_4SI },
- { MASK_VSX, CODE_FOR_vsx_xxsldwi_v8hi, "__builtin_vsx_xxsldwi_8hi", VSX_BUILTIN_XXSLDWI_8HI },
- { MASK_VSX, CODE_FOR_vsx_xxsldwi_v16qi, "__builtin_vsx_xxsldwi_16qi", VSX_BUILTIN_XXSLDWI_16QI },
- { MASK_VSX, CODE_FOR_nothing, "__builtin_vsx_xxsldwi", VSX_BUILTIN_VEC_XXSLDWI },
-
- { 0, CODE_FOR_fmsv2sf4, "__builtin_paired_msub", PAIRED_BUILTIN_MSUB },
- { 0, CODE_FOR_fmav2sf4, "__builtin_paired_madd", PAIRED_BUILTIN_MADD },
- { 0, CODE_FOR_paired_madds0, "__builtin_paired_madds0", PAIRED_BUILTIN_MADDS0 },
- { 0, CODE_FOR_paired_madds1, "__builtin_paired_madds1", PAIRED_BUILTIN_MADDS1 },
- { 0, CODE_FOR_nfmsv2sf4, "__builtin_paired_nmsub", PAIRED_BUILTIN_NMSUB },
- { 0, CODE_FOR_nfmav2sf4, "__builtin_paired_nmadd", PAIRED_BUILTIN_NMADD },
- { 0, CODE_FOR_paired_sum0, "__builtin_paired_sum0", PAIRED_BUILTIN_SUM0 },
- { 0, CODE_FOR_paired_sum1, "__builtin_paired_sum1", PAIRED_BUILTIN_SUM1 },
- { 0, CODE_FOR_selv2sf4, "__builtin_paired_selv2sf4", PAIRED_BUILTIN_SELV2SF4 },
+#include "rs6000-builtin.def"
};
/* DST operations: void foo (void *, const int, const char). */
+#undef RS6000_BUILTIN_1
+#undef RS6000_BUILTIN_2
+#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_A
+#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_P
+#undef RS6000_BUILTIN_Q
+#undef RS6000_BUILTIN_S
+#undef RS6000_BUILTIN_X
+
+#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) \
+ { MASK, ICODE, NAME, ENUM },
+
+#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE)
+
static const struct builtin_description bdesc_dst[] =
{
- { MASK_ALTIVEC, CODE_FOR_altivec_dst, "__builtin_altivec_dst", ALTIVEC_BUILTIN_DST },
- { MASK_ALTIVEC, CODE_FOR_altivec_dstt, "__builtin_altivec_dstt", ALTIVEC_BUILTIN_DSTT },
- { MASK_ALTIVEC, CODE_FOR_altivec_dstst, "__builtin_altivec_dstst", ALTIVEC_BUILTIN_DSTST },
- { MASK_ALTIVEC, CODE_FOR_altivec_dststt, "__builtin_altivec_dststt", ALTIVEC_BUILTIN_DSTSTT },
-
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_dst", ALTIVEC_BUILTIN_VEC_DST },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_dstt", ALTIVEC_BUILTIN_VEC_DSTT },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_dstst", ALTIVEC_BUILTIN_VEC_DSTST },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_dststt", ALTIVEC_BUILTIN_VEC_DSTSTT }
+#include "rs6000-builtin.def"
};
/* Simple binary operations: VECc = foo (VECa, VECb). */
-static struct builtin_description bdesc_2arg[] =
-{
- { MASK_ALTIVEC, CODE_FOR_addv16qi3, "__builtin_altivec_vaddubm", ALTIVEC_BUILTIN_VADDUBM },
- { MASK_ALTIVEC, CODE_FOR_addv8hi3, "__builtin_altivec_vadduhm", ALTIVEC_BUILTIN_VADDUHM },
- { MASK_ALTIVEC, CODE_FOR_addv4si3, "__builtin_altivec_vadduwm", ALTIVEC_BUILTIN_VADDUWM },
- { MASK_ALTIVEC, CODE_FOR_addv4sf3, "__builtin_altivec_vaddfp", ALTIVEC_BUILTIN_VADDFP },
- { MASK_ALTIVEC, CODE_FOR_altivec_vaddcuw, "__builtin_altivec_vaddcuw", ALTIVEC_BUILTIN_VADDCUW },
- { MASK_ALTIVEC, CODE_FOR_altivec_vaddubs, "__builtin_altivec_vaddubs", ALTIVEC_BUILTIN_VADDUBS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vaddsbs, "__builtin_altivec_vaddsbs", ALTIVEC_BUILTIN_VADDSBS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vadduhs, "__builtin_altivec_vadduhs", ALTIVEC_BUILTIN_VADDUHS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vaddshs, "__builtin_altivec_vaddshs", ALTIVEC_BUILTIN_VADDSHS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vadduws, "__builtin_altivec_vadduws", ALTIVEC_BUILTIN_VADDUWS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vaddsws, "__builtin_altivec_vaddsws", ALTIVEC_BUILTIN_VADDSWS },
- { MASK_ALTIVEC, CODE_FOR_andv4si3, "__builtin_altivec_vand", ALTIVEC_BUILTIN_VAND },
- { MASK_ALTIVEC, CODE_FOR_andcv4si3, "__builtin_altivec_vandc", ALTIVEC_BUILTIN_VANDC },
- { MASK_ALTIVEC, CODE_FOR_altivec_vavgub, "__builtin_altivec_vavgub", ALTIVEC_BUILTIN_VAVGUB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vavgsb, "__builtin_altivec_vavgsb", ALTIVEC_BUILTIN_VAVGSB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vavguh, "__builtin_altivec_vavguh", ALTIVEC_BUILTIN_VAVGUH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vavgsh, "__builtin_altivec_vavgsh", ALTIVEC_BUILTIN_VAVGSH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vavguw, "__builtin_altivec_vavguw", ALTIVEC_BUILTIN_VAVGUW },
- { MASK_ALTIVEC, CODE_FOR_altivec_vavgsw, "__builtin_altivec_vavgsw", ALTIVEC_BUILTIN_VAVGSW },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcfux, "__builtin_altivec_vcfux", ALTIVEC_BUILTIN_VCFUX },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcfsx, "__builtin_altivec_vcfsx", ALTIVEC_BUILTIN_VCFSX },
- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpbfp, "__builtin_altivec_vcmpbfp", ALTIVEC_BUILTIN_VCMPBFP },
- { MASK_ALTIVEC, CODE_FOR_vector_eqv16qi, "__builtin_altivec_vcmpequb", ALTIVEC_BUILTIN_VCMPEQUB },
- { MASK_ALTIVEC, CODE_FOR_vector_eqv8hi, "__builtin_altivec_vcmpequh", ALTIVEC_BUILTIN_VCMPEQUH },
- { MASK_ALTIVEC, CODE_FOR_vector_eqv4si, "__builtin_altivec_vcmpequw", ALTIVEC_BUILTIN_VCMPEQUW },
- { MASK_ALTIVEC, CODE_FOR_vector_eqv4sf, "__builtin_altivec_vcmpeqfp", ALTIVEC_BUILTIN_VCMPEQFP },
- { MASK_ALTIVEC, CODE_FOR_vector_gev4sf, "__builtin_altivec_vcmpgefp", ALTIVEC_BUILTIN_VCMPGEFP },
- { MASK_ALTIVEC, CODE_FOR_vector_gtuv16qi, "__builtin_altivec_vcmpgtub", ALTIVEC_BUILTIN_VCMPGTUB },
- { MASK_ALTIVEC, CODE_FOR_vector_gtv16qi, "__builtin_altivec_vcmpgtsb", ALTIVEC_BUILTIN_VCMPGTSB },
- { MASK_ALTIVEC, CODE_FOR_vector_gtuv8hi, "__builtin_altivec_vcmpgtuh", ALTIVEC_BUILTIN_VCMPGTUH },
- { MASK_ALTIVEC, CODE_FOR_vector_gtv8hi, "__builtin_altivec_vcmpgtsh", ALTIVEC_BUILTIN_VCMPGTSH },
- { MASK_ALTIVEC, CODE_FOR_vector_gtuv4si, "__builtin_altivec_vcmpgtuw", ALTIVEC_BUILTIN_VCMPGTUW },
- { MASK_ALTIVEC, CODE_FOR_vector_gtv4si, "__builtin_altivec_vcmpgtsw", ALTIVEC_BUILTIN_VCMPGTSW },
- { MASK_ALTIVEC, CODE_FOR_vector_gtv4sf, "__builtin_altivec_vcmpgtfp", ALTIVEC_BUILTIN_VCMPGTFP },
- { MASK_ALTIVEC, CODE_FOR_altivec_vctsxs, "__builtin_altivec_vctsxs", ALTIVEC_BUILTIN_VCTSXS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vctuxs, "__builtin_altivec_vctuxs", ALTIVEC_BUILTIN_VCTUXS },
- { MASK_ALTIVEC, CODE_FOR_umaxv16qi3, "__builtin_altivec_vmaxub", ALTIVEC_BUILTIN_VMAXUB },
- { MASK_ALTIVEC, CODE_FOR_smaxv16qi3, "__builtin_altivec_vmaxsb", ALTIVEC_BUILTIN_VMAXSB },
- { MASK_ALTIVEC, CODE_FOR_umaxv8hi3, "__builtin_altivec_vmaxuh", ALTIVEC_BUILTIN_VMAXUH },
- { MASK_ALTIVEC, CODE_FOR_smaxv8hi3, "__builtin_altivec_vmaxsh", ALTIVEC_BUILTIN_VMAXSH },
- { MASK_ALTIVEC, CODE_FOR_umaxv4si3, "__builtin_altivec_vmaxuw", ALTIVEC_BUILTIN_VMAXUW },
- { MASK_ALTIVEC, CODE_FOR_smaxv4si3, "__builtin_altivec_vmaxsw", ALTIVEC_BUILTIN_VMAXSW },
- { MASK_ALTIVEC, CODE_FOR_smaxv4sf3, "__builtin_altivec_vmaxfp", ALTIVEC_BUILTIN_VMAXFP },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmrghb, "__builtin_altivec_vmrghb", ALTIVEC_BUILTIN_VMRGHB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmrghh, "__builtin_altivec_vmrghh", ALTIVEC_BUILTIN_VMRGHH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmrghw, "__builtin_altivec_vmrghw", ALTIVEC_BUILTIN_VMRGHW },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmrglb, "__builtin_altivec_vmrglb", ALTIVEC_BUILTIN_VMRGLB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmrglh, "__builtin_altivec_vmrglh", ALTIVEC_BUILTIN_VMRGLH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmrglw, "__builtin_altivec_vmrglw", ALTIVEC_BUILTIN_VMRGLW },
- { MASK_ALTIVEC, CODE_FOR_uminv16qi3, "__builtin_altivec_vminub", ALTIVEC_BUILTIN_VMINUB },
- { MASK_ALTIVEC, CODE_FOR_sminv16qi3, "__builtin_altivec_vminsb", ALTIVEC_BUILTIN_VMINSB },
- { MASK_ALTIVEC, CODE_FOR_uminv8hi3, "__builtin_altivec_vminuh", ALTIVEC_BUILTIN_VMINUH },
- { MASK_ALTIVEC, CODE_FOR_sminv8hi3, "__builtin_altivec_vminsh", ALTIVEC_BUILTIN_VMINSH },
- { MASK_ALTIVEC, CODE_FOR_uminv4si3, "__builtin_altivec_vminuw", ALTIVEC_BUILTIN_VMINUW },
- { MASK_ALTIVEC, CODE_FOR_sminv4si3, "__builtin_altivec_vminsw", ALTIVEC_BUILTIN_VMINSW },
- { MASK_ALTIVEC, CODE_FOR_sminv4sf3, "__builtin_altivec_vminfp", ALTIVEC_BUILTIN_VMINFP },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmuleub, "__builtin_altivec_vmuleub", ALTIVEC_BUILTIN_VMULEUB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmuleub, "__builtin_altivec_vmuleub_uns", ALTIVEC_BUILTIN_VMULEUB_UNS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmulesb, "__builtin_altivec_vmulesb", ALTIVEC_BUILTIN_VMULESB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmuleuh, "__builtin_altivec_vmuleuh", ALTIVEC_BUILTIN_VMULEUH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmuleuh, "__builtin_altivec_vmuleuh_uns", ALTIVEC_BUILTIN_VMULEUH_UNS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmulesh, "__builtin_altivec_vmulesh", ALTIVEC_BUILTIN_VMULESH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmuloub, "__builtin_altivec_vmuloub", ALTIVEC_BUILTIN_VMULOUB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmuloub, "__builtin_altivec_vmuloub_uns", ALTIVEC_BUILTIN_VMULOUB_UNS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmulosb, "__builtin_altivec_vmulosb", ALTIVEC_BUILTIN_VMULOSB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmulouh, "__builtin_altivec_vmulouh", ALTIVEC_BUILTIN_VMULOUH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmulouh, "__builtin_altivec_vmulouh_uns", ALTIVEC_BUILTIN_VMULOUH_UNS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vmulosh, "__builtin_altivec_vmulosh", ALTIVEC_BUILTIN_VMULOSH },
- { MASK_ALTIVEC, CODE_FOR_norv4si3, "__builtin_altivec_vnor", ALTIVEC_BUILTIN_VNOR },
- { MASK_ALTIVEC, CODE_FOR_iorv4si3, "__builtin_altivec_vor", ALTIVEC_BUILTIN_VOR },
- { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhum, "__builtin_altivec_vpkuhum", ALTIVEC_BUILTIN_VPKUHUM },
- { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum, "__builtin_altivec_vpkuwum", ALTIVEC_BUILTIN_VPKUWUM },
- { MASK_ALTIVEC, CODE_FOR_altivec_vpkpx, "__builtin_altivec_vpkpx", ALTIVEC_BUILTIN_VPKPX },
- { MASK_ALTIVEC, CODE_FOR_altivec_vpkshss, "__builtin_altivec_vpkshss", ALTIVEC_BUILTIN_VPKSHSS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vpkswss, "__builtin_altivec_vpkswss", ALTIVEC_BUILTIN_VPKSWSS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhus, "__builtin_altivec_vpkuhus", ALTIVEC_BUILTIN_VPKUHUS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vpkshus, "__builtin_altivec_vpkshus", ALTIVEC_BUILTIN_VPKSHUS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwus, "__builtin_altivec_vpkuwus", ALTIVEC_BUILTIN_VPKUWUS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vpkswus, "__builtin_altivec_vpkswus", ALTIVEC_BUILTIN_VPKSWUS },
- { MASK_ALTIVEC, CODE_FOR_recipv4sf3, "__builtin_altivec_vrecipdivfp", ALTIVEC_BUILTIN_VRECIPFP },
- { MASK_ALTIVEC, CODE_FOR_vrotlv16qi3, "__builtin_altivec_vrlb", ALTIVEC_BUILTIN_VRLB },
- { MASK_ALTIVEC, CODE_FOR_vrotlv8hi3, "__builtin_altivec_vrlh", ALTIVEC_BUILTIN_VRLH },
- { MASK_ALTIVEC, CODE_FOR_vrotlv4si3, "__builtin_altivec_vrlw", ALTIVEC_BUILTIN_VRLW },
- { MASK_ALTIVEC, CODE_FOR_vashlv16qi3, "__builtin_altivec_vslb", ALTIVEC_BUILTIN_VSLB },
- { MASK_ALTIVEC, CODE_FOR_vashlv8hi3, "__builtin_altivec_vslh", ALTIVEC_BUILTIN_VSLH },
- { MASK_ALTIVEC, CODE_FOR_vashlv4si3, "__builtin_altivec_vslw", ALTIVEC_BUILTIN_VSLW },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsl, "__builtin_altivec_vsl", ALTIVEC_BUILTIN_VSL },
- { MASK_ALTIVEC, CODE_FOR_altivec_vslo, "__builtin_altivec_vslo", ALTIVEC_BUILTIN_VSLO },
- { MASK_ALTIVEC, CODE_FOR_altivec_vspltb, "__builtin_altivec_vspltb", ALTIVEC_BUILTIN_VSPLTB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsplth, "__builtin_altivec_vsplth", ALTIVEC_BUILTIN_VSPLTH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vspltw, "__builtin_altivec_vspltw", ALTIVEC_BUILTIN_VSPLTW },
- { MASK_ALTIVEC, CODE_FOR_vlshrv16qi3, "__builtin_altivec_vsrb", ALTIVEC_BUILTIN_VSRB },
- { MASK_ALTIVEC, CODE_FOR_vlshrv8hi3, "__builtin_altivec_vsrh", ALTIVEC_BUILTIN_VSRH },
- { MASK_ALTIVEC, CODE_FOR_vlshrv4si3, "__builtin_altivec_vsrw", ALTIVEC_BUILTIN_VSRW },
- { MASK_ALTIVEC, CODE_FOR_vashrv16qi3, "__builtin_altivec_vsrab", ALTIVEC_BUILTIN_VSRAB },
- { MASK_ALTIVEC, CODE_FOR_vashrv8hi3, "__builtin_altivec_vsrah", ALTIVEC_BUILTIN_VSRAH },
- { MASK_ALTIVEC, CODE_FOR_vashrv4si3, "__builtin_altivec_vsraw", ALTIVEC_BUILTIN_VSRAW },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsr, "__builtin_altivec_vsr", ALTIVEC_BUILTIN_VSR },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsro, "__builtin_altivec_vsro", ALTIVEC_BUILTIN_VSRO },
- { MASK_ALTIVEC, CODE_FOR_subv16qi3, "__builtin_altivec_vsububm", ALTIVEC_BUILTIN_VSUBUBM },
- { MASK_ALTIVEC, CODE_FOR_subv8hi3, "__builtin_altivec_vsubuhm", ALTIVEC_BUILTIN_VSUBUHM },
- { MASK_ALTIVEC, CODE_FOR_subv4si3, "__builtin_altivec_vsubuwm", ALTIVEC_BUILTIN_VSUBUWM },
- { MASK_ALTIVEC, CODE_FOR_subv4sf3, "__builtin_altivec_vsubfp", ALTIVEC_BUILTIN_VSUBFP },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsubcuw, "__builtin_altivec_vsubcuw", ALTIVEC_BUILTIN_VSUBCUW },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsububs, "__builtin_altivec_vsububs", ALTIVEC_BUILTIN_VSUBUBS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsubsbs, "__builtin_altivec_vsubsbs", ALTIVEC_BUILTIN_VSUBSBS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsubuhs, "__builtin_altivec_vsubuhs", ALTIVEC_BUILTIN_VSUBUHS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsubshs, "__builtin_altivec_vsubshs", ALTIVEC_BUILTIN_VSUBSHS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsubuws, "__builtin_altivec_vsubuws", ALTIVEC_BUILTIN_VSUBUWS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsubsws, "__builtin_altivec_vsubsws", ALTIVEC_BUILTIN_VSUBSWS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsum4ubs, "__builtin_altivec_vsum4ubs", ALTIVEC_BUILTIN_VSUM4UBS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsum4sbs, "__builtin_altivec_vsum4sbs", ALTIVEC_BUILTIN_VSUM4SBS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsum4shs, "__builtin_altivec_vsum4shs", ALTIVEC_BUILTIN_VSUM4SHS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsum2sws, "__builtin_altivec_vsum2sws", ALTIVEC_BUILTIN_VSUM2SWS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsumsws, "__builtin_altivec_vsumsws", ALTIVEC_BUILTIN_VSUMSWS },
- { MASK_ALTIVEC, CODE_FOR_xorv4si3, "__builtin_altivec_vxor", ALTIVEC_BUILTIN_VXOR },
- { MASK_ALTIVEC, CODE_FOR_vector_copysignv4sf3, "__builtin_altivec_copysignfp", ALTIVEC_BUILTIN_COPYSIGN_V4SF },
-
- { MASK_VSX, CODE_FOR_addv2df3, "__builtin_vsx_xvadddp", VSX_BUILTIN_XVADDDP },
- { MASK_VSX, CODE_FOR_subv2df3, "__builtin_vsx_xvsubdp", VSX_BUILTIN_XVSUBDP },
- { MASK_VSX, CODE_FOR_mulv2df3, "__builtin_vsx_xvmuldp", VSX_BUILTIN_XVMULDP },
- { MASK_VSX, CODE_FOR_divv2df3, "__builtin_vsx_xvdivdp", VSX_BUILTIN_XVDIVDP },
- { MASK_VSX, CODE_FOR_recipv2df3, "__builtin_vsx_xvrecipdivdp", VSX_BUILTIN_RECIP_V2DF },
- { MASK_VSX, CODE_FOR_sminv2df3, "__builtin_vsx_xvmindp", VSX_BUILTIN_XVMINDP },
- { MASK_VSX, CODE_FOR_smaxv2df3, "__builtin_vsx_xvmaxdp", VSX_BUILTIN_XVMAXDP },
- { MASK_VSX, CODE_FOR_vsx_tdivv2df3_fe, "__builtin_vsx_xvtdivdp_fe", VSX_BUILTIN_XVTDIVDP_FE },
- { MASK_VSX, CODE_FOR_vsx_tdivv2df3_fg, "__builtin_vsx_xvtdivdp_fg", VSX_BUILTIN_XVTDIVDP_FG },
- { MASK_VSX, CODE_FOR_vector_eqv2df, "__builtin_vsx_xvcmpeqdp", VSX_BUILTIN_XVCMPEQDP },
- { MASK_VSX, CODE_FOR_vector_gtv2df, "__builtin_vsx_xvcmpgtdp", VSX_BUILTIN_XVCMPGTDP },
- { MASK_VSX, CODE_FOR_vector_gev2df, "__builtin_vsx_xvcmpgedp", VSX_BUILTIN_XVCMPGEDP },
-
- { MASK_VSX, CODE_FOR_addv4sf3, "__builtin_vsx_xvaddsp", VSX_BUILTIN_XVADDSP },
- { MASK_VSX, CODE_FOR_subv4sf3, "__builtin_vsx_xvsubsp", VSX_BUILTIN_XVSUBSP },
- { MASK_VSX, CODE_FOR_mulv4sf3, "__builtin_vsx_xvmulsp", VSX_BUILTIN_XVMULSP },
- { MASK_VSX, CODE_FOR_divv4sf3, "__builtin_vsx_xvdivsp", VSX_BUILTIN_XVDIVSP },
- { MASK_VSX, CODE_FOR_recipv4sf3, "__builtin_vsx_xvrecipdivsp", VSX_BUILTIN_RECIP_V4SF },
- { MASK_VSX, CODE_FOR_sminv4sf3, "__builtin_vsx_xvminsp", VSX_BUILTIN_XVMINSP },
- { MASK_VSX, CODE_FOR_smaxv4sf3, "__builtin_vsx_xvmaxsp", VSX_BUILTIN_XVMAXSP },
- { MASK_VSX, CODE_FOR_vsx_tdivv4sf3_fe, "__builtin_vsx_xvtdivsp_fe", VSX_BUILTIN_XVTDIVSP_FE },
- { MASK_VSX, CODE_FOR_vsx_tdivv4sf3_fg, "__builtin_vsx_xvtdivsp_fg", VSX_BUILTIN_XVTDIVSP_FG },
- { MASK_VSX, CODE_FOR_vector_eqv4sf, "__builtin_vsx_xvcmpeqsp", VSX_BUILTIN_XVCMPEQSP },
- { MASK_VSX, CODE_FOR_vector_gtv4sf, "__builtin_vsx_xvcmpgtsp", VSX_BUILTIN_XVCMPGTSP },
- { MASK_VSX, CODE_FOR_vector_gev4sf, "__builtin_vsx_xvcmpgesp", VSX_BUILTIN_XVCMPGESP },
-
- { MASK_VSX, CODE_FOR_smindf3, "__builtin_vsx_xsmindp", VSX_BUILTIN_XSMINDP },
- { MASK_VSX, CODE_FOR_smaxdf3, "__builtin_vsx_xsmaxdp", VSX_BUILTIN_XSMAXDP },
- { MASK_VSX, CODE_FOR_vsx_tdivdf3_fe, "__builtin_vsx_xstdivdp_fe", VSX_BUILTIN_XSTDIVDP_FE },
- { MASK_VSX, CODE_FOR_vsx_tdivdf3_fg, "__builtin_vsx_xstdivdp_fg", VSX_BUILTIN_XSTDIVDP_FG },
- { MASK_VSX, CODE_FOR_vector_copysignv2df3, "__builtin_vsx_cpsgndp", VSX_BUILTIN_CPSGNDP },
- { MASK_VSX, CODE_FOR_vector_copysignv4sf3, "__builtin_vsx_cpsgnsp", VSX_BUILTIN_CPSGNSP },
-
- { MASK_VSX, CODE_FOR_vsx_concat_v2df, "__builtin_vsx_concat_2df", VSX_BUILTIN_CONCAT_2DF },
- { MASK_VSX, CODE_FOR_vsx_concat_v2di, "__builtin_vsx_concat_2di", VSX_BUILTIN_CONCAT_2DI },
- { MASK_VSX, CODE_FOR_vsx_splat_v2df, "__builtin_vsx_splat_2df", VSX_BUILTIN_SPLAT_2DF },
- { MASK_VSX, CODE_FOR_vsx_splat_v2di, "__builtin_vsx_splat_2di", VSX_BUILTIN_SPLAT_2DI },
- { MASK_VSX, CODE_FOR_vsx_xxmrghw_v4sf, "__builtin_vsx_xxmrghw", VSX_BUILTIN_XXMRGHW_4SF },
- { MASK_VSX, CODE_FOR_vsx_xxmrghw_v4si, "__builtin_vsx_xxmrghw_4si", VSX_BUILTIN_XXMRGHW_4SI },
- { MASK_VSX, CODE_FOR_vsx_xxmrglw_v4sf, "__builtin_vsx_xxmrglw", VSX_BUILTIN_XXMRGLW_4SF },
- { MASK_VSX, CODE_FOR_vsx_xxmrglw_v4si, "__builtin_vsx_xxmrglw_4si", VSX_BUILTIN_XXMRGLW_4SI },
- { MASK_VSX, CODE_FOR_vec_interleave_lowv2df, "__builtin_vsx_mergel_2df", VSX_BUILTIN_VEC_MERGEL_V2DF },
- { MASK_VSX, CODE_FOR_vec_interleave_lowv2di, "__builtin_vsx_mergel_2di", VSX_BUILTIN_VEC_MERGEL_V2DI },
- { MASK_VSX, CODE_FOR_vec_interleave_highv2df, "__builtin_vsx_mergeh_2df", VSX_BUILTIN_VEC_MERGEH_V2DF },
- { MASK_VSX, CODE_FOR_vec_interleave_highv2di, "__builtin_vsx_mergeh_2di", VSX_BUILTIN_VEC_MERGEH_V2DI },
-
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_add", ALTIVEC_BUILTIN_VEC_ADD },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vaddfp", ALTIVEC_BUILTIN_VEC_VADDFP },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduwm", ALTIVEC_BUILTIN_VEC_VADDUWM },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduhm", ALTIVEC_BUILTIN_VEC_VADDUHM },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddubm", ALTIVEC_BUILTIN_VEC_VADDUBM },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_addc", ALTIVEC_BUILTIN_VEC_ADDC },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_adds", ALTIVEC_BUILTIN_VEC_ADDS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddsws", ALTIVEC_BUILTIN_VEC_VADDSWS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduws", ALTIVEC_BUILTIN_VEC_VADDUWS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddshs", ALTIVEC_BUILTIN_VEC_VADDSHS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduhs", ALTIVEC_BUILTIN_VEC_VADDUHS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddsbs", ALTIVEC_BUILTIN_VEC_VADDSBS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddubs", ALTIVEC_BUILTIN_VEC_VADDUBS },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_and", ALTIVEC_BUILTIN_VEC_AND },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_andc", ALTIVEC_BUILTIN_VEC_ANDC },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_avg", ALTIVEC_BUILTIN_VEC_AVG },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavgsw", ALTIVEC_BUILTIN_VEC_VAVGSW },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavguw", ALTIVEC_BUILTIN_VEC_VAVGUW },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavgsh", ALTIVEC_BUILTIN_VEC_VAVGSH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavguh", ALTIVEC_BUILTIN_VEC_VAVGUH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavgsb", ALTIVEC_BUILTIN_VEC_VAVGSB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavgub", ALTIVEC_BUILTIN_VEC_VAVGUB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmpb", ALTIVEC_BUILTIN_VEC_CMPB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmpeq", ALTIVEC_BUILTIN_VEC_CMPEQ },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpeqfp", ALTIVEC_BUILTIN_VEC_VCMPEQFP },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpequw", ALTIVEC_BUILTIN_VEC_VCMPEQUW },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpequh", ALTIVEC_BUILTIN_VEC_VCMPEQUH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpequb", ALTIVEC_BUILTIN_VEC_VCMPEQUB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmpge", ALTIVEC_BUILTIN_VEC_CMPGE },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmpgt", ALTIVEC_BUILTIN_VEC_CMPGT },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtfp", ALTIVEC_BUILTIN_VEC_VCMPGTFP },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtsw", ALTIVEC_BUILTIN_VEC_VCMPGTSW },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtuw", ALTIVEC_BUILTIN_VEC_VCMPGTUW },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtsh", ALTIVEC_BUILTIN_VEC_VCMPGTSH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtuh", ALTIVEC_BUILTIN_VEC_VCMPGTUH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtsb", ALTIVEC_BUILTIN_VEC_VCMPGTSB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtub", ALTIVEC_BUILTIN_VEC_VCMPGTUB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmple", ALTIVEC_BUILTIN_VEC_CMPLE },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmplt", ALTIVEC_BUILTIN_VEC_CMPLT },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_copysign", ALTIVEC_BUILTIN_VEC_COPYSIGN },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_max", ALTIVEC_BUILTIN_VEC_MAX },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vmaxfp", ALTIVEC_BUILTIN_VEC_VMAXFP },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxsw", ALTIVEC_BUILTIN_VEC_VMAXSW },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxuw", ALTIVEC_BUILTIN_VEC_VMAXUW },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxsh", ALTIVEC_BUILTIN_VEC_VMAXSH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxuh", ALTIVEC_BUILTIN_VEC_VMAXUH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxsb", ALTIVEC_BUILTIN_VEC_VMAXSB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxub", ALTIVEC_BUILTIN_VEC_VMAXUB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mergeh", ALTIVEC_BUILTIN_VEC_MERGEH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrghw", ALTIVEC_BUILTIN_VEC_VMRGHW },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrghh", ALTIVEC_BUILTIN_VEC_VMRGHH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrghb", ALTIVEC_BUILTIN_VEC_VMRGHB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mergel", ALTIVEC_BUILTIN_VEC_MERGEL },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglw", ALTIVEC_BUILTIN_VEC_VMRGLW },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglh", ALTIVEC_BUILTIN_VEC_VMRGLH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglb", ALTIVEC_BUILTIN_VEC_VMRGLB },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_min", ALTIVEC_BUILTIN_VEC_MIN },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vminfp", ALTIVEC_BUILTIN_VEC_VMINFP },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminsw", ALTIVEC_BUILTIN_VEC_VMINSW },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminuw", ALTIVEC_BUILTIN_VEC_VMINUW },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminsh", ALTIVEC_BUILTIN_VEC_VMINSH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminuh", ALTIVEC_BUILTIN_VEC_VMINUH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminsb", ALTIVEC_BUILTIN_VEC_VMINSB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminub", ALTIVEC_BUILTIN_VEC_VMINUB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mule", ALTIVEC_BUILTIN_VEC_MULE },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmuleub", ALTIVEC_BUILTIN_VEC_VMULEUB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulesb", ALTIVEC_BUILTIN_VEC_VMULESB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmuleuh", ALTIVEC_BUILTIN_VEC_VMULEUH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulesh", ALTIVEC_BUILTIN_VEC_VMULESH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mulo", ALTIVEC_BUILTIN_VEC_MULO },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulosh", ALTIVEC_BUILTIN_VEC_VMULOSH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulouh", ALTIVEC_BUILTIN_VEC_VMULOUH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulosb", ALTIVEC_BUILTIN_VEC_VMULOSB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmuloub", ALTIVEC_BUILTIN_VEC_VMULOUB },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_nor", ALTIVEC_BUILTIN_VEC_NOR },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_or", ALTIVEC_BUILTIN_VEC_OR },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_pack", ALTIVEC_BUILTIN_VEC_PACK },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuwum", ALTIVEC_BUILTIN_VEC_VPKUWUM },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuhum", ALTIVEC_BUILTIN_VEC_VPKUHUM },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_packpx", ALTIVEC_BUILTIN_VEC_PACKPX },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_packs", ALTIVEC_BUILTIN_VEC_PACKS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkswss", ALTIVEC_BUILTIN_VEC_VPKSWSS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuwus", ALTIVEC_BUILTIN_VEC_VPKUWUS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkshss", ALTIVEC_BUILTIN_VEC_VPKSHSS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuhus", ALTIVEC_BUILTIN_VEC_VPKUHUS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_packsu", ALTIVEC_BUILTIN_VEC_PACKSU },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkswus", ALTIVEC_BUILTIN_VEC_VPKSWUS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkshus", ALTIVEC_BUILTIN_VEC_VPKSHUS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_recipdiv", ALTIVEC_BUILTIN_VEC_RECIP },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_rl", ALTIVEC_BUILTIN_VEC_RL },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vrlw", ALTIVEC_BUILTIN_VEC_VRLW },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vrlh", ALTIVEC_BUILTIN_VEC_VRLH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vrlb", ALTIVEC_BUILTIN_VEC_VRLB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sl", ALTIVEC_BUILTIN_VEC_SL },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vslw", ALTIVEC_BUILTIN_VEC_VSLW },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vslh", ALTIVEC_BUILTIN_VEC_VSLH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vslb", ALTIVEC_BUILTIN_VEC_VSLB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sll", ALTIVEC_BUILTIN_VEC_SLL },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_slo", ALTIVEC_BUILTIN_VEC_SLO },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sr", ALTIVEC_BUILTIN_VEC_SR },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrw", ALTIVEC_BUILTIN_VEC_VSRW },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrh", ALTIVEC_BUILTIN_VEC_VSRH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrb", ALTIVEC_BUILTIN_VEC_VSRB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sra", ALTIVEC_BUILTIN_VEC_SRA },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsraw", ALTIVEC_BUILTIN_VEC_VSRAW },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrah", ALTIVEC_BUILTIN_VEC_VSRAH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrab", ALTIVEC_BUILTIN_VEC_VSRAB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_srl", ALTIVEC_BUILTIN_VEC_SRL },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sro", ALTIVEC_BUILTIN_VEC_SRO },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_sub", ALTIVEC_BUILTIN_VEC_SUB },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vsubfp", ALTIVEC_BUILTIN_VEC_VSUBFP },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuwm", ALTIVEC_BUILTIN_VEC_VSUBUWM },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuhm", ALTIVEC_BUILTIN_VEC_VSUBUHM },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsububm", ALTIVEC_BUILTIN_VEC_VSUBUBM },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_subc", ALTIVEC_BUILTIN_VEC_SUBC },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_subs", ALTIVEC_BUILTIN_VEC_SUBS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubsws", ALTIVEC_BUILTIN_VEC_VSUBSWS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuws", ALTIVEC_BUILTIN_VEC_VSUBUWS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubshs", ALTIVEC_BUILTIN_VEC_VSUBSHS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuhs", ALTIVEC_BUILTIN_VEC_VSUBUHS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubsbs", ALTIVEC_BUILTIN_VEC_VSUBSBS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsububs", ALTIVEC_BUILTIN_VEC_VSUBUBS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sum4s", ALTIVEC_BUILTIN_VEC_SUM4S },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsum4shs", ALTIVEC_BUILTIN_VEC_VSUM4SHS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsum4sbs", ALTIVEC_BUILTIN_VEC_VSUM4SBS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsum4ubs", ALTIVEC_BUILTIN_VEC_VSUM4UBS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sum2s", ALTIVEC_BUILTIN_VEC_SUM2S },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sums", ALTIVEC_BUILTIN_VEC_SUMS },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_xor", ALTIVEC_BUILTIN_VEC_XOR },
-
- { MASK_VSX, CODE_FOR_nothing, "__builtin_vec_mul", VSX_BUILTIN_VEC_MUL },
- { MASK_VSX, CODE_FOR_nothing, "__builtin_vec_div", VSX_BUILTIN_VEC_DIV },
-
- { 0, CODE_FOR_paired_divv2sf3, "__builtin_paired_divv2sf3", PAIRED_BUILTIN_DIVV2SF3 },
- { 0, CODE_FOR_paired_addv2sf3, "__builtin_paired_addv2sf3", PAIRED_BUILTIN_ADDV2SF3 },
- { 0, CODE_FOR_paired_subv2sf3, "__builtin_paired_subv2sf3", PAIRED_BUILTIN_SUBV2SF3 },
- { 0, CODE_FOR_paired_mulv2sf3, "__builtin_paired_mulv2sf3", PAIRED_BUILTIN_MULV2SF3 },
- { 0, CODE_FOR_paired_muls0, "__builtin_paired_muls0", PAIRED_BUILTIN_MULS0 },
- { 0, CODE_FOR_paired_muls1, "__builtin_paired_muls1", PAIRED_BUILTIN_MULS1 },
- { 0, CODE_FOR_paired_merge00, "__builtin_paired_merge00", PAIRED_BUILTIN_MERGE00 },
- { 0, CODE_FOR_paired_merge01, "__builtin_paired_merge01", PAIRED_BUILTIN_MERGE01 },
- { 0, CODE_FOR_paired_merge10, "__builtin_paired_merge10", PAIRED_BUILTIN_MERGE10 },
- { 0, CODE_FOR_paired_merge11, "__builtin_paired_merge11", PAIRED_BUILTIN_MERGE11 },
-
- /* Place holder, leave as first spe builtin. */
- { 0, CODE_FOR_addv2si3, "__builtin_spe_evaddw", SPE_BUILTIN_EVADDW },
- { 0, CODE_FOR_andv2si3, "__builtin_spe_evand", SPE_BUILTIN_EVAND },
- { 0, CODE_FOR_spe_evandc, "__builtin_spe_evandc", SPE_BUILTIN_EVANDC },
- { 0, CODE_FOR_divv2si3, "__builtin_spe_evdivws", SPE_BUILTIN_EVDIVWS },
- { 0, CODE_FOR_spe_evdivwu, "__builtin_spe_evdivwu", SPE_BUILTIN_EVDIVWU },
- { 0, CODE_FOR_spe_eveqv, "__builtin_spe_eveqv", SPE_BUILTIN_EVEQV },
- { 0, CODE_FOR_spe_evfsadd, "__builtin_spe_evfsadd", SPE_BUILTIN_EVFSADD },
- { 0, CODE_FOR_spe_evfsdiv, "__builtin_spe_evfsdiv", SPE_BUILTIN_EVFSDIV },
- { 0, CODE_FOR_spe_evfsmul, "__builtin_spe_evfsmul", SPE_BUILTIN_EVFSMUL },
- { 0, CODE_FOR_spe_evfssub, "__builtin_spe_evfssub", SPE_BUILTIN_EVFSSUB },
- { 0, CODE_FOR_spe_evmergehi, "__builtin_spe_evmergehi", SPE_BUILTIN_EVMERGEHI },
- { 0, CODE_FOR_spe_evmergehilo, "__builtin_spe_evmergehilo", SPE_BUILTIN_EVMERGEHILO },
- { 0, CODE_FOR_spe_evmergelo, "__builtin_spe_evmergelo", SPE_BUILTIN_EVMERGELO },
- { 0, CODE_FOR_spe_evmergelohi, "__builtin_spe_evmergelohi", SPE_BUILTIN_EVMERGELOHI },
- { 0, CODE_FOR_spe_evmhegsmfaa, "__builtin_spe_evmhegsmfaa", SPE_BUILTIN_EVMHEGSMFAA },
- { 0, CODE_FOR_spe_evmhegsmfan, "__builtin_spe_evmhegsmfan", SPE_BUILTIN_EVMHEGSMFAN },
- { 0, CODE_FOR_spe_evmhegsmiaa, "__builtin_spe_evmhegsmiaa", SPE_BUILTIN_EVMHEGSMIAA },
- { 0, CODE_FOR_spe_evmhegsmian, "__builtin_spe_evmhegsmian", SPE_BUILTIN_EVMHEGSMIAN },
- { 0, CODE_FOR_spe_evmhegumiaa, "__builtin_spe_evmhegumiaa", SPE_BUILTIN_EVMHEGUMIAA },
- { 0, CODE_FOR_spe_evmhegumian, "__builtin_spe_evmhegumian", SPE_BUILTIN_EVMHEGUMIAN },
- { 0, CODE_FOR_spe_evmhesmf, "__builtin_spe_evmhesmf", SPE_BUILTIN_EVMHESMF },
- { 0, CODE_FOR_spe_evmhesmfa, "__builtin_spe_evmhesmfa", SPE_BUILTIN_EVMHESMFA },
- { 0, CODE_FOR_spe_evmhesmfaaw, "__builtin_spe_evmhesmfaaw", SPE_BUILTIN_EVMHESMFAAW },
- { 0, CODE_FOR_spe_evmhesmfanw, "__builtin_spe_evmhesmfanw", SPE_BUILTIN_EVMHESMFANW },
- { 0, CODE_FOR_spe_evmhesmi, "__builtin_spe_evmhesmi", SPE_BUILTIN_EVMHESMI },
- { 0, CODE_FOR_spe_evmhesmia, "__builtin_spe_evmhesmia", SPE_BUILTIN_EVMHESMIA },
- { 0, CODE_FOR_spe_evmhesmiaaw, "__builtin_spe_evmhesmiaaw", SPE_BUILTIN_EVMHESMIAAW },
- { 0, CODE_FOR_spe_evmhesmianw, "__builtin_spe_evmhesmianw", SPE_BUILTIN_EVMHESMIANW },
- { 0, CODE_FOR_spe_evmhessf, "__builtin_spe_evmhessf", SPE_BUILTIN_EVMHESSF },
- { 0, CODE_FOR_spe_evmhessfa, "__builtin_spe_evmhessfa", SPE_BUILTIN_EVMHESSFA },
- { 0, CODE_FOR_spe_evmhessfaaw, "__builtin_spe_evmhessfaaw", SPE_BUILTIN_EVMHESSFAAW },
- { 0, CODE_FOR_spe_evmhessfanw, "__builtin_spe_evmhessfanw", SPE_BUILTIN_EVMHESSFANW },
- { 0, CODE_FOR_spe_evmhessiaaw, "__builtin_spe_evmhessiaaw", SPE_BUILTIN_EVMHESSIAAW },
- { 0, CODE_FOR_spe_evmhessianw, "__builtin_spe_evmhessianw", SPE_BUILTIN_EVMHESSIANW },
- { 0, CODE_FOR_spe_evmheumi, "__builtin_spe_evmheumi", SPE_BUILTIN_EVMHEUMI },
- { 0, CODE_FOR_spe_evmheumia, "__builtin_spe_evmheumia", SPE_BUILTIN_EVMHEUMIA },
- { 0, CODE_FOR_spe_evmheumiaaw, "__builtin_spe_evmheumiaaw", SPE_BUILTIN_EVMHEUMIAAW },
- { 0, CODE_FOR_spe_evmheumianw, "__builtin_spe_evmheumianw", SPE_BUILTIN_EVMHEUMIANW },
- { 0, CODE_FOR_spe_evmheusiaaw, "__builtin_spe_evmheusiaaw", SPE_BUILTIN_EVMHEUSIAAW },
- { 0, CODE_FOR_spe_evmheusianw, "__builtin_spe_evmheusianw", SPE_BUILTIN_EVMHEUSIANW },
- { 0, CODE_FOR_spe_evmhogsmfaa, "__builtin_spe_evmhogsmfaa", SPE_BUILTIN_EVMHOGSMFAA },
- { 0, CODE_FOR_spe_evmhogsmfan, "__builtin_spe_evmhogsmfan", SPE_BUILTIN_EVMHOGSMFAN },
- { 0, CODE_FOR_spe_evmhogsmiaa, "__builtin_spe_evmhogsmiaa", SPE_BUILTIN_EVMHOGSMIAA },
- { 0, CODE_FOR_spe_evmhogsmian, "__builtin_spe_evmhogsmian", SPE_BUILTIN_EVMHOGSMIAN },
- { 0, CODE_FOR_spe_evmhogumiaa, "__builtin_spe_evmhogumiaa", SPE_BUILTIN_EVMHOGUMIAA },
- { 0, CODE_FOR_spe_evmhogumian, "__builtin_spe_evmhogumian", SPE_BUILTIN_EVMHOGUMIAN },
- { 0, CODE_FOR_spe_evmhosmf, "__builtin_spe_evmhosmf", SPE_BUILTIN_EVMHOSMF },
- { 0, CODE_FOR_spe_evmhosmfa, "__builtin_spe_evmhosmfa", SPE_BUILTIN_EVMHOSMFA },
- { 0, CODE_FOR_spe_evmhosmfaaw, "__builtin_spe_evmhosmfaaw", SPE_BUILTIN_EVMHOSMFAAW },
- { 0, CODE_FOR_spe_evmhosmfanw, "__builtin_spe_evmhosmfanw", SPE_BUILTIN_EVMHOSMFANW },
- { 0, CODE_FOR_spe_evmhosmi, "__builtin_spe_evmhosmi", SPE_BUILTIN_EVMHOSMI },
- { 0, CODE_FOR_spe_evmhosmia, "__builtin_spe_evmhosmia", SPE_BUILTIN_EVMHOSMIA },
- { 0, CODE_FOR_spe_evmhosmiaaw, "__builtin_spe_evmhosmiaaw", SPE_BUILTIN_EVMHOSMIAAW },
- { 0, CODE_FOR_spe_evmhosmianw, "__builtin_spe_evmhosmianw", SPE_BUILTIN_EVMHOSMIANW },
- { 0, CODE_FOR_spe_evmhossf, "__builtin_spe_evmhossf", SPE_BUILTIN_EVMHOSSF },
- { 0, CODE_FOR_spe_evmhossfa, "__builtin_spe_evmhossfa", SPE_BUILTIN_EVMHOSSFA },
- { 0, CODE_FOR_spe_evmhossfaaw, "__builtin_spe_evmhossfaaw", SPE_BUILTIN_EVMHOSSFAAW },
- { 0, CODE_FOR_spe_evmhossfanw, "__builtin_spe_evmhossfanw", SPE_BUILTIN_EVMHOSSFANW },
- { 0, CODE_FOR_spe_evmhossiaaw, "__builtin_spe_evmhossiaaw", SPE_BUILTIN_EVMHOSSIAAW },
- { 0, CODE_FOR_spe_evmhossianw, "__builtin_spe_evmhossianw", SPE_BUILTIN_EVMHOSSIANW },
- { 0, CODE_FOR_spe_evmhoumi, "__builtin_spe_evmhoumi", SPE_BUILTIN_EVMHOUMI },
- { 0, CODE_FOR_spe_evmhoumia, "__builtin_spe_evmhoumia", SPE_BUILTIN_EVMHOUMIA },
- { 0, CODE_FOR_spe_evmhoumiaaw, "__builtin_spe_evmhoumiaaw", SPE_BUILTIN_EVMHOUMIAAW },
- { 0, CODE_FOR_spe_evmhoumianw, "__builtin_spe_evmhoumianw", SPE_BUILTIN_EVMHOUMIANW },
- { 0, CODE_FOR_spe_evmhousiaaw, "__builtin_spe_evmhousiaaw", SPE_BUILTIN_EVMHOUSIAAW },
- { 0, CODE_FOR_spe_evmhousianw, "__builtin_spe_evmhousianw", SPE_BUILTIN_EVMHOUSIANW },
- { 0, CODE_FOR_spe_evmwhsmf, "__builtin_spe_evmwhsmf", SPE_BUILTIN_EVMWHSMF },
- { 0, CODE_FOR_spe_evmwhsmfa, "__builtin_spe_evmwhsmfa", SPE_BUILTIN_EVMWHSMFA },
- { 0, CODE_FOR_spe_evmwhsmi, "__builtin_spe_evmwhsmi", SPE_BUILTIN_EVMWHSMI },
- { 0, CODE_FOR_spe_evmwhsmia, "__builtin_spe_evmwhsmia", SPE_BUILTIN_EVMWHSMIA },
- { 0, CODE_FOR_spe_evmwhssf, "__builtin_spe_evmwhssf", SPE_BUILTIN_EVMWHSSF },
- { 0, CODE_FOR_spe_evmwhssfa, "__builtin_spe_evmwhssfa", SPE_BUILTIN_EVMWHSSFA },
- { 0, CODE_FOR_spe_evmwhumi, "__builtin_spe_evmwhumi", SPE_BUILTIN_EVMWHUMI },
- { 0, CODE_FOR_spe_evmwhumia, "__builtin_spe_evmwhumia", SPE_BUILTIN_EVMWHUMIA },
- { 0, CODE_FOR_spe_evmwlsmiaaw, "__builtin_spe_evmwlsmiaaw", SPE_BUILTIN_EVMWLSMIAAW },
- { 0, CODE_FOR_spe_evmwlsmianw, "__builtin_spe_evmwlsmianw", SPE_BUILTIN_EVMWLSMIANW },
- { 0, CODE_FOR_spe_evmwlssiaaw, "__builtin_spe_evmwlssiaaw", SPE_BUILTIN_EVMWLSSIAAW },
- { 0, CODE_FOR_spe_evmwlssianw, "__builtin_spe_evmwlssianw", SPE_BUILTIN_EVMWLSSIANW },
- { 0, CODE_FOR_spe_evmwlumi, "__builtin_spe_evmwlumi", SPE_BUILTIN_EVMWLUMI },
- { 0, CODE_FOR_spe_evmwlumia, "__builtin_spe_evmwlumia", SPE_BUILTIN_EVMWLUMIA },
- { 0, CODE_FOR_spe_evmwlumiaaw, "__builtin_spe_evmwlumiaaw", SPE_BUILTIN_EVMWLUMIAAW },
- { 0, CODE_FOR_spe_evmwlumianw, "__builtin_spe_evmwlumianw", SPE_BUILTIN_EVMWLUMIANW },
- { 0, CODE_FOR_spe_evmwlusiaaw, "__builtin_spe_evmwlusiaaw", SPE_BUILTIN_EVMWLUSIAAW },
- { 0, CODE_FOR_spe_evmwlusianw, "__builtin_spe_evmwlusianw", SPE_BUILTIN_EVMWLUSIANW },
- { 0, CODE_FOR_spe_evmwsmf, "__builtin_spe_evmwsmf", SPE_BUILTIN_EVMWSMF },
- { 0, CODE_FOR_spe_evmwsmfa, "__builtin_spe_evmwsmfa", SPE_BUILTIN_EVMWSMFA },
- { 0, CODE_FOR_spe_evmwsmfaa, "__builtin_spe_evmwsmfaa", SPE_BUILTIN_EVMWSMFAA },
- { 0, CODE_FOR_spe_evmwsmfan, "__builtin_spe_evmwsmfan", SPE_BUILTIN_EVMWSMFAN },
- { 0, CODE_FOR_spe_evmwsmi, "__builtin_spe_evmwsmi", SPE_BUILTIN_EVMWSMI },
- { 0, CODE_FOR_spe_evmwsmia, "__builtin_spe_evmwsmia", SPE_BUILTIN_EVMWSMIA },
- { 0, CODE_FOR_spe_evmwsmiaa, "__builtin_spe_evmwsmiaa", SPE_BUILTIN_EVMWSMIAA },
- { 0, CODE_FOR_spe_evmwsmian, "__builtin_spe_evmwsmian", SPE_BUILTIN_EVMWSMIAN },
- { 0, CODE_FOR_spe_evmwssf, "__builtin_spe_evmwssf", SPE_BUILTIN_EVMWSSF },
- { 0, CODE_FOR_spe_evmwssfa, "__builtin_spe_evmwssfa", SPE_BUILTIN_EVMWSSFA },
- { 0, CODE_FOR_spe_evmwssfaa, "__builtin_spe_evmwssfaa", SPE_BUILTIN_EVMWSSFAA },
- { 0, CODE_FOR_spe_evmwssfan, "__builtin_spe_evmwssfan", SPE_BUILTIN_EVMWSSFAN },
- { 0, CODE_FOR_spe_evmwumi, "__builtin_spe_evmwumi", SPE_BUILTIN_EVMWUMI },
- { 0, CODE_FOR_spe_evmwumia, "__builtin_spe_evmwumia", SPE_BUILTIN_EVMWUMIA },
- { 0, CODE_FOR_spe_evmwumiaa, "__builtin_spe_evmwumiaa", SPE_BUILTIN_EVMWUMIAA },
- { 0, CODE_FOR_spe_evmwumian, "__builtin_spe_evmwumian", SPE_BUILTIN_EVMWUMIAN },
- { 0, CODE_FOR_spe_evnand, "__builtin_spe_evnand", SPE_BUILTIN_EVNAND },
- { 0, CODE_FOR_spe_evnor, "__builtin_spe_evnor", SPE_BUILTIN_EVNOR },
- { 0, CODE_FOR_spe_evor, "__builtin_spe_evor", SPE_BUILTIN_EVOR },
- { 0, CODE_FOR_spe_evorc, "__builtin_spe_evorc", SPE_BUILTIN_EVORC },
- { 0, CODE_FOR_spe_evrlw, "__builtin_spe_evrlw", SPE_BUILTIN_EVRLW },
- { 0, CODE_FOR_spe_evslw, "__builtin_spe_evslw", SPE_BUILTIN_EVSLW },
- { 0, CODE_FOR_spe_evsrws, "__builtin_spe_evsrws", SPE_BUILTIN_EVSRWS },
- { 0, CODE_FOR_spe_evsrwu, "__builtin_spe_evsrwu", SPE_BUILTIN_EVSRWU },
- { 0, CODE_FOR_subv2si3, "__builtin_spe_evsubfw", SPE_BUILTIN_EVSUBFW },
-
- /* SPE binary operations expecting a 5-bit unsigned literal. */
- { 0, CODE_FOR_spe_evaddiw, "__builtin_spe_evaddiw", SPE_BUILTIN_EVADDIW },
-
- { 0, CODE_FOR_spe_evrlwi, "__builtin_spe_evrlwi", SPE_BUILTIN_EVRLWI },
- { 0, CODE_FOR_spe_evslwi, "__builtin_spe_evslwi", SPE_BUILTIN_EVSLWI },
- { 0, CODE_FOR_spe_evsrwis, "__builtin_spe_evsrwis", SPE_BUILTIN_EVSRWIS },
- { 0, CODE_FOR_spe_evsrwiu, "__builtin_spe_evsrwiu", SPE_BUILTIN_EVSRWIU },
- { 0, CODE_FOR_spe_evsubifw, "__builtin_spe_evsubifw", SPE_BUILTIN_EVSUBIFW },
- { 0, CODE_FOR_spe_evmwhssfaa, "__builtin_spe_evmwhssfaa", SPE_BUILTIN_EVMWHSSFAA },
- { 0, CODE_FOR_spe_evmwhssmaa, "__builtin_spe_evmwhssmaa", SPE_BUILTIN_EVMWHSSMAA },
- { 0, CODE_FOR_spe_evmwhsmfaa, "__builtin_spe_evmwhsmfaa", SPE_BUILTIN_EVMWHSMFAA },
- { 0, CODE_FOR_spe_evmwhsmiaa, "__builtin_spe_evmwhsmiaa", SPE_BUILTIN_EVMWHSMIAA },
- { 0, CODE_FOR_spe_evmwhusiaa, "__builtin_spe_evmwhusiaa", SPE_BUILTIN_EVMWHUSIAA },
- { 0, CODE_FOR_spe_evmwhumiaa, "__builtin_spe_evmwhumiaa", SPE_BUILTIN_EVMWHUMIAA },
- { 0, CODE_FOR_spe_evmwhssfan, "__builtin_spe_evmwhssfan", SPE_BUILTIN_EVMWHSSFAN },
- { 0, CODE_FOR_spe_evmwhssian, "__builtin_spe_evmwhssian", SPE_BUILTIN_EVMWHSSIAN },
- { 0, CODE_FOR_spe_evmwhsmfan, "__builtin_spe_evmwhsmfan", SPE_BUILTIN_EVMWHSMFAN },
- { 0, CODE_FOR_spe_evmwhsmian, "__builtin_spe_evmwhsmian", SPE_BUILTIN_EVMWHSMIAN },
- { 0, CODE_FOR_spe_evmwhusian, "__builtin_spe_evmwhusian", SPE_BUILTIN_EVMWHUSIAN },
- { 0, CODE_FOR_spe_evmwhumian, "__builtin_spe_evmwhumian", SPE_BUILTIN_EVMWHUMIAN },
- { 0, CODE_FOR_spe_evmwhgssfaa, "__builtin_spe_evmwhgssfaa", SPE_BUILTIN_EVMWHGSSFAA },
- { 0, CODE_FOR_spe_evmwhgsmfaa, "__builtin_spe_evmwhgsmfaa", SPE_BUILTIN_EVMWHGSMFAA },
- { 0, CODE_FOR_spe_evmwhgsmiaa, "__builtin_spe_evmwhgsmiaa", SPE_BUILTIN_EVMWHGSMIAA },
- { 0, CODE_FOR_spe_evmwhgumiaa, "__builtin_spe_evmwhgumiaa", SPE_BUILTIN_EVMWHGUMIAA },
- { 0, CODE_FOR_spe_evmwhgssfan, "__builtin_spe_evmwhgssfan", SPE_BUILTIN_EVMWHGSSFAN },
- { 0, CODE_FOR_spe_evmwhgsmfan, "__builtin_spe_evmwhgsmfan", SPE_BUILTIN_EVMWHGSMFAN },
- { 0, CODE_FOR_spe_evmwhgsmian, "__builtin_spe_evmwhgsmian", SPE_BUILTIN_EVMWHGSMIAN },
- { 0, CODE_FOR_spe_evmwhgumian, "__builtin_spe_evmwhgumian", SPE_BUILTIN_EVMWHGUMIAN },
- { 0, CODE_FOR_spe_brinc, "__builtin_spe_brinc", SPE_BUILTIN_BRINC },
-
- /* Place-holder. Leave as last binary SPE builtin. */
- { 0, CODE_FOR_xorv2si3, "__builtin_spe_evxor", SPE_BUILTIN_EVXOR }
+#undef RS6000_BUILTIN_1
+#undef RS6000_BUILTIN_2
+#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_A
+#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_P
+#undef RS6000_BUILTIN_Q
+#undef RS6000_BUILTIN_S
+#undef RS6000_BUILTIN_X
+
+#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) \
+ { MASK, ICODE, NAME, ENUM },
+
+#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE)
+
+static const struct builtin_description bdesc_2arg[] =
+{
+#include "rs6000-builtin.def"
};
+#undef RS6000_BUILTIN_1
+#undef RS6000_BUILTIN_2
+#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_A
+#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_P
+#undef RS6000_BUILTIN_Q
+#undef RS6000_BUILTIN_S
+#undef RS6000_BUILTIN_X
+
+#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) \
+ { MASK, ICODE, NAME, ENUM },
+
+#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE)
+
/* AltiVec predicates. */
-struct builtin_description_predicates
+static const struct builtin_description bdesc_altivec_preds[] =
{
- const unsigned int mask;
- const enum insn_code icode;
- const char *const name;
- const enum rs6000_builtins code;
-};
-
-static const struct builtin_description_predicates bdesc_altivec_preds[] =
-{
- { MASK_ALTIVEC, CODE_FOR_altivec_vcmpbfp_p, "__builtin_altivec_vcmpbfp_p",
- ALTIVEC_BUILTIN_VCMPBFP_P },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_vector_eq_v4sf_p,
- "__builtin_altivec_vcmpeqfp_p", ALTIVEC_BUILTIN_VCMPEQFP_P },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_vector_ge_v4sf_p,
- "__builtin_altivec_vcmpgefp_p", ALTIVEC_BUILTIN_VCMPGEFP_P },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_vector_gt_v4sf_p,
- "__builtin_altivec_vcmpgtfp_p", ALTIVEC_BUILTIN_VCMPGTFP_P },
- { MASK_ALTIVEC, CODE_FOR_vector_eq_v4si_p, "__builtin_altivec_vcmpequw_p",
- ALTIVEC_BUILTIN_VCMPEQUW_P },
- { MASK_ALTIVEC, CODE_FOR_vector_gt_v4si_p, "__builtin_altivec_vcmpgtsw_p",
- ALTIVEC_BUILTIN_VCMPGTSW_P },
- { MASK_ALTIVEC, CODE_FOR_vector_gtu_v4si_p, "__builtin_altivec_vcmpgtuw_p",
- ALTIVEC_BUILTIN_VCMPGTUW_P },
- { MASK_ALTIVEC, CODE_FOR_vector_eq_v8hi_p, "__builtin_altivec_vcmpequh_p",
- ALTIVEC_BUILTIN_VCMPEQUH_P },
- { MASK_ALTIVEC, CODE_FOR_vector_gt_v8hi_p, "__builtin_altivec_vcmpgtsh_p",
- ALTIVEC_BUILTIN_VCMPGTSH_P },
- { MASK_ALTIVEC, CODE_FOR_vector_gtu_v8hi_p, "__builtin_altivec_vcmpgtuh_p",
- ALTIVEC_BUILTIN_VCMPGTUH_P },
- { MASK_ALTIVEC, CODE_FOR_vector_eq_v16qi_p, "__builtin_altivec_vcmpequb_p",
- ALTIVEC_BUILTIN_VCMPEQUB_P },
- { MASK_ALTIVEC, CODE_FOR_vector_gt_v16qi_p, "__builtin_altivec_vcmpgtsb_p",
- ALTIVEC_BUILTIN_VCMPGTSB_P },
- { MASK_ALTIVEC, CODE_FOR_vector_gtu_v16qi_p, "__builtin_altivec_vcmpgtub_p",
- ALTIVEC_BUILTIN_VCMPGTUB_P },
-
- { MASK_VSX, CODE_FOR_vector_eq_v4sf_p, "__builtin_vsx_xvcmpeqsp_p",
- VSX_BUILTIN_XVCMPEQSP_P },
- { MASK_VSX, CODE_FOR_vector_ge_v4sf_p, "__builtin_vsx_xvcmpgesp_p",
- VSX_BUILTIN_XVCMPGESP_P },
- { MASK_VSX, CODE_FOR_vector_gt_v4sf_p, "__builtin_vsx_xvcmpgtsp_p",
- VSX_BUILTIN_XVCMPGTSP_P },
- { MASK_VSX, CODE_FOR_vector_eq_v2df_p, "__builtin_vsx_xvcmpeqdp_p",
- VSX_BUILTIN_XVCMPEQDP_P },
- { MASK_VSX, CODE_FOR_vector_ge_v2df_p, "__builtin_vsx_xvcmpgedp_p",
- VSX_BUILTIN_XVCMPGEDP_P },
- { MASK_VSX, CODE_FOR_vector_gt_v2df_p, "__builtin_vsx_xvcmpgtdp_p",
- VSX_BUILTIN_XVCMPGTDP_P },
-
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vcmpeq_p",
- ALTIVEC_BUILTIN_VCMPEQ_P },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vcmpgt_p",
- ALTIVEC_BUILTIN_VCMPGT_P },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vcmpge_p",
- ALTIVEC_BUILTIN_VCMPGE_P }
+#include "rs6000-builtin.def"
};
/* SPE predicates. */
-static struct builtin_description bdesc_spe_predicates[] =
-{
- /* Place-holder. Leave as first. */
- { 0, CODE_FOR_spe_evcmpeq, "__builtin_spe_evcmpeq", SPE_BUILTIN_EVCMPEQ },
- { 0, CODE_FOR_spe_evcmpgts, "__builtin_spe_evcmpgts", SPE_BUILTIN_EVCMPGTS },
- { 0, CODE_FOR_spe_evcmpgtu, "__builtin_spe_evcmpgtu", SPE_BUILTIN_EVCMPGTU },
- { 0, CODE_FOR_spe_evcmplts, "__builtin_spe_evcmplts", SPE_BUILTIN_EVCMPLTS },
- { 0, CODE_FOR_spe_evcmpltu, "__builtin_spe_evcmpltu", SPE_BUILTIN_EVCMPLTU },
- { 0, CODE_FOR_spe_evfscmpeq, "__builtin_spe_evfscmpeq", SPE_BUILTIN_EVFSCMPEQ },
- { 0, CODE_FOR_spe_evfscmpgt, "__builtin_spe_evfscmpgt", SPE_BUILTIN_EVFSCMPGT },
- { 0, CODE_FOR_spe_evfscmplt, "__builtin_spe_evfscmplt", SPE_BUILTIN_EVFSCMPLT },
- { 0, CODE_FOR_spe_evfststeq, "__builtin_spe_evfststeq", SPE_BUILTIN_EVFSTSTEQ },
- { 0, CODE_FOR_spe_evfststgt, "__builtin_spe_evfststgt", SPE_BUILTIN_EVFSTSTGT },
- /* Place-holder. Leave as last. */
- { 0, CODE_FOR_spe_evfststlt, "__builtin_spe_evfststlt", SPE_BUILTIN_EVFSTSTLT },
+#undef RS6000_BUILTIN_1
+#undef RS6000_BUILTIN_2
+#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_A
+#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_P
+#undef RS6000_BUILTIN_Q
+#undef RS6000_BUILTIN_S
+#undef RS6000_BUILTIN_X
+
+#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE) \
+ { MASK, ICODE, NAME, ENUM },
+
+#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE)
+
+static const struct builtin_description bdesc_spe_predicates[] =
+{
+#include "rs6000-builtin.def"
};
/* SPE evsel predicates. */
-static struct builtin_description bdesc_spe_evsel[] =
-{
- /* Place-holder. Leave as first. */
- { 0, CODE_FOR_spe_evcmpgts, "__builtin_spe_evsel_gts", SPE_BUILTIN_EVSEL_CMPGTS },
- { 0, CODE_FOR_spe_evcmpgtu, "__builtin_spe_evsel_gtu", SPE_BUILTIN_EVSEL_CMPGTU },
- { 0, CODE_FOR_spe_evcmplts, "__builtin_spe_evsel_lts", SPE_BUILTIN_EVSEL_CMPLTS },
- { 0, CODE_FOR_spe_evcmpltu, "__builtin_spe_evsel_ltu", SPE_BUILTIN_EVSEL_CMPLTU },
- { 0, CODE_FOR_spe_evcmpeq, "__builtin_spe_evsel_eq", SPE_BUILTIN_EVSEL_CMPEQ },
- { 0, CODE_FOR_spe_evfscmpgt, "__builtin_spe_evsel_fsgt", SPE_BUILTIN_EVSEL_FSCMPGT },
- { 0, CODE_FOR_spe_evfscmplt, "__builtin_spe_evsel_fslt", SPE_BUILTIN_EVSEL_FSCMPLT },
- { 0, CODE_FOR_spe_evfscmpeq, "__builtin_spe_evsel_fseq", SPE_BUILTIN_EVSEL_FSCMPEQ },
- { 0, CODE_FOR_spe_evfststgt, "__builtin_spe_evsel_fststgt", SPE_BUILTIN_EVSEL_FSTSTGT },
- { 0, CODE_FOR_spe_evfststlt, "__builtin_spe_evsel_fststlt", SPE_BUILTIN_EVSEL_FSTSTLT },
- /* Place-holder. Leave as last. */
- { 0, CODE_FOR_spe_evfststeq, "__builtin_spe_evsel_fststeq", SPE_BUILTIN_EVSEL_FSTSTEQ },
+#undef RS6000_BUILTIN_1
+#undef RS6000_BUILTIN_2
+#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_A
+#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_P
+#undef RS6000_BUILTIN_Q
+#undef RS6000_BUILTIN_S
+#undef RS6000_BUILTIN_X
+
+#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) \
+ { MASK, ICODE, NAME, ENUM },
+
+#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE)
+
+static const struct builtin_description bdesc_spe_evsel[] =
+{
+#include "rs6000-builtin.def"
};
/* PAIRED predicates. */
+#undef RS6000_BUILTIN_1
+#undef RS6000_BUILTIN_2
+#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_A
+#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_P
+#undef RS6000_BUILTIN_Q
+#undef RS6000_BUILTIN_S
+#undef RS6000_BUILTIN_X
+
+#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE) \
+ { MASK, ICODE, NAME, ENUM },
+
+#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE)
+
static const struct builtin_description bdesc_paired_preds[] =
{
- /* Place-holder. Leave as first. */
- { 0, CODE_FOR_paired_cmpu0, "__builtin_paired_cmpu0", PAIRED_BUILTIN_CMPU0 },
- /* Place-holder. Leave as last. */
- { 0, CODE_FOR_paired_cmpu1, "__builtin_paired_cmpu1", PAIRED_BUILTIN_CMPU1 },
+#include "rs6000-builtin.def"
};
/* ABS* operations. */
+#undef RS6000_BUILTIN_1
+#undef RS6000_BUILTIN_2
+#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_A
+#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_P
+#undef RS6000_BUILTIN_Q
+#undef RS6000_BUILTIN_S
+#undef RS6000_BUILTIN_X
+
+#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) \
+ { MASK, ICODE, NAME, ENUM },
+
+#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE)
+
static const struct builtin_description bdesc_abs[] =
{
- { MASK_ALTIVEC, CODE_FOR_absv4si2, "__builtin_altivec_abs_v4si", ALTIVEC_BUILTIN_ABS_V4SI },
- { MASK_ALTIVEC, CODE_FOR_absv8hi2, "__builtin_altivec_abs_v8hi", ALTIVEC_BUILTIN_ABS_V8HI },
- { MASK_ALTIVEC, CODE_FOR_absv4sf2, "__builtin_altivec_abs_v4sf", ALTIVEC_BUILTIN_ABS_V4SF },
- { MASK_ALTIVEC, CODE_FOR_absv16qi2, "__builtin_altivec_abs_v16qi", ALTIVEC_BUILTIN_ABS_V16QI },
- { MASK_ALTIVEC, CODE_FOR_altivec_abss_v4si, "__builtin_altivec_abss_v4si", ALTIVEC_BUILTIN_ABSS_V4SI },
- { MASK_ALTIVEC, CODE_FOR_altivec_abss_v8hi, "__builtin_altivec_abss_v8hi", ALTIVEC_BUILTIN_ABSS_V8HI },
- { MASK_ALTIVEC, CODE_FOR_altivec_abss_v16qi, "__builtin_altivec_abss_v16qi", ALTIVEC_BUILTIN_ABSS_V16QI },
- { MASK_VSX, CODE_FOR_absv2df2, "__builtin_vsx_xvabsdp", VSX_BUILTIN_XVABSDP },
- { MASK_VSX, CODE_FOR_vsx_nabsv2df2, "__builtin_vsx_xvnabsdp", VSX_BUILTIN_XVNABSDP },
- { MASK_VSX, CODE_FOR_absv4sf2, "__builtin_vsx_xvabssp", VSX_BUILTIN_XVABSSP },
- { MASK_VSX, CODE_FOR_vsx_nabsv4sf2, "__builtin_vsx_xvnabssp", VSX_BUILTIN_XVNABSSP },
+#include "rs6000-builtin.def"
};
/* Simple unary operations: VECb = foo (unsigned literal) or VECb =
foo (VECa). */
-static struct builtin_description bdesc_1arg[] =
-{
- { MASK_ALTIVEC, CODE_FOR_altivec_vexptefp, "__builtin_altivec_vexptefp", ALTIVEC_BUILTIN_VEXPTEFP },
- { MASK_ALTIVEC, CODE_FOR_altivec_vlogefp, "__builtin_altivec_vlogefp", ALTIVEC_BUILTIN_VLOGEFP },
- { MASK_ALTIVEC, CODE_FOR_rev4sf2, "__builtin_altivec_vrefp", ALTIVEC_BUILTIN_VREFP },
- { MASK_ALTIVEC, CODE_FOR_vector_floorv4sf2, "__builtin_altivec_vrfim", ALTIVEC_BUILTIN_VRFIM },
- { MASK_ALTIVEC, CODE_FOR_altivec_vrfin, "__builtin_altivec_vrfin", ALTIVEC_BUILTIN_VRFIN },
- { MASK_ALTIVEC, CODE_FOR_vector_ceilv4sf2, "__builtin_altivec_vrfip", ALTIVEC_BUILTIN_VRFIP },
- { MASK_ALTIVEC, CODE_FOR_vector_btruncv4sf2, "__builtin_altivec_vrfiz", ALTIVEC_BUILTIN_VRFIZ },
- { MASK_ALTIVEC, CODE_FOR_rsqrtv4sf2, "__builtin_altivec_vrsqrtfp", ALTIVEC_BUILTIN_VRSQRTFP },
- { MASK_ALTIVEC, CODE_FOR_rsqrtev4sf2, "__builtin_altivec_vrsqrtefp", ALTIVEC_BUILTIN_VRSQRTEFP },
- { MASK_ALTIVEC, CODE_FOR_altivec_vspltisb, "__builtin_altivec_vspltisb", ALTIVEC_BUILTIN_VSPLTISB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vspltish, "__builtin_altivec_vspltish", ALTIVEC_BUILTIN_VSPLTISH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vspltisw, "__builtin_altivec_vspltisw", ALTIVEC_BUILTIN_VSPLTISW },
- { MASK_ALTIVEC, CODE_FOR_altivec_vupkhsb, "__builtin_altivec_vupkhsb", ALTIVEC_BUILTIN_VUPKHSB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vupkhpx, "__builtin_altivec_vupkhpx", ALTIVEC_BUILTIN_VUPKHPX },
- { MASK_ALTIVEC, CODE_FOR_altivec_vupkhsh, "__builtin_altivec_vupkhsh", ALTIVEC_BUILTIN_VUPKHSH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vupklsb, "__builtin_altivec_vupklsb", ALTIVEC_BUILTIN_VUPKLSB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vupklpx, "__builtin_altivec_vupklpx", ALTIVEC_BUILTIN_VUPKLPX },
- { MASK_ALTIVEC, CODE_FOR_altivec_vupklsh, "__builtin_altivec_vupklsh", ALTIVEC_BUILTIN_VUPKLSH },
-
- { MASK_VSX, CODE_FOR_negv2df2, "__builtin_vsx_xvnegdp", VSX_BUILTIN_XVNEGDP },
- { MASK_VSX, CODE_FOR_sqrtv2df2, "__builtin_vsx_xvsqrtdp", VSX_BUILTIN_XVSQRTDP },
- { MASK_VSX, CODE_FOR_rsqrtv2df2, "__builtin_vsx_xvrsqrtdp", VSX_BUILTIN_VEC_RSQRT_V2DF },
- { MASK_VSX, CODE_FOR_rsqrtev2df2, "__builtin_vsx_xvrsqrtedp", VSX_BUILTIN_XVRSQRTEDP },
- { MASK_VSX, CODE_FOR_vsx_tsqrtv2df2_fe, "__builtin_vsx_xvtsqrtdp_fe", VSX_BUILTIN_XVTSQRTDP_FE },
- { MASK_VSX, CODE_FOR_vsx_tsqrtv2df2_fg, "__builtin_vsx_xvtsqrtdp_fg", VSX_BUILTIN_XVTSQRTDP_FG },
- { MASK_VSX, CODE_FOR_vsx_frev2df2, "__builtin_vsx_xvredp", VSX_BUILTIN_XVREDP },
-
- { MASK_VSX, CODE_FOR_negv4sf2, "__builtin_vsx_xvnegsp", VSX_BUILTIN_XVNEGSP },
- { MASK_VSX, CODE_FOR_sqrtv4sf2, "__builtin_vsx_xvsqrtsp", VSX_BUILTIN_XVSQRTSP },
- { MASK_VSX, CODE_FOR_rsqrtv4sf2, "__builtin_vsx_xvrsqrtsp", VSX_BUILTIN_VEC_RSQRT_V4SF },
- { MASK_VSX, CODE_FOR_rsqrtev4sf2, "__builtin_vsx_xvrsqrtesp", VSX_BUILTIN_XVRSQRTESP },
- { MASK_VSX, CODE_FOR_vsx_tsqrtv4sf2_fe, "__builtin_vsx_xvtsqrtsp_fe", VSX_BUILTIN_XVTSQRTSP_FE },
- { MASK_VSX, CODE_FOR_vsx_tsqrtv4sf2_fg, "__builtin_vsx_xvtsqrtsp_fg", VSX_BUILTIN_XVTSQRTSP_FG },
- { MASK_VSX, CODE_FOR_vsx_frev4sf2, "__builtin_vsx_xvresp", VSX_BUILTIN_XVRESP },
-
- { MASK_VSX, CODE_FOR_vsx_xscvdpsp, "__builtin_vsx_xscvdpsp", VSX_BUILTIN_XSCVDPSP },
- { MASK_VSX, CODE_FOR_vsx_xscvdpsp, "__builtin_vsx_xscvspdp", VSX_BUILTIN_XSCVSPDP },
- { MASK_VSX, CODE_FOR_vsx_xvcvdpsp, "__builtin_vsx_xvcvdpsp", VSX_BUILTIN_XVCVDPSP },
- { MASK_VSX, CODE_FOR_vsx_xvcvspdp, "__builtin_vsx_xvcvspdp", VSX_BUILTIN_XVCVSPDP },
- { MASK_VSX, CODE_FOR_vsx_tsqrtdf2_fe, "__builtin_vsx_xstsqrtdp_fe", VSX_BUILTIN_XSTSQRTDP_FE },
- { MASK_VSX, CODE_FOR_vsx_tsqrtdf2_fg, "__builtin_vsx_xstsqrtdp_fg", VSX_BUILTIN_XSTSQRTDP_FG },
-
- { MASK_VSX, CODE_FOR_vsx_fix_truncv2dfv2di2, "__builtin_vsx_xvcvdpsxds", VSX_BUILTIN_XVCVDPSXDS },
- { MASK_VSX, CODE_FOR_vsx_fixuns_truncv2dfv2di2, "__builtin_vsx_xvcvdpuxds", VSX_BUILTIN_XVCVDPUXDS },
- { MASK_VSX, CODE_FOR_vsx_fixuns_truncv2dfv2di2, "__builtin_vsx_xvcvdpuxds_uns", VSX_BUILTIN_XVCVDPUXDS_UNS },
- { MASK_VSX, CODE_FOR_vsx_floatv2div2df2, "__builtin_vsx_xvcvsxddp", VSX_BUILTIN_XVCVSXDDP },
- { MASK_VSX, CODE_FOR_vsx_floatunsv2div2df2, "__builtin_vsx_xvcvuxddp", VSX_BUILTIN_XVCVUXDDP },
- { MASK_VSX, CODE_FOR_vsx_floatunsv2div2df2, "__builtin_vsx_xvcvuxddp_uns", VSX_BUILTIN_XVCVUXDDP_UNS },
-
- { MASK_VSX, CODE_FOR_vsx_fix_truncv4sfv4si2, "__builtin_vsx_xvcvspsxws", VSX_BUILTIN_XVCVSPSXWS },
- { MASK_VSX, CODE_FOR_vsx_fixuns_truncv4sfv4si2, "__builtin_vsx_xvcvspuxws", VSX_BUILTIN_XVCVSPUXWS },
- { MASK_VSX, CODE_FOR_vsx_floatv4siv4sf2, "__builtin_vsx_xvcvsxwsp", VSX_BUILTIN_XVCVSXWSP },
- { MASK_VSX, CODE_FOR_vsx_floatunsv4siv4sf2, "__builtin_vsx_xvcvuxwsp", VSX_BUILTIN_XVCVUXWSP },
-
- { MASK_VSX, CODE_FOR_vsx_xvcvdpsxws, "__builtin_vsx_xvcvdpsxws", VSX_BUILTIN_XVCVDPSXWS },
- { MASK_VSX, CODE_FOR_vsx_xvcvdpuxws, "__builtin_vsx_xvcvdpuxws", VSX_BUILTIN_XVCVDPUXWS },
- { MASK_VSX, CODE_FOR_vsx_xvcvsxwdp, "__builtin_vsx_xvcvsxwdp", VSX_BUILTIN_XVCVSXWDP },
- { MASK_VSX, CODE_FOR_vsx_xvcvuxwdp, "__builtin_vsx_xvcvuxwdp", VSX_BUILTIN_XVCVUXWDP },
- { MASK_VSX, CODE_FOR_vsx_xvrdpi, "__builtin_vsx_xvrdpi", VSX_BUILTIN_XVRDPI },
- { MASK_VSX, CODE_FOR_vsx_xvrdpic, "__builtin_vsx_xvrdpic", VSX_BUILTIN_XVRDPIC },
- { MASK_VSX, CODE_FOR_vsx_floorv2df2, "__builtin_vsx_xvrdpim", VSX_BUILTIN_XVRDPIM },
- { MASK_VSX, CODE_FOR_vsx_ceilv2df2, "__builtin_vsx_xvrdpip", VSX_BUILTIN_XVRDPIP },
- { MASK_VSX, CODE_FOR_vsx_btruncv2df2, "__builtin_vsx_xvrdpiz", VSX_BUILTIN_XVRDPIZ },
-
- { MASK_VSX, CODE_FOR_vsx_xvcvspsxds, "__builtin_vsx_xvcvspsxds", VSX_BUILTIN_XVCVSPSXDS },
- { MASK_VSX, CODE_FOR_vsx_xvcvspuxds, "__builtin_vsx_xvcvspuxds", VSX_BUILTIN_XVCVSPUXDS },
- { MASK_VSX, CODE_FOR_vsx_xvcvsxdsp, "__builtin_vsx_xvcvsxdsp", VSX_BUILTIN_XVCVSXDSP },
- { MASK_VSX, CODE_FOR_vsx_xvcvuxdsp, "__builtin_vsx_xvcvuxdsp", VSX_BUILTIN_XVCVUXDSP },
- { MASK_VSX, CODE_FOR_vsx_xvrspi, "__builtin_vsx_xvrspi", VSX_BUILTIN_XVRSPI },
- { MASK_VSX, CODE_FOR_vsx_xvrspic, "__builtin_vsx_xvrspic", VSX_BUILTIN_XVRSPIC },
- { MASK_VSX, CODE_FOR_vsx_floorv4sf2, "__builtin_vsx_xvrspim", VSX_BUILTIN_XVRSPIM },
- { MASK_VSX, CODE_FOR_vsx_ceilv4sf2, "__builtin_vsx_xvrspip", VSX_BUILTIN_XVRSPIP },
- { MASK_VSX, CODE_FOR_vsx_btruncv4sf2, "__builtin_vsx_xvrspiz", VSX_BUILTIN_XVRSPIZ },
-
- { MASK_VSX, CODE_FOR_vsx_xsrdpi, "__builtin_vsx_xsrdpi", VSX_BUILTIN_XSRDPI },
- { MASK_VSX, CODE_FOR_vsx_xsrdpic, "__builtin_vsx_xsrdpic", VSX_BUILTIN_XSRDPIC },
- { MASK_VSX, CODE_FOR_vsx_floordf2, "__builtin_vsx_xsrdpim", VSX_BUILTIN_XSRDPIM },
- { MASK_VSX, CODE_FOR_vsx_ceildf2, "__builtin_vsx_xsrdpip", VSX_BUILTIN_XSRDPIP },
- { MASK_VSX, CODE_FOR_vsx_btruncdf2, "__builtin_vsx_xsrdpiz", VSX_BUILTIN_XSRDPIZ },
-
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abs", ALTIVEC_BUILTIN_VEC_ABS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abss", ALTIVEC_BUILTIN_VEC_ABSS },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_ceil", ALTIVEC_BUILTIN_VEC_CEIL },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_expte", ALTIVEC_BUILTIN_VEC_EXPTE },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_floor", ALTIVEC_BUILTIN_VEC_FLOOR },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_loge", ALTIVEC_BUILTIN_VEC_LOGE },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mtvscr", ALTIVEC_BUILTIN_VEC_MTVSCR },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_re", ALTIVEC_BUILTIN_VEC_RE },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_round", ALTIVEC_BUILTIN_VEC_ROUND },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_rsqrt", ALTIVEC_BUILTIN_VEC_RSQRT },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_rsqrte", ALTIVEC_BUILTIN_VEC_RSQRTE },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_trunc", ALTIVEC_BUILTIN_VEC_TRUNC },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_unpackh", ALTIVEC_BUILTIN_VEC_UNPACKH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupkhsh", ALTIVEC_BUILTIN_VEC_VUPKHSH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupkhpx", ALTIVEC_BUILTIN_VEC_VUPKHPX },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupkhsb", ALTIVEC_BUILTIN_VEC_VUPKHSB },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_unpackl", ALTIVEC_BUILTIN_VEC_UNPACKL },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklpx", ALTIVEC_BUILTIN_VEC_VUPKLPX },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklsh", ALTIVEC_BUILTIN_VEC_VUPKLSH },
- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklsb", ALTIVEC_BUILTIN_VEC_VUPKLSB },
-
- { MASK_VSX, CODE_FOR_nothing, "__builtin_vec_nearbyint", ALTIVEC_BUILTIN_VEC_NEARBYINT },
- { MASK_VSX, CODE_FOR_nothing, "__builtin_vec_rint", ALTIVEC_BUILTIN_VEC_RINT },
- { MASK_VSX, CODE_FOR_nothing, "__builtin_vec_sqrt", ALTIVEC_BUILTIN_VEC_SQRT },
-
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_floatv4siv4sf2, "__builtin_vec_float_sisf", VECTOR_BUILTIN_FLOAT_V4SI_V4SF },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_unsigned_floatv4siv4sf2, "__builtin_vec_uns_float_sisf", VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vec_fix_sfsi", VECTOR_BUILTIN_FIX_V4SF_V4SI },
- { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vec_fixuns_sfsi", VECTOR_BUILTIN_FIXUNS_V4SF_V4SI },
-
- /* The SPE unary builtins must start with SPE_BUILTIN_EVABS and
- end with SPE_BUILTIN_EVSUBFUSIAAW. */
- { 0, CODE_FOR_absv2si2, "__builtin_spe_evabs", SPE_BUILTIN_EVABS },
- { 0, CODE_FOR_spe_evaddsmiaaw, "__builtin_spe_evaddsmiaaw", SPE_BUILTIN_EVADDSMIAAW },
- { 0, CODE_FOR_spe_evaddssiaaw, "__builtin_spe_evaddssiaaw", SPE_BUILTIN_EVADDSSIAAW },
- { 0, CODE_FOR_spe_evaddumiaaw, "__builtin_spe_evaddumiaaw", SPE_BUILTIN_EVADDUMIAAW },
- { 0, CODE_FOR_spe_evaddusiaaw, "__builtin_spe_evaddusiaaw", SPE_BUILTIN_EVADDUSIAAW },
- { 0, CODE_FOR_spe_evcntlsw, "__builtin_spe_evcntlsw", SPE_BUILTIN_EVCNTLSW },
- { 0, CODE_FOR_spe_evcntlzw, "__builtin_spe_evcntlzw", SPE_BUILTIN_EVCNTLZW },
- { 0, CODE_FOR_spe_evextsb, "__builtin_spe_evextsb", SPE_BUILTIN_EVEXTSB },
- { 0, CODE_FOR_spe_evextsh, "__builtin_spe_evextsh", SPE_BUILTIN_EVEXTSH },
- { 0, CODE_FOR_spe_evfsabs, "__builtin_spe_evfsabs", SPE_BUILTIN_EVFSABS },
- { 0, CODE_FOR_spe_evfscfsf, "__builtin_spe_evfscfsf", SPE_BUILTIN_EVFSCFSF },
- { 0, CODE_FOR_spe_evfscfsi, "__builtin_spe_evfscfsi", SPE_BUILTIN_EVFSCFSI },
- { 0, CODE_FOR_spe_evfscfuf, "__builtin_spe_evfscfuf", SPE_BUILTIN_EVFSCFUF },
- { 0, CODE_FOR_spe_evfscfui, "__builtin_spe_evfscfui", SPE_BUILTIN_EVFSCFUI },
- { 0, CODE_FOR_spe_evfsctsf, "__builtin_spe_evfsctsf", SPE_BUILTIN_EVFSCTSF },
- { 0, CODE_FOR_spe_evfsctsi, "__builtin_spe_evfsctsi", SPE_BUILTIN_EVFSCTSI },
- { 0, CODE_FOR_spe_evfsctsiz, "__builtin_spe_evfsctsiz", SPE_BUILTIN_EVFSCTSIZ },
- { 0, CODE_FOR_spe_evfsctuf, "__builtin_spe_evfsctuf", SPE_BUILTIN_EVFSCTUF },
- { 0, CODE_FOR_spe_evfsctui, "__builtin_spe_evfsctui", SPE_BUILTIN_EVFSCTUI },
- { 0, CODE_FOR_spe_evfsctuiz, "__builtin_spe_evfsctuiz", SPE_BUILTIN_EVFSCTUIZ },
- { 0, CODE_FOR_spe_evfsnabs, "__builtin_spe_evfsnabs", SPE_BUILTIN_EVFSNABS },
- { 0, CODE_FOR_spe_evfsneg, "__builtin_spe_evfsneg", SPE_BUILTIN_EVFSNEG },
- { 0, CODE_FOR_spe_evmra, "__builtin_spe_evmra", SPE_BUILTIN_EVMRA },
- { 0, CODE_FOR_negv2si2, "__builtin_spe_evneg", SPE_BUILTIN_EVNEG },
- { 0, CODE_FOR_spe_evrndw, "__builtin_spe_evrndw", SPE_BUILTIN_EVRNDW },
- { 0, CODE_FOR_spe_evsubfsmiaaw, "__builtin_spe_evsubfsmiaaw", SPE_BUILTIN_EVSUBFSMIAAW },
- { 0, CODE_FOR_spe_evsubfssiaaw, "__builtin_spe_evsubfssiaaw", SPE_BUILTIN_EVSUBFSSIAAW },
- { 0, CODE_FOR_spe_evsubfumiaaw, "__builtin_spe_evsubfumiaaw", SPE_BUILTIN_EVSUBFUMIAAW },
-
- /* Place-holder. Leave as last unary SPE builtin. */
- { 0, CODE_FOR_spe_evsubfusiaaw, "__builtin_spe_evsubfusiaaw", SPE_BUILTIN_EVSUBFUSIAAW },
-
- { 0, CODE_FOR_paired_absv2sf2, "__builtin_paired_absv2sf2", PAIRED_BUILTIN_ABSV2SF2 },
- { 0, CODE_FOR_nabsv2sf2, "__builtin_paired_nabsv2sf2", PAIRED_BUILTIN_NABSV2SF2 },
- { 0, CODE_FOR_paired_negv2sf2, "__builtin_paired_negv2sf2", PAIRED_BUILTIN_NEGV2SF2 },
- { 0, CODE_FOR_sqrtv2sf2, "__builtin_paired_sqrtv2sf2", PAIRED_BUILTIN_SQRTV2SF2 },
- { 0, CODE_FOR_resv2sf2, "__builtin_paired_resv2sf2", PAIRED_BUILTIN_RESV2SF2 }
+#undef RS6000_BUILTIN_1
+#undef RS6000_BUILTIN_2
+#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_A
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_P
+#undef RS6000_BUILTIN_Q
+#undef RS6000_BUILTIN_S
+#undef RS6000_BUILTIN_X
+
+#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) \
+ { MASK, ICODE, NAME, ENUM },
+
+#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE)
+
+static const struct builtin_description bdesc_1arg[] =
+{
+#include "rs6000-builtin.def"
};
+#undef RS6000_BUILTIN_1
+#undef RS6000_BUILTIN_2
+#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_A
+#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_P
+#undef RS6000_BUILTIN_Q
+#undef RS6000_BUILTIN_S
+#undef RS6000_BUILTIN_X
+
+/* Return true if a builtin function is overloaded. */
+bool
+rs6000_overloaded_builtin_p (enum rs6000_builtins fncode)
+{
+ return (rs6000_builtin_info[(int)fncode].attr & RS6000_BTC_OVERLOADED) != 0;
+}
+
+
static rtx
rs6000_expand_unop_builtin (enum insn_code icode, tree exp, rtx target)
{
altivec_expand_builtin (tree exp, rtx target, bool *expandedp)
{
const struct builtin_description *d;
- const struct builtin_description_predicates *dp;
size_t i;
enum insn_code icode;
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
tree arg0;
rtx op0, pat;
enum machine_mode tmode, mode0;
- unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+ enum rs6000_builtins fcode
+ = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl);
- if ((fcode >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
- && fcode <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
- || (fcode >= VSX_BUILTIN_OVERLOADED_FIRST
- && fcode <= VSX_BUILTIN_OVERLOADED_LAST))
+ if (rs6000_overloaded_builtin_p (fcode))
{
*expandedp = true;
error ("unresolved overload for Altivec builtin %qF", fndecl);
- return const0_rtx;
+
+ /* Given it is invalid, just generate a normal call. */
+ return expand_call (exp, target, false);
}
target = altivec_expand_ld_builtin (exp, target, expandedp);
return altivec_expand_abs_builtin (d->icode, exp, target);
/* Expand the AltiVec predicates. */
- dp = bdesc_altivec_preds;
- for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, dp++)
- if (dp->code == fcode)
- return altivec_expand_predicate_builtin (dp->icode, exp, target);
+ d = bdesc_altivec_preds;
+ for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, d++)
+ if (d->code == fcode)
+ return altivec_expand_predicate_builtin (d->icode, exp, target);
/* LV* are funky. We initialized them differently. */
switch (fcode)
/* Binops that need to be initialized manually, but can be expanded
automagically by rs6000_expand_binop_builtin. */
-static struct builtin_description bdesc_2arg_spe[] =
-{
- { 0, CODE_FOR_spe_evlddx, "__builtin_spe_evlddx", SPE_BUILTIN_EVLDDX },
- { 0, CODE_FOR_spe_evldwx, "__builtin_spe_evldwx", SPE_BUILTIN_EVLDWX },
- { 0, CODE_FOR_spe_evldhx, "__builtin_spe_evldhx", SPE_BUILTIN_EVLDHX },
- { 0, CODE_FOR_spe_evlwhex, "__builtin_spe_evlwhex", SPE_BUILTIN_EVLWHEX },
- { 0, CODE_FOR_spe_evlwhoux, "__builtin_spe_evlwhoux", SPE_BUILTIN_EVLWHOUX },
- { 0, CODE_FOR_spe_evlwhosx, "__builtin_spe_evlwhosx", SPE_BUILTIN_EVLWHOSX },
- { 0, CODE_FOR_spe_evlwwsplatx, "__builtin_spe_evlwwsplatx", SPE_BUILTIN_EVLWWSPLATX },
- { 0, CODE_FOR_spe_evlwhsplatx, "__builtin_spe_evlwhsplatx", SPE_BUILTIN_EVLWHSPLATX },
- { 0, CODE_FOR_spe_evlhhesplatx, "__builtin_spe_evlhhesplatx", SPE_BUILTIN_EVLHHESPLATX },
- { 0, CODE_FOR_spe_evlhhousplatx, "__builtin_spe_evlhhousplatx", SPE_BUILTIN_EVLHHOUSPLATX },
- { 0, CODE_FOR_spe_evlhhossplatx, "__builtin_spe_evlhhossplatx", SPE_BUILTIN_EVLHHOSSPLATX },
- { 0, CODE_FOR_spe_evldd, "__builtin_spe_evldd", SPE_BUILTIN_EVLDD },
- { 0, CODE_FOR_spe_evldw, "__builtin_spe_evldw", SPE_BUILTIN_EVLDW },
- { 0, CODE_FOR_spe_evldh, "__builtin_spe_evldh", SPE_BUILTIN_EVLDH },
- { 0, CODE_FOR_spe_evlwhe, "__builtin_spe_evlwhe", SPE_BUILTIN_EVLWHE },
- { 0, CODE_FOR_spe_evlwhou, "__builtin_spe_evlwhou", SPE_BUILTIN_EVLWHOU },
- { 0, CODE_FOR_spe_evlwhos, "__builtin_spe_evlwhos", SPE_BUILTIN_EVLWHOS },
- { 0, CODE_FOR_spe_evlwwsplat, "__builtin_spe_evlwwsplat", SPE_BUILTIN_EVLWWSPLAT },
- { 0, CODE_FOR_spe_evlwhsplat, "__builtin_spe_evlwhsplat", SPE_BUILTIN_EVLWHSPLAT },
- { 0, CODE_FOR_spe_evlhhesplat, "__builtin_spe_evlhhesplat", SPE_BUILTIN_EVLHHESPLAT },
- { 0, CODE_FOR_spe_evlhhousplat, "__builtin_spe_evlhhousplat", SPE_BUILTIN_EVLHHOUSPLAT },
- { 0, CODE_FOR_spe_evlhhossplat, "__builtin_spe_evlhhossplat", SPE_BUILTIN_EVLHHOSSPLAT }
+static const struct builtin_description bdesc_2arg_spe[] =
+{
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlddx, "__builtin_spe_evlddx", SPE_BUILTIN_EVLDDX },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evldwx, "__builtin_spe_evldwx", SPE_BUILTIN_EVLDWX },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evldhx, "__builtin_spe_evldhx", SPE_BUILTIN_EVLDHX },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlwhex, "__builtin_spe_evlwhex", SPE_BUILTIN_EVLWHEX },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlwhoux, "__builtin_spe_evlwhoux", SPE_BUILTIN_EVLWHOUX },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlwhosx, "__builtin_spe_evlwhosx", SPE_BUILTIN_EVLWHOSX },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlwwsplatx, "__builtin_spe_evlwwsplatx", SPE_BUILTIN_EVLWWSPLATX },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlwhsplatx, "__builtin_spe_evlwhsplatx", SPE_BUILTIN_EVLWHSPLATX },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlhhesplatx, "__builtin_spe_evlhhesplatx", SPE_BUILTIN_EVLHHESPLATX },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlhhousplatx, "__builtin_spe_evlhhousplatx", SPE_BUILTIN_EVLHHOUSPLATX },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlhhossplatx, "__builtin_spe_evlhhossplatx", SPE_BUILTIN_EVLHHOSSPLATX },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evldd, "__builtin_spe_evldd", SPE_BUILTIN_EVLDD },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evldw, "__builtin_spe_evldw", SPE_BUILTIN_EVLDW },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evldh, "__builtin_spe_evldh", SPE_BUILTIN_EVLDH },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlwhe, "__builtin_spe_evlwhe", SPE_BUILTIN_EVLWHE },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlwhou, "__builtin_spe_evlwhou", SPE_BUILTIN_EVLWHOU },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlwhos, "__builtin_spe_evlwhos", SPE_BUILTIN_EVLWHOS },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlwwsplat, "__builtin_spe_evlwwsplat", SPE_BUILTIN_EVLWWSPLAT },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlwhsplat, "__builtin_spe_evlwhsplat", SPE_BUILTIN_EVLWHSPLAT },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlhhesplat, "__builtin_spe_evlhhesplat", SPE_BUILTIN_EVLHHESPLAT },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlhhousplat, "__builtin_spe_evlhhousplat", SPE_BUILTIN_EVLHHOUSPLAT },
+ { RS6000_BTM_SPE, CODE_FOR_spe_evlhhossplat, "__builtin_spe_evlhhossplat", SPE_BUILTIN_EVLHHOSSPLAT }
};
/* Expand the builtin in EXP and store the result in TARGET. Store
enum insn_code icode;
enum machine_mode tmode, mode0;
rtx pat, op0;
- struct builtin_description *d;
+ const struct builtin_description *d;
size_t i;
*expandedp = true;
break;
}
- d = (struct builtin_description *) bdesc_2arg_spe;
+ d = bdesc_2arg_spe;
for (i = 0; i < ARRAY_SIZE (bdesc_2arg_spe); ++i, ++d)
if (d->code == fcode)
return rs6000_expand_binop_builtin (d->icode, exp, target);
- d = (struct builtin_description *) bdesc_spe_predicates;
+ d = bdesc_spe_predicates;
for (i = 0; i < ARRAY_SIZE (bdesc_spe_predicates); ++i, ++d)
if (d->code == fcode)
return spe_expand_predicate_builtin (d->icode, exp, target);
- d = (struct builtin_description *) bdesc_spe_evsel;
+ d = bdesc_spe_evsel;
for (i = 0; i < ARRAY_SIZE (bdesc_spe_evsel); ++i, ++d)
if (d->code == fcode)
return spe_expand_evsel_builtin (d->icode, exp, target);
return target;
}
+/* Raise an error message for a builtin function that is called without the
+ appropriate target options being set. */
+
+static void
+rs6000_invalid_builtin (enum rs6000_builtins fncode)
+{
+ size_t uns_fncode = (size_t)fncode;
+ const char *name = rs6000_builtin_info[uns_fncode].name;
+ unsigned fnmask = rs6000_builtin_info[uns_fncode].mask;
+
+ gcc_assert (name != NULL);
+ if ((fnmask & RS6000_BTM_CELL) != 0)
+ error ("Builtin function %s is only valid for the cell processor", name);
+ else if ((fnmask & RS6000_BTM_VSX) != 0)
+ error ("Builtin function %s requires the -mvsx option", name);
+ else if ((fnmask & RS6000_BTM_ALTIVEC) != 0)
+ error ("Builtin function %s requires the -maltivec option", name);
+ else if ((fnmask & RS6000_BTM_PAIRED) != 0)
+ error ("Builtin function %s requires the -mpaired option", name);
+ else if ((fnmask & RS6000_BTM_SPE) != 0)
+ error ("Builtin function %s requires the -mspe option", name);
+ else
+ error ("Builtin function %s is not supported with the current options",
+ name);
+}
+
/* Expand an expression EXP that calls a built-in function,
with result going to TARGET if that's convenient
(and in mode MODE if that's convenient).
int ignore ATTRIBUTE_UNUSED)
{
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
- unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+ enum rs6000_builtins fcode
+ = (enum rs6000_builtins)DECL_FUNCTION_CODE (fndecl);
+ size_t uns_fcode = (size_t)fcode;
const struct builtin_description *d;
size_t i;
rtx ret;
bool success;
+ unsigned mask = rs6000_builtin_info[uns_fcode].mask;
+ bool func_valid_p = ((rs6000_builtin_mask & mask) == mask);
+
+ if (TARGET_DEBUG_BUILTIN)
+ {
+ enum insn_code icode = rs6000_builtin_info[uns_fcode].icode;
+ const char *name1 = rs6000_builtin_info[uns_fcode].name;
+ const char *name2 = ((icode != CODE_FOR_nothing)
+ ? get_insn_name ((int)icode)
+ : "nothing");
+ const char *name3;
+
+ switch (rs6000_builtin_info[uns_fcode].attr & RS6000_BTC_TYPE_MASK)
+ {
+ default: name3 = "unknown"; break;
+ case RS6000_BTC_SPECIAL: name3 = "special"; break;
+ case RS6000_BTC_UNARY: name3 = "unary"; break;
+ case RS6000_BTC_BINARY: name3 = "binary"; break;
+ case RS6000_BTC_TERNARY: name3 = "ternary"; break;
+ case RS6000_BTC_PREDICATE: name3 = "predicate"; break;
+ case RS6000_BTC_ABS: name3 = "abs"; break;
+ case RS6000_BTC_EVSEL: name3 = "evsel"; break;
+ case RS6000_BTC_DST: name3 = "dst"; break;
+ }
+
+
+ fprintf (stderr,
+ "rs6000_expand_builtin, %s (%d), insn = %s (%d), type=%s%s\n",
+ (name1) ? name1 : "---", fcode,
+ (name2) ? name2 : "---", (int)icode,
+ name3,
+ func_valid_p ? "" : ", not valid");
+ }
+
+ if (!func_valid_p)
+ {
+ rs6000_invalid_builtin (fcode);
+
+ /* Given it is invalid, just generate a normal call. */
+ return expand_call (exp, target, ignore);
+ }
switch (fcode)
{
gcc_assert (TARGET_ALTIVEC || TARGET_VSX || TARGET_SPE || TARGET_PAIRED_FLOAT);
/* Handle simple unary operations. */
- d = (struct builtin_description *) bdesc_1arg;
+ d = bdesc_1arg;
for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
if (d->code == fcode)
return rs6000_expand_unop_builtin (d->icode, exp, target);
/* Handle simple binary operations. */
- d = (struct builtin_description *) bdesc_2arg;
+ d = bdesc_2arg;
for (i = 0; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
if (d->code == fcode)
return rs6000_expand_binop_builtin (d->icode, exp, target);
{
tree tdecl;
tree ftype;
+ enum machine_mode mode;
+
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr, "rs6000_init_builtins%s%s%s%s\n",
+ (TARGET_PAIRED_FLOAT) ? ", paired" : "",
+ (TARGET_SPE) ? ", spe" : "",
+ (TARGET_ALTIVEC) ? ", altivec" : "",
+ (TARGET_VSX) ? ", vsx" : "");
V2SI_type_node = build_vector_type (intSI_type_node, 2);
V2SF_type_node = build_vector_type (float_type_node, 2);
TYPE_NAME (pixel_V8HI_type_node) = tdecl;
(*lang_hooks.decls.pushdecl) (tdecl);
- if (TARGET_VSX)
- {
- tdecl = build_decl (BUILTINS_LOCATION,
- TYPE_DECL, get_identifier ("__vector double"),
- V2DF_type_node);
- TYPE_NAME (V2DF_type_node) = tdecl;
- (*lang_hooks.decls.pushdecl) (tdecl);
+ tdecl = build_decl (BUILTINS_LOCATION,
+ TYPE_DECL, get_identifier ("__vector double"),
+ V2DF_type_node);
+ TYPE_NAME (V2DF_type_node) = tdecl;
+ (*lang_hooks.decls.pushdecl) (tdecl);
- tdecl = build_decl (BUILTINS_LOCATION,
- TYPE_DECL, get_identifier ("__vector long"),
- V2DI_type_node);
- TYPE_NAME (V2DI_type_node) = tdecl;
- (*lang_hooks.decls.pushdecl) (tdecl);
+ tdecl = build_decl (BUILTINS_LOCATION,
+ TYPE_DECL, get_identifier ("__vector long"),
+ V2DI_type_node);
+ TYPE_NAME (V2DI_type_node) = tdecl;
+ (*lang_hooks.decls.pushdecl) (tdecl);
- tdecl = build_decl (BUILTINS_LOCATION,
- TYPE_DECL, get_identifier ("__vector unsigned long"),
- unsigned_V2DI_type_node);
- TYPE_NAME (unsigned_V2DI_type_node) = tdecl;
- (*lang_hooks.decls.pushdecl) (tdecl);
+ tdecl = build_decl (BUILTINS_LOCATION,
+ TYPE_DECL, get_identifier ("__vector unsigned long"),
+ unsigned_V2DI_type_node);
+ TYPE_NAME (unsigned_V2DI_type_node) = tdecl;
+ (*lang_hooks.decls.pushdecl) (tdecl);
- tdecl = build_decl (BUILTINS_LOCATION,
- TYPE_DECL, get_identifier ("__vector __bool long"),
- bool_V2DI_type_node);
- TYPE_NAME (bool_V2DI_type_node) = tdecl;
- (*lang_hooks.decls.pushdecl) (tdecl);
- }
+ tdecl = build_decl (BUILTINS_LOCATION,
+ TYPE_DECL, get_identifier ("__vector __bool long"),
+ bool_V2DI_type_node);
+ TYPE_NAME (bool_V2DI_type_node) = tdecl;
+ (*lang_hooks.decls.pushdecl) (tdecl);
+ /* Paired and SPE builtins are only available if you build a compiler with
+ the appropriate options, so only create those builtins with the
+ appropriate compiler option. Create Altivec and VSX builtins on machines
+ with at least the general purpose extensions (970 and newer) to allow the
+ use of the target attribute. */
if (TARGET_PAIRED_FLOAT)
paired_init_builtins ();
if (TARGET_SPE)
spe_init_builtins ();
- if (TARGET_ALTIVEC)
+ if (TARGET_EXTRA_BUILTINS)
altivec_init_builtins ();
- if (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT || TARGET_VSX)
+ if (TARGET_EXTRA_BUILTINS || TARGET_SPE || TARGET_PAIRED_FLOAT)
rs6000_common_init_builtins ();
- if (TARGET_FRE)
- {
- ftype = builtin_function_type (DFmode, DFmode, DFmode, VOIDmode,
- RS6000_BUILTIN_RECIP,
- "__builtin_recipdiv");
- def_builtin (MASK_POPCNTB, "__builtin_recipdiv", ftype,
- RS6000_BUILTIN_RECIP);
- }
- if (TARGET_FRES)
- {
- ftype = builtin_function_type (SFmode, SFmode, SFmode, VOIDmode,
- RS6000_BUILTIN_RECIPF,
- "__builtin_recipdivf");
- def_builtin (MASK_PPC_GFXOPT, "__builtin_recipdivf", ftype,
- RS6000_BUILTIN_RECIPF);
- }
- if (TARGET_FRSQRTE)
- {
- ftype = builtin_function_type (DFmode, DFmode, VOIDmode, VOIDmode,
- RS6000_BUILTIN_RSQRT,
- "__builtin_rsqrt");
- def_builtin (MASK_PPC_GFXOPT, "__builtin_rsqrt", ftype,
- RS6000_BUILTIN_RSQRT);
- }
- if (TARGET_FRSQRTES)
- {
- ftype = builtin_function_type (SFmode, SFmode, VOIDmode, VOIDmode,
- RS6000_BUILTIN_RSQRTF,
- "__builtin_rsqrtf");
- def_builtin (MASK_PPC_GFXOPT, "__builtin_rsqrtf", ftype,
- RS6000_BUILTIN_RSQRTF);
- }
- if (TARGET_POPCNTD)
- {
- enum machine_mode mode = (TARGET_64BIT) ? DImode : SImode;
- tree ftype = builtin_function_type (mode, mode, mode, VOIDmode,
- POWER7_BUILTIN_BPERMD,
- "__builtin_bpermd");
- def_builtin (MASK_POPCNTD, "__builtin_bpermd", ftype,
- POWER7_BUILTIN_BPERMD);
- }
- if (TARGET_POWERPC)
- {
+
+ ftype = builtin_function_type (DFmode, DFmode, DFmode, VOIDmode,
+ RS6000_BUILTIN_RECIP, "__builtin_recipdiv");
+ def_builtin ("__builtin_recipdiv", ftype, RS6000_BUILTIN_RECIP);
+
+ ftype = builtin_function_type (SFmode, SFmode, SFmode, VOIDmode,
+ RS6000_BUILTIN_RECIPF, "__builtin_recipdivf");
+ def_builtin ("__builtin_recipdivf", ftype, RS6000_BUILTIN_RECIPF);
+
+ ftype = builtin_function_type (DFmode, DFmode, VOIDmode, VOIDmode,
+ RS6000_BUILTIN_RSQRT, "__builtin_rsqrt");
+ def_builtin ("__builtin_rsqrt", ftype, RS6000_BUILTIN_RSQRT);
+
+ ftype = builtin_function_type (SFmode, SFmode, VOIDmode, VOIDmode,
+ RS6000_BUILTIN_RSQRTF, "__builtin_rsqrtf");
+ def_builtin ("__builtin_rsqrtf", ftype, RS6000_BUILTIN_RSQRTF);
+
+ mode = (TARGET_64BIT) ? DImode : SImode;
+ ftype = builtin_function_type (mode, mode, mode, VOIDmode,
+ POWER7_BUILTIN_BPERMD, "__builtin_bpermd");
+ def_builtin ("__builtin_bpermd", ftype, POWER7_BUILTIN_BPERMD);
+
/* Don't use builtin_function_type here, as it maps HI/QI to SI. */
- tree ftype = build_function_type_list (unsigned_intHI_type_node,
- unsigned_intHI_type_node,
- NULL_TREE);
- def_builtin (MASK_POWERPC, "__builtin_bswap16", ftype,
- RS6000_BUILTIN_BSWAP_HI);
- }
+ ftype = build_function_type_list (unsigned_intHI_type_node,
+ unsigned_intHI_type_node,
+ NULL_TREE);
+ def_builtin ("__builtin_bswap16", ftype, RS6000_BUILTIN_BSWAP_HI);
#if TARGET_XCOFF
/* AIX libm provides clog as __clog. */
- if (built_in_decls [BUILT_IN_CLOG])
- set_user_assembler_name (built_in_decls [BUILT_IN_CLOG], "__clog");
+ if ((tdecl = builtin_decl_explicit (BUILT_IN_CLOG)) != NULL_TREE)
+ set_user_assembler_name (tdecl, "__clog");
#endif
#ifdef SUBTARGET_INIT_BUILTINS
static tree
rs6000_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
{
+ unsigned fnmask;
+
if (code >= RS6000_BUILTIN_COUNT)
return error_mark_node;
- return rs6000_builtin_decls[code];
-}
-
-/* Search through a set of builtins and enable the mask bits.
- DESC is an array of builtins.
- SIZE is the total number of builtins.
- START is the builtin enum at which to start.
- END is the builtin enum at which to end. */
-static void
-enable_mask_for_builtins (struct builtin_description *desc, int size,
- enum rs6000_builtins start,
- enum rs6000_builtins end)
-{
- int i;
-
- for (i = 0; i < size; ++i)
- if (desc[i].code == start)
- break;
-
- if (i == size)
- return;
-
- for (; i < size; ++i)
+ fnmask = rs6000_builtin_info[code].mask;
+ if ((fnmask & rs6000_builtin_mask) != fnmask)
{
- /* Flip all the bits on. */
- desc[i].mask = target_flags;
- if (desc[i].code == end)
- break;
+ rs6000_invalid_builtin ((enum rs6000_builtins)code);
+ return error_mark_node;
}
+
+ return rs6000_builtin_decls[code];
}
static void
spe_init_builtins (void)
{
- tree endlink = void_list_node;
tree puint_type_node = build_pointer_type (unsigned_type_node);
tree pushort_type_node = build_pointer_type (short_unsigned_type_node);
- struct builtin_description *d;
+ const struct builtin_description *d;
size_t i;
tree v2si_ftype_4_v2si
- = build_function_type
- (opaque_V2SI_type_node,
- tree_cons (NULL_TREE, opaque_V2SI_type_node,
- tree_cons (NULL_TREE, opaque_V2SI_type_node,
- tree_cons (NULL_TREE, opaque_V2SI_type_node,
- tree_cons (NULL_TREE, opaque_V2SI_type_node,
- endlink)))));
+ = build_function_type_list (opaque_V2SI_type_node,
+ opaque_V2SI_type_node,
+ opaque_V2SI_type_node,
+ opaque_V2SI_type_node,
+ opaque_V2SI_type_node,
+ NULL_TREE);
tree v2sf_ftype_4_v2sf
- = build_function_type
- (opaque_V2SF_type_node,
- tree_cons (NULL_TREE, opaque_V2SF_type_node,
- tree_cons (NULL_TREE, opaque_V2SF_type_node,
- tree_cons (NULL_TREE, opaque_V2SF_type_node,
- tree_cons (NULL_TREE, opaque_V2SF_type_node,
- endlink)))));
+ = build_function_type_list (opaque_V2SF_type_node,
+ opaque_V2SF_type_node,
+ opaque_V2SF_type_node,
+ opaque_V2SF_type_node,
+ opaque_V2SF_type_node,
+ NULL_TREE);
tree int_ftype_int_v2si_v2si
- = build_function_type
- (integer_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE, opaque_V2SI_type_node,
- tree_cons (NULL_TREE, opaque_V2SI_type_node,
- endlink))));
+ = build_function_type_list (integer_type_node,
+ integer_type_node,
+ opaque_V2SI_type_node,
+ opaque_V2SI_type_node,
+ NULL_TREE);
tree int_ftype_int_v2sf_v2sf
- = build_function_type
- (integer_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE, opaque_V2SF_type_node,
- tree_cons (NULL_TREE, opaque_V2SF_type_node,
- endlink))));
+ = build_function_type_list (integer_type_node,
+ integer_type_node,
+ opaque_V2SF_type_node,
+ opaque_V2SF_type_node,
+ NULL_TREE);
tree void_ftype_v2si_puint_int
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, opaque_V2SI_type_node,
- tree_cons (NULL_TREE, puint_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))));
+ = build_function_type_list (void_type_node,
+ opaque_V2SI_type_node,
+ puint_type_node,
+ integer_type_node,
+ NULL_TREE);
tree void_ftype_v2si_puint_char
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, opaque_V2SI_type_node,
- tree_cons (NULL_TREE, puint_type_node,
- tree_cons (NULL_TREE,
- char_type_node,
- endlink))));
+ = build_function_type_list (void_type_node,
+ opaque_V2SI_type_node,
+ puint_type_node,
+ char_type_node,
+ NULL_TREE);
tree void_ftype_v2si_pv2si_int
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, opaque_V2SI_type_node,
- tree_cons (NULL_TREE, opaque_p_V2SI_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))));
+ = build_function_type_list (void_type_node,
+ opaque_V2SI_type_node,
+ opaque_p_V2SI_type_node,
+ integer_type_node,
+ NULL_TREE);
tree void_ftype_v2si_pv2si_char
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, opaque_V2SI_type_node,
- tree_cons (NULL_TREE, opaque_p_V2SI_type_node,
- tree_cons (NULL_TREE,
- char_type_node,
- endlink))));
+ = build_function_type_list (void_type_node,
+ opaque_V2SI_type_node,
+ opaque_p_V2SI_type_node,
+ char_type_node,
+ NULL_TREE);
tree void_ftype_int
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, integer_type_node, endlink));
+ = build_function_type_list (void_type_node, integer_type_node, NULL_TREE);
tree int_ftype_void
- = build_function_type (integer_type_node, endlink);
+ = build_function_type_list (integer_type_node, NULL_TREE);
tree v2si_ftype_pv2si_int
- = build_function_type (opaque_V2SI_type_node,
- tree_cons (NULL_TREE, opaque_p_V2SI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- endlink)));
+ = build_function_type_list (opaque_V2SI_type_node,
+ opaque_p_V2SI_type_node,
+ integer_type_node,
+ NULL_TREE);
tree v2si_ftype_puint_int
- = build_function_type (opaque_V2SI_type_node,
- tree_cons (NULL_TREE, puint_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- endlink)));
+ = build_function_type_list (opaque_V2SI_type_node,
+ puint_type_node,
+ integer_type_node,
+ NULL_TREE);
tree v2si_ftype_pushort_int
- = build_function_type (opaque_V2SI_type_node,
- tree_cons (NULL_TREE, pushort_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- endlink)));
+ = build_function_type_list (opaque_V2SI_type_node,
+ pushort_type_node,
+ integer_type_node,
+ NULL_TREE);
tree v2si_ftype_signed_char
- = build_function_type (opaque_V2SI_type_node,
- tree_cons (NULL_TREE, signed_char_type_node,
- endlink));
-
- /* The initialization of the simple binary and unary builtins is
- done in rs6000_common_init_builtins, but we have to enable the
- mask bits here manually because we have run out of `target_flags'
- bits. We really need to redesign this mask business. */
-
- enable_mask_for_builtins ((struct builtin_description *) bdesc_2arg,
- ARRAY_SIZE (bdesc_2arg),
- SPE_BUILTIN_EVADDW,
- SPE_BUILTIN_EVXOR);
- enable_mask_for_builtins ((struct builtin_description *) bdesc_1arg,
- ARRAY_SIZE (bdesc_1arg),
- SPE_BUILTIN_EVABS,
- SPE_BUILTIN_EVSUBFUSIAAW);
- enable_mask_for_builtins ((struct builtin_description *) bdesc_spe_predicates,
- ARRAY_SIZE (bdesc_spe_predicates),
- SPE_BUILTIN_EVCMPEQ,
- SPE_BUILTIN_EVFSTSTLT);
- enable_mask_for_builtins ((struct builtin_description *) bdesc_spe_evsel,
- ARRAY_SIZE (bdesc_spe_evsel),
- SPE_BUILTIN_EVSEL_CMPGTS,
- SPE_BUILTIN_EVSEL_FSTSTEQ);
+ = build_function_type_list (opaque_V2SI_type_node,
+ signed_char_type_node,
+ NULL_TREE);
(*lang_hooks.decls.pushdecl)
(build_decl (BUILTINS_LOCATION, TYPE_DECL,
/* Initialize irregular SPE builtins. */
- def_builtin (target_flags, "__builtin_spe_mtspefscr", void_ftype_int, SPE_BUILTIN_MTSPEFSCR);
- def_builtin (target_flags, "__builtin_spe_mfspefscr", int_ftype_void, SPE_BUILTIN_MFSPEFSCR);
- def_builtin (target_flags, "__builtin_spe_evstddx", void_ftype_v2si_pv2si_int, SPE_BUILTIN_EVSTDDX);
- def_builtin (target_flags, "__builtin_spe_evstdhx", void_ftype_v2si_pv2si_int, SPE_BUILTIN_EVSTDHX);
- def_builtin (target_flags, "__builtin_spe_evstdwx", void_ftype_v2si_pv2si_int, SPE_BUILTIN_EVSTDWX);
- def_builtin (target_flags, "__builtin_spe_evstwhex", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWHEX);
- def_builtin (target_flags, "__builtin_spe_evstwhox", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWHOX);
- def_builtin (target_flags, "__builtin_spe_evstwwex", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWWEX);
- def_builtin (target_flags, "__builtin_spe_evstwwox", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWWOX);
- def_builtin (target_flags, "__builtin_spe_evstdd", void_ftype_v2si_pv2si_char, SPE_BUILTIN_EVSTDD);
- def_builtin (target_flags, "__builtin_spe_evstdh", void_ftype_v2si_pv2si_char, SPE_BUILTIN_EVSTDH);
- def_builtin (target_flags, "__builtin_spe_evstdw", void_ftype_v2si_pv2si_char, SPE_BUILTIN_EVSTDW);
- def_builtin (target_flags, "__builtin_spe_evstwhe", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWHE);
- def_builtin (target_flags, "__builtin_spe_evstwho", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWHO);
- def_builtin (target_flags, "__builtin_spe_evstwwe", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWWE);
- def_builtin (target_flags, "__builtin_spe_evstwwo", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWWO);
- def_builtin (target_flags, "__builtin_spe_evsplatfi", v2si_ftype_signed_char, SPE_BUILTIN_EVSPLATFI);
- def_builtin (target_flags, "__builtin_spe_evsplati", v2si_ftype_signed_char, SPE_BUILTIN_EVSPLATI);
+ def_builtin ("__builtin_spe_mtspefscr", void_ftype_int, SPE_BUILTIN_MTSPEFSCR);
+ def_builtin ("__builtin_spe_mfspefscr", int_ftype_void, SPE_BUILTIN_MFSPEFSCR);
+ def_builtin ("__builtin_spe_evstddx", void_ftype_v2si_pv2si_int, SPE_BUILTIN_EVSTDDX);
+ def_builtin ("__builtin_spe_evstdhx", void_ftype_v2si_pv2si_int, SPE_BUILTIN_EVSTDHX);
+ def_builtin ("__builtin_spe_evstdwx", void_ftype_v2si_pv2si_int, SPE_BUILTIN_EVSTDWX);
+ def_builtin ("__builtin_spe_evstwhex", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWHEX);
+ def_builtin ("__builtin_spe_evstwhox", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWHOX);
+ def_builtin ("__builtin_spe_evstwwex", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWWEX);
+ def_builtin ("__builtin_spe_evstwwox", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWWOX);
+ def_builtin ("__builtin_spe_evstdd", void_ftype_v2si_pv2si_char, SPE_BUILTIN_EVSTDD);
+ def_builtin ("__builtin_spe_evstdh", void_ftype_v2si_pv2si_char, SPE_BUILTIN_EVSTDH);
+ def_builtin ("__builtin_spe_evstdw", void_ftype_v2si_pv2si_char, SPE_BUILTIN_EVSTDW);
+ def_builtin ("__builtin_spe_evstwhe", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWHE);
+ def_builtin ("__builtin_spe_evstwho", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWHO);
+ def_builtin ("__builtin_spe_evstwwe", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWWE);
+ def_builtin ("__builtin_spe_evstwwo", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWWO);
+ def_builtin ("__builtin_spe_evsplatfi", v2si_ftype_signed_char, SPE_BUILTIN_EVSPLATFI);
+ def_builtin ("__builtin_spe_evsplati", v2si_ftype_signed_char, SPE_BUILTIN_EVSPLATI);
/* Loads. */
- def_builtin (target_flags, "__builtin_spe_evlddx", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDDX);
- def_builtin (target_flags, "__builtin_spe_evldwx", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDWX);
- def_builtin (target_flags, "__builtin_spe_evldhx", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDHX);
- def_builtin (target_flags, "__builtin_spe_evlwhex", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHEX);
- def_builtin (target_flags, "__builtin_spe_evlwhoux", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOUX);
- def_builtin (target_flags, "__builtin_spe_evlwhosx", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOSX);
- def_builtin (target_flags, "__builtin_spe_evlwwsplatx", v2si_ftype_puint_int, SPE_BUILTIN_EVLWWSPLATX);
- def_builtin (target_flags, "__builtin_spe_evlwhsplatx", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHSPLATX);
- def_builtin (target_flags, "__builtin_spe_evlhhesplatx", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHESPLATX);
- def_builtin (target_flags, "__builtin_spe_evlhhousplatx", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOUSPLATX);
- def_builtin (target_flags, "__builtin_spe_evlhhossplatx", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOSSPLATX);
- def_builtin (target_flags, "__builtin_spe_evldd", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDD);
- def_builtin (target_flags, "__builtin_spe_evldw", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDW);
- def_builtin (target_flags, "__builtin_spe_evldh", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDH);
- def_builtin (target_flags, "__builtin_spe_evlhhesplat", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHESPLAT);
- def_builtin (target_flags, "__builtin_spe_evlhhossplat", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOSSPLAT);
- def_builtin (target_flags, "__builtin_spe_evlhhousplat", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOUSPLAT);
- def_builtin (target_flags, "__builtin_spe_evlwhe", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHE);
- def_builtin (target_flags, "__builtin_spe_evlwhos", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOS);
- def_builtin (target_flags, "__builtin_spe_evlwhou", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOU);
- def_builtin (target_flags, "__builtin_spe_evlwhsplat", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHSPLAT);
- def_builtin (target_flags, "__builtin_spe_evlwwsplat", v2si_ftype_puint_int, SPE_BUILTIN_EVLWWSPLAT);
+ def_builtin ("__builtin_spe_evlddx", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDDX);
+ def_builtin ("__builtin_spe_evldwx", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDWX);
+ def_builtin ("__builtin_spe_evldhx", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDHX);
+ def_builtin ("__builtin_spe_evlwhex", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHEX);
+ def_builtin ("__builtin_spe_evlwhoux", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOUX);
+ def_builtin ("__builtin_spe_evlwhosx", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOSX);
+ def_builtin ("__builtin_spe_evlwwsplatx", v2si_ftype_puint_int, SPE_BUILTIN_EVLWWSPLATX);
+ def_builtin ("__builtin_spe_evlwhsplatx", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHSPLATX);
+ def_builtin ("__builtin_spe_evlhhesplatx", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHESPLATX);
+ def_builtin ("__builtin_spe_evlhhousplatx", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOUSPLATX);
+ def_builtin ("__builtin_spe_evlhhossplatx", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOSSPLATX);
+ def_builtin ("__builtin_spe_evldd", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDD);
+ def_builtin ("__builtin_spe_evldw", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDW);
+ def_builtin ("__builtin_spe_evldh", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDH);
+ def_builtin ("__builtin_spe_evlhhesplat", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHESPLAT);
+ def_builtin ("__builtin_spe_evlhhossplat", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOSSPLAT);
+ def_builtin ("__builtin_spe_evlhhousplat", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOUSPLAT);
+ def_builtin ("__builtin_spe_evlwhe", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHE);
+ def_builtin ("__builtin_spe_evlwhos", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOS);
+ def_builtin ("__builtin_spe_evlwhou", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOU);
+ def_builtin ("__builtin_spe_evlwhsplat", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHSPLAT);
+ def_builtin ("__builtin_spe_evlwwsplat", v2si_ftype_puint_int, SPE_BUILTIN_EVLWWSPLAT);
/* Predicates. */
- d = (struct builtin_description *) bdesc_spe_predicates;
+ d = bdesc_spe_predicates;
for (i = 0; i < ARRAY_SIZE (bdesc_spe_predicates); ++i, d++)
{
tree type;
gcc_unreachable ();
}
- def_builtin (d->mask, d->name, type, d->code);
+ def_builtin (d->name, type, d->code);
}
/* Evsel predicates. */
- d = (struct builtin_description *) bdesc_spe_evsel;
+ d = bdesc_spe_evsel;
for (i = 0; i < ARRAY_SIZE (bdesc_spe_evsel); ++i, d++)
{
tree type;
gcc_unreachable ();
}
- def_builtin (d->mask, d->name, type, d->code);
+ def_builtin (d->name, type, d->code);
}
}
{
const struct builtin_description *d;
size_t i;
- tree endlink = void_list_node;
tree int_ftype_int_v2sf_v2sf
- = build_function_type
- (integer_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE, V2SF_type_node,
- tree_cons (NULL_TREE, V2SF_type_node,
- endlink))));
+ = build_function_type_list (integer_type_node,
+ integer_type_node,
+ V2SF_type_node,
+ V2SF_type_node,
+ NULL_TREE);
tree pcfloat_type_node =
build_pointer_type (build_qualified_type
(float_type_node, TYPE_QUAL_CONST));
NULL_TREE);
- def_builtin (0, "__builtin_paired_lx", v2sf_ftype_long_pcfloat,
+ def_builtin ("__builtin_paired_lx", v2sf_ftype_long_pcfloat,
PAIRED_BUILTIN_LX);
- def_builtin (0, "__builtin_paired_stx", void_ftype_v2sf_long_pcfloat,
+ def_builtin ("__builtin_paired_stx", void_ftype_v2sf_long_pcfloat,
PAIRED_BUILTIN_STX);
/* Predicates. */
{
tree type;
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr, "paired pred #%d, insn = %s [%d], mode = %s\n",
+ (int)i, get_insn_name (d->icode), (int)d->icode,
+ GET_MODE_NAME (insn_data[d->icode].operand[1].mode));
+
switch (insn_data[d->icode].operand[1].mode)
{
case V2SFmode:
gcc_unreachable ();
}
- def_builtin (d->mask, d->name, type, d->code);
+ def_builtin (d->name, type, d->code);
}
}
altivec_init_builtins (void)
{
const struct builtin_description *d;
- const struct builtin_description_predicates *dp;
size_t i;
tree ftype;
+ tree decl;
tree pvoid_type_node = build_pointer_type (void_type_node);
= build_function_type_list (integer_type_node,
opaque_V4SI_type_node, NULL_TREE);
tree opaque_ftype_opaque
- = build_function_type (integer_type_node,
- NULL_TREE);
+ = build_function_type_list (integer_type_node, NULL_TREE);
tree opaque_ftype_opaque_int
= build_function_type_list (opaque_V4SI_type_node,
opaque_V4SI_type_node, integer_type_node, NULL_TREE);
tree void_ftype_v4si
= build_function_type_list (void_type_node, V4SI_type_node, NULL_TREE);
tree v8hi_ftype_void
- = build_function_type (V8HI_type_node, void_list_node);
+ = build_function_type_list (V8HI_type_node, NULL_TREE);
tree void_ftype_void
- = build_function_type (void_type_node, void_list_node);
+ = build_function_type_list (void_type_node, NULL_TREE);
tree void_ftype_int
= build_function_type_list (void_type_node, integer_type_node, NULL_TREE);
pcvoid_type_node, integer_type_node,
integer_type_node, NULL_TREE);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_mtvscr", void_ftype_v4si, ALTIVEC_BUILTIN_MTVSCR);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_mfvscr", v8hi_ftype_void, ALTIVEC_BUILTIN_MFVSCR);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_dssall", void_ftype_void, ALTIVEC_BUILTIN_DSSALL);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_dss", void_ftype_int, ALTIVEC_BUILTIN_DSS);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvsl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVSL);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvsr", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVSR);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvebx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEBX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvehx", v8hi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEHX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvewx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEWX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvxl", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVXL);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvx", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvewx", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVEWX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvxl", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVXL);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvebx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVEBX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvehx", void_ftype_v8hi_long_pvoid, ALTIVEC_BUILTIN_STVEHX);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_ld", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LD);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_lde", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LDE);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_ldl", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LDL);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_lvsl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVSL);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_lvsr", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVSR);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_lvebx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEBX);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_lvehx", v8hi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEHX);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_lvewx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEWX);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_st", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_ST);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_ste", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STE);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_stl", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STL);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_stvewx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEWX);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_stvebx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEBX);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_stvehx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEHX);
-
- def_builtin (MASK_VSX, "__builtin_vsx_lxvd2x_v2df", v2df_ftype_long_pcvoid,
+ def_builtin ("__builtin_altivec_mtvscr", void_ftype_v4si, ALTIVEC_BUILTIN_MTVSCR);
+ def_builtin ("__builtin_altivec_mfvscr", v8hi_ftype_void, ALTIVEC_BUILTIN_MFVSCR);
+ def_builtin ("__builtin_altivec_dssall", void_ftype_void, ALTIVEC_BUILTIN_DSSALL);
+ def_builtin ("__builtin_altivec_dss", void_ftype_int, ALTIVEC_BUILTIN_DSS);
+ def_builtin ("__builtin_altivec_lvsl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVSL);
+ def_builtin ("__builtin_altivec_lvsr", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVSR);
+ def_builtin ("__builtin_altivec_lvebx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEBX);
+ def_builtin ("__builtin_altivec_lvehx", v8hi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEHX);
+ def_builtin ("__builtin_altivec_lvewx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEWX);
+ def_builtin ("__builtin_altivec_lvxl", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVXL);
+ def_builtin ("__builtin_altivec_lvx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVX);
+ def_builtin ("__builtin_altivec_stvx", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVX);
+ def_builtin ("__builtin_altivec_stvewx", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVEWX);
+ def_builtin ("__builtin_altivec_stvxl", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVXL);
+ def_builtin ("__builtin_altivec_stvebx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVEBX);
+ def_builtin ("__builtin_altivec_stvehx", void_ftype_v8hi_long_pvoid, ALTIVEC_BUILTIN_STVEHX);
+ def_builtin ("__builtin_vec_ld", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LD);
+ def_builtin ("__builtin_vec_lde", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LDE);
+ def_builtin ("__builtin_vec_ldl", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LDL);
+ def_builtin ("__builtin_vec_lvsl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVSL);
+ def_builtin ("__builtin_vec_lvsr", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVSR);
+ def_builtin ("__builtin_vec_lvebx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEBX);
+ def_builtin ("__builtin_vec_lvehx", v8hi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEHX);
+ def_builtin ("__builtin_vec_lvewx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEWX);
+ def_builtin ("__builtin_vec_st", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_ST);
+ def_builtin ("__builtin_vec_ste", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STE);
+ def_builtin ("__builtin_vec_stl", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STL);
+ def_builtin ("__builtin_vec_stvewx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEWX);
+ def_builtin ("__builtin_vec_stvebx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEBX);
+ def_builtin ("__builtin_vec_stvehx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEHX);
+
+ def_builtin ("__builtin_vsx_lxvd2x_v2df", v2df_ftype_long_pcvoid,
VSX_BUILTIN_LXVD2X_V2DF);
- def_builtin (MASK_VSX, "__builtin_vsx_lxvd2x_v2di", v2di_ftype_long_pcvoid,
+ def_builtin ("__builtin_vsx_lxvd2x_v2di", v2di_ftype_long_pcvoid,
VSX_BUILTIN_LXVD2X_V2DI);
- def_builtin (MASK_VSX, "__builtin_vsx_lxvw4x_v4sf", v4sf_ftype_long_pcvoid,
+ def_builtin ("__builtin_vsx_lxvw4x_v4sf", v4sf_ftype_long_pcvoid,
VSX_BUILTIN_LXVW4X_V4SF);
- def_builtin (MASK_VSX, "__builtin_vsx_lxvw4x_v4si", v4si_ftype_long_pcvoid,
+ def_builtin ("__builtin_vsx_lxvw4x_v4si", v4si_ftype_long_pcvoid,
VSX_BUILTIN_LXVW4X_V4SI);
- def_builtin (MASK_VSX, "__builtin_vsx_lxvw4x_v8hi",
- v8hi_ftype_long_pcvoid, VSX_BUILTIN_LXVW4X_V8HI);
- def_builtin (MASK_VSX, "__builtin_vsx_lxvw4x_v16qi",
- v16qi_ftype_long_pcvoid, VSX_BUILTIN_LXVW4X_V16QI);
- def_builtin (MASK_VSX, "__builtin_vsx_stxvd2x_v2df",
- void_ftype_v2df_long_pvoid, VSX_BUILTIN_STXVD2X_V2DF);
- def_builtin (MASK_VSX, "__builtin_vsx_stxvd2x_v2di",
- void_ftype_v2di_long_pvoid, VSX_BUILTIN_STXVD2X_V2DI);
- def_builtin (MASK_VSX, "__builtin_vsx_stxvw4x_v4sf",
- void_ftype_v4sf_long_pvoid, VSX_BUILTIN_STXVW4X_V4SF);
- def_builtin (MASK_VSX, "__builtin_vsx_stxvw4x_v4si",
- void_ftype_v4si_long_pvoid, VSX_BUILTIN_STXVW4X_V4SI);
- def_builtin (MASK_VSX, "__builtin_vsx_stxvw4x_v8hi",
- void_ftype_v8hi_long_pvoid, VSX_BUILTIN_STXVW4X_V8HI);
- def_builtin (MASK_VSX, "__builtin_vsx_stxvw4x_v16qi",
- void_ftype_v16qi_long_pvoid, VSX_BUILTIN_STXVW4X_V16QI);
- def_builtin (MASK_VSX, "__builtin_vec_vsx_ld", opaque_ftype_long_pcvoid,
+ def_builtin ("__builtin_vsx_lxvw4x_v8hi", v8hi_ftype_long_pcvoid,
+ VSX_BUILTIN_LXVW4X_V8HI);
+ def_builtin ("__builtin_vsx_lxvw4x_v16qi", v16qi_ftype_long_pcvoid,
+ VSX_BUILTIN_LXVW4X_V16QI);
+ def_builtin ("__builtin_vsx_stxvd2x_v2df", void_ftype_v2df_long_pvoid,
+ VSX_BUILTIN_STXVD2X_V2DF);
+ def_builtin ("__builtin_vsx_stxvd2x_v2di", void_ftype_v2di_long_pvoid,
+ VSX_BUILTIN_STXVD2X_V2DI);
+ def_builtin ("__builtin_vsx_stxvw4x_v4sf", void_ftype_v4sf_long_pvoid,
+ VSX_BUILTIN_STXVW4X_V4SF);
+ def_builtin ("__builtin_vsx_stxvw4x_v4si", void_ftype_v4si_long_pvoid,
+ VSX_BUILTIN_STXVW4X_V4SI);
+ def_builtin ("__builtin_vsx_stxvw4x_v8hi", void_ftype_v8hi_long_pvoid,
+ VSX_BUILTIN_STXVW4X_V8HI);
+ def_builtin ("__builtin_vsx_stxvw4x_v16qi", void_ftype_v16qi_long_pvoid,
+ VSX_BUILTIN_STXVW4X_V16QI);
+ def_builtin ("__builtin_vec_vsx_ld", opaque_ftype_long_pcvoid,
VSX_BUILTIN_VEC_LD);
- def_builtin (MASK_VSX, "__builtin_vec_vsx_st", void_ftype_opaque_long_pvoid,
+ def_builtin ("__builtin_vec_vsx_st", void_ftype_opaque_long_pvoid,
VSX_BUILTIN_VEC_ST);
- if (rs6000_cpu == PROCESSOR_CELL)
- {
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvlx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVLX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvlxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVLXL);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvrx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVRX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvrxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVRXL);
-
- def_builtin (MASK_ALTIVEC, "__builtin_vec_lvlx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVLX);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_lvlxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVLXL);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_lvrx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVRX);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_lvrxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVRXL);
-
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvlx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVLX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvlxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVLXL);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvrx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVRX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvrxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVRXL);
-
- def_builtin (MASK_ALTIVEC, "__builtin_vec_stvlx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVLX);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_stvlxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVLXL);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_stvrx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVRX);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_stvrxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVRXL);
- }
- def_builtin (MASK_ALTIVEC, "__builtin_vec_step", int_ftype_opaque, ALTIVEC_BUILTIN_VEC_STEP);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_splats", opaque_ftype_opaque, ALTIVEC_BUILTIN_VEC_SPLATS);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_promote", opaque_ftype_opaque, ALTIVEC_BUILTIN_VEC_PROMOTE);
-
- def_builtin (MASK_ALTIVEC, "__builtin_vec_sld", opaque_ftype_opaque_opaque_int, ALTIVEC_BUILTIN_VEC_SLD);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_splat", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_SPLAT);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_extract", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_EXTRACT);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_insert", opaque_ftype_opaque_opaque_int, ALTIVEC_BUILTIN_VEC_INSERT);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_vspltw", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTW);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_vsplth", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTH);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_vspltb", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTB);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_ctf", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTF);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_vcfsx", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VCFSX);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_vcfux", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VCFUX);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_cts", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTS);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_ctu", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTU);
+ def_builtin ("__builtin_vec_step", int_ftype_opaque, ALTIVEC_BUILTIN_VEC_STEP);
+ def_builtin ("__builtin_vec_splats", opaque_ftype_opaque, ALTIVEC_BUILTIN_VEC_SPLATS);
+ def_builtin ("__builtin_vec_promote", opaque_ftype_opaque, ALTIVEC_BUILTIN_VEC_PROMOTE);
+
+ def_builtin ("__builtin_vec_sld", opaque_ftype_opaque_opaque_int, ALTIVEC_BUILTIN_VEC_SLD);
+ def_builtin ("__builtin_vec_splat", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_SPLAT);
+ def_builtin ("__builtin_vec_extract", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_EXTRACT);
+ def_builtin ("__builtin_vec_insert", opaque_ftype_opaque_opaque_int, ALTIVEC_BUILTIN_VEC_INSERT);
+ def_builtin ("__builtin_vec_vspltw", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTW);
+ def_builtin ("__builtin_vec_vsplth", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTH);
+ def_builtin ("__builtin_vec_vspltb", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTB);
+ def_builtin ("__builtin_vec_ctf", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTF);
+ def_builtin ("__builtin_vec_vcfsx", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VCFSX);
+ def_builtin ("__builtin_vec_vcfux", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VCFUX);
+ def_builtin ("__builtin_vec_cts", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTS);
+ def_builtin ("__builtin_vec_ctu", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTU);
+
+ /* Cell builtins. */
+ def_builtin ("__builtin_altivec_lvlx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVLX);
+ def_builtin ("__builtin_altivec_lvlxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVLXL);
+ def_builtin ("__builtin_altivec_lvrx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVRX);
+ def_builtin ("__builtin_altivec_lvrxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVRXL);
+
+ def_builtin ("__builtin_vec_lvlx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVLX);
+ def_builtin ("__builtin_vec_lvlxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVLXL);
+ def_builtin ("__builtin_vec_lvrx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVRX);
+ def_builtin ("__builtin_vec_lvrxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVRXL);
+
+ def_builtin ("__builtin_altivec_stvlx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVLX);
+ def_builtin ("__builtin_altivec_stvlxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVLXL);
+ def_builtin ("__builtin_altivec_stvrx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVRX);
+ def_builtin ("__builtin_altivec_stvrxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVRXL);
+
+ def_builtin ("__builtin_vec_stvlx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVLX);
+ def_builtin ("__builtin_vec_stvlxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVLXL);
+ def_builtin ("__builtin_vec_stvrx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVRX);
+ def_builtin ("__builtin_vec_stvrxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVRXL);
/* Add the DST variants. */
d = bdesc_dst;
for (i = 0; i < ARRAY_SIZE (bdesc_dst); i++, d++)
- def_builtin (d->mask, d->name, void_ftype_pcvoid_int_int, d->code);
+ def_builtin (d->name, void_ftype_pcvoid_int_int, d->code);
/* Initialize the predicates. */
- dp = bdesc_altivec_preds;
- for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, dp++)
+ d = bdesc_altivec_preds;
+ for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, d++)
{
enum machine_mode mode1;
tree type;
- bool is_overloaded = ((dp->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
- && dp->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
- || (dp->code >= VSX_BUILTIN_OVERLOADED_FIRST
- && dp->code <= VSX_BUILTIN_OVERLOADED_LAST));
- if (is_overloaded)
+ if (rs6000_overloaded_builtin_p (d->code))
mode1 = VOIDmode;
else
- mode1 = insn_data[dp->icode].operand[1].mode;
+ mode1 = insn_data[d->icode].operand[1].mode;
switch (mode1)
{
gcc_unreachable ();
}
- def_builtin (dp->mask, dp->name, type, dp->code);
+ def_builtin (d->name, type, d->code);
}
/* Initialize the abs* operators. */
gcc_unreachable ();
}
- def_builtin (d->mask, d->name, type, d->code);
+ def_builtin (d->name, type, d->code);
}
- if (TARGET_ALTIVEC)
- {
- tree decl;
-
- /* Initialize target builtin that implements
- targetm.vectorize.builtin_mask_for_load. */
+ /* Initialize target builtin that implements
+ targetm.vectorize.builtin_mask_for_load. */
- decl = add_builtin_function ("__builtin_altivec_mask_for_load",
- v16qi_ftype_long_pcvoid,
- ALTIVEC_BUILTIN_MASK_FOR_LOAD,
- BUILT_IN_MD, NULL, NULL_TREE);
- TREE_READONLY (decl) = 1;
- /* Record the decl. Will be used by rs6000_builtin_mask_for_load. */
- altivec_builtin_mask_for_load = decl;
- }
+ decl = add_builtin_function ("__builtin_altivec_mask_for_load",
+ v16qi_ftype_long_pcvoid,
+ ALTIVEC_BUILTIN_MASK_FOR_LOAD,
+ BUILT_IN_MD, NULL, NULL_TREE);
+ TREE_READONLY (decl) = 1;
+ /* Record the decl. Will be used by rs6000_builtin_mask_for_load. */
+ altivec_builtin_mask_for_load = decl;
/* Access to the vec_init patterns. */
ftype = build_function_type_list (V4SI_type_node, integer_type_node,
integer_type_node, integer_type_node,
integer_type_node, NULL_TREE);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_init_v4si", ftype,
- ALTIVEC_BUILTIN_VEC_INIT_V4SI);
+ def_builtin ("__builtin_vec_init_v4si", ftype, ALTIVEC_BUILTIN_VEC_INIT_V4SI);
ftype = build_function_type_list (V8HI_type_node, short_integer_type_node,
short_integer_type_node,
short_integer_type_node,
short_integer_type_node,
short_integer_type_node, NULL_TREE);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_init_v8hi", ftype,
- ALTIVEC_BUILTIN_VEC_INIT_V8HI);
+ def_builtin ("__builtin_vec_init_v8hi", ftype, ALTIVEC_BUILTIN_VEC_INIT_V8HI);
ftype = build_function_type_list (V16QI_type_node, char_type_node,
char_type_node, char_type_node,
char_type_node, char_type_node,
char_type_node, char_type_node,
char_type_node, NULL_TREE);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_init_v16qi", ftype,
+ def_builtin ("__builtin_vec_init_v16qi", ftype,
ALTIVEC_BUILTIN_VEC_INIT_V16QI);
ftype = build_function_type_list (V4SF_type_node, float_type_node,
float_type_node, float_type_node,
float_type_node, NULL_TREE);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_init_v4sf", ftype,
- ALTIVEC_BUILTIN_VEC_INIT_V4SF);
+ def_builtin ("__builtin_vec_init_v4sf", ftype, ALTIVEC_BUILTIN_VEC_INIT_V4SF);
- if (TARGET_VSX)
- {
- ftype = build_function_type_list (V2DF_type_node, double_type_node,
- double_type_node, NULL_TREE);
- def_builtin (MASK_VSX, "__builtin_vec_init_v2df", ftype,
- VSX_BUILTIN_VEC_INIT_V2DF);
+ /* VSX builtins. */
+ ftype = build_function_type_list (V2DF_type_node, double_type_node,
+ double_type_node, NULL_TREE);
+ def_builtin ("__builtin_vec_init_v2df", ftype, VSX_BUILTIN_VEC_INIT_V2DF);
- ftype = build_function_type_list (V2DI_type_node, intDI_type_node,
- intDI_type_node, NULL_TREE);
- def_builtin (MASK_VSX, "__builtin_vec_init_v2di", ftype,
- VSX_BUILTIN_VEC_INIT_V2DI);
- }
+ ftype = build_function_type_list (V2DI_type_node, intDI_type_node,
+ intDI_type_node, NULL_TREE);
+ def_builtin ("__builtin_vec_init_v2di", ftype, VSX_BUILTIN_VEC_INIT_V2DI);
/* Access to the vec_set patterns. */
ftype = build_function_type_list (V4SI_type_node, V4SI_type_node,
intSI_type_node,
integer_type_node, NULL_TREE);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_set_v4si", ftype,
- ALTIVEC_BUILTIN_VEC_SET_V4SI);
+ def_builtin ("__builtin_vec_set_v4si", ftype, ALTIVEC_BUILTIN_VEC_SET_V4SI);
ftype = build_function_type_list (V8HI_type_node, V8HI_type_node,
intHI_type_node,
integer_type_node, NULL_TREE);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_set_v8hi", ftype,
- ALTIVEC_BUILTIN_VEC_SET_V8HI);
+ def_builtin ("__builtin_vec_set_v8hi", ftype, ALTIVEC_BUILTIN_VEC_SET_V8HI);
ftype = build_function_type_list (V16QI_type_node, V16QI_type_node,
intQI_type_node,
integer_type_node, NULL_TREE);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_set_v16qi", ftype,
- ALTIVEC_BUILTIN_VEC_SET_V16QI);
+ def_builtin ("__builtin_vec_set_v16qi", ftype, ALTIVEC_BUILTIN_VEC_SET_V16QI);
ftype = build_function_type_list (V4SF_type_node, V4SF_type_node,
float_type_node,
integer_type_node, NULL_TREE);
- def_builtin (MASK_ALTIVEC|MASK_VSX, "__builtin_vec_set_v4sf", ftype,
- ALTIVEC_BUILTIN_VEC_SET_V4SF);
+ def_builtin ("__builtin_vec_set_v4sf", ftype, ALTIVEC_BUILTIN_VEC_SET_V4SF);
- if (TARGET_VSX)
- {
- ftype = build_function_type_list (V2DF_type_node, V2DF_type_node,
- double_type_node,
- integer_type_node, NULL_TREE);
- def_builtin (MASK_VSX, "__builtin_vec_set_v2df", ftype,
- VSX_BUILTIN_VEC_SET_V2DF);
+ ftype = build_function_type_list (V2DF_type_node, V2DF_type_node,
+ double_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin ("__builtin_vec_set_v2df", ftype, VSX_BUILTIN_VEC_SET_V2DF);
- ftype = build_function_type_list (V2DI_type_node, V2DI_type_node,
- intDI_type_node,
- integer_type_node, NULL_TREE);
- def_builtin (MASK_VSX, "__builtin_vec_set_v2di", ftype,
- VSX_BUILTIN_VEC_SET_V2DI);
- }
+ ftype = build_function_type_list (V2DI_type_node, V2DI_type_node,
+ intDI_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin ("__builtin_vec_set_v2di", ftype, VSX_BUILTIN_VEC_SET_V2DI);
/* Access to the vec_extract patterns. */
ftype = build_function_type_list (intSI_type_node, V4SI_type_node,
integer_type_node, NULL_TREE);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_ext_v4si", ftype,
- ALTIVEC_BUILTIN_VEC_EXT_V4SI);
+ def_builtin ("__builtin_vec_ext_v4si", ftype, ALTIVEC_BUILTIN_VEC_EXT_V4SI);
ftype = build_function_type_list (intHI_type_node, V8HI_type_node,
integer_type_node, NULL_TREE);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_ext_v8hi", ftype,
- ALTIVEC_BUILTIN_VEC_EXT_V8HI);
+ def_builtin ("__builtin_vec_ext_v8hi", ftype, ALTIVEC_BUILTIN_VEC_EXT_V8HI);
ftype = build_function_type_list (intQI_type_node, V16QI_type_node,
integer_type_node, NULL_TREE);
- def_builtin (MASK_ALTIVEC, "__builtin_vec_ext_v16qi", ftype,
- ALTIVEC_BUILTIN_VEC_EXT_V16QI);
+ def_builtin ("__builtin_vec_ext_v16qi", ftype, ALTIVEC_BUILTIN_VEC_EXT_V16QI);
ftype = build_function_type_list (float_type_node, V4SF_type_node,
integer_type_node, NULL_TREE);
- def_builtin (MASK_ALTIVEC|MASK_VSX, "__builtin_vec_ext_v4sf", ftype,
- ALTIVEC_BUILTIN_VEC_EXT_V4SF);
+ def_builtin ("__builtin_vec_ext_v4sf", ftype, ALTIVEC_BUILTIN_VEC_EXT_V4SF);
- if (TARGET_VSX)
- {
- ftype = build_function_type_list (double_type_node, V2DF_type_node,
- integer_type_node, NULL_TREE);
- def_builtin (MASK_VSX, "__builtin_vec_ext_v2df", ftype,
- VSX_BUILTIN_VEC_EXT_V2DF);
+ ftype = build_function_type_list (double_type_node, V2DF_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin ("__builtin_vec_ext_v2df", ftype, VSX_BUILTIN_VEC_EXT_V2DF);
- ftype = build_function_type_list (intDI_type_node, V2DI_type_node,
- integer_type_node, NULL_TREE);
- def_builtin (MASK_VSX, "__builtin_vec_ext_v2di", ftype,
- VSX_BUILTIN_VEC_EXT_V2DI);
- }
+ ftype = build_function_type_list (intDI_type_node, V2DI_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin ("__builtin_vec_ext_v2di", ftype, VSX_BUILTIN_VEC_EXT_V2DI);
}
/* Hash function for builtin functions with up to 3 arguments and a return
int i;
tree ret_type = NULL_TREE;
tree arg_type[3] = { NULL_TREE, NULL_TREE, NULL_TREE };
- tree args;
/* Create builtin_hash_table. */
if (builtin_hash_table == NULL)
/* unsigned args, signed return. */
case VSX_BUILTIN_XVCVUXDDP_UNS:
- case VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF:
+ case ALTIVEC_BUILTIN_UNSFLOAT_V4SI_V4SF:
h.uns_p[1] = 1;
break;
/* signed args, unsigned return. */
case VSX_BUILTIN_XVCVDPUXDS_UNS:
- case VECTOR_BUILTIN_FIXUNS_V4SF_V4SI:
+ case ALTIVEC_BUILTIN_FIXUNS_V4SF_V4SI:
h.uns_p[0] = 1;
break;
fatal_error ("internal error: builtin function %s had an unexpected "
"return type %s", name, GET_MODE_NAME (h.mode[0]));
+ for (i = 0; i < (int) ARRAY_SIZE (arg_type); i++)
+ arg_type[i] = NULL_TREE;
+
for (i = 0; i < num_args; i++)
{
int m = (int) h.mode[i+1];
h2 = ggc_alloc_builtin_hash_struct ();
*h2 = h;
*found = (void *)h2;
- args = void_list_node;
-
- for (i = num_args - 1; i >= 0; i--)
- args = tree_cons (NULL_TREE, arg_type[i], args);
- h2->type = build_function_type (ret_type, args);
+ h2->type = build_function_type_list (ret_type, arg_type[0], arg_type[1],
+ arg_type[2], NULL_TREE);
}
return ((struct builtin_hash_struct *)(*found))->type;
tree v2si_ftype_qi = NULL_TREE;
tree v2si_ftype_v2si_qi = NULL_TREE;
tree v2si_ftype_int_qi = NULL_TREE;
+ unsigned builtin_mask = rs6000_builtin_mask;
if (!TARGET_PAIRED_FLOAT)
{
builtin_mode_to_type[V2SFmode][0] = opaque_V2SF_type_node;
}
+ /* Paired and SPE builtins are only available if you build a compiler with
+ the appropriate options, so only create those builtins with the
+ appropriate compiler option. Create Altivec and VSX builtins on machines
+ with at least the general purpose extensions (970 and newer) to allow the
+ use of the target attribute.. */
+
+ if (TARGET_EXTRA_BUILTINS)
+ builtin_mask |= RS6000_BTM_COMMON;
+
/* Add the ternary operators. */
d = bdesc_3arg;
for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
{
tree type;
- int mask = d->mask;
+ unsigned mask = d->mask;
- if ((mask != 0 && (mask & target_flags) == 0)
- || (mask == 0 && !TARGET_PAIRED_FLOAT))
- continue;
+ if ((mask & builtin_mask) != mask)
+ {
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr, "rs6000_builtin, skip ternary %s\n", d->name);
+ continue;
+ }
- if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
- && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
- || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST
- && d->code <= VSX_BUILTIN_OVERLOADED_LAST))
+ if (rs6000_overloaded_builtin_p (d->code))
{
if (! (type = opaque_ftype_opaque_opaque_opaque))
type = opaque_ftype_opaque_opaque_opaque
d->code, d->name);
}
- def_builtin (d->mask, d->name, type, d->code);
+ def_builtin (d->name, type, d->code);
}
/* Add the binary operators. */
{
enum machine_mode mode0, mode1, mode2;
tree type;
- int mask = d->mask;
+ unsigned mask = d->mask;
- if ((mask != 0 && (mask & target_flags) == 0)
- || (mask == 0 && !TARGET_PAIRED_FLOAT))
- continue;
+ if ((mask & builtin_mask) != mask)
+ {
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr, "rs6000_builtin, skip binary %s\n", d->name);
+ continue;
+ }
- if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
- && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
- || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST
- && d->code <= VSX_BUILTIN_OVERLOADED_LAST))
+ if (rs6000_overloaded_builtin_p (d->code))
{
if (! (type = opaque_ftype_opaque_opaque))
type = opaque_ftype_opaque_opaque
d->code, d->name);
}
- def_builtin (d->mask, d->name, type, d->code);
+ def_builtin (d->name, type, d->code);
}
/* Add the simple unary operators. */
- d = (struct builtin_description *) bdesc_1arg;
+ d = bdesc_1arg;
for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
{
enum machine_mode mode0, mode1;
tree type;
- int mask = d->mask;
+ unsigned mask = d->mask;
- if ((mask != 0 && (mask & target_flags) == 0)
- || (mask == 0 && !TARGET_PAIRED_FLOAT))
- continue;
+ if ((mask & builtin_mask) != mask)
+ {
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr, "rs6000_builtin, skip unary %s\n", d->name);
+ continue;
+ }
- if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
- && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
- || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST
- && d->code <= VSX_BUILTIN_OVERLOADED_LAST))
+ if (rs6000_overloaded_builtin_p (d->code))
{
if (! (type = opaque_ftype_opaque))
type = opaque_ftype_opaque
d->code, d->name);
}
- def_builtin (d->mask, d->name, type, d->code);
+ def_builtin (d->name, type, d->code);
}
}
rtx src_reg = copy_addr_to_reg (XEXP (src, 0));
src = replace_equiv_address (src, src_reg);
}
- set_mem_size (src, GEN_INT (move_bytes));
+ set_mem_size (src, move_bytes);
if (!REG_P (XEXP (dest, 0)))
{
rtx dest_reg = copy_addr_to_reg (XEXP (dest, 0));
dest = replace_equiv_address (dest, dest_reg);
}
- set_mem_size (dest, GEN_INT (move_bytes));
+ set_mem_size (dest, move_bytes);
emit_insn ((*gen_func.movmemsi) (dest, src,
GEN_INT (move_bytes & 31),
needed for the immediate register.
For VSX and Altivec, we may need a register to convert sp+offset into
- reg+sp. */
+ reg+sp.
+
+ For misaligned 64-bit gpr loads and stores we need a register to
+ convert an offset address to indirect. */
static reg_class_t
rs6000_secondary_reload (bool in_p,
else
default_p = true;
}
+ else if (TARGET_POWERPC64
+ && rs6000_reload_register_type (rclass) == GPR_REGISTER_TYPE
+ && MEM_P (x)
+ && GET_MODE_SIZE (GET_MODE (x)) >= UNITS_PER_WORD)
+ {
+ rtx addr = XEXP (x, 0);
+
+ if (GET_CODE (addr) == PRE_MODIFY)
+ addr = XEXP (addr, 1);
+ else if (GET_CODE (addr) == LO_SUM
+ && GET_CODE (XEXP (addr, 0)) == REG
+ && GET_CODE (XEXP (addr, 1)) == CONST)
+ addr = XEXP (XEXP (addr, 1), 0);
+
+ if (GET_CODE (addr) == PLUS
+ && GET_CODE (XEXP (addr, 1)) == CONST_INT
+ && (INTVAL (XEXP (addr, 1)) & 3) != 0)
+ {
+ if (in_p)
+ sri->icode = CODE_FOR_reload_di_load;
+ else
+ sri->icode = CODE_FOR_reload_di_store;
+ sri->extra_cost = 2;
+ ret = NO_REGS;
+ }
+ else
+ default_p = true;
+ }
else
default_p = true;
return;
}
-/* Target hook to return the cover classes for Integrated Register Allocator.
- Cover classes is a set of non-intersected register classes covering all hard
- registers used for register allocation purpose. Any move between two
- registers of a cover class should be cheaper than load or store of the
- registers. The value is array of register classes with LIM_REG_CLASSES used
- as the end marker.
+/* Convert reloads involving 64-bit gprs and misaligned offset
+ addressing to use indirect addressing. */
- We need two IRA_COVER_CLASSES, one for pre-VSX, and the other for VSX to
- account for the Altivec and Floating registers being subsets of the VSX
- register set under VSX, but distinct register sets on pre-VSX machines. */
-
-static const reg_class_t *
-rs6000_ira_cover_classes (void)
+void
+rs6000_secondary_reload_ppc64 (rtx reg, rtx mem, rtx scratch, bool store_p)
{
- static const reg_class_t cover_pre_vsx[] = IRA_COVER_CLASSES_PRE_VSX;
- static const reg_class_t cover_vsx[] = IRA_COVER_CLASSES_VSX;
-
- return (TARGET_VSX) ? cover_vsx : cover_pre_vsx;
-}
+ int regno = true_regnum (reg);
+ enum reg_class rclass;
+ rtx addr;
+ rtx scratch_or_premodify = scratch;
+
+ if (TARGET_DEBUG_ADDR)
+ {
+ fprintf (stderr, "\nrs6000_secondary_reload_ppc64, type = %s\n",
+ store_p ? "store" : "load");
+ fprintf (stderr, "reg:\n");
+ debug_rtx (reg);
+ fprintf (stderr, "mem:\n");
+ debug_rtx (mem);
+ fprintf (stderr, "scratch:\n");
+ debug_rtx (scratch);
+ }
+
+ gcc_assert (regno >= 0 && regno < FIRST_PSEUDO_REGISTER);
+ gcc_assert (GET_CODE (mem) == MEM);
+ rclass = REGNO_REG_CLASS (regno);
+ gcc_assert (rclass == GENERAL_REGS || rclass == BASE_REGS);
+ addr = XEXP (mem, 0);
+
+ if (GET_CODE (addr) == PRE_MODIFY)
+ {
+ scratch_or_premodify = XEXP (addr, 0);
+ gcc_assert (REG_P (scratch_or_premodify));
+ addr = XEXP (addr, 1);
+ }
+ gcc_assert (GET_CODE (addr) == PLUS || GET_CODE (addr) == LO_SUM);
+
+ rs6000_emit_move (scratch_or_premodify, addr, Pmode);
+
+ mem = replace_equiv_address_nv (mem, scratch_or_premodify);
+
+ /* Now create the move. */
+ if (store_p)
+ emit_insn (gen_rtx_SET (VOIDmode, mem, reg));
+ else
+ emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
+
+ return;
+}
/* Allocate a 64-bit stack slot to be used for copying SDmode
values through if this function has any SDmode references. */
fprintf (file, ")(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
}
#endif
- else if (legitimate_constant_pool_address_p (x, true))
+ else if (legitimate_constant_pool_address_p (x, QImode, true))
{
/* This hack along with a corresponding hack in
rs6000_output_addr_const_extra arranges to output addends
{
static int recurse = 0;
- /* For -mrelocatable, we mark all addresses that need to be fixed up
- in the .fixup section. */
+ /* For -mrelocatable, we mark all addresses that need to be fixed up in
+ the .fixup section. Since the TOC section is already relocated, we
+ don't need to mark it here. We used to skip the text section, but it
+ should never be valid for relocated addresses to be placed in the text
+ section. */
if (TARGET_RELOCATABLE
&& in_section != toc_section
- && in_section != text_section
- && !unlikely_text_section_p (in_section)
&& !recurse
&& GET_CODE (x) != CONST_INT
&& GET_CODE (x) != CONST_DOUBLE
return default_assemble_integer (x, size, aligned_p);
}
-#ifdef HAVE_GAS_HIDDEN
+#if defined (HAVE_GAS_HIDDEN) && !TARGET_MACHO
/* Emit an assembler directive to set symbol visibility for DECL to
VISIBILITY_TYPE. */
rtx cond, rtx cc_op0, rtx cc_op1)
{
enum machine_mode dest_mode = GET_MODE (dest);
+ enum machine_mode mask_mode = GET_MODE (cc_op0);
enum rtx_code rcode = GET_CODE (cond);
enum machine_mode cc_mode = CCmode;
rtx mask;
if (VECTOR_UNIT_NONE_P (dest_mode))
return 0;
+ gcc_assert (GET_MODE_SIZE (dest_mode) == GET_MODE_SIZE (mask_mode)
+ && GET_MODE_NUNITS (dest_mode) == GET_MODE_NUNITS (mask_mode));
+
switch (rcode)
{
/* Swap operands if we can, and fall back to doing the operation as
}
/* Get the vector mask for the given relational operations. */
- mask = rs6000_emit_vector_compare (rcode, cc_op0, cc_op1, dest_mode);
+ mask = rs6000_emit_vector_compare (rcode, cc_op0, cc_op1, mask_mode);
if (!mask)
return 0;
op_false = tmp;
}
- cond2 = gen_rtx_fmt_ee (NE, cc_mode, mask, const0_rtx);
+ cond2 = gen_rtx_fmt_ee (NE, cc_mode, gen_lowpart (dest_mode, mask),
+ CONST0_RTX (dest_mode));
emit_insn (gen_rtx_SET (VOIDmode,
dest,
gen_rtx_IF_THEN_ELSE (dest_mode,
emit_move_insn (dest, target);
}
-/* Emit instructions to perform a load-reserved/store-conditional operation.
- The operation performed is an atomic
- (set M (CODE:MODE M OP))
- If not NULL, BEFORE is atomically set to M before the operation, and
- AFTER is set to M after the operation (that is, (CODE:MODE M OP)).
- If SYNC_P then a memory barrier is emitted before the operation.
- Either OP or M may be wrapped in a NOT operation. */
-
-void
-rs6000_emit_sync (enum rtx_code code, enum machine_mode mode,
- rtx m, rtx op, rtx before_param, rtx after_param,
- bool sync_p)
-{
- enum machine_mode used_mode;
- rtx the_op, set_before, set_after, set_atomic, cc_scratch, before, after;
- rtx used_m;
- rtvec vec;
- HOST_WIDE_INT imask = GET_MODE_MASK (mode);
- rtx shift = NULL_RTX;
-
- if (sync_p)
- emit_insn (gen_lwsync ());
-
- used_m = m;
-
- /* If this is smaller than SImode, we'll have to use SImode with
- adjustments. */
- if (mode == QImode || mode == HImode)
- {
- rtx newop, oldop;
-
- if (MEM_ALIGN (used_m) >= 32)
- {
- int ishift = 0;
- if (BYTES_BIG_ENDIAN)
- ishift = GET_MODE_BITSIZE (SImode) - GET_MODE_BITSIZE (mode);
-
- shift = GEN_INT (ishift);
- used_m = change_address (used_m, SImode, 0);
- }
- else
- {
- rtx addrSI, aligned_addr;
- int shift_mask = mode == QImode ? 0x18 : 0x10;
-
- addrSI = gen_lowpart_common (SImode,
- force_reg (Pmode, XEXP (used_m, 0)));
- addrSI = force_reg (SImode, addrSI);
- shift = gen_reg_rtx (SImode);
-
- emit_insn (gen_rlwinm (shift, addrSI, GEN_INT (3),
- GEN_INT (shift_mask)));
- emit_insn (gen_xorsi3 (shift, shift, GEN_INT (shift_mask)));
-
- aligned_addr = expand_binop (Pmode, and_optab,
- XEXP (used_m, 0),
- GEN_INT (-4), NULL_RTX,
- 1, OPTAB_LIB_WIDEN);
- used_m = change_address (used_m, SImode, aligned_addr);
- set_mem_align (used_m, 32);
- }
- /* It's safe to keep the old alias set of USED_M, because
- the operation is atomic and only affects the original
- USED_M. */
- m = used_m;
-
- if (GET_CODE (op) == NOT)
- {
- oldop = lowpart_subreg (SImode, XEXP (op, 0), mode);
- oldop = gen_rtx_NOT (SImode, oldop);
- }
- else
- oldop = lowpart_subreg (SImode, op, mode);
-
- switch (code)
- {
- case IOR:
- case XOR:
- newop = expand_binop (SImode, and_optab,
- oldop, GEN_INT (imask), NULL_RTX,
- 1, OPTAB_LIB_WIDEN);
- emit_insn (gen_ashlsi3 (newop, newop, shift));
- break;
-
- case NOT: /* NAND */
- newop = expand_binop (SImode, ior_optab,
- oldop, GEN_INT (~imask), NULL_RTX,
- 1, OPTAB_LIB_WIDEN);
- emit_insn (gen_rotlsi3 (newop, newop, shift));
- break;
-
- case AND:
- newop = expand_binop (SImode, ior_optab,
- oldop, GEN_INT (~imask), NULL_RTX,
- 1, OPTAB_LIB_WIDEN);
- emit_insn (gen_rotlsi3 (newop, newop, shift));
- break;
-
- case PLUS:
- case MINUS:
- {
- rtx mask;
-
- newop = expand_binop (SImode, and_optab,
- oldop, GEN_INT (imask), NULL_RTX,
- 1, OPTAB_LIB_WIDEN);
- emit_insn (gen_ashlsi3 (newop, newop, shift));
-
- mask = gen_reg_rtx (SImode);
- emit_move_insn (mask, GEN_INT (imask));
- emit_insn (gen_ashlsi3 (mask, mask, shift));
-
- if (code == PLUS)
- newop = gen_rtx_PLUS (SImode, m, newop);
- else
- newop = gen_rtx_MINUS (SImode, m, newop);
- newop = gen_rtx_AND (SImode, newop, mask);
- newop = gen_rtx_IOR (SImode, newop,
- gen_rtx_AND (SImode,
- gen_rtx_NOT (SImode, mask),
- m));
- break;
- }
-
- default:
- gcc_unreachable ();
- }
-
- op = newop;
- used_mode = SImode;
- before = gen_reg_rtx (used_mode);
- after = gen_reg_rtx (used_mode);
- }
- else
- {
- used_mode = mode;
- before = before_param;
- after = after_param;
-
- if (before == NULL_RTX)
- before = gen_reg_rtx (used_mode);
- if (after == NULL_RTX)
- after = gen_reg_rtx (used_mode);
- }
-
- if ((code == PLUS || code == MINUS)
- && used_mode != mode)
- the_op = op; /* Computed above. */
- else if (GET_CODE (op) == NOT && GET_CODE (m) != NOT)
- the_op = gen_rtx_fmt_ee (code, used_mode, op, m);
- else if (code == NOT)
- the_op = gen_rtx_fmt_ee (IOR, used_mode,
- gen_rtx_NOT (used_mode, m),
- gen_rtx_NOT (used_mode, op));
- else
- the_op = gen_rtx_fmt_ee (code, used_mode, m, op);
-
- set_after = gen_rtx_SET (VOIDmode, after, the_op);
- set_before = gen_rtx_SET (VOIDmode, before, used_m);
- set_atomic = gen_rtx_SET (VOIDmode, used_m,
- gen_rtx_UNSPEC (used_mode,
- gen_rtvec (1, the_op),
- UNSPEC_SYNC_OP));
- cc_scratch = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (CCmode));
-
- if ((code == PLUS || code == MINUS) && used_mode != mode)
- vec = gen_rtvec (5, set_after, set_before, set_atomic, cc_scratch,
- gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
- else
- vec = gen_rtvec (4, set_after, set_before, set_atomic, cc_scratch);
- emit_insn (gen_rtx_PARALLEL (VOIDmode, vec));
-
- /* Shift and mask the return values properly. */
- if (used_mode != mode && before_param)
- {
- emit_insn (gen_lshrsi3 (before, before, shift));
- convert_move (before_param, before, 1);
- }
-
- if (used_mode != mode && after_param)
- {
- emit_insn (gen_lshrsi3 (after, after, shift));
- convert_move (after_param, after, 1);
- }
-
- /* The previous sequence will end with a branch that's dependent on
- the conditional store, so placing an isync will ensure that no
- other instructions (especially, no load or store instructions)
- can start before the atomic operation completes. */
- if (sync_p)
- emit_insn (gen_isync ());
-}
-
/* A subroutine of the atomic operation splitters. Jump to LABEL if
COND is true. Mark the jump as unlikely to be taken. */
emit_load_locked (enum machine_mode mode, rtx reg, rtx mem)
{
rtx (*fn) (rtx, rtx) = NULL;
- if (mode == SImode)
- fn = gen_load_locked_si;
- else if (mode == DImode)
- fn = gen_load_locked_di;
+
+ switch (mode)
+ {
+ case SImode:
+ fn = gen_load_lockedsi;
+ break;
+ case DImode:
+ fn = gen_load_lockeddi;
+ break;
+ default:
+ gcc_unreachable ();
+ }
emit_insn (fn (reg, mem));
}
emit_store_conditional (enum machine_mode mode, rtx res, rtx mem, rtx val)
{
rtx (*fn) (rtx, rtx, rtx) = NULL;
- if (mode == SImode)
- fn = gen_store_conditional_si;
- else if (mode == DImode)
- fn = gen_store_conditional_di;
+
+ switch (mode)
+ {
+ case SImode:
+ fn = gen_store_conditionalsi;
+ break;
+ case DImode:
+ fn = gen_store_conditionaldi;
+ break;
+ default:
+ gcc_unreachable ();
+ }
/* Emit sync before stwcx. to address PPC405 Erratum. */
if (PPC405_ERRATUM77)
- emit_insn (gen_memory_barrier ());
+ emit_insn (gen_hwsync ());
emit_insn (fn (res, mem, val));
}
-/* Expand an atomic fetch-and-operate pattern. CODE is the binary operation
- to perform. MEM is the memory on which to operate. VAL is the second
- operand of the binary operator. BEFORE and AFTER are optional locations to
- return the value of MEM either before of after the operation. SCRATCH is
- a scratch register. */
+/* Expand barriers before and after a load_locked/store_cond sequence. */
-void
-rs6000_split_atomic_op (enum rtx_code code, rtx mem, rtx val,
- rtx before, rtx after, rtx scratch)
+static void
+rs6000_pre_atomic_barrier (enum memmodel model)
{
- enum machine_mode mode = GET_MODE (mem);
- rtx label, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
+ switch (model)
+ {
+ case MEMMODEL_RELAXED:
+ case MEMMODEL_CONSUME:
+ case MEMMODEL_ACQUIRE:
+ break;
+ case MEMMODEL_RELEASE:
+ case MEMMODEL_ACQ_REL:
+ emit_insn (gen_lwsync ());
+ break;
+ case MEMMODEL_SEQ_CST:
+ emit_insn (gen_hwsync ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
- emit_insn (gen_lwsync ());
+static void
+rs6000_post_atomic_barrier (enum memmodel model)
+{
+ switch (model)
+ {
+ case MEMMODEL_RELAXED:
+ case MEMMODEL_CONSUME:
+ case MEMMODEL_RELEASE:
+ break;
+ case MEMMODEL_ACQUIRE:
+ case MEMMODEL_ACQ_REL:
+ case MEMMODEL_SEQ_CST:
+ emit_insn (gen_isync ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
- label = gen_label_rtx ();
- emit_label (label);
- label = gen_rtx_LABEL_REF (VOIDmode, label);
+/* A subroutine of the various atomic expanders. For sub-word operations,
+ we must adjust things to operate on SImode. Given the original MEM,
+ return a new aligned memory. Also build and return the quantities by
+ which to shift and mask. */
- if (before == NULL_RTX)
- before = scratch;
- emit_load_locked (mode, before, mem);
+static rtx
+rs6000_adjust_atomic_subword (rtx orig_mem, rtx *pshift, rtx *pmask)
+{
+ rtx addr, align, shift, mask, mem;
+ HOST_WIDE_INT shift_mask;
+ enum machine_mode mode = GET_MODE (orig_mem);
- if (code == NOT)
- x = gen_rtx_IOR (mode,
- gen_rtx_NOT (mode, before),
- gen_rtx_NOT (mode, val));
- else if (code == AND)
- x = gen_rtx_UNSPEC (mode, gen_rtvec (2, before, val), UNSPEC_AND);
- else
- x = gen_rtx_fmt_ee (code, mode, before, val);
+ /* For smaller modes, we have to implement this via SImode. */
+ shift_mask = (mode == QImode ? 0x18 : 0x10);
- if (after != NULL_RTX)
- emit_insn (gen_rtx_SET (VOIDmode, after, copy_rtx (x)));
- emit_insn (gen_rtx_SET (VOIDmode, scratch, x));
+ addr = XEXP (orig_mem, 0);
+ addr = force_reg (GET_MODE (addr), addr);
- emit_store_conditional (mode, cond, mem, scratch);
+ /* Aligned memory containing subword. Generate a new memory. We
+ do not want any of the existing MEM_ATTR data, as we're now
+ accessing memory outside the original object. */
+ align = expand_simple_binop (Pmode, AND, addr, GEN_INT (-4),
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ mem = gen_rtx_MEM (SImode, align);
+ MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (orig_mem);
+ if (MEM_ALIAS_SET (orig_mem) == ALIAS_SET_MEMORY_BARRIER)
+ set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
- x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
- emit_unlikely_jump (x, label);
+ /* Shift amount for subword relative to aligned word. */
+ shift = gen_reg_rtx (SImode);
+ addr = gen_lowpart (SImode, addr);
+ emit_insn (gen_rlwinm (shift, addr, GEN_INT (3), GEN_INT (shift_mask)));
+ shift = expand_simple_binop (SImode, XOR, shift, GEN_INT (shift_mask),
+ shift, 1, OPTAB_LIB_WIDEN);
+ *pshift = shift;
+
+ /* Mask for insertion. */
+ mask = expand_simple_binop (SImode, ASHIFT, GEN_INT (GET_MODE_MASK (mode)),
+ shift, NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ *pmask = mask;
+
+ return mem;
+}
+
+/* A subroutine of the various atomic expanders. For sub-word operands,
+ combine OLDVAL and NEWVAL via MASK. Returns a new pseduo. */
+
+static rtx
+rs6000_mask_atomic_subword (rtx oldval, rtx newval, rtx mask)
+{
+ rtx x;
+
+ x = gen_reg_rtx (SImode);
+ emit_insn (gen_rtx_SET (VOIDmode, x,
+ gen_rtx_AND (SImode,
+ gen_rtx_NOT (SImode, mask),
+ oldval)));
+
+ x = expand_simple_binop (SImode, IOR, newval, x, x, 1, OPTAB_LIB_WIDEN);
+
+ return x;
+}
+
+/* A subroutine of the various atomic expanders. For sub-word operands,
+ extract WIDE to NARROW via SHIFT. */
- emit_insn (gen_isync ());
+static void
+rs6000_finish_atomic_subword (rtx narrow, rtx wide, rtx shift)
+{
+ wide = expand_simple_binop (SImode, LSHIFTRT, wide, shift,
+ wide, 1, OPTAB_LIB_WIDEN);
+ emit_move_insn (narrow, gen_lowpart (GET_MODE (narrow), wide));
}
-/* Expand an atomic compare and swap operation. MEM is the memory on which
- to operate. OLDVAL is the old value to be compared. NEWVAL is the new
- value to be stored. SCRATCH is a scratch GPR. */
+/* Expand an atomic compare and swap operation. */
void
-rs6000_split_compare_and_swap (rtx retval, rtx mem, rtx oldval, rtx newval,
- rtx scratch)
+rs6000_expand_atomic_compare_and_swap (rtx operands[])
{
- enum machine_mode mode = GET_MODE (mem);
- rtx label1, label2, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
+ rtx boolval, retval, mem, oldval, newval, cond;
+ rtx label1, label2, x, mask, shift;
+ enum machine_mode mode;
+ enum memmodel mod_s, mod_f;
+ bool is_weak;
+
+ boolval = operands[0];
+ retval = operands[1];
+ mem = operands[2];
+ oldval = operands[3];
+ newval = operands[4];
+ is_weak = (INTVAL (operands[5]) != 0);
+ mod_s = (enum memmodel) INTVAL (operands[6]);
+ mod_f = (enum memmodel) INTVAL (operands[7]);
+ mode = GET_MODE (mem);
+
+ mask = shift = NULL_RTX;
+ if (mode == QImode || mode == HImode)
+ {
+ mem = rs6000_adjust_atomic_subword (mem, &shift, &mask);
+
+ /* Shift and mask OLDVAL into position with the word. */
+ oldval = convert_modes (SImode, mode, oldval, 1);
+ oldval = expand_simple_binop (SImode, ASHIFT, oldval, shift,
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
+
+ /* Shift and mask NEWVAL into position within the word. */
+ newval = convert_modes (SImode, mode, newval, 1);
+ newval = expand_simple_binop (SImode, ASHIFT, newval, shift,
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
- emit_insn (gen_lwsync ());
+ /* Prepare to adjust the return value. */
+ retval = gen_reg_rtx (SImode);
+ mode = SImode;
+ }
+ else if (reg_overlap_mentioned_p (retval, oldval))
+ oldval = copy_to_reg (oldval);
+
+ rs6000_pre_atomic_barrier (mod_s);
- label1 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+ label1 = NULL_RTX;
+ if (!is_weak)
+ {
+ label1 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+ emit_label (XEXP (label1, 0));
+ }
label2 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
- emit_label (XEXP (label1, 0));
emit_load_locked (mode, retval, mem);
- x = gen_rtx_COMPARE (CCmode, retval, oldval);
+ x = retval;
+ if (mask)
+ {
+ x = expand_simple_binop (SImode, AND, retval, mask,
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ }
+
+ cond = gen_reg_rtx (CCmode);
+ x = gen_rtx_COMPARE (CCmode, x, oldval);
emit_insn (gen_rtx_SET (VOIDmode, cond, x));
x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
emit_unlikely_jump (x, label2);
- emit_move_insn (scratch, newval);
- emit_store_conditional (mode, cond, mem, scratch);
+ x = newval;
+ if (mask)
+ x = rs6000_mask_atomic_subword (retval, newval, mask);
- x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
- emit_unlikely_jump (x, label1);
+ emit_store_conditional (mode, cond, mem, x);
+
+ if (!is_weak)
+ {
+ x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
+ emit_unlikely_jump (x, label1);
+ }
+
+ if (mod_f != MEMMODEL_RELAXED)
+ emit_label (XEXP (label2, 0));
+
+ rs6000_post_atomic_barrier (mod_s);
+
+ if (mod_f == MEMMODEL_RELAXED)
+ emit_label (XEXP (label2, 0));
- emit_insn (gen_isync ());
- emit_label (XEXP (label2, 0));
+ if (shift)
+ rs6000_finish_atomic_subword (operands[1], retval, shift);
+
+ /* In all cases, CR0 contains EQ on success, and NE on failure. */
+ x = gen_rtx_EQ (SImode, cond, const0_rtx);
+ emit_insn (gen_rtx_SET (VOIDmode, boolval, x));
}
-/* Expand an atomic test and set operation. MEM is the memory on which
- to operate. VAL is the value set. SCRATCH is a scratch GPR. */
+/* Expand an atomic exchange operation. */
void
-rs6000_split_lock_test_and_set (rtx retval, rtx mem, rtx val, rtx scratch)
+rs6000_expand_atomic_exchange (rtx operands[])
{
- enum machine_mode mode = GET_MODE (mem);
- rtx label, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
+ rtx retval, mem, val, cond;
+ enum machine_mode mode;
+ enum memmodel model;
+ rtx label, x, mask, shift;
+
+ retval = operands[0];
+ mem = operands[1];
+ val = operands[2];
+ model = (enum memmodel) INTVAL (operands[3]);
+ mode = GET_MODE (mem);
+
+ mask = shift = NULL_RTX;
+ if (mode == QImode || mode == HImode)
+ {
+ mem = rs6000_adjust_atomic_subword (mem, &shift, &mask);
+
+ /* Shift and mask VAL into position with the word. */
+ val = convert_modes (SImode, mode, val, 1);
+ val = expand_simple_binop (SImode, ASHIFT, val, shift,
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
+
+ /* Prepare to adjust the return value. */
+ retval = gen_reg_rtx (SImode);
+ mode = SImode;
+ }
+
+ rs6000_pre_atomic_barrier (model);
label = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
emit_label (XEXP (label, 0));
emit_load_locked (mode, retval, mem);
- emit_move_insn (scratch, val);
- emit_store_conditional (mode, cond, mem, scratch);
+
+ x = val;
+ if (mask)
+ x = rs6000_mask_atomic_subword (retval, val, mask);
+
+ cond = gen_reg_rtx (CCmode);
+ emit_store_conditional (mode, cond, mem, x);
x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
emit_unlikely_jump (x, label);
- emit_insn (gen_isync ());
+ rs6000_post_atomic_barrier (model);
+
+ if (shift)
+ rs6000_finish_atomic_subword (operands[0], retval, shift);
}
+/* Expand an atomic fetch-and-operate pattern. CODE is the binary operation
+ to perform. MEM is the memory on which to operate. VAL is the second
+ operand of the binary operator. BEFORE and AFTER are optional locations to
+ return the value of MEM either before of after the operation. MODEL_RTX
+ is a CONST_INT containing the memory model to use. */
+
void
-rs6000_expand_compare_and_swapqhi (rtx dst, rtx mem, rtx oldval, rtx newval)
+rs6000_expand_atomic_op (enum rtx_code code, rtx mem, rtx val,
+ rtx orig_before, rtx orig_after, rtx model_rtx)
{
+ enum memmodel model = (enum memmodel) INTVAL (model_rtx);
enum machine_mode mode = GET_MODE (mem);
- rtx addrSI, align, wdst, shift, mask;
- HOST_WIDE_INT shift_mask = mode == QImode ? 0x18 : 0x10;
- HOST_WIDE_INT imask = GET_MODE_MASK (mode);
+ rtx label, x, cond, mask, shift;
+ rtx before = orig_before, after = orig_after;
- /* Shift amount for subword relative to aligned word. */
- addrSI = force_reg (GET_MODE (XEXP (mem, 0)), XEXP (mem, 0));
- addrSI = force_reg (SImode, gen_lowpart_common (SImode, addrSI));
- shift = gen_reg_rtx (SImode);
- emit_insn (gen_rlwinm (shift, addrSI, GEN_INT (3),
- GEN_INT (shift_mask)));
- emit_insn (gen_xorsi3 (shift, shift, GEN_INT (shift_mask)));
-
- /* Shift and mask old value into position within word. */
- oldval = convert_modes (SImode, mode, oldval, 1);
- oldval = expand_binop (SImode, and_optab,
- oldval, GEN_INT (imask), NULL_RTX,
- 1, OPTAB_LIB_WIDEN);
- emit_insn (gen_ashlsi3 (oldval, oldval, shift));
-
- /* Shift and mask new value into position within word. */
- newval = convert_modes (SImode, mode, newval, 1);
- newval = expand_binop (SImode, and_optab,
- newval, GEN_INT (imask), NULL_RTX,
- 1, OPTAB_LIB_WIDEN);
- emit_insn (gen_ashlsi3 (newval, newval, shift));
+ mask = shift = NULL_RTX;
+ if (mode == QImode || mode == HImode)
+ {
+ mem = rs6000_adjust_atomic_subword (mem, &shift, &mask);
- /* Mask for insertion. */
- mask = gen_reg_rtx (SImode);
- emit_move_insn (mask, GEN_INT (imask));
- emit_insn (gen_ashlsi3 (mask, mask, shift));
+ /* Shift and mask VAL into position with the word. */
+ val = convert_modes (SImode, mode, val, 1);
+ val = expand_simple_binop (SImode, ASHIFT, val, shift,
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
- /* Address of aligned word containing subword. */
- align = expand_binop (Pmode, and_optab, XEXP (mem, 0), GEN_INT (-4),
- NULL_RTX, 1, OPTAB_LIB_WIDEN);
- mem = change_address (mem, SImode, align);
- set_mem_align (mem, 32);
- MEM_VOLATILE_P (mem) = 1;
+ switch (code)
+ {
+ case IOR:
+ case XOR:
+ /* We've already zero-extended VAL. That is sufficient to
+ make certain that it does not affect other bits. */
+ mask = NULL;
+ break;
+
+ case AND:
+ /* If we make certain that all of the other bits in VAL are
+ set, that will be sufficient to not affect other bits. */
+ x = gen_rtx_NOT (SImode, mask);
+ x = gen_rtx_IOR (SImode, x, val);
+ emit_insn (gen_rtx_SET (VOIDmode, val, x));
+ mask = NULL;
+ break;
- wdst = gen_reg_rtx (SImode);
- emit_insn (gen_sync_compare_and_swapqhi_internal (wdst, mask,
- oldval, newval, mem));
+ case NOT:
+ case PLUS:
+ case MINUS:
+ /* These will all affect bits outside the field and need
+ adjustment via MASK within the loop. */
+ break;
- /* Shift the result back. */
- emit_insn (gen_lshrsi3 (wdst, wdst, shift));
+ default:
+ gcc_unreachable ();
+ }
- emit_move_insn (dst, gen_lowpart (mode, wdst));
-}
+ /* Prepare to adjust the return value. */
+ before = gen_reg_rtx (SImode);
+ if (after)
+ after = gen_reg_rtx (SImode);
+ mode = SImode;
+ }
-void
-rs6000_split_compare_and_swapqhi (rtx dest, rtx mask,
- rtx oldval, rtx newval, rtx mem,
- rtx scratch)
-{
- rtx label1, label2, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
+ rs6000_pre_atomic_barrier (model);
- emit_insn (gen_lwsync ());
- label1 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
- label2 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
- emit_label (XEXP (label1, 0));
+ label = gen_label_rtx ();
+ emit_label (label);
+ label = gen_rtx_LABEL_REF (VOIDmode, label);
- emit_load_locked (SImode, scratch, mem);
+ if (before == NULL_RTX)
+ before = gen_reg_rtx (mode);
- /* Mask subword within loaded value for comparison with oldval.
- Use UNSPEC_AND to avoid clobber.*/
- emit_insn (gen_rtx_SET (SImode, dest,
- gen_rtx_UNSPEC (SImode,
- gen_rtvec (2, scratch, mask),
- UNSPEC_AND)));
+ emit_load_locked (mode, before, mem);
- x = gen_rtx_COMPARE (CCmode, dest, oldval);
- emit_insn (gen_rtx_SET (VOIDmode, cond, x));
+ if (code == NOT)
+ {
+ x = expand_simple_binop (mode, AND, before, val,
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ after = expand_simple_unop (mode, NOT, x, after, 1);
+ }
+ else
+ {
+ after = expand_simple_binop (mode, code, before, val,
+ after, 1, OPTAB_LIB_WIDEN);
+ }
- x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
- emit_unlikely_jump (x, label2);
+ x = after;
+ if (mask)
+ {
+ x = expand_simple_binop (SImode, AND, after, mask,
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ x = rs6000_mask_atomic_subword (before, x, mask);
+ }
- /* Clear subword within loaded value for insertion of new value. */
- emit_insn (gen_rtx_SET (SImode, scratch,
- gen_rtx_AND (SImode,
- gen_rtx_NOT (SImode, mask), scratch)));
- emit_insn (gen_iorsi3 (scratch, scratch, newval));
- emit_store_conditional (SImode, cond, mem, scratch);
+ cond = gen_reg_rtx (CCmode);
+ emit_store_conditional (mode, cond, mem, x);
x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
- emit_unlikely_jump (x, label1);
-
- emit_insn (gen_isync ());
- emit_label (XEXP (label2, 0));
-}
+ emit_unlikely_jump (x, label);
+ rs6000_post_atomic_barrier (model);
- /* Emit instructions to move SRC to DST. Called by splitters for
+ if (shift)
+ {
+ if (orig_before)
+ rs6000_finish_atomic_subword (orig_before, before, shift);
+ if (orig_after)
+ rs6000_finish_atomic_subword (orig_after, after, shift);
+ }
+ else if (orig_after && after != orig_after)
+ emit_move_insn (orig_after, after);
+}
+
+/* Emit instructions to move SRC to DST. Called by splitters for
multi-register moves. It will emit at most one instruction for
each register that is accessed; that is, it won't emit li/lis pairs
(or equivalent for 64-bit code). One of SRC or DST must be a hard
info_ptr->world_save_p
= (WORLD_SAVE_P (info_ptr)
&& DEFAULT_ABI == ABI_DARWIN
- && ! (cfun->calls_setjmp && flag_exceptions)
+ && !cfun->has_nonlocal_label
&& info_ptr->first_fp_reg_save == FIRST_SAVED_FP_REGNO
&& info_ptr->first_gp_reg_save == FIRST_SAVED_GP_REGNO
&& info_ptr->first_altivec_reg_save == FIRST_SAVED_ALTIVEC_REGNO
/* Don't bother to try to save things out-of-line if r11 is occupied
by the static chain. It would require too much fiddling and the
- static chain is rarely used anyway. */
+ static chain is rarely used anyway. FPRs are saved w.r.t the stack
+ pointer on Darwin. */
if (using_static_chain_p)
- strategy |= SAVE_INLINE_FPRS | SAVE_INLINE_GPRS;
+ strategy |= (DEFAULT_ABI == ABI_DARWIN ? 0 : SAVE_INLINE_FPRS)
+ | SAVE_INLINE_GPRS;
/* If we are going to use store multiple, then don't even bother
with the out-of-line routines, since the store-multiple
if (TARGET_AIX && !(strategy & REST_INLINE_FPRS))
strategy |= REST_NOINLINE_FPRS_DOESNT_RESTORE_LR;
#endif
+ if (TARGET_MACHO && !(strategy & SAVE_INLINE_FPRS))
+ strategy |= SAVE_NOINLINE_FPRS_SAVES_LR;
+
return strategy;
}
static rs6000_stack_t *
rs6000_stack_info (void)
{
-#ifdef ENABLE_CHECKING
- static rs6000_stack_t info_save;
-#endif
rs6000_stack_t *info_ptr = &stack_info;
int reg_size = TARGET_32BIT ? 4 : 8;
int ehrd_size;
HOST_WIDE_INT non_fixed_size;
bool using_static_chain_p;
-#ifdef ENABLE_CHECKING
- memcpy (&info_save, &stack_info, sizeof stack_info);
-#else
if (reload_completed && info_ptr->reload_completed)
return info_ptr;
-#endif
- memset (&stack_info, 0, sizeof (stack_info));
+ memset (info_ptr, 0, sizeof (*info_ptr));
info_ptr->reload_completed = reload_completed;
if (TARGET_SPE)
if (! info_ptr->cr_save_p)
info_ptr->cr_save_offset = 0;
-#ifdef ENABLE_CHECKING
- gcc_assert (!(reload_completed && info_save.reload_completed)
- || memcmp (&info_save, &stack_info, sizeof stack_info) == 0);
-#endif
return info_ptr;
}
if (info->reg_size != 4)
fprintf (stderr, "\treg_size = %5d\n", info->reg_size);
+ fprintf (stderr, "\tsave-strategy = %04x\n", info->savres_strategy);
+
fprintf (stderr, "\n");
}
return get_hard_reg_initial_val (Pmode, LR_REGNO);
}
-/* Say whether a function is a candidate for sibcall handling or not.
- We do not allow indirect calls to be optimized into sibling calls.
- Also, we can't do it if there are any vector parameters; there's
- nowhere to put the VRsave code so it works; note that functions with
- vector parameters are required to have a prototype, so the argument
- type info must be available here. (The tail recursion case can work
- with vector parameters, but there's no way to distinguish here.) */
+/* Say whether a function is a candidate for sibcall handling or not. */
+
static bool
-rs6000_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
+rs6000_function_ok_for_sibcall (tree decl, tree exp)
{
- tree type;
+ tree fntype;
+
if (decl)
+ fntype = TREE_TYPE (decl);
+ else
+ fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (exp)));
+
+ /* We can't do it if the called function has more vector parameters
+ than the current function; there's nowhere to put the VRsave code. */
+ if (TARGET_ALTIVEC_ABI
+ && TARGET_ALTIVEC_VRSAVE
+ && !(decl && decl == current_function_decl))
{
- if (TARGET_ALTIVEC_VRSAVE)
- {
- for (type = TYPE_ARG_TYPES (TREE_TYPE (decl));
- type; type = TREE_CHAIN (type))
- {
- if (TREE_CODE (TREE_VALUE (type)) == VECTOR_TYPE)
- return false;
- }
- }
- if (DEFAULT_ABI == ABI_DARWIN
- || ((*targetm.binds_local_p) (decl)
- && (DEFAULT_ABI != ABI_AIX || !DECL_EXTERNAL (decl))))
- {
- tree attr_list = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+ function_args_iterator args_iter;
+ tree type;
+ int nvreg = 0;
+
+ /* Functions with vector parameters are required to have a
+ prototype, so the argument type info must be available
+ here. */
+ FOREACH_FUNCTION_ARGS(fntype, type, args_iter)
+ if (TREE_CODE (type) == VECTOR_TYPE
+ && ALTIVEC_OR_VSX_VECTOR_MODE (TYPE_MODE (type)))
+ nvreg++;
+
+ FOREACH_FUNCTION_ARGS(TREE_TYPE (current_function_decl), type, args_iter)
+ if (TREE_CODE (type) == VECTOR_TYPE
+ && ALTIVEC_OR_VSX_VECTOR_MODE (TYPE_MODE (type)))
+ nvreg--;
+
+ if (nvreg > 0)
+ return false;
+ }
- if (!lookup_attribute ("longcall", attr_list)
- || lookup_attribute ("shortcall", attr_list))
- return true;
- }
+ /* Under the AIX ABI we can't allow calls to non-local functions,
+ because the callee may have a different TOC pointer to the
+ caller and there's no way to ensure we restore the TOC when we
+ return. With the secure-plt SYSV ABI we can't make non-local
+ calls when -fpic/PIC because the plt call stubs use r30. */
+ if (DEFAULT_ABI == ABI_DARWIN
+ || (DEFAULT_ABI == ABI_AIX
+ && decl
+ && !DECL_EXTERNAL (decl)
+ && (*targetm.binds_local_p) (decl))
+ || (DEFAULT_ABI == ABI_V4
+ && (!TARGET_SECURE_PLT
+ || !flag_pic
+ || (decl
+ && (*targetm.binds_local_p) (decl)))))
+ {
+ tree attr_list = TYPE_ATTRIBUTES (fntype);
+
+ if (!lookup_attribute ("longcall", attr_list)
+ || lookup_attribute ("shortcall", attr_list))
+ return true;
}
+
return false;
}
lab = gen_label_rtx ();
emit_insn (gen_load_toc_v4_PIC_1b (tocsym, lab));
emit_move_insn (dest, gen_rtx_REG (Pmode, LR_REGNO));
+ if (TARGET_LINK_STACK)
+ emit_insn (gen_addsi3 (dest, dest, GEN_INT (4)));
emit_move_insn (temp0, gen_rtx_MEM (Pmode, dest));
}
emit_insn (gen_addsi3 (dest, temp0, dest));
tocreg = gen_rtx_REG (Pmode, TOC_REGISTER);
if (TARGET_CMODEL != CMODEL_SMALL)
{
- rtx hi = gen_rtx_PLUS (Pmode, tocreg, gen_rtx_HIGH (Pmode, tocrel));
+ rtx hi = gen_rtx_CONST (Pmode,
+ gen_rtx_PLUS (Pmode, tocreg,
+ gen_rtx_HIGH (Pmode, tocrel)));
if (largetoc_reg != NULL)
{
emit_move_insn (largetoc_reg, hi);
output_asm_insn ("{cal %0,%1(%0)|addi %0,%0,%1}", xops);
/* Probe at TEST_ADDR and branch. */
- output_asm_insn ("{st|stw} 0,0(%0)", xops);
+ xops[1] = gen_rtx_REG (Pmode, 0);
+ output_asm_insn ("{st|stw} %1,0(%0)", xops);
fprintf (asm_out_file, "\tb ");
assemble_name_raw (asm_out_file, loop_lab);
fputc ('\n', asm_out_file);
deduce these equivalences by itself so it wasn't necessary to hold
its hand so much. */
-static void
+static rtx
rs6000_frame_related (rtx insn, rtx reg, HOST_WIDE_INT val,
rtx reg2, rtx rreg)
{
RTX_FRAME_RELATED_P (insn) = 1;
add_reg_note (insn, REG_FRAME_RELATED_EXPR, real);
+
+ return insn;
}
/* Returns an insn that has a vrsave set operation with the
/* Save a register into the frame, and emit RTX_FRAME_RELATED_P notes.
Save REGNO into [FRAME_REG + OFFSET] in mode MODE. */
-static void
+static rtx
emit_frame_save (rtx frame_reg, rtx frame_ptr, enum machine_mode mode,
unsigned int regno, int offset, HOST_WIDE_INT total_size)
{
/* Some cases that need register indexed addressing. */
if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
- || (TARGET_VSX && VSX_VECTOR_MODE (mode))
+ || (TARGET_VSX && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
|| (TARGET_E500_DOUBLE && mode == DFmode)
|| (TARGET_SPE_ABI
&& SPE_VECTOR_MODE (mode)
insn = emit_move_insn (mem, reg);
- rs6000_frame_related (insn, frame_ptr, total_size, replacea, replaceb);
+ return rs6000_frame_related (insn, frame_ptr, total_size, replacea, replaceb);
}
/* Emit an offset memory reference suitable for a frame store, while
suffix = savep ? SAVE_FP_SUFFIX : RESTORE_FP_SUFFIX;
}
}
- else if (DEFAULT_ABI == ABI_DARWIN)
- sorry ("out-of-line save/restore routines not supported on Darwin");
- sprintf (savres_routine_name, "%s%d%s", prefix, regno, suffix);
+ if (DEFAULT_ABI == ABI_DARWIN)
+ {
+ /* The Darwin approach is (slightly) different, in order to be
+ compatible with code generated by the system toolchain. There is a
+ single symbol for the start of save sequence, and the code here
+ embeds an offset into that code on the basis of the first register
+ to be saved. */
+ prefix = savep ? "save" : "rest" ;
+ if (gpr)
+ sprintf (savres_routine_name, "*%sGPR%s%s%.0d ; %s r%d-r31",
+ prefix, (lr ? "x" : ""), (regno == 13 ? "" : "+"),
+ (regno-13) * 4, prefix, regno);
+ else
+ sprintf (savres_routine_name, "*%sFP%s%.0d ; %s f%d-f31",
+ prefix, (regno == 14 ? "" : "+"), (regno-14) * 4, prefix, regno);
+ }
+ else
+ sprintf (savres_routine_name, "%s%d%s", prefix, regno, suffix);
return savres_routine_name;
}
{
/* This blockage is needed so that sched doesn't decide to move
the sp change before the register restores. */
- if (frame_reg_rtx != sp_reg_rtx
+ if (DEFAULT_ABI == ABI_V4
|| (TARGET_SPE_ABI
&& info->spe_64bit_regs_used != 0
&& info->first_gp_reg_save != 32))
if (sp_offset != 0)
{
rtx dest_reg = savres ? gen_rtx_REG (Pmode, 11) : sp_reg_rtx;
- return emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx,
- GEN_INT (sp_offset)));
+ rtx insn = emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx,
+ GEN_INT (sp_offset)));
+ if (!savres)
+ return insn;
}
else if (!savres)
return emit_move_insn (sp_reg_rtx, frame_reg_rtx);
}
/* Construct a parallel rtx describing the effect of a call to an
- out-of-line register save/restore routine. */
+ out-of-line register save/restore routine, and emit the insn
+ or jump_insn as appropriate. */
static rtx
-rs6000_make_savres_rtx (rs6000_stack_t *info,
+rs6000_emit_savres_rtx (rs6000_stack_t *info,
rtx frame_reg_rtx, int save_area_offset,
enum machine_mode reg_mode,
bool savep, bool gpr, bool lr)
{
int i;
- int offset, start_reg, end_reg, n_regs;
+ int offset, start_reg, end_reg, n_regs, use_reg;
int reg_size = GET_MODE_SIZE (reg_mode);
rtx sym;
rtvec p;
+ rtx par, insn;
offset = 0;
start_reg = (gpr
p = rtvec_alloc ((lr ? 4 : 3) + n_regs);
if (!savep && lr)
- RTVEC_ELT (p, offset++) = gen_rtx_RETURN (VOIDmode);
+ RTVEC_ELT (p, offset++) = ret_rtx;
RTVEC_ELT (p, offset++)
- = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 65));
+ = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNO));
sym = rs6000_savres_routine_sym (info, savep, gpr, lr);
RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, sym);
+ use_reg = DEFAULT_ABI == ABI_AIX ? (gpr && !lr ? 12 : 1)
+ : DEFAULT_ABI == ABI_DARWIN && !gpr ? 1
+ : 11;
RTVEC_ELT (p, offset++)
= gen_rtx_USE (VOIDmode,
- gen_rtx_REG (Pmode, DEFAULT_ABI != ABI_AIX ? 11
- : gpr && !lr ? 12
- : 1));
+ gen_rtx_REG (Pmode, use_reg));
for (i = 0; i < end_reg - start_reg; i++)
{
RTVEC_ELT (p, i + offset) = gen_rtx_SET (VOIDmode, mem, reg);
}
- return gen_rtx_PARALLEL (VOIDmode, p);
+ par = gen_rtx_PARALLEL (VOIDmode, p);
+
+ if (!savep && lr)
+ {
+ insn = emit_jump_insn (par);
+ JUMP_LABEL (insn) = ret_rtx;
+ }
+ else
+ insn = emit_insn (par);
+ return insn;
}
/* Determine whether the gp REG is really used. */
&& call_used_regs[STATIC_CHAIN_REGNUM]);
HOST_WIDE_INT sp_offset = 0;
- if (flag_stack_usage)
+ if (flag_stack_usage_info)
current_function_static_stack_size = info->total_size;
if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK && info->total_size)
}
else if (!WORLD_SAVE_P (info) && info->first_fp_reg_save != 64)
{
- rtx par;
-
- par = rs6000_make_savres_rtx (info, frame_reg_rtx,
- info->fp_save_offset + sp_offset,
- DFmode,
- /*savep=*/true, /*gpr=*/false,
- /*lr=*/(strategy
- & SAVE_NOINLINE_FPRS_SAVES_LR)
- != 0);
- insn = emit_insn (par);
+ insn = rs6000_emit_savres_rtx (info, frame_reg_rtx,
+ info->fp_save_offset + sp_offset,
+ DFmode,
+ /*savep=*/true, /*gpr=*/false,
+ /*lr=*/((strategy
+ & SAVE_NOINLINE_FPRS_SAVES_LR)
+ != 0));
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
}
{
int i;
rtx spe_save_area_ptr;
-
+ int save_ptr_to_sp;
+ int ool_adjust = 0;
+
/* Determine whether we can address all of the registers that need
- to be saved with an offset from the stack pointer that fits in
+ to be saved with an offset from frame_reg_rtx that fits in
the small const field for SPE memory instructions. */
- int spe_regs_addressable_via_sp
- = (SPE_CONST_OFFSET_OK(info->spe_gp_save_offset + sp_offset
- + (32 - info->first_gp_reg_save - 1) * reg_size)
+ int spe_regs_addressable
+ = (SPE_CONST_OFFSET_OK (info->spe_gp_save_offset + sp_offset
+ + reg_size * (32 - info->first_gp_reg_save - 1))
&& saving_GPRs_inline);
int spe_offset;
-
- if (spe_regs_addressable_via_sp)
+
+ if (spe_regs_addressable)
{
spe_save_area_ptr = frame_reg_rtx;
+ save_ptr_to_sp = info->total_size - sp_offset;
spe_offset = info->spe_gp_save_offset + sp_offset;
}
else
{
/* Make r11 point to the start of the SPE save area. We need
to be careful here if r11 is holding the static chain. If
- it is, then temporarily save it in r0. We would use r0 as
- our base register here, but using r0 as a base register in
- loads and stores means something different from what we
- would like. */
- int ool_adjust = (saving_GPRs_inline
- ? 0
- : (info->first_gp_reg_save
- - (FIRST_SAVRES_REGISTER+1))*8);
- HOST_WIDE_INT offset = (info->spe_gp_save_offset
- + sp_offset - ool_adjust);
+ it is, then temporarily save it in r0. */
+ int offset;
+
+ if (!saving_GPRs_inline)
+ ool_adjust = 8 * (info->first_gp_reg_save
+ - (FIRST_SAVRES_REGISTER + 1));
+ offset = info->spe_gp_save_offset + sp_offset - ool_adjust;
+ spe_save_area_ptr = gen_rtx_REG (Pmode, 11);
+ save_ptr_to_sp = info->total_size - sp_offset + offset;
+ spe_offset = 0;
if (using_static_chain_p)
{
rtx r0 = gen_rtx_REG (Pmode, 0);
gcc_assert (info->first_gp_reg_save > 11);
-
- emit_move_insn (r0, gen_rtx_REG (Pmode, 11));
+
+ emit_move_insn (r0, spe_save_area_ptr);
}
-
- spe_save_area_ptr = gen_rtx_REG (Pmode, 11);
- insn = emit_insn (gen_addsi3 (spe_save_area_ptr,
- frame_reg_rtx,
- GEN_INT (offset)));
- /* We need to make sure the move to r11 gets noted for
- properly outputting unwind information. */
- if (!saving_GPRs_inline)
- rs6000_frame_related (insn, frame_reg_rtx, offset,
- NULL_RTX, NULL_RTX);
- spe_offset = 0;
+ emit_insn (gen_addsi3 (spe_save_area_ptr,
+ frame_reg_rtx, GEN_INT (offset)));
+ if (REGNO (frame_reg_rtx) == 11)
+ sp_offset = -info->spe_gp_save_offset + ool_adjust;
}
-
+
if (saving_GPRs_inline)
{
for (i = 0; i < 32 - info->first_gp_reg_save; i++)
/* We're doing all this to ensure that the offset fits into
the immediate offset of 'evstdd'. */
gcc_assert (SPE_CONST_OFFSET_OK (reg_size * i + spe_offset));
-
+
offset = GEN_INT (reg_size * i + spe_offset);
addr = gen_rtx_PLUS (Pmode, spe_save_area_ptr, offset);
mem = gen_rtx_MEM (V2SImode, addr);
-
+
insn = emit_move_insn (mem, reg);
-
- rs6000_frame_related (insn, spe_save_area_ptr,
- info->spe_gp_save_offset
- + sp_offset + reg_size * i,
- offset, const0_rtx);
+
+ rs6000_frame_related (insn,
+ spe_save_area_ptr, save_ptr_to_sp,
+ NULL_RTX, NULL_RTX);
}
}
else
{
- rtx par;
+ insn = rs6000_emit_savres_rtx (info, spe_save_area_ptr,
+ ool_adjust, reg_mode,
+ /*savep=*/true, /*gpr=*/true,
+ /*lr=*/false);
- par = rs6000_make_savres_rtx (info, gen_rtx_REG (Pmode, 11),
- 0, reg_mode,
- /*savep=*/true, /*gpr=*/true,
- /*lr=*/false);
- insn = emit_insn (par);
- rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ rs6000_frame_related (insn, spe_save_area_ptr, save_ptr_to_sp,
NULL_RTX, NULL_RTX);
}
-
-
+
/* Move the static chain pointer back. */
- if (using_static_chain_p && !spe_regs_addressable_via_sp)
- emit_move_insn (gen_rtx_REG (Pmode, 11), gen_rtx_REG (Pmode, 0));
+ if (using_static_chain_p && !spe_regs_addressable)
+ emit_move_insn (spe_save_area_ptr, gen_rtx_REG (Pmode, 0));
}
else if (!WORLD_SAVE_P (info) && !saving_GPRs_inline)
{
- rtx par;
+ if (DEFAULT_ABI == ABI_DARWIN)
+ {
+ rtx dest_reg = gen_rtx_REG (Pmode, 11);
+ if (info->first_fp_reg_save == 64)
+ {
+ /* we only need a copy, no fprs were saved. */
+ if (dest_reg != frame_reg_rtx)
+ emit_move_insn (dest_reg, frame_reg_rtx);
+ }
+ else
+ {
+ int save_off = 8 * (64 - info->first_fp_reg_save);
+ rtx offset = GEN_INT (sp_offset - save_off);
+ if (REGNO (dest_reg) == REGNO (frame_reg_rtx))
+ sp_offset = save_off;
+ emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx, offset));
+ }
+ }
/* Need to adjust r11 (r12) if we saved any FPRs. */
- if (info->first_fp_reg_save != 64)
- {
- rtx dest_reg = gen_rtx_REG (reg_mode, DEFAULT_ABI == ABI_AIX
- ? 12 : 11);
- rtx offset = GEN_INT (sp_offset
- + (-8 * (64-info->first_fp_reg_save)));
+ else if (info->first_fp_reg_save != 64)
+ {
+ rtx dest_reg = gen_rtx_REG (Pmode, DEFAULT_ABI == ABI_AIX ? 12 : 11);
+ int save_off = 8 * (64 - info->first_fp_reg_save);
+ rtx offset = GEN_INT (sp_offset - save_off);
+
+ if (REGNO (dest_reg) == REGNO (frame_reg_rtx))
+ sp_offset = save_off;
emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx, offset));
- }
+ }
- par = rs6000_make_savres_rtx (info, frame_reg_rtx,
- info->gp_save_offset + sp_offset,
- reg_mode,
- /*savep=*/true, /*gpr=*/true,
- /*lr=*/(strategy
- & SAVE_NOINLINE_GPRS_SAVES_LR)
- != 0);
- insn = emit_insn (par);
+ insn = rs6000_emit_savres_rtx (info, frame_reg_rtx,
+ info->gp_save_offset + sp_offset,
+ reg_mode,
+ /*savep=*/true, /*gpr=*/true,
+ /*lr=*/((strategy
+ & SAVE_NOINLINE_GPRS_SAVES_LR)
+ != 0));
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
}
if (TARGET_AIX && crtl->calls_eh_return)
{
rtx tmp_reg, tmp_reg_si, hi, lo, compare_result, toc_save_done, jump;
+ rtx save_insn, join_insn, note;
long toc_restore_insn;
gcc_assert (frame_reg_rtx == frame_ptr_rtx
JUMP_LABEL (jump) = toc_save_done;
LABEL_NUSES (toc_save_done) += 1;
- emit_frame_save (frame_reg_rtx, frame_ptr_rtx, reg_mode, 2,
- sp_offset + 5 * reg_size, info->total_size);
+ save_insn = emit_frame_save (frame_reg_rtx, frame_ptr_rtx, reg_mode,
+ TOC_REGNUM, sp_offset + 5 * reg_size,
+ info->total_size);
+
emit_label (toc_save_done);
+
+ /* ??? If we leave SAVE_INSN as marked as saving R2, then we'll
+ have a CFG that has different saves along different paths.
+ Move the note to a dummy blockage insn, which describes that
+ R2 is unconditionally saved after the label. */
+ /* ??? An alternate representation might be a special insn pattern
+ containing both the branch and the store. That might let the
+ code that minimizes the number of DW_CFA_advance opcodes better
+ freedom in placing the annotations. */
+ note = find_reg_note (save_insn, REG_FRAME_RELATED_EXPR, NULL);
+ gcc_assert (note);
+ remove_note (save_insn, note);
+ RTX_FRAME_RELATED_P (save_insn) = 0;
+
+ join_insn = emit_insn (gen_blockage ());
+ REG_NOTES (join_insn) = note;
+ RTX_FRAME_RELATED_P (join_insn) = 1;
+
if (using_static_chain_p)
emit_move_insn (tmp_reg, gen_rtx_REG (Pmode, 0));
}
used in this function, and do the corresponding magic in the
epilogue. */
- if (TARGET_ALTIVEC && TARGET_ALTIVEC_VRSAVE
+ if (!WORLD_SAVE_P (info)
+ && TARGET_ALTIVEC
+ && TARGET_ALTIVEC_VRSAVE
&& info->vrsave_mask != 0)
{
rtx reg, mem, vrsave;
else
emit_insn (gen_rtx_SET (VOIDmode, reg, vrsave));
- if (!WORLD_SAVE_P (info))
- {
- /* Save VRSAVE. */
- offset = info->vrsave_save_offset + sp_offset;
- mem = gen_frame_mem (SImode,
- gen_rtx_PLUS (Pmode, frame_reg_rtx,
- GEN_INT (offset)));
- insn = emit_move_insn (mem, reg);
- }
+ /* Save VRSAVE. */
+ offset = info->vrsave_save_offset + sp_offset;
+ mem = gen_frame_mem (SImode,
+ gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (offset)));
+ insn = emit_move_insn (mem, reg);
/* Include the registers in the mask. */
emit_insn (gen_iorsi3 (reg, reg, GEN_INT ((int) info->vrsave_mask)));
insn = emit_insn (generate_set_vrsave (reg, info, 0));
}
- if (TARGET_SINGLE_PIC_BASE)
- return; /* Do not set PIC register */
-
/* If we are using RS6000_PIC_OFFSET_TABLE_REGNUM, we need to set it up. */
- if ((TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0)
- || (DEFAULT_ABI == ABI_V4
- && (flag_pic == 1 || (flag_pic && TARGET_SECURE_PLT))
- && df_regs_ever_live_p (RS6000_PIC_OFFSET_TABLE_REGNUM)))
+ if (!TARGET_SINGLE_PIC_BASE
+ && ((TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0)
+ || (DEFAULT_ABI == ABI_V4
+ && (flag_pic == 1 || (flag_pic && TARGET_SECURE_PLT))
+ && df_regs_ever_live_p (RS6000_PIC_OFFSET_TABLE_REGNUM))))
{
/* If emit_load_toc_table will use the link register, we need to save
it. We use R12 for this purpose because emit_load_toc_table
rs6000_emit_load_toc_table (TRUE);
insn = emit_move_insn (lr, frame_ptr_rtx);
+ add_reg_note (insn, REG_CFA_RESTORE, lr);
RTX_FRAME_RELATED_P (insn) = 1;
}
else
}
#if TARGET_MACHO
- if (DEFAULT_ABI == ABI_DARWIN
+ if (!TARGET_SINGLE_PIC_BASE
+ && DEFAULT_ABI == ABI_DARWIN
&& flag_pic && crtl->uses_pic_offset_table)
{
rtx lr = gen_rtx_REG (Pmode, LR_REGNO);
emit_move_insn (lr, gen_rtx_REG (Pmode, 0));
}
#endif
+
+ /* If we need to, save the TOC register after doing the stack setup.
+ Do not emit eh frame info for this save. The unwinder wants info,
+ conceptually attached to instructions in this function, about
+ register values in the caller of this function. This R2 may have
+ already been changed from the value in the caller.
+ We don't attempt to write accurate DWARF EH frame info for R2
+ because code emitted by gcc for a (non-pointer) function call
+ doesn't save and restore R2. Instead, R2 is managed out-of-line
+ by a linker generated plt call stub when the function resides in
+ a shared library. This behaviour is costly to describe in DWARF,
+ both in terms of the size of DWARF info and the time taken in the
+ unwinder to interpret it. R2 changes, apart from the
+ calls_eh_return case earlier in this function, are handled by
+ linux-unwind.h frob_update_context. */
+ if (rs6000_save_toc_in_prologue_p ())
+ {
+ rtx addr = gen_rtx_PLUS (Pmode, sp_reg_rtx, GEN_INT (5 * reg_size));
+ rtx mem = gen_frame_mem (reg_mode, addr);
+ emit_move_insn (mem, gen_rtx_REG (reg_mode, TOC_REGNUM));
+ }
}
/* Write function prologue. */
/* Write .extern for any function we will call to save and restore
fp values. */
- if (info->first_fp_reg_save < 64)
+ if (info->first_fp_reg_save < 64
+ && !TARGET_MACHO)
{
char *name;
int regno = info->first_fp_reg_save - 32;
common_mode_defined = 1;
}
- if (! HAVE_prologue)
- {
- rtx prologue;
-
- start_sequence ();
-
- /* A NOTE_INSN_DELETED is supposed to be at the start and end of
- the "toplevel" insn chain. */
- emit_note (NOTE_INSN_DELETED);
- rs6000_emit_prologue ();
- emit_note (NOTE_INSN_DELETED);
-
- /* Expand INSN_ADDRESSES so final() doesn't crash. */
- {
- rtx insn;
- unsigned addr = 0;
- for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
- {
- INSN_ADDRESSES_NEW (insn, addr);
- addr += 4;
- }
- }
-
- prologue = get_insns ();
- end_sequence ();
-
- if (TARGET_DEBUG_STACK)
- debug_rtx_list (prologue, 100);
-
- emit_insn_before_noloc (prologue, BB_HEAD (ENTRY_BLOCK_PTR->next_bb),
- ENTRY_BLOCK_PTR);
- }
-
rs6000_pic_labelno++;
}
: TARGET_32BIT ? -220 : -288);
}
+/* Append CFA_RESTORES to any existing REG_NOTES on the last insn. */
+
+static void
+emit_cfa_restores (rtx cfa_restores)
+{
+ rtx insn = get_last_insn ();
+ rtx *loc = ®_NOTES (insn);
+
+ while (*loc)
+ loc = &XEXP (*loc, 1);
+ *loc = cfa_restores;
+ RTX_FRAME_RELATED_P (insn) = 1;
+}
+
/* Emit function epilogue as insns. */
void
here will not trigger at the moment; We don't actually need a
frame pointer for alloca, but the generic parts of the compiler
give us one anyway. */
- use_backchain_to_restore_sp = (info->total_size > 32767
- || info->total_size
- + (info->lr_save_p ? info->lr_save_offset : 0)
- > 32767
+ use_backchain_to_restore_sp = (info->total_size > 32767 - info->lr_save_offset
|| (cfun->calls_alloca
&& !frame_pointer_needed));
restore_lr = (info->lr_save_p
alloc_rname = ggc_strdup (rname);
j = 0;
- RTVEC_ELT (p, j++) = gen_rtx_RETURN (VOIDmode);
+ RTVEC_ELT (p, j++) = ret_rtx;
RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode,
gen_rtx_REG (Pmode,
LR_REGNO));
rtx mem = gen_frame_mem (reg_mode, addr);
RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
+
+ if (flag_shrink_wrap)
+ {
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
+ gen_rtx_REG (Pmode, LR_REGNO),
+ cfa_restores);
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
+ }
}
for (i = 0; i < 32 - info->first_gp_reg_save; i++)
rtx mem = gen_frame_mem (reg_mode, addr);
RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
+ if (flag_shrink_wrap)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
}
for (i = 0; info->first_altivec_reg_save + i <= LAST_ALTIVEC_REGNO; i++)
{
rtx mem = gen_frame_mem (V4SImode, addr);
RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
+ if (flag_shrink_wrap)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
}
for (i = 0; info->first_fp_reg_save + i <= 63; i++)
{
? DFmode : SFmode), addr);
RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
+ if (flag_shrink_wrap)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
}
RTVEC_ELT (p, j++)
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 0));
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 8));
RTVEC_ELT (p, j++)
= gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, 10));
- emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
+ insn = emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
+ if (flag_shrink_wrap)
+ {
+ REG_NOTES (insn) = cfa_restores;
+ add_reg_note (insn, REG_CFA_DEF_CFA, sp_reg_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
return;
}
reg = gen_rtx_REG (V4SImode, i);
emit_move_insn (reg, mem);
- if (offset_below_red_zone_p (info->altivec_save_offset
- + (i - info->first_altivec_reg_save)
- * 16))
+ if (flag_shrink_wrap
+ || offset_below_red_zone_p (info->altivec_save_offset
+ + (i - info->first_altivec_reg_save)
+ * 16))
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
cfa_restores);
}
reg = gen_rtx_REG (V4SImode, i);
emit_move_insn (reg, mem);
- if (DEFAULT_ABI == ABI_V4)
+ if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
cfa_restores);
}
emit_move_insn (cr_save_reg, mem);
}
- /* Set LR here to try to overlap restores below. LR is always saved
- above incoming stack, so it never needs REG_CFA_RESTORE. */
+ /* Set LR here to try to overlap restores below. */
if (restore_lr && restoring_GPRs_inline)
emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO),
gen_rtx_REG (Pmode, 0));
/* Restore GPRs. This is done as a PARALLEL if we are using
the load-multiple instructions. */
if (TARGET_SPE_ABI
- && info->spe_64bit_regs_used != 0
+ && info->spe_64bit_regs_used
&& info->first_gp_reg_save != 32)
{
/* Determine whether we can address all of the registers that need
- to be saved with an offset from the stack pointer that fits in
- the small const field for SPE memory instructions. */
- int spe_regs_addressable_via_sp
- = (SPE_CONST_OFFSET_OK(info->spe_gp_save_offset + sp_offset
- + (32 - info->first_gp_reg_save - 1) * reg_size)
+ to be saved with an offset from frame_reg_rtx that fits in
+ the small const field for SPE memory instructions. */
+ int spe_regs_addressable
+ = (SPE_CONST_OFFSET_OK (info->spe_gp_save_offset + sp_offset
+ + reg_size * (32 - info->first_gp_reg_save - 1))
&& restoring_GPRs_inline);
int spe_offset;
+ int ool_adjust = 0;
- if (spe_regs_addressable_via_sp)
+ if (spe_regs_addressable)
spe_offset = info->spe_gp_save_offset + sp_offset;
else
- {
+ {
rtx old_frame_reg_rtx = frame_reg_rtx;
- /* Make r11 point to the start of the SPE save area. We worried about
- not clobbering it when we were saving registers in the prologue.
- There's no need to worry here because the static chain is passed
- anew to every function. */
- int ool_adjust = (restoring_GPRs_inline
- ? 0
- : (info->first_gp_reg_save
- - (FIRST_SAVRES_REGISTER+1))*8);
-
- if (frame_reg_rtx == sp_reg_rtx)
- frame_reg_rtx = gen_rtx_REG (Pmode, 11);
- emit_insn (gen_addsi3 (frame_reg_rtx, old_frame_reg_rtx,
+ /* Make r11 point to the start of the SPE save area. We worried about
+ not clobbering it when we were saving registers in the prologue.
+ There's no need to worry here because the static chain is passed
+ anew to every function. */
+
+ if (!restoring_GPRs_inline)
+ ool_adjust = 8 * (info->first_gp_reg_save
+ - (FIRST_SAVRES_REGISTER + 1));
+ frame_reg_rtx = gen_rtx_REG (Pmode, 11);
+ emit_insn (gen_addsi3 (frame_reg_rtx, old_frame_reg_rtx,
GEN_INT (info->spe_gp_save_offset
+ sp_offset
- ool_adjust)));
/* Keep the invariant that frame_reg_rtx + sp_offset points
at the top of the stack frame. */
- sp_offset = -info->spe_gp_save_offset;
+ sp_offset = -info->spe_gp_save_offset + ool_adjust;
- spe_offset = 0;
- }
+ spe_offset = 0;
+ }
if (restoring_GPRs_inline)
{
mem = gen_rtx_MEM (V2SImode, addr);
reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
- insn = emit_move_insn (reg, mem);
- if (DEFAULT_ABI == ABI_V4)
- {
- if (frame_pointer_needed
- && info->first_gp_reg_save + i
- == HARD_FRAME_POINTER_REGNUM)
- {
- add_reg_note (insn, REG_CFA_DEF_CFA,
- plus_constant (frame_reg_rtx,
- sp_offset));
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
- cfa_restores);
- }
+ emit_move_insn (reg, mem);
}
}
else
- {
- rtx par;
-
- par = rs6000_make_savres_rtx (info, gen_rtx_REG (Pmode, 11),
- 0, reg_mode,
- /*savep=*/false, /*gpr=*/true,
- /*lr=*/true);
- emit_jump_insn (par);
- /* We don't want anybody else emitting things after we jumped
- back. */
- return;
- }
+ rs6000_emit_savres_rtx (info, frame_reg_rtx,
+ ool_adjust, reg_mode,
+ /*savep=*/false, /*gpr=*/true,
+ /*lr=*/true);
}
else if (!restoring_GPRs_inline)
{
/* We are jumping to an out-of-line function. */
bool can_use_exit = info->first_fp_reg_save == 64;
- rtx par;
/* Emit stack reset code if we need it. */
if (can_use_exit)
- rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx,
- sp_offset, can_use_exit);
- else
{
- emit_insn (gen_add3_insn (gen_rtx_REG (Pmode, DEFAULT_ABI == ABI_AIX
- ? 12 : 11),
- frame_reg_rtx,
- GEN_INT (sp_offset - info->fp_size)));
- if (REGNO (frame_reg_rtx) == 11)
- sp_offset += info->fp_size;
- }
-
- par = rs6000_make_savres_rtx (info, frame_reg_rtx,
- info->gp_save_offset, reg_mode,
- /*savep=*/false, /*gpr=*/true,
- /*lr=*/can_use_exit);
+ rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx,
+ sp_offset, can_use_exit);
+ if (DEFAULT_ABI == ABI_DARWIN)
+ /* we only need a copy, no fprs were saved. */
+ emit_move_insn (gen_rtx_REG (Pmode, 11), frame_reg_rtx);
- if (can_use_exit)
- {
if (info->cr_save_p)
- {
- rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
- if (DEFAULT_ABI == ABI_V4)
- cfa_restores
- = alloc_reg_note (REG_CFA_RESTORE,
- gen_rtx_REG (SImode, CR2_REGNO),
- cfa_restores);
- }
-
- emit_jump_insn (par);
-
- /* We don't want anybody else emitting things after we jumped
- back. */
- return;
+ rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
}
-
- insn = emit_insn (par);
- if (DEFAULT_ABI == ABI_V4)
+ else
{
- if (frame_pointer_needed)
- {
- add_reg_note (insn, REG_CFA_DEF_CFA,
- plus_constant (frame_reg_rtx, sp_offset));
- RTX_FRAME_RELATED_P (insn) = 1;
- }
+ rtx src_reg = gen_rtx_REG (Pmode, DEFAULT_ABI == ABI_AIX ? 12 : 11);
- for (i = info->first_gp_reg_save; i < 32; i++)
- cfa_restores
- = alloc_reg_note (REG_CFA_RESTORE,
- gen_rtx_REG (reg_mode, i), cfa_restores);
+ emit_insn (gen_add3_insn (src_reg, frame_reg_rtx,
+ GEN_INT (sp_offset - info->fp_size)));
+ if (REGNO (frame_reg_rtx) == REGNO (src_reg))
+ sp_offset = info->fp_size;
}
+
+ rs6000_emit_savres_rtx (info, frame_reg_rtx,
+ info->gp_save_offset, reg_mode,
+ /*savep=*/false, /*gpr=*/true,
+ /*lr=*/can_use_exit);
}
else if (using_load_multiple)
{
rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
RTVEC_ELT (p, i) = gen_rtx_SET (VOIDmode, reg, mem);
- if (DEFAULT_ABI == ABI_V4)
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
- cfa_restores);
- }
- insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
- if (DEFAULT_ABI == ABI_V4 && frame_pointer_needed)
- {
- add_reg_note (insn, REG_CFA_DEF_CFA,
- plus_constant (frame_reg_rtx, sp_offset));
- RTX_FRAME_RELATED_P (insn) = 1;
}
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
}
else
{
rtx mem = gen_frame_mem (reg_mode, addr);
rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
- insn = emit_move_insn (reg, mem);
- if (DEFAULT_ABI == ABI_V4)
- {
- if (frame_pointer_needed
- && info->first_gp_reg_save + i
- == HARD_FRAME_POINTER_REGNUM)
- {
- add_reg_note (insn, REG_CFA_DEF_CFA,
- plus_constant (frame_reg_rtx, sp_offset));
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
- cfa_restores);
- }
+ emit_move_insn (reg, mem);
}
}
+ if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
+ {
+ /* If the frame pointer was used then we can't delay emitting
+ a REG_CFA_DEF_CFA note. This must happen on the insn that
+ restores the frame pointer, r31. We may have already emitted
+ a REG_CFA_DEF_CFA note, but that's OK; A duplicate is
+ discarded by dwarf2cfi.c/dwarf2out.c, and in any case would
+ be harmless if emitted. */
+ if (frame_pointer_needed)
+ {
+ insn = get_last_insn ();
+ add_reg_note (insn, REG_CFA_DEF_CFA,
+ plus_constant (frame_reg_rtx, sp_offset));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ /* Set up cfa_restores. We always need these when
+ shrink-wrapping. If not shrink-wrapping then we only need
+ the cfa_restore when the stack location is no longer valid.
+ The cfa_restores must be emitted on or before the insn that
+ invalidates the stack, and of course must not be emitted
+ before the insn that actually does the restore. The latter
+ is why the LR cfa_restore condition below is a little
+ complicated. It's also why it is a bad idea to emit the
+ cfa_restores as a group on the last instruction here that
+ actually does a restore: That insn may be reordered with
+ respect to others doing restores. */
+ if (info->cr_save_p)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
+ gen_rtx_REG (SImode, CR2_REGNO),
+ cfa_restores);
+ if (flag_shrink_wrap
+ && (restore_lr
+ || (info->lr_save_p
+ && !restoring_GPRs_inline
+ && info->first_fp_reg_save == 64)))
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
+ gen_rtx_REG (Pmode, LR_REGNO),
+ cfa_restores);
+
+ for (i = info->first_gp_reg_save; i < 32; i++)
+ if (!restoring_GPRs_inline
+ || using_load_multiple
+ || rs6000_reg_live_or_pic_offset_p (i))
+ {
+ rtx reg = gen_rtx_REG (reg_mode, i);
+
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
+ }
+ }
+
+ if (!restoring_GPRs_inline
+ && info->first_fp_reg_save == 64)
+ {
+ /* We are jumping to an out-of-line function. */
+ if (cfa_restores)
+ emit_cfa_restores (cfa_restores);
+ return;
+ }
+
if (restore_lr && !restoring_GPRs_inline)
{
rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx,
/* Restore fpr's if we need to do it without calling a function. */
if (restoring_FPRs_inline)
for (i = 0; i < 64 - info->first_fp_reg_save; i++)
- if ((df_regs_ever_live_p (info->first_fp_reg_save+i)
- && ! call_used_regs[info->first_fp_reg_save+i]))
+ if ((df_regs_ever_live_p (info->first_fp_reg_save + i)
+ && !call_used_regs[info->first_fp_reg_save + i]))
{
rtx addr, mem, reg;
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
info->first_fp_reg_save + i);
emit_move_insn (reg, mem);
- if (DEFAULT_ABI == ABI_V4)
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
- cfa_restores);
+ if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
}
/* If we saved cr, restore it here. Just those that were used. */
if (info->cr_save_p)
- {
- rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
- if (DEFAULT_ABI == ABI_V4)
- cfa_restores
- = alloc_reg_note (REG_CFA_RESTORE, gen_rtx_REG (SImode, CR2_REGNO),
- cfa_restores);
- }
+ rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
/* If this is V.4, unwind the stack pointer after all of the loads
have been done. */
rtvec p;
bool lr = (strategy & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR) == 0;
if (! restoring_FPRs_inline)
- p = rtvec_alloc (4 + 64 - info->first_fp_reg_save);
+ {
+ p = rtvec_alloc (4 + 64 - info->first_fp_reg_save);
+ RTVEC_ELT (p, 0) = ret_rtx;
+ }
else
- p = rtvec_alloc (2);
+ {
+ if (cfa_restores)
+ {
+ /* We can't hang the cfa_restores off a simple return,
+ since the shrink-wrap code sometimes uses an existing
+ return. This means there might be a path from
+ pre-prologue code to this return, and dwarf2cfi code
+ wants the eh_frame unwinder state to be the same on
+ all paths to any point. So we need to emit the
+ cfa_restores before the return. For -m64 we really
+ don't need epilogue cfa_restores at all, except for
+ this irritating dwarf2cfi with shrink-wrap
+ requirement; The stack red-zone means eh_frame info
+ from the prologue telling the unwinder to restore
+ from the stack is perfectly good right to the end of
+ the function. */
+ emit_insn (gen_blockage ());
+ emit_cfa_restores (cfa_restores);
+ cfa_restores = NULL_RTX;
+ }
+ p = rtvec_alloc (2);
+ RTVEC_ELT (p, 0) = simple_return_rtx;
+ }
- RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
RTVEC_ELT (p, 1) = ((restoring_FPRs_inline || !lr)
- ? gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 65))
+ ? gen_rtx_USE (VOIDmode,
+ gen_rtx_REG (Pmode, LR_REGNO))
: gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_REG (Pmode, 65)));
+ gen_rtx_REG (Pmode, LR_REGNO)));
/* If we have to restore more than two FP registers, branch to the
restore function. It will return to our caller. */
int i;
rtx sym;
+ if ((DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
+ && lr)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
+ gen_rtx_REG (Pmode, LR_REGNO),
+ cfa_restores);
+
sym = rs6000_savres_routine_sym (info,
/*savep=*/false,
/*gpr=*/false,
? 1 : 11));
for (i = 0; i < 64 - info->first_fp_reg_save; i++)
{
- rtx addr, mem;
+ rtx addr, mem, reg;
+
addr = gen_rtx_PLUS (Pmode, sp_reg_rtx,
- GEN_INT (info->fp_save_offset + 8*i));
+ GEN_INT (info->fp_save_offset + 8 * i));
mem = gen_frame_mem (DFmode, addr);
+ reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
- RTVEC_ELT (p, i+4) =
- gen_rtx_SET (VOIDmode,
- gen_rtx_REG (DFmode, info->first_fp_reg_save + i),
- mem);
+ RTVEC_ELT (p, i + 4) = gen_rtx_SET (VOIDmode, reg, mem);
+ if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
+ cfa_restores);
}
}
emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
}
+
+ if (cfa_restores)
+ {
+ if (sibcall)
+ /* Ensure the cfa_restores are hung off an insn that won't
+ be reordered above other restores. */
+ emit_insn (gen_blockage ());
+
+ emit_cfa_restores (cfa_restores);
+ }
}
/* Write function epilogue. */
rs6000_output_function_epilogue (FILE *file,
HOST_WIDE_INT size ATTRIBUTE_UNUSED)
{
- if (! HAVE_epilogue)
- {
- rtx insn = get_last_insn ();
- /* If the last insn was a BARRIER, we don't have to write anything except
- the trace table. */
- if (GET_CODE (insn) == NOTE)
- insn = prev_nonnote_insn (insn);
- if (insn == 0 || GET_CODE (insn) != BARRIER)
- {
- /* This is slightly ugly, but at least we don't have two
- copies of the epilogue-emitting code. */
- start_sequence ();
-
- /* A NOTE_INSN_DELETED is supposed to be at the start
- and end of the "toplevel" insn chain. */
- emit_note (NOTE_INSN_DELETED);
- rs6000_emit_epilogue (FALSE);
- emit_note (NOTE_INSN_DELETED);
-
- /* Expand INSN_ADDRESSES so final() doesn't crash. */
- {
- rtx insn;
- unsigned addr = 0;
- for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
- {
- INSN_ADDRESSES_NEW (insn, addr);
- addr += 4;
- }
- }
-
- if (TARGET_DEBUG_STACK)
- debug_rtx_list (get_insns (), 100);
- final (get_insns (), file, FALSE);
- end_sequence ();
- }
- }
-
#if TARGET_MACHO
macho_branch_islands ();
/* Mach-O doesn't support labels at the end of objects, so if
it looks like we might want one, insert a NOP. */
{
rtx insn = get_last_insn ();
+ rtx deleted_debug_label = NULL_RTX;
while (insn
&& NOTE_P (insn)
&& NOTE_KIND (insn) != NOTE_INSN_DELETED_LABEL)
- insn = PREV_INSN (insn);
+ {
+ /* Don't insert a nop for NOTE_INSN_DELETED_DEBUG_LABEL
+ notes only, instead set their CODE_LABEL_NUMBER to -1,
+ otherwise there would be code generation differences
+ in between -g and -g0. */
+ if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL)
+ deleted_debug_label = insn;
+ insn = PREV_INSN (insn);
+ }
if (insn
&& (LABEL_P (insn)
|| (NOTE_P (insn)
&& NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL)))
fputs ("\tnop\n", file);
+ else if (deleted_debug_label)
+ for (insn = deleted_debug_label; insn; insn = NEXT_INSN (insn))
+ if (NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL)
+ CODE_LABEL_NUMBER (insn) = -1;
}
#endif
use language_string.
C is 0. Fortran is 1. Pascal is 2. Ada is 3. C++ is 9.
Java is 13. Objective-C is 14. Objective-C++ isn't assigned
- a number, so for now use 9. LTO isn't assigned a number either,
- so for now use 0. */
+ a number, so for now use 9. LTO and Go aren't assigned numbers
+ either, so for now use 0. */
if (! strcmp (language_string, "GNU C")
- || ! strcmp (language_string, "GNU GIMPLE"))
+ || ! strcmp (language_string, "GNU GIMPLE")
+ || ! strcmp (language_string, "GNU Go"))
i = 0;
else if (! strcmp (language_string, "GNU F77")
|| ! strcmp (language_string, "GNU Fortran"))
gen_rtx_USE (VOIDmode,
gen_rtx_REG (SImode,
LR_REGNO)),
- gen_rtx_RETURN (VOIDmode))));
+ simple_return_rtx)));
SIBLING_CALL_P (insn) = 1;
emit_barrier ();
rs6000_xcoff_strip_dollar (const char *name)
{
char *strip, *p;
- int len;
+ const char *q;
+ size_t len;
- p = strchr (name, '$');
+ q = (const char *) strchr (name, '$');
- if (p == 0 || p == name)
+ if (q == 0 || q == name)
return name;
len = strlen (name);
- strip = (char *) alloca (len + 1);
+ strip = XALLOCAVEC (char, len + 1);
strcpy (strip, name);
- p = strchr (strip, '$');
+ p = strip + (q - name);
while (p)
{
*p = '_';
rtx fun;
ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
- label_name = (*targetm.strip_name_encoding) (ggc_strdup (buf));
+ label_name = ggc_strdup ((*targetm.strip_name_encoding) (buf));
fun = gen_rtx_SYMBOL_REF (Pmode, label_name);
emit_library_call (init_one_libfunc (RS6000_MCOUNT),
}
else if (TARGET_SECURE_PLT && flag_pic)
{
- asm_fprintf (file, "\tbcl 20,31,1f\n1:\n\t{st|stw} %s,4(%s)\n",
+ if (TARGET_LINK_STACK)
+ {
+ char name[32];
+ get_ppc476_thunk_name (name);
+ asm_fprintf (file, "\tbl %s\n", name);
+ }
+ else
+ asm_fprintf (file, "\tbcl 20,31,1f\n1:\n");
+ asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
reg_names[0], reg_names[1]);
asm_fprintf (file, "\tmflr %s\n", reg_names[12]);
asm_fprintf (file, "\t{cau|addis} %s,%s,",
asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
reg_names[0], reg_names[1]);
/* Now, we need to get the address of the label. */
- fputs ("\tbcl 20,31,1f\n\t.long ", file);
- assemble_name (file, buf);
- fputs ("-.\n1:", file);
- asm_fprintf (file, "\tmflr %s\n", reg_names[11]);
- asm_fprintf (file, "\t{l|lwz} %s,0(%s)\n",
- reg_names[0], reg_names[11]);
- asm_fprintf (file, "\t{cax|add} %s,%s,%s\n",
- reg_names[0], reg_names[0], reg_names[11]);
+ if (TARGET_LINK_STACK)
+ {
+ char name[32];
+ get_ppc476_thunk_name (name);
+ asm_fprintf (file, "\tbl %s\n\tb 1f\n\t.long ", name);
+ assemble_name (file, buf);
+ fputs ("-.\n1:", file);
+ asm_fprintf (file, "\tmflr %s\n", reg_names[11]);
+ asm_fprintf (file, "\taddi %s,%s,4\n",
+ reg_names[11], reg_names[11]);
+ }
+ else
+ {
+ fputs ("\tbcl 20,31,1f\n\t.long ", file);
+ assemble_name (file, buf);
+ fputs ("-.\n1:", file);
+ asm_fprintf (file, "\tmflr %s\n", reg_names[11]);
+ }
+ asm_fprintf (file, "\t{l|lwz} %s,0(%s)\n",
+ reg_names[0], reg_names[11]);
+ asm_fprintf (file, "\t{cax|add} %s,%s,%s\n",
+ reg_names[0], reg_names[0], reg_names[11]);
}
else
{
val_diff = val1 - val0;
return ((REGNO (reg0) == REGNO (reg1))
- && ((MEM_SIZE (a) && val_diff == INTVAL (MEM_SIZE (a)))
- || (MEM_SIZE (b) && val_diff == -INTVAL (MEM_SIZE (b)))));
+ && ((MEM_SIZE_KNOWN_P (a) && val_diff == MEM_SIZE (a))
+ || (MEM_SIZE_KNOWN_P (b) && val_diff == -MEM_SIZE (b))));
}
return false;
/* Under AIX, just build the 3 word function descriptor */
case ABI_AIX:
{
- rtx fnmem = gen_const_mem (Pmode, force_reg (Pmode, fnaddr));
- rtx fn_reg = gen_reg_rtx (Pmode);
- rtx toc_reg = gen_reg_rtx (Pmode);
+ rtx fnmem, fn_reg, toc_reg;
+
+ if (!TARGET_POINTERS_TO_NESTED_FUNCTIONS)
+ error ("-mno-r11 must not be used if you have trampolines");
+
+ fnmem = gen_const_mem (Pmode, force_reg (Pmode, fnaddr));
+ fn_reg = gen_reg_rtx (Pmode);
+ toc_reg = gen_reg_rtx (Pmode);
/* Macro to shorten the code expansions below. */
# define MEM_PLUS(MEM, OFFSET) adjust_address (MEM, Pmode, OFFSET)
#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
if (flag_pic)
{
- strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,");
- strcat (tmp_buf, label);
- strcat (tmp_buf, "_pic\n");
- strcat (tmp_buf, label);
- strcat (tmp_buf, "_pic:\n\tmflr r11\n");
+ if (TARGET_LINK_STACK)
+ {
+ char name[32];
+ get_ppc476_thunk_name (name);
+ strcat (tmp_buf, ":\n\tmflr r0\n\tbl ");
+ strcat (tmp_buf, name);
+ strcat (tmp_buf, "\n");
+ strcat (tmp_buf, label);
+ strcat (tmp_buf, "_pic:\n\tmflr r11\n");
+ }
+ else
+ {
+ strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,");
+ strcat (tmp_buf, label);
+ strcat (tmp_buf, "_pic\n");
+ strcat (tmp_buf, label);
+ strcat (tmp_buf, "_pic:\n\tmflr r11\n");
+ }
strcat (tmp_buf, "\taddis r11,r11,ha16(");
strcat (tmp_buf, name_buf);
sprintf (local_label_0, "\"L%011d$spb\"", label);
fprintf (file, "\tmflr r0\n");
- fprintf (file, "\tbcl 20,31,%s\n", local_label_0);
- fprintf (file, "%s:\n\tmflr r11\n", local_label_0);
+ if (TARGET_LINK_STACK)
+ {
+ char name[32];
+ get_ppc476_thunk_name (name);
+ fprintf (file, "\tbl %s\n", name);
+ fprintf (file, "%s:\n\tmflr r11\n", local_label_0);
+ }
+ else
+ {
+ fprintf (file, "\tbcl 20,31,%s\n", local_label_0);
+ fprintf (file, "%s:\n\tmflr r11\n", local_label_0);
+ }
fprintf (file, "\taddis r11,r11,ha16(%s-%s)\n",
lazy_ptr_name, local_label_0);
fprintf (file, "\tmtlr r0\n");
darwin_file_start ();
/* Determine the argument to -mcpu=. Default to G3 if not specified. */
- for (i = 0; i < ARRAY_SIZE (rs6000_select); i++)
- if (rs6000_select[i].set_arch_p && rs6000_select[i].string
- && rs6000_select[i].string[0] != '\0')
- cpu_id = rs6000_select[i].string;
+
+ if (rs6000_default_cpu != 0 && rs6000_default_cpu[0] != '\0')
+ cpu_id = rs6000_default_cpu;
+
+ if (global_options_set.x_rs6000_cpu_index)
+ cpu_id = processor_target_table[rs6000_cpu_index].name;
/* Look through the mapping array. Pick the first name that either
matches the argument, has a bit set in IF_SET that is also set
unsigned int flags = default_section_type_flags (decl, name, reloc);
/* Align to at least UNIT size. */
- if (flags & SECTION_CODE)
+ if (flags & SECTION_CODE || !decl)
align = MIN_UNITS_PER_WORD;
else
/* Increase alignment of large objects if not already stricter. */
scanned. In either case, *TOTAL contains the cost result. */
static bool
-rs6000_rtx_costs (rtx x, int code, int outer_code, int *total,
- bool speed)
+rs6000_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+ int *total, bool speed)
{
enum machine_mode mode = GET_MODE (x);
/* Debug form of r6000_rtx_costs that is selected if -mdebug=cost. */
static bool
-rs6000_debug_rtx_costs (rtx x, int code, int outer_code, int *total,
+rs6000_debug_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
bool speed)
{
- bool ret = rs6000_rtx_costs (x, code, outer_code, total, speed);
+ bool ret = rs6000_rtx_costs (x, code, outer_code, opno, total, speed);
fprintf (stderr,
"\nrs6000_rtx_costs, return = %s, code = %s, outer_code = %s, "
- "total = %d, speed = %s, x:\n",
+ "opno = %d, total = %d, speed = %s, x:\n",
ret ? "complete" : "scan inner",
GET_RTX_NAME (code),
GET_RTX_NAME (outer_code),
+ opno,
*total,
speed ? "true" : "false");
{
int ret;
+ if (TARGET_DEBUG_COST)
+ dbg_cost_ctrl++;
+
/* Moves from/to GENERAL_REGS. */
if (reg_classes_intersect_p (to, GENERAL_REGS)
|| reg_classes_intersect_p (from, GENERAL_REGS))
{
+ reg_class_t rclass = from;
+
if (! reg_classes_intersect_p (to, GENERAL_REGS))
- from = to;
+ rclass = to;
- if (from == FLOAT_REGS || from == ALTIVEC_REGS || from == VSX_REGS)
- ret = (rs6000_memory_move_cost (mode, from, false)
+ if (rclass == FLOAT_REGS || rclass == ALTIVEC_REGS || rclass == VSX_REGS)
+ ret = (rs6000_memory_move_cost (mode, rclass, false)
+ rs6000_memory_move_cost (mode, GENERAL_REGS, false));
/* It's more expensive to move CR_REGS than CR0_REGS because of the
shift. */
- else if (from == CR_REGS)
+ else if (rclass == CR_REGS)
ret = 4;
- /* Power6 has slower LR/CTR moves so make them more expensive than
- memory in order to bias spills to memory .*/
- else if (rs6000_cpu == PROCESSOR_POWER6
- && reg_classes_intersect_p (from, LINK_OR_CTR_REGS))
+ /* For those processors that have slow LR/CTR moves, make them more
+ expensive than memory in order to bias spills to memory .*/
+ else if ((rs6000_cpu == PROCESSOR_POWER6
+ || rs6000_cpu == PROCESSOR_POWER7)
+ && reg_classes_intersect_p (rclass, LINK_OR_CTR_REGS))
ret = 6 * hard_regno_nregs[0][mode];
else
+ rs6000_register_move_cost (mode, from, GENERAL_REGS));
if (TARGET_DEBUG_COST)
- fprintf (stderr,
- "rs6000_register_move_cost:, ret=%d, mode=%s, from=%s, to=%s\n",
- ret, GET_MODE_NAME (mode), reg_class_names[from],
- reg_class_names[to]);
+ {
+ if (dbg_cost_ctrl == 1)
+ fprintf (stderr,
+ "rs6000_register_move_cost:, ret=%d, mode=%s, from=%s, to=%s\n",
+ ret, GET_MODE_NAME (mode), reg_class_names[from],
+ reg_class_names[to]);
+ dbg_cost_ctrl--;
+ }
return ret;
}
{
int ret;
+ if (TARGET_DEBUG_COST)
+ dbg_cost_ctrl++;
+
if (reg_classes_intersect_p (rclass, GENERAL_REGS))
ret = 4 * hard_regno_nregs[0][mode];
else if (reg_classes_intersect_p (rclass, FLOAT_REGS))
ret = 4 + rs6000_register_move_cost (mode, rclass, GENERAL_REGS);
if (TARGET_DEBUG_COST)
- fprintf (stderr,
- "rs6000_memory_move_cost: ret=%d, mode=%s, rclass=%s, in=%d\n",
- ret, GET_MODE_NAME (mode), reg_class_names[rclass], in);
+ {
+ if (dbg_cost_ctrl == 1)
+ fprintf (stderr,
+ "rs6000_memory_move_cost: ret=%d, mode=%s, rclass=%s, in=%d\n",
+ ret, GET_MODE_NAME (mode), reg_class_names[rclass], in);
+ dbg_cost_ctrl--;
+ }
return ret;
}
if (!RS6000_RECIP_AUTO_RSQRTE_P (V2DFmode))
return NULL_TREE;
- return rs6000_builtin_decls[VSX_BUILTIN_VEC_RSQRT_V2DF];
+ return rs6000_builtin_decls[VSX_BUILTIN_RSQRT_2DF];
case VSX_BUILTIN_XVSQRTSP:
if (!RS6000_RECIP_AUTO_RSQRTE_P (V4SFmode))
return NULL_TREE;
- return rs6000_builtin_decls[VSX_BUILTIN_VEC_RSQRT_V4SF];
+ return rs6000_builtin_decls[VSX_BUILTIN_RSQRT_4SF];
default:
return NULL_TREE;
}
}
+/* Expand an Altivec constant permutation. Return true if we match
+ an efficient implementation; false to fall back to VPERM. */
+
+bool
+altivec_expand_vec_perm_const (rtx operands[4])
+{
+ struct altivec_perm_insn {
+ enum insn_code impl;
+ unsigned char perm[16];
+ };
+ static const struct altivec_perm_insn patterns[] = {
+ { CODE_FOR_altivec_vpkuhum,
+ { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 } },
+ { CODE_FOR_altivec_vpkuwum,
+ { 2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31 } },
+ { CODE_FOR_altivec_vmrghb,
+ { 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23 } },
+ { CODE_FOR_altivec_vmrghh,
+ { 0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23 } },
+ { CODE_FOR_altivec_vmrghw,
+ { 0, 1, 2, 3, 16, 17, 18, 19, 4, 5, 6, 7, 20, 21, 22, 23 } },
+ { CODE_FOR_altivec_vmrglb,
+ { 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31 } },
+ { CODE_FOR_altivec_vmrglh,
+ { 8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31 } },
+ { CODE_FOR_altivec_vmrglw,
+ { 8, 9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31 } }
+ };
+
+ unsigned int i, j, elt, which;
+ unsigned char perm[16];
+ rtx target, op0, op1, sel, x;
+ bool one_vec;
+
+ target = operands[0];
+ op0 = operands[1];
+ op1 = operands[2];
+ sel = operands[3];
+
+ /* Unpack the constant selector. */
+ for (i = which = 0; i < 16; ++i)
+ {
+ rtx e = XVECEXP (sel, 0, i);
+ elt = INTVAL (e) & 31;
+ which |= (elt < 16 ? 1 : 2);
+ perm[i] = elt;
+ }
+
+ /* Simplify the constant selector based on operands. */
+ switch (which)
+ {
+ default:
+ gcc_unreachable ();
+
+ case 3:
+ one_vec = false;
+ if (!rtx_equal_p (op0, op1))
+ break;
+ /* FALLTHRU */
+
+ case 2:
+ for (i = 0; i < 16; ++i)
+ perm[i] &= 15;
+ op0 = op1;
+ one_vec = true;
+ break;
+
+ case 1:
+ op1 = op0;
+ one_vec = true;
+ break;
+ }
+
+ /* Look for splat patterns. */
+ if (one_vec)
+ {
+ elt = perm[0];
+
+ for (i = 0; i < 16; ++i)
+ if (perm[i] != elt)
+ break;
+ if (i == 16)
+ {
+ emit_insn (gen_altivec_vspltb (target, op0, GEN_INT (elt)));
+ return true;
+ }
+
+ if (elt % 2 == 0)
+ {
+ for (i = 0; i < 16; i += 2)
+ if (perm[i] != elt || perm[i + 1] != elt + 1)
+ break;
+ if (i == 16)
+ {
+ x = gen_reg_rtx (V8HImode);
+ emit_insn (gen_altivec_vsplth (x, gen_lowpart (V8HImode, op0),
+ GEN_INT (elt / 2)));
+ emit_move_insn (target, gen_lowpart (V16QImode, x));
+ return true;
+ }
+ }
+
+ if (elt % 4 == 0)
+ {
+ for (i = 0; i < 16; i += 4)
+ if (perm[i] != elt
+ || perm[i + 1] != elt + 1
+ || perm[i + 2] != elt + 2
+ || perm[i + 3] != elt + 3)
+ break;
+ if (i == 16)
+ {
+ x = gen_reg_rtx (V4SImode);
+ emit_insn (gen_altivec_vspltw (x, gen_lowpart (V4SImode, op0),
+ GEN_INT (elt / 4)));
+ emit_move_insn (target, gen_lowpart (V16QImode, x));
+ return true;
+ }
+ }
+ }
+
+ /* Look for merge and pack patterns. */
+ for (j = 0; j < ARRAY_SIZE (patterns); ++j)
+ {
+ bool swapped;
+
+ elt = patterns[j].perm[0];
+ if (perm[0] == elt)
+ swapped = false;
+ else if (perm[0] == elt + 16)
+ swapped = true;
+ else
+ continue;
+ for (i = 1; i < 16; ++i)
+ {
+ elt = patterns[j].perm[i];
+ if (swapped)
+ elt = (elt >= 16 ? elt - 16 : elt + 16);
+ else if (one_vec && elt >= 16)
+ elt -= 16;
+ if (perm[i] != elt)
+ break;
+ }
+ if (i == 16)
+ {
+ enum insn_code icode = patterns[j].impl;
+ enum machine_mode omode = insn_data[icode].operand[0].mode;
+ enum machine_mode imode = insn_data[icode].operand[1].mode;
+
+ if (swapped)
+ x = op0, op0 = op1, op1 = x;
+ if (imode != V16QImode)
+ {
+ op0 = gen_lowpart (imode, op0);
+ op1 = gen_lowpart (imode, op1);
+ }
+ if (omode == V16QImode)
+ x = target;
+ else
+ x = gen_reg_rtx (omode);
+ emit_insn (GEN_FCN (icode) (x, op0, op1));
+ if (omode != V16QImode)
+ emit_move_insn (target, gen_lowpart (V16QImode, x));
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Expand a Paired Single, VSX Permute Doubleword, or SPE constant permutation.
+ Return true if we match an efficient implementation. */
+
+static bool
+rs6000_expand_vec_perm_const_1 (rtx target, rtx op0, rtx op1,
+ unsigned char perm0, unsigned char perm1)
+{
+ rtx x;
+
+ /* If both selectors come from the same operand, fold to single op. */
+ if ((perm0 & 2) == (perm1 & 2))
+ {
+ if (perm0 & 2)
+ op0 = op1;
+ else
+ op1 = op0;
+ }
+ /* If both operands are equal, fold to simpler permutation. */
+ if (rtx_equal_p (op0, op1))
+ {
+ perm0 = perm0 & 1;
+ perm1 = (perm1 & 1) + 2;
+ }
+ /* If the first selector comes from the second operand, swap. */
+ else if (perm0 & 2)
+ {
+ if (perm1 & 2)
+ return false;
+ perm0 -= 2;
+ perm1 += 2;
+ x = op0, op0 = op1, op1 = x;
+ }
+ /* If the second selector does not come from the second operand, fail. */
+ else if ((perm1 & 2) == 0)
+ return false;
+
+ /* Success! */
+ if (target != NULL)
+ {
+ enum machine_mode vmode, dmode;
+ rtvec v;
+
+ vmode = GET_MODE (target);
+ gcc_assert (GET_MODE_NUNITS (vmode) == 2);
+ dmode = mode_for_vector (GET_MODE_INNER (vmode), 4);
+
+ x = gen_rtx_VEC_CONCAT (dmode, op0, op1);
+ v = gen_rtvec (2, GEN_INT (perm0), GEN_INT (perm1));
+ x = gen_rtx_VEC_SELECT (vmode, x, gen_rtx_PARALLEL (VOIDmode, v));
+ emit_insn (gen_rtx_SET (VOIDmode, target, x));
+ }
+ return true;
+}
+
+bool
+rs6000_expand_vec_perm_const (rtx operands[4])
+{
+ rtx target, op0, op1, sel;
+ unsigned char perm0, perm1;
+
+ target = operands[0];
+ op0 = operands[1];
+ op1 = operands[2];
+ sel = operands[3];
+
+ /* Unpack the constant selector. */
+ perm0 = INTVAL (XVECEXP (sel, 0, 0)) & 3;
+ perm1 = INTVAL (XVECEXP (sel, 0, 1)) & 3;
+
+ return rs6000_expand_vec_perm_const_1 (target, op0, op1, perm0, perm1);
+}
+
+/* Test whether a constant permutation is supported. */
+
+static bool
+rs6000_vectorize_vec_perm_const_ok (enum machine_mode vmode,
+ const unsigned char *sel)
+{
+ /* AltiVec (and thus VSX) can handle arbitrary permutations. */
+ if (TARGET_ALTIVEC)
+ return true;
+
+ /* Check for ps_merge* or evmerge* insns. */
+ if ((TARGET_PAIRED_FLOAT && vmode == V2SFmode)
+ || (TARGET_SPE && vmode == V2SImode))
+ {
+ rtx op0 = gen_raw_REG (vmode, LAST_VIRTUAL_REGISTER + 1);
+ rtx op1 = gen_raw_REG (vmode, LAST_VIRTUAL_REGISTER + 2);
+ return rs6000_expand_vec_perm_const_1 (NULL, op0, op1, sel[0], sel[1]);
+ }
+
+ return false;
+}
+
+/* A subroutine for rs6000_expand_extract_even & rs6000_expand_interleave. */
+
+static void
+rs6000_do_expand_vec_perm (rtx target, rtx op0, rtx op1,
+ enum machine_mode vmode, unsigned nelt, rtx perm[])
+{
+ enum machine_mode imode;
+ rtx x;
+
+ imode = vmode;
+ if (GET_MODE_CLASS (vmode) != MODE_VECTOR_INT)
+ {
+ imode = GET_MODE_INNER (vmode);
+ imode = mode_for_size (GET_MODE_BITSIZE (imode), MODE_INT, 0);
+ imode = mode_for_vector (imode, nelt);
+ }
+
+ x = gen_rtx_CONST_VECTOR (imode, gen_rtvec_v (nelt, perm));
+ x = expand_vec_perm (vmode, op0, op1, x, target);
+ if (x != target)
+ emit_move_insn (target, x);
+}
+
+/* Expand an extract even operation. */
+
+void
+rs6000_expand_extract_even (rtx target, rtx op0, rtx op1)
+{
+ enum machine_mode vmode = GET_MODE (target);
+ unsigned i, nelt = GET_MODE_NUNITS (vmode);
+ rtx perm[16];
+
+ for (i = 0; i < nelt; i++)
+ perm[i] = GEN_INT (i * 2);
+
+ rs6000_do_expand_vec_perm (target, op0, op1, vmode, nelt, perm);
+}
+
+/* Expand a vector interleave operation. */
+
+void
+rs6000_expand_interleave (rtx target, rtx op0, rtx op1, bool highp)
+{
+ enum machine_mode vmode = GET_MODE (target);
+ unsigned i, high, nelt = GET_MODE_NUNITS (vmode);
+ rtx perm[16];
+
+ high = (highp == BYTES_BIG_ENDIAN ? 0 : nelt / 2);
+ for (i = 0; i < nelt / 2; i++)
+ {
+ perm[i * 2] = GEN_INT (i + high);
+ perm[i * 2 + 1] = GEN_INT (i + nelt + high);
+ }
+
+ rs6000_do_expand_vec_perm (target, op0, op1, vmode, nelt, perm);
+}
+
/* Return an RTX representing where to find the function value of a
function returning MODE. */
static rtx
else if (TREE_CODE (valtype) == COMPLEX_TYPE
&& targetm.calls.split_complex_arg)
return rs6000_complex_function_value (mode);
+ /* VSX is a superset of Altivec and adds V2DImode/V2DFmode. Since the same
+ return register is used in both cases, and we won't see V2DImode/V2DFmode
+ for pure altivec, combine the two cases. */
else if (TREE_CODE (valtype) == VECTOR_TYPE
&& TARGET_ALTIVEC && TARGET_ALTIVEC_ABI
- && ALTIVEC_VECTOR_MODE (mode))
- regno = ALTIVEC_ARG_RETURN;
- else if (TREE_CODE (valtype) == VECTOR_TYPE
- && TARGET_VSX && TARGET_ALTIVEC_ABI
- && VSX_VECTOR_MODE (mode))
+ && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
regno = ALTIVEC_ARG_RETURN;
else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
&& (mode == DFmode || mode == DCmode
&& TARGET_HARD_FLOAT && TARGET_FPRS
&& ((TARGET_SINGLE_FLOAT && mode == SFmode) || TARGET_DOUBLE_FLOAT))
regno = FP_ARG_RETURN;
- else if (ALTIVEC_VECTOR_MODE (mode)
+ /* VSX is a superset of Altivec and adds V2DImode/V2DFmode. Since the same
+ return register is used in both cases, and we won't see V2DImode/V2DFmode
+ for pure altivec, combine the two cases. */
+ else if (ALTIVEC_OR_VSX_VECTOR_MODE (mode)
&& TARGET_ALTIVEC && TARGET_ALTIVEC_ABI)
regno = ALTIVEC_ARG_RETURN;
- else if (VSX_VECTOR_MODE (mode)
- && TARGET_VSX && TARGET_ALTIVEC_ABI)
- regno = ALTIVEC_ARG_RETURN;
else if (COMPLEX_MODE_P (mode) && targetm.calls.split_complex_arg)
return rs6000_complex_function_value (mode);
else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
calling __stack_chk_fail directly. Otherwise it is better to call
__stack_chk_fail directly. */
-static tree
+static tree ATTRIBUTE_UNUSED
rs6000_stack_protect_fail (void)
{
return (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT && flag_pic)
{ "string", MASK_STRING, false, false },
};
+/* Builtin mask mapping for printing the flags. */
+static struct rs6000_opt_mask const rs6000_builtin_mask_names[] =
+{
+ { "altivec", RS6000_BTM_ALTIVEC, false, false },
+ { "vsx", RS6000_BTM_VSX, false, false },
+ { "spe", RS6000_BTM_SPE, false, false },
+ { "paired", RS6000_BTM_PAIRED, false, false },
+ { "fre", RS6000_BTM_FRE, false, false },
+ { "fres", RS6000_BTM_FRES, false, false },
+ { "frsqrte", RS6000_BTM_FRSQRTE, false, false },
+ { "frsqrtes", RS6000_BTM_FRSQRTES, false, false },
+ { "popcntd", RS6000_BTM_POPCNTD, false, false },
+ { "powerpc", RS6000_BTM_POWERPC, false, false },
+ { "cell", RS6000_BTM_CELL, false, false },
+};
+
/* Option variables that we want to support inside attribute((target)) and
#pragma GCC target operations. */
error_p = false;
target_flags_explicit |= mask;
+ /* VSX needs altivec, so -mvsx automagically sets
+ altivec. */
+ if (mask == MASK_VSX && !invert)
+ mask |= MASK_ALTIVEC;
+
if (rs6000_opt_masks[i].invert)
invert = !invert;
if (strcmp (r, rs6000_opt_vars[i].name) == 0)
{
size_t j = rs6000_opt_vars[i].global_offset;
- ((int *) &global_options)[j] = !invert;
+ *((int *) ((char *)&global_options + j)) = !invert;
error_p = false;
break;
}
bool
rs6000_pragma_target_parse (tree args, tree pop_target)
{
+ tree prev_tree = build_target_option_node ();
tree cur_tree;
- bool ret;
+ struct cl_target_option *prev_opt, *cur_opt;
+ unsigned prev_bumask, cur_bumask, diff_bumask;
+ int prev_flags, cur_flags, diff_flags;
if (TARGET_DEBUG_TARGET)
{
if (! args)
{
- ret = true;
cur_tree = ((pop_target)
? pop_target
: target_option_default_node);
else
{
rs6000_cpu_index = rs6000_tune_index = -1;
- ret = rs6000_inner_target_options (args, false);
- cur_tree = build_target_option_node ();
+ if (!rs6000_inner_target_options (args, false)
+ || !rs6000_option_override_internal (false)
+ || (cur_tree = build_target_option_node ()) == NULL_TREE)
+ {
+ if (TARGET_DEBUG_BUILTIN || TARGET_DEBUG_TARGET)
+ fprintf (stderr, "invalid pragma\n");
- if (!cur_tree)
- ret = false;
+ return false;
+ }
}
- if (cur_tree)
- target_option_current_node = cur_tree;
+ target_option_current_node = cur_tree;
- return ret;
+ /* If we have the preprocessor linked in (i.e. C or C++ languages), possibly
+ change the macros that are defined. */
+ if (rs6000_target_modify_macros_ptr)
+ {
+ prev_opt = TREE_TARGET_OPTION (prev_tree);
+ prev_bumask = prev_opt->x_rs6000_builtin_mask;
+ prev_flags = prev_opt->x_target_flags;
+
+ cur_opt = TREE_TARGET_OPTION (cur_tree);
+ cur_flags = cur_opt->x_target_flags;
+ cur_bumask = cur_opt->x_rs6000_builtin_mask;
+
+ diff_bumask = (prev_bumask ^ cur_bumask);
+ diff_flags = (prev_flags ^ cur_flags);
+
+ if ((diff_flags != 0) || (diff_bumask != 0))
+ {
+ /* Delete old macros. */
+ rs6000_target_modify_macros_ptr (false,
+ prev_flags & diff_flags,
+ prev_bumask & diff_bumask);
+
+ /* Define new macros. */
+ rs6000_target_modify_macros_ptr (true,
+ cur_flags & diff_flags,
+ cur_bumask & diff_bumask);
+ }
+ }
+
+ return true;
}
\f
{
size_t i;
int flags = ptr->x_target_flags;
+ unsigned bu_mask = ptr->x_rs6000_builtin_mask;
/* Print the various mask options. */
for (i = 0; i < ARRAY_SIZE (rs6000_opt_masks); i++)
fprintf (file, "%*s-m%s\n", indent, "",
rs6000_opt_vars[i].name);
}
+
+ /* Print the various builtin flags. */
+ fprintf (file, "%*sbuiltin mask = 0x%x\n", indent, "", bu_mask);
+ for (i = 0; i < ARRAY_SIZE (rs6000_builtin_mask_names); i++)
+ if ((bu_mask & rs6000_builtin_mask_names[i].mask) != 0)
+ {
+ fprintf (file, "%*s%s builtins supported\n", indent, "",
+ rs6000_builtin_mask_names[i].name);
+ }
}
\f
return x;
}
+/* Implement TARGET_LEGITIMATE_CONSTANT_P.
+
+ On the RS/6000, all integer constants are acceptable, most won't be valid
+ for particular insns, though. Only easy FP constants are acceptable. */
+
+static bool
+rs6000_legitimate_constant_p (enum machine_mode mode, rtx x)
+{
+ if (rs6000_tls_referenced_p (x))
+ return false;
+
+ return ((GET_CODE (x) != CONST_DOUBLE && GET_CODE (x) != CONST_VECTOR)
+ || GET_MODE (x) == VOIDmode
+ || (TARGET_POWERPC64 && mode == DImode)
+ || easy_fp_constant (x, mode)
+ || easy_vector_constant (x, mode));
+}
+
+\f
+/* A function pointer under AIX is a pointer to a data area whose first word
+ contains the actual address of the function, whose second word contains a
+ pointer to its TOC, and whose third word contains a value to place in the
+ static chain register (r11). Note that if we load the static chain, our
+ "trampoline" need not have any executable code. */
+
+void
+rs6000_call_indirect_aix (rtx value, rtx func_desc, rtx flag)
+{
+ rtx func_addr;
+ rtx toc_reg;
+ rtx sc_reg;
+ rtx stack_ptr;
+ rtx stack_toc_offset;
+ rtx stack_toc_mem;
+ rtx func_toc_offset;
+ rtx func_toc_mem;
+ rtx func_sc_offset;
+ rtx func_sc_mem;
+ rtx insn;
+ rtx (*call_func) (rtx, rtx, rtx, rtx);
+ rtx (*call_value_func) (rtx, rtx, rtx, rtx, rtx);
+
+ stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+ toc_reg = gen_rtx_REG (Pmode, TOC_REGNUM);
+
+ /* Load up address of the actual function. */
+ func_desc = force_reg (Pmode, func_desc);
+ func_addr = gen_reg_rtx (Pmode);
+ emit_move_insn (func_addr, gen_rtx_MEM (Pmode, func_desc));
+
+ if (TARGET_32BIT)
+ {
+
+ stack_toc_offset = GEN_INT (TOC_SAVE_OFFSET_32BIT);
+ func_toc_offset = GEN_INT (AIX_FUNC_DESC_TOC_32BIT);
+ func_sc_offset = GEN_INT (AIX_FUNC_DESC_SC_32BIT);
+ if (TARGET_POINTERS_TO_NESTED_FUNCTIONS)
+ {
+ call_func = gen_call_indirect_aix32bit;
+ call_value_func = gen_call_value_indirect_aix32bit;
+ }
+ else
+ {
+ call_func = gen_call_indirect_aix32bit_nor11;
+ call_value_func = gen_call_value_indirect_aix32bit_nor11;
+ }
+ }
+ else
+ {
+ stack_toc_offset = GEN_INT (TOC_SAVE_OFFSET_64BIT);
+ func_toc_offset = GEN_INT (AIX_FUNC_DESC_TOC_64BIT);
+ func_sc_offset = GEN_INT (AIX_FUNC_DESC_SC_64BIT);
+ if (TARGET_POINTERS_TO_NESTED_FUNCTIONS)
+ {
+ call_func = gen_call_indirect_aix64bit;
+ call_value_func = gen_call_value_indirect_aix64bit;
+ }
+ else
+ {
+ call_func = gen_call_indirect_aix64bit_nor11;
+ call_value_func = gen_call_value_indirect_aix64bit_nor11;
+ }
+ }
+
+ /* Reserved spot to store the TOC. */
+ stack_toc_mem = gen_frame_mem (Pmode,
+ gen_rtx_PLUS (Pmode,
+ stack_ptr,
+ stack_toc_offset));
+
+ gcc_assert (cfun);
+ gcc_assert (cfun->machine);
+
+ /* Can we optimize saving the TOC in the prologue or do we need to do it at
+ every call? */
+ if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca)
+ cfun->machine->save_toc_in_prologue = true;
+
+ else
+ {
+ MEM_VOLATILE_P (stack_toc_mem) = 1;
+ emit_move_insn (stack_toc_mem, toc_reg);
+ }
+
+ /* Calculate the address to load the TOC of the called function. We don't
+ actually load this until the split after reload. */
+ func_toc_mem = gen_rtx_MEM (Pmode,
+ gen_rtx_PLUS (Pmode,
+ func_desc,
+ func_toc_offset));
+
+ /* If we have a static chain, load it up. */
+ if (TARGET_POINTERS_TO_NESTED_FUNCTIONS)
+ {
+ func_sc_mem = gen_rtx_MEM (Pmode,
+ gen_rtx_PLUS (Pmode,
+ func_desc,
+ func_sc_offset));
+
+ sc_reg = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
+ emit_move_insn (sc_reg, func_sc_mem);
+ }
+
+ /* Create the call. */
+ if (value)
+ insn = call_value_func (value, func_addr, flag, func_toc_mem,
+ stack_toc_mem);
+ else
+ insn = call_func (func_addr, flag, func_toc_mem, stack_toc_mem);
+
+ emit_call_insn (insn);
+}
+
+/* Return whether we need to always update the saved TOC pointer when we update
+ the stack pointer. */
+
+static bool
+rs6000_save_toc_in_prologue_p (void)
+{
+ return (cfun && cfun->machine && cfun->machine->save_toc_in_prologue);
+}
+
+#ifdef HAVE_GAS_HIDDEN
+# define USE_HIDDEN_LINKONCE 1
+#else
+# define USE_HIDDEN_LINKONCE 0
+#endif
+
+/* Fills in the label name that should be used for a 476 link stack thunk. */
+
+void
+get_ppc476_thunk_name (char name[32])
+{
+ gcc_assert (TARGET_LINK_STACK);
+
+ if (USE_HIDDEN_LINKONCE)
+ sprintf (name, "__ppc476.get_thunk");
+ else
+ ASM_GENERATE_INTERNAL_LABEL (name, "LPPC476_", 0);
+}
+
+/* This function emits the simple thunk routine that is used to preserve
+ the link stack on the 476 cpu. */
+
+static void
+rs6000_code_end (void)
+{
+ char name[32];
+ tree decl;
+
+ if (!TARGET_LINK_STACK)
+ return;
+
+ get_ppc476_thunk_name (name);
+
+ decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, get_identifier (name),
+ build_function_type_list (void_type_node, NULL_TREE));
+ DECL_RESULT (decl) = build_decl (BUILTINS_LOCATION, RESULT_DECL,
+ NULL_TREE, void_type_node);
+ TREE_PUBLIC (decl) = 1;
+ TREE_STATIC (decl) = 1;
+
+ if (USE_HIDDEN_LINKONCE)
+ {
+ DECL_COMDAT_GROUP (decl) = DECL_ASSEMBLER_NAME (decl);
+ targetm.asm_out.unique_section (decl, 0);
+ switch_to_section (get_named_section (decl, NULL, 0));
+ DECL_WEAK (decl) = 1;
+ ASM_WEAKEN_DECL (asm_out_file, decl, name, 0);
+ targetm.asm_out.globalize_label (asm_out_file, name);
+ targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN);
+ ASM_DECLARE_FUNCTION_NAME (asm_out_file, name, decl);
+ }
+ else
+ {
+ switch_to_section (text_section);
+ ASM_OUTPUT_LABEL (asm_out_file, name);
+ }
+
+ DECL_INITIAL (decl) = make_node (BLOCK);
+ current_function_decl = decl;
+ init_function_start (decl);
+ first_function_block_is_cold = false;
+ /* Make sure unwind info is emitted for the thunk if needed. */
+ final_start_function (emit_barrier (), asm_out_file, 1);
+
+ fputs ("\tblr\n", asm_out_file);
+
+ final_end_function ();
+ init_insn_lengths ();
+ free_after_compilation (cfun);
+ set_cfun (NULL);
+ current_function_decl = NULL;
+}
+
+/* Add r30 to hard reg set if the prologue sets it up and it is not
+ pic_offset_table_rtx. */
+
+static void
+rs6000_set_up_by_prologue (struct hard_reg_set_container *set)
+{
+ if (!TARGET_SINGLE_PIC_BASE
+ && TARGET_TOC
+ && TARGET_MINIMAL_TOC
+ && get_pool_size () != 0)
+ add_to_hard_reg_set (&set->set, Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
+}
+
+struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-rs6000.h"