/* Subroutines used for code generation on the Lattice Mico32 architecture.
Contributed by Jon Beniston <jon@beniston.com>
- Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2009-2020 Free Software Foundation, Inc.
This file is part of GCC.
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+#define IN_TARGET_CODE 1
+
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
+#include "backend.h"
+#include "target.h"
#include "rtl.h"
+#include "tree.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "df.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "optabs.h"
#include "regs.h"
-#include "hard-reg-set.h"
-#include "basic-block.h"
-#include "insn-config.h"
-#include "conditions.h"
-#include "insn-flags.h"
-#include "insn-attr.h"
-#include "insn-codes.h"
+#include "emit-rtl.h"
#include "recog.h"
#include "output.h"
-#include "tree.h"
+#include "calls.h"
+#include "alias.h"
+#include "explow.h"
#include "expr.h"
-#include "flags.h"
-#include "reload.h"
-#include "tm_p.h"
-#include "function.h"
-#include "diagnostic-core.h"
-#include "optabs.h"
-#include "libfuncs.h"
-#include "ggc.h"
-#include "target.h"
-#include "target-def.h"
-#include "langhooks.h"
#include "tm-constrs.h"
-#include "df.h"
+#include "builtins.h"
+
+/* This file should be included last. */
+#include "target-def.h"
struct lm32_frame_info
{
static void stack_adjust (HOST_WIDE_INT amount);
static bool lm32_in_small_data_p (const_tree);
static void lm32_setup_incoming_varargs (cumulative_args_t cum,
- enum machine_mode mode, tree type,
+ const function_arg_info &,
int *pretend_size, int no_rtl);
-static bool lm32_rtx_costs (rtx x, int code, int outer_code, int *total,
- bool speed);
+static bool lm32_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
+ int *total, bool speed);
static bool lm32_can_eliminate (const int, const int);
static bool
-lm32_legitimate_address_p (enum machine_mode mode, rtx x, bool strict);
+lm32_legitimate_address_p (machine_mode mode, rtx x, bool strict);
static HOST_WIDE_INT lm32_compute_frame_size (int size);
static void lm32_option_override (void);
-static rtx lm32_function_arg (cumulative_args_t cum,
- enum machine_mode mode, const_tree type,
- bool named);
+static rtx lm32_function_arg (cumulative_args_t, const function_arg_info &);
static void lm32_function_arg_advance (cumulative_args_t cum,
- enum machine_mode mode,
- const_tree type, bool named);
-static bool lm32_legitimate_constant_p (enum machine_mode, rtx);
+ const function_arg_info &);
+static bool lm32_hard_regno_mode_ok (unsigned int, machine_mode);
+static bool lm32_modes_tieable_p (machine_mode, machine_mode);
+static HOST_WIDE_INT lm32_starting_frame_offset (void);
#undef TARGET_OPTION_OVERRIDE
#define TARGET_OPTION_OVERRIDE lm32_option_override
#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_RTX_COSTS
#define TARGET_RTX_COSTS lm32_rtx_costs
#undef TARGET_IN_SMALL_DATA_P
#define TARGET_MAX_ANCHOR_OFFSET 0x7fff
#undef TARGET_CAN_ELIMINATE
#define TARGET_CAN_ELIMINATE lm32_can_eliminate
+#undef TARGET_LRA_P
+#define TARGET_LRA_P hook_bool_void_false
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P lm32_legitimate_address_p
-#undef TARGET_LEGITIMATE_CONSTANT_P
-#define TARGET_LEGITIMATE_CONSTANT_P lm32_legitimate_constant_p
+#undef TARGET_HARD_REGNO_MODE_OK
+#define TARGET_HARD_REGNO_MODE_OK lm32_hard_regno_mode_ok
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P lm32_modes_tieable_p
+
+#undef TARGET_CONSTANT_ALIGNMENT
+#define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
+
+#undef TARGET_STARTING_FRAME_OFFSET
+#define TARGET_STARTING_FRAME_OFFSET lm32_starting_frame_offset
struct gcc_target targetm = TARGET_INITIALIZER;
rtx cmp1,
rtx destination)
{
- enum machine_mode mode;
+ machine_mode mode;
int branch_p;
- rtx temp;
- rtx cond;
- rtx label;
mode = GET_MODE (cmp0);
if (mode == VOIDmode)
/* Generate conditional branch instruction. */
cond = gen_rtx_fmt_ee (code, mode, cmp0, cmp1);
label = gen_rtx_LABEL_REF (VOIDmode, destination);
- insn = gen_rtx_SET (VOIDmode, pc_rtx,
- gen_rtx_IF_THEN_ELSE (VOIDmode,
- cond, label, pc_rtx));
+ insn = gen_rtx_SET (pc_rtx, gen_rtx_IF_THEN_ELSE (VOIDmode,
+ cond, label, pc_rtx));
emit_jump_insn (insn);
}
else
and calculate size required to store them in the stack. */
for (regno = 1; regno < SP_REGNUM; regno++)
{
- if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
+ if (df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno))
{
reg_save_mask |= 1 << regno;
callee_size += UNITS_PER_WORD;
}
}
- if (df_regs_ever_live_p (RA_REGNUM) || !current_function_is_leaf
+ if (df_regs_ever_live_p (RA_REGNUM) || ! crtl->is_leaf
|| !optimize)
{
reg_save_mask |= 1 << RA_REGNUM;
else if (code == HIGH)
output_addr_const (file, XEXP (op, 0));
else if (code == MEM)
- output_address (XEXP (op, 0));
+ output_address (GET_MODE (op), XEXP (op, 0));
else if (letter == 'z' && GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
fprintf (file, "%s", reg_names[0]);
else if (GET_CODE (op) == CONST_DOUBLE)
break;
case MEM:
- output_address (XEXP (addr, 0));
+ output_address (VOIDmode, XEXP (addr, 0));
break;
case PLUS:
Value is zero to push the argument on the stack,
or a hard register in which to store the argument.
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
CUM is a variable of type CUMULATIVE_ARGS which gives info about
the preceding args and about the function being called.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis). */
+ ARG is a description of the argument. */
static rtx
-lm32_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
- const_tree type, bool named)
+lm32_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
- if (mode == VOIDmode)
+ if (arg.end_marker_p ())
/* Compute operand 2 of the call insn. */
return GEN_INT (0);
- if (targetm.calls.must_pass_in_stack (mode, type))
+ if (targetm.calls.must_pass_in_stack (arg))
return NULL_RTX;
- if (!named || (*cum + LM32_NUM_REGS2 (mode, type) > LM32_NUM_ARG_REGS))
+ if (!arg.named
+ || *cum + LM32_NUM_REGS2 (arg.mode, arg.type) > LM32_NUM_ARG_REGS)
return NULL_RTX;
- return gen_rtx_REG (mode, *cum + LM32_FIRST_ARG_REG);
+ return gen_rtx_REG (arg.mode, *cum + LM32_FIRST_ARG_REG);
}
static void
-lm32_function_arg_advance (cumulative_args_t cum, enum machine_mode mode,
- const_tree type, bool named ATTRIBUTE_UNUSED)
+lm32_function_arg_advance (cumulative_args_t cum,
+ const function_arg_info &arg)
{
- *get_cumulative_args (cum) += LM32_NUM_REGS2 (mode, type);
+ *get_cumulative_args (cum) += LM32_NUM_REGS2 (arg.mode, arg.type);
}
HOST_WIDE_INT
}
static void
-lm32_setup_incoming_varargs (cumulative_args_t cum_v, enum machine_mode mode,
- tree type, int *pretend_size, int no_rtl)
+lm32_setup_incoming_varargs (cumulative_args_t cum_v,
+ const function_arg_info &arg,
+ int *pretend_size, int no_rtl)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
int first_anon_arg;
registers, if any used in passing this named paramter in
order to determine which is the first registers used to pass
anonymous arguments. */
- int size;
-
- if (mode == BLKmode)
- size = int_size_in_bytes (type);
- else
- size = GET_MODE_SIZE (mode);
+ int size = arg.promoted_size_in_bytes ();
first_anon_arg =
*cum + LM32_FIRST_ARG_REG +
rtx regblock;
regblock = gen_rtx_MEM (BLKmode,
- plus_constant (arg_pointer_rtx,
+ plus_constant (Pmode, arg_pointer_rtx,
FIRST_PARM_OFFSET (0)));
move_block_from_reg (first_reg_offset, regblock, size);
if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
{
- const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
+ const char *section = DECL_SECTION_NAME (exp);
if (strcmp (section, ".sdata") == 0 || strcmp (section, ".sbss") == 0)
return true;
}
HOST_WIDE_INT offset, delta;
unsigned HOST_WIDE_INT bits;
int i;
- enum machine_mode mode;
+ machine_mode mode;
rtx *regs;
/* Work out how many bits to move at a time. */
break;
}
- mode = mode_for_size (bits, MODE_INT, 0);
+ mode = int_mode_for_size (bits, 0).require ();
delta = bits / BITS_PER_UNIT;
/* Allocate a buffer for the temporary registers. */
src = adjust_address (src, BLKmode, offset);
dest = adjust_address (dest, BLKmode, offset);
move_by_pieces (dest, src, length - offset,
- MIN (MEM_ALIGN (src), MEM_ALIGN (dest)), 0);
+ MIN (MEM_ALIGN (src), MEM_ALIGN (dest)), RETURN_BEGIN);
}
}
scanned. In either case, *TOTAL contains the cost result. */
static bool
-lm32_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed)
+lm32_rtx_costs (rtx x, machine_mode mode, int outer_code,
+ int opno ATTRIBUTE_UNUSED, int *total, bool speed)
{
- enum machine_mode mode = GET_MODE (x);
+ int code = GET_CODE (x);
bool small_mode;
const int arithmetic_latency = 1;
/* Implement TARGET_LEGITIMATE_ADDRESS_P. */
static bool
-lm32_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x, bool strict)
+lm32_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x, bool strict)
{
/* (rM) */
if (strict && REG_P (x) && STRICT_REG_OK_FOR_BASE_P (x))
/* Check a move is not memory to memory. */
bool
-lm32_move_ok (enum machine_mode mode, rtx operands[2]) {
+lm32_move_ok (machine_mode mode, rtx operands[2]) {
if (memory_operand (operands[0], mode))
return register_or_zero_operand (operands[1], mode);
return true;
}
-/* Implement TARGET_LEGITIMATE_CONSTANT_P. */
+/* Implement TARGET_HARD_REGNO_MODE_OK. */
static bool
-lm32_legitimate_constant_p (enum machine_mode mode, rtx x)
+lm32_hard_regno_mode_ok (unsigned int regno, machine_mode)
{
- /* 32-bit addresses require multiple instructions. */
- if (!flag_pic && reloc_operand (x, mode))
- return false;
-
- return true;
+ return G_REG_P (regno);
+}
+
+/* Implement TARGET_MODES_TIEABLE_P. */
+
+static bool
+lm32_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+ return (GET_MODE_CLASS (mode1) == MODE_INT
+ && GET_MODE_CLASS (mode2) == MODE_INT
+ && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD
+ && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD);
+}
+
+/* Implement TARGET_STARTING_FRAME_OFFSET. */
+
+static HOST_WIDE_INT
+lm32_starting_frame_offset (void)
+{
+ return UNITS_PER_WORD;
}