diff options
author | Imre Kaloz <kaloz@openwrt.org> | 2011-07-02 07:43:26 +0000 |
---|---|---|
committer | Imre Kaloz <kaloz@openwrt.org> | 2011-07-02 07:43:26 +0000 |
commit | 4fbc50d89a2d97cd1d4b2537a29cd6b2f85b3d48 (patch) | |
tree | 5bbb84c84b1900a136e402db910673080932898c /toolchain/gcc/patches/4.4.1+cs | |
parent | 5f397b16ef44c1338c447a8e24a1b9f51a3c51d8 (diff) | |
download | upstream-4fbc50d89a2d97cd1d4b2537a29cd6b2f85b3d48.tar.gz upstream-4fbc50d89a2d97cd1d4b2537a29cd6b2f85b3d48.tar.bz2 upstream-4fbc50d89a2d97cd1d4b2537a29cd6b2f85b3d48.zip |
nuke support for older gcc versions, except for 4.4.6 (needed for avr32 and ubicom32)
SVN-Revision: 27351
Diffstat (limited to 'toolchain/gcc/patches/4.4.1+cs')
12 files changed, 0 insertions, 39498 deletions
diff --git a/toolchain/gcc/patches/4.4.1+cs/000-codesourcery_2010_71.patch b/toolchain/gcc/patches/4.4.1+cs/000-codesourcery_2010_71.patch deleted file mode 100644 index cf2e68f13e..0000000000 --- a/toolchain/gcc/patches/4.4.1+cs/000-codesourcery_2010_71.patch +++ /dev/null @@ -1,29759 +0,0 @@ ---- a/gcc/addresses.h -+++ b/gcc/addresses.h -@@ -78,3 +78,42 @@ - - return ok_for_base_p_1 (regno, mode, outer_code, index_code); - } -+ -+/* Wrapper function to unify target macros MODE_INDEX_REG_CLASS and -+ INDEX_REG_CLASS. Arguments as for the MODE_INDEX_REG_CLASS macro. */ -+ -+static inline enum reg_class -+index_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED) -+{ -+#ifdef MODE_INDEX_REG_CLASS -+ return MODE_INDEX_REG_CLASS (mode); -+#else -+ return INDEX_REG_CLASS; -+#endif -+} -+ -+/* Wrapper function to unify target macros REGNO_MODE_OK_FOR_INDEX_P -+ and REGNO_OK_FOR_INDEX_P. Arguments as for the -+ REGNO_MODE_OK_FOR_INDEX_P macro. */ -+ -+static inline bool -+ok_for_index_p_1 (unsigned regno, enum machine_mode mode ATTRIBUTE_UNUSED) -+{ -+#ifdef REGNO_MODE_OK_FOR_INDEX_P -+ return REGNO_MODE_OK_FOR_INDEX_P (regno, mode); -+#else -+ return REGNO_OK_FOR_INDEX_P (regno); -+#endif -+} -+ -+/* Wrapper around ok_for_index_p_1, for use after register allocation is -+ complete. Arguments as for the called function. */ -+ -+static inline bool -+regno_ok_for_index_p (unsigned regno, enum machine_mode mode) -+{ -+ if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0) -+ regno = reg_renumber[regno]; -+ -+ return ok_for_index_p_1 (regno, mode); -+} ---- a/gcc/calls.c -+++ b/gcc/calls.c -@@ -3803,7 +3803,7 @@ - cse'ing of library calls could delete a call and leave the pop. */ - NO_DEFER_POP; - valreg = (mem_value == 0 && outmode != VOIDmode -- ? hard_libcall_value (outmode) : NULL_RTX); -+ ? hard_libcall_value (outmode, orgfun) : NULL_RTX); - - /* Stack must be properly aligned now. */ - gcc_assert (!(stack_pointer_delta -@@ -4048,8 +4048,17 @@ - /* We need to make a save area. */ - unsigned int size = arg->locate.size.constant * BITS_PER_UNIT; - enum machine_mode save_mode = mode_for_size (size, MODE_INT, 1); -- rtx adr = memory_address (save_mode, XEXP (arg->stack_slot, 0)); -- rtx stack_area = gen_rtx_MEM (save_mode, adr); -+ rtx adr; -+ rtx stack_area; -+ -+ /* We can only use save_mode if the arg is sufficiently -+ aligned. */ -+ if (STRICT_ALIGNMENT -+ && GET_MODE_ALIGNMENT (save_mode) > arg->locate.boundary) -+ save_mode = BLKmode; -+ -+ adr = memory_address (save_mode, XEXP (arg->stack_slot, 0)); -+ stack_area = gen_rtx_MEM (save_mode, adr); - - if (save_mode == BLKmode) - { ---- a/gcc/c-common.c -+++ b/gcc/c-common.c -@@ -33,7 +33,6 @@ - #include "varray.h" - #include "expr.h" - #include "c-common.h" --#include "diagnostic.h" - #include "tm_p.h" - #include "obstack.h" - #include "cpplib.h" -@@ -42,6 +41,7 @@ - #include "tree-inline.h" - #include "c-tree.h" - #include "toplev.h" -+#include "diagnostic.h" - #include "tree-iterator.h" - #include "hashtab.h" - #include "tree-mudflap.h" -@@ -497,6 +497,10 @@ - This is a count, since unevaluated expressions can nest. */ - int skip_evaluation; - -+/* Whether lexing has been completed, so subsequent preprocessor -+ errors should use the compiler's input_location. */ -+bool done_lexing = false; -+ - /* Information about how a function name is generated. */ - struct fname_var_t - { -@@ -7522,6 +7526,68 @@ - #undef catenate_messages - } - -+/* Callback from cpp_error for PFILE to print diagnostics from the -+ preprocessor. The diagnostic is of type LEVEL, at location -+ LOCATION unless this is after lexing and the compiler's location -+ should be used instead, with column number possibly overridden by -+ COLUMN_OVERRIDE if not zero; MSG is the translated message and AP -+ the arguments. Returns true if a diagnostic was emitted, false -+ otherwise. */ -+ -+bool -+c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, -+ location_t location, unsigned int column_override, -+ const char *msg, va_list *ap) -+{ -+ diagnostic_info diagnostic; -+ diagnostic_t dlevel; -+ int save_warn_system_headers = warn_system_headers; -+ bool ret; -+ -+ switch (level) -+ { -+ case CPP_DL_WARNING_SYSHDR: -+ if (flag_no_output) -+ return false; -+ warn_system_headers = 1; -+ /* Fall through. */ -+ case CPP_DL_WARNING: -+ if (flag_no_output) -+ return false; -+ dlevel = DK_WARNING; -+ break; -+ case CPP_DL_PEDWARN: -+ if (flag_no_output && !flag_pedantic_errors) -+ return false; -+ dlevel = DK_PEDWARN; -+ break; -+ case CPP_DL_ERROR: -+ dlevel = DK_ERROR; -+ break; -+ case CPP_DL_ICE: -+ dlevel = DK_ICE; -+ break; -+ case CPP_DL_NOTE: -+ dlevel = DK_NOTE; -+ break; -+ case CPP_DL_FATAL: -+ dlevel = DK_FATAL; -+ break; -+ default: -+ gcc_unreachable (); -+ } -+ if (done_lexing) -+ location = input_location; -+ diagnostic_set_info_translated (&diagnostic, msg, ap, -+ location, dlevel); -+ if (column_override) -+ diagnostic_override_column (&diagnostic, column_override); -+ ret = report_diagnostic (&diagnostic); -+ if (level == CPP_DL_WARNING_SYSHDR) -+ warn_system_headers = save_warn_system_headers; -+ return ret; -+} -+ - /* Walk a gimplified function and warn for functions whose return value is - ignored and attribute((warn_unused_result)) is set. This is done before - inlining, so we don't have to worry about that. */ ---- a/gcc/c-common.h -+++ b/gcc/c-common.h -@@ -658,6 +658,11 @@ - - extern int skip_evaluation; - -+/* Whether lexing has been completed, so subsequent preprocessor -+ errors should use the compiler's input_location. */ -+ -+extern bool done_lexing; -+ - /* C types are partitioned into three subsets: object, function, and - incomplete types. */ - #define C_TYPE_OBJECT_P(type) \ ---- a/gcc/c-convert.c -+++ b/gcc/c-convert.c -@@ -70,6 +70,7 @@ - tree e = expr; - enum tree_code code = TREE_CODE (type); - const char *invalid_conv_diag; -+ tree ret; - - if (type == error_mark_node - || expr == error_mark_node -@@ -85,6 +86,9 @@ - - if (type == TREE_TYPE (expr)) - return expr; -+ ret = targetm.convert_to_type (type, expr); -+ if (ret) -+ return ret; - - if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))) - return fold_convert (type, expr); ---- a/gcc/c-decl.c -+++ b/gcc/c-decl.c -@@ -3994,6 +3994,7 @@ - bool bitfield = width != NULL; - tree element_type; - struct c_arg_info *arg_info = 0; -+ const char *errmsg; - - if (decl_context == FUNCDEF) - funcdef_flag = true, decl_context = NORMAL; -@@ -4531,6 +4532,12 @@ - error ("%qs declared as function returning an array", name); - type = integer_type_node; - } -+ errmsg = targetm.invalid_return_type (type); -+ if (errmsg) -+ { -+ error (errmsg); -+ type = integer_type_node; -+ } - - /* Construct the function type and go to the next - inner layer of declarator. */ -@@ -5044,6 +5051,7 @@ - { - tree parm, type, typelt; - unsigned int parmno; -+ const char *errmsg; - - /* If there is a parameter of incomplete type in a definition, - this is an error. In a declaration this is valid, and a -@@ -5087,6 +5095,14 @@ - } - } - -+ errmsg = targetm.invalid_parameter_type (type); -+ if (errmsg) -+ { -+ error (errmsg); -+ TREE_VALUE (typelt) = error_mark_node; -+ TREE_TYPE (parm) = error_mark_node; -+ } -+ - if (DECL_NAME (parm) && TREE_USED (parm)) - warn_if_shadowing (parm); - } -@@ -8071,7 +8087,7 @@ - - /* Don't waste time on further processing if -fsyntax-only or we've - encountered errors. */ -- if (flag_syntax_only || errorcount || sorrycount || cpp_errors (parse_in)) -+ if (flag_syntax_only || errorcount || sorrycount) - return; - - /* Close the external scope. */ ---- a/gcc/cfgexpand.c -+++ b/gcc/cfgexpand.c -@@ -488,7 +488,8 @@ - { - unsigned int align; - -- align = LOCAL_DECL_ALIGNMENT (decl); -+ align = alignment_for_aligned_arrays (TREE_TYPE (decl), -+ LOCAL_DECL_ALIGNMENT (decl)); - - if (align > MAX_SUPPORTED_STACK_ALIGNMENT) - align = MAX_SUPPORTED_STACK_ALIGNMENT; ---- a/gcc/cgraph.c -+++ b/gcc/cgraph.c -@@ -475,9 +475,11 @@ - if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL) - { - node->origin = cgraph_node (DECL_CONTEXT (decl)); -+ node->origin->ever_was_nested = 1; - node->next_nested = node->origin->nested; - node->origin->nested = node; - node->master_clone = node; -+ node->ever_was_nested = 1; - } - if (assembler_name_hash) - { ---- a/gcc/cgraph.h -+++ b/gcc/cgraph.h -@@ -185,6 +185,8 @@ - unsigned output : 1; - /* Set for aliases once they got through assemble_alias. */ - unsigned alias : 1; -+ /* Set if the function is a nested function or has nested functions. */ -+ unsigned ever_was_nested : 1; - - /* In non-unit-at-a-time mode the function body of inline candidates is saved - into clone before compiling so the function in original form can be ---- a/gcc/common.opt -+++ b/gcc/common.opt -@@ -153,6 +153,10 @@ - Common Var(warn_padded) Warning - Warn when padding is required to align structure members - -+Wpoison-system-directories -+Common Var(flag_poison_system_directories) Init(1) -+Warn for -I and -L options using system directories if cross compiling -+ - Wshadow - Common Var(warn_shadow) Warning - Warn when one local variable shadows another -@@ -270,6 +274,12 @@ - fabi-version= - Common Joined UInteger Var(flag_abi_version) Init(2) - -+falign-arrays -+Target Report Var(flag_align_arrays) -+Set the minimum alignment for array variables to be the largest power -+of two less than or equal to their total storage size, or the biggest -+alignment used on the machine, whichever is smaller. -+ - falign-functions - Common Report Var(align_functions,0) Optimization UInteger - Align the start of functions -@@ -467,6 +477,10 @@ - Common Report Var(flag_early_inlining) Init(1) Optimization - Perform early inlining - -+feglibc= -+Common Report Joined Undocumented -+EGLIBC configuration specifier, serves multilib purposes. -+ - feliminate-dwarf2-dups - Common Report Var(flag_eliminate_dwarf2_dups) - Perform DWARF2 duplicate elimination -@@ -895,6 +909,10 @@ - Common Report Var(flag_profile_values) - Insert code to profile values of expressions - -+fpromote-loop-indices -+Common Report Var(flag_promote_loop_indices) Optimization -+Promote loop indices to word-sized indices when safe -+ - frandom-seed - Common - -@@ -1227,6 +1245,15 @@ - Common Report Var(flag_tree_pre) Optimization - Enable SSA-PRE optimization on trees - -+ftree-pre-partial-partial -+Common Report Var(flag_tree_pre_partial_partial) Optimization -+In SSA-PRE optimization on trees, enable partial-partial redundancy elimination. -+ -+ftree-pre-partial-partial-obliviously -+Common Report Var(flag_tree_pre_partial_partial_obliviously) Optimization -+In SSA-PRE optimization on trees, enable partial-partial redundancy -+elimination without regard for the cost of the inserted phi nodes. -+ - ftree-reassoc - Common Report Var(flag_tree_reassoc) Init(1) Optimization - Enable reassociation on tree level ---- a/gcc/config/arm/arm.c -+++ b/gcc/config/arm/arm.c -@@ -43,6 +43,7 @@ - #include "optabs.h" - #include "toplev.h" - #include "recog.h" -+#include "cgraph.h" - #include "ggc.h" - #include "except.h" - #include "c-pragma.h" -@@ -53,6 +54,8 @@ - #include "debug.h" - #include "langhooks.h" - #include "df.h" -+#include "intl.h" -+#include "params.h" - - /* Forward definitions of types. */ - typedef struct minipool_node Mnode; -@@ -110,6 +113,7 @@ - static unsigned long arm_isr_value (tree); - static unsigned long arm_compute_func_type (void); - static tree arm_handle_fndecl_attribute (tree *, tree, tree, int, bool *); -+static tree arm_handle_pcs_attribute (tree *, tree, tree, int, bool *); - static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *); - #if TARGET_DLLIMPORT_DECL_ATTRIBUTES - static tree arm_handle_notshared_attribute (tree *, tree, tree, int, bool *); -@@ -123,6 +127,10 @@ - static int count_insns_for_constant (HOST_WIDE_INT, int); - static int arm_get_strip_length (int); - static bool arm_function_ok_for_sibcall (tree, tree); -+static bool arm_return_in_memory (const_tree, const_tree); -+static rtx arm_function_value (const_tree, const_tree, bool); -+static rtx arm_libcall_value (enum machine_mode, rtx); -+ - static void arm_internal_label (FILE *, const char *, unsigned long); - static void arm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, - tree); -@@ -148,6 +156,9 @@ - static rtx emit_set_insn (rtx, rtx); - static int arm_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, - tree, bool); -+static rtx aapcs_allocate_return_reg (enum machine_mode, const_tree, -+ const_tree); -+static int aapcs_select_return_coproc (const_tree, const_tree); - - #ifdef OBJECT_FORMAT_ELF - static void arm_elf_asm_constructor (rtx, int) ATTRIBUTE_UNUSED; -@@ -175,6 +186,7 @@ - static bool arm_output_ttype (rtx); - #endif - static void arm_dwarf_handle_frame_unspec (const char *, rtx, int); -+static rtx arm_dwarf_register_span(rtx); - - static tree arm_cxx_guard_type (void); - static bool arm_cxx_guard_mask_bit (void); -@@ -197,6 +209,15 @@ - static int arm_issue_rate (void); - static void arm_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED; - static bool arm_allocate_stack_slots_for_args (void); -+static bool arm_warn_func_result (void); -+static int arm_multipass_dfa_lookahead (void); -+static const char *arm_invalid_parameter_type (const_tree t); -+static const char *arm_invalid_return_type (const_tree t); -+static tree arm_promoted_type (const_tree t); -+static tree arm_convert_to_type (tree type, tree expr); -+static bool arm_scalar_mode_supported_p (enum machine_mode); -+static int arm_vector_min_alignment (const_tree type); -+static bool arm_vector_always_misalign(const_tree); - - - /* Initialize the GCC target structure. */ -@@ -256,6 +277,12 @@ - #undef TARGET_FUNCTION_OK_FOR_SIBCALL - #define TARGET_FUNCTION_OK_FOR_SIBCALL arm_function_ok_for_sibcall - -+#undef TARGET_FUNCTION_VALUE -+#define TARGET_FUNCTION_VALUE arm_function_value -+ -+#undef TARGET_LIBCALL_VALUE -+#define TARGET_LIBCALL_VALUE arm_libcall_value -+ - #undef TARGET_ASM_OUTPUT_MI_THUNK - #define TARGET_ASM_OUTPUT_MI_THUNK arm_output_mi_thunk - #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK -@@ -299,6 +326,9 @@ - #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS - #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS arm_allocate_stack_slots_for_args - -+#undef TARGET_WARN_FUNC_RESULT -+#define TARGET_WARN_FUNC_RESULT arm_warn_func_result -+ - #undef TARGET_DEFAULT_SHORT_ENUMS - #define TARGET_DEFAULT_SHORT_ENUMS arm_default_short_enums - -@@ -353,6 +383,9 @@ - #undef TARGET_ASM_TTYPE - #define TARGET_ASM_TTYPE arm_output_ttype - -+#undef TARGET_CXX_TTYPE_REF_ENCODE -+#define TARGET_CXX_TTYPE_REF_ENCODE hook_cxx_ttype_ref_in_bit0 -+ - #undef TARGET_ARM_EABI_UNWINDER - #define TARGET_ARM_EABI_UNWINDER true - #endif /* TARGET_UNWIND_INFO */ -@@ -360,6 +393,9 @@ - #undef TARGET_DWARF_HANDLE_FRAME_UNSPEC - #define TARGET_DWARF_HANDLE_FRAME_UNSPEC arm_dwarf_handle_frame_unspec - -+#undef TARGET_DWARF_REGISTER_SPAN -+#define TARGET_DWARF_REGISTER_SPAN arm_dwarf_register_span -+ - #undef TARGET_CANNOT_COPY_INSN_P - #define TARGET_CANNOT_COPY_INSN_P arm_cannot_copy_insn_p - -@@ -398,6 +434,30 @@ - #define TARGET_ASM_OUTPUT_DWARF_DTPREL arm_output_dwarf_dtprel - #endif - -+#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD -+#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD arm_multipass_dfa_lookahead -+ -+#undef TARGET_INVALID_PARAMETER_TYPE -+#define TARGET_INVALID_PARAMETER_TYPE arm_invalid_parameter_type -+ -+#undef TARGET_INVALID_RETURN_TYPE -+#define TARGET_INVALID_RETURN_TYPE arm_invalid_return_type -+ -+#undef TARGET_PROMOTED_TYPE -+#define TARGET_PROMOTED_TYPE arm_promoted_type -+ -+#undef TARGET_CONVERT_TO_TYPE -+#define TARGET_CONVERT_TO_TYPE arm_convert_to_type -+ -+#undef TARGET_SCALAR_MODE_SUPPORTED_P -+#define TARGET_SCALAR_MODE_SUPPORTED_P arm_scalar_mode_supported_p -+ -+#undef TARGET_VECTOR_MIN_ALIGNMENT -+#define TARGET_VECTOR_MIN_ALIGNMENT arm_vector_min_alignment -+ -+#undef TARGET_VECTOR_ALWAYS_MISALIGN -+#define TARGET_VECTOR_ALWAYS_MISALIGN arm_vector_always_misalign -+ - struct gcc_target targetm = TARGET_INITIALIZER; - - /* Obstack for minipool constant handling. */ -@@ -423,18 +483,18 @@ - /* The default processor used if not overridden by commandline. */ - static enum processor_type arm_default_cpu = arm_none; - --/* Which floating point model to use. */ --enum arm_fp_model arm_fp_model; -- --/* Which floating point hardware is available. */ --enum fputype arm_fpu_arch; -- - /* Which floating point hardware to schedule for. */ --enum fputype arm_fpu_tune; -+int arm_fpu_attr; -+ -+/* Which floating popint hardware to use. */ -+const struct arm_fpu_desc *arm_fpu_desc; - - /* Whether to use floating point hardware. */ - enum float_abi_type arm_float_abi; - -+/* Which __fp16 format to use. */ -+enum arm_fp16_format_type arm_fp16_format; -+ - /* Which ABI to use. */ - enum arm_abi_type arm_abi; - -@@ -473,9 +533,19 @@ - #define FL_DIV (1 << 18) /* Hardware divide. */ - #define FL_VFPV3 (1 << 19) /* Vector Floating Point V3. */ - #define FL_NEON (1 << 20) /* Neon instructions. */ -+#define FL_MARVELL_F (1 << 21) /* Marvell Feroceon. */ -+#define FL_ARCH7EM (1 << 22) /* Instructions present in ARMv7E-M. */ - - #define FL_IWMMXT (1 << 29) /* XScale v2 or "Intel Wireless MMX technology". */ - -+/* Some flags are ignored when comparing -mcpu and -march: -+ FL_MARVELL_F so that -mcpu=marvell-f -march=v5te works. -+ FL_LDSCHED and FL_WBUF only effect tuning, -+ FL_CO_PROC, FL_VFPV2, FL_VFPV3 and FL_NEON because FP -+ coprocessors are handled separately. */ -+#define FL_COMPAT (FL_MARVELL_F | FL_LDSCHED | FL_WBUF | FL_CO_PROC | \ -+ FL_VFPV2 | FL_VFPV3 | FL_NEON) -+ - #define FL_FOR_ARCH2 FL_NOTM - #define FL_FOR_ARCH3 (FL_FOR_ARCH2 | FL_MODE32) - #define FL_FOR_ARCH3M (FL_FOR_ARCH3 | FL_ARCH3M) -@@ -497,6 +567,7 @@ - #define FL_FOR_ARCH7A (FL_FOR_ARCH7 | FL_NOTM) - #define FL_FOR_ARCH7R (FL_FOR_ARCH7A | FL_DIV) - #define FL_FOR_ARCH7M (FL_FOR_ARCH7 | FL_DIV) -+#define FL_FOR_ARCH7EM (FL_FOR_ARCH7M | FL_ARCH7EM) - - /* The bits in this mask specify which - instructions we are allowed to generate. */ -@@ -533,6 +604,9 @@ - /* Nonzero if instructions not present in the 'M' profile can be used. */ - int arm_arch_notm = 0; - -+/* Nonzero if instructions present in ARMv7E-M can be used. */ -+int arm_arch7em = 0; -+ - /* Nonzero if this chip can benefit from load scheduling. */ - int arm_ld_sched = 0; - -@@ -551,6 +625,9 @@ - /* Nonzero if tuning for XScale */ - int arm_tune_xscale = 0; - -+/* Nonzero if tuning for Marvell Feroceon. */ -+int arm_tune_marvell_f = 0; -+ - /* Nonzero if we want to tune for stores that access the write-buffer. - This typically means an ARM6 or ARM7 with MMU or MPU. */ - int arm_tune_wbuf = 0; -@@ -561,6 +638,9 @@ - /* Nonzero if generating Thumb instructions. */ - int thumb_code = 0; - -+/* Nonzero if generating code for Janus2. */ -+int janus2_code = 0; -+ - /* Nonzero if we should define __THUMB_INTERWORK__ in the - preprocessor. - XXX This is a bit of a hack, it's intended to help work around -@@ -593,6 +673,8 @@ - /* The maximum number of insns to be used when loading a constant. */ - static int arm_constant_limit = 3; - -+static enum arm_pcs arm_pcs_default; -+ - /* For an explanation of these variables, see final_prescan_insn below. */ - int arm_ccfsm_state; - /* arm_current_cc is also used for Thumb-2 cond_exec blocks. */ -@@ -673,9 +755,11 @@ - {"armv7-a", cortexa8, "7A", FL_CO_PROC | FL_FOR_ARCH7A, NULL}, - {"armv7-r", cortexr4, "7R", FL_CO_PROC | FL_FOR_ARCH7R, NULL}, - {"armv7-m", cortexm3, "7M", FL_CO_PROC | FL_FOR_ARCH7M, NULL}, -+ {"armv7e-m", cortexm3, "7EM", FL_CO_PROC | FL_FOR_ARCH7EM, NULL}, - {"ep9312", ep9312, "4T", FL_LDSCHED | FL_CIRRUS | FL_FOR_ARCH4, NULL}, - {"iwmmxt", iwmmxt, "5TE", FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT , NULL}, - {"iwmmxt2", iwmmxt2, "5TE", FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT , NULL}, -+ {"marvell-f", marvell_f, "5TE", FL_CO_PROC | FL_FOR_ARCH5TE | FL_MARVELL_F, NULL}, - {NULL, arm_none, NULL, 0 , NULL} - }; - -@@ -705,49 +789,34 @@ - - /* The name of the preprocessor macro to define for this architecture. */ - --char arm_arch_name[] = "__ARM_ARCH_0UNK__"; -- --struct fpu_desc --{ -- const char * name; -- enum fputype fpu; --}; -- -+#define ARM_ARCH_NAME_SIZE 25 -+char arm_arch_name[ARM_ARCH_NAME_SIZE] = "__ARM_ARCH_0UNK__"; - - /* Available values for -mfpu=. */ - --static const struct fpu_desc all_fpus[] = -+static const struct arm_fpu_desc all_fpus[] = - { -- {"fpa", FPUTYPE_FPA}, -- {"fpe2", FPUTYPE_FPA_EMU2}, -- {"fpe3", FPUTYPE_FPA_EMU2}, -- {"maverick", FPUTYPE_MAVERICK}, -- {"vfp", FPUTYPE_VFP}, -- {"vfp3", FPUTYPE_VFP3}, -- {"vfpv3", FPUTYPE_VFP3}, -- {"vfpv3-d16", FPUTYPE_VFP3D16}, -- {"neon", FPUTYPE_NEON} -+ {"fpa", ARM_FP_MODEL_FPA, 0, 0, false, false}, -+ {"fpe2", ARM_FP_MODEL_FPA, 2, 0, false, false}, -+ {"fpe3", ARM_FP_MODEL_FPA, 3, 0, false, false}, -+ {"maverick", ARM_FP_MODEL_MAVERICK, 0, 0, false, false}, -+ {"vfp", ARM_FP_MODEL_VFP, 2, VFP_REG_D16, false, false}, -+ {"vfpv3", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, false, false}, -+ {"vfpv3-fp16", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, false, true }, -+ {"vfpv3-d16", ARM_FP_MODEL_VFP, 3, VFP_REG_D16, false, false}, -+ {"vfpv3xd", ARM_FP_MODEL_VFP, 3, VFP_REG_SINGLE, false, false}, -+ {"vfpv3xd-fp16", ARM_FP_MODEL_VFP, 3, VFP_REG_SINGLE, false, true }, -+ {"vfpv3-d16-fp16", ARM_FP_MODEL_VFP, 3, VFP_REG_D16, false, true }, -+ {"neon", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, true , false}, -+ {"neon-fp16", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, true , true }, -+ {"vfpv4", ARM_FP_MODEL_VFP, 4, VFP_REG_D32, false, true }, -+ {"vfpv4-d16", ARM_FP_MODEL_VFP, 4, VFP_REG_D16, false, true }, -+ {"fpv4-sp-d16", ARM_FP_MODEL_VFP, 4, VFP_REG_SINGLE, false, true }, -+ {"neon-vfpv4", ARM_FP_MODEL_VFP, 4, VFP_REG_D32, true , true }, -+ /* Compatibility aliases. */ -+ {"vfp3", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, false, false}, - }; - -- --/* Floating point models used by the different hardware. -- See fputype in arm.h. */ -- --static const enum fputype fp_model_for_fpu[] = --{ -- /* No FP hardware. */ -- ARM_FP_MODEL_UNKNOWN, /* FPUTYPE_NONE */ -- ARM_FP_MODEL_FPA, /* FPUTYPE_FPA */ -- ARM_FP_MODEL_FPA, /* FPUTYPE_FPA_EMU2 */ -- ARM_FP_MODEL_FPA, /* FPUTYPE_FPA_EMU3 */ -- ARM_FP_MODEL_MAVERICK, /* FPUTYPE_MAVERICK */ -- ARM_FP_MODEL_VFP, /* FPUTYPE_VFP */ -- ARM_FP_MODEL_VFP, /* FPUTYPE_VFP3D16 */ -- ARM_FP_MODEL_VFP, /* FPUTYPE_VFP3 */ -- ARM_FP_MODEL_VFP /* FPUTYPE_NEON */ --}; -- -- - struct float_abi - { - const char * name; -@@ -765,6 +834,23 @@ - }; - - -+struct fp16_format -+{ -+ const char *name; -+ enum arm_fp16_format_type fp16_format_type; -+}; -+ -+ -+/* Available values for -mfp16-format=. */ -+ -+static const struct fp16_format all_fp16_formats[] = -+{ -+ {"none", ARM_FP16_FORMAT_NONE}, -+ {"ieee", ARM_FP16_FORMAT_IEEE}, -+ {"alternative", ARM_FP16_FORMAT_ALTERNATIVE} -+}; -+ -+ - struct abi_name - { - const char *name; -@@ -922,6 +1008,44 @@ - set_optab_libfunc (umod_optab, DImode, NULL); - set_optab_libfunc (smod_optab, SImode, NULL); - set_optab_libfunc (umod_optab, SImode, NULL); -+ -+ /* Half-precision float operations. The compiler handles all operations -+ with NULL libfuncs by converting the SFmode. */ -+ switch (arm_fp16_format) -+ { -+ case ARM_FP16_FORMAT_IEEE: -+ case ARM_FP16_FORMAT_ALTERNATIVE: -+ -+ /* Conversions. */ -+ set_conv_libfunc (trunc_optab, HFmode, SFmode, -+ (arm_fp16_format == ARM_FP16_FORMAT_IEEE -+ ? "__gnu_f2h_ieee" -+ : "__gnu_f2h_alternative")); -+ set_conv_libfunc (sext_optab, SFmode, HFmode, -+ (arm_fp16_format == ARM_FP16_FORMAT_IEEE -+ ? "__gnu_h2f_ieee" -+ : "__gnu_h2f_alternative")); -+ -+ /* Arithmetic. */ -+ set_optab_libfunc (add_optab, HFmode, NULL); -+ set_optab_libfunc (sdiv_optab, HFmode, NULL); -+ set_optab_libfunc (smul_optab, HFmode, NULL); -+ set_optab_libfunc (neg_optab, HFmode, NULL); -+ set_optab_libfunc (sub_optab, HFmode, NULL); -+ -+ /* Comparisons. */ -+ set_optab_libfunc (eq_optab, HFmode, NULL); -+ set_optab_libfunc (ne_optab, HFmode, NULL); -+ set_optab_libfunc (lt_optab, HFmode, NULL); -+ set_optab_libfunc (le_optab, HFmode, NULL); -+ set_optab_libfunc (ge_optab, HFmode, NULL); -+ set_optab_libfunc (gt_optab, HFmode, NULL); -+ set_optab_libfunc (unord_optab, HFmode, NULL); -+ break; -+ -+ default: -+ break; -+ } - } - - /* On AAPCS systems, this is the "struct __va_list". */ -@@ -1135,6 +1259,7 @@ - arm_override_options (void) - { - unsigned i; -+ int len; - enum processor_type target_arch_cpu = arm_none; - enum processor_type selected_cpu = arm_none; - -@@ -1152,7 +1277,11 @@ - { - /* Set the architecture define. */ - if (i != ARM_OPT_SET_TUNE) -- sprintf (arm_arch_name, "__ARM_ARCH_%s__", sel->arch); -+ { -+ len = snprintf (arm_arch_name, ARM_ARCH_NAME_SIZE, -+ "__ARM_ARCH_%s__", sel->arch); -+ gcc_assert (len < ARM_ARCH_NAME_SIZE); -+ } - - /* Determine the processor core for which we should - tune code-generation. */ -@@ -1178,8 +1307,8 @@ - make sure that they are compatible. We only generate - a warning though, and we prefer the CPU over the - architecture. */ -- if (insn_flags != 0 && (insn_flags ^ sel->flags)) -- warning (0, "switch -mcpu=%s conflicts with -march= switch", -+ if (insn_flags != 0 && ((insn_flags ^ sel->flags) & ~FL_COMPAT)) -+ warning (0, "switch -mcpu=%s conflicts with -march= switch, assuming CPU feature set", - ptr->string); - - insn_flags = sel->flags; -@@ -1279,7 +1408,11 @@ - - insn_flags = sel->flags; - } -- sprintf (arm_arch_name, "__ARM_ARCH_%s__", sel->arch); -+ -+ len = snprintf (arm_arch_name, ARM_ARCH_NAME_SIZE, -+ "__ARM_ARCH_%s__", sel->arch); -+ gcc_assert (len < ARM_ARCH_NAME_SIZE); -+ - arm_default_cpu = (enum processor_type) (sel - all_cores); - if (arm_tune == arm_none) - arm_tune = arm_default_cpu; -@@ -1289,8 +1422,35 @@ - chosen. */ - gcc_assert (arm_tune != arm_none); - -+ if (arm_tune == cortexa8 && optimize >= 3) -+ { -+ /* These alignments were experimentally determined to improve SPECint -+ performance on SPECCPU 2000. */ -+ if (align_functions <= 0) -+ align_functions = 16; -+ if (align_jumps <= 0) -+ align_jumps = 16; -+ } -+ - tune_flags = all_cores[(int)arm_tune].flags; - -+ if (target_fp16_format_name) -+ { -+ for (i = 0; i < ARRAY_SIZE (all_fp16_formats); i++) -+ { -+ if (streq (all_fp16_formats[i].name, target_fp16_format_name)) -+ { -+ arm_fp16_format = all_fp16_formats[i].fp16_format_type; -+ break; -+ } -+ } -+ if (i == ARRAY_SIZE (all_fp16_formats)) -+ error ("invalid __fp16 format option: -mfp16-format=%s", -+ target_fp16_format_name); -+ } -+ else -+ arm_fp16_format = ARM_FP16_FORMAT_NONE; -+ - if (target_abi_name) - { - for (i = 0; i < ARRAY_SIZE (arm_all_abis); i++) -@@ -1383,6 +1543,7 @@ - arm_arch6 = (insn_flags & FL_ARCH6) != 0; - arm_arch6k = (insn_flags & FL_ARCH6K) != 0; - arm_arch_notm = (insn_flags & FL_NOTM) != 0; -+ arm_arch7em = (insn_flags & FL_ARCH7EM) != 0; - arm_arch_thumb2 = (insn_flags & FL_THUMB2) != 0; - arm_arch_xscale = (insn_flags & FL_XSCALE) != 0; - arm_arch_cirrus = (insn_flags & FL_CIRRUS) != 0; -@@ -1390,12 +1551,25 @@ - arm_ld_sched = (tune_flags & FL_LDSCHED) != 0; - arm_tune_strongarm = (tune_flags & FL_STRONG) != 0; - thumb_code = (TARGET_ARM == 0); -+ janus2_code = (TARGET_FIX_JANUS != 0); -+ if (janus2_code && TARGET_THUMB2) -+ error ("janus2 fix is not applicable when targeting a thumb2 core"); - arm_tune_wbuf = (tune_flags & FL_WBUF) != 0; - arm_tune_xscale = (tune_flags & FL_XSCALE) != 0; -+ arm_tune_marvell_f = (tune_flags & FL_MARVELL_F) != 0; - arm_arch_iwmmxt = (insn_flags & FL_IWMMXT) != 0; -- arm_arch_hwdiv = (insn_flags & FL_DIV) != 0; - arm_tune_cortex_a9 = (arm_tune == cortexa9) != 0; - -+ /* Hardware integer division is supported by some variants of the ARM -+ architecture in Thumb-2 mode. In addition some (but not all) Marvell -+ CPUs support their own hardware integer division instructions. -+ The assembler will pick the correct encoding. */ -+ if (TARGET_MARVELL_DIV && (insn_flags & FL_MARVELL_F) == 0) -+ error ("-mmarvell-div is only supported when targeting a Marvell core"); -+ -+ arm_arch_hwdiv = (TARGET_ARM && TARGET_MARVELL_DIV) -+ || (TARGET_THUMB2 && (insn_flags & FL_DIV) != 0); -+ - /* If we are not using the default (ARM mode) section anchor offset - ranges, then set the correct ranges now. */ - if (TARGET_THUMB1) -@@ -1434,7 +1608,6 @@ - if (TARGET_IWMMXT_ABI && !TARGET_IWMMXT) - error ("iwmmxt abi requires an iwmmxt capable cpu"); - -- arm_fp_model = ARM_FP_MODEL_UNKNOWN; - if (target_fpu_name == NULL && target_fpe_name != NULL) - { - if (streq (target_fpe_name, "2")) -@@ -1445,46 +1618,52 @@ - error ("invalid floating point emulation option: -mfpe=%s", - target_fpe_name); - } -- if (target_fpu_name != NULL) -- { -- /* The user specified a FPU. */ -- for (i = 0; i < ARRAY_SIZE (all_fpus); i++) -- { -- if (streq (all_fpus[i].name, target_fpu_name)) -- { -- arm_fpu_arch = all_fpus[i].fpu; -- arm_fpu_tune = arm_fpu_arch; -- arm_fp_model = fp_model_for_fpu[arm_fpu_arch]; -- break; -- } -- } -- if (arm_fp_model == ARM_FP_MODEL_UNKNOWN) -- error ("invalid floating point option: -mfpu=%s", target_fpu_name); -- } -- else -+ -+ if (target_fpu_name == NULL) - { - #ifdef FPUTYPE_DEFAULT -- /* Use the default if it is specified for this platform. */ -- arm_fpu_arch = FPUTYPE_DEFAULT; -- arm_fpu_tune = FPUTYPE_DEFAULT; -+ target_fpu_name = FPUTYPE_DEFAULT; - #else -- /* Pick one based on CPU type. */ -- /* ??? Some targets assume FPA is the default. -- if ((insn_flags & FL_VFP) != 0) -- arm_fpu_arch = FPUTYPE_VFP; -- else -- */ - if (arm_arch_cirrus) -- arm_fpu_arch = FPUTYPE_MAVERICK; -+ target_fpu_name = "maverick"; - else -- arm_fpu_arch = FPUTYPE_FPA_EMU2; -+ target_fpu_name = "fpe2"; - #endif -- if (tune_flags & FL_CO_PROC && arm_fpu_arch == FPUTYPE_FPA_EMU2) -- arm_fpu_tune = FPUTYPE_FPA; -+ } -+ -+ arm_fpu_desc = NULL; -+ for (i = 0; i < ARRAY_SIZE (all_fpus); i++) -+ { -+ if (streq (all_fpus[i].name, target_fpu_name)) -+ { -+ arm_fpu_desc = &all_fpus[i]; -+ break; -+ } -+ } -+ if (!arm_fpu_desc) -+ error ("invalid floating point option: -mfpu=%s", target_fpu_name); -+ -+ switch (arm_fpu_desc->model) -+ { -+ case ARM_FP_MODEL_FPA: -+ if (arm_fpu_desc->rev == 2) -+ arm_fpu_attr = FPU_FPE2; -+ else if (arm_fpu_desc->rev == 3) -+ arm_fpu_attr = FPU_FPE3; - else -- arm_fpu_tune = arm_fpu_arch; -- arm_fp_model = fp_model_for_fpu[arm_fpu_arch]; -- gcc_assert (arm_fp_model != ARM_FP_MODEL_UNKNOWN); -+ arm_fpu_attr = FPU_FPA; -+ break; -+ -+ case ARM_FP_MODEL_MAVERICK: -+ arm_fpu_attr = FPU_MAVERICK; -+ break; -+ -+ case ARM_FP_MODEL_VFP: -+ arm_fpu_attr = FPU_VFP; -+ break; -+ -+ default: -+ gcc_unreachable(); - } - - if (target_float_abi_name != NULL) -@@ -1505,9 +1684,6 @@ - else - arm_float_abi = TARGET_DEFAULT_FLOAT_ABI; - -- if (arm_float_abi == ARM_FLOAT_ABI_HARD && TARGET_VFP) -- sorry ("-mfloat-abi=hard and VFP"); -- - /* FPA and iWMMXt are incompatible because the insn encodings overlap. - VFP and iWMMXt can theoretically coexist, but it's unlikely such silicon - will ever exist. GCC makes no attempt to support this combination. */ -@@ -1518,15 +1694,40 @@ - if (TARGET_THUMB2 && TARGET_IWMMXT) - sorry ("Thumb-2 iWMMXt"); - -+ /* __fp16 support currently assumes the core has ldrh. */ -+ if (!arm_arch4 && arm_fp16_format != ARM_FP16_FORMAT_NONE) -+ sorry ("__fp16 and no ldrh"); -+ - /* If soft-float is specified then don't use FPU. */ - if (TARGET_SOFT_FLOAT) -- arm_fpu_arch = FPUTYPE_NONE; -+ arm_fpu_attr = FPU_NONE; -+ -+ if (TARGET_AAPCS_BASED) -+ { -+ if (arm_abi == ARM_ABI_IWMMXT) -+ arm_pcs_default = ARM_PCS_AAPCS_IWMMXT; -+ else if (arm_float_abi == ARM_FLOAT_ABI_HARD -+ && TARGET_HARD_FLOAT -+ && TARGET_VFP) -+ arm_pcs_default = ARM_PCS_AAPCS_VFP; -+ else -+ arm_pcs_default = ARM_PCS_AAPCS; -+ } -+ else -+ { -+ if (arm_float_abi == ARM_FLOAT_ABI_HARD && TARGET_VFP) -+ sorry ("-mfloat-abi=hard and VFP"); -+ -+ if (arm_abi == ARM_ABI_APCS) -+ arm_pcs_default = ARM_PCS_APCS; -+ else -+ arm_pcs_default = ARM_PCS_ATPCS; -+ } - - /* For arm2/3 there is no need to do any scheduling if there is only - a floating point emulator, or we are doing software floating-point. */ - if ((TARGET_SOFT_FLOAT -- || arm_fpu_tune == FPUTYPE_FPA_EMU2 -- || arm_fpu_tune == FPUTYPE_FPA_EMU3) -+ || (TARGET_FPA && arm_fpu_desc->rev)) - && (tune_flags & FL_MODE32) == 0) - flag_schedule_insns = flag_schedule_insns_after_reload = 0; - -@@ -1616,8 +1817,7 @@ - fix_cm3_ldrd = 0; - } - -- /* ??? We might want scheduling for thumb2. */ -- if (TARGET_THUMB && flag_schedule_insns) -+ if (TARGET_THUMB1 && flag_schedule_insns) - { - /* Don't warn since it's on by default in -O2. */ - flag_schedule_insns = 0; -@@ -1653,6 +1853,36 @@ - - /* Register global variables with the garbage collector. */ - arm_add_gc_roots (); -+ -+ if (low_irq_latency && TARGET_THUMB) -+ { -+ warning (0, -+ "-low-irq-latency has no effect when compiling for the Thumb"); -+ low_irq_latency = 0; -+ } -+ -+ /* CSL LOCAL */ -+ /* Loop unrolling can be a substantial win. At -O2, limit to 2x -+ unrolling by default to prevent excessive code growth; at -O3, -+ limit to 4x unrolling by default. We know we are not optimizing -+ for size if this is set (see arm_optimization_options). */ -+ if (flag_unroll_loops == 2) -+ { -+ if (optimize == 2) -+ { -+ flag_unroll_loops = 1; -+ if (!PARAM_SET_P (PARAM_MAX_UNROLL_TIMES)) -+ set_param_value ("max-unroll-times", 2); -+ } -+ else if (optimize > 2) -+ { -+ flag_unroll_loops = 1; -+ if (!PARAM_SET_P (PARAM_MAX_UNROLL_TIMES)) -+ set_param_value ("max-unroll-times", 4); -+ } -+ else -+ flag_unroll_loops = 0; -+ } - } - - static void -@@ -1782,6 +2012,14 @@ - return !IS_NAKED (arm_current_func_type ()); - } - -+static bool -+arm_warn_func_result (void) -+{ -+ /* Naked functions are implemented entirely in assembly, including the -+ return sequence, so suppress warnings about this. */ -+ return !IS_NAKED (arm_current_func_type ()); -+} -+ - - /* Return 1 if it is possible to return using a single instruction. - If SIBLING is non-null, this is a test for a return before a sibling -@@ -2873,14 +3111,19 @@ - - /* Define how to find the value returned by a function. */ - --rtx --arm_function_value(const_tree type, const_tree func ATTRIBUTE_UNUSED) -+static rtx -+arm_function_value(const_tree type, const_tree func, -+ bool outgoing ATTRIBUTE_UNUSED) - { - enum machine_mode mode; - int unsignedp ATTRIBUTE_UNUSED; - rtx r ATTRIBUTE_UNUSED; - - mode = TYPE_MODE (type); -+ -+ if (TARGET_AAPCS_BASED) -+ return aapcs_allocate_return_reg (mode, type, func); -+ - /* Promote integer types. */ - if (INTEGRAL_TYPE_P (type)) - PROMOTE_FUNCTION_MODE (mode, unsignedp, type); -@@ -2897,7 +3140,36 @@ - } - } - -- return LIBCALL_VALUE(mode); -+ return LIBCALL_VALUE (mode); -+} -+ -+rtx -+arm_libcall_value (enum machine_mode mode, rtx libcall) -+{ -+ if (TARGET_AAPCS_BASED && arm_pcs_default != ARM_PCS_AAPCS -+ && GET_MODE_CLASS (mode) == MODE_FLOAT) -+ { -+ /* The following libcalls return their result in integer registers, -+ even though they return a floating point value. */ -+ if (rtx_equal_p (libcall, -+ convert_optab_libfunc (sfloat_optab, mode, SImode)) -+ || rtx_equal_p (libcall, -+ convert_optab_libfunc (ufloat_optab, mode, SImode)) -+ || rtx_equal_p (libcall, -+ convert_optab_libfunc (sfloat_optab, mode, DImode)) -+ || rtx_equal_p (libcall, -+ convert_optab_libfunc (ufloat_optab, mode, DImode)) -+ || rtx_equal_p (libcall, -+ convert_optab_libfunc (trunc_optab, HFmode, SFmode)) -+ || rtx_equal_p (libcall, -+ convert_optab_libfunc (sext_optab, SFmode, HFmode))) -+ return gen_rtx_REG (mode, ARG_REGISTER(1)); -+ -+ /* XXX There are other libcalls that return in integer registers, -+ but I think they are all handled by hard insns. */ -+ } -+ -+ return LIBCALL_VALUE (mode); - } - - /* Determine the amount of memory needed to store the possible return -@@ -2907,10 +3179,12 @@ - { - int size = 16; - -- if (TARGET_ARM) -+ if (TARGET_32BIT) - { - if (TARGET_HARD_FLOAT_ABI) - { -+ if (TARGET_VFP) -+ size += 32; - if (TARGET_FPA) - size += 12; - if (TARGET_MAVERICK) -@@ -2923,27 +3197,56 @@ - return size; - } - --/* Decide whether a type should be returned in memory (true) -- or in a register (false). This is called as the target hook -- TARGET_RETURN_IN_MEMORY. */ -+/* Decide whether TYPE should be returned in memory (true) -+ or in a register (false). FNTYPE is the type of the function making -+ the call. */ - static bool --arm_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) -+arm_return_in_memory (const_tree type, const_tree fntype) - { - HOST_WIDE_INT size; - -- size = int_size_in_bytes (type); -+ size = int_size_in_bytes (type); /* Negative if not fixed size. */ -+ -+ if (TARGET_AAPCS_BASED) -+ { -+ /* Simple, non-aggregate types (ie not including vectors and -+ complex) are always returned in a register (or registers). -+ We don't care about which register here, so we can short-cut -+ some of the detail. */ -+ if (!AGGREGATE_TYPE_P (type) -+ && TREE_CODE (type) != VECTOR_TYPE -+ && TREE_CODE (type) != COMPLEX_TYPE) -+ return false; -+ -+ /* Any return value that is no larger than one word can be -+ returned in r0. */ -+ if (((unsigned HOST_WIDE_INT) size) <= UNITS_PER_WORD) -+ return false; -+ -+ /* Check any available co-processors to see if they accept the -+ type as a register candidate (VFP, for example, can return -+ some aggregates in consecutive registers). These aren't -+ available if the call is variadic. */ -+ if (aapcs_select_return_coproc (type, fntype) >= 0) -+ return false; -+ -+ /* Vector values should be returned using ARM registers, not -+ memory (unless they're over 16 bytes, which will break since -+ we only have four call-clobbered registers to play with). */ -+ if (TREE_CODE (type) == VECTOR_TYPE) -+ return (size < 0 || size > (4 * UNITS_PER_WORD)); -+ -+ /* The rest go in memory. */ -+ return true; -+ } - -- /* Vector values should be returned using ARM registers, not memory (unless -- they're over 16 bytes, which will break since we only have four -- call-clobbered registers to play with). */ - if (TREE_CODE (type) == VECTOR_TYPE) - return (size < 0 || size > (4 * UNITS_PER_WORD)); - - if (!AGGREGATE_TYPE_P (type) && -- !(TARGET_AAPCS_BASED && TREE_CODE (type) == COMPLEX_TYPE)) -- /* All simple types are returned in registers. -- For AAPCS, complex types are treated the same as aggregates. */ -- return 0; -+ (TREE_CODE (type) != VECTOR_TYPE)) -+ /* All simple types are returned in registers. */ -+ return false; - - if (arm_abi != ARM_ABI_APCS) - { -@@ -2960,7 +3263,7 @@ - the aggregate is either huge or of variable size, and in either case - we will want to return it via memory and not in a register. */ - if (size < 0 || size > UNITS_PER_WORD) -- return 1; -+ return true; - - if (TREE_CODE (type) == RECORD_TYPE) - { -@@ -2980,18 +3283,18 @@ - continue; - - if (field == NULL) -- return 0; /* An empty structure. Allowed by an extension to ANSI C. */ -+ return false; /* An empty structure. Allowed by an extension to ANSI C. */ - - /* Check that the first field is valid for returning in a register. */ - - /* ... Floats are not allowed */ - if (FLOAT_TYPE_P (TREE_TYPE (field))) -- return 1; -+ return true; - - /* ... Aggregates that are not themselves valid for returning in - a register are not allowed. */ - if (arm_return_in_memory (TREE_TYPE (field), NULL_TREE)) -- return 1; -+ return true; - - /* Now check the remaining fields, if any. Only bitfields are allowed, - since they are not addressable. */ -@@ -3003,10 +3306,10 @@ - continue; - - if (!DECL_BIT_FIELD_TYPE (field)) -- return 1; -+ return true; - } - -- return 0; -+ return false; - } - - if (TREE_CODE (type) == UNION_TYPE) -@@ -3023,18 +3326,18 @@ - continue; - - if (FLOAT_TYPE_P (TREE_TYPE (field))) -- return 1; -+ return true; - - if (arm_return_in_memory (TREE_TYPE (field), NULL_TREE)) -- return 1; -+ return true; - } - -- return 0; -+ return false; - } - #endif /* not ARM_WINCE */ - - /* Return all other types in memory. */ -- return 1; -+ return true; - } - - /* Indicate whether or not words of a double are in big-endian order. */ -@@ -3059,14 +3362,780 @@ - return 1; - } - -+const struct pcs_attribute_arg -+{ -+ const char *arg; -+ enum arm_pcs value; -+} pcs_attribute_args[] = -+ { -+ {"aapcs", ARM_PCS_AAPCS}, -+ {"aapcs-vfp", ARM_PCS_AAPCS_VFP}, -+ {"aapcs-iwmmxt", ARM_PCS_AAPCS_IWMMXT}, -+ {"atpcs", ARM_PCS_ATPCS}, -+ {"apcs", ARM_PCS_APCS}, -+ {NULL, ARM_PCS_UNKNOWN} -+ }; -+ -+static enum arm_pcs -+arm_pcs_from_attribute (tree attr) -+{ -+ const struct pcs_attribute_arg *ptr; -+ const char *arg; -+ -+ /* Get the value of the argument. */ -+ if (TREE_VALUE (attr) == NULL_TREE -+ || TREE_CODE (TREE_VALUE (attr)) != STRING_CST) -+ return ARM_PCS_UNKNOWN; -+ -+ arg = TREE_STRING_POINTER (TREE_VALUE (attr)); -+ -+ /* Check it against the list of known arguments. */ -+ for (ptr = pcs_attribute_args; ptr->arg != NULL; ptr++) -+ if (streq (arg, ptr->arg)) -+ return ptr->value; -+ -+ /* An unrecognized interrupt type. */ -+ return ARM_PCS_UNKNOWN; -+} -+ -+/* Get the PCS variant to use for this call. TYPE is the function's type -+ specification, DECL is the specific declartion. DECL may be null if -+ the call could be indirect or if this is a library call. */ -+static enum arm_pcs -+arm_get_pcs_model (const_tree type, const_tree decl) -+{ -+ bool user_convention = false; -+ enum arm_pcs user_pcs = arm_pcs_default; -+ tree attr; -+ -+ gcc_assert (type); -+ -+ attr = lookup_attribute ("pcs", TYPE_ATTRIBUTES (type)); -+ if (attr) -+ { -+ user_pcs = arm_pcs_from_attribute (TREE_VALUE (attr)); -+ user_convention = true; -+ } -+ -+ if (TARGET_AAPCS_BASED) -+ { -+ /* Detect varargs functions. These always use the base rules -+ (no argument is ever a candidate for a co-processor -+ register). */ -+ bool base_rules = (TYPE_ARG_TYPES (type) != 0 -+ && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (type))) -+ != void_type_node)); -+ -+ if (user_convention) -+ { -+ if (user_pcs > ARM_PCS_AAPCS_LOCAL) -+ sorry ("Non-AAPCS derived PCS variant"); -+ else if (base_rules && user_pcs != ARM_PCS_AAPCS) -+ error ("Variadic functions must use the base AAPCS variant"); -+ } -+ -+ if (base_rules) -+ return ARM_PCS_AAPCS; -+ else if (user_convention) -+ return user_pcs; -+ else if (decl && flag_unit_at_a_time) -+ { -+ /* Local functions never leak outside this compilation unit, -+ so we are free to use whatever conventions are -+ appropriate. */ -+ /* FIXME: remove CONST_CAST_TREE when cgraph is constified. */ -+ struct cgraph_local_info *i = cgraph_local_info (CONST_CAST_TREE(decl)); -+ if (i && i->local) -+ return ARM_PCS_AAPCS_LOCAL; -+ } -+ } -+ else if (user_convention && user_pcs != arm_pcs_default) -+ sorry ("PCS variant"); -+ -+ /* For everything else we use the target's default. */ -+ return arm_pcs_default; -+} -+ -+ -+static void -+aapcs_vfp_cum_init (CUMULATIVE_ARGS *pcum ATTRIBUTE_UNUSED, -+ const_tree fntype ATTRIBUTE_UNUSED, -+ rtx libcall ATTRIBUTE_UNUSED, -+ const_tree fndecl ATTRIBUTE_UNUSED) -+{ -+ /* Record the unallocated VFP registers. */ -+ pcum->aapcs_vfp_regs_free = (1 << NUM_VFP_ARG_REGS) - 1; -+ pcum->aapcs_vfp_reg_alloc = 0; -+} -+ -+/* Walk down the type tree of TYPE counting consecutive base elements. -+ If *MODEP is VOIDmode, then set it to the first valid floating point -+ type. If a non-floating point type is found, or if a floating point -+ type that doesn't match a non-VOIDmode *MODEP is found, then return -1, -+ otherwise return the count in the sub-tree. */ -+static int -+aapcs_vfp_sub_candidate (const_tree type, enum machine_mode *modep) -+{ -+ enum machine_mode mode; -+ HOST_WIDE_INT size; -+ -+ switch (TREE_CODE (type)) -+ { -+ case REAL_TYPE: -+ mode = TYPE_MODE (type); -+ if (mode != DFmode && mode != SFmode) -+ return -1; -+ -+ if (*modep == VOIDmode) -+ *modep = mode; -+ -+ if (*modep == mode) -+ return 1; -+ -+ break; -+ -+ case COMPLEX_TYPE: -+ mode = TYPE_MODE (TREE_TYPE (type)); -+ if (mode != DFmode && mode != SFmode) -+ return -1; -+ -+ if (*modep == VOIDmode) -+ *modep = mode; -+ -+ if (*modep == mode) -+ return 2; -+ -+ break; -+ -+ case VECTOR_TYPE: -+ /* Use V2SImode and V4SImode as representatives of all 64-bit -+ and 128-bit vector types, whether or not those modes are -+ supported with the present options. */ -+ size = int_size_in_bytes (type); -+ switch (size) -+ { -+ case 8: -+ mode = V2SImode; -+ break; -+ case 16: -+ mode = V4SImode; -+ break; -+ default: -+ return -1; -+ } -+ -+ if (*modep == VOIDmode) -+ *modep = mode; -+ -+ /* Vector modes are considered to be opaque: two vectors are -+ equivalent for the purposes of being homogeneous aggregates -+ if they are the same size. */ -+ if (*modep == mode) -+ return 1; -+ -+ break; -+ -+ case ARRAY_TYPE: -+ { -+ int count; -+ tree index = TYPE_DOMAIN (type); -+ -+ /* Can't handle incomplete types. */ -+ if (!COMPLETE_TYPE_P(type)) -+ return -1; -+ -+ count = aapcs_vfp_sub_candidate (TREE_TYPE (type), modep); -+ if (count == -1 -+ || !index -+ || !TYPE_MAX_VALUE (index) -+ || !host_integerp (TYPE_MAX_VALUE (index), 1) -+ || !TYPE_MIN_VALUE (index) -+ || !host_integerp (TYPE_MIN_VALUE (index), 1) -+ || count < 0) -+ return -1; -+ -+ count *= (1 + tree_low_cst (TYPE_MAX_VALUE (index), 1) -+ - tree_low_cst (TYPE_MIN_VALUE (index), 1)); -+ -+ /* There must be no padding. */ -+ if (!host_integerp (TYPE_SIZE (type), 1) -+ || (tree_low_cst (TYPE_SIZE (type), 1) -+ != count * GET_MODE_BITSIZE (*modep))) -+ return -1; -+ -+ return count; -+ } -+ -+ case RECORD_TYPE: -+ { -+ int count = 0; -+ int sub_count; -+ tree field; -+ -+ /* Can't handle incomplete types. */ -+ if (!COMPLETE_TYPE_P(type)) -+ return -1; -+ -+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) -+ { -+ if (TREE_CODE (field) != FIELD_DECL) -+ continue; -+ -+ sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep); -+ if (sub_count < 0) -+ return -1; -+ count += sub_count; -+ } -+ -+ /* There must be no padding. */ -+ if (!host_integerp (TYPE_SIZE (type), 1) -+ || (tree_low_cst (TYPE_SIZE (type), 1) -+ != count * GET_MODE_BITSIZE (*modep))) -+ return -1; -+ -+ return count; -+ } -+ -+ case UNION_TYPE: -+ case QUAL_UNION_TYPE: -+ { -+ /* These aren't very interesting except in a degenerate case. */ -+ int count = 0; -+ int sub_count; -+ tree field; -+ -+ /* Can't handle incomplete types. */ -+ if (!COMPLETE_TYPE_P(type)) -+ return -1; -+ -+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) -+ { -+ if (TREE_CODE (field) != FIELD_DECL) -+ continue; -+ -+ sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep); -+ if (sub_count < 0) -+ return -1; -+ count = count > sub_count ? count : sub_count; -+ } -+ -+ /* There must be no padding. */ -+ if (!host_integerp (TYPE_SIZE (type), 1) -+ || (tree_low_cst (TYPE_SIZE (type), 1) -+ != count * GET_MODE_BITSIZE (*modep))) -+ return -1; -+ -+ return count; -+ } -+ -+ default: -+ break; -+ } -+ -+ return -1; -+} -+ -+/* Return true if PCS_VARIANT should use VFP registers. */ -+static bool -+use_vfp_abi (enum arm_pcs pcs_variant, bool is_double) -+{ -+ if (pcs_variant == ARM_PCS_AAPCS_VFP) -+ return true; -+ -+ if (pcs_variant != ARM_PCS_AAPCS_LOCAL) -+ return false; -+ -+ return (TARGET_32BIT && TARGET_VFP && TARGET_HARD_FLOAT && -+ (TARGET_VFP_DOUBLE || !is_double)); -+} -+ -+static bool -+aapcs_vfp_is_call_or_return_candidate (enum arm_pcs pcs_variant, -+ enum machine_mode mode, const_tree type, -+ int *base_mode, int *count) -+{ -+ enum machine_mode new_mode = VOIDmode; -+ -+ if (GET_MODE_CLASS (mode) == MODE_FLOAT -+ || GET_MODE_CLASS (mode) == MODE_VECTOR_INT -+ || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) -+ { -+ *count = 1; -+ new_mode = mode; -+ } -+ else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT) -+ { -+ *count = 2; -+ new_mode = (mode == DCmode ? DFmode : SFmode); -+ } -+ else if (type && (mode == BLKmode || TREE_CODE (type) == VECTOR_TYPE)) -+ { -+ int ag_count = aapcs_vfp_sub_candidate (type, &new_mode); -+ -+ if (ag_count > 0 && ag_count <= 4) -+ *count = ag_count; -+ else -+ return false; -+ } -+ else -+ return false; -+ -+ -+ if (!use_vfp_abi (pcs_variant, ARM_NUM_REGS (new_mode) > 1)) -+ return false; -+ -+ *base_mode = new_mode; -+ return true; -+} -+ -+static bool -+aapcs_vfp_is_return_candidate (enum arm_pcs pcs_variant, -+ enum machine_mode mode, const_tree type) -+{ -+ int count ATTRIBUTE_UNUSED; -+ int ag_mode ATTRIBUTE_UNUSED; -+ -+ if (!use_vfp_abi (pcs_variant, false)) -+ return false; -+ return aapcs_vfp_is_call_or_return_candidate (pcs_variant, mode, type, -+ &ag_mode, &count); -+} -+ -+static bool -+aapcs_vfp_is_call_candidate (CUMULATIVE_ARGS *pcum, enum machine_mode mode, -+ const_tree type) -+{ -+ if (!use_vfp_abi (pcum->pcs_variant, false)) -+ return false; -+ -+ return aapcs_vfp_is_call_or_return_candidate (pcum->pcs_variant, mode, type, -+ &pcum->aapcs_vfp_rmode, -+ &pcum->aapcs_vfp_rcount); -+} -+ -+static bool -+aapcs_vfp_allocate (CUMULATIVE_ARGS *pcum, enum machine_mode mode, -+ const_tree type ATTRIBUTE_UNUSED) -+{ -+ int shift = GET_MODE_SIZE (pcum->aapcs_vfp_rmode) / GET_MODE_SIZE (SFmode); -+ unsigned mask = (1 << (shift * pcum->aapcs_vfp_rcount)) - 1; -+ int regno; -+ -+ for (regno = 0; regno < NUM_VFP_ARG_REGS; regno += shift) -+ if (((pcum->aapcs_vfp_regs_free >> regno) & mask) == mask) -+ { -+ pcum->aapcs_vfp_reg_alloc = mask << regno; -+ if (mode == BLKmode || (mode == TImode && !TARGET_NEON)) -+ { -+ int i; -+ int rcount = pcum->aapcs_vfp_rcount; -+ int rshift = shift; -+ enum machine_mode rmode = pcum->aapcs_vfp_rmode; -+ rtx par; -+ if (!TARGET_NEON) -+ { -+ /* Avoid using unsupported vector modes. */ -+ if (rmode == V2SImode) -+ rmode = DImode; -+ else if (rmode == V4SImode) -+ { -+ rmode = DImode; -+ rcount *= 2; -+ rshift /= 2; -+ } -+ } -+ par = gen_rtx_PARALLEL (mode, rtvec_alloc (rcount)); -+ for (i = 0; i < rcount; i++) -+ { -+ rtx tmp = gen_rtx_REG (rmode, -+ FIRST_VFP_REGNUM + regno + i * rshift); -+ tmp = gen_rtx_EXPR_LIST -+ (VOIDmode, tmp, -+ GEN_INT (i * GET_MODE_SIZE (rmode))); -+ XVECEXP (par, 0, i) = tmp; -+ } -+ -+ pcum->aapcs_reg = par; -+ } -+ else -+ pcum->aapcs_reg = gen_rtx_REG (mode, FIRST_VFP_REGNUM + regno); -+ return true; -+ } -+ return false; -+} -+ -+static rtx -+aapcs_vfp_allocate_return_reg (enum arm_pcs pcs_variant ATTRIBUTE_UNUSED, -+ enum machine_mode mode, -+ const_tree type ATTRIBUTE_UNUSED) -+{ -+ if (!use_vfp_abi (pcs_variant, false)) -+ return false; -+ -+ if (mode == BLKmode || (mode == TImode && !TARGET_NEON)) -+ { -+ int count; -+ int ag_mode; -+ int i; -+ rtx par; -+ int shift; -+ -+ aapcs_vfp_is_call_or_return_candidate (pcs_variant, mode, type, -+ &ag_mode, &count); -+ -+ if (!TARGET_NEON) -+ { -+ if (ag_mode == V2SImode) -+ ag_mode = DImode; -+ else if (ag_mode == V4SImode) -+ { -+ ag_mode = DImode; -+ count *= 2; -+ } -+ } -+ shift = GET_MODE_SIZE(ag_mode) / GET_MODE_SIZE(SFmode); -+ par = gen_rtx_PARALLEL (mode, rtvec_alloc (count)); -+ for (i = 0; i < count; i++) -+ { -+ rtx tmp = gen_rtx_REG (ag_mode, FIRST_VFP_REGNUM + i * shift); -+ tmp = gen_rtx_EXPR_LIST (VOIDmode, tmp, -+ GEN_INT (i * GET_MODE_SIZE (ag_mode))); -+ XVECEXP (par, 0, i) = tmp; -+ } -+ -+ return par; -+ } -+ -+ return gen_rtx_REG (mode, FIRST_VFP_REGNUM); -+} -+ -+static void -+aapcs_vfp_advance (CUMULATIVE_ARGS *pcum ATTRIBUTE_UNUSED, -+ enum machine_mode mode ATTRIBUTE_UNUSED, -+ const_tree type ATTRIBUTE_UNUSED) -+{ -+ pcum->aapcs_vfp_regs_free &= ~pcum->aapcs_vfp_reg_alloc; -+ pcum->aapcs_vfp_reg_alloc = 0; -+ return; -+} -+ -+#define AAPCS_CP(X) \ -+ { \ -+ aapcs_ ## X ## _cum_init, \ -+ aapcs_ ## X ## _is_call_candidate, \ -+ aapcs_ ## X ## _allocate, \ -+ aapcs_ ## X ## _is_return_candidate, \ -+ aapcs_ ## X ## _allocate_return_reg, \ -+ aapcs_ ## X ## _advance \ -+ } -+ -+/* Table of co-processors that can be used to pass arguments in -+ registers. Idealy no arugment should be a candidate for more than -+ one co-processor table entry, but the table is processed in order -+ and stops after the first match. If that entry then fails to put -+ the argument into a co-processor register, the argument will go on -+ the stack. */ -+static struct -+{ -+ /* Initialize co-processor related state in CUMULATIVE_ARGS structure. */ -+ void (*cum_init) (CUMULATIVE_ARGS *, const_tree, rtx, const_tree); -+ -+ /* Return true if an argument of mode MODE (or type TYPE if MODE is -+ BLKmode) is a candidate for this co-processor's registers; this -+ function should ignore any position-dependent state in -+ CUMULATIVE_ARGS and only use call-type dependent information. */ -+ bool (*is_call_candidate) (CUMULATIVE_ARGS *, enum machine_mode, const_tree); -+ -+ /* Return true if the argument does get a co-processor register; it -+ should set aapcs_reg to an RTX of the register allocated as is -+ required for a return from FUNCTION_ARG. */ -+ bool (*allocate) (CUMULATIVE_ARGS *, enum machine_mode, const_tree); -+ -+ /* Return true if a result of mode MODE (or type TYPE if MODE is -+ BLKmode) is can be returned in this co-processor's registers. */ -+ bool (*is_return_candidate) (enum arm_pcs, enum machine_mode, const_tree); -+ -+ /* Allocate and return an RTX element to hold the return type of a -+ call, this routine must not fail and will only be called if -+ is_return_candidate returned true with the same parameters. */ -+ rtx (*allocate_return_reg) (enum arm_pcs, enum machine_mode, const_tree); -+ -+ /* Finish processing this argument and prepare to start processing -+ the next one. */ -+ void (*advance) (CUMULATIVE_ARGS *, enum machine_mode, const_tree); -+} aapcs_cp_arg_layout[ARM_NUM_COPROC_SLOTS] = -+ { -+ AAPCS_CP(vfp) -+ }; -+ -+#undef AAPCS_CP -+ -+static int -+aapcs_select_call_coproc (CUMULATIVE_ARGS *pcum, enum machine_mode mode, -+ tree type) -+{ -+ int i; -+ -+ for (i = 0; i < ARM_NUM_COPROC_SLOTS; i++) -+ if (aapcs_cp_arg_layout[i].is_call_candidate (pcum, mode, type)) -+ return i; -+ -+ return -1; -+} -+ -+static int -+aapcs_select_return_coproc (const_tree type, const_tree fntype) -+{ -+ /* We aren't passed a decl, so we can't check that a call is local. -+ However, it isn't clear that that would be a win anyway, since it -+ might limit some tail-calling opportunities. */ -+ enum arm_pcs pcs_variant; -+ -+ if (fntype) -+ { -+ const_tree fndecl = NULL_TREE; -+ -+ if (TREE_CODE (fntype) == FUNCTION_DECL) -+ { -+ fndecl = fntype; -+ fntype = TREE_TYPE (fntype); -+ } -+ -+ pcs_variant = arm_get_pcs_model (fntype, fndecl); -+ } -+ else -+ pcs_variant = arm_pcs_default; -+ -+ if (pcs_variant != ARM_PCS_AAPCS) -+ { -+ int i; -+ -+ for (i = 0; i < ARM_NUM_COPROC_SLOTS; i++) -+ if (aapcs_cp_arg_layout[i].is_return_candidate (pcs_variant, -+ TYPE_MODE (type), -+ type)) -+ return i; -+ } -+ return -1; -+} -+ -+static rtx -+aapcs_allocate_return_reg (enum machine_mode mode, const_tree type, -+ const_tree fntype) -+{ -+ /* We aren't passed a decl, so we can't check that a call is local. -+ However, it isn't clear that that would be a win anyway, since it -+ might limit some tail-calling opportunities. */ -+ enum arm_pcs pcs_variant; -+ -+ if (fntype) -+ { -+ const_tree fndecl = NULL_TREE; -+ -+ if (TREE_CODE (fntype) == FUNCTION_DECL) -+ { -+ fndecl = fntype; -+ fntype = TREE_TYPE (fntype); -+ } -+ -+ pcs_variant = arm_get_pcs_model (fntype, fndecl); -+ } -+ else -+ pcs_variant = arm_pcs_default; -+ -+ /* Promote integer types. */ -+ if (type && INTEGRAL_TYPE_P (type)) -+ PROMOTE_FUNCTION_MODE (mode, unsignedp, type); -+ -+ if (pcs_variant != ARM_PCS_AAPCS) -+ { -+ int i; -+ -+ for (i = 0; i < ARM_NUM_COPROC_SLOTS; i++) -+ if (aapcs_cp_arg_layout[i].is_return_candidate (pcs_variant, mode, -+ type)) -+ return aapcs_cp_arg_layout[i].allocate_return_reg (pcs_variant, -+ mode, type); -+ } -+ -+ /* Promotes small structs returned in a register to full-word size -+ for big-endian AAPCS. */ -+ if (type && arm_return_in_msb (type)) -+ { -+ HOST_WIDE_INT size = int_size_in_bytes (type); -+ if (size % UNITS_PER_WORD != 0) -+ { -+ size += UNITS_PER_WORD - size % UNITS_PER_WORD; -+ mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0); -+ } -+ } -+ -+ return gen_rtx_REG (mode, R0_REGNUM); -+} -+ -+rtx -+aapcs_libcall_value (enum machine_mode mode) -+{ -+ return aapcs_allocate_return_reg (mode, NULL_TREE, NULL_TREE); -+} -+ -+/* Lay out a function argument using the AAPCS rules. The rule -+ numbers referred to here are those in the AAPCS. */ -+static void -+aapcs_layout_arg (CUMULATIVE_ARGS *pcum, enum machine_mode mode, -+ tree type, int named) -+{ -+ int nregs, nregs2; -+ int ncrn; -+ -+ /* We only need to do this once per argument. */ -+ if (pcum->aapcs_arg_processed) -+ return; -+ -+ pcum->aapcs_arg_processed = true; -+ -+ /* Special case: if named is false then we are handling an incoming -+ anonymous argument which is on the stack. */ -+ if (!named) -+ return; -+ -+ /* Is this a potential co-processor register candidate? */ -+ if (pcum->pcs_variant != ARM_PCS_AAPCS) -+ { -+ int slot = aapcs_select_call_coproc (pcum, mode, type); -+ pcum->aapcs_cprc_slot = slot; -+ -+ /* We don't have to apply any of the rules from part B of the -+ preparation phase, these are handled elsewhere in the -+ compiler. */ -+ -+ if (slot >= 0) -+ { -+ /* A Co-processor register candidate goes either in its own -+ class of registers or on the stack. */ -+ if (!pcum->aapcs_cprc_failed[slot]) -+ { -+ /* C1.cp - Try to allocate the argument to co-processor -+ registers. */ -+ if (aapcs_cp_arg_layout[slot].allocate (pcum, mode, type)) -+ return; -+ -+ /* C2.cp - Put the argument on the stack and note that we -+ can't assign any more candidates in this slot. We also -+ need to note that we have allocated stack space, so that -+ we won't later try to split a non-cprc candidate between -+ core registers and the stack. */ -+ pcum->aapcs_cprc_failed[slot] = true; -+ pcum->can_split = false; -+ } -+ -+ /* We didn't get a register, so this argument goes on the -+ stack. */ -+ gcc_assert (pcum->can_split == false); -+ return; -+ } -+ } -+ -+ /* C3 - For double-word aligned arguments, round the NCRN up to the -+ next even number. */ -+ ncrn = pcum->aapcs_ncrn; -+ if ((ncrn & 1) && arm_needs_doubleword_align (mode, type)) -+ ncrn++; -+ -+ nregs = ARM_NUM_REGS2(mode, type); -+ -+ /* Sigh, this test should really assert that nregs > 0, but a GCC -+ extension allows empty structs and then gives them empty size; it -+ then allows such a structure to be passed by value. For some of -+ the code below we have to pretend that such an argument has -+ non-zero size so that we 'locate' it correctly either in -+ registers or on the stack. */ -+ gcc_assert (nregs >= 0); -+ -+ nregs2 = nregs ? nregs : 1; -+ -+ /* C4 - Argument fits entirely in core registers. */ -+ if (ncrn + nregs2 <= NUM_ARG_REGS) -+ { -+ pcum->aapcs_reg = gen_rtx_REG (mode, ncrn); -+ pcum->aapcs_next_ncrn = ncrn + nregs; -+ return; -+ } -+ -+ /* C5 - Some core registers left and there are no arguments already -+ on the stack: split this argument between the remaining core -+ registers and the stack. */ -+ if (ncrn < NUM_ARG_REGS && pcum->can_split) -+ { -+ pcum->aapcs_reg = gen_rtx_REG (mode, ncrn); -+ pcum->aapcs_next_ncrn = NUM_ARG_REGS; -+ pcum->aapcs_partial = (NUM_ARG_REGS - ncrn) * UNITS_PER_WORD; -+ return; -+ } -+ -+ /* C6 - NCRN is set to 4. */ -+ pcum->aapcs_next_ncrn = NUM_ARG_REGS; -+ -+ /* C7,C8 - arugment goes on the stack. We have nothing to do here. */ -+ return; -+} -+ - /* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is NULL. */ - void - arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype, -- rtx libname ATTRIBUTE_UNUSED, -+ rtx libname, - tree fndecl ATTRIBUTE_UNUSED) - { -+ /* Long call handling. */ -+ if (fntype) -+ pcum->pcs_variant = arm_get_pcs_model (fntype, fndecl); -+ else -+ pcum->pcs_variant = arm_pcs_default; -+ -+ if (pcum->pcs_variant <= ARM_PCS_AAPCS_LOCAL) -+ { -+ /* XXX We should also detect some library calls here and handle -+ them using the base rules too; for example the floating point -+ support functions always work this way. */ -+ -+ if (rtx_equal_p (libname, -+ convert_optab_libfunc (sfix_optab, DImode, DFmode)) -+ || rtx_equal_p (libname, -+ convert_optab_libfunc (ufix_optab, DImode, DFmode)) -+ || rtx_equal_p (libname, -+ convert_optab_libfunc (sfix_optab, DImode, SFmode)) -+ || rtx_equal_p (libname, -+ convert_optab_libfunc (ufix_optab, DImode, SFmode)) -+ || rtx_equal_p (libname, -+ convert_optab_libfunc (trunc_optab, HFmode, SFmode)) -+ || rtx_equal_p (libname, -+ convert_optab_libfunc (sext_optab, SFmode, HFmode))) -+ pcum->pcs_variant = ARM_PCS_AAPCS; -+ -+ pcum->aapcs_ncrn = pcum->aapcs_next_ncrn = 0; -+ pcum->aapcs_reg = NULL_RTX; -+ pcum->aapcs_partial = 0; -+ pcum->aapcs_arg_processed = false; -+ pcum->aapcs_cprc_slot = -1; -+ pcum->can_split = true; -+ -+ if (pcum->pcs_variant != ARM_PCS_AAPCS) -+ { -+ int i; -+ -+ for (i = 0; i < ARM_NUM_COPROC_SLOTS; i++) -+ { -+ pcum->aapcs_cprc_failed[i] = false; -+ aapcs_cp_arg_layout[i].cum_init (pcum, fntype, libname, fndecl); -+ } -+ } -+ return; -+ } -+ -+ /* Legacy ABIs */ -+ - /* On the ARM, the offset starts at 0. */ - pcum->nregs = 0; - pcum->iwmmxt_nregs = 0; -@@ -3120,6 +4189,17 @@ - { - int nregs; - -+ /* Handle the special case quickly. Pick an arbitrary value for op2 of -+ a call insn (op3 of a call_value insn). */ -+ if (mode == VOIDmode) -+ return const0_rtx; -+ -+ if (pcum->pcs_variant <= ARM_PCS_AAPCS_LOCAL) -+ { -+ aapcs_layout_arg (pcum, mode, type, named); -+ return pcum->aapcs_reg; -+ } -+ - /* Varargs vectors are treated the same as long long. - named_count avoids having to change the way arm handles 'named' */ - if (TARGET_IWMMXT_ABI -@@ -3161,10 +4241,16 @@ - - static int - arm_arg_partial_bytes (CUMULATIVE_ARGS *pcum, enum machine_mode mode, -- tree type, bool named ATTRIBUTE_UNUSED) -+ tree type, bool named) - { - int nregs = pcum->nregs; - -+ if (pcum->pcs_variant <= ARM_PCS_AAPCS_LOCAL) -+ { -+ aapcs_layout_arg (pcum, mode, type, named); -+ return pcum->aapcs_partial; -+ } -+ - if (TARGET_IWMMXT_ABI && arm_vector_mode_supported_p (mode)) - return 0; - -@@ -3176,6 +4262,39 @@ - return 0; - } - -+void -+arm_function_arg_advance (CUMULATIVE_ARGS *pcum, enum machine_mode mode, -+ tree type, bool named) -+{ -+ if (pcum->pcs_variant <= ARM_PCS_AAPCS_LOCAL) -+ { -+ aapcs_layout_arg (pcum, mode, type, named); -+ -+ if (pcum->aapcs_cprc_slot >= 0) -+ { -+ aapcs_cp_arg_layout[pcum->aapcs_cprc_slot].advance (pcum, mode, -+ type); -+ pcum->aapcs_cprc_slot = -1; -+ } -+ -+ /* Generic stuff. */ -+ pcum->aapcs_arg_processed = false; -+ pcum->aapcs_ncrn = pcum->aapcs_next_ncrn; -+ pcum->aapcs_reg = NULL_RTX; -+ pcum->aapcs_partial = 0; -+ } -+ else -+ { -+ pcum->nargs += 1; -+ if (arm_vector_mode_supported_p (mode) -+ && pcum->named_count > pcum->nargs -+ && TARGET_IWMMXT_ABI) -+ pcum->iwmmxt_nregs += 1; -+ else -+ pcum->nregs += ARM_NUM_REGS2 (mode, type); -+ } -+} -+ - /* Variable sized types are passed by reference. This is a GCC - extension to the ARM ABI. */ - -@@ -3226,6 +4345,8 @@ - /* Whereas these functions are always known to reside within the 26 bit - addressing range. */ - { "short_call", 0, 0, false, true, true, NULL }, -+ /* Specify the procedure call conventions for a function. */ -+ { "pcs", 1, 1, false, true, true, arm_handle_pcs_attribute }, - /* Interrupt Service Routines have special prologue and epilogue requirements. */ - { "isr", 0, 1, false, false, false, arm_handle_isr_attribute }, - { "interrupt", 0, 1, false, false, false, arm_handle_isr_attribute }, -@@ -3328,6 +4449,21 @@ - return NULL_TREE; - } - -+/* Handle a "pcs" attribute; arguments as in struct -+ attribute_spec.handler. */ -+static tree -+arm_handle_pcs_attribute (tree *node ATTRIBUTE_UNUSED, tree name, tree args, -+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) -+{ -+ if (arm_pcs_from_attribute (args) == ARM_PCS_UNKNOWN) -+ { -+ warning (OPT_Wattributes, "%qs attribute ignored", -+ IDENTIFIER_POINTER (name)); -+ *no_add_attrs = true; -+ } -+ return NULL_TREE; -+} -+ - #if TARGET_DLLIMPORT_DECL_ATTRIBUTES - /* Handle the "notshared" attribute. This attribute is another way of - requesting hidden visibility. ARM's compiler supports -@@ -3489,7 +4625,7 @@ - - /* Return nonzero if it is ok to make a tail-call to DECL. */ - static bool --arm_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) -+arm_function_ok_for_sibcall (tree decl, tree exp) - { - unsigned long func_type; - -@@ -3522,6 +4658,21 @@ - if (IS_INTERRUPT (func_type)) - return false; - -+ if (!VOID_TYPE_P (TREE_TYPE (DECL_RESULT (cfun->decl)))) -+ { -+ /* Check that the return value locations are the same. For -+ example that we aren't returning a value from the sibling in -+ a VFP register but then need to transfer it to a core -+ register. */ -+ rtx a, b; -+ -+ a = arm_function_value (TREE_TYPE (exp), decl, false); -+ b = arm_function_value (TREE_TYPE (DECL_RESULT (cfun->decl)), -+ cfun->decl, false); -+ if (!rtx_equal_p (a, b)) -+ return false; -+ } -+ - /* Never tailcall if function may be called with a misaligned SP. */ - if (IS_STACKALIGN (func_type)) - return false; -@@ -4120,6 +5271,7 @@ - if (GET_MODE_SIZE (mode) <= 4 - && ! (arm_arch4 - && (mode == HImode -+ || mode == HFmode - || (mode == QImode && outer == SIGN_EXTEND)))) - { - if (code == MULT) -@@ -4148,13 +5300,15 @@ - load. */ - if (arm_arch4) - { -- if (mode == HImode || (outer == SIGN_EXTEND && mode == QImode)) -+ if (mode == HImode -+ || mode == HFmode -+ || (outer == SIGN_EXTEND && mode == QImode)) - range = 256; - else - range = 4096; - } - else -- range = (mode == HImode) ? 4095 : 4096; -+ range = (mode == HImode || mode == HFmode) ? 4095 : 4096; - - return (code == CONST_INT - && INTVAL (index) < range -@@ -4325,7 +5479,8 @@ - return 1; - - /* This is PC relative data after arm_reorg runs. */ -- else if (GET_MODE_SIZE (mode) >= 4 && reload_completed -+ else if ((GET_MODE_SIZE (mode) >= 4 || mode == HFmode) -+ && reload_completed - && (GET_CODE (x) == LABEL_REF - || (GET_CODE (x) == CONST - && GET_CODE (XEXP (x, 0)) == PLUS -@@ -5024,7 +6179,7 @@ - case UMOD: - if (TARGET_HARD_FLOAT && mode == SFmode) - *total = COSTS_N_INSNS (2); -- else if (TARGET_HARD_FLOAT && mode == DFmode) -+ else if (TARGET_HARD_FLOAT && mode == DFmode && !TARGET_VFP_SINGLE) - *total = COSTS_N_INSNS (4); - else - *total = COSTS_N_INSNS (20); -@@ -5063,23 +6218,6 @@ - return true; - - case MINUS: -- if (TARGET_THUMB2) -- { -- if (GET_MODE_CLASS (mode) == MODE_FLOAT) -- { -- if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode)) -- *total = COSTS_N_INSNS (1); -- else -- *total = COSTS_N_INSNS (20); -- } -- else -- *total = COSTS_N_INSNS (ARM_NUM_REGS (mode)); -- /* Thumb2 does not have RSB, so all arguments must be -- registers (subtracting a constant is canonicalized as -- addition of the negated constant). */ -- return false; -- } -- - if (mode == DImode) - { - *total = COSTS_N_INSNS (ARM_NUM_REGS (mode)); -@@ -5102,7 +6240,9 @@ - - if (GET_MODE_CLASS (mode) == MODE_FLOAT) - { -- if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode)) -+ if (TARGET_HARD_FLOAT -+ && (mode == SFmode -+ || (mode == DFmode && !TARGET_VFP_SINGLE))) - { - *total = COSTS_N_INSNS (1); - if (GET_CODE (XEXP (x, 0)) == CONST_DOUBLE -@@ -5143,6 +6283,17 @@ - return true; - } - -+ /* A shift as a part of RSB costs no more than RSB itself. */ -+ if (GET_CODE (XEXP (x, 0)) == MULT -+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT -+ && ((INTVAL (XEXP (XEXP (x, 0), 1)) -+ & (INTVAL (XEXP (XEXP (x, 0), 1)) - 1)) == 0)) -+ { -+ *total += rtx_cost (XEXP (XEXP (x, 0), 0), code, speed); -+ *total += rtx_cost (XEXP (x, 1), code, speed); -+ return true; -+ } -+ - if (subcode == MULT - && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT - && ((INTVAL (XEXP (XEXP (x, 1), 1)) & -@@ -5164,6 +6315,19 @@ - return true; - } - -+ /* MLS is just as expensive as its underlying multiplication. -+ Exclude a shift by a constant, which is expressed as a -+ multiplication. */ -+ if (TARGET_32BIT && arm_arch_thumb2 -+ && GET_CODE (XEXP (x, 1)) == MULT -+ && ! (GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT -+ && ((INTVAL (XEXP (XEXP (x, 1), 1)) & -+ (INTVAL (XEXP (XEXP (x, 1), 1)) - 1)) == 0))) -+ { -+ /* The cost comes from the cost of the multiply. */ -+ return false; -+ } -+ - /* Fall through */ - - case PLUS: -@@ -5192,7 +6356,9 @@ - - if (GET_MODE_CLASS (mode) == MODE_FLOAT) - { -- if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode)) -+ if (TARGET_HARD_FLOAT -+ && (mode == SFmode -+ || (mode == DFmode && !TARGET_VFP_SINGLE))) - { - *total = COSTS_N_INSNS (1); - if (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE -@@ -5307,7 +6473,9 @@ - case NEG: - if (GET_MODE_CLASS (mode) == MODE_FLOAT) - { -- if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode)) -+ if (TARGET_HARD_FLOAT -+ && (mode == SFmode -+ || (mode == DFmode && !TARGET_VFP_SINGLE))) - { - *total = COSTS_N_INSNS (1); - return false; -@@ -5460,7 +6628,9 @@ - case ABS: - if (GET_MODE_CLASS (mode == MODE_FLOAT)) - { -- if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode)) -+ if (TARGET_HARD_FLOAT -+ && (mode == SFmode -+ || (mode == DFmode && !TARGET_VFP_SINGLE))) - { - *total = COSTS_N_INSNS (1); - return false; -@@ -5563,7 +6733,8 @@ - return true; - - case CONST_DOUBLE: -- if (TARGET_HARD_FLOAT && vfp3_const_double_rtx (x)) -+ if (TARGET_HARD_FLOAT && vfp3_const_double_rtx (x) -+ && (mode == SFmode || !TARGET_VFP_SINGLE)) - *total = COSTS_N_INSNS (1); - else - *total = COSTS_N_INSNS (4); -@@ -5638,7 +6809,8 @@ - return false; - - case MINUS: -- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT) -+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT -+ && (mode == SFmode || !TARGET_VFP_SINGLE)) - { - *total = COSTS_N_INSNS (1); - return false; -@@ -5668,7 +6840,8 @@ - return false; - - case PLUS: -- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT) -+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT -+ && (mode == SFmode || !TARGET_VFP_SINGLE)) - { - *total = COSTS_N_INSNS (1); - return false; -@@ -5698,7 +6871,8 @@ - return false; - - case NEG: -- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT) -+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT -+ && (mode == SFmode || !TARGET_VFP_SINGLE)) - { - *total = COSTS_N_INSNS (1); - return false; -@@ -5722,7 +6896,8 @@ - return false; - - case ABS: -- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT) -+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT -+ && (mode == SFmode || !TARGET_VFP_SINGLE)) - *total = COSTS_N_INSNS (1); - else - *total = COSTS_N_INSNS (1 + ARM_NUM_REGS (mode)); -@@ -5939,7 +7114,9 @@ - - if (GET_MODE_CLASS (mode) == MODE_FLOAT) - { -- if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode)) -+ if (TARGET_HARD_FLOAT -+ && (mode == SFmode -+ || (mode == DFmode && !TARGET_VFP_SINGLE))) - { - *total = COSTS_N_INSNS (1); - return false; -@@ -6096,7 +7273,9 @@ - - if (GET_MODE_CLASS (mode) == MODE_FLOAT) - { -- if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode)) -+ if (TARGET_HARD_FLOAT -+ && (mode == SFmode -+ || (mode == DFmode && !TARGET_VFP_SINGLE))) - { - *total = COSTS_N_INSNS (1); - return false; -@@ -6919,10 +8098,13 @@ - } - - /* Return TRUE if OP is a memory operand which we can load or store a vector -- to/from. If CORE is true, we're moving from ARM registers not Neon -- registers. */ -+ to/from. TYPE is one of the following values: -+ 0 - Vector load/stor (vldr) -+ 1 - Core registers (ldm) -+ 2 - Element/structure loads (vld1) -+ */ - int --neon_vector_mem_operand (rtx op, bool core) -+neon_vector_mem_operand (rtx op, int type) - { - rtx ind; - -@@ -6955,23 +8137,16 @@ - return arm_address_register_rtx_p (ind, 0); - - /* Allow post-increment with Neon registers. */ -- if (!core && GET_CODE (ind) == POST_INC) -+ if ((type != 1 && GET_CODE (ind) == POST_INC) -+ || (type == 0 && GET_CODE (ind) == PRE_DEC)) - return arm_address_register_rtx_p (XEXP (ind, 0), 0); - --#if 0 -- /* FIXME: We can support this too if we use VLD1/VST1. */ -- if (!core -- && GET_CODE (ind) == POST_MODIFY -- && arm_address_register_rtx_p (XEXP (ind, 0), 0) -- && GET_CODE (XEXP (ind, 1)) == PLUS -- && rtx_equal_p (XEXP (XEXP (ind, 1), 0), XEXP (ind, 0))) -- ind = XEXP (ind, 1); --#endif -+ /* FIXME: vld1 allows register post-modify. */ - - /* Match: - (plus (reg) - (const)). */ -- if (!core -+ if (type == 0 - && GET_CODE (ind) == PLUS - && GET_CODE (XEXP (ind, 0)) == REG - && REG_MODE_OK_FOR_BASE_P (XEXP (ind, 0), VOIDmode) -@@ -7038,10 +8213,19 @@ - enum reg_class - coproc_secondary_reload_class (enum machine_mode mode, rtx x, bool wb) - { -+ if (mode == HFmode) -+ { -+ if (!TARGET_NEON_FP16) -+ return GENERAL_REGS; -+ if (s_register_operand (x, mode) || neon_vector_mem_operand (x, 2)) -+ return NO_REGS; -+ return GENERAL_REGS; -+ } -+ - if (TARGET_NEON - && (GET_MODE_CLASS (mode) == MODE_VECTOR_INT - || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) -- && neon_vector_mem_operand (x, FALSE)) -+ && neon_vector_mem_operand (x, 0)) - return NO_REGS; - - if (arm_coproc_mem_operand (x, wb) || s_register_operand (x, mode)) -@@ -7438,6 +8622,9 @@ - int base_reg = -1; - int i; - -+ if (low_irq_latency) -+ return 0; -+ - /* Can only handle 2, 3, or 4 insns at present, - though could be easily extended if required. */ - gcc_assert (nops >= 2 && nops <= 4); -@@ -7667,6 +8854,9 @@ - int base_reg = -1; - int i; - -+ if (low_irq_latency) -+ return 0; -+ - /* Can only handle 2, 3, or 4 insns at present, though could be easily - extended if required. */ - gcc_assert (nops >= 2 && nops <= 4); -@@ -7874,7 +9064,7 @@ - - As a compromise, we use ldr for counts of 1 or 2 regs, and ldm - for counts of 3 or 4 regs. */ -- if (arm_tune_xscale && count <= 2 && ! optimize_size) -+ if (low_irq_latency || (arm_tune_xscale && count <= 2 && ! optimize_size)) - { - rtx seq; - -@@ -7937,7 +9127,7 @@ - - /* See arm_gen_load_multiple for discussion of - the pros/cons of ldm/stm usage for XScale. */ -- if (arm_tune_xscale && count <= 2 && ! optimize_size) -+ if (low_irq_latency || (arm_tune_xscale && count <= 2 && ! optimize_size)) - { - rtx seq; - -@@ -9555,7 +10745,10 @@ - gcc_assert (GET_CODE (from) != BARRIER); - - /* Count the length of this insn. */ -- count += get_attr_length (from); -+ if (LABEL_P (from) && (align_jumps > 0 || align_loops > 0)) -+ count += MAX (align_jumps, align_loops); -+ else -+ count += get_attr_length (from); - - /* If there is a jump table, add its length. */ - tmp = is_jump_table (from); -@@ -9867,6 +11060,8 @@ - insn = table; - } - } -+ else if (LABEL_P (insn) && (align_jumps > 0 || align_loops > 0)) -+ address += MAX (align_jumps, align_loops); - } - - fix = minipool_fix_head; -@@ -10072,6 +11267,21 @@ - vfp_output_fldmd (FILE * stream, unsigned int base, int reg, int count) - { - int i; -+ int offset; -+ -+ if (low_irq_latency) -+ { -+ /* Output a sequence of FLDD instructions. */ -+ offset = 0; -+ for (i = reg; i < reg + count; ++i, offset += 8) -+ { -+ fputc ('\t', stream); -+ asm_fprintf (stream, "fldd\td%d, [%r,#%d]\n", i, base, offset); -+ } -+ asm_fprintf (stream, "\tadd\tsp, sp, #%d\n", count * 8); -+ return; -+ } -+ - - /* Workaround ARM10 VFPr1 bug. */ - if (count == 2 && !arm_arch6) -@@ -10142,6 +11352,56 @@ - rtx tmp, reg; - int i; - -+ if (low_irq_latency) -+ { -+ int saved_size; -+ rtx sp_insn; -+ -+ if (!count) -+ return 0; -+ -+ saved_size = count * GET_MODE_SIZE (DFmode); -+ -+ /* Since fstd does not have postdecrement addressing mode, -+ we first decrement stack pointer and then use base+offset -+ stores for VFP registers. The ARM EABI unwind information -+ can't easily describe base+offset loads, so we attach -+ a note for the effects of the whole block in the first insn, -+ and avoid marking the subsequent instructions -+ with RTX_FRAME_RELATED_P. */ -+ sp_insn = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, -+ GEN_INT (-saved_size)); -+ sp_insn = emit_insn (sp_insn); -+ RTX_FRAME_RELATED_P (sp_insn) = 1; -+ -+ dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1)); -+ XVECEXP (dwarf, 0, 0) = -+ gen_rtx_SET (VOIDmode, stack_pointer_rtx, -+ plus_constant (stack_pointer_rtx, -saved_size)); -+ -+ /* push double VFP registers to stack */ -+ for (i = 0; i < count; ++i ) -+ { -+ rtx reg; -+ rtx mem; -+ rtx addr; -+ rtx insn; -+ reg = gen_rtx_REG (DFmode, base_reg + 2*i); -+ addr = (i == 0) ? stack_pointer_rtx -+ : gen_rtx_PLUS (SImode, stack_pointer_rtx, -+ GEN_INT (i * GET_MODE_SIZE (DFmode))); -+ mem = gen_frame_mem (DFmode, addr); -+ insn = emit_move_insn (mem, reg); -+ XVECEXP (dwarf, 0, i+1) = -+ gen_rtx_SET (VOIDmode, mem, reg); -+ } -+ -+ REG_NOTES (sp_insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf, -+ REG_NOTES (sp_insn)); -+ -+ return saved_size; -+ } -+ - /* Workaround ARM10 VFPr1 bug. Data corruption can occur when exactly two - register pairs are stored by a store multiple insn. We avoid this - by pushing an extra pair. */ -@@ -10758,7 +12018,7 @@ - } - - /* Output a move, load or store for quad-word vectors in ARM registers. Only -- handles MEMs accepted by neon_vector_mem_operand with CORE=true. */ -+ handles MEMs accepted by neon_vector_mem_operand with TYPE=1. */ - - const char * - output_move_quad (rtx *operands) -@@ -10954,6 +12214,12 @@ - ops[1] = reg; - break; - -+ case PRE_DEC: -+ templ = "v%smdb%%?\t%%0!, %%h1"; -+ ops[0] = XEXP (addr, 0); -+ ops[1] = reg; -+ break; -+ - case POST_MODIFY: - /* FIXME: Not currently enabled in neon_vector_mem_operand. */ - gcc_unreachable (); -@@ -10968,7 +12234,7 @@ - { - /* We're only using DImode here because it's a convenient size. */ - ops[0] = gen_rtx_REG (DImode, REGNO (reg) + 2 * i); -- ops[1] = adjust_address (mem, SImode, 8 * i); -+ ops[1] = adjust_address (mem, DImode, 8 * i); - if (reg_overlap_mentioned_p (ops[0], mem)) - { - gcc_assert (overlap == -1); -@@ -11557,7 +12823,7 @@ - if (count > 0) - { - /* Workaround ARM10 VFPr1 bug. */ -- if (count == 2 && !arm_arch6) -+ if (count == 2 && !arm_arch6 && !low_irq_latency) - count++; - saved += count * 8; - } -@@ -11886,6 +13152,41 @@ - return_used_this_function = 0; - } - -+/* Generate to STREAM a code sequence that pops registers identified -+ in REGS_MASK from SP. SP is incremented as the result. -+*/ -+static void -+print_pop_reg_by_ldr (FILE *stream, int regs_mask, int rfe) -+{ -+ int reg; -+ -+ gcc_assert (! (regs_mask & (1 << SP_REGNUM))); -+ -+ for (reg = 0; reg < PC_REGNUM; ++reg) -+ if (regs_mask & (1 << reg)) -+ asm_fprintf (stream, "\tldr\t%r, [%r], #4\n", -+ reg, SP_REGNUM); -+ -+ if (regs_mask & (1 << PC_REGNUM)) -+ { -+ if (rfe) -+ /* When returning from exception, we need to -+ copy SPSR to CPSR. There are two ways to do -+ that: the ldm instruction with "^" suffix, -+ and movs instruction. The latter would -+ require that we load from stack to some -+ scratch register, and then move to PC. -+ Therefore, we'd need extra instruction and -+ have to make sure we actually have a spare -+ register. Using ldm with a single register -+ is simler. */ -+ asm_fprintf (stream, "\tldm\tsp!, {pc}^\n"); -+ else -+ asm_fprintf (stream, "\tldr\t%r, [%r], #4\n", -+ PC_REGNUM, SP_REGNUM); -+ } -+} -+ - const char * - arm_output_epilogue (rtx sibling) - { -@@ -11946,7 +13247,7 @@ - /* This variable is for the Virtual Frame Pointer, not VFP regs. */ - int vfp_offset = offsets->frame; - -- if (arm_fpu_arch == FPUTYPE_FPA_EMU2) -+ if (TARGET_FPA_EMU2) - { - for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--) - if (df_regs_ever_live_p (reg) && !call_used_regs[reg]) -@@ -12169,7 +13470,7 @@ - SP_REGNUM, HARD_FRAME_POINTER_REGNUM); - } - -- if (arm_fpu_arch == FPUTYPE_FPA_EMU2) -+ if (TARGET_FPA_EMU2) - { - for (reg = FIRST_FPA_REGNUM; reg <= LAST_FPA_REGNUM; reg++) - if (df_regs_ever_live_p (reg) && !call_used_regs[reg]) -@@ -12253,22 +13554,19 @@ - to load use the LDR instruction - it is faster. For Thumb-2 - always use pop and the assembler will pick the best instruction.*/ - if (TARGET_ARM && saved_regs_mask == (1 << LR_REGNUM) -- && !IS_INTERRUPT(func_type)) -+ && !IS_INTERRUPT (func_type)) - { - asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM); - } - else if (saved_regs_mask) - { -- if (saved_regs_mask & (1 << SP_REGNUM)) -- /* Note - write back to the stack register is not enabled -- (i.e. "ldmfd sp!..."). We know that the stack pointer is -- in the list of registers and if we add writeback the -- instruction becomes UNPREDICTABLE. */ -- print_multi_reg (f, "ldmfd\t%r, ", SP_REGNUM, saved_regs_mask, -- rfe); -- else if (TARGET_ARM) -- print_multi_reg (f, "ldmfd\t%r!, ", SP_REGNUM, saved_regs_mask, -- rfe); -+ gcc_assert ( ! (saved_regs_mask & (1 << SP_REGNUM))); -+ if (TARGET_ARM) -+ if (low_irq_latency) -+ print_pop_reg_by_ldr (f, saved_regs_mask, rfe); -+ else -+ print_multi_reg (f, "ldmfd\t%r!, ", SP_REGNUM, saved_regs_mask, -+ rfe); - else - print_multi_reg (f, "pop\t", SP_REGNUM, saved_regs_mask, 0); - } -@@ -12389,6 +13687,32 @@ - - gcc_assert (num_regs && num_regs <= 16); - -+ if (low_irq_latency) -+ { -+ rtx insn = 0; -+ -+ /* Emit a series of ldr instructions rather rather than a single ldm. */ -+ /* TODO: Use ldrd where possible. */ -+ gcc_assert (! (mask & (1 << SP_REGNUM))); -+ -+ for (i = LAST_ARM_REGNUM; i >= 0; --i) -+ { -+ if (mask & (1 << i)) -+ -+ { -+ rtx reg, where, mem; -+ -+ reg = gen_rtx_REG (SImode, i); -+ where = gen_rtx_PRE_DEC (SImode, stack_pointer_rtx); -+ mem = gen_rtx_MEM (SImode, where); -+ insn = emit_move_insn (mem, reg); -+ RTX_FRAME_RELATED_P (insn) = 1; -+ } -+ } -+ -+ return insn; -+ } -+ - /* We don't record the PC in the dwarf frame information. */ - num_dwarf_regs = num_regs; - if (mask & (1 << PC_REGNUM)) -@@ -12737,22 +14061,23 @@ - { - int reg = -1; - -- for (i = 4; i <= (TARGET_THUMB1 ? LAST_LO_REGNUM : 11); i++) -- { -- if ((offsets->saved_regs_mask & (1 << i)) == 0) -- { -- reg = i; -- break; -- } -- } -- -- if (reg == -1 && arm_size_return_regs () <= 12 -- && !crtl->tail_call_emit) -+ /* If it is safe to use r3, then do so. This sometimes -+ generates better code on Thumb-2 by avoiding the need to -+ use 32-bit push/pop instructions. */ -+ if (!crtl->tail_call_emit -+ && arm_size_return_regs () <= 12) - { -- /* Push/pop an argument register (r3) if all callee saved -- registers are already being pushed. */ - reg = 3; - } -+ else -+ for (i = 4; i <= (TARGET_THUMB1 ? LAST_LO_REGNUM : 11); i++) -+ { -+ if ((offsets->saved_regs_mask & (1 << i)) == 0) -+ { -+ reg = i; -+ break; -+ } -+ } - - if (reg != -1) - { -@@ -12876,7 +14201,7 @@ - - /* Save any floating point call-saved registers used by this - function. */ -- if (arm_fpu_arch == FPUTYPE_FPA_EMU2) -+ if (TARGET_FPA_EMU2) - { - for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--) - if (df_regs_ever_live_p (reg) && !call_used_regs[reg]) -@@ -13483,7 +14808,11 @@ - { - fprintf (stream, ", %s ", shift); - if (val == -1) -- arm_print_operand (stream, XEXP (x, 1), 0); -+ { -+ arm_print_operand (stream, XEXP (x, 1), 0); -+ if (janus2_code) -+ fprintf(stream, "\n\tnop"); -+ } - else - fprintf (stream, "#" HOST_WIDE_INT_PRINT_DEC, val); - } -@@ -13704,6 +15033,30 @@ - } - return; - -+ /* Print the high single-precision register of a VFP double-precision -+ register. */ -+ case 'p': -+ { -+ int mode = GET_MODE (x); -+ int regno; -+ -+ if (GET_MODE_SIZE (mode) != 8 || GET_CODE (x) != REG) -+ { -+ output_operand_lossage ("invalid operand for code '%c'", code); -+ return; -+ } -+ -+ regno = REGNO (x); -+ if (!VFP_REGNO_OK_FOR_DOUBLE (regno)) -+ { -+ output_operand_lossage ("invalid operand for code '%c'", code); -+ return; -+ } -+ -+ fprintf (stream, "s%d", regno - FIRST_VFP_REGNUM + 1); -+ } -+ return; -+ - /* Print a VFP/Neon double precision or quad precision register name. */ - case 'P': - case 'q': -@@ -13821,6 +15174,57 @@ - } - return; - -+ /* Memory operand for vld1/vst1 instruction. */ -+ case 'A': -+ { -+ rtx addr; -+ bool postinc = FALSE; -+ unsigned align; -+ -+ gcc_assert (GET_CODE (x) == MEM); -+ addr = XEXP (x, 0); -+ if (GET_CODE (addr) == POST_INC) -+ { -+ postinc = 1; -+ addr = XEXP (addr, 0); -+ } -+ align = MEM_ALIGN (x) >> 3; -+ asm_fprintf (stream, "[%r", REGNO (addr)); -+ if (align > GET_MODE_SIZE (GET_MODE (x))) -+ align = GET_MODE_SIZE (GET_MODE (x)); -+ if (align >= 8) -+ asm_fprintf (stream, ", :%d", align << 3); -+ asm_fprintf (stream, "]"); -+ if (postinc) -+ fputs("!", stream); -+ } -+ return; -+ -+ /* Register specifier for vld1.16/vst1.16. Translate the S register -+ number into a D register number and element index. */ -+ case 'z': -+ { -+ int mode = GET_MODE (x); -+ int regno; -+ -+ if (GET_MODE_SIZE (mode) != 2 || GET_CODE (x) != REG) -+ { -+ output_operand_lossage ("invalid operand for code '%c'", code); -+ return; -+ } -+ -+ regno = REGNO (x); -+ if (!VFP_REGNO_OK_FOR_SINGLE (regno)) -+ { -+ output_operand_lossage ("invalid operand for code '%c'", code); -+ return; -+ } -+ -+ regno = regno - FIRST_VFP_REGNUM; -+ fprintf (stream, "d%d[%d]", regno/2, ((regno % 2) ? 2 : 0)); -+ } -+ return; -+ - default: - if (x == 0) - { -@@ -13854,6 +15258,12 @@ - default: - gcc_assert (GET_CODE (x) != NEG); - fputc ('#', stream); -+ if (GET_CODE (x) == HIGH) -+ { -+ fputs (":lower16:", stream); -+ x = XEXP (x, 0); -+ } -+ - output_addr_const (stream, x); - break; - } -@@ -14245,6 +15655,10 @@ - first insn after the following code_label if REVERSE is true. */ - rtx start_insn = insn; - -+ /* Don't do this if we're not considering conditional execution. */ -+ if (TARGET_NO_SINGLE_COND_EXEC) -+ return; -+ - /* If in state 4, check if the target branch is reached, in order to - change back to state 0. */ - if (arm_ccfsm_state == 4) -@@ -14618,6 +16032,11 @@ - if (mode == DFmode) - return VFP_REGNO_OK_FOR_DOUBLE (regno); - -+ /* VFP registers can hold HFmode values, but there is no point in -+ putting them there unless we have hardware conversion insns. */ -+ if (mode == HFmode) -+ return TARGET_FP16 && VFP_REGNO_OK_FOR_SINGLE (regno); -+ - if (TARGET_NEON) - return (VALID_NEON_DREG_MODE (mode) && VFP_REGNO_OK_FOR_DOUBLE (regno)) - || (VALID_NEON_QREG_MODE (mode) -@@ -14637,16 +16056,16 @@ - return mode == SImode; - - if (IS_IWMMXT_REGNUM (regno)) -- return VALID_IWMMXT_REG_MODE (mode); -+ return VALID_IWMMXT_REG_MODE (mode) && mode != SImode; - } - -- /* We allow any value to be stored in the general registers. -+ /* We allow almost any value to be stored in the general registers. - Restrict doubleword quantities to even register pairs so that we can -- use ldrd. Do not allow Neon structure opaque modes in general registers; -- they would use too many. */ -+ use ldrd. Do not allow very large Neon structure opaque modes in -+ general registers; they would use too many. */ - if (regno <= LAST_ARM_REGNUM) - return !(TARGET_LDRD && GET_MODE_SIZE (mode) > 4 && (regno & 1) != 0) -- && !VALID_NEON_STRUCT_MODE (mode); -+ && ARM_NUM_REGS (mode) <= 4; - - if (regno == FRAME_POINTER_REGNUM - || regno == ARG_POINTER_REGNUM) -@@ -16103,6 +17522,15 @@ - } - - static void -+arm_init_fp16_builtins (void) -+{ -+ tree fp16_type = make_node (REAL_TYPE); -+ TYPE_PRECISION (fp16_type) = 16; -+ layout_type (fp16_type); -+ (*lang_hooks.types.register_builtin_type) (fp16_type, "__fp16"); -+} -+ -+static void - arm_init_builtins (void) - { - arm_init_tls_builtins (); -@@ -16112,6 +17540,71 @@ - - if (TARGET_NEON) - arm_init_neon_builtins (); -+ -+ if (arm_fp16_format) -+ arm_init_fp16_builtins (); -+} -+ -+/* Implement TARGET_INVALID_PARAMETER_TYPE. */ -+ -+static const char * -+arm_invalid_parameter_type (const_tree t) -+{ -+ if (SCALAR_FLOAT_TYPE_P (t) && TYPE_PRECISION (t) == 16) -+ return N_("function parameters cannot have __fp16 type"); -+ return NULL; -+} -+ -+/* Implement TARGET_INVALID_PARAMETER_TYPE. */ -+ -+static const char * -+arm_invalid_return_type (const_tree t) -+{ -+ if (SCALAR_FLOAT_TYPE_P (t) && TYPE_PRECISION (t) == 16) -+ return N_("functions cannot return __fp16 type"); -+ return NULL; -+} -+ -+/* Implement TARGET_PROMOTED_TYPE. */ -+ -+static tree -+arm_promoted_type (const_tree t) -+{ -+ if (SCALAR_FLOAT_TYPE_P (t) && TYPE_PRECISION (t) == 16) -+ return float_type_node; -+ return NULL_TREE; -+} -+ -+/* Implement TARGET_CONVERT_TO_TYPE. -+ Specifically, this hook implements the peculiarity of the ARM -+ half-precision floating-point C semantics that requires conversions between -+ __fp16 to or from double to do an intermediate conversion to float. */ -+ -+static tree -+arm_convert_to_type (tree type, tree expr) -+{ -+ tree fromtype = TREE_TYPE (expr); -+ if (!SCALAR_FLOAT_TYPE_P (fromtype) || !SCALAR_FLOAT_TYPE_P (type)) -+ return NULL_TREE; -+ if ((TYPE_PRECISION (fromtype) == 16 && TYPE_PRECISION (type) > 32) -+ || (TYPE_PRECISION (type) == 16 && TYPE_PRECISION (fromtype) > 32)) -+ return convert (type, convert (float_type_node, expr)); -+ return NULL_TREE; -+} -+ -+/* Implement TARGET_SCALAR_MODE_SUPPORTED_P. -+ This simply adds HFmode as a supported mode; even though we don't -+ implement arithmetic on this type directly, it's supported by -+ optabs conversions, much the way the double-word arithmetic is -+ special-cased in the default hook. */ -+ -+static bool -+arm_scalar_mode_supported_p (enum machine_mode mode) -+{ -+ if (mode == HFmode) -+ return (arm_fp16_format != ARM_FP16_FORMAT_NONE); -+ else -+ return default_scalar_mode_supported_p (mode); - } - - /* Errors in the source file can cause expand_expr to return const0_rtx -@@ -17191,6 +18684,7 @@ - unsigned HOST_WIDE_INT mask = 0xff; - int i; - -+ val = val & (unsigned HOST_WIDE_INT)0xffffffffu; - if (val == 0) /* XXX */ - return 0; - -@@ -18279,40 +19773,8 @@ - else - { - int set_float_abi_attributes = 0; -- switch (arm_fpu_arch) -- { -- case FPUTYPE_FPA: -- fpu_name = "fpa"; -- break; -- case FPUTYPE_FPA_EMU2: -- fpu_name = "fpe2"; -- break; -- case FPUTYPE_FPA_EMU3: -- fpu_name = "fpe3"; -- break; -- case FPUTYPE_MAVERICK: -- fpu_name = "maverick"; -- break; -- case FPUTYPE_VFP: -- fpu_name = "vfp"; -- set_float_abi_attributes = 1; -- break; -- case FPUTYPE_VFP3D16: -- fpu_name = "vfpv3-d16"; -- set_float_abi_attributes = 1; -- break; -- case FPUTYPE_VFP3: -- fpu_name = "vfpv3"; -- set_float_abi_attributes = 1; -- break; -- case FPUTYPE_NEON: -- fpu_name = "neon"; -- set_float_abi_attributes = 1; -- break; -- default: -- abort(); -- } -- if (set_float_abi_attributes) -+ fpu_name = arm_fpu_desc->name; -+ if (arm_fp_model == ARM_FP_MODEL_VFP) - { - if (TARGET_HARD_FLOAT) - asm_fprintf (asm_out_file, "\t.eabi_attribute 27, 3\n"); -@@ -18362,6 +19824,11 @@ - val = 6; - asm_fprintf (asm_out_file, "\t.eabi_attribute 30, %d\n", val); - -+ /* Tag_ABI_FP_16bit_format. */ -+ if (arm_fp16_format) -+ asm_fprintf (asm_out_file, "\t.eabi_attribute 38, %d\n", -+ (int)arm_fp16_format); -+ - if (arm_lang_output_object_attributes_hook) - arm_lang_output_object_attributes_hook(); - } -@@ -18591,6 +20058,23 @@ - return 1; - } - -+/* Emit a fp16 constant appropriately padded to occupy a 4-byte word. -+ HFmode constant pool entries are actually loaded with ldr. */ -+void -+arm_emit_fp16_const (rtx c) -+{ -+ REAL_VALUE_TYPE r; -+ long bits; -+ -+ REAL_VALUE_FROM_CONST_DOUBLE (r, c); -+ bits = real_to_target (NULL, &r, HFmode); -+ if (WORDS_BIG_ENDIAN) -+ assemble_zeros (2); -+ assemble_integer (GEN_INT (bits), 2, BITS_PER_WORD, 1); -+ if (!WORDS_BIG_ENDIAN) -+ assemble_zeros (2); -+} -+ - const char * - arm_output_load_gr (rtx *operands) - { -@@ -18628,19 +20112,24 @@ - that way. */ - - static void --arm_setup_incoming_varargs (CUMULATIVE_ARGS *cum, -+arm_setup_incoming_varargs (CUMULATIVE_ARGS *pcum, - enum machine_mode mode, - tree type, - int *pretend_size, - int second_time ATTRIBUTE_UNUSED) - { -- int nregs = cum->nregs; -- if (nregs & 1 -- && ARM_DOUBLEWORD_ALIGN -- && arm_needs_doubleword_align (mode, type)) -- nregs++; -- -+ int nregs; -+ - cfun->machine->uses_anonymous_args = 1; -+ if (pcum->pcs_variant <= ARM_PCS_AAPCS_LOCAL) -+ { -+ nregs = pcum->aapcs_ncrn; -+ if ((nregs & 1) && arm_needs_doubleword_align (mode, type)) -+ nregs++; -+ } -+ else -+ nregs = pcum->nregs; -+ - if (nregs < NUM_ARG_REGS) - *pretend_size = (NUM_ARG_REGS - nregs) * UNITS_PER_WORD; - } -@@ -19024,9 +20513,10 @@ - || mode == V16QImode || mode == V4SFmode || mode == V2DImode)) - return true; - -- if ((mode == V2SImode) -- || (mode == V4HImode) -- || (mode == V8QImode)) -+ if ((TARGET_NEON || TARGET_IWMMXT) -+ && ((mode == V2SImode) -+ || (mode == V4HImode) -+ || (mode == V8QImode))) - return true; - - return false; -@@ -19057,9 +20547,14 @@ - if (IS_FPA_REGNUM (regno)) - return (TARGET_AAPCS_BASED ? 96 : 16) + regno - FIRST_FPA_REGNUM; - -- /* FIXME: VFPv3 register numbering. */ - if (IS_VFP_REGNUM (regno)) -- return 64 + regno - FIRST_VFP_REGNUM; -+ { -+ /* See comment in arm_dwarf_register_span. */ -+ if (VFP_REGNO_OK_FOR_SINGLE (regno)) -+ return 64 + regno - FIRST_VFP_REGNUM; -+ else -+ return 256 + (regno - FIRST_VFP_REGNUM) / 2; -+ } - - if (IS_IWMMXT_GR_REGNUM (regno)) - return 104 + regno - FIRST_IWMMXT_GR_REGNUM; -@@ -19070,6 +20565,39 @@ - gcc_unreachable (); - } - -+/* Dwarf models VFPv3 registers as 32 64-bit registers. -+ GCC models tham as 64 32-bit registers, so we need to describe this to -+ the DWARF generation code. Other registers can use the default. */ -+static rtx -+arm_dwarf_register_span(rtx rtl) -+{ -+ unsigned regno; -+ int nregs; -+ int i; -+ rtx p; -+ -+ regno = REGNO (rtl); -+ if (!IS_VFP_REGNUM (regno)) -+ return NULL_RTX; -+ -+ /* The EABI defines two VFP register ranges: -+ 64-95: Legacy VFPv2 numbering for S0-S31 (obsolescent) -+ 256-287: D0-D31 -+ The recommended encodings for s0-s31 is a DW_OP_bit_piece of the -+ corresponding D register. However gdb6.6 does not support this, so -+ we use the legacy encodings. We also use these encodings for D0-D15 -+ for compatibility with older debuggers. */ -+ if (VFP_REGNO_OK_FOR_SINGLE (regno)) -+ return NULL_RTX; -+ -+ nregs = GET_MODE_SIZE (GET_MODE (rtl)) / 8; -+ p = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc(nregs)); -+ regno = (regno - FIRST_VFP_REGNUM) / 2; -+ for (i = 0; i < nregs; i++) -+ XVECEXP (p, 0, i) = gen_rtx_REG (DImode, 256 + regno + i); -+ -+ return p; -+} - - #ifdef TARGET_UNWIND_INFO - /* Emit unwind directives for a store-multiple instruction or stack pointer -@@ -19556,6 +21084,7 @@ - case cortexr4f: - case cortexa8: - case cortexa9: -+ case marvell_f: - return 2; - - default: -@@ -19620,6 +21149,10 @@ - return "St9__va_list"; - } - -+ /* Half-precision float. */ -+ if (TREE_CODE (type) == REAL_TYPE && TYPE_PRECISION (type) == 16) -+ return "Dh"; -+ - if (TREE_CODE (type) != VECTOR_TYPE) - return NULL; - -@@ -19676,6 +21209,87 @@ - given on the command line. */ - if (level > 0) - flag_section_anchors = 2; -+ -+ if (size) -+ { -+ /* Select optimizations that are a win for code size. -+ -+ The inlining options set below have two important -+ consequences for functions not explicitly marked -+ inline: -+ - Static functions used once are inlined if -+ sufficiently small. Static functions used twice -+ are not inlined. -+ - Non-static functions are never inlined. -+ So in effect, inlining will never cause two copies -+ of function bodies to be created. */ -+ /* Empirical results show that these options benefit code -+ size on arm. */ -+ /* FIXME: -fsee seems to be broken for Thumb-2. */ -+ /* flag_see = 1; */ -+ flag_move_loop_invariants = 0; -+ /* In Thumb mode the function call code size overhead is typically very -+ small, and narrow branch instructions have very limited range. -+ Inlining even medium sized functions tends to bloat the caller and -+ require the use of long branch instructions. On average the long -+ branches cost more than eliminating the function call overhead saves, -+ so we use extremely restrictive automatic inlining heuristics. In ARM -+ mode the results are fairly neutral, probably due to better constant -+ pool placement. */ -+ set_param_value ("max-inline-insns-single", 1); -+ set_param_value ("max-inline-insns-auto", 1); -+ } -+ else -+ { -+ /* CSL LOCAL */ -+ /* Set flag_unroll_loops to a default value, so that we can tell -+ if it was specified on the command line; see -+ arm_override_options. */ -+ flag_unroll_loops = 2; -+ /* Promote loop indices to int where possible. Consider moving this -+ to -Os, also. */ -+ flag_promote_loop_indices = 1; -+ } -+} -+ -+/* Return how many instructions to look ahead for better insn -+ scheduling. */ -+static int -+arm_multipass_dfa_lookahead (void) -+{ -+ return (arm_tune == marvell_f) ? 4 : 0; -+} -+ -+/* Return the minimum alignment required to load or store a -+ vector of the given type, which may be less than the -+ natural alignment of the type. */ -+ -+static int -+arm_vector_min_alignment (const_tree type) -+{ -+ if (TARGET_NEON) -+ { -+ /* The NEON element load and store instructions only require the -+ alignment of the element type. They can benefit from higher -+ statically reported alignment, but we do not take advantage -+ of that yet. */ -+ gcc_assert (TREE_CODE (type) == VECTOR_TYPE); -+ return TYPE_ALIGN_UNIT (TREE_TYPE (type)); -+ } -+ -+ return default_vector_min_alignment (type); -+} -+ -+static bool -+arm_vector_always_misalign(const_tree type ATTRIBUTE_UNUSED) -+{ -+ /* On big-endian targets array loads (vld1) and vector loads (vldm) -+ use a different format. Always use the "misaligned" array variant. -+ FIXME: this still doesn't work for big-endian because of constant -+ loads and other operations using vldm ordering. See -+ issue 6722. */ -+ return TARGET_NEON && !BYTES_BIG_ENDIAN; - } - - #include "gt-arm.h" -+ ---- a/gcc/config/arm/arm-cores.def -+++ b/gcc/config/arm/arm-cores.def -@@ -104,6 +104,7 @@ - ARM_CORE("xscale", xscale, 5TE, FL_LDSCHED | FL_STRONG | FL_XSCALE, xscale) - ARM_CORE("iwmmxt", iwmmxt, 5TE, FL_LDSCHED | FL_STRONG | FL_XSCALE | FL_IWMMXT, xscale) - ARM_CORE("iwmmxt2", iwmmxt2, 5TE, FL_LDSCHED | FL_STRONG | FL_XSCALE | FL_IWMMXT, xscale) -+ARM_CORE("marvell-f", marvell_f, 5TE, FL_LDSCHED | FL_VFPV2 | FL_MARVELL_F, 9e) - - /* V5TEJ Architecture Processors */ - ARM_CORE("arm926ej-s", arm926ejs, 5TEJ, FL_LDSCHED, 9e) -@@ -117,9 +118,13 @@ - ARM_CORE("mpcorenovfp", mpcorenovfp, 6K, FL_LDSCHED, 9e) - ARM_CORE("mpcore", mpcore, 6K, FL_LDSCHED | FL_VFPV2, 9e) - ARM_CORE("arm1156t2-s", arm1156t2s, 6T2, FL_LDSCHED, 9e) -+ -+/* V7 Architecture Processors */ -+ARM_CORE("cortex-a5", cortexa5, 7A, FL_LDSCHED, 9e) - ARM_CORE("cortex-a8", cortexa8, 7A, FL_LDSCHED, 9e) - ARM_CORE("cortex-a9", cortexa9, 7A, FL_LDSCHED, 9e) - ARM_CORE("cortex-r4", cortexr4, 7R, FL_LDSCHED, 9e) - ARM_CORE("cortex-r4f", cortexr4f, 7R, FL_LDSCHED, 9e) - ARM_CORE("cortex-m3", cortexm3, 7M, FL_LDSCHED, 9e) - ARM_CORE("cortex-m1", cortexm1, 6M, FL_LDSCHED, 9e) -+ARM_CORE("cortex-m0", cortexm0, 6M, FL_LDSCHED, 9e) ---- a/gcc/config/arm/arm.h -+++ b/gcc/config/arm/arm.h -@@ -85,6 +85,10 @@ - builtin_define ("__IWMMXT__"); \ - if (TARGET_AAPCS_BASED) \ - builtin_define ("__ARM_EABI__"); \ -+ if (arm_tune_marvell_f) \ -+ builtin_define ("__ARM_TUNE_MARVELL_F__"); \ -+ if (low_irq_latency) \ -+ builtin_define ("__low_irq_latency__"); \ - } while (0) - - /* The various ARM cores. */ -@@ -199,6 +203,13 @@ - #define TARGET_AAPCS_BASED \ - (arm_abi != ARM_ABI_APCS && arm_abi != ARM_ABI_ATPCS) - -+/* True if we should avoid generating conditional execution instructions. */ -+#define TARGET_NO_COND_EXEC (arm_tune_marvell_f && !optimize_size) -+/* Avoid most conditional instructions, but allow pairs with opposite -+ conditions and the same destination. */ -+#define TARGET_NO_SINGLE_COND_EXEC \ -+ ((arm_tune_cortex_a9 || arm_tune_marvell_f) && !optimize_size) -+ - #define TARGET_HARD_TP (target_thread_pointer == TP_CP15) - #define TARGET_SOFT_TP (target_thread_pointer == TP_SOFT) - -@@ -211,35 +222,43 @@ - /* Thumb-1 only. */ - #define TARGET_THUMB1_ONLY (TARGET_THUMB1 && !arm_arch_notm) - -+#define TARGET_FPA_EMU2 (TARGET_FPA && arm_fpu_desc->rev == 2) - /* The following two macros concern the ability to execute coprocessor - instructions for VFPv3 or NEON. TARGET_VFP3/TARGET_VFPD32 are currently - only ever tested when we know we are generating for VFP hardware; we need - to be more careful with TARGET_NEON as noted below. */ - - /* FPU is has the full VFPv3/NEON register file of 32 D registers. */ --#define TARGET_VFPD32 (arm_fp_model == ARM_FP_MODEL_VFP \ -- && (arm_fpu_arch == FPUTYPE_VFP3 \ -- || arm_fpu_arch == FPUTYPE_NEON)) -+#define TARGET_VFPD32 (TARGET_VFP && arm_arch_vfp_regs == VFP_REG_D32) - - /* FPU supports VFPv3 instructions. */ --#define TARGET_VFP3 (arm_fp_model == ARM_FP_MODEL_VFP \ -- && (arm_fpu_arch == FPUTYPE_VFP3D16 \ -- || TARGET_VFPD32)) -+#define TARGET_VFP3 (TARGET_VFP && arm_arch_vfp_rev >= 3) -+ -+/* FPU only supports VFP single-precision instructions. */ -+#define TARGET_VFP_SINGLE (TARGET_VFP && arm_arch_vfp_regs == VFP_REG_SINGLE) -+ -+/* FPU supports VFP double-precision instructions. */ -+#define TARGET_VFP_DOUBLE (TARGET_VFP && arm_arch_vfp_regs != VFP_REG_SINGLE) -+ -+/* FPU supports half-precision floating-point with NEON element load/store. */ -+#define TARGET_NEON_FP16 (TARGET_VFP && arm_arch_vfp_neon && arm_arch_vfp_fp16) -+ -+/* FPU supports VFP half-precision floating-point. */ -+#define TARGET_FP16 (TARGET_VFP && arm_arch_vfp_fp16) - - /* FPU supports Neon instructions. The setting of this macro gets - revealed via __ARM_NEON__ so we add extra guards upon TARGET_32BIT - and TARGET_HARD_FLOAT to ensure that NEON instructions are - available. */ - #define TARGET_NEON (TARGET_32BIT && TARGET_HARD_FLOAT \ -- && arm_fp_model == ARM_FP_MODEL_VFP \ -- && arm_fpu_arch == FPUTYPE_NEON) -+ && TARGET_VFP && arm_arch_vfp_neon) - - /* "DSP" multiply instructions, eg. SMULxy. */ - #define TARGET_DSP_MULTIPLY \ -- (TARGET_32BIT && arm_arch5e && arm_arch_notm) -+ (TARGET_32BIT && arm_arch5e && (arm_arch_notm || arm_arch7em)) - /* Integer SIMD instructions, and extend-accumulate instructions. */ - #define TARGET_INT_SIMD \ -- (TARGET_32BIT && arm_arch6 && arm_arch_notm) -+ (TARGET_32BIT && arm_arch6 && (arm_arch_notm || arm_arch7em)) - - /* Should MOVW/MOVT be used in preference to a constant pool. */ - #define TARGET_USE_MOVT (arm_arch_thumb2 && !optimize_size) -@@ -289,40 +308,30 @@ - ARM_FP_MODEL_VFP - }; - --extern enum arm_fp_model arm_fp_model; -- --/* Which floating point hardware is available. Also update -- fp_model_for_fpu in arm.c when adding entries to this list. */ --enum fputype --{ -- /* No FP hardware. */ -- FPUTYPE_NONE, -- /* Full FPA support. */ -- FPUTYPE_FPA, -- /* Emulated FPA hardware, Issue 2 emulator (no LFM/SFM). */ -- FPUTYPE_FPA_EMU2, -- /* Emulated FPA hardware, Issue 3 emulator. */ -- FPUTYPE_FPA_EMU3, -- /* Cirrus Maverick floating point co-processor. */ -- FPUTYPE_MAVERICK, -- /* VFP. */ -- FPUTYPE_VFP, -- /* VFPv3-D16. */ -- FPUTYPE_VFP3D16, -- /* VFPv3. */ -- FPUTYPE_VFP3, -- /* Neon. */ -- FPUTYPE_NEON -+enum vfp_reg_type { -+ VFP_REG_D16, -+ VFP_REG_D32, -+ VFP_REG_SINGLE - }; - --/* Recast the floating point class to be the floating point attribute. */ --#define arm_fpu_attr ((enum attr_fpu) arm_fpu_tune) -- --/* What type of floating point to tune for */ --extern enum fputype arm_fpu_tune; -+extern const struct arm_fpu_desc -+{ -+ const char *name; -+ enum arm_fp_model model; -+ int rev; -+ enum vfp_reg_type myregs; -+ int neon; -+ int fp16; -+} *arm_fpu_desc; -+ -+#define arm_fp_model arm_fpu_desc->model -+#define arm_arch_vfp_rev arm_fpu_desc->rev -+#define arm_arch_vfp_regs arm_fpu_desc->myregs -+#define arm_arch_vfp_neon arm_fpu_desc->neon -+#define arm_arch_vfp_fp16 arm_fpu_desc->fp16 - --/* What type of floating point instructions are available */ --extern enum fputype arm_fpu_arch; -+/* Which floating point hardware to schedule for. */ -+extern int arm_fpu_attr; - - enum float_abi_type - { -@@ -337,6 +346,21 @@ - #define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_SOFT - #endif - -+/* Which __fp16 format to use. -+ The enumeration values correspond to the numbering for the -+ Tag_ABI_FP_16bit_format attribute. -+ */ -+enum arm_fp16_format_type -+{ -+ ARM_FP16_FORMAT_NONE = 0, -+ ARM_FP16_FORMAT_IEEE = 1, -+ ARM_FP16_FORMAT_ALTERNATIVE = 2 -+}; -+ -+extern enum arm_fp16_format_type arm_fp16_format; -+#define LARGEST_EXPONENT_IS_NORMAL(bits) \ -+ ((bits) == 16 && arm_fp16_format == ARM_FP16_FORMAT_ALTERNATIVE) -+ - /* Which ABI to use. */ - enum arm_abi_type - { -@@ -383,12 +407,18 @@ - /* Nonzero if instructions not present in the 'M' profile can be used. */ - extern int arm_arch_notm; - -+/* Nonzero if instructions present in ARMv7E-M can be used. */ -+extern int arm_arch7em; -+ - /* Nonzero if this chip can benefit from load scheduling. */ - extern int arm_ld_sched; - - /* Nonzero if generating thumb code. */ - extern int thumb_code; - -+/* Nonzero if generating Janus2 code. */ -+extern int janus2_code; -+ - /* Nonzero if this chip is a StrongARM. */ - extern int arm_tune_strongarm; - -@@ -404,6 +434,9 @@ - /* Nonzero if tuning for XScale. */ - extern int arm_tune_xscale; - -+/* Nonzero if tuning for Marvell Feroceon. */ -+extern int arm_tune_marvell_f; -+ - /* Nonzero if tuning for stores via the write buffer. */ - extern int arm_tune_wbuf; - -@@ -423,6 +456,10 @@ - /* Nonzero if chip supports integer division instruction. */ - extern int arm_arch_hwdiv; - -+/* Nonzero if we should minimize interrupt latency of the -+ generated code. */ -+extern int low_irq_latency; -+ - #ifndef TARGET_DEFAULT - #define TARGET_DEFAULT (MASK_APCS_FRAME) - #endif -@@ -757,12 +794,11 @@ - fixed_regs[regno] = call_used_regs[regno] = 1; \ - } \ - \ -- if (TARGET_THUMB && optimize_size) \ -- { \ -- /* When optimizing for size, it's better not to use \ -- the HI regs, because of the overhead of stacking \ -- them. */ \ -- /* ??? Is this still true for thumb2? */ \ -+ if (TARGET_THUMB1 && optimize_size) \ -+ { \ -+ /* When optimizing for size on Thumb-1, it's better not \ -+ to use the HI regs, because of the overhead of \ -+ stacking them. */ \ - for (regno = FIRST_HI_REGNUM; \ - regno <= LAST_HI_REGNUM; ++regno) \ - fixed_regs[regno] = call_used_regs[regno] = 1; \ -@@ -881,6 +917,9 @@ - /* The number of (integer) argument register available. */ - #define NUM_ARG_REGS 4 - -+/* And similarly for the VFP. */ -+#define NUM_VFP_ARG_REGS 16 -+ - /* Return the register number of the N'th (integer) argument. */ - #define ARG_REGISTER(N) (N - 1) - -@@ -1059,7 +1098,7 @@ - (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2)) - - #define VALID_IWMMXT_REG_MODE(MODE) \ -- (arm_vector_mode_supported_p (MODE) || (MODE) == DImode) -+ (arm_vector_mode_supported_p (MODE) || (MODE) == DImode || (MODE) == SImode) - - /* Modes valid for Neon D registers. */ - #define VALID_NEON_DREG_MODE(MODE) \ -@@ -1230,11 +1269,14 @@ - || reg_classes_intersect_p (VFP_REGS, (CLASS)) \ - : 0) - --/* We need to define this for LO_REGS on thumb. Otherwise we can end up -- using r0-r4 for function arguments, r7 for the stack frame and don't -- have enough left over to do doubleword arithmetic. */ -+/* We need to define this for LO_REGS on Thumb-1. Otherwise we can end up -+ using r0-r4 for function arguments, r7 for the stack frame and don't have -+ enough left over to do doubleword arithmetic. For Thumb-2 all the -+ potentially problematic instructions accept high registers so this is not -+ necessary. Care needs to be taken to avoid adding new Thumb-2 patterns -+ that require many low registers. */ - #define CLASS_LIKELY_SPILLED_P(CLASS) \ -- ((TARGET_THUMB && (CLASS) == LO_REGS) \ -+ ((TARGET_THUMB1 && (CLASS) == LO_REGS) \ - || (CLASS) == CC_REG) - - /* The class value for index registers, and the one for base regs. */ -@@ -1245,7 +1287,7 @@ - when addressing quantities in QI or HI mode; if we don't know the - mode, then we must be conservative. */ - #define MODE_BASE_REG_CLASS(MODE) \ -- (TARGET_32BIT ? CORE_REGS : \ -+ (TARGET_32BIT ? (TARGET_THUMB2 ? LO_REGS : CORE_REGS) : \ - (((MODE) == SImode) ? BASE_REGS : LO_REGS)) - - /* For Thumb we can not support SP+reg addressing, so we return LO_REGS -@@ -1346,6 +1388,9 @@ - else if (TARGET_MAVERICK && TARGET_HARD_FLOAT) \ - /* Need to be careful, -256 is not a valid offset. */ \ - low = val >= 0 ? (val & 0xff) : -((-val) & 0xff); \ -+ else if (TARGET_REALLY_IWMMXT && MODE == SImode) \ -+ /* Need to be careful, -1024 is not a valid offset. */ \ -+ low = val >= 0 ? (val & 0x3ff) : -((-val) & 0x3ff); \ - else if (MODE == SImode \ - || (MODE == SFmode && TARGET_SOFT_FLOAT) \ - || ((MODE == HImode || MODE == QImode) && ! arm_arch4)) \ -@@ -1416,13 +1461,17 @@ - /* If defined, gives a class of registers that cannot be used as the - operand of a SUBREG that changes the mode of the object illegally. */ - --/* Moves between FPA_REGS and GENERAL_REGS are two memory insns. */ -+/* Moves between FPA_REGS and GENERAL_REGS are two memory insns. -+ Moves between VFP_REGS and GENERAL_REGS are a single insn, but -+ it is typically more expensive than a single memory access. We set -+ the cost to less than two memory accesses so that floating -+ point to integer conversion does not go through memory. */ - #define REGISTER_MOVE_COST(MODE, FROM, TO) \ - (TARGET_32BIT ? \ - ((FROM) == FPA_REGS && (TO) != FPA_REGS ? 20 : \ - (FROM) != FPA_REGS && (TO) == FPA_REGS ? 20 : \ -- IS_VFP_CLASS (FROM) && !IS_VFP_CLASS (TO) ? 10 : \ -- !IS_VFP_CLASS (FROM) && IS_VFP_CLASS (TO) ? 10 : \ -+ IS_VFP_CLASS (FROM) && !IS_VFP_CLASS (TO) ? 15 : \ -+ !IS_VFP_CLASS (FROM) && IS_VFP_CLASS (TO) ? 15 : \ - (FROM) == IWMMXT_REGS && (TO) != IWMMXT_REGS ? 4 : \ - (FROM) != IWMMXT_REGS && (TO) == IWMMXT_REGS ? 4 : \ - (FROM) == IWMMXT_GR_REGS || (TO) == IWMMXT_GR_REGS ? 20 : \ -@@ -1491,9 +1540,10 @@ - - /* Define how to find the value returned by a library function - assuming the value has mode MODE. */ --#define LIBCALL_VALUE(MODE) \ -- (TARGET_32BIT && TARGET_HARD_FLOAT_ABI && TARGET_FPA \ -- && GET_MODE_CLASS (MODE) == MODE_FLOAT \ -+#define LIBCALL_VALUE(MODE) \ -+ (TARGET_AAPCS_BASED ? aapcs_libcall_value (MODE) \ -+ : (TARGET_32BIT && TARGET_HARD_FLOAT_ABI && TARGET_FPA \ -+ && GET_MODE_CLASS (MODE) == MODE_FLOAT) \ - ? gen_rtx_REG (MODE, FIRST_FPA_REGNUM) \ - : TARGET_32BIT && TARGET_HARD_FLOAT_ABI && TARGET_MAVERICK \ - && GET_MODE_CLASS (MODE) == MODE_FLOAT \ -@@ -1502,22 +1552,16 @@ - ? gen_rtx_REG (MODE, FIRST_IWMMXT_REGNUM) \ - : gen_rtx_REG (MODE, ARG_REGISTER (1))) - --/* Define how to find the value returned by a function. -- VALTYPE is the data type of the value (as a tree). -- If the precise function being called is known, FUNC is its FUNCTION_DECL; -- otherwise, FUNC is 0. */ --#define FUNCTION_VALUE(VALTYPE, FUNC) \ -- arm_function_value (VALTYPE, FUNC); -- --/* 1 if N is a possible register number for a function value. -- On the ARM, only r0 and f0 can return results. */ --/* On a Cirrus chip, mvf0 can return results. */ --#define FUNCTION_VALUE_REGNO_P(REGNO) \ -- ((REGNO) == ARG_REGISTER (1) \ -- || (TARGET_32BIT && ((REGNO) == FIRST_CIRRUS_FP_REGNUM) \ -- && TARGET_HARD_FLOAT_ABI && TARGET_MAVERICK) \ -- || ((REGNO) == FIRST_IWMMXT_REGNUM && TARGET_IWMMXT_ABI) \ -- || (TARGET_32BIT && ((REGNO) == FIRST_FPA_REGNUM) \ -+/* 1 if REGNO is a possible register number for a function value. */ -+#define FUNCTION_VALUE_REGNO_P(REGNO) \ -+ ((REGNO) == ARG_REGISTER (1) \ -+ || (TARGET_AAPCS_BASED && TARGET_32BIT \ -+ && TARGET_VFP && TARGET_HARD_FLOAT \ -+ && (REGNO) == FIRST_VFP_REGNUM) \ -+ || (TARGET_32BIT && ((REGNO) == FIRST_CIRRUS_FP_REGNUM) \ -+ && TARGET_HARD_FLOAT_ABI && TARGET_MAVERICK) \ -+ || ((REGNO) == FIRST_IWMMXT_REGNUM && TARGET_IWMMXT_ABI) \ -+ || (TARGET_32BIT && ((REGNO) == FIRST_FPA_REGNUM) \ - && TARGET_HARD_FLOAT_ABI && TARGET_FPA)) - - /* Amount of memory needed for an untyped call to save all possible return -@@ -1617,9 +1661,27 @@ - that is in text_section. */ - extern GTY(()) rtx thumb_call_via_label[14]; - -+/* The number of potential ways of assigning to a co-processor. */ -+#define ARM_NUM_COPROC_SLOTS 1 -+ -+/* Enumeration of procedure calling standard variants. We don't really -+ support all of these yet. */ -+enum arm_pcs -+{ -+ ARM_PCS_AAPCS, /* Base standard AAPCS. */ -+ ARM_PCS_AAPCS_VFP, /* Use VFP registers for floating point values. */ -+ ARM_PCS_AAPCS_IWMMXT, /* Use iWMMXT registers for vectors. */ -+ /* This must be the last AAPCS variant. */ -+ ARM_PCS_AAPCS_LOCAL, /* Private call within this compilation unit. */ -+ ARM_PCS_ATPCS, /* ATPCS. */ -+ ARM_PCS_APCS, /* APCS (legacy Linux etc). */ -+ ARM_PCS_UNKNOWN -+}; -+ -+/* We can't define this inside a generator file because it needs enum -+ machine_mode. */ - /* A C type for declaring a variable that is used as the first argument of -- `FUNCTION_ARG' and other related values. For some target machines, the -- type `int' suffices and can hold the number of bytes of argument so far. */ -+ `FUNCTION_ARG' and other related values. */ - typedef struct - { - /* This is the number of registers of arguments scanned so far. */ -@@ -1628,9 +1690,33 @@ - int iwmmxt_nregs; - int named_count; - int nargs; -- int can_split; -+ /* Which procedure call variant to use for this call. */ -+ enum arm_pcs pcs_variant; -+ -+ /* AAPCS related state tracking. */ -+ int aapcs_arg_processed; /* No need to lay out this argument again. */ -+ int aapcs_cprc_slot; /* Index of co-processor rules to handle -+ this argument, or -1 if using core -+ registers. */ -+ int aapcs_ncrn; -+ int aapcs_next_ncrn; -+ rtx aapcs_reg; /* Register assigned to this argument. */ -+ int aapcs_partial; /* How many bytes are passed in regs (if -+ split between core regs and stack. -+ Zero otherwise. */ -+ int aapcs_cprc_failed[ARM_NUM_COPROC_SLOTS]; -+ int can_split; /* Argument can be split between core regs -+ and the stack. */ -+ /* Private data for tracking VFP register allocation */ -+ unsigned aapcs_vfp_regs_free; -+ unsigned aapcs_vfp_reg_alloc; -+ int aapcs_vfp_rcount; -+ /* Can't include insn-modes.h because this header is needed before we -+ generate it. */ -+ int /* enum machine_mode */ aapcs_vfp_rmode; - } CUMULATIVE_ARGS; - -+ - /* Define where to put the arguments to a function. - Value is zero to push the argument on the stack, - or a hard register in which to store the argument. -@@ -1674,13 +1760,7 @@ - of mode MODE and data type TYPE. - (TYPE is null for libcalls where that information may not be available.) */ - #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ -- (CUM).nargs += 1; \ -- if (arm_vector_mode_supported_p (MODE) \ -- && (CUM).named_count > (CUM).nargs \ -- && TARGET_IWMMXT_ABI) \ -- (CUM).iwmmxt_nregs += 1; \ -- else \ -- (CUM).nregs += ARM_NUM_REGS2 (MODE, TYPE) -+ arm_function_arg_advance (&(CUM), (MODE), (TYPE), (NAMED)) - - /* If defined, a C expression that gives the alignment boundary, in bits, of an - argument with the specified mode and type. If it is not defined, -@@ -1692,9 +1772,11 @@ - - /* 1 if N is a possible register number for function argument passing. - On the ARM, r0-r3 are used to pass args. */ --#define FUNCTION_ARG_REGNO_P(REGNO) \ -- (IN_RANGE ((REGNO), 0, 3) \ -- || (TARGET_IWMMXT_ABI \ -+#define FUNCTION_ARG_REGNO_P(REGNO) \ -+ (IN_RANGE ((REGNO), 0, 3) \ -+ || (TARGET_AAPCS_BASED && TARGET_VFP && TARGET_HARD_FLOAT \ -+ && IN_RANGE ((REGNO), FIRST_VFP_REGNUM, FIRST_VFP_REGNUM + 15)) \ -+ || (TARGET_IWMMXT_ABI \ - && IN_RANGE ((REGNO), FIRST_IWMMXT_REGNUM, FIRST_IWMMXT_REGNUM + 9))) - - -@@ -2324,7 +2406,8 @@ - /* Try to generate sequences that don't involve branches, we can then use - conditional instructions */ - #define BRANCH_COST(speed_p, predictable_p) \ -- (TARGET_32BIT ? 4 : (optimize > 0 ? 2 : 0)) -+ (TARGET_32BIT ? (TARGET_THUMB2 && optimize_size ? 1 : 4) \ -+ : (optimize > 0 ? 2 : 0)) - - /* Position Independent Code. */ - /* We decide which register to use based on the compilation options and -@@ -2392,6 +2475,7 @@ - - /* The arm5 clz instruction returns 32. */ - #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1) -+#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1) - - #undef ASM_APP_OFF - #define ASM_APP_OFF (TARGET_THUMB1 ? "\t.code\t16\n" : \ -@@ -2404,6 +2488,19 @@ - if (TARGET_ARM) \ - asm_fprintf (STREAM,"\tstmfd\t%r!,{%r}\n", \ - STACK_POINTER_REGNUM, REGNO); \ -+ else if (TARGET_THUMB1 \ -+ && (REGNO) == STATIC_CHAIN_REGNUM) \ -+ { \ -+ /* We can't push STATIC_CHAIN_REGNUM (r12) directly with Thumb-1. -+ We know that ASM_OUTPUT_REG_PUSH will be matched with -+ ASM_OUTPUT_REG_POP, and that r7 isn't used by the function -+ profiler, so we can use it as a scratch reg. WARNING: This isn't -+ safe in the general case! It may be sensitive to future changes -+ in final.c:profile_function. */ \ -+ asm_fprintf (STREAM, "\tpush\t{r7}\n"); \ -+ asm_fprintf (STREAM, "\tmov\tr7, %r\n", REGNO);\ -+ asm_fprintf (STREAM, "\tpush\t{r7}\n"); \ -+ } \ - else \ - asm_fprintf (STREAM, "\tpush {%r}\n", REGNO); \ - } while (0) -@@ -2415,6 +2512,14 @@ - if (TARGET_ARM) \ - asm_fprintf (STREAM, "\tldmfd\t%r!,{%r}\n", \ - STACK_POINTER_REGNUM, REGNO); \ -+ else if (TARGET_THUMB1 \ -+ && (REGNO) == STATIC_CHAIN_REGNUM) \ -+ { \ -+ /* See comment in ASM_OUTPUT_REG_PUSH. */ \ -+ asm_fprintf (STREAM, "\tpop\t{r7}\n"); \ -+ asm_fprintf (STREAM, "\tmov\t%r, r7\n", REGNO);\ -+ asm_fprintf (STREAM, "\tpop\t{r7}\n"); \ -+ } \ - else \ - asm_fprintf (STREAM, "\tpop {%r}\n", REGNO); \ - } while (0) ---- a/gcc/config/arm/arm.md -+++ b/gcc/config/arm/arm.md -@@ -99,6 +99,7 @@ - ; correctly for PIC usage. - (UNSPEC_GOTSYM_OFF 24) ; The offset of the start of the the GOT from a - ; a given symbolic address. -+ (UNSPEC_RBIT 25) ; rbit operation. - ] - ) - -@@ -131,6 +132,8 @@ - (VUNSPEC_WCMP_EQ 12) ; Used by the iWMMXt WCMPEQ instructions - (VUNSPEC_WCMP_GTU 13) ; Used by the iWMMXt WCMPGTU instructions - (VUNSPEC_WCMP_GT 14) ; Used by the iwMMXT WCMPGT instructions -+ (VUNSPEC_ALIGN16 15) ; Used to force 16-byte alignment. -+ (VUNSPEC_ALIGN32 16) ; Used to force 32-byte alignment. - (VUNSPEC_EH_RETURN 20); Use to override the return address for exception - ; handling. - ] -@@ -144,6 +147,10 @@ - ; patterns that share the same RTL in both ARM and Thumb code. - (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code"))) - -+; FIX_JANUS is set to 'yes' when compiling for Janus2, it causes to -+; add a nop after shifts, in order to work around a Janus2 bug -+(define_attr "fix_janus" "no,yes" (const (symbol_ref "janus2_code"))) -+ - ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects - ; scheduling decisions for the load unit and the multiplier. - (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm"))) -@@ -158,7 +165,7 @@ - ; Floating Point Unit. If we only have floating point emulation, then there - ; is no point in scheduling the floating point insns. (Well, for best - ; performance we should try and group them together). --(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp,vfpv3d16,vfpv3,neon" -+(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp" - (const (symbol_ref "arm_fpu_attr"))) - - ; LENGTH of an instruction (in bytes) -@@ -185,7 +192,7 @@ - ;; scheduling information. - - (define_attr "insn" -- "mov,mvn,smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,smmla,umaal,smlald,smlsld,clz,mrs,msr,xtab,sdiv,udiv,other" -+ "mov,mvn,and,orr,eor,smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,smmla,umaal,smlald,smlsld,clz,mrs,msr,xtab,sdiv,udiv,other" - (const_string "other")) - - ; TYPE attribute is used to detect floating point instructions which, if -@@ -251,8 +258,6 @@ - (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched"))) - - ;; Classification of NEON instructions for scheduling purposes. --;; Do not set this attribute and the "type" attribute together in --;; any one instruction pattern. - (define_attr "neon_type" - "neon_int_1,\ - neon_int_2,\ -@@ -415,7 +420,7 @@ - - (define_attr "generic_sched" "yes,no" - (const (if_then_else -- (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8,cortexa9") -+ (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8,cortexa9,marvell_f") - (eq_attr "tune_cortexr4" "yes")) - (const_string "no") - (const_string "yes")))) -@@ -423,7 +428,7 @@ - (define_attr "generic_vfp" "yes,no" - (const (if_then_else - (and (eq_attr "fpu" "vfp") -- (eq_attr "tune" "!arm1020e,arm1022e,cortexa8,cortexa9") -+ (eq_attr "tune" "!arm1020e,arm1022e,cortexa8,cortexa9,marvell_f") - (eq_attr "tune_cortexr4" "no")) - (const_string "yes") - (const_string "no")))) -@@ -437,6 +442,8 @@ - (include "cortex-a9.md") - (include "cortex-r4.md") - (include "cortex-r4f.md") -+(include "marvell-f.md") -+(include "marvell-f-vfp.md") - (include "vfp11.md") - - -@@ -472,9 +479,9 @@ - if (TARGET_THUMB1) - { - if (GET_CODE (operands[1]) != REG) -- operands[1] = force_reg (SImode, operands[1]); -+ operands[1] = force_reg (DImode, operands[1]); - if (GET_CODE (operands[2]) != REG) -- operands[2] = force_reg (SImode, operands[2]); -+ operands[2] = force_reg (DImode, operands[2]); - } - " - ) -@@ -620,10 +627,11 @@ - sub%?\\t%0, %1, #%n2 - sub%?\\t%0, %1, #%n2 - #" -- "TARGET_32BIT && -- GET_CODE (operands[2]) == CONST_INT -+ "TARGET_32BIT -+ && GET_CODE (operands[2]) == CONST_INT - && !(const_ok_for_arm (INTVAL (operands[2])) -- || const_ok_for_arm (-INTVAL (operands[2])))" -+ || const_ok_for_arm (-INTVAL (operands[2]))) -+ && (reload_completed || !arm_eliminable_register (operands[1]))" - [(clobber (const_int 0))] - " - arm_split_constant (PLUS, SImode, curr_insn, -@@ -639,10 +647,10 @@ - ;; register. Trying to reload it will always fail catastrophically, - ;; so never allow those alternatives to match if reloading is needed. - --(define_insn "*thumb1_addsi3" -- [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,!k") -- (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k") -- (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,!M,!O")))] -+(define_insn_and_split "*thumb1_addsi3" -+ [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,!k,l,l") -+ (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k,0,l") -+ (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,!M,!O,Pa,Pb")))] - "TARGET_THUMB1" - "* - static const char * const asms[] = -@@ -653,7 +661,9 @@ - \"add\\t%0, %0, %2\", - \"add\\t%0, %0, %2\", - \"add\\t%0, %1, %2\", -- \"add\\t%0, %1, %2\" -+ \"add\\t%0, %1, %2\", -+ \"#\", -+ \"#\" - }; - if ((which_alternative == 2 || which_alternative == 6) - && GET_CODE (operands[2]) == CONST_INT -@@ -661,7 +671,22 @@ - return \"sub\\t%0, %1, #%n2\"; - return asms[which_alternative]; - " -- [(set_attr "length" "2")] -+ "&& reload_completed && CONST_INT_P (operands[2]) -+ && operands[1] != stack_pointer_rtx -+ && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255)" -+ [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2))) -+ (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))] -+ { -+ HOST_WIDE_INT offset = INTVAL (operands[2]); -+ if (offset > 255) -+ offset = 255; -+ else if (offset < -255) -+ offset = -255; -+ -+ operands[3] = GEN_INT (offset); -+ operands[2] = GEN_INT (INTVAL (operands[2]) - offset); -+ } -+ [(set_attr "length" "2,2,2,2,2,2,2,4,4")] - ) - - ;; Reloading and elimination of the frame pointer can -@@ -854,7 +879,11 @@ - [(set_attr "conds" "use") - (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - (define_insn "*addsi3_carryin_alt1" -@@ -938,7 +967,7 @@ - [(set (match_operand:DF 0 "s_register_operand" "") - (plus:DF (match_operand:DF 1 "s_register_operand" "") - (match_operand:DF 2 "arm_float_add_operand" "")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE" - " - if (TARGET_MAVERICK - && !cirrus_fp_register (operands[2], DFmode)) -@@ -1176,7 +1205,7 @@ - [(set (match_operand:DF 0 "s_register_operand" "") - (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "") - (match_operand:DF 2 "arm_float_rhs_operand" "")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE" - " - if (TARGET_MAVERICK) - { -@@ -1332,6 +1361,49 @@ - (set_attr "predicable" "yes")] - ) - -+; The combiner cannot combine the first and last insns in the -+; following sequence because of the intervening insn, so help the -+; combiner with this splitter. The combiner does attempt to split -+; this particular combination but does not know this exact split. -+; Note that the combiner puts the constant at the outermost operation -+; as a part of canonicalization. -+; -+; mul r3, r2, r1 -+; <add/sub> r3, r3, <constant> -+; add r3, r3, r4 -+ -+(define_split -+ [(set (match_operand:SI 0 "s_register_operand" "") -+ (match_operator:SI 1 "plusminus_operator" -+ [(plus:SI (mult:SI (match_operand:SI 2 "s_register_operand" "") -+ (match_operand:SI 3 "s_register_operand" "")) -+ (match_operand:SI 4 "s_register_operand" "")) -+ (match_operand:SI 5 "arm_immediate_operand" "")]))] -+ "TARGET_32BIT" -+ [(set (match_dup 0) -+ (plus:SI (mult:SI (match_dup 2) (match_dup 3)) -+ (match_dup 4))) -+ (set (match_dup 0) -+ (match_op_dup:SI 1 [(match_dup 0) (match_dup 5)]))] -+ "") -+ -+; Likewise for MLS. MLS is available only on select architectures. -+ -+(define_split -+ [(set (match_operand:SI 0 "s_register_operand" "") -+ (match_operator:SI 1 "plusminus_operator" -+ [(minus:SI (match_operand:SI 2 "s_register_operand" "") -+ (mult:SI (match_operand:SI 3 "s_register_operand" "") -+ (match_operand:SI 4 "s_register_operand" ""))) -+ (match_operand:SI 5 "arm_immediate_operand" "")]))] -+ "TARGET_32BIT && arm_arch_thumb2" -+ [(set (match_dup 0) -+ (minus:SI (match_dup 2) -+ (mult:SI (match_dup 3) (match_dup 4)))) -+ (set (match_dup 0) -+ (match_op_dup:SI 1 [(match_dup 0) (match_dup 5)]))] -+ "") -+ - (define_insn "*mulsi3addsi_compare0" - [(set (reg:CC_NOOV CC_REGNUM) - (compare:CC_NOOV -@@ -1713,7 +1785,7 @@ - [(set (match_operand:DF 0 "s_register_operand" "") - (mult:DF (match_operand:DF 1 "s_register_operand" "") - (match_operand:DF 2 "arm_float_rhs_operand" "")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE" - " - if (TARGET_MAVERICK - && !cirrus_fp_register (operands[2], DFmode)) -@@ -1733,7 +1805,7 @@ - [(set (match_operand:DF 0 "s_register_operand" "") - (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "") - (match_operand:DF 2 "arm_float_rhs_operand" "")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)" - "") - - ;; Modulo insns -@@ -1960,6 +2032,7 @@ - DONE; - " - [(set_attr "length" "4,4,16") -+ (set_attr "insn" "and") - (set_attr "predicable" "yes")] - ) - -@@ -1969,7 +2042,8 @@ - (match_operand:SI 2 "register_operand" "l")))] - "TARGET_THUMB1" - "and\\t%0, %0, %2" -- [(set_attr "length" "2")] -+ [(set_attr "length" "2") -+ (set_attr "insn" "and")] - ) - - (define_insn "*andsi3_compare0" -@@ -1984,7 +2058,8 @@ - "@ - and%.\\t%0, %1, %2 - bic%.\\t%0, %1, #%B2" -- [(set_attr "conds" "set")] -+ [(set_attr "conds" "set") -+ (set_attr "insn" "and,*")] - ) - - (define_insn "*andsi3_compare0_scratch" -@@ -2280,7 +2355,7 @@ - } - } - -- target = operands[0]; -+ target = copy_rtx (operands[0]); - /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical - subreg as the final target. */ - if (GET_CODE (target) == SUBREG) -@@ -2528,7 +2603,11 @@ - (set_attr "shift" "2") - (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - (define_insn "*andsi_notsi_si_compare0" -@@ -2576,6 +2655,7 @@ - orr%?\\t%Q0, %Q1, %2 - #" - [(set_attr "length" "4,8") -+ (set_attr "insn" "orr") - (set_attr "predicable" "yes")] - ) - -@@ -2638,7 +2718,8 @@ - (match_operand:SI 2 "register_operand" "l")))] - "TARGET_THUMB1" - "orr\\t%0, %0, %2" -- [(set_attr "length" "2")] -+ [(set_attr "length" "2") -+ (set_attr "insn" "orr")] - ) - - (define_peephole2 -@@ -2663,7 +2744,8 @@ - (ior:SI (match_dup 1) (match_dup 2)))] - "TARGET_32BIT" - "orr%.\\t%0, %1, %2" -- [(set_attr "conds" "set")] -+ [(set_attr "conds" "set") -+ (set_attr "insn" "orr")] - ) - - (define_insn "*iorsi3_compare0_scratch" -@@ -2674,7 +2756,8 @@ - (clobber (match_scratch:SI 0 "=r"))] - "TARGET_32BIT" - "orr%.\\t%0, %1, %2" -- [(set_attr "conds" "set")] -+ [(set_attr "conds" "set") -+ (set_attr "insn" "orr")] - ) - - (define_insn "xordi3" -@@ -2697,7 +2780,8 @@ - eor%?\\t%Q0, %Q1, %2 - #" - [(set_attr "length" "4,8") -- (set_attr "predicable" "yes")] -+ (set_attr "predicable" "yes") -+ (set_attr "insn" "eor")] - ) - - (define_insn "*xordi_sesidi_di" -@@ -2728,7 +2812,8 @@ - (match_operand:SI 2 "arm_rhs_operand" "rI")))] - "TARGET_32BIT" - "eor%?\\t%0, %1, %2" -- [(set_attr "predicable" "yes")] -+ [(set_attr "predicable" "yes") -+ (set_attr "insn" "eor")] - ) - - (define_insn "*thumb1_xorsi3" -@@ -2737,7 +2822,8 @@ - (match_operand:SI 2 "register_operand" "l")))] - "TARGET_THUMB1" - "eor\\t%0, %0, %2" -- [(set_attr "length" "2")] -+ [(set_attr "length" "2") -+ (set_attr "insn" "eor")] - ) - - (define_insn "*xorsi3_compare0" -@@ -2749,7 +2835,8 @@ - (xor:SI (match_dup 1) (match_dup 2)))] - "TARGET_32BIT" - "eor%.\\t%0, %1, %2" -- [(set_attr "conds" "set")] -+ [(set_attr "conds" "set") -+ (set_attr "insn" "eor")] - ) - - (define_insn "*xorsi3_compare0_scratch" -@@ -2906,7 +2993,7 @@ - (smax:SI (match_operand:SI 1 "s_register_operand" "") - (match_operand:SI 2 "arm_rhs_operand" ""))) - (clobber (reg:CC CC_REGNUM))])] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_COND_EXEC" - " - if (operands[2] == const0_rtx || operands[2] == constm1_rtx) - { -@@ -2933,7 +3020,8 @@ - (const_int -1)))] - "TARGET_32BIT" - "orr%?\\t%0, %1, %1, asr #31" -- [(set_attr "predicable" "yes")] -+ [(set_attr "predicable" "yes") -+ (set_attr "insn" "orr")] - ) - - (define_insn "*arm_smax_insn" -@@ -2941,7 +3029,7 @@ - (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r") - (match_operand:SI 2 "arm_rhs_operand" "rI,rI"))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_COND_EXEC" - "@ - cmp\\t%1, %2\;movlt\\t%0, %2 - cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2" -@@ -2955,7 +3043,7 @@ - (smin:SI (match_operand:SI 1 "s_register_operand" "") - (match_operand:SI 2 "arm_rhs_operand" ""))) - (clobber (reg:CC CC_REGNUM))])] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_COND_EXEC" - " - if (operands[2] == const0_rtx) - { -@@ -2973,7 +3061,8 @@ - (const_int 0)))] - "TARGET_32BIT" - "and%?\\t%0, %1, %1, asr #31" -- [(set_attr "predicable" "yes")] -+ [(set_attr "predicable" "yes") -+ (set_attr "insn" "and")] - ) - - (define_insn "*arm_smin_insn" -@@ -2981,7 +3070,7 @@ - (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r") - (match_operand:SI 2 "arm_rhs_operand" "rI,rI"))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_COND_EXEC" - "@ - cmp\\t%1, %2\;movge\\t%0, %2 - cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2" -@@ -2995,7 +3084,7 @@ - (umax:SI (match_operand:SI 1 "s_register_operand" "") - (match_operand:SI 2 "arm_rhs_operand" ""))) - (clobber (reg:CC CC_REGNUM))])] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_COND_EXEC" - "" - ) - -@@ -3004,7 +3093,7 @@ - (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") - (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_COND_EXEC" - "@ - cmp\\t%1, %2\;movcc\\t%0, %2 - cmp\\t%1, %2\;movcs\\t%0, %1 -@@ -3019,7 +3108,7 @@ - (umin:SI (match_operand:SI 1 "s_register_operand" "") - (match_operand:SI 2 "arm_rhs_operand" ""))) - (clobber (reg:CC CC_REGNUM))])] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_COND_EXEC" - "" - ) - -@@ -3028,7 +3117,7 @@ - (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") - (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_COND_EXEC" - "@ - cmp\\t%1, %2\;movcs\\t%0, %2 - cmp\\t%1, %2\;movcc\\t%0, %1 -@@ -3043,7 +3132,7 @@ - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "s_register_operand" "r")])) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_COND_EXEC" - "* - operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode, - operands[1], operands[2]); -@@ -3163,11 +3252,23 @@ - [(set (match_operand:SI 0 "register_operand" "=l,l") - (ashift:SI (match_operand:SI 1 "register_operand" "l,0") - (match_operand:SI 2 "nonmemory_operand" "N,l")))] -- "TARGET_THUMB1" -+ "TARGET_THUMB1 && !janus2_code" - "lsl\\t%0, %1, %2" - [(set_attr "length" "2")] - ) - -+(define_insn "*thumb1_ashlsi3_janus2" -+ [(set (match_operand:SI 0 "register_operand" "=l,l") -+ (ashift:SI (match_operand:SI 1 "register_operand" "l,0") -+ (match_operand:SI 2 "nonmemory_operand" "N,l")))] -+ "TARGET_THUMB1 && janus2_code" -+ "@ -+ lsl\\t%0, %1, %2 -+ lsl\\t%0, %1, %2\;nop" -+ [(set_attr "length" "2,4")] -+) -+ -+ - (define_expand "ashrdi3" - [(set (match_operand:DI 0 "s_register_operand" "") - (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "") -@@ -3200,6 +3301,7 @@ - "TARGET_32BIT" - "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx" - [(set_attr "conds" "clob") -+ (set_attr "insn" "mov") - (set_attr "length" "8")] - ) - -@@ -3219,11 +3321,22 @@ - [(set (match_operand:SI 0 "register_operand" "=l,l") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0") - (match_operand:SI 2 "nonmemory_operand" "N,l")))] -- "TARGET_THUMB1" -+ "TARGET_THUMB1 && !janus2_code" - "asr\\t%0, %1, %2" - [(set_attr "length" "2")] - ) - -+(define_insn "*thumb1_ashrsi3_janus2" -+ [(set (match_operand:SI 0 "register_operand" "=l,l") -+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0") -+ (match_operand:SI 2 "nonmemory_operand" "N,l")))] -+ "TARGET_THUMB1 && janus2_code" -+ "@ -+ asr\\t%0, %1, %2 -+ asr\\t%0, %1, %2\;nop" -+ [(set_attr "length" "2,4")] -+) -+ - (define_expand "lshrdi3" - [(set (match_operand:DI 0 "s_register_operand" "") - (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "") -@@ -3256,6 +3369,7 @@ - "TARGET_32BIT" - "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx" - [(set_attr "conds" "clob") -+ (set_attr "insn" "mov") - (set_attr "length" "8")] - ) - -@@ -3278,11 +3392,22 @@ - [(set (match_operand:SI 0 "register_operand" "=l,l") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0") - (match_operand:SI 2 "nonmemory_operand" "N,l")))] -- "TARGET_THUMB1" -+ "TARGET_THUMB1 && !janus2_code" - "lsr\\t%0, %1, %2" - [(set_attr "length" "2")] - ) - -+(define_insn "*thumb1_lshrsi3_janus2" -+ [(set (match_operand:SI 0 "register_operand" "=l,l") -+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0") -+ (match_operand:SI 2 "nonmemory_operand" "N,l")))] -+ "TARGET_THUMB1 && janus2_code" -+ "@ -+ lsr\\t%0, %1, %2 -+ lsr\\t%0, %1, %2; nop" -+ [(set_attr "length" "2,4")] -+) -+ - (define_expand "rotlsi3" - [(set (match_operand:SI 0 "s_register_operand" "") - (rotatert:SI (match_operand:SI 1 "s_register_operand" "") -@@ -3324,11 +3449,20 @@ - [(set (match_operand:SI 0 "register_operand" "=l") - (rotatert:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "register_operand" "l")))] -- "TARGET_THUMB1" -+ "TARGET_THUMB1 && !janus2_code" - "ror\\t%0, %0, %2" - [(set_attr "length" "2")] - ) - -+(define_insn "*thumb1_rotrsi3_janus2" -+ [(set (match_operand:SI 0 "register_operand" "=l") -+ (rotatert:SI (match_operand:SI 1 "register_operand" "0") -+ (match_operand:SI 2 "register_operand" "l")))] -+ "TARGET_THUMB1 && janus2_code" -+ "ror\\t%0, %0, %2; nop" -+ [(set_attr "length" "4")] -+) -+ - (define_insn "*arm_shiftsi3" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (match_operator:SI 3 "shift_operator" -@@ -3340,7 +3474,11 @@ - (set_attr "shift" "1") - (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - (define_insn "*shiftsi3_compare0" -@@ -3357,7 +3495,11 @@ - (set_attr "shift" "1") - (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - (define_insn "*shiftsi3_compare0_scratch" -@@ -3370,7 +3512,11 @@ - "TARGET_32BIT" - "* return arm_output_shift(operands, 1);" - [(set_attr "conds" "set") -- (set_attr "shift" "1")] -+ (set_attr "shift" "1") -+ (set (attr "length") (if_then_else (and (match_operand 2 "s_register_operand" "") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - (define_insn "*arm_notsi_shiftsi" -@@ -3382,9 +3528,14 @@ - "mvn%?\\t%0, %1%S3" - [(set_attr "predicable" "yes") - (set_attr "shift" "1") -+ (set_attr "insn" "mvn") - (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - (define_insn "*arm_notsi_shiftsi_compare0" -@@ -3399,9 +3550,14 @@ - "mvn%.\\t%0, %1%S3" - [(set_attr "conds" "set") - (set_attr "shift" "1") -+ (set_attr "insn" "mvn") - (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - (define_insn "*arm_not_shiftsi_compare0_scratch" -@@ -3415,9 +3571,14 @@ - "mvn%.\\t%0, %1%S3" - [(set_attr "conds" "set") - (set_attr "shift" "1") -+ (set_attr "insn" "mvn") - (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - ;; We don't really have extzv, but defining this using shifts helps -@@ -3550,12 +3711,12 @@ - (define_expand "negdf2" - [(set (match_operand:DF 0 "s_register_operand" "") - (neg:DF (match_operand:DF 1 "s_register_operand" "")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)" - "") - - ;; abssi2 doesn't really clobber the condition codes if a different register - ;; is being set. To keep things simple, assume during rtl manipulations that --;; it does, but tell the final scan operator the truth. Similarly for -+;; it does, and the splitter will eliminate it. Similarly for - ;; (neg (abs...)) - - (define_expand "abssi2" -@@ -3567,22 +3728,28 @@ - " - if (TARGET_THUMB1) - operands[2] = gen_rtx_SCRATCH (SImode); -+ else if (TARGET_NO_SINGLE_COND_EXEC) -+ { -+ emit_insn(gen_rtx_SET(VOIDmode, operands[0], -+ gen_rtx_ABS(SImode, operands[1]))); -+ DONE; -+ } - else - operands[2] = gen_rtx_REG (CCmode, CC_REGNUM); - ") - - (define_insn "*arm_abssi2" -- [(set (match_operand:SI 0 "s_register_operand" "=r,&r") -- (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))) -+ [(set (match_operand:SI 0 "s_register_operand" "=r") -+ (abs:SI (match_operand:SI 1 "s_register_operand" "r"))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -- "@ -- cmp\\t%0, #0\;rsblt\\t%0, %0, #0 -- eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31" -- [(set_attr "conds" "clob,*") -- (set_attr "shift" "1") -+ "TARGET_32BIT && !TARGET_NO_SINGLE_COND_EXEC" -+ "#" -+ [(set_attr "shift" "1") - ;; predicable can't be set based on the variant, so left as no -- (set_attr "length" "8")] -+ (set (attr "length") -+ (if_then_else (eq_attr "is_thumb" "yes") -+ (const_int 10) -+ (const_int 8)))] - ) - - (define_insn_and_split "*thumb1_abssi2" -@@ -3600,17 +3767,17 @@ - ) - - (define_insn "*arm_neg_abssi2" -- [(set (match_operand:SI 0 "s_register_operand" "=r,&r") -- (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))) -+ [(set (match_operand:SI 0 "s_register_operand" "=r") -+ (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "r")))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -- "@ -- cmp\\t%0, #0\;rsbgt\\t%0, %0, #0 -- eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31" -- [(set_attr "conds" "clob,*") -- (set_attr "shift" "1") -+ "TARGET_32BIT && !TARGET_NO_SINGLE_COND_EXEC" -+ "#" -+ [(set_attr "shift" "1") - ;; predicable can't be set based on the variant, so left as no -- (set_attr "length" "8")] -+ (set (attr "length") -+ (if_then_else (eq_attr "is_thumb" "yes") -+ (const_int 10) -+ (const_int 8)))] - ) - - (define_insn_and_split "*thumb1_neg_abssi2" -@@ -3627,6 +3794,93 @@ - [(set_attr "length" "6")] - ) - -+;; Simplified version for when avoiding conditional execution -+(define_insn "*arm_nocond_abssi2" -+ [(set (match_operand:SI 0 "s_register_operand" "=&r") -+ (abs:SI (match_operand:SI 1 "s_register_operand" "r")))] -+ "TARGET_32BIT && TARGET_NO_SINGLE_COND_EXEC" -+ "#" -+ [(set_attr "shift" "1") -+ (set_attr "length" "8") -+ (set_attr "predicable" "yes")] -+) -+ -+(define_insn "*arm_nocond_neg_abssi2" -+ [(set (match_operand:SI 0 "s_register_operand" "=&r") -+ (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "r"))))] -+ "TARGET_32BIT && TARGET_NO_SINGLE_COND_EXEC" -+ "#" -+ [(set_attr "shift" "1") -+ (set_attr "length" "8") -+ (set_attr "predicable" "yes")] -+) -+ -+;; Splitters for ABS patterns. -+ -+(define_split -+ [(set (match_operand:SI 0 "s_register_operand" "") -+ (abs:SI (match_operand:SI 1 "s_register_operand" ""))) -+ (clobber (reg:CC CC_REGNUM))] -+ "TARGET_32BIT && reload_completed && rtx_equal_p(operands[0], operands[1])" -+ [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0))) -+ (cond_exec (lt (reg:CC CC_REGNUM) (const_int 0)) -+ (set (match_dup 0) (neg:SI (match_dup 1))))] -+) -+ -+(define_split -+ [(set (match_operand:SI 0 "s_register_operand" "") -+ (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "")))) -+ (clobber (reg:CC CC_REGNUM))] -+ "TARGET_32BIT && reload_completed && rtx_equal_p(operands[0], operands[1])" -+ [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0))) -+ (cond_exec (gt (reg:CC CC_REGNUM) (const_int 0)) -+ (set (match_dup 0) (neg:SI (match_dup 1))))] -+) -+ -+;; GCC does not add/remove clobbers when matching splitters, so we need -+;; variants with and without the CC clobber. -+(define_split -+ [(set (match_operand:SI 0 "s_register_operand" "") -+ (abs:SI (match_operand:SI 1 "s_register_operand" "")))] -+ "TARGET_32BIT && reload_completed && !rtx_equal_p(operands[0], operands[1])" -+ [(set (match_dup 0) (xor:SI (ashiftrt:SI (match_dup 1) (const_int 31)) -+ (match_dup 1))) -+ (set (match_dup 0) (minus:SI (match_dup 0) -+ (ashiftrt:SI (match_dup 1) (const_int 31))))] -+) -+ -+(define_split -+ [(set (match_operand:SI 0 "s_register_operand" "") -+ (abs:SI (match_operand:SI 1 "s_register_operand" ""))) -+ (clobber (reg:CC CC_REGNUM))] -+ "TARGET_32BIT && reload_completed && !rtx_equal_p(operands[0], operands[1])" -+ [(set (match_dup 0) (xor:SI (ashiftrt:SI (match_dup 1) (const_int 31)) -+ (match_dup 1))) -+ (set (match_dup 0) (minus:SI (match_dup 0) -+ (ashiftrt:SI (match_dup 1) (const_int 31))))] -+) -+ -+(define_split -+ [(set (match_operand:SI 0 "s_register_operand" "") -+ (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" ""))))] -+ "TARGET_32BIT && reload_completed && !rtx_equal_p(operands[0], operands[1])" -+ [(set (match_dup 0) (xor:SI (ashiftrt:SI (match_dup 1) (const_int 31)) -+ (match_dup 1))) -+ (set (match_dup 0) (minus:SI (ashiftrt:SI (match_dup 1) (const_int 31)) -+ (match_dup 0)))] -+) -+ -+(define_split -+ [(set (match_operand:SI 0 "s_register_operand" "") -+ (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "")))) -+ (clobber (reg:CC CC_REGNUM))] -+ "TARGET_32BIT && reload_completed && !rtx_equal_p(operands[0], operands[1])" -+ [(set (match_dup 0) (xor:SI (ashiftrt:SI (match_dup 1) (const_int 31)) -+ (match_dup 1))) -+ (set (match_dup 0) (minus:SI (ashiftrt:SI (match_dup 1) (const_int 31)) -+ (match_dup 0)))] -+) -+ - (define_expand "abssf2" - [(set (match_operand:SF 0 "s_register_operand" "") - (abs:SF (match_operand:SF 1 "s_register_operand" "")))] -@@ -3636,7 +3890,7 @@ - (define_expand "absdf2" - [(set (match_operand:DF 0 "s_register_operand" "") - (abs:DF (match_operand:DF 1 "s_register_operand" "")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE" - "") - - (define_expand "sqrtsf2" -@@ -3648,7 +3902,7 @@ - (define_expand "sqrtdf2" - [(set (match_operand:DF 0 "s_register_operand" "") - (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)" - "") - - (define_insn_and_split "one_cmpldi2" -@@ -3682,7 +3936,8 @@ - (not:SI (match_operand:SI 1 "s_register_operand" "r")))] - "TARGET_32BIT" - "mvn%?\\t%0, %1" -- [(set_attr "predicable" "yes")] -+ [(set_attr "predicable" "yes") -+ (set_attr "insn" "mvn")] - ) - - (define_insn "*thumb1_one_cmplsi2" -@@ -3690,7 +3945,8 @@ - (not:SI (match_operand:SI 1 "register_operand" "l")))] - "TARGET_THUMB1" - "mvn\\t%0, %1" -- [(set_attr "length" "2")] -+ [(set_attr "length" "2") -+ (set_attr "insn" "mvn")] - ) - - (define_insn "*notsi_compare0" -@@ -3701,7 +3957,8 @@ - (not:SI (match_dup 1)))] - "TARGET_32BIT" - "mvn%.\\t%0, %1" -- [(set_attr "conds" "set")] -+ [(set_attr "conds" "set") -+ (set_attr "insn" "mvn")] - ) - - (define_insn "*notsi_compare0_scratch" -@@ -3711,11 +3968,40 @@ - (clobber (match_scratch:SI 0 "=r"))] - "TARGET_32BIT" - "mvn%.\\t%0, %1" -- [(set_attr "conds" "set")] -+ [(set_attr "conds" "set") -+ (set_attr "insn" "mvn")] - ) - - ;; Fixed <--> Floating conversion insns - -+(define_expand "floatsihf2" -+ [(set (match_operand:HF 0 "general_operand" "") -+ (float:HF (match_operand:SI 1 "general_operand" "")))] -+ "TARGET_EITHER" -+ " -+ { -+ rtx op1 = gen_reg_rtx (SFmode); -+ expand_float (op1, operands[1], 0); -+ op1 = convert_to_mode (HFmode, op1, 0); -+ emit_move_insn (operands[0], op1); -+ DONE; -+ }" -+) -+ -+(define_expand "floatdihf2" -+ [(set (match_operand:HF 0 "general_operand" "") -+ (float:HF (match_operand:DI 1 "general_operand" "")))] -+ "TARGET_EITHER" -+ " -+ { -+ rtx op1 = gen_reg_rtx (SFmode); -+ expand_float (op1, operands[1], 0); -+ op1 = convert_to_mode (HFmode, op1, 0); -+ emit_move_insn (operands[0], op1); -+ DONE; -+ }" -+) -+ - (define_expand "floatsisf2" - [(set (match_operand:SF 0 "s_register_operand" "") - (float:SF (match_operand:SI 1 "s_register_operand" "")))] -@@ -3731,7 +4017,7 @@ - (define_expand "floatsidf2" - [(set (match_operand:DF 0 "s_register_operand" "") - (float:DF (match_operand:SI 1 "s_register_operand" "")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE" - " - if (TARGET_MAVERICK) - { -@@ -3740,6 +4026,30 @@ - } - ") - -+(define_expand "fix_trunchfsi2" -+ [(set (match_operand:SI 0 "general_operand" "") -+ (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))] -+ "TARGET_EITHER" -+ " -+ { -+ rtx op1 = convert_to_mode (SFmode, operands[1], 0); -+ expand_fix (operands[0], op1, 0); -+ DONE; -+ }" -+) -+ -+(define_expand "fix_trunchfdi2" -+ [(set (match_operand:DI 0 "general_operand" "") -+ (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))] -+ "TARGET_EITHER" -+ " -+ { -+ rtx op1 = convert_to_mode (SFmode, operands[1], 0); -+ expand_fix (operands[0], op1, 0); -+ DONE; -+ }" -+) -+ - (define_expand "fix_truncsfsi2" - [(set (match_operand:SI 0 "s_register_operand" "") - (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))] -@@ -3759,7 +4069,7 @@ - (define_expand "fix_truncdfsi2" - [(set (match_operand:SI 0 "s_register_operand" "") - (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))] -- "TARGET_32BIT && TARGET_HARD_FLOAT" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE" - " - if (TARGET_MAVERICK) - { -@@ -3776,9 +4086,25 @@ - [(set (match_operand:SF 0 "s_register_operand" "") - (float_truncate:SF - (match_operand:DF 1 "s_register_operand" "")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE" - "" - ) -+ -+/* DFmode -> HFmode conversions have to go through SFmode. */ -+(define_expand "truncdfhf2" -+ [(set (match_operand:HF 0 "general_operand" "") -+ (float_truncate:HF -+ (match_operand:DF 1 "general_operand" "")))] -+ "TARGET_EITHER" -+ " -+ { -+ rtx op1; -+ op1 = convert_to_mode (SFmode, operands[1], 0); -+ op1 = convert_to_mode (HFmode, op1, 0); -+ emit_move_insn (operands[0], op1); -+ DONE; -+ }" -+) - - ;; Zero and sign extension instructions. - -@@ -3800,6 +4126,7 @@ - return \"mov%?\\t%R0, #0\"; - " - [(set_attr "length" "8") -+ (set_attr "insn" "mov") - (set_attr "predicable" "yes")] - ) - -@@ -3843,6 +4170,7 @@ - " - [(set_attr "length" "8") - (set_attr "shift" "1") -+ (set_attr "insn" "mov") - (set_attr "predicable" "yes")] - ) - -@@ -4123,6 +4451,28 @@ - "" - ) - -+(define_code_iterator ior_xor [ior xor]) -+ -+(define_split -+ [(set (match_operand:SI 0 "s_register_operand" "") -+ (ior_xor:SI (and:SI (ashift:SI -+ (match_operand:SI 1 "s_register_operand" "") -+ (match_operand:SI 2 "const_int_operand" "")) -+ (match_operand:SI 3 "const_int_operand" "")) -+ (zero_extend:SI -+ (match_operator 5 "subreg_lowpart_operator" -+ [(match_operand:SI 4 "s_register_operand" "")]))))] -+ "TARGET_32BIT -+ && (INTVAL (operands[3]) -+ == (GET_MODE_MASK (GET_MODE (operands[5])) -+ & (GET_MODE_MASK (GET_MODE (operands[5])) -+ << (INTVAL (operands[2])))))" -+ [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2)) -+ (match_dup 4))) -+ (set (match_dup 0) (zero_extend:SI (match_dup 5)))] -+ "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);" -+) -+ - (define_insn "*compareqi_eq0" - [(set (reg:CC_Z CC_REGNUM) - (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r") -@@ -4639,9 +4989,24 @@ - (define_expand "extendsfdf2" - [(set (match_operand:DF 0 "s_register_operand" "") - (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE" - "" - ) -+ -+/* HFmode -> DFmode conversions have to go through SFmode. */ -+(define_expand "extendhfdf2" -+ [(set (match_operand:DF 0 "general_operand" "") -+ (float_extend:DF (match_operand:HF 1 "general_operand" "")))] -+ "TARGET_EITHER" -+ " -+ { -+ rtx op1; -+ op1 = convert_to_mode (SFmode, operands[1], 0); -+ op1 = convert_to_mode (DFmode, op1, 0); -+ emit_insn (gen_movdf (operands[0], op1)); -+ DONE; -+ }" -+) - - ;; Move insns (including loads and stores) - -@@ -4877,6 +5242,7 @@ - }" - [(set_attr "length" "4,4,6,2,2,6,4,4") - (set_attr "type" "*,*,*,load2,store2,load2,store2,*") -+ (set_attr "insn" "*,mov,*,*,*,*,*,mov") - (set_attr "pool_range" "*,*,*,*,*,1020,*,*")] - ) - -@@ -4903,14 +5269,6 @@ - optimize && can_create_pseudo_p ()); - DONE; - } -- -- if (TARGET_USE_MOVT && !target_word_relocations -- && GET_CODE (operands[1]) == SYMBOL_REF -- && !flag_pic && !arm_tls_referenced_p (operands[1])) -- { -- arm_emit_movpair (operands[0], operands[1]); -- DONE; -- } - } - else /* TARGET_THUMB1... */ - { -@@ -4984,18 +5342,9 @@ - (set_attr "length" "4")] - ) - --(define_insn "*arm_movw" -- [(set (match_operand:SI 0 "nonimmediate_operand" "=r") -- (high:SI (match_operand:SI 1 "general_operand" "i")))] -- "TARGET_32BIT" -- "movw%?\t%0, #:lower16:%c1" -- [(set_attr "predicable" "yes") -- (set_attr "length" "4")] --) -- - (define_insn "*arm_movsi_insn" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m") -- (match_operand:SI 1 "general_operand" "rk, I,K,N,mi,rk"))] -+ (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))] - "TARGET_ARM && ! TARGET_IWMMXT - && !(TARGET_HARD_FLOAT && TARGET_VFP) - && ( register_operand (operands[0], SImode) -@@ -5008,6 +5357,7 @@ - ldr%?\\t%0, %1 - str%?\\t%1, %0" - [(set_attr "type" "*,*,*,*,load1,store1") -+ (set_attr "insn" "mov,mov,mvn,mov,*,*") - (set_attr "predicable" "yes") - (set_attr "pool_range" "*,*,*,*,4096,*") - (set_attr "neg_pool_range" "*,*,*,*,4084,*")] -@@ -5027,6 +5377,19 @@ - " - ) - -+(define_split -+ [(set (match_operand:SI 0 "arm_general_register_operand" "") -+ (match_operand:SI 1 "general_operand" ""))] -+ "TARGET_32BIT -+ && TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF -+ && !flag_pic && !target_word_relocations -+ && !arm_tls_referenced_p (operands[1])" -+ [(clobber (const_int 0))] -+{ -+ arm_emit_movpair (operands[0], operands[1]); -+ DONE; -+}) -+ - (define_insn "*thumb1_movsi_insn" - [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk") - (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lhk"))] -@@ -5065,7 +5428,7 @@ - (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))] - " - { -- unsigned HOST_WIDE_INT val = INTVAL (operands[1]); -+ unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu; - unsigned HOST_WIDE_INT mask = 0xff; - int i; - -@@ -5627,6 +5990,7 @@ - ldr%(h%)\\t%0, %1\\t%@ movhi" - [(set_attr "type" "*,*,store1,load1") - (set_attr "predicable" "yes") -+ (set_attr "insn" "mov,mvn,*,*") - (set_attr "pool_range" "*,*,*,256") - (set_attr "neg_pool_range" "*,*,*,244")] - ) -@@ -5638,7 +6002,8 @@ - "@ - mov%?\\t%0, %1\\t%@ movhi - mvn%?\\t%0, #%B1\\t%@ movhi" -- [(set_attr "predicable" "yes")] -+ [(set_attr "predicable" "yes") -+ (set_attr "insn" "mov,mvn")] - ) - - (define_expand "thumb_movhi_clobber" -@@ -5769,6 +6134,7 @@ - ldr%(b%)\\t%0, %1 - str%(b%)\\t%1, %0" - [(set_attr "type" "*,*,load1,store1") -+ (set_attr "insn" "mov,mvn,*,*") - (set_attr "predicable" "yes")] - ) - -@@ -5787,9 +6153,111 @@ - mov\\t%0, %1" - [(set_attr "length" "2") - (set_attr "type" "*,load1,store1,*,*,*") -+ (set_attr "insn" "*,*,*,mov,mov,mov") - (set_attr "pool_range" "*,32,*,*,*,*")] - ) - -+;; HFmode moves -+(define_expand "movhf" -+ [(set (match_operand:HF 0 "general_operand" "") -+ (match_operand:HF 1 "general_operand" ""))] -+ "TARGET_EITHER" -+ " -+ if (TARGET_32BIT) -+ { -+ if (GET_CODE (operands[0]) == MEM) -+ operands[1] = force_reg (HFmode, operands[1]); -+ } -+ else /* TARGET_THUMB1 */ -+ { -+ if (can_create_pseudo_p ()) -+ { -+ if (GET_CODE (operands[0]) != REG) -+ operands[1] = force_reg (HFmode, operands[1]); -+ } -+ } -+ " -+) -+ -+(define_insn "*arm32_movhf" -+ [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r") -+ (match_operand:HF 1 "general_operand" " m,r,r,F"))] -+ "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16) -+ && ( s_register_operand (operands[0], HFmode) -+ || s_register_operand (operands[1], HFmode))" -+ "* -+ switch (which_alternative) -+ { -+ case 0: /* ARM register from memory */ -+ return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\"; -+ case 1: /* memory from ARM register */ -+ return \"str%(h%)\\t%1, %0\\t%@ __fp16\"; -+ case 2: /* ARM register from ARM register */ -+ return \"mov%?\\t%0, %1\\t%@ __fp16\"; -+ case 3: /* ARM register from constant */ -+ { -+ REAL_VALUE_TYPE r; -+ long bits; -+ rtx ops[4]; -+ -+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]); -+ bits = real_to_target (NULL, &r, HFmode); -+ ops[0] = operands[0]; -+ ops[1] = GEN_INT (bits); -+ ops[2] = GEN_INT (bits & 0xff00); -+ ops[3] = GEN_INT (bits & 0x00ff); -+ -+ if (arm_arch_thumb2) -+ output_asm_insn (\"movw%?\\t%0, %1\", ops); -+ else -+ output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops); -+ return \"\"; -+ } -+ default: -+ gcc_unreachable (); -+ } -+ " -+ [(set_attr "conds" "unconditional") -+ (set_attr "type" "load1,store1,*,*") -+ (set_attr "length" "4,4,4,8") -+ (set_attr "predicable" "yes") -+ ] -+) -+ -+(define_insn "*thumb1_movhf" -+ [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,m,*r,*h") -+ (match_operand:HF 1 "general_operand" "l,mF,l,*h,*r"))] -+ "TARGET_THUMB1 -+ && ( s_register_operand (operands[0], HFmode) -+ || s_register_operand (operands[1], HFmode))" -+ "* -+ switch (which_alternative) -+ { -+ case 1: -+ { -+ rtx addr; -+ gcc_assert (GET_CODE(operands[1]) == MEM); -+ addr = XEXP (operands[1], 0); -+ if (GET_CODE (addr) == LABEL_REF -+ || (GET_CODE (addr) == CONST -+ && GET_CODE (XEXP (addr, 0)) == PLUS -+ && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF -+ && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)) -+ { -+ /* Constant pool entry. */ -+ return \"ldr\\t%0, %1\"; -+ } -+ return \"ldrh\\t%0, %1\"; -+ } -+ case 2: return \"strh\\t%1, %0\"; -+ default: return \"mov\\t%0, %1\"; -+ } -+ " -+ [(set_attr "length" "2") -+ (set_attr "type" "*,load1,store1,*,*") -+ (set_attr "pool_range" "*,1020,*,*,*")] -+) -+ - (define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] -@@ -5842,6 +6310,7 @@ - [(set_attr "length" "4,4,4") - (set_attr "predicable" "yes") - (set_attr "type" "*,load1,store1") -+ (set_attr "insn" "mov,*,*") - (set_attr "pool_range" "*,4096,*") - (set_attr "neg_pool_range" "*,4084,*")] - ) -@@ -6297,7 +6766,7 @@ - (match_operand:BLK 1 "general_operand" "") - (match_operand:SI 2 "const_int_operand" "") - (match_operand:SI 3 "const_int_operand" "")] -- "TARGET_EITHER" -+ "TARGET_EITHER && !low_irq_latency" - " - if (TARGET_32BIT) - { -@@ -7476,7 +7945,7 @@ - (define_expand "cmpdf" - [(match_operand:DF 0 "s_register_operand" "") - (match_operand:DF 1 "arm_float_compare_operand" "")] -- "TARGET_32BIT && TARGET_HARD_FLOAT" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE" - " - arm_compare_op0 = operands[0]; - arm_compare_op1 = operands[1]; -@@ -7507,7 +7976,11 @@ - (set_attr "shift" "1") - (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - (define_insn "*arm_cmpsi_shiftsi_swp" -@@ -7522,7 +7995,11 @@ - (set_attr "shift" "1") - (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - (define_insn "*arm_cmpsi_negshiftsi_si" -@@ -7537,7 +8014,11 @@ - [(set_attr "conds" "set") - (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - ;; Cirrus SF compare instruction -@@ -7879,77 +8360,77 @@ - (define_expand "seq" - [(set (match_operand:SI 0 "s_register_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_COND_EXEC" - "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" - ) - - (define_expand "sne" - [(set (match_operand:SI 0 "s_register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_COND_EXEC" - "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" - ) - - (define_expand "sgt" - [(set (match_operand:SI 0 "s_register_operand" "") - (gt:SI (match_dup 1) (const_int 0)))] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_COND_EXEC" - "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" - ) - - (define_expand "sle" - [(set (match_operand:SI 0 "s_register_operand" "") - (le:SI (match_dup 1) (const_int 0)))] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_COND_EXEC" - "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" - ) - - (define_expand "sge" - [(set (match_operand:SI 0 "s_register_operand" "") - (ge:SI (match_dup 1) (const_int 0)))] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_COND_EXEC" - "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" - ) - - (define_expand "slt" - [(set (match_operand:SI 0 "s_register_operand" "") - (lt:SI (match_dup 1) (const_int 0)))] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_COND_EXEC" - "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" - ) - - (define_expand "sgtu" - [(set (match_operand:SI 0 "s_register_operand" "") - (gtu:SI (match_dup 1) (const_int 0)))] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_COND_EXEC" - "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" - ) - - (define_expand "sleu" - [(set (match_operand:SI 0 "s_register_operand" "") - (leu:SI (match_dup 1) (const_int 0)))] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_COND_EXEC" - "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" - ) - - (define_expand "sgeu" - [(set (match_operand:SI 0 "s_register_operand" "") - (geu:SI (match_dup 1) (const_int 0)))] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_COND_EXEC" - "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" - ) - - (define_expand "sltu" - [(set (match_operand:SI 0 "s_register_operand" "") - (ltu:SI (match_dup 1) (const_int 0)))] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_COND_EXEC" - "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" - ) - - (define_expand "sunordered" - [(set (match_operand:SI 0 "s_register_operand" "") - (unordered:SI (match_dup 1) (const_int 0)))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP) && !TARGET_NO_COND_EXEC" - "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, - arm_compare_op1);" - ) -@@ -7957,7 +8438,7 @@ - (define_expand "sordered" - [(set (match_operand:SI 0 "s_register_operand" "") - (ordered:SI (match_dup 1) (const_int 0)))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP) && !TARGET_NO_COND_EXEC" - "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, - arm_compare_op1);" - ) -@@ -7965,7 +8446,7 @@ - (define_expand "sungt" - [(set (match_operand:SI 0 "s_register_operand" "") - (ungt:SI (match_dup 1) (const_int 0)))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP) && !TARGET_NO_COND_EXEC" - "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, - arm_compare_op1);" - ) -@@ -7973,7 +8454,7 @@ - (define_expand "sunge" - [(set (match_operand:SI 0 "s_register_operand" "") - (unge:SI (match_dup 1) (const_int 0)))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP) && !TARGET_NO_COND_EXEC" - "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, - arm_compare_op1);" - ) -@@ -7981,7 +8462,7 @@ - (define_expand "sunlt" - [(set (match_operand:SI 0 "s_register_operand" "") - (unlt:SI (match_dup 1) (const_int 0)))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP) && !TARGET_NO_COND_EXEC" - "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, - arm_compare_op1);" - ) -@@ -7989,7 +8470,7 @@ - (define_expand "sunle" - [(set (match_operand:SI 0 "s_register_operand" "") - (unle:SI (match_dup 1) (const_int 0)))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP) && !TARGET_NO_COND_EXEC" - "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, - arm_compare_op1);" - ) -@@ -8018,6 +8499,7 @@ - "TARGET_ARM" - "mov%D1\\t%0, #0\;mov%d1\\t%0, #1" - [(set_attr "conds" "use") -+ (set_attr "insn" "mov") - (set_attr "length" "8")] - ) - -@@ -8028,6 +8510,7 @@ - "TARGET_ARM" - "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0" - [(set_attr "conds" "use") -+ (set_attr "insn" "mov") - (set_attr "length" "8")] - ) - -@@ -8038,6 +8521,7 @@ - "TARGET_ARM" - "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1" - [(set_attr "conds" "use") -+ (set_attr "insn" "mov") - (set_attr "length" "8")] - ) - -@@ -8241,7 +8725,7 @@ - (if_then_else:SI (match_operand 1 "arm_comparison_operator" "") - (match_operand:SI 2 "arm_not_operand" "") - (match_operand:SI 3 "arm_not_operand" "")))] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_COND_EXEC" - " - { - enum rtx_code code = GET_CODE (operands[1]); -@@ -8260,7 +8744,7 @@ - (if_then_else:SF (match_operand 1 "arm_comparison_operator" "") - (match_operand:SF 2 "s_register_operand" "") - (match_operand:SF 3 "nonmemory_operand" "")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_NO_COND_EXEC" - " - { - enum rtx_code code = GET_CODE (operands[1]); -@@ -8285,7 +8769,7 @@ - (if_then_else:DF (match_operand 1 "arm_comparison_operator" "") - (match_operand:DF 2 "s_register_operand" "") - (match_operand:DF 3 "arm_float_add_operand" "")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE) && !TARGET_NO_COND_EXEC" - " - { - enum rtx_code code = GET_CODE (operands[1]); -@@ -8317,7 +8801,8 @@ - mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2 - mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2" - [(set_attr "length" "4,4,4,4,8,8,8,8") -- (set_attr "conds" "use")] -+ (set_attr "conds" "use") -+ (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")] - ) - - (define_insn "*movsfcc_soft_insn" -@@ -8330,7 +8815,8 @@ - "@ - mov%D3\\t%0, %2 - mov%d3\\t%0, %1" -- [(set_attr "conds" "use")] -+ [(set_attr "conds" "use") -+ (set_attr "insn" "mov")] - ) - - -@@ -8733,7 +9219,7 @@ - [(match_operand 1 "cc_register" "") (const_int 0)]) - (return) - (pc)))] -- "TARGET_ARM && USE_RETURN_INSN (TRUE)" -+ "TARGET_ARM && USE_RETURN_INSN (TRUE) && !TARGET_NO_COND_EXEC" - "* - { - if (arm_ccfsm_state == 2) -@@ -8754,7 +9240,7 @@ - [(match_operand 1 "cc_register" "") (const_int 0)]) - (pc) - (return)))] -- "TARGET_ARM && USE_RETURN_INSN (TRUE)" -+ "TARGET_ARM && USE_RETURN_INSN (TRUE) && !TARGET_NO_COND_EXEC" - "* - { - if (arm_ccfsm_state == 2) -@@ -9072,7 +9558,11 @@ - (set_attr "shift" "4") - (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - (define_split -@@ -9110,7 +9600,11 @@ - (set_attr "shift" "4") - (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - (define_insn "*arith_shiftsi_compare0_scratch" -@@ -9128,7 +9622,11 @@ - (set_attr "shift" "4") - (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - (define_insn "*sub_shiftsi" -@@ -9143,7 +9641,11 @@ - (set_attr "shift" "3") - (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - (define_insn "*sub_shiftsi_compare0" -@@ -9163,7 +9665,11 @@ - (set_attr "shift" "3") - (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - (define_insn "*sub_shiftsi_compare0_scratch" -@@ -9181,7 +9687,11 @@ - (set_attr "shift" "3") - (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)))] - ) - - -@@ -9194,6 +9704,7 @@ - "TARGET_ARM" - "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1" - [(set_attr "conds" "use") -+ (set_attr "insn" "mov") - (set_attr "length" "8")] - ) - -@@ -9207,6 +9718,7 @@ - orr%d2\\t%0, %1, #1 - mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1" - [(set_attr "conds" "use") -+ (set_attr "insn" "orr") - (set_attr "length" "4,8")] - ) - -@@ -9216,7 +9728,7 @@ - [(match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 3 "arm_add_operand" "rI,L")])) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_COND_EXEC" - "* - if (operands[3] == const0_rtx) - { -@@ -9271,6 +9783,7 @@ - return \"\"; - " - [(set_attr "conds" "use") -+ (set_attr "insn" "mov") - (set_attr "length" "4,4,8")] - ) - -@@ -9282,7 +9795,7 @@ - (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) - (match_operand:SI 1 "s_register_operand" "0,?r")])) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_SINGLE_COND_EXEC" - "* - if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx) - return \"%i5\\t%0, %1, %2, lsr #31\"; -@@ -9678,7 +10191,7 @@ - (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") - (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_COND_EXEC" - "* - if (GET_CODE (operands[5]) == LT - && (operands[4] == const0_rtx)) -@@ -9744,7 +10257,7 @@ - (match_operand:SI 3 "arm_add_operand" "rIL,rIL")) - (match_operand:SI 1 "arm_rhs_operand" "0,?rI"))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_SINGLE_COND_EXEC" - "#" - [(set_attr "conds" "clob") - (set_attr "length" "8,12")] -@@ -9780,7 +10293,7 @@ - (match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 3 "arm_add_operand" "rIL,rIL")))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_SINGLE_COND_EXEC" - "#" - [(set_attr "conds" "clob") - (set_attr "length" "8,12")] -@@ -9818,7 +10331,7 @@ - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "arm_rhs_operand" "rI")]))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_SINGLE_COND_EXEC" - "#" - [(set_attr "conds" "clob") - (set_attr "length" "12")] -@@ -9968,7 +10481,7 @@ - (not:SI - (match_operand:SI 2 "s_register_operand" "r,r")))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_SINGLE_COND_EXEC" - "#" - [(set_attr "conds" "clob") - (set_attr "length" "8,12")] -@@ -9987,6 +10500,7 @@ - mov%d4\\t%0, %1\;mvn%D4\\t%0, %2 - mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2" - [(set_attr "conds" "use") -+ (set_attr "insn" "mvn") - (set_attr "length" "4,8,8")] - ) - -@@ -10000,7 +10514,7 @@ - (match_operand:SI 2 "s_register_operand" "r,r")) - (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_SINGLE_COND_EXEC" - "#" - [(set_attr "conds" "clob") - (set_attr "length" "8,12")] -@@ -10019,6 +10533,7 @@ - mov%D4\\t%0, %1\;mvn%d4\\t%0, %2 - mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2" - [(set_attr "conds" "use") -+ (set_attr "insn" "mvn") - (set_attr "length" "4,8,8")] - ) - -@@ -10033,7 +10548,7 @@ - (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]) - (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_SINGLE_COND_EXEC" - "#" - [(set_attr "conds" "clob") - (set_attr "length" "8,12")] -@@ -10055,10 +10570,23 @@ - mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4" - [(set_attr "conds" "use") - (set_attr "shift" "2") -- (set_attr "length" "4,8,8") -+ (set_attr "insn" "mov") - (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set_attr_alternative "length" -+ [(if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)) -+ (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 12) -+ (const_int 8)) -+ (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 12) -+ (const_int 8))])] - ) - - (define_insn "*ifcompare_move_shift" -@@ -10072,7 +10600,7 @@ - [(match_operand:SI 2 "s_register_operand" "r,r") - (match_operand:SI 3 "arm_rhs_operand" "rM,rM")]))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_SINGLE_COND_EXEC" - "#" - [(set_attr "conds" "clob") - (set_attr "length" "8,12")] -@@ -10094,10 +10622,24 @@ - mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4" - [(set_attr "conds" "use") - (set_attr "shift" "2") -- (set_attr "length" "4,8,8") -+ (set_attr "insn" "mov") - (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "") - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set_attr_alternative "length" -+ [(if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 8) -+ (const_int 4)) -+ (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 12) -+ (const_int 8)) -+ (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 12) -+ (const_int 8))]) -+ (set_attr "insn" "mov")] - ) - - (define_insn "*ifcompare_shift_shift" -@@ -10113,7 +10655,7 @@ - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "arm_rhs_operand" "rM")]))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_SINGLE_COND_EXEC" - "#" - [(set_attr "conds" "clob") - (set_attr "length" "12")] -@@ -10134,12 +10676,16 @@ - "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7" - [(set_attr "conds" "use") - (set_attr "shift" "1") -- (set_attr "length" "8") -+ (set_attr "insn" "mov") - (set (attr "type") (if_then_else - (and (match_operand 2 "const_int_operand" "") - (match_operand 4 "const_int_operand" "")) - (const_string "alu_shift") -- (const_string "alu_shift_reg")))] -+ (const_string "alu_shift_reg"))) -+ (set (attr "length") (if_then_else (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "fix_janus" "yes")) -+ (const_int 16) -+ (const_int 8)))] - ) - - (define_insn "*ifcompare_not_arith" -@@ -10153,7 +10699,7 @@ - [(match_operand:SI 2 "s_register_operand" "r") - (match_operand:SI 3 "arm_rhs_operand" "rI")]))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_SINGLE_COND_EXEC" - "#" - [(set_attr "conds" "clob") - (set_attr "length" "12")] -@@ -10171,6 +10717,7 @@ - "TARGET_ARM" - "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3" - [(set_attr "conds" "use") -+ (set_attr "insn" "mvn") - (set_attr "length" "8")] - ) - -@@ -10185,7 +10732,7 @@ - (match_operand:SI 3 "arm_rhs_operand" "rI")]) - (not:SI (match_operand:SI 1 "s_register_operand" "r")))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_SINGLE_COND_EXEC" - "#" - [(set_attr "conds" "clob") - (set_attr "length" "12")] -@@ -10203,6 +10750,7 @@ - "TARGET_ARM" - "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3" - [(set_attr "conds" "use") -+ (set_attr "insn" "mvn") - (set_attr "length" "8")] - ) - -@@ -10215,7 +10763,7 @@ - (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")) - (match_operand:SI 1 "arm_not_operand" "0,?rIK"))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_SINGLE_COND_EXEC" - "#" - [(set_attr "conds" "clob") - (set_attr "length" "8,12")] -@@ -10246,7 +10794,7 @@ - (match_operand:SI 1 "arm_not_operand" "0,?rIK") - (neg:SI (match_operand:SI 2 "s_register_operand" "r,r")))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM" -+ "TARGET_ARM && !TARGET_NO_SINGLE_COND_EXEC" - "#" - [(set_attr "conds" "clob") - (set_attr "length" "8,12")] -@@ -10614,7 +11162,7 @@ - (match_dup 0) - (match_operand 4 "" ""))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM && reload_completed" -+ "TARGET_ARM && reload_completed && !TARGET_NO_SINGLE_COND_EXEC" - [(set (match_dup 5) (match_dup 6)) - (cond_exec (match_dup 7) - (set (match_dup 0) (match_dup 4)))] -@@ -10642,7 +11190,7 @@ - (match_operand 4 "" "") - (match_dup 0))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM && reload_completed" -+ "TARGET_ARM && reload_completed && !TARGET_NO_SINGLE_COND_EXEC" - [(set (match_dup 5) (match_dup 6)) - (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)]) - (set (match_dup 0) (match_dup 4)))] -@@ -10663,7 +11211,7 @@ - (match_operand 4 "" "") - (match_operand 5 "" ""))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM && reload_completed" -+ "TARGET_ARM && reload_completed && !TARGET_NO_SINGLE_COND_EXEC" - [(set (match_dup 6) (match_dup 7)) - (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)]) - (set (match_dup 0) (match_dup 4))) -@@ -10695,7 +11243,7 @@ - (not:SI - (match_operand:SI 5 "s_register_operand" "")))) - (clobber (reg:CC CC_REGNUM))] -- "TARGET_ARM && reload_completed" -+ "TARGET_ARM && reload_completed && !TARGET_NO_SINGLE_COND_EXEC" - [(set (match_dup 6) (match_dup 7)) - (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)]) - (set (match_dup 0) (match_dup 4))) -@@ -10730,6 +11278,7 @@ - mvn%D4\\t%0, %2 - mov%d4\\t%0, %1\;mvn%D4\\t%0, %2" - [(set_attr "conds" "use") -+ (set_attr "insn" "mvn") - (set_attr "length" "4,8")] - ) - -@@ -10864,6 +11413,24 @@ - " - ) - -+(define_insn "align_16" -+ [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN16)] -+ "TARGET_EITHER" -+ "* -+ assemble_align (128); -+ return \"\"; -+ " -+) -+ -+(define_insn "align_32" -+ [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN32)] -+ "TARGET_EITHER" -+ "* -+ assemble_align (256); -+ return \"\"; -+ " -+) -+ - (define_insn "consttable_end" - [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)] - "TARGET_EITHER" -@@ -10890,6 +11457,7 @@ - "TARGET_THUMB1" - "* - making_const_table = TRUE; -+ gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT); - assemble_integer (operands[0], 2, BITS_PER_WORD, 1); - assemble_zeros (2); - return \"\"; -@@ -10902,19 +11470,30 @@ - "TARGET_EITHER" - "* - { -+ rtx x = operands[0]; - making_const_table = TRUE; -- switch (GET_MODE_CLASS (GET_MODE (operands[0]))) -+ switch (GET_MODE_CLASS (GET_MODE (x))) - { - case MODE_FLOAT: -- { -- REAL_VALUE_TYPE r; -- REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]); -- assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD); -- break; -- } -+ if (GET_MODE (x) == HFmode) -+ arm_emit_fp16_const (x); -+ else -+ { -+ REAL_VALUE_TYPE r; -+ REAL_VALUE_FROM_CONST_DOUBLE (r, x); -+ assemble_real (r, GET_MODE (x), BITS_PER_WORD); -+ } -+ break; - default: -- assemble_integer (operands[0], 4, BITS_PER_WORD, 1); -- mark_symbol_refs_as_used (operands[0]); -+ /* XXX: Sometimes gcc does something really dumb and ends up with -+ a HIGH in a constant pool entry, usually because it's trying to -+ load into a VFP register. We know this will always be used in -+ combination with a LO_SUM which ignores the high bits, so just -+ strip off the HIGH. */ -+ if (GET_CODE (x) == HIGH) -+ x = XEXP (x, 0); -+ assemble_integer (x, 4, BITS_PER_WORD, 1); -+ mark_symbol_refs_as_used (x); - break; - } - return \"\"; -@@ -11008,6 +11587,28 @@ - [(set_attr "predicable" "yes") - (set_attr "insn" "clz")]) - -+(define_insn "rbitsi2" -+ [(set (match_operand:SI 0 "s_register_operand" "=r") -+ (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))] -+ "TARGET_32BIT && arm_arch_thumb2" -+ "rbit%?\\t%0, %1" -+ [(set_attr "predicable" "yes") -+ (set_attr "insn" "clz")]) -+ -+(define_expand "ctzsi2" -+ [(set (match_operand:SI 0 "s_register_operand" "") -+ (ctz:SI (match_operand:SI 1 "s_register_operand" "")))] -+ "TARGET_32BIT && arm_arch_thumb2" -+ " -+ { -+ rtx tmp = gen_reg_rtx (SImode); -+ emit_insn (gen_rbitsi2 (tmp, operands[1])); -+ emit_insn (gen_clzsi2 (operands[0], tmp)); -+ } -+ DONE; -+ " -+) -+ - ;; V5E instructions. - - (define_insn "prefetch" -@@ -11017,13 +11618,15 @@ - "TARGET_32BIT && arm_arch5e" - "pld\\t%a0") - --;; General predication pattern -+;; General predication pattern. -+;; Conditional branches are available as both arm_cond_branch and -+;; predicated arm_jump, so it doesn't matter if we disable the latter. - - (define_cond_exec - [(match_operator 0 "arm_comparison_operator" - [(match_operand 1 "cc_register" "") - (const_int 0)])] -- "TARGET_32BIT" -+ "TARGET_32BIT && !TARGET_NO_SINGLE_COND_EXEC" - "" - ) - ---- a/gcc/config/arm/arm-modes.def -+++ b/gcc/config/arm/arm-modes.def -@@ -25,6 +25,11 @@ - FIXME What format is this? */ - FLOAT_MODE (XF, 12, 0); - -+/* Half-precision floating point */ -+FLOAT_MODE (HF, 2, 0); -+ADJUST_FLOAT_FORMAT (HF, ((arm_fp16_format == ARM_FP16_FORMAT_ALTERNATIVE) -+ ? &arm_half_format : &ieee_half_format)); -+ - /* CCFPEmode should be used with floating inequalities, - CCFPmode should be used with floating equalities. - CC_NOOVmode should be used with SImode integer equalities. -@@ -62,6 +67,4 @@ - INT_MODE (EI, 24); - INT_MODE (OI, 32); - INT_MODE (CI, 48); --/* ??? This should actually have 512 bits but the precision only has 9 -- bits. */ --FRACTIONAL_INT_MODE (XI, 511, 64); -+INT_MODE (XI, 64); ---- a/gcc/config/arm/arm_neon.h -+++ b/gcc/config/arm/arm_neon.h -@@ -61,7 +61,7 @@ - typedef __builtin_neon_usi uint32x4_t __attribute__ ((__vector_size__ (16))); - typedef __builtin_neon_udi uint64x2_t __attribute__ ((__vector_size__ (16))); - --typedef __builtin_neon_sf float32_t; -+typedef float float32_t; - typedef __builtin_neon_poly8 poly8_t; - typedef __builtin_neon_poly16 poly16_t; - -@@ -5085,7 +5085,7 @@ - __extension__ static __inline float32x2_t __attribute__ ((__always_inline__)) - vset_lane_f32 (float32_t __a, float32x2_t __b, const int __c) - { -- return (float32x2_t)__builtin_neon_vset_lanev2sf (__a, __b, __c); -+ return (float32x2_t)__builtin_neon_vset_lanev2sf ((__builtin_neon_sf) __a, __b, __c); - } - - __extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) -@@ -5151,7 +5151,7 @@ - __extension__ static __inline float32x4_t __attribute__ ((__always_inline__)) - vsetq_lane_f32 (float32_t __a, float32x4_t __b, const int __c) - { -- return (float32x4_t)__builtin_neon_vset_lanev4sf (__a, __b, __c); -+ return (float32x4_t)__builtin_neon_vset_lanev4sf ((__builtin_neon_sf) __a, __b, __c); - } - - __extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) -@@ -5283,7 +5283,7 @@ - __extension__ static __inline float32x2_t __attribute__ ((__always_inline__)) - vdup_n_f32 (float32_t __a) - { -- return (float32x2_t)__builtin_neon_vdup_nv2sf (__a); -+ return (float32x2_t)__builtin_neon_vdup_nv2sf ((__builtin_neon_sf) __a); - } - - __extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) -@@ -5349,7 +5349,7 @@ - __extension__ static __inline float32x4_t __attribute__ ((__always_inline__)) - vdupq_n_f32 (float32_t __a) - { -- return (float32x4_t)__builtin_neon_vdup_nv4sf (__a); -+ return (float32x4_t)__builtin_neon_vdup_nv4sf ((__builtin_neon_sf) __a); - } - - __extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) -@@ -5415,7 +5415,7 @@ - __extension__ static __inline float32x2_t __attribute__ ((__always_inline__)) - vmov_n_f32 (float32_t __a) - { -- return (float32x2_t)__builtin_neon_vdup_nv2sf (__a); -+ return (float32x2_t)__builtin_neon_vdup_nv2sf ((__builtin_neon_sf) __a); - } - - __extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) -@@ -5481,7 +5481,7 @@ - __extension__ static __inline float32x4_t __attribute__ ((__always_inline__)) - vmovq_n_f32 (float32_t __a) - { -- return (float32x4_t)__builtin_neon_vdup_nv4sf (__a); -+ return (float32x4_t)__builtin_neon_vdup_nv4sf ((__builtin_neon_sf) __a); - } - - __extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) -@@ -6591,7 +6591,7 @@ - __extension__ static __inline float32x2_t __attribute__ ((__always_inline__)) - vmul_n_f32 (float32x2_t __a, float32_t __b) - { -- return (float32x2_t)__builtin_neon_vmul_nv2sf (__a, __b, 3); -+ return (float32x2_t)__builtin_neon_vmul_nv2sf (__a, (__builtin_neon_sf) __b, 3); - } - - __extension__ static __inline uint16x4_t __attribute__ ((__always_inline__)) -@@ -6621,7 +6621,7 @@ - __extension__ static __inline float32x4_t __attribute__ ((__always_inline__)) - vmulq_n_f32 (float32x4_t __a, float32_t __b) - { -- return (float32x4_t)__builtin_neon_vmul_nv4sf (__a, __b, 3); -+ return (float32x4_t)__builtin_neon_vmul_nv4sf (__a, (__builtin_neon_sf) __b, 3); - } - - __extension__ static __inline uint16x8_t __attribute__ ((__always_inline__)) -@@ -6735,7 +6735,7 @@ - __extension__ static __inline float32x2_t __attribute__ ((__always_inline__)) - vmla_n_f32 (float32x2_t __a, float32x2_t __b, float32_t __c) - { -- return (float32x2_t)__builtin_neon_vmla_nv2sf (__a, __b, __c, 3); -+ return (float32x2_t)__builtin_neon_vmla_nv2sf (__a, __b, (__builtin_neon_sf) __c, 3); - } - - __extension__ static __inline uint16x4_t __attribute__ ((__always_inline__)) -@@ -6765,7 +6765,7 @@ - __extension__ static __inline float32x4_t __attribute__ ((__always_inline__)) - vmlaq_n_f32 (float32x4_t __a, float32x4_t __b, float32_t __c) - { -- return (float32x4_t)__builtin_neon_vmla_nv4sf (__a, __b, __c, 3); -+ return (float32x4_t)__builtin_neon_vmla_nv4sf (__a, __b, (__builtin_neon_sf) __c, 3); - } - - __extension__ static __inline uint16x8_t __attribute__ ((__always_inline__)) -@@ -6831,7 +6831,7 @@ - __extension__ static __inline float32x2_t __attribute__ ((__always_inline__)) - vmls_n_f32 (float32x2_t __a, float32x2_t __b, float32_t __c) - { -- return (float32x2_t)__builtin_neon_vmls_nv2sf (__a, __b, __c, 3); -+ return (float32x2_t)__builtin_neon_vmls_nv2sf (__a, __b, (__builtin_neon_sf) __c, 3); - } - - __extension__ static __inline uint16x4_t __attribute__ ((__always_inline__)) -@@ -6861,7 +6861,7 @@ - __extension__ static __inline float32x4_t __attribute__ ((__always_inline__)) - vmlsq_n_f32 (float32x4_t __a, float32x4_t __b, float32_t __c) - { -- return (float32x4_t)__builtin_neon_vmls_nv4sf (__a, __b, __c, 3); -+ return (float32x4_t)__builtin_neon_vmls_nv4sf (__a, __b, (__builtin_neon_sf) __c, 3); - } - - __extension__ static __inline uint16x8_t __attribute__ ((__always_inline__)) -@@ -7851,7 +7851,7 @@ - __extension__ static __inline float32x2_t __attribute__ ((__always_inline__)) - vld1_f32 (const float32_t * __a) - { -- return (float32x2_t)__builtin_neon_vld1v2sf (__a); -+ return (float32x2_t)__builtin_neon_vld1v2sf ((const __builtin_neon_sf *) __a); - } - - __extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) -@@ -7917,7 +7917,7 @@ - __extension__ static __inline float32x4_t __attribute__ ((__always_inline__)) - vld1q_f32 (const float32_t * __a) - { -- return (float32x4_t)__builtin_neon_vld1v4sf (__a); -+ return (float32x4_t)__builtin_neon_vld1v4sf ((const __builtin_neon_sf *) __a); - } - - __extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) -@@ -7977,7 +7977,7 @@ - __extension__ static __inline float32x2_t __attribute__ ((__always_inline__)) - vld1_lane_f32 (const float32_t * __a, float32x2_t __b, const int __c) - { -- return (float32x2_t)__builtin_neon_vld1_lanev2sf (__a, __b, __c); -+ return (float32x2_t)__builtin_neon_vld1_lanev2sf ((const __builtin_neon_sf *) __a, __b, __c); - } - - __extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) -@@ -8043,7 +8043,7 @@ - __extension__ static __inline float32x4_t __attribute__ ((__always_inline__)) - vld1q_lane_f32 (const float32_t * __a, float32x4_t __b, const int __c) - { -- return (float32x4_t)__builtin_neon_vld1_lanev4sf (__a, __b, __c); -+ return (float32x4_t)__builtin_neon_vld1_lanev4sf ((const __builtin_neon_sf *) __a, __b, __c); - } - - __extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) -@@ -8109,7 +8109,7 @@ - __extension__ static __inline float32x2_t __attribute__ ((__always_inline__)) - vld1_dup_f32 (const float32_t * __a) - { -- return (float32x2_t)__builtin_neon_vld1_dupv2sf (__a); -+ return (float32x2_t)__builtin_neon_vld1_dupv2sf ((const __builtin_neon_sf *) __a); - } - - __extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) -@@ -8175,7 +8175,7 @@ - __extension__ static __inline float32x4_t __attribute__ ((__always_inline__)) - vld1q_dup_f32 (const float32_t * __a) - { -- return (float32x4_t)__builtin_neon_vld1_dupv4sf (__a); -+ return (float32x4_t)__builtin_neon_vld1_dupv4sf ((const __builtin_neon_sf *) __a); - } - - __extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) -@@ -8247,7 +8247,7 @@ - __extension__ static __inline void __attribute__ ((__always_inline__)) - vst1_f32 (float32_t * __a, float32x2_t __b) - { -- __builtin_neon_vst1v2sf (__a, __b); -+ __builtin_neon_vst1v2sf ((__builtin_neon_sf *) __a, __b); - } - - __extension__ static __inline void __attribute__ ((__always_inline__)) -@@ -8313,7 +8313,7 @@ - __extension__ static __inline void __attribute__ ((__always_inline__)) - vst1q_f32 (float32_t * __a, float32x4_t __b) - { -- __builtin_neon_vst1v4sf (__a, __b); -+ __builtin_neon_vst1v4sf ((__builtin_neon_sf *) __a, __b); - } - - __extension__ static __inline void __attribute__ ((__always_inline__)) -@@ -8373,7 +8373,7 @@ - __extension__ static __inline void __attribute__ ((__always_inline__)) - vst1_lane_f32 (float32_t * __a, float32x2_t __b, const int __c) - { -- __builtin_neon_vst1_lanev2sf (__a, __b, __c); -+ __builtin_neon_vst1_lanev2sf ((__builtin_neon_sf *) __a, __b, __c); - } - - __extension__ static __inline void __attribute__ ((__always_inline__)) -@@ -8439,7 +8439,7 @@ - __extension__ static __inline void __attribute__ ((__always_inline__)) - vst1q_lane_f32 (float32_t * __a, float32x4_t __b, const int __c) - { -- __builtin_neon_vst1_lanev4sf (__a, __b, __c); -+ __builtin_neon_vst1_lanev4sf ((__builtin_neon_sf *) __a, __b, __c); - } - - __extension__ static __inline void __attribute__ ((__always_inline__)) -@@ -8512,7 +8512,7 @@ - vld2_f32 (const float32_t * __a) - { - union { float32x2x2_t __i; __builtin_neon_ti __o; } __rv; -- __rv.__o = __builtin_neon_vld2v2sf (__a); -+ __rv.__o = __builtin_neon_vld2v2sf ((const __builtin_neon_sf *) __a); - return __rv.__i; - } - -@@ -8600,7 +8600,7 @@ - vld2q_f32 (const float32_t * __a) - { - union { float32x4x2_t __i; __builtin_neon_oi __o; } __rv; -- __rv.__o = __builtin_neon_vld2v4sf (__a); -+ __rv.__o = __builtin_neon_vld2v4sf ((const __builtin_neon_sf *) __a); - return __rv.__i; - } - -@@ -8676,7 +8676,7 @@ - { - union { float32x2x2_t __i; __builtin_neon_ti __o; } __bu = { __b }; - union { float32x2x2_t __i; __builtin_neon_ti __o; } __rv; -- __rv.__o = __builtin_neon_vld2_lanev2sf (__a, __bu.__o, __c); -+ __rv.__o = __builtin_neon_vld2_lanev2sf ((const __builtin_neon_sf *) __a, __bu.__o, __c); - return __rv.__i; - } - -@@ -8748,7 +8748,7 @@ - { - union { float32x4x2_t __i; __builtin_neon_oi __o; } __bu = { __b }; - union { float32x4x2_t __i; __builtin_neon_oi __o; } __rv; -- __rv.__o = __builtin_neon_vld2_lanev4sf (__a, __bu.__o, __c); -+ __rv.__o = __builtin_neon_vld2_lanev4sf ((const __builtin_neon_sf *) __a, __bu.__o, __c); - return __rv.__i; - } - -@@ -8807,7 +8807,7 @@ - vld2_dup_f32 (const float32_t * __a) - { - union { float32x2x2_t __i; __builtin_neon_ti __o; } __rv; -- __rv.__o = __builtin_neon_vld2_dupv2sf (__a); -+ __rv.__o = __builtin_neon_vld2_dupv2sf ((const __builtin_neon_sf *) __a); - return __rv.__i; - } - -@@ -8892,7 +8892,7 @@ - vst2_f32 (float32_t * __a, float32x2x2_t __b) - { - union { float32x2x2_t __i; __builtin_neon_ti __o; } __bu = { __b }; -- __builtin_neon_vst2v2sf (__a, __bu.__o); -+ __builtin_neon_vst2v2sf ((__builtin_neon_sf *) __a, __bu.__o); - } - - __extension__ static __inline void __attribute__ ((__always_inline__)) -@@ -8969,7 +8969,7 @@ - vst2q_f32 (float32_t * __a, float32x4x2_t __b) - { - union { float32x4x2_t __i; __builtin_neon_oi __o; } __bu = { __b }; -- __builtin_neon_vst2v4sf (__a, __bu.__o); -+ __builtin_neon_vst2v4sf ((__builtin_neon_sf *) __a, __bu.__o); - } - - __extension__ static __inline void __attribute__ ((__always_inline__)) -@@ -9032,7 +9032,7 @@ - vst2_lane_f32 (float32_t * __a, float32x2x2_t __b, const int __c) - { - union { float32x2x2_t __i; __builtin_neon_ti __o; } __bu = { __b }; -- __builtin_neon_vst2_lanev2sf (__a, __bu.__o, __c); -+ __builtin_neon_vst2_lanev2sf ((__builtin_neon_sf *) __a, __bu.__o, __c); - } - - __extension__ static __inline void __attribute__ ((__always_inline__)) -@@ -9088,7 +9088,7 @@ - vst2q_lane_f32 (float32_t * __a, float32x4x2_t __b, const int __c) - { - union { float32x4x2_t __i; __builtin_neon_oi __o; } __bu = { __b }; -- __builtin_neon_vst2_lanev4sf (__a, __bu.__o, __c); -+ __builtin_neon_vst2_lanev4sf ((__builtin_neon_sf *) __a, __bu.__o, __c); - } - - __extension__ static __inline void __attribute__ ((__always_inline__)) -@@ -9140,7 +9140,7 @@ - vld3_f32 (const float32_t * __a) - { - union { float32x2x3_t __i; __builtin_neon_ei __o; } __rv; -- __rv.__o = __builtin_neon_vld3v2sf (__a); -+ __rv.__o = __builtin_neon_vld3v2sf ((const __builtin_neon_sf *) __a); - return __rv.__i; - } - -@@ -9228,7 +9228,7 @@ - vld3q_f32 (const float32_t * __a) - { - union { float32x4x3_t __i; __builtin_neon_ci __o; } __rv; -- __rv.__o = __builtin_neon_vld3v4sf (__a); -+ __rv.__o = __builtin_neon_vld3v4sf ((const __builtin_neon_sf *) __a); - return __rv.__i; - } - -@@ -9304,7 +9304,7 @@ - { - union { float32x2x3_t __i; __builtin_neon_ei __o; } __bu = { __b }; - union { float32x2x3_t __i; __builtin_neon_ei __o; } __rv; -- __rv.__o = __builtin_neon_vld3_lanev2sf (__a, __bu.__o, __c); -+ __rv.__o = __builtin_neon_vld3_lanev2sf ((const __builtin_neon_sf *) __a, __bu.__o, __c); - return __rv.__i; - } - -@@ -9376,7 +9376,7 @@ - { - union { float32x4x3_t __i; __builtin_neon_ci __o; } __bu = { __b }; - union { float32x4x3_t __i; __builtin_neon_ci __o; } __rv; -- __rv.__o = __builtin_neon_vld3_lanev4sf (__a, __bu.__o, __c); -+ __rv.__o = __builtin_neon_vld3_lanev4sf ((const __builtin_neon_sf *) __a, __bu.__o, __c); - return __rv.__i; - } - -@@ -9435,7 +9435,7 @@ - vld3_dup_f32 (const float32_t * __a) - { - union { float32x2x3_t __i; __builtin_neon_ei __o; } __rv; -- __rv.__o = __builtin_neon_vld3_dupv2sf (__a); -+ __rv.__o = __builtin_neon_vld3_dupv2sf ((const __builtin_neon_sf *) __a); - return __rv.__i; - } - -@@ -9520,7 +9520,7 @@ - vst3_f32 (float32_t * __a, float32x2x3_t __b) - { - union { float32x2x3_t __i; __builtin_neon_ei __o; } __bu = { __b }; -- __builtin_neon_vst3v2sf (__a, __bu.__o); -+ __builtin_neon_vst3v2sf ((__builtin_neon_sf *) __a, __bu.__o); - } - - __extension__ static __inline void __attribute__ ((__always_inline__)) -@@ -9597,7 +9597,7 @@ - vst3q_f32 (float32_t * __a, float32x4x3_t __b) - { - union { float32x4x3_t __i; __builtin_neon_ci __o; } __bu = { __b }; -- __builtin_neon_vst3v4sf (__a, __bu.__o); -+ __builtin_neon_vst3v4sf ((__builtin_neon_sf *) __a, __bu.__o); - } - - __extension__ static __inline void __attribute__ ((__always_inline__)) -@@ -9660,7 +9660,7 @@ - vst3_lane_f32 (float32_t * __a, float32x2x3_t __b, const int __c) - { - union { float32x2x3_t __i; __builtin_neon_ei __o; } __bu = { __b }; -- __builtin_neon_vst3_lanev2sf (__a, __bu.__o, __c); -+ __builtin_neon_vst3_lanev2sf ((__builtin_neon_sf *) __a, __bu.__o, __c); - } - - __extension__ static __inline void __attribute__ ((__always_inline__)) -@@ -9716,7 +9716,7 @@ - vst3q_lane_f32 (float32_t * __a, float32x4x3_t __b, const int __c) - { - union { float32x4x3_t __i; __builtin_neon_ci __o; } __bu = { __b }; -- __builtin_neon_vst3_lanev4sf (__a, __bu.__o, __c); -+ __builtin_neon_vst3_lanev4sf ((__builtin_neon_sf *) __a, __bu.__o, __c); - } - - __extension__ static __inline void __attribute__ ((__always_inline__)) -@@ -9768,7 +9768,7 @@ - vld4_f32 (const float32_t * __a) - { - union { float32x2x4_t __i; __builtin_neon_oi __o; } __rv; -- __rv.__o = __builtin_neon_vld4v2sf (__a); -+ __rv.__o = __builtin_neon_vld4v2sf ((const __builtin_neon_sf *) __a); - return __rv.__i; - } - -@@ -9856,7 +9856,7 @@ - vld4q_f32 (const float32_t * __a) - { - union { float32x4x4_t __i; __builtin_neon_xi __o; } __rv; -- __rv.__o = __builtin_neon_vld4v4sf (__a); -+ __rv.__o = __builtin_neon_vld4v4sf ((const __builtin_neon_sf *) __a); - return __rv.__i; - } - -@@ -9932,7 +9932,7 @@ - { - union { float32x2x4_t __i; __builtin_neon_oi __o; } __bu = { __b }; - union { float32x2x4_t __i; __builtin_neon_oi __o; } __rv; -- __rv.__o = __builtin_neon_vld4_lanev2sf (__a, __bu.__o, __c); -+ __rv.__o = __builtin_neon_vld4_lanev2sf ((const __builtin_neon_sf *) __a, __bu.__o, __c); - return __rv.__i; - } - -@@ -10004,7 +10004,7 @@ - { - union { float32x4x4_t __i; __builtin_neon_xi __o; } __bu = { __b }; - union { float32x4x4_t __i; __builtin_neon_xi __o; } __rv; -- __rv.__o = __builtin_neon_vld4_lanev4sf (__a, __bu.__o, __c); -+ __rv.__o = __builtin_neon_vld4_lanev4sf ((const __builtin_neon_sf *) __a, __bu.__o, __c); - return __rv.__i; - } - -@@ -10063,7 +10063,7 @@ - vld4_dup_f32 (const float32_t * __a) - { - union { float32x2x4_t __i; __builtin_neon_oi __o; } __rv; -- __rv.__o = __builtin_neon_vld4_dupv2sf (__a); -+ __rv.__o = __builtin_neon_vld4_dupv2sf ((const __builtin_neon_sf *) __a); - return __rv.__i; - } - -@@ -10148,7 +10148,7 @@ - vst4_f32 (float32_t * __a, float32x2x4_t __b) - { - union { float32x2x4_t __i; __builtin_neon_oi __o; } __bu = { __b }; -- __builtin_neon_vst4v2sf (__a, __bu.__o); -+ __builtin_neon_vst4v2sf ((__builtin_neon_sf *) __a, __bu.__o); - } - - __extension__ static __inline void __attribute__ ((__always_inline__)) -@@ -10225,7 +10225,7 @@ - vst4q_f32 (float32_t * __a, float32x4x4_t __b) - { - union { float32x4x4_t __i; __builtin_neon_xi __o; } __bu = { __b }; -- __builtin_neon_vst4v4sf (__a, __bu.__o); -+ __builtin_neon_vst4v4sf ((__builtin_neon_sf *) __a, __bu.__o); - } - - __extension__ static __inline void __attribute__ ((__always_inline__)) -@@ -10288,7 +10288,7 @@ - vst4_lane_f32 (float32_t * __a, float32x2x4_t __b, const int __c) - { - union { float32x2x4_t __i; __builtin_neon_oi __o; } __bu = { __b }; -- __builtin_neon_vst4_lanev2sf (__a, __bu.__o, __c); -+ __builtin_neon_vst4_lanev2sf ((__builtin_neon_sf *) __a, __bu.__o, __c); - } - - __extension__ static __inline void __attribute__ ((__always_inline__)) -@@ -10344,7 +10344,7 @@ - vst4q_lane_f32 (float32_t * __a, float32x4x4_t __b, const int __c) - { - union { float32x4x4_t __i; __builtin_neon_xi __o; } __bu = { __b }; -- __builtin_neon_vst4_lanev4sf (__a, __bu.__o, __c); -+ __builtin_neon_vst4_lanev4sf ((__builtin_neon_sf *) __a, __bu.__o, __c); - } - - __extension__ static __inline void __attribute__ ((__always_inline__)) ---- a/gcc/config/arm/arm.opt -+++ b/gcc/config/arm/arm.opt -@@ -78,6 +78,10 @@ - mfp= - Target RejectNegative Joined Undocumented Var(target_fpe_name) - -+mfp16-format= -+Target RejectNegative Joined Var(target_fp16_format_name) -+Specify the __fp16 floating-point format -+ - ;; Now ignored. - mfpe - Target RejectNegative Mask(FPE) Undocumented -@@ -93,6 +97,10 @@ - Target RejectNegative - Alias for -mfloat-abi=hard - -+mfix-janus-2cc -+Target Report Mask(FIX_JANUS) -+Work around hardware errata for Avalent Janus 2CC cores. -+ - mlittle-endian - Target Report RejectNegative InverseMask(BIG_END) - Assume target CPU is configured as little endian -@@ -101,6 +109,10 @@ - Target Report Mask(LONG_CALLS) - Generate call insns as indirect calls, if necessary - -+mmarvell-div -+Target Report Mask(MARVELL_DIV) -+Generate hardware integer division instructions supported by some Marvell cores. -+ - mpic-register= - Target RejectNegative Joined Var(arm_pic_register_string) - Specify the register to be used for PIC addressing -@@ -157,6 +169,10 @@ - Target Report Mask(NEON_VECTORIZE_QUAD) - Use Neon quad-word (rather than double-word) registers for vectorization - -+mlow-irq-latency -+Target Report Var(low_irq_latency) -+Try to reduce interrupt latency of the generated code -+ - mword-relocations - Target Report Var(target_word_relocations) Init(TARGET_DEFAULT_WORD_RELOCATIONS) - Only generate absolute relocations on word sized values. ---- a/gcc/config/arm/arm-protos.h -+++ b/gcc/config/arm/arm-protos.h -@@ -88,7 +88,7 @@ - - extern int cirrus_memory_offset (rtx); - extern int arm_coproc_mem_operand (rtx, bool); --extern int neon_vector_mem_operand (rtx, bool); -+extern int neon_vector_mem_operand (rtx, int); - extern int neon_struct_mem_operand (rtx); - extern int arm_no_early_store_addr_dep (rtx, rtx); - extern int arm_no_early_alu_shift_dep (rtx, rtx); -@@ -144,6 +144,7 @@ - extern int arm_debugger_arg_offset (int, rtx); - extern bool arm_is_long_call_p (tree); - extern int arm_emit_vector_const (FILE *, rtx); -+extern void arm_emit_fp16_const (rtx c); - extern const char * arm_output_load_gr (rtx *); - extern const char *vfp_output_fstmd (rtx *); - extern void arm_set_return_address (rtx, rtx); -@@ -154,13 +155,15 @@ - - #if defined TREE_CODE - extern rtx arm_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int); -+extern void arm_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, -+ tree, bool); - extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree); - extern bool arm_pad_arg_upward (enum machine_mode, const_tree); - extern bool arm_pad_reg_upward (enum machine_mode, tree, int); - extern bool arm_needs_doubleword_align (enum machine_mode, tree); --extern rtx arm_function_value(const_tree, const_tree); - #endif - extern int arm_apply_result_size (void); -+extern rtx aapcs_libcall_value (enum machine_mode); - - #endif /* RTX_CODE */ - ---- a/gcc/config/arm/arm-tune.md -+++ b/gcc/config/arm/arm-tune.md -@@ -1,5 +1,5 @@ - ;; -*- buffer-read-only: t -*- - ;; Generated automatically by gentune.sh from arm-cores.def - (define_attr "tune" -- "arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7d,arm7di,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7m,arm7dm,arm7dmi,arm8,arm810,strongarm,strongarm110,strongarm1100,strongarm1110,arm7tdmi,arm7tdmis,arm710t,arm720t,arm740t,arm9,arm9tdmi,arm920,arm920t,arm922t,arm940t,ep9312,arm10tdmi,arm1020t,arm9e,arm946es,arm966es,arm968es,arm10e,arm1020e,arm1022e,xscale,iwmmxt,iwmmxt2,arm926ejs,arm1026ejs,arm1136js,arm1136jfs,arm1176jzs,arm1176jzfs,mpcorenovfp,mpcore,arm1156t2s,cortexa8,cortexa9,cortexr4,cortexr4f,cortexm3,cortexm1" -+ "arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7d,arm7di,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7m,arm7dm,arm7dmi,arm8,arm810,strongarm,strongarm110,strongarm1100,strongarm1110,arm7tdmi,arm7tdmis,arm710t,arm720t,arm740t,arm9,arm9tdmi,arm920,arm920t,arm922t,arm940t,ep9312,arm10tdmi,arm1020t,arm9e,arm946es,arm966es,arm968es,arm10e,arm1020e,arm1022e,xscale,iwmmxt,iwmmxt2,marvell_f,arm926ejs,arm1026ejs,arm1136js,arm1136jfs,arm1176jzs,arm1176jzfs,mpcorenovfp,mpcore,arm1156t2s,cortexa5,cortexa8,cortexa9,cortexr4,cortexr4f,cortexm3,cortexm1,cortexm0" - (const (symbol_ref "arm_tune"))) ---- a/gcc/config/arm/bpabi.h -+++ b/gcc/config/arm/bpabi.h -@@ -30,7 +30,7 @@ - - /* Section 4.1 of the AAPCS requires the use of VFP format. */ - #undef FPUTYPE_DEFAULT --#define FPUTYPE_DEFAULT FPUTYPE_VFP -+#define FPUTYPE_DEFAULT "vfp" - - /* TARGET_BIG_ENDIAN_DEFAULT is set in - config.gcc for big endian configurations. */ -@@ -53,6 +53,8 @@ - - #define TARGET_FIX_V4BX_SPEC " %{mcpu=arm8|mcpu=arm810|mcpu=strongarm*|march=armv4:--fix-v4bx}" - -+#define BE8_LINK_SPEC " %{mbig-endian:%{march=armv7-a|mcpu=cortex-a5|mcpu=cortex-a8|mcpu=cortex-a9:%{!r:--be8}}}" -+ - /* Tell the assembler to build BPABI binaries. */ - #undef SUBTARGET_EXTRA_ASM_SPEC - #define SUBTARGET_EXTRA_ASM_SPEC "%{mabi=apcs-gnu|mabi=atpcs:-meabi=gnu;:-meabi=5}" TARGET_FIX_V4BX_SPEC -@@ -65,7 +67,7 @@ - #define BPABI_LINK_SPEC \ - "%{mbig-endian:-EB} %{mlittle-endian:-EL} " \ - "%{static:-Bstatic} %{shared:-shared} %{symbolic:-Bsymbolic} " \ -- "-X" SUBTARGET_EXTRA_LINK_SPEC TARGET_FIX_V4BX_SPEC -+ "-X" SUBTARGET_EXTRA_LINK_SPEC TARGET_FIX_V4BX_SPEC BE8_LINK_SPEC - - #undef LINK_SPEC - #define LINK_SPEC BPABI_LINK_SPEC -@@ -90,16 +92,22 @@ - #define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (muldi3, lmul) - #endif - #ifdef L_fixdfdi --#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixdfdi, d2lz) -+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixdfdi, d2lz) \ -+ extern DWtype __fixdfdi (DFtype) __attribute__((pcs("aapcs"))); \ -+ extern UDWtype __fixunsdfdi (DFtype) __asm__("__aeabi_d2ulz") __attribute__((pcs("aapcs"))); - #endif - #ifdef L_fixunsdfdi --#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunsdfdi, d2ulz) -+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunsdfdi, d2ulz) \ -+ extern UDWtype __fixunsdfdi (DFtype) __attribute__((pcs("aapcs"))); - #endif - #ifdef L_fixsfdi --#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixsfdi, f2lz) -+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixsfdi, f2lz) \ -+ extern DWtype __fixsfdi (SFtype) __attribute__((pcs("aapcs"))); \ -+ extern UDWtype __fixunssfdi (SFtype) __asm__("__aeabi_f2ulz") __attribute__((pcs("aapcs"))); - #endif - #ifdef L_fixunssfdi --#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunssfdi, f2ulz) -+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunssfdi, f2ulz) \ -+ extern UDWtype __fixunssfdi (SFtype) __attribute__((pcs("aapcs"))); - #endif - #ifdef L_floatdidf - #define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdidf, l2d) ---- a/gcc/config/arm/bpabi.S -+++ b/gcc/config/arm/bpabi.S -@@ -64,20 +64,69 @@ - - #endif /* L_aeabi_ulcmp */ - -+.macro test_div_by_zero signed -+/* Tail-call to divide-by-zero handlers which may be overridden by the user, -+ so unwinding works properly. */ -+#if defined(__thumb2__) -+ cbnz yyh, 1f -+ cbnz yyl, 1f -+ cmp xxh, #0 -+ do_it eq -+ cmpeq xxl, #0 -+ .ifc \signed, unsigned -+ beq 2f -+ mov xxh, #0xffffffff -+ mov xxl, xxh -+2: -+ .else -+ do_it lt, t -+ movlt xxl, #0 -+ movlt xxh, #0x80000000 -+ do_it gt, t -+ movgt xxh, #0x7fffffff -+ movgt xxl, #0xffffffff -+ .endif -+ b SYM (__aeabi_ldiv0) __PLT__ -+1: -+#else -+ /* Note: Thumb-1 code calls via an ARM shim on processors which -+ support ARM mode. */ -+ cmp yyh, #0 -+ cmpeq yyl, #0 -+ bne 2f -+ cmp xxh, #0 -+ cmpeq xxl, #0 -+ .ifc \signed, unsigned -+ movne xxh, #0xffffffff -+ movne xxl, #0xffffffff -+ .else -+ movlt xxh, #0x80000000 -+ movlt xxl, #0 -+ movgt xxh, #0x7fffffff -+ movgt xxl, #0xffffffff -+ .endif -+ b SYM (__aeabi_ldiv0) __PLT__ -+2: -+#endif -+.endm -+ - #ifdef L_aeabi_ldivmod - - ARM_FUNC_START aeabi_ldivmod -+ test_div_by_zero signed -+ - sub sp, sp, #8 --#if defined(__thumb2__) -+/* Low latency and Thumb-2 do_push implementations can't push sp directly. */ -+#if defined(__thumb2__) || defined(__irq_low_latency__) - mov ip, sp -- push {ip, lr} -+ do_push (ip, lr) - #else -- do_push {sp, lr} -+ stmfd sp!, {sp, lr} - #endif - bl SYM(__gnu_ldivmod_helper) __PLT__ - ldr lr, [sp, #4] - add sp, sp, #8 -- do_pop {r2, r3} -+ do_pop (r2, r3) - RET - - #endif /* L_aeabi_ldivmod */ -@@ -85,17 +134,20 @@ - #ifdef L_aeabi_uldivmod - - ARM_FUNC_START aeabi_uldivmod -+ test_div_by_zero unsigned -+ - sub sp, sp, #8 --#if defined(__thumb2__) -+/* Low latency and Thumb-2 do_push implementations can't push sp directly. */ -+#if defined(__thumb2__) || defined(__irq_low_latency__) - mov ip, sp -- push {ip, lr} -+ do_push (ip, lr) - #else -- do_push {sp, lr} -+ stmfd sp!, {sp, lr} - #endif - bl SYM(__gnu_uldivmod_helper) __PLT__ - ldr lr, [sp, #4] - add sp, sp, #8 -- do_pop {r2, r3} -+ do_pop (r2, r3) - RET - - #endif /* L_aeabi_divmod */ ---- a/gcc/config/arm/bpabi-v6m.S -+++ b/gcc/config/arm/bpabi-v6m.S -@@ -69,9 +69,52 @@ - - #endif /* L_aeabi_ulcmp */ - -+.macro test_div_by_zero signed -+ cmp yyh, #0 -+ bne 7f -+ cmp yyl, #0 -+ bne 7f -+ cmp xxh, #0 -+ bne 2f -+ cmp xxl, #0 -+2: -+ .ifc \signed, unsigned -+ beq 3f -+ mov xxh, #0 -+ mvn xxh, xxh @ 0xffffffff -+ mov xxl, xxh -+3: -+ .else -+ beq 5f -+ blt 6f -+ mov xxl, #0 -+ mvn xxl, xxl @ 0xffffffff -+ lsr xxh, xxl, #1 @ 0x7fffffff -+ b 5f -+6: mov xxh, #0x80 -+ lsl xxh, xxh, #24 @ 0x80000000 -+ mov xxl, #0 -+5: -+ .endif -+ @ tailcalls are tricky on v6-m. -+ push {r0, r1, r2} -+ ldr r0, 1f -+ adr r1, 1f -+ add r0, r1 -+ str r0, [sp, #8] -+ @ We know we are not on armv4t, so pop pc is safe. -+ pop {r0, r1, pc} -+ .align 2 -+1: -+ .word __aeabi_ldiv0 - 1b -+7: -+.endm -+ - #ifdef L_aeabi_ldivmod - - FUNC_START aeabi_ldivmod -+ test_div_by_zero signed -+ - push {r0, r1} - mov r0, sp - push {r0, lr} -@@ -89,6 +132,8 @@ - #ifdef L_aeabi_uldivmod - - FUNC_START aeabi_uldivmod -+ test_div_by_zero unsigned -+ - push {r0, r1} - mov r0, sp - push {r0, lr} ---- a/gcc/config/arm/constraints.md -+++ b/gcc/config/arm/constraints.md -@@ -25,14 +25,15 @@ - ;; In ARM state, 'l' is an alias for 'r' - - ;; The following normal constraints have been used: --;; in ARM/Thumb-2 state: G, H, I, J, K, L, M -+;; in ARM/Thumb-2 state: G, H, I, j, J, K, L, M - ;; in Thumb-1 state: I, J, K, L, M, N, O - - ;; The following multi-letter normal constraints have been used: --;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv -+;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy -+;; in Thumb-1 state: Pa, Pb - - ;; The following memory constraints have been used: --;; in ARM/Thumb-2 state: Q, Ut, Uv, Uy, Un, Us -+;; in ARM/Thumb-2 state: Q, Ut, Uv, Uy, Un, Um, Us - ;; in ARM state: Uq - - -@@ -65,6 +66,13 @@ - (define_register_constraint "h" "TARGET_THUMB ? HI_REGS : NO_REGS" - "In Thumb state the core registers @code{r8}-@code{r15}.") - -+(define_constraint "j" -+ "A constant suitable for a MOVW instruction. (ARM/Thumb-2)" -+ (and (match_test "TARGET_32BIT && arm_arch_thumb2") -+ (ior (match_code "high") -+ (and (match_code "const_int") -+ (match_test "(ival & 0xffff0000) == 0"))))) -+ - (define_register_constraint "k" "STACK_REG" - "@internal The stack register.") - -@@ -116,11 +124,9 @@ - : ((ival >= 0 && ival <= 1020) && ((ival & 3) == 0))"))) - - (define_constraint "N" -- "In ARM/Thumb-2 state a constant suitable for a MOVW instruction. -- In Thumb-1 state a constant in the range 0-31." -+ "Thumb-1 state a constant in the range 0-31." - (and (match_code "const_int") -- (match_test "TARGET_32BIT ? arm_arch_thumb2 && ((ival & 0xffff0000) == 0) -- : (ival >= 0 && ival <= 31)"))) -+ (match_test "!TARGET_32BIT && (ival >= 0 && ival <= 31)"))) - - (define_constraint "O" - "In Thumb-1 state a constant that is a multiple of 4 in the range -@@ -129,6 +135,18 @@ - (match_test "TARGET_THUMB1 && ival >= -508 && ival <= 508 - && ((ival & 3) == 0)"))) - -+(define_constraint "Pa" -+ "@internal In Thumb-1 state a constant in the range -510 to +510" -+ (and (match_code "const_int") -+ (match_test "TARGET_THUMB1 && ival >= -510 && ival <= 510 -+ && (ival > 255 || ival < -255)"))) -+ -+(define_constraint "Pb" -+ "@internal In Thumb-1 state a constant in the range -262 to +262" -+ (and (match_code "const_int") -+ (match_test "TARGET_THUMB1 && ival >= -262 && ival <= 262 -+ && (ival > 255 || ival < -255)"))) -+ - (define_constraint "G" - "In ARM/Thumb-2 state a valid FPA immediate constant." - (and (match_code "const_double") -@@ -189,10 +207,17 @@ - (define_constraint "Dv" - "@internal - In ARM/Thumb-2 state a const_double which can be used with a VFP fconsts -- or fconstd instruction." -+ instruction." - (and (match_code "const_double") - (match_test "TARGET_32BIT && vfp3_const_double_rtx (op)"))) - -+(define_constraint "Dy" -+ "@internal -+ In ARM/Thumb-2 state a const_double which can be used with a VFP fconstd -+ instruction." -+ (and (match_code "const_double") -+ (match_test "TARGET_32BIT && TARGET_VFP_DOUBLE && vfp3_const_double_rtx (op)"))) -+ - (define_memory_constraint "Ut" - "@internal - In ARM/Thumb-2 state an address valid for loading/storing opaque structure -@@ -214,17 +239,24 @@ - - (define_memory_constraint "Un" - "@internal -+ In ARM/Thumb-2 state a valid address for Neon doubleword vector -+ load/store instructions." -+ (and (match_code "mem") -+ (match_test "TARGET_32BIT && neon_vector_mem_operand (op, 0)"))) -+ -+(define_memory_constraint "Um" -+ "@internal - In ARM/Thumb-2 state a valid address for Neon element and structure - load/store instructions." - (and (match_code "mem") -- (match_test "TARGET_32BIT && neon_vector_mem_operand (op, FALSE)"))) -+ (match_test "TARGET_32BIT && neon_vector_mem_operand (op, 2)"))) - - (define_memory_constraint "Us" - "@internal - In ARM/Thumb-2 state a valid address for non-offset loads/stores of - quad-word values in four ARM registers." - (and (match_code "mem") -- (match_test "TARGET_32BIT && neon_vector_mem_operand (op, TRUE)"))) -+ (match_test "TARGET_32BIT && neon_vector_mem_operand (op, 1)"))) - - (define_memory_constraint "Uq" - "@internal ---- /dev/null -+++ b/gcc/config/arm/fp16.c -@@ -0,0 +1,145 @@ -+/* Half-float conversion routines. -+ -+ Copyright (C) 2008, 2009 Free Software Foundation, Inc. -+ Contributed by CodeSourcery. -+ -+ This file is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published by the -+ Free Software Foundation; either version 3, or (at your option) any -+ later version. -+ -+ This file is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ Under Section 7 of GPL version 3, you are granted additional -+ permissions described in the GCC Runtime Library Exception, version -+ 3.1, as published by the Free Software Foundation. -+ -+ You should have received a copy of the GNU General Public License and -+ a copy of the GCC Runtime Library Exception along with this program; -+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -+ <http://www.gnu.org/licenses/>. */ -+ -+static inline unsigned short -+__gnu_f2h_internal(unsigned int a, int ieee) -+{ -+ unsigned short sign = (a >> 16) & 0x8000; -+ int aexp = (a >> 23) & 0xff; -+ unsigned int mantissa = a & 0x007fffff; -+ unsigned int mask; -+ unsigned int increment; -+ -+ if (aexp == 0xff) -+ { -+ if (!ieee) -+ return sign; -+ return sign | 0x7e00 | (mantissa >> 13); -+ } -+ -+ if (aexp == 0 && mantissa == 0) -+ return sign; -+ -+ aexp -= 127; -+ -+ /* Decimal point between bits 22 and 23. */ -+ mantissa |= 0x00800000; -+ if (aexp < -14) -+ { -+ mask = 0x007fffff; -+ if (aexp < -25) -+ aexp = -26; -+ else if (aexp != -25) -+ mask >>= 24 + aexp; -+ } -+ else -+ mask = 0x00001fff; -+ -+ /* Round. */ -+ if (mantissa & mask) -+ { -+ increment = (mask + 1) >> 1; -+ if ((mantissa & mask) == increment) -+ increment = mantissa & (increment << 1); -+ mantissa += increment; -+ if (mantissa >= 0x01000000) -+ { -+ mantissa >>= 1; -+ aexp++; -+ } -+ } -+ -+ if (ieee) -+ { -+ if (aexp > 15) -+ return sign | 0x7c00; -+ } -+ else -+ { -+ if (aexp > 16) -+ return sign | 0x7fff; -+ } -+ -+ if (aexp < -24) -+ return sign; -+ -+ if (aexp < -14) -+ { -+ mantissa >>= -14 - aexp; -+ aexp = -14; -+ } -+ -+ /* We leave the leading 1 in the mantissa, and subtract one -+ from the exponent bias to compensate. */ -+ return sign | (((aexp + 14) << 10) + (mantissa >> 13)); -+} -+ -+unsigned int -+__gnu_h2f_internal(unsigned short a, int ieee) -+{ -+ unsigned int sign = (unsigned int)(a & 0x8000) << 16; -+ int aexp = (a >> 10) & 0x1f; -+ unsigned int mantissa = a & 0x3ff; -+ -+ if (aexp == 0x1f && ieee) -+ return sign | 0x7f800000 | (mantissa << 13); -+ -+ if (aexp == 0) -+ { -+ int shift; -+ -+ if (mantissa == 0) -+ return sign; -+ -+ shift = __builtin_clz(mantissa) - 21; -+ mantissa <<= shift; -+ aexp = -shift; -+ } -+ -+ return sign | (((aexp + 0x70) << 23) + (mantissa << 13)); -+} -+ -+unsigned short -+__gnu_f2h_ieee(unsigned int a) -+{ -+ return __gnu_f2h_internal(a, 1); -+} -+ -+unsigned int -+__gnu_h2f_ieee(unsigned short a) -+{ -+ return __gnu_h2f_internal(a, 1); -+} -+ -+unsigned short -+__gnu_f2h_alternative(unsigned int x) -+{ -+ return __gnu_f2h_internal(x, 0); -+} -+ -+unsigned int -+__gnu_h2f_alternative(unsigned short a) -+{ -+ return __gnu_h2f_internal(a, 0); -+} ---- a/gcc/config/arm/fpa.md -+++ b/gcc/config/arm/fpa.md -@@ -599,10 +599,10 @@ - { - default: - case 0: return \"mvf%?e\\t%0, %1\"; -- case 1: if (arm_fpu_arch == FPUTYPE_FPA_EMU2) -+ case 1: if (TARGET_FPA_EMU2) - return \"ldf%?e\\t%0, %1\"; - return \"lfm%?\\t%0, 1, %1\"; -- case 2: if (arm_fpu_arch == FPUTYPE_FPA_EMU2) -+ case 2: if (TARGET_FPA_EMU2) - return \"stf%?e\\t%1, %0\"; - return \"sfm%?\\t%1, 1, %0\"; - } ---- /dev/null -+++ b/gcc/config/arm/hwdiv.md -@@ -0,0 +1,41 @@ -+;; ARM instruction patterns for hardware division -+;; Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. -+;; Written by CodeSourcery, LLC. -+;; -+;; This file is part of GCC. -+;; -+;; GCC is free software; you can redistribute it and/or modify it -+;; under the terms of the GNU General Public License as published by -+;; the Free Software Foundation; either version 2, or (at your option) -+;; any later version. -+;; -+;; GCC is distributed in the hope that it will be useful, but -+;; WITHOUT ANY WARRANTY; without even the implied warranty of -+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+;; General Public License for more details. -+;; -+;; You should have received a copy of the GNU General Public License -+;; along with GCC; see the file COPYING. If not, write to -+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor, -+;; Boston, MA 02110-1301, USA. -+ -+(define_insn "divsi3" -+ [(set (match_operand:SI 0 "s_register_operand" "=r") -+ (div:SI (match_operand:SI 1 "s_register_operand" "r") -+ (match_operand:SI 2 "s_register_operand" "r")))] -+ "arm_arch_hwdiv" -+ "sdiv%?\t%0, %1, %2" -+ [(set_attr "predicable" "yes") -+ (set_attr "insn" "sdiv")] -+) -+ -+(define_insn "udivsi3" -+ [(set (match_operand:SI 0 "s_register_operand" "=r") -+ (udiv:SI (match_operand:SI 1 "s_register_operand" "r") -+ (match_operand:SI 2 "s_register_operand" "r")))] -+ "arm_arch_hwdiv" -+ "udiv%?\t%0, %1, %2" -+ [(set_attr "predicable" "yes") -+ (set_attr "insn" "udiv")] -+) -+ ---- a/gcc/config/arm/ieee754-df.S -+++ b/gcc/config/arm/ieee754-df.S -@@ -83,7 +83,7 @@ - ARM_FUNC_START adddf3 - ARM_FUNC_ALIAS aeabi_dadd adddf3 - --1: do_push {r4, r5, lr} -+1: do_push (r4, r5, lr) - - @ Look for zeroes, equal values, INF, or NAN. - shift1 lsl, r4, xh, #1 -@@ -427,7 +427,7 @@ - do_it eq, t - moveq r1, #0 - RETc(eq) -- do_push {r4, r5, lr} -+ do_push (r4, r5, lr) - mov r4, #0x400 @ initial exponent - add r4, r4, #(52-1 - 1) - mov r5, #0 @ sign bit is 0 -@@ -447,7 +447,7 @@ - do_it eq, t - moveq r1, #0 - RETc(eq) -- do_push {r4, r5, lr} -+ do_push (r4, r5, lr) - mov r4, #0x400 @ initial exponent - add r4, r4, #(52-1 - 1) - ands r5, r0, #0x80000000 @ sign bit in r5 -@@ -481,7 +481,7 @@ - RETc(eq) @ we are done already. - - @ value was denormalized. We can normalize it now. -- do_push {r4, r5, lr} -+ do_push (r4, r5, lr) - mov r4, #0x380 @ setup corresponding exponent - and r5, xh, #0x80000000 @ move sign bit in r5 - bic xh, xh, #0x80000000 -@@ -508,9 +508,9 @@ - @ compatibility. - adr ip, LSYM(f0_ret) - @ Push pc as well so that RETLDM works correctly. -- do_push {r4, r5, ip, lr, pc} -+ do_push (r4, r5, ip, lr, pc) - #else -- do_push {r4, r5, lr} -+ do_push (r4, r5, lr) - #endif - - mov r5, #0 -@@ -534,9 +534,9 @@ - @ compatibility. - adr ip, LSYM(f0_ret) - @ Push pc as well so that RETLDM works correctly. -- do_push {r4, r5, ip, lr, pc} -+ do_push (r4, r5, ip, lr, pc) - #else -- do_push {r4, r5, lr} -+ do_push (r4, r5, lr) - #endif - - ands r5, ah, #0x80000000 @ sign bit in r5 -@@ -585,7 +585,7 @@ - @ Legacy code expects the result to be returned in f0. Copy it - @ there as well. - LSYM(f0_ret): -- do_push {r0, r1} -+ do_push (r0, r1) - ldfd f0, [sp], #8 - RETLDM - -@@ -602,7 +602,7 @@ - - ARM_FUNC_START muldf3 - ARM_FUNC_ALIAS aeabi_dmul muldf3 -- do_push {r4, r5, r6, lr} -+ do_push (r4, r5, r6, lr) - - @ Mask out exponents, trap any zero/denormal/INF/NAN. - mov ip, #0xff -@@ -910,7 +910,7 @@ - ARM_FUNC_START divdf3 - ARM_FUNC_ALIAS aeabi_ddiv divdf3 - -- do_push {r4, r5, r6, lr} -+ do_push (r4, r5, r6, lr) - - @ Mask out exponents, trap any zero/denormal/INF/NAN. - mov ip, #0xff -@@ -1117,7 +1117,7 @@ - ARM_FUNC_ALIAS eqdf2 cmpdf2 - mov ip, #1 @ how should we specify unordered here? - --1: str ip, [sp, #-4] -+1: str ip, [sp, #-4]! - - @ Trap any INF/NAN first. - mov ip, xh, lsl #1 -@@ -1129,7 +1129,8 @@ - - @ Test for equality. - @ Note that 0.0 is equal to -0.0. --2: orrs ip, xl, xh, lsl #1 @ if x == 0.0 or -0.0 -+2: add sp, sp, #4 -+ orrs ip, xl, xh, lsl #1 @ if x == 0.0 or -0.0 - do_it eq, e - COND(orr,s,eq) ip, yl, yh, lsl #1 @ and y == 0.0 or -0.0 - teqne xh, yh @ or xh == yh -@@ -1168,7 +1169,7 @@ - bne 2b - orrs ip, yl, yh, lsl #12 - beq 2b @ y is not NAN --5: ldr r0, [sp, #-4] @ unordered return code -+5: ldr r0, [sp], #4 @ unordered return code - RET - - FUNC_END gedf2 -@@ -1194,7 +1195,7 @@ - - @ The status-returning routines are required to preserve all - @ registers except ip, lr, and cpsr. --6: do_push {r0, lr} -+6: do_push (r0, lr) - ARM_CALL cmpdf2 - @ Set the Z flag correctly, and the C flag unconditionally. - cmp r0, #0 ---- a/gcc/config/arm/ieee754-sf.S -+++ b/gcc/config/arm/ieee754-sf.S -@@ -481,7 +481,7 @@ - and r3, ip, #0x80000000 - - @ Well, no way to make it shorter without the umull instruction. -- do_push {r3, r4, r5} -+ do_push (r3, r4, r5) - mov r4, r0, lsr #16 - mov r5, r1, lsr #16 - bic r0, r0, r4, lsl #16 -@@ -492,7 +492,7 @@ - mla r0, r4, r1, r0 - adds r3, r3, r0, lsl #16 - adc r1, ip, r0, lsr #16 -- do_pop {r0, r4, r5} -+ do_pop (r0, r4, r5) - - #else - -@@ -822,7 +822,7 @@ - ARM_FUNC_ALIAS eqsf2 cmpsf2 - mov ip, #1 @ how should we specify unordered here? - --1: str ip, [sp, #-4] -+1: str ip, [sp, #-4]! - - @ Trap any INF/NAN first. - mov r2, r0, lsl #1 -@@ -834,7 +834,8 @@ - - @ Compare values. - @ Note that 0.0 is equal to -0.0. --2: orrs ip, r2, r3, lsr #1 @ test if both are 0, clear C flag -+2: add sp, sp, #4 -+ orrs ip, r2, r3, lsr #1 @ test if both are 0, clear C flag - do_it ne - teqne r0, r1 @ if not 0 compare sign - do_it pl -@@ -858,7 +859,7 @@ - bne 2b - movs ip, r1, lsl #9 - beq 2b @ r1 is not NAN --5: ldr r0, [sp, #-4] @ return unordered code. -+5: ldr r0, [sp], #4 @ return unordered code. - RET - - FUNC_END gesf2 -@@ -881,7 +882,7 @@ - - @ The status-returning routines are required to preserve all - @ registers except ip, lr, and cpsr. --6: do_push {r0, r1, r2, r3, lr} -+6: do_push (r0, r1, r2, r3, lr) - ARM_CALL cmpsf2 - @ Set the Z flag correctly, and the C flag unconditionally. - cmp r0, #0 ---- a/gcc/config/arm/lib1funcs.asm -+++ b/gcc/config/arm/lib1funcs.asm -@@ -27,8 +27,17 @@ - #if defined(__ELF__) && defined(__linux__) - .section .note.GNU-stack,"",%progbits - .previous --#endif -+#endif /* __ELF__ and __linux__ */ - -+#ifdef __ARM_EABI__ -+/* Some attributes that are common to all routines in this file. */ -+ /* Tag_ABI_align8_needed: This code does not require 8-byte -+ alignment from the caller. */ -+ /* .eabi_attribute 24, 0 -- default setting. */ -+ /* Tag_ABI_align8_preserved: This code preserves 8-byte -+ alignment in any callee. */ -+ .eabi_attribute 25, 1 -+#endif /* __ARM_EABI__ */ - /* ------------------------------------------------------------------------ */ - - /* We need to know what prefix to add to function names. */ -@@ -233,8 +242,8 @@ - .macro shift1 op, arg0, arg1, arg2 - \op \arg0, \arg1, \arg2 - .endm --#define do_push push --#define do_pop pop -+#define do_push(...) push {__VA_ARGS__} -+#define do_pop(...) pop {__VA_ARGS__} - #define COND(op1, op2, cond) op1 ## op2 ## cond - /* Perform an arithmetic operation with a variable shift operand. This - requires two instructions and a scratch register on Thumb-2. */ -@@ -248,24 +257,133 @@ - .macro shift1 op, arg0, arg1, arg2 - mov \arg0, \arg1, \op \arg2 - .endm --#define do_push stmfd sp!, --#define do_pop ldmfd sp!, -+#if defined(__low_irq_latency__) -+#define do_push(...) \ -+ _buildN1(do_push, _buildC1(__VA_ARGS__))( __VA_ARGS__) -+#define _buildN1(BASE, X) _buildN2(BASE, X) -+#define _buildN2(BASE, X) BASE##X -+#define _buildC1(...) _buildC2(__VA_ARGS__,9,8,7,6,5,4,3,2,1) -+#define _buildC2(a1,a2,a3,a4,a5,a6,a7,a8,a9,c,...) c -+ -+#define do_push1(r1) str r1, [sp, #-4]! -+#define do_push2(r1, r2) str r2, [sp, #-4]! ; str r1, [sp, #-4]! -+#define do_push3(r1, r2, r3) str r3, [sp, #-4]! ; str r2, [sp, #-4]!; str r1, [sp, #-4]! -+#define do_push4(r1, r2, r3, r4) \ -+ do_push3 (r2, r3, r4);\ -+ do_push1 (r1) -+#define do_push5(r1, r2, r3, r4, r5) \ -+ do_push4 (r2, r3, r4, r5);\ -+ do_push1 (r1) -+ -+#define do_pop(...) \ -+_buildN1(do_pop, _buildC1(__VA_ARGS__))( __VA_ARGS__) -+ -+#define do_pop1(r1) ldr r1, [sp], #4 -+#define do_pop2(r1, r2) ldr r1, [sp], #4 ; ldr r2, [sp], #4 -+#define do_pop3(r1, r2, r3) ldr r1, [sp], #4 ; str r2, [sp], #4; str r3, [sp], #4 -+#define do_pop4(r1, r2, r3, r4) \ -+ do_pop1 (r1);\ -+ do_pup3 (r2, r3, r4) -+#define do_pop5(r1, r2, r3, r4, r5) \ -+ do_pop1 (r1);\ -+ do_pop4 (r2, r3, r4, r5) -+#else -+#define do_push(...) stmfd sp!, { __VA_ARGS__} -+#define do_pop(...) ldmfd sp!, {__VA_ARGS__} -+#endif -+ -+ - #define COND(op1, op2, cond) op1 ## cond ## op2 - .macro shiftop name, dest, src1, src2, shiftop, shiftreg, tmp - \name \dest, \src1, \src2, \shiftop \shiftreg - .endm - #endif - --.macro ARM_LDIV0 name -+#ifdef __ARM_EABI__ -+.macro ARM_LDIV0 name signed -+ cmp r0, #0 -+ .ifc \signed, unsigned -+ movne r0, #0xffffffff -+ .else -+ movgt r0, #0x7fffffff -+ movlt r0, #0x80000000 -+ .endif -+ b SYM (__aeabi_idiv0) __PLT__ -+.endm -+#else -+.macro ARM_LDIV0 name signed - str lr, [sp, #-8]! - 98: cfi_push 98b - __\name, 0xe, -0x8, 0x8 - bl SYM (__div0) __PLT__ - mov r0, #0 @ About as wrong as it could be. - RETLDM unwind=98b - .endm -+#endif - - --.macro THUMB_LDIV0 name -+#ifdef __ARM_EABI__ -+.macro THUMB_LDIV0 name signed -+#if defined(__ARM_ARCH_6M__) -+ .ifc \signed, unsigned -+ cmp r0, #0 -+ beq 1f -+ mov r0, #0 -+ mvn r0, r0 @ 0xffffffff -+1: -+ .else -+ cmp r0, #0 -+ beq 2f -+ blt 3f -+ mov r0, #0 -+ mvn r0, r0 -+ lsr r0, r0, #1 @ 0x7fffffff -+ b 2f -+3: mov r0, #0x80 -+ lsl r0, r0, #24 @ 0x80000000 -+2: -+ .endif -+ push {r0, r1, r2} -+ ldr r0, 4f -+ adr r1, 4f -+ add r0, r1 -+ str r0, [sp, #8] -+ @ We know we are not on armv4t, so pop pc is safe. -+ pop {r0, r1, pc} -+ .align 2 -+4: -+ .word __aeabi_idiv0 - 4b -+#elif defined(__thumb2__) -+ .syntax unified -+ .ifc \signed, unsigned -+ cbz r0, 1f -+ mov r0, #0xffffffff -+1: -+ .else -+ cmp r0, #0 -+ do_it gt -+ movgt r0, #0x7fffffff -+ do_it lt -+ movlt r0, #0x80000000 -+ .endif -+ b.w SYM(__aeabi_idiv0) __PLT__ -+#else -+ .align 2 -+ bx pc -+ nop -+ .arm -+ cmp r0, #0 -+ .ifc \signed, unsigned -+ movne r0, #0xffffffff -+ .else -+ movgt r0, #0x7fffffff -+ movlt r0, #0x80000000 -+ .endif -+ b SYM(__aeabi_idiv0) __PLT__ -+ .thumb -+#endif -+.endm -+#else -+.macro THUMB_LDIV0 name signed - push { r1, lr } - 98: cfi_push 98b - __\name, 0xe, -0x4, 0x8 - bl SYM (__div0) -@@ -277,18 +395,19 @@ - pop { r1, pc } - #endif - .endm -+#endif - - .macro FUNC_END name - SIZE (__\name) - .endm - --.macro DIV_FUNC_END name -+.macro DIV_FUNC_END name signed - cfi_start __\name, LSYM(Lend_div0) - LSYM(Ldiv0): - #ifdef __thumb__ -- THUMB_LDIV0 \name -+ THUMB_LDIV0 \name \signed - #else -- ARM_LDIV0 \name -+ ARM_LDIV0 \name \signed - #endif - cfi_end LSYM(Lend_div0) - FUNC_END \name -@@ -413,6 +532,12 @@ - #define yyl r2 - #endif - -+#ifdef __ARM_EABI__ -+.macro WEAK name -+ .weak SYM (__\name) -+.endm -+#endif -+ - #ifdef __thumb__ - /* Register aliases. */ - -@@ -437,6 +562,43 @@ - - #if __ARM_ARCH__ >= 5 && ! defined (__OPTIMIZE_SIZE__) - -+#if defined (__thumb2__) -+ clz \curbit, \dividend -+ clz \result, \divisor -+ sub \curbit, \result, \curbit -+ rsb \curbit, \curbit, #31 -+ adr \result, 1f -+ add \curbit, \result, \curbit, lsl #4 -+ mov \result, #0 -+ mov pc, \curbit -+.p2align 3 -+1: -+ .set shift, 32 -+ .rept 32 -+ .set shift, shift - 1 -+ cmp.w \dividend, \divisor, lsl #shift -+ nop.n -+ adc.w \result, \result, \result -+ it cs -+ subcs.w \dividend, \dividend, \divisor, lsl #shift -+ .endr -+#elif defined(__ARM_TUNE_MARVELL_F__) -+ clz \curbit, \dividend -+ clz \result, \divisor -+ sub \curbit, \result, \curbit -+ mov \divisor, \divisor, lsl \curbit -+ rsb \curbit, \curbit, #31 -+ mov \curbit, \curbit, lsl #2 -+ mov \result, #0 -+ add pc, pc, \curbit, lsl #2 -+ nop -+ .rept 32 -+ cmp \dividend, \divisor -+ subcs \dividend, \dividend, \divisor -+ mov \divisor, \divisor, lsr #1 -+ adc \result, \result, \result -+ .endr -+#else /* ! defined(__ARM_TUNE_MARVELL_F__) */ - clz \curbit, \dividend - clz \result, \divisor - sub \curbit, \result, \curbit -@@ -452,6 +614,7 @@ - adc \result, \result, \result - subcs \dividend, \dividend, \divisor, lsl #shift - .endr -+#endif /* defined(__ARM_TUNE_MARVELL_F__) */ - - #else /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */ - #if __ARM_ARCH__ >= 5 -@@ -499,18 +662,23 @@ - - @ Division loop - 1: cmp \dividend, \divisor -+ do_it hs, t - subhs \dividend, \dividend, \divisor - orrhs \result, \result, \curbit - cmp \dividend, \divisor, lsr #1 -+ do_it hs, t - subhs \dividend, \dividend, \divisor, lsr #1 - orrhs \result, \result, \curbit, lsr #1 - cmp \dividend, \divisor, lsr #2 -+ do_it hs, t - subhs \dividend, \dividend, \divisor, lsr #2 - orrhs \result, \result, \curbit, lsr #2 - cmp \dividend, \divisor, lsr #3 -+ do_it hs, t - subhs \dividend, \dividend, \divisor, lsr #3 - orrhs \result, \result, \curbit, lsr #3 - cmp \dividend, #0 @ Early termination? -+ do_it ne, t - movnes \curbit, \curbit, lsr #4 @ No, any more bits to do? - movne \divisor, \divisor, lsr #4 - bne 1b -@@ -799,13 +967,14 @@ - /* ------------------------------------------------------------------------ */ - #ifdef L_udivsi3 - -+#if defined(__ARM_ARCH_6M__) -+ - FUNC_START udivsi3 - FUNC_ALIAS aeabi_uidiv udivsi3 - --#ifdef __thumb__ -- - cmp divisor, #0 - beq LSYM(Ldiv0) -+LSYM(udivsi3_nodiv0): - mov curbit, #1 - mov result, #0 - -@@ -819,9 +988,16 @@ - pop { work } - RET - --#else /* ARM version. */ -+#else /* ARM/Thumb-2 version. */ -+ -+ ARM_FUNC_START udivsi3 -+ ARM_FUNC_ALIAS aeabi_uidiv udivsi3 - -+ /* Note: if called via udivsi3_nodiv0, this will unnecessarily check -+ for division-by-zero a second time. */ -+LSYM(udivsi3_nodiv0): - subs r2, r1, #1 -+ do_it eq - RETc(eq) - bcc LSYM(Ldiv0) - cmp r0, r1 -@@ -834,7 +1010,8 @@ - mov r0, r2 - RET - --11: moveq r0, #1 -+11: do_it eq, e -+ moveq r0, #1 - movne r0, #0 - RET - -@@ -845,19 +1022,24 @@ - - #endif /* ARM version */ - -- DIV_FUNC_END udivsi3 -+ DIV_FUNC_END udivsi3 unsigned - -+#if defined(__ARM_ARCH_6M__) - FUNC_START aeabi_uidivmod --#ifdef __thumb__ -+ cmp r1, #0 -+ beq LSYM(Ldiv0) - push {r0, r1, lr} -- bl SYM(__udivsi3) -+ bl LSYM(udivsi3_nodiv0) - POP {r1, r2, r3} - mul r2, r0 - sub r1, r1, r2 - bx r3 - #else -+ARM_FUNC_START aeabi_uidivmod -+ cmp r1, #0 -+ beq LSYM(Ldiv0) - stmfd sp!, { r0, r1, lr } -- bl SYM(__udivsi3) -+ bl LSYM(udivsi3_nodiv0) - ldmfd sp!, { r1, r2, lr } - mul r3, r2, r0 - sub r1, r1, r3 -@@ -904,19 +1086,20 @@ - - #endif /* ARM version. */ - -- DIV_FUNC_END umodsi3 -+ DIV_FUNC_END umodsi3 unsigned - - #endif /* L_umodsi3 */ - /* ------------------------------------------------------------------------ */ - #ifdef L_divsi3 - -+#if defined(__ARM_ARCH_6M__) -+ - FUNC_START divsi3 - FUNC_ALIAS aeabi_idiv divsi3 - --#ifdef __thumb__ - cmp divisor, #0 - beq LSYM(Ldiv0) -- -+LSYM(divsi3_nodiv0): - push { work } - mov work, dividend - eor work, divisor @ Save the sign of the result. -@@ -945,15 +1128,21 @@ - pop { work } - RET - --#else /* ARM version. */ -+#else /* ARM/Thumb-2 version. */ - -+ ARM_FUNC_START divsi3 -+ ARM_FUNC_ALIAS aeabi_idiv divsi3 -+ - cmp r1, #0 -- eor ip, r0, r1 @ save the sign of the result. - beq LSYM(Ldiv0) -+LSYM(divsi3_nodiv0): -+ eor ip, r0, r1 @ save the sign of the result. -+ do_it mi - rsbmi r1, r1, #0 @ loops below use unsigned. - subs r2, r1, #1 @ division by 1 or -1 ? - beq 10f - movs r3, r0 -+ do_it mi - rsbmi r3, r0, #0 @ positive dividend value - cmp r3, r1 - bls 11f -@@ -963,14 +1152,18 @@ - ARM_DIV_BODY r3, r1, r0, r2 - - cmp ip, #0 -+ do_it mi - rsbmi r0, r0, #0 - RET - - 10: teq ip, r0 @ same sign ? -+ do_it mi - rsbmi r0, r0, #0 - RET - --11: movlo r0, #0 -+11: do_it lo -+ movlo r0, #0 -+ do_it eq,t - moveq r0, ip, asr #31 - orreq r0, r0, #1 - RET -@@ -979,24 +1172,30 @@ - - cmp ip, #0 - mov r0, r3, lsr r2 -+ do_it mi - rsbmi r0, r0, #0 - RET - - #endif /* ARM version */ - -- DIV_FUNC_END divsi3 -+ DIV_FUNC_END divsi3 signed - -+#if defined(__ARM_ARCH_6M__) - FUNC_START aeabi_idivmod --#ifdef __thumb__ -+ cmp r1, #0 -+ beq LSYM(Ldiv0) - push {r0, r1, lr} -- bl SYM(__divsi3) -+ bl LSYM(divsi3_nodiv0) - POP {r1, r2, r3} - mul r2, r0 - sub r1, r1, r2 - bx r3 - #else -+ARM_FUNC_START aeabi_idivmod -+ cmp r1, #0 -+ beq LSYM(Ldiv0) - stmfd sp!, { r0, r1, lr } -- bl SYM(__divsi3) -+ bl LSYM(divsi3_nodiv0) - ldmfd sp!, { r1, r2, lr } - mul r3, r2, r0 - sub r1, r1, r3 -@@ -1062,21 +1261,25 @@ - - #endif /* ARM version */ - -- DIV_FUNC_END modsi3 -+ DIV_FUNC_END modsi3 signed - - #endif /* L_modsi3 */ - /* ------------------------------------------------------------------------ */ - #ifdef L_dvmd_tls - -- FUNC_START div0 -- FUNC_ALIAS aeabi_idiv0 div0 -- FUNC_ALIAS aeabi_ldiv0 div0 -- -+#ifdef __ARM_EABI__ -+ WEAK aeabi_idiv0 -+ WEAK aeabi_ldiv0 -+ FUNC_START aeabi_idiv0 -+ FUNC_START aeabi_ldiv0 - RET -- - FUNC_END aeabi_ldiv0 - FUNC_END aeabi_idiv0 -+#else -+ FUNC_START div0 -+ RET - FUNC_END div0 -+#endif - - #endif /* L_divmodsi_tools */ - /* ------------------------------------------------------------------------ */ -@@ -1086,16 +1289,49 @@ - /* Constant taken from <asm/signal.h>. */ - #define SIGFPE 8 - -+#ifdef __ARM_EABI__ -+ WEAK aeabi_idiv0 -+ WEAK aeabi_ldiv0 -+ ARM_FUNC_START aeabi_idiv0 -+ ARM_FUNC_START aeabi_ldiv0 -+#else - ARM_FUNC_START div0 -+#endif - -- do_push {r1, lr} -+ do_push (r1, lr) - mov r0, #SIGFPE - bl SYM(raise) __PLT__ - RETLDM r1 - -+#ifdef __ARM_EABI__ -+ FUNC_END aeabi_ldiv0 -+ FUNC_END aeabi_idiv0 -+#else - FUNC_END div0 -+#endif - - #endif /* L_dvmd_lnx */ -+#ifdef L_clear_cache -+#if defined __ARM_EABI__ && defined __linux__ -+@ EABI GNU/Linux call to cacheflush syscall. -+ ARM_FUNC_START clear_cache -+ do_push (r7) -+#if __ARM_ARCH__ >= 7 || defined(__ARM_ARCH_6T2__) -+ movw r7, #2 -+ movt r7, #0xf -+#else -+ mov r7, #0xf0000 -+ add r7, r7, #2 -+#endif -+ mov r2, #0 -+ swi 0 -+ do_pop (r7) -+ RET -+ FUNC_END clear_cache -+#else -+#error "This is only for ARM EABI GNU/Linux" -+#endif -+#endif /* L_clear_cache */ - /* ------------------------------------------------------------------------ */ - /* Dword shift operations. */ - /* All the following Dword shift variants rely on the fact that -@@ -1292,7 +1528,7 @@ - push {r4, lr} - # else - ARM_FUNC_START clzdi2 -- do_push {r4, lr} -+ do_push (r4, lr) - # endif - cmp xxh, #0 - bne 1f ---- a/gcc/config/arm/linux-eabi.h -+++ b/gcc/config/arm/linux-eabi.h -@@ -66,22 +66,14 @@ - /* At this point, bpabi.h will have clobbered LINK_SPEC. We want to - use the GNU/Linux version, not the generic BPABI version. */ - #undef LINK_SPEC --#define LINK_SPEC LINUX_TARGET_LINK_SPEC -+#define LINK_SPEC LINUX_TARGET_LINK_SPEC BE8_LINK_SPEC - - /* Use the default LIBGCC_SPEC, not the version in linux-elf.h, as we - do not use -lfloat. */ - #undef LIBGCC_SPEC - --/* Clear the instruction cache from `beg' to `end'. This makes an -- inline system call to SYS_cacheflush. */ -+/* Clear the instruction cache from `beg' to `end'. This is -+ implemented in lib1funcs.asm, so ensure an error if this definition -+ is used. */ - #undef CLEAR_INSN_CACHE --#define CLEAR_INSN_CACHE(BEG, END) \ --{ \ -- register unsigned long _beg __asm ("a1") = (unsigned long) (BEG); \ -- register unsigned long _end __asm ("a2") = (unsigned long) (END); \ -- register unsigned long _flg __asm ("a3") = 0; \ -- register unsigned long _scno __asm ("r7") = 0xf0002; \ -- __asm __volatile ("swi 0 @ sys_cacheflush" \ -- : "=r" (_beg) \ -- : "0" (_beg), "r" (_end), "r" (_flg), "r" (_scno)); \ --} -+#define CLEAR_INSN_CACHE(BEG, END) not used ---- a/gcc/config/arm/linux-elf.h -+++ b/gcc/config/arm/linux-elf.h -@@ -98,7 +98,7 @@ - - /* NWFPE always understands FPA instructions. */ - #undef FPUTYPE_DEFAULT --#define FPUTYPE_DEFAULT FPUTYPE_FPA_EMU3 -+#define FPUTYPE_DEFAULT "fpe3" - - /* Call the function profiler with a given profile label. */ - #undef ARM_FUNCTION_PROFILER ---- /dev/null -+++ b/gcc/config/arm/marvell-f.md -@@ -0,0 +1,365 @@ -+;; Marvell 2850 pipeline description -+;; Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. -+;; Written by Marvell and CodeSourcery, Inc. -+ -+;; This file is part of GCC. -+ -+;; GCC is free software; you can redistribute it and/or modify it -+;; under the terms of the GNU General Public License as published -+;; by the Free Software Foundation; either version 2, or (at your -+;; option) any later version. -+ -+;; GCC is distributed in the hope that it will be useful, but WITHOUT -+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+;; License for more details. -+ -+;; You should have received a copy of the GNU General Public License -+;; along with GCC; see the file COPYING. If not, write to -+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor, -+;; Boston, MA 02110-1301, USA. -+ -+;; This automaton provides a pipeline description for the Marvell -+;; 2850 core. -+;; -+;; The model given here assumes that the condition for all conditional -+;; instructions is "true", i.e., that all of the instructions are -+;; actually executed. -+ -+(define_automaton "marvell_f") -+ -+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -+;; Pipelines -+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -+ -+;; This is a dual-issue processor with three pipelines: -+;; -+;; 1. Arithmetic and load/store pipeline A1. -+;; Issue | E1 | E2 | OF | WR | WB for load-store instructions -+;; Issue | E1 | E2 | WB for arithmetic instructions -+;; -+;; 2. Arithmetic pipeline A2. -+;; Issue | E1 | E2 | WB -+;; -+;; 3. Multiply and multiply-accumulate pipeline. -+;; Issue | MAC1 | MAC2 | MAC3 | WB -+;; -+;; There are various bypasses modelled to a greater or lesser extent. -+;; -+;; Latencies in this file correspond to the number of cycles after -+;; the issue stage that it takes for the result of the instruction to -+;; be computed, or for its side-effects to occur. -+ -+(define_cpu_unit "a1_e1,a1_e2,a1_of,a1_wr,a1_wb" "marvell_f") ; ALU 1 -+(define_cpu_unit "a2_e1,a2_e2,a2_wb" "marvell_f") ; ALU 2 -+(define_cpu_unit "m_1,m_2,m_3,m_wb" "marvell_f") ; MAC -+ -+;; We define an SRAM cpu unit to enable us to describe conflicts -+;; between loads at the E2 stage and stores at the WR stage. -+ -+(define_cpu_unit "sram" "marvell_f") -+ -+;; Handling of dual-issue constraints. -+;; -+;; Certain pairs of instructions can be issued in parallel, and certain -+;; pairs cannot. We divide a subset of the instructions into groups as -+;; follows. -+;; -+;; - data processing 1 (mov, mvn); -+;; - data processing 2 (adc, add, and, bic, cmn, cmp, eor, orr, rsb, -+;; rsc, sbc, sub, teq, tst); -+;; - load single (ldr, ldrb, ldrbt, ldrt, ldrh, ldrsb, ldrsh); -+;; - store single (str, strb, strbt, strt, strh); -+;; - swap (swp, swpb); -+;; - pld; -+;; - count leading zeros and DSP add/sub (clz, qadd, qdadd, qsub, qdsub); -+;; - multiply 2 (mul, muls, smull, umull, smulxy, smulls, umulls); -+;; - multiply 3 (mla, mlas, smlal, umlal, smlaxy, smlalxy, smlawx, -+;; smlawy, smlals, umlals); -+;; - branches (b, bl, blx, bx). -+;; -+;; Ignoring conditional execution, it is a good approximation to the core -+;; to model that two instructions may only be issued in parallel if the -+;; following conditions are met. -+;; I. The instructions both fall into one of the above groups and their -+;; corresponding groups have a entry in the matrix below that is not X. -+;; II. The second instruction does not read any register updated by the -+;; first instruction (already enforced by the GCC scheduler). -+;; III. The second instruction does not need the carry flag updated by the -+;; first instruction. Currently we do not model this. -+;; -+;; First Second instruction group -+;; insn -+;; DP1 DP2 L S SWP PLD CLZ M2 M3 B -+;; -+;; DP1 ok ok ok ok ok ok ok ok ok ok -+;; DP2(1) ok ok ok ok ok ok ok ok ok ok -+;; DP2(2) ok (2) ok (4) ok ok ok ok X ok -+;; L } -+;; SWP } ok ok X X X X ok ok ok ok -+;; PLD } -+;; S(3) ok ok X X X X ok ok ok ok -+;; S(4) ok (2) X X X X ok ok X ok -+;; CLZ ok ok ok ok ok ok ok ok ok ok -+;; M2 ok ok ok ok ok ok ok X X ok -+;; M3 ok (2) ok (4) ok ok ok X X ok -+;; B ok ok ok ok ok ok ok ok ok ok -+;; -+;; (1) without register shift -+;; (2) with register shift -+;; (3) with immediate offset -+;; (4) with register offset -+;; -+;; We define a fake cpu unit "reg_shift_lock" to enforce constraints -+;; between instructions in groups DP2(2) and M3. All other -+;; constraints are enforced automatically by virtue of the limited -+;; number of pipelines available for the various operations, with -+;; the exception of constraints involving S(4) that we do not model. -+ -+(define_cpu_unit "reg_shift_lock" "marvell_f") -+ -+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -+;; ALU instructions -+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -+ -+;; 1. Certain logic operations can be retired after the E1 stage if -+;; the pipeline is not already retiring another instruction. In this -+;; model we assume this behaviour always holds for mov, mvn, and, orr, eor -+;; instructions. If a register shift is involved and the instruction is -+;; not mov or mvn, then a dual-issue constraint must be enforced. -+ -+;; The first two cases are separate so they can be identified for -+;; bypasses below. -+ -+(define_insn_reservation "marvell_f_alu_early_retire" 1 -+ (and (eq_attr "tune" "marvell_f") -+ (and (eq_attr "type" "alu") -+ (eq_attr "insn" "mov,mvn,and,orr,eor"))) -+ "(a1_e1,a1_wb)|(a2_e1,a2_wb)") -+ -+(define_insn_reservation "marvell_f_alu_early_retire_shift" 1 -+ (and (eq_attr "tune" "marvell_f") -+ (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "insn" "mov,mvn,and,orr,eor"))) -+ "(a1_e1,a1_wb)|(a2_e1,a2_wb)") -+ -+(define_insn_reservation "marvell_f_alu_early_retire_reg_shift1" 1 -+ (and (eq_attr "tune" "marvell_f") -+ (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "insn" "mov,mvn"))) -+ "(a1_e1,a1_wb)|(a2_e1,a2_wb)") -+ -+(define_insn_reservation "marvell_f_alu_early_retire_reg_shift2" 1 -+ (and (eq_attr "tune" "marvell_f") -+ (and (eq_attr "type" "alu_shift_reg") -+ (eq_attr "insn" "and,orr,eor"))) -+ "(reg_shift_lock+a1_e1,a1_wb)|(reg_shift_lock+a2_e1,a2_wb)") -+ -+;; 2. ALU operations with no shifted operand. These bypass the E1 stage if -+;; the E2 stage of the corresponding pipeline is clear; here, we always -+;; model this scenario [*]. We give the operation a latency of 1 yet reserve -+;; both E1 and E2 for it (thus preventing the GCC scheduler, in the case -+;; where both E1 and E2 of one pipeline are clear, from issuing one -+;; instruction to each). -+;; -+;; [*] The non-bypass case is a latency of two, reserving E1 on the first -+;; cycle and E2 on the next. Due to the way the scheduler works we -+;; have to choose between taking this as the default and taking the -+;; above case (with latency one) as the default; we choose the latter. -+ -+(define_insn_reservation "marvell_f_alu_op_bypass_e1" 1 -+ (and (eq_attr "tune" "marvell_f") -+ (and (eq_attr "type" "alu") -+ (not (eq_attr "insn" "mov,mvn,and,orr,eor")))) -+ "(a1_e1+a1_e2,a1_wb)|(a2_e1+a2_e2,a2_wb)") -+ -+;; 3. ALU operations with a shift-by-constant operand. -+ -+(define_insn_reservation "marvell_f_alu_shift_op" 2 -+ (and (eq_attr "tune" "marvell_f") -+ (and (eq_attr "type" "alu_shift") -+ (not (eq_attr "insn" "mov,mvn,and,orr,eor")))) -+ "(a1_e1,a1_e2,a1_wb)|(a2_e1,a2_e2,a2_wb)") -+ -+;; 4. ALU operations with a shift-by-register operand. Since the -+;; instruction is never mov or mvn, a dual-issue constraint must -+;; be enforced. -+ -+(define_insn_reservation "marvell_f_alu_shift_reg_op" 2 -+ (and (eq_attr "tune" "marvell_f") -+ (and (eq_attr "type" "alu_shift_reg") -+ (not (eq_attr "insn" "mov,mvn,and,orr,eor")))) -+ "(reg_shift_lock+a1_e1,a1_e2,a1_wb)|(reg_shift_lock+a2_e1,a2_e2,a2_wb)") -+ -+;; Given an ALU operation with shift (I1) followed by another ALU -+;; operation (I2), with I2 depending on the destination register Rd of I1 -+;; and with I2 not using that value as the amount or the starting value for -+;; a shift, then I1 and I2 may be issued to the same pipeline on -+;; consecutive cycles. In terms of this model that corresponds to I1 -+;; having a latency of one cycle. There are three cases for various -+;; I1 and I2 as follows. -+ -+;; (a) I1 has a constant or register shift and I2 doesn't have a shift at all. -+(define_bypass 1 "marvell_f_alu_shift_op,\ -+ marvell_f_alu_shift_reg_op" -+ "marvell_f_alu_op_bypass_e1,marvell_f_alu_early_retire") -+ -+;; (b) I1 has a constant or register shift and I2 has a constant shift. -+;; Rd must not provide the starting value for the shift. -+(define_bypass 1 "marvell_f_alu_shift_op,\ -+ marvell_f_alu_shift_reg_op" -+ "marvell_f_alu_shift_op,marvell_f_alu_early_retire_shift" -+ "arm_no_early_alu_shift_value_dep") -+ -+;; (c) I1 has a constant or register shift and I2 has a register shift. -+;; Rd must not provide the amount by which to shift. -+(define_bypass 1 "marvell_f_alu_shift_op,\ -+ marvell_f_alu_shift_reg_op" -+ "marvell_f_alu_shift_reg_op,\ -+ marvell_f_alu_early_retire_reg_shift1,\ -+ marvell_f_alu_early_retire_reg_shift2" -+ "arm_no_early_alu_shift_dep") -+ -+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -+;; Multiplication instructions -+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -+ -+;; Multiplication instructions in group "Multiply 2". -+ -+(define_insn_reservation "marvell_f_multiply_2" 3 -+ (and (eq_attr "tune" "marvell_f") -+ (eq_attr "insn" "mul,muls,smull,umull,smulxy,smulls,umulls")) -+ "m_1,m_2,m_3,m_wb") -+ -+;; Multiplication instructions in group "Multiply 3". There is a -+;; dual-issue constraint with non-multiplication ALU instructions -+;; to be respected here. -+ -+(define_insn_reservation "marvell_f_multiply_3" 3 -+ (and (eq_attr "tune" "marvell_f") -+ (eq_attr "insn" "mla,mlas,smlal,umlal,smlaxy,smlalxy,smlawx,\ -+ smlawy,smlals,umlals")) -+ "reg_shift_lock+m_1,m_2,m_3,m_wb") -+ -+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -+;; Branch instructions -+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -+ -+;; Conditional backward b instructions can have a zero-cycle penalty, and -+;; other conditional b and bl instructions have a one-cycle penalty if -+;; predicted correctly. Currently we model the zero-cycle case for all -+;; branches. -+ -+(define_insn_reservation "marvell_f_branches" 0 -+ (and (eq_attr "tune" "marvell_f") -+ (eq_attr "type" "branch")) -+ "nothing") -+ -+;; Call latencies are not predictable; a semi-arbitrary very large -+;; number is used as "positive infinity" for such latencies. -+ -+(define_insn_reservation "marvell_f_call" 32 -+ (and (eq_attr "tune" "marvell_f") -+ (eq_attr "type" "call")) -+ "nothing") -+ -+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -+;; Load/store instructions -+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -+ -+;; The models for load/store instructions do not accurately describe -+;; the difference between operations with a base register writeback. -+;; These models assume that all memory references hit in dcache. -+ -+;; 1. Load/store for single registers. -+ -+;; The worst case for a load is when the load result is needed in E1 -+;; (for example for a register shift), giving a latency of four. Loads -+;; skip E1 and access memory at the E2 stage. -+ -+(define_insn_reservation "marvell_f_load1" 4 -+ (and (eq_attr "tune" "marvell_f") -+ (eq_attr "type" "load1,load_byte")) -+ "a1_e2+sram,a1_of,a1_wr,a1_wb") -+ -+;; The result for a load may be bypassed (to be available at the same -+;; time as the load arrives in the WR stage, so effectively at the OF -+;; stage) to the Rn operand at E2 with a latency of two. The result may -+;; be bypassed to a non-Rn operand at E2 with a latency of three. For -+;; instructions without shifts, detection of an Rn bypass situation is -+;; difficult (because some of the instruction patterns switch their -+;; operands), and so we do not model that here. For instructions with -+;; shifts, the operand used at E2 will always be Rn, and so we can -+;; model the latency-two bypass for these. -+ -+(define_bypass 2 "marvell_f_load1" -+ "marvell_f_alu_shift_op" -+ "arm_no_early_alu_shift_value_dep") -+ -+(define_bypass 2 "marvell_f_load1" -+ "marvell_f_alu_shift_reg_op" -+ "arm_no_early_alu_shift_dep") -+ -+;; Stores write at the WR stage and loads read at the E2 stage, giving -+;; a store latency of three. -+ -+(define_insn_reservation "marvell_f_store1" 3 -+ (and (eq_attr "tune" "marvell_f") -+ (eq_attr "type" "store1")) -+ "a1_e2,a1_of,a1_wr+sram,a1_wb") -+ -+;; 2. Load/store for two consecutive registers. These may be dealt -+;; with in the same number of cycles as single loads and stores. -+ -+(define_insn_reservation "marvell_f_load2" 4 -+ (and (eq_attr "tune" "marvell_f") -+ (eq_attr "type" "load2")) -+ "a1_e2+sram,a1_of,a1_wr,a1_wb") -+ -+(define_insn_reservation "marvell_f_store2" 3 -+ (and (eq_attr "tune" "marvell_f") -+ (eq_attr "type" "store2")) -+ "a1_e2,a1_of,a1_wr+sram,a1_wb") -+ -+;; The first word of a doubleword load is eligible for the latency-two -+;; bypass described above for single loads, but this is not modelled here. -+;; We do however assume that either word may also be bypassed with -+;; latency three for ALU operations with shifts (where the shift value and -+;; amount do not depend on the loaded value) and latency four for ALU -+;; operations without shifts. The latency four case is of course the default. -+ -+(define_bypass 3 "marvell_f_load2" -+ "marvell_f_alu_shift_op" -+ "arm_no_early_alu_shift_value_dep") -+ -+(define_bypass 3 "marvell_f_load2" -+ "marvell_f_alu_shift_reg_op" -+ "arm_no_early_alu_shift_dep") -+ -+;; 3. Load/store for more than two registers. -+ -+;; These instructions stall for an extra cycle in the decode stage; -+;; individual load/store instructions for each register are then issued. -+;; The load/store multiple instruction itself is removed from the decode -+;; stage at the same time as the final load/store instruction is issued. -+;; To complicate matters, pairs of loads/stores referencing two -+;; consecutive registers will be issued together as doubleword operations. -+;; We model a 3-word load as an LDR plus an LDRD, and a 4-word load -+;; as two LDRDs; thus, these are allocated the same latencies (the -+;; latency for two consecutive loads plus one for the setup stall). -+;; The extra stall is modelled by reserving E1. -+ -+(define_insn_reservation "marvell_f_load3_4" 6 -+ (and (eq_attr "tune" "marvell_f") -+ (eq_attr "type" "load3,load4")) -+ "a1_e1,a1_e1+a1_e2+sram,a1_e2+sram+a1_of,a1_of+a1_wr,a1_wr+a1_wb,a1_wb") -+ -+;; Bypasses are possible for ldm as for single loads, but we do not -+;; model them here since the order of the constituent loads is -+;; difficult to predict. -+ -+(define_insn_reservation "marvell_f_store3_4" 5 -+ (and (eq_attr "tune" "marvell_f") -+ (eq_attr "type" "store3,store4")) -+ "a1_e1,a1_e1+a1_e2,a1_e2+a1_of,a1_of+a1_wr+sram,a1_wr+sram+a1_wb,a1_wb") -+ ---- /dev/null -+++ b/gcc/config/arm/marvell-f-vfp.md -@@ -0,0 +1,153 @@ -+;; Marvell 2850 VFP pipeline description -+;; Copyright (C) 2007 Free Software Foundation, Inc. -+;; Written by CodeSourcery, Inc. -+ -+;; This file is part of GCC. -+ -+;; GCC is distributed in the hope that it will be useful, but WITHOUT -+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+;; License for more details. -+ -+;; You should have received a copy of the GNU General Public License -+;; along with GCC; see the file COPYING. If not, write to -+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor, -+;; Boston, MA 02110-1301, USA. -+ -+;; This automaton provides a pipeline description for the Marvell -+;; 2850 core. -+;; -+;; The model given here assumes that the condition for all conditional -+;; instructions is "true", i.e., that all of the instructions are -+;; actually executed. -+ -+(define_automaton "marvell_f_vfp") -+ -+;; This is a single-issue VFPv2 implementation with the following execution -+;; units: -+;; -+;; 1. Addition/subtraction unit; takes three cycles, pipelined. -+;; 2. Multiplication unit; takes four cycles, pipelined. -+;; 3. Add buffer, used for multiply-accumulate (see below). -+;; 4. Divide/square root unit, not pipelined. -+;; For single-precision: takes sixteen cycles, can accept another insn -+;; after fifteen cycles. -+;; For double-precision: takes thirty-one cycles, can accept another insn -+;; after thirty cycles. -+;; 5. Single-cycle unit, pipelined. -+;; This does absolute value/copy/negate/compare in one cycle and -+;; conversion in two cycles. -+;; -+;; When all three operands of a multiply-accumulate instruction are ready, -+;; one is issued to the add buffer (which can hold six operands in a FIFO) -+;; and the two to be multiplied are issued to the multiply unit. After -+;; four cycles in the multiply unit, one cycle is taken to issue the -+;; operand from the add buffer plus the multiplication result to the -+;; addition/subtraction unit. That issue takes priority over any add/sub -+;; instruction waiting at the normal issue stage, but may be performed in -+;; parallel with the issue of a non-add/sub instruction. The total time -+;; for a multiply-accumulate instruction to pass through the execution -+;; units is hence eight cycles. -+;; -+;; We do not need to explicitly model the add buffer because it can -+;; always issue the instruction at the head of its FIFO (due to the above -+;; priority rule) and there are more spaces in the add buffer (six) than -+;; there are stages (four) in the multiplication unit. -+;; -+;; Two instructions may be retired at once from the head of an 8-entry -+;; reorder buffer. Data from these first two instructions only may be -+;; forwarded to the inputs of the issue unit. We assume that the -+;; pressure on the reorder buffer will be sufficiently low that every -+;; instruction entering it will be eligible for data forwarding. Since -+;; data is forwarded to the issue unit and not the execution units (so -+;; for example single-cycle instructions cannot be issued back-to-back), -+;; the latencies given below are the cycle counts above plus one. -+ -+(define_cpu_unit "mf_vfp_issue" "marvell_f_vfp") -+(define_cpu_unit "mf_vfp_add" "marvell_f_vfp") -+(define_cpu_unit "mf_vfp_mul" "marvell_f_vfp") -+(define_cpu_unit "mf_vfp_div" "marvell_f_vfp") -+(define_cpu_unit "mf_vfp_single_cycle" "marvell_f_vfp") -+ -+;; An attribute to indicate whether our reservations are applicable. -+ -+(define_attr "marvell_f_vfp" "yes,no" -+ (const (if_then_else (and (eq_attr "tune" "marvell_f") -+ (eq_attr "fpu" "vfp")) -+ (const_string "yes") (const_string "no")))) -+ -+;; Reservations of functional units. The nothing*2 reservations at the -+;; start of many of the reservation strings correspond to the decode -+;; stages. We need to have these reservations so that we can correctly -+;; reserve parts of the core's A1 pipeline for loads and stores. For -+;; that case (since loads skip E1) the pipelines line up thus: -+;; A1 pipe: Issue E2 OF WR WB ... -+;; VFP pipe: Fetch Decode1 Decode2 Issue Execute1 ... -+;; For a load, we need to make a reservation of E2, and thus we must -+;; use Decode1 as the starting point for all VFP reservations here. -+;; -+;; For reservations of pipelined VFP execution units we only reserve -+;; the execution unit for the first execution cycle, omitting any trailing -+;; "nothing" reservations. -+ -+(define_insn_reservation "marvell_f_vfp_add" 4 -+ (and (eq_attr "marvell_f_vfp" "yes") -+ (eq_attr "type" "farith")) -+ "nothing*2,mf_vfp_issue,mf_vfp_add") -+ -+(define_insn_reservation "marvell_f_vfp_mul" 5 -+ (and (eq_attr "marvell_f_vfp" "yes") -+ (eq_attr "type" "fmuls,fmuld")) -+ "nothing*2,mf_vfp_issue,mf_vfp_mul") -+ -+(define_insn_reservation "marvell_f_vfp_divs" 17 -+ (and (eq_attr "marvell_f_vfp" "yes") -+ (eq_attr "type" "fdivs")) -+ "nothing*2,mf_vfp_issue,mf_vfp_div*15") -+ -+(define_insn_reservation "marvell_f_vfp_divd" 32 -+ (and (eq_attr "marvell_f_vfp" "yes") -+ (eq_attr "type" "fdivd")) -+ "nothing*2,mf_vfp_issue,mf_vfp_div*30") -+ -+;; The DFA lookahead is small enough that the "add" reservation here -+;; will always take priority over any addition/subtraction instruction -+;; issued five cycles after the multiply-accumulate instruction, as -+;; required. -+(define_insn_reservation "marvell_f_vfp_mac" 9 -+ (and (eq_attr "marvell_f_vfp" "yes") -+ (eq_attr "type" "fmacs,fmacd")) -+ "nothing*2,mf_vfp_issue,mf_vfp_mul,nothing*4,mf_vfp_add") -+ -+(define_insn_reservation "marvell_f_vfp_single" 2 -+ (and (eq_attr "marvell_f_vfp" "yes") -+ (eq_attr "type" "ffarith")) -+ "nothing*2,mf_vfp_issue,mf_vfp_single_cycle") -+ -+(define_insn_reservation "marvell_f_vfp_convert" 3 -+ (and (eq_attr "marvell_f_vfp" "yes") -+ (eq_attr "type" "f_cvt")) -+ "nothing*2,mf_vfp_issue,mf_vfp_single_cycle") -+ -+(define_insn_reservation "marvell_f_vfp_load" 2 -+ (and (eq_attr "marvell_f_vfp" "yes") -+ (eq_attr "type" "f_loads,f_loadd")) -+ "a1_e2+sram,a1_of,a1_wr+mf_vfp_issue,a1_wb+mf_vfp_single_cycle") -+ -+(define_insn_reservation "marvell_f_vfp_from_core" 2 -+ (and (eq_attr "marvell_f_vfp" "yes") -+ (eq_attr "type" "r_2_f")) -+ "a1_e2,a1_of,a1_wr+mf_vfp_issue,a1_wb+mf_vfp_single_cycle") -+ -+;; The interaction between the core and VFP pipelines during VFP -+;; store operations and core <-> VFP moves is not clear, so we guess. -+(define_insn_reservation "marvell_f_vfp_store" 3 -+ (and (eq_attr "marvell_f_vfp" "yes") -+ (eq_attr "type" "f_stores,f_stored")) -+ "a1_e2,a1_of,mf_vfp_issue,a1_wr+sram+mf_vfp_single_cycle") -+ -+(define_insn_reservation "marvell_f_vfp_to_core" 4 -+ (and (eq_attr "marvell_f_vfp" "yes") -+ (eq_attr "type" "f_2_r")) -+ "a1_e2,a1_of,a1_wr+mf_vfp_issue,a1_wb+mf_vfp_single_cycle") -+ ---- /dev/null -+++ b/gcc/config/arm/montavista-linux.h -@@ -0,0 +1,33 @@ -+/* MontaVista GNU/Linux Configuration. -+ Copyright (C) 2009 -+ Free Software Foundation, Inc. -+ -+This file is part of GCC. -+ -+GCC is free software; you can redistribute it and/or modify -+it under the terms of the GNU General Public License as published by -+the Free Software Foundation; either version 3, or (at your option) -+any later version. -+ -+GCC is distributed in the hope that it will be useful, -+but WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+GNU General Public License for more details. -+ -+You should have received a copy of the GNU General Public License -+along with GCC; see the file COPYING3. If not see -+<http://www.gnu.org/licenses/>. */ -+ -+/* Add -tarmv6 and -tthumb2 options for convenience in generating multilibs. -+*/ -+#undef CC1_SPEC -+#define CC1_SPEC " \ -+ %{tarmv6: -march=armv6 -mfloat-abi=softfp ; \ -+ tthumb2: -mthumb -march=armv7-a -mfloat-abi=softfp ; \ -+ : -march=armv5t}" -+ -+/* The various C libraries each have their own subdirectory. */ -+#undef SYSROOT_SUFFIX_SPEC -+#define SYSROOT_SUFFIX_SPEC \ -+ "%{tarmv6:/armv6 ; \ -+ tthumb2:/thumb2}" ---- a/gcc/config/arm/neon-gen.ml -+++ b/gcc/config/arm/neon-gen.ml -@@ -122,6 +122,7 @@ - | T_uint16 | T_int16 -> T_intHI - | T_uint32 | T_int32 -> T_intSI - | T_uint64 | T_int64 -> T_intDI -+ | T_float32 -> T_floatSF - | T_poly8 -> T_intQI - | T_poly16 -> T_intHI - | T_arrayof (n, elt) -> T_arrayof (n, signed_ctype elt) -@@ -320,7 +321,7 @@ - typeinfo; - Format.print_newline (); - (* Extra types not in <stdint.h>. *) -- Format.printf "typedef __builtin_neon_sf float32_t;\n"; -+ Format.printf "typedef float float32_t;\n"; - Format.printf "typedef __builtin_neon_poly8 poly8_t;\n"; - Format.printf "typedef __builtin_neon_poly16 poly16_t;\n" - ---- a/gcc/config/arm/neon.md -+++ b/gcc/config/arm/neon.md -@@ -159,7 +159,8 @@ - (UNSPEC_VUZP1 201) - (UNSPEC_VUZP2 202) - (UNSPEC_VZIP1 203) -- (UNSPEC_VZIP2 204)]) -+ (UNSPEC_VZIP2 204) -+ (UNSPEC_MISALIGNED_ACCESS 205)]) - - ;; Double-width vector modes. - (define_mode_iterator VD [V8QI V4HI V2SI V2SF]) -@@ -459,7 +460,9 @@ - "=w,Uv,w, w, ?r,?w,?r,?r, ?Us") - (match_operand:VD 1 "general_operand" - " w,w, Dn,Uvi, w, r, r, Usi,r"))] -- "TARGET_NEON" -+ "TARGET_NEON -+ && (register_operand (operands[0], <MODE>mode) -+ || register_operand (operands[1], <MODE>mode))" - { - if (which_alternative == 2) - { -@@ -481,7 +484,7 @@ - - /* FIXME: If the memory layout is changed in big-endian mode, output_move_vfp - below must be changed to output_move_neon (which will use the -- element/structure loads/stores), and the constraint changed to 'Un' instead -+ element/structure loads/stores), and the constraint changed to 'Um' instead - of 'Uv'. */ - - switch (which_alternative) -@@ -506,7 +509,9 @@ - "=w,Un,w, w, ?r,?w,?r,?r, ?Us") - (match_operand:VQXMOV 1 "general_operand" - " w,w, Dn,Uni, w, r, r, Usi, r"))] -- "TARGET_NEON" -+ "TARGET_NEON -+ && (register_operand (operands[0], <MODE>mode) -+ || register_operand (operands[1], <MODE>mode))" - { - if (which_alternative == 2) - { -@@ -549,6 +554,11 @@ - (match_operand:TI 1 "general_operand" ""))] - "TARGET_NEON" - { -+ if (can_create_pseudo_p ()) -+ { -+ if (GET_CODE (operands[0]) != REG) -+ operands[1] = force_reg (TImode, operands[1]); -+ } - }) - - (define_expand "mov<mode>" -@@ -556,12 +566,19 @@ - (match_operand:VSTRUCT 1 "general_operand" ""))] - "TARGET_NEON" - { -+ if (can_create_pseudo_p ()) -+ { -+ if (GET_CODE (operands[0]) != REG) -+ operands[1] = force_reg (<MODE>mode, operands[1]); -+ } - }) - - (define_insn "*neon_mov<mode>" - [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "=w,Ut,w") - (match_operand:VSTRUCT 1 "general_operand" " w,w, Ut"))] -- "TARGET_NEON" -+ "TARGET_NEON -+ && (register_operand (operands[0], <MODE>mode) -+ || register_operand (operands[1], <MODE>mode))" - { - switch (which_alternative) - { -@@ -658,6 +675,49 @@ - neon_disambiguate_copy (operands, dest, src, 4); - }) - -+(define_expand "movmisalign<mode>" -+ [(set (match_operand:VDQX 0 "nonimmediate_operand" "") -+ (unspec:VDQX [(match_operand:VDQX 1 "general_operand" "")] -+ UNSPEC_MISALIGNED_ACCESS))] -+ "TARGET_NEON && !BYTES_BIG_ENDIAN" -+{ -+ if (!s_register_operand (operands[0], <MODE>mode) -+ && !s_register_operand (operands[1], <MODE>mode)) -+ FAIL; -+}) -+ -+(define_insn "*movmisalign<mode>_neon_store" -+ [(set (match_operand:VDX 0 "memory_operand" "=Um") -+ (unspec:VDX [(match_operand:VDX 1 "s_register_operand" " w")] -+ UNSPEC_MISALIGNED_ACCESS))] -+ "TARGET_NEON && !BYTES_BIG_ENDIAN" -+ "vst1.<V_sz_elem>\t{%P1}, %A0" -+ [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")]) -+ -+(define_insn "*movmisalign<mode>_neon_load" -+ [(set (match_operand:VDX 0 "s_register_operand" "=w") -+ (unspec:VDX [(match_operand:VDX 1 "memory_operand" " Um")] -+ UNSPEC_MISALIGNED_ACCESS))] -+ "TARGET_NEON && !BYTES_BIG_ENDIAN" -+ "vld1.<V_sz_elem>\t{%P0}, %A1" -+ [(set_attr "neon_type" "neon_vld1_1_2_regs")]) -+ -+(define_insn "*movmisalign<mode>_neon_store" -+ [(set (match_operand:VQX 0 "memory_operand" "=Um") -+ (unspec:VQX [(match_operand:VQX 1 "s_register_operand" " w")] -+ UNSPEC_MISALIGNED_ACCESS))] -+ "TARGET_NEON && !BYTES_BIG_ENDIAN" -+ "vst1.<V_sz_elem>\t{%q1}, %A0" -+ [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")]) -+ -+(define_insn "*movmisalign<mode>_neon_load" -+ [(set (match_operand:VQX 0 "s_register_operand" "=w") -+ (unspec:VQX [(match_operand:VQX 1 "general_operand" " Um")] -+ UNSPEC_MISALIGNED_ACCESS))] -+ "TARGET_NEON && !BYTES_BIG_ENDIAN" -+ "vld1.<V_sz_elem>\t{%q0}, %A1" -+ [(set_attr "neon_type" "neon_vld1_1_2_regs")]) -+ - (define_insn "vec_set<mode>_internal" - [(set (match_operand:VD 0 "s_register_operand" "=w") - (vec_merge:VD -@@ -862,6 +922,50 @@ - (const_string "neon_mul_qqq_8_16_32_ddd_32")))))] - ) - -+(define_insn "*mul<mode>3add<mode>_neon" -+ [(set (match_operand:VDQ 0 "s_register_operand" "=w") -+ (plus:VDQ (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w") -+ (match_operand:VDQ 3 "s_register_operand" "w")) -+ (match_operand:VDQ 1 "s_register_operand" "0")))] -+ "TARGET_NEON" -+ "vmla.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3" -+ [(set (attr "neon_type") -+ (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) -+ (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) -+ (const_string "neon_fp_vmla_ddd") -+ (const_string "neon_fp_vmla_qqq")) -+ (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) -+ (if_then_else -+ (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) -+ (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long") -+ (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")) -+ (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) -+ (const_string "neon_mla_qqq_8_16") -+ (const_string "neon_mla_qqq_32_qqd_32_scalar")))))] -+) -+ -+(define_insn "*mul<mode>3neg<mode>add<mode>_neon" -+ [(set (match_operand:VDQ 0 "s_register_operand" "=w") -+ (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "0") -+ (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w") -+ (match_operand:VDQ 3 "s_register_operand" "w"))))] -+ "TARGET_NEON" -+ "vmls.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3" -+ [(set (attr "neon_type") -+ (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) -+ (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) -+ (const_string "neon_fp_vmla_ddd") -+ (const_string "neon_fp_vmla_qqq")) -+ (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) -+ (if_then_else -+ (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) -+ (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long") -+ (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")) -+ (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) -+ (const_string "neon_mla_qqq_8_16") -+ (const_string "neon_mla_qqq_32_qqd_32_scalar")))))] -+) -+ - (define_insn "ior<mode>3" - [(set (match_operand:VDQ 0 "s_register_operand" "=w,w") - (ior:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0") -@@ -3611,7 +3715,8 @@ - UNSPEC_VSHLL_N))] - "TARGET_NEON" - { -- neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode)); -+ /* The boundaries are: 0 < imm <= size. */ -+ neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode) + 1); - return "vshll.%T3%#<V_sz_elem>\t%q0, %P1, %2"; - } - [(set_attr "neon_type" "neon_shift_1")] ---- a/gcc/config/arm/neon.ml -+++ b/gcc/config/arm/neon.ml -@@ -50,7 +50,7 @@ - | T_ptrto of vectype | T_const of vectype - | T_void | T_intQI - | T_intHI | T_intSI -- | T_intDI -+ | T_intDI | T_floatSF - - (* The meanings of the following are: - TImode : "Tetra", two registers (four words). -@@ -1693,6 +1693,7 @@ - | T_intHI -> "__builtin_neon_hi" - | T_intSI -> "__builtin_neon_si" - | T_intDI -> "__builtin_neon_di" -+ | T_floatSF -> "__builtin_neon_sf" - | T_arrayof (num, base) -> - let basename = name (fun x -> x) base in - affix (Printf.sprintf "%sx%d" basename num) ---- a/gcc/config/arm/neon-testgen.ml -+++ b/gcc/config/arm/neon-testgen.ml -@@ -51,8 +51,8 @@ - Printf.fprintf chan "/* This file was autogenerated by neon-testgen. */\n\n"; - Printf.fprintf chan "/* { dg-do assemble } */\n"; - Printf.fprintf chan "/* { dg-require-effective-target arm_neon_ok } */\n"; -- Printf.fprintf chan -- "/* { dg-options \"-save-temps -O0 -mfpu=neon -mfloat-abi=softfp\" } */\n"; -+ Printf.fprintf chan "/* { dg-options \"-save-temps -O0\" } */\n"; -+ Printf.fprintf chan "/* { dg-add-options arm_neon } */\n"; - Printf.fprintf chan "\n#include \"arm_neon.h\"\n\n"; - Printf.fprintf chan "void test_%s (void)\n{\n" test_name - ---- a/gcc/config/arm/netbsd-elf.h -+++ b/gcc/config/arm/netbsd-elf.h -@@ -153,5 +153,5 @@ - while (0) - - #undef FPUTYPE_DEFAULT --#define FPUTYPE_DEFAULT FPUTYPE_VFP -+#define FPUTYPE_DEFAULT "vfp" - ---- /dev/null -+++ b/gcc/config/arm/nocrt0.h -@@ -0,0 +1,25 @@ -+/* Definitions for generic libgloss based cofigs where crt0 is supplied by -+ the linker script. -+ Copyright (C) 2006 Free Software Foundation, Inc. -+ -+ This file is part of GCC. -+ -+ GCC is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published -+ by the Free Software Foundation; either version 3, or (at your -+ option) any later version. -+ -+ GCC is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+ License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with GCC; see the file COPYING3. If not see -+ <http://www.gnu.org/licenses/>. */ -+ -+#undef STARTFILE_SPEC -+#define STARTFILE_SPEC " crti%O%s crtbegin%O%s" -+ -+#undef LIB_SPEC -+#define LIB_SPEC "-lc" ---- a/gcc/config/arm/predicates.md -+++ b/gcc/config/arm/predicates.md -@@ -73,6 +73,10 @@ - || REGNO_REG_CLASS (REGNO (op)) == FPA_REGS)); - }) - -+(define_special_predicate "subreg_lowpart_operator" -+ (and (match_code "subreg") -+ (match_test "subreg_lowpart_p (op)"))) -+ - ;; Reg, subreg(reg) or const_int. - (define_predicate "reg_or_int_operand" - (ior (match_code "const_int") -@@ -168,6 +172,11 @@ - (and (match_code "plus,minus,ior,xor,and") - (match_test "mode == GET_MODE (op)"))) - -+;; True for plus/minus operators -+(define_special_predicate "plusminus_operator" -+ (and (match_code "plus,minus") -+ (match_test "mode == GET_MODE (op)"))) -+ - ;; True for logical binary operators. - (define_special_predicate "logical_binary_operator" - (and (match_code "ior,xor,and") -@@ -295,6 +304,9 @@ - HOST_WIDE_INT i = 1, base = 0; - rtx elt; - -+ if (low_irq_latency) -+ return false; -+ - if (count <= 1 - || GET_CODE (XVECEXP (op, 0, 0)) != SET) - return false; -@@ -352,6 +364,9 @@ - HOST_WIDE_INT i = 1, base = 0; - rtx elt; - -+ if (low_irq_latency) -+ return false; -+ - if (count <= 1 - || GET_CODE (XVECEXP (op, 0, 0)) != SET) - return false; ---- a/gcc/config/arm/sfp-machine.h -+++ b/gcc/config/arm/sfp-machine.h -@@ -14,9 +14,11 @@ - #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y) - #define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y) - -+#define _FP_NANFRAC_H ((_FP_QNANBIT_H << 1) - 1) - #define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1) - #define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1 - #define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1 -+#define _FP_NANSIGN_H 0 - #define _FP_NANSIGN_S 0 - #define _FP_NANSIGN_D 0 - #define _FP_NANSIGN_Q 0 -@@ -92,5 +94,7 @@ - #define __fixdfdi __aeabi_d2lz - #define __fixunsdfdi __aeabi_d2ulz - #define __floatdidf __aeabi_l2d -+#define __extendhfsf2 __gnu_h2f_ieee -+#define __truncsfhf2 __gnu_f2h_ieee - - #endif /* __ARM_EABI__ */ ---- a/gcc/config/arm/t-arm -+++ b/gcc/config/arm/t-arm -@@ -13,7 +13,9 @@ - $(srcdir)/config/arm/iwmmxt.md \ - $(srcdir)/config/arm/vfp.md \ - $(srcdir)/config/arm/neon.md \ -- $(srcdir)/config/arm/thumb2.md -+ $(srcdir)/config/arm/thumb2.md \ -+ $(srcdir)/config/arm/marvell-f.md \ -+ $(srcdir)/config/arm/hwdiv.md - - s-config s-conditions s-flags s-codes s-constants s-emit s-recog s-preds \ - s-opinit s-extract s-peep s-attr s-attrtab s-output: $(MD_INCLUDES) ---- a/gcc/config/arm/t-arm-elf -+++ b/gcc/config/arm/t-arm-elf -@@ -24,10 +24,18 @@ - #MULTILIB_MATCHES += march?armv7=march?armv7-a - #MULTILIB_MATCHES += march?armv7=march?armv7-r - #MULTILIB_MATCHES += march?armv7=march?armv7-m -+#MULTILIB_MATCHES += march?armv7=march?armv7e-m - #MULTILIB_MATCHES += march?armv7=mcpu?cortex-a8 - #MULTILIB_MATCHES += march?armv7=mcpu?cortex-r4 - #MULTILIB_MATCHES += march?armv7=mcpu?cortex-m3 - -+# Not quite true. We can support hard-vfp calling in Thumb2, but how do we -+# express that here? Also, we really need architecture v5e or later -+# (mcrr etc). -+MULTILIB_OPTIONS += mfloat-abi=hard -+MULTILIB_DIRNAMES += fpu -+MULTILIB_EXCEPTIONS += *mthumb/*mfloat-abi=hard* -+ - # MULTILIB_OPTIONS += mcpu=ep9312 - # MULTILIB_DIRNAMES += ep9312 - # MULTILIB_EXCEPTIONS += *mthumb/*mcpu=ep9312* ---- a/gcc/config/arm/t-bpabi -+++ b/gcc/config/arm/t-bpabi -@@ -1,10 +1,13 @@ - # Add the bpabi.S functions. --LIB1ASMFUNCS += _aeabi_lcmp _aeabi_ulcmp _aeabi_ldivmod _aeabi_uldivmod -+LIB1ASMFUNCS += _aeabi_lcmp _aeabi_ulcmp _aeabi_ldivmod _aeabi_uldivmod \ -+ _aeabi_idiv0 _aeabi_ldiv0 - - # Add the BPABI C functions. - LIB2FUNCS_EXTRA = $(srcdir)/config/arm/bpabi.c \ - $(srcdir)/config/arm/unaligned-funcs.c - -+LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/arm/fp16.c -+ - UNWIND_H = $(srcdir)/config/arm/unwind-arm.h - LIB2ADDEH = $(srcdir)/config/arm/unwind-arm.c \ - $(srcdir)/config/arm/libunwind.S \ ---- a/gcc/config/arm/thumb2.md -+++ b/gcc/config/arm/thumb2.md -@@ -24,6 +24,8 @@ - ;; changes made in armv5t as "thumb2". These are considered part - ;; the 16-bit Thumb-1 instruction set. - -+(include "hwdiv.md") -+ - (define_insn "*thumb2_incscc" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (plus:SI (match_operator:SI 2 "arm_comparison_operator" -@@ -172,34 +174,6 @@ - (set_attr "length" "8")] - ) - --(define_insn "*thumb2_abssi2" -- [(set (match_operand:SI 0 "s_register_operand" "=r,&r") -- (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))) -- (clobber (reg:CC CC_REGNUM))] -- "TARGET_THUMB2" -- "@ -- cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0 -- eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31" -- [(set_attr "conds" "clob,*") -- (set_attr "shift" "1") -- ;; predicable can't be set based on the variant, so left as no -- (set_attr "length" "10,8")] --) -- --(define_insn "*thumb2_neg_abssi2" -- [(set (match_operand:SI 0 "s_register_operand" "=r,&r") -- (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))) -- (clobber (reg:CC CC_REGNUM))] -- "TARGET_THUMB2" -- "@ -- cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0 -- eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31" -- [(set_attr "conds" "clob,*") -- (set_attr "shift" "1") -- ;; predicable can't be set based on the variant, so left as no -- (set_attr "length" "10,8")] --) -- - (define_insn "*thumb2_movdi" - [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m") - (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))] -@@ -223,9 +197,14 @@ - (set_attr "neg_pool_range" "*,*,*,0,*")] - ) - -+;; We have two alternatives here for memory loads (and similarly for stores) -+;; to reflect the fact that the permissible constant pool ranges differ -+;; between ldr instructions taking low regs and ldr instructions taking high -+;; regs. The high register alternatives are not taken into account when -+;; choosing register preferences in order to reflect their expense. - (define_insn "*thumb2_movsi_insn" -- [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m") -- (match_operand:SI 1 "general_operand" "rk ,I,K,N,mi,rk"))] -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,l,*hk,m,*m") -+ (match_operand:SI 1 "general_operand" "rk ,I,K,j,mi,*mi,l,*hk"))] - "TARGET_THUMB2 && ! TARGET_IWMMXT - && !(TARGET_HARD_FLOAT && TARGET_VFP) - && ( register_operand (operands[0], SImode) -@@ -236,11 +215,13 @@ - mvn%?\\t%0, #%B1 - movw%?\\t%0, %1 - ldr%?\\t%0, %1 -+ ldr%?\\t%0, %1 -+ str%?\\t%1, %0 - str%?\\t%1, %0" -- [(set_attr "type" "*,*,*,*,load1,store1") -+ [(set_attr "type" "*,*,*,*,load1,load1,store1,store1") - (set_attr "predicable" "yes") -- (set_attr "pool_range" "*,*,*,*,4096,*") -- (set_attr "neg_pool_range" "*,*,*,*,0,*")] -+ (set_attr "pool_range" "*,*,*,*,1020,4096,*,*") -+ (set_attr "neg_pool_range" "*,*,*,*,0,0,*,*")] - ) - - ;; ??? We can probably do better with thumb2 -@@ -1128,27 +1109,7 @@ - return \"add%!\\t%0, %1, %2\"; - " - [(set_attr "predicable" "yes") -- (set_attr "length" "2")] --) -- --(define_insn "divsi3" -- [(set (match_operand:SI 0 "s_register_operand" "=r") -- (div:SI (match_operand:SI 1 "s_register_operand" "r") -- (match_operand:SI 2 "s_register_operand" "r")))] -- "TARGET_THUMB2 && arm_arch_hwdiv" -- "sdiv%?\t%0, %1, %2" -- [(set_attr "predicable" "yes") -- (set_attr "insn" "sdiv")] --) -- --(define_insn "udivsi3" -- [(set (match_operand:SI 0 "s_register_operand" "=r") -- (udiv:SI (match_operand:SI 1 "s_register_operand" "r") -- (match_operand:SI 2 "s_register_operand" "r")))] -- "TARGET_THUMB2 && arm_arch_hwdiv" -- "udiv%?\t%0, %1, %2" -- [(set_attr "predicable" "yes") -- (set_attr "insn" "udiv")] -+ (set_attr "length" "4")] - ) - - (define_insn "*thumb2_subsi_short" -@@ -1162,6 +1123,71 @@ - (set_attr "length" "2")] - ) - -+;; 16-bit encodings of "muls" and "mul<c>". We only use these when -+;; optimizing for size since "muls" is slow on all known -+;; implementations and since "mul<c>" will be generated by -+;; "*arm_mulsi3_v6" anyhow. The assembler will use a 16-bit encoding -+;; for "mul<c>" whenever possible anyhow. -+(define_peephole2 -+ [(set (match_operand:SI 0 "low_register_operand" "") -+ (mult:SI (match_operand:SI 1 "low_register_operand" "") -+ (match_dup 0)))] -+ "TARGET_THUMB2 && optimize_size && peep2_regno_dead_p (0, CC_REGNUM)" -+ [(parallel -+ [(set (match_dup 0) -+ (mult:SI (match_dup 0) (match_dup 1))) -+ (clobber (reg:CC CC_REGNUM))])] -+ "" -+) -+ -+(define_peephole2 -+ [(set (match_operand:SI 0 "low_register_operand" "") -+ (mult:SI (match_dup 0) -+ (match_operand:SI 1 "low_register_operand" "")))] -+ "TARGET_THUMB2 && optimize_size && peep2_regno_dead_p (0, CC_REGNUM)" -+ [(parallel -+ [(set (match_dup 0) -+ (mult:SI (match_dup 0) (match_dup 1))) -+ (clobber (reg:CC CC_REGNUM))])] -+ "" -+) -+ -+(define_insn "*thumb2_mulsi_short" -+ [(set (match_operand:SI 0 "low_register_operand" "=l") -+ (mult:SI (match_operand:SI 1 "low_register_operand" "%0") -+ (match_operand:SI 2 "low_register_operand" "l"))) -+ (clobber (reg:CC CC_REGNUM))] -+ "TARGET_THUMB2 && optimize_size && reload_completed" -+ "mul%!\\t%0, %2, %0" -+ [(set_attr "predicable" "yes") -+ (set_attr "length" "2") -+ (set_attr "insn" "muls")]) -+ -+(define_insn "*thumb2_mulsi_short_compare0" -+ [(set (reg:CC_NOOV CC_REGNUM) -+ (compare:CC_NOOV -+ (mult:SI (match_operand:SI 1 "register_operand" "%0") -+ (match_operand:SI 2 "register_operand" "l")) -+ (const_int 0))) -+ (set (match_operand:SI 0 "register_operand" "=l") -+ (mult:SI (match_dup 1) (match_dup 2)))] -+ "TARGET_THUMB2 && optimize_size" -+ "muls\\t%0, %2, %0" -+ [(set_attr "length" "2") -+ (set_attr "insn" "muls")]) -+ -+(define_insn "*thumb2_mulsi_short_compare0_scratch" -+ [(set (reg:CC_NOOV CC_REGNUM) -+ (compare:CC_NOOV -+ (mult:SI (match_operand:SI 1 "register_operand" "%0") -+ (match_operand:SI 2 "register_operand" "l")) -+ (const_int 0))) -+ (clobber (match_scratch:SI 0 "=r"))] -+ "TARGET_THUMB2 && optimize_size" -+ "muls\\t%0, %2, %0" -+ [(set_attr "length" "2") -+ (set_attr "insn" "muls")]) -+ - (define_insn "*thumb2_cbz" - [(set (pc) (if_then_else - (eq (match_operand:SI 0 "s_register_operand" "l,?r") -@@ -1171,7 +1197,7 @@ - (clobber (reg:CC CC_REGNUM))] - "TARGET_THUMB2" - "* -- if (get_attr_length (insn) == 2 && which_alternative == 0) -+ if (get_attr_length (insn) == 2) - return \"cbz\\t%0, %l1\"; - else - return \"cmp\\t%0, #0\;beq\\t%l1\"; -@@ -1179,7 +1205,8 @@ - [(set (attr "length") - (if_then_else - (and (ge (minus (match_dup 1) (pc)) (const_int 2)) -- (le (minus (match_dup 1) (pc)) (const_int 128))) -+ (le (minus (match_dup 1) (pc)) (const_int 128)) -+ (eq (symbol_ref ("which_alternative")) (const_int 0))) - (const_int 2) - (const_int 8)))] - ) -@@ -1193,7 +1220,7 @@ - (clobber (reg:CC CC_REGNUM))] - "TARGET_THUMB2" - "* -- if (get_attr_length (insn) == 2 && which_alternative == 0) -+ if (get_attr_length (insn) == 2) - return \"cbnz\\t%0, %l1\"; - else - return \"cmp\\t%0, #0\;bne\\t%l1\"; -@@ -1201,7 +1228,8 @@ - [(set (attr "length") - (if_then_else - (and (ge (minus (match_dup 1) (pc)) (const_int 2)) -- (le (minus (match_dup 1) (pc)) (const_int 128))) -+ (le (minus (match_dup 1) (pc)) (const_int 128)) -+ (eq (symbol_ref ("which_alternative")) (const_int 0))) - (const_int 2) - (const_int 8)))] - ) ---- a/gcc/config/arm/t-linux-eabi -+++ b/gcc/config/arm/t-linux-eabi -@@ -6,8 +6,8 @@ - MULTILIB_OPTIONS = - MULTILIB_DIRNAMES = - --# Use a version of div0 which raises SIGFPE. --LIB1ASMFUNCS := $(filter-out _dvmd_tls,$(LIB1ASMFUNCS)) _dvmd_lnx -+# Use a version of div0 which raises SIGFPE, and a special __clear_cache. -+LIB1ASMFUNCS := $(filter-out _dvmd_tls,$(LIB1ASMFUNCS)) _dvmd_lnx _clear_cache - - # Multilib the standard Linux files. Don't include crti.o or crtn.o, - # which are provided by glibc. ---- a/gcc/config/arm/t-symbian -+++ b/gcc/config/arm/t-symbian -@@ -17,6 +17,9 @@ - LIB2ADDEH = $(srcdir)/unwind-c.c $(srcdir)/config/arm/pr-support.c - LIB2ADDEHDEP = $(UNWIND_H) - -+# Include half-float helpers. -+LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/arm/fp16.c -+ - # Create a multilib for processors with VFP floating-point, and a - # multilib for those without -- using the soft-float ABI in both - # cases. Symbian OS object should be compiled with interworking ---- a/gcc/config/arm/uclinux-eabi.h -+++ b/gcc/config/arm/uclinux-eabi.h -@@ -50,6 +50,10 @@ - #undef ARM_DEFAULT_ABI - #define ARM_DEFAULT_ABI ARM_ABI_AAPCS_LINUX - -+#undef LINK_GCC_C_SEQUENCE_SPEC -+#define LINK_GCC_C_SEQUENCE_SPEC \ -+ "--start-group %G %L --end-group" -+ - /* Clear the instruction cache from `beg' to `end'. This makes an - inline system call to SYS_cacheflush. */ - #undef CLEAR_INSN_CACHE ---- a/gcc/config/arm/unwind-arm.c -+++ b/gcc/config/arm/unwind-arm.c -@@ -1000,7 +1000,6 @@ - while (code != _URC_END_OF_STACK - && code != _URC_FAILURE); - -- finish: - restore_non_core_regs (&saved_vrs); - return code; - } -@@ -1168,6 +1167,9 @@ - { - matched = (void *)(ucbp + 1); - rtti = _Unwind_decode_target2 ((_uw) &data[i + 1]); -+ /* There is no way to encode an exception -+ specification for 'class X * &', so -+ always pass false for is_reference. */ - if (__cxa_type_match (ucbp, (type_info *) rtti, 0, - &matched)) - break; -@@ -1197,8 +1199,6 @@ - ucbp->barrier_cache.bitpattern[4] = (_uw) &data[1]; - - if (data[0] & uint32_highbit) -- phase2_call_unexpected_after_unwind = 1; -- else - { - data += rtti_count + 1; - /* Setup for entry to the handler. */ -@@ -1208,6 +1208,8 @@ - _Unwind_SetGR (context, 0, (_uw) ucbp); - return _URC_INSTALL_CONTEXT; - } -+ else -+ phase2_call_unexpected_after_unwind = 1; - } - if (data[0] & uint32_highbit) - data++; ---- a/gcc/config/arm/unwind-arm.h -+++ b/gcc/config/arm/unwind-arm.h -@@ -229,9 +229,10 @@ - return 0; - - #if (defined(linux) && !defined(__uClinux__)) || defined(__NetBSD__) -- /* Pc-relative indirect. */ -+ /* Pc-relative indirect. Propagate the bottom 2 bits, which can -+ contain referenceness information in gnu unwinding tables. */ - tmp += ptr; -- tmp = *(_Unwind_Word *) tmp; -+ tmp = *(_Unwind_Word *) (tmp & ~(_Unwind_Word)3) | (tmp & 3); - #elif defined(__symbian__) || defined(__uClinux__) - /* Absolute pointer. Nothing more to do. */ - #else ---- a/gcc/config/arm/vec-common.md -+++ b/gcc/config/arm/vec-common.md -@@ -38,6 +38,11 @@ - "TARGET_NEON - || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))" - { -+ if (can_create_pseudo_p ()) -+ { -+ if (GET_CODE (operands[0]) != REG) -+ operands[1] = force_reg (<MODE>mode, operands[1]); -+ } - }) - - ;; Vector arithmetic. Expanders are blank, then unnamed insns implement ---- a/gcc/config/arm/vfp.md -+++ b/gcc/config/arm/vfp.md -@@ -51,7 +51,7 @@ - ;; problems because small constants get converted into adds. - (define_insn "*arm_movsi_vfp" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m ,*t,r,*t,*t, *Uv") -- (match_operand:SI 1 "general_operand" "rk, I,K,N,mi,rk,r,*t,*t,*Uvi,*t"))] -+ (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk,r,*t,*t,*Uvi,*t"))] - "TARGET_ARM && TARGET_VFP && TARGET_HARD_FLOAT - && ( s_register_operand (operands[0], SImode) - || s_register_operand (operands[1], SImode))" -@@ -82,13 +82,17 @@ - " - [(set_attr "predicable" "yes") - (set_attr "type" "*,*,*,*,load1,store1,r_2_f,f_2_r,fcpys,f_loads,f_stores") -+ (set_attr "neon_type" "*,*,*,*,*,*,neon_mcr,neon_mrc,neon_vmov,*,*") -+ (set_attr "insn" "mov,mov,mvn,mov,*,*,*,*,*,*,*") - (set_attr "pool_range" "*,*,*,*,4096,*,*,*,*,1020,*") - (set_attr "neg_pool_range" "*,*,*,*,4084,*,*,*,*,1008,*")] - ) - -+;; See thumb2.md:thumb2_movsi_insn for an explanation of the split -+;; high/low register alternatives for loads and stores here. - (define_insn "*thumb2_movsi_vfp" -- [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m,*t,r, *t,*t, *Uv") -- (match_operand:SI 1 "general_operand" "rk, I,K,N,mi,rk,r,*t,*t,*Uvi,*t"))] -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,l,*hk,m,*m,*t,r, *t,*t, *Uv") -+ (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,*mi,l,*hk,r,*t,*t,*Uvi,*t"))] - "TARGET_THUMB2 && TARGET_VFP && TARGET_HARD_FLOAT - && ( s_register_operand (operands[0], SImode) - || s_register_operand (operands[1], SImode))" -@@ -102,25 +106,29 @@ - case 3: - return \"movw%?\\t%0, %1\"; - case 4: -- return \"ldr%?\\t%0, %1\"; - case 5: -- return \"str%?\\t%1, %0\"; -+ return \"ldr%?\\t%0, %1\"; - case 6: -- return \"fmsr%?\\t%0, %1\\t%@ int\"; - case 7: -- return \"fmrs%?\\t%0, %1\\t%@ int\"; -+ return \"str%?\\t%1, %0\"; - case 8: -+ return \"fmsr%?\\t%0, %1\\t%@ int\"; -+ case 9: -+ return \"fmrs%?\\t%0, %1\\t%@ int\"; -+ case 10: - return \"fcpys%?\\t%0, %1\\t%@ int\"; -- case 9: case 10: -+ case 11: case 12: - return output_move_vfp (operands); - default: - gcc_unreachable (); - } - " - [(set_attr "predicable" "yes") -- (set_attr "type" "*,*,*,*,load1,store1,r_2_f,f_2_r,fcpys,f_load,f_store") -- (set_attr "pool_range" "*,*,*,*,4096,*,*,*,*,1020,*") -- (set_attr "neg_pool_range" "*,*,*,*, 0,*,*,*,*,1008,*")] -+ (set_attr "type" "*,*,*,*,load1,load1,store1,store1,r_2_f,f_2_r,fcpys,f_load,f_store") -+ (set_attr "neon_type" "*,*,*,*,*,*,*,*,neon_mcr,neon_mrc,neon_vmov,*,*") -+ (set_attr "insn" "mov,mov,mvn,mov,*,*,*,*,*,*,*,*,*") -+ (set_attr "pool_range" "*,*,*,*,1020,4096,*,*,*,*,*,1020,*") -+ (set_attr "neg_pool_range" "*,*,*,*, 0, 0,*,*,*,*,*,1008,*")] - ) - - -@@ -145,7 +153,10 @@ - case 4: - return \"fmrrd%?\\t%Q0, %R0, %P1\\t%@ int\"; - case 5: -- return \"fcpyd%?\\t%P0, %P1\\t%@ int\"; -+ if (TARGET_VFP_SINGLE) -+ return \"fcpys%?\\t%0, %1\\t%@ int\;fcpys%?\\t%p0, %p1\\t%@ int\"; -+ else -+ return \"fcpyd%?\\t%P0, %P1\\t%@ int\"; - case 6: case 7: - return output_move_vfp (operands); - default: -@@ -153,7 +164,14 @@ - } - " - [(set_attr "type" "*,load2,store2,r_2_f,f_2_r,ffarithd,f_loadd,f_stored") -- (set_attr "length" "8,8,8,4,4,4,4,4") -+ (set_attr "neon_type" "*,*,*,neon_mcr_2_mcrr,neon_mrrc,neon_vmov,*,*") -+ (set (attr "length") (cond [(eq_attr "alternative" "0,1,2") (const_int 8) -+ (eq_attr "alternative" "5") -+ (if_then_else -+ (eq (symbol_ref "TARGET_VFP_SINGLE") (const_int 1)) -+ (const_int 8) -+ (const_int 4))] -+ (const_int 4))) - (set_attr "pool_range" "*,1020,*,*,*,*,1020,*") - (set_attr "neg_pool_range" "*,1008,*,*,*,*,1008,*")] - ) -@@ -172,7 +190,10 @@ - case 4: - return \"fmrrd%?\\t%Q0, %R0, %P1\\t%@ int\"; - case 5: -- return \"fcpyd%?\\t%P0, %P1\\t%@ int\"; -+ if (TARGET_VFP_SINGLE) -+ return \"fcpys%?\\t%0, %1\\t%@ int\;fcpys%?\\t%p0, %p1\\t%@ int\"; -+ else -+ return \"fcpyd%?\\t%P0, %P1\\t%@ int\"; - case 6: case 7: - return output_move_vfp (operands); - default: -@@ -180,11 +201,123 @@ - } - " - [(set_attr "type" "*,load2,store2,r_2_f,f_2_r,ffarithd,f_load,f_store") -- (set_attr "length" "8,8,8,4,4,4,4,4") -+ (set_attr "neon_type" "*,*,*,neon_mcr_2_mcrr,neon_mrrc,neon_vmov,*,*") -+ (set (attr "length") (cond [(eq_attr "alternative" "0,1,2") (const_int 8) -+ (eq_attr "alternative" "5") -+ (if_then_else -+ (eq (symbol_ref "TARGET_VFP_SINGLE") (const_int 1)) -+ (const_int 8) -+ (const_int 4))] -+ (const_int 4))) - (set_attr "pool_range" "*,4096,*,*,*,*,1020,*") - (set_attr "neg_pool_range" "*, 0,*,*,*,*,1008,*")] - ) - -+;; HFmode moves -+(define_insn "*movhf_vfp_neon" -+ [(set (match_operand:HF 0 "nonimmediate_operand" "= t,Um,r,m,t,r,t,r,r") -+ (match_operand:HF 1 "general_operand" " Um, t,m,r,t,r,r,t,F"))] -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_NEON_FP16 -+ && ( s_register_operand (operands[0], HFmode) -+ || s_register_operand (operands[1], HFmode))" -+ "* -+ switch (which_alternative) -+ { -+ case 0: /* S register from memory */ -+ return \"vld1.16\\t{%z0}, %A1\"; -+ case 1: /* memory from S register */ -+ return \"vst1.16\\t{%z1}, %A0\"; -+ case 2: /* ARM register from memory */ -+ return \"ldrh\\t%0, %1\\t%@ __fp16\"; -+ case 3: /* memory from ARM register */ -+ return \"strh\\t%1, %0\\t%@ __fp16\"; -+ case 4: /* S register from S register */ -+ return \"fcpys\\t%0, %1\"; -+ case 5: /* ARM register from ARM register */ -+ return \"mov\\t%0, %1\\t%@ __fp16\"; -+ case 6: /* S register from ARM register */ -+ return \"fmsr\\t%0, %1\"; -+ case 7: /* ARM register from S register */ -+ return \"fmrs\\t%0, %1\"; -+ case 8: /* ARM register from constant */ -+ { -+ REAL_VALUE_TYPE r; -+ long bits; -+ rtx ops[4]; -+ -+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]); -+ bits = real_to_target (NULL, &r, HFmode); -+ ops[0] = operands[0]; -+ ops[1] = GEN_INT (bits); -+ ops[2] = GEN_INT (bits & 0xff00); -+ ops[3] = GEN_INT (bits & 0x00ff); -+ -+ if (arm_arch_thumb2) -+ output_asm_insn (\"movw\\t%0, %1\", ops); -+ else -+ output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops); -+ return \"\"; -+ } -+ default: -+ gcc_unreachable (); -+ } -+ " -+ [(set_attr "conds" "unconditional") -+ (set_attr "type" "*,*,load1,store1,fcpys,*,r_2_f,f_2_r,*") -+ (set_attr "neon_type" "neon_vld1_1_2_regs,neon_vst1_1_2_regs_vst2_2_regs,*,*,*,*,*,*,*") -+ (set_attr "length" "4,4,4,4,4,4,4,4,8")] -+) -+ -+;; FP16 without element load/store instructions. -+(define_insn "*movhf_vfp" -+ [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r") -+ (match_operand:HF 1 "general_operand" " m,r,t,r,r,t,F"))] -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FP16 && !TARGET_NEON_FP16 -+ && ( s_register_operand (operands[0], HFmode) -+ || s_register_operand (operands[1], HFmode))" -+ "* -+ switch (which_alternative) -+ { -+ case 0: /* ARM register from memory */ -+ return \"ldrh\\t%0, %1\\t%@ __fp16\"; -+ case 1: /* memory from ARM register */ -+ return \"strh\\t%1, %0\\t%@ __fp16\"; -+ case 2: /* S register from S register */ -+ return \"fcpys\\t%0, %1\"; -+ case 3: /* ARM register from ARM register */ -+ return \"mov\\t%0, %1\\t%@ __fp16\"; -+ case 4: /* S register from ARM register */ -+ return \"fmsr\\t%0, %1\"; -+ case 5: /* ARM register from S register */ -+ return \"fmrs\\t%0, %1\"; -+ case 6: /* ARM register from constant */ -+ { -+ REAL_VALUE_TYPE r; -+ long bits; -+ rtx ops[4]; -+ -+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]); -+ bits = real_to_target (NULL, &r, HFmode); -+ ops[0] = operands[0]; -+ ops[1] = GEN_INT (bits); -+ ops[2] = GEN_INT (bits & 0xff00); -+ ops[3] = GEN_INT (bits & 0x00ff); -+ -+ if (arm_arch_thumb2) -+ output_asm_insn (\"movw\\t%0, %1\", ops); -+ else -+ output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops); -+ return \"\"; -+ } -+ default: -+ gcc_unreachable (); -+ } -+ " -+ [(set_attr "conds" "unconditional") -+ (set_attr "type" "load1,store1,fcpys,*,r_2_f,f_2_r,*") -+ (set_attr "length" "4,4,4,4,4,4,8")] -+) -+ - - ;; SFmode moves - ;; Disparage the w<->r cases because reloading an invalid address is -@@ -222,6 +355,8 @@ - [(set_attr "predicable" "yes") - (set_attr "type" - "r_2_f,f_2_r,fconsts,f_loads,f_stores,load1,store1,fcpys,*") -+ (set_attr "neon_type" "neon_mcr,neon_mrc,*,*,*,*,*,neon_vmov,*") -+ (set_attr "insn" "*,*,*,*,*,*,*,*,mov") - (set_attr "pool_range" "*,*,*,1020,*,4096,*,*,*") - (set_attr "neg_pool_range" "*,*,*,1008,*,4080,*,*,*")] - ) -@@ -258,6 +393,8 @@ - [(set_attr "predicable" "yes") - (set_attr "type" - "r_2_f,f_2_r,fconsts,f_load,f_store,load1,store1,fcpys,*") -+ (set_attr "neon_type" "neon_mcr,neon_mrc,*,*,*,*,*,neon_vmov,*") -+ (set_attr "insn" "*,*,*,*,*,*,*,*,mov") - (set_attr "pool_range" "*,*,*,1020,*,4092,*,*,*") - (set_attr "neg_pool_range" "*,*,*,1008,*,0,*,*,*")] - ) -@@ -267,7 +404,7 @@ - - (define_insn "*movdf_vfp" - [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,r, m,w ,Uv,w,r") -- (match_operand:DF 1 "soft_df_operand" " ?r,w,Dv,mF,r,UvF,w, w,r"))] -+ (match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,mF,r,UvF,w, w,r"))] - "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP - && ( register_operand (operands[0], DFmode) - || register_operand (operands[1], DFmode))" -@@ -280,13 +417,17 @@ - case 1: - return \"fmrrd%?\\t%Q0, %R0, %P1\"; - case 2: -+ gcc_assert (TARGET_VFP_DOUBLE); - return \"fconstd%?\\t%P0, #%G1\"; - case 3: case 4: - return output_move_double (operands); - case 5: case 6: - return output_move_vfp (operands); - case 7: -- return \"fcpyd%?\\t%P0, %P1\"; -+ if (TARGET_VFP_SINGLE) -+ return \"fcpys%?\\t%0, %1\;fcpys%?\\t%p0, %p1\"; -+ else -+ return \"fcpyd%?\\t%P0, %P1\"; - case 8: - return \"#\"; - default: -@@ -296,14 +437,21 @@ - " - [(set_attr "type" - "r_2_f,f_2_r,fconstd,f_loadd,f_stored,load2,store2,ffarithd,*") -- (set_attr "length" "4,4,4,8,8,4,4,4,8") -+ (set_attr "neon_type" "neon_mcr_2_mcrr,neon_mrrc,*,*,*,*,*,neon_vmov,*") -+ (set (attr "length") (cond [(eq_attr "alternative" "3,4,8") (const_int 8) -+ (eq_attr "alternative" "7") -+ (if_then_else -+ (eq (symbol_ref "TARGET_VFP_SINGLE") (const_int 1)) -+ (const_int 8) -+ (const_int 4))] -+ (const_int 4))) - (set_attr "pool_range" "*,*,*,1020,*,1020,*,*,*") - (set_attr "neg_pool_range" "*,*,*,1008,*,1008,*,*,*")] - ) - - (define_insn "*thumb2_movdf_vfp" - [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,r, m,w ,Uv,w,r") -- (match_operand:DF 1 "soft_df_operand" " ?r,w,Dv,mF,r,UvF,w, w,r"))] -+ (match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,mF,r,UvF,w, w,r"))] - "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP" - "* - { -@@ -314,13 +462,17 @@ - case 1: - return \"fmrrd%?\\t%Q0, %R0, %P1\"; - case 2: -+ gcc_assert (TARGET_VFP_DOUBLE); - return \"fconstd%?\\t%P0, #%G1\"; - case 3: case 4: case 8: - return output_move_double (operands); - case 5: case 6: - return output_move_vfp (operands); - case 7: -- return \"fcpyd%?\\t%P0, %P1\"; -+ if (TARGET_VFP_SINGLE) -+ return \"fcpys%?\\t%0, %1\;fcpys%?\\t%p0, %p1\"; -+ else -+ return \"fcpyd%?\\t%P0, %P1\"; - default: - abort (); - } -@@ -328,7 +480,14 @@ - " - [(set_attr "type" - "r_2_f,f_2_r,fconstd,load2,store2,f_load,f_store,ffarithd,*") -- (set_attr "length" "4,4,4,8,8,4,4,4,8") -+ (set_attr "neon_type" "neon_mcr_2_mcrr,neon_mrrc,*,*,*,*,*,neon_vmov,*") -+ (set (attr "length") (cond [(eq_attr "alternative" "3,4,8") (const_int 8) -+ (eq_attr "alternative" "7") -+ (if_then_else -+ (eq (symbol_ref "TARGET_VFP_SINGLE") (const_int 1)) -+ (const_int 8) -+ (const_int 4))] -+ (const_int 4))) - (set_attr "pool_range" "*,*,*,4096,*,1020,*,*,*") - (set_attr "neg_pool_range" "*,*,*,0,*,1008,*,*,*")] - ) -@@ -356,7 +515,8 @@ - fmrs%D3\\t%0, %2\;fmrs%d3\\t%0, %1" - [(set_attr "conds" "use") - (set_attr "length" "4,4,8,4,4,8,4,4,8") -- (set_attr "type" "fcpys,fcpys,fcpys,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")] -+ (set_attr "type" "fcpys,fcpys,fcpys,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r") -+ (set_attr "neon_type" "neon_vmov,neon_vmov,neon_vmov,neon_mcr,neon_mcr,neon_mcr,neon_mrc,neon_mrc,neon_mrc")] - ) - - (define_insn "*thumb2_movsfcc_vfp" -@@ -379,7 +539,8 @@ - ite\\t%D3\;fmrs%D3\\t%0, %2\;fmrs%d3\\t%0, %1" - [(set_attr "conds" "use") - (set_attr "length" "6,6,10,6,6,10,6,6,10") -- (set_attr "type" "fcpys,fcpys,fcpys,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")] -+ (set_attr "type" "fcpys,fcpys,fcpys,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r") -+ (set_attr "neon_type" "neon_vmov,neon_vmov,neon_vmov,neon_mcr,neon_mcr,neon_mcr,neon_mrc,neon_mrc,neon_mrc")] - ) - - (define_insn "*movdfcc_vfp" -@@ -389,7 +550,7 @@ - [(match_operand 4 "cc_register" "") (const_int 0)]) - (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w") - (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))] -- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "@ - fcpyd%D3\\t%P0, %P2 - fcpyd%d3\\t%P0, %P1 -@@ -402,7 +563,8 @@ - fmrrd%D3\\t%Q0, %R0, %P2\;fmrrd%d3\\t%Q0, %R0, %P1" - [(set_attr "conds" "use") - (set_attr "length" "4,4,8,4,4,8,4,4,8") -- (set_attr "type" "ffarithd,ffarithd,ffarithd,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")] -+ (set_attr "type" "ffarithd,ffarithd,ffarithd,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r") -+ (set_attr "neon_type" "neon_vmov,neon_vmov,neon_vmov,neon_mcr_2_mcrr,neon_mcr_2_mcrr,neon_mcr_2_mcrr,neon_mrrc,neon_mrrc,neon_mrrc")] - ) - - (define_insn "*thumb2_movdfcc_vfp" -@@ -412,7 +574,7 @@ - [(match_operand 4 "cc_register" "") (const_int 0)]) - (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w") - (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))] -- "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "@ - it\\t%D3\;fcpyd%D3\\t%P0, %P2 - it\\t%d3\;fcpyd%d3\\t%P0, %P1 -@@ -425,7 +587,8 @@ - ite\\t%D3\;fmrrd%D3\\t%Q0, %R0, %P2\;fmrrd%d3\\t%Q0, %R0, %P1" - [(set_attr "conds" "use") - (set_attr "length" "6,6,10,6,6,10,6,6,10") -- (set_attr "type" "ffarithd,ffarithd,ffarithd,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")] -+ (set_attr "type" "ffarithd,ffarithd,ffarithd,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r") -+ (set_attr "neon_type" "neon_vmov,neon_vmov,neon_vmov,neon_mcr_2_mcrr,neon_mcr_2_mcrr,neon_mcr_2_mcrr,neon_mrrc,neon_mrrc,neon_mrrc")] - ) - - -@@ -443,7 +606,7 @@ - (define_insn "*absdf2_vfp" - [(set (match_operand:DF 0 "s_register_operand" "=w") - (abs:DF (match_operand:DF 1 "s_register_operand" "w")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "fabsd%?\\t%P0, %P1" - [(set_attr "predicable" "yes") - (set_attr "type" "ffarithd")] -@@ -463,12 +626,12 @@ - (define_insn_and_split "*negdf2_vfp" - [(set (match_operand:DF 0 "s_register_operand" "=w,?r,?r") - (neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "@ - fnegd%?\\t%P0, %P1 - # - #" -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP && reload_completed -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && reload_completed - && arm_general_register_operand (operands[0], DFmode)" - [(set (match_dup 0) (match_dup 1))] - " -@@ -523,7 +686,7 @@ - [(set (match_operand:DF 0 "s_register_operand" "=w") - (plus:DF (match_operand:DF 1 "s_register_operand" "w") - (match_operand:DF 2 "s_register_operand" "w")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "faddd%?\\t%P0, %P1, %P2" - [(set_attr "predicable" "yes") - (set_attr "type" "faddd")] -@@ -544,7 +707,7 @@ - [(set (match_operand:DF 0 "s_register_operand" "=w") - (minus:DF (match_operand:DF 1 "s_register_operand" "w") - (match_operand:DF 2 "s_register_operand" "w")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "fsubd%?\\t%P0, %P1, %P2" - [(set_attr "predicable" "yes") - (set_attr "type" "faddd")] -@@ -567,7 +730,7 @@ - [(set (match_operand:DF 0 "s_register_operand" "+w") - (div:DF (match_operand:DF 1 "s_register_operand" "w") - (match_operand:DF 2 "s_register_operand" "w")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "fdivd%?\\t%P0, %P1, %P2" - [(set_attr "predicable" "yes") - (set_attr "type" "fdivd")] -@@ -590,7 +753,7 @@ - [(set (match_operand:DF 0 "s_register_operand" "+w") - (mult:DF (match_operand:DF 1 "s_register_operand" "w") - (match_operand:DF 2 "s_register_operand" "w")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "fmuld%?\\t%P0, %P1, %P2" - [(set_attr "predicable" "yes") - (set_attr "type" "fmuld")] -@@ -611,7 +774,7 @@ - [(set (match_operand:DF 0 "s_register_operand" "+w") - (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w")) - (match_operand:DF 2 "s_register_operand" "w")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "fnmuld%?\\t%P0, %P1, %P2" - [(set_attr "predicable" "yes") - (set_attr "type" "fmuld")] -@@ -626,7 +789,8 @@ - (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t") - (match_operand:SF 3 "s_register_operand" "t")) - (match_operand:SF 1 "s_register_operand" "0")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP -+ && (!arm_tune_marvell_f || optimize_size)" - "fmacs%?\\t%0, %2, %3" - [(set_attr "predicable" "yes") - (set_attr "type" "fmacs")] -@@ -637,7 +801,8 @@ - (plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w") - (match_operand:DF 3 "s_register_operand" "w")) - (match_operand:DF 1 "s_register_operand" "0")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE -+ && (!arm_tune_marvell_f || optimize_size)" - "fmacd%?\\t%P0, %P2, %P3" - [(set_attr "predicable" "yes") - (set_attr "type" "fmacd")] -@@ -649,7 +814,8 @@ - (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t") - (match_operand:SF 3 "s_register_operand" "t")) - (match_operand:SF 1 "s_register_operand" "0")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP -+ && (!arm_tune_marvell_f || optimize_size)" - "fmscs%?\\t%0, %2, %3" - [(set_attr "predicable" "yes") - (set_attr "type" "fmacs")] -@@ -660,7 +826,8 @@ - (minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w") - (match_operand:DF 3 "s_register_operand" "w")) - (match_operand:DF 1 "s_register_operand" "0")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE -+ && (!arm_tune_marvell_f || optimize_size)" - "fmscd%?\\t%P0, %P2, %P3" - [(set_attr "predicable" "yes") - (set_attr "type" "fmacd")] -@@ -672,7 +839,8 @@ - (minus:SF (match_operand:SF 1 "s_register_operand" "0") - (mult:SF (match_operand:SF 2 "s_register_operand" "t") - (match_operand:SF 3 "s_register_operand" "t"))))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP -+ && (!arm_tune_marvell_f || optimize_size)" - "fnmacs%?\\t%0, %2, %3" - [(set_attr "predicable" "yes") - (set_attr "type" "fmacs")] -@@ -683,7 +851,8 @@ - (minus:DF (match_operand:DF 1 "s_register_operand" "0") - (mult:DF (match_operand:DF 2 "s_register_operand" "w") - (match_operand:DF 3 "s_register_operand" "w"))))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE -+ && (!arm_tune_marvell_f || optimize_size)" - "fnmacd%?\\t%P0, %P2, %P3" - [(set_attr "predicable" "yes") - (set_attr "type" "fmacd")] -@@ -697,7 +866,8 @@ - (neg:SF (match_operand:SF 2 "s_register_operand" "t")) - (match_operand:SF 3 "s_register_operand" "t")) - (match_operand:SF 1 "s_register_operand" "0")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP -+ && (!arm_tune_marvell_f || optimize_size)" - "fnmscs%?\\t%0, %2, %3" - [(set_attr "predicable" "yes") - (set_attr "type" "fmacs")] -@@ -709,7 +879,8 @@ - (neg:DF (match_operand:DF 2 "s_register_operand" "w")) - (match_operand:DF 3 "s_register_operand" "w")) - (match_operand:DF 1 "s_register_operand" "0")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE -+ && (!arm_tune_marvell_f || optimize_size)" - "fnmscd%?\\t%P0, %P2, %P3" - [(set_attr "predicable" "yes") - (set_attr "type" "fmacd")] -@@ -721,7 +892,7 @@ - (define_insn "*extendsfdf2_vfp" - [(set (match_operand:DF 0 "s_register_operand" "=w") - (float_extend:DF (match_operand:SF 1 "s_register_operand" "t")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "fcvtds%?\\t%P0, %1" - [(set_attr "predicable" "yes") - (set_attr "type" "f_cvt")] -@@ -730,12 +901,30 @@ - (define_insn "*truncdfsf2_vfp" - [(set (match_operand:SF 0 "s_register_operand" "=t") - (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "fcvtsd%?\\t%0, %P1" - [(set_attr "predicable" "yes") - (set_attr "type" "f_cvt")] - ) - -+(define_insn "extendhfsf2" -+ [(set (match_operand:SF 0 "s_register_operand" "=t") -+ (float_extend:SF (match_operand:HF 1 "s_register_operand" "t")))] -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FP16" -+ "vcvtb%?.f32.f16\\t%0, %1" -+ [(set_attr "predicable" "yes") -+ (set_attr "type" "f_cvt")] -+) -+ -+(define_insn "truncsfhf2" -+ [(set (match_operand:HF 0 "s_register_operand" "=t") -+ (float_truncate:HF (match_operand:SF 1 "s_register_operand" "t")))] -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FP16" -+ "vcvtb%?.f16.f32\\t%0, %1" -+ [(set_attr "predicable" "yes") -+ (set_attr "type" "f_cvt")] -+) -+ - (define_insn "*truncsisf2_vfp" - [(set (match_operand:SI 0 "s_register_operand" "=t") - (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))] -@@ -748,7 +937,7 @@ - (define_insn "*truncsidf2_vfp" - [(set (match_operand:SI 0 "s_register_operand" "=t") - (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "ftosizd%?\\t%0, %P1" - [(set_attr "predicable" "yes") - (set_attr "type" "f_cvt")] -@@ -767,7 +956,7 @@ - (define_insn "fixuns_truncdfsi2" - [(set (match_operand:SI 0 "s_register_operand" "=t") - (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "t"))))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "ftouizd%?\\t%0, %P1" - [(set_attr "predicable" "yes") - (set_attr "type" "f_cvt")] -@@ -786,7 +975,7 @@ - (define_insn "*floatsidf2_vfp" - [(set (match_operand:DF 0 "s_register_operand" "=w") - (float:DF (match_operand:SI 1 "s_register_operand" "t")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "fsitod%?\\t%P0, %1" - [(set_attr "predicable" "yes") - (set_attr "type" "f_cvt")] -@@ -805,7 +994,7 @@ - (define_insn "floatunssidf2" - [(set (match_operand:DF 0 "s_register_operand" "=w") - (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "t")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "fuitod%?\\t%P0, %1" - [(set_attr "predicable" "yes") - (set_attr "type" "f_cvt")] -@@ -826,7 +1015,7 @@ - (define_insn "*sqrtdf2_vfp" - [(set (match_operand:DF 0 "s_register_operand" "=w") - (sqrt:DF (match_operand:DF 1 "s_register_operand" "w")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "fsqrtd%?\\t%P0, %P1" - [(set_attr "predicable" "yes") - (set_attr "type" "fdivd")] -@@ -878,9 +1067,9 @@ - [(set (reg:CCFP CC_REGNUM) - (compare:CCFP (match_operand:DF 0 "s_register_operand" "w") - (match_operand:DF 1 "vfp_compare_operand" "wG")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "#" -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - [(set (reg:CCFP VFPCC_REGNUM) - (compare:CCFP (match_dup 0) - (match_dup 1))) -@@ -893,9 +1082,9 @@ - [(set (reg:CCFPE CC_REGNUM) - (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w") - (match_operand:DF 1 "vfp_compare_operand" "wG")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "#" -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - [(set (reg:CCFPE VFPCC_REGNUM) - (compare:CCFPE (match_dup 0) - (match_dup 1))) -@@ -935,7 +1124,7 @@ - [(set (reg:CCFP VFPCC_REGNUM) - (compare:CCFP (match_operand:DF 0 "s_register_operand" "w,w") - (match_operand:DF 1 "vfp_compare_operand" "w,G")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "@ - fcmpd%?\\t%P0, %P1 - fcmpzd%?\\t%P0" -@@ -947,7 +1136,7 @@ - [(set (reg:CCFPE VFPCC_REGNUM) - (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w,w") - (match_operand:DF 1 "vfp_compare_operand" "w,G")))] -- "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" -+ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" - "@ - fcmped%?\\t%P0, %P1 - fcmpezd%?\\t%P0" ---- /dev/null -+++ b/gcc/config/i386/atom.md -@@ -0,0 +1,795 @@ -+;; Atom Scheduling -+;; Copyright (C) 2009 Free Software Foundation, Inc. -+;; -+;; This file is part of GCC. -+;; -+;; GCC is free software; you can redistribute it and/or modify -+;; it under the terms of the GNU General Public License as published by -+;; the Free Software Foundation; either version 3, or (at your option) -+;; any later version. -+;; -+;; GCC is distributed in the hope that it will be useful, -+;; but WITHOUT ANY WARRANTY; without even the implied warranty of -+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+;; GNU General Public License for more details. -+;; -+;; You should have received a copy of the GNU General Public License -+;; along with GCC; see the file COPYING3. If not see -+;; <http://www.gnu.org/licenses/>. -+;; -+;; Atom is an in-order core with two integer pipelines. -+ -+ -+(define_attr "atom_unit" "sishuf,simul,jeu,complex,other" -+ (const_string "other")) -+ -+(define_attr "atom_sse_attr" "rcp,movdup,lfence,fence,prefetch,sqrt,mxcsr,other" -+ (const_string "other")) -+ -+(define_automaton "atom") -+ -+;; Atom has two ports: port 0 and port 1 connecting to all execution units -+(define_cpu_unit "atom-port-0,atom-port-1" "atom") -+ -+;; EU: Execution Unit -+;; Atom EUs are connected by port 0 or port 1. -+ -+(define_cpu_unit "atom-eu-0, atom-eu-1, -+ atom-imul-1, atom-imul-2, atom-imul-3, atom-imul-4" -+ "atom") -+ -+;; Some EUs have duplicated copied and can be accessed via either -+;; port 0 or port 1 -+;; (define_reservation "atom-port-either" "(atom-port-0 | atom-port-1)") -+ -+;;; Some instructions is dual-pipe execution, need both ports -+;;; Complex multi-op macro-instructoins need both ports and all EUs -+(define_reservation "atom-port-dual" "(atom-port-0 + atom-port-1)") -+(define_reservation "atom-all-eu" "(atom-eu-0 + atom-eu-1 + -+ atom-imul-1 + atom-imul-2 + atom-imul-3 + -+ atom-imul-4)") -+ -+;;; Most of simple instructions have 1 cycle latency. Some of them -+;;; issue in port 0, some in port 0 and some in either port. -+(define_reservation "atom-simple-0" "(atom-port-0 + atom-eu-0)") -+(define_reservation "atom-simple-1" "(atom-port-1 + atom-eu-1)") -+(define_reservation "atom-simple-either" "(atom-simple-0 | atom-simple-1)") -+ -+;;; Some insn issues in port 0 with 3 cycle latency and 1 cycle tput -+(define_reservation "atom-eu-0-3-1" "(atom-port-0 + atom-eu-0, nothing*2)") -+ -+;;; fmul insn can have 4 or 5 cycles latency -+(define_reservation "atom-fmul-5c" "(atom-port-0 + atom-eu-0), nothing*4") -+(define_reservation "atom-fmul-4c" "(atom-port-0 + atom-eu-0), nothing*3") -+ -+;;; fadd can has 5 cycles latency depends on instruction forms -+(define_reservation "atom-fadd-5c" "(atom-port-1 + atom-eu-1), nothing*5") -+ -+;;; imul insn has 5 cycles latency -+(define_reservation "atom-imul-32" -+ "atom-imul-1, atom-imul-2, atom-imul-3, atom-imul-4, -+ atom-port-0") -+;;; imul instruction excludes other non-FP instructions. -+(exclusion_set "atom-eu-0, atom-eu-1" -+ "atom-imul-1, atom-imul-2, atom-imul-3, atom-imul-4") -+ -+;;; dual-execution instructions can have 1,2,4,5 cycles latency depends on -+;;; instruction forms -+(define_reservation "atom-dual-1c" "(atom-port-dual + atom-eu-0 + atom-eu-1)") -+(define_reservation "atom-dual-2c" -+ "(atom-port-dual + atom-eu-0 + atom-eu-1, nothing)") -+(define_reservation "atom-dual-5c" -+ "(atom-port-dual + atom-eu-0 + atom-eu-1, nothing*4)") -+ -+;;; Complex macro-instruction has variants of latency, and uses both ports. -+(define_reservation "atom-complex" "(atom-port-dual + atom-all-eu)") -+ -+(define_insn_reservation "atom_other" 9 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "other") -+ (eq_attr "atom_unit" "!jeu"))) -+ "atom-complex, atom-all-eu*8") -+ -+;; return has type "other" with atom_unit "jeu" -+(define_insn_reservation "atom_other_2" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "other") -+ (eq_attr "atom_unit" "jeu"))) -+ "atom-dual-1c") -+ -+(define_insn_reservation "atom_multi" 9 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "multi")) -+ "atom-complex, atom-all-eu*8") -+ -+;; Normal alu insns without carry -+(define_insn_reservation "atom_alu" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "alu") -+ (and (eq_attr "memory" "none") -+ (eq_attr "use_carry" "0")))) -+ "atom-simple-either") -+ -+;; Normal alu insns without carry -+(define_insn_reservation "atom_alu_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "alu") -+ (and (eq_attr "memory" "!none") -+ (eq_attr "use_carry" "0")))) -+ "atom-simple-either") -+ -+;; Alu insn consuming CF, such as add/sbb -+(define_insn_reservation "atom_alu_carry" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "alu") -+ (and (eq_attr "memory" "none") -+ (eq_attr "use_carry" "1")))) -+ "atom-simple-either") -+ -+;; Alu insn consuming CF, such as add/sbb -+(define_insn_reservation "atom_alu_carry_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "alu") -+ (and (eq_attr "memory" "!none") -+ (eq_attr "use_carry" "1")))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_alu1" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "alu1") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_alu1_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "alu1") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_negnot" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "negnot") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_negnot_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "negnot") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_imov" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imov") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_imov_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imov") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+;; 16<-16, 32<-32 -+(define_insn_reservation "atom_imovx" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imovx") -+ (and (eq_attr "memory" "none") -+ (ior (and (match_operand:HI 0 "register_operand") -+ (match_operand:HI 1 "general_operand")) -+ (and (match_operand:SI 0 "register_operand") -+ (match_operand:SI 1 "general_operand")))))) -+ "atom-simple-either") -+ -+;; 16<-16, 32<-32, mem -+(define_insn_reservation "atom_imovx_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imovx") -+ (and (eq_attr "memory" "!none") -+ (ior (and (match_operand:HI 0 "register_operand") -+ (match_operand:HI 1 "general_operand")) -+ (and (match_operand:SI 0 "register_operand") -+ (match_operand:SI 1 "general_operand")))))) -+ "atom-simple-either") -+ -+;; 32<-16, 32<-8, 64<-16, 64<-8, 64<-32, 8<-8 -+(define_insn_reservation "atom_imovx_2" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imovx") -+ (and (eq_attr "memory" "none") -+ (ior (match_operand:QI 0 "register_operand") -+ (ior (and (match_operand:SI 0 "register_operand") -+ (not (match_operand:SI 1 "general_operand"))) -+ (match_operand:DI 0 "register_operand")))))) -+ "atom-simple-0") -+ -+;; 32<-16, 32<-8, 64<-16, 64<-8, 64<-32, 8<-8, mem -+(define_insn_reservation "atom_imovx_2_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imovx") -+ (and (eq_attr "memory" "!none") -+ (ior (match_operand:QI 0 "register_operand") -+ (ior (and (match_operand:SI 0 "register_operand") -+ (not (match_operand:SI 1 "general_operand"))) -+ (match_operand:DI 0 "register_operand")))))) -+ "atom-simple-0") -+ -+;; 16<-8 -+(define_insn_reservation "atom_imovx_3" 3 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imovx") -+ (and (match_operand:HI 0 "register_operand") -+ (match_operand:QI 1 "general_operand")))) -+ "atom-complex, atom-all-eu*2") -+ -+(define_insn_reservation "atom_lea" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "lea") -+ (eq_attr "mode" "!HI"))) -+ "atom-simple-either") -+ -+;; lea 16bit address is complex insn -+(define_insn_reservation "atom_lea_2" 2 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "lea") -+ (eq_attr "mode" "HI"))) -+ "atom-complex, atom-all-eu") -+ -+(define_insn_reservation "atom_incdec" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "incdec") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_incdec_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "incdec") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+;; simple shift instruction use SHIFT eu, none memory -+(define_insn_reservation "atom_ishift" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ishift") -+ (and (eq_attr "memory" "none") (eq_attr "prefix_0f" "0")))) -+ "atom-simple-0") -+ -+;; simple shift instruction use SHIFT eu, memory -+(define_insn_reservation "atom_ishift_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ishift") -+ (and (eq_attr "memory" "!none") (eq_attr "prefix_0f" "0")))) -+ "atom-simple-0") -+ -+;; DF shift (prefixed with 0f) is complex insn with latency of 7 cycles -+(define_insn_reservation "atom_ishift_3" 7 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ishift") -+ (eq_attr "prefix_0f" "1"))) -+ "atom-complex, atom-all-eu*6") -+ -+(define_insn_reservation "atom_ishift1" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ishift1") -+ (eq_attr "memory" "none"))) -+ "atom-simple-0") -+ -+(define_insn_reservation "atom_ishift1_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ishift1") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-0") -+ -+(define_insn_reservation "atom_rotate" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "rotate") -+ (eq_attr "memory" "none"))) -+ "atom-simple-0") -+ -+(define_insn_reservation "atom_rotate_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "rotate") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-0") -+ -+(define_insn_reservation "atom_rotate1" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "rotate1") -+ (eq_attr "memory" "none"))) -+ "atom-simple-0") -+ -+(define_insn_reservation "atom_rotate1_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "rotate1") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-0") -+ -+(define_insn_reservation "atom_imul" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imul") -+ (and (eq_attr "memory" "none") (eq_attr "mode" "SI")))) -+ "atom-imul-32") -+ -+(define_insn_reservation "atom_imul_mem" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imul") -+ (and (eq_attr "memory" "!none") (eq_attr "mode" "SI")))) -+ "atom-imul-32") -+ -+;; latency set to 10 as common 64x64 imul -+(define_insn_reservation "atom_imul_3" 10 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imul") -+ (eq_attr "mode" "!SI"))) -+ "atom-complex, atom-all-eu*9") -+ -+(define_insn_reservation "atom_idiv" 65 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "idiv")) -+ "atom-complex, atom-all-eu*32, nothing*32") -+ -+(define_insn_reservation "atom_icmp" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "icmp") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_icmp_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "icmp") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_test" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "test") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_test_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "test") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_ibr" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ibr") -+ (eq_attr "memory" "!load"))) -+ "atom-simple-1") -+ -+;; complex if jump target is from address -+(define_insn_reservation "atom_ibr_2" 2 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ibr") -+ (eq_attr "memory" "load"))) -+ "atom-complex, atom-all-eu") -+ -+(define_insn_reservation "atom_setcc" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "setcc") -+ (eq_attr "memory" "!store"))) -+ "atom-simple-either") -+ -+;; 2 cycles complex if target is in memory -+(define_insn_reservation "atom_setcc_2" 2 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "setcc") -+ (eq_attr "memory" "store"))) -+ "atom-complex, atom-all-eu") -+ -+(define_insn_reservation "atom_icmov" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "icmov") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_icmov_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "icmov") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+;; UCODE if segreg, ignored -+(define_insn_reservation "atom_push" 2 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "push")) -+ "atom-dual-2c") -+ -+;; pop r64 is 1 cycle. UCODE if segreg, ignored -+(define_insn_reservation "atom_pop" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "pop") -+ (eq_attr "mode" "DI"))) -+ "atom-dual-1c") -+ -+;; pop non-r64 is 2 cycles. UCODE if segreg, ignored -+(define_insn_reservation "atom_pop_2" 2 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "pop") -+ (eq_attr "mode" "!DI"))) -+ "atom-dual-2c") -+ -+;; UCODE if segreg, ignored -+(define_insn_reservation "atom_call" 1 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "call")) -+ "atom-dual-1c") -+ -+(define_insn_reservation "atom_callv" 1 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "callv")) -+ "atom-dual-1c") -+ -+(define_insn_reservation "atom_leave" 3 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "leave")) -+ "atom-complex, atom-all-eu*2") -+ -+(define_insn_reservation "atom_str" 3 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "str")) -+ "atom-complex, atom-all-eu*2") -+ -+(define_insn_reservation "atom_sselog" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sselog") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_sselog_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sselog") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_sselog1" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sselog1") -+ (eq_attr "memory" "none"))) -+ "atom-simple-0") -+ -+(define_insn_reservation "atom_sselog1_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sselog1") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-0") -+ -+;; not pmad, not psad -+(define_insn_reservation "atom_sseiadd" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseiadd") -+ (and (not (match_operand:V2DI 0 "register_operand")) -+ (and (eq_attr "atom_unit" "!simul") -+ (eq_attr "atom_unit" "!complex"))))) -+ "atom-simple-either") -+ -+;; pmad, psad and 64 -+(define_insn_reservation "atom_sseiadd_2" 4 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseiadd") -+ (and (not (match_operand:V2DI 0 "register_operand")) -+ (and (eq_attr "atom_unit" "simul" ) -+ (eq_attr "mode" "DI"))))) -+ "atom-fmul-4c") -+ -+;; pmad, psad and 128 -+(define_insn_reservation "atom_sseiadd_3" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseiadd") -+ (and (not (match_operand:V2DI 0 "register_operand")) -+ (and (eq_attr "atom_unit" "simul" ) -+ (eq_attr "mode" "TI"))))) -+ "atom-fmul-5c") -+ -+;; if paddq(64 bit op), phadd/phsub -+(define_insn_reservation "atom_sseiadd_4" 6 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseiadd") -+ (ior (match_operand:V2DI 0 "register_operand") -+ (eq_attr "atom_unit" "complex")))) -+ "atom-complex, atom-all-eu*5") -+ -+;; if immediate op. -+(define_insn_reservation "atom_sseishft" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseishft") -+ (and (eq_attr "atom_unit" "!sishuf") -+ (match_operand 2 "immediate_operand")))) -+ "atom-simple-either") -+ -+;; if palignr or psrldq -+(define_insn_reservation "atom_sseishft_2" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseishft") -+ (and (eq_attr "atom_unit" "sishuf") -+ (match_operand 2 "immediate_operand")))) -+ "atom-simple-0") -+ -+;; if reg/mem op -+(define_insn_reservation "atom_sseishft_3" 2 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseishft") -+ (not (match_operand 2 "immediate_operand")))) -+ "atom-complex, atom-all-eu") -+ -+(define_insn_reservation "atom_sseimul" 1 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "sseimul")) -+ "atom-simple-0") -+ -+;; rcpss or rsqrtss -+(define_insn_reservation "atom_sse" 4 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sse") -+ (and (eq_attr "atom_sse_attr" "rcp") (eq_attr "mode" "SF")))) -+ "atom-fmul-4c") -+ -+;; movshdup, movsldup. Suggest to type sseishft -+(define_insn_reservation "atom_sse_2" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sse") -+ (eq_attr "atom_sse_attr" "movdup"))) -+ "atom-simple-0") -+ -+;; lfence -+(define_insn_reservation "atom_sse_3" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sse") -+ (eq_attr "atom_sse_attr" "lfence"))) -+ "atom-simple-either") -+ -+;; sfence,clflush,mfence, prefetch -+(define_insn_reservation "atom_sse_4" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sse") -+ (ior (eq_attr "atom_sse_attr" "fence") -+ (eq_attr "atom_sse_attr" "prefetch")))) -+ "atom-simple-0") -+ -+;; rcpps, rsqrtss, sqrt, ldmxcsr -+(define_insn_reservation "atom_sse_5" 7 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sse") -+ (ior (ior (eq_attr "atom_sse_attr" "sqrt") -+ (eq_attr "atom_sse_attr" "mxcsr")) -+ (and (eq_attr "atom_sse_attr" "rcp") -+ (eq_attr "mode" "V4SF"))))) -+ "atom-complex, atom-all-eu*6") -+ -+;; xmm->xmm -+(define_insn_reservation "atom_ssemov" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssemov") -+ (and (match_operand 0 "register_operand" "xy") (match_operand 1 "register_operand" "xy")))) -+ "atom-simple-either") -+ -+;; reg->xmm -+(define_insn_reservation "atom_ssemov_2" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssemov") -+ (and (match_operand 0 "register_operand" "xy") (match_operand 1 "register_operand" "r")))) -+ "atom-simple-0") -+ -+;; xmm->reg -+(define_insn_reservation "atom_ssemov_3" 3 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssemov") -+ (and (match_operand 0 "register_operand" "r") (match_operand 1 "register_operand" "xy")))) -+ "atom-eu-0-3-1") -+ -+;; mov mem -+(define_insn_reservation "atom_ssemov_4" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssemov") -+ (and (eq_attr "movu" "0") (eq_attr "memory" "!none")))) -+ "atom-simple-0") -+ -+;; movu mem -+(define_insn_reservation "atom_ssemov_5" 2 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssemov") -+ (ior (eq_attr "movu" "1") (eq_attr "memory" "!none")))) -+ "atom-complex, atom-all-eu") -+ -+;; no memory simple -+(define_insn_reservation "atom_sseadd" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseadd") -+ (and (eq_attr "memory" "none") -+ (and (eq_attr "mode" "!V2DF") -+ (eq_attr "atom_unit" "!complex"))))) -+ "atom-fadd-5c") -+ -+;; memory simple -+(define_insn_reservation "atom_sseadd_mem" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseadd") -+ (and (eq_attr "memory" "!none") -+ (and (eq_attr "mode" "!V2DF") -+ (eq_attr "atom_unit" "!complex"))))) -+ "atom-dual-5c") -+ -+;; maxps, minps, *pd, hadd, hsub -+(define_insn_reservation "atom_sseadd_3" 8 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseadd") -+ (ior (eq_attr "mode" "V2DF") (eq_attr "atom_unit" "complex")))) -+ "atom-complex, atom-all-eu*7") -+ -+;; Except dppd/dpps -+(define_insn_reservation "atom_ssemul" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssemul") -+ (eq_attr "mode" "!SF"))) -+ "atom-fmul-5c") -+ -+;; Except dppd/dpps, 4 cycle if mulss -+(define_insn_reservation "atom_ssemul_2" 4 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssemul") -+ (eq_attr "mode" "SF"))) -+ "atom-fmul-4c") -+ -+(define_insn_reservation "atom_ssecmp" 1 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "ssecmp")) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_ssecomi" 10 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "ssecomi")) -+ "atom-complex, atom-all-eu*9") -+ -+;; no memory and cvtpi2ps, cvtps2pi, cvttps2pi -+(define_insn_reservation "atom_ssecvt" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssecvt") -+ (ior (and (match_operand:V2SI 0 "register_operand") -+ (match_operand:V4SF 1 "register_operand")) -+ (and (match_operand:V4SF 0 "register_operand") -+ (match_operand:V2SI 1 "register_operand"))))) -+ "atom-fadd-5c") -+ -+;; memory and cvtpi2ps, cvtps2pi, cvttps2pi -+(define_insn_reservation "atom_ssecvt_2" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssecvt") -+ (ior (and (match_operand:V2SI 0 "register_operand") -+ (match_operand:V4SF 1 "memory_operand")) -+ (and (match_operand:V4SF 0 "register_operand") -+ (match_operand:V2SI 1 "memory_operand"))))) -+ "atom-dual-5c") -+ -+;; otherwise. 7 cycles average for cvtss2sd -+(define_insn_reservation "atom_ssecvt_3" 7 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssecvt") -+ (not (ior (and (match_operand:V2SI 0 "register_operand") -+ (match_operand:V4SF 1 "nonimmediate_operand")) -+ (and (match_operand:V4SF 0 "register_operand") -+ (match_operand:V2SI 1 "nonimmediate_operand")))))) -+ "atom-complex, atom-all-eu*6") -+ -+;; memory and cvtsi2sd -+(define_insn_reservation "atom_sseicvt" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseicvt") -+ (and (match_operand:V2DF 0 "register_operand") -+ (match_operand:SI 1 "memory_operand")))) -+ "atom-dual-5c") -+ -+;; otherwise. 8 cycles average for cvtsd2si -+(define_insn_reservation "atom_sseicvt_2" 8 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseicvt") -+ (not (and (match_operand:V2DF 0 "register_operand") -+ (match_operand:SI 1 "memory_operand"))))) -+ "atom-complex, atom-all-eu*7") -+ -+(define_insn_reservation "atom_ssediv" 62 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "ssediv")) -+ "atom-complex, atom-all-eu*12, nothing*49") -+ -+;; simple for fmov -+(define_insn_reservation "atom_fmov" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "fmov") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+;; simple for fmov -+(define_insn_reservation "atom_fmov_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "fmov") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+;; Define bypass here -+ -+;; There will be no stall from lea to non-mem EX insns -+(define_bypass 0 "atom_lea" -+ "atom_alu_carry, -+ atom_alu,atom_alu1,atom_negnot,atom_imov,atom_imovx, -+ atom_incdec, atom_setcc, atom_icmov, atom_pop") -+ -+(define_bypass 0 "atom_lea" -+ "atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem, -+ atom_imovx_mem, atom_imovx_2_mem, -+ atom_imov_mem, atom_icmov_mem, atom_fmov_mem" -+ "!ix86_agi_dependent") -+ -+;; There will be 3 cycles stall from EX insns to AGAN insns LEA -+(define_bypass 4 "atom_alu_carry, -+ atom_alu,atom_alu1,atom_negnot,atom_imov,atom_imovx, -+ atom_incdec,atom_ishift,atom_ishift1,atom_rotate, -+ atom_rotate1, atom_setcc, atom_icmov, atom_pop, -+ atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem, -+ atom_imovx_mem, atom_imovx_2_mem, -+ atom_imov_mem, atom_icmov_mem, atom_fmov_mem" -+ "atom_lea") -+ -+;; There will be 3 cycles stall from EX insns to insns need addr calculation -+(define_bypass 4 "atom_alu_carry, -+ atom_alu,atom_alu1,atom_negnot,atom_imov,atom_imovx, -+ atom_incdec,atom_ishift,atom_ishift1,atom_rotate, -+ atom_rotate1, atom_setcc, atom_icmov, atom_pop, -+ atom_imovx_mem, atom_imovx_2_mem, -+ atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem, -+ atom_imov_mem, atom_icmov_mem, atom_fmov_mem" -+ "atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem, -+ atom_negnot_mem, atom_imov_mem, atom_incdec_mem, -+ atom_imovx_mem, atom_imovx_2_mem, -+ atom_imul_mem, atom_icmp_mem, -+ atom_test_mem, atom_icmov_mem, atom_sselog_mem, -+ atom_sselog1_mem, atom_fmov_mem, atom_sseadd_mem, -+ atom_ishift_mem, atom_ishift1_mem, -+ atom_rotate_mem, atom_rotate1_mem" -+ "ix86_agi_dependent") -+ -+;; Stall from imul to lea is 8 cycles. -+(define_bypass 9 "atom_imul, atom_imul_mem" "atom_lea") -+ -+;; Stall from imul to memory address is 8 cycles. -+(define_bypass 9 "atom_imul, atom_imul_mem" -+ "atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem, -+ atom_negnot_mem, atom_imov_mem, atom_incdec_mem, -+ atom_ishift_mem, atom_ishift1_mem, atom_rotate_mem, -+ atom_rotate1_mem, atom_imul_mem, atom_icmp_mem, -+ atom_test_mem, atom_icmov_mem, atom_sselog_mem, -+ atom_sselog1_mem, atom_fmov_mem, atom_sseadd_mem" -+ "ix86_agi_dependent") -+ -+;; There will be 0 cycle stall from cmp/test to jcc -+ -+;; There will be 1 cycle stall from flag producer to cmov and adc/sbb -+(define_bypass 2 "atom_icmp, atom_test, atom_alu, atom_alu_carry, -+ atom_alu1, atom_negnot, atom_incdec, atom_ishift, -+ atom_ishift1, atom_rotate, atom_rotate1" -+ "atom_icmov, atom_alu_carry") -+ -+;; lea to shift count stall is 2 cycles -+(define_bypass 3 "atom_lea" -+ "atom_ishift, atom_ishift1, atom_rotate, atom_rotate1, -+ atom_ishift_mem, atom_ishift1_mem, -+ atom_rotate_mem, atom_rotate1_mem" -+ "ix86_dep_by_shift_count") -+ -+;; lea to shift source stall is 1 cycle -+(define_bypass 2 "atom_lea" -+ "atom_ishift, atom_ishift1, atom_rotate, atom_rotate1" -+ "!ix86_dep_by_shift_count") -+ -+;; non-lea to shift count stall is 1 cycle -+(define_bypass 2 "atom_alu_carry, -+ atom_alu,atom_alu1,atom_negnot,atom_imov,atom_imovx, -+ atom_incdec,atom_ishift,atom_ishift1,atom_rotate, -+ atom_rotate1, atom_setcc, atom_icmov, atom_pop, -+ atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem, -+ atom_imovx_mem, atom_imovx_2_mem, -+ atom_imov_mem, atom_icmov_mem, atom_fmov_mem" -+ "atom_ishift, atom_ishift1, atom_rotate, atom_rotate1, -+ atom_ishift_mem, atom_ishift1_mem, -+ atom_rotate_mem, atom_rotate1_mem" -+ "ix86_dep_by_shift_count") ---- a/gcc/config/i386/cpuid.h -+++ b/gcc/config/i386/cpuid.h -@@ -29,6 +29,7 @@ - #define bit_CMPXCHG16B (1 << 13) - #define bit_SSE4_1 (1 << 19) - #define bit_SSE4_2 (1 << 20) -+#define bit_MOVBE (1 << 22) - #define bit_POPCNT (1 << 23) - #define bit_AES (1 << 25) - #define bit_XSAVE (1 << 26) ---- a/gcc/config/i386/cygming.h -+++ b/gcc/config/i386/cygming.h -@@ -34,7 +34,7 @@ - #endif - - #undef TARGET_64BIT_MS_ABI --#define TARGET_64BIT_MS_ABI (!cfun ? DEFAULT_ABI == MS_ABI : TARGET_64BIT && cfun->machine->call_abi == MS_ABI) -+#define TARGET_64BIT_MS_ABI (!cfun ? ix86_abi == MS_ABI : TARGET_64BIT && cfun->machine->call_abi == MS_ABI) - - #undef DEFAULT_ABI - #define DEFAULT_ABI (TARGET_64BIT ? MS_ABI : SYSV_ABI) -@@ -203,7 +203,7 @@ - #define CHECK_STACK_LIMIT 4000 - - #undef STACK_BOUNDARY --#define STACK_BOUNDARY (DEFAULT_ABI == MS_ABI ? 128 : BITS_PER_WORD) -+#define STACK_BOUNDARY (ix86_abi == MS_ABI ? 128 : BITS_PER_WORD) - - /* By default, target has a 80387, uses IEEE compatible arithmetic, - returns float values in the 387 and needs stack probes. ---- a/gcc/config/i386/cygming.opt -+++ b/gcc/config/i386/cygming.opt -@@ -45,3 +45,7 @@ - mwindows - Target - Create GUI application -+ -+mpe-aligned-commons -+Target Var(use_pe_aligned_common) Init(HAVE_GAS_ALIGNED_COMM) -+Use the GNU extension to the PE format for aligned common data ---- a/gcc/config/i386/driver-i386.c -+++ b/gcc/config/i386/driver-i386.c -@@ -378,7 +378,7 @@ - /* Extended features */ - unsigned int has_lahf_lm = 0, has_sse4a = 0; - unsigned int has_longmode = 0, has_3dnowp = 0, has_3dnow = 0; -- unsigned int has_sse4_1 = 0, has_sse4_2 = 0; -+ unsigned int has_movbe = 0, has_sse4_1 = 0, has_sse4_2 = 0; - unsigned int has_popcnt = 0, has_aes = 0, has_avx = 0; - unsigned int has_pclmul = 0; - -@@ -398,9 +398,22 @@ - - __cpuid (1, eax, ebx, ecx, edx); - -- /* We don't care for extended family. */ - model = (eax >> 4) & 0x0f; - family = (eax >> 8) & 0x0f; -+ if (vendor == SIG_INTEL) -+ { -+ unsigned int extended_model, extended_family; -+ -+ extended_model = (eax >> 12) & 0xf0; -+ extended_family = (eax >> 20) & 0xff; -+ if (family == 0x0f) -+ { -+ family += extended_family; -+ model += extended_model; -+ } -+ else if (family == 0x06) -+ model += extended_model; -+ } - - has_sse3 = ecx & bit_SSE3; - has_ssse3 = ecx & bit_SSSE3; -@@ -408,6 +421,7 @@ - has_sse4_2 = ecx & bit_SSE4_2; - has_avx = ecx & bit_AVX; - has_cmpxchg16b = ecx & bit_CMPXCHG16B; -+ has_movbe = ecx & bit_MOVBE; - has_popcnt = ecx & bit_POPCNT; - has_aes = ecx & bit_AES; - has_pclmul = ecx & bit_PCLMUL; -@@ -505,8 +519,8 @@ - break; - case PROCESSOR_PENTIUMPRO: - if (has_longmode) -- /* It is Core 2 Duo. */ -- cpu = "core2"; -+ /* It is Core 2 or Atom. */ -+ cpu = (model == 28) ? "atom" : "core2"; - else if (arch) - { - if (has_sse3) -@@ -597,6 +611,8 @@ - options = concat (options, "-mcx16 ", NULL); - if (has_lahf_lm) - options = concat (options, "-msahf ", NULL); -+ if (has_movbe) -+ options = concat (options, "-mmovbe ", NULL); - if (has_aes) - options = concat (options, "-maes ", NULL); - if (has_pclmul) ---- a/gcc/config/i386/i386.c -+++ b/gcc/config/i386/i386.c -@@ -1036,6 +1036,79 @@ - 1, /* cond_not_taken_branch_cost. */ - }; - -+static const -+struct processor_costs atom_cost = { -+ COSTS_N_INSNS (1), /* cost of an add instruction */ -+ COSTS_N_INSNS (1) + 1, /* cost of a lea instruction */ -+ COSTS_N_INSNS (1), /* variable shift costs */ -+ COSTS_N_INSNS (1), /* constant shift costs */ -+ {COSTS_N_INSNS (3), /* cost of starting multiply for QI */ -+ COSTS_N_INSNS (4), /* HI */ -+ COSTS_N_INSNS (3), /* SI */ -+ COSTS_N_INSNS (4), /* DI */ -+ COSTS_N_INSNS (2)}, /* other */ -+ 0, /* cost of multiply per each bit set */ -+ {COSTS_N_INSNS (18), /* cost of a divide/mod for QI */ -+ COSTS_N_INSNS (26), /* HI */ -+ COSTS_N_INSNS (42), /* SI */ -+ COSTS_N_INSNS (74), /* DI */ -+ COSTS_N_INSNS (74)}, /* other */ -+ COSTS_N_INSNS (1), /* cost of movsx */ -+ COSTS_N_INSNS (1), /* cost of movzx */ -+ 8, /* "large" insn */ -+ 17, /* MOVE_RATIO */ -+ 2, /* cost for loading QImode using movzbl */ -+ {4, 4, 4}, /* cost of loading integer registers -+ in QImode, HImode and SImode. -+ Relative to reg-reg move (2). */ -+ {4, 4, 4}, /* cost of storing integer registers */ -+ 4, /* cost of reg,reg fld/fst */ -+ {12, 12, 12}, /* cost of loading fp registers -+ in SFmode, DFmode and XFmode */ -+ {6, 6, 8}, /* cost of storing fp registers -+ in SFmode, DFmode and XFmode */ -+ 2, /* cost of moving MMX register */ -+ {8, 8}, /* cost of loading MMX registers -+ in SImode and DImode */ -+ {8, 8}, /* cost of storing MMX registers -+ in SImode and DImode */ -+ 2, /* cost of moving SSE register */ -+ {8, 8, 8}, /* cost of loading SSE registers -+ in SImode, DImode and TImode */ -+ {8, 8, 8}, /* cost of storing SSE registers -+ in SImode, DImode and TImode */ -+ 5, /* MMX or SSE register to integer */ -+ 32, /* size of l1 cache. */ -+ 256, /* size of l2 cache. */ -+ 64, /* size of prefetch block */ -+ 6, /* number of parallel prefetches */ -+ 3, /* Branch cost */ -+ COSTS_N_INSNS (8), /* cost of FADD and FSUB insns. */ -+ COSTS_N_INSNS (8), /* cost of FMUL instruction. */ -+ COSTS_N_INSNS (20), /* cost of FDIV instruction. */ -+ COSTS_N_INSNS (8), /* cost of FABS instruction. */ -+ COSTS_N_INSNS (8), /* cost of FCHS instruction. */ -+ COSTS_N_INSNS (40), /* cost of FSQRT instruction. */ -+ {{libcall, {{11, loop}, {-1, rep_prefix_4_byte}}}, -+ {libcall, {{32, loop}, {64, rep_prefix_4_byte}, -+ {8192, rep_prefix_8_byte}, {-1, libcall}}}}, -+ {{libcall, {{8, loop}, {15, unrolled_loop}, -+ {2048, rep_prefix_4_byte}, {-1, libcall}}}, -+ {libcall, {{24, loop}, {32, unrolled_loop}, -+ {8192, rep_prefix_8_byte}, {-1, libcall}}}}, -+ 1, /* scalar_stmt_cost. */ -+ 1, /* scalar load_cost. */ -+ 1, /* scalar_store_cost. */ -+ 1, /* vec_stmt_cost. */ -+ 1, /* vec_to_scalar_cost. */ -+ 1, /* scalar_to_vec_cost. */ -+ 1, /* vec_align_load_cost. */ -+ 2, /* vec_unalign_load_cost. */ -+ 1, /* vec_store_cost. */ -+ 3, /* cond_taken_branch_cost. */ -+ 1, /* cond_not_taken_branch_cost. */ -+}; -+ - /* Generic64 should produce code tuned for Nocona and K8. */ - static const - struct processor_costs generic64_cost = { -@@ -1194,6 +1267,7 @@ - #define m_PENT4 (1<<PROCESSOR_PENTIUM4) - #define m_NOCONA (1<<PROCESSOR_NOCONA) - #define m_CORE2 (1<<PROCESSOR_CORE2) -+#define m_ATOM (1<<PROCESSOR_ATOM) - - #define m_GEODE (1<<PROCESSOR_GEODE) - #define m_K6 (1<<PROCESSOR_K6) -@@ -1231,10 +1305,11 @@ - m_486 | m_PENT, - - /* X86_TUNE_UNROLL_STRLEN */ -- m_486 | m_PENT | m_PPRO | m_AMD_MULTIPLE | m_K6 | m_CORE2 | m_GENERIC, -+ m_486 | m_PENT | m_ATOM | m_PPRO | m_AMD_MULTIPLE | m_K6 -+ | m_CORE2 | m_GENERIC, - - /* X86_TUNE_DEEP_BRANCH_PREDICTION */ -- m_PPRO | m_K6_GEODE | m_AMD_MULTIPLE | m_PENT4 | m_GENERIC, -+ m_ATOM | m_PPRO | m_K6_GEODE | m_AMD_MULTIPLE | m_PENT4 | m_GENERIC, - - /* X86_TUNE_BRANCH_PREDICTION_HINTS: Branch hints were put in P4 based - on simulation result. But after P4 was made, no performance benefit -@@ -1246,12 +1321,12 @@ - ~m_386, - - /* X86_TUNE_USE_SAHF */ -- m_PPRO | m_K6_GEODE | m_K8 | m_AMDFAM10 | m_PENT4 -+ m_ATOM | m_PPRO | m_K6_GEODE | m_K8 | m_AMDFAM10 | m_PENT4 - | m_NOCONA | m_CORE2 | m_GENERIC, - - /* X86_TUNE_MOVX: Enable to zero extend integer registers to avoid - partial dependencies. */ -- m_AMD_MULTIPLE | m_PPRO | m_PENT4 | m_NOCONA -+ m_AMD_MULTIPLE | m_ATOM | m_PPRO | m_PENT4 | m_NOCONA - | m_CORE2 | m_GENERIC | m_GEODE /* m_386 | m_K6 */, - - /* X86_TUNE_PARTIAL_REG_STALL: We probably ought to watch for partial -@@ -1271,13 +1346,13 @@ - m_386 | m_486 | m_K6_GEODE, - - /* X86_TUNE_USE_SIMODE_FIOP */ -- ~(m_PPRO | m_AMD_MULTIPLE | m_PENT | m_CORE2 | m_GENERIC), -+ ~(m_PPRO | m_AMD_MULTIPLE | m_PENT | m_ATOM | m_CORE2 | m_GENERIC), - - /* X86_TUNE_USE_MOV0 */ - m_K6, - - /* X86_TUNE_USE_CLTD */ -- ~(m_PENT | m_K6 | m_CORE2 | m_GENERIC), -+ ~(m_PENT | m_ATOM | m_K6 | m_CORE2 | m_GENERIC), - - /* X86_TUNE_USE_XCHGB: Use xchgb %rh,%rl instead of rolw/rorw $8,rx. */ - m_PENT4, -@@ -1292,8 +1367,8 @@ - ~(m_PENT | m_PPRO), - - /* X86_TUNE_PROMOTE_QIMODE */ -- m_K6_GEODE | m_PENT | m_386 | m_486 | m_AMD_MULTIPLE | m_CORE2 -- | m_GENERIC /* | m_PENT4 ? */, -+ m_K6_GEODE | m_PENT | m_ATOM | m_386 | m_486 | m_AMD_MULTIPLE -+ | m_CORE2 | m_GENERIC /* | m_PENT4 ? */, - - /* X86_TUNE_FAST_PREFIX */ - ~(m_PENT | m_486 | m_386), -@@ -1317,26 +1392,28 @@ - m_PPRO, - - /* X86_TUNE_ADD_ESP_4: Enable if add/sub is preferred over 1/2 push/pop. */ -- m_AMD_MULTIPLE | m_K6_GEODE | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC, -+ m_ATOM | m_AMD_MULTIPLE | m_K6_GEODE | m_PENT4 | m_NOCONA -+ | m_CORE2 | m_GENERIC, - - /* X86_TUNE_ADD_ESP_8 */ -- m_AMD_MULTIPLE | m_PPRO | m_K6_GEODE | m_386 -+ m_AMD_MULTIPLE | m_ATOM | m_PPRO | m_K6_GEODE | m_386 - | m_486 | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC, - - /* X86_TUNE_SUB_ESP_4 */ -- m_AMD_MULTIPLE | m_PPRO | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC, -+ m_AMD_MULTIPLE | m_ATOM | m_PPRO | m_PENT4 | m_NOCONA | m_CORE2 -+ | m_GENERIC, - - /* X86_TUNE_SUB_ESP_8 */ -- m_AMD_MULTIPLE | m_PPRO | m_386 | m_486 -+ m_AMD_MULTIPLE | m_ATOM | m_PPRO | m_386 | m_486 - | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC, - - /* X86_TUNE_INTEGER_DFMODE_MOVES: Enable if integer moves are preferred - for DFmode copies */ -- ~(m_AMD_MULTIPLE | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2 -+ ~(m_AMD_MULTIPLE | m_ATOM | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2 - | m_GENERIC | m_GEODE), - - /* X86_TUNE_PARTIAL_REG_DEPENDENCY */ -- m_AMD_MULTIPLE | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC, -+ m_AMD_MULTIPLE | m_ATOM | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC, - - /* X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY: In the Generic model we have a - conflict here in between PPro/Pentium4 based chips that thread 128bit -@@ -1347,7 +1424,8 @@ - shows that disabling this option on P4 brings over 20% SPECfp regression, - while enabling it on K8 brings roughly 2.4% regression that can be partly - masked by careful scheduling of moves. */ -- m_PENT4 | m_NOCONA | m_PPRO | m_CORE2 | m_GENERIC | m_AMDFAM10, -+ m_ATOM | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2 | m_GENERIC -+ | m_AMDFAM10, - - /* X86_TUNE_SSE_UNALIGNED_MOVE_OPTIMAL */ - m_AMDFAM10, -@@ -1365,13 +1443,13 @@ - m_PPRO | m_PENT4 | m_NOCONA, - - /* X86_TUNE_MEMORY_MISMATCH_STALL */ -- m_AMD_MULTIPLE | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC, -+ m_AMD_MULTIPLE | m_ATOM | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC, - - /* X86_TUNE_PROLOGUE_USING_MOVE */ -- m_ATHLON_K8 | m_PPRO | m_CORE2 | m_GENERIC, -+ m_ATHLON_K8 | m_ATOM | m_PPRO | m_CORE2 | m_GENERIC, - - /* X86_TUNE_EPILOGUE_USING_MOVE */ -- m_ATHLON_K8 | m_PPRO | m_CORE2 | m_GENERIC, -+ m_ATHLON_K8 | m_ATOM | m_PPRO | m_CORE2 | m_GENERIC, - - /* X86_TUNE_SHIFT1 */ - ~m_486, -@@ -1380,29 +1458,32 @@ - m_AMD_MULTIPLE, - - /* X86_TUNE_INTER_UNIT_MOVES */ -- ~(m_AMD_MULTIPLE | m_GENERIC), -+ ~(m_AMD_MULTIPLE | m_ATOM | m_GENERIC), - - /* X86_TUNE_INTER_UNIT_CONVERSIONS */ - ~(m_AMDFAM10), - - /* X86_TUNE_FOUR_JUMP_LIMIT: Some CPU cores are not able to predict more - than 4 branch instructions in the 16 byte window. */ -- m_PPRO | m_AMD_MULTIPLE | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC, -+ m_ATOM | m_PPRO | m_AMD_MULTIPLE | m_PENT4 | m_NOCONA | m_CORE2 -+ | m_GENERIC, - - /* X86_TUNE_SCHEDULE */ -- m_PPRO | m_AMD_MULTIPLE | m_K6_GEODE | m_PENT | m_CORE2 | m_GENERIC, -+ m_PPRO | m_AMD_MULTIPLE | m_K6_GEODE | m_PENT | m_ATOM | m_CORE2 -+ | m_GENERIC, - - /* X86_TUNE_USE_BT */ -- m_AMD_MULTIPLE | m_CORE2 | m_GENERIC, -+ m_AMD_MULTIPLE | m_ATOM | m_CORE2 | m_GENERIC, - - /* X86_TUNE_USE_INCDEC */ -- ~(m_PENT4 | m_NOCONA | m_GENERIC), -+ ~(m_PENT4 | m_NOCONA | m_GENERIC | m_ATOM), - - /* X86_TUNE_PAD_RETURNS */ - m_AMD_MULTIPLE | m_CORE2 | m_GENERIC, - - /* X86_TUNE_EXT_80387_CONSTANTS */ -- m_K6_GEODE | m_ATHLON_K8 | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2 | m_GENERIC, -+ m_K6_GEODE | m_ATHLON_K8 | m_ATOM | m_PENT4 | m_NOCONA | m_PPRO -+ | m_CORE2 | m_GENERIC, - - /* X86_TUNE_SHORTEN_X87_SSE */ - ~m_K8, -@@ -1447,6 +1528,10 @@ - with a subsequent conditional jump instruction into a single - compare-and-branch uop. */ - m_CORE2, -+ -+ /* X86_TUNE_OPT_AGU: Optimize for Address Generation Unit. This flag -+ will impact LEA instruction selection. */ -+ m_ATOM, - }; - - /* Feature tests against the various architecture variations. */ -@@ -1472,10 +1557,11 @@ - }; - - static const unsigned int x86_accumulate_outgoing_args -- = m_AMD_MULTIPLE | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2 | m_GENERIC; -+ = m_AMD_MULTIPLE | m_ATOM | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2 -+ | m_GENERIC; - - static const unsigned int x86_arch_always_fancy_math_387 -- = m_PENT | m_PPRO | m_AMD_MULTIPLE | m_PENT4 -+ = m_PENT | m_ATOM | m_PPRO | m_AMD_MULTIPLE | m_PENT4 - | m_NOCONA | m_CORE2 | m_GENERIC; - - static enum stringop_alg stringop_alg = no_stringop; -@@ -1743,6 +1829,9 @@ - /* Alignment for incoming stack boundary in bits. */ - unsigned int ix86_incoming_stack_boundary; - -+/* The abi used by target. */ -+enum calling_abi ix86_abi; -+ - /* Values 1-5: see jump.c */ - int ix86_branch_cost; - -@@ -1819,6 +1908,8 @@ - static bool ix86_can_inline_p (tree, tree); - static void ix86_set_current_function (tree); - -+static enum calling_abi ix86_function_abi (const_tree); -+ - - /* The svr4 ABI for the i386 says that records and unions are returned - in memory. */ -@@ -1877,9 +1968,11 @@ - - #define OPTION_MASK_ISA_ABM_SET \ - (OPTION_MASK_ISA_ABM | OPTION_MASK_ISA_POPCNT) -+ - #define OPTION_MASK_ISA_POPCNT_SET OPTION_MASK_ISA_POPCNT - #define OPTION_MASK_ISA_CX16_SET OPTION_MASK_ISA_CX16 - #define OPTION_MASK_ISA_SAHF_SET OPTION_MASK_ISA_SAHF -+#define OPTION_MASK_ISA_MOVBE_SET OPTION_MASK_ISA_MOVBE - - /* Define a set of ISAs which aren't available when a given ISA is - disabled. MMX and SSE ISAs are handled separately. */ -@@ -1921,6 +2014,7 @@ - #define OPTION_MASK_ISA_POPCNT_UNSET OPTION_MASK_ISA_POPCNT - #define OPTION_MASK_ISA_CX16_UNSET OPTION_MASK_ISA_CX16 - #define OPTION_MASK_ISA_SAHF_UNSET OPTION_MASK_ISA_SAHF -+#define OPTION_MASK_ISA_MOVBE_UNSET OPTION_MASK_ISA_MOVBE - - /* Vectorization library interface and handlers. */ - tree (*ix86_veclib_handler)(enum built_in_function, tree, tree) = NULL; -@@ -1953,7 +2047,8 @@ - {&core2_cost, 16, 10, 16, 10, 16}, - {&generic32_cost, 16, 7, 16, 7, 16}, - {&generic64_cost, 16, 10, 16, 10, 16}, -- {&amdfam10_cost, 32, 24, 32, 7, 32} -+ {&amdfam10_cost, 32, 24, 32, 7, 32}, -+ {&atom_cost, 16, 7, 16, 7, 16} - }; - - static const char *const cpu_names[TARGET_CPU_DEFAULT_max] = -@@ -1971,6 +2066,7 @@ - "prescott", - "nocona", - "core2", -+ "atom", - "geode", - "k6", - "k6-2", -@@ -2209,6 +2305,19 @@ - } - return true; - -+ case OPT_mmovbe: -+ if (value) -+ { -+ ix86_isa_flags |= OPTION_MASK_ISA_MOVBE_SET; -+ ix86_isa_flags_explicit |= OPTION_MASK_ISA_MOVBE_SET; -+ } -+ else -+ { -+ ix86_isa_flags &= ~OPTION_MASK_ISA_MOVBE_UNSET; -+ ix86_isa_flags_explicit |= OPTION_MASK_ISA_MOVBE_UNSET; -+ } -+ return true; -+ - case OPT_maes: - if (value) - { -@@ -2271,6 +2380,7 @@ - { "-mmmx", OPTION_MASK_ISA_MMX }, - { "-mabm", OPTION_MASK_ISA_ABM }, - { "-mpopcnt", OPTION_MASK_ISA_POPCNT }, -+ { "-mmovbe", OPTION_MASK_ISA_MOVBE }, - { "-maes", OPTION_MASK_ISA_AES }, - { "-mpclmul", OPTION_MASK_ISA_PCLMUL }, - }; -@@ -2487,7 +2597,8 @@ - PTA_AES = 1 << 17, - PTA_PCLMUL = 1 << 18, - PTA_AVX = 1 << 19, -- PTA_FMA = 1 << 20 -+ PTA_FMA = 1 << 20, -+ PTA_MOVBE = 1 << 21 - }; - - static struct pta -@@ -2529,6 +2640,9 @@ - {"core2", PROCESSOR_CORE2, CPU_CORE2, - PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 - | PTA_SSSE3 | PTA_CX16}, -+ {"atom", PROCESSOR_ATOM, CPU_ATOM, -+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 -+ | PTA_SSSE3 | PTA_CX16 | PTA_MOVBE}, - {"geode", PROCESSOR_GEODE, CPU_GEODE, - PTA_MMX | PTA_3DNOW | PTA_3DNOW_A |PTA_PREFETCH_SSE}, - {"k6", PROCESSOR_K6, CPU_K6, PTA_MMX}, -@@ -2716,6 +2830,20 @@ - error ("bad value (%s) for %sarch=%s %s", - ix86_arch_string, prefix, suffix, sw); - -+ /* Validate -mabi= value. */ -+ if (ix86_abi_string) -+ { -+ if (strcmp (ix86_abi_string, "sysv") == 0) -+ ix86_abi = SYSV_ABI; -+ else if (strcmp (ix86_abi_string, "ms") == 0) -+ ix86_abi = MS_ABI; -+ else -+ error ("unknown ABI (%s) for %sabi=%s %s", -+ ix86_abi_string, prefix, suffix, sw); -+ } -+ else -+ ix86_abi = DEFAULT_ABI; -+ - if (ix86_cmodel_string != 0) - { - if (!strcmp (ix86_cmodel_string, "small")) -@@ -2828,6 +2956,9 @@ - if (!(TARGET_64BIT && (processor_alias_table[i].flags & PTA_NO_SAHF)) - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SAHF)) - ix86_isa_flags |= OPTION_MASK_ISA_SAHF; -+ if (processor_alias_table[i].flags & PTA_MOVBE -+ && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_MOVBE)) -+ ix86_isa_flags |= OPTION_MASK_ISA_MOVBE; - if (processor_alias_table[i].flags & PTA_AES - && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AES)) - ix86_isa_flags |= OPTION_MASK_ISA_AES; -@@ -4592,14 +4723,14 @@ - default ABI. */ - - /* RAX is used as hidden argument to va_arg functions. */ -- if (DEFAULT_ABI == SYSV_ABI && regno == AX_REG) -+ if (ix86_abi == SYSV_ABI && regno == AX_REG) - return true; - -- if (DEFAULT_ABI == MS_ABI) -+ if (ix86_abi == MS_ABI) - parm_regs = x86_64_ms_abi_int_parameter_registers; - else - parm_regs = x86_64_int_parameter_registers; -- for (i = 0; i < (DEFAULT_ABI == MS_ABI ? X64_REGPARM_MAX -+ for (i = 0; i < (ix86_abi == MS_ABI ? X64_REGPARM_MAX - : X86_64_REGPARM_MAX); i++) - if (regno == parm_regs[i]) - return true; -@@ -4627,7 +4758,7 @@ - int - ix86_reg_parm_stack_space (const_tree fndecl) - { -- int call_abi = SYSV_ABI; -+ enum calling_abi call_abi = SYSV_ABI; - if (fndecl != NULL_TREE && TREE_CODE (fndecl) == FUNCTION_DECL) - call_abi = ix86_function_abi (fndecl); - else -@@ -4639,37 +4770,39 @@ - - /* Returns value SYSV_ABI, MS_ABI dependent on fntype, specifying the - call abi used. */ --int -+enum calling_abi - ix86_function_type_abi (const_tree fntype) - { - if (TARGET_64BIT && fntype != NULL) - { -- int abi; -- if (DEFAULT_ABI == SYSV_ABI) -- abi = lookup_attribute ("ms_abi", TYPE_ATTRIBUTES (fntype)) ? MS_ABI : SYSV_ABI; -- else -- abi = lookup_attribute ("sysv_abi", TYPE_ATTRIBUTES (fntype)) ? SYSV_ABI : MS_ABI; -- -+ enum calling_abi abi = ix86_abi; -+ if (abi == SYSV_ABI) -+ { -+ if (lookup_attribute ("ms_abi", TYPE_ATTRIBUTES (fntype))) -+ abi = MS_ABI; -+ } -+ else if (lookup_attribute ("sysv_abi", TYPE_ATTRIBUTES (fntype))) -+ abi = SYSV_ABI; - return abi; - } -- return DEFAULT_ABI; -+ return ix86_abi; - } - --int -+static enum calling_abi - ix86_function_abi (const_tree fndecl) - { - if (! fndecl) -- return DEFAULT_ABI; -+ return ix86_abi; - return ix86_function_type_abi (TREE_TYPE (fndecl)); - } - - /* Returns value SYSV_ABI, MS_ABI dependent on cfun, specifying the - call abi used. */ --int -+enum calling_abi - ix86_cfun_abi (void) - { - if (! cfun || ! TARGET_64BIT) -- return DEFAULT_ABI; -+ return ix86_abi; - return cfun->machine->call_abi; - } - -@@ -4683,7 +4816,7 @@ - ix86_call_abi_override (const_tree fndecl) - { - if (fndecl == NULL_TREE) -- cfun->machine->call_abi = DEFAULT_ABI; -+ cfun->machine->call_abi = ix86_abi; - else - cfun->machine->call_abi = ix86_function_type_abi (TREE_TYPE (fndecl)); - } -@@ -4724,8 +4857,8 @@ - cum->nregs = ix86_regparm; - if (TARGET_64BIT) - { -- if (cum->call_abi != DEFAULT_ABI) -- cum->nregs = DEFAULT_ABI != SYSV_ABI ? X86_64_REGPARM_MAX -+ if (cum->call_abi != ix86_abi) -+ cum->nregs = ix86_abi != SYSV_ABI ? X86_64_REGPARM_MAX - : X64_REGPARM_MAX; - } - if (TARGET_SSE) -@@ -4733,8 +4866,8 @@ - cum->sse_nregs = SSE_REGPARM_MAX; - if (TARGET_64BIT) - { -- if (cum->call_abi != DEFAULT_ABI) -- cum->sse_nregs = DEFAULT_ABI != SYSV_ABI ? X86_64_SSE_REGPARM_MAX -+ if (cum->call_abi != ix86_abi) -+ cum->sse_nregs = ix86_abi != SYSV_ABI ? X86_64_SSE_REGPARM_MAX - : X64_SSE_REGPARM_MAX; - } - } -@@ -5700,7 +5833,7 @@ - if (type) - mode = type_natural_mode (type, NULL); - -- if (TARGET_64BIT && (cum ? cum->call_abi : DEFAULT_ABI) == MS_ABI) -+ if (TARGET_64BIT && (cum ? cum->call_abi : ix86_abi) == MS_ABI) - function_arg_advance_ms_64 (cum, bytes, words); - else if (TARGET_64BIT) - function_arg_advance_64 (cum, mode, type, words, named); -@@ -5846,9 +5979,9 @@ - if (mode == VOIDmode) - return GEN_INT (cum->maybe_vaarg - ? (cum->sse_nregs < 0 -- ? (cum->call_abi == DEFAULT_ABI -+ ? (cum->call_abi == ix86_abi - ? SSE_REGPARM_MAX -- : (DEFAULT_ABI != SYSV_ABI ? X86_64_SSE_REGPARM_MAX -+ : (ix86_abi != SYSV_ABI ? X86_64_SSE_REGPARM_MAX - : X64_SSE_REGPARM_MAX)) - : cum->sse_regno) - : -1); -@@ -5942,7 +6075,7 @@ - if (type && TREE_CODE (type) == VECTOR_TYPE) - mode = type_natural_mode (type, cum); - -- if (TARGET_64BIT && (cum ? cum->call_abi : DEFAULT_ABI) == MS_ABI) -+ if (TARGET_64BIT && (cum ? cum->call_abi : ix86_abi) == MS_ABI) - return function_arg_ms_64 (cum, mode, omode, named, bytes); - else if (TARGET_64BIT) - return function_arg_64 (cum, mode, omode, type, named); -@@ -5962,7 +6095,7 @@ - const_tree type, bool named ATTRIBUTE_UNUSED) - { - /* See Windows x64 Software Convention. */ -- if (TARGET_64BIT && (cum ? cum->call_abi : DEFAULT_ABI) == MS_ABI) -+ if (TARGET_64BIT && (cum ? cum->call_abi : ix86_abi) == MS_ABI) - { - int msize = (int) GET_MODE_SIZE (mode); - if (type) -@@ -6102,7 +6235,7 @@ - /* TODO: The function should depend on current function ABI but - builtins.c would need updating then. Therefore we use the - default ABI. */ -- if (TARGET_64BIT && DEFAULT_ABI == MS_ABI) -+ if (TARGET_64BIT && ix86_abi == MS_ABI) - return false; - return TARGET_FLOAT_RETURNS_IN_80387; - -@@ -6498,13 +6631,13 @@ - static tree - ix86_build_builtin_va_list (void) - { -- tree ret = ix86_build_builtin_va_list_abi (DEFAULT_ABI); -+ tree ret = ix86_build_builtin_va_list_abi (ix86_abi); - - /* Initialize abi specific va_list builtin types. */ - if (TARGET_64BIT) - { - tree t; -- if (DEFAULT_ABI == MS_ABI) -+ if (ix86_abi == MS_ABI) - { - t = ix86_build_builtin_va_list_abi (SYSV_ABI); - if (TREE_CODE (t) != RECORD_TYPE) -@@ -6518,7 +6651,7 @@ - t = build_variant_type_copy (t); - sysv_va_list_type_node = t; - } -- if (DEFAULT_ABI != MS_ABI) -+ if (ix86_abi != MS_ABI) - { - t = ix86_build_builtin_va_list_abi (MS_ABI); - if (TREE_CODE (t) != RECORD_TYPE) -@@ -6551,8 +6684,8 @@ - int i; - int regparm = ix86_regparm; - -- if (cum->call_abi != DEFAULT_ABI) -- regparm = DEFAULT_ABI != SYSV_ABI ? X86_64_REGPARM_MAX : X64_REGPARM_MAX; -+ if (cum->call_abi != ix86_abi) -+ regparm = ix86_abi != SYSV_ABI ? X86_64_REGPARM_MAX : X64_REGPARM_MAX; - - /* GPR size of varargs save area. */ - if (cfun->va_list_gpr_size) -@@ -6705,7 +6838,7 @@ - return true; - canonic = ix86_canonical_va_list_type (type); - return (canonic == ms_va_list_type_node -- || (DEFAULT_ABI == MS_ABI && canonic == va_list_type_node)); -+ || (ix86_abi == MS_ABI && canonic == va_list_type_node)); - } - - /* Implement va_start. */ -@@ -12987,6 +13120,316 @@ - emit_move_insn (operands[0], dst); - } - -+#define LEA_SEARCH_THRESHOLD 12 -+ -+/* Search backward for non-agu definition of register number REGNO1 -+ or register number REGNO2 in INSN's basic block until -+ 1. Pass LEA_SEARCH_THRESHOLD instructions, or -+ 2. Reach BB boundary, or -+ 3. Reach agu definition. -+ Returns the distance between the non-agu definition point and INSN. -+ If no definition point, returns -1. */ -+ -+static int -+distance_non_agu_define (unsigned int regno1, unsigned int regno2, -+ rtx insn) -+{ -+ basic_block bb = BLOCK_FOR_INSN (insn); -+ int distance = 0; -+ df_ref *def_rec; -+ enum attr_type insn_type; -+ -+ if (insn != BB_HEAD (bb)) -+ { -+ rtx prev = PREV_INSN (insn); -+ while (prev && distance < LEA_SEARCH_THRESHOLD) -+ { -+ if (INSN_P (prev)) -+ { -+ distance++; -+ for (def_rec = DF_INSN_DEFS (prev); *def_rec; def_rec++) -+ if (DF_REF_TYPE (*def_rec) == DF_REF_REG_DEF -+ && !DF_REF_IS_ARTIFICIAL (*def_rec) -+ && (regno1 == DF_REF_REGNO (*def_rec) -+ || regno2 == DF_REF_REGNO (*def_rec))) -+ { -+ insn_type = get_attr_type (prev); -+ if (insn_type != TYPE_LEA) -+ goto done; -+ } -+ } -+ if (prev == BB_HEAD (bb)) -+ break; -+ prev = PREV_INSN (prev); -+ } -+ } -+ -+ if (distance < LEA_SEARCH_THRESHOLD) -+ { -+ edge e; -+ edge_iterator ei; -+ bool simple_loop = false; -+ -+ FOR_EACH_EDGE (e, ei, bb->preds) -+ if (e->src == bb) -+ { -+ simple_loop = true; -+ break; -+ } -+ -+ if (simple_loop) -+ { -+ rtx prev = BB_END (bb); -+ while (prev -+ && prev != insn -+ && distance < LEA_SEARCH_THRESHOLD) -+ { -+ if (INSN_P (prev)) -+ { -+ distance++; -+ for (def_rec = DF_INSN_DEFS (prev); *def_rec; def_rec++) -+ if (DF_REF_TYPE (*def_rec) == DF_REF_REG_DEF -+ && !DF_REF_IS_ARTIFICIAL (*def_rec) -+ && (regno1 == DF_REF_REGNO (*def_rec) -+ || regno2 == DF_REF_REGNO (*def_rec))) -+ { -+ insn_type = get_attr_type (prev); -+ if (insn_type != TYPE_LEA) -+ goto done; -+ } -+ } -+ prev = PREV_INSN (prev); -+ } -+ } -+ } -+ -+ distance = -1; -+ -+done: -+ /* get_attr_type may modify recog data. We want to make sure -+ that recog data is valid for instruction INSN, on which -+ distance_non_agu_define is called. INSN is unchanged here. */ -+ extract_insn_cached (insn); -+ return distance; -+} -+ -+/* Return the distance between INSN and the next insn that uses -+ register number REGNO0 in memory address. Return -1 if no such -+ a use is found within LEA_SEARCH_THRESHOLD or REGNO0 is set. */ -+ -+static int -+distance_agu_use (unsigned int regno0, rtx insn) -+{ -+ basic_block bb = BLOCK_FOR_INSN (insn); -+ int distance = 0; -+ df_ref *def_rec; -+ df_ref *use_rec; -+ -+ if (insn != BB_END (bb)) -+ { -+ rtx next = NEXT_INSN (insn); -+ while (next && distance < LEA_SEARCH_THRESHOLD) -+ { -+ if (INSN_P (next)) -+ { -+ distance++; -+ -+ for (use_rec = DF_INSN_USES (next); *use_rec; use_rec++) -+ if ((DF_REF_TYPE (*use_rec) == DF_REF_REG_MEM_LOAD -+ || DF_REF_TYPE (*use_rec) == DF_REF_REG_MEM_STORE) -+ && regno0 == DF_REF_REGNO (*use_rec)) -+ { -+ /* Return DISTANCE if OP0 is used in memory -+ address in NEXT. */ -+ return distance; -+ } -+ -+ for (def_rec = DF_INSN_DEFS (next); *def_rec; def_rec++) -+ if (DF_REF_TYPE (*def_rec) == DF_REF_REG_DEF -+ && !DF_REF_IS_ARTIFICIAL (*def_rec) -+ && regno0 == DF_REF_REGNO (*def_rec)) -+ { -+ /* Return -1 if OP0 is set in NEXT. */ -+ return -1; -+ } -+ } -+ if (next == BB_END (bb)) -+ break; -+ next = NEXT_INSN (next); -+ } -+ } -+ -+ if (distance < LEA_SEARCH_THRESHOLD) -+ { -+ edge e; -+ edge_iterator ei; -+ bool simple_loop = false; -+ -+ FOR_EACH_EDGE (e, ei, bb->succs) -+ if (e->dest == bb) -+ { -+ simple_loop = true; -+ break; -+ } -+ -+ if (simple_loop) -+ { -+ rtx next = BB_HEAD (bb); -+ while (next -+ && next != insn -+ && distance < LEA_SEARCH_THRESHOLD) -+ { -+ if (INSN_P (next)) -+ { -+ distance++; -+ -+ for (use_rec = DF_INSN_USES (next); *use_rec; use_rec++) -+ if ((DF_REF_TYPE (*use_rec) == DF_REF_REG_MEM_LOAD -+ || DF_REF_TYPE (*use_rec) == DF_REF_REG_MEM_STORE) -+ && regno0 == DF_REF_REGNO (*use_rec)) -+ { -+ /* Return DISTANCE if OP0 is used in memory -+ address in NEXT. */ -+ return distance; -+ } -+ -+ for (def_rec = DF_INSN_DEFS (next); *def_rec; def_rec++) -+ if (DF_REF_TYPE (*def_rec) == DF_REF_REG_DEF -+ && !DF_REF_IS_ARTIFICIAL (*def_rec) -+ && regno0 == DF_REF_REGNO (*def_rec)) -+ { -+ /* Return -1 if OP0 is set in NEXT. */ -+ return -1; -+ } -+ -+ } -+ next = NEXT_INSN (next); -+ } -+ } -+ } -+ -+ return -1; -+} -+ -+/* Define this macro to tune LEA priority vs ADD, it take effect when -+ there is a dilemma of choicing LEA or ADD -+ Negative value: ADD is more preferred than LEA -+ Zero: Netrual -+ Positive value: LEA is more preferred than ADD*/ -+#define IX86_LEA_PRIORITY 2 -+ -+/* Return true if it is ok to optimize an ADD operation to LEA -+ operation to avoid flag register consumation. For the processors -+ like ATOM, if the destination register of LEA holds an actual -+ address which will be used soon, LEA is better and otherwise ADD -+ is better. */ -+ -+bool -+ix86_lea_for_add_ok (enum rtx_code code ATTRIBUTE_UNUSED, -+ rtx insn, rtx operands[]) -+{ -+ unsigned int regno0 = true_regnum (operands[0]); -+ unsigned int regno1 = true_regnum (operands[1]); -+ unsigned int regno2; -+ -+ if (!TARGET_OPT_AGU || optimize_function_for_size_p (cfun)) -+ return regno0 != regno1; -+ -+ regno2 = true_regnum (operands[2]); -+ -+ /* If a = b + c, (a!=b && a!=c), must use lea form. */ -+ if (regno0 != regno1 && regno0 != regno2) -+ return true; -+ else -+ { -+ int dist_define, dist_use; -+ dist_define = distance_non_agu_define (regno1, regno2, insn); -+ if (dist_define <= 0) -+ return true; -+ -+ /* If this insn has both backward non-agu dependence and forward -+ agu dependence, the one with short distance take effect. */ -+ dist_use = distance_agu_use (regno0, insn); -+ if (dist_use <= 0 -+ || (dist_define + IX86_LEA_PRIORITY) < dist_use) -+ return false; -+ -+ return true; -+ } -+} -+ -+/* Return true if destination reg of SET_BODY is shift count of -+ USE_BODY. */ -+ -+static bool -+ix86_dep_by_shift_count_body (const_rtx set_body, const_rtx use_body) -+{ -+ rtx set_dest; -+ rtx shift_rtx; -+ int i; -+ -+ /* Retrieve destination of SET_BODY. */ -+ switch (GET_CODE (set_body)) -+ { -+ case SET: -+ set_dest = SET_DEST (set_body); -+ if (!set_dest || !REG_P (set_dest)) -+ return false; -+ break; -+ case PARALLEL: -+ for (i = XVECLEN (set_body, 0) - 1; i >= 0; i--) -+ if (ix86_dep_by_shift_count_body (XVECEXP (set_body, 0, i), -+ use_body)) -+ return true; -+ default: -+ return false; -+ break; -+ } -+ -+ /* Retrieve shift count of USE_BODY. */ -+ switch (GET_CODE (use_body)) -+ { -+ case SET: -+ shift_rtx = XEXP (use_body, 1); -+ break; -+ case PARALLEL: -+ for (i = XVECLEN (use_body, 0) - 1; i >= 0; i--) -+ if (ix86_dep_by_shift_count_body (set_body, -+ XVECEXP (use_body, 0, i))) -+ return true; -+ default: -+ return false; -+ break; -+ } -+ -+ if (shift_rtx -+ && (GET_CODE (shift_rtx) == ASHIFT -+ || GET_CODE (shift_rtx) == LSHIFTRT -+ || GET_CODE (shift_rtx) == ASHIFTRT -+ || GET_CODE (shift_rtx) == ROTATE -+ || GET_CODE (shift_rtx) == ROTATERT)) -+ { -+ rtx shift_count = XEXP (shift_rtx, 1); -+ -+ /* Return true if shift count is dest of SET_BODY. */ -+ if (REG_P (shift_count) -+ && true_regnum (set_dest) == true_regnum (shift_count)) -+ return true; -+ } -+ -+ return false; -+} -+ -+/* Return true if destination reg of SET_INSN is shift count of -+ USE_INSN. */ -+ -+bool -+ix86_dep_by_shift_count (const_rtx set_insn, const_rtx use_insn) -+{ -+ return ix86_dep_by_shift_count_body (PATTERN (set_insn), -+ PATTERN (use_insn)); -+} -+ - /* Return TRUE or FALSE depending on whether the unary operator meets the - appropriate constraints. */ - -@@ -18838,7 +19281,7 @@ - f = GGC_CNEW (struct machine_function); - f->use_fast_prologue_epilogue_nregs = -1; - f->tls_descriptor_call_expanded_p = 0; -- f->call_abi = DEFAULT_ABI; -+ f->call_abi = ix86_abi; - - return f; - } -@@ -19099,6 +19542,7 @@ - switch (ix86_tune) - { - case PROCESSOR_PENTIUM: -+ case PROCESSOR_ATOM: - case PROCESSOR_K6: - return 2; - -@@ -19165,41 +19609,21 @@ - return 1; - } - --/* A subroutine of ix86_adjust_cost -- return true iff INSN has a memory -- address with operands set by DEP_INSN. */ -+/* Return true iff USE_INSN has a memory address with operands set by -+ SET_INSN. */ - --static int --ix86_agi_dependent (rtx insn, rtx dep_insn, enum attr_type insn_type) -+bool -+ix86_agi_dependent (rtx set_insn, rtx use_insn) - { -- rtx addr; -- -- if (insn_type == TYPE_LEA -- && TARGET_PENTIUM) -- { -- addr = PATTERN (insn); -- -- if (GET_CODE (addr) == PARALLEL) -- addr = XVECEXP (addr, 0, 0); -- -- gcc_assert (GET_CODE (addr) == SET); -- -- addr = SET_SRC (addr); -- } -- else -- { -- int i; -- extract_insn_cached (insn); -- for (i = recog_data.n_operands - 1; i >= 0; --i) -- if (MEM_P (recog_data.operand[i])) -- { -- addr = XEXP (recog_data.operand[i], 0); -- goto found; -- } -- return 0; -- found:; -- } -- -- return modified_in_p (addr, dep_insn); -+ int i; -+ extract_insn_cached (use_insn); -+ for (i = recog_data.n_operands - 1; i >= 0; --i) -+ if (MEM_P (recog_data.operand[i])) -+ { -+ rtx addr = XEXP (recog_data.operand[i], 0); -+ return modified_in_p (addr, set_insn) != 0; -+ } -+ return false; - } - - static int -@@ -19227,7 +19651,20 @@ - { - case PROCESSOR_PENTIUM: - /* Address Generation Interlock adds a cycle of latency. */ -- if (ix86_agi_dependent (insn, dep_insn, insn_type)) -+ if (insn_type == TYPE_LEA) -+ { -+ rtx addr = PATTERN (insn); -+ -+ if (GET_CODE (addr) == PARALLEL) -+ addr = XVECEXP (addr, 0, 0); -+ -+ gcc_assert (GET_CODE (addr) == SET); -+ -+ addr = SET_SRC (addr); -+ if (modified_in_p (addr, dep_insn)) -+ cost += 1; -+ } -+ else if (ix86_agi_dependent (dep_insn, insn)) - cost += 1; - - /* ??? Compares pair with jump/setcc. */ -@@ -19237,7 +19674,7 @@ - /* Floating point stores require value to be ready one cycle earlier. */ - if (insn_type == TYPE_FMOV - && get_attr_memory (insn) == MEMORY_STORE -- && !ix86_agi_dependent (insn, dep_insn, insn_type)) -+ && !ix86_agi_dependent (dep_insn, insn)) - cost += 1; - break; - -@@ -19260,7 +19697,7 @@ - in parallel with previous instruction in case - previous instruction is not needed to compute the address. */ - if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH) -- && !ix86_agi_dependent (insn, dep_insn, insn_type)) -+ && !ix86_agi_dependent (dep_insn, insn)) - { - /* Claim moves to take one cycle, as core can issue one load - at time and the next load can start cycle later. */ -@@ -19289,7 +19726,7 @@ - in parallel with previous instruction in case - previous instruction is not needed to compute the address. */ - if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH) -- && !ix86_agi_dependent (insn, dep_insn, insn_type)) -+ && !ix86_agi_dependent (dep_insn, insn)) - { - /* Claim moves to take one cycle, as core can issue one load - at time and the next load can start cycle later. */ -@@ -19306,6 +19743,7 @@ - case PROCESSOR_ATHLON: - case PROCESSOR_K8: - case PROCESSOR_AMDFAM10: -+ case PROCESSOR_ATOM: - case PROCESSOR_GENERIC32: - case PROCESSOR_GENERIC64: - memory = get_attr_memory (insn); -@@ -19314,7 +19752,7 @@ - in parallel with previous instruction in case - previous instruction is not needed to compute the address. */ - if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH) -- && !ix86_agi_dependent (insn, dep_insn, insn_type)) -+ && !ix86_agi_dependent (dep_insn, insn)) - { - enum attr_unit unit = get_attr_unit (insn); - int loadcost = 3; -@@ -29594,14 +30032,11 @@ - tree - ix86_fn_abi_va_list (tree fndecl) - { -- int abi; -- - if (!TARGET_64BIT) - return va_list_type_node; - gcc_assert (fndecl != NULL_TREE); -- abi = ix86_function_abi ((const_tree) fndecl); - -- if (abi == MS_ABI) -+ if (ix86_function_abi ((const_tree) fndecl) == MS_ABI) - return ms_va_list_type_node; - else - return sysv_va_list_type_node; ---- a/gcc/config/i386/i386-c.c -+++ b/gcc/config/i386/i386-c.c -@@ -119,6 +119,10 @@ - def_or_undef (parse_in, "__core2"); - def_or_undef (parse_in, "__core2__"); - break; -+ case PROCESSOR_ATOM: -+ def_or_undef (parse_in, "__atom"); -+ def_or_undef (parse_in, "__atom__"); -+ break; - /* use PROCESSOR_max to not set/unset the arch macro. */ - case PROCESSOR_max: - break; -@@ -187,6 +191,9 @@ - case PROCESSOR_CORE2: - def_or_undef (parse_in, "__tune_core2__"); - break; -+ case PROCESSOR_ATOM: -+ def_or_undef (parse_in, "__tune_atom__"); -+ break; - case PROCESSOR_GENERIC32: - case PROCESSOR_GENERIC64: - break; ---- a/gcc/config/i386/i386.h -+++ b/gcc/config/i386/i386.h -@@ -59,6 +59,7 @@ - #define TARGET_ABM OPTION_ISA_ABM - #define TARGET_POPCNT OPTION_ISA_POPCNT - #define TARGET_SAHF OPTION_ISA_SAHF -+#define TARGET_MOVBE OPTION_ISA_MOVBE - #define TARGET_AES OPTION_ISA_AES - #define TARGET_PCLMUL OPTION_ISA_PCLMUL - #define TARGET_CMPXCHG16B OPTION_ISA_CX16 -@@ -236,6 +237,7 @@ - #define TARGET_GENERIC64 (ix86_tune == PROCESSOR_GENERIC64) - #define TARGET_GENERIC (TARGET_GENERIC32 || TARGET_GENERIC64) - #define TARGET_AMDFAM10 (ix86_tune == PROCESSOR_AMDFAM10) -+#define TARGET_ATOM (ix86_tune == PROCESSOR_ATOM) - - /* Feature tests against the various tunings. */ - enum ix86_tune_indices { -@@ -300,6 +302,7 @@ - X86_TUNE_USE_VECTOR_FP_CONVERTS, - X86_TUNE_USE_VECTOR_CONVERTS, - X86_TUNE_FUSE_CMP_AND_BRANCH, -+ X86_TUNE_OPT_AGU, - - X86_TUNE_LAST - }; -@@ -387,6 +390,7 @@ - ix86_tune_features[X86_TUNE_USE_VECTOR_CONVERTS] - #define TARGET_FUSE_CMP_AND_BRANCH \ - ix86_tune_features[X86_TUNE_FUSE_CMP_AND_BRANCH] -+#define TARGET_OPT_AGU ix86_tune_features[X86_TUNE_OPT_AGU] - - /* Feature tests against the various architecture variations. */ - enum ix86_arch_indices { -@@ -470,7 +474,10 @@ - MS_ABI = 1 - }; - --/* The default abi form used by target. */ -+/* The abi used by target. */ -+extern enum calling_abi ix86_abi; -+ -+/* The default abi used by target. */ - #define DEFAULT_ABI SYSV_ABI - - /* Subtargets may reset this to 1 in order to enable 96-bit long double -@@ -569,6 +576,7 @@ - TARGET_CPU_DEFAULT_prescott, - TARGET_CPU_DEFAULT_nocona, - TARGET_CPU_DEFAULT_core2, -+ TARGET_CPU_DEFAULT_atom, - - TARGET_CPU_DEFAULT_geode, - TARGET_CPU_DEFAULT_k6, -@@ -658,7 +666,7 @@ - - /* Boundary (in *bits*) on which stack pointer should be aligned. */ - #define STACK_BOUNDARY \ -- (TARGET_64BIT && DEFAULT_ABI == MS_ABI ? 128 : BITS_PER_WORD) -+ (TARGET_64BIT && ix86_abi == MS_ABI ? 128 : BITS_PER_WORD) - - /* Stack boundary of the main function guaranteed by OS. */ - #define MAIN_STACK_BOUNDARY (TARGET_64BIT ? 128 : 32) -@@ -1584,7 +1592,7 @@ - int maybe_vaarg; /* true for calls to possibly vardic fncts. */ - int float_in_sse; /* 1 if in 32-bit mode SFmode (2 for DFmode) should - be passed in SSE registers. Otherwise 0. */ -- int call_abi; /* Set to SYSV_ABI for sysv abi. Otherwise -+ enum calling_abi call_abi; /* Set to SYSV_ABI for sysv abi. Otherwise - MS_ABI for ms abi. */ - } CUMULATIVE_ARGS; - -@@ -2230,6 +2238,7 @@ - PROCESSOR_GENERIC32, - PROCESSOR_GENERIC64, - PROCESSOR_AMDFAM10, -+ PROCESSOR_ATOM, - PROCESSOR_max - }; - -@@ -2403,7 +2412,7 @@ - int tls_descriptor_call_expanded_p; - /* This value is used for amd64 targets and specifies the current abi - to be used. MS_ABI means ms abi. Otherwise SYSV_ABI means sysv abi. */ -- int call_abi; -+ enum calling_abi call_abi; - }; - - #define ix86_stack_locals (cfun->machine->stack_locals) ---- a/gcc/config/i386/i386.md -+++ b/gcc/config/i386/i386.md -@@ -316,7 +316,7 @@ - - - ;; Processor type. --(define_attr "cpu" "none,pentium,pentiumpro,geode,k6,athlon,k8,core2, -+(define_attr "cpu" "none,pentium,pentiumpro,geode,k6,athlon,k8,core2,atom, - generic64,amdfam10" - (const (symbol_ref "ix86_schedule"))) - -@@ -612,6 +612,12 @@ - (define_attr "i387_cw" "trunc,floor,ceil,mask_pm,uninitialized,any" - (const_string "any")) - -+;; Define attribute to classify add/sub insns that consumes carry flag (CF) -+(define_attr "use_carry" "0,1" (const_string "0")) -+ -+;; Define attribute to indicate unaligned ssemov insns -+(define_attr "movu" "0,1" (const_string "0")) -+ - ;; Describe a user's asm statement. - (define_asm_attributes - [(set_attr "length" "128") -@@ -727,6 +733,7 @@ - (include "k6.md") - (include "athlon.md") - (include "geode.md") -+(include "atom.md") - - - ;; Operand and operator predicates and constraints -@@ -5790,6 +5797,7 @@ - "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)" - "adc{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "DI")]) - -@@ -5864,6 +5872,7 @@ - "ix86_binary_operator_ok (PLUS, QImode, operands)" - "adc{b}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "QI")]) - -@@ -5876,6 +5885,7 @@ - "ix86_binary_operator_ok (PLUS, HImode, operands)" - "adc{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "HI")]) - -@@ -5888,6 +5898,7 @@ - "ix86_binary_operator_ok (PLUS, SImode, operands)" - "adc{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "SI")]) - -@@ -5901,6 +5912,7 @@ - "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)" - "adc{l}\t{%2, %k0|%k0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "SI")]) - -@@ -6130,9 +6142,9 @@ - (set_attr "mode" "SI")]) - - (define_insn "*adddi_1_rex64" -- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r") -- (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r") -- (match_operand:DI 2 "x86_64_general_operand" "rme,re,le"))) -+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r") -+ (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r,r") -+ (match_operand:DI 2 "x86_64_general_operand" "rme,re,0,le"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)" - { -@@ -6153,6 +6165,10 @@ - } - - default: -+ /* Use add as much as possible to replace lea for AGU optimization. */ -+ if (which_alternative == 2 && TARGET_OPT_AGU) -+ return "add{q}\t{%1, %0|%0, %1}"; -+ - gcc_assert (rtx_equal_p (operands[0], operands[1])); - - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. -@@ -6171,8 +6187,11 @@ - } - } - [(set (attr "type") -- (cond [(eq_attr "alternative" "2") -+ (cond [(and (eq_attr "alternative" "2") -+ (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0))) - (const_string "lea") -+ (eq_attr "alternative" "3") -+ (const_string "lea") - ; Current assemblers are broken and do not allow @GOTOFF in - ; ought but a memory context. - (match_operand:DI 2 "pic_symbolic_operand" "") -@@ -6189,8 +6208,8 @@ - (plus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "x86_64_nonmemory_operand" ""))) - (clobber (reg:CC FLAGS_REG))] -- "TARGET_64BIT && reload_completed -- && true_regnum (operands[0]) != true_regnum (operands[1])" -+ "TARGET_64BIT && reload_completed -+ && ix86_lea_for_add_ok (PLUS, insn, operands)" - [(set (match_dup 0) - (plus:DI (match_dup 1) - (match_dup 2)))] -@@ -6394,9 +6413,9 @@ - - - (define_insn "*addsi_1" -- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r") -- (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r") -- (match_operand:SI 2 "general_operand" "g,ri,li"))) -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r,r") -+ (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r,r") -+ (match_operand:SI 2 "general_operand" "g,ri,0,li"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (PLUS, SImode, operands)" - { -@@ -6417,6 +6436,10 @@ - } - - default: -+ /* Use add as much as possible to replace lea for AGU optimization. */ -+ if (which_alternative == 2 && TARGET_OPT_AGU) -+ return "add{l}\t{%1, %0|%0, %1}"; -+ - gcc_assert (rtx_equal_p (operands[0], operands[1])); - - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. -@@ -6433,7 +6456,10 @@ - } - } - [(set (attr "type") -- (cond [(eq_attr "alternative" "2") -+ (cond [(and (eq_attr "alternative" "2") -+ (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0))) -+ (const_string "lea") -+ (eq_attr "alternative" "3") - (const_string "lea") - ; Current assemblers are broken and do not allow @GOTOFF in - ; ought but a memory context. -@@ -6451,8 +6477,7 @@ - (plus (match_operand 1 "register_operand" "") - (match_operand 2 "nonmemory_operand" ""))) - (clobber (reg:CC FLAGS_REG))] -- "reload_completed -- && true_regnum (operands[0]) != true_regnum (operands[1])" -+ "reload_completed && ix86_lea_for_add_ok (PLUS, insn, operands)" - [(const_int 0)] - { - rtx pat; -@@ -7553,6 +7578,7 @@ - "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)" - "sbb{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "DI")]) - -@@ -7601,6 +7627,7 @@ - "ix86_binary_operator_ok (MINUS, QImode, operands)" - "sbb{b}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "QI")]) - -@@ -7613,6 +7640,7 @@ - "ix86_binary_operator_ok (MINUS, HImode, operands)" - "sbb{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "HI")]) - -@@ -7625,6 +7653,7 @@ - "ix86_binary_operator_ok (MINUS, SImode, operands)" - "sbb{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "SI")]) - -@@ -15155,7 +15184,7 @@ - ? gen_rtx_REG (XCmode, FIRST_FLOAT_REG) : NULL), - operands[0], const0_rtx, - GEN_INT ((TARGET_64BIT -- ? (DEFAULT_ABI == SYSV_ABI -+ ? (ix86_abi == SYSV_ABI - ? X86_64_SSE_REGPARM_MAX - : X64_SSE_REGPARM_MAX) - : X86_32_SSE_REGPARM_MAX) -@@ -15235,6 +15264,7 @@ - "reload_completed" - "ret" - [(set_attr "length" "1") -+ (set_attr "atom_unit" "jeu") - (set_attr "length_immediate" "0") - (set_attr "modrm" "0")]) - -@@ -15247,6 +15277,7 @@ - "reload_completed" - "rep\;ret" - [(set_attr "length" "1") -+ (set_attr "atom_unit" "jeu") - (set_attr "length_immediate" "0") - (set_attr "prefix_rep" "1") - (set_attr "modrm" "0")]) -@@ -15257,6 +15288,7 @@ - "reload_completed" - "ret\t%0" - [(set_attr "length" "3") -+ (set_attr "atom_unit" "jeu") - (set_attr "length_immediate" "2") - (set_attr "modrm" "0")]) - -@@ -15610,7 +15642,7 @@ - (bswap:SI (match_operand:SI 1 "register_operand" "")))] - "" - { -- if (!TARGET_BSWAP) -+ if (!(TARGET_BSWAP || TARGET_MOVBE)) - { - rtx x = operands[0]; - -@@ -15622,6 +15654,21 @@ - } - }) - -+(define_insn "*bswapsi_movbe" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m") -+ (bswap:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,r")))] -+ "TARGET_MOVBE && !(MEM_P (operands[0]) && MEM_P (operands[1]))" -+ "@ -+ bswap\t%0 -+ movbe\t{%1, %0|%0, %1} -+ movbe\t{%1, %0|%0, %1}" -+ [(set_attr "type" "*,imov,imov") -+ (set_attr "modrm" "*,1,1") -+ (set_attr "prefix_0f" "1") -+ (set_attr "prefix_extra" "*,1,1") -+ (set_attr "length" "2,*,*") -+ (set_attr "mode" "SI")]) -+ - (define_insn "*bswapsi_1" - [(set (match_operand:SI 0 "register_operand" "=r") - (bswap:SI (match_operand:SI 1 "register_operand" "0")))] -@@ -15650,7 +15697,29 @@ - [(set_attr "length" "4") - (set_attr "mode" "HI")]) - --(define_insn "bswapdi2" -+(define_expand "bswapdi2" -+ [(set (match_operand:DI 0 "register_operand" "") -+ (bswap:DI (match_operand:DI 1 "register_operand" "")))] -+ "TARGET_64BIT" -+ "") -+ -+(define_insn "*bswapdi_movbe" -+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m") -+ (bswap:DI (match_operand:DI 1 "nonimmediate_operand" "0,m,r")))] -+ "TARGET_64BIT && TARGET_MOVBE -+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))" -+ "@ -+ bswap\t%0 -+ movbe\t{%1, %0|%0, %1} -+ movbe\t{%1, %0|%0, %1}" -+ [(set_attr "type" "*,imov,imov") -+ (set_attr "modrm" "*,1,1") -+ (set_attr "prefix_0f" "1") -+ (set_attr "prefix_extra" "*,1,1") -+ (set_attr "length" "3,*,*") -+ (set_attr "mode" "DI")]) -+ -+(define_insn "*bswapdi_1" - [(set (match_operand:DI 0 "register_operand" "=r") - (bswap:DI (match_operand:DI 1 "register_operand" "0")))] - "TARGET_64BIT" -@@ -16378,6 +16447,7 @@ - "TARGET_SSE_MATH" - "%vrcpss\t{%1, %d0|%d0, %1}" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "rcp") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "SF")]) - -@@ -16729,6 +16799,7 @@ - "TARGET_SSE_MATH" - "%vrsqrtss\t{%1, %d0|%d0, %1}" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "rcp") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "SF")]) - -@@ -16749,6 +16820,7 @@ - "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH" - "%vsqrts<ssemodefsuffix>\t{%1, %d0|%d0, %1}" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "sqrt") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "<MODE>") - (set_attr "athlon_decode" "*") -@@ -19802,6 +19874,7 @@ - ; Since we don't have the proper number of operands for an alu insn, - ; fill in all the blanks. - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "memory" "none") - (set_attr "imm_disp" "false") -@@ -19817,6 +19890,7 @@ - "" - "sbb{q}\t%0, %0" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "memory" "none") - (set_attr "imm_disp" "false") -@@ -19860,6 +19934,7 @@ - ; Since we don't have the proper number of operands for an alu insn, - ; fill in all the blanks. - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "memory" "none") - (set_attr "imm_disp" "false") -@@ -19875,6 +19950,7 @@ - "" - "sbb{l}\t%0, %0" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "memory" "none") - (set_attr "imm_disp" "false") -@@ -20207,7 +20283,8 @@ - } - } - [(set (attr "type") -- (cond [(eq_attr "alternative" "0") -+ (cond [(and (eq_attr "alternative" "0") -+ (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0))) - (const_string "alu") - (match_operand:SI 2 "const0_operand" "") - (const_string "imov") -@@ -20250,7 +20327,8 @@ - } - } - [(set (attr "type") -- (cond [(eq_attr "alternative" "0") -+ (cond [(and (eq_attr "alternative" "0") -+ (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0))) - (const_string "alu") - (match_operand:DI 2 "const0_operand" "") - (const_string "imov") -@@ -21734,6 +21812,7 @@ - return patterns[locality]; - } - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "prefetch") - (set_attr "memory" "none")]) - - (define_insn "*prefetch_sse_rex" -@@ -21752,6 +21831,7 @@ - return patterns[locality]; - } - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "prefetch") - (set_attr "memory" "none")]) - - (define_insn "*prefetch_3dnow" ---- a/gcc/config/i386/i386.opt -+++ b/gcc/config/i386/i386.opt -@@ -228,6 +228,10 @@ - Target RejectNegative Joined Var(ix86_tune_string) - Schedule code for given CPU - -+mabi= -+Target RejectNegative Joined Var(ix86_abi_string) -+Generate code that conforms to the given ABI -+ - mveclibabi= - Target RejectNegative Joined Var(ix86_veclibabi_string) - Vector library ABI to use -@@ -335,6 +339,10 @@ - Target Report Mask(ISA_SAHF) Var(ix86_isa_flags) VarExists Save - Support code generation of sahf instruction in 64bit x86-64 code. - -+mmovbe -+Target Report Mask(ISA_MOVBE) Var(ix86_isa_flags) VarExists Save -+Support code generation of movbe instruction. -+ - maes - Target Report Mask(ISA_AES) Var(ix86_isa_flags) VarExists Save - Support AES built-in functions and code generation ---- a/gcc/config/i386/i386-protos.h -+++ b/gcc/config/i386/i386-protos.h -@@ -86,6 +86,9 @@ - extern void ix86_expand_binary_operator (enum rtx_code, - enum machine_mode, rtx[]); - extern int ix86_binary_operator_ok (enum rtx_code, enum machine_mode, rtx[]); -+extern bool ix86_lea_for_add_ok (enum rtx_code, rtx, rtx[]); -+extern bool ix86_dep_by_shift_count (const_rtx set_insn, const_rtx use_insn); -+extern bool ix86_agi_dependent (rtx set_insn, rtx use_insn); - extern void ix86_expand_unary_operator (enum rtx_code, enum machine_mode, - rtx[]); - extern rtx ix86_build_const_vector (enum machine_mode, bool, rtx); -@@ -140,9 +143,8 @@ - extern bool ix86_sol10_return_in_memory (const_tree,const_tree); - extern rtx ix86_force_to_memory (enum machine_mode, rtx); - extern void ix86_free_from_memory (enum machine_mode); --extern int ix86_cfun_abi (void); --extern int ix86_function_abi (const_tree); --extern int ix86_function_type_abi (const_tree); -+extern enum calling_abi ix86_cfun_abi (void); -+extern enum calling_abi ix86_function_type_abi (const_tree); - extern void ix86_call_abi_override (const_tree); - extern tree ix86_fn_abi_va_list (tree); - extern tree ix86_canonical_va_list_type (tree); ---- a/gcc/config/i386/mingw32.h -+++ b/gcc/config/i386/mingw32.h -@@ -38,7 +38,7 @@ - builtin_define_std ("WINNT"); \ - builtin_define_with_int_value ("_INTEGRAL_MAX_BITS", \ - TYPE_PRECISION (intmax_type_node));\ -- if (TARGET_64BIT && DEFAULT_ABI == MS_ABI) \ -+ if (TARGET_64BIT && ix86_abi == MS_ABI) \ - { \ - builtin_define ("__MINGW64__"); \ - builtin_define_std ("WIN64"); \ ---- a/gcc/config/i386/sse.md -+++ b/gcc/config/i386/sse.md -@@ -338,6 +338,7 @@ - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "vmovup<avxmodesuffixf2c>\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") -+ (set_attr "movu" "1") - (set_attr "prefix" "vex") - (set_attr "mode" "<MODE>")]) - -@@ -363,6 +364,7 @@ - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "movup<ssemodesuffixf2c>\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") -+ (set_attr "movu" "1") - (set_attr "mode" "<MODE>")]) - - (define_insn "avx_movdqu<avxmodesuffix>" -@@ -373,6 +375,7 @@ - "TARGET_AVX && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "vmovdqu\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") -+ (set_attr "movu" "1") - (set_attr "prefix" "vex") - (set_attr "mode" "<avxvecmode>")]) - -@@ -383,6 +386,7 @@ - "TARGET_SSE2 && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "movdqu\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") -+ (set_attr "movu" "1") - (set_attr "prefix_data16" "1") - (set_attr "mode" "TI")]) - -@@ -424,7 +428,7 @@ - UNSPEC_MOVNT))] - "TARGET_SSE2" - "movntdq\t{%1, %0|%0, %1}" -- [(set_attr "type" "ssecvt") -+ [(set_attr "type" "ssemov") - (set_attr "prefix_data16" "1") - (set_attr "mode" "TI")]) - -@@ -434,7 +438,7 @@ - UNSPEC_MOVNT))] - "TARGET_SSE2" - "movnti\t{%1, %0|%0, %1}" -- [(set_attr "type" "ssecvt") -+ [(set_attr "type" "ssemov") - (set_attr "mode" "V2DF")]) - - (define_insn "avx_lddqu<avxmodesuffix>" -@@ -445,6 +449,7 @@ - "TARGET_AVX" - "vlddqu\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") -+ (set_attr "movu" "1") - (set_attr "prefix" "vex") - (set_attr "mode" "<avxvecmode>")]) - -@@ -454,7 +459,8 @@ - UNSPEC_LDDQU))] - "TARGET_SSE3" - "lddqu\t{%1, %0|%0, %1}" -- [(set_attr "type" "ssecvt") -+ [(set_attr "type" "ssemov") -+ (set_attr "movu" "1") - (set_attr "prefix_rep" "1") - (set_attr "mode" "TI")]) - -@@ -761,6 +767,7 @@ - "TARGET_SSE" - "%vrcpps\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "rcp") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "V4SF")]) - -@@ -787,6 +794,7 @@ - "TARGET_SSE" - "rcpss\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "rcp") - (set_attr "mode" "SF")]) - - (define_expand "sqrtv8sf2" -@@ -832,6 +840,7 @@ - "TARGET_SSE" - "%vsqrtps\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "sqrt") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "V4SF")]) - -@@ -876,6 +885,7 @@ - "SSE_VEC_FLOAT_MODE_P (<MODE>mode)" - "sqrts<ssemodesuffixf2c>\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "sqrt") - (set_attr "mode" "<ssescalarmode>")]) - - (define_expand "rsqrtv8sf2" -@@ -1039,7 +1049,7 @@ - (const_int 1)))] - "SSE_VEC_FLOAT_MODE_P (<MODE>mode)" - "<maxminfprefix>s<ssemodesuffixf2c>\t{%2, %0|%0, %2}" -- [(set_attr "type" "sse") -+ [(set_attr "type" "sseadd") - (set_attr "mode" "<ssescalarmode>")]) - - ;; These versions of the min/max patterns implement exactly the operations -@@ -1175,6 +1185,7 @@ - "TARGET_SSE3" - "addsubpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") -+ (set_attr "atom_unit" "complex") - (set_attr "mode" "V2DF")]) - - (define_insn "avx_h<plusminus_insn>v4df3" -@@ -1298,6 +1309,7 @@ - "TARGET_SSE3" - "h<plusminus_mnemonic>ps\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_rep" "1") - (set_attr "mode" "V4SF")]) - -@@ -5066,6 +5078,7 @@ - "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V8HImode, operands)" - "pmaddwd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "simul") - (set_attr "prefix_data16" "1") - (set_attr "mode" "TI")]) - -@@ -7025,6 +7038,7 @@ - movq\t{%H1, %0|%0, %H1} - mov{q}\t{%H1, %0|%0, %H1}" - [(set_attr "type" "ssemov,sseishft,ssemov,imov") -+ (set_attr "atom_unit" "*,sishuf,*,*") - (set_attr "memory" "*,none,*,*") - (set_attr "mode" "V2SF,TI,TI,DI")]) - -@@ -7057,6 +7071,7 @@ - psrldq\t{$8, %0|%0, 8} - movq\t{%H1, %0|%0, %H1}" - [(set_attr "type" "ssemov,sseishft,ssemov") -+ (set_attr "atom_unit" "*,sishuf,*") - (set_attr "memory" "*,none,*") - (set_attr "mode" "V2SF,TI,TI")]) - -@@ -7614,6 +7629,7 @@ - "TARGET_SSE2" - "psadbw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "simul") - (set_attr "prefix_data16" "1") - (set_attr "mode" "TI")]) - -@@ -7635,7 +7651,7 @@ - UNSPEC_MOVMSK))] - "SSE_VEC_FLOAT_MODE_P (<MODE>mode)" - "%vmovmskp<ssemodesuffixf2c>\t{%1, %0|%0, %1}" -- [(set_attr "type" "ssecvt") -+ [(set_attr "type" "ssemov") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "<MODE>")]) - -@@ -7645,7 +7661,7 @@ - UNSPEC_MOVMSK))] - "TARGET_SSE2" - "%vpmovmskb\t{%1, %0|%0, %1}" -- [(set_attr "type" "ssecvt") -+ [(set_attr "type" "ssemov") - (set_attr "prefix_data16" "1") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "SI")]) -@@ -7668,7 +7684,7 @@ - "TARGET_SSE2 && !TARGET_64BIT" - ;; @@@ check ordering of operands in intel/nonintel syntax - "%vmaskmovdqu\t{%2, %1|%1, %2}" -- [(set_attr "type" "ssecvt") -+ [(set_attr "type" "ssemov") - (set_attr "prefix_data16" "1") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "TI")]) -@@ -7682,7 +7698,7 @@ - "TARGET_SSE2 && TARGET_64BIT" - ;; @@@ check ordering of operands in intel/nonintel syntax - "%vmaskmovdqu\t{%2, %1|%1, %2}" -- [(set_attr "type" "ssecvt") -+ [(set_attr "type" "ssemov") - (set_attr "prefix_data16" "1") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "TI")]) -@@ -7693,6 +7709,7 @@ - "TARGET_SSE" - "%vldmxcsr\t%0" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "mxcsr") - (set_attr "prefix" "maybe_vex") - (set_attr "memory" "load")]) - -@@ -7702,6 +7719,7 @@ - "TARGET_SSE" - "%vstmxcsr\t%0" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "mxcsr") - (set_attr "prefix" "maybe_vex") - (set_attr "memory" "store")]) - -@@ -7720,6 +7738,7 @@ - "TARGET_SSE || TARGET_3DNOW_A" - "sfence" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "fence") - (set_attr "memory" "unknown")]) - - (define_insn "sse2_clflush" -@@ -7728,6 +7747,7 @@ - "TARGET_SSE2" - "clflush\t%a0" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "fence") - (set_attr "memory" "unknown")]) - - (define_expand "sse2_mfence" -@@ -7745,6 +7765,7 @@ - "TARGET_64BIT || TARGET_SSE2" - "mfence" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "fence") - (set_attr "memory" "unknown")]) - - (define_expand "sse2_lfence" -@@ -7762,6 +7783,7 @@ - "TARGET_SSE2" - "lfence" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "lfence") - (set_attr "memory" "unknown")]) - - (define_insn "sse3_mwait" -@@ -7885,6 +7907,7 @@ - "TARGET_SSSE3" - "phaddw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_data16" "1") - (set_attr "prefix_extra" "1") - (set_attr "mode" "TI")]) -@@ -7913,6 +7936,7 @@ - "TARGET_SSSE3" - "phaddw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_extra" "1") - (set_attr "mode" "DI")]) - -@@ -7967,6 +7991,7 @@ - "TARGET_SSSE3" - "phaddd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_data16" "1") - (set_attr "prefix_extra" "1") - (set_attr "mode" "TI")]) -@@ -7987,6 +8012,7 @@ - "TARGET_SSSE3" - "phaddd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_extra" "1") - (set_attr "mode" "DI")]) - -@@ -8073,6 +8099,7 @@ - "TARGET_SSSE3" - "phaddsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_data16" "1") - (set_attr "prefix_extra" "1") - (set_attr "mode" "TI")]) -@@ -8101,6 +8128,7 @@ - "TARGET_SSSE3" - "phaddsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_extra" "1") - (set_attr "mode" "DI")]) - -@@ -8187,6 +8215,7 @@ - "TARGET_SSSE3" - "phsubw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_data16" "1") - (set_attr "prefix_extra" "1") - (set_attr "mode" "TI")]) -@@ -8215,6 +8244,7 @@ - "TARGET_SSSE3" - "phsubw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_extra" "1") - (set_attr "mode" "DI")]) - -@@ -8269,6 +8299,7 @@ - "TARGET_SSSE3" - "phsubd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_data16" "1") - (set_attr "prefix_extra" "1") - (set_attr "mode" "TI")]) -@@ -8289,6 +8320,7 @@ - "TARGET_SSSE3" - "phsubd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_extra" "1") - (set_attr "mode" "DI")]) - -@@ -8375,6 +8407,7 @@ - "TARGET_SSSE3" - "phsubsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_data16" "1") - (set_attr "prefix_extra" "1") - (set_attr "mode" "TI")]) -@@ -8403,6 +8436,7 @@ - "TARGET_SSSE3" - "phsubsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_extra" "1") - (set_attr "mode" "DI")]) - -@@ -8509,6 +8543,7 @@ - "TARGET_SSSE3" - "pmaddubsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "simul") - (set_attr "prefix_data16" "1") - (set_attr "prefix_extra" "1") - (set_attr "mode" "TI")]) -@@ -8547,6 +8582,7 @@ - "TARGET_SSSE3" - "pmaddubsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "simul") - (set_attr "prefix_extra" "1") - (set_attr "mode" "DI")]) - -@@ -8754,6 +8790,7 @@ - return "palignr\t{%3, %2, %0|%0, %2, %3}"; - } - [(set_attr "type" "sseishft") -+ (set_attr "atom_unit" "sishuf") - (set_attr "prefix_data16" "1") - (set_attr "prefix_extra" "1") - (set_attr "mode" "TI")]) -@@ -8770,6 +8807,7 @@ - return "palignr\t{%3, %2, %0|%0, %2, %3}"; - } - [(set_attr "type" "sseishft") -+ (set_attr "atom_unit" "sishuf") - (set_attr "prefix_extra" "1") - (set_attr "mode" "DI")]) - -@@ -8956,7 +8994,7 @@ - UNSPEC_MOVNTDQA))] - "TARGET_SSE4_1" - "%vmovntdqa\t{%1, %0|%0, %1}" -- [(set_attr "type" "ssecvt") -+ [(set_attr "type" "ssemov") - (set_attr "prefix_extra" "1") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "TI")]) ---- a/gcc/config/i386/winnt.c -+++ b/gcc/config/i386/winnt.c -@@ -499,8 +499,11 @@ - { - HOST_WIDE_INT rounded; - -- /* Compute as in assemble_noswitch_variable, since we don't actually -- support aligned common. */ -+ /* Compute as in assemble_noswitch_variable, since we don't have -+ support for aligned common on older binutils. We must also -+ avoid emitting a common symbol of size zero, as this is the -+ overloaded representation that indicates an undefined external -+ symbol in the PE object file format. */ - rounded = size ? size : 1; - rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1; - rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) -@@ -510,9 +513,13 @@ - - fprintf (stream, "\t.comm\t"); - assemble_name (stream, name); -- fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC "\t" ASM_COMMENT_START -- " " HOST_WIDE_INT_PRINT_DEC "\n", -- rounded, size); -+ if (use_pe_aligned_common) -+ fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC ", %d\n", -+ size ? size : (HOST_WIDE_INT) 1, -+ exact_log2 (align) - exact_log2 (CHAR_BIT)); -+ else -+ fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC "\t" ASM_COMMENT_START -+ " " HOST_WIDE_INT_PRINT_DEC "\n", rounded, size); - } - - /* The Microsoft linker requires that every function be marked as ---- a/gcc/config/m68k/constraints.md -+++ b/gcc/config/m68k/constraints.md -@@ -124,6 +124,11 @@ - (and (match_code "const_int") - (match_test "ival < -0x8000 || ival > 0x7FFF"))) - -+(define_constraint "Cu" -+ "16-bit offset for wrapped symbols" -+ (and (match_code "const") -+ (match_test "m68k_unwrap_symbol (op, false) != op"))) -+ - (define_constraint "CQ" - "Integers valid for mvq." - (and (match_code "const_int") ---- a/gcc/config/m68k/lb1sf68.asm -+++ b/gcc/config/m68k/lb1sf68.asm -@@ -163,6 +163,8 @@ - #if defined (__mcoldfire__) && !defined (__mcfisab__) && !defined (__mcfisac__) - lea \addr-.-8,a0 - jsr pc@(a0) -+#elif defined (__mcfisab__) || defined (__mcfisac__) -+ bsr.l \addr - #else - bsr \addr - #endif -@@ -202,6 +204,8 @@ - #if defined (__mcoldfire__) && !defined (__mcfisab__) && !defined (__mcfisac__) - lea \addr-.-8,a0 - jsr pc@(a0) -+#elif defined (__mcfisab__) || defined (__mcfisac__) -+ bsr.l \addr - #else - bsr \addr - #endif ---- a/gcc/config/m68k/linux-unwind.h -+++ b/gcc/config/m68k/linux-unwind.h -@@ -77,9 +77,15 @@ - fs->regs.reg[9].how = REG_SAVED_OFFSET; - fs->regs.reg[9].loc.offset = (long) &sc->sc_a1 - cfa; - -+#ifdef __uClinux__ -+ fs->regs.reg[13].how = REG_SAVED_OFFSET; -+ fs->regs.reg[13].loc.offset = (long) &sc->sc_a5 - cfa; -+#endif -+ - fs->regs.reg[24].how = REG_SAVED_OFFSET; - fs->regs.reg[24].loc.offset = (long) &sc->sc_pc - cfa; - -+#if defined __mcffpu__ && !defined __uClinux__ - if (*(int *) sc->sc_fpstate) - { - int *fpregs = (int *) sc->sc_fpregs; -@@ -89,11 +95,19 @@ - fs->regs.reg[17].how = REG_SAVED_OFFSET; - fs->regs.reg[17].loc.offset = (long) &fpregs[M68K_FP_SIZE/4] - cfa; - } -+#elif defined __mcffpu__ -+# error Implement this when uClinux kernel is ported to an FPU architecture -+#endif - } - #ifdef __mcoldfire__ - /* move.l #__NR_rt_sigreturn,%d0; trap #0 */ -- else if (pc[0] == 0x203c && pc[1] == 0x0000 && -- pc[2] == 0x00ad && pc[3] == 0x4e40) -+ else if ((pc[0] == 0x203c && pc[1] == 0x0000 && -+ pc[2] == 0x00ad && pc[3] == 0x4e40) || -+ /* Don't ask me why, this is just what some kernels do: -+ moveq #-__NR_rt_sigreturn,%d0; andil 0xff,%d0; trap #0; -+ Sigh... */ -+ (pc[0] == 0x70ad && pc[1] == 0x0280 && pc[2] == 0x0000 && -+ pc[3] == 0x00ff && pc[4] == 0x4e40 && pc[5] == 0x0000)) - #else - /* moveq #~__NR_rt_sigreturn,%d0; not.b %d0; trap #0 */ - else if (pc[0] == 0x7052 && pc[1] == 0x4600 && pc[2] == 0x4e40) ---- a/gcc/config/m68k/m68k.c -+++ b/gcc/config/m68k/m68k.c -@@ -46,6 +46,7 @@ - /* ??? Need to add a dependency between m68k.o and sched-int.h. */ - #include "sched-int.h" - #include "insn-codes.h" -+#include "ggc.h" - - enum reg_class regno_reg_class[] = - { -@@ -146,10 +147,12 @@ - static void m68k_compute_frame_layout (void); - static bool m68k_save_reg (unsigned int regno, bool interrupt_handler); - static bool m68k_ok_for_sibcall_p (tree, tree); -+static bool m68k_tls_symbol_p (rtx); - static bool m68k_rtx_costs (rtx, int, int, int *, bool); - #if M68K_HONOR_TARGET_STRICT_ALIGNMENT - static bool m68k_return_in_memory (const_tree, const_tree); - #endif -+static void m68k_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED; - - - /* Specify the identification number of the library being built */ -@@ -252,6 +255,14 @@ - #define TARGET_RETURN_IN_MEMORY m68k_return_in_memory - #endif - -+#ifdef HAVE_AS_TLS -+#undef TARGET_HAVE_TLS -+#define TARGET_HAVE_TLS (true) -+ -+#undef TARGET_ASM_OUTPUT_DWARF_DTPREL -+#define TARGET_ASM_OUTPUT_DWARF_DTPREL m68k_output_dwarf_dtprel -+#endif -+ - static const struct attribute_spec m68k_attribute_table[] = - { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ -@@ -1150,8 +1161,7 @@ - current_frame.reg_mask, true, true)); - } - -- if (flag_pic -- && !TARGET_SEP_DATA -+ if (!TARGET_SEP_DATA - && crtl->uses_pic_offset_table) - insn = emit_insn (gen_load_got (pic_offset_table_rtx)); - } -@@ -1425,6 +1435,86 @@ - return replace_equiv_address (x, gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM)); - } - -+/* Convert X to a legitimate address and return it if successful. Otherwise -+ return X. -+ -+ For the 68000, we handle X+REG by loading X into a register R and -+ using R+REG. R will go in an address reg and indexing will be used. -+ However, if REG is a broken-out memory address or multiplication, -+ nothing needs to be done because REG can certainly go in an address reg. */ -+ -+rtx -+m68k_legitimize_address (rtx x, rtx oldx, enum machine_mode mode) -+{ -+ if (m68k_tls_symbol_p (x)) -+ return m68k_legitimize_tls_address (x); -+ -+ if (GET_CODE (x) == PLUS) -+ { -+ int ch = (x) != (oldx); -+ int copied = 0; -+ -+#define COPY_ONCE(Y) if (!copied) { Y = copy_rtx (Y); copied = ch = 1; } -+ -+ if (GET_CODE (XEXP (x, 0)) == MULT) -+ { -+ COPY_ONCE (x); -+ XEXP (x, 0) = force_operand (XEXP (x, 0), 0); -+ } -+ if (GET_CODE (XEXP (x, 1)) == MULT) -+ { -+ COPY_ONCE (x); -+ XEXP (x, 1) = force_operand (XEXP (x, 1), 0); -+ } -+ if (ch) -+ { -+ if (GET_CODE (XEXP (x, 1)) == REG -+ && GET_CODE (XEXP (x, 0)) == REG) -+ { -+ if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (mode) == MODE_FLOAT) -+ { -+ COPY_ONCE (x); -+ x = force_operand (x, 0); -+ } -+ return x; -+ } -+ if (memory_address_p (mode, x)) -+ return x; -+ } -+ if (GET_CODE (XEXP (x, 0)) == REG -+ || (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND -+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG -+ && GET_MODE (XEXP (XEXP (x, 0), 0)) == HImode)) -+ { -+ rtx temp = gen_reg_rtx (Pmode); -+ rtx val = force_operand (XEXP (x, 1), 0); -+ emit_move_insn (temp, val); -+ COPY_ONCE (x); -+ XEXP (x, 1) = temp; -+ if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (mode) == MODE_FLOAT -+ && GET_CODE (XEXP (x, 0)) == REG) -+ x = force_operand (x, 0); -+ } -+ else if (GET_CODE (XEXP (x, 1)) == REG -+ || (GET_CODE (XEXP (x, 1)) == SIGN_EXTEND -+ && GET_CODE (XEXP (XEXP (x, 1), 0)) == REG -+ && GET_MODE (XEXP (XEXP (x, 1), 0)) == HImode)) -+ { -+ rtx temp = gen_reg_rtx (Pmode); -+ rtx val = force_operand (XEXP (x, 0), 0); -+ emit_move_insn (temp, val); -+ COPY_ONCE (x); -+ XEXP (x, 0) = temp; -+ if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (mode) == MODE_FLOAT -+ && GET_CODE (XEXP (x, 1)) == REG) -+ x = force_operand (x, 0); -+ } -+ } -+ -+ return x; -+} -+ -+ - /* Output a dbCC; jCC sequence. Note we do not handle the - floating point version of this sequence (Fdbcc). We also - do not handle alternative conditions when CC_NO_OVERFLOW is -@@ -1713,15 +1803,16 @@ - whether we need strict checking. */ - - bool --m68k_legitimate_index_reg_p (rtx x, bool strict_p) -+m68k_legitimate_index_reg_p (enum machine_mode mode, rtx x, bool strict_p) - { - if (!strict_p && GET_CODE (x) == SUBREG) - x = SUBREG_REG (x); - - return (REG_P (x) - && (strict_p -- ? REGNO_OK_FOR_INDEX_P (REGNO (x)) -- : REGNO_OK_FOR_INDEX_NONSTRICT_P (REGNO (x)))); -+ ? REGNO_MODE_OK_FOR_INDEX_P (REGNO (x), mode) -+ : (MODE_OK_FOR_INDEX_P (mode) -+ && REGNO_OK_FOR_INDEX_NONSTRICT_P (REGNO (x))))); - } - - /* Return true if X is a legitimate index expression for a (d8,An,Xn) or -@@ -1729,7 +1820,8 @@ - ADDRESS if so. STRICT_P says whether we need strict checking. */ - - static bool --m68k_decompose_index (rtx x, bool strict_p, struct m68k_address *address) -+m68k_decompose_index (enum machine_mode mode, rtx x, bool strict_p, -+ struct m68k_address *address) - { - int scale; - -@@ -1753,7 +1845,7 @@ - && GET_MODE (XEXP (x, 0)) == HImode) - x = XEXP (x, 0); - -- if (m68k_legitimate_index_reg_p (x, strict_p)) -+ if (m68k_legitimate_index_reg_p (mode, x, strict_p)) - { - address->scale = scale; - address->index = x; -@@ -1777,7 +1869,7 @@ - && !offset_within_block_p (base, INTVAL (offset))) - return true; - } -- return false; -+ return m68k_tls_reference_p (x, false); - } - - /* Return true if X is a legitimate constant address that can reach -@@ -1805,7 +1897,7 @@ - return false; - } - -- return true; -+ return !m68k_tls_reference_p (x, false); - } - - /* Return true if X is a LABEL_REF for a jump table. Assume that unplaced -@@ -1872,15 +1964,17 @@ - /* Check for GOT loads. These are (bd,An,Xn) addresses if - TARGET_68020 && flag_pic == 2, otherwise they are (d16,An) - addresses. */ -- if (flag_pic -- && GET_CODE (x) == PLUS -- && XEXP (x, 0) == pic_offset_table_rtx -- && (GET_CODE (XEXP (x, 1)) == SYMBOL_REF -- || GET_CODE (XEXP (x, 1)) == LABEL_REF)) -+ if (GET_CODE (x) == PLUS -+ && XEXP (x, 0) == pic_offset_table_rtx) - { -- address->base = XEXP (x, 0); -- address->offset = XEXP (x, 1); -- return true; -+ /* As we are processing a PLUS, do not unwrap RELOC32 symbols -- -+ they are invalid in this context. */ -+ if (m68k_unwrap_symbol (XEXP (x, 1), false) != XEXP (x, 1)) -+ { -+ address->base = XEXP (x, 0); -+ address->offset = XEXP (x, 1); -+ return true; -+ } - } - - /* The ColdFire FPU only accepts addressing modes 2-5. */ -@@ -1905,7 +1999,7 @@ - accesses to unplaced labels in other cases. */ - if (GET_CODE (x) == PLUS - && m68k_jump_table_ref_p (XEXP (x, 1)) -- && m68k_decompose_index (XEXP (x, 0), strict_p, address)) -+ && m68k_decompose_index (mode, XEXP (x, 0), strict_p, address)) - { - address->offset = XEXP (x, 1); - return true; -@@ -1937,7 +2031,7 @@ - worse code. */ - if (address->offset - && symbolic_operand (address->offset, VOIDmode) -- && m68k_decompose_index (x, strict_p, address)) -+ && m68k_decompose_index (mode, x, strict_p, address)) - return true; - } - else -@@ -1956,14 +2050,14 @@ - if (GET_CODE (x) == PLUS) - { - if (m68k_legitimate_base_reg_p (XEXP (x, 0), strict_p) -- && m68k_decompose_index (XEXP (x, 1), strict_p, address)) -+ && m68k_decompose_index (mode, XEXP (x, 1), strict_p, address)) - { - address->base = XEXP (x, 0); - return true; - } - - if (m68k_legitimate_base_reg_p (XEXP (x, 1), strict_p) -- && m68k_decompose_index (XEXP (x, 0), strict_p, address)) -+ && m68k_decompose_index (mode, XEXP (x, 0), strict_p, address)) - { - address->base = XEXP (x, 1); - return true; -@@ -2025,6 +2119,243 @@ - && !address.index); - } - -+/* Return GOT pointer. */ -+ -+static rtx -+m68k_get_gp (void) -+{ -+ if (pic_offset_table_rtx == NULL_RTX) -+ pic_offset_table_rtx = gen_rtx_REG (Pmode, PIC_REG); -+ -+ crtl->uses_pic_offset_table = 1; -+ -+ return pic_offset_table_rtx; -+} -+ -+/* M68K relocations, used to distinguish GOT and TLS relocations in UNSPEC -+ wrappers. */ -+enum m68k_reloc { RELOC_GOT, RELOC_TLSGD, RELOC_TLSLDM, RELOC_TLSLDO, -+ RELOC_TLSIE, RELOC_TLSLE }; -+ -+#define TLS_RELOC_P(RELOC) ((RELOC) != RELOC_GOT) -+ -+/* Wrap symbol X into unspec representing relocation RELOC. -+ BASE_REG - register that should be added to the result. -+ TEMP_REG - if non-null, temporary register. */ -+ -+static rtx -+m68k_wrap_symbol (rtx x, enum m68k_reloc reloc, rtx base_reg, rtx temp_reg) -+{ -+ bool use_x_p; -+ -+ use_x_p = (base_reg == pic_offset_table_rtx) ? TARGET_XGOT : TARGET_XTLS; -+ -+ if (TARGET_COLDFIRE && use_x_p) -+ /* When compiling with -mx{got, tls} switch the code will look like this: -+ -+ move.l <X>@<RELOC>,<TEMP_REG> -+ add.l <BASE_REG>,<TEMP_REG> */ -+ { -+ /* Wrap X in UNSPEC_??? to tip m68k_output_addr_const_extra -+ to put @RELOC after reference. */ -+ x = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (reloc)), -+ UNSPEC_RELOC32); -+ x = gen_rtx_CONST (Pmode, x); -+ -+ if (temp_reg == NULL) -+ { -+ gcc_assert (can_create_pseudo_p ()); -+ temp_reg = gen_reg_rtx (Pmode); -+ } -+ -+ emit_move_insn (temp_reg, x); -+ emit_insn (gen_addsi3 (temp_reg, temp_reg, base_reg)); -+ x = temp_reg; -+ } -+ else -+ { -+ x = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (reloc)), -+ UNSPEC_RELOC16); -+ x = gen_rtx_CONST (Pmode, x); -+ -+ x = gen_rtx_PLUS (Pmode, base_reg, x); -+ } -+ -+ return x; -+} -+ -+/* Helper for m68k_unwrap_symbol. -+ Also, if unwrapping was successful (that is if (ORIG != <return value>)), -+ sets *RELOC_PTR to relocation type for the symbol. */ -+ -+static rtx -+m68k_unwrap_symbol_1 (rtx orig, bool unwrap_reloc32_p, -+ enum m68k_reloc *reloc_ptr) -+{ -+ if (GET_CODE (orig) == CONST) -+ { -+ rtx x; -+ enum m68k_reloc dummy; -+ -+ x = XEXP (orig, 0); -+ -+ if (reloc_ptr == NULL) -+ reloc_ptr = &dummy; -+ -+ /* Handle an addend. */ -+ if ((GET_CODE (x) == PLUS || GET_CODE (x) == MINUS) -+ && CONST_INT_P (XEXP (x, 1))) -+ x = XEXP (x, 0); -+ -+ if (GET_CODE (x) == UNSPEC) -+ { -+ switch (XINT (x, 1)) -+ { -+ case UNSPEC_RELOC16: -+ orig = XVECEXP (x, 0, 0); -+ *reloc_ptr = (enum m68k_reloc) INTVAL (XVECEXP (x, 0, 1)); -+ break; -+ -+ case UNSPEC_RELOC32: -+ if (unwrap_reloc32_p) -+ { -+ orig = XVECEXP (x, 0, 0); -+ *reloc_ptr = (enum m68k_reloc) INTVAL (XVECEXP (x, 0, 1)); -+ } -+ break; -+ -+ default: -+ break; -+ } -+ } -+ } -+ -+ return orig; -+} -+ -+/* Unwrap symbol from UNSPEC_RELOC16 and, if unwrap_reloc32_p, -+ UNSPEC_RELOC32 wrappers. */ -+ -+rtx -+m68k_unwrap_symbol (rtx orig, bool unwrap_reloc32_p) -+{ -+ return m68k_unwrap_symbol_1 (orig, unwrap_reloc32_p, NULL); -+} -+ -+/* Helper for m68k_final_prescan_insn. */ -+ -+static int -+m68k_final_prescan_insn_1 (rtx *x_ptr, void *data ATTRIBUTE_UNUSED) -+{ -+ rtx x = *x_ptr; -+ -+ if (m68k_unwrap_symbol (x, true) != x) -+ /* For rationale of the below, see comment in m68k_final_prescan_insn. */ -+ { -+ rtx plus; -+ -+ gcc_assert (GET_CODE (x) == CONST); -+ plus = XEXP (x, 0); -+ -+ if (GET_CODE (plus) == PLUS || GET_CODE (plus) == MINUS) -+ { -+ rtx unspec; -+ rtx addend; -+ -+ unspec = XEXP (plus, 0); -+ gcc_assert (GET_CODE (unspec) == UNSPEC); -+ addend = XEXP (plus, 1); -+ gcc_assert (CONST_INT_P (addend)); -+ -+ /* We now have all the pieces, rearrange them. */ -+ -+ /* Move symbol to plus. */ -+ XEXP (plus, 0) = XVECEXP (unspec, 0, 0); -+ -+ /* Move plus inside unspec. */ -+ XVECEXP (unspec, 0, 0) = plus; -+ -+ /* Move unspec to top level of const. */ -+ XEXP (x, 0) = unspec; -+ } -+ -+ return -1; -+ } -+ -+ return 0; -+} -+ -+/* Prescan insn before outputing assembler for it. */ -+ -+void -+m68k_final_prescan_insn (rtx insn ATTRIBUTE_UNUSED, -+ rtx *operands, int n_operands) -+{ -+ int i; -+ -+ /* Combine and, possibly, other optimizations may do good job -+ converting -+ (const (unspec [(symbol)])) -+ into -+ (const (plus (unspec [(symbol)]) -+ (const_int N))). -+ The problem with this is emitting @TLS or @GOT decorations. -+ The decoration is emitted when processing (unspec), so the -+ result would be "#symbol@TLSLE+N" instead of "#symbol+N@TLSLE". -+ -+ It seems that the easiest solution to this is to convert such -+ operands to -+ (const (unspec [(plus (symbol) -+ (const_int N))])). -+ Note, that the top level of operand remains intact, so we don't have -+ to patch up anything outside of the operand. */ -+ -+ for (i = 0; i < n_operands; ++i) -+ { -+ rtx op; -+ -+ op = operands[i]; -+ -+ for_each_rtx (&op, m68k_final_prescan_insn_1, NULL); -+ } -+} -+ -+/* Move X to a register and add REG_EQUAL note pointing to ORIG. -+ If REG is non-null, use it; generate new pseudo otherwise. */ -+ -+static rtx -+m68k_move_to_reg (rtx x, rtx orig, rtx reg) -+{ -+ rtx insn; -+ -+ if (reg == NULL_RTX) -+ { -+ gcc_assert (can_create_pseudo_p ()); -+ reg = gen_reg_rtx (Pmode); -+ } -+ -+ insn = emit_move_insn (reg, x); -+ /* Put a REG_EQUAL note on this insn, so that it can be optimized -+ by loop. */ -+ set_unique_reg_note (insn, REG_EQUAL, orig); -+ -+ return reg; -+} -+ -+/* Does the same as m68k_wrap_symbol, but returns a memory reference to -+ GOT slot. */ -+ -+static rtx -+m68k_wrap_symbol_into_got_ref (rtx x, enum m68k_reloc reloc, rtx temp_reg) -+{ -+ x = m68k_wrap_symbol (x, reloc, m68k_get_gp (), temp_reg); -+ -+ x = gen_rtx_MEM (Pmode, x); -+ MEM_READONLY_P (x) = 1; -+ -+ return x; -+} -+ - /* Legitimize PIC addresses. If the address is already - position-independent, we return ORIG. Newly generated - position-independent addresses go to REG. If we need more -@@ -2076,42 +2407,15 @@ - { - gcc_assert (reg); - -- if (TARGET_COLDFIRE && TARGET_XGOT) -- /* When compiling with -mxgot switch the code for the above -- example will look like this: -- -- movel a5, a0 -- addl _foo@GOT, a0 -- movel a0@, a0 -- movel #12345, a0@ */ -- { -- rtx pic_offset; -- -- /* Wrap ORIG in UNSPEC_GOTOFF to tip m68k_output_addr_const_extra -- to put @GOT after reference. */ -- pic_offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, orig), -- UNSPEC_GOTOFF); -- pic_offset = gen_rtx_CONST (Pmode, pic_offset); -- emit_move_insn (reg, pic_offset); -- emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx)); -- pic_ref = gen_rtx_MEM (Pmode, reg); -- } -- else -- pic_ref = gen_rtx_MEM (Pmode, -- gen_rtx_PLUS (Pmode, -- pic_offset_table_rtx, orig)); -- crtl->uses_pic_offset_table = 1; -- MEM_READONLY_P (pic_ref) = 1; -- emit_move_insn (reg, pic_ref); -- return reg; -+ pic_ref = m68k_wrap_symbol_into_got_ref (orig, RELOC_GOT, reg); -+ pic_ref = m68k_move_to_reg (pic_ref, orig, reg); - } - else if (GET_CODE (orig) == CONST) - { - rtx base; - - /* Make sure this has not already been legitimized. */ -- if (GET_CODE (XEXP (orig, 0)) == PLUS -- && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx) -+ if (m68k_unwrap_symbol (orig, true) != orig) - return orig; - - gcc_assert (reg); -@@ -2124,13 +2428,257 @@ - base == reg ? 0 : reg); - - if (GET_CODE (orig) == CONST_INT) -- return plus_constant (base, INTVAL (orig)); -- pic_ref = gen_rtx_PLUS (Pmode, base, orig); -- /* Likewise, should we set special REG_NOTEs here? */ -+ pic_ref = plus_constant (base, INTVAL (orig)); -+ else -+ pic_ref = gen_rtx_PLUS (Pmode, base, orig); - } -+ - return pic_ref; - } - -+/* The __tls_get_addr symbol. */ -+static GTY(()) rtx m68k_tls_get_addr; -+ -+/* Return SYMBOL_REF for __tls_get_addr. */ -+ -+static rtx -+m68k_get_tls_get_addr (void) -+{ -+ if (m68k_tls_get_addr == NULL_RTX) -+ m68k_tls_get_addr = init_one_libfunc ("__tls_get_addr"); -+ -+ return m68k_tls_get_addr; -+} -+ -+/* Return libcall result in A0 instead of usual D0. */ -+static bool m68k_libcall_value_in_a0_p = false; -+ -+/* Emit instruction sequence that calls __tls_get_addr. X is -+ the TLS symbol we are referencing and RELOC is the symbol type to use -+ (either TLSGD or TLSLDM). EQV is the REG_EQUAL note for the sequence -+ emitted. A pseudo register with result of __tls_get_addr call is -+ returned. */ -+ -+static rtx -+m68k_call_tls_get_addr (rtx x, rtx eqv, enum m68k_reloc reloc) -+{ -+ rtx a0; -+ rtx insns; -+ rtx dest; -+ -+ /* Emit the call sequence. */ -+ start_sequence (); -+ -+ /* FIXME: Unfortunately, emit_library_call_value does not -+ consider (plus (%a5) (const (unspec))) to be a good enough -+ operand for push, so it forces it into a register. The bad -+ thing about this is that combiner, due to copy propagation and other -+ optimizations, sometimes can not later fix this. As a consequence, -+ additional register may be allocated resulting in a spill. -+ For reference, see args processing loops in -+ calls.c:emit_library_call_value_1. -+ For testcase, see gcc.target/m68k/tls-{gd, ld}.c */ -+ x = m68k_wrap_symbol (x, reloc, m68k_get_gp (), NULL_RTX); -+ -+ /* __tls_get_addr() is not a libcall, but emitting a libcall_value -+ is the simpliest way of generating a call. The difference between -+ __tls_get_addr() and libcall is that the result is returned in D0 -+ instead of A0. To workaround this, we use m68k_libcall_value_in_a0_p -+ which temporarily switches returning the result to A0. */ -+ -+ m68k_libcall_value_in_a0_p = true; -+ a0 = emit_library_call_value (m68k_get_tls_get_addr (), NULL_RTX, LCT_PURE, -+ Pmode, 1, x, Pmode); -+ m68k_libcall_value_in_a0_p = false; -+ -+ insns = get_insns (); -+ end_sequence (); -+ -+ gcc_assert (can_create_pseudo_p ()); -+ dest = gen_reg_rtx (Pmode); -+ emit_libcall_block (insns, dest, a0, eqv); -+ -+ return dest; -+} -+ -+/* The __tls_get_addr symbol. */ -+static GTY(()) rtx m68k_read_tp; -+ -+/* Return SYMBOL_REF for __m68k_read_tp. */ -+ -+static rtx -+m68k_get_m68k_read_tp (void) -+{ -+ if (m68k_read_tp == NULL_RTX) -+ m68k_read_tp = init_one_libfunc ("__m68k_read_tp"); -+ -+ return m68k_read_tp; -+} -+ -+/* Emit instruction sequence that calls __m68k_read_tp. -+ A pseudo register with result of __m68k_read_tp call is returned. */ -+ -+static rtx -+m68k_call_m68k_read_tp (void) -+{ -+ rtx a0; -+ rtx eqv; -+ rtx insns; -+ rtx dest; -+ -+ start_sequence (); -+ -+ /* __m68k_read_tp() is not a libcall, but emitting a libcall_value -+ is the simpliest way of generating a call. The difference between -+ __m68k_read_tp() and libcall is that the result is returned in D0 -+ instead of A0. To workaround this, we use m68k_libcall_value_in_a0_p -+ which temporarily switches returning the result to A0. */ -+ -+ /* Emit the call sequence. */ -+ m68k_libcall_value_in_a0_p = true; -+ a0 = emit_library_call_value (m68k_get_m68k_read_tp (), NULL_RTX, LCT_PURE, -+ Pmode, 0); -+ m68k_libcall_value_in_a0_p = false; -+ insns = get_insns (); -+ end_sequence (); -+ -+ /* Attach a unique REG_EQUIV, to allow the RTL optimizers to -+ share the m68k_read_tp result with other IE/LE model accesses. */ -+ eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const1_rtx), UNSPEC_RELOC32); -+ -+ gcc_assert (can_create_pseudo_p ()); -+ dest = gen_reg_rtx (Pmode); -+ emit_libcall_block (insns, dest, a0, eqv); -+ -+ return dest; -+} -+ -+/* Return a legitimized address for accessing TLS SYMBOL_REF X. -+ For explanations on instructions sequences see TLS/NPTL ABI for m68k and -+ ColdFire. */ -+ -+rtx -+m68k_legitimize_tls_address (rtx orig) -+{ -+ switch (SYMBOL_REF_TLS_MODEL (orig)) -+ { -+ case TLS_MODEL_GLOBAL_DYNAMIC: -+ orig = m68k_call_tls_get_addr (orig, orig, RELOC_TLSGD); -+ break; -+ -+ case TLS_MODEL_LOCAL_DYNAMIC: -+ { -+ rtx eqv; -+ rtx a0; -+ rtx x; -+ -+ /* Attach a unique REG_EQUIV, to allow the RTL optimizers to -+ share the LDM result with other LD model accesses. */ -+ eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), -+ UNSPEC_RELOC32); -+ -+ a0 = m68k_call_tls_get_addr (orig, eqv, RELOC_TLSLDM); -+ -+ x = m68k_wrap_symbol (orig, RELOC_TLSLDO, a0, NULL_RTX); -+ -+ if (can_create_pseudo_p ()) -+ x = m68k_move_to_reg (x, orig, NULL_RTX); -+ -+ orig = x; -+ break; -+ } -+ -+ case TLS_MODEL_INITIAL_EXEC: -+ { -+ rtx a0; -+ rtx x; -+ -+ a0 = m68k_call_m68k_read_tp (); -+ -+ x = m68k_wrap_symbol_into_got_ref (orig, RELOC_TLSIE, NULL_RTX); -+ x = gen_rtx_PLUS (Pmode, x, a0); -+ -+ if (can_create_pseudo_p ()) -+ x = m68k_move_to_reg (x, orig, NULL_RTX); -+ -+ orig = x; -+ break; -+ } -+ -+ case TLS_MODEL_LOCAL_EXEC: -+ { -+ rtx a0; -+ rtx x; -+ -+ a0 = m68k_call_m68k_read_tp (); -+ -+ x = m68k_wrap_symbol (orig, RELOC_TLSLE, a0, NULL_RTX); -+ -+ if (can_create_pseudo_p ()) -+ x = m68k_move_to_reg (x, orig, NULL_RTX); -+ -+ orig = x; -+ break; -+ } -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return orig; -+} -+ -+/* Return true if X is a TLS symbol. */ -+ -+static bool -+m68k_tls_symbol_p (rtx x) -+{ -+ if (!TARGET_HAVE_TLS) -+ return false; -+ -+ if (GET_CODE (x) != SYMBOL_REF) -+ return false; -+ -+ return SYMBOL_REF_TLS_MODEL (x) != 0; -+} -+ -+/* Helper for m68k_tls_referenced_p. */ -+ -+static int -+m68k_tls_reference_p_1 (rtx *x_ptr, void *data ATTRIBUTE_UNUSED) -+{ -+ /* Note: this is not the same as m68k_tls_symbol_p. */ -+ if (GET_CODE (*x_ptr) == SYMBOL_REF) -+ return SYMBOL_REF_TLS_MODEL (*x_ptr) != 0 ? 1 : 0; -+ -+ /* Don't recurse into legitimate TLS references. */ -+ if (m68k_tls_reference_p (*x_ptr, true)) -+ return -1; -+ -+ return 0; -+} -+ -+/* If !LEGITIMATE_P, return true if X is a TLS symbol reference, -+ though illegitimate one. -+ If LEGITIMATE_P, return true if X is a legitimate TLS symbol reference. */ -+ -+bool -+m68k_tls_reference_p (rtx x, bool legitimate_p) -+{ -+ if (!TARGET_HAVE_TLS) -+ return false; -+ -+ if (!legitimate_p) -+ return for_each_rtx (&x, m68k_tls_reference_p_1, NULL) == 1 ? true : false; -+ else -+ { -+ enum m68k_reloc reloc = RELOC_GOT; -+ -+ return (m68k_unwrap_symbol_1 (x, true, &reloc) != x -+ && TLS_RELOC_P (reloc)); -+ } -+} -+ - - - #define USE_MOVQ(i) ((unsigned) ((i) + 128) <= 255) -@@ -3918,18 +4466,92 @@ - } - } - -+/* Return string for TLS relocation RELOC. */ -+ -+static const char * -+m68k_get_reloc_decoration (enum m68k_reloc reloc) -+{ -+ /* To my knowledge, !MOTOROLA assemblers don't support TLS. */ -+ gcc_assert (MOTOROLA || reloc == RELOC_GOT); -+ -+ switch (reloc) -+ { -+ case RELOC_GOT: -+ if (MOTOROLA) -+ { -+ if (flag_pic == 1 && TARGET_68020) -+ return "@GOT.w"; -+ else -+ return "@GOT"; -+ } -+ else -+ { -+ if (TARGET_68020) -+ { -+ switch (flag_pic) -+ { -+ case 1: -+ return ":w"; -+ case 2: -+ return ":l"; -+ default: -+ return ""; -+ } -+ } -+ } -+ -+ case RELOC_TLSGD: -+ return "@TLSGD"; -+ -+ case RELOC_TLSLDM: -+ return "@TLSLDM"; -+ -+ case RELOC_TLSLDO: -+ return "@TLSLDO"; -+ -+ case RELOC_TLSIE: -+ return "@TLSIE"; -+ -+ case RELOC_TLSLE: -+ return "@TLSLE"; -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ - /* m68k implementation of OUTPUT_ADDR_CONST_EXTRA. */ - - bool - m68k_output_addr_const_extra (FILE *file, rtx x) - { -- if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_GOTOFF) -- return false; -+ if (GET_CODE (x) == UNSPEC) -+ { -+ switch (XINT (x, 1)) -+ { -+ case UNSPEC_RELOC16: -+ case UNSPEC_RELOC32: -+ output_addr_const (file, XVECEXP (x, 0, 0)); -+ fputs (m68k_get_reloc_decoration (INTVAL (XVECEXP (x, 0, 1))), file); -+ return true; - -- output_addr_const (file, XVECEXP (x, 0, 0)); -- /* ??? What is the non-MOTOROLA syntax? */ -- fputs ("@GOT", file); -- return true; -+ default: -+ break; -+ } -+ } -+ -+ return false; -+} -+ -+/* M68K implementation of TARGET_ASM_OUTPUT_DWARF_DTPREL. */ -+ -+static void -+m68k_output_dwarf_dtprel (FILE *file, int size, rtx x) -+{ -+ gcc_assert (size == 4); -+ fputs ("\t.long\t", file); -+ output_addr_const (file, x); -+ fputs ("@TLSLDO+0x8000", file); - } - - -@@ -4019,15 +4641,8 @@ - else - { - if (address.offset) -- { -- output_addr_const (file, address.offset); -- if (flag_pic && address.base == pic_offset_table_rtx) -- { -- fprintf (file, "@GOT"); -- if (flag_pic == 1 && TARGET_68020) -- fprintf (file, ".w"); -- } -- } -+ output_addr_const (file, address.offset); -+ - putc ('(', file); - if (address.base) - fputs (M68K_REGNAME (REGNO (address.base)), file); -@@ -4060,19 +4675,7 @@ - fputs (M68K_REGNAME (REGNO (address.base)), file); - fprintf (file, "@("); - if (address.offset) -- { -- output_addr_const (file, address.offset); -- if (address.base == pic_offset_table_rtx && TARGET_68020) -- switch (flag_pic) -- { -- case 1: -- fprintf (file, ":w"); break; -- case 2: -- fprintf (file, ":l"); break; -- default: -- break; -- } -- } -+ output_addr_const (file, address.offset); - } - /* Print the ",index" component, if any. */ - if (address.index) -@@ -4580,7 +5183,8 @@ - default: - break; - } -- return gen_rtx_REG (mode, D0_REG); -+ -+ return gen_rtx_REG (mode, m68k_libcall_value_in_a0_p ? A0_REG : D0_REG); - } - - rtx -@@ -4846,9 +5450,8 @@ - return OP_TYPE_IMM_L; - - default: -- if (GET_CODE (op) == SYMBOL_REF) -- /* ??? Just a guess. Probably we can guess better using length -- attribute of the instructions. */ -+ if (symbolic_operand (m68k_unwrap_symbol (op, false), VOIDmode)) -+ /* Just a guess. */ - return OP_TYPE_IMM_W; - - return OP_TYPE_IMM_L; -@@ -5793,3 +6396,5 @@ - return 0; - } - } -+ -+#include "gt-m68k.h" ---- a/gcc/config/m68k/m68k-devices.def -+++ b/gcc/config/m68k/m68k-devices.def -@@ -72,8 +72,8 @@ - /* 680x0 series processors. */ - M68K_DEVICE ("68000", m68000, "68000", "68000", 68000, isa_00, 0) - M68K_DEVICE ("68010", m68010, "68010", "68000", 68010, isa_10, 0) --M68K_DEVICE ("68020", m68020, "68020", "68020", 68020, isa_20, FL_MMU) --M68K_DEVICE ("68030", m68030, "68030", "68020", 68030, isa_20, FL_MMU) -+M68K_DEVICE ("68020", m68020, "68020", "68020", 68020, isa_20, FL_MMU | FL_UCLINUX) -+M68K_DEVICE ("68030", m68030, "68030", "68020", 68030, isa_20, FL_MMU | FL_UCLINUX) - M68K_DEVICE ("68040", m68040, "68040", "68040", 68040, isa_40, FL_MMU) - M68K_DEVICE ("68060", m68060, "68060", "68060", 68060, isa_40, FL_MMU) - M68K_DEVICE ("68302", m68302, "68302", "68000", 68000, isa_00, FL_MMU) -@@ -81,7 +81,13 @@ - M68K_DEVICE ("cpu32", cpu32, "cpu32", "cpu32", cpu32, isa_cpu32, FL_MMU) - - /* ColdFire CFV1 processor. */ --M68K_DEVICE ("51qe", mcf51qe, "51qe", "51qe", cfv1, isa_c, FL_CF_USP) -+/* For historical reasons, the 51 multilib is named 51qe. */ -+M68K_DEVICE ("51", mcf51, "51", "51qe", cfv1, isa_c, FL_CF_USP) -+M68K_DEVICE ("51ac", mcf51ac, "51", "51qe", cfv1, isa_c, FL_CF_USP) -+M68K_DEVICE ("51cn", mcf51cn, "51", "51qe", cfv1, isa_c, FL_CF_USP) -+M68K_DEVICE ("51em", mcf51em, "51", "51qe", cfv1, isa_c, FL_CF_USP | FL_CF_MAC) -+M68K_DEVICE ("51jm", mcf51jm, "51", "51qe", cfv1, isa_c, FL_CF_USP) -+M68K_DEVICE ("51qe", mcf51qe, "51", "51qe", cfv1, isa_c, FL_CF_USP) - - /* ColdFire CFV2 processors. */ - M68K_DEVICE ("5202", mcf5202, "5206", "5206", cfv2, isa_a, 0) -@@ -97,6 +103,7 @@ - M68K_DEVICE ("5213", mcf5213, "5213", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) - M68K_DEVICE ("5214", mcf5214, "5216", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) - M68K_DEVICE ("5216", mcf5216, "5216", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -+M68K_DEVICE ("5221x", mcf5221x, "5221x", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) - M68K_DEVICE ("52221", mcf52221, "52223", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) - M68K_DEVICE ("52223", mcf52223, "52223", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) - M68K_DEVICE ("52230", mcf52230, "52235", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -@@ -107,6 +114,14 @@ - M68K_DEVICE ("52235", mcf52235, "52235", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) - M68K_DEVICE ("5224", mcf5224, "5225", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) - M68K_DEVICE ("5225", mcf5225, "5225", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) -+M68K_DEVICE ("52252", mcf52252, "52259", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -+M68K_DEVICE ("52254", mcf52254, "52259", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -+M68K_DEVICE ("52255", mcf52255, "52259", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -+M68K_DEVICE ("52256", mcf52256, "52259", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -+M68K_DEVICE ("52258", mcf52258, "52259", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -+M68K_DEVICE ("52259", mcf52259, "52259", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -+M68K_DEVICE ("52274", mcf52274, "52277", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -+M68K_DEVICE ("52277", mcf52277, "52277", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) - M68K_DEVICE ("5232", mcf5232, "5235", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) - M68K_DEVICE ("5233", mcf5233, "5235", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) - M68K_DEVICE ("5234", mcf5234, "5235", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -@@ -126,6 +141,13 @@ - M68K_DEVICE ("528x", mcf528x, "5282", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) - - /* CFV3 processors. */ -+M68K_DEVICE ("53011", mcf53011, "53017", "5329", cfv3, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -+M68K_DEVICE ("53012", mcf53012, "53017", "5329", cfv3, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -+M68K_DEVICE ("53013", mcf53013, "53017", "5329", cfv3, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -+M68K_DEVICE ("53014", mcf53014, "53017", "5329", cfv3, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -+M68K_DEVICE ("53015", mcf53015, "53017", "5329", cfv3, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -+M68K_DEVICE ("53016", mcf53016, "53017", "5329", cfv3, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -+M68K_DEVICE ("53017", mcf53017, "53017", "5329", cfv3, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) - M68K_DEVICE ("5307", mcf5307, "5307", "5307", cfv3, isa_a, FL_CF_HWDIV | FL_CF_MAC) - M68K_DEVICE ("5327", mcf5327, "5329", "5329", cfv3, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) - M68K_DEVICE ("5328", mcf5328, "5329", "5329", cfv3, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -@@ -137,12 +159,17 @@ - - /* CFV4/CFV4e processors. */ - M68K_DEVICE ("5407", mcf5407, "5407", "5407", cfv4, isa_b, FL_CF_MAC) --M68K_DEVICE ("54450", mcf54450, "54455", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU) --M68K_DEVICE ("54451", mcf54451, "54455", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU) --M68K_DEVICE ("54452", mcf54452, "54455", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU) --M68K_DEVICE ("54453", mcf54453, "54455", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU) --M68K_DEVICE ("54454", mcf54454, "54455", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU) --M68K_DEVICE ("54455", mcf54455, "54455", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU) -+M68K_DEVICE ("54410", mcf54410, "54418", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU | FL_UCLINUX) -+M68K_DEVICE ("54415", mcf54415, "54418", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU | FL_UCLINUX) -+M68K_DEVICE ("54416", mcf54416, "54418", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU | FL_UCLINUX) -+M68K_DEVICE ("54417", mcf54417, "54418", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU | FL_UCLINUX) -+M68K_DEVICE ("54418", mcf54418, "54418", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU | FL_UCLINUX) -+M68K_DEVICE ("54450", mcf54450, "54455", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU | FL_UCLINUX) -+M68K_DEVICE ("54451", mcf54451, "54455", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU | FL_UCLINUX) -+M68K_DEVICE ("54452", mcf54452, "54455", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU | FL_UCLINUX) -+M68K_DEVICE ("54453", mcf54453, "54455", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU | FL_UCLINUX) -+M68K_DEVICE ("54454", mcf54454, "54455", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU | FL_UCLINUX) -+M68K_DEVICE ("54455", mcf54455, "54455", "54455", cfv4, isa_c, FL_CF_HWDIV | FL_CF_USP | FL_CF_EMAC | FL_MMU | FL_UCLINUX) - M68K_DEVICE ("5470", mcf5470, "5475", "5475", cfv4e, isa_b, FL_CF_USP | FL_CF_EMAC | FL_CF_FPU | FL_MMU) - M68K_DEVICE ("5471", mcf5471, "5475", "5475", cfv4e, isa_b, FL_CF_USP | FL_CF_EMAC | FL_CF_FPU | FL_MMU) - M68K_DEVICE ("5472", mcf5472, "5475", "5475", cfv4e, isa_b, FL_CF_USP | FL_CF_EMAC | FL_CF_FPU | FL_MMU) ---- a/gcc/config/m68k/m68k.h -+++ b/gcc/config/m68k/m68k.h -@@ -232,6 +232,7 @@ - #define FL_ISA_C (1 << 16) - #define FL_FIDOA (1 << 17) - #define FL_MMU 0 /* Used by multilib machinery. */ -+#define FL_UCLINUX 0 /* Used by multilib machinery. */ - - #define TARGET_68010 ((m68k_cpu_flags & FL_ISA_68010) != 0) - #define TARGET_68020 ((m68k_cpu_flags & FL_ISA_68020) != 0) -@@ -501,7 +502,8 @@ - - extern enum reg_class regno_reg_class[]; - #define REGNO_REG_CLASS(REGNO) (regno_reg_class[(REGNO)]) --#define INDEX_REG_CLASS GENERAL_REGS -+#define MODE_INDEX_REG_CLASS(MODE) \ -+ (MODE_OK_FOR_INDEX_P (MODE) ? GENERAL_REGS : NO_REGS) - #define BASE_REG_CLASS ADDR_REGS - - #define PREFERRED_RELOAD_CLASS(X,CLASS) \ -@@ -644,7 +646,7 @@ - (though the operand list is empty). */ - #define TRANSFER_FROM_TRAMPOLINE \ - void \ --__transfer_from_trampoline () \ -+__transfer_from_trampoline (void) \ - { \ - register char *a0 asm (M68K_STATIC_CHAIN_REG_NAME); \ - asm (GLOBAL_ASM_OP "___trampoline"); \ -@@ -675,6 +677,10 @@ - #define HAVE_POST_INCREMENT 1 - #define HAVE_PRE_DECREMENT 1 - -+/* Return true if addresses of mode MODE can have an index register. */ -+#define MODE_OK_FOR_INDEX_P(MODE) \ -+ (!TARGET_COLDFIRE_FPU || GET_MODE_CLASS (MODE) != MODE_FLOAT) -+ - /* Macros to check register numbers against specific register classes. */ - - /* True for data registers, D0 through D7. */ -@@ -689,9 +695,10 @@ - /* True for floating point registers, FP0 through FP7. */ - #define FP_REGNO_P(REGNO) IN_RANGE (REGNO, 16, 23) - --#define REGNO_OK_FOR_INDEX_P(REGNO) \ -- (INT_REGNO_P (REGNO) \ -- || INT_REGNO_P (reg_renumber[REGNO])) -+#define REGNO_MODE_OK_FOR_INDEX_P(REGNO, MODE) \ -+ (MODE_OK_FOR_INDEX_P (MODE) \ -+ && (INT_REGNO_P (REGNO) \ -+ || INT_REGNO_P (reg_renumber[REGNO]))) - - #define REGNO_OK_FOR_BASE_P(REGNO) \ - (ADDRESS_REGNO_P (REGNO) \ -@@ -751,13 +758,14 @@ - - #define LEGITIMATE_PIC_OPERAND_P(X) \ - (!symbolic_operand (X, VOIDmode) \ -- || (TARGET_PCREL && REG_STRICT_P)) -+ || (TARGET_PCREL && REG_STRICT_P) \ -+ || m68k_tls_reference_p (X, true)) - - #define REG_OK_FOR_BASE_P(X) \ - m68k_legitimate_base_reg_p (X, REG_STRICT_P) - --#define REG_OK_FOR_INDEX_P(X) \ -- m68k_legitimate_index_reg_p (X, REG_STRICT_P) -+#define REG_MODE_OK_FOR_INDEX_P(X, MODE) \ -+ m68k_legitimate_index_reg_p (MODE, X, REG_STRICT_P) - - #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ - do \ -@@ -770,52 +778,19 @@ - /* This address is OK as it stands. */ - #define PIC_CASE_VECTOR_ADDRESS(index) index - --/* For the 68000, we handle X+REG by loading X into a register R and -- using R+REG. R will go in an address reg and indexing will be used. -- However, if REG is a broken-out memory address or multiplication, -- nothing needs to be done because REG can certainly go in an address reg. */ --#define COPY_ONCE(Y) if (!copied) { Y = copy_rtx (Y); copied = ch = 1; } --#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ --{ register int ch = (X) != (OLDX); \ -- if (GET_CODE (X) == PLUS) \ -- { int copied = 0; \ -- if (GET_CODE (XEXP (X, 0)) == MULT) \ -- { COPY_ONCE (X); XEXP (X, 0) = force_operand (XEXP (X, 0), 0);} \ -- if (GET_CODE (XEXP (X, 1)) == MULT) \ -- { COPY_ONCE (X); XEXP (X, 1) = force_operand (XEXP (X, 1), 0);} \ -- if (ch && GET_CODE (XEXP (X, 1)) == REG \ -- && GET_CODE (XEXP (X, 0)) == REG) \ -- { if (TARGET_COLDFIRE_FPU \ -- && GET_MODE_CLASS (MODE) == MODE_FLOAT) \ -- { COPY_ONCE (X); X = force_operand (X, 0);} \ -- goto WIN; } \ -- if (ch) { GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); } \ -- if (GET_CODE (XEXP (X, 0)) == REG \ -- || (GET_CODE (XEXP (X, 0)) == SIGN_EXTEND \ -- && GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \ -- && GET_MODE (XEXP (XEXP (X, 0), 0)) == HImode)) \ -- { register rtx temp = gen_reg_rtx (Pmode); \ -- register rtx val = force_operand (XEXP (X, 1), 0); \ -- emit_move_insn (temp, val); \ -- COPY_ONCE (X); \ -- XEXP (X, 1) = temp; \ -- if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT \ -- && GET_CODE (XEXP (X, 0)) == REG) \ -- X = force_operand (X, 0); \ -- goto WIN; } \ -- else if (GET_CODE (XEXP (X, 1)) == REG \ -- || (GET_CODE (XEXP (X, 1)) == SIGN_EXTEND \ -- && GET_CODE (XEXP (XEXP (X, 1), 0)) == REG \ -- && GET_MODE (XEXP (XEXP (X, 1), 0)) == HImode)) \ -- { register rtx temp = gen_reg_rtx (Pmode); \ -- register rtx val = force_operand (XEXP (X, 0), 0); \ -- emit_move_insn (temp, val); \ -- COPY_ONCE (X); \ -- XEXP (X, 0) = temp; \ -- if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT \ -- && GET_CODE (XEXP (X, 1)) == REG) \ -- X = force_operand (X, 0); \ -- goto WIN; }}} -+#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ -+do { \ -+ rtx __x; \ -+ \ -+ __x = m68k_legitimize_address (X, OLDX, MODE); \ -+ if (__x != NULL_RTX) \ -+ { \ -+ X = __x; \ -+ \ -+ if (memory_address_p (MODE, X)) \ -+ goto WIN; \ -+ } \ -+} while (0) - - /* On the 68000, only predecrement and postincrement address depend thus - (the amount of decrement or increment being the length of the operand). -@@ -1028,6 +1003,9 @@ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%u\n", (int)(ROUNDED))) - -+#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \ -+ m68k_final_prescan_insn (INSN, OPVEC, NOPERANDS) -+ - /* On the 68000, we use several CODE characters: - '.' for dot needed in Motorola-style opcode names. - '-' for an operand pushing on the stack: ---- a/gcc/config/m68k/m68k.md -+++ b/gcc/config/m68k/m68k.md -@@ -116,7 +116,8 @@ - (UNSPEC_GOT 3) - (UNSPEC_IB 4) - (UNSPEC_TIE 5) -- (UNSPEC_GOTOFF 6) -+ (UNSPEC_RELOC16 6) -+ (UNSPEC_RELOC32 7) - ]) - - ;; UNSPEC_VOLATILE usage: -@@ -414,7 +415,7 @@ - - (define_insn "tst<mode>_cf" - [(set (cc0) -- (match_operand:FP 0 "general_operand" "f<FP:dreg><Q>U"))] -+ (match_operand:FP 0 "general_operand" "f<FP:dreg>m"))] - "TARGET_COLDFIRE_FPU" - { - cc_status.flags = CC_IN_68881; -@@ -570,8 +571,8 @@ - - (define_insn "*cmp<mode>_cf" - [(set (cc0) -- (compare (match_operand:FP 0 "fp_src_operand" "f,f,<FP:dreg><Q>U") -- (match_operand:FP 1 "fp_src_operand" "f,<FP:dreg><Q>U,f")))] -+ (compare (match_operand:FP 0 "fp_src_operand" "f,f,<FP:dreg>m") -+ (match_operand:FP 1 "fp_src_operand" "f,<FP:dreg>m,f")))] - "TARGET_COLDFIRE_FPU - && (register_operand (operands[0], <MODE>mode) - || register_operand (operands[1], <MODE>mode))" -@@ -779,7 +780,41 @@ - { - rtx tmp, base, offset; - -- if (flag_pic && !TARGET_PCREL && symbolic_operand (operands[1], SImode)) -+ /* Recognize the case where operand[1] is a reference to thread-local -+ data and load its address to a register. */ -+ if (!TARGET_PCREL && m68k_tls_reference_p (operands[1], false)) -+ { -+ rtx tmp = operands[1]; -+ rtx addend = NULL; -+ -+ if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS) -+ { -+ addend = XEXP (XEXP (tmp, 0), 1); -+ tmp = XEXP (XEXP (tmp, 0), 0); -+ } -+ -+ gcc_assert (GET_CODE (tmp) == SYMBOL_REF); -+ gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0); -+ -+ tmp = m68k_legitimize_tls_address (tmp); -+ -+ if (addend) -+ { -+ if (!REG_P (tmp)) -+ { -+ rtx reg; -+ -+ reg = gen_reg_rtx (Pmode); -+ emit_move_insn (reg, tmp); -+ tmp = reg; -+ } -+ -+ tmp = gen_rtx_PLUS (SImode, tmp, addend); -+ } -+ -+ operands[1] = tmp; -+ } -+ else if (flag_pic && !TARGET_PCREL && symbolic_operand (operands[1], SImode)) - { - /* The source is an address which requires PIC relocation. - Call legitimize_pic_address with the source, mode, and a relocation -@@ -1070,10 +1105,8 @@ - ;; SFmode MEMs are restricted to modes 2-4 if TARGET_COLDFIRE_FPU. - ;; The move instructions can handle all combinations. - (define_insn "movsf_cf_hard" -- [(set (match_operand:SF 0 "nonimmediate_operand" "=r<Q>U, f, f,mr,f,r<Q>,f --,m") -- (match_operand:SF 1 "general_operand" " f, r<Q>U,f,rm,F,F, m --,f"))] -+ [(set (match_operand:SF 0 "nonimmediate_operand" "=rm,f, f,rm,f,r<Q>,f,m") -+ (match_operand:SF 1 "general_operand" " f, rm,f,rm,F,F, m,f"))] - "TARGET_COLDFIRE_FPU" - { - if (which_alternative == 4 || which_alternative == 5) { -@@ -1215,8 +1248,8 @@ - }) - - (define_insn "movdf_cf_hard" -- [(set (match_operand:DF 0 "nonimmediate_operand" "=f, <Q>U,r,f,r,r,m,f") -- (match_operand:DF 1 "general_operand" " f<Q>U,f, f,r,r,m,r,E"))] -+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f, m,r,f,r,r,m,f") -+ (match_operand:DF 1 "general_operand" " fm,f,f,r,r,m,r,E"))] - "TARGET_COLDFIRE_FPU" - { - rtx xoperands[3]; -@@ -1857,7 +1890,7 @@ - (define_insn "extendsfdf2_cf" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f") - (float_extend:DF -- (match_operand:SF 1 "general_operand" "f,<Q>U")))] -+ (match_operand:SF 1 "general_operand" "f,m")))] - "TARGET_COLDFIRE_FPU" - { - if (FP_REG_P (operands[0]) && FP_REG_P (operands[1])) -@@ -1897,9 +1930,9 @@ - }) - - (define_insn "truncdfsf2_cf" -- [(set (match_operand:SF 0 "nonimmediate_operand" "=f,d<Q>U") -+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,dm") - (float_truncate:SF -- (match_operand:DF 1 "general_operand" "<Q>U,f")))] -+ (match_operand:DF 1 "general_operand" "m,f")))] - "TARGET_COLDFIRE_FPU" - "@ - fsmove%.d %1,%0 -@@ -2045,7 +2078,7 @@ - - (define_insn "ftrunc<mode>2_cf" - [(set (match_operand:FP 0 "nonimmediate_operand" "=f") -- (fix:FP (match_operand:FP 1 "general_operand" "f<FP:dreg><Q>U")))] -+ (fix:FP (match_operand:FP 1 "general_operand" "f<FP:dreg>m")))] - "TARGET_COLDFIRE_FPU" - { - if (FP_REG_P (operands[1])) -@@ -2338,9 +2371,9 @@ - "* return output_addsi3 (operands);") - - (define_insn_and_split "*addsi3_5200" -- [(set (match_operand:SI 0 "nonimmediate_operand" "=mr,mr,a,m,r, ?a, ?a,?a,?a") -- (plus:SI (match_operand:SI 1 "general_operand" "%0, 0, 0,0,0, a, a, r, a") -- (match_operand:SI 2 "general_src_operand" " I, L, J,d,mrKi,Cj, r, a, J")))] -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=mr,mr,a, m,r, ?a, ?a,?a,?a") -+ (plus:SI (match_operand:SI 1 "general_operand" "%0, 0, 0, 0,0, a, a, r, a") -+ (match_operand:SI 2 "general_src_operand" " I, L, JCu,d,mrKi,Cj, r, a, JCu")))] - "TARGET_COLDFIRE" - { - switch (which_alternative) -@@ -2382,9 +2415,9 @@ - (plus:SI (match_dup 0) - (match_dup 1)))] - "" -- [(set_attr "type" "aluq_l,aluq_l,lea,alu_l,alu_l,*,lea,lea,lea") -- (set_attr "opy" "2,2,*,2,2,*,*,*,*") -- (set_attr "opy_type" "*,*,mem5,*,*,*,mem6,mem6,mem5")]) -+ [(set_attr "type" "aluq_l,aluq_l,lea, alu_l,alu_l,*,lea, lea, lea") -+ (set_attr "opy" "2, 2, *, 2, 2, *,*, *, *") -+ (set_attr "opy_type" "*, *, mem5,*, *, *,mem6,mem6,mem5")]) - - (define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=a") -@@ -2666,7 +2699,7 @@ - (define_insn "add<mode>3_cf" - [(set (match_operand:FP 0 "nonimmediate_operand" "=f") - (plus:FP (match_operand:FP 1 "general_operand" "%0") -- (match_operand:FP 2 "general_operand" "f<FP:dreg><Q>U")))] -+ (match_operand:FP 2 "general_operand" "f<FP:dreg>m")))] - "TARGET_COLDFIRE_FPU" - { - if (FP_REG_P (operands[2])) -@@ -2889,7 +2922,7 @@ - (define_insn "sub<mode>3_cf" - [(set (match_operand:FP 0 "nonimmediate_operand" "=f") - (minus:FP (match_operand:FP 1 "general_operand" "0") -- (match_operand:FP 2 "general_operand" "f<FP:dreg><Q>U")))] -+ (match_operand:FP 2 "general_operand" "f<FP:dreg>m")))] - "TARGET_COLDFIRE_FPU" - { - if (FP_REG_P (operands[2])) -@@ -3245,7 +3278,7 @@ - (define_insn "fmul<mode>3_cf" - [(set (match_operand:FP 0 "nonimmediate_operand" "=f") - (mult:FP (match_operand:FP 1 "general_operand" "%0") -- (match_operand:FP 2 "general_operand" "f<Q>U<FP:dreg>")))] -+ (match_operand:FP 2 "general_operand" "fm<FP:dreg>")))] - "TARGET_COLDFIRE_FPU" - { - if (FP_REG_P (operands[2])) -@@ -3315,7 +3348,7 @@ - (define_insn "div<mode>3_cf" - [(set (match_operand:FP 0 "nonimmediate_operand" "=f") - (div:FP (match_operand:FP 1 "general_operand" "0") -- (match_operand:FP 2 "general_operand" "f<Q>U<FP:dreg>")))] -+ (match_operand:FP 2 "general_operand" "fm<FP:dreg>")))] - "TARGET_COLDFIRE_FPU" - { - if (FP_REG_P (operands[2])) -@@ -4163,7 +4196,7 @@ - - (define_insn "neg<mode>2_cf" - [(set (match_operand:FP 0 "nonimmediate_operand" "=f,d") -- (neg:FP (match_operand:FP 1 "general_operand" "f<FP:dreg><Q>U,0")))] -+ (neg:FP (match_operand:FP 1 "general_operand" "f<FP:dreg>m,0")))] - "TARGET_COLDFIRE_FPU" - { - if (DATA_REG_P (operands[0])) -@@ -4197,7 +4230,7 @@ - - (define_insn "sqrt<mode>2_cf" - [(set (match_operand:FP 0 "nonimmediate_operand" "=f") -- (sqrt:FP (match_operand:FP 1 "general_operand" "f<FP:dreg><Q>U")))] -+ (sqrt:FP (match_operand:FP 1 "general_operand" "f<FP:dreg>m")))] - "TARGET_COLDFIRE_FPU" - { - if (FP_REG_P (operands[1])) -@@ -4316,7 +4349,7 @@ - - (define_insn "abs<mode>2_cf" - [(set (match_operand:FP 0 "nonimmediate_operand" "=f,d") -- (abs:FP (match_operand:FP 1 "general_operand" "f<FP:dreg><Q>U,0")))] -+ (abs:FP (match_operand:FP 1 "general_operand" "f<FP:dreg>m,0")))] - "TARGET_COLDFIRE_FPU" - { - if (DATA_REG_P (operands[0])) ---- a/gcc/config/m68k/m68k.opt -+++ b/gcc/config/m68k/m68k.opt -@@ -182,3 +182,7 @@ - mxgot - Target Report Mask(XGOT) - Support more than 8192 GOT entries on ColdFire -+ -+mxtls -+Target Report Mask(XTLS) -+Support TLS segment larger than 64K ---- a/gcc/config/m68k/m68k-protos.h -+++ b/gcc/config/m68k/m68k-protos.h -@@ -54,19 +54,27 @@ - extern bool m68k_output_addr_const_extra (FILE *, rtx); - extern void notice_update_cc (rtx, rtx); - extern bool m68k_legitimate_base_reg_p (rtx, bool); --extern bool m68k_legitimate_index_reg_p (rtx, bool); -+extern bool m68k_legitimate_index_reg_p (enum machine_mode, rtx, bool); - extern bool m68k_illegitimate_symbolic_constant_p (rtx); - extern bool m68k_legitimate_address_p (enum machine_mode, rtx, bool); - extern bool m68k_matches_q_p (rtx); - extern bool m68k_matches_u_p (rtx); - extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx); -+extern rtx m68k_legitimize_tls_address (rtx); -+extern bool m68k_tls_reference_p (rtx, bool); -+extern rtx m68k_legitimize_address (rtx, rtx, enum machine_mode); - extern int valid_dbcc_comparison_p_2 (rtx, enum machine_mode); - extern rtx m68k_libcall_value (enum machine_mode); - extern rtx m68k_function_value (const_tree, const_tree); - extern int emit_move_sequence (rtx *, enum machine_mode, rtx); - extern bool m68k_movem_pattern_p (rtx, rtx, HOST_WIDE_INT, bool); - extern const char *m68k_output_movem (rtx *, rtx, HOST_WIDE_INT, bool); -+extern void m68k_final_prescan_insn (rtx, rtx *, int); - -+/* Functions from m68k.c used in constraints.md. */ -+extern rtx m68k_unwrap_symbol (rtx, bool); -+ -+/* Functions from m68k.c used in genattrtab. */ - #ifdef HAVE_ATTR_cpu - extern enum attr_cpu m68k_sched_cpu; - extern enum attr_mac m68k_sched_mac; ---- a/gcc/config/m68k/predicates.md -+++ b/gcc/config/m68k/predicates.md -@@ -130,7 +130,9 @@ - (match_code "sign_extend,zero_extend")) - - ;; Returns true if OP is either a symbol reference or a sum of a --;; symbol reference and a constant. -+;; symbol reference and a constant. This predicate is for "raw" -+;; symbol references not yet processed by legitimize*_address, -+;; hence we do not handle UNSPEC_{XGOT, TLS, XTLS} here. - - (define_predicate "symbolic_operand" - (match_code "symbol_ref,label_ref,const") ---- a/gcc/config/m68k/t-uclinux -+++ b/gcc/config/m68k/t-uclinux -@@ -1,8 +1,8 @@ - # crti and crtn are provided by uClibc. - EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o - --# Only include multilibs for the 68020 and for CPUs without an MMU. --M68K_MLIB_CPU += && (MLIB == "68020" || !match(FLAGS, "FL_MMU")) -+# Include multilibs for CPUs without an MMU or with FL_UCLINUX -+M68K_MLIB_CPU += && (!match(FLAGS, "FL_MMU") || match(FLAGS, "FL_UCLINUX")) - - # Add multilibs for execute-in-place and shared-library code. - M68K_MLIB_OPTIONS += msep-data/mid-shared-library ---- a/gcc/config/mips/74k.md -+++ b/gcc/config/mips/74k.md -@@ -118,8 +118,7 @@ - ;; stores - (define_insn_reservation "r74k_int_store" 1 - (and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2") -- (and (eq_attr "type" "store") -- (eq_attr "mode" "!unknown"))) -+ (eq_attr "type" "store")) - "r74k_agen") - - -@@ -145,33 +144,123 @@ - ;; load->load base: 4 cycles - ;; load->store base: 4 cycles - (define_bypass 4 "r74k_int_load" "r74k_int_load") --(define_bypass 4 "r74k_int_load" "r74k_int_store" "!store_data_bypass_p") -+(define_bypass 4 "r74k_int_load" "r74k_int_store" "!mips_store_data_bypass_p") - - ;; logical/move/slt/signext->next use : 1 cycles (Default) - ;; logical/move/slt/signext->load base: 2 cycles - ;; logical/move/slt/signext->store base: 2 cycles - (define_bypass 2 "r74k_int_logical" "r74k_int_load") --(define_bypass 2 "r74k_int_logical" "r74k_int_store" "!store_data_bypass_p") -+(define_bypass 2 "r74k_int_logical" "r74k_int_store" -+ "!mips_store_data_bypass_p") - - ;; arith->next use : 2 cycles (Default) - ;; arith->load base: 3 cycles - ;; arith->store base: 3 cycles - (define_bypass 3 "r74k_int_arith" "r74k_int_load") --(define_bypass 3 "r74k_int_arith" "r74k_int_store" "!store_data_bypass_p") -+(define_bypass 3 "r74k_int_arith" "r74k_int_store" "!mips_store_data_bypass_p") - - ;; cmove->next use : 4 cycles (Default) - ;; cmove->load base: 5 cycles - ;; cmove->store base: 5 cycles - (define_bypass 5 "r74k_int_cmove" "r74k_int_load") --(define_bypass 5 "r74k_int_cmove" "r74k_int_store" "!store_data_bypass_p") -+(define_bypass 5 "r74k_int_cmove" "r74k_int_store" -+ "!mips_store_data_bypass_p") - - ;; mult/madd/msub->int_mfhilo : 4 cycles (default) - ;; mult->madd/msub : 1 cycles - ;; madd/msub->madd/msub : 1 cycles --(define_bypass 1 "r74k_int_mult,r74k_int_mul3" "r74k_int_madd" -- "mips_linked_madd_p") --(define_bypass 1 "r74k_int_madd" "r74k_int_madd" -- "mips_linked_madd_p") -+(define_bypass 1 "r74k_int_mult" "r74k_int_madd") -+(define_bypass 1 "r74k_int_madd" "r74k_int_madd") -+ -+(define_bypass 1 "r74k_int_mul3" "r74k_int_madd" -+ "mips_mult_madd_chain_bypass_p") -+ -+ -+;; -------------------------------------------------------------- -+;; DSP instructins -+;; -------------------------------------------------------------- -+ -+;; Non-saturating insn have the same latency as normal ALU operations, -+(define_insn_reservation "r74k_dsp_alu" 2 -+ (and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2") -+ (eq_attr "type" "dspalu")) -+ "r74k_alu") -+ -+;; Saturating insn takes an extra cycle. -+(define_insn_reservation "r74k_dsp_alu_sat" 3 -+ (and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2") -+ (eq_attr "type" "dspalusat")) -+ "r74k_alu") -+ -+;; dpaq_s, dpau, dpsq_s, dpsu, maq_s, mulsaq -+;; - delivers result to hi/lo in 6 cycle (bypass at M4) -+(define_insn_reservation "r74k_dsp_mac" 6 -+ (and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2") -+ (eq_attr "type" "dspmac")) -+ "r74k_alu+r74k_mul") -+ -+;; dpaq_sa, dpsq_sa, maq_sa -+;; - delivers result to hi/lo in 7 cycle (bypass at WB) -+(define_insn_reservation "r74k_dsp_mac_sat" 7 -+ (and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2") -+ (eq_attr "type" "dspmacsat")) -+ "r74k_alu+r74k_mul") -+ -+;; extp, extpdp, extpdpv, extpv, extr, extrv -+;; - same latency as "mul" -+(define_insn_reservation "r74k_dsp_acc_ext" 7 -+ (and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2") -+ (eq_attr "type" "accext")) -+ "r74k_alu+r74k_mul") -+ -+;; mthlip, shilo, shilov -+;; - same latency as "mul" -+(define_insn_reservation "r74k_dsp_acc_mod" 7 -+ (and (eq_attr "cpu" "74kc,74kf2_1,74kf1_1,74kf3_2") -+ (eq_attr "type" "accmod")) -+ "r74k_alu+r74k_mul") -+ -+;; dspalu ->load/store base -+;; dspalusat->load/store base -+;; - we should never see these in real life. -+ -+;; dsp_mac->dsp_mac : 1 cycles (repeat rate of 1) -+;; dsp_mac->dsp_mac_sat : 1 cycles (repeat rate of 1) -+(define_bypass 1 "r74k_dsp_mac" "r74k_dsp_mac") -+(define_bypass 1 "r74k_dsp_mac" "r74k_dsp_mac_sat") -+ -+;; dsp_mac_sat->dsp_mac_sat : 2 cycles (repeat rate of 2) -+;; dsp_mac_sat->dsp_mac : 2 cycles (repeat rate of 2) -+(define_bypass 2 "r74k_dsp_mac_sat" "r74k_dsp_mac_sat") -+(define_bypass 2 "r74k_dsp_mac_sat" "r74k_dsp_mac") -+ -+(define_bypass 1 "r74k_int_mult" "r74k_dsp_mac") -+(define_bypass 1 "r74k_int_mult" "r74k_dsp_mac_sat") -+ -+;; Before reload, all multiplier is registered as imul3 (which has a long -+;; latency). We temporary jig the latency such that the macc groups -+;; are scheduled closely together during the first scheduler pass. -+(define_bypass 1 "r74k_int_mul3" "r74k_dsp_mac" -+ "mips_mult_madd_chain_bypass_p") -+(define_bypass 1 "r74k_int_mul3" "r74k_dsp_mac_sat" -+ "mips_mult_madd_chain_bypass_p") -+ -+;; Assuming the following is true (bypass at M4) -+;; AP AF AM MB M1 M2 M3 M4 WB GR GC -+;; AP AF AM MB M1 M2 M3 M4 WB GR GC -+;; dsp_mac->dsp_acc_ext : 4 cycles -+;; dsp_mac->dsp_acc_mod : 4 cycles -+(define_bypass 4 "r74k_dsp_mac" "r74k_dsp_acc_ext") -+(define_bypass 4 "r74k_dsp_mac" "r74k_dsp_acc_mod") -+ -+;; Assuming the following is true (bypass at WB) -+;; AP AF AM MB M1 M2 M3 M4 WB GR GC -+;; AP AF AM MB M1 M2 M3 M4 WB GR GC -+;; dsp_mac_sat->dsp_acc_ext : 5 cycles -+;; dsp_mac_sat->dsp_acc_mod : 5 cycles -+(define_bypass 5 "r74k_dsp_mac_sat" "r74k_dsp_acc_ext") -+(define_bypass 5 "r74k_dsp_mac_sat" "r74k_dsp_acc_mod") -+ - - ;; -------------------------------------------------------------- - ;; Floating Point Instructions ---- /dev/null -+++ b/gcc/config/mips/crtfastmath.c -@@ -0,0 +1,53 @@ -+/* Copyright (C) 2008, 2009 Free Software Foundation, Inc. -+ -+ This file is part of GCC. -+ -+ GCC is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3, or (at your option) -+ any later version. -+ -+ GCC is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+ License for more details. -+ -+ Under Section 7 of GPL version 3, you are granted additional -+ permissions described in the GCC Runtime Library Exception, version -+ 3.1, as published by the Free Software Foundation. -+ -+ You should have received a copy of the GNU General Public License -+ and a copy of the GCC Runtime Library Exception along with this -+ program; see the files COPYING3 and COPYING.RUNTIME respectively. -+ If not, see <http://www.gnu.org/licenses/>. */ -+ -+#ifdef __mips_hard_float -+ -+/* flush denormalized numbers to zero */ -+#define _FPU_FLUSH_TZ 0x1000000 -+ -+/* rounding control */ -+#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ -+#define _FPU_RC_ZERO 0x1 -+#define _FPU_RC_UP 0x2 -+#define _FPU_RC_DOWN 0x3 -+ -+/* enable interrupts for IEEE exceptions */ -+#define _FPU_IEEE 0x00000F80 -+ -+/* Macros for accessing the hardware control word. */ -+#define _FPU_GETCW(cw) __asm__ ("cfc1 %0,$31" : "=r" (cw)) -+#define _FPU_SETCW(cw) __asm__ ("ctc1 %0,$31" : : "r" (cw)) -+ -+static void __attribute__((constructor)) -+set_fast_math (void) -+{ -+ unsigned int fcr; -+ -+ /* fastmath: flush to zero, round to nearest, ieee exceptions disabled */ -+ fcr = _FPU_FLUSH_TZ | _FPU_RC_NEAREST; -+ -+ _FPU_SETCW(fcr); -+} -+ -+#endif /* __mips_hard_float */ ---- a/gcc/config/mips/linux64.h -+++ b/gcc/config/mips/linux64.h -@@ -69,3 +69,9 @@ - ieee_quad_format is the default, but let's put this here to make - sure nobody thinks we just forgot to set it to something else. */ - #define MIPS_TFMODE_FORMAT mips_quad_format -+ -+/* Similar to standard Linux, but adding -ffast-math support. */ -+#undef ENDFILE_SPEC -+#define ENDFILE_SPEC \ -+ "%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \ -+ %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s" ---- a/gcc/config/mips/linux.h -+++ b/gcc/config/mips/linux.h -@@ -147,3 +147,17 @@ - #define DRIVER_SELF_SPECS \ - BASE_DRIVER_SELF_SPECS, \ - LINUX_DRIVER_SELF_SPECS -+ -+/* Similar to standard Linux, but adding -ffast-math support. */ -+#undef ENDFILE_SPEC -+#define ENDFILE_SPEC \ -+ "%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \ -+ %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s" -+ -+#undef SUBTARGET_OVERRIDE_OPTIONS -+#define SUBTARGET_OVERRIDE_OPTIONS \ -+do { \ -+ /* __thread_support is not supported by uClibc. */ \ -+ if (linux_uclibc) \ -+ targetm.have_tls = 0; \ -+} while (0) ---- a/gcc/config/mips/mips.c -+++ b/gcc/config/mips/mips.c -@@ -261,18 +261,29 @@ - /* Likewise FPR X. */ - unsigned int fmask; - -- /* The number of GPRs and FPRs saved. */ -+ /* Likewise doubleword accumulator X ($acX). */ -+ unsigned int acc_mask; -+ -+ /* The number of GPRs, FPRs, doubleword accumulators and COP0 -+ registers saved. */ - unsigned int num_gp; - unsigned int num_fp; -+ unsigned int num_acc; -+ unsigned int num_cop0_regs; - -- /* The offset of the topmost GPR and FPR save slots from the top of -- the frame, or zero if no such slots are needed. */ -+ /* The offset of the topmost GPR, FPR, accumulator and COP0-register -+ save slots from the top of the frame, or zero if no such slots are -+ needed. */ - HOST_WIDE_INT gp_save_offset; - HOST_WIDE_INT fp_save_offset; -+ HOST_WIDE_INT acc_save_offset; -+ HOST_WIDE_INT cop0_save_offset; - - /* Likewise, but giving offsets from the bottom of the frame. */ - HOST_WIDE_INT gp_sp_offset; - HOST_WIDE_INT fp_sp_offset; -+ HOST_WIDE_INT acc_sp_offset; -+ HOST_WIDE_INT cop0_sp_offset; - - /* The offset of arg_pointer_rtx from frame_pointer_rtx. */ - HOST_WIDE_INT arg_pointer_offset; -@@ -310,6 +321,20 @@ - /* True if we have emitted an instruction to initialize - mips16_gp_pseudo_rtx. */ - bool initialized_mips16_gp_pseudo_p; -+ -+ /* True if this is an interrupt handler. */ -+ bool interrupt_handler_p; -+ -+ /* True if this is an interrupt handler that uses shadow registers. */ -+ bool use_shadow_register_set_p; -+ -+ /* True if this is an interrupt handler that should keep interrupts -+ masked. */ -+ bool keep_interrupts_masked_p; -+ -+ /* True if this is an interrupt handler that should use DERET -+ instead of ERET. */ -+ bool use_debug_exception_return_p; - }; - - /* Information about a single argument. */ -@@ -542,9 +567,16 @@ - ALL_REGS, ALL_REGS, ALL_REGS, ALL_REGS - }; - -+#ifdef CVMX_SHARED_BSS_FLAGS -+static tree octeon_handle_cvmx_shared_attribute (tree *, tree, tree, int, bool *); -+#endif -+ - /* The value of TARGET_ATTRIBUTE_TABLE. */ - const struct attribute_spec mips_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ -+#ifdef CVMX_SHARED_BSS_FLAGS -+ { "cvmx_shared", 0, 0, true, false, false, octeon_handle_cvmx_shared_attribute }, -+#endif - { "long_call", 0, 0, false, true, true, NULL }, - { "far", 0, 0, false, true, true, NULL }, - { "near", 0, 0, false, true, true, NULL }, -@@ -554,6 +586,11 @@ - code generation but don't carry other semantics. */ - { "mips16", 0, 0, true, false, false, NULL }, - { "nomips16", 0, 0, true, false, false, NULL }, -+ /* Allow functions to be specified as interrupt handlers */ -+ { "interrupt", 0, 0, false, true, true, NULL }, -+ { "use_shadow_register_set", 0, 0, false, true, true, NULL }, -+ { "keep_interrupts_masked", 0, 0, false, true, true, NULL }, -+ { "use_debug_exception_return", 0, 0, false, true, true, NULL }, - { NULL, 0, 0, false, false, false, NULL } - }; - -@@ -659,6 +696,11 @@ - { "74kx", PROCESSOR_74KF1_1, 33, 0 }, - { "74kf3_2", PROCESSOR_74KF3_2, 33, 0 }, - -+ { "1004kc", PROCESSOR_24KC, 33, 0 }, /* 1004K with MT/DSP. */ -+ { "1004kf2_1", PROCESSOR_24KF2_1, 33, 0 }, -+ { "1004kf", PROCESSOR_24KF2_1, 33, 0 }, -+ { "1004kf1_1", PROCESSOR_24KF1_1, 33, 0 }, -+ - /* MIPS64 processors. */ - { "5kc", PROCESSOR_5KC, 64, 0 }, - { "5kf", PROCESSOR_5KF, 64, 0 }, -@@ -1064,13 +1106,7 @@ - DEFAULT_COSTS - }, - { /* XLR */ -- /* Need to replace first five with the costs of calling the appropriate -- libgcc routine. */ -- COSTS_N_INSNS (256), /* fp_add */ -- COSTS_N_INSNS (256), /* fp_mult_sf */ -- COSTS_N_INSNS (256), /* fp_mult_df */ -- COSTS_N_INSNS (256), /* fp_div_sf */ -- COSTS_N_INSNS (256), /* fp_div_df */ -+ SOFT_FP_COSTS, - COSTS_N_INSNS (8), /* int_mult_si */ - COSTS_N_INSNS (8), /* int_mult_di */ - COSTS_N_INSNS (72), /* int_div_si */ -@@ -1172,6 +1208,42 @@ - return lookup_attribute ("nomips16", DECL_ATTRIBUTES (decl)) != NULL; - } - -+/* Check if the interrupt attribute is set for a function. */ -+ -+static bool -+mips_interrupt_type_p (tree type) -+{ -+ return lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type)) != NULL; -+} -+ -+/* Check if the attribute to use shadow register set is set for a function. */ -+ -+static bool -+mips_use_shadow_register_set_p (tree type) -+{ -+ return lookup_attribute ("use_shadow_register_set", -+ TYPE_ATTRIBUTES (type)) != NULL; -+} -+ -+/* Check if the attribute to keep interrupts masked is set for a function. */ -+ -+static bool -+mips_keep_interrupts_masked_p (tree type) -+{ -+ return lookup_attribute ("keep_interrupts_masked", -+ TYPE_ATTRIBUTES (type)) != NULL; -+} -+ -+/* Check if the attribute to use debug exception return is set for -+ a function. */ -+ -+static bool -+mips_use_debug_exception_return_p (tree type) -+{ -+ return lookup_attribute ("use_debug_exception_return", -+ TYPE_ATTRIBUTES (type)) != NULL; -+} -+ - /* Return true if function DECL is a MIPS16 function. Return the ambient - setting if DECL is null. */ - -@@ -2795,7 +2867,7 @@ - mips_legitimize_address (rtx *xloc, enum machine_mode mode) - { - rtx base, addr; -- HOST_WIDE_INT offset; -+ HOST_WIDE_INT intval, high, offset; - - if (mips_tls_symbol_p (*xloc)) - { -@@ -2820,6 +2892,32 @@ - *xloc = mips_force_address (addr, mode); - return true; - } -+ -+ /* Handle references to constant addresses by loading the high part -+ into a register and using an offset for the low part. */ -+ if (GET_CODE (base) == CONST_INT) -+ { -+ intval = INTVAL (base); -+ high = trunc_int_for_mode (CONST_HIGH_PART (intval), Pmode); -+ offset = CONST_LOW_PART (intval); -+ /* Ignore cases in which a positive address would be accessed by a -+ negative offset from a negative address. The required wraparound -+ does not occur for 32-bit addresses on 64-bit targets, and it is -+ very unlikely that such an access would occur in real code anyway. -+ -+ If the low offset is not legitimate for MODE, prefer to load -+ the constant normally, instead of using mips_force_address on -+ the legitimized address. The latter option would cause us to -+ use (D)ADDIU unconditionally, but LUI/ORI is more efficient -+ than LUI/ADDIU on some targets. */ -+ if ((intval < 0 || high > 0) -+ && mips_valid_offset_p (GEN_INT (offset), mode)) -+ { -+ base = mips_force_temporary (NULL, GEN_INT (high)); -+ *xloc = plus_constant (base, offset); -+ return true; -+ } -+ } - return false; - } - -@@ -6188,6 +6286,11 @@ - if (!TARGET_SIBCALLS) - return false; - -+ /* Interrupt handlers need special epilogue code and therefore can't -+ use sibcalls. */ -+ if (mips_interrupt_type_p (TREE_TYPE (current_function_decl))) -+ return false; -+ - /* We can't do a sibcall if the called function is a MIPS16 function - because there is no direct "jx" instruction equivalent to "jalx" to - switch the ISA mode. We only care about cases where the sibling -@@ -6608,6 +6711,15 @@ - if (!mips_get_unaligned_mem (&src, width, bitpos, &left, &right)) - return false; - -+ if (ISA_HAS_UL_US) -+ { -+ if (GET_MODE (dest) == DImode) -+ emit_insn (gen_mov_uld (dest, src, left)); -+ else -+ emit_insn (gen_mov_ulw (dest, src, left)); -+ return true; -+ } -+ - temp = gen_reg_rtx (GET_MODE (dest)); - if (GET_MODE (dest) == DImode) - { -@@ -6642,6 +6754,16 @@ - - mode = mode_for_size (width, MODE_INT, 0); - src = gen_lowpart (mode, src); -+ -+ if (ISA_HAS_UL_US) -+ { -+ if (GET_MODE (src) == DImode) -+ emit_insn (gen_mov_usd (dest, src, left)); -+ else -+ emit_insn (gen_mov_usw (dest, src, left)); -+ return true; -+ } -+ - if (mode == DImode) - { - emit_insn (gen_mov_sdl (dest, src, left)); -@@ -7229,7 +7351,11 @@ - || (letter == 'L' && TARGET_BIG_ENDIAN) - || letter == 'D') - regno++; -- fprintf (file, "%s", reg_names[regno]); -+ /* We need to print $0 .. $31 for COP0 registers. */ -+ if (COP0_REG_P (regno)) -+ fprintf (file, "$%s", ®_names[regno][4]); -+ else -+ fprintf (file, "%s", reg_names[regno]); - } - break; - -@@ -7369,6 +7495,12 @@ - if (TARGET_ABICALLS || TARGET_VXWORKS_RTP) - return false; - -+#ifdef CVMX_SHARED_BSS_FLAGS -+ if (TARGET_OCTEON && TREE_CODE (decl) == VAR_DECL -+ && lookup_attribute ("cvmx_shared", DECL_ATTRIBUTES (decl))) -+ return false; -+#endif -+ - if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0) - { - const char *name; -@@ -7595,6 +7727,37 @@ - return NULL_RTX; - } - -+/* DSP ALU can bypass data with no delays for the following pairs. */ -+enum insn_code dspalu_bypass_table[][2] = -+{ -+ {CODE_FOR_mips_addsc, CODE_FOR_mips_addwc}, -+ {CODE_FOR_mips_cmpu_eq_qb, CODE_FOR_mips_pick_qb}, -+ {CODE_FOR_mips_cmpu_lt_qb, CODE_FOR_mips_pick_qb}, -+ {CODE_FOR_mips_cmpu_le_qb, CODE_FOR_mips_pick_qb}, -+ {CODE_FOR_mips_cmp_eq_ph, CODE_FOR_mips_pick_ph}, -+ {CODE_FOR_mips_cmp_lt_ph, CODE_FOR_mips_pick_ph}, -+ {CODE_FOR_mips_cmp_le_ph, CODE_FOR_mips_pick_ph}, -+ {CODE_FOR_mips_wrdsp, CODE_FOR_mips_insv} -+}; -+ -+int -+mips_dspalu_bypass_p (rtx out_insn, rtx in_insn) -+{ -+ int i; -+ int num_bypass = (sizeof (dspalu_bypass_table) -+ / (2 * sizeof (enum insn_code))); -+ enum insn_code out_icode = INSN_CODE (out_insn); -+ enum insn_code in_icode = INSN_CODE (in_insn); -+ -+ for (i = 0; i < num_bypass; i++) -+ { -+ if (out_icode == dspalu_bypass_table[i][0] -+ && in_icode == dspalu_bypass_table[i][1]) -+ return true; -+ } -+ -+ return false; -+} - /* Implement ASM_OUTPUT_ASCII. */ - - void -@@ -7819,11 +7982,19 @@ - "\t.previous\n", TARGET_LONG64 ? 64 : 32); - - #ifdef HAVE_AS_GNU_ATTRIBUTE -+#ifdef TARGET_MIPS_SDEMTK -+ fprintf (asm_out_file, "\t.gnu_attribute 4, %d\n", -+ (!TARGET_NO_FLOAT -+ ? (TARGET_HARD_FLOAT -+ ? (TARGET_DOUBLE_FLOAT -+ ? ((!TARGET_64BIT && TARGET_FLOAT64) ? 4 : 1) : 2) : 3) : 0)); -+#else - fprintf (asm_out_file, "\t.gnu_attribute 4, %d\n", - (TARGET_HARD_FLOAT_ABI - ? (TARGET_DOUBLE_FLOAT - ? ((!TARGET_64BIT && TARGET_FLOAT64) ? 4 : 1) : 2) : 3)); - #endif -+#endif - } - - /* If TARGET_ABICALLS, tell GAS to generate -KPIC code. */ -@@ -8436,12 +8607,53 @@ - return GLOBAL_POINTER_REGNUM; - } - -+/* Return true if REGNO is a register that is ordinarily call-clobbered -+ but must nevertheless be preserved by an interrupt handler. */ -+ -+static bool -+mips_interrupt_extra_call_saved_reg_p (unsigned int regno) -+{ -+ if (MD_REG_P (regno)) -+ return true; -+ -+ if (TARGET_DSP && DSP_ACC_REG_P (regno)) -+ return true; -+ -+ if (GP_REG_P (regno) && !cfun->machine->use_shadow_register_set_p) -+ { -+ /* $0 is hard-wired. */ -+ if (regno == GP_REG_FIRST) -+ return false; -+ -+ /* The interrupt handler can treat kernel registers as -+ scratch registers. */ -+ if (KERNEL_REG_P (regno)) -+ return false; -+ -+ /* The function will return the stack pointer to its original value -+ anyway. */ -+ if (regno == STACK_POINTER_REGNUM) -+ return false; -+ -+ /* Otherwise, return true for registers that aren't ordinarily -+ call-clobbered. */ -+ return call_really_used_regs[regno]; -+ } -+ -+ return false; -+} -+ - /* Return true if the current function should treat register REGNO - as call-saved. */ - - static bool - mips_cfun_call_saved_reg_p (unsigned int regno) - { -+ /* Interrupt handlers need to save extra registers. */ -+ if (cfun->machine->interrupt_handler_p -+ && mips_interrupt_extra_call_saved_reg_p (regno)) -+ return true; -+ - /* call_insns preserve $28 unless they explicitly say otherwise, - so call_really_used_regs[] treats $28 as call-saved. However, - we want the ABI property rather than the default call_insn -@@ -8490,6 +8702,13 @@ - if (regno == GP_REG_FIRST + 31 && mips16_cfun_returns_in_fpr_p ()) - return true; - -+ /* If REGNO is ordinarily call-clobbered, we must assume that any -+ called function could modify it. */ -+ if (cfun->machine->interrupt_handler_p -+ && !current_function_is_leaf -+ && mips_interrupt_extra_call_saved_reg_p (regno)) -+ return true; -+ - return false; - } - -@@ -8545,6 +8764,14 @@ - C | callee-allocated save area | - | for register varargs | - | | -+ +-------------------------------+ <-- frame_pointer_rtx -+ | | + cop0_sp_offset -+ | COP0 reg save area | + UNITS_PER_WORD -+ | | -+ +-------------------------------+ <-- frame_pointer_rtx + acc_sp_offset -+ | | + UNITS_PER_WORD -+ | accumulator save area | -+ | | - +-------------------------------+ <-- frame_pointer_rtx + fp_sp_offset - | | + UNITS_PER_HWFPVALUE - | FPR save area | -@@ -8588,6 +8815,28 @@ - HOST_WIDE_INT offset, size; - unsigned int regno, i; - -+ /* Set this function's interrupt properties. */ -+ if (mips_interrupt_type_p (TREE_TYPE (current_function_decl))) -+ { -+ if (!ISA_MIPS32R2) -+ error ("the %<interrupt%> attribute requires a MIPS32r2 processor"); -+ else if (TARGET_HARD_FLOAT) -+ error ("the %<interrupt%> attribute requires %<-msoft-float%>"); -+ else if (TARGET_MIPS16) -+ error ("interrupt handlers cannot be MIPS16 functions"); -+ else -+ { -+ cfun->machine->interrupt_handler_p = true; -+ cfun->machine->use_shadow_register_set_p = -+ mips_use_shadow_register_set_p (TREE_TYPE (current_function_decl)); -+ cfun->machine->keep_interrupts_masked_p = -+ mips_keep_interrupts_masked_p (TREE_TYPE (current_function_decl)); -+ cfun->machine->use_debug_exception_return_p = -+ mips_use_debug_exception_return_p (TREE_TYPE -+ (current_function_decl)); -+ } -+ } -+ - frame = &cfun->machine->frame; - memset (frame, 0, sizeof (*frame)); - size = get_frame_size (); -@@ -8657,7 +8906,7 @@ - } - - /* Find out which FPRs we need to save. This loop must iterate over -- the same space as its companion in mips_for_each_saved_reg. */ -+ the same space as its companion in mips_for_each_saved_gpr_and_fpr. */ - if (TARGET_HARD_FLOAT) - for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno += MAX_FPRS_PER_FMT) - if (mips_save_reg_p (regno)) -@@ -8673,6 +8922,47 @@ - frame->fp_sp_offset = offset - UNITS_PER_HWFPVALUE; - } - -+ /* Add in space for the interrupt context information. */ -+ if (cfun->machine->interrupt_handler_p) -+ { -+ /* Check HI/LO. */ -+ if (mips_save_reg_p (LO_REGNUM) || mips_save_reg_p (HI_REGNUM)) -+ { -+ frame->num_acc++; -+ frame->acc_mask |= (1 << 0); -+ } -+ -+ /* Check accumulators 1, 2, 3. */ -+ for (i = DSP_ACC_REG_FIRST; i <= DSP_ACC_REG_LAST; i += 2) -+ if (mips_save_reg_p (i) || mips_save_reg_p (i + 1)) -+ { -+ frame->num_acc++; -+ frame->acc_mask |= 1 << (((i - DSP_ACC_REG_FIRST) / 2) + 1); -+ } -+ -+ /* All interrupt context functions need space to preserve STATUS. */ -+ frame->num_cop0_regs++; -+ -+ /* If we don't keep interrupts masked, we need to save EPC. */ -+ if (!cfun->machine->keep_interrupts_masked_p) -+ frame->num_cop0_regs++; -+ } -+ -+ /* Move above the accumulator save area. */ -+ if (frame->num_acc > 0) -+ { -+ /* Each accumulator needs 2 words. */ -+ offset += frame->num_acc * 2 * UNITS_PER_WORD; -+ frame->acc_sp_offset = offset - UNITS_PER_WORD; -+ } -+ -+ /* Move above the COP0 register save area. */ -+ if (frame->num_cop0_regs > 0) -+ { -+ offset += frame->num_cop0_regs * UNITS_PER_WORD; -+ frame->cop0_sp_offset = offset - UNITS_PER_WORD; -+ } -+ - /* Move above the callee-allocated varargs save area. */ - offset += MIPS_STACK_ALIGN (cfun->machine->varargs_size); - frame->arg_pointer_offset = offset; -@@ -8686,6 +8976,10 @@ - frame->gp_save_offset = frame->gp_sp_offset - offset; - if (frame->fp_sp_offset > 0) - frame->fp_save_offset = frame->fp_sp_offset - offset; -+ if (frame->acc_sp_offset > 0) -+ frame->acc_save_offset = frame->acc_sp_offset - offset; -+ if (frame->num_cop0_regs > 0) -+ frame->cop0_save_offset = frame->cop0_sp_offset - offset; - - /* MIPS16 code offsets the frame pointer by the size of the outgoing - arguments. This tends to increase the chances of using unextended -@@ -8882,12 +9176,41 @@ - fn (gen_rtx_REG (mode, regno), mem); - } - -+/* Call FN for each accumlator that is saved by the current function. -+ SP_OFFSET is the offset of the current stack pointer from the start -+ of the frame. */ -+ -+static void -+mips_for_each_saved_acc (HOST_WIDE_INT sp_offset, mips_save_restore_fn fn) -+{ -+ HOST_WIDE_INT offset; -+ int regno; -+ -+ offset = cfun->machine->frame.acc_sp_offset - sp_offset; -+ if (BITSET_P (cfun->machine->frame.acc_mask, 0)) -+ { -+ mips_save_restore_reg (word_mode, LO_REGNUM, offset, fn); -+ offset -= UNITS_PER_WORD; -+ mips_save_restore_reg (word_mode, HI_REGNUM, offset, fn); -+ offset -= UNITS_PER_WORD; -+ } -+ -+ for (regno = DSP_ACC_REG_FIRST; regno <= DSP_ACC_REG_LAST; regno++) -+ if (BITSET_P (cfun->machine->frame.acc_mask, -+ ((regno - DSP_ACC_REG_FIRST) / 2) + 1)) -+ { -+ mips_save_restore_reg (word_mode, regno, offset, fn); -+ offset -= UNITS_PER_WORD; -+ } -+} -+ - /* Call FN for each register that is saved by the current function. - SP_OFFSET is the offset of the current stack pointer from the start - of the frame. */ - - static void --mips_for_each_saved_reg (HOST_WIDE_INT sp_offset, mips_save_restore_fn fn) -+mips_for_each_saved_gpr_and_fpr (HOST_WIDE_INT sp_offset, -+ mips_save_restore_fn fn) - { - enum machine_mode fpr_mode; - HOST_WIDE_INT offset; -@@ -9075,13 +9398,24 @@ - } - else - { -- if (TARGET_MIPS16 -- && REGNO (reg) != GP_REG_FIRST + 31 -- && !M16_REG_P (REGNO (reg))) -- { -- /* Save a non-MIPS16 register by moving it through a temporary. -- We don't need to do this for $31 since there's a special -- instruction for it. */ -+ if (REGNO (reg) == HI_REGNUM) -+ { -+ if (TARGET_64BIT) -+ emit_insn (gen_mfhidi_ti (MIPS_PROLOGUE_TEMP (DImode), -+ gen_rtx_REG (TImode, MD_REG_FIRST))); -+ else -+ emit_insn (gen_mfhisi_di (MIPS_PROLOGUE_TEMP (SImode), -+ gen_rtx_REG (DImode, MD_REG_FIRST))); -+ mips_emit_move (mem, MIPS_PROLOGUE_TEMP (GET_MODE (reg))); -+ } -+ else if ((TARGET_MIPS16 -+ && REGNO (reg) != GP_REG_FIRST + 31 -+ && !M16_REG_P (REGNO (reg))) -+ || ACC_REG_P (REGNO (reg))) -+ { -+ /* If the register has no direct store instruction, move it -+ through a temporary. Note that there's a special MIPS16 -+ instruction to save $31. */ - mips_emit_move (MIPS_PROLOGUE_TEMP (GET_MODE (reg)), reg); - mips_emit_move (mem, MIPS_PROLOGUE_TEMP (GET_MODE (reg))); - } -@@ -9153,6 +9487,14 @@ - emit_insn (gen_loadgp_blockage ()); - } - -+/* A for_each_rtx callback. Stop the search if *X is a kernel register. */ -+ -+static int -+mips_kernel_reg_p (rtx *x, void *data ATTRIBUTE_UNUSED) -+{ -+ return GET_CODE (*x) == REG && KERNEL_REG_P (REGNO (*x)); -+} -+ - /* Expand the "prologue" pattern. */ - - void -@@ -9172,7 +9514,8 @@ - /* Save the registers. Allocate up to MIPS_MAX_FIRST_STACK_STEP - bytes beforehand; this is enough to cover the register save area - without going out of range. */ -- if ((frame->mask | frame->fmask) != 0) -+ if (((frame->mask | frame->fmask | frame->acc_mask) != 0) -+ || frame->num_cop0_regs > 0) - { - HOST_WIDE_INT step1; - -@@ -9203,12 +9546,97 @@ - } - else - { -- insn = gen_add3_insn (stack_pointer_rtx, -- stack_pointer_rtx, -- GEN_INT (-step1)); -- RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; -- size -= step1; -- mips_for_each_saved_reg (size, mips_save_reg); -+ if (cfun->machine->interrupt_handler_p) -+ { -+ HOST_WIDE_INT offset; -+ rtx mem; -+ -+ /* If this interrupt is using a shadow register set, we need to -+ get the stack pointer from the previous register set. */ -+ if (cfun->machine->use_shadow_register_set_p) -+ emit_insn (gen_mips_rdpgpr (stack_pointer_rtx, -+ stack_pointer_rtx)); -+ -+ if (!cfun->machine->keep_interrupts_masked_p) -+ { -+ /* Move from COP0 Cause to K0. */ -+ emit_insn (gen_cop0_move (gen_rtx_REG (SImode, K0_REG_NUM), -+ gen_rtx_REG (SImode, -+ COP0_CAUSE_REG_NUM))); -+ /* Move from COP0 EPC to K1. */ -+ emit_insn (gen_cop0_move (gen_rtx_REG (SImode, K1_REG_NUM), -+ gen_rtx_REG (SImode, -+ COP0_EPC_REG_NUM))); -+ } -+ -+ /* Allocate the first part of the frame. */ -+ insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, -+ GEN_INT (-step1)); -+ RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; -+ size -= step1; -+ -+ /* Start at the uppermost location for saving. */ -+ offset = frame->cop0_sp_offset - size; -+ if (!cfun->machine->keep_interrupts_masked_p) -+ { -+ /* Push EPC into its stack slot. */ -+ mem = gen_frame_mem (word_mode, -+ plus_constant (stack_pointer_rtx, -+ offset)); -+ mips_emit_move (mem, gen_rtx_REG (word_mode, K1_REG_NUM)); -+ offset -= UNITS_PER_WORD; -+ } -+ -+ /* Move from COP0 Status to K1. */ -+ emit_insn (gen_cop0_move (gen_rtx_REG (SImode, K1_REG_NUM), -+ gen_rtx_REG (SImode, -+ COP0_STATUS_REG_NUM))); -+ -+ /* Right justify the RIPL in k0. */ -+ if (!cfun->machine->keep_interrupts_masked_p) -+ emit_insn (gen_lshrsi3 (gen_rtx_REG (SImode, K0_REG_NUM), -+ gen_rtx_REG (SImode, K0_REG_NUM), -+ GEN_INT (CAUSE_IPL))); -+ -+ /* Push Status into its stack slot. */ -+ mem = gen_frame_mem (word_mode, -+ plus_constant (stack_pointer_rtx, offset)); -+ mips_emit_move (mem, gen_rtx_REG (word_mode, K1_REG_NUM)); -+ offset -= UNITS_PER_WORD; -+ -+ /* Insert the RIPL into our copy of SR (k1) as the new IPL. */ -+ if (!cfun->machine->keep_interrupts_masked_p) -+ emit_insn (gen_insvsi (gen_rtx_REG (SImode, K1_REG_NUM), -+ GEN_INT (6), -+ GEN_INT (SR_IPL), -+ gen_rtx_REG (SImode, K0_REG_NUM))); -+ -+ if (!cfun->machine->keep_interrupts_masked_p) -+ /* Enable interrupts by clearing the KSU ERL and EXL bits. -+ IE is already the correct value, so we don't have to do -+ anything explicit. */ -+ emit_insn (gen_insvsi (gen_rtx_REG (SImode, K1_REG_NUM), -+ GEN_INT (4), -+ GEN_INT (SR_EXL), -+ gen_rtx_REG (SImode, GP_REG_FIRST))); -+ else -+ /* Disable interrupts by clearing the KSU, ERL, EXL, -+ and IE bits. */ -+ emit_insn (gen_insvsi (gen_rtx_REG (SImode, K1_REG_NUM), -+ GEN_INT (5), -+ GEN_INT (SR_IE), -+ gen_rtx_REG (SImode, GP_REG_FIRST))); -+ } -+ else -+ { -+ insn = gen_add3_insn (stack_pointer_rtx, -+ stack_pointer_rtx, -+ GEN_INT (-step1)); -+ RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; -+ size -= step1; -+ } -+ mips_for_each_saved_acc (size, mips_save_reg); -+ mips_for_each_saved_gpr_and_fpr (size, mips_save_reg); - } - } - -@@ -9293,6 +9721,20 @@ - pic_offset_table_rtx); - } - -+ /* We need to search back to the last use of K0 or K1. */ -+ if (cfun->machine->interrupt_handler_p) -+ { -+ for (insn = get_last_insn (); insn != NULL_RTX; insn = PREV_INSN (insn)) -+ if (INSN_P (insn) -+ && for_each_rtx (&PATTERN (insn), mips_kernel_reg_p, NULL)) -+ break; -+ /* Emit a move from K1 to COP0 Status after insn. */ -+ gcc_assert (insn != NULL_RTX); -+ emit_insn_after (gen_cop0_move (gen_rtx_REG (SImode, COP0_STATUS_REG_NUM), -+ gen_rtx_REG (SImode, K1_REG_NUM)), -+ insn); -+ } -+ - /* If we are profiling, make sure no instructions are scheduled before - the call to mcount. */ - if (crtl->profile) -@@ -9309,7 +9751,20 @@ - if (TARGET_MIPS16 && REGNO (reg) == GP_REG_FIRST + 31) - reg = gen_rtx_REG (GET_MODE (reg), GP_REG_FIRST + 7); - -- if (TARGET_MIPS16 && !M16_REG_P (REGNO (reg))) -+ if (REGNO (reg) == HI_REGNUM) -+ { -+ mips_emit_move (MIPS_EPILOGUE_TEMP (GET_MODE (reg)), mem); -+ if (TARGET_64BIT) -+ emit_insn (gen_mthisi_di (gen_rtx_REG (TImode, MD_REG_FIRST), -+ MIPS_EPILOGUE_TEMP (DImode), -+ gen_rtx_REG (DImode, LO_REGNUM))); -+ else -+ emit_insn (gen_mthisi_di (gen_rtx_REG (DImode, MD_REG_FIRST), -+ MIPS_EPILOGUE_TEMP (SImode), -+ gen_rtx_REG (SImode, LO_REGNUM))); -+ } -+ else if ((TARGET_MIPS16 && !M16_REG_P (REGNO (reg))) -+ || ACC_REG_P (REGNO (reg))) - { - /* Can't restore directly; move through a temporary. */ - mips_emit_move (MIPS_EPILOGUE_TEMP (GET_MODE (reg)), mem); -@@ -9345,7 +9800,7 @@ - { - const struct mips_frame_info *frame; - HOST_WIDE_INT step1, step2; -- rtx base, target; -+ rtx base, target, insn; - - if (!sibcall_p && mips_can_use_return_insn ()) - { -@@ -9378,7 +9833,8 @@ - - /* If we need to restore registers, deallocate as much stack as - possible in the second step without going out of range. */ -- if ((frame->mask | frame->fmask) != 0) -+ if ((frame->mask | frame->fmask | frame->acc_mask) != 0 -+ || frame->num_cop0_regs > 0) - { - step2 = MIN (step1, MIPS_MAX_FIRST_STACK_STEP); - step1 -= step2; -@@ -9440,13 +9896,53 @@ - else - { - /* Restore the registers. */ -- mips_for_each_saved_reg (frame->total_size - step2, mips_restore_reg); -+ mips_for_each_saved_acc (frame->total_size - step2, mips_restore_reg); -+ mips_for_each_saved_gpr_and_fpr (frame->total_size - step2, -+ mips_restore_reg); - -- /* Deallocate the final bit of the frame. */ -- if (step2 > 0) -- emit_insn (gen_add3_insn (stack_pointer_rtx, -- stack_pointer_rtx, -- GEN_INT (step2))); -+ if (cfun->machine->interrupt_handler_p) -+ { -+ HOST_WIDE_INT offset; -+ rtx mem; -+ -+ offset = frame->cop0_sp_offset - (frame->total_size - step2); -+ if (!cfun->machine->keep_interrupts_masked_p) -+ { -+ /* Restore the original EPC. */ -+ mem = gen_frame_mem (word_mode, -+ plus_constant (stack_pointer_rtx, offset)); -+ mips_emit_move (gen_rtx_REG (word_mode, K0_REG_NUM), mem); -+ offset -= UNITS_PER_WORD; -+ -+ /* Move to COP0 EPC. */ -+ emit_insn (gen_cop0_move (gen_rtx_REG (SImode, COP0_EPC_REG_NUM), -+ gen_rtx_REG (SImode, K0_REG_NUM))); -+ } -+ -+ /* Restore the original Status. */ -+ mem = gen_frame_mem (word_mode, -+ plus_constant (stack_pointer_rtx, offset)); -+ mips_emit_move (gen_rtx_REG (word_mode, K0_REG_NUM), mem); -+ offset -= UNITS_PER_WORD; -+ -+ /* If we don't use shoadow register set, we need to update SP. */ -+ if (!cfun->machine->use_shadow_register_set_p && step2 > 0) -+ emit_insn (gen_add3_insn (stack_pointer_rtx, -+ stack_pointer_rtx, -+ GEN_INT (step2))); -+ -+ /* Move to COP0 Status. */ -+ emit_insn (gen_cop0_move (gen_rtx_REG (SImode, COP0_STATUS_REG_NUM), -+ gen_rtx_REG (SImode, K0_REG_NUM))); -+ } -+ else -+ { -+ /* Deallocate the final bit of the frame. */ -+ if (step2 > 0) -+ emit_insn (gen_add3_insn (stack_pointer_rtx, -+ stack_pointer_rtx, -+ GEN_INT (step2))); -+ } - } - - /* Add in the __builtin_eh_return stack adjustment. We need to -@@ -9469,18 +9965,44 @@ - - if (!sibcall_p) - { -- unsigned int regno; -- -- /* When generating MIPS16 code, the normal mips_for_each_saved_reg -- path will restore the return address into $7 rather than $31. */ -- if (TARGET_MIPS16 -- && !GENERATE_MIPS16E_SAVE_RESTORE -- && BITSET_P (frame->mask, 31)) -- regno = GP_REG_FIRST + 7; -- else -- regno = GP_REG_FIRST + 31; - mips_expand_before_return (); -- emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, regno))); -+ if (cfun->machine->interrupt_handler_p) -+ { -+ /* Interrupt handlers generate eret or deret. */ -+ if (cfun->machine->use_debug_exception_return_p) -+ emit_jump_insn (gen_mips_deret ()); -+ else -+ emit_jump_insn (gen_mips_eret ()); -+ } -+ else -+ { -+ unsigned int regno; -+ -+ /* When generating MIPS16 code, the normal -+ mips_for_each_saved_gpr_and_fpr path will restore the return -+ address into $7 rather than $31. */ -+ if (TARGET_MIPS16 -+ && !GENERATE_MIPS16E_SAVE_RESTORE -+ && BITSET_P (frame->mask, 31)) -+ regno = GP_REG_FIRST + 7; -+ else -+ regno = GP_REG_FIRST + 31; -+ emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, regno))); -+ } -+ } -+ -+ /* Search from the beginning to the first use of K0 or K1. */ -+ if (cfun->machine->interrupt_handler_p -+ && !cfun->machine->keep_interrupts_masked_p) -+ { -+ for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn)) -+ if (INSN_P (insn) -+ && for_each_rtx (&PATTERN(insn), mips_kernel_reg_p, NULL)) -+ break; -+ gcc_assert (insn != NULL_RTX); -+ /* Insert disable interrupts before the first use of K0 or K1. */ -+ emit_insn_before (gen_mips_di (), insn); -+ emit_insn_before (gen_mips_ehb (), insn); - } - } - -@@ -9491,6 +10013,10 @@ - bool - mips_can_use_return_insn (void) - { -+ /* Interrupt handlers need to go through the epilogue. */ -+ if (cfun->machine->interrupt_handler_p) -+ return false; -+ - if (!reload_completed) - return false; - -@@ -10422,10 +10948,15 @@ - s = "bnez\t%2,1f\n\tbreak\t7\n1:"; - } - else if (GENERATE_DIVIDE_TRAPS) -- { -- output_asm_insn (s, operands); -- s = "teq\t%2,%.,7"; -- } -+ { -+ if (TUNE_74K) -+ output_asm_insn ("teq\t%2,%.,7", operands); -+ else -+ { -+ output_asm_insn (s, operands); -+ s = "teq\t%2,%.,7"; -+ } -+ } - else - { - output_asm_insn ("%(bne\t%2,%.,1f", operands); -@@ -10737,7 +11268,17 @@ - ready[pos2] = temp; - } - } -- -+ -+int -+mips_mult_madd_chain_bypass_p (rtx out_insn ATTRIBUTE_UNUSED, -+ rtx in_insn ATTRIBUTE_UNUSED) -+{ -+ if (reload_completed) -+ return false; -+ else -+ return true; -+} -+ - /* Used by TUNE_MACC_CHAINS to record the last scheduled instruction - that may clobber hi or lo. */ - static rtx mips_macc_chains_last_hilo; -@@ -13910,6 +14451,14 @@ - long as any indirect jumps use $25. */ - flag_pic = 1; - -+ /* For SDE, switch on ABICALLS mode if -fpic or -fpie were used, and the -+ user hasn't explicitly disabled these modes. */ -+ if (TARGET_MIPS_SDE -+ && (flag_pic || flag_pie) && !TARGET_ABICALLS -+ && !((target_flags_explicit & MASK_ABICALLS)) -+ && mips_abi != ABI_EABI) -+ target_flags |= MASK_ABICALLS; -+ - /* -mvr4130-align is a "speed over size" optimization: it usually produces - faster code, but at the expense of more nops. Enable it at -O3 and - above. */ -@@ -13984,26 +14533,46 @@ - if (TARGET_DSPR2) - target_flags |= MASK_DSP; - -- /* .eh_frame addresses should be the same width as a C pointer. -- Most MIPS ABIs support only one pointer size, so the assembler -- will usually know exactly how big an .eh_frame address is. -- -- Unfortunately, this is not true of the 64-bit EABI. The ABI was -- originally defined to use 64-bit pointers (i.e. it is LP64), and -- this is still the default mode. However, we also support an n32-like -- ILP32 mode, which is selected by -mlong32. The problem is that the -- assembler has traditionally not had an -mlong option, so it has -- traditionally not known whether we're using the ILP32 or LP64 form. -- -- As it happens, gas versions up to and including 2.19 use _32-bit_ -- addresses for EABI64 .cfi_* directives. This is wrong for the -- default LP64 mode, so we can't use the directives by default. -- Moreover, since gas's current behavior is at odds with gcc's -- default behavior, it seems unwise to rely on future versions -- of gas behaving the same way. We therefore avoid using .cfi -- directives for -mlong32 as well. */ -- if (mips_abi == ABI_EABI && TARGET_64BIT) -- flag_dwarf2_cfi_asm = 0; -+ /* Use the traditional method of generating .eh_frames. -+ We need this for two reasons: -+ -+ - .eh_frame addresses should be the same width as a C pointer. -+ Most MIPS ABIs support only one pointer size, so the assembler -+ will usually know exactly how big an .eh_frame address is. -+ -+ Unfortunately, this is not true of the 64-bit EABI. The ABI was -+ originally defined to use 64-bit pointers (i.e. it is LP64), and -+ this is still the default mode. However, we also support an n32-like -+ ILP32 mode, which is selected by -mlong32. The problem is that the -+ assembler has traditionally not had an -mlong option, so it has -+ traditionally not known whether we're using the ILP32 or LP64 form. -+ -+ As it happens, gas versions up to and including 2.19 use _32-bit_ -+ addresses for EABI64 .cfi_* directives. This is wrong for the -+ default LP64 mode, so we can't use the directives by default. -+ Moreover, since gas's current behavior is at odds with gcc's -+ default behavior, it seems unwise to rely on future versions -+ of gas behaving the same way. We therefore avoid using .cfi -+ directives for -mlong32 as well. -+ -+ - .cfi* directives generate read-only .eh_frame sections. -+ However, MIPS has traditionally not allowed directives like: -+ -+ .long x-. -+ -+ in cases where "x" is in a different section, or is not defined -+ in the same assembly file. We have therefore traditionally -+ used absolute addresses and a writable .eh_frame instead. -+ -+ The linker is able to convert most of these absolute addresses -+ into PC-relative form where doing so is necessary to avoid -+ relocations. However, until 2.21, it wasn't able to do this -+ for indirect encodings or personality routines. -+ -+ GNU ld 2.21 and GCC 4.5 have support for read-only .eh_frames, -+ but for the time being, we should stick to the approach used -+ in 4.3 and earlier. */ -+ flag_dwarf2_cfi_asm = 0; - - mips_init_print_operand_punct (); - -@@ -14242,6 +14811,178 @@ - reg_alloc_order[24] = 0; - } - } -+ -+/* Implement EPILOGUE_USES. */ -+ -+bool -+mips_epilogue_uses (unsigned int regno) -+{ -+ /* Say that the epilogue uses the return address register. Note that -+ in the case of sibcalls, the values "used by the epilogue" are -+ considered live at the start of the called function. */ -+ if (regno == 31) -+ return true; -+ -+ /* If using a GOT, say that the epilogue also uses GOT_VERSION_REGNUM. -+ See the comment above load_call<mode> for details. */ -+ if (TARGET_USE_GOT && (regno) == GOT_VERSION_REGNUM) -+ return true; -+ -+ /* An interrupt handler must preserve some registers that are -+ ordinarily call-clobbered. */ -+ if (cfun->machine->interrupt_handler_p -+ && mips_interrupt_extra_call_saved_reg_p (regno)) -+ return true; -+ -+ return false; -+} -+ -+#ifdef CVMX_SHARED_BSS_FLAGS -+/* Handle a "cvmx_shared" attribute; arguments as in -+ struct attribute_spec.handler. */ -+ -+static tree -+octeon_handle_cvmx_shared_attribute (tree *node, tree name, -+ tree args ATTRIBUTE_UNUSED, -+ int flags ATTRIBUTE_UNUSED, -+ bool *no_add_attrs) -+{ -+ if (TREE_CODE (*node) != VAR_DECL) -+ { -+ warning (OPT_Wattributes, "%qs attribute only applies to variables", -+ IDENTIFIER_POINTER (name)); -+ *no_add_attrs = true; -+ } -+ -+ return NULL_TREE; -+} -+ -+/* Switch to the appropriate section for output of DECL. -+ DECL is either a `VAR_DECL' node or a constant of some sort. -+ RELOC indicates whether forming the initial value of DECL requires -+ link-time relocations. */ -+ -+static section * -+octeon_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align) -+{ -+ if (decl && TREE_CODE (decl) == VAR_DECL -+ && lookup_attribute ("cvmx_shared", DECL_ATTRIBUTES (decl))) -+ { -+ const char *sname = NULL; -+ unsigned int flags = SECTION_WRITE; -+ -+ switch (categorize_decl_for_section (decl, reloc)) -+ { -+ case SECCAT_DATA: -+ case SECCAT_SDATA: -+ case SECCAT_RODATA: -+ case SECCAT_SRODATA: -+ case SECCAT_RODATA_MERGE_STR: -+ case SECCAT_RODATA_MERGE_STR_INIT: -+ case SECCAT_RODATA_MERGE_CONST: -+ case SECCAT_DATA_REL: -+ case SECCAT_DATA_REL_LOCAL: -+ case SECCAT_DATA_REL_RO: -+ case SECCAT_DATA_REL_RO_LOCAL: -+ sname = ".cvmx_shared"; -+ break; -+ case SECCAT_BSS: -+ case SECCAT_SBSS: -+ sname = ".cvmx_shared_bss"; -+ flags |= SECTION_BSS; -+ break; -+ case SECCAT_TEXT: -+ case SECCAT_TDATA: -+ case SECCAT_TBSS: -+ break; -+ } -+ if (sname) -+ { -+ return get_section (sname, flags, decl); -+ } -+ } -+ return default_elf_select_section (decl, reloc, align); -+} -+ -+/* Build up a unique section name, expressed as a -+ STRING_CST node, and assign it to DECL_SECTION_NAME (decl). -+ RELOC indicates whether the initial value of EXP requires -+ link-time relocations. */ -+ -+static void -+octeon_unique_section (tree decl, int reloc) -+{ -+ if (decl && TREE_CODE (decl) == VAR_DECL -+ && lookup_attribute ("cvmx_shared", DECL_ATTRIBUTES (decl))) -+ { -+ const char *sname = NULL; -+ -+ if (! DECL_ONE_ONLY (decl)) -+ { -+ section *sect; -+ sect = octeon_select_section (decl, reloc, DECL_ALIGN (decl)); -+ DECL_SECTION_NAME (decl) = build_string (strlen (sect->named.name), -+ sect->named.name); -+ return; -+ } -+ -+ switch (categorize_decl_for_section (decl, reloc)) -+ { -+ case SECCAT_BSS: -+ case SECCAT_SBSS: -+ sname = ".cvmx_shared_bss.linkonce."; -+ break; -+ case SECCAT_SDATA: -+ case SECCAT_DATA: -+ case SECCAT_DATA_REL: -+ case SECCAT_DATA_REL_LOCAL: -+ case SECCAT_DATA_REL_RO: -+ case SECCAT_DATA_REL_RO_LOCAL: -+ case SECCAT_RODATA: -+ case SECCAT_SRODATA: -+ case SECCAT_RODATA_MERGE_STR: -+ case SECCAT_RODATA_MERGE_STR_INIT: -+ case SECCAT_RODATA_MERGE_CONST: -+ sname = ".cvmx_shared.linkonce."; -+ break; -+ case SECCAT_TEXT: -+ case SECCAT_TDATA: -+ case SECCAT_TBSS: -+ break; -+ } -+ if (sname) -+ { -+ const char *name; -+ size_t plen, nlen; -+ char *string; -+ plen = strlen (sname); -+ -+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); -+ name = targetm.strip_name_encoding (name); -+ nlen = strlen (name); -+ -+ string = alloca (plen + nlen + 1); -+ memcpy (string, sname, plen); -+ memcpy (string + plen, name, nlen + 1); -+ DECL_SECTION_NAME (decl) = build_string (nlen + plen, string); -+ return; -+ } -+ } -+ default_unique_section (decl, reloc); -+} -+ -+/* Emit an uninitialized cvmx_shared variable. */ -+void -+octeon_output_shared_variable (FILE *stream, tree decl, const char *name, -+ unsigned HOST_WIDE_INT size, int align) -+{ -+ switch_to_section (get_section (".cvmx_shared_bss", CVMX_SHARED_BSS_FLAGS, -+ NULL_TREE)); -+ ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT)); -+ ASM_DECLARE_OBJECT_NAME (stream, name, decl); -+ ASM_OUTPUT_SKIP (stream, size != 0 ? size : 1); -+} -+#endif - - /* Initialize the GCC target structure. */ - #undef TARGET_ASM_ALIGNED_HI_OP ---- a/gcc/config/mips/mips-dsp.md -+++ b/gcc/config/mips/mips-dsp.md -@@ -42,9 +42,9 @@ - (match_operand:DSPV 2 "register_operand" "d"))) - (set (reg:CCDSP CCDSP_OU_REGNUM) - (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDQ))])] -- "" -+ "ISA_HAS_DSP" - "add<DSPV:dspfmt1>.<DSPV:dspfmt2>\t%0,%1,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_add<DSP:dspfmt1>_s_<DSP:dspfmt2>" -@@ -55,9 +55,9 @@ - UNSPEC_ADDQ_S)) - (set (reg:CCDSP CCDSP_OU_REGNUM) - (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDQ_S))])] -- "" -+ "ISA_HAS_DSP" - "add<DSP:dspfmt1>_s.<DSP:dspfmt2>\t%0,%1,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalusat") - (set_attr "mode" "SI")]) - - ;; SUBQ* -@@ -70,7 +70,7 @@ - (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SUBQ))])] - "ISA_HAS_DSP" - "sub<DSPV:dspfmt1>.<DSPV:dspfmt2>\t%0,%1,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_sub<DSP:dspfmt1>_s_<DSP:dspfmt2>" -@@ -83,7 +83,7 @@ - (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SUBQ_S))])] - "ISA_HAS_DSP" - "sub<DSP:dspfmt1>_s.<DSP:dspfmt2>\t%0,%1,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalusat") - (set_attr "mode" "SI")]) - - ;; ADDSC -@@ -97,7 +97,7 @@ - (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDSC))])] - "ISA_HAS_DSP" - "addsc\t%0,%1,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; ADDWC -@@ -112,7 +112,7 @@ - (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDWC))])] - "ISA_HAS_DSP" - "addwc\t%0,%1,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; MODSUB -@@ -123,7 +123,7 @@ - UNSPEC_MODSUB))] - "ISA_HAS_DSP" - "modsub\t%0,%1,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; RADDU* -@@ -133,7 +133,7 @@ - UNSPEC_RADDU_W_QB))] - "ISA_HAS_DSP" - "raddu.w.qb\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; ABSQ* -@@ -146,7 +146,7 @@ - (unspec:CCDSP [(match_dup 1)] UNSPEC_ABSQ_S))])] - "ISA_HAS_DSP" - "absq_s.<DSPQ:dspfmt2>\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalusat") - (set_attr "mode" "SI")]) - - ;; PRECRQ* -@@ -157,7 +157,7 @@ - UNSPEC_PRECRQ_QB_PH))] - "ISA_HAS_DSP" - "precrq.qb.ph\t%0,%1,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_precrq_ph_w" -@@ -167,7 +167,7 @@ - UNSPEC_PRECRQ_PH_W))] - "ISA_HAS_DSP" - "precrq.ph.w\t%0,%1,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_precrq_rs_ph_w" -@@ -181,7 +181,7 @@ - UNSPEC_PRECRQ_RS_PH_W))])] - "ISA_HAS_DSP" - "precrq_rs.ph.w\t%0,%1,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; PRECRQU* -@@ -196,7 +196,7 @@ - UNSPEC_PRECRQU_S_QB_PH))])] - "ISA_HAS_DSP" - "precrqu_s.qb.ph\t%0,%1,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalusat") - (set_attr "mode" "SI")]) - - ;; PRECEQ* -@@ -206,7 +206,7 @@ - UNSPEC_PRECEQ_W_PHL))] - "ISA_HAS_DSP" - "preceq.w.phl\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_preceq_w_phr" -@@ -215,7 +215,7 @@ - UNSPEC_PRECEQ_W_PHR))] - "ISA_HAS_DSP" - "preceq.w.phr\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; PRECEQU* -@@ -225,7 +225,7 @@ - UNSPEC_PRECEQU_PH_QBL))] - "ISA_HAS_DSP" - "precequ.ph.qbl\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_precequ_ph_qbr" -@@ -234,7 +234,7 @@ - UNSPEC_PRECEQU_PH_QBR))] - "ISA_HAS_DSP" - "precequ.ph.qbr\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_precequ_ph_qbla" -@@ -243,7 +243,7 @@ - UNSPEC_PRECEQU_PH_QBLA))] - "ISA_HAS_DSP" - "precequ.ph.qbla\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_precequ_ph_qbra" -@@ -252,7 +252,7 @@ - UNSPEC_PRECEQU_PH_QBRA))] - "ISA_HAS_DSP" - "precequ.ph.qbra\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; PRECEU* -@@ -262,7 +262,7 @@ - UNSPEC_PRECEU_PH_QBL))] - "ISA_HAS_DSP" - "preceu.ph.qbl\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_preceu_ph_qbr" -@@ -271,7 +271,7 @@ - UNSPEC_PRECEU_PH_QBR))] - "ISA_HAS_DSP" - "preceu.ph.qbr\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_preceu_ph_qbla" -@@ -280,7 +280,7 @@ - UNSPEC_PRECEU_PH_QBLA))] - "ISA_HAS_DSP" - "preceu.ph.qbla\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_preceu_ph_qbra" -@@ -289,7 +289,7 @@ - UNSPEC_PRECEU_PH_QBRA))] - "ISA_HAS_DSP" - "preceu.ph.qbra\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; Table 2-2. MIPS DSP ASE Instructions: Shift -@@ -313,7 +313,7 @@ - } - return "shllv.<DSPV:dspfmt2>\t%0,%1,%2"; - } -- [(set_attr "type" "shift") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_shll_s_<DSPQ:dspfmt2>" -@@ -335,7 +335,7 @@ - } - return "shllv_s.<DSPQ:dspfmt2>\t%0,%1,%2"; - } -- [(set_attr "type" "shift") -+ [(set_attr "type" "dspalusat") - (set_attr "mode" "SI")]) - - ;; SHRL* -@@ -354,7 +354,7 @@ - } - return "shrlv.qb\t%0,%1,%2"; - } -- [(set_attr "type" "shift") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; SHRA* -@@ -373,7 +373,7 @@ - } - return "shrav.ph\t%0,%1,%2"; - } -- [(set_attr "type" "shift") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_shra_r_<DSPQ:dspfmt2>" -@@ -392,7 +392,7 @@ - } - return "shrav_r.<DSPQ:dspfmt2>\t%0,%1,%2"; - } -- [(set_attr "type" "shift") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; Table 2-3. MIPS DSP ASE Instructions: Multiply -@@ -478,7 +478,7 @@ - UNSPEC_DPAU_H_QBL))] - "ISA_HAS_DSP && !TARGET_64BIT" - "dpau.h.qbl\t%q0,%2,%3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmac") - (set_attr "mode" "SI")]) - - (define_insn "mips_dpau_h_qbr" -@@ -489,7 +489,7 @@ - UNSPEC_DPAU_H_QBR))] - "ISA_HAS_DSP && !TARGET_64BIT" - "dpau.h.qbr\t%q0,%2,%3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmac") - (set_attr "mode" "SI")]) - - ;; DPSU* -@@ -501,7 +501,7 @@ - UNSPEC_DPSU_H_QBL))] - "ISA_HAS_DSP && !TARGET_64BIT" - "dpsu.h.qbl\t%q0,%2,%3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmac") - (set_attr "mode" "SI")]) - - (define_insn "mips_dpsu_h_qbr" -@@ -512,7 +512,7 @@ - UNSPEC_DPSU_H_QBR))] - "ISA_HAS_DSP && !TARGET_64BIT" - "dpsu.h.qbr\t%q0,%2,%3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmac") - (set_attr "mode" "SI")]) - - ;; DPAQ* -@@ -528,7 +528,7 @@ - UNSPEC_DPAQ_S_W_PH))])] - "ISA_HAS_DSP && !TARGET_64BIT" - "dpaq_s.w.ph\t%q0,%2,%3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmac") - (set_attr "mode" "SI")]) - - ;; DPSQ* -@@ -544,7 +544,7 @@ - UNSPEC_DPSQ_S_W_PH))])] - "ISA_HAS_DSP && !TARGET_64BIT" - "dpsq_s.w.ph\t%q0,%2,%3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmac") - (set_attr "mode" "SI")]) - - ;; MULSAQ* -@@ -560,7 +560,7 @@ - UNSPEC_MULSAQ_S_W_PH))])] - "ISA_HAS_DSP && !TARGET_64BIT" - "mulsaq_s.w.ph\t%q0,%2,%3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmac") - (set_attr "mode" "SI")]) - - ;; DPAQ* -@@ -576,7 +576,7 @@ - UNSPEC_DPAQ_SA_L_W))])] - "ISA_HAS_DSP && !TARGET_64BIT" - "dpaq_sa.l.w\t%q0,%2,%3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmacsat") - (set_attr "mode" "SI")]) - - ;; DPSQ* -@@ -592,7 +592,7 @@ - UNSPEC_DPSQ_SA_L_W))])] - "ISA_HAS_DSP && !TARGET_64BIT" - "dpsq_sa.l.w\t%q0,%2,%3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmacsat") - (set_attr "mode" "SI")]) - - ;; MAQ* -@@ -608,7 +608,7 @@ - UNSPEC_MAQ_S_W_PHL))])] - "ISA_HAS_DSP && !TARGET_64BIT" - "maq_s.w.phl\t%q0,%2,%3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmac") - (set_attr "mode" "SI")]) - - (define_insn "mips_maq_s_w_phr" -@@ -623,7 +623,7 @@ - UNSPEC_MAQ_S_W_PHR))])] - "ISA_HAS_DSP && !TARGET_64BIT" - "maq_s.w.phr\t%q0,%2,%3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmac") - (set_attr "mode" "SI")]) - - ;; MAQ_SA* -@@ -639,7 +639,7 @@ - UNSPEC_MAQ_SA_W_PHL))])] - "ISA_HAS_DSP && !TARGET_64BIT" - "maq_sa.w.phl\t%q0,%2,%3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmacsat") - (set_attr "mode" "SI")]) - - (define_insn "mips_maq_sa_w_phr" -@@ -654,7 +654,7 @@ - UNSPEC_MAQ_SA_W_PHR))])] - "ISA_HAS_DSP && !TARGET_64BIT" - "maq_sa.w.phr\t%q0,%2,%3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmacsat") - (set_attr "mode" "SI")]) - - ;; Table 2-4. MIPS DSP ASE Instructions: General Bit/Manipulation -@@ -665,7 +665,7 @@ - UNSPEC_BITREV))] - "ISA_HAS_DSP" - "bitrev\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; INSV -@@ -678,7 +678,7 @@ - UNSPEC_INSV))] - "ISA_HAS_DSP" - "insv\t%0,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; REPL* -@@ -696,7 +696,7 @@ - } - return "replv.qb\t%0,%1"; - } -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_repl_ph" -@@ -707,7 +707,7 @@ - "@ - repl.ph\t%0,%1 - replv.ph\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; Table 2-5. MIPS DSP ASE Instructions: Compare-Pick -@@ -720,7 +720,7 @@ - UNSPEC_CMP_EQ))] - "ISA_HAS_DSP" - "cmp<DSPV:dspfmt1_1>.eq.<DSPV:dspfmt2>\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_cmp<DSPV:dspfmt1_1>_lt_<DSPV:dspfmt2>" -@@ -731,7 +731,7 @@ - UNSPEC_CMP_LT))] - "ISA_HAS_DSP" - "cmp<DSPV:dspfmt1_1>.lt.<DSPV:dspfmt2>\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_cmp<DSPV:dspfmt1_1>_le_<DSPV:dspfmt2>" -@@ -742,7 +742,7 @@ - UNSPEC_CMP_LE))] - "ISA_HAS_DSP" - "cmp<DSPV:dspfmt1_1>.le.<DSPV:dspfmt2>\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_cmpgu_eq_qb" -@@ -752,7 +752,7 @@ - UNSPEC_CMPGU_EQ_QB))] - "ISA_HAS_DSP" - "cmpgu.eq.qb\t%0,%1,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_cmpgu_lt_qb" -@@ -762,7 +762,7 @@ - UNSPEC_CMPGU_LT_QB))] - "ISA_HAS_DSP" - "cmpgu.lt.qb\t%0,%1,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_cmpgu_le_qb" -@@ -772,7 +772,7 @@ - UNSPEC_CMPGU_LE_QB))] - "ISA_HAS_DSP" - "cmpgu.le.qb\t%0,%1,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; PICK* -@@ -784,7 +784,7 @@ - UNSPEC_PICK))] - "ISA_HAS_DSP" - "pick.<DSPV:dspfmt2>\t%0,%1,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; PACKRL* -@@ -795,7 +795,7 @@ - UNSPEC_PACKRL_PH))] - "ISA_HAS_DSP" - "packrl.ph\t%0,%1,%2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; Table 2-6. MIPS DSP ASE Instructions: Accumulator and DSPControl Access -@@ -818,7 +818,7 @@ - } - return "extrv.w\t%0,%q1,%2"; - } -- [(set_attr "type" "mfhilo") -+ [(set_attr "type" "accext") - (set_attr "mode" "SI")]) - - (define_insn "mips_extr_r_w" -@@ -839,7 +839,7 @@ - } - return "extrv_r.w\t%0,%q1,%2"; - } -- [(set_attr "type" "mfhilo") -+ [(set_attr "type" "accext") - (set_attr "mode" "SI")]) - - (define_insn "mips_extr_rs_w" -@@ -860,7 +860,7 @@ - } - return "extrv_rs.w\t%0,%q1,%2"; - } -- [(set_attr "type" "mfhilo") -+ [(set_attr "type" "accext") - (set_attr "mode" "SI")]) - - ;; EXTR*_S.H -@@ -882,7 +882,7 @@ - } - return "extrv_s.h\t%0,%q1,%2"; - } -- [(set_attr "type" "mfhilo") -+ [(set_attr "type" "accext") - (set_attr "mode" "SI")]) - - ;; EXTP* -@@ -905,7 +905,7 @@ - } - return "extpv\t%0,%q1,%2"; - } -- [(set_attr "type" "mfhilo") -+ [(set_attr "type" "accext") - (set_attr "mode" "SI")]) - - (define_insn "mips_extpdp" -@@ -930,7 +930,7 @@ - } - return "extpdpv\t%0,%q1,%2"; - } -- [(set_attr "type" "mfhilo") -+ [(set_attr "type" "accext") - (set_attr "mode" "SI")]) - - ;; SHILO* -@@ -949,7 +949,7 @@ - } - return "shilov\t%q0,%2"; - } -- [(set_attr "type" "mfhilo") -+ [(set_attr "type" "accmod") - (set_attr "mode" "SI")]) - - ;; MTHLIP* -@@ -965,7 +965,7 @@ - (reg:CCDSP CCDSP_PO_REGNUM)] UNSPEC_MTHLIP))])] - "ISA_HAS_DSP && !TARGET_64BIT" - "mthlip\t%2,%q0" -- [(set_attr "type" "mfhilo") -+ [(set_attr "type" "accmod") - (set_attr "mode" "SI")]) - - ;; WRDSP -@@ -987,7 +987,7 @@ - (unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP))])] - "ISA_HAS_DSP" - "wrdsp\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; RDDSP -@@ -1003,7 +1003,7 @@ - UNSPEC_RDDSP))] - "ISA_HAS_DSP" - "rddsp\t%0,%1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - ;; Table 2-7. MIPS DSP ASE Instructions: Indexed-Load ---- a/gcc/config/mips/mips-dspr2.md -+++ b/gcc/config/mips/mips-dspr2.md -@@ -9,7 +9,7 @@ - (unspec:CCDSP [(match_dup 1)] UNSPEC_ABSQ_S_QB))])] - "ISA_HAS_DSPR2" - "absq_s.qb\t%0,%z1" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalusat") - (set_attr "mode" "SI")]) - - (define_insn "mips_addu_ph" -@@ -21,7 +21,7 @@ - (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDU_PH))])] - "ISA_HAS_DSPR2" - "addu.ph\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_addu_s_ph" -@@ -34,7 +34,7 @@ - (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDU_S_PH))])] - "ISA_HAS_DSPR2" - "addu_s.ph\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalusat") - (set_attr "mode" "SI")]) - - (define_insn "mips_adduh_qb" -@@ -44,7 +44,7 @@ - UNSPEC_ADDUH_QB))] - "ISA_HAS_DSPR2" - "adduh.qb\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_adduh_r_qb" -@@ -54,7 +54,7 @@ - UNSPEC_ADDUH_R_QB))] - "ISA_HAS_DSPR2" - "adduh_r.qb\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalusat") - (set_attr "mode" "SI")]) - - (define_insn "mips_append" -@@ -69,7 +69,7 @@ - operands[2] = GEN_INT (INTVAL (operands[2]) & 31); - return "append\t%0,%z2,%3"; - } -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_balign" -@@ -84,7 +84,7 @@ - operands[2] = GEN_INT (INTVAL (operands[2]) & 3); - return "balign\t%0,%z2,%3"; - } -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_cmpgdu_eq_qb" -@@ -99,7 +99,7 @@ - UNSPEC_CMPGDU_EQ_QB))])] - "ISA_HAS_DSPR2" - "cmpgdu.eq.qb\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_cmpgdu_lt_qb" -@@ -114,7 +114,7 @@ - UNSPEC_CMPGDU_LT_QB))])] - "ISA_HAS_DSPR2" - "cmpgdu.lt.qb\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_cmpgdu_le_qb" -@@ -129,7 +129,7 @@ - UNSPEC_CMPGDU_LE_QB))])] - "ISA_HAS_DSPR2" - "cmpgdu.le.qb\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_dpa_w_ph" -@@ -140,7 +140,7 @@ - UNSPEC_DPA_W_PH))] - "ISA_HAS_DSPR2 && !TARGET_64BIT" - "dpa.w.ph\t%q0,%z2,%z3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmac") - (set_attr "mode" "SI")]) - - (define_insn "mips_dps_w_ph" -@@ -151,7 +151,7 @@ - UNSPEC_DPS_W_PH))] - "ISA_HAS_DSPR2 && !TARGET_64BIT" - "dps.w.ph\t%q0,%z2,%z3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmac") - (set_attr "mode" "SI")]) - - (define_expand "mips_madd<u>" -@@ -247,7 +247,7 @@ - UNSPEC_MULSA_W_PH))] - "ISA_HAS_DSPR2 && !TARGET_64BIT" - "mulsa.w.ph\t%q0,%z2,%z3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmac") - (set_attr "mode" "SI")]) - - (define_insn "mips_mult" -@@ -277,7 +277,7 @@ - UNSPEC_PRECR_QB_PH))] - "ISA_HAS_DSPR2" - "precr.qb.ph\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_precr_sra_ph_w" -@@ -292,7 +292,7 @@ - operands[2] = GEN_INT (INTVAL (operands[2]) & 31); - return "precr_sra.ph.w\t%0,%z2,%3"; - } -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_precr_sra_r_ph_w" -@@ -307,7 +307,7 @@ - operands[2] = GEN_INT (INTVAL (operands[2]) & 31); - return "precr_sra_r.ph.w\t%0,%z2,%3"; - } -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_prepend" -@@ -322,7 +322,7 @@ - operands[2] = GEN_INT (INTVAL (operands[2]) & 31); - return "prepend\t%0,%z2,%3"; - } -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_shra_qb" -@@ -340,7 +340,7 @@ - } - return "shrav.qb\t%0,%z1,%2"; - } -- [(set_attr "type" "shift") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - -@@ -359,7 +359,7 @@ - } - return "shrav_r.qb\t%0,%z1,%2"; - } -- [(set_attr "type" "shift") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_shrl_ph" -@@ -377,7 +377,7 @@ - } - return "shrlv.ph\t%0,%z1,%2"; - } -- [(set_attr "type" "shift") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_subu_ph" -@@ -390,7 +390,7 @@ - (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SUBU_PH))])] - "ISA_HAS_DSPR2" - "subu.ph\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_subu_s_ph" -@@ -403,7 +403,7 @@ - (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SUBU_S_PH))])] - "ISA_HAS_DSPR2" - "subu_s.ph\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalusat") - (set_attr "mode" "SI")]) - - (define_insn "mips_subuh_qb" -@@ -413,7 +413,7 @@ - UNSPEC_SUBUH_QB))] - "ISA_HAS_DSPR2" - "subuh.qb\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_subuh_r_qb" -@@ -423,7 +423,7 @@ - UNSPEC_SUBUH_R_QB))] - "ISA_HAS_DSPR2" - "subuh_r.qb\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_addqh_ph" -@@ -433,7 +433,7 @@ - UNSPEC_ADDQH_PH))] - "ISA_HAS_DSPR2" - "addqh.ph\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_addqh_r_ph" -@@ -443,7 +443,7 @@ - UNSPEC_ADDQH_R_PH))] - "ISA_HAS_DSPR2" - "addqh_r.ph\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_addqh_w" -@@ -453,7 +453,7 @@ - UNSPEC_ADDQH_W))] - "ISA_HAS_DSPR2" - "addqh.w\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_addqh_r_w" -@@ -463,7 +463,7 @@ - UNSPEC_ADDQH_R_W))] - "ISA_HAS_DSPR2" - "addqh_r.w\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_subqh_ph" -@@ -473,7 +473,7 @@ - UNSPEC_SUBQH_PH))] - "ISA_HAS_DSPR2" - "subqh.ph\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_subqh_r_ph" -@@ -483,7 +483,7 @@ - UNSPEC_SUBQH_R_PH))] - "ISA_HAS_DSPR2" - "subqh_r.ph\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_subqh_w" -@@ -493,7 +493,7 @@ - UNSPEC_SUBQH_W))] - "ISA_HAS_DSPR2" - "subqh.w\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_subqh_r_w" -@@ -503,7 +503,7 @@ - UNSPEC_SUBQH_R_W))] - "ISA_HAS_DSPR2" - "subqh_r.w\t%0,%z1,%z2" -- [(set_attr "type" "arith") -+ [(set_attr "type" "dspalu") - (set_attr "mode" "SI")]) - - (define_insn "mips_dpax_w_ph" -@@ -514,7 +514,7 @@ - UNSPEC_DPAX_W_PH))] - "ISA_HAS_DSPR2 && !TARGET_64BIT" - "dpax.w.ph\t%q0,%z2,%z3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmac") - (set_attr "mode" "SI")]) - - (define_insn "mips_dpsx_w_ph" -@@ -525,7 +525,7 @@ - UNSPEC_DPSX_W_PH))] - "ISA_HAS_DSPR2 && !TARGET_64BIT" - "dpsx.w.ph\t%q0,%z2,%z3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmac") - (set_attr "mode" "SI")]) - - (define_insn "mips_dpaqx_s_w_ph" -@@ -540,7 +540,7 @@ - UNSPEC_DPAQX_S_W_PH))])] - "ISA_HAS_DSPR2 && !TARGET_64BIT" - "dpaqx_s.w.ph\t%q0,%z2,%z3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmac") - (set_attr "mode" "SI")]) - - (define_insn "mips_dpaqx_sa_w_ph" -@@ -555,7 +555,7 @@ - UNSPEC_DPAQX_SA_W_PH))])] - "ISA_HAS_DSPR2 && !TARGET_64BIT" - "dpaqx_sa.w.ph\t%q0,%z2,%z3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmacsat") - (set_attr "mode" "SI")]) - - (define_insn "mips_dpsqx_s_w_ph" -@@ -570,7 +570,7 @@ - UNSPEC_DPSQX_S_W_PH))])] - "ISA_HAS_DSPR2 && !TARGET_64BIT" - "dpsqx_s.w.ph\t%q0,%z2,%z3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmac") - (set_attr "mode" "SI")]) - - (define_insn "mips_dpsqx_sa_w_ph" -@@ -585,5 +585,43 @@ - UNSPEC_DPSQX_SA_W_PH))])] - "ISA_HAS_DSPR2 && !TARGET_64BIT" - "dpsqx_sa.w.ph\t%q0,%z2,%z3" -- [(set_attr "type" "imadd") -+ [(set_attr "type" "dspmacsat") -+ (set_attr "mode" "SI")]) -+ -+;; Convert mtlo $ac[1-3],$0 => mult $ac[1-3],$0,$0 -+;; mthi $ac[1-3],$0 -+(define_peephole2 -+ [(set (match_operand:SI 0 "register_operand" "") -+ (const_int 0)) -+ (set (match_operand:SI 1 "register_operand" "") -+ (const_int 0))] -+ "ISA_HAS_DSPR2 -+ && !TARGET_MIPS16 -+ && !TARGET_64BIT -+ && (((true_regnum (operands[0]) == AC1LO_REGNUM -+ && true_regnum (operands[1]) == AC1HI_REGNUM) -+ || (true_regnum (operands[0]) == AC1HI_REGNUM -+ && true_regnum (operands[1]) == AC1LO_REGNUM)) -+ || ((true_regnum (operands[0]) == AC2LO_REGNUM -+ && true_regnum (operands[1]) == AC2HI_REGNUM) -+ || (true_regnum (operands[0]) == AC2HI_REGNUM -+ && true_regnum (operands[1]) == AC2LO_REGNUM)) -+ || ((true_regnum (operands[0]) == AC3LO_REGNUM -+ && true_regnum (operands[1]) == AC3HI_REGNUM) -+ || (true_regnum (operands[0]) == AC3HI_REGNUM -+ && true_regnum (operands[1]) == AC3LO_REGNUM)))" -+ [(parallel [(set (match_dup 0) (const_int 0)) -+ (set (match_dup 1) (const_int 0))])] -+) -+ -+(define_insn "*mips_acc_init" -+ [(parallel [(set (match_operand:SI 0 "register_operand" "=a") -+ (const_int 0)) -+ (set (match_operand:SI 1 "register_operand" "=a") -+ (const_int 0))])] -+ "ISA_HAS_DSPR2 -+ && !TARGET_MIPS16 -+ && !TARGET_64BIT" -+ "mult\t%q0,$0,$0\t\t# Clear ACC HI/LO" -+ [(set_attr "type" "imul") - (set_attr "mode" "SI")]) ---- a/gcc/config/mips/mips.h -+++ b/gcc/config/mips/mips.h -@@ -342,6 +342,9 @@ - #define TARGET_IRIX 0 - #define TARGET_IRIX6 0 - -+/* SDE specific stuff. */ -+#define TARGET_MIPS_SDE 0 -+ - /* Define preprocessor macros for the -march and -mtune options. - PREFIX is either _MIPS_ARCH or _MIPS_TUNE, INFO is the selected - processor. If INFO's canonical name is "foo", define PREFIX to -@@ -708,8 +711,9 @@ - |march=r10000|march=r12000|march=r14000|march=r16000:-mips4} \ - %{march=mips32|march=4kc|march=4km|march=4kp|march=4ksc:-mips32} \ - %{march=mips32r2|march=m4k|march=4ke*|march=4ksd|march=24k* \ -- |march=34k*|march=74k*: -mips32r2} \ -- %{march=mips64|march=5k*|march=20k*|march=sb1*|march=sr71000: -mips64} \ -+ |march=34k*|march=74k*|march=1004k*: -mips32r2} \ -+ %{march=mips64|march=5k*|march=20k*|march=sb1*|march=sr71000 \ -+ |march=xlr: -mips64} \ - %{march=mips64r2|march=octeon: -mips64r2} \ - %{!march=*: -" MULTILIB_ISA_DEFAULT "}}" - -@@ -720,7 +724,8 @@ - #define MIPS_ARCH_FLOAT_SPEC \ - "%{mhard-float|msoft-float|march=mips*:; \ - march=vr41*|march=m4k|march=4k*|march=24kc|march=24kec \ -- |march=34kc|march=74kc|march=5kc|march=octeon: -msoft-float; \ -+ |march=34kc|march=74kc|march=1004kc|march=5kc \ -+ |march=octeon|march=xlr: -msoft-float; \ - march=*: -mhard-float}" - - /* A spec condition that matches 32-bit options. It only works if -@@ -731,8 +736,9 @@ - - /* Support for a compile-time default CPU, et cetera. The rules are: - --with-arch is ignored if -march is specified or a -mips is specified -- (other than -mips16). -- --with-tune is ignored if -mtune is specified. -+ (other than -mips16); likewise --with-arch-32 and --with-arch-64. -+ --with-tune is ignored if -mtune is specified; likewise -+ --with-tune-32 and --with-tune-64. - --with-abi is ignored if -mabi is specified. - --with-float is ignored if -mhard-float or -msoft-float are - specified. -@@ -740,7 +746,11 @@ - specified. */ - #define OPTION_DEFAULT_SPECS \ - {"arch", "%{" MIPS_ARCH_OPTION_SPEC ":;: -march=%(VALUE)}" }, \ -+ {"arch_32", "%{!mabi=*|mabi=32:%{" MIPS_ARCH_OPTION_SPEC ":;: -march=%(VALUE)}}" }, \ -+ {"arch_64", "%{mabi=n32|mabi=64:%{" MIPS_ARCH_OPTION_SPEC ":;: -march=%(VALUE)}}" }, \ - {"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \ -+ {"tune_32", "%{!mabi=*|mabi=32:%{!mtune=*:-mtune=%(VALUE)}}" }, \ -+ {"tune_64", "%{mabi=n32|mabi=64:%{!mtune=*:-mtune=%(VALUE)}}" }, \ - {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \ - {"float", "%{!msoft-float:%{!mhard-float:-m%(VALUE)-float}}" }, \ - {"divide", "%{!mdivide-traps:%{!mdivide-breaks:-mdivide-%(VALUE)}}" }, \ -@@ -750,7 +760,7 @@ - - /* A spec that infers the -mdsp setting from an -march argument. */ - #define BASE_DRIVER_SELF_SPECS \ -- "%{!mno-dsp:%{march=24ke*|march=34k*|march=74k*: -mdsp}}" -+ "%{!mno-dsp:%{march=24ke*|march=34k*|march=74k*|march=1004k*: -mdsp}}" - - #define DRIVER_SELF_SPECS BASE_DRIVER_SELF_SPECS - -@@ -1038,6 +1048,11 @@ - /* ISA includes the bbit* instructions. */ - #define ISA_HAS_BBIT (TARGET_OCTEON && !TARGET_MIPS16) - -+/* ISA has single-instruction unaligned load/store support. */ -+#define ISA_HAS_UL_US (TARGET_OCTEON \ -+ && TARGET_OCTEON_UNALIGNED \ -+ && !TARGET_MIPS16) -+ - /* ISA includes the cins instruction. */ - #define ISA_HAS_CINS (TARGET_OCTEON && !TARGET_MIPS16) - -@@ -1055,6 +1070,7 @@ - - /* The CACHE instruction is available. */ - #define ISA_HAS_CACHE (TARGET_CACHE_BUILTIN && !TARGET_MIPS16) -+ - - /* Add -G xx support. */ - -@@ -1152,6 +1168,7 @@ - %{mshared} %{mno-shared} \ - %{msym32} %{mno-sym32} \ - %{mtune=*} %{v} \ -+%{mocteon-useun} %{mno-octeon-useun} \ - %(subtarget_asm_spec)" - - /* Extra switches sometimes passed to the linker. */ -@@ -1622,6 +1639,9 @@ - #define GP_REG_LAST 31 - #define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1) - #define GP_DBX_FIRST 0 -+#define K0_REG_NUM (GP_REG_FIRST + 26) -+#define K1_REG_NUM (GP_REG_FIRST + 27) -+#define KERNEL_REG_P(REGNO) (IN_RANGE (REGNO, K0_REG_NUM, K1_REG_NUM)) - - #define FP_REG_FIRST 32 - #define FP_REG_LAST 63 -@@ -1649,6 +1669,10 @@ - #define COP0_REG_LAST 111 - #define COP0_REG_NUM (COP0_REG_LAST - COP0_REG_FIRST + 1) - -+#define COP0_STATUS_REG_NUM (COP0_REG_FIRST + 12) -+#define COP0_CAUSE_REG_NUM (COP0_REG_FIRST + 13) -+#define COP0_EPC_REG_NUM (COP0_REG_FIRST + 14) -+ - #define COP2_REG_FIRST 112 - #define COP2_REG_LAST 143 - #define COP2_REG_NUM (COP2_REG_LAST - COP2_REG_FIRST + 1) -@@ -1666,6 +1690,29 @@ - #define AT_REGNUM (GP_REG_FIRST + 1) - #define HI_REGNUM (TARGET_BIG_ENDIAN ? MD_REG_FIRST : MD_REG_FIRST + 1) - #define LO_REGNUM (TARGET_BIG_ENDIAN ? MD_REG_FIRST + 1 : MD_REG_FIRST) -+#define AC1HI_REGNUM (TARGET_BIG_ENDIAN \ -+ ? DSP_ACC_REG_FIRST : DSP_ACC_REG_FIRST + 1) -+#define AC1LO_REGNUM (TARGET_BIG_ENDIAN \ -+ ? DSP_ACC_REG_FIRST + 1 : DSP_ACC_REG_FIRST) -+#define AC2HI_REGNUM (TARGET_BIG_ENDIAN \ -+ ? DSP_ACC_REG_FIRST + 2 : DSP_ACC_REG_FIRST + 3) -+#define AC2LO_REGNUM (TARGET_BIG_ENDIAN \ -+ ? DSP_ACC_REG_FIRST + 3 : DSP_ACC_REG_FIRST + 2) -+#define AC3HI_REGNUM (TARGET_BIG_ENDIAN \ -+ ? DSP_ACC_REG_FIRST + 4 : DSP_ACC_REG_FIRST + 5) -+#define AC3LO_REGNUM (TARGET_BIG_ENDIAN \ -+ ? DSP_ACC_REG_FIRST + 5 : DSP_ACC_REG_FIRST + 4) -+ -+/* A few bitfield locations for the coprocessor registers. */ -+/* Request Interrupt Priority Level is from bit 10 to bit 15 of -+ the cause register for the EIC interrupt mode. */ -+#define CAUSE_IPL 10 -+/* Interrupt Priority Level is from bit 10 to bit 15 of the status register. */ -+#define SR_IPL 10 -+/* Exception Level is at bit 1 of the status register. */ -+#define SR_EXL 1 -+/* Interrupt Enable is at bit 0 of the status register. */ -+#define SR_IE 0 - - /* FPSW_REGNUM is the single condition code used if !ISA_HAS_8CC. - If ISA_HAS_8CC, it should not be used, and an arbitrary ST_REG -@@ -1754,11 +1801,18 @@ - incoming arguments, the static chain pointer, or the frame pointer. - The epilogue temporary mustn't conflict with the return registers, - the PIC call register ($25), the frame pointer, the EH stack adjustment, -- or the EH data registers. */ -+ or the EH data registers. -+ -+ If we're generating interrupt handlers, we use K0 as a temporary register -+ in prologue/epilogue code. */ - - #define MIPS16_PIC_TEMP_REGNUM (GP_REG_FIRST + 2) --#define MIPS_PROLOGUE_TEMP_REGNUM (GP_REG_FIRST + 3) --#define MIPS_EPILOGUE_TEMP_REGNUM (GP_REG_FIRST + (TARGET_MIPS16 ? 6 : 8)) -+#define MIPS_PROLOGUE_TEMP_REGNUM \ -+ (cfun->machine->interrupt_handler_p ? K0_REG_NUM : GP_REG_FIRST + 3) -+#define MIPS_EPILOGUE_TEMP_REGNUM \ -+ (cfun->machine->interrupt_handler_p \ -+ ? K0_REG_NUM \ -+ : GP_REG_FIRST + (TARGET_MIPS16 ? 6 : 8)) - - #define MIPS16_PIC_TEMP gen_rtx_REG (Pmode, MIPS16_PIC_TEMP_REGNUM) - #define MIPS_PROLOGUE_TEMP(MODE) gen_rtx_REG (MODE, MIPS_PROLOGUE_TEMP_REGNUM) -@@ -2284,14 +2338,7 @@ - (mips_abi == ABI_EABI && UNITS_PER_FPVALUE >= UNITS_PER_DOUBLE) - - --/* Say that the epilogue uses the return address register. Note that -- in the case of sibcalls, the values "used by the epilogue" are -- considered live at the start of the called function. -- -- If using a GOT, say that the epilogue also uses GOT_VERSION_REGNUM. -- See the comment above load_call<mode> for details. */ --#define EPILOGUE_USES(REGNO) \ -- ((REGNO) == 31 || (TARGET_USE_GOT && (REGNO) == GOT_VERSION_REGNUM)) -+#define EPILOGUE_USES(REGNO) mips_epilogue_uses (REGNO) - - /* Treat LOC as a byte offset from the stack pointer and round it up - to the next fully-aligned offset. */ ---- a/gcc/config/mips/mips.md -+++ b/gcc/config/mips/mips.md -@@ -67,7 +67,16 @@ - (UNSPEC_SET_GOT_VERSION 46) - (UNSPEC_UPDATE_GOT_VERSION 47) - (UNSPEC_COPYGP 48) -+ (UNSPEC_ERET 49) -+ (UNSPEC_DERET 50) -+ (UNSPEC_DI 51) -+ (UNSPEC_EHB 52) -+ (UNSPEC_RDPGPR 53) -+ (UNSPEC_COP0 54) - -+ (UNSPEC_UNALIGNED_LOAD 60) -+ (UNSPEC_UNALIGNED_STORE 61) -+ - (UNSPEC_ADDRESS_FIRST 100) - - (TLS_GET_TP_REGNUM 3) -@@ -372,6 +381,12 @@ - ;; frsqrt floating point reciprocal square root - ;; frsqrt1 floating point reciprocal square root step1 - ;; frsqrt2 floating point reciprocal square root step2 -+;; dspmac DSP MAC instructions not saturating the accumulator -+;; dspmacsat DSP MAC instructions that saturate the accumulator -+;; accext DSP accumulator extract instructions -+;; accmod DSP accumulator modify instructions -+;; dspalu DSP ALU instructions not saturating the result -+;; dspalusat DSP ALU instructions that saturate the result - ;; multi multiword sequence (or user asm statements) - ;; nop no operation - ;; ghost an instruction that produces no real code -@@ -380,7 +395,7 @@ - prefetch,prefetchx,condmove,mtc,mfc,mthilo,mfhilo,const,arith,logical, - shift,slt,signext,clz,pop,trap,imul,imul3,imul3nc,imadd,idiv,idiv3,move, - fmove,fadd,fmul,fmadd,fdiv,frdiv,frdiv1,frdiv2,fabs,fneg,fcmp,fcvt,fsqrt, -- frsqrt,frsqrt1,frsqrt2,multi,nop,ghost" -+ frsqrt,frsqrt1,frsqrt2,dspmac,dspmacsat,accext,accmod,dspalu,dspalusat,multi,nop,ghost" - (cond [(eq_attr "jal" "!unset") (const_string "call") - (eq_attr "got" "load") (const_string "load") - -@@ -3565,7 +3580,9 @@ - (unspec:GPR [(match_operand:BLK 1 "memory_operand" "m") - (match_operand:QI 2 "memory_operand" "m")] - UNSPEC_LOAD_LEFT))] -- "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[1])" -+ "!TARGET_MIPS16 -+ && !ISA_HAS_UL_US -+ && mips_mem_fits_mode_p (<MODE>mode, operands[1])" - "<load>l\t%0,%2" - [(set_attr "move_type" "load") - (set_attr "mode" "<MODE>")]) -@@ -3576,7 +3593,9 @@ - (match_operand:QI 2 "memory_operand" "m") - (match_operand:GPR 3 "register_operand" "0")] - UNSPEC_LOAD_RIGHT))] -- "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[1])" -+ "!TARGET_MIPS16 -+ && !ISA_HAS_UL_US -+ && mips_mem_fits_mode_p (<MODE>mode, operands[1])" - "<load>r\t%0,%2" - [(set_attr "move_type" "load") - (set_attr "mode" "<MODE>")]) -@@ -3586,7 +3605,9 @@ - (unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ") - (match_operand:QI 2 "memory_operand" "m")] - UNSPEC_STORE_LEFT))] -- "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[0])" -+ "!TARGET_MIPS16 -+ && !ISA_HAS_UL_US -+ && mips_mem_fits_mode_p (<MODE>mode, operands[0])" - "<store>l\t%z1,%2" - [(set_attr "move_type" "store") - (set_attr "mode" "<MODE>")]) -@@ -3602,6 +3623,28 @@ - [(set_attr "move_type" "store") - (set_attr "mode" "<MODE>")]) - -+;; Unaligned load and store patterns. -+ -+(define_insn "mov_u<load>" -+ [(set (match_operand:GPR 0 "register_operand" "=d") -+ (unspec:GPR [(match_operand:BLK 1 "memory_operand" "m") -+ (match_operand:QI 2 "memory_operand" "m")] -+ UNSPEC_UNALIGNED_LOAD))] -+ "ISA_HAS_UL_US && mips_mem_fits_mode_p (<MODE>mode, operands[1])" -+ "u<load>\t%0,%2" -+ [(set_attr "type" "load") -+ (set_attr "mode" "<MODE>")]) -+ -+(define_insn "mov_u<store>" -+ [(set (match_operand:BLK 0 "memory_operand" "=m") -+ (unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ") -+ (match_operand:QI 2 "memory_operand" "m")] -+ UNSPEC_UNALIGNED_STORE))] -+ "ISA_HAS_UL_US && mips_mem_fits_mode_p (<MODE>mode, operands[0])" -+ "u<store>\t%z1,%2" -+ [(set_attr "type" "store") -+ (set_attr "mode" "<MODE>")]) -+ - ;; An instruction to calculate the high part of a 64-bit SYMBOL_ABSOLUTE. - ;; The required value is: - ;; -@@ -5472,6 +5515,26 @@ - return "%*b\t%l0%/"; - else - { -+ if (final_sequence && (mips_abi == ABI_32 || mips_abi == ABI_O64)) -+ { -+ /* If the delay slot contains a $gp restore, we need to -+ do that first, because we need it for the load -+ label. Other ABIs do not have caller-save $gp. */ -+ rtx next = NEXT_INSN (insn); -+ if (INSN_P (next) && !INSN_DELETED_P (next)) -+ { -+ rtx pat = PATTERN (next); -+ if (GET_CODE (pat) == SET -+ && REG_P (SET_DEST (pat)) -+ && REGNO (SET_DEST (pat)) == PIC_OFFSET_TABLE_REGNUM) -+ { -+ rtx ops[2]; -+ ops[0] = SET_DEST (pat); -+ ops[1] = SET_SRC (pat); -+ output_asm_insn (mips_output_move (ops[0], ops[1]), ops); -+ } -+ } -+ } - output_asm_insn (mips_output_load_label (), operands); - return "%*jr\t%@%/%]"; - } -@@ -5490,7 +5553,13 @@ - (lt (abs (minus (match_dup 0) - (plus (pc) (const_int 4)))) - (const_int 131072))) -- (const_int 4) (const_int 16)))]) -+ (const_int 4) -+ (if_then_else -+ ;; for these two ABIs we may need to move a restore of $gp -+ (ior (eq (symbol_ref "mips_abi") (symbol_ref "ABI_32")) -+ (eq (symbol_ref "mips_abi") (symbol_ref "ABI_O64"))) -+ (const_int 20) -+ (const_int 16))))]) - - ;; We need a different insn for the mips16, because a mips16 branch - ;; does not have a delay slot. -@@ -5679,6 +5748,60 @@ - [(set_attr "type" "jump") - (set_attr "mode" "none")]) - -+;; Exception return. -+(define_insn "mips_eret" -+ [(return) -+ (unspec_volatile [(const_int 0)] UNSPEC_ERET)] -+ "" -+ "eret" -+ [(set_attr "type" "trap") -+ (set_attr "mode" "none")]) -+ -+;; Debug exception return. -+(define_insn "mips_deret" -+ [(return) -+ (unspec_volatile [(const_int 0)] UNSPEC_DERET)] -+ "" -+ "deret" -+ [(set_attr "type" "trap") -+ (set_attr "mode" "none")]) -+ -+;; Disable interrupts. -+(define_insn "mips_di" -+ [(unspec_volatile [(const_int 0)] UNSPEC_DI)] -+ "" -+ "di" -+ [(set_attr "type" "trap") -+ (set_attr "mode" "none")]) -+ -+;; Execution hazard barrier. -+(define_insn "mips_ehb" -+ [(unspec_volatile [(const_int 0)] UNSPEC_EHB)] -+ "" -+ "ehb" -+ [(set_attr "type" "trap") -+ (set_attr "mode" "none")]) -+ -+;; Read GPR from previous shadow register set. -+(define_insn "mips_rdpgpr" -+ [(set (match_operand:SI 0 "register_operand" "=d") -+ (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "d")] -+ UNSPEC_RDPGPR))] -+ "" -+ "rdpgpr\t%0,%1" -+ [(set_attr "type" "move") -+ (set_attr "mode" "SI")]) -+ -+;; Move involving COP0 registers. -+(define_insn "cop0_move" -+ [(set (match_operand:SI 0 "register_operand" "=B,d") -+ (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "d,B")] -+ UNSPEC_COP0))] -+ "" -+{ return mips_output_move (operands[0], operands[1]); } -+ [(set_attr "type" "mtc,mfc") -+ (set_attr "mode" "SI")]) -+ - ;; This is used in compiling the unwind routines. - (define_expand "eh_return" - [(use (match_operand 0 "general_operand"))] ---- a/gcc/config/mips/mips.opt -+++ b/gcc/config/mips/mips.opt -@@ -184,6 +184,10 @@ - Target Report RejectNegative Mask(MIPS16) - Generate MIPS16 code - -+mips16e -+Target Report RejectNegative Mask(MIPS16) MaskExists -+Deprecated; alias for -mips16 -+ - mips3d - Target Report RejectNegative Mask(MIPS3D) - Use MIPS-3D instructions -@@ -236,6 +240,10 @@ - Target Report RejectNegative InverseMask(MIPS3D) - Do not use MIPS-3D instructions - -+mocteon-useun -+Target Report Mask(OCTEON_UNALIGNED) -+Use Octeon-specific unaligned loads/stores for 32/64-bit data -+ - mpaired-single - Target Report Mask(PAIRED_SINGLE_FLOAT) - Use paired-single floating-point instructions ---- a/gcc/config/mips/mips-protos.h -+++ b/gcc/config/mips/mips-protos.h -@@ -261,6 +261,8 @@ - extern void mips_output_external (FILE *, tree, const char *); - extern void mips_output_filename (FILE *, const char *); - extern void mips_output_ascii (FILE *, const char *, size_t); -+extern void octeon_output_shared_variable (FILE *, tree, const char *, -+ unsigned HOST_WIDE_INT, int); - extern void mips_output_aligned_decl_common (FILE *, tree, const char *, - unsigned HOST_WIDE_INT, - unsigned int); -@@ -307,6 +309,8 @@ - extern bool mips_linked_madd_p (rtx, rtx); - extern bool mips_store_data_bypass_p (rtx, rtx); - extern rtx mips_prefetch_cookie (rtx, rtx); -+extern int mips_mult_madd_chain_bypass_p (rtx, rtx); -+extern int mips_dspalu_bypass_p (rtx, rtx); - - extern void irix_asm_output_align (FILE *, unsigned); - extern const char *current_section_name (void); -@@ -332,4 +336,6 @@ - - extern void mips_expand_vector_init (rtx, rtx); - -+extern bool mips_epilogue_uses (unsigned int); -+ - #endif /* ! GCC_MIPS_PROTOS_H */ ---- /dev/null -+++ b/gcc/config/mips/octeon-elf.h -@@ -0,0 +1,98 @@ -+/* Macros for mips*-octeon-elf target. -+ Copyright (C) 2004, 2005, 2006 Cavium Networks. -+ -+This file is part of GCC. -+ -+GCC is free software; you can redistribute it and/or modify -+it under the terms of the GNU General Public License as published by -+the Free Software Foundation; either version 2, or (at your option) -+any later version. -+ -+GCC is distributed in the hope that it will be useful, -+but WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+GNU General Public License for more details. -+ -+You should have received a copy of the GNU General Public License -+along with GCC; see the file COPYING. If not, write to -+the Free Software Foundation, 51 Franklin Street, Fifth Floor, -+Boston, MA 02110-1301, USA. */ -+ -+/* Add MASK_SOFT_FLOAT and MASK_OCTEON_UNALIGNED. */ -+ -+#undef TARGET_DEFAULT -+#define TARGET_DEFAULT (MASK_SOFT_FLOAT_ABI | MASK_OCTEON_UNALIGNED) -+ -+/* Forward -m*octeon-useun. */ -+ -+#undef SUBTARGET_ASM_SPEC -+#define SUBTARGET_ASM_SPEC "%{mno-octeon-useun} %{!mno-octeon-useun:-mocteon-useun}" -+ -+/* Enable backtrace including on machine exceptions by default. */ -+ -+#undef SUBTARGET_CC1_SPEC -+#define SUBTARGET_CC1_SPEC "%{!fno-asynchronous-unwind-tables:-fasynchronous-unwind-tables}" -+ -+/* Without ASM_PREFERRED_EH_DATA_FORMAT, output_call_frame_info emits -+ pointer-sized addresses for FDE addresses. For 64-bit targets, it does -+ it without properly "switching over" to 64-bit as described in the DWARF3 -+ spec. GDB can fall back on .eh_frames and misinterpret FDE addresses. -+ Instead let's be explicit and use augmentation to describe the encoding if -+ pointer size is 64. */ -+ -+#undef ASM_PREFERRED_EH_DATA_FORMAT -+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \ -+ ((CODE) == 1 && POINTER_SIZE == 64 \ -+ ? (ABI_HAS_64BIT_SYMBOLS ? DW_EH_PE_udata8 : DW_EH_PE_udata4) \ -+ : DW_EH_PE_absptr) -+ -+/* Link to libc library. */ -+ -+#undef LIB_SPEC -+#define LIB_SPEC "-lc" -+ -+/* Link to startup file. */ -+ -+#undef STARTFILE_SPEC -+#define STARTFILE_SPEC "crti%O%s crtbegin%O%s crt0%O%s" -+ -+/* Default our test-only n64 configuration to -G0 since that is what -+ the kernel uses. */ -+ -+#undef SUBTARGET_SELF_SPECS -+#define SUBTARGET_SELF_SPECS \ -+"%{mabi=64:%{!G*: -G0}}" -+ -+/* Pass linker emulation mode for N32. */ -+ -+#undef LINK_SPEC -+#define LINK_SPEC "\ -+%(endian_spec) \ -+%{G*} %{mips1} %{mips2} %{mips3} %{mips4} %{mips32} %{mips32r2} %{mips64} \ -+%{mips64r2} %{bestGnum} %{shared} %{non_shared} \ -+%{mabi=n32:-melf32e%{!EL:b}%{EL:l}octeonn32} \ -+%{mabi=64:-melf64e%{!EL:b}%{EL:l}octeon}" -+ -+/* Override because of N32. */ -+ -+#undef LOCAL_LABEL_PREFIX -+#define LOCAL_LABEL_PREFIX ((mips_abi == ABI_N32) ? "." : "$") -+ -+/* Append the core number to the GCOV filename FN. */ -+ -+#define GCOV_TARGET_SUFFIX_LENGTH 2 -+#define ADD_GCOV_TARGET_SUFFIX(FN) \ -+do \ -+ { \ -+ char *fn = FN; \ -+ int core; \ -+ char s[3]; \ -+ \ -+ asm ("rdhwr %0, $0" : "=r"(core)); \ -+ sprintf (s, "%d", core); \ -+ strcat (fn, s); \ -+ } \ -+while (0) -+ -+/* Code to unwind through the exception frame. */ -+#define MD_UNWIND_SUPPORT "config/mips/octeon-elf-unwind.h" ---- /dev/null -+++ b/gcc/config/mips/octeon-elf-unwind.h -@@ -0,0 +1,57 @@ -+/* Stack unwinding support through the first exception frame. -+ Copyright (C) 2007 Cavium Networks. -+ -+This file is part of GCC. -+ -+GCC is free software; you can redistribute it and/or modify -+it under the terms of the GNU General Public License as published by -+the Free Software Foundation; either version 2, or (at your option) -+any later version. -+ -+GCC is distributed in the hope that it will be useful, -+but WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+GNU General Public License for more details. -+ -+You should have received a copy of the GNU General Public License -+along with GCC; see the file COPYING. If not, write to -+the Free Software Foundation, 51 Franklin Street, Fifth Floor, -+Boston, MA 02110-1301, USA. */ -+ -+#define MD_FALLBACK_FRAME_STATE_FOR octeon_elf_fallback_frame_state -+ -+/* Check whether this is the cvmx_interrupt_stage2 frame. If the -+ function call was dispatched via k0 assume we are in -+ cvmx_interrupt_stage2. In this case the sp in point to the saved -+ register array. */ -+ -+static _Unwind_Reason_Code -+octeon_elf_fallback_frame_state (struct _Unwind_Context *context, -+ _Unwind_FrameState *fs) -+{ -+ unsigned i; -+ unsigned *pc = context->ra; -+ -+ /* Look for "jalr k0". */ -+ if (pc[-2] != 0x0340f809) -+ return _URC_END_OF_STACK; -+ -+ for (i = 0; i < 32; i++) -+ { -+ fs->regs.reg[i].how = REG_SAVED_OFFSET; -+ fs->regs.reg[i].loc.offset = 8 * i; -+ } -+ -+ /* Keep the next frame's sp. This way we have a CFA that points -+ exactly to the register array. */ -+ fs->regs.cfa_how = CFA_REG_OFFSET; -+ fs->regs.cfa_reg = STACK_POINTER_REGNUM; -+ fs->regs.cfa_offset = 0; -+ -+ /* DEPC is saved as the 35. register. */ -+ fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].how = REG_SAVED_OFFSET; -+ fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].loc.offset = 8 * 35; -+ fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN; -+ -+ return _URC_NO_REASON; -+} ---- /dev/null -+++ b/gcc/config/mips/octeon.h -@@ -0,0 +1,68 @@ -+/* Macros for mips*-octeon-* target. -+ Copyright (C) 2004, 2005, 2006 Cavium Networks. -+ -+This file is part of GCC. -+ -+GCC is free software; you can redistribute it and/or modify -+it under the terms of the GNU General Public License as published by -+the Free Software Foundation; either version 2, or (at your option) -+any later version. -+ -+GCC is distributed in the hope that it will be useful, -+but WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+GNU General Public License for more details. -+ -+You should have received a copy of the GNU General Public License -+along with GCC; see the file COPYING. If not, write to -+the Free Software Foundation, 51 Franklin Street, Fifth Floor, -+Boston, MA 02110-1301, USA. */ -+ -+#define CVMX_SHARED_BSS_FLAGS (SECTION_WRITE | SECTION_BSS) -+ -+#undef TARGET_ASM_SELECT_SECTION -+#define TARGET_ASM_SELECT_SECTION octeon_select_section -+ -+#undef TARGET_ASM_UNIQUE_SECTION -+#define TARGET_ASM_UNIQUE_SECTION octeon_unique_section -+ -+/* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. This differs from the -+ generic version only in the use of cvmx_shared attribute. */ -+ -+#undef ASM_OUTPUT_ALIGNED_DECL_LOCAL -+#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGN) \ -+ do \ -+ { \ -+ if ((DECL) && TREE_CODE ((DECL)) == VAR_DECL \ -+ && lookup_attribute ("cvmx_shared", DECL_ATTRIBUTES (DECL))) \ -+ { \ -+ fprintf ((STREAM), "%s", LOCAL_ASM_OP); \ -+ assemble_name ((STREAM), (NAME)); \ -+ fprintf ((STREAM), "\n"); \ -+ octeon_output_shared_variable ((STREAM), (DECL), (NAME), \ -+ (SIZE), (ALIGN)); \ -+ } \ -+ else \ -+ ASM_OUTPUT_ALIGNED_LOCAL (STREAM, NAME, SIZE, ALIGN); \ -+ } \ -+ while (0) -+ -+ -+/* Implement ASM_OUTPUT_ALIGNED_DECL_COMMON. This differs from the mips -+ version only in the use of cvmx_shared attribute. */ -+ -+#undef ASM_OUTPUT_ALIGNED_DECL_COMMON -+#define ASM_OUTPUT_ALIGNED_DECL_COMMON(STREAM, DECL, NAME, SIZE, ALIGN) \ -+ { \ -+ if (TREE_CODE ((DECL)) == VAR_DECL \ -+ && lookup_attribute ("cvmx_shared", DECL_ATTRIBUTES ((DECL)))) \ -+ { \ -+ if (TREE_PUBLIC ((DECL)) && DECL_NAME ((DECL))) \ -+ targetm.asm_out.globalize_label (asm_out_file, (NAME)); \ -+ octeon_output_shared_variable ((STREAM), (DECL), (NAME), \ -+ (SIZE), (ALIGN)); \ -+ } \ -+ else \ -+ mips_output_aligned_decl_common ((STREAM), (DECL), (NAME), (SIZE), \ -+ (ALIGN)); \ -+ } ---- a/gcc/config/mips/predicates.md -+++ b/gcc/config/mips/predicates.md -@@ -211,6 +211,20 @@ - } - }) - -+(define_predicate "mask_low_and_shift_operator" -+ (and (match_code "and") -+ (match_test "GET_CODE (XEXP (op, 0)) == ASHIFT -+ && GET_CODE (XEXP (op, 1)) == CONST_INT -+ && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT")) -+{ -+ int len; -+ -+ len = mask_low_and_shift_len (GET_MODE (op), -+ INTVAL (XEXP (XEXP (op, 0), 1)), -+ INTVAL (XEXP (op, 1))); -+ return 0 < len && len <= 32; -+}) -+ - (define_predicate "consttable_operand" - (match_test "CONSTANT_P (op)")) - ---- a/gcc/config/mips/sde.h -+++ b/gcc/config/mips/sde.h -@@ -19,6 +19,9 @@ - along with GCC; see the file COPYING3. If not see - <http://www.gnu.org/licenses/>. */ - -+#undef TARGET_MIPS_SDE -+#define TARGET_MIPS_SDE 1 -+ - #undef DRIVER_SELF_SPECS - #define DRIVER_SELF_SPECS \ - /* Make sure a -mips option is present. This helps us to pick \ -@@ -90,7 +93,8 @@ - - /* Use $5 as a temporary for both MIPS16 and non-MIPS16. */ - #undef MIPS_EPILOGUE_TEMP_REGNUM --#define MIPS_EPILOGUE_TEMP_REGNUM (GP_REG_FIRST + 5) -+#define MIPS_EPILOGUE_TEMP_REGNUM \ -+ (cfun->machine->interrupt_handler_p ? K0_REG_NUM : GP_REG_FIRST + 5) - - /* Using long will always be right for size_t and ptrdiff_t, since - sizeof(long) must equal sizeof(void *), following from the setting ---- a/gcc/config/mips/sdemtk.h -+++ b/gcc/config/mips/sdemtk.h -@@ -19,6 +19,8 @@ - along with GCC; see the file COPYING3. If not see - <http://www.gnu.org/licenses/>. */ - -+#define TARGET_MIPS_SDEMTK 1 -+ - #define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ -@@ -113,3 +115,12 @@ - /* ...nor does the call sequence preserve $31. */ - #undef MIPS_SAVE_REG_FOR_PROFILING_P - #define MIPS_SAVE_REG_FOR_PROFILING_P(REGNO) ((REGNO) == GP_REG_FIRST + 31) -+ -+/* From mips.h, with mno-float option added. */ -+ -+#undef MIPS_ARCH_FLOAT_SPEC -+#define MIPS_ARCH_FLOAT_SPEC \ -+ "%{mhard-float|msoft-float|mno-float|march=mips*:; \ -+ march=vr41*|march=m4k|march=4k*|march=24kc|march=24kec \ -+ |march=34kc|march=74kc|march=1004kc|march=5kc|march=octeon|march=xlr: -msoft-float; \ -+ march=*: -mhard-float}" ---- /dev/null -+++ b/gcc/config/mips/t-crtfm -@@ -0,0 +1,9 @@ -+ -+EXTRA_MULTILIB_PARTS += crtfastmath.o -+ -+EXTRA_PARTS += crtfastmath.o -+ -+$(T)crtfastmath.o: $(srcdir)/config/mips/crtfastmath.c $(GCC_PASSES) -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \ -+ -c -o $(T)crtfastmath.o $(srcdir)/config/mips/crtfastmath.c -+ ---- /dev/null -+++ b/gcc/config/mips/t-octeon-elf -@@ -0,0 +1,41 @@ -+# Don't let CTOR_LIST end up in sdata section. -+ -+CRTSTUFF_T_CFLAGS = -G 0 -fno-asynchronous-unwind-tables -+ -+# Assemble startup files. -+ -+$(T)crti.o: $(srcdir)/config/mips/crti.asm $(GCC_PASSES) -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \ -+ -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/mips/crti.asm -+ -+$(T)crtn.o: $(srcdir)/config/mips/crtn.asm $(GCC_PASSES) -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \ -+ -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/mips/crtn.asm -+ -+# N32 uses TFmode for long double. -+ -+TPBIT = tp-bit.c -+ -+tp-bit.c: $(srcdir)/config/fp-bit.c -+ echo '#ifdef __MIPSEL__' > tp-bit.c -+ echo '# define FLOAT_BIT_ORDER_MISMATCH' >> tp-bit.c -+ echo '#endif' >> tp-bit.c -+ echo '#if __LDBL_MANT_DIG__ == 113' >> tp-bit.c -+ echo '#define QUIET_NAN_NEGATED' >> tp-bit.c -+ echo '# define TFLOAT' >> tp-bit.c -+ cat $(srcdir)/config/fp-bit.c >> tp-bit.c -+ echo '#endif' >> tp-bit.c -+ -+# We must build libgcc2.a with -G 0, in case the user wants to link -+# without the $gp register. -+ -+TARGET_LIBGCC2_CFLAGS = -G 0 -+ -+# Build both ABIs. -+ -+MULTILIB_OPTIONS = mabi=n32/mabi=eabi/mabi=64 -+MULTILIB_DIRNAMES = n32 eabi n64 -+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o -+ -+LIBGCC = stmp-multilib -+INSTALL_LIBGCC = install-multilib ---- a/gcc/config/mips/xlr.md -+++ b/gcc/config/mips/xlr.md -@@ -1,5 +1,5 @@ - ;; DFA-based pipeline description for the XLR. --;; Copyright (C) 2008 Free Software Foundation, Inc. -+;; Copyright (C) 2008, 2009 Free Software Foundation, Inc. - ;; - ;; xlr.md Machine Description for the RMI XLR Microprocessor - ;; This file is part of GCC. -@@ -31,7 +31,7 @@ - ;; Integer arithmetic instructions. - (define_insn_reservation "ir_xlr_alu" 1 - (and (eq_attr "cpu" "xlr") -- (eq_attr "type" "arith,shift,clz,const,unknown,multi,nop,trap")) -+ (eq_attr "type" "move,arith,shift,clz,logical,signext,const,unknown,multi,nop,trap")) - "xlr_main_pipe") - - ;; Integer arithmetic instructions. ---- /dev/null -+++ b/gcc/config/rs6000/e500mc.h -@@ -0,0 +1,46 @@ -+/* Core target definitions for GNU compiler -+ for IBM RS/6000 PowerPC targeted to embedded ELF systems. -+ Copyright (C) 1995, 1996, 2000, 2003, 2004, 2007 Free Software Foundation, Inc. -+ Contributed by Cygnus Support. -+ -+ This file is part of GCC. -+ -+ GCC is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published -+ by the Free Software Foundation; either version 3, or (at your -+ option) any later version. -+ -+ GCC is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+ License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with GCC; see the file COPYING3. If not see -+ <http://www.gnu.org/licenses/>. */ -+ -+/* Add -meabi to target flags. */ -+#undef TARGET_DEFAULT -+#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_EABI) -+ -+#undef TARGET_VERSION -+#define TARGET_VERSION fprintf (stderr, " (PowerPC Embedded)"); -+ -+#undef TARGET_OS_CPP_BUILTINS -+#define TARGET_OS_CPP_BUILTINS() \ -+ do \ -+ { \ -+ builtin_define_std ("PPC"); \ -+ builtin_define ("__embedded__"); \ -+ builtin_assert ("system=embedded"); \ -+ builtin_assert ("cpu=powerpc"); \ -+ builtin_assert ("machine=powerpc"); \ -+ TARGET_OS_SYSV_CPP_BUILTINS (); \ -+ } \ -+ while (0) -+ -+#undef CC1_EXTRA_SPEC -+#define CC1_EXTRA_SPEC "-maix-struct-return" -+ -+#undef ASM_DEFAULT_SPEC -+#define ASM_DEFAULT_SPEC "-mppc%{m64:64} -me500mc" ---- a/gcc/config/rs6000/eabi.asm -+++ b/gcc/config/rs6000/eabi.asm -@@ -230,7 +230,7 @@ - r11 has the address of .LCTOC1 in it. - r12 has the value to add to each pointer - r13 .. r31 are unchanged */ -- -+#ifdef _RELOCATABLE - FUNC_START(__eabi_convert) - cmplw 1,3,4 /* any pointers to convert? */ - subf 5,3,4 /* calculate number of words to convert */ -@@ -285,5 +285,5 @@ - blr - - FUNC_END(__eabi_uconvert) -- -+#endif - #endif ---- a/gcc/config/rs6000/eabi-ci.asm -+++ b/gcc/config/rs6000/eabi-ci.asm -@@ -98,6 +98,7 @@ - /* Head of __init function used for static constructors. */ - .section ".init","ax" - .align 2 -+FUNC_START(_init) - FUNC_START(__init) - stwu 1,-16(1) - mflr 0 -@@ -106,6 +107,7 @@ - /* Head of __fini function used for static destructors. */ - .section ".fini","ax" - .align 2 -+FUNC_START(_fini) - FUNC_START(__fini) - stwu 1,-16(1) - mflr 0 ---- a/gcc/config/rs6000/eabi.h -+++ b/gcc/config/rs6000/eabi.h -@@ -23,10 +23,6 @@ - #undef TARGET_DEFAULT - #define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_EABI) - --/* Invoke an initializer function to set up the GOT. */ --#define NAME__MAIN "__eabi" --#define INVOKE__main -- - #undef TARGET_VERSION - #define TARGET_VERSION fprintf (stderr, " (PowerPC Embedded)"); - -@@ -42,3 +38,20 @@ - TARGET_OS_SYSV_CPP_BUILTINS (); \ - } \ - while (0) -+ -+/* Add -te500v1 and -te500v2 options for convenience in generating -+ multilibs. */ -+#undef CC1_EXTRA_SPEC -+#define CC1_EXTRA_SPEC \ -+ "%{te500v1: -mcpu=8540 -mfloat-gprs=single -mspe=yes -mabi=spe} " \ -+ "%{te500v2: -mcpu=8548 -mfloat-gprs=double -mspe=yes -mabi=spe} " \ -+ "%{te600: -mcpu=7400 -maltivec -mabi=altivec}" \ -+ "%{te500mc: -mcpu=e500mc -maix-struct-return}" -+ -+#undef ASM_DEFAULT_SPEC -+#define ASM_DEFAULT_SPEC \ -+ "%{te500v1:-mppc -mspe -me500 ; \ -+ te500v2:-mppc -mspe -me500 ; \ -+ te600:-mppc -maltivec ; \ -+ te500mc:-mppc -me500mc ; \ -+ :-mppc%{m64:64}}" ---- a/gcc/config/rs6000/linux.h -+++ b/gcc/config/rs6000/linux.h -@@ -128,3 +128,29 @@ - #ifdef TARGET_DEFAULT_LONG_DOUBLE_128 - #define RS6000_DEFAULT_LONG_DOUBLE_SIZE 128 - #endif -+ -+/* Add -te500v1 and -te500v2 options for convenience in generating -+ multilibs. */ -+#undef CC1_EXTRA_SPEC -+#define CC1_EXTRA_SPEC \ -+ "%{te500v1: -mcpu=8540 -mfloat-gprs=single -mspe=yes -mabi=spe} " \ -+ "%{te500v2: -mcpu=8548 -mfloat-gprs=double -mspe=yes -mabi=spe} " \ -+ "%{te600: -mcpu=7400 -maltivec -mabi=altivec}" \ -+ "%{te500mc: -mcpu=e500mc}" -+ -+#undef ASM_DEFAULT_SPEC -+#define ASM_DEFAULT_SPEC \ -+ "%{te500v1:-mppc -mspe -me500 ; \ -+ te500v2:-mppc -mspe -me500 ; \ -+ te600:-mppc -maltivec ; \ -+ te500mc:-me500mc ; \ -+ :-mppc%{m64:64}}" -+ -+/* The various C libraries each have their own subdirectory. */ -+#undef SYSROOT_SUFFIX_SPEC -+#define SYSROOT_SUFFIX_SPEC \ -+ "%{msoft-float:/nof ; \ -+ te600:/te600 ; \ -+ te500v1:/te500v1 ; \ -+ te500v2:/te500v2 ; \ -+ te500mc:/te500mc}" ---- /dev/null -+++ b/gcc/config/rs6000/option-defaults.h -@@ -0,0 +1,64 @@ -+/* Definitions of default options for config/rs6000 configurations. -+ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 -+ Free Software Foundation, Inc. -+ -+ This file is part of GCC. -+ -+ GCC is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published -+ by the Free Software Foundation; either version 3, or (at your -+ option) any later version. -+ -+ GCC is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+ License for more details. -+ -+ Under Section 7 of GPL version 3, you are granted additional -+ permissions described in the GCC Runtime Library Exception, version -+ 3.1, as published by the Free Software Foundation. -+ -+ You should have received a copy of the GNU General Public License and -+ a copy of the GCC Runtime Library Exception along with this program; -+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -+ <http://www.gnu.org/licenses/>. */ -+ -+/* This header needs to be included after any other headers affecting -+ TARGET_DEFAULT. */ -+ -+#if TARGET_AIX -+#define OPT_64 "maix64" -+#define OPT_32 "maix32" -+#else -+#define OPT_64 "m64" -+#define OPT_32 "m32" -+#endif -+ -+#ifndef MASK_64BIT -+#define MASK_64BIT 0 -+#endif -+ -+#if TARGET_DEFAULT & MASK_64BIT -+#define OPT_ARCH64 "!"OPT_32 -+#define OPT_ARCH32 OPT_32 -+#else -+#define OPT_ARCH64 OPT_64 -+#define OPT_ARCH32 "!"OPT_64 -+#endif -+ -+/* Support for a compile-time default CPU, et cetera. The rules are: -+ --with-cpu is ignored if -mcpu is specified; likewise --with-cpu-32 -+ and --with-cpu-64. -+ --with-tune is ignored if -mtune is specified; likewise --with-tune-32 -+ and --with-tune-64. -+ --with-float is ignored if -mhard-float or -msoft-float are -+ specified. */ -+#define OPTION_DEFAULT_SPECS \ -+ {"cpu", "%{mcpu=*|te500mc|te500v1|te500v2|te600:;:-mcpu=%(VALUE)}" }, \ -+ {"cpu_32", "%{" OPT_ARCH32 ":%{mcpu=*|te500mc|te500v1|te500v2|te600:;:-mcpu=%(VALUE)}}" }, \ -+ {"cpu_64", "%{" OPT_ARCH64 ":%{mcpu=*|te500mc|te500v1|te500v2|te600:;:-mcpu=%(VALUE)}}" }, \ -+ {"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \ -+ {"tune_32", "%{" OPT_ARCH32 ":%{!mtune=*:-mtune=%(VALUE)}}" }, \ -+ {"tune_64", "%{" OPT_ARCH64 ":%{!mtune=*:-mtune=%(VALUE)}}" }, \ -+ {"float", "%{!msoft-float:%{!mhard-float:-m%(VALUE)-float}}" } ---- a/gcc/config/rs6000/paired.md -+++ b/gcc/config/rs6000/paired.md -@@ -27,7 +27,7 @@ - (UNSPEC_EXTODD_V2SF 333) - ]) - --(define_insn "negv2sf2" -+(define_insn "paired_negv2sf2" - [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") - (neg:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")))] - "TARGET_PAIRED_FLOAT" -@@ -41,7 +41,7 @@ - "ps_rsqrte %0,%1" - [(set_attr "type" "fp")]) - --(define_insn "absv2sf2" -+(define_insn "paired_absv2sf2" - [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") - (abs:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")))] - "TARGET_PAIRED_FLOAT" -@@ -55,7 +55,7 @@ - "ps_nabs %0,%1" - [(set_attr "type" "fp")]) - --(define_insn "addv2sf3" -+(define_insn "paired_addv2sf3" - [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") - (plus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "%f") - (match_operand:V2SF 2 "gpc_reg_operand" "f")))] -@@ -63,7 +63,7 @@ - "ps_add %0,%1,%2" - [(set_attr "type" "fp")]) - --(define_insn "subv2sf3" -+(define_insn "paired_subv2sf3" - [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") - (minus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f") - (match_operand:V2SF 2 "gpc_reg_operand" "f")))] -@@ -71,7 +71,7 @@ - "ps_sub %0,%1,%2" - [(set_attr "type" "fp")]) - --(define_insn "mulv2sf3" -+(define_insn "paired_mulv2sf3" - [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") - (mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "%f") - (match_operand:V2SF 2 "gpc_reg_operand" "f")))] -@@ -86,7 +86,7 @@ - "ps_res %0,%1" - [(set_attr "type" "fp")]) - --(define_insn "divv2sf3" -+(define_insn "paired_divv2sf3" - [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") - (div:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f") - (match_operand:V2SF 2 "gpc_reg_operand" "f")))] ---- a/gcc/config/rs6000/rs6000.c -+++ b/gcc/config/rs6000/rs6000.c -@@ -919,6 +919,7 @@ - static bool rs6000_is_opaque_type (const_tree); - static rtx rs6000_dwarf_register_span (rtx); - static void rs6000_init_dwarf_reg_sizes_extra (tree); -+static int rs6000_commutative_operand_precedence (const_rtx, int); - static rtx rs6000_legitimize_tls_address (rtx, enum tls_model); - static void rs6000_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED; - static rtx rs6000_tls_get_addr (void); -@@ -1194,6 +1195,10 @@ - #undef TARGET_VECTOR_OPAQUE_P - #define TARGET_VECTOR_OPAQUE_P rs6000_is_opaque_type - -+#undef TARGET_COMMUTATIVE_OPERAND_PRECEDENCE -+#define TARGET_COMMUTATIVE_OPERAND_PRECEDENCE \ -+ rs6000_commutative_operand_precedence -+ - #undef TARGET_DWARF_REGISTER_SPAN - #define TARGET_DWARF_REGISTER_SPAN rs6000_dwarf_register_span - -@@ -4682,16 +4687,19 @@ - if (TARGET_ALTIVEC) - global_regs[VSCR_REGNO] = 1; - -- if (TARGET_ALTIVEC_ABI) -- { -- for (i = FIRST_ALTIVEC_REGNO; i < FIRST_ALTIVEC_REGNO + 20; ++i) -- call_used_regs[i] = call_really_used_regs[i] = 1; -+ /* If we are not using the AltiVec ABI, pretend that the normally -+ call-saved registers are also call-used. We could use them -+ normally if we saved and restored them in the prologue; that -+ would require using the alignment padding around the register -+ save area, and some care with unwinding information. */ -+ if (! TARGET_ALTIVEC_ABI) -+ for (i = FIRST_ALTIVEC_REGNO + 20; i <= LAST_ALTIVEC_REGNO; ++i) -+ call_used_regs[i] = call_really_used_regs[i] = 1; - -- /* AIX reserves VR20:31 in non-extended ABI mode. */ -- if (TARGET_XCOFF) -- for (i = FIRST_ALTIVEC_REGNO + 20; i < FIRST_ALTIVEC_REGNO + 32; ++i) -- fixed_regs[i] = call_used_regs[i] = call_really_used_regs[i] = 1; -- } -+ if (TARGET_ALTIVEC_ABI && TARGET_XCOFF) -+ /* AIX reserves VR20:31 in non-extended ABI mode. */ -+ for (i = FIRST_ALTIVEC_REGNO + 20; i < FIRST_ALTIVEC_REGNO + 32; ++i) -+ fixed_regs[i] = call_used_regs[i] = call_really_used_regs[i] = 1; - } - - /* Try to output insns to set TARGET equal to the constant C if it can -@@ -7507,10 +7515,10 @@ - { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sums", ALTIVEC_BUILTIN_VEC_SUMS }, - { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_xor", ALTIVEC_BUILTIN_VEC_XOR }, - -- { 0, CODE_FOR_divv2sf3, "__builtin_paired_divv2sf3", PAIRED_BUILTIN_DIVV2SF3 }, -- { 0, CODE_FOR_addv2sf3, "__builtin_paired_addv2sf3", PAIRED_BUILTIN_ADDV2SF3 }, -- { 0, CODE_FOR_subv2sf3, "__builtin_paired_subv2sf3", PAIRED_BUILTIN_SUBV2SF3 }, -- { 0, CODE_FOR_mulv2sf3, "__builtin_paired_mulv2sf3", PAIRED_BUILTIN_MULV2SF3 }, -+ { 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 }, -@@ -7519,10 +7527,10 @@ - { 0, CODE_FOR_paired_merge11, "__builtin_paired_merge11", PAIRED_BUILTIN_MERGE11 }, - - /* Place holder, leave as first spe builtin. */ -- { 0, CODE_FOR_spe_evaddw, "__builtin_spe_evaddw", SPE_BUILTIN_EVADDW }, -- { 0, CODE_FOR_spe_evand, "__builtin_spe_evand", SPE_BUILTIN_EVAND }, -+ { 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_spe_evdivws, "__builtin_spe_evdivws", SPE_BUILTIN_EVDIVWS }, -+ { 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 }, -@@ -7798,7 +7806,7 @@ - - /* The SPE unary builtins must start with SPE_BUILTIN_EVABS and - end with SPE_BUILTIN_EVSUBFUSIAAW. */ -- { 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS }, -+ { 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 }, -@@ -7830,9 +7838,9 @@ - /* Place-holder. Leave as last unary SPE builtin. */ - { 0, CODE_FOR_spe_evsubfusiaaw, "__builtin_spe_evsubfusiaaw", SPE_BUILTIN_EVSUBFUSIAAW }, - -- { 0, CODE_FOR_absv2sf2, "__builtin_paired_absv2sf2", PAIRED_BUILTIN_ABSV2SF2 }, -+ { 0, CODE_FOR_paired_absv2sf2, "__builtin_paired_absv2sf2", PAIRED_BUILTIN_ABSV2SF2 }, - { 0, CODE_FOR_nabsv2sf2, "__builtin_paired_nabsv2sf2", PAIRED_BUILTIN_NABSV2SF2 }, -- { 0, CODE_FOR_negv2sf2, "__builtin_paired_negv2sf2", PAIRED_BUILTIN_NEGV2SF2 }, -+ { 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 } - }; -@@ -9370,6 +9378,8 @@ - static void - rs6000_init_builtins (void) - { -+ tree tdecl; -+ - V2SI_type_node = build_vector_type (intSI_type_node, 2); - V2SF_type_node = build_vector_type (float_type_node, 2); - V4HI_type_node = build_vector_type (intHI_type_node, 4); -@@ -9407,60 +9417,75 @@ - float_type_internal_node = float_type_node; - void_type_internal_node = void_type_node; - -- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, -- get_identifier ("__bool char"), -- bool_char_type_node)); -- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, -- get_identifier ("__bool short"), -- bool_short_type_node)); -- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, -- get_identifier ("__bool int"), -- bool_int_type_node)); -- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, -- get_identifier ("__pixel"), -- pixel_type_node)); -+ tdecl = build_decl (TYPE_DECL, get_identifier ("__bool char"), -+ bool_char_type_node); -+ TYPE_NAME (bool_char_type_node) = tdecl; -+ (*lang_hooks.decls.pushdecl) (tdecl); -+ tdecl = build_decl (TYPE_DECL, get_identifier ("__bool short"), -+ bool_short_type_node); -+ TYPE_NAME (bool_short_type_node) = tdecl; -+ (*lang_hooks.decls.pushdecl) (tdecl); -+ tdecl = build_decl (TYPE_DECL, get_identifier ("__bool int"), -+ bool_int_type_node); -+ TYPE_NAME (bool_int_type_node) = tdecl; -+ (*lang_hooks.decls.pushdecl) (tdecl); -+ tdecl = build_decl (TYPE_DECL, get_identifier ("__pixel"), -+ pixel_type_node); -+ TYPE_NAME (pixel_type_node) = tdecl; -+ (*lang_hooks.decls.pushdecl) (tdecl); - - bool_V16QI_type_node = build_vector_type (bool_char_type_node, 16); - bool_V8HI_type_node = build_vector_type (bool_short_type_node, 8); - bool_V4SI_type_node = build_vector_type (bool_int_type_node, 4); - pixel_V8HI_type_node = build_vector_type (pixel_type_node, 8); - -- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, -- get_identifier ("__vector unsigned char"), -- unsigned_V16QI_type_node)); -- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, -- get_identifier ("__vector signed char"), -- V16QI_type_node)); -- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, -- get_identifier ("__vector __bool char"), -- bool_V16QI_type_node)); -- -- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, -- get_identifier ("__vector unsigned short"), -- unsigned_V8HI_type_node)); -- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, -- get_identifier ("__vector signed short"), -- V8HI_type_node)); -- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, -- get_identifier ("__vector __bool short"), -- bool_V8HI_type_node)); -- -- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, -- get_identifier ("__vector unsigned int"), -- unsigned_V4SI_type_node)); -- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, -- get_identifier ("__vector signed int"), -- V4SI_type_node)); -- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, -- get_identifier ("__vector __bool int"), -- bool_V4SI_type_node)); -- -- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, -- get_identifier ("__vector float"), -- V4SF_type_node)); -- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, -- get_identifier ("__vector __pixel"), -- pixel_V8HI_type_node)); -+ tdecl = build_decl (TYPE_DECL, get_identifier ("__vector unsigned char"), -+ unsigned_V16QI_type_node); -+ TYPE_NAME (unsigned_V16QI_type_node) = tdecl; -+ (*lang_hooks.decls.pushdecl) (tdecl); -+ tdecl = build_decl (TYPE_DECL, get_identifier ("__vector signed char"), -+ V16QI_type_node); -+ TYPE_NAME (V16QI_type_node) = tdecl; -+ (*lang_hooks.decls.pushdecl) (tdecl); -+ tdecl = build_decl (TYPE_DECL, get_identifier ("__vector __bool char"), -+ bool_V16QI_type_node); -+ TYPE_NAME ( bool_V16QI_type_node) = tdecl; -+ (*lang_hooks.decls.pushdecl) (tdecl); -+ -+ tdecl = build_decl (TYPE_DECL, get_identifier ("__vector unsigned short"), -+ unsigned_V8HI_type_node); -+ TYPE_NAME (unsigned_V8HI_type_node) = tdecl; -+ (*lang_hooks.decls.pushdecl) (tdecl); -+ tdecl = build_decl (TYPE_DECL, get_identifier ("__vector signed short"), -+ V8HI_type_node); -+ TYPE_NAME (V8HI_type_node) = tdecl; -+ (*lang_hooks.decls.pushdecl) (tdecl); -+ tdecl = build_decl (TYPE_DECL, get_identifier ("__vector __bool short"), -+ bool_V8HI_type_node); -+ TYPE_NAME (bool_V8HI_type_node) = tdecl; -+ (*lang_hooks.decls.pushdecl) (tdecl); -+ -+ tdecl = build_decl (TYPE_DECL, get_identifier ("__vector unsigned int"), -+ unsigned_V4SI_type_node); -+ TYPE_NAME (unsigned_V4SI_type_node) = tdecl; -+ (*lang_hooks.decls.pushdecl) (tdecl); -+ tdecl = build_decl (TYPE_DECL, get_identifier ("__vector signed int"), -+ V4SI_type_node); -+ TYPE_NAME (V4SI_type_node) = tdecl; -+ (*lang_hooks.decls.pushdecl) (tdecl); -+ tdecl = build_decl (TYPE_DECL, get_identifier ("__vector __bool int"), -+ bool_V4SI_type_node); -+ TYPE_NAME (bool_V4SI_type_node) = tdecl; -+ (*lang_hooks.decls.pushdecl) (tdecl); -+ -+ tdecl = build_decl (TYPE_DECL, get_identifier ("__vector float"), -+ V4SF_type_node); -+ TYPE_NAME (V4SF_type_node) = tdecl; -+ (*lang_hooks.decls.pushdecl) (tdecl); -+ tdecl = build_decl (TYPE_DECL, get_identifier ("__vector __pixel"), -+ pixel_V8HI_type_node); -+ TYPE_NAME (pixel_V8HI_type_node) = tdecl; -+ (*lang_hooks.decls.pushdecl) (tdecl); - - if (TARGET_PAIRED_FLOAT) - paired_init_builtins (); -@@ -15843,7 +15868,7 @@ - no_global_regs_above (int first, bool gpr) - { - int i; -- for (i = first; i < gpr ? 32 : 64 ; i++) -+ for (i = first; i < (gpr ? 32 : 64); i++) - if (global_regs[i]) - return false; - return true; -@@ -15869,11 +15894,11 @@ - int regno = gpr ? info->first_gp_reg_save : (info->first_fp_reg_save - 32); - rtx sym; - int select = ((savep ? 1 : 0) << 2 -- | (gpr -+ | (TARGET_SPE_ABI - /* On the SPE, we never have any FPRs, but we do have - 32/64-bit versions of the routines. */ -- ? (TARGET_SPE_ABI && info->spe_64bit_regs_used ? 1 : 0) -- : 0) << 1 -+ ? (info->spe_64bit_regs_used ? 1 : 0) -+ : (gpr ? 1 : 0)) << 1 - | (exitp ? 1: 0)); - - /* Don't generate bogus routine names. */ -@@ -15908,6 +15933,7 @@ - - sym = savres_routine_syms[regno-FIRST_SAVRES_REGISTER][select] - = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name)); -+ SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_FUNCTION; - } - - return sym; -@@ -16098,6 +16124,14 @@ - savres_gprs_inline = savres_gprs_inline || using_multiple_p; - } - -+ /* Code intended for use in shared libraries cannot be reliably linked -+ with out-of-line prologues and epilogues. */ -+ if (flag_pic) -+ { -+ savres_gprs_inline = 1; -+ savres_fprs_inline = 1; -+ } -+ - return (using_multiple_p - | (savres_fprs_inline << 1) - | (savres_gprs_inline << 2)); -@@ -16122,7 +16156,7 @@ - int using_store_multiple; - int using_static_chain_p = (cfun->static_chain_decl != NULL_TREE - && df_regs_ever_live_p (STATIC_CHAIN_REGNUM) -- && !call_used_regs[STATIC_CHAIN_REGNUM]); -+ && call_used_regs[STATIC_CHAIN_REGNUM]); - HOST_WIDE_INT sp_offset = 0; - - if (TARGET_FIX_AND_CONTINUE) -@@ -16924,8 +16958,9 @@ - || (cfun->calls_alloca - && !frame_pointer_needed)); - restore_lr = (info->lr_save_p -- && restoring_GPRs_inline -- && restoring_FPRs_inline); -+ && (restoring_GPRs_inline -+ || (restoring_FPRs_inline -+ && info->first_fp_reg_save < 64))); - - if (WORLD_SAVE_P (info)) - { -@@ -17197,7 +17232,7 @@ - - /* Get the old lr if we saved it. If we are restoring registers - out-of-line, then the out-of-line routines can do this for us. */ -- if (restore_lr) -+ if (restore_lr && restoring_GPRs_inline) - { - rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx, - info->lr_save_offset + sp_offset); -@@ -17216,7 +17251,7 @@ - } - - /* Set LR here to try to overlap restores below. */ -- if (restore_lr) -+ if (restore_lr && restoring_GPRs_inline) - emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO), - gen_rtx_REG (Pmode, 0)); - -@@ -17396,6 +17431,18 @@ - } - } - -+ if (restore_lr && !restoring_GPRs_inline) -+ { -+ rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx, -+ info->lr_save_offset + sp_offset); -+ -+ emit_move_insn (gen_rtx_REG (Pmode, 0), mem); -+ } -+ -+ if (restore_lr && !restoring_GPRs_inline) -+ emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO), -+ gen_rtx_REG (Pmode, 0)); -+ - /* 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++) -@@ -22163,6 +22210,30 @@ - return 4 + rs6000_register_move_cost (mode, rclass, GENERAL_REGS); - } - -+/* Return a value indicating whether OP, an operand of a commutative -+ operation, is preferred as the first or second operand. The higher -+ the value, the stronger the preference for being the first operand. -+ We use negative values to indicate a preference for the first operand -+ and positive values for the second operand. -+ VALUE is the default precedence for OP; see rtlanal.c: -+ commutative_operand_precendece. */ -+ -+static int -+rs6000_commutative_operand_precedence (const_rtx op, int value) -+{ -+ /* Prefer pointer objects over non pointer objects. -+ For rationale see PR28690. */ -+ if (GET_RTX_CLASS (GET_CODE (op)) == RTX_OBJ -+ && ((REG_P (op) && REG_POINTER (op)) -+ || (MEM_P (op) && MEM_POINTER (op)))) -+ /* value = -1 */; -+ else -+ /* value = -2 */ -+ --value; -+ -+ return value; -+} -+ - /* Returns a code for a target-specific builtin that implements - reciprocal of the function, or NULL_TREE if not available. */ - -@@ -22686,12 +22757,16 @@ - static rtx - rs6000_dwarf_register_span (rtx reg) - { -- unsigned regno; -+ rtx parts[8]; -+ int i, words; -+ unsigned regno = REGNO (reg); -+ enum machine_mode mode = GET_MODE (reg); - - if (TARGET_SPE -+ && regno < 32 - && (SPE_VECTOR_MODE (GET_MODE (reg)) -- || (TARGET_E500_DOUBLE -- && (GET_MODE (reg) == DFmode || GET_MODE (reg) == DDmode)))) -+ || (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) -+ && mode != SFmode && mode != SDmode && mode != SCmode))) - ; - else - return NULL_RTX; -@@ -22701,15 +22776,23 @@ - /* The duality of the SPE register size wreaks all kinds of havoc. - This is a way of distinguishing r0 in 32-bits from r0 in - 64-bits. */ -- return -- gen_rtx_PARALLEL (VOIDmode, -- BYTES_BIG_ENDIAN -- ? gen_rtvec (2, -- gen_rtx_REG (SImode, regno + 1200), -- gen_rtx_REG (SImode, regno)) -- : gen_rtvec (2, -- gen_rtx_REG (SImode, regno), -- gen_rtx_REG (SImode, regno + 1200))); -+ words = (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD; -+ gcc_assert (words <= 4); -+ for (i = 0; i < words; i++, regno++) -+ { -+ if (BYTES_BIG_ENDIAN) -+ { -+ parts[2 * i] = gen_rtx_REG (SImode, regno + 1200); -+ parts[2 * i + 1] = gen_rtx_REG (SImode, regno); -+ } -+ else -+ { -+ parts[2 * i] = gen_rtx_REG (SImode, regno); -+ parts[2 * i + 1] = gen_rtx_REG (SImode, regno + 1200); -+ } -+ } -+ -+ return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (words * 2, parts)); - } - - /* Fill in sizes for SPE register high parts in table used by unwinder. */ ---- a/gcc/config/rs6000/rs6000.h -+++ b/gcc/config/rs6000/rs6000.h -@@ -368,16 +368,6 @@ - previous_group - }; - --/* Support for a compile-time default CPU, et cetera. The rules are: -- --with-cpu is ignored if -mcpu is specified. -- --with-tune is ignored if -mtune is specified. -- --with-float is ignored if -mhard-float or -msoft-float are -- specified. */ --#define OPTION_DEFAULT_SPECS \ -- {"cpu", "%{!mcpu=*:-mcpu=%(VALUE)}" }, \ -- {"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \ -- {"float", "%{!msoft-float:%{!mhard-float:-m%(VALUE)-float}}" } -- - /* rs6000_select[0] is reserved for the default cpu defined via --with-cpu */ - struct rs6000_cpu_select - { -@@ -794,8 +784,8 @@ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, \ - /* AltiVec registers. */ \ -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ -+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -+ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 1, 1 \ - , 1, 1, 1 \ - } -@@ -813,8 +803,8 @@ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, \ - /* AltiVec registers. */ \ -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ -+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ -+ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0 \ - , 0, 0, 0 \ - } ---- a/gcc/config/rs6000/rs6000.md -+++ b/gcc/config/rs6000/rs6000.md -@@ -14703,9 +14703,9 @@ - [(match_parallel 0 "any_parallel_operand" - [(clobber (reg:P 65)) - (use (match_operand:P 1 "symbol_ref_operand" "s")) -- (use (match_operand:P 2 "gpc_reg_operand" "r")) -- (set (match_operand:P 3 "memory_operand" "=m") -- (match_operand:P 4 "gpc_reg_operand" "r"))])] -+ (use (reg:P 11)) -+ (set (match_operand:P 2 "memory_operand" "=m") -+ (match_operand:P 3 "gpc_reg_operand" "r"))])] - "" - "bl %z1" - [(set_attr "type" "branch") -@@ -14715,9 +14715,9 @@ - [(match_parallel 0 "any_parallel_operand" - [(clobber (reg:P 65)) - (use (match_operand:P 1 "symbol_ref_operand" "s")) -- (use (match_operand:P 2 "gpc_reg_operand" "r")) -- (set (match_operand:DF 3 "memory_operand" "=m") -- (match_operand:DF 4 "gpc_reg_operand" "f"))])] -+ (use (reg:P 11)) -+ (set (match_operand:DF 2 "memory_operand" "=m") -+ (match_operand:DF 3 "gpc_reg_operand" "f"))])] - "" - "bl %z1" - [(set_attr "type" "branch") -@@ -14810,9 +14810,9 @@ - [(match_parallel 0 "any_parallel_operand" - [(clobber (match_operand:P 1 "register_operand" "=l")) - (use (match_operand:P 2 "symbol_ref_operand" "s")) -- (use (match_operand:P 3 "gpc_reg_operand" "r")) -- (set (match_operand:P 4 "gpc_reg_operand" "=r") -- (match_operand:P 5 "memory_operand" "m"))])] -+ (use (reg:P 11)) -+ (set (match_operand:P 3 "gpc_reg_operand" "=r") -+ (match_operand:P 4 "memory_operand" "m"))])] - "" - "bl %z2" - [(set_attr "type" "branch") -@@ -14823,9 +14823,9 @@ - [(return) - (clobber (match_operand:P 1 "register_operand" "=l")) - (use (match_operand:P 2 "symbol_ref_operand" "s")) -- (use (match_operand:P 3 "gpc_reg_operand" "r")) -- (set (match_operand:P 4 "gpc_reg_operand" "=r") -- (match_operand:P 5 "memory_operand" "m"))])] -+ (use (reg:P 11)) -+ (set (match_operand:P 3 "gpc_reg_operand" "=r") -+ (match_operand:P 4 "memory_operand" "m"))])] - "" - "b %z2" - [(set_attr "type" "branch") -@@ -14836,9 +14836,9 @@ - [(return) - (clobber (match_operand:P 1 "register_operand" "=l")) - (use (match_operand:P 2 "symbol_ref_operand" "s")) -- (use (match_operand:P 3 "gpc_reg_operand" "r")) -- (set (match_operand:DF 4 "gpc_reg_operand" "=f") -- (match_operand:DF 5 "memory_operand" "m"))])] -+ (use (reg:P 11)) -+ (set (match_operand:DF 3 "gpc_reg_operand" "=f") -+ (match_operand:DF 4 "memory_operand" "m"))])] - "" - "b %z2" - [(set_attr "type" "branch") -@@ -14889,6 +14889,120 @@ - }" - [(set_attr "type" "load")]) - -+;;; Expanders for vector insn patterns shared between the SPE and TARGET_PAIRED systems. -+ -+(define_expand "absv2sf2" -+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "") -+ (abs:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")))] -+ "TARGET_PAIRED_FLOAT || TARGET_SPE" -+ " -+{ -+ if (TARGET_SPE) -+ { -+ /* We need to make a note that we clobber SPEFSCR. */ -+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], -+ gen_rtx_ABS (V2SFmode, operands[1]))); -+ emit_insn (gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO))); -+ DONE; -+ } -+}") -+ -+(define_expand "negv2sf2" -+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "") -+ (neg:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "")))] -+ "TARGET_PAIRED_FLOAT || TARGET_SPE" -+ " -+{ -+ if (TARGET_SPE) -+ { -+ /* We need to make a note that we clobber SPEFSCR. */ -+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], -+ gen_rtx_NEG (V2SFmode, operands[1]))); -+ emit_insn (gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO))); -+ DONE; -+ } -+}") -+ -+(define_expand "addv2sf3" -+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "") -+ (plus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "") -+ (match_operand:V2SF 2 "gpc_reg_operand" "")))] -+ "TARGET_PAIRED_FLOAT || TARGET_SPE" -+ " -+{ -+ if (TARGET_SPE) -+ { -+ /* We need to make a note that we clobber SPEFSCR. */ -+ rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2)); -+ -+ XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, operands[0], -+ gen_rtx_PLUS (V2SFmode, operands[1], operands[2])); -+ XVECEXP (par, 0, 1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO)); -+ emit_insn (par); -+ DONE; -+ } -+}") -+ -+(define_expand "subv2sf3" -+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "") -+ (minus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "") -+ (match_operand:V2SF 2 "gpc_reg_operand" "")))] -+ "TARGET_PAIRED_FLOAT || TARGET_SPE" -+ " -+{ -+ if (TARGET_SPE) -+ { -+ /* We need to make a note that we clobber SPEFSCR. */ -+ rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2)); -+ -+ XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, operands[0], -+ gen_rtx_MINUS (V2SFmode, operands[1], operands[2])); -+ XVECEXP (par, 0, 1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO)); -+ emit_insn (par); -+ DONE; -+ } -+}") -+ -+(define_expand "mulv2sf3" -+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "") -+ (mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "") -+ (match_operand:V2SF 2 "gpc_reg_operand" "")))] -+ "TARGET_PAIRED_FLOAT || TARGET_SPE" -+ " -+{ -+ if (TARGET_SPE) -+ { -+ /* We need to make a note that we clobber SPEFSCR. */ -+ rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2)); -+ -+ XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, operands[0], -+ gen_rtx_MULT (V2SFmode, operands[1], operands[2])); -+ XVECEXP (par, 0, 1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO)); -+ emit_insn (par); -+ DONE; -+ } -+}") -+ -+(define_expand "divv2sf3" -+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "") -+ (div:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "") -+ (match_operand:V2SF 2 "gpc_reg_operand" "")))] -+ "TARGET_PAIRED_FLOAT || TARGET_SPE" -+ " -+{ -+ if (TARGET_SPE) -+ { -+ /* We need to make a note that we clobber SPEFSCR. */ -+ rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2)); -+ -+ XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, operands[0], -+ gen_rtx_DIV (V2SFmode, operands[1], operands[2])); -+ XVECEXP (par, 0, 1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, SPEFSCR_REGNO)); -+ emit_insn (par); -+ DONE; -+ } -+}") -+ - - (include "sync.md") - (include "altivec.md") ---- a/gcc/config/rs6000/spe.md -+++ b/gcc/config/rs6000/spe.md -@@ -164,7 +164,7 @@ - - ;; SPE SIMD instructions - --(define_insn "spe_evabs" -+(define_insn "absv2si2" - [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r") - (abs:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")))] - "TARGET_SPE" -@@ -181,7 +181,7 @@ - [(set_attr "type" "vecsimple") - (set_attr "length" "4")]) - --(define_insn "spe_evand" -+(define_insn "andv2si3" - [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r") - (and:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r") - (match_operand:V2SI 2 "gpc_reg_operand" "r")))] -@@ -1898,7 +1898,7 @@ - [(set_attr "type" "veccomplex") - (set_attr "length" "4")]) - --(define_insn "spe_evaddw" -+(define_insn "addv2si3" - [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r") - (plus:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r") - (match_operand:V2SI 2 "gpc_reg_operand" "r")))] -@@ -2028,7 +2028,7 @@ - [(set_attr "type" "veccomplex") - (set_attr "length" "4")]) - --(define_insn "spe_evdivws" -+(define_insn "divv2si3" - [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r") - (div:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r") - (match_operand:V2SI 2 "gpc_reg_operand" "r"))) -@@ -3156,9 +3156,9 @@ - [(match_parallel 0 "any_parallel_operand" - [(clobber (reg:P 65)) - (use (match_operand:P 1 "symbol_ref_operand" "s")) -- (use (match_operand:P 2 "gpc_reg_operand" "r")) -- (set (match_operand:V2SI 3 "memory_operand" "=m") -- (match_operand:V2SI 4 "gpc_reg_operand" "r"))])] -+ (use (reg:P 11)) -+ (set (match_operand:V2SI 2 "memory_operand" "=m") -+ (match_operand:V2SI 3 "gpc_reg_operand" "r"))])] - "TARGET_SPE_ABI" - "bl %z1" - [(set_attr "type" "branch") -@@ -3168,9 +3168,9 @@ - [(match_parallel 0 "any_parallel_operand" - [(clobber (reg:P 65)) - (use (match_operand:P 1 "symbol_ref_operand" "s")) -- (use (match_operand:P 2 "gpc_reg_operand" "r")) -- (set (match_operand:V2SI 3 "gpc_reg_operand" "=r") -- (match_operand:V2SI 4 "memory_operand" "m"))])] -+ (use (reg:P 11)) -+ (set (match_operand:V2SI 2 "gpc_reg_operand" "=r") -+ (match_operand:V2SI 3 "memory_operand" "m"))])] - "TARGET_SPE_ABI" - "bl %z1" - [(set_attr "type" "branch") -@@ -3181,9 +3181,9 @@ - [(return) - (clobber (reg:P 65)) - (use (match_operand:P 1 "symbol_ref_operand" "s")) -- (use (match_operand:P 2 "gpc_reg_operand" "r")) -- (set (match_operand:V2SI 3 "gpc_reg_operand" "=r") -- (match_operand:V2SI 4 "memory_operand" "m"))])] -+ (use (reg:P 11)) -+ (set (match_operand:V2SI 2 "gpc_reg_operand" "=r") -+ (match_operand:V2SI 3 "memory_operand" "m"))])] - "TARGET_SPE_ABI" - "b %z1" - [(set_attr "type" "branch") ---- a/gcc/config/rs6000/sysv4.h -+++ b/gcc/config/rs6000/sysv4.h -@@ -619,6 +619,9 @@ - #define CC1_SECURE_PLT_DEFAULT_SPEC "" - #endif - -+#undef CC1_EXTRA_SPEC -+#define CC1_EXTRA_SPEC "" -+ - /* Pass -G xxx to the compiler and set correct endian mode. */ - #define CC1_SPEC "%{G*} %(cc1_cpu) \ - %{mlittle|mlittle-endian: %(cc1_endian_little); \ -@@ -643,7 +646,7 @@ - %{msdata: -msdata=default} \ - %{mno-sdata: -msdata=none} \ - %{!mbss-plt: %{!msecure-plt: %(cc1_secure_plt_default)}} \ --%{profile: -p}" -+%{profile: -p}" CC1_EXTRA_SPEC - - /* Don't put -Y P,<path> for cross compilers. */ - #ifndef CROSS_DIRECTORY_STRUCTURE -@@ -843,15 +846,15 @@ - #define CPP_OS_MVME_SPEC "" - - /* PowerPC simulator based on netbsd system calls support. */ --#define LIB_SIM_SPEC "--start-group -lsim -lc --end-group" -+#define LIB_SIM_SPEC LIB_DEFAULT_SPEC - --#define STARTFILE_SIM_SPEC "ecrti.o%s sim-crt0.o%s crtbegin.o%s" -+#define STARTFILE_SIM_SPEC "ecrti.o%s crtbegin.o%s" - --#define ENDFILE_SIM_SPEC "crtend.o%s ecrtn.o%s" -+#define ENDFILE_SIM_SPEC "crtend.o%s ecrtn.o%s -Tsim-hosted.ld" - - #define LINK_START_SIM_SPEC "" - --#define LINK_OS_SIM_SPEC "-m elf32ppcsim" -+#define LINK_OS_SIM_SPEC "" - - #define CPP_OS_SIM_SPEC "" - ---- a/gcc/config/rs6000/t-ppccomm -+++ b/gcc/config/rs6000/t-ppccomm -@@ -3,10 +3,23 @@ - LIB2FUNCS_EXTRA += tramp.S $(srcdir)/config/rs6000/darwin-ldouble.c - - # These can't end up in shared libgcc --LIB2FUNCS_STATIC_EXTRA = eabi.S -- --eabi.S: $(srcdir)/config/rs6000/eabi.asm -- cat $(srcdir)/config/rs6000/eabi.asm > eabi.S -+LIB2FUNCS_STATIC_EXTRA = \ -+ crtsavfpr.S crtresfpr.S \ -+ crtsavgpr.S crtresgpr.S \ -+ crtresxfpr.S crtresxgpr.S \ -+ e500crtres32gpr.S \ -+ e500crtres64gpr.S \ -+ e500crtres64gprctr.S \ -+ e500crtrest32gpr.S \ -+ e500crtrest64gpr.S \ -+ e500crtresx32gpr.S \ -+ e500crtresx64gpr.S \ -+ e500crtsav32gpr.S \ -+ e500crtsav64gpr.S \ -+ e500crtsav64gprctr.S \ -+ e500crtsavg32gpr.S \ -+ e500crtsavg64gpr.S \ -+ e500crtsavg64gprctr.S - - tramp.S: $(srcdir)/config/rs6000/tramp.asm - cat $(srcdir)/config/rs6000/tramp.asm > tramp.S -@@ -36,6 +49,63 @@ - ncrtn.S: $(srcdir)/config/rs6000/sol-cn.asm - cat $(srcdir)/config/rs6000/sol-cn.asm >ncrtn.S - -+crtsavfpr.S: $(srcdir)/config/rs6000/crtsavfpr.asm -+ cat $(srcdir)/config/rs6000/crtsavfpr.asm >crtsavfpr.S -+ -+crtresfpr.S: $(srcdir)/config/rs6000/crtresfpr.asm -+ cat $(srcdir)/config/rs6000/crtresfpr.asm >crtresfpr.S -+ -+crtsavgpr.S: $(srcdir)/config/rs6000/crtsavgpr.asm -+ cat $(srcdir)/config/rs6000/crtsavgpr.asm >crtsavgpr.S -+ -+crtresgpr.S: $(srcdir)/config/rs6000/crtresgpr.asm -+ cat $(srcdir)/config/rs6000/crtresgpr.asm >crtresgpr.S -+ -+crtresxfpr.S: $(srcdir)/config/rs6000/crtresxfpr.asm -+ cat $(srcdir)/config/rs6000/crtresxfpr.asm >crtresxfpr.S -+ -+crtresxgpr.S: $(srcdir)/config/rs6000/crtresxgpr.asm -+ cat $(srcdir)/config/rs6000/crtresxgpr.asm >crtresxgpr.S -+ -+e500crtres32gpr.S: $(srcdir)/config/rs6000/e500crtres32gpr.asm -+ cat $(srcdir)/config/rs6000/e500crtres32gpr.asm >e500crtres32gpr.S -+ -+e500crtres64gpr.S: $(srcdir)/config/rs6000/e500crtres64gpr.asm -+ cat $(srcdir)/config/rs6000/e500crtres64gpr.asm >e500crtres64gpr.S -+ -+e500crtres64gprctr.S: $(srcdir)/config/rs6000/e500crtres64gprctr.asm -+ cat $(srcdir)/config/rs6000/e500crtres64gprctr.asm >e500crtres64gprctr.S -+ -+e500crtrest32gpr.S: $(srcdir)/config/rs6000/e500crtrest32gpr.asm -+ cat $(srcdir)/config/rs6000/e500crtrest32gpr.asm >e500crtrest32gpr.S -+ -+e500crtrest64gpr.S: $(srcdir)/config/rs6000/e500crtrest64gpr.asm -+ cat $(srcdir)/config/rs6000/e500crtrest64gpr.asm >e500crtrest64gpr.S -+ -+e500crtresx32gpr.S: $(srcdir)/config/rs6000/e500crtresx32gpr.asm -+ cat $(srcdir)/config/rs6000/e500crtresx32gpr.asm >e500crtresx32gpr.S -+ -+e500crtresx64gpr.S: $(srcdir)/config/rs6000/e500crtresx64gpr.asm -+ cat $(srcdir)/config/rs6000/e500crtresx64gpr.asm >e500crtresx64gpr.S -+ -+e500crtsav32gpr.S: $(srcdir)/config/rs6000/e500crtsav32gpr.asm -+ cat $(srcdir)/config/rs6000/e500crtsav32gpr.asm >e500crtsav32gpr.S -+ -+e500crtsav64gpr.S: $(srcdir)/config/rs6000/e500crtsav64gpr.asm -+ cat $(srcdir)/config/rs6000/e500crtsav64gpr.asm >e500crtsav64gpr.S -+ -+e500crtsav64gprctr.S: $(srcdir)/config/rs6000/e500crtsav64gprctr.asm -+ cat $(srcdir)/config/rs6000/e500crtsav64gprctr.asm >e500crtsav64gprctr.S -+ -+e500crtsavg32gpr.S: $(srcdir)/config/rs6000/e500crtsavg32gpr.asm -+ cat $(srcdir)/config/rs6000/e500crtsavg32gpr.asm >e500crtsavg32gpr.S -+ -+e500crtsavg64gpr.S: $(srcdir)/config/rs6000/e500crtsavg64gpr.asm -+ cat $(srcdir)/config/rs6000/e500crtsavg64gpr.asm >e500crtsavg64gpr.S -+ -+e500crtsavg64gprctr.S: $(srcdir)/config/rs6000/e500crtsavg64gprctr.asm -+ cat $(srcdir)/config/rs6000/e500crtsavg64gprctr.asm >e500crtsavg64gprctr.S -+ - # Build multiple copies of ?crt{i,n}.o, one for each target switch. - $(T)ecrti$(objext): ecrti.S - $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c ecrti.S -o $(T)ecrti$(objext) -@@ -49,6 +119,63 @@ - $(T)ncrtn$(objext): ncrtn.S - $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c ncrtn.S -o $(T)ncrtn$(objext) - -+$(T)crtsavfpr$(objext): crtsavfpr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c crtsavfpr.S -o $(T)crtsavfpr$(objext) -+ -+$(T)crtresfpr$(objext): crtresfpr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c crtresfpr.S -o $(T)crtresfpr$(objext) -+ -+$(T)crtsavgpr$(objext): crtsavgpr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c crtsavgpr.S -o $(T)crtsavgpr$(objext) -+ -+$(T)crtresgpr$(objext): crtresgpr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c crtresgpr.S -o $(T)crtresgpr$(objext) -+ -+$(T)crtresxfpr$(objext): crtresxfpr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c crtresxfpr.S -o $(T)crtresxfpr$(objext) -+ -+$(T)crtresxgpr$(objext): crtresxgpr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c crtresxgpr.S -o $(T)crtresxgpr$(objext) -+ -+$(T)e500crtres32gpr$(objext): e500crtres32gpr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c e500crtres32gpr.S -o $(T)e500crtres32gpr$(objext) -+ -+$(T)e500crtres64gpr$(objext): e500crtres64gpr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c e500crtres64gpr.S -o $(T)e500crtres64gpr$(objext) -+ -+$(T)e500crtres64gprctr$(objext): e500crtres64gprctr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c e500crtres64gprctr.S -o $(T)e500crtres64gprctr$(objext) -+ -+$(T)e500crtrest32gpr$(objext): e500crtrest32gpr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c e500crtrest32gpr.S -o $(T)e500crtrest32gpr$(objext) -+ -+$(T)e500crtrest64gpr$(objext): e500crtrest64gpr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c e500crtrest64gpr.S -o $(T)e500crtrest64gpr$(objext) -+ -+$(T)e500crtresx32gpr$(objext): e500crtresx32gpr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c e500crtresx32gpr.S -o $(T)e500crtresx32gpr$(objext) -+ -+$(T)e500crtresx64gpr$(objext): e500crtresx64gpr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c e500crtresx64gpr.S -o $(T)e500crtresx64gpr$(objext) -+ -+$(T)e500crtsav32gpr$(objext): e500crtsav32gpr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c e500crtsav32gpr.S -o $(T)e500crtsav32gpr$(objext) -+ -+$(T)e500crtsav64gpr$(objext): e500crtsav64gpr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c e500crtsav64gpr.S -o $(T)e500crtsav64gpr$(objext) -+ -+$(T)e500crtsav64gprctr$(objext): e500crtsav64gprctr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c e500crtsav64gprctr.S -o $(T)e500crtsav64gprctr$(objext) -+ -+$(T)e500crtsavg32gpr$(objext): e500crtsavg32gpr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c e500crtsavg32gpr.S -o $(T)e500crtsavg32gpr$(objext) -+ -+$(T)e500crtsavg64gpr$(objext): e500crtsavg64gpr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c e500crtsavg64gpr.S -o $(T)e500crtsavg64gpr$(objext) -+ -+$(T)e500crtsavg64gprctr$(objext): e500crtsavg64gprctr.S -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c e500crtsavg64gprctr.S -o $(T)e500crtsavg64gprctr$(objext) -+ - # It is important that crtbegin.o, etc., aren't surprised by stuff in .sdata. - CRTSTUFF_T_CFLAGS = -msdata=none - # Make sure crt*.o are built with -fPIC even if configured with ---- /dev/null -+++ b/gcc/config/rs6000/t-ppc-e500mc -@@ -0,0 +1,12 @@ -+# Multilibs for powerpc embedded ELF targets. -+ -+MULTILIB_OPTIONS = -+ -+MULTILIB_DIRNAMES = -+ -+MULTILIB_EXCEPTIONS = -+ -+MULTILIB_EXTRA_OPTS = mno-eabi mstrict-align -+ -+MULTILIB_MATCHES = ${MULTILIB_MATCHES_FLOAT} \ -+ ${MULTILIB_MATCHES_ENDIAN} ---- a/gcc/config/sh/lib1funcs.asm -+++ b/gcc/config/sh/lib1funcs.asm -@@ -2080,8 +2080,9 @@ - GLOBAL(ic_invalidate): - ocbwb @r4 - synco -- rts - icbi @r4 -+ rts -+ nop - ENDFUNC(GLOBAL(ic_invalidate)) - #elif defined(__SH4_SINGLE__) || defined(__SH4__) || defined(__SH4_SINGLE_ONLY__) || (defined(__SH4_NOFPU__) && !defined(__SH5__)) - /* For system code, we use ic_invalidate_line_i, but user code -@@ -2147,8 +2148,10 @@ - GLOBAL(ic_invalidate_array): - add r1,r4 - synco -- rts - icbi @r4 -+ rts -+ nop -+ .align 2 - .long 0 - ENDFUNC(GLOBAL(ic_invalidate_array)) - #elif defined(__SH4_SINGLE__) || defined(__SH4__) || defined(__SH4_SINGLE_ONLY__) || (defined(__SH4_NOFPU__) && !defined(__SH5__)) ---- a/gcc/config/sh/linux-unwind.h -+++ b/gcc/config/sh/linux-unwind.h -@@ -24,7 +24,10 @@ - - - /* Do code reading to identify a signal frame, and set the frame -- state data appropriately. See unwind-dw2.c for the structs. */ -+ state data appropriately. See unwind-dw2.c for the structs. -+ Don't use this at all if inhibit_libc is used. */ -+ -+#ifndef inhibit_libc - - #include <signal.h> - #include <sys/ucontext.h> -@@ -248,3 +251,5 @@ - return _URC_NO_REASON; - } - #endif /* defined (__SH5__) */ -+ -+#endif /* inhibit_libc */ ---- a/gcc/config/sh/sh.h -+++ b/gcc/config/sh/sh.h -@@ -712,8 +712,9 @@ - /* Never run scheduling before reload, since that can \ - break global alloc, and generates slower code anyway due \ - to the pressure on R0. */ \ -- /* Enable sched1 for SH4; ready queue will be reordered by \ -- the target hooks when pressure is high. We can not do this for \ -+ /* Enable sched1 for SH4 if the user explicitly requests. \ -+ When sched1 is enabled, the ready queue will be reordered by \ -+ the target hooks if pressure is high. We can not do this for \ - PIC, SH3 and lower as they give spill failures for R0. */ \ - if (!TARGET_HARD_SH4 || flag_pic) \ - flag_schedule_insns = 0; \ -@@ -728,6 +729,8 @@ - warning (0, "ignoring -fschedule-insns because of exception handling bug"); \ - flag_schedule_insns = 0; \ - } \ -+ else if (flag_schedule_insns == 2) \ -+ flag_schedule_insns = 0; \ - } \ - \ - if (align_loops == 0) \ ---- a/gcc/config/sol2.h -+++ b/gcc/config/sol2.h -@@ -123,12 +123,12 @@ - %{YP,*} \ - %{R*} \ - %{compat-bsd: \ -- %{!YP,*:%{p|pg:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \ -- %{!p:%{!pg:-Y P,/usr/ucblib:/usr/ccs/lib:/usr/lib}}} \ -- -R /usr/ucblib} \ -+ %{!YP,*:%{p|pg:-Y P,%R/usr/ucblib:%R/usr/ccs/lib/libp:%R/usr/lib/libp:%R/usr/ccs/lib:%R/usr/lib} \ -+ %{!p:%{!pg:-Y P,%R/usr/ucblib:%R/usr/ccs/lib:%R/usr/lib}}} \ -+ -R %R/usr/ucblib} \ - %{!compat-bsd: \ -- %{!YP,*:%{p|pg:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \ -- %{!p:%{!pg:-Y P,/usr/ccs/lib:/usr/lib}}}}" -+ %{!YP,*:%{p|pg:-Y P,%R/usr/ccs/lib/libp:%R/usr/lib/libp:%R/usr/ccs/lib:%R/usr/lib} \ -+ %{!p:%{!pg:-Y P,%R/usr/ccs/lib:%R/usr/lib}}}}" - - #undef LINK_ARCH32_SPEC - #define LINK_ARCH32_SPEC LINK_ARCH32_SPEC_BASE ---- a/gcc/config/sparc/linux64.h -+++ b/gcc/config/sparc/linux64.h -@@ -40,10 +40,15 @@ - in a Medium/Low code model environment. */ - - #undef TARGET_DEFAULT -+#ifdef BIARCH_32BIT_DEFAULT -+#define TARGET_DEFAULT \ -+ (MASK_APP_REGS + MASK_FPU) -+#else - #define TARGET_DEFAULT \ - (MASK_V9 + MASK_PTR64 + MASK_64BIT /* + MASK_HARD_QUAD */ \ - + MASK_STACK_BIAS + MASK_APP_REGS + MASK_FPU + MASK_LONG_DOUBLE_128) - #endif -+#endif - - /* This must be v9a not just v9 because by default we enable - -mvis. */ ---- a/gcc/config/sparc/sol2-bi.h -+++ b/gcc/config/sparc/sol2-bi.h -@@ -172,12 +172,12 @@ - %{YP,*} \ - %{R*} \ - %{compat-bsd: \ -- %{!YP,*:%{p|pg:-Y P,/usr/ucblib/sparcv9:/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \ -- %{!p:%{!pg:-Y P,/usr/ucblib/sparcv9:/usr/lib/sparcv9}}} \ -- -R /usr/ucblib/sparcv9} \ -+ %{!YP,*:%{p|pg:-Y P,%R/usr/ucblib/sparcv9:%R/usr/lib/libp/sparcv9:%R/usr/lib/sparcv9} \ -+ %{!p:%{!pg:-Y P,%R/usr/ucblib/sparcv9:%R/usr/lib/sparcv9}}} \ -+ -R %R/usr/ucblib/sparcv9} \ - %{!compat-bsd: \ -- %{!YP,*:%{p|pg:-Y P,/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \ -- %{!p:%{!pg:-Y P,/usr/lib/sparcv9}}}}" -+ %{!YP,*:%{p|pg:-Y P,%R/usr/lib/libp/sparcv9:%R/usr/lib/sparcv9} \ -+ %{!p:%{!pg:-Y P,%R/usr/lib/sparcv9}}}}" - - #define LINK_ARCH64_SPEC LINK_ARCH64_SPEC_BASE - ---- a/gcc/config/sparc/sparc.c -+++ b/gcc/config/sparc/sparc.c -@@ -6120,7 +6120,7 @@ - sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison) - { - const char *qpfunc; -- rtx slot0, slot1, result, tem, tem2; -+ rtx slot0, slot1, result, tem, tem2, libfunc; - enum machine_mode mode; - enum rtx_code new_comparison; - -@@ -6183,7 +6183,8 @@ - emit_move_insn (slot1, y); - } - -- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), LCT_NORMAL, -+ libfunc = gen_rtx_SYMBOL_REF (Pmode, qpfunc); -+ emit_library_call (libfunc, LCT_NORMAL, - DImode, 2, - XEXP (slot0, 0), Pmode, - XEXP (slot1, 0), Pmode); -@@ -6191,7 +6192,8 @@ - } - else - { -- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), LCT_NORMAL, -+ libfunc = gen_rtx_SYMBOL_REF (Pmode, qpfunc); -+ emit_library_call (libfunc, LCT_NORMAL, - SImode, 2, - x, TFmode, y, TFmode); - mode = SImode; -@@ -6202,7 +6204,7 @@ - register so reload doesn't clobber the value if it needs - the return register for a spill reg. */ - result = gen_reg_rtx (mode); -- emit_move_insn (result, hard_libcall_value (mode)); -+ emit_move_insn (result, hard_libcall_value (mode, libfunc)); - - switch (comparison) - { ---- a/gcc/config/spu/spu.h -+++ b/gcc/config/spu/spu.h -@@ -270,7 +270,8 @@ - - #define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LINK_REGISTER_REGNUM) - --#define ARG_POINTER_CFA_OFFSET(FNDECL) (-STACK_POINTER_OFFSET) -+#define ARG_POINTER_CFA_OFFSET(FNDECL) \ -+ (crtl->args.pretend_args_size - STACK_POINTER_OFFSET) - - - /* Stack Checking */ ---- a/gcc/config.gcc -+++ b/gcc/config.gcc -@@ -1088,7 +1088,7 @@ - tmake_file="${tmake_file} i386/t-linux64" - need_64bit_hwint=yes - case X"${with_cpu}" in -- Xgeneric|Xcore2|Xnocona|Xx86-64|Xamdfam10|Xbarcelona|Xk8|Xopteron|Xathlon64|Xathlon-fx) -+ Xgeneric|Xatom|Xcore2|Xnocona|Xx86-64|Xamdfam10|Xbarcelona|Xk8|Xopteron|Xathlon64|Xathlon-fx) - ;; - X) - if test x$with_cpu_64 = x; then -@@ -1097,7 +1097,7 @@ - ;; - *) - echo "Unsupported CPU used in --with-cpu=$with_cpu, supported values:" 1>&2 -- echo "generic core2 nocona x86-64 amdfam10 barcelona k8 opteron athlon64 athlon-fx" 1>&2 -+ echo "generic atom core2 nocona x86-64 amdfam10 barcelona k8 opteron athlon64 athlon-fx" 1>&2 - exit 1 - ;; - esac -@@ -1202,7 +1202,7 @@ - # libgcc/configure.ac instead. - need_64bit_hwint=yes - case X"${with_cpu}" in -- Xgeneric|Xcore2|Xnocona|Xx86-64|Xamdfam10|Xbarcelona|Xk8|Xopteron|Xathlon64|Xathlon-fx) -+ Xgeneric|Xatom|Xcore2|Xnocona|Xx86-64|Xamdfam10|Xbarcelona|Xk8|Xopteron|Xathlon64|Xathlon-fx) - ;; - X) - if test x$with_cpu_64 = x; then -@@ -1211,7 +1211,7 @@ - ;; - *) - echo "Unsupported CPU used in --with-cpu=$with_cpu, supported values:" 1>&2 -- echo "generic core2 nocona x86-64 amdfam10 barcelona k8 opteron athlon64 athlon-fx" 1>&2 -+ echo "generic atom core2 nocona x86-64 amdfam10 barcelona k8 opteron athlon64 athlon-fx" 1>&2 - exit 1 - ;; - esac -@@ -1566,6 +1566,7 @@ - tm_defines="${tm_defines} MIPS_ISA_DEFAULT=65" - ;; - esac -+ tmake_file="$tmake_file mips/t-crtfm" - gnu_ld=yes - gas=yes - test x$with_llsc != x || with_llsc=yes -@@ -1581,6 +1582,7 @@ - tm_defines="${tm_defines} MIPS_ISA_DEFAULT=32" - esac - test x$with_llsc != x || with_llsc=yes -+ tmake_file="$tmake_file mips/t-crtfm" - ;; - mips*-*-openbsd*) - tm_defines="${tm_defines} OBSD_HAS_DECLARE_FUNCTION_NAME OBSD_HAS_DECLARE_OBJECT OBSD_HAS_CORRECT_SPECS" -@@ -1796,6 +1798,10 @@ - tm_file="${tm_file} dbxelf.h elfos.h usegas.h svr4.h freebsd-spec.h rs6000/sysv4.h" - extra_options="${extra_options} rs6000/sysv4.opt" - tmake_file="rs6000/t-fprules rs6000/t-fprules-fpbit rs6000/t-ppcgas rs6000/t-ppccomm" -+ if test x$enable_powerpc_e500mc_elf = xyes; then -+ tm_file="${tm_file} rs6000/e500mc.h" -+ tmake_file="${tmake_file} rs6000/t-ppc-e500mc" -+ fi - ;; - powerpc-*-eabialtivec*) - tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/eabi.h rs6000/e500.h rs6000/eabialtivec.h" -@@ -2420,6 +2426,8 @@ - i[34567]86-*-* | x86_64-*-*) - tmake_file="${tmake_file} i386/t-gmm_malloc i386/t-i386" - ;; -+powerpc*-*-* | rs6000-*-*) -+ tm_file="${tm_file} rs6000/option-defaults.h" - esac - - # Support for --with-cpu and related options (and a few unrelated options, -@@ -2646,8 +2654,8 @@ - | armv[23456] | armv2a | armv3m | armv4t | armv5t \ - | armv5te | armv6j |armv6k | armv6z | armv6zk | armv6-m \ - | armv7 | armv7-a | armv7-r | armv7-m \ -- | iwmmxt | ep9312) -- # OK -+ | iwmmxt | ep9312 | marvell-f ) -+ # OK - ;; - *) - echo "Unknown arch used in --with-arch=$with_arch" 1>&2 -@@ -2668,7 +2676,10 @@ - - case "$with_fpu" in - "" \ -- | fpa | fpe2 | fpe3 | maverick | vfp | vfp3 | neon ) -+ | fpa | fpe2 | fpe3 | maverick \ -+ | vfp | vfp3 | vfpv3 | vfpv3-fp16 | vfpv3-d16 \ -+ | vfpv3-d16-fp16 | vfpv4 | vfpv4-d16 | fpv4-sp-d16 \ -+ | neon | neon-fp16 | neon-vfpv4 ) - # OK - ;; - *) -@@ -2805,7 +2816,7 @@ - esac - # OK - ;; -- "" | amdfam10 | barcelona | k8 | opteron | athlon64 | athlon-fx | nocona | core2 | generic) -+ "" | amdfam10 | barcelona | k8 | opteron | athlon64 | athlon-fx | nocona | core2 | atom | generic) - # OK - ;; - *) -@@ -2817,7 +2828,7 @@ - ;; - - mips*-*-*) -- supported_defaults="abi arch float tune divide llsc mips-plt" -+ supported_defaults="abi arch arch_32 arch_64 float tune tune_32 tune_64 divide llsc mips-plt" - - case ${with_float} in - "" | soft | hard) -@@ -2882,12 +2893,20 @@ - ;; - - powerpc*-*-* | rs6000-*-*) -- supported_defaults="cpu float tune" -+ supported_defaults="cpu cpu_32 cpu_64 float tune tune_32 tune_64" - -- for which in cpu tune; do -+ for which in cpu cpu_32 cpu_64 tune tune_32 tune_64; do - eval "val=\$with_$which" - case ${val} in - default32 | default64) -+ case $which in -+ cpu | tune) -+ ;; -+ *) -+ echo "$val only valid for --with-cpu and --with-tune." 1>&2 -+ exit 1 -+ ;; -+ esac - with_which="with_$which" - eval $with_which= - ;; ---- a/gcc/config.in -+++ b/gcc/config.in -@@ -108,6 +108,12 @@ - #endif - - -+/* Define to warn for use of native system header directories */ -+#ifndef USED_FOR_TARGET -+#undef ENABLE_POISON_SYSTEM_DIRECTORIES -+#endif -+ -+ - /* Define if you want all operations on RTL (the basic data structure of the - optimizer and back end) to be checked for dynamic type safety at runtime. - This is quite expensive. */ -@@ -821,6 +827,13 @@ - #endif - - -+/* Define if your assembler supports specifying the alignment of objects -+ allocated using the GAS .comm command. */ -+#ifndef USED_FOR_TARGET -+#undef HAVE_GAS_ALIGNED_COMM -+#endif -+ -+ - /* Define if your assembler supports .balign and .p2align. */ - #ifndef USED_FOR_TARGET - #undef HAVE_GAS_BALIGN_AND_P2ALIGN ---- a/gcc/configure -+++ b/gcc/configure -@@ -458,7 +458,7 @@ - # include <unistd.h> - #endif" - --ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical build_libsubdir build_subdir host_subdir target_subdir GENINSRC CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT GNATBIND ac_ct_GNATBIND GNATMAKE ac_ct_GNATMAKE NO_MINUS_C_MINUS_O OUTPUT_OPTION CPP EGREP loose_warn strict_warn warn_cflags nocommon_flag TREEBROWSER valgrind_path valgrind_path_defines valgrind_command coverage_flags enable_multilib enable_decimal_float enable_fixed_point enable_shared TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE CROSS_SYSTEM_HEADER_DIR onestep PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI datarootdir docdir htmldir SET_MAKE AWK LN_S LN RANLIB ac_ct_RANLIB ranlib_flags INSTALL INSTALL_PROGRAM INSTALL_DATA make_compare_target have_mktemp_command MAKEINFO BUILD_INFO GENERATED_MANPAGES FLEX BISON NM AR COLLECT2_LIBS GNAT_LIBEXC LDEXP_LIB TARGET_GETGROUPS_T LIBICONV LTLIBICONV LIBICONV_DEP manext objext gthread_flags extra_modes_file extra_opt_files USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT CROSS ALL SYSTEM_HEADER_DIR inhibit_libc CC_FOR_BUILD BUILD_CFLAGS BUILD_LDFLAGS STMP_FIXINC STMP_FIXPROTO collect2 LIBTOOL SED FGREP GREP LD DUMPBIN ac_ct_DUMPBIN OBJDUMP ac_ct_OBJDUMP ac_ct_AR STRIP ac_ct_STRIP lt_ECHO DSYMUTIL ac_ct_DSYMUTIL NMEDIT ac_ct_NMEDIT LIPO ac_ct_LIPO OTOOL ac_ct_OTOOL OTOOL64 ac_ct_OTOOL64 objdir enable_fast_install gcc_cv_as ORIGINAL_AS_FOR_TARGET gcc_cv_ld ORIGINAL_LD_FOR_TARGET gcc_cv_nm ORIGINAL_NM_FOR_TARGET gcc_cv_objdump gcc_cv_readelf libgcc_visibility GGC zlibdir zlibinc MAINT gcc_tooldir dollar slibdir subdirs srcdir all_compilers all_gtfiles all_lang_makefrags all_lang_makefiles all_languages all_selected_languages build_exeext build_install_headers_dir build_xm_file_list build_xm_include_list build_xm_defines build_file_translate check_languages cpp_install_dir xmake_file tmake_file extra_gcc_objs extra_headers_list extra_objs extra_parts extra_passes extra_programs float_h_file gcc_config_arguments gcc_gxx_include_dir host_exeext host_xm_file_list host_xm_include_list host_xm_defines out_host_hook_obj install lang_opt_files lang_specs_files lang_tree_files local_prefix md_file objc_boehm_gc out_file out_object_file thread_file tm_file_list tm_include_list tm_defines tm_p_file_list tm_p_include_list xm_file_list xm_include_list xm_defines c_target_objs cxx_target_objs fortran_target_objs target_cpu_default GMPLIBS GMPINC PPLLIBS PPLINC CLOOGLIBS CLOOGINC LIBOBJS LTLIBOBJS' -+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical licensedir build_libsubdir build_subdir host_subdir target_subdir GENINSRC CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT GNATBIND ac_ct_GNATBIND GNATMAKE ac_ct_GNATMAKE NO_MINUS_C_MINUS_O OUTPUT_OPTION CPP EGREP loose_warn strict_warn warn_cflags nocommon_flag TREEBROWSER valgrind_path valgrind_path_defines valgrind_command coverage_flags enable_multilib enable_decimal_float enable_fixed_point enable_shared TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE CROSS_SYSTEM_HEADER_DIR EGLIBC_CONFIGS CONFIGURE_SPECS onestep PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI datarootdir docdir htmldir SET_MAKE AWK LN_S LN RANLIB ac_ct_RANLIB ranlib_flags INSTALL INSTALL_PROGRAM INSTALL_DATA make_compare_target have_mktemp_command MAKEINFO BUILD_INFO GENERATED_MANPAGES FLEX BISON NM AR COLLECT2_LIBS GNAT_LIBEXC LDEXP_LIB TARGET_GETGROUPS_T LIBICONV LTLIBICONV LIBICONV_DEP manext objext gthread_flags extra_modes_file extra_opt_files USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT CROSS ALL SYSTEM_HEADER_DIR inhibit_libc CC_FOR_BUILD BUILD_CFLAGS BUILD_LDFLAGS STMP_FIXINC STMP_FIXPROTO collect2 LIBTOOL SED FGREP GREP LD DUMPBIN ac_ct_DUMPBIN OBJDUMP ac_ct_OBJDUMP ac_ct_AR STRIP ac_ct_STRIP lt_ECHO DSYMUTIL ac_ct_DSYMUTIL NMEDIT ac_ct_NMEDIT LIPO ac_ct_LIPO OTOOL ac_ct_OTOOL OTOOL64 ac_ct_OTOOL64 objdir enable_fast_install gcc_cv_as ORIGINAL_AS_FOR_TARGET gcc_cv_ld ORIGINAL_LD_FOR_TARGET gcc_cv_nm ORIGINAL_NM_FOR_TARGET gcc_cv_objdump gcc_cv_readelf libgcc_visibility GGC zlibdir zlibinc MAINT gcc_tooldir dollar slibdir subdirs srcdir all_compilers all_gtfiles all_lang_makefrags all_lang_makefiles all_languages all_selected_languages build_exeext build_install_headers_dir build_xm_file_list build_xm_include_list build_xm_defines build_file_translate check_languages cpp_install_dir xmake_file tmake_file TM_ENDIAN_CONFIG TM_MULTILIB_CONFIG TM_MULTILIB_EXCEPTIONS_CONFIG extra_gcc_objs extra_headers_list extra_objs extra_parts extra_passes extra_programs float_h_file gcc_config_arguments gcc_gxx_include_dir host_exeext host_xm_file_list host_xm_include_list host_xm_defines out_host_hook_obj install lang_opt_files lang_specs_files lang_tree_files local_prefix md_file objc_boehm_gc out_file out_object_file thread_file tm_file_list tm_include_list tm_defines tm_p_file_list tm_p_include_list xm_file_list xm_include_list xm_defines c_target_objs cxx_target_objs fortran_target_objs target_cpu_default GMPLIBS GMPINC PPLLIBS PPLINC CLOOGLIBS CLOOGINC LIBOBJS LTLIBOBJS' - ac_subst_files='language_hooks' - ac_pwd=`pwd` - -@@ -1084,6 +1084,8 @@ - --enable-version-specific-runtime-libs - specify that runtime libraries should be - installed in a compiler-specific directory -+ --enable-poison-system-directories -+ warn for use of native system header directories - - Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] -@@ -22108,6 +22110,22 @@ - tls_first_minor=16 - tls_as_opt='-32 --fatal-warnings' - ;; -+ m68k-*-*) -+ conftest_s=' -+ .section .tdata,"awT",@progbits -+x: -+ .word 2 -+ .text -+foo: -+ move.l x@TLSGD(%a5),%a0 -+ move.l x@TLSLDM(%a5),%a0 -+ move.l x@TLSLDO(%a5),%a0 -+ move.l x@TLSIE(%a5),%a0 -+ move.l x@TLSLE(%a5),%a0' -+ tls_first_major=2 -+ tls_first_minor=19 -+ tls_as_opt='--fatal-warnings' -+ ;; - powerpc-*-*) - conftest_s=' - .section ".tdata","awT",@progbits -@@ -22739,6 +22757,44 @@ - i[34567]86-*-* | x86_64-*-*) - case $target_os in - cygwin* | pe | mingw32*) -+ # Recent binutils allows the three-operand form of ".comm" on PE. This -+ # definition is used unconditionally to initialise the default state of -+ # the target option variable that governs usage of the feature. -+ echo "$as_me:$LINENO: checking assembler for .comm with alignment" >&5 -+echo $ECHO_N "checking assembler for .comm with alignment... $ECHO_C" >&6 -+if test "${gcc_cv_as_comm_has_align+set}" = set; then -+ echo $ECHO_N "(cached) $ECHO_C" >&6 -+else -+ gcc_cv_as_comm_has_align=no -+ if test $in_tree_gas = yes; then -+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 52` -+ then gcc_cv_as_comm_has_align=yes -+fi -+ elif test x$gcc_cv_as != x; then -+ echo '.comm foo,1,32' > conftest.s -+ if { ac_try='$gcc_cv_as -o conftest.o conftest.s >&5' -+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 -+ (eval $ac_try) 2>&5 -+ ac_status=$? -+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 -+ (exit $ac_status); }; } -+ then -+ gcc_cv_as_comm_has_align=yes -+ else -+ echo "configure: failed program was" >&5 -+ cat conftest.s >&5 -+ fi -+ rm -f conftest.o conftest.s -+ fi -+fi -+echo "$as_me:$LINENO: result: $gcc_cv_as_comm_has_align" >&5 -+echo "${ECHO_T}$gcc_cv_as_comm_has_align" >&6 -+ -+ -+cat >>confdefs.h <<_ACEOF -+#define HAVE_GAS_ALIGNED_COMM `if test $gcc_cv_as_comm_has_align = yes; then echo 1; else echo 0; fi` -+_ACEOF -+ - # Used for DWARF 2 in PE - echo "$as_me:$LINENO: checking assembler for .secrel32 relocs" >&5 - echo $ECHO_N "checking assembler for .secrel32 relocs... $ECHO_C" >&6 -@@ -24711,6 +24767,21 @@ - fi; - - -+# Check whether --enable-poison-system-directories or --disable-poison-system-directories was given. -+if test "${enable_poison_system_directories+set}" = set; then -+ enableval="$enable_poison_system_directories" -+ -+else -+ enable_poison_system_directories=no -+fi; -+if test "x${enable_poison_system_directories}" = "xyes"; then -+ -+cat >>confdefs.h <<\_ACEOF -+#define ENABLE_POISON_SYSTEM_DIRECTORIES 1 -+_ACEOF -+ -+fi -+ - # Substitute configuration variables - - ---- a/gcc/configure.ac -+++ b/gcc/configure.ac -@@ -2576,6 +2576,22 @@ - tls_first_minor=16 - tls_as_opt='-32 --fatal-warnings' - ;; -+ m68k-*-*) -+ conftest_s=' -+ .section .tdata,"awT",@progbits -+x: -+ .word 2 -+ .text -+foo: -+ move.l x@TLSGD(%a5),%a0 -+ move.l x@TLSLDM(%a5),%a0 -+ move.l x@TLSLDO(%a5),%a0 -+ move.l x@TLSIE(%a5),%a0 -+ move.l x@TLSLE(%a5),%a0' -+ tls_first_major=2 -+ tls_first_minor=19 -+ tls_as_opt='--fatal-warnings' -+ ;; - powerpc-*-*) - conftest_s=' - .section ".tdata","awT",@progbits -@@ -2944,6 +2960,15 @@ - changequote([,])dnl - case $target_os in - cygwin* | pe | mingw32*) -+ # Recent binutils allows the three-operand form of ".comm" on PE. This -+ # definition is used unconditionally to initialise the default state of -+ # the target option variable that governs usage of the feature. -+ gcc_GAS_CHECK_FEATURE([.comm with alignment], gcc_cv_as_comm_has_align, -+ [2,19,52],,[.comm foo,1,32]) -+ AC_DEFINE_UNQUOTED(HAVE_GAS_ALIGNED_COMM, -+ [`if test $gcc_cv_as_comm_has_align = yes; then echo 1; else echo 0; fi`], -+ [Define if your assembler supports specifying the alignment -+ of objects allocated using the GAS .comm command.]) - # Used for DWARF 2 in PE - gcc_GAS_CHECK_FEATURE([.secrel32 relocs], - gcc_cv_as_ix86_pe_secrel32, -@@ -3891,6 +3916,16 @@ - htmldir='$(docdir)') - AC_SUBST(htmldir) - -+AC_ARG_ENABLE([poison-system-directories], -+ AS_HELP_STRING([--enable-poison-system-directories], -+ [warn for use of native system header directories]),, -+ [enable_poison_system_directories=no]) -+if test "x${enable_poison_system_directories}" = "xyes"; then -+ AC_DEFINE([ENABLE_POISON_SYSTEM_DIRECTORIES], -+ [1], -+ [Define to warn for use of native system header directories]) -+fi -+ - # Substitute configuration variables - AC_SUBST(subdirs) - AC_SUBST(srcdir) ---- a/gcc/c.opt -+++ b/gcc/c.opt -@@ -716,6 +716,10 @@ - C ObjC C++ ObjC++ - Treat the input file as already preprocessed - -+fremove-local-statics -+C C++ Var(flag_remove_local_statics) Optimization -+Convert function-local static variables to automatic variables when it is safe to do so -+ - freplace-objc-classes - ObjC ObjC++ - Used in Fix-and-Continue mode to indicate that object files may be swapped in at runtime ---- a/gcc/c-opts.c -+++ b/gcc/c-opts.c -@@ -40,6 +40,7 @@ - #include "mkdeps.h" - #include "target.h" - #include "tm_p.h" -+#include "c-tree.h" /* For c_cpp_error. */ - - #ifndef DOLLARS_IN_IDENTIFIERS - # define DOLLARS_IN_IDENTIFIERS true -@@ -201,6 +202,7 @@ - { - static const unsigned int lang_flags[] = {CL_C, CL_ObjC, CL_CXX, CL_ObjCXX}; - unsigned int i, result; -+ struct cpp_callbacks *cb; - - /* This is conditionalized only because that is the way the front - ends used to do it. Maybe this should be unconditional? */ -@@ -216,6 +218,8 @@ - - parse_in = cpp_create_reader (c_dialect_cxx () ? CLK_GNUCXX: CLK_GNUC89, - ident_hash, line_table); -+ cb = cpp_get_callbacks (parse_in); -+ cb->error = c_cpp_error; - - cpp_opts = cpp_get_options (parse_in); - cpp_opts->dollars_in_ident = DOLLARS_IN_IDENTIFIERS; -@@ -333,12 +337,12 @@ - or environment var dependency generation is used. */ - cpp_opts->deps.style = (code == OPT_M ? DEPS_SYSTEM: DEPS_USER); - flag_no_output = 1; -- cpp_opts->inhibit_warnings = 1; - break; - - case OPT_MD: - case OPT_MMD: - cpp_opts->deps.style = (code == OPT_MD ? DEPS_SYSTEM: DEPS_USER); -+ cpp_opts->deps.need_preprocessor_output = true; - deps_file = arg; - break; - -@@ -444,7 +448,6 @@ - break; - - case OPT_Werror: -- cpp_opts->warnings_are_errors = value; - global_dc->warning_as_error_requested = value; - break; - -@@ -503,10 +506,6 @@ - warn_strict_null_sentinel = value; - break; - -- case OPT_Wsystem_headers: -- cpp_opts->warn_system_headers = value; -- break; -- - case OPT_Wtraditional: - cpp_opts->warn_traditional = value; - break; -@@ -895,8 +894,6 @@ - c_common_post_options, so that a subsequent -Wno-endif-labels - is not overridden. */ - case OPT_pedantic_errors: -- cpp_opts->pedantic_errors = 1; -- /* Fall through. */ - case OPT_pedantic: - cpp_opts->pedantic = 1; - cpp_opts->warn_endif_labels = 1; -@@ -971,10 +968,6 @@ - flag_undef = 1; - break; - -- case OPT_w: -- cpp_opts->inhibit_warnings = 1; -- break; -- - case OPT_v: - verbose = true; - break; -@@ -1159,10 +1152,6 @@ - - input_location = UNKNOWN_LOCATION; - -- /* If an error has occurred in cpplib, note it so we fail -- immediately. */ -- errorcount += cpp_errors (parse_in); -- - *pfilename = this_input_filename - = cpp_read_main_file (parse_in, in_fnames[0]); - /* Don't do any compilation or preprocessing if there is no input file. */ -@@ -1274,7 +1263,8 @@ - { - FILE *deps_stream = NULL; - -- if (cpp_opts->deps.style != DEPS_NONE) -+ /* Don't write the deps file if there are errors. */ -+ if (cpp_opts->deps.style != DEPS_NONE && errorcount == 0) - { - /* If -M or -MM was seen without -MF, default output to the - output stream. */ -@@ -1290,7 +1280,7 @@ - - /* For performance, avoid tearing down cpplib's internal structures - with cpp_destroy (). */ -- errorcount += cpp_finish (parse_in, deps_stream); -+ cpp_finish (parse_in, deps_stream); - - if (deps_stream && deps_stream != out_stream - && (ferror (deps_stream) || fclose (deps_stream))) ---- a/gcc/cp/class.c -+++ b/gcc/cp/class.c -@@ -6136,7 +6136,7 @@ - if (flags & tf_error) - { - error ("no matches converting function %qD to type %q#T", -- DECL_NAME (OVL_FUNCTION (overload)), -+ DECL_NAME (OVL_CURRENT (overload)), - target_type); - - /* print_candidates expects a chain with the functions in -@@ -6299,13 +6299,8 @@ - dependent on overload resolution. */ - gcc_assert (TREE_CODE (rhs) == ADDR_EXPR - || TREE_CODE (rhs) == COMPONENT_REF -- || TREE_CODE (rhs) == COMPOUND_EXPR -- || really_overloaded_fn (rhs)); -- -- /* We don't overwrite rhs if it is an overloaded function. -- Copying it would destroy the tree link. */ -- if (TREE_CODE (rhs) != OVERLOAD) -- rhs = copy_node (rhs); -+ || really_overloaded_fn (rhs) -+ || (flag_ms_extensions && TREE_CODE (rhs) == FUNCTION_DECL)); - - /* This should really only be used when attempting to distinguish - what sort of a pointer to function we have. For now, any -@@ -6357,19 +6352,6 @@ - /*explicit_targs=*/NULL_TREE, - access_path); - -- case COMPOUND_EXPR: -- TREE_OPERAND (rhs, 0) -- = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags); -- if (TREE_OPERAND (rhs, 0) == error_mark_node) -- return error_mark_node; -- TREE_OPERAND (rhs, 1) -- = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags); -- if (TREE_OPERAND (rhs, 1) == error_mark_node) -- return error_mark_node; -- -- TREE_TYPE (rhs) = lhstype; -- return rhs; -- - case ADDR_EXPR: - { - if (PTRMEM_OK_P (rhs)) ---- a/gcc/cp/cp-tree.h -+++ b/gcc/cp/cp-tree.h -@@ -43,9 +43,6 @@ - #else - #define ATTRIBUTE_GCC_CXXDIAG(m, n) ATTRIBUTE_NONNULL(m) - #endif --extern void cp_cpp_error (cpp_reader *, int, -- const char *, va_list *) -- ATTRIBUTE_GCC_CXXDIAG(3,0); - #ifdef GCC_TOPLEV_H - #error \ - In order for the format checking to accept the C++ front end diagnostic \ ---- a/gcc/cp/cvt.c -+++ b/gcc/cp/cvt.c -@@ -581,6 +581,7 @@ - tree e = expr; - enum tree_code code = TREE_CODE (type); - const char *invalid_conv_diag; -+ tree e1; - - if (error_operand_p (e) || type == error_mark_node) - return error_mark_node; -@@ -629,6 +630,10 @@ - } - } - -+ e1 = targetm.convert_to_type (type, e); -+ if (e1) -+ return e1; -+ - if (code == VOID_TYPE && (convtype & CONV_STATIC)) - { - e = convert_to_void (e, /*implicit=*/NULL, tf_warning_or_error); -@@ -1231,11 +1236,18 @@ - tree - type_promotes_to (tree type) - { -+ tree promoted_type; -+ - if (type == error_mark_node) - return error_mark_node; - - type = TYPE_MAIN_VARIANT (type); - -+ /* Check for promotions of target-defined types first. */ -+ promoted_type = targetm.promoted_type (type); -+ if (promoted_type) -+ return promoted_type; -+ - /* bool always promotes to int (not unsigned), even if it's the same - size. */ - if (type == boolean_type_node) ---- a/gcc/cp/decl2.c -+++ b/gcc/cp/decl2.c -@@ -1717,6 +1717,10 @@ - || (DECL_ASSEMBLER_NAME_SET_P (decl) - && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))) - return true; -+ /* Functions marked "dllexport" must be emitted so that they are -+ visible to other DLLs. */ -+ if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) -+ return true; - /* Otherwise, DECL does not need to be emitted -- yet. A subsequent - reference to DECL might cause it to be emitted later. */ - return false; -@@ -3802,6 +3806,15 @@ - } - - TREE_USED (decl) = 1; -+ if (current_function_decl != NULL_TREE -+ && (TREE_CODE (decl) == VAR_DECL -+ || TREE_CODE (decl) == PARM_DECL -+ || TREE_CODE (decl) == FUNCTION_DECL)) -+ { -+ tree context = decl_function_context (decl); -+ if (context != NULL_TREE && context != current_function_decl) -+ DECL_NONLOCAL (decl) = 1; -+ } - if (DECL_CLONED_FUNCTION_P (decl)) - TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1; - if (TREE_CODE (decl) == FUNCTION_DECL ---- a/gcc/cp/decl.c -+++ b/gcc/cp/decl.c -@@ -4515,7 +4515,7 @@ - - cp_apply_type_quals_to_decl (cp_type_quals (TREE_TYPE (decl)), decl); - -- layout_decl (decl, 0); -+ relayout_decl (decl); - } - } - -@@ -7620,6 +7620,7 @@ - bool parameter_pack_p = declarator? declarator->parameter_pack_p : false; - bool set_no_warning = false; - bool template_type_arg = false; -+ const char *errmsg; - - signed_p = declspecs->specs[(int)ds_signed]; - unsigned_p = declspecs->specs[(int)ds_unsigned]; -@@ -8299,6 +8300,12 @@ - type_quals = TYPE_UNQUALIFIED; - set_no_warning = true; - } -+ errmsg = targetm.invalid_return_type (type); -+ if (errmsg) -+ { -+ error (errmsg); -+ type = integer_type_node; -+ } - - /* Error about some types functions can't return. */ - -@@ -8841,8 +8848,13 @@ - - /* Replace the anonymous name with the real name everywhere. */ - for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) -- if (TYPE_NAME (t) == oldname) -- TYPE_NAME (t) = decl; -+ { -+ if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) -+ { -+ debug_hooks->set_name (t, decl); -+ TYPE_NAME (t) = decl; -+ } -+ } - - if (TYPE_LANG_SPECIFIC (type)) - TYPE_WAS_ANONYMOUS (type) = 1; -@@ -9679,6 +9691,7 @@ - tree type = NULL_TREE; - tree init = TREE_PURPOSE (parm); - tree decl = TREE_VALUE (parm); -+ const char *errmsg; - - if (parm == void_list_node) - break; -@@ -9712,6 +9725,14 @@ - init = NULL_TREE; - } - -+ if (type != error_mark_node -+ && (errmsg = targetm.invalid_parameter_type (type))) -+ { -+ error (errmsg); -+ type = error_mark_node; -+ TREE_TYPE (decl) = error_mark_node; -+ } -+ - if (type != error_mark_node) - { - if (deprecated_state != DEPRECATED_SUPPRESS) ---- a/gcc/cp/error.c -+++ b/gcc/cp/error.c -@@ -2667,39 +2667,6 @@ - #undef next_int - } - --/* Callback from cpp_error for PFILE to print diagnostics arising from -- interpreting strings. The diagnostic is of type LEVEL; MSG is the -- translated message and AP the arguments. */ -- --void --cp_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, -- const char *msg, va_list *ap) --{ -- diagnostic_info diagnostic; -- diagnostic_t dlevel; -- switch (level) -- { -- case CPP_DL_WARNING: -- case CPP_DL_WARNING_SYSHDR: -- dlevel = DK_WARNING; -- break; -- case CPP_DL_PEDWARN: -- dlevel = DK_PEDWARN; -- break; -- case CPP_DL_ERROR: -- dlevel = DK_ERROR; -- break; -- case CPP_DL_ICE: -- dlevel = DK_ICE; -- break; -- default: -- gcc_unreachable (); -- } -- diagnostic_set_info_translated (&diagnostic, msg, ap, -- input_location, dlevel); -- report_diagnostic (&diagnostic); --} -- - /* Warn about the use of C++0x features when appropriate. */ - void - maybe_warn_cpp0x (const char* str) ---- a/gcc/cp/except.c -+++ b/gcc/cp/except.c -@@ -146,14 +146,26 @@ - static tree - build_eh_type_type (tree type) - { -- tree exp = eh_type_info (type); -+ bool is_ref = TREE_CODE (type) == REFERENCE_TYPE; -+ tree exp; -+ -+ if (is_ref) -+ type = TREE_TYPE (type); -+ -+ exp = eh_type_info (type); - - if (!exp) - return NULL; - - mark_used (exp); - -- return convert (ptr_type_node, build_address (exp)); -+ exp = build_address (exp); -+ -+ if (is_ref) -+ exp = targetm.cxx.ttype_ref_encode (exp); -+ -+ exp = convert (ptr_type_node, exp); -+ return exp; - } - - tree -@@ -495,6 +507,16 @@ - initialize_handler_parm (decl, exp); - } - -+ /* Preserve the reference type on the exception, as this affects -+ derived-to-base conversions in catch matching. Only do this when -+ the ABI supports it, as originally this case was (incorrectly) -+ treated just as catching a pointer-to-class by value. */ -+ if (targetm.cxx.ttype_ref_encode -+ && decl && TREE_CODE (type) == POINTER_TYPE -+ && CLASS_TYPE_P (TREE_TYPE (type)) -+ && TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE) -+ type = build_reference_type (type); -+ - return type; - } - -@@ -538,10 +560,20 @@ - raw_raises && TREE_VALUE (raw_raises); - raw_raises = TREE_CHAIN (raw_raises)) - { -- tree type = prepare_eh_type (TREE_VALUE (raw_raises)); -+ tree orig_type = TREE_VALUE (raw_raises); -+ tree type = prepare_eh_type (orig_type); - tree tinfo = eh_type_info (type); - - mark_used (tinfo); -+ /* Preserve the reference type on the exception, as this affects -+ derived-to-base conversions in catch matching. Only do this when -+ the ABI supports it, as originally this case was (incorrectly) -+ treated just as catching a pointer-to-class by value. */ -+ if (targetm.cxx.ttype_ref_encode -+ && TREE_CODE (orig_type) == REFERENCE_TYPE -+ && TREE_CODE (type) == POINTER_TYPE -+ && CLASS_TYPE_P (TREE_TYPE (type))) -+ type = build_reference_type (type); - raises = tree_cons (NULL_TREE, type, raises); - } - -@@ -956,24 +988,40 @@ - static int - can_convert_eh (tree to, tree from) - { -- to = non_reference (to); -- from = non_reference (from); -+ bool to_ref = TREE_CODE (to) == REFERENCE_TYPE; -+ int depth = to_ref; -+ bool outer_const = true; - -- if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE) -+ if (to_ref) -+ to = TREE_TYPE (to); -+ from = non_reference (from); -+ -+ while (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE) - { -+ unsigned to_quals, from_quals; -+ -+ depth++; -+ - to = TREE_TYPE (to); - from = TREE_TYPE (from); -+ to_quals = TYPE_QUALS (to); -+ from_quals = TYPE_QUALS (from); - -- if (! at_least_as_qualified_p (to, from)) -+ if ((from_quals & ~to_quals) -+ || (!outer_const && to_quals & ~from_quals)) - return 0; -- -- if (TREE_CODE (to) == VOID_TYPE) -- return 1; -- -- /* Else fall through. */ -+ -+ if (!(to_quals & TYPE_QUAL_CONST)) -+ outer_const = false; - } - -- if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from) -+ if (same_type_ignoring_top_level_qualifiers_p (from, to)) -+ return 1; -+ -+ if (depth == to_ref + 1 && TREE_CODE (to) == VOID_TYPE) -+ return 1; -+ -+ if (depth < 2 && CLASS_TYPE_P (to) && CLASS_TYPE_P (from) - && PUBLICLY_UNIQUELY_DERIVED_P (to, from)) - return 1; - ---- a/gcc/cp/parser.c -+++ b/gcc/cp/parser.c -@@ -309,8 +309,7 @@ - - /* Subsequent preprocessor diagnostics should use compiler - diagnostic functions to get the compiler source location. */ -- cpp_get_options (parse_in)->client_diagnostic = true; -- cpp_get_callbacks (parse_in)->error = cp_cpp_error; -+ done_lexing = true; - - gcc_assert (lexer->next_token->type != CPP_PURGED); - return lexer; ---- a/gcc/cp/rtti.c -+++ b/gcc/cp/rtti.c -@@ -393,6 +393,7 @@ - return d; - } - -+ gcc_assert (TREE_CODE (type) != REFERENCE_TYPE); - name = mangle_typeinfo_for_type (type); - - d = IDENTIFIER_GLOBAL_VALUE (name); ---- a/gcc/cp/semantics.c -+++ b/gcc/cp/semantics.c -@@ -1120,7 +1120,11 @@ - type = expand_start_catch_block (decl); - HANDLER_TYPE (handler) = type; - if (!processing_template_decl && type) -- mark_used (eh_type_info (type)); -+ { -+ if (TREE_CODE (type) == REFERENCE_TYPE) -+ type = TREE_TYPE (type); -+ mark_used (eh_type_info (type)); -+ } - } - - /* Finish a handler, which may be given by HANDLER. The BLOCKs are -@@ -3243,8 +3247,10 @@ - - /* If the user wants us to keep all inline functions, then mark - this function as needed so that finish_file will make sure to -- output it later. */ -- if (flag_keep_inline_functions && DECL_DECLARED_INLINE_P (fn)) -+ output it later. Similarly, all dllexport'd functions must -+ be emitted; there may be callers in other DLLs. */ -+ if ((flag_keep_inline_functions && DECL_DECLARED_INLINE_P (fn)) -+ || lookup_attribute ("dllexport", DECL_ATTRIBUTES (fn))) - mark_needed (fn); - } - ---- a/gcc/cp/typeck.c -+++ b/gcc/cp/typeck.c -@@ -1707,10 +1707,14 @@ - tree - default_conversion (tree exp) - { -+ /* Check for target-specific promotions. */ -+ tree promoted_type = targetm.promoted_type (TREE_TYPE (exp)); -+ if (promoted_type) -+ exp = cp_convert (promoted_type, exp); - /* Perform the integral promotions first so that bitfield - expressions (which may promote to "int", even if the bitfield is - declared "unsigned") are promoted correctly. */ -- if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (exp))) -+ else if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (exp))) - exp = perform_integral_promotions (exp); - /* Perform the other conversions. */ - exp = decay_conversion (exp); -@@ -3378,7 +3382,6 @@ - - /* If an error was already reported for one of the arguments, - avoid reporting another error. */ -- - if (code0 == ERROR_MARK || code1 == ERROR_MARK) - return error_mark_node; - -@@ -3389,6 +3392,25 @@ - return error_mark_node; - } - -+ /* Issue warnings about peculiar, but valid, uses of NULL. */ -+ if ((orig_op0 == null_node || orig_op1 == null_node) -+ /* It's reasonable to use pointer values as operands of && -+ and ||, so NULL is no exception. */ -+ && code != TRUTH_ANDIF_EXPR && code != TRUTH_ORIF_EXPR -+ && ( /* Both are NULL (or 0) and the operation was not a -+ comparison or a pointer subtraction. */ -+ (null_ptr_cst_p (orig_op0) && null_ptr_cst_p (orig_op1) -+ && code != EQ_EXPR && code != NE_EXPR && code != MINUS_EXPR) -+ /* Or if one of OP0 or OP1 is neither a pointer nor NULL. */ -+ || (!null_ptr_cst_p (orig_op0) -+ && !TYPE_PTR_P (type0) && !TYPE_PTR_TO_MEMBER_P (type0)) -+ || (!null_ptr_cst_p (orig_op1) -+ && !TYPE_PTR_P (type1) && !TYPE_PTR_TO_MEMBER_P (type1))) -+ && (complain & tf_warning)) -+ /* Some sort of arithmetic operation involving NULL was -+ performed. */ -+ warning (OPT_Wpointer_arith, "NULL used in arithmetic"); -+ - switch (code) - { - case MINUS_EXPR: -@@ -3979,25 +4001,6 @@ - } - } - -- /* Issue warnings about peculiar, but valid, uses of NULL. */ -- if ((orig_op0 == null_node || orig_op1 == null_node) -- /* It's reasonable to use pointer values as operands of && -- and ||, so NULL is no exception. */ -- && code != TRUTH_ANDIF_EXPR && code != TRUTH_ORIF_EXPR -- && ( /* Both are NULL (or 0) and the operation was not a comparison. */ -- (null_ptr_cst_p (orig_op0) && null_ptr_cst_p (orig_op1) -- && code != EQ_EXPR && code != NE_EXPR) -- /* Or if one of OP0 or OP1 is neither a pointer nor NULL. */ -- || (!null_ptr_cst_p (orig_op0) && TREE_CODE (TREE_TYPE (op0)) != POINTER_TYPE) -- || (!null_ptr_cst_p (orig_op1) && TREE_CODE (TREE_TYPE (op1)) != POINTER_TYPE)) -- && (complain & tf_warning)) -- /* Some sort of arithmetic operation involving NULL was -- performed. Note that pointer-difference and pointer-addition -- have already been handled above, and so we don't end up here in -- that case. */ -- warning (OPT_Wpointer_arith, "NULL used in arithmetic"); -- -- - /* If CONVERTED is zero, both args will be converted to type RESULT_TYPE. - Then the expression will be built. - It will be given type FINAL_TYPE if that is nonzero; -@@ -5024,6 +5027,12 @@ - return rhs; - } - -+ if (type_unknown_p (rhs)) -+ { -+ error ("no context to resolve type of %qE", rhs); -+ return error_mark_node; -+ } -+ - return build2 (COMPOUND_EXPR, TREE_TYPE (rhs), lhs, rhs); - } - ---- a/gcc/c-ppoutput.c -+++ b/gcc/c-ppoutput.c -@@ -521,6 +521,7 @@ - - if (map != NULL) - { -+ input_location = map->start_location; - if (print.first_time) - { - /* Avoid printing foo.i when the main file is foo.c. */ ---- a/gcc/cse.c -+++ b/gcc/cse.c -@@ -5754,6 +5754,11 @@ - validate_change (object, &XEXP (x, i), - cse_process_notes (XEXP (x, i), object, changed), 0); - -+ /* Rebuild a PLUS expression in canonical form if the first operand -+ ends up as a constant. */ -+ if (code == PLUS && GET_CODE (XEXP (x, 0)) == CONST_INT) -+ return plus_constant (XEXP(x, 1), INTVAL (XEXP (x, 0))); -+ - return x; - } - ---- a/gcc/c-tree.h -+++ b/gcc/c-tree.h -@@ -647,4 +647,8 @@ - extern void pedwarn_c90 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_CDIAG(3,4); - extern void pedwarn_c99 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_CDIAG(3,4); - -+extern bool c_cpp_error (cpp_reader *, int, location_t, unsigned int, -+ const char *, va_list *) -+ ATTRIBUTE_GCC_CDIAG(5,0); -+ - #endif /* ! GCC_C_TREE_H */ ---- a/gcc/c-typeck.c -+++ b/gcc/c-typeck.c -@@ -1765,6 +1765,7 @@ - tree orig_exp; - tree type = TREE_TYPE (exp); - enum tree_code code = TREE_CODE (type); -+ tree promoted_type; - - /* Functions and arrays have been converted during parsing. */ - gcc_assert (code != FUNCTION_TYPE); -@@ -1801,6 +1802,10 @@ - if (exp == error_mark_node) - return error_mark_node; - -+ promoted_type = targetm.promoted_type (type); -+ if (promoted_type) -+ return convert (promoted_type, exp); -+ - if (INTEGRAL_TYPE_P (type)) - return perform_integral_promotions (exp); - ---- a/gcc/dbxout.c -+++ b/gcc/dbxout.c -@@ -376,6 +376,7 @@ - dbxout_handle_pch, /* handle_pch */ - debug_nothing_rtx, /* var_location */ - debug_nothing_void, /* switch_text_section */ -+ debug_nothing_tree_tree, /* set_name */ - 0 /* start_end_main_source_file */ - }; - #endif /* DBX_DEBUGGING_INFO */ -@@ -408,6 +409,7 @@ - dbxout_handle_pch, /* handle_pch */ - debug_nothing_rtx, /* var_location */ - debug_nothing_void, /* switch_text_section */ -+ debug_nothing_tree_tree, /* set_name */ - 0 /* start_end_main_source_file */ - }; - #endif /* XCOFF_DEBUGGING_INFO */ ---- a/gcc/debug.c -+++ b/gcc/debug.c -@@ -50,6 +50,7 @@ - debug_nothing_int, /* handle_pch */ - debug_nothing_rtx, /* var_location */ - debug_nothing_void, /* switch_text_section */ -+ debug_nothing_tree_tree, /* set_name */ - 0 /* start_end_main_source_file */ - }; - -@@ -67,6 +68,12 @@ - } - - void -+debug_nothing_tree_tree (tree t1 ATTRIBUTE_UNUSED, -+ tree t2 ATTRIBUTE_UNUSED) -+{ -+} -+ -+void - debug_nothing_tree_tree_tree_bool (tree t1 ATTRIBUTE_UNUSED, - tree t2 ATTRIBUTE_UNUSED, - tree t3 ATTRIBUTE_UNUSED, ---- a/gcc/debug.h -+++ b/gcc/debug.h -@@ -126,6 +126,10 @@ - text sections. */ - void (* switch_text_section) (void); - -+ /* Called from grokdeclarator. Replaces the anonymous name with the -+ type name. */ -+ void (* set_name) (tree, tree); -+ - /* This is 1 if the debug writer wants to see start and end commands for the - main source files, and 0 otherwise. */ - int start_end_main_source_file; -@@ -140,6 +144,7 @@ - extern void debug_nothing_int (unsigned int); - extern void debug_nothing_int_int (unsigned int, unsigned int); - extern void debug_nothing_tree (tree); -+extern void debug_nothing_tree_tree (tree, tree); - extern void debug_nothing_tree_int (tree, int); - extern void debug_nothing_tree_tree_tree_bool (tree, tree, tree, bool); - extern bool debug_true_const_tree (const_tree); ---- a/gcc/defaults.h -+++ b/gcc/defaults.h -@@ -902,7 +902,8 @@ - - /* On most machines, the CFA coincides with the first incoming parm. */ - #ifndef ARG_POINTER_CFA_OFFSET --#define ARG_POINTER_CFA_OFFSET(FNDECL) FIRST_PARM_OFFSET (FNDECL) -+#define ARG_POINTER_CFA_OFFSET(FNDECL) \ -+ (FIRST_PARM_OFFSET (FNDECL) + crtl->args.pretend_args_size) - #endif - - /* On most machines, we use the CFA as DW_AT_frame_base. */ ---- a/gcc/diagnostic.c -+++ b/gcc/diagnostic.c -@@ -126,6 +126,7 @@ - diagnostic->message.args_ptr = args; - diagnostic->message.format_spec = msg; - diagnostic->location = location; -+ diagnostic->override_column = 0; - diagnostic->kind = kind; - diagnostic->option_index = 0; - } -@@ -153,6 +154,8 @@ - }; - const char *text = _(diagnostic_kind_text[diagnostic->kind]); - expanded_location s = expand_location (diagnostic->location); -+ if (diagnostic->override_column) -+ s.column = diagnostic->override_column; - gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND); - - return ---- a/gcc/diagnostic.h -+++ b/gcc/diagnostic.h -@@ -41,6 +41,7 @@ - { - text_info message; - location_t location; -+ unsigned int override_column; - /* TREE_BLOCK if the diagnostic is to be reported in some inline - function inlined into other function, otherwise NULL. */ - tree abstract_origin; -@@ -185,6 +186,10 @@ - - #define report_diagnostic(D) diagnostic_report_diagnostic (global_dc, D) - -+/* Override the column number to be used for reporting a -+ diagnostic. */ -+#define diagnostic_override_column(DI, COL) (DI)->override_column = (COL) -+ - /* Diagnostic related functions. */ - extern void diagnostic_initialize (diagnostic_context *); - extern void diagnostic_report_current_module (diagnostic_context *); ---- a/gcc/dwarf2out.c -+++ b/gcc/dwarf2out.c -@@ -2474,6 +2474,12 @@ - insn = PATTERN (insn); - - dwarf2out_frame_debug_expr (insn, label); -+ -+ /* Check again. A parallel can save and update the same register. -+ We could probably check just once, here, but this is safer than -+ removing the check above. */ -+ if (clobbers_queued_reg_save (insn)) -+ flush_queued_reg_saves (); - } - - #endif -@@ -4598,6 +4604,7 @@ - static void dwarf2out_abstract_function (tree); - static void dwarf2out_var_location (rtx); - static void dwarf2out_begin_function (tree); -+static void dwarf2out_set_name (tree, tree); - - /* The debug hooks structure. */ - -@@ -4631,6 +4638,7 @@ - debug_nothing_int, /* handle_pch */ - dwarf2out_var_location, - dwarf2out_switch_text_section, -+ dwarf2out_set_name, - 1 /* start_end_main_source_file */ - }; - #endif -@@ -5975,12 +5983,9 @@ - (const char *)x2) == 0; - } - --/* Add a string attribute value to a DIE. */ -- --static inline void --add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str) -+static struct indirect_string_node * -+find_AT_string (const char *str) - { -- dw_attr_node attr; - struct indirect_string_node *node; - void **slot; - -@@ -6001,6 +6006,18 @@ - node = (struct indirect_string_node *) *slot; - - node->refcount++; -+ return node; -+} -+ -+/* Add a string attribute value to a DIE. */ -+ -+static inline void -+add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str) -+{ -+ dw_attr_node attr; -+ struct indirect_string_node *node; -+ -+ node = find_AT_string (str); - - attr.dw_attr = attr_kind; - attr.dw_attr_val.val_class = dw_val_class_str; -@@ -6637,6 +6654,8 @@ - static inline var_loc_list * - lookup_decl_loc (const_tree decl) - { -+ if (!decl_loc_table) -+ return NULL; - return (var_loc_list *) - htab_find_with_hash (decl_loc_table, decl, DECL_UID (decl)); - } -@@ -13471,6 +13490,7 @@ - tree save_fn; - tree context; - int was_abstract = DECL_ABSTRACT (decl); -+ htab_t old_decl_loc_table; - - /* Make sure we have the actual abstract inline, not a clone. */ - decl = DECL_ORIGIN (decl); -@@ -13480,6 +13500,12 @@ - /* We've already generated the abstract instance. */ - return; - -+ /* We can be called while recursively when seeing block defining inlined subroutine -+ DIE. Be sure to not clobber the outer location table nor use it or we would -+ get locations in abstract instantces. */ -+ old_decl_loc_table = decl_loc_table; -+ decl_loc_table = NULL; -+ - /* Be sure we've emitted the in-class declaration DIE (if any) first, so - we don't get confused by DECL_ABSTRACT. */ - if (debug_info_level > DINFO_LEVEL_TERSE) -@@ -13501,6 +13527,7 @@ - set_decl_abstract_flags (decl, 0); - - current_function_decl = save_fn; -+ decl_loc_table = old_decl_loc_table; - pop_cfun (); - } - -@@ -15796,6 +15823,31 @@ - return fd->emitted_number; - } - -+/* Replace DW_AT_name for the decl with name. */ -+ -+static void -+dwarf2out_set_name (tree decl, tree name) -+{ -+ dw_die_ref die; -+ dw_attr_ref attr; -+ -+ die = TYPE_SYMTAB_DIE (decl); -+ if (!die) -+ return; -+ -+ attr = get_AT (die, DW_AT_name); -+ if (attr) -+ { -+ struct indirect_string_node *node; -+ -+ node = find_AT_string (dwarf2_name (name, 0)); -+ /* replace the string. */ -+ attr->dw_attr_val.v.val_str = node; -+ } -+ -+ else -+ add_name_attribute (die, dwarf2_name (name, 0)); -+} - /* Called by the final INSN scan whenever we see a var location. We - use it to drop labels in the right places, and throw the location in - our lookup table. */ ---- a/gcc/except.c -+++ b/gcc/except.c -@@ -3567,6 +3567,12 @@ - paths below go through assemble_integer, which would take - care of this for us. */ - STRIP_NOPS (type); -+ if (TREE_CODE (type) == POINTER_PLUS_EXPR) -+ { -+ gcc_assert (TREE_CODE (TREE_OPERAND (type, 1)) == INTEGER_CST); -+ type = TREE_OPERAND (type, 0); -+ STRIP_NOPS (type); -+ } - if (TREE_CODE (type) == ADDR_EXPR) - { - type = TREE_OPERAND (type, 0); ---- a/gcc/explow.c -+++ b/gcc/explow.c -@@ -1491,9 +1491,9 @@ - in which a scalar value of mode MODE was returned by a library call. */ - - rtx --hard_libcall_value (enum machine_mode mode) -+hard_libcall_value (enum machine_mode mode, rtx fun) - { -- return LIBCALL_VALUE (mode); -+ return targetm.calls.libcall_value (mode, fun); - } - - /* Look up the tree code for a given rtx code ---- a/gcc/expmed.c -+++ b/gcc/expmed.c -@@ -103,7 +103,8 @@ - static int neg_cost[2][NUM_MACHINE_MODES]; - static int shift_cost[2][NUM_MACHINE_MODES][MAX_BITS_PER_WORD]; - static int shiftadd_cost[2][NUM_MACHINE_MODES][MAX_BITS_PER_WORD]; --static int shiftsub_cost[2][NUM_MACHINE_MODES][MAX_BITS_PER_WORD]; -+static int shiftsub0_cost[2][NUM_MACHINE_MODES][MAX_BITS_PER_WORD]; -+static int shiftsub1_cost[2][NUM_MACHINE_MODES][MAX_BITS_PER_WORD]; - static int mul_cost[2][NUM_MACHINE_MODES]; - static int sdiv_cost[2][NUM_MACHINE_MODES]; - static int udiv_cost[2][NUM_MACHINE_MODES]; -@@ -130,7 +131,8 @@ - struct rtx_def shift; rtunion shift_fld1; - struct rtx_def shift_mult; rtunion shift_mult_fld1; - struct rtx_def shift_add; rtunion shift_add_fld1; -- struct rtx_def shift_sub; rtunion shift_sub_fld1; -+ struct rtx_def shift_sub0; rtunion shift_sub0_fld1; -+ struct rtx_def shift_sub1; rtunion shift_sub1_fld1; - } all; - - rtx pow2[MAX_BITS_PER_WORD]; -@@ -201,9 +203,13 @@ - XEXP (&all.shift_add, 0) = &all.shift_mult; - XEXP (&all.shift_add, 1) = &all.reg; - -- PUT_CODE (&all.shift_sub, MINUS); -- XEXP (&all.shift_sub, 0) = &all.shift_mult; -- XEXP (&all.shift_sub, 1) = &all.reg; -+ PUT_CODE (&all.shift_sub0, MINUS); -+ XEXP (&all.shift_sub0, 0) = &all.shift_mult; -+ XEXP (&all.shift_sub0, 1) = &all.reg; -+ -+ PUT_CODE (&all.shift_sub1, MINUS); -+ XEXP (&all.shift_sub1, 0) = &all.reg; -+ XEXP (&all.shift_sub1, 1) = &all.shift_mult; - - for (speed = 0; speed < 2; speed++) - { -@@ -226,7 +232,8 @@ - PUT_MODE (&all.shift, mode); - PUT_MODE (&all.shift_mult, mode); - PUT_MODE (&all.shift_add, mode); -- PUT_MODE (&all.shift_sub, mode); -+ PUT_MODE (&all.shift_sub0, mode); -+ PUT_MODE (&all.shift_sub1, mode); - - add_cost[speed][mode] = rtx_cost (&all.plus, SET, speed); - neg_cost[speed][mode] = rtx_cost (&all.neg, SET, speed); -@@ -254,8 +261,8 @@ - } - - shift_cost[speed][mode][0] = 0; -- shiftadd_cost[speed][mode][0] = shiftsub_cost[speed][mode][0] -- = add_cost[speed][mode]; -+ shiftadd_cost[speed][mode][0] = shiftsub0_cost[speed][mode][0] -+ = shiftsub1_cost[speed][mode][0] = add_cost[speed][mode]; - - n = MIN (MAX_BITS_PER_WORD, GET_MODE_BITSIZE (mode)); - for (m = 1; m < n; m++) -@@ -265,7 +272,8 @@ - - shift_cost[speed][mode][m] = rtx_cost (&all.shift, SET, speed); - shiftadd_cost[speed][mode][m] = rtx_cost (&all.shift_add, SET, speed); -- shiftsub_cost[speed][mode][m] = rtx_cost (&all.shift_sub, SET, speed); -+ shiftsub0_cost[speed][mode][m] = rtx_cost (&all.shift_sub0, SET, speed); -+ shiftsub1_cost[speed][mode][m] = rtx_cost (&all.shift_sub1, SET, speed); - } - } - } -@@ -2397,6 +2405,7 @@ - struct mult_cost best_cost; - struct mult_cost new_limit; - int op_cost, op_latency; -+ unsigned HOST_WIDE_INT orig_t = t; - unsigned HOST_WIDE_INT q; - int maxm = MIN (BITS_PER_WORD, GET_MODE_BITSIZE (mode)); - int hash_index; -@@ -2542,6 +2551,38 @@ - best_alg->log[best_alg->ops] = m; - best_alg->op[best_alg->ops] = alg_shift; - } -+ -+ /* See if treating ORIG_T as a signed number yields a better -+ sequence. Try this sequence only for a negative ORIG_T -+ as it would be useless for a non-negative ORIG_T. */ -+ if ((HOST_WIDE_INT) orig_t < 0) -+ { -+ /* Shift ORIG_T as follows because a right shift of a -+ negative-valued signed type is implementation -+ defined. */ -+ q = ~(~orig_t >> m); -+ /* The function expand_shift will choose between a shift -+ and a sequence of additions, so the observed cost is -+ given as MIN (m * add_cost[speed][mode], -+ shift_cost[speed][mode][m]). */ -+ op_cost = m * add_cost[speed][mode]; -+ if (shift_cost[speed][mode][m] < op_cost) -+ op_cost = shift_cost[speed][mode][m]; -+ new_limit.cost = best_cost.cost - op_cost; -+ new_limit.latency = best_cost.latency - op_cost; -+ synth_mult (alg_in, q, &new_limit, mode); -+ -+ alg_in->cost.cost += op_cost; -+ alg_in->cost.latency += op_cost; -+ if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost)) -+ { -+ struct algorithm *x; -+ best_cost = alg_in->cost; -+ x = alg_in, alg_in = best_alg, best_alg = x; -+ best_alg->log[best_alg->ops] = m; -+ best_alg->op[best_alg->ops] = alg_shift; -+ } -+ } - } - if (cache_hit) - goto done; -@@ -2604,6 +2645,29 @@ - best_alg->op[best_alg->ops] = alg_add_t_m2; - } - } -+ -+ /* We may be able to calculate a * -7, a * -15, a * -31, etc -+ quickly with a - a * n for some appropriate constant n. */ -+ m = exact_log2 (-orig_t + 1); -+ if (m >= 0 && m < maxm) -+ { -+ op_cost = shiftsub1_cost[speed][mode][m]; -+ new_limit.cost = best_cost.cost - op_cost; -+ new_limit.latency = best_cost.latency - op_cost; -+ synth_mult (alg_in, (unsigned HOST_WIDE_INT) (-orig_t + 1) >> m, &new_limit, mode); -+ -+ alg_in->cost.cost += op_cost; -+ alg_in->cost.latency += op_cost; -+ if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost)) -+ { -+ struct algorithm *x; -+ best_cost = alg_in->cost; -+ x = alg_in, alg_in = best_alg, best_alg = x; -+ best_alg->log[best_alg->ops] = m; -+ best_alg->op[best_alg->ops] = alg_sub_t_m2; -+ } -+ } -+ - if (cache_hit) - goto done; - } -@@ -2673,9 +2737,9 @@ - hardware the shift may be executed concurrently with the - earlier steps in the algorithm. */ - op_cost = add_cost[speed][mode] + shift_cost[speed][mode][m]; -- if (shiftsub_cost[speed][mode][m] < op_cost) -+ if (shiftsub0_cost[speed][mode][m] < op_cost) - { -- op_cost = shiftsub_cost[speed][mode][m]; -+ op_cost = shiftsub0_cost[speed][mode][m]; - op_latency = op_cost; - } - else -@@ -2738,7 +2802,7 @@ - m = exact_log2 (q); - if (m >= 0 && m < maxm) - { -- op_cost = shiftsub_cost[speed][mode][m]; -+ op_cost = shiftsub0_cost[speed][mode][m]; - new_limit.cost = best_cost.cost - op_cost; - new_limit.latency = best_cost.latency - op_cost; - synth_mult (alg_in, (t + 1) >> m, &new_limit, mode); ---- a/gcc/expr.c -+++ b/gcc/expr.c -@@ -4391,6 +4391,29 @@ - - /* Compute FROM and store the value in the rtx we got. */ - -+ if (TREE_CODE (to) == MISALIGNED_INDIRECT_REF) -+ { -+ rtx insn; -+ rtx from_rtx; -+ enum insn_code icode; -+ enum machine_mode mode = GET_MODE (to_rtx); -+ -+ icode = optab_handler (movmisalign_optab, mode)->insn_code; -+ gcc_assert (icode != CODE_FOR_nothing); -+ -+ from_rtx = expand_expr (from, NULL_RTX, mode, EXPAND_NORMAL); -+ insn = GEN_FCN (icode) (to_rtx, from_rtx); -+ /* If that failed then force the source into a reg and try again. */ -+ if (!insn) -+ { -+ from_rtx = copy_to_mode_reg(mode, from_rtx); -+ insn = GEN_FCN (icode) (to_rtx, from_rtx); -+ gcc_assert(insn); -+ } -+ emit_insn (insn); -+ return; -+ } -+ - push_temp_slots (); - result = store_expr (from, to_rtx, 0, nontemporal); - preserve_temp_slots (result); -@@ -7291,6 +7314,19 @@ - decl_rtl = DECL_RTL (exp); - gcc_assert (decl_rtl); - decl_rtl = copy_rtx (decl_rtl); -+ /* Record writes to register variables. */ -+ if (modifier == EXPAND_WRITE && REG_P(decl_rtl) -+ && REGNO(decl_rtl) < FIRST_PSEUDO_REGISTER) -+ { -+ int i = REGNO(decl_rtl); -+ int nregs = hard_regno_nregs[i][GET_MODE(decl_rtl)]; -+ while (nregs) -+ { -+ SET_HARD_REG_BIT(crtl->asm_clobbers, i); -+ i++; -+ nregs--; -+ } -+ } - - /* Ensure variable marked as used even if it doesn't go through - a parser. If it hasn't be used yet, write out an external -@@ -7538,14 +7574,15 @@ - - /* Resolve the misalignment now, so that we don't have to remember - to resolve it later. Of course, this only works for reads. */ -- /* ??? When we get around to supporting writes, we'll have to handle -- this in store_expr directly. The vectorizer isn't generating -- those yet, however. */ - if (code == MISALIGNED_INDIRECT_REF) - { - int icode; - rtx reg, insn; - -+ /* For writes produce a MEM, and expand_assignment will DTRT. */ -+ if (modifier == EXPAND_WRITE) -+ return temp; -+ - gcc_assert (modifier == EXPAND_NORMAL - || modifier == EXPAND_STACK_PARM); - ---- a/gcc/expr.h -+++ b/gcc/expr.h -@@ -757,7 +757,7 @@ - - /* Return an rtx that refers to the value returned by a library call - in its original home. This becomes invalid if any more code is emitted. */ --extern rtx hard_libcall_value (enum machine_mode); -+extern rtx hard_libcall_value (enum machine_mode, rtx); - - /* Return the mode desired by operand N of a particular bitfield - insert/extract insn, or MAX_MACHINE_MODE if no such insn is ---- a/gcc/final.c -+++ b/gcc/final.c -@@ -891,6 +891,7 @@ - if (LABEL_P (insn)) - { - rtx next; -+ bool next_is_jumptable; - - /* Merge in alignments computed by compute_alignments. */ - log = LABEL_TO_ALIGNMENT (insn); -@@ -900,31 +901,30 @@ - max_skip = LABEL_TO_MAX_SKIP (insn); - } - -- log = LABEL_ALIGN (insn); -- if (max_log < log) -+ next = next_nonnote_insn (insn); -+ next_is_jumptable = next && JUMP_TABLE_DATA_P (next); -+ if (!next_is_jumptable) - { -- max_log = log; -- max_skip = LABEL_ALIGN_MAX_SKIP; -+ log = LABEL_ALIGN (insn); -+ if (max_log < log) -+ { -+ max_log = log; -+ max_skip = LABEL_ALIGN_MAX_SKIP; -+ } - } -- next = next_nonnote_insn (insn); - /* ADDR_VECs only take room if read-only data goes into the text - section. */ -- if (JUMP_TABLES_IN_TEXT_SECTION -- || readonly_data_section == text_section) -- if (next && JUMP_P (next)) -- { -- rtx nextbody = PATTERN (next); -- if (GET_CODE (nextbody) == ADDR_VEC -- || GET_CODE (nextbody) == ADDR_DIFF_VEC) -- { -- log = ADDR_VEC_ALIGN (next); -- if (max_log < log) -- { -- max_log = log; -- max_skip = LABEL_ALIGN_MAX_SKIP; -- } -- } -- } -+ if ((JUMP_TABLES_IN_TEXT_SECTION -+ || readonly_data_section == text_section) -+ && next_is_jumptable) -+ { -+ log = ADDR_VEC_ALIGN (next); -+ if (max_log < log) -+ { -+ max_log = log; -+ max_skip = LABEL_ALIGN_MAX_SKIP; -+ } -+ } - LABEL_TO_ALIGNMENT (insn) = max_log; - LABEL_TO_MAX_SKIP (insn) = max_skip; - max_log = 0; -@@ -2013,48 +2013,41 @@ - app_disable (); - - next = next_nonnote_insn (insn); -- if (next != 0 && JUMP_P (next)) -+ /* If this label is followed by a jump-table, make sure we put -+ the label in the read-only section. Also possibly write the -+ label and jump table together. */ -+ if (next != 0 && JUMP_TABLE_DATA_P (next)) - { -- rtx nextbody = PATTERN (next); -- -- /* If this label is followed by a jump-table, -- make sure we put the label in the read-only section. Also -- possibly write the label and jump table together. */ -- -- if (GET_CODE (nextbody) == ADDR_VEC -- || GET_CODE (nextbody) == ADDR_DIFF_VEC) -- { - #if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC) -- /* In this case, the case vector is being moved by the -- target, so don't output the label at all. Leave that -- to the back end macros. */ -+ /* In this case, the case vector is being moved by the -+ target, so don't output the label at all. Leave that -+ to the back end macros. */ - #else -- if (! JUMP_TABLES_IN_TEXT_SECTION) -- { -- int log_align; -+ if (! JUMP_TABLES_IN_TEXT_SECTION) -+ { -+ int log_align; - -- switch_to_section (targetm.asm_out.function_rodata_section -- (current_function_decl)); -+ switch_to_section (targetm.asm_out.function_rodata_section -+ (current_function_decl)); - - #ifdef ADDR_VEC_ALIGN -- log_align = ADDR_VEC_ALIGN (next); -+ log_align = ADDR_VEC_ALIGN (next); - #else -- log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT); -+ log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT); - #endif -- ASM_OUTPUT_ALIGN (file, log_align); -- } -- else -- switch_to_section (current_function_section ()); -+ ASM_OUTPUT_ALIGN (file, log_align); -+ } -+ else -+ switch_to_section (current_function_section ()); - - #ifdef ASM_OUTPUT_CASE_LABEL -- ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), -- next); -+ ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), -+ next); - #else -- targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn)); -+ targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn)); - #endif - #endif -- break; -- } -+ break; - } - if (LABEL_ALT_ENTRY_P (insn)) - output_alternate_entry_point (file, insn); ---- a/gcc/fold-const.c -+++ b/gcc/fold-const.c -@@ -2289,7 +2289,24 @@ - real_convert (&value, TYPE_MODE (type), &TREE_REAL_CST (arg1)); - t = build_real (type, value); - -- TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1); -+ /* If converting an infinity or NAN to a representation that doesn't -+ have one, set the overflow bit so that we can produce some kind of -+ error message at the appropriate point if necessary. It's not the -+ most user-friendly message, but it's better than nothing. */ -+ if (REAL_VALUE_ISINF (TREE_REAL_CST (arg1)) -+ && !MODE_HAS_INFINITIES (TYPE_MODE (type))) -+ TREE_OVERFLOW (t) = 1; -+ else if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg1)) -+ && !MODE_HAS_NANS (TYPE_MODE (type))) -+ TREE_OVERFLOW (t) = 1; -+ /* Regular overflow, conversion produced an infinity in a mode that -+ can't represent them. */ -+ else if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) -+ && REAL_VALUE_ISINF (value) -+ && !REAL_VALUE_ISINF (TREE_REAL_CST (arg1))) -+ TREE_OVERFLOW (t) = 1; -+ else -+ TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1); - return t; - } - ---- a/gcc/fortran/cpp.c -+++ b/gcc/fortran/cpp.c -@@ -137,6 +137,9 @@ - static void cb_ident (cpp_reader *, source_location, const cpp_string *); - static void cb_used_define (cpp_reader *, source_location, cpp_hashnode *); - static void cb_used_undef (cpp_reader *, source_location, cpp_hashnode *); -+static bool cb_cpp_error (cpp_reader *, int, location_t, unsigned int, -+ const char *, va_list *) -+ ATTRIBUTE_GCC_DIAG(5,0); - void pp_dir_change (cpp_reader *, const char *); - - static int dump_macro (cpp_reader *, cpp_hashnode *, void *); -@@ -452,7 +455,6 @@ - cpp_option->cplusplus_comments = 0; - - cpp_option->pedantic = pedantic; -- cpp_option->inhibit_warnings = inhibit_warnings; - - cpp_option->dollars_in_ident = gfc_option.flag_dollar_ok; - cpp_option->discard_comments = gfc_cpp_option.discard_comments; -@@ -465,9 +467,6 @@ - - cpp_post_options (cpp_in); - -- /* If an error has occurred in cpplib, note it so we fail immediately. */ -- errorcount += cpp_errors (cpp_in); -- - gfc_cpp_register_include_paths (); - } - -@@ -482,6 +481,7 @@ - cb->line_change = cb_line_change; - cb->ident = cb_ident; - cb->def_pragma = cb_def_pragma; -+ cb->error = cb_cpp_error; - - if (gfc_cpp_option.dump_includes) - cb->include = cb_include; -@@ -961,6 +961,57 @@ - cpp_define_queue = q; - } - -+/* Callback from cpp_error for PFILE to print diagnostics from the -+ preprocessor. The diagnostic is of type LEVEL, at location -+ LOCATION, with column number possibly overridden by COLUMN_OVERRIDE -+ if not zero; MSG is the translated message and AP the arguments. -+ Returns true if a diagnostic was emitted, false otherwise. */ -+ -+static bool -+cb_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, -+ location_t location, unsigned int column_override, -+ const char *msg, va_list *ap) -+{ -+ diagnostic_info diagnostic; -+ diagnostic_t dlevel; -+ int save_warn_system_headers = warn_system_headers; -+ bool ret; -+ -+ switch (level) -+ { -+ case CPP_DL_WARNING_SYSHDR: -+ warn_system_headers = 1; -+ /* Fall through. */ -+ case CPP_DL_WARNING: -+ dlevel = DK_WARNING; -+ break; -+ case CPP_DL_PEDWARN: -+ dlevel = DK_PEDWARN; -+ break; -+ case CPP_DL_ERROR: -+ dlevel = DK_ERROR; -+ break; -+ case CPP_DL_ICE: -+ dlevel = DK_ICE; -+ break; -+ case CPP_DL_NOTE: -+ dlevel = DK_NOTE; -+ break; -+ case CPP_DL_FATAL: -+ dlevel = DK_FATAL; -+ break; -+ default: -+ gcc_unreachable (); -+ } -+ diagnostic_set_info_translated (&diagnostic, msg, ap, -+ location, dlevel); -+ if (column_override) -+ diagnostic_override_column (&diagnostic, column_override); -+ ret = report_diagnostic (&diagnostic); -+ if (level == CPP_DL_WARNING_SYSHDR) -+ warn_system_headers = save_warn_system_headers; -+ return ret; -+} - - /* Callback called when -fworking-director and -E to emit working - directory in cpp output file. */ ---- a/gcc/function.c -+++ b/gcc/function.c -@@ -272,7 +272,10 @@ - if (! type) - type = lang_hooks.types.type_for_mode (mode, 0); - -- return STACK_SLOT_ALIGNMENT (type, mode, alignment); -+ return alignment_for_aligned_arrays (type, -+ STACK_SLOT_ALIGNMENT (type, -+ mode, -+ alignment)); - } - - /* Allocate a stack slot of SIZE bytes and return a MEM rtx for it -@@ -5359,6 +5362,57 @@ - { - return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (cfun->decl)); - } -+ -+/* This function adjusts alignments as appropriate according to the -+ setting of -falign-arrays. If that is specified then the minimum -+ alignment for array variables is set to be the largest power of two -+ less than or equal to their total storage size, or the biggest -+ alignment used on the machine, whichever is smaller. */ -+ -+unsigned int -+alignment_for_aligned_arrays (tree ty, unsigned int existing_alignment) -+{ -+ unsigned int min_alignment; -+ tree size; -+ -+ /* Return the existing alignment if not using -falign-arrays or if -+ the type is not an array type. */ -+ if (!flag_align_arrays || !ty || TREE_CODE (ty) != ARRAY_TYPE) -+ return existing_alignment; -+ -+ /* Extract the total storage size of the array in bits. */ -+ size = TYPE_SIZE (ty); -+ gcc_assert (size); -+ -+ /* At least for variable-length arrays, TREE_CODE (size) might not be an -+ integer constant; check it now. If it is not, give the array at -+ least BIGGEST_ALIGNMENT just to be safe. Furthermore, we assume that -+ alignments always fit into a host integer. So if we can't fit the -+ size of the array in bits into a host integer, it must also be large -+ enough to deserve at least BIGGEST_ALIGNMENT (see below). */ -+ if (TREE_CODE (size) != INTEGER_CST || !host_integerp (size, 1)) -+ min_alignment = BIGGEST_ALIGNMENT; -+ else -+ { -+ unsigned HOST_WIDE_INT bits = TREE_INT_CST_LOW (size); -+ bits = (bits ? bits : 1); -+ -+ /* An array with size greater than BIGGEST_ALIGNMENT is assigned -+ at least that alignment. In all other cases the minimum -+ alignment of the array is set to be the largest power of two -+ less than or equal to the total storage size of the array. -+ We assume that BIGGEST_ALIGNMENT fits in "unsigned int"; thus, -+ the shift below will not overflow. */ -+ if (bits >= BIGGEST_ALIGNMENT) -+ min_alignment = BIGGEST_ALIGNMENT; -+ else -+ min_alignment = 1 << (floor_log2 (bits)); -+ } -+ -+ /* Having computed the minimum permissible alignment, enlarge it -+ if EXISTING_ALIGNMENT is greater. */ -+ return MAX (min_alignment, existing_alignment); -+} - - - static unsigned int ---- a/gcc/function.h -+++ b/gcc/function.h -@@ -25,6 +25,7 @@ - #include "tree.h" - #include "hashtab.h" - #include "varray.h" -+#include "hard-reg-set.h" - - /* Stack of pending (incomplete) sequences saved by `start_sequence'. - Each element describes one pending sequence. -@@ -441,6 +442,8 @@ - - /* True if dbr_schedule has already been called for this function. */ - bool dbr_scheduled_p; -+ -+ HARD_REG_SET asm_clobbers; - }; - - #define return_label (crtl->x_return_label) -@@ -687,4 +690,7 @@ - extern void used_types_insert (tree); - - extern int get_next_funcdef_no (void); -+ -+extern unsigned int alignment_for_aligned_arrays (tree, unsigned int); -+ - #endif /* GCC_FUNCTION_H */ ---- a/gcc/gcc.c -+++ b/gcc/gcc.c -@@ -651,8 +651,32 @@ - - /* config.h can define SWITCHES_NEED_SPACES to control which options - require spaces between the option and the argument. */ -+/* GCC Bugzilla PR11810 indicates that GCC does not correctly handle -+ "-ofoo.o", in that it records "-ofoo.o" as a temporary file to -+ delete, rather than "foo.o". -+ -+ Unfortunately, Eclipse's makefile generators use the "-ofoo.o" -+ form. See also CS Issue #3433. So, although most users probably -+ use "-o foo.o", the "-ofoo.o" form is used in practice. -+ -+ See this email thread for additional information: -+ -+ http://gcc.gnu.org/ml/gcc/2008-07/msg00395.html -+ -+ Therefore, we define SWITCHES_NEED_SPACES to include "o" by -+ default. This causes "-ofoo.o" to be split into "-o foo.o" during -+ the initial processing of the command-line, before being seen by -+ the specs machinery. -+ -+ A risk of this change is that tools which *require* the "-ofoo.o" -+ form will no longer work. However, we know of no such tools, and -+ they would not have worked with the "-o foo.o" form anyhow. -+ -+ If this general strategy is acceptable upstream, the best approach -+ might be simply to eliminate this macro, since the only definitions -+ in target files are also to the value "o". */ - #ifndef SWITCHES_NEED_SPACES --#define SWITCHES_NEED_SPACES "" -+#define SWITCHES_NEED_SPACES "o" - #endif - - /* config.h can define ENDFILE_SPEC to override the default crtn files. */ -@@ -728,6 +752,8 @@ - %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\ - %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\ - %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\ -+ %{Wno-poison-system-directories:--no-poison-system-directories}\ -+ %{Werror=poison-system-directories:--error-poison-system-directories}\ - %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\ - %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)} %(mflib)\ - %{fprofile-arcs|fprofile-generate|coverage:-lgcov}\ -@@ -4616,27 +4642,53 @@ - - if (argbuf_index > 0) - { -- int i, first; -+ int i, first, n; - - first = n_switches; -- n_switches += argbuf_index; -- switches = XRESIZEVEC (struct switchstr, switches, n_switches + 1); -+ n = n_switches + argbuf_index; -+ switches = XRESIZEVEC (struct switchstr, switches, n + 1); -+ switches[n] = switches[first]; - - switches[n_switches] = switches[first]; - for (i = 0; i < argbuf_index; i++) - { - struct switchstr *sw; -+ const char *p = &argbuf[i][1]; -+ int c = *p; - - /* Each switch should start with '-'. */ - if (argbuf[i][0] != '-') - fatal ("switch '%s' does not start with '-'", argbuf[i]); - -- sw = &switches[i + first]; -+ sw = &switches[n_switches]; - sw->part1 = &argbuf[i][1]; - sw->args = 0; - sw->live_cond = 0; - sw->validated = 0; - sw->ordering = 0; -+ -+ /* Deal with option arguments in separate argv elements. */ -+ if ((SWITCH_TAKES_ARG (c) > (p[1] != 0)) -+ || WORD_SWITCH_TAKES_ARG (p)) -+ { -+ int j = 0; -+ int n_args = WORD_SWITCH_TAKES_ARG (p); -+ -+ if (n_args == 0) -+ { -+ /* Count only the option arguments in separate argv elements. */ -+ n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0); -+ } -+ if (i + n_args >= argbuf_index) -+ fatal ("argument to '-%s' is missing", p); -+ switches[n_switches].args -+ = XNEWVEC (const char *, n_args + 1); -+ while (j < n_args) -+ switches[n_switches].args[j++] = argbuf[++i]; -+ /* Null-terminate the vector. */ -+ switches[n_switches].args[j] = 0; -+ } -+ n_switches++; - } - } - } ---- a/gcc/gcse.c -+++ b/gcc/gcse.c -@@ -172,6 +172,7 @@ - #include "hashtab.h" - #include "df.h" - #include "dbgcnt.h" -+#include "target.h" - - /* Propagate flow information through back edges and thus enable PRE's - moving loop invariant calculations out of loops. -@@ -1744,7 +1745,9 @@ - REG_EQUIV notes and if the argument slot is used somewhere - explicitly, it means address of parameter has been taken, - so we should not extend the lifetime of the pseudo. */ -- && (note == NULL_RTX || ! MEM_P (XEXP (note, 0)))) -+ && (note == NULL_RTX || ! MEM_P (XEXP (note, 0))) -+ && ! (targetm.cannot_copy_insn_p && INSN_P (insn) -+ && targetm.cannot_copy_insn_p (insn))) - { - /* An expression is not anticipatable if its operands are - modified before this insn or if this is not the only SET in ---- a/gcc/genautomata.c -+++ b/gcc/genautomata.c -@@ -1,5 +1,5 @@ - /* Pipeline hazard description translator. -- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 -+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 - Free Software Foundation, Inc. - - Written by Vladimir Makarov <vmakarov@redhat.com> -@@ -22,21 +22,25 @@ - - /* References: - -- 1. Detecting pipeline structural hazards quickly. T. Proebsting, -+ 1. The finite state automaton based pipeline hazard recognizer and -+ instruction scheduler in GCC. V. Makarov. Proceedings of GCC -+ summit, 2003. -+ -+ 2. Detecting pipeline structural hazards quickly. T. Proebsting, - C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on - Principles of Programming Languages, pages 280--286, 1994. - - This article is a good start point to understand usage of finite - state automata for pipeline hazard recognizers. But I'd -- recommend the 2nd article for more deep understanding. -+ recommend the 1st and 3rd article for more deep understanding. - -- 2. Efficient Instruction Scheduling Using Finite State Automata: -+ 3. Efficient Instruction Scheduling Using Finite State Automata: - V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best - article about usage of finite state automata for pipeline hazard - recognizers. - -- The current implementation is different from the 2nd article in the -- following: -+ The current implementation is described in the 1st article and it -+ is different from the 3rd article in the following: - - 1. New operator `|' (alternative) is permitted in functional unit - reservation which can be treated deterministically and -@@ -463,7 +467,10 @@ - insn. */ - int insn_num; - /* The following field value is list of bypasses in which given insn -- is output insn. */ -+ is output insn. Bypasses with the same input insn stay one after -+ another in the list in the same order as their occurrences in the -+ description but the bypass without a guard stays always the last -+ in a row of bypasses with the same input insn. */ - struct bypass_decl *bypass_list; - - /* The following fields are defined by automaton generator. */ -@@ -2367,18 +2374,67 @@ - } - - --/* The function searches for bypass with given IN_INSN_RESERV in given -- BYPASS_LIST. */ --static struct bypass_decl * --find_bypass (struct bypass_decl *bypass_list, -- struct insn_reserv_decl *in_insn_reserv) --{ -- struct bypass_decl *bypass; -- -- for (bypass = bypass_list; bypass != NULL; bypass = bypass->next) -- if (bypass->in_insn_reserv == in_insn_reserv) -- break; -- return bypass; -+/* The function inserts BYPASS in the list of bypasses of the -+ corresponding output insn. The order of bypasses in the list is -+ decribed in a comment for member `bypass_list' (see above). If -+ there is already the same bypass in the list the function reports -+ this and does nothing. */ -+static void -+insert_bypass (struct bypass_decl *bypass) -+{ -+ struct bypass_decl *curr, *last; -+ struct insn_reserv_decl *out_insn_reserv = bypass->out_insn_reserv; -+ struct insn_reserv_decl *in_insn_reserv = bypass->in_insn_reserv; -+ -+ for (curr = out_insn_reserv->bypass_list, last = NULL; -+ curr != NULL; -+ last = curr, curr = curr->next) -+ if (curr->in_insn_reserv == in_insn_reserv) -+ { -+ if ((bypass->bypass_guard_name != NULL -+ && curr->bypass_guard_name != NULL -+ && ! strcmp (bypass->bypass_guard_name, curr->bypass_guard_name)) -+ || bypass->bypass_guard_name == curr->bypass_guard_name) -+ { -+ if (bypass->bypass_guard_name == NULL) -+ { -+ if (!w_flag) -+ error ("the same bypass `%s - %s' is already defined", -+ bypass->out_insn_name, bypass->in_insn_name); -+ else -+ warning (0, "the same bypass `%s - %s' is already defined", -+ bypass->out_insn_name, bypass->in_insn_name); -+ } -+ else if (!w_flag) -+ error ("the same bypass `%s - %s' (guard %s) is already defined", -+ bypass->out_insn_name, bypass->in_insn_name, -+ bypass->bypass_guard_name); -+ else -+ warning -+ (0, "the same bypass `%s - %s' (guard %s) is already defined", -+ bypass->out_insn_name, bypass->in_insn_name, -+ bypass->bypass_guard_name); -+ return; -+ } -+ if (curr->bypass_guard_name == NULL) -+ break; -+ if (curr->next == NULL || curr->next->in_insn_reserv != in_insn_reserv) -+ { -+ last = curr; -+ break; -+ } -+ -+ } -+ if (last == NULL) -+ { -+ bypass->next = out_insn_reserv->bypass_list; -+ out_insn_reserv->bypass_list = bypass; -+ } -+ else -+ { -+ bypass->next = last->next; -+ last->next = bypass; -+ } - } - - /* The function processes pipeline description declarations, checks -@@ -2391,7 +2447,6 @@ - decl_t decl_in_table; - decl_t out_insn_reserv; - decl_t in_insn_reserv; -- struct bypass_decl *bypass; - int automaton_presence; - int i; - -@@ -2514,36 +2569,7 @@ - = DECL_INSN_RESERV (out_insn_reserv); - DECL_BYPASS (decl)->in_insn_reserv - = DECL_INSN_RESERV (in_insn_reserv); -- bypass -- = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list, -- DECL_BYPASS (decl)->in_insn_reserv); -- if (bypass != NULL) -- { -- if (DECL_BYPASS (decl)->latency == bypass->latency) -- { -- if (!w_flag) -- error -- ("the same bypass `%s - %s' is already defined", -- DECL_BYPASS (decl)->out_insn_name, -- DECL_BYPASS (decl)->in_insn_name); -- else -- warning -- (0, "the same bypass `%s - %s' is already defined", -- DECL_BYPASS (decl)->out_insn_name, -- DECL_BYPASS (decl)->in_insn_name); -- } -- else -- error ("bypass `%s - %s' is already defined", -- DECL_BYPASS (decl)->out_insn_name, -- DECL_BYPASS (decl)->in_insn_name); -- } -- else -- { -- DECL_BYPASS (decl)->next -- = DECL_INSN_RESERV (out_insn_reserv)->bypass_list; -- DECL_INSN_RESERV (out_insn_reserv)->bypass_list -- = DECL_BYPASS (decl); -- } -+ insert_bypass (DECL_BYPASS (decl)); - } - } - } -@@ -8159,19 +8185,32 @@ - (advance_cycle_insn_decl)->insn_num)); - fprintf (output_file, " case %d:\n", - bypass->in_insn_reserv->insn_num); -- if (bypass->bypass_guard_name == NULL) -- fprintf (output_file, " return %d;\n", -- bypass->latency); -- else -+ for (;;) - { -- fprintf (output_file, -- " if (%s (%s, %s))\n", -- bypass->bypass_guard_name, INSN_PARAMETER_NAME, -- INSN2_PARAMETER_NAME); -- fprintf (output_file, -- " return %d;\n break;\n", -- bypass->latency); -+ if (bypass->bypass_guard_name == NULL) -+ { -+ gcc_assert (bypass->next == NULL -+ || (bypass->in_insn_reserv -+ != bypass->next->in_insn_reserv)); -+ fprintf (output_file, " return %d;\n", -+ bypass->latency); -+ } -+ else -+ { -+ fprintf (output_file, -+ " if (%s (%s, %s))\n", -+ bypass->bypass_guard_name, INSN_PARAMETER_NAME, -+ INSN2_PARAMETER_NAME); -+ fprintf (output_file, " return %d;\n", -+ bypass->latency); -+ } -+ if (bypass->next == NULL -+ || bypass->in_insn_reserv != bypass->next->in_insn_reserv) -+ break; -+ bypass = bypass->next; - } -+ if (bypass->bypass_guard_name != NULL) -+ fprintf (output_file, " break;\n"); - } - fputs (" }\n break;\n", output_file); - } ---- a/gcc/gengtype-lex.c -+++ /dev/null -@@ -1,2638 +0,0 @@ --#line 2 "gengtype-lex.c" -- --#line 4 "gengtype-lex.c" -- --#define YY_INT_ALIGNED short int -- --/* A lexical scanner generated by flex */ -- --#define FLEX_SCANNER --#define YY_FLEX_MAJOR_VERSION 2 --#define YY_FLEX_MINOR_VERSION 5 --#define YY_FLEX_SUBMINOR_VERSION 35 --#if YY_FLEX_SUBMINOR_VERSION > 0 --#define FLEX_BETA --#endif -- --/* First, we deal with platform-specific or compiler-specific issues. */ -- --/* begin standard C headers. */ --#include <stdio.h> --#include <string.h> --#include <errno.h> --#include <stdlib.h> -- --/* end standard C headers. */ -- --/* flex integer type definitions */ -- --#ifndef FLEXINT_H --#define FLEXINT_H -- --/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ -- --#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -- --/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, -- * if you want the limit (max/min) macros for int types. -- */ --#ifndef __STDC_LIMIT_MACROS --#define __STDC_LIMIT_MACROS 1 --#endif -- --#include <inttypes.h> --typedef int8_t flex_int8_t; --typedef uint8_t flex_uint8_t; --typedef int16_t flex_int16_t; --typedef uint16_t flex_uint16_t; --typedef int32_t flex_int32_t; --typedef uint32_t flex_uint32_t; --#else --typedef signed char flex_int8_t; --typedef short int flex_int16_t; --typedef int flex_int32_t; --typedef unsigned char flex_uint8_t; --typedef unsigned short int flex_uint16_t; --typedef unsigned int flex_uint32_t; --#endif /* ! C99 */ -- --/* Limits of integral types. */ --#ifndef INT8_MIN --#define INT8_MIN (-128) --#endif --#ifndef INT16_MIN --#define INT16_MIN (-32767-1) --#endif --#ifndef INT32_MIN --#define INT32_MIN (-2147483647-1) --#endif --#ifndef INT8_MAX --#define INT8_MAX (127) --#endif --#ifndef INT16_MAX --#define INT16_MAX (32767) --#endif --#ifndef INT32_MAX --#define INT32_MAX (2147483647) --#endif --#ifndef UINT8_MAX --#define UINT8_MAX (255U) --#endif --#ifndef UINT16_MAX --#define UINT16_MAX (65535U) --#endif --#ifndef UINT32_MAX --#define UINT32_MAX (4294967295U) --#endif -- --#endif /* ! FLEXINT_H */ -- --#ifdef __cplusplus -- --/* The "const" storage-class-modifier is valid. */ --#define YY_USE_CONST -- --#else /* ! __cplusplus */ -- --/* C99 requires __STDC__ to be defined as 1. */ --#if defined (__STDC__) -- --#define YY_USE_CONST -- --#endif /* defined (__STDC__) */ --#endif /* ! __cplusplus */ -- --#ifdef YY_USE_CONST --#define yyconst const --#else --#define yyconst --#endif -- --/* Returned upon end-of-file. */ --#define YY_NULL 0 -- --/* Promotes a possibly negative, possibly signed char to an unsigned -- * integer for use as an array index. If the signed char is negative, -- * we want to instead treat it as an 8-bit unsigned char, hence the -- * double cast. -- */ --#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) -- --/* Enter a start condition. This macro really ought to take a parameter, -- * but we do it the disgusting crufty way forced on us by the ()-less -- * definition of BEGIN. -- */ --#define BEGIN (yy_start) = 1 + 2 * -- --/* Translate the current start state into a value that can be later handed -- * to BEGIN to return to the state. The YYSTATE alias is for lex -- * compatibility. -- */ --#define YY_START (((yy_start) - 1) / 2) --#define YYSTATE YY_START -- --/* Action number for EOF rule of a given start state. */ --#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) -- --/* Special action meaning "start processing a new file". */ --#define YY_NEW_FILE yyrestart(yyin ) -- --#define YY_END_OF_BUFFER_CHAR 0 -- --/* Size of default input buffer. */ --#ifndef YY_BUF_SIZE --#define YY_BUF_SIZE 16384 --#endif -- --/* The state buf must be large enough to hold one state per character in the main buffer. -- */ --#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) -- --#ifndef YY_TYPEDEF_YY_BUFFER_STATE --#define YY_TYPEDEF_YY_BUFFER_STATE --typedef struct yy_buffer_state *YY_BUFFER_STATE; --#endif -- --extern int yyleng; -- --extern FILE *yyin, *yyout; -- --#define EOB_ACT_CONTINUE_SCAN 0 --#define EOB_ACT_END_OF_FILE 1 --#define EOB_ACT_LAST_MATCH 2 -- -- #define YY_LESS_LINENO(n) -- --/* Return all but the first "n" matched characters back to the input stream. */ --#define yyless(n) \ -- do \ -- { \ -- /* Undo effects of setting up yytext. */ \ -- int yyless_macro_arg = (n); \ -- YY_LESS_LINENO(yyless_macro_arg);\ -- *yy_cp = (yy_hold_char); \ -- YY_RESTORE_YY_MORE_OFFSET \ -- (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ -- YY_DO_BEFORE_ACTION; /* set up yytext again */ \ -- } \ -- while ( 0 ) -- --#define unput(c) yyunput( c, (yytext_ptr) ) -- --#ifndef YY_TYPEDEF_YY_SIZE_T --#define YY_TYPEDEF_YY_SIZE_T --typedef size_t yy_size_t; --#endif -- --#ifndef YY_STRUCT_YY_BUFFER_STATE --#define YY_STRUCT_YY_BUFFER_STATE --struct yy_buffer_state -- { -- FILE *yy_input_file; -- -- char *yy_ch_buf; /* input buffer */ -- char *yy_buf_pos; /* current position in input buffer */ -- -- /* Size of input buffer in bytes, not including room for EOB -- * characters. -- */ -- yy_size_t yy_buf_size; -- -- /* Number of characters read into yy_ch_buf, not including EOB -- * characters. -- */ -- int yy_n_chars; -- -- /* Whether we "own" the buffer - i.e., we know we created it, -- * and can realloc() it to grow it, and should free() it to -- * delete it. -- */ -- int yy_is_our_buffer; -- -- /* Whether this is an "interactive" input source; if so, and -- * if we're using stdio for input, then we want to use getc() -- * instead of fread(), to make sure we stop fetching input after -- * each newline. -- */ -- int yy_is_interactive; -- -- /* Whether we're considered to be at the beginning of a line. -- * If so, '^' rules will be active on the next match, otherwise -- * not. -- */ -- int yy_at_bol; -- -- int yy_bs_lineno; /**< The line count. */ -- int yy_bs_column; /**< The column count. */ -- -- /* Whether to try to fill the input buffer when we reach the -- * end of it. -- */ -- int yy_fill_buffer; -- -- int yy_buffer_status; -- --#define YY_BUFFER_NEW 0 --#define YY_BUFFER_NORMAL 1 -- /* When an EOF's been seen but there's still some text to process -- * then we mark the buffer as YY_EOF_PENDING, to indicate that we -- * shouldn't try reading from the input source any more. We might -- * still have a bunch of tokens to match, though, because of -- * possible backing-up. -- * -- * When we actually see the EOF, we change the status to "new" -- * (via yyrestart()), so that the user can continue scanning by -- * just pointing yyin at a new input file. -- */ --#define YY_BUFFER_EOF_PENDING 2 -- -- }; --#endif /* !YY_STRUCT_YY_BUFFER_STATE */ -- --/* Stack of input buffers. */ --static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ --static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ --static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ -- --/* We provide macros for accessing buffer states in case in the -- * future we want to put the buffer states in a more general -- * "scanner state". -- * -- * Returns the top of the stack, or NULL. -- */ --#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ -- ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ -- : NULL) -- --/* Same as previous macro, but useful when we know that the buffer stack is not -- * NULL or when we need an lvalue. For internal use only. -- */ --#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] -- --/* yy_hold_char holds the character lost when yytext is formed. */ --static char yy_hold_char; --static int yy_n_chars; /* number of characters read into yy_ch_buf */ --int yyleng; -- --/* Points to current character in buffer. */ --static char *yy_c_buf_p = (char *) 0; --static int yy_init = 0; /* whether we need to initialize */ --static int yy_start = 0; /* start state number */ -- --/* Flag which is used to allow yywrap()'s to do buffer switches -- * instead of setting up a fresh yyin. A bit of a hack ... -- */ --static int yy_did_buffer_switch_on_eof; -- --void yyrestart (FILE *input_file ); --void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); --YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); --void yy_delete_buffer (YY_BUFFER_STATE b ); --void yy_flush_buffer (YY_BUFFER_STATE b ); --void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); --void yypop_buffer_state (void ); -- --static void yyensure_buffer_stack (void ); --static void yy_load_buffer_state (void ); --static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); -- --#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) -- --YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); --YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); --YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); -- --void *yyalloc (yy_size_t ); --void *yyrealloc (void *,yy_size_t ); --void yyfree (void * ); -- --#define yy_new_buffer yy_create_buffer -- --#define yy_set_interactive(is_interactive) \ -- { \ -- if ( ! YY_CURRENT_BUFFER ){ \ -- yyensure_buffer_stack (); \ -- YY_CURRENT_BUFFER_LVALUE = \ -- yy_create_buffer(yyin,YY_BUF_SIZE ); \ -- } \ -- YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ -- } -- --#define yy_set_bol(at_bol) \ -- { \ -- if ( ! YY_CURRENT_BUFFER ){\ -- yyensure_buffer_stack (); \ -- YY_CURRENT_BUFFER_LVALUE = \ -- yy_create_buffer(yyin,YY_BUF_SIZE ); \ -- } \ -- YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ -- } -- --#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) -- --/* Begin user sect3 */ -- --#define yywrap(n) 1 --#define YY_SKIP_YYWRAP -- --typedef unsigned char YY_CHAR; -- --FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; -- --typedef int yy_state_type; -- --extern int yylineno; -- --int yylineno = 1; -- --extern char *yytext; --#define yytext_ptr yytext -- --static yy_state_type yy_get_previous_state (void ); --static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); --static int yy_get_next_buffer (void ); --static void yy_fatal_error (yyconst char msg[] ); -- --/* Done after the current pattern has been matched and before the -- * corresponding action - sets up yytext. -- */ --#define YY_DO_BEFORE_ACTION \ -- (yytext_ptr) = yy_bp; \ -- yyleng = (size_t) (yy_cp - yy_bp); \ -- (yy_hold_char) = *yy_cp; \ -- *yy_cp = '\0'; \ -- (yy_c_buf_p) = yy_cp; -- --#define YY_NUM_RULES 49 --#define YY_END_OF_BUFFER 50 --/* This struct is not used in this scanner, -- but its presence is necessary. */ --struct yy_trans_info -- { -- flex_int32_t yy_verify; -- flex_int32_t yy_nxt; -- }; --static yyconst flex_int16_t yy_accept[445] = -- { 0, -- 0, 0, 0, 0, 0, 0, 0, 0, 50, 36, -- 36, 33, 45, 36, 45, 34, 36, 36, 34, 34, -- 34, 34, 34, 31, 10, 10, 31, 29, 31, 31, -- 31, 20, 31, 31, 31, 31, 31, 31, 31, 31, -- 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, -- 31, 10, 31, 41, 39, 46, 46, 0, 0, 0, -- 37, 0, 0, 0, 38, 32, 34, 0, 0, 0, -- 0, 0, 0, 0, 0, 0, 34, 34, 34, 34, -- 34, 10, 0, 25, 0, 0, 0, 0, 9, 20, -- 24, 0, 0, 0, 0, 0, 0, 0, 0, 26, -- -- 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, -- 42, 44, 43, 0, 35, 0, 0, 0, 0, 0, -- 0, 34, 34, 34, 34, 34, 34, 27, 28, 0, -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 0, 34, 34, 34, 34, 34, 34, -- 0, 0, 0, 13, 0, 14, 0, 0, 0, 0, -- 22, 22, 0, 0, 0, 0, 0, 0, 0, 0, -- -- 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, -- 0, 34, 34, 34, 34, 34, 34, 0, 0, 0, -- 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, -- 34, 34, 34, 34, 3, 0, 0, 0, 0, 12, -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, -- 0, 0, 0, 0, 34, 4, 5, 2, 34, 0, -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, -- 0, 0, 0, 0, 34, 1, 0, 0, 0, 0, -- 0, 0, 0, 0, 0, 22, 22, 0, 0, 0, -- 0, 0, 0, 0, 0, 0, 0, 34, 34, 34, -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 21, 0, 0, 0, 0, 0, 0, 34, 7, 6, -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, -- 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, -- 0, 0, 19, 0, 0, 47, 34, 0, 0, 0, -- 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, -- -- 0, 0, 0, 0, 0, 0, 34, 0, 24, 24, -- 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, -- 0, 23, 0, 0, 0, 0, 0, 40, 0, 0, -- 0, 0, 0, 0 -- } ; -- --static yyconst flex_int32_t yy_ec[256] = -- { 0, -- 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, -- 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, -- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 1, 2, 1, 4, 5, 1, 6, 1, 7, 8, -- 9, 10, 1, 6, 6, 11, 12, 13, 13, 13, -- 13, 13, 13, 13, 13, 13, 13, 6, 6, 6, -- 6, 6, 1, 1, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 23, 24, 25, 26, 27, 28, -- 23, 29, 30, 31, 32, 33, 34, 23, 35, 23, -- 36, 37, 38, 1, 39, 1, 40, 41, 42, 43, -- -- 44, 45, 46, 47, 48, 49, 49, 50, 51, 52, -- 53, 54, 49, 55, 56, 57, 58, 59, 49, 60, -- 61, 62, 6, 6, 6, 1, 1, 1, 1, 1, -- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- -- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 1, 1, 1, 1, 1 -- } ; -- --static yyconst flex_int32_t yy_meta[63] = -- { 0, -- 1, 2, 3, 1, 1, 1, 1, 1, 4, 5, -- 1, 1, 6, 7, 7, 7, 7, 7, 7, 7, -- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, -- 7, 7, 7, 7, 7, 8, 1, 1, 9, 9, -- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, -- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, -- 9, 9 -- } ; -- --static yyconst flex_int16_t yy_base[483] = -- { 0, -- 0, 38, 96, 12, 12, 13, 15, 16, 1028, 1444, -- 32, 51, 20, 990, 1016, 0, 157, 18, 1007, 964, -- 966, 961, 969, 1444, 25, 27, 27, 1444, 983, 1008, -- 1008, 1004, 215, 253, 5, 32, 29, 974, 45, 962, -- 996, 35, 38, 39, 40, 41, 134, 42, 136, 137, -- 138, 75, 996, 0, 1444, 985, 984, 166, 964, 162, -- 1444, 0, 987, 990, 1444, 1444, 0, 186, 165, 974, -- 931, 933, 928, 936, 168, 943, 967, 928, 140, 930, -- 935, 87, 167, 1444, 979, 974, 977, 968, 1444, 950, -- 1444, 935, 934, 145, 52, 46, 148, 165, 922, 1444, -- -- 1444, 152, 156, 155, 170, 173, 175, 182, 183, 185, -- 211, 214, 222, 218, 221, 269, 957, 956, 291, 0, -- 1444, 1444, 1444, 922, 1444, 937, 898, 195, 900, 905, -- 907, 912, 906, 892, 890, 903, 893, 1444, 1444, 209, -- 254, 251, 353, 248, 391, 354, 350, 351, 340, 355, -- 341, 429, 339, 356, 344, 347, 360, 390, 43, 361, -- 391, 395, 429, 1444, 0, 0, 280, 906, 900, 886, -- 884, 897, 872, 876, 890, 867, 873, 878, 876, 866, -- 381, 348, 382, 1444, 384, 1444, 389, 397, 491, 398, -- 1444, 528, 418, 399, 420, 477, 478, 422, 421, 480, -- -- 479, 0, 449, 1444, 884, 861, 867, 872, 870, 860, -- 859, 892, 857, 866, 850, 862, 586, 493, 496, 494, -- 484, 624, 1444, 0, 878, 876, 876, 834, 839, 841, -- 832, 830, 199, 830, 490, 499, 486, 492, 488, 489, -- 662, 0, 863, 828, 837, 821, 833, 0, 832, 859, -- 700, 738, 776, 829, 1444, 431, 258, 437, 515, 1444, -- 846, 844, 841, 817, 829, 809, 319, 815, 813, 478, -- 809, 512, 528, 520, 525, 814, 1444, 0, 833, 0, -- 0, 0, 803, 551, 808, 1444, 1444, 1444, 852, 383, -- 521, 530, 539, 822, 829, 813, 793, 787, 802, 801, -- -- 556, 793, 783, 785, 792, 787, 523, 545, 535, 1444, -- 0, 795, 0, 561, 585, 1444, 555, 343, 581, 584, -- 794, 811, 792, 773, 772, 1444, 0, 771, 783, 772, -- 764, 552, 890, 558, 0, 623, 778, 784, 928, 966, -- 583, 593, 594, 613, 792, 792, 771, 761, 746, 591, -- 1444, 1004, 0, 778, 0, 0, 766, 776, 1444, 1444, -- 620, 621, 626, 627, 653, 777, 769, 775, 1042, 1444, -- 0, 772, 787, 767, 556, 577, 615, 649, 629, 762, -- 753, 774, 1444, 0, 763, 1444, 773, 632, 659, 662, -- 656, 654, 754, 742, 753, 0, 754, 729, 665, 688, -- -- 667, 744, 742, 683, 0, 695, 692, 689, 715, 722, -- 699, 711, 701, 666, 673, 0, 705, 1080, 704, 749, -- 751, 753, 756, 663, 658, 618, 593, 0, 0, 1444, -- 758, 1444, 760, 600, 588, 543, 483, 1444, 439, 386, -- 247, 206, 167, 1444, 1118, 1127, 1136, 1145, 1154, 1158, -- 1167, 1176, 1185, 1194, 1202, 1211, 1220, 1229, 1238, 1247, -- 1256, 1265, 1273, 1282, 1290, 1298, 1306, 1314, 1323, 1331, -- 1340, 1349, 1357, 1365, 1374, 1383, 1392, 1400, 1409, 1417, -- 1426, 1435 -- } ; -- --static yyconst flex_int16_t yy_def[483] = -- { 0, -- 445, 445, 444, 3, 446, 446, 446, 446, 444, 444, -- 444, 444, 447, 448, 449, 450, 444, 444, 450, 450, -- 450, 450, 450, 444, 444, 444, 451, 444, 452, 444, -- 444, 444, 453, 453, 34, 34, 34, 34, 34, 454, -- 444, 34, 34, 34, 34, 34, 34, 34, 34, 34, -- 34, 444, 455, 456, 444, 457, 457, 444, 444, 447, -- 444, 447, 444, 448, 444, 444, 450, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 450, 450, 450, 450, -- 450, 444, 451, 444, 451, 444, 452, 444, 444, 444, -- 444, 34, 34, 34, 34, 34, 34, 34, 454, 444, -- -- 444, 34, 34, 34, 34, 34, 34, 34, 34, 34, -- 34, 34, 34, 34, 34, 444, 455, 455, 444, 458, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- 444, 450, 450, 450, 450, 450, 450, 444, 444, 34, -- 34, 34, 453, 34, 453, 34, 34, 34, 34, 34, -- 34, 453, 34, 34, 34, 34, 34, 34, 34, 34, -- 34, 34, 119, 444, 119, 459, 444, 444, 444, 444, -- 444, 444, 444, 444, 450, 450, 450, 450, 450, 450, -- 34, 34, 34, 444, 34, 444, 34, 34, 453, 34, -- 444, 444, 34, 34, 34, 34, 34, 34, 34, 34, -- -- 34, 460, 444, 444, 444, 444, 444, 444, 444, 444, -- 444, 450, 450, 450, 450, 450, 450, 34, 34, 34, -- 34, 453, 444, 192, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 34, 34, 34, 34, 34, 34, -- 453, 461, 444, 444, 444, 444, 444, 462, 444, 450, -- 450, 450, 450, 450, 444, 34, 34, 34, 34, 444, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- 444, 34, 34, 34, 34, 453, 444, 463, 444, 464, -- 465, 466, 444, 444, 450, 444, 444, 444, 450, 34, -- 34, 34, 34, 444, 444, 444, 444, 444, 444, 444, -- -- 467, 444, 444, 444, 444, 444, 34, 34, 34, 444, -- 468, 444, 469, 444, 450, 444, 34, 34, 34, 34, -- 444, 444, 444, 444, 444, 444, 192, 444, 444, 444, -- 444, 34, 453, 34, 470, 444, 444, 450, 450, 450, -- 34, 34, 34, 34, 444, 444, 444, 444, 444, 34, -- 444, 453, 471, 444, 472, 473, 444, 450, 444, 444, -- 34, 34, 34, 34, 34, 444, 444, 444, 453, 444, -- 474, 444, 444, 450, 34, 34, 34, 34, 34, 444, -- 444, 444, 444, 475, 444, 444, 450, 34, 34, 34, -- 34, 34, 444, 444, 444, 476, 444, 450, 34, 34, -- -- 34, 444, 444, 444, 477, 444, 450, 34, 444, 478, -- 34, 444, 444, 444, 444, 479, 444, 450, 34, 444, -- 478, 478, 480, 444, 444, 444, 444, 481, 482, 444, -- 444, 444, 480, 444, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 0, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- 444, 444 -- } ; -- --static yyconst flex_int16_t yy_nxt[1507] = -- { 0, -- 10, 11, 12, 13, 10, 10, 14, 10, 10, 10, -- 10, 15, 10, 52, 55, 55, 53, 55, 55, 75, -- 444, 56, 56, 61, 57, 57, 82, 82, 82, 82, -- 84, 92, 94, 58, 58, 10, 10, 10, 10, 17, -- 12, 13, 18, 10, 14, 10, 10, 10, 10, 15, -- 10, 59, 58, 58, 19, 92, 62, 95, 92, 96, -- 76, 92, 98, 85, 92, 92, 92, 92, 92, 92, -- 59, 92, 92, 10, 10, 10, 116, 82, 92, 117, -- 143, 20, 105, 142, 103, 109, 198, 102, 82, 82, -- 104, 106, 107, 21, 22, 23, 24, 25, 26, 27, -- -- 24, 28, 29, 28, 28, 28, 30, 31, 32, 33, -- 34, 35, 33, 36, 33, 37, 38, 33, 33, 33, -- 33, 33, 33, 33, 33, 33, 33, 33, 39, 33, -- 33, 40, 41, 24, 33, 33, 42, 43, 44, 45, -- 33, 33, 33, 46, 33, 47, 33, 48, 33, 49, -- 33, 50, 33, 51, 33, 33, 33, 33, 68, 58, -- 92, 69, 92, 92, 92, 61, 75, 58, 58, 75, -- 84, 92, 141, 70, 92, 110, 59, 144, 92, 134, -- 145, 92, 92, 112, 113, 59, 108, 68, 58, 115, -- 69, 92, 111, 114, 135, 147, 92, 301, 62, 92, -- -- 71, 92, 70, 85, 146, 59, 148, 76, 92, 92, -- 76, 92, 72, 73, 74, 91, 91, 91, 91, 91, -- 91, 91, 91, 91, 91, 91, 91, 151, 149, 71, -- 150, 152, 181, 153, 170, 92, 301, 92, 154, 155, -- 92, 72, 73, 74, 92, 269, 270, 92, 92, 171, -- 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, -- 91, 91, 91, 91, 91, 156, 157, 158, 161, 182, -- 116, 82, 160, 117, 92, 183, 162, 92, 185, 93, -- 92, 203, 203, 159, 92, 443, 291, 204, 91, 91, -- 91, 163, 163, 164, 163, 163, 163, 163, 163, 163, -- -- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, -- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, -- 163, 163, 163, 163, 163, 163, 163, 163, 163, 165, -- 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, -- 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, -- 165, 165, 165, 184, 184, 184, 184, 184, 184, 184, -- 184, 184, 184, 184, 184, 92, 92, 92, 219, 92, -- 92, 300, 342, 92, 92, 301, 92, 92, 188, 190, -- 92, 92, 92, 194, 152, 195, 92, 92, 184, 184, -- 184, 186, 186, 186, 186, 186, 186, 186, 186, 186, -- -- 186, 186, 186, 152, 152, 189, 187, 92, 92, 92, -- 92, 442, 193, 317, 196, 92, 92, 92, 199, 218, -- 220, 92, 221, 92, 92, 92, 186, 186, 186, 191, -- 192, 192, 191, 191, 191, 191, 191, 191, 191, 191, -- 191, 197, 201, 200, 92, 222, 92, 92, 92, 236, -- 203, 203, 290, 152, 152, 441, 204, 92, 292, 237, -- 239, 235, 240, 92, 191, 191, 191, 163, 163, 163, -- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, -- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, -- 163, 223, 223, 223, 223, 223, 223, 223, 223, 223, -- -- 223, 223, 223, 92, 92, 92, 92, 256, 258, 257, -- 92, 273, 92, 301, 92, 92, 92, 259, 92, 92, -- 92, 238, 92, 304, 158, 92, 223, 223, 223, 224, -- 224, 241, 272, 152, 152, 275, 293, 274, 92, 305, -- 273, 92, 225, 226, 152, 276, 92, 92, 227, 92, -- 307, 92, 314, 314, 92, 320, 92, 327, 327, 318, -- 319, 92, 314, 314, 440, 92, 274, 308, 228, 229, -- 230, 92, 309, 341, 334, 231, 332, 232, 92, 388, -- 337, 92, 92, 233, 92, 234, 255, 255, 255, 255, -- 255, 255, 255, 255, 255, 255, 255, 255, 338, 343, -- -- 333, 344, 389, 92, 361, 439, 339, 92, 350, 92, -- 92, 340, 340, 352, 362, 363, 301, 92, 437, 92, -- 92, 255, 255, 255, 260, 260, 260, 260, 260, 260, -- 260, 260, 260, 260, 260, 260, 354, 375, 390, 92, -- 376, 92, 364, 377, 355, 369, 92, 92, 152, 356, -- 356, 365, 92, 92, 392, 92, 436, 378, 92, 260, -- 260, 260, 277, 277, 277, 277, 277, 277, 277, 277, -- 277, 277, 277, 277, 379, 92, 399, 401, 400, 92, -- 92, 408, 92, 435, 152, 92, 434, 391, 92, 409, -- 409, 92, 411, 92, 427, 410, 426, 277, 277, 277, -- -- 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, -- 286, 286, 414, 418, 92, 92, 420, 420, 418, 418, -- 425, 415, 421, 422, 422, 92, 429, 419, 424, 152, -- 92, 429, 429, 417, 152, 286, 286, 286, 287, 287, -- 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, -- 420, 420, 422, 422, 422, 422, 421, 431, 431, 431, -- 431, 431, 431, 413, 432, 412, 432, 407, 432, 406, -- 404, 403, 402, 287, 287, 287, 288, 288, 288, 288, -- 288, 288, 288, 288, 288, 288, 288, 288, 398, 397, -- 395, 394, 393, 387, 386, 385, 382, 381, 380, 374, -- -- 373, 372, 301, 301, 368, 367, 366, 358, 357, 304, -- 349, 288, 288, 288, 310, 310, 310, 310, 310, 310, -- 310, 310, 310, 310, 310, 310, 348, 301, 301, 301, -- 347, 346, 345, 336, 331, 330, 329, 328, 301, 325, -- 324, 301, 301, 323, 322, 321, 315, 313, 312, 310, -- 310, 310, 316, 316, 316, 316, 316, 316, 316, 316, -- 316, 316, 316, 316, 306, 303, 302, 299, 298, 297, -- 296, 295, 294, 289, 285, 284, 283, 282, 281, 280, -- 279, 271, 268, 267, 266, 265, 264, 316, 316, 316, -- 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, -- -- 351, 351, 263, 262, 261, 254, 253, 252, 251, 250, -- 249, 248, 247, 246, 245, 244, 243, 217, 216, 215, -- 214, 213, 212, 211, 210, 351, 351, 351, 359, 359, -- 359, 359, 359, 359, 359, 359, 359, 359, 359, 359, -- 209, 208, 207, 206, 205, 180, 179, 178, 177, 176, -- 175, 174, 173, 172, 169, 168, 167, 118, 118, 100, -- 140, 92, 90, 359, 359, 359, 360, 360, 360, 360, -- 360, 360, 360, 360, 360, 360, 360, 360, 139, 444, -- 138, 444, 137, 136, 133, 132, 131, 130, 129, 128, -- 127, 126, 444, 125, 124, 123, 122, 118, 101, 100, -- -- 97, 360, 360, 360, 370, 370, 370, 370, 370, 370, -- 370, 370, 370, 370, 370, 370, 90, 89, 88, 87, -- 81, 80, 79, 78, 77, 66, 64, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 370, -- 370, 370, 383, 383, 383, 383, 383, 383, 383, 383, -- 383, 383, 383, 383, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 444, 383, 383, 383, -- 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, -- 430, 430, 444, 444, 444, 444, 444, 444, 444, 444, -- -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 444, 430, 430, 430, 16, 16, -- 16, 16, 16, 16, 16, 16, 16, 54, 54, 54, -- 54, 54, 54, 54, 54, 54, 60, 60, 60, 60, -- 60, 60, 60, 60, 60, 63, 63, 63, 63, 63, -- 63, 63, 63, 63, 65, 65, 65, 65, 65, 65, -- 65, 65, 65, 67, 67, 444, 67, 83, 83, 83, -- 83, 83, 83, 83, 83, 83, 86, 86, 86, 86, -- 86, 86, 86, 86, 86, 92, 92, 92, 92, 92, -- 92, 92, 92, 92, 99, 99, 99, 99, 99, 99, -- -- 99, 444, 99, 119, 444, 444, 444, 444, 444, 444, -- 119, 120, 120, 444, 120, 444, 120, 120, 120, 120, -- 121, 121, 121, 121, 121, 121, 121, 121, 121, 166, -- 166, 444, 166, 444, 166, 166, 166, 166, 202, 202, -- 444, 202, 444, 202, 202, 202, 202, 242, 242, 444, -- 242, 444, 242, 242, 242, 242, 278, 278, 444, 278, -- 444, 278, 278, 278, 278, 255, 255, 255, 255, 255, -- 444, 444, 255, 311, 311, 444, 311, 444, 311, 311, -- 311, 311, 286, 286, 286, 286, 286, 444, 444, 286, -- 287, 287, 287, 287, 287, 444, 444, 287, 288, 288, -- -- 288, 288, 288, 444, 444, 288, 326, 326, 326, 326, -- 326, 444, 444, 326, 335, 335, 444, 335, 444, 335, -- 335, 335, 335, 316, 316, 316, 316, 316, 444, 444, -- 316, 353, 353, 444, 353, 444, 353, 353, 353, 353, -- 371, 371, 444, 371, 444, 371, 371, 371, 371, 359, -- 359, 359, 359, 359, 444, 444, 359, 360, 360, 360, -- 360, 360, 444, 444, 360, 384, 384, 444, 384, 444, -- 384, 384, 384, 384, 396, 396, 444, 396, 444, 396, -- 396, 396, 396, 405, 405, 444, 405, 444, 405, 405, -- 405, 405, 416, 416, 444, 416, 444, 416, 416, 416, -- -- 416, 423, 423, 444, 444, 444, 423, 444, 423, 428, -- 428, 444, 428, 444, 428, 428, 428, 428, 433, 433, -- 433, 444, 433, 433, 444, 433, 438, 438, 444, 438, -- 444, 438, 438, 438, 438, 430, 430, 430, 430, 430, -- 444, 444, 430, 9, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- -- 444, 444, 444, 444, 444, 444 -- } ; -- --static yyconst flex_int16_t yy_chk[1507] = -- { 0, -- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 1, 1, 1, 4, 5, 6, 4, 7, 8, 18, -- 0, 5, 6, 13, 7, 8, 25, 25, 26, 26, -- 27, 35, 35, 11, 11, 1, 1, 1, 2, 2, -- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -- 2, 11, 12, 12, 2, 37, 13, 36, 36, 37, -- 18, 42, 39, 27, 43, 44, 45, 46, 48, 159, -- 12, 39, 96, 2, 2, 2, 52, 52, 95, 52, -- 96, 2, 44, 95, 43, 48, 159, 42, 82, 82, -- 43, 45, 46, 2, 2, 2, 3, 3, 3, 3, -- -- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -- 3, 3, 3, 3, 3, 3, 3, 3, 17, 17, -- 47, 17, 49, 50, 51, 60, 69, 58, 58, 75, -- 83, 94, 94, 17, 97, 49, 17, 97, 102, 79, -- 98, 104, 103, 50, 50, 58, 47, 68, 68, 51, -- 68, 98, 49, 50, 79, 103, 105, 443, 60, 106, -- -- 17, 107, 68, 83, 102, 68, 104, 69, 108, 109, -- 75, 110, 17, 17, 17, 33, 33, 33, 33, 33, -- 33, 33, 33, 33, 33, 33, 33, 107, 105, 68, -- 106, 107, 140, 108, 128, 140, 442, 111, 109, 110, -- 112, 68, 68, 68, 114, 233, 233, 115, 113, 128, -- 33, 33, 33, 34, 34, 34, 34, 34, 34, 34, -- 34, 34, 34, 34, 34, 111, 112, 113, 115, 141, -- 116, 116, 114, 116, 144, 142, 115, 142, 144, 34, -- 141, 167, 167, 113, 257, 441, 257, 167, 34, 34, -- 34, 119, 119, 119, 119, 119, 119, 119, 119, 119, -- -- 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, -- 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, -- 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, -- 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, -- 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, -- 119, 119, 119, 143, 143, 143, 143, 143, 143, 143, -- 143, 143, 143, 143, 143, 153, 149, 151, 182, 318, -- 155, 267, 318, 156, 182, 267, 147, 148, 149, 151, -- 146, 150, 154, 155, 153, 156, 157, 160, 143, 143, -- 143, 145, 145, 145, 145, 145, 145, 145, 145, 145, -- -- 145, 145, 145, 146, 147, 150, 148, 181, 183, 290, -- 185, 440, 154, 290, 157, 187, 158, 161, 160, 181, -- 183, 162, 185, 188, 190, 194, 145, 145, 145, 152, -- 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, -- 152, 158, 162, 161, 193, 187, 195, 199, 198, 194, -- 203, 203, 256, 188, 190, 439, 203, 256, 258, 195, -- 198, 193, 199, 258, 152, 152, 152, 163, 163, 163, -- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, -- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, -- 163, 189, 189, 189, 189, 189, 189, 189, 189, 189, -- -- 189, 189, 189, 196, 197, 201, 200, 218, 220, 219, -- 221, 236, 237, 437, 239, 240, 235, 221, 238, 218, -- 220, 197, 219, 270, 201, 236, 189, 189, 189, 192, -- 192, 200, 235, 196, 238, 237, 259, 236, 272, 270, -- 273, 259, 192, 192, 239, 240, 274, 291, 192, 307, -- 272, 275, 284, 284, 273, 293, 292, 301, 301, 291, -- 292, 309, 314, 314, 436, 293, 273, 274, 192, 192, -- 192, 308, 275, 317, 309, 192, 307, 192, 332, 375, -- 314, 317, 375, 192, 334, 192, 217, 217, 217, 217, -- 217, 217, 217, 217, 217, 217, 217, 217, 315, 319, -- -- 308, 320, 376, 376, 341, 435, 315, 319, 332, 341, -- 320, 315, 315, 334, 342, 343, 434, 350, 427, 342, -- 343, 217, 217, 217, 222, 222, 222, 222, 222, 222, -- 222, 222, 222, 222, 222, 222, 336, 361, 377, 344, -- 362, 377, 344, 363, 336, 350, 361, 362, 388, 336, -- 336, 344, 363, 364, 379, 379, 426, 364, 388, 222, -- 222, 222, 241, 241, 241, 241, 241, 241, 241, 241, -- 241, 241, 241, 241, 365, 378, 389, 391, 390, 365, -- 392, 399, 391, 425, 392, 389, 424, 378, 390, 400, -- 400, 399, 401, 401, 415, 400, 414, 241, 241, 241, -- -- 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, -- 251, 251, 404, 407, 400, 408, 409, 409, 407, 407, -- 413, 404, 409, 410, 410, 411, 417, 408, 412, 411, -- 419, 417, 417, 406, 419, 251, 251, 251, 252, 252, -- 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, -- 420, 420, 421, 421, 422, 422, 420, 423, 423, 431, -- 431, 433, 433, 403, 423, 402, 431, 398, 433, 397, -- 395, 394, 393, 252, 252, 252, 253, 253, 253, 253, -- 253, 253, 253, 253, 253, 253, 253, 253, 387, 385, -- 382, 381, 380, 374, 373, 372, 368, 367, 366, 358, -- -- 357, 354, 349, 348, 347, 346, 345, 338, 337, 331, -- 330, 253, 253, 253, 276, 276, 276, 276, 276, 276, -- 276, 276, 276, 276, 276, 276, 329, 328, 325, 324, -- 323, 322, 321, 312, 306, 305, 304, 303, 302, 300, -- 299, 298, 297, 296, 295, 294, 285, 283, 279, 276, -- 276, 276, 289, 289, 289, 289, 289, 289, 289, 289, -- 289, 289, 289, 289, 271, 269, 268, 266, 265, 264, -- 263, 262, 261, 254, 250, 249, 247, 246, 245, 244, -- 243, 234, 232, 231, 230, 229, 228, 289, 289, 289, -- 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, -- -- 333, 333, 227, 226, 225, 216, 215, 214, 213, 212, -- 211, 210, 209, 208, 207, 206, 205, 180, 179, 178, -- 177, 176, 175, 174, 173, 333, 333, 333, 339, 339, -- 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, -- 172, 171, 170, 169, 168, 137, 136, 135, 134, 133, -- 132, 131, 130, 129, 127, 126, 124, 118, 117, 99, -- 93, 92, 90, 339, 339, 339, 340, 340, 340, 340, -- 340, 340, 340, 340, 340, 340, 340, 340, 88, 87, -- 86, 85, 81, 80, 78, 77, 76, 74, 73, 72, -- 71, 70, 64, 63, 59, 57, 56, 53, 41, 40, -- -- 38, 340, 340, 340, 352, 352, 352, 352, 352, 352, -- 352, 352, 352, 352, 352, 352, 32, 31, 30, 29, -- 23, 22, 21, 20, 19, 15, 14, 9, 0, 0, -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, -- 352, 352, 369, 369, 369, 369, 369, 369, 369, 369, -- 369, 369, 369, 369, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 0, 0, 0, 0, 369, 369, 369, -- 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, -- 418, 418, 0, 0, 0, 0, 0, 0, 0, 0, -- -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 0, 0, 418, 418, 418, 445, 445, -- 445, 445, 445, 445, 445, 445, 445, 446, 446, 446, -- 446, 446, 446, 446, 446, 446, 447, 447, 447, 447, -- 447, 447, 447, 447, 447, 448, 448, 448, 448, 448, -- 448, 448, 448, 448, 449, 449, 449, 449, 449, 449, -- 449, 449, 449, 450, 450, 0, 450, 451, 451, 451, -- 451, 451, 451, 451, 451, 451, 452, 452, 452, 452, -- 452, 452, 452, 452, 452, 453, 453, 453, 453, 453, -- 453, 453, 453, 453, 454, 454, 454, 454, 454, 454, -- -- 454, 0, 454, 455, 0, 0, 0, 0, 0, 0, -- 455, 456, 456, 0, 456, 0, 456, 456, 456, 456, -- 457, 457, 457, 457, 457, 457, 457, 457, 457, 458, -- 458, 0, 458, 0, 458, 458, 458, 458, 459, 459, -- 0, 459, 0, 459, 459, 459, 459, 460, 460, 0, -- 460, 0, 460, 460, 460, 460, 461, 461, 0, 461, -- 0, 461, 461, 461, 461, 462, 462, 462, 462, 462, -- 0, 0, 462, 463, 463, 0, 463, 0, 463, 463, -- 463, 463, 464, 464, 464, 464, 464, 0, 0, 464, -- 465, 465, 465, 465, 465, 0, 0, 465, 466, 466, -- -- 466, 466, 466, 0, 0, 466, 467, 467, 467, 467, -- 467, 0, 0, 467, 468, 468, 0, 468, 0, 468, -- 468, 468, 468, 469, 469, 469, 469, 469, 0, 0, -- 469, 470, 470, 0, 470, 0, 470, 470, 470, 470, -- 471, 471, 0, 471, 0, 471, 471, 471, 471, 472, -- 472, 472, 472, 472, 0, 0, 472, 473, 473, 473, -- 473, 473, 0, 0, 473, 474, 474, 0, 474, 0, -- 474, 474, 474, 474, 475, 475, 0, 475, 0, 475, -- 475, 475, 475, 476, 476, 0, 476, 0, 476, 476, -- 476, 476, 477, 477, 0, 477, 0, 477, 477, 477, -- -- 477, 478, 478, 0, 0, 0, 478, 0, 478, 479, -- 479, 0, 479, 0, 479, 479, 479, 479, 480, 480, -- 480, 0, 480, 480, 0, 480, 481, 481, 0, 481, -- 0, 481, 481, 481, 481, 482, 482, 482, 482, 482, -- 0, 0, 482, 444, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- 444, 444, 444, 444, 444, 444, 444, 444, 444, 444, -- -- 444, 444, 444, 444, 444, 444 -- } ; -- --static yy_state_type yy_last_accepting_state; --static char *yy_last_accepting_cpos; -- --extern int yy_flex_debug; --int yy_flex_debug = 0; -- --/* The intent behind this definition is that it'll catch -- * any uses of REJECT which flex missed. -- */ --#define REJECT reject_used_but_not_detected --#define yymore() yymore_used_but_not_detected --#define YY_MORE_ADJ 0 --#define YY_RESTORE_YY_MORE_OFFSET --char *yytext; --#line 1 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --/* -*- indented-text -*- */ --/* Process source files and output type information. -- Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009 -- Free Software Foundation, Inc. -- --This file is part of GCC. -- --GCC is free software; you can redistribute it and/or modify it under --the terms of the GNU General Public License as published by the Free --Software Foundation; either version 3, or (at your option) any later --version. -- --GCC is distributed in the hope that it will be useful, but WITHOUT ANY --WARRANTY; without even the implied warranty of MERCHANTABILITY or --FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --for more details. -- --You should have received a copy of the GNU General Public License --along with GCC; see the file COPYING3. If not see --<http://www.gnu.org/licenses/>. */ --#line 23 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --#include "bconfig.h" --#include "system.h" -- --#define malloc xmalloc --#define realloc xrealloc -- --#include "gengtype.h" -- --#define YY_NO_INPUT --#define YY_DECL int yylex (const char **yylval) --#define yyterminate() return EOF_TOKEN -- --struct fileloc lexer_line; --int lexer_toplevel_done; -- --static void --update_lineno (const char *l, size_t len) --{ -- while (len-- > 0) -- if (*l++ == '\n') -- lexer_line.line++; --} -- -- --#line 986 "gengtype-lex.c" -- --#define INITIAL 0 --#define in_struct 1 --#define in_struct_comment 2 --#define in_comment 3 -- --#ifndef YY_NO_UNISTD_H --/* Special case for "unistd.h", since it is non-ANSI. We include it way -- * down here because we want the user's section 1 to have been scanned first. -- * The user has a chance to override it with an option. -- */ --#include <unistd.h> --#endif -- --#ifndef YY_EXTRA_TYPE --#define YY_EXTRA_TYPE void * --#endif -- --static int yy_init_globals (void ); -- --/* Accessor methods to globals. -- These are made visible to non-reentrant scanners for convenience. */ -- --int yylex_destroy (void ); -- --int yyget_debug (void ); -- --void yyset_debug (int debug_flag ); -- --YY_EXTRA_TYPE yyget_extra (void ); -- --void yyset_extra (YY_EXTRA_TYPE user_defined ); -- --FILE *yyget_in (void ); -- --void yyset_in (FILE * in_str ); -- --FILE *yyget_out (void ); -- --void yyset_out (FILE * out_str ); -- --int yyget_leng (void ); -- --char *yyget_text (void ); -- --int yyget_lineno (void ); -- --void yyset_lineno (int line_number ); -- --/* Macros after this point can all be overridden by user definitions in -- * section 1. -- */ -- --#ifndef YY_SKIP_YYWRAP --#ifdef __cplusplus --extern "C" int yywrap (void ); --#else --extern int yywrap (void ); --#endif --#endif -- --#ifndef yytext_ptr --static void yy_flex_strncpy (char *,yyconst char *,int ); --#endif -- --#ifdef YY_NEED_STRLEN --static int yy_flex_strlen (yyconst char * ); --#endif -- --#ifndef YY_NO_INPUT -- --#ifdef __cplusplus --static int yyinput (void ); --#else --static int input (void ); --#endif -- --#endif -- --/* Amount of stuff to slurp up with each read. */ --#ifndef YY_READ_BUF_SIZE --#define YY_READ_BUF_SIZE 8192 --#endif -- --/* Copy whatever the last rule matched to the standard output. */ --#ifndef ECHO --/* This used to be an fputs(), but since the string might contain NUL's, -- * we now use fwrite(). -- */ --#define ECHO fwrite( yytext, yyleng, 1, yyout ) --#endif -- --/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, -- * is returned in "result". -- */ --#ifndef YY_INPUT --#define YY_INPUT(buf,result,max_size) \ -- if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ -- { \ -- int c = '*'; \ -- unsigned n; \ -- for ( n = 0; n < max_size && \ -- (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ -- buf[n] = (char) c; \ -- if ( c == '\n' ) \ -- buf[n++] = (char) c; \ -- if ( c == EOF && ferror( yyin ) ) \ -- YY_FATAL_ERROR( "input in flex scanner failed" ); \ -- result = n; \ -- } \ -- else \ -- { \ -- errno=0; \ -- while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ -- { \ -- if( errno != EINTR) \ -- { \ -- YY_FATAL_ERROR( "input in flex scanner failed" ); \ -- break; \ -- } \ -- errno=0; \ -- clearerr(yyin); \ -- } \ -- }\ --\ -- --#endif -- --/* No semi-colon after return; correct usage is to write "yyterminate();" - -- * we don't want an extra ';' after the "return" because that will cause -- * some compilers to complain about unreachable statements. -- */ --#ifndef yyterminate --#define yyterminate() return YY_NULL --#endif -- --/* Number of entries by which start-condition stack grows. */ --#ifndef YY_START_STACK_INCR --#define YY_START_STACK_INCR 25 --#endif -- --/* Report a fatal error. */ --#ifndef YY_FATAL_ERROR --#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) --#endif -- --/* end tables serialization structures and prototypes */ -- --/* Default declaration of generated scanner - a define so the user can -- * easily add parameters. -- */ --#ifndef YY_DECL --#define YY_DECL_IS_OURS 1 -- --extern int yylex (void); -- --#define YY_DECL int yylex (void) --#endif /* !YY_DECL */ -- --/* Code executed at the beginning of each rule, after yytext and yyleng -- * have been set up. -- */ --#ifndef YY_USER_ACTION --#define YY_USER_ACTION --#endif -- --/* Code executed at the end of each rule. */ --#ifndef YY_BREAK --#define YY_BREAK break; --#endif -- --#define YY_RULE_SETUP \ -- if ( yyleng > 0 ) \ -- YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \ -- (yytext[yyleng - 1] == '\n'); \ -- YY_USER_ACTION -- --/** The main scanner function which does all the work. -- */ --YY_DECL --{ -- register yy_state_type yy_current_state; -- register char *yy_cp, *yy_bp; -- register int yy_act; -- --#line 58 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" -- -- /* Do this on entry to yylex(): */ -- *yylval = 0; -- if (lexer_toplevel_done) -- { -- BEGIN(INITIAL); -- lexer_toplevel_done = 0; -- } -- -- /* Things we look for in skipping mode: */ --#line 1183 "gengtype-lex.c" -- -- if ( !(yy_init) ) -- { -- (yy_init) = 1; -- --#ifdef YY_USER_INIT -- YY_USER_INIT; --#endif -- -- if ( ! (yy_start) ) -- (yy_start) = 1; /* first start state */ -- -- if ( ! yyin ) -- yyin = stdin; -- -- if ( ! yyout ) -- yyout = stdout; -- -- if ( ! YY_CURRENT_BUFFER ) { -- yyensure_buffer_stack (); -- YY_CURRENT_BUFFER_LVALUE = -- yy_create_buffer(yyin,YY_BUF_SIZE ); -- } -- -- yy_load_buffer_state( ); -- } -- -- while ( 1 ) /* loops until end-of-file is reached */ -- { -- yy_cp = (yy_c_buf_p); -- -- /* Support of yytext. */ -- *yy_cp = (yy_hold_char); -- -- /* yy_bp points to the position in yy_ch_buf of the start of -- * the current run. -- */ -- yy_bp = yy_cp; -- -- yy_current_state = (yy_start); -- yy_current_state += YY_AT_BOL(); --yy_match: -- do -- { -- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; -- if ( yy_accept[yy_current_state] ) -- { -- (yy_last_accepting_state) = yy_current_state; -- (yy_last_accepting_cpos) = yy_cp; -- } -- while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) -- { -- yy_current_state = (int) yy_def[yy_current_state]; -- if ( yy_current_state >= 445 ) -- yy_c = yy_meta[(unsigned int) yy_c]; -- } -- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; -- ++yy_cp; -- } -- while ( yy_current_state != 444 ); -- yy_cp = (yy_last_accepting_cpos); -- yy_current_state = (yy_last_accepting_state); -- --yy_find_action: -- yy_act = yy_accept[yy_current_state]; -- -- YY_DO_BEFORE_ACTION; -- --do_action: /* This label is used only to access EOF actions. */ -- -- switch ( yy_act ) -- { /* beginning of action switch */ -- case 0: /* must back up */ -- /* undo the effects of YY_DO_BEFORE_ACTION */ -- *yy_cp = (yy_hold_char); -- yy_cp = (yy_last_accepting_cpos); -- yy_current_state = (yy_last_accepting_state); -- goto yy_find_action; -- --case 1: --/* rule 1 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp -= 1; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 69 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- BEGIN(in_struct); -- return TYPEDEF; --} -- YY_BREAK --case 2: --/* rule 2 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp -= 1; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 73 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- BEGIN(in_struct); -- return STRUCT; --} -- YY_BREAK --case 3: --/* rule 3 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp -= 1; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 77 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- BEGIN(in_struct); -- return UNION; --} -- YY_BREAK --case 4: --/* rule 4 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp -= 1; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 81 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- BEGIN(in_struct); -- return EXTERN; --} -- YY_BREAK --case 5: --/* rule 5 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp -= 1; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 85 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- BEGIN(in_struct); -- return STATIC; --} -- YY_BREAK --case 6: --/* rule 6 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp -= 1; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 90 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- BEGIN(in_struct); -- return DEFVEC_OP; --} -- YY_BREAK --case 7: --/* rule 7 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp -= 1; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 94 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- BEGIN(in_struct); -- return DEFVEC_I; --} -- YY_BREAK --case 8: --/* rule 8 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp -= 1; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 98 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- BEGIN(in_struct); -- return DEFVEC_ALLOC; --} -- YY_BREAK -- -- --case 9: --YY_RULE_SETUP --#line 106 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ BEGIN(in_struct_comment); } -- YY_BREAK --case 10: --/* rule 10 can match eol */ --YY_RULE_SETUP --#line 108 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ update_lineno (yytext, yyleng); } -- YY_BREAK --case 11: --/* rule 11 can match eol */ --YY_RULE_SETUP --#line 109 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ lexer_line.line++; } -- YY_BREAK --case 12: --/* rule 12 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp = yy_bp + 5; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 111 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --/* don't care */ -- YY_BREAK --case 13: --/* rule 13 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp = yy_bp + 3; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 112 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ return GTY_TOKEN; } -- YY_BREAK --case 14: --/* rule 14 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp = yy_bp + 3; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 113 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ return VEC_TOKEN; } -- YY_BREAK --case 15: --/* rule 15 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp = yy_bp + 5; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 114 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ return UNION; } -- YY_BREAK --case 16: --/* rule 16 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp = yy_bp + 6; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 115 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ return STRUCT; } -- YY_BREAK --case 17: --/* rule 17 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp = yy_bp + 4; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 116 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ return ENUM; } -- YY_BREAK --case 18: --/* rule 18 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp = yy_bp + 9; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 117 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ return PTR_ALIAS; } -- YY_BREAK --case 19: --/* rule 19 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp = yy_bp + 10; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 118 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ return NESTED_PTR; } -- YY_BREAK --case 20: --YY_RULE_SETUP --#line 119 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ return NUM; } -- YY_BREAK --case 21: --/* rule 21 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp -= 1; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 120 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- *yylval = XDUPVAR (const char, yytext, yyleng, yyleng+1); -- return PARAM_IS; --} -- YY_BREAK --case 22: --/* rule 22 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp -= 1; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --#line 126 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --case 23: --/* rule 23 can match eol */ --YY_RULE_SETUP --#line 126 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- size_t len; -- -- for (len = yyleng; ISSPACE (yytext[len-1]); len--) -- ; -- -- *yylval = XDUPVAR (const char, yytext, len, len+1); -- update_lineno (yytext, yyleng); -- return SCALAR; --} -- YY_BREAK --case 24: --/* rule 24 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp -= 1; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 138 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- *yylval = XDUPVAR (const char, yytext, yyleng, yyleng+1); -- return ID; --} -- YY_BREAK --case 25: --/* rule 25 can match eol */ --YY_RULE_SETUP --#line 143 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- *yylval = XDUPVAR (const char, yytext+1, yyleng-2, yyleng-1); -- return STRING; --} -- YY_BREAK --/* This "terminal" avoids having to parse integer constant expressions. */ --case 26: --/* rule 26 can match eol */ --YY_RULE_SETUP --#line 148 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- *yylval = XDUPVAR (const char, yytext+1, yyleng-2, yyleng-1); -- return ARRAY; --} -- YY_BREAK --case 27: --/* rule 27 can match eol */ --YY_RULE_SETUP --#line 152 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- *yylval = XDUPVAR (const char, yytext+1, yyleng-2, yyleng); -- return CHAR; --} -- YY_BREAK --case 28: --YY_RULE_SETUP --#line 157 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ return ELLIPSIS; } -- YY_BREAK --case 29: --YY_RULE_SETUP --#line 158 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ return yytext[0]; } -- YY_BREAK --/* ignore pp-directives */ --case 30: --/* rule 30 can match eol */ --YY_RULE_SETUP --#line 161 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{lexer_line.line++;} -- YY_BREAK --case 31: --YY_RULE_SETUP --#line 163 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- error_at_line (&lexer_line, "unexpected character `%s'", yytext); --} -- YY_BREAK -- --case 32: --YY_RULE_SETUP --#line 168 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ BEGIN(in_comment); } -- YY_BREAK --case 33: --/* rule 33 can match eol */ --YY_RULE_SETUP --#line 169 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ lexer_line.line++; } -- YY_BREAK --case 34: --#line 171 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --case 35: --/* rule 35 can match eol */ --#line 172 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --case 36: --/* rule 36 can match eol */ --YY_RULE_SETUP --#line 172 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --/* do nothing */ -- YY_BREAK --case 37: --/* rule 37 can match eol */ --YY_RULE_SETUP --#line 173 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ update_lineno (yytext, yyleng); } -- YY_BREAK --case 38: --/* rule 38 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp = yy_bp + 1; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 174 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --/* do nothing */ -- YY_BREAK -- --case 39: --/* rule 39 can match eol */ --YY_RULE_SETUP --#line 177 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ lexer_line.line++; } -- YY_BREAK --case 40: --#line 179 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --case 41: --YY_RULE_SETUP --#line 179 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --/* do nothing */ -- YY_BREAK --case 42: --/* rule 42 can match eol */ --*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ --(yy_c_buf_p) = yy_cp = yy_bp + 1; --YY_DO_BEFORE_ACTION; /* set up yytext again */ --YY_RULE_SETUP --#line 180 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --/* do nothing */ -- YY_BREAK -- --case 43: --YY_RULE_SETUP --#line 182 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ BEGIN(INITIAL); } -- YY_BREAK --case 44: --YY_RULE_SETUP --#line 183 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ BEGIN(in_struct); } -- YY_BREAK --case 45: --#line 186 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --case 46: --YY_RULE_SETUP --#line 186 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- error_at_line (&lexer_line, -- "unterminated comment or string; unexpected EOF"); --} -- YY_BREAK --case 47: --/* rule 47 can match eol */ --YY_RULE_SETUP --#line 191 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --/* do nothing */ -- YY_BREAK --case 48: --/* rule 48 can match eol */ --YY_RULE_SETUP --#line 192 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --{ -- error_at_line (&lexer_line, "stray GTY marker"); --} -- YY_BREAK --case 49: --YY_RULE_SETUP --#line 196 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" --YY_FATAL_ERROR( "flex scanner jammed" ); -- YY_BREAK --#line 1653 "gengtype-lex.c" --case YY_STATE_EOF(INITIAL): --case YY_STATE_EOF(in_struct): --case YY_STATE_EOF(in_struct_comment): --case YY_STATE_EOF(in_comment): -- yyterminate(); -- -- case YY_END_OF_BUFFER: -- { -- /* Amount of text matched not including the EOB char. */ -- int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; -- -- /* Undo the effects of YY_DO_BEFORE_ACTION. */ -- *yy_cp = (yy_hold_char); -- YY_RESTORE_YY_MORE_OFFSET -- -- if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) -- { -- /* We're scanning a new file or input source. It's -- * possible that this happened because the user -- * just pointed yyin at a new source and called -- * yylex(). If so, then we have to assure -- * consistency between YY_CURRENT_BUFFER and our -- * globals. Here is the right place to do so, because -- * this is the first action (other than possibly a -- * back-up) that will match for the new input source. -- */ -- (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; -- YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; -- YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; -- } -- -- /* Note that here we test for yy_c_buf_p "<=" to the position -- * of the first EOB in the buffer, since yy_c_buf_p will -- * already have been incremented past the NUL character -- * (since all states make transitions on EOB to the -- * end-of-buffer state). Contrast this with the test -- * in input(). -- */ -- if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) -- { /* This was really a NUL. */ -- yy_state_type yy_next_state; -- -- (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; -- -- yy_current_state = yy_get_previous_state( ); -- -- /* Okay, we're now positioned to make the NUL -- * transition. We couldn't have -- * yy_get_previous_state() go ahead and do it -- * for us because it doesn't know how to deal -- * with the possibility of jamming (and we don't -- * want to build jamming into it because then it -- * will run more slowly). -- */ -- -- yy_next_state = yy_try_NUL_trans( yy_current_state ); -- -- yy_bp = (yytext_ptr) + YY_MORE_ADJ; -- -- if ( yy_next_state ) -- { -- /* Consume the NUL. */ -- yy_cp = ++(yy_c_buf_p); -- yy_current_state = yy_next_state; -- goto yy_match; -- } -- -- else -- { -- yy_cp = (yy_last_accepting_cpos); -- yy_current_state = (yy_last_accepting_state); -- goto yy_find_action; -- } -- } -- -- else switch ( yy_get_next_buffer( ) ) -- { -- case EOB_ACT_END_OF_FILE: -- { -- (yy_did_buffer_switch_on_eof) = 0; -- -- if ( yywrap( ) ) -- { -- /* Note: because we've taken care in -- * yy_get_next_buffer() to have set up -- * yytext, we can now set up -- * yy_c_buf_p so that if some total -- * hoser (like flex itself) wants to -- * call the scanner after we return the -- * YY_NULL, it'll still work - another -- * YY_NULL will get returned. -- */ -- (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; -- -- yy_act = YY_STATE_EOF(YY_START); -- goto do_action; -- } -- -- else -- { -- if ( ! (yy_did_buffer_switch_on_eof) ) -- YY_NEW_FILE; -- } -- break; -- } -- -- case EOB_ACT_CONTINUE_SCAN: -- (yy_c_buf_p) = -- (yytext_ptr) + yy_amount_of_matched_text; -- -- yy_current_state = yy_get_previous_state( ); -- -- yy_cp = (yy_c_buf_p); -- yy_bp = (yytext_ptr) + YY_MORE_ADJ; -- goto yy_match; -- -- case EOB_ACT_LAST_MATCH: -- (yy_c_buf_p) = -- &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; -- -- yy_current_state = yy_get_previous_state( ); -- -- yy_cp = (yy_c_buf_p); -- yy_bp = (yytext_ptr) + YY_MORE_ADJ; -- goto yy_find_action; -- } -- break; -- } -- -- default: -- YY_FATAL_ERROR( -- "fatal flex scanner internal error--no action found" ); -- } /* end of action switch */ -- } /* end of scanning one token */ --} /* end of yylex */ -- --/* yy_get_next_buffer - try to read in a new buffer -- * -- * Returns a code representing an action: -- * EOB_ACT_LAST_MATCH - -- * EOB_ACT_CONTINUE_SCAN - continue scanning from current position -- * EOB_ACT_END_OF_FILE - end of file -- */ --static int yy_get_next_buffer (void) --{ -- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; -- register char *source = (yytext_ptr); -- register int number_to_move, i; -- int ret_val; -- -- if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) -- YY_FATAL_ERROR( -- "fatal flex scanner internal error--end of buffer missed" ); -- -- if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) -- { /* Don't try to fill the buffer, so this is an EOF. */ -- if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) -- { -- /* We matched a single character, the EOB, so -- * treat this as a final EOF. -- */ -- return EOB_ACT_END_OF_FILE; -- } -- -- else -- { -- /* We matched some text prior to the EOB, first -- * process it. -- */ -- return EOB_ACT_LAST_MATCH; -- } -- } -- -- /* Try to read more data. */ -- -- /* First move last chars to start of buffer. */ -- number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; -- -- for ( i = 0; i < number_to_move; ++i ) -- *(dest++) = *(source++); -- -- if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) -- /* don't do the read, it's not guaranteed to return an EOF, -- * just force an EOF -- */ -- YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; -- -- else -- { -- int num_to_read = -- YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; -- -- while ( num_to_read <= 0 ) -- { /* Not enough room in the buffer - grow it. */ -- -- /* just a shorter name for the current buffer */ -- YY_BUFFER_STATE b = YY_CURRENT_BUFFER; -- -- int yy_c_buf_p_offset = -- (int) ((yy_c_buf_p) - b->yy_ch_buf); -- -- if ( b->yy_is_our_buffer ) -- { -- int new_size = b->yy_buf_size * 2; -- -- if ( new_size <= 0 ) -- b->yy_buf_size += b->yy_buf_size / 8; -- else -- b->yy_buf_size *= 2; -- -- b->yy_ch_buf = (char *) -- /* Include room in for 2 EOB chars. */ -- yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); -- } -- else -- /* Can't grow it, we don't own it. */ -- b->yy_ch_buf = 0; -- -- if ( ! b->yy_ch_buf ) -- YY_FATAL_ERROR( -- "fatal error - scanner input buffer overflow" ); -- -- (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; -- -- num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - -- number_to_move - 1; -- -- } -- -- if ( num_to_read > YY_READ_BUF_SIZE ) -- num_to_read = YY_READ_BUF_SIZE; -- -- /* Read in more data. */ -- YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), -- (yy_n_chars), (size_t) num_to_read ); -- -- YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); -- } -- -- if ( (yy_n_chars) == 0 ) -- { -- if ( number_to_move == YY_MORE_ADJ ) -- { -- ret_val = EOB_ACT_END_OF_FILE; -- yyrestart(yyin ); -- } -- -- else -- { -- ret_val = EOB_ACT_LAST_MATCH; -- YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = -- YY_BUFFER_EOF_PENDING; -- } -- } -- -- else -- ret_val = EOB_ACT_CONTINUE_SCAN; -- -- if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { -- /* Extend the array by 50%, plus the number we really need. */ -- yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); -- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); -- if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) -- YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); -- } -- -- (yy_n_chars) += number_to_move; -- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; -- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; -- -- (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; -- -- return ret_val; --} -- --/* yy_get_previous_state - get the state just before the EOB char was reached */ -- -- static yy_state_type yy_get_previous_state (void) --{ -- register yy_state_type yy_current_state; -- register char *yy_cp; -- -- yy_current_state = (yy_start); -- yy_current_state += YY_AT_BOL(); -- -- for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) -- { -- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); -- if ( yy_accept[yy_current_state] ) -- { -- (yy_last_accepting_state) = yy_current_state; -- (yy_last_accepting_cpos) = yy_cp; -- } -- while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) -- { -- yy_current_state = (int) yy_def[yy_current_state]; -- if ( yy_current_state >= 445 ) -- yy_c = yy_meta[(unsigned int) yy_c]; -- } -- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; -- } -- -- return yy_current_state; --} -- --/* yy_try_NUL_trans - try to make a transition on the NUL character -- * -- * synopsis -- * next_state = yy_try_NUL_trans( current_state ); -- */ -- static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) --{ -- register int yy_is_jam; -- register char *yy_cp = (yy_c_buf_p); -- -- register YY_CHAR yy_c = 1; -- if ( yy_accept[yy_current_state] ) -- { -- (yy_last_accepting_state) = yy_current_state; -- (yy_last_accepting_cpos) = yy_cp; -- } -- while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) -- { -- yy_current_state = (int) yy_def[yy_current_state]; -- if ( yy_current_state >= 445 ) -- yy_c = yy_meta[(unsigned int) yy_c]; -- } -- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; -- yy_is_jam = (yy_current_state == 444); -- -- return yy_is_jam ? 0 : yy_current_state; --} -- --#ifndef YY_NO_INPUT --#ifdef __cplusplus -- static int yyinput (void) --#else -- static int input (void) --#endif -- --{ -- int c; -- -- *(yy_c_buf_p) = (yy_hold_char); -- -- if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) -- { -- /* yy_c_buf_p now points to the character we want to return. -- * If this occurs *before* the EOB characters, then it's a -- * valid NUL; if not, then we've hit the end of the buffer. -- */ -- if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) -- /* This was really a NUL. */ -- *(yy_c_buf_p) = '\0'; -- -- else -- { /* need more input */ -- int offset = (yy_c_buf_p) - (yytext_ptr); -- ++(yy_c_buf_p); -- -- switch ( yy_get_next_buffer( ) ) -- { -- case EOB_ACT_LAST_MATCH: -- /* This happens because yy_g_n_b() -- * sees that we've accumulated a -- * token and flags that we need to -- * try matching the token before -- * proceeding. But for input(), -- * there's no matching to consider. -- * So convert the EOB_ACT_LAST_MATCH -- * to EOB_ACT_END_OF_FILE. -- */ -- -- /* Reset buffer status. */ -- yyrestart(yyin ); -- -- /*FALLTHROUGH*/ -- -- case EOB_ACT_END_OF_FILE: -- { -- if ( yywrap( ) ) -- return EOF; -- -- if ( ! (yy_did_buffer_switch_on_eof) ) -- YY_NEW_FILE; --#ifdef __cplusplus -- return yyinput(); --#else -- return input(); --#endif -- } -- -- case EOB_ACT_CONTINUE_SCAN: -- (yy_c_buf_p) = (yytext_ptr) + offset; -- break; -- } -- } -- } -- -- c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ -- *(yy_c_buf_p) = '\0'; /* preserve yytext */ -- (yy_hold_char) = *++(yy_c_buf_p); -- -- YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n'); -- -- return c; --} --#endif /* ifndef YY_NO_INPUT */ -- --/** Immediately switch to a different input stream. -- * @param input_file A readable stream. -- * -- * @note This function does not reset the start condition to @c INITIAL . -- */ -- void yyrestart (FILE * input_file ) --{ -- -- if ( ! YY_CURRENT_BUFFER ){ -- yyensure_buffer_stack (); -- YY_CURRENT_BUFFER_LVALUE = -- yy_create_buffer(yyin,YY_BUF_SIZE ); -- } -- -- yy_init_buffer(YY_CURRENT_BUFFER,input_file ); -- yy_load_buffer_state( ); --} -- --/** Switch to a different input buffer. -- * @param new_buffer The new input buffer. -- * -- */ -- void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) --{ -- -- /* TODO. We should be able to replace this entire function body -- * with -- * yypop_buffer_state(); -- * yypush_buffer_state(new_buffer); -- */ -- yyensure_buffer_stack (); -- if ( YY_CURRENT_BUFFER == new_buffer ) -- return; -- -- if ( YY_CURRENT_BUFFER ) -- { -- /* Flush out information for old buffer. */ -- *(yy_c_buf_p) = (yy_hold_char); -- YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); -- YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); -- } -- -- YY_CURRENT_BUFFER_LVALUE = new_buffer; -- yy_load_buffer_state( ); -- -- /* We don't actually know whether we did this switch during -- * EOF (yywrap()) processing, but the only time this flag -- * is looked at is after yywrap() is called, so it's safe -- * to go ahead and always set it. -- */ -- (yy_did_buffer_switch_on_eof) = 1; --} -- --static void yy_load_buffer_state (void) --{ -- (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; -- (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; -- yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; -- (yy_hold_char) = *(yy_c_buf_p); --} -- --/** Allocate and initialize an input buffer state. -- * @param file A readable stream. -- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. -- * -- * @return the allocated buffer state. -- */ -- YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) --{ -- YY_BUFFER_STATE b; -- -- b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); -- if ( ! b ) -- YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); -- -- b->yy_buf_size = size; -- -- /* yy_ch_buf has to be 2 characters longer than the size given because -- * we need to put in 2 end-of-buffer characters. -- */ -- b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); -- if ( ! b->yy_ch_buf ) -- YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); -- -- b->yy_is_our_buffer = 1; -- -- yy_init_buffer(b,file ); -- -- return b; --} -- --/** Destroy the buffer. -- * @param b a buffer created with yy_create_buffer() -- * -- */ -- void yy_delete_buffer (YY_BUFFER_STATE b ) --{ -- -- if ( ! b ) -- return; -- -- if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ -- YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; -- -- if ( b->yy_is_our_buffer ) -- yyfree((void *) b->yy_ch_buf ); -- -- yyfree((void *) b ); --} -- --/* Initializes or reinitializes a buffer. -- * This function is sometimes called more than once on the same buffer, -- * such as during a yyrestart() or at EOF. -- */ -- static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) -- --{ -- int oerrno = errno; -- -- yy_flush_buffer(b ); -- -- b->yy_input_file = file; -- b->yy_fill_buffer = 1; -- -- /* If b is the current buffer, then yy_init_buffer was _probably_ -- * called from yyrestart() or through yy_get_next_buffer. -- * In that case, we don't want to reset the lineno or column. -- */ -- if (b != YY_CURRENT_BUFFER){ -- b->yy_bs_lineno = 1; -- b->yy_bs_column = 0; -- } -- -- b->yy_is_interactive = 0; -- -- errno = oerrno; --} -- --/** Discard all buffered characters. On the next scan, YY_INPUT will be called. -- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. -- * -- */ -- void yy_flush_buffer (YY_BUFFER_STATE b ) --{ -- if ( ! b ) -- return; -- -- b->yy_n_chars = 0; -- -- /* We always need two end-of-buffer characters. The first causes -- * a transition to the end-of-buffer state. The second causes -- * a jam in that state. -- */ -- b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; -- b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; -- -- b->yy_buf_pos = &b->yy_ch_buf[0]; -- -- b->yy_at_bol = 1; -- b->yy_buffer_status = YY_BUFFER_NEW; -- -- if ( b == YY_CURRENT_BUFFER ) -- yy_load_buffer_state( ); --} -- --/** Pushes the new state onto the stack. The new state becomes -- * the current state. This function will allocate the stack -- * if necessary. -- * @param new_buffer The new state. -- * -- */ --void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) --{ -- if (new_buffer == NULL) -- return; -- -- yyensure_buffer_stack(); -- -- /* This block is copied from yy_switch_to_buffer. */ -- if ( YY_CURRENT_BUFFER ) -- { -- /* Flush out information for old buffer. */ -- *(yy_c_buf_p) = (yy_hold_char); -- YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); -- YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); -- } -- -- /* Only push if top exists. Otherwise, replace top. */ -- if (YY_CURRENT_BUFFER) -- (yy_buffer_stack_top)++; -- YY_CURRENT_BUFFER_LVALUE = new_buffer; -- -- /* copied from yy_switch_to_buffer. */ -- yy_load_buffer_state( ); -- (yy_did_buffer_switch_on_eof) = 1; --} -- --/** Removes and deletes the top of the stack, if present. -- * The next element becomes the new top. -- * -- */ --void yypop_buffer_state (void) --{ -- if (!YY_CURRENT_BUFFER) -- return; -- -- yy_delete_buffer(YY_CURRENT_BUFFER ); -- YY_CURRENT_BUFFER_LVALUE = NULL; -- if ((yy_buffer_stack_top) > 0) -- --(yy_buffer_stack_top); -- -- if (YY_CURRENT_BUFFER) { -- yy_load_buffer_state( ); -- (yy_did_buffer_switch_on_eof) = 1; -- } --} -- --/* Allocates the stack if it does not exist. -- * Guarantees space for at least one push. -- */ --static void yyensure_buffer_stack (void) --{ -- int num_to_alloc; -- -- if (!(yy_buffer_stack)) { -- -- /* First allocation is just for 2 elements, since we don't know if this -- * scanner will even need a stack. We use 2 instead of 1 to avoid an -- * immediate realloc on the next call. -- */ -- num_to_alloc = 1; -- (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc -- (num_to_alloc * sizeof(struct yy_buffer_state*) -- ); -- if ( ! (yy_buffer_stack) ) -- YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); -- -- memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); -- -- (yy_buffer_stack_max) = num_to_alloc; -- (yy_buffer_stack_top) = 0; -- return; -- } -- -- if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ -- -- /* Increase the buffer to prepare for a possible push. */ -- int grow_size = 8 /* arbitrary grow size */; -- -- num_to_alloc = (yy_buffer_stack_max) + grow_size; -- (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc -- ((yy_buffer_stack), -- num_to_alloc * sizeof(struct yy_buffer_state*) -- ); -- if ( ! (yy_buffer_stack) ) -- YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); -- -- /* zero only the new slots.*/ -- memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); -- (yy_buffer_stack_max) = num_to_alloc; -- } --} -- --/** Setup the input buffer state to scan directly from a user-specified character buffer. -- * @param base the character buffer -- * @param size the size in bytes of the character buffer -- * -- * @return the newly allocated buffer state object. -- */ --YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) --{ -- YY_BUFFER_STATE b; -- -- if ( size < 2 || -- base[size-2] != YY_END_OF_BUFFER_CHAR || -- base[size-1] != YY_END_OF_BUFFER_CHAR ) -- /* They forgot to leave room for the EOB's. */ -- return 0; -- -- b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); -- if ( ! b ) -- YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); -- -- b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ -- b->yy_buf_pos = b->yy_ch_buf = base; -- b->yy_is_our_buffer = 0; -- b->yy_input_file = 0; -- b->yy_n_chars = b->yy_buf_size; -- b->yy_is_interactive = 0; -- b->yy_at_bol = 1; -- b->yy_fill_buffer = 0; -- b->yy_buffer_status = YY_BUFFER_NEW; -- -- yy_switch_to_buffer(b ); -- -- return b; --} -- --/** Setup the input buffer state to scan a string. The next call to yylex() will -- * scan from a @e copy of @a str. -- * @param yystr a NUL-terminated string to scan -- * -- * @return the newly allocated buffer state object. -- * @note If you want to scan bytes that may contain NUL values, then use -- * yy_scan_bytes() instead. -- */ --YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) --{ -- -- return yy_scan_bytes(yystr,strlen(yystr) ); --} -- --/** Setup the input buffer state to scan the given bytes. The next call to yylex() will -- * scan from a @e copy of @a bytes. -- * @param bytes the byte buffer to scan -- * @param len the number of bytes in the buffer pointed to by @a bytes. -- * -- * @return the newly allocated buffer state object. -- */ --YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) --{ -- YY_BUFFER_STATE b; -- char *buf; -- yy_size_t n; -- int i; -- -- /* Get memory for full buffer, including space for trailing EOB's. */ -- n = _yybytes_len + 2; -- buf = (char *) yyalloc(n ); -- if ( ! buf ) -- YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); -- -- for ( i = 0; i < _yybytes_len; ++i ) -- buf[i] = yybytes[i]; -- -- buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; -- -- b = yy_scan_buffer(buf,n ); -- if ( ! b ) -- YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); -- -- /* It's okay to grow etc. this buffer, and we should throw it -- * away when we're done. -- */ -- b->yy_is_our_buffer = 1; -- -- return b; --} -- --#ifndef YY_EXIT_FAILURE --#define YY_EXIT_FAILURE 2 --#endif -- --static void yy_fatal_error (yyconst char* msg ) --{ -- (void) fprintf( stderr, "%s\n", msg ); -- exit( YY_EXIT_FAILURE ); --} -- --/* Redefine yyless() so it works in section 3 code. */ -- --#undef yyless --#define yyless(n) \ -- do \ -- { \ -- /* Undo effects of setting up yytext. */ \ -- int yyless_macro_arg = (n); \ -- YY_LESS_LINENO(yyless_macro_arg);\ -- yytext[yyleng] = (yy_hold_char); \ -- (yy_c_buf_p) = yytext + yyless_macro_arg; \ -- (yy_hold_char) = *(yy_c_buf_p); \ -- *(yy_c_buf_p) = '\0'; \ -- yyleng = yyless_macro_arg; \ -- } \ -- while ( 0 ) -- --/* Accessor methods (get/set functions) to struct members. */ -- --/** Get the current line number. -- * -- */ --int yyget_lineno (void) --{ -- -- return yylineno; --} -- --/** Get the input stream. -- * -- */ --FILE *yyget_in (void) --{ -- return yyin; --} -- --/** Get the output stream. -- * -- */ --FILE *yyget_out (void) --{ -- return yyout; --} -- --/** Get the length of the current token. -- * -- */ --int yyget_leng (void) --{ -- return yyleng; --} -- --/** Get the current token. -- * -- */ -- --char *yyget_text (void) --{ -- return yytext; --} -- --/** Set the current line number. -- * @param line_number -- * -- */ --void yyset_lineno (int line_number ) --{ -- -- yylineno = line_number; --} -- --/** Set the input stream. This does not discard the current -- * input buffer. -- * @param in_str A readable stream. -- * -- * @see yy_switch_to_buffer -- */ --void yyset_in (FILE * in_str ) --{ -- yyin = in_str ; --} -- --void yyset_out (FILE * out_str ) --{ -- yyout = out_str ; --} -- --int yyget_debug (void) --{ -- return yy_flex_debug; --} -- --void yyset_debug (int bdebug ) --{ -- yy_flex_debug = bdebug ; --} -- --static int yy_init_globals (void) --{ -- /* Initialization is the same as for the non-reentrant scanner. -- * This function is called from yylex_destroy(), so don't allocate here. -- */ -- -- (yy_buffer_stack) = 0; -- (yy_buffer_stack_top) = 0; -- (yy_buffer_stack_max) = 0; -- (yy_c_buf_p) = (char *) 0; -- (yy_init) = 0; -- (yy_start) = 0; -- --/* Defined in main.c */ --#ifdef YY_STDINIT -- yyin = stdin; -- yyout = stdout; --#else -- yyin = (FILE *) 0; -- yyout = (FILE *) 0; --#endif -- -- /* For future reference: Set errno on error, since we are called by -- * yylex_init() -- */ -- return 0; --} -- --/* yylex_destroy is for both reentrant and non-reentrant scanners. */ --int yylex_destroy (void) --{ -- -- /* Pop the buffer stack, destroying each element. */ -- while(YY_CURRENT_BUFFER){ -- yy_delete_buffer(YY_CURRENT_BUFFER ); -- YY_CURRENT_BUFFER_LVALUE = NULL; -- yypop_buffer_state(); -- } -- -- /* Destroy the stack itself. */ -- yyfree((yy_buffer_stack) ); -- (yy_buffer_stack) = NULL; -- -- /* Reset the globals. This is important in a non-reentrant scanner so the next time -- * yylex() is called, initialization will occur. */ -- yy_init_globals( ); -- -- return 0; --} -- --/* -- * Internal utility routines. -- */ -- --#ifndef yytext_ptr --static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) --{ -- register int i; -- for ( i = 0; i < n; ++i ) -- s1[i] = s2[i]; --} --#endif -- --#ifdef YY_NEED_STRLEN --static int yy_flex_strlen (yyconst char * s ) --{ -- register int n; -- for ( n = 0; s[n]; ++n ) -- ; -- -- return n; --} --#endif -- --void *yyalloc (yy_size_t size ) --{ -- return (void *) malloc( size ); --} -- --void *yyrealloc (void * ptr, yy_size_t size ) --{ -- /* The cast to (char *) in the following accommodates both -- * implementations that use char* generic pointers, and those -- * that use void* generic pointers. It works with the latter -- * because both ANSI C and C++ allow castless assignment from -- * any pointer type to void*, and deal with argument conversions -- * as though doing an assignment. -- */ -- return (void *) realloc( (char *) ptr, size ); --} -- --void yyfree (void * ptr ) --{ -- free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ --} -- --#define YYTABLES_NAME "yytables" -- --#line 196 "/d/gcc-4.4.1/gcc-4.4.1/gcc/gengtype-lex.l" -- -- -- --void --yybegin (const char *fname) --{ -- yyin = fopen (fname, "r"); -- if (yyin == NULL) -- { -- perror (fname); -- exit (1); -- } -- lexer_line.file = fname; -- lexer_line.line = 1; --} -- --void --yyend (void) --{ -- fclose (yyin); --} -- ---- a/gcc/gengtype-lex.l -+++ b/gcc/gengtype-lex.l -@@ -48,7 +48,7 @@ - ID [[:alpha:]_][[:alnum:]_]* - WS [[:space:]]+ - HWS [ \t\r\v\f]* --IWORD short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD|CPPCHAR_SIGNED_T|ino_t|dev_t -+IWORD short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD|CPPCHAR_SIGNED_T|ino_t|dev_t|HARD_REG_SET - ITYPE {IWORD}({WS}{IWORD})* - EOID [^[:alnum:]_] - ---- a/gcc/haifa-sched.c -+++ b/gcc/haifa-sched.c -@@ -1990,6 +1990,23 @@ - SCHED_GROUP_P (insn) = 0; - } - -+/* Return true if scheduling INSN will finish current clock cycle. */ -+static bool -+insn_finishes_cycle_p (rtx insn) -+{ -+ if (SCHED_GROUP_P (insn)) -+ /* After issuing INSN, rest of the sched_group will be forced to issue -+ in order. Don't make any plans for the rest of cycle. */ -+ return true; -+ -+ /* Finishing the block will, apparently, finish the cycle. */ -+ if (current_sched_info->insn_finishes_block_p -+ && current_sched_info->insn_finishes_block_p (insn)) -+ return true; -+ -+ return false; -+} -+ - /* The following structure describe an entry of the stack of choices. */ - struct choice_entry - { -@@ -2168,7 +2185,10 @@ - delay = state_transition (state, insn); - if (delay < 0) - { -- if (state_dead_lock_p (state)) -+ if (state_dead_lock_p (state) -+ || insn_finishes_cycle_p (insn)) -+ /* We won't issue any more instructions in the next -+ choice_state. */ - top->rest = 0; - else - top->rest--; ---- a/gcc/hooks.c -+++ b/gcc/hooks.c -@@ -335,3 +335,10 @@ - { - return NULL; - } -+ -+/* Generic hook that takes a const_tree and returns NULL_TREE. */ -+tree -+hook_tree_const_tree_null (const_tree t ATTRIBUTE_UNUSED) -+{ -+ return NULL; -+} ---- a/gcc/hooks.h -+++ b/gcc/hooks.h -@@ -64,6 +64,8 @@ - extern int hook_int_size_t_constcharptr_int_0 (size_t, const char *, int); - extern int hook_int_void_no_regs (void); - -+extern tree hook_tree_const_tree_null (const_tree); -+ - extern tree hook_tree_tree_tree_null (tree, tree); - extern tree hook_tree_tree_tree_tree_null (tree, tree, tree); - extern tree hook_tree_tree_tree_tree_3rd_identity (tree, tree, tree); ---- a/gcc/incpath.c -+++ b/gcc/incpath.c -@@ -30,6 +30,8 @@ - #include "intl.h" - #include "incpath.h" - #include "cppdefault.h" -+#include "flags.h" -+#include "toplev.h" - - /* Microsoft Windows does not natively support inodes. - VMS has non-numeric inodes. */ -@@ -353,6 +355,24 @@ - } - fprintf (stderr, _("End of search list.\n")); - } -+ -+#ifdef ENABLE_POISON_SYSTEM_DIRECTORIES -+ if (flag_poison_system_directories) -+ { -+ struct cpp_dir *p; -+ -+ for (p = heads[QUOTE]; p; p = p->next) -+ { -+ if ((!strncmp (p->name, "/usr/include", 12)) -+ || (!strncmp (p->name, "/usr/local/include", 18)) -+ || (!strncmp (p->name, "/usr/X11R6/include", 18))) -+ warning (OPT_Wpoison_system_directories, -+ "include location \"%s\" is unsafe for " -+ "cross-compilation", -+ p->name); -+ } -+ } -+#endif - } - - /* Use given -I paths for #include "..." but not #include <...>, and ---- a/gcc/ira.c -+++ b/gcc/ira.c -@@ -1349,14 +1349,12 @@ - return for_each_rtx (&insn, insn_contains_asm_1, NULL); - } - --/* Set up regs_asm_clobbered. */ -+/* Add register clobbers from asm statements. */ - static void --compute_regs_asm_clobbered (char *regs_asm_clobbered) -+compute_regs_asm_clobbered (void) - { - basic_block bb; - -- memset (regs_asm_clobbered, 0, sizeof (char) * FIRST_PSEUDO_REGISTER); -- - FOR_EACH_BB (bb) - { - rtx insn; -@@ -1377,7 +1375,7 @@ - + hard_regno_nregs[dregno][mode] - 1; - - for (i = dregno; i <= end; ++i) -- regs_asm_clobbered[i] = 1; -+ SET_HARD_REG_BIT(crtl->asm_clobbers, i); - } - } - } -@@ -1415,7 +1413,8 @@ - COPY_HARD_REG_SET (ira_no_alloc_regs, no_unit_alloc_regs); - CLEAR_HARD_REG_SET (eliminable_regset); - -- compute_regs_asm_clobbered (regs_asm_clobbered); -+ compute_regs_asm_clobbered (); -+ - /* Build the regset of all eliminable registers and show we can't - use those that we already know won't be eliminated. */ - #ifdef ELIMINABLE_REGS -@@ -1425,7 +1424,7 @@ - = (! CAN_ELIMINATE (eliminables[i].from, eliminables[i].to) - || (eliminables[i].to == STACK_POINTER_REGNUM && need_fp)); - -- if (! regs_asm_clobbered[eliminables[i].from]) -+ if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, eliminables[i].from)) - { - SET_HARD_REG_BIT (eliminable_regset, eliminables[i].from); - -@@ -1439,7 +1438,7 @@ - df_set_regs_ever_live (eliminables[i].from, true); - } - #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM -- if (! regs_asm_clobbered[HARD_FRAME_POINTER_REGNUM]) -+ if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, HARD_FRAME_POINTER_REGNUM)) - { - SET_HARD_REG_BIT (eliminable_regset, HARD_FRAME_POINTER_REGNUM); - if (need_fp) -@@ -1453,7 +1452,7 @@ - #endif - - #else -- if (! regs_asm_clobbered[FRAME_POINTER_REGNUM]) -+ if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, HARD_FRAME_POINTER_REGNUM)) - { - SET_HARD_REG_BIT (eliminable_regset, FRAME_POINTER_REGNUM); - if (need_fp) ---- a/gcc/ira-costs.c -+++ b/gcc/ira-costs.c -@@ -706,11 +706,11 @@ - - /* Wrapper around REGNO_OK_FOR_INDEX_P, to allow pseudo registers. */ - static inline bool --ok_for_index_p_nonstrict (rtx reg) -+ok_for_index_p_nonstrict (rtx reg, enum machine_mode mode) - { - unsigned regno = REGNO (reg); - -- return regno >= FIRST_PSEUDO_REGISTER || REGNO_OK_FOR_INDEX_P (regno); -+ return regno >= FIRST_PSEUDO_REGISTER || ok_for_index_p_1 (regno, mode); - } - - /* A version of regno_ok_for_base_p for use here, when all -@@ -748,7 +748,7 @@ - enum reg_class rclass; - - if (context == 1) -- rclass = INDEX_REG_CLASS; -+ rclass = index_reg_class (mode); - else - rclass = base_reg_class (mode, outer_code, index_code); - -@@ -795,7 +795,8 @@ - just record registers in any non-constant operands. We - assume here, as well as in the tests below, that all - addresses are in canonical form. */ -- else if (INDEX_REG_CLASS == base_reg_class (VOIDmode, PLUS, SCRATCH)) -+ else if (index_reg_class (mode) -+ == base_reg_class (mode, PLUS, SCRATCH)) - { - record_address_regs (mode, arg0, context, PLUS, code1, scale); - if (! CONSTANT_P (arg1)) -@@ -816,7 +817,7 @@ - else if (code0 == REG && code1 == REG - && REGNO (arg0) < FIRST_PSEUDO_REGISTER - && (ok_for_base_p_nonstrict (arg0, mode, PLUS, REG) -- || ok_for_index_p_nonstrict (arg0))) -+ || ok_for_index_p_nonstrict (arg0, mode))) - record_address_regs (mode, arg1, - ok_for_base_p_nonstrict (arg0, mode, PLUS, REG) - ? 1 : 0, -@@ -824,7 +825,7 @@ - else if (code0 == REG && code1 == REG - && REGNO (arg1) < FIRST_PSEUDO_REGISTER - && (ok_for_base_p_nonstrict (arg1, mode, PLUS, REG) -- || ok_for_index_p_nonstrict (arg1))) -+ || ok_for_index_p_nonstrict (arg1, mode))) - record_address_regs (mode, arg0, - ok_for_base_p_nonstrict (arg1, mode, PLUS, REG) - ? 1 : 0, ---- a/gcc/longlong.h -+++ b/gcc/longlong.h -@@ -982,7 +982,7 @@ - " or r1,%0" \ - : "=r" (q), "=&z" (r) \ - : "1" (n1), "r" (n0), "rm" (d), "r" (&__udiv_qrnnd_16) \ -- : "r1", "r2", "r4", "r5", "r6", "pr"); \ -+ : "r1", "r2", "r4", "r5", "r6", "pr", "t"); \ - } while (0) - - #define UDIV_TIME 80 ---- a/gcc/Makefile.in -+++ b/gcc/Makefile.in -@@ -1249,6 +1249,7 @@ - tree-ssa-loop-manip.o \ - tree-ssa-loop-niter.o \ - tree-ssa-loop-prefetch.o \ -+ tree-ssa-loop-promote.o \ - tree-ssa-loop-unswitch.o \ - tree-ssa-loop.o \ - tree-ssa-math-opts.o \ -@@ -1258,6 +1259,7 @@ - tree-ssa-pre.o \ - tree-ssa-propagate.o \ - tree-ssa-reassoc.o \ -+ tree-ssa-remove-local-statics.o \ - tree-ssa-sccvn.o \ - tree-ssa-sink.o \ - tree-ssa-structalias.o \ -@@ -1674,7 +1676,7 @@ - $(MACHMODE_H) $(FPBIT) $(DPBIT) $(TPBIT) $(LIB2ADD) \ - $(LIB2ADD_ST) $(LIB2ADDEH) $(srcdir)/emutls.c gcov-iov.h $(SFP_MACHINE) - --libgcc.mvars: config.status Makefile $(LIB2ADD) $(LIB2ADD_ST) specs \ -+libgcc.mvars: config.status Makefile $(LIB2ADD) $(LIB2ADD_ST) specs $(tmake_file) \ - xgcc$(exeext) - : > tmp-libgcc.mvars - echo LIB1ASMFUNCS = '$(LIB1ASMFUNCS)' >> tmp-libgcc.mvars -@@ -1728,7 +1730,7 @@ - # driver program needs to select the library directory based on the - # switches. - multilib.h: s-mlib; @true --s-mlib: $(srcdir)/genmultilib Makefile -+s-mlib: $(srcdir)/genmultilib Makefile $(tmakefile) - if test @enable_multilib@ = yes \ - || test -n "$(MULTILIB_OSDIRNAMES)"; then \ - $(SHELL) $(srcdir)/genmultilib \ -@@ -1816,7 +1818,7 @@ - - incpath.o: incpath.c incpath.h $(CONFIG_H) $(SYSTEM_H) $(CPPLIB_H) \ - intl.h prefix.h coretypes.h $(TM_H) cppdefault.h $(TARGET_H) \ -- $(MACHMODE_H) -+ $(MACHMODE_H) $(FLAGS_H) toplev.h - - c-decl.o : c-decl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ - $(RTL_H) $(C_TREE_H) $(GGC_H) $(TARGET_H) $(FLAGS_H) $(FUNCTION_H) output.h \ -@@ -1900,7 +1902,7 @@ - $(TREE_H) $(C_PRAGMA_H) $(FLAGS_H) $(TOPLEV_H) langhooks.h \ - $(TREE_INLINE_H) $(DIAGNOSTIC_H) intl.h debug.h $(C_COMMON_H) \ - opts.h options.h $(MKDEPS_H) incpath.h cppdefault.h $(TARGET_H) \ -- $(TM_P_H) $(VARRAY_H) -+ $(TM_P_H) $(VARRAY_H) $(C_TREE_H) - $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) \ - $< $(OUTPUT_OPTION) @TARGET_SYSTEM_ROOT_DEFINE@ - -@@ -2176,6 +2178,9 @@ - alloc-pool.h $(BASIC_BLOCK_H) $(BITMAP_H) $(HASHTAB_H) $(GIMPLE_H) \ - $(TREE_INLINE_H) tree-iterator.h tree-ssa-sccvn.h $(PARAMS_H) \ - $(DBGCNT_H) -+tree-ssa-remove-local-statics.o: tree-ssa-remove-local-statics.c \ -+ coretypes.h $(CONFIG_H) $(SYSTEM_H) $(BASIC_BLOCK_H) tree.h tree-pass.h \ -+ $(TM_H) $(HASHTAB_H) $(BASIC_BLOCK_H) - tree-ssa-sccvn.o : tree-ssa-sccvn.c $(TREE_FLOW_H) $(CONFIG_H) \ - $(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) $(FIBHEAP_H) \ - $(TM_H) coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H) $(CFGLOOP_H) \ -@@ -2271,6 +2276,12 @@ - $(CFGLOOP_H) $(PARAMS_H) langhooks.h $(BASIC_BLOCK_H) hard-reg-set.h \ - tree-chrec.h $(TOPLEV_H) langhooks.h $(TREE_INLINE_H) $(TREE_DATA_REF_H) \ - $(OPTABS_H) -+tree-ssa-loop-promote.o: tree-ssa-loop-promote.c \ -+ coretypes.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TOPLEV_H) \ -+ $(RTL_H) $(TM_P_H) hard-reg-set.h $(OBSTACK_H) $(BASIC_BLOCK_H) \ -+ pointer-set.h intl.h $(TREE_H) $(GIMPLE_H) $(HASHTAB_H) $(DIAGNOSTIC_H) \ -+ $(TREE_FLOW_H) $(TREE_DUMP_H) $(CFGLOOP_H) $(FLAGS_H) $(TIMEVAR_H) \ -+ tree-pass.h $(TM_H) - tree-predcom.o: tree-predcom.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_P_H) \ - $(CFGLOOP_H) $(TREE_FLOW_H) $(GGC_H) $(TREE_DATA_REF_H) $(SCEV_H) \ - $(PARAMS_H) $(DIAGNOSTIC_H) tree-pass.h $(TM_H) coretypes.h tree-affine.h \ -@@ -2865,7 +2876,7 @@ - $(RTL_H) $(REAL_H) $(FLAGS_H) $(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) \ - hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) $(RECOG_H) output.h \ - $(FUNCTION_H) $(TOPLEV_H) cselib.h $(TM_P_H) except.h $(TREE_H) $(MACHMODE_H) \ -- $(OBSTACK_H) $(TIMEVAR_H) tree-pass.h $(DF_H) $(DBGCNT_H) -+ $(OBSTACK_H) $(TIMEVAR_H) tree-pass.h addresses.h $(DF_H) $(DBGCNT_H) - postreload-gcse.o : postreload-gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ - $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \ - $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h $(TOPLEV_H) \ -@@ -3582,7 +3593,7 @@ - # be rebuilt. - - # Build the include directories. --stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) $(UNWIND_H) fixinc_list -+stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) $(UNWIND_H) - # Copy in the headers provided with gcc. - # The sed command gets just the last file name component; - # this is necessary because VPATH could add a dirname. -@@ -3601,21 +3612,23 @@ - done - rm -f include/unwind.h - cp $(UNWIND_H) include/unwind.h -- set -e; for ml in `cat fixinc_list`; do \ -- sysroot_headers_suffix=`echo $${ml} | sed -e 's/;.*$$//'`; \ -- multi_dir=`echo $${ml} | sed -e 's/^[^;]*;//'`; \ -- fix_dir=include-fixed$${multi_dir}; \ -- if $(LIMITS_H_TEST) ; then \ -- cat $(srcdir)/limitx.h $(srcdir)/glimits.h $(srcdir)/limity.h > tmp-xlimits.h; \ -- else \ -- cat $(srcdir)/glimits.h > tmp-xlimits.h; \ -- fi; \ -- $(mkinstalldirs) $${fix_dir}; \ -- chmod a+rx $${fix_dir} || true; \ -- rm -f $${fix_dir}/limits.h; \ -- mv tmp-xlimits.h $${fix_dir}/limits.h; \ -- chmod a+r $${fix_dir}/limits.h; \ -- done -+ set -e; if [ -f fixinc_list ] ; then \ -+ for ml in `cat fixinc_list`; do \ -+ sysroot_headers_suffix=`echo $${ml} | sed -e 's/;.*$$//'`; \ -+ multi_dir=`echo $${ml} | sed -e 's/^[^;]*;//'`; \ -+ fix_dir=include-fixed$${multi_dir}; \ -+ if $(LIMITS_H_TEST) ; then \ -+ cat $(srcdir)/limitx.h $(srcdir)/glimits.h $(srcdir)/limity.h > tmp-xlimits.h; \ -+ else \ -+ cat $(srcdir)/glimits.h > tmp-xlimits.h; \ -+ fi; \ -+ $(mkinstalldirs) $${fix_dir}; \ -+ chmod a+rx $${fix_dir} || true; \ -+ rm -f $${fix_dir}/limits.h; \ -+ mv tmp-xlimits.h $${fix_dir}/limits.h; \ -+ chmod a+r $${fix_dir}/limits.h; \ -+ done; \ -+ fi - # Install the README - rm -f include-fixed/README - cp $(srcdir)/../fixincludes/README-fixinc include-fixed/README -@@ -4340,16 +4353,18 @@ - - # Install supporting files for fixincludes to be run later. - install-mkheaders: stmp-int-hdrs $(STMP_FIXPROTO) install-itoolsdirs \ -- macro_list fixinc_list -+ macro_list - $(INSTALL_DATA) $(srcdir)/gsyslimits.h \ - $(DESTDIR)$(itoolsdatadir)/gsyslimits.h - $(INSTALL_DATA) macro_list $(DESTDIR)$(itoolsdatadir)/macro_list -- $(INSTALL_DATA) fixinc_list $(DESTDIR)$(itoolsdatadir)/fixinc_list -- set -e; for ml in `cat fixinc_list`; do \ -- multi_dir=`echo $${ml} | sed -e 's/^[^;]*;//'`; \ -- $(mkinstalldirs) $(DESTDIR)$(itoolsdatadir)/include$${multi_dir}; \ -- $(INSTALL_DATA) include-fixed$${multidir}/limits.h $(DESTDIR)$(itoolsdatadir)/include$${multi_dir}/limits.h; \ -- done -+ set -e; if [ -f fixinc_list ] ; then \ -+ $(INSTALL_DATA) fixinc_list $(DESTDIR)$(itoolsdatadir)/fixinc_list; \ -+ for ml in `cat fixinc_list`; do \ -+ multi_dir=`echo $${ml} | sed -e 's/^[^;]*;//'`; \ -+ $(mkinstalldirs) $(DESTDIR)$(itoolsdatadir)/include$${multi_dir}; \ -+ $(INSTALL_DATA) include-fixed$${multidir}/limits.h $(DESTDIR)$(itoolsdatadir)/include$${multi_dir}/limits.h; \ -+ done; \ -+ fi - $(INSTALL_SCRIPT) $(srcdir)/../mkinstalldirs \ - $(DESTDIR)$(itoolsdir)/mkinstalldirs ; \ - if [ x$(STMP_FIXPROTO) != x ] ; then \ ---- a/gcc/modulo-sched.c -+++ b/gcc/modulo-sched.c -@@ -270,6 +270,7 @@ - NULL, - sms_print_insn, - NULL, -+ NULL, /* insn_finishes_block_p */ - NULL, NULL, - NULL, NULL, - 0, 0, ---- a/gcc/optabs.c -+++ b/gcc/optabs.c -@@ -3300,7 +3300,8 @@ - if (unoptab == ffs_optab || unoptab == clz_optab || unoptab == ctz_optab - || unoptab == popcount_optab || unoptab == parity_optab) - outmode -- = GET_MODE (hard_libcall_value (TYPE_MODE (integer_type_node))); -+ = GET_MODE (hard_libcall_value (TYPE_MODE (integer_type_node), -+ optab_libfunc (unoptab, mode))); - - start_sequence (); - -@@ -4357,10 +4358,12 @@ - mode != VOIDmode; - mode = GET_MODE_WIDER_MODE (mode)) - { -- if ((libfunc = optab_libfunc (code_to_optab[comparison], mode))) -+ if (code_to_optab[comparison] -+ && (libfunc = optab_libfunc (code_to_optab[comparison], mode))) - break; - -- if ((libfunc = optab_libfunc (code_to_optab[swapped] , mode))) -+ if (code_to_optab[swapped] -+ && (libfunc = optab_libfunc (code_to_optab[swapped], mode))) - { - rtx tmp; - tmp = x; x = y; y = tmp; -@@ -4368,7 +4371,8 @@ - break; - } - -- if ((libfunc = optab_libfunc (code_to_optab[reversed], mode)) -+ if (code_to_optab[reversed] -+ && (libfunc = optab_libfunc (code_to_optab[reversed], mode)) - && FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, reversed)) - { - comparison = reversed; ---- a/gcc/opts.c -+++ b/gcc/opts.c -@@ -904,7 +904,7 @@ - flag_tree_vrp = opt2; - flag_tree_builtin_call_dce = opt2; - flag_tree_pre = opt2; -- flag_tree_switch_conversion = 1; -+ flag_tree_switch_conversion = opt2; - flag_ipa_cp = opt2; - - /* Allow more virtual operators to increase alias precision. */ -@@ -928,6 +928,7 @@ - flag_gcse_after_reload = opt3; - flag_tree_vectorize = opt3; - flag_ipa_cp_clone = opt3; -+ flag_tree_pre_partial_partial = opt3; - if (flag_ipa_cp_clone) - flag_ipa_cp = 1; - -@@ -951,10 +952,13 @@ - being declared inline. */ - flag_inline_functions = 1; - -- /* Basic optimization options. */ -- optimize_size = 1; -+ /* Basic optimization options at -Os are almost the same as -O2. The -+ only difference is that we disable PRE, because it sometimes still -+ increases code size. If the user want to run PRE with -Os, he/she -+ will have to indicate so explicitly. */ - if (optimize > 2) - optimize = 2; -+ flag_tree_pre = 0; - - /* We want to crossjump as much as possible. */ - set_param_value ("min-crossjump-insns", 1); -@@ -2060,6 +2064,10 @@ - /* These are no-ops, preserved for backward compatibility. */ - break; - -+ case OPT_feglibc_: -+ /* This is a no-op at the moment. */ -+ break; -+ - default: - /* If the flag was handled in a standard way, assume the lack of - processing here is intentional. */ ---- a/gcc/passes.c -+++ b/gcc/passes.c -@@ -591,6 +591,7 @@ - NEXT_PASS (pass_rename_ssa_copies); - NEXT_PASS (pass_complete_unrolli); - NEXT_PASS (pass_ccp); -+ NEXT_PASS (pass_promote_indices); - NEXT_PASS (pass_forwprop); - /* Ideally the function call conditional - dead code elimination phase can be delayed -@@ -605,6 +606,7 @@ - alias information also rewrites no longer addressed - locals into SSA form if possible. */ - NEXT_PASS (pass_build_alias); -+ NEXT_PASS (pass_remove_local_statics); - NEXT_PASS (pass_return_slot); - NEXT_PASS (pass_phiprop); - NEXT_PASS (pass_fre); ---- a/gcc/pointer-set.c -+++ b/gcc/pointer-set.c -@@ -181,6 +181,23 @@ - break; - } - -+/* Return the number of elements in PSET. */ -+ -+size_t -+pointer_set_n_elements (struct pointer_set_t *pset) -+{ -+ return pset->n_elements; -+} -+ -+/* Remove all entries from PSET. */ -+ -+void -+pointer_set_clear (struct pointer_set_t *pset) -+{ -+ pset->n_elements = 0; -+ memset (pset->slots, 0, sizeof (pset->slots[0]) * pset->n_slots); -+} -+ - - /* A pointer map is represented the same way as a pointer_set, so - the hash code is based on the address of the key, rather than -@@ -301,3 +318,20 @@ - if (pmap->keys[i] && !fn (pmap->keys[i], &pmap->values[i], data)) - break; - } -+ -+/* Return the number of elements in PMAP. */ -+ -+size_t -+pointer_map_n_elements (struct pointer_map_t *pmap) -+{ -+ return pmap->n_elements; -+} -+ -+/* Remove all entries from PMAP. */ -+ -+void pointer_map_clear (struct pointer_map_t *pmap) -+{ -+ pmap->n_elements = 0; -+ memset (pmap->keys, 0, sizeof (pmap->keys[0]) * pmap->n_slots); -+ memset (pmap->values, 0, sizeof (pmap->values[0]) * pmap->n_slots); -+} ---- a/gcc/pointer-set.h -+++ b/gcc/pointer-set.h -@@ -29,6 +29,8 @@ - void pointer_set_traverse (const struct pointer_set_t *, - bool (*) (const void *, void *), - void *); -+size_t pointer_set_n_elements (struct pointer_set_t *); -+void pointer_set_clear (struct pointer_set_t *); - - struct pointer_map_t; - struct pointer_map_t *pointer_map_create (void); -@@ -38,5 +40,7 @@ - void **pointer_map_insert (struct pointer_map_t *pmap, const void *p); - void pointer_map_traverse (const struct pointer_map_t *, - bool (*) (const void *, void **, void *), void *); -+size_t pointer_map_n_elements (struct pointer_map_t *); -+void pointer_map_clear (struct pointer_map_t *); - - #endif /* POINTER_SET_H */ ---- a/gcc/postreload.c -+++ b/gcc/postreload.c -@@ -46,6 +46,7 @@ - #include "tree.h" - #include "timevar.h" - #include "tree-pass.h" -+#include "addresses.h" - #include "df.h" - #include "dbgcnt.h" - -@@ -708,17 +709,19 @@ - int last_label_ruid; - int min_labelno, n_labels; - HARD_REG_SET ever_live_at_start, *label_live; -+ enum reg_class index_regs; - - /* If reg+reg can be used in offsetable memory addresses, the main chunk of - reload has already used it where appropriate, so there is no use in - trying to generate it now. */ -- if (double_reg_address_ok && INDEX_REG_CLASS != NO_REGS) -+ index_regs = index_reg_class (VOIDmode); -+ if (double_reg_address_ok && index_regs != NO_REGS) - return; - - /* To avoid wasting too much time later searching for an index register, - determine the minimum and maximum index register numbers. */ - for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) -- if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], r)) -+ if (TEST_HARD_REG_BIT (reg_class_contents[index_regs], r)) - { - if (first_index_reg == -1) - first_index_reg = r; -@@ -826,8 +829,8 @@ - substitute uses of REG (typically in MEMs) with. - First check REG and BASE for being index registers; - we can use them even if they are not dead. */ -- if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno) -- || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], -+ if (TEST_HARD_REG_BIT (reg_class_contents[index_regs], regno) -+ || TEST_HARD_REG_BIT (reg_class_contents[index_regs], - REGNO (base))) - { - const_reg = reg; -@@ -841,8 +844,7 @@ - two registers. */ - for (i = first_index_reg; i <= last_index_reg; i++) - { -- if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], -- i) -+ if (TEST_HARD_REG_BIT (reg_class_contents[index_regs], i) - && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES - && reg_state[i].store_ruid <= reg_state[regno].use_ruid - && hard_regno_nregs[i][GET_MODE (reg)] == 1) ---- a/gcc/real.c -+++ b/gcc/real.c -@@ -4513,6 +4513,167 @@ - false - }; - -+/* Encode half-precision floats. This routine is used both for the IEEE -+ ARM alternative encodings. */ -+static void -+encode_ieee_half (const struct real_format *fmt, long *buf, -+ const REAL_VALUE_TYPE *r) -+{ -+ unsigned long image, sig, exp; -+ unsigned long sign = r->sign; -+ bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; -+ -+ image = sign << 15; -+ sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 11)) & 0x3ff; -+ -+ switch (r->cl) -+ { -+ case rvc_zero: -+ break; -+ -+ case rvc_inf: -+ if (fmt->has_inf) -+ image |= 31 << 10; -+ else -+ image |= 0x7fff; -+ break; -+ -+ case rvc_nan: -+ if (fmt->has_nans) -+ { -+ if (r->canonical) -+ sig = (fmt->canonical_nan_lsbs_set ? (1 << 9) - 1 : 0); -+ if (r->signalling == fmt->qnan_msb_set) -+ sig &= ~(1 << 9); -+ else -+ sig |= 1 << 9; -+ if (sig == 0) -+ sig = 1 << 8; -+ -+ image |= 31 << 10; -+ image |= sig; -+ } -+ else -+ image |= 0x3ff; -+ break; -+ -+ case rvc_normal: -+ /* Recall that IEEE numbers are interpreted as 1.F x 2**exp, -+ whereas the intermediate representation is 0.F x 2**exp. -+ Which means we're off by one. */ -+ if (denormal) -+ exp = 0; -+ else -+ exp = REAL_EXP (r) + 15 - 1; -+ image |= exp << 10; -+ image |= sig; -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ buf[0] = image; -+} -+ -+/* Decode half-precision floats. This routine is used both for the IEEE -+ ARM alternative encodings. */ -+static void -+decode_ieee_half (const struct real_format *fmt, REAL_VALUE_TYPE *r, -+ const long *buf) -+{ -+ unsigned long image = buf[0] & 0xffff; -+ bool sign = (image >> 15) & 1; -+ int exp = (image >> 10) & 0x1f; -+ -+ memset (r, 0, sizeof (*r)); -+ image <<= HOST_BITS_PER_LONG - 11; -+ image &= ~SIG_MSB; -+ -+ if (exp == 0) -+ { -+ if (image && fmt->has_denorm) -+ { -+ r->cl = rvc_normal; -+ r->sign = sign; -+ SET_REAL_EXP (r, -14); -+ r->sig[SIGSZ-1] = image << 1; -+ normalize (r); -+ } -+ else if (fmt->has_signed_zero) -+ r->sign = sign; -+ } -+ else if (exp == 31 && (fmt->has_nans || fmt->has_inf)) -+ { -+ if (image) -+ { -+ r->cl = rvc_nan; -+ r->sign = sign; -+ r->signalling = (((image >> (HOST_BITS_PER_LONG - 2)) & 1) -+ ^ fmt->qnan_msb_set); -+ r->sig[SIGSZ-1] = image; -+ } -+ else -+ { -+ r->cl = rvc_inf; -+ r->sign = sign; -+ } -+ } -+ else -+ { -+ r->cl = rvc_normal; -+ r->sign = sign; -+ SET_REAL_EXP (r, exp - 15 + 1); -+ r->sig[SIGSZ-1] = image | SIG_MSB; -+ } -+} -+ -+/* Half-precision format, as specified in IEEE 754R. */ -+const struct real_format ieee_half_format = -+ { -+ encode_ieee_half, -+ decode_ieee_half, -+ 2, -+ 11, -+ 11, -+ -13, -+ 16, -+ 15, -+ 15, -+ false, -+ true, -+ true, -+ true, -+ true, -+ true, -+ true, -+ false -+ }; -+ -+/* ARM's alternative half-precision format, similar to IEEE but with -+ no reserved exponent value for NaNs and infinities; rather, it just -+ extends the range of exponents by one. */ -+const struct real_format arm_half_format = -+ { -+ encode_ieee_half, -+ decode_ieee_half, -+ 2, -+ 11, -+ 11, -+ -13, -+ 17, -+ 15, -+ 15, -+ false, -+ true, -+ false, -+ false, -+ true, -+ true, -+ false, -+ false -+ }; -+ - /* A synthetic "format" for internal arithmetic. It's the size of the - internal significand minus the two bits needed for proper rounding. - The encode and decode routines exist only to satisfy our paranoia ---- a/gcc/real.h -+++ b/gcc/real.h -@@ -304,6 +304,8 @@ - extern const struct real_format decimal_single_format; - extern const struct real_format decimal_double_format; - extern const struct real_format decimal_quad_format; -+extern const struct real_format ieee_half_format; -+extern const struct real_format arm_half_format; - - - /* ====================================================================== */ ---- a/gcc/regrename.c -+++ b/gcc/regrename.c -@@ -567,14 +567,14 @@ - int index_op; - unsigned regno0 = REGNO (op0), regno1 = REGNO (op1); - -- if (REGNO_OK_FOR_INDEX_P (regno1) -+ if (regno_ok_for_index_p (regno1, mode) - && regno_ok_for_base_p (regno0, mode, PLUS, REG)) - index_op = 1; -- else if (REGNO_OK_FOR_INDEX_P (regno0) -+ else if (regno_ok_for_index_p (regno0, mode) - && regno_ok_for_base_p (regno1, mode, PLUS, REG)) - index_op = 0; - else if (regno_ok_for_base_p (regno0, mode, PLUS, REG) -- || REGNO_OK_FOR_INDEX_P (regno1)) -+ || regno_ok_for_index_p (regno1, mode)) - index_op = 1; - else if (regno_ok_for_base_p (regno1, mode, PLUS, REG)) - index_op = 0; -@@ -599,7 +599,7 @@ - } - - if (locI) -- scan_rtx_address (insn, locI, INDEX_REG_CLASS, action, mode); -+ scan_rtx_address (insn, locI, index_reg_class (mode), action, mode); - if (locB) - scan_rtx_address (insn, locB, base_reg_class (mode, PLUS, index_code), - action, mode); -@@ -1488,14 +1488,14 @@ - int index_op; - unsigned regno0 = REGNO (op0), regno1 = REGNO (op1); - -- if (REGNO_OK_FOR_INDEX_P (regno1) -+ if (regno_ok_for_index_p (regno1, mode) - && regno_ok_for_base_p (regno0, mode, PLUS, REG)) - index_op = 1; -- else if (REGNO_OK_FOR_INDEX_P (regno0) -+ else if (regno_ok_for_index_p (regno0, mode) - && regno_ok_for_base_p (regno1, mode, PLUS, REG)) - index_op = 0; - else if (regno_ok_for_base_p (regno0, mode, PLUS, REG) -- || REGNO_OK_FOR_INDEX_P (regno1)) -+ || regno_ok_for_index_p (regno1, mode)) - index_op = 1; - else if (regno_ok_for_base_p (regno1, mode, PLUS, REG)) - index_op = 0; -@@ -1520,8 +1520,8 @@ - } - - if (locI) -- changed |= replace_oldest_value_addr (locI, INDEX_REG_CLASS, mode, -- insn, vd); -+ changed |= replace_oldest_value_addr (locI, index_reg_class (mode), -+ mode, insn, vd); - if (locB) - changed |= replace_oldest_value_addr (locB, - base_reg_class (mode, PLUS, ---- a/gcc/reload.c -+++ b/gcc/reload.c -@@ -5046,7 +5046,7 @@ - loc = &XEXP (*loc, 0); - } - -- if (double_reg_address_ok) -+ if (double_reg_address_ok && index_reg_class (mode) != NO_REGS) - { - /* Unshare the sum as well. */ - *loc = ad = copy_rtx (ad); -@@ -5054,8 +5054,8 @@ - /* Reload the displacement into an index reg. - We assume the frame pointer or arg pointer is a base reg. */ - find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1), -- INDEX_REG_CLASS, GET_MODE (ad), opnum, -- type, ind_levels); -+ index_reg_class (mode), GET_MODE (ad), -+ opnum, type, ind_levels); - return 0; - } - else -@@ -5448,13 +5448,13 @@ - #define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, OUTER, INDEX) \ - ((CONTEXT) == 0 \ - ? regno_ok_for_base_p (REGNO, MODE, OUTER, INDEX) \ -- : REGNO_OK_FOR_INDEX_P (REGNO)) -+ : regno_ok_for_index_p (REGNO, MODE)) - - enum reg_class context_reg_class; - RTX_CODE code = GET_CODE (x); - - if (context == 1) -- context_reg_class = INDEX_REG_CLASS; -+ context_reg_class = index_reg_class (mode); - else - context_reg_class = base_reg_class (mode, outer_code, index_code); - -@@ -5546,17 +5546,17 @@ - - else if (code0 == REG && code1 == REG) - { -- if (REGNO_OK_FOR_INDEX_P (REGNO (op1)) -+ if (regno_ok_for_index_p (REGNO (op1), mode) - && regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG)) - return 0; -- else if (REGNO_OK_FOR_INDEX_P (REGNO (op0)) -+ else if (regno_ok_for_index_p (REGNO (op0), mode) - && regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG)) - return 0; - else if (regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG)) - find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH, - &XEXP (x, 1), opnum, type, ind_levels, - insn); -- else if (REGNO_OK_FOR_INDEX_P (REGNO (op1))) -+ else if (regno_ok_for_index_p (REGNO (op1), mode)) - find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG, - &XEXP (x, 0), opnum, type, ind_levels, - insn); -@@ -5564,7 +5564,7 @@ - find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH, - &XEXP (x, 0), opnum, type, ind_levels, - insn); -- else if (REGNO_OK_FOR_INDEX_P (REGNO (op0))) -+ else if (regno_ok_for_index_p (REGNO (op0), mode)) - find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG, - &XEXP (x, 1), opnum, type, ind_levels, - insn); -@@ -5634,7 +5634,7 @@ - need to live longer than a TYPE reload normally would, so be - conservative and class it as RELOAD_OTHER. */ - if ((REG_P (XEXP (op1, 1)) -- && !REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1)))) -+ && !regno_ok_for_index_p (REGNO (XEXP (op1, 1)), mode)) - || GET_CODE (XEXP (op1, 1)) == PLUS) - find_reloads_address_1 (mode, XEXP (op1, 1), 1, code, SCRATCH, - &XEXP (op1, 1), opnum, RELOAD_OTHER, -@@ -6128,18 +6128,26 @@ - /* For some processors an address may be valid in the - original mode but not in a smaller mode. For - example, ARM accepts a scaled index register in -- SImode but not in HImode. Similarly, the address may -- have been valid before the subreg offset was added, -- but not afterwards. find_reloads_address -- assumes that we pass it a valid address, and doesn't -- force a reload. This will probably be fine if -- find_reloads_address finds some reloads. But if it -- doesn't find any, then we may have just converted a -- valid address into an invalid one. Check for that -- here. */ -+ SImode but not in HImode. Note that this is only -+ a problem if the address in reg_equiv_mem is already -+ invalid in the new mode; other cases would be fixed -+ by find_reloads_address as usual. -+ -+ ??? We attempt to handle such cases here by doing an -+ additional reload of the full address after the -+ usual processing by find_reloads_address. Note that -+ this may not work in the general case, but it seems -+ to cover the cases where this situation currently -+ occurs. A more general fix might be to reload the -+ *value* instead of the address, but this would not -+ be expected by the callers of this routine as-is. -+ -+ If find_reloads_address already completed replaced -+ the address, there is nothing further to do. */ - if (reloaded == 0 -- && !strict_memory_address_p (GET_MODE (tem), -- XEXP (tem, 0))) -+ && reg_equiv_mem[regno] != 0 -+ && !strict_memory_address_p (GET_MODE (x), -+ XEXP (reg_equiv_mem[regno], 0))) - push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0, - base_reg_class (GET_MODE (tem), MEM, SCRATCH), - GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0, ---- a/gcc/rtlanal.c -+++ b/gcc/rtlanal.c -@@ -2913,62 +2913,78 @@ - commutative_operand_precedence (rtx op) - { - enum rtx_code code = GET_CODE (op); -+ int value; - - /* Constants always come the second operand. Prefer "nice" constants. */ - if (code == CONST_INT) -- return -8; -- if (code == CONST_DOUBLE) -- return -7; -- if (code == CONST_FIXED) -- return -7; -- op = avoid_constant_pool_reference (op); -- code = GET_CODE (op); -- -- switch (GET_RTX_CLASS (code)) -- { -- case RTX_CONST_OBJ: -- if (code == CONST_INT) -- return -6; -- if (code == CONST_DOUBLE) -- return -5; -- if (code == CONST_FIXED) -- return -5; -- return -4; -- -- case RTX_EXTRA: -- /* SUBREGs of objects should come second. */ -- if (code == SUBREG && OBJECT_P (SUBREG_REG (op))) -- return -3; -- return 0; -+ value = -8; -+ else if (code == CONST_DOUBLE) -+ value = -7; -+ else if (code == CONST_FIXED) -+ value = -7; -+ else -+ { -+ op = avoid_constant_pool_reference (op); -+ code = GET_CODE (op); -+ -+ switch (GET_RTX_CLASS (code)) -+ { -+ case RTX_CONST_OBJ: -+ if (code == CONST_INT) -+ value = -6; -+ else if (code == CONST_DOUBLE) -+ value = -5; -+ else if (code == CONST_FIXED) -+ value = -5; -+ else -+ value = -4; -+ break; -+ -+ case RTX_EXTRA: -+ /* SUBREGs of objects should come second. */ -+ if (code == SUBREG && OBJECT_P (SUBREG_REG (op))) -+ value = -3; -+ else -+ value = 0; -+ break; -+ -+ case RTX_OBJ: -+ /* Complex expressions should be the first, so decrease priority -+ of objects. */ -+ value = -1; -+ break; - -- case RTX_OBJ: -- /* Complex expressions should be the first, so decrease priority -- of objects. Prefer pointer objects over non pointer objects. */ -- if ((REG_P (op) && REG_POINTER (op)) -- || (MEM_P (op) && MEM_POINTER (op))) -- return -1; -- return -2; -- -- case RTX_COMM_ARITH: -- /* Prefer operands that are themselves commutative to be first. -- This helps to make things linear. In particular, -- (and (and (reg) (reg)) (not (reg))) is canonical. */ -- return 4; -- -- case RTX_BIN_ARITH: -- /* If only one operand is a binary expression, it will be the first -- operand. In particular, (plus (minus (reg) (reg)) (neg (reg))) -- is canonical, although it will usually be further simplified. */ -- return 2; -+ case RTX_COMM_ARITH: -+ /* Prefer operands that are themselves commutative to be first. -+ This helps to make things linear. In particular, -+ (and (and (reg) (reg)) (not (reg))) is canonical. */ -+ value = 4; -+ break; -+ -+ case RTX_BIN_ARITH: -+ /* If only one operand is a binary expression, it will be the first -+ operand. In particular, (plus (minus (reg) (reg)) (neg (reg))) -+ is canonical, although it will usually be further simplified. */ -+ value = 2; -+ break; - -- case RTX_UNARY: -- /* Then prefer NEG and NOT. */ -- if (code == NEG || code == NOT) -- return 1; -+ case RTX_UNARY: -+ /* Then prefer NEG and NOT. */ -+ if (code == NEG || code == NOT) -+ value = 1; -+ else -+ value = 0; -+ break; - -- default: -- return 0; -+ default: -+ value = 0; -+ } - } -+ -+ if (targetm.commutative_operand_precedence) -+ value = targetm.commutative_operand_precedence (op, value); -+ -+ return value; - } - - /* Return 1 iff it is necessary to swap operands of commutative operation ---- a/gcc/rtl.def -+++ b/gcc/rtl.def -@@ -1088,7 +1088,11 @@ - guard for the bypass. The function will get the two insns as - parameters. If the function returns zero the bypass will be - ignored for this case. Additional guard is necessary to recognize -- complicated bypasses, e.g. when consumer is load address. */ -+ complicated bypasses, e.g. when consumer is load address. If there -+ are more one bypass with the same output and input insns, the -+ chosen bypass is the first bypass with a guard in description whose -+ guard function returns nonzero. If there is no such bypass, then -+ bypass without the guard function is chosen. */ - DEF_RTL_EXPR(DEFINE_BYPASS, "define_bypass", "issS", RTX_EXTRA) - - /* (define_automaton string) describes names of automata generated and ---- a/gcc/sched-ebb.c -+++ b/gcc/sched-ebb.c -@@ -286,6 +286,7 @@ - rank, - ebb_print_insn, - ebb_contributes_to_priority, -+ NULL, /* insn_finishes_block_p */ - - NULL, NULL, - NULL, NULL, ---- a/gcc/sched-int.h -+++ b/gcc/sched-int.h -@@ -558,6 +558,10 @@ - calculations. */ - int (*contributes_to_priority) (rtx, rtx); - -+ /* Return true if scheduling insn (passed as the parameter) will trigger -+ finish of scheduling current block. */ -+ bool (*insn_finishes_block_p) (rtx); -+ - /* The boundaries of the set of insns to be scheduled. */ - rtx prev_head, next_tail; - ---- a/gcc/sched-rgn.c -+++ b/gcc/sched-rgn.c -@@ -2338,6 +2338,19 @@ - 0, 0, 0 - }; - -+/* Return true if scheduling INSN will trigger finish of scheduling -+ current block. */ -+static bool -+rgn_insn_finishes_block_p (rtx insn) -+{ -+ if (INSN_BB (insn) == target_bb -+ && sched_target_n_insns + 1 == target_n_insns) -+ /* INSN is the last not-scheduled instruction in the current block. */ -+ return true; -+ -+ return false; -+} -+ - /* Used in schedule_insns to initialize current_sched_info for scheduling - regions (or single basic blocks). */ - -@@ -2350,6 +2363,7 @@ - rgn_rank, - rgn_print_insn, - contributes_to_priority, -+ rgn_insn_finishes_block_p, - - NULL, NULL, - NULL, NULL, ---- a/gcc/sdbout.c -+++ b/gcc/sdbout.c -@@ -337,6 +337,7 @@ - debug_nothing_int, /* handle_pch */ - debug_nothing_rtx, /* var_location */ - debug_nothing_void, /* switch_text_section */ -+ debug_nothing_tree_tree, /* set_name */ - 0 /* start_end_main_source_file */ - }; - ---- a/gcc/sel-sched-ir.c -+++ b/gcc/sel-sched-ir.c -@@ -5431,6 +5431,7 @@ - NULL, /* rgn_rank */ - sel_print_insn, /* rgn_print_insn */ - contributes_to_priority, -+ NULL, /* insn_finishes_block_p */ - - NULL, NULL, - NULL, NULL, ---- a/gcc/target-def.h -+++ b/gcc/target-def.h -@@ -84,7 +84,7 @@ - #define TARGET_ASM_INTERNAL_LABEL default_internal_label - #endif - --#ifndef TARGET_ARM_TTYPE -+#ifndef TARGET_ASM_TTYPE - #define TARGET_ASM_TTYPE hook_bool_rtx_false - #endif - -@@ -208,6 +208,10 @@ - #define TARGET_EXTRA_LIVE_ON_ENTRY hook_void_bitmap - #endif - -+#ifndef TARGET_WARN_FUNC_RESULT -+#define TARGET_WARN_FUNC_RESULT hook_bool_void_true -+#endif -+ - #ifndef TARGET_ASM_FILE_START_APP_OFF - #define TARGET_ASM_FILE_START_APP_OFF false - #endif -@@ -383,6 +387,9 @@ - #define TARGET_VECTOR_ALIGNMENT_REACHABLE \ - default_builtin_vector_alignment_reachable - #define TARGET_VECTORIZE_BUILTIN_VEC_PERM 0 -+#define TARGET_VECTOR_MIN_ALIGNMENT \ -+ default_vector_min_alignment -+#define TARGET_VECTOR_ALWAYS_MISALIGN hook_bool_const_tree_false - - #define TARGET_VECTORIZE \ - { \ -@@ -393,7 +400,9 @@ - TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD, \ - TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST, \ - TARGET_VECTOR_ALIGNMENT_REACHABLE, \ -- TARGET_VECTORIZE_BUILTIN_VEC_PERM \ -+ TARGET_VECTORIZE_BUILTIN_VEC_PERM, \ -+ TARGET_VECTOR_MIN_ALIGNMENT, \ -+ TARGET_VECTOR_ALWAYS_MISALIGN, \ - } - - #define TARGET_DEFAULT_TARGET_FLAGS 0 -@@ -504,6 +513,7 @@ - #define TARGET_ALLOCATE_INITIAL_VALUE NULL - - #define TARGET_UNSPEC_MAY_TRAP_P default_unspec_may_trap_p -+#define TARGET_COMMUTATIVE_OPERAND_PRECEDENCE NULL - - #ifndef TARGET_SET_CURRENT_FUNCTION - #define TARGET_SET_CURRENT_FUNCTION hook_void_tree -@@ -532,6 +542,10 @@ - #define TARGET_INVALID_CONVERSION hook_constcharptr_const_tree_const_tree_null - #define TARGET_INVALID_UNARY_OP hook_constcharptr_int_const_tree_null - #define TARGET_INVALID_BINARY_OP hook_constcharptr_int_const_tree_const_tree_null -+#define TARGET_INVALID_PARAMETER_TYPE hook_constcharptr_const_tree_null -+#define TARGET_INVALID_RETURN_TYPE hook_constcharptr_const_tree_null -+#define TARGET_PROMOTED_TYPE hook_tree_const_tree_null -+#define TARGET_CONVERT_TO_TYPE hook_tree_tree_tree_null - - #define TARGET_FIXED_CONDITION_CODE_REGS hook_bool_uintp_uintp_false - -@@ -590,6 +604,7 @@ - #define TARGET_ARG_PARTIAL_BYTES hook_int_CUMULATIVE_ARGS_mode_tree_bool_0 - - #define TARGET_FUNCTION_VALUE default_function_value -+#define TARGET_LIBCALL_VALUE default_libcall_value - #define TARGET_INTERNAL_ARG_POINTER default_internal_arg_pointer - #define TARGET_UPDATE_STACK_BOUNDARY NULL - #define TARGET_GET_DRAP_RTX NULL -@@ -613,6 +628,7 @@ - TARGET_ARG_PARTIAL_BYTES, \ - TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN, \ - TARGET_FUNCTION_VALUE, \ -+ TARGET_LIBCALL_VALUE, \ - TARGET_INTERNAL_ARG_POINTER, \ - TARGET_UPDATE_STACK_BOUNDARY, \ - TARGET_GET_DRAP_RTX, \ -@@ -716,6 +732,11 @@ - #define TARGET_CXX_ADJUST_CLASS_AT_DEFINITION hook_void_tree - #endif - -+ -+#ifndef TARGET_CXX_TTYPE_REF_ENCODE -+#define TARGET_CXX_TTYPE_REF_ENCODE NULL -+#endif -+ - #define TARGET_CXX \ - { \ - TARGET_CXX_GUARD_TYPE, \ -@@ -730,7 +751,8 @@ - TARGET_CXX_LIBRARY_RTTI_COMDAT, \ - TARGET_CXX_USE_AEABI_ATEXIT, \ - TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT, \ -- TARGET_CXX_ADJUST_CLASS_AT_DEFINITION \ -+ TARGET_CXX_ADJUST_CLASS_AT_DEFINITION, \ -+ TARGET_CXX_TTYPE_REF_ENCODE \ - } - - /* EMUTLS specific */ -@@ -886,6 +908,7 @@ - TARGET_ADDRESS_COST, \ - TARGET_ALLOCATE_INITIAL_VALUE, \ - TARGET_UNSPEC_MAY_TRAP_P, \ -+ TARGET_COMMUTATIVE_OPERAND_PRECEDENCE, \ - TARGET_DWARF_REGISTER_SPAN, \ - TARGET_INIT_DWARF_REG_SIZES_EXTRA, \ - TARGET_FIXED_CONDITION_CODE_REGS, \ -@@ -913,6 +936,10 @@ - TARGET_INVALID_CONVERSION, \ - TARGET_INVALID_UNARY_OP, \ - TARGET_INVALID_BINARY_OP, \ -+ TARGET_INVALID_PARAMETER_TYPE, \ -+ TARGET_INVALID_RETURN_TYPE, \ -+ TARGET_PROMOTED_TYPE, \ -+ TARGET_CONVERT_TO_TYPE, \ - TARGET_IRA_COVER_CLASSES, \ - TARGET_SECONDARY_RELOAD, \ - TARGET_EXPAND_TO_RTL_HOOK, \ -@@ -923,6 +950,7 @@ - TARGET_EMUTLS, \ - TARGET_OPTION_HOOKS, \ - TARGET_EXTRA_LIVE_ON_ENTRY, \ -+ TARGET_WARN_FUNC_RESULT, \ - TARGET_UNWIND_TABLES_DEFAULT, \ - TARGET_HAVE_NAMED_SECTIONS, \ - TARGET_HAVE_SWITCHABLE_BSS_SECTIONS, \ ---- a/gcc/target.h -+++ b/gcc/target.h -@@ -473,7 +473,16 @@ - - /* Target builtin that implements vector permute. */ - tree (* builtin_vec_perm) (tree, tree*); --} vectorize; -+ -+ /* Return the minimum alignment required to load or store a -+ vector of the given type, which may be less than the -+ natural alignment of the type. */ -+ int (* vector_min_alignment) (const_tree); -+ -+ /* Return true if "movmisalign" patterns should be used for all -+ loads/stores from data arrays. */ -+ bool (* always_misalign) (const_tree); -+ } vectorize; - - /* The initial value of target_flags. */ - int default_target_flags; -@@ -694,6 +703,10 @@ - FLAGS has the same meaning as in rtlanal.c: may_trap_p_1. */ - int (* unspec_may_trap_p) (const_rtx x, unsigned flags); - -+ /* Return a value indicating whether an operand of a commutative -+ operation is preferred as the first or second operand. */ -+ int (* commutative_operand_precedence) (const_rtx, int); -+ - /* Given a register, this hook should return a parallel of registers - to represent where to find the register pieces. Define this hook - if the register and its mode are represented in Dwarf in -@@ -870,6 +883,10 @@ - rtx (*function_value) (const_tree ret_type, const_tree fn_decl_or_type, - bool outgoing); - -+ /* Return the rtx for the result of a libcall of mode MODE, -+ calling the function FN_NAME. */ -+ rtx (*libcall_value) (enum machine_mode, rtx); -+ - /* Return an rtx for the argument pointer incoming to the - current function. */ - rtx (*internal_arg_pointer) (void); -@@ -899,6 +916,24 @@ - is not permitted on TYPE1 and TYPE2, NULL otherwise. */ - const char *(*invalid_binary_op) (int op, const_tree type1, const_tree type2); - -+ /* Return the diagnostic message string if TYPE is not valid as a -+ function parameter type, NULL otherwise. */ -+ const char *(*invalid_parameter_type) (const_tree type); -+ -+ /* Return the diagnostic message string if TYPE is not valid as a -+ function return type, NULL otherwise. */ -+ const char *(*invalid_return_type) (const_tree type); -+ -+ /* If values of TYPE are promoted to some other type when used in -+ expressions (analogous to the integer promotions), return that type, -+ or NULL_TREE otherwise. */ -+ tree (*promoted_type) (const_tree type); -+ -+ /* Convert EXPR to TYPE, if target-specific types with special conversion -+ rules are involved. Return the converted expression, or NULL to apply -+ the standard conversion rules. */ -+ tree (*convert_to_type) (tree type, tree expr); -+ - /* Return the array of IRA cover classes for the current target. */ - const enum reg_class *(*ira_cover_classes) (void); - -@@ -977,6 +1012,11 @@ - class (eg, tweak visibility or perform any other required - target modifications). */ - void (*adjust_class_at_definition) (tree type); -+ /* Encode a reference type info, used for catching pointer -+ references. The provided expression will be the address of the -+ type info object of the type to which a reference is being -+ caught. */ -+ tree (* ttype_ref_encode) (tree); - } cxx; - - /* Functions and data for emulated TLS support. */ -@@ -1040,6 +1080,10 @@ - bits in the bitmap passed in. */ - void (*live_on_entry) (bitmap); - -+ /* Return false if warnings about missing return statements or suspect -+ noreturn attributes should be suppressed for the current function. */ -+ bool (*warn_func_result) (void); -+ - /* True if unwinding tables should be generated by default. */ - bool unwind_tables_default; - ---- a/gcc/targhooks.c -+++ b/gcc/targhooks.c -@@ -441,6 +441,15 @@ - return NULL; - } - -+tree -+hook_cxx_ttype_ref_in_bit0 (tree exp) -+{ -+ exp = convert (build_pointer_type (char_type_node), exp); -+ exp = pointer_int_sum (PLUS_EXPR, exp, integer_one_node); -+ -+ return exp; -+} -+ - /* Initialize the stack protection decls. */ - - /* Stack protection related decls living in libgcc. */ -@@ -561,6 +570,12 @@ - } - - rtx -+default_libcall_value (enum machine_mode mode, rtx fun ATTRIBUTE_UNUSED) -+{ -+ return LIBCALL_VALUE (mode); -+} -+ -+rtx - default_internal_arg_pointer (void) - { - /* If the reg that the virtual arg pointer will be translated into is -@@ -712,6 +727,12 @@ - return true; - } - -+int -+default_vector_min_alignment (const_tree type) -+{ -+ return TYPE_ALIGN_UNIT (type); -+} -+ - bool - default_hard_regno_scratch_ok (unsigned int regno ATTRIBUTE_UNUSED) - { ---- a/gcc/targhooks.h -+++ b/gcc/targhooks.h -@@ -48,6 +48,7 @@ - - extern tree default_cxx_guard_type (void); - extern tree default_cxx_get_cookie_size (tree); -+extern tree hook_cxx_ttype_ref_in_bit0 (tree); - - extern bool hook_pass_by_reference_must_pass_in_stack - (CUMULATIVE_ARGS *, enum machine_mode mode, const_tree, bool); -@@ -71,6 +72,8 @@ - - extern bool default_builtin_vector_alignment_reachable (const_tree, bool); - -+extern int default_vector_min_alignment (const_tree); -+ - /* These are here, and not in hooks.[ch], because not all users of - hooks.h include tm.h, and thus we don't have CUMULATIVE_ARGS. */ - -@@ -87,6 +90,7 @@ - (const_tree, const_tree, const_tree); - extern bool hook_bool_const_rtx_commutative_p (const_rtx, int); - extern rtx default_function_value (const_tree, const_tree, bool); -+extern rtx default_libcall_value (enum machine_mode, rtx); - extern rtx default_internal_arg_pointer (void); - #ifdef IRA_COVER_CLASSES - extern const enum reg_class *default_ira_cover_classes (void); ---- a/gcc/timevar.def -+++ b/gcc/timevar.def -@@ -134,6 +134,7 @@ - DEFTIMEVAR (TV_PREDCOM , "predictive commoning") - DEFTIMEVAR (TV_TREE_LOOP_INIT , "tree loop init") - DEFTIMEVAR (TV_TREE_LOOP_FINI , "tree loop fini") -+DEFTIMEVAR (TV_TREE_LOOP_PROMOTE , "tree loop index promotion") - DEFTIMEVAR (TV_TREE_CH , "tree copy headers") - DEFTIMEVAR (TV_TREE_SSA_UNCPROP , "tree SSA uncprop") - DEFTIMEVAR (TV_TREE_SSA_TO_NORMAL , "tree SSA to normal") -@@ -141,6 +142,7 @@ - DEFTIMEVAR (TV_TREE_COPY_RENAME , "tree rename SSA copies") - DEFTIMEVAR (TV_TREE_SSA_VERIFY , "tree SSA verifier") - DEFTIMEVAR (TV_TREE_STMT_VERIFY , "tree STMT verifier") -+DEFTIMEVAR (TV_TREE_RLS , "tree local static removal") - DEFTIMEVAR (TV_TREE_SWITCH_CONVERSION, "tree switch initialization conversion") - DEFTIMEVAR (TV_CGRAPH_VERIFY , "callgraph verifier") - DEFTIMEVAR (TV_DOM_FRONTIERS , "dominance frontiers") ---- a/gcc/toplev.h -+++ b/gcc/toplev.h -@@ -139,6 +139,7 @@ - extern int flag_unroll_all_loops; - extern int flag_unswitch_loops; - extern int flag_cprop_registers; -+extern int flag_remove_local_statics; - extern int time_report; - extern int flag_ira_coalesce; - extern int flag_ira_move_spills; ---- a/gcc/tree.c -+++ b/gcc/tree.c -@@ -4062,6 +4062,7 @@ - bool *no_add_attrs) - { - tree node = *pnode; -+ bool is_dllimport; - - /* These attributes may apply to structure and union types being created, - but otherwise should pass to the declaration involved. */ -@@ -4109,9 +4110,11 @@ - return NULL_TREE; - } - -+ is_dllimport = is_attribute_p ("dllimport", name); -+ - /* Report error on dllimport ambiguities seen now before they cause - any damage. */ -- else if (is_attribute_p ("dllimport", name)) -+ if (is_dllimport) - { - /* Honor any target-specific overrides. */ - if (!targetm.valid_dllimport_attribute_p (node)) -@@ -4153,6 +4156,9 @@ - if (*no_add_attrs == false) - DECL_DLLIMPORT_P (node) = 1; - } -+ else if (DECL_DECLARED_INLINE_P (node)) -+ /* An exported function, even if inline, must be emitted. */ -+ DECL_EXTERNAL (node) = 0; - - /* Report error if symbol is not accessible at global scope. */ - if (!TREE_PUBLIC (node) ---- a/gcc/tree-cfg.c -+++ b/gcc/tree-cfg.c -@@ -47,6 +47,7 @@ - #include "value-prof.h" - #include "pointer-set.h" - #include "tree-inline.h" -+#include "target.h" - - /* This file contains functions for building the Control Flow Graph (CFG) - for a function tree. */ -@@ -7052,6 +7053,9 @@ - edge e; - edge_iterator ei; - -+ if (!targetm.warn_func_result()) -+ return 0; -+ - /* If we have a path to EXIT, then we do return. */ - if (TREE_THIS_VOLATILE (cfun->decl) - && EDGE_COUNT (EXIT_BLOCK_PTR->preds) > 0) ---- a/gcc/tree.h -+++ b/gcc/tree.h -@@ -381,8 +381,10 @@ - unsigned lang_flag_5 : 1; - unsigned lang_flag_6 : 1; - unsigned visited : 1; -+ unsigned packed_flag : 1; -+ unsigned user_align : 1; - -- unsigned spare : 23; -+ unsigned spare : 21; - - union tree_ann_d *ann; - }; -@@ -2140,7 +2142,7 @@ - - /* 1 if the alignment for this type was requested by "aligned" attribute, - 0 if it is the default for this type. */ --#define TYPE_USER_ALIGN(NODE) (TYPE_CHECK (NODE)->type.user_align) -+#define TYPE_USER_ALIGN(NODE) (TYPE_CHECK (NODE)->common.base.user_align) - - /* The alignment for NODE, in bytes. */ - #define TYPE_ALIGN_UNIT(NODE) (TYPE_ALIGN (NODE) / BITS_PER_UNIT) -@@ -2246,7 +2248,7 @@ - - /* Indicated that objects of this type should be laid out in as - compact a way as possible. */ --#define TYPE_PACKED(NODE) (TYPE_CHECK (NODE)->type.packed_flag) -+#define TYPE_PACKED(NODE) (TYPE_CHECK (NODE)->common.base.packed_flag) - - /* Used by type_contains_placeholder_p to avoid recomputation. - Values are: 0 (unknown), 1 (false), 2 (true). Never access -@@ -2265,17 +2267,16 @@ - tree attributes; - unsigned int uid; - -- unsigned int precision : 9; -- ENUM_BITFIELD(machine_mode) mode : 7; -- -- unsigned string_flag : 1; -+ unsigned int precision : 10; - unsigned no_force_blk_flag : 1; - unsigned needs_constructing_flag : 1; - unsigned transparent_union_flag : 1; -- unsigned packed_flag : 1; - unsigned restrict_flag : 1; - unsigned contains_placeholder_bits : 2; - -+ ENUM_BITFIELD(machine_mode) mode : 8; -+ -+ unsigned string_flag : 1; - unsigned lang_flag_0 : 1; - unsigned lang_flag_1 : 1; - unsigned lang_flag_2 : 1; -@@ -2283,7 +2284,6 @@ - unsigned lang_flag_4 : 1; - unsigned lang_flag_5 : 1; - unsigned lang_flag_6 : 1; -- unsigned user_align : 1; - - unsigned int align; - alias_set_type alias_set; -@@ -2584,7 +2584,7 @@ - #define DECL_ALIGN_UNIT(NODE) (DECL_ALIGN (NODE) / BITS_PER_UNIT) - /* Set if the alignment of this DECL has been set by the user, for - example with an 'aligned' attribute. */ --#define DECL_USER_ALIGN(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.user_align) -+#define DECL_USER_ALIGN(NODE) (DECL_COMMON_CHECK (NODE)->common.base.user_align) - /* Holds the machine mode corresponding to the declaration of a variable or - field. Always equal to TYPE_MODE (TREE_TYPE (decl)) except for a - FIELD_DECL. */ -@@ -2621,7 +2621,7 @@ - example, for a FUNCTION_DECL, DECL_SAVED_TREE may be non-NULL and - DECL_EXTERNAL may be true simultaneously; that can be the case for - a C99 "extern inline" function. */ --#define DECL_EXTERNAL(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.decl_flag_2) -+#define DECL_EXTERNAL(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.decl_flag_1) - - /* Nonzero in a ..._DECL means this variable is ref'd from a nested function. - For VAR_DECL nodes, PARM_DECL nodes, and FUNCTION_DECL nodes. -@@ -2696,7 +2696,6 @@ - unsigned ignored_flag : 1; - unsigned abstract_flag : 1; - unsigned artificial_flag : 1; -- unsigned user_align : 1; - unsigned preserve_flag: 1; - unsigned debug_expr_is_from : 1; - -@@ -2712,22 +2711,20 @@ - /* In LABEL_DECL, this is DECL_ERROR_ISSUED. - In VAR_DECL and PARM_DECL, this is DECL_REGISTER. */ - unsigned decl_flag_0 : 1; -- /* In FIELD_DECL, this is DECL_PACKED. */ -- unsigned decl_flag_1 : 1; - /* In FIELD_DECL, this is DECL_BIT_FIELD - In VAR_DECL and FUNCTION_DECL, this is DECL_EXTERNAL. -- In TYPE_DECL, this is TYPE_DECL_SUPRESS_DEBUG. */ -- unsigned decl_flag_2 : 1; -+ In TYPE_DECL, this is TYPE_DECL_SUPPRESS_DEBUG. */ -+ unsigned decl_flag_1 : 1; - /* In FIELD_DECL, this is DECL_NONADDRESSABLE_P -- In VAR_DECL and PARM_DECL, this is DECL_HAS_VALUE_EXPR. */ -- unsigned decl_flag_3 : 1; -+ In VAR_DECL and PARM_DECL, this is DECL_HAS_VALUE_EXPR_P. */ -+ unsigned decl_flag_2 : 1; - /* Logically, these two would go in a theoretical base shared by var and - parm decl. */ - unsigned gimple_reg_flag : 1; - /* In a DECL with pointer type, set if no TBAA should be done. */ - unsigned no_tbaa_flag : 1; - /* Padding so that 'align' can be on a 32-bit boundary. */ -- unsigned decl_common_unused : 2; -+ unsigned decl_common_unused : 4; - - unsigned int align : 24; - /* DECL_OFFSET_ALIGN, used only for FIELD_DECLs. */ -@@ -2751,7 +2748,7 @@ - decl itself. This should only be used for debugging; once this field has - been set, the decl itself may not legitimately appear in the function. */ - #define DECL_HAS_VALUE_EXPR_P(NODE) \ -- (TREE_CHECK2 (NODE, VAR_DECL, PARM_DECL)->decl_common.decl_flag_3) -+ (TREE_CHECK2 (NODE, VAR_DECL, PARM_DECL)->decl_common.decl_flag_2) - #define DECL_VALUE_EXPR(NODE) \ - (decl_value_expr_lookup (DECL_WRTL_CHECK (NODE))) - #define SET_DECL_VALUE_EXPR(NODE, VAL) \ -@@ -2830,11 +2827,11 @@ - #define DECL_FCONTEXT(NODE) (FIELD_DECL_CHECK (NODE)->field_decl.fcontext) - - /* In a FIELD_DECL, indicates this field should be bit-packed. */ --#define DECL_PACKED(NODE) (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_1) -+#define DECL_PACKED(NODE) (FIELD_DECL_CHECK (NODE)->common.base.packed_flag) - - /* Nonzero in a FIELD_DECL means it is a bit field, and must be accessed - specially. */ --#define DECL_BIT_FIELD(NODE) (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_2) -+#define DECL_BIT_FIELD(NODE) (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_1) - - /* Used in a FIELD_DECL to indicate that we cannot form the address of - this component. This makes it possible for Type-Based Alias Analysis -@@ -2852,7 +2849,7 @@ - accesses to s.i must not be given the alias set of the type of 'i' - (int) but instead directly that of the type of 's' (struct S). */ - #define DECL_NONADDRESSABLE_P(NODE) \ -- (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_3) -+ (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_2) - - struct tree_field_decl GTY(()) - { -@@ -3337,7 +3334,7 @@ - into stabs. Instead it will generate cross reference ('x') of names. - This uses the same flag as DECL_EXTERNAL. */ - #define TYPE_DECL_SUPPRESS_DEBUG(NODE) \ -- (TYPE_DECL_CHECK (NODE)->decl_common.decl_flag_2) -+ (TYPE_DECL_CHECK (NODE)->decl_common.decl_flag_1) - - /* Getter of the imported declaration associated to the - IMPORTED_DECL node. */ ---- a/gcc/tree-pass.h -+++ b/gcc/tree-pass.h -@@ -323,6 +323,7 @@ - extern struct gimple_opt_pass pass_empty_loop; - extern struct gimple_opt_pass pass_record_bounds; - extern struct gimple_opt_pass pass_graphite_transforms; -+extern struct gimple_opt_pass pass_promote_indices; - extern struct gimple_opt_pass pass_if_conversion; - extern struct gimple_opt_pass pass_loop_distribution; - extern struct gimple_opt_pass pass_vectorize; -@@ -388,6 +389,7 @@ - extern struct gimple_opt_pass pass_rebuild_cgraph_edges; - extern struct gimple_opt_pass pass_build_cgraph_edges; - extern struct gimple_opt_pass pass_reset_cc_flags; -+extern struct gimple_opt_pass pass_remove_local_statics; - - /* IPA Passes */ - extern struct ipa_opt_pass pass_ipa_inline; ---- a/gcc/tree-sra.c -+++ b/gcc/tree-sra.c -@@ -274,6 +274,12 @@ - != TYPE_PRECISION (TREE_TYPE (t)))) - goto fail; - -+ /* Disable optimization of bitfields on BITS_BIG_ENDIAN -+ architectures. SRA doesn't properly handle padding bits -+ at the bottom, see issue6713. */ -+ if (DECL_BIT_FIELD (t) && BITS_BIG_ENDIAN) -+ goto fail; -+ - saw_one_field = true; - } - ---- /dev/null -+++ b/gcc/tree-ssa-loop-promote.c -@@ -0,0 +1,1628 @@ -+/* Promotion of shorter-than-word-size loop indices. -+ Copyright (C) 2009 Free Software Foundation, Inc. -+ -+This file is part of GCC. -+ -+GCC is free software; you can redistribute it and/or modify it -+under the terms of the GNU General Public License as published by the -+Free Software Foundation; either version 3, or (at your option) any -+later version. -+ -+GCC is distributed in the hope that it will be useful, but WITHOUT -+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+for more details. -+ -+You should have received a copy of the GNU General Public License -+along with GCC; see the file COPYING3. If not see -+<http://www.gnu.org/licenses/>. */ -+ -+/* This pass finds loop indices that are declared as -+ shorter-than-word-size and replaces them with word-sized loop -+ indices. (It assumes that word-sized quantities are the most -+ efficient type on which to do arithmetic.) The loop optimization -+ machinery has a difficult time seeing through the casts required to -+ promote such indices to word-sized quantities for memory addressing -+ and/or preserving the semantics of the source language (such as C). -+ The transformation also helps eliminate unnecessary -+ {sign,zero}-extensions required for the same. -+ -+ Although this is most naturally expressed as a loop optimization -+ pass, we choose to place this pass some ways before the loop -+ optimization passes proper, so that other scalar optimizations will -+ run on our "cleaned-up" code. This decision has the negative of -+ requiring us to build and destroy all the loop optimization -+ infrastructure. -+ -+ The algorithm is relatively simple. For each single-exit loop, we -+ identify the loop index variable. If the loop index variable is -+ shorter than the word size, then we have a candidate for promotion. -+ We determine whether the scalar evolution of the loop index fits a -+ particular pattern (incremented by 1, compared against a -+ similarly-typed loop bound, and only modified by a single increment -+ within the loop), as well as examining the uses of the loop index to -+ ensure we are able to safely promote those uses (e.g. the loop index -+ must not be stored to memory or passed to function calls). If these -+ conditions are satisfied, we create an appropriate word-sized type -+ and replace all uses and defs of the loop index variable with the new -+ variable. */ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "tm.h" -+ -+#include "toplev.h" -+#include "rtl.h" -+#include "tm_p.h" -+#include "hard-reg-set.h" -+#include "obstack.h" -+#include "basic-block.h" -+#include "pointer-set.h" -+#include "intl.h" -+ -+#include "tree.h" -+#include "gimple.h" -+#include "hashtab.h" -+#include "diagnostic.h" -+#include "tree-flow.h" -+#include "tree-dump.h" -+#include "cfgloop.h" -+#include "flags.h" -+#include "timevar.h" -+#include "tree-pass.h" -+ -+struct promote_info { -+ /* The loop being analyzed. */ -+ struct loop *loop; -+ -+ /* The GIMPLE_COND controlling exit from the loop. */ -+ gimple exit_expr; -+ -+ /* The loop index variable's SSA_NAME that is defined in a phi node in -+ LOOP->HEADER. Note that this SSA_NAME may be different than the -+ one appearing in EXIT_EXPR. */ -+ tree loop_index_name; -+ -+ /* The bound of the loop. */ -+ tree loop_limit; -+ -+ /* Whether we've warned about things with -+ warn_unsafe_loop_optimizations. */ -+ bool warned; -+ -+ /* LOOP_INDEX_NAME's underlying VAR_DECL. */ -+ tree var_decl; -+ -+ /* The types to which defs/uses of LOOP_INDEX_NAME are cast via -+ NOP_EXPRs. */ -+ VEC(tree, heap) *cast_types; -+ -+ /* The number of times we have seen a cast to the corresponding type -+ (as determined by types_compatible_p) in CAST_TYPES. */ -+ VEC(int, heap) *cast_counts; -+ -+ /* Whether LOOP_INDEX_NAME is suitable for promotion. */ -+ bool can_be_promoted_p; -+ -+ /* If CAN_BE_PROMOTED_P, the promoted type. */ -+ tree promoted_type; -+ -+ /* If CAN_BE_PROMOTED_P, the promoted VAR_DECL. */ -+ tree promoted_var; -+}; -+ -+/* A set of `struct promote_info'. */ -+ -+static struct pointer_set_t *promotion_info; -+ -+/* A set of all potentially promotable SSA_NAMEs, used for quick -+decision-making during analysis. */ -+ -+static struct pointer_set_t *promotable_names; -+ -+/* A map from SSA_NAMEs to the VAR_DECL to which they will be -+ promoted. */ -+ -+static struct pointer_map_t *variable_map; -+ -+/* A set of the stmts that we have already rebuilt with promoted variables. */ -+ -+static struct pointer_set_t *promoted_stmts; -+ -+ -+/* Add CASTED to PI->CAST_TYPES if we haven't seen CASTED before. */ -+ -+static void -+add_casted_type (struct promote_info *pi, tree casted) -+{ -+ int i; -+ tree type; -+ -+ /* For this information to be useful later, CASTED must be wider than -+ the type of the variable. */ -+ if (TYPE_PRECISION (casted) <= TYPE_PRECISION (TREE_TYPE (pi->var_decl))) -+ return; -+ -+ for (i = 0; VEC_iterate (tree, pi->cast_types, i, type); i++) -+ if (types_compatible_p (casted, type)) -+ { -+ int c = VEC_index(int, pi->cast_counts, i); -+ VEC_replace(int, pi->cast_counts, i, ++c); -+ return; -+ } -+ -+ /* Haven't see the type before. */ -+ VEC_safe_push (tree, heap, pi->cast_types, casted); -+ VEC_safe_push (int, heap, pi->cast_counts, 1); -+} -+ -+/* Return the most-casted-to type in PI->CAST_TYPES. Return an -+ appropriately signed variant of size_type_node if the variable wasn't -+ cast in some fashion. */ -+ -+static tree -+choose_profitable_promoted_type (struct promote_info *pi) -+{ -+ int i; -+ int count; -+ tree type = NULL_TREE; -+ int maxuse = -1; -+ -+ for (i = 0; VEC_iterate (int, pi->cast_counts, i, count); i++) -+ if (count > maxuse) -+ { -+ maxuse = count; -+ type = VEC_index (tree, pi->cast_types, i); -+ } -+ -+ if (type == NULL_TREE) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, "Warning, failed to find upcast type for "); -+ print_generic_expr (dump_file, pi->loop_index_name, 0); -+ fprintf (dump_file, "\n"); -+ } -+ return (TYPE_UNSIGNED (TREE_TYPE (pi->var_decl)) -+ ? size_type_node -+ : signed_type_for (size_type_node)); -+ } -+ else -+ return signed_type_for (type); -+} -+ -+/* Intuit the loop index for LOOP from PHI. There must be a path that -+ only goes through NOP_EXPRs or CONVERT_EXPRs from the result of PHI -+ to one of the operands of COND. If such a path cannot be found, -+ return NULL_TREE. If LIMIT is not NULL and a path can be found, -+ store the other operand of COND into LIMIT. */ -+ -+static tree -+find_promotion_candidate_from_phi (struct loop *loop, gimple cond, -+ gimple phi, tree *limit) -+{ -+ tree op0, op1; -+ tree result, candidate; -+ -+ result = candidate = PHI_RESULT (phi); -+ /* Must be an integer variable. */ -+ if (TREE_CODE (TREE_TYPE (candidate)) != INTEGER_TYPE) -+ return NULL_TREE; -+ -+ op0 = gimple_cond_lhs (cond); -+ op1 = gimple_cond_rhs (cond); -+ -+ /* See if there's a path from CANDIDATE to an operand of COND. */ -+ while (true) -+ { -+ use_operand_p use; -+ imm_use_iterator iui; -+ gimple use_stmt = NULL; -+ -+ if (candidate == op0) -+ { -+ if (limit) *limit = op1; -+ break; -+ } -+ if (candidate == op1) -+ { -+ if (limit) *limit = op0; -+ break; -+ } -+ -+ /* Find a single use in the loop header. Give up if there's -+ multiple ones. */ -+ FOR_EACH_IMM_USE_FAST (use, iui, candidate) -+ { -+ gimple stmt = USE_STMT (use); -+ -+ if (gimple_bb (stmt) == loop->header) -+ { -+ if (use_stmt) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, "Rejecting "); -+ print_generic_expr (dump_file, candidate, 0); -+ fprintf (dump_file, " because it has multiple uses in the loop header (bb #%d).\n", -+ loop->header->index); -+ fprintf (dump_file, "first use: "); -+ print_gimple_stmt (dump_file, use_stmt, 0, 0); -+ fprintf (dump_file, "\nsecond use: "); -+ print_gimple_stmt (dump_file, stmt, 0, 0); -+ fprintf (dump_file, "\n(possibly more, but unanalyzed)\n"); -+ } -+ return NULL_TREE; -+ } -+ else -+ use_stmt = stmt; -+ } -+ } -+ -+ /* No uses in the loop header, bail. */ -+ if (use_stmt == NULL) -+ return NULL_TREE; -+ -+ if (gimple_code (use_stmt) != GIMPLE_ASSIGN -+ || TREE_CODE (gimple_assign_lhs (use_stmt)) != SSA_NAME -+ || (gimple_assign_rhs_code (use_stmt) != NOP_EXPR -+ && gimple_assign_rhs_code (use_stmt) != CONVERT_EXPR)) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, "Rejecting "); -+ print_generic_expr (dump_file, candidate, 0); -+ fprintf (dump_file, " because of use in "); -+ print_gimple_stmt (dump_file, use_stmt, 0, 0); -+ fprintf (dump_file, "\n"); -+ } -+ return NULL_TREE; -+ } -+ -+ candidate = gimple_assign_lhs (use_stmt); -+ } -+ -+ /* CANDIDATE is now what we believe to be the loop index variable. There -+ are two possibilities: -+ -+ - CANDIDATE is not the "true" loop index variable, but rather is a -+ promoted version of RESULT, done for purposes of satisfying a -+ language's semantics; -+ -+ - CANDIDATE is the "true" loop index variable. */ -+ if (!types_compatible_p (TREE_TYPE (result), TREE_TYPE (candidate))) -+ candidate = result; -+ -+ /* The type of candidate must be "short" to consider promoting it. */ -+ if (TREE_CODE (TREE_TYPE (candidate)) != INTEGER_TYPE -+ || TYPE_PRECISION (TREE_TYPE (candidate)) >= TYPE_PRECISION (size_type_node)) -+ return NULL_TREE; -+ -+ return candidate; -+} -+ -+/* Find the loop index variable of LOOP. LOOP's exit is controlled by -+ the COND_EXPR EXPR. IF we can't determine what the loop index -+ variable is, or EXPR does not appear to be analyzable, then return -+ NULL_TREE. */ -+ -+static tree -+find_promotion_candidate (struct loop *loop, gimple cond, tree *limit) -+{ -+ tree candidate = NULL_TREE; -+ gimple_stmt_iterator gsi; -+ -+ switch (gimple_cond_code (cond)) -+ { -+ case GT_EXPR: -+ case GE_EXPR: -+ case NE_EXPR: -+ case LT_EXPR: -+ case LE_EXPR: -+ break; -+ -+ default: -+ return NULL_TREE; -+ } -+ -+ /* We'd like to examine COND and intuit the loop index variable from -+ there. Instead, we're going to start from the phi nodes in BB and -+ attempt to work our way forwards to one of the operands of COND, -+ since starting from COND might yield an upcast loop index. If we -+ find multiple phi nodes whose results reach COND, then give up. */ -+ for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi)) -+ { -+ gimple phi = gsi_stmt (gsi); -+ tree t = find_promotion_candidate_from_phi (loop, cond, phi, limit); -+ -+ if (t == NULL_TREE) -+ continue; -+ else if (candidate == NULL_TREE) -+ candidate = t; -+ else -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, "Can't find a candidate from "); -+ print_gimple_stmt (dump_file, cond, 0, 0); -+ fprintf (dump_file, "\n because too many phi node results reach the condition.\n"); -+ } -+ return NULL_TREE; -+ } -+ } -+ -+ return candidate; -+} -+ -+/* Return true if X is something that could be promoted. */ -+ -+static bool -+could_be_promoted (tree x) -+{ -+ return (TREE_CODE (x) == INTEGER_CST -+ || (TREE_CODE (x) == SSA_NAME -+ && pointer_set_contains (promotable_names, x))); -+} -+ -+/* Examine the RHS of STMT's suitability with respect to being able to -+ promote VAR. */ -+ -+static bool -+check_rhs_for_promotability (struct promote_info *pi, tree var, gimple stmt, -+ bool is_assign) -+{ -+ enum tree_code subcode = gimple_assign_rhs_code (stmt); -+ -+ bool ok = true; -+ -+ switch (subcode) -+ { -+ case PLUS_EXPR: -+ case MINUS_EXPR: -+ case MULT_EXPR: -+ case EQ_EXPR: -+ case NE_EXPR: -+ case LT_EXPR: -+ case LE_EXPR: -+ case GT_EXPR: -+ case GE_EXPR: -+ { -+ tree op0 = gimple_assign_rhs1 (stmt); -+ tree op1 = gimple_assign_rhs2 (stmt); -+ -+ ok = ((op0 == var && could_be_promoted (op1)) -+ || (op1 == var && could_be_promoted (op0))); -+ break; -+ } -+ case COND_EXPR: -+ if (gimple_expr_type (stmt) == NULL -+ || gimple_expr_type (stmt) == void_type_node) -+ ok = true; -+ else -+ /* This is conservative; it's possible that these sorts of nodes -+ could be promoted, but we'd have to be very careful about -+ checking in which parts of the COND_EXPR the promotable -+ variable(s) are. */ -+ ok = false; -+ break; -+ case SSA_NAME: -+ { -+ tree expr = gimple_assign_rhs1 (stmt); -+ ok = (expr == var || could_be_promoted (expr)); -+ } -+ break; -+ case INTEGER_CST: -+ break; -+ case NOP_EXPR: -+ case CONVERT_EXPR: -+ if (!is_assign) -+ { -+ add_casted_type (pi, gimple_expr_type (stmt)); -+ break; -+ } -+ /* Fallthrough. */ -+ default: -+ ok = false; -+ break; -+ } -+ -+ return ok; -+} -+ -+/* Analyze the loop index VAR for promotability. The rules for -+ promotability are: -+ -+ For uses: -+ -+ - The underlying variable may be used in NOP_EXPRs. -+ -+ - The underlying variable may be used in simple arithmmetic -+ expressions so long as the other parts are potentially promotable -+ variables or constants (so we don't go willy-nilly on promoting -+ things). -+ -+ - The underlying variable may not be stored to memory. -+ -+ - All uses must occur inside the loop. -+ -+ For defs: -+ -+ - The underlying variable may not be loaded from memory; and -+ -+ - The underlying variable may only be formed from expressions -+ involving potentially promotable varibles or constants. -+ -+ Note that defs may occur outside of the loop; we do this to handle -+ initial conditions before entering the loop. */ -+ -+static void -+analyze_loop_index_uses (tree var, struct promote_info *pi) -+{ -+ imm_use_iterator iui; -+ use_operand_p use; -+ gimple bad_stmt = NULL; -+ const char *reason = NULL; -+ -+ FOR_EACH_IMM_USE_FAST (use, iui, var) -+ { -+ basic_block bb; -+ gimple use_stmt = USE_STMT (use); -+ -+ /* Uses must exist only within the loop. */ -+ bb = gimple_bb (use_stmt); -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, "Checking "); -+ print_gimple_stmt (dump_file, use_stmt, 0, 0); -+ fprintf (dump_file, "\n"); -+ } -+ -+ if (!flow_bb_inside_loop_p (pi->loop, bb)) -+ { -+ bad_stmt = use_stmt; -+ reason = " is involved in stmt outside loop "; -+ break; -+ } -+ -+ /* We cannot store the index to memory. */ -+ if (gimple_references_memory_p (use_stmt)) -+ { -+ bad_stmt = use_stmt; -+ reason = " is stored to memory in "; -+ break; -+ } -+ -+ if (gimple_code (use_stmt) == GIMPLE_CALL) -+ { -+ /* We cannot pass the variable to a function. */ -+ bad_stmt = use_stmt; -+ reason = " is passed to function in "; -+ break; -+ } -+ else if (gimple_code (use_stmt) == GIMPLE_ASSIGN) -+ { -+ tree lhs = gimple_assign_lhs (use_stmt); -+ -+ if (!check_rhs_for_promotability (pi, var, use_stmt, -+ /*is_assign=*/false)) -+ { -+ bad_stmt = use_stmt; -+ reason = " is involved in non-promotable expression "; -+ break; -+ } -+ else if ((TREE_CODE_CLASS (gimple_assign_rhs_code (use_stmt)) == tcc_binary -+ || gimple_assign_rhs_code (use_stmt) == SSA_NAME) -+ && !could_be_promoted (lhs)) -+ { -+ bad_stmt = use_stmt; -+ reason = " is being assigned to non-promotable variable "; -+ break; -+ } -+ } -+ else if (gimple_code (use_stmt) != GIMPLE_COND -+ && gimple_code (use_stmt) != GIMPLE_PHI) -+ { -+ /* Use of the variable in some statement we don't know how to -+ analyze. */ -+ bad_stmt = use_stmt; -+ reason = " is used in unanalyzable expression in "; -+ break; -+ } -+ } -+ -+ if (bad_stmt && reason) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, "Loop index "); -+ print_generic_expr (dump_file, var, 0); -+ fprintf (dump_file, "%s", reason); -+ print_gimple_stmt (dump_file, bad_stmt, 0, 0); -+ fprintf (dump_file, "\n"); -+ } -+ pi->can_be_promoted_p = false; -+ } -+} -+ -+/* Check that the uses and def of VAR, defined in STMT, conform to the -+ rules given above. */ -+ -+static bool -+analyze_loop_index (tree var, gimple stmt, void *data) -+{ -+ struct promote_info *pi = (struct promote_info *) data; -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, "Analyzing loop index "); -+ print_generic_expr (dump_file, var, 0); -+ fprintf (dump_file, " defined in "); -+ print_gimple_stmt (dump_file, stmt, 0, 0); -+ fprintf (dump_file, "\n"); -+ } -+ -+ /* Check the definition. */ -+ switch (gimple_code (stmt)) -+ { -+ case GIMPLE_PHI: -+ /* Phi nodes are OK. */ -+ break; -+ -+ case GIMPLE_ASSIGN: -+ if (!check_rhs_for_promotability (pi, var, stmt, -+ /*is_assign=*/true)) -+ break; -+ /* Fallthrough. */ -+ -+ default: -+ /* Something we can't handle or the variable is being loaded from -+ memory. */ -+ pi->can_be_promoted_p = false; -+ goto done; -+ } -+ -+ if (gimple_code (stmt) == GIMPLE_PHI) -+ { -+ unsigned int i; -+ -+ for (i = 0; i < gimple_phi_num_args (stmt); i++) -+ { -+ tree arg = PHI_ARG_DEF (stmt, i); -+ -+ if (TREE_CODE (arg) == SSA_NAME) -+ pointer_set_insert (promotable_names, arg); -+ } -+ -+ analyze_loop_index_uses (PHI_RESULT (stmt), pi); -+ } -+ else -+ analyze_loop_index_uses (var, pi); -+ -+ /* Only worth continuing if we think the loop index can be -+ promoted. */ -+ done: -+ if (dump_file) -+ { -+ fprintf (dump_file, "Done analyzing "); -+ print_generic_expr (dump_file, var, 0); -+ fprintf (dump_file, " defined in "); -+ print_gimple_stmt (dump_file, stmt, 0, 0); -+ fprintf (dump_file, "...%s to analyze\n\n", -+ pi->can_be_promoted_p ? "continuing" : "not continuing"); -+ } -+ return !pi->can_be_promoted_p; -+} -+ -+/* Determine whether T is an INTEGER_CST or a single-use SSA_NAME -+ defined as the result of a NOP_EXPR or CONVERT_EXPR. Return the -+ operand of the NOP_EXPR or CONVERT_EXPR if so. */ -+ -+static tree -+upcast_operand_p (tree t) -+{ -+ gimple def; -+ -+ if (TREE_CODE (t) == INTEGER_CST) -+ return t; -+ -+ if (TREE_CODE (t) != SSA_NAME -+ || !has_single_use (t)) -+ return NULL_TREE; -+ -+ def = SSA_NAME_DEF_STMT (t); -+ if (gimple_code (def) != GIMPLE_ASSIGN) -+ return NULL_TREE; -+ -+ if (gimple_assign_rhs_code (def) != CONVERT_EXPR -+ && gimple_assign_rhs_code (def) != NOP_EXPR) -+ return NULL_TREE; -+ -+ return gimple_assign_rhs1 (def); -+} -+ -+/* Check for the idiom: -+ -+ short x, y; -+ unsigned short x.2, y.2, tmp; -+ ... -+ x.2 = (unsigned short) x; -+ y.2 = (unsigned short) y; -+ tmp = x.2 + y.2; -+ x = (short) tmp; -+ -+ which is generated by convert for avoiding signed arithmetic -+ overflow. RHS is TMP in the above statement. If RHS is -+ defined via such an idiom, store x and y into *OP0 and *OP1, -+ respectively. We permit y.2 to be a constant if necessary. */ -+ -+static bool -+signed_arithmetic_overflow_idiom_p (tree rhs, tree *op0, tree *op1) -+{ -+ gimple op_stmt = SSA_NAME_DEF_STMT (rhs); -+ tree x2, y2; -+ bool yes = false; -+ enum tree_code code; -+ -+ if (!has_single_use (rhs) -+ || gimple_code (op_stmt) != GIMPLE_ASSIGN) -+ goto done; -+ -+ /* This could probably profitably be expanded to consider -+ MINUS_EXPR, MULT_EXPR, etc. */ -+ code = gimple_assign_rhs_code (op_stmt); -+ if (code != PLUS_EXPR) -+ goto done; -+ x2 = gimple_assign_rhs1 (op_stmt); -+ y2 = gimple_assign_rhs2 (op_stmt); -+ -+ x2 = upcast_operand_p (x2); -+ if (x2 == NULL_TREE) -+ goto done; -+ y2 = upcast_operand_p (y2); -+ if (y2 == NULL_TREE) -+ goto done; -+ -+ *op0 = x2; -+ *op1 = y2; -+ yes = true; -+ -+ done: -+ return yes; -+} -+ -+/* Simple wrapper around flow_bb_inside_loop_p that handles NULL -+ statements and initial definitions of variables. */ -+ -+static bool -+stmt_in_loop_p (gimple t, struct loop *loop) -+{ -+ basic_block bb; -+ -+ if (t == NULL) -+ return false; -+ -+ bb = gimple_bb (t); -+ if (bb == NULL) -+ return false; -+ -+ return flow_bb_inside_loop_p (loop, bb); -+} -+ -+/* The loop index should have a specific usage pattern: -+ -+ - It should be defined in a phi node with two incoming values: -+ -+ LI_phi = PHI (LI_out, LI_in) -+ -+ - One incoming value, LI_out, should be from outside the loop. -+ -+ - The other incoming value, LI_in, should be defined thusly: -+ -+ LI_in = LI_phi + increment -+ -+ - increment should be 1. We permit other increments with -+ -funsafe-loop-optimizations. -+ -+ - Finally, in the comparison to exit the loop, the loop index must be -+ compared against a variable that has a type at least as precise as -+ the loop index's type. For instance, something like: -+ -+ char limit; -+ short i; -+ -+ for (i = 0; i < limit; i++) ... -+ -+ would not be permitted. */ -+ -+static bool -+analyze_loop_index_definition_pattern (struct promote_info *pi) -+{ -+ gimple phi = SSA_NAME_DEF_STMT (pi->loop_index_name); -+ bool ok = false, warn = false; -+ tree in0, in1; -+ bool inside0, inside1; -+ gimple def0, def1; -+ tree op0, op1, increment = NULL_TREE; -+ -+ if (gimple_code (phi) != GIMPLE_PHI -+ || gimple_phi_num_args (phi) != 2) -+ goto done; -+ -+ in0 = PHI_ARG_DEF (phi, 0); -+ in1 = PHI_ARG_DEF (phi, 1); -+ -+ /* Figure out which value comes from outside the loop. */ -+ def0 = TREE_CODE (in0) == SSA_NAME ? SSA_NAME_DEF_STMT (in0) : NULL; -+ def1 = TREE_CODE (in1) == SSA_NAME ? SSA_NAME_DEF_STMT (in1) : NULL; -+ -+ inside0 = stmt_in_loop_p (def0, pi->loop); -+ inside1 = stmt_in_loop_p (def1, pi->loop); -+ -+ if (inside0 && inside1) -+ goto done; -+ else if (inside0) -+ { -+ tree t = in0; -+ gimple g; -+ in0 = in1; -+ in1 = t; -+ g = def0; -+ def0 = def1; -+ def1 = g; -+ } -+ else if (!inside1) -+ goto done; -+ -+ /* IN0 comes from outside the loop, IN1 from inside. Analyze IN1. */ -+ if (gimple_code (def1) != GIMPLE_ASSIGN) -+ goto done; -+ -+ switch (gimple_assign_rhs_code (def1)) -+ { -+ case CONVERT_EXPR: -+ case NOP_EXPR: -+ if (!signed_arithmetic_overflow_idiom_p (gimple_assign_rhs1 (def1), -+ &op0, &op1)) -+ goto done; -+ goto plus; -+ case PLUS_EXPR: -+ op0 = gimple_assign_rhs1 (def1); -+ op1 = gimple_assign_rhs2 (def1); -+ plus: -+ { -+ bool op0_li = op0 == PHI_RESULT (phi); -+ bool op1_li = op1 == PHI_RESULT (phi); -+ if (op0_li && op1_li) -+ /* This is weird, and definitely is not a case we can support -+ for promotion. */ -+ goto done; -+ else if (op0_li) -+ increment = op1; -+ else if (op1_li) -+ increment = op0; -+ else -+ goto done; -+ break; -+ } -+ default: -+ break; -+ } -+ -+ -+ /* Check that the exit condition for the loop is OK. */ -+ { -+ enum tree_code code = gimple_cond_code (pi->exit_expr); -+ -+ op0 = gimple_cond_lhs (pi->exit_expr); -+ op1 = gimple_cond_rhs (pi->exit_expr); -+ -+ if (op0 == pi->loop_limit) -+ { -+ tree t = op0; -+ op0 = op1; -+ op1 = t; -+ code = swap_tree_comparison (code); -+ } -+ -+ if (code != LT_EXPR && code != LE_EXPR) -+ goto done; -+ -+ if (!types_compatible_p (TREE_TYPE (pi->loop_index_name), -+ TREE_TYPE (pi->loop_limit))) -+ { -+ switch (TREE_CODE (pi->loop_limit)) -+ { -+ case INTEGER_CST: -+ if (!int_fits_type_p (pi->loop_limit, -+ TREE_TYPE (pi->loop_index_name))) -+ goto done; -+ break; -+ case SSA_NAME: -+ { -+ tree v = pi->loop_limit; -+ gimple def = SSA_NAME_DEF_STMT (v); -+ -+ /* Backtrack through CONVERT_EXPRs and/or NOP_EXPRs to -+ determine if the variables "started out" as the same -+ type. */ -+ while (gimple_code (def) == GIMPLE_ASSIGN) -+ { -+ enum tree_code rhs_code = gimple_assign_rhs_code (def); -+ -+ if (rhs_code != NOP_EXPR && rhs_code != CONVERT_EXPR) -+ break; -+ -+ v = gimple_assign_rhs1 (def); -+ def = SSA_NAME_DEF_STMT (v); -+ } -+ /* Permit comparisons between non-compatible types with -+ flag_unsafe_loop_optimizations, since we can assume the -+ loop index does not overflow. */ -+ if (types_compatible_p (TREE_TYPE (pi->loop_index_name), -+ TREE_TYPE (v)) -+ || flag_unsafe_loop_optimizations) -+ break; -+ /* Fallthrough. */ -+ default: -+ goto done; -+ } -+ } -+ } -+ } -+ -+ if (increment == NULL_TREE) -+ goto done; -+ if (TREE_CODE (increment) != INTEGER_CST -+ || compare_tree_int (increment, 1) != 0) -+ { -+ warn = true; -+ if (!flag_unsafe_loop_optimizations) -+ goto done; -+ } -+ -+ ok = true; -+ done: -+ if (warn && !pi->warned) -+ { -+ pi->warned = true; -+ /* We can promote unsigned indices only if -funsafe-loop-optimizations -+ is in effect, since the user might be depending on the modulo -+ wraparound behavior of unsigned types. */ -+ if (warn_unsafe_loop_optimizations) -+ { -+ const char *wording; -+ -+ wording = (flag_unsafe_loop_optimizations -+ ? N_("assuming that the loop counter does not overflow") -+ : N_("cannot optimize loop, the loop counter may overflow")); -+ warning (OPT_Wunsafe_loop_optimizations, "%s", gettext (wording)); -+ } -+ } -+ -+ return ok; -+} -+ -+/* Analyze the loop associated with PI_ to see if its loop index can be -+ promoted. */ -+ -+static bool -+analyze_loop (const void *pi_, void *data) -+{ -+ struct promote_info *pi = CONST_CAST (struct promote_info *, -+ (const struct promote_info *) pi_); -+ bool *changed = (bool *) data; -+ -+ /* We previously determined we can't promote this; go ahead and -+ continue iterating. */ -+ if (pi->loop_index_name == NULL_TREE) -+ return true; -+ -+ /* Assume we can always promote the loop index, even if it doesn't -+ exist. */ -+ pi->can_be_promoted_p = true; -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, "Analyzing "); -+ print_generic_expr (dump_file, pi->loop_index_name, 0); -+ fprintf (dump_file, "\n"); -+ } -+ -+ if (pi->loop_index_name -+ && analyze_loop_index_definition_pattern (pi)) -+ { -+ /* Clear any previously gathered information. */ -+ VEC_truncate (tree, pi->cast_types, 0); -+ VEC_truncate (int, pi->cast_counts, 0); -+ -+ walk_use_def_chains (pi->loop_index_name, analyze_loop_index, pi, false); -+ } -+ else -+ pi->can_be_promoted_p = false; -+ -+ /* If we determined the loop index is used in strange ways, clear it -+ so we don't examine it again. */ -+ if (!pi->can_be_promoted_p) -+ pi->loop_index_name = NULL_TREE; -+ -+ /* Let our caller know whether to re-do the analysis. */ -+ *changed = *changed || !pi->can_be_promoted_p; -+ /* Continue if PI is promotable. */ -+ return pi->can_be_promoted_p; -+} -+ -+/* Add PI_->LOOP_INDEX_NAME to the set of variables, DATA, that we are -+ considering for promotion. */ -+ -+static bool -+add_variable (const void *pi_, void *data ATTRIBUTE_UNUSED) -+{ -+ const struct promote_info *pi = (const struct promote_info *) pi_; -+ struct pointer_set_t *pset = (struct pointer_set_t *) data; -+ int presentp; -+ -+ if (pi->loop_index_name != NULL_TREE) -+ { -+ presentp = pointer_set_insert (pset, pi->loop_index_name); -+ gcc_assert (!presentp); -+ } -+ -+ /* Continue traversal. */ -+ return true; -+} -+ -+/* For each promotable variable: -+ -+ - create a new, promoted VAR_DECL; -+ -+ - walk through all the uses and defs and create new statements using -+ the promoted variables. We don't create new phi nodes; post-pass -+ SSA update will handle those for us. */ -+ -+/* Make dump files readable. */ -+#define PROMOTED_VAR_SUFFIX ".promoted" -+ -+/* Create a variable NAME with TYPE and do the necessary work to inform -+ the SSA machinery about it. */ -+ -+static tree -+create_pli_var (tree type, char *name) -+{ -+ tree var = create_tmp_var (type, name); -+ create_var_ann (var); -+ mark_sym_for_renaming (var); -+ add_referenced_var (var); -+ return var; -+} -+ -+/* Associate the SSA_NAME VAR with the promoted variable DATA. */ -+ -+static bool -+associate_name_with_var (tree var, gimple def_stmt, void *data) -+{ -+ tree promoted_var = (tree) data; -+ void **p; -+ -+ gcc_assert (promoted_var != NULL_TREE); -+ -+ if (gimple_code (def_stmt) == GIMPLE_PHI) -+ var = PHI_RESULT (def_stmt); -+ -+ p = pointer_map_insert (variable_map, var); -+ -+ if (!*p) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, "Associating "); -+ print_generic_expr (dump_file, var, 0); -+ fprintf (dump_file, " with "); -+ print_generic_expr (dump_file, promoted_var, 0); -+ fprintf (dump_file, "\n\n"); -+ } -+ *(tree *)p = promoted_var; -+ } -+ -+ /* Continue traversal. */ -+ return false; -+} -+ -+/* Create a promoted variable for the variable from PI_. */ -+ -+static bool -+create_promoted_variable (const void *pi_, void *data ATTRIBUTE_UNUSED) -+{ -+ struct promote_info *pi = CONST_CAST (struct promote_info *, -+ (const struct promote_info *) pi_); -+ -+ if (pi->can_be_promoted_p) -+ { -+ tree type = choose_profitable_promoted_type (pi); -+ tree orig_name = DECL_NAME (pi->var_decl); -+ size_t id_len = IDENTIFIER_LENGTH (orig_name); -+ size_t name_len = id_len + strlen (PROMOTED_VAR_SUFFIX) + 1; -+ char *name; -+ -+ name = (char *) alloca (name_len); -+ strcpy (name, IDENTIFIER_POINTER (orig_name)); -+ strcpy (name + id_len, PROMOTED_VAR_SUFFIX); -+ -+ pi->promoted_type = type; -+ pi->promoted_var = create_pli_var (type, name); -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, "Created new variable "); -+ print_generic_expr (dump_file, pi->promoted_var, 0); -+ fprintf (dump_file, " to stand in for "); -+ print_generic_expr (dump_file, pi->loop_index_name, 0); -+ fprintf (dump_file, "\n\n"); -+ } -+ -+ walk_use_def_chains (pi->loop_index_name, -+ associate_name_with_var, -+ pi->promoted_var, false); -+ } -+ -+ /* Continue traversal. */ -+ return true; -+} -+ -+/* Rebuild T with newly promoted variables; STMT is the original -+ statement in which T appeared and may be equivalent to T. TYPE is -+ non-null when rebuilding the rhs of a GIMPLE_ASSIGN and indicates the -+ type of the lhs. */ -+ -+static tree -+rebuild_tree_with_promotion (tree t, gimple stmt, tree type, -+ gimple_stmt_iterator gsi, -+ struct promote_info *pi) -+{ -+ tree op0, op1; -+ -+ switch (TREE_CODE (t)) -+ { -+ case NOP_EXPR: -+ case CONVERT_EXPR: -+ { -+ tree pvar = rebuild_tree_with_promotion (TREE_OPERAND (t, 0), stmt, type, gsi, pi); -+ -+ if (types_compatible_p (type, TREE_TYPE (pvar))) -+ return pvar; -+ else -+ return build1 (TREE_CODE (t), type, pvar); -+ } -+ case INTEGER_CST: -+ { -+ return build_int_cst_wide (pi->promoted_type, -+ TREE_INT_CST_LOW (t), -+ TREE_INT_CST_HIGH (t)); -+ } -+ case COND_EXPR: -+ { -+ tree orig_op0 = TREE_OPERAND (t, 0); -+ op0 = rebuild_tree_with_promotion (orig_op0, stmt, type, gsi, pi); -+ gcc_assert (orig_op0 != op0); -+ TREE_OPERAND (t, 0) = op0; -+ return t; -+ } -+ case PLUS_EXPR: -+ case MINUS_EXPR: -+ case MULT_EXPR: -+ type = pi->promoted_type; -+ goto binary_expr; -+ case EQ_EXPR: -+ case NE_EXPR: -+ case LT_EXPR: -+ case LE_EXPR: -+ case GT_EXPR: -+ case GE_EXPR: -+ type = TREE_TYPE (t); -+ binary_expr: -+ op0 = TREE_OPERAND (t, 0); -+ op1 = TREE_OPERAND (t, 1); -+ op0 = rebuild_tree_with_promotion (op0, stmt, type, gsi, pi); -+ op1 = rebuild_tree_with_promotion (op1, stmt, type, gsi, pi); -+ return build2 (TREE_CODE (t), type, op0, op1); -+ case SSA_NAME: -+ { -+ void **p = pointer_map_contains (variable_map, t); -+ -+ if (p == NULL) -+ { -+ /* This is unexpected, but it does happen if we were dealing -+ with COND_EXPRs and such. Just go ahead and create a -+ temporary for it. */ -+ if (types_compatible_p (TREE_TYPE (t), pi->promoted_type) -+ || SSA_NAME_DEF_STMT (t) == stmt) -+ return t; -+ else -+ goto insert_cast; -+ } -+ else -+ return *(tree *)p; -+ } -+ case VAR_DECL: -+ return t; -+ default: -+ insert_cast: -+ { -+ gimple cast; -+ tree tmp, nop; -+ tree to_upcast = t; -+ -+ /* If we are dealing with a memory reference, then we can't have -+ wrap it in a NOP_EXPR; we need to load the value from memory -+ first, then convert it. */ -+ if (!is_gimple_reg (to_upcast)) -+ { -+ tree tmp = create_pli_var (TREE_TYPE (to_upcast), -+ CONST_CAST (char *, "loadtmp")); -+ gimple stmt = gimple_build_assign (tmp, to_upcast); -+ gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); -+ to_upcast = tmp; -+ } -+ -+ tmp = create_pli_var (pi->promoted_type, -+ CONST_CAST (char *, "promotetmp")); -+ nop = build1 (NOP_EXPR, pi->promoted_type, to_upcast); -+ cast = gimple_build_assign (tmp, nop); -+ if (dump_file) -+ { -+ fprintf (dump_file, "Inserting cast "); -+ print_gimple_stmt (dump_file, cast, 0, 0); -+ fprintf (dump_file, " prior to "); -+ print_gimple_stmt (dump_file, stmt, 0, 0); -+ fprintf (dump_file, "\n"); -+ } -+ gsi_insert_before (&gsi, cast, GSI_SAME_STMT); -+ return tmp; -+ } -+ } -+} -+ -+/* Split E and place STMT in the block created by doing so. */ -+ -+static void -+insert_along_edge (gimple stmt, edge e) -+{ -+ basic_block bb = split_edge (e); -+ -+ gimple_set_bb (stmt, bb); -+ set_bb_seq (bb, gimple_seq_alloc_with_stmt (stmt)); -+} -+ -+/* Rebuild STMT, which contains uses or a def of the promotable variable -+ associated with PI. */ -+ -+static void -+rebuild_with_promotion (gimple stmt, struct promote_info *pi) -+{ -+ gimple_stmt_iterator gsi; -+ -+ if (pointer_set_insert (promoted_stmts, stmt)) -+ return; -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, "Rebuilding stmt "); -+ print_gimple_stmt (dump_file, stmt, 0, 0); -+ fprintf (dump_file, "\n"); -+ } -+ -+ gsi = gsi_for_stmt (stmt); -+ -+ switch (gimple_code (stmt)) -+ { -+ case GIMPLE_ASSIGN: -+ { -+ enum tree_code subcode = gimple_assign_rhs_code (stmt); -+ enum tree_code newcode = subcode; -+ tree lhs = gimple_assign_lhs (stmt); -+ tree rhs1 = gimple_assign_rhs1 (stmt); -+ tree rhs2 = gimple_assign_rhs2 (stmt); -+ tree x, y; -+ void **v; -+ -+ /* If we are defining a promotable variable, check for special -+ idioms. */ -+ v = pointer_map_contains (variable_map, lhs); -+ if (v != NULL -+ && *(tree *)v == pi->promoted_var -+ && (subcode == NOP_EXPR || subcode == CONVERT_EXPR) -+ && signed_arithmetic_overflow_idiom_p (rhs1, &x, &y)) -+ { -+ void **xp; -+ void **yp; -+ if (TYPE_PRECISION (TREE_TYPE (rhs1)) -+ >= TYPE_PRECISION (pi->promoted_type)) -+ goto done; -+ -+ /* It's possible that we've already promoted the operands of -+ one or both of the NOP_EXPRs. In that case, we can -+ bypass the logic below and go straight to rebuilding the -+ rhs that we really want to transform. */ -+ if (TREE_CODE (x) == VAR_DECL -+ || TREE_CODE (y) == VAR_DECL) -+ goto build_fake; -+ xp = pointer_map_contains (variable_map, x); -+ yp = pointer_map_contains (variable_map, y); -+ -+ /* Nothing to see here. */ -+ if (!types_compatible_p (TREE_TYPE (x), -+ TREE_TYPE (y)) -+ || (xp == NULL && yp == NULL)) -+ goto done; -+ x = (xp == NULL ? NULL_TREE : *(tree *)xp); -+ y = (yp == NULL ? NULL_TREE : *(tree *)yp); -+ -+ if (x != pi->promoted_var && y != pi->promoted_var) -+ goto done; -+ -+ build_fake: -+ newcode = PLUS_EXPR; -+ rhs1 = x; -+ rhs2 = y; -+ if (dump_file) -+ { -+ fprintf (dump_file, "Substituting "); -+ print_generic_expr (dump_file, x, 0); -+ fprintf (dump_file, " + "); -+ print_generic_expr (dump_file, y, 0); -+ fprintf (dump_file, " for rhs of original statement\n"); -+ } -+ -+ done: -+ ; -+ } -+ -+ lhs = rebuild_tree_with_promotion (lhs, stmt, NULL, gsi, pi); -+ rhs1 = rebuild_tree_with_promotion (rhs1, stmt, NULL, gsi, pi); -+ if (rhs2) -+ rhs2 = rebuild_tree_with_promotion (rhs2, stmt, NULL, gsi, pi); -+ -+ if (newcode != subcode) -+ { -+ gimple newstmt = gimple_build_assign_with_ops (newcode, -+ lhs, rhs1, rhs2); -+ gsi_replace (&gsi, newstmt, true); -+ stmt = newstmt; -+ } -+ else -+ { -+ gimple_assign_set_lhs (stmt, lhs); -+ gimple_assign_set_rhs1 (stmt, rhs1); -+ if (rhs2) -+ gimple_assign_set_rhs2 (stmt, rhs2); -+ } -+ } -+ break; -+ case GIMPLE_COND: -+ { -+ tree lhs = gimple_cond_lhs (stmt); -+ tree rhs = gimple_cond_rhs (stmt); -+ -+ lhs = rebuild_tree_with_promotion (lhs, stmt, NULL, gsi, pi); -+ rhs = rebuild_tree_with_promotion (rhs, stmt, NULL, gsi, pi); -+ -+ gimple_cond_set_lhs (stmt, lhs); -+ gimple_cond_set_rhs (stmt, rhs); -+ } -+ break; -+ case GIMPLE_PHI: -+ { -+ unsigned int i; -+ bool promoted_result = could_be_promoted (PHI_RESULT (stmt)); -+ -+ for (i = 0; i < gimple_phi_num_args (stmt); i++) -+ { -+ tree var = gimple_phi_arg_def (stmt, i); -+ edge e = gimple_phi_arg_edge (stmt, i); -+ gimple assign = NULL; -+ -+ if (TREE_CODE (var) == INTEGER_CST && promoted_result) -+ { -+ tree cst = build_int_cst_wide (pi->promoted_type, -+ TREE_INT_CST_LOW (var), -+ TREE_INT_CST_HIGH (var)); -+ -+ assign = gimple_build_assign (pi->promoted_var, cst); -+ insert_along_edge (assign, e); -+ } -+ else if (TREE_CODE (var) == SSA_NAME -+ && SSA_NAME_VAR (var) == pi->var_decl -+ && !promoted_result) -+ { -+ tree t = create_pli_var (TREE_TYPE (PHI_RESULT (stmt)), -+ CONST_CAST (char *, "promotetmp")); -+ tree name; -+ assign = gimple_build_assign_with_ops (CONVERT_EXPR, -+ t, pi->promoted_var, -+ NULL_TREE); -+ -+ name = make_ssa_name (t, assign); -+ gimple_assign_set_lhs (assign, name); -+ -+ insert_along_edge (assign, e); -+ SET_PHI_ARG_DEF (stmt, i, name); -+ } -+ } -+ } -+ break; -+ default: -+ gcc_unreachable (); -+ } -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, "Converted stmt "); -+ print_gimple_stmt (dump_file, stmt, 0, 0); -+ fprintf (dump_file, "\n\n"); -+ } -+ update_stmt (stmt); -+} -+ -+/* Helper function for promote_variable that walks over use/def -+ chains. */ -+ -+static bool -+promote_variable_1 (tree var, gimple stmt, void *data) -+{ -+ struct promote_info *pi = (struct promote_info *) data; -+ imm_use_iterator imi; -+ gimple use_stmt; -+ -+ rebuild_with_promotion (stmt, pi); -+ -+ if (gimple_code (stmt) == GIMPLE_PHI) -+ var = PHI_RESULT (stmt); -+ -+ if (could_be_promoted (var)) -+ FOR_EACH_IMM_USE_STMT (use_stmt, imi, var) -+ { -+ rebuild_with_promotion (use_stmt, pi); -+ } -+ -+ return false; -+} -+ -+/* Convert all uses and defs of PI_->LOOP_INDEX_NAME as linked by -+ use-def chains to uses and defs of PI_->PROMOTED_VAR. */ -+ -+static bool -+promote_variable (const void *pi_, void *data ATTRIBUTE_UNUSED) -+{ -+ const struct promote_info *pi = (const struct promote_info *) pi_; -+ -+ if (pi->can_be_promoted_p) -+ { -+ walk_use_def_chains (pi->loop_index_name, promote_variable_1, -+ CONST_CAST (struct promote_info *, pi), false); -+ } -+ -+ /* Continue traversal. */ -+ return true; -+} -+ -+/* Free PI_ and its associated data. */ -+ -+static bool -+free_pi_entries (const void *pi_, void *data ATTRIBUTE_UNUSED) -+{ -+ struct promote_info *pi = CONST_CAST (struct promote_info *, -+ (const struct promote_info *) pi_); -+ -+ VEC_free (tree, heap, pi->cast_types); -+ VEC_free (int, heap, pi->cast_counts); -+ free (pi); -+ -+ /* Continue traversal. */ -+ return true; -+} -+ -+/* Collect information about variables that we believe to be loop -+ indices in PROMOTION_INFO. */ -+ -+static void -+collect_promotion_candidates (void) -+{ -+ loop_iterator li; -+ struct loop *loop; -+ -+ FOR_EACH_LOOP (li, loop, 0) -+ { -+ basic_block header = loop->header; -+ gimple exit_cond = last_stmt (header); -+ -+ if (exit_cond && gimple_code (exit_cond) == GIMPLE_COND) -+ { -+ tree loop_index; -+ tree limit = NULL_TREE; -+ tree decl; -+ struct promote_info *pi; -+ -+ loop_index = find_promotion_candidate (loop, exit_cond, &limit); -+ if (loop_index == NULL_TREE) -+ continue; -+ decl = SSA_NAME_VAR (loop_index); -+ if (TREE_ADDRESSABLE (decl)) -+ continue; -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, "Found loop index "); -+ print_generic_expr (dump_file, loop_index, 0); -+ fprintf (dump_file, " involved in "); -+ print_gimple_stmt (dump_file, exit_cond, 0, 0); -+ fprintf (dump_file, "\n\n"); -+ } -+ -+ pi = XCNEW (struct promote_info); -+ pi->loop = loop; -+ pi->exit_expr = exit_cond; -+ pi->loop_index_name = loop_index; -+ pi->loop_limit = limit; -+ pi->var_decl = decl; -+ /* We think so, anyway... */ -+ pi->can_be_promoted_p = true; -+ pointer_set_insert (promotion_info, pi); -+ } -+ else if (dump_file) -+ { -+ fprintf (dump_file, "\nSkipping analysis of loop %d (header bb #%d)\n", -+ loop->num, loop->header->index); -+ if (exit_cond) -+ { -+ fprintf (dump_file, "Exit condition was "); -+ print_gimple_stmt (dump_file, exit_cond, 0, 0); -+ fprintf (dump_file, "\n"); -+ } -+ } -+ } -+} -+ -+/* Free memory associated with global variables that we used. */ -+ -+static void -+pli_cleanup (void) -+{ -+ if (promoted_stmts) -+ { -+ pointer_set_destroy (promoted_stmts); -+ promoted_stmts = NULL; -+ } -+ if (variable_map) -+ { -+ pointer_map_destroy (variable_map); -+ variable_map = NULL; -+ } -+ if (promotable_names) -+ { -+ pointer_set_destroy (promotable_names); -+ promotable_names = NULL; -+ } -+ if (promotion_info) -+ { -+ pointer_set_traverse (promotion_info, free_pi_entries, NULL); -+ pointer_set_destroy (promotion_info); -+ promotion_info = NULL; -+ } -+} -+ -+/* The guts of the pass. */ -+ -+static unsigned int -+promote_short_indices (void) -+{ -+ bool did_something = false; -+ bool changed; -+ size_t max_iterations, i, n_promoted; -+ -+ promotion_info = pointer_set_create (); -+ collect_promotion_candidates (); -+ -+ if (dump_file) -+ fprintf (dump_file, "Found %d candidates for promotion\n", -+ (int) pointer_set_n_elements (promotion_info)); -+ -+ /* Nothing to do. */ -+ if (pointer_set_n_elements (promotion_info) == 0) -+ goto cleanup; -+ -+ /* We have information about which variables are loop index variables. -+ We now need to determine the promotability of the loop indices. -+ Since the promotability of loop indices may depend on other loop -+ indices, we need to repeat this until we reach a fixed point. */ -+ changed = true; -+ max_iterations = pointer_set_n_elements (promotion_info); -+ i = 0; -+ -+ promotable_names = pointer_set_create (); -+ -+ while (changed) -+ { -+ changed = false; -+ pointer_set_clear (promotable_names); -+ pointer_set_traverse (promotion_info, add_variable, -+ promotable_names); -+ n_promoted = pointer_set_n_elements (promotable_names); -+ -+ if (dump_file) -+ fprintf (dump_file, "\nIteration %d, have %d variables to consider\n", -+ (int) i, (int) n_promoted); -+ -+ if (n_promoted == 0) -+ break; -+ gcc_assert (i < max_iterations); -+ pointer_set_traverse (promotion_info, analyze_loop, &changed); -+ i++; -+ } -+ -+ if (dump_file) -+ fprintf (dump_file, "Promoting %d variables\n", -+ (int) n_promoted); -+ -+ if (n_promoted != 0) -+ { -+ did_something = true; -+ variable_map = pointer_map_create (); -+ promoted_stmts = pointer_set_create (); -+ pointer_set_traverse (promotion_info, create_promoted_variable, NULL); -+ pointer_set_traverse (promotion_info, promote_variable, NULL); -+ } -+ -+ cleanup: -+ pli_cleanup (); -+ return did_something ? TODO_update_ssa : 0; -+} -+ -+/* Entry point for the short loop index promotion pass. */ -+ -+static unsigned int -+tree_short_index_promotion (void) -+{ -+ unsigned int changed = 0; -+ -+ /* Initialize all the necessary loop infrastructure. */ -+ loop_optimizer_init (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES | LOOPS_HAVE_RECORDED_EXITS); -+ add_noreturn_fake_exit_edges (); -+ connect_infinite_loops_to_exit (); -+ -+ if (number_of_loops () > 1) -+ changed = promote_short_indices (); -+ -+ /* Tear down loop optimization infrastructure. */ -+ remove_fake_exit_edges (); -+ free_numbers_of_iterations_estimates (); -+ loop_optimizer_finalize (); -+ -+ return changed; -+} -+ -+static bool -+gate_short_index_promotion (void) -+{ -+ return optimize > 0 && flag_promote_loop_indices; -+} -+ -+struct gimple_opt_pass pass_promote_indices = -+{ -+ { -+ GIMPLE_PASS, -+ "promoteshort", /* name */ -+ gate_short_index_promotion, /* gate */ -+ tree_short_index_promotion, /* execute */ -+ NULL, /* sub */ -+ NULL, /* next */ -+ 0, /* static_pass_number */ -+ TV_TREE_LOOP_PROMOTE, /* tv_id */ -+ PROP_cfg | PROP_ssa, /* properties_required */ -+ 0, /* properties_provided */ -+ 0, /* properties_destroyed */ -+ 0, /* todo_flags_start */ -+ TODO_dump_func | TODO_verify_loops -+ | TODO_ggc_collect /* todo_flags_finish */ -+ } -+}; ---- a/gcc/tree-ssa-pre.c -+++ b/gcc/tree-ssa-pre.c -@@ -104,6 +104,10 @@ - In order to make it fully redundant, we insert the expression into - the predecessors where it is not available, but is ANTIC. - -+ When optimizing for size, we only eliminate the partial redundancy -+ if we need to insert in only one predecessor. This avoids almost -+ completely the code size increase that PRE usually causes. -+ - For the partial anticipation case, we only perform insertion if it - is partially anticipated in some block, and fully available in all - of the predecessors. -@@ -429,6 +433,7 @@ - static void bitmap_value_insert_into_set (bitmap_set_t, pre_expr); - static void bitmap_value_replace_in_set (bitmap_set_t, pre_expr); - static void bitmap_set_copy (bitmap_set_t, bitmap_set_t); -+static void bitmap_set_and (bitmap_set_t, bitmap_set_t); - static bool bitmap_set_contains_value (bitmap_set_t, unsigned int); - static void bitmap_insert_into_set (bitmap_set_t, pre_expr); - static void bitmap_insert_into_set_1 (bitmap_set_t, pre_expr, bool); -@@ -2988,13 +2993,6 @@ - tree temp; - gimple phi; - -- if (dump_file && (dump_flags & TDF_DETAILS)) -- { -- fprintf (dump_file, "Found partial redundancy for expression "); -- print_pre_expr (dump_file, expr); -- fprintf (dump_file, " (%04d)\n", val); -- } -- - /* Make sure we aren't creating an induction variable. */ - if (block->loop_depth > 0 && EDGE_COUNT (block->preds) == 2 - && expr->kind != REFERENCE) -@@ -3192,6 +3190,47 @@ - } - - -+/* Indicate if, when optimizing for speed, it is appropriate to make -+ INSERTS_NEEDED insertions in order to make EXPR in BLOCK redundant. */ -+static bool -+ppre_n_insert_for_speed_p (pre_expr expr, basic_block block, -+ unsigned int inserts_needed) -+{ -+ /* The more expensive EXPR is, the more we should be prepared to insert -+ in the predecessors of BLOCK to make EXPR fully redundant. -+ For now, only recognize AND, OR, XOR, PLUS and MINUS of a multiple-use -+ SSA_NAME with a constant as cheap. */ -+ int cost; -+ -+ if (flag_tree_pre_partial_partial_obliviously) -+ return true; -+ if (expr->kind == NARY) -+ { -+ vn_nary_op_t nary = PRE_EXPR_NARY (expr); -+ switch (nary->opcode) -+ { -+ tree name, cnst; -+ case BIT_AND_EXPR: case BIT_IOR_EXPR: case BIT_XOR_EXPR: -+ case PLUS_EXPR: case MINUS_EXPR: -+ -+ gcc_assert (nary->length == 2); -+ name = nary->op[0]; -+ cnst = nary->op[1]; -+ if (TREE_CODE (name) != SSA_NAME || has_single_use (name)) -+ return true; -+ if (!is_gimple_min_invariant (cnst)) -+ return true; -+ cost = 1; -+ break; -+ default: -+ return true; -+ } -+ } -+ else -+ return true; -+ return EDGE_COUNT (block->preds) * cost >= inserts_needed; -+ -+} - - /* Perform insertion of partially redundant values. - For BLOCK, do the following: -@@ -3226,6 +3265,7 @@ - pre_expr *avail; - unsigned int val; - bool by_some = false; -+ unsigned int inserts_needed = 0; - bool cant_insert = false; - bool all_same = true; - pre_expr first_s = NULL; -@@ -3280,6 +3320,7 @@ - { - avail[bprime->index] = eprime; - all_same = false; -+ inserts_needed++; - } - else - { -@@ -3289,6 +3330,11 @@ - first_s = edoubleprime; - else if (!pre_expr_eq (first_s, edoubleprime)) - all_same = false; -+ /* If the available value is not a NAME, PREing this -+ value will probably result in a copy on the edge -+ to assign the expression to a register. */ -+ if (edoubleprime->kind != NAME) -+ inserts_needed++; - } - } - /* If we can insert it, it's not the same value -@@ -3297,9 +3343,27 @@ - partially redundant. */ - if (!cant_insert && !all_same && by_some && dbg_cnt (treepre_insert)) - { -- if (insert_into_preds_of_block (block, get_expression_id (expr), -- avail)) -- new_stuff = true; -+ if (dump_file && (dump_flags & TDF_DETAILS)) -+ { -+ fprintf (dump_file, -+ "Found partial redundancy for expression "); -+ print_pre_expr (dump_file, expr); -+ fprintf (dump_file, " (%04d)\n", get_expr_value_id (expr)); -+ } -+ -+ /* If optimizing for size, insert at most one -+ new expression to avoid increasing code size. */ -+ if (optimize_function_for_speed_p (cfun) -+ ? 1 : EDGE_COUNT (block->preds) - inserts_needed == 1) -+ new_stuff |= -+ insert_into_preds_of_block (block, -+ get_expression_id (expr), -+ avail); -+ else if (dump_file && (dump_flags & TDF_DETAILS)) -+ fprintf (dump_file, "Not inserting (optimizing for %s)\n", -+ optimize_function_for_speed_p (cfun) -+ ? "speed" : "size"); -+ - } - /* If all edges produce the same value and that value is - an invariant, then the PHI has the same value on all -@@ -3428,9 +3492,28 @@ - if (!cant_insert && by_all && dbg_cnt (treepre_insert)) - { - pre_stats.pa_insert++; -- if (insert_into_preds_of_block (block, get_expression_id (expr), -- avail)) -- new_stuff = true; -+ if (dump_file && (dump_flags & TDF_DETAILS)) -+ { -+ fprintf (dump_file, -+ "Found partial redundancy for expression "); -+ print_pre_expr (dump_file, expr); -+ fprintf (dump_file, " (%04d)\n", get_expr_value_id (expr)); -+ } -+ /* Assuming the expression is 50% anticipatable, we have to -+ multiply the number of insertions needed by two for a cost -+ comparison. */ -+ if (!optimize_function_for_speed_p (cfun) -+ || ppre_n_insert_for_speed_p (expr, block, -+ 2 * EDGE_COUNT (block->preds))) -+ new_stuff |= -+ insert_into_preds_of_block (block, -+ get_expression_id (expr), -+ avail); -+ else if (dump_file && (dump_flags & TDF_DETAILS)) -+ fprintf (dump_file, "Not inserting (optimizing for %s)\n", -+ optimize_function_for_speed_p (cfun) -+ ? "speed" : "size"); -+ - } - free (avail); - } -@@ -3471,7 +3554,9 @@ - if (!single_pred_p (block)) - { - new_stuff |= do_regular_insertion (block, dom); -- if (do_partial_partial) -+ /* Don't bother with partial-partial redundancies when -+ optimizing for size. */ -+ if (do_partial_partial && ! optimize_function_for_size_p (cfun)) - new_stuff |= do_partial_partial_insertion (block, dom); - } - } -@@ -4220,11 +4305,11 @@ - only wants to do full redundancy elimination. */ - - static unsigned int --execute_pre (bool do_fre ATTRIBUTE_UNUSED) -+execute_pre (bool do_fre) - { - unsigned int todo = 0; - -- do_partial_partial = optimize > 2; -+ do_partial_partial = flag_tree_pre_partial_partial; - - /* This has to happen before SCCVN runs because - loop_optimizer_init may create new phis, etc. */ -@@ -4297,19 +4382,20 @@ - return todo; - } - --/* Gate and execute functions for PRE. */ -+/* Gate and execute functions for FRE/PRE. */ - - static unsigned int - do_pre (void) - { -- return TODO_rebuild_alias | execute_pre (false); -+ return TODO_rebuild_alias -+ | execute_pre (! flag_tree_pre); - } - - static bool - gate_pre (void) - { -- /* PRE tends to generate bigger code. */ -- return flag_tree_pre != 0 && optimize_function_for_speed_p (cfun); -+ /* Run FRE even if we don't run PRE. */ -+ return (flag_tree_fre || flag_tree_pre); - } - - struct gimple_opt_pass pass_pre = ---- /dev/null -+++ b/gcc/tree-ssa-remove-local-statics.c -@@ -0,0 +1,868 @@ -+/* Local static variable elimination pass. -+ Copyright (C) 2007 Free Software Foundation, Inc. -+ Contributed by Nathan Froyd <froydnj@codesourcery.com> -+ -+This file is part of GCC. -+ -+GCC is free software; you can redistribute it and/or modify it -+under the terms of the GNU General Public License as published by the -+Free Software Foundation; either version 3, or (at your option) any -+later version. -+ -+GCC is distributed in the hope that it will be useful, but WITHOUT -+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+for more details. -+ -+You should have received a copy of the GNU General Public License -+along with GCC; see the file COPYING3. If not see -+<http://www.gnu.org/licenses/>. */ -+ -+/* Converting static function-local variables to automatic variables. -+ -+ The motivating example is a function like: -+ -+ void -+ foo (unsigned n) -+ { -+ static int var; -+ unsigned i; -+ -+ for (i = 0; i != n; i++) -+ { -+ var = ... -+ -+ do other things with var... -+ } -+ } -+ -+ Because VAR is static, doing things like code motion to loads and -+ stores of VAR is difficult. Furthermore, accesses to VAR are -+ inefficient. This pass aims to recognize the cases where it is not -+ necessary for VAR to be static and modify the code so that later -+ passes will do the appropriate optimizations. -+ -+ The criteria for a static function-local variable V in a function F -+ being converted to an automatic variable are: -+ -+ 1. F does not call setjmp; and -+ 2. V's address is never taken; and -+ 3. V is not declared volatile; and -+ 4. V is not used in any nested function; -+ 5. V is not an aggregate value (union, struct, array, etc.); and -+ 6. Every use of V is defined along all paths leading to the use. -+ -+ NOTE: For ease of implementation, we currently treat a function call -+ as killing all previous definitions of static variables, since we -+ could have: -+ -+ static void -+ foo (...) -+ { -+ static int x; -+ -+ x = ...; (1) -+ -+ f (...); (2) -+ -+ ... = x; (3) -+ } -+ -+ The use at (3) needs to pick up a possible definition made by the -+ call at (2). If the call at (2) does not call back into 'foo', -+ then the call is not a killing call. We currently treat it as -+ though it is. */ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "tm.h" -+ -+#include "rtl.h" -+#include "tm_p.h" -+#include "hard-reg-set.h" -+#include "obstack.h" -+#include "basic-block.h" -+ -+#include "tree.h" -+#include "gimple.h" -+#include "hashtab.h" -+#include "diagnostic.h" -+#include "tree-flow.h" -+#include "tree-dump.h" -+#include "flags.h" -+#include "timevar.h" -+#include "tree-pass.h" -+ -+struct rls_decl_info -+{ -+ /* The variable declaration. */ -+ tree orig_var; -+ -+ /* Its index in rls_block_local_data. */ -+ int index; -+ -+ /* Whether we can optimize this variable. */ -+ bool optimizable_p; -+ -+ /* The new variable declaration, if we can optimize away the staticness -+ of 'orig_var'. */ -+ tree new_var; -+}; -+ -+/* Filled with 'struct rls_decl_info'; keyed off ORIG_VAR. */ -+static htab_t static_variables; -+ -+struct rls_stmt_info -+{ -+ /* The variable declaration. */ -+ tree var; -+ -+ /* The statement in which we found a def or a use of the variable. */ -+ gimple stmt; -+ -+ /* Whether STMT represents a use of VAR. */ -+ bool use_p; -+ -+ /* A bitmap whose entries denote what variables have been defined -+ when execution arrives at STMT. This field is only used when -+ USE_P is true. */ -+ sbitmap defined; -+}; -+ -+/* Filled with 'struct rls_stmt_info'; keyed off STMT. */ -+static htab_t defuse_statements; -+ -+static struct -+{ -+ /* The number of static variables we found. */ -+ size_t n_statics; -+ -+ /* The number of optimizable variables we found. */ -+ size_t n_optimizable; -+} stats; -+ -+struct rls_block_dataflow_data { -+ /* A bitmap whose entries denote what variables have been defined on -+ entry to this block. */ -+ sbitmap defined_in; -+ -+ /* A bitmap whose entries denote what variables have been defined on -+ exit from this block. */ -+ sbitmap defined_out; -+}; -+ -+/* Parameters for the 'static_variables' hash table. */ -+ -+static hashval_t -+rls_hash_decl_info (const void *x) -+{ -+ return htab_hash_pointer -+ ((const void *) ((const struct rls_decl_info *) x)->orig_var); -+} -+ -+static int -+rls_eq_decl_info (const void *x, const void *y) -+{ -+ const struct rls_decl_info *a = (const struct rls_decl_info *) x; -+ const struct rls_decl_info *b = (const struct rls_decl_info *) y; -+ -+ return a->orig_var == b->orig_var; -+} -+ -+static void -+rls_free_decl_info (void *info) -+{ -+ free (info); -+} -+ -+/* Parameters for the 'defuse_statements' hash table. */ -+ -+static hashval_t -+rls_hash_use_info (const void *x) -+{ -+ return htab_hash_pointer -+ ((const void *) ((const struct rls_stmt_info *) x)->stmt); -+} -+ -+static int -+rls_eq_use_info (const void *x, const void *y) -+{ -+ const struct rls_stmt_info *a = (const struct rls_stmt_info *) x; -+ const struct rls_stmt_info *b = (const struct rls_stmt_info *) y; -+ -+ return a->stmt == b->stmt; -+} -+ -+static void -+rls_free_use_info (void *info) -+{ -+ struct rls_stmt_info *stmt_info = (struct rls_stmt_info *) info; -+ -+ if (stmt_info->defined) -+ sbitmap_free (stmt_info->defined); -+ -+ free (stmt_info); -+} -+ -+/* Initialize data structures and statistics. */ -+ -+static void -+rls_init (void) -+{ -+ basic_block bb; -+ -+ /* We expect relatively few static variables, hence the small -+ initial size for the hash table. */ -+ static_variables = htab_create (8, rls_hash_decl_info, -+ rls_eq_decl_info, rls_free_decl_info); -+ -+ /* We expect quite a few statements. */ -+ defuse_statements = htab_create (128, rls_hash_use_info, -+ rls_eq_use_info, rls_free_use_info); -+ -+ FOR_ALL_BB (bb) -+ { -+ struct rls_block_dataflow_data *data; -+ -+ data = XNEW (struct rls_block_dataflow_data); -+ memset (data, 0, sizeof (*data)); -+ bb->aux = data; -+ } -+ -+ stats.n_statics = 0; -+ stats.n_optimizable = 0; -+} -+ -+/* Free data structures. */ -+ -+static void -+rls_done (void) -+{ -+ basic_block bb; -+ -+ htab_delete (static_variables); -+ htab_delete (defuse_statements); -+ -+ FOR_ALL_BB (bb) -+ { -+ struct rls_block_dataflow_data *data -+ = (struct rls_block_dataflow_data *) bb->aux; -+ -+ gcc_assert (data); -+ -+ if (data->defined_in) -+ sbitmap_free (data->defined_in); -+ if (data->defined_out) -+ sbitmap_free (data->defined_out); -+ free (data); -+ bb->aux = NULL; -+ } -+} -+ -+ -+/* Doing the initial work to find static variables. */ -+ -+/* Examine the defining statement for VAR and determine whether it is a -+ static variable we could potentially optimize. If so, stick in it -+ in the 'static_variables' hashtable. -+ -+ STMT is the statement in which a definition or use of VAR occurs. -+ USE_P indicates whether VAR is used or defined in STMT. Enter STMT -+ into 'defuse_statements' as well for use during dataflow -+ analysis. */ -+ -+static void -+maybe_discover_new_declaration (tree var, gimple stmt, bool use_p) -+{ -+ tree def_stmt = SSA_NAME_VAR (var); -+ -+ if (TREE_CODE (def_stmt) == VAR_DECL -+ && DECL_CONTEXT (def_stmt) != NULL_TREE -+ && TREE_CODE (DECL_CONTEXT (def_stmt)) == FUNCTION_DECL -+ /* We cannot optimize away a static used in multiple functions (as -+ might happen in C++). */ -+ && !DECL_NONLOCAL(def_stmt) -+ && TREE_STATIC (def_stmt) -+ /* We cannot optimize away aggregate statics, as we would have to -+ prove that definitions of every field of the aggregate dominate -+ uses. */ -+ && !AGGREGATE_TYPE_P (TREE_TYPE (def_stmt)) -+ /* GCC doesn't normally treat vectors as aggregates; we need to, -+ though, since a user could use intrinsics to read/write -+ particular fields of the vector, thereby treating it as an -+ array. */ -+ && TREE_CODE (TREE_TYPE (def_stmt)) != VECTOR_TYPE -+ && !TREE_ADDRESSABLE (def_stmt) -+ && !TREE_THIS_VOLATILE (def_stmt)) -+ { -+ struct rls_decl_info dummy; -+ void **slot; -+ -+ dummy.orig_var = def_stmt; -+ slot = htab_find_slot (static_variables, &dummy, INSERT); -+ -+ if (*slot == NULL) -+ { -+ /* Found a use or a def of a new declaration. */ -+ struct rls_decl_info *info = XNEW (struct rls_decl_info); -+ -+ info->orig_var = def_stmt; -+ info->index = stats.n_statics++; -+ /* Optimistically assume that we can optimize. */ -+ info->optimizable_p = true; -+ info->new_var = NULL_TREE; -+ *slot = (void *) info; -+ } -+ -+ /* Enter the statement into DEFUSE_STATEMENTS. */ -+ { -+ struct rls_stmt_info dummy; -+ struct rls_stmt_info *info; -+ -+ dummy.stmt = stmt; -+ slot = htab_find_slot (defuse_statements, &dummy, INSERT); -+ -+ /* We should never insert the same statement into the -+ hashtable twice. */ -+ gcc_assert (*slot == NULL -+ || ((struct rls_stmt_info *)(*slot))->stmt == stmt); -+ -+ if (*slot != NULL && ((struct rls_stmt_info *)(*slot))->stmt == stmt) -+ return; -+ -+ info = XNEW (struct rls_stmt_info); -+ info->var = def_stmt; -+ info->stmt = stmt; -+ if (dump_file) -+ { -+ fprintf (dump_file, "entering as %s ", use_p ? "use" : "def"); -+ print_gimple_stmt (dump_file, stmt, 0, TDF_DETAILS | TDF_VOPS); -+ } -+ info->use_p = use_p; -+ /* We don't know how big to make the bitmap yet. */ -+ info->defined = NULL; -+ *slot = (void *) info; -+ } -+ } -+} -+ -+/* Grovel through all the statements in the program, looking for -+ SSA_NAMEs whose SSA_NAME_VAR is a VAR_DECL. We look at both use and -+ def SSA_NAMEs. */ -+ -+static void -+find_static_nonvolatile_declarations (void) -+{ -+ basic_block bb; -+ -+ FOR_EACH_BB (bb) -+ { -+ gimple_stmt_iterator i; -+ -+ for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i)) -+ { -+ tree var; -+ ssa_op_iter iter; -+ gimple stmt = gsi_stmt (i); -+ -+ /* If there's a call expression in STMT, then previous passes -+ will have determined if the call transitively defines some -+ static variable. However, we need more precise -+ information--we need to know whether static variables are -+ live out after the call. -+ -+ Since we'll never see something like: -+ -+ staticvar = foo (bar, baz); -+ -+ in GIMPLE (the result of the call will be assigned to a -+ normal, non-static local variable which is then assigned to -+ STATICVAR in a subsequent statement), don't bother finding -+ new declarations if we see a GIMPLE_CALL. -+ -+ In a similar fashion, asm statements that clobber memory -+ will appear to define static variables. In general, -+ however, assuming that asm statements define static -+ variables would cause us to see that in the following -+ situation: -+ -+ static int foo = 0; -+ -+ __asm__ (... : "memory"); -+ foo++; -+ -+ foo could be unstaticized because the asm has "defined" -+ foo. This is likely false. (Even if the asm does happen -+ to define foo--and only foo--that situation would be -+ sufficiently unusual that not optimizing it seems OK.) */ -+ if (gimple_code (stmt) != GIMPLE_CALL -+ && gimple_code (stmt) != GIMPLE_ASM) -+ FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_VDEF) -+ { -+ maybe_discover_new_declaration (var, stmt, false); -+ } -+ -+ FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_VUSE) -+ { -+ maybe_discover_new_declaration (var, stmt, true); -+ } -+ } -+ } -+} -+ -+ -+/* Determining if we have anything to optimize. */ -+ -+/* Examine *SLOT (which is a 'struct rls_decl_info *') to see whether -+ the associated variable is optimizable. If it is, create a new, -+ non-static declaration for the variable; this new variable will be -+ used during a subsequent rewrite of the function. */ -+ -+#define NEW_VAR_PREFIX ".unstatic" -+ -+static int -+maybe_create_new_variable (void **slot, void *data ATTRIBUTE_UNUSED) -+{ -+ struct rls_decl_info *info = (struct rls_decl_info *) *slot; -+ tree id_node = DECL_NAME (info->orig_var); -+ size_t id_len = IDENTIFIER_LENGTH (id_node); -+ size_t name_len = id_len + strlen (NEW_VAR_PREFIX) + 1; -+ char *name; -+ -+ /* Don't create a new variable multiple times. */ -+ gcc_assert (!info->new_var); -+ -+ /* Tie the new name to the old one to aid debugging dumps. */ -+ name = (char *) alloca (name_len); -+ strcpy (name, IDENTIFIER_POINTER (id_node)); -+ strcpy (name + id_len, NEW_VAR_PREFIX); -+ info->new_var = create_tmp_var (TREE_TYPE (info->orig_var), name); -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, "new variable "); -+ print_generic_expr (dump_file, info->new_var, 0); -+ fprintf (dump_file, "\n"); -+ } -+ -+ /* Inform SSA about this new variable. */ -+ create_var_ann (info->new_var); -+ mark_sym_for_renaming (info->new_var); -+ /* We need to make sure we rebuild bits for the original variable, -+ such as virtual operands attached to statements. */ -+ mark_sym_for_renaming (info->orig_var); -+ add_referenced_var (info->new_var); -+ -+ /* Always continue scanning. */ -+ return 1; -+} -+ -+#undef NEW_VAR_PREFIX -+ -+/* Traverse the 'defuse_statements' hash table. For every use, -+ determine if the associated variable is defined along all paths -+ leading to said use. Remove the associated variable from -+ 'static_variables' if it is not. */ -+ -+static int -+check_definedness (void **slot, void *data ATTRIBUTE_UNUSED) -+{ -+ struct rls_stmt_info *info = (struct rls_stmt_info *) *slot; -+ struct rls_decl_info dummy; -+ -+ /* We don't need to look at definitions. Continue scanning. */ -+ if (!info->use_p) -+ return 1; -+ -+ dummy.orig_var = info->var; -+ slot = htab_find_slot (static_variables, &dummy, INSERT); -+ -+ /* Might not be there because we deleted it already. */ -+ if (*slot) -+ { -+ struct rls_decl_info *decl = (struct rls_decl_info *) *slot; -+ -+ if (!TEST_BIT (info->defined, decl->index)) -+ { -+ if (dump_file) -+ { -+ fprintf (dump_file, "not optimizing "); -+ print_generic_expr (dump_file, decl->orig_var, 0); -+ fprintf (dump_file, "due to uncovered use in "); -+ print_gimple_stmt (dump_file, info->stmt, 0, 0); -+ fprintf (dump_file, "\n"); -+ } -+ -+ htab_clear_slot (static_variables, slot); -+ stats.n_optimizable--; -+ } -+ } -+ -+ /* Continue scan. */ -+ return 1; -+} -+ -+/* Check all statements in 'defuse_statements' to see if all the -+ statements that use a static variable have that variable defined -+ along all paths leading to the statement. Once that's done, go -+ through and create new, non-static variables for any static variables -+ that can be optimized. */ -+ -+static size_t -+determine_optimizable_statics (void) -+{ -+ htab_traverse (defuse_statements, check_definedness, NULL); -+ -+ htab_traverse (static_variables, maybe_create_new_variable, NULL); -+ -+ return stats.n_optimizable; -+} -+ -+/* Look at STMT to see if we have uses or defs of a static variable. -+ STMT is passed in DATA. Definitions of a static variable are found -+ by the presence of a V_MUST_DEF, while uses are found by the presence -+ of a VUSE. */ -+ -+static int -+unstaticize_variable (void **slot, void *data) -+{ -+ struct rls_decl_info *info = (struct rls_decl_info *) *slot; -+ gimple stmt = (gimple) data; -+ tree vdef; -+ tree vuse; -+ int continue_scan = 1; -+ -+ /* We should have removed unoptimizable variables during an earlier -+ traversal. */ -+ gcc_assert (info->optimizable_p); -+ -+ /* Check for virtual definitions first. */ -+ vdef = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_VDEF); -+ -+ if (vdef != NULL -+ && ZERO_SSA_OPERANDS (stmt, SSA_OP_DEF) -+ && gimple_code (stmt) == GIMPLE_ASSIGN -+ && TREE_CODE (gimple_assign_lhs (stmt)) == VAR_DECL -+ && gimple_assign_lhs(stmt) == info->orig_var) -+ { -+ /* Make the statement define the new name. The new name has -+ already been marked for renaming, so no need to do that -+ here. */ -+ gimple_assign_set_lhs (stmt, info->new_var); -+ if (dump_file) -+ { -+ fprintf (dump_file, "found virtual definition!\n"); -+ print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS | TDF_DETAILS); -+ fprintf (dump_file, "\n"); -+ } -+ continue_scan = 0; -+ goto done; -+ } -+ -+ /* Check for virtual uses. */ -+ vuse = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_VUSE); -+ -+ if (vuse != NULL -+ && gimple_code (stmt) == GIMPLE_ASSIGN -+ && gimple_assign_rhs_code (stmt) == VAR_DECL -+ && gimple_assign_rhs1 (stmt) == info->orig_var) -+ { -+ /* Make the statement use the new name. */ -+ gimple_assign_set_rhs1 (stmt, info->new_var); -+ if (dump_file) -+ { -+ fprintf (dump_file, "found virtual use!\n"); -+ print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS | TDF_DETAILS); -+ fprintf (dump_file, "\n"); -+ } -+ continue_scan = 0; -+ goto done; -+ } -+ -+ done: -+ if (!continue_scan) -+ { -+ /* None of the other optimizable static variables can occur -+ in this statement. Stop the scan. */ -+ update_stmt (stmt); -+ -+ if (dump_file) -+ { -+ fprintf (dump_file, "updated stmt\n"); -+ print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS | TDF_DETAILS); -+ } -+ } -+ -+ return continue_scan; -+} -+ -+/* Determine if we have any static variables we can optimize. If so, -+ replace any defs or uses of those variables in their defining/using -+ statements. */ -+ -+static void -+maybe_remove_static_from_declarations (void) -+{ -+ size_t n_optimizable = determine_optimizable_statics (); -+ basic_block bb; -+ -+ if (n_optimizable) -+ /* Replace any optimizable variables with new, non-static variables. */ -+ FOR_EACH_BB (bb) -+ { -+ gimple_stmt_iterator gsi; -+ -+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) -+ { -+ gimple stmt = gsi_stmt (gsi); -+ -+ htab_traverse (static_variables, unstaticize_variable, stmt); -+ } -+ } -+} -+ -+/* Callback for htab_traverse to initialize the bitmap for *SLOT, which -+ is a 'struct rls_stmt_info'. */ -+ -+static int -+initialize_statement_dataflow (void **slot, void *data ATTRIBUTE_UNUSED) -+{ -+ struct rls_stmt_info *info = (struct rls_stmt_info *) *slot; -+ -+ gcc_assert (!info->defined); -+ -+ if (info->use_p) -+ { -+ info->defined = sbitmap_alloc (stats.n_statics); -+ /* Assume defined along all paths until otherwise informed. */ -+ sbitmap_ones (info->defined); -+ } -+ -+ /* Continue traversal. */ -+ return 1; -+} -+ -+/* We have N_STATICS static variables to consider. Go through all the -+ blocks and all the use statements to initialize their bitmaps. */ -+ -+static void -+initialize_block_and_statement_dataflow (size_t n_statics) -+{ -+ basic_block bb; -+ -+ FOR_ALL_BB (bb) -+ { -+ struct rls_block_dataflow_data *data -+ = (struct rls_block_dataflow_data *) bb->aux; -+ -+ gcc_assert (data); -+ -+ data->defined_in = sbitmap_alloc (n_statics); -+ sbitmap_zero (data->defined_in); -+ data->defined_out = sbitmap_alloc (n_statics); -+ sbitmap_zero (data->defined_out); -+ } -+ -+ htab_traverse (defuse_statements, initialize_statement_dataflow, NULL); -+} -+ -+/* Apply the individual effects of the stmts in BB to update the -+ dataflow analysis information for BB. */ -+ -+static void -+compute_definedness_for_block (basic_block bb) -+{ -+ bool changed_p = false; -+ struct rls_block_dataflow_data *data -+ = (struct rls_block_dataflow_data *) bb->aux; -+ gimple_stmt_iterator gsi; -+ -+ sbitmap_copy (data->defined_out, data->defined_in); -+ -+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) -+ { -+ gimple stmt = gsi_stmt (gsi); -+ -+ if (gimple_code (stmt) == GIMPLE_CALL) -+ /* If there's a call expression in STMT, then previous passes -+ will have determined if the call transitively defines some -+ static variable. However, we need more precise -+ information--we need to know whether static variables are -+ live out after the call. In the absence of such information, -+ simply declare that all static variables are clobbered by the -+ call. A better analysis would be interprocedural and compute -+ the liveness information we require, but for now, we're being -+ pessimistic. */ -+ sbitmap_zero (data->defined_out); -+ else -+ { -+ struct rls_stmt_info dummy; -+ void **slot; -+ -+ /* See if this statement uses or defines a static variable. */ -+ dummy.stmt = stmt; -+ slot = htab_find_slot (defuse_statements, &dummy, INSERT); -+ -+ /* Check for uses. */ -+ if (*slot != NULL) -+ { -+ struct rls_stmt_info *info = (struct rls_stmt_info *) *slot; -+ -+ if (info->use_p) -+ { -+ gcc_assert (info->defined); -+ -+ /* Found a statement that uses a function-local static -+ variable. Copy the current state of definedness. */ -+ sbitmap_copy (info->defined, data->defined_out); -+ } -+ else -+ { -+ struct rls_decl_info dummy; -+ struct rls_decl_info *decl; -+ -+ gcc_assert (!info->defined); -+ -+ /* Found a statement that defines a function-local static -+ variable. Look up the associated variable's information -+ and mark it as defined in the block. */ -+ dummy.orig_var = info->var; -+ slot = htab_find_slot (static_variables, &dummy, INSERT); -+ -+ gcc_assert (*slot); -+ -+ decl = (struct rls_decl_info *) *slot; -+ -+ SET_BIT (data->defined_out, decl->index); -+ changed_p |= true; -+ } -+ } -+ } -+ } -+} -+ -+/* Solve the dataflow equations: -+ -+ DEFINED_IN(b) = intersect DEFINED_OUT(p) for p in preds(b) -+ DEFINED_OUT(b) = VARIABLES_DEFINED (b, DEFINED_IN (b)) -+ -+ via a simple iterative solver. VARIABLES_DEFINED is computed by -+ 'compute_definedness_for_block'. */ -+ -+static void -+compute_definedness (void) -+{ -+ basic_block bb; -+ bool changed_p; -+ sbitmap tmp_bitmap = sbitmap_alloc (stats.n_statics); -+ -+ /* Compute initial sets. */ -+ FOR_EACH_BB (bb) -+ { -+ compute_definedness_for_block (bb); -+ } -+ -+ /* Iterate. */ -+ do { -+ changed_p = false; -+ -+ FOR_EACH_BB (bb) -+ { -+ edge e; -+ edge_iterator ei; -+ struct rls_block_dataflow_data *data -+ = (struct rls_block_dataflow_data *) bb->aux; -+ bool bitmap_changed_p = false; -+ -+ sbitmap_ones (tmp_bitmap); -+ -+ gcc_assert (data); -+ -+ /* We require information about whether a variable was defined -+ over all paths leading to a particular use. Therefore, we -+ intersect the DEFINED sets of all predecessors. */ -+ FOR_EACH_EDGE (e, ei, bb->preds) -+ { -+ struct rls_block_dataflow_data *pred_data -+ = (struct rls_block_dataflow_data *) e->src->aux; -+ -+ gcc_assert (pred_data); -+ -+ sbitmap_a_and_b (tmp_bitmap, tmp_bitmap, pred_data->defined_out); -+ } -+ -+ bitmap_changed_p = !sbitmap_equal (tmp_bitmap, data->defined_in); -+ -+ if (bitmap_changed_p) -+ { -+ sbitmap_copy (data->defined_in, tmp_bitmap); -+ compute_definedness_for_block (bb); -+ } -+ -+ changed_p |= bitmap_changed_p; -+ } -+ } while (changed_p); -+ -+ sbitmap_free (tmp_bitmap); -+} -+ -+static unsigned int -+execute_rls (void) -+{ -+ rls_init (); -+ -+ find_static_nonvolatile_declarations (); -+ -+ /* Can we optimize anything? */ -+ if (stats.n_statics != 0) -+ { -+ stats.n_optimizable = stats.n_statics; -+ -+ if (dump_file) -+ fprintf (dump_file, "found %d static variables to consider\n", -+ stats.n_statics); -+ -+ initialize_block_and_statement_dataflow (stats.n_statics); -+ -+ compute_definedness (); -+ -+ maybe_remove_static_from_declarations (); -+ -+ if (dump_file) -+ fprintf (dump_file, "removed %d static variables\n", -+ stats.n_optimizable); -+ } -+ -+ rls_done (); -+ -+ return 0; -+} -+ -+static bool -+gate_rls (void) -+{ -+ return (flag_remove_local_statics != 0 -+ && !cfun->calls_setjmp -+ && !cgraph_node (current_function_decl)->ever_was_nested); -+} -+ -+struct gimple_opt_pass pass_remove_local_statics = -+{ -+ { -+ GIMPLE_PASS, -+ "remlocstatic", /* name */ -+ gate_rls, /* gate */ -+ execute_rls, /* execute */ -+ NULL, /* sub */ -+ NULL, /* next */ -+ 0, /* static_pass_number */ -+ TV_TREE_RLS, /* tv_id */ -+ PROP_cfg | PROP_ssa, /* properties_required */ -+ 0, /* properties_provided */ -+ 0, /* properties_destroyed */ -+ 0, /* todo_flags_start */ -+ TODO_dump_func | TODO_verify_ssa | TODO_verify_stmts -+ | TODO_rebuild_alias | TODO_update_ssa /* todo_flags_finish */ -+ } -+}; ---- a/gcc/tree-ssa-sink.c -+++ b/gcc/tree-ssa-sink.c -@@ -449,6 +449,47 @@ - last = false; - continue; - } -+ -+ /* We cannot move statements that contain references to block-scope -+ variables out of that block, as this may lead to incorrect aliasing -+ when we lay out the stack frame in cfgexpand.c. -+ In lieu of more sophisticated analysis, be very conservative here -+ and prohibit moving any statement that references memory out of a -+ block with variables. */ -+ if (gimple_references_memory_p (stmt)) -+ { -+ tree fromblock = gimple_block (stmt); -+ while (fromblock -+ && fromblock != current_function_decl -+ && !BLOCK_VARS (fromblock)) -+ fromblock = BLOCK_SUPERCONTEXT (fromblock); -+ if (fromblock && fromblock != current_function_decl) -+ { -+ gimple tostmt; -+ tree toblock; -+ -+ if (gsi_end_p (togsi)) -+ tostmt = gimple_seq_last_stmt (gsi_seq (togsi)); -+ else -+ tostmt = gsi_stmt (togsi); -+ if (tostmt) -+ toblock = gimple_block (tostmt); -+ else -+ toblock = NULL; -+ while (toblock -+ && toblock != current_function_decl -+ && toblock != fromblock) -+ toblock = BLOCK_SUPERCONTEXT (toblock); -+ if (!toblock || toblock != fromblock) -+ { -+ if (!gsi_end_p (gsi)) -+ gsi_prev (&gsi); -+ last = false; -+ continue; -+ } -+ } -+ } -+ - if (dump_file) - { - fprintf (dump_file, "Sinking "); ---- a/gcc/tree-ssa-structalias.c -+++ b/gcc/tree-ssa-structalias.c -@@ -2926,7 +2926,8 @@ - /* Some people like to do cute things like take the address of - &0->a.b */ - forzero = t; -- while (!SSA_VAR_P (forzero) && !CONSTANT_CLASS_P (forzero)) -+ while (!SSA_VAR_P (forzero) && TREE_CODE (forzero) != FUNCTION_DECL -+ && !CONSTANT_CLASS_P (forzero)) - forzero = TREE_OPERAND (forzero, 0); - - if (CONSTANT_CLASS_P (forzero) && integer_zerop (forzero)) ---- a/gcc/tree-vect-analyze.c -+++ b/gcc/tree-vect-analyze.c -@@ -1459,7 +1459,7 @@ - } - - base = build_fold_indirect_ref (base_addr); -- alignment = ssize_int (TYPE_ALIGN (vectype)/BITS_PER_UNIT); -+ alignment = ssize_int (targetm.vectorize.vector_min_alignment (vectype)); - - if ((aligned_to && tree_int_cst_compare (aligned_to, alignment) < 0) - || !misalign) -@@ -1510,7 +1510,8 @@ - /* At this point we assume that the base is aligned. */ - gcc_assert (base_aligned - || (TREE_CODE (base) == VAR_DECL -- && DECL_ALIGN (base) >= TYPE_ALIGN (vectype))); -+ && (DECL_ALIGN (base) -+ >= targetm.vectorize.vector_min_alignment (vectype)))); - - /* Modulo alignment. */ - misalign = size_binop (TRUNC_MOD_EXPR, misalign, alignment); ---- a/gcc/tree-vectorizer.c -+++ b/gcc/tree-vectorizer.c -@@ -2868,11 +2868,13 @@ - vnode = vnode->next_needed) - { - tree vectype, decl = vnode->decl; -+ tree t; - unsigned int alignment; - -- if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE) -+ t = TREE_TYPE(decl); -+ if (TREE_CODE (t) != ARRAY_TYPE) - continue; -- vectype = get_vectype_for_scalar_type (TREE_TYPE (TREE_TYPE (decl))); -+ vectype = get_vectype_for_scalar_type (strip_array_types (t)); - if (!vectype) - continue; - alignment = TYPE_ALIGN (vectype); -@@ -2887,6 +2889,7 @@ - { - fprintf (dump_file, "Increasing alignment of decl: "); - print_generic_expr (dump_file, decl, TDF_SLIM); -+ fprintf (dump_file, "\n"); - } - } - } ---- a/gcc/tree-vect-transform.c -+++ b/gcc/tree-vect-transform.c -@@ -5442,7 +5442,21 @@ - vect_permute_store_chain(). */ - vec_oprnd = VEC_index (tree, result_chain, i); - -- data_ref = build_fold_indirect_ref (dataref_ptr); -+ if (alignment_support_scheme == dr_aligned -+ && !targetm.vectorize.always_misalign(vectype)) -+ { -+ data_ref = build_fold_indirect_ref (dataref_ptr); -+ } -+ else -+ { -+ /* TODO: Record actual alignment in always_misalign case. */ -+ int mis = DR_MISALIGNMENT (first_dr); -+ tree tmis; -+ tmis = (mis == -1 ? size_zero_node : size_int (mis)); -+ tmis = size_binop (MULT_EXPR, tmis, size_int(BITS_PER_UNIT)); -+ data_ref = -+ build2 (MISALIGNED_INDIRECT_REF, vectype, dataref_ptr, tmis); -+ } - - /* Arguments are ready. Create the new vector stmt. */ - new_stmt = gimple_build_assign (data_ref, vec_oprnd); -@@ -6621,10 +6635,15 @@ - { - case dr_aligned: - gcc_assert (aligned_access_p (first_dr)); -- data_ref = build_fold_indirect_ref (dataref_ptr); -- break; -+ if (!targetm.vectorize.always_misalign(vectype)) -+ { -+ data_ref = build_fold_indirect_ref (dataref_ptr); -+ break; -+ } -+ /* Fall through... */ - case dr_unaligned_supported: - { -+ /* TODO: Record actual alignment in always_misalign case. */ - int mis = DR_MISALIGNMENT (first_dr); - tree tmis = (mis == -1 ? size_zero_node : size_int (mis)); - -@@ -7595,7 +7614,7 @@ - gimple dr_stmt = DR_STMT (dr); - stmt_vec_info stmt_info = vinfo_for_stmt (dr_stmt); - tree vectype = STMT_VINFO_VECTYPE (stmt_info); -- int vectype_align = TYPE_ALIGN (vectype) / BITS_PER_UNIT; -+ int vectype_align = targetm.vectorize.vector_min_alignment (vectype); - tree niters_type = TREE_TYPE (loop_niters); - int step = 1; - int element_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (DR_REF (dr)))); ---- a/gcc/unwind-dw2.c -+++ b/gcc/unwind-dw2.c -@@ -1414,16 +1414,12 @@ - /* Fill in CONTEXT for top-of-stack. The only valid registers at this - level will be the return address and the CFA. */ - --#define uw_init_context(CONTEXT) \ -- do \ -- { \ -- /* Do any necessary initialization to access arbitrary stack frames. \ -- On the SPARC, this means flushing the register windows. */ \ -- __builtin_unwind_init (); \ -- uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \ -- __builtin_return_address (0)); \ -- } \ -- while (0) -+#define uw_init_context(CONTEXT) \ -+ /* Do any necessary initialization to access arbitrary stack frames. \ -+ On the SPARC, this means flushing the register windows. */ \ -+ (__builtin_unwind_init (), \ -+ uw_init_context_1 ((CONTEXT), __builtin_dwarf_cfa (), \ -+ __builtin_return_address (0))) - - static inline void - init_dwarf_reg_size_table (void) -@@ -1431,7 +1427,7 @@ - __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table); - } - --static void -+static _Unwind_Reason_Code - uw_init_context_1 (struct _Unwind_Context *context, - void *outer_cfa, void *outer_ra) - { -@@ -1445,7 +1441,8 @@ - context->flags = EXTENDED_CONTEXT_BIT; - - code = uw_frame_state_for (context, &fs); -- gcc_assert (code == _URC_NO_REASON); -+ if (code != _URC_NO_REASON) -+ return code; - - #if __GTHREADS - { -@@ -1471,6 +1468,8 @@ - initialization context, then we can't see it in the given - call frame data. So have the initialization context tell us. */ - context->ra = __builtin_extract_return_addr (outer_ra); -+ -+ return _URC_NO_REASON; - } - - ---- a/gcc/unwind.inc -+++ b/gcc/unwind.inc -@@ -85,7 +85,8 @@ - _Unwind_Reason_Code code; - - /* Set up this_context to describe the current stack frame. */ -- uw_init_context (&this_context); -+ code = uw_init_context (&this_context); -+ gcc_assert (code == _URC_NO_REASON); - cur_context = this_context; - - /* Phase 1: Search. Unwind the stack, calling the personality routine -@@ -198,7 +199,8 @@ - struct _Unwind_Context this_context, cur_context; - _Unwind_Reason_Code code; - -- uw_init_context (&this_context); -+ code = uw_init_context (&this_context); -+ gcc_assert (code == _URC_NO_REASON); - cur_context = this_context; - - exc->private_1 = (_Unwind_Ptr) stop; -@@ -221,7 +223,8 @@ - struct _Unwind_Context this_context, cur_context; - _Unwind_Reason_Code code; - -- uw_init_context (&this_context); -+ code = uw_init_context (&this_context); -+ gcc_assert (code == _URC_NO_REASON); - cur_context = this_context; - - /* Choose between continuing to process _Unwind_RaiseException -@@ -251,7 +254,8 @@ - if (exc->private_1 == 0) - return _Unwind_RaiseException (exc); - -- uw_init_context (&this_context); -+ code = uw_init_context (&this_context); -+ gcc_assert (code == _URC_NO_REASON); - cur_context = this_context; - - code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context); -@@ -280,7 +284,9 @@ - struct _Unwind_Context context; - _Unwind_Reason_Code code; - -- uw_init_context (&context); -+ code = uw_init_context (&context); -+ if (code != _URC_NO_REASON) -+ return _URC_FATAL_PHASE1_ERROR; - - while (1) - { ---- a/gcc/unwind-sjlj.c -+++ b/gcc/unwind-sjlj.c -@@ -292,10 +292,11 @@ - uw_update_context (context, fs); - } - --static inline void -+static inline _Unwind_Reason_Code - uw_init_context (struct _Unwind_Context *context) - { - context->fc = _Unwind_SjLj_GetContext (); -+ return _URC_NO_REASON; - } - - static void __attribute__((noreturn)) ---- a/gcc/varasm.c -+++ b/gcc/varasm.c -@@ -1126,11 +1126,14 @@ - { - #ifdef DATA_ALIGNMENT - unsigned int data_align = DATA_ALIGNMENT (TREE_TYPE (decl), align); -+#else -+ unsigned int data_align = align; -+#endif -+ data_align = alignment_for_aligned_arrays (TREE_TYPE (decl), data_align); - /* Don't increase alignment too much for TLS variables - TLS space - is too precious. */ - if (! DECL_THREAD_LOCAL_P (decl) || data_align <= BITS_PER_WORD) - align = data_align; --#endif - #ifdef CONSTANT_ALIGNMENT - if (DECL_INITIAL (decl) != 0 && DECL_INITIAL (decl) != error_mark_node) - { -@@ -3196,6 +3199,10 @@ - set_mem_alias_set (rtl, 0); - set_mem_alias_set (rtl, const_alias_set); - -+ /* We cannot share RTX'es in pool entries. -+ Mark this piece of RTL as required for unsharing. */ -+ RTX_FLAG (rtl, used) = 1; -+ - /* Set flags or add text to the name to record information, such as - that it is a local symbol. If the name is changed, the macro - ASM_OUTPUT_LABELREF will have to know how to strip this ---- a/gcc/vmsdbgout.c -+++ b/gcc/vmsdbgout.c -@@ -211,6 +211,7 @@ - debug_nothing_int, /* handle_pch */ - debug_nothing_rtx, /* var_location */ - debug_nothing_void, /* switch_text_section */ -+ debug_nothing_tree_tree, /* set_name */ - 0 /* start_end_main_source_file */ - }; - ---- a/libcpp/directives.c -+++ b/libcpp/directives.c -@@ -2299,13 +2299,6 @@ - run_directive (pfile, type, str, count); - } - --/* The number of errors for a given reader. */ --unsigned int --cpp_errors (cpp_reader *pfile) --{ -- return pfile->errors; --} -- - /* The options structure. */ - cpp_options * - cpp_get_options (cpp_reader *pfile) ---- a/libcpp/errors.c -+++ b/libcpp/errors.c -@@ -28,171 +28,69 @@ - #include "cpplib.h" - #include "internal.h" - --static void print_location (cpp_reader *, source_location, unsigned int); -- --/* Print the logical file location (LINE, COL) in preparation for a -- diagnostic. Outputs the #include chain if it has changed. A line -- of zero suppresses the include stack, and outputs the program name -- instead. */ --static void --print_location (cpp_reader *pfile, source_location line, unsigned int col) --{ -- if (line == 0) -- fprintf (stderr, "%s: ", progname); -- else -- { -- const struct line_map *map; -- linenum_type lin; -- -- map = linemap_lookup (pfile->line_table, line); -- linemap_print_containing_files (pfile->line_table, map); -- -- lin = SOURCE_LINE (map, line); -- if (col == 0) -- { -- col = SOURCE_COLUMN (map, line); -- if (col == 0) -- col = 1; -- } -- -- if (lin == 0) -- fprintf (stderr, "%s:", map->to_file); -- else if (CPP_OPTION (pfile, show_column) == 0) -- fprintf (stderr, "%s:%u:", map->to_file, lin); -- else -- fprintf (stderr, "%s:%u:%u:", map->to_file, lin, col); -- -- fputc (' ', stderr); -- } --} -- --/* Set up for a diagnostic: print the file and line, bump the error -- counter, etc. SRC_LOC is the logical line number; zero means to print -- at the location of the previously lexed token, which tends to be -- the correct place by default. The column number can be specified either -- using COLUMN or (if COLUMN==0) extracting SOURCE_COLUMN from SRC_LOC. -- (This may seem redundant, but is useful when pre-scanning (cleaning) a line, -- when we haven't yet verified whether the current line_map has a -- big enough max_column_hint.) -- -- Returns 0 if the error has been suppressed. */ --static int --_cpp_begin_message (cpp_reader *pfile, int code, -- source_location src_loc, unsigned int column) --{ -- int level = CPP_DL_EXTRACT (code); -- -- switch (level) -- { -- case CPP_DL_WARNING: -- case CPP_DL_PEDWARN: -- if (cpp_in_system_header (pfile) -- && ! CPP_OPTION (pfile, warn_system_headers)) -- return 0; -- /* Fall through. */ -- -- case CPP_DL_WARNING_SYSHDR: -- if (CPP_OPTION (pfile, warnings_are_errors) -- || (level == CPP_DL_PEDWARN && CPP_OPTION (pfile, pedantic_errors))) -- { -- if (CPP_OPTION (pfile, inhibit_errors)) -- return 0; -- level = CPP_DL_ERROR; -- pfile->errors++; -- } -- else if (CPP_OPTION (pfile, inhibit_warnings)) -- return 0; -- break; -- -- case CPP_DL_ERROR: -- if (CPP_OPTION (pfile, inhibit_errors)) -- return 0; -- /* ICEs cannot be inhibited. */ -- case CPP_DL_ICE: -- pfile->errors++; -- break; -- } -- -- print_location (pfile, src_loc, column); -- if (CPP_DL_WARNING_P (level)) -- fputs (_("warning: "), stderr); -- else if (level == CPP_DL_ICE) -- fputs (_("internal error: "), stderr); -- else -- fputs (_("error: "), stderr); -- -- return 1; --} -- --/* Don't remove the blank before do, as otherwise the exgettext -- script will mistake this as a function definition */ --#define v_message(msgid, ap) \ -- do { vfprintf (stderr, _(msgid), ap); putc ('\n', stderr); } while (0) -- --/* Exported interface. */ -- - /* Print an error at the location of the previously lexed token. */ --void -+bool - cpp_error (cpp_reader * pfile, int level, const char *msgid, ...) - { - source_location src_loc; - va_list ap; -- -+ bool ret; -+ - va_start (ap, msgid); - -- if (CPP_OPTION (pfile, client_diagnostic)) -- pfile->cb.error (pfile, level, _(msgid), &ap); -- else -+ if (CPP_OPTION (pfile, traditional)) - { -- if (CPP_OPTION (pfile, traditional)) -- { -- if (pfile->state.in_directive) -- src_loc = pfile->directive_line; -- else -- src_loc = pfile->line_table->highest_line; -- } -- /* We don't want to refer to a token before the beginning of the -- current run -- that is invalid. */ -- else if (pfile->cur_token == pfile->cur_run->base) -- { -- if (pfile->cur_run->prev != NULL) -- src_loc = pfile->cur_run->prev->limit->src_loc; -- else -- src_loc = 0; -- } -+ if (pfile->state.in_directive) -+ src_loc = pfile->directive_line; - else -- { -- src_loc = pfile->cur_token[-1].src_loc; -- } -- -- if (_cpp_begin_message (pfile, level, src_loc, 0)) -- v_message (msgid, ap); -+ src_loc = pfile->line_table->highest_line; -+ } -+ /* We don't want to refer to a token before the beginning of the -+ current run -- that is invalid. */ -+ else if (pfile->cur_token == pfile->cur_run->base) -+ { -+ if (pfile->cur_run->prev != NULL) -+ src_loc = pfile->cur_run->prev->limit->src_loc; -+ else -+ src_loc = 0; - } -+ else -+ { -+ src_loc = pfile->cur_token[-1].src_loc; -+ } -+ -+ if (!pfile->cb.error) -+ abort (); -+ ret = pfile->cb.error (pfile, level, src_loc, 0, _(msgid), &ap); - - va_end (ap); -+ return ret; - } - - /* Print an error at a specific location. */ --void -+bool - cpp_error_with_line (cpp_reader *pfile, int level, - source_location src_loc, unsigned int column, - const char *msgid, ...) - { - va_list ap; -+ bool ret; - - va_start (ap, msgid); - -- if (_cpp_begin_message (pfile, level, src_loc, column)) -- v_message (msgid, ap); -+ if (!pfile->cb.error) -+ abort (); -+ ret = pfile->cb.error (pfile, level, src_loc, column, _(msgid), &ap); - - va_end (ap); -+ return ret; - } - --void -+bool - cpp_errno (cpp_reader *pfile, int level, const char *msgid) - { - if (msgid[0] == '\0') - msgid = _("stdout"); - -- cpp_error (pfile, level, "%s: %s", msgid, xstrerror (errno)); -+ return cpp_error (pfile, level, "%s: %s", msgid, xstrerror (errno)); - } ---- a/libcpp/files.c -+++ b/libcpp/files.c -@@ -488,7 +488,6 @@ - return file; - } - -- open_file_failed (pfile, file, angle_brackets); - if (invalid_pch) - { - cpp_error (pfile, CPP_DL_ERROR, -@@ -497,6 +496,7 @@ - cpp_error (pfile, CPP_DL_ERROR, - "use -Winvalid-pch for more information"); - } -+ open_file_failed (pfile, file, angle_brackets); - break; - } - -@@ -934,15 +934,28 @@ - - errno = file->err_no; - if (print_dep && CPP_OPTION (pfile, deps.missing_files) && errno == ENOENT) -- deps_add_dep (pfile->deps, file->name); -+ { -+ deps_add_dep (pfile->deps, file->name); -+ /* If the preprocessor output (other than dependency information) is -+ being used, we must also flag an error. */ -+ if (CPP_OPTION (pfile, deps.need_preprocessor_output)) -+ cpp_errno (pfile, CPP_DL_FATAL, file->path); -+ } - else - { -- /* If we are outputting dependencies but not for this file then -- don't error because we can still produce correct output. */ -- if (CPP_OPTION (pfile, deps.style) && ! print_dep) -- cpp_errno (pfile, CPP_DL_WARNING, file->path); -+ /* If we are not outputting dependencies, or if we are and dependencies -+ were requested for this file, or if preprocessor output is needed -+ in addition to dependency information, this is an error. -+ -+ Otherwise (outputting dependencies but not for this file, and not -+ using the preprocessor output), we can still produce correct output -+ so it's only a warning. */ -+ if (CPP_OPTION (pfile, deps.style) == DEPS_NONE -+ || print_dep -+ || CPP_OPTION (pfile, deps.need_preprocessor_output)) -+ cpp_errno (pfile, CPP_DL_FATAL, file->path); - else -- cpp_errno (pfile, CPP_DL_ERROR, file->path); -+ cpp_errno (pfile, CPP_DL_WARNING, file->path); - } - } - ---- a/libcpp/include/cpplib.h -+++ b/libcpp/include/cpplib.h -@@ -302,22 +302,9 @@ - /* Nonzero means print names of header files (-H). */ - unsigned char print_include_names; - -- /* Nonzero means cpp_pedwarn causes a hard error. */ -- unsigned char pedantic_errors; -- -- /* Nonzero means don't print warning messages. */ -- unsigned char inhibit_warnings; -- - /* Nonzero means complain about deprecated features. */ - unsigned char warn_deprecated; - -- /* Nonzero means don't suppress warnings from system headers. */ -- unsigned char warn_system_headers; -- -- /* Nonzero means don't print error messages. Has no option to -- select it, but can be set by a user of cpplib (e.g. fix-header). */ -- unsigned char inhibit_errors; -- - /* Nonzero means warn if slash-star appears in a comment. */ - unsigned char warn_comments; - -@@ -353,9 +340,6 @@ - explicitly undefined. */ - unsigned char warn_builtin_macro_redefined; - -- /* Nonzero means turn warnings into errors. */ -- unsigned char warnings_are_errors; -- - /* Nonzero means we should look for header.gcc files that remap file - names. */ - unsigned char remap; -@@ -432,6 +416,10 @@ - - /* If true, no dependency is generated on the main file. */ - bool ignore_main_file; -+ -+ /* If true, intend to use the preprocessor output (e.g., for compilation) -+ in addition to the dependency info. */ -+ bool need_preprocessor_output; - } deps; - - /* Target-specific features set by the front end or client. */ -@@ -450,9 +438,6 @@ - /* Nonzero means __STDC__ should have the value 0 in system headers. */ - unsigned char stdc_0_in_system_headers; - -- /* True means error callback should be used for diagnostics. */ -- bool client_diagnostic; -- - /* True disables tokenization outside of preprocessing directives. */ - bool directives_only; - }; -@@ -492,10 +477,11 @@ - be expanded. */ - cpp_hashnode * (*macro_to_expand) (cpp_reader *, const cpp_token *); - -- /* Called to emit a diagnostic if client_diagnostic option is true. -- This callback receives the translated message. */ -- void (*error) (cpp_reader *, int, const char *, va_list *) -- ATTRIBUTE_FPTR_PRINTF(3,0); -+ /* Called to emit a diagnostic. This callback receives the -+ translated message. */ -+ bool (*error) (cpp_reader *, int, source_location, unsigned int, -+ const char *, va_list *) -+ ATTRIBUTE_FPTR_PRINTF(5,0); - - /* Callbacks for when a macro is expanded, or tested (whether - defined or not at the time) in #ifdef, #ifndef or "defined". */ -@@ -697,19 +683,13 @@ - - /* Call this to finish preprocessing. If you requested dependency - generation, pass an open stream to write the information to, -- otherwise NULL. It is your responsibility to close the stream. -- -- Returns cpp_errors (pfile). */ --extern int cpp_finish (cpp_reader *, FILE *deps_stream); -+ otherwise NULL. It is your responsibility to close the stream. */ -+extern void cpp_finish (cpp_reader *, FILE *deps_stream); - - /* Call this to release the handle at the end of preprocessing. Any -- use of the handle after this function returns is invalid. Returns -- cpp_errors (pfile). */ -+ use of the handle after this function returns is invalid. */ - extern void cpp_destroy (cpp_reader *); - --/* Error count. */ --extern unsigned int cpp_errors (cpp_reader *); -- - extern unsigned int cpp_token_len (const cpp_token *); - extern unsigned char *cpp_token_as_text (cpp_reader *, const cpp_token *); - extern unsigned char *cpp_spell_token (cpp_reader *, const cpp_token *, -@@ -835,24 +815,23 @@ - /* An internal consistency check failed. Prints "internal error: ", - otherwise the same as CPP_DL_ERROR. */ - #define CPP_DL_ICE 0x04 --/* Extracts a diagnostic level from an int. */ --#define CPP_DL_EXTRACT(l) (l & 0xf) --/* Nonzero if a diagnostic level is one of the warnings. */ --#define CPP_DL_WARNING_P(l) (CPP_DL_EXTRACT (l) >= CPP_DL_WARNING \ -- && CPP_DL_EXTRACT (l) <= CPP_DL_PEDWARN) -+/* An informative note following a warning. */ -+#define CPP_DL_NOTE 0x05 -+/* A fatal error. */ -+#define CPP_DL_FATAL 0x06 - - /* Output a diagnostic of some kind. */ --extern void cpp_error (cpp_reader *, int, const char *msgid, ...) -+extern bool cpp_error (cpp_reader *, int, const char *msgid, ...) - ATTRIBUTE_PRINTF_3; - - /* Output a diagnostic with "MSGID: " preceding the - error string of errno. No location is printed. */ --extern void cpp_errno (cpp_reader *, int, const char *msgid); -+extern bool cpp_errno (cpp_reader *, int, const char *msgid); - - /* Same as cpp_error, except additionally specifies a position as a - (translation unit) physical line and physical column. If the line is - zero, then no location is printed. */ --extern void cpp_error_with_line (cpp_reader *, int, source_location, unsigned, -+extern bool cpp_error_with_line (cpp_reader *, int, source_location, unsigned, - const char *msgid, ...) ATTRIBUTE_PRINTF_5; - - /* In lex.c */ ---- a/libcpp/include/line-map.h -+++ b/libcpp/include/line-map.h -@@ -144,12 +144,6 @@ - extern const struct line_map *linemap_lookup - (struct line_maps *, source_location); - --/* Print the file names and line numbers of the #include commands -- which led to the map MAP, if any, to stderr. Nothing is output if -- the most recently listed stack is the same as the current one. */ --extern void linemap_print_containing_files (struct line_maps *, -- const struct line_map *); -- - /* Converts a map and a source_location to source line. */ - #define SOURCE_LINE(MAP, LOC) \ - ((((LOC) - (MAP)->start_location) >> (MAP)->column_bits) + (MAP)->to_line) ---- a/libcpp/init.c -+++ b/libcpp/init.c -@@ -616,12 +616,11 @@ - } - - /* This is called at the end of preprocessing. It pops the last -- buffer and writes dependency output, and returns the number of -- errors. -+ buffer and writes dependency output. - - Maybe it should also reset state, such that you could call - cpp_start_read with a new filename to restart processing. */ --int -+void - cpp_finish (cpp_reader *pfile, FILE *deps_stream) - { - /* Warn about unused macros before popping the final buffer. */ -@@ -636,9 +635,8 @@ - while (pfile->buffer) - _cpp_pop_buffer (pfile); - -- /* Don't write the deps file if there are errors. */ - if (CPP_OPTION (pfile, deps.style) != DEPS_NONE -- && deps_stream && pfile->errors == 0) -+ && deps_stream) - { - deps_write (pfile->deps, deps_stream, 72); - -@@ -649,8 +647,6 @@ - /* Report on headers that could use multiple include guards. */ - if (CPP_OPTION (pfile, print_include_names)) - _cpp_report_missing_guards (pfile); -- -- return pfile->errors; - } - - static void ---- a/libcpp/internal.h -+++ b/libcpp/internal.h -@@ -388,9 +388,6 @@ - /* Nonzero prevents the lexer from re-using the token runs. */ - unsigned int keep_tokens; - -- /* Error counter for exit code. */ -- unsigned int errors; -- - /* Buffer to hold macro definition string. */ - unsigned char *macro_buffer; - unsigned int macro_buffer_len; ---- a/libcpp/line-map.c -+++ b/libcpp/line-map.c -@@ -302,45 +302,6 @@ - return &set->maps[mn]; - } - --/* Print the file names and line numbers of the #include commands -- which led to the map MAP, if any, to stderr. Nothing is output if -- the most recently listed stack is the same as the current one. */ -- --void --linemap_print_containing_files (struct line_maps *set, -- const struct line_map *map) --{ -- if (MAIN_FILE_P (map) || set->last_listed == map->included_from) -- return; -- -- set->last_listed = map->included_from; -- map = INCLUDED_FROM (set, map); -- -- fprintf (stderr, _("In file included from %s:%u"), -- map->to_file, LAST_SOURCE_LINE (map)); -- -- while (! MAIN_FILE_P (map)) -- { -- map = INCLUDED_FROM (set, map); -- /* Translators note: this message is used in conjunction -- with "In file included from %s:%ld" and some other -- tricks. We want something like this: -- -- | In file included from sys/select.h:123, -- | from sys/types.h:234, -- | from userfile.c:31: -- | bits/select.h:45: <error message here> -- -- with all the "from"s lined up. -- The trailing comma is at the beginning of this message, -- and the trailing colon is not translated. */ -- fprintf (stderr, _(",\n from %s:%u"), -- map->to_file, LAST_SOURCE_LINE (map)); -- } -- -- fputs (":\n", stderr); --} -- - /* Print an include trace, for e.g. the -H option of the preprocessor. */ - - static void ---- a/libcpp/macro.c -+++ b/libcpp/macro.c -@@ -1833,11 +1833,13 @@ - - if (warn_of_redefinition (pfile, node, macro)) - { -- cpp_error_with_line (pfile, CPP_DL_PEDWARN, pfile->directive_line, 0, -- "\"%s\" redefined", NODE_NAME (node)); -+ bool warned; -+ warned = cpp_error_with_line (pfile, CPP_DL_PEDWARN, -+ pfile->directive_line, 0, -+ "\"%s\" redefined", NODE_NAME (node)); - -- if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)) -- cpp_error_with_line (pfile, CPP_DL_PEDWARN, -+ if (warned && node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)) -+ cpp_error_with_line (pfile, CPP_DL_NOTE, - node->value.macro->line, 0, - "this is the location of the previous definition"); - } ---- /dev/null -+++ b/libgcc/config/arm/t-divmod-ef -@@ -0,0 +1,4 @@ -+# On ARM, specifying -fnon-call-exceptions will needlessly pull in -+# the unwinder in simple programs which use 64-bit division. Omitting -+# the option is safe. -+LIB2_DIVMOD_EXCEPTION_FLAGS := -fexceptions ---- /dev/null -+++ b/libgcc/config/mips/t-crtfm -@@ -0,0 +1,3 @@ -+crtfastmath.o: $(gcc_srcdir)/config/mips/crtfastmath.c -+ $(gcc_compile) -c $(gcc_srcdir)/config/mips/crtfastmath.c -+ ---- a/libgcc/config/rs6000/t-ppccomm -+++ b/libgcc/config/rs6000/t-ppccomm -@@ -101,3 +101,63 @@ - - ncrtn$(objext): ncrtn.S - $(crt_compile) -c ncrtn.S -+ -+crtsavres$(objext): crtsavres.S -+ $(crt_compile) -c crtsavres.S -+ -+crtsavfpr$(objext): crtsavfpr.S -+ $(crt_compile) -c crtsavfpr.S -+ -+crtresfpr$(objext): crtresfpr.S -+ $(crt_compile) -c crtresfpr.S -+ -+crtsavgpr$(objext): crtsavgpr.S -+ $(crt_compile) -c crtsavgpr.S -+ -+crtresgpr$(objext): crtresgpr.S -+ $(crt_compile) -c crtresgpr.S -+ -+crtresxfpr$(objext): crtresxfpr.S -+ $(crt_compile) -c crtresxfpr.S -+ -+crtresxgpr$(objext): crtresxgpr.S -+ $(crt_compile) -c crtresxgpr.S -+ -+e500crtres32gpr$(objext): e500crtres32gpr.S -+ $(crt_compile) -c e500crtres32gpr.S -+ -+e500crtres64gpr$(objext): e500crtres64gpr.S -+ $(crt_compile) -c e500crtres64gpr.S -+ -+e500crtres64gprctr$(objext): e500crtres64gprctr.S -+ $(crt_compile) -c e500crtres64gprctr.S -+ -+e500crtrest32gpr$(objext): e500crtrest32gpr.S -+ $(crt_compile) -c e500crtrest32gpr.S -+ -+e500crtrest64gpr$(objext): e500crtrest64gpr.S -+ $(crt_compile) -c e500crtrest64gpr.S -+ -+e500crtresx32gpr$(objext): e500crtresx32gpr.S -+ $(crt_compile) -c e500crtresx32gpr.S -+ -+e500crtresx64gpr$(objext): e500crtresx64gpr.S -+ $(crt_compile) -c e500crtresx64gpr.S -+ -+e500crtsav32gpr$(objext): e500crtsav32gpr.S -+ $(crt_compile) -c e500crtsav32gpr.S -+ -+e500crtsav64gpr$(objext): e500crtsav64gpr.S -+ $(crt_compile) -c e500crtsav64gpr.S -+ -+e500crtsav64gprctr$(objext): e500crtsav64gprctr.S -+ $(crt_compile) -c e500crtsav64gprctr.S -+ -+e500crtsavg32gpr$(objext): e500crtsavg32gpr.S -+ $(crt_compile) -c e500crtsavg32gpr.S -+ -+e500crtsavg64gpr$(objext): e500crtsavg64gpr.S -+ $(crt_compile) -c e500crtsavg64gpr.S -+ -+e500crtsavg64gprctr$(objext): e500crtsavg64gprctr.S -+ $(crt_compile) -c e500crtsavg64gprctr.S ---- a/libgcc/config.host -+++ b/libgcc/config.host -@@ -203,12 +203,15 @@ - arm*-*-netbsd*) - ;; - arm*-*-linux*) # ARM GNU/Linux with ELF -+ tmake_file="${tmake_file} arm/t-divmod-ef" - ;; - arm*-*-uclinux*) # ARM ucLinux -+ tmake_file="${tmake_file} arm/t-divmod-ef" - ;; - arm*-*-ecos-elf) - ;; - arm*-*-eabi* | arm*-*-symbianelf* ) -+ tmake_file="${tmake_file} arm/t-divmod-ef" - ;; - arm*-*-rtems*) - ;; -@@ -394,8 +397,12 @@ - mips*-*-netbsd*) # NetBSD/mips, either endian. - ;; - mips64*-*-linux*) -+ extra_parts="$extra_parts crtfastmath.o" -+ tmake_file="{$tmake_file} mips/t-crtfm" - ;; - mips*-*-linux*) # Linux MIPS, either endian. -+ extra_parts="$extra_parts crtfastmath.o" -+ tmake_file="{$tmake_file} mips/t-crtfm" - ;; - mips*-*-openbsd*) - ;; -@@ -419,6 +426,10 @@ - ;; - mips64orion-*-elf* | mips64orionel-*-elf*) - ;; -+mips64octeon-wrs-elf* | mips64octeonel-wrs-elf*) -+ ;; -+mips64octeon-montavista-elf*) -+ ;; - mips*-*-rtems*) - ;; - mips-wrs-vxworks) ---- a/libgcc/Makefile.in -+++ b/libgcc/Makefile.in -@@ -389,18 +389,24 @@ - endif - endif - -+ifeq ($(LIB2_DIVMOD_EXCEPTION_FLAGS),) -+# Provide default flags for compiling divmod functions, if they haven't been -+# set already by a target-specific Makefile fragment. -+LIB2_DIVMOD_EXCEPTION_FLAGS := -fexceptions -fnon-call-exceptions -+endif -+ - # Build LIB2_DIVMOD_FUNCS. - lib2-divmod-o = $(patsubst %,%$(objext),$(LIB2_DIVMOD_FUNCS)) - $(lib2-divmod-o): %$(objext): $(gcc_srcdir)/libgcc2.c - $(gcc_compile) -DL$* -c $(gcc_srcdir)/libgcc2.c \ -- -fexceptions -fnon-call-exceptions $(vis_hide) -+ $(LIB2_DIVMOD_EXCEPTION_FLAGS) $(vis_hide) - libgcc-objects += $(lib2-divmod-o) - - ifeq ($(enable_shared),yes) - lib2-divmod-s-o = $(patsubst %,%_s$(objext),$(LIB2_DIVMOD_FUNCS)) - $(lib2-divmod-s-o): %_s$(objext): $(gcc_srcdir)/libgcc2.c - $(gcc_s_compile) -DL$* -c $(gcc_srcdir)/libgcc2.c \ -- -fexceptions -fnon-call-exceptions -+ $(LIB2_DIVMOD_EXCEPTION_FLAGS) - libgcc-s-objects += $(lib2-divmod-s-o) - endif - ---- a/libgcc/shared-object.mk -+++ b/libgcc/shared-object.mk -@@ -8,11 +8,13 @@ - - ifeq ($(suffix $o),.c) - -+c_flags-$(base)$(objext) := $(c_flags) - $(base)$(objext): $o -- $(gcc_compile) $(c_flags) -c $< $(vis_hide) -+ $(gcc_compile) $(c_flags-$@) -c $< $(vis_hide) - -+c_flags-$(base)_s$(objext) := $(c_flags) - $(base)_s$(objext): $o -- $(gcc_s_compile) $(c_flags) -c $< -+ $(gcc_s_compile) $(c_flags-$@) -c $< - - else - ---- a/libgcc/static-object.mk -+++ b/libgcc/static-object.mk -@@ -8,8 +8,9 @@ - - ifeq ($(suffix $o),.c) - -+c_flags-$(base)$(objext) := $(c_flags) - $(base)$(objext): $o -- $(gcc_compile) $(c_flags) -c $< $(vis_hide) -+ $(gcc_compile) $(c_flags-$@) -c $< $(vis_hide) - - else - ---- a/libiberty/argv.c -+++ b/libiberty/argv.c -@@ -119,6 +119,24 @@ - } - } - -+static void -+consume_whitespace (const char **input) -+{ -+ while (ISSPACE (**input)) -+ { -+ (*input)++; -+ } -+} -+ -+static int -+only_whitespace (const char* input) -+{ -+ while (*input != EOS && ISSPACE (*input)) -+ input++; -+ -+ return (*input == EOS); -+} -+ - /* - - @deftypefn Extension char** buildargv (char *@var{sp}) -@@ -179,10 +197,8 @@ - do - { - /* Pick off argv[argc] */ -- while (ISBLANK (*input)) -- { -- input++; -- } -+ consume_whitespace (&input); -+ - if ((maxargc == 0) || (argc >= (maxargc - 1))) - { - /* argv needs initialization, or expansion */ -@@ -278,10 +294,7 @@ - argc++; - argv[argc] = NULL; - -- while (ISSPACE (*input)) -- { -- input++; -- } -+ consume_whitespace (&input); - } - while (*input != EOS); - } -@@ -420,8 +433,17 @@ - goto error; - /* Add a NUL terminator. */ - buffer[len] = '\0'; -- /* Parse the string. */ -- file_argv = buildargv (buffer); -+ /* If the file is empty or contains only whitespace, buildargv would -+ return a single empty argument. In this context we want no arguments, -+ instead. */ -+ if (only_whitespace (buffer)) -+ { -+ file_argv = (char **) xmalloc (sizeof (char *)); -+ file_argv[0] = NULL; -+ } -+ else -+ /* Parse the string. */ -+ file_argv = buildargv (buffer); - /* If *ARGVP is not already dynamically allocated, copy it. */ - if (!argv_dynamic) - { -@@ -434,7 +456,7 @@ - } - /* Count the number of arguments. */ - file_argc = 0; -- while (file_argv[file_argc] && *file_argv[file_argc]) -+ while (file_argv[file_argc]) - ++file_argc; - /* Now, insert FILE_ARGV into ARGV. The "+1" below handles the - NULL terminator at the end of ARGV. */ ---- a/libstdc++-v3/config/cpu/sh/atomicity.h -+++ b/libstdc++-v3/config/cpu/sh/atomicity.h -@@ -25,47 +25,48 @@ - - #ifdef __SH4A__ - --#ifndef _GLIBCXX_ATOMICITY_H --#define _GLIBCXX_ATOMICITY_H 1 -+#include <ext/atomicity.h> - --typedef int _Atomic_word; -+_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) - --static inline _Atomic_word --__attribute__ ((__unused__)) --__exchange_and_add (volatile _Atomic_word* __mem, int __val) --{ -- _Atomic_word __result; -+ typedef int _Atomic_word; - -- __asm__ __volatile__ -- ("0:\n" -- "\tmovli.l\t@%2,r0\n" -- "\tmov\tr0,%1\n" -- "\tadd\t%3,r0\n" -- "\tmovco.l\tr0,@%2\n" -- "\tbf\t0b" -- : "+m" (*__mem), "=r" (__result) -- : "r" (__mem), "rI08" (__val) -- : "r0"); -- -- return __result; --} -- -- --static inline void --__attribute__ ((__unused__)) --__atomic_add (volatile _Atomic_word* __mem, int __val) --{ -- asm("0:\n" -- "\tmovli.l\t@%1,r0\n" -- "\tadd\t%2,r0\n" -- "\tmovco.l\tr0,@%1\n" -- "\tbf\t0b" -- : "+m" (*__mem) -- : "r" (__mem), "rI08" (__val) -- : "r0"); --} -+ _Atomic_word -+ __attribute__ ((__unused__)) -+ __exchange_and_add (volatile _Atomic_word* __mem, int __val) -+ { -+ _Atomic_word __result; - --#endif -+ __asm__ __volatile__ -+ ("0:\n" -+ "\tmovli.l\t@%2,r0\n" -+ "\tmov\tr0,%1\n" -+ "\tadd\t%3,r0\n" -+ "\tmovco.l\tr0,@%2\n" -+ "\tbf\t0b" -+ : "+m" (*__mem), "=&r" (__result) -+ : "r" (__mem), "rI08" (__val) -+ : "r0"); -+ -+ return __result; -+ } -+ -+ -+ void -+ __attribute__ ((__unused__)) -+ __atomic_add (volatile _Atomic_word* __mem, int __val) -+ { -+ asm("0:\n" -+ "\tmovli.l\t@%1,r0\n" -+ "\tadd\t%2,r0\n" -+ "\tmovco.l\tr0,@%1\n" -+ "\tbf\t0b" -+ : "+m" (*__mem) -+ : "r" (__mem), "rI08" (__val) -+ : "r0"); -+ } -+ -+_GLIBCXX_END_NAMESPACE - - #else /* !__SH4A__ */ - ---- a/libstdc++-v3/libsupc++/eh_arm.cc -+++ b/libstdc++-v3/libsupc++/eh_arm.cc -@@ -38,7 +38,7 @@ - extern "C" __cxa_type_match_result - __cxa_type_match(_Unwind_Exception* ue_header, - const std::type_info* catch_type, -- bool is_reference __attribute__((__unused__)), -+ bool is_reference, - void** thrown_ptr_p) - { - bool forced_unwind = __is_gxx_forced_unwind_class(ue_header->exception_class); -@@ -68,11 +68,11 @@ - if (throw_type->__is_pointer_p()) - thrown_ptr = *(void**) thrown_ptr; - -- if (catch_type->__do_catch(throw_type, &thrown_ptr, 1)) -+ if (catch_type->__do_catch (throw_type, &thrown_ptr, 1 + is_reference * 2)) - { - *thrown_ptr_p = thrown_ptr; - -- if (typeid(*catch_type) == typeid (typeid(void*))) -+ if (typeid (*catch_type) == typeid (typeid(void*))) - { - const __pointer_type_info *catch_pointer_type = - static_cast<const __pointer_type_info *> (catch_type); ---- a/libstdc++-v3/libsupc++/eh_personality.cc -+++ b/libstdc++-v3/libsupc++/eh_personality.cc -@@ -89,20 +89,22 @@ - // Return an element from a type table. - - static const std::type_info* --get_ttype_entry(lsda_header_info* info, _uleb128_t i) -+get_ttype_entry(lsda_header_info* info, _uleb128_t i, bool &is_ref) - { - _Unwind_Ptr ptr; - - ptr = (_Unwind_Ptr) (info->TType - (i * 4)); - ptr = _Unwind_decode_target2(ptr); - -- return reinterpret_cast<const std::type_info *>(ptr); -+ is_ref = ptr & 1; -+ -+ return reinterpret_cast<const std::type_info *>(ptr & ~1); - } - - // The ABI provides a routine for matching exception object types. - typedef _Unwind_Control_Block _throw_typet; --#define get_adjusted_ptr(catch_type, throw_type, thrown_ptr_p) \ -- (__cxa_type_match (throw_type, catch_type, false, thrown_ptr_p) \ -+#define get_adjusted_ptr(catch_type, throw_type, is_ref, thrown_ptr_p) \ -+ (__cxa_type_match (throw_type, catch_type, is_ref, thrown_ptr_p) \ - != ctm_failed) - - // Return true if THROW_TYPE matches one if the filter types. -@@ -118,6 +120,7 @@ - { - const std::type_info* catch_type; - _uleb128_t tmp; -+ bool is_ref; - - tmp = *e; - -@@ -129,13 +132,14 @@ - tmp = _Unwind_decode_target2((_Unwind_Word) e); - - // Match a ttype entry. -- catch_type = reinterpret_cast<const std::type_info*>(tmp); -+ is_ref = tmp & 1; -+ catch_type = reinterpret_cast<const std::type_info*>(tmp & ~1); - - // ??? There is currently no way to ask the RTTI code about the - // relationship between two types without reference to a specific - // object. There should be; then we wouldn't need to mess with - // thrown_ptr here. -- if (get_adjusted_ptr(catch_type, throw_type, &thrown_ptr)) -+ if (get_adjusted_ptr(catch_type, throw_type, is_ref, &thrown_ptr)) - return true; - - // Advance to the next entry. -@@ -207,7 +211,7 @@ - // Return an element from a type table. - - static const std::type_info * --get_ttype_entry (lsda_header_info *info, _uleb128_t i) -+get_ttype_entry (lsda_header_info *info, _uleb128_t i, bool &is_ref) - { - _Unwind_Ptr ptr; - -@@ -215,7 +219,9 @@ - read_encoded_value_with_base (info->ttype_encoding, info->ttype_base, - info->TType - i, &ptr); - -- return reinterpret_cast<const std::type_info *>(ptr); -+ is_ref = ptr & 1; -+ -+ return reinterpret_cast<const std::type_info *>(ptr & ~1); - } - - // Given the thrown type THROW_TYPE, pointer to a variable containing a -@@ -226,6 +232,7 @@ - static bool - get_adjusted_ptr (const std::type_info *catch_type, - const std::type_info *throw_type, -+ bool is_ref, - void **thrown_ptr_p) - { - void *thrown_ptr = *thrown_ptr_p; -@@ -237,7 +244,7 @@ - if (throw_type->__is_pointer_p ()) - thrown_ptr = *(void **) thrown_ptr; - -- if (catch_type->__do_catch (throw_type, &thrown_ptr, 1)) -+ if (catch_type->__do_catch (throw_type, &thrown_ptr, 1 + is_ref * 2)) - { - *thrown_ptr_p = thrown_ptr; - return true; -@@ -267,13 +274,15 @@ - return false; - - // Match a ttype entry. -- catch_type = get_ttype_entry (info, tmp); -+ bool is_ref; -+ -+ catch_type = get_ttype_entry (info, tmp, is_ref); - - // ??? There is currently no way to ask the RTTI code about the - // relationship between two types without reference to a specific - // object. There should be; then we wouldn't need to mess with - // thrown_ptr here. -- if (get_adjusted_ptr (catch_type, throw_type, &thrown_ptr)) -+ if (get_adjusted_ptr (catch_type, throw_type, is_ref, &thrown_ptr)) - return true; - } - } -@@ -582,14 +591,16 @@ - else if (ar_filter > 0) - { - // Positive filter values are handlers. -- catch_type = get_ttype_entry (&info, ar_filter); -+ bool is_ref; -+ -+ catch_type = get_ttype_entry (&info, ar_filter, is_ref); - - // Null catch type is a catch-all handler; we can catch foreign - // exceptions with this. Otherwise we must match types. - if (! catch_type - || (throw_type - && get_adjusted_ptr (catch_type, throw_type, -- &thrown_ptr))) -+ is_ref, &thrown_ptr))) - { - saw_handler = true; - break; ---- a/libcpp/Makefile.in -+++ b/libcpp/Makefile.in -@@ -72,13 +72,12 @@ - libcpp_a_OBJS = charset.o directives.o directives-only.o errors.o \ - expr.o files.o identifiers.o init.o lex.o line-map.o macro.o \ - mkdeps.o pch.o symtab.o traditional.o --makedepend_OBJS = makedepend.o - - libcpp_a_SOURCES = charset.c directives.c directives-only.c errors.c \ - expr.c files.c identifiers.c init.c lex.c line-map.c macro.c \ - mkdeps.c pch.c symtab.c traditional.c - --all: libcpp.a makedepend$(EXEEXT) $(USED_CATALOGS) -+all: libcpp.a $(USED_CATALOGS) - - .SUFFIXES: - .SUFFIXES: .c .gmo .o .obj .po .pox -@@ -88,12 +87,6 @@ - $(AR) $(ARFLAGS) libcpp.a $(libcpp_a_OBJS) - $(RANLIB) libcpp.a - --makedepend$(EXEEXT): $(makedepend_OBJS) libcpp.a ../libiberty/libiberty.a -- @rm -f makedepend$(EXEEXT) -- $(CC) $(CFLAGS) $(LDFLAGS) -o makedepend$(EXEEXT) \ -- $(makedepend_OBJS) libcpp.a ../libiberty/libiberty.a \ -- $(LIBINTL) $(LIBICONV) -- - # Rules to rebuild the configuration - - Makefile: $(srcdir)/Makefile.in config.status -@@ -165,7 +158,7 @@ - -rm -f *.o - - clean: mostlyclean -- -rm -rf makedepend$(EXEEXT) libcpp.a $(srcdir)/autom4te.cache -+ -rm -rf libcpp.a $(srcdir)/autom4te.cache - - distclean: clean - -rm -f config.h stamp-h1 config.status config.cache config.log \ -@@ -247,7 +240,7 @@ - sed 's:$(srcdir)/::g' <po/$(PACKAGE).pot.tmp >po/$(PACKAGE).pot - rm po/$(PACKAGE).pot.tmp - --TAGS_SOURCES = $(libcpp_a_SOURCES) makedepend.c internal.h ucnid.h \ -+TAGS_SOURCES = $(libcpp_a_SOURCES) internal.h ucnid.h \ - include/line-map.h include/symtab.h include/cpp-id-data.h \ - include/cpplib.h include/mkdeps.h system.h - -@@ -259,7 +252,7 @@ - .NOEXPORT: - - # Dependencies ---include $(patsubst %.o, $(DEPDIR)/%.Po, $(libcpp_a_OBJS) $(makedepend_OBJS)) -+-include $(patsubst %.o, $(DEPDIR)/%.Po, $(libcpp_a_OBJS)) - - # Dependencies on generated headers have to be explicit. - init.o: localedir.h diff --git a/toolchain/gcc/patches/4.4.1+cs/100-uclibc-conf.patch b/toolchain/gcc/patches/4.4.1+cs/100-uclibc-conf.patch deleted file mode 100644 index 7c6b791162..0000000000 --- a/toolchain/gcc/patches/4.4.1+cs/100-uclibc-conf.patch +++ /dev/null @@ -1,33 +0,0 @@ ---- a/contrib/regression/objs-gcc.sh -+++ b/contrib/regression/objs-gcc.sh -@@ -106,6 +106,10 @@ - then - make all-gdb all-dejagnu all-ld || exit 1 - make install-gdb install-dejagnu install-ld || exit 1 -+elif [ $H_REAL_TARGET = $H_REAL_HOST -a $H_REAL_TARGET = i686-pc-linux-uclibc ] -+ then -+ make all-gdb all-dejagnu all-ld || exit 1 -+ make install-gdb install-dejagnu install-ld || exit 1 - elif [ $H_REAL_TARGET = $H_REAL_HOST ] ; then - make bootstrap || exit 1 - make install || exit 1 ---- a/libjava/classpath/ltconfig -+++ b/libjava/classpath/ltconfig -@@ -603,7 +603,7 @@ - - # Transform linux* to *-*-linux-gnu*, to support old configure scripts. - case $host_os in --linux-gnu*) ;; -+linux-gnu*|linux-uclibc*) ;; - linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` - esac - -@@ -1251,7 +1251,7 @@ - ;; - - # This must be Linux ELF. --linux-gnu*) -+linux*) - version_type=linux - need_lib_prefix=no - need_version=no diff --git a/toolchain/gcc/patches/4.4.1+cs/106-fix_linker_error.patch b/toolchain/gcc/patches/4.4.1+cs/106-fix_linker_error.patch deleted file mode 100644 index 57698ea5e9..0000000000 --- a/toolchain/gcc/patches/4.4.1+cs/106-fix_linker_error.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/gcc/cp/Make-lang.in -+++ b/gcc/cp/Make-lang.in -@@ -72,8 +72,7 @@ g++-cross$(exeext): g++$(exeext) - # Shared with C front end: - CXX_C_OBJS = attribs.o c-common.o c-format.o c-pragma.o c-semantics.o c-lex.o \ - c-dump.o $(CXX_TARGET_OBJS) c-pretty-print.o c-opts.o c-pch.o \ -- incpath.o cppdefault.o c-ppoutput.o c-cppbuiltin.o prefix.o \ -- c-gimplify.o c-omp.o tree-inline.o -+ incpath.o c-ppoutput.o c-cppbuiltin.o prefix.o c-gimplify.o c-omp.o - - # Language-specific object files for C++ and Objective C++. - CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \ diff --git a/toolchain/gcc/patches/4.4.1+cs/301-missing-execinfo_h.patch b/toolchain/gcc/patches/4.4.1+cs/301-missing-execinfo_h.patch deleted file mode 100644 index 5a7aa4e47d..0000000000 --- a/toolchain/gcc/patches/4.4.1+cs/301-missing-execinfo_h.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/boehm-gc/include/gc.h -+++ b/boehm-gc/include/gc.h -@@ -503,7 +503,7 @@ - #if defined(__linux__) || defined(__GLIBC__) - # include <features.h> - # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \ -- && !defined(__ia64__) -+ && !defined(__ia64__) && !defined(__UCLIBC__) - # ifndef GC_HAVE_BUILTIN_BACKTRACE - # define GC_HAVE_BUILTIN_BACKTRACE - # endif diff --git a/toolchain/gcc/patches/4.4.1+cs/302-c99-snprintf.patch b/toolchain/gcc/patches/4.4.1+cs/302-c99-snprintf.patch deleted file mode 100644 index f0ba5411ed..0000000000 --- a/toolchain/gcc/patches/4.4.1+cs/302-c99-snprintf.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/libstdc++-v3/include/c_global/cstdio -+++ b/libstdc++-v3/include/c_global/cstdio -@@ -139,7 +139,7 @@ - - _GLIBCXX_END_NAMESPACE - --#if _GLIBCXX_USE_C99 -+#if _GLIBCXX_USE_C99 || defined __UCLIBC__ - - #undef snprintf - #undef vfscanf diff --git a/toolchain/gcc/patches/4.4.1+cs/305-libmudflap-susv3-legacy.patch b/toolchain/gcc/patches/4.4.1+cs/305-libmudflap-susv3-legacy.patch deleted file mode 100644 index 5bc4aebb67..0000000000 --- a/toolchain/gcc/patches/4.4.1+cs/305-libmudflap-susv3-legacy.patch +++ /dev/null @@ -1,47 +0,0 @@ ---- a/libmudflap/mf-hooks2.c -+++ b/libmudflap/mf-hooks2.c -@@ -421,7 +421,7 @@ - { - TRACE ("%s\n", __PRETTY_FUNCTION__); - MF_VALIDATE_EXTENT(s, n, __MF_CHECK_WRITE, "bzero region"); -- bzero (s, n); -+ memset (s, 0, n); - } - - -@@ -431,7 +431,7 @@ - TRACE ("%s\n", __PRETTY_FUNCTION__); - MF_VALIDATE_EXTENT(src, n, __MF_CHECK_READ, "bcopy src"); - MF_VALIDATE_EXTENT(dest, n, __MF_CHECK_WRITE, "bcopy dest"); -- bcopy (src, dest, n); -+ memmove (dest, src, n); - } - - -@@ -441,7 +441,7 @@ - TRACE ("%s\n", __PRETTY_FUNCTION__); - MF_VALIDATE_EXTENT(s1, n, __MF_CHECK_READ, "bcmp 1st arg"); - MF_VALIDATE_EXTENT(s2, n, __MF_CHECK_READ, "bcmp 2nd arg"); -- return bcmp (s1, s2, n); -+ return n == 0 ? 0 : memcmp (s1, s2, n); - } - - -@@ -450,7 +450,7 @@ - size_t n = strlen (s); - TRACE ("%s\n", __PRETTY_FUNCTION__); - MF_VALIDATE_EXTENT(s, CLAMPADD(n, 1), __MF_CHECK_READ, "index region"); -- return index (s, c); -+ return strchr (s, c); - } - - -@@ -459,7 +459,7 @@ - size_t n = strlen (s); - TRACE ("%s\n", __PRETTY_FUNCTION__); - MF_VALIDATE_EXTENT(s, CLAMPADD(n, 1), __MF_CHECK_READ, "rindex region"); -- return rindex (s, c); -+ return strrchr (s, c); - } - - /* XXX: stpcpy, memccpy */ diff --git a/toolchain/gcc/patches/4.4.1+cs/600-ubicom_support.patch b/toolchain/gcc/patches/4.4.1+cs/600-ubicom_support.patch deleted file mode 100644 index 9a02598903..0000000000 --- a/toolchain/gcc/patches/4.4.1+cs/600-ubicom_support.patch +++ /dev/null @@ -1,9368 +0,0 @@ ---- a/configure -+++ b/configure -@@ -2688,6 +2688,9 @@ - ip2k-*-*) - noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj}" - ;; -+ ubicom32-*-*) -+ noconfigdirs="$noconfigdirs target-libffi" -+ ;; - *-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu | *-*-kopensolaris*-gnu) - noconfigdirs="$noconfigdirs target-newlib target-libgloss" - ;; ---- /dev/null -+++ b/gcc/config/ubicom32/constraints.md -@@ -0,0 +1,149 @@ -+; Constraint definitions for Ubicom32 -+ -+; Copyright (C) 2009 Free Software Foundation, Inc. -+; Contributed by Ubicom, Inc. -+ -+; This file is part of GCC. -+ -+; GCC is free software; you can redistribute it and/or modify it -+; under the terms of the GNU General Public License as published -+; by the Free Software Foundation; either version 3, or (at your -+; option) any later version. -+ -+; GCC is distributed in the hope that it will be useful, but WITHOUT -+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+; License for more details. -+ -+; You should have received a copy of the GNU General Public License -+; along with GCC; see the file COPYING3. If not see -+; <http://www.gnu.org/licenses/>. -+ -+(define_register_constraint "a" "ALL_ADDRESS_REGS" -+ "An An register.") -+ -+(define_register_constraint "d" "DATA_REGS" -+ "A Dn register.") -+ -+(define_register_constraint "h" "ACC_REGS" -+ "An accumulator register.") -+ -+(define_register_constraint "l" "ACC_LO_REGS" -+ "An accn_lo register.") -+ -+(define_register_constraint "Z" "FDPIC_REG" -+ "The FD-PIC GOT pointer: A0.") -+ -+(define_constraint "I" -+ "An 8-bit signed constant value." -+ (and (match_code "const_int") -+ (match_test "(ival >= -128) && (ival <= 127)"))) -+ -+(define_constraint "Q" -+ "An 8-bit signed constant value represented as unsigned." -+ (and (match_code "const_int") -+ (match_test "(ival >= 0x00) && (ival <= 0xff)"))) -+ -+(define_constraint "R" -+ "An 8-bit signed constant value represented as unsigned." -+ (and (match_code "const_int") -+ (match_test "((ival >= 0x0000) && (ival <= 0x007f)) || ((ival >= 0xff80) && (ival <= 0xffff))"))) -+ -+(define_constraint "J" -+ "A 7-bit unsigned constant value." -+ (and (match_code "const_int") -+ (match_test "(ival >= 0) && (ival <= 127)"))) -+ -+(define_constraint "K" -+ "A 7-bit unsigned constant value shifted << 1." -+ (and (match_code "const_int") -+ (match_test "(ival >= 0) && (ival <= 254) && ((ival & 1) == 0)"))) -+ -+(define_constraint "L" -+ "A 7-bit unsigned constant value shifted << 2." -+ (and (match_code "const_int") -+ (match_test "(ival >= 0) && (ival <= 508) && ((ival & 3) == 0)"))) -+ -+(define_constraint "M" -+ "A 5-bit unsigned constant value." -+ (and (match_code "const_int") -+ (match_test "(ival >= 0) && (ival <= 31)"))) -+ -+(define_constraint "N" -+ "A signed 16 bit constant value." -+ (and (match_code "const_int") -+ (match_test "(ival >= -32768) && (ival <= 32767)"))) -+ -+(define_constraint "O" -+ "An exact bitmask of contiguous 1 bits starting at bit 0." -+ (and (match_code "const_int") -+ (match_test "exact_log2 (ival + 1) != -1"))) -+ -+(define_constraint "P" -+ "A 7-bit negative constant value shifted << 2." -+ (and (match_code "const_int") -+ (match_test "(ival >= -504) && (ival <= 0) && ((ival & 3) == 0)"))) -+ -+(define_constraint "S" -+ "A symbolic reference." -+ (match_code "symbol_ref")) -+ -+(define_constraint "Y" -+ "An FD-PIC symbolic reference." -+ (and (match_test "TARGET_FDPIC") -+ (match_test "GET_CODE (op) == UNSPEC") -+ (ior (match_test "XINT (op, 1) == UNSPEC_FDPIC_GOT") -+ (match_test "XINT (op, 1) == UNSPEC_FDPIC_GOT_FUNCDESC")))) -+ -+(define_memory_constraint "T1" -+ "A memory operand that can be used for .1 instruction." -+ (and (match_test "memory_operand (op, GET_MODE(op))") -+ (match_test "GET_MODE (op) == QImode"))) -+ -+(define_memory_constraint "T2" -+ "A memory operand that can be used for .2 instruction." -+ (and (match_test "memory_operand (op, GET_MODE(op))") -+ (match_test "GET_MODE (op) == HImode"))) -+ -+(define_memory_constraint "T4" -+ "A memory operand that can be used for .4 instruction." -+ (and (match_test "memory_operand (op, GET_MODE(op))") -+ (ior (match_test "GET_MODE (op) == SImode") -+ (match_test "GET_MODE (op) == DImode") -+ (match_test "GET_MODE (op) == SFmode")))) -+ -+(define_memory_constraint "U1" -+ "An offsettable memory operand that can be used for .1 instruction." -+ (and (match_test "memory_operand (op, GET_MODE(op))") -+ (match_test "GET_MODE (op) == QImode") -+ (match_test "GET_CODE (XEXP (op, 0)) != POST_INC") -+ (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC") -+ (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC") -+ (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC") -+ (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY") -+ (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY"))) -+ -+(define_memory_constraint "U2" -+ "An offsettable memory operand that can be used for .2 instruction." -+ (and (match_test "memory_operand (op, GET_MODE(op))") -+ (match_test "GET_MODE (op) == HImode") -+ (match_test "GET_CODE (XEXP (op, 0)) != POST_INC") -+ (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC") -+ (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC") -+ (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC") -+ (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY") -+ (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY"))) -+ -+(define_memory_constraint "U4" -+ "An offsettable memory operand that can be used for .4 instruction." -+ (and (match_test "memory_operand (op, GET_MODE(op))") -+ (ior (match_test "GET_MODE (op) == SImode") -+ (match_test "GET_MODE (op) == DImode") -+ (match_test "GET_MODE (op) == SFmode")) -+ (match_test "GET_CODE (XEXP (op, 0)) != POST_INC") -+ (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC") -+ (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC") -+ (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC") -+ (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY") -+ (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY"))) -+ ---- /dev/null -+++ b/gcc/config/ubicom32/crti.S -@@ -0,0 +1,54 @@ -+/* Specialized code needed to support construction and destruction of -+ file-scope objects in C++ and Java code, and to support exception handling. -+ Copyright (C) 1999 Free Software Foundation, Inc. -+ Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca). -+ -+This file is part of GCC. -+ -+GCC is free software; you can redistribute it and/or modify -+it under the terms of the GNU General Public License as published by -+the Free Software Foundation; either version 2, or (at your option) -+any later version. -+ -+GCC is distributed in the hope that it will be useful, -+but WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+GNU General Public License for more details. -+ -+You should have received a copy of the GNU General Public License -+along with GCC; see the file COPYING. If not, write to -+the Free Software Foundation, 59 Temple Place - Suite 330, -+Boston, MA 02111-1307, USA. */ -+ -+/* As a special exception, if you link this library with files -+ compiled with GCC to produce an executable, this does not cause -+ the resulting executable to be covered by the GNU General Public License. -+ This exception does not however invalidate any other reasons why -+ the executable file might be covered by the GNU General Public License. */ -+ -+/* -+ * This file just supplies function prologues for the .init and .fini -+ * sections. It is linked in before crtbegin.o. -+ */ -+ .file "crti.o" -+ .ident "GNU C crti.o" -+ -+ .section .init -+ .align 2 -+ .globl _init -+ .type _init, @function -+_init: -+ move.4 -4(sp)++, a5 -+#ifdef __UBICOM32_FDPIC__ -+ move.4 -4(sp)++, a0 -+#endif -+ -+ .section .fini -+ .align 2 -+ .globl _fini -+ .type _fini, @function -+_fini: -+ move.4 -4(sp)++, a5 -+#ifdef __UBICOM32_FDPIC__ -+ move.4 -4(sp)++, a0 -+#endif ---- /dev/null -+++ b/gcc/config/ubicom32/crtn.S -@@ -0,0 +1,47 @@ -+/* Specialized code needed to support construction and destruction of -+ file-scope objects in C++ and Java code, and to support exception handling. -+ Copyright (C) 1999 Free Software Foundation, Inc. -+ Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca). -+ -+This file is part of GCC. -+ -+GCC is free software; you can redistribute it and/or modify -+it under the terms of the GNU General Public License as published by -+the Free Software Foundation; either version 2, or (at your option) -+any later version. -+ -+GCC is distributed in the hope that it will be useful, -+but WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+GNU General Public License for more details. -+ -+You should have received a copy of the GNU General Public License -+along with GCC; see the file COPYING. If not, write to -+the Free Software Foundation, 59 Temple Place - Suite 330, -+Boston, MA 02111-1307, USA. */ -+ -+/* As a special exception, if you link this library with files -+ compiled with GCC to produce an executable, this does not cause -+ the resulting executable to be covered by the GNU General Public License. -+ This exception does not however invalidate any other reasons why -+ the executable file might be covered by the GNU General Public License. */ -+ -+/* -+ * This file supplies function epilogues for the .init and .fini sections. -+ * It is linked in after all other files. -+ */ -+ -+ .file "crtn.o" -+ .ident "GNU C crtn.o" -+ -+ .section .init -+#ifdef __UBICOM32_FDPIC__ -+ move.4 a0, (sp)4++ -+#endif -+ ret (sp)4++ -+ -+ .section .fini -+#ifdef __UBICOM32_FDPIC__ -+ move.4 a0, (sp)4++ -+#endif -+ ret (sp)4++ ---- /dev/null -+++ b/gcc/config/ubicom32/elf.h -@@ -0,0 +1,29 @@ -+#undef STARTFILE_SPEC -+#define STARTFILE_SPEC "\ -+%{msim:%{!shared:crt0%O%s}} \ -+crti%O%s crtbegin%O%s" -+ -+#undef ENDFILE_SPEC -+#define ENDFILE_SPEC "crtend%O%s crtn%O%s" -+ -+#ifdef __UBICOM32_FDPIC__ -+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \ -+ asm (SECTION_OP); \ -+ asm ("move.4 a0, 0(sp);\n\t" \ -+ "call a5," USER_LABEL_PREFIX #FUNC ";"); \ -+ asm (TEXT_SECTION_ASM_OP); -+#endif -+ -+#undef SUBTARGET_DRIVER_SELF_SPECS -+#define SUBTARGET_DRIVER_SELF_SPECS \ -+ "%{mfdpic:-msim} " -+ -+#define NO_IMPLICIT_EXTERN_C -+ -+/* -+ * We need this to compile crtbegin/crtend. This should really be picked -+ * up from elfos.h but at the moment including elfos.h causes other more -+ * serous linker issues. -+ */ -+#define INIT_SECTION_ASM_OP "\t.section\t.init" -+#define FINI_SECTION_ASM_OP "\t.section\t.fini" ---- /dev/null -+++ b/gcc/config/ubicom32/linux.h -@@ -0,0 +1,80 @@ -+/* Definitions of target machine for Ubicom32-uclinux -+ -+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -+ 2009 Free Software Foundation, Inc. -+ Contributed by Ubicom, Inc. -+ -+ This file is part of GCC. -+ -+ GCC is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published -+ by the Free Software Foundation; either version 3, or (at your -+ option) any later version. -+ -+ GCC is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+ License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with GCC; see the file COPYING3. If not see -+ <http://www.gnu.org/licenses/>. */ -+ -+/* Don't assume anything about the header files. */ -+#define NO_IMPLICIT_EXTERN_C -+ -+#undef LIB_SPEC -+#define LIB_SPEC \ -+ "%{pthread:-lpthread} " \ -+ "-lc" -+ -+#undef LINK_GCC_C_SEQUENCE_SPEC -+#define LINK_GCC_C_SEQUENCE_SPEC \ -+ "%{static:--start-group} %G %L %{static:--end-group} " \ -+ "%{!static: %G}" -+ -+#undef STARTFILE_SPEC -+#define STARTFILE_SPEC \ -+ "%{!shared: %{pg|p|profile:gcrt1%O%s;pie:Scrt1%O%s;:crt1%O%s}} " \ -+ "crtreloc%O%s crti%O%s %{shared|pie:crtbeginS%O%s;:crtbegin%O%s}" -+ -+#undef ENDFILE_SPEC -+#define ENDFILE_SPEC \ -+ "%{shared|pie:crtendS%O%s;:crtend%O%s} crtn%O%s" -+ -+/* taken from linux.h */ -+/* The GNU C++ standard library requires that these macros be defined. */ -+#undef CPLUSPLUS_CPP_SPEC -+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)" -+ -+#define TARGET_OS_CPP_BUILTINS() \ -+ do { \ -+ builtin_define_std ("__UBICOM32__"); \ -+ builtin_define_std ("__ubicom32__"); \ -+ builtin_define ("__gnu_linux__"); \ -+ builtin_define_std ("linux"); \ -+ builtin_define_std ("unix"); \ -+ builtin_assert ("system=linux"); \ -+ builtin_assert ("system=unix"); \ -+ builtin_assert ("system=posix"); \ -+ } while (0) -+ -+#define OBJECT_FORMAT_ELF -+ -+ -+#undef DRIVER_SELF_SPECS -+#define DRIVER_SELF_SPECS \ -+ "%{!mno-fdpic:-mfdpic}" -+ -+#undef LINK_SPEC -+#define LINK_SPEC "%{mfdpic: -m elf32ubicom32fdpic -z text } %{shared} %{pie} \ -+ %{static:-dn -Bstatic} \ -+ %{shared:-G -Bdynamic} \ -+ %{!shared: %{!static: \ -+ %{rdynamic:-export-dynamic} \ -+ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \ -+ %{static}} " -+ -+/* -+#define MD_UNWIND_SUPPORT "config/bfin/linux-unwind.h" -+*/ ---- /dev/null -+++ b/gcc/config/ubicom32/predicates.md -@@ -0,0 +1,327 @@ -+; Predicate definitions for Ubicom32. -+ -+; Copyright (C) 2009 Free Software Foundation, Inc. -+; Contributed by Ubicom, Inc. -+ -+; This file is part of GCC. -+ -+; GCC is free software; you can redistribute it and/or modify it -+; under the terms of the GNU General Public License as published -+; by the Free Software Foundation; either version 3, or (at your -+; option) any later version. -+ -+; GCC is distributed in the hope that it will be useful, but WITHOUT -+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+; License for more details. -+ -+; You should have received a copy of the GNU General Public License -+; along with GCC; see the file COPYING3. If not see -+; <http://www.gnu.org/licenses/>. -+ -+(define_predicate "ubicom32_move_operand" -+ (match_code "const_int, const_double, const, mem, subreg, reg, lo_sum") -+{ -+ if (CONST_INT_P (op)) -+ return true; -+ -+ if (GET_CODE (op) == CONST_DOUBLE) -+ return true; -+ -+ if (GET_CODE (op) == CONST) -+ return memory_address_p (mode, op); -+ -+ if (GET_MODE (op) != mode) -+ return false; -+ -+ if (MEM_P (op)) -+ return memory_address_p (mode, XEXP (op, 0)); -+ -+ if (GET_CODE (op) == SUBREG) { -+ op = SUBREG_REG (op); -+ -+ if (REG_P (op)) -+ return true; -+ -+ if (! MEM_P (op)) -+ return false; -+ -+ /* Paradoxical SUBREG. */ -+ if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (op))) -+ return false; -+ -+ return memory_address_p (GET_MODE (op), XEXP (op, 0)); -+ } -+ -+ return register_operand (op, mode); -+}) -+ -+;; Returns true if OP is either a symbol reference or a sum of a -+;; symbol reference and a constant. -+ -+(define_predicate "ubicom32_symbolic_address_operand" -+ (match_code "symbol_ref, label_ref, const") -+{ -+ switch (GET_CODE (op)) -+ { -+ case SYMBOL_REF: -+ case LABEL_REF: -+ return true; -+ -+ case CONST: -+ op = XEXP (op, 0); -+ return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF -+ || GET_CODE (XEXP (op, 0)) == LABEL_REF) -+ && CONST_INT_P (XEXP (op, 1))); -+ -+ default: -+ return false; -+ } -+}) -+ -+;; Return true if operand is the uClinux FD-PIC register. -+ -+(define_predicate "ubicom32_fdpic_operand" -+ (match_code "reg") -+{ -+ if (! TARGET_FDPIC) -+ return false; -+ -+ if (!REG_P (op)) -+ return false; -+ -+ if (GET_MODE (op) != mode && mode != VOIDmode) -+ return false; -+ -+ if (REGNO (op) != FDPIC_REGNUM && REGNO (op) < FIRST_PSEUDO_REGISTER) -+ return false; -+ -+ return true; -+}) -+ -+(define_predicate "ubicom32_fdpic_got_offset_operand" -+ (match_code "unspec") -+{ -+ if (! TARGET_FDPIC) -+ return false; -+ -+ if (GET_CODE (op) != UNSPEC) -+ return false; -+ -+ if (XINT (op, 1) != UNSPEC_FDPIC_GOT -+ && XINT (op, 1) != UNSPEC_FDPIC_GOT_FUNCDESC) -+ return false; -+ -+ return true; -+}) -+ -+(define_predicate "ubicom32_arith_operand" -+ (match_code "subreg, reg, const_int, lo_sum, mem") -+{ -+ return (ubicom32_move_operand (op, mode) -+ && ! ubicom32_symbolic_address_operand (op, mode) -+ && (! CONST_INT_P (op) -+ || satisfies_constraint_I (op))); -+}) -+ -+(define_predicate "ubicom32_arith_operand_dot1" -+ (match_code "subreg, reg, const_int, lo_sum, mem") -+{ -+ return (ubicom32_move_operand (op, mode) -+ && ! ubicom32_symbolic_address_operand (op, mode) -+ && (! CONST_INT_P (op) -+ || satisfies_constraint_Q (op))); -+}) -+ -+(define_predicate "ubicom32_arith_operand_dot2" -+ (match_code "subreg, reg, const_int, lo_sum, mem") -+{ -+ return (ubicom32_move_operand (op, mode) -+ && ! ubicom32_symbolic_address_operand (op, mode) -+ && (! CONST_INT_P (op) -+ || satisfies_constraint_R (op))); -+}) -+ -+(define_predicate "ubicom32_compare_operand" -+ (match_code "subreg, reg, const_int, lo_sum, mem") -+{ -+ return (ubicom32_move_operand (op, mode) -+ && ! ubicom32_symbolic_address_operand (op, mode) -+ && (! CONST_INT_P (op) -+ || satisfies_constraint_N (op))); -+}) -+ -+(define_predicate "ubicom32_compare_operator" -+ (match_code "compare")) -+ -+(define_predicate "ubicom32_and_or_si3_operand" -+ (match_code "subreg, reg, const_int, lo_sum, mem") -+{ -+ return (ubicom32_arith_operand (op, mode) -+ || (CONST_INT_P (op) -+ && ((exact_log2 (INTVAL (op) + 1) != -1 -+ && exact_log2 (INTVAL (op) + 1) <= 31) -+ || (exact_log2 (INTVAL (op)) != -1 -+ && exact_log2 (INTVAL (op)) <= 31) -+ || (exact_log2 (~INTVAL (op)) != -1 -+ && exact_log2 (~INTVAL (op)) <= 31)))); -+}) -+ -+(define_predicate "ubicom32_and_or_hi3_operand" -+ (match_code "subreg, reg, const_int, lo_sum, mem") -+{ -+ return (ubicom32_arith_operand (op, mode) -+ || (CONST_INT_P (op) -+ && exact_log2 (INTVAL (op) + 1) != -1 -+ && exact_log2 (INTVAL (op) + 1) <= 15)); -+}) -+ -+(define_predicate "ubicom32_mem_or_address_register_operand" -+ (match_code "subreg, reg, mem") -+{ -+ unsigned int regno; -+ -+ if (MEM_P (op) -+ && memory_operand (op, mode)) -+ return true; -+ -+ if (REG_P (op)) -+ regno = REGNO (op); -+ else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op))) -+ { -+ int offset; -+ if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER) -+ offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op))); -+ else -+ offset = subreg_regno_offset (REGNO (SUBREG_REG (op)), -+ GET_MODE (SUBREG_REG (op)), -+ SUBREG_BYTE (op), -+ GET_MODE (op)); -+ regno = REGNO (SUBREG_REG (op)) + offset; -+ } -+ else -+ return false; -+ -+ return (regno >= FIRST_PSEUDO_REGISTER -+ || REGNO_REG_CLASS (regno) == FDPIC_REG -+ || REGNO_REG_CLASS (regno) == ADDRESS_REGS); -+}) -+ -+(define_predicate "ubicom32_data_register_operand" -+ (match_code "subreg, reg") -+{ -+ unsigned int regno; -+ -+ if (REG_P (op)) -+ regno = REGNO (op); -+ else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op))) -+ { -+ int offset; -+ if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER) -+ offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op))); -+ else -+ offset = subreg_regno_offset (REGNO (SUBREG_REG (op)), -+ GET_MODE (SUBREG_REG (op)), -+ SUBREG_BYTE (op), -+ GET_MODE (op)); -+ regno = REGNO (SUBREG_REG (op)) + offset; -+ } -+ else -+ return false; -+ -+ return ((regno >= FIRST_PSEUDO_REGISTER -+ && regno != REGNO (virtual_stack_vars_rtx)) -+ || REGNO_REG_CLASS (regno) == DATA_REGS); -+}) -+ -+(define_predicate "ubicom32_address_register_operand" -+ (match_code "subreg, reg") -+{ -+ unsigned int regno; -+ -+ if (REG_P (op)) -+ regno = REGNO (op); -+ else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op))) -+ { -+ int offset; -+ if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER) -+ offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op))); -+ else -+ offset = subreg_regno_offset (REGNO (SUBREG_REG (op)), -+ GET_MODE (SUBREG_REG (op)), -+ SUBREG_BYTE (op), -+ GET_MODE (op)); -+ regno = REGNO (SUBREG_REG (op)) + offset; -+ } -+ else -+ return false; -+ -+ return (regno >= FIRST_PSEUDO_REGISTER -+ || REGNO_REG_CLASS (regno) == FDPIC_REG -+ || REGNO_REG_CLASS (regno) == ADDRESS_REGS); -+}) -+ -+(define_predicate "ubicom32_acc_lo_register_operand" -+ (match_code "subreg, reg") -+{ -+ unsigned int regno; -+ -+ if (REG_P (op)) -+ regno = REGNO (op); -+ else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op))) -+ { -+ int offset; -+ if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER) -+ offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op))); -+ else -+ offset = subreg_regno_offset (REGNO (SUBREG_REG (op)), -+ GET_MODE (SUBREG_REG (op)), -+ SUBREG_BYTE (op), -+ GET_MODE (op)); -+ regno = REGNO (SUBREG_REG (op)) + offset; -+ } -+ else -+ return false; -+ -+ return ((regno >= FIRST_PSEUDO_REGISTER -+ && regno != REGNO (virtual_stack_vars_rtx)) -+ || REGNO_REG_CLASS (regno) == ACC_LO_REGS); -+}) -+ -+(define_predicate "ubicom32_acc_hi_register_operand" -+ (match_code "subreg, reg") -+{ -+ unsigned int regno; -+ -+ if (REG_P (op)) -+ regno = REGNO (op); -+ else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op))) -+ { -+ int offset; -+ if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER) -+ offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op))); -+ else -+ offset = subreg_regno_offset (REGNO (SUBREG_REG (op)), -+ GET_MODE (SUBREG_REG (op)), -+ SUBREG_BYTE (op), -+ GET_MODE (op)); -+ regno = REGNO (SUBREG_REG (op)) + offset; -+ } -+ else -+ return false; -+ -+ return ((regno >= FIRST_PSEUDO_REGISTER -+ && regno != REGNO (virtual_stack_vars_rtx)) -+ || REGNO_REG_CLASS (regno) == ACC_REGS); -+}) -+ -+(define_predicate "ubicom32_call_address_operand" -+ (match_code "symbol_ref, subreg, reg") -+{ -+ return (GET_CODE (op) == SYMBOL_REF || REG_P (op)); -+}) -+ -+(define_special_predicate "ubicom32_cc_register_operand" -+ (and (match_code "reg") -+ (match_test "REGNO (op) == CC_REGNUM"))) -+ ---- /dev/null -+++ b/gcc/config/ubicom32/t-ubicom32 -@@ -0,0 +1,52 @@ -+# Name of assembly file containing libgcc1 functions. -+# This entry must be present, but it can be empty if the target does -+# not need any assembler functions to support its code generation. -+CROSS_LIBGCC1 = -+ -+# Alternatively if assembler functions *are* needed then define the -+# entries below: -+# CROSS_LIBGCC1 = libgcc1-asm.a -+ -+LIB2FUNCS_EXTRA = \ -+ $(srcdir)/config/udivmodsi4.c \ -+ $(srcdir)/config/divmod.c \ -+ $(srcdir)/config/udivmod.c -+ -+# If any special flags are necessary when building libgcc2 put them here. -+# -+# TARGET_LIBGCC2_CFLAGS = -+ -+# We want fine grained libraries, so use the new code to build the -+# floating point emulation libraries. -+FPBIT = fp-bit.c -+DPBIT = dp-bit.c -+ -+fp-bit.c: $(srcdir)/config/fp-bit.c -+ echo '#define FLOAT' > fp-bit.c -+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c -+ -+dp-bit.c: $(srcdir)/config/fp-bit.c -+ cat $(srcdir)/config/fp-bit.c > dp-bit.c -+ -+# Commented out to speed up compiler development! -+# -+# MULTILIB_OPTIONS = march=ubicom32v1/march=ubicom32v2/march=ubicom32v3/march=ubicom32v4 -+# MULTILIB_DIRNAMES = ubicom32v1 ubicom32v2 ubicom32v3 ubicom32v4 -+ -+MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4 -+MULTILIB_OPTIONS += mfdpic -+MULTILIB_OPTIONS += mno-ipos-abi/mipos-abi -+MULTILIB_OPTIONS += fno-leading-underscore/fleading-underscore -+ -+# Assemble startup files. -+$(T)crti.o: $(srcdir)/config/ubicom32/crti.S $(GCC_PASSES) -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \ -+ -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/ubicom32/crti.S -+ -+$(T)crtn.o: $(srcdir)/config/ubicom32/crtn.S $(GCC_PASSES) -+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \ -+ -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/ubicom32/crtn.S -+ -+# these parts are required because uClibc ldso needs them to link. -+# they are not in the specfile so they will not be included automatically. -+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o crti.o crtn.o ---- /dev/null -+++ b/gcc/config/ubicom32/t-ubicom32-linux -@@ -0,0 +1,35 @@ -+# Name of assembly file containing libgcc1 functions. -+# This entry must be present, but it can be empty if the target does -+# not need any assembler functions to support its code generation. -+CROSS_LIBGCC1 = -+ -+# Alternatively if assembler functions *are* needed then define the -+# entries below: -+# CROSS_LIBGCC1 = libgcc1-asm.a -+ -+LIB2FUNCS_EXTRA = \ -+ $(srcdir)/config/udivmodsi4.c \ -+ $(srcdir)/config/divmod.c \ -+ $(srcdir)/config/udivmod.c -+ -+# If any special flags are necessary when building libgcc2 put them here. -+# -+# TARGET_LIBGCC2_CFLAGS = -+ -+# We want fine grained libraries, so use the new code to build the -+# floating point emulation libraries. -+FPBIT = fp-bit.c -+DPBIT = dp-bit.c -+ -+fp-bit.c: $(srcdir)/config/fp-bit.c -+ echo '#define FLOAT' > fp-bit.c -+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c -+ -+dp-bit.c: $(srcdir)/config/fp-bit.c -+ cat $(srcdir)/config/fp-bit.c > dp-bit.c -+ -+# We only support v3 and v4 ISAs for uClinux. -+ -+MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4 -+ -+#EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o ---- /dev/null -+++ b/gcc/config/ubicom32/t-ubicom32-uclinux -@@ -0,0 +1,35 @@ -+# Name of assembly file containing libgcc1 functions. -+# This entry must be present, but it can be empty if the target does -+# not need any assembler functions to support its code generation. -+CROSS_LIBGCC1 = -+ -+# Alternatively if assembler functions *are* needed then define the -+# entries below: -+# CROSS_LIBGCC1 = libgcc1-asm.a -+ -+LIB2FUNCS_EXTRA = \ -+ $(srcdir)/config/udivmodsi4.c \ -+ $(srcdir)/config/divmod.c \ -+ $(srcdir)/config/udivmod.c -+ -+# If any special flags are necessary when building libgcc2 put them here. -+# -+# TARGET_LIBGCC2_CFLAGS = -+ -+# We want fine grained libraries, so use the new code to build the -+# floating point emulation libraries. -+FPBIT = fp-bit.c -+DPBIT = dp-bit.c -+ -+fp-bit.c: $(srcdir)/config/fp-bit.c -+ echo '#define FLOAT' > fp-bit.c -+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c -+ -+dp-bit.c: $(srcdir)/config/fp-bit.c -+ cat $(srcdir)/config/fp-bit.c > dp-bit.c -+ -+# We only support v3 and v4 ISAs for uClinux. -+ -+MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4 -+ -+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o # crtbeginS.o crtendS.o ---- /dev/null -+++ b/gcc/config/ubicom32/ubicom32-modes.def -@@ -0,0 +1,30 @@ -+/* Definitions of target machine for GNU compiler, Ubicom32 architecture. -+ Copyright (C) 2009 Free Software Foundation, Inc. -+ Contributed by Ubicom, Inc. -+ -+ This file is part of GCC. -+ -+ GCC is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published -+ by the Free Software Foundation; either version 3, or (at your -+ option) any later version. -+ -+ GCC is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+ License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with GCC; see the file COPYING3. If not see -+ <http://www.gnu.org/licenses/>. */ -+ -+/* Some insns set all condition code flags, some only set the Z and N flags, and -+ some only set the Z flag. */ -+ -+CC_MODE (CCW); -+CC_MODE (CCWZN); -+CC_MODE (CCWZ); -+CC_MODE (CCS); -+CC_MODE (CCSZN); -+CC_MODE (CCSZ); -+ ---- /dev/null -+++ b/gcc/config/ubicom32/ubicom32-protos.h -@@ -0,0 +1,84 @@ -+/* Function prototypes for Ubicom IP3000. -+ -+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -+ 2009 Free Software Foundation, Inc. -+ Contributed by Ubicom, Inc. -+ -+ This file is part of GNU CC. -+ -+ GNU CC is free software; you can redistribute it and/or modify it under -+ the terms of the GNU General Public License as published by the Free -+ Software Foundation; either version 2, or (at your option) any later -+ version. -+ -+ GNU CC is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ for more details. -+ -+ You should have received a copy of the GNU General Public License along -+ with GNU CC; see the file COPYING. If not, write to the Free Software -+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -+ -+#ifdef RTX_CODE -+ -+#ifdef TREE_CODE -+extern void ubicom32_va_start (tree, rtx); -+#endif /* TREE_CODE */ -+ -+extern void ubicom32_print_operand (FILE *, rtx, int); -+extern void ubicom32_print_operand_address (FILE *, rtx); -+ -+extern void ubicom32_conditional_register_usage (void); -+extern enum reg_class ubicom32_preferred_reload_class (rtx, enum reg_class); -+extern int ubicom32_regno_ok_for_index_p (int, int); -+extern void ubicom32_expand_movsi (rtx *); -+extern void ubicom32_expand_addsi3 (rtx *); -+extern int ubicom32_emit_mult_sequence (rtx *); -+extern void ubicom32_emit_move_const_int (rtx, rtx); -+extern bool ubicom32_legitimate_constant_p (rtx); -+extern bool ubicom32_legitimate_address_p (enum machine_mode, rtx, int); -+extern rtx ubicom32_legitimize_address (rtx, rtx, enum machine_mode); -+extern rtx ubicom32_legitimize_reload_address (rtx, enum machine_mode, int, int); -+extern void ubicom32_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1); -+extern int ubicom32_mode_dependent_address_p (rtx); -+extern void ubicom32_output_cond_jump (rtx, rtx, rtx); -+extern void ubicom32_expand_eh_return (rtx *); -+extern void ubicom32_expand_call_fdpic (rtx *); -+extern void ubicom32_expand_call_value_fdpic (rtx *); -+extern enum machine_mode ubicom32_select_cc_mode (RTX_CODE, rtx, rtx); -+extern rtx ubicom32_gen_compare_reg (RTX_CODE, rtx, rtx); -+extern int ubicom32_shiftable_const_int (int); -+#endif /* RTX_CODE */ -+ -+#ifdef TREE_CODE -+extern void init_cumulative_args (CUMULATIVE_ARGS *cum, -+ tree fntype, -+ struct rtx_def *libname, -+ int indirect); -+extern struct rtx_def *function_arg (CUMULATIVE_ARGS *, -+ enum machine_mode, tree, int); -+extern struct rtx_def *function_incoming_arg (CUMULATIVE_ARGS *, -+ enum machine_mode, -+ tree, int); -+extern int function_arg_partial_nregs (CUMULATIVE_ARGS *, -+ enum machine_mode, tree, int); -+extern struct rtx_def *ubicom32_va_arg (tree, tree); -+extern int ubicom32_reg_parm_stack_space (tree); -+#endif /* TREE_CODE */ -+ -+extern struct rtx_def * ubicom32_builtin_saveregs (void); -+extern void asm_file_start (FILE *); -+extern void ubicom32_expand_prologue (void); -+extern void ubicom32_expand_epilogue (void); -+extern int ubicom32_initial_elimination_offset (int, int); -+extern int ubicom32_regno_ok_for_base_p (int, int); -+extern bool ubicom32_hard_regno_mode_ok (unsigned int, enum machine_mode); -+extern int ubicom32_can_use_return_insn_p (void); -+extern rtx ubicom32_return_addr_rtx (int, rtx); -+extern void ubicom32_optimization_options (int, int); -+extern void ubicom32_override_options (void); -+extern bool ubicom32_match_cc_mode (rtx, enum machine_mode); -+ -+extern int ubicom32_reorg_completed; -+ ---- /dev/null -+++ b/gcc/config/ubicom32/ubicom32.c -@@ -0,0 +1,2881 @@ -+/* Subroutines for insn-output.c for Ubicom32 -+ -+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -+ 2009 Free Software Foundation, Inc. -+ Contributed by Ubicom, Inc. -+ -+ This file is part of GCC. -+ -+ GCC is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published -+ by the Free Software Foundation; either version 3, or (at your -+ option) any later version. -+ -+ GCC is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+ License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with GCC; see the file COPYING3. If not see -+ <http://www.gnu.org/licenses/>. */ -+ -+#include "config.h" -+#include "system.h" -+#include "coretypes.h" -+#include "tm.h" -+#include "rtl.h" -+#include "tree.h" -+#include "regs.h" -+#include "hard-reg-set.h" -+#include "real.h" -+#include "insn-config.h" -+#include "conditions.h" -+#include "insn-flags.h" -+#include "output.h" -+#include "insn-attr.h" -+#include "insn-codes.h" -+#include "flags.h" -+#include "recog.h" -+#include "expr.h" -+#include "function.h" -+#include "obstack.h" -+#include "toplev.h" -+#include "tm_p.h" -+#include "tm-constrs.h" -+#include "basic-block.h" -+#include "integrate.h" -+#include "target.h" -+#include "target-def.h" -+#include "reload.h" -+#include "df.h" -+#include "langhooks.h" -+#include "optabs.h" -+ -+static tree ubicom32_handle_fndecl_attribute (tree *, tree, tree, int, bool *); -+static void ubicom32_layout_frame (void); -+static void ubicom32_function_prologue (FILE *, HOST_WIDE_INT); -+static void ubicom32_function_epilogue (FILE *, HOST_WIDE_INT); -+static bool ubicom32_rtx_costs (rtx, int, int, int *, bool speed); -+static bool ubicom32_fixed_condition_code_regs (unsigned int *, -+ unsigned int *); -+static enum machine_mode ubicom32_cc_modes_compatible (enum machine_mode, -+ enum machine_mode); -+static int ubicom32_naked_function_p (void); -+static void ubicom32_machine_dependent_reorg (void); -+static bool ubicom32_assemble_integer (rtx, unsigned int, int); -+static void ubicom32_asm_init_sections (void); -+static int ubicom32_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,tree, -+ bool); -+static bool ubicom32_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED, -+ enum machine_mode mode, const_tree type, -+ bool named ATTRIBUTE_UNUSED); -+static bool ubicom32_callee_copies (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED, -+ enum machine_mode mode, const_tree type, -+ bool named ATTRIBUTE_UNUSED); -+ -+static bool ubicom32_return_in_memory (const_tree type, -+ const_tree fntype ATTRIBUTE_UNUSED); -+static bool ubicom32_is_base_reg (rtx, int); -+static void ubicom32_init_builtins (void); -+static rtx ubicom32_expand_builtin (tree, rtx, rtx, enum machine_mode, int); -+static tree ubicom32_fold_builtin (tree, tree, bool); -+static int ubicom32_get_valid_offset_mask (enum machine_mode); -+static bool ubicom32_cannot_force_const_mem (rtx); -+ -+/* Case values threshold */ -+int ubicom32_case_values_threshold = 6; -+ -+/* Nonzero if this chip supports the Ubicom32 v3 ISA. */ -+int ubicom32_v3 = 1; -+ -+/* Nonzero if this chip supports the Ubicom32 v4 ISA. */ -+int ubicom32_v4 = 1; -+ -+/* Valid attributes: -+ naked - don't generate function prologue/epilogue and `ret' command. */ -+const struct attribute_spec ubicom32_attribute_table[] = -+{ -+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ -+ { "naked", 0, 0, true, false, false, ubicom32_handle_fndecl_attribute }, -+ { NULL, 0, 0, false, false, false, NULL } -+}; -+ -+#undef TARGET_ASM_FUNCTION_PROLOGUE -+#define TARGET_ASM_FUNCTION_PROLOGUE ubicom32_function_prologue -+ -+#undef TARGET_ASM_FUNCTION_EPILOGUE -+#define TARGET_ASM_FUNCTION_EPILOGUE ubicom32_function_epilogue -+ -+#undef TARGET_ATTRIBUTE_TABLE -+#define TARGET_ATTRIBUTE_TABLE ubicom32_attribute_table -+ -+/* All addresses cost the same amount. */ -+#undef TARGET_ADDRESS_COST -+#define TARGET_ADDRESS_COST hook_int_rtx_bool_0 -+ -+#undef TARGET_RTX_COSTS -+#define TARGET_RTX_COSTS ubicom32_rtx_costs -+ -+#undef TARGET_FIXED_CONDITION_CODE_REGS -+#define TARGET_FIXED_CONDITION_CODE_REGS ubicom32_fixed_condition_code_regs -+ -+#undef TARGET_CC_MODES_COMPATIBLE -+#define TARGET_CC_MODES_COMPATIBLE ubicom32_cc_modes_compatible -+ -+#undef TARGET_MACHINE_DEPENDENT_REORG -+#define TARGET_MACHINE_DEPENDENT_REORG ubicom32_machine_dependent_reorg -+ -+#undef TARGET_ASM_INTEGER -+#define TARGET_ASM_INTEGER ubicom32_assemble_integer -+ -+#undef TARGET_ASM_INIT_SECTIONS -+#define TARGET_ASM_INIT_SECTIONS ubicom32_asm_init_sections -+ -+#undef TARGET_ARG_PARTIAL_BYTES -+#define TARGET_ARG_PARTIAL_BYTES ubicom32_arg_partial_bytes -+ -+#undef TARGET_PASS_BY_REFERENCE -+#define TARGET_PASS_BY_REFERENCE ubicom32_pass_by_reference -+ -+#undef TARGET_CALLEE_COPIES -+#define TARGET_CALLEE_COPIES ubicom32_callee_copies -+ -+#undef TARGET_RETURN_IN_MEMORY -+#define TARGET_RETURN_IN_MEMORY ubicom32_return_in_memory -+ -+#undef TARGET_INIT_BUILTINS -+#define TARGET_INIT_BUILTINS ubicom32_init_builtins -+ -+#undef TARGET_EXPAND_BUILTIN -+#define TARGET_EXPAND_BUILTIN ubicom32_expand_builtin -+ -+#undef TARGET_FOLD_BUILTIN -+#define TARGET_FOLD_BUILTIN ubicom32_fold_builtin -+ -+#undef TARGET_CANNOT_FORCE_CONST_MEM -+#define TARGET_CANNOT_FORCE_CONST_MEM ubicom32_cannot_force_const_mem -+ -+struct gcc_target targetm = TARGET_INITIALIZER; -+ -+static char save_regs[FIRST_PSEUDO_REGISTER]; -+static int nregs; -+static int frame_size; -+int ubicom32_stack_size = 0; /* size of allocated stack (including frame) */ -+int ubicom32_can_use_calli_to_ret; -+ -+#define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT) -+#define ROUND_CALL_BLOCK_SIZE(BYTES) \ -+ (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1)) -+ -+/* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we -+ must report the mode of the memory reference from PRINT_OPERAND to -+ PRINT_OPERAND_ADDRESS. */ -+enum machine_mode output_memory_reference_mode; -+ -+/* Flag for some split insns from the ubicom32.md. */ -+int ubicom32_reorg_completed; -+ -+enum reg_class const ubicom32_regclass_map[FIRST_PSEUDO_REGISTER] = -+{ -+ DATA_REGS, -+ DATA_REGS, -+ DATA_REGS, -+ DATA_REGS, -+ DATA_REGS, -+ DATA_REGS, -+ DATA_REGS, -+ DATA_REGS, -+ DATA_REGS, -+ DATA_REGS, -+ DATA_REGS, -+ DATA_REGS, -+ DATA_REGS, -+ DATA_REGS, -+ DATA_REGS, -+ DATA_REGS, -+ FDPIC_REG, -+ ADDRESS_REGS, -+ ADDRESS_REGS, -+ ADDRESS_REGS, -+ ADDRESS_REGS, -+ ADDRESS_REGS, -+ ADDRESS_REGS, -+ ADDRESS_REGS, -+ ACC_REGS, -+ ACC_LO_REGS, -+ ACC_REGS, -+ ACC_LO_REGS, -+ SOURCE3_REG, -+ ADDRESS_REGS, -+ NO_REGS, /* CC_REG must be NO_REGS */ -+ SPECIAL_REGS, -+ SPECIAL_REGS, -+ SPECIAL_REGS, -+ SPECIAL_REGS, -+ SPECIAL_REGS, -+ SPECIAL_REGS, -+ SPECIAL_REGS, -+ SPECIAL_REGS -+}; -+ -+rtx ubicom32_compare_op0; -+rtx ubicom32_compare_op1; -+ -+/* Handle command line option overrides. */ -+ -+void -+ubicom32_override_options (void) -+{ -+ flag_pic = 0; -+ -+ if (strcmp (ubicom32_arch_name, "ubicom32v1") == 0) { -+ /* If we have a version 1 architecture then we want to avoid using jump -+ tables. */ -+ ubicom32_case_values_threshold = 30000; -+ ubicom32_v3 = 0; -+ ubicom32_v4 = 0; -+ } else if (strcmp (ubicom32_arch_name, "ubicom32v2") == 0) { -+ ubicom32_v3 = 0; -+ ubicom32_v4 = 0; -+ } else if (strcmp (ubicom32_arch_name, "ubicom32v3") == 0) { -+ ubicom32_v3 = 1; -+ ubicom32_v4 = 0; -+ } else if (strcmp (ubicom32_arch_name, "ubicom32v4") == 0) { -+ ubicom32_v3 = 1; -+ ubicom32_v4 = 1; -+ } -+ -+ /* There is no single unaligned SI op for PIC code. Sometimes we -+ need to use ".4byte" and sometimes we need to use ".picptr". -+ See ubicom32_assemble_integer for details. */ -+ if (TARGET_FDPIC) -+ targetm.asm_out.unaligned_op.si = 0; -+} -+ -+void -+ubicom32_conditional_register_usage (void) -+{ -+ /* If we're using the old ipOS ABI we need to make D10 through D13 -+ caller-clobbered. */ -+ if (TARGET_IPOS_ABI) -+ { -+ call_used_regs[D10_REGNUM] = 1; -+ call_used_regs[D11_REGNUM] = 1; -+ call_used_regs[D12_REGNUM] = 1; -+ call_used_regs[D13_REGNUM] = 1; -+ } -+} -+ -+/* We have some number of optimizations that don't really work for the Ubicom32 -+ architecture so we deal with them here. */ -+ -+void -+ubicom32_optimization_options (int level ATTRIBUTE_UNUSED, -+ int size ATTRIBUTE_UNUSED) -+{ -+ /* The tree IVOPTs pass seems to do really bad things for the Ubicom32 -+ architecture - it tends to turn things that would happily use pre/post -+ increment/decrement into operations involving unecessary loop -+ indicies. */ -+ flag_ivopts = 0; -+ -+ /* We have problems where DSE at the RTL level misses partial stores -+ to the stack. For now we disable it to avoid this. */ -+ flag_dse = 0; -+} -+ -+/* Print operand X using operand code CODE to assembly language output file -+ FILE. */ -+ -+void -+ubicom32_print_operand (FILE *file, rtx x, int code) -+{ -+ switch (code) -+ { -+ case 'A': -+ /* Identify the correct accumulator to use. */ -+ if (REGNO (x) == ACC0_HI_REGNUM || REGNO (x) == ACC0_LO_REGNUM) -+ fprintf (file, "acc0"); -+ else if (REGNO (x) == ACC1_HI_REGNUM || REGNO (x) == ACC1_LO_REGNUM) -+ fprintf (file, "acc1"); -+ else -+ abort (); -+ break; -+ -+ case 'b': -+ case 'B': -+ { -+ enum machine_mode mode; -+ -+ mode = GET_MODE (XEXP (x, 0)); -+ -+ /* These are normal and reversed branches. */ -+ switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x))) -+ { -+ case NE: -+ fprintf (file, "ne"); -+ break; -+ -+ case EQ: -+ fprintf (file, "eq"); -+ break; -+ -+ case GE: -+ if (mode == CCSZNmode || mode == CCWZNmode) -+ fprintf (file, "pl"); -+ else -+ fprintf (file, "ge"); -+ break; -+ -+ case GT: -+ fprintf (file, "gt"); -+ break; -+ -+ case LE: -+ fprintf (file, "le"); -+ break; -+ -+ case LT: -+ if (mode == CCSZNmode || mode == CCWZNmode) -+ fprintf (file, "mi"); -+ else -+ fprintf (file, "lt"); -+ break; -+ -+ case GEU: -+ fprintf (file, "cs"); -+ break; -+ -+ case GTU: -+ fprintf (file, "hi"); -+ break; -+ -+ case LEU: -+ fprintf (file, "ls"); -+ break; -+ -+ case LTU: -+ fprintf (file, "cc"); -+ break; -+ -+ default: -+ abort (); -+ } -+ } -+ break; -+ -+ case 'C': -+ /* This is used for the operand to a call instruction; -+ if it's a REG, enclose it in parens, else output -+ the operand normally. */ -+ if (REG_P (x)) -+ { -+ fputc ('(', file); -+ ubicom32_print_operand (file, x, 0); -+ fputc (')', file); -+ } -+ else -+ ubicom32_print_operand (file, x, 0); -+ break; -+ -+ case 'd': -+ /* Bit operations we need bit numbers. */ -+ fprintf (file, "%d", exact_log2 (INTVAL (x))); -+ break; -+ -+ case 'D': -+ /* Bit operations we need bit numbers. */ -+ fprintf (file, "%d", exact_log2 (~ INTVAL (x))); -+ break; -+ -+ case 'E': -+ /* For lea, which we use to add address registers. -+ We don't want the '#' on a constant. */ -+ if (CONST_INT_P (x)) -+ { -+ fprintf (file, "%ld", INTVAL (x)); -+ break; -+ } -+ /* FALL THROUGH */ -+ -+ default: -+ switch (GET_CODE (x)) -+ { -+ case MEM: -+ output_memory_reference_mode = GET_MODE (x); -+ output_address (XEXP (x, 0)); -+ break; -+ -+ case PLUS: -+ output_address (x); -+ break; -+ -+ case REG: -+ fprintf (file, "%s", reg_names[REGNO (x)]); -+ break; -+ -+ case SUBREG: -+ fprintf (file, "%s", reg_names[subreg_regno (x)]); -+ break; -+ -+ /* This will only be single precision.... */ -+ case CONST_DOUBLE: -+ { -+ unsigned long val; -+ REAL_VALUE_TYPE rv; -+ -+ REAL_VALUE_FROM_CONST_DOUBLE (rv, x); -+ REAL_VALUE_TO_TARGET_SINGLE (rv, val); -+ fprintf (file, "0x%lx", val); -+ break; -+ } -+ -+ case CONST_INT: -+ case SYMBOL_REF: -+ case CONST: -+ case LABEL_REF: -+ case CODE_LABEL: -+ case LO_SUM: -+ ubicom32_print_operand_address (file, x); -+ break; -+ -+ case HIGH: -+ fprintf (file, "#%%hi("); -+ ubicom32_print_operand_address (file, XEXP (x, 0)); -+ fprintf (file, ")"); -+ break; -+ -+ case UNSPEC: -+ switch (XINT (x, 1)) -+ { -+ case UNSPEC_FDPIC_GOT: -+ fprintf (file, "#%%got_lo("); -+ ubicom32_print_operand_address (file, XVECEXP (x, 0, 0)); -+ fprintf (file, ")"); -+ break; -+ -+ case UNSPEC_FDPIC_GOT_FUNCDESC: -+ fprintf (file, "#%%got_funcdesc_lo("); -+ ubicom32_print_operand_address (file, XVECEXP (x, 0, 0)); -+ fprintf (file, ")"); -+ break; -+ -+ default: -+ abort (); -+ } -+ break; -+ -+ default: -+ abort (); -+ } -+ break; -+ } -+} -+ -+/* Output assembly language output for the address ADDR to FILE. */ -+ -+void -+ubicom32_print_operand_address (FILE *file, rtx addr) -+{ -+ switch (GET_CODE (addr)) -+ { -+ case POST_INC: -+ ubicom32_print_operand_address (file, XEXP (addr, 0)); -+ fprintf (file, "%d++", GET_MODE_SIZE (output_memory_reference_mode)); -+ break; -+ -+ case PRE_INC: -+ fprintf (file, "%d", GET_MODE_SIZE (output_memory_reference_mode)); -+ ubicom32_print_operand_address (file, XEXP (addr, 0)); -+ fprintf (file, "++"); -+ break; -+ -+ case POST_DEC: -+ ubicom32_print_operand_address (file, XEXP (addr, 0)); -+ fprintf (file, "%d++", -GET_MODE_SIZE (output_memory_reference_mode)); -+ break; -+ -+ case PRE_DEC: -+ fprintf (file, "%d", -GET_MODE_SIZE (output_memory_reference_mode)); -+ ubicom32_print_operand_address (file, XEXP (addr, 0)); -+ fprintf (file, "++"); -+ break; -+ -+ case POST_MODIFY: -+ ubicom32_print_operand_address (file, XEXP (addr, 0)); -+ fprintf (file, "%ld++", INTVAL (XEXP (XEXP (addr,1), 1))); -+ break; -+ -+ case PRE_MODIFY: -+ fprintf (file, "%ld", INTVAL (XEXP (XEXP (addr,1), 1))); -+ ubicom32_print_operand_address (file, XEXP (addr, 0)); -+ fprintf (file, "++"); -+ break; -+ -+ case REG: -+ fputc ('(', file); -+ fprintf (file, "%s", reg_names[REGNO (addr)]); -+ fputc (')', file); -+ break; -+ -+ case PLUS: -+ { -+ rtx base = XEXP (addr, 0); -+ rtx index = XEXP (addr, 1); -+ -+ /* Switch around addresses of the form index * scaling + base. */ -+ if (! ubicom32_is_base_reg (base, 1)) -+ { -+ rtx tmp = base; -+ base = index; -+ index = tmp; -+ } -+ -+ if (CONST_INT_P (index)) -+ { -+ fprintf (file, "%ld", INTVAL (index)); -+ fputc ('(', file); -+ fputs (reg_names[REGNO (base)], file); -+ } -+ else if (GET_CODE (index) == MULT -+ || REG_P (index)) -+ { -+ if (GET_CODE (index) == MULT) -+ index = XEXP (index, 0); -+ fputc ('(', file); -+ fputs (reg_names[REGNO (base)], file); -+ fputc (',', file); -+ fputs (reg_names[REGNO (index)], file); -+ } -+ else -+ abort (); -+ -+ fputc (')', file); -+ break; -+ } -+ -+ case LO_SUM: -+ fprintf (file, "%%lo("); -+ ubicom32_print_operand (file, XEXP (addr, 1), 'L'); -+ fprintf (file, ")("); -+ ubicom32_print_operand (file, XEXP (addr, 0), 0); -+ fprintf (file, ")"); -+ break; -+ -+ case CONST_INT: -+ fputc ('#', file); -+ output_addr_const (file, addr); -+ break; -+ -+ default: -+ output_addr_const (file, addr); -+ break; -+ } -+} -+ -+/* X and Y are two things to compare using CODE. Emit the compare insn and -+ return the rtx for the cc reg in the proper mode. */ -+ -+rtx -+ubicom32_gen_compare_reg (enum rtx_code code, rtx x, rtx y) -+{ -+ enum machine_mode mode = SELECT_CC_MODE (code, x, y); -+ rtx cc_reg; -+ -+ cc_reg = gen_rtx_REG (mode, CC_REGNUM); -+ -+ emit_insn (gen_rtx_SET (VOIDmode, cc_reg, -+ gen_rtx_COMPARE (mode, x, y))); -+ -+ return cc_reg; -+} -+ -+/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, -+ return the mode to be used for the comparison. */ -+ -+enum machine_mode -+ubicom32_select_cc_mode (enum rtx_code op, rtx x, rtx y) -+{ -+ /* Is this a short compare? */ -+ if (GET_MODE (x) == QImode -+ || GET_MODE (x) == HImode -+ || GET_MODE (y) == QImode -+ || GET_MODE (y) == HImode) -+ { -+ switch (op) -+ { -+ case EQ : -+ case NE : -+ return CCSZmode; -+ -+ case GE: -+ case LT: -+ if (y == const0_rtx) -+ return CCSZNmode; -+ -+ default : -+ return CCSmode; -+ } -+ } -+ -+ /* We have a word compare. */ -+ switch (op) -+ { -+ case EQ : -+ case NE : -+ return CCWZmode; -+ -+ case GE : -+ case LT : -+ if (y == const0_rtx) -+ return CCWZNmode; -+ -+ default : -+ return CCWmode; -+ } -+} -+ -+/* Return TRUE or FALSE depending on whether the first SET in INSN -+ has source and destination with matching CC modes, and that the -+ CC mode is at least as constrained as REQ_MODE. */ -+bool -+ubicom32_match_cc_mode (rtx insn, enum machine_mode req_mode) -+{ -+ rtx set; -+ enum machine_mode set_mode; -+ -+ set = PATTERN (insn); -+ if (GET_CODE (set) == PARALLEL) -+ set = XVECEXP (set, 0, 0); -+ gcc_assert (GET_CODE (set) == SET); -+ gcc_assert (GET_CODE (SET_SRC (set)) == COMPARE); -+ -+ /* SET_MODE is the mode we have in the instruction. This must either -+ be the same or less restrictive that the required mode REQ_MODE. */ -+ set_mode = GET_MODE (SET_DEST (set)); -+ -+ switch (req_mode) -+ { -+ case CCSZmode: -+ if (set_mode != CCSZmode) -+ return 0; -+ break; -+ -+ case CCSZNmode: -+ if (set_mode != CCSZmode -+ && set_mode != CCSZNmode) -+ return 0; -+ break; -+ -+ case CCSmode: -+ if (set_mode != CCSmode -+ && set_mode != CCSZmode -+ && set_mode != CCSZNmode) -+ return 0; -+ break; -+ -+ case CCWZmode: -+ if (set_mode != CCWZmode) -+ return 0; -+ break; -+ -+ case CCWZNmode: -+ if (set_mode != CCWZmode -+ && set_mode != CCWZNmode) -+ return 0; -+ break; -+ -+ case CCWmode: -+ if (set_mode != CCWmode -+ && set_mode != CCWZmode -+ && set_mode != CCWZNmode) -+ return 0; -+ break; -+ -+ default: -+ gcc_unreachable (); -+ } -+ -+ return (GET_MODE (SET_SRC (set)) == set_mode); -+} -+ -+/* Replace the comparison OP0 CODE OP1 by a semantically equivalent one -+ that we can implement more efficiently. */ -+ -+void -+ubicom32_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1) -+{ -+ /* If we have a REG and a MEM then compare the MEM with the REG and not -+ the other way round. */ -+ if (REG_P (*op0) && MEM_P (*op1)) -+ { -+ rtx tem = *op0; -+ *op0 = *op1; -+ *op1 = tem; -+ *code = swap_condition (*code); -+ return; -+ } -+ -+ /* If we have a REG and a CONST_INT then we may want to reverse things -+ if the constant can be represented as an "I" constraint. */ -+ if (REG_P (*op0) && CONST_INT_P (*op1) && satisfies_constraint_I (*op1)) -+ { -+ rtx tem = *op0; -+ *op0 = *op1; -+ *op1 = tem; -+ *code = swap_condition (*code); -+ return; -+ } -+} -+ -+/* Return the fixed registers used for condition codes. */ -+ -+static bool -+ubicom32_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2) -+{ -+ *p1 = CC_REGNUM; -+ *p2 = INVALID_REGNUM; -+ -+ return true; -+} -+ -+/* If two condition code modes are compatible, return a condition code -+ mode which is compatible with both. Otherwise, return -+ VOIDmode. */ -+ -+static enum machine_mode -+ubicom32_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2) -+{ -+ if (m1 == m2) -+ return m1; -+ -+ if (GET_MODE_CLASS (m1) != MODE_CC || GET_MODE_CLASS (m2) != MODE_CC) -+ return VOIDmode; -+ -+ switch (m1) -+ { -+ case CCWmode: -+ if (m2 == CCWZNmode || m2 == CCWZmode) -+ return m1; -+ -+ return VOIDmode; -+ -+ case CCWZNmode: -+ if (m2 == CCWmode) -+ return m2; -+ -+ if (m2 == CCWZmode) -+ return m1; -+ -+ return VOIDmode; -+ -+ case CCWZmode: -+ if (m2 == CCWmode || m2 == CCWZNmode) -+ return m2; -+ -+ return VOIDmode; -+ -+ case CCSmode: -+ if (m2 == CCSZNmode || m2 == CCSZmode) -+ return m1; -+ -+ return VOIDmode; -+ -+ case CCSZNmode: -+ if (m2 == CCSmode) -+ return m2; -+ -+ if (m2 == CCSZmode) -+ return m1; -+ -+ return VOIDmode; -+ -+ case CCSZmode: -+ if (m2 == CCSmode || m2 == CCSZNmode) -+ return m2; -+ -+ return VOIDmode; -+ -+ default: -+ gcc_unreachable (); -+ } -+} -+ -+static rtx -+ubicom32_legitimize_fdpic_address_symbol (rtx orig, rtx reg, rtx fdpic_reg) -+{ -+ int unspec; -+ rtx got_offs; -+ rtx got_offs_scaled; -+ rtx plus_scaled; -+ rtx tmp; -+ rtx new_rtx; -+ -+ gcc_assert (reg != 0); -+ -+ if (GET_CODE (orig) == SYMBOL_REF -+ && SYMBOL_REF_FUNCTION_P (orig)) -+ unspec = UNSPEC_FDPIC_GOT_FUNCDESC; -+ else -+ unspec = UNSPEC_FDPIC_GOT; -+ -+ got_offs = gen_reg_rtx (SImode); -+ tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, orig), unspec); -+ emit_move_insn (got_offs, tmp); -+ -+ got_offs_scaled = gen_rtx_MULT (SImode, got_offs, GEN_INT (4)); -+ plus_scaled = gen_rtx_PLUS (Pmode, fdpic_reg, got_offs_scaled); -+ new_rtx = gen_const_mem (Pmode, plus_scaled); -+ emit_move_insn (reg, new_rtx); -+ -+ return reg; -+} -+ -+static rtx -+ubicom32_legitimize_fdpic_address (rtx orig, rtx reg, rtx fdpic_reg) -+{ -+ rtx addr = orig; -+ rtx new_rtx = orig; -+ -+ if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS) -+ { -+ rtx base; -+ -+ if (GET_CODE (addr) == CONST) -+ { -+ addr = XEXP (addr, 0); -+ gcc_assert (GET_CODE (addr) == PLUS); -+ } -+ -+ base = ubicom32_legitimize_fdpic_address_symbol (XEXP (addr, 0), reg, fdpic_reg); -+ return gen_rtx_PLUS (Pmode, base, XEXP (addr, 1)); -+ } -+ -+ return new_rtx; -+} -+ -+/* Code generation. */ -+ -+void -+ubicom32_expand_movsi (rtx *operands) -+{ -+ if (GET_CODE (operands[1]) == SYMBOL_REF -+ || (GET_CODE (operands[1]) == CONST -+ && GET_CODE (XEXP (operands[1], 0)) == PLUS -+ && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF) -+ || CONSTANT_ADDRESS_P (operands[1])) -+ { -+ if (TARGET_FDPIC) -+ { -+ rtx tmp; -+ rtx fdpic_reg; -+ -+ gcc_assert (can_create_pseudo_p ()); -+ tmp = gen_reg_rtx (Pmode); -+ fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM); -+ if (GET_CODE (operands[1]) == SYMBOL_REF -+ || GET_CODE (operands[1]) == LABEL_REF) -+ operands[1] = ubicom32_legitimize_fdpic_address_symbol (operands[1], tmp, fdpic_reg); -+ else -+ operands[1] = ubicom32_legitimize_fdpic_address (operands[1], tmp, fdpic_reg); -+ } -+ else -+ { -+ rtx tmp; -+ enum machine_mode mode; -+ -+ /* We want to avoid reusing operand 0 if we can because it limits -+ our ability to optimize later. */ -+ tmp = ! can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode); -+ -+ mode = GET_MODE (operands[0]); -+ emit_insn (gen_rtx_SET (VOIDmode, tmp, -+ gen_rtx_HIGH (mode, operands[1]))); -+ operands[1] = gen_rtx_LO_SUM (mode, tmp, operands[1]); -+ if (can_create_pseudo_p() && ! REG_P (operands[0])) -+ { -+ tmp = gen_reg_rtx (mode); -+ emit_insn (gen_rtx_SET (VOIDmode, tmp, operands[1])); -+ operands[1] = tmp; -+ } -+ } -+ } -+} -+ -+/* Emit code for addsi3. */ -+ -+void -+ubicom32_expand_addsi3 (rtx *operands) -+{ -+ rtx op, clob; -+ -+ if (can_create_pseudo_p ()) -+ { -+ /* If we have a non-data reg for operand 1 then prefer that over -+ a CONST_INT in operand 2. */ -+ if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])) -+ && CONST_INT_P (operands[2])) -+ operands[2] = copy_to_mode_reg (SImode, operands[2]); -+ -+ if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2])) -+ operands[2] = copy_to_mode_reg (SImode, operands[2]); -+ } -+ -+ /* Emit the instruction. */ -+ -+ op = gen_rtx_SET (VOIDmode, operands[0], -+ gen_rtx_PLUS (SImode, operands[1], operands[2])); -+ -+ if (! can_create_pseudo_p ()) -+ { -+ /* Reload doesn't know about the flags register, and doesn't know that -+ it doesn't want to clobber it. We can only do this with PLUS. */ -+ emit_insn (op); -+ } -+ else -+ { -+ clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM)); -+ emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob))); -+ } -+} -+ -+/* Emit code for mulsi3. Return 1 if we have generated all the code -+ necessary to do the multiplication. */ -+ -+int -+ubicom32_emit_mult_sequence (rtx *operands) -+{ -+ if (! ubicom32_v4) -+ { -+ rtx a1, a1_1, a2; -+ rtx b1, b1_1, b2; -+ rtx mac_lo_rtx; -+ rtx t1, t2, t3; -+ -+ /* Give up if we cannot create new pseudos. */ -+ if (!can_create_pseudo_p()) -+ return 0; -+ -+ /* Synthesize 32-bit multiplication using 16-bit operations: -+ -+ a1 = highpart (a) -+ a2 = lowpart (a) -+ -+ b1 = highpart (b) -+ b2 = lowpart (b) -+ -+ c = (a1 * b1) << 32 + (a1 * b2) << 16 + (a2 * b1) << 16 + a2 * b2 -+ = 0 + (a1 * b2) << 16 + (a2 * b1) << 16 + a2 * b2 -+ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^ -+ Signed Signed Unsigned */ -+ -+ if (!ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))) -+ { -+ rtx op1; -+ -+ op1 = gen_reg_rtx (SImode); -+ emit_move_insn (op1, operands[1]); -+ operands[1] = op1; -+ } -+ -+ if (!ubicom32_data_register_operand (operands[2], GET_MODE (operands[2]))) -+ { -+ rtx op2; -+ -+ op2 = gen_reg_rtx (SImode); -+ emit_move_insn (op2, operands[2]); -+ operands[2] = op2; -+ } -+ -+ /* a1 = highpart (a) */ -+ a1 = gen_reg_rtx (HImode); -+ a1_1 = gen_reg_rtx (SImode); -+ emit_insn (gen_ashrsi3 (a1_1, operands[1], GEN_INT (16))); -+ emit_move_insn (a1, gen_lowpart (HImode, a1_1)); -+ -+ /* a2 = lowpart (a) */ -+ a2 = gen_reg_rtx (HImode); -+ emit_move_insn (a2, gen_lowpart (HImode, operands[1])); -+ -+ /* b1 = highpart (b) */ -+ b1 = gen_reg_rtx (HImode); -+ b1_1 = gen_reg_rtx (SImode); -+ emit_insn (gen_ashrsi3 (b1_1, operands[2], GEN_INT (16))); -+ emit_move_insn (b1, gen_lowpart (HImode, b1_1)); -+ -+ /* b2 = lowpart (b) */ -+ b2 = gen_reg_rtx (HImode); -+ emit_move_insn (b2, gen_lowpart (HImode, operands[2])); -+ -+ /* t1 = (a1 * b2) << 16 */ -+ t1 = gen_reg_rtx (SImode); -+ mac_lo_rtx = gen_rtx_REG (SImode, ACC0_LO_REGNUM); -+ emit_insn (gen_mulhisi3 (mac_lo_rtx, a1, b2)); -+ emit_insn (gen_ashlsi3 (t1, mac_lo_rtx, GEN_INT (16))); -+ -+ /* t2 = (a2 * b1) << 16 */ -+ t2 = gen_reg_rtx (SImode); -+ emit_insn (gen_mulhisi3 (mac_lo_rtx, a2, b1)); -+ emit_insn (gen_ashlsi3 (t2, mac_lo_rtx, GEN_INT (16))); -+ -+ /* mac_lo = a2 * b2 */ -+ emit_insn (gen_umulhisi3 (mac_lo_rtx, a2, b2)); -+ -+ /* t3 = t1 + t2 */ -+ t3 = gen_reg_rtx (SImode); -+ emit_insn (gen_addsi3 (t3, t1, t2)); -+ -+ /* c = t3 + mac_lo_rtx */ -+ emit_insn (gen_addsi3 (operands[0], mac_lo_rtx, t3)); -+ -+ return 1; -+ } -+ else -+ { -+ rtx acc_rtx; -+ -+ /* Give up if we cannot create new pseudos. */ -+ if (!can_create_pseudo_p()) -+ return 0; -+ -+ if (!ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))) -+ { -+ rtx op1; -+ -+ op1 = gen_reg_rtx (SImode); -+ emit_move_insn (op1, operands[1]); -+ operands[1] = op1; -+ } -+ -+ if (!ubicom32_data_register_operand (operands[2], GET_MODE (operands[2]))) -+ { -+ rtx op2; -+ -+ op2 = gen_reg_rtx (SImode); -+ emit_move_insn (op2, operands[2]); -+ operands[2] = op2; -+ } -+ -+ acc_rtx = gen_reg_rtx (DImode); -+ emit_insn (gen_umulsidi3 (acc_rtx, operands[1], operands[2])); -+ emit_move_insn (operands[0], gen_lowpart (SImode, acc_rtx)); -+ -+ return 1; -+ } -+} -+ -+/* Move the integer value VAL into OPERANDS[0]. */ -+ -+void -+ubicom32_emit_move_const_int (rtx dest, rtx imm) -+{ -+ rtx xoperands[2]; -+ -+ xoperands[0] = dest; -+ xoperands[1] = imm; -+ -+ /* Treat mem destinations separately. Values must be explicitly sign -+ extended. */ -+ if (MEM_P (dest)) -+ { -+ rtx low_hword_mem; -+ rtx low_hword_addr; -+ -+ /* Emit shorter sequence for signed 7-bit quantities. */ -+ if (satisfies_constraint_I (imm)) -+ { -+ output_asm_insn ("move.4\t%0, %1", xoperands); -+ return; -+ } -+ -+ /* Special case for pushing constants. */ -+ if (GET_CODE (XEXP (dest, 0)) == PRE_DEC -+ && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx) -+ { -+ output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands); -+ output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands); -+ return; -+ } -+ -+ /* See if we can add 2 to the original address. This is only -+ possible if the original address is of the form REG or -+ REG+const. */ -+ low_hword_addr = plus_constant (XEXP (dest, 0), 2); -+ if (ubicom32_legitimate_address_p (HImode, low_hword_addr, 1)) -+ { -+ low_hword_mem = gen_rtx_MEM (HImode, low_hword_addr); -+ MEM_COPY_ATTRIBUTES (low_hword_mem, dest); -+ output_asm_insn ("movei\t%0, #%%hi(%E1)", xoperands); -+ xoperands[0] = low_hword_mem; -+ output_asm_insn ("movei\t%0, #%%lo(%E1)", xoperands); -+ return; -+ } -+ -+ /* The original address is too complex. We need to use a -+ scratch memory by (sp) and move that to the original -+ destination. */ -+ if (! reg_mentioned_p (stack_pointer_rtx, dest)) -+ { -+ output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands); -+ output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands); -+ output_asm_insn ("move.4\t%0, (sp)4++", xoperands); -+ return; -+ } -+ -+ /* Our address mentions the stack pointer so we need to -+ use our scratch data register here as well as scratch -+ memory. */ -+ output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands); -+ output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands); -+ output_asm_insn ("move.4\td15, (sp)4++", xoperands); -+ output_asm_insn ("move.4\t%0, d15", xoperands); -+ return; -+ } -+ -+ /* Move into registers are zero extended by default. */ -+ if (! REG_P (dest)) -+ abort (); -+ -+ if (satisfies_constraint_N (imm)) -+ { -+ output_asm_insn ("movei\t%0, %1", xoperands); -+ return; -+ } -+ -+ if (INTVAL (xoperands[1]) >= 0xff80 -+ && INTVAL (xoperands[1]) < 0x10000) -+ { -+ xoperands[1] = GEN_INT (INTVAL (xoperands[1]) - 0x10000); -+ output_asm_insn ("move.2\t%0, %1", xoperands); -+ return; -+ } -+ -+ if ((REGNO_REG_CLASS (REGNO (xoperands[0])) == ADDRESS_REGS -+ || REGNO_REG_CLASS (REGNO (xoperands[0])) == FDPIC_REG) -+ && ((INTVAL (xoperands[1]) & 0x80000000) == 0)) -+ { -+ output_asm_insn ("moveai\t%0, #%%hi(%E1)", xoperands); -+ if ((INTVAL (xoperands[1]) & 0x7f) != 0) -+ output_asm_insn ("lea.1\t%0, %%lo(%E1)(%0)", xoperands); -+ return; -+ } -+ -+ if ((INTVAL (xoperands[1]) & 0xffff0000) == 0) -+ { -+ output_asm_insn ("movei\t%0, #%%lo(%E1)", xoperands); -+ output_asm_insn ("move.2\t%0, %0", xoperands); -+ return; -+ } -+ -+ /* This is very expensive. The constant is so large that we -+ need to use the stack to do the load. */ -+ output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands); -+ output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands); -+ output_asm_insn ("move.4\t%0, (sp)4++", xoperands); -+} -+ -+/* Stack layout. Prologue/Epilogue. */ -+ -+static int save_regs_size; -+ -+static void -+ubicom32_layout_frame (void) -+{ -+ int regno; -+ -+ memset ((char *) &save_regs[0], 0, sizeof (save_regs)); -+ nregs = 0; -+ frame_size = get_frame_size (); -+ -+ if (frame_pointer_needed || df_regs_ever_live_p (FRAME_POINTER_REGNUM)) -+ { -+ save_regs[FRAME_POINTER_REGNUM] = 1; -+ ++nregs; -+ } -+ -+ if (current_function_is_leaf && ! df_regs_ever_live_p (LINK_REGNO)) -+ ubicom32_can_use_calli_to_ret = 1; -+ else -+ { -+ ubicom32_can_use_calli_to_ret = 0; -+ save_regs[LINK_REGNO] = 1; -+ ++nregs; -+ } -+ -+ /* Figure out which register(s) needs to be saved. */ -+ for (regno = 0; regno <= LAST_ADDRESS_REGNUM; regno++) -+ if (df_regs_ever_live_p(regno) -+ && ! call_used_regs[regno] -+ && ! fixed_regs[regno] -+ && ! save_regs[regno]) -+ { -+ save_regs[regno] = 1; -+ ++nregs; -+ } -+ -+ save_regs_size = 4 * nregs; -+} -+ -+static void -+ubicom32_emit_add_movsi (int regno, int adj) -+{ -+ rtx x; -+ rtx reg = gen_rtx_REG (SImode, regno); -+ -+ adj += 4; -+ if (adj > 8 * 4) -+ { -+ x = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, -+ GEN_INT (-adj))); -+ RTX_FRAME_RELATED_P (x) = 1; -+ x = emit_move_insn (gen_rtx_MEM (SImode, stack_pointer_rtx), reg); -+ } -+ else -+ { -+ rtx addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx, -+ gen_rtx_PLUS (Pmode, stack_pointer_rtx, -+ GEN_INT (-adj))); -+ x = emit_move_insn (gen_rtx_MEM (SImode, addr), reg); -+ } -+ RTX_FRAME_RELATED_P (x) = 1; -+} -+ -+void -+ubicom32_expand_prologue (void) -+{ -+ rtx x; -+ int regno; -+ int outgoing_args_size = crtl->outgoing_args_size; -+ int adj; -+ -+ if (ubicom32_naked_function_p ()) -+ return; -+ -+ ubicom32_builtin_saveregs (); -+ -+ ubicom32_layout_frame (); -+ adj = (outgoing_args_size + get_frame_size () + save_regs_size -+ + crtl->args.pretend_args_size); -+ -+ if (!adj) -+ ; -+ else if (outgoing_args_size + save_regs_size < 508 -+ && get_frame_size () + save_regs_size > 508) -+ { -+ int i = 0; -+ x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, -+ GEN_INT (-adj)); -+ x = emit_insn (x); -+ RTX_FRAME_RELATED_P (x) = 1; -+ -+ for (regno = LAST_ADDRESS_REGNUM; regno >= 0; --regno) -+ if (save_regs[regno] && regno != LINK_REGNO) -+ { -+ x = gen_rtx_MEM (SImode, -+ gen_rtx_PLUS (Pmode, -+ stack_pointer_rtx, -+ GEN_INT (i * 4 + outgoing_args_size))); -+ x = emit_move_insn (x, gen_rtx_REG (SImode, regno)); -+ RTX_FRAME_RELATED_P (x) = 1; -+ ++i; -+ } -+ if (save_regs[LINK_REGNO]) -+ { -+ x = gen_rtx_MEM (SImode, -+ gen_rtx_PLUS (Pmode, -+ stack_pointer_rtx, -+ GEN_INT (i * 4 + outgoing_args_size))); -+ x = emit_move_insn (x, gen_rtx_REG (SImode, LINK_REGNO)); -+ RTX_FRAME_RELATED_P (x) = 1; -+ } -+ } -+ else -+ { -+ int regno; -+ int adj = get_frame_size () + crtl->args.pretend_args_size; -+ int i = 0; -+ -+ if (save_regs[LINK_REGNO]) -+ { -+ ubicom32_emit_add_movsi (LINK_REGNO, adj); -+ ++i; -+ } -+ -+ for (regno = 0; regno <= LAST_ADDRESS_REGNUM; ++regno) -+ if (save_regs[regno] && regno != LINK_REGNO) -+ { -+ if (i) -+ { -+ rtx mem = gen_rtx_MEM (SImode, -+ gen_rtx_PRE_DEC (Pmode, -+ stack_pointer_rtx)); -+ x = emit_move_insn (mem, gen_rtx_REG (SImode, regno)); -+ RTX_FRAME_RELATED_P (x) = 1; -+ } -+ else -+ ubicom32_emit_add_movsi (regno, adj); -+ ++i; -+ } -+ -+ if (outgoing_args_size || (!i && adj)) -+ { -+ x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, -+ GEN_INT (-outgoing_args_size - (i ? 0 : adj))); -+ x = emit_insn (x); -+ RTX_FRAME_RELATED_P (x) = 1; -+ } -+ } -+ -+ if (frame_pointer_needed) -+ { -+ int fp_adj = save_regs_size + outgoing_args_size; -+ x = gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx, -+ GEN_INT (fp_adj)); -+ x = emit_insn (x); -+ RTX_FRAME_RELATED_P (x) = 1; -+ } -+} -+ -+void -+ubicom32_expand_epilogue (void) -+{ -+ rtx x; -+ int regno; -+ int outgoing_args_size = crtl->outgoing_args_size; -+ int adj; -+ int i; -+ -+ if (ubicom32_naked_function_p ()) -+ { -+ emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode, -+ LINK_REGNO))); -+ return; -+ } -+ -+ if (cfun->calls_alloca) -+ { -+ x = gen_addsi3 (stack_pointer_rtx, frame_pointer_rtx, -+ GEN_INT (-save_regs_size)); -+ emit_insn (x); -+ outgoing_args_size = 0; -+ } -+ -+ if (outgoing_args_size) -+ { -+ x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, -+ GEN_INT (outgoing_args_size)); -+ emit_insn (x); -+ } -+ -+ i = 0; -+ for (regno = LAST_ADDRESS_REGNUM; regno >= 0; --regno) -+ if (save_regs[regno] && regno != LINK_REGNO) -+ { -+ x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx)); -+ emit_move_insn (gen_rtx_REG (SImode, regno), x); -+ ++i; -+ } -+ -+ /* Do we have to adjust the stack after we've finished restoring regs? */ -+ adj = get_frame_size() + crtl->args.pretend_args_size; -+ if (cfun->stdarg) -+ adj += UBICOM32_FUNCTION_ARG_REGS * UNITS_PER_WORD; -+ -+#if 0 -+ if (crtl->calls_eh_return && 0) -+ { -+ if (save_regs[LINK_REGNO]) -+ { -+ x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx)); -+ emit_move_insn (gen_rtx_REG (SImode, LINK_REGNO), x); -+ } -+ -+ if (adj) -+ { -+ x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, -+ GEN_INT (adj)); -+ x = emit_insn (x); -+ } -+ -+ /* Perform the additional bump for __throw. */ -+ emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, -+ EH_RETURN_STACKADJ_RTX)); -+ emit_jump_insn (gen_eh_return_internal ()); -+ return; -+ } -+#endif -+ -+ if (save_regs[LINK_REGNO]) -+ { -+ if (adj >= 4 && adj <= (6 * 4)) -+ { -+ x = GEN_INT (adj + 4); -+ emit_jump_insn (gen_return_from_post_modify_sp (x)); -+ return; -+ } -+ -+ if (adj == 0) -+ { -+ x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx)); -+ emit_jump_insn (gen_return_internal (x)); -+ return; -+ } -+ -+ x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx)); -+ emit_move_insn (gen_rtx_REG (SImode, LINK_REGNO), x); -+ } -+ -+ if (adj) -+ { -+ x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, -+ GEN_INT (adj)); -+ x = emit_insn (x); -+ adj = 0; -+ } -+ -+ /* Given that we've just done all the hard work here we may as well use -+ a calli to return. */ -+ ubicom32_can_use_calli_to_ret = 1; -+ emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode, LINK_REGNO))); -+} -+ -+void -+ubicom32_expand_call_fdpic (rtx *operands) -+{ -+ rtx c; -+ rtx addr; -+ rtx fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM); -+ -+ addr = XEXP (operands[0], 0); -+ -+ c = gen_call_fdpic (addr, operands[1], fdpic_reg); -+ emit_call_insn (c); -+} -+ -+void -+ubicom32_expand_call_value_fdpic (rtx *operands) -+{ -+ rtx c; -+ rtx addr; -+ rtx fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM); -+ -+ addr = XEXP (operands[1], 0); -+ -+ c = gen_call_value_fdpic (operands[0], addr, operands[2], fdpic_reg); -+ emit_call_insn (c); -+} -+ -+void -+ubicom32_expand_eh_return (rtx *operands) -+{ -+ if (REG_P (operands[0]) -+ || REGNO (operands[0]) != EH_RETURN_STACKADJ_REGNO) -+ { -+ rtx sp = EH_RETURN_STACKADJ_RTX; -+ emit_move_insn (sp, operands[0]); -+ operands[0] = sp; -+ } -+ -+ if (REG_P (operands[1]) -+ || REGNO (operands[1]) != EH_RETURN_HANDLER_REGNO) -+ { -+ rtx ra = EH_RETURN_HANDLER_RTX; -+ emit_move_insn (ra, operands[1]); -+ operands[1] = ra; -+ } -+} -+ -+/* Compute the offsets between eliminable registers. */ -+ -+int -+ubicom32_initial_elimination_offset (int from, int to) -+{ -+ ubicom32_layout_frame (); -+ if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) -+ return save_regs_size + crtl->outgoing_args_size; -+ -+ if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM) -+ return get_frame_size ()/* + save_regs_size */; -+ -+ if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) -+ return get_frame_size () -+ + crtl->outgoing_args_size -+ + save_regs_size; -+ -+ return 0; -+} -+ -+/* Return 1 if it is appropriate to emit `ret' instructions in the -+ body of a function. Do this only if the epilogue is simple, needing a -+ couple of insns. Prior to reloading, we can't tell how many registers -+ must be saved, so return 0 then. Return 0 if there is no frame -+ marker to de-allocate. -+ -+ If NON_SAVING_SETJMP is defined and true, then it is not possible -+ for the epilogue to be simple, so return 0. This is a special case -+ since NON_SAVING_SETJMP will not cause regs_ever_live to change -+ until final, but jump_optimize may need to know sooner if a -+ `return' is OK. */ -+ -+int -+ubicom32_can_use_return_insn_p (void) -+{ -+ if (! reload_completed || frame_pointer_needed) -+ return 0; -+ -+ return 1; -+} -+ -+/* Attributes and CC handling. */ -+ -+/* Handle an attribute requiring a FUNCTION_DECL; arguments as in -+ struct attribute_spec.handler. */ -+static tree -+ubicom32_handle_fndecl_attribute (tree *node, tree name, -+ tree args ATTRIBUTE_UNUSED, -+ int flags ATTRIBUTE_UNUSED, -+ bool *no_add_attrs) -+{ -+ if (TREE_CODE (*node) != FUNCTION_DECL) -+ { -+ warning ("'%s' attribute only applies to functions", -+ IDENTIFIER_POINTER (name)); -+ *no_add_attrs = true; -+ } -+ -+ return NULL_TREE; -+} -+ -+/* A C expression that places additional restrictions on the register class to -+ use when it is necessary to copy value X into a register in class CLASS. -+ The value is a register class; perhaps CLASS, or perhaps another, smaller -+ class. On many machines, the following definition is safe: -+ -+ #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS -+ -+ Sometimes returning a more restrictive class makes better code. For -+ example, on the 68000, when X is an integer constant that is in range for a -+ `moveq' instruction, the value of this macro is always `DATA_REGS' as long -+ as CLASS includes the data registers. Requiring a data register guarantees -+ that a `moveq' will be used. -+ -+ If X is a `const_double', by returning `NO_REGS' you can force X into a -+ memory constant. This is useful on certain machines where immediate -+ floating values cannot be loaded into certain kinds of registers. */ -+ -+enum reg_class -+ubicom32_preferred_reload_class (rtx x, enum reg_class class) -+{ -+ /* If a symbolic constant, HIGH or a PLUS is reloaded, -+ it is most likely being used as an address, so -+ prefer ADDRESS_REGS. If 'class' is not a superset -+ of ADDRESS_REGS, e.g. DATA_REGS, then reject this reload. */ -+ if (GET_CODE (x) == PLUS -+ || GET_CODE (x) == HIGH -+ || GET_CODE (x) == LABEL_REF -+ || GET_CODE (x) == SYMBOL_REF -+ || GET_CODE (x) == CONST) -+ { -+ if (reg_class_subset_p (ALL_ADDRESS_REGS, class)) -+ return ALL_ADDRESS_REGS; -+ -+ return NO_REGS; -+ } -+ -+ return class; -+} -+ -+/* Function arguments and varargs. */ -+ -+int -+ubicom32_reg_parm_stack_space (tree fndecl) -+{ -+ return 0; -+ -+ if (fndecl -+ && TYPE_ARG_TYPES (TREE_TYPE (fndecl)) != 0 -+ && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))) -+ != void_type_node)) -+ return UBICOM32_FUNCTION_ARG_REGS * UNITS_PER_WORD; -+ -+ return 0; -+} -+ -+/* Flush the argument registers to the stack for a stdarg function; -+ return the new argument pointer. */ -+ -+rtx -+ubicom32_builtin_saveregs (void) -+{ -+ int regno; -+ -+ if (! cfun->stdarg) -+ return 0; -+ -+ for (regno = UBICOM32_FUNCTION_ARG_REGS - 1; regno >= 0; --regno) -+ emit_move_insn (gen_rtx_MEM (SImode, -+ gen_rtx_PRE_DEC (SImode, -+ stack_pointer_rtx)), -+ gen_rtx_REG (SImode, regno)); -+ -+ return stack_pointer_rtx; -+} -+ -+void -+ubicom32_va_start (tree valist, rtx nextarg) -+{ -+ std_expand_builtin_va_start (valist, nextarg); -+} -+ -+rtx -+ubicom32_va_arg (tree valist, tree type) -+{ -+ HOST_WIDE_INT size, rsize; -+ tree addr, incr, tmp; -+ rtx addr_rtx; -+ int indirect = 0; -+ -+ /* Round up sizeof(type) to a word. */ -+ size = int_size_in_bytes (type); -+ rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD; -+ -+ /* Large types are passed by reference. */ -+ if (size > 8) -+ { -+ indirect = 1; -+ size = rsize = UNITS_PER_WORD; -+ } -+ -+ incr = valist; -+ addr = incr = save_expr (incr); -+ -+ /* FIXME Nat's version - is it correct? */ -+ tmp = fold_convert (ptr_type_node, size_int (rsize)); -+ tmp = build2 (PLUS_EXPR, ptr_type_node, incr, tmp); -+ incr = fold (tmp); -+ -+ /* FIXME Nat's version - is it correct? */ -+ incr = build2 (MODIFY_EXPR, ptr_type_node, valist, incr); -+ -+ TREE_SIDE_EFFECTS (incr) = 1; -+ expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL); -+ -+ addr_rtx = expand_expr (addr, NULL, Pmode, EXPAND_NORMAL); -+ -+ if (size < UNITS_PER_WORD) -+ emit_insn (gen_addsi3 (addr_rtx, addr_rtx, -+ GEN_INT (UNITS_PER_WORD - size))); -+ -+ if (indirect) -+ { -+ addr_rtx = force_reg (Pmode, addr_rtx); -+ addr_rtx = gen_rtx_MEM (Pmode, addr_rtx); -+ set_mem_alias_set (addr_rtx, get_varargs_alias_set ()); -+ } -+ -+ return addr_rtx; -+} -+ -+void -+init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname, -+ int indirect ATTRIBUTE_UNUSED) -+{ -+ cum->nbytes = 0; -+ -+ if (!libname) -+ { -+ cum->stdarg = (TYPE_ARG_TYPES (fntype) != 0 -+ && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) -+ != void_type_node)); -+ } -+} -+ -+/* Return an RTX to represent where a value in mode MODE will be passed -+ to a function. If the result is 0, the argument will be pushed. */ -+ -+rtx -+function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, -+ int named ATTRIBUTE_UNUSED) -+{ -+ rtx result = 0; -+ int size, align; -+ int nregs = UBICOM32_FUNCTION_ARG_REGS; -+ -+ /* Figure out the size of the object to be passed. */ -+ if (mode == BLKmode) -+ size = int_size_in_bytes (type); -+ else -+ size = GET_MODE_SIZE (mode); -+ -+ /* Figure out the alignment of the object to be passed. */ -+ align = size; -+ -+ cum->nbytes = (cum->nbytes + 3) & ~3; -+ -+ /* Don't pass this arg via a register if all the argument registers -+ are used up. */ -+ if (cum->nbytes >= nregs * UNITS_PER_WORD) -+ return 0; -+ -+ /* Don't pass this arg via a register if it would be split between -+ registers and memory. */ -+ result = gen_rtx_REG (mode, cum->nbytes / UNITS_PER_WORD); -+ -+ return result; -+} -+ -+rtx -+function_incoming_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, -+ int named ATTRIBUTE_UNUSED) -+{ -+ if (cfun->stdarg) -+ return 0; -+ -+ return function_arg (cum, mode, type, named); -+} -+ -+ -+/* Implement hook TARGET_ARG_PARTIAL_BYTES. -+ -+ Returns the number of bytes at the beginning of an argument that -+ must be put in registers. The value must be zero for arguments -+ that are passed entirely in registers or that are entirely pushed -+ on the stack. */ -+static int -+ubicom32_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode, -+ tree type, bool named ATTRIBUTE_UNUSED) -+{ -+ int size, diff; -+ -+ int nregs = UBICOM32_FUNCTION_ARG_REGS; -+ -+ /* round up to full word */ -+ cum->nbytes = (cum->nbytes + 3) & ~3; -+ -+ if (targetm.calls.pass_by_reference (cum, mode, type, named)) -+ return 0; -+ -+ /* number of bytes left in registers */ -+ diff = nregs*UNITS_PER_WORD - cum->nbytes; -+ -+ /* regs all used up */ -+ if (diff <= 0) -+ return 0; -+ -+ /* Figure out the size of the object to be passed. */ -+ if (mode == BLKmode) -+ size = int_size_in_bytes (type); -+ else -+ size = GET_MODE_SIZE (mode); -+ -+ /* enough space left in regs for size */ -+ if (size <= diff) -+ return 0; -+ -+ /* put diff bytes in regs and rest on stack */ -+ return diff; -+ -+} -+ -+static bool -+ubicom32_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED, -+ enum machine_mode mode, const_tree type, -+ bool named ATTRIBUTE_UNUSED) -+{ -+ int size; -+ -+ if (type) -+ size = int_size_in_bytes (type); -+ else -+ size = GET_MODE_SIZE (mode); -+ -+ return size <= 0 || size > 8; -+} -+ -+static bool -+ubicom32_callee_copies (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED, -+ enum machine_mode mode, const_tree type, -+ bool named ATTRIBUTE_UNUSED) -+{ -+ int size; -+ -+ if (type) -+ size = int_size_in_bytes (type); -+ else -+ size = GET_MODE_SIZE (mode); -+ -+ return size <= 0 || size > 8; -+} -+ -+static bool -+ubicom32_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) -+{ -+ int size, mode; -+ -+ if (!type) -+ return true; -+ -+ size = int_size_in_bytes(type); -+ if (size > 8) -+ return true; -+ -+ mode = TYPE_MODE(type); -+ if (mode == BLKmode) -+ return true; -+ -+ return false; -+} -+ -+/* Return true if a given register number REGNO is acceptable for machine -+ mode MODE. */ -+bool -+ubicom32_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode) -+{ -+ /* If we're not at least a v3 ISA then ACC0_HI is only 16 bits. */ -+ if (! ubicom32_v3) -+ { -+ if (regno == ACC0_HI_REGNUM) -+ return (mode == QImode || mode == HImode); -+ } -+ -+ /* Only the flags reg can hold CCmode. */ -+ if (GET_MODE_CLASS (mode) == MODE_CC) -+ return regno == CC_REGNUM; -+ -+ /* We restrict the choice of DImode registers to only being address, -+ data or accumulator regs. We also restrict them to only start on -+ even register numbers so we never have to worry about partial -+ overlaps between operands in instructions. */ -+ if (GET_MODE_SIZE (mode) > 4) -+ { -+ switch (REGNO_REG_CLASS (regno)) -+ { -+ case ADDRESS_REGS: -+ case DATA_REGS: -+ case ACC_REGS: -+ return (regno & 1) == 0; -+ -+ default: -+ return false; -+ } -+ } -+ -+ return true; -+} -+ -+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx -+ and check its validity for a certain class. -+ We have two alternate definitions for each of them. -+ The usual definition accepts all pseudo regs; the other rejects -+ them unless they have been allocated suitable hard regs. -+ The symbol REG_OK_STRICT causes the latter definition to be used. -+ -+ Most source files want to accept pseudo regs in the hope that -+ they will get allocated to the class that the insn wants them to be in. -+ Source files for reload pass need to be strict. -+ After reload, it makes no difference, since pseudo regs have -+ been eliminated by then. -+ -+ These assume that REGNO is a hard or pseudo reg number. -+ They give nonzero only if REGNO is a hard reg of the suitable class -+ or a pseudo reg currently allocated to a suitable hard reg. -+ Since they use reg_renumber, they are safe only once reg_renumber -+ has been allocated, which happens in local-alloc.c. */ -+ -+int -+ubicom32_regno_ok_for_base_p (int regno, int strict) -+{ -+ if ((regno >= FIRST_ADDRESS_REGNUM && regno <= STACK_POINTER_REGNUM) -+ || (!strict -+ && (regno >= FIRST_PSEUDO_REGISTER -+ || regno == ARG_POINTER_REGNUM)) -+ || (strict && (reg_renumber -+ && reg_renumber[regno] >= FIRST_ADDRESS_REGNUM -+ && reg_renumber[regno] <= STACK_POINTER_REGNUM))) -+ return 1; -+ -+ return 0; -+} -+ -+int -+ubicom32_regno_ok_for_index_p (int regno, int strict) -+{ -+ if ((regno >= FIRST_DATA_REGNUM && regno <= LAST_DATA_REGNUM) -+ || (!strict && regno >= FIRST_PSEUDO_REGISTER) -+ || (strict && (reg_renumber -+ && reg_renumber[regno] >= FIRST_DATA_REGNUM -+ && reg_renumber[regno] <= LAST_DATA_REGNUM))) -+ return 1; -+ -+ return 0; -+} -+ -+/* Returns 1 if X is a valid index register. STRICT is 1 if only hard -+ registers should be accepted. Accept either REG or SUBREG where a -+ register is valid. */ -+ -+static bool -+ubicom32_is_index_reg (rtx x, int strict) -+{ -+ if ((REG_P (x) && ubicom32_regno_ok_for_index_p (REGNO (x), strict)) -+ || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x)) -+ && ubicom32_regno_ok_for_index_p (REGNO (SUBREG_REG (x)), strict))) -+ return true; -+ -+ return false; -+} -+ -+/* Return 1 if X is a valid index for a memory address. */ -+ -+static bool -+ubicom32_is_index_expr (enum machine_mode mode, rtx x, int strict) -+{ -+ /* Immediate index must be an unsigned 7-bit offset multiple of 1, 2 -+ or 4 depending on mode. */ -+ if (CONST_INT_P (x)) -+ { -+ switch (mode) -+ { -+ case QImode: -+ return satisfies_constraint_J (x); -+ -+ case HImode: -+ return satisfies_constraint_K (x); -+ -+ case SImode: -+ case SFmode: -+ return satisfies_constraint_L (x); -+ -+ case DImode: -+ return satisfies_constraint_L (x) -+ && satisfies_constraint_L (GEN_INT (INTVAL (x) + 4)); -+ -+ default: -+ return false; -+ } -+ } -+ -+ if (mode != SImode && mode != HImode && mode != QImode) -+ return false; -+ -+ /* Register index scaled by mode of operand: REG + REG * modesize. -+ Valid scaled index registers are: -+ -+ SImode (mult (dreg) 4)) -+ HImode (mult (dreg) 2)) -+ QImode (mult (dreg) 1)) */ -+ if (GET_CODE (x) == MULT -+ && ubicom32_is_index_reg (XEXP (x, 0), strict) -+ && CONST_INT_P (XEXP (x, 1)) -+ && INTVAL (XEXP (x, 1)) == (HOST_WIDE_INT)GET_MODE_SIZE (mode)) -+ return true; -+ -+ /* REG + REG addressing is allowed for QImode. */ -+ if (ubicom32_is_index_reg (x, strict) && mode == QImode) -+ return true; -+ -+ return false; -+} -+ -+static bool -+ubicom32_is_valid_offset (enum machine_mode mode, HOST_WIDE_INT offs) -+{ -+ if (offs < 0) -+ return false; -+ -+ switch (mode) -+ { -+ case QImode: -+ return offs <= 127; -+ -+ case HImode: -+ return offs <= 254; -+ -+ case SImode: -+ case SFmode: -+ return offs <= 508; -+ -+ case DImode: -+ return offs <= 504; -+ -+ default: -+ return false; -+ } -+} -+ -+static int -+ubicom32_get_valid_offset_mask (enum machine_mode mode) -+{ -+ switch (mode) -+ { -+ case QImode: -+ return 127; -+ -+ case HImode: -+ return 255; -+ -+ case SImode: -+ case SFmode: -+ return 511; -+ -+ case DImode: -+ return 255; -+ -+ default: -+ return 0; -+ } -+} -+ -+/* Returns 1 if X is a valid base register. STRICT is 1 if only hard -+ registers should be accepted. Accept either REG or SUBREG where a -+ register is valid. */ -+ -+static bool -+ubicom32_is_base_reg (rtx x, int strict) -+{ -+ if ((REG_P (x) && ubicom32_regno_ok_for_base_p (REGNO (x), strict)) -+ || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x)) -+ && ubicom32_regno_ok_for_base_p (REGNO (SUBREG_REG (x)), strict))) -+ return true; -+ -+ return false; -+} -+ -+static bool -+ubicom32_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED) -+{ -+ return TARGET_FDPIC; -+} -+ -+/* Determine if X is a legitimate constant. */ -+ -+bool -+ubicom32_legitimate_constant_p (rtx x) -+{ -+ /* Among its other duties, LEGITIMATE_CONSTANT_P decides whether -+ a constant can be entered into reg_equiv_constant[]. If we return true, -+ reload can create new instances of the constant whenever it likes. -+ -+ The idea is therefore to accept as many constants as possible (to give -+ reload more freedom) while rejecting constants that can only be created -+ at certain times. In particular, anything with a symbolic component will -+ require use of the pseudo FDPIC register, which is only available before -+ reload. */ -+ if (TARGET_FDPIC) -+ { -+ if (GET_CODE (x) == SYMBOL_REF -+ || (GET_CODE (x) == CONST -+ && GET_CODE (XEXP (x, 0)) == PLUS -+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF) -+ || CONSTANT_ADDRESS_P (x)) -+ return false; -+ -+ return true; -+ } -+ -+ /* For non-PIC code anything goes! */ -+ return true; -+} -+ -+/* Address validation. */ -+ -+bool -+ubicom32_legitimate_address_p (enum machine_mode mode, rtx x, int strict) -+{ -+ if (TARGET_DEBUG_ADDRESS) -+ { -+ fprintf (stderr, "\n==> GO_IF_LEGITIMATE_ADDRESS%s\n", -+ (strict) ? " (STRICT)" : ""); -+ debug_rtx (x); -+ } -+ -+ if (CONSTANT_ADDRESS_P (x)) -+ return false; -+ -+ if (ubicom32_is_base_reg (x, strict)) -+ return true; -+ -+ if ((GET_CODE (x) == POST_INC -+ || GET_CODE (x) == PRE_INC -+ || GET_CODE (x) == POST_DEC -+ || GET_CODE (x) == PRE_DEC) -+ && REG_P (XEXP (x, 0)) -+ && ubicom32_is_base_reg (XEXP (x, 0), strict) -+ && mode != DImode) -+ return true; -+ -+ if ((GET_CODE (x) == PRE_MODIFY || GET_CODE (x) == POST_MODIFY) -+ && ubicom32_is_base_reg (XEXP (x, 0), strict) -+ && GET_CODE (XEXP (x, 1)) == PLUS -+ && rtx_equal_p (XEXP (x, 0), XEXP (XEXP (x, 1), 0)) -+ && CONST_INT_P (XEXP (XEXP (x, 1), 1)) -+ && mode != DImode) -+ { -+ HOST_WIDE_INT disp = INTVAL (XEXP (XEXP (x, 1), 1)); -+ switch (mode) -+ { -+ case QImode: -+ return disp >= -8 && disp <= 7; -+ -+ case HImode: -+ return disp >= -16 && disp <= 14 && ! (disp & 1); -+ -+ case SImode: -+ return disp >= -32 && disp <= 28 && ! (disp & 3); -+ -+ default: -+ return false; -+ } -+ } -+ -+ /* Accept base + index * scale. */ -+ if (GET_CODE (x) == PLUS -+ && ubicom32_is_base_reg (XEXP (x, 0), strict) -+ && ubicom32_is_index_expr (mode, XEXP (x, 1), strict)) -+ return true; -+ -+ /* Accept index * scale + base. */ -+ if (GET_CODE (x) == PLUS -+ && ubicom32_is_base_reg (XEXP (x, 1), strict) -+ && ubicom32_is_index_expr (mode, XEXP (x, 0), strict)) -+ return true; -+ -+ if (! TARGET_FDPIC) -+ { -+ /* Accept (lo_sum (reg) (symbol_ref)) that can be used as a mem+7bits -+ displacement operand: -+ -+ moveai a1, #%hi(SYM) -+ move.4 d3, %lo(SYM)(a1) */ -+ if (GET_CODE (x) == LO_SUM -+ && ubicom32_is_base_reg (XEXP (x, 0), strict) -+ && (GET_CODE (XEXP (x, 1)) == SYMBOL_REF -+ || GET_CODE (XEXP (x, 1)) == LABEL_REF /* FIXME: wrong */) -+ && mode != DImode) -+ return true; -+ } -+ -+ if (TARGET_DEBUG_ADDRESS) -+ fprintf (stderr, "\nNot a legitimate address.\n"); -+ -+ return false; -+} -+ -+rtx -+ubicom32_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, -+ enum machine_mode mode) -+{ -+ if (mode == BLKmode) -+ return NULL_RTX; -+ -+ if (GET_CODE (x) == PLUS -+ && REG_P (XEXP (x, 0)) -+ && ! REGNO_PTR_FRAME_P (REGNO (XEXP (x, 0))) -+ && CONST_INT_P (XEXP (x, 1)) -+ && ! ubicom32_is_valid_offset (mode, INTVAL (XEXP (x, 1)))) -+ { -+ rtx base; -+ rtx plus; -+ rtx new_rtx; -+ HOST_WIDE_INT val = INTVAL (XEXP (x, 1)); -+ HOST_WIDE_INT low = val & ubicom32_get_valid_offset_mask (mode); -+ HOST_WIDE_INT high = val ^ low; -+ -+ if (val < 0) -+ return NULL_RTX; -+ -+ if (! low) -+ return NULL_RTX; -+ -+ /* Reload the high part into a base reg; leave the low part -+ in the mem directly. */ -+ base = XEXP (x, 0); -+ if (! ubicom32_is_base_reg (base, 0)) -+ base = copy_to_mode_reg (Pmode, base); -+ -+ plus = expand_simple_binop (Pmode, PLUS, -+ gen_int_mode (high, Pmode), -+ base, NULL, 0, OPTAB_WIDEN); -+ new_rtx = plus_constant (plus, low); -+ -+ return new_rtx; -+ } -+ -+ return NULL_RTX; -+} -+ -+/* Try a machine-dependent way of reloading an illegitimate address AD -+ operand. If we find one, push the reload and and return the new address. -+ -+ MODE is the mode of the enclosing MEM. OPNUM is the operand number -+ and TYPE is the reload type of the current reload. */ -+ -+rtx -+ubicom32_legitimize_reload_address (rtx ad, enum machine_mode mode, -+ int opnum, int type) -+{ -+ /* Is this an address that we've already fixed up? If it is then -+ recognize it and move on. */ -+ if (GET_CODE (ad) == PLUS -+ && GET_CODE (XEXP (ad, 0)) == PLUS -+ && REG_P (XEXP (XEXP (ad, 0), 0)) -+ && CONST_INT_P (XEXP (XEXP (ad, 0), 1)) -+ && CONST_INT_P (XEXP (ad, 1))) -+ { -+ push_reload (XEXP (ad, 0), NULL_RTX, &XEXP (ad, 0), NULL, -+ BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, -+ opnum, (enum reload_type) type); -+ return ad; -+ } -+ -+ /* Have we got an address where the offset is simply out of range? If -+ yes then reload the range as a high part and smaller offset. */ -+ if (GET_CODE (ad) == PLUS -+ && REG_P (XEXP (ad, 0)) -+ && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER -+ && REGNO_OK_FOR_BASE_P (REGNO (XEXP (ad, 0))) -+ && CONST_INT_P (XEXP (ad, 1)) -+ && ! ubicom32_is_valid_offset (mode, INTVAL (XEXP (ad, 1)))) -+ { -+ rtx temp; -+ rtx new_rtx; -+ -+ HOST_WIDE_INT val = INTVAL (XEXP (ad, 1)); -+ HOST_WIDE_INT low = val & ubicom32_get_valid_offset_mask (mode); -+ HOST_WIDE_INT high = val ^ low; -+ -+ /* Reload the high part into a base reg; leave the low part -+ in the mem directly. */ -+ temp = gen_rtx_PLUS (Pmode, XEXP (ad, 0), GEN_INT (high)); -+ new_rtx = gen_rtx_PLUS (Pmode, temp, GEN_INT (low)); -+ -+ push_reload (XEXP (new_rtx, 0), NULL_RTX, &XEXP (new_rtx, 0), NULL, -+ BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, -+ opnum, (enum reload_type) type); -+ return new_rtx; -+ } -+ -+ /* If we're presented with an pre/post inc/dec then we must force this -+ to be done in an address register. The register allocator should -+ work this out for itself but at times ends up trying to use the wrong -+ class. If we get the wrong class then reload will end up generating -+ at least 3 instructions whereas this way we can hopefully keep it to -+ just 2. */ -+ if ((GET_CODE (ad) == POST_INC -+ || GET_CODE (ad) == PRE_INC -+ || GET_CODE (ad) == POST_DEC -+ || GET_CODE (ad) == PRE_DEC) -+ && REG_P (XEXP (ad, 0)) -+ && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER -+ && ! REGNO_OK_FOR_BASE_P (REGNO (XEXP (ad, 0)))) -+ { -+ push_reload (XEXP (ad, 0), XEXP (ad, 0), &XEXP (ad, 0), &XEXP (ad, 0), -+ BASE_REG_CLASS, GET_MODE (XEXP (ad, 0)), GET_MODE (XEXP (ad, 0)), 0, 0, -+ opnum, RELOAD_OTHER); -+ return ad; -+ } -+ -+ return NULL_RTX; -+} -+ -+/* Compute a (partial) cost for rtx X. Return true if the complete -+ cost has been computed, and false if subexpressions should be -+ scanned. In either case, *TOTAL contains the cost result. */ -+ -+static bool -+ubicom32_rtx_costs (rtx x, int code, int outer_code, int *total, -+ bool speed ATTRIBUTE_UNUSED) -+{ -+ enum machine_mode mode = GET_MODE (x); -+ -+ switch (code) -+ { -+ case CONST_INT: -+ /* Very short constants often fold into instructions so -+ we pretend that they don't cost anything! This is -+ really important as regards zero values as otherwise -+ the compiler has a nasty habit of wanting to reuse -+ zeroes that are in regs but that tends to pessimize -+ the code. */ -+ if (satisfies_constraint_I (x)) -+ { -+ *total = 0; -+ return true; -+ } -+ -+ /* Bit clearing costs nothing */ -+ if (outer_code == AND -+ && exact_log2 (~INTVAL (x)) != -1) -+ { -+ *total = 0; -+ return true; -+ } -+ -+ /* Masking the lower set of bits costs nothing. */ -+ if (outer_code == AND -+ && exact_log2 (INTVAL (x) + 1) != -1) -+ { -+ *total = 0; -+ return true; -+ } -+ -+ /* Bit setting costs nothing. */ -+ if (outer_code == IOR -+ && exact_log2 (INTVAL (x)) != -1) -+ { -+ *total = 0; -+ return true; -+ } -+ -+ /* Larger constants that can be loaded via movei aren't too -+ bad. If we're just doing a set they cost nothing extra. */ -+ if (satisfies_constraint_N (x)) -+ { -+ if (mode == DImode) -+ *total = COSTS_N_INSNS (2); -+ else -+ *total = COSTS_N_INSNS (1); -+ return true; -+ } -+ -+ if (mode == DImode) -+ *total = COSTS_N_INSNS (5); -+ else -+ *total = COSTS_N_INSNS (3); -+ return true; -+ -+ case CONST_DOUBLE: -+ /* We don't optimize CONST_DOUBLEs well nor do we relax them well, -+ so their cost is very high. */ -+ *total = COSTS_N_INSNS (6); -+ return true; -+ -+ case CONST: -+ case SYMBOL_REF: -+ case MEM: -+ *total = 0; -+ return true; -+ -+ case IF_THEN_ELSE: -+ *total = COSTS_N_INSNS (1); -+ return true; -+ -+ case LABEL_REF: -+ case HIGH: -+ case LO_SUM: -+ case BSWAP: -+ case PLUS: -+ case MINUS: -+ case AND: -+ case IOR: -+ case XOR: -+ case ASHIFT: -+ case ASHIFTRT: -+ case LSHIFTRT: -+ case NEG: -+ case NOT: -+ case SIGN_EXTEND: -+ case ZERO_EXTEND: -+ case ZERO_EXTRACT: -+ if (outer_code == SET) -+ { -+ if (mode == DImode) -+ *total = COSTS_N_INSNS (2); -+ else -+ *total = COSTS_N_INSNS (1); -+ } -+ return true; -+ -+ case COMPARE: -+ if (outer_code == SET) -+ { -+ if (GET_MODE (XEXP (x, 0)) == DImode -+ || GET_MODE (XEXP (x, 1)) == DImode) -+ *total = COSTS_N_INSNS (2); -+ else -+ *total = COSTS_N_INSNS (1); -+ } -+ return true; -+ -+ case UMOD: -+ case UDIV: -+ case MOD: -+ case DIV: -+ if (outer_code == SET) -+ { -+ if (mode == DImode) -+ *total = COSTS_N_INSNS (600); -+ else -+ *total = COSTS_N_INSNS (200); -+ } -+ return true; -+ -+ case MULT: -+ if (outer_code == SET) -+ { -+ if (! ubicom32_v4) -+ { -+ if (mode == DImode) -+ *total = COSTS_N_INSNS (15); -+ else -+ *total = COSTS_N_INSNS (5); -+ } -+ else -+ { -+ if (mode == DImode) -+ *total = COSTS_N_INSNS (6); -+ else -+ *total = COSTS_N_INSNS (2); -+ } -+ } -+ return true; -+ -+ case UNSPEC: -+ if (XINT (x, 1) == UNSPEC_FDPIC_GOT -+ || XINT (x, 1) == UNSPEC_FDPIC_GOT_FUNCDESC) -+ *total = 0; -+ return true; -+ -+ default: -+ return false; -+ } -+} -+ -+/* Return 1 if ADDR can have different meanings depending on the machine -+ mode of the memory reference it is used for or if the address is -+ valid for some modes but not others. -+ -+ Autoincrement and autodecrement addresses typically have -+ mode-dependent effects because the amount of the increment or -+ decrement is the size of the operand being addressed. Some machines -+ have other mode-dependent addresses. Many RISC machines have no -+ mode-dependent addresses. -+ -+ You may assume that ADDR is a valid address for the machine. */ -+ -+int -+ubicom32_mode_dependent_address_p (rtx addr) -+{ -+ if (GET_CODE (addr) == POST_INC -+ || GET_CODE (addr) == PRE_INC -+ || GET_CODE (addr) == POST_DEC -+ || GET_CODE (addr) == PRE_DEC -+ || GET_CODE (addr) == POST_MODIFY -+ || GET_CODE (addr) == PRE_MODIFY) -+ return 1; -+ -+ return 0; -+} -+ -+static void -+ubicom32_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) -+{ -+ fprintf (file, "/* frame/pretend: %ld/%d save_regs: %d out_args: %d %s */\n", -+ get_frame_size (), crtl->args.pretend_args_size, -+ save_regs_size, crtl->outgoing_args_size, -+ current_function_is_leaf ? "leaf" : "nonleaf"); -+} -+ -+static void -+ubicom32_function_epilogue (FILE *file ATTRIBUTE_UNUSED, -+ HOST_WIDE_INT size ATTRIBUTE_UNUSED) -+{ -+ ubicom32_reorg_completed = 0; -+} -+ -+static void -+ubicom32_machine_dependent_reorg (void) -+{ -+#if 0 /* Commenting out this optimization until it is fixed */ -+ if (optimize) -+ { -+ compute_bb_for_insn (); -+ -+ /* Do a very simple CSE pass over just the hard registers. */ -+ reload_cse_regs (get_insns ()); -+ -+ /* Reload_cse_regs can eliminate potentially-trapping MEMs. -+ Remove any EH edges associated with them. */ -+ if (flag_non_call_exceptions) -+ purge_all_dead_edges (); -+ } -+#endif -+ ubicom32_reorg_completed = 1; -+} -+ -+void -+ubicom32_output_cond_jump (rtx insn, rtx cond, rtx target) -+{ -+ rtx note; -+ int mostly_false_jump; -+ rtx xoperands[2]; -+ rtx cc_reg; -+ -+ note = find_reg_note (insn, REG_BR_PROB, 0); -+ mostly_false_jump = !note || (INTVAL (XEXP (note, 0)) -+ <= REG_BR_PROB_BASE / 2); -+ -+ xoperands[0] = target; -+ xoperands[1] = cond; -+ cc_reg = XEXP (cond, 0); -+ -+ if (GET_MODE (cc_reg) == CCWmode -+ || GET_MODE (cc_reg) == CCWZmode -+ || GET_MODE (cc_reg) == CCWZNmode) -+ { -+ if (mostly_false_jump) -+ output_asm_insn ("jmp%b1.w.f\t%0", xoperands); -+ else -+ output_asm_insn ("jmp%b1.w.t\t%0", xoperands); -+ return; -+ } -+ -+ if (GET_MODE (cc_reg) == CCSmode -+ || GET_MODE (cc_reg) == CCSZmode -+ || GET_MODE (cc_reg) == CCSZNmode) -+ { -+ if (mostly_false_jump) -+ output_asm_insn ("jmp%b1.s.f\t%0", xoperands); -+ else -+ output_asm_insn ("jmp%b1.s.t\t%0", xoperands); -+ return; -+ } -+ -+ abort (); -+} -+ -+/* Return non-zero if FUNC is a naked function. */ -+ -+static int -+ubicom32_naked_function_p (void) -+{ -+ return lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE; -+} -+ -+/* Return an RTX indicating where the return address to the -+ calling function can be found. */ -+rtx -+ubicom32_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED) -+{ -+ if (count != 0) -+ return NULL_RTX; -+ -+ return get_hard_reg_initial_val (Pmode, LINK_REGNO); -+} -+ -+/* -+ * ubicom32_readonly_data_section: This routtine handles code -+ * at the start of readonly data sections -+ */ -+static void -+ubicom32_readonly_data_section (const void *data ATTRIBUTE_UNUSED) -+{ -+ static int num = 0; -+ if (in_section == readonly_data_section){ -+ fprintf (asm_out_file, "%s", DATA_SECTION_ASM_OP); -+ if (flag_data_sections){ -+ fprintf (asm_out_file, ".rodata%d", num); -+ fprintf (asm_out_file, ",\"a\""); -+ } -+ fprintf (asm_out_file, "\n"); -+ } -+ num++; -+} -+ -+/* -+ * ubicom32_text_section: not in readonly section -+ */ -+static void -+ubicom32_text_section(const void *data ATTRIBUTE_UNUSED) -+{ -+ fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP); -+} -+ -+/* -+ * ubicom32_data_section: not in readonly section -+ */ -+static void -+ubicom32_data_section(const void *data ATTRIBUTE_UNUSED) -+{ -+ fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP); -+} -+ -+/* -+ * ubicom32_asm_init_sections: This routine implements special -+ * section handling -+ */ -+static void -+ubicom32_asm_init_sections(void) -+{ -+ text_section = get_unnamed_section(SECTION_CODE, ubicom32_text_section, NULL); -+ -+ data_section = get_unnamed_section(SECTION_WRITE, ubicom32_data_section, NULL); -+ -+ readonly_data_section = get_unnamed_section(0, ubicom32_readonly_data_section, NULL); -+} -+ -+/* -+ * ubicom32_profiler: This routine would call -+ * mcount to support prof and gprof if mcount -+ * was supported. Currently, do nothing. -+ */ -+void -+ubicom32_profiler(void) -+{ -+} -+ -+/* Initialise the builtin functions. Start by initialising -+ descriptions of different types of functions (e.g., void fn(int), -+ int fn(void)), and then use these to define the builtins. */ -+static void -+ubicom32_init_builtins (void) -+{ -+ tree endlink; -+ tree short_unsigned_endlink; -+ tree unsigned_endlink; -+ tree short_unsigned_ftype_short_unsigned; -+ tree unsigned_ftype_unsigned; -+ -+ endlink = void_list_node; -+ -+ short_unsigned_endlink -+ = tree_cons (NULL_TREE, short_unsigned_type_node, endlink); -+ -+ unsigned_endlink -+ = tree_cons (NULL_TREE, unsigned_type_node, endlink); -+ -+ short_unsigned_ftype_short_unsigned -+ = build_function_type (short_unsigned_type_node, short_unsigned_endlink); -+ -+ unsigned_ftype_unsigned -+ = build_function_type (unsigned_type_node, unsigned_endlink); -+ -+ /* Initialise the byte swap function. */ -+ add_builtin_function ("__builtin_ubicom32_swapb_2", -+ short_unsigned_ftype_short_unsigned, -+ UBICOM32_BUILTIN_UBICOM32_SWAPB_2, -+ BUILT_IN_MD, NULL, -+ NULL_TREE); -+ -+ /* Initialise the byte swap function. */ -+ add_builtin_function ("__builtin_ubicom32_swapb_4", -+ unsigned_ftype_unsigned, -+ UBICOM32_BUILTIN_UBICOM32_SWAPB_4, -+ BUILT_IN_MD, NULL, -+ NULL_TREE); -+} -+ -+/* Given a builtin function taking 2 operands (i.e., target + source), -+ emit the RTL for the underlying instruction. */ -+static rtx -+ubicom32_expand_builtin_2op (enum insn_code icode, tree arglist, rtx target) -+{ -+ tree arg0; -+ rtx op0, pat; -+ enum machine_mode tmode, mode0; -+ -+ /* Grab the incoming argument and emit its RTL. */ -+ arg0 = TREE_VALUE (arglist); -+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); -+ -+ /* Determine the modes of the instruction operands. */ -+ tmode = insn_data[icode].operand[0].mode; -+ mode0 = insn_data[icode].operand[1].mode; -+ -+ /* Ensure that the incoming argument RTL is in a register of the -+ correct mode. */ -+ if (!(*insn_data[icode].operand[1].predicate) (op0, mode0)) -+ op0 = copy_to_mode_reg (mode0, op0); -+ -+ /* If there isn't a suitable target, emit a target register. */ -+ if (target == 0 -+ || GET_MODE (target) != tmode -+ || !(*insn_data[icode].operand[0].predicate) (target, tmode)) -+ target = gen_reg_rtx (tmode); -+ -+ /* Emit and return the new instruction. */ -+ pat = GEN_FCN (icode) (target, op0); -+ if (!pat) -+ return 0; -+ emit_insn (pat); -+ -+ return target; -+} -+ -+/* Expand a call to a builtin function. */ -+static rtx -+ubicom32_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, -+ enum machine_mode mode ATTRIBUTE_UNUSED, -+ int ignore ATTRIBUTE_UNUSED) -+{ -+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); -+ tree arglist = CALL_EXPR_ARGS(exp); -+ int fcode = DECL_FUNCTION_CODE (fndecl); -+ -+ switch (fcode) -+ { -+ case UBICOM32_BUILTIN_UBICOM32_SWAPB_2: -+ return ubicom32_expand_builtin_2op (CODE_FOR_bswaphi, arglist, target); -+ -+ case UBICOM32_BUILTIN_UBICOM32_SWAPB_4: -+ return ubicom32_expand_builtin_2op (CODE_FOR_bswapsi, arglist, target); -+ -+ default: -+ gcc_unreachable(); -+ } -+ -+ /* Should really do something sensible here. */ -+ return NULL_RTX; -+} -+ -+/* Fold any constant argument for a swapb.2 instruction. */ -+static tree -+ubicom32_fold_builtin_ubicom32_swapb_2 (tree fndecl, tree arglist) -+{ -+ tree arg0; -+ -+ arg0 = TREE_VALUE (arglist); -+ -+ /* Optimize constant value. */ -+ if (TREE_CODE (arg0) == INTEGER_CST) -+ { -+ HOST_WIDE_INT v; -+ HOST_WIDE_INT res; -+ -+ v = TREE_INT_CST_LOW (arg0); -+ res = ((v >> 8) & 0xff) -+ | ((v & 0xff) << 8); -+ -+ return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), res); -+ } -+ -+ return NULL_TREE; -+} -+ -+/* Fold any constant argument for a swapb.4 instruction. */ -+static tree -+ubicom32_fold_builtin_ubicom32_swapb_4 (tree fndecl, tree arglist) -+{ -+ tree arg0; -+ -+ arg0 = TREE_VALUE (arglist); -+ -+ /* Optimize constant value. */ -+ if (TREE_CODE (arg0) == INTEGER_CST) -+ { -+ unsigned HOST_WIDE_INT v; -+ unsigned HOST_WIDE_INT res; -+ -+ v = TREE_INT_CST_LOW (arg0); -+ res = ((v >> 24) & 0xff) -+ | (((v >> 16) & 0xff) << 8) -+ | (((v >> 8) & 0xff) << 16) -+ | ((v & 0xff) << 24); -+ -+ return build_int_cst_wide (TREE_TYPE (TREE_TYPE (fndecl)), res, 0); -+ } -+ -+ return NULL_TREE; -+} -+ -+/* Fold any constant arguments for builtin functions. */ -+static tree -+ubicom32_fold_builtin (tree fndecl, tree arglist, bool ignore ATTRIBUTE_UNUSED) -+{ -+ switch (DECL_FUNCTION_CODE (fndecl)) -+ { -+ case UBICOM32_BUILTIN_UBICOM32_SWAPB_2: -+ return ubicom32_fold_builtin_ubicom32_swapb_2 (fndecl, arglist); -+ -+ case UBICOM32_BUILTIN_UBICOM32_SWAPB_4: -+ return ubicom32_fold_builtin_ubicom32_swapb_4 (fndecl, arglist); -+ -+ default: -+ return NULL; -+ } -+} -+ -+/* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to -+ tell the assembler to generate pointers to function descriptors in -+ some cases. */ -+static bool -+ubicom32_assemble_integer (rtx value, unsigned int size, int aligned_p) -+{ -+ if (TARGET_FDPIC && size == UNITS_PER_WORD) -+ { -+ if (GET_CODE (value) == SYMBOL_REF -+ && SYMBOL_REF_FUNCTION_P (value)) -+ { -+ fputs ("\t.picptr\t%funcdesc(", asm_out_file); -+ output_addr_const (asm_out_file, value); -+ fputs (")\n", asm_out_file); -+ return true; -+ } -+ -+ if (!aligned_p) -+ { -+ /* We've set the unaligned SI op to NULL, so we always have to -+ handle the unaligned case here. */ -+ assemble_integer_with_op ("\t.4byte\t", value); -+ return true; -+ } -+ } -+ -+ return default_assemble_integer (value, size, aligned_p); -+} -+ -+/* If the constant I can be constructed by shifting a source-1 immediate -+ by a constant number of bits then return the bit count. If not -+ return 0. */ -+ -+int -+ubicom32_shiftable_const_int (int i) -+{ -+ int shift = 0; -+ -+ /* Note that any constant that can be represented as an immediate to -+ a movei instruction is automatically ignored here in the interests -+ of the clarity of the output asm code. */ -+ if (i >= -32768 && i <= 32767) -+ return 0; -+ -+ /* Find the number of trailing zeroes. We could use __builtin_ctz -+ here but it's not obvious if this is supported on all build -+ compilers so we err on the side of caution. */ -+ if ((i & 0xffff) == 0) -+ { -+ shift += 16; -+ i >>= 16; -+ } -+ -+ if ((i & 0xff) == 0) -+ { -+ shift += 8; -+ i >>= 8; -+ } -+ -+ if ((i & 0xf) == 0) -+ { -+ shift += 4; -+ i >>= 4; -+ } -+ -+ if ((i & 0x3) == 0) -+ { -+ shift += 2; -+ i >>= 2; -+ } -+ -+ if ((i & 0x1) == 0) -+ { -+ shift += 1; -+ i >>= 1; -+ } -+ -+ if (i >= -128 && i <= 127) -+ return shift; -+ -+ return 0; -+} -+ ---- /dev/null -+++ b/gcc/config/ubicom32/ubicom32.h -@@ -0,0 +1,1564 @@ -+/* Definitions of target machine for Ubicom32 -+ -+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -+ 2009 Free Software Foundation, Inc. -+ Contributed by Ubicom, Inc. -+ -+ This file is part of GCC. -+ -+ GCC is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published -+ by the Free Software Foundation; either version 3, or (at your -+ option) any later version. -+ -+ GCC is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+ License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with GCC; see the file COPYING3. If not see -+ <http://www.gnu.org/licenses/>. */ -+ -+ -+ -+#define OBJECT_FORMAT_ELF -+ -+/* Run-time target specifications. */ -+ -+/* Target CPU builtins. */ -+#define TARGET_CPU_CPP_BUILTINS() \ -+ do \ -+ { \ -+ builtin_define_std ("__UBICOM32__"); \ -+ builtin_define_std ("__ubicom32__"); \ -+ \ -+ if (TARGET_FDPIC) \ -+ { \ -+ builtin_define ("__UBICOM32_FDPIC__"); \ -+ builtin_define ("__FDPIC__"); \ -+ } \ -+ } \ -+ while (0) -+ -+#ifndef TARGET_DEFAULT -+#define TARGET_DEFAULT 0 -+#endif -+ -+extern int ubicom32_case_values_threshold; -+ -+/* Nonzero if this chip supports the Ubicom32 v3 ISA. */ -+extern int ubicom32_v3; -+ -+/* Nonzero if this chip supports the Ubicom32 v4 ISA. */ -+extern int ubicom32_v4; -+ -+extern int ubicom32_stack_size; -+ -+/* Flag for whether we can use calli instead of ret in returns. */ -+extern int ubicom32_can_use_calli_to_ret; -+ -+/* This macro is a C statement to print on `stderr' a string describing the -+ particular machine description choice. Every machine description should -+ define `TARGET_VERSION'. */ -+#define TARGET_VERSION fprintf (stderr, " (UBICOM32)"); -+ -+/* We don't need a frame pointer to debug things. Doing this means -+ that gcc can turn on -fomit-frame-pointer when '-O' is specified. */ -+#define CAN_DEBUG_WITHOUT_FP -+ -+/* We need to handle processor-specific options. */ -+#define OVERRIDE_OPTIONS ubicom32_override_options () -+ -+#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) \ -+ ubicom32_optimization_options (LEVEL, SIZE) -+ -+/* For Ubicom32 the least significant bit has the lowest bit number -+ so we define this to be 0. */ -+#define BITS_BIG_ENDIAN 0 -+ -+/* For Ubicom32 the most significant byte in a word has the lowest -+ number. */ -+#define BYTES_BIG_ENDIAN 1 -+ -+/* For Ubicom32, in a multiword object, the most signifant word has the -+ lowest number. */ -+#define WORDS_BIG_ENDIAN 1 -+ -+/* Ubicom32 has 8 bits per byte. */ -+#define BITS_PER_UNIT 8 -+ -+/* Ubicom32 has 32 bits per word. */ -+#define BITS_PER_WORD 32 -+ -+/* Width of a word, in units (bytes). */ -+#define UNITS_PER_WORD 4 -+ -+/* Width of a pointer, in bits. */ -+#define POINTER_SIZE 32 -+ -+/* Alias for pointers. Ubicom32 is a 32-bit architecture so we use -+ SImode. */ -+#define Pmode SImode -+ -+/* Normal alignment required for function parameters on the stack, in -+ bits. */ -+#define PARM_BOUNDARY 32 -+ -+/* We need to maintain the stack on a 32-bit boundary. */ -+#define STACK_BOUNDARY 32 -+ -+/* Alignment required for a function entry point, in bits. */ -+#define FUNCTION_BOUNDARY 32 -+ -+/* Alias for the machine mode used for memory references to functions being -+ called, in `call' RTL expressions. We use byte-oriented addresses -+ here. */ -+#define FUNCTION_MODE QImode -+ -+/* Biggest alignment that any data type can require on this machine, -+ in bits. */ -+#define BIGGEST_ALIGNMENT 32 -+ -+/* this default to BIGGEST_ALIGNMENT unless defined */ -+/* ART: What's the correct value here? Default is (((unsigned int)1<<28)*8)*/ -+#undef MAX_OFILE_ALIGNMENT -+#define MAX_OFILE_ALIGNMENT (128 * 8) -+ -+/* Alignment in bits to be given to a structure bit field that follows an empty -+ field such as `int : 0;'. */ -+#define EMPTY_FIELD_BOUNDARY 32 -+ -+/* All structures must be a multiple of 32 bits in size. */ -+#define STRUCTURE_SIZE_BOUNDARY 32 -+ -+/* A bit-field declared as `int' forces `int' alignment for the struct. */ -+#define PCC_BITFIELD_TYPE_MATTERS 1 -+ -+/* For Ubicom32 we absolutely require that data be aligned with nominal -+ alignment. */ -+#define STRICT_ALIGNMENT 1 -+ -+/* Make strcpy of constants fast. */ -+#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ -+ (TREE_CODE (EXP) == STRING_CST \ -+ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) -+ -+/* Define this macro as an expression for the alignment of a structure -+ (given by STRUCT as a tree node) if the alignment computed in the -+ usual way is COMPUTED and the alignment explicitly specified was -+ SPECIFIED. */ -+#define DATA_ALIGNMENT(TYPE, ALIGN) \ -+ ((((ALIGN) < BITS_PER_WORD) \ -+ && (TREE_CODE (TYPE) == ARRAY_TYPE \ -+ || TREE_CODE (TYPE) == UNION_TYPE \ -+ || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN)) -+ -+#define LOCAL_ALIGNMENT(TYPE,ALIGN) DATA_ALIGNMENT(TYPE,ALIGN) -+ -+/* For Ubicom32 we default to unsigned chars. */ -+#define DEFAULT_SIGNED_CHAR 0 -+ -+/* Machine-specific data register numbers. */ -+#define FIRST_DATA_REGNUM 0 -+#define D10_REGNUM 10 -+#define D11_REGNUM 11 -+#define D12_REGNUM 12 -+#define D13_REGNUM 13 -+#define LAST_DATA_REGNUM 15 -+ -+/* Machine-specific address register numbers. */ -+#define FIRST_ADDRESS_REGNUM 16 -+#define LAST_ADDRESS_REGNUM 22 -+ -+/* Register numbers used for passing a function's static chain pointer. If -+ register windows are used, the register number as seen by the called -+ function is `STATIC_CHAIN_INCOMING_REGNUM', while the register number as -+ seen by the calling function is `STATIC_CHAIN_REGNUM'. If these registers -+ are the same, `STATIC_CHAIN_INCOMING_REGNUM' need not be defined. -+ -+ The static chain register need not be a fixed register. -+ -+ If the static chain is passed in memory, these macros should not be defined; -+ instead, the next two macros should be defined. */ -+#define STATIC_CHAIN_REGNUM (FIRST_ADDRESS_REGNUM + 1) -+ -+/* The register number of the frame pointer register, which is used to access -+ automatic variables in the stack frame. We generally eliminate this anyway -+ for Ubicom32 but we make it A6 by default. */ -+#define FRAME_POINTER_REGNUM (LAST_ADDRESS_REGNUM) -+ -+/* The register number of the stack pointer register, which is also be a -+ fixed register according to `FIXED_REGISTERS'. For Ubicom32 we don't -+ have a hardware requirement about which register this is, but by convention -+ we use A7. */ -+#define STACK_POINTER_REGNUM (LAST_ADDRESS_REGNUM + 1) -+ -+/* Machine-specific accumulator register numbers. */ -+#define ACC0_HI_REGNUM 24 -+#define ACC0_LO_REGNUM 25 -+#define ACC1_HI_REGNUM 26 -+#define ACC1_LO_REGNUM 27 -+ -+/* source3 register number */ -+#define SOURCE3_REGNUM 28 -+ -+/* The register number of the arg pointer register, which is used to access the -+ function's argument list. On some machines, this is the same as the frame -+ pointer register. On some machines, the hardware determines which register -+ this is. On other machines, you can choose any register you wish for this -+ purpose. If this is not the same register as the frame pointer register, -+ then you must mark it as a fixed register according to `FIXED_REGISTERS', or -+ arrange to be able to eliminate it. */ -+#define ARG_POINTER_REGNUM 29 -+ -+/* Pseudo-reg for condition code. */ -+#define CC_REGNUM 30 -+ -+/* Interrupt set/clear registers. */ -+#define INT_SET0_REGNUM 31 -+#define INT_SET1_REGNUM 32 -+#define INT_CLR0_REGNUM 33 -+#define INT_CLR1_REGNUM 34 -+ -+/* Scratchpad registers. */ -+#define SCRATCHPAD0_REGNUM 35 -+#define SCRATCHPAD1_REGNUM 36 -+#define SCRATCHPAD2_REGNUM 37 -+#define SCRATCHPAD3_REGNUM 38 -+ -+/* FDPIC register. */ -+#define FDPIC_REGNUM 16 -+ -+/* Number of hardware registers known to the compiler. They receive numbers 0 -+ through `FIRST_PSEUDO_REGISTER-1'; thus, the first pseudo register's number -+ really is assigned the number `FIRST_PSEUDO_REGISTER'. */ -+#define FIRST_PSEUDO_REGISTER 39 -+ -+/* An initializer that says which registers are used for fixed purposes all -+ throughout the compiled code and are therefore not available for general -+ allocation. These would include the stack pointer, the frame pointer -+ (except on machines where that can be used as a general register when no -+ frame pointer is needed), the program counter on machines where that is -+ considered one of the addressable registers, and any other numbered register -+ with a standard use. -+ -+ This information is expressed as a sequence of numbers, separated by commas -+ and surrounded by braces. The Nth number is 1 if register N is fixed, 0 -+ otherwise. -+ -+ The table initialized from this macro, and the table initialized by the -+ following one, may be overridden at run time either automatically, by the -+ actions of the macro `CONDITIONAL_REGISTER_USAGE', or by the user with the -+ command options `-ffixed-REG', `-fcall-used-REG' and `-fcall-saved-REG'. */ -+#define FIXED_REGISTERS \ -+ { \ -+ 0, 0, 0, 0, 0, 0, 0, 0, /* d0 - d7 */ \ -+ 0, 0, 0, 0, 0, 0, 0, 1, /* d8 - d15 */ \ -+ 0, 0, 0, 0, 0, 0, 0, 1, /* a0 - a7 */ \ -+ 0, 0, /* acc0 hi/lo */ \ -+ 0, 0, /* acc1 hi/lo */ \ -+ 0, /* source3 */ \ -+ 1, /* arg */ \ -+ 1, /* cc */ \ -+ 1, 1, /* int_set[01] */ \ -+ 1, 1, /* int_clr[01] */ \ -+ 1, 1, 1, 1 /* scratchpad[0123] */ \ -+ } -+ -+/* Like `FIXED_REGISTERS' but has 1 for each register that is clobbered (in -+ general) by function calls as well as for fixed registers. This macro -+ therefore identifies the registers that are not available for general -+ allocation of values that must live across function calls. -+ -+ If a register has 0 in `CALL_USED_REGISTERS', the compiler automatically -+ saves it on function entry and restores it on function exit, if the register -+ is used within the function. */ -+#define CALL_USED_REGISTERS \ -+ { \ -+ 1, 1, 1, 1, 1, 1, 1, 1, /* d0 - d7 */ \ -+ 1, 1, 0, 0, 0, 0, 1, 1, /* d8 - d15 */ \ -+ 1, 0, 0, 1, 1, 1, 0, 1, /* a0 - a7 */ \ -+ 1, 1, /* acc0 hi/lo */ \ -+ 1, 1, /* acc1 hi/lo */ \ -+ 1, /* source3 */ \ -+ 1, /* arg */ \ -+ 1, /* cc */ \ -+ 1, 1, /* int_set[01] */ \ -+ 1, 1, /* int_clr[01] */ \ -+ 1, 1, 1, 1 /* scratchpad[0123] */ \ -+ } -+ -+/* How to refer to registers in assembler output. -+ This sequence is indexed by compiler's hard-register-number (see above). */ -+ -+/* A C initializer containing the assembler's names for the machine registers, -+ each one as a C string constant. This is what translates register numbers -+ in the compiler into assembler language. */ -+#define REGISTER_NAMES \ -+ { \ -+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \ -+ "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", \ -+ "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp", \ -+ "acc0_hi", "acc0_lo", \ -+ "acc1_hi", "acc1_lo", \ -+ "source3", \ -+ "arg", \ -+ "cc", \ -+ "int_set0", "int_set1", \ -+ "int_clr0", "int_clr1", \ -+ "scratchpad0", "scratchpad1", "scratchpad2", "scratchpad3" \ -+ } -+ -+#define CONDITIONAL_REGISTER_USAGE \ -+ ubicom32_conditional_register_usage (); -+ -+/* Order of allocation of registers. */ -+ -+/* If defined, an initializer for a vector of integers, containing the numbers -+ of hard registers in the order in which GNU CC should prefer to use them -+ (from most preferred to least). -+ -+ For Ubicom32 we try using caller-clobbered data registers first, then -+ callee-saved data registers, then caller-clobbered address registers, -+ then callee-saved address registers and finally everything else. -+ -+ The caller-clobbered registers are usually slightly cheaper to use because -+ there's no need to save/restore. */ -+#define REG_ALLOC_ORDER \ -+ { \ -+ 0, 1, 2, 3, 4, /* d0 - d4 */ \ -+ 5, 6, 7, 8, 9, /* d5 - d9 */ \ -+ 14, /* d14 */ \ -+ 10, 11, 12, 13, /* d10 - d13 */ \ -+ 19, 20, 16, 21, /* a3, a4, a0, a5 */ \ -+ 17, 18, 22, /* a1, a2, a6 */ \ -+ 24, 25, /* acc0 hi/lo */ \ -+ 26, 27, /* acc0 hi/lo */ \ -+ 28 /* source3 */ \ -+ } -+ -+/* C expression for the number of consecutive hard registers, starting at -+ register number REGNO, required to hold a value of mode MODE. */ -+#define HARD_REGNO_NREGS(REGNO, MODE) \ -+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) -+ -+/* Most registers can hold QImode, HImode and SImode values but we have to -+ be able to indicate any hard registers that cannot hold values with some -+ modes. */ -+#define HARD_REGNO_MODE_OK(REGNO, MODE) \ -+ ubicom32_hard_regno_mode_ok(REGNO, MODE) -+ -+/* We can rename most registers aside from the FDPIC register if we're using -+ FDPIC. */ -+#define HARD_REGNO_RENAME_OK(from, to) (TARGET_FDPIC ? ((to) != FDPIC_REGNUM) : 1) -+ -+/* A C expression that is nonzero if it is desirable to choose register -+ allocation so as to avoid move instructions between a value of mode MODE1 -+ and a value of mode MODE2. -+ -+ If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, MODE2)' are -+ ever different for any R, then `MODES_TIEABLE_P (MODE1, MODE2)' must be -+ zero. */ -+#define MODES_TIEABLE_P(MODE1, MODE2) 1 -+ -+/* An enumeral type that must be defined with all the register class names as -+ enumeral values. `NO_REGS' must be first. `ALL_REGS' must be the last -+ register class, followed by one more enumeral value, `LIM_REG_CLASSES', -+ which is not a register class but rather tells how many classes there are. -+ -+ Each register class has a number, which is the value of casting the class -+ name to type `int'. The number serves as an index in many of the tables -+ described below. */ -+ -+enum reg_class -+{ -+ NO_REGS, -+ DATA_REGS, -+ FDPIC_REG, -+ ADDRESS_REGS, -+ ALL_ADDRESS_REGS, -+ ACC_LO_REGS, -+ ACC_REGS, -+ CC_REG, -+ DATA_ACC_REGS, -+ SOURCE3_REG, -+ SPECIAL_REGS, -+ GENERAL_REGS, -+ ALL_REGS, -+ LIM_REG_CLASSES -+}; -+ -+/* The number of distinct register classes. */ -+#define N_REG_CLASSES (int) LIM_REG_CLASSES -+ -+/* An initializer containing the names of the register classes as C string -+ constants. These names are used in writing some of the debugging dumps. */ -+ -+#define REG_CLASS_NAMES \ -+{ \ -+ "NO_REGS", \ -+ "DATA_REGS", \ -+ "FDPIC_REG", \ -+ "ADDRESS_REGS", \ -+ "ALL_ADDRESS_REGS", \ -+ "ACC_LO_REGS", \ -+ "ACC_REGS", \ -+ "CC_REG", \ -+ "DATA_ACC_REGS", \ -+ "SOURCE3_REG", \ -+ "SPECIAL_REGS", \ -+ "GENERAL_REGS", \ -+ "ALL_REGS", \ -+ "LIM_REGS" \ -+} -+ -+/* An initializer containing the contents of the register classes, as integers -+ which are bit masks. The Nth integer specifies the contents of class N. -+ The way the integer MASK is interpreted is that register R is in the class -+ if `MASK & (1 << R)' is 1. -+ -+ When the machine has more than 32 registers, an integer does not suffice. -+ Then the integers are replaced by sub-initializers, braced groupings -+ containing several integers. Each sub-initializer must be suitable as an -+ initializer for the type `HARD_REG_SET' which is defined in -+ `hard-reg-set.h'. */ -+#define REG_CLASS_CONTENTS \ -+{ \ -+ {0x00000000, 0x00000000}, /* No regs */ \ -+ {0x0000ffff, 0x00000000}, /* DATA_REGS */ \ -+ {0x00010000, 0x00000000}, /* FDPIC_REG */ \ -+ {0x20fe0000, 0x00000000}, /* ADDRESS_REGS */ \ -+ {0x20ff0000, 0x00000000}, /* ALL_ADDRESS_REGS */ \ -+ {0x0a000000, 0x00000000}, /* ACC_LO_REGS */ \ -+ {0x0f000000, 0x00000000}, /* ACC_REGS */ \ -+ {0x40000000, 0x00000000}, /* CC_REG */ \ -+ {0x0f00ffff, 0x00000000}, /* DATA_ACC_REGS */ \ -+ {0x10000000, 0x00000000}, /* SOURGE3_REG */ \ -+ {0x80000000, 0x0000007f}, /* SPECIAL_REGS */ \ -+ {0xbfffffff, 0x0000007f}, /* GENERAL_REGS */ \ -+ {0xbfffffff, 0x0000007f} /* ALL_REGS */ \ -+} -+ -+extern enum reg_class const ubicom32_regclass_map[FIRST_PSEUDO_REGISTER]; -+ -+/* A C expression whose value is a register class containing hard register -+ REGNO. In general there is more than one such class; choose a class which -+ is "minimal", meaning that no smaller class also contains the register. */ -+#define REGNO_REG_CLASS(REGNO) (ubicom32_regclass_map[REGNO]) -+ -+#define IRA_COVER_CLASSES \ -+{ \ -+ GENERAL_REGS, \ -+ LIM_REG_CLASSES \ -+} -+ -+/* Ubicom32 base registers must be address registers since addresses can -+ only be reached via address registers. */ -+#define BASE_REG_CLASS ALL_ADDRESS_REGS -+ -+/* Ubicom32 index registers must be data registers since we cannot add -+ two address registers together to form an address. */ -+#define INDEX_REG_CLASS DATA_REGS -+ -+/* A C expression which is nonzero if register number NUM is suitable for use -+ as a base register in operand addresses. It may be either a suitable hard -+ register or a pseudo register that has been allocated such a hard register. */ -+ -+#ifndef REG_OK_STRICT -+#define REGNO_OK_FOR_BASE_P(regno) \ -+ ubicom32_regno_ok_for_base_p (regno, 0) -+#else -+#define REGNO_OK_FOR_BASE_P(regno) \ -+ ubicom32_regno_ok_for_base_p (regno, 1) -+#endif -+ -+/* A C expression which is nonzero if register number NUM is suitable for use -+ as an index register in operand addresses. It may be either a suitable hard -+ register or a pseudo register that has been allocated such a hard register. -+ -+ The difference between an index register and a base register is that the -+ index register may be scaled. If an address involves the sum of two -+ registers, neither one of them scaled, then either one may be labeled the -+ "base" and the other the "index"; but whichever labeling is used must fit -+ the machine's constraints of which registers may serve in each capacity. -+ The compiler will try both labelings, looking for one that is valid, and -+ will reload one or both registers only if neither labeling works. */ -+#ifndef REG_OK_STRICT -+#define REGNO_OK_FOR_INDEX_P(regno) \ -+ ubicom32_regno_ok_for_index_p (regno, 0) -+#else -+#define REGNO_OK_FOR_INDEX_P(regno) \ -+ ubicom32_regno_ok_for_index_p (regno, 1) -+#endif -+ -+/* Attempt to restrict the register class we need to copy value X intoto the -+ would-be register class CLASS. Most things are fine for Ubicom32 but we -+ have to restrict certain types of address loads. */ -+#define PREFERRED_RELOAD_CLASS(X, CLASS) \ -+ ubicom32_preferred_reload_class (X, CLASS) -+ -+/* A C expression for the maximum number of consecutive registers of -+ class CLASS needed to hold a value of mode MODE. For Ubicom32 this -+ is pretty much identical to HARD_REGNO_NREGS. */ -+#define CLASS_MAX_NREGS(CLASS, MODE) \ -+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) -+ -+/* For Ubicom32 the stack grows downwards when we push a word onto the stack -+ - i.e. it moves to a smaller address. */ -+#define STACK_GROWS_DOWNWARD 1 -+ -+/* Offset from the frame pointer to the first local variable slot to -+ be allocated. */ -+#define STARTING_FRAME_OFFSET 0 -+ -+/* Offset from the argument pointer register to the first argument's -+ address. */ -+#define FIRST_PARM_OFFSET(FNDECL) 0 -+ -+/* A C expression whose value is RTL representing the value of the return -+ address for the frame COUNT steps up from the current frame, after the -+ prologue. FRAMEADDR is the frame pointer of the COUNT frame, or the frame -+ pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is -+ defined. -+ -+ The value of the expression must always be the correct address when COUNT is -+ zero, but may be `NULL_RTX' if there is not way to determine the return -+ address of other frames. */ -+#define RETURN_ADDR_RTX(COUNT, FRAME) \ -+ ubicom32_return_addr_rtx (COUNT, FRAME) -+ -+/* Register That Address the Stack Frame. */ -+ -+/* We don't actually require a frame pointer in most functions with the -+ Ubicom32 architecture so we allow it to be eliminated. */ -+#define FRAME_POINTER_REQUIRED 0 -+ -+/* Macro that defines a table of register pairs used to eliminate unecessary -+ registers that point into the stack frame. -+ -+ For Ubicom32 we don't generally need an arg pointer of a frame pointer -+ so we allow the arg pointer to be replaced by either the frame pointer or -+ the stack pointer. We also allow the frame pointer to be replaced by -+ the stack pointer. */ -+#define ELIMINABLE_REGS \ -+{ \ -+ {ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ -+ {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ -+ {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM} \ -+} -+ -+/* Let the compiler know that we want to use the ELIMINABLE_REGS macro -+ above. */ -+#define CAN_ELIMINATE(FROM, TO) 1 -+ -+/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It specifies the -+ initial difference between the specified pair of registers. This macro must -+ be defined if `ELIMINABLE_REGS' is defined. */ -+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ -+ (OFFSET) = ubicom32_initial_elimination_offset (FROM, TO) -+ -+/* If defined, the maximum amount of space required for outgoing arguments will -+ be computed and placed into the variable -+ `current_function_outgoing_args_size'. No space will be pushed onto the -+ stack for each call; instead, the function prologue should increase the -+ stack frame size by this amount. -+ -+ Defining both `PUSH_ROUNDING' and `ACCUMULATE_OUTGOING_ARGS' is not -+ proper. */ -+#define ACCUMULATE_OUTGOING_ARGS 1 -+ -+/* Define this macro if functions should assume that stack space has been -+ allocated for arguments even when their values are passed in registers. -+ -+ The value of this macro is the size, in bytes, of the area reserved for -+ arguments passed in registers for the function represented by FNDECL. -+ -+ This space can be allocated by the caller, or be a part of the -+ machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' says -+ which. */ -+#define REG_PARM_STACK_SPACE(FNDECL) ubicom32_reg_parm_stack_space(FNDECL) -+ -+/* A C expression that should indicate the number of bytes of its own arguments -+ that a function pops on returning, or 0 if the function pops no arguments -+ and the caller must therefore pop them all after the function returns. -+ -+ FUNDECL is a C variable whose value is a tree node that describes the -+ function in question. Normally it is a node of type `FUNCTION_DECL' that -+ describes the declaration of the function. From this it is possible to -+ obtain the DECL_MACHINE_ATTRIBUTES of the function. -+ -+ FUNTYPE is a C variable whose value is a tree node that describes the -+ function in question. Normally it is a node of type `FUNCTION_TYPE' that -+ describes the data type of the function. From this it is possible to obtain -+ the data types of the value and arguments (if known). -+ -+ When a call to a library function is being considered, FUNTYPE will contain -+ an identifier node for the library function. Thus, if you need to -+ distinguish among various library functions, you can do so by their names. -+ Note that "library function" in this context means a function used to -+ perform arithmetic, whose name is known specially in the compiler and was -+ not mentioned in the C code being compiled. -+ -+ STACK-SIZE is the number of bytes of arguments passed on the stack. If a -+ variable number of bytes is passed, it is zero, and argument popping will -+ always be the responsibility of the calling function. -+ -+ On the Vax, all functions always pop their arguments, so the definition of -+ this macro is STACK-SIZE. On the 68000, using the standard calling -+ convention, no functions pop their arguments, so the value of the macro is -+ always 0 in this case. But an alternative calling convention is available -+ in which functions that take a fixed number of arguments pop them but other -+ functions (such as `printf') pop nothing (the caller pops all). When this -+ convention is in use, FUNTYPE is examined to determine whether a function -+ takes a fixed number of arguments. */ -+#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0 -+ -+/* A C expression that controls whether a function argument is passed in a -+ register, and which register. -+ -+ The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes (in a way -+ defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE) all of the previous -+ arguments so far passed in registers; MODE, the machine mode of the argument; -+ TYPE, the data type of the argument as a tree node or 0 if that is not known -+ (which happens for C support library functions); and NAMED, which is 1 for an -+ ordinary argument and 0 for nameless arguments that correspond to `...' in the -+ called function's prototype. -+ -+ The value of the expression should either be a `reg' RTX for the hard -+ register in which to pass the argument, or zero to pass the argument on the -+ stack. -+ -+ For machines like the Vax and 68000, where normally all arguments are -+ pushed, zero suffices as a definition. -+ -+ The usual way to make the ANSI library `stdarg.h' work on a machine where -+ some arguments are usually passed in registers, is to cause nameless -+ arguments to be passed on the stack instead. This is done by making -+ `FUNCTION_ARG' return 0 whenever NAMED is 0. -+ -+ You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of -+ this macro to determine if this argument is of a type that must be passed in -+ the stack. If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG' -+ returns non-zero for such an argument, the compiler will abort. If -+ `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the -+ stack and then loaded into a register. */ -+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ -+ function_arg (&CUM, MODE, TYPE, NAMED) -+ -+#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \ -+ function_incoming_arg (&CUM, MODE, TYPE, NAMED) -+ -+/* A C expression for the number of words, at the beginning of an argument, -+ must be put in registers. The value must be zero for arguments that are -+ passed entirely in registers or that are entirely pushed on the stack. -+ -+ On some machines, certain arguments must be passed partially in registers -+ and partially in memory. On these machines, typically the first N words of -+ arguments are passed in registers, and the rest on the stack. If a -+ multi-word argument (a `double' or a structure) crosses that boundary, its -+ first few words must be passed in registers and the rest must be pushed. -+ This macro tells the compiler when this occurs, and how many of the words -+ should go in registers. -+ -+ `FUNCTION_ARG' for these arguments should return the first register to be -+ used by the caller for this argument; likewise `FUNCTION_INCOMING_ARG', for -+ the called function. */ -+ -+/* A C expression that indicates when an argument must be passed by reference. -+ If nonzero for an argument, a copy of that argument is made in memory and a -+ pointer to the argument is passed instead of the argument itself. The -+ pointer is passed in whatever way is appropriate for passing a pointer to -+ that type. -+ -+ On machines where `REG_PARM_STACK_SPACE' is not defined, a suitable -+ definition of this macro might be -+ #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ -+ MUST_PASS_IN_STACK (MODE, TYPE) */ -+ -+/* If defined, a C expression that indicates when it is the called function's -+ responsibility to make a copy of arguments passed by invisible reference. -+ Normally, the caller makes a copy and passes the address of the copy to the -+ routine being called. When FUNCTION_ARG_CALLEE_COPIES is defined and is -+ nonzero, the caller does not make a copy. Instead, it passes a pointer to -+ the "live" value. The called function must not modify this value. If it -+ can be determined that the value won't be modified, it need not make a copy; -+ otherwise a copy must be made. */ -+ -+/* A C type for declaring a variable that is used as the first argument of -+ `FUNCTION_ARG' and other related values. For some target machines, the type -+ `int' suffices and can hold the number of bytes of argument so far. -+ -+ There is no need to record in `CUMULATIVE_ARGS' anything about the arguments -+ that have been passed on the stack. The compiler has other variables to -+ keep track of that. For target machines on which all arguments are passed -+ on the stack, there is no need to store anything in `CUMULATIVE_ARGS'; -+ however, the data structure must exist and should not be empty, so use -+ `int'. */ -+struct cum_arg -+{ -+ int nbytes; -+ int reg; -+ int stdarg; -+}; -+#define CUMULATIVE_ARGS struct cum_arg -+ -+/* A C statement (sans semicolon) for initializing the variable CUM for the -+ state at the beginning of the argument list. The variable has type -+ `CUMULATIVE_ARGS'. The value of FNTYPE is the tree node for the data type -+ of the function which will receive the args, or 0 if the args are to a -+ compiler support library function. The value of INDIRECT is nonzero when -+ processing an indirect call, for example a call through a function pointer. -+ The value of INDIRECT is zero for a call to an explicitly named function, a -+ library function call, or when `INIT_CUMULATIVE_ARGS' is used to find -+ arguments for the function being compiled. -+ -+ When processing a call to a compiler support library function, LIBNAME -+ identifies which one. It is a `symbol_ref' rtx which contains the name of -+ the function, as a string. LIBNAME is 0 when an ordinary C function call is -+ being processed. Thus, each time this macro is called, either LIBNAME or -+ FNTYPE is nonzero, but never both of them at once. */ -+ -+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT, NAMED_ARGS) \ -+ init_cumulative_args (&(CUM), FNTYPE, LIBNAME, INDIRECT); -+ -+/* A C statement (sans semicolon) to update the summarizer variable CUM to -+ advance past an argument in the argument list. The values MODE, TYPE and -+ NAMED describe that argument. Once this is done, the variable CUM is -+ suitable for analyzing the *following* argument with `FUNCTION_ARG', etc. -+ -+ This macro need not do anything if the argument in question was passed on -+ the stack. The compiler knows how to track the amount of stack space used -+ for arguments without any special help. */ -+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ -+ ((CUM).nbytes += ((MODE) != BLKmode \ -+ ? (GET_MODE_SIZE (MODE) + 3) & ~3 \ -+ : (int_size_in_bytes (TYPE) + 3) & ~3)) -+ -+/* For the Ubicom32 we define the upper function argument register here. */ -+#define UBICOM32_FUNCTION_ARG_REGS 10 -+ -+/* A C expression that is nonzero if REGNO is the number of a hard register in -+ which function arguments are sometimes passed. This does *not* include -+ implicit arguments such as the static chain and the structure-value address. -+ On many machines, no registers can be used for this purpose since all -+ function arguments are pushed on the stack. */ -+#define FUNCTION_ARG_REGNO_P(N) ((N) < UBICOM32_FUNCTION_ARG_REGS) -+ -+ -+/* How Scalar Function Values are Returned. */ -+ -+/* The number of the hard register that is used to return a scalar value from a -+ function call. */ -+#define RETURN_VALUE_REGNUM 0 -+ -+/* A C expression to create an RTX representing the place where a function -+ returns a value of data type VALTYPE. VALTYPE is a tree node representing a -+ data type. Write `TYPE_MODE (VALTYPE)' to get the machine mode used to -+ represent that type. On many machines, only the mode is relevant. -+ (Actually, on most machines, scalar values are returned in the same place -+ regardless of mode). -+ -+ If `PROMOTE_FUNCTION_RETURN' is defined, you must apply the same promotion -+ rules specified in `PROMOTE_MODE' if VALTYPE is a scalar type. -+ -+ If the precise function being called is known, FUNC is a tree node -+ (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer. This makes it -+ possible to use a different value-returning convention for specific -+ functions when all their calls are known. -+ -+ `FUNCTION_VALUE' is not used for return vales with aggregate data types, -+ because these are returned in another way. See `STRUCT_VALUE_REGNUM' and -+ related macros, below. */ -+#define FUNCTION_VALUE(VALTYPE, FUNC) \ -+ gen_rtx_REG (TYPE_MODE (VALTYPE), FIRST_DATA_REGNUM) -+ -+/* A C expression to create an RTX representing the place where a library -+ function returns a value of mode MODE. -+ -+ Note that "library function" in this context means a compiler support -+ routine, used to perform arithmetic, whose name is known specially by the -+ compiler and was not mentioned in the C code being compiled. -+ -+ The definition of `LIBRARY_VALUE' need not be concerned aggregate data -+ types, because none of the library functions returns such types. */ -+#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, FIRST_DATA_REGNUM) -+ -+/* A C expression that is nonzero if REGNO is the number of a hard register in -+ which the values of called function may come back. -+ -+ A register whose use for returning values is limited to serving as the -+ second of a pair (for a value of type `double', say) need not be recognized -+ by this macro. So for most machines, this definition suffices: -+ -+ #define FUNCTION_VALUE_REGNO_P(N) ((N) == RETURN) -+ -+ If the machine has register windows, so that the caller and the called -+ function use different registers for the return value, this macro should -+ recognize only the caller's register numbers. */ -+#define FUNCTION_VALUE_REGNO_P(N) ((N) == FIRST_DATA_REGNUM) -+ -+ -+/* How Large Values are Returned. */ -+ -+/* A C expression which can inhibit the returning of certain function values in -+ registers, based on the type of value. A nonzero value says to return the -+ function value in memory, just as large structures are always returned. -+ Here TYPE will be a C expression of type `tree', representing the data type -+ of the value. -+ -+ Note that values of mode `BLKmode' must be explicitly handled by this macro. -+ Also, the option `-fpcc-struct-return' takes effect regardless of this -+ macro. On most systems, it is possible to leave the macro undefined; this -+ causes a default definition to be used, whose value is the constant 1 for -+ `BLKmode' values, and 0 otherwise. -+ -+ Do not use this macro to indicate that structures and unions should always -+ be returned in memory. You should instead use `DEFAULT_PCC_STRUCT_RETURN' -+ to indicate this. */ -+#define RETURN_IN_MEMORY(TYPE) \ -+ (int_size_in_bytes (TYPE) > 8 || TYPE_MODE (TYPE) == BLKmode) -+ -+/* Define this macro to be 1 if all structure and union return values must be -+ in memory. Since this results in slower code, this should be defined only -+ if needed for compatibility with other compilers or with an ABI. If you -+ define this macro to be 0, then the conventions used for structure and union -+ return values are decided by the `RETURN_IN_MEMORY' macro. -+ -+ If not defined, this defaults to the value 1. */ -+#define DEFAULT_PCC_STRUCT_RETURN 0 -+ -+/* If the structure value address is not passed in a register, define -+ `STRUCT_VALUE' as an expression returning an RTX for the place -+ where the address is passed. If it returns 0, the address is -+ passed as an "invisible" first argument. */ -+#define STRUCT_VALUE 0 -+ -+/* Define this macro as a C expression that is nonzero if the return -+ instruction or the function epilogue ignores the value of the stack pointer; -+ in other words, if it is safe to delete an instruction to adjust the stack -+ pointer before a return from the function. -+ -+ Note that this macro's value is relevant only for functions for which frame -+ pointers are maintained. It is never safe to delete a final stack -+ adjustment in a function that has no frame pointer, and the compiler knows -+ this regardless of `EXIT_IGNORE_STACK'. */ -+#define EXIT_IGNORE_STACK 1 -+ -+/* A C statement or compound statement to output to FILE some assembler code to -+ call the profiling subroutine `mcount'. Before calling, the assembler code -+ must load the address of a counter variable into a register where `mcount' -+ expects to find the address. The name of this variable is `LP' followed by -+ the number LABELNO, so you would generate the name using `LP%d' in a -+ `fprintf'. -+ -+ The details of how the address should be passed to `mcount' are determined -+ by your operating system environment, not by GNU CC. To figure them out, -+ compile a small program for profiling using the system's installed C -+ compiler and look at the assembler code that results. -+ -+ This declaration must be present, but it can be an abort if profiling is -+ not implemented. */ -+ -+#define FUNCTION_PROFILER(file, labelno) ubicom32_profiler(file, labelno) -+ -+/* A C statement to output, on the stream FILE, assembler code for a block of -+ data that contains the constant parts of a trampoline. This code should not -+ include a label--the label is taken care of automatically. */ -+#if 0 -+#define TRAMPOLINE_TEMPLATE(FILE) \ -+ do { \ -+ fprintf (FILE, "\tadd -4,sp\n"); \ -+ fprintf (FILE, "\t.long 0x0004fffa\n"); \ -+ fprintf (FILE, "\tmov (0,sp),a0\n"); \ -+ fprintf (FILE, "\tadd 4,sp\n"); \ -+ fprintf (FILE, "\tmov (13,a0),a1\n"); \ -+ fprintf (FILE, "\tmov (17,a0),a0\n"); \ -+ fprintf (FILE, "\tjmp (a0)\n"); \ -+ fprintf (FILE, "\t.long 0\n"); \ -+ fprintf (FILE, "\t.long 0\n"); \ -+ } while (0) -+#endif -+ -+/* A C expression for the size in bytes of the trampoline, as an integer. */ -+#define TRAMPOLINE_SIZE 0x1b -+ -+/* Alignment required for trampolines, in bits. -+ -+ If you don't define this macro, the value of `BIGGEST_ALIGNMENT' is used for -+ aligning trampolines. */ -+#define TRAMPOLINE_ALIGNMENT 32 -+ -+/* A C statement to initialize the variable parts of a trampoline. ADDR is an -+ RTX for the address of the trampoline; FNADDR is an RTX for the address of -+ the nested function; STATIC_CHAIN is an RTX for the static chain value that -+ should be passed to the function when it is called. */ -+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -+{ \ -+ emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 0x14)), \ -+ (CXT)); \ -+ emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 0x18)), \ -+ (FNADDR)); \ -+} -+ -+/* Ubicom32 supports pre and post increment/decrement addressing. */ -+#define HAVE_POST_INCREMENT 1 -+#define HAVE_PRE_INCREMENT 1 -+#define HAVE_POST_DECREMENT 1 -+#define HAVE_PRE_DECREMENT 1 -+ -+/* Ubicom32 supports pre and post address side-effects with constants -+ other than the size of the memory operand. */ -+#define HAVE_PRE_MODIFY_DISP 1 -+#define HAVE_POST_MODIFY_DISP 1 -+ -+/* A C expression that is 1 if the RTX X is a constant which is a valid -+ address. On most machines, this can be defined as `CONSTANT_P (X)', -+ but a few machines are more restrictive in which constant addresses -+ are supported. -+ -+ `CONSTANT_P' accepts integer-values expressions whose values are not -+ explicitly known, such as `symbol_ref', `label_ref', and `high' -+ expressions and `const' arithmetic expressions, in addition to -+ `const_int' and `const_double' expressions. */ -+#define CONSTANT_ADDRESS_P(X) \ -+ (GET_CODE (X) == LABEL_REF \ -+ || (GET_CODE (X) == CONST \ -+ && GET_CODE (XEXP (X, 0)) == PLUS \ -+ && GET_CODE (XEXP (XEXP (X, 0), 0)) == LABEL_REF)) -+ -+/* Ubicom32 supports a maximum of 2 registers in a valid memory address. -+ One is always an address register while a second, optional, one may be a -+ data register. */ -+#define MAX_REGS_PER_ADDRESS 2 -+ -+/* A C compound statement with a conditional `goto LABEL;' executed if X (an -+ RTX) is a legitimate memory address on the target machine for a memory -+ operand of mode MODE. -+ -+ It usually pays to define several simpler macros to serve as subroutines for -+ this one. Otherwise it may be too complicated to understand. -+ -+ This macro must exist in two variants: a strict variant and a non-strict -+ one. The strict variant is used in the reload pass. It must be defined so -+ that any pseudo-register that has not been allocated a hard register is -+ considered a memory reference. In contexts where some kind of register is -+ required, a pseudo-register with no hard register must be rejected. -+ -+ The non-strict variant is used in other passes. It must be defined to -+ accept all pseudo-registers in every context where some kind of register is -+ required. -+ -+ Compiler source files that want to use the strict variant of this macro -+ define the macro `REG_OK_STRICT'. You should use an `#ifdef REG_OK_STRICT' -+ conditional to define the strict variant in that case and the non-strict -+ variant otherwise. -+ -+ Subroutines to check for acceptable registers for various purposes (one for -+ base registers, one for index registers, and so on) are typically among the -+ subroutines used to define `GO_IF_LEGITIMATE_ADDRESS'. Then only these -+ subroutine macros need have two variants; the higher levels of macros may be -+ the same whether strict or not. -+ -+ Normally, constant addresses which are the sum of a `symbol_ref' and an -+ integer are stored inside a `const' RTX to mark them as constant. -+ Therefore, there is no need to recognize such sums specifically as -+ legitimate addresses. Normally you would simply recognize any `const' as -+ legitimate. -+ -+ Usually `PRINT_OPERAND_ADDRESS' is not prepared to handle constant sums that -+ are not marked with `const'. It assumes that a naked `plus' indicates -+ indexing. If so, then you *must* reject such naked constant sums as -+ illegitimate addresses, so that none of them will be given to -+ `PRINT_OPERAND_ADDRESS'. -+ -+ On some machines, whether a symbolic address is legitimate depends on the -+ section that the address refers to. On these machines, define the macro -+ `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and -+ then check for it here. When you see a `const', you will have to look -+ inside it to find the `symbol_ref' in order to determine the section. -+ -+ The best way to modify the name string is by adding text to the beginning, -+ with suitable punctuation to prevent any ambiguity. Allocate the new name -+ in `saveable_obstack'. You will have to modify `ASM_OUTPUT_LABELREF' to -+ remove and decode the added text and output the name accordingly, and define -+ `STRIP_NAME_ENCODING' to access the original name string. -+ -+ You can check the information stored here into the `symbol_ref' in the -+ definitions of the macros `GO_IF_LEGITIMATE_ADDRESS' and -+ `PRINT_OPERAND_ADDRESS'. */ -+/* On the ubicom32, the value in the address register must be -+ in the same memory space/segment as the effective address. -+ -+ This is problematical for reload since it does not understand -+ that base+index != index+base in a memory reference. */ -+ -+#ifdef REG_OK_STRICT -+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -+ if (ubicom32_legitimate_address_p (MODE, X, 1)) goto ADDR; -+#else -+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -+ if (ubicom32_legitimate_address_p (MODE, X, 0)) goto ADDR; -+#endif -+ -+/* Try machine-dependent ways of modifying an illegitimate address -+ to be legitimate. If we find one, return the new, valid address. -+ This macro is used in only one place: `memory_address' in explow.c. -+ -+ OLDX is the address as it was before break_out_memory_refs was called. -+ In some cases it is useful to look at this to decide what needs to be done. -+ -+ MODE and WIN are passed so that this macro can use -+ GO_IF_LEGITIMATE_ADDRESS. -+ -+ It is always safe for this macro to do nothing. It exists to recognize -+ opportunities to optimize the output. -+ -+ On RS/6000, first check for the sum of a register with a constant -+ integer that is out of range. If so, generate code to add the -+ constant with the low-order 16 bits masked to the register and force -+ this result into another register (this can be done with `cau'). -+ Then generate an address of REG+(CONST&0xffff), allowing for the -+ possibility of bit 16 being a one. -+ -+ Then check for the sum of a register and something not constant, try to -+ load the other things into a register and return the sum. */ -+ -+#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ -+{ \ -+ rtx result = ubicom32_legitimize_address ((X), (OLDX), (MODE)); \ -+ if (result != NULL_RTX) \ -+ { \ -+ (X) = result; \ -+ goto WIN; \ -+ } \ -+} -+ -+/* Try a machine-dependent way of reloading an illegitimate address -+ operand. If we find one, push the reload and jump to WIN. This -+ macro is used in only one place: `find_reloads_address' in reload.c. */ -+#define LEGITIMIZE_RELOAD_ADDRESS(AD, MODE, OPNUM, TYPE, IND, WIN) \ -+{ \ -+ rtx new_rtx = ubicom32_legitimize_reload_address ((AD), (MODE), (OPNUM), (int)(TYPE)); \ -+ if (new_rtx) \ -+ { \ -+ (AD) = new_rtx; \ -+ goto WIN; \ -+ } \ -+} -+ -+/* A C statement or compound statement with a conditional `goto LABEL;' -+ executed if memory address X (an RTX) can have different meanings depending -+ on the machine mode of the memory reference it is used for or if the address -+ is valid for some modes but not others. -+ -+ Autoincrement and autodecrement addresses typically have mode-dependent -+ effects because the amount of the increment or decrement is the size of the -+ operand being addressed. Some machines have other mode-dependent addresses. -+ Many RISC machines have no mode-dependent addresses. -+ -+ You may assume that ADDR is a valid address for the machine. */ -+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ -+ if (ubicom32_mode_dependent_address_p (ADDR)) \ -+ goto LABEL; -+ -+/* A C expression that is nonzero if X is a legitimate constant for an -+ immediate operand on the target machine. You can assume that X -+ satisfies `CONSTANT_P', so you need not check this. In fact, `1' is -+ a suitable definition for this macro on machines where anything -+ `CONSTANT_P' is valid. */ -+#define LEGITIMATE_CONSTANT_P(X) \ -+ ubicom32_legitimate_constant_p ((X)) -+ -+/* Moves between registers are pretty-much single instructions for -+ Ubicom32. We make this the default "2" that gcc likes. */ -+#define REGISTER_MOVE_COST(MODE, FROM, TO) 2 -+ -+/* This is a little bit of magic from the S390 port that wins 2% on code -+ size when building the Linux kernel! Unfortunately while it wins on -+ that size the user-space apps built using FD-PIC don't improve and the -+ performance is lower because we put more pressure on the caches. We may -+ want this back on some future CPU that has higher cache performance. */ -+/* #define IRA_HARD_REGNO_ADD_COST_MULTIPLIER(regno) 0.5 */ -+ -+/* Moves between registers and memory are more expensive than between -+ registers because we have caches and write buffers that slow things -+ down! */ -+#define MEMORY_MOVE_COST(MODE, CLASS, IN) 2 -+ -+/* A fall-through branch is very low cost but anything that changes the PC -+ incurs a major pipeline hazard. We don't make the full extent of this -+ hazard visible because we hope that multiple threads will absorb much -+ of the cost and so we don't want a jump being replaced with, say, 7 -+ instructions. */ -+#define BRANCH_COST(SPEED_P, PREDICTABLE_P) \ -+ ((PREDICTABLE_P) ? 1 : 3) -+ -+/* Define this macro as a C expression which is nonzero if accessing less than -+ a word of memory (i.e. a `char' or a `short') is no faster than accessing a -+ word of memory, i.e., if such access require more than one instruction or if -+ there is no difference in cost between byte and (aligned) word loads. -+ -+ When this macro is not defined, the compiler will access a field by finding -+ the smallest containing object; when it is defined, a fullword load will be -+ used if alignment permits. Unless bytes accesses are faster than word -+ accesses, using word accesses is preferable since it may eliminate -+ subsequent memory access if subsequent accesses occur to other fields in the -+ same word of the structure, but to different bytes. */ -+#define SLOW_BYTE_ACCESS 0 -+ -+/* The number of scalar move insns which should be generated instead of a -+ string move insn or a library call. Increasing the value will always make -+ code faster, but eventually incurs high cost in increased code size. -+ -+ If you don't define this, a reasonable default is used. */ -+/* According to expr.c, a value of around 6 should minimize code size. */ -+#define MOVE_RATIO(SPEED) 6 -+ -+/* We're much better off calling a constant function address with the -+ Ubicom32 architecture because we have an opcode for doing so. Don't -+ let the compiler extract function addresses as common subexpressions -+ into an address register. */ -+#define NO_FUNCTION_CSE -+ -+#define SELECT_CC_MODE(OP, X, Y) ubicom32_select_cc_mode (OP, X, Y) -+ -+#define REVERSIBLE_CC_MODE(MODE) 1 -+ -+/* Canonicalize a comparison from one we don't have to one we do have. */ -+#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \ -+ ubicom32_canonicalize_comparison (&(CODE), &(OP0), &(OP1)) -+ -+/* Dividing the output into sections. */ -+ -+/* A C expression whose value is a string containing the assembler operation -+ that should precede instructions and read-only data. Normally `".text"' is -+ right. */ -+#define TEXT_SECTION_ASM_OP "\t.section .text" -+ -+/* A C expression whose value is a string containing the assembler operation to -+ identify the following data as writable initialized data. Normally -+ `".data"' is right. */ -+#define DATA_SECTION_ASM_OP "\t.section .data" -+ -+ -+/* If defined, a C expression whose value is a string containing the -+ assembler operation to identify the following data as -+ uninitialized global data. If not defined, and neither -+ `ASM_OUTPUT_BSS' nor `ASM_OUTPUT_ALIGNED_BSS' are defined, -+ uninitialized global data will be output in the data section if -+ `-fno-common' is passed, otherwise `ASM_OUTPUT_COMMON' will be -+ used. */ -+#define BSS_SECTION_ASM_OP "\t.section .bss" -+ -+/* This is how we tell the assembler that a symbol is weak. */ -+ -+#define ASM_WEAKEN_LABEL(FILE, NAME) \ -+ do \ -+ { \ -+ fputs ("\t.weak\t", (FILE)); \ -+ assemble_name ((FILE), (NAME)); \ -+ fputc ('\n', (FILE)); \ -+ } \ -+ while (0) -+ -+/* The Overall Framework of an Assembler File. */ -+ -+#undef SET_ASM_OP -+#define SET_ASM_OP "\t.set\t" -+ -+/* A C string constant describing how to begin a comment in the target -+ assembler language. The compiler assumes that the comment will end at the -+ end of the line. */ -+#define ASM_COMMENT_START ";" -+ -+/* A C string constant for text to be output before each `asm' statement or -+ group of consecutive ones. Normally this is `"#APP"', which is a comment -+ that has no effect on most assemblers but tells the GNU assembler that it -+ must check the lines that follow for all valid assembler constructs. */ -+#define ASM_APP_ON "#APP\n" -+ -+/* A C string constant for text to be output after each `asm' statement or -+ group of consecutive ones. Normally this is `"#NO_APP"', which tells the -+ GNU assembler to resume making the time-saving assumptions that are valid -+ for ordinary compiler output. */ -+#define ASM_APP_OFF "#NO_APP\n" -+ -+/* Like `ASM_OUTPUT_BSS' except takes the required alignment as a separate, -+ explicit argument. If you define this macro, it is used in place of -+ `ASM_OUTPUT_BSS', and gives you more flexibility in handling the required -+ alignment of the variable. The alignment is specified as the number of -+ bits. -+ -+ Try to use function `asm_output_aligned_bss' defined in file `varasm.c' when -+ defining this macro. */ -+#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ -+ asm_output_aligned_bss ((FILE), (DECL), (NAME), (SIZE), (ALIGN)) -+ -+/* A C expression to assign to OUTVAR (which is a variable of type `char *') a -+ newly allocated string made from the string NAME and the number NUMBER, with -+ some suitable punctuation added. Use `alloca' to get space for the string. -+ -+ The string will be used as an argument to `ASM_OUTPUT_LABELREF' to produce -+ an assembler label for an internal static variable whose name is NAME. -+ Therefore, the string must be such as to result in valid assembler code. -+ The argument NUMBER is different each time this macro is executed; it -+ prevents conflicts between similarly-named internal static variables in -+ different scopes. -+ -+ Ideally this string should not be a valid C identifier, to prevent any -+ conflict with the user's own symbols. Most assemblers allow periods or -+ percent signs in assembler symbols; putting at least one of these between -+ the name and the number will suffice. */ -+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ -+ ((OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ -+ sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO))) -+ -+#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) \ -+ sprintf (STRING, "*.%s%ld", PREFIX, (long)(NUM)) -+/* A C statement to store into the string STRING a label whose name -+ is made from the string PREFIX and the number NUM. -+ -+ This string, when output subsequently by `assemble_name', should -+ produce the output that `(*targetm.asm_out.internal_label)' would produce -+ with the same PREFIX and NUM. -+ -+ If the string begins with `*', then `assemble_name' will output -+ the rest of the string unchanged. It is often convenient for -+ `ASM_GENERATE_INTERNAL_LABEL' to use `*' in this way. If the -+ string doesn't start with `*', then `ASM_OUTPUT_LABELREF' gets to -+ output the string, and may change it. (Of course, -+ `ASM_OUTPUT_LABELREF' is also part of your machine description, so -+ you should know what it does on your machine.) */ -+ -+/* This says how to output assembler code to declare an -+ uninitialized external linkage data object. Under SVR4, -+ the linker seems to want the alignment of data objects -+ to depend on their types. We do exactly that here. */ -+ -+#define COMMON_ASM_OP "\t.comm\t" -+ -+#undef ASM_OUTPUT_COMMON -+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ -+ do \ -+ { \ -+ fprintf ((FILE), "%s", COMMON_ASM_OP); \ -+ assemble_name ((FILE), (NAME)); \ -+ fprintf ((FILE), ", %u\n", (SIZE)); \ -+ } \ -+ while (0) -+ -+/* This says how to output assembler code to declare an -+ uninitialized internal linkage data object. Under SVR4, -+ the linker seems to want the alignment of data objects -+ to depend on their types. We do exactly that here. */ -+#define LOCAL_ASM_OP "\t.lcomm\t" -+ -+#undef ASM_OUTPUT_LOCAL -+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ -+ do \ -+ { \ -+ fprintf ((FILE), "%s", LOCAL_ASM_OP); \ -+ assemble_name ((FILE), (NAME)); \ -+ fprintf ((FILE), ", %u\n", (SIZE)); \ -+ } \ -+ while (0) -+ -+/* Globalizing directive for a label. */ -+#define GLOBAL_ASM_OP ".global\t" -+ -+/* Output the operand of an instruction. */ -+#define PRINT_OPERAND(FILE, X, CODE) \ -+ ubicom32_print_operand(FILE, X, CODE) -+ -+/* Output the address of an operand. */ -+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ -+ ubicom32_print_operand_address (FILE, ADDR) -+ -+/* A C expression to output to STREAM some assembler code which will push hard -+ register number REGNO onto the stack. The code need not be optimal, since -+ this macro is used only when profiling. */ -+#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) -+ -+/* A C expression to output to STREAM some assembler code which will pop hard -+ register number REGNO off of the stack. The code need not be optimal, since -+ this macro is used only when profiling. */ -+#define ASM_OUTPUT_REG_POP(FILE, REGNO) -+ -+/* This macro should be provided on machines where the addresses in a dispatch -+ table are relative to the table's own address. -+ -+ The definition should be a C statement to output to the stdio stream STREAM -+ an assembler pseudo-instruction to generate a difference between two labels. -+ VALUE and REL are the numbers of two internal labels. The definitions of -+ these labels are output using `ASM_OUTPUT_INTERNAL_LABEL', and they must be -+ printed in the same way here. For example, -+ -+ fprintf (STREAM, "\t.word L%d-L%d\n", VALUE, REL) */ -+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ -+ fprintf (FILE, "\t%s .L%d-.L%d\n", ".long", VALUE, REL) -+ -+/* This macro should be provided on machines where the addresses in a dispatch -+ table are absolute. -+ -+ The definition should be a C statement to output to the stdio stream STREAM -+ an assembler pseudo-instruction to generate a reference to a label. VALUE -+ is the number of an internal label whose definition is output using -+ `ASM_OUTPUT_INTERNAL_LABEL'. For example, -+ -+ fprintf (STREAM, "\t.word L%d\n", VALUE) */ -+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \ -+ fprintf (STREAM, "\t.word .L%d\n", VALUE) -+ -+/* Switch into a generic section. */ -+#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section -+ -+/* Assembler Commands for Alignment. */ -+ -+#define ASM_OUTPUT_SKIP(STREAM, N) fprintf (STREAM, "\t.skip %d,0\n", N) -+/* A C statement to output to the stdio stream STREAM an assembler -+ instruction to advance the location counter by NBYTES bytes. -+ Those bytes should be zero when loaded. NBYTES will be a C -+ expression of type `int'. */ -+ -+/* A C statement to output to the stdio stream STREAM an assembler command to -+ advance the location counter to a multiple of 2 to the POWER bytes. POWER -+ will be a C expression of type `int'. */ -+#define ASM_OUTPUT_ALIGN(FILE, LOG) \ -+ if ((LOG) != 0) \ -+ fprintf (FILE, "\t.align %d\n", (LOG)) -+ -+/* A C expression that returns the DBX register number for the compiler -+ register number REGNO. In simple cases, the value of this expression may be -+ REGNO itself. But sometimes there are some registers that the compiler -+ knows about and DBX does not, or vice versa. In such cases, some register -+ may need to have one number in the compiler and another for DBX. -+ -+ If two registers have consecutive numbers inside GNU CC, and they can be -+ used as a pair to hold a multiword value, then they *must* have consecutive -+ numbers after renumbering with `DBX_REGISTER_NUMBER'. Otherwise, debuggers -+ will be unable to access such a pair, because they expect register pairs to -+ be consecutive in their own numbering scheme. -+ -+ If you find yourself defining `DBX_REGISTER_NUMBER' in way that does not -+ preserve register pairs, then what you must do instead is redefine the -+ actual register numbering scheme. -+ -+ This declaration is required. */ -+#define DBX_REGISTER_NUMBER(REGNO) REGNO -+ -+/* A C expression that returns the integer offset value for an automatic -+ variable having address X (an RTL expression). The default computation -+ assumes that X is based on the frame-pointer and gives the offset from the -+ frame-pointer. This is required for targets that produce debugging output -+ for DBX or COFF-style debugging output for SDB and allow the frame-pointer -+ to be eliminated when the `-g' options is used. */ -+#define DEBUGGER_AUTO_OFFSET(X) \ -+ ((GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0) \ -+ + (frame_pointer_needed \ -+ ? 0 : -initial_elimination_offset (FRAME_POINTER_REGNUM, \ -+ STACK_POINTER_REGNUM))) -+ -+/* A C expression that returns the integer offset value for an argument having -+ address X (an RTL expression). The nominal offset is OFFSET. */ -+#define DEBUGGER_ARG_OFFSET(OFFSET, X) \ -+ ((GET_CODE (X) == PLUS ? OFFSET : 0) \ -+ + (frame_pointer_needed \ -+ ? 0 : -initial_elimination_offset (ARG_POINTER_REGNUM, \ -+ STACK_POINTER_REGNUM))) -+ -+/* A C expression that returns the type of debugging output GNU CC produces -+ when the user specifies `-g' or `-ggdb'. Define this if you have arranged -+ for GNU CC to support more than one format of debugging output. Currently, -+ the allowable values are `DBX_DEBUG', `SDB_DEBUG', `DWARF_DEBUG', -+ `DWARF2_DEBUG', and `XCOFF_DEBUG'. -+ -+ The value of this macro only affects the default debugging output; the user -+ can always get a specific type of output by using `-gstabs', `-gcoff', -+ `-gdwarf-1', `-gdwarf-2', or `-gxcoff'. -+ -+ Defined in svr4.h. -+*/ -+#undef PREFERRED_DEBUGGING_TYPE -+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG -+ -+/* Define this macro if GNU CC should produce dwarf version 2 format debugging -+ output in response to the `-g' option. -+ -+ To support optional call frame debugging information, you must also define -+ `INCOMING_RETURN_ADDR_RTX' and either set `RTX_FRAME_RELATED_P' on the -+ prologue insns if you use RTL for the prologue, or call `dwarf2out_def_cfa' -+ and `dwarf2out_reg_save' as appropriate from `FUNCTION_PROLOGUE' if you -+ don't. -+ -+ Defined in svr4.h. */ -+ -+#define DWARF2_DEBUGGING_INFO 1 -+/*#define DWARF2_UNWIND_INFO 1*/ -+#define DWARF2_UNWIND_INFO 0 -+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LINK_REGNO) -+#define INCOMING_FRAME_SP_OFFSET 0 -+#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LINK_REGNO) -+#define EH_RETURN_FIRST 9 -+#define EH_RETURN_DATA_REGNO(N) ((N) < 2 ? (N) + EH_RETURN_FIRST : INVALID_REGNUM) -+ -+/* The EH_RETURN_STACKADJ_RTX macro returns RTL which describes the -+ location used to store the amount to ajdust the stack. This is -+ usually a registers that is available from end of the function's body -+ to the end of the epilogue. Thus, this cannot be a register used as a -+ temporary by the epilogue. -+ -+ This must be an integer register. */ -+#define EH_RETURN_STACKADJ_REGNO 11 -+#define EH_RETURN_STACKADJ_RTX \ -+ gen_rtx_REG (Pmode, EH_RETURN_STACKADJ_REGNO) -+ -+/* The EH_RETURN_HANDLER_RTX macro returns RTL which describes the -+ location used to store the address the processor should jump to -+ catch exception. This is usually a registers that is available from -+ end of the function's body to the end of the epilogue. Thus, this -+ cannot be a register used as a temporary by the epilogue. -+ -+ This must be an address register. */ -+#define EH_RETURN_HANDLER_REGNO 18 -+#define EH_RETURN_HANDLER_RTX \ -+ gen_rtx_REG (Pmode, EH_RETURN_HANDLER_REGNO) -+ -+/* #define DWARF2_DEBUGGING_INFO */ -+ -+/* Define this macro if GNU CC should produce dwarf version 2-style -+ line numbers. This usually requires extending the assembler to -+ support them, and #defining DWARF2_LINE_MIN_INSN_LENGTH in the -+ assembler configuration header files. */ -+/* #define DWARF2_ASM_LINE_DEBUG_INFO 1 */ -+ -+ -+/* An alias for a machine mode name. This is the machine mode that elements -+ of a jump-table have. */ -+#define CASE_VECTOR_MODE Pmode -+ -+/* Smallest number of different values for which it is best to use a -+ jump-table instead of a tree of conditional branches. For most Ubicom32 -+ targets this is quite small, but for the v1 architecture implementations -+ we had very little data memory and so heavily prefer the tree approach -+ rather than the jump tables. */ -+#define CASE_VALUES_THRESHOLD ubicom32_case_values_threshold -+ -+/* Register operations within the Ubicom32 architecture always operate on -+ the whole register word and not just the sub-bits required for the opcode -+ mode size. */ -+#define WORD_REGISTER_OPERATIONS -+ -+/* The maximum number of bytes that a single instruction can move quickly from -+ memory to memory. */ -+#define MOVE_MAX 4 -+ -+/* A C expression that is nonzero if on this machine the number of bits -+ actually used for the count of a shift operation is equal to the number of -+ bits needed to represent the size of the object being shifted. When this -+ macro is non-zero, the compiler will assume that it is safe to omit a -+ sign-extend, zero-extend, and certain bitwise `and' instructions that -+ truncates the count of a shift operation. On machines that have -+ instructions that act on bitfields at variable positions, which may include -+ `bit test' instructions, a nonzero `SHIFT_COUNT_TRUNCATED' also enables -+ deletion of truncations of the values that serve as arguments to bitfield -+ instructions. -+ -+ If both types of instructions truncate the count (for shifts) and position -+ (for bitfield operations), or if no variable-position bitfield instructions -+ exist, you should define this macro. -+ -+ However, on some machines, such as the 80386 and the 680x0, truncation only -+ applies to shift operations and not the (real or pretended) bitfield -+ operations. Define `SHIFT_COUNT_TRUNCATED' to be zero on such machines. -+ Instead, add patterns to the `md' file that include the implied truncation -+ of the shift instructions. -+ -+ You need not define this macro if it would always have the value of zero. */ -+#define SHIFT_COUNT_TRUNCATED 1 -+ -+/* A C expression which is nonzero if on this machine it is safe to "convert" -+ an integer of INPREC bits to one of OUTPREC bits (where OUTPREC is smaller -+ than INPREC) by merely operating on it as if it had only OUTPREC bits. -+ -+ On many machines, this expression can be 1. -+ -+ When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes for -+ which `MODES_TIEABLE_P' is 0, suboptimal code can result. If this is the -+ case, making `TRULY_NOOP_TRUNCATION' return 0 in such cases may improve -+ things. */ -+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 -+ -+/* A C string constant that tells the GNU CC driver program options to pass -+ to the assembler. It can also specify how to translate options you give -+ to GNU CC into options for GNU CC to pass to the assembler. See the -+ file `sun3.h' for an example of this. -+ -+ Defined in svr4.h. */ -+#undef ASM_SPEC -+#define ASM_SPEC \ -+ "%{march=*:-m%*} %{!march=*:-mubicom32v4} %{mfdpic:-mfdpic}" -+ -+#define LINK_SPEC "\ -+%{h*} %{v:-V} \ -+%{b} \ -+%{mfdpic:-melf32ubicom32fdpic -z text} \ -+%{static:-dn -Bstatic} \ -+%{shared:-G -Bdynamic} \ -+%{symbolic:-Bsymbolic} \ -+%{G*} \ -+%{YP,*} \ -+%{Qy:} %{!Qn:-Qy}" -+ -+#undef STARTFILE_SPEC -+#undef ENDFILE_SPEC -+ -+/* The svr4.h LIB_SPEC with -leval and --*group tacked on */ -+ -+#undef LIB_SPEC -+#define LIB_SPEC "%{!shared:%{!symbolic:--start-group -lc -leval -lgcc --end-group}}" -+ -+#undef HAVE_GAS_SHF_MERGE -+#define HAVE_GAS_SHF_MERGE 0 -+ -+#define HANDLE_SYSV_PRAGMA 1 -+#undef HANDLE_PRAGMA_PACK -+ -+typedef void (*ubicom32_func_ptr) (void); -+ -+/* Define builtins for selected special-purpose instructions. */ -+enum ubicom32_builtins -+{ -+ UBICOM32_BUILTIN_UBICOM32_SWAPB_2, -+ UBICOM32_BUILTIN_UBICOM32_SWAPB_4 -+}; -+ -+extern rtx ubicom32_compare_op0; -+extern rtx ubicom32_compare_op1; -+ -+#define TYPE_ASM_OP "\t.type\t" -+#define TYPE_OPERAND_FMT "@%s" -+ -+#ifndef ASM_DECLARE_RESULT -+#define ASM_DECLARE_RESULT(FILE, RESULT) -+#endif -+ -+/* These macros generate the special .type and .size directives which -+ are used to set the corresponding fields of the linker symbol table -+ entries in an ELF object file under SVR4. These macros also output -+ the starting labels for the relevant functions/objects. */ -+ -+/* Write the extra assembler code needed to declare a function properly. -+ Some svr4 assemblers need to also have something extra said about the -+ function's return value. We allow for that here. */ -+ -+#ifndef ASM_DECLARE_FUNCTION_NAME -+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ -+ do \ -+ { \ -+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \ -+ ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \ -+ ASM_OUTPUT_LABEL (FILE, NAME); \ -+ } \ -+ while (0) -+#endif ---- /dev/null -+++ b/gcc/config/ubicom32/ubicom32.md -@@ -0,0 +1,3753 @@ -+; GCC machine description for Ubicom32 -+; -+; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software -+; Foundation, Inc. -+; Contributed by Ubicom, Inc. -+; -+; This file is part of GCC. -+; -+; GCC is free software; you can redistribute it and/or modify -+; it under the terms of the GNU General Public License as published by -+; the Free Software Foundation; either version 3, or (at your option) -+; any later version. -+; -+; GCC is distributed in the hope that it will be useful, -+; but WITHOUT ANY WARRANTY; without even the implied warranty of -+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+; GNU General Public License for more details. -+; -+; You should have received a copy of the GNU General Public License -+; along with GCC; see the file COPYING3. If not see -+; <http://www.gnu.org/licenses/>. -+ -+(define_constants -+ [(AUX_DATA_REGNO 15) -+ (LINK_REGNO 21) -+ (SP_REGNO 23) -+ (ACC0_HI_REGNO 24) -+ (ACC1_HI_REGNO 26) -+ (CC_REGNO 30)]) -+ -+(define_constants -+ [(UNSPEC_FDPIC_GOT 0) -+ (UNSPEC_FDPIC_GOT_FUNCDESC 1)]) -+ -+(define_constants -+ [(UNSPEC_VOLATILE_LOAD_FDPIC_FUNCDESC 0)]) -+ -+;; Types of instructions (for scheduling purposes). -+ -+(define_attr "type" "mul,addr,other" -+ (const_string "other")) -+ -+; Define instruction scheduling characteristics. We can only issue -+; one instruction per clock so we don't need to define CPU units. -+; -+(define_automaton "ubicom32") -+ -+(define_cpu_unit "i_pipeline" "ubicom32"); -+ -+; We have a 4 cycle hazard associated with address calculations which -+; seems rather tricky to avoid so we go with a defensive assumption -+; that almost anything can be used to generate addresses. -+; -+;(define_insn_reservation "ubicom32_other" 4 -+; (eq_attr "type" "other") -+; "i_pipeline") -+ -+; Some moves don't generate hazards. -+; -+;(define_insn_reservation "ubicom32_addr" 1 -+; (eq_attr "type" "addr") -+; "i_pipeline") -+ -+; We need 3 cycles between a multiply instruction and any use of the -+; matching accumulator register(s). -+; -+(define_insn_reservation "ubicom32_mul" 4 -+ (eq_attr "type" "mul") -+ "i_pipeline") -+ -+(define_attr "length" "" -+ (const_int 4)) -+ -+(include "predicates.md") -+(include "constraints.md") -+ -+; 8-bit move with no change to the flags reg. -+; -+(define_insn "movqi" -+ [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") -+ (match_operand:QI 1 "ubicom32_move_operand" "g"))] -+ "" -+ "move.1\\t%0, %1") -+ -+; Combiner-generated 8-bit move with the zero flag set accordingly. -+; -+(define_insn "movqi_ccszn" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:QI 0 "nonimmediate_operand" "rm") -+ (const_int 0))) -+ (set (match_operand:QI 1 "nonimmediate_operand" "=rm") -+ (match_dup 0))] -+ "ubicom32_match_cc_mode(insn, CCSZNmode)" -+ "ext.1\\t%1, %0") -+ -+; Combine isn't very good at merging some types of operations so we -+; have to make do with a peephole. It's not as effective but it's better -+; than doing nothing. -+; -+(define_peephole2 -+ [(set (match_operand:QI 0 "nonimmediate_operand" "") -+ (match_operand:QI 1 "nonimmediate_operand" "")) -+ (set (match_operand 2 "ubicom32_cc_register_operand" "") -+ (match_operator 3 "ubicom32_compare_operator" -+ [(match_dup 0) -+ (const_int 0)]))] -+ "(GET_MODE (operands[2]) == CCSZNmode -+ || GET_MODE (operands[2]) == CCSZmode)" -+ [(parallel -+ [(set (match_dup 2) -+ (match_op_dup 3 -+ [(match_dup 1) -+ (const_int 0)])) -+ (set (match_dup 0) -+ (match_dup 1))])] -+ "") -+ -+; Combine isn't very good at merging some types of operations so we -+; have to make do with a peephole. It's not as effective but it's better -+; than doing nothing. -+; -+(define_peephole2 -+ [(set (match_operand:QI 0 "nonimmediate_operand" "") -+ (match_operand:QI 1 "nonimmediate_operand" "")) -+ (set (match_operand 2 "ubicom32_cc_register_operand" "") -+ (match_operator 3 "ubicom32_compare_operator" -+ [(match_dup 1) -+ (const_int 0)]))] -+ "(GET_MODE (operands[2]) == CCSZNmode -+ || GET_MODE (operands[2]) == CCSZmode)" -+ [(parallel -+ [(set (match_dup 2) -+ (match_op_dup 3 -+ [(match_dup 1) -+ (const_int 0)])) -+ (set (match_dup 0) -+ (match_dup 1))])] -+ "") -+ -+; 16-bit move with no change to the flags reg. -+; -+(define_insn "movhi" -+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") -+ (match_operand:HI 1 "ubicom32_move_operand" "g"))] -+ "" -+ "* -+ { -+ if (CONST_INT_P (operands[1])) -+ return \"movei\\t%0, %1\"; -+ -+ return \"move.2\\t%0, %1\"; -+ }") -+ -+; Combiner-generated 16-bit move with the zero flag set accordingly. -+; -+(define_insn "movhi_ccszn" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:HI 0 "nonimmediate_operand" "rm") -+ (const_int 0))) -+ (set (match_operand:HI 1 "nonimmediate_operand" "=rm") -+ (match_dup 0))] -+ "ubicom32_match_cc_mode(insn, CCSZNmode)" -+ "ext.2\\t%1, %0") -+ -+; Combine isn't very good at merging some types of operations so we -+; have to make do with a peephole. It's not as effective but it's better -+; than doing nothing. -+; -+(define_peephole2 -+ [(set (match_operand:HI 0 "nonimmediate_operand" "") -+ (match_operand:HI 1 "nonimmediate_operand" "")) -+ (set (match_operand 2 "ubicom32_cc_register_operand" "") -+ (match_operator 3 "ubicom32_compare_operator" -+ [(match_dup 0) -+ (const_int 0)]))] -+ "(GET_MODE (operands[2]) == CCSZNmode -+ || GET_MODE (operands[2]) == CCSZmode)" -+ [(parallel -+ [(set (match_dup 2) -+ (match_op_dup 3 -+ [(match_dup 1) -+ (const_int 0)])) -+ (set (match_dup 0) -+ (match_dup 1))])] -+ "") -+ -+; Combine isn't very good at merging some types of operations so we -+; have to make do with a peephole. It's not as effective but it's better -+; than doing nothing. -+; -+(define_peephole2 -+ [(set (match_operand:HI 0 "nonimmediate_operand" "") -+ (match_operand:HI 1 "nonimmediate_operand" "")) -+ (set (match_operand 2 "ubicom32_cc_register_operand" "") -+ (match_operator 3 "ubicom32_compare_operator" -+ [(match_dup 1) -+ (const_int 0)]))] -+ "(GET_MODE (operands[2]) == CCSZNmode -+ || GET_MODE (operands[2]) == CCSZmode)" -+ [(parallel -+ [(set (match_dup 2) -+ (match_op_dup 3 -+ [(match_dup 1) -+ (const_int 0)])) -+ (set (match_dup 0) -+ (match_dup 1))])] -+ "") -+ -+; 32-bit move with no change to the flags reg. -+; -+(define_expand "movsi" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "") -+ (match_operand:SI 1 "general_operand" ""))] -+ "" -+ "{ -+ /* Convert any complexities in operand 1 into something that can just -+ fall into the default expander code. */ -+ ubicom32_expand_movsi (operands); -+ }") -+ -+(define_insn "movsi_high" -+ [(set (match_operand:SI 0 "ubicom32_address_register_operand" "=a") -+ (high:SI (match_operand:SI 1 "ubicom32_symbolic_address_operand" "s")))] -+ "" -+ "moveai\\t%0, #%%hi(%E1)") -+ -+(define_insn "movsi_lo_sum" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") -+ (lo_sum:SI (match_operand:SI 1 "ubicom32_address_register_operand" "a") -+ (match_operand:SI 2 "immediate_operand" "s")))] -+ "" -+ "lea.1\\t%0, %%lo(%E2)(%1)") -+ -+(define_insn "movsi_internal" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") -+ (match_operand:SI 1 "ubicom32_move_operand" "rmnY"))] -+ "" -+ "* -+ { -+ if (CONST_INT_P (operands[1])) -+ { -+ ubicom32_emit_move_const_int (operands[0], operands[1]); -+ return \"\"; -+ } -+ -+ if (GET_CODE (operands[1]) == CONST_DOUBLE) -+ { -+ HOST_WIDE_INT i = CONST_DOUBLE_LOW (operands[1]); -+ -+ ubicom32_emit_move_const_int (operands[0], GEN_INT (i)); -+ return \"\"; -+ } -+ -+ if (ubicom32_address_register_operand (operands[0], VOIDmode) -+ && register_operand (operands[1], VOIDmode)) -+ { -+ if (ubicom32_address_register_operand (operands[1], VOIDmode)) -+ return \"lea.1\\t%0, 0(%1)\"; -+ -+ /* Use movea here to utilize the hazard bypass in the >= v4 ISA. */ -+ if (ubicom32_v4) -+ return \"movea\\t%0, %1\"; -+ -+ return \"move.4\\t%0, %1\"; -+ } -+ -+ return \"move.4\\t%0, %1\"; -+ }") -+ -+; If we're not dependent on the state of the condition codes we can construct -+; constants of value 2^n by using a bset. -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "nonimmediate_operand" "") -+ (match_operand:SI 1 "const_int_operand" ""))] -+ "(exact_log2 (INTVAL (operands[1])) > 14 -+ && peep2_regno_dead_p (0, CC_REGNO))" -+ [(parallel -+ [(set (match_dup 0) -+ (ior:SI (const_int 0) -+ (match_dup 1))) -+ (clobber (reg:CC CC_REGNO))])] -+ "") -+ -+; If we're not dependent on the state of the condition codes we can construct -+; constants of value ~(2^n) by using a bclr. -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "nonimmediate_operand" "") -+ (match_operand:SI 1 "const_int_operand" ""))] -+ "(exact_log2 (~INTVAL (operands[1])) > 14 -+ && peep2_regno_dead_p (0, CC_REGNO))" -+ [(parallel -+ [(set (match_dup 0) -+ (and:SI (const_int -1) -+ (match_dup 1))) -+ (clobber (reg:CC CC_REGNO))])] -+ "") -+ -+; For 32-bit constants that have bits 0 through 24 and bit 31 set the same -+; we can use swapb.4! -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "nonimmediate_operand" "") -+ (match_operand:SI 1 "const_int_operand" ""))] -+ "(ubicom32_v4 -+ && (INTVAL (operands[1]) & 0xffffffff) != 0xffffffff -+ && (INTVAL (operands[1]) & 0xffffffff) != 0 -+ && ((INTVAL (operands[1]) & 0x80ffffff) == 0 -+ || (INTVAL (operands[1]) & 0x80ffffff) == 0x80ffffff))" -+ [(set (match_dup 0) -+ (bswap:SI (match_dup 2)))] -+ "{ -+ operands[2] = GEN_INT (INTVAL (operands[1]) >> 24); -+ }") -+ -+; If this is a write of a constant to memory look to see if we can usefully -+; transform this into 2 smaller writes. -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "memory_operand" "") -+ (match_operand:SI 1 "const_int_operand" ""))] -+ "! satisfies_constraint_I (operands[1]) -+ && ubicom32_legitimate_address_p (HImode, plus_constant (XEXP (operands[0], 0), 2), 1)" -+ [(set (match_dup 4) (match_dup 2)) -+ (set (match_dup 5) (match_dup 3))] -+ "{ -+ rtx low_hword_addr; -+ -+ operands[2] = gen_highpart_mode (HImode, SImode, operands[1]); -+ operands[3] = gen_lowpart (HImode, operands[1]); -+ -+ operands[4] = gen_rtx_MEM (HImode, XEXP (operands[0], 0)); -+ MEM_COPY_ATTRIBUTES (operands[4], operands[0]); -+ -+ low_hword_addr = plus_constant (XEXP (operands[0], 0), 2); -+ operands[5] = gen_rtx_MEM (HImode, low_hword_addr); -+ MEM_COPY_ATTRIBUTES (operands[5], operands[0]); -+ }") -+ -+; If we're writing memory and we've not found a better way to do this then -+; try loading into a D register and then copying to memory. This will -+; perform the fewest possible memory read/writes. -+; -+(define_peephole2 -+ [(match_scratch:SI 2 "d") -+ (set (match_operand:SI 0 "memory_operand" "") -+ (match_operand:SI 1 "const_int_operand" ""))] -+ "! satisfies_constraint_I (operands[1])" -+ [(set (match_dup 2) (match_dup 1)) -+ (set (match_dup 0) (match_dup 2))] -+ "") -+ -+; If we're not dependent on the state of the condition codes we can construct -+; constants of value (2^n - 1) by using an lsr.4. -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "") -+ (match_operand:SI 1 "const_int_operand" ""))] -+ "(exact_log2 (INTVAL (operands[1]) + 1) > 14 -+ && peep2_regno_dead_p (0, CC_REGNO))" -+ [(parallel -+ [(set (match_dup 0) -+ (lshiftrt:SI (const_int -1) -+ (match_dup 2))) -+ (clobber (reg:CC CC_REGNO))])] -+ "{ -+ operands[2] = GEN_INT (32 - exact_log2 (INTVAL (operands[1]) + 1)); -+ }") -+ -+; If we're not dependent on the state of the condition codes we can construct -+; constants of value (2^n - 1) by using an lsr.4. -+; -+(define_peephole2 -+ [(match_scratch:SI 2 "d") -+ (set (match_operand:SI 0 "nonimmediate_operand" "") -+ (match_operand:SI 1 "const_int_operand" ""))] -+ "(exact_log2 (INTVAL (operands[1]) + 1) > 14 -+ && peep2_regno_dead_p (0, CC_REGNO))" -+ [(parallel -+ [(set (match_dup 2) -+ (lshiftrt:SI (const_int -1) -+ (match_dup 3))) -+ (clobber (reg:CC CC_REGNO))]) -+ (set (match_dup 0) -+ (match_dup 2))] -+ "{ -+ operands[3] = GEN_INT (32 - exact_log2 (INTVAL (operands[1]) + 1)); -+ }") -+ -+; If we're not dependent on the state of the condition codes we can construct -+; some other constants by using an lsl.4 to shift 7 bits left by some -+; constant. -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "") -+ (match_operand:SI 1 "const_int_operand" ""))] -+ "(ubicom32_shiftable_const_int (INTVAL (operands[1])) -+ && peep2_regno_dead_p (0, CC_REGNO))" -+ [(parallel -+ [(set (match_dup 0) -+ (ashift:SI (match_dup 2) -+ (match_dup 3))) -+ (clobber (reg:CC CC_REGNO))])] -+ "{ -+ int shift = ubicom32_shiftable_const_int (INTVAL (operands[1])); -+ operands[2] = GEN_INT (INTVAL (operands[1]) >> shift); -+ operands[3] = GEN_INT (shift); -+ }") -+ -+; If we're not dependent on the state of the condition codes we can construct -+; some other constants by using an lsl.4 to shift 7 bits left by some -+; constant. -+; -+(define_peephole2 -+ [(match_scratch:SI 2 "d") -+ (set (match_operand:SI 0 "nonimmediate_operand" "") -+ (match_operand:SI 1 "const_int_operand" ""))] -+ "(ubicom32_shiftable_const_int (INTVAL (operands[1])) -+ && peep2_regno_dead_p (0, CC_REGNO))" -+ [(parallel -+ [(set (match_dup 2) -+ (ashift:SI (match_dup 3) -+ (match_dup 4))) -+ (clobber (reg:CC CC_REGNO))]) -+ (set (match_dup 0) -+ (match_dup 2))] -+ "{ -+ int shift = ubicom32_shiftable_const_int (INTVAL (operands[1])); -+ operands[3] = GEN_INT (INTVAL (operands[1]) >> shift); -+ operands[4] = GEN_INT (shift); -+ }") -+ -+; For some 16-bit unsigned constants that have bit 15 set we can use -+; swapb.2! -+; -+; Note that the movsi code emits the same sequence but by using a peephole2 -+; we split the pattern early enough to allow instruction scheduling to -+; occur. -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "const_int_operand" ""))] -+ "(ubicom32_v4 -+ && (INTVAL (operands[1]) & 0xffff80ff) == 0x80ff)" -+ [(set (match_dup 0) -+ (zero_extend:SI (bswap:HI (match_dup 2))))] -+ "{ -+ HOST_WIDE_INT i = INTVAL (operands[1]) >> 8; -+ if (i >= 0x80) -+ i -= 0x100; -+ operands[2] = GEN_INT (i); -+ }") -+ -+; In general for a 16-bit unsigned constant that has bit 15 set -+; then we need a movei/move.2 pair unless we can represent it -+; via just a move.2. -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "const_int_operand" ""))] -+ "(INTVAL (operands[1]) & 0xffff8000) == 0x8000 -+ && (INTVAL (operands[1]) & 0xffff) < 0xff80" -+ [(set (match_dup 2) -+ (match_dup 1)) -+ (set (match_dup 0) -+ (zero_extend:SI (match_dup 2)))] -+ "{ -+ operands[2] = gen_rtx_REG (HImode, REGNO (operands[0])); -+ }") -+ -+; If we're not dependent on the state of the condition codes we can construct -+; 32-bit constants that have bits 16 through 31 set to arbitrary values -+; and have bits 0 through 15 set to something representable as a default -+; source-1 immediate - we use movei/shmrg.2 -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "") -+ (match_operand:SI 1 "const_int_operand" ""))] -+ "(((INTVAL (operands[1]) >= 0x8000 -+ && INTVAL (operands[1]) < 0xff80) -+ || INTVAL (operands[1]) >= 0x10000 -+ || INTVAL (operands[1]) < -0x8000) -+ && ((INTVAL (operands[1]) & 0xffff) >= 0xff80 -+ || (INTVAL (operands[1]) & 0xffff) < 0x80) -+ && peep2_regno_dead_p (0, CC_REGNO))" -+ [(set (match_dup 0) -+ (match_dup 2)) -+ (parallel -+ [(set (match_dup 0) -+ (ior:SI -+ (ashift:SI (match_dup 0) -+ (const_int 16)) -+ (zero_extend:SI -+ (match_dup 3)))) -+ (clobber (reg:CC CC_REGNO))])] -+ "{ -+ operands[2] = gen_highpart_mode (HImode, SImode, operands[1]); -+ operands[3] = gen_lowpart (HImode, operands[1]); -+ }") -+ -+; Exactly the same as the peephole2 preceding except that this targets a -+; general register instead of D register. Hopefully the later optimization -+; passes will notice that the value ended up in a D register first here -+; and eliminate away the other register! -+; -+(define_peephole2 -+ [(match_scratch:SI 2 "d") -+ (set (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "const_int_operand" ""))] -+ "(((INTVAL (operands[1]) >= 0x8000 -+ && INTVAL (operands[1]) < 0xff80) -+ || INTVAL (operands[1]) >= 0x10000 -+ || INTVAL (operands[1]) < -0x8000) -+ && ((INTVAL (operands[1]) & 0xffff) >= 0xff80 -+ || (INTVAL (operands[1]) & 0xffff) < 0x80) -+ && peep2_regno_dead_p (0, CC_REGNO))" -+ [(set (match_dup 2) -+ (match_dup 3)) -+ (parallel -+ [(set (match_dup 2) -+ (ior:SI -+ (ashift:SI (match_dup 2) -+ (const_int 16)) -+ (zero_extend:SI -+ (match_dup 4)))) -+ (clobber (reg:CC CC_REGNO))]) -+ (set (match_dup 0) -+ (match_dup 2))] -+ "{ -+ operands[3] = gen_highpart_mode (HImode, SImode, operands[1]); -+ operands[4] = gen_lowpart (HImode, operands[1]); -+ }") -+ -+; If we have a load of a large integer constant which does not have bit 31 -+; set and we have a spare A reg then construct it with a moveai/lea.1 pair -+; instead. This avoids constructing it in 3 instructions on the stack. -+; -+; Note that we have to be careful not to match anything that matches -+; something we can do in a single instruction! There aren't many such -+; constants but there are some. -+; -+(define_peephole2 -+ [(match_scratch:SI 2 "a") -+ (set (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "const_int_operand" ""))] -+ "(! (INTVAL (operands[1]) & 0x80000000) -+ && ((INTVAL (operands[1]) >= 0x8000 -+ && INTVAL (operands[1]) < 0xff80) -+ || INTVAL (operands[1]) >= 0x10000))" -+ [(set (match_dup 2) -+ (match_dup 3)) -+ (set (match_dup 0) -+ (plus:SI (match_dup 2) -+ (match_dup 4)))] -+ "{ -+ HOST_WIDE_INT i = INTVAL (operands[1]); -+ operands[3] = GEN_INT (i & 0xffffff80); -+ operands[4] = GEN_INT (i & 0x7f); -+ }") -+ -+; If we're not dependent on the state of the condition codes we can construct -+; a 32-bit constant with a movei/movei/shmrg.2 sequence if possible. -+; -+(define_peephole2 -+ [(match_scratch:HI 2 "d") -+ (set (match_operand:SI 0 "ubicom32_data_register_operand" "") -+ (match_operand:SI 1 "const_int_operand" "")) -+ (match_dup 2)] -+ "(INTVAL (operands[1]) & 0x80000000 -+ && INTVAL (operands[1]) < -0x8000 -+ && peep2_regno_dead_p (0, CC_REGNO))" -+ [(set (match_dup 0) -+ (match_dup 3)) -+ (set (match_dup 2) -+ (match_dup 4)) -+ (parallel -+ [(set (match_dup 0) -+ (ior:SI -+ (ashift:SI (match_dup 0) -+ (const_int 16)) -+ (zero_extend:SI -+ (match_dup 2)))) -+ (clobber (reg:CC CC_REGNO))])] -+ "{ -+ operands[3] = gen_highpart_mode (HImode, SImode, operands[1]); -+ operands[4] = gen_lowpart (HImode, operands[1]); -+ }") -+ -+; Exactly the same as the peephole2 preceding except that this targets a -+; general register instead of D register. Hopefully the later optimization -+; passes will notice that the value ended up in a D register first here -+; and eliminate away the other register! -+; -+(define_peephole2 -+ [(match_scratch:SI 2 "d") -+ (match_scratch:HI 3 "d") -+ (set (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "const_int_operand" "")) -+ (match_dup 3)] -+ "(INTVAL (operands[1]) & 0x80000000 -+ && INTVAL (operands[1]) < -0x8000 -+ && peep2_regno_dead_p (0, CC_REGNO))" -+ [(set (match_dup 2) -+ (match_dup 4)) -+ (set (match_dup 3) -+ (match_dup 5)) -+ (parallel -+ [(set (match_dup 2) -+ (ior:SI -+ (ashift:SI (match_dup 2) -+ (const_int 16)) -+ (zero_extend:SI -+ (match_dup 3)))) -+ (clobber (reg:CC CC_REGNO))]) -+ (set (match_dup 0) -+ (match_dup 2))] -+ "{ -+ operands[4] = gen_highpart_mode (HImode, SImode, operands[1]); -+ operands[5] = gen_lowpart (HImode, operands[1]); -+ }") -+ -+(define_insn "movsi_fdpic_got_offset" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (match_operand:SI 1 "ubicom32_fdpic_got_offset_operand" "Y"))] -+ "" -+ "movei\\t%0, %1") -+ -+; The explicit MEM inside the UNSPEC prevents the compiler from moving -+; the load before a branch after a NULL test, or before a store that -+; initializes a function descriptor. -+ -+(define_insn_and_split "load_fdpic_funcdesc" -+ [(set (match_operand:SI 0 "ubicom32_address_register_operand" "=a") -+ (unspec_volatile:SI [(mem:SI (match_operand:SI 1 "address_operand" "p"))] -+ UNSPEC_VOLATILE_LOAD_FDPIC_FUNCDESC))] -+ "" -+ "#" -+ "reload_completed" -+ [(set (match_dup 0) -+ (mem:SI (match_dup 1)))]) -+ -+; Combiner-generated 32-bit move with the zero flag set accordingly. -+; -+(define_insn "movsi_ccwzn" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:SI 0 "nonimmediate_operand" "rm, d") -+ (const_int 0))) -+ (set (match_operand:SI 1 "nonimmediate_operand" "=d,rm") -+ (match_dup 0))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "@ -+ lsl.4\\t%1, %0, #0 -+ add.4\\t%1, #0, %0") -+ -+; Combiner-generated 32-bit move with all flags set accordingly. -+; -+(define_insn "movsi_ccw" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:SI 0 "ubicom32_data_register_operand" "d") -+ (const_int 0))) -+ (set (match_operand:SI 1 "nonimmediate_operand" "=rm") -+ (match_dup 0))] -+ "ubicom32_match_cc_mode(insn, CCWmode)" -+ "add.4\\t%1, #0, %0") -+ -+; Combine isn't very good at merging some types of operations so we -+; have to make do with a peephole. It's not as effective but it's better -+; than doing nothing. -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "") -+ (match_operand:SI 1 "nonimmediate_operand" "")) -+ (parallel -+ [(set (match_operand 2 "ubicom32_cc_register_operand" "") -+ (match_operator 3 "ubicom32_compare_operator" -+ [(match_dup 0) -+ (const_int 0)])) -+ (clobber (match_operand:SI 4 "ubicom32_data_register_operand" ""))])] -+ "(GET_MODE (operands[2]) == CCWZNmode -+ || GET_MODE (operands[2]) == CCWZmode)" -+ [(parallel -+ [(set (match_dup 2) -+ (match_op_dup 3 -+ [(match_dup 1) -+ (const_int 0)])) -+ (set (match_dup 0) -+ (match_dup 1))])] -+ "") -+ -+; Combine isn't very good at merging some types of operations so we -+; have to make do with a peephole. It's not as effective but it's better -+; than doing nothing. -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "nonimmediate_operand" "") -+ (match_operand:SI 1 "ubicom32_data_register_operand" "")) -+ (parallel -+ [(set (match_operand 2 "ubicom32_cc_register_operand" "") -+ (match_operator 3 "ubicom32_compare_operator" -+ [(match_dup 1) -+ (const_int 0)])) -+ (clobber (match_operand:SI 4 "ubicom32_data_register_operand" ""))])] -+ "(GET_MODE (operands[2]) == CCWZNmode -+ || GET_MODE (operands[2]) == CCWZmode)" -+ [(parallel -+ [(set (match_dup 2) -+ (match_op_dup 3 -+ [(match_dup 1) -+ (const_int 0)])) -+ (set (match_dup 0) -+ (match_dup 1))])] -+ "") -+ -+; Combine isn't very good at merging some types of operations so we -+; have to make do with a peephole. It's not as effective but it's better -+; than doing nothing. -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "nonimmediate_operand" "")) -+ (parallel -+ [(set (match_operand 2 "ubicom32_cc_register_operand" "") -+ (match_operator 3 "ubicom32_compare_operator" -+ [(match_dup 0) -+ (const_int 0)])) -+ (set (match_operand:SI 4 "ubicom32_data_register_operand" "") -+ (match_dup 0))])] -+ "(peep2_reg_dead_p (2, operands[0]) -+ && (GET_MODE (operands[2]) == CCWZNmode -+ || GET_MODE (operands[2]) == CCWZmode))" -+ [(parallel -+ [(set (match_dup 2) -+ (match_op_dup 3 -+ [(match_dup 1) -+ (const_int 0)])) -+ (set (match_dup 4) -+ (match_dup 1))])] -+ "") -+ -+; Register renaming may make a general reg into a D reg in which case -+; we may be able to simplify a compare. -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "nonimmediate_operand" "")) -+ (parallel -+ [(set (match_operand 2 "ubicom32_cc_register_operand" "") -+ (match_operator 3 "ubicom32_compare_operator" -+ [(match_dup 0) -+ (const_int 0)])) -+ (clobber (match_operand:SI 4 "ubicom32_data_register_operand" ""))])] -+ "(peep2_reg_dead_p (2, operands[0]) -+ && (GET_MODE (operands[2]) == CCWZNmode -+ || GET_MODE (operands[2]) == CCWZmode))" -+ [(parallel -+ [(set (match_dup 2) -+ (match_op_dup 3 -+ [(match_dup 1) -+ (const_int 0)])) -+ (clobber (match_dup 4))])] -+ "") -+ -+(define_insn_and_split "movdi" -+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm") -+ (match_operand:DI 1 "general_operand" "rmi,ri"))] -+ "" -+ "#" -+ "reload_completed" -+ [(set (match_dup 2) (match_dup 3)) -+ (set (match_dup 4) (match_dup 5))] -+ "{ -+ rtx dest_low; -+ rtx src_low; -+ -+ dest_low = gen_lowpart (SImode, operands[0]); -+ src_low = gen_lowpart (SImode, operands[1]); -+ -+ if (REG_P (operands[0]) -+ && REG_P (operands[1]) -+ && REGNO (operands[0]) < REGNO (operands[1])) -+ { -+ operands[2] = gen_highpart (SImode, operands[0]); -+ operands[3] = gen_highpart_mode (SImode, DImode, operands[1]); -+ operands[4] = dest_low; -+ operands[5] = src_low; -+ } -+ else if (reg_mentioned_p (dest_low, src_low)) -+ { -+ operands[2] = gen_highpart (SImode, operands[0]); -+ operands[3] = gen_highpart_mode (SImode, DImode, operands[1]); -+ operands[4] = dest_low; -+ operands[5] = src_low; -+ } -+ else -+ { -+ operands[2] = dest_low; -+ operands[3] = src_low; -+ operands[4] = gen_highpart (SImode, operands[0]); -+ operands[5] = gen_highpart_mode (SImode, DImode, operands[1]); -+ } -+ }" -+ [(set_attr "length" "8")]) -+ -+; Combiner-generated 64-bit move with all flags set accordingly. -+; -+(define_insn "movdi_ccwzn" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:DI 0 "nonimmediate_operand" "d, m, r") -+ (const_int 0))) -+ (set (match_operand:DI 1 "nonimmediate_operand" "=&rm,rm,!&rm") -+ (match_dup 0)) -+ (clobber (match_scratch:SI 2 "=X, d, d"))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "* -+ { -+ operands[3] = gen_lowpart (SImode, operands[0]); -+ operands[4] = gen_lowpart (SImode, operands[1]); -+ operands[5] = gen_highpart (SImode, operands[0]); -+ operands[6] = gen_highpart (SImode, operands[1]); -+ -+ if (ubicom32_data_register_operand (operands[0], VOIDmode)) -+ return \"add.4\\t%4, #0, %3\;addc\\t%6, #0, %5\"; -+ -+ return \"movei\\t%2, #0\;add.4\\t%4, %3, %2\;addc\\t%6, %5, %2\"; -+ }" -+ [(set_attr "length" "8")]) -+ -+(define_insn "movdi_ccw" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:DI 0 "nonimmediate_operand" "d, m, r") -+ (const_int 0))) -+ (set (match_operand:DI 1 "nonimmediate_operand" "=&rm,rm,!&rm") -+ (match_dup 0)) -+ (clobber (match_scratch:SI 2 "=X, d, d"))] -+ "ubicom32_match_cc_mode(insn, CCWmode)" -+ "* -+ { -+ operands[3] = gen_lowpart (SImode, operands[0]); -+ operands[4] = gen_lowpart (SImode, operands[1]); -+ operands[5] = gen_highpart (SImode, operands[0]); -+ operands[6] = gen_highpart (SImode, operands[1]); -+ -+ if (ubicom32_data_register_operand (operands[0], VOIDmode)) -+ return \"add.4\\t%4, #0, %3\;addc\\t%6, #0, %5\"; -+ -+ return \"movei\\t%2, #0\;add.4\\t%4, %3, %2\;addc\\t%6, %5, %2\"; -+ }" -+ [(set_attr "length" "8")]) -+ -+(define_insn "movsf" -+ [(set (match_operand:SF 0 "nonimmediate_operand" "=!d,*rm") -+ (match_operand:SF 1 "ubicom32_move_operand" "rmF,rmF"))] -+ "" -+ "* -+ { -+ if (GET_CODE (operands[1]) == CONST_DOUBLE) -+ { -+ HOST_WIDE_INT val; -+ REAL_VALUE_TYPE rv; -+ -+ REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); -+ REAL_VALUE_TO_TARGET_SINGLE (rv, val); -+ -+ ubicom32_emit_move_const_int (operands[0], GEN_INT (val)); -+ return \"\"; -+ } -+ -+ return \"move.4\\t%0, %1\"; -+ }") -+ -+(define_insn "zero_extendqihi2" -+ [(set (match_operand:HI 0 "register_operand" "=r") -+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))] -+ "" -+ "move.1\\t%0, %1") -+ -+(define_insn "zero_extendqisi2" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))] -+ "" -+ "move.1\\t%0, %1") -+ -+(define_insn "zero_extendqisi2_ccwz_1" -+ [(set (reg CC_REGNO) -+ (compare -+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")) -+ (const_int 0))) -+ (set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (zero_extend:SI (match_dup 1)))] -+ "ubicom32_match_cc_mode(insn, CCWZmode)" -+ "shmrg.1\\t%0, %1, #0") -+ -+(define_insn "zero_extendhisi2" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))] -+ "" -+ "move.2\\t%0, %1") -+ -+(define_insn "zero_extendhisi2_ccwz_1" -+ [(set (reg CC_REGNO) -+ (compare -+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")) -+ (const_int 0))) -+ (set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (zero_extend:SI (match_dup 1)))] -+ "ubicom32_match_cc_mode(insn, CCWZmode)" -+ "shmrg.2\\t%0, %1, #0") -+ -+(define_insn_and_split "zero_extendqidi2" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "rm")))] -+ "" -+ "#" -+ "reload_completed" -+ [(set (match_dup 2) -+ (zero_extend:SI (match_dup 1))) -+ (set (match_dup 3) -+ (const_int 0))] -+ "{ -+ operands[2] = gen_lowpart (SImode, operands[0]); -+ operands[3] = gen_highpart (SImode, operands[0]); -+ }" -+ [(set_attr "length" "8")]) -+ -+(define_insn_and_split "zero_extendhidi2" -+ [(set (match_operand:DI 0 "register_operand" "=r") -+ (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))] -+ "" -+ "#" -+ "reload_completed" -+ [(set (match_dup 2) -+ (zero_extend:SI (match_dup 1))) -+ (set (match_dup 3) -+ (const_int 0))] -+ "{ -+ operands[2] = gen_lowpart (SImode, operands[0]); -+ operands[3] = gen_highpart (SImode, operands[0]); -+ }" -+ [(set_attr "length" "8")]) -+ -+(define_insn_and_split "zero_extendsidi2" -+ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") -+ (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))] -+ "" -+ "#" -+ "reload_completed" -+ [(set (match_dup 2) -+ (match_dup 1)) -+ (set (match_dup 3) -+ (const_int 0))] -+ "{ -+ operands[2] = gen_lowpart (SImode, operands[0]); -+ operands[3] = gen_highpart (SImode, operands[0]); -+ }" -+ [(set_attr "length" "8")]) -+ -+(define_insn "extendqihi2" -+ [(set (match_operand:HI 0 "register_operand" "=r") -+ (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "ext.1\\t%0, %1") -+ -+(define_insn "extendqisi2" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "ext.1\\t%0, %1") -+ -+(define_insn "extendhisi2" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "ext.2\\t%0, %1") -+ -+(define_insn_and_split "extendsidi2" -+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d") -+ (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "#" -+ "reload_completed" -+ [(set (match_dup 2) -+ (match_dup 1)) -+ (parallel -+ [(set (match_dup 3) -+ (ashiftrt:SI (match_dup 2) -+ (const_int 31))) -+ (clobber (reg:CC CC_REGNO))])] -+ "{ -+ operands[2] = gen_lowpart (SImode, operands[0]); -+ operands[3] = gen_highpart (SImode, operands[0]); -+ }" -+ [(set_attr "length" "8")]) -+ -+(define_insn "bswaphi" -+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") -+ (bswap:HI (match_operand:HI 1 "ubicom32_arith_operand" "rmI")))] -+ "(ubicom32_v4)" -+ "swapb.2\\t%0, %1"); -+ -+(define_insn "bswaphisi" -+ [(set (match_operand:SI 0 "register_operand" "=r") -+ (zero_extend:SI -+ (bswap:HI (match_operand:HI 1 "ubicom32_arith_operand" "rmI"))))] -+ "(ubicom32_v4)" -+ "swapb.2\\t%0, %1"); -+ -+(define_insn "bswapsi" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") -+ (bswap:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")))] -+ "(ubicom32_v4)" -+ "swapb.4\\t%0, %1"); -+ -+(define_insn "tstqi_ext1" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:QI 0 "nonimmediate_operand" "rm") -+ (const_int 0)))] -+ "ubicom32_match_cc_mode(insn, CCSZNmode)" -+ "ext.1\\t#0, %0") -+ -+(define_expand "cmpqi" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:QI 0 "ubicom32_arith_operand" "") -+ (match_operand:QI 1 "ubicom32_data_register_operand" "")))] -+ "(ubicom32_v4)" -+ "{ -+ ubicom32_compare_op0 = operands[0]; -+ ubicom32_compare_op1 = operands[1]; -+ DONE; -+ }") -+ -+(define_insn "sub1_ccs" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:QI 0 "ubicom32_arith_operand" "rmI") -+ (match_operand:QI 1 "ubicom32_data_register_operand" "d")))] -+ "(ubicom32_v4)" -+ "sub.1\\t#0, %0, %1") -+ -+; If we're testing for equality we don't have to worry about reversing conditions. -+; -+(define_insn "sub1_ccsz_1" -+ [(set (reg:CCSZ CC_REGNO) -+ (compare:CCSZ (match_operand:QI 0 "nonimmediate_operand" "rm") -+ (match_operand:QI 1 "ubicom32_data_register_operand" "d")))] -+ "(ubicom32_v4)" -+ "sub.1\\t#0, %0, %1") -+ -+(define_insn "sub1_ccsz_2" -+ [(set (reg:CCSZ CC_REGNO) -+ (compare:CCSZ (match_operand:QI 0 "ubicom32_data_register_operand" "d") -+ (match_operand:QI 1 "ubicom32_arith_operand" "rmI")))] -+ "(ubicom32_v4)" -+ "sub.1\\t#0, %1, %0") -+ -+; When the combiner runs it doesn't have any insight into whether or not an argument -+; to a compare is spilled to the stack and therefore can't swap the comparison in -+; an attempt to use sub.1 more effectively. We peephole this case here. -+; -+(define_peephole2 -+ [(set (match_operand:QI 0 "register_operand" "") -+ (match_operand:QI 1 "ubicom32_arith_operand" "")) -+ (set (match_operand 2 "ubicom32_cc_register_operand" "") -+ (compare (match_operand:QI 3 "ubicom32_data_register_operand" "") -+ (match_dup 0))) -+ (set (pc) -+ (if_then_else (match_operator 4 "comparison_operator" -+ [(match_dup 2) -+ (const_int 0)]) -+ (label_ref (match_operand 5 "" "")) -+ (pc)))] -+ "(peep2_reg_dead_p (2, operands[0]) -+ && peep2_regno_dead_p (3, CC_REGNO))" -+ [(set (match_dup 2) -+ (compare (match_dup 1) -+ (match_dup 3))) -+ (set (pc) -+ (if_then_else (match_op_dup 6 -+ [(match_dup 2) -+ (const_int 0)]) -+ (label_ref (match_dup 5)) -+ (pc)))] -+ "{ -+ rtx cc_reg; -+ -+ cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO); -+ operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])), -+ GET_MODE (operands[4]), -+ cc_reg, -+ const0_rtx); -+ }") -+ -+(define_insn "tsthi_ext2" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:HI 0 "nonimmediate_operand" "rm") -+ (const_int 0)))] -+ "ubicom32_match_cc_mode(insn, CCSZNmode)" -+ "ext.2\\t#0, %0") -+ -+(define_expand "cmphi" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:HI 0 "ubicom32_arith_operand" "") -+ (match_operand:HI 1 "ubicom32_compare_operand" "")))] -+ "" -+ "{ -+ do -+ { -+ /* Is this a cmpi? */ -+ if (CONST_INT_P (operands[1])) -+ break; -+ -+ /* Must be a sub.2 - if necessary copy an operand into a reg. */ -+ if (! ubicom32_data_register_operand (operands[1], HImode)) -+ operands[1] = copy_to_mode_reg (HImode, operands[1]); -+ } -+ while (0); -+ -+ ubicom32_compare_op0 = operands[0]; -+ ubicom32_compare_op1 = operands[1]; -+ DONE; -+ }") -+ -+(define_insn "cmpi" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:HI 0 "nonimmediate_operand" "rm") -+ (match_operand 1 "const_int_operand" "N")))] -+ "" -+ "cmpi\\t%0, %1") -+ -+(define_insn "sub2_ccs" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:HI 0 "ubicom32_arith_operand" "rmI") -+ (match_operand:HI 1 "ubicom32_data_register_operand" "d")))] -+ "" -+ "sub.2\\t#0, %0, %1") -+ -+; If we're testing for equality we don't have to worry about reversing conditions. -+; -+(define_insn "sub2_ccsz_1" -+ [(set (reg:CCSZ CC_REGNO) -+ (compare:CCSZ (match_operand:HI 0 "nonimmediate_operand" "rm") -+ (match_operand:HI 1 "ubicom32_data_register_operand" "d")))] -+ "" -+ "sub.2\\t#0, %0, %1") -+ -+(define_insn "sub2_ccsz_2" -+ [(set (reg:CCSZ CC_REGNO) -+ (compare:CCSZ (match_operand:HI 0 "ubicom32_data_register_operand" "d") -+ (match_operand:HI 1 "ubicom32_arith_operand" "rmI")))] -+ "" -+ "sub.2\\t#0, %1, %0") -+ -+; When the combiner runs it doesn't have any insight into whether or not an argument -+; to a compare is spilled to the stack and therefore can't swap the comparison in -+; an attempt to use sub.2 more effectively. We peephole this case here. -+; -+(define_peephole2 -+ [(set (match_operand:HI 0 "register_operand" "") -+ (match_operand:HI 1 "ubicom32_arith_operand" "")) -+ (set (match_operand 2 "ubicom32_cc_register_operand" "") -+ (compare (match_operand:HI 3 "ubicom32_data_register_operand" "") -+ (match_dup 0))) -+ (set (pc) -+ (if_then_else (match_operator 4 "comparison_operator" -+ [(match_dup 2) -+ (const_int 0)]) -+ (label_ref (match_operand 5 "" "")) -+ (pc)))] -+ "(peep2_reg_dead_p (2, operands[0]) -+ && peep2_regno_dead_p (3, CC_REGNO))" -+ [(set (match_dup 2) -+ (compare (match_dup 1) -+ (match_dup 3))) -+ (set (pc) -+ (if_then_else (match_op_dup 6 -+ [(match_dup 2) -+ (const_int 0)]) -+ (label_ref (match_dup 5)) -+ (pc)))] -+ "{ -+ rtx cc_reg; -+ -+ cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO); -+ operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])), -+ GET_MODE (operands[4]), -+ cc_reg, -+ const0_rtx); -+ }") -+ -+(define_insn_and_split "tstsi_lsl4" -+ [(set (match_operand 0 "ubicom32_cc_register_operand" "=r") -+ (match_operator 1 "ubicom32_compare_operator" -+ [(match_operand:SI 2 "nonimmediate_operand" "rm") -+ (const_int 0)]))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "#" -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ [(parallel -+ [(set (match_dup 0) -+ (match_op_dup 1 -+ [(match_dup 2) -+ (const_int 0)])) -+ (clobber (match_dup 3))])] -+ "{ -+ operands[3] = gen_reg_rtx (SImode); -+ }") -+ -+(define_insn "tstsi_lsl4_d" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:SI 0 "nonimmediate_operand" "rm") -+ (const_int 0))) -+ (clobber (match_operand:SI 1 "ubicom32_data_register_operand" "=d"))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "lsl.4\\t%1, %0, #0") -+ -+; Comparison for equality with -1. -+; -+(define_insn "cmpsi_not4_ccwz" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:SI 0 "nonimmediate_operand" "rm") -+ (const_int -1)))] -+ "ubicom32_match_cc_mode(insn, CCWZmode)" -+ "not.4\\t#0, %0") -+ -+(define_expand "cmpsi" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:SI 0 "ubicom32_arith_operand" "") -+ (match_operand:SI 1 "ubicom32_compare_operand" "")))] -+ "" -+ "{ -+ do -+ { -+ /* Is this a cmpi? We can't take a memory address as cmpi takes -+ 16-bit operands. */ -+ if (register_operand (operands[0], SImode) -+ && CONST_INT_P (operands[1]) -+ && satisfies_constraint_N (operands[1])) -+ break; -+ -+ /* Must be a sub.4 - if necessary copy an operand into a reg. */ -+ if (! ubicom32_data_register_operand (operands[1], SImode)) -+ operands[1] = copy_to_mode_reg (SImode, operands[1]); -+ } -+ while (0); -+ -+ ubicom32_compare_op0 = operands[0]; -+ ubicom32_compare_op1 = operands[1]; -+ DONE; -+ }") -+ -+(define_insn "cmpsi_cmpi" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:SI 0 "register_operand" "r") -+ (match_operand 1 "const_int_operand" "N")))] -+ "(satisfies_constraint_N (operands[1]))" -+ "cmpi\\t%0, %1") -+ -+(define_insn "cmpsi_sub4" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:SI 0 "ubicom32_arith_operand" "rmI") -+ (match_operand:SI 1 "ubicom32_data_register_operand" "d")))] -+ "" -+ "sub.4\\t#0, %0, %1") -+ -+; If we're testing for equality we don't have to worry about reversing conditions. -+; -+(define_insn "cmpsi_sub4_ccwz_1" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:SI 0 "nonimmediate_operand" "rm") -+ (match_operand:SI 1 "ubicom32_data_register_operand" "d")))] -+ "ubicom32_match_cc_mode(insn, CCWZmode)" -+ "sub.4\\t#0, %0, %1") -+ -+(define_insn "cmpsi_sub4_ccwz_2" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:SI 0 "ubicom32_data_register_operand" "d") -+ (match_operand:SI 1 "nonimmediate_operand" "rm")))] -+ "ubicom32_match_cc_mode(insn, CCWZmode)" -+ "sub.4\\t#0, %1, %0") -+ -+; When the combiner runs it doesn't have any insight into whether or not an argument -+; to a compare is spilled to the stack and therefore can't swap the comparison in -+; an attempt to use sub.4 more effectively. We peephole this case here. -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "ubicom32_arith_operand" "")) -+ (set (match_operand 2 "ubicom32_cc_register_operand" "") -+ (compare (match_operand:SI 3 "ubicom32_data_register_operand" "") -+ (match_dup 0))) -+ (set (pc) -+ (if_then_else (match_operator 4 "comparison_operator" -+ [(match_dup 2) -+ (const_int 0)]) -+ (label_ref (match_operand 5 "" "")) -+ (pc)))] -+ "(peep2_reg_dead_p (2, operands[0]) -+ && peep2_regno_dead_p (3, CC_REGNO))" -+ [(set (match_dup 2) -+ (compare (match_dup 1) -+ (match_dup 3))) -+ (set (pc) -+ (if_then_else (match_op_dup 6 -+ [(match_dup 2) -+ (const_int 0)]) -+ (label_ref (match_dup 5)) -+ (pc)))] -+ "{ -+ rtx cc_reg; -+ -+ cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO); -+ operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])), -+ GET_MODE (operands[4]), -+ cc_reg, -+ const0_rtx); -+ }") -+ -+(define_insn_and_split "tstdi_or4" -+ [(set (reg:CCWZ CC_REGNO) -+ (compare:CCWZ (match_operand:DI 0 "nonimmediate_operand" "rm") -+ (const_int 0)))] -+ "" -+ "#" -+ "" -+ [(parallel -+ [(set (reg:CCWZ CC_REGNO) -+ (compare:CCWZ (match_dup 0) -+ (const_int 0))) -+ (clobber (match_dup 1))])] -+ "{ -+ operands[1] = gen_reg_rtx (SImode); -+ }") -+ -+(define_insn "tstdi_or4_d" -+ [(set (reg:CCWZ CC_REGNO) -+ (compare:CCWZ (match_operand:DI 0 "nonimmediate_operand" "rm") -+ (const_int 0))) -+ (clobber (match_operand:SI 1 "ubicom32_data_register_operand" "=d"))] -+ "" -+ "* -+ { -+ operands[2] = gen_lowpart (SImode, operands[0]); -+ operands[3] = gen_highpart_mode (SImode, DImode, operands[0]); -+ -+ if (ubicom32_data_register_operand (operands[0], GET_MODE (operands[0]))) -+ return \"or.4\\t#0, %2, %3\"; -+ -+ return \"move.4\\t%1, %2\;or.4\\t%1, %3, %1\"; -+ }" -+ [(set_attr "length" "8")]) -+ -+(define_expand "cmpdi" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:DI 0 "ubicom32_arith_operand" "") -+ (match_operand:DI 1 "ubicom32_data_register_operand" "")))] -+ "" -+ "{ -+ ubicom32_compare_op0 = operands[0]; -+ ubicom32_compare_op1 = operands[1]; -+ DONE; -+ }") -+ -+(define_insn "cmpdi_sub4subc" -+ [(set (reg CC_REGNO) -+ (compare (match_operand:DI 0 "ubicom32_arith_operand" "rmI") -+ (match_operand:DI 1 "ubicom32_data_register_operand" "d")))] -+ "" -+ "* -+ { -+ operands[2] = gen_lowpart (SImode, operands[0]); -+ operands[3] = gen_lowpart (SImode, operands[1]); -+ operands[4] = gen_highpart_mode (SImode, DImode, operands[0]); -+ operands[5] = gen_highpart_mode (SImode, DImode, operands[1]); -+ -+ return \"sub.4\\t#0, %2, %3\;subc\\t#0, %4, %5\"; -+ }" -+ [(set_attr "length" "8")]) -+ -+; When the combiner runs it doesn't have any insight into whether or not an argument -+; to a compare is spilled to the stack and therefore can't swap the comparison in -+; an attempt to use sub.4/subc more effectively. We peephole this case here. -+; -+(define_peephole2 -+ [(set (match_operand:DI 0 "register_operand" "") -+ (match_operand:DI 1 "ubicom32_arith_operand" "")) -+ (set (match_operand 2 "ubicom32_cc_register_operand" "") -+ (compare (match_operand:DI 3 "ubicom32_data_register_operand" "") -+ (match_dup 0))) -+ (set (pc) -+ (if_then_else (match_operator 4 "comparison_operator" -+ [(match_dup 2) -+ (const_int 0)]) -+ (label_ref (match_operand 5 "" "")) -+ (pc)))] -+ "(peep2_reg_dead_p (2, operands[0]) -+ && peep2_regno_dead_p (3, CC_REGNO))" -+ [(set (match_dup 2) -+ (compare (match_dup 1) -+ (match_dup 3))) -+ (set (pc) -+ (if_then_else (match_op_dup 6 -+ [(match_dup 2) -+ (const_int 0)]) -+ (label_ref (match_dup 5)) -+ (pc)))] -+ "{ -+ rtx cc_reg; -+ -+ cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO); -+ operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])), -+ GET_MODE (operands[4]), -+ cc_reg, -+ const0_rtx); -+ }") -+ -+(define_insn "btst" -+ [(set (reg:CCWZ CC_REGNO) -+ (compare:CCWZ -+ (zero_extract:SI -+ (match_operand:SI 0 "nonimmediate_operand" "rm") -+ (const_int 1) -+ (match_operand:SI 1 "ubicom32_arith_operand" "dM")) -+ (const_int 0)))] -+ "" -+ "btst\\t%0, %1") -+ -+(define_insn "bfextu_ccwz_null" -+ [(set (reg:CCWZ CC_REGNO) -+ (compare:CCWZ -+ (zero_extract:SI -+ (match_operand:SI 0 "nonimmediate_operand" "rm") -+ (match_operand 1 "const_int_operand" "M") -+ (const_int 0)) -+ (const_int 0))) -+ (clobber (match_scratch:SI 2 "=d"))] -+ "" -+ "bfextu\\t%2, %0, %1") -+ -+(define_expand "addqi3" -+ [(parallel -+ [(set (match_operand:QI 0 "memory_operand" "") -+ (plus:QI (match_operand:QI 1 "nonimmediate_operand" "") -+ (match_operand:QI 2 "ubicom32_arith_operand" ""))) -+ (clobber (reg:CC CC_REGNO))])] -+ "(ubicom32_v4)" -+ "{ -+ if (!memory_operand (operands[0], QImode)) -+ FAIL; -+ -+ /* If we have a non-data reg for operand 1 then prefer that over -+ a CONST_INT in operand 2. */ -+ if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])) -+ && CONST_INT_P (operands[2])) -+ operands[2] = copy_to_mode_reg (QImode, operands[2]); -+ -+ if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2])) -+ operands[2] = copy_to_mode_reg (QImode, operands[2]); -+ }") -+ -+(define_insn "addqi3_add1" -+ [(set (match_operand:QI 0 "memory_operand" "=m, m") -+ (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(ubicom32_v4)" -+ "@ -+ add.1\\t%0, %2, %1 -+ add.1\\t%0, %1, %2") -+ -+(define_insn "addqi3_add1_ccszn_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (neg:QI (match_operand:QI 0 "nonimmediate_operand" "%d,rm")) -+ (match_operand:QI 1 "ubicom32_arith_operand" "rmI, d")))] -+ "(ubicom32_v4 -+ && ubicom32_match_cc_mode(insn, CCSZNmode))" -+ "@ -+ add.1\\t#0, %1, %0 -+ add.1\\t#0, %0, %1") -+ -+(define_expand "addhi3" -+ [(parallel -+ [(set (match_operand:HI 0 "memory_operand" "") -+ (plus:HI (match_operand:HI 1 "nonimmediate_operand" "") -+ (match_operand:HI 2 "ubicom32_arith_operand" ""))) -+ (clobber (reg:CC CC_REGNO))])] -+ "" -+ "{ -+ if (!memory_operand (operands[0], HImode)) -+ FAIL; -+ -+ /* If we have a non-data reg for operand 1 then prefer that over -+ a CONST_INT in operand 2. */ -+ if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])) -+ && CONST_INT_P (operands[2])) -+ operands[2] = copy_to_mode_reg (HImode, operands[2]); -+ -+ if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2])) -+ operands[2] = copy_to_mode_reg (HImode, operands[2]); -+ }") -+ -+(define_insn "addhi3_add2" -+ [(set (match_operand:HI 0 "memory_operand" "=m, m") -+ (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "@ -+ add.2\\t%0, %2, %1 -+ add.2\\t%0, %1, %2") -+ -+(define_insn "addhi3_add2_ccszn_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (neg:HI (match_operand:HI 0 "nonimmediate_operand" "%d,rm")) -+ (match_operand:HI 1 "ubicom32_arith_operand" "rmI, d")))] -+ "ubicom32_match_cc_mode(insn, CCSZNmode)" -+ "@ -+ add.2\\t#0, %1, %0 -+ add.2\\t#0, %0, %1") -+ -+(define_expand "addsi3" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "") -+ (plus:SI (match_operand:SI 1 "nonimmediate_operand" "") -+ (match_operand:SI 2 "ubicom32_move_operand" "")))] -+ "" -+ "{ -+ ubicom32_expand_addsi3 (operands); -+ DONE; -+ }") -+ -+; We start with an instruction pattern that can do all sorts of interesting -+; things but we split out any uses of lea or pdec instructions because -+; those instructions don't clobber the condition codes. -+; -+(define_insn_and_split "addsi3_1" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm,rm,rm,rm, rm,rm") -+ (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%a, a, a, a, a, d,rm") -+ (match_operand:SI 2 "ubicom32_move_operand" "L, K, J, P, d,rmI, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "@ -+ # -+ # -+ # -+ # -+ # -+ add.4\\t%0, %2, %1 -+ add.4\\t%0, %1, %2" -+ "(reload_completed -+ && ubicom32_address_register_operand (operands[1], GET_MODE (operands[1])))" -+ [(set (match_dup 0) -+ (plus:SI (match_dup 1) -+ (match_dup 2)))] -+ "" -+) -+ -+(define_insn "addsi3_1_ccwzn" -+ [(set (reg CC_REGNO) -+ (compare -+ (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d")) -+ (const_int 0))) -+ (set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") -+ (plus:SI (match_dup 1) -+ (match_dup 2)))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "@ -+ add.4\\t%0, %2, %1 -+ add.4\\t%0, %1, %2") -+ -+(define_insn "addsi3_1_ccwzn_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (neg:SI (match_operand:SI 0 "nonimmediate_operand" "%d,rm")) -+ (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d")))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "@ -+ add.4\\t#0, %1, %0 -+ add.4\\t#0, %0, %1") -+ -+(define_insn_and_split "addsi3_2" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm,rm,rm,rm,rm") -+ (plus:SI (match_operand:SI 1 "ubicom32_address_register_operand" "%a, a, a, a, a, a") -+ (match_operand:SI 2 "ubicom32_move_operand" "L, K, J, P, d, n")))] -+ "" -+ "@ -+ lea.4\\t%0, %E2(%1) -+ lea.2\\t%0, %E2(%1) -+ lea.1\\t%0, %E2(%1) -+ pdec\\t%0, %n2(%1) -+ lea.1\\t%0, (%1,%2) -+ #" -+ "(reload_completed -+ && ! satisfies_constraint_L (operands[2]) -+ && ! satisfies_constraint_K (operands[2]) -+ && ! satisfies_constraint_J (operands[2]) -+ && ! satisfies_constraint_P (operands[2]) -+ && ! ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))" -+ [(set (reg:SI AUX_DATA_REGNO) -+ (match_dup 2)) -+ (set (match_dup 0) -+ (plus:SI (match_dup 1) -+ (reg:SI AUX_DATA_REGNO)))] -+ "" -+) -+ -+(define_insn "lea_2" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") -+ (plus:SI (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d") -+ (const_int 2)) -+ (match_operand:SI 2 "ubicom32_address_register_operand" "a")))] -+ "" -+ "lea.2\\t%0, (%2,%1)") -+ -+(define_insn "lea_4" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") -+ (plus:SI (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d") -+ (const_int 4)) -+ (match_operand:SI 2 "ubicom32_address_register_operand" "a")))] -+ "" -+ "lea.4\\t%0, (%2,%1)") -+ -+(define_expand "adddi3" -+ [(parallel -+ [(set (match_operand:DI 0 "nonimmediate_operand" "") -+ (plus:DI (match_operand:DI 1 "nonimmediate_operand" "") -+ (match_operand:DI 2 "ubicom32_arith_operand" ""))) -+ (clobber (reg:CC CC_REGNO))])] -+ "" -+ "{ -+ /* If we have a non-data reg for operand 1 then prefer that over -+ a CONST_INT in operand 2. */ -+ if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])) -+ && CONST_INT_P (operands[2])) -+ operands[2] = copy_to_mode_reg (DImode, operands[2]); -+ -+ if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2])) -+ operands[2] = copy_to_mode_reg (DImode, operands[2]); -+ }") -+ -+; We construct a 64-bit add from 32-bit operations. Note that we use the -+; & constraint to prevent overlapping registers being allocated. We do -+; allow identical registers though as that won't break anything. -+; -+(define_insn "adddi3_add4addc" -+ [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,&r,rm, d, m, m") -+ (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%d,rm, 0, 0, d,rm") -+ (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d, d,rmI,rmI, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "* -+ { -+ operands[3] = gen_lowpart (SImode, operands[0]); -+ operands[4] = gen_lowpart (SImode, operands[1]); -+ operands[5] = gen_lowpart (SImode, operands[2]); -+ operands[6] = gen_highpart (SImode, operands[0]); -+ operands[7] = gen_highpart (SImode, operands[1]); -+ operands[8] = gen_highpart_mode (SImode, DImode, operands[2]); -+ -+ if (ubicom32_data_register_operand (operands[2], GET_MODE (operands[2]))) -+ return \"add.4\\t%3, %4, %5\;addc\\t%6, %7, %8\"; -+ -+ return \"add.4\\t%3, %5, %4\;addc\\t%6, %8, %7\"; -+ }" -+ [(set_attr "length" "8")]) -+ -+(define_insn "adddi3_ccwz" -+ [(set (reg CC_REGNO) -+ (compare -+ (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%d,rm, 0, 0, d,rm") -+ (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d, d,rmI,rmI, d")) -+ (const_int 0))) -+ (set (match_operand:DI 0 "nonimmediate_operand" "=&r,&r,rm, d, m, m") -+ (plus:DI (match_dup 1) -+ (match_dup 2)))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "* -+ { -+ operands[3] = gen_lowpart (SImode, operands[0]); -+ operands[6] = gen_highpart (SImode, operands[0]); -+ -+ if (ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))) -+ { -+ operands[4] = gen_lowpart (SImode, operands[1]); -+ operands[5] = gen_lowpart (SImode, operands[2]); -+ operands[7] = gen_highpart (SImode, operands[1]); -+ operands[8] = gen_highpart_mode (SImode, DImode, operands[2]); -+ } -+ else -+ { -+ operands[4] = gen_lowpart (SImode, operands[2]); -+ operands[5] = gen_lowpart (SImode, operands[1]); -+ operands[7] = gen_highpart (SImode, operands[2]); -+ operands[8] = gen_highpart (SImode, operands[1]); -+ } -+ -+ return \"add.4\\t%3, %5, %4\;addc\\t%6, %8, %7\"; -+ }" -+ [(set_attr "length" "8")]) -+ -+(define_insn "adddi3_ccwz_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (neg:DI (match_operand:DI 0 "nonimmediate_operand" "%d,rm")) -+ (match_operand:DI 1 "ubicom32_arith_operand" "rmI, d")))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "* -+ { -+ if (ubicom32_data_register_operand (operands[0], GET_MODE (operands[0]))) -+ { -+ operands[2] = gen_lowpart (SImode, operands[0]); -+ operands[3] = gen_lowpart (SImode, operands[1]); -+ operands[4] = gen_highpart (SImode, operands[0]); -+ operands[5] = gen_highpart_mode (SImode, DImode, operands[1]); -+ } -+ else -+ { -+ operands[2] = gen_lowpart (SImode, operands[1]); -+ operands[3] = gen_lowpart (SImode, operands[0]); -+ operands[4] = gen_highpart (SImode, operands[1]); -+ operands[5] = gen_highpart (SImode, operands[0]); -+ } -+ -+ return \"add.4\\t#0, %3, %2\;addc\\t#0, %5, %4\"; -+ }" -+ [(set_attr "length" "8")]) -+ -+(define_expand "subqi3" -+ [(parallel -+ [(set (match_operand:QI 0 "memory_operand" "") -+ (minus:QI (match_operand:QI 1 "ubicom32_arith_operand" "") -+ (match_operand:QI 2 "ubicom32_data_register_operand" ""))) -+ (clobber (reg:CC CC_REGNO))])] -+ "(ubicom32_v4)" -+ "{ -+ if (!memory_operand (operands[0], QImode)) -+ FAIL; -+ }") -+ -+(define_insn "subqi3_sub1" -+ [(set (match_operand:QI 0 "memory_operand" "=m") -+ (minus:QI (match_operand:QI 1 "ubicom32_arith_operand" "rmI") -+ (match_operand:QI 2 "ubicom32_data_register_operand" "d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(ubicom32_v4)" -+ "sub.1\\t%0, %1, %2") -+ -+(define_expand "subhi3" -+ [(parallel -+ [(set (match_operand:HI 0 "memory_operand" "") -+ (minus:HI (match_operand:HI 1 "ubicom32_arith_operand" "") -+ (match_operand:HI 2 "ubicom32_data_register_operand" ""))) -+ (clobber (reg:CC CC_REGNO))])] -+ "(ubicom32_v4)" -+ "{ -+ if (!memory_operand (operands[0], HImode)) -+ FAIL; -+ }") -+ -+(define_insn "subhi3_sub2" -+ [(set (match_operand:HI 0 "memory_operand" "=m") -+ (minus:HI (match_operand:HI 1 "ubicom32_arith_operand" "rmI") -+ (match_operand:HI 2 "ubicom32_data_register_operand" "d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "sub.2\\t%0, %1, %2") -+ -+(define_insn "subsi3" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") -+ (minus:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI") -+ (match_operand:SI 2 "ubicom32_data_register_operand" "d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "sub.4\\t%0, %1, %2") -+ -+(define_insn "subsi3_ccwz" -+ [(set (reg CC_REGNO) -+ (compare -+ (minus:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI") -+ (match_operand:SI 2 "ubicom32_data_register_operand" "d")) -+ (const_int 0))) -+ (set (match_operand:SI 0 "nonimmediate_operand" "=rm") -+ (minus:SI (match_dup 1) -+ (match_dup 2)))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "sub.4\\t%0, %1, %2") -+ -+; We construct a 64-bit add from 32-bit operations. Note that we use the -+; & constraint to prevent overlapping registers being allocated. We do -+; allow identical registers though as that won't break anything. -+; -+(define_insn "subdi3" -+ [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r, d, m") -+ (minus:DI (match_operand:DI 1 "ubicom32_arith_operand" "rmI,0,rmI,rmI") -+ (match_operand:DI 2 "ubicom32_data_register_operand" "d,d, 0, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "* -+ { -+ operands[3] = gen_lowpart (SImode, operands[0]); -+ operands[4] = gen_lowpart (SImode, operands[1]); -+ operands[5] = gen_lowpart (SImode, operands[2]); -+ operands[6] = gen_highpart (SImode, operands[0]); -+ operands[7] = gen_highpart_mode (SImode, DImode, operands[1]); -+ operands[8] = gen_highpart (SImode, operands[2]); -+ -+ return \"sub.4\\t%3, %4, %5\;subc\\t%6, %7, %8\"; -+ }" -+ [(set_attr "length" "8")]) -+ -+(define_insn "subdi3_ccwz" -+ [(set (reg CC_REGNO) -+ (compare -+ (minus:DI (match_operand:DI 1 "ubicom32_arith_operand" "rmI,rmI") -+ (match_operand:DI 2 "ubicom32_data_register_operand" "d, d")) -+ (const_int 0))) -+ (set (match_operand:DI 0 "nonimmediate_operand" "=&r, m") -+ (minus:DI (match_dup 1) -+ (match_dup 2)))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "* -+ { -+ operands[3] = gen_lowpart (SImode, operands[0]); -+ operands[4] = gen_lowpart (SImode, operands[1]); -+ operands[5] = gen_lowpart (SImode, operands[2]); -+ operands[6] = gen_highpart (SImode, operands[0]); -+ operands[7] = gen_highpart_mode (SImode, DImode, operands[1]); -+ operands[8] = gen_highpart (SImode, operands[2]); -+ -+ return \"sub.4\\t%3, %4, %5\;subc\\t%6, %7, %8\"; -+ }" -+ [(set_attr "length" "8")]) -+ -+;(define_insn "negqi2" -+; [(set (match_operand:QI 0 "nonimmediate_operand" "=rm") -+; (neg:QI (match_operand:QI 1 "ubicom32_data_register_operand" "d"))) -+; (clobber (reg:CC CC_REGNO))] -+; "(ubicom32_v4)" -+; "sub.1\\t%0, #0, %1") -+ -+;(define_insn "neghi2" -+; [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") -+; (neg:HI (match_operand:HI 1 "ubicom32_data_register_operand" "d"))) -+; (clobber (reg:CC CC_REGNO))] -+; "" -+; "sub.2\\t%0, #0, %1") -+ -+(define_insn "negsi2" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") -+ (neg:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "sub.4\\t%0, #0, %1") -+ -+(define_insn_and_split "negdi2" -+ [(set (match_operand:DI 0 "nonimmediate_operand" "=&rm") -+ (neg:DI (match_operand:DI 1 "ubicom32_data_register_operand" "d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "#" -+ "reload_completed" -+ [(parallel [(set (match_dup 0) -+ (minus:DI (const_int 0) -+ (match_dup 1))) -+ (clobber (reg:CC CC_REGNO))])] -+ "" -+ [(set_attr "length" "8")]) -+ -+(define_insn "umulhisi3" -+ [(set (match_operand:SI 0 "ubicom32_acc_lo_register_operand" "=l, l") -+ (mult:SI -+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "%d,rm")) -+ (zero_extend:SI (match_operand:HI 2 "nonimmediate_operand" "rm, d")))) -+ (clobber (reg:HI ACC0_HI_REGNO)) -+ (clobber (reg:HI ACC1_HI_REGNO))] -+ "" -+ "@ -+ mulu\\t%A0, %2, %1 -+ mulu\\t%A0, %1, %2" -+ [(set_attr "type" "mul,mul")]) -+ -+(define_insn "mulhisi3" -+ [(set (match_operand:SI 0 "ubicom32_acc_lo_register_operand" "=l, l") -+ (mult:SI -+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "%d,rm")) -+ (sign_extend:SI (match_operand:HI 2 "nonimmediate_operand" "rm, d")))) -+ (clobber (reg:HI ACC0_HI_REGNO)) -+ (clobber (reg:HI ACC1_HI_REGNO))] -+ "" -+ "@ -+ muls\\t%A0, %2, %1 -+ muls\\t%A0, %1, %2" -+ [(set_attr "type" "mul,mul")]) -+ -+(define_expand "mulsi3" -+ [(set (match_operand:SI 0 "ubicom32_acc_hi_register_operand" "") -+ (mult:SI (match_operand:SI 1 "ubicom32_arith_operand" "") -+ (match_operand:SI 2 "ubicom32_arith_operand" "")))] -+ "" -+ "{ -+ if (ubicom32_emit_mult_sequence (operands)) -+ DONE; -+ }") -+ -+(define_insn "umulsidi3" -+ [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand" "=h, h") -+ (mult:DI -+ (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%d,rm")) -+ (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm, d"))))] -+ "(ubicom32_v4)" -+ "@ -+ mulu.4\\t%A0, %2, %1 -+ mulu.4\\t%A0, %1, %2" -+ [(set_attr "type" "mul,mul")]) -+ -+(define_peephole2 -+ [(set (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "nonimmediate_operand" "")) -+ (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "") -+ (mult:DI -+ (zero_extend:DI (match_dup 0)) -+ (zero_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))))] -+ "(peep2_reg_dead_p (2, operands[0]) -+ || REGNO (operands[0]) == REGNO (operands[2]) -+ || REGNO (operands[0]) == REGNO (operands[2]) + 1) -+ && ! rtx_equal_p (operands[0], operands[3])" -+ [(set (match_dup 2) -+ (mult:DI -+ (zero_extend:DI (match_dup 1)) -+ (zero_extend:DI (match_dup 3))))] -+ "") -+ -+(define_peephole2 -+ [(set (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "nonimmediate_operand" "")) -+ (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "") -+ (mult:DI -+ (zero_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" "")) -+ (zero_extend:DI (match_dup 0))))] -+ "(peep2_reg_dead_p (2, operands[0]) -+ || REGNO (operands[0]) == REGNO (operands[2]) -+ || REGNO (operands[0]) == REGNO (operands[2]) + 1) -+ && ! rtx_equal_p (operands[0], operands[3])" -+ [(set (match_dup 2) -+ (mult:DI -+ (zero_extend:DI (match_dup 1)) -+ (zero_extend:DI (match_dup 3))))] -+ "") -+ -+(define_insn "umulsidi3_const" -+ [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand" "=h") -+ (mult:DI -+ (zero_extend:DI (match_operand:SI 1 "ubicom32_data_register_operand" "%d")) -+ (match_operand 2 "const_int_operand" "I")))] -+ "(ubicom32_v4 && satisfies_constraint_I (operands[2]))" -+ "mulu.4\\t%A0, %2, %1" -+ [(set_attr "type" "mul")]) -+ -+(define_insn "mulsidi3" -+ [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand" "=h, h") -+ (mult:DI -+ (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%d,rm")) -+ (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm, d"))))] -+ "(ubicom32_v4)" -+ "@ -+ muls.4\\t%A0, %2, %1 -+ muls.4\\t%A0, %1, %2" -+ [(set_attr "type" "mul,mul")]) -+ -+(define_peephole2 -+ [(set (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "nonimmediate_operand" "")) -+ (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "") -+ (mult:DI -+ (sign_extend:DI (match_dup 0)) -+ (sign_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))))] -+ "(peep2_reg_dead_p (2, operands[0]) -+ || REGNO (operands[0]) == REGNO (operands[2]) -+ || REGNO (operands[0]) == REGNO (operands[2]) + 1) -+ && ! rtx_equal_p (operands[0], operands[3])" -+ [(set (match_dup 2) -+ (mult:DI -+ (sign_extend:DI (match_dup 1)) -+ (sign_extend:DI (match_dup 3))))] -+ "") -+ -+(define_peephole2 -+ [(set (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "nonimmediate_operand" "")) -+ (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "") -+ (mult:DI -+ (sign_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" "")) -+ (sign_extend:DI (match_dup 0))))] -+ "(peep2_reg_dead_p (2, operands[0]) -+ || REGNO (operands[0]) == REGNO (operands[2]) -+ || REGNO (operands[0]) == REGNO (operands[2]) + 1) -+ && ! rtx_equal_p (operands[0], operands[3])" -+ [(set (match_dup 2) -+ (mult:DI -+ (sign_extend:DI (match_dup 1)) -+ (sign_extend:DI (match_dup 3))))] -+ "") -+ -+(define_insn "mulsidi3_const" -+ [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand" "=h") -+ (mult:DI -+ (sign_extend:DI (match_operand:SI 1 "ubicom32_data_register_operand" "%d")) -+ (match_operand 2 "const_int_operand" "I")))] -+ "(ubicom32_v4 && satisfies_constraint_I (operands[2]))" -+ "muls.4\\t%A0, %2, %1" -+ [(set_attr "type" "mul")]) -+ -+(define_expand "andqi3" -+ [(parallel -+ [(set (match_operand:QI 0 "memory_operand" "") -+ (and:QI (match_operand:QI 1 "nonimmediate_operand" "") -+ (match_operand:QI 2 "ubicom32_arith_operand" ""))) -+ (clobber (reg:CC CC_REGNO))])] -+ "(ubicom32_v4)" -+ "{ -+ if (!memory_operand (operands[0], QImode)) -+ FAIL; -+ -+ /* If we have a non-data reg for operand 1 then prefer that over -+ a CONST_INT in operand 2. */ -+ if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])) -+ && CONST_INT_P (operands[2])) -+ operands[2] = copy_to_mode_reg (QImode, operands[2]); -+ -+ if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2])) -+ operands[2] = copy_to_mode_reg (QImode, operands[2]); -+ }") -+ -+(define_insn "andqi3_and1" -+ [(set (match_operand:QI 0 "memory_operand" "=m, m") -+ (and:QI (match_operand:QI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(ubicom32_v4)" -+ "@ -+ and.1\\t%0, %2, %1 -+ and.1\\t%0, %1, %2") -+ -+(define_insn "andqi3_and1_ccszn" -+ [(set (reg CC_REGNO) -+ (compare -+ (and:QI (match_operand:QI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")) -+ (const_int 0))) -+ (set (match_operand:QI 0 "memory_operand" "=m, m") -+ (and:QI (match_dup 1) -+ (match_dup 2)))] -+ "(ubicom32_v4 -+ && ubicom32_match_cc_mode(insn, CCSZNmode))" -+ "@ -+ and.1\\t%0, %2, %1 -+ and.1\\t%0, %1, %2") -+ -+(define_insn "andqi3_and1_ccszn_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (and:QI (match_operand:QI 0 "nonimmediate_operand" "%d,rm") -+ (match_operand:QI 1 "ubicom32_arith_operand" "rmI, d")) -+ (const_int 0)))] -+ "(ubicom32_v4 -+ && ubicom32_match_cc_mode(insn, CCSZNmode))" -+ "@ -+ and.1\\t#0, %1, %0 -+ and.1\\t#0, %0, %1") -+ -+(define_insn "and1_ccszn_null_1" -+ [(set (reg CC_REGNO) -+ (compare -+ (subreg:QI -+ (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d") -+ (match_operand:SI 1 "ubicom32_arith_operand" "rI")) -+ 3) -+ (const_int 0)))] -+ "(ubicom32_v4 -+ && ubicom32_match_cc_mode(insn, CCSZNmode))" -+ "and.1\\t#0, %1, %0") -+ -+(define_insn "and1_ccszn_null_2" -+ [(set (reg CC_REGNO) -+ (compare -+ (subreg:QI -+ (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d") -+ (subreg:SI -+ (match_operand:QI 1 "memory_operand" "m") -+ 0)) -+ 3) -+ (const_int 0)))] -+ "(ubicom32_v4 -+ && ubicom32_match_cc_mode(insn, CCSZNmode))" -+ "and.1\\t#0, %1, %0") -+ -+(define_insn "and1_ccszn_null_3" -+ [(set (reg CC_REGNO) -+ (compare -+ (subreg:QI -+ (and:SI (subreg:SI -+ (match_operand:QI 0 "memory_operand" "m") -+ 0) -+ (match_operand:SI 1 "ubicom32_data_register_operand" "d")) -+ 3) -+ (const_int 0)))] -+ "(ubicom32_v4 -+ && ubicom32_match_cc_mode(insn, CCSZNmode))" -+ "and.1\\t#0, %0, %1") -+ -+(define_expand "andhi3" -+ [(parallel -+ [(set (match_operand:HI 0 "memory_operand" "") -+ (and:HI (match_operand:HI 1 "nonimmediate_operand" "") -+ (match_operand:HI 2 "ubicom32_arith_operand" ""))) -+ (clobber (reg:CC CC_REGNO))])] -+ "" -+ "{ -+ if (!memory_operand (operands[0], HImode)) -+ FAIL; -+ -+ /* If we have a non-data reg for operand 1 then prefer that over -+ a CONST_INT in operand 2. */ -+ if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])) -+ && CONST_INT_P (operands[2])) -+ operands[2] = copy_to_mode_reg (HImode, operands[2]); -+ -+ if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2])) -+ operands[2] = copy_to_mode_reg (HImode, operands[2]); -+ }") -+ -+(define_insn "andhi3_and2" -+ [(set (match_operand:HI 0 "memory_operand" "=m, m") -+ (and:HI (match_operand:HI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "@ -+ and.2\\t%0, %2, %1 -+ and.2\\t%0, %1, %2") -+ -+(define_insn "andhi3_and2_ccszn" -+ [(set (reg CC_REGNO) -+ (compare -+ (and:HI (match_operand:HI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")) -+ (const_int 0))) -+ (set (match_operand:HI 0 "memory_operand" "=m, m") -+ (and:HI (match_dup 1) -+ (match_dup 2)))] -+ "ubicom32_match_cc_mode(insn, CCSZNmode)" -+ "@ -+ and.2\\t%0, %2, %1 -+ and.2\\t%0, %1, %2") -+ -+(define_insn "andhi3_and2_ccszn_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (and:HI (match_operand:HI 0 "nonimmediate_operand" "%d,rm") -+ (match_operand:HI 1 "ubicom32_arith_operand" "rmI, d")) -+ (const_int 0)))] -+ "ubicom32_match_cc_mode(insn, CCSZNmode)" -+ "@ -+ and.2\\t#0, %1, %0 -+ and.2\\t#0, %0, %1") -+ -+(define_insn "and2_ccszn_null_1" -+ [(set (reg CC_REGNO) -+ (compare -+ (subreg:HI -+ (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d") -+ (match_operand:SI 1 "ubicom32_arith_operand" "rI")) -+ 2) -+ (const_int 0)))] -+ "ubicom32_match_cc_mode(insn, CCSZNmode)" -+ "and.2\\t#0, %1, %0") -+ -+(define_insn "and2_ccszn_null_2" -+ [(set (reg CC_REGNO) -+ (compare -+ (subreg:HI -+ (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d") -+ (subreg:SI -+ (match_operand:HI 1 "memory_operand" "m") -+ 0)) -+ 2) -+ (const_int 0)))] -+ "ubicom32_match_cc_mode(insn, CCSZNmode)" -+ "and.2\\t#0, %1, %0") -+ -+(define_insn "and2_ccszn_null_3" -+ [(set (reg CC_REGNO) -+ (compare -+ (subreg:HI -+ (and:SI (subreg:SI -+ (match_operand:HI 0 "memory_operand" "m") -+ 0) -+ (match_operand:SI 1 "ubicom32_data_register_operand" "d")) -+ 2) -+ (const_int 0)))] -+ "ubicom32_match_cc_mode(insn, CCSZNmode)" -+ "and.2\\t#0, %0, %1") -+ -+(define_expand "andsi3" -+ [(parallel -+ [(set (match_operand:SI 0 "nonimmediate_operand" "") -+ (and:SI (match_operand:SI 1 "nonimmediate_operand" "") -+ (match_operand:SI 2 "ubicom32_and_or_si3_operand" ""))) -+ (clobber (reg:CC CC_REGNO))])] -+ "" -+ "{ -+ do -+ { -+ /* Is this a bfextu? */ -+ if (ubicom32_data_register_operand (operands[0], SImode) -+ && CONST_INT_P (operands[2]) -+ && exact_log2 (INTVAL (operands[2]) + 1) != -1) -+ break; -+ -+ /* Is this a bclr? */ -+ if (CONST_INT_P (operands[2]) -+ && exact_log2 (~INTVAL (operands[2])) != -1) -+ break; -+ -+ /* Must be an and.4 */ -+ if (!ubicom32_data_register_operand (operands[1], SImode)) -+ operands[1] = copy_to_mode_reg (SImode, operands[1]); -+ -+ if (!ubicom32_arith_operand (operands[2], SImode)) -+ operands[2] = copy_to_mode_reg (SImode, operands[2]); -+ } -+ while (0); -+ }") -+ -+(define_insn "andsi3_bfextu" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (and:SI (match_operand:SI 1 "nonimmediate_operand" "%rm") -+ (match_operand:SI 2 "const_int_operand" "O"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(satisfies_constraint_O (operands[2]))" -+ "* -+ { -+ operands[3] = GEN_INT (exact_log2 (INTVAL (operands[2]) + 1)); -+ -+ return \"bfextu\\t%0, %1, %3\"; -+ }") -+ -+(define_insn "andsi3_bfextu_ccwz" -+ [(set (reg CC_REGNO) -+ (compare -+ (and:SI (match_operand:SI 1 "nonimmediate_operand" "%rm") -+ (match_operand:SI 2 "const_int_operand" "O")) -+ (const_int 0))) -+ (set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (and:SI (match_dup 1) -+ (match_dup 2)))] -+ "(satisfies_constraint_O (operands[2]) -+ && ubicom32_match_cc_mode(insn, CCWZmode))" -+ "* -+ { -+ operands[3] = GEN_INT (exact_log2 (INTVAL (operands[2]) + 1)); -+ -+ return \"bfextu\\t%0, %1, %3\"; -+ }") -+ -+(define_insn "andsi3_bfextu_ccwz_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm") -+ (match_operand:SI 1 "const_int_operand" "O")) -+ (const_int 0))) -+ (clobber (match_scratch:SI 2 "=d"))] -+ "(satisfies_constraint_O (operands[1]) -+ && ubicom32_match_cc_mode(insn, CCWZmode))" -+ "* -+ { -+ operands[3] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); -+ -+ return \"bfextu\\t%2, %0, %3\"; -+ }") -+ -+(define_insn "andsi3_bclr" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") -+ (and:SI (match_operand:SI 1 "ubicom32_arith_operand" "%rmI") -+ (match_operand:SI 2 "const_int_operand" "n"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(exact_log2 (~INTVAL (operands[2])) != -1)" -+ "bclr\\t%0, %1, #%D2") -+ -+(define_insn "andsi3_and4" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") -+ (and:SI (match_operand:SI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "@ -+ and.4\\t%0, %2, %1 -+ and.4\\t%0, %1, %2") -+ -+(define_insn "andsi3_and4_ccwzn" -+ [(set (reg CC_REGNO) -+ (compare -+ (and:SI (match_operand:SI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d")) -+ (const_int 0))) -+ (set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") -+ (and:SI (match_dup 1) -+ (match_dup 2)))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "@ -+ and.4\\t%0, %2, %1 -+ and.4\\t%0, %1, %2") -+ -+(define_insn "andsi3_and4_ccwzn_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (and:SI (match_operand:SI 0 "nonimmediate_operand" "%d,rm") -+ (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d")) -+ (const_int 0)))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "@ -+ and.4\\t#0, %1, %0 -+ and.4\\t#0, %0, %1") -+ -+(define_insn "andsi3_lsr4_ccwz_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm") -+ (match_operand:SI 1 "const_int_operand" "n")) -+ (const_int 0))) -+ (clobber (match_scratch:SI 2 "=d"))] -+ "(exact_log2 ((~(INTVAL (operands[1]))) + 1) != -1 -+ && ubicom32_match_cc_mode(insn, CCWZmode))" -+ "* -+ { -+ operands[3] = GEN_INT (exact_log2 ((~(INTVAL (operands[1]))) + 1)); -+ -+ return \"lsr.4\\t%2, %0, %3\"; -+ }") -+ -+; We really would like the combiner to recognize this scenario and deal with -+; it but unfortunately it tries to canonicalize zero_extract ops on MEMs -+; into QImode operations and we can't match them in any useful way. -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "register_operand" "") -+ (match_operand:SI 1 "const_int_operand" "")) -+ (set (reg:CCWZ CC_REGNO) -+ (compare:CCWZ -+ (and:SI (match_operand:SI 2 "nonimmediate_operand" "") -+ (match_dup 0)) -+ (const_int 0)))] -+ "(exact_log2 (INTVAL (operands[1])) != -1 -+ && peep2_reg_dead_p (2, operands[0]))" -+ [(set (reg:CCWZ CC_REGNO) -+ (compare:CCWZ -+ (zero_extract:SI -+ (match_dup 2) -+ (const_int 1) -+ (match_dup 3)) -+ (const_int 0)))] -+ "{ -+ operands[3] = GEN_INT (exact_log2 (INTVAL (operands[1]))); -+ }") -+ -+(define_expand "anddi3" -+ [(parallel -+ [(set (match_operand:DI 0 "nonimmediate_operand" "") -+ (and:DI (match_operand:DI 1 "nonimmediate_operand" "") -+ (match_operand:DI 2 "ubicom32_arith_operand" ""))) -+ (clobber (reg:CC CC_REGNO))])] -+ "" -+ "{ -+ /* If we have a non-data reg for operand 1 then prefer that over -+ a CONST_INT in operand 2. */ -+ if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])) -+ && CONST_INT_P (operands[2])) -+ operands[2] = copy_to_mode_reg (DImode, operands[2]); -+ -+ if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2])) -+ operands[2] = copy_to_mode_reg (DImode, operands[2]); -+ }") -+ -+(define_insn_and_split "anddi3_and4" -+ [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,&r, d,rm, m, m") -+ (and:DI (match_operand:DI 1 "nonimmediate_operand" "%d,rm, 0, 0, d,rm") -+ (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d,rmI, d,rmI, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "#" -+ "reload_completed" -+ [(parallel [(set (match_dup 3) -+ (and:SI (match_dup 4) -+ (match_dup 5))) -+ (clobber (reg:CC CC_REGNO))]) -+ (parallel [(set (match_dup 6) -+ (and:SI (match_dup 7) -+ (match_dup 8))) -+ (clobber (reg:CC CC_REGNO))])] -+ "{ -+ operands[3] = gen_lowpart (SImode, operands[0]); -+ operands[4] = gen_lowpart (SImode, operands[1]); -+ operands[5] = gen_lowpart (SImode, operands[2]); -+ operands[6] = gen_highpart (SImode, operands[0]); -+ operands[7] = gen_highpart (SImode, operands[1]); -+ operands[8] = gen_highpart_mode (SImode, DImode, operands[2]); -+ }" -+ [(set_attr "length" "8")]) -+ -+(define_expand "iorqi3" -+ [(parallel -+ [(set (match_operand:QI 0 "memory_operand" "") -+ (ior:QI (match_operand:QI 1 "nonimmediate_operand" "") -+ (match_operand:QI 2 "ubicom32_arith_operand" ""))) -+ (clobber (reg:CC CC_REGNO))])] -+ "(ubicom32_v4)" -+ "{ -+ if (!memory_operand (operands[0], QImode)) -+ FAIL; -+ -+ /* If we have a non-data reg for operand 1 then prefer that over -+ a CONST_INT in operand 2. */ -+ if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])) -+ && CONST_INT_P (operands[2])) -+ operands[2] = copy_to_mode_reg (QImode, operands[2]); -+ -+ if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2])) -+ operands[2] = copy_to_mode_reg (QImode, operands[2]); -+ }") -+ -+(define_insn "iorqi3_or1" -+ [(set (match_operand:QI 0 "memory_operand" "=m, m") -+ (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(ubicom32_v4)" -+ "@ -+ or.1\\t%0, %2, %1 -+ or.1\\t%0, %1, %2") -+ -+(define_expand "iorhi3" -+ [(parallel -+ [(set (match_operand:HI 0 "memory_operand" "") -+ (ior:HI (match_operand:HI 1 "nonimmediate_operand" "") -+ (match_operand:HI 2 "ubicom32_arith_operand" ""))) -+ (clobber (reg:CC CC_REGNO))])] -+ "" -+ "{ -+ if (!memory_operand (operands[0], HImode)) -+ FAIL; -+ -+ /* If we have a non-data reg for operand 1 then prefer that over -+ a CONST_INT in operand 2. */ -+ if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])) -+ && CONST_INT_P (operands[2])) -+ operands[2] = copy_to_mode_reg (HImode, operands[2]); -+ -+ if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2])) -+ operands[2] = copy_to_mode_reg (HImode, operands[2]); -+ }") -+ -+(define_insn "iorhi3_or2" -+ [(set (match_operand:HI 0 "memory_operand" "=m, m") -+ (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "@ -+ or.2\\t%0, %2, %1 -+ or.2\\t%0, %1, %2") -+ -+(define_expand "iorsi3" -+ [(parallel -+ [(set (match_operand:SI 0 "nonimmediate_operand" "") -+ (ior:SI (match_operand:SI 1 "nonimmediate_operand" "") -+ (match_operand:SI 2 "ubicom32_and_or_si3_operand" ""))) -+ (clobber (reg:CC CC_REGNO))])] -+ "" -+ "{ -+ do -+ { -+ /* Is this a bset? */ -+ if (CONST_INT_P (operands[2]) -+ && exact_log2 (INTVAL (operands[2])) != -1) -+ break; -+ -+ /* Must be an or.4 */ -+ if (!ubicom32_data_register_operand (operands[1], SImode)) -+ operands[1] = copy_to_mode_reg (SImode, operands[1]); -+ -+ if (!ubicom32_arith_operand (operands[2], SImode)) -+ operands[2] = copy_to_mode_reg (SImode, operands[2]); -+ } -+ while (0); -+ }") -+ -+(define_insn "iorsi3_bset" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") -+ (ior:SI (match_operand:SI 1 "ubicom32_arith_operand" "%rmI") -+ (match_operand 2 "const_int_operand" "n"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(exact_log2 (INTVAL (operands[2])) != -1)" -+ "bset\\t%0, %1, #%d2") -+ -+(define_insn "iorsi3_or4" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") -+ (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "@ -+ or.4\\t%0, %2, %1 -+ or.4\\t%0, %1, %2") -+ -+(define_insn "iorsi3_ccwzn" -+ [(set (reg CC_REGNO) -+ (compare -+ (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d")) -+ (const_int 0))) -+ (set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") -+ (ior:SI (match_dup 1) -+ (match_dup 2)))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "@ -+ or.4\\t%0, %2, %1 -+ or.4\\t%0, %1, %2") -+ -+(define_insn "iorsi3_ccwzn_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (ior:SI (match_operand:SI 0 "nonimmediate_operand" "%d,rm") -+ (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d")) -+ (const_int 0)))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "@ -+ or.4\\t#0, %1, %0 -+ or.4\\t#0, %0, %1") -+ -+(define_expand "iordi3" -+ [(parallel -+ [(set (match_operand:DI 0 "nonimmediate_operand" "") -+ (ior:DI (match_operand:DI 1 "nonimmediate_operand" "") -+ (match_operand:DI 2 "ubicom32_arith_operand" ""))) -+ (clobber (reg:CC CC_REGNO))])] -+ "" -+ "{ -+ /* If we have a non-data reg for operand 1 then prefer that over -+ a CONST_INT in operand 2. */ -+ if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])) -+ && CONST_INT_P (operands[2])) -+ operands[2] = copy_to_mode_reg (DImode, operands[2]); -+ -+ if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2])) -+ operands[2] = copy_to_mode_reg (DImode, operands[2]); -+ }") -+ -+(define_insn_and_split "iordi3_or4" -+ [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,&r, d,rm, m, m") -+ (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%d,rm, 0, 0, d,rm") -+ (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d,rmI, d,rmI, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "#" -+ "reload_completed" -+ [(parallel [(set (match_dup 3) -+ (ior:SI (match_dup 4) -+ (match_dup 5))) -+ (clobber (reg:CC CC_REGNO))]) -+ (parallel [(set (match_dup 6) -+ (ior:SI (match_dup 7) -+ (match_dup 8))) -+ (clobber (reg:CC CC_REGNO))])] -+ "{ -+ operands[3] = gen_lowpart (SImode, operands[0]); -+ operands[4] = gen_lowpart (SImode, operands[1]); -+ operands[5] = gen_lowpart (SImode, operands[2]); -+ operands[6] = gen_highpart (SImode, operands[0]); -+ operands[7] = gen_highpart (SImode, operands[1]); -+ operands[8] = gen_highpart_mode (SImode, DImode, operands[2]); -+ }" -+ [(set_attr "length" "8")]) -+ -+(define_expand "xorqi3" -+ [(parallel -+ [(set (match_operand:QI 0 "memory_operand" "") -+ (xor:QI (match_operand:QI 1 "nonimmediate_operand" "") -+ (match_operand:QI 2 "ubicom32_arith_operand" ""))) -+ (clobber (reg:CC CC_REGNO))])] -+ "(ubicom32_v4)" -+ "{ -+ if (!memory_operand (operands[0], QImode)) -+ FAIL; -+ -+ /* If we have a non-data reg for operand 1 then prefer that over -+ a CONST_INT in operand 2. */ -+ if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])) -+ && CONST_INT_P (operands[2])) -+ operands[2] = copy_to_mode_reg (QImode, operands[2]); -+ -+ if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2])) -+ operands[2] = copy_to_mode_reg (QImode, operands[2]); -+ }") -+ -+(define_insn "xorqi3_xor1" -+ [(set (match_operand:QI 0 "memory_operand" "=m, m") -+ (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(ubicom32_v4)" -+ "@ -+ xor.1\\t%0, %2, %1 -+ xor.1\\t%0, %1, %2") -+ -+(define_insn "xorqi3_xor1_ccszn" -+ [(set (reg CC_REGNO) -+ (compare -+ (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")) -+ (const_int 0))) -+ (set (match_operand:QI 0 "memory_operand" "=m, m") -+ (xor:QI (match_dup 1) -+ (match_dup 2)))] -+ "(ubicom32_v4 -+ && ubicom32_match_cc_mode(insn, CCSZNmode))" -+ "@ -+ xor.1\\t%0, %2, %1 -+ xor.1\\t%0, %1, %2") -+ -+(define_insn "xorqi3_xor1_ccszn_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (xor:QI (match_operand:QI 0 "nonimmediate_operand" "%d,rm") -+ (match_operand:QI 1 "ubicom32_arith_operand" "rmI, d")) -+ (const_int 0)))] -+ "(ubicom32_v4 -+ && ubicom32_match_cc_mode(insn, CCSZNmode))" -+ "@ -+ xor.1\\t#0, %1, %0 -+ xor.1\\t#0, %0, %1") -+ -+(define_insn "xor1_ccszn_null_1" -+ [(set (reg CC_REGNO) -+ (compare -+ (subreg:QI -+ (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d") -+ (match_operand:SI 1 "ubicom32_arith_operand" "rI")) -+ 3) -+ (const_int 0)))] -+ "(ubicom32_v4 -+ && ubicom32_match_cc_mode(insn, CCSZNmode))" -+ "xor.1\\t#0, %1, %0") -+ -+(define_insn "xor1_ccszn_null_2" -+ [(set (reg CC_REGNO) -+ (compare -+ (subreg:QI -+ (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d") -+ (subreg:SI -+ (match_operand:QI 1 "memory_operand" "m") -+ 0)) -+ 3) -+ (const_int 0)))] -+ "(ubicom32_v4 -+ && ubicom32_match_cc_mode(insn, CCSZNmode))" -+ "xor.1\\t#0, %1, %0") -+ -+(define_insn "xor1_ccwzn_null_3" -+ [(set (reg CC_REGNO) -+ (compare -+ (subreg:QI -+ (xor:SI (subreg:SI -+ (match_operand:QI 0 "memory_operand" "m") -+ 0) -+ (match_operand:SI 1 "ubicom32_data_register_operand" "d")) -+ 3) -+ (const_int 0)))] -+ "(ubicom32_v4 -+ && ubicom32_match_cc_mode(insn, CCSZNmode))" -+ "xor.1\\t#0, %0, %1") -+ -+(define_expand "xorhi3" -+ [(parallel -+ [(set (match_operand:HI 0 "memory_operand" "") -+ (xor:HI (match_operand:HI 1 "nonimmediate_operand" "") -+ (match_operand:HI 2 "ubicom32_arith_operand" ""))) -+ (clobber (reg:CC CC_REGNO))])] -+ "" -+ "{ -+ if (!memory_operand (operands[0], HImode)) -+ FAIL; -+ -+ /* If we have a non-data reg for operand 1 then prefer that over -+ a CONST_INT in operand 2. */ -+ if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])) -+ && CONST_INT_P (operands[2])) -+ operands[2] = copy_to_mode_reg (HImode, operands[2]); -+ -+ if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2])) -+ operands[2] = copy_to_mode_reg (HImode, operands[2]); -+ }") -+ -+(define_insn "xorhi3_xor2" -+ [(set (match_operand:HI 0 "memory_operand" "=m, m") -+ (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "@ -+ xor.2\\t%0, %2, %1 -+ xor.2\\t%0, %1, %2") -+ -+(define_insn "xorhi3_xor2_ccszn" -+ [(set (reg CC_REGNO) -+ (compare -+ (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")) -+ (const_int 0))) -+ (set (match_operand:HI 0 "memory_operand" "=m, m") -+ (xor:HI (match_dup 1) -+ (match_dup 2)))] -+ "ubicom32_match_cc_mode(insn, CCSZNmode)" -+ "@ -+ xor.2\\t%0, %2, %1 -+ xor.2\\t%0, %1, %2") -+ -+(define_insn "xorhi3_xor2_ccszn_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (xor:HI (match_operand:HI 0 "nonimmediate_operand" "%d,rm") -+ (match_operand:HI 1 "ubicom32_arith_operand" "rmI, d")) -+ (const_int 0)))] -+ "ubicom32_match_cc_mode(insn, CCSZNmode)" -+ "@ -+ xor.2\\t#0, %1, %0 -+ xor.2\\t#0, %0, %1") -+ -+(define_insn "xor2_ccszn_null_1" -+ [(set (reg CC_REGNO) -+ (compare -+ (subreg:HI -+ (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d") -+ (match_operand:SI 1 "ubicom32_arith_operand" "rI")) -+ 2) -+ (const_int 0)))] -+ "ubicom32_match_cc_mode(insn, CCSZNmode)" -+ "xor.2\\t#0, %1, %0") -+ -+(define_insn "xor2_ccszn_null_2" -+ [(set (reg CC_REGNO) -+ (compare -+ (subreg:HI -+ (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d") -+ (subreg:SI -+ (match_operand:HI 1 "memory_operand" "m") -+ 0)) -+ 2) -+ (const_int 0)))] -+ "ubicom32_match_cc_mode(insn, CCSZNmode)" -+ "xor.2\\t#0, %1, %0") -+ -+(define_insn "xor2_ccszn_null_3" -+ [(set (reg CC_REGNO) -+ (compare -+ (subreg:HI -+ (xor:SI (subreg:SI -+ (match_operand:HI 0 "memory_operand" "m") -+ 0) -+ (match_operand:SI 1 "ubicom32_data_register_operand" "d")) -+ 2) -+ (const_int 0)))] -+ "ubicom32_match_cc_mode(insn, CCSZNmode)" -+ "xor.2\\t#0, %0, %1") -+ -+(define_insn "xorsi3" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") -+ (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "@ -+ xor.4\\t%0, %2, %1 -+ xor.4\\t%0, %1, %2") -+ -+(define_insn "xorsi3_ccwzn" -+ [(set (reg CC_REGNO) -+ (compare -+ (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%d,rm") -+ (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d")) -+ (const_int 0))) -+ (set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm") -+ (xor:SI (match_dup 1) -+ (match_dup 2)))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "@ -+ xor.4\\t%0, %2, %1 -+ xor.4\\t%0, %1, %2") -+ -+(define_insn "xorsi3_ccwzn_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (xor:SI (match_operand:SI 0 "nonimmediate_operand" "%d,rm") -+ (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d")) -+ (const_int 0)))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "@ -+ xor.4\\t#0, %1, %0 -+ xor.4\\t#0, %0, %1") -+ -+(define_expand "xordi3" -+ [(parallel -+ [(set (match_operand:DI 0 "nonimmediate_operand" "") -+ (xor:DI (match_operand:DI 1 "nonimmediate_operand" "") -+ (match_operand:DI 2 "ubicom32_arith_operand" ""))) -+ (clobber (reg:CC CC_REGNO))])] -+ "" -+ "{ -+ /* If we have a non-data reg for operand 1 then prefer that over -+ a CONST_INT in operand 2. */ -+ if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])) -+ && CONST_INT_P (operands[2])) -+ operands[2] = copy_to_mode_reg (DImode, operands[2]); -+ -+ if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2])) -+ operands[2] = copy_to_mode_reg (DImode, operands[2]); -+ }") -+ -+(define_insn_and_split "xordi3_xor4" -+ [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,&r, d,rm, m, m") -+ (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%d,rm, 0, 0, d,rm") -+ (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d,rmI, d,rmI, d"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "#" -+ "reload_completed" -+ [(parallel [(set (match_dup 3) -+ (xor:SI (match_dup 4) -+ (match_dup 5))) -+ (clobber (reg:CC CC_REGNO))]) -+ (parallel [(set (match_dup 6) -+ (xor:SI (match_dup 7) -+ (match_dup 8))) -+ (clobber (reg:CC CC_REGNO))])] -+ "{ -+ operands[3] = gen_lowpart (SImode, operands[0]); -+ operands[4] = gen_lowpart (SImode, operands[1]); -+ operands[5] = gen_lowpart (SImode, operands[2]); -+ operands[6] = gen_highpart (SImode, operands[0]); -+ operands[7] = gen_highpart (SImode, operands[1]); -+ operands[8] = gen_highpart_mode (SImode, DImode, operands[2]); -+ }" -+ [(set_attr "length" "8")]) -+ -+(define_insn "not2_2" -+ [(set (match_operand:HI 0 "memory_operand" "=m") -+ (subreg:HI -+ (not:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")) -+ 2)) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "not.2\\t%0, %1") -+ -+(define_insn "one_cmplsi2" -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") -+ (not:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "not.4\\t%0, %1") -+ -+(define_insn "one_cmplsi2_ccwzn" -+ [(set (reg CC_REGNO) -+ (compare -+ (not:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")) -+ (const_int 0))) -+ (set (match_operand:SI 0 "nonimmediate_operand" "=rm") -+ (not:SI (match_dup 1)))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "not.4\\t%0, %1") -+ -+(define_insn "one_cmplsi2_ccwzn_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (not:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmI")) -+ (const_int 0)))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "not.4\\t#0, %0") -+ -+(define_insn_and_split "one_cmpldi2" -+ [(set (match_operand:DI 0 "nonimmediate_operand" "=&rm") -+ (not:DI (match_operand:DI 1 "nonimmediate_operand" "rmI0"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "#" -+ "" -+ [(parallel [(set (match_dup 2) -+ (not:SI (match_dup 3))) -+ (clobber (reg:CC CC_REGNO))]) -+ (parallel [(set (match_dup 4) -+ (not:SI (match_dup 5))) -+ (clobber (reg:CC CC_REGNO))])] -+ "{ -+ operands[2] = gen_lowpart (SImode, operands[0]); -+ operands[3] = gen_lowpart (SImode, operands[1]); -+ operands[4] = gen_highpart (SImode, operands[0]); -+ operands[5] = gen_highpart (SImode, operands[1]); -+ }" -+ [(set_attr "length" "8")]) -+ -+; Conditional jump instructions -+ -+(define_expand "beq" -+ [(set (pc) -+ (if_then_else (eq (match_dup 1) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+ "{ -+ operands[1] = ubicom32_gen_compare_reg (EQ, ubicom32_compare_op0, -+ ubicom32_compare_op1); -+ }") -+ -+(define_expand "bne" -+ [(set (pc) -+ (if_then_else (ne (match_dup 1) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+ "{ -+ operands[1] = ubicom32_gen_compare_reg (NE, ubicom32_compare_op0, -+ ubicom32_compare_op1); -+ }") -+ -+(define_expand "bgt" -+ [(set (pc) -+ (if_then_else (gt (match_dup 1) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+ "{ -+ operands[1] = ubicom32_gen_compare_reg (GT, ubicom32_compare_op0, -+ ubicom32_compare_op1); -+ }") -+ -+(define_expand "ble" -+ [(set (pc) -+ (if_then_else (le (match_dup 1) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+ "{ -+ operands[1] = ubicom32_gen_compare_reg (LE, ubicom32_compare_op0, -+ ubicom32_compare_op1); -+ }") -+ -+(define_expand "bge" -+ [(set (pc) -+ (if_then_else (ge (match_dup 1) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+ "{ -+ operands[1] = ubicom32_gen_compare_reg (GE, ubicom32_compare_op0, -+ ubicom32_compare_op1); -+ }") -+ -+(define_expand "blt" -+ [(set (pc) -+ (if_then_else (lt (match_dup 1) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+ "{ -+ operands[1] = ubicom32_gen_compare_reg (LT, ubicom32_compare_op0, -+ ubicom32_compare_op1); -+ }") -+ -+(define_expand "bgtu" -+ [(set (pc) -+ (if_then_else (gtu (match_dup 1) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+ "{ -+ operands[1] = ubicom32_gen_compare_reg (GTU, ubicom32_compare_op0, -+ ubicom32_compare_op1); -+ }") -+ -+(define_expand "bleu" -+ [(set (pc) -+ (if_then_else (leu (match_dup 1) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+ "{ -+ operands[1] = ubicom32_gen_compare_reg (LEU, ubicom32_compare_op0, -+ ubicom32_compare_op1); -+ }") -+ -+(define_expand "bgeu" -+ [(set (pc) -+ (if_then_else (geu (match_dup 1) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+ "{ -+ operands[1] = ubicom32_gen_compare_reg (GEU, ubicom32_compare_op0, -+ ubicom32_compare_op1); -+ }") -+ -+(define_expand "bltu" -+ [(set (pc) -+ (if_then_else (ltu (match_dup 1) -+ (const_int 0)) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+ "{ -+ operands[1] = ubicom32_gen_compare_reg (LTU, ubicom32_compare_op0, -+ ubicom32_compare_op1); -+ }") -+ -+(define_insn "jcc" -+ [(set (pc) -+ (if_then_else (match_operator 1 "comparison_operator" -+ [(match_operand 2 "ubicom32_cc_register_operand" "") -+ (const_int 0)]) -+ (label_ref (match_operand 0 "" "")) -+ (pc)))] -+ "" -+ "* -+ { -+ ubicom32_output_cond_jump (insn, operands[1], operands[0]); -+ return \"\"; -+ }") -+ -+; Reverse branch - reverse our comparison condition so that we can -+; branch in the opposite sense. -+; -+(define_insn_and_split "jcc_reverse" -+ [(set (pc) -+ (if_then_else (match_operator 1 "comparison_operator" -+ [(match_operand 2 "ubicom32_cc_register_operand" "") -+ (const_int 0)]) -+ (pc) -+ (label_ref (match_operand 0 "" ""))))] -+ "" -+ "#" -+ "reload_completed" -+ [(set (pc) -+ (if_then_else (match_dup 3) -+ (label_ref (match_dup 0)) -+ (pc)))] -+ "{ -+ rtx cc_reg; -+ -+ cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO); -+ operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])), -+ GET_MODE (operands[1]), -+ cc_reg, -+ const0_rtx); -+ }") -+ -+(define_insn "jump" -+ [(set (pc) -+ (label_ref (match_operand 0 "" "")))] -+ "" -+ "jmpt\\t%l0") -+ -+(define_expand "indirect_jump" -+ [(parallel [(set (pc) -+ (match_operand:SI 0 "register_operand" "")) -+ (clobber (match_dup 0))])] -+ "" -+ "") -+ -+(define_insn "indirect_jump_internal" -+ [(set (pc) -+ (match_operand:SI 0 "register_operand" "a")) -+ (clobber (match_dup 0))] -+ "" -+ "calli\\t%0,0(%0)") -+ -+; Program Space: The table contains instructions, typically jumps. -+; CALL An,TABLE_SIZE(PC) ;An = Jump Table Base Address. -+; <Jump Table is Here> ;An -> Here. -+; LEA Ak, (An,Dn) ;Ak -> Table Entry -+; JMP/CALL (Ak) -+ -+(define_expand "tablejump" -+ [(parallel [(set (pc) -+ (match_operand:SI 0 "nonimmediate_operand" "")) -+ (use (label_ref (match_operand 1 "" "")))])] -+ "" -+ "") -+ -+(define_insn "tablejump_internal" -+ [(set (pc) -+ (match_operand:SI 0 "nonimmediate_operand" "rm")) -+ (use (label_ref (match_operand 1 "" "")))] -+ "" -+ "ret\\t%0") -+ -+; Call subroutine with no return value. -+; -+(define_expand "call" -+ [(call (match_operand:QI 0 "general_operand" "") -+ (match_operand:SI 1 "general_operand" ""))] -+ "" -+ "{ -+ if (TARGET_FDPIC) -+ { -+ ubicom32_expand_call_fdpic (operands); -+ DONE; -+ } -+ -+ if (! ubicom32_call_address_operand (XEXP (operands[0], 0), VOIDmode)) -+ XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0)); -+ }") -+ -+; We expand to a simple form that doesn't clobber the link register and -+; then split to a form that does. This allows the RTL optimizers that -+; run before the splitter to have the opportunity to eliminate the call -+; without marking A5 as being clobbered and this in turn avoids saves -+; and returns in a number of cases. -+; -+(define_insn_and_split "call_1" -+ [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S")) -+ (match_operand:SI 1 "general_operand" "g,g"))] -+ "! TARGET_FDPIC" -+ "#" -+ "" -+ [(parallel -+ [(call (mem:QI (match_dup 0)) -+ (match_dup 1)) -+ (clobber (reg:SI LINK_REGNO))])] -+ "") -+ -+(define_insn "call_slow" -+ [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S")) -+ (match_operand:SI 1 "general_operand" "g,g")) -+ (clobber (reg:SI LINK_REGNO))] -+ "(! TARGET_FDPIC && ! TARGET_FASTCALL)" -+ "@ -+ calli\\ta5, 0(%0) -+ moveai\\ta5, #%%hi(%C0)\;calli\\ta5, %%lo(%C0)(a5)") -+ -+(define_insn "call_fast" -+ [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S")) -+ (match_operand:SI 1 "general_operand" "g,g")) -+ (clobber (reg:SI LINK_REGNO))] -+ "(! TARGET_FDPIC && TARGET_FASTCALL)" -+ "@ -+ calli\\ta5, 0(%0) -+ call\\ta5, %C0") -+ -+; We expand to a simple form that doesn't clobber the link register and -+; then split to a form that does. This allows the RTL optimizers that -+; run before the splitter to have the opportunity to eliminate the call -+; without marking A5 as being clobbered and this in turn avoids saves -+; and returns in a number of cases. -+; -+(define_insn_and_split "call_fdpic" -+ [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S")) -+ (match_operand:SI 1 "general_operand" "g,g")) -+ (use (match_operand:SI 2 "ubicom32_fdpic_operand" "Z,Z"))] -+ "TARGET_FDPIC" -+ "#" -+ "" -+ [(parallel -+ [(call (mem:QI (match_dup 0)) -+ (match_dup 1)) -+ (use (match_dup 2)) -+ (clobber (reg:SI LINK_REGNO))])] -+ "") -+ -+(define_insn "call_fdpic_clobber" -+ [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S")) -+ (match_operand:SI 1 "general_operand" "g,g")) -+ (use (match_operand:SI 2 "ubicom32_fdpic_operand" "Z,Z")) -+ (clobber (reg:SI LINK_REGNO))] -+ "TARGET_FDPIC" -+ "@ -+ move.4\\ta5, 0(%0)\;move.4\\t%2, 4(%0)\;calli\\ta5, 0(a5) -+ call\\ta5, %C0") -+ -+; Call subroutine, returning value in operand 0 -+; (which must be a hard register). -+; -+(define_expand "call_value" -+ [(set (match_operand 0 "" "") -+ (call (match_operand:QI 1 "general_operand" "") -+ (match_operand:SI 2 "general_operand" "")))] -+ "" -+ "{ -+ if (TARGET_FDPIC) -+ { -+ ubicom32_expand_call_value_fdpic (operands); -+ DONE; -+ } -+ -+ if (! ubicom32_call_address_operand (XEXP (operands[1], 0), VOIDmode)) -+ XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0)); -+ }") -+ -+; We expand to a simple form that doesn't clobber the link register and -+; then split to a form that does. This allows the RTL optimizers that -+; run before the splitter to have the opportunity to eliminate the call -+; without marking A5 as being clobbered and this in turn avoids saves -+; and returns in a number of cases. -+; -+(define_insn_and_split "call_value_1" -+ [(set (match_operand 0 "register_operand" "=r,r") -+ (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S")) -+ (match_operand:SI 2 "general_operand" "g,g")))] -+ "! TARGET_FDPIC" -+ "#" -+ "" -+ [(parallel -+ [(set (match_dup 0) -+ (call (mem:QI (match_dup 1)) -+ (match_dup 2))) -+ (clobber (reg:SI LINK_REGNO))])] -+ "") -+ -+(define_insn "call_value_slow" -+ [(set (match_operand 0 "register_operand" "=r,r") -+ (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S")) -+ (match_operand:SI 2 "general_operand" "g,g"))) -+ (clobber (reg:SI LINK_REGNO))] -+ "(! TARGET_FDPIC && ! TARGET_FASTCALL)" -+ "@ -+ calli\\ta5, 0(%1) -+ moveai\\ta5, #%%hi(%C1)\;calli\\ta5, %%lo(%C1)(a5)") -+ -+(define_insn "call_value_fast" -+ [(set (match_operand 0 "register_operand" "=r,r") -+ (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S")) -+ (match_operand:SI 2 "general_operand" "g,g"))) -+ (clobber (reg:SI LINK_REGNO))] -+ "(! TARGET_FDPIC && TARGET_FASTCALL)" -+ "@ -+ calli\\ta5, 0(%1) -+ call\\ta5, %C1") -+ -+; We expand to a simple form that doesn't clobber the link register and -+; then split to a form that does. This allows the RTL optimizers that -+; run before the splitter to have the opportunity to eliminate the call -+; without marking A5 as being clobbered and this in turn avoids saves -+; and returns in a number of cases. -+; -+(define_insn_and_split "call_value_fdpic" -+ [(set (match_operand 0 "register_operand" "=r,r") -+ (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S")) -+ (match_operand:SI 2 "general_operand" "g,g"))) -+ (use (match_operand:SI 3 "ubicom32_fdpic_operand" "Z,Z"))] -+ "TARGET_FDPIC" -+ "#" -+ "" -+ [(parallel -+ [(set (match_dup 0) -+ (call (mem:QI (match_dup 1)) -+ (match_dup 2))) -+ (use (match_dup 3)) -+ (clobber (reg:SI LINK_REGNO))])] -+ "") -+ -+(define_insn "call_value_fdpic_clobber" -+ [(set (match_operand 0 "register_operand" "=r,r") -+ (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S")) -+ (match_operand:SI 2 "general_operand" "g,g"))) -+ (use (match_operand:SI 3 "ubicom32_fdpic_operand" "Z,Z")) -+ (clobber (reg:SI LINK_REGNO))] -+ "TARGET_FDPIC" -+ "@ -+ move.4\\ta5, 0(%1)\;move.4\\t%3, 4(%1)\;calli\\ta5, 0(a5) -+ call\\ta5, %C1") -+ -+(define_expand "untyped_call" -+ [(parallel [(call (match_operand 0 "" "") -+ (const_int 0)) -+ (match_operand 1 "" "") -+ (match_operand 2 "" "")])] -+ "" -+ "{ -+ int i; -+ -+ emit_call_insn (gen_call (operands[0], const0_rtx)); -+ -+ for (i = 0; i < XVECLEN (operands[2], 0); i++) -+ { -+ rtx set = XVECEXP (operands[2], 0, i); -+ emit_move_insn (SET_DEST (set), SET_SRC (set)); -+ } -+ DONE; -+ }") -+ -+(define_insn "lsl1_1" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (ashift:SI (subreg:SI -+ (match_operand:QI 1 "memory_operand" "m") -+ 0) -+ (match_operand:SI 2 "ubicom32_arith_operand" "dM"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(ubicom32_v4)" -+ "lsl.1\\t%0, %1, %2") -+ -+; The combiner gets rather creative about left shifts of sub-word memory -+; operands because it's uncertain about whether the memory is sign or -+; zero extended. It only wants zero-extended behaviour and so throws -+; in an extra and operation. -+; -+(define_insn "lsl1_2" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (and:SI -+ (ashift:SI (subreg:SI -+ (match_operand:QI 1 "memory_operand" "m") -+ 0) -+ (match_operand:SI 2 "const_int_operand" "M")) -+ (match_operand:SI 3 "const_int_operand" "n"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(ubicom32_v4 -+ && INTVAL (operands[3]) == (0xff << INTVAL (operands[2])))" -+ "lsl.1\\t%0, %1, %2") -+ -+(define_insn "lsl2_1" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (ashift:SI (subreg:SI -+ (match_operand:HI 1 "memory_operand" "m") -+ 0) -+ (match_operand:SI 2 "ubicom32_arith_operand" "dM"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(ubicom32_v4)" -+ "lsl.2\\t%0, %1, %2") -+ -+; The combiner gets rather creative about left shifts of sub-word memory -+; operands because it's uncertain about whether the memory is sign or -+; zero extended. It only wants zero-extended behaviour and so throws -+; in an extra and operation. -+; -+(define_insn "lsl2_2" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (and:SI -+ (ashift:SI (subreg:SI -+ (match_operand:HI 1 "memory_operand" "m") -+ 0) -+ (match_operand:SI 2 "const_int_operand" "M")) -+ (match_operand:SI 3 "const_int_operand" "n"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(ubicom32_v4 -+ && INTVAL (operands[3]) == (0xffff << INTVAL (operands[2])))" -+ "lsl.2\\t%0, %1, %2") -+ -+(define_insn "ashlsi3" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (ashift:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI") -+ (match_operand:SI 2 "ubicom32_arith_operand" "dM"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "lsl.4\\t%0, %1, %2") -+ -+(define_insn "lshlsi3_ccwz" -+ [(set (reg CC_REGNO) -+ (compare -+ (ashift:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI") -+ (match_operand:SI 2 "ubicom32_arith_operand" "dM")) -+ (const_int 0))) -+ (set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (ashift:SI (match_dup 1) -+ (match_dup 2)))] -+ "ubicom32_match_cc_mode(insn, CCWZmode)" -+ "lsl.4\\t%0, %1, %2") -+ -+(define_insn "lshlsi3_ccwz_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (ashift:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmI") -+ (match_operand:SI 1 "ubicom32_arith_operand" "dM")) -+ (const_int 0))) -+ (clobber (match_scratch:SI 2 "=d"))] -+ "ubicom32_match_cc_mode(insn, CCWZmode)" -+ "lsl.4\\t%2, %0, %1") -+ -+; The combiner finds this canonical form for what is in essence a right -+; shift. -+; -+(define_insn "asr1_2" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (sign_extract:SI (match_operand:QI 1 "memory_operand" "m") -+ (match_operand:SI 2 "const_int_operand" "M") -+ (match_operand:SI 3 "const_int_operand" "M"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(ubicom32_v4 -+ && (INTVAL (operands[2]) + INTVAL (operands[3]) == 8))" -+ "asr.1\\t%0, %1, %3") -+ -+; The combiner finds this canonical form for what is in essence a right -+; shift. -+; -+(define_insn "asr2_2" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (sign_extract:SI (match_operand:HI 1 "memory_operand" "m") -+ (match_operand:SI 2 "const_int_operand" "M") -+ (match_operand:SI 3 "const_int_operand" "M"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(ubicom32_v4 -+ && (INTVAL (operands[2]) + INTVAL (operands[3]) == 16))" -+ "asr.2\\t%0, %1, %3") -+ -+(define_insn "ashrsi3" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (ashiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmJ") -+ (match_operand:SI 2 "ubicom32_arith_operand" "dM"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "asr.4\\t%0, %1, %2") -+ -+(define_insn "ashrsi3_ccwzn" -+ [(set (reg CC_REGNO) -+ (compare -+ (ashiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmJ") -+ (match_operand:SI 2 "ubicom32_arith_operand" "dM")) -+ (const_int 0))) -+ (set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (ashiftrt:SI (match_dup 1) -+ (match_dup 2)))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "asr.4\\t%0, %1, %2") -+ -+(define_insn "ashrsi3_ccwzn_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (ashiftrt:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmJ") -+ (match_operand:SI 1 "ubicom32_arith_operand" "dM")) -+ (const_int 0))) -+ (clobber (match_scratch:SI 2 "=d"))] -+ "ubicom32_match_cc_mode(insn, CCWZNmode)" -+ "asr.4\\t%2, %0, %1") -+ -+(define_insn "lsr1_1" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (lshiftrt:SI (subreg:SI -+ (match_operand:QI 1 "memory_operand" "m") -+ 0) -+ (match_operand:SI 2 "ubicom32_arith_operand" "dM"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(ubicom32_v4)" -+ "lsr.1\\t%0, %1, %2") -+ -+; The combiner finds this canonical form for what is in essence a right -+; shift. -+; -+(define_insn "lsr1_2" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (zero_extract:SI (match_operand:QI 1 "memory_operand" "m") -+ (match_operand:SI 2 "const_int_operand" "M") -+ (match_operand:SI 3 "const_int_operand" "M"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(ubicom32_v4 -+ && (INTVAL (operands[2]) + INTVAL (operands[3]) == 8))" -+ "lsr.1\\t%0, %1, %3") -+ -+(define_insn "lsr2_1" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (lshiftrt:SI (subreg:SI -+ (match_operand:HI 1 "memory_operand" "m") -+ 0) -+ (match_operand:SI 2 "ubicom32_arith_operand" "dM"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(ubicom32_v4)" -+ "lsr.2\\t%0, %1, %2") -+ -+; The combiner finds this canonical form for what is in essence a right -+; shift. -+; -+(define_insn "lsr2_2" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (zero_extract:SI (match_operand:HI 1 "memory_operand" "m") -+ (match_operand:SI 2 "const_int_operand" "M") -+ (match_operand:SI 3 "const_int_operand" "M"))) -+ (clobber (reg:CC CC_REGNO))] -+ "(ubicom32_v4 -+ && (INTVAL (operands[2]) + INTVAL (operands[3]) == 16))" -+ "lsr.2\\t%0, %1, %3") -+ -+(define_insn "lshrsi3" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (lshiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI") -+ (match_operand:SI 2 "ubicom32_arith_operand" "dM"))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "lsr.4\\t%0, %1, %2") -+ -+(define_insn "lshrsi3_ccwz" -+ [(set (reg CC_REGNO) -+ (compare -+ (lshiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI") -+ (match_operand:SI 2 "ubicom32_arith_operand" "dM")) -+ (const_int 0))) -+ (set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (lshiftrt:SI (match_dup 1) -+ (match_dup 2)))] -+ "ubicom32_match_cc_mode(insn, CCWZmode)" -+ "lsr.4\\t%0, %1, %2") -+ -+(define_insn "lshrsi3_ccwz_null" -+ [(set (reg CC_REGNO) -+ (compare -+ (lshiftrt:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmI") -+ (match_operand:SI 1 "ubicom32_arith_operand" "dM")) -+ (const_int 0))) -+ (clobber (match_scratch:SI 2 "=d"))] -+ "ubicom32_match_cc_mode(insn, CCWZmode)" -+ "lsr.4\\t%2, %0, %1") -+ -+(define_expand "prologue" -+ [(const_int 0)] -+ "" -+ "{ -+ ubicom32_expand_prologue (); -+ DONE; -+ }") -+ -+(define_expand "epilogue" -+ [(return)] -+ "" -+ "{ -+ ubicom32_expand_epilogue (); -+ DONE; -+ }") -+ -+(define_expand "return" -+ [(return)] -+ "" -+ "{ -+ ubicom32_expand_epilogue (); -+ DONE; -+ }") -+ -+(define_expand "_eh_return" -+ [(use (match_operand:SI 0 "register_operand" "r")) -+ (use (match_operand:SI 1 "register_operand" "r"))] -+ "" -+ "{ -+ ubicom32_expand_eh_return (operands); -+ DONE; -+ }") -+ -+; XXX - it looks almost certain that we could make return_internal use a Dn -+; register too. In that instance we'd have to use a ret instruction -+; rather than a calli but it might save cycles. -+; -+(define_insn "return_internal" -+ [(const_int 2) -+ (return) -+ (use (match_operand:SI 0 "ubicom32_mem_or_address_register_operand" "rm"))] -+ "" -+ "* -+ { -+ if (REG_P (operands[0]) && REGNO (operands[0]) == LINK_REGNO -+ && ubicom32_can_use_calli_to_ret) -+ return \"calli\\t%0, 0(%0)\"; -+ -+ return \"ret\\t%0\"; -+ }") -+ -+(define_insn "return_from_post_modify_sp" -+ [(parallel -+ [(const_int 2) -+ (return) -+ (use (mem:SI (post_modify:SI -+ (reg:SI SP_REGNO) -+ (plus:SI (reg:SI SP_REGNO) -+ (match_operand:SI 0 "const_int_operand" "n")))))])] -+ "INTVAL (operands[0]) >= 4 && INTVAL (operands[0]) <= 7 * 4" -+ "ret\\t(sp)%E0++") -+ -+;(define_insn "eh_return_internal" -+; [(const_int 4) -+; (return) -+; (use (reg:SI 34))] -+; "" -+; "ret\\ta2") -+ -+; No operation, needed in case the user uses -g but not -O. -+(define_expand "nop" -+ [(const_int 0)] -+ "" -+ "") -+ -+(define_insn "nop_internal" -+ [(const_int 0)] -+ "" -+ "nop") -+ -+; The combiner will generate this pattern given shift and add operations. -+; The canonical form that the combiner wants to use appears to be multiplies -+; instead of shifts even if the compiled sources use shifts. -+; -+(define_insn "shmrg1_add" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (plus:SI -+ (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d") -+ (const_int 256)) -+ (zero_extend:SI -+ (match_operand:QI 2 "ubicom32_arith_operand" "rmI")))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "shmrg.1\\t%0, %2, %1") -+ -+; The combiner will generate this pattern given shift and or operations. -+; -+(define_insn "shmrg1_ior" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (ior:SI -+ (ashift:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d") -+ (const_int 8)) -+ (zero_extend:SI -+ (match_operand:QI 2 "ubicom32_arith_operand" "rmI")))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "shmrg.1\\t%0, %2, %1") -+ -+; The combiner will generate this pattern given shift and add operations. -+; The canonical form that the combiner wants to use appears to be multiplies -+; instead of shifts even if the compiled sources use shifts. -+; -+(define_insn "shmrg2_add" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (plus:SI -+ (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d") -+ (const_int 65536)) -+ (zero_extend:SI -+ (match_operand:HI 2 "ubicom32_arith_operand" "rmI")))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "shmrg.2\\t%0, %2, %1") -+ -+; The combiner will generate this pattern given shift and or operations. -+; -+(define_insn "shmrg2_ior" -+ [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d") -+ (ior:SI -+ (ashift:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d") -+ (const_int 16)) -+ (zero_extend:SI -+ (match_operand:HI 2 "ubicom32_arith_operand" "rmI")))) -+ (clobber (reg:CC CC_REGNO))] -+ "" -+ "shmrg.2\\t%0, %2, %1") -+ -+; Match the case where we load a word from the stack but then discard the -+; upper 16 bits. We turn this into a zero-extended load of that useful -+; 16 bits direct from the stack where possible. -+; -+ -+; XXX - do these peephole2 ops actually work after the CCmode conversion? -+(define_peephole2 -+ [(set (match_operand:SI 0 "register_operand" "") -+ (mem:SI (plus:SI (reg:SI SP_REGNO) -+ (match_operand:SI 1 "const_int_operand" "")))) -+ (set (match_operand:SI 2 "nonimmediate_operand" "") -+ (zero_extend:SI (match_operand:HI 3 "register_operand" "")))] -+ "(INTVAL (operands[1]) <= 252 -+ && REGNO (operands[3]) == REGNO (operands[0]) -+ && ((peep2_reg_dead_p (2, operands[0]) -+ && ! reg_mentioned_p (operands[0], operands[2])) -+ || rtx_equal_p (operands[0], operands[2])))" -+ [(set (match_dup 2) -+ (zero_extend:SI (mem:HI (plus:SI (reg:SI SP_REGNO) -+ (match_dup 4)))))] -+ "{ -+ operands[4] = GEN_INT (INTVAL (operands[1]) + 2); -+ }") -+ -+; Match the case where we load a word from the stack but then discard the -+; upper 16 bits. We turn this into a 16-bit load of that useful -+; 16 bits direct from the stack where possible. -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "register_operand" "") -+ (mem:SI (plus:SI (reg:SI SP_REGNO) -+ (match_operand:SI 1 "const_int_operand" "")))) -+ (set (match_operand:HI 2 "nonimmediate_operand" "") -+ (match_operand:HI 3 "register_operand" ""))] -+ "(INTVAL (operands[1]) <= 252 -+ && REGNO (operands[3]) == REGNO (operands[0]) -+ && ((peep2_reg_dead_p (2, operands[0]) -+ && ! reg_mentioned_p (operands[0], operands[2])) -+ || rtx_equal_p (operands[0], operands[2])))" -+ [(set (match_dup 2) -+ (mem:HI (plus:SI (reg:SI SP_REGNO) -+ (match_dup 4))))] -+ "{ -+ operands[4] = GEN_INT (INTVAL (operands[1]) + 2); -+ }") -+ -+; Match the case where we load a word from the stack but then discard the -+; upper 24 bits. We turn this into a zero-extended load of that useful -+; 8 bits direct from the stack where possible. -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "register_operand" "") -+ (mem:SI (plus:SI (reg:SI SP_REGNO) -+ (match_operand:SI 1 "const_int_operand" "")))) -+ (set (match_operand:SI 2 "nonimmediate_operand" "") -+ (zero_extend:SI (match_operand:QI 3 "register_operand" "")))] -+ "(INTVAL (operands[1]) <= 124 -+ && REGNO (operands[3]) == REGNO (operands[0]) -+ && ((peep2_reg_dead_p (2, operands[0]) -+ && ! reg_mentioned_p (operands[0], operands[2])) -+ || rtx_equal_p (operands[0], operands[2])))" -+ [(set (match_dup 2) -+ (zero_extend:SI (mem:QI (plus:SI (reg:SI SP_REGNO) -+ (match_dup 4)))))] -+ "{ -+ operands[4] = GEN_INT (INTVAL (operands[1]) + 3); -+ }") -+ -+; Match the case where we load a word from the stack but then discard the -+; upper 24 bits. We turn this into an 8-bit load of that useful -+; 8 bits direct from the stack where possible. -+; -+(define_peephole2 -+ [(set (match_operand:SI 0 "register_operand" "") -+ (mem:SI (plus:SI (reg:SI SP_REGNO) -+ (match_operand:SI 1 "const_int_operand" "")))) -+ (set (match_operand:QI 2 "nonimmediate_operand" "") -+ (match_operand:QI 3 "register_operand" ""))] -+ "(INTVAL (operands[1]) <= 124 -+ && REGNO (operands[3]) == REGNO (operands[0]) -+ && ((peep2_reg_dead_p (2, operands[0]) -+ && ! reg_mentioned_p (operands[0], operands[2])) -+ || rtx_equal_p (operands[0], operands[2])))" -+ [(set (match_dup 2) -+ (mem:QI (plus:SI (reg:SI SP_REGNO) -+ (match_dup 4))))] -+ "{ -+ operands[4] = GEN_INT (INTVAL (operands[1]) + 3); -+ }") -+ ---- /dev/null -+++ b/gcc/config/ubicom32/ubicom32.opt -@@ -0,0 +1,27 @@ -+mdebug-address -+Target RejectNegative Report Undocumented Mask(DEBUG_ADDRESS) -+Debug addresses -+ -+mdebug-context -+Target RejectNegative Report Undocumented Mask(DEBUG_CONTEXT) -+Debug contexts -+ -+march= -+Target Report Var(ubicom32_arch_name) Init("ubicom32v4") Joined -+Specify the name of the target architecture -+ -+mfdpic -+Target Report Mask(FDPIC) -+Enable Function Descriptor PIC mode -+ -+minline-plt -+Target Report Mask(INLINE_PLT) -+Enable inlining of PLT in function calls -+ -+mfastcall -+Target Report Mask(FASTCALL) -+Enable default fast (call) calling sequence for smaller applications -+ -+mipos-abi -+Target Report Mask(IPOS_ABI) -+Enable the ipOS ABI in which D10-D13 are caller-clobbered ---- /dev/null -+++ b/gcc/config/ubicom32/uclinux.h -@@ -0,0 +1,67 @@ -+/* Definitions of target machine for Ubicom32-uclinux -+ -+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -+ 2009 Free Software Foundation, Inc. -+ Contributed by Ubicom, Inc. -+ -+ This file is part of GCC. -+ -+ GCC is free software; you can redistribute it and/or modify it -+ under the terms of the GNU General Public License as published -+ by the Free Software Foundation; either version 3, or (at your -+ option) any later version. -+ -+ GCC is distributed in the hope that it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -+ License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with GCC; see the file COPYING3. If not see -+ <http://www.gnu.org/licenses/>. */ -+ -+/* Don't assume anything about the header files. */ -+#define NO_IMPLICIT_EXTERN_C -+ -+#undef LIB_SPEC -+#define LIB_SPEC \ -+ "%{pthread:-lpthread} " \ -+ "%{!shared:%{!symbolic: -lc}} " -+ -+ -+#undef LINK_GCC_C_SEQUENCE_SPEC -+#define LINK_GCC_C_SEQUENCE_SPEC \ -+ "%{!shared:--start-group} %G %L %{!shared:--end-group}%{shared:%G} " -+ -+#undef STARTFILE_SPEC -+#define STARTFILE_SPEC \ -+ "%{!shared: crt1%O%s}" \ -+ " crti%O%s crtbegin%O%s" -+ -+#undef ENDFILE_SPEC -+#define ENDFILE_SPEC "crtend%O%s crtn%O%s" -+ -+/* This macro applies on top of OBJECT_FORMAT_ELF and indicates that -+ we want to support both flat and ELF output. */ -+#define OBJECT_FORMAT_FLAT -+ -+#undef DRIVER_SELF_SPECS -+#define DRIVER_SELF_SPECS \ -+ "%{!mno-fastcall:-mfastcall}" -+ -+/* taken from linux.h */ -+/* The GNU C++ standard library requires that these macros be defined. */ -+#undef CPLUSPLUS_CPP_SPEC -+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)" -+ -+#define TARGET_OS_CPP_BUILTINS() \ -+ do { \ -+ builtin_define_std ("__UBICOM32__"); \ -+ builtin_define_std ("__ubicom32__"); \ -+ builtin_define ("__gnu_linux__"); \ -+ builtin_define_std ("linux"); \ -+ builtin_define_std ("unix"); \ -+ builtin_assert ("system=linux"); \ -+ builtin_assert ("system=unix"); \ -+ builtin_assert ("system=posix"); \ -+ } while (0) ---- /dev/null -+++ b/gcc/config/ubicom32/xm-ubicom32.h -@@ -0,0 +1,36 @@ -+/* Configuration for Ubicom's Ubicom32 architecture. -+ Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software -+ Foundation, Inc. -+ Contributed by Ubicom Inc. -+ -+This file is part of GNU CC. -+ -+GNU CC is free software; you can redistribute it and/or modify -+it under the terms of the GNU General Public License as published by -+the Free Software Foundation; either version 2, or (at your option) -+any later version. -+ -+GNU CC is distributed in the hope that it will be useful, -+but WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+GNU General Public License for more details. -+ -+You should have received a copy of the GNU General Public License -+along with GNU CC; see the file COPYING. If not, write to -+the Free Software Foundation, 59 Temple Place - Suite 330, -+Boston, MA 02111-1307, USA. */ -+ -+/* #defines that need visibility everywhere. */ -+#define FALSE 0 -+#define TRUE 1 -+ -+/* This describes the machine the compiler is hosted on. */ -+#define HOST_BITS_PER_CHAR 8 -+#define HOST_BITS_PER_SHORT 16 -+#define HOST_BITS_PER_INT 32 -+#define HOST_BITS_PER_LONG 32 -+#define HOST_BITS_PER_LONGLONG 64 -+ -+/* Arguments to use with `exit'. */ -+#define SUCCESS_EXIT_CODE 0 -+#define FATAL_EXIT_CODE 33 ---- a/gcc/config.gcc -+++ b/gcc/config.gcc -@@ -2320,6 +2320,34 @@ - c_target_objs="${c_target_objs} spu-c.o" - cxx_target_objs="${cxx_target_objs} spu-c.o" - ;; -+ubicom32-*-elf) -+ xm_file=ubicom32/xm-ubicom32.h -+ tm_file="${tm_file} ubicom32/elf.h" # still need dbxelf.h elfos.h -+ tmake_file=ubicom32/t-ubicom32 -+ ;; -+ubicom32-*-uclinux*) -+ xm_file=ubicom32/xm-ubicom32.h -+ tm_file="${tm_file} ubicom32/elf.h ubicom32/uclinux.h" # still need dbxelf.h elfos.h linux.h -+ tm_defines="${tm_defines} UCLIBC_DEFAULT=1" -+ extra_options="${extra_options} linux.opt" -+ tmake_file=ubicom32/t-ubicom32-uclinux -+ use_collect2=no -+ ;; -+ubicom32-*-linux-uclibc) -+ xm_file=ubicom32/xm-ubicom32.h -+ tm_file="${tm_file} ubicom32/elf.h linux.h ubicom32/linux.h" # still need dbxelf.h elfos.h -+ tmake_file="t-slibgcc-elf-ver ubicom32/t-ubicom32-linux" -+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" -+ use_collect2=no -+ ;; -+ubicom32-*-linux*) -+ xm_file=ubicom32/xm-ubicom32.h -+ tm_file="${tm_file} ubicom32/elf.h linux.h ubicom32/linux.h" # still need dbxelf.h elfos.h -+ tmake_file="t-slibgcc-elf-ver ubicom32/t-ubicom32-linux" -+ tm_defines="${tm_defines} UCLIBC_DEFAULT=1" -+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" -+ use_collect2=no -+ ;; - v850e1-*-*) - target_cpu_default="TARGET_CPU_v850e1" - tm_file="dbxelf.h elfos.h svr4.h v850/v850.h" ---- a/libgcc/config.host -+++ b/libgcc/config.host -@@ -562,6 +562,15 @@ - ;; - spu-*-elf*) - ;; -+ubicom32*-*-elf*) -+ ;; -+ubicom32*-*-uclinux*) -+ ;; -+ubicom32*-*-linux*) -+ # No need to build crtbeginT.o on uClibc systems. Should probably -+ # be moved to the OS specific section above. -+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" -+ ;; - v850e1-*-*) - ;; - v850e-*-*) diff --git a/toolchain/gcc/patches/4.4.1+cs/810-arm-softfloat-libgcc.patch b/toolchain/gcc/patches/4.4.1+cs/810-arm-softfloat-libgcc.patch deleted file mode 100644 index 4ca297a41a..0000000000 --- a/toolchain/gcc/patches/4.4.1+cs/810-arm-softfloat-libgcc.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- a/gcc/config/arm/linux-elf.h -+++ b/gcc/config/arm/linux-elf.h -@@ -60,7 +60,7 @@ - %{shared:-lc} \ - %{!shared:%{profile:-lc_p}%{!profile:-lc}}" - --#define LIBGCC_SPEC "%{msoft-float:-lfloat} %{mfloat-abi=soft*:-lfloat} -lgcc" -+#define LIBGCC_SPEC "-lgcc" - - #define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2" - ---- a/gcc/config/arm/t-linux -+++ b/gcc/config/arm/t-linux -@@ -4,7 +4,10 @@ - - LIB1ASMSRC = arm/lib1funcs.asm - LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx _clzsi2 _clzdi2 \ -- _arm_addsubdf3 _arm_addsubsf3 -+ _arm_addsubdf3 _arm_addsubsf3 \ -+ _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \ -+ _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \ -+ _fixsfsi _fixunssfsi _floatdidf _floatundidf _floatdisf _floatundisf - - # MULTILIB_OPTIONS = mhard-float/msoft-float - # MULTILIB_DIRNAMES = hard-float soft-float diff --git a/toolchain/gcc/patches/4.4.1+cs/820-libgcc_pic.patch b/toolchain/gcc/patches/4.4.1+cs/820-libgcc_pic.patch deleted file mode 100644 index 97a47c0bcb..0000000000 --- a/toolchain/gcc/patches/4.4.1+cs/820-libgcc_pic.patch +++ /dev/null @@ -1,36 +0,0 @@ ---- a/libgcc/Makefile.in -+++ b/libgcc/Makefile.in -@@ -735,11 +735,12 @@ - - # Static libraries. - libgcc.a: $(libgcc-objects) -+libgcc_pic.a: $(libgcc-s-objects) - libgcov.a: $(libgcov-objects) - libunwind.a: $(libunwind-objects) - libgcc_eh.a: $(libgcc-eh-objects) - --libgcc.a libgcov.a libunwind.a libgcc_eh.a: -+libgcc.a libgcov.a libunwind.a libgcc_eh.a libgcc_pic.a: - -rm -f $@ - - objects="$(objects)"; \ -@@ -761,7 +762,7 @@ - endif - - ifeq ($(enable_shared),yes) --all: libgcc_eh.a libgcc_s$(SHLIB_EXT) -+all: libgcc_eh.a libgcc_pic.a libgcc_s$(SHLIB_EXT) - ifneq ($(LIBUNWIND),) - all: libunwind$(SHLIB_EXT) - endif -@@ -934,6 +935,10 @@ - chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_eh.a - $(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_eh.a - -+ $(INSTALL_DATA) libgcc_pic.a $(mapfile) $(DESTDIR)$(inst_libdir)/ -+ chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_pic.a -+ $(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_pic.a -+ - $(subst @multilib_dir@,$(MULTIDIR),$(subst \ - @shlib_base_name@,libgcc_s,$(subst \ - @shlib_slibdir_qual@,$(MULTIOSSUBDIR),$(SHLIB_INSTALL)))) diff --git a/toolchain/gcc/patches/4.4.1+cs/910-mbsd_multi.patch b/toolchain/gcc/patches/4.4.1+cs/910-mbsd_multi.patch deleted file mode 100644 index 90343dc7a1..0000000000 --- a/toolchain/gcc/patches/4.4.1+cs/910-mbsd_multi.patch +++ /dev/null @@ -1,172 +0,0 @@ - - This patch brings over a few features from MirBSD: - * -fhonour-copts - If this option is not given, it's warned (depending - on environment variables). This is to catch errors - of misbuilt packages which override CFLAGS themselves. - * Make -fno-strict-aliasing and -fno-delete-null-pointer-checks - the default for -O2/-Os, because they trigger gcc bugs - and can delete code with security implications. - - This patch was authored by Thorsten Glaser <tg at mirbsd.de> - with copyright assignment to the FSF in effect. - ---- a/gcc/c-opts.c -+++ b/gcc/c-opts.c -@@ -106,6 +106,9 @@ - /* Number of deferred options scanned for -include. */ - static size_t include_cursor; - -+/* Check if a port honours COPTS. */ -+static int honour_copts = 0; -+ - static void set_Wimplicit (int); - static void handle_OPT_d (const char *); - static void set_std_cxx98 (int); -@@ -689,6 +692,12 @@ - flag_exceptions = value; - break; - -+ case OPT_fhonour_copts: -+ if (c_language == clk_c) { -+ honour_copts++; -+ } -+ break; -+ - case OPT_fimplement_inlines: - flag_implement_inlines = value; - break; -@@ -1198,6 +1207,47 @@ - return false; - } - -+ if (c_language == clk_c) { -+ char *ev = getenv ("GCC_HONOUR_COPTS"); -+ int evv; -+ if (ev == NULL) -+ evv = -1; -+ else if ((*ev == '0') || (*ev == '\0')) -+ evv = 0; -+ else if (*ev == '1') -+ evv = 1; -+ else if (*ev == '2') -+ evv = 2; -+ else if (*ev == 's') -+ evv = -1; -+ else { -+ warning (0, "unknown GCC_HONOUR_COPTS value, assuming 1"); -+ evv = 1; /* maybe depend this on something like MIRBSD_NATIVE? */ -+ } -+ if (evv == 1) { -+ if (honour_copts == 0) { -+ error ("someone does not honour COPTS at all in lenient mode"); -+ return false; -+ } else if (honour_copts != 1) { -+ warning (0, "someone does not honour COPTS correctly, passed %d times", -+ honour_copts); -+ } -+ } else if (evv == 2) { -+ if (honour_copts == 0) { -+ error ("someone does not honour COPTS at all in strict mode"); -+ return false; -+ } else if (honour_copts != 1) { -+ error ("someone does not honour COPTS correctly, passed %d times", -+ honour_copts); -+ return false; -+ } -+ } else if (evv == 0) { -+ if (honour_copts != 1) -+ inform (0, "someone does not honour COPTS correctly, passed %d times", -+ honour_copts); -+ } -+ } -+ - return true; - } - ---- a/gcc/c.opt -+++ b/gcc/c.opt -@@ -609,6 +609,9 @@ - fhonor-std - C++ ObjC++ - -+fhonour-copts -+C ObjC C++ ObjC++ RejectNegative -+ - fhosted - C ObjC - Assume normal C execution environment ---- a/gcc/common.opt -+++ b/gcc/common.opt -@@ -587,6 +587,9 @@ - Common Report Var(flag_guess_branch_prob) Optimization - Enable guessing of branch probabilities - -+fhonour-copts -+Common RejectNegative -+ - ; Nonzero means ignore `#ident' directives. 0 means handle them. - ; Generate position-independent code for executables if possible - ; On SVR4 targets, it also controls whether or not to emit a ---- a/gcc/opts.c -+++ b/gcc/opts.c -@@ -896,9 +896,6 @@ - flag_schedule_insns_after_reload = opt2; - #endif - flag_regmove = opt2; -- flag_strict_aliasing = opt2; -- flag_strict_overflow = opt2; -- flag_delete_null_pointer_checks = opt2; - flag_reorder_blocks = opt2; - flag_reorder_functions = opt2; - flag_tree_vrp = opt2; -@@ -922,6 +919,9 @@ - - /* -O3 optimizations. */ - opt3 = (optimize >= 3); -+ flag_strict_aliasing = opt3; -+ flag_strict_overflow = opt3; -+ flag_delete_null_pointer_checks = opt3; - flag_predictive_commoning = opt3; - flag_inline_functions = opt3; - flag_unswitch_loops = opt3; -@@ -1605,6 +1605,9 @@ - enable_warning_as_error (arg, value, lang_mask); - break; - -+ case OPT_fhonour_copts: -+ break; -+ - case OPT_Wextra: - set_Wextra (value); - break; ---- a/gcc/doc/invoke.texi -+++ b/gcc/doc/invoke.texi -@@ -5699,7 +5699,7 @@ - second branch or a point immediately following it, depending on whether - the condition is known to be true or false. - --Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}. -+Enabled at levels @option{-O3}. - - @item -fsplit-wide-types - @opindex fsplit-wide-types -@@ -5844,7 +5844,7 @@ - @option{-fno-delete-null-pointer-checks} to disable this optimization - for programs which depend on that behavior. - --Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}. -+Enabled at levels @option{-O3}. - - @item -fexpensive-optimizations - @opindex fexpensive-optimizations ---- a/gcc/java/jvspec.c -+++ b/gcc/java/jvspec.c -@@ -670,6 +670,7 @@ - class name. Append dummy `.c' that can be stripped by set_input so %b - is correct. */ - set_input (concat (main_class_name, "main.c", NULL)); -+ putenv ("GCC_HONOUR_COPTS=s"); /* XXX hack! */ - err = do_spec (jvgenmain_spec); - if (err == 0) - { diff --git a/toolchain/gcc/patches/4.4.1+cs/993-arm_insn-opinit-RTX_CODE-fixup.patch b/toolchain/gcc/patches/4.4.1+cs/993-arm_insn-opinit-RTX_CODE-fixup.patch deleted file mode 100644 index d7e5fa612a..0000000000 --- a/toolchain/gcc/patches/4.4.1+cs/993-arm_insn-opinit-RTX_CODE-fixup.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- a/gcc/config/arm/arm-protos.h -+++ b/gcc/config/arm/arm-protos.h -@@ -43,10 +43,10 @@ - extern void arm_output_fn_unwind (FILE *, bool); - - --#ifdef RTX_CODE - extern bool arm_vector_mode_supported_p (enum machine_mode); - extern int arm_hard_regno_mode_ok (unsigned int, enum machine_mode); - extern int const_ok_for_arm (HOST_WIDE_INT); -+#ifdef RTX_CODE - extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx, - HOST_WIDE_INT, rtx, rtx, int); - extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, enum machine_mode, diff --git a/toolchain/gcc/patches/4.4.1+cs/999-coldfire.patch b/toolchain/gcc/patches/4.4.1+cs/999-coldfire.patch deleted file mode 100644 index d17f1d9109..0000000000 --- a/toolchain/gcc/patches/4.4.1+cs/999-coldfire.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/gcc/config.gcc -+++ b/gcc/config.gcc -@@ -1499,6 +1499,7 @@ - if test x$sjlj != x1; then - tmake_file="$tmake_file m68k/t-slibgcc-elf-ver" - fi -+ tmake_file="m68k/t-floatlib m68k/t-m68kbare m68k/t-m68kelf" - ;; - m68k-*-rtems*) - default_m68k_cpu=68020 |