This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 1/6] [ARC] Add JLI support.


The ARCv2 ISA provides the JLI instruction, which is two-byte instructions
that can be used to reduce code size in an application. To make use of it,
we provide two new function attributes 'jli_always' and 'jli_fixed' which
will force the compiler to call the indicated function using a jli_s
instruction. The compiler also generates the entries in the JLI table for
the case when we use 'jli_always' attribute. In the case of 'jli_fixed'
the compiler assumes a fixed position of the function into JLI
table. Thus, the user needs to provide an assembly file with the JLI table
for the final link. This is usefully when we want to have a table in ROM
and a second table in the RAM memory.

The jli instruction usage can be also forced without the need to annotate
the source code via '-mjli-always' command.

gcc/
2017-02-10  Claudiu Zissulescu  <claziss@synopsys.com>
	    John Eric Martin <John.Martin@emmicro-us.com>

	* config/arc/arc-protos.h: Add arc_is_jli_call_p proto.
	* config/arc/arc.c (_arc_jli_section): New struct.
	(arc_jli_section): New type.
	(rc_jli_sections): New static variable.
	(arc_handle_jli_attribute): New function.
	(arc_attribute_table): Add jli_always and jli_fixed attribute.
	(arc_file_end): New function.
	(TARGET_ASM_FILE_END): Define.
	(arc_print_operand): Reuse 'S' letter for JLI output instruction.
	(arc_add_jli_section): New function.
	(jli_call_scan): Likewise.
	(arc_reorg): Call jli_call_scan.
	(arc_output_addsi): Remove 'S' from printing asm operand.
	(arc_is_jli_call_p): New function.
	* config/arc/arc.md (movqi_insn): Remove 'S' from printing asm
	operand.
	(movhi_insn): Likewise.
	(movsi_insn): Likewise.
	(movsi_set_cc_insn): Likewise.
	(loadqi_update): Likewise.
	(load_zeroextendqisi_update): Likewise.
	(load_signextendqisi_update): Likewise.
	(loadhi_update): Likewise.
	(load_zeroextendhisi_update): Likewise.
	(load_signextendhisi_update): Likewise.
	(loadsi_update): Likewise.
	(loadsf_update): Likewise.
	(movsicc_insn): Likewise.
	(bset_insn): Likewise.
	(bxor_insn): Likewise.
	(bclr_insn): Likewise.
	(bmsk_insn): Likewise.
	(bicsi3_insn): Likewise.
	(cmpsi_cc_c_insn): Likewise.
	(movsi_ne): Likewise.
	(movsi_cond_exec): Likewise.
	(clrsbsi2): Likewise.
	(norm_f): Likewise.
	(normw): Likewise.
	(swap): Likewise.
	(divaw): Likewise.
	(flag): Likewise.
	(sr): Likewise.
	(kflag): Likewise.
	(ffs): Likewise.
	(ffs_f): Likewise.
	(fls): Likewise.
	(call_i): Remove 'S' asm letter, add jli instruction.
	(call_value_i): Likewise.
	* config/arc/arc.op (mjli-always): New option.
	* config/arc/constraints.md (Cji): New constraint.
	* config/arc/fpx.md (addsf3_fpx): Remove 'S' from printing asm
	operand.
	(subsf3_fpx): Likewise.
	(mulsf3_fpx): Likewise.
	* config/arc/simdext.md (vendrec_insn): Remove 'S' from printing
	asm operand.
	* doc/extend.texi (ARC): Document 'jli-always' and 'jli-fixed'
	function attrbutes.
	* doc/invoke.texi (ARC): Document mjli-always option.

gcc/testsuite
2017-02-10  Claudiu Zissulescu  <claziss@synopsys.com>

	* gcc.target/arc/jli-1.c: New file.
	* gcc.target/arc/jli-2.c: Likewise.
---
 gcc/config/arc/arc-protos.h          |   2 +
 gcc/config/arc/arc.c                 | 220 ++++++++++++++++++++++++++++++++++-
 gcc/config/arc/arc.md                | 128 ++++++++++----------
 gcc/config/arc/arc.opt               |   4 +
 gcc/config/arc/constraints.md        |   6 +
 gcc/config/arc/elf.h                 |   3 +
 gcc/config/arc/fpx.md                |  18 +--
 gcc/config/arc/linux.h               |   1 +
 gcc/config/arc/simdext.md            |   2 +-
 gcc/doc/extend.texi                  |  10 ++
 gcc/doc/invoke.texi                  |   7 +-
 gcc/testsuite/gcc.target/arc/jli-1.c |  19 +++
 gcc/testsuite/gcc.target/arc/jli-2.c |  19 +++
 13 files changed, 358 insertions(+), 81 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arc/jli-1.c
 create mode 100644 gcc/testsuite/gcc.target/arc/jli-2.c

diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
index 6e7239f..1557293 100644
--- a/gcc/config/arc/arc-protos.h
+++ b/gcc/config/arc/arc-protos.h
@@ -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);
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index e35d198..489cb91 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -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,
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 43a962f..c72420c 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -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")])
 
diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
index d1ebd44..9baaf77 100644
--- a/gcc/config/arc/arc.opt
+++ b/gcc/config/arc/arc.opt
@@ -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.
diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
index b8a4a90..7114e6e 100644
--- a/gcc/config/arc/constraints.md
+++ b/gcc/config/arc/constraints.md
@@ -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)"))
diff --git a/gcc/config/arc/elf.h b/gcc/config/arc/elf.h
index 43f3408..175e9fd 100644
--- a/gcc/config/arc/elf.h
+++ b/gcc/config/arc/elf.h
@@ -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
diff --git a/gcc/config/arc/fpx.md b/gcc/config/arc/fpx.md
index 990b3a8..2daab44 100644
--- a/gcc/config/arc/fpx.md
+++ b/gcc/config/arc/fpx.md
@@ -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")])
 
diff --git a/gcc/config/arc/linux.h b/gcc/config/arc/linux.h
index d8e0063..8abc2c6 100644
--- a/gcc/config/arc/linux.h
+++ b/gcc/config/arc/linux.h
@@ -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.  */
diff --git a/gcc/config/arc/simdext.md b/gcc/config/arc/simdext.md
index 9f5b4a8..32a9638 100644
--- a/gcc/config/arc/simdext.md
+++ b/gcc/config/arc/simdext.md
@@ -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")])
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 8aa443f..1e16d06 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -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
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 1533a12..041be9a 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -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
diff --git a/gcc/testsuite/gcc.target/arc/jli-1.c b/gcc/testsuite/gcc.target/arc/jli-1.c
new file mode 100644
index 0000000..f7259b3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/jli-1.c
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.target/arc/jli-2.c b/gcc/testsuite/gcc.target/arc/jli-2.c
new file mode 100644
index 0000000..96a35a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/jli-2.c
@@ -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" } } */
-- 
1.9.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]