This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] AAPCS small aggregate argument passing/return in big-endianmode [csl-arm-branch]


This is a patch to correct passing and returning of small aggregates and small complex values to and from functions in big-endian mode in accordance with the ARM AAPCS. It incorporates a backported patch from mainline by Richard Sandiford which cleans up the handling of return_in_msb, since not doing so exposed a bug in the handling of complex return values. The original patch is here:

http://gcc.gnu.org/ml/gcc-patches/2004-11/msg01490.html

Tested with no regressions with cross-compilation to arm-none-eabi in both big-endian and little-endian ARM modes. Additionally, a number of test cases are fixed in both modes.

The patch should be applied to csl-arm-branch.

ChangeLog:

2005-01-25 Julian Brown <julian@codesourcery.com>

	* calls.c (shift_returned_value): Delete in favour of...
	(shift_return_value): ...this function. Leave the caller to
	check for non-BLKmode values passed in the msb of a register.
	Take said mode and a shift direction as argument.  Operate on
	the hard function value, not a pseudo.
	* (expand_call): Adjust accordingly
	* expr.h (shift_return_value): Declare
	* function.c (expand_function_start): If a non-BLKmode return
	value is padded at the last significant end of the return
	register, use the return value's natural mode for the
	DECL_RESULT, not the mode of the padded register.
        (expand_function_end): Shift the same sort of return values left
	by the appropriate amount.
        * optabs.c (simplify_expand_binop): New function, backported
	from mainline.
        (force_expand_binop): New function, backported from mainline and
        exported.
        * optabs.h (force_expand_binop): Declare.
        * stmt.c (shift_return_value): Delete.
        (expand_return): Don't call shift_return_value
        * config/arm/arm-protos.h (arm_must_pass_in_stack): Declare.
        (arm_pad_arg_upward): Declare:
        (arm_pad_reg_upward): Declare.
        * config/arm/arm.c (TARGET_RETURN_IN_MSB): Define target hook
	as...
        (arm_return_in_msb): New function, specifying when values
	returned in registers should be aligned to the most-significant
	end.
        (arm_function_value): If necessary (aggregates and complex
	values of word size or less), promote the return type of a
	function to SImode to enable padding to word size.
        (arm_must_pass_in_stack): New function, returns false for small
        aggregates so they can be passed in registers (the default
        implementation passes them in the stack).
        (arm_pad_arg_upward): New function, fixes argument padding on
	the stack in big-endian AAPCS mode.
        (arm_pad_reg_upward): New function, fixes argument padding in
	registers in big-endian AAPCS mode.
        * config/arm/arm.h (PROMOTE_FUNCTION_MODE): modes of mode class
        MODE_COMPLEX_INT are also promoted to SImode.
        (MUST_PASS_IN_STACK): Define.
        (FUNCTION_ARG_PADDING): Define.
        (BLOCK_REG_PADDING): Define.
        (PAD_VARARGS_DOWN): For AAPCS, varargs are always padded upwards
        regardless of endianness.

--
Julian Brown
CodeSourcery, LLC
Index: gcc/calls.c
===================================================================
RCS file: /home/gcc/repos/gcc/gcc/gcc/calls.c,v
retrieving revision 1.304.4.7
diff -c -p -r1.304.4.7 calls.c
*** gcc/calls.c	16 Aug 2004 17:12:57 -0000	1.304.4.7
--- gcc/calls.c	24 Jan 2005 19:17:09 -0000
*************** static int check_sibcall_argument_overla
*** 149,155 ****
  static int combine_pending_stack_adjustment_and_call (int, struct args_size *,
  						      int);
  static tree fix_unsafe_tree (tree);
- static bool shift_returned_value (tree, rtx *);
  
  #ifdef REG_PARM_STACK_SPACE
  static rtx save_fixed_argument_area (int, rtx, int *, int *);
--- 149,154 ----
*************** fix_unsafe_tree (tree t)
*** 2025,2055 ****
  }
  
  
! /* If function value *VALUE was returned at the most significant end of a
!    register, shift it towards the least significant end and convert it to
!    TYPE's mode.  Return true and update *VALUE if some action was needed.
  
!    TYPE is the type of the function's return value, which is known not
!    to have mode BLKmode.  */
! 
! static bool
! shift_returned_value (tree type, rtx *value)
  {
!   if (targetm.calls.return_in_msb (type))
!     {
!       HOST_WIDE_INT shift;
  
!       shift = (GET_MODE_BITSIZE (GET_MODE (*value))
! 	       - BITS_PER_UNIT * int_size_in_bytes (type));
!       if (shift > 0)
! 	{
! 	  *value = expand_binop (GET_MODE (*value), lshr_optab, *value,
! 				 GEN_INT (shift), 0, 1, OPTAB_WIDEN);
! 	  *value = convert_to_mode (TYPE_MODE (type), *value, 0);
! 	  return true;
! 	}
!     }
!   return false;
  }
  
  /* Generate all the code for a function call
--- 2024,2051 ----
  }
  
  
! /* Given that a function returns a value of mode MODE at the most
!    significant end of hard register VALUE, shift VALUE left or right
!    as specified by LEFT_P.  Return true if some action was needed.  */
  
! bool
! shift_return_value (enum machine_mode mode, bool left_p, rtx value)
  {
!   HOST_WIDE_INT shift;
  
!   if (!(REG_P (value) && HARD_REGISTER_P (value)))
!     abort ();
!   shift = GET_MODE_BITSIZE (GET_MODE (value)) - GET_MODE_BITSIZE (mode);
!   if (shift == 0)
!     return false;
! 
!   /* Use ashr rather than lshr for right shifts.  This is for the benefit
!      of the MIPS port, which requires SImode values to be sign-extended
!      when stored in 64-bit registers.  */
!   if (!force_expand_binop (GET_MODE (value), left_p ? ashl_optab : ashr_optab,
!                            value, GEN_INT (shift), value, 1, OPTAB_WIDEN))
!     abort ();
!   return true;
  }
  
  /* Generate all the code for a function call
*************** expand_call (tree exp, rtx target, int i
*** 3146,3151 ****
--- 3142,3161 ----
  		   next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
  		   flags, & args_so_far);
  
+       /* If a non-BLKmode value is returned at the most significant end
+          of a register, shift the register right by the appropriate amount
+          and update VALREG accordingly.  BLKmode values are handled by the
+          group load/store machinery below.  */
+       if (!structure_value_addr
+           && !pcc_struct_value
+           && TYPE_MODE (TREE_TYPE (exp)) != BLKmode
+           && targetm.calls.return_in_msb (TREE_TYPE (exp)))
+         {
+           if (shift_return_value (TYPE_MODE (TREE_TYPE (exp)), false, valreg))
+             sibcall_failure = 1;
+           valreg = gen_rtx_REG (TYPE_MODE (TREE_TYPE (exp)), REGNO (valreg));
+         }
+ 
        /* If call is cse'able, make appropriate pair of reg-notes around it.
  	 Test valreg so we don't crash; may safely ignore `const'
  	 if return type is void.  Disable for PARALLEL return values, because
*************** expand_call (tree exp, rtx target, int i
*** 3357,3368 ****
  	  sibcall_failure = 1;
  	}
        else
! 	{
! 	  if (shift_returned_value (TREE_TYPE (exp), &valreg))
! 	    sibcall_failure = 1;
! 
! 	  target = copy_to_reg (valreg);
! 	}
  
        if (targetm.calls.promote_function_return(funtype))
  	{
--- 3367,3373 ----
  	  sibcall_failure = 1;
  	}
        else
!         target = copy_to_reg (valreg);
  
        if (targetm.calls.promote_function_return(funtype))
  	{
Index: gcc/expr.h
===================================================================
RCS file: /home/gcc/repos/gcc/gcc/gcc/expr.h,v
retrieving revision 1.149.4.3
diff -c -p -r1.149.4.3 expr.h
*** gcc/expr.h	9 Apr 2004 13:39:58 -0000	1.149.4.3
--- gcc/expr.h	24 Jan 2005 18:41:54 -0000
*************** extern rtx hard_function_value (tree, tr
*** 585,590 ****
--- 585,592 ----
  
  extern rtx prepare_call_address (rtx, tree, rtx *, int, int);
  
+ extern bool shift_return_value (enum machine_mode mode, bool, rtx);
+ 
  extern rtx expand_call (tree, rtx, int);
  
  #ifdef TREE_CODE
Index: gcc/function.c
===================================================================
RCS file: /home/gcc/repos/gcc/gcc/gcc/function.c,v
retrieving revision 1.463.4.9
diff -c -p -r1.463.4.9 function.c
*** gcc/function.c	30 Dec 2004 22:33:34 -0000	1.463.4.9
--- gcc/function.c	24 Jan 2005 19:13:24 -0000
*************** expand_function_start (tree subr, int pa
*** 6725,6746 ****
      {
        /* Compute the return values into a pseudo reg, which we will copy
  	 into the true return register after the cleanups are done.  */
! 
!       /* In order to figure out what mode to use for the pseudo, we
! 	 figure out what the mode of the eventual return register will
! 	 actually be, and use that.  */
!       rtx hard_reg
! 	= hard_function_value (TREE_TYPE (DECL_RESULT (subr)),
! 			       subr, 1);
! 
!       /* Structures that are returned in registers are not aggregate_value_p,
! 	 so we may see a PARALLEL or a REG.  */
!       if (REG_P (hard_reg))
! 	SET_DECL_RTL (DECL_RESULT (subr), gen_reg_rtx (GET_MODE (hard_reg)));
!       else if (GET_CODE (hard_reg) == PARALLEL)
! 	SET_DECL_RTL (DECL_RESULT (subr), gen_group_rtx (hard_reg));
        else
! 	abort ();
  
        /* Set DECL_REGISTER flag so that expand_function_end will copy the
  	 result to the real return register(s).  */
--- 6725,6757 ----
      {
        /* Compute the return values into a pseudo reg, which we will copy
  	 into the true return register after the cleanups are done.  */
!       tree return_type = TREE_TYPE (DECL_RESULT (subr));
!       if (TYPE_MODE (return_type) != BLKmode
!           && targetm.calls.return_in_msb (return_type))
!         /* expand_function_end will insert the appropriate padding in
!            this case.  Use the return value's natural (unpadded) mode
!            within the function proper.  */
!         SET_DECL_RTL (DECL_RESULT (subr),
!                       gen_reg_rtx (TYPE_MODE (return_type)));
        else
!         {
!           /* In order to figure out what mode to use for the pseudo, we
!              figure out what the mode of the eventual return register will
!              actually be, and use that.  */
!           rtx hard_reg = hard_function_value (return_type, subr, 1);
! 
!           /* Structures that are returned in registers are not
!              aggregate_value_p, so we may see a PARALLEL or a REG.  */
!           if (REG_P (hard_reg))
!             SET_DECL_RTL (DECL_RESULT (subr),
!                           gen_reg_rtx (GET_MODE (hard_reg)));
!           else
!             {
!               if (GET_CODE (hard_reg) != PARALLEL)
!                 abort ();
!               SET_DECL_RTL (DECL_RESULT (subr), gen_group_rtx (hard_reg));
!             }
!         }
  
        /* Set DECL_REGISTER flag so that expand_function_end will copy the
  	 result to the real return register(s).  */
*************** expand_function_end (void)
*** 7152,7161 ****
  	  if (GET_MODE (real_decl_rtl) == BLKmode)
  	    PUT_MODE (real_decl_rtl, GET_MODE (decl_rtl));
  
  	  /* If a named return value dumped decl_return to memory, then
  	     we may need to re-do the PROMOTE_MODE signed/unsigned
  	     extension.  */
! 	  if (GET_MODE (real_decl_rtl) != GET_MODE (decl_rtl))
  	    {
  	      int unsignedp = TREE_UNSIGNED (TREE_TYPE (decl_result));
  
--- 7163,7184 ----
  	  if (GET_MODE (real_decl_rtl) == BLKmode)
  	    PUT_MODE (real_decl_rtl, GET_MODE (decl_rtl));
  
+           /* If a non-BLKmode return value should be padded at the least
+              significant end of the register, shift it left by the appropriate
+              amount.  Blkmode results are handled using the group load/store
+              machinery.  */
+           if (TYPE_MODE (TREE_TYPE (decl_result)) != BLKmode
+               && targetm.calls.return_in_msb (TREE_TYPE (decl_result)))
+             {
+               emit_move_insn (gen_rtx_REG (GET_MODE (decl_rtl),
+                                            REGNO (real_decl_rtl)),
+                               decl_rtl);
+               shift_return_value (GET_MODE (decl_rtl), true, real_decl_rtl);
+             }
  	  /* If a named return value dumped decl_return to memory, then
  	     we may need to re-do the PROMOTE_MODE signed/unsigned
  	     extension.  */
!           else if (GET_MODE (real_decl_rtl) != GET_MODE (decl_rtl))
  	    {
  	      int unsignedp = TREE_UNSIGNED (TREE_TYPE (decl_result));
  
Index: gcc/optabs.c
===================================================================
RCS file: /home/gcc/repos/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.202.2.5
diff -c -p -r1.202.2.5 optabs.c
*** gcc/optabs.c	29 Sep 2004 16:08:34 -0000	1.202.2.5
--- gcc/optabs.c	24 Jan 2005 18:39:48 -0000
*************** expand_binop (enum machine_mode mode, op
*** 1869,1874 ****
--- 1869,1908 ----
    return 0;
  }
  
+ 
+ /* Like expand_binop, but return a constant rtx if the result can be
+  * calculated at compile time.  The arguments and return value are
+  * otherwise the same as for expand_binop.  */
+ 
+ static rtx
+ simplify_expand_binop (enum machine_mode mode, optab binoptab,
+                            rtx op0, rtx op1, rtx target, int unsignedp,
+                                                   enum optab_methods methods)
+ {
+   if (CONSTANT_P (op0) && CONSTANT_P (op1))
+     return simplify_gen_binary (binoptab->code, mode, op0, op1);
+   else
+     return expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods);
+ }
+ 
+ /* Like simplify_expand_binop, but always put the result in TARGET.
+  * Return true if the expansion succeeded.  */
+ 
+ bool
+ force_expand_binop (enum machine_mode mode, optab binoptab,
+                     rtx op0, rtx op1, rtx target, int unsignedp,
+                     enum optab_methods methods)
+ {
+   rtx x = simplify_expand_binop (mode, binoptab, op0, op1,
+                                  target, unsignedp, methods);
+   if (x == 0)
+     return false;
+   if (x != target)
+     emit_move_insn (target, x);
+   return true;
+ }
+ 
+ 
  /* Like expand_binop, but for open-coding vectors binops.  */
  
  static rtx
Index: gcc/optabs.h
===================================================================
RCS file: /home/gcc/repos/gcc/gcc/gcc/optabs.h,v
retrieving revision 1.19.4.2
diff -c -p -r1.19.4.2 optabs.h
*** gcc/optabs.h	18 Aug 2004 03:57:42 -0000	1.19.4.2
--- gcc/optabs.h	24 Jan 2005 18:33:05 -0000
*************** extern enum insn_code cmpmem_optab[NUM_M
*** 370,375 ****
--- 370,378 ----
  extern rtx expand_binop (enum machine_mode, optab, rtx, rtx, rtx, int,
  			 enum optab_methods);
  
+ extern bool force_expand_binop (enum machine_mode, optab, rtx, rtx, rtx, int,
+                                 enum optab_methods);
+ 
  /* Expand a binary operation with both signed and unsigned forms.  */
  extern rtx sign_expand_binop (enum machine_mode, optab, optab, rtx, rtx,
  			      rtx, int, enum optab_methods);
Index: gcc/stmt.c
===================================================================
RCS file: /home/gcc/repos/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.334.4.3
diff -c -p -r1.334.4.3 stmt.c
*** gcc/stmt.c	16 Aug 2004 17:13:11 -0000	1.334.4.3
--- gcc/stmt.c	24 Jan 2005 18:41:25 -0000
*************** static bool check_unique_operand_names (
*** 405,411 ****
  static char *resolve_operand_name_1 (char *, tree, tree);
  static void expand_null_return_1 (rtx);
  static enum br_predictor return_prediction (rtx);
- static rtx shift_return_value (rtx);
  static void expand_value_return (rtx);
  static int tail_recursion_args (tree, tree);
  static void expand_cleanups (tree, int, int);
--- 405,410 ----
*************** return_prediction (rtx val)
*** 2947,2979 ****
  }
  
  
- /* If the current function returns values in the most significant part
-    of a register, shift return value VAL appropriately.  The mode of
-    the function's return type is known not to be BLKmode.  */
- 
- static rtx
- shift_return_value (rtx val)
- {
-   tree type;
- 
-   type = TREE_TYPE (DECL_RESULT (current_function_decl));
-   if (targetm.calls.return_in_msb (type))
-     {
-       rtx target;
-       HOST_WIDE_INT shift;
- 
-       target = DECL_RTL (DECL_RESULT (current_function_decl));
-       shift = (GET_MODE_BITSIZE (GET_MODE (target))
- 	       - BITS_PER_UNIT * int_size_in_bytes (type));
-       if (shift > 0)
- 	val = expand_binop (GET_MODE (target), ashl_optab,
- 			    gen_lowpart (GET_MODE (target), val),
- 			    GEN_INT (shift), target, 1, OPTAB_WIDEN);
-     }
-   return val;
- }
- 
- 
  /* Generate RTL to return from the current function, with value VAL.  */
  
  static void
--- 2946,2951 ----
*************** expand_return (tree retval)
*** 3258,3265 ****
        val = expand_expr (retval_rhs, val, GET_MODE (val), 0);
        val = force_not_mem (val);
        emit_queue ();
        /* Return the calculated value, doing cleanups first.  */
!       expand_value_return (shift_return_value (val));
      }
    else
      {
--- 3230,3238 ----
        val = expand_expr (retval_rhs, val, GET_MODE (val), 0);
        val = force_not_mem (val);
        emit_queue ();
+ 
        /* Return the calculated value, doing cleanups first.  */
!       expand_value_return (val);
      }
    else
      {
*************** expand_return (tree retval)
*** 3267,3272 ****
--- 3240,3246 ----
  	 calculate value into hard return reg.  */
        expand_expr (retval, const0_rtx, VOIDmode, 0);
        emit_queue ();
+ 
        expand_value_return (result_rtl);
      }
  }
Index: gcc/config/arm/arm-protos.h
===================================================================
RCS file: /home/gcc/repos/gcc/gcc/gcc/config/arm/arm-protos.h,v
retrieving revision 1.60.4.16
diff -c -p -r1.60.4.16 arm-protos.h
*** gcc/config/arm/arm-protos.h	13 Oct 2004 12:49:28 -0000	1.60.4.16
--- gcc/config/arm/arm-protos.h	25 Jan 2005 13:40:24 -0000
*************** extern void arm_init_cumulative_args (CU
*** 159,164 ****
--- 159,167 ----
  extern rtx arm_va_arg (tree, tree);
  extern int arm_function_arg_pass_by_reference (CUMULATIVE_ARGS *,
  					       enum machine_mode, tree, int);
+ extern bool arm_must_pass_in_stack (enum machine_mode, 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: gcc/config/arm/arm.c
===================================================================
RCS file: /home/gcc/repos/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.303.2.67
diff -c -p -r1.303.2.67 arm.c
*** gcc/config/arm/arm.c	5 Jan 2005 18:33:22 -0000	1.303.2.67
--- gcc/config/arm/arm.c	25 Jan 2005 18:04:28 -0000
*************** static const char * arm_cxx_unwind_resum
*** 176,181 ****
--- 176,183 ----
  static bool arm_cxx_use_aeabi_atexit (void);
  static void arm_init_libfuncs (void);
  
+ static bool arm_return_in_msb (tree);
+ 
  
  /* Initialize the GCC target structure.  */
  #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
*************** static void arm_init_libfuncs (void);
*** 311,316 ****
--- 313,321 ----
  #define TARGET_EH_FNSPEC_TTABLE_INDIRECT hook_bool_void_false
  #endif
  
+ #undef TARGET_RETURN_IN_MSB
+ #define TARGET_RETURN_IN_MSB arm_return_in_msb
+ 
  struct gcc_target targetm = TARGET_INITIALIZER;
  
  /* Obstack for minipool constant handling.  */
*************** arm_canonicalize_comparison (enum rtx_co
*** 2254,2259 ****
--- 2259,2275 ----
    return code;
  }
  
+ /* 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));
+ }
  
  /* Define how to find the value returned by a function.  */
  
*************** rtx arm_function_value(tree type, tree f
*** 2263,2273 ****
    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);
    return LIBCALL_VALUE(mode);
  }
  
--- 2279,2301 ----
    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);
  }
  
*************** arm_return_in_memory (tree type)
*** 2380,2385 ****
--- 2408,2414 ----
    return 1;
  }
  
+ 
  /* Indicate whether or not words of a double are in big-endian order.  */
  
  int
*************** arm_va_arg (tree valist, tree type)
*** 2565,2570 ****
--- 2594,2664 ----
  
    return std_expand_builtin_va_arg (valist, type);
  }
+ 
+ /* Return true if a type must be passed in memory. The default definition
+    doesn't allow small aggregates (padded to the size of a word) to be passed
+    in a register, which is required for AAPCS.  */
+ 
+ bool
+ arm_must_pass_in_stack (enum machine_mode mode, tree type)
+ {
+   if (!TARGET_AAPCS_BASED)
+     return default_must_pass_in_stack (mode, type);
+ 
+   if (!type)
+     return false;
+ 
+   /* If the type has variable size...  */
+   if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+     return true;
+ 
+   /* If the type is marked as addressable (it is required
+      to be constructed into the stack)...  */
+   if (TREE_ADDRESSABLE (type))
+     return true;
+ 
+   return false;
+ }
+ 
+ 
+ /* 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, tree type, int first)
+ {
+   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;
+ }
+ 
+ 
  
  /* Encode the current state of the #pragma [no_]long_calls.  */
  typedef enum
Index: gcc/config/arm/arm.h
===================================================================
RCS file: /home/gcc/repos/gcc/gcc/gcc/config/arm/arm.h,v
retrieving revision 1.210.2.49
diff -c -p -r1.210.2.49 arm.h
*** gcc/config/arm/arm.h	5 Jan 2005 16:56:28 -0000	1.210.2.49
--- gcc/config/arm/arm.h	25 Jan 2005 13:40:59 -0000
*************** extern int arm_is_6_or_7;
*** 607,615 ****
  #define PROMOTE_FUNCTION_ARGS
  
  #define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE)	\
!   if (GET_MODE_CLASS (MODE) == MODE_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.  */
--- 607,616 ----
  #define PROMOTE_FUNCTION_ARGS
  
  #define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE)	\
!   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.  */
*************** typedef struct
*** 1751,1756 ****
--- 1752,1771 ----
  #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
    arm_function_arg_pass_by_reference (&CUM, MODE, TYPE, NAMED)
  
+ #define MUST_PASS_IN_STACK(MODE, TYPE) \
+   arm_must_pass_in_stack (MODE, TYPE)
+ 
+ #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.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]