/* Compute different info about registers.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996
1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- 2009 Free Software Foundation, Inc.
+ 2009, 2010 Free Software Foundation, Inc.
This file is part of GCC.
#include "insn-config.h"
#include "recog.h"
#include "reload.h"
-#include "toplev.h"
#include "diagnostic-core.h"
#include "output.h"
#include "timevar.h"
}
}
-/* Function called only once to initialize the above data on reg usage.
- Once this is done, various switches may override. */
+/* Function called only once per target_globals to initialize the
+ target_hard_regs structure. Once this is done, various switches
+ may override. */
void
init_reg_sets (void)
{
memcpy (reg_alloc_order, initial_reg_alloc_order, sizeof reg_alloc_order);
#endif
memcpy (reg_names, initial_reg_names, sizeof reg_names);
- memset (global_regs, 0, sizeof global_regs);
}
/* Initialize may_move_cost and friends for mode M. */
inv_reg_alloc_order[reg_alloc_order[i]] = i;
#endif
- /* This macro allows the fixed or call-used registers
- and the register classes to depend on target flags. */
+ /* Let the target tweak things if necessary. */
-#ifdef CONDITIONAL_REGISTER_USAGE
- CONDITIONAL_REGISTER_USAGE;
-#endif
+ targetm.conditional_register_usage ();
/* Compute number of hard regs in each class. */
}
else if (i == FRAME_POINTER_REGNUM)
;
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
else if (i == HARD_FRAME_POINTER_REGNUM)
;
#endif
else if (i == ARG_POINTER_REGNUM && fixed_regs[i])
;
#endif
-#ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
- else if (i == (unsigned) PIC_OFFSET_TABLE_REGNUM && fixed_regs[i])
+ else if (!PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
+ && i == (unsigned) PIC_OFFSET_TABLE_REGNUM && fixed_regs[i])
;
-#endif
else if (CALL_REALLY_USED_REGNO_P (i))
{
SET_HARD_REG_BIT (regs_invalidated_by_call, i);
TO, using MODE. */
int
-register_move_cost (enum machine_mode mode, enum reg_class from,
- enum reg_class to)
+register_move_cost (enum machine_mode mode, reg_class_t from, reg_class_t to)
{
return targetm.register_move_cost (mode, from, to);
}
/* Compute extra cost of moving registers to/from memory due to reloads.
Only needed if secondary reloads are required for memory moves. */
int
-memory_move_secondary_cost (enum machine_mode mode, enum reg_class rclass,
+memory_move_secondary_cost (enum machine_mode mode, reg_class_t rclass,
bool in)
{
- enum reg_class altclass;
+ reg_class_t altclass;
int partial_cost = 0;
/* We need a memory reference to feed to SECONDARY... macros. */
/* mem may be unused even if the SECONDARY_ macros are defined. */
fix_register (const char *name, int fixed, int call_used)
{
int i;
+ int reg, nregs;
/* Decode the name and update the primary form of
the register info. */
- if ((i = decode_reg_name (name)) >= 0)
+ if ((reg = decode_reg_name_and_count (name, &nregs)) >= 0)
{
- if ((i == STACK_POINTER_REGNUM
+ gcc_assert (nregs >= 1);
+ for (i = reg; i < reg + nregs; i++)
+ {
+ if ((i == STACK_POINTER_REGNUM
#ifdef HARD_FRAME_POINTER_REGNUM
- || i == HARD_FRAME_POINTER_REGNUM
+ || i == HARD_FRAME_POINTER_REGNUM
#else
- || i == FRAME_POINTER_REGNUM
+ || i == FRAME_POINTER_REGNUM
#endif
- )
- && (fixed == 0 || call_used == 0))
- {
- static const char * const what_option[2][2] = {
- { "call-saved", "call-used" },
- { "no-such-option", "fixed" }};
-
- error ("can't use '%s' as a %s register", name,
- what_option[fixed][call_used]);
- }
- else
- {
- fixed_regs[i] = fixed;
- call_used_regs[i] = call_used;
+ )
+ && (fixed == 0 || call_used == 0))
+ {
+ switch (fixed)
+ {
+ case 0:
+ switch (call_used)
+ {
+ case 0:
+ error ("can%'t use %qs as a call-saved register", name);
+ break;
+
+ case 1:
+ error ("can%'t use %qs as a call-used register", name);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ break;
+
+ case 1:
+ switch (call_used)
+ {
+ case 1:
+ error ("can%'t use %qs as a fixed register", name);
+ break;
+
+ case 0:
+ default:
+ gcc_unreachable ();
+ }
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else
+ {
+ fixed_regs[i] = fixed;
+ call_used_regs[i] = call_used;
#ifdef CALL_REALLY_USED_REGISTERS
- if (fixed == 0)
- call_really_used_regs[i] = call_used;
+ if (fixed == 0)
+ call_really_used_regs[i] = call_used;
#endif
+ }
}
}
else
void
globalize_reg (int i)
{
+#ifdef STACK_REGS
+ if (IN_RANGE (i, FIRST_STACK_REG, LAST_STACK_REG))
+ {
+ error ("stack register used for global register variable");
+ return;
+ }
+#endif
+
if (fixed_regs[i] == 0 && no_global_reg_vars)
error ("global register variable follows a function definition");
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
- TV_NONE, /* tv_id */
+ TV_NONE, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
/* Return nonzero if C1 is a subset of C2, i.e., if every register in C1
is also in C2. */
int
-reg_class_subset_p (enum reg_class c1, enum reg_class c2)
+reg_class_subset_p (reg_class_t c1, reg_class_t c2)
{
return (c1 == c2
|| c2 == ALL_REGS