From dd52a1908e68df4088b184b027c12866b6727a9f Mon Sep 17 00:00:00 2001 From: bwilson Date: Tue, 26 Mar 2002 19:32:18 +0000 Subject: [PATCH] * config/xtensa/xtensa.c (xtensa_va_arg): Handle variable-sized types. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@51400 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 4 +++ gcc/config/xtensa/xtensa.c | 65 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 16b0964..4054887 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2002-03-26 Bob Wilson + + * config/xtensa/xtensa.c (xtensa_va_arg): Handle variable-sized types. + 2002-03-26 Richard Earnshaw PR target/5621 diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index 5abb5f8..0455737 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -2431,14 +2431,10 @@ xtensa_va_arg (valist, type) tree f_stk, stk; tree f_reg, reg; tree f_ndx, ndx; - tree tmp, addr_tree; - rtx array, orig_ndx, r, addr; - HOST_WIDE_INT size, va_size; + tree tmp, addr_tree, type_size; + rtx array, orig_ndx, r, addr, size, va_size; rtx lab_false, lab_over, lab_false2; - size = int_size_in_bytes (type); - va_size = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD; - f_stk = TYPE_FIELDS (va_list_type_node); f_reg = TREE_CHAIN (f_stk); f_ndx = TREE_CHAIN (f_reg); @@ -2447,6 +2443,20 @@ xtensa_va_arg (valist, type) reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg); ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx); + type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type)); + + va_size = gen_reg_rtx (SImode); + tmp = fold (build (MULT_EXPR, sizetype, + fold (build (TRUNC_DIV_EXPR, sizetype, + fold (build (PLUS_EXPR, sizetype, + type_size, + size_int (UNITS_PER_WORD - 1))), + size_int (UNITS_PER_WORD))), + size_int (UNITS_PER_WORD))); + r = expand_expr (tmp, va_size, SImode, EXPAND_NORMAL); + if (r != va_size) + emit_move_insn (va_size, r); + /* First align __va_ndx to a double word boundary if necessary for this arg: @@ -2477,7 +2487,8 @@ xtensa_va_arg (valist, type) if (r != orig_ndx) emit_move_insn (orig_ndx, r); - tmp = build (PLUS_EXPR, integer_type_node, ndx, build_int_2 (va_size, 0)); + tmp = build (PLUS_EXPR, integer_type_node, ndx, + make_tree (intSI_type_node, va_size)); tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp); TREE_SIDE_EFFECTS (tmp) = 1; expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL); @@ -2522,7 +2533,8 @@ xtensa_va_arg (valist, type) GEN_INT (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD), GE, const1_rtx, SImode, 0, lab_false2); - tmp = build_int_2 ((MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD) + va_size, 0); + tmp = build (PLUS_EXPR, sizetype, make_tree (intSI_type_node, va_size), + build_int_2 (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, 0)); tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp); TREE_SIDE_EFFECTS (tmp) = 1; expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL); @@ -2533,31 +2545,44 @@ xtensa_va_arg (valist, type) if (r != array) emit_move_insn (array, r); + emit_label (lab_over); + /* Given the base array pointer (__array) and index to the subsequent argument (__va_ndx), find the address: - Big-endian: - __array + (AP).__va_ndx - sizeof (TYPE) - - Little-endian: - __array + (AP).__va_ndx - __va_size (TYPE) + __array + (AP).__va_ndx - (BYTES_BIG_ENDIAN && sizeof (TYPE) < 4 + ? sizeof (TYPE) + : __va_size (TYPE)) The results are endian-dependent because values smaller than one word are aligned differently. */ - emit_label (lab_over); + size = gen_reg_rtx (SImode); + emit_move_insn (size, va_size); + + if (BYTES_BIG_ENDIAN) + { + rtx lab_use_va_size = gen_label_rtx (); + + emit_cmp_and_jump_insns (expand_expr (type_size, NULL_RTX, SImode, + EXPAND_NORMAL), + GEN_INT (PARM_BOUNDARY / BITS_PER_UNIT), + GE, const1_rtx, SImode, 0, lab_use_va_size); + + r = expand_expr (type_size, size, SImode, EXPAND_NORMAL); + if (r != size) + emit_move_insn (size, r); + + emit_label (lab_use_va_size); + } addr_tree = build (PLUS_EXPR, ptr_type_node, make_tree (ptr_type_node, array), ndx); - addr_tree = build (PLUS_EXPR, ptr_type_node, - addr_tree, - build_int_2 (BYTES_BIG_ENDIAN - && size < (PARM_BOUNDARY / BITS_PER_UNIT) - ? -size - : -va_size, -1)); + addr_tree = build (MINUS_EXPR, ptr_type_node, addr_tree, + make_tree (intSI_type_node, size)); addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL); addr = copy_to_reg (addr); return addr; -- 2.7.4