[ARC] Add SJLI support.
authorClaudiu Zissulescu <claziss@synopsys.com>
Fri, 26 Jan 2018 11:33:42 +0000 (12:33 +0100)
committerClaudiu Zissulescu <claziss@gcc.gnu.org>
Fri, 26 Jan 2018 11:33:42 +0000 (12:33 +0100)
gcc/
2018-01-26  Claudiu Zissulescu  <claziss@synopsys.com>

        * config/arc/arc-protos.h: Add arc_is_secure_call_p proto.
        * config/arc/arc.c (arc_handle_secure_attribute): New function.
        (arc_attribute_table): Add 'secure_call' attribute.
        (arc_print_operand): Print secure call operand.
        (arc_function_ok_for_sibcall): Don't optimize tail calls when
        secure.
        (arc_is_secure_call_p): New function.
        * config/arc/arc.md (call_i): Add support for sjli instruction.
        (call_value_i): Likewise.
        * config/arc/constraints.md (Csc): New constraint.

From-SVN: r257082

gcc/ChangeLog
gcc/config/arc/arc-protos.h
gcc/config/arc/arc.c
gcc/config/arc/arc.md
gcc/config/arc/constraints.md
gcc/doc/extend.texi

index 61a85f8c9d716dcf0a7db65c92a9257395790fa1..8782ff8b17af6c3b99ed7d24c792d34e3f8f9e19 100644 (file)
@@ -1,3 +1,16 @@
+2018-01-26  Claudiu Zissulescu  <claziss@synopsys.com>
+
+       * config/arc/arc-protos.h: Add arc_is_secure_call_p proto.
+       * config/arc/arc.c (arc_handle_secure_attribute): New function.
+       (arc_attribute_table): Add 'secure_call' attribute.
+       (arc_print_operand): Print secure call operand.
+       (arc_function_ok_for_sibcall): Don't optimize tail calls when
+       secure.
+       (arc_is_secure_call_p): New function.  * config/arc/arc.md
+       (call_i): Add support for sjli instruction.
+       (call_value_i): Likewise.
+       * config/arc/constraints.md (Csc): New constraint.
+
 2018-01-26  Claudiu Zissulescu  <claziss@synopsys.com>
            John Eric Martin <John.Martin@emmicro-us.com>
 
index 7274fe0e4a0b2942d7d554b06ff20e316a3102a1..76b82bfb517ae6900e5f577e5affcc02829b998b 100644 (file)
@@ -118,3 +118,4 @@ extern bool arc_store_addr_hazard_p (rtx_insn *, rtx_insn *);
 extern rtx arc_eh_return_address_location (void);
 extern bool arc_is_jli_call_p (rtx);
 extern void arc_file_end (void);
+extern bool arc_is_secure_call_p (rtx);
index 78cf323a0367273931a1b79b0f8b24e0ba1b8120..1ad0bf601f605d604e8d0e34a7760cb508a6c17a 100644 (file)
@@ -226,6 +226,7 @@ static int get_arc_condition_code (rtx);
 static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
 static tree arc_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
 static tree arc_handle_jli_attribute (tree *, tree, tree, int, bool *);
+static tree arc_handle_secure_attribute (tree *, tree, tree, int, bool *);
 
 
 /* Initialized arc_attribute_table to NULL since arc doesnot have any
@@ -257,6 +258,9 @@ const struct attribute_spec arc_attribute_table[] =
      table is given as input parameter.  */
   { "jli_fixed",    1, 1, false, true,  true,  arc_handle_jli_attribute,
     NULL },
+  /* Call a function using secure-mode.  */
+  { "secure_call",  1, 1, false, true, true, arc_handle_secure_attribute,
+    NULL },
   { NULL, 0, 0, false, false, false, false, NULL, NULL }
 };
 static int arc_comp_type_attributes (const_tree, const_tree);
@@ -3745,6 +3749,46 @@ arc_initialize_trampoline (rtx tramp, tree fndecl, rtx cxt)
                     Pmode);
 }
 
+/* Add the given function declaration to emit code in JLI section.  */
+
+static void
+arc_add_jli_section (rtx pat)
+{
+  const char *name;
+  tree attrs;
+  arc_jli_section *sec = arc_jli_sections, *new_section;
+  tree decl = SYMBOL_REF_DECL (pat);
+
+  if (!pat)
+    return;
+
+  if (decl)
+    {
+      /* For fixed locations do not generate the jli table entry.  It
+        should be provided by the user as an asm file.  */
+      attrs = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+      if (lookup_attribute ("jli_fixed", attrs))
+       return;
+    }
+
+  name = XSTR (pat, 0);
+
+  /* Don't insert the same symbol twice.  */
+  while (sec != NULL)
+    {
+      if(strcmp (name, sec->name) == 0)
+       return;
+      sec = sec->next;
+    }
+
+  /* New name, insert it.  */
+  new_section = (arc_jli_section *) xmalloc (sizeof (arc_jli_section));
+  gcc_assert (new_section != NULL);
+  new_section->name = name;
+  new_section->next = arc_jli_sections;
+  arc_jli_sections = new_section;
+}
+
 /* This is set briefly to 1 when we output a ".as" address modifer, and then
    reset when we output the scaled address.  */
 static int output_scaled = 0;
@@ -3772,6 +3816,7 @@ static int output_scaled = 0;
     'D'
     'R': Second word
     'S': JLI instruction
+    'j': used by mov instruction to properly emit jli related labels.
     'B': Branch comparison operand - suppress sda reference
     'H': Most significant word
     'L': Least significant word
@@ -3986,6 +4031,7 @@ arc_print_operand (FILE *file, rtx x, int code)
       else
        output_operand_lossage ("invalid operand to %%R code");
       return;
+    case 'j':
     case 'S' :
       if (GET_CODE (x) == SYMBOL_REF
          && arc_is_jli_call_p (x))
@@ -3997,6 +4043,9 @@ arc_print_operand (FILE *file, rtx x, int code)
                            : NULL_TREE);
              if (lookup_attribute ("jli_fixed", attrs))
                {
+                 /* No special treatment for jli_fixed functions.  */
+                 if (code == 'j')
+                   break;
                  fprintf (file, "%ld\t; @",
                           TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attrs))));
                  assemble_name (file, XSTR (x, 0));
@@ -4005,6 +4054,22 @@ arc_print_operand (FILE *file, rtx x, int code)
            }
          fprintf (file, "@__jli.");
          assemble_name (file, XSTR (x, 0));
+         if (code == 'j')
+           arc_add_jli_section (x);
+         return;
+       }
+      if (GET_CODE (x) == SYMBOL_REF
+         && arc_is_secure_call_p (x))
+       {
+         /* No special treatment for secure functions.  */
+         if (code == 'j' )
+           break;
+         tree attrs = (TREE_TYPE (SYMBOL_REF_DECL (x)) != error_mark_node
+                       ? TYPE_ATTRIBUTES (TREE_TYPE (SYMBOL_REF_DECL (x)))
+                       : NULL_TREE);
+         fprintf (file, "%ld\t; @",
+                  TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attrs))));
+         assemble_name (file, XSTR (x, 0));
          return;
        }
       break;
@@ -6949,6 +7014,8 @@ arc_function_ok_for_sibcall (tree decl,
        return false;
       if (lookup_attribute ("jli_fixed", attrs))
        return false;
+      if (lookup_attribute ("secure_call", attrs))
+       return false;
     }
 
   /* Everything else is ok.  */
@@ -7655,46 +7722,6 @@ arc_reorg_loops (void)
   reorg_loops (true, &arc_doloop_hooks);
 }
 
-/* Add the given function declaration to emit code in JLI section.  */
-
-static void
-arc_add_jli_section (rtx pat)
-{
-  const char *name;
-  tree attrs;
-  arc_jli_section *sec = arc_jli_sections, *new_section;
-  tree decl = SYMBOL_REF_DECL (pat);
-
-  if (!pat)
-    return;
-
-  if (decl)
-    {
-      /* For fixed locations do not generate the jli table entry.  It
-        should be provided by the user as an asm file.  */
-      attrs = TYPE_ATTRIBUTES (TREE_TYPE (decl));
-      if (lookup_attribute ("jli_fixed", attrs))
-       return;
-    }
-
-  name = XSTR (pat, 0);
-
-  /* Don't insert the same symbol twice.  */
-  while (sec != NULL)
-    {
-      if(strcmp (name, sec->name) == 0)
-       return;
-      sec = sec->next;
-    }
-
-  /* New name, insert it.  */
-  new_section = (arc_jli_section *) xmalloc (sizeof (arc_jli_section));
-  gcc_assert (new_section != NULL);
-  new_section->name = name;
-  new_section->next = arc_jli_sections;
-  arc_jli_sections = new_section;
-}
-
 /* Scan all calls and add symbols to be emitted in the jli section if
    needed.  */
 
@@ -11030,6 +11057,62 @@ arc_handle_jli_attribute (tree *node ATTRIBUTE_UNUSED,
    return NULL_TREE;
 }
 
+/* Handle and "scure" attribute; arguments as in struct
+   attribute_spec.handler.  */
+
+static tree
+arc_handle_secure_attribute (tree *node ATTRIBUTE_UNUSED,
+                         tree name, tree args, int,
+                         bool *no_add_attrs)
+{
+  if (!TARGET_EM)
+    {
+      warning (OPT_Wattributes,
+              "%qE attribute only valid for ARC EM architecture",
+              name);
+      *no_add_attrs = true;
+    }
+
+  if (args == NULL_TREE)
+    {
+      warning (OPT_Wattributes,
+              "argument of %qE attribute is missing",
+              name);
+      *no_add_attrs = true;
+    }
+  else
+    {
+      if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
+       TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
+      tree arg = TREE_VALUE (args);
+      if (TREE_CODE (arg) != INTEGER_CST)
+       {
+         warning (0, "%qE attribute allows only an integer constant argument",
+                  name);
+         *no_add_attrs = true;
+       }
+    }
+   return NULL_TREE;
+}
+
+/* Return nonzero if the symbol is a secure function.  */
+
+bool
+arc_is_secure_call_p (rtx pat)
+{
+  tree attrs;
+  tree decl = SYMBOL_REF_DECL (pat);
+
+  if (!decl)
+    return false;
+
+  attrs = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+  if (lookup_attribute ("secure_call", attrs))
+    return true;
+
+  return false;
+}
+
 /* Implement TARGET_USE_ANCHORS_FOR_SYMBOL_P.  We don't want to use
    anchors for small data: the GP register acts as an anchor in that
    case.  We also don't want to use them for PC-relative accesses,
index 233e6f5379e61be1d5e57fdb6b702c27262066c5..172fd115d25bd46eb07712cadaffd89d08002d41 100644 (file)
    mov%? %0,%1         ;11
    add %0,%1           ;12
    add %0,pcl,%1@pcl    ;13
-   mov%? %0,%        ;14
-   mov%? %0,%1         ;15
-   mov%? %0,%1         ;16
-   ld%?%U1 %0,%1       ;17
+   mov%? %0,%j1        ;14
+   mov%? %0,%j1                ;15
+   mov%? %0,%j1                ;16
+   ld%? %0,%1          ;17
    st%? %1,%0%&                ;18
    * return arc_short_long (insn, \"push%? %1%&\", \"st%U0 %1,%0%&\");
    * return arc_short_long (insn, \"pop%? %0%&\",  \"ld%U1 %0,%1%&\");
 ; alternative 1 ("q"), that means that we can't use the short form.
 (define_insn "*call_i"
   [(call (mem:SI (match_operand:SI 0
-                 "call_address_operand" "Rcq,q,c,Cji,Cbp,Cbr,L,I,Cal"))
+                 "call_address_operand" "Rcq,q,c,Cji,Csc,Cbp,Cbr,L,I,Cal"))
         (match_operand 1 "" ""))
    (clobber (reg:SI 31))]
   ""
    jl%!%* [%0]%&
    jl%!%* [%0]
    jli_s %S0
+   sjli  %S0
    bl%!%* %P0
    bl%!%* %P0
    jl%!%* %0
    jl%* %0
    jl%! %0"
-  [(set_attr "type" "call,call,call,call_no_delay_slot,call,call,call,call,call_no_delay_slot")
-   (set_attr "iscompact" "maybe,false,*,true,*,*,*,*,*")
-   (set_attr "predicable" "no,no,yes,no,yes,no,yes,no,yes")
-   (set_attr "length" "*,*,4,2,4,4,4,4,8")])
+  [(set_attr "type" "call,call,call,call_no_delay_slot,call_no_delay_slot,call,call,call,call,call_no_delay_slot")
+   (set_attr "iscompact" "maybe,false,*,true,*,*,*,*,*,*")
+   (set_attr "predicable" "no,no,yes,no,no,yes,no,yes,no,yes")
+   (set_attr "length" "*,*,4,2,4,4,4,4,4,8")])
 
 (define_expand "call_value"
   ;; operand 2 is stack_size_rtx
 ; At instruction output time, if it doesn't match and we end up with
 ; alternative 1 ("q"), that means that we can't use the short form.
 (define_insn "*call_value_i"
-  [(set (match_operand 0 "dest_reg_operand"  "=Rcq,q,w,  w,  w,  w,w,w,  w")
+  [(set (match_operand 0 "dest_reg_operand"  "=Rcq,q,w,  w,  w,  w,  w,w,w,  w")
        (call (mem:SI (match_operand:SI 1
-                      "call_address_operand" "Rcq,q,c,Cji,Cbp,Cbr,L,I,Cal"))
+                      "call_address_operand" "Rcq,q,c,Cji,Csc,Cbp,Cbr,L,I,Cal"))
              (match_operand 2 "" "")))
    (clobber (reg:SI 31))]
   ""
    jl%!%* [%1]%&
    jl%!%* [%1]
    jli_s %S1
+   sjli  %S1
    bl%!%* %P1;1
    bl%!%* %P1;1
    jl%!%* %1
    jl%* %1
    jl%! %1"
-  [(set_attr "type" "call,call,call,call_no_delay_slot,call,call,call,call,call_no_delay_slot")
-   (set_attr "iscompact" "maybe,false,*,true,*,*,*,*,*")
-   (set_attr "predicable" "no,no,yes,no,yes,no,yes,no,yes")
-   (set_attr "length" "*,*,4,2,4,4,4,4,8")])
+  [(set_attr "type" "call,call,call,call_no_delay_slot,call_no_delay_slot,call,call,call,call,call_no_delay_slot")
+   (set_attr "iscompact" "maybe,false,*,true,false,*,*,*,*,*")
+   (set_attr "predicable" "no,no,yes,no,no,yes,no,yes,no,yes")
+   (set_attr "length" "*,*,4,2,4,4,4,4,4,8")])
 
 ; There is a bl_s instruction (16 bit opcode branch-and-link), but we can't
 ; use it for lack of inter-procedural branch shortening.
index 565d8608e85099fdc3ef43f9d12d5381217f095d..7249107d988fe705b087b28946c102a2b009013e 100644 (file)
        (match_test "TARGET_CODE_DENSITY")
        (match_test "arc_is_jli_call_p (op)")))
 
+(define_constraint "Csc"
+  "Secure call"
+  (and (match_code "symbol_ref")
+       (match_test "TARGET_CODE_DENSITY")
+       (match_test "TARGET_EM")
+       (match_test "arc_is_secure_call_p (op)")))
+
 (define_constraint "Cpc"
   "pc-relative constant"
   (match_test "arc_legitimate_pic_addr_p (op)"))
index 478894be0ea80f2e3b3275807bac3fcffaeee0b4..a4b21e6c67a1b2a2fb98a124e833b6359765a849 100644 (file)
@@ -3775,6 +3775,12 @@ which are addressed using this instruction.
 Identical like the above one, but the location of the function in the
 @code{jli} table is known and given as an attribute parameter.
 
+@item secure_call
+@cindex @code{secure_call} function attribute, ARC
+This attribute allows one to mark secure-code functions that are
+callable from normal mode.  The location of the secure call function
+into the @code{sjli} table needs to be passed as argument.
+
 @end table
 
 @node ARM Function Attributes