]> gcc.gnu.org Git - gcc.git/commitdiff
clipper.h (EXPAND_BUILTIN_SAVEREGS): Remove argument.
authorRichard Henderson <rth@cygnus.com>
Mon, 26 Jul 1999 06:48:07 +0000 (23:48 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Mon, 26 Jul 1999 06:48:07 +0000 (23:48 -0700)
        * clipper.h (EXPAND_BUILTIN_SAVEREGS): Remove argument.
        (BUILD_VA_LIST_TYPE): New.
        (EXPAND_BUILTIN_VA_START): New.
        (EXPAND_BUILTIN_VA_ARG): New.
        * clipper.c (clipper_builtin_saveregs): Only dump registers.
        Return the address of the save area.
        (clipper_build_va_list): New.
        (clipper_va_start): New.
        (clipper_va_arg): New.

From-SVN: r28257

gcc/ChangeLog
gcc/config/clipper/clipper.c
gcc/config/clipper/clipper.h

index bfaaf383b0b3326a8ab6ca4b6b1d282668d31c4e..8c7f7e0c8ecc73abebf7a705d466e2d9485d9511 100644 (file)
@@ -1,3 +1,15 @@
+Sun Jul 25 23:44:13 1999  Richard Henderson  <rth@cygnus.com>
+
+       * clipper.h (EXPAND_BUILTIN_SAVEREGS): Remove argument.
+       (BUILD_VA_LIST_TYPE): New.
+       (EXPAND_BUILTIN_VA_START): New.
+       (EXPAND_BUILTIN_VA_ARG): New.
+       * clipper.c (clipper_builtin_saveregs): Only dump registers.
+       Return the address of the save area.
+       (clipper_build_va_list): New.
+       (clipper_va_start): New.
+       (clipper_va_arg): New.
+
 Sun Jul 25 22:56:47 1999  Richard Henderson  <rth@cygnus.com>
 
        * arc.h (EXPAND_BUILTIN_VA_START): New.
index d59d3f1671e13fb9f21badcb006debc5f86c5a4b..3bae60b81483c68c1cccfc4edce1ddb569f35e44 100644 (file)
@@ -365,93 +365,56 @@ rev_cond_name (op)
 }
 
 \f
-/* Do what is necessary for `va_start'.  The argument is ignored;
-   We fill in an initial va_list.  A pointer to this constructor
-   is returned. */
-
+/* Dump the argument register to the stack; return the location
+   of the block.  */
 
 struct rtx_def *
-clipper_builtin_saveregs (arglist)
-     tree arglist;
+clipper_builtin_saveregs ()
 {
-  extern int current_function_varargs;
-  rtx block, addr, argsize, scratch, r0_addr,r1_addr,f0_addr,f1_addr;
+  rtx block, addr, r0_addr, r1_addr, f0_addr, f1_addr, mem;
+  int set = get_varargs_alias_set ();
 
-  /* Allocate the va_list constructor + save area for r0,r1,f0,f1 */
+  /* Allocate the save area for r0,r1,f0,f1 */
 
-  block = assign_stack_local (BLKmode,
-                             (6 + 6) * UNITS_PER_WORD, 2 * BITS_PER_WORD);
+  block = assign_stack_local (BLKmode, 6 * UNITS_PER_WORD, 2 * BITS_PER_WORD);
 
   RTX_UNCHANGING_P (block) = 1;
   RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
 
-  addr = copy_to_reg (XEXP (block, 0));
+  addr = XEXP (block, 0);
 
-  f0_addr =  gen_rtx (PLUS, Pmode, addr, GEN_INT (24));
-  f1_addr =  gen_rtx (PLUS, Pmode, addr, GEN_INT (32));
-  r0_addr =  gen_rtx (PLUS, Pmode, addr, GEN_INT (40));
-  r1_addr =  gen_rtx (PLUS, Pmode, addr, GEN_INT (44));
+  r0_addr = addr;
+  r1_addr = plus_constant (addr, 4);
+  f0_addr = plus_constant (addr, 8);
+  f1_addr = plus_constant (addr, 16);
 
+  /* Store int regs  */
 
-  /* Store float regs  */
+  mem = gen_rtx_MEM (SImode, r0_addr);
+  MEM_ALIAS_SET (mem) = set;
+  emit_move_insn (mem, gen_rtx_REG (SImode, 0));
 
-  emit_move_insn (gen_rtx (MEM, DFmode, f0_addr), gen_rtx (REG, DFmode, 16));
-  emit_move_insn (gen_rtx (MEM, DFmode, f1_addr), gen_rtx (REG, DFmode, 17));
+  mem = gen_rtx_MEM (SImode, r1_addr);
+  MEM_ALIAS_SET (mem) = set;
+  emit_move_insn (mem, gen_rtx_REG (SImode, 1));
 
-  /* Store int regs  */
+  /* Store float regs  */
 
-  emit_move_insn (gen_rtx (MEM, SImode, r0_addr), gen_rtx (REG, SImode, 0));
-  emit_move_insn (gen_rtx (MEM, SImode, r1_addr), gen_rtx (REG, SImode, 1));
-
-  /* Store the arg pointer in the __va_stk member.  */
-
-  emit_move_insn (gen_rtx (MEM, SImode, addr),
-                 copy_to_reg (virtual_incoming_args_rtx));
-                 
-
-  /* now move addresses of the saved regs into the pointer array */
-
-  scratch = gen_reg_rtx (Pmode);
-
-  emit_move_insn (scratch, r0_addr);
-  emit_move_insn (gen_rtx (MEM, SImode,
-                          gen_rtx (PLUS, Pmode, addr,
-                                   GEN_INT (4))),
-                 scratch);
-                 
-  emit_move_insn (scratch, f0_addr);
-  emit_move_insn (gen_rtx (MEM, SImode,
-                          gen_rtx (PLUS, Pmode, addr,
-                                   GEN_INT (8))),
-                 scratch);
-                 
-  emit_move_insn (scratch, r1_addr);
-  emit_move_insn (gen_rtx (MEM, SImode,
-                          gen_rtx (PLUS, Pmode, addr,
-                                   GEN_INT (12))),
-                 scratch);
-                 
-  emit_move_insn (scratch, f1_addr);
-  emit_move_insn (gen_rtx (MEM, SImode,
-                          gen_rtx (PLUS, Pmode, addr,
-                                   GEN_INT (16))),
-                 scratch);
+  mem = gen_rtx_MEM (DFmode, f0_addr);
+  MEM_ALIAS_SET (mem) = set;
+  emit_move_insn (mem, gen_rtx_REG (DFmode, 16));
 
+  mem = gen_rtx_MEM (DFmode, f1_addr);
+  MEM_ALIAS_SET (mem) = set;
+  emit_move_insn (mem, gen_rtx_REG (DFmode, 17));
 
   if (current_function_check_memory_usage)
     {
-      emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
-                        addr, ptr_mode,
-                        GEN_INT (5 * GET_MODE_SIZE (SImode)),
-                        TYPE_MODE (sizetype),
-                        GEN_INT (MEMORY_USE_RW),
-                        TYPE_MODE (integer_type_node));
-
       emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
                         f0_addr, ptr_mode,
                         GEN_INT (GET_MODE_SIZE (DFmode)),
                         TYPE_MODE (sizetype),
-                        GEN_INT (MEMORY_USE_RW), 
+                        GEN_INT (MEMORY_USE_RW),
                         TYPE_MODE (integer_type_node));
       emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
                         f1_addr, ptr_mode,
@@ -473,12 +436,222 @@ clipper_builtin_saveregs (arglist)
                         TYPE_MODE (integer_type_node));
     }
 
-  /* Return the address of the va_list constructor, but don't put it in a
-     register.  This fails when not optimizing and produces worse code when
-     optimizing.  */
-  return XEXP (block, 0);
+  return addr;
+}
+
+tree
+clipper_build_va_list ()
+{
+  tree record, ap, reg, num;
+
+  /*
+    struct
+    {
+      int __va_ap;             // pointer to stack args
+      void *__va_reg[4];       // pointer to r0,f0,r1,f1
+      int __va_num;            // number of args processed
+    };
+  */
+
+  record = make_node (RECORD_TYPE);
+
+  num = build_decl (FIELD_DECL, get_identifier ("__va_num"),
+                   integer_type_node);
+  DECL_FIELD_CONTEXT (num) = record;
+
+  reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
+                   build_array_type (ptr_type_node,
+                                     build_index_type (build_int_2 (3, 0))));
+  DECL_FIELD_CONTEXT (reg) = record;
+  TREE_CHAIN (reg) = num;
+
+  ap = build_decl (FIELD_DECL, get_identifier ("__va_ap"),
+                  integer_type_node);
+  DECL_FIELD_CONTEXT (ap) = record;
+  TREE_CHAIN (ap) = reg;
+
+  TYPE_FIELDS (record) = ap;
+  layout_type (record);
+
+  return record;
+}
+
+void
+clipper_va_start (stdarg_p, valist, nextarg)
+     int stdarg_p;
+     tree valist;
+     rtx nextarg ATTRIBUTE_UNUSED;
+{
+  tree ap_field, reg_field, num_field;
+  tree t, u, save_area;
+
+  ap_field = TYPE_FIELDS (TREE_TYPE (valist));
+  reg_field = TREE_CHAIN (ap_field);
+  num_field = TREE_CHAIN (reg_field);
+
+  ap_field = build (COMPONENT_REF, TREE_TYPE (ap_field), valist, ap_field);
+  reg_field = build (COMPONENT_REF, TREE_TYPE (reg_field), valist, reg_field);
+  num_field = build (COMPONENT_REF, TREE_TYPE (num_field), valist, num_field);
+
+  /* Call __builtin_saveregs to save r0, r1, f0, and f1 in a block.  */
+
+  save_area = make_tree (integer_type_node, expand_builtin_saveregs ());
+
+  /* Set __va_ap.  */
+
+  t = make_tree (ptr_type_node, virtual_incoming_args_rtx);
+  if (stdarg_p && current_function_args_info.size != 0)
+    t = build (PLUS_EXPR, ptr_type_node, t,
+              build_int_2 (current_function_args_info.size, 0));
+  t = build (MODIFY_EXPR, TREE_TYPE (ap_field), ap_field, t);
+  TREE_SIZE_EFFECTS (t) = 1;
+  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  /* Set the four entries of __va_reg.  */
+
+  t = build1 (NOP_EXPR, ptr_type_node, save_area);
+  u = build (ARRAY_REF, ptr_type_node, reg_field, build_int (0, 0));
+  t = build (MODIFY_EXPR, ptr_type_node, u, t);
+  TREE_SIZE_EFFECTS (t) = 1;
+  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  t = fold (build (PLUS_EXPR, integer_type_node, save_area,
+                  build_int_2 (8, 0)));
+  t = build1 (NOP_EXPR, ptr_type_node, save_area);
+  u = build (ARRAY_REF, ptr_type_node, reg_field, build_int (1, 0));
+  t = build (MODIFY_EXPR, ptr_type_node, u, t);
+  TREE_SIZE_EFFECTS (t) = 1;
+  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  t = fold (build (PLUS_EXPR, integer_type_node, save_area,
+                  build_int_2 (4, 0)));
+  t = build1 (NOP_EXPR, ptr_type_node, save_area);
+  u = build (ARRAY_REF, ptr_type_node, reg_field, build_int (2, 0));
+  t = build (MODIFY_EXPR, ptr_type_node, u, t);
+  TREE_SIZE_EFFECTS (t) = 1;
+  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  t = fold (build (PLUS_EXPR, integer_type_node, save_area,
+                  build_int_2 (16, 0)));
+  t = build1 (NOP_EXPR, ptr_type_node, save_area);
+  u = build (ARRAY_REF, ptr_type_node, reg_field, build_int (3, 0));
+  t = build (MODIFY_EXPR, ptr_type_node, u, t);
+  TREE_SIZE_EFFECTS (t) = 1;
+  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  /* Set __va_num.  */
+
+  t = build_int_2 (current_function_args_info.num, 0);
+  t = build (MODIFY_EXPR, TREE_TYPE (num_field), num_field, t);
+  TREE_SIZE_EFFECTS (t) = 1;
 }
 
+rtx
+clipper_va_arg (valist, type)
+     tree valist, type;
+{
+  tree ap_field, reg_field, num_field;
+  tree addr, t;
+  HOST_WIDE_INT align;
+  rtx addr_rtx, over_label = NULL_RTX, tr;
+
+  /*
+    Integers:
+
+    if (VA.__va_num < 2)
+      addr = VA.__va_reg[2 * VA.__va_num];
+    else
+      addr = round(VA.__va_ap), VA.__va_ap = round(VA.__va_ap) + sizeof(TYPE);
+    VA.__va_num++;
+
+    Floats:
+
+    if (VA.__va_num < 2)
+      addr = VA.__va_reg[2 * VA.__va_num + 1];
+    else
+      addr = round(VA.__va_ap), VA.__va_ap = round(VA.__va_ap) + sizeof(TYPE);
+    VA.__va_num++;
+
+    Aggregates:
+
+    addr = round(VA.__va_ap), VA.__va_ap = round(VA.__va_ap) + sizeof(TYPE);
+    VA.__va_num++;
+  */
+
+  ap_field = TYPE_FIELDS (TREE_TYPE (valist));
+  reg_field = TREE_CHAIN (ap_field);
+  num_field = TREE_CHAIN (reg_field);
+
+  ap_field = build (COMPONENT_REF, TREE_TYPE (ap_field), valist, ap_field);
+  reg_field = build (COMPONENT_REF, TREE_TYPE (reg_field), valist, reg_field);
+  num_field = build (COMPONENT_REF, TREE_TYPE (num_field), valist, num_field);
+
+  addr_rtx = gen_reg_rtx (Pmode);
+
+  if (! AGGREGATE_TYPE_P (type))
+    {
+      tree inreg;
+      rtx false_label;
+
+      over_label = gen_label_rtx ();
+      false_label = gen_label_rtx ();
+
+      emit_cmp_and_jump_insns (expand_expr (num_field, NULL_RTX, 0,
+                                           OPTAB_LIB_WIDEN),
+                              GEN_INT (2), GE, const0_rtx,
+                              TYPE_MODE (TREE_TYPE (num_field)),
+                              TREE_UNSIGNED (num_field), 0, false_label);
+
+      inreg = fold (build (MULT_EXPR, integer_type_node, num_field,
+                          build_int_2 (2, 0)));
+      if (FLOAT_TYPE_P (type))
+       inreg = fold (build (PLUS_EXPR, integer_type_node, inreg,
+                            build_int_2 (1, 0)));
+      inreg = fold (build (ARRAY_REF, ptr_type_node, reg_field, inreg));
+
+      tr = expand_expr (inreg, addr_rtx, VOIDmode, EXPAND_NORMAL);
+      if (tr != addr_rtx)
+       emit_move_insn (addr_rtx, tr);
+
+      emit_jump_insn (gen_jump (over_label));
+      emit_barrier ();
+      emit_label (false_label);
+    }
+
+  /* Round to alignment of `type', or at least integer alignment.  */
+
+  align = TYPE_ALIGN (type);
+  if (align < TYPE_ALIGN (integer_type_node))
+    align = TYPE_ALIGN (integer_type_node);
+  align /= BITS_PER_UNIT;
+
+  addr = fold (build (PLUS_EXPR, ptr_type_node, ap_field,
+                     build_int_2 (align-1, 0)));
+  addr = fold (build (BIT_AND_EXPR, ptr_type_node, addr,
+                     build_int_2 (-align, -1)));
+  addr = save_expr (addr);
+
+  tr = expand_expr (addr, addr_rtx, Pmode, EXPAND_NORMAL);
+  if (tr != addr_rtx)
+    emit_move_insn (addr_rtx, tr);
+  
+  t = build (MODIFY_EXPR, TREE_TYPE (ap_field), ap_field,
+            build (PLUS_EXPR, TREE_TYPE (ap_field), 
+                   addr, build_int_2 (int_size_in_bytes (type), 0)));
+  TREE_SIDE_EFFECTS (t) = 1;
+  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  if (over_label)
+    emit_label (over_label);
+
+  t = build (MODIFY_EXPR, TREE_TYPE (num_field), num_field,
+            build (PLUS_EXPR, TREE_TYPE (num_field), 
+                   num_field, build_int_2 (1, 0)));
+  TREE_SIDE_EFFECTS (t) = 1;
+  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  return addr_rtx;
+}
 
 /* Return truth value of whether OP can be used as an word register
    operand. Reject (SUBREG:SI (REG:SF )) */
index bd2e5a66fc4f3e0b1c3924218a171a3878f4e95f..9b46916302d10d2a44162e27b8b4160011225ff7 100644 (file)
@@ -549,7 +549,7 @@ do                                                                        \
 /* Generate necessary RTL for __builtin_saveregs().
    ARGLIST is the argument list; see expr.c.  */
 
-#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) clipper_builtin_saveregs (ARGLIST)
+#define EXPAND_BUILTIN_SAVEREGS() clipper_builtin_saveregs ()
 
 /* This macro generates the assembly code for function entry.
    FILE is a stdio stream to output the code to.
@@ -1123,3 +1123,15 @@ Clipper operand formatting codes:
 #define PREDICATE_CODES \
   {"int_reg_operand", {SUBREG, REG}},  \
   {"fp_reg_operand", {SUBREG, REG}},
+\f
+/* Define the `__builtin_va_list' type for the ABI.  */
+#define BUILD_VA_LIST_TYPE(VALIST) \
+  (VALIST) = clipper_build_va_list ()
+
+/* Implement `va_start' for varargs and stdarg.  */
+#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
+  clipper_va_start (stdarg, valist, nextarg)
+
+/* Implement `va_arg'.  */
+#define EXPAND_BUILTIN_VA_ARG(valist, type) \
+  clipper_va_arg (valist, type)
This page took 0.075223 seconds and 5 git commands to generate.