/* Definitions of target machine for GNU compiler, for MMIX.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
- 2010, 2011
- 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 "tm.h"
+#include "backend.h"
+#include "target.h"
#include "rtl.h"
-#include "regs.h"
-#include "hard-reg-set.h"
-#include "hashtab.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"
+#include "diagnostic-core.h"
#include "output.h"
-#include "basic-block.h"
-#include "flags.h"
-#include "tree.h"
-#include "function.h"
+#include "varasm.h"
+#include "stor-layout.h"
+#include "calls.h"
+#include "explow.h"
#include "expr.h"
-#include "diagnostic-core.h"
-#include "recog.h"
-#include "ggc.h"
#include "dwarf2.h"
-#include "debug.h"
-#include "tm_p.h"
-#include "integrate.h"
-#include "target.h"
+#include "tm-constrs.h"
+#include "builtins.h"
+
+/* This file should be included last. */
#include "target-def.h"
-#include "df.h"
/* First some local helper definitions. */
#define MMIX_FIRST_GLOBAL_REGNUM 32
/* 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_option_override (void);
static void mmix_asm_output_source_filename (FILE *, const char *);
static void mmix_output_shiftvalue_op_from_str
- (FILE *, const char *, HOST_WIDEST_INT);
-static void mmix_output_shifted_value (FILE *, HOST_WIDEST_INT);
+ (FILE *, const char *, int64_t);
+static void mmix_output_shifted_value (FILE *, int64_t);
static void mmix_output_condition (FILE *, const_rtx, int);
-static HOST_WIDEST_INT mmix_intval (const_rtx);
-static void mmix_output_octa (FILE *, HOST_WIDEST_INT, int);
+static void mmix_output_octa (FILE *, int64_t, int);
static bool mmix_assemble_integer (rtx, unsigned int, int);
static struct machine_function *mmix_init_machine_status (void);
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 (enum machine_mode, rtx, bool);
-static bool mmix_legitimate_constant_p (enum machine_mode, rtx);
+static bool mmix_legitimate_address_p (machine_mode, rtx, bool);
+static bool mmix_legitimate_constant_p (machine_mode, rtx);
static void mmix_reorg (void);
static void mmix_asm_output_mi_thunk
(FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree);
static void mmix_setup_incoming_varargs
- (cumulative_args_t, enum machine_mode, tree, int *, int);
+ (cumulative_args_t, machine_mode, tree, int *, int);
static void mmix_file_start (void);
static void mmix_file_end (void);
-static bool mmix_rtx_costs (rtx, int, int, int *, bool);
-static int mmix_register_move_cost (enum machine_mode,
+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 rtx mmix_struct_value_rtx (tree, int);
-static enum machine_mode mmix_promote_function_mode (const_tree,
- enum machine_mode,
+static machine_mode mmix_promote_function_mode (const_tree,
+ machine_mode,
int *, const_tree, int);
-static void mmix_function_arg_advance (cumulative_args_t, enum machine_mode,
+static void mmix_function_arg_advance (cumulative_args_t, machine_mode,
const_tree, bool);
-static rtx mmix_function_arg_1 (const cumulative_args_t, enum machine_mode,
+static rtx mmix_function_arg_1 (const cumulative_args_t, machine_mode,
const_tree, bool, bool);
-static rtx mmix_function_incoming_arg (cumulative_args_t, enum machine_mode,
+static rtx mmix_function_incoming_arg (cumulative_args_t, machine_mode,
const_tree, bool);
-static rtx mmix_function_arg (cumulative_args_t, enum machine_mode,
+static rtx mmix_function_arg (cumulative_args_t, machine_mode,
const_tree, bool);
static rtx mmix_function_value (const_tree, const_tree, bool);
-static rtx mmix_libcall_value (enum machine_mode, const_rtx);
+static rtx mmix_libcall_value (machine_mode, const_rtx);
static bool mmix_function_value_regno_p (const unsigned int);
static bool mmix_pass_by_reference (cumulative_args_t,
- enum machine_mode, const_tree, bool);
+ machine_mode, const_tree, bool);
static bool mmix_frame_pointer_required (void);
static void mmix_asm_trampoline_template (FILE *);
static void mmix_trampoline_init (rtx, tree, rtx);
static void mmix_print_operand (FILE *, rtx, int);
-static void mmix_print_operand_address (FILE *, rtx);
+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
-#define TARGET_ADDRESS_COST hook_int_rtx_bool_0
+#define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
#undef TARGET_REGISTER_MOVE_COST
#define TARGET_REGISTER_MOVE_COST mmix_register_move_cost
#undef TARGET_PREFERRED_RELOAD_CLASS
#define TARGET_PREFERRED_RELOAD_CLASS mmix_preferred_reload_class
#undef TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
-#define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS mmix_preferred_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_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;
}
}
static struct machine_function *
mmix_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
-/* DATA_ALIGNMENT.
+/* DATA_ABI_ALIGNMENT.
We have trouble getting the address of stuff that is located at other
than 32-bit alignments (GETA requirements), so try to give everything
at least 32-bit alignment. */
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;
/* INCOMING_REGNO and OUTGOING_REGNO worker function.
Those two macros must only be applied to function argument
- registers. FIXME: for their current use in gcc, it'd be better
- with an explicit specific additional FUNCTION_INCOMING_ARG_REGNO_P
- a'la TARGET_FUNCTION_ARG / TARGET_FUNCTION_INCOMING_ARG instead of
+ registers and the function return value register for the opposite
+ use. FIXME: for their current use in gcc, it'd be better with an
+ explicit specific additional FUNCTION_INCOMING_ARG_REGNO_P a'la
+ TARGET_FUNCTION_ARG / TARGET_FUNCTION_INCOMING_ARG instead of
forcing the target to commit to a fixed mapping and for any
- unspecified register use. */
+ unspecified register use. Particularly when thinking about the
+ return-value, it is better to imagine INCOMING_REGNO and
+ OUTGOING_REGNO as named CALLEE_TO_CALLER_REGNO and INNER_REGNO as
+ named CALLER_TO_CALLEE_REGNO because the direction. The "incoming"
+ and "outgoing" is from the perspective of the parameter-registers,
+ but the same macro is (must be, lacking an alternative like
+ suggested above) used to map the return-value-register from the
+ same perspective. To make directions even more confusing, the macro
+ MMIX_OUTGOING_RETURN_VALUE_REGNUM holds the number of the register
+ in which to return a value, i.e. INCOMING_REGNO for the return-value-
+ register as received from a called function; the return-value on the
+ way out. */
int
mmix_opposite_regno (int regno, int incoming)
{
+ if (incoming && regno == MMIX_OUTGOING_RETURN_VALUE_REGNUM)
+ return MMIX_RETURN_VALUE_REGNUM;
+
+ if (!incoming && regno == MMIX_RETURN_VALUE_REGNUM)
+ return MMIX_OUTGOING_RETURN_VALUE_REGNUM;
+
if (!mmix_function_arg_regno_p (regno, incoming))
return regno;
enum reg_class
mmix_secondary_reload_class (enum reg_class rclass,
- enum machine_mode mode ATTRIBUTE_UNUSED,
+ machine_mode mode ATTRIBUTE_UNUSED,
rtx x ATTRIBUTE_UNUSED,
int in_p ATTRIBUTE_UNUSED)
{
return NO_REGS;
}
-/* CONST_OK_FOR_LETTER_P. */
-
-int
-mmix_const_ok_for_letter_p (HOST_WIDE_INT value, int c)
-{
- return
- (c == 'I' ? value >= 0 && value <= 255
- : c == 'J' ? value >= 0 && value <= 65535
- : c == 'K' ? value <= 0 && value >= -255
- : c == 'L' ? mmix_shiftable_wyde_value (value)
- : c == 'M' ? value == 0
- : c == 'N' ? mmix_shiftable_wyde_value (~value)
- : c == 'O' ? (value == 3 || value == 5 || value == 9
- || value == 17)
- : 0);
-}
-
-/* CONST_DOUBLE_OK_FOR_LETTER_P. */
-
-int
-mmix_const_double_ok_for_letter_p (rtx value, int c)
-{
- return
- (c == 'G' ? value == CONST0_RTX (GET_MODE (value))
- : 0);
-}
-
-/* EXTRA_CONSTRAINT.
- We need this since our constants are not always expressible as
- CONST_INT:s, but rather often as CONST_DOUBLE:s. */
-
-int
-mmix_extra_constraint (rtx x, int c, int strict)
-{
- HOST_WIDEST_INT value;
-
- /* When checking for an address, we need to handle strict vs. non-strict
- register checks. Don't use address_operand, but instead its
- equivalent (its callee, which it is just a wrapper for),
- memory_operand_p and the strict-equivalent strict_memory_address_p. */
- if (c == 'U')
- return
- strict
- ? strict_memory_address_p (Pmode, x)
- : memory_address_p (Pmode, x);
-
- /* R asks whether x is to be loaded with GETA or something else. Right
- now, only a SYMBOL_REF and LABEL_REF can fit for
- TARGET_BASE_ADDRESSES.
-
- Only constant symbolic addresses apply. With TARGET_BASE_ADDRESSES,
- we just allow straight LABEL_REF or SYMBOL_REFs with SYMBOL_REF_FLAG
- set right now; only function addresses and code labels. If we change
- to let SYMBOL_REF_FLAG be set on other symbols, we have to check
- inside CONST expressions. When TARGET_BASE_ADDRESSES is not in
- effect, a "raw" constant check together with mmix_constant_address_p
- is all that's needed; we want all constant addresses to be loaded
- with GETA then. */
- if (c == 'R')
- return
- GET_CODE (x) != CONST_INT && GET_CODE (x) != CONST_DOUBLE
- && mmix_constant_address_p (x)
- && (! TARGET_BASE_ADDRESSES
- || (GET_CODE (x) == LABEL_REF
- || (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FLAG (x))));
-
- if (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != VOIDmode)
- return 0;
-
- value = mmix_intval (x);
-
- /* We used to map Q->J, R->K, S->L, T->N, U->O, but we don't have to any
- more ('U' taken for address_operand, 'R' similarly). Some letters map
- outside of CONST_INT, though; we still use 'S' and 'T'. */
- if (c == 'S')
- return mmix_shiftable_wyde_value (value);
- else if (c == 'T')
- return mmix_shiftable_wyde_value (~value);
- return 0;
-}
-
/* DYNAMIC_CHAIN_ADDRESS. */
rtx
frame-pointer. Unfortunately, the caller assumes that a
frame-pointer is present for *all* previous frames. There should be
a way to say that that cannot be done, like for RETURN_ADDR_RTX. */
- return plus_constant (frame, -8);
+ 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
See mmix_initial_elimination_offset for the reason we can't use
get_hard_reg_initial_val for both. Always using a stack slot
and not a register would be suboptimal. */
- ? validize_mem (gen_rtx_MEM (Pmode, plus_constant (frame_pointer_rtx, -16)))
+ ? validize_mem (gen_rtx_MEM (Pmode,
+ plus_constant (Pmode,
+ frame_pointer_rtx, -16)))
: get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM))
: NULL_RTX;
}
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.
}
static void
-mmix_function_arg_advance (cumulative_args_t argsp_v, enum machine_mode mode,
+mmix_function_arg_advance (cumulative_args_t argsp_v, machine_mode mode,
const_tree type, bool named ATTRIBUTE_UNUSED)
{
CUMULATIVE_ARGS *argsp = get_cumulative_args (argsp_v);
static rtx
mmix_function_arg_1 (const cumulative_args_t argsp_v,
- enum machine_mode mode,
+ machine_mode mode,
const_tree type,
bool named ATTRIBUTE_UNUSED,
bool incoming)
static rtx
mmix_function_arg (cumulative_args_t argsp,
- enum machine_mode mode,
+ machine_mode mode,
const_tree type,
bool named)
{
static rtx
mmix_function_incoming_arg (cumulative_args_t argsp,
- enum machine_mode mode,
+ machine_mode mode,
const_tree type,
bool named)
{
everything that goes by value. */
static bool
-mmix_pass_by_reference (cumulative_args_t argsp_v, enum machine_mode mode,
+mmix_pass_by_reference (cumulative_args_t argsp_v, machine_mode mode,
const_tree type, bool named ATTRIBUTE_UNUSED)
{
CUMULATIVE_ARGS *argsp = get_cumulative_args (argsp_v);
const_tree func ATTRIBUTE_UNUSED,
bool outgoing)
{
- enum machine_mode mode = TYPE_MODE (valtype);
- enum machine_mode cmode;
+ machine_mode mode = TYPE_MODE (valtype);
+ machine_mode cmode;
int first_val_regnum = MMIX_OUTGOING_RETURN_VALUE_REGNUM;
rtx vec[MMIX_MAX_REGS_FOR_VALUE];
int i;
gen_rtx_REG (cmode, first_val_regnum + nregs - 1),
const0_rtx);
- return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nregs, vec));
+ return gen_rtx_PARALLEL (mode, gen_rtvec_v (nregs, vec));
}
/* Implements TARGET_LIBCALL_VALUE. */
static rtx
-mmix_libcall_value (enum machine_mode mode,
+mmix_libcall_value (machine_mode mode,
const_rtx fun ATTRIBUTE_UNUSED)
{
return gen_rtx_REG (mode, MMIX_RETURN_VALUE_REGNUM);
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);
static void
mmix_setup_incoming_varargs (cumulative_args_t args_so_farp_v,
- enum machine_mode mode,
+ machine_mode mode,
tree vartype,
int *pretend_sizep,
int second_time ATTRIBUTE_UNUSED)
/* Return 1 if the address is OK, otherwise 0. */
bool
-mmix_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+mmix_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
rtx x,
bool strict_checking)
{
return 1;
/* (mem (plus (reg) (0..255?))) */
- if (GET_CODE (x2) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (x2), 'I'))
+ if (satisfies_constraint_I (x2))
return 1;
return 0;
/* Implement TARGET_LEGITIMATE_CONSTANT_P. */
static bool
-mmix_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+mmix_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
{
RTX_CODE code = GET_CODE (x);
/* SELECT_CC_MODE. */
-enum machine_mode
+machine_mode
mmix_select_cc_mode (RTX_CODE op, rtx x, rtx y ATTRIBUTE_UNUSED)
{
/* We use CCmode, CC_UNSmode, CC_FPmode, CC_FPEQmode and CC_FUNmode to
/* REVERSIBLE_CC_MODE. */
int
-mmix_reversible_cc_mode (enum machine_mode mode)
+mmix_reversible_cc_mode (machine_mode mode)
{
/* That is, all integer and the EQ, NE, ORDERED and UNORDERED float
compares. */
static bool
mmix_rtx_costs (rtx x ATTRIBUTE_UNUSED,
- int code ATTRIBUTE_UNUSED,
+ machine_mode mode ATTRIBUTE_UNUSED,
int outer_code ATTRIBUTE_UNUSED,
+ int opno ATTRIBUTE_UNUSED,
int *total ATTRIBUTE_UNUSED,
bool speed ATTRIBUTE_UNUSED)
{
need to check that their constraints match, so say 3 for them. */
static int
-mmix_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+mmix_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
reg_class_t from,
reg_class_t to)
{
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 && INTVAL (XEXP (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;
output. */
case 'A':
mmix_output_shiftvalue_op_from_str (stream, "ANDN",
- ~(unsigned HOST_WIDEST_INT)
+ ~(uint64_t)
mmix_intval (x));
return;
case 'i':
mmix_output_shiftvalue_op_from_str (stream, "INC",
- (unsigned HOST_WIDEST_INT)
+ (uint64_t)
mmix_intval (x));
return;
case 'o':
mmix_output_shiftvalue_op_from_str (stream, "OR",
- (unsigned HOST_WIDEST_INT)
+ (uint64_t)
mmix_intval (x));
return;
case 's':
mmix_output_shiftvalue_op_from_str (stream, "SET",
- (unsigned HOST_WIDEST_INT)
+ (uint64_t)
mmix_intval (x));
return;
fatal_insn ("MMIX Internal: Bad value for 'm', not a CONST_INT",
x);
}
- fprintf (stream, HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) (mmix_intval (x) - 1));
+ fprintf (stream, "%" PRId64,
+ (int64_t) (mmix_intval (x) - 1));
return;
case 'p':
return;
case 'v':
- mmix_output_shifted_value (stream, (HOST_WIDEST_INT) mmix_intval (x));
+ mmix_output_shifted_value (stream, (int64_t) mmix_intval (x));
return;
case 'V':
- mmix_output_shifted_value (stream, (HOST_WIDEST_INT) ~mmix_intval (x));
+ mmix_output_shifted_value (stream, (int64_t) ~mmix_intval (x));
return;
case 'W':
return;
case MEM:
- output_address (XEXP (modified_x, 0));
+ output_address (GET_MODE (modified_x), XEXP (modified_x, 0));
return;
case CONST_INT:
if (CONSTANT_P (modified_x)
/* Strangely enough, this is not included in CONSTANT_P.
FIXME: Ask/check about sanity here. */
- || GET_CODE (modified_x) == CODE_LABEL)
+ || LABEL_P (modified_x))
{
output_addr_const (stream, modified_x);
return;
/* TARGET_PRINT_OPERAND_ADDRESS. */
static void
-mmix_print_operand_address (FILE *stream, rtx x)
+mmix_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x)
{
if (REG_P (x))
{
reg_names[MMIX_OUTPUT_REGNO (REGNO (x2))]);
return;
}
- else if (GET_CODE (x2) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (x2), 'I'))
+ else if (satisfies_constraint_I (x2))
{
output_addr_const (stream, x2);
return;
from insn-emit.c. */
rtx
-mmix_get_hard_reg_initial_val (enum machine_mode mode, int regno)
+mmix_get_hard_reg_initial_val (machine_mode mode, int regno)
{
return get_hard_reg_initial_val (mode, regno);
}
/* These registers aren't actually saved (as in "will be
restored"), so don't tell DWARF2 they're saved. */
emit_move_insn (gen_rtx_MEM (DImode,
- plus_constant (stack_pointer_rtx,
+ plus_constant (Pmode, stack_pointer_rtx,
offset)),
gen_rtx_REG (DImode, regno));
offset -= 8;
}
insn = emit_move_insn (gen_rtx_MEM (DImode,
- plus_constant (stack_pointer_rtx,
+ plus_constant (Pmode,
+ stack_pointer_rtx,
offset)),
hard_frame_pointer_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
emit_move_insn (tmpreg, retreg);
insn = emit_move_insn (gen_rtx_MEM (DImode,
- plus_constant (stack_pointer_rtx,
+ plus_constant (Pmode,
+ stack_pointer_rtx,
offset)),
tmpreg);
RTX_FRAME_RELATED_P (insn) = 1;
add_reg_note (insn, REG_FRAME_RELATED_EXPR,
- gen_rtx_SET (VOIDmode,
- gen_rtx_MEM (DImode,
- plus_constant (stack_pointer_rtx,
+ gen_rtx_SET (gen_rtx_MEM (DImode,
+ plus_constant (Pmode,
+ stack_pointer_rtx,
offset)),
retreg));
gen_rtx_REG (DImode,
MMIX_rO_REGNUM));
emit_move_insn (gen_rtx_MEM (DImode,
- plus_constant (stack_pointer_rtx, offset)),
+ plus_constant (Pmode, stack_pointer_rtx,
+ offset)),
gen_rtx_REG (DImode, 255));
offset -= 8;
}
}
insn = emit_move_insn (gen_rtx_MEM (DImode,
- plus_constant (stack_pointer_rtx,
+ plus_constant (Pmode,
+ stack_pointer_rtx,
offset)),
gen_rtx_REG (DImode, regno));
RTX_FRAME_RELATED_P (insn) = 1;
emit_move_insn (gen_rtx_REG (DImode, regno),
gen_rtx_MEM (DImode,
- plus_constant (stack_pointer_rtx,
+ plus_constant (Pmode, stack_pointer_rtx,
offset)));
offset += 8;
}
emit_move_insn (hard_frame_pointer_rtx,
gen_rtx_MEM (DImode,
- plus_constant (stack_pointer_rtx,
+ plus_constant (Pmode, stack_pointer_rtx,
offset)));
offset += 8;
}
void
mmix_output_register_setting (FILE *stream,
int regno,
- HOST_WIDEST_INT value,
+ int64_t value,
int do_begin_end)
{
if (do_begin_end)
fprintf (stream, "\t");
- if (mmix_shiftable_wyde_value ((unsigned HOST_WIDEST_INT) value))
+ if (insn_const_int_ok_for_constraint (value, CONSTRAINT_K))
+ fprintf (stream, "NEGU %s,0,%" PRId64, reg_names[regno], -value);
+ else if (mmix_shiftable_wyde_value ((uint64_t) value))
{
/* First, the one-insn cases. */
mmix_output_shiftvalue_op_from_str (stream, "SET",
- (unsigned HOST_WIDEST_INT)
+ (uint64_t)
value);
fprintf (stream, " %s,", reg_names[regno]);
- mmix_output_shifted_value (stream, (unsigned HOST_WIDEST_INT) value);
+ mmix_output_shifted_value (stream, (uint64_t) value);
}
- else if (mmix_shiftable_wyde_value (-(unsigned HOST_WIDEST_INT) value))
+ else if (mmix_shiftable_wyde_value (-(uint64_t) value))
{
/* We do this to get a bit more legible assembly code. The next
alternative is mostly redundant with this. */
mmix_output_shiftvalue_op_from_str (stream, "SET",
- -(unsigned HOST_WIDEST_INT)
+ -(uint64_t)
value);
fprintf (stream, " %s,", reg_names[regno]);
- mmix_output_shifted_value (stream, -(unsigned HOST_WIDEST_INT) value);
+ mmix_output_shifted_value (stream, -(uint64_t) value);
fprintf (stream, "\n\tNEGU %s,0,%s", reg_names[regno],
reg_names[regno]);
}
- else if (mmix_shiftable_wyde_value (~(unsigned HOST_WIDEST_INT) value))
+ else if (mmix_shiftable_wyde_value (~(uint64_t) value))
{
/* Slightly more expensive, the two-insn cases. */
anyone else cares). */
mmix_output_shiftvalue_op_from_str (stream, "SET",
- ~(unsigned HOST_WIDEST_INT)
+ ~(uint64_t)
value);
fprintf (stream, " %s,", reg_names[regno]);
- mmix_output_shifted_value (stream, ~(unsigned HOST_WIDEST_INT) value);
+ mmix_output_shifted_value (stream, ~(uint64_t) value);
fprintf (stream, "\n\tNOR %s,%s,0", reg_names[regno],
reg_names[regno]);
}
const char *line_begin = "";
int insns = 0;
int i;
- HOST_WIDEST_INT tmpvalue = value;
+ int64_t tmpvalue = value;
/* Compute the number of insns needed to output this constant. */
for (i = 0; i < 4 && tmpvalue != 0; i++)
else return 0. */
int
-mmix_shiftable_wyde_value (unsigned HOST_WIDEST_INT value)
+mmix_shiftable_wyde_value (uint64_t value)
{
/* Shift by 16 bits per group, stop when we've found two groups with
nonzero bits. */
rtx
mmix_gen_compare_reg (RTX_CODE code, rtx x, rtx y)
{
- enum machine_mode ccmode = SELECT_CC_MODE (code, x, y);
+ machine_mode ccmode = SELECT_CC_MODE (code, x, y);
return gen_reg_rtx (ccmode);
}
{
/* Positive adjustments are in the epilogue only. Don't mark them
as "frame-related" for unwind info. */
- if (CONST_OK_FOR_LETTER_P (offset, 'L'))
+ if (insn_const_int_ok_for_constraint (offset, CONSTRAINT_L))
emit_insn (gen_adddi3 (stack_pointer_rtx,
stack_pointer_rtx,
GEN_INT (offset)));
static void
mmix_output_shiftvalue_op_from_str (FILE *stream,
const char *mainop,
- HOST_WIDEST_INT value)
+ int64_t value)
{
static const char *const op_part[] = {"L", "ML", "MH", "H"};
int i;
if (! mmix_shiftable_wyde_value (value))
{
char s[sizeof ("0xffffffffffffffff")];
- sprintf (s, HOST_WIDEST_INT_PRINT_HEX, value);
+ sprintf (s, "%#" PRIx64, value);
internal_error ("MMIX Internal: %s is not a shiftable int", s);
}
/* Print a 64-bit value, optionally prefixed by assembly pseudo. */
static void
-mmix_output_octa (FILE *stream, HOST_WIDEST_INT value, int do_begin_end)
+mmix_output_octa (FILE *stream, int64_t value, int do_begin_end)
{
- /* Snipped from final.c:output_addr_const. We need to avoid the
- presumed universal "0x" prefix. We can do it by replacing "0x" with
- "#0" here; we must avoid a space in the operands and no, the zero
- won't cause the number to be assumed in octal format. */
- char hex_format[sizeof (HOST_WIDEST_INT_PRINT_HEX)];
-
if (do_begin_end)
fprintf (stream, "\tOCTA ");
- strcpy (hex_format, HOST_WIDEST_INT_PRINT_HEX);
- hex_format[0] = '#';
- hex_format[1] = '0';
-
/* Provide a few alternative output formats depending on the number, to
improve legibility of assembler output. */
- if ((value < (HOST_WIDEST_INT) 0 && value > (HOST_WIDEST_INT) -10000)
- || (value >= (HOST_WIDEST_INT) 0 && value <= (HOST_WIDEST_INT) 16384))
+ if ((value < (int64_t) 0 && value > (int64_t) -10000)
+ || (value >= (int64_t) 0 && value <= (int64_t) 16384))
fprintf (stream, "%d", (int) value);
- else if (value > (HOST_WIDEST_INT) 0
- && value < ((HOST_WIDEST_INT) 1 << 31) * 2)
+ else if (value > (int64_t) 0
+ && value < ((int64_t) 1 << 31) * 2)
fprintf (stream, "#%x", (unsigned int) value);
- else
- fprintf (stream, hex_format, value);
+ else if (sizeof (HOST_WIDE_INT) == sizeof (int64_t))
+ /* We need to avoid the not-so-universal "0x" prefix; we need the
+ pure hex-digits together with the mmixal "#" hex prefix. */
+ fprintf (stream, "#" HOST_WIDE_INT_PRINT_HEX_PURE,
+ (HOST_WIDE_INT) value);
+ else /* Need to avoid the hex output; there's no ...WIDEST...HEX_PURE. */
+ fprintf (stream, "%" PRIu64, value);
if (do_begin_end)
fprintf (stream, "\n");
be output with an operand). */
static void
-mmix_output_shifted_value (FILE *stream, HOST_WIDEST_INT value)
+mmix_output_shifted_value (FILE *stream, int64_t value)
{
int i;
if (! mmix_shiftable_wyde_value (value))
{
char s[16+2+1];
- sprintf (s, HOST_WIDEST_INT_PRINT_HEX, value);
+ sprintf (s, "%#" PRIx64, value);
internal_error ("MMIX Internal: %s is not a shiftable int", s);
}
struct cc_type_conv
{
- enum machine_mode cc_mode;
+ machine_mode cc_mode;
/* Terminated with {UNKNOWN, NULL, NULL} */
const struct cc_conv *const convs;
#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;
- enum machine_mode mode = GET_MODE (XEXP (x, 0));
+ machine_mode mode = GET_MODE (XEXP (x, 0));
RTX_CODE cc = GET_CODE (x);
for (i = 0; i < ARRAY_SIZE (cc_convs); i++)
/* Return the bit-value for a const_int or const_double. */
-static HOST_WIDEST_INT
+int64_t
mmix_intval (const_rtx x)
{
- unsigned HOST_WIDEST_INT retval;
-
if (GET_CODE (x) == CONST_INT)
return INTVAL (x);
gcc-2.7.2 is broken. I still want people to be able to use it for
cross-compilation to MMIX. */
if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == VOIDmode)
- {
- if (sizeof (HOST_WIDE_INT) < sizeof (HOST_WIDEST_INT))
- {
- retval = (unsigned) CONST_DOUBLE_LOW (x) / 2;
- retval *= 2;
- retval |= CONST_DOUBLE_LOW (x) & 1;
-
- retval |=
- (unsigned HOST_WIDEST_INT) CONST_DOUBLE_HIGH (x)
- << (HOST_BITS_PER_LONG)/2 << (HOST_BITS_PER_LONG)/2;
- }
- else
- retval = CONST_DOUBLE_HIGH (x);
-
- return retval;
- }
+ return CONST_DOUBLE_HIGH (x);
if (GET_CODE (x) == CONST_DOUBLE)
{
- REAL_VALUE_TYPE value;
-
- /* FIXME: This macro is not in the manual but should be. */
- REAL_VALUE_FROM_CONST_DOUBLE (value, x);
-
if (GET_MODE (x) == DFmode)
{
long bits[2];
- REAL_VALUE_TO_TARGET_DOUBLE (value, bits);
+ REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (x), bits);
/* The double cast is necessary to avoid getting the long
sign-extended to unsigned long long(!) when they're of
different size (usually 32-bit hosts). */
return
- ((unsigned HOST_WIDEST_INT) (unsigned long) bits[0]
- << (unsigned HOST_WIDEST_INT) 32U)
- | (unsigned HOST_WIDEST_INT) (unsigned long) bits[1];
+ ((uint64_t) (unsigned long) bits[0]
+ << (uint64_t) 32U)
+ | (uint64_t) (unsigned long) bits[1];
}
else if (GET_MODE (x) == SFmode)
{
long bits;
- REAL_VALUE_TO_TARGET_SINGLE (value, bits);
+ REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), bits);
return (unsigned long) bits;
}
/* Worker function for TARGET_PROMOTE_FUNCTION_MODE. */
-enum machine_mode
+machine_mode
mmix_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
- enum machine_mode mode,
+ machine_mode mode,
int *punsignedp ATTRIBUTE_UNUSED,
const_tree fntype ATTRIBUTE_UNUSED,
int for_return)