OSDN Git Service

* c-common.c, c-parser.c, cfgbuild.c, cfghooks.c, cfghooks.h,
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / arm.c
index aaa9daa..8924a49 100644 (file)
@@ -73,6 +73,7 @@ static int thumb_far_jump_used_p (void);
 static bool thumb_force_lr_save (void);
 static int const_ok_for_op (HOST_WIDE_INT, enum rtx_code);
 static rtx emit_sfm (int, int);
+static int arm_size_return_regs (void);
 #ifndef AOF_ASSEMBLER
 static bool arm_assemble_integer (rtx, unsigned int, int);
 #endif
@@ -373,20 +374,7 @@ enum float_abi_type arm_float_abi;
 /* Which ABI to use.  */
 enum arm_abi_type arm_abi;
 
-/* Set by the -mfpu=... option.  */
-static const char * target_fpu_name = NULL;
-
-/* Set by the -mfpe=... option.  */
-static const char * target_fpe_name = NULL;
-
-/* Set by the -mfloat-abi=... option.  */
-static const char * target_float_abi_name = NULL;
-
-/* Set by the -mabi=... option.  */
-static const char * target_abi_name = NULL;
-
 /* Used to parse -mstructure_size_boundary command line option.  */
-static const char * structure_size_string = NULL;
 int    arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY;
 
 /* Used for Thumb call_via trampolines.  */
@@ -497,7 +485,6 @@ int arm_cpp_interwork = 0;
 enum machine_mode output_memory_reference_mode;
 
 /* The register number to be used for the PIC offset register.  */
-static const char * arm_pic_register_string = NULL;
 int arm_pic_register = INVALID_REGNUM;
 
 /* Set to 1 when a return insn is output, this means that the epilogue
@@ -800,10 +787,6 @@ arm_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
 {
   switch (code)
     {
-    case OPT_mabi_:
-      target_abi_name = arg;
-      return true;
-
     case OPT_march_:
       arm_select[1].string = arg;
       return true;
@@ -812,35 +795,14 @@ arm_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
       arm_select[0].string = arg;
       return true;
 
-    case OPT_mfloat_abi_:
-      target_float_abi_name = arg;
-      return true;
-
-    case OPT_mfp_:
-    case OPT_mfpe_:
-      target_fpe_name = arg;
-      return true;
-
-    case OPT_mfpu_:
-      target_fpu_name = arg;
-      return true;
-
     case OPT_mhard_float:
       target_float_abi_name = "hard";
       return true;
 
-    case OPT_mpic_register_:
-      arm_pic_register_string = arg;
-      return true;
-
     case OPT_msoft_float:
       target_float_abi_name = "soft";
       return true;
 
-    case OPT_mstructure_size_boundary_:
-      structure_size_string = arg;
-      return true;
-
     case OPT_mtune_:
       arm_select[2].string = arg;
       return true;
@@ -1465,9 +1427,11 @@ use_return_insn (int iscond, rtx sibling)
       if (!call_used_regs[3])
        return 0;
 
-      /* ... that it isn't being used for a return value (always true
-        until we implement return-in-regs), or for a tail-call
-        argument ...  */
+      /* ... that it isn't being used for a return value ... */
+      if (arm_size_return_regs () >= (4 * UNITS_PER_WORD))
+       return 0;
+
+      /* ... or for a tail-call argument ...  */
       if (sibling)
        {
          gcc_assert (GET_CODE (sibling) == CALL_INSN);
@@ -1914,6 +1878,41 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond,
            }
        }
 
+      /* See if we can calculate the value as the difference between two
+        valid immediates.  */
+      if (clear_sign_bit_copies + clear_zero_bit_copies <= 16)
+       {
+         int topshift = clear_sign_bit_copies & ~1;
+
+         temp1 = ARM_SIGN_EXTEND ((remainder + (0x00800000 >> topshift))
+                                  & (0xff000000 >> topshift));
+
+         /* If temp1 is zero, then that means the 9 most significant
+            bits of remainder were 1 and we've caused it to overflow.
+            When topshift is 0 we don't need to do anything since we
+            can borrow from 'bit 32'.  */
+         if (temp1 == 0 && topshift != 0)
+           temp1 = 0x80000000 >> (topshift - 1);
+
+         temp2 = ARM_SIGN_EXTEND (temp1 - remainder);
+         
+         if (const_ok_for_arm (temp2))
+           {
+             if (generate)
+               {
+                 rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
+                 emit_constant_insn (cond,
+                                     gen_rtx_SET (VOIDmode, new_src,
+                                                  GEN_INT (temp1)));
+                 emit_constant_insn (cond,
+                                     gen_addsi3 (target, new_src,
+                                                 GEN_INT (-temp2)));
+               }
+
+             return 2;
+           }
+       }
+
       /* See if we can generate this by setting the bottom (or the top)
         16 bits, and then shifting these into the other half of the
         word.  We only look for the simplest cases, to do more would cost
@@ -2432,6 +2431,7 @@ arm_return_in_memory (tree type)
   HOST_WIDE_INT size;
 
   if (!AGGREGATE_TYPE_P (type) &&
+      (TREE_CODE (type) != VECTOR_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.  */
@@ -2446,6 +2446,11 @@ arm_return_in_memory (tree type)
       return (size < 0 || size > UNITS_PER_WORD);
     }
 
+  /* To maximize backwards compatibility with previous versions of gcc,
+     return vectors up to 4 words in registers.  */
+  if (TREE_CODE (type) == VECTOR_TYPE)
+    return (size < 0 || size > (4 * UNITS_PER_WORD));
+
   /* For the arm-wince targets we choose to be compatible with Microsoft's
      ARM and Thumb compilers, which always return aggregates in memory.  */
 #ifndef ARM_WINCE
@@ -2768,7 +2773,7 @@ arm_handle_fndecl_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
 {
   if (TREE_CODE (*node) != FUNCTION_DECL)
     {
-      warning (0, "%qs attribute only applies to functions",
+      warning (OPT_Wattributes, "%qs attribute only applies to functions",
               IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
@@ -2786,7 +2791,7 @@ arm_handle_isr_attribute (tree *node, tree name, tree args, int flags,
     {
       if (TREE_CODE (*node) != FUNCTION_DECL)
        {
-         warning (0, "%qs attribute only applies to functions",
+         warning (OPT_Wattributes, "%qs attribute only applies to functions",
                   IDENTIFIER_POINTER (name));
          *no_add_attrs = true;
        }
@@ -2800,7 +2805,8 @@ arm_handle_isr_attribute (tree *node, tree name, tree args, int flags,
        {
          if (arm_isr_value (args) == ARM_FT_UNKNOWN)
            {
-             warning (0, "%qs attribute ignored", IDENTIFIER_POINTER (name));
+             warning (OPT_Wattributes, "%qs attribute ignored",
+                      IDENTIFIER_POINTER (name));
              *no_add_attrs = true;
            }
        }
@@ -2827,7 +2833,8 @@ arm_handle_isr_attribute (tree *node, tree name, tree args, int flags,
            }
          else
            {
-             warning (0, "%qs attribute ignored", IDENTIFIER_POINTER (name));
+             warning (OPT_Wattributes, "%qs attribute ignored",
+                      IDENTIFIER_POINTER (name));
            }
        }
     }
@@ -6969,7 +6976,7 @@ add_minipool_forward_ref (Mfix *fix)
   /* If this fix's address is greater than the address of the first
      entry, then we can't put the fix in this pool.  We subtract the
      size of the current fix to ensure that if the table is fully
-     packed we still have enough room to insert this value by suffling
+     packed we still have enough room to insert this value by shuffling
      the other fixes forwards.  */
   if (minipool_vector_head &&
       fix->address >= minipool_vector_head->max_address - fix->fix_size)
@@ -9810,6 +9817,20 @@ emit_multi_reg_push (unsigned long mask)
   return par;
 }
 
+/* Calculate the size of the return value that is passed in registers.  */
+static int
+arm_size_return_regs (void)
+{
+  enum machine_mode mode;
+
+  if (current_function_return_rtx != 0)
+    mode = GET_MODE (current_function_return_rtx);
+  else
+    mode = DECL_MODE (DECL_RESULT (current_function_decl));
+
+  return GET_MODE_SIZE (mode);
+}
+
 static rtx
 emit_sfm (int base_reg, int count)
 {
@@ -12864,7 +12885,6 @@ thumb_unexpanded_epilogue (void)
   int high_regs_pushed = 0;
   int had_to_push_lr;
   int size;
-  int mode;
 
   if (return_used_this_function)
     return "";
@@ -12879,13 +12899,7 @@ thumb_unexpanded_epilogue (void)
      This is more reliable that examining regs_ever_live[] because that
      will be set if the register is ever used in the function, not just if
      the register is used to hold a return value.  */
-
-  if (current_function_return_rtx != 0)
-    mode = GET_MODE (current_function_return_rtx);
-  else
-    mode = DECL_MODE (DECL_RESULT (current_function_decl));
-
-  size = GET_MODE_SIZE (mode);
+  size = arm_size_return_regs ();
 
   /* The prolog may have pushed some high registers to use as
      work registers.  e.g. the testsuite file:
@@ -13478,7 +13492,7 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
       asm_fprintf (f, "\tmov\t%r, %r\t\t%@ Backtrace structure created\n",
                   ARM_HARD_FRAME_POINTER_REGNUM, work_register);
     }
-  /* Optimisation:  If we are not pushing any low registers but we are going
+  /* Optimization:  If we are not pushing any low registers but we are going
      to push some high registers then delay our first push.  This will just
      be a push of LR and we can combine it with the push of the first high
      register.  */
@@ -14422,7 +14436,7 @@ arm_cxx_guard_type (void)
 }
 
 
-/* The EABI says test the least significan bit of a guard variable.  */
+/* The EABI says test the least significant bit of a guard variable.  */
 
 static bool
 arm_cxx_guard_mask_bit (void)