]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/cris/cris.c
Turn HARD_REGNO_MODE_OK into a target hook
[thirdparty/gcc.git] / gcc / config / cris / cris.c
index 0df3c5d7e4d79c9597b1c9079c666364e56a0508..01806389075a17d770ef24cefbf798527dab6028 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
@@ -25,8 +25,11 @@ along with GCC; see the file COPYING3.  If not see
 #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"
@@ -160,6 +163,7 @@ static rtx cris_function_value(const_tree, const_tree, bool);
 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.  */
@@ -212,6 +216,9 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
 #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
 
@@ -274,6 +281,9 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
 #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.  */
@@ -541,11 +551,9 @@ cris_op_str (rtx x)
     {
     case PLUS:
       return "add";
-      break;
 
     case MINUS:
       return "sub";
-      break;
 
     case MULT:
       /* This function is for retrieving a part of an instruction name for
@@ -557,46 +565,36 @@ cris_op_str (rtx x)
 
     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;
   }
 }
 
@@ -1282,8 +1280,7 @@ cris_return_address_on_stack_for_return (void)
     : 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)
@@ -1606,7 +1603,7 @@ cris_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t rclass)
       && rclass != SRP_REGS
       && rclass != CC0_REGS
       && rclass != SPECIAL_REGS)
-    return GENERAL_REGS;
+    return GENNONACR_REGS;
 
   return rclass;
 }
@@ -2407,7 +2404,7 @@ cris_side_effect_mode_ok (enum rtx_code code, rtx *ops,
    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;
@@ -2586,11 +2583,11 @@ cris_asm_output_ident (const char *string)
 /* 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
@@ -2598,15 +2595,15 @@ cris_asm_output_case_end (FILE *stream, int num, rtx table)
                  || (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",
@@ -2621,7 +2618,7 @@ cris_asm_output_case_end (FILE *stream, int num, rtx table)
               "\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" : ""));
@@ -2772,18 +2769,18 @@ cris_asm_output_mi_thunk (FILE *stream,
        {
          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");
 
@@ -4299,6 +4296,18 @@ cris_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
      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