OSDN Git Service

2009-08-28 Sebastian Pop <sebastian.pop@amd.com>
[pf3gnuchains/gcc-fork.git] / gcc / config / cris / cris.c
index 88d8999..6b3fd0f 100644 (file)
@@ -1,6 +1,6 @@
 /* Definitions for GCC.  Part of the machine description for CRIS.
-   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
-   Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+   2008, 2009  Free Software Foundation, Inc.
    Contributed by Axis Communications.  Written by Hans-Peter Nilsson.
 
 This file is part of GCC.
@@ -63,7 +63,7 @@ enum cris_retinsn_type
  { CRIS_RETINSN_UNKNOWN = 0, CRIS_RETINSN_RET, CRIS_RETINSN_JUMP };
 
 /* Per-function machine data.  */
-struct machine_function GTY(())
+struct GTY(()) machine_function
  {
    int needs_return_address_on_stack;
 
@@ -85,6 +85,9 @@ static int in_code = 0;
 /* Fix for reg_overlap_mentioned_p.  */
 static int cris_reg_overlap_mentioned_p (rtx, rtx);
 
+static enum machine_mode cris_promote_function_mode (const_tree, enum machine_mode,
+                                                    int *, const_tree, int);
+
 static void cris_print_base (rtx, FILE *);
 
 static void cris_print_index (rtx, FILE *);
@@ -122,6 +125,8 @@ static tree cris_md_asm_clobbers (tree, tree, tree);
 
 static bool cris_handle_option (size_t, const char *, int);
 
+static bool cris_frame_pointer_required (void);
+
 /* This is the parsed result of the "-max-stack-stackframe=" option.  If
    it (still) is zero, then there was no such option given.  */
 int cris_max_stackframe = 0;
@@ -164,8 +169,9 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST cris_address_cost
 
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE cris_promote_function_mode
+
 #undef TARGET_STRUCT_VALUE_RTX
 #define TARGET_STRUCT_VALUE_RTX cris_struct_value_rtx
 #undef TARGET_SETUP_INCOMING_VARARGS
@@ -180,6 +186,8 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
 #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | CRIS_SUBTARGET_DEFAULT)
 #undef TARGET_HANDLE_OPTION
 #define TARGET_HANDLE_OPTION cris_handle_option
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED cris_frame_pointer_required
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
@@ -1431,13 +1439,18 @@ cris_normal_notice_update_cc (rtx exp, rtx insn)
       if (SET_DEST (exp) == cc0_rtx)
        {
          CC_STATUS_INIT;
-         cc_status.value1 = SET_SRC (exp);
 
-         /* Handle flags for the special btstq on one bit.  */
-         if (GET_CODE (SET_SRC (exp)) == ZERO_EXTRACT
-             && XEXP (SET_SRC (exp), 1) == const1_rtx)
+         if (GET_CODE (SET_SRC (exp)) == COMPARE
+             && XEXP (SET_SRC (exp), 1) == const0_rtx)
+           cc_status.value1 = XEXP (SET_SRC (exp), 0);
+         else
+           cc_status.value1 = SET_SRC (exp);
+
+          /* Handle flags for the special btstq on one bit.  */
+         if (GET_CODE (cc_status.value1) == ZERO_EXTRACT
+             && XEXP (cc_status.value1, 1) == const1_rtx)
            {
-             if (CONST_INT_P (XEXP (SET_SRC (exp), 0)))
+             if (CONST_INT_P (XEXP (cc_status.value1, 0)))
                /* Using cmpq.  */
                cc_status.flags = CC_INVERTED;
              else
@@ -1445,7 +1458,7 @@ cris_normal_notice_update_cc (rtx exp, rtx insn)
                cc_status.flags = CC_Z_IN_NOT_N;
            }
 
-         if (GET_CODE (SET_SRC (exp)) == COMPARE)
+         else if (GET_CODE (SET_SRC (exp)) == COMPARE)
            {
              if (!REG_P (XEXP (SET_SRC (exp), 0))
                  && XEXP (SET_SRC (exp), 1) != const0_rtx)
@@ -1855,6 +1868,11 @@ cris_rtx_costs (rtx x, int code, int outer_code, int *total,
        }
       return false;
 
+    case ZERO_EXTRACT:
+      if (outer_code != COMPARE)
+        return false;
+      /* fall through */
+
     case ZERO_EXTEND: case SIGN_EXTEND:
       *total = rtx_cost (XEXP (x, 0), outer_code, speed);
       return true;
@@ -3565,14 +3583,15 @@ cris_expand_pic_call_address (rtx *opp)
 }
 
 /* Make sure operands are in the right order for an addsi3 insn as
-   generated by a define_split.  A MEM as the first operand isn't
-   recognized by addsi3 after reload.  OPERANDS contains the operands,
-   with the first at OPERANDS[N] and the second at OPERANDS[N+1].  */
+   generated by a define_split.  Nothing but REG_P as the first
+   operand is recognized by addsi3 after reload.  OPERANDS contains
+   the operands, with the first at OPERANDS[N] and the second at
+   OPERANDS[N+1].  */
 
 void
 cris_order_for_addsi3 (rtx *operands, int n)
 {
-  if (MEM_P (operands[n]))
+  if (!REG_P (operands[n]))
     {
       rtx tem = operands[n];
       operands[n] = operands[n + 1];
@@ -3738,6 +3757,25 @@ cris_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
          || CRIS_FUNCTION_ARG_SIZE (mode, type) > 8);
 }
 
+/* A combination of defining TARGET_PROMOTE_FUNCTION_MODE, promoting arguments
+   and *not* defining TARGET_PROMOTE_PROTOTYPES or PROMOTE_MODE gives the
+   best code size and speed for gcc, ipps and products in gcc-2.7.2.  */
+
+enum machine_mode
+cris_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
+                            enum machine_mode mode,
+                            int *punsignedp ATTRIBUTE_UNUSED,
+                           const_tree fntype ATTRIBUTE_UNUSED,
+                            int for_return)
+{
+  /* Defining PROMOTE_FUNCTION_RETURN in gcc-2.7.2 uncovered bug 981110 (even
+     when modifying FUNCTION_VALUE to return the promoted mode).  Maybe
+     pointless as of now, but let's keep the old behavior.  */
+  if (for_return == 1)
+    return mode;
+  return CRIS_PROMOTED_MODE (mode, *punsignedp, type);
+} 
+
 
 static int
 cris_arg_partial_bytes (CUMULATIVE_ARGS *ca, enum machine_mode mode,
@@ -3803,6 +3841,18 @@ cris_md_asm_clobbers (tree outputs, tree inputs, tree in_clobbers)
                    clobbers);
 }
 
+/* Implement TARGET_FRAME_POINTER_REQUIRED.
+
+   Really only needed if the stack frame has variable length (alloca
+   or variable sized local arguments (GNU C extension).  See PR39499 and
+   PR38609 for the reason this isn't just 0.  */
+
+bool
+cris_frame_pointer_required (void)
+{
+  return !current_function_sp_is_unchanging;
+}
+
 #if 0
 /* Various small functions to replace macros.  Only called from a
    debugger.  They might collide with gcc functions or system functions,