Integrate lexical block into source_location.
[platform/upstream/gcc.git] / gcc / config / xtensa / xtensa.c
index 9d846c5..987b6d7 100644 (file)
@@ -1,5 +1,5 @@
 /* Subroutines for insn-output.c for Tensilica's Xtensa architecture.
-   Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
 
@@ -41,7 +41,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm_p.h"
 #include "function.h"
 #include "diagnostic-core.h"
-#include "toplev.h"
 #include "optabs.h"
 #include "libfuncs.h"
 #include "ggc.h"
@@ -119,7 +118,6 @@ const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER] =
 };
 
 static void xtensa_option_override (void);
-static void xtensa_option_optimization (int, int);
 static enum internal_test map_test_to_internal_test (enum rtx_code);
 static rtx gen_int_relational (enum rtx_code, rtx, rtx, int *);
 static rtx gen_float_relational (enum rtx_code, rtx, rtx);
@@ -128,6 +126,7 @@ static rtx fixup_subreg_mem (rtx);
 static struct machine_function * xtensa_init_machine_status (void);
 static rtx xtensa_legitimize_tls_address (rtx);
 static rtx xtensa_legitimize_address (rtx, rtx, enum machine_mode);
+static bool xtensa_mode_dependent_address_p (const_rtx);
 static bool xtensa_return_in_msb (const_tree);
 static void printx (FILE *, signed int);
 static void xtensa_function_epilogue (FILE *, HOST_WIDE_INT);
@@ -137,18 +136,25 @@ static unsigned int xtensa_multibss_section_type_flags (tree, const char *,
                                                        int) ATTRIBUTE_UNUSED;
 static section *xtensa_select_rtx_section (enum machine_mode, rtx,
                                           unsigned HOST_WIDE_INT);
-static bool xtensa_rtx_costs (rtx, int, int, int *, bool);
+static bool xtensa_rtx_costs (rtx, int, int, int, int *, bool);
+static int xtensa_register_move_cost (enum machine_mode, reg_class_t,
+                                     reg_class_t);
+static int xtensa_memory_move_cost (enum machine_mode, reg_class_t, bool);
 static tree xtensa_build_builtin_va_list (void);
 static bool xtensa_return_in_memory (const_tree, const_tree);
 static tree xtensa_gimplify_va_arg_expr (tree, tree, gimple_seq *,
                                         gimple_seq *);
-static void xtensa_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+static void xtensa_function_arg_advance (cumulative_args_t, enum machine_mode,
                                         const_tree, bool);
-static rtx xtensa_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+static rtx xtensa_function_arg (cumulative_args_t, enum machine_mode,
                                const_tree, bool);
-static rtx xtensa_function_incoming_arg (CUMULATIVE_ARGS *,
+static rtx xtensa_function_incoming_arg (cumulative_args_t,
                                         enum machine_mode, const_tree, bool);
 static rtx xtensa_function_value (const_tree, const_tree, bool);
+static rtx xtensa_libcall_value (enum machine_mode, const_rtx);
+static bool xtensa_function_value_regno_p (const unsigned int);
+static unsigned int xtensa_function_arg_boundary (enum machine_mode,
+                                                 const_tree);
 static void xtensa_init_builtins (void);
 static tree xtensa_fold_builtin (tree, int, tree *, bool);
 static rtx xtensa_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
@@ -157,6 +163,20 @@ static bool xtensa_frame_pointer_required (void);
 static rtx xtensa_static_chain (const_tree, bool);
 static void xtensa_asm_trampoline_template (FILE *);
 static void xtensa_trampoline_init (rtx, tree, rtx);
+static bool xtensa_output_addr_const_extra (FILE *, rtx);
+static bool xtensa_cannot_force_const_mem (enum machine_mode, rtx);
+
+static reg_class_t xtensa_preferred_reload_class (rtx, reg_class_t);
+static reg_class_t xtensa_preferred_output_reload_class (rtx, reg_class_t);
+static reg_class_t xtensa_secondary_reload (bool, rtx, reg_class_t,
+                                           enum machine_mode,
+                                           struct secondary_reload_info *);
+
+static bool constantpool_address_p (const_rtx addr);
+static bool xtensa_legitimate_constant_p (enum machine_mode, rtx);
+
+static bool xtensa_member_type_forces_blk (const_tree,
+                                          enum machine_mode mode);
 
 static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
   REG_ALLOC_ORDER;
@@ -179,16 +199,22 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
 #undef TARGET_ASM_SELECT_RTX_SECTION
 #define TARGET_ASM_SELECT_RTX_SECTION  xtensa_select_rtx_section
 
-#undef TARGET_DEFAULT_TARGET_FLAGS
-#define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | MASK_FUSED_MADD)
-
 #undef TARGET_LEGITIMIZE_ADDRESS
 #define TARGET_LEGITIMIZE_ADDRESS xtensa_legitimize_address
+#undef TARGET_MODE_DEPENDENT_ADDRESS_P
+#define TARGET_MODE_DEPENDENT_ADDRESS_P xtensa_mode_dependent_address_p
 
+#undef TARGET_REGISTER_MOVE_COST
+#define TARGET_REGISTER_MOVE_COST xtensa_register_move_cost
+#undef TARGET_MEMORY_MOVE_COST
+#define TARGET_MEMORY_MOVE_COST xtensa_memory_move_cost
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS xtensa_rtx_costs
 #undef TARGET_ADDRESS_COST
-#define TARGET_ADDRESS_COST hook_int_rtx_bool_0
+#define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
+
+#undef TARGET_MEMBER_TYPE_FORCES_BLK
+#define TARGET_MEMBER_TYPE_FORCES_BLK xtensa_member_type_forces_blk
 
 #undef TARGET_BUILD_BUILTIN_VA_LIST
 #define TARGET_BUILD_BUILTIN_VA_LIST xtensa_build_builtin_va_list
@@ -205,6 +231,11 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
 #define TARGET_RETURN_IN_MEMORY xtensa_return_in_memory
 #undef TARGET_FUNCTION_VALUE
 #define TARGET_FUNCTION_VALUE xtensa_function_value
+#undef TARGET_LIBCALL_VALUE
+#define TARGET_LIBCALL_VALUE xtensa_libcall_value
+#undef TARGET_FUNCTION_VALUE_REGNO_P
+#define TARGET_FUNCTION_VALUE_REGNO_P xtensa_function_value_regno_p
+
 #undef TARGET_SPLIT_COMPLEX_ARG
 #define TARGET_SPLIT_COMPLEX_ARG hook_bool_const_tree_true
 #undef TARGET_MUST_PASS_IN_STACK
@@ -215,6 +246,8 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
 #define TARGET_FUNCTION_ARG xtensa_function_arg
 #undef TARGET_FUNCTION_INCOMING_ARG
 #define TARGET_FUNCTION_INCOMING_ARG xtensa_function_incoming_arg
+#undef TARGET_FUNCTION_ARG_BOUNDARY
+#define TARGET_FUNCTION_ARG_BOUNDARY xtensa_function_arg_boundary
 
 #undef TARGET_EXPAND_BUILTIN_SAVEREGS
 #define TARGET_EXPAND_BUILTIN_SAVEREGS xtensa_builtin_saveregs
@@ -231,6 +264,11 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
 #undef  TARGET_EXPAND_BUILTIN
 #define TARGET_EXPAND_BUILTIN xtensa_expand_builtin
 
+#undef  TARGET_PREFERRED_RELOAD_CLASS
+#define TARGET_PREFERRED_RELOAD_CLASS xtensa_preferred_reload_class
+#undef  TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
+#define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS xtensa_preferred_output_reload_class
+
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD xtensa_secondary_reload
 
@@ -238,7 +276,7 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
 #define TARGET_HAVE_TLS (TARGET_THREADPTR && HAVE_AS_TLS)
 
 #undef TARGET_CANNOT_FORCE_CONST_MEM
-#define TARGET_CANNOT_FORCE_CONST_MEM xtensa_tls_referenced_p
+#define TARGET_CANNOT_FORCE_CONST_MEM xtensa_cannot_force_const_mem
 
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P    xtensa_legitimate_address_p
@@ -255,8 +293,12 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
 
 #undef TARGET_OPTION_OVERRIDE
 #define TARGET_OPTION_OVERRIDE xtensa_option_override
-#undef TARGET_OPTION_OPTIMIZATION
-#define TARGET_OPTION_OPTIMIZATION xtensa_option_optimization
+
+#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
+#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA xtensa_output_addr_const_extra
+
+#undef TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P xtensa_legitimate_constant_p
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
@@ -467,10 +509,10 @@ smalloffset_mem_p (rtx op)
 }
 
 
-int
-constantpool_address_p (rtx addr)
+static bool
+constantpool_address_p (const_rtx addr)
 {
-  rtx sym = addr;
+  const_rtx sym = addr;
 
   if (GET_CODE (addr) == CONST)
     {
@@ -479,21 +521,21 @@ constantpool_address_p (rtx addr)
       /* Only handle (PLUS (SYM, OFFSET)) form.  */
       addr = XEXP (addr, 0);
       if (GET_CODE (addr) != PLUS)
-       return FALSE;
+       return false;
 
       /* Make sure the address is word aligned.  */
       offset = XEXP (addr, 1);
-      if ((GET_CODE (offset) != CONST_INT)
+      if ((!CONST_INT_P (offset))
          || ((INTVAL (offset) & 3) != 0))
-       return FALSE;
+       return false;
 
       sym = XEXP (addr, 0);
     }
 
   if ((GET_CODE (sym) == SYMBOL_REF)
       && CONSTANT_POOL_ADDRESS_P (sym))
-    return TRUE;
-  return FALSE;
+    return true;
+  return false;
 }
 
 
@@ -1043,7 +1085,7 @@ fixup_subreg_mem (rtx x)
     {
       rtx temp =
        gen_rtx_SUBREG (GET_MODE (x),
-                       reg_equiv_mem [REGNO (SUBREG_REG (x))],
+                       reg_equiv_mem (REGNO (SUBREG_REG (x))),
                        SUBREG_BYTE (x));
       x = alter_subreg (&temp);
     }
@@ -1292,7 +1334,7 @@ xtensa_expand_nonlocal_goto (rtx *operands)
     containing_fp = force_reg (Pmode, containing_fp);
 
   emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_nonlocal_goto"),
-                    0, VOIDmode, 2,
+                    LCT_NORMAL, VOIDmode, 2,
                     containing_fp, Pmode,
                     goto_handler, Pmode);
 }
@@ -1570,7 +1612,7 @@ xtensa_setup_frame_addresses (void)
 
   emit_library_call
     (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_libgcc_window_spill"),
-     0, VOIDmode, 0);
+     LCT_NORMAL, VOIDmode, 0);
 }
 
 
@@ -1822,9 +1864,7 @@ xtensa_call_tls_desc (rtx sym, rtx *retp)
   emit_insn (gen_tls_arg (arg, sym));
   emit_move_insn (a10, arg);
   call_insn = emit_call_insn (gen_tls_call (a10, fn, sym, const1_rtx));
-  CALL_INSN_FUNCTION_USAGE (call_insn)
-    = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_USE (VOIDmode, a10),
-                        CALL_INSN_FUNCTION_USAGE (call_insn));
+  use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), a10);
   insns = get_insns ();
   end_sequence ();
 
@@ -1910,6 +1950,21 @@ xtensa_legitimize_address (rtx x,
   return x;
 }
 
+/* Worker function for TARGET_MODE_DEPENDENT_ADDRESS_P.
+
+   Treat constant-pool references as "mode dependent" since they can
+   only be accessed with SImode loads.  This works around a bug in the
+   combiner where a constant pool reference is temporarily converted
+   to an HImode load, which is then assumed to zero-extend based on
+   our definition of LOAD_EXTEND_OP.  This is wrong because the high
+   bits of a 16-bit value in the constant pool are now sign-extended
+   by default.  */
+
+static bool
+xtensa_mode_dependent_address_p (const_rtx addr)
+{
+  return constantpool_address_p (addr);
+}
 
 /* Helper for xtensa_tls_referenced_p.  */
 
@@ -1951,6 +2006,15 @@ xtensa_tls_referenced_p (rtx x)
 }
 
 
+/* Implement TARGET_CANNOT_FORCE_CONST_MEM.  */
+
+static bool
+xtensa_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+  return xtensa_tls_referenced_p (x);
+}
+
+
 /* Return the debugger register number to use for 'regno'.  */
 
 int
@@ -2003,13 +2067,13 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, int incoming)
 /* Advance the argument to the next argument position.  */
 
 static void
-xtensa_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+xtensa_function_arg_advance (cumulative_args_t cum, enum machine_mode mode,
                             const_tree type, bool named ATTRIBUTE_UNUSED)
 {
   int words, max;
   int *arg_words;
 
-  arg_words = &cum->arg_words;
+  arg_words = &get_cumulative_args (cum)->arg_words;
   max = MAX_ARGS_IN_REGISTERS;
 
   words = (((mode != BLKmode)
@@ -2030,9 +2094,10 @@ xtensa_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
    if this is an incoming argument to the current function.  */
 
 static rtx
-xtensa_function_arg_1 (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
+xtensa_function_arg_1 (cumulative_args_t cum_v, enum machine_mode mode,
                       const_tree type, bool incoming_p)
 {
+  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int regbase, words, max;
   int *arg_words;
   int regno;
@@ -2065,7 +2130,7 @@ xtensa_function_arg_1 (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
 /* Implement TARGET_FUNCTION_ARG.  */
 
 static rtx
-xtensa_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+xtensa_function_arg (cumulative_args_t cum, enum machine_mode mode,
                     const_tree type, bool named ATTRIBUTE_UNUSED)
 {
   return xtensa_function_arg_1 (cum, mode, type, false);
@@ -2074,14 +2139,14 @@ xtensa_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
 /* Implement TARGET_FUNCTION_INCOMING_ARG.  */
 
 static rtx
-xtensa_function_incoming_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+xtensa_function_incoming_arg (cumulative_args_t cum, enum machine_mode mode,
                              const_tree type, bool named ATTRIBUTE_UNUSED)
 {
   return xtensa_function_arg_1 (cum, mode, type, true);
 }
 
-int
-function_arg_boundary (enum machine_mode mode, tree type)
+static unsigned int
+xtensa_function_arg_boundary (enum machine_mode mode, const_tree type)
 {
   unsigned int alignment;
 
@@ -2171,20 +2236,6 @@ xtensa_option_override (void)
     }
 }
 
-/* Implement TARGET_OPTION_OPTIMIZATION.  */
-
-static void
-xtensa_option_optimization (int level ATTRIBUTE_UNUSED,
-                           int size ATTRIBUTE_UNUSED)
-{
-  /* Reordering blocks for Xtensa is not a good idea unless the
-     compiler understands the range of conditional branches.
-     Currently all branch relaxation for Xtensa is handled in the
-     assembler, so GCC cannot do a good job of reordering blocks.  Do
-     not enable reordering unless it is explicitly requested.  */
-  flag_reorder_blocks = 0;
-}
-
 /* A C compound statement to output to stdio stream STREAM the
    assembler syntax for an instruction operand X.  X is an RTL
    expression.
@@ -2435,8 +2486,9 @@ print_operand_address (FILE *file, rtx addr)
     }
 }
 
+/* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA.  */
 
-bool
+static bool
 xtensa_output_addr_const_extra (FILE *fp, rtx x)
 {
   if (GET_CODE (x) == UNSPEC && XVECLEN (x, 0) == 1)
@@ -2636,10 +2688,10 @@ xtensa_expand_prologue (void)
   note_rtx = gen_rtx_SET (VOIDmode, (frame_pointer_needed
                                     ? hard_frame_pointer_rtx
                                     : stack_pointer_rtx),
-                         plus_constant (stack_pointer_rtx, -total_size));
+                         plus_constant (Pmode, stack_pointer_rtx,
+                                        -total_size));
   RTX_FRAME_RELATED_P (insn) = 1;
-  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
-                                       note_rtx, REG_NOTES (insn));
+  add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
 }
 
 
@@ -2662,7 +2714,7 @@ xtensa_return_addr (int count, rtx frame)
     retaddr = gen_rtx_REG (Pmode, A0_REG);
   else
     {
-      rtx addr = plus_constant (frame, -4 * UNITS_PER_WORD);
+      rtx addr = plus_constant (Pmode, frame, -4 * UNITS_PER_WORD);
       addr = memory_address (Pmode, addr);
       retaddr = gen_reg_rtx (Pmode);
       emit_move_insn (retaddr, gen_rtx_MEM (Pmode, addr));
@@ -2692,6 +2744,18 @@ xtensa_return_addr (int count, rtx frame)
   return result;
 }
 
+/* Disable the use of word-sized or smaller complex modes for structures,
+   and for function arguments in particular, where they cause problems with
+   register a7.  The xtensa_copy_incoming_a7 function assumes that there is
+   a single reference to an argument in a7, but with small complex modes the
+   real and imaginary components may be extracted separately, leading to two
+   uses of the register, only one of which would be replaced.  */
+
+static bool
+xtensa_member_type_forces_blk (const_tree, enum machine_mode mode)
+{
+  return mode == CQImode || mode == CHImode;
+}
 
 /* Create the va_list data type.
 
@@ -2808,7 +2872,7 @@ xtensa_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
 
   /* Set the __va_stk member to ($arg_ptr - 32).  */
   u = make_tree (ptr_type_node, virtual_incoming_args_rtx);
-  u = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, u, size_int (-32));
+  u = fold_build_pointer_plus_hwi (u, -32);
   t = build2 (MODIFY_EXPR, ptr_type_node, stk, u);
   TREE_SIDE_EFFECTS (t) = 1;
   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
@@ -2997,7 +3061,7 @@ xtensa_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
 
   t = fold_convert (sizetype, unshare_expr (ndx));
   t = build2 (MINUS_EXPR, sizetype, t, size);
-  addr = build2 (POINTER_PLUS_EXPR, ptr_type_node, unshare_expr (array), t);
+  addr = fold_build_pointer_plus (unshare_expr (array), t);
 
   addr = fold_convert (build_pointer_type (type), addr);
   if (indirect)
@@ -3034,7 +3098,7 @@ xtensa_init_builtins (void)
 
   if (TARGET_THREADPTR)
     {
-      ftype = build_function_type (ptr_type_node, void_list_node);
+      ftype = build_function_type_list (ptr_type_node, NULL_TREE);
       decl = add_builtin_function ("__builtin_thread_pointer", ftype,
                                   XTENSA_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
                                   NULL, NULL_TREE);
@@ -3120,11 +3184,12 @@ xtensa_expand_builtin (tree exp, rtx target,
   return NULL_RTX;
 }
 
+/* Worker function for TARGET_PREFERRED_RELOAD_CLASS.  */
 
-enum reg_class
-xtensa_preferred_reload_class (rtx x, enum reg_class rclass, int isoutput)
+static reg_class_t
+xtensa_preferred_reload_class (rtx x, reg_class_t rclass)
 {
-  if (!isoutput && CONSTANT_P (x) && GET_CODE (x) == CONST_DOUBLE)
+  if (CONSTANT_P (x) && CONST_DOUBLE_P (x))
     return NO_REGS;
 
   /* Don't use the stack pointer or hard frame pointer for reloads!
@@ -3139,8 +3204,27 @@ xtensa_preferred_reload_class (rtx x, enum reg_class rclass, int isoutput)
   return rclass;
 }
 
+/* Worker function for TARGET_PREFERRED_OUTPUT_RELOAD_CLASS.  */
+
+static reg_class_t
+xtensa_preferred_output_reload_class (rtx x ATTRIBUTE_UNUSED,
+                                     reg_class_t rclass)
+{
+  /* Don't use the stack pointer or hard frame pointer for reloads!
+     The hard frame pointer would normally be OK except that it may
+     briefly hold an incoming argument in the prologue, and reload
+     won't know that it is live because the hard frame pointer is
+     treated specially.  */
+
+  if (rclass == AR_REGS || rclass == GR_REGS)
+    return RL_REGS;
+
+  return rclass;
+}
+
+/* Worker function for TARGET_SECONDARY_RELOAD.  */
 
-reg_class_t
+static reg_class_t
 xtensa_secondary_reload (bool in_p, rtx x, reg_class_t rclass,
                         enum machine_mode mode, secondary_reload_info *sri)
 {
@@ -3243,14 +3327,42 @@ xtensa_select_rtx_section (enum machine_mode mode ATTRIBUTE_UNUSED,
   return function_section (current_function_decl);
 }
 
+/* Worker function for TARGET_REGISTER_MOVE_COST.  */
+
+static int
+xtensa_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+                          reg_class_t from, reg_class_t to)
+{
+  if (from == to && from != BR_REGS && to != BR_REGS)
+    return 2;
+  else if (reg_class_subset_p (from, AR_REGS)
+          && reg_class_subset_p (to, AR_REGS))
+    return 2;
+  else if (reg_class_subset_p (from, AR_REGS) && to == ACC_REG)
+    return 3;
+  else if (from == ACC_REG && reg_class_subset_p (to, AR_REGS))
+    return 3;
+  else
+    return 10;
+}
+
+/* Worker function for TARGET_MEMORY_MOVE_COST.  */
+
+static int
+xtensa_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+                        reg_class_t rclass ATTRIBUTE_UNUSED,
+                        bool in ATTRIBUTE_UNUSED)
+{
+  return 4;
+}
 
 /* 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
-xtensa_rtx_costs (rtx x, int code, int outer_code, int *total,
-                 bool speed ATTRIBUTE_UNUSED)
+xtensa_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+                 int *total, bool speed ATTRIBUTE_UNUSED)
 {
   switch (code)
     {
@@ -3490,6 +3602,24 @@ xtensa_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED,
                      outgoing ? GP_OUTGOING_RETURN : GP_RETURN);
 }
 
+/* Worker function for TARGET_LIBCALL_VALUE.  */
+
+static rtx
+xtensa_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG ((GET_MODE_CLASS (mode) == MODE_INT
+                      && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+                     ? SImode : mode, GP_RETURN);
+}
+
+/* Worker function TARGET_FUNCTION_VALUE_REGNO_P.  */
+
+static bool
+xtensa_function_value_regno_p (const unsigned int regno)
+{
+  return (regno == GP_RETURN);
+}
+
 /* The static chain is passed in memory.  Provide rtx giving 'mem'
    expressions that denote where they are stored.  */
 
@@ -3497,7 +3627,8 @@ static rtx
 xtensa_static_chain (const_tree ARG_UNUSED (fndecl), bool incoming_p)
 {
   rtx base = incoming_p ? arg_pointer_rtx : stack_pointer_rtx;
-  return gen_frame_mem (Pmode, plus_constant (base, -5 * UNITS_PER_WORD));
+  return gen_frame_mem (Pmode, plus_constant (Pmode, base,
+                                             -5 * UNITS_PER_WORD));
 }
 
 
@@ -3591,8 +3722,15 @@ xtensa_trampoline_init (rtx m_tramp, tree fndecl, rtx chain)
   emit_move_insn (adjust_address (m_tramp, SImode, chain_off), chain);
   emit_move_insn (adjust_address (m_tramp, SImode, func_off), func);
   emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_sync_caches"),
-                    0, VOIDmode, 1, XEXP (m_tramp, 0), Pmode);
+                    LCT_NORMAL, VOIDmode, 1, XEXP (m_tramp, 0), Pmode);
 }
 
+/* Implement TARGET_LEGITIMATE_CONSTANT_P.  */
+
+static bool
+xtensa_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+  return !xtensa_tls_referenced_p (x);
+}
 
 #include "gt-xtensa.h"