Commit 822e895c by Bob Wilson Committed by Bob Wilson

xtensa.c (function_arg): Handle 16-byte aligned args.

	* config/xtensa/xtensa.c (function_arg): Handle 16-byte aligned args.
	(xtensa_va_start): Initialize __va_stk to ($arg_ptr - 32).  Adjust
	__va_ndx by 2 words when referencing an argument on the stack.
	(xtensa_va_arg): Handle 16-byte aligned args.  Adjust __va_ndx by 2
	words when an arg on the stack is first seen.

From-SVN: r78990
parent d5e63fce
2004-03-05 Bob Wilson <bob.wilson@acm.org>
* config/xtensa/xtensa.c (function_arg): Handle 16-byte aligned args.
(xtensa_va_start): Initialize __va_stk to ($arg_ptr - 32). Adjust
__va_ndx by 2 words when referencing an argument on the stack.
(xtensa_va_arg): Handle 16-byte aligned args. Adjust __va_ndx by 2
words when an arg on the stack is first seen.
2004-03-05 Paul Brook <paul@codesourcery.com> 2004-03-05 Paul Brook <paul@codesourcery.com>
* arm.h (ARM_FLAG_VFP): Remove. * arm.h (ARM_FLAG_VFP): Remove.
......
...@@ -1805,7 +1805,10 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, ...@@ -1805,7 +1805,10 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
: int_size_in_bytes (type)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; : int_size_in_bytes (type)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
if (type && (TYPE_ALIGN (type) > BITS_PER_WORD)) if (type && (TYPE_ALIGN (type) > BITS_PER_WORD))
*arg_words += (*arg_words & 1); {
int align = TYPE_ALIGN (type) / BITS_PER_WORD;
*arg_words = (*arg_words + align - 1) & -align;
}
if (*arg_words + words > max) if (*arg_words + words > max)
return (rtx)0; return (rtx)0;
...@@ -2335,17 +2338,20 @@ xtensa_return_addr (int count, rtx frame) ...@@ -2335,17 +2338,20 @@ xtensa_return_addr (int count, rtx frame)
/* Create the va_list data type. /* Create the va_list data type.
This structure is set up by __builtin_saveregs. The __va_reg
field points to a stack-allocated region holding the contents of the This structure is set up by __builtin_saveregs. The __va_reg field
incoming argument registers. The __va_ndx field is an index initialized points to a stack-allocated region holding the contents of the
to the position of the first unnamed (variable) argument. This same index incoming argument registers. The __va_ndx field is an index
is also used to address the arguments passed in memory. Thus, the initialized to the position of the first unnamed (variable)
__va_stk field is initialized to point to the position of the first argument. This same index is also used to address the arguments
argument in memory offset to account for the arguments passed in passed in memory. Thus, the __va_stk field is initialized to point
registers. E.G., if there are 6 argument registers, and each register is to the position of the first argument in memory offset to account
4 bytes, then __va_stk is set to $sp - (6 * 4); then __va_reg[N*4] for the arguments passed in registers and to account for the size
references argument word N for 0 <= N < 6, and __va_stk[N*4] references of the argument registers not being 16-byte aligned. E.G., there
argument word N for N >= 6. */ are 6 argument registers of 4 bytes each, but we want the __va_ndx
for the first stack argument to have the maximal alignment of 16
bytes, so we offset the __va_stk address by 32 bytes so that
__va_stk[32] references the first argument on the stack. */
static tree static tree
xtensa_build_builtin_va_list (void) xtensa_build_builtin_va_list (void)
...@@ -2436,15 +2442,18 @@ xtensa_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED) ...@@ -2436,15 +2442,18 @@ xtensa_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
TREE_SIDE_EFFECTS (t) = 1; TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
/* Set the __va_stk member to $arg_ptr - (size of __va_reg area) */ /* Set the __va_stk member to ($arg_ptr - 32). */
u = make_tree (ptr_type_node, virtual_incoming_args_rtx); u = make_tree (ptr_type_node, virtual_incoming_args_rtx);
u = fold (build (PLUS_EXPR, ptr_type_node, u, u = fold (build (PLUS_EXPR, ptr_type_node, u, build_int_2 (-32, -1)));
build_int_2 (-MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, -1)));
t = build (MODIFY_EXPR, ptr_type_node, stk, u); t = build (MODIFY_EXPR, ptr_type_node, stk, u);
TREE_SIDE_EFFECTS (t) = 1; TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
/* Set the __va_ndx member. */ /* Set the __va_ndx member. If the first variable argument is on
the stack, adjust __va_ndx by 2 words to account for the extra
alignment offset for __va_stk. */
if (arg_words >= MAX_ARGS_IN_REGISTERS)
arg_words += 2;
u = build_int_2 (arg_words * UNITS_PER_WORD, 0); u = build_int_2 (arg_words * UNITS_PER_WORD, 0);
t = build (MODIFY_EXPR, integer_type_node, ndx, u); t = build (MODIFY_EXPR, integer_type_node, ndx, u);
TREE_SIDE_EFFECTS (t) = 1; TREE_SIDE_EFFECTS (t) = 1;
...@@ -2506,17 +2515,19 @@ xtensa_va_arg (tree valist, tree type) ...@@ -2506,17 +2515,19 @@ xtensa_va_arg (tree valist, tree type)
emit_move_insn (va_size, r); emit_move_insn (va_size, r);
/* First align __va_ndx to a double word boundary if necessary for this arg: /* First align __va_ndx if necessary for this arg:
if (__alignof__ (TYPE) > 4) if (__alignof__ (TYPE) > 4 )
(AP).__va_ndx = (((AP).__va_ndx + 7) & -8); */ (AP).__va_ndx = (((AP).__va_ndx + __alignof__ (TYPE) - 1)
& -__alignof__ (TYPE)); */
if (TYPE_ALIGN (type) > BITS_PER_WORD) if (TYPE_ALIGN (type) > BITS_PER_WORD)
{ {
int align = TYPE_ALIGN (type) / BITS_PER_UNIT;
tmp = build (PLUS_EXPR, integer_type_node, ndx, tmp = build (PLUS_EXPR, integer_type_node, ndx,
build_int_2 ((2 * UNITS_PER_WORD) - 1, 0)); build_int_2 (align - 1, 0));
tmp = build (BIT_AND_EXPR, integer_type_node, tmp, tmp = build (BIT_AND_EXPR, integer_type_node, tmp,
build_int_2 (-2 * UNITS_PER_WORD, -1)); build_int_2 (-align, -1));
tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp); tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp);
TREE_SIDE_EFFECTS (tmp) = 1; TREE_SIDE_EFFECTS (tmp) = 1;
expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL); expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
...@@ -2574,18 +2585,18 @@ xtensa_va_arg (tree valist, tree type) ...@@ -2574,18 +2585,18 @@ xtensa_va_arg (tree valist, tree type)
else else
{ {
if (orig_ndx < __MAX_ARGS_IN_REGISTERS * 4) if (orig_ndx <= __MAX_ARGS_IN_REGISTERS * 4)
(AP).__va_ndx = __MAX_ARGS_IN_REGISTERS * 4 + __va_size (TYPE); (AP).__va_ndx = 32 + __va_size (TYPE);
__array = (AP).__va_stk; __array = (AP).__va_stk;
} */ } */
lab_false2 = gen_label_rtx (); lab_false2 = gen_label_rtx ();
emit_cmp_and_jump_insns (orig_ndx, emit_cmp_and_jump_insns (orig_ndx,
GEN_INT (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD), GEN_INT (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD),
GE, const1_rtx, SImode, 0, lab_false2); GT, const1_rtx, SImode, 0, lab_false2);
tmp = build (PLUS_EXPR, sizetype, make_tree (intSI_type_node, va_size), tmp = build (PLUS_EXPR, sizetype, make_tree (intSI_type_node, va_size),
build_int_2 (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, 0)); build_int_2 (32, 0));
tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp); tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp);
TREE_SIDE_EFFECTS (tmp) = 1; TREE_SIDE_EFFECTS (tmp) = 1;
expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL); expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment