OSDN Git Service

* config/arm/arm.c (arm_return_in_msb): New function.
authorjules <jules@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 26 Apr 2005 16:30:37 +0000 (16:30 +0000)
committerjules <jules@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 26 Apr 2005 16:30:37 +0000 (16:30 +0000)
(arm_must_pass_in_stack): New function.
(TARGET_RETURN_IN_MSB): Define target hook.
(TARGET_MUST_PASS_IN_STACK): Define target hook.
(arm_function_value): Pad small aggregate return.
(arm_pad_arg_upward): New function.
(arm_pad_reg_upward): New function.
* config/arm/arm.h (PROMOTE_FUNCTION_MODE): Include complex values.
(FUNCTION_ARG_PADDING): Define macro.
(BLOCK_REG_PADDING): Define macro.
(PAD_VARARGS_DOWN): Correct padding for AAPCS.
* config/arm/arm-protos.h (arm_pad_arg_upward): Declare function.
(arm_pad_reg_upward): Declare function.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@98774 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/arm/arm-protos.h
gcc/config/arm/arm.c
gcc/config/arm/arm.h

index 2d441c4..07c96a5 100644 (file)
@@ -1,3 +1,19 @@
+2005-04-26  Julian Brown  <julian@codesourcery.com>
+
+       * config/arm/arm.c (arm_return_in_msb): New function.
+       (arm_must_pass_in_stack): New function.
+       (TARGET_RETURN_IN_MSB): Define target hook.
+       (TARGET_MUST_PASS_IN_STACK): Define target hook.
+       (arm_function_value): Pad small aggregate return.
+       (arm_pad_arg_upward): New function.
+       (arm_pad_reg_upward): New function.
+       * config/arm/arm.h (PROMOTE_FUNCTION_MODE): Include complex values.
+       (FUNCTION_ARG_PADDING): Define macro.
+       (BLOCK_REG_PADDING): Define macro.
+       (PAD_VARARGS_DOWN): Correct padding for AAPCS.
+       * config/arm/arm-protos.h (arm_pad_arg_upward): Declare function.
+       (arm_pad_reg_upward): Declare function.
+
 2005-04-26  Kazu Hirata  <kazu@cs.umass.edu>
 
        * basic-block.h (ei_cond): New.
index 087b475..0d20eb8 100644 (file)
@@ -121,6 +121,8 @@ extern int arm_eliminable_register (rtx);
 #if defined TREE_CODE
 extern rtx arm_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
 extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
+extern bool arm_pad_arg_upward (enum machine_mode, 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(tree, tree);
 #endif
index 8189909..cd52936 100644 (file)
@@ -165,6 +165,8 @@ static bool arm_pass_by_reference (CUMULATIVE_ARGS *,
 static bool arm_promote_prototypes (tree);
 static bool arm_default_short_enums (void);
 static bool arm_align_anon_bitfield (void);
+static bool arm_return_in_msb (tree);
+static bool arm_must_pass_in_stack (enum machine_mode, tree);
 
 static tree arm_cxx_guard_type (void);
 static bool arm_cxx_guard_mask_bit (void);
@@ -319,6 +321,12 @@ static unsigned HOST_WIDE_INT arm_shift_truncation_mask (enum machine_mode);
 #undef TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT
 #define TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT arm_cxx_class_data_always_comdat
 
+#undef TARGET_RETURN_IN_MSB
+#define TARGET_RETURN_IN_MSB arm_return_in_msb
+
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK arm_must_pass_in_stack
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Obstack for minipool constant handling.  */
@@ -2302,11 +2310,23 @@ arm_function_value(tree type, tree func ATTRIBUTE_UNUSED)
   int unsignedp ATTRIBUTE_UNUSED;
   rtx r ATTRIBUTE_UNUSED;
 
-
   mode = TYPE_MODE (type);
   /* Promote integer types.  */
   if (INTEGRAL_TYPE_P (type))
     PROMOTE_FUNCTION_MODE (mode, unsignedp, type);
+
+  /* Promotes small structs returned in a register to full-word size
+     for big-endian AAPCS.  */
+  if (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 LIBCALL_VALUE(mode);
 }
 
@@ -4905,6 +4925,17 @@ vfp_secondary_reload_class (enum machine_mode mode, rtx x)
   return GENERAL_REGS;
 }
 
+/* Values which must be returned in the most-significant end of the return
+   register.  */
+
+static bool
+arm_return_in_msb (tree valtype)
+{
+  return (TARGET_AAPCS_BASED
+          && BYTES_BIG_ENDIAN
+          && (AGGREGATE_TYPE_P (valtype)
+              || TREE_CODE (valtype) == COMPLEX_TYPE));
+}
 
 /* Returns TRUE if INSN is an "LDR REG, ADDR" instruction.
    Use by the Cirrus Maverick code which has to workaround
@@ -6503,6 +6534,59 @@ arm_reload_out_hi (rtx *operands)
                            gen_lowpart (QImode, scratch)));
     }
 }
+
+/* Return true if a type must be passed in memory. For AAPCS, small aggregates
+   (padded to the size of a word) should be passed in a register.  */
+
+static bool
+arm_must_pass_in_stack (enum machine_mode mode, tree type)
+{
+  if (TARGET_AAPCS_BASED)
+    return must_pass_in_stack_var_size (mode, type);
+  else
+    return must_pass_in_stack_var_size_or_pad (mode, type);
+}
+
+
+/* For use by FUNCTION_ARG_PADDING (MODE, TYPE).
+   Return true if an argument passed on the stack should be padded upwards,
+   i.e. if the least-significant byte has useful data.  */
+
+bool
+arm_pad_arg_upward (enum machine_mode mode, tree type)
+{
+  if (!TARGET_AAPCS_BASED)
+    return DEFAULT_FUNCTION_ARG_PADDING(mode, type);
+
+  if (type && BYTES_BIG_ENDIAN && INTEGRAL_TYPE_P (type))
+    return false;
+
+  return true;
+}
+
+
+/* Similarly, for use by BLOCK_REG_PADDING (MODE, TYPE, FIRST).
+   For non-AAPCS, return !BYTES_BIG_ENDIAN if the least significant
+   byte of the register has useful data, and return the opposite if the
+   most significant byte does.
+   For AAPCS, small aggregates and small complex types are always padded
+   upwards.  */
+
+bool
+arm_pad_reg_upward (enum machine_mode mode ATTRIBUTE_UNUSED,
+                    tree type, int first ATTRIBUTE_UNUSED)
+{
+  if (TARGET_AAPCS_BASED
+      && BYTES_BIG_ENDIAN
+      && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE)
+      && int_size_in_bytes (type) <= 4)
+    return true;
+
+  /* Otherwise, use default padding.  */
+  return !BYTES_BIG_ENDIAN;
+}
+
+
 \f
 /* Print a symbolic form of X to the debug file, F.  */
 static void
index 5955a52..61ff213 100644 (file)
@@ -607,9 +607,10 @@ extern int arm_cpp_interwork;
     }
 
 #define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE)   \
-  if (GET_MODE_CLASS (MODE) == MODE_INT                \
-      && GET_MODE_SIZE (MODE) < 4)             \
-    (MODE) = SImode;                           \
+  if ((GET_MODE_CLASS (MODE) == MODE_INT               \
+       || GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT)    \
+      && GET_MODE_SIZE (MODE) < 4)                      \
+    (MODE) = SImode;                                   \
 
 /* Define this if most significant bit is lowest numbered
    in instructions that operate on numbered bit-fields.  */
@@ -1761,6 +1762,17 @@ typedef struct
 #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
   arm_function_arg (&(CUM), (MODE), (TYPE), (NAMED))
 
+#define FUNCTION_ARG_PADDING(MODE, TYPE) \
+  (arm_pad_arg_upward (MODE, TYPE) ? upward : downward)
+
+#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
+  (arm_pad_reg_upward (MODE, TYPE, FIRST) ? upward : downward)
+
+/* For AAPCS, padding should never be below the argument. For other ABIs,
+ * mimic the default.  */
+#define PAD_VARARGS_DOWN \
+  ((TARGET_AAPCS_BASED) ? 0 : BYTES_BIG_ENDIAN)
+
 /* 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 0.