Commit 7778a1ad by Claudiu Zissulescu Committed by Claudiu Zissulescu

[ARC] Add SJLI support.

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
parent 6b55f8c9
2018-01-26 Claudiu Zissulescu <claziss@synopsys.com> 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> John Eric Martin <John.Martin@emmicro-us.com>
* config/arc/arc-protos.h: Add arc_is_jli_call_p proto. * config/arc/arc-protos.h: Add arc_is_jli_call_p proto.
......
...@@ -118,3 +118,4 @@ extern bool arc_store_addr_hazard_p (rtx_insn *, rtx_insn *); ...@@ -118,3 +118,4 @@ extern bool arc_store_addr_hazard_p (rtx_insn *, rtx_insn *);
extern rtx arc_eh_return_address_location (void); extern rtx arc_eh_return_address_location (void);
extern bool arc_is_jli_call_p (rtx); extern bool arc_is_jli_call_p (rtx);
extern void arc_file_end (void); extern void arc_file_end (void);
extern bool arc_is_secure_call_p (rtx);
...@@ -226,6 +226,7 @@ static int get_arc_condition_code (rtx); ...@@ -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_interrupt_attribute (tree *, tree, tree, int, bool *);
static tree arc_handle_fndecl_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_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 /* Initialized arc_attribute_table to NULL since arc doesnot have any
...@@ -257,6 +258,9 @@ const struct attribute_spec arc_attribute_table[] = ...@@ -257,6 +258,9 @@ const struct attribute_spec arc_attribute_table[] =
table is given as input parameter. */ table is given as input parameter. */
{ "jli_fixed", 1, 1, false, true, true, arc_handle_jli_attribute, { "jli_fixed", 1, 1, false, true, true, arc_handle_jli_attribute,
NULL }, 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 } { NULL, 0, 0, false, false, false, false, NULL, NULL }
}; };
static int arc_comp_type_attributes (const_tree, const_tree); static int arc_comp_type_attributes (const_tree, const_tree);
...@@ -3745,6 +3749,46 @@ arc_initialize_trampoline (rtx tramp, tree fndecl, rtx cxt) ...@@ -3745,6 +3749,46 @@ arc_initialize_trampoline (rtx tramp, tree fndecl, rtx cxt)
Pmode); 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 /* This is set briefly to 1 when we output a ".as" address modifer, and then
reset when we output the scaled address. */ reset when we output the scaled address. */
static int output_scaled = 0; static int output_scaled = 0;
...@@ -3772,6 +3816,7 @@ static int output_scaled = 0; ...@@ -3772,6 +3816,7 @@ static int output_scaled = 0;
'D' 'D'
'R': Second word 'R': Second word
'S': JLI instruction 'S': JLI instruction
'j': used by mov instruction to properly emit jli related labels.
'B': Branch comparison operand - suppress sda reference 'B': Branch comparison operand - suppress sda reference
'H': Most significant word 'H': Most significant word
'L': Least significant word 'L': Least significant word
...@@ -3986,6 +4031,7 @@ arc_print_operand (FILE *file, rtx x, int code) ...@@ -3986,6 +4031,7 @@ arc_print_operand (FILE *file, rtx x, int code)
else else
output_operand_lossage ("invalid operand to %%R code"); output_operand_lossage ("invalid operand to %%R code");
return; return;
case 'j':
case 'S' : case 'S' :
if (GET_CODE (x) == SYMBOL_REF if (GET_CODE (x) == SYMBOL_REF
&& arc_is_jli_call_p (x)) && arc_is_jli_call_p (x))
...@@ -3997,6 +4043,9 @@ arc_print_operand (FILE *file, rtx x, int code) ...@@ -3997,6 +4043,9 @@ arc_print_operand (FILE *file, rtx x, int code)
: NULL_TREE); : NULL_TREE);
if (lookup_attribute ("jli_fixed", attrs)) if (lookup_attribute ("jli_fixed", attrs))
{ {
/* No special treatment for jli_fixed functions. */
if (code == 'j')
break;
fprintf (file, "%ld\t; @", fprintf (file, "%ld\t; @",
TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attrs)))); TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attrs))));
assemble_name (file, XSTR (x, 0)); assemble_name (file, XSTR (x, 0));
...@@ -4005,6 +4054,22 @@ arc_print_operand (FILE *file, rtx x, int code) ...@@ -4005,6 +4054,22 @@ arc_print_operand (FILE *file, rtx x, int code)
} }
fprintf (file, "@__jli."); fprintf (file, "@__jli.");
assemble_name (file, XSTR (x, 0)); 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; return;
} }
break; break;
...@@ -6949,6 +7014,8 @@ arc_function_ok_for_sibcall (tree decl, ...@@ -6949,6 +7014,8 @@ arc_function_ok_for_sibcall (tree decl,
return false; return false;
if (lookup_attribute ("jli_fixed", attrs)) if (lookup_attribute ("jli_fixed", attrs))
return false; return false;
if (lookup_attribute ("secure_call", attrs))
return false;
} }
/* Everything else is ok. */ /* Everything else is ok. */
...@@ -7655,46 +7722,6 @@ arc_reorg_loops (void) ...@@ -7655,46 +7722,6 @@ arc_reorg_loops (void)
reorg_loops (true, &arc_doloop_hooks); 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 /* Scan all calls and add symbols to be emitted in the jli section if
needed. */ needed. */
...@@ -11030,6 +11057,62 @@ arc_handle_jli_attribute (tree *node ATTRIBUTE_UNUSED, ...@@ -11030,6 +11057,62 @@ arc_handle_jli_attribute (tree *node ATTRIBUTE_UNUSED,
return NULL_TREE; 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 /* 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 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, case. We also don't want to use them for PC-relative accesses,
......
...@@ -740,10 +740,10 @@ ...@@ -740,10 +740,10 @@
mov%? %0,%1 ;11 mov%? %0,%1 ;11
add %0,%1 ;12 add %0,%1 ;12
add %0,pcl,%1@pcl ;13 add %0,pcl,%1@pcl ;13
mov%? %0,%1 ;14 mov%? %0,%j1 ;14
mov%? %0,%1 ;15 mov%? %0,%j1 ;15
mov%? %0,%1 ;16 mov%? %0,%j1 ;16
ld%?%U1 %0,%1 ;17 ld%? %0,%1 ;17
st%? %1,%0%& ;18 st%? %1,%0%& ;18
* return arc_short_long (insn, \"push%? %1%&\", \"st%U0 %1,%0%&\"); * return arc_short_long (insn, \"push%? %1%&\", \"st%U0 %1,%0%&\");
* return arc_short_long (insn, \"pop%? %0%&\", \"ld%U1 %0,%1%&\"); * return arc_short_long (insn, \"pop%? %0%&\", \"ld%U1 %0,%1%&\");
...@@ -4233,7 +4233,7 @@ ...@@ -4233,7 +4233,7 @@
; alternative 1 ("q"), that means that we can't use the short form. ; alternative 1 ("q"), that means that we can't use the short form.
(define_insn "*call_i" (define_insn "*call_i"
[(call (mem:SI (match_operand:SI 0 [(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 "" "")) (match_operand 1 "" ""))
(clobber (reg:SI 31))] (clobber (reg:SI 31))]
"" ""
...@@ -4242,15 +4242,16 @@ ...@@ -4242,15 +4242,16 @@
jl%!%* [%0]%& jl%!%* [%0]%&
jl%!%* [%0] jl%!%* [%0]
jli_s %S0 jli_s %S0
sjli %S0
bl%!%* %P0 bl%!%* %P0
bl%!%* %P0 bl%!%* %P0
jl%!%* %0 jl%!%* %0
jl%* %0 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 "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 "iscompact" "maybe,false,*,true,*,*,*,*,*,*")
(set_attr "predicable" "no,no,yes,no,yes,no,yes,no,yes") (set_attr "predicable" "no,no,yes,no,no,yes,no,yes,no,yes")
(set_attr "length" "*,*,4,2,4,4,4,4,8")]) (set_attr "length" "*,*,4,2,4,4,4,4,4,8")])
(define_expand "call_value" (define_expand "call_value"
;; operand 2 is stack_size_rtx ;; operand 2 is stack_size_rtx
...@@ -4276,9 +4277,9 @@ ...@@ -4276,9 +4277,9 @@
; At instruction output time, if it doesn't match and we end up with ; 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. ; alternative 1 ("q"), that means that we can't use the short form.
(define_insn "*call_value_i" (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 (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 "" ""))) (match_operand 2 "" "")))
(clobber (reg:SI 31))] (clobber (reg:SI 31))]
"" ""
...@@ -4287,15 +4288,16 @@ ...@@ -4287,15 +4288,16 @@
jl%!%* [%1]%& jl%!%* [%1]%&
jl%!%* [%1] jl%!%* [%1]
jli_s %S1 jli_s %S1
sjli %S1
bl%!%* %P1;1 bl%!%* %P1;1
bl%!%* %P1;1 bl%!%* %P1;1
jl%!%* %1 jl%!%* %1
jl%* %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 "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 "iscompact" "maybe,false,*,true,false,*,*,*,*,*")
(set_attr "predicable" "no,no,yes,no,yes,no,yes,no,yes") (set_attr "predicable" "no,no,yes,no,no,yes,no,yes,no,yes")
(set_attr "length" "*,*,4,2,4,4,4,4,8")]) (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 ; 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. ; use it for lack of inter-procedural branch shortening.
......
...@@ -407,6 +407,13 @@ ...@@ -407,6 +407,13 @@
(match_test "TARGET_CODE_DENSITY") (match_test "TARGET_CODE_DENSITY")
(match_test "arc_is_jli_call_p (op)"))) (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" (define_constraint "Cpc"
"pc-relative constant" "pc-relative constant"
(match_test "arc_legitimate_pic_addr_p (op)")) (match_test "arc_legitimate_pic_addr_p (op)"))
......
...@@ -3775,6 +3775,12 @@ which are addressed using this instruction. ...@@ -3775,6 +3775,12 @@ which are addressed using this instruction.
Identical like the above one, but the location of the function in the Identical like the above one, but the location of the function in the
@code{jli} table is known and given as an attribute parameter. @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 @end table
@node ARM Function Attributes @node ARM Function Attributes
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment