This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the EGCS project.
va_list: clipper
- To: gcc-patches@gcc.gnu.org
- Subject: va_list: clipper
- From: Richard Henderson <rth@cygnus.com>
- Date: Sun, 25 Jul 1999 23:47:38 -0700
Another dead architecture. It does look moderately interesting
for an 80's risc.
r~
* 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.
Index: config/clipper/clipper.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/clipper/clipper.c,v
retrieving revision 1.4
diff -c -p -d -r1.4 clipper.c
*** clipper.c 1998/12/16 21:02:17 1.4
--- clipper.c 1999/07/26 06:43:35
*************** rev_cond_name (op)
*** 365,457 ****
}
! /* 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. */
!
struct rtx_def *
! clipper_builtin_saveregs (arglist)
! tree arglist;
{
! extern int current_function_varargs;
! rtx block, addr, argsize, scratch, r0_addr,r1_addr,f0_addr,f1_addr;
! /* Allocate the va_list constructor + save area for r0,r1,f0,f1 */
! block = assign_stack_local (BLKmode,
! (6 + 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));
! 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));
!
!
! /* Store float regs */
! 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));
/* Store int 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);
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),
TYPE_MODE (integer_type_node));
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
f1_addr, ptr_mode,
--- 365,420 ----
}
! /* Dump the argument register to the stack; return the location
! of the block. */
struct rtx_def *
! clipper_builtin_saveregs ()
{
! rtx block, addr, r0_addr, r1_addr, f0_addr, f1_addr, mem;
! int set = get_varargs_alias_set ();
! /* Allocate the save area for r0,r1,f0,f1 */
! 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 = XEXP (block, 0);
! r0_addr = addr;
! r1_addr = plus_constant (addr, 4);
! f0_addr = plus_constant (addr, 8);
! f1_addr = plus_constant (addr, 16);
/* Store int regs */
! mem = gen_rtx_MEM (SImode, r0_addr);
! MEM_ALIAS_SET (mem) = set;
! emit_move_insn (mem, gen_rtx_REG (SImode, 0));
! mem = gen_rtx_MEM (SImode, r1_addr);
! MEM_ALIAS_SET (mem) = set;
! emit_move_insn (mem, gen_rtx_REG (SImode, 1));
! /* Store float regs */
! 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,
f0_addr, ptr_mode,
GEN_INT (GET_MODE_SIZE (DFmode)),
TYPE_MODE (sizetype),
! GEN_INT (MEMORY_USE_RW),
TYPE_MODE (integer_type_node));
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
f1_addr, ptr_mode,
*************** clipper_builtin_saveregs (arglist)
*** 473,484 ****
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 truth value of whether OP can be used as an word register
operand. Reject (SUBREG:SI (REG:SF )) */
--- 436,657 ----
TYPE_MODE (integer_type_node));
}
! 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: config/clipper/clipper.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/clipper/clipper.h,v
retrieving revision 1.8
diff -c -p -d -r1.8 clipper.h
*** clipper.h 1999/03/22 00:08:21 1.8
--- clipper.h 1999/07/26 06:43:35
*************** do \
*** 549,555 ****
/* Generate necessary RTL for __builtin_saveregs().
ARGLIST is the argument list; see expr.c. */
! #define EXPAND_BUILTIN_SAVEREGS(ARGLIST) clipper_builtin_saveregs (ARGLIST)
/* This macro generates the assembly code for function entry.
FILE is a stdio stream to output the code to.
--- 549,555 ----
/* Generate necessary RTL for __builtin_saveregs().
ARGLIST is the argument list; see expr.c. */
! #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.
*************** Clipper operand formatting codes:
*** 1123,1125 ****
--- 1123,1137 ----
#define PREDICATE_CODES \
{"int_reg_operand", {SUBREG, REG}}, \
{"fp_reg_operand", {SUBREG, REG}},
+
+ /* 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)