/* Definitions for GCC. Part of the machine description for CRIS.
- Copyright (C) 1998-2016 Free Software Foundation, Inc.
+ Copyright (C) 1998-2017 Free Software Foundation, Inc.
Contributed by Axis Communications. Written by Hans-Peter Nilsson.
This file is part of GCC.
#include "target.h"
#include "rtl.h"
#include "tree.h"
+#include "stringpool.h"
+#include "attribs.h"
#include "cfghooks.h"
#include "df.h"
+#include "memmodel.h"
#include "tm_p.h"
#include "optabs.h"
#include "regs.h"
static rtx cris_libcall_value (machine_mode, const_rtx);
static bool cris_function_value_regno_p (const unsigned int);
static void cris_file_end (void);
+static bool cris_hard_regno_mode_ok (unsigned int, machine_mode);
/* This is the parsed result of the "-max-stack-stackframe=" option. If
it (still) is zero, then there was no such option given. */
#undef TARGET_INIT_LIBFUNCS
#define TARGET_INIT_LIBFUNCS cris_init_libfuncs
+#undef TARGET_LRA_P
+#define TARGET_LRA_P hook_bool_void_false
+
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P cris_legitimate_address_p
#undef TARGET_FUNCTION_VALUE_REGNO_P
#define TARGET_FUNCTION_VALUE_REGNO_P cris_function_value_regno_p
+#undef TARGET_HARD_REGNO_MODE_OK
+#define TARGET_HARD_REGNO_MODE_OK cris_hard_regno_mode_ok
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Helper for cris_load_multiple_op and cris_ret_movem_op. */
{
case PLUS:
return "add";
- break;
case MINUS:
return "sub";
- break;
case MULT:
/* This function is for retrieving a part of an instruction name for
case DIV:
return "div";
- break;
case AND:
return "and";
- break;
case IOR:
return "or";
- break;
case XOR:
return "xor";
- break;
case NOT:
return "not";
- break;
case ASHIFT:
return "lsl";
- break;
case LSHIFTRT:
return "lsr";
- break;
case ASHIFTRT:
return "asr";
- break;
case UMIN:
/* Used to control the sign/zero-extend character for the 'E' modifier.
BOUND has none. */
cris_output_insn_is_bound = 1;
return "bound";
- break;
default:
return "Unknown operator";
- break;
}
}
: cris_return_address_on_stack ();
}
-/* This used to be the INITIAL_FRAME_POINTER_OFFSET worker; now only
- handles FP -> SP elimination offset. */
+/* This handles FP -> SP elimination offset. */
static int
cris_initial_frame_pointer_offset (void)
&& rclass != SRP_REGS
&& rclass != CC0_REGS
&& rclass != SPECIAL_REGS)
- return GENERAL_REGS;
+ return GENNONACR_REGS;
return rclass;
}
insn for other reasons. */
bool
-cris_cc0_user_requires_cmp (rtx insn)
+cris_cc0_user_requires_cmp (rtx_insn *insn)
{
rtx_insn *cc0_user = NULL;
rtx body;
/* The ASM_OUTPUT_CASE_END worker. */
void
-cris_asm_output_case_end (FILE *stream, int num, rtx table)
+cris_asm_output_case_end (FILE *stream, int num, rtx_insn *table)
{
/* Step back, over the label for the table, to the actual casejump and
assert that we find only what's expected. */
- rtx whole_jump_insn = prev_nonnote_nondebug_insn (table);
+ rtx_insn *whole_jump_insn = prev_nonnote_nondebug_insn (table);
gcc_assert (whole_jump_insn != NULL_RTX && LABEL_P (whole_jump_insn));
whole_jump_insn = prev_nonnote_nondebug_insn (whole_jump_insn);
gcc_assert (whole_jump_insn != NULL_RTX
|| (TARGET_V32 && INSN_P (whole_jump_insn)
&& GET_CODE (PATTERN (whole_jump_insn)) == SEQUENCE)));
/* Get the pattern of the casejump, so we can extract the default label. */
- whole_jump_insn = PATTERN (whole_jump_insn);
+ rtx whole_jump_pat = PATTERN (whole_jump_insn);
if (TARGET_V32)
{
/* This can be a SEQUENCE, meaning the delay-slot of the jump is
filled. We also output the offset word a little differently. */
rtx parallel_jump
- = (GET_CODE (whole_jump_insn) == SEQUENCE
- ? PATTERN (XVECEXP (whole_jump_insn, 0, 0)) : whole_jump_insn);
+ = (GET_CODE (whole_jump_pat) == SEQUENCE
+ ? PATTERN (XVECEXP (whole_jump_pat, 0, 0)) : whole_jump_pat);
asm_fprintf (stream,
"\t.word %LL%d-.%s\n",
"\t.word %LL%d-%LL%d%s\n",
CODE_LABEL_NUMBER (XEXP
(XEXP
- (XEXP (XVECEXP (whole_jump_insn, 0, 0), 1),
+ (XEXP (XVECEXP (whole_jump_pat, 0, 0), 1),
2), 0)),
num,
(TARGET_PDEBUG ? "; default" : ""));
{
fprintf (stream, "\tba ");
assemble_name (stream, name);
- fprintf (stream, "%s\n", CRIS_PLT_PCOFFSET_SUFFIX);
+ fprintf (stream, "%s\n\tnop\n", CRIS_PLT_PCOFFSET_SUFFIX);
}
else
{
- fprintf (stream, "add.d ");
+ fprintf (stream, "\tadd.d ");
assemble_name (stream, name);
fprintf (stream, "%s,$pc\n", CRIS_PLT_PCOFFSET_SUFFIX);
}
}
else
{
- fprintf (stream, "jump ");
+ fprintf (stream, "\tjump ");
assemble_name (stream, XSTR (XEXP (DECL_RTL (funcdecl), 0), 0));
fprintf (stream, "\n");
sake of a trampoline. */
}
+/* Implement TARGET_HARD_REGNO_MODE_OK.
+
+ CRIS permits all registers to hold all modes. Well, except for the
+ condition-code register. And we can't hold larger-than-register size
+ modes in the last special register that can hold a full 32 bits. */
+static bool
+cris_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
+{
+ return ((mode == CCmode || regno != CRIS_CC0_REGNUM)
+ && (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
+ || (regno != CRIS_MOF_REGNUM && regno != CRIS_ACR_REGNUM)));
+}
#if 0
/* Various small functions to replace macros. Only called from a