/* Subroutines used for code generation on Vitesse IQ2000 processors
- Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+ Free Software Foundation, Inc.
This file is part of GCC.
int num_gp; /* Number of gp registers saved. */
} iq2000_frame_info;
-struct machine_function GTY(())
+struct GTY(()) machine_function
{
/* Current frame information, calculated by compute_frame_size. */
long total_size; /* # bytes that the entire frame takes up. */
unsigned HOST_WIDE_INT);
static void iq2000_init_builtins (void);
static rtx iq2000_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
-static bool iq2000_return_in_memory (tree, tree);
+static bool iq2000_return_in_memory (const_tree, const_tree);
static void iq2000_setup_incoming_varargs (CUMULATIVE_ARGS *,
enum machine_mode, tree, int *,
int);
-static bool iq2000_rtx_costs (rtx, int, int, int *);
-static int iq2000_address_cost (rtx);
+static bool iq2000_rtx_costs (rtx, int, int, int *, bool);
+static int iq2000_address_cost (rtx, bool);
static section *iq2000_select_section (tree, int, unsigned HOST_WIDE_INT);
-static bool iq2000_return_in_memory (tree, tree);
static bool iq2000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
- tree, bool);
+ const_tree, bool);
static int iq2000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
tree, bool);
+static void iq2000_va_start (tree, rtx);
#undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS iq2000_init_builtins
#define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false
#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
+#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
+#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
#undef TARGET_PROMOTE_PROTOTYPES
-#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY iq2000_return_in_memory
#undef TARGET_STRICT_ARGUMENT_NAMING
#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
+#undef TARGET_EXPAND_BUILTIN_VA_START
+#define TARGET_EXPAND_BUILTIN_VA_START iq2000_va_start
+
struct gcc_target targetm = TARGET_INITIALIZER;
\f
/* Return nonzero if we split the address into high and low parts. */
/* Provide the costs of an addressing mode that contains ADDR. */
static int
-iq2000_address_cost (rtx addr)
+iq2000_address_cost (rtx addr, bool speed)
{
switch (GET_CODE (addr))
{
case LABEL_REF:
case HIGH:
case LO_SUM:
- return iq2000_address_cost (plus1) + 1;
+ return iq2000_address_cost (plus1, speed) + 1;
default:
break;
{
if (p_info->const_add != 0)
{
- HOST_WIDE_INT new = INTVAL (cmp1) + p_info->const_add;
+ HOST_WIDE_INT new_const = INTVAL (cmp1) + p_info->const_add;
/* If modification of cmp1 caused overflow,
we would get the wrong answer if we follow the usual path;
thus, x > 0xffffffffU would turn into x > 0U. */
if ((p_info->unsignedp
- ? (unsigned HOST_WIDE_INT) new >
+ ? (unsigned HOST_WIDE_INT) new_const >
(unsigned HOST_WIDE_INT) INTVAL (cmp1)
- : new > INTVAL (cmp1))
+ : new_const > INTVAL (cmp1))
!= (p_info->const_add > 0))
{
/* This test is always true, but if INVERT is true then
return result;
}
else
- cmp1 = GEN_INT (new);
+ cmp1 = GEN_INT (new_const);
}
}
cum->arg_words += 2;
break;
+ case TImode:
+ cum->gp_reg_found = 1;
+ cum->arg_words += 4;
+ break;
+
case QImode:
case HImode:
case SImode:
and type TYPE in CUM, or 0 if the argument is to be passed on the stack. */
struct rtx_def *
-function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
+function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, const_tree type,
int named)
{
rtx ret;
"function_arg( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
cum->gp_reg_found, cum->arg_number, cum->arg_words,
GET_MODE_NAME (mode));
- fprintf (stderr, "%p", (void *) type);
+ fprintf (stderr, "%p", (const void *) type);
fprintf (stderr, ", %d ) = ", named);
}
case DImode:
cum->arg_words += (cum->arg_words & 1);
regbase = GP_ARG_FIRST;
+ break;
+
+ case TImode:
+ cum->arg_words += (cum->arg_words & 3);
+ regbase = GP_ARG_FIRST;
+ break;
}
if (*arg_words >= (unsigned) MAX_ARGS_IN_REGISTERS)
\f
/* Implement va_start. */
-void
+static void
iq2000_va_start (tree valist, rtx nextarg)
{
int int_arg_words;
/* Find out how many non-float named formals. */
int gpr_save_area_size;
/* Note UNITS_PER_WORD is 4 bytes. */
- int_arg_words = current_function_args_info.arg_words;
+ int_arg_words = crtl->args.info.arg_words;
if (int_arg_words < 8 )
/* Adjust for the prologue's economy measure. */
{
struct machine_function *f;
- f = ggc_alloc_cleared (sizeof (struct machine_function));
+ f = GGC_CNEW (struct machine_function);
return f;
}
mask = 0;
extra_size = IQ2000_STACK_ALIGN ((0));
var_size = IQ2000_STACK_ALIGN (size);
- args_size = IQ2000_STACK_ALIGN (current_function_outgoing_args_size);
+ args_size = IQ2000_STACK_ALIGN (crtl->outgoing_args_size);
/* If a function dynamically allocates the stack and
has 0 for STACK_DYNAMIC_OFFSET then allocate some stack space. */
- if (args_size == 0 && current_function_calls_alloca)
+ if (args_size == 0 && cfun->calls_alloca)
args_size = 4 * UNITS_PER_WORD;
total_size = var_size + args_size + extra_size;
}
/* We need to restore these for the handler. */
- if (current_function_calls_eh_return)
+ if (crtl->calls_eh_return)
{
unsigned int i;
&& ! profile_flag)
total_size = extra_size = 0;
- total_size += IQ2000_STACK_ALIGN (current_function_pretend_args_size);
+ total_size += IQ2000_STACK_ALIGN (crtl->args.pretend_args_size);
/* Save other computed information. */
cfun->machine->total_size = total_size;
/* If struct value address is treated as the first argument. */
if (aggregate_value_p (DECL_RESULT (fndecl), fndecl)
- && ! current_function_returns_pcc_struct
+ && !cfun->returns_pcc_struct
&& targetm.calls.struct_value_rtx (TREE_TYPE (fndecl), 1) == 0)
{
tree type = build_pointer_type (fntype);
save_restore_insns (0);
- if (current_function_calls_eh_return)
+ if (crtl->calls_eh_return)
{
rtx eh_ofs = EH_RETURN_STACKADJ_RTX;
emit_insn (gen_addsi3 (eh_ofs, eh_ofs, tsize_rtx));
emit_insn (gen_blockage ());
- if (tsize != 0 || current_function_calls_eh_return)
+ if (tsize != 0 || crtl->calls_eh_return)
{
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
tsize_rtx));
}
}
- if (current_function_calls_eh_return)
+ if (crtl->calls_eh_return)
{
/* Perform the additional bump for __throw. */
emit_move_insn (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM),
stack_pointer_rtx);
- emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode,
- HARD_FRAME_POINTER_REGNUM)));
+ emit_use (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM));
emit_jump_insn (gen_eh_return_internal ());
}
else
FUNC. */
rtx
-iq2000_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
+iq2000_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
{
int reg = GP_RETURN;
enum machine_mode mode = TYPE_MODE (valtype);
static bool
iq2000_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- tree type, bool named ATTRIBUTE_UNUSED)
+ const_tree type, bool named ATTRIBUTE_UNUSED)
{
int size;
/* Worker function for TARGET_RETURN_IN_MEMORY. */
static bool
-iq2000_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
+iq2000_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
{
return ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD))
|| (int_size_in_bytes (type) == -1));
}
static bool
-iq2000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int * total)
+iq2000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int * total,
+ bool speed ATTRIBUTE_UNUSED)
{
enum machine_mode mode = GET_MODE (x);