This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] AAPCS small aggregate argument passing/return in big-endianmode [csl-arm-branch]
- From: Julian Brown <julian at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 26 Jan 2005 14:59:15 +0000
- Subject: [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.