diff gcc/config/mn10300/mn10300.c @ 55:77e2b8dfacca gcc-4.4.5

update it from 4.4.3 to 4.5.0
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Fri, 12 Feb 2010 23:39:51 +0900
parents a06113de4d67
children b7f97abdc517
line wrap: on
line diff
--- a/gcc/config/mn10300/mn10300.c	Sun Feb 07 18:28:00 2010 +0900
+++ b/gcc/config/mn10300/mn10300.c	Fri Feb 12 23:39:51 2010 +0900
@@ -1,6 +1,6 @@
 /* Subroutines for insn-output.c for Matsushita MN10300 series
    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
    Contributed by Jeff Law (law@cygnus.com).
 
 This file is part of GCC.
@@ -69,6 +69,7 @@
 
 
 static bool mn10300_handle_option (size_t, const char *, int);
+static bool mn10300_legitimate_address_p (enum machine_mode, rtx, bool);
 static int mn10300_address_cost_1 (rtx, int *);
 static int mn10300_address_cost (rtx, bool);
 static bool mn10300_rtx_costs (rtx, int, int, int *, bool);
@@ -76,15 +77,25 @@
 static bool mn10300_return_in_memory (const_tree, const_tree);
 static rtx mn10300_builtin_saveregs (void);
 static void mn10300_va_start (tree, rtx);
+static rtx mn10300_legitimize_address (rtx, rtx, enum machine_mode);
 static bool mn10300_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
 				       const_tree, bool);
 static int mn10300_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
 				      tree, bool);
+static unsigned int mn10300_case_values_threshold (void);
+static void mn10300_encode_section_info (tree, rtx, int);
+static void mn10300_asm_trampoline_template (FILE *);
+static void mn10300_trampoline_init (rtx, tree, rtx);
+static rtx mn10300_function_value (const_tree, const_tree, bool);
+static rtx mn10300_libcall_value (enum machine_mode, const_rtx);
 
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS mn10300_legitimize_address
+
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS mn10300_rtx_costs
 #undef TARGET_ADDRESS_COST
@@ -119,7 +130,22 @@
 #undef TARGET_EXPAND_BUILTIN_VA_START
 #define TARGET_EXPAND_BUILTIN_VA_START mn10300_va_start
 
-static void mn10300_encode_section_info (tree, rtx, int);
+#undef TARGET_CASE_VALUES_THRESHOLD
+#define TARGET_CASE_VALUES_THRESHOLD mn10300_case_values_threshold
+
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P	mn10300_legitimate_address_p
+
+#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
+#define TARGET_ASM_TRAMPOLINE_TEMPLATE mn10300_asm_trampoline_template
+#undef TARGET_TRAMPOLINE_INIT
+#define TARGET_TRAMPOLINE_INIT mn10300_trampoline_init
+
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE mn10300_function_value
+#undef TARGET_LIBCALL_VALUE
+#define TARGET_LIBCALL_VALUE mn10300_libcall_value
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Implement TARGET_HANDLE_OPTION.  */
@@ -1605,8 +1631,10 @@
    we only return the PARALLEL for outgoing values; we do not want
    callers relying on this extra copy.  */
 
-rtx
-mn10300_function_value (const_tree valtype, const_tree func, int outgoing)
+static rtx
+mn10300_function_value (const_tree valtype,
+			const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
+			bool outgoing)
 {
   rtx rv;
   enum machine_mode mode = TYPE_MODE (valtype);
@@ -1630,6 +1658,23 @@
   return rv;
 }
 
+/* Implements TARGET_LIBCALL_VALUE.  */
+
+static rtx
+mn10300_libcall_value (enum machine_mode mode,
+		       const_rtx fun ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (mode, FIRST_DATA_REGNUM);
+}
+
+/* Implements FUNCTION_VALUE_REGNO_P.  */
+
+bool
+mn10300_function_value_regno_p (const unsigned int regno)
+{
+ return (regno == FIRST_DATA_REGNUM || regno == FIRST_ADDRESS_REGNUM);
+}
+
 /* Output a tst insn.  */
 const char *
 output_tst (rtx operand, rtx insn)
@@ -1782,17 +1827,14 @@
    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.
-
    Normally it is always safe for this macro to do nothing.  It exists to
    recognize opportunities to optimize the output.
 
    But on a few ports with segmented architectures and indexed addressing
    (mn10300, hppa) it is used to rewrite certain problematical addresses.  */
 rtx
-legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
-		    enum machine_mode mode ATTRIBUTE_UNUSED)
+mn10300_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+			    enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   if (flag_pic && ! legitimate_pic_operand_p (x))
     x = legitimize_pic_address (oldx, NULL_RTX);
@@ -1892,9 +1934,21 @@
 }
 
 /* Return TRUE if the address X, taken from a (MEM:MODE X) rtx, is
-   legitimate, and FALSE otherwise.  */
+   legitimate, and FALSE otherwise.
+
+   On the mn10300, 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.
+
+   Note it is still possible to use reg+reg addressing modes,
+   it's just much more difficult.  For a discussion of a possible
+   workaround and solution, see the comments in pa.c before the
+   function record_unscaled_index_insn_codes.  */
+
 bool
-legitimate_address_p (enum machine_mode mode, rtx x, int strict)
+mn10300_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
 {
   if (CONSTANT_ADDRESS_P (x)
       && (! flag_pic || legitimate_pic_operand_p (x)))
@@ -2022,7 +2076,7 @@
     {
     case CONST_INT:
       /* Zeros are extremely cheap.  */
-      if (INTVAL (x) == 0 && outer_code == SET)
+      if (INTVAL (x) == 0 && (outer_code == SET || outer_code == COMPARE))
 	*total = 0;
       /* If it fits in 8 bits, then it's still relatively cheap.  */
       else if (INT_8_BITS (INTVAL (x)))
@@ -2051,6 +2105,12 @@
       *total = 8;
       return true;
 
+    case ZERO_EXTRACT:
+      /* This is cheap, we can use btst.  */
+      if (outer_code == COMPARE)
+	*total = 0;
+      return false;
+
    /* ??? This probably needs more work.  */
     case MOD:
     case DIV:
@@ -2126,3 +2186,48 @@
   if (flag_pic)
     SYMBOL_REF_FLAG (symbol) = (*targetm.binds_local_p) (decl);
 }
+
+/* Dispatch tables on the mn10300 are extremely expensive in terms of code
+   and readonly data size.  So we crank up the case threshold value to
+   encourage a series of if/else comparisons to implement many small switch
+   statements.  In theory, this value could be increased much more if we
+   were solely optimizing for space, but we keep it "reasonable" to avoid
+   serious code efficiency lossage.  */
+
+unsigned int mn10300_case_values_threshold (void)
+{
+  return 6;
+}
+
+/* Worker function for TARGET_ASM_TRAMPOLINE_TEMPLATE.  */
+
+static void
+mn10300_asm_trampoline_template (FILE *f)
+{
+  fprintf (f, "\tadd -4,sp\n");
+  fprintf (f, "\t.long 0x0004fffa\n");
+  fprintf (f, "\tmov (0,sp),a0\n");
+  fprintf (f, "\tadd 4,sp\n");
+  fprintf (f, "\tmov (13,a0),a1\n");	
+  fprintf (f, "\tmov (17,a0),a0\n");
+  fprintf (f, "\tjmp (a0)\n");
+  fprintf (f, "\t.long 0\n");
+  fprintf (f, "\t.long 0\n");
+}
+
+/* Worker function for TARGET_TRAMPOLINE_INIT.  */
+
+static void
+mn10300_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
+{
+  rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
+  rtx mem;
+
+  emit_block_move (m_tramp, assemble_trampoline_template (),
+		   GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
+
+  mem = adjust_address (m_tramp, SImode, 0x14);
+  emit_move_insn (mem, chain_value);
+  mem = adjust_address (m_tramp, SImode, 0x18);
+  emit_move_insn (mem, fnaddr);
+}