@@ -116,3 +116,5 @@ extern void arc_secondary_reload_conv (rtx, rtx, rtx, bool);
extern void arc_cpu_cpp_builtins (cpp_reader *);
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);
@@ -71,6 +71,14 @@ along with GCC; see the file COPYING3. If not see
static char arc_cpu_name[10] = "";
static const char *arc_cpu_string = arc_cpu_name;
+typedef struct GTY (()) _arc_jli_section
+{
+ const char *name;
+ struct _arc_jli_section *next;
+} arc_jli_section;
+
+static arc_jli_section *arc_jli_sections = NULL;
+
/* Maximum size of a loop. */
#define ARC_MAX_LOOP_LENGTH 4095
@@ -212,6 +220,8 @@ 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 *);
+
/* Initialized arc_attribute_table to NULL since arc doesnot have any
machine specific supported attributes. */
@@ -233,6 +243,13 @@ const struct attribute_spec arc_attribute_table[] =
/* Function which are not having the prologue and epilogue generated
by the compiler. */
{ "naked", 0, 0, true, false, false, arc_handle_fndecl_attribute, false },
+ /* Functions calls made using jli instruction. The pointer in JLI
+ table is found latter. */
+ { "jli_always", 0, 0, false, true, true, NULL, false },
+ /* Functions calls made using jli instruction. The pointer in JLI
+ table is given as input parameter. */
+ { "jli_fixed", 1, 1, false, true, true, arc_handle_jli_attribute,
+ false },
{ NULL, 0, 0, false, false, false, NULL, false }
};
static int arc_comp_type_attributes (const_tree, const_tree);
@@ -3696,7 +3713,7 @@ static int output_scaled = 0;
'd'
'D'
'R': Second word
- 'S'
+ 'S': JLI instruction
'B': Branch comparison operand - suppress sda reference
'H': Most significant word
'L': Least significant word
@@ -3912,8 +3929,27 @@ arc_print_operand (FILE *file, rtx x, int code)
output_operand_lossage ("invalid operand to %%R code");
return;
case 'S' :
- /* FIXME: remove %S option. */
- break;
+ if (GET_CODE (x) == SYMBOL_REF
+ && arc_is_jli_call_p (x))
+ {
+ if (SYMBOL_REF_DECL (x))
+ {
+ tree attrs = (TREE_TYPE (SYMBOL_REF_DECL (x)) != error_mark_node
+ ? TYPE_ATTRIBUTES (TREE_TYPE (SYMBOL_REF_DECL (x)))
+ : NULL_TREE);
+ if (lookup_attribute ("jli_fixed", attrs))
+ {
+ fprintf (file, "%ld\t; @",
+ TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attrs))));
+ assemble_name (file, XSTR (x, 0));
+ return;
+ }
+ }
+ fprintf (file, "@__jli.");
+ assemble_name (file, XSTR (x, 0));
+ return;
+ }
+ break;
case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
if (CONSTANT_P (x))
{
@@ -5026,6 +5062,36 @@ static void arc_file_start (void)
fprintf (asm_out_file, "\t.cpu %s\n", arc_cpu_string);
}
+/* Implement `TARGET_ASM_FILE_END'. */
+/* Outputs to the stdio stream FILE jli related text. */
+
+void arc_file_end (void)
+{
+ arc_jli_section *sec = arc_jli_sections;
+
+ while (sec != NULL)
+ {
+ fprintf (asm_out_file, "\n");
+ fprintf (asm_out_file, "# JLI entry for function ");
+ assemble_name (asm_out_file, sec->name);
+ fprintf (asm_out_file, "\n\t.section .jlitab, \"axG\", @progbits, "
+ ".jlitab.");
+ assemble_name (asm_out_file, sec->name);
+ fprintf (asm_out_file,", comdat\n");
+
+ fprintf (asm_out_file, "\t.align\t4\n");
+ fprintf (asm_out_file, "__jli.");
+ assemble_name (asm_out_file, sec->name);
+ fprintf (asm_out_file, ":\n\t.weak __jli.");
+ assemble_name (asm_out_file, sec->name);
+ fprintf (asm_out_file, "\n\tb\t@");
+ assemble_name (asm_out_file, sec->name);
+ fprintf (asm_out_file, "\n");
+ sec = sec->next;
+ }
+ file_end_indicate_exec_stack ();
+}
+
/* Cost functions. */
/* Compute a (partial) cost for rtx X. Return true if the complete
@@ -6814,13 +6880,25 @@ check_if_valid_sleep_operand (rtx *operands, int opno)
/* Return true if it is ok to make a tail-call to DECL. */
static bool
-arc_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
+arc_function_ok_for_sibcall (tree decl,
tree exp ATTRIBUTE_UNUSED)
{
+ tree attrs = NULL_TREE;
+
/* Never tailcall from an ISR routine - it needs a special exit sequence. */
if (ARC_INTERRUPT_P (arc_compute_function_type (cfun)))
return false;
+ if (decl)
+ {
+ attrs = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+
+ if (lookup_attribute ("jli_always", attrs))
+ return false;
+ if (lookup_attribute ("jli_fixed", attrs))
+ return false;
+ }
+
/* Everything else is ok. */
return true;
}
@@ -7516,6 +7594,73 @@ 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. */
+
+static void
+jli_call_scan (void)
+{
+ rtx_insn *insn;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ if (!CALL_P (insn))
+ continue;
+
+ rtx pat = PATTERN (insn);
+ if (GET_CODE (pat) == COND_EXEC)
+ pat = COND_EXEC_CODE (pat);
+ pat = XVECEXP (pat, 0, 0);
+ if (GET_CODE (pat) == SET)
+ pat = SET_SRC (pat);
+
+ pat = XEXP (XEXP (pat, 0), 0);
+ if (GET_CODE (pat) == SYMBOL_REF
+ && arc_is_jli_call_p (pat))
+ arc_add_jli_section (pat);
+ }
+}
+
static int arc_reorg_in_progress = 0;
/* ARC's machince specific reorg function. */
@@ -7540,6 +7685,7 @@ arc_reorg (void)
arc_reorg_loops ();
workaround_arc_anomaly ();
+ jli_call_scan ();
/* FIXME: should anticipate ccfsm action, generate special patterns for
to-be-deleted branches that have no delay slot and have at least the
@@ -8218,11 +8364,11 @@ arc_output_addsi (rtx *operands, bool cond_p, bool output_p)
/* Try to emit a 16 bit opcode with long immediate. */
ret = 6;
if (short_p && match)
- ADDSI_OUTPUT1 ("add%? %0,%1,%S2");
+ ADDSI_OUTPUT1 ("add%? %0,%1,%2");
/* We have to use a 32 bit opcode, and with a long immediate. */
ret = 8;
- ADDSI_OUTPUT1 (intval < 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%S2");
+ ADDSI_OUTPUT1 (intval < 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%2");
}
/* Emit code for an commutative_cond_exec instruction with OPERANDS.
@@ -10760,6 +10906,68 @@ arc_builtin_setjmp_frame_value (void)
return gen_raw_REG (Pmode, FRAME_POINTER_REGNUM);
}
+/* Return nonzero if a jli call should be generated for a call from
+ the current function to DECL. */
+
+bool
+arc_is_jli_call_p (rtx pat)
+{
+ tree attrs;
+ tree decl = SYMBOL_REF_DECL (pat);
+
+ /* If it is not a well defined public function then return false. */
+ if (!decl || !SYMBOL_REF_FUNCTION_P (pat) || !TREE_PUBLIC (decl))
+ return false;
+
+ attrs = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+ if (lookup_attribute ("jli_always", attrs))
+ return true;
+
+ if (lookup_attribute ("jli_fixed", attrs))
+ return true;
+
+ return TARGET_JLI_ALWAYS;
+}
+
+/* Handle and "jli" attribute; arguments as in struct
+ attribute_spec.handler. */
+
+static tree
+arc_handle_jli_attribute (tree *node ATTRIBUTE_UNUSED,
+ tree name, tree args, int,
+ bool *no_add_attrs)
+{
+ if (!TARGET_V2)
+ {
+ warning (OPT_Wattributes,
+ "%qE attribute only valid for ARCv2 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;
+ }
+ /* FIXME! add range check. TREE_INT_CST_LOW (arg) */
+ }
+ return NULL_TREE;
+}
+
/* 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,
@@ -637,7 +637,7 @@
mov%? %0,%1
mov%? %0,%1
mov%? %0,%1
- mov%? %0,%S1
+ mov%? %0,%1
ldb%? %0,%1%&
stb%? %1,%0%&
ldb%? %0,%1%&
@@ -678,9 +678,9 @@
mov%? %0,%1
mov%? %0,%1
mov%? %0,%1
- mov%? %0,%S1%&
- mov%? %0,%S1
- mov%? %0,%S1
+ mov%? %0,%1%&
+ mov%? %0,%1
+ mov%? %0,%1
ld%_%? %0,%1%&
st%_%? %1,%0%&
xld%_%U1 %0,%1
@@ -688,8 +688,8 @@
xst%_%U0 %1,%0
st%_%U0%V0 %1,%0
st%_%U0%V0 %1,%0
- st%_%U0%V0 %S1,%0
- st%_%U0%V0 %S1,%0"
+ st%_%U0%V0 %1,%0
+ st%_%U0%V0 %1,%0"
[(set_attr "type" "move,move,move,move,move,move,move,move,move,move,move,load,store,load,load,store,store,store,store,store")
(set_attr "iscompact" "maybe,maybe,maybe,true,true,false,false,false,maybe_limm,maybe_limm,false,true,true,false,false,false,false,false,false,false")
(set_attr "predicable" "yes,no,yes,no,no,yes,no,yes,yes,yes,yes,no,no,no,no,no,no,no,no,no")
@@ -734,7 +734,7 @@
movh.cl %0,%L1>>16 ;9
* return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;10\" : \"movbi.cl %0,%L1 >> 24,24,8;10\";
mov%? %0,%1 ;11
- add %0,%S1 ;12
+ add %0,%1 ;12
add %0,pcl,%1@pcl ;13
mov%? %0,%1 ;14
mov%? %0,%1 ;15
@@ -795,7 +795,7 @@
(set (match_operand:SI 0 "register_operand" "=w,w,w")
(match_dup 1))]
""
- "mov%?.f %0,%S1"
+ "mov%?.f %0,%1"
; splitting to 'tst' allows short insns and combination into brcc.
"reload_completed && operands_match_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 3))]
@@ -1283,7 +1283,7 @@
(set (match_operand:SI 0 "dest_reg_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
- "ldb.a%V4 %3,[%0,%S2]"
+ "ldb.a%V4 %3,[%0,%2]"
[(set_attr "type" "load,load")
(set_attr "length" "4,8")])
@@ -1295,7 +1295,7 @@
(set (match_operand:SI 0 "dest_reg_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
- "ldb.a%V4 %3,[%0,%S2]"
+ "ldb.a%V4 %3,[%0,%2]"
[(set_attr "type" "load,load")
(set_attr "length" "4,8")])
@@ -1307,7 +1307,7 @@
(set (match_operand:SI 0 "dest_reg_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
- "ldb.x.a%V4 %3,[%0,%S2]"
+ "ldb.x.a%V4 %3,[%0,%2]"
[(set_attr "type" "load,load")
(set_attr "length" "4,8")])
@@ -1333,7 +1333,7 @@
(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
(plus:SI (match_dup 1) (match_dup 2)))]
""
- "ld%_.a%V4 %3,[%0,%S2]"
+ "ld%_.a%V4 %3,[%0,%2]"
[(set_attr "type" "load,load")
(set_attr "length" "4,8")])
@@ -1345,7 +1345,7 @@
(set (match_operand:SI 0 "dest_reg_operand" "=r,r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
- "ld%_.a%V4 %3,[%0,%S2]"
+ "ld%_.a%V4 %3,[%0,%2]"
[(set_attr "type" "load,load")
(set_attr "length" "4,8")])
@@ -1358,7 +1358,7 @@
(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
(plus:SI (match_dup 1) (match_dup 2)))]
""
- "ld%_.x.a%V4 %3,[%0,%S2]"
+ "ld%_.x.a%V4 %3,[%0,%2]"
[(set_attr "type" "load,load")
(set_attr "length" "4,8")])
@@ -1383,7 +1383,7 @@
(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
(plus:SI (match_dup 1) (match_dup 2)))]
""
- "ld.a%V4 %3,[%0,%S2]"
+ "ld.a%V4 %3,[%0,%2]"
[(set_attr "type" "load,load")
(set_attr "length" "4,8")])
@@ -1407,7 +1407,7 @@
(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
(plus:SI (match_dup 1) (match_dup 2)))]
""
- "ld.a%V4 %3,[%0,%S2]"
+ "ld.a%V4 %3,[%0,%2]"
[(set_attr "type" "load,load")
(set_attr "length" "4,8")])
@@ -1475,7 +1475,7 @@
&& rtx_equal_p (operands[1], constm1_rtx)
&& GET_CODE (operands[3]) == LTU)
return "sbc.cs %0,%0,%0";
- return "mov.%d3 %0,%S1";
+ return "mov.%d3 %0,%1";
}
[(set_attr "type" "cmove,cmove")
(set_attr "length" "4,8")])
@@ -3140,7 +3140,7 @@
"@
bset%? %0,%1,%2 ;;peep2, constr 1
bset %0,%1,%2 ;;peep2, constr 2
- bset %0,%S1,%2 ;;peep2, constr 3"
+ bset %0,%1,%2 ;;peep2, constr 3"
[(set_attr "length" "4,4,8")
(set_attr "predicable" "yes,no,no")
(set_attr "cond" "canuse,nocond,nocond")]
@@ -3156,7 +3156,7 @@
"@
bxor%? %0,%1,%2
bxor %0,%1,%2
- bxor %0,%S1,%2"
+ bxor %0,%1,%2"
[(set_attr "length" "4,4,8")
(set_attr "predicable" "yes,no,no")
(set_attr "cond" "canuse,nocond,nocond")]
@@ -3172,7 +3172,7 @@
"@
bclr%? %0,%1,%2
bclr %0,%1,%2
- bclr %0,%S1,%2"
+ bclr %0,%1,%2"
[(set_attr "length" "4,4,8")
(set_attr "predicable" "yes,no,no")
(set_attr "cond" "canuse,nocond,nocond")]
@@ -3188,9 +3188,9 @@
(const_int -1))))]
""
"@
- bmsk%? %0,%S1,%2
+ bmsk%? %0,%1,%2
bmsk %0,%1,%2
- bmsk %0,%S1,%2"
+ bmsk %0,%1,%2"
[(set_attr "length" "4,4,8")
(set_attr "predicable" "yes,no,no")
(set_attr "cond" "canuse,nocond,nocond")]
@@ -3302,10 +3302,10 @@
bic%? %0, %2, %1%& ;;constraint 0
bic%? %0,%2,%1 ;;constraint 1
bic %0,%2,%1 ;;constraint 2, FIXME: will it ever get generated ???
- bic%? %0,%2,%S1 ;;constraint 3, FIXME: will it ever get generated ???
+ bic%? %0,%2,%1 ;;constraint 3, FIXME: will it ever get generated ???
bic %0,%2,%1 ;;constraint 4
- bic %0,%2,%S1 ;;constraint 5, FIXME: will it ever get generated ???
- bic %0,%S2,%1 ;;constraint 6"
+ bic %0,%2,%1 ;;constraint 5, FIXME: will it ever get generated ???
+ bic %0,%2,%1 ;;constraint 6"
[(set_attr "length" "*,4,4,8,4,8,8")
(set_attr "iscompact" "maybe, false, false, false, false, false, false")
(set_attr "predicable" "no,yes,no,yes,no,no,no")
@@ -3636,7 +3636,7 @@
(compare:CC_C (match_operand:SI 0 "register_operand" "Rcqq,Rcqq, h, c,Rcqq, c")
(match_operand:SI 1 "nonmemory_operand" "cO, hO,Cm1,cI, Cal,Cal")))]
""
- "cmp%? %0,%S1%&"
+ "cmp%? %0,%1%&"
[(set_attr "type" "compare")
(set_attr "iscompact" "true,true,true,false,true_limm,false")
(set_attr "cond" "set")
@@ -3743,7 +3743,7 @@
* current_insn_predicate = 0; return \"mov%?.ne %0,%1\";
* current_insn_predicate = 0; return \"mov%?.ne %0,%1\";
mov.ne %0,%1
- mov.ne %0,%S1"
+ mov.ne %0,%1"
[(set_attr "type" "cmove")
(set_attr "iscompact" "true,true,true_limm,false,false")
(set_attr "length" "2,2,6,4,8")
@@ -3756,7 +3756,7 @@
(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
(match_operand:SI 1 "nonmemory_operand" "LRac,?Cal")))]
""
- "mov.%d3 %0,%S1"
+ "mov.%d3 %0,%1"
[(set_attr "type" "cmove")
(set_attr "length" "4,8")])
@@ -4224,13 +4224,12 @@
}
")
-
; Rcq, which is used in alternative 0, checks for conditional execution.
; 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_i"
[(call (mem:SI (match_operand:SI 0
- "call_address_operand" "Rcq,q,c,Cbp,Cbr,L,I,Cal"))
+ "call_address_operand" "Rcq,q,c,Cji,Cbp,Cbr,L,I,Cal"))
(match_operand 1 "" ""))
(clobber (reg:SI 31))]
""
@@ -4238,15 +4237,16 @@
jl%!%* [%0]%&
jl%!%* [%0]%&
jl%!%* [%0]
+ jli_s %S0
bl%!%* %P0
bl%!%* %P0
- jl%!%* %S0
- jl%* %S0
- jl%! %S0"
- [(set_attr "type" "call,call,call,call,call,call,call,call_no_delay_slot")
- (set_attr "iscompact" "maybe,false,*,*,*,*,*,*")
- (set_attr "predicable" "no,no,yes,yes,no,yes,no,yes")
- (set_attr "length" "*,*,4,4,4,4,4,8")])
+ 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")])
(define_expand "call_value"
;; operand 2 is stack_size_rtx
@@ -4268,14 +4268,13 @@
XEXP (operands[1], 0) = force_reg (Pmode, callee);
}")
-
; Rcq, which is used in alternative 0, checks for conditional execution.
; 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")
+ [(set (match_operand 0 "dest_reg_operand" "=Rcq,q,w, w, w, w,w,w, w")
(call (mem:SI (match_operand:SI 1
- "call_address_operand" "Rcq,q,c,Cbp,Cbr,L,I,Cal"))
+ "call_address_operand" "Rcq,q,c,Cji,Cbp,Cbr,L,I,Cal"))
(match_operand 2 "" "")))
(clobber (reg:SI 31))]
""
@@ -4283,15 +4282,16 @@
jl%!%* [%1]%&
jl%!%* [%1]%&
jl%!%* [%1]
+ jli_s %S1
bl%!%* %P1;1
bl%!%* %P1;1
- jl%!%* %S1
- jl%* %S1
- jl%! %S1"
- [(set_attr "type" "call,call,call,call,call,call,call,call_no_delay_slot")
- (set_attr "iscompact" "maybe,false,*,*,*,*,*,*")
- (set_attr "predicable" "no,no,yes,yes,no,yes,no,yes")
- (set_attr "length" "*,*,4,4,4,4,4,8")])
+ 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")])
; 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.
@@ -4465,7 +4465,7 @@
"TARGET_NORM"
"@
norm \t%0, %1
- norm \t%0, %S1"
+ norm \t%0, %1"
[(set_attr "length" "4,8")
(set_attr "type" "two_cycle_core,two_cycle_core")])
@@ -4477,7 +4477,7 @@
"TARGET_NORM"
"@
norm.f\t%0, %1
- norm.f\t%0, %S1"
+ norm.f\t%0, %1"
[(set_attr "length" "4,8")
(set_attr "type" "two_cycle_core,two_cycle_core")])
@@ -4497,7 +4497,7 @@
"TARGET_NORM"
"@
norm%_ \t%0, %1
- norm%_ \t%0, %S1"
+ norm%_ \t%0, %1"
[(set_attr "length" "4,8")
(set_attr "type" "two_cycle_core,two_cycle_core")])
@@ -4586,7 +4586,7 @@
"TARGET_SWAP"
"@
swap \t%0, %1
- swap \t%0, %S1
+ swap \t%0, %1
swap \t%0, %1"
[(set_attr "length" "4,8,4")
(set_attr "type" "two_cycle_core,two_cycle_core,two_cycle_core")])
@@ -4599,8 +4599,8 @@
"TARGET_ARC700 || TARGET_EA_SET"
"@
divaw \t%0, %1, %2
- divaw \t%0, %S1, %2
- divaw \t%0, %1, %S2"
+ divaw \t%0, %1, %2
+ divaw \t%0, %1, %2"
[(set_attr "length" "4,8,8")
(set_attr "type" "divaw,divaw,divaw")])
@@ -4611,7 +4611,7 @@
"@
flag%? %0
flag %0
- flag%? %S0"
+ flag%? %0"
[(set_attr "length" "4,4,8")
(set_attr "type" "misc,misc,misc")
(set_attr "predicable" "yes,no,yes")
@@ -4705,7 +4705,7 @@
(match_operand:SI 1 "general_operand" "Ir,I,HCal,r")]
VUNSPEC_ARC_SR)]
""
- "sr\t%S0, [%1]"
+ "sr\t%0, [%1]"
[(set_attr "length" "8,4,8,4")
(set_attr "type" "sr,sr,sr,sr")])
@@ -5281,7 +5281,7 @@
;; ??? Should this use arc_output_libcall and set is_sfunc?
(define_insn "*millicode_thunk_st"
[(match_parallel 0 "millicode_store_operation"
- [(set (mem:SI (reg:SI SP_REG)) (reg:SI 13))])]
+ [(set (mem:SI (reg:SI SP_REG)) (reg:SI 13))])]
""
{
output_asm_insn ("bl%* __st_r13_to_%0",
@@ -5293,7 +5293,7 @@
(define_insn "*millicode_thunk_ld"
[(match_parallel 0 "millicode_load_clob_operation"
- [(set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])]
+ [(set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])]
""
{
output_asm_insn ("bl%* __ld_r13_to_%0",
@@ -5306,9 +5306,9 @@
; the sibthunk restores blink, so we use the return rtx.
(define_insn "*millicode_sibthunk_ld"
[(match_parallel 0 "millicode_load_operation"
- [(return)
- (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (reg:SI 12)))
- (set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])]
+ [(return)
+ (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (reg:SI 12)))
+ (set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])]
""
{
output_asm_insn ("b%* __ld_r13_to_%0_ret",
@@ -5627,7 +5627,7 @@
"@
kflag%? %0
kflag %0
- kflag%? %S0"
+ kflag%? %0"
[(set_attr "length" "4,4,8")
(set_attr "type" "misc,misc,misc")
(set_attr "predicable" "yes,no,yes")
@@ -5649,7 +5649,7 @@
"TARGET_NORM && TARGET_V2"
"@
ffs \t%0, %1
- ffs \t%0, %S1"
+ ffs \t%0, %1"
[(set_attr "length" "4,8")
(set_attr "type" "two_cycle_core,two_cycle_core")])
@@ -5662,7 +5662,7 @@
"TARGET_NORM && TARGET_V2"
"@
ffs.f\t%0, %1
- ffs.f\t%0, %S1"
+ ffs.f\t%0, %1"
[(set_attr "length" "4,8")
(set_attr "type" "two_cycle_core,two_cycle_core")])
@@ -5689,7 +5689,7 @@
"TARGET_NORM && TARGET_V2"
"@
fls \t%0, %1
- fls \t%0, %S1"
+ fls \t%0, %1"
[(set_attr "length" "4,8")
(set_attr "type" "two_cycle_core,two_cycle_core")])
@@ -53,6 +53,10 @@ mARC700
Target Report
Same as -mA7.
+mjli-always
+Target Report Mask(JLI_ALWAYS)
+Force all calls to be made via a jli instruction.
+
mmpy-option=
Target RejectNegative Joined Enum(arc_mpy) Var(arc_mpy_option) Init(DEFAULT_arc_mpy_option)
-mmpy-option=MPY Compile ARCv2 code with a multiplier design option.
@@ -401,6 +401,12 @@
(match_test "arc_is_shortcall_p (op)"))
(match_code "label_ref")))
+(define_constraint "Cji"
+ "JLI call"
+ (and (match_code "symbol_ref")
+ (match_test "TARGET_CODE_DENSITY")
+ (match_test "arc_is_jli_call_p (op)")))
+
(define_constraint "Cpc"
"pc-relative constant"
(match_test "arc_legitimate_pic_addr_p (op)"))
@@ -66,3 +66,6 @@ along with GCC; see the file COPYING3. If not see
/* Pre/post modify with register displacement are default. */
#undef TARGET_AUTO_MODIFY_REG_DEFAULT
#define TARGET_AUTO_MODIFY_REG_DEFAULT 1
+
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END arc_file_end
@@ -59,9 +59,9 @@
"@
fadd %0,%1,%2
fadd %0,%1,%2
- fadd %0,%S1,%2
- fadd %0,%1,%S2
- fadd%? %0,%1,%S2"
+ fadd %0,%1,%2
+ fadd %0,%1,%2
+ fadd%? %0,%1,%2"
[(set_attr "type" "spfp")
(set_attr "length" "4,4,8,8,8")])
@@ -74,9 +74,9 @@
"@
fsub %0,%1,%2
fsub %0,%1,%2
- fsub %0,%S1,%2
- fsub %0,%1,%S2
- fsub%? %0,%1,%S2"
+ fsub %0,%1,%2
+ fsub %0,%1,%2
+ fsub%? %0,%1,%2"
[(set_attr "type" "spfp")
(set_attr "length" "4,4,8,8,8")])
@@ -89,9 +89,9 @@
"@
fmul %0,%1,%2
fmul %0,%1,%2
- fmul %0,%S1,%2
- fmul %0,%1,%S2
- fmul%? %0,%1,%S2"
+ fmul %0,%1,%2
+ fmul %0,%1,%2
+ fmul%? %0,%1,%2"
[(set_attr "type" "spfp")
(set_attr "length" "4,4,8,8,8")])
@@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see
%{shared:-lc} \
%{!shared:%{profile:-lc_p}%{!profile:-lc}}"
+#undef TARGET_ASM_FILE_END
#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
/* No SDATA default for linux. */
@@ -1190,7 +1190,7 @@
(define_insn "vendrec_insn"
[(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "r")] UNSPEC_ARC_SIMD_VENDREC)]
"TARGET_SIMD_SET"
- "vendrec %S0"
+ "vendrec %0"
[(set_attr "type" "simd_vcontrol")
(set_attr "length" "4")
(set_attr "cond" "nocond")])
@@ -3751,6 +3751,16 @@ the call site. A function marked with the @code{short_call}
attribute will always be close enough to be called with a conditional
branch-and-link instruction, which has a 21-bit offset from
the call site.
+
+@item jli_always
+@cindex @code{jli_always} function attribute, ARC
+Forces the particular function to be called using jli instruction.
+
+@item jli_fixed
+@cindex @code{jli_fixed} function attribute, ARC
+Identical like the above one, but the location of the function in the
+JLI table is known and given as an attribute parameter.
+
@end table
@node ARM Function Attributes
@@ -608,7 +608,7 @@ Objective-C and Objective-C++ Dialects}.
-msplit-vecmove-early -m1reg-@var{reg}}
@emph{ARC Options}
-@gccoptlist{-mbarrel-shifter @gol
+@gccoptlist{-mbarrel-shifter -mjli-always @gol
-mcpu=@var{cpu} -mA6 -mARC600 -mA7 -mARC700 @gol
-mdpfp -mdpfp-compact -mdpfp-fast -mno-dpfp-lrsr @gol
-mea -mno-mpy -mmul32x16 -mmul64 -matomic @gol
@@ -14622,6 +14622,11 @@ is being compiled:
Generate instructions supported by barrel shifter. This is the default
unless @option{-mcpu=ARC601} or @samp{-mcpu=ARCEM} is in effect.
+@item -mjli-always
+@opindex mjli-alawys
+Force to call a function using jli_s instruction. This option is
+valid only for ARCv2 architecture.
+
@item -mcpu=@var{cpu}
@opindex mcpu
Set architecture type, register usage, and instruction scheduling
new file mode 100644
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-skip-if "jli only available for ARCv2" { arc700 || arc6xx } } */
+/* { dg-options "-O0 -mcode-density" } */
+
+int func(int i) __attribute__((jli_always));
+
+int func(int i)
+{
+ return i*i;
+}
+
+int main()
+{
+ return func(100);
+}
+
+/* { dg-final { scan-assembler "jli_s @__jli.func" } } */
+/* { dg-final { scan-assembler ".weak __jli.func" } } */
+/* { dg-final { scan-assembler "b\\\s+@func" } } */
new file mode 100644
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-skip-if "jli only available for ARCv2" { arc700 || arc6xx } } */
+/* { dg-options "-O0 -mcode-density" } */
+
+int func(int i) __attribute__((jli_fixed(2)));
+
+int func(int i)
+{
+ return i*i;
+}
+
+int main()
+{
+ return func(100);
+}
+
+/* { dg-final { scan-assembler "jli_s 2" } } */
+/* { dg-final { scan-assembler-not ".weak __jli.func" } } */
+/* { dg-final { scan-assembler-not "b\\\s+@func" } } */