OSDN Git Service

* arc.h (EXPAND_BUILTIN_VA_START): New.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 26 Jul 1999 06:37:29 +0000 (06:37 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 26 Jul 1999 06:37:29 +0000 (06:37 +0000)
        (EXPAND_BUILTIN_VA_ARG): New.
        * arc.c (arc_setup_incoming_varargs): Set alias set of
        varargs save area.
        (arc_va_start): New.
        (arc_va_arg): New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@28254 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/arc/arc.c
gcc/config/arc/arc.h

index 90e9027..bfaaf38 100644 (file)
@@ -1,3 +1,12 @@
+Sun Jul 25 22:56:47 1999  Richard Henderson  <rth@cygnus.com>
+
+       * arc.h (EXPAND_BUILTIN_VA_START): New.
+       (EXPAND_BUILTIN_VA_ARG): New.
+       * arc.c (arc_setup_incoming_varargs): Set alias set of 
+       varargs save area.
+       (arc_va_start): New.
+       (arc_va_arg): New.
+
 Sun Jul 25 22:45:55 1999  Richard Henderson  <rth@cygnus.com>
 
        * alpha.h (EXPAND_BUILTIN_SAVEREGS): Delete.
index 64aec44..957db0b 100644 (file)
@@ -751,7 +751,7 @@ arc_double_limm_p (value)
 
    We do things a little weird here.  We're supposed to only allocate space
    for the anonymous arguments.  However we need to keep the stack eight byte
-   aligned.  So we round the space up if necessary, and leave it to va-arc.h
+   aligned.  So we round the space up if necessary, and leave it to va_start
    to compensate.  */
 
 void
@@ -789,6 +789,8 @@ arc_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
                          plus_constant (arg_pointer_rtx,
                                         FIRST_PARM_OFFSET (0)
                                         + align_slop * UNITS_PER_WORD));
+      MEM_ALIAS_SET (regblock) = get_varargs_alias_set ();
+
       move_block_from_reg (first_reg_offset, regblock,
                           MAX_ARC_PARM_REGS - first_reg_offset,
                           ((MAX_ARC_PARM_REGS - first_reg_offset)
@@ -2201,3 +2203,90 @@ arc_ccfsm_record_branch_deleted ()
      for the just deleted branch.  */
   current_insn_set_cc_p = last_insn_set_cc_p;
 }
+\f
+void
+arc_va_start (stdarg_p, valist, nextarg)
+     int stdarg_p;
+     tree valist;
+     rtx nextarg;
+{
+  /* See arc_setup_incoming_varargs for reasons for this oddity.  */
+  if (current_function_args_info < 8
+      && (current_function_args_info & 1))
+    nextarg = plus_constant (nextarg, UNITS_PER_WORD);
+
+  std_expand_builtin_va_start (stdarg_p, valist, nextarg);
+}
+
+rtx
+arc_va_arg (valist, type)
+     tree valist, type;
+{
+  rtx addr_rtx;
+  tree addr, incr;
+  tree type_ptr = build_pointer_type (type);
+
+  /* All aggregates are passed by reference.  All scalar types larger
+     than 8 bytes are passed by reference.  */
+
+  if (AGGREGATE_TYPE_P (type) || int_size_in_bytes (type) > 8)
+    {
+      tree type_ptr_ptr = build_pointer_type (type_ptr);
+
+      addr = build (INDIRECT_REF, type_ptr,
+                   build (NOP_EXPR, type_ptr_ptr, valist));
+
+      incr = build (PLUS_EXPR, TREE_TYPE (valist),
+                   valist, build_int_2 (UNITS_PER_WORD, 0));
+    }
+  else
+    {
+      HOST_WIDE_INT align, rounded_size;
+
+      /* Compute the rounded size of the type.  */
+      align = PARM_BOUNDARY / BITS_PER_UNIT;
+      rounded_size = (((TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT
+                       + align - 1) / align) * align);
+
+      /* Align 8 byte operands.  */
+      addr = valist;
+      if (TYPE_ALIGN (type) > BITS_PER_WORD)
+       {
+         /* AP = (TYPE *)(((int)AP + 7) & -8)  */
+
+         addr = build (NOP_EXPR, integer_type_node, valist);
+         addr = fold (build (PLUS_EXPR, integer_type_node, addr,
+                             build_int_2 (7, 0)));
+         addr = fold (build (BIT_AND_EXPR, integer_type_node, addr,
+                             build_int_2 (-8, 0)));
+         addr = fold (build (NOP_EXPR, TREE_TYPE (valist), addr));
+       }
+
+      /* The increment is always rounded_size past the aligned pointer.  */
+      incr = fold (build (PLUS_EXPR, TREE_TYPE (addr), addr,
+                         build_int_2 (rounded_size, 0)));
+
+      /* Adjust the pointer in big-endian mode.  */
+      if (BYTES_BIG_ENDIAN)
+       {
+         HOST_WIDE_INT adj;
+         adj = TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT;
+         if (rounded_size > align)
+           adj = rounded_size;
+
+         addr = fold (build (PLUS_EXPR, TREE_TYPE (addr), addr,
+                             build_int_2 (rounded_size - adj, 0)));
+       }
+    }
+
+  /* Evaluate the data address.  */
+  addr_rtx = expand_expr (addr, NULL_RTX, Pmode, EXPAND_NORMAL);
+  addr_rtx = copy_to_reg (addr_rtx);
+  
+  /* Compute new value for AP.  */
+  incr = build (MODIFY_EXPR, TREE_TYPE (valist), valist, incr);
+  TREE_SIDE_EFFECTS (incr) = 1;
+  expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  return addr_rtx;
+}
index 49d9fe2..81c6c87 100644 (file)
@@ -1640,3 +1640,12 @@ enum arc_function_type {
 ((TYPE) == ARC_FUNCTION_ILINK1 || (TYPE) == ARC_FUNCTION_ILINK2)
 /* Compute the type of a function from its DECL.  */
 enum arc_function_type arc_compute_function_type ();
+
+\f
+/* Implement `va_start' for varargs and stdarg.  */
+#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
+  arc_va_start (stdarg, valist, nextarg)
+
+/* Implement `va_arg'.  */
+#define EXPAND_BUILTIN_VA_ARG(valist, type) \
+  arc_va_arg (valist, type)