/* Definitions of target machine for GNU compiler, for MMIX.
- Copyright (C) 2000-2015 Free Software Foundation, Inc.
+ Copyright (C) 2000-2019 Free Software Foundation, Inc.
Contributed by Hans-Peter Nilsson (hp@bitrange.com)
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 "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 "insn-config.h"
+#include "optabs.h"
#include "regs.h"
#include "emit-rtl.h"
#include "recog.h"
/* We have no means to tell DWARF 2 about the register stack, so we need
to store the return address on the stack if an exception can get into
- this function. FIXME: Narrow condition. Before any whole-function
- analysis, df_regs_ever_live_p () isn't initialized. We know it's up-to-date
- after reload_completed; it may contain incorrect information some time
- before that. Within a RTL sequence (after a call to start_sequence,
- such as in RTL expanders), leaf_function_p doesn't see all insns
- (perhaps any insn). But regs_ever_live is up-to-date when
- leaf_function_p () isn't, so we "or" them together to get accurate
- information. FIXME: Some tweak to leaf_function_p might be
- preferable. */
+ this function. We'll have an "initial value" recorded for the
+ return-register if we've seen a call instruction emitted. This note
+ will be inaccurate before instructions are emitted, but the only caller
+ at that time is looking for modulo from stack-boundary, to which the
+ return-address does not contribute, and which is always 0 for MMIX
+ anyway. Beware of calling leaf_function_p here, as it'll abort if
+ called within a sequence. */
#define MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS \
(flag_exceptions \
- && ((reload_completed && df_regs_ever_live_p (MMIX_rJ_REGNUM)) \
- || !leaf_function_p ()))
+ && has_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM))
#define IS_MMIX_EH_RETURN_DATA_REG(REGNO) \
(crtl->calls_eh_return \
static void mmix_encode_section_info (tree, rtx, int);
static const char *mmix_strip_name_encoding (const char *);
static void mmix_emit_sp_add (HOST_WIDE_INT offset);
-static void mmix_target_asm_function_prologue (FILE *, HOST_WIDE_INT);
+static void mmix_target_asm_function_prologue (FILE *);
static void mmix_target_asm_function_end_prologue (FILE *);
-static void mmix_target_asm_function_epilogue (FILE *, HOST_WIDE_INT);
+static void mmix_target_asm_function_epilogue (FILE *);
static reg_class_t mmix_preferred_reload_class (rtx, reg_class_t);
static reg_class_t mmix_preferred_output_reload_class (rtx, reg_class_t);
static bool mmix_legitimate_address_p (machine_mode, rtx, bool);
(cumulative_args_t, machine_mode, tree, int *, int);
static void mmix_file_start (void);
static void mmix_file_end (void);
+static void mmix_init_libfuncs (void);
static bool mmix_rtx_costs (rtx, machine_mode, int, int, int *, bool);
static int mmix_register_move_cost (machine_mode,
reg_class_t, reg_class_t);
static void mmix_print_operand_address (FILE *, machine_mode, rtx);
static bool mmix_print_operand_punct_valid_p (unsigned char);
static void mmix_conditional_register_usage (void);
+static HOST_WIDE_INT mmix_static_rtx_alignment (machine_mode);
+static HOST_WIDE_INT mmix_constant_alignment (const_tree, HOST_WIDE_INT);
+static HOST_WIDE_INT mmix_starting_frame_offset (void);
/* Target structure macros. Listed by node. See `Using and Porting GCC'
for a general description. */
#undef TARGET_ASM_OUTPUT_SOURCE_FILENAME
#define TARGET_ASM_OUTPUT_SOURCE_FILENAME mmix_asm_output_source_filename
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS mmix_init_libfuncs
+
#undef TARGET_CONDITIONAL_REGISTER_USAGE
#define TARGET_CONDITIONAL_REGISTER_USAGE mmix_conditional_register_usage
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS mmix_rtx_costs
#undef TARGET_ADDRESS_COST
#undef TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
#define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS mmix_preferred_output_reload_class
+#undef TARGET_LRA_P
+#define TARGET_LRA_P hook_bool_void_false
+
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P mmix_legitimate_address_p
#undef TARGET_LEGITIMATE_CONSTANT_P
#undef TARGET_OPTION_OVERRIDE
#define TARGET_OPTION_OVERRIDE mmix_option_override
+#undef TARGET_STATIC_RTX_ALIGNMENT
+#define TARGET_STATIC_RTX_ALIGNMENT mmix_static_rtx_alignment
+#undef TARGET_CONSTANT_ALIGNMENT
+#define TARGET_CONSTANT_ALIGNMENT mmix_constant_alignment
+
+#undef TARGET_STARTING_FRAME_OFFSET
+#define TARGET_STARTING_FRAME_OFFSET mmix_starting_frame_offset
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Functions that are expansions for target macros.
labels. */
if (flag_pic)
{
- warning (0, "-f%s not supported: ignored", (flag_pic > 1) ? "PIC" : "pic");
+ warning (0, "%<-f%s%> not supported: ignored",
+ (flag_pic > 1) ? "PIC" : "pic");
flag_pic = 0;
}
}
return basic_align;
}
-/* CONSTANT_ALIGNMENT. */
+/* Implement TARGET_STATIC_RTX_ALIGNMENT. */
-int
-mmix_constant_alignment (tree constant ATTRIBUTE_UNUSED, int basic_align)
+static HOST_WIDE_INT
+mmix_static_rtx_alignment (machine_mode mode)
+{
+ return MAX (GET_MODE_ALIGNMENT (mode), 32);
+}
+
+/* Implement tARGET_CONSTANT_ALIGNMENT. */
+
+static HOST_WIDE_INT
+mmix_constant_alignment (const_tree, HOST_WIDE_INT basic_align)
{
if (basic_align < 32)
return 32;
return plus_constant (Pmode, frame, -8);
}
-/* STARTING_FRAME_OFFSET. */
+/* Implement TARGET_STARTING_FRAME_OFFSET. */
-int
+static HOST_WIDE_INT
mmix_starting_frame_offset (void)
{
/* The old frame pointer is in the slot below the new one, so
counted; the others go on the register stack.
The frame-pointer is counted too if it is what is eliminated, as we
- need to balance the offset for it from STARTING_FRAME_OFFSET.
+ need to balance the offset for it from TARGET_STARTING_FRAME_OFFSET.
Also add in the slot for the register stack pointer we save if we
have a landing pad.
mmix_reorg. */
static void
-mmix_target_asm_function_prologue (FILE *stream ATTRIBUTE_UNUSED,
- HOST_WIDE_INT framesize ATTRIBUTE_UNUSED)
+mmix_target_asm_function_prologue (FILE *)
{
cfun->machine->in_prologue = 1;
}
/* TARGET_ASM_FUNCTION_EPILOGUE. */
static void
-mmix_target_asm_function_epilogue (FILE *stream,
- HOST_WIDE_INT locals_size ATTRIBUTE_UNUSED)
+mmix_target_asm_function_epilogue (FILE *stream)
{
/* Emit an \n for readability of the generated assembly. */
fputc ('\n', stream);
fprintf (stream, "\n");
}
+/* Unfortunately, by default __builtin_ffs is expanded to ffs for
+ targets where INT_TYPE_SIZE < BITS_PER_WORD. That together with
+ newlib since 2017-07-04 implementing ffs as __builtin_ffs leads to
+ (newlib) ffs recursively calling itself. But, because of argument
+ promotion, and with ffs we're counting from the least bit, the
+ libgcc equivalent for ffsl works equally well for int arguments, so
+ just use that. */
+
+static void
+mmix_init_libfuncs (void)
+{
+ set_optab_libfunc (ffs_optab, SImode, "__ffsdi2");
+}
+
/* OUTPUT_QUOTED_STRING. */
void
case 1:
if (GET_CODE (x) != CONST_INT)
{
- aligned_p = 0;
- break;
+ /* There is no "unaligned byte" op or generic function to
+ which we can punt, so we have to handle this here. As
+ the expression isn't a plain literal, the generated
+ assembly-code can't be mmixal-equivalent (i.e. "BYTE"
+ won't work) and thus it's ok to emit the default op
+ ".byte". */
+ assemble_integer_with_op ("\t.byte\t", x);
+ return true;
}
fputs ("\tBYTE\t", asm_out_file);
mmix_print_operand (asm_out_file, x, 'B');
if (TARGET_BRANCH_PREDICT)
{
x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
- if (x && XINT (x, 0) > REG_BR_PROB_BASE / 2)
+ if (x && profile_probability::from_reg_br_prob_note (XINT (x, 0))
+ > profile_probability::even ())
putc ('P', stream);
}
return;
#undef CCEND
static const struct cc_type_conv cc_convs[]
- = {{CC_FUNmode, cc_fun_convs},
- {CC_FPmode, cc_fp_convs},
- {CC_FPEQmode, cc_fpeq_convs},
- {CC_UNSmode, cc_uns_convs},
- {CCmode, cc_signed_convs},
- {DImode, cc_di_convs}};
+ = {{E_CC_FUNmode, cc_fun_convs},
+ {E_CC_FPmode, cc_fp_convs},
+ {E_CC_FPEQmode, cc_fpeq_convs},
+ {E_CC_UNSmode, cc_uns_convs},
+ {E_CCmode, cc_signed_convs},
+ {E_DImode, cc_di_convs}};
size_t i;
int j;