#include "common/common-target.h"
#include "langhooks.h"
#include "sched-int.h"
-#include "pointer-set.h"
#include "vec.h"
#include "basic-block.h"
#include "tree-ssa-alias.h"
#include "opts.h"
#include "tree-pass.h"
#include "context.h"
+#include "cgraph.h"
+#include "builtins.h"
/* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */
#define UNSPEC_ADDRESS_P(X) \
in the sequence, otherwise return INSN itself. */
#define SEQ_BEGIN(INSN) \
(INSN_P (INSN) && GET_CODE (PATTERN (INSN)) == SEQUENCE \
- ? XVECEXP (PATTERN (INSN), 0, 0) \
+ ? as_a <rtx_insn *> (XVECEXP (PATTERN (INSN), 0, 0)) \
: (INSN))
/* Likewise for the last instruction in a delayed branch sequence. */
#define SEQ_END(INSN) \
(INSN_P (INSN) && GET_CODE (PATTERN (INSN)) == SEQUENCE \
- ? XVECEXP (PATTERN (INSN), 0, XVECLEN (PATTERN (INSN), 0) - 1) \
+ ? as_a <rtx_insn *> (XVECEXP (PATTERN (INSN), \
+ 0, \
+ XVECLEN (PATTERN (INSN), 0) - 1)) \
: (INSN))
/* Execute the following loop body with SUBINSN set to each instruction
/* The ISA level associated with mips_arch. */
int mips_isa;
+/* The ISA revision level. This is 0 for MIPS I to V and N for
+ MIPS{32,64}rN. */
+int mips_isa_rev;
+
/* The architecture selected by -mipsN, or null if -mipsN wasn't used. */
static const struct mips_cpu_info *mips_isa_option_info;
M16_REGS, M16_STORE_REGS, LEA_REGS, LEA_REGS,
LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
T_REG, PIC_FN_ADDR_REG, LEA_REGS, LEA_REGS,
- LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
+ LEA_REGS, M16_SP_REGS, LEA_REGS, LEA_REGS,
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
COSTS_N_INSNS (68), /* int_div_di */
1, /* branch_cost */
4 /* memory_latency */
+ },
+ { /* P5600 */
+ COSTS_N_INSNS (4), /* fp_add */
+ COSTS_N_INSNS (5), /* fp_mult_sf */
+ COSTS_N_INSNS (5), /* fp_mult_df */
+ COSTS_N_INSNS (17), /* fp_div_sf */
+ COSTS_N_INSNS (17), /* fp_div_df */
+ COSTS_N_INSNS (5), /* int_mult_si */
+ COSTS_N_INSNS (5), /* int_mult_di */
+ COSTS_N_INSNS (8), /* int_div_si */
+ COSTS_N_INSNS (8), /* int_div_di */
+ 2, /* branch_cost */
+ 10 /* memory_latency */
}
};
\f
-static rtx mips_find_pic_call_symbol (rtx, rtx, bool);
+static rtx mips_find_pic_call_symbol (rtx_insn *, rtx, bool);
static int mips_register_move_cost (enum machine_mode, reg_class_t,
reg_class_t);
static unsigned int mips_function_arg_boundary (enum machine_mode, const_tree);
\f
-/* This hash table keeps track of implicit "mips16" and "nomips16" attributes
- for -mflip_mips16. It maps decl names onto a boolean mode setting. */
-struct GTY (()) mflip_mips16_entry {
- const char *name;
- bool mips16_p;
-};
-static GTY ((param_is (struct mflip_mips16_entry))) htab_t mflip_mips16_htab;
-
-/* Hash table callbacks for mflip_mips16_htab. */
-
-static hashval_t
-mflip_mips16_htab_hash (const void *entry)
+struct mips16_flip_traits : default_hashmap_traits
{
- return htab_hash_string (((const struct mflip_mips16_entry *) entry)->name);
-}
+ static hashval_t hash (const char *s) { return htab_hash_string (s); }
+ static bool
+ equal_keys (const char *a, const char *b)
+ {
+ return !strcmp (a, b);
+ }
+};
-static int
-mflip_mips16_htab_eq (const void *entry, const void *name)
-{
- return strcmp (((const struct mflip_mips16_entry *) entry)->name,
- (const char *) name) == 0;
-}
+/* This hash table keeps track of implicit "mips16" and "nomips16" attributes
+ for -mflip_mips16. It maps decl names onto a boolean mode setting. */
+static GTY (()) hash_map<const char *, bool, mips16_flip_traits> *
+ mflip_mips16_htab;
/* True if -mflip-mips16 should next add an attribute for the default MIPS16
mode, false if it should next add an attribute for the opposite mode. */
static bool
mflip_mips16_use_mips16_p (tree decl)
{
- struct mflip_mips16_entry *entry;
const char *name;
- hashval_t hash;
- void **slot;
bool base_is_mips16 = (mips_base_compression_flags & MASK_MIPS16) != 0;
/* Use the opposite of the command-line setting for anonymous decls. */
return !base_is_mips16;
if (!mflip_mips16_htab)
- mflip_mips16_htab = htab_create_ggc (37, mflip_mips16_htab_hash,
- mflip_mips16_htab_eq, NULL);
+ mflip_mips16_htab
+ = hash_map<const char *, bool, mips16_flip_traits>::create_ggc (37);
name = IDENTIFIER_POINTER (DECL_NAME (decl));
- hash = htab_hash_string (name);
- slot = htab_find_slot_with_hash (mflip_mips16_htab, name, hash, INSERT);
- entry = (struct mflip_mips16_entry *) *slot;
- if (!entry)
+
+ bool existed;
+ bool *slot = &mflip_mips16_htab->get_or_insert (name, &existed);
+ if (!existed)
{
mips16_flipper = !mips16_flipper;
- entry = ggc_alloc_mflip_mips16_entry ();
- entry->name = name;
- entry->mips16_p = mips16_flipper ? !base_is_mips16 : base_is_mips16;
- *slot = entry;
+ *slot = mips16_flipper ? !base_is_mips16 : base_is_mips16;
}
- return entry->mips16_p;
+ return *slot;
}
\f
/* Predicates to test for presence of "near" and "far"/"long_call"
return mips_symbol_insns_1 (type, mode) * (TARGET_MIPS16 ? 2 : 1);
}
\f
-/* A for_each_rtx callback. Stop the search if *X references a
- thread-local symbol. */
-
-static int
-mips_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
-{
- return mips_tls_symbol_p (*x);
-}
-
/* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
static bool
}
/* TLS symbols must be computed by mips_legitimize_move. */
- if (for_each_rtx (&x, &mips_tls_symbol_ref_1, NULL))
+ if (tls_referenced_p (x))
return true;
return false;
return true;
/* In MIPS16 mode, the stack pointer can only address word and doubleword
- values, nothing smaller. There are two problems here:
-
- (a) Instantiating virtual registers can introduce new uses of the
- stack pointer. If these virtual registers are valid addresses,
- the stack pointer should be too.
-
- (b) Most uses of the stack pointer are not made explicit until
- FRAME_POINTER_REGNUM and ARG_POINTER_REGNUM have been eliminated.
- We don't know until that stage whether we'll be eliminating to the
- stack pointer (which needs the restriction) or the hard frame
- pointer (which doesn't).
-
- All in all, it seems more consistent to only enforce this restriction
- during and after reload. */
+ values, nothing smaller. */
if (TARGET_MIPS16 && regno == STACK_POINTER_REGNUM)
- return !strict_p || GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
+ return GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
return TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno);
}
BASE_INSN_LENGTH is the length of one instruction. */
int
-mips_load_store_insns (rtx mem, rtx insn)
+mips_load_store_insns (rtx mem, rtx_insn *insn)
{
enum machine_mode mode;
bool might_split_p;
how to force Pmode objects into the constant pool even when the
constant pool address is not itself legitimate. */
-rtx
+rtx_insn *
mips_emit_move (rtx dest, rtx src)
{
return (can_create_pseudo_p ()
ADDR is the legitimized form, and LAZY_P is true if the call
address is lazily-bound. */
-static rtx
+static rtx_insn *
mips_emit_call_insn (rtx pattern, rtx orig_addr, rtx addr, bool lazy_p)
{
- rtx insn, reg;
+ rtx_insn *insn;
+ rtx reg;
insn = emit_call_insn (pattern);
gen_rtx_REG (Pmode, GOT_VERSION_REGNUM));
emit_insn (gen_update_got_version ());
}
+
+ if (TARGET_MIPS16
+ && TARGET_EXPLICIT_RELOCS
+ && TARGET_CALL_CLOBBERED_GP)
+ {
+ rtx post_call_tmp_reg = gen_rtx_REG (word_mode, POST_CALL_TMP_REG);
+ clobber_reg (&CALL_INSN_FUNCTION_USAGE (insn), post_call_tmp_reg);
+ }
+
return insn;
}
\f
{
if (cfun->machine->mips16_gp_pseudo_rtx == NULL_RTX)
{
- rtx insn, scan;
+ rtx_insn *scan;
cfun->machine->mips16_gp_pseudo_rtx = gen_reg_rtx (Pmode);
while (NEXT_INSN (scan) && !INSN_P (NEXT_INSN (scan)))
scan = NEXT_INSN (scan);
- insn = gen_load_const_gp (cfun->machine->mips16_gp_pseudo_rtx);
- insn = emit_insn_after (insn, scan);
+ rtx set = gen_load_const_gp (cfun->machine->mips16_gp_pseudo_rtx);
+ rtx_insn *insn = emit_insn_after (set, scan);
INSN_LOCATION (insn) = 0;
pop_topmost_sequence ();
TREE_PUBLIC (decl) = 1;
TREE_STATIC (decl) = 1;
- DECL_COMDAT_GROUP (decl) = DECL_ASSEMBLER_NAME (decl);
+ cgraph_node::create (decl)->set_comdat_group (DECL_ASSEMBLER_NAME (decl));
targetm.asm_out.unique_section (decl, 0);
switch_to_section (get_named_section (decl, NULL, 0));
}
}
\f
+struct local_alias_traits : default_hashmap_traits
+{
+ static hashval_t hash (rtx);
+ static bool equal_keys (rtx, rtx);
+};
+
/* Each locally-defined hard-float MIPS16 function has a local symbol
associated with it. This hash table maps the function symbol (FUNC)
to the local symbol (LOCAL). */
-struct GTY(()) mips16_local_alias {
- rtx func;
- rtx local;
-};
-static GTY ((param_is (struct mips16_local_alias))) htab_t mips16_local_aliases;
+static GTY (()) hash_map<rtx, rtx, local_alias_traits> *mips16_local_aliases;
/* Hash table callbacks for mips16_local_aliases. */
-static hashval_t
-mips16_local_aliases_hash (const void *entry)
+hashval_t
+local_alias_traits::hash (rtx func)
{
- const struct mips16_local_alias *alias;
-
- alias = (const struct mips16_local_alias *) entry;
- return htab_hash_string (XSTR (alias->func, 0));
+ return htab_hash_string (XSTR (func, 0));
}
-static int
-mips16_local_aliases_eq (const void *entry1, const void *entry2)
+bool
+local_alias_traits::equal_keys (rtx func1, rtx func2)
{
- const struct mips16_local_alias *alias1, *alias2;
-
- alias1 = (const struct mips16_local_alias *) entry1;
- alias2 = (const struct mips16_local_alias *) entry2;
- return rtx_equal_p (alias1->func, alias2->func);
+ return rtx_equal_p (func1, func2);
}
/* FUNC is the symbol for a locally-defined hard-float MIPS16 function.
static rtx
mips16_local_alias (rtx func)
{
- struct mips16_local_alias *alias, tmp_alias;
- void **slot;
-
/* Create the hash table if this is the first call. */
if (mips16_local_aliases == NULL)
- mips16_local_aliases = htab_create_ggc (37, mips16_local_aliases_hash,
- mips16_local_aliases_eq, NULL);
+ mips16_local_aliases
+ = hash_map<rtx, rtx, local_alias_traits>::create_ggc (37);
/* Look up the function symbol, creating a new entry if need be. */
- tmp_alias.func = func;
- slot = htab_find_slot (mips16_local_aliases, &tmp_alias, INSERT);
+ bool existed;
+ rtx *slot = &mips16_local_aliases->get_or_insert (func, &existed);
gcc_assert (slot != NULL);
- alias = (struct mips16_local_alias *) *slot;
- if (alias == NULL)
+ if (!existed)
{
const char *func_name, *local_name;
rtx local;
SYMBOL_REF_FLAGS (local) = SYMBOL_REF_FLAGS (func) | SYMBOL_FLAG_LOCAL;
/* Create a new structure to represent the mapping. */
- alias = ggc_alloc_mips16_local_alias ();
- alias->func = func;
- alias->local = local;
- *slot = alias;
+ *slot = local;
}
- return alias->local;
+ return *slot;
}
\f
/* A chained list of functions for which mips16_build_call_stub has already
stubdecl = build_decl (BUILTINS_LOCATION,
FUNCTION_DECL, get_identifier (stubname),
build_function_type_list (void_type_node, NULL_TREE));
- DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname);
+ set_decl_section_name (stubdecl, secname);
DECL_RESULT (stubdecl) = build_decl (BUILTINS_LOCATION,
RESULT_DECL, NULL_TREE, void_type_node);
automatically redirects the JAL to the stub, otherwise the JAL
continues to call FN directly. */
-static rtx
+static rtx_insn *
mips16_build_call_stub (rtx retval, rtx *fn_ptr, rtx args_size, int fp_code)
{
const char *fnname;
bool fp_ret_p;
struct mips16_stub *l;
- rtx insn, fn;
+ rtx_insn *insn;
+ rtx pattern, fn;
/* We don't need to do anything if we aren't in MIPS16 mode, or if
we were invoked with the -msoft-float option. */
if (!TARGET_MIPS16 || TARGET_SOFT_FLOAT_ABI)
- return NULL_RTX;
+ return NULL;
/* Figure out whether the value might come back in a floating-point
register. */
arguments and the value will not be returned in a floating-point
register. */
if (fp_code == 0 && !fp_ret_p)
- return NULL_RTX;
+ return NULL;
/* We don't need to do anything if this is a call to a special
MIPS16 support function. */
fn = *fn_ptr;
if (mips16_stub_function_p (fn))
- return NULL_RTX;
+ return NULL;
/* If we're calling a locally-defined MIPS16 function, we know that
it will return values in both the "soft-float" and "hard-float"
registers. There is no need to use a stub to move the latter
to the former. */
if (fp_code == 0 && mips16_local_function_p (fn))
- return NULL_RTX;
+ return NULL;
/* This code will only work for o32 and o64 abis. The other ABI's
require more sophisticated support. */
|| !call_insn_operand (fn, VOIDmode))
{
char buf[30];
- rtx stub_fn, insn, addr;
+ rtx stub_fn, addr;
+ rtx_insn *insn;
bool lazy_p;
/* If this is a locally-defined and locally-binding function,
if (mips16_local_function_p (fn))
{
*fn_ptr = mips16_local_alias (fn);
- return NULL_RTX;
+ return NULL;
}
/* Create a SYMBOL_REF for the libgcc.a function. */
FUNCTION_DECL, stubid,
build_function_type_list (void_type_node,
NULL_TREE));
- DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname);
+ set_decl_section_name (stubdecl, secname);
DECL_RESULT (stubdecl) = build_decl (BUILTINS_LOCATION,
RESULT_DECL, NULL_TREE,
void_type_node);
error ("cannot handle inconsistent calls to %qs", fnname);
if (retval == NULL_RTX)
- insn = gen_call_internal_direct (fn, args_size);
+ pattern = gen_call_internal_direct (fn, args_size);
else
- insn = gen_call_value_internal_direct (retval, fn, args_size);
- insn = mips_emit_call_insn (insn, fn, fn, false);
+ pattern = gen_call_value_internal_direct (retval, fn, args_size);
+ insn = mips_emit_call_insn (pattern, fn, fn, false);
/* If we are calling a stub which handles a floating-point return
value, we need to arrange to save $18 in the prologue. We do this
Return the call itself. */
-rtx
+rtx_insn *
mips_expand_call (enum mips_call_type type, rtx result, rtx addr,
rtx args_size, rtx aux, bool lazy_p)
{
- rtx orig_addr, pattern, insn;
+ rtx orig_addr, pattern;
+ rtx_insn *insn;
int fp_code;
fp_code = aux == 0 ? 0 : (int) GET_MODE (aux);
{
emit_call_insn (call_pattern);
if (!find_reg_note (insn, REG_NORETURN, 0))
- /* Pick a temporary register that is suitable for both MIPS16 and
- non-MIPS16 code. $4 and $5 are used for returning complex double
- values in soft-float code, so $6 is the first suitable candidate. */
- mips_restore_gp_from_cprestore_slot (gen_rtx_REG (Pmode, GP_ARG_FIRST + 2));
+ mips_restore_gp_from_cprestore_slot (gen_rtx_REG (Pmode,
+ POST_CALL_TMP_REG));
}
/* Return true if a call to DECL may need to use JALX. */
return true;
}
\f
-/* Emit code to move general operand SRC into condition-code
- register DEST given that SCRATCH is a scratch TFmode FPR.
- The sequence is:
-
- FP1 = SRC
- FP2 = 0.0f
- DEST = FP2 < FP1
-
- where FP1 and FP2 are single-precision FPRs taken from SCRATCH. */
-
-void
-mips_expand_fcc_reload (rtx dest, rtx src, rtx scratch)
-{
- rtx fp1, fp2;
-
- /* Change the source to SFmode. */
- if (MEM_P (src))
- src = adjust_address (src, SFmode, 0);
- else if (REG_P (src) || GET_CODE (src) == SUBREG)
- src = gen_rtx_REG (SFmode, true_regnum (src));
-
- fp1 = gen_rtx_REG (SFmode, REGNO (scratch));
- fp2 = gen_rtx_REG (SFmode, REGNO (scratch) + MAX_FPRS_PER_FMT);
-
- mips_emit_move (copy_rtx (fp1), src);
- mips_emit_move (copy_rtx (fp2), CONST0_RTX (SFmode));
- emit_insn (gen_slt_sf (dest, fp2, fp1));
-}
-\f
/* Implement MOVE_BY_PIECES_P. */
bool
mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length,
HOST_WIDE_INT bytes_per_iter)
{
- rtx label, src_reg, dest_reg, final_src, test;
+ rtx_code_label *label;
+ rtx src_reg, dest_reg, final_src, test;
HOST_WIDE_INT leftover;
leftover = length % bytes_per_iter;
void
mips_expand_synci_loop (rtx begin, rtx end)
{
- rtx inc, label, end_label, cmp_result, mask, length;
+ rtx inc, cmp_result, mask, length;
+ rtx_code_label *label, *end_label;
/* Create end_label. */
end_label = gen_label_rtx ();
length = mips_force_binary (Pmode, MINUS, end, begin);
/* Loop back to here. */
- label = gen_label_rtx ();
+ label = gen_label_rtx ();
emit_label (label);
emit_insn (gen_synci (begin));
/* If the delay slot instruction is short, then use the
compact version. */
if (final_sequence == 0
- || get_attr_length (XVECEXP (final_sequence, 0, 1)) == 2)
+ || get_attr_length (final_sequence->insn (1)) == 2)
putc ('s', file);
break;
if (decl && DECL_SECTION_NAME (decl))
{
- const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
- if (DECL_ONE_ONLY (decl) && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
+ const char *name = DECL_SECTION_NAME (decl);
+ if (DECL_COMDAT_GROUP (decl) && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
{
char *rname = ASTRDUP (name);
rname[14] = 'd';
const char *name;
/* Reject anything that isn't in a known small-data section. */
- name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
+ name = DECL_SECTION_NAME (decl);
if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0)
return false;
static void
mips_set_frame_expr (rtx frame_pattern)
{
- rtx insn;
+ rtx_insn *insn;
insn = get_last_insn ();
RTX_FRAME_RELATED_P (insn) = 1;
mips16e_collect_argument_saves (void)
{
rtx reg_values[FIRST_PSEUDO_REGISTER];
- rtx insn, next, set, dest, src;
+ rtx_insn *insn, *next;
+ rtx set, dest, src;
unsigned int nargs, regno;
push_topmost_sequence ();
if *CACHE is already true. */
static bool
-mips_find_gp_ref (bool *cache, bool (*pred) (rtx))
+mips_find_gp_ref (bool *cache, bool (*pred) (rtx_insn *))
{
- rtx insn;
+ rtx_insn *insn;
if (!*cache)
{
See mips_cfun_has_inflexible_gp_ref_p for details. */
static bool
-mips_insn_has_inflexible_gp_ref_p (rtx insn)
+mips_insn_has_inflexible_gp_ref_p (rtx_insn *insn)
{
/* Uses of pic_offset_table_rtx in CALL_INSN_FUNCTION_USAGE
indicate that the target could be a traditional MIPS
See mips_cfun_has_flexible_gp_ref_p for details. */
static bool
-mips_insn_has_flexible_gp_ref_p (rtx insn)
+mips_insn_has_flexible_gp_ref_p (rtx_insn *insn)
{
return (get_attr_got (insn) != GOT_UNSET
|| mips_small_data_pattern_p (PATTERN (insn))
/* Set this function's interrupt properties. */
if (mips_interrupt_type_p (TREE_TYPE (current_function_decl)))
{
- if (!ISA_MIPS32R2)
- error ("the %<interrupt%> attribute requires a MIPS32r2 processor");
+ if (mips_isa_rev < 2)
+ error ("the %<interrupt%> attribute requires a MIPS32r2 processor or greater");
else if (TARGET_HARD_FLOAT)
error ("the %<interrupt%> attribute requires %<-msoft-float%>");
else if (TARGET_MIPS16)
const struct mips_frame_info *frame;
HOST_WIDE_INT size;
unsigned int nargs;
- rtx insn;
if (cfun->machine->global_pointer != INVALID_REGNUM)
{
/* Build the save instruction. */
mask = frame->mask;
- insn = mips16e_build_save_restore (false, &mask, &offset,
- nargs, step1);
+ rtx insn = mips16e_build_save_restore (false, &mask, &offset,
+ nargs, step1);
RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
mips_frame_barrier ();
size -= step1;
}
/* Allocate the first part of the frame. */
- insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-step1));
+ rtx insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
+ GEN_INT (-step1));
RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
mips_frame_barrier ();
size -= step1;
}
else
{
- insn = gen_add3_insn (stack_pointer_rtx,
- stack_pointer_rtx,
- GEN_INT (-step1));
+ rtx insn = gen_add3_insn (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (-step1));
RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
mips_frame_barrier ();
size -= step1;
offset = frame->hard_frame_pointer_offset;
if (offset == 0)
{
- insn = mips_emit_move (hard_frame_pointer_rtx, stack_pointer_rtx);
+ rtx insn = mips_emit_move (hard_frame_pointer_rtx, stack_pointer_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
}
else if (SMALL_OPERAND (offset))
{
- insn = gen_add3_insn (hard_frame_pointer_rtx,
- stack_pointer_rtx, GEN_INT (offset));
+ rtx insn = gen_add3_insn (hard_frame_pointer_rtx,
+ stack_pointer_rtx, GEN_INT (offset));
RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
}
else
/* We need to search back to the last use of K0 or K1. */
if (cfun->machine->interrupt_handler_p)
{
+ rtx_insn *insn;
for (insn = get_last_insn (); insn != NULL_RTX; insn = PREV_INSN (insn))
if (INSN_P (insn)
&& for_each_rtx (&PATTERN (insn), mips_kernel_reg_p, NULL))
/* Attach all pending register saves to the previous instruction.
Return that instruction. */
-static rtx
+static rtx_insn *
mips_epilogue_emit_cfa_restores (void)
{
- rtx insn;
+ rtx_insn *insn;
insn = get_last_insn ();
gcc_assert (insn && !REG_NOTES (insn));
static void
mips_epilogue_set_cfa (rtx reg, HOST_WIDE_INT offset)
{
- rtx insn;
+ rtx_insn *insn;
insn = mips_epilogue_emit_cfa_restores ();
if (reg != mips_epilogue.cfa_reg || offset != mips_epilogue.cfa_offset)
{
const struct mips_frame_info *frame;
HOST_WIDE_INT step1, step2;
- rtx base, adjust, insn;
+ rtx base, adjust;
+ rtx_insn *insn;
bool use_jraddiusp_p = false;
if (!sibcall_p && mips_can_use_return_insn ())
return rclass;
}
-/* Return the cost of moving a value of mode MODE from a register of
- class FROM to a GPR. Return 0 for classes that are unions of other
- classes handled by this function. */
+/* Return the cost of moving a value from a register of class FROM to a GPR.
+ Return 0 for classes that are unions of other classes handled by this
+ function. */
static int
-mips_move_to_gpr_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
- reg_class_t from)
+mips_move_to_gpr_cost (reg_class_t from)
{
switch (from)
{
/* MFC1, etc. */
return 4;
- case ST_REGS:
- /* LUI followed by MOVF. */
- return 4;
-
case COP0_REGS:
case COP2_REGS:
case COP3_REGS:
}
}
-/* Return the cost of moving a value of mode MODE from a GPR to a
- register of class TO. Return 0 for classes that are unions of
- other classes handled by this function. */
+/* Return the cost of moving a value from a GPR to a register of class TO.
+ Return 0 for classes that are unions of other classes handled by this
+ function. */
static int
-mips_move_from_gpr_cost (enum machine_mode mode, reg_class_t to)
+mips_move_from_gpr_cost (reg_class_t to)
{
switch (to)
{
/* MTC1, etc. */
return 4;
- case ST_REGS:
- /* A secondary reload through an FPR scratch. */
- return (mips_register_move_cost (mode, GENERAL_REGS, FP_REGS)
- + mips_register_move_cost (mode, FP_REGS, ST_REGS));
-
case COP0_REGS:
case COP2_REGS:
case COP3_REGS:
if (to == FP_REGS && mips_mode_ok_for_mov_fmt_p (mode))
/* MOV.FMT. */
return 4;
- if (to == ST_REGS)
- /* The sequence generated by mips_expand_fcc_reload. */
- return 8;
}
/* Handle cases in which only one class deviates from the ideal. */
dregs = TARGET_MIPS16 ? M16_REGS : GENERAL_REGS;
if (from == dregs)
- return mips_move_from_gpr_cost (mode, to);
+ return mips_move_from_gpr_cost (to);
if (to == dregs)
- return mips_move_to_gpr_cost (mode, from);
+ return mips_move_to_gpr_cost (from);
/* Handles cases that require a GPR temporary. */
- cost1 = mips_move_to_gpr_cost (mode, from);
+ cost1 = mips_move_to_gpr_cost (from);
if (cost1 != 0)
{
- cost2 = mips_move_from_gpr_cost (mode, to);
+ cost2 = mips_move_from_gpr_cost (to);
if (cost2 != 0)
return cost1 + cost2;
}
return 0;
}
+/* Implement TARGET_REGISTER_PRIORITY. */
+
+static int
+mips_register_priority (int hard_regno)
+{
+ /* Treat MIPS16 registers with higher priority than other regs. */
+ if (TARGET_MIPS16
+ && TEST_HARD_REG_BIT (reg_class_contents[M16_REGS], hard_regno))
+ return 1;
+ return 0;
+}
+
/* Implement TARGET_MEMORY_MOVE_COST. */
static int
enum reg_class
mips_secondary_reload_class (enum reg_class rclass,
- enum machine_mode mode, rtx x, bool in_p)
+ enum machine_mode mode, rtx x, bool)
{
int regno;
if (ACC_REG_P (regno))
return reg_class_subset_p (rclass, GR_REGS) ? NO_REGS : GR_REGS;
- /* We can only copy a value to a condition code register from a
- floating-point register, and even then we require a scratch
- floating-point register. We can only copy a value out of a
- condition-code register into a general register. */
- if (reg_class_subset_p (rclass, ST_REGS))
- {
- if (in_p)
- return FP_REGS;
- return GP_REG_P (regno) ? NO_REGS : GR_REGS;
- }
- if (ST_REG_P (regno))
- {
- if (!in_p)
- return FP_REGS;
- return reg_class_subset_p (rclass, GR_REGS) ? NO_REGS : GR_REGS;
- }
-
if (reg_class_subset_p (rclass, FP_REGS))
{
- if (MEM_P (x)
- && (GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8))
+ if (regno < 0
+ || (MEM_P (x)
+ && (GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8)))
/* In this case we can use lwc1, swc1, ldc1 or sdc1. We'll use
pairs of lwc1s and swc1s if ldc1 and sdc1 are not supported. */
return NO_REGS;
attributes in the machine-description file. */
int
-mips_adjust_insn_length (rtx insn, int length)
+mips_adjust_insn_length (rtx_insn *insn, int length)
{
/* mips.md uses MAX_PIC_BRANCH_LENGTH as a placeholder for the length
of a PIC long-branch sequence. Substitute the correct value. */
version of BRANCH_IF_TRUE. */
const char *
-mips_output_conditional_branch (rtx insn, rtx *operands,
+mips_output_conditional_branch (rtx_insn *insn, rtx *operands,
const char *branch_if_true,
const char *branch_if_false)
{
unsigned int length;
- rtx taken, not_taken;
+ rtx taken;
gcc_assert (LABEL_P (operands[0]));
/* Generate a reversed branch around a direct jump. This fallback does
not use branch-likely instructions. */
mips_branch_likely = false;
- not_taken = gen_label_rtx ();
+ rtx_code_label *not_taken = gen_label_rtx ();
taken = operands[0];
/* Generate the reversed branch to NOT_TAKEN. */
delay slot if is not annulled. */
if (!INSN_ANNULLED_BRANCH_P (insn))
{
- final_scan_insn (XVECEXP (final_sequence, 0, 1),
+ final_scan_insn (final_sequence->insn (1),
asm_out_file, optimize, 1, NULL);
- INSN_DELETED_P (XVECEXP (final_sequence, 0, 1)) = 1;
+ final_sequence->insn (1)->set_deleted ();
}
else
output_asm_insn ("nop", 0);
Use INSN's delay slot if is annulled. */
if (INSN_ANNULLED_BRANCH_P (insn))
{
- final_scan_insn (XVECEXP (final_sequence, 0, 1),
+ final_scan_insn (final_sequence->insn (1),
asm_out_file, optimize, 1, NULL);
- INSN_DELETED_P (XVECEXP (final_sequence, 0, 1)) = 1;
+ final_sequence->insn (1)->set_deleted ();
}
else
output_asm_insn ("nop", 0);
its second is always zero. */
const char *
-mips_output_order_conditional_branch (rtx insn, rtx *operands, bool inverted_p)
+mips_output_order_conditional_branch (rtx_insn *insn, rtx *operands, bool inverted_p)
{
const char *branch[2];
sequence for it. */
static void
-mips_process_sync_loop (rtx insn, rtx *operands)
+mips_process_sync_loop (rtx_insn *insn, rtx *operands)
{
rtx at, mem, oldval, newval, inclusive_mask, exclusive_mask;
rtx required_oldval, insn1_op2, tmp1, tmp2, tmp3, cmp;
the operands given by OPERANDS. */
const char *
-mips_output_sync_loop (rtx insn, rtx *operands)
+mips_output_sync_loop (rtx_insn *insn, rtx *operands)
{
mips_process_sync_loop (insn, operands);
which has the operands given by OPERANDS. */
unsigned int
-mips_sync_loop_insns (rtx insn, rtx *operands)
+mips_sync_loop_insns (rtx_insn *insn, rtx *operands)
{
mips_process_sync_loop (insn, operands);
return mips_multi_num_insns;
return s;
}
\f
+/* Return true if destination of IN_INSN is used as add source in
+ OUT_INSN. Both IN_INSN and OUT_INSN are of type fmadd. Example:
+ madd.s dst, x, y, z
+ madd.s a, dst, b, c */
+
+bool
+mips_fmadd_bypass (rtx_insn *out_insn, rtx_insn *in_insn)
+{
+ int dst_reg, src_reg;
+
+ gcc_assert (get_attr_type (in_insn) == TYPE_FMADD);
+ gcc_assert (get_attr_type (out_insn) == TYPE_FMADD);
+
+ extract_insn (in_insn);
+ dst_reg = REG_P (recog_data.operand[0]);
+
+ extract_insn (out_insn);
+ src_reg = REG_P (recog_data.operand[1]);
+
+ if (dst_reg == src_reg)
+ return true;
+
+ return false;
+}
+
/* Return true if IN_INSN is a multiply-add or multiply-subtract
instruction and if OUT_INSN assigns to the accumulator operand. */
bool
-mips_linked_madd_p (rtx out_insn, rtx in_insn)
+mips_linked_madd_p (rtx_insn *out_insn, rtx_insn *in_insn)
{
enum attr_accum_in accum_in;
int accum_in_opnum;
for that case. */
bool
-mips_store_data_bypass_p (rtx out_insn, rtx in_insn)
+mips_store_data_bypass_p (rtx_insn *out_insn, rtx_insn *in_insn)
{
if (GET_CODE (PATTERN (in_insn)) == UNSPEC_VOLATILE)
return false;
DFA state.
E.g., when alu1_turn_enabled_insn is issued it makes next ALU1/2
instruction to go ALU1. */
- rtx alu1_turn_enabled_insn;
- rtx alu2_turn_enabled_insn;
- rtx falu1_turn_enabled_insn;
- rtx falu2_turn_enabled_insn;
+ rtx_insn *alu1_turn_enabled_insn;
+ rtx_insn *alu2_turn_enabled_insn;
+ rtx_insn *falu1_turn_enabled_insn;
+ rtx_insn *falu2_turn_enabled_insn;
} mips_ls2;
/* Implement TARGET_SCHED_ADJUST_COST. We assume that anti and output
is treated like input-dependence. */
static int
-mips_adjust_cost (rtx insn ATTRIBUTE_UNUSED, rtx link,
- rtx dep ATTRIBUTE_UNUSED, int cost)
+mips_adjust_cost (rtx_insn *insn ATTRIBUTE_UNUSED, rtx link,
+ rtx_insn *dep ATTRIBUTE_UNUSED, int cost)
{
if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT
&& TUNE_20KC)
case PROCESSOR_LOONGSON_2E:
case PROCESSOR_LOONGSON_2F:
case PROCESSOR_LOONGSON_3A:
+ case PROCESSOR_P5600:
return 4;
case PROCESSOR_XLP:
if (TUNE_OCTEON)
return 2;
+ if (TUNE_P5600)
+ return 4;
+
return 0;
}
\f
be <= HIGHER. */
static void
-mips_promote_ready (rtx *ready, int lower, int higher)
+mips_promote_ready (rtx_insn **ready, int lower, int higher)
{
- rtx new_head;
+ rtx_insn *new_head;
int i;
new_head = ready[lower];
instructions if POS2 is not already less than POS1. */
static void
-mips_maybe_swap_ready (rtx *ready, int pos1, int pos2, int limit)
+mips_maybe_swap_ready (rtx_insn **ready, int pos1, int pos2, int limit)
{
if (pos1 < pos2
&& INSN_PRIORITY (ready[pos1]) + limit >= INSN_PRIORITY (ready[pos2]))
{
- rtx temp;
+ rtx_insn *temp;
temp = ready[pos1];
ready[pos1] = ready[pos2];
\f
/* Used by TUNE_MACC_CHAINS to record the last scheduled instruction
that may clobber hi or lo. */
-static rtx mips_macc_chains_last_hilo;
+static rtx_insn *mips_macc_chains_last_hilo;
/* A TUNE_MACC_CHAINS helper function. Record that instruction INSN has
been scheduled, updating mips_macc_chains_last_hilo appropriately. */
static void
-mips_macc_chains_record (rtx insn)
+mips_macc_chains_record (rtx_insn *insn)
{
if (get_attr_may_clobber_hilo (insn))
mips_macc_chains_last_hilo = insn;
clobber hi or lo. */
static void
-mips_macc_chains_reorder (rtx *ready, int nready)
+mips_macc_chains_reorder (rtx_insn **ready, int nready)
{
int i, j;
}
\f
/* The last instruction to be scheduled. */
-static rtx vr4130_last_insn;
+static rtx_insn *vr4130_last_insn;
/* A note_stores callback used by vr4130_true_reg_dependence_p. DATA
points to an rtx that is initially an instruction. Nullify the rtx
alignment than (INSN1, INSN2). See 4130.md for more details. */
static bool
-vr4130_swap_insns_p (rtx insn1, rtx insn2)
+vr4130_swap_insns_p (rtx_insn *insn1, rtx_insn *insn2)
{
sd_iterator_def sd_it;
dep_t dep;
vr4130_swap_insns_p says that it could be worthwhile. */
static void
-vr4130_reorder (rtx *ready, int nready)
+vr4130_reorder (rtx_insn **ready, int nready)
{
if (vr4130_swap_insns_p (ready[nready - 1], ready[nready - 2]))
mips_promote_ready (ready, nready - 2, nready - 1);
resets to TYPE_UNKNOWN state. */
static void
-mips_74k_agen_init (rtx insn)
+mips_74k_agen_init (rtx_insn *insn)
{
if (!insn || CALL_P (insn) || JUMP_P (insn))
mips_last_74k_agen_insn = TYPE_UNKNOWN;
together. Swap things around in the ready queue to make this happen. */
static void
-mips_74k_agen_reorder (rtx *ready, int nready)
+mips_74k_agen_reorder (rtx_insn **ready, int nready)
{
int i;
int store_pos, load_pos;
for (i = nready - 1; i >= 0; i--)
{
- rtx insn = ready[i];
+ rtx_insn *insn = ready[i];
if (USEFUL_INSN_P (insn))
switch (get_attr_type (insn))
{
{
mips_macc_chains_last_hilo = 0;
vr4130_last_insn = 0;
- mips_74k_agen_init (NULL_RTX);
+ mips_74k_agen_init (NULL);
/* When scheduling for Loongson2, branch instructions go to ALU1,
therefore basic block is most likely to start with round-robin counter
static void
mips_sched_reorder_1 (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
- rtx *ready, int *nreadyp, int cycle ATTRIBUTE_UNUSED)
+ rtx_insn **ready, int *nreadyp, int cycle ATTRIBUTE_UNUSED)
{
if (!reload_completed
&& TUNE_MACC_CHAINS
static int
mips_sched_reorder (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
- rtx *ready, int *nreadyp, int cycle ATTRIBUTE_UNUSED)
+ rtx_insn **ready, int *nreadyp, int cycle ATTRIBUTE_UNUSED)
{
mips_sched_reorder_1 (file, verbose, ready, nreadyp, cycle);
return mips_issue_rate ();
static int
mips_sched_reorder2 (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
- rtx *ready, int *nreadyp, int cycle ATTRIBUTE_UNUSED)
+ rtx_insn **ready, int *nreadyp, int cycle ATTRIBUTE_UNUSED)
{
mips_sched_reorder_1 (file, verbose, ready, nreadyp, cycle);
return cached_can_issue_more;
/* Update round-robin counters for ALU1/2 and FALU1/2. */
static void
-mips_ls2_variable_issue (rtx insn)
+mips_ls2_variable_issue (rtx_insn *insn)
{
if (mips_ls2.alu1_turn_p)
{
static int
mips_variable_issue (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
- rtx insn, int more)
+ rtx_insn *insn, int more)
{
/* Ignore USEs and CLOBBERs; don't count them against the issue rate. */
if (USEFUL_INSN_P (insn))
mips_builtin_branch_and_move (rtx condition, rtx target,
rtx value_if_true, rtx value_if_false)
{
- rtx true_label, done_label;
+ rtx_code_label *true_label, *done_label;
true_label = gen_label_rtx ();
done_label = gen_label_rtx ();
struct mips16_constant {
struct mips16_constant *next;
rtx value;
- rtx label;
+ rtx_code_label *label;
enum machine_mode mode;
};
/* Add constant VALUE to POOL and return its label. MODE is the
value's mode (used for CONST_INTs, etc.). */
-static rtx
+static rtx_code_label *
mips16_add_constant (struct mips16_constant_pool *pool,
rtx value, enum machine_mode mode)
{
/* Output constant VALUE after instruction INSN and return the last
instruction emitted. MODE is the mode of the constant. */
-static rtx
-mips16_emit_constants_1 (enum machine_mode mode, rtx value, rtx insn)
+static rtx_insn *
+mips16_emit_constants_1 (enum machine_mode mode, rtx value, rtx_insn *insn)
{
if (SCALAR_INT_MODE_P (mode) || ALL_SCALAR_FIXED_POINT_MODE_P (mode))
{
/* Dump out the constants in CONSTANTS after INSN. */
static void
-mips16_emit_constants (struct mips16_constant *constants, rtx insn)
+mips16_emit_constants (struct mips16_constant *constants, rtx_insn *insn)
{
struct mips16_constant *c, *next;
int align;
/* Return the length of instruction INSN. */
static int
-mips16_insn_length (rtx insn)
+mips16_insn_length (rtx_insn *insn)
{
if (JUMP_TABLE_DATA_P (insn))
{
static void
mips16_rewrite_pool_constant (struct mips16_constant_pool *pool, rtx *x)
{
- rtx base, offset, label;
+ rtx base, offset;
+ rtx_code_label *label;
split_const (*x, &base, &offset);
if (GET_CODE (base) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (base))
INSN is the instruction we're rewriting and POOL points to the current
constant pool. */
struct mips16_rewrite_pool_refs_info {
- rtx insn;
+ rtx_insn *insn;
struct mips16_constant_pool *pool;
};
{
struct mips16_constant_pool pool;
struct mips16_rewrite_pool_refs_info info;
- rtx insn, barrier;
+ rtx_insn *insn, *barrier;
if (!TARGET_MIPS16_PCREL_LOADS)
return;
do it immediately before INSN. */
if (barrier == 0 && pool.insn_address + 4 > pool.highest_address)
{
- rtx label, jump;
+ rtx_code_label *label;
+ rtx_insn *jump;
label = gen_label_rtx ();
virtual_incoming_args_rtx (which should never occur in X otherwise). */
static rtx
-r10k_simplify_address (rtx x, rtx insn)
+r10k_simplify_address (rtx x, rtx_insn *insn)
{
- rtx newx, op0, op1, set, def_insn, note;
+ rtx newx, op0, op1, set, note;
+ rtx_insn *def_insn;
df_ref use, def;
struct df_link *defs;
expression; it might not be a legitimate address. */
static bool
-r10k_safe_address_p (rtx x, rtx insn)
+r10k_safe_address_p (rtx x, rtx_insn *insn)
{
rtx base, offset;
HOST_WIDE_INT offset_val;
&& r10k_safe_mem_expr_p (MEM_EXPR (mem), MEM_OFFSET (mem)))
return -1;
- if (r10k_safe_address_p (XEXP (mem, 0), (rtx) data))
+ if (r10k_safe_address_p (XEXP (mem, 0), (rtx_insn *) data))
return -1;
return 1;
r10k_needs_protection_p_store (rtx x, const_rtx pat ATTRIBUTE_UNUSED,
void *data)
{
- rtx *insn_ptr;
+ rtx_insn **insn_ptr;
- insn_ptr = (rtx *) data;
+ insn_ptr = (rtx_insn **) data;
if (*insn_ptr && for_each_rtx (&x, r10k_needs_protection_p_1, *insn_ptr))
- *insn_ptr = NULL_RTX;
+ *insn_ptr = NULL;
}
/* A for_each_rtx callback that iterates over the pattern of a CALL_INSN.
cache barrier. */
static bool
-r10k_needs_protection_p (rtx insn)
+r10k_needs_protection_p (rtx_insn *insn)
{
if (CALL_P (insn))
return for_each_rtx (&PATTERN (insn), r10k_needs_protection_p_call, NULL);
unsigned int i, n;
basic_block bb;
sbitmap protected_bbs;
- rtx insn, end, unprotected_region;
+ rtx_insn *insn, *end;
+ rtx unprotected_region;
if (TARGET_MIPS16)
{
SECOND_CALL. */
static rtx
-mips_call_expr_from_insn (rtx insn, rtx *second_call)
+mips_call_expr_from_insn (rtx_insn *insn, rtx *second_call)
{
rtx x;
rtx x2;
static rtx
mips_pic_call_symbol_from_set (df_ref def, rtx reg, bool recurse_p)
{
- rtx def_insn, set;
+ rtx_insn *def_insn;
+ rtx set;
if (DF_REF_IS_ARTIFICIAL (def))
return NULL_RTX;
mips_pic_call_symbol_from_set. */
static rtx
-mips_find_pic_call_symbol (rtx insn, rtx reg, bool recurse_p)
+mips_find_pic_call_symbol (rtx_insn *insn, rtx reg, bool recurse_p)
{
df_ref use;
struct df_link *defs;
mips_annotate_pic_calls (void)
{
basic_block bb;
- rtx insn;
+ rtx_insn *insn;
FOR_EACH_BB_FN (bb, cfun)
FOR_BB_INSNS (bb, insn)
}
\f
/* A temporary variable used by for_each_rtx callbacks, etc. */
-static rtx mips_sim_insn;
+static rtx_insn *mips_sim_insn;
/* A structure representing the state of the processor pipeline.
Used by the mips_sim_* family of functions. */
LAST_SET[X].TIME is the time at which that instruction was issued.
INSN is null if no instruction has yet set register X. */
struct {
- rtx insn;
+ rtx_insn *insn;
unsigned int time;
} last_set[FIRST_PSEUDO_REGISTER];
register REG. */
static void
-mips_sim_wait_reg (struct mips_sim *state, rtx insn, rtx reg)
+mips_sim_wait_reg (struct mips_sim *state, rtx_insn *insn, rtx reg)
{
unsigned int regno, end_regno;
dependencies are satisfied. */
static void
-mips_sim_wait_regs (struct mips_sim *state, rtx insn)
+mips_sim_wait_regs (struct mips_sim *state, rtx_insn *insn)
{
mips_sim_insn = insn;
note_uses (&PATTERN (insn), mips_sim_wait_regs_1, state);
instruction INSN are available. */
static void
-mips_sim_wait_units (struct mips_sim *state, rtx insn)
+mips_sim_wait_units (struct mips_sim *state, rtx_insn *insn)
{
state_t tmp_state;
/* Advance simulation state STATE until INSN is ready to issue. */
static void
-mips_sim_wait_insn (struct mips_sim *state, rtx insn)
+mips_sim_wait_insn (struct mips_sim *state, rtx_insn *insn)
{
mips_sim_wait_regs (state, insn);
mips_sim_wait_units (state, insn);
been called). */
static void
-mips_sim_issue_insn (struct mips_sim *state, rtx insn)
+mips_sim_issue_insn (struct mips_sim *state, rtx_insn *insn)
{
curr_state = state->dfa_state;
SEQUENCE. */
static void
-mips_sim_finish_insn (struct mips_sim *state, rtx insn)
+mips_sim_finish_insn (struct mips_sim *state, rtx_insn *insn)
{
/* If INSN is a jump with an implicit delay slot, simulate a nop. */
if (JUMP_P (insn))
instruction sequence SEQ. */
static unsigned int
-mips_seq_time (struct mips_sim *state, rtx seq)
+mips_seq_time (struct mips_sim *state, rtx_insn *seq)
{
mips_sim_reset (state);
- for (rtx insn = seq; insn; insn = NEXT_INSN (insn))
+ for (rtx_insn *insn = seq; insn; insn = NEXT_INSN (insn))
{
mips_sim_wait_insn (state, insn);
mips_sim_issue_insn (state, insn);
try to avoid it by swapping rs and rt. */
static void
-vr4130_avoid_branch_rt_conflict (rtx insn)
+vr4130_avoid_branch_rt_conflict (rtx_insn *insn)
{
- rtx first, second;
+ rtx_insn *first, *second;
first = SEQ_BEGIN (insn);
second = SEQ_END (insn);
vr4130_align_insns (void)
{
struct mips_sim state;
- rtx insn, subinsn, last, last2, next;
+ rtx_insn *insn, *subinsn, *last, *last2, *next;
bool aligned_p;
dfa_start ();
return rtx_equal_p (entry->base, value);
}
-typedef hash_table <mips_lo_sum_offset_hasher> mips_offset_table;
+typedef hash_table<mips_lo_sum_offset_hasher> mips_offset_table;
/* Look up symbolic constant X in HTAB, which is a hash table of
mips_lo_sum_offsets. If OPTION is NO_INSERT, return true if X can be
paired with a recorded LO_SUM, otherwise record X in the table. */
static bool
-mips_lo_sum_offset_lookup (mips_offset_table htab, rtx x,
+mips_lo_sum_offset_lookup (mips_offset_table *htab, rtx x,
enum insert_option option)
{
rtx base, offset;
base = UNSPEC_ADDRESS (base);
/* Look up the base in the hash table. */
- slot = htab.find_slot_with_hash (base, mips_hash_base (base), option);
+ slot = htab->find_slot_with_hash (base, mips_hash_base (base), option);
if (slot == NULL)
return false;
mips_record_lo_sum (rtx *loc, void *data)
{
if (GET_CODE (*loc) == LO_SUM)
- mips_lo_sum_offset_lookup (*(mips_offset_table*) data,
+ mips_lo_sum_offset_lookup ((mips_offset_table*) data,
XEXP (*loc, 1), INSERT);
return 0;
}
LO_SUMs in the current function. */
static bool
-mips_orphaned_high_part_p (mips_offset_table htab, rtx insn)
+mips_orphaned_high_part_p (mips_offset_table *htab, rtx_insn *insn)
{
enum mips_symbol_type type;
rtx x, set;
LO_REG is an rtx for the LO register, used in dependence checking. */
static void
-mips_avoid_hazard (rtx after, rtx insn, int *hilo_delay,
+mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay,
rtx *delayed_reg, rtx lo_reg)
{
rtx pattern, set;
static void
mips_reorg_process_insns (void)
{
- rtx insn, last_insn, subinsn, next_insn, lo_reg, delayed_reg;
+ rtx_insn *insn, *last_insn, *subinsn, *next_insn;
+ rtx lo_reg, delayed_reg;
int hilo_delay;
- mips_offset_table htab;
/* Force all instructions to be split into their final form. */
split_all_insns_noflow ();
if (TARGET_FIX_VR4130 && !ISA_HAS_MACCHI)
cfun->machine->all_noreorder_p = false;
- htab.create (37);
+ mips_offset_table htab (37);
/* Make a first pass over the instructions, recording all the LO_SUMs. */
for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
FOR_EACH_SUBINSN (subinsn, insn)
if (INSN_P (subinsn))
{
- if (mips_orphaned_high_part_p (htab, subinsn))
+ if (mips_orphaned_high_part_p (&htab, subinsn))
{
PATTERN (subinsn) = gen_nop ();
INSN_CODE (subinsn) = CODE_FOR_nop;
{
/* INSN is a single instruction. Delete it if it's an
orphaned high-part relocation. */
- if (mips_orphaned_high_part_p (htab, insn))
+ if (mips_orphaned_high_part_p (&htab, insn))
delete_insn (insn);
/* Also delete cache barriers if the last instruction
was an annulled branch. INSN will not be speculatively
}
}
}
-
- htab.dispose ();
}
/* Return true if the function has a long branch instruction. */
static bool
mips_has_long_branch_p (void)
{
- rtx insn, subinsn;
+ rtx_insn *insn, *subinsn;
int normal_length;
/* We need up-to-date instruction lengths. */
/* Loop until the alignments for all targets are sufficient. */
do
{
- rtx insn;
+ rtx_insn *insn;
shorten_branches (get_insns ());
something_changed = false;
&& get_attr_length (insn) > 4
&& (any_condjump_p (insn) || any_uncondjump_p (insn)))
{
- rtx old_label, new_label, temp, saved_temp;
- rtx target, jump, jump_sequence;
+ rtx old_label, temp, saved_temp;
+ rtx_code_label *new_label;
+ rtx target;
+ rtx_insn *jump, *jump_sequence;
start_sequence ();
if (simplejump_p (insn))
/* We're going to replace INSN with a longer form. */
- new_label = NULL_RTX;
+ new_label = NULL;
else
{
/* Create a branch-around label for the original
RTL_PASS, /* type */
"mach2", /* name */
OPTGROUP_NONE, /* optinfo_flags */
- false, /* has_gate */
- true, /* has_execute */
TV_MACH_DEP, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_verify_rtl_sharing, /* todo_flags_finish */
+ 0, /* todo_flags_finish */
};
class pass_mips_machine_reorg2 : public rtl_opt_pass
{}
/* opt_pass methods: */
- unsigned int execute () { return mips_machine_reorg2 (); }
+ virtual unsigned int execute (function *) { return mips_machine_reorg2 (); }
}; // class pass_mips_machine_reorg2
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
- rtx this_rtx, temp1, temp2, insn, fnaddr;
+ rtx this_rtx, temp1, temp2, fnaddr;
+ rtx_insn *insn;
bool use_sibcall_p;
/* Pretend to be a post-reload pass while generating rtl. */
static struct machine_function *
mips_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
/* Return the processor associated with the given ISA level, or null
mips_arch_info = info;
mips_arch = info->cpu;
mips_isa = info->isa;
+ if (mips_isa < 32)
+ mips_isa_rev = 0;
+ else
+ mips_isa_rev = (mips_isa & 31) + 1;
}
}
}
}
-/* When generating MIPS16 code, we want to allocate $24 (T_REG) before
- other registers for instructions for which it is possible. This
- encourages the compiler to use CMP in cases where an XOR would
- require some register shuffling. */
-
-void
-mips_order_regs_for_local_alloc (void)
-{
- int i;
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- reg_alloc_order[i] = i;
-
- if (TARGET_MIPS16)
- {
- /* It really doesn't matter where we put register 0, since it is
- a fixed register anyhow. */
- reg_alloc_order[0] = 24;
- reg_alloc_order[24] = 0;
- }
-}
-
/* Implement EH_USES. */
bool
INSN has NOPERANDS operands, stored in OPVEC. */
static bool
-mips_need_noat_wrapper_p (rtx insn, rtx *opvec, int noperands)
+mips_need_noat_wrapper_p (rtx_insn *insn, rtx *opvec, int noperands)
{
int i;
/* Implement FINAL_PRESCAN_INSN. */
void
-mips_final_prescan_insn (rtx insn, rtx *opvec, int noperands)
+mips_final_prescan_insn (rtx_insn *insn, rtx *opvec, int noperands)
{
if (mips_need_noat_wrapper_p (insn, opvec, noperands))
mips_push_asm_switch (&mips_noat);
/* Implement TARGET_ASM_FINAL_POSTSCAN_INSN. */
static void
-mips_final_postscan_insn (FILE *file ATTRIBUTE_UNUSED, rtx insn,
+mips_final_postscan_insn (FILE *file ATTRIBUTE_UNUSED, rtx_insn *insn,
rtx *opvec, int noperands)
{
if (mips_need_noat_wrapper_p (insn, opvec, noperands))
const unsigned char *perm, unsigned nelt)
{
rtx rperm[MAX_VECT_LEN], x;
+ rtx_insn *insn;
unsigned i;
for (i = 0; i < nelt; ++i)
x = gen_rtx_VEC_SELECT (GET_MODE (target), op0, x);
x = gen_rtx_SET (VOIDmode, target, x);
- x = emit_insn (x);
- if (recog_memoized (x) < 0)
+ insn = emit_insn (x);
+ if (recog_memoized (insn) < 0)
{
- remove_insn (x);
+ remove_insn (insn);
return false;
}
return true;
*update = build2 (COMPOUND_EXPR, void_type_node, *update,
atomic_feraiseexcept_call);
}
+
+/* Implement TARGET_SPILL_CLASS. */
+
+static reg_class_t
+mips_spill_class (reg_class_t rclass ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ if (TARGET_MIPS16)
+ return SPILL_REGS;
+ return NO_REGS;
+}
+
+/* Implement TARGET_LRA_P. */
+
+static bool
+mips_lra_p (void)
+{
+ return mips_lra_flag;
+}
\f
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
#define TARGET_VALID_POINTER_MODE mips_valid_pointer_mode
#undef TARGET_REGISTER_MOVE_COST
#define TARGET_REGISTER_MOVE_COST mips_register_move_cost
+#undef TARGET_REGISTER_PRIORITY
+#define TARGET_REGISTER_PRIORITY mips_register_priority
#undef TARGET_MEMORY_MOVE_COST
#define TARGET_MEMORY_MOVE_COST mips_memory_move_cost
#undef TARGET_RTX_COSTS
#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV mips_atomic_assign_expand_fenv
+#undef TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS
+#define TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS true
+
+#undef TARGET_SPILL_CLASS
+#define TARGET_SPILL_CLASS mips_spill_class
+#undef TARGET_LRA_P
+#define TARGET_LRA_P mips_lra_p
+
struct gcc_target targetm = TARGET_INITIALIZER;
\f
#include "gt-mips.h"