/* Subroutines used for code generation on the Renesas M32R cpu.
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 1996-2017 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-#include "tree.h"
+#include "backend.h"
+#include "target.h"
#include "rtl.h"
-#include "regs.h"
-#include "hard-reg-set.h"
+#include "tree.h"
+#include "df.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "stringpool.h"
#include "insn-config.h"
-#include "conditions.h"
+#include "emit-rtl.h"
+#include "recog.h"
+#include "diagnostic-core.h"
+#include "alias.h"
+#include "stor-layout.h"
+#include "varasm.h"
+#include "calls.h"
#include "output.h"
#include "insn-attr.h"
-#include "flags.h"
+#include "explow.h"
#include "expr.h"
-#include "function.h"
-#include "recog.h"
-#include "diagnostic-core.h"
-#include "toplev.h"
-#include "ggc.h"
-#include "integrate.h"
-#include "df.h"
-#include "tm_p.h"
-#include "target.h"
-#include "target-def.h"
#include "tm-constrs.h"
+#include "builtins.h"
+
+/* This file should be included last. */
+#include "target-def.h"
/* Array of valid operand punctuation characters. */
static char m32r_punct_chars[256];
-/* Selected code model. */
-enum m32r_model m32r_model = M32R_MODEL_DEFAULT;
-
-/* Selected SDA support. */
-enum m32r_sdata m32r_sdata = M32R_SDATA_DEFAULT;
-
/* Machine-specific symbol_ref flags. */
#define SYMBOL_FLAG_MODEL_SHIFT SYMBOL_FLAG_MACH_DEP_SHIFT
#define SYMBOL_REF_MODEL(X) \
#define LIT_NAME_P(NAME) ((NAME)[0] == '*' && (NAME)[1] == '.')
/* Forward declaration. */
-static bool m32r_handle_option (size_t, const char *, int);
static void m32r_option_override (void);
static void init_reg_tables (void);
static void block_move_call (rtx, rtx, rtx);
static int m32r_is_insn (rtx);
-static rtx m32r_legitimize_address (rtx, rtx, enum machine_mode);
-static bool m32r_mode_dependent_address_p (const_rtx);
+static bool m32r_legitimate_address_p (machine_mode, rtx, bool);
+static rtx m32r_legitimize_address (rtx, rtx, machine_mode);
+static bool m32r_mode_dependent_address_p (const_rtx, addr_space_t);
static tree m32r_handle_model_attribute (tree *, tree, tree, int, bool *);
static void m32r_print_operand (FILE *, rtx, int);
-static void m32r_print_operand_address (FILE *, rtx);
+static void m32r_print_operand_address (FILE *, machine_mode, rtx);
static bool m32r_print_operand_punct_valid_p (unsigned char code);
static void m32r_output_function_prologue (FILE *, HOST_WIDE_INT);
static void m32r_output_function_epilogue (FILE *, HOST_WIDE_INT);
static void m32r_file_start (void);
-static int m32r_adjust_priority (rtx, int);
+static int m32r_adjust_priority (rtx_insn *, int);
static int m32r_issue_rate (void);
static void m32r_encode_section_info (tree, rtx, int);
static bool m32r_in_small_data_p (const_tree);
static bool m32r_return_in_memory (const_tree, const_tree);
static rtx m32r_function_value (const_tree, const_tree, bool);
-static rtx m32r_libcall_value (enum machine_mode, const_rtx);
+static rtx m32r_libcall_value (machine_mode, const_rtx);
static bool m32r_function_value_regno_p (const unsigned int);
-static void m32r_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
+static void m32r_setup_incoming_varargs (cumulative_args_t, machine_mode,
tree, int *, int);
static void init_idents (void);
-static bool m32r_rtx_costs (rtx, int, int, int *, bool speed);
-static int m32r_memory_move_cost (enum machine_mode, reg_class_t, bool);
-static bool m32r_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
+static bool m32r_rtx_costs (rtx, machine_mode, int, int, int *, bool speed);
+static int m32r_memory_move_cost (machine_mode, reg_class_t, bool);
+static bool m32r_pass_by_reference (cumulative_args_t, machine_mode,
const_tree, bool);
-static int m32r_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
+static int m32r_arg_partial_bytes (cumulative_args_t, machine_mode,
tree, bool);
-static rtx m32r_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
+static rtx m32r_function_arg (cumulative_args_t, machine_mode,
const_tree, bool);
-static void m32r_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+static void m32r_function_arg_advance (cumulative_args_t, machine_mode,
const_tree, bool);
static bool m32r_can_eliminate (const int, const int);
+static void m32r_conditional_register_usage (void);
static void m32r_trampoline_init (rtx, tree, rtx);
+static bool m32r_legitimate_constant_p (machine_mode, rtx);
+static bool m32r_attribute_identifier (const_tree);
\f
/* M32R specific attributes. */
static const struct attribute_spec m32r_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
- { "interrupt", 0, 0, true, false, false, NULL },
- { "model", 1, 1, true, false, false, m32r_handle_model_attribute },
- { NULL, 0, 0, false, false, false, NULL }
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+ affects_type_identity } */
+ { "interrupt", 0, 0, true, false, false, NULL, false },
+ { "model", 1, 1, true, false, false, m32r_handle_model_attribute,
+ false },
+ { NULL, 0, 0, false, false, false, NULL, false }
};
-
-static const struct default_options m32r_option_optimization_table[] =
- {
- { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
- { OPT_LEVELS_1_PLUS, OPT_fregmove, NULL, 1 },
- { OPT_LEVELS_NONE, 0, NULL, 0 }
- };
\f
/* Initialize the GCC target structure. */
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE m32r_attribute_table
+#undef TARGET_ATTRIBUTE_TAKES_IDENTIFIER_P
+#define TARGET_ATTRIBUTE_TAKES_IDENTIFIER_P m32r_attribute_identifier
+#undef TARGET_LRA_P
+#define TARGET_LRA_P hook_bool_void_false
+
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P m32r_legitimate_address_p
#undef TARGET_LEGITIMIZE_ADDRESS
#define TARGET_LEGITIMIZE_ADDRESS m32r_legitimize_address
#undef TARGET_MODE_DEPENDENT_ADDRESS_P
#undef TARGET_SCHED_ISSUE_RATE
#define TARGET_SCHED_ISSUE_RATE m32r_issue_rate
-#undef TARGET_DEFAULT_TARGET_FLAGS
-#define TARGET_DEFAULT_TARGET_FLAGS TARGET_CPU_DEFAULT
-#undef TARGET_HANDLE_OPTION
-#define TARGET_HANDLE_OPTION m32r_handle_option
#undef TARGET_OPTION_OVERRIDE
#define TARGET_OPTION_OVERRIDE m32r_option_override
-#undef TARGET_OPTION_OPTIMIZATION_TABLE
-#define TARGET_OPTION_OPTIMIZATION_TABLE m32r_option_optimization_table
#undef TARGET_ENCODE_SECTION_INFO
#define TARGET_ENCODE_SECTION_INFO m32r_encode_section_info
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS m32r_rtx_costs
#undef TARGET_ADDRESS_COST
-#define TARGET_ADDRESS_COST hook_int_rtx_bool_0
+#define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
#undef TARGET_PROMOTE_PROTOTYPES
#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
#undef TARGET_CAN_ELIMINATE
#define TARGET_CAN_ELIMINATE m32r_can_eliminate
+#undef TARGET_CONDITIONAL_REGISTER_USAGE
+#define TARGET_CONDITIONAL_REGISTER_USAGE m32r_conditional_register_usage
+
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT m32r_trampoline_init
+#undef TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P m32r_legitimate_constant_p
+
struct gcc_target targetm = TARGET_INITIALIZER;
\f
-/* Implement TARGET_HANDLE_OPTION. */
-
-static bool
-m32r_handle_option (size_t code, const char *arg, int value)
-{
- switch (code)
- {
- case OPT_m32r:
- target_flags &= ~(MASK_M32R2 | MASK_M32RX);
- return true;
-
- case OPT_mmodel_:
- if (strcmp (arg, "small") == 0)
- m32r_model = M32R_MODEL_SMALL;
- else if (strcmp (arg, "medium") == 0)
- m32r_model = M32R_MODEL_MEDIUM;
- else if (strcmp (arg, "large") == 0)
- m32r_model = M32R_MODEL_LARGE;
- else
- return false;
- return true;
-
- case OPT_msdata_:
- if (strcmp (arg, "none") == 0)
- m32r_sdata = M32R_SDATA_NONE;
- else if (strcmp (arg, "sdata") == 0)
- m32r_sdata = M32R_SDATA_SDATA;
- else if (strcmp (arg, "use") == 0)
- m32r_sdata = M32R_SDATA_USE;
- else
- return false;
- return true;
-
- case OPT_mno_flush_func:
- m32r_cache_flush_func = NULL;
- return true;
-
- case OPT_mflush_trap_:
- return value <= 15;
-
- case OPT_mno_flush_trap:
- m32r_cache_flush_trap = -1;
- return true;
-
- default:
- return true;
- }
-}
-
/* Called by m32r_option_override to initialize various things. */
void
for (i = 0; i < NUM_MACHINE_MODES; i++)
{
- switch (GET_MODE_CLASS (i))
+ machine_mode m = (machine_mode) i;
+
+ switch (GET_MODE_CLASS (m))
{
case MODE_INT:
case MODE_PARTIAL_INT:
case MODE_COMPLEX_INT:
- if (GET_MODE_SIZE (i) <= 4)
+ if (GET_MODE_SIZE (m) <= 4)
m32r_mode_class[i] = 1 << (int) S_MODE;
- else if (GET_MODE_SIZE (i) == 8)
+ else if (GET_MODE_SIZE (m) == 8)
m32r_mode_class[i] = 1 << (int) D_MODE;
- else if (GET_MODE_SIZE (i) == 16)
+ else if (GET_MODE_SIZE (m) == 16)
m32r_mode_class[i] = 1 << (int) T_MODE;
- else if (GET_MODE_SIZE (i) == 32)
+ else if (GET_MODE_SIZE (m) == 32)
m32r_mode_class[i] = 1 << (int) O_MODE;
else
m32r_mode_class[i] = 0;
break;
case MODE_FLOAT:
case MODE_COMPLEX_FLOAT:
- if (GET_MODE_SIZE (i) <= 4)
+ if (GET_MODE_SIZE (m) <= 4)
m32r_mode_class[i] = 1 << (int) SF_MODE;
- else if (GET_MODE_SIZE (i) == 8)
+ else if (GET_MODE_SIZE (m) == 8)
m32r_mode_class[i] = 1 << (int) DF_MODE;
- else if (GET_MODE_SIZE (i) == 16)
+ else if (GET_MODE_SIZE (m) == 16)
m32r_mode_class[i] = 1 << (int) TF_MODE;
- else if (GET_MODE_SIZE (i) == 32)
+ else if (GET_MODE_SIZE (m) == 32)
m32r_mode_class[i] = 1 << (int) OF_MODE;
else
m32r_mode_class[i] = 0;
return NULL_TREE;
}
+
+static bool
+m32r_attribute_identifier (const_tree name)
+{
+ return strcmp (IDENTIFIER_POINTER (name), "model") == 0
+ || strcmp (IDENTIFIER_POINTER (name), "__model__") == 0;
+}
\f
/* Encode section information of DECL, which is either a VAR_DECL,
FUNCTION_DECL, STRING_CST, CONSTRUCTOR, or ???.
static bool
m32r_in_small_data_p (const_tree decl)
{
- const_tree section;
+ const char *section;
if (TREE_CODE (decl) != VAR_DECL)
return false;
section = DECL_SECTION_NAME (decl);
if (section)
{
- const char *const name = TREE_STRING_POINTER (section);
- if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0)
+ if (strcmp (section, ".sdata") == 0 || strcmp (section, ".sbss") == 0)
return true;
}
else
}
\f
int
-call_operand (rtx op, enum machine_mode mode)
+call_operand (rtx op, machine_mode mode)
{
if (!MEM_P (op))
return 0;
/* Return 1 if OP is a reference to an object in .sdata/.sbss. */
int
-small_data_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+small_data_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED)
{
if (! TARGET_SDATA_USE)
return 0;
/* Return 1 if OP is a symbol that can use 24-bit addressing. */
int
-addr24_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+addr24_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED)
{
rtx sym;
/* Return 1 if OP is a symbol that needs 32-bit addressing. */
int
-addr32_operand (rtx op, enum machine_mode mode)
+addr32_operand (rtx op, machine_mode mode)
{
rtx sym;
/* Return 1 if OP is a function that can be called with the `bl' insn. */
int
-call26_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+call26_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED)
{
if (flag_pic)
return 1;
/* Return 1 if OP is a DImode const we want to handle inline.
This must match the code in the movdi pattern.
- It is used by the 'G' CONST_DOUBLE_OK_FOR_LETTER. */
+ It is used by the 'G' constraint. */
int
easy_di_const (rtx op)
/* Return 1 if OP is a DFmode const we want to handle inline.
This must match the code in the movdf pattern.
- It is used by the 'H' CONST_DOUBLE_OK_FOR_LETTER. */
+ It is used by the 'H' constraint. */
int
easy_df_const (rtx op)
{
- REAL_VALUE_TYPE r;
long l[2];
- REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- REAL_VALUE_TO_TARGET_DOUBLE (r, l);
+ REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (op), l);
if (l[0] == 0 && l[1] == 0)
return 1;
if ((l[0] & 0xffff) == 0 && l[1] == 0)
This is used in insn length calcs. */
int
-memreg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+memreg_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED)
{
return MEM_P (op) && REG_P (XEXP (op, 0));
}
/* Return nonzero if TYPE must be passed by indirect reference. */
static bool
-m32r_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
- enum machine_mode mode, const_tree type,
+m32r_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
+ machine_mode mode, const_tree type,
bool named ATTRIBUTE_UNUSED)
{
int size;
bool
gen_cond_store (enum rtx_code code, rtx op0, rtx op1, rtx op2)
{
- enum machine_mode mode = GET_MODE (op0);
+ machine_mode mode = GET_MODE (op0);
gcc_assert (mode == SImode);
switch (code)
rtx
gen_split_move_double (rtx operands[])
{
- enum machine_mode mode = GET_MODE (operands[0]);
+ machine_mode mode = GET_MODE (operands[0]);
rtx dest = operands[0];
rtx src = operands[1];
rtx val;
subregs to make this code simpler. It is safe to call
alter_subreg any time after reload. */
if (GET_CODE (dest) == SUBREG)
- alter_subreg (&dest);
+ alter_subreg (&dest, true);
if (GET_CODE (src) == SUBREG)
- alter_subreg (&src);
+ alter_subreg (&src, true);
start_sequence ();
if (REG_P (dest))
/* We normally copy the low-numbered register first. However, if
the first register operand 0 is the same as the second register of
operand 1, we must copy in the opposite order. */
- emit_insn (gen_rtx_SET (VOIDmode,
- operand_subword (dest, reverse, TRUE, mode),
+ emit_insn (gen_rtx_SET (operand_subword (dest, reverse, TRUE, mode),
operand_subword (src, reverse, TRUE, mode)));
- emit_insn (gen_rtx_SET (VOIDmode,
- operand_subword (dest, !reverse, TRUE, mode),
+ emit_insn (gen_rtx_SET (operand_subword (dest, !reverse, TRUE, mode),
operand_subword (src, !reverse, TRUE, mode)));
}
{
rtx words[2];
split_double (src, &words[0], &words[1]);
- emit_insn (gen_rtx_SET (VOIDmode,
- operand_subword (dest, 0, TRUE, mode),
+ emit_insn (gen_rtx_SET (operand_subword (dest, 0, TRUE, mode),
words[0]));
- emit_insn (gen_rtx_SET (VOIDmode,
- operand_subword (dest, 1, TRUE, mode),
+ emit_insn (gen_rtx_SET (operand_subword (dest, 1, TRUE, mode),
words[1]));
}
{
/* If the high-address word is used in the address, we must load it
last. Otherwise, load it first. */
- int reverse
- = (refers_to_regno_p (dregno, dregno + 1, XEXP (src, 0), 0) != 0);
+ int reverse = refers_to_regno_p (dregno, XEXP (src, 0));
/* We used to optimize loads from single registers as
ld r1,r3+; ld r2,r3; addi r3,-4
which saves 2 bytes and doesn't force longword alignment. */
- emit_insn (gen_rtx_SET (VOIDmode,
- operand_subword (dest, reverse, TRUE, mode),
+ emit_insn (gen_rtx_SET (operand_subword (dest, reverse, TRUE, mode),
adjust_address (src, SImode,
reverse * UNITS_PER_WORD)));
- emit_insn (gen_rtx_SET (VOIDmode,
- operand_subword (dest, !reverse, TRUE, mode),
+ emit_insn (gen_rtx_SET (operand_subword (dest, !reverse, TRUE, mode),
adjust_address (src, SImode,
!reverse * UNITS_PER_WORD)));
}
which saves 2 bytes and doesn't force longword alignment. */
else if (MEM_P (dest) && REG_P (src))
{
- emit_insn (gen_rtx_SET (VOIDmode,
- adjust_address (dest, SImode, 0),
+ emit_insn (gen_rtx_SET (adjust_address (dest, SImode, 0),
operand_subword (src, 0, TRUE, mode)));
- emit_insn (gen_rtx_SET (VOIDmode,
- adjust_address (dest, SImode, UNITS_PER_WORD),
+ emit_insn (gen_rtx_SET (adjust_address (dest, SImode, UNITS_PER_WORD),
operand_subword (src, 1, TRUE, mode)));
}
\f
static int
-m32r_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+m32r_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
tree type, bool named ATTRIBUTE_UNUSED)
{
+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+
int words;
unsigned int size =
(((mode == BLKmode && type)
and the rest are pushed. */
static rtx
-m32r_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+m32r_function_arg (cumulative_args_t cum_v, machine_mode mode,
const_tree type ATTRIBUTE_UNUSED,
bool named ATTRIBUTE_UNUSED)
{
+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+
return (PASS_IN_REG_P (*cum, mode, type)
? gen_rtx_REG (mode, ROUND_ADVANCE_CUM (*cum, mode, type))
: NULL_RTX);
(TYPE is null for libcalls where that information may not be available.) */
static void
-m32r_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+m32r_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
const_tree type, bool named ATTRIBUTE_UNUSED)
{
+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+
*cum = (ROUND_ADVANCE_CUM (*cum, mode, type)
+ ROUND_ADVANCE_ARG (mode, type));
}
static bool
m32r_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
{
- return m32r_pass_by_reference (NULL, TYPE_MODE (type), type, false);
+ cumulative_args_t dummy = pack_cumulative_args (NULL);
+
+ return m32r_pass_by_reference (dummy, TYPE_MODE (type), type, false);
}
/* Worker function for TARGET_FUNCTION_VALUE. */
/* Worker function for TARGET_LIBCALL_VALUE. */
static rtx
-m32r_libcall_value (enum machine_mode mode,
+m32r_libcall_value (machine_mode mode,
const_rtx fun ATTRIBUTE_UNUSED)
{
return gen_rtx_REG (mode, 0);
and mode MODE, and we rely on this fact. */
static void
-m32r_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+m32r_setup_incoming_varargs (cumulative_args_t cum, machine_mode mode,
tree type, int *pretend_size, int no_rtl)
{
int first_anon_arg;
/* All BLKmode values are passed by reference. */
gcc_assert (mode != BLKmode);
- first_anon_arg = (ROUND_ADVANCE_CUM (*cum, mode, type)
+ first_anon_arg = (ROUND_ADVANCE_CUM (*get_cumulative_args (cum), mode, type)
+ ROUND_ADVANCE_ARG (mode, type));
if (first_anon_arg < M32R_MAX_PARM_REGS)
rtx regblock;
regblock = gen_frame_mem (BLKmode,
- plus_constant (arg_pointer_rtx,
+ plus_constant (Pmode, arg_pointer_rtx,
FIRST_PARM_OFFSET (0)));
set_mem_alias_set (regblock, get_varargs_alias_set ());
move_block_from_reg (first_reg_offset, regblock, size);
{
return (NONDEBUG_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) != USE
- && GET_CODE (PATTERN (insn)) != CLOBBER
- && GET_CODE (PATTERN (insn)) != ADDR_VEC);
+ && GET_CODE (PATTERN (insn)) != CLOBBER);
}
/* Increase the priority of long instructions so that the
short instructions are scheduled ahead of the long ones. */
static int
-m32r_adjust_priority (rtx insn, int priority)
+m32r_adjust_priority (rtx_insn *insn, int priority)
{
if (m32r_is_insn (insn)
&& get_attr_insn_size (insn) != INSN_SIZE_SHORT)
}
\f
/* Cost functions. */
-
-/* Implement TARGET_HANDLE_OPTION.
-
- Memory is 3 times as expensive as registers.
+/* Memory is 3 times as expensive as registers.
??? Is that the right way to look at it? */
static int
-m32r_memory_move_cost (enum machine_mode mode,
+m32r_memory_move_cost (machine_mode mode,
reg_class_t rclass ATTRIBUTE_UNUSED,
bool in ATTRIBUTE_UNUSED)
{
}
static bool
-m32r_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total,
+m32r_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
+ int outer_code ATTRIBUTE_UNUSED,
+ int opno ATTRIBUTE_UNUSED, int *total,
bool speed ATTRIBUTE_UNUSED)
{
+ int code = GET_CODE (x);
+
switch (code)
{
/* Small integers are as cheap as registers. 4 byte values can be
if (! current_frame_info.initialized)
m32r_compute_frame_size (get_frame_size ());
+ if (flag_stack_usage_info)
+ current_function_static_stack_size = current_frame_info.total_size;
+
gmask = current_frame_info.gmask;
/* These cases shouldn't happen. Catch them now. */
if (total_size == 0)
{
- rtx insn = get_last_insn ();
+ rtx_insn *insn = get_last_insn ();
/* If the last insn was a BARRIER, we don't have to write any code
because a jump (aka return) was put there. */
if (CONST_INT_P (offset))
{
if (INT16_P (INTVAL (offset)))
- return plus_constant (base, INTVAL (offset));
+ return plus_constant (Pmode, base, INTVAL (offset));
else
{
gcc_assert (! reload_in_progress && ! reload_completed);
static rtx
m32r_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED)
+ machine_mode mode ATTRIBUTE_UNUSED)
{
if (flag_pic)
return m32r_legitimize_pic_address (x, NULL_RTX);
/* Worker function for TARGET_MODE_DEPENDENT_ADDRESS_P. */
static bool
-m32r_mode_dependent_address_p (const_rtx addr)
+m32r_mode_dependent_address_p (const_rtx addr, addr_space_t as ATTRIBUTE_UNUSED)
{
if (GET_CODE (addr) == LO_SUM)
return true;
fputs (reg_names[REGNO (x)+1], file);
else if (MEM_P (x))
{
+ machine_mode mode = GET_MODE (x);
+
fprintf (file, "@(");
/* Handle possible auto-increment. Since it is pre-increment and
we have already done it, we can just use an offset of four. */
currently necessary, but keep it around. */
if (GET_CODE (XEXP (x, 0)) == PRE_INC
|| GET_CODE (XEXP (x, 0)) == PRE_DEC)
- output_address (plus_constant (XEXP (XEXP (x, 0), 0), 4));
+ output_address (mode, plus_constant (Pmode,
+ XEXP (XEXP (x, 0), 0), 4));
else
- output_address (plus_constant (XEXP (x, 0), 4));
+ output_address (mode, plus_constant (Pmode, XEXP (x, 0), 4));
fputc (')', file);
}
else
else
{
fputs ("@(", file);
- output_address (XEXP (x, 0));
+ output_address (GET_MODE (x), addr);
fputc (')', file);
}
break;
/* We handle SFmode constants here as output_addr_const doesn't. */
if (GET_MODE (x) == SFmode)
{
- REAL_VALUE_TYPE d;
long l;
- REAL_VALUE_FROM_CONST_DOUBLE (d, x);
- REAL_VALUE_TO_TARGET_SINGLE (d, l);
+ REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), l);
fprintf (file, "0x%08lx", l);
break;
}
- /* Fall through. Let output_addr_const deal with it. */
+ /* FALLTHRU */
+ /* Let output_addr_const deal with it. */
default :
output_addr_const (file, x);
/* Print a memory address as an operand to reference that memory location. */
static void
-m32r_print_operand_address (FILE * file, rtx addr)
+m32r_print_operand_address (FILE * file, machine_mode /*mode*/, rtx addr)
{
rtx base;
rtx index = 0;
fputs ("sda(", file);
else
fputs ("low(", file);
- output_addr_const (file, plus_constant (XEXP (base, 1), offset));
+ output_addr_const (file, plus_constant (Pmode, XEXP (base, 1),
+ offset));
fputs ("),", file);
fputs (reg_names[REGNO (XEXP (base, 0))], file);
}
/* If necessary, generate a loop to handle the bulk of the copy. */
if (bytes)
{
- rtx label = NULL_RTX;
+ rtx_code_label *label = NULL;
rtx final_src = NULL_RTX;
rtx at_a_time = GEN_INT (MAX_MOVE_BYTES);
rtx rounded_total = GEN_INT (bytes);
gen_int_mode (TRAMPOLINE_SIZE, SImode), SImode,
GEN_INT (3), SImode);
}
+
+/* True if X is a reg that can be used as a base reg. */
+
+static bool
+m32r_rtx_ok_for_base_p (const_rtx x, bool strict)
+{
+ if (! REG_P (x))
+ return false;
+
+ if (strict)
+ {
+ if (GPR_P (REGNO (x)))
+ return true;
+ }
+ else
+ {
+ if (GPR_P (REGNO (x))
+ || REGNO (x) == ARG_POINTER_REGNUM
+ || ! HARD_REGISTER_P (x))
+ return true;
+ }
+
+ return false;
+}
+
+static inline bool
+m32r_rtx_ok_for_offset_p (const_rtx x)
+{
+ return (CONST_INT_P (x) && INT16_P (INTVAL (x)));
+}
+
+static inline bool
+m32r_legitimate_offset_addres_p (machine_mode mode ATTRIBUTE_UNUSED,
+ const_rtx x, bool strict)
+{
+ if (GET_CODE (x) == PLUS
+ && m32r_rtx_ok_for_base_p (XEXP (x, 0), strict)
+ && m32r_rtx_ok_for_offset_p (XEXP (x, 1)))
+ return true;
+
+ return false;
+}
+
+/* For LO_SUM addresses, do not allow them if the MODE is > 1 word,
+ since more than one instruction will be required. */
+
+static inline bool
+m32r_legitimate_lo_sum_addres_p (machine_mode mode, const_rtx x,
+ bool strict)
+{
+ if (GET_CODE (x) == LO_SUM
+ && (mode != BLKmode && GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
+ && m32r_rtx_ok_for_base_p (XEXP (x, 0), strict)
+ && CONSTANT_P (XEXP (x, 1)))
+ return true;
+
+ return false;
+}
+
+/* Is this a load and increment operation. */
+
+static inline bool
+m32r_load_postinc_p (machine_mode mode, const_rtx x, bool strict)
+{
+ if ((mode == SImode || mode == SFmode)
+ && GET_CODE (x) == POST_INC
+ && REG_P (XEXP (x, 0))
+ && m32r_rtx_ok_for_base_p (XEXP (x, 0), strict))
+ return true;
+
+ return false;
+}
+
+/* Is this an increment/decrement and store operation. */
+
+static inline bool
+m32r_store_preinc_predec_p (machine_mode mode, const_rtx x, bool strict)
+{
+ if ((mode == SImode || mode == SFmode)
+ && (GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
+ && REG_P (XEXP (x, 0)) \
+ && m32r_rtx_ok_for_base_p (XEXP (x, 0), strict))
+ return true;
+
+ return false;
+}
+
+/* Implement TARGET_LEGITIMATE_ADDRESS_P. */
+
+static bool
+m32r_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+{
+ if (m32r_rtx_ok_for_base_p (x, strict)
+ || m32r_legitimate_offset_addres_p (mode, x, strict)
+ || m32r_legitimate_lo_sum_addres_p (mode, x, strict)
+ || m32r_load_postinc_p (mode, x, strict)
+ || m32r_store_preinc_predec_p (mode, x, strict))
+ return true;
+
+ return false;
+}
+
+static void
+m32r_conditional_register_usage (void)
+{
+ if (flag_pic)
+ {
+ fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
+ call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
+ }
+}
+
+/* Implement TARGET_LEGITIMATE_CONSTANT_P
+
+ We don't allow (plus symbol large-constant) as the relocations can't
+ describe it. INTVAL > 32767 handles both 16-bit and 24-bit relocations.
+ We allow all CONST_DOUBLE's as the md file patterns will force the
+ constant to memory if they can't handle them. */
+
+static bool
+m32r_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+ return !(GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+ || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
+ && CONST_INT_P (XEXP (XEXP (x, 0), 1))
+ && UINTVAL (XEXP (XEXP (x, 0), 1)) > 32767);
+}