]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: xtensa_reorg instead; remove irrelevant portions of the patch)
authorBob Wilson <bob.wilson@acm.org>
Tue, 24 Feb 2004 19:44:12 +0000 (19:44 +0000)
committerBob Wilson <bwilson@gcc.gnu.org>
Tue, 24 Feb 2004 19:44:12 +0000 (19:44 +0000)
Backport from mainline (changes to xtensa_expand_prologue go into
xtensa_reorg instead; remove irrelevant portions of the patch)

2004-02-09  Bob Wilson  <bob.wilson@acm.org>:

* config/xtensa/xtensa-protos.h (xtensa_copy_incoming_a7): Update.
(init_cumulative_args): Likewise.
(a7_overlap_mentioned_p): Delete prototype.
* config/xtensa/xtensa.c (struct machine_function): Replace
incoming_a7_copied field with need_a7_copy and vararg_a7 flags.
Add set_frame_ptr_insn field.
(xtensa_emit_move_sequence): Update call to xtensa_copy_incoming_a7.
(xtensa_copy_incoming_a7): Rewrite to check need_a7_copy flag and check
if the operand is an argument in a7.  If so, copy a7 to a new pseudo
at the function entry and replace the operand with the pseudo.
(init_cumulative_args): Remove unused arguments.  Add new "incoming"
argument and record this flag in CUMULATIVE_ARGS.
(function_arg): Remove result_mode and special-case code to handle
arguments in a7.  Instead, set need_a7_copy flag when there is an
incoming argument in a7.
(xtensa_expand_prologue): Remove code to search for set_frame_ptr insn
and use the value recorded in cfun->machine->set_frame_ptr_insn.
(xtensa_builtin_saveregs): Check for negative gp_left value.  Set
need_a7_copy and vararg_a7 flags.  Use move_block_from_reg instead of
special-case code.
(a7_overlap_mentioned_p): Delete.
* config/xtensa/xtensa.h (CUMULATIVE_ARGS): Add "incoming" flag.
(INIT_CUMULATIVE_ARGS, INIT_CUMULATIVE_INCOMING_ARGS): Remove useless
arguments to init_cumulative_args and pass "incoming" flag instead.
(BLOCK_REG_PADDING): Delete.
* config/xtensa/xtensa.md (movdi, movsf, movdf): Remove unnecessary
checks for reload_in_progress and reload_completed.  Update calls to
xtensa_copy_incoming_a7.
(ashlsi3): Rename existing insn to ashlsi3_internal.  Add expander
to call xtensa_copy_incoming_a7.

From-SVN: r78381

gcc/ChangeLog
gcc/config/xtensa/xtensa-protos.h
gcc/config/xtensa/xtensa.c
gcc/config/xtensa/xtensa.h
gcc/config/xtensa/xtensa.md

index 84c6ec0680353eef77883b6c839b862505947657..9957c6472ca34ef6b52971a4f33d8ee3cf394227 100644 (file)
@@ -1,3 +1,41 @@
+2004-02-24  Bob Wilson  <bob.wilson@acm.org>
+
+       Backport from mainline (changes to xtensa_expand_prologue go into
+       xtensa_reorg instead; remove irrelevant portions of the patch)
+
+       2004-02-09  Bob Wilson  <bob.wilson@acm.org>:
+
+       * config/xtensa/xtensa-protos.h (xtensa_copy_incoming_a7): Update.
+       (init_cumulative_args): Likewise.
+       (a7_overlap_mentioned_p): Delete prototype.
+       * config/xtensa/xtensa.c (struct machine_function): Replace
+       incoming_a7_copied field with need_a7_copy and vararg_a7 flags.
+       Add set_frame_ptr_insn field.
+       (xtensa_emit_move_sequence): Update call to xtensa_copy_incoming_a7.
+       (xtensa_copy_incoming_a7): Rewrite to check need_a7_copy flag and check
+       if the operand is an argument in a7.  If so, copy a7 to a new pseudo
+       at the function entry and replace the operand with the pseudo.
+       (init_cumulative_args): Remove unused arguments.  Add new "incoming"
+       argument and record this flag in CUMULATIVE_ARGS.
+       (function_arg): Remove result_mode and special-case code to handle
+       arguments in a7.  Instead, set need_a7_copy flag when there is an
+       incoming argument in a7.
+       (xtensa_expand_prologue): Remove code to search for set_frame_ptr insn
+       and use the value recorded in cfun->machine->set_frame_ptr_insn.
+       (xtensa_builtin_saveregs): Check for negative gp_left value.  Set
+       need_a7_copy and vararg_a7 flags.  Use move_block_from_reg instead of
+       special-case code.
+       (a7_overlap_mentioned_p): Delete.
+       * config/xtensa/xtensa.h (CUMULATIVE_ARGS): Add "incoming" flag.
+       (INIT_CUMULATIVE_ARGS, INIT_CUMULATIVE_INCOMING_ARGS): Remove useless
+       arguments to init_cumulative_args and pass "incoming" flag instead.
+       (BLOCK_REG_PADDING): Delete.
+       * config/xtensa/xtensa.md (movdi, movsf, movdf): Remove unnecessary
+       checks for reload_in_progress and reload_completed.  Update calls to
+       xtensa_copy_incoming_a7.
+       (ashlsi3): Rename existing insn to ashlsi3_internal.  Add expander
+       to call xtensa_copy_incoming_a7.
+
 2004-02-22  Jakub Jelinek  <jakub@redhat.com>
 
        * config/i386/i386.c (override_options): Don't imply 3DNow! for -m64
index 47befc04be98b3fa0ae076188d8a665dc6b29416..ec689792daeec41387d4392568b2938cfa3c447c 100644 (file)
@@ -1,5 +1,5 @@
 /* Prototypes of target machine for GNU compiler for Xtensa.
-   Copyright 2001,2002,2003 Free Software Foundation, Inc.
+   Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
    Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
 
 This file is part of GCC.
@@ -70,14 +70,14 @@ extern int xtensa_expand_conditional_move PARAMS ((rtx *, int));
 extern int xtensa_expand_scc PARAMS ((rtx *));
 extern int xtensa_expand_block_move PARAMS ((rtx *));
 extern int xtensa_emit_move_sequence PARAMS ((rtx *, enum machine_mode));
-extern bool xtensa_copy_incoming_a7 PARAMS ((rtx *, enum machine_mode));
+extern rtx xtensa_copy_incoming_a7 PARAMS ((rtx));
 extern void xtensa_emit_block_move PARAMS ((rtx *, rtx *, int));
 extern void xtensa_expand_nonlocal_goto PARAMS ((rtx *));
 extern void xtensa_emit_loop_end PARAMS ((rtx, rtx *));
 extern char * xtensa_emit_call PARAMS ((int, rtx *));
 
 #ifdef TREE_CODE
-extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx));
+extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, int));
 extern void xtensa_va_start PARAMS ((tree, rtx));
 extern rtx xtensa_va_arg PARAMS ((tree, tree));
 #endif /* TREE_CODE */
@@ -93,7 +93,6 @@ extern enum reg_class xtensa_preferred_reload_class
   PARAMS ((rtx, enum reg_class, int));
 extern enum reg_class xtensa_secondary_reload_class
   PARAMS ((enum reg_class, enum machine_mode, rtx, int));
-extern int a7_overlap_mentioned_p PARAMS ((rtx x));
 #endif /* RTX_CODE */
 
 #ifdef TREE_CODE
index d72a3e94cc2b9e2458839e554d5e16f460efb994..426aa328be296506b6eabca11ce91fc0a08e3607 100644 (file)
@@ -1,5 +1,5 @@
 /* Subroutines for insn-output.c for Tensilica's Xtensa architecture.
-   Copyright 2001,2002,2003 Free Software Foundation, Inc.
+   Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
    Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
 
 This file is part of GCC.
@@ -90,7 +90,9 @@ const char *xtensa_st_opcodes[(int) MAX_MACHINE_MODE];
 struct machine_function GTY(())
 {
   int accesses_prev_frame;
-  bool incoming_a7_copied;
+  bool need_a7_copy;
+  bool vararg_a7;
+  rtx set_frame_ptr_insn;
 };
 
 /* Vector, indexed by hard register number, which contains 1 for a
@@ -1276,8 +1278,7 @@ xtensa_emit_move_sequence (operands, mode)
       if (!xtensa_valid_move (mode, operands))
        operands[1] = force_reg (mode, operands[1]);
 
-      if (xtensa_copy_incoming_a7 (operands, mode))
-       return 1;
+      operands[1] = xtensa_copy_incoming_a7 (operands[1]);
     }
 
   /* During reload we don't want to emit (subreg:X (mem:Y)) since that
@@ -1309,71 +1310,115 @@ fixup_subreg_mem (x)
 }
 
 
-/* Check if this move is copying an incoming argument in a7.  If so,
-   emit the move, followed by the special "set_frame_ptr"
-   unspec_volatile insn, at the very beginning of the function.  This
-   is necessary because the register allocator will ignore conflicts
-   with a7 and may assign some other pseudo to a7.  If that pseudo was
-   assigned prior to this move, it would clobber the incoming argument
-   in a7.  By copying the argument out of a7 as the very first thing,
-   and then immediately following that with an unspec_volatile to keep
-   the scheduler away, we should avoid any problems.  */
+/* Check if an incoming argument in a7 is expected to be used soon and
+   if OPND is a register or register pair that includes a7.  If so,
+   create a new pseudo and copy a7 into that pseudo at the very
+   beginning of the function, followed by the special "set_frame_ptr"
+   unspec_volatile insn.  The return value is either the original
+   operand, if it is not a7, or the new pseudo containing a copy of
+   the incoming argument.  This is necessary because the register
+   allocator will ignore conflicts with a7 and may either assign some
+   other pseudo to a7 or use a7 as the hard_frame_pointer, clobbering
+   the incoming argument in a7.  By copying the argument out of a7 as
+   the very first thing, and then immediately following that with an
+   unspec_volatile to keep the scheduler away, we should avoid any
+   problems.  Putting the set_frame_ptr insn at the beginning, with
+   only the a7 copy before it, also makes it easier for the prologue
+   expander to initialize the frame pointer after the a7 copy and to
+   fix up the a7 copy to use the stack pointer instead of the frame
+   pointer.  */
 
-bool
-xtensa_copy_incoming_a7 (operands, mode)
-     rtx *operands;
-     enum machine_mode mode;
+rtx
+xtensa_copy_incoming_a7 (opnd)
+     rtx opnd;
 {
-  if (a7_overlap_mentioned_p (operands[1])
-      && !cfun->machine->incoming_a7_copied)
+  rtx entry_insns = 0;
+  rtx reg, tmp;
+  enum machine_mode mode;
+
+  if (!cfun->machine->need_a7_copy)
+    return opnd;
+
+  /* This function should never be called again once a7 has been copied.  */
+  if (cfun->machine->set_frame_ptr_insn)
+    abort ();
+
+  mode = GET_MODE (opnd);
+
+  /* The operand using a7 may come in a later instruction, so just return
+     the original operand if it doesn't use a7.  */
+  reg = opnd;
+  if (GET_CODE (reg) == SUBREG)
     {
-      rtx mov;
-      switch (mode)
-       {
-       case DFmode:
-         mov = gen_movdf_internal (operands[0], operands[1]);
-         break;
-       case SFmode:
-         mov = gen_movsf_internal (operands[0], operands[1]);
-         break;
-       case DImode:
-         mov = gen_movdi_internal (operands[0], operands[1]);
-         break;
-       case SImode:
-         mov = gen_movsi_internal (operands[0], operands[1]);
-         break;
-       case HImode:
-         mov = gen_movhi_internal (operands[0], operands[1]);
-         break;
-       case QImode:
-         mov = gen_movqi_internal (operands[0], operands[1]);
-         break;
-       default:
-         abort ();
-       }
+      if (SUBREG_BYTE (reg) != 0)
+       abort ();
+      reg = SUBREG_REG (reg);
+    }
+  if (GET_CODE (reg) != REG
+      || REGNO (reg) > A7_REG
+      || REGNO (reg) + HARD_REGNO_NREGS (A7_REG, mode) <= A7_REG)
+    return opnd;
 
-      /* Insert the instructions before any other argument copies.
-        (The set_frame_ptr insn comes _after_ the move, so push it
-        out first.)  */
-      push_topmost_sequence ();
-      emit_insn_after (gen_set_frame_ptr (), get_insns ());
-      emit_insn_after (mov, get_insns ());
-      pop_topmost_sequence ();
+  /* 1-word args will always be in a7; 2-word args in a6/a7.  */
+  if (REGNO (reg) + HARD_REGNO_NREGS (A7_REG, mode) - 1 != A7_REG)
+    abort ();
 
-      /* Ideally the incoming argument in a7 would only be copied
-        once, since propagating a7 into the body of a function
-        will almost certainly lead to errors.  However, there is
-        at least one harmless case (in GCSE) where the original
-        copy from a7 is changed to copy into a new pseudo.  Thus,
-        we use a flag to only do this special treatment for the
-        first copy of a7.  */
+  cfun->machine->need_a7_copy = false;
 
-      cfun->machine->incoming_a7_copied = true;
+  /* Copy a7 to a new pseudo at the function entry.  Use gen_raw_REG to
+     create the REG for a7 so that hard_frame_pointer_rtx is not used.  */
 
-      return 1;
+  push_to_sequence (entry_insns);
+  tmp = gen_reg_rtx (mode);
+
+  switch (mode)
+    {
+    case DFmode:
+    case DImode:
+      emit_insn (gen_movsi_internal (gen_rtx_SUBREG (SImode, tmp, 0),
+                                    gen_rtx_REG (SImode, A7_REG - 1)));
+      emit_insn (gen_movsi_internal (gen_rtx_SUBREG (SImode, tmp, 4),
+                                    gen_raw_REG (SImode, A7_REG)));
+      break;
+    case SFmode:
+      emit_insn (gen_movsf_internal (tmp, gen_raw_REG (mode, A7_REG)));
+      break;
+    case SImode:
+      emit_insn (gen_movsi_internal (tmp, gen_raw_REG (mode, A7_REG)));
+      break;
+    case HImode:
+      emit_insn (gen_movhi_internal (tmp, gen_raw_REG (mode, A7_REG)));
+      break;
+    case QImode:
+      emit_insn (gen_movqi_internal (tmp, gen_raw_REG (mode, A7_REG)));
+      break;
+    default:
+      abort ();
     }
 
-  return 0;
+  cfun->machine->set_frame_ptr_insn = emit_insn (gen_set_frame_ptr ());
+  entry_insns = get_insns ();
+  end_sequence ();
+
+  if (cfun->machine->vararg_a7)
+    {
+      /* This is called from within builtin_savereg, so we're already
+        inside a start_sequence that will be placed at the start of
+        the function.  */
+      emit_insn (entry_insns);
+    }
+  else
+    {
+      /* Put entry_insns after the NOTE that starts the function.  If
+        this is inside a start_sequence, make the outer-level insn
+        chain current, so the code is placed at the start of the
+        function.  */
+      push_topmost_sequence ();
+      emit_insn_after (entry_insns, get_insns ());
+      pop_topmost_sequence ();
+    }
+
+  return tmp;
 }
 
 
@@ -1721,12 +1766,12 @@ xtensa_dbx_register_number (regno)
 /* Initialize CUMULATIVE_ARGS for a function.  */
 
 void
-init_cumulative_args (cum, fntype, libname)
+init_cumulative_args (cum, incoming)
      CUMULATIVE_ARGS *cum;     /* argument info to initialize */
-     tree fntype ATTRIBUTE_UNUSED;     /* tree ptr for function decl */
-     rtx libname ATTRIBUTE_UNUSED;     /* SYMBOL_REF of library name or 0 */
+     int incoming;
 {
   cum->arg_words = 0;
+  cum->incoming = incoming;
 }
 
 /* Advance the argument to the next argument position.  */
@@ -1767,7 +1812,6 @@ function_arg (cum, mode, type, incoming_p)
   int regbase, words, max;
   int *arg_words;
   int regno;
-  enum machine_mode result_mode;
 
   arg_words = &cum->arg_words;
   regbase = (incoming_p ? GP_ARG_FIRST : GP_OUTGOING_ARG_FIRST);
@@ -1784,33 +1828,11 @@ function_arg (cum, mode, type, incoming_p)
     return (rtx)0;
 
   regno = regbase + *arg_words;
-  result_mode = (mode == BLKmode ? TYPE_MODE (type) : mode);
-
-  /* We need to make sure that references to a7 are represented with
-     rtx that is not equal to hard_frame_pointer_rtx.  For BLKmode and
-     modes bigger than 2 words (because we only have patterns for
-     modes of 2 words or smaller), we can't control the expansion
-     unless we explicitly list the individual registers in a PARALLEL. */
-
-  if ((mode == BLKmode || words > 2)
-      && regno < A7_REG
-      && regno + words > A7_REG)
-    {
-      rtx result;
-      int n;
 
-      result = gen_rtx_PARALLEL (result_mode, rtvec_alloc (words));
-      for (n = 0; n < words; n++)
-       {
-         XVECEXP (result, 0, n) =
-           gen_rtx_EXPR_LIST (VOIDmode,
-                              gen_raw_REG (SImode, regno + n),
-                              GEN_INT (n * UNITS_PER_WORD));
-       }
-      return result;
-    }
+  if (cum->incoming && regno <= A7_REG && regno + words > A7_REG)
+    cfun->machine->need_a7_copy = true;
 
-  return gen_raw_REG (result_mode, regno);
+  return gen_rtx_REG (mode, regno);
 }
 
 
@@ -2187,8 +2209,6 @@ void
 xtensa_reorg (first)
     rtx first;
 {
-  rtx insn, set_frame_ptr_insn = 0;
-    
   unsigned long tsize = compute_frame_size (get_frame_size ());
   if (tsize < (1 << (12+3)))
     frame_size_const = 0;
@@ -2204,34 +2224,15 @@ xtensa_reorg (first)
   if (!frame_pointer_needed)
     return;
 
-  /* Search all instructions, looking for the insn that sets up the
-     frame pointer.  This search will fail if the function does not
-     have an incoming argument in $a7, but in that case, we can just
-     set up the frame pointer at the very beginning of the
-     function. */
-
-  for (insn = first; insn; insn = NEXT_INSN (insn))
+  if (cfun->machine->set_frame_ptr_insn)
     {
-      rtx pat;
+      rtx insn;
 
-      if (!INSN_P (insn))
-       continue;
-
-      pat = PATTERN (insn);
-      if (GET_CODE (pat) == SET
-         && GET_CODE (SET_SRC (pat)) == UNSPEC_VOLATILE
-         && (XINT (SET_SRC (pat), 1) == UNSPECV_SET_FP))
-       {
-         set_frame_ptr_insn = insn;
-         break;
-       }
-    }
-
-  if (set_frame_ptr_insn)
-    {
       /* for all instructions prior to set_frame_ptr_insn, replace
         hard_frame_pointer references with stack_pointer */
-      for (insn = first; insn != set_frame_ptr_insn; insn = NEXT_INSN (insn))
+      for (insn = first;
+          insn != cfun->machine->set_frame_ptr_insn;
+          insn = NEXT_INSN (insn))
        {
          if (INSN_P (insn))
            PATTERN (insn) = replace_rtx (copy_rtx (PATTERN (insn)),
@@ -2379,9 +2380,8 @@ xtensa_builtin_saveregs ()
   rtx gp_regs, dest;
   int arg_words = current_function_arg_words;
   int gp_left = MAX_ARGS_IN_REGISTERS - arg_words;
-  int i;
 
-  if (gp_left == 0)
+  if (gp_left <= 0)
     return const0_rtx;
 
   /* allocate the general-purpose register space */
@@ -2394,15 +2394,10 @@ xtensa_builtin_saveregs ()
                         plus_constant (XEXP (gp_regs, 0),
                                        arg_words * UNITS_PER_WORD));
 
-  /* Note: Don't use move_block_from_reg() here because the incoming
-     argument in a7 cannot be represented by hard_frame_pointer_rtx.
-     Instead, call gen_raw_REG() directly so that we get a distinct
-     instance of (REG:SI 7). */
-  for (i = 0; i < gp_left; i++)
-    {
-      emit_move_insn (operand_subword (dest, i, 1, BLKmode),
-                     gen_raw_REG (SImode, GP_ARG_FIRST + arg_words + i));
-    }
+  cfun->machine->need_a7_copy = true;
+  cfun->machine->vararg_a7 = true;
+  move_block_from_reg (GP_ARG_FIRST + arg_words, dest, gp_left,
+                      gp_left * UNITS_PER_WORD);
 
   return XEXP (gp_regs, 0);
 }
@@ -2722,56 +2717,6 @@ order_regs_for_local_alloc ()
 }
 
 
-/* A customized version of reg_overlap_mentioned_p that only looks for
-   references to a7 (as opposed to hard_frame_pointer_rtx). */
-
-int
-a7_overlap_mentioned_p (x)
-     rtx x;
-{
-  int i, j;
-  unsigned int x_regno;
-  const char *fmt;
-
-  if (GET_CODE (x) == REG)
-    {
-      x_regno = REGNO (x);
-      return (x != hard_frame_pointer_rtx
-             && x_regno < A7_REG + 1
-             && x_regno + HARD_REGNO_NREGS (A7_REG, GET_MODE (x)) > A7_REG);
-    }
-
-  if (GET_CODE (x) == SUBREG
-      && GET_CODE (SUBREG_REG (x)) == REG
-      && REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
-    {
-      x_regno = subreg_regno (x);
-      return (SUBREG_REG (x) != hard_frame_pointer_rtx
-             && x_regno < A7_REG + 1
-             && x_regno + HARD_REGNO_NREGS (A7_REG, GET_MODE (x)) > A7_REG);
-    }
-
-  /* X does not match, so try its subexpressions.  */
-  fmt = GET_RTX_FORMAT (GET_CODE (x));
-  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
-    {
-      if (fmt[i] == 'e')
-       {
-         if (a7_overlap_mentioned_p (XEXP (x, i)))
-           return 1;
-       }
-      else if (fmt[i] == 'E')
-       {
-         for (j = XVECLEN (x, i) - 1; j >=0; j--)
-           if (a7_overlap_mentioned_p (XVECEXP (x, i, j)))
-             return 1;
-       }
-    }
-
-  return 0;
-}
-
-
 /* Some Xtensa targets support multiple bss sections.  If the section
    name ends with ".bss", add SECTION_BSS to the flags.  */
 
index 3a5a7343a01009e67ca2168ab64f4f00a7c468e9..6e80e163527016f41855b6a2feda196d3d24eb81 100644 (file)
@@ -1,5 +1,5 @@
 /* Definitions of Tensilica's Xtensa target machine for GNU compiler.
-   Copyright 2001,2002,2003 Free Software Foundation, Inc.
+   Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
    Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
 
 This file is part of GCC.
@@ -853,23 +853,21 @@ extern enum reg_class xtensa_char_to_class[256];
 #define FUNCTION_ARG_REGNO_P(N)                                                \
   ((N) >= GP_OUTGOING_ARG_FIRST && (N) <= GP_OUTGOING_ARG_LAST)
 
-/* Define a data type for recording info about an argument list
-   during the scan of that argument list.  This data type should
-   hold all necessary information about the function itself
-   and about the args processed so far, enough to enable macros
-   such as FUNCTION_ARG to determine where the next arg should go. */
-typedef struct xtensa_args {
-    int arg_words;             /* # total words the arguments take */
+/* Record the number of argument words seen so far, along with a flag to
+   indicate whether these are incoming arguments.  (FUNCTION_INCOMING_ARG
+   is used for both incoming and outgoing args, so a separate flag is
+   needed.  */
+typedef struct xtensa_args
+{
+  int arg_words;
+  int incoming;
 } CUMULATIVE_ARGS;
 
-/* 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. */
 #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT)           \
-  init_cumulative_args (&CUM, FNTYPE, LIBNAME)
+  init_cumulative_args (&CUM, 0)
 
 #define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME)            \
-  init_cumulative_args (&CUM, FNTYPE, LIBNAME)
+  init_cumulative_args (&CUM, 1)
 
 /* Update the data in CUM to advance over an argument
    of mode MODE and data type TYPE.
index cc722b932a9286ee81d8a985821ffd09befa85ac..92a25a17521445f62bf2f961332a7d0d022ff9c2 100644 (file)
@@ -1,5 +1,5 @@
 ;; GCC machine description for Tensilica's Xtensa architecture.
-;; Copyright (C) 2001 Free Software Foundation, Inc.
+;; Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 ;; Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
 
 ;; This file is part of GCC.
          && !register_operand (operands[1], DImode))
        operands[1] = force_reg (DImode, operands[1]);
 
-      if (xtensa_copy_incoming_a7 (operands, DImode))
-       DONE;
+      operands[1] = xtensa_copy_incoming_a7 (operands[1]);
     }
 }")
 
              && constantpool_mem_p (operands[1]))))
        operands[1] = force_reg (SFmode, operands[1]);
 
-      if (xtensa_copy_incoming_a7 (operands, SFmode))
-       DONE;
+      operands[1] = xtensa_copy_incoming_a7 (operands[1]);
     }
 }")
 
          && !register_operand (operands[1], DFmode))
        operands[1] = force_reg (DFmode, operands[1]);
 
-      if (xtensa_copy_incoming_a7 (operands, DFmode))
-       DONE;
+      operands[1] = xtensa_copy_incoming_a7 (operands[1]);
     }
 }")
 
 ;;  ....................
 ;;
 
-(define_insn "ashlsi3"
+(define_expand "ashlsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (ashift:SI (match_operand:SI 1 "register_operand" "")
+                  (match_operand:SI 2 "arith_operand" "")))]
+  ""
+{
+  operands[1] = xtensa_copy_incoming_a7 (operands[1]);
+})
+
+(define_insn "ashlsi3_internal"
   [(set (match_operand:SI 0 "register_operand" "=a,a")
        (ashift:SI (match_operand:SI 1 "register_operand" "r,r")
                   (match_operand:SI 2 "arith_operand" "J,r")))]