diff gcc/config/rl78/rl78.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
line wrap: on
line diff
--- a/gcc/config/rl78/rl78.c	Fri Oct 27 22:46:09 2017 +0900
+++ b/gcc/config/rl78/rl78.c	Thu Oct 25 07:37:49 2018 +0900
@@ -1,5 +1,5 @@
 /* Subroutines used for code generation on Renesas RL78 processors.
-   Copyright (C) 2011-2017 Free Software Foundation, Inc.
+   Copyright (C) 2011-2018 Free Software Foundation, Inc.
    Contributed by Red Hat.
 
    This file is part of GCC.
@@ -18,6 +18,8 @@
    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"
@@ -78,6 +80,9 @@
   "sp", "ap", "psw", "es", "cs"
 };
 
+/* used by rl78_addsi3_internal for formatting insns output */
+static char fmt_buffer[1024];
+
 /* Structure for G13 MDUC registers.  */
 struct mduc_reg_type
 {
@@ -223,7 +228,7 @@
     }
 
   if (dump_file)
-    print_rtl_with_bb (dump_file, get_insns (), 0);
+    print_rtl_with_bb (dump_file, get_insns (), TDF_NONE);
 
   return 0;
 }
@@ -360,6 +365,8 @@
   if (TARGET_ES0
       && strcmp (lang_hooks.name, "GNU C")
       && strcmp (lang_hooks.name, "GNU C11")
+      && strcmp (lang_hooks.name, "GNU C17")
+      && strcmp (lang_hooks.name, "GNU C2X")
       && strcmp (lang_hooks.name, "GNU C89")
       && strcmp (lang_hooks.name, "GNU C99")
       /* Compiling with -flto results in a language of GNU GIMPLE being used... */
@@ -595,6 +602,18 @@
     }
 }
 
+void
+rl78_split_movdi (rtx *operands, enum machine_mode omode)
+{
+    rtx op00, op04, op10, op14;
+    op00 = rl78_subreg (SImode, operands[0], omode, 0);
+    op04 = rl78_subreg (SImode, operands[0], omode, 4);
+    op10 = rl78_subreg (SImode, operands[1], omode, 0);
+    op14 = rl78_subreg (SImode, operands[1], omode, 4);
+    emit_insn (gen_movsi (op00, op10));
+    emit_insn (gen_movsi (op04, op14));
+}
+
 /* Used by various two-operand expanders which cannot accept all
    operands in the "far" namespace.  Force some such operands into
    registers so that each pattern has at most one far operand.  */
@@ -786,12 +805,11 @@
 static tree
 rl78_handle_func_attribute (tree * node,
 			    tree   name,
-			    tree   args,
+			    tree   args ATTRIBUTE_UNUSED,
 			    int    flags ATTRIBUTE_UNUSED,
 			    bool * no_add_attrs)
 {
   gcc_assert (DECL_P (* node));
-  gcc_assert (args == NULL_TREE);
 
   if (TREE_CODE (* node) != FUNCTION_DECL)
     {
@@ -850,23 +868,47 @@
   return NULL_TREE;
 }
 
+/* Check "vector" attribute.  */
+
+static tree
+rl78_handle_vector_attribute (tree * node,
+			    tree   name,
+			    tree   args,
+			    int    flags ATTRIBUTE_UNUSED,
+			    bool * no_add_attrs)
+{
+  gcc_assert (DECL_P (* node));
+  gcc_assert (args != NULL_TREE);
+
+  if (TREE_CODE (* node) != FUNCTION_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute only applies to functions",
+	       name);
+      * no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 #undef  TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE		rl78_attribute_table
 
 /* Table of RL78-specific attributes.  */
 const struct attribute_spec rl78_attribute_table[] =
 {
-  /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
-     affects_type_identity.  */
-  { "interrupt",      0, 0, true, false, false, rl78_handle_func_attribute,
-    false },
-  { "brk_interrupt",  0, 0, true, false, false, rl78_handle_func_attribute,
-    false },
-  { "naked",          0, 0, true, false, false, rl78_handle_naked_attribute,
-    false },
-  { "saddr",          0, 0, true, false, false, rl78_handle_saddr_attribute,
-    false },
-  { NULL,             0, 0, false, false, false, NULL, false }
+  /* Name, min_len, max_len, decl_req, type_req, fn_type_req,
+     affects_type_identity, handler, exclude.  */
+  { "interrupt",      0, -1, true, false, false, false,
+    rl78_handle_func_attribute, NULL },
+  { "brk_interrupt",  0, 0, true, false, false, false,
+    rl78_handle_func_attribute, NULL },
+  { "naked",          0, 0, true, false, false, false,
+    rl78_handle_naked_attribute, NULL },
+  { "saddr",          0, 0, true, false, false, false,
+    rl78_handle_saddr_attribute, NULL },
+  { "vector",         1, -1, true, false, false, false,
+	rl78_handle_vector_attribute, NULL },
+  { NULL,             0, 0, false, false, false, false, NULL, NULL }
 };
 
 
@@ -1565,6 +1607,62 @@
 #undef  TARGET_ASM_FUNCTION_PROLOGUE
 #define TARGET_ASM_FUNCTION_PROLOGUE	rl78_start_function
 
+static void
+add_vector_labels (FILE *file, const char *aname)
+{
+  tree vec_attr;
+  tree val_attr;
+  const char *vname = "vect";
+  const char *s;
+  int vnum;
+
+  /* This node is for the vector/interrupt tag itself */
+  vec_attr = lookup_attribute (aname, DECL_ATTRIBUTES (current_function_decl));
+  if (!vec_attr)
+    return;
+
+  /* Now point it at the first argument */
+  vec_attr = TREE_VALUE (vec_attr);
+
+  /* Iterate through the arguments.  */
+  while (vec_attr)
+    {
+      val_attr = TREE_VALUE (vec_attr);
+      switch (TREE_CODE (val_attr))
+	{
+	case STRING_CST:
+	  s = TREE_STRING_POINTER (val_attr);
+	  goto string_id_common;
+
+	case IDENTIFIER_NODE:
+	  s = IDENTIFIER_POINTER (val_attr);
+
+	string_id_common:
+	  if (strcmp (s, "$default") == 0)
+	    {
+	      fprintf (file, "\t.global\t$tableentry$default$%s\n", vname);
+	      fprintf (file, "$tableentry$default$%s:\n", vname);
+	    }
+	  else
+	    vname = s;
+	  break;
+
+	case INTEGER_CST:
+	  vnum = TREE_INT_CST_LOW (val_attr);
+
+	  fprintf (file, "\t.global\t$tableentry$%d$%s\n", vnum, vname);
+	  fprintf (file, "$tableentry$%d$%s:\n", vnum, vname);
+	  break;
+
+	default:
+	  ;
+	}
+
+      vec_attr = TREE_CHAIN (vec_attr);
+    }
+
+}
+
 /* We don't use this to actually emit the function prologue.  We use
    this to insert a comment in the asm file describing the
    function.  */
@@ -1572,6 +1670,9 @@
 rl78_start_function (FILE *file)
 {
   int i;
+  
+  add_vector_labels (file, "interrupt");
+  add_vector_labels (file, "vector");
 
   if (cfun->machine->framesize == 0)
     return;
@@ -3789,16 +3890,21 @@
 rl78_note_reg_set (char *dead, rtx d, rtx insn)
 {
   int r, i;
-
+  bool is_dead;
   if (GET_CODE (d) == MEM)
     rl78_note_reg_uses (dead, XEXP (d, 0), insn);
 
   if (GET_CODE (d) != REG)
     return;
 
+  /* Do not mark the reg unused unless all QImode parts of it are dead.  */
   r = REGNO (d);
-  if (dead [r])
-    add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
+  is_dead = true;
+  for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
+	  if (!dead [r + i])
+		  is_dead = false;
+  if(is_dead)
+	add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
   if (dump_file)
     fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
   for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
@@ -4212,7 +4318,7 @@
   if (dump_file)
     {
       fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
-      print_rtl_with_bb (dump_file, get_insns (), 0);
+      print_rtl_with_bb (dump_file, get_insns (), TDF_NONE);
     }
 
   rl78_propogate_register_origins ();
@@ -4221,7 +4327,7 @@
   if (dump_file)
     {
       fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
-      print_rtl_with_bb (dump_file, get_insns (), 0);
+      print_rtl_with_bb (dump_file, get_insns (), TDF_NONE);
       fprintf (dump_file, "\n======================================================================\n");
     }
 
@@ -4768,6 +4874,8 @@
 const char *
 rl78_addsi3_internal (rtx * operands, unsigned int alternative)
 {
+  const char *addH2 = "addw ax, %H2\n\t";
+
   /* If we are adding in a constant symbolic address when -mes0
      is active then we know that the address must be <64K and
      that it is invalid to access anything above 64K relative to
@@ -4779,16 +4887,38 @@
       && ! TREE_SIDE_EFFECTS (SYMBOL_REF_DECL (operands[2])))
     return "movw ax, %h1\n\taddw ax, %h2\n\tmovw %h0, ax";
 
+  if(CONST_INT_P(operands[2]))
+  {
+    if((INTVAL(operands[2]) & 0xFFFF0000) == 0)
+    {
+        addH2 = "";
+    }
+    else if((INTVAL(operands[2]) & 0xFFFF0000) == 0x00010000)
+    {
+        addH2 = "incw ax\n\t";
+    }
+    else if((INTVAL(operands[2]) & 0xFFFF0000) == 0xFFFF0000)
+    {
+        addH2 = "decw ax\n\t";
+    }
+  }
+
   switch (alternative)
     {
     case 0:
     case 1:
-      return "movw ax, %h1\n\taddw ax, %h2\n\tmovw %h0, ax\n\tmovw ax, %H1\n\tsknc\n\tincw ax\n\taddw ax, %H2\n\tmovw %H0, ax";
+	  snprintf(fmt_buffer, sizeof(fmt_buffer),
+               "movw ax, %%h1\n\taddw ax, %%h2\n\tmovw %%h0, ax\n\tmovw ax, %%H1\n\tsknc\n\tincw ax\n\t%smovw %%H0,ax", addH2);
+	  break;
     case 2:
-      return "movw ax, %h1\n\taddw ax,%h2\n\tmovw bc, ax\n\tmovw ax, %H1\n\tsknc\n\tincw ax\n\taddw ax, %H2\n\tmovw %H0, ax\n\tmovw ax, bc\n\tmovw %h0, ax";
+	  snprintf(fmt_buffer, sizeof(fmt_buffer),
+               "movw ax, %%h1\n\taddw ax, %%h2\n\tmovw bc, ax\n\tmovw ax, %%H1\n\tsknc\n\tincw ax\n\t%smovw %%H0, ax\n\tmovw ax, bc\n\tmovw %%h0, ax", addH2);
+ 	  break;
     default:
       gcc_unreachable ();
     }
+
+  return fmt_buffer;
 }
 
 rtx