+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>
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);
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
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);
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;
'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
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))
: 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));
}
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;
return false;
if (lookup_attribute ("jli_fixed", attrs))
return false;
+ if (lookup_attribute ("secure_call", attrs))
+ return false;
}
/* Everything else is ok. */
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. */
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,
mov%? %0,%1 ;11
add %0,%1 ;12
add %0,pcl,%1@pcl ;13
- mov%? %0,%1 ;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.
(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)"))
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