public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/4] arc: Add GNU/Linux support
@ 2020-03-26 12:52 Shahab Vahedi
  2020-03-26 12:52 ` [PATCH 1/4] arc: Add XML target features for Linux targets Shahab Vahedi
                   ` (9 more replies)
  0 siblings, 10 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-03-26 12:52 UTC (permalink / raw)
  To: gdb-patches; +Cc: Shahab Vahedi, Shahab Vahedi, Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

This is a series of changes to enable debugging ARC targets that are
running on a native ARC GNU/Linux system.  Most of these changes are
related to how registers are slightly handled differently compared
to a baremetal scenario.  Each commit illustrate further on those.

After this series, there will come patches that add support for
native ARC gdb/gdbserver.

Anton Kolesov (4):
  arc: Add XML target features for Linux targets
  arc: Recognize registers available on Linux targets
  arc: Add GNU/Linux support for ARC
  arc: Add arc-*-linux regformats

 gdb/Makefile.in                           |   1 +
 gdb/arc-linux-tdep.c                      | 284 ++++++++++++++++++++++
 gdb/arc-tdep.c                            |  84 +++++--
 gdb/arc-tdep.h                            |  22 +-
 gdb/arch/arc.c                            |  40 ++-
 gdb/arch/arc.h                            |  18 +-
 gdb/configure.tgt                         |   6 +
 gdb/doc/gdb.texinfo                       |   3 +-
 gdb/features/Makefile                     |   8 +-
 gdb/features/arc/aux-arcompact-linux.c    |  34 +++
 gdb/features/arc/aux-arcompact-linux.xml  |  31 +++
 gdb/features/arc/aux-v2-linux.c           |  38 +++
 gdb/features/arc/aux-v2-linux.xml         |  35 +++
 gdb/features/arc/core-arcompact-linux.c   |  45 ++++
 gdb/features/arc/core-arcompact-linux.xml |  56 +++++
 gdb/features/arc/core-v2-linux.c          |  48 ++++
 gdb/features/arc/core-v2-linux.xml        |  58 +++++
 gdb/regformats/arc-arcompact-linux.dat    |  42 ++++
 gdb/regformats/arc-v2-linux.dat           |  45 ++++
 19 files changed, 859 insertions(+), 39 deletions(-)
 create mode 100644 gdb/arc-linux-tdep.c
 create mode 100644 gdb/features/arc/aux-arcompact-linux.c
 create mode 100644 gdb/features/arc/aux-arcompact-linux.xml
 create mode 100644 gdb/features/arc/aux-v2-linux.c
 create mode 100644 gdb/features/arc/aux-v2-linux.xml
 create mode 100644 gdb/features/arc/core-arcompact-linux.c
 create mode 100644 gdb/features/arc/core-arcompact-linux.xml
 create mode 100644 gdb/features/arc/core-v2-linux.c
 create mode 100644 gdb/features/arc/core-v2-linux.xml
 create mode 100644 gdb/regformats/arc-arcompact-linux.dat
 create mode 100644 gdb/regformats/arc-v2-linux.dat

-- 
2.26.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH 1/4] arc: Add XML target features for Linux targets
  2020-03-26 12:52 [PATCH 0/4] arc: Add GNU/Linux support Shahab Vahedi
@ 2020-03-26 12:52 ` Shahab Vahedi
  2020-04-24 13:46   ` Tom Tromey
  2020-03-26 12:52 ` [PATCH 2/4] arc: Recognize registers available on " Shahab Vahedi
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-03-26 12:52 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Anton Kolesov, Francois Bedard,
	Anton Kolesov

From: Anton Kolesov <Anton.Kolesov@synopsys.com>

Add XML target features for Linux targets.  Compared to default
Linux features:

- Explicitly specify CPU machine.
- Remove baremetal only ILINK{,1,2} registers.
- Add LP_START and LP_END registers for hardware loops - required to
  properly evaluate possible next instruction during software single
  instruction stepping.
- Add BTA register which contains branch target address - address of
  next instruction when processor is in the delay slot.
- ARC HS description also adds R30, R58 and R59 registers, specific to
  this architecture.

gdb/ChangeLog:
2020-03-26  Anton Kolesov  <anton.kolesov@synopsys.com>

	* arch/arc.h (arc_create_target_description): Support Linux targets.
	* arch/arc.c (arc_create_target_description): Likewise.
	* arc-tdep.c (arc_tdesc_init): Update invocation of
	  arc_read_description.
	* features/Makefile (FEATURE_XMLFILES): Add new files.
	* features/arc/aux-arcompact-linux.xml: New file.
	* features/arc/aux-v2-linux.xml: Likewise.
	* features/arc/core-arcompact-linux.xml: Likewise.
	* features/arc/core-v2-linux.xml: Likewise.
	* features/arc/aux-arcompact-linux.c: Generate.
	* features/arc/aux-v2-linux.c: Likewise.
	* features/arc/core-arcompact-linux.c: Likewise.
	* features/arc/core-v2-linux.c: Likewise.
---
 gdb/arc-tdep.c                            |  4 +-
 gdb/arch/arc.c                            | 40 ++++++++++++----
 gdb/arch/arc.h                            | 18 ++++---
 gdb/features/Makefile                     |  4 ++
 gdb/features/arc/aux-arcompact-linux.c    | 34 +++++++++++++
 gdb/features/arc/aux-arcompact-linux.xml  | 31 ++++++++++++
 gdb/features/arc/aux-v2-linux.c           | 38 +++++++++++++++
 gdb/features/arc/aux-v2-linux.xml         | 35 ++++++++++++++
 gdb/features/arc/core-arcompact-linux.c   | 45 ++++++++++++++++++
 gdb/features/arc/core-arcompact-linux.xml | 56 ++++++++++++++++++++++
 gdb/features/arc/core-v2-linux.c          | 48 +++++++++++++++++++
 gdb/features/arc/core-v2-linux.xml        | 58 +++++++++++++++++++++++
 12 files changed, 394 insertions(+), 17 deletions(-)
 create mode 100644 gdb/features/arc/aux-arcompact-linux.c
 create mode 100644 gdb/features/arc/aux-arcompact-linux.xml
 create mode 100644 gdb/features/arc/aux-v2-linux.c
 create mode 100644 gdb/features/arc/aux-v2-linux.xml
 create mode 100644 gdb/features/arc/core-arcompact-linux.c
 create mode 100644 gdb/features/arc/core-arcompact-linux.xml
 create mode 100644 gdb/features/arc/core-v2-linux.c
 create mode 100644 gdb/features/arc/core-v2-linux.xml

diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 3020099c335..a4f3f44b4fb 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -1756,9 +1756,9 @@ arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
   if (!tdesc_has_registers (tdesc_loc))
     {
       if (is_arcv2)
-	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCV2);
+	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCV2_BMT);
       else
-	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCOMPACT);
+	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCOMPACT_BMT);
     }
   else
     {
diff --git a/gdb/arch/arc.c b/gdb/arch/arc.c
index 9552b4aff97..0babbf8a36a 100644
--- a/gdb/arch/arc.c
+++ b/gdb/arch/arc.c
@@ -24,8 +24,12 @@
 /* Target description features.  */
 #include "features/arc/core-v2.c"
 #include "features/arc/aux-v2.c"
+#include "features/arc/core-v2-linux.c"
+#include "features/arc/aux-v2-linux.c"
 #include "features/arc/core-arcompact.c"
 #include "features/arc/aux-arcompact.c"
+#include "features/arc/core-arcompact-linux.c"
+#include "features/arc/aux-arcompact-linux.c"
 
 /* See arc.h.  */
 
@@ -37,21 +41,39 @@ arc_create_target_description (arc_sys_type sys_type)
   long regnum = 0;
 
 #ifndef IN_PROCESS_AGENT
-  if (sys_type == ARC_SYS_TYPE_ARCV2)
+  if (sys_type == ARC_SYS_TYPE_ARCV2_BMT)
     set_tdesc_architecture (tdesc, "arc:ARCv2");
+  else if (sys_type == ARC_SYS_TYPE_ARCV2_LNX)
+    /* If this is ARCv2 Linux, then it is ARC HS.  */
+    set_tdesc_architecture (tdesc, "arc:HS");
   else
     set_tdesc_architecture (tdesc, "arc:ARC700");
+
+  if (sys_type == ARC_SYS_TYPE_ARCOMPACT_LNX
+      || sys_type == ARC_SYS_TYPE_ARCV2_LNX)
+    set_tdesc_osabi (tdesc, "GNU/Linux");
 #endif
 
-  if (sys_type == ARC_SYS_TYPE_ARCV2)
-    {
-      regnum = create_feature_arc_core_v2 (tdesc, regnum);
-      regnum = create_feature_arc_aux_v2 (tdesc, regnum);
-    }
-  else
+  switch (sys_type)
     {
-      regnum = create_feature_arc_core_arcompact (tdesc, regnum);
-      regnum = create_feature_arc_aux_arcompact (tdesc, regnum);
+    case ARC_SYS_TYPE_ARCOMPACT_BMT:
+	  regnum = create_feature_arc_core_arcompact (tdesc, regnum);
+	  regnum = create_feature_arc_aux_arcompact (tdesc, regnum);
+	  break;
+    case ARC_SYS_TYPE_ARCOMPACT_LNX:
+	  regnum = create_feature_arc_core_arcompact_linux (tdesc, regnum);
+	  regnum = create_feature_arc_aux_arcompact_linux (tdesc, regnum);
+	  break;
+    case ARC_SYS_TYPE_ARCV2_BMT:
+	  regnum = create_feature_arc_core_v2 (tdesc, regnum);
+	  regnum = create_feature_arc_aux_v2 (tdesc, regnum);
+	  break;
+    case ARC_SYS_TYPE_ARCV2_LNX:
+	  regnum = create_feature_arc_core_v2_linux (tdesc, regnum);
+	  regnum = create_feature_arc_aux_v2_linux (tdesc, regnum);
+	  break;
+    default:
+	  gdb_assert(!"Invalid arc_sys_type.");
     }
 
   return tdesc;
diff --git a/gdb/arch/arc.h b/gdb/arch/arc.h
index fd806ae7d34..3c19118b946 100644
--- a/gdb/arch/arc.h
+++ b/gdb/arch/arc.h
@@ -23,8 +23,10 @@
 /* Supported ARC system hardware types.  */
 enum arc_sys_type
 {
-  ARC_SYS_TYPE_ARCOMPACT = 0,	  /* ARC600 or ARC700 */
-  ARC_SYS_TYPE_ARCV2,		  /* ARC EM or ARC HS */
+  ARC_SYS_TYPE_ARCOMPACT_BMT = 0, /* ARC600 or ARC700 (baremetal) */
+  ARC_SYS_TYPE_ARCOMPACT_LNX,	  /* ARC600 or ARC700 (linux) */
+  ARC_SYS_TYPE_ARCV2_BMT,	  /* ARC EM or ARC HS (baremetal) */
+  ARC_SYS_TYPE_ARCV2_LNX,	  /* ARC HS (linux) */
   ARC_SYS_TYPE_NUM
 };
 
@@ -33,10 +35,14 @@ arc_sys_type_to_str (const arc_sys_type type)
 {
   switch (type)
     {
-    case ARC_SYS_TYPE_ARCOMPACT:
-      return "ARC_SYS_TYPE_ARCOMPACT";
-    case ARC_SYS_TYPE_ARCV2:
-      return "ARC_SYS_TYPE_ARCV2";
+    case ARC_SYS_TYPE_ARCOMPACT_BMT:
+      return "ARC_SYS_TYPE_ARCOMPACT_BMT";
+    case ARC_SYS_TYPE_ARCOMPACT_LNX:
+      return "ARC_SYS_TYPE_ARCOMPACT_LNX";
+    case ARC_SYS_TYPE_ARCV2_BMT:
+      return "ARC_SYS_TYPE_ARCV2_BMT";
+    case ARC_SYS_TYPE_ARCV2_LNX:
+      return "ARC_SYS_TYPE_ARCV2_LNX";
     default:
       return "Invalid";
     }
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index cc65baa6eda..a95be667dc1 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -206,8 +206,12 @@ FEATURE_XMLFILES = aarch64-core.xml \
 	aarch64-pauth.xml \
 	arc/core-v2.xml \
 	arc/aux-v2.xml \
+	arc/core-v2-linux.xml \
+	arc/aux-v2-linux.xml \
 	arc/core-arcompact.xml \
 	arc/aux-arcompact.xml \
+	arc/core-arcompact-linux.xml \
+	arc/aux-arcompact-linux.xml \
 	arm/arm-core.xml \
 	arm/arm-fpa.xml \
 	arm/arm-m-profile.xml \
diff --git a/gdb/features/arc/aux-arcompact-linux.c b/gdb/features/arc/aux-arcompact-linux.c
new file mode 100644
index 00000000000..41f26c1e2ec
--- /dev/null
+++ b/gdb/features/arc/aux-arcompact-linux.c
@@ -0,0 +1,34 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: aux-arcompact-linux.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_arc_aux_arcompact_linux (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux-minimal");
+  tdesc_type_with_fields *type_with_fields;
+  type_with_fields = tdesc_create_flags (feature, "status32_type", 4);
+  tdesc_add_flag (type_with_fields, 0, "H");
+  tdesc_add_bitfield (type_with_fields, "E", 1, 2);
+  tdesc_add_bitfield (type_with_fields, "A", 3, 4);
+  tdesc_add_flag (type_with_fields, 5, "AE");
+  tdesc_add_flag (type_with_fields, 6, "DE");
+  tdesc_add_flag (type_with_fields, 7, "U");
+  tdesc_add_flag (type_with_fields, 8, "V");
+  tdesc_add_flag (type_with_fields, 9, "C");
+  tdesc_add_flag (type_with_fields, 10, "N");
+  tdesc_add_flag (type_with_fields, 11, "Z");
+  tdesc_add_flag (type_with_fields, 12, "L");
+  tdesc_add_flag (type_with_fields, 13, "R");
+  tdesc_add_flag (type_with_fields, 14, "SE");
+
+  tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "status32", regnum++, 1, NULL, 32, "status32_type");
+  tdesc_create_reg (feature, "lp_start", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "lp_end", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "bta", regnum++, 1, NULL, 32, "code_ptr");
+  return regnum;
+}
diff --git a/gdb/features/arc/aux-arcompact-linux.xml b/gdb/features/arc/aux-arcompact-linux.xml
new file mode 100644
index 00000000000..0d72373eda3
--- /dev/null
+++ b/gdb/features/arc/aux-arcompact-linux.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2020 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.arc.aux-minimal">
+  <flags id="status32_type" size="4">
+      <field name="H"   start="0" end="0"/>
+      <field name="E"   start="1" end="2"/>
+      <field name="A"   start="3" end="4"/>
+      <field name="AE"  start="5" end="5"/>
+      <field name="DE"  start="6" end="6"/>
+      <field name="U"   start="7" end="7"/>
+      <field name="V"   start="8" end="8"/>
+      <field name="C"   start="9" end="9"/>
+      <field name="N"   start="10" end="10"/>
+      <field name="Z"   start="11" end="11"/>
+      <field name="L"   start="12" end="12"/>
+      <field name="R"  start="13" end="13"/>
+      <field name="SE"  start="14" end="14"/>
+  </flags>
+
+  <reg name="pc"       bitsize="32" type="code_ptr"/>
+  <reg name="status32" bitsize="32" type="status32_type"/>
+  <reg name="lp_start" bitsize="32" type="code_ptr"/>
+  <reg name="lp_end"   bitsize="32" type="code_ptr"/>
+  <reg name="bta"      bitsize="32" type="code_ptr"/>
+</feature>
diff --git a/gdb/features/arc/aux-v2-linux.c b/gdb/features/arc/aux-v2-linux.c
new file mode 100644
index 00000000000..6e4d7c02efa
--- /dev/null
+++ b/gdb/features/arc/aux-v2-linux.c
@@ -0,0 +1,38 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: aux-v2-linux.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_arc_aux_v2_linux (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux-minimal");
+  tdesc_type_with_fields *type_with_fields;
+  type_with_fields = tdesc_create_flags (feature, "status32_type", 4);
+  tdesc_add_flag (type_with_fields, 0, "H");
+  tdesc_add_bitfield (type_with_fields, "E", 1, 4);
+  tdesc_add_flag (type_with_fields, 5, "AE");
+  tdesc_add_flag (type_with_fields, 6, "DE");
+  tdesc_add_flag (type_with_fields, 7, "U");
+  tdesc_add_flag (type_with_fields, 8, "V");
+  tdesc_add_flag (type_with_fields, 9, "C");
+  tdesc_add_flag (type_with_fields, 10, "N");
+  tdesc_add_flag (type_with_fields, 11, "Z");
+  tdesc_add_flag (type_with_fields, 12, "L");
+  tdesc_add_flag (type_with_fields, 13, "DZ");
+  tdesc_add_flag (type_with_fields, 14, "SC");
+  tdesc_add_flag (type_with_fields, 15, "ES");
+  tdesc_add_bitfield (type_with_fields, "RB", 16, 18);
+  tdesc_add_flag (type_with_fields, 19, "AD");
+  tdesc_add_flag (type_with_fields, 20, "US");
+  tdesc_add_flag (type_with_fields, 31, "IE");
+
+  tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "status32", regnum++, 1, NULL, 32, "status32_type");
+  tdesc_create_reg (feature, "lp_start", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "lp_end", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "bta", regnum++, 1, NULL, 32, "code_ptr");
+  return regnum;
+}
diff --git a/gdb/features/arc/aux-v2-linux.xml b/gdb/features/arc/aux-v2-linux.xml
new file mode 100644
index 00000000000..165ebb1d6d6
--- /dev/null
+++ b/gdb/features/arc/aux-v2-linux.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2020 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.arc.aux-minimal">
+  <flags id="status32_type" size="4">
+      <field name="H"   start="0" end="0"/>
+      <field name="E"   start="1" end="4"/>
+      <field name="AE"  start="5" end="5"/>
+      <field name="DE"  start="6" end="6"/>
+      <field name="U"   start="7" end="7"/>
+      <field name="V"   start="8" end="8"/>
+      <field name="C"   start="9" end="9"/>
+      <field name="N"   start="10" end="10"/>
+      <field name="Z"   start="11" end="11"/>
+      <field name="L"   start="12" end="12"/>
+      <field name="DZ"  start="13" end="13"/>
+      <field name="SC"  start="14" end="14"/>
+      <field name="ES"  start="15" end="15"/>
+      <field name="RB"  start="16" end="18"/>
+      <field name="AD"  start="19" end="19"/>
+      <field name="US"  start="20" end="20"/>
+      <field name="IE"  start="31" end="31"/>
+  </flags>
+
+  <reg name="pc"       bitsize="32" type="code_ptr"/>
+  <reg name="status32" bitsize="32" type="status32_type"/>
+  <reg name="lp_start" bitsize="32" type="code_ptr"/>
+  <reg name="lp_end"   bitsize="32" type="code_ptr"/>
+  <reg name="bta"      bitsize="32" type="code_ptr"/>
+</feature>
diff --git a/gdb/features/arc/core-arcompact-linux.c b/gdb/features/arc/core-arcompact-linux.c
new file mode 100644
index 00000000000..c870413e922
--- /dev/null
+++ b/gdb/features/arc/core-arcompact-linux.c
@@ -0,0 +1,45 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: core-arcompact-linux.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_arc_core_arcompact_linux (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core.arcompact");
+  tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r3", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r4", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r5", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r6", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r7", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r8", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r9", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r10", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r11", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r12", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r13", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r14", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r15", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r16", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r17", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r18", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r19", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r20", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r21", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r22", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r23", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r24", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r25", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "gp", regnum++, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "fp", regnum++, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "blink", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "lp_count", regnum++, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "pcl", regnum++, 1, NULL, 32, "code_ptr");
+  return regnum;
+}
diff --git a/gdb/features/arc/core-arcompact-linux.xml b/gdb/features/arc/core-arcompact-linux.xml
new file mode 100644
index 00000000000..9b2865d32be
--- /dev/null
+++ b/gdb/features/arc/core-arcompact-linux.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2020 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.arc.core.arcompact">
+  <reg name="r0"  bitsize="32"/>
+  <reg name="r1"  bitsize="32"/>
+  <reg name="r2"  bitsize="32"/>
+  <reg name="r3"  bitsize="32"/>
+  <reg name="r4"  bitsize="32"/>
+  <reg name="r5"  bitsize="32"/>
+  <reg name="r6"  bitsize="32"/>
+  <reg name="r7"  bitsize="32"/>
+  <reg name="r8"  bitsize="32"/>
+  <reg name="r9"  bitsize="32"/>
+  <reg name="r10" bitsize="32"/>
+  <reg name="r11" bitsize="32"/>
+  <reg name="r12" bitsize="32"/>
+  <reg name="r13" bitsize="32"/>
+  <reg name="r14" bitsize="32"/>
+  <reg name="r15" bitsize="32"/>
+  <reg name="r16" bitsize="32"/>
+  <reg name="r17" bitsize="32"/>
+  <reg name="r18" bitsize="32"/>
+  <reg name="r19" bitsize="32"/>
+  <reg name="r20" bitsize="32"/>
+  <reg name="r21" bitsize="32"/>
+  <reg name="r22" bitsize="32"/>
+  <reg name="r23" bitsize="32"/>
+  <reg name="r24" bitsize="32"/>
+  <reg name="r25" bitsize="32"/>
+
+  <!-- ARC core data pointer registers.  -->
+  <reg name="gp"  bitsize="32" type="data_ptr"/>
+  <reg name="fp"  bitsize="32" type="data_ptr"/>
+  <reg name="sp"  bitsize="32" type="data_ptr"/>
+
+  <!-- Code pointers.  -->
+  <reg name="blink"  bitsize="32" type="code_ptr"/>
+
+  <!-- Here goes extension core registers: r32 - r59 -->
+
+  <!-- Loop counter.  -->
+  <reg name="lp_count" bitsize="32" type="uint32"/>
+
+  <!-- r61 is a reserved register address.  -->
+
+  <!-- r62 is a long immediate value, not a real register.  -->
+
+  <!-- 4-byte aligned read-only program counter.  -->
+  <reg name="pcl" bitsize="32" type="code_ptr" group=""/>
+</feature>
diff --git a/gdb/features/arc/core-v2-linux.c b/gdb/features/arc/core-v2-linux.c
new file mode 100644
index 00000000000..d3e563778ff
--- /dev/null
+++ b/gdb/features/arc/core-v2-linux.c
@@ -0,0 +1,48 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: core-v2-linux.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_arc_core_v2_linux (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core.v2");
+  tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r3", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r4", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r5", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r6", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r7", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r8", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r9", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r10", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r11", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r12", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r13", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r14", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r15", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r16", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r17", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r18", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r19", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r20", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r21", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r22", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r23", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r24", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r25", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "gp", regnum++, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "fp", regnum++, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "r30", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "blink", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "r58", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r59", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lp_count", regnum++, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "pcl", regnum++, 1, NULL, 32, "code_ptr");
+  return regnum;
+}
diff --git a/gdb/features/arc/core-v2-linux.xml b/gdb/features/arc/core-v2-linux.xml
new file mode 100644
index 00000000000..3ac4a86da56
--- /dev/null
+++ b/gdb/features/arc/core-v2-linux.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2020 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.arc.core.v2">
+  <reg name="r0"  bitsize="32"/>
+  <reg name="r1"  bitsize="32"/>
+  <reg name="r2"  bitsize="32"/>
+  <reg name="r3"  bitsize="32"/>
+  <reg name="r4"  bitsize="32"/>
+  <reg name="r5"  bitsize="32"/>
+  <reg name="r6"  bitsize="32"/>
+  <reg name="r7"  bitsize="32"/>
+  <reg name="r8"  bitsize="32"/>
+  <reg name="r9"  bitsize="32"/>
+  <reg name="r10" bitsize="32"/>
+  <reg name="r11" bitsize="32"/>
+  <reg name="r12" bitsize="32"/>
+  <reg name="r13" bitsize="32"/>
+  <reg name="r14" bitsize="32"/>
+  <reg name="r15" bitsize="32"/>
+  <reg name="r16" bitsize="32"/>
+  <reg name="r17" bitsize="32"/>
+  <reg name="r18" bitsize="32"/>
+  <reg name="r19" bitsize="32"/>
+  <reg name="r20" bitsize="32"/>
+  <reg name="r21" bitsize="32"/>
+  <reg name="r22" bitsize="32"/>
+  <reg name="r23" bitsize="32"/>
+  <reg name="r24" bitsize="32"/>
+  <reg name="r25" bitsize="32"/>
+
+  <!-- ARC core data pointer registers.  -->
+  <reg name="gp"  bitsize="32" type="data_ptr"/>
+  <reg name="fp"  bitsize="32" type="data_ptr"/>
+  <reg name="sp"  bitsize="32" type="data_ptr"/>
+
+  <reg name="r30"   bitsize="32" group=""/>
+  <reg name="blink" bitsize="32" type="code_ptr"/>
+
+  <!-- Here goes extension core registers: r32 - r57.  -->
+  <reg name="r58"   bitsize="32"/>
+  <reg name="r59"   bitsize="32"/>
+
+  <!-- Loop counter.  -->
+  <reg name="lp_count" bitsize="32" type="uint32"/>
+
+  <!-- r61 is a reserved register address.  -->
+
+  <!-- r62 is a long immediate value, not a real register.  -->
+
+  <!-- 4-byte aligned read-only program counter.  -->
+  <reg name="pcl" bitsize="32" type="code_ptr" group=""/>
+</feature>
-- 
2.26.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH 2/4] arc: Recognize registers available on Linux targets
  2020-03-26 12:52 [PATCH 0/4] arc: Add GNU/Linux support Shahab Vahedi
  2020-03-26 12:52 ` [PATCH 1/4] arc: Add XML target features for Linux targets Shahab Vahedi
@ 2020-03-26 12:52 ` Shahab Vahedi
  2020-04-24 13:50   ` Tom Tromey
  2020-03-26 12:52 ` [PATCH 3/4] arc: Add GNU/Linux support for ARC Shahab Vahedi
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-03-26 12:52 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Anton Kolesov, Francois Bedard,
	Anton Kolesov

From: Anton Kolesov <Anton.Kolesov@synopsys.com>

For ARC there are registers that are not part of a required set in XML target
descriptions by default, but which are almost always present on ARC targets and
are universally exposed by the ptrace interface.  This patch adds those
registers to those recognized by GDB:

- R30 - core register available in user-space on ARC HS processors only (used
  to be a privileged only ILINK2 on ARC700).
- R58, R59 - accumulator register pair for a 64-multiplier and
  double-precision FPU - only on ARC HS.
- LP_START, LP_END - AUX registers, hardware loop start and end.  Formally
  optional, though it is hard to find ARC configuration that doesn't have
  them and is always present in processors that can run Linux.  GDB needs to
  know about those registers to implement proper software single stepping,
  since they affect what instruction will be next.
- BTA - AUX register that contains branch target address.  Value of this
  register makes sense only when execution halts at the delay slot
  instruction - in this case branch instruction is already committed,
  STATUS32.DE is set to 1 and BTA contains address of next PC.  GDB needs to
  understand this register to properly handle situations when breakpoint has
  been set in the delay slot (delay slot is stepped over when doing software
  single stepping).  Unfortunately, right now this doesn't work very well,
  because Linux doesn't allow modifications of STATUS32 via ptrace and Linux
  uses TRAP_S instruction to implement software breakpoints - this
  instruction commits when executed, therefore when TRAP_S is set in the
  delay slot and execution halts at it, PC is already advanced to BTA value
  and STATUS32.DE is reset.  BTA register will be more useful for debugger
  after support for SWI instruction will be added to ARC Linux - this
  breakpoint instruction doesn't commit, hence it doesn't change processor
  state.

gdb/ChangeLog:
2020-03-26  Anton Kolesov  <anton.kolesov@synopsys.com>

	* arc-tdep.c (core_v2_register_names): Fix names of R58 and R59.
	(aux_minimal_register_names): Add LP_START, LP_END and BTA.
	(arc_tdesc_init): Recognize those registers.
	* arc-tdep.h (arc_regnum): Add R58, R59, LP_START, LP_END and BTA.
	(gdbarch_tdep): New field has_hw_loops.

gdb/doc/ChangeLog:
2020-03-26  Anton Kolesov  <anton.kolesov@synopsys.com>

	* gdb.texinfo (Synopsys ARC): Document LP_START, LP_END and BTA.
---
 gdb/arc-tdep.c      | 77 +++++++++++++++++++++++++++++++++++----------
 gdb/arc-tdep.h      | 17 ++++++++--
 gdb/doc/gdb.texinfo |  3 +-
 3 files changed, 78 insertions(+), 19 deletions(-)

diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index a4f3f44b4fb..edcb8286b07 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -117,12 +117,12 @@ static const char *const core_v2_register_names[] = {
   "r44", "r45", "r46", "r47",
   "r48", "r49", "r50", "r51",
   "r52", "r53", "r54", "r55",
-  "r56", "r57", "accl", "acch",
-  "lp_count", "reserved", "limm", "pcl",
+  "r56", "r57", "r58", "r59",
+  "lp_count", "reserved", "limm", "pcl"
 };
 
 static const char *const aux_minimal_register_names[] = {
-  "pc", "status32",
+  "pc", "status32", "lp_start", "lp_end", "bta"
 };
 
 static const char *const core_arcompact_register_names[] = {
@@ -141,7 +141,7 @@ static const char *const core_arcompact_register_names[] = {
   "r48", "r49", "r50", "r51",
   "r52", "r53", "r54", "r55",
   "r56", "r57", "r58", "r59",
-  "lp_count", "reserved", "limm", "pcl",
+  "lp_count", "reserved", "limm", "pcl"
 };
 
 static char *arc_disassembler_options = NULL;
@@ -1724,7 +1724,7 @@ static const struct frame_base arc_normal_base = {
 
 static bool
 arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
-		struct tdesc_arch_data **tdesc_data)
+		struct tdesc_arch_data **tdesc_data, struct gdbarch_tdep *tdep)
 {
   if (arc_debug)
     debug_printf ("arc: Target description initialization.\n");
@@ -1858,17 +1858,44 @@ arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
 			    || (i >= ARC_R16_REGNUM && i <= ARC_R25_REGNUM)))
 	continue;
 
-      valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i,
-					 core_regs[i]);
+      /* R58 and R59 can have special names: ACCL and ACCH, however which
+	 one is which depends on target endianness - for little endian R58
+	 is ACCL, R59 is ACCH; vice versa for big endian.  */
+
+      const char *const r58_names[] = {
+	core_regs[58],
+	(info.byte_order == BFD_ENDIAN_LITTLE ? "accl" : "acch"),
+	NULL
+      };
+      const char *const r59_names[] = {
+	core_regs[59],
+	(info.byte_order == BFD_ENDIAN_LITTLE ? "acch" : "accl"),
+	NULL
+      };
+
+      switch (i)
+	{
+	case ARC_R58_REGNUM:
+	  valid_p = tdesc_numbered_register_choices (feature, tdesc_data_loc,
+						     i, r58_names);
+	  break;
+	case ARC_R59_REGNUM:
+	  valid_p = tdesc_numbered_register_choices (feature, tdesc_data_loc,
+						     i, r59_names);
+	  break;
+	default:
+	  valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i,
+					     core_regs[i]);
+	}
 
       /* - Ignore errors in extension registers - they are optional.
 	 - Ignore missing ILINK because it doesn't make sense for Linux.
-	 - Ignore missing ILINK2 when architecture is ARCompact, because it
-	 doesn't make sense for Linux targets.
+	 - Ignore missing ILINK2 when architecture is ARCompact, because
+	 it doesn't make sense for Linux targets.
 
-	 In theory those optional registers should be in separate features, but
-	 that would create numerous but tiny features, which looks like an
-	 overengineering of a rather simple task.  */
+	 In theory those optional registers should be in separate
+	 features, but that would create numerous but tiny features, which
+	 looks like an overengineering of a rather simple task.  */
       if (!valid_p && (i <= ARC_SP_REGNUM || i == ARC_BLINK_REGNUM
 		       || i == ARC_LP_COUNT_REGNUM || i == ARC_PCL_REGNUM
 		       || (i == ARC_R30_REGNUM && is_arcv2)))
@@ -1895,7 +1922,9 @@ arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
     {
       const char *name = aux_minimal_register_names[i - ARC_FIRST_AUX_REGNUM];
       valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i, name);
-      if (!valid_p)
+
+      /* Only STATUS32 and PC are mandatory.  */
+      if (!valid_p && (i == ARC_PC_REGNUM || i == ARC_STATUS32_REGNUM))
 	{
 	  arc_print (_("Error: Cannot find required register `%s' "
 		       "in feature `%s'.\n"),
@@ -1903,6 +1932,11 @@ arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
 	  tdesc_data_cleanup (tdesc_data_loc);
 	  return false;
 	}
+      /* Hardware loops present if both its registers are.  */
+      else if (ARC_LP_START_REGNUM == i)
+	tdep->has_hw_loops = valid_p;
+      else if (ARC_LP_END_REGNUM == i)
+	tdep->has_hw_loops &= valid_p;
     }
 
   *tdesc = tdesc_loc;
@@ -1950,13 +1984,17 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   if (arc_debug)
     debug_printf ("arc: Architecture initialization.\n");
 
-  if (!arc_tdesc_init (info, &tdesc, &tdesc_data))
-    return NULL;
-
   /* Allocate the ARC-private target-dependent information structure, and the
      GDB target-independent information structure.  */
   struct gdbarch_tdep *tdep = XCNEW (struct gdbarch_tdep);
   tdep->jb_pc = -1; /* No longjmp support by default.  */
+
+  if (!arc_tdesc_init (info, &tdesc, &tdesc_data, tdep))
+    {
+      XDELETE (tdep);
+      return NULL;
+    }
+
   struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep);
 
   /* Data types.  */
@@ -1987,6 +2025,13 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_ps_regnum (gdbarch, ARC_STATUS32_REGNUM);
   set_gdbarch_fp0_regnum (gdbarch, -1);	/* No FPU registers.  */
 
+  /* Confirm that register name lists have proper length.  */
+  gdb_static_assert (ARC_LAST_REGNUM + 1
+		     == (ARRAY_SIZE (core_v2_register_names)
+			 + ARRAY_SIZE (aux_minimal_register_names)));
+  gdb_static_assert (ARRAY_SIZE (core_v2_register_names)
+		     == ARRAY_SIZE (core_arcompact_register_names));
+
   set_gdbarch_push_dummy_call (gdbarch, arc_push_dummy_call);
   set_gdbarch_push_dummy_code (gdbarch, arc_push_dummy_code);
 
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index d72332c7638..8fd8571457f 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -23,6 +23,7 @@
 
 /* Need disassemble_info.  */
 #include "dis-asm.h"
+#include "gdbarch.h"
 #include "arch/arc.h"
 
 /* To simplify GDB code this enum assumes that internal regnums should be same
@@ -54,6 +55,8 @@ enum arc_regnum
     ARC_R30_REGNUM,
     /* Return address from function.  */
     ARC_BLINK_REGNUM,
+    ARC_R58_REGNUM = 58,
+    ARC_R59_REGNUM,
     /* Zero-delay loop counter.  */
     ARC_LP_COUNT_REGNUM = 60,
     /* Reserved register number.  There should never be a register with such
@@ -69,14 +72,21 @@ enum arc_regnum
     /* Program counter, aligned to 4-bytes, read-only.  */
     ARC_PCL_REGNUM,
     ARC_LAST_CORE_REGNUM = ARC_PCL_REGNUM,
+
     /* AUX registers.  */
     /* Actual program counter.  */
     ARC_PC_REGNUM,
     ARC_FIRST_AUX_REGNUM = ARC_PC_REGNUM,
     /* Status register.  */
     ARC_STATUS32_REGNUM,
-    ARC_LAST_REGNUM = ARC_STATUS32_REGNUM,
-    ARC_LAST_AUX_REGNUM = ARC_STATUS32_REGNUM,
+    /* Zero-delay loop start instruction.  */
+    ARC_LP_START_REGNUM,
+    /* Zero-delay loop next-after-last instruction.  */
+    ARC_LP_END_REGNUM,
+    /* Branch target address.  */
+    ARC_BTA_REGNUM,
+    ARC_LAST_AUX_REGNUM = ARC_BTA_REGNUM,
+    ARC_LAST_REGNUM = ARC_LAST_AUX_REGNUM,
 
     /* Additional ABI constants.  */
     ARC_FIRST_ARG_REGNUM = ARC_R0_REGNUM,
@@ -101,6 +111,9 @@ struct gdbarch_tdep
   /* Offset to PC value in jump buffer.  If this is negative, longjmp
      support will be disabled.  */
   int jb_pc;
+
+  /* Whether target has hardware (aka zero-delay) loops.  */
+  bool has_hw_loops;
 };
 
 /* Utility functions used by other ARC-specific modules.  */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 385c832f222..1671d44c6c8 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -45115,7 +45115,8 @@ difference with @samp{org.gnu.gdb.arc.core.v2} feature is in the names of
 ARC v2, but @samp{ilink2} is optional on ARCompact.
 
 The @samp{org.gnu.gdb.arc.aux-minimal} feature is required for all ARC
-targets.  It should contain registers @samp{pc} and @samp{status32}.
+targets.  It should contain registers @samp{pc} and @samp{status32}.  It may
+contain registers @samp{lp_start}, @samp{lp_end} and @samp{bta}.
 
 @node ARM Features
 @subsection ARM Features
-- 
2.26.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH 3/4] arc: Add GNU/Linux support for ARC
  2020-03-26 12:52 [PATCH 0/4] arc: Add GNU/Linux support Shahab Vahedi
  2020-03-26 12:52 ` [PATCH 1/4] arc: Add XML target features for Linux targets Shahab Vahedi
  2020-03-26 12:52 ` [PATCH 2/4] arc: Recognize registers available on " Shahab Vahedi
@ 2020-03-26 12:52 ` Shahab Vahedi
  2020-04-24 14:00   ` Tom Tromey
  2020-03-26 12:52 ` [PATCH 4/4] arc: Add arc-*-linux regformats Shahab Vahedi
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-03-26 12:52 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Anton Kolesov, Francois Bedard,
	Anton Kolesov

From: Anton Kolesov <Anton.Kolesov@synopsys.com>

ARC Linux targets differences from baremetal:

- No support for hardware single instruction stepping.
- Different access rules to registers.
- Use of another instruction for breakpoints.

2020-03-26  Anton Kolesov  <anton.kolesov@synopsys.com>

	* configure.tgt: ARC support for GNU/Linux.
	* Makefile.in (ALL_TARGET_OBJS): Likewise.
	* arc-linux-tdep.c: New file.
	* arc-tdep.h (ARC_STATUS32_L_MASK, ARC_STATUS32_DE_MASK): Declare.
	* arc-tdep.c (arc_write_pc): Use it.
---
 gdb/Makefile.in      |   1 +
 gdb/arc-linux-tdep.c | 284 +++++++++++++++++++++++++++++++++++++++++++
 gdb/arc-tdep.c       |   3 +-
 gdb/arc-tdep.h       |   5 +
 gdb/configure.tgt    |   6 +
 5 files changed, 297 insertions(+), 2 deletions(-)
 create mode 100644 gdb/arc-linux-tdep.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 0c331af4bff..028992ab664 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -695,6 +695,7 @@ ALL_64_TARGET_OBS = \
 # All other target-dependent objects files (used with --enable-targets=all).
 ALL_TARGET_OBS = \
 	aarch32-tdep.o \
+	arc-linux-tdep.o \
 	arc-tdep.o \
 	arch/aarch32.o \
 	arch/arc.o \
diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
new file mode 100644
index 00000000000..ebb5d622988
--- /dev/null
+++ b/gdb/arc-linux-tdep.c
@@ -0,0 +1,284 @@
+/* Target dependent code for GNU/Linux ARC.
+
+   Copyright 2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* GDB header files.  */
+#include "defs.h"
+#include "linux-tdep.h"
+#include "objfiles.h"
+#include "opcode/arc.h"
+#include "osabi.h"
+#include "solib-svr4.h"
+
+/* ARC header files.  */
+#include "opcodes/arc-dis.h"
+#include "arc-tdep.h"
+
+/* Implement the "cannot_fetch_register" gdbarch method.  */
+
+static int
+arc_linux_cannot_fetch_register (struct gdbarch *gdbarch, int regnum)
+{
+  /* Assume that register is readable if it is unknown.  */
+  switch (regnum)
+    {
+    case ARC_ILINK_REGNUM:
+    case ARC_RESERVED_REGNUM:
+    case ARC_LIMM_REGNUM:
+      return TRUE;
+    case ARC_R30_REGNUM:
+    case ARC_R58_REGNUM:
+    case ARC_R59_REGNUM:
+      return !arc_mach_is_arcv2 (gdbarch);
+    }
+  if (regnum > ARC_BLINK_REGNUM && regnum < ARC_LP_COUNT_REGNUM)
+    return TRUE;
+  return FALSE;
+}
+
+/* Implement the "cannot_store_register" gdbarch method.  */
+
+static int
+arc_linux_cannot_store_register (struct gdbarch *gdbarch, int regnum)
+{
+  /* Assume that register is writable if it is unknown.  */
+  switch (regnum)
+    {
+    case ARC_ILINK_REGNUM:
+    case ARC_RESERVED_REGNUM:
+    case ARC_LIMM_REGNUM:
+    case ARC_PCL_REGNUM:
+      return TRUE;
+    case ARC_R30_REGNUM:
+    case ARC_R58_REGNUM:
+    case ARC_R59_REGNUM:
+      return !arc_mach_is_arcv2 (gdbarch);
+    }
+  if (regnum > ARC_BLINK_REGNUM && regnum < ARC_LP_COUNT_REGNUM)
+    return TRUE;
+  return FALSE;
+}
+
+/* For ARC Linux, breakpoint uses the 16-bit TRAP_S 1 instruction, which
+   is 0x3e78 (little endian) or 0x783e (big endian).  */
+
+static const gdb_byte arc_linux_trap_s_be[] = { 0x78, 0x3e };
+static const gdb_byte arc_linux_trap_s_le[] = { 0x3e, 0x78 };
+
+/* Implement the "breakpoint_kind_from_pc" gdbarch method.  */
+
+static int
+arc_linux_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+  return 2;
+}
+
+/* Implement the "sw_breakpoint_from_kind" gdbarch method.  */
+
+static const gdb_byte *
+arc_linux_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+
+  *size = kind;
+  return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+	  ? arc_linux_trap_s_be
+	  : arc_linux_trap_s_le);
+}
+
+/* Implement the "software_single_step" gdbarch method.  */
+
+static std::vector<CORE_ADDR>
+arc_linux_software_single_step (struct regcache *regcache)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct disassemble_info di = arc_disassemble_info (gdbarch);
+
+  /* Read current instruction.  */
+  struct arc_instruction curr_insn;
+  arc_insn_decode (regcache_read_pc (regcache), &di, arc_delayed_print_insn,
+		   &curr_insn);
+  CORE_ADDR next_pc = arc_insn_get_linear_next_pc (curr_insn);
+
+  std::vector<CORE_ADDR> next_pcs;
+
+  /* For instructions with delay slots, the fall thru is not the
+     instruction immediately after the current instruction, but the one
+     after that.  */
+  if (curr_insn.has_delay_slot)
+    {
+      struct arc_instruction next_insn;
+      arc_insn_decode (next_pc, &di, arc_delayed_print_insn, &next_insn);
+      next_pcs.push_back (arc_insn_get_linear_next_pc (next_insn));
+    }
+  else
+    {
+      next_pcs.push_back (next_pc);
+    }
+
+  ULONGEST status32;
+  regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
+				 &status32);
+
+  if (curr_insn.is_control_flow)
+    {
+      CORE_ADDR branch_pc = arc_insn_get_branch_target (curr_insn);
+      if (branch_pc != next_pc)
+	next_pcs.push_back (branch_pc);
+    }
+  /* Is current instruction the last in a loop body?  */
+  else if (tdep->has_hw_loops)
+    {
+      /* If STATUS32.L is 1, then ZD-loops are disabled.  */
+      if (!(status32 & ARC_STATUS32_L_MASK))
+	{
+	  ULONGEST lp_end, lp_start, lp_count;
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_START_REGNUM,
+					 &lp_start);
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_END_REGNUM, &lp_end);
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_COUNT_REGNUM,
+					 &lp_count);
+
+	  if (arc_debug)
+	    {
+	      debug_printf ("arc-linux: lp_start = %s, lp_end = %s, "
+			    "lp_count = %s, next_pc = %s\n",
+			    paddress (gdbarch, lp_start),
+			    paddress (gdbarch, lp_end),
+			    pulongest (lp_count),
+			    paddress (gdbarch, next_pc));
+	    }
+
+	  if (next_pc == lp_end && lp_count > 1)
+	    {
+	      /* The instruction is in effect a jump back to the start of
+		 the loop.  */
+	      next_pcs.push_back (lp_start);
+	    }
+
+	}
+    }
+
+  /* Is this a delay slot?  Then next PC is in BTA register.  */
+  if (status32 & ARC_STATUS32_DE_MASK)
+    {
+      ULONGEST bta;
+      regcache_cooked_read_unsigned (regcache, ARC_BTA_REGNUM, &bta);
+      next_pcs.push_back (bta);
+    }
+
+  return next_pcs;
+}
+
+/* Implement the "skip_solib_resolver" gdbarch method.
+
+   See glibc_skip_solib_resolver for details.  */
+
+static CORE_ADDR
+arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  /* For uClibc 0.9.26+.
+
+     An unresolved PLT entry points to "__dl_linux_resolve", which calls
+     "_dl_linux_resolver" to do the resolving and then eventually jumps to
+     the function.
+
+     So we look for the symbol `_dl_linux_resolver', and if we are there,
+     gdb sets a breakpoint at the return address, and continues.  */
+  struct bound_minimal_symbol resolver =
+    lookup_minimal_symbol ("_dl_linux_resolver", NULL, NULL);
+
+  if (arc_debug)
+    {
+      if (resolver.minsym)
+	{
+	  CORE_ADDR res_addr = BMSYMBOL_VALUE_ADDRESS (resolver);
+	  debug_printf ("arc-linux: skip_solib_resolver (): "
+			"pc = %s, resolver at %s\n",
+			print_core_address (gdbarch, pc),
+			print_core_address (gdbarch, res_addr));
+	}
+      else
+	{
+	  debug_printf ("arc-linux: skip_solib_resolver (): "
+			"pc = %s, no resolver found\n",
+			print_core_address (gdbarch, pc));
+	}
+    }
+
+  if (resolver.minsym && BMSYMBOL_VALUE_ADDRESS (resolver) == pc)
+    {
+      /* Find the return address.  */
+      return frame_unwind_caller_pc (get_current_frame ());
+    }
+  else
+    {
+      /* No breakpoint required.  */
+      return 0;
+    }
+}
+
+/* Initialization specific to Linux environment.  */
+
+static void
+arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (arc_debug)
+    debug_printf ("arc-linux: GNU/Linux OS/ABI initialization.\n");
+
+  /* If we are using Linux, we have in uClibc
+     (libc/sysdeps/linux/arc/bits/setjmp.h):
+
+     typedef int __jmp_buf[13+1+1+1];    //r13-r25, fp, sp, blink
+
+     Where "blink" is a stored PC of a caller function.
+   */
+  tdep->jb_pc = 15;
+
+  linux_init_abi (info, gdbarch);
+
+  /* Set up target dependent GDB architecture entries.  */
+  set_gdbarch_cannot_fetch_register (gdbarch, arc_linux_cannot_fetch_register);
+  set_gdbarch_cannot_store_register (gdbarch, arc_linux_cannot_store_register);
+  set_gdbarch_breakpoint_kind_from_pc (gdbarch,
+				       arc_linux_breakpoint_kind_from_pc);
+  set_gdbarch_sw_breakpoint_from_kind (gdbarch,
+				       arc_linux_sw_breakpoint_from_kind);
+  set_gdbarch_fetch_tls_load_module_address (gdbarch,
+					     svr4_fetch_objfile_link_map);
+  set_gdbarch_software_single_step (gdbarch, arc_linux_software_single_step);
+  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+  set_gdbarch_skip_solib_resolver (gdbarch, arc_linux_skip_solib_resolver);
+
+  /* GNU/Linux uses SVR4-style shared libraries, with 32-bit ints, longs
+     and pointers (ILP32).  */
+  set_solib_svr4_fetch_link_map_offsets (gdbarch,
+					 svr4_ilp32_fetch_link_map_offsets);
+}
+
+/* Suppress warning from -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_arc_linux_tdep;
+
+void
+_initialize_arc_linux_tdep (void)
+{
+  gdbarch_register_osabi (bfd_arch_arc, 0, GDB_OSABI_LINUX,
+			  arc_linux_init_osabi);
+}
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index edcb8286b07..2ef3738ef5d 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -462,8 +462,7 @@ arc_write_pc (struct regcache *regcache, CORE_ADDR new_pc)
   regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
 				 &status32);
 
-  /* Mask for DE bit is 0x40.  */
-  if (status32 & 0x40)
+  if (status32 & ARC_STATUS32_DE_MASK)
     {
       if (arc_debug)
 	{
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index 8fd8571457f..015ef3d4953 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -100,6 +100,11 @@ enum arc_regnum
    Longer registers are represented as pairs of 32-bit registers.  */
 #define ARC_REGISTER_SIZE  4
 
+/* STATUS32 register: hardware loops disabled bit.  */
+#define ARC_STATUS32_L_MASK (1 << 12)
+/* STATUS32 register: current instruction is a delay slot.  */
+#define ARC_STATUS32_DE_MASK (1 << 6)
+
 #define arc_print(fmt, args...) fprintf_unfiltered (gdb_stdlog, fmt, ##args)
 
 extern int arc_debug;
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index b3f31af763c..5c607320055 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -157,6 +157,12 @@ arc*-*-elf32)
 	gdb_target_obs="arc-newlib-tdep.o"
 	;;
 
+arc*-*-linux*)
+	# Target: ARC machine running Linux
+	gdb_target_obs="arc-linux-tdep.o linux-tdep.o solib-svr4.o"
+	build_gdbserver=yes
+	;;
+
 arm*-wince-pe | arm*-*-mingw32ce*)
 	# Target: ARM based machine running Windows CE (win32)
 	gdb_target_obs="arm-wince-tdep.o windows-tdep.o"
-- 
2.26.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH 4/4] arc: Add arc-*-linux regformats
  2020-03-26 12:52 [PATCH 0/4] arc: Add GNU/Linux support Shahab Vahedi
                   ` (2 preceding siblings ...)
  2020-03-26 12:52 ` [PATCH 3/4] arc: Add GNU/Linux support for ARC Shahab Vahedi
@ 2020-03-26 12:52 ` Shahab Vahedi
  2020-04-24 14:01   ` Tom Tromey
  2020-04-06  9:13 ` [PING][PATCH 0/4] arc: Add GNU/Linux support Shahab Vahedi
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-03-26 12:52 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Anton Kolesov, Francois Bedard,
	Anton Kolesov

From: Anton Kolesov <Anton.Kolesov@synopsys.com>

gdb/ChangeLog:
2020-03-26  Anton Kolesov <anton.kolesov@synopsys.com>

	* features/Makefile: Add new files and expedite registers.
	* regformats/arc-arcompact-Linux.dat: New file.
	* regformats/arc-v2-Linux.dat: Likewise.
---
 gdb/features/Makefile                  |  4 ++-
 gdb/regformats/arc-arcompact-linux.dat | 42 ++++++++++++++++++++++++
 gdb/regformats/arc-v2-linux.dat        | 45 ++++++++++++++++++++++++++
 3 files changed, 90 insertions(+), 1 deletion(-)
 create mode 100644 gdb/regformats/arc-arcompact-linux.dat
 create mode 100644 gdb/regformats/arc-v2-linux.dat

diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index a95be667dc1..312c4f53185 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -44,7 +44,8 @@
 #   make GDB=/path/to/gdb XMLTOC="xml files" FEATURE_XMLFILES="xml files" cfiles
 
 # List of .dat files to create in ../regformats/
-WHICH = arm/arm-with-iwmmxt arm/arm-with-vfpv2 arm/arm-with-vfpv3 \
+WHICH = arc-v2-linux arc-arcompact-linux \
+	arm/arm-with-iwmmxt arm/arm-with-vfpv2 arm/arm-with-vfpv3 \
 	arm/arm-with-neon \
 	mips-linux mips-dsp-linux \
 	microblaze-with-stack-protect \
@@ -72,6 +73,7 @@ WHICH = arm/arm-with-iwmmxt arm/arm-with-vfpv2 arm/arm-with-vfpv3 \
 
 # Record which registers should be sent to GDB by default after stop.
 aarch64-expedite = x29,sp,pc
+arc-expedite = sp,pc
 arm-expedite = r11,sp,pc
 i386-expedite = ebp,esp,eip
 amd64-expedite = rbp,rsp,rip
diff --git a/gdb/regformats/arc-arcompact-linux.dat b/gdb/regformats/arc-arcompact-linux.dat
new file mode 100644
index 00000000000..1d35860af3d
--- /dev/null
+++ b/gdb/regformats/arc-arcompact-linux.dat
@@ -0,0 +1,42 @@
+# THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi :set ro:
+# Generated from: arc-arcompact-linux.xml
+name:arc_arcompact_linux
+xmltarget:arc-arcompact-linux.xml
+expedite:sp,pc
+32:r0
+32:r1
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:r8
+32:r9
+32:r10
+32:r11
+32:r12
+32:r13
+32:r14
+32:r15
+32:r16
+32:r17
+32:r18
+32:r19
+32:r20
+32:r21
+32:r22
+32:r23
+32:r24
+32:r25
+32:gp
+32:fp
+32:sp
+32:blink
+32:lp_count
+32:pcl
+32:pc
+32:status32
+32:lp_start
+32:lp_end
+32:bta
diff --git a/gdb/regformats/arc-v2-linux.dat b/gdb/regformats/arc-v2-linux.dat
new file mode 100644
index 00000000000..7e5d1904664
--- /dev/null
+++ b/gdb/regformats/arc-v2-linux.dat
@@ -0,0 +1,45 @@
+# THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi :set ro:
+# Generated from: arc-v2-linux.xml
+name:arc_v2_linux
+xmltarget:arc-v2-linux.xml
+expedite:sp,pc
+32:r0
+32:r1
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:r8
+32:r9
+32:r10
+32:r11
+32:r12
+32:r13
+32:r14
+32:r15
+32:r16
+32:r17
+32:r18
+32:r19
+32:r20
+32:r21
+32:r22
+32:r23
+32:r24
+32:r25
+32:gp
+32:fp
+32:sp
+32:r30
+32:blink
+32:r58
+32:r59
+32:lp_count
+32:pcl
+32:pc
+32:status32
+32:lp_start
+32:lp_end
+32:bta
-- 
2.26.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PING][PATCH 0/4] arc: Add GNU/Linux support
  2020-03-26 12:52 [PATCH 0/4] arc: Add GNU/Linux support Shahab Vahedi
                   ` (3 preceding siblings ...)
  2020-03-26 12:52 ` [PATCH 4/4] arc: Add arc-*-linux regformats Shahab Vahedi
@ 2020-04-06  9:13 ` Shahab Vahedi
  2020-04-20 16:51 ` [PING^2][PATCH " Shahab Vahedi
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-04-06  9:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Shahab Vahedi, Anton Kolesov, Francois Bedard

A friendly reminder for the patch series in:

https://sourceware.org/pipermail/gdb-patches/2020-March/167022.html

I appreciate taking the time to review it.


Cheers,
Shahab

^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PING^2][PATCH 0/4] arc: Add GNU/Linux support
  2020-03-26 12:52 [PATCH 0/4] arc: Add GNU/Linux support Shahab Vahedi
                   ` (4 preceding siblings ...)
  2020-04-06  9:13 ` [PING][PATCH 0/4] arc: Add GNU/Linux support Shahab Vahedi
@ 2020-04-20 16:51 ` Shahab Vahedi
  2020-04-28 16:04 ` [PATCH v2 " Shahab Vahedi
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-04-20 16:51 UTC (permalink / raw)
  To: gdb-patches; +Cc: Shahab Vahedi, Shahab Vahedi, Anton Kolesov, Francois Bedard

Second ping:
---
A friendly reminder for the patch series in:

https://sourceware.org/pipermail/gdb-patches/2020-March/167022.html

I appreciate taking the time to review it.


Cheers,
Shahab

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH 1/4] arc: Add XML target features for Linux targets
  2020-03-26 12:52 ` [PATCH 1/4] arc: Add XML target features for Linux targets Shahab Vahedi
@ 2020-04-24 13:46   ` Tom Tromey
  0 siblings, 0 replies; 86+ messages in thread
From: Tom Tromey @ 2020-04-24 13:46 UTC (permalink / raw)
  To: Shahab Vahedi via Gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Anton Kolesov, Francois Bedard

>>>>> ">" == Shahab Vahedi via Gdb-patches <gdb-patches@sourceware.org> writes:

>> From: Anton Kolesov <Anton.Kolesov@synopsys.com>
>> Add XML target features for Linux targets.  Compared to default
>> Linux features:

>> - Explicitly specify CPU machine.
>> - Remove baremetal only ILINK{,1,2} registers.
>> - Add LP_START and LP_END registers for hardware loops - required to
>>   properly evaluate possible next instruction during software single
>>   instruction stepping.
>> - Add BTA register which contains branch target address - address of
>>   next instruction when processor is in the delay slot.
>> - ARC HS description also adds R30, R58 and R59 registers, specific to
>>   this architecture.

>> gdb/ChangeLog:
>> 2020-03-26  Anton Kolesov  <anton.kolesov@synopsys.com>

>> 	* arch/arc.h (arc_create_target_description): Support Linux targets.
>> 	* arch/arc.c (arc_create_target_description): Likewise.
>> 	* arc-tdep.c (arc_tdesc_init): Update invocation of
>> 	  arc_read_description.
>> 	* features/Makefile (FEATURE_XMLFILES): Add new files.
>> 	* features/arc/aux-arcompact-linux.xml: New file.
>> 	* features/arc/aux-v2-linux.xml: Likewise.
>> 	* features/arc/core-arcompact-linux.xml: Likewise.
>> 	* features/arc/core-v2-linux.xml: Likewise.
>> 	* features/arc/aux-arcompact-linux.c: Generate.
>> 	* features/arc/aux-v2-linux.c: Likewise.
>> 	* features/arc/core-arcompact-linux.c: Likewise.
>> 	* features/arc/core-v2-linux.c: Likewise.

Thanks, and sorry about the delay.  This is ok.

Tom

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH 2/4] arc: Recognize registers available on Linux targets
  2020-03-26 12:52 ` [PATCH 2/4] arc: Recognize registers available on " Shahab Vahedi
@ 2020-04-24 13:50   ` Tom Tromey
  0 siblings, 0 replies; 86+ messages in thread
From: Tom Tromey @ 2020-04-24 13:50 UTC (permalink / raw)
  To: Shahab Vahedi via Gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Anton Kolesov, Francois Bedard

>>>>> ">" == Shahab Vahedi via Gdb-patches <gdb-patches@sourceware.org> writes:

>> +      const char *const r58_names[] = {
>> +	core_regs[58],

This should probably say ARC_R58_REGNUM?

>> +	core_regs[59],

ARC_R59_REGNUM ?

>>    /* Allocate the ARC-private target-dependent information structure, and the
>>       GDB target-independent information structure.  */
>>    struct gdbarch_tdep *tdep = XCNEW (struct gdbarch_tdep);
>> 	tdep-> jb_pc = -1; /* No longjmp support by default.  */
>> +
>> +  if (!arc_tdesc_init (info, &tdesc, &tdesc_data, tdep))
>> +    {
>> +      XDELETE (tdep);
>> +      return NULL;
>> +    }

gdb doesn't use XDELETE, but rather "xfree".
You might as well "return nullptr;" while you're at it.

thanks,
Tom

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH 3/4] arc: Add GNU/Linux support for ARC
  2020-03-26 12:52 ` [PATCH 3/4] arc: Add GNU/Linux support for ARC Shahab Vahedi
@ 2020-04-24 14:00   ` Tom Tromey
  0 siblings, 0 replies; 86+ messages in thread
From: Tom Tromey @ 2020-04-24 14:00 UTC (permalink / raw)
  To: Shahab Vahedi via Gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Anton Kolesov, Francois Bedard

>>>>> ">" == Shahab Vahedi via Gdb-patches <gdb-patches@sourceware.org> writes:

Thank you for the patch.
I have a few nits to pick, but no serious issues.

>> +static int
>> +arc_linux_cannot_fetch_register (struct gdbarch *gdbarch, int regnum)
>> +{
>> +  /* Assume that register is readable if it is unknown.  */
>> +  switch (regnum)
>> +    {
>> +    case ARC_ILINK_REGNUM:
>> +    case ARC_RESERVED_REGNUM:
>> +    case ARC_LIMM_REGNUM:
>> +      return TRUE;

gdb doesn't generally use the TRUE / FALSE defines -- there are
exceptions, mostly for curses code, but on the whole these should be
avoided.  You can either use 1 / 0, or true / false.

These functions only return int nowadays because C++-ification is
incomplete and nobody has gone back to fix up gdbarch to use bool
here, so I guess I'd opt for true / false.

>> +/* Implement the "sw_breakpoint_from_kind" gdbarch method.  */
>> +
>> +static const gdb_byte *
>> +arc_linux_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)

This line is too long.

>> +{
>> +
>> +  *size = kind;
>> +  return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)

Spurious blank line at the start of this function.

>> +  /* Is this a delay slot?  Then next PC is in BTA register.  */
>> +  if (status32 & ARC_STATUS32_DE_MASK)

Normally in gdb this kind of expression is written out more fully, like:

    if ((status32 & ARC_STATUS32_DE_MASK) != 0)

I thought GCC had a warning that prevented the form in the patch?
Maybe I'm confusing it with something else.

>> -  /* Mask for DE bit is 0x40.  */
>> -  if (status32 & 0x40)
>> +  if (status32 & ARC_STATUS32_DE_MASK)

As long as you're touching this, you might as well change it to the
"!= 0" form.

>> +arc*-*-linux*)
>> +	# Target: ARC machine running Linux
>> +	gdb_target_obs="arc-linux-tdep.o linux-tdep.o solib-svr4.o"
>> +	build_gdbserver=yes

build_gdbserver is no longer needed in this file.  Since gdbserver was
moved to the top level, Whether or not gdbserver is built is now decided
entirely by gdbserver/configure.srv.

Tom

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH 4/4] arc: Add arc-*-linux regformats
  2020-03-26 12:52 ` [PATCH 4/4] arc: Add arc-*-linux regformats Shahab Vahedi
@ 2020-04-24 14:01   ` Tom Tromey
  0 siblings, 0 replies; 86+ messages in thread
From: Tom Tromey @ 2020-04-24 14:01 UTC (permalink / raw)
  To: Shahab Vahedi via Gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Anton Kolesov, Francois Bedard

>>>>> ">" == Shahab Vahedi via Gdb-patches <gdb-patches@sourceware.org> writes:

>> From: Anton Kolesov <Anton.Kolesov@synopsys.com>
>> gdb/ChangeLog:
>> 2020-03-26  Anton Kolesov <anton.kolesov@synopsys.com>

>> 	* features/Makefile: Add new files and expedite registers.
>> 	* regformats/arc-arcompact-Linux.dat: New file.
>> 	* regformats/arc-v2-Linux.dat: Likewise.

This is ok.  Thank you.

Tom

^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v2 0/4] arc: Add GNU/Linux support
  2020-03-26 12:52 [PATCH 0/4] arc: Add GNU/Linux support Shahab Vahedi
                   ` (5 preceding siblings ...)
  2020-04-20 16:51 ` [PING^2][PATCH " Shahab Vahedi
@ 2020-04-28 16:04 ` Shahab Vahedi
  2020-04-28 16:04   ` [PATCH v2 1/4] arc: Add XML target features for Linux targets Shahab Vahedi
                     ` (5 more replies)
  2020-08-04  8:57 ` [PATCH v5 0/4] " Shahab Vahedi
                   ` (2 subsequent siblings)
  9 siblings, 6 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-04-28 16:04 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Tom Tromey, Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

This is a series of changes to enable debugging ARC targets that are
running on a native ARC GNU/Linux system.  Most of these changes are
related to how registers are slightly handled differently compared
to a baremetal scenario.  Each commit illustrate further on those.

After this series, there will come patches that add support for
native ARC gdb/gdbserver.

v2: Changes after Tom's remarks:
 arc-tdep.c
  - arc_tdesc_init(): Use "ARC_{R58,R59}_REGNUM" to index "core_regs[]".
  - arc_gdbarch_init(): Use "xfree ()" instead of "XDELETE ()"
  - arc_gdbarch_init(): return "nullptr" instead of "NULL".
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 arc-linux-tdep.c
  - Use true/false instead of TRUE/FALSE.
  - arc_linux_sw_breakpoint_from_kind (): Break long lines into two.
  - arc_linux_sw_breakpoint_from_kind (): Remove starting blank line.
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 gdb/configure.tgt
  - arc*-*-linux*): Remove "build_gdbserver=yes".

Anton Kolesov (4):
  arc: Add XML target features for Linux targets
  arc: Recognize registers available on Linux targets
  arc: Add GNU/Linux support for ARC
  arc: Add arc-*-linux regformats

 gdb/Makefile.in                           |   1 +
 gdb/arc-linux-tdep.c                      | 284 ++++++++++++++++++++++
 gdb/arc-tdep.c                            |  84 +++++--
 gdb/arc-tdep.h                            |  22 +-
 gdb/arch/arc.c                            |  40 ++-
 gdb/arch/arc.h                            |  18 +-
 gdb/configure.tgt                         |   5 +
 gdb/doc/gdb.texinfo                       |   3 +-
 gdb/features/Makefile                     |   8 +-
 gdb/features/arc/aux-arcompact-linux.c    |  34 +++
 gdb/features/arc/aux-arcompact-linux.xml  |  31 +++
 gdb/features/arc/aux-v2-linux.c           |  38 +++
 gdb/features/arc/aux-v2-linux.xml         |  35 +++
 gdb/features/arc/core-arcompact-linux.c   |  45 ++++
 gdb/features/arc/core-arcompact-linux.xml |  56 +++++
 gdb/features/arc/core-v2-linux.c          |  48 ++++
 gdb/features/arc/core-v2-linux.xml        |  58 +++++
 gdb/regformats/arc-arcompact-linux.dat    |  42 ++++
 gdb/regformats/arc-v2-linux.dat           |  45 ++++
 19 files changed, 858 insertions(+), 39 deletions(-)
 create mode 100644 gdb/arc-linux-tdep.c
 create mode 100644 gdb/features/arc/aux-arcompact-linux.c
 create mode 100644 gdb/features/arc/aux-arcompact-linux.xml
 create mode 100644 gdb/features/arc/aux-v2-linux.c
 create mode 100644 gdb/features/arc/aux-v2-linux.xml
 create mode 100644 gdb/features/arc/core-arcompact-linux.c
 create mode 100644 gdb/features/arc/core-arcompact-linux.xml
 create mode 100644 gdb/features/arc/core-v2-linux.c
 create mode 100644 gdb/features/arc/core-v2-linux.xml
 create mode 100644 gdb/regformats/arc-arcompact-linux.dat
 create mode 100644 gdb/regformats/arc-v2-linux.dat

-- 
2.26.2


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v2 1/4] arc: Add XML target features for Linux targets
  2020-04-28 16:04 ` [PATCH v2 " Shahab Vahedi
@ 2020-04-28 16:04   ` Shahab Vahedi
  2020-05-14 14:49     ` Simon Marchi
  2020-04-28 16:04   ` [PATCH v2 2/4] arc: Recognize registers available on " Shahab Vahedi
                     ` (4 subsequent siblings)
  5 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-04-28 16:04 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Tom Tromey, Anton Kolesov,
	Francois Bedard, Anton Kolesov

From: Anton Kolesov <Anton.Kolesov@synopsys.com>

Add XML target features for Linux targets.  Compared to default
Linux features:

- Explicitly specify CPU machine.
- Remove baremetal only ILINK{,1,2} registers.
- Add LP_START and LP_END registers for hardware loops - required to
  properly evaluate possible next instruction during software single
  instruction stepping.
- Add BTA register which contains branch target address - address of
  next instruction when processor is in the delay slot.
- ARC HS description also adds R30, R58 and R59 registers, specific to
  this architecture.

gdb/ChangeLog:
2020-04-28  Anton Kolesov  <anton.kolesov@synopsys.com>

	* arch/arc.h (arc_create_target_description): Support Linux targets.
	* arch/arc.c (arc_create_target_description): Likewise.
	* arc-tdep.c (arc_tdesc_init): Update invocation of
	  arc_read_description.
	* features/Makefile (FEATURE_XMLFILES): Add new files.
	* features/arc/aux-arcompact-linux.xml: New file.
	* features/arc/aux-v2-linux.xml: Likewise.
	* features/arc/core-arcompact-linux.xml: Likewise.
	* features/arc/core-v2-linux.xml: Likewise.
	* features/arc/aux-arcompact-linux.c: Generate.
	* features/arc/aux-v2-linux.c: Likewise.
	* features/arc/core-arcompact-linux.c: Likewise.
	* features/arc/core-v2-linux.c: Likewise.
---
 gdb/arc-tdep.c                            |  4 +-
 gdb/arch/arc.c                            | 40 ++++++++++++----
 gdb/arch/arc.h                            | 18 ++++---
 gdb/features/Makefile                     |  4 ++
 gdb/features/arc/aux-arcompact-linux.c    | 34 +++++++++++++
 gdb/features/arc/aux-arcompact-linux.xml  | 31 ++++++++++++
 gdb/features/arc/aux-v2-linux.c           | 38 +++++++++++++++
 gdb/features/arc/aux-v2-linux.xml         | 35 ++++++++++++++
 gdb/features/arc/core-arcompact-linux.c   | 45 ++++++++++++++++++
 gdb/features/arc/core-arcompact-linux.xml | 56 ++++++++++++++++++++++
 gdb/features/arc/core-v2-linux.c          | 48 +++++++++++++++++++
 gdb/features/arc/core-v2-linux.xml        | 58 +++++++++++++++++++++++
 12 files changed, 394 insertions(+), 17 deletions(-)
 create mode 100644 gdb/features/arc/aux-arcompact-linux.c
 create mode 100644 gdb/features/arc/aux-arcompact-linux.xml
 create mode 100644 gdb/features/arc/aux-v2-linux.c
 create mode 100644 gdb/features/arc/aux-v2-linux.xml
 create mode 100644 gdb/features/arc/core-arcompact-linux.c
 create mode 100644 gdb/features/arc/core-arcompact-linux.xml
 create mode 100644 gdb/features/arc/core-v2-linux.c
 create mode 100644 gdb/features/arc/core-v2-linux.xml

diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 3020099c335..a4f3f44b4fb 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -1756,9 +1756,9 @@ arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
   if (!tdesc_has_registers (tdesc_loc))
     {
       if (is_arcv2)
-	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCV2);
+	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCV2_BMT);
       else
-	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCOMPACT);
+	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCOMPACT_BMT);
     }
   else
     {
diff --git a/gdb/arch/arc.c b/gdb/arch/arc.c
index 9552b4aff97..0babbf8a36a 100644
--- a/gdb/arch/arc.c
+++ b/gdb/arch/arc.c
@@ -24,8 +24,12 @@
 /* Target description features.  */
 #include "features/arc/core-v2.c"
 #include "features/arc/aux-v2.c"
+#include "features/arc/core-v2-linux.c"
+#include "features/arc/aux-v2-linux.c"
 #include "features/arc/core-arcompact.c"
 #include "features/arc/aux-arcompact.c"
+#include "features/arc/core-arcompact-linux.c"
+#include "features/arc/aux-arcompact-linux.c"
 
 /* See arc.h.  */
 
@@ -37,21 +41,39 @@ arc_create_target_description (arc_sys_type sys_type)
   long regnum = 0;
 
 #ifndef IN_PROCESS_AGENT
-  if (sys_type == ARC_SYS_TYPE_ARCV2)
+  if (sys_type == ARC_SYS_TYPE_ARCV2_BMT)
     set_tdesc_architecture (tdesc, "arc:ARCv2");
+  else if (sys_type == ARC_SYS_TYPE_ARCV2_LNX)
+    /* If this is ARCv2 Linux, then it is ARC HS.  */
+    set_tdesc_architecture (tdesc, "arc:HS");
   else
     set_tdesc_architecture (tdesc, "arc:ARC700");
+
+  if (sys_type == ARC_SYS_TYPE_ARCOMPACT_LNX
+      || sys_type == ARC_SYS_TYPE_ARCV2_LNX)
+    set_tdesc_osabi (tdesc, "GNU/Linux");
 #endif
 
-  if (sys_type == ARC_SYS_TYPE_ARCV2)
-    {
-      regnum = create_feature_arc_core_v2 (tdesc, regnum);
-      regnum = create_feature_arc_aux_v2 (tdesc, regnum);
-    }
-  else
+  switch (sys_type)
     {
-      regnum = create_feature_arc_core_arcompact (tdesc, regnum);
-      regnum = create_feature_arc_aux_arcompact (tdesc, regnum);
+    case ARC_SYS_TYPE_ARCOMPACT_BMT:
+	  regnum = create_feature_arc_core_arcompact (tdesc, regnum);
+	  regnum = create_feature_arc_aux_arcompact (tdesc, regnum);
+	  break;
+    case ARC_SYS_TYPE_ARCOMPACT_LNX:
+	  regnum = create_feature_arc_core_arcompact_linux (tdesc, regnum);
+	  regnum = create_feature_arc_aux_arcompact_linux (tdesc, regnum);
+	  break;
+    case ARC_SYS_TYPE_ARCV2_BMT:
+	  regnum = create_feature_arc_core_v2 (tdesc, regnum);
+	  regnum = create_feature_arc_aux_v2 (tdesc, regnum);
+	  break;
+    case ARC_SYS_TYPE_ARCV2_LNX:
+	  regnum = create_feature_arc_core_v2_linux (tdesc, regnum);
+	  regnum = create_feature_arc_aux_v2_linux (tdesc, regnum);
+	  break;
+    default:
+	  gdb_assert(!"Invalid arc_sys_type.");
     }
 
   return tdesc;
diff --git a/gdb/arch/arc.h b/gdb/arch/arc.h
index fd806ae7d34..3c19118b946 100644
--- a/gdb/arch/arc.h
+++ b/gdb/arch/arc.h
@@ -23,8 +23,10 @@
 /* Supported ARC system hardware types.  */
 enum arc_sys_type
 {
-  ARC_SYS_TYPE_ARCOMPACT = 0,	  /* ARC600 or ARC700 */
-  ARC_SYS_TYPE_ARCV2,		  /* ARC EM or ARC HS */
+  ARC_SYS_TYPE_ARCOMPACT_BMT = 0, /* ARC600 or ARC700 (baremetal) */
+  ARC_SYS_TYPE_ARCOMPACT_LNX,	  /* ARC600 or ARC700 (linux) */
+  ARC_SYS_TYPE_ARCV2_BMT,	  /* ARC EM or ARC HS (baremetal) */
+  ARC_SYS_TYPE_ARCV2_LNX,	  /* ARC HS (linux) */
   ARC_SYS_TYPE_NUM
 };
 
@@ -33,10 +35,14 @@ arc_sys_type_to_str (const arc_sys_type type)
 {
   switch (type)
     {
-    case ARC_SYS_TYPE_ARCOMPACT:
-      return "ARC_SYS_TYPE_ARCOMPACT";
-    case ARC_SYS_TYPE_ARCV2:
-      return "ARC_SYS_TYPE_ARCV2";
+    case ARC_SYS_TYPE_ARCOMPACT_BMT:
+      return "ARC_SYS_TYPE_ARCOMPACT_BMT";
+    case ARC_SYS_TYPE_ARCOMPACT_LNX:
+      return "ARC_SYS_TYPE_ARCOMPACT_LNX";
+    case ARC_SYS_TYPE_ARCV2_BMT:
+      return "ARC_SYS_TYPE_ARCV2_BMT";
+    case ARC_SYS_TYPE_ARCV2_LNX:
+      return "ARC_SYS_TYPE_ARCV2_LNX";
     default:
       return "Invalid";
     }
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index cc65baa6eda..a95be667dc1 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -206,8 +206,12 @@ FEATURE_XMLFILES = aarch64-core.xml \
 	aarch64-pauth.xml \
 	arc/core-v2.xml \
 	arc/aux-v2.xml \
+	arc/core-v2-linux.xml \
+	arc/aux-v2-linux.xml \
 	arc/core-arcompact.xml \
 	arc/aux-arcompact.xml \
+	arc/core-arcompact-linux.xml \
+	arc/aux-arcompact-linux.xml \
 	arm/arm-core.xml \
 	arm/arm-fpa.xml \
 	arm/arm-m-profile.xml \
diff --git a/gdb/features/arc/aux-arcompact-linux.c b/gdb/features/arc/aux-arcompact-linux.c
new file mode 100644
index 00000000000..41f26c1e2ec
--- /dev/null
+++ b/gdb/features/arc/aux-arcompact-linux.c
@@ -0,0 +1,34 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: aux-arcompact-linux.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_arc_aux_arcompact_linux (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux-minimal");
+  tdesc_type_with_fields *type_with_fields;
+  type_with_fields = tdesc_create_flags (feature, "status32_type", 4);
+  tdesc_add_flag (type_with_fields, 0, "H");
+  tdesc_add_bitfield (type_with_fields, "E", 1, 2);
+  tdesc_add_bitfield (type_with_fields, "A", 3, 4);
+  tdesc_add_flag (type_with_fields, 5, "AE");
+  tdesc_add_flag (type_with_fields, 6, "DE");
+  tdesc_add_flag (type_with_fields, 7, "U");
+  tdesc_add_flag (type_with_fields, 8, "V");
+  tdesc_add_flag (type_with_fields, 9, "C");
+  tdesc_add_flag (type_with_fields, 10, "N");
+  tdesc_add_flag (type_with_fields, 11, "Z");
+  tdesc_add_flag (type_with_fields, 12, "L");
+  tdesc_add_flag (type_with_fields, 13, "R");
+  tdesc_add_flag (type_with_fields, 14, "SE");
+
+  tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "status32", regnum++, 1, NULL, 32, "status32_type");
+  tdesc_create_reg (feature, "lp_start", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "lp_end", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "bta", regnum++, 1, NULL, 32, "code_ptr");
+  return regnum;
+}
diff --git a/gdb/features/arc/aux-arcompact-linux.xml b/gdb/features/arc/aux-arcompact-linux.xml
new file mode 100644
index 00000000000..0d72373eda3
--- /dev/null
+++ b/gdb/features/arc/aux-arcompact-linux.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2020 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.arc.aux-minimal">
+  <flags id="status32_type" size="4">
+      <field name="H"   start="0" end="0"/>
+      <field name="E"   start="1" end="2"/>
+      <field name="A"   start="3" end="4"/>
+      <field name="AE"  start="5" end="5"/>
+      <field name="DE"  start="6" end="6"/>
+      <field name="U"   start="7" end="7"/>
+      <field name="V"   start="8" end="8"/>
+      <field name="C"   start="9" end="9"/>
+      <field name="N"   start="10" end="10"/>
+      <field name="Z"   start="11" end="11"/>
+      <field name="L"   start="12" end="12"/>
+      <field name="R"  start="13" end="13"/>
+      <field name="SE"  start="14" end="14"/>
+  </flags>
+
+  <reg name="pc"       bitsize="32" type="code_ptr"/>
+  <reg name="status32" bitsize="32" type="status32_type"/>
+  <reg name="lp_start" bitsize="32" type="code_ptr"/>
+  <reg name="lp_end"   bitsize="32" type="code_ptr"/>
+  <reg name="bta"      bitsize="32" type="code_ptr"/>
+</feature>
diff --git a/gdb/features/arc/aux-v2-linux.c b/gdb/features/arc/aux-v2-linux.c
new file mode 100644
index 00000000000..6e4d7c02efa
--- /dev/null
+++ b/gdb/features/arc/aux-v2-linux.c
@@ -0,0 +1,38 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: aux-v2-linux.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_arc_aux_v2_linux (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux-minimal");
+  tdesc_type_with_fields *type_with_fields;
+  type_with_fields = tdesc_create_flags (feature, "status32_type", 4);
+  tdesc_add_flag (type_with_fields, 0, "H");
+  tdesc_add_bitfield (type_with_fields, "E", 1, 4);
+  tdesc_add_flag (type_with_fields, 5, "AE");
+  tdesc_add_flag (type_with_fields, 6, "DE");
+  tdesc_add_flag (type_with_fields, 7, "U");
+  tdesc_add_flag (type_with_fields, 8, "V");
+  tdesc_add_flag (type_with_fields, 9, "C");
+  tdesc_add_flag (type_with_fields, 10, "N");
+  tdesc_add_flag (type_with_fields, 11, "Z");
+  tdesc_add_flag (type_with_fields, 12, "L");
+  tdesc_add_flag (type_with_fields, 13, "DZ");
+  tdesc_add_flag (type_with_fields, 14, "SC");
+  tdesc_add_flag (type_with_fields, 15, "ES");
+  tdesc_add_bitfield (type_with_fields, "RB", 16, 18);
+  tdesc_add_flag (type_with_fields, 19, "AD");
+  tdesc_add_flag (type_with_fields, 20, "US");
+  tdesc_add_flag (type_with_fields, 31, "IE");
+
+  tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "status32", regnum++, 1, NULL, 32, "status32_type");
+  tdesc_create_reg (feature, "lp_start", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "lp_end", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "bta", regnum++, 1, NULL, 32, "code_ptr");
+  return regnum;
+}
diff --git a/gdb/features/arc/aux-v2-linux.xml b/gdb/features/arc/aux-v2-linux.xml
new file mode 100644
index 00000000000..165ebb1d6d6
--- /dev/null
+++ b/gdb/features/arc/aux-v2-linux.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2020 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.arc.aux-minimal">
+  <flags id="status32_type" size="4">
+      <field name="H"   start="0" end="0"/>
+      <field name="E"   start="1" end="4"/>
+      <field name="AE"  start="5" end="5"/>
+      <field name="DE"  start="6" end="6"/>
+      <field name="U"   start="7" end="7"/>
+      <field name="V"   start="8" end="8"/>
+      <field name="C"   start="9" end="9"/>
+      <field name="N"   start="10" end="10"/>
+      <field name="Z"   start="11" end="11"/>
+      <field name="L"   start="12" end="12"/>
+      <field name="DZ"  start="13" end="13"/>
+      <field name="SC"  start="14" end="14"/>
+      <field name="ES"  start="15" end="15"/>
+      <field name="RB"  start="16" end="18"/>
+      <field name="AD"  start="19" end="19"/>
+      <field name="US"  start="20" end="20"/>
+      <field name="IE"  start="31" end="31"/>
+  </flags>
+
+  <reg name="pc"       bitsize="32" type="code_ptr"/>
+  <reg name="status32" bitsize="32" type="status32_type"/>
+  <reg name="lp_start" bitsize="32" type="code_ptr"/>
+  <reg name="lp_end"   bitsize="32" type="code_ptr"/>
+  <reg name="bta"      bitsize="32" type="code_ptr"/>
+</feature>
diff --git a/gdb/features/arc/core-arcompact-linux.c b/gdb/features/arc/core-arcompact-linux.c
new file mode 100644
index 00000000000..c870413e922
--- /dev/null
+++ b/gdb/features/arc/core-arcompact-linux.c
@@ -0,0 +1,45 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: core-arcompact-linux.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_arc_core_arcompact_linux (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core.arcompact");
+  tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r3", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r4", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r5", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r6", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r7", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r8", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r9", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r10", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r11", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r12", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r13", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r14", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r15", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r16", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r17", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r18", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r19", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r20", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r21", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r22", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r23", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r24", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r25", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "gp", regnum++, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "fp", regnum++, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "blink", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "lp_count", regnum++, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "pcl", regnum++, 1, NULL, 32, "code_ptr");
+  return regnum;
+}
diff --git a/gdb/features/arc/core-arcompact-linux.xml b/gdb/features/arc/core-arcompact-linux.xml
new file mode 100644
index 00000000000..9b2865d32be
--- /dev/null
+++ b/gdb/features/arc/core-arcompact-linux.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2020 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.arc.core.arcompact">
+  <reg name="r0"  bitsize="32"/>
+  <reg name="r1"  bitsize="32"/>
+  <reg name="r2"  bitsize="32"/>
+  <reg name="r3"  bitsize="32"/>
+  <reg name="r4"  bitsize="32"/>
+  <reg name="r5"  bitsize="32"/>
+  <reg name="r6"  bitsize="32"/>
+  <reg name="r7"  bitsize="32"/>
+  <reg name="r8"  bitsize="32"/>
+  <reg name="r9"  bitsize="32"/>
+  <reg name="r10" bitsize="32"/>
+  <reg name="r11" bitsize="32"/>
+  <reg name="r12" bitsize="32"/>
+  <reg name="r13" bitsize="32"/>
+  <reg name="r14" bitsize="32"/>
+  <reg name="r15" bitsize="32"/>
+  <reg name="r16" bitsize="32"/>
+  <reg name="r17" bitsize="32"/>
+  <reg name="r18" bitsize="32"/>
+  <reg name="r19" bitsize="32"/>
+  <reg name="r20" bitsize="32"/>
+  <reg name="r21" bitsize="32"/>
+  <reg name="r22" bitsize="32"/>
+  <reg name="r23" bitsize="32"/>
+  <reg name="r24" bitsize="32"/>
+  <reg name="r25" bitsize="32"/>
+
+  <!-- ARC core data pointer registers.  -->
+  <reg name="gp"  bitsize="32" type="data_ptr"/>
+  <reg name="fp"  bitsize="32" type="data_ptr"/>
+  <reg name="sp"  bitsize="32" type="data_ptr"/>
+
+  <!-- Code pointers.  -->
+  <reg name="blink"  bitsize="32" type="code_ptr"/>
+
+  <!-- Here goes extension core registers: r32 - r59 -->
+
+  <!-- Loop counter.  -->
+  <reg name="lp_count" bitsize="32" type="uint32"/>
+
+  <!-- r61 is a reserved register address.  -->
+
+  <!-- r62 is a long immediate value, not a real register.  -->
+
+  <!-- 4-byte aligned read-only program counter.  -->
+  <reg name="pcl" bitsize="32" type="code_ptr" group=""/>
+</feature>
diff --git a/gdb/features/arc/core-v2-linux.c b/gdb/features/arc/core-v2-linux.c
new file mode 100644
index 00000000000..d3e563778ff
--- /dev/null
+++ b/gdb/features/arc/core-v2-linux.c
@@ -0,0 +1,48 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: core-v2-linux.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_arc_core_v2_linux (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core.v2");
+  tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r3", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r4", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r5", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r6", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r7", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r8", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r9", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r10", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r11", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r12", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r13", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r14", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r15", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r16", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r17", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r18", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r19", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r20", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r21", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r22", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r23", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r24", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r25", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "gp", regnum++, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "fp", regnum++, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "r30", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "blink", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "r58", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r59", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lp_count", regnum++, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "pcl", regnum++, 1, NULL, 32, "code_ptr");
+  return regnum;
+}
diff --git a/gdb/features/arc/core-v2-linux.xml b/gdb/features/arc/core-v2-linux.xml
new file mode 100644
index 00000000000..3ac4a86da56
--- /dev/null
+++ b/gdb/features/arc/core-v2-linux.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2020 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.arc.core.v2">
+  <reg name="r0"  bitsize="32"/>
+  <reg name="r1"  bitsize="32"/>
+  <reg name="r2"  bitsize="32"/>
+  <reg name="r3"  bitsize="32"/>
+  <reg name="r4"  bitsize="32"/>
+  <reg name="r5"  bitsize="32"/>
+  <reg name="r6"  bitsize="32"/>
+  <reg name="r7"  bitsize="32"/>
+  <reg name="r8"  bitsize="32"/>
+  <reg name="r9"  bitsize="32"/>
+  <reg name="r10" bitsize="32"/>
+  <reg name="r11" bitsize="32"/>
+  <reg name="r12" bitsize="32"/>
+  <reg name="r13" bitsize="32"/>
+  <reg name="r14" bitsize="32"/>
+  <reg name="r15" bitsize="32"/>
+  <reg name="r16" bitsize="32"/>
+  <reg name="r17" bitsize="32"/>
+  <reg name="r18" bitsize="32"/>
+  <reg name="r19" bitsize="32"/>
+  <reg name="r20" bitsize="32"/>
+  <reg name="r21" bitsize="32"/>
+  <reg name="r22" bitsize="32"/>
+  <reg name="r23" bitsize="32"/>
+  <reg name="r24" bitsize="32"/>
+  <reg name="r25" bitsize="32"/>
+
+  <!-- ARC core data pointer registers.  -->
+  <reg name="gp"  bitsize="32" type="data_ptr"/>
+  <reg name="fp"  bitsize="32" type="data_ptr"/>
+  <reg name="sp"  bitsize="32" type="data_ptr"/>
+
+  <reg name="r30"   bitsize="32" group=""/>
+  <reg name="blink" bitsize="32" type="code_ptr"/>
+
+  <!-- Here goes extension core registers: r32 - r57.  -->
+  <reg name="r58"   bitsize="32"/>
+  <reg name="r59"   bitsize="32"/>
+
+  <!-- Loop counter.  -->
+  <reg name="lp_count" bitsize="32" type="uint32"/>
+
+  <!-- r61 is a reserved register address.  -->
+
+  <!-- r62 is a long immediate value, not a real register.  -->
+
+  <!-- 4-byte aligned read-only program counter.  -->
+  <reg name="pcl" bitsize="32" type="code_ptr" group=""/>
+</feature>
-- 
2.26.2


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v2 2/4] arc: Recognize registers available on Linux targets
  2020-04-28 16:04 ` [PATCH v2 " Shahab Vahedi
  2020-04-28 16:04   ` [PATCH v2 1/4] arc: Add XML target features for Linux targets Shahab Vahedi
@ 2020-04-28 16:04   ` Shahab Vahedi
  2020-04-28 16:56     ` Eli Zaretskii
  2020-05-14 15:01     ` Simon Marchi
  2020-04-28 16:04   ` [PATCH v2 3/4] arc: Add GNU/Linux support for ARC Shahab Vahedi
                     ` (3 subsequent siblings)
  5 siblings, 2 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-04-28 16:04 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Tom Tromey, Anton Kolesov,
	Francois Bedard, Anton Kolesov

From: Anton Kolesov <Anton.Kolesov@synopsys.com>

For ARC there are registers that are not part of a required set in XML target
descriptions by default, but which are almost always present on ARC targets and
are universally exposed by the ptrace interface.  This patch adds those
registers to those recognized by GDB:

- R30 - core register available in user-space on ARC HS processors only (used
  to be a privileged only ILINK2 on ARC700).
- R58, R59 - accumulator register pair for a 64-multiplier and
  double-precision FPU - only on ARC HS.
- LP_START, LP_END - AUX registers, hardware loop start and end.  Formally
  optional, though it is hard to find ARC configuration that doesn't have
  them and is always present in processors that can run Linux.  GDB needs to
  know about those registers to implement proper software single stepping,
  since they affect what instruction will be next.
- BTA - AUX register that contains branch target address.  Value of this
  register makes sense only when execution halts at the delay slot
  instruction - in this case branch instruction is already committed,
  STATUS32.DE is set to 1 and BTA contains address of next PC.  GDB needs to
  understand this register to properly handle situations when breakpoint has
  been set in the delay slot (delay slot is stepped over when doing software
  single stepping).  Unfortunately, right now this doesn't work very well,
  because Linux doesn't allow modifications of STATUS32 via ptrace and Linux
  uses TRAP_S instruction to implement software breakpoints - this
  instruction commits when executed, therefore when TRAP_S is set in the
  delay slot and execution halts at it, PC is already advanced to BTA value
  and STATUS32.DE is reset.  BTA register will be more useful for debugger
  after support for SWI instruction will be added to ARC Linux - this
  breakpoint instruction doesn't commit, hence it doesn't change processor
  state.

v2: Changes after Tom's remarks:
 arc-tdep.c
  - arc_tdesc_init(): Use "ARC_{R58,R59}_REGNUM" to index "core_regs[]".
  - arc_gdbarch_init(): Use "xfree ()" instead of "XDELETE ()"
  - arc_gdbarch_init(): return "nullptr" instead of "NULL".

gdb/ChangeLog:
2020-04-28  Anton Kolesov  <anton.kolesov@synopsys.com>

	* arc-tdep.c (core_v2_register_names): Fix names of R58 and R59.
	(aux_minimal_register_names): Add LP_START, LP_END and BTA.
	(arc_tdesc_init): Recognize those registers.
	* arc-tdep.h (arc_regnum): Add R58, R59, LP_START, LP_END and BTA.
	(gdbarch_tdep): New field has_hw_loops.

gdb/doc/ChangeLog:
2020-04-28  Anton Kolesov  <anton.kolesov@synopsys.com>

	* gdb.texinfo (Synopsys ARC): Document LP_START, LP_END and BTA.
---
 gdb/arc-tdep.c      | 77 +++++++++++++++++++++++++++++++++++----------
 gdb/arc-tdep.h      | 17 ++++++++--
 gdb/doc/gdb.texinfo |  3 +-
 3 files changed, 78 insertions(+), 19 deletions(-)

diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index a4f3f44b4fb..878728bc62c 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -117,12 +117,12 @@ static const char *const core_v2_register_names[] = {
   "r44", "r45", "r46", "r47",
   "r48", "r49", "r50", "r51",
   "r52", "r53", "r54", "r55",
-  "r56", "r57", "accl", "acch",
-  "lp_count", "reserved", "limm", "pcl",
+  "r56", "r57", "r58", "r59",
+  "lp_count", "reserved", "limm", "pcl"
 };
 
 static const char *const aux_minimal_register_names[] = {
-  "pc", "status32",
+  "pc", "status32", "lp_start", "lp_end", "bta"
 };
 
 static const char *const core_arcompact_register_names[] = {
@@ -141,7 +141,7 @@ static const char *const core_arcompact_register_names[] = {
   "r48", "r49", "r50", "r51",
   "r52", "r53", "r54", "r55",
   "r56", "r57", "r58", "r59",
-  "lp_count", "reserved", "limm", "pcl",
+  "lp_count", "reserved", "limm", "pcl"
 };
 
 static char *arc_disassembler_options = NULL;
@@ -1724,7 +1724,7 @@ static const struct frame_base arc_normal_base = {
 
 static bool
 arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
-		struct tdesc_arch_data **tdesc_data)
+		struct tdesc_arch_data **tdesc_data, struct gdbarch_tdep *tdep)
 {
   if (arc_debug)
     debug_printf ("arc: Target description initialization.\n");
@@ -1858,17 +1858,44 @@ arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
 			    || (i >= ARC_R16_REGNUM && i <= ARC_R25_REGNUM)))
 	continue;
 
-      valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i,
-					 core_regs[i]);
+      /* R58 and R59 can have special names: ACCL and ACCH, however which
+	 one is which depends on target endianness - for little endian R58
+	 is ACCL, R59 is ACCH; vice versa for big endian.  */
+
+      const char *const r58_names[] = {
+	core_regs[ARC_R58_REGNUM],
+	(info.byte_order == BFD_ENDIAN_LITTLE ? "accl" : "acch"),
+	NULL
+      };
+      const char *const r59_names[] = {
+	core_regs[ARC_R59_REGNUM],
+	(info.byte_order == BFD_ENDIAN_LITTLE ? "acch" : "accl"),
+	NULL
+      };
+
+      switch (i)
+	{
+	case ARC_R58_REGNUM:
+	  valid_p = tdesc_numbered_register_choices (feature, tdesc_data_loc,
+						     i, r58_names);
+	  break;
+	case ARC_R59_REGNUM:
+	  valid_p = tdesc_numbered_register_choices (feature, tdesc_data_loc,
+						     i, r59_names);
+	  break;
+	default:
+	  valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i,
+					     core_regs[i]);
+	}
 
       /* - Ignore errors in extension registers - they are optional.
 	 - Ignore missing ILINK because it doesn't make sense for Linux.
-	 - Ignore missing ILINK2 when architecture is ARCompact, because it
-	 doesn't make sense for Linux targets.
+	 - Ignore missing ILINK2 when architecture is ARCompact, because
+	 it doesn't make sense for Linux targets.
 
-	 In theory those optional registers should be in separate features, but
-	 that would create numerous but tiny features, which looks like an
-	 overengineering of a rather simple task.  */
+	 In theory those optional registers should be in separate
+	 features, but that would create numerous but tiny features, which
+	 looks like an overengineering of a rather simple task.  */
       if (!valid_p && (i <= ARC_SP_REGNUM || i == ARC_BLINK_REGNUM
 		       || i == ARC_LP_COUNT_REGNUM || i == ARC_PCL_REGNUM
 		       || (i == ARC_R30_REGNUM && is_arcv2)))
@@ -1895,7 +1922,9 @@ arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
     {
       const char *name = aux_minimal_register_names[i - ARC_FIRST_AUX_REGNUM];
       valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i, name);
-      if (!valid_p)
+
+      /* Only STATUS32 and PC are mandatory.  */
+      if (!valid_p && (i == ARC_PC_REGNUM || i == ARC_STATUS32_REGNUM))
 	{
 	  arc_print (_("Error: Cannot find required register `%s' "
 		       "in feature `%s'.\n"),
@@ -1903,6 +1932,11 @@ arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
 	  tdesc_data_cleanup (tdesc_data_loc);
 	  return false;
 	}
+      /* Hardware loops present if both its registers are.  */
+      else if (ARC_LP_START_REGNUM == i)
+	tdep->has_hw_loops = valid_p;
+      else if (ARC_LP_END_REGNUM == i)
+	tdep->has_hw_loops &= valid_p;
     }
 
   *tdesc = tdesc_loc;
@@ -1950,13 +1984,17 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   if (arc_debug)
     debug_printf ("arc: Architecture initialization.\n");
 
-  if (!arc_tdesc_init (info, &tdesc, &tdesc_data))
-    return NULL;
-
   /* Allocate the ARC-private target-dependent information structure, and the
      GDB target-independent information structure.  */
   struct gdbarch_tdep *tdep = XCNEW (struct gdbarch_tdep);
   tdep->jb_pc = -1; /* No longjmp support by default.  */
+
+  if (!arc_tdesc_init (info, &tdesc, &tdesc_data, tdep))
+    {
+      xfree (tdep);
+      return nullptr;
+    }
+
   struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep);
 
   /* Data types.  */
@@ -1987,6 +2025,13 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_ps_regnum (gdbarch, ARC_STATUS32_REGNUM);
   set_gdbarch_fp0_regnum (gdbarch, -1);	/* No FPU registers.  */
 
+  /* Confirm that register name lists have proper length.  */
+  gdb_static_assert (ARC_LAST_REGNUM + 1
+		     == (ARRAY_SIZE (core_v2_register_names)
+			 + ARRAY_SIZE (aux_minimal_register_names)));
+  gdb_static_assert (ARRAY_SIZE (core_v2_register_names)
+		     == ARRAY_SIZE (core_arcompact_register_names));
+
   set_gdbarch_push_dummy_call (gdbarch, arc_push_dummy_call);
   set_gdbarch_push_dummy_code (gdbarch, arc_push_dummy_code);
 
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index d72332c7638..8fd8571457f 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -23,6 +23,7 @@
 
 /* Need disassemble_info.  */
 #include "dis-asm.h"
+#include "gdbarch.h"
 #include "arch/arc.h"
 
 /* To simplify GDB code this enum assumes that internal regnums should be same
@@ -54,6 +55,8 @@ enum arc_regnum
     ARC_R30_REGNUM,
     /* Return address from function.  */
     ARC_BLINK_REGNUM,
+    ARC_R58_REGNUM = 58,
+    ARC_R59_REGNUM,
     /* Zero-delay loop counter.  */
     ARC_LP_COUNT_REGNUM = 60,
     /* Reserved register number.  There should never be a register with such
@@ -69,14 +72,21 @@ enum arc_regnum
     /* Program counter, aligned to 4-bytes, read-only.  */
     ARC_PCL_REGNUM,
     ARC_LAST_CORE_REGNUM = ARC_PCL_REGNUM,
+
     /* AUX registers.  */
     /* Actual program counter.  */
     ARC_PC_REGNUM,
     ARC_FIRST_AUX_REGNUM = ARC_PC_REGNUM,
     /* Status register.  */
     ARC_STATUS32_REGNUM,
-    ARC_LAST_REGNUM = ARC_STATUS32_REGNUM,
-    ARC_LAST_AUX_REGNUM = ARC_STATUS32_REGNUM,
+    /* Zero-delay loop start instruction.  */
+    ARC_LP_START_REGNUM,
+    /* Zero-delay loop next-after-last instruction.  */
+    ARC_LP_END_REGNUM,
+    /* Branch target address.  */
+    ARC_BTA_REGNUM,
+    ARC_LAST_AUX_REGNUM = ARC_BTA_REGNUM,
+    ARC_LAST_REGNUM = ARC_LAST_AUX_REGNUM,
 
     /* Additional ABI constants.  */
     ARC_FIRST_ARG_REGNUM = ARC_R0_REGNUM,
@@ -101,6 +111,9 @@ struct gdbarch_tdep
   /* Offset to PC value in jump buffer.  If this is negative, longjmp
      support will be disabled.  */
   int jb_pc;
+
+  /* Whether target has hardware (aka zero-delay) loops.  */
+  bool has_hw_loops;
 };
 
 /* Utility functions used by other ARC-specific modules.  */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 385c832f222..1671d44c6c8 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -45115,7 +45115,8 @@ difference with @samp{org.gnu.gdb.arc.core.v2} feature is in the names of
 ARC v2, but @samp{ilink2} is optional on ARCompact.
 
 The @samp{org.gnu.gdb.arc.aux-minimal} feature is required for all ARC
-targets.  It should contain registers @samp{pc} and @samp{status32}.
+targets.  It should contain registers @samp{pc} and @samp{status32}.  It may
+contain registers @samp{lp_start}, @samp{lp_end} and @samp{bta}.
 
 @node ARM Features
 @subsection ARM Features
-- 
2.26.2


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v2 3/4] arc: Add GNU/Linux support for ARC
  2020-04-28 16:04 ` [PATCH v2 " Shahab Vahedi
  2020-04-28 16:04   ` [PATCH v2 1/4] arc: Add XML target features for Linux targets Shahab Vahedi
  2020-04-28 16:04   ` [PATCH v2 2/4] arc: Recognize registers available on " Shahab Vahedi
@ 2020-04-28 16:04   ` Shahab Vahedi
  2020-05-14 15:09     ` Simon Marchi
  2020-04-28 16:04   ` [PATCH v2 4/4] arc: Add arc-*-linux regformats Shahab Vahedi
                     ` (2 subsequent siblings)
  5 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-04-28 16:04 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Tom Tromey, Anton Kolesov,
	Francois Bedard, Anton Kolesov

From: Anton Kolesov <Anton.Kolesov@synopsys.com>

ARC Linux targets differences from baremetal:

- No support for hardware single instruction stepping.
- Different access rules to registers.
- Use of another instruction for breakpoints.

v2: Changes after Tom's remarks
 arc-linux-tdep.c
  - Use true/false instead of TRUE/FALSE.
  - arc_linux_sw_breakpoint_from_kind (): Break long lines into two.
  - arc_linux_sw_breakpoint_from_kind (): Remove starting blank line.
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 arc-tdep.c
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 gdb/configure.tgt
  - arc*-*-linux*): Remove "build_gdbserver=yes".

2020-04-28  Anton Kolesov  <anton.kolesov@synopsys.com>

	* configure.tgt: ARC support for GNU/Linux.
	* Makefile.in (ALL_TARGET_OBJS): Likewise.
	* arc-linux-tdep.c: New file.
	* arc-tdep.h (ARC_STATUS32_L_MASK, ARC_STATUS32_DE_MASK): Declare.
	* arc-tdep.c (arc_write_pc): Use it.
---
 gdb/Makefile.in      |   1 +
 gdb/arc-linux-tdep.c | 284 +++++++++++++++++++++++++++++++++++++++++++
 gdb/arc-tdep.c       |   3 +-
 gdb/arc-tdep.h       |   5 +
 gdb/configure.tgt    |   5 +
 5 files changed, 296 insertions(+), 2 deletions(-)
 create mode 100644 gdb/arc-linux-tdep.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 0c331af4bff..028992ab664 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -695,6 +695,7 @@ ALL_64_TARGET_OBS = \
 # All other target-dependent objects files (used with --enable-targets=all).
 ALL_TARGET_OBS = \
 	aarch32-tdep.o \
+	arc-linux-tdep.o \
 	arc-tdep.o \
 	arch/aarch32.o \
 	arch/arc.o \
diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
new file mode 100644
index 00000000000..91eac68ebb5
--- /dev/null
+++ b/gdb/arc-linux-tdep.c
@@ -0,0 +1,284 @@
+/* Target dependent code for GNU/Linux ARC.
+
+   Copyright 2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* GDB header files.  */
+#include "defs.h"
+#include "linux-tdep.h"
+#include "objfiles.h"
+#include "opcode/arc.h"
+#include "osabi.h"
+#include "solib-svr4.h"
+
+/* ARC header files.  */
+#include "opcodes/arc-dis.h"
+#include "arc-tdep.h"
+
+/* Implement the "cannot_fetch_register" gdbarch method.  */
+
+static int
+arc_linux_cannot_fetch_register (struct gdbarch *gdbarch, int regnum)
+{
+  /* Assume that register is readable if it is unknown.  */
+  switch (regnum)
+    {
+    case ARC_ILINK_REGNUM:
+    case ARC_RESERVED_REGNUM:
+    case ARC_LIMM_REGNUM:
+      return true;
+    case ARC_R30_REGNUM:
+    case ARC_R58_REGNUM:
+    case ARC_R59_REGNUM:
+      return !arc_mach_is_arcv2 (gdbarch);
+    }
+  if (regnum > ARC_BLINK_REGNUM && regnum < ARC_LP_COUNT_REGNUM)
+    return true;
+  return false;
+}
+
+/* Implement the "cannot_store_register" gdbarch method.  */
+
+static int
+arc_linux_cannot_store_register (struct gdbarch *gdbarch, int regnum)
+{
+  /* Assume that register is writable if it is unknown.  */
+  switch (regnum)
+    {
+    case ARC_ILINK_REGNUM:
+    case ARC_RESERVED_REGNUM:
+    case ARC_LIMM_REGNUM:
+    case ARC_PCL_REGNUM:
+      return true;
+    case ARC_R30_REGNUM:
+    case ARC_R58_REGNUM:
+    case ARC_R59_REGNUM:
+      return !arc_mach_is_arcv2 (gdbarch);
+    }
+  if (regnum > ARC_BLINK_REGNUM && regnum < ARC_LP_COUNT_REGNUM)
+    return true;
+  return false;
+}
+
+/* For ARC Linux, breakpoint uses the 16-bit TRAP_S 1 instruction, which
+   is 0x3e78 (little endian) or 0x783e (big endian).  */
+
+static const gdb_byte arc_linux_trap_s_be[] = { 0x78, 0x3e };
+static const gdb_byte arc_linux_trap_s_le[] = { 0x3e, 0x78 };
+
+/* Implement the "breakpoint_kind_from_pc" gdbarch method.  */
+
+static int
+arc_linux_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+  return 2;
+}
+
+/* Implement the "sw_breakpoint_from_kind" gdbarch method.  */
+
+static const gdb_byte *
+arc_linux_sw_breakpoint_from_kind (struct gdbarch *gdbarch,
+				   int kind, int *size)
+{
+  *size = kind;
+  return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+	  ? arc_linux_trap_s_be
+	  : arc_linux_trap_s_le);
+}
+
+/* Implement the "software_single_step" gdbarch method.  */
+
+static std::vector<CORE_ADDR>
+arc_linux_software_single_step (struct regcache *regcache)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct disassemble_info di = arc_disassemble_info (gdbarch);
+
+  /* Read current instruction.  */
+  struct arc_instruction curr_insn;
+  arc_insn_decode (regcache_read_pc (regcache), &di, arc_delayed_print_insn,
+		   &curr_insn);
+  CORE_ADDR next_pc = arc_insn_get_linear_next_pc (curr_insn);
+
+  std::vector<CORE_ADDR> next_pcs;
+
+  /* For instructions with delay slots, the fall thru is not the
+     instruction immediately after the current instruction, but the one
+     after that.  */
+  if (curr_insn.has_delay_slot)
+    {
+      struct arc_instruction next_insn;
+      arc_insn_decode (next_pc, &di, arc_delayed_print_insn, &next_insn);
+      next_pcs.push_back (arc_insn_get_linear_next_pc (next_insn));
+    }
+  else
+    {
+      next_pcs.push_back (next_pc);
+    }
+
+  ULONGEST status32;
+  regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
+				 &status32);
+
+  if (curr_insn.is_control_flow)
+    {
+      CORE_ADDR branch_pc = arc_insn_get_branch_target (curr_insn);
+      if (branch_pc != next_pc)
+	next_pcs.push_back (branch_pc);
+    }
+  /* Is current instruction the last in a loop body?  */
+  else if (tdep->has_hw_loops)
+    {
+      /* If STATUS32.L is 1, then ZD-loops are disabled.  */
+      if ((status32 & ARC_STATUS32_L_MASK) == 0)
+	{
+	  ULONGEST lp_end, lp_start, lp_count;
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_START_REGNUM,
+					 &lp_start);
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_END_REGNUM, &lp_end);
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_COUNT_REGNUM,
+					 &lp_count);
+
+	  if (arc_debug)
+	    {
+	      debug_printf ("arc-linux: lp_start = %s, lp_end = %s, "
+			    "lp_count = %s, next_pc = %s\n",
+			    paddress (gdbarch, lp_start),
+			    paddress (gdbarch, lp_end),
+			    pulongest (lp_count),
+			    paddress (gdbarch, next_pc));
+	    }
+
+	  if (next_pc == lp_end && lp_count > 1)
+	    {
+	      /* The instruction is in effect a jump back to the start of
+		 the loop.  */
+	      next_pcs.push_back (lp_start);
+	    }
+
+	}
+    }
+
+  /* Is this a delay slot?  Then next PC is in BTA register.  */
+  if ((status32 & ARC_STATUS32_DE_MASK) != 0)
+    {
+      ULONGEST bta;
+      regcache_cooked_read_unsigned (regcache, ARC_BTA_REGNUM, &bta);
+      next_pcs.push_back (bta);
+    }
+
+  return next_pcs;
+}
+
+/* Implement the "skip_solib_resolver" gdbarch method.
+
+   See glibc_skip_solib_resolver for details.  */
+
+static CORE_ADDR
+arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  /* For uClibc 0.9.26+.
+
+     An unresolved PLT entry points to "__dl_linux_resolve", which calls
+     "_dl_linux_resolver" to do the resolving and then eventually jumps to
+     the function.
+
+     So we look for the symbol `_dl_linux_resolver', and if we are there,
+     gdb sets a breakpoint at the return address, and continues.  */
+  struct bound_minimal_symbol resolver =
+    lookup_minimal_symbol ("_dl_linux_resolver", NULL, NULL);
+
+  if (arc_debug)
+    {
+      if (resolver.minsym)
+	{
+	  CORE_ADDR res_addr = BMSYMBOL_VALUE_ADDRESS (resolver);
+	  debug_printf ("arc-linux: skip_solib_resolver (): "
+			"pc = %s, resolver at %s\n",
+			print_core_address (gdbarch, pc),
+			print_core_address (gdbarch, res_addr));
+	}
+      else
+	{
+	  debug_printf ("arc-linux: skip_solib_resolver (): "
+			"pc = %s, no resolver found\n",
+			print_core_address (gdbarch, pc));
+	}
+    }
+
+  if (resolver.minsym && BMSYMBOL_VALUE_ADDRESS (resolver) == pc)
+    {
+      /* Find the return address.  */
+      return frame_unwind_caller_pc (get_current_frame ());
+    }
+  else
+    {
+      /* No breakpoint required.  */
+      return 0;
+    }
+}
+
+/* Initialization specific to Linux environment.  */
+
+static void
+arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (arc_debug)
+    debug_printf ("arc-linux: GNU/Linux OS/ABI initialization.\n");
+
+  /* If we are using Linux, we have in uClibc
+     (libc/sysdeps/linux/arc/bits/setjmp.h):
+
+     typedef int __jmp_buf[13+1+1+1];    //r13-r25, fp, sp, blink
+
+     Where "blink" is a stored PC of a caller function.
+   */
+  tdep->jb_pc = 15;
+
+  linux_init_abi (info, gdbarch);
+
+  /* Set up target dependent GDB architecture entries.  */
+  set_gdbarch_cannot_fetch_register (gdbarch, arc_linux_cannot_fetch_register);
+  set_gdbarch_cannot_store_register (gdbarch, arc_linux_cannot_store_register);
+  set_gdbarch_breakpoint_kind_from_pc (gdbarch,
+				       arc_linux_breakpoint_kind_from_pc);
+  set_gdbarch_sw_breakpoint_from_kind (gdbarch,
+				       arc_linux_sw_breakpoint_from_kind);
+  set_gdbarch_fetch_tls_load_module_address (gdbarch,
+					     svr4_fetch_objfile_link_map);
+  set_gdbarch_software_single_step (gdbarch, arc_linux_software_single_step);
+  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+  set_gdbarch_skip_solib_resolver (gdbarch, arc_linux_skip_solib_resolver);
+
+  /* GNU/Linux uses SVR4-style shared libraries, with 32-bit ints, longs
+     and pointers (ILP32).  */
+  set_solib_svr4_fetch_link_map_offsets (gdbarch,
+					 svr4_ilp32_fetch_link_map_offsets);
+}
+
+/* Suppress warning from -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_arc_linux_tdep;
+
+void
+_initialize_arc_linux_tdep (void)
+{
+  gdbarch_register_osabi (bfd_arch_arc, 0, GDB_OSABI_LINUX,
+			  arc_linux_init_osabi);
+}
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 878728bc62c..b3d1e192ceb 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -462,8 +462,7 @@ arc_write_pc (struct regcache *regcache, CORE_ADDR new_pc)
   regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
 				 &status32);
 
-  /* Mask for DE bit is 0x40.  */
-  if (status32 & 0x40)
+  if ((status32 & ARC_STATUS32_DE_MASK) != 0)
     {
       if (arc_debug)
 	{
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index 8fd8571457f..015ef3d4953 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -100,6 +100,11 @@ enum arc_regnum
    Longer registers are represented as pairs of 32-bit registers.  */
 #define ARC_REGISTER_SIZE  4
 
+/* STATUS32 register: hardware loops disabled bit.  */
+#define ARC_STATUS32_L_MASK (1 << 12)
+/* STATUS32 register: current instruction is a delay slot.  */
+#define ARC_STATUS32_DE_MASK (1 << 6)
+
 #define arc_print(fmt, args...) fprintf_unfiltered (gdb_stdlog, fmt, ##args)
 
 extern int arc_debug;
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index b3f31af763c..1a5c3a351fd 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -157,6 +157,11 @@ arc*-*-elf32)
 	gdb_target_obs="arc-newlib-tdep.o"
 	;;
 
+arc*-*-linux*)
+	# Target: ARC machine running Linux
+	gdb_target_obs="arc-linux-tdep.o linux-tdep.o solib-svr4.o"
+	;;
+
 arm*-wince-pe | arm*-*-mingw32ce*)
 	# Target: ARM based machine running Windows CE (win32)
 	gdb_target_obs="arm-wince-tdep.o windows-tdep.o"
-- 
2.26.2


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v2 4/4] arc: Add arc-*-linux regformats
  2020-04-28 16:04 ` [PATCH v2 " Shahab Vahedi
                     ` (2 preceding siblings ...)
  2020-04-28 16:04   ` [PATCH v2 3/4] arc: Add GNU/Linux support for ARC Shahab Vahedi
@ 2020-04-28 16:04   ` Shahab Vahedi
  2020-05-14 15:12     ` Simon Marchi
  2020-05-14 11:43   ` [PATCH v2 0/4] arc: Add GNU/Linux support Shahab Vahedi
  2020-07-13 15:45   ` [PATCH v3 0/3] " Shahab Vahedi
  5 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-04-28 16:04 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Tom Tromey, Anton Kolesov,
	Francois Bedard, Anton Kolesov

From: Anton Kolesov <Anton.Kolesov@synopsys.com>

gdb/ChangeLog:
2020-04-28  Anton Kolesov <anton.kolesov@synopsys.com>

	* features/Makefile: Add new files and expedite registers.
	* regformats/arc-arcompact-Linux.dat: New file.
	* regformats/arc-v2-Linux.dat: Likewise.
---
 gdb/features/Makefile                  |  4 ++-
 gdb/regformats/arc-arcompact-linux.dat | 42 ++++++++++++++++++++++++
 gdb/regformats/arc-v2-linux.dat        | 45 ++++++++++++++++++++++++++
 3 files changed, 90 insertions(+), 1 deletion(-)
 create mode 100644 gdb/regformats/arc-arcompact-linux.dat
 create mode 100644 gdb/regformats/arc-v2-linux.dat

diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index a95be667dc1..312c4f53185 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -44,7 +44,8 @@
 #   make GDB=/path/to/gdb XMLTOC="xml files" FEATURE_XMLFILES="xml files" cfiles
 
 # List of .dat files to create in ../regformats/
-WHICH = arm/arm-with-iwmmxt arm/arm-with-vfpv2 arm/arm-with-vfpv3 \
+WHICH = arc-v2-linux arc-arcompact-linux \
+	arm/arm-with-iwmmxt arm/arm-with-vfpv2 arm/arm-with-vfpv3 \
 	arm/arm-with-neon \
 	mips-linux mips-dsp-linux \
 	microblaze-with-stack-protect \
@@ -72,6 +73,7 @@ WHICH = arm/arm-with-iwmmxt arm/arm-with-vfpv2 arm/arm-with-vfpv3 \
 
 # Record which registers should be sent to GDB by default after stop.
 aarch64-expedite = x29,sp,pc
+arc-expedite = sp,pc
 arm-expedite = r11,sp,pc
 i386-expedite = ebp,esp,eip
 amd64-expedite = rbp,rsp,rip
diff --git a/gdb/regformats/arc-arcompact-linux.dat b/gdb/regformats/arc-arcompact-linux.dat
new file mode 100644
index 00000000000..1d35860af3d
--- /dev/null
+++ b/gdb/regformats/arc-arcompact-linux.dat
@@ -0,0 +1,42 @@
+# THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi :set ro:
+# Generated from: arc-arcompact-linux.xml
+name:arc_arcompact_linux
+xmltarget:arc-arcompact-linux.xml
+expedite:sp,pc
+32:r0
+32:r1
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:r8
+32:r9
+32:r10
+32:r11
+32:r12
+32:r13
+32:r14
+32:r15
+32:r16
+32:r17
+32:r18
+32:r19
+32:r20
+32:r21
+32:r22
+32:r23
+32:r24
+32:r25
+32:gp
+32:fp
+32:sp
+32:blink
+32:lp_count
+32:pcl
+32:pc
+32:status32
+32:lp_start
+32:lp_end
+32:bta
diff --git a/gdb/regformats/arc-v2-linux.dat b/gdb/regformats/arc-v2-linux.dat
new file mode 100644
index 00000000000..7e5d1904664
--- /dev/null
+++ b/gdb/regformats/arc-v2-linux.dat
@@ -0,0 +1,45 @@
+# THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi :set ro:
+# Generated from: arc-v2-linux.xml
+name:arc_v2_linux
+xmltarget:arc-v2-linux.xml
+expedite:sp,pc
+32:r0
+32:r1
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:r8
+32:r9
+32:r10
+32:r11
+32:r12
+32:r13
+32:r14
+32:r15
+32:r16
+32:r17
+32:r18
+32:r19
+32:r20
+32:r21
+32:r22
+32:r23
+32:r24
+32:r25
+32:gp
+32:fp
+32:sp
+32:r30
+32:blink
+32:r58
+32:r59
+32:lp_count
+32:pcl
+32:pc
+32:status32
+32:lp_start
+32:lp_end
+32:bta
-- 
2.26.2


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v2 2/4] arc: Recognize registers available on Linux targets
  2020-04-28 16:04   ` [PATCH v2 2/4] arc: Recognize registers available on " Shahab Vahedi
@ 2020-04-28 16:56     ` Eli Zaretskii
  2020-05-14 15:01     ` Simon Marchi
  1 sibling, 0 replies; 86+ messages in thread
From: Eli Zaretskii @ 2020-04-28 16:56 UTC (permalink / raw)
  To: Shahab Vahedi; +Cc: gdb-patches, shahab, Anton.Kolesov, tom, fbedard

> Date: Tue, 28 Apr 2020 18:04:35 +0200
> From: Shahab Vahedi via Gdb-patches <gdb-patches@sourceware.org>
> Cc: Shahab Vahedi <shahab.vahedi@gmail.com>,
>  Shahab Vahedi <shahab@synopsys.com>,
>  Anton Kolesov <Anton.Kolesov@synopsys.com>, Tom Tromey <tom@tromey.com>,
>  Francois Bedard <fbedard@synopsys.com>
> 
> gdb/ChangeLog:
> 2020-04-28  Anton Kolesov  <anton.kolesov@synopsys.com>
> 
> 	* arc-tdep.c (core_v2_register_names): Fix names of R58 and R59.
> 	(aux_minimal_register_names): Add LP_START, LP_END and BTA.
> 	(arc_tdesc_init): Recognize those registers.
> 	* arc-tdep.h (arc_regnum): Add R58, R59, LP_START, LP_END and BTA.
> 	(gdbarch_tdep): New field has_hw_loops.
> 
> gdb/doc/ChangeLog:
> 2020-04-28  Anton Kolesov  <anton.kolesov@synopsys.com>
> 
> 	* gdb.texinfo (Synopsys ARC): Document LP_START, LP_END and BTA.

OK for the gdb.texinfo part.

Thanks.

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v2 0/4] arc: Add GNU/Linux support
  2020-04-28 16:04 ` [PATCH v2 " Shahab Vahedi
                     ` (3 preceding siblings ...)
  2020-04-28 16:04   ` [PATCH v2 4/4] arc: Add arc-*-linux regformats Shahab Vahedi
@ 2020-05-14 11:43   ` Shahab Vahedi
  2020-07-13 15:45   ` [PATCH v3 0/3] " Shahab Vahedi
  5 siblings, 0 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-05-14 11:43 UTC (permalink / raw)
  To: Shahab Vahedi, gdb-patches; +Cc: Tom Tromey, Anton Kolesov, Francois Bedard

A gentle reminder for the _second_ version of the patch series in:

https://sourceware.org/pipermail/gdb-patches/2020-April/168003.html

I appreciate taking the time to review it.

--
Shahab

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v2 1/4] arc: Add XML target features for Linux targets
  2020-04-28 16:04   ` [PATCH v2 1/4] arc: Add XML target features for Linux targets Shahab Vahedi
@ 2020-05-14 14:49     ` Simon Marchi
  0 siblings, 0 replies; 86+ messages in thread
From: Simon Marchi @ 2020-05-14 14:49 UTC (permalink / raw)
  To: Shahab Vahedi, gdb-patches
  Cc: Shahab Vahedi, Anton Kolesov, Tom Tromey, Francois Bedard

On 2020-04-28 12:04 p.m., Shahab Vahedi via Gdb-patches wrote:
> From: Anton Kolesov <Anton.Kolesov@synopsys.com>
> 
> Add XML target features for Linux targets.  Compared to default
> Linux features:
> 
> - Explicitly specify CPU machine.
> - Remove baremetal only ILINK{,1,2} registers.
> - Add LP_START and LP_END registers for hardware loops - required to
>   properly evaluate possible next instruction during software single
>   instruction stepping.
> - Add BTA register which contains branch target address - address of
>   next instruction when processor is in the delay slot.
> - ARC HS description also adds R30, R58 and R59 registers, specific to
>   this architecture.
> 
> gdb/ChangeLog:
> 2020-04-28  Anton Kolesov  <anton.kolesov@synopsys.com>
> 
> 	* arch/arc.h (arc_create_target_description): Support Linux targets.
> 	* arch/arc.c (arc_create_target_description): Likewise.
> 	* arc-tdep.c (arc_tdesc_init): Update invocation of
> 	  arc_read_description.
> 	* features/Makefile (FEATURE_XMLFILES): Add new files.
> 	* features/arc/aux-arcompact-linux.xml: New file.
> 	* features/arc/aux-v2-linux.xml: Likewise.
> 	* features/arc/core-arcompact-linux.xml: Likewise.
> 	* features/arc/core-v2-linux.xml: Likewise.
> 	* features/arc/aux-arcompact-linux.c: Generate.
> 	* features/arc/aux-v2-linux.c: Likewise.
> 	* features/arc/core-arcompact-linux.c: Likewise.
> 	* features/arc/core-v2-linux.c: Likewise.

Hi Shahab,

Instead of having multiple almost identical features, it's now usual
to build small features and compose them into the full target description.

For example, instead of having both:

- core-arcompact.xml
- core-arcompact-linux.xml

I think you should have:

- core-arcompact.xml, containing everything that's common in the two above
- core-arcompact-baremetal.xml, containing only the registers that are only present
  in the baremetal version.

When building the target description, the pseudo code would look like:

  if (arcompact)
    create_core_arcompact_feature ();
  else
    create_core_v2_feature ();

  if (baremetal) // or if (!linux)
    {
      if (arcompact)
        create_core_arccompact_baremetal_feature ();
      else
        create_core_v2_baremetal_feature ();
    }

Same goes for aux.  The i386 and arm target descriptions have examples of how to do
that.

Note that I don't know if the order of the registers in the target description
matters...  if so it could make this more difficult.

> @@ -37,21 +41,39 @@ arc_create_target_description (arc_sys_type sys_type)
>    long regnum = 0;
>  
>  #ifndef IN_PROCESS_AGENT
> -  if (sys_type == ARC_SYS_TYPE_ARCV2)
> +  if (sys_type == ARC_SYS_TYPE_ARCV2_BMT)
>      set_tdesc_architecture (tdesc, "arc:ARCv2");
> +  else if (sys_type == ARC_SYS_TYPE_ARCV2_LNX)
> +    /* If this is ARCv2 Linux, then it is ARC HS.  */
> +    set_tdesc_architecture (tdesc, "arc:HS");
>    else
>      set_tdesc_architecture (tdesc, "arc:ARC700");
> +
> +  if (sys_type == ARC_SYS_TYPE_ARCOMPACT_LNX
> +      || sys_type == ARC_SYS_TYPE_ARCV2_LNX)
> +    set_tdesc_osabi (tdesc, "GNU/Linux");
>  #endif
>  
> -  if (sys_type == ARC_SYS_TYPE_ARCV2)
> -    {
> -      regnum = create_feature_arc_core_v2 (tdesc, regnum);
> -      regnum = create_feature_arc_aux_v2 (tdesc, regnum);
> -    }
> -  else
> +  switch (sys_type)
>      {
> -      regnum = create_feature_arc_core_arcompact (tdesc, regnum);
> -      regnum = create_feature_arc_aux_arcompact (tdesc, regnum);
> +    case ARC_SYS_TYPE_ARCOMPACT_BMT:
> +	  regnum = create_feature_arc_core_arcompact (tdesc, regnum);
> +	  regnum = create_feature_arc_aux_arcompact (tdesc, regnum);
> +	  break;
> +    case ARC_SYS_TYPE_ARCOMPACT_LNX:
> +	  regnum = create_feature_arc_core_arcompact_linux (tdesc, regnum);
> +	  regnum = create_feature_arc_aux_arcompact_linux (tdesc, regnum);
> +	  break;
> +    case ARC_SYS_TYPE_ARCV2_BMT:
> +	  regnum = create_feature_arc_core_v2 (tdesc, regnum);
> +	  regnum = create_feature_arc_aux_v2 (tdesc, regnum);
> +	  break;
> +    case ARC_SYS_TYPE_ARCV2_LNX:
> +	  regnum = create_feature_arc_core_v2_linux (tdesc, regnum);
> +	  regnum = create_feature_arc_aux_v2_linux (tdesc, regnum);
> +	  break;
> +    default:
> +	  gdb_assert(!"Invalid arc_sys_type.");
>      }

The goal of having descriptions built at runtime with features is to avoid
this kind of combinatorial explosion.  Now, you have two axis of configuration
(arcompact vs arcv2, bare-metal vs linux).  If you had more, it would become
less and less practical.  That's why I would encourage you to consider what I
said above.

>  
>    return tdesc;
> diff --git a/gdb/arch/arc.h b/gdb/arch/arc.h
> index fd806ae7d34..3c19118b946 100644
> --- a/gdb/arch/arc.h
> +++ b/gdb/arch/arc.h
> @@ -23,8 +23,10 @@
>  /* Supported ARC system hardware types.  */
>  enum arc_sys_type
>  {
> -  ARC_SYS_TYPE_ARCOMPACT = 0,	  /* ARC600 or ARC700 */
> -  ARC_SYS_TYPE_ARCV2,		  /* ARC EM or ARC HS */
> +  ARC_SYS_TYPE_ARCOMPACT_BMT = 0, /* ARC600 or ARC700 (baremetal) */
> +  ARC_SYS_TYPE_ARCOMPACT_LNX,	  /* ARC600 or ARC700 (linux) */
> +  ARC_SYS_TYPE_ARCV2_BMT,	  /* ARC EM or ARC HS (baremetal) */
> +  ARC_SYS_TYPE_ARCV2_LNX,	  /* ARC HS (linux) */
>    ARC_SYS_TYPE_NUM

That's also not expected.  The fact that the target system is running Linux
should be handled by the fact that the selected osabi will be Linux.  So
you shouldn't need any changes here.

Simon

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v2 2/4] arc: Recognize registers available on Linux targets
  2020-04-28 16:04   ` [PATCH v2 2/4] arc: Recognize registers available on " Shahab Vahedi
  2020-04-28 16:56     ` Eli Zaretskii
@ 2020-05-14 15:01     ` Simon Marchi
  2020-06-17 15:46       ` Shahab Vahedi
  1 sibling, 1 reply; 86+ messages in thread
From: Simon Marchi @ 2020-05-14 15:01 UTC (permalink / raw)
  To: Shahab Vahedi, gdb-patches
  Cc: Shahab Vahedi, Anton Kolesov, Tom Tromey, Francois Bedard

Just some nits - I don't really know about the specific details of the ARC architecture.

On 2020-04-28 12:04 p.m., Shahab Vahedi via Gdb-patches wrote:
> @@ -1950,13 +1984,17 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>    if (arc_debug)
>      debug_printf ("arc: Architecture initialization.\n");
>  
> -  if (!arc_tdesc_init (info, &tdesc, &tdesc_data))
> -    return NULL;
> -
>    /* Allocate the ARC-private target-dependent information structure, and the
>       GDB target-independent information structure.  */
>    struct gdbarch_tdep *tdep = XCNEW (struct gdbarch_tdep);
>    tdep->jb_pc = -1; /* No longjmp support by default.  */
> +
> +  if (!arc_tdesc_init (info, &tdesc, &tdesc_data, tdep))
> +    {
> +      xfree (tdep);
> +      return nullptr;
> +    }
> +

I would suggest to do it in a bit more C++-y way, to even avoid the xfree:

  gdb::unique_xmalloc_ptr<gdbarch_tdep> tdep (XCNEW (struct gdbarch_tdep));
  tdep->jb_pc = -1; /* No longjmp support by default.  */

  if (!arc_tdesc_init (info, &tdesc, &tdesc_data, tdep.get ()))
    return nullptr;

  struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep.release ());

This way it shows clearly that this function is giving ownership of the tdep
to gdbarch_alloc.

>    struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep);
>  
>    /* Data types.  */
> @@ -1987,6 +2025,13 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>    set_gdbarch_ps_regnum (gdbarch, ARC_STATUS32_REGNUM);
>    set_gdbarch_fp0_regnum (gdbarch, -1);	/* No FPU registers.  */
>  
> +  /* Confirm that register name lists have proper length.  */
> +  gdb_static_assert (ARC_LAST_REGNUM + 1
> +		     == (ARRAY_SIZE (core_v2_register_names)
> +			 + ARRAY_SIZE (aux_minimal_register_names)));
> +  gdb_static_assert (ARRAY_SIZE (core_v2_register_names)
> +		     == ARRAY_SIZE (core_arcompact_register_names));

Does this need to be here?  I would expect them to be near (just after) the definitions
of said arrays.

Simon


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v2 3/4] arc: Add GNU/Linux support for ARC
  2020-04-28 16:04   ` [PATCH v2 3/4] arc: Add GNU/Linux support for ARC Shahab Vahedi
@ 2020-05-14 15:09     ` Simon Marchi
  2020-06-15 23:13       ` Shahab Vahedi
  0 siblings, 1 reply; 86+ messages in thread
From: Simon Marchi @ 2020-05-14 15:09 UTC (permalink / raw)
  To: Shahab Vahedi, gdb-patches
  Cc: Shahab Vahedi, Anton Kolesov, Tom Tromey, Francois Bedard

On 2020-04-28 12:04 p.m., Shahab Vahedi via Gdb-patches wrote:
> +/* Implement the "breakpoint_kind_from_pc" gdbarch method.  */
> +
> +static int
> +arc_linux_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
> +{
> +  return 2;

What is 2?

> +}
> +
> +/* Implement the "sw_breakpoint_from_kind" gdbarch method.  */
> +
> +static const gdb_byte *
> +arc_linux_sw_breakpoint_from_kind (struct gdbarch *gdbarch,
> +				   int kind, int *size)
> +{
> +  *size = kind;
> +  return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
> +	  ? arc_linux_trap_s_be
> +	  : arc_linux_trap_s_le);
> +}
> +
> +/* Implement the "software_single_step" gdbarch method.  */
> +
> +static std::vector<CORE_ADDR>
> +arc_linux_software_single_step (struct regcache *regcache)
> +{
> +  struct gdbarch *gdbarch = regcache->arch ();
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  struct disassemble_info di = arc_disassemble_info (gdbarch);
> +
> +  /* Read current instruction.  */
> +  struct arc_instruction curr_insn;
> +  arc_insn_decode (regcache_read_pc (regcache), &di, arc_delayed_print_insn,
> +		   &curr_insn);
> +  CORE_ADDR next_pc = arc_insn_get_linear_next_pc (curr_insn);
> +
> +  std::vector<CORE_ADDR> next_pcs;
> +
> +  /* For instructions with delay slots, the fall thru is not the
> +     instruction immediately after the current instruction, but the one
> +     after that.  */
> +  if (curr_insn.has_delay_slot)
> +    {
> +      struct arc_instruction next_insn;
> +      arc_insn_decode (next_pc, &di, arc_delayed_print_insn, &next_insn);
> +      next_pcs.push_back (arc_insn_get_linear_next_pc (next_insn));
> +    }
> +  else
> +    {
> +      next_pcs.push_back (next_pc);
> +    }

Remove curly braces here.

> +
> +  ULONGEST status32;
> +  regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
> +				 &status32);
> +
> +  if (curr_insn.is_control_flow)
> +    {
> +      CORE_ADDR branch_pc = arc_insn_get_branch_target (curr_insn);
> +      if (branch_pc != next_pc)
> +	next_pcs.push_back (branch_pc);
> +    }
> +  /* Is current instruction the last in a loop body?  */
> +  else if (tdep->has_hw_loops)
> +    {
> +      /* If STATUS32.L is 1, then ZD-loops are disabled.  */
> +      if ((status32 & ARC_STATUS32_L_MASK) == 0)
> +	{
> +	  ULONGEST lp_end, lp_start, lp_count;
> +	  regcache_cooked_read_unsigned (regcache, ARC_LP_START_REGNUM,
> +					 &lp_start);
> +	  regcache_cooked_read_unsigned (regcache, ARC_LP_END_REGNUM, &lp_end);
> +	  regcache_cooked_read_unsigned (regcache, ARC_LP_COUNT_REGNUM,
> +					 &lp_count);
> +
> +	  if (arc_debug)
> +	    {
> +	      debug_printf ("arc-linux: lp_start = %s, lp_end = %s, "
> +			    "lp_count = %s, next_pc = %s\n",
> +			    paddress (gdbarch, lp_start),
> +			    paddress (gdbarch, lp_end),
> +			    pulongest (lp_count),
> +			    paddress (gdbarch, next_pc));
> +	    }
> +
> +	  if (next_pc == lp_end && lp_count > 1)
> +	    {
> +	      /* The instruction is in effect a jump back to the start of
> +		 the loop.  */
> +	      next_pcs.push_back (lp_start);
> +	    }
> +
> +	}
> +    }
> +
> +  /* Is this a delay slot?  Then next PC is in BTA register.  */
> +  if ((status32 & ARC_STATUS32_DE_MASK) != 0)
> +    {
> +      ULONGEST bta;
> +      regcache_cooked_read_unsigned (regcache, ARC_BTA_REGNUM, &bta);
> +      next_pcs.push_back (bta);
> +    }
> +
> +  return next_pcs;
> +}
> +
> +/* Implement the "skip_solib_resolver" gdbarch method.
> +
> +   See glibc_skip_solib_resolver for details.  */
> +
> +static CORE_ADDR
> +arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
> +{
> +  /* For uClibc 0.9.26+.
> +
> +     An unresolved PLT entry points to "__dl_linux_resolve", which calls
> +     "_dl_linux_resolver" to do the resolving and then eventually jumps to
> +     the function.
> +
> +     So we look for the symbol `_dl_linux_resolver', and if we are there,
> +     gdb sets a breakpoint at the return address, and continues.  */
> +  struct bound_minimal_symbol resolver =
> +    lookup_minimal_symbol ("_dl_linux_resolver", NULL, NULL);
> +
> +  if (arc_debug)
> +    {
> +      if (resolver.minsym)
> +	{
> +	  CORE_ADDR res_addr = BMSYMBOL_VALUE_ADDRESS (resolver);
> +	  debug_printf ("arc-linux: skip_solib_resolver (): "
> +			"pc = %s, resolver at %s\n",
> +			print_core_address (gdbarch, pc),
> +			print_core_address (gdbarch, res_addr));
> +	}
> +      else
> +	{
> +	  debug_printf ("arc-linux: skip_solib_resolver (): "
> +			"pc = %s, no resolver found\n",
> +			print_core_address (gdbarch, pc));
> +	}
> +    }
> +
> +  if (resolver.minsym && BMSYMBOL_VALUE_ADDRESS (resolver) == pc)
> +    {
> +      /* Find the return address.  */
> +      return frame_unwind_caller_pc (get_current_frame ());
> +    }
> +  else
> +    {
> +      /* No breakpoint required.  */
> +      return 0;
> +    }
> +}
> +
> +/* Initialization specific to Linux environment.  */
> +
> +static void
> +arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
> +{
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +
> +  if (arc_debug)
> +    debug_printf ("arc-linux: GNU/Linux OS/ABI initialization.\n");
> +
> +  /* If we are using Linux, we have in uClibc
> +     (libc/sysdeps/linux/arc/bits/setjmp.h):
> +
> +     typedef int __jmp_buf[13+1+1+1];    //r13-r25, fp, sp, blink
> +
> +     Where "blink" is a stored PC of a caller function.
> +   */
> +  tdep->jb_pc = 15;

I don't really understand this, could you dumb it down a bit for me?

> +/* Suppress warning from -Wmissing-prototypes.  */
> +extern initialize_file_ftype _initialize_arc_linux_tdep;
> +
> +void
> +_initialize_arc_linux_tdep (void)

Remove the void.

Simon

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v2 4/4] arc: Add arc-*-linux regformats
  2020-04-28 16:04   ` [PATCH v2 4/4] arc: Add arc-*-linux regformats Shahab Vahedi
@ 2020-05-14 15:12     ` Simon Marchi
  2020-06-15 23:37       ` Shahab Vahedi
  0 siblings, 1 reply; 86+ messages in thread
From: Simon Marchi @ 2020-05-14 15:12 UTC (permalink / raw)
  To: Shahab Vahedi, gdb-patches
  Cc: Shahab Vahedi, Anton Kolesov, Tom Tromey, Francois Bedard

On 2020-04-28 12:04 p.m., Shahab Vahedi via Gdb-patches wrote:
> From: Anton Kolesov <Anton.Kolesov@synopsys.com>
> 
> gdb/ChangeLog:
> 2020-04-28  Anton Kolesov <anton.kolesov@synopsys.com>
> 
> 	* features/Makefile: Add new files and expedite registers.
> 	* regformats/arc-arcompact-Linux.dat: New file.
> 	* regformats/arc-v2-Linux.dat: Likewise.

Can you explain why this is useful?  I always forget, but I have the feeling
that regformats are something we are going away from, and that if you support
target descriptions, you don't need that... but I would need to refresh my
memory.

Simon


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v2 3/4] arc: Add GNU/Linux support for ARC
  2020-05-14 15:09     ` Simon Marchi
@ 2020-06-15 23:13       ` Shahab Vahedi
  2020-06-16  0:58         ` Simon Marchi
  0 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-06-15 23:13 UTC (permalink / raw)
  To: Simon Marchi
  Cc: gdb-patches, Shahab Vahedi, Anton Kolesov, Tom Tromey, Francois Bedard

On Thu, May 14, 2020 at 11:09:08AM -0400, Simon Marchi wrote:
> On 2020-04-28 12:04 p.m., Shahab Vahedi via Gdb-patches wrote:
> > +/* Initialization specific to Linux environment.  */
> > +
> > +static void
> > +arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
> > +{
> > +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> > +
> > +  if (arc_debug)
> > +    debug_printf ("arc-linux: GNU/Linux OS/ABI initialization.\n");
> > +
> > +  /* If we are using Linux, we have in uClibc
> > +     (libc/sysdeps/linux/arc/bits/setjmp.h):
> > +
> > +     typedef int __jmp_buf[13+1+1+1];    //r13-r25, fp, sp, blink
> > +
> > +     Where "blink" is a stored PC of a caller function.
> > +   */
> > +  tdep->jb_pc = 15;
> 
> I don't really understand this, could you dumb it down a bit for me?

In advance, I appologize if my explanation is not right on the spot
or is too verbose. I am not 100% sure what is not clear, so I try to
explain as much as I can.

If you mean why "tdep->jb_pc" is 15 and what the comments mean, then:

fp    -> Frame Pointer register
sp    -> Stack Pointer register
blink -> Branch and LINK register (acts like a "return" register)

blink register is set (implicitly) when "bl @name_of_fuction" instruction
is used. It will point to the instruction that comes after "bl" (branch
and link). e.g.:

  0x100: add r0, r1, r2
  0x104: bl @galaxy_far_away     # pc=@galaxy_far_away; blink=0x108
  0x108: add r3, r4, r5

a simple "j(ump)  blink" will return from the function.

-----

The layout of "__jump_buf" looks like:
0..12:   stored registers r13, r14, ..., r25
13:      stored fp
14:      stored sp
15:      stored blink

This is how the "calling" convention in ARC saves the
registers before switching the frame to another function.

I hope it is clear now.


Shahab

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v2 4/4] arc: Add arc-*-linux regformats
  2020-05-14 15:12     ` Simon Marchi
@ 2020-06-15 23:37       ` Shahab Vahedi
  2020-06-16  2:08         ` Simon Marchi
  0 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-06-15 23:37 UTC (permalink / raw)
  To: Simon Marchi
  Cc: gdb-patches, Shahab Vahedi, Anton Kolesov, Tom Tromey, Francois Bedard

On Thu, May 14, 2020 at 11:12:55AM -0400, Simon Marchi wrote:
> On 2020-04-28 12:04 p.m., Shahab Vahedi via Gdb-patches wrote:
> > From: Anton Kolesov <Anton.Kolesov@synopsys.com>
> > 
> > gdb/ChangeLog:
> > 2020-04-28  Anton Kolesov <anton.kolesov@synopsys.com>
> > 
> > 	* features/Makefile: Add new files and expedite registers.
> > 	* regformats/arc-arcompact-Linux.dat: New file.
> > 	* regformats/arc-v2-Linux.dat: Likewise.
> 
> Can you explain why this is useful?  I always forget, but I have the feeling
> that regformats are something we are going away from, and that if you support
> target descriptions, you don't need that... but I would need to refresh my
> memory.

To my understanding, the values of "expedite" registers are always transferred
from the "server" to GDB client. With every step you take, or any stop you do,
GDB client will know about the value of "expedite" registers. In case of ARC,
those are the "program counter" and "stack pointer" registers.
I _think_ the "dat" files are the mechanism holding information about that.
After all it is generated from the XML and we also followed other targets
in doing so.


Shahab

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v2 3/4] arc: Add GNU/Linux support for ARC
  2020-06-15 23:13       ` Shahab Vahedi
@ 2020-06-16  0:58         ` Simon Marchi
  0 siblings, 0 replies; 86+ messages in thread
From: Simon Marchi @ 2020-06-16  0:58 UTC (permalink / raw)
  To: Shahab Vahedi
  Cc: gdb-patches, Shahab Vahedi, Anton Kolesov, Tom Tromey, Francois Bedard

On 2020-06-15 7:13 p.m., Shahab Vahedi wrote:
> On Thu, May 14, 2020 at 11:09:08AM -0400, Simon Marchi wrote:
>> On 2020-04-28 12:04 p.m., Shahab Vahedi via Gdb-patches wrote:
>>> +/* Initialization specific to Linux environment.  */
>>> +
>>> +static void
>>> +arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
>>> +{
>>> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
>>> +
>>> +  if (arc_debug)
>>> +    debug_printf ("arc-linux: GNU/Linux OS/ABI initialization.\n");
>>> +
>>> +  /* If we are using Linux, we have in uClibc
>>> +     (libc/sysdeps/linux/arc/bits/setjmp.h):
>>> +
>>> +     typedef int __jmp_buf[13+1+1+1];    //r13-r25, fp, sp, blink
>>> +
>>> +     Where "blink" is a stored PC of a caller function.
>>> +   */
>>> +  tdep->jb_pc = 15;
>>
>> I don't really understand this, could you dumb it down a bit for me?
> 
> In advance, I appologize if my explanation is not right on the spot
> or is too verbose. I am not 100% sure what is not clear, so I try to
> explain as much as I can.
> 
> If you mean why "tdep->jb_pc" is 15 and what the comments mean, then:
> 
> fp    -> Frame Pointer register
> sp    -> Stack Pointer register
> blink -> Branch and LINK register (acts like a "return" register)
> 
> blink register is set (implicitly) when "bl @name_of_fuction" instruction
> is used. It will point to the instruction that comes after "bl" (branch
> and link). e.g.:
> 
>   0x100: add r0, r1, r2
>   0x104: bl @galaxy_far_away     # pc=@galaxy_far_away; blink=0x108
>   0x108: add r3, r4, r5
> 
> a simple "j(ump)  blink" will return from the function.
> 
> -----
> 
> The layout of "__jump_buf" looks like:
> 0..12:   stored registers r13, r14, ..., r25
> 13:      stored fp
> 14:      stored sp
> 15:      stored blink
> 
> This is how the "calling" convention in ARC saves the
> registers before switching the frame to another function.
> 
> I hope it is clear now.

Ah ok, and that value is the offset of the PC in the buffer.  I see that the
comment above the definition of the jb_pc explains that, I might have missed
it the first time.

Thanks,

Simon

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v2 4/4] arc: Add arc-*-linux regformats
  2020-06-15 23:37       ` Shahab Vahedi
@ 2020-06-16  2:08         ` Simon Marchi
  0 siblings, 0 replies; 86+ messages in thread
From: Simon Marchi @ 2020-06-16  2:08 UTC (permalink / raw)
  To: Shahab Vahedi
  Cc: gdb-patches, Shahab Vahedi, Anton Kolesov, Tom Tromey, Francois Bedard

On 2020-06-15 7:37 p.m., Shahab Vahedi wrote:
> On Thu, May 14, 2020 at 11:12:55AM -0400, Simon Marchi wrote:
>> On 2020-04-28 12:04 p.m., Shahab Vahedi via Gdb-patches wrote:
>>> From: Anton Kolesov <Anton.Kolesov@synopsys.com>
>>>
>>> gdb/ChangeLog:
>>> 2020-04-28  Anton Kolesov <anton.kolesov@synopsys.com>
>>>
>>> 	* features/Makefile: Add new files and expedite registers.
>>> 	* regformats/arc-arcompact-Linux.dat: New file.
>>> 	* regformats/arc-v2-Linux.dat: Likewise.
>>
>> Can you explain why this is useful?  I always forget, but I have the feeling
>> that regformats are something we are going away from, and that if you support
>> target descriptions, you don't need that... but I would need to refresh my
>> memory.
> 
> To my understanding, the values of "expedite" registers are always transferred
> from the "server" to GDB client. With every step you take, or any stop you do,
> GDB client will know about the value of "expedite" registers. In case of ARC,
> those are the "program counter" and "stack pointer" registers.
> I _think_ the "dat" files are the mechanism holding information about that.
> After all it is generated from the XML and we also followed other targets
> in doing so.

It's true that these .dat files do that, but it's not the only way.  They
don't offer any flexibility for architectures that have optional set of
registers, as it requires you to generate one format for each possible
combination of these options.  So the trend has been to move away from that,
towards target descriptions assembled at runtime.

I would encourage you to look at how aarch64 handles it, as it's one of the
latest that was introduced.  You'll notice that there is one xml file for
each "feature".  They are then assembled at runtime based on the features
detected on the current hardware.  The expedite registers are also taken
care of, it's all in gdbserver/linux-aarch64-tdesc.cc.

I'd prefer if we didn't add a new architecture that uses the old method.

Simon



^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v2 2/4] arc: Recognize registers available on Linux targets
  2020-05-14 15:01     ` Simon Marchi
@ 2020-06-17 15:46       ` Shahab Vahedi
  2020-07-13 15:48         ` Simon Marchi
  0 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-06-17 15:46 UTC (permalink / raw)
  To: Simon Marchi
  Cc: gdb-patches, Shahab Vahedi, Anton Kolesov, Tom Tromey, Francois Bedard

Hi Simon,

On Thu, May 14, 2020 at 11:01:44AM -0400, Simon Marchi wrote:
> Just some nits - I don't really know about the specific details of the ARC architecture.
> 
> On 2020-04-28 12:04 p.m., Shahab Vahedi via Gdb-patches wrote:
> >    struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep);
> >  
> >    /* Data types.  */
> > @@ -1987,6 +2025,13 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
> >    set_gdbarch_ps_regnum (gdbarch, ARC_STATUS32_REGNUM);
> >    set_gdbarch_fp0_regnum (gdbarch, -1);	/* No FPU registers.  */
> >  
> > +  /* Confirm that register name lists have proper length.  */
> > +  gdb_static_assert (ARC_LAST_REGNUM + 1
> > +		     == (ARRAY_SIZE (core_v2_register_names)
> > +			 + ARRAY_SIZE (aux_minimal_register_names)));
> > +  gdb_static_assert (ARRAY_SIZE (core_v2_register_names)
> > +		     == ARRAY_SIZE (core_arcompact_register_names));
> 
> Does this need to be here?  I would expect them to be near (just after) the definitions
> of said arrays.

*_register_names are static arrays. That should be why gdb_STATIC_assert
is used as well. I believe this place in the code is OK for making that
check.

Shahab

^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v3 0/3] arc: Add GNU/Linux support
  2020-04-28 16:04 ` [PATCH v2 " Shahab Vahedi
                     ` (4 preceding siblings ...)
  2020-05-14 11:43   ` [PATCH v2 0/4] arc: Add GNU/Linux support Shahab Vahedi
@ 2020-07-13 15:45   ` Shahab Vahedi
  2020-07-13 15:45     ` [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
                       ` (3 more replies)
  5 siblings, 4 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-07-13 15:45 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

This is a series of changes to enable debugging ARC targets that are
running on a native ARC GNU/Linux system.  Since this heavily relies
on XML target descriptions provided for different targets, that piece
of code has been refactored to accomadate flexible register support.

After this series, there will come patches that add support for
native ARC gdb/gdbserver.

v3: Changes after Simon's remarks:
The XML files have reduced to minimal comprehensible set.
The code is adjusted to work with new reg sets and be platform agnostic.

v2: Changes after Tom's remarks:
 arc-tdep.c
  - arc_tdesc_init(): Use "ARC_{R58,R59}_REGNUM" to index "core_regs[]".
  - arc_gdbarch_init(): Use "xfree ()" instead of "XDELETE ()"
  - arc_gdbarch_init(): return "nullptr" instead of "NULL".
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 arc-linux-tdep.c
  - Use true/false instead of TRUE/FALSE.
  - arc_linux_sw_breakpoint_from_kind (): Break long lines into two.
  - arc_linux_sw_breakpoint_from_kind (): Remove starting blank line.
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 gdb/configure.tgt
  - arc*-*-linux*): Remove "build_gdbserver=yes".

Anton Kolesov (1):
  arc: Add GNU/Linux support for ARC

Shahab Vahedi (2):
  arc: Add ARCv2 XML target along with refactoring
  arc: Add hardware loop detection

 gdb/Makefile.in                               |   1 +
 gdb/arc-linux-tdep.c                          | 283 ++++++++
 gdb/arc-tdep.c                                | 657 +++++++++++-------
 gdb/arc-tdep.h                                |  30 +-
 gdb/arch/arc.c                                | 106 ++-
 gdb/arch/arc.h                                |  76 +-
 gdb/configure.tgt                             |   5 +
 gdb/doc/gdb.texinfo                           |   3 +-
 gdb/features/Makefile                         |   8 +-
 .../arc/{aux-arcompact.c => v1-aux.c}         |   9 +-
 .../arc/{aux-arcompact.xml => v1-aux.xml}     |   7 +-
 .../arc/{core-arcompact.c => v1-core.c}       |   8 +-
 .../arc/{core-arcompact.xml => v1-core.xml}   |   4 +-
 gdb/features/arc/{aux-v2.c => v2-aux.c}       |   9 +-
 gdb/features/arc/{aux-v2.xml => v2-aux.xml}   |   5 +-
 gdb/features/arc/{core-v2.c => v2-core.c}     |   7 +-
 gdb/features/arc/{core-v2.xml => v2-core.xml} |   7 +-
 17 files changed, 907 insertions(+), 318 deletions(-)
 create mode 100644 gdb/arc-linux-tdep.c
 rename gdb/features/arc/{aux-arcompact.c => v1-aux.c} (73%)
 rename gdb/features/arc/{aux-arcompact.xml => v1-aux.xml} (80%)
 rename gdb/features/arc/{core-arcompact.c => v1-core.c} (87%)
 rename gdb/features/arc/{core-arcompact.xml => v1-core.xml} (92%)
 rename gdb/features/arc/{aux-v2.c => v2-aux.c} (76%)
 rename gdb/features/arc/{aux-v2.xml => v2-aux.xml} (86%)
 rename gdb/features/arc/{core-v2.c => v2-core.c} (91%)
 rename gdb/features/arc/{core-v2.xml => v2-core.xml} (90%)

-- 
2.27.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring
  2020-07-13 15:45   ` [PATCH v3 0/3] " Shahab Vahedi
@ 2020-07-13 15:45     ` Shahab Vahedi
  2020-07-15  2:52       ` Simon Marchi
  2020-07-13 15:45     ` [PATCH v3 2/3] arc: Add hardware loop detection Shahab Vahedi
                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-07-13 15:45 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

A few changes have been made to make the register support simpler,
more flexible and extendible.  The trigger for most of these changes
are the remarks [1] made earlier for v2 of this patch.  The noticeable
improvements are:

- The arc XML target features are placed under gdb/features/arc
- There are two cores (based on ISA) and one auxiliary feature:
  v1-core: ARC600, ARC601, ARC700
  v2-core: ARC EM, ARC HS
  aux: common in both
- The XML target features represent a minimalistic sane set of
  registers irrespective of application (baremetal or linux).
- A concept of "feature" class has been introduced in the code.
  The "feature" object is constructed from BFD and GDBARCH data.
  It contains necessary information (ISA and register size) to
  determine which XML target feature to use.
- A new structure (ARC_REGISTER_FEATURE) is added that allows
  providing index, names, and the necessity of registers. This
  simplifies the sanity checks and future extendibility.

The last two points were inspired from RiscV port.

[1]
https://sourceware.org/pipermail/gdb-patches/2020-May/168511.html

gdb/ChangeLog:
2020-07-09  Shahab Vahedi  <shahab@synopsys.com>

	* arch/arc.h
	  (arc_gdbarch_features): New class to stir the selection of target XML.
	  (arc_create_target_description): Use FEATURES to choose XML target.
	  (arc_lookup_target_description): Use arc_create_target_description
	  to create _new_ target descriptions or return the already created
	  ones if the FEATURES is the same.
	* arch/arc.c: Implementation of prototypes described above.
	* gdb/arc-tdep.h (arc_regnum enum): Add more registers.
	  (arc_gdbarch_features_init): Initialize the FEATURES struct.
	* arc-tdep.c (*_feature_name): Make feature names consistent.
	  (arc_register_feature): A new struct to hold information about
	  registers of a particular target/feature.
	  (arc_check_tdesc_feature): Check if XML provides registers in
	  compliance with ARC_REGISTER_FEATURE structs.
	  (arc_update_acc_reg_names): Add aliases for r58 and r59.
	  (determine_*_reg_feature_set): Which feature name to look for.
	  (arc_gdbarch_features_init): Given MACH and ABFD, initialize FEATURES.
	  (mach_type_to_arc_isa): Convert from a set of binutils machine types
	  to expected ISA enums to be used in arc_gdbarch_features structs.
	* features/Makefile (FEATURE_XMLFILES): Add new files.
	* gdb/features/arc/v1-aux.c: New file.
	* gdb/features/arc/v1-aux.xml: Likewise.
	* gdb/features/arc/v1-core.c: Likewise.
	* gdb/features/arc/v1-core.xml: Likewise.
	* gdb/features/arc/v2-aux.c: Likewise.
	* gdb/features/arc/v2-aux.xml: Likewise.
	* gdb/features/arc/v2-core.c: Likewise.
	* gdb/features/arc/v2-core.xml: Likewise.
---
 gdb/arc-tdep.c                                | 615 +++++++++++-------
 gdb/arc-tdep.h                                |  21 +-
 gdb/arch/arc.c                                | 106 ++-
 gdb/arch/arc.h                                |  76 ++-
 gdb/features/Makefile                         |   8 +-
 .../arc/{aux-arcompact.c => v1-aux.c}         |   9 +-
 .../arc/{aux-arcompact.xml => v1-aux.xml}     |   7 +-
 .../arc/{core-arcompact.c => v1-core.c}       |   8 +-
 .../arc/{core-arcompact.xml => v1-core.xml}   |   4 +-
 gdb/features/arc/{aux-v2.c => v2-aux.c}       |   9 +-
 gdb/features/arc/{aux-v2.xml => v2-aux.xml}   |   5 +-
 gdb/features/arc/{core-v2.c => v2-core.c}     |   7 +-
 gdb/features/arc/{core-v2.xml => v2-core.xml} |   7 +-
 13 files changed, 571 insertions(+), 311 deletions(-)
 rename gdb/features/arc/{aux-arcompact.c => v1-aux.c} (73%)
 rename gdb/features/arc/{aux-arcompact.xml => v1-aux.xml} (80%)
 rename gdb/features/arc/{core-arcompact.c => v1-core.c} (87%)
 rename gdb/features/arc/{core-arcompact.xml => v1-core.xml} (92%)
 rename gdb/features/arc/{aux-v2.c => v2-aux.c} (76%)
 rename gdb/features/arc/{aux-v2.xml => v2-aux.xml} (86%)
 rename gdb/features/arc/{core-v2.c => v2-core.c} (91%)
 rename gdb/features/arc/{core-v2.xml => v2-core.xml} (90%)

diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 7e6d29c334b..6979c2ad7d0 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -21,6 +21,7 @@
 /* GDB header files.  */
 #include "defs.h"
 #include "arch-utils.h"
+#include "elf-bfd.h"
 #include "disasm.h"
 #include "dwarf2/frame.h"
 #include "frame-base.h"
@@ -41,6 +42,7 @@
 
 /* Standard headers.  */
 #include <algorithm>
+#include <sstream>
 
 /* The frame unwind cache for ARC.  */
 
@@ -91,63 +93,201 @@ int arc_debug;
 
 static struct cmd_list_element *maintenance_print_arc_list = NULL;
 
-/* XML target description features.  */
-
-static const char core_v2_feature_name[] = "org.gnu.gdb.arc.core.v2";
-static const char
-  core_reduced_v2_feature_name[] = "org.gnu.gdb.arc.core-reduced.v2";
-static const char
-  core_arcompact_feature_name[] = "org.gnu.gdb.arc.core.arcompact";
-static const char aux_minimal_feature_name[] = "org.gnu.gdb.arc.aux-minimal";
-
-/* XML target description known registers.  */
-
-static const char *const core_v2_register_names[] = {
-  "r0", "r1", "r2", "r3",
-  "r4", "r5", "r6", "r7",
-  "r8", "r9", "r10", "r11",
-  "r12", "r13", "r14", "r15",
-  "r16", "r17", "r18", "r19",
-  "r20", "r21", "r22", "r23",
-  "r24", "r25", "gp", "fp",
-  "sp", "ilink", "r30", "blink",
-  "r32", "r33", "r34", "r35",
-  "r36", "r37", "r38", "r39",
-  "r40", "r41", "r42", "r43",
-  "r44", "r45", "r46", "r47",
-  "r48", "r49", "r50", "r51",
-  "r52", "r53", "r54", "r55",
-  "r56", "r57", "accl", "acch",
-  "lp_count", "reserved", "limm", "pcl",
+/* A set of registers that we expect to find in a tdesc_feature.  These
+   are used in ARC_TDESC_INIT when processing the target description.  */
+
+struct arc_register_feature
+{
+  /* Information for a single register.  */
+  struct register_info
+  {
+    /* The GDB register number for this register.  */
+    int regnum;
+
+    /* List of names for this register.  The first name in this list is the
+       preferred name, the name GDB will use when describing this register.  */
+    std::vector<const char *> names;
+
+    /* When true, this register must be present in this feature set.  */
+    bool required_p;
+  };
+
+  /* The name for this feature.  This is the name used to find this feature
+     within the target description.  */
+  const char *name;
+
+  /* List of all the registers that we expect to encounter in this register
+     set.  */
+  std::vector<struct register_info> registers;
 };
 
-static const char *const aux_minimal_register_names[] = {
-  "pc", "status32",
+static const char *ARC_CORE_FEATURE_NAME="org.gnu.gdb.arc.core";
+static const char *ARC_AUX_FEATURE_NAME="org.gnu.gdb.arc.aux";
+
+/* ARCv1 (ARC600, ARC601, ARC700) general core registers feature set.
+   See also arc_update_acc_reg_names() for "accl/acch" names.  */
+
+static struct arc_register_feature arc_v1_core_reg_feature =
+{
+  ARC_CORE_FEATURE_NAME,
+  {
+    { ARC_R0_REGNUM + 0, { "r0" }, true },
+    { ARC_R0_REGNUM + 1, { "r1" }, true },
+    { ARC_R0_REGNUM + 2, { "r2" }, true },
+    { ARC_R0_REGNUM + 3, { "r3" }, true },
+    { ARC_R0_REGNUM + 4, { "r4" }, false },
+    { ARC_R0_REGNUM + 5, { "r5" }, false },
+    { ARC_R0_REGNUM + 6, { "r6" }, false },
+    { ARC_R0_REGNUM + 7, { "r7" }, false },
+    { ARC_R0_REGNUM + 8, { "r8" }, false },
+    { ARC_R0_REGNUM + 9, { "r9" }, false },
+    { ARC_R0_REGNUM + 10, { "r10" }, true },
+    { ARC_R0_REGNUM + 11, { "r11" }, true },
+    { ARC_R0_REGNUM + 12, { "r12" }, true },
+    { ARC_R0_REGNUM + 13, { "r13" }, true },
+    { ARC_R0_REGNUM + 14, { "r14" }, true },
+    { ARC_R0_REGNUM + 15, { "r15" }, true },
+    { ARC_R0_REGNUM + 16, { "r16" }, false },
+    { ARC_R0_REGNUM + 17, { "r17" }, false },
+    { ARC_R0_REGNUM + 18, { "r18" }, false },
+    { ARC_R0_REGNUM + 19, { "r19" }, false },
+    { ARC_R0_REGNUM + 20, { "r20" }, false },
+    { ARC_R0_REGNUM + 21, { "r21" }, false },
+    { ARC_R0_REGNUM + 22, { "r22" }, false },
+    { ARC_R0_REGNUM + 23, { "r23" }, false },
+    { ARC_R0_REGNUM + 24, { "r24" }, false },
+    { ARC_R0_REGNUM + 25, { "r25" }, false },
+    { ARC_R0_REGNUM + 26, { "gp" }, true },
+    { ARC_R0_REGNUM + 27, { "fp" }, true },
+    { ARC_R0_REGNUM + 28, { "sp" }, true },
+    { ARC_R0_REGNUM + 29, { "ilink1" }, false },
+    { ARC_R0_REGNUM + 30, { "ilink2" }, false },
+    { ARC_R0_REGNUM + 31, { "blink" }, true },
+    { ARC_R0_REGNUM + 32, { "r32" }, false },
+    { ARC_R0_REGNUM + 33, { "r33" }, false },
+    { ARC_R0_REGNUM + 34, { "r34" }, false },
+    { ARC_R0_REGNUM + 35, { "r35" }, false },
+    { ARC_R0_REGNUM + 36, { "r36" }, false },
+    { ARC_R0_REGNUM + 37, { "r37" }, false },
+    { ARC_R0_REGNUM + 38, { "r38" }, false },
+    { ARC_R0_REGNUM + 39, { "r39" }, false },
+    { ARC_R0_REGNUM + 40, { "r40" }, false },
+    { ARC_R0_REGNUM + 41, { "r41" }, false },
+    { ARC_R0_REGNUM + 42, { "r42" }, false },
+    { ARC_R0_REGNUM + 43, { "r43" }, false },
+    { ARC_R0_REGNUM + 44, { "r44" }, false },
+    { ARC_R0_REGNUM + 45, { "r45" }, false },
+    { ARC_R0_REGNUM + 46, { "r46" }, false },
+    { ARC_R0_REGNUM + 47, { "r47" }, false },
+    { ARC_R0_REGNUM + 48, { "r48" }, false },
+    { ARC_R0_REGNUM + 49, { "r49" }, false },
+    { ARC_R0_REGNUM + 50, { "r50" }, false },
+    { ARC_R0_REGNUM + 51, { "r51" }, false },
+    { ARC_R0_REGNUM + 52, { "r52" }, false },
+    { ARC_R0_REGNUM + 53, { "r53" }, false },
+    { ARC_R0_REGNUM + 54, { "r54" }, false },
+    { ARC_R0_REGNUM + 55, { "r55" }, false },
+    { ARC_R0_REGNUM + 56, { "r56" }, false },
+    { ARC_R0_REGNUM + 57, { "r57" }, false },
+    { ARC_R0_REGNUM + 58, { "r58", "accl" }, false },
+    { ARC_R0_REGNUM + 59, { "r59", "acch" }, false },
+    { ARC_R0_REGNUM + 60, { "lp_count" }, false },
+    { ARC_R0_REGNUM + 61, { "reserved" }, false },
+    { ARC_R0_REGNUM + 62, { "limm" }, false },
+    { ARC_R0_REGNUM + 63, { "pcl" }, true }
+  }
 };
 
-static const char *const core_arcompact_register_names[] = {
-  "r0", "r1", "r2", "r3",
-  "r4", "r5", "r6", "r7",
-  "r8", "r9", "r10", "r11",
-  "r12", "r13", "r14", "r15",
-  "r16", "r17", "r18", "r19",
-  "r20", "r21", "r22", "r23",
-  "r24", "r25", "gp", "fp",
-  "sp", "ilink1", "ilink2", "blink",
-  "r32", "r33", "r34", "r35",
-  "r36", "r37", "r38", "r39",
-  "r40", "r41", "r42", "r43",
-  "r44", "r45", "r46", "r47",
-  "r48", "r49", "r50", "r51",
-  "r52", "r53", "r54", "r55",
-  "r56", "r57", "r58", "r59",
-  "lp_count", "reserved", "limm", "pcl",
+/* ARCv2 (ARCHS) general core registers feature set.  See also
+   arc_update_acc_reg_names() for "accl/acch" names.  */
+
+static struct arc_register_feature arc_v2_core_reg_feature =
+{
+  ARC_CORE_FEATURE_NAME,
+  {
+    { ARC_R0_REGNUM + 0, { "r0" }, true },
+    { ARC_R0_REGNUM + 1, { "r1" }, true },
+    { ARC_R0_REGNUM + 2, { "r2" }, true },
+    { ARC_R0_REGNUM + 3, { "r3" }, true },
+    { ARC_R0_REGNUM + 4, { "r4" }, false },
+    { ARC_R0_REGNUM + 5, { "r5" }, false },
+    { ARC_R0_REGNUM + 6, { "r6" }, false },
+    { ARC_R0_REGNUM + 7, { "r7" }, false },
+    { ARC_R0_REGNUM + 8, { "r8" }, false },
+    { ARC_R0_REGNUM + 9, { "r9" }, false },
+    { ARC_R0_REGNUM + 10, { "r10" }, true },
+    { ARC_R0_REGNUM + 11, { "r11" }, true },
+    { ARC_R0_REGNUM + 12, { "r12" }, true },
+    { ARC_R0_REGNUM + 13, { "r13" }, true },
+    { ARC_R0_REGNUM + 14, { "r14" }, true },
+    { ARC_R0_REGNUM + 15, { "r15" }, true },
+    { ARC_R0_REGNUM + 16, { "r16" }, false },
+    { ARC_R0_REGNUM + 17, { "r17" }, false },
+    { ARC_R0_REGNUM + 18, { "r18" }, false },
+    { ARC_R0_REGNUM + 19, { "r19" }, false },
+    { ARC_R0_REGNUM + 20, { "r20" }, false },
+    { ARC_R0_REGNUM + 21, { "r21" }, false },
+    { ARC_R0_REGNUM + 22, { "r22" }, false },
+    { ARC_R0_REGNUM + 23, { "r23" }, false },
+    { ARC_R0_REGNUM + 24, { "r24" }, false },
+    { ARC_R0_REGNUM + 25, { "r25" }, false },
+    { ARC_R0_REGNUM + 26, { "gp" }, true },
+    { ARC_R0_REGNUM + 27, { "fp" }, true },
+    { ARC_R0_REGNUM + 28, { "sp" }, true },
+    { ARC_R0_REGNUM + 29, { "ilink" }, false },
+    { ARC_R0_REGNUM + 30, { "r30" }, true },
+    { ARC_R0_REGNUM + 31, { "blink" }, true },
+    { ARC_R0_REGNUM + 32, { "r32" }, false },
+    { ARC_R0_REGNUM + 33, { "r33" }, false },
+    { ARC_R0_REGNUM + 34, { "r34" }, false },
+    { ARC_R0_REGNUM + 35, { "r35" }, false },
+    { ARC_R0_REGNUM + 36, { "r36" }, false },
+    { ARC_R0_REGNUM + 37, { "r37" }, false },
+    { ARC_R0_REGNUM + 38, { "r38" }, false },
+    { ARC_R0_REGNUM + 39, { "r39" }, false },
+    { ARC_R0_REGNUM + 40, { "r40" }, false },
+    { ARC_R0_REGNUM + 41, { "r41" }, false },
+    { ARC_R0_REGNUM + 42, { "r42" }, false },
+    { ARC_R0_REGNUM + 43, { "r43" }, false },
+    { ARC_R0_REGNUM + 44, { "r44" }, false },
+    { ARC_R0_REGNUM + 45, { "r45" }, false },
+    { ARC_R0_REGNUM + 46, { "r46" }, false },
+    { ARC_R0_REGNUM + 47, { "r47" }, false },
+    { ARC_R0_REGNUM + 48, { "r48" }, false },
+    { ARC_R0_REGNUM + 49, { "r49" }, false },
+    { ARC_R0_REGNUM + 50, { "r50" }, false },
+    { ARC_R0_REGNUM + 51, { "r51" }, false },
+    { ARC_R0_REGNUM + 52, { "r52" }, false },
+    { ARC_R0_REGNUM + 53, { "r53" }, false },
+    { ARC_R0_REGNUM + 54, { "r54" }, false },
+    { ARC_R0_REGNUM + 55, { "r55" }, false },
+    { ARC_R0_REGNUM + 56, { "r56" }, false },
+    { ARC_R0_REGNUM + 57, { "r57" }, false },
+    { ARC_R0_REGNUM + 58, { "r58", "accl" }, false },
+    { ARC_R0_REGNUM + 59, { "r59", "acch" }, false },
+    { ARC_R0_REGNUM + 60, { "lp_count" }, false },
+    { ARC_R0_REGNUM + 61, { "reserved" }, false },
+    { ARC_R0_REGNUM + 62, { "limm" }, false },
+    { ARC_R0_REGNUM + 63, { "pcl" }, true }
+  }
 };
 
-static char *arc_disassembler_options = NULL;
+/* The common auxiliary registers feature set.  The REGNUM field
+   must match the ARC_REGNUM enum in arc-tdep.h.  */
 
-/* Possible arc target descriptors.  */
-static struct target_desc *tdesc_arc_list[ARC_SYS_TYPE_NUM];
+static const struct arc_register_feature arc_common_aux_reg_feature =
+{
+  ARC_AUX_FEATURE_NAME,
+  {
+    { ARC_FIRST_AUX_REGNUM + 0, { "pc" }, true },
+    { ARC_FIRST_AUX_REGNUM + 1, { "status32" }, true },
+    { ARC_FIRST_AUX_REGNUM + 2, { "lp_start" }, false },
+    { ARC_FIRST_AUX_REGNUM + 3, { "lp_end" }, false },
+    { ARC_FIRST_AUX_REGNUM + 4, { "bta" }, false }
+  }
+};
+
+static char *arc_disassembler_options = NULL;
 
 /* Functions are sorted in the order as they are used in the
    _initialize_arc_tdep (), which uses the same order as gdbarch.h.  Static
@@ -1717,192 +1857,227 @@ static const struct frame_base arc_normal_base = {
   arc_frame_base_address
 };
 
-/* Initialize target description for the ARC.
-
-   Returns TRUE if input tdesc was valid and in this case it will assign TDESC
-   and TDESC_DATA output parameters.  */
-
-static bool
-arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
-		struct tdesc_arch_data **tdesc_data)
+static inline enum
+arc_isa mach_type_to_arc_isa (const unsigned long mach)
 {
-  if (arc_debug)
-    debug_printf ("arc: Target description initialization.\n");
-
-  const struct target_desc *tdesc_loc = info.target_desc;
-
-  /* Depending on whether this is ARCompact or ARCv2 we will assign
-     different default registers sets (which will differ in exactly two core
-     registers).  GDB will also refuse to accept register feature from invalid
-     ISA - v2 features can be used only with v2 ARChitecture.  We read
-     bfd_arch_info, which looks like to be a safe bet here, as it looks like it
-     is always initialized even when we don't pass any elf file to GDB at all
-     (it uses default arch in this case).  Also GDB will call this function
-     multiple times, and if XML target description file contains architecture
-     specifications, then GDB will set this architecture to info.bfd_arch_info,
-     overriding value from ELF file if they are different.  That means that,
-     where matters, this value is always our best guess on what CPU we are
-     debugging.  It has been noted that architecture specified in tdesc file
-     has higher precedence over ELF and even "set architecture" - that is,
-     using "set architecture" command will have no effect when tdesc has "arch"
-     tag.  */
-  /* Cannot use arc_mach_is_arcv2 (), because gdbarch is not created yet.  */
-  const int is_arcv2 = (info.bfd_arch_info->mach == bfd_mach_arc_arcv2);
-  bool is_reduced_rf;
-  const char *const *core_regs;
-  const char *core_feature_name;
+  switch (mach)
+    {
+    case bfd_mach_arc_arc600:
+    case bfd_mach_arc_arc601:
+    case bfd_mach_arc_arc700:
+      return ARC_ISA_ARCV1;
+      break;
+    case bfd_mach_arc_arcv2:
+      return ARC_ISA_ARCV2;
+      break;
+    default:
+	internal_error (__FILE__, __LINE__,
+			_("unknown machine id %lu"), mach);
+    }
+  return ARC_ISA_NONE;
+}
 
-  /* If target doesn't provide a description, use the default ones.  */
-  if (!tdesc_has_registers (tdesc_loc))
+/* Common construction code for ARC_GDBARCH_FEATURES struct.  If there
+   is no ABFD, then a FEATURE with default values is returned.  */
+void arc_gdbarch_features_init (arc_gdbarch_features &features,
+				const bfd *abfd, const unsigned long mach)
+{
+  /* Try to guess the features parameters by looking at the binary to be
+     executed.  If the user is providing a binary that does not match the
+     target, then tough luck.  This is the last effort to makes sense of
+     what's going on.  */
+  if (abfd != NULL && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
     {
-      if (is_arcv2)
-	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCV2);
+      unsigned char eclass = elf_elfheader (abfd)->e_ident[EI_CLASS];
+
+      if (eclass == ELFCLASS32)
+	features.reg_size = 4;
+      else if (eclass == ELFCLASS64)
+	features.reg_size = 8;
       else
-	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCOMPACT);
+	internal_error (__FILE__, __LINE__,
+			_("unknown ELF header class %d"), eclass);
     }
-  else
+
+  /* MACH from a bfd_arch_info struct is used here.  It should be a safe
+     bet, as it looks like the struct is always initialized even when we
+     don't pass any elf file to GDB at all (it uses default arch in that
+     case).  */
+  features.isa = mach_type_to_arc_isa (mach);
+
+  /* Put the most frequent values for the undetermined parameters.  */
+  if (features.reg_size == 0)
+    features.reg_size = 4;
+  if (features.isa == ARC_ISA_NONE)
+    features.reg_size = ARC_ISA_ARCV2;
+}
+
+/* Based on the MACH value, determines which core register features set
+   must be used.  Possible outcomes:
+   {nullptr, &arc_v1_core_reg_feature, &arc_v2_core_reg_feature}  */
+
+static arc_register_feature *
+determine_core_reg_feature_set (const unsigned long mach)
+{
+  switch (mach_type_to_arc_isa (mach))
     {
-      if (arc_debug)
-	debug_printf ("arc: Using provided register set.\n");
+    case ARC_ISA_ARCV1:
+      return &arc_v1_core_reg_feature;
+    case ARC_ISA_ARCV2:
+      return &arc_v2_core_reg_feature;
+    default:
+      return nullptr;
     }
-  gdb_assert (tdesc_loc != NULL);
-
-  /* Now we can search for base registers.  Core registers can be either full
-     or reduced.  Summary:
-
-     - core.v2 + aux-minimal
-     - core-reduced.v2 + aux-minimal
-     - core.arcompact + aux-minimal
-
-     NB: It is entirely feasible to have ARCompact with reduced core regs, but
-     we ignore that because GCC doesn't support that and at the same time
-     ARCompact is considered obsolete, so there is not much reason to support
-     that.  */
-  const struct tdesc_feature *feature
-    = tdesc_find_feature (tdesc_loc, core_v2_feature_name);
-  if (feature != NULL)
-    {
-      /* Confirm that register and architecture match, to prevent accidents in
-	 some situations.  This code will trigger an error if:
+}
 
-	 1. XML tdesc doesn't specify arch explicitly, registers are for arch
-	 X, but ELF specifies arch Y.
+/* At the moment, there is only 1 auxiliary register features set.
+   This is a place holder for future extendability.  */
 
-	 2. XML tdesc specifies arch X, but contains registers for arch Y.
+static const arc_register_feature *
+determine_aux_reg_feature_set ()
+{
+  return &arc_common_aux_reg_feature;
+}
 
-	 It will not protect from case where XML or ELF specify arch X,
-	 registers are for the same arch X, but the real target is arch Y.  To
-	 detect this case we need to check IDENTITY register.  */
-      if (!is_arcv2)
-	{
-	  arc_print (_("Error: ARC v2 target description supplied for "
-		       "non-ARCv2 target.\n"));
-	  return false;
-	}
+/* Update accumulator register names (ACCH/ACCL) for r58 and r59 in the
+   register sets.  The endianness determines the assignment:
 
-      is_reduced_rf = false;
-      core_feature_name = core_v2_feature_name;
-      core_regs = core_v2_register_names;
-    }
-  else
+         ,------.------.
+         |  LE  |  BE  |
+   ,-----|------+------|
+   | r58 | accl | acch |
+   | r59 | acch | accl |
+   `-----^------^------'  */
+
+static void
+arc_update_acc_reg_names (const int byte_order)
+{
+  const char *r58_alias
+    = byte_order == BFD_ENDIAN_LITTLE ? "accl" : "acch";
+  const char *r59_alias
+    = byte_order == BFD_ENDIAN_LITTLE ? "acch" : "accl";
+
+  /* Subscript 1 must be OK because those registers have 2 names.  */
+  arc_v1_core_reg_feature.registers[ARC_R58_REGNUM].names[1] = r58_alias;
+  arc_v1_core_reg_feature.registers[ARC_R59_REGNUM].names[1] = r59_alias;
+  arc_v2_core_reg_feature.registers[ARC_R58_REGNUM].names[1] = r58_alias;
+  arc_v2_core_reg_feature.registers[ARC_R59_REGNUM].names[1] = r59_alias;
+}
+
+/* Go through all the registers in REG_SET and check if they exist
+   in FEATURE.  The TDESC_DATA is updated with the register number
+   in REG_SET if it is found in the feature.  If a required register
+   is not found, this function returns false.  */
+
+static bool
+arc_check_tdesc_feature (struct tdesc_arch_data *tdesc_data,
+			 const struct tdesc_feature *feature,
+			 const struct arc_register_feature *reg_set)
+{
+  for (const auto &reg : reg_set->registers)
     {
-      feature = tdesc_find_feature (tdesc_loc, core_reduced_v2_feature_name);
-      if (feature != NULL)
+      bool found = false;
+
+      for (const char *name : reg.names)
 	{
-	  if (!is_arcv2)
-	    {
-	      arc_print (_("Error: ARC v2 target description supplied for "
-			   "non-ARCv2 target.\n"));
-	      return false;
-	    }
+	  found =
+	    tdesc_numbered_register (feature, tdesc_data, reg.regnum, name);
 
-	  is_reduced_rf = true;
-	  core_feature_name = core_reduced_v2_feature_name;
-	  core_regs = core_v2_register_names;
+	  if (found)
+	    break;
 	}
-      else
+
+      if (!found && reg.required_p)
 	{
-	  feature = tdesc_find_feature (tdesc_loc,
-					core_arcompact_feature_name);
-	  if (feature != NULL)
-	    {
-	      if (is_arcv2)
-		{
-		  arc_print (_("Error: ARCompact target description supplied "
-			       "for non-ARCompact target.\n"));
-		  return false;
-		}
-
-	      is_reduced_rf = false;
-	      core_feature_name = core_arcompact_feature_name;
-	      core_regs = core_arcompact_register_names;
-	    }
-	  else
+	  std::ostringstream reg_names;
+	  for (std::size_t i = 0; i < reg.names.size(); ++i)
 	    {
-	      arc_print (_("Error: Couldn't find core register feature in "
-			   "supplied target description."));
-	      return false;
+	      if (i == 0)
+		reg_names << "'" << reg.names[0] << "'";
+	      else
+		reg_names << " or '" << reg.names[0] << "'";
 	    }
+	  arc_print (_("Error: Cannot find required register(s) %s "
+		       "in feature '%s'.\n"), reg_names.str ().c_str (),
+		       feature->name.c_str ());
+	  return false;
 	}
     }
 
-  struct tdesc_arch_data *tdesc_data_loc = tdesc_data_alloc ();
+  return true;
+}
 
-  gdb_assert (feature != NULL);
-  int valid_p = 1;
+/* Initialize target description for the ARC.
 
-  for (int i = 0; i <= ARC_LAST_CORE_REGNUM; i++)
+   Returns true if input TDESC was valid and in this case it will assign TDESC
+   and TDESC_DATA output parameters.  */
+
+static bool
+arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
+		struct tdesc_arch_data **tdesc_data)
+{
+  const struct target_desc *tdesc_loc = info.target_desc;
+  if (arc_debug)
+    debug_printf ("arc: Target description initialization.\n");
+
+  /* If target doesn't provide a description, use the default ones.  */
+  if (!tdesc_has_registers (tdesc_loc))
     {
-      /* If rf16, then skip extra registers.  */
-      if (is_reduced_rf && ((i >= ARC_R4_REGNUM && i <= ARC_R9_REGNUM)
-			    || (i >= ARC_R16_REGNUM && i <= ARC_R25_REGNUM)))
-	continue;
-
-      valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i,
-					 core_regs[i]);
-
-      /* - Ignore errors in extension registers - they are optional.
-	 - Ignore missing ILINK because it doesn't make sense for Linux.
-	 - Ignore missing ILINK2 when architecture is ARCompact, because it
-	 doesn't make sense for Linux targets.
-
-	 In theory those optional registers should be in separate features, but
-	 that would create numerous but tiny features, which looks like an
-	 overengineering of a rather simple task.  */
-      if (!valid_p && (i <= ARC_SP_REGNUM || i == ARC_BLINK_REGNUM
-		       || i == ARC_LP_COUNT_REGNUM || i == ARC_PCL_REGNUM
-		       || (i == ARC_R30_REGNUM && is_arcv2)))
-	{
-	  arc_print (_("Error: Cannot find required register `%s' in "
-		       "feature `%s'.\n"), core_regs[i], core_feature_name);
-	  tdesc_data_cleanup (tdesc_data_loc);
-	  return false;
-	}
+      arc_gdbarch_features features;
+      arc_gdbarch_features_init (features, info.abfd,
+				 info.bfd_arch_info->mach);
+      tdesc_loc = arc_lookup_target_description (features);
     }
+  gdb_assert (tdesc_loc != nullptr);
+
+  if (arc_debug)
+    debug_printf ("arc: Have got a target description\n");
 
-  /* Mandatory AUX registers are intentionally few and are common between
-     ARCompact and ARC v2, so same code can be used for both.  */
-  feature = tdesc_find_feature (tdesc_loc, aux_minimal_feature_name);
-  if (feature == NULL)
+  const struct tdesc_feature *feature_core
+    = tdesc_find_feature (tdesc_loc, ARC_CORE_FEATURE_NAME);
+  const struct tdesc_feature *feature_aux
+    = tdesc_find_feature (tdesc_loc, ARC_AUX_FEATURE_NAME);
+
+  if (feature_core == nullptr)
     {
-      arc_print (_("Error: Cannot find required feature `%s' in supplied "
-		   "target description.\n"), aux_minimal_feature_name);
-      tdesc_data_cleanup (tdesc_data_loc);
+      arc_print (_("Error: Cannot find required feature '%s' in supplied "
+		   "target description.\n"), ARC_CORE_FEATURE_NAME);
       return false;
     }
 
-  for (int i = ARC_FIRST_AUX_REGNUM; i <= ARC_LAST_AUX_REGNUM; i++)
+  if (feature_aux == nullptr)
     {
-      const char *name = aux_minimal_register_names[i - ARC_FIRST_AUX_REGNUM];
-      valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i, name);
-      if (!valid_p)
-	{
-	  arc_print (_("Error: Cannot find required register `%s' "
-		       "in feature `%s'.\n"),
-		     name, tdesc_feature_name (feature));
-	  tdesc_data_cleanup (tdesc_data_loc);
-	  return false;
-	}
+      arc_print (_("Error: Cannot find required feature '%s' in supplied "
+		   "target description.\n"), ARC_AUX_FEATURE_NAME);
+      return false;
+    }
+
+  const auto arc_core_reg_feature
+    = determine_core_reg_feature_set (info.bfd_arch_info->mach);
+  const auto arc_aux_reg_feature
+    = determine_aux_reg_feature_set ();
+
+  if (arc_core_reg_feature == nullptr || arc_aux_reg_feature == nullptr)
+    return false;
+
+  struct tdesc_arch_data *tdesc_data_loc = tdesc_data_alloc ();
+
+  arc_update_acc_reg_names (info.byte_order);
+
+  bool valid_p = arc_check_tdesc_feature (tdesc_data_loc,
+					  feature_core,
+					  arc_core_reg_feature);
+
+  valid_p &= arc_check_tdesc_feature (tdesc_data_loc,
+				      feature_aux,
+				      arc_aux_reg_feature);
+
+  if (!valid_p)
+    {
+      if (arc_debug)
+        debug_printf ("arc: Target description is not valid\n");
+      tdesc_data_cleanup (tdesc_data_loc);
+      return false;
     }
 
   *tdesc = tdesc_loc;
@@ -2133,36 +2308,6 @@ dump_arc_instruction_command (const char *args, int from_tty)
 
 /* See arc-tdep.h.  */
 
-const target_desc *
-arc_read_description (arc_sys_type sys_type)
-{
-  if (arc_debug)
-    debug_printf ("arc: Reading target description for \"%s\".\n",
-		  arc_sys_type_to_str (sys_type));
-
-  gdb_assert ((sys_type >= 0) && (sys_type < ARC_SYS_TYPE_NUM));
-  struct target_desc *tdesc = tdesc_arc_list[sys_type];
-
-  if (tdesc == nullptr)
-    {
-      tdesc = arc_create_target_description (sys_type);
-      tdesc_arc_list[sys_type] = tdesc;
-
-      if (arc_debug)
-	{
-	  const char *arch = tdesc_architecture_name (tdesc);
-	  const char *abi = tdesc_osabi_name (tdesc);
-	  arch = arch != NULL ? arch : "";
-	  abi = abi != NULL ? abi : "";
-	  debug_printf ("arc: Created target description for "
-			"\"%s\": arch=\"%s\", ABI=\"%s\"\n",
-			arc_sys_type_to_str (sys_type), arch, abi);
-	}
-    }
-
-  return tdesc;
-}
-
 void _initialize_arc_tdep ();
 void
 _initialize_arc_tdep ()
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index d72332c7638..f4ce6a9a50a 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -35,7 +35,6 @@ enum arc_regnum
   {
     /* Core registers.  */
     ARC_R0_REGNUM = 0,
-    ARC_FIRST_CORE_REGNUM = ARC_R0_REGNUM,
     ARC_R1_REGNUM = 1,
     ARC_R4_REGNUM = 4,
     ARC_R7_REGNUM = 7,
@@ -54,6 +53,9 @@ enum arc_regnum
     ARC_R30_REGNUM,
     /* Return address from function.  */
     ARC_BLINK_REGNUM,
+    /* Accumulator registers.  */
+    ARC_R58_REGNUM = 58,
+    ARC_R59_REGNUM,
     /* Zero-delay loop counter.  */
     ARC_LP_COUNT_REGNUM = 60,
     /* Reserved register number.  There should never be a register with such
@@ -69,14 +71,21 @@ enum arc_regnum
     /* Program counter, aligned to 4-bytes, read-only.  */
     ARC_PCL_REGNUM,
     ARC_LAST_CORE_REGNUM = ARC_PCL_REGNUM,
+
     /* AUX registers.  */
     /* Actual program counter.  */
     ARC_PC_REGNUM,
     ARC_FIRST_AUX_REGNUM = ARC_PC_REGNUM,
     /* Status register.  */
     ARC_STATUS32_REGNUM,
-    ARC_LAST_REGNUM = ARC_STATUS32_REGNUM,
-    ARC_LAST_AUX_REGNUM = ARC_STATUS32_REGNUM,
+    /* Zero-delay loop start instruction.  */
+    ARC_LP_START_REGNUM,
+    /* Zero-delay loop next-after-last instruction.  */
+    ARC_LP_END_REGNUM,
+    /* Branch target address.  */
+    ARC_BTA_REGNUM,
+    ARC_LAST_AUX_REGNUM = ARC_BTA_REGNUM,
+    ARC_LAST_REGNUM = ARC_LAST_AUX_REGNUM,
 
     /* Additional ABI constants.  */
     ARC_FIRST_ARG_REGNUM = ARC_R0_REGNUM,
@@ -164,7 +173,9 @@ CORE_ADDR arc_insn_get_branch_target (const struct arc_instruction &insn);
 
 CORE_ADDR arc_insn_get_linear_next_pc (const struct arc_instruction &insn);
 
-/* Get the correct ARC target description for the given system type.  */
-const target_desc *arc_read_description (arc_sys_type sys_type);
+/* Initialize FEATURES from the provided data.  */
+
+void arc_gdbarch_features_init (arc_gdbarch_features &features,
+				const bfd *abfd, const unsigned long mach);
 
 #endif /* ARC_TDEP_H */
diff --git a/gdb/arch/arc.c b/gdb/arch/arc.c
index 9552b4aff97..84bc8df7788 100644
--- a/gdb/arch/arc.c
+++ b/gdb/arch/arc.c
@@ -17,42 +17,104 @@
 
 
 #include "gdbsupport/common-defs.h"
-#include <stdlib.h>
-
 #include "arc.h"
+#include <stdlib.h>
+#include <unordered_map>
+#include <sstream>
 
 /* Target description features.  */
-#include "features/arc/core-v2.c"
-#include "features/arc/aux-v2.c"
-#include "features/arc/core-arcompact.c"
-#include "features/arc/aux-arcompact.c"
+#include "features/arc/v1-core.c"
+#include "features/arc/v1-aux.c"
+#include "features/arc/v2-core.c"
+#include "features/arc/v2-aux.c"
 
-/* See arc.h.  */
+#ifndef GDBSERVER
+#define STATIC_IN_GDB static
+#else
+#define STATIC_IN_GDB
+#endif
 
-target_desc *
-arc_create_target_description (arc_sys_type sys_type)
+STATIC_IN_GDB target_desc *
+arc_create_target_description (const struct arc_gdbarch_features &features)
 {
+  /* Create a new target description.  */
   target_desc *tdesc = allocate_target_description ();
 
-  long regnum = 0;
-
 #ifndef IN_PROCESS_AGENT
-  if (sys_type == ARC_SYS_TYPE_ARCV2)
-    set_tdesc_architecture (tdesc, "arc:ARCv2");
-  else
-    set_tdesc_architecture (tdesc, "arc:ARC700");
-#endif
+  std::string arch_name = "arc";
 
-  if (sys_type == ARC_SYS_TYPE_ARCV2)
+  /* Architecture names here must match the ones in
+     ARCH_INFO_STRUCT in bfd/cpu-arc.c.  */
+  if (features.isa == ARC_ISA_ARCV1 && features.reg_size == 4)
+      arch_name.append (":ARC700");
+  else if (features.isa == ARC_ISA_ARCV2 && features.reg_size == 4)
+      arch_name.append (":ARCv2");
+  else
     {
-      regnum = create_feature_arc_core_v2 (tdesc, regnum);
-      regnum = create_feature_arc_aux_v2 (tdesc, regnum);
+      std::ostringstream msg;
+      msg << "Cannot determine architecture: ISA=" << features.isa
+	  << "; bitness=" << 8*features.reg_size;
+      gdb_assert_not_reached (msg.str ().c_str ());
     }
-  else
+
+  set_tdesc_architecture (tdesc, arch_name.c_str ());
+#endif
+
+  long regnum = 0;
+
+  switch (features.isa)
     {
-      regnum = create_feature_arc_core_arcompact (tdesc, regnum);
-      regnum = create_feature_arc_aux_arcompact (tdesc, regnum);
+    case ARC_ISA_ARCV1:
+	  regnum = create_feature_arc_v1_core (tdesc, regnum);
+	  regnum = create_feature_arc_v1_aux (tdesc, regnum);
+	  break;
+    case ARC_ISA_ARCV2:
+	  regnum = create_feature_arc_v2_core (tdesc, regnum);
+	  regnum = create_feature_arc_v2_aux (tdesc, regnum);
+	  break;
+    default:
+	  std::ostringstream msg;
+	  msg << "Cannot choose target description XML: " << features.isa;
+	  gdb_assert_not_reached (msg.str ().c_str ());
     }
 
   return tdesc;
 }
+
+#ifndef GDBSERVER
+
+/* Wrapper used by std::unordered_map to generate hash for features set.  */
+struct arc_gdbarch_features_hasher
+{
+  std::size_t
+  operator() (const arc_gdbarch_features &features) const noexcept
+  {
+    return features.hash ();
+  }
+};
+
+/* Cache of previously created target descriptions, indexed by the hash
+   of the features set used to create them.  */
+static std::unordered_map<arc_gdbarch_features,
+			  const target_desc *,
+			  arc_gdbarch_features_hasher> arc_tdesc_cache;
+
+/* See arch/arc.h.  */
+
+const target_desc *
+arc_lookup_target_description (const struct arc_gdbarch_features &features)
+{
+  /* Lookup in the cache first.  */
+  const auto it = arc_tdesc_cache.find (features);
+  if (it != arc_tdesc_cache.end ())
+    return it->second;
+
+  target_desc *tdesc = arc_create_target_description (features);
+
+  /* Add the newly created target description to the repertoire.  */
+  arc_tdesc_cache.emplace (features, tdesc);
+
+  return tdesc;
+}
+
+#endif /* !GDBSERVER */
diff --git a/gdb/arch/arc.h b/gdb/arch/arc.h
index fd806ae7d34..4f400c93a7d 100644
--- a/gdb/arch/arc.h
+++ b/gdb/arch/arc.h
@@ -20,29 +20,65 @@
 
 #include "gdbsupport/tdesc.h"
 
-/* Supported ARC system hardware types.  */
-enum arc_sys_type
+/* Supported ARC ISAs.  */
+enum arc_isa
 {
-  ARC_SYS_TYPE_ARCOMPACT = 0,	  /* ARC600 or ARC700 */
-  ARC_SYS_TYPE_ARCV2,		  /* ARC EM or ARC HS */
-  ARC_SYS_TYPE_NUM
+  ARC_ISA_NONE = 0,
+  ARC_ISA_ARCV1,    /* a.k.a. ARCompact (ARC600, ARC700)  */
+  ARC_ISA_ARCV2	    /* such as ARC EM and ARC HS  */
 };
 
-static inline const char *
-arc_sys_type_to_str (const arc_sys_type type)
+struct arc_gdbarch_features
 {
-  switch (type)
-    {
-    case ARC_SYS_TYPE_ARCOMPACT:
-      return "ARC_SYS_TYPE_ARCOMPACT";
-    case ARC_SYS_TYPE_ARCV2:
-      return "ARC_SYS_TYPE_ARCV2";
-    default:
-      return "Invalid";
-    }
-}
-
-/* Create target description for the specified system type.  */
-target_desc *arc_create_target_description (arc_sys_type sys_type);
+  /* Register size in bytes.  Possible values are 4, and 8.  A 0 indicates
+     an uninitialised value.  */
+  int reg_size = 0;
+
+  /* See ARC_ISA enum.  */
+  int isa = ARC_ISA_NONE;
+
+  /* Equality operator.  */
+  bool operator== (const struct arc_gdbarch_features &rhs) const
+  {
+    return (reg_size == rhs.reg_size && isa == rhs.isa);
+  }
+
+  /* Inequality operator.  */
+  bool operator!= (const struct arc_gdbarch_features &rhs) const
+  {
+    return !(*this == rhs);
+  }
+
+  /* Used by std::unordered_map to hash the feature sets.  The hash is
+     calculated in the manner below:
+     REG_SIZE |  ISA
+      5-bits  | 4-bits  */
+
+  std::size_t hash () const noexcept
+  {
+    std::size_t val = ((reg_size & 0x1f) << 8 | (isa & 0xf) << 0);
+    return val;
+  }
+};
+
+#ifdef GDBSERVER
+
+/* Create and return a target description that is compatible with FEATURES.
+   The only external client of this must be the gdbserver which manipulates
+   the returned data.  */
+
+target_desc *arc_create_target_description
+	(const struct arc_gdbarch_features &features);
+
+#else
+
+/* Lookup the cache for a target description matching the FEATURES.
+   If nothing is found, then create one and return it.  */
+
+const target_desc *arc_lookup_target_description
+	(const struct arc_gdbarch_features &features);
+
+#endif /* GDBSERVER */
+
 
 #endif /* ARCH_ARC_H */
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index cc65baa6eda..532daa8226b 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -204,10 +204,10 @@ $(outdir)/%.dat: %.xml number-regs.xsl sort-regs.xsl gdbserver-regs.xsl
 FEATURE_XMLFILES = aarch64-core.xml \
 	aarch64-fpu.xml \
 	aarch64-pauth.xml \
-	arc/core-v2.xml \
-	arc/aux-v2.xml \
-	arc/core-arcompact.xml \
-	arc/aux-arcompact.xml \
+	arc/v1-core.xml \
+	arc/v1-aux.xml \
+	arc/v2-core.xml \
+	arc/v2-aux.xml \
 	arm/arm-core.xml \
 	arm/arm-fpa.xml \
 	arm/arm-m-profile.xml \
diff --git a/gdb/features/arc/aux-arcompact.c b/gdb/features/arc/v1-aux.c
similarity index 73%
rename from gdb/features/arc/aux-arcompact.c
rename to gdb/features/arc/v1-aux.c
index d8e8c74e639..d1540763433 100644
--- a/gdb/features/arc/aux-arcompact.c
+++ b/gdb/features/arc/v1-aux.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: aux-arcompact.xml */
+  Original: v1-aux.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_aux_arcompact (struct target_desc *result, long regnum)
+create_feature_arc_v1_aux (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux-minimal");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux");
   tdesc_type_with_fields *type_with_fields;
   type_with_fields = tdesc_create_flags (feature, "status32_type", 4);
   tdesc_add_flag (type_with_fields, 0, "H");
@@ -27,5 +27,8 @@ create_feature_arc_aux_arcompact (struct target_desc *result, long regnum)
 
   tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "status32", regnum++, 1, NULL, 32, "status32_type");
+  tdesc_create_reg (feature, "lp_start", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "lp_end", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "bta", regnum++, 1, NULL, 32, "code_ptr");
   return regnum;
 }
diff --git a/gdb/features/arc/aux-arcompact.xml b/gdb/features/arc/v1-aux.xml
similarity index 80%
rename from gdb/features/arc/aux-arcompact.xml
rename to gdb/features/arc/v1-aux.xml
index bf68112f5db..091808b1e29 100644
--- a/gdb/features/arc/aux-arcompact.xml
+++ b/gdb/features/arc/v1-aux.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.aux-minimal">
+<feature name="org.gnu.gdb.arc.aux">
   <flags id="status32_type" size="4">
       <field name="H"   start="0" end="0"/>
       <field name="E"   start="1" end="2"/>
@@ -19,10 +19,13 @@
       <field name="N"   start="10" end="10"/>
       <field name="Z"   start="11" end="11"/>
       <field name="L"   start="12" end="12"/>
-      <field name="R"  start="13" end="13"/>
+      <field name="R"   start="13" end="13"/>
       <field name="SE"  start="14" end="14"/>
   </flags>
 
   <reg name="pc"       bitsize="32" type="code_ptr"/>
   <reg name="status32" bitsize="32" type="status32_type"/>
+  <reg name="lp_start" bitsize="32" type="code_ptr"/>
+  <reg name="lp_end"   bitsize="32" type="code_ptr"/>
+  <reg name="bta"      bitsize="32" type="code_ptr"/>
 </feature>
diff --git a/gdb/features/arc/core-arcompact.c b/gdb/features/arc/v1-core.c
similarity index 87%
rename from gdb/features/arc/core-arcompact.c
rename to gdb/features/arc/v1-core.c
index 7d9a4b23c21..df51d4788df 100644
--- a/gdb/features/arc/core-arcompact.c
+++ b/gdb/features/arc/v1-core.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: core-arcompact.xml */
+  Original: v1-core.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_core_arcompact (struct target_desc *result, long regnum)
+create_feature_arc_v1_core (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core.arcompact");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core");
   tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
@@ -38,8 +38,6 @@ create_feature_arc_core_arcompact (struct target_desc *result, long regnum)
   tdesc_create_reg (feature, "gp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "fp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
-  tdesc_create_reg (feature, "ilink1", regnum++, 1, NULL, 32, "code_ptr");
-  tdesc_create_reg (feature, "ilink2", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "blink", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "lp_count", regnum++, 1, NULL, 32, "uint32");
   tdesc_create_reg (feature, "pcl", regnum++, 1, NULL, 32, "code_ptr");
diff --git a/gdb/features/arc/core-arcompact.xml b/gdb/features/arc/v1-core.xml
similarity index 92%
rename from gdb/features/arc/core-arcompact.xml
rename to gdb/features/arc/v1-core.xml
index 9209891b41a..68d04bdf9d0 100644
--- a/gdb/features/arc/core-arcompact.xml
+++ b/gdb/features/arc/v1-core.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.core.arcompact">
+<feature name="org.gnu.gdb.arc.core">
   <reg name="r0"  bitsize="32"/>
   <reg name="r1"  bitsize="32"/>
   <reg name="r2"  bitsize="32"/>
@@ -40,8 +40,6 @@
   <reg name="sp"  bitsize="32" type="data_ptr"/>
 
   <!-- Code pointers.  -->
-  <reg name="ilink1" bitsize="32" type="code_ptr"/>
-  <reg name="ilink2" bitsize="32" type="code_ptr"/>
   <reg name="blink"  bitsize="32" type="code_ptr"/>
 
   <!-- Here goes extension core registers: r32 - r59 -->
diff --git a/gdb/features/arc/aux-v2.c b/gdb/features/arc/v2-aux.c
similarity index 76%
rename from gdb/features/arc/aux-v2.c
rename to gdb/features/arc/v2-aux.c
index 6290b9b1a7f..7b38e377fe1 100644
--- a/gdb/features/arc/aux-v2.c
+++ b/gdb/features/arc/v2-aux.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: aux-v2.xml */
+  Original: v2-aux.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_aux_v2 (struct target_desc *result, long regnum)
+create_feature_arc_v2_aux (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux-minimal");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux");
   tdesc_type_with_fields *type_with_fields;
   type_with_fields = tdesc_create_flags (feature, "status32_type", 4);
   tdesc_add_flag (type_with_fields, 0, "H");
@@ -31,5 +31,8 @@ create_feature_arc_aux_v2 (struct target_desc *result, long regnum)
 
   tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "status32", regnum++, 1, NULL, 32, "status32_type");
+  tdesc_create_reg (feature, "lp_start", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "lp_end", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "bta", regnum++, 1, NULL, 32, "code_ptr");
   return regnum;
 }
diff --git a/gdb/features/arc/aux-v2.xml b/gdb/features/arc/v2-aux.xml
similarity index 86%
rename from gdb/features/arc/aux-v2.xml
rename to gdb/features/arc/v2-aux.xml
index 2701fad72dc..5d81e248088 100644
--- a/gdb/features/arc/aux-v2.xml
+++ b/gdb/features/arc/v2-aux.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.aux-minimal">
+<feature name="org.gnu.gdb.arc.aux">
   <flags id="status32_type" size="4">
       <field name="H"   start="0" end="0"/>
       <field name="E"   start="1" end="4"/>
@@ -29,4 +29,7 @@
 
   <reg name="pc"       bitsize="32" type="code_ptr"/>
   <reg name="status32" bitsize="32" type="status32_type"/>
+  <reg name="lp_start" bitsize="32" type="code_ptr"/>
+  <reg name="lp_end"   bitsize="32" type="code_ptr"/>
+  <reg name="bta"      bitsize="32" type="code_ptr"/>
 </feature>
diff --git a/gdb/features/arc/core-v2.c b/gdb/features/arc/v2-core.c
similarity index 91%
rename from gdb/features/arc/core-v2.c
rename to gdb/features/arc/v2-core.c
index d37da990457..1c3ef1a91df 100644
--- a/gdb/features/arc/core-v2.c
+++ b/gdb/features/arc/v2-core.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: core-v2.xml */
+  Original: v2-core.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_core_v2 (struct target_desc *result, long regnum)
+create_feature_arc_v2_core (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core.v2");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core");
   tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
@@ -38,7 +38,6 @@ create_feature_arc_core_v2 (struct target_desc *result, long regnum)
   tdesc_create_reg (feature, "gp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "fp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
-  tdesc_create_reg (feature, "ilink", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "r30", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "blink", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "lp_count", regnum++, 1, NULL, 32, "uint32");
diff --git a/gdb/features/arc/core-v2.xml b/gdb/features/arc/v2-core.xml
similarity index 90%
rename from gdb/features/arc/core-v2.xml
rename to gdb/features/arc/v2-core.xml
index 1b17968fb2e..2a2561eab16 100644
--- a/gdb/features/arc/core-v2.xml
+++ b/gdb/features/arc/v2-core.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.core.v2">
+<feature name="org.gnu.gdb.arc.core">
   <reg name="r0"  bitsize="32"/>
   <reg name="r1"  bitsize="32"/>
   <reg name="r2"  bitsize="32"/>
@@ -42,12 +42,11 @@
   <!-- Code pointers.  R30 is general purpose, but it used to be ILINK2 in
   ARCompact, thus its odd position in between of special purpose registers.
   GCC does't use this register, so it isn't a member of a general group. -->
-  <reg name="ilink" bitsize="32" type="code_ptr"/>
   <reg name="r30"   bitsize="32" group=""/>
   <reg name="blink" bitsize="32" type="code_ptr"/>
 
-  <!-- Here goes extension core registers: r32 - r57.  -->
-  <!-- Here goes ACCL/ACCH registers, r58, r59.  -->
+  <!-- Extension core registers: r32 - r57.  -->
+  <!-- ACCL/ACCH registers: r58, r59.  -->
 
   <!-- Loop counter.  -->
   <reg name="lp_count" bitsize="32" type="uint32"/>
-- 
2.27.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v3 2/3] arc: Add hardware loop detection
  2020-07-13 15:45   ` [PATCH v3 0/3] " Shahab Vahedi
  2020-07-13 15:45     ` [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
@ 2020-07-13 15:45     ` Shahab Vahedi
  2020-07-15  2:55       ` Simon Marchi
  2020-07-13 15:45     ` [PATCH v3 3/3] arc: Add GNU/Linux support for ARC Shahab Vahedi
  2020-07-23 19:35     ` [PATCH v4 0/3] arc: Add GNU/Linux support Shahab Vahedi
  3 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-07-13 15:45 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

For ARC there are registers that are not part of a required set in XML
target descriptions by default, but are almost always present on ARC
targets and are universally exposed by the ptrace interface.  Hardware
loop registers being one of them.

LP_START and LP_END auxiliary registers are hardware loop start and end.
Formally, they are optional, but it is hard to find an ARC configuration
that doesn't have them.  They are always present in processors that can
run GNU/Linux.  GDB needs to know about those registers to implement
proper software single stepping, since they affect  what instruction
will be next.

This commit adds the code to check for the existance of "lp_start" and
"lp_end" in XML target descriptions. If they exist, then the function
reports that the target supports hardware loops.

gdb/ChangeLog:
2020-07-09  Shahab Vahedi  <shahab@synopsys.com>

	* arc-tdep.c (arc_check_for_hardware_loop): New.
	* arc-tdep.h (gdbarch_tdep): New field has_hw_loops.

gdb/doc/ChangeLog:
2020-07-09  Anton Kolesov  <anton.kolesov@synopsys.com>

	* gdb.texinfo (Synopsys ARC): Document LP_START, LP_END and BTA.
---
 gdb/arc-tdep.c      | 39 +++++++++++++++++++++++++++++++++++----
 gdb/arc-tdep.h      |  4 ++++
 gdb/doc/gdb.texinfo |  3 ++-
 3 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 6979c2ad7d0..ad54a3a72d1 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -2007,6 +2007,35 @@ arc_check_tdesc_feature (struct tdesc_arch_data *tdesc_data,
   return true;
 }
 
+/* Check for the existance of "lp_start" and "lp_end" in target description.
+   If both are present, assume there is hardware loop support in the target.
+   This can be improved by looking into "lpc_size" field of "isa_config"
+   auxiliary register.  */
+
+static bool
+arc_check_for_hw_loops (const struct target_desc *tdesc,
+			struct tdesc_arch_data *data)
+{
+  const auto feature_aux = tdesc_find_feature (tdesc, ARC_AUX_FEATURE_NAME);
+  const auto *aux_regset = determine_aux_reg_feature_set ();
+
+  if (feature_aux == nullptr || aux_regset == nullptr)
+    return false;
+
+  bool hw_loop_p = false;
+  const auto lp_start_name =
+    aux_regset->registers[ARC_LP_START_REGNUM - ARC_FIRST_AUX_REGNUM].names[0];
+  const auto lp_end_name =
+    aux_regset->registers[ARC_LP_END_REGNUM - ARC_FIRST_AUX_REGNUM].names[0];
+
+  hw_loop_p = tdesc_numbered_register (feature_aux, data,
+				       ARC_LP_START_REGNUM, lp_start_name);
+  hw_loop_p &= tdesc_numbered_register (feature_aux, data,
+				       ARC_LP_END_REGNUM, lp_end_name);
+
+  return hw_loop_p;
+}
+
 /* Initialize target description for the ARC.
 
    Returns true if input TDESC was valid and in this case it will assign TDESC
@@ -2126,13 +2155,15 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     debug_printf ("arc: Architecture initialization.\n");
 
   if (!arc_tdesc_init (info, &tdesc, &tdesc_data))
-    return NULL;
+    return nullptr;
 
   /* Allocate the ARC-private target-dependent information structure, and the
      GDB target-independent information structure.  */
-  struct gdbarch_tdep *tdep = XCNEW (struct gdbarch_tdep);
+  gdb::unique_xmalloc_ptr<struct gdbarch_tdep> tdep
+    (XCNEW (struct gdbarch_tdep));
   tdep->jb_pc = -1; /* No longjmp support by default.  */
-  struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep);
+  tdep->has_hw_loops = arc_check_for_hw_loops (tdesc, tdesc_data);
+  struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep.release ());
 
   /* Data types.  */
   set_gdbarch_short_bit (gdbarch, 16);
@@ -2213,7 +2244,7 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      It can override functions set earlier.  */
   gdbarch_init_osabi (info, gdbarch);
 
-  if (tdep->jb_pc >= 0)
+  if (gdbarch_tdep (gdbarch)->jb_pc >= 0)
     set_gdbarch_get_longjmp_target (gdbarch, arc_get_longjmp_target);
 
   /* Disassembler options.  Enforce CPU if it was specified in XML target
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index f4ce6a9a50a..3c99f4aacb8 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -23,6 +23,7 @@
 
 /* Need disassemble_info.  */
 #include "dis-asm.h"
+#include "gdbarch.h"
 #include "arch/arc.h"
 
 /* To simplify GDB code this enum assumes that internal regnums should be same
@@ -110,6 +111,9 @@ struct gdbarch_tdep
   /* Offset to PC value in jump buffer.  If this is negative, longjmp
      support will be disabled.  */
   int jb_pc;
+
+  /* Whether target has hardware (aka zero-delay) loops.  */
+  bool has_hw_loops;
 };
 
 /* Utility functions used by other ARC-specific modules.  */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index d90c33d67ae..5c6c6b39fcf 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -45118,7 +45118,8 @@ difference with @samp{org.gnu.gdb.arc.core.v2} feature is in the names of
 ARC v2, but @samp{ilink2} is optional on ARCompact.
 
 The @samp{org.gnu.gdb.arc.aux-minimal} feature is required for all ARC
-targets.  It should contain registers @samp{pc} and @samp{status32}.
+targets.  It should contain registers @samp{pc} and @samp{status32}.  It may
+contain registers @samp{lp_start}, @samp{lp_end} and @samp{bta}.
 
 @node ARM Features
 @subsection ARM Features
-- 
2.27.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v3 3/3] arc: Add GNU/Linux support for ARC
  2020-07-13 15:45   ` [PATCH v3 0/3] " Shahab Vahedi
  2020-07-13 15:45     ` [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
  2020-07-13 15:45     ` [PATCH v3 2/3] arc: Add hardware loop detection Shahab Vahedi
@ 2020-07-13 15:45     ` Shahab Vahedi
  2020-07-15  3:03       ` Simon Marchi
  2020-07-23 19:35     ` [PATCH v4 0/3] arc: Add GNU/Linux support Shahab Vahedi
  3 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-07-13 15:45 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Anton Kolesov, Francois Bedard, Anton Kolesov

From: Anton Kolesov <Anton.Kolesov@synopsys.com>

ARC Linux targets differences from baremetal:

- No support for hardware single instruction stepping.
- Different access rules to registers.
- Use of another instruction for breakpoints.

v2: Changes after Tom's remarks [1]
 arc-linux-tdep.c
  - Use true/false instead of TRUE/FALSE.
  - arc_linux_sw_breakpoint_from_kind (): Break long lines into two.
  - arc_linux_sw_breakpoint_from_kind (): Remove starting blank line.
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 arc-tdep.c
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 gdb/configure.tgt
  - arc*-*-linux*): Remove "build_gdbserver=yes".

v3: Changes after Simon's remarks [2]
  arc-linux-tdep.c
  - Use "return trap_size" instead of cryptic "return 2".
  - Removed unnecessary curly braces.
  - Removed "void" from "_initialize_arc_linux_tdep (void)".

[1] Tom's remarks
https://sourceware.org/pipermail/gdb-patches/2020-April/167887.html

[2] Simon's remarks
https://sourceware.org/pipermail/gdb-patches/2020-May/168513.html

2020-04-28  Anton Kolesov  <anton.kolesov@synopsys.com>

	* configure.tgt: ARC support for GNU/Linux.
	* Makefile.in (ALL_TARGET_OBJS): Likewise.
	* arc-linux-tdep.c: New file.
	* arc-tdep.h (ARC_STATUS32_L_MASK, ARC_STATUS32_DE_MASK): Declare.
	* arc-tdep.c (arc_write_pc): Use it.
---
 gdb/Makefile.in      |   1 +
 gdb/arc-linux-tdep.c | 283 +++++++++++++++++++++++++++++++++++++++++++
 gdb/arc-tdep.c       |   3 +-
 gdb/arc-tdep.h       |   5 +
 gdb/configure.tgt    |   5 +
 5 files changed, 295 insertions(+), 2 deletions(-)
 create mode 100644 gdb/arc-linux-tdep.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 32d0eee7c63..9348652576f 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -695,6 +695,7 @@ ALL_64_TARGET_OBS = \
 # All other target-dependent objects files (used with --enable-targets=all).
 ALL_TARGET_OBS = \
 	aarch32-tdep.o \
+	arc-linux-tdep.o \
 	arc-tdep.o \
 	arch/aarch32.o \
 	arch/arc.o \
diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
new file mode 100644
index 00000000000..5d1c9a74833
--- /dev/null
+++ b/gdb/arc-linux-tdep.c
@@ -0,0 +1,283 @@
+/* Target dependent code for GNU/Linux ARC.
+
+   Copyright 2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* GDB header files.  */
+#include "defs.h"
+#include "linux-tdep.h"
+#include "objfiles.h"
+#include "opcode/arc.h"
+#include "osabi.h"
+#include "solib-svr4.h"
+
+/* ARC header files.  */
+#include "opcodes/arc-dis.h"
+#include "arc-tdep.h"
+
+/* Implement the "cannot_fetch_register" gdbarch method.  */
+
+static int
+arc_linux_cannot_fetch_register (struct gdbarch *gdbarch, int regnum)
+{
+  /* Assume that register is readable if it is unknown.  */
+  switch (regnum)
+    {
+    case ARC_ILINK_REGNUM:
+    case ARC_RESERVED_REGNUM:
+    case ARC_LIMM_REGNUM:
+      return true;
+    case ARC_R30_REGNUM:
+    case ARC_R58_REGNUM:
+    case ARC_R59_REGNUM:
+      return !arc_mach_is_arcv2 (gdbarch);
+    }
+  if (regnum > ARC_BLINK_REGNUM && regnum < ARC_LP_COUNT_REGNUM)
+    return true;
+  return false;
+}
+
+/* Implement the "cannot_store_register" gdbarch method.  */
+
+static int
+arc_linux_cannot_store_register (struct gdbarch *gdbarch, int regnum)
+{
+  /* Assume that register is writable if it is unknown.  */
+  switch (regnum)
+    {
+    case ARC_ILINK_REGNUM:
+    case ARC_RESERVED_REGNUM:
+    case ARC_LIMM_REGNUM:
+    case ARC_PCL_REGNUM:
+      return true;
+    case ARC_R30_REGNUM:
+    case ARC_R58_REGNUM:
+    case ARC_R59_REGNUM:
+      return !arc_mach_is_arcv2 (gdbarch);
+    }
+  if (regnum > ARC_BLINK_REGNUM && regnum < ARC_LP_COUNT_REGNUM)
+    return true;
+  return false;
+}
+
+/* For ARC Linux, breakpoint uses the 16-bit TRAP_S 1 instruction, which
+   is 0x3e78 (little endian) or 0x783e (big endian).  */
+
+static const gdb_byte arc_linux_trap_s_be[] = { 0x78, 0x3e };
+static const gdb_byte arc_linux_trap_s_le[] = { 0x3e, 0x78 };
+static const int trap_size = 2;   /* Number of bytes to insert "trap".  */
+
+/* Implement the "breakpoint_kind_from_pc" gdbarch method.  */
+
+static int
+arc_linux_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+  return trap_size;
+}
+
+/* Implement the "sw_breakpoint_from_kind" gdbarch method.  */
+
+static const gdb_byte *
+arc_linux_sw_breakpoint_from_kind (struct gdbarch *gdbarch,
+				   int kind, int *size)
+{
+  *size = kind;
+  return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+	  ? arc_linux_trap_s_be
+	  : arc_linux_trap_s_le);
+}
+
+/* Implement the "software_single_step" gdbarch method.  */
+
+static std::vector<CORE_ADDR>
+arc_linux_software_single_step (struct regcache *regcache)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct disassemble_info di = arc_disassemble_info (gdbarch);
+
+  /* Read current instruction.  */
+  struct arc_instruction curr_insn;
+  arc_insn_decode (regcache_read_pc (regcache), &di, arc_delayed_print_insn,
+		   &curr_insn);
+  CORE_ADDR next_pc = arc_insn_get_linear_next_pc (curr_insn);
+
+  std::vector<CORE_ADDR> next_pcs;
+
+  /* For instructions with delay slots, the fall thru is not the
+     instruction immediately after the current instruction, but the one
+     after that.  */
+  if (curr_insn.has_delay_slot)
+    {
+      struct arc_instruction next_insn;
+      arc_insn_decode (next_pc, &di, arc_delayed_print_insn, &next_insn);
+      next_pcs.push_back (arc_insn_get_linear_next_pc (next_insn));
+    }
+  else
+    next_pcs.push_back (next_pc);
+
+  ULONGEST status32;
+  regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
+				 &status32);
+
+  if (curr_insn.is_control_flow)
+    {
+      CORE_ADDR branch_pc = arc_insn_get_branch_target (curr_insn);
+      if (branch_pc != next_pc)
+	next_pcs.push_back (branch_pc);
+    }
+  /* Is current instruction the last in a loop body?  */
+  else if (tdep->has_hw_loops)
+    {
+      /* If STATUS32.L is 1, then ZD-loops are disabled.  */
+      if ((status32 & ARC_STATUS32_L_MASK) == 0)
+	{
+	  ULONGEST lp_end, lp_start, lp_count;
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_START_REGNUM,
+					 &lp_start);
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_END_REGNUM, &lp_end);
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_COUNT_REGNUM,
+					 &lp_count);
+
+	  if (arc_debug)
+	    {
+	      debug_printf ("arc-linux: lp_start = %s, lp_end = %s, "
+			    "lp_count = %s, next_pc = %s\n",
+			    paddress (gdbarch, lp_start),
+			    paddress (gdbarch, lp_end),
+			    pulongest (lp_count),
+			    paddress (gdbarch, next_pc));
+	    }
+
+	  if (next_pc == lp_end && lp_count > 1)
+	    {
+	      /* The instruction is in effect a jump back to the start of
+		 the loop.  */
+	      next_pcs.push_back (lp_start);
+	    }
+
+	}
+    }
+
+  /* Is this a delay slot?  Then next PC is in BTA register.  */
+  if ((status32 & ARC_STATUS32_DE_MASK) != 0)
+    {
+      ULONGEST bta;
+      regcache_cooked_read_unsigned (regcache, ARC_BTA_REGNUM, &bta);
+      next_pcs.push_back (bta);
+    }
+
+  return next_pcs;
+}
+
+/* Implement the "skip_solib_resolver" gdbarch method.
+
+   See glibc_skip_solib_resolver for details.  */
+
+static CORE_ADDR
+arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  /* For uClibc 0.9.26+.
+
+     An unresolved PLT entry points to "__dl_linux_resolve", which calls
+     "_dl_linux_resolver" to do the resolving and then eventually jumps to
+     the function.
+
+     So we look for the symbol `_dl_linux_resolver', and if we are there,
+     gdb sets a breakpoint at the return address, and continues.  */
+  struct bound_minimal_symbol resolver =
+    lookup_minimal_symbol ("_dl_linux_resolver", NULL, NULL);
+
+  if (arc_debug)
+    {
+      if (resolver.minsym)
+	{
+	  CORE_ADDR res_addr = BMSYMBOL_VALUE_ADDRESS (resolver);
+	  debug_printf ("arc-linux: skip_solib_resolver (): "
+			"pc = %s, resolver at %s\n",
+			print_core_address (gdbarch, pc),
+			print_core_address (gdbarch, res_addr));
+	}
+      else
+	{
+	  debug_printf ("arc-linux: skip_solib_resolver (): "
+			"pc = %s, no resolver found\n",
+			print_core_address (gdbarch, pc));
+	}
+    }
+
+  if (resolver.minsym && BMSYMBOL_VALUE_ADDRESS (resolver) == pc)
+    {
+      /* Find the return address.  */
+      return frame_unwind_caller_pc (get_current_frame ());
+    }
+  else
+    {
+      /* No breakpoint required.  */
+      return 0;
+    }
+}
+
+/* Initialization specific to Linux environment.  */
+
+static void
+arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (arc_debug)
+    debug_printf ("arc-linux: GNU/Linux OS/ABI initialization.\n");
+
+  /* If we are using Linux, we have in uClibc
+     (libc/sysdeps/linux/arc/bits/setjmp.h):
+
+     typedef int __jmp_buf[13+1+1+1];    //r13-r25, fp, sp, blink
+
+     Where "blink" is a stored PC of a caller function.
+   */
+  tdep->jb_pc = 15;
+
+  linux_init_abi (info, gdbarch);
+
+  /* Set up target dependent GDB architecture entries.  */
+  set_gdbarch_cannot_fetch_register (gdbarch, arc_linux_cannot_fetch_register);
+  set_gdbarch_cannot_store_register (gdbarch, arc_linux_cannot_store_register);
+  set_gdbarch_breakpoint_kind_from_pc (gdbarch,
+				       arc_linux_breakpoint_kind_from_pc);
+  set_gdbarch_sw_breakpoint_from_kind (gdbarch,
+				       arc_linux_sw_breakpoint_from_kind);
+  set_gdbarch_fetch_tls_load_module_address (gdbarch,
+					     svr4_fetch_objfile_link_map);
+  set_gdbarch_software_single_step (gdbarch, arc_linux_software_single_step);
+  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+  set_gdbarch_skip_solib_resolver (gdbarch, arc_linux_skip_solib_resolver);
+
+  /* GNU/Linux uses SVR4-style shared libraries, with 32-bit ints, longs
+     and pointers (ILP32).  */
+  set_solib_svr4_fetch_link_map_offsets (gdbarch,
+					 svr4_ilp32_fetch_link_map_offsets);
+}
+
+/* Suppress warning from -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_arc_linux_tdep;
+
+void
+_initialize_arc_linux_tdep ()
+{
+  gdbarch_register_osabi (bfd_arch_arc, 0, GDB_OSABI_LINUX,
+			  arc_linux_init_osabi);
+}
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index ad54a3a72d1..1712eff5a63 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -602,8 +602,7 @@ arc_write_pc (struct regcache *regcache, CORE_ADDR new_pc)
   regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
 				 &status32);
 
-  /* Mask for DE bit is 0x40.  */
-  if (status32 & 0x40)
+  if ((status32 & ARC_STATUS32_DE_MASK) != 0)
     {
       if (arc_debug)
 	{
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index 3c99f4aacb8..319450fa334 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -100,6 +100,11 @@ enum arc_regnum
    Longer registers are represented as pairs of 32-bit registers.  */
 #define ARC_REGISTER_SIZE  4
 
+/* STATUS32 register: hardware loops disabled bit.  */
+#define ARC_STATUS32_L_MASK (1 << 12)
+/* STATUS32 register: current instruction is a delay slot.  */
+#define ARC_STATUS32_DE_MASK (1 << 6)
+
 #define arc_print(fmt, args...) fprintf_unfiltered (gdb_stdlog, fmt, ##args)
 
 extern int arc_debug;
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index b3f31af763c..1a5c3a351fd 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -157,6 +157,11 @@ arc*-*-elf32)
 	gdb_target_obs="arc-newlib-tdep.o"
 	;;
 
+arc*-*-linux*)
+	# Target: ARC machine running Linux
+	gdb_target_obs="arc-linux-tdep.o linux-tdep.o solib-svr4.o"
+	;;
+
 arm*-wince-pe | arm*-*-mingw32ce*)
 	# Target: ARM based machine running Windows CE (win32)
 	gdb_target_obs="arm-wince-tdep.o windows-tdep.o"
-- 
2.27.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v2 2/4] arc: Recognize registers available on Linux targets
  2020-06-17 15:46       ` Shahab Vahedi
@ 2020-07-13 15:48         ` Simon Marchi
  2020-07-14  9:05           ` Shahab Vahedi
  0 siblings, 1 reply; 86+ messages in thread
From: Simon Marchi @ 2020-07-13 15:48 UTC (permalink / raw)
  To: Shahab Vahedi
  Cc: Anton Kolesov, Shahab Vahedi, Tom Tromey, gdb-patches, Francois Bedard

On 2020-06-17 11:46 a.m., Shahab Vahedi via Gdb-patches wrote:
> *_register_names are static arrays. That should be why gdb_STATIC_assert
> is used as well. I believe this place in the code is OK for making that
> check.

I meant, could those gdb_static_assert "calls" be moved right next to where the
arrays are defined?

Simon

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v2 2/4] arc: Recognize registers available on Linux targets
  2020-07-13 15:48         ` Simon Marchi
@ 2020-07-14  9:05           ` Shahab Vahedi
  0 siblings, 0 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-07-14  9:05 UTC (permalink / raw)
  To: Simon Marchi, Shahab Vahedi
  Cc: Anton Kolesov, Tom Tromey, gdb-patches, Francois Bedard

On 7/13/20 5:48 PM, Simon Marchi wrote:
> I meant, could those gdb_static_assert "calls" be moved right next to where the
> arrays are defined?

That was my bad, sorry. I _assumed_ it was not possible to use "gdb_static_assert ()"
next to a global variable, but it does work like a charm if the input is a
constant-expression.

Nevertheless, with the new changes in v3 [1], this gdb_static_assert () is irrelative.


[1] patch v3
https://sourceware.org/pipermail/gdb-patches/2020-July/170394.html

-- 
Shahab

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring
  2020-07-13 15:45     ` [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
@ 2020-07-15  2:52       ` Simon Marchi
  2020-07-15 20:35         ` Shahab Vahedi
  0 siblings, 1 reply; 86+ messages in thread
From: Simon Marchi @ 2020-07-15  2:52 UTC (permalink / raw)
  To: Shahab Vahedi, gdb-patches
  Cc: Shahab Vahedi, Tom Tromey, Anton Kolesov, Francois Bedard

Hi Shahab,

Again, I'm a bit clueless for the ARC-specific stuff, I'll assume it's all right.

I just put a few minor comments, but it looks like the feature-based target description
thing is well done.

> @@ -91,63 +93,201 @@ int arc_debug;
>  
>  static struct cmd_list_element *maintenance_print_arc_list = NULL;
>  
> -/* XML target description features.  */
> -
> -static const char core_v2_feature_name[] = "org.gnu.gdb.arc.core.v2";
> -static const char
> -  core_reduced_v2_feature_name[] = "org.gnu.gdb.arc.core-reduced.v2";
> -static const char
> -  core_arcompact_feature_name[] = "org.gnu.gdb.arc.core.arcompact";
> -static const char aux_minimal_feature_name[] = "org.gnu.gdb.arc.aux-minimal";
> -
> -/* XML target description known registers.  */
> -
> -static const char *const core_v2_register_names[] = {
> -  "r0", "r1", "r2", "r3",
> -  "r4", "r5", "r6", "r7",
> -  "r8", "r9", "r10", "r11",
> -  "r12", "r13", "r14", "r15",
> -  "r16", "r17", "r18", "r19",
> -  "r20", "r21", "r22", "r23",
> -  "r24", "r25", "gp", "fp",
> -  "sp", "ilink", "r30", "blink",
> -  "r32", "r33", "r34", "r35",
> -  "r36", "r37", "r38", "r39",
> -  "r40", "r41", "r42", "r43",
> -  "r44", "r45", "r46", "r47",
> -  "r48", "r49", "r50", "r51",
> -  "r52", "r53", "r54", "r55",
> -  "r56", "r57", "accl", "acch",
> -  "lp_count", "reserved", "limm", "pcl",
> +/* A set of registers that we expect to find in a tdesc_feature.  These
> +   are used in ARC_TDESC_INIT when processing the target description.  */
> +
> +struct arc_register_feature
> +{
> +  /* Information for a single register.  */
> +  struct register_info
> +  {
> +    /* The GDB register number for this register.  */
> +    int regnum;
> +
> +    /* List of names for this register.  The first name in this list is the
> +       preferred name, the name GDB will use when describing this register.  */
> +    std::vector<const char *> names;
> +
> +    /* When true, this register must be present in this feature set.  */
> +    bool required_p;
> +  };
> +
> +  /* The name for this feature.  This is the name used to find this feature
> +     within the target description.  */
> +  const char *name;
> +
> +  /* List of all the registers that we expect to encounter in this register
> +     set.  */
> +  std::vector<struct register_info> registers;
>  };
>  
> -static const char *const aux_minimal_register_names[] = {
> -  "pc", "status32",
> +static const char *ARC_CORE_FEATURE_NAME="org.gnu.gdb.arc.core";
> +static const char *ARC_AUX_FEATURE_NAME="org.gnu.gdb.arc.aux";

Spaces around `=`.

> @@ -1717,192 +1857,227 @@ static const struct frame_base arc_normal_base = {
>    arc_frame_base_address
>  };
>  
> -/* Initialize target description for the ARC.
> -
> -   Returns TRUE if input tdesc was valid and in this case it will assign TDESC
> -   and TDESC_DATA output parameters.  */
> -
> -static bool
> -arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
> -		struct tdesc_arch_data **tdesc_data)
> +static inline enum
> +arc_isa mach_type_to_arc_isa (const unsigned long mach)

`arc_isa` goes on previous line.  I'd drop the `inline`, the compiler will take
care of that if needed.

>  {
> -  if (arc_debug)
> -    debug_printf ("arc: Target description initialization.\n");
> -
> -  const struct target_desc *tdesc_loc = info.target_desc;
> -
> -  /* Depending on whether this is ARCompact or ARCv2 we will assign
> -     different default registers sets (which will differ in exactly two core
> -     registers).  GDB will also refuse to accept register feature from invalid
> -     ISA - v2 features can be used only with v2 ARChitecture.  We read
> -     bfd_arch_info, which looks like to be a safe bet here, as it looks like it
> -     is always initialized even when we don't pass any elf file to GDB at all
> -     (it uses default arch in this case).  Also GDB will call this function
> -     multiple times, and if XML target description file contains architecture
> -     specifications, then GDB will set this architecture to info.bfd_arch_info,
> -     overriding value from ELF file if they are different.  That means that,
> -     where matters, this value is always our best guess on what CPU we are
> -     debugging.  It has been noted that architecture specified in tdesc file
> -     has higher precedence over ELF and even "set architecture" - that is,
> -     using "set architecture" command will have no effect when tdesc has "arch"
> -     tag.  */
> -  /* Cannot use arc_mach_is_arcv2 (), because gdbarch is not created yet.  */
> -  const int is_arcv2 = (info.bfd_arch_info->mach == bfd_mach_arc_arcv2);
> -  bool is_reduced_rf;
> -  const char *const *core_regs;
> -  const char *core_feature_name;
> +  switch (mach)
> +    {
> +    case bfd_mach_arc_arc600:
> +    case bfd_mach_arc_arc601:
> +    case bfd_mach_arc_arc700:
> +      return ARC_ISA_ARCV1;
> +      break;
> +    case bfd_mach_arc_arcv2:
> +      return ARC_ISA_ARCV2;
> +      break;
> +    default:
> +	internal_error (__FILE__, __LINE__,
> +			_("unknown machine id %lu"), mach);
> +    }
> +  return ARC_ISA_NONE;
> +}
>  
> -  /* If target doesn't provide a description, use the default ones.  */
> -  if (!tdesc_has_registers (tdesc_loc))
> +/* Common construction code for ARC_GDBARCH_FEATURES struct.  If there
> +   is no ABFD, then a FEATURE with default values is returned.  */
> +void arc_gdbarch_features_init (arc_gdbarch_features &features,
> +				const bfd *abfd, const unsigned long mach)

Since this function is only used in this file, can it be static?

Could this function return a arc_gdbarch_features by value instead?  Then,
you could add a constructor to arc_gdbarch_features.  You wouldn't need
the "A 0 indicates an uninitialised value" comment on reg_size, as the
object could never be in an uninitialised state.

> +{
> +  /* Try to guess the features parameters by looking at the binary to be
> +     executed.  If the user is providing a binary that does not match the
> +     target, then tough luck.  This is the last effort to makes sense of
> +     what's going on.  */
> +  if (abfd != NULL && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
>      {
> -      if (is_arcv2)
> -	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCV2);
> +      unsigned char eclass = elf_elfheader (abfd)->e_ident[EI_CLASS];
> +
> +      if (eclass == ELFCLASS32)
> +	features.reg_size = 4;
> +      else if (eclass == ELFCLASS64)
> +	features.reg_size = 8;
>        else
> -	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCOMPACT);
> +	internal_error (__FILE__, __LINE__,
> +			_("unknown ELF header class %d"), eclass);
>      }
> -  else
> +
> +  /* MACH from a bfd_arch_info struct is used here.  It should be a safe
> +     bet, as it looks like the struct is always initialized even when we
> +     don't pass any elf file to GDB at all (it uses default arch in that
> +     case).  */
> +  features.isa = mach_type_to_arc_isa (mach);
> +
> +  /* Put the most frequent values for the undetermined parameters.  */
> +  if (features.reg_size == 0)
> +    features.reg_size = 4;

Can you add an empty line here to separate the two `if`s?

> +  if (features.isa == ARC_ISA_NONE)
> +    features.reg_size = ARC_ISA_ARCV2;

Did you mean to assign features.isa on the last line?

> diff --git a/gdb/arch/arc.c b/gdb/arch/arc.c
> index 9552b4aff97..84bc8df7788 100644
> --- a/gdb/arch/arc.c
> +++ b/gdb/arch/arc.c
> @@ -17,42 +17,104 @@
>  
>  
>  #include "gdbsupport/common-defs.h"
> -#include <stdlib.h>
> -
>  #include "arc.h"
> +#include <stdlib.h>
> +#include <unordered_map>
> +#include <sstream>
>  
>  /* Target description features.  */
> -#include "features/arc/core-v2.c"
> -#include "features/arc/aux-v2.c"
> -#include "features/arc/core-arcompact.c"
> -#include "features/arc/aux-arcompact.c"
> +#include "features/arc/v1-core.c"
> +#include "features/arc/v1-aux.c"
> +#include "features/arc/v2-core.c"
> +#include "features/arc/v2-aux.c"
>  
> -/* See arc.h.  */
> +#ifndef GDBSERVER
> +#define STATIC_IN_GDB static
> +#else
> +#define STATIC_IN_GDB
> +#endif
>  
> -target_desc *
> -arc_create_target_description (arc_sys_type sys_type)
> +STATIC_IN_GDB target_desc *
> +arc_create_target_description (const struct arc_gdbarch_features &features)
>  {
> +  /* Create a new target description.  */
>    target_desc *tdesc = allocate_target_description ();
>  
> -  long regnum = 0;
> -
>  #ifndef IN_PROCESS_AGENT
> -  if (sys_type == ARC_SYS_TYPE_ARCV2)
> -    set_tdesc_architecture (tdesc, "arc:ARCv2");
> -  else
> -    set_tdesc_architecture (tdesc, "arc:ARC700");
> -#endif
> +  std::string arch_name = "arc";
>  
> -  if (sys_type == ARC_SYS_TYPE_ARCV2)
> +  /* Architecture names here must match the ones in
> +     ARCH_INFO_STRUCT in bfd/cpu-arc.c.  */
> +  if (features.isa == ARC_ISA_ARCV1 && features.reg_size == 4)
> +      arch_name.append (":ARC700");
> +  else if (features.isa == ARC_ISA_ARCV2 && features.reg_size == 4)
> +      arch_name.append (":ARCv2");

It's really a nit, but it would be more efficient to just use two constant
strings:

const char *arch_name;

if (a)
  arch_name = "arc:ARC700";
else if (b)
  arch_name = "arc:ARCv2";
else
  assert

> +  else
>      {
> -      regnum = create_feature_arc_core_v2 (tdesc, regnum);
> -      regnum = create_feature_arc_aux_v2 (tdesc, regnum);
> +      std::ostringstream msg;
> +      msg << "Cannot determine architecture: ISA=" << features.isa
> +	  << "; bitness=" << 8*features.reg_size;

I'd suggest using string_printf instead, throughout the patch where you use
ostringstream.

> +      gdb_assert_not_reached (msg.str ().c_str ());
>      }
> -  else
> +
> +  set_tdesc_architecture (tdesc, arch_name.c_str ());
> +#endif
> +
> +  long regnum = 0;
> +
> +  switch (features.isa)
>      {
> -      regnum = create_feature_arc_core_arcompact (tdesc, regnum);
> -      regnum = create_feature_arc_aux_arcompact (tdesc, regnum);
> +    case ARC_ISA_ARCV1:
> +	  regnum = create_feature_arc_v1_core (tdesc, regnum);
> +	  regnum = create_feature_arc_v1_aux (tdesc, regnum);
> +	  break;
> +    case ARC_ISA_ARCV2:
> +	  regnum = create_feature_arc_v2_core (tdesc, regnum);
> +	  regnum = create_feature_arc_v2_aux (tdesc, regnum);
> +	  break;
> +    default:
> +	  std::ostringstream msg;
> +	  msg << "Cannot choose target description XML: " << features.isa;
> +	  gdb_assert_not_reached (msg.str ().c_str ());
>      }
>  
>    return tdesc;
>  }
> +
> +#ifndef GDBSERVER
> +
> +/* Wrapper used by std::unordered_map to generate hash for features set.  */
> +struct arc_gdbarch_features_hasher
> +{
> +  std::size_t
> +  operator() (const arc_gdbarch_features &features) const noexcept
> +  {
> +    return features.hash ();
> +  }
> +};
> +
> +/* Cache of previously created target descriptions, indexed by the hash
> +   of the features set used to create them.  */
> +static std::unordered_map<arc_gdbarch_features,
> +			  const target_desc *,
> +			  arc_gdbarch_features_hasher> arc_tdesc_cache;

Should this map hold unique_ptr of target_desc?  I understand that they
are never really deallocated anyway, but just to do it right and avoid
adding more leaks to the final AddressSanitizer report shown when you exit
GDB (and you have it build with AddressSanitizer)?

> +
> +/* See arch/arc.h.  */
> +
> +const target_desc *
> +arc_lookup_target_description (const struct arc_gdbarch_features &features)
> +{
> +  /* Lookup in the cache first.  */
> +  const auto it = arc_tdesc_cache.find (features);
> +  if (it != arc_tdesc_cache.end ())
> +    return it->second;
> +
> +  target_desc *tdesc = arc_create_target_description (features);
> +
> +  /* Add the newly created target description to the repertoire.  */
> +  arc_tdesc_cache.emplace (features, tdesc);
> +
> +  return tdesc;
> +}
> +
> +#endif /* !GDBSERVER */
> diff --git a/gdb/arch/arc.h b/gdb/arch/arc.h
> index fd806ae7d34..4f400c93a7d 100644
> --- a/gdb/arch/arc.h
> +++ b/gdb/arch/arc.h
> @@ -20,29 +20,65 @@
>  
>  #include "gdbsupport/tdesc.h"
>  
> -/* Supported ARC system hardware types.  */
> -enum arc_sys_type
> +/* Supported ARC ISAs.  */
> +enum arc_isa
>  {
> -  ARC_SYS_TYPE_ARCOMPACT = 0,	  /* ARC600 or ARC700 */
> -  ARC_SYS_TYPE_ARCV2,		  /* ARC EM or ARC HS */
> -  ARC_SYS_TYPE_NUM
> +  ARC_ISA_NONE = 0,
> +  ARC_ISA_ARCV1,    /* a.k.a. ARCompact (ARC600, ARC700)  */
> +  ARC_ISA_ARCV2	    /* such as ARC EM and ARC HS  */
>  };
>  
> -static inline const char *
> -arc_sys_type_to_str (const arc_sys_type type)
> +struct arc_gdbarch_features
>  {
> -  switch (type)
> -    {
> -    case ARC_SYS_TYPE_ARCOMPACT:
> -      return "ARC_SYS_TYPE_ARCOMPACT";
> -    case ARC_SYS_TYPE_ARCV2:
> -      return "ARC_SYS_TYPE_ARCV2";
> -    default:
> -      return "Invalid";
> -    }
> -}
> -
> -/* Create target description for the specified system type.  */
> -target_desc *arc_create_target_description (arc_sys_type sys_type);
> +  /* Register size in bytes.  Possible values are 4, and 8.  A 0 indicates
> +     an uninitialised value.  */
> +  int reg_size = 0;
> +
> +  /* See ARC_ISA enum.  */
> +  int isa = ARC_ISA_NONE;
> +
> +  /* Equality operator.  */
> +  bool operator== (const struct arc_gdbarch_features &rhs) const
> +  {
> +    return (reg_size == rhs.reg_size && isa == rhs.isa);
> +  }
> +
> +  /* Inequality operator.  */
> +  bool operator!= (const struct arc_gdbarch_features &rhs) const
> +  {
> +    return !(*this == rhs);
> +  }
> +
> +  /* Used by std::unordered_map to hash the feature sets.  The hash is
> +     calculated in the manner below:
> +     REG_SIZE |  ISA
> +      5-bits  | 4-bits  */
> +
> +  std::size_t hash () const noexcept
> +  {
> +    std::size_t val = ((reg_size & 0x1f) << 8 | (isa & 0xf) << 0);
> +    return val;

I don't know much about hashing, but I don't think makes for a very good hash
function.  It outputs similar hashes for similar inputs, and does not use the
range of possible hash values uniformly.

It would be more appropriate and typical to use std::hash on each member and
then combine the hashes.  Doing a quick search I found that Boost offers
something exactly for that called hash_combine:

https://www.boost.org/doc/libs/1_55_0/doc/html/hash/combine.html

Unfortunately, there is nothing similar in the standard library.  But

A bit off-topic: intuitively, I would have thought that it would have been
sufficient to just add the hash values together.  Anyone knows why this
wouldn't be a good idea?

Simon

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v3 2/3] arc: Add hardware loop detection
  2020-07-13 15:45     ` [PATCH v3 2/3] arc: Add hardware loop detection Shahab Vahedi
@ 2020-07-15  2:55       ` Simon Marchi
  0 siblings, 0 replies; 86+ messages in thread
From: Simon Marchi @ 2020-07-15  2:55 UTC (permalink / raw)
  To: Shahab Vahedi, gdb-patches
  Cc: Shahab Vahedi, Tom Tromey, Anton Kolesov, Francois Bedard

On 2020-07-13 11:45 a.m., Shahab Vahedi wrote:
> From: Shahab Vahedi <shahab@synopsys.com>
> 
> For ARC there are registers that are not part of a required set in XML
> target descriptions by default, but are almost always present on ARC
> targets and are universally exposed by the ptrace interface.  Hardware
> loop registers being one of them.
> 
> LP_START and LP_END auxiliary registers are hardware loop start and end.
> Formally, they are optional, but it is hard to find an ARC configuration
> that doesn't have them.  They are always present in processors that can
> run GNU/Linux.  GDB needs to know about those registers to implement
> proper software single stepping, since they affect  what instruction
> will be next.
> 
> This commit adds the code to check for the existance of "lp_start" and
> "lp_end" in XML target descriptions. If they exist, then the function
> reports that the target supports hardware loops.

This looks good to me.

Simon


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v3 3/3] arc: Add GNU/Linux support for ARC
  2020-07-13 15:45     ` [PATCH v3 3/3] arc: Add GNU/Linux support for ARC Shahab Vahedi
@ 2020-07-15  3:03       ` Simon Marchi
  0 siblings, 0 replies; 86+ messages in thread
From: Simon Marchi @ 2020-07-15  3:03 UTC (permalink / raw)
  To: Shahab Vahedi, gdb-patches
  Cc: Anton Kolesov, Francois Bedard, Shahab Vahedi, Tom Tromey

LGTM, with two nits below.

> +/* Implement the "skip_solib_resolver" gdbarch method.
> +
> +   See glibc_skip_solib_resolver for details.  */
> +
> +static CORE_ADDR
> +arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
> +{
> +  /* For uClibc 0.9.26+.
> +
> +     An unresolved PLT entry points to "__dl_linux_resolve", which calls
> +     "_dl_linux_resolver" to do the resolving and then eventually jumps to
> +     the function.
> +
> +     So we look for the symbol `_dl_linux_resolver', and if we are there,
> +     gdb sets a breakpoint at the return address, and continues.  */
> +  struct bound_minimal_symbol resolver =
> +    lookup_minimal_symbol ("_dl_linux_resolver", NULL, NULL);
> +
> +  if (arc_debug)
> +    {
> +      if (resolver.minsym)

!= nullptr

> +	{
> +	  CORE_ADDR res_addr = BMSYMBOL_VALUE_ADDRESS (resolver);
> +	  debug_printf ("arc-linux: skip_solib_resolver (): "
> +			"pc = %s, resolver at %s\n",
> +			print_core_address (gdbarch, pc),
> +			print_core_address (gdbarch, res_addr));
> +	}
> +      else
> +	{
> +	  debug_printf ("arc-linux: skip_solib_resolver (): "
> +			"pc = %s, no resolver found\n",
> +			print_core_address (gdbarch, pc));
> +	}
> +    }
> +
> +  if (resolver.minsym && BMSYMBOL_VALUE_ADDRESS (resolver) == pc)

!= nullptr

Simon

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring
  2020-07-15  2:52       ` Simon Marchi
@ 2020-07-15 20:35         ` Shahab Vahedi
  2020-07-15 21:23           ` Christian Biesinger
  2020-07-16 13:28           ` Simon Marchi
  0 siblings, 2 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-07-15 20:35 UTC (permalink / raw)
  To: Simon Marchi
  Cc: gdb-patches, Shahab Vahedi, Tom Tromey, Anton Kolesov, Francois Bedard

Hi Simon,

Thank you a lot for going through all the changes. I've taken most
of your remarks in. There are a few of them that need answering.
Below, you will find them.

If you think the current state of code is satisfactory, I will go
ahead and merge them. With one note: there might come another
patch on top of this if the output of "AddressSanitizer" shows some
leak. Please see my question for the "AddressSanitizer" below.

On Tue, Jul 14, 2020 at 10:52:12PM -0400, Simon Marchi wrote:
> Hi Shahab,
> 
> > +/* Common construction code for ARC_GDBARCH_FEATURES struct.  If there
> > +   is no ABFD, then a FEATURE with default values is returned.  */
> > +void arc_gdbarch_features_init (arc_gdbarch_features &features,
> > +				const bfd *abfd, const unsigned long mach)
> 
> Since this function is only used in this file, can it be static?

The other patch [1] in this series makes use of this function.

[1] [PATCH v3 3/3] arc: Add GNU/Linux support for ARC
https://sourceware.org/pipermail/gdb-patches/2020-July/170429.html
> Could this function return a arc_gdbarch_features by value instead?  Then,
> you could add a constructor to arc_gdbarch_features.  You wouldn't need
> the "A 0 indicates an uninitialised value" comment on reg_size, as the
> object could never be in an uninitialised state.

Those were my thoughts as well. I tried something like that, but I failed
in the end:

Since the "arc_gdbarch_features" is introduced in "gdb/arch/arc.h", I
tried implementing the constructor in "gdb/arch/arc.c". Because the
constructor had to make use of "struct bfd", "bfd_get_flavour ()",
"elf_header ()", "EFCLASS*", etc. the following headers had to be used in
"gdb/arch/arc.c":

  #include "defs.h"
  #include "arch-utils.h"
  #include "elf-bfd.h"

This would build OK for gdb targets, but when compiling "arc.o" for
gdbserver target, I ended up with something like:

  (paraphrasing)
  Error: defs.h should not be included while building gdbserver.
  (I am not sure if the error was indeed about "defs.h")

And removing/if-def-guarding that header file was opening other cans of
worms. Eventually, I gave up and went for the current approach.

> > +/* Wrapper used by std::unordered_map to generate hash for features set.  */
> > +struct arc_gdbarch_features_hasher
> > +{
> > +  std::size_t
> > +  operator() (const arc_gdbarch_features &features) const noexcept
> > +  {
> > +    return features.hash ();
> > +  }
> > +};
> > +
> > +/* Cache of previously created target descriptions, indexed by the hash
> > +   of the features set used to create them.  */
> > +static std::unordered_map<arc_gdbarch_features,
> > +			  const target_desc *,
> > +			  arc_gdbarch_features_hasher> arc_tdesc_cache;
> 
> Should this map hold unique_ptr of target_desc?  I understand that they
> are never really deallocated anyway, but just to do it right and avoid
> adding more leaks to the final AddressSanitizer report shown when you exit
> GDB (and you have it build with AddressSanitizer)?

No, I haven't built it with AddressSanitizer. Could you point me in the right
direction how I can use it?
> > +  /* Used by std::unordered_map to hash the feature sets.  The hash is
> > +     calculated in the manner below:
> > +     REG_SIZE |  ISA
> > +      5-bits  | 4-bits  */
> > +
> > +  std::size_t hash () const noexcept
> > +  {
> > +    std::size_t val = ((reg_size & 0x1f) << 8 | (isa & 0xf) << 0);
> > +    return val;
> 
> I don't know much about hashing, but I don't think makes for a very good hash
> function.  It outputs similar hashes for similar inputs, and does not use the
> range of possible hash values uniformly.

Indeed it does not output hashes uniformly but I believe it is unique. The
meaningful (and future proof) values for "reg_size" are {4, 8, 16} _bytes_.
Hence, the "0x1f" mask should suffice. Having 15 versions for ISA should be
enough as well. Having these conditions in mind, I don't think there is any
collusion while hashing such inputs.
> It would be more appropriate and typical to use std::hash on each member and
> then combine the hashes.  Doing a quick search I found that Boost offers
> something exactly for that called hash_combine:
> 
> https://www.boost.org/doc/libs/1_55_0/doc/html/hash/combine.html

Thanks for this. I didn't know about such functionality. As you said
though, we can't use it. Personally, I think it would be an overkill
here. We can get away with a simple "shift" and "or". Please read my
response above for my reasoning.
> 
> Unfortunately, there is nothing similar in the standard library.  But
> 
> A bit off-topic: intuitively, I would have thought that it would have been
> sufficient to just add the hash values together.  Anyone knows why this
> wouldn't be a good idea?

So far, possible values are:

  reg_size : {4, 8, 16}
  ISA: {1, 2, ... 15}

A simple addition would produce the same result for these legally valid
inputs:

reg_size=8, ISA=2   --->  hash = 10
reg_size=4, ISA=6   --->  hash = 10


Shahab

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring
  2020-07-15 20:35         ` Shahab Vahedi
@ 2020-07-15 21:23           ` Christian Biesinger
  2020-07-16  1:59             ` Simon Marchi
  2020-07-16 13:28           ` Simon Marchi
  1 sibling, 1 reply; 86+ messages in thread
From: Christian Biesinger @ 2020-07-15 21:23 UTC (permalink / raw)
  To: Shahab Vahedi
  Cc: Simon Marchi, Anton Kolesov, Shahab Vahedi, Tom Tromey,
	gdb-patches, Francois Bedard

On Wed, Jul 15, 2020 at 3:35 PM Shahab Vahedi via Gdb-patches
<gdb-patches@sourceware.org> wrote:
> No, I haven't built it with AddressSanitizer. Could you point me in the right
> direction how I can use it?

I'm not Simon, but--

To enable asan, just add it to CXXFLAGS, like:
../configure --enable-targets=all CXXFLAGS="-g -fsanitize=address"
CLAGS="-g -fsanitize=address"

Some documentation at https://github.com/google/sanitizers/wiki/AddressSanitizer

I thought someone had added a configure option for it, but for now it
looks like there's only --enable-ubsan

Christian

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring
  2020-07-15 21:23           ` Christian Biesinger
@ 2020-07-16  1:59             ` Simon Marchi
  0 siblings, 0 replies; 86+ messages in thread
From: Simon Marchi @ 2020-07-16  1:59 UTC (permalink / raw)
  To: Christian Biesinger, Shahab Vahedi
  Cc: Anton Kolesov, Shahab Vahedi, Tom Tromey, gdb-patches, Francois Bedard

On 2020-07-15 5:23 p.m., Christian Biesinger wrote:
> On Wed, Jul 15, 2020 at 3:35 PM Shahab Vahedi via Gdb-patches
> <gdb-patches@sourceware.org> wrote:
>> No, I haven't built it with AddressSanitizer. Could you point me in the right
>> direction how I can use it?
> 
> I'm not Simon, but--
> 
> To enable asan, just add it to CXXFLAGS, like:
> ../configure --enable-targets=all CXXFLAGS="-g -fsanitize=address"
> CLAGS="-g -fsanitize=address"
> 
> Some documentation at https://github.com/google/sanitizers/wiki/AddressSanitizer
> 
> I thought someone had added a configure option for it, but for now it
> looks like there's only --enable-ubsan

I had this thought the other day, maybe we should add --enable-asan?  Ideally, that
option would enable ASan in all binutils-gdb subprojects.

Simon

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring
  2020-07-15 20:35         ` Shahab Vahedi
  2020-07-15 21:23           ` Christian Biesinger
@ 2020-07-16 13:28           ` Simon Marchi
  2020-07-22 13:36             ` Shahab Vahedi
  1 sibling, 1 reply; 86+ messages in thread
From: Simon Marchi @ 2020-07-16 13:28 UTC (permalink / raw)
  To: Shahab Vahedi
  Cc: gdb-patches, Shahab Vahedi, Tom Tromey, Anton Kolesov, Francois Bedard

On 2020-07-15 4:35 p.m., Shahab Vahedi wrote:
>>> +/* Common construction code for ARC_GDBARCH_FEATURES struct.  If there
>>> +   is no ABFD, then a FEATURE with default values is returned.  */
>>> +void arc_gdbarch_features_init (arc_gdbarch_features &features,
>>> +				const bfd *abfd, const unsigned long mach)
>>
>> Since this function is only used in this file, can it be static?
> 
> The other patch [1] in this series makes use of this function.
> 
> [1] [PATCH v3 3/3] arc: Add GNU/Linux support for ARC
> https://sourceware.org/pipermail/gdb-patches/2020-July/170429.html

When I search for `arc_gdbarch_features_init` in that patch I don't find anything...

>> Could this function return a arc_gdbarch_features by value instead?  Then,
>> you could add a constructor to arc_gdbarch_features.  You wouldn't need
>> the "A 0 indicates an uninitialised value" comment on reg_size, as the
>> object could never be in an uninitialised state.
> 
> Those were my thoughts as well. I tried something like that, but I failed
> in the end:
> 
> Since the "arc_gdbarch_features" is introduced in "gdb/arch/arc.h", I
> tried implementing the constructor in "gdb/arch/arc.c". Because the
> constructor had to make use of "struct bfd", "bfd_get_flavour ()",
> "elf_header ()", "EFCLASS*", etc. the following headers had to be used in
> "gdb/arch/arc.c":
> 
>   #include "defs.h"
>   #include "arch-utils.h"
>   #include "elf-bfd.h"
> 
> This would build OK for gdb targets, but when compiling "arc.o" for
> gdbserver target, I ended up with something like:
> 
>   (paraphrasing)
>   Error: defs.h should not be included while building gdbserver.
>   (I am not sure if the error was indeed about "defs.h")
> 
> And removing/if-def-guarding that header file was opening other cans of
> worms. Eventually, I gave up and went for the current approach.

The constructor of arc_gdbarch_features shouldn't use a `bfd *`, since the code
in arch/ is used by gdbserver too, which doesn't use BFD.  I meant the constructor
should be just:

  arc_gdbarch_features (int reg_size, enum arc_isa isa)
    : reg_size (reg_size), isa (isa)
  {}

The code in GDB constructing an arc_gdbarch_features will use the BFD to determine
these two values, whereas the code in GDBserver will use something else (usually
looking at the current process' properties).

In fact, the constructor is optional, you could just build a arc_gdbarch_features
using aggregate initialization and return it from that function:

  arc_gdbarch_features features {reg_size, isa};

It doesn't really matter.  I just happen to prefer the constructor method, because
that makes it so you can't "forget" a field and it ensures it can never be in an
uninitialized state.

> No, I haven't built it with AddressSanitizer. Could you point me in the right
> direction how I can use it?

You already got the right information from Christian.

>>> +  /* Used by std::unordered_map to hash the feature sets.  The hash is
>>> +     calculated in the manner below:
>>> +     REG_SIZE |  ISA
>>> +      5-bits  | 4-bits  */
>>> +
>>> +  std::size_t hash () const noexcept
>>> +  {
>>> +    std::size_t val = ((reg_size & 0x1f) << 8 | (isa & 0xf) << 0);
>>> +    return val;
>>
>> I don't know much about hashing, but I don't think makes for a very good hash
>> function.  It outputs similar hashes for similar inputs, and does not use the
>> range of possible hash values uniformly.
> 
> Indeed it does not output hashes uniformly but I believe it is unique. The
> meaningful (and future proof) values for "reg_size" are {4, 8, 16} _bytes_.
> Hence, the "0x1f" mask should suffice. Having 15 versions for ISA should be
> enough as well. Having these conditions in mind, I don't think there is any
> collusion while hashing such inputs.

Well, I guess that depends on how the hash map implementation uses the hash value
to map into buckets.  Let's say that there are 16 buckets, and the hash table
implements decides which bucket a value goes in by looking at the last four bits.
And let's imagine that you insert 32 values, all with the same ISA value but with
32 different reg_sizes values (assuming that would make sense).  Then even though
the hash values are all different, they all end up in the same bucket.

Having a hash function that uniformly distributes the hash values makes that kind
of pathological case much more unlikely.

Anyway, I won't press more on that issue, since it's really not that important.
We're talking about just a few items, so it will never make a difference.  And as
Luis said on IRC, it could also use a vector it a linear search.

>> It would be more appropriate and typical to use std::hash on each member and
>> then combine the hashes.  Doing a quick search I found that Boost offers
>> something exactly for that called hash_combine:
>>
>> https://www.boost.org/doc/libs/1_55_0/doc/html/hash/combine.html
> 
> Thanks for this. I didn't know about such functionality. As you said
> though, we can't use it. Personally, I think it would be an overkill
> here. We can get away with a simple "shift" and "or". Please read my
> response above for my reasoning.
>>
>> Unfortunately, there is nothing similar in the standard library.  But
>>
>> A bit off-topic: intuitively, I would have thought that it would have been
>> sufficient to just add the hash values together.  Anyone knows why this
>> wouldn't be a good idea?
> 
> So far, possible values are:
> 
>   reg_size : {4, 8, 16}
>   ISA: {1, 2, ... 15}
> 
> A simple addition would produce the same result for these legally valid
> inputs:
> 
> reg_size=8, ISA=2   --->  hash = 10
> reg_size=4, ISA=6   --->  hash = 10

Sorry, I meant `std::hash (reg_size) + std::hash (isa)`, not `reg_size + isa`.

If `std::hash (reg_size)` produces a uniformly-distributed hash value, and
`std::hash (isa)` as well, then the output is surely uniformly-distributed,
no?

Simon


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring
  2020-07-16 13:28           ` Simon Marchi
@ 2020-07-22 13:36             ` Shahab Vahedi
  2020-07-22 13:49               ` Simon Marchi
  0 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-07-22 13:36 UTC (permalink / raw)
  To: Simon Marchi
  Cc: gdb-patches, Shahab Vahedi, Tom Tromey, Anton Kolesov, Francois Bedard

On Thu, Jul 16, 2020 at 09:28:50AM -0400, Simon Marchi wrote:
> On 2020-07-15 4:35 p.m., Shahab Vahedi wrote:
> When I search for `arc_gdbarch_features_init` in that patch I don't find anything...

You're correct. I have it in my local branch. The patch that uses it is going
to be submitted very soon. I hope you don't mind if it remains like this.
> The code in GDB constructing an arc_gdbarch_features will use the BFD to determine
> these two values, whereas the code in GDBserver will use something else (usually
> looking at the current process' properties).
> 
> In fact, the constructor is optional, you could just build a arc_gdbarch_features
> using aggregate initialization and return it from that function:
> 
>   arc_gdbarch_features features {reg_size, isa};
> 
> It doesn't really matter.  I just happen to prefer the constructor method, because
> that makes it so you can't "forget" a field and it ensures it can never be in an
> uninitialized state.

I see now. Actually, I have usecases to not initialize it immediately,
but in a few lines of code.
> > No, I haven't built it with AddressSanitizer. Could you point me in the right
> > direction how I can use it?
> 
> You already got the right information from Christian.

You were correct. There were some leaks. After adapting the code to use
"target_desc_up" on top of Andrew's fix [1], it is OK now.

[1]
https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=0e26741636bee18321d6743ecee6ae9effd35d1f
> Well, I guess that depends on how the hash map implementation uses the hash value
> to map into buckets.  Let's say that there are 16 buckets, and the hash table
> implements decides which bucket a value goes in by looking at the last four bits.
> And let's imagine that you insert 32 values, all with the same ISA value but with
> 32 different reg_sizes values (assuming that would make sense).  Then even though
> the hash values are all different, they all end up in the same bucket.
> 
> Having a hash function that uniformly distributes the hash values makes that kind
> of pathological case much more unlikely.

I didn't know about the internals (buckets). Thanks for the explanations.
However, if I understand your example correctly, the implementation
practically would use the hash values partially (only 8 bits). IMHO, I don't
expect it to happen.
> 
> Anyway, I won't press more on that issue, since it's really not that important.

I'll leave it as is then.
> We're talking about just a few items, so it will never make a difference.  And as
> Luis said on IRC, it could also use a vector it a linear search.

Now specially that the leakage is not an issue anymore, I will keep it as
a map.
> If `std::hash (reg_size)` produces a uniformly-distributed hash value, and
> `std::hash (isa)` as well, then the output is surely uniformly-distributed,
> no?

I'd say yes: f(x)+f(y) should be uniform if f() is uniform.

Cheers,
Shahab

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring
  2020-07-22 13:36             ` Shahab Vahedi
@ 2020-07-22 13:49               ` Simon Marchi
  2020-07-22 14:33                 ` Shahab Vahedi
  0 siblings, 1 reply; 86+ messages in thread
From: Simon Marchi @ 2020-07-22 13:49 UTC (permalink / raw)
  To: Shahab Vahedi
  Cc: gdb-patches, Shahab Vahedi, Tom Tromey, Anton Kolesov, Francois Bedard

On 2020-07-22 9:36 a.m., Shahab Vahedi wrote:
> On Thu, Jul 16, 2020 at 09:28:50AM -0400, Simon Marchi wrote:
>> On 2020-07-15 4:35 p.m., Shahab Vahedi wrote:
>> When I search for `arc_gdbarch_features_init` in that patch I don't find anything...
> 
> You're correct. I have it in my local branch. The patch that uses it is going
> to be submitted very soon. I hope you don't mind if it remains like this.

Let's just make it static in this patch, and make in non-static again in your future
patch, it's not a big change.

>> The code in GDB constructing an arc_gdbarch_features will use the BFD to determine
>> these two values, whereas the code in GDBserver will use something else (usually
>> looking at the current process' properties).
>>
>> In fact, the constructor is optional, you could just build a arc_gdbarch_features
>> using aggregate initialization and return it from that function:
>>
>>   arc_gdbarch_features features {reg_size, isa};
>>
>> It doesn't really matter.  I just happen to prefer the constructor method, because
>> that makes it so you can't "forget" a field and it ensures it can never be in an
>> uninitialized state.
> 
> I see now. Actually, I have usecases to not initialize it immediately,
> but in a few lines of code.

I'd be curious to see.  Because instead of declaring it immediately, you can keep
the fields separate until you initialize it:

  int reg_size;
  enum arc_isa isa;

  if (something)
    {
      reg_size = 8;
      isa = foo;
    }
  else
    {
      reg_size = 4;
      isa = bar;
    }

  arc_gdbarch_features features (reg_size, isa);

I think this is good, because the day you add a third axis to arc_gdbarch_features,
that code will not build and you'll be forced to updated it (you can't forget it).

Whereas with:

  arc_gdbarch_features features;

  if (something)
    {
      features.reg_size = 8;
      features.isa = foo;
    }
  else
    {
      features.reg_size = 4;
      features.isa = bar;
    }

It's possible to forget.

But maybe you have a different use case in mind?

Simon

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring
  2020-07-22 13:49               ` Simon Marchi
@ 2020-07-22 14:33                 ` Shahab Vahedi
  2020-07-22 14:54                   ` Simon Marchi
  0 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-07-22 14:33 UTC (permalink / raw)
  To: Simon Marchi
  Cc: gdb-patches, Shahab Vahedi, Tom Tromey, Anton Kolesov, Francois Bedard

On Wed, Jul 22, 2020 at 09:49:48AM -0400, Simon Marchi wrote:
> On 2020-07-22 9:36 a.m., Shahab Vahedi wrote:
> > On Thu, Jul 16, 2020 at 09:28:50AM -0400, Simon Marchi wrote:
> >> On 2020-07-15 4:35 p.m., Shahab Vahedi wrote:
> >> When I search for `arc_gdbarch_features_init` in that patch I don't find anything...
> > 
> > You're correct. I have it in my local branch. The patch that uses it is going
> > to be submitted very soon. I hope you don't mind if it remains like this.
> 
> Let's just make it static in this patch, and make in non-static again in your future
> patch, it's not a big change.

Will do.
> 
> >> The code in GDB constructing an arc_gdbarch_features will use the BFD to determine
> >> these two values, whereas the code in GDBserver will use something else (usually
> >> looking at the current process' properties).
> >>
> >> In fact, the constructor is optional, you could just build a arc_gdbarch_features
> >> using aggregate initialization and return it from that function:
> >>
> >>   arc_gdbarch_features features {reg_size, isa};
> >>
> >> It doesn't really matter.  I just happen to prefer the constructor method, because
> >> that makes it so you can't "forget" a field and it ensures it can never be in an
> >> uninitialized state.
> > 
> > I see now. Actually, I have usecases to not initialize it immediately,
> > but in a few lines of code.
> 
> I'd be curious to see.  Because instead of declaring it immediately, you can keep
> the fields separate until you initialize it:
> 
>   int reg_size;
>   enum arc_isa isa;
> 
>   if (something)
>     {
>       reg_size = 8;
>       isa = foo;
>     }
>   else
>     {
>       reg_size = 4;
>       isa = bar;
>     }
> 
>   arc_gdbarch_features features (reg_size, isa);
> 
> I think this is good, because the day you add a third axis to arc_gdbarch_features,
> that code will not build and you'll be forced to updated it (you can't forget it).
> 
> Whereas with:
> 
>   arc_gdbarch_features features;
> 
>   if (something)
>     {
>       features.reg_size = 8;
>       features.isa = foo;
>     }
>   else
>     {
>       features.reg_size = 4;
>       features.isa = bar;
>     }
> 
> It's possible to forget.
> 
> But maybe you have a different use case in mind?

These are the 2 usecases I have:

gdb/arc-tdep.c
--------------
static bool
arc_tdesc_init (struct gdbarch_info info, ...)
{
  const struct target_desc *tdesc_loc = info.target_desc;

  if (!tdesc_has_registers (tdesc_loc))
    {
      arc_gdbarch_features features;
      arc_gdbarch_features_init (features, info.abfd,
                                 info.bfd_arch_info->mach);
      tdesc_loc = arc_lookup_target_description (features);
    }
  ...
}

gdb/arc-linux-tdep.c
--------------------
static const struct target_desc *
arc_linux_core_read_description (struct gdbarch *gdbarch,
                                 struct target_ops *target,
                                 bfd *abfd)
{
  arc_gdbarch_features features;
  arc_gdbarch_features_init (features, abfd,
           gdbarch_bfd_arch_info (gdbarch)->mach);
  return arc_lookup_target_description (features);
}

While I totally understand your point, I don't want to unroll the
logic of "arc_gdbarch_features_init ()" to the same level that
"features" is declared. Ideally, I should have a constructor
with the same signature as "arc_gdbarch_features_init ()", but
that is not possible because compilation of gdbserver will go
awry when there is mention of ELF data in "gdb/arch/arc.h".

To have a complete overview, in a soon-to-be-submitted patch
you're going to see that "features" is initialized like:

gdbserver/linux-arc-low.cc
--------------------------
static const struct target_desc *
arc_linux_read_description (void)
{
  struct target_desc *tdesc;
  arc_gdbarch_features features = {4, ARC_ISA_NONE};
#ifdef __ARC700__
  features.isa = ARC_ISA_ARCV1;
#else
  features.isa = ARC_ISA_ARCV2;
#endif
  tdesc = arc_create_target_description (features);
  ...
}

Cheers,
Shahab

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring
  2020-07-22 14:33                 ` Shahab Vahedi
@ 2020-07-22 14:54                   ` Simon Marchi
  0 siblings, 0 replies; 86+ messages in thread
From: Simon Marchi @ 2020-07-22 14:54 UTC (permalink / raw)
  To: Shahab Vahedi
  Cc: gdb-patches, Shahab Vahedi, Tom Tromey, Anton Kolesov, Francois Bedard

On 2020-07-22 10:33 a.m., Shahab Vahedi wrote:
> On Wed, Jul 22, 2020 at 09:49:48AM -0400, Simon Marchi wrote:
>> On 2020-07-22 9:36 a.m., Shahab Vahedi wrote:
>>> On Thu, Jul 16, 2020 at 09:28:50AM -0400, Simon Marchi wrote:
>>>> On 2020-07-15 4:35 p.m., Shahab Vahedi wrote:
>>>> When I search for `arc_gdbarch_features_init` in that patch I don't find anything...
>>>
>>> You're correct. I have it in my local branch. The patch that uses it is going
>>> to be submitted very soon. I hope you don't mind if it remains like this.
>>
>> Let's just make it static in this patch, and make in non-static again in your future
>> patch, it's not a big change.
> 
> Will do.
>>
>>>> The code in GDB constructing an arc_gdbarch_features will use the BFD to determine
>>>> these two values, whereas the code in GDBserver will use something else (usually
>>>> looking at the current process' properties).
>>>>
>>>> In fact, the constructor is optional, you could just build a arc_gdbarch_features
>>>> using aggregate initialization and return it from that function:
>>>>
>>>>   arc_gdbarch_features features {reg_size, isa};
>>>>
>>>> It doesn't really matter.  I just happen to prefer the constructor method, because
>>>> that makes it so you can't "forget" a field and it ensures it can never be in an
>>>> uninitialized state.
>>>
>>> I see now. Actually, I have usecases to not initialize it immediately,
>>> but in a few lines of code.
>>
>> I'd be curious to see.  Because instead of declaring it immediately, you can keep
>> the fields separate until you initialize it:
>>
>>   int reg_size;
>>   enum arc_isa isa;
>>
>>   if (something)
>>     {
>>       reg_size = 8;
>>       isa = foo;
>>     }
>>   else
>>     {
>>       reg_size = 4;
>>       isa = bar;
>>     }
>>
>>   arc_gdbarch_features features (reg_size, isa);
>>
>> I think this is good, because the day you add a third axis to arc_gdbarch_features,
>> that code will not build and you'll be forced to updated it (you can't forget it).
>>
>> Whereas with:
>>
>>   arc_gdbarch_features features;
>>
>>   if (something)
>>     {
>>       features.reg_size = 8;
>>       features.isa = foo;
>>     }
>>   else
>>     {
>>       features.reg_size = 4;
>>       features.isa = bar;
>>     }
>>
>> It's possible to forget.
>>
>> But maybe you have a different use case in mind?
> 
> These are the 2 usecases I have:
> 
> gdb/arc-tdep.c
> --------------
> static bool
> arc_tdesc_init (struct gdbarch_info info, ...)
> {
>   const struct target_desc *tdesc_loc = info.target_desc;
> 
>   if (!tdesc_has_registers (tdesc_loc))
>     {
>       arc_gdbarch_features features;
>       arc_gdbarch_features_init (features, info.abfd,
>                                  info.bfd_arch_info->mach);
>       tdesc_loc = arc_lookup_target_description (features);
>     }
>   ...
> }
> 
> gdb/arc-linux-tdep.c
> --------------------
> static const struct target_desc *
> arc_linux_core_read_description (struct gdbarch *gdbarch,
>                                  struct target_ops *target,
>                                  bfd *abfd)
> {
>   arc_gdbarch_features features;
>   arc_gdbarch_features_init (features, abfd,
>            gdbarch_bfd_arch_info (gdbarch)->mach);
>   return arc_lookup_target_description (features);
> }

I mentioned earlier that arc_gdbarch_features_init should return a
`arc_gdbarch_features` by value, that would avoid this problem (and
be cleaner, IMO).

> While I totally understand your point, I don't want to unroll the
> logic of "arc_gdbarch_features_init ()" to the same level that
> "features" is declared. Ideally, I should have a constructor
> with the same signature as "arc_gdbarch_features_init ()", but
> that is not possible because compilation of gdbserver will go
> awry when there is mention of ELF data in "gdb/arch/arc.h".
> 
> To have a complete overview, in a soon-to-be-submitted patch
> you're going to see that "features" is initialized like:
> 
> gdbserver/linux-arc-low.cc
> --------------------------
> static const struct target_desc *
> arc_linux_read_description (void)
> {
>   struct target_desc *tdesc;
>   arc_gdbarch_features features = {4, ARC_ISA_NONE};
> #ifdef __ARC700__
>   features.isa = ARC_ISA_ARCV1;
> #else
>   features.isa = ARC_ISA_ARCV2;
> #endif
>   tdesc = arc_create_target_description (features);
>   ...
> }

You can easily apply the suggestion from my previous message here.

Simon


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v4 0/3] arc: Add GNU/Linux support
  2020-07-13 15:45   ` [PATCH v3 0/3] " Shahab Vahedi
                       ` (2 preceding siblings ...)
  2020-07-13 15:45     ` [PATCH v3 3/3] arc: Add GNU/Linux support for ARC Shahab Vahedi
@ 2020-07-23 19:35     ` Shahab Vahedi
  2020-07-23 19:35       ` [PATCH v4 1/3] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
                         ` (3 more replies)
  3 siblings, 4 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-07-23 19:35 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

This is a series of changes to enable debugging ARC targets that are
running on a native ARC GNU/Linux system.  Since this heavily relies
on XML target descriptions provided for different targets, that piece
of code has been refactored to accommodate flexible register support.

After this series, there will come patches that add support for
native ARC gdb/gdbserver.

v4: Latest changes per remarks of Simon [1]
 arc-tdep.c
  - Surround "=" in 2 assignments with space.
  - Put the return type of "mach_type_to_arc_isa ()" on the first line.
  - Remove "inline" from "mach_type_to_arc_isa ()".
  - Add space between the "if" conditions for readability.
  - Use "featues.isa" instead of "features.reg_size" in one occurrence.
  - Make "arc_gdbarch_features_init" static
  - Rename "arc_gdbarch_features_init" to "arc_gdbarch_features_create".
  - Adapt "arc_gdbarch_features_create" to act as a constructor.
 arch/arc.c
  - Add a constructor for "arc_gdbarch_features".
  - Get rid of "ARC_ISA_NONE" now that there is a constructor.
 arch/arc.c
  - Use simple assignments (instead of append) for "architecture".
  - Use "string_sprintf ()".
  - Use "target_desc_up" in "arc_tdesc_cache" to avoid memory leakage.
 arc-linux-tdep.c
  - Two occurrences: compare "resolver.minsym" against "nullptr".
  

[1] [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring
https://sourceware.org/pipermail/gdb-patches/2020-July/170427.html

v3: Changes after Simon's remarks:
The XML files have reduced to minimal comprehensible set.
The code is adjusted to work with new reg sets and be platform agnostic.

v2: Changes after Tom's remarks:
 arc-tdep.c
  - arc_tdesc_init(): Use "ARC_{R58,R59}_REGNUM" to index "core_regs[]".
  - arc_gdbarch_init(): Use "xfree ()" instead of "XDELETE ()"
  - arc_gdbarch_init(): return "nullptr" instead of "NULL".
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 arc-linux-tdep.c
  - Use true/false instead of TRUE/FALSE.
  - arc_linux_sw_breakpoint_from_kind (): Break long lines into two.
  - arc_linux_sw_breakpoint_from_kind (): Remove starting blank line.
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 gdb/configure.tgt
  - arc*-*-linux*): Remove "build_gdbserver=yes".

Anton Kolesov (1):
  arc: Add GNU/Linux support for ARC

Shahab Vahedi (2):
  arc: Add ARCv2 XML target along with refactoring
  arc: Add hardware loop detection

 gdb/Makefile.in                               |   1 +
 gdb/arc-linux-tdep.c                          | 283 ++++++++
 gdb/arc-tdep.c                                | 654 +++++++++++-------
 gdb/arc-tdep.h                                |  27 +-
 gdb/arch/arc.c                                | 108 ++-
 gdb/arch/arc.h                                |  79 ++-
 gdb/configure.tgt                             |   5 +
 gdb/doc/gdb.texinfo                           |   3 +-
 gdb/features/Makefile                         |   8 +-
 .../arc/{aux-arcompact.c => v1-aux.c}         |   9 +-
 .../arc/{aux-arcompact.xml => v1-aux.xml}     |   7 +-
 .../arc/{core-arcompact.c => v1-core.c}       |   8 +-
 .../arc/{core-arcompact.xml => v1-core.xml}   |   4 +-
 gdb/features/arc/{aux-v2.c => v2-aux.c}       |   9 +-
 gdb/features/arc/{aux-v2.xml => v2-aux.xml}   |   5 +-
 gdb/features/arc/{core-v2.c => v2-core.c}     |   7 +-
 gdb/features/arc/{core-v2.xml => v2-core.xml} |   7 +-
 17 files changed, 906 insertions(+), 318 deletions(-)
 create mode 100644 gdb/arc-linux-tdep.c
 rename gdb/features/arc/{aux-arcompact.c => v1-aux.c} (73%)
 rename gdb/features/arc/{aux-arcompact.xml => v1-aux.xml} (80%)
 rename gdb/features/arc/{core-arcompact.c => v1-core.c} (87%)
 rename gdb/features/arc/{core-arcompact.xml => v1-core.xml} (92%)
 rename gdb/features/arc/{aux-v2.c => v2-aux.c} (76%)
 rename gdb/features/arc/{aux-v2.xml => v2-aux.xml} (86%)
 rename gdb/features/arc/{core-v2.c => v2-core.c} (91%)
 rename gdb/features/arc/{core-v2.xml => v2-core.xml} (90%)

-- 
2.27.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v4 1/3] arc: Add ARCv2 XML target along with refactoring
  2020-07-23 19:35     ` [PATCH v4 0/3] arc: Add GNU/Linux support Shahab Vahedi
@ 2020-07-23 19:35       ` Shahab Vahedi
  2020-07-30 23:34         ` Simon Marchi
  2020-07-23 19:35       ` [PATCH v4 2/3] arc: Add hardware loop detection Shahab Vahedi
                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-07-23 19:35 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

A few changes have been made to make the register support simpler,
more flexible and extendible.  The trigger for most of these changes
are the remarks [1] made earlier for v2 of this patch.  The noticeable
improvements are:

- The arc XML target features are placed under gdb/features/arc
- There are two cores (based on ISA) and one auxiliary feature:
  v1-core: ARC600, ARC601, ARC700
  v2-core: ARC EM, ARC HS
  aux: common in both
- The XML target features represent a minimalistic sane set of
  registers irrespective of application (baremetal or linux).
- A concept of "feature" class has been introduced in the code.
  The "feature" object is constructed from BFD and GDBARCH data.
  It contains necessary information (ISA and register size) to
  determine which XML target feature to use.
- A new structure (ARC_REGISTER_FEATURE) is added that allows
  providing index, names, and the necessity of registers. This
  simplifies the sanity checks and future extendibility.

The last two points were inspired from RiscV port.

[1]
https://sourceware.org/pipermail/gdb-patches/2020-May/168511.html

gdb/ChangeLog:
2020-07-22  Shahab Vahedi  <shahab@synopsys.com>

	* arch/arc.h
	  (arc_gdbarch_features): New class to stir the selection of target XML.
	  (arc_create_target_description): Use FEATURES to choose XML target.
	  (arc_lookup_target_description): Use arc_create_target_description
	  to create _new_ target descriptions or return the already created
	  ones if the FEATURES is the same.
	* arch/arc.c: Implementation of prototypes described above.
	* gdb/arc-tdep.h (arc_regnum enum): Add more registers.
	  (arc_gdbarch_features_init): Initialize the FEATURES struct.
	* arc-tdep.c (*_feature_name): Make feature names consistent.
	  (arc_register_feature): A new struct to hold information about
	  registers of a particular target/feature.
	  (arc_check_tdesc_feature): Check if XML provides registers in
	  compliance with ARC_REGISTER_FEATURE structs.
	  (arc_update_acc_reg_names): Add aliases for r58 and r59.
	  (determine_*_reg_feature_set): Which feature name to look for.
	  (arc_gdbarch_features_init): Given MACH and ABFD, initialize FEATURES.
	  (mach_type_to_arc_isa): Convert from a set of binutils machine types
	  to expected ISA enums to be used in arc_gdbarch_features structs.
	* features/Makefile (FEATURE_XMLFILES): Add new files.
	* gdb/features/arc/v1-aux.c: New file.
	* gdb/features/arc/v1-aux.xml: Likewise.
	* gdb/features/arc/v1-core.c: Likewise.
	* gdb/features/arc/v1-core.xml: Likewise.
	* gdb/features/arc/v2-aux.c: Likewise.
	* gdb/features/arc/v2-aux.xml: Likewise.
	* gdb/features/arc/v2-core.c: Likewise.
	* gdb/features/arc/v2-core.xml: Likewise.
---
 gdb/arc-tdep.c                                | 612 +++++++++++-------
 gdb/arc-tdep.h                                |  18 +-
 gdb/arch/arc.c                                | 108 +++-
 gdb/arch/arc.h                                |  79 ++-
 gdb/features/Makefile                         |   8 +-
 .../arc/{aux-arcompact.c => v1-aux.c}         |   9 +-
 .../arc/{aux-arcompact.xml => v1-aux.xml}     |   7 +-
 .../arc/{core-arcompact.c => v1-core.c}       |   8 +-
 .../arc/{core-arcompact.xml => v1-core.xml}   |   4 +-
 gdb/features/arc/{aux-v2.c => v2-aux.c}       |   9 +-
 gdb/features/arc/{aux-v2.xml => v2-aux.xml}   |   5 +-
 gdb/features/arc/{core-v2.c => v2-core.c}     |   7 +-
 gdb/features/arc/{core-v2.xml => v2-core.xml} |   7 +-
 13 files changed, 570 insertions(+), 311 deletions(-)
 rename gdb/features/arc/{aux-arcompact.c => v1-aux.c} (73%)
 rename gdb/features/arc/{aux-arcompact.xml => v1-aux.xml} (80%)
 rename gdb/features/arc/{core-arcompact.c => v1-core.c} (87%)
 rename gdb/features/arc/{core-arcompact.xml => v1-core.xml} (92%)
 rename gdb/features/arc/{aux-v2.c => v2-aux.c} (76%)
 rename gdb/features/arc/{aux-v2.xml => v2-aux.xml} (86%)
 rename gdb/features/arc/{core-v2.c => v2-core.c} (91%)
 rename gdb/features/arc/{core-v2.xml => v2-core.xml} (90%)

diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 7e6d29c334b..0c7e045e54b 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -21,6 +21,7 @@
 /* GDB header files.  */
 #include "defs.h"
 #include "arch-utils.h"
+#include "elf-bfd.h"
 #include "disasm.h"
 #include "dwarf2/frame.h"
 #include "frame-base.h"
@@ -41,6 +42,7 @@
 
 /* Standard headers.  */
 #include <algorithm>
+#include <sstream>
 
 /* The frame unwind cache for ARC.  */
 
@@ -91,63 +93,201 @@ int arc_debug;
 
 static struct cmd_list_element *maintenance_print_arc_list = NULL;
 
-/* XML target description features.  */
-
-static const char core_v2_feature_name[] = "org.gnu.gdb.arc.core.v2";
-static const char
-  core_reduced_v2_feature_name[] = "org.gnu.gdb.arc.core-reduced.v2";
-static const char
-  core_arcompact_feature_name[] = "org.gnu.gdb.arc.core.arcompact";
-static const char aux_minimal_feature_name[] = "org.gnu.gdb.arc.aux-minimal";
-
-/* XML target description known registers.  */
-
-static const char *const core_v2_register_names[] = {
-  "r0", "r1", "r2", "r3",
-  "r4", "r5", "r6", "r7",
-  "r8", "r9", "r10", "r11",
-  "r12", "r13", "r14", "r15",
-  "r16", "r17", "r18", "r19",
-  "r20", "r21", "r22", "r23",
-  "r24", "r25", "gp", "fp",
-  "sp", "ilink", "r30", "blink",
-  "r32", "r33", "r34", "r35",
-  "r36", "r37", "r38", "r39",
-  "r40", "r41", "r42", "r43",
-  "r44", "r45", "r46", "r47",
-  "r48", "r49", "r50", "r51",
-  "r52", "r53", "r54", "r55",
-  "r56", "r57", "accl", "acch",
-  "lp_count", "reserved", "limm", "pcl",
+/* A set of registers that we expect to find in a tdesc_feature.  These
+   are used in ARC_TDESC_INIT when processing the target description.  */
+
+struct arc_register_feature
+{
+  /* Information for a single register.  */
+  struct register_info
+  {
+    /* The GDB register number for this register.  */
+    int regnum;
+
+    /* List of names for this register.  The first name in this list is the
+       preferred name, the name GDB will use when describing this register.  */
+    std::vector<const char *> names;
+
+    /* When true, this register must be present in this feature set.  */
+    bool required_p;
+  };
+
+  /* The name for this feature.  This is the name used to find this feature
+     within the target description.  */
+  const char *name;
+
+  /* List of all the registers that we expect to encounter in this register
+     set.  */
+  std::vector<struct register_info> registers;
 };
 
-static const char *const aux_minimal_register_names[] = {
-  "pc", "status32",
+static const char *ARC_CORE_FEATURE_NAME = "org.gnu.gdb.arc.core";
+static const char *ARC_AUX_FEATURE_NAME = "org.gnu.gdb.arc.aux";
+
+/* ARCv1 (ARC600, ARC601, ARC700) general core registers feature set.
+   See also arc_update_acc_reg_names() for "accl/acch" names.  */
+
+static struct arc_register_feature arc_v1_core_reg_feature =
+{
+  ARC_CORE_FEATURE_NAME,
+  {
+    { ARC_R0_REGNUM + 0, { "r0" }, true },
+    { ARC_R0_REGNUM + 1, { "r1" }, true },
+    { ARC_R0_REGNUM + 2, { "r2" }, true },
+    { ARC_R0_REGNUM + 3, { "r3" }, true },
+    { ARC_R0_REGNUM + 4, { "r4" }, false },
+    { ARC_R0_REGNUM + 5, { "r5" }, false },
+    { ARC_R0_REGNUM + 6, { "r6" }, false },
+    { ARC_R0_REGNUM + 7, { "r7" }, false },
+    { ARC_R0_REGNUM + 8, { "r8" }, false },
+    { ARC_R0_REGNUM + 9, { "r9" }, false },
+    { ARC_R0_REGNUM + 10, { "r10" }, true },
+    { ARC_R0_REGNUM + 11, { "r11" }, true },
+    { ARC_R0_REGNUM + 12, { "r12" }, true },
+    { ARC_R0_REGNUM + 13, { "r13" }, true },
+    { ARC_R0_REGNUM + 14, { "r14" }, true },
+    { ARC_R0_REGNUM + 15, { "r15" }, true },
+    { ARC_R0_REGNUM + 16, { "r16" }, false },
+    { ARC_R0_REGNUM + 17, { "r17" }, false },
+    { ARC_R0_REGNUM + 18, { "r18" }, false },
+    { ARC_R0_REGNUM + 19, { "r19" }, false },
+    { ARC_R0_REGNUM + 20, { "r20" }, false },
+    { ARC_R0_REGNUM + 21, { "r21" }, false },
+    { ARC_R0_REGNUM + 22, { "r22" }, false },
+    { ARC_R0_REGNUM + 23, { "r23" }, false },
+    { ARC_R0_REGNUM + 24, { "r24" }, false },
+    { ARC_R0_REGNUM + 25, { "r25" }, false },
+    { ARC_R0_REGNUM + 26, { "gp" }, true },
+    { ARC_R0_REGNUM + 27, { "fp" }, true },
+    { ARC_R0_REGNUM + 28, { "sp" }, true },
+    { ARC_R0_REGNUM + 29, { "ilink1" }, false },
+    { ARC_R0_REGNUM + 30, { "ilink2" }, false },
+    { ARC_R0_REGNUM + 31, { "blink" }, true },
+    { ARC_R0_REGNUM + 32, { "r32" }, false },
+    { ARC_R0_REGNUM + 33, { "r33" }, false },
+    { ARC_R0_REGNUM + 34, { "r34" }, false },
+    { ARC_R0_REGNUM + 35, { "r35" }, false },
+    { ARC_R0_REGNUM + 36, { "r36" }, false },
+    { ARC_R0_REGNUM + 37, { "r37" }, false },
+    { ARC_R0_REGNUM + 38, { "r38" }, false },
+    { ARC_R0_REGNUM + 39, { "r39" }, false },
+    { ARC_R0_REGNUM + 40, { "r40" }, false },
+    { ARC_R0_REGNUM + 41, { "r41" }, false },
+    { ARC_R0_REGNUM + 42, { "r42" }, false },
+    { ARC_R0_REGNUM + 43, { "r43" }, false },
+    { ARC_R0_REGNUM + 44, { "r44" }, false },
+    { ARC_R0_REGNUM + 45, { "r45" }, false },
+    { ARC_R0_REGNUM + 46, { "r46" }, false },
+    { ARC_R0_REGNUM + 47, { "r47" }, false },
+    { ARC_R0_REGNUM + 48, { "r48" }, false },
+    { ARC_R0_REGNUM + 49, { "r49" }, false },
+    { ARC_R0_REGNUM + 50, { "r50" }, false },
+    { ARC_R0_REGNUM + 51, { "r51" }, false },
+    { ARC_R0_REGNUM + 52, { "r52" }, false },
+    { ARC_R0_REGNUM + 53, { "r53" }, false },
+    { ARC_R0_REGNUM + 54, { "r54" }, false },
+    { ARC_R0_REGNUM + 55, { "r55" }, false },
+    { ARC_R0_REGNUM + 56, { "r56" }, false },
+    { ARC_R0_REGNUM + 57, { "r57" }, false },
+    { ARC_R0_REGNUM + 58, { "r58", "accl" }, false },
+    { ARC_R0_REGNUM + 59, { "r59", "acch" }, false },
+    { ARC_R0_REGNUM + 60, { "lp_count" }, false },
+    { ARC_R0_REGNUM + 61, { "reserved" }, false },
+    { ARC_R0_REGNUM + 62, { "limm" }, false },
+    { ARC_R0_REGNUM + 63, { "pcl" }, true }
+  }
 };
 
-static const char *const core_arcompact_register_names[] = {
-  "r0", "r1", "r2", "r3",
-  "r4", "r5", "r6", "r7",
-  "r8", "r9", "r10", "r11",
-  "r12", "r13", "r14", "r15",
-  "r16", "r17", "r18", "r19",
-  "r20", "r21", "r22", "r23",
-  "r24", "r25", "gp", "fp",
-  "sp", "ilink1", "ilink2", "blink",
-  "r32", "r33", "r34", "r35",
-  "r36", "r37", "r38", "r39",
-  "r40", "r41", "r42", "r43",
-  "r44", "r45", "r46", "r47",
-  "r48", "r49", "r50", "r51",
-  "r52", "r53", "r54", "r55",
-  "r56", "r57", "r58", "r59",
-  "lp_count", "reserved", "limm", "pcl",
+/* ARCv2 (ARCHS) general core registers feature set.  See also
+   arc_update_acc_reg_names() for "accl/acch" names.  */
+
+static struct arc_register_feature arc_v2_core_reg_feature =
+{
+  ARC_CORE_FEATURE_NAME,
+  {
+    { ARC_R0_REGNUM + 0, { "r0" }, true },
+    { ARC_R0_REGNUM + 1, { "r1" }, true },
+    { ARC_R0_REGNUM + 2, { "r2" }, true },
+    { ARC_R0_REGNUM + 3, { "r3" }, true },
+    { ARC_R0_REGNUM + 4, { "r4" }, false },
+    { ARC_R0_REGNUM + 5, { "r5" }, false },
+    { ARC_R0_REGNUM + 6, { "r6" }, false },
+    { ARC_R0_REGNUM + 7, { "r7" }, false },
+    { ARC_R0_REGNUM + 8, { "r8" }, false },
+    { ARC_R0_REGNUM + 9, { "r9" }, false },
+    { ARC_R0_REGNUM + 10, { "r10" }, true },
+    { ARC_R0_REGNUM + 11, { "r11" }, true },
+    { ARC_R0_REGNUM + 12, { "r12" }, true },
+    { ARC_R0_REGNUM + 13, { "r13" }, true },
+    { ARC_R0_REGNUM + 14, { "r14" }, true },
+    { ARC_R0_REGNUM + 15, { "r15" }, true },
+    { ARC_R0_REGNUM + 16, { "r16" }, false },
+    { ARC_R0_REGNUM + 17, { "r17" }, false },
+    { ARC_R0_REGNUM + 18, { "r18" }, false },
+    { ARC_R0_REGNUM + 19, { "r19" }, false },
+    { ARC_R0_REGNUM + 20, { "r20" }, false },
+    { ARC_R0_REGNUM + 21, { "r21" }, false },
+    { ARC_R0_REGNUM + 22, { "r22" }, false },
+    { ARC_R0_REGNUM + 23, { "r23" }, false },
+    { ARC_R0_REGNUM + 24, { "r24" }, false },
+    { ARC_R0_REGNUM + 25, { "r25" }, false },
+    { ARC_R0_REGNUM + 26, { "gp" }, true },
+    { ARC_R0_REGNUM + 27, { "fp" }, true },
+    { ARC_R0_REGNUM + 28, { "sp" }, true },
+    { ARC_R0_REGNUM + 29, { "ilink" }, false },
+    { ARC_R0_REGNUM + 30, { "r30" }, true },
+    { ARC_R0_REGNUM + 31, { "blink" }, true },
+    { ARC_R0_REGNUM + 32, { "r32" }, false },
+    { ARC_R0_REGNUM + 33, { "r33" }, false },
+    { ARC_R0_REGNUM + 34, { "r34" }, false },
+    { ARC_R0_REGNUM + 35, { "r35" }, false },
+    { ARC_R0_REGNUM + 36, { "r36" }, false },
+    { ARC_R0_REGNUM + 37, { "r37" }, false },
+    { ARC_R0_REGNUM + 38, { "r38" }, false },
+    { ARC_R0_REGNUM + 39, { "r39" }, false },
+    { ARC_R0_REGNUM + 40, { "r40" }, false },
+    { ARC_R0_REGNUM + 41, { "r41" }, false },
+    { ARC_R0_REGNUM + 42, { "r42" }, false },
+    { ARC_R0_REGNUM + 43, { "r43" }, false },
+    { ARC_R0_REGNUM + 44, { "r44" }, false },
+    { ARC_R0_REGNUM + 45, { "r45" }, false },
+    { ARC_R0_REGNUM + 46, { "r46" }, false },
+    { ARC_R0_REGNUM + 47, { "r47" }, false },
+    { ARC_R0_REGNUM + 48, { "r48" }, false },
+    { ARC_R0_REGNUM + 49, { "r49" }, false },
+    { ARC_R0_REGNUM + 50, { "r50" }, false },
+    { ARC_R0_REGNUM + 51, { "r51" }, false },
+    { ARC_R0_REGNUM + 52, { "r52" }, false },
+    { ARC_R0_REGNUM + 53, { "r53" }, false },
+    { ARC_R0_REGNUM + 54, { "r54" }, false },
+    { ARC_R0_REGNUM + 55, { "r55" }, false },
+    { ARC_R0_REGNUM + 56, { "r56" }, false },
+    { ARC_R0_REGNUM + 57, { "r57" }, false },
+    { ARC_R0_REGNUM + 58, { "r58", "accl" }, false },
+    { ARC_R0_REGNUM + 59, { "r59", "acch" }, false },
+    { ARC_R0_REGNUM + 60, { "lp_count" }, false },
+    { ARC_R0_REGNUM + 61, { "reserved" }, false },
+    { ARC_R0_REGNUM + 62, { "limm" }, false },
+    { ARC_R0_REGNUM + 63, { "pcl" }, true }
+  }
 };
 
-static char *arc_disassembler_options = NULL;
+/* The common auxiliary registers feature set.  The REGNUM field
+   must match the ARC_REGNUM enum in arc-tdep.h.  */
 
-/* Possible arc target descriptors.  */
-static struct target_desc *tdesc_arc_list[ARC_SYS_TYPE_NUM];
+static const struct arc_register_feature arc_common_aux_reg_feature =
+{
+  ARC_AUX_FEATURE_NAME,
+  {
+    { ARC_FIRST_AUX_REGNUM + 0, { "pc" }, true },
+    { ARC_FIRST_AUX_REGNUM + 1, { "status32" }, true },
+    { ARC_FIRST_AUX_REGNUM + 2, { "lp_start" }, false },
+    { ARC_FIRST_AUX_REGNUM + 3, { "lp_end" }, false },
+    { ARC_FIRST_AUX_REGNUM + 4, { "bta" }, false }
+  }
+};
+
+static char *arc_disassembler_options = NULL;
 
 /* Functions are sorted in the order as they are used in the
    _initialize_arc_tdep (), which uses the same order as gdbarch.h.  Static
@@ -1717,192 +1857,226 @@ static const struct frame_base arc_normal_base = {
   arc_frame_base_address
 };
 
-/* Initialize target description for the ARC.
-
-   Returns TRUE if input tdesc was valid and in this case it will assign TDESC
-   and TDESC_DATA output parameters.  */
-
-static bool
-arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
-		struct tdesc_arch_data **tdesc_data)
+static enum arc_isa
+mach_type_to_arc_isa (const unsigned long mach)
 {
-  if (arc_debug)
-    debug_printf ("arc: Target description initialization.\n");
-
-  const struct target_desc *tdesc_loc = info.target_desc;
+  switch (mach)
+    {
+    case bfd_mach_arc_arc600:
+    case bfd_mach_arc_arc601:
+    case bfd_mach_arc_arc700:
+      return ARC_ISA_ARCV1;
+      break;
+    case bfd_mach_arc_arcv2:
+      return ARC_ISA_ARCV2;
+      break;
+    default:
+	internal_error (__FILE__, __LINE__,
+			_("unknown machine id %lu"), mach);
+    }
+}
 
-  /* Depending on whether this is ARCompact or ARCv2 we will assign
-     different default registers sets (which will differ in exactly two core
-     registers).  GDB will also refuse to accept register feature from invalid
-     ISA - v2 features can be used only with v2 ARChitecture.  We read
-     bfd_arch_info, which looks like to be a safe bet here, as it looks like it
-     is always initialized even when we don't pass any elf file to GDB at all
-     (it uses default arch in this case).  Also GDB will call this function
-     multiple times, and if XML target description file contains architecture
-     specifications, then GDB will set this architecture to info.bfd_arch_info,
-     overriding value from ELF file if they are different.  That means that,
-     where matters, this value is always our best guess on what CPU we are
-     debugging.  It has been noted that architecture specified in tdesc file
-     has higher precedence over ELF and even "set architecture" - that is,
-     using "set architecture" command will have no effect when tdesc has "arch"
-     tag.  */
-  /* Cannot use arc_mach_is_arcv2 (), because gdbarch is not created yet.  */
-  const int is_arcv2 = (info.bfd_arch_info->mach == bfd_mach_arc_arcv2);
-  bool is_reduced_rf;
-  const char *const *core_regs;
-  const char *core_feature_name;
+/* Common construction code for ARC_GDBARCH_FEATURES struct.  If there
+   is no ABFD, then a FEATURE with default values is returned.  */
 
-  /* If target doesn't provide a description, use the default ones.  */
-  if (!tdesc_has_registers (tdesc_loc))
+static arc_gdbarch_features
+arc_gdbarch_features_create (const bfd *abfd, const unsigned long mach)
+{
+  /* Use 4 as a fallback value.  */
+  int reg_size = 4;
+
+  /* Try to guess the features parameters by looking at the binary to be
+     executed.  If the user is providing a binary that does not match the
+     target, then tough luck.  This is the last effort to makes sense of
+     what's going on.  */
+  if (abfd != NULL && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
     {
-      if (is_arcv2)
-	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCV2);
+      unsigned char eclass = elf_elfheader (abfd)->e_ident[EI_CLASS];
+
+      if (eclass == ELFCLASS32)
+	reg_size = 4;
+      else if (eclass == ELFCLASS64)
+	reg_size = 8;
       else
-	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCOMPACT);
+	internal_error (__FILE__, __LINE__,
+			_("unknown ELF header class %d"), eclass);
     }
-  else
+
+  /* MACH from a bfd_arch_info struct is used here.  It should be a safe
+     bet, as it looks like the struct is always initialized even when we
+     don't pass any elf file to GDB at all (it uses default arch in that
+     case).  */
+  arc_isa isa = mach_type_to_arc_isa (mach);
+
+  return arc_gdbarch_features (reg_size, isa);
+}
+
+/* Based on the MACH value, determines which core register features set
+   must be used.  Possible outcomes:
+   {nullptr, &arc_v1_core_reg_feature, &arc_v2_core_reg_feature}  */
+
+static arc_register_feature *
+determine_core_reg_feature_set (const unsigned long mach)
+{
+  switch (mach_type_to_arc_isa (mach))
     {
-      if (arc_debug)
-	debug_printf ("arc: Using provided register set.\n");
+    case ARC_ISA_ARCV1:
+      return &arc_v1_core_reg_feature;
+    case ARC_ISA_ARCV2:
+      return &arc_v2_core_reg_feature;
+    default:
+      return nullptr;
     }
-  gdb_assert (tdesc_loc != NULL);
-
-  /* Now we can search for base registers.  Core registers can be either full
-     or reduced.  Summary:
-
-     - core.v2 + aux-minimal
-     - core-reduced.v2 + aux-minimal
-     - core.arcompact + aux-minimal
-
-     NB: It is entirely feasible to have ARCompact with reduced core regs, but
-     we ignore that because GCC doesn't support that and at the same time
-     ARCompact is considered obsolete, so there is not much reason to support
-     that.  */
-  const struct tdesc_feature *feature
-    = tdesc_find_feature (tdesc_loc, core_v2_feature_name);
-  if (feature != NULL)
-    {
-      /* Confirm that register and architecture match, to prevent accidents in
-	 some situations.  This code will trigger an error if:
+}
 
-	 1. XML tdesc doesn't specify arch explicitly, registers are for arch
-	 X, but ELF specifies arch Y.
+/* At the moment, there is only 1 auxiliary register features set.
+   This is a place holder for future extendability.  */
 
-	 2. XML tdesc specifies arch X, but contains registers for arch Y.
+static const arc_register_feature *
+determine_aux_reg_feature_set ()
+{
+  return &arc_common_aux_reg_feature;
+}
 
-	 It will not protect from case where XML or ELF specify arch X,
-	 registers are for the same arch X, but the real target is arch Y.  To
-	 detect this case we need to check IDENTITY register.  */
-      if (!is_arcv2)
-	{
-	  arc_print (_("Error: ARC v2 target description supplied for "
-		       "non-ARCv2 target.\n"));
-	  return false;
-	}
+/* Update accumulator register names (ACCH/ACCL) for r58 and r59 in the
+   register sets.  The endianness determines the assignment:
 
-      is_reduced_rf = false;
-      core_feature_name = core_v2_feature_name;
-      core_regs = core_v2_register_names;
-    }
-  else
+         ,------.------.
+         |  LE  |  BE  |
+   ,-----|------+------|
+   | r58 | accl | acch |
+   | r59 | acch | accl |
+   `-----^------^------'  */
+
+static void
+arc_update_acc_reg_names (const int byte_order)
+{
+  const char *r58_alias
+    = byte_order == BFD_ENDIAN_LITTLE ? "accl" : "acch";
+  const char *r59_alias
+    = byte_order == BFD_ENDIAN_LITTLE ? "acch" : "accl";
+
+  /* Subscript 1 must be OK because those registers have 2 names.  */
+  arc_v1_core_reg_feature.registers[ARC_R58_REGNUM].names[1] = r58_alias;
+  arc_v1_core_reg_feature.registers[ARC_R59_REGNUM].names[1] = r59_alias;
+  arc_v2_core_reg_feature.registers[ARC_R58_REGNUM].names[1] = r58_alias;
+  arc_v2_core_reg_feature.registers[ARC_R59_REGNUM].names[1] = r59_alias;
+}
+
+/* Go through all the registers in REG_SET and check if they exist
+   in FEATURE.  The TDESC_DATA is updated with the register number
+   in REG_SET if it is found in the feature.  If a required register
+   is not found, this function returns false.  */
+
+static bool
+arc_check_tdesc_feature (struct tdesc_arch_data *tdesc_data,
+			 const struct tdesc_feature *feature,
+			 const struct arc_register_feature *reg_set)
+{
+  for (const auto &reg : reg_set->registers)
     {
-      feature = tdesc_find_feature (tdesc_loc, core_reduced_v2_feature_name);
-      if (feature != NULL)
+      bool found = false;
+
+      for (const char *name : reg.names)
 	{
-	  if (!is_arcv2)
-	    {
-	      arc_print (_("Error: ARC v2 target description supplied for "
-			   "non-ARCv2 target.\n"));
-	      return false;
-	    }
+	  found =
+	    tdesc_numbered_register (feature, tdesc_data, reg.regnum, name);
 
-	  is_reduced_rf = true;
-	  core_feature_name = core_reduced_v2_feature_name;
-	  core_regs = core_v2_register_names;
+	  if (found)
+	    break;
 	}
-      else
+
+      if (!found && reg.required_p)
 	{
-	  feature = tdesc_find_feature (tdesc_loc,
-					core_arcompact_feature_name);
-	  if (feature != NULL)
-	    {
-	      if (is_arcv2)
-		{
-		  arc_print (_("Error: ARCompact target description supplied "
-			       "for non-ARCompact target.\n"));
-		  return false;
-		}
-
-	      is_reduced_rf = false;
-	      core_feature_name = core_arcompact_feature_name;
-	      core_regs = core_arcompact_register_names;
-	    }
-	  else
+	  std::ostringstream reg_names;
+	  for (std::size_t i = 0; i < reg.names.size(); ++i)
 	    {
-	      arc_print (_("Error: Couldn't find core register feature in "
-			   "supplied target description."));
-	      return false;
+	      if (i == 0)
+		reg_names << "'" << reg.names[0] << "'";
+	      else
+		reg_names << " or '" << reg.names[0] << "'";
 	    }
+	  arc_print (_("Error: Cannot find required register(s) %s "
+		       "in feature '%s'.\n"), reg_names.str ().c_str (),
+		       feature->name.c_str ());
+	  return false;
 	}
     }
 
-  struct tdesc_arch_data *tdesc_data_loc = tdesc_data_alloc ();
+  return true;
+}
 
-  gdb_assert (feature != NULL);
-  int valid_p = 1;
+/* Initialize target description for the ARC.
 
-  for (int i = 0; i <= ARC_LAST_CORE_REGNUM; i++)
+   Returns true if input TDESC was valid and in this case it will assign TDESC
+   and TDESC_DATA output parameters.  */
+
+static bool
+arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
+		struct tdesc_arch_data **tdesc_data)
+{
+  const struct target_desc *tdesc_loc = info.target_desc;
+  if (arc_debug)
+    debug_printf ("arc: Target description initialization.\n");
+
+  /* If target doesn't provide a description, use the default ones.  */
+  if (!tdesc_has_registers (tdesc_loc))
     {
-      /* If rf16, then skip extra registers.  */
-      if (is_reduced_rf && ((i >= ARC_R4_REGNUM && i <= ARC_R9_REGNUM)
-			    || (i >= ARC_R16_REGNUM && i <= ARC_R25_REGNUM)))
-	continue;
-
-      valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i,
-					 core_regs[i]);
-
-      /* - Ignore errors in extension registers - they are optional.
-	 - Ignore missing ILINK because it doesn't make sense for Linux.
-	 - Ignore missing ILINK2 when architecture is ARCompact, because it
-	 doesn't make sense for Linux targets.
-
-	 In theory those optional registers should be in separate features, but
-	 that would create numerous but tiny features, which looks like an
-	 overengineering of a rather simple task.  */
-      if (!valid_p && (i <= ARC_SP_REGNUM || i == ARC_BLINK_REGNUM
-		       || i == ARC_LP_COUNT_REGNUM || i == ARC_PCL_REGNUM
-		       || (i == ARC_R30_REGNUM && is_arcv2)))
-	{
-	  arc_print (_("Error: Cannot find required register `%s' in "
-		       "feature `%s'.\n"), core_regs[i], core_feature_name);
-	  tdesc_data_cleanup (tdesc_data_loc);
-	  return false;
-	}
+      arc_gdbarch_features features
+	= arc_gdbarch_features_create (info.abfd,
+				       info.bfd_arch_info->mach);
+      tdesc_loc = arc_lookup_target_description (features);
     }
+  gdb_assert (tdesc_loc != nullptr);
+
+  if (arc_debug)
+    debug_printf ("arc: Have got a target description\n");
 
-  /* Mandatory AUX registers are intentionally few and are common between
-     ARCompact and ARC v2, so same code can be used for both.  */
-  feature = tdesc_find_feature (tdesc_loc, aux_minimal_feature_name);
-  if (feature == NULL)
+  const struct tdesc_feature *feature_core
+    = tdesc_find_feature (tdesc_loc, ARC_CORE_FEATURE_NAME);
+  const struct tdesc_feature *feature_aux
+    = tdesc_find_feature (tdesc_loc, ARC_AUX_FEATURE_NAME);
+
+  if (feature_core == nullptr)
     {
-      arc_print (_("Error: Cannot find required feature `%s' in supplied "
-		   "target description.\n"), aux_minimal_feature_name);
-      tdesc_data_cleanup (tdesc_data_loc);
+      arc_print (_("Error: Cannot find required feature '%s' in supplied "
+		   "target description.\n"), ARC_CORE_FEATURE_NAME);
       return false;
     }
 
-  for (int i = ARC_FIRST_AUX_REGNUM; i <= ARC_LAST_AUX_REGNUM; i++)
+  if (feature_aux == nullptr)
     {
-      const char *name = aux_minimal_register_names[i - ARC_FIRST_AUX_REGNUM];
-      valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i, name);
-      if (!valid_p)
-	{
-	  arc_print (_("Error: Cannot find required register `%s' "
-		       "in feature `%s'.\n"),
-		     name, tdesc_feature_name (feature));
-	  tdesc_data_cleanup (tdesc_data_loc);
-	  return false;
-	}
+      arc_print (_("Error: Cannot find required feature '%s' in supplied "
+		   "target description.\n"), ARC_AUX_FEATURE_NAME);
+      return false;
+    }
+
+  const auto arc_core_reg_feature
+    = determine_core_reg_feature_set (info.bfd_arch_info->mach);
+  const auto arc_aux_reg_feature
+    = determine_aux_reg_feature_set ();
+
+  if (arc_core_reg_feature == nullptr || arc_aux_reg_feature == nullptr)
+    return false;
+
+  struct tdesc_arch_data *tdesc_data_loc = tdesc_data_alloc ();
+
+  arc_update_acc_reg_names (info.byte_order);
+
+  bool valid_p = arc_check_tdesc_feature (tdesc_data_loc,
+					  feature_core,
+					  arc_core_reg_feature);
+
+  valid_p &= arc_check_tdesc_feature (tdesc_data_loc,
+				      feature_aux,
+				      arc_aux_reg_feature);
+
+  if (!valid_p)
+    {
+      if (arc_debug)
+        debug_printf ("arc: Target description is not valid\n");
+      tdesc_data_cleanup (tdesc_data_loc);
+      return false;
     }
 
   *tdesc = tdesc_loc;
@@ -2133,36 +2307,6 @@ dump_arc_instruction_command (const char *args, int from_tty)
 
 /* See arc-tdep.h.  */
 
-const target_desc *
-arc_read_description (arc_sys_type sys_type)
-{
-  if (arc_debug)
-    debug_printf ("arc: Reading target description for \"%s\".\n",
-		  arc_sys_type_to_str (sys_type));
-
-  gdb_assert ((sys_type >= 0) && (sys_type < ARC_SYS_TYPE_NUM));
-  struct target_desc *tdesc = tdesc_arc_list[sys_type];
-
-  if (tdesc == nullptr)
-    {
-      tdesc = arc_create_target_description (sys_type);
-      tdesc_arc_list[sys_type] = tdesc;
-
-      if (arc_debug)
-	{
-	  const char *arch = tdesc_architecture_name (tdesc);
-	  const char *abi = tdesc_osabi_name (tdesc);
-	  arch = arch != NULL ? arch : "";
-	  abi = abi != NULL ? abi : "";
-	  debug_printf ("arc: Created target description for "
-			"\"%s\": arch=\"%s\", ABI=\"%s\"\n",
-			arc_sys_type_to_str (sys_type), arch, abi);
-	}
-    }
-
-  return tdesc;
-}
-
 void _initialize_arc_tdep ();
 void
 _initialize_arc_tdep ()
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index d72332c7638..6ca759a661d 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -35,7 +35,6 @@ enum arc_regnum
   {
     /* Core registers.  */
     ARC_R0_REGNUM = 0,
-    ARC_FIRST_CORE_REGNUM = ARC_R0_REGNUM,
     ARC_R1_REGNUM = 1,
     ARC_R4_REGNUM = 4,
     ARC_R7_REGNUM = 7,
@@ -54,6 +53,9 @@ enum arc_regnum
     ARC_R30_REGNUM,
     /* Return address from function.  */
     ARC_BLINK_REGNUM,
+    /* Accumulator registers.  */
+    ARC_R58_REGNUM = 58,
+    ARC_R59_REGNUM,
     /* Zero-delay loop counter.  */
     ARC_LP_COUNT_REGNUM = 60,
     /* Reserved register number.  There should never be a register with such
@@ -69,14 +71,21 @@ enum arc_regnum
     /* Program counter, aligned to 4-bytes, read-only.  */
     ARC_PCL_REGNUM,
     ARC_LAST_CORE_REGNUM = ARC_PCL_REGNUM,
+
     /* AUX registers.  */
     /* Actual program counter.  */
     ARC_PC_REGNUM,
     ARC_FIRST_AUX_REGNUM = ARC_PC_REGNUM,
     /* Status register.  */
     ARC_STATUS32_REGNUM,
-    ARC_LAST_REGNUM = ARC_STATUS32_REGNUM,
-    ARC_LAST_AUX_REGNUM = ARC_STATUS32_REGNUM,
+    /* Zero-delay loop start instruction.  */
+    ARC_LP_START_REGNUM,
+    /* Zero-delay loop next-after-last instruction.  */
+    ARC_LP_END_REGNUM,
+    /* Branch target address.  */
+    ARC_BTA_REGNUM,
+    ARC_LAST_AUX_REGNUM = ARC_BTA_REGNUM,
+    ARC_LAST_REGNUM = ARC_LAST_AUX_REGNUM,
 
     /* Additional ABI constants.  */
     ARC_FIRST_ARG_REGNUM = ARC_R0_REGNUM,
@@ -164,7 +173,4 @@ CORE_ADDR arc_insn_get_branch_target (const struct arc_instruction &insn);
 
 CORE_ADDR arc_insn_get_linear_next_pc (const struct arc_instruction &insn);
 
-/* Get the correct ARC target description for the given system type.  */
-const target_desc *arc_read_description (arc_sys_type sys_type);
-
 #endif /* ARC_TDEP_H */
diff --git a/gdb/arch/arc.c b/gdb/arch/arc.c
index 9552b4aff97..585d1d881eb 100644
--- a/gdb/arch/arc.c
+++ b/gdb/arch/arc.c
@@ -17,42 +17,106 @@
 
 
 #include "gdbsupport/common-defs.h"
-#include <stdlib.h>
-
 #include "arc.h"
+#include <stdlib.h>
+#include <unordered_map>
+#include <string>
 
 /* Target description features.  */
-#include "features/arc/core-v2.c"
-#include "features/arc/aux-v2.c"
-#include "features/arc/core-arcompact.c"
-#include "features/arc/aux-arcompact.c"
+#include "features/arc/v1-core.c"
+#include "features/arc/v1-aux.c"
+#include "features/arc/v2-core.c"
+#include "features/arc/v2-aux.c"
 
-/* See arc.h.  */
+#ifndef GDBSERVER
+#define STATIC_IN_GDB static
+#else
+#define STATIC_IN_GDB
+#endif
 
-target_desc *
-arc_create_target_description (arc_sys_type sys_type)
+STATIC_IN_GDB target_desc *
+arc_create_target_description (const struct arc_gdbarch_features &features)
 {
+  /* Create a new target description.  */
   target_desc *tdesc = allocate_target_description ();
 
-  long regnum = 0;
-
 #ifndef IN_PROCESS_AGENT
-  if (sys_type == ARC_SYS_TYPE_ARCV2)
-    set_tdesc_architecture (tdesc, "arc:ARCv2");
-  else
-    set_tdesc_architecture (tdesc, "arc:ARC700");
-#endif
+  std::string arch_name;
 
-  if (sys_type == ARC_SYS_TYPE_ARCV2)
+  /* Architecture names here must match the ones in
+     ARCH_INFO_STRUCT in bfd/cpu-arc.c.  */
+  if (features.isa == ARC_ISA_ARCV1 && features.reg_size == 4)
+      arch_name = "arc:ARC700";
+  else if (features.isa == ARC_ISA_ARCV2 && features.reg_size == 4)
+      arch_name = "arc:ARCv2";
+  else
     {
-      regnum = create_feature_arc_core_v2 (tdesc, regnum);
-      regnum = create_feature_arc_aux_v2 (tdesc, regnum);
+      std::string msg = string_printf
+	("Cannot determine architecture: ISA=%d; bitness=%d",
+	 features.isa, 8 * features.reg_size);
+      gdb_assert_not_reached (msg.c_str ());
     }
-  else
+
+  set_tdesc_architecture (tdesc, arch_name.c_str ());
+#endif
+
+  long regnum = 0;
+
+  switch (features.isa)
     {
-      regnum = create_feature_arc_core_arcompact (tdesc, regnum);
-      regnum = create_feature_arc_aux_arcompact (tdesc, regnum);
+    case ARC_ISA_ARCV1:
+	  regnum = create_feature_arc_v1_core (tdesc, regnum);
+	  regnum = create_feature_arc_v1_aux (tdesc, regnum);
+	  break;
+    case ARC_ISA_ARCV2:
+	  regnum = create_feature_arc_v2_core (tdesc, regnum);
+	  regnum = create_feature_arc_v2_aux (tdesc, regnum);
+	  break;
+    default:
+	  std::string msg = string_printf
+	    ("Cannot choose target description XML: %d", features.isa);
+	  gdb_assert_not_reached (msg.c_str ());
     }
 
   return tdesc;
 }
+
+#ifndef GDBSERVER
+
+/* Wrapper used by std::unordered_map to generate hash for features set.  */
+struct arc_gdbarch_features_hasher
+{
+  std::size_t
+  operator() (const arc_gdbarch_features &features) const noexcept
+  {
+    return features.hash ();
+  }
+};
+
+/* Cache of previously created target descriptions, indexed by the hash
+   of the features set used to create them.  */
+static std::unordered_map<arc_gdbarch_features,
+			  const target_desc_up,
+			  arc_gdbarch_features_hasher> arc_tdesc_cache;
+
+/* See arch/arc.h.  */
+
+const target_desc *
+arc_lookup_target_description (const struct arc_gdbarch_features &features)
+{
+  /* Lookup in the cache first.  If found, return the pointer from the
+     "target_desc_up" type which is a "unique_ptr".  This should be fine
+     as the "arc_tdesc_cache" will persist until GDB terminates.  */
+  const auto it = arc_tdesc_cache.find (features);
+  if (it != arc_tdesc_cache.end ())
+    return it->second.get ();
+
+  target_desc *tdesc = arc_create_target_description (features);
+
+  /* Add the newly created target description to the repertoire.  */
+  arc_tdesc_cache.emplace (features, tdesc);
+
+  return tdesc;
+}
+
+#endif /* !GDBSERVER */
diff --git a/gdb/arch/arc.h b/gdb/arch/arc.h
index fd806ae7d34..4f01d92bf09 100644
--- a/gdb/arch/arc.h
+++ b/gdb/arch/arc.h
@@ -20,29 +20,68 @@
 
 #include "gdbsupport/tdesc.h"
 
-/* Supported ARC system hardware types.  */
-enum arc_sys_type
+/* Supported ARC ISAs.  */
+enum arc_isa
 {
-  ARC_SYS_TYPE_ARCOMPACT = 0,	  /* ARC600 or ARC700 */
-  ARC_SYS_TYPE_ARCV2,		  /* ARC EM or ARC HS */
-  ARC_SYS_TYPE_NUM
+  ARC_ISA_ARCV1 = 1,  /* a.k.a. ARCompact (ARC600, ARC700)  */
+  ARC_ISA_ARCV2	      /* such as ARC EM and ARC HS  */
 };
 
-static inline const char *
-arc_sys_type_to_str (const arc_sys_type type)
+struct arc_gdbarch_features
 {
-  switch (type)
-    {
-    case ARC_SYS_TYPE_ARCOMPACT:
-      return "ARC_SYS_TYPE_ARCOMPACT";
-    case ARC_SYS_TYPE_ARCV2:
-      return "ARC_SYS_TYPE_ARCV2";
-    default:
-      return "Invalid";
-    }
-}
-
-/* Create target description for the specified system type.  */
-target_desc *arc_create_target_description (arc_sys_type sys_type);
+  arc_gdbarch_features (int reg_size, arc_isa isa)
+    : reg_size (reg_size), isa (isa)
+  {}
+
+  /* Register size in bytes.  Possible values are 4, and 8.  A 0 indicates
+     an uninitialised value.  */
+  int reg_size;
+
+  /* See ARC_ISA enum.  */
+  arc_isa isa;
+
+  /* Equality operator.  */
+  bool operator== (const struct arc_gdbarch_features &rhs) const
+  {
+    return (reg_size == rhs.reg_size && isa == rhs.isa);
+  }
+
+  /* Inequality operator.  */
+  bool operator!= (const struct arc_gdbarch_features &rhs) const
+  {
+    return !(*this == rhs);
+  }
+
+  /* Used by std::unordered_map to hash the feature sets.  The hash is
+     calculated in the manner below:
+     REG_SIZE |  ISA
+      5-bits  | 4-bits  */
+
+  std::size_t hash () const noexcept
+  {
+    std::size_t val = ((reg_size & 0x1f) << 8 | (isa & 0xf) << 0);
+    return val;
+  }
+};
+
+#ifdef GDBSERVER
+
+/* Create and return a target description that is compatible with FEATURES.
+   The only external client of this must be the gdbserver which manipulates
+   the returned data.  */
+
+target_desc *arc_create_target_description
+	(const struct arc_gdbarch_features &features);
+
+#else
+
+/* Lookup the cache for a target description matching the FEATURES.
+   If nothing is found, then create one and return it.  */
+
+const target_desc *arc_lookup_target_description
+	(const struct arc_gdbarch_features &features);
+
+#endif /* GDBSERVER */
+
 
 #endif /* ARCH_ARC_H */
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index d0af9a47b48..689603847a0 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -201,10 +201,10 @@ $(outdir)/%.dat: %.xml number-regs.xsl sort-regs.xsl gdbserver-regs.xsl
 FEATURE_XMLFILES = aarch64-core.xml \
 	aarch64-fpu.xml \
 	aarch64-pauth.xml \
-	arc/core-v2.xml \
-	arc/aux-v2.xml \
-	arc/core-arcompact.xml \
-	arc/aux-arcompact.xml \
+	arc/v1-core.xml \
+	arc/v1-aux.xml \
+	arc/v2-core.xml \
+	arc/v2-aux.xml \
 	arm/arm-core.xml \
 	arm/arm-fpa.xml \
 	arm/arm-m-profile.xml \
diff --git a/gdb/features/arc/aux-arcompact.c b/gdb/features/arc/v1-aux.c
similarity index 73%
rename from gdb/features/arc/aux-arcompact.c
rename to gdb/features/arc/v1-aux.c
index d8e8c74e639..d1540763433 100644
--- a/gdb/features/arc/aux-arcompact.c
+++ b/gdb/features/arc/v1-aux.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: aux-arcompact.xml */
+  Original: v1-aux.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_aux_arcompact (struct target_desc *result, long regnum)
+create_feature_arc_v1_aux (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux-minimal");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux");
   tdesc_type_with_fields *type_with_fields;
   type_with_fields = tdesc_create_flags (feature, "status32_type", 4);
   tdesc_add_flag (type_with_fields, 0, "H");
@@ -27,5 +27,8 @@ create_feature_arc_aux_arcompact (struct target_desc *result, long regnum)
 
   tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "status32", regnum++, 1, NULL, 32, "status32_type");
+  tdesc_create_reg (feature, "lp_start", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "lp_end", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "bta", regnum++, 1, NULL, 32, "code_ptr");
   return regnum;
 }
diff --git a/gdb/features/arc/aux-arcompact.xml b/gdb/features/arc/v1-aux.xml
similarity index 80%
rename from gdb/features/arc/aux-arcompact.xml
rename to gdb/features/arc/v1-aux.xml
index bf68112f5db..091808b1e29 100644
--- a/gdb/features/arc/aux-arcompact.xml
+++ b/gdb/features/arc/v1-aux.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.aux-minimal">
+<feature name="org.gnu.gdb.arc.aux">
   <flags id="status32_type" size="4">
       <field name="H"   start="0" end="0"/>
       <field name="E"   start="1" end="2"/>
@@ -19,10 +19,13 @@
       <field name="N"   start="10" end="10"/>
       <field name="Z"   start="11" end="11"/>
       <field name="L"   start="12" end="12"/>
-      <field name="R"  start="13" end="13"/>
+      <field name="R"   start="13" end="13"/>
       <field name="SE"  start="14" end="14"/>
   </flags>
 
   <reg name="pc"       bitsize="32" type="code_ptr"/>
   <reg name="status32" bitsize="32" type="status32_type"/>
+  <reg name="lp_start" bitsize="32" type="code_ptr"/>
+  <reg name="lp_end"   bitsize="32" type="code_ptr"/>
+  <reg name="bta"      bitsize="32" type="code_ptr"/>
 </feature>
diff --git a/gdb/features/arc/core-arcompact.c b/gdb/features/arc/v1-core.c
similarity index 87%
rename from gdb/features/arc/core-arcompact.c
rename to gdb/features/arc/v1-core.c
index 7d9a4b23c21..df51d4788df 100644
--- a/gdb/features/arc/core-arcompact.c
+++ b/gdb/features/arc/v1-core.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: core-arcompact.xml */
+  Original: v1-core.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_core_arcompact (struct target_desc *result, long regnum)
+create_feature_arc_v1_core (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core.arcompact");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core");
   tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
@@ -38,8 +38,6 @@ create_feature_arc_core_arcompact (struct target_desc *result, long regnum)
   tdesc_create_reg (feature, "gp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "fp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
-  tdesc_create_reg (feature, "ilink1", regnum++, 1, NULL, 32, "code_ptr");
-  tdesc_create_reg (feature, "ilink2", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "blink", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "lp_count", regnum++, 1, NULL, 32, "uint32");
   tdesc_create_reg (feature, "pcl", regnum++, 1, NULL, 32, "code_ptr");
diff --git a/gdb/features/arc/core-arcompact.xml b/gdb/features/arc/v1-core.xml
similarity index 92%
rename from gdb/features/arc/core-arcompact.xml
rename to gdb/features/arc/v1-core.xml
index 9209891b41a..68d04bdf9d0 100644
--- a/gdb/features/arc/core-arcompact.xml
+++ b/gdb/features/arc/v1-core.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.core.arcompact">
+<feature name="org.gnu.gdb.arc.core">
   <reg name="r0"  bitsize="32"/>
   <reg name="r1"  bitsize="32"/>
   <reg name="r2"  bitsize="32"/>
@@ -40,8 +40,6 @@
   <reg name="sp"  bitsize="32" type="data_ptr"/>
 
   <!-- Code pointers.  -->
-  <reg name="ilink1" bitsize="32" type="code_ptr"/>
-  <reg name="ilink2" bitsize="32" type="code_ptr"/>
   <reg name="blink"  bitsize="32" type="code_ptr"/>
 
   <!-- Here goes extension core registers: r32 - r59 -->
diff --git a/gdb/features/arc/aux-v2.c b/gdb/features/arc/v2-aux.c
similarity index 76%
rename from gdb/features/arc/aux-v2.c
rename to gdb/features/arc/v2-aux.c
index 6290b9b1a7f..7b38e377fe1 100644
--- a/gdb/features/arc/aux-v2.c
+++ b/gdb/features/arc/v2-aux.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: aux-v2.xml */
+  Original: v2-aux.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_aux_v2 (struct target_desc *result, long regnum)
+create_feature_arc_v2_aux (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux-minimal");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux");
   tdesc_type_with_fields *type_with_fields;
   type_with_fields = tdesc_create_flags (feature, "status32_type", 4);
   tdesc_add_flag (type_with_fields, 0, "H");
@@ -31,5 +31,8 @@ create_feature_arc_aux_v2 (struct target_desc *result, long regnum)
 
   tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "status32", regnum++, 1, NULL, 32, "status32_type");
+  tdesc_create_reg (feature, "lp_start", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "lp_end", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "bta", regnum++, 1, NULL, 32, "code_ptr");
   return regnum;
 }
diff --git a/gdb/features/arc/aux-v2.xml b/gdb/features/arc/v2-aux.xml
similarity index 86%
rename from gdb/features/arc/aux-v2.xml
rename to gdb/features/arc/v2-aux.xml
index 2701fad72dc..5d81e248088 100644
--- a/gdb/features/arc/aux-v2.xml
+++ b/gdb/features/arc/v2-aux.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.aux-minimal">
+<feature name="org.gnu.gdb.arc.aux">
   <flags id="status32_type" size="4">
       <field name="H"   start="0" end="0"/>
       <field name="E"   start="1" end="4"/>
@@ -29,4 +29,7 @@
 
   <reg name="pc"       bitsize="32" type="code_ptr"/>
   <reg name="status32" bitsize="32" type="status32_type"/>
+  <reg name="lp_start" bitsize="32" type="code_ptr"/>
+  <reg name="lp_end"   bitsize="32" type="code_ptr"/>
+  <reg name="bta"      bitsize="32" type="code_ptr"/>
 </feature>
diff --git a/gdb/features/arc/core-v2.c b/gdb/features/arc/v2-core.c
similarity index 91%
rename from gdb/features/arc/core-v2.c
rename to gdb/features/arc/v2-core.c
index d37da990457..1c3ef1a91df 100644
--- a/gdb/features/arc/core-v2.c
+++ b/gdb/features/arc/v2-core.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: core-v2.xml */
+  Original: v2-core.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_core_v2 (struct target_desc *result, long regnum)
+create_feature_arc_v2_core (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core.v2");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core");
   tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
@@ -38,7 +38,6 @@ create_feature_arc_core_v2 (struct target_desc *result, long regnum)
   tdesc_create_reg (feature, "gp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "fp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
-  tdesc_create_reg (feature, "ilink", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "r30", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "blink", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "lp_count", regnum++, 1, NULL, 32, "uint32");
diff --git a/gdb/features/arc/core-v2.xml b/gdb/features/arc/v2-core.xml
similarity index 90%
rename from gdb/features/arc/core-v2.xml
rename to gdb/features/arc/v2-core.xml
index 1b17968fb2e..2a2561eab16 100644
--- a/gdb/features/arc/core-v2.xml
+++ b/gdb/features/arc/v2-core.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.core.v2">
+<feature name="org.gnu.gdb.arc.core">
   <reg name="r0"  bitsize="32"/>
   <reg name="r1"  bitsize="32"/>
   <reg name="r2"  bitsize="32"/>
@@ -42,12 +42,11 @@
   <!-- Code pointers.  R30 is general purpose, but it used to be ILINK2 in
   ARCompact, thus its odd position in between of special purpose registers.
   GCC does't use this register, so it isn't a member of a general group. -->
-  <reg name="ilink" bitsize="32" type="code_ptr"/>
   <reg name="r30"   bitsize="32" group=""/>
   <reg name="blink" bitsize="32" type="code_ptr"/>
 
-  <!-- Here goes extension core registers: r32 - r57.  -->
-  <!-- Here goes ACCL/ACCH registers, r58, r59.  -->
+  <!-- Extension core registers: r32 - r57.  -->
+  <!-- ACCL/ACCH registers: r58, r59.  -->
 
   <!-- Loop counter.  -->
   <reg name="lp_count" bitsize="32" type="uint32"/>
-- 
2.27.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v4 2/3] arc: Add hardware loop detection
  2020-07-23 19:35     ` [PATCH v4 0/3] arc: Add GNU/Linux support Shahab Vahedi
  2020-07-23 19:35       ` [PATCH v4 1/3] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
@ 2020-07-23 19:35       ` Shahab Vahedi
  2020-08-01 14:53         ` Simon Marchi
  2020-07-23 19:35       ` [PATCH v4 3/3] arc: Add GNU/Linux support for ARC Shahab Vahedi
  2020-08-01 23:31       ` [PATCH v4 0/3] arc: Add GNU/Linux support Simon Marchi
  3 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-07-23 19:35 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

For ARC there are registers that are not part of a required set in XML
target descriptions by default, but are almost always present on ARC
targets and are universally exposed by the ptrace interface.  Hardware
loop registers being one of them.

LP_START and LP_END auxiliary registers are hardware loop start and end.
Formally, they are optional, but it is hard to find an ARC configuration
that doesn't have them.  They are always present in processors that can
run GNU/Linux.  GDB needs to know about those registers to implement
proper software single stepping, since they affect  what instruction
will be next.

This commit adds the code to check for the existance of "lp_start" and
"lp_end" in XML target descriptions. If they exist, then the function
reports that the target supports hardware loops.

gdb/ChangeLog:
2020-07-22  Shahab Vahedi  <shahab@synopsys.com>

	* arc-tdep.c (arc_check_for_hardware_loop): New.
	* arc-tdep.h (gdbarch_tdep): New field has_hw_loops.

gdb/doc/ChangeLog:
2020-07-22  Anton Kolesov  <anton.kolesov@synopsys.com>

	* gdb.texinfo (Synopsys ARC): Document LP_START, LP_END and BTA.
---
 gdb/arc-tdep.c      | 39 +++++++++++++++++++++++++++++++++++----
 gdb/arc-tdep.h      |  4 ++++
 gdb/doc/gdb.texinfo |  3 ++-
 3 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 0c7e045e54b..59e698bb18b 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -2006,6 +2006,35 @@ arc_check_tdesc_feature (struct tdesc_arch_data *tdesc_data,
   return true;
 }
 
+/* Check for the existance of "lp_start" and "lp_end" in target description.
+   If both are present, assume there is hardware loop support in the target.
+   This can be improved by looking into "lpc_size" field of "isa_config"
+   auxiliary register.  */
+
+static bool
+arc_check_for_hw_loops (const struct target_desc *tdesc,
+			struct tdesc_arch_data *data)
+{
+  const auto feature_aux = tdesc_find_feature (tdesc, ARC_AUX_FEATURE_NAME);
+  const auto *aux_regset = determine_aux_reg_feature_set ();
+
+  if (feature_aux == nullptr || aux_regset == nullptr)
+    return false;
+
+  bool hw_loop_p = false;
+  const auto lp_start_name =
+    aux_regset->registers[ARC_LP_START_REGNUM - ARC_FIRST_AUX_REGNUM].names[0];
+  const auto lp_end_name =
+    aux_regset->registers[ARC_LP_END_REGNUM - ARC_FIRST_AUX_REGNUM].names[0];
+
+  hw_loop_p = tdesc_numbered_register (feature_aux, data,
+				       ARC_LP_START_REGNUM, lp_start_name);
+  hw_loop_p &= tdesc_numbered_register (feature_aux, data,
+				       ARC_LP_END_REGNUM, lp_end_name);
+
+  return hw_loop_p;
+}
+
 /* Initialize target description for the ARC.
 
    Returns true if input TDESC was valid and in this case it will assign TDESC
@@ -2125,13 +2154,15 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     debug_printf ("arc: Architecture initialization.\n");
 
   if (!arc_tdesc_init (info, &tdesc, &tdesc_data))
-    return NULL;
+    return nullptr;
 
   /* Allocate the ARC-private target-dependent information structure, and the
      GDB target-independent information structure.  */
-  struct gdbarch_tdep *tdep = XCNEW (struct gdbarch_tdep);
+  gdb::unique_xmalloc_ptr<struct gdbarch_tdep> tdep
+    (XCNEW (struct gdbarch_tdep));
   tdep->jb_pc = -1; /* No longjmp support by default.  */
-  struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep);
+  tdep->has_hw_loops = arc_check_for_hw_loops (tdesc, tdesc_data);
+  struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep.release ());
 
   /* Data types.  */
   set_gdbarch_short_bit (gdbarch, 16);
@@ -2212,7 +2243,7 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      It can override functions set earlier.  */
   gdbarch_init_osabi (info, gdbarch);
 
-  if (tdep->jb_pc >= 0)
+  if (gdbarch_tdep (gdbarch)->jb_pc >= 0)
     set_gdbarch_get_longjmp_target (gdbarch, arc_get_longjmp_target);
 
   /* Disassembler options.  Enforce CPU if it was specified in XML target
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index 6ca759a661d..e752348a262 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -23,6 +23,7 @@
 
 /* Need disassemble_info.  */
 #include "dis-asm.h"
+#include "gdbarch.h"
 #include "arch/arc.h"
 
 /* To simplify GDB code this enum assumes that internal regnums should be same
@@ -110,6 +111,9 @@ struct gdbarch_tdep
   /* Offset to PC value in jump buffer.  If this is negative, longjmp
      support will be disabled.  */
   int jb_pc;
+
+  /* Whether target has hardware (aka zero-delay) loops.  */
+  bool has_hw_loops;
 };
 
 /* Utility functions used by other ARC-specific modules.  */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index a002084d5b9..9502992b9af 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -45238,7 +45238,8 @@ difference with @samp{org.gnu.gdb.arc.core.v2} feature is in the names of
 ARC v2, but @samp{ilink2} is optional on ARCompact.
 
 The @samp{org.gnu.gdb.arc.aux-minimal} feature is required for all ARC
-targets.  It should contain registers @samp{pc} and @samp{status32}.
+targets.  It should contain registers @samp{pc} and @samp{status32}.  It may
+contain registers @samp{lp_start}, @samp{lp_end} and @samp{bta}.
 
 @node ARM Features
 @subsection ARM Features
-- 
2.27.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v4 3/3] arc: Add GNU/Linux support for ARC
  2020-07-23 19:35     ` [PATCH v4 0/3] arc: Add GNU/Linux support Shahab Vahedi
  2020-07-23 19:35       ` [PATCH v4 1/3] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
  2020-07-23 19:35       ` [PATCH v4 2/3] arc: Add hardware loop detection Shahab Vahedi
@ 2020-07-23 19:35       ` Shahab Vahedi
  2020-08-01 15:01         ` Simon Marchi
  2020-08-01 23:31       ` [PATCH v4 0/3] arc: Add GNU/Linux support Simon Marchi
  3 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-07-23 19:35 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Anton Kolesov, Francois Bedard, Anton Kolesov

From: Anton Kolesov <Anton.Kolesov@synopsys.com>

ARC Linux targets differences from baremetal:

- No support for hardware single instruction stepping.
- Different access rules to registers.
- Use of another instruction for breakpoints.

v2: Changes after Tom's remarks [1]
 arc-linux-tdep.c
  - Use true/false instead of TRUE/FALSE.
  - arc_linux_sw_breakpoint_from_kind (): Break long lines into two.
  - arc_linux_sw_breakpoint_from_kind (): Remove starting blank line.
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 arc-tdep.c
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 gdb/configure.tgt
  - arc*-*-linux*): Remove "build_gdbserver=yes".

v3: Changes after Simon's remarks [2]
  arc-linux-tdep.c
  - Use "return trap_size" instead of cryptic "return 2".
  - Removed unnecessary curly braces.
  - Removed "void" from "_initialize_arc_linux_tdep (void)".

[1] Tom's remarks
https://sourceware.org/pipermail/gdb-patches/2020-April/167887.html

[2] Simon's remarks
https://sourceware.org/pipermail/gdb-patches/2020-May/168513.html

2020-07-22  Anton Kolesov  <anton.kolesov@synopsys.com>

	* configure.tgt: ARC support for GNU/Linux.
	* Makefile.in (ALL_TARGET_OBJS): Likewise.
	* arc-linux-tdep.c: New file.
	* arc-tdep.h (ARC_STATUS32_L_MASK, ARC_STATUS32_DE_MASK): Declare.
	* arc-tdep.c (arc_write_pc): Use it.
---
 gdb/Makefile.in      |   1 +
 gdb/arc-linux-tdep.c | 283 +++++++++++++++++++++++++++++++++++++++++++
 gdb/arc-tdep.c       |   3 +-
 gdb/arc-tdep.h       |   5 +
 gdb/configure.tgt    |   5 +
 5 files changed, 295 insertions(+), 2 deletions(-)
 create mode 100644 gdb/arc-linux-tdep.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 9d484457397..85304b9f549 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -697,6 +697,7 @@ ALL_64_TARGET_OBS = \
 # All other target-dependent objects files (used with --enable-targets=all).
 ALL_TARGET_OBS = \
 	aarch32-tdep.o \
+	arc-linux-tdep.o \
 	arc-tdep.o \
 	arch/aarch32.o \
 	arch/arc.o \
diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
new file mode 100644
index 00000000000..be24a072881
--- /dev/null
+++ b/gdb/arc-linux-tdep.c
@@ -0,0 +1,283 @@
+/* Target dependent code for GNU/Linux ARC.
+
+   Copyright 2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* GDB header files.  */
+#include "defs.h"
+#include "linux-tdep.h"
+#include "objfiles.h"
+#include "opcode/arc.h"
+#include "osabi.h"
+#include "solib-svr4.h"
+
+/* ARC header files.  */
+#include "opcodes/arc-dis.h"
+#include "arc-tdep.h"
+
+/* Implement the "cannot_fetch_register" gdbarch method.  */
+
+static int
+arc_linux_cannot_fetch_register (struct gdbarch *gdbarch, int regnum)
+{
+  /* Assume that register is readable if it is unknown.  */
+  switch (regnum)
+    {
+    case ARC_ILINK_REGNUM:
+    case ARC_RESERVED_REGNUM:
+    case ARC_LIMM_REGNUM:
+      return true;
+    case ARC_R30_REGNUM:
+    case ARC_R58_REGNUM:
+    case ARC_R59_REGNUM:
+      return !arc_mach_is_arcv2 (gdbarch);
+    }
+  if (regnum > ARC_BLINK_REGNUM && regnum < ARC_LP_COUNT_REGNUM)
+    return true;
+  return false;
+}
+
+/* Implement the "cannot_store_register" gdbarch method.  */
+
+static int
+arc_linux_cannot_store_register (struct gdbarch *gdbarch, int regnum)
+{
+  /* Assume that register is writable if it is unknown.  */
+  switch (regnum)
+    {
+    case ARC_ILINK_REGNUM:
+    case ARC_RESERVED_REGNUM:
+    case ARC_LIMM_REGNUM:
+    case ARC_PCL_REGNUM:
+      return true;
+    case ARC_R30_REGNUM:
+    case ARC_R58_REGNUM:
+    case ARC_R59_REGNUM:
+      return !arc_mach_is_arcv2 (gdbarch);
+    }
+  if (regnum > ARC_BLINK_REGNUM && regnum < ARC_LP_COUNT_REGNUM)
+    return true;
+  return false;
+}
+
+/* For ARC Linux, breakpoint uses the 16-bit TRAP_S 1 instruction, which
+   is 0x3e78 (little endian) or 0x783e (big endian).  */
+
+static const gdb_byte arc_linux_trap_s_be[] = { 0x78, 0x3e };
+static const gdb_byte arc_linux_trap_s_le[] = { 0x3e, 0x78 };
+static const int trap_size = 2;   /* Number of bytes to insert "trap".  */
+
+/* Implement the "breakpoint_kind_from_pc" gdbarch method.  */
+
+static int
+arc_linux_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+  return trap_size;
+}
+
+/* Implement the "sw_breakpoint_from_kind" gdbarch method.  */
+
+static const gdb_byte *
+arc_linux_sw_breakpoint_from_kind (struct gdbarch *gdbarch,
+				   int kind, int *size)
+{
+  *size = kind;
+  return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+	  ? arc_linux_trap_s_be
+	  : arc_linux_trap_s_le);
+}
+
+/* Implement the "software_single_step" gdbarch method.  */
+
+static std::vector<CORE_ADDR>
+arc_linux_software_single_step (struct regcache *regcache)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct disassemble_info di = arc_disassemble_info (gdbarch);
+
+  /* Read current instruction.  */
+  struct arc_instruction curr_insn;
+  arc_insn_decode (regcache_read_pc (regcache), &di, arc_delayed_print_insn,
+		   &curr_insn);
+  CORE_ADDR next_pc = arc_insn_get_linear_next_pc (curr_insn);
+
+  std::vector<CORE_ADDR> next_pcs;
+
+  /* For instructions with delay slots, the fall thru is not the
+     instruction immediately after the current instruction, but the one
+     after that.  */
+  if (curr_insn.has_delay_slot)
+    {
+      struct arc_instruction next_insn;
+      arc_insn_decode (next_pc, &di, arc_delayed_print_insn, &next_insn);
+      next_pcs.push_back (arc_insn_get_linear_next_pc (next_insn));
+    }
+  else
+    next_pcs.push_back (next_pc);
+
+  ULONGEST status32;
+  regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
+				 &status32);
+
+  if (curr_insn.is_control_flow)
+    {
+      CORE_ADDR branch_pc = arc_insn_get_branch_target (curr_insn);
+      if (branch_pc != next_pc)
+	next_pcs.push_back (branch_pc);
+    }
+  /* Is current instruction the last in a loop body?  */
+  else if (tdep->has_hw_loops)
+    {
+      /* If STATUS32.L is 1, then ZD-loops are disabled.  */
+      if ((status32 & ARC_STATUS32_L_MASK) == 0)
+	{
+	  ULONGEST lp_end, lp_start, lp_count;
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_START_REGNUM,
+					 &lp_start);
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_END_REGNUM, &lp_end);
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_COUNT_REGNUM,
+					 &lp_count);
+
+	  if (arc_debug)
+	    {
+	      debug_printf ("arc-linux: lp_start = %s, lp_end = %s, "
+			    "lp_count = %s, next_pc = %s\n",
+			    paddress (gdbarch, lp_start),
+			    paddress (gdbarch, lp_end),
+			    pulongest (lp_count),
+			    paddress (gdbarch, next_pc));
+	    }
+
+	  if (next_pc == lp_end && lp_count > 1)
+	    {
+	      /* The instruction is in effect a jump back to the start of
+		 the loop.  */
+	      next_pcs.push_back (lp_start);
+	    }
+
+	}
+    }
+
+  /* Is this a delay slot?  Then next PC is in BTA register.  */
+  if ((status32 & ARC_STATUS32_DE_MASK) != 0)
+    {
+      ULONGEST bta;
+      regcache_cooked_read_unsigned (regcache, ARC_BTA_REGNUM, &bta);
+      next_pcs.push_back (bta);
+    }
+
+  return next_pcs;
+}
+
+/* Implement the "skip_solib_resolver" gdbarch method.
+
+   See glibc_skip_solib_resolver for details.  */
+
+static CORE_ADDR
+arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  /* For uClibc 0.9.26+.
+
+     An unresolved PLT entry points to "__dl_linux_resolve", which calls
+     "_dl_linux_resolver" to do the resolving and then eventually jumps to
+     the function.
+
+     So we look for the symbol `_dl_linux_resolver', and if we are there,
+     gdb sets a breakpoint at the return address, and continues.  */
+  struct bound_minimal_symbol resolver =
+    lookup_minimal_symbol ("_dl_linux_resolver", NULL, NULL);
+
+  if (arc_debug)
+    {
+      if (resolver.minsym != nullptr)
+	{
+	  CORE_ADDR res_addr = BMSYMBOL_VALUE_ADDRESS (resolver);
+	  debug_printf ("arc-linux: skip_solib_resolver (): "
+			"pc = %s, resolver at %s\n",
+			print_core_address (gdbarch, pc),
+			print_core_address (gdbarch, res_addr));
+	}
+      else
+	{
+	  debug_printf ("arc-linux: skip_solib_resolver (): "
+			"pc = %s, no resolver found\n",
+			print_core_address (gdbarch, pc));
+	}
+    }
+
+  if (resolver.minsym != nullptr && BMSYMBOL_VALUE_ADDRESS (resolver) == pc)
+    {
+      /* Find the return address.  */
+      return frame_unwind_caller_pc (get_current_frame ());
+    }
+  else
+    {
+      /* No breakpoint required.  */
+      return 0;
+    }
+}
+
+/* Initialization specific to Linux environment.  */
+
+static void
+arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (arc_debug)
+    debug_printf ("arc-linux: GNU/Linux OS/ABI initialization.\n");
+
+  /* If we are using Linux, we have in uClibc
+     (libc/sysdeps/linux/arc/bits/setjmp.h):
+
+     typedef int __jmp_buf[13+1+1+1];    //r13-r25, fp, sp, blink
+
+     Where "blink" is a stored PC of a caller function.
+   */
+  tdep->jb_pc = 15;
+
+  linux_init_abi (info, gdbarch);
+
+  /* Set up target dependent GDB architecture entries.  */
+  set_gdbarch_cannot_fetch_register (gdbarch, arc_linux_cannot_fetch_register);
+  set_gdbarch_cannot_store_register (gdbarch, arc_linux_cannot_store_register);
+  set_gdbarch_breakpoint_kind_from_pc (gdbarch,
+				       arc_linux_breakpoint_kind_from_pc);
+  set_gdbarch_sw_breakpoint_from_kind (gdbarch,
+				       arc_linux_sw_breakpoint_from_kind);
+  set_gdbarch_fetch_tls_load_module_address (gdbarch,
+					     svr4_fetch_objfile_link_map);
+  set_gdbarch_software_single_step (gdbarch, arc_linux_software_single_step);
+  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+  set_gdbarch_skip_solib_resolver (gdbarch, arc_linux_skip_solib_resolver);
+
+  /* GNU/Linux uses SVR4-style shared libraries, with 32-bit ints, longs
+     and pointers (ILP32).  */
+  set_solib_svr4_fetch_link_map_offsets (gdbarch,
+					 svr4_ilp32_fetch_link_map_offsets);
+}
+
+/* Suppress warning from -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_arc_linux_tdep;
+
+void
+_initialize_arc_linux_tdep ()
+{
+  gdbarch_register_osabi (bfd_arch_arc, 0, GDB_OSABI_LINUX,
+			  arc_linux_init_osabi);
+}
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 59e698bb18b..aadf1889c9b 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -602,8 +602,7 @@ arc_write_pc (struct regcache *regcache, CORE_ADDR new_pc)
   regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
 				 &status32);
 
-  /* Mask for DE bit is 0x40.  */
-  if (status32 & 0x40)
+  if ((status32 & ARC_STATUS32_DE_MASK) != 0)
     {
       if (arc_debug)
 	{
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index e752348a262..6331d29f402 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -100,6 +100,11 @@ enum arc_regnum
    Longer registers are represented as pairs of 32-bit registers.  */
 #define ARC_REGISTER_SIZE  4
 
+/* STATUS32 register: hardware loops disabled bit.  */
+#define ARC_STATUS32_L_MASK (1 << 12)
+/* STATUS32 register: current instruction is a delay slot.  */
+#define ARC_STATUS32_DE_MASK (1 << 6)
+
 #define arc_print(fmt, args...) fprintf_unfiltered (gdb_stdlog, fmt, ##args)
 
 extern int arc_debug;
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index d66f01bb9f7..4178eb4e773 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -157,6 +157,11 @@ arc*-*-elf32)
 	gdb_target_obs="arc-newlib-tdep.o"
 	;;
 
+arc*-*-linux*)
+	# Target: ARC machine running Linux
+	gdb_target_obs="arc-linux-tdep.o linux-tdep.o solib-svr4.o"
+	;;
+
 arm*-wince-pe | arm*-*-mingw32ce*)
 	# Target: ARM based machine running Windows CE (win32)
 	gdb_target_obs="arm-wince-tdep.o windows-tdep.o"
-- 
2.27.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 1/3] arc: Add ARCv2 XML target along with refactoring
  2020-07-23 19:35       ` [PATCH v4 1/3] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
@ 2020-07-30 23:34         ` Simon Marchi
  0 siblings, 0 replies; 86+ messages in thread
From: Simon Marchi @ 2020-07-30 23:34 UTC (permalink / raw)
  To: Shahab Vahedi, gdb-patches
  Cc: Shahab Vahedi, Tom Tromey, Anton Kolesov, Francois Bedard

I noted a few extra comments.  The patch LGTM with those fixed.

> @@ -1717,192 +1857,226 @@ static const struct frame_base arc_normal_base = {
>    arc_frame_base_address
>  };
>  
> -/* Initialize target description for the ARC.
> -
> -   Returns TRUE if input tdesc was valid and in this case it will assign TDESC
> -   and TDESC_DATA output parameters.  */
> -
> -static bool
> -arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
> -		struct tdesc_arch_data **tdesc_data)
> +static enum arc_isa
> +mach_type_to_arc_isa (const unsigned long mach)
>  {
> -  if (arc_debug)
> -    debug_printf ("arc: Target description initialization.\n");
> -
> -  const struct target_desc *tdesc_loc = info.target_desc;
> +  switch (mach)
> +    {
> +    case bfd_mach_arc_arc600:
> +    case bfd_mach_arc_arc601:
> +    case bfd_mach_arc_arc700:
> +      return ARC_ISA_ARCV1;
> +      break;
> +    case bfd_mach_arc_arcv2:
> +      return ARC_ISA_ARCV2;
> +      break;

Remove the "break"s.

> +    default:
> +	internal_error (__FILE__, __LINE__,
> +			_("unknown machine id %lu"), mach);
> +    }
> +}
>  
> -  /* Depending on whether this is ARCompact or ARCv2 we will assign
> -     different default registers sets (which will differ in exactly two core
> -     registers).  GDB will also refuse to accept register feature from invalid
> -     ISA - v2 features can be used only with v2 ARChitecture.  We read
> -     bfd_arch_info, which looks like to be a safe bet here, as it looks like it
> -     is always initialized even when we don't pass any elf file to GDB at all
> -     (it uses default arch in this case).  Also GDB will call this function
> -     multiple times, and if XML target description file contains architecture
> -     specifications, then GDB will set this architecture to info.bfd_arch_info,
> -     overriding value from ELF file if they are different.  That means that,
> -     where matters, this value is always our best guess on what CPU we are
> -     debugging.  It has been noted that architecture specified in tdesc file
> -     has higher precedence over ELF and even "set architecture" - that is,
> -     using "set architecture" command will have no effect when tdesc has "arch"
> -     tag.  */
> -  /* Cannot use arc_mach_is_arcv2 (), because gdbarch is not created yet.  */
> -  const int is_arcv2 = (info.bfd_arch_info->mach == bfd_mach_arc_arcv2);
> -  bool is_reduced_rf;
> -  const char *const *core_regs;
> -  const char *core_feature_name;
> +/* Common construction code for ARC_GDBARCH_FEATURES struct.  If there
> +   is no ABFD, then a FEATURE with default values is returned.  */
>  
> -  /* If target doesn't provide a description, use the default ones.  */
> -  if (!tdesc_has_registers (tdesc_loc))
> +static arc_gdbarch_features
> +arc_gdbarch_features_create (const bfd *abfd, const unsigned long mach)
> +{
> +  /* Use 4 as a fallback value.  */
> +  int reg_size = 4;
> +
> +  /* Try to guess the features parameters by looking at the binary to be
> +     executed.  If the user is providing a binary that does not match the
> +     target, then tough luck.  This is the last effort to makes sense of
> +     what's going on.  */
> +  if (abfd != NULL && bfd_get_flavour (abfd) == bfd_target_elf_flavour)

NULL -> nullptr, at least for new code.

>      {
> -      if (is_arcv2)
> -	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCV2);
> +      unsigned char eclass = elf_elfheader (abfd)->e_ident[EI_CLASS];
> +
> +      if (eclass == ELFCLASS32)
> +	reg_size = 4;
> +      else if (eclass == ELFCLASS64)
> +	reg_size = 8;
>        else
> -	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCOMPACT);
> +	internal_error (__FILE__, __LINE__,
> +			_("unknown ELF header class %d"), eclass);
>      }
> -  else
> +
> +  /* MACH from a bfd_arch_info struct is used here.  It should be a safe
> +     bet, as it looks like the struct is always initialized even when we
> +     don't pass any elf file to GDB at all (it uses default arch in that
> +     case).  */
> +  arc_isa isa = mach_type_to_arc_isa (mach);
> +
> +  return arc_gdbarch_features (reg_size, isa);
> +}
> +
> +/* Based on the MACH value, determines which core register features set
> +   must be used.  Possible outcomes:
> +   {nullptr, &arc_v1_core_reg_feature, &arc_v2_core_reg_feature}  */
> +
> +static arc_register_feature *
> +determine_core_reg_feature_set (const unsigned long mach)
> +{
> +  switch (mach_type_to_arc_isa (mach))
>      {
> -      if (arc_debug)
> -	debug_printf ("arc: Using provided register set.\n");
> +    case ARC_ISA_ARCV1:
> +      return &arc_v1_core_reg_feature;
> +    case ARC_ISA_ARCV2:
> +      return &arc_v2_core_reg_feature;
> +    default:
> +      return nullptr;

I think this should be gdb_assert_not_reached, since it's not possible for
mach_type_to_arc_isa to return another value.

The contract of this function should be that it can't return nullptr, and then
the callers can assume that the return value is always != nullptr.

>      }
> -  gdb_assert (tdesc_loc != NULL);
> -
> -  /* Now we can search for base registers.  Core registers can be either full
> -     or reduced.  Summary:
> -
> -     - core.v2 + aux-minimal
> -     - core-reduced.v2 + aux-minimal
> -     - core.arcompact + aux-minimal
> -
> -     NB: It is entirely feasible to have ARCompact with reduced core regs, but
> -     we ignore that because GCC doesn't support that and at the same time
> -     ARCompact is considered obsolete, so there is not much reason to support
> -     that.  */
> -  const struct tdesc_feature *feature
> -    = tdesc_find_feature (tdesc_loc, core_v2_feature_name);
> -  if (feature != NULL)
> -    {
> -      /* Confirm that register and architecture match, to prevent accidents in
> -	 some situations.  This code will trigger an error if:
> +}
>  
> -	 1. XML tdesc doesn't specify arch explicitly, registers are for arch
> -	 X, but ELF specifies arch Y.
> +/* At the moment, there is only 1 auxiliary register features set.
> +   This is a place holder for future extendability.  */
>  
> -	 2. XML tdesc specifies arch X, but contains registers for arch Y.
> +static const arc_register_feature *
> +determine_aux_reg_feature_set ()
> +{
> +  return &arc_common_aux_reg_feature;
> +}
>  
> -	 It will not protect from case where XML or ELF specify arch X,
> -	 registers are for the same arch X, but the real target is arch Y.  To
> -	 detect this case we need to check IDENTITY register.  */
> -      if (!is_arcv2)
> -	{
> -	  arc_print (_("Error: ARC v2 target description supplied for "
> -		       "non-ARCv2 target.\n"));
> -	  return false;
> -	}
> +/* Update accumulator register names (ACCH/ACCL) for r58 and r59 in the
> +   register sets.  The endianness determines the assignment:
>  
> -      is_reduced_rf = false;
> -      core_feature_name = core_v2_feature_name;
> -      core_regs = core_v2_register_names;
> -    }
> -  else
> +         ,------.------.
> +         |  LE  |  BE  |
> +   ,-----|------+------|
> +   | r58 | accl | acch |
> +   | r59 | acch | accl |
> +   `-----^------^------'  */
> +
> +static void
> +arc_update_acc_reg_names (const int byte_order)
> +{
> +  const char *r58_alias
> +    = byte_order == BFD_ENDIAN_LITTLE ? "accl" : "acch";
> +  const char *r59_alias
> +    = byte_order == BFD_ENDIAN_LITTLE ? "acch" : "accl";
> +
> +  /* Subscript 1 must be OK because those registers have 2 names.  */
> +  arc_v1_core_reg_feature.registers[ARC_R58_REGNUM].names[1] = r58_alias;
> +  arc_v1_core_reg_feature.registers[ARC_R59_REGNUM].names[1] = r59_alias;
> +  arc_v2_core_reg_feature.registers[ARC_R58_REGNUM].names[1] = r58_alias;
> +  arc_v2_core_reg_feature.registers[ARC_R59_REGNUM].names[1] = r59_alias;
> +}
> +
> +/* Go through all the registers in REG_SET and check if they exist
> +   in FEATURE.  The TDESC_DATA is updated with the register number
> +   in REG_SET if it is found in the feature.  If a required register
> +   is not found, this function returns false.  */
> +
> +static bool
> +arc_check_tdesc_feature (struct tdesc_arch_data *tdesc_data,
> +			 const struct tdesc_feature *feature,
> +			 const struct arc_register_feature *reg_set)
> +{
> +  for (const auto &reg : reg_set->registers)
>      {
> -      feature = tdesc_find_feature (tdesc_loc, core_reduced_v2_feature_name);
> -      if (feature != NULL)
> +      bool found = false;
> +
> +      for (const char *name : reg.names)
>  	{
> -	  if (!is_arcv2)
> -	    {
> -	      arc_print (_("Error: ARC v2 target description supplied for "
> -			   "non-ARCv2 target.\n"));
> -	      return false;
> -	    }
> +	  found =
> +	    

The assignment operator goes on the next line:

  found
    = tdesc_numbered_register (feature, tdesc_data, reg.regnum, name);

> @@ -2133,36 +2307,6 @@ dump_arc_instruction_command (const char *args, int from_tty)
>  
>  /* See arc-tdep.h.  */

This comment is now dangling.

>  
> -const target_desc *
> -arc_read_description (arc_sys_type sys_type)
> -{
> -  if (arc_debug)
> -    debug_printf ("arc: Reading target description for \"%s\".\n",
> -		  arc_sys_type_to_str (sys_type));
> -
> -  gdb_assert ((sys_type >= 0) && (sys_type < ARC_SYS_TYPE_NUM));
> -  struct target_desc *tdesc = tdesc_arc_list[sys_type];
> -
> -  if (tdesc == nullptr)
> -    {
> -      tdesc = arc_create_target_description (sys_type);
> -      tdesc_arc_list[sys_type] = tdesc;
> -
> -      if (arc_debug)
> -	{
> -	  const char *arch = tdesc_architecture_name (tdesc);
> -	  const char *abi = tdesc_osabi_name (tdesc);
> -	  arch = arch != NULL ? arch : "";
> -	  abi = abi != NULL ? abi : "";
> -	  debug_printf ("arc: Created target description for "
> -			"\"%s\": arch=\"%s\", ABI=\"%s\"\n",
> -			arc_sys_type_to_str (sys_type), arch, abi);
> -	}
> -    }
> -
> -  return tdesc;
> -}
> -
>  void _initialize_arc_tdep ();
>  void
>  _initialize_arc_tdep ()
> diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
> index d72332c7638..6ca759a661d 100644
> --- a/gdb/arc-tdep.h
> +++ b/gdb/arc-tdep.h
> @@ -35,7 +35,6 @@ enum arc_regnum
>    {
>      /* Core registers.  */
>      ARC_R0_REGNUM = 0,
> -    ARC_FIRST_CORE_REGNUM = ARC_R0_REGNUM,
>      ARC_R1_REGNUM = 1,
>      ARC_R4_REGNUM = 4,
>      ARC_R7_REGNUM = 7,
> @@ -54,6 +53,9 @@ enum arc_regnum
>      ARC_R30_REGNUM,
>      /* Return address from function.  */
>      ARC_BLINK_REGNUM,
> +    /* Accumulator registers.  */
> +    ARC_R58_REGNUM = 58,
> +    ARC_R59_REGNUM,
>      /* Zero-delay loop counter.  */
>      ARC_LP_COUNT_REGNUM = 60,
>      /* Reserved register number.  There should never be a register with such
> @@ -69,14 +71,21 @@ enum arc_regnum
>      /* Program counter, aligned to 4-bytes, read-only.  */
>      ARC_PCL_REGNUM,
>      ARC_LAST_CORE_REGNUM = ARC_PCL_REGNUM,
> +
>      /* AUX registers.  */
>      /* Actual program counter.  */
>      ARC_PC_REGNUM,
>      ARC_FIRST_AUX_REGNUM = ARC_PC_REGNUM,
>      /* Status register.  */
>      ARC_STATUS32_REGNUM,
> -    ARC_LAST_REGNUM = ARC_STATUS32_REGNUM,
> -    ARC_LAST_AUX_REGNUM = ARC_STATUS32_REGNUM,
> +    /* Zero-delay loop start instruction.  */
> +    ARC_LP_START_REGNUM,
> +    /* Zero-delay loop next-after-last instruction.  */
> +    ARC_LP_END_REGNUM,
> +    /* Branch target address.  */
> +    ARC_BTA_REGNUM,
> +    ARC_LAST_AUX_REGNUM = ARC_BTA_REGNUM,
> +    ARC_LAST_REGNUM = ARC_LAST_AUX_REGNUM,
>  
>      /* Additional ABI constants.  */
>      ARC_FIRST_ARG_REGNUM = ARC_R0_REGNUM,
> @@ -164,7 +173,4 @@ CORE_ADDR arc_insn_get_branch_target (const struct arc_instruction &insn);
>  
>  CORE_ADDR arc_insn_get_linear_next_pc (const struct arc_instruction &insn);
>  
> -/* Get the correct ARC target description for the given system type.  */
> -const target_desc *arc_read_description (arc_sys_type sys_type);
> -
>  #endif /* ARC_TDEP_H */
> diff --git a/gdb/arch/arc.c b/gdb/arch/arc.c
> index 9552b4aff97..585d1d881eb 100644
> --- a/gdb/arch/arc.c
> +++ b/gdb/arch/arc.c
> @@ -17,42 +17,106 @@
>  
>  
>  #include "gdbsupport/common-defs.h"
> -#include <stdlib.h>
> -
>  #include "arc.h"
> +#include <stdlib.h>
> +#include <unordered_map>
> +#include <string>
>  
>  /* Target description features.  */
> -#include "features/arc/core-v2.c"
> -#include "features/arc/aux-v2.c"
> -#include "features/arc/core-arcompact.c"
> -#include "features/arc/aux-arcompact.c"
> +#include "features/arc/v1-core.c"
> +#include "features/arc/v1-aux.c"
> +#include "features/arc/v2-core.c"
> +#include "features/arc/v2-aux.c"
>  
> -/* See arc.h.  */
> +#ifndef GDBSERVER
> +#define STATIC_IN_GDB static
> +#else
> +#define STATIC_IN_GDB
> +#endif
>  
> -target_desc *
> -arc_create_target_description (arc_sys_type sys_type)
> +STATIC_IN_GDB target_desc *
> +arc_create_target_description (const struct arc_gdbarch_features &features)
>  {
> +  /* Create a new target description.  */
>    target_desc *tdesc = allocate_target_description ();
>  
> -  long regnum = 0;
> -
>  #ifndef IN_PROCESS_AGENT
> -  if (sys_type == ARC_SYS_TYPE_ARCV2)
> -    set_tdesc_architecture (tdesc, "arc:ARCv2");
> -  else
> -    set_tdesc_architecture (tdesc, "arc:ARC700");
> -#endif
> +  std::string arch_name;
>  
> -  if (sys_type == ARC_SYS_TYPE_ARCV2)
> +  /* Architecture names here must match the ones in
> +     ARCH_INFO_STRUCT in bfd/cpu-arc.c.  */
> +  if (features.isa == ARC_ISA_ARCV1 && features.reg_size == 4)
> +      arch_name = "arc:ARC700";
> +  else if (features.isa == ARC_ISA_ARCV2 && features.reg_size == 4)
> +      arch_name = "arc:ARCv2";
> +  else
>      {
> -      regnum = create_feature_arc_core_v2 (tdesc, regnum);
> -      regnum = create_feature_arc_aux_v2 (tdesc, regnum);
> +      std::string msg = string_printf
> +	("Cannot determine architecture: ISA=%d; bitness=%d",
> +	 features.isa, 8 * features.reg_size);
> +      gdb_assert_not_reached (msg.c_str ());
>      }
> -  else
> +
> +  set_tdesc_architecture (tdesc, arch_name.c_str ());
> +#endif
> +
> +  long regnum = 0;
> +
> +  switch (features.isa)
>      {
> -      regnum = create_feature_arc_core_arcompact (tdesc, regnum);
> -      regnum = create_feature_arc_aux_arcompact (tdesc, regnum);
> +    case ARC_ISA_ARCV1:
> +	  regnum = create_feature_arc_v1_core (tdesc, regnum);
> +	  regnum = create_feature_arc_v1_aux (tdesc, regnum);
> +	  break;
> +    case ARC_ISA_ARCV2:
> +	  regnum = create_feature_arc_v2_core (tdesc, regnum);
> +	  regnum = create_feature_arc_v2_aux (tdesc, regnum);
> +	  break;
> +    default:
> +	  std::string msg = string_printf
> +	    ("Cannot choose target description XML: %d", features.isa);
> +	  gdb_assert_not_reached (msg.c_str ());

The code in the cases here has two too many indentation level.

>      }
>  
>    return tdesc;
>  }
> +
> +#ifndef GDBSERVER
> +
> +/* Wrapper used by std::unordered_map to generate hash for features set.  */
> +struct arc_gdbarch_features_hasher
> +{
> +  std::size_t
> +  operator() (const arc_gdbarch_features &features) const noexcept
> +  {
> +    return features.hash ();
> +  }
> +};
> +
> +/* Cache of previously created target descriptions, indexed by the hash
> +   of the features set used to create them.  */
> +static std::unordered_map<arc_gdbarch_features,
> +			  const target_desc_up,
> +			  arc_gdbarch_features_hasher> arc_tdesc_cache;
> +
> +/* See arch/arc.h.  */
> +
> +const target_desc *
> +arc_lookup_target_description (const struct arc_gdbarch_features &features)
> +{
> +  /* Lookup in the cache first.  If found, return the pointer from the
> +     "target_desc_up" type which is a "unique_ptr".  This should be fine
> +     as the "arc_tdesc_cache" will persist until GDB terminates.  */
> +  const auto it = arc_tdesc_cache.find (features);
> +  if (it != arc_tdesc_cache.end ())
> +    return it->second.get ();
> +
> +  target_desc *tdesc = arc_create_target_description (features);
> +
> +  /* Add the newly created target description to the repertoire.  */

Nice use of the word "repertoire" :).

> +  arc_tdesc_cache.emplace (features, tdesc);
> +
> +  return tdesc;
> +}
> +
> +#endif /* !GDBSERVER */
> diff --git a/gdb/arch/arc.h b/gdb/arch/arc.h
> index fd806ae7d34..4f01d92bf09 100644
> --- a/gdb/arch/arc.h
> +++ b/gdb/arch/arc.h
> @@ -20,29 +20,68 @@
>  
>  #include "gdbsupport/tdesc.h"
>  
> -/* Supported ARC system hardware types.  */
> -enum arc_sys_type
> +/* Supported ARC ISAs.  */
> +enum arc_isa
>  {
> -  ARC_SYS_TYPE_ARCOMPACT = 0,	  /* ARC600 or ARC700 */
> -  ARC_SYS_TYPE_ARCV2,		  /* ARC EM or ARC HS */
> -  ARC_SYS_TYPE_NUM
> +  ARC_ISA_ARCV1 = 1,  /* a.k.a. ARCompact (ARC600, ARC700)  */
> +  ARC_ISA_ARCV2	      /* such as ARC EM and ARC HS  */
>  };
>  
> -static inline const char *
> -arc_sys_type_to_str (const arc_sys_type type)
> +struct arc_gdbarch_features
>  {
> -  switch (type)
> -    {
> -    case ARC_SYS_TYPE_ARCOMPACT:
> -      return "ARC_SYS_TYPE_ARCOMPACT";
> -    case ARC_SYS_TYPE_ARCV2:
> -      return "ARC_SYS_TYPE_ARCV2";
> -    default:
> -      return "Invalid";
> -    }
> -}
> -
> -/* Create target description for the specified system type.  */
> -target_desc *arc_create_target_description (arc_sys_type sys_type);
> +  arc_gdbarch_features (int reg_size, arc_isa isa)
> +    : reg_size (reg_size), isa (isa)
> +  {}
> +
> +  /* Register size in bytes.  Possible values are 4, and 8.  A 0 indicates
> +     an uninitialised value.  */
> +  int reg_size;
> +
> +  /* See ARC_ISA enum.  */
> +  arc_isa isa;

I think these two fields could/should be const.

Simon

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 2/3] arc: Add hardware loop detection
  2020-07-23 19:35       ` [PATCH v4 2/3] arc: Add hardware loop detection Shahab Vahedi
@ 2020-08-01 14:53         ` Simon Marchi
  0 siblings, 0 replies; 86+ messages in thread
From: Simon Marchi @ 2020-08-01 14:53 UTC (permalink / raw)
  To: Shahab Vahedi, gdb-patches
  Cc: Shahab Vahedi, Tom Tromey, Anton Kolesov, Francois Bedard

This patch is also OK with these nits fixed.

On 2020-07-23 3:35 p.m., Shahab Vahedi wrote:
> diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
> index 0c7e045e54b..59e698bb18b 100644
> --- a/gdb/arc-tdep.c
> +++ b/gdb/arc-tdep.c
> @@ -2006,6 +2006,35 @@ arc_check_tdesc_feature (struct tdesc_arch_data *tdesc_data,
>    return true;
>  }
>  
> +/* Check for the existance of "lp_start" and "lp_end" in target description.
> +   If both are present, assume there is hardware loop support in the target.
> +   This can be improved by looking into "lpc_size" field of "isa_config"
> +   auxiliary register.  */
> +
> +static bool
> +arc_check_for_hw_loops (const struct target_desc *tdesc,
> +			struct tdesc_arch_data *data)
> +{
> +  const auto feature_aux = tdesc_find_feature (tdesc, ARC_AUX_FEATURE_NAME);
> +  const auto *aux_regset = determine_aux_reg_feature_set ();

To be consistent, I'd suggest using the star in both places or not use it in both places.

> +
> +  if (feature_aux == nullptr || aux_regset == nullptr)
> +    return false;

If a function (I'm thinking of determine_aux_reg_feature_set) can't (according to its contract)
return nullptr, don't check for nullptr, that's:

(1) unnecessary
(2) confusing, since by reading this code my mind goes searching for a reason why
    determine_aux_reg_feature_set might return nullptr

I suppose that tdesc_find_feature can return nullptr, if the feature is not present.

> diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
> index 6ca759a661d..e752348a262 100644
> --- a/gdb/arc-tdep.h
> +++ b/gdb/arc-tdep.h
> @@ -23,6 +23,7 @@
>  
>  /* Need disassemble_info.  */
>  #include "dis-asm.h"
> +#include "gdbarch.h"

I suppose that adding this is correct, as this file uses some things from gdbarch.h.

It's a change unrelated to the topic of this patch, so it's preferable to send it as
a separate patch, with its own explanation.

Simon


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 3/3] arc: Add GNU/Linux support for ARC
  2020-07-23 19:35       ` [PATCH v4 3/3] arc: Add GNU/Linux support for ARC Shahab Vahedi
@ 2020-08-01 15:01         ` Simon Marchi
  0 siblings, 0 replies; 86+ messages in thread
From: Simon Marchi @ 2020-08-01 15:01 UTC (permalink / raw)
  To: Shahab Vahedi, gdb-patches
  Cc: Anton Kolesov, Francois Bedard, Shahab Vahedi, Tom Tromey

This is OK, with the nits mentioned below fixed.

On 2020-07-23 3:35 p.m., Shahab Vahedi via Gdb-patches wrote:
> From: Anton Kolesov <Anton.Kolesov@synopsys.com>
> 
> ARC Linux targets differences from baremetal:
> 
> - No support for hardware single instruction stepping.
> - Different access rules to registers.
> - Use of another instruction for breakpoints.
> 
> v2: Changes after Tom's remarks [1]
>  arc-linux-tdep.c
>   - Use true/false instead of TRUE/FALSE.
>   - arc_linux_sw_breakpoint_from_kind (): Break long lines into two.
>   - arc_linux_sw_breakpoint_from_kind (): Remove starting blank line.
>   - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
>  arc-tdep.c
>   - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
>  gdb/configure.tgt
>   - arc*-*-linux*): Remove "build_gdbserver=yes".
> 
> v3: Changes after Simon's remarks [2]
>   arc-linux-tdep.c
>   - Use "return trap_size" instead of cryptic "return 2".
>   - Removed unnecessary curly braces.
>   - Removed "void" from "_initialize_arc_linux_tdep (void)".
> 
> [1] Tom's remarks
> https://sourceware.org/pipermail/gdb-patches/2020-April/167887.html
> 
> [2] Simon's remarks
> https://sourceware.org/pipermail/gdb-patches/2020-May/168513.html
> 
> 2020-07-22  Anton Kolesov  <anton.kolesov@synopsys.com>
> 
> 	* configure.tgt: ARC support for GNU/Linux.
> 	* Makefile.in (ALL_TARGET_OBJS): Likewise.
> 	* arc-linux-tdep.c: New file.
> 	* arc-tdep.h (ARC_STATUS32_L_MASK, ARC_STATUS32_DE_MASK): Declare.
> 	* arc-tdep.c (arc_write_pc): Use it.
> ---
>  gdb/Makefile.in      |   1 +
>  gdb/arc-linux-tdep.c | 283 +++++++++++++++++++++++++++++++++++++++++++
>  gdb/arc-tdep.c       |   3 +-
>  gdb/arc-tdep.h       |   5 +
>  gdb/configure.tgt    |   5 +
>  5 files changed, 295 insertions(+), 2 deletions(-)
>  create mode 100644 gdb/arc-linux-tdep.c
> 
> diff --git a/gdb/Makefile.in b/gdb/Makefile.in
> index 9d484457397..85304b9f549 100644
> --- a/gdb/Makefile.in
> +++ b/gdb/Makefile.in
> @@ -697,6 +697,7 @@ ALL_64_TARGET_OBS = \
>  # All other target-dependent objects files (used with --enable-targets=all).
>  ALL_TARGET_OBS = \
>  	aarch32-tdep.o \
> +	arc-linux-tdep.o \
>  	arc-tdep.o \
>  	arch/aarch32.o \
>  	arch/arc.o \
> diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
> new file mode 100644
> index 00000000000..be24a072881
> --- /dev/null
> +++ b/gdb/arc-linux-tdep.c
> @@ -0,0 +1,283 @@
> +/* Target dependent code for GNU/Linux ARC.
> +
> +   Copyright 2020 Free Software Foundation, Inc.
> +
> +   This file is part of GDB.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +/* GDB header files.  */
> +#include "defs.h"
> +#include "linux-tdep.h"
> +#include "objfiles.h"
> +#include "opcode/arc.h"
> +#include "osabi.h"
> +#include "solib-svr4.h"
> +
> +/* ARC header files.  */
> +#include "opcodes/arc-dis.h"
> +#include "arc-tdep.h"
> +
> +/* Implement the "cannot_fetch_register" gdbarch method.  */
> +
> +static int
> +arc_linux_cannot_fetch_register (struct gdbarch *gdbarch, int regnum)
> +{
> +  /* Assume that register is readable if it is unknown.  */
> +  switch (regnum)
> +    {
> +    case ARC_ILINK_REGNUM:
> +    case ARC_RESERVED_REGNUM:
> +    case ARC_LIMM_REGNUM:
> +      return true;
> +    case ARC_R30_REGNUM:
> +    case ARC_R58_REGNUM:
> +    case ARC_R59_REGNUM:
> +      return !arc_mach_is_arcv2 (gdbarch);
> +    }
> +  if (regnum > ARC_BLINK_REGNUM && regnum < ARC_LP_COUNT_REGNUM)
> +    return true;
> +  return false;

Not very important, but it would be more idiomatic to write:

  return regnum > ARC_BLINK_REGNUM && regnum < ARC_LP_COUNT_REGNUM;

> +}
> +
> +/* Implement the "cannot_store_register" gdbarch method.  */
> +
> +static int
> +arc_linux_cannot_store_register (struct gdbarch *gdbarch, int regnum)
> +{
> +  /* Assume that register is writable if it is unknown.  */
> +  switch (regnum)
> +    {
> +    case ARC_ILINK_REGNUM:
> +    case ARC_RESERVED_REGNUM:
> +    case ARC_LIMM_REGNUM:
> +    case ARC_PCL_REGNUM:
> +      return true;
> +    case ARC_R30_REGNUM:
> +    case ARC_R58_REGNUM:
> +    case ARC_R59_REGNUM:
> +      return !arc_mach_is_arcv2 (gdbarch);
> +    }
> +  if (regnum > ARC_BLINK_REGNUM && regnum < ARC_LP_COUNT_REGNUM)
> +    return true;
> +  return false;

Same here.

> +}
> +
> +/* For ARC Linux, breakpoint uses the 16-bit TRAP_S 1 instruction, which

It would read better if "breakpoint" was plural, so "breakpoints use the...".

> +   is 0x3e78 (little endian) or 0x783e (big endian).  */
> +
> +static const gdb_byte arc_linux_trap_s_be[] = { 0x78, 0x3e };
> +static const gdb_byte arc_linux_trap_s_le[] = { 0x3e, 0x78 };
> +static const int trap_size = 2;   /* Number of bytes to insert "trap".  */
> +
> +/* Implement the "breakpoint_kind_from_pc" gdbarch method.  */
> +
> +static int
> +arc_linux_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
> +{
> +  return trap_size;
> +}
> +
> +/* Implement the "sw_breakpoint_from_kind" gdbarch method.  */
> +
> +static const gdb_byte *
> +arc_linux_sw_breakpoint_from_kind (struct gdbarch *gdbarch,
> +				   int kind, int *size)
> +{
> +  *size = kind;
> +  return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
> +	  ? arc_linux_trap_s_be
> +	  : arc_linux_trap_s_le);
> +}
> +
> +/* Implement the "software_single_step" gdbarch method.  */
> +
> +static std::vector<CORE_ADDR>
> +arc_linux_software_single_step (struct regcache *regcache)
> +{
> +  struct gdbarch *gdbarch = regcache->arch ();
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  struct disassemble_info di = arc_disassemble_info (gdbarch);
> +
> +  /* Read current instruction.  */
> +  struct arc_instruction curr_insn;
> +  arc_insn_decode (regcache_read_pc (regcache), &di, arc_delayed_print_insn,
> +		   &curr_insn);
> +  CORE_ADDR next_pc = arc_insn_get_linear_next_pc (curr_insn);
> +
> +  std::vector<CORE_ADDR> next_pcs;
> +
> +  /* For instructions with delay slots, the fall thru is not the
> +     instruction immediately after the current instruction, but the one
> +     after that.  */
> +  if (curr_insn.has_delay_slot)
> +    {
> +      struct arc_instruction next_insn;
> +      arc_insn_decode (next_pc, &di, arc_delayed_print_insn, &next_insn);
> +      next_pcs.push_back (arc_insn_get_linear_next_pc (next_insn));
> +    }
> +  else
> +    next_pcs.push_back (next_pc);
> +
> +  ULONGEST status32;
> +  regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
> +				 &status32);
> +
> +  if (curr_insn.is_control_flow)
> +    {
> +      CORE_ADDR branch_pc = arc_insn_get_branch_target (curr_insn);
> +      if (branch_pc != next_pc)
> +	next_pcs.push_back (branch_pc);
> +    }
> +  /* Is current instruction the last in a loop body?  */
> +  else if (tdep->has_hw_loops)
> +    {
> +      /* If STATUS32.L is 1, then ZD-loops are disabled.  */
> +      if ((status32 & ARC_STATUS32_L_MASK) == 0)
> +	{
> +	  ULONGEST lp_end, lp_start, lp_count;
> +	  regcache_cooked_read_unsigned (regcache, ARC_LP_START_REGNUM,
> +					 &lp_start);
> +	  regcache_cooked_read_unsigned (regcache, ARC_LP_END_REGNUM, &lp_end);
> +	  regcache_cooked_read_unsigned (regcache, ARC_LP_COUNT_REGNUM,
> +					 &lp_count);
> +
> +	  if (arc_debug)
> +	    {
> +	      debug_printf ("arc-linux: lp_start = %s, lp_end = %s, "
> +			    "lp_count = %s, next_pc = %s\n",
> +			    paddress (gdbarch, lp_start),
> +			    paddress (gdbarch, lp_end),
> +			    pulongest (lp_count),
> +			    paddress (gdbarch, next_pc));
> +	    }
> +
> +	  if (next_pc == lp_end && lp_count > 1)
> +	    {
> +	      /* The instruction is in effect a jump back to the start of
> +		 the loop.  */
> +	      next_pcs.push_back (lp_start);
> +	    }
> +
> +	}

Remove empty line above.

> +    }
> +
> +  /* Is this a delay slot?  Then next PC is in BTA register.  */
> +  if ((status32 & ARC_STATUS32_DE_MASK) != 0)
> +    {
> +      ULONGEST bta;
> +      regcache_cooked_read_unsigned (regcache, ARC_BTA_REGNUM, &bta);
> +      next_pcs.push_back (bta);
> +    }
> +
> +  return next_pcs;
> +}
> +
> +/* Implement the "skip_solib_resolver" gdbarch method.
> +
> +   See glibc_skip_solib_resolver for details.  */
> +
> +static CORE_ADDR
> +arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
> +{
> +  /* For uClibc 0.9.26+.
> +
> +     An unresolved PLT entry points to "__dl_linux_resolve", which calls
> +     "_dl_linux_resolver" to do the resolving and then eventually jumps to
> +     the function.
> +
> +     So we look for the symbol `_dl_linux_resolver', and if we are there,
> +     gdb sets a breakpoint at the return address, and continues.  */
> +  struct bound_minimal_symbol resolver =
> +    lookup_minimal_symbol ("_dl_linux_resolver", NULL, NULL);

Put the equal sign on the next line:

  struct bound_minimal_symbol resolver
    = lookup_minimal_symbol ("_dl_linux_resolver", NULL, NULL);

Simon

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 0/3] arc: Add GNU/Linux support
  2020-07-23 19:35     ` [PATCH v4 0/3] arc: Add GNU/Linux support Shahab Vahedi
                         ` (2 preceding siblings ...)
  2020-07-23 19:35       ` [PATCH v4 3/3] arc: Add GNU/Linux support for ARC Shahab Vahedi
@ 2020-08-01 23:31       ` Simon Marchi
  2020-08-04  7:59         ` Shahab Vahedi
  3 siblings, 1 reply; 86+ messages in thread
From: Simon Marchi @ 2020-08-01 23:31 UTC (permalink / raw)
  To: Shahab Vahedi, gdb-patches
  Cc: Anton Kolesov, Francois Bedard, Shahab Vahedi, Tom Tromey

On 2020-07-23 3:35 p.m., Shahab Vahedi via Gdb-patches wrote:
> This is a series of changes to enable debugging ARC targets that are
> running on a native ARC GNU/Linux system.  Since this heavily relies
> on XML target descriptions provided for different targets, that piece
> of code has been refactored to accommodate flexible register support.
> 
> After this series, there will come patches that add support for
> native ARC gdb/gdbserver.

Btw, I think it would make sense to add an entry in the arch section of
the MAINTAINERS file for ARC, don't you think?  If you plan on sticking
around, I think it would make sense to have you there.

Simon

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 0/3] arc: Add GNU/Linux support
  2020-08-01 23:31       ` [PATCH v4 0/3] arc: Add GNU/Linux support Simon Marchi
@ 2020-08-04  7:59         ` Shahab Vahedi
  2020-08-04 12:42           ` Simon Marchi
  0 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-04  7:59 UTC (permalink / raw)
  To: Simon Marchi
  Cc: gdb-patches, Anton Kolesov, Francois Bedard, Shahab Vahedi, Tom Tromey

Hi Simon,

On Sat, Aug 01, 2020 at 07:31:12PM -0400, Simon Marchi wrote:
> Btw, I think it would make sense to add an entry in the arch section of
> the MAINTAINERS file for ARC, don't you think?  If you plan on sticking
> around, I think it would make sense to have you there.

I already have added my info to "gdb/MAINTAINERS" file.  Is that what
you mean?


Cheers,
Shahab


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v5 0/4] arc: Add GNU/Linux support
  2020-03-26 12:52 [PATCH 0/4] arc: Add GNU/Linux support Shahab Vahedi
                   ` (6 preceding siblings ...)
  2020-04-28 16:04 ` [PATCH v2 " Shahab Vahedi
@ 2020-08-04  8:57 ` Shahab Vahedi
  2020-08-04  8:57   ` [PATCH v5 1/4] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
                     ` (4 more replies)
  2020-08-05 11:09 ` [PATCH v6 " Shahab Vahedi
  2020-08-25 15:47 ` [PUSHED " Shahab Vahedi
  9 siblings, 5 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-04  8:57 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Eli Zaretskii, Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

This is a series of changes to enable debugging ARC targets that are
running on a native ARC GNU/Linux system.  Since this heavily relies
on XML target descriptions provided for different targets, that piece
of code has been refactored to accommodate flexible register support.

After this series, there will come patches that add support for
native ARC gdb/gdbserver.

v5: Changes per remarks of Simon [1] and on my own (documentation and tests)
 arc.h:
  - Made "reg_size" and "isa" constant in "arc_gdbarch_features".
 arc.c:
  - Fix some malformed indentations.
 arc-tdep.h:
  - Inclusion of "gdbarch.h" has its own patch now.
 arc-tdep.c
  - Use "nullptr" instead of "NULL".
  - Remove unnecessary "break"s after "return"s.
  - "determine_core_reg_feature_set" will assert if wrong input is given.
  - Removed dangling comment.
  - Replaced "const auto *" with "const auto" to be consistent.
  - in "arc_check_for_hw_loops()": No "nullptr" check for "aux_regset".
 arc-linux-tdep.c
  - Remove unnecessary empty lines.
  - Replace "breakpoint uses" with "breakpoints use" in a comment.
  - "return condition;" i.s.o. "if (condition) return true; else return false;"
 gdb.texinfo
  - Update documentation regarding the new feature files.
 arc-tdesc-cpu.xml
  - Use new feature names.

[1] Simon's remarks to v4 of the patches
https://sourceware.org/pipermail/gdb-patches/2020-July/170975.html
https://sourceware.org/pipermail/gdb-patches/2020-August/170993.html
https://sourceware.org/pipermail/gdb-patches/2020-August/170994.html

v4: Latest changes per remarks of Simon [2]
 arc-tdep.c
  - Surround "=" in 2 assignments with space.
  - Put the return type of "mach_type_to_arc_isa ()" on the first line.
  - Remove "inline" from "mach_type_to_arc_isa ()".
  - Add space between the "if" conditions for readability.
  - Use "featues.isa" instead of "features.reg_size" in one occurrence.
  - Make "arc_gdbarch_features_init" static
  - Rename "arc_gdbarch_features_init" to "arc_gdbarch_features_create".
  - Adapt "arc_gdbarch_features_create" to act as a constructor.
 arch/arc.c
  - Add a constructor for "arc_gdbarch_features".
  - Get rid of "ARC_ISA_NONE" now that there is a constructor.
 arch/arc.c
  - Use simple assignments (instead of append) for "architecture".
  - Use "string_sprintf ()".
  - Use "target_desc_up" in "arc_tdesc_cache" to avoid memory leakage.
 arc-linux-tdep.c
  - Two occurrences: compare "resolver.minsym" against "nullptr".
  

[2] [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring
https://sourceware.org/pipermail/gdb-patches/2020-July/170427.html

v3: Changes after Simon's remarks:
The XML files have reduced to minimal comprehensible set.
The code is adjusted to work with new reg sets and be platform agnostic.

v2: Changes after Tom's remarks:
 arc-tdep.c
  - arc_tdesc_init(): Use "ARC_{R58,R59}_REGNUM" to index "core_regs[]".
  - arc_gdbarch_init(): Use "xfree ()" instead of "XDELETE ()"
  - arc_gdbarch_init(): return "nullptr" instead of "NULL".
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 arc-linux-tdep.c
  - Use true/false instead of TRUE/FALSE.
  - arc_linux_sw_breakpoint_from_kind (): Break long lines into two.
  - arc_linux_sw_breakpoint_from_kind (): Remove starting blank line.
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 gdb/configure.tgt
  - arc*-*-linux*): Remove "build_gdbserver=yes".

Anton Kolesov (1):
  arc: Add GNU/Linux support for ARC

Shahab Vahedi (3):
  arc: Add ARCv2 XML target along with refactoring
  arc: Add inclusion of "gdbarch.h" in "arc-tdep.h"
  arc: Add hardware loop detection

 gdb/Makefile.in                               |   1 +
 gdb/arc-linux-tdep.c                          | 278 ++++++++
 gdb/arc-tdep.c                                | 651 +++++++++++-------
 gdb/arc-tdep.h                                |  27 +-
 gdb/arch/arc.c                                | 108 ++-
 gdb/arch/arc.h                                |  79 ++-
 gdb/configure.tgt                             |   5 +
 gdb/doc/gdb.texinfo                           |  76 +-
 gdb/features/Makefile                         |   8 +-
 .../arc/{aux-arcompact.c => v1-aux.c}         |   9 +-
 .../arc/{aux-arcompact.xml => v1-aux.xml}     |   7 +-
 .../arc/{core-arcompact.c => v1-core.c}       |   8 +-
 .../arc/{core-arcompact.xml => v1-core.xml}   |   4 +-
 gdb/features/arc/{aux-v2.c => v2-aux.c}       |   9 +-
 gdb/features/arc/{aux-v2.xml => v2-aux.xml}   |   5 +-
 gdb/features/arc/{core-v2.c => v2-core.c}     |   7 +-
 gdb/features/arc/{core-v2.xml => v2-core.xml} |   7 +-
 gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml      |   4 +-
 18 files changed, 938 insertions(+), 355 deletions(-)
 create mode 100644 gdb/arc-linux-tdep.c
 rename gdb/features/arc/{aux-arcompact.c => v1-aux.c} (73%)
 rename gdb/features/arc/{aux-arcompact.xml => v1-aux.xml} (80%)
 rename gdb/features/arc/{core-arcompact.c => v1-core.c} (87%)
 rename gdb/features/arc/{core-arcompact.xml => v1-core.xml} (92%)
 rename gdb/features/arc/{aux-v2.c => v2-aux.c} (76%)
 rename gdb/features/arc/{aux-v2.xml => v2-aux.xml} (86%)
 rename gdb/features/arc/{core-v2.c => v2-core.c} (91%)
 rename gdb/features/arc/{core-v2.xml => v2-core.xml} (90%)

-- 
2.28.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v5 1/4] arc: Add ARCv2 XML target along with refactoring
  2020-08-04  8:57 ` [PATCH v5 0/4] " Shahab Vahedi
@ 2020-08-04  8:57   ` Shahab Vahedi
  2020-08-04 13:08     ` Simon Marchi
  2020-08-04  8:57   ` [PATCH v5 2/4] arc: Add inclusion of "gdbarch.h" in "arc-tdep.h" Shahab Vahedi
                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-04  8:57 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Eli Zaretskii, Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

A few changes have been made to make the register support simpler,
more flexible and extendible.  The trigger for most of these changes
are the remarks [1] made earlier for v2 of this patch.  The noticeable
improvements are:

- The arc XML target features are placed under gdb/features/arc
- There are two cores (based on ISA) and one auxiliary feature:
  v1-core: ARC600, ARC601, ARC700
  v2-core: ARC EM, ARC HS
  aux: common in both
- The XML target features represent a minimalistic sane set of
  registers irrespective of application (baremetal or linux).
- A concept of "feature" class has been introduced in the code.
  The "feature" object is constructed from BFD and GDBARCH data.
  It contains necessary information (ISA and register size) to
  determine which XML target feature to use.
- A new structure (ARC_REGISTER_FEATURE) is added that allows
  providing index, names, and the necessity of registers. This
  simplifies the sanity checks and future extendibility.

The last two points were inspired from RiscV port.

[1]
https://sourceware.org/pipermail/gdb-patches/2020-May/168511.html

gdb/ChangeLog:

	* arch/arc.h
	  (arc_gdbarch_features): New class to stir the selection of target XML.
	  (arc_create_target_description): Use FEATURES to choose XML target.
	  (arc_lookup_target_description): Use arc_create_target_description
	  to create _new_ target descriptions or return the already created
	  ones if the FEATURES is the same.
	* arch/arc.c: Implementation of prototypes described above.
	* gdb/arc-tdep.h (arc_regnum enum): Add more registers.
	  (arc_gdbarch_features_init): Initialize the FEATURES struct.
	* arc-tdep.c (*_feature_name): Make feature names consistent.
	  (arc_register_feature): A new struct to hold information about
	  registers of a particular target/feature.
	  (arc_check_tdesc_feature): Check if XML provides registers in
	  compliance with ARC_REGISTER_FEATURE structs.
	  (arc_update_acc_reg_names): Add aliases for r58 and r59.
	  (determine_*_reg_feature_set): Which feature name to look for.
	  (arc_gdbarch_features_init): Given MACH and ABFD, initialize FEATURES.
	  (mach_type_to_arc_isa): Convert from a set of binutils machine types
	  to expected ISA enums to be used in arc_gdbarch_features structs.
	* features/Makefile (FEATURE_XMLFILES): Add new files.
	* gdb/features/arc/v1-aux.c: New file.
	* gdb/features/arc/v1-aux.xml: Likewise.
	* gdb/features/arc/v1-core.c: Likewise.
	* gdb/features/arc/v1-core.xml: Likewise.
	* gdb/features/arc/v2-aux.c: Likewise.
	* gdb/features/arc/v2-aux.xml: Likewise.
	* gdb/features/arc/v2-core.c: Likewise.
	* gdb/features/arc/v2-core.xml: Likewise.

gdb/doc/ChangeLog:

	* gdb.texinfo (Synopsys ARC): Update the documentation for ARC Features.

gdb/testsuite/ChangeLog:

	* gdb.arch/arc-tdesc-cpu.xml: Use new feature names.
---
 gdb/arc-tdep.c                                | 609 +++++++++++-------
 gdb/arc-tdep.h                                |  18 +-
 gdb/arch/arc.c                                | 108 +++-
 gdb/arch/arc.h                                |  79 ++-
 gdb/doc/gdb.texinfo                           |  69 +-
 gdb/features/Makefile                         |   8 +-
 .../arc/{aux-arcompact.c => v1-aux.c}         |   9 +-
 .../arc/{aux-arcompact.xml => v1-aux.xml}     |   7 +-
 .../arc/{core-arcompact.c => v1-core.c}       |   8 +-
 .../arc/{core-arcompact.xml => v1-core.xml}   |   4 +-
 gdb/features/arc/{aux-v2.c => v2-aux.c}       |   9 +-
 gdb/features/arc/{aux-v2.xml => v2-aux.xml}   |   5 +-
 gdb/features/arc/{core-v2.c => v2-core.c}     |   7 +-
 gdb/features/arc/{core-v2.xml => v2-core.xml} |   7 +-
 gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml      |   4 +-
 15 files changed, 602 insertions(+), 349 deletions(-)
 rename gdb/features/arc/{aux-arcompact.c => v1-aux.c} (73%)
 rename gdb/features/arc/{aux-arcompact.xml => v1-aux.xml} (80%)
 rename gdb/features/arc/{core-arcompact.c => v1-core.c} (87%)
 rename gdb/features/arc/{core-arcompact.xml => v1-core.xml} (92%)
 rename gdb/features/arc/{aux-v2.c => v2-aux.c} (76%)
 rename gdb/features/arc/{aux-v2.xml => v2-aux.xml} (86%)
 rename gdb/features/arc/{core-v2.c => v2-core.c} (91%)
 rename gdb/features/arc/{core-v2.xml => v2-core.xml} (90%)

diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 7e6d29c334b..3b79e0ee685 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -21,6 +21,7 @@
 /* GDB header files.  */
 #include "defs.h"
 #include "arch-utils.h"
+#include "elf-bfd.h"
 #include "disasm.h"
 #include "dwarf2/frame.h"
 #include "frame-base.h"
@@ -41,6 +42,7 @@
 
 /* Standard headers.  */
 #include <algorithm>
+#include <sstream>
 
 /* The frame unwind cache for ARC.  */
 
@@ -91,63 +93,201 @@ int arc_debug;
 
 static struct cmd_list_element *maintenance_print_arc_list = NULL;
 
-/* XML target description features.  */
-
-static const char core_v2_feature_name[] = "org.gnu.gdb.arc.core.v2";
-static const char
-  core_reduced_v2_feature_name[] = "org.gnu.gdb.arc.core-reduced.v2";
-static const char
-  core_arcompact_feature_name[] = "org.gnu.gdb.arc.core.arcompact";
-static const char aux_minimal_feature_name[] = "org.gnu.gdb.arc.aux-minimal";
-
-/* XML target description known registers.  */
-
-static const char *const core_v2_register_names[] = {
-  "r0", "r1", "r2", "r3",
-  "r4", "r5", "r6", "r7",
-  "r8", "r9", "r10", "r11",
-  "r12", "r13", "r14", "r15",
-  "r16", "r17", "r18", "r19",
-  "r20", "r21", "r22", "r23",
-  "r24", "r25", "gp", "fp",
-  "sp", "ilink", "r30", "blink",
-  "r32", "r33", "r34", "r35",
-  "r36", "r37", "r38", "r39",
-  "r40", "r41", "r42", "r43",
-  "r44", "r45", "r46", "r47",
-  "r48", "r49", "r50", "r51",
-  "r52", "r53", "r54", "r55",
-  "r56", "r57", "accl", "acch",
-  "lp_count", "reserved", "limm", "pcl",
+/* A set of registers that we expect to find in a tdesc_feature.  These
+   are used in ARC_TDESC_INIT when processing the target description.  */
+
+struct arc_register_feature
+{
+  /* Information for a single register.  */
+  struct register_info
+  {
+    /* The GDB register number for this register.  */
+    int regnum;
+
+    /* List of names for this register.  The first name in this list is the
+       preferred name, the name GDB will use when describing this register.  */
+    std::vector<const char *> names;
+
+    /* When true, this register must be present in this feature set.  */
+    bool required_p;
+  };
+
+  /* The name for this feature.  This is the name used to find this feature
+     within the target description.  */
+  const char *name;
+
+  /* List of all the registers that we expect to encounter in this register
+     set.  */
+  std::vector<struct register_info> registers;
 };
 
-static const char *const aux_minimal_register_names[] = {
-  "pc", "status32",
+static const char *ARC_CORE_FEATURE_NAME = "org.gnu.gdb.arc.core";
+static const char *ARC_AUX_FEATURE_NAME = "org.gnu.gdb.arc.aux";
+
+/* ARCv1 (ARC600, ARC601, ARC700) general core registers feature set.
+   See also arc_update_acc_reg_names() for "accl/acch" names.  */
+
+static struct arc_register_feature arc_v1_core_reg_feature =
+{
+  ARC_CORE_FEATURE_NAME,
+  {
+    { ARC_R0_REGNUM + 0, { "r0" }, true },
+    { ARC_R0_REGNUM + 1, { "r1" }, true },
+    { ARC_R0_REGNUM + 2, { "r2" }, true },
+    { ARC_R0_REGNUM + 3, { "r3" }, true },
+    { ARC_R0_REGNUM + 4, { "r4" }, false },
+    { ARC_R0_REGNUM + 5, { "r5" }, false },
+    { ARC_R0_REGNUM + 6, { "r6" }, false },
+    { ARC_R0_REGNUM + 7, { "r7" }, false },
+    { ARC_R0_REGNUM + 8, { "r8" }, false },
+    { ARC_R0_REGNUM + 9, { "r9" }, false },
+    { ARC_R0_REGNUM + 10, { "r10" }, true },
+    { ARC_R0_REGNUM + 11, { "r11" }, true },
+    { ARC_R0_REGNUM + 12, { "r12" }, true },
+    { ARC_R0_REGNUM + 13, { "r13" }, true },
+    { ARC_R0_REGNUM + 14, { "r14" }, true },
+    { ARC_R0_REGNUM + 15, { "r15" }, true },
+    { ARC_R0_REGNUM + 16, { "r16" }, false },
+    { ARC_R0_REGNUM + 17, { "r17" }, false },
+    { ARC_R0_REGNUM + 18, { "r18" }, false },
+    { ARC_R0_REGNUM + 19, { "r19" }, false },
+    { ARC_R0_REGNUM + 20, { "r20" }, false },
+    { ARC_R0_REGNUM + 21, { "r21" }, false },
+    { ARC_R0_REGNUM + 22, { "r22" }, false },
+    { ARC_R0_REGNUM + 23, { "r23" }, false },
+    { ARC_R0_REGNUM + 24, { "r24" }, false },
+    { ARC_R0_REGNUM + 25, { "r25" }, false },
+    { ARC_R0_REGNUM + 26, { "gp" }, true },
+    { ARC_R0_REGNUM + 27, { "fp" }, true },
+    { ARC_R0_REGNUM + 28, { "sp" }, true },
+    { ARC_R0_REGNUM + 29, { "ilink1" }, false },
+    { ARC_R0_REGNUM + 30, { "ilink2" }, false },
+    { ARC_R0_REGNUM + 31, { "blink" }, true },
+    { ARC_R0_REGNUM + 32, { "r32" }, false },
+    { ARC_R0_REGNUM + 33, { "r33" }, false },
+    { ARC_R0_REGNUM + 34, { "r34" }, false },
+    { ARC_R0_REGNUM + 35, { "r35" }, false },
+    { ARC_R0_REGNUM + 36, { "r36" }, false },
+    { ARC_R0_REGNUM + 37, { "r37" }, false },
+    { ARC_R0_REGNUM + 38, { "r38" }, false },
+    { ARC_R0_REGNUM + 39, { "r39" }, false },
+    { ARC_R0_REGNUM + 40, { "r40" }, false },
+    { ARC_R0_REGNUM + 41, { "r41" }, false },
+    { ARC_R0_REGNUM + 42, { "r42" }, false },
+    { ARC_R0_REGNUM + 43, { "r43" }, false },
+    { ARC_R0_REGNUM + 44, { "r44" }, false },
+    { ARC_R0_REGNUM + 45, { "r45" }, false },
+    { ARC_R0_REGNUM + 46, { "r46" }, false },
+    { ARC_R0_REGNUM + 47, { "r47" }, false },
+    { ARC_R0_REGNUM + 48, { "r48" }, false },
+    { ARC_R0_REGNUM + 49, { "r49" }, false },
+    { ARC_R0_REGNUM + 50, { "r50" }, false },
+    { ARC_R0_REGNUM + 51, { "r51" }, false },
+    { ARC_R0_REGNUM + 52, { "r52" }, false },
+    { ARC_R0_REGNUM + 53, { "r53" }, false },
+    { ARC_R0_REGNUM + 54, { "r54" }, false },
+    { ARC_R0_REGNUM + 55, { "r55" }, false },
+    { ARC_R0_REGNUM + 56, { "r56" }, false },
+    { ARC_R0_REGNUM + 57, { "r57" }, false },
+    { ARC_R0_REGNUM + 58, { "r58", "accl" }, false },
+    { ARC_R0_REGNUM + 59, { "r59", "acch" }, false },
+    { ARC_R0_REGNUM + 60, { "lp_count" }, false },
+    { ARC_R0_REGNUM + 61, { "reserved" }, false },
+    { ARC_R0_REGNUM + 62, { "limm" }, false },
+    { ARC_R0_REGNUM + 63, { "pcl" }, true }
+  }
 };
 
-static const char *const core_arcompact_register_names[] = {
-  "r0", "r1", "r2", "r3",
-  "r4", "r5", "r6", "r7",
-  "r8", "r9", "r10", "r11",
-  "r12", "r13", "r14", "r15",
-  "r16", "r17", "r18", "r19",
-  "r20", "r21", "r22", "r23",
-  "r24", "r25", "gp", "fp",
-  "sp", "ilink1", "ilink2", "blink",
-  "r32", "r33", "r34", "r35",
-  "r36", "r37", "r38", "r39",
-  "r40", "r41", "r42", "r43",
-  "r44", "r45", "r46", "r47",
-  "r48", "r49", "r50", "r51",
-  "r52", "r53", "r54", "r55",
-  "r56", "r57", "r58", "r59",
-  "lp_count", "reserved", "limm", "pcl",
+/* ARCv2 (ARCHS) general core registers feature set.  See also
+   arc_update_acc_reg_names() for "accl/acch" names.  */
+
+static struct arc_register_feature arc_v2_core_reg_feature =
+{
+  ARC_CORE_FEATURE_NAME,
+  {
+    { ARC_R0_REGNUM + 0, { "r0" }, true },
+    { ARC_R0_REGNUM + 1, { "r1" }, true },
+    { ARC_R0_REGNUM + 2, { "r2" }, true },
+    { ARC_R0_REGNUM + 3, { "r3" }, true },
+    { ARC_R0_REGNUM + 4, { "r4" }, false },
+    { ARC_R0_REGNUM + 5, { "r5" }, false },
+    { ARC_R0_REGNUM + 6, { "r6" }, false },
+    { ARC_R0_REGNUM + 7, { "r7" }, false },
+    { ARC_R0_REGNUM + 8, { "r8" }, false },
+    { ARC_R0_REGNUM + 9, { "r9" }, false },
+    { ARC_R0_REGNUM + 10, { "r10" }, true },
+    { ARC_R0_REGNUM + 11, { "r11" }, true },
+    { ARC_R0_REGNUM + 12, { "r12" }, true },
+    { ARC_R0_REGNUM + 13, { "r13" }, true },
+    { ARC_R0_REGNUM + 14, { "r14" }, true },
+    { ARC_R0_REGNUM + 15, { "r15" }, true },
+    { ARC_R0_REGNUM + 16, { "r16" }, false },
+    { ARC_R0_REGNUM + 17, { "r17" }, false },
+    { ARC_R0_REGNUM + 18, { "r18" }, false },
+    { ARC_R0_REGNUM + 19, { "r19" }, false },
+    { ARC_R0_REGNUM + 20, { "r20" }, false },
+    { ARC_R0_REGNUM + 21, { "r21" }, false },
+    { ARC_R0_REGNUM + 22, { "r22" }, false },
+    { ARC_R0_REGNUM + 23, { "r23" }, false },
+    { ARC_R0_REGNUM + 24, { "r24" }, false },
+    { ARC_R0_REGNUM + 25, { "r25" }, false },
+    { ARC_R0_REGNUM + 26, { "gp" }, true },
+    { ARC_R0_REGNUM + 27, { "fp" }, true },
+    { ARC_R0_REGNUM + 28, { "sp" }, true },
+    { ARC_R0_REGNUM + 29, { "ilink" }, false },
+    { ARC_R0_REGNUM + 30, { "r30" }, true },
+    { ARC_R0_REGNUM + 31, { "blink" }, true },
+    { ARC_R0_REGNUM + 32, { "r32" }, false },
+    { ARC_R0_REGNUM + 33, { "r33" }, false },
+    { ARC_R0_REGNUM + 34, { "r34" }, false },
+    { ARC_R0_REGNUM + 35, { "r35" }, false },
+    { ARC_R0_REGNUM + 36, { "r36" }, false },
+    { ARC_R0_REGNUM + 37, { "r37" }, false },
+    { ARC_R0_REGNUM + 38, { "r38" }, false },
+    { ARC_R0_REGNUM + 39, { "r39" }, false },
+    { ARC_R0_REGNUM + 40, { "r40" }, false },
+    { ARC_R0_REGNUM + 41, { "r41" }, false },
+    { ARC_R0_REGNUM + 42, { "r42" }, false },
+    { ARC_R0_REGNUM + 43, { "r43" }, false },
+    { ARC_R0_REGNUM + 44, { "r44" }, false },
+    { ARC_R0_REGNUM + 45, { "r45" }, false },
+    { ARC_R0_REGNUM + 46, { "r46" }, false },
+    { ARC_R0_REGNUM + 47, { "r47" }, false },
+    { ARC_R0_REGNUM + 48, { "r48" }, false },
+    { ARC_R0_REGNUM + 49, { "r49" }, false },
+    { ARC_R0_REGNUM + 50, { "r50" }, false },
+    { ARC_R0_REGNUM + 51, { "r51" }, false },
+    { ARC_R0_REGNUM + 52, { "r52" }, false },
+    { ARC_R0_REGNUM + 53, { "r53" }, false },
+    { ARC_R0_REGNUM + 54, { "r54" }, false },
+    { ARC_R0_REGNUM + 55, { "r55" }, false },
+    { ARC_R0_REGNUM + 56, { "r56" }, false },
+    { ARC_R0_REGNUM + 57, { "r57" }, false },
+    { ARC_R0_REGNUM + 58, { "r58", "accl" }, false },
+    { ARC_R0_REGNUM + 59, { "r59", "acch" }, false },
+    { ARC_R0_REGNUM + 60, { "lp_count" }, false },
+    { ARC_R0_REGNUM + 61, { "reserved" }, false },
+    { ARC_R0_REGNUM + 62, { "limm" }, false },
+    { ARC_R0_REGNUM + 63, { "pcl" }, true }
+  }
 };
 
-static char *arc_disassembler_options = NULL;
+/* The common auxiliary registers feature set.  The REGNUM field
+   must match the ARC_REGNUM enum in arc-tdep.h.  */
 
-/* Possible arc target descriptors.  */
-static struct target_desc *tdesc_arc_list[ARC_SYS_TYPE_NUM];
+static const struct arc_register_feature arc_common_aux_reg_feature =
+{
+  ARC_AUX_FEATURE_NAME,
+  {
+    { ARC_FIRST_AUX_REGNUM + 0, { "pc" }, true },
+    { ARC_FIRST_AUX_REGNUM + 1, { "status32" }, true },
+    { ARC_FIRST_AUX_REGNUM + 2, { "lp_start" }, false },
+    { ARC_FIRST_AUX_REGNUM + 3, { "lp_end" }, false },
+    { ARC_FIRST_AUX_REGNUM + 4, { "bta" }, false }
+  }
+};
+
+static char *arc_disassembler_options = NULL;
 
 /* Functions are sorted in the order as they are used in the
    _initialize_arc_tdep (), which uses the same order as gdbarch.h.  Static
@@ -1717,192 +1857,221 @@ static const struct frame_base arc_normal_base = {
   arc_frame_base_address
 };
 
-/* Initialize target description for the ARC.
-
-   Returns TRUE if input tdesc was valid and in this case it will assign TDESC
-   and TDESC_DATA output parameters.  */
-
-static bool
-arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
-		struct tdesc_arch_data **tdesc_data)
+static enum arc_isa
+mach_type_to_arc_isa (const unsigned long mach)
 {
-  if (arc_debug)
-    debug_printf ("arc: Target description initialization.\n");
-
-  const struct target_desc *tdesc_loc = info.target_desc;
+  switch (mach)
+    {
+    case bfd_mach_arc_arc600:
+    case bfd_mach_arc_arc601:
+    case bfd_mach_arc_arc700:
+      return ARC_ISA_ARCV1;
+    case bfd_mach_arc_arcv2:
+      return ARC_ISA_ARCV2;
+    default:
+	internal_error (__FILE__, __LINE__,
+			_("unknown machine id %lu"), mach);
+    }
+}
 
-  /* Depending on whether this is ARCompact or ARCv2 we will assign
-     different default registers sets (which will differ in exactly two core
-     registers).  GDB will also refuse to accept register feature from invalid
-     ISA - v2 features can be used only with v2 ARChitecture.  We read
-     bfd_arch_info, which looks like to be a safe bet here, as it looks like it
-     is always initialized even when we don't pass any elf file to GDB at all
-     (it uses default arch in this case).  Also GDB will call this function
-     multiple times, and if XML target description file contains architecture
-     specifications, then GDB will set this architecture to info.bfd_arch_info,
-     overriding value from ELF file if they are different.  That means that,
-     where matters, this value is always our best guess on what CPU we are
-     debugging.  It has been noted that architecture specified in tdesc file
-     has higher precedence over ELF and even "set architecture" - that is,
-     using "set architecture" command will have no effect when tdesc has "arch"
-     tag.  */
-  /* Cannot use arc_mach_is_arcv2 (), because gdbarch is not created yet.  */
-  const int is_arcv2 = (info.bfd_arch_info->mach == bfd_mach_arc_arcv2);
-  bool is_reduced_rf;
-  const char *const *core_regs;
-  const char *core_feature_name;
+/* Common construction code for ARC_GDBARCH_FEATURES struct.  If there
+   is no ABFD, then a FEATURE with default values is returned.  */
 
-  /* If target doesn't provide a description, use the default ones.  */
-  if (!tdesc_has_registers (tdesc_loc))
+static arc_gdbarch_features
+arc_gdbarch_features_create (const bfd *abfd, const unsigned long mach)
+{
+  /* Use 4 as a fallback value.  */
+  int reg_size = 4;
+
+  /* Try to guess the features parameters by looking at the binary to be
+     executed.  If the user is providing a binary that does not match the
+     target, then tough luck.  This is the last effort to makes sense of
+     what's going on.  */
+  if (abfd != nullptr && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
     {
-      if (is_arcv2)
-	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCV2);
+      unsigned char eclass = elf_elfheader (abfd)->e_ident[EI_CLASS];
+
+      if (eclass == ELFCLASS32)
+	reg_size = 4;
+      else if (eclass == ELFCLASS64)
+	reg_size = 8;
       else
-	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCOMPACT);
+	internal_error (__FILE__, __LINE__,
+			_("unknown ELF header class %d"), eclass);
     }
-  else
+
+  /* MACH from a bfd_arch_info struct is used here.  It should be a safe
+     bet, as it looks like the struct is always initialized even when we
+     don't pass any elf file to GDB at all (it uses default arch in that
+     case).  */
+  arc_isa isa = mach_type_to_arc_isa (mach);
+
+  return arc_gdbarch_features (reg_size, isa);
+}
+
+/* Based on the MACH value, determines which core register features set
+   must be used.  */
+
+static arc_register_feature *
+determine_core_reg_feature_set (const unsigned long mach)
+{
+  switch (mach_type_to_arc_isa (mach))
     {
-      if (arc_debug)
-	debug_printf ("arc: Using provided register set.\n");
+    case ARC_ISA_ARCV1:
+      return &arc_v1_core_reg_feature;
+    case ARC_ISA_ARCV2:
+      return &arc_v2_core_reg_feature;
+    default:
+      gdb_assert_not_reached
+        ("Unknown machine type to determine the core feature set.");
     }
-  gdb_assert (tdesc_loc != NULL);
-
-  /* Now we can search for base registers.  Core registers can be either full
-     or reduced.  Summary:
-
-     - core.v2 + aux-minimal
-     - core-reduced.v2 + aux-minimal
-     - core.arcompact + aux-minimal
-
-     NB: It is entirely feasible to have ARCompact with reduced core regs, but
-     we ignore that because GCC doesn't support that and at the same time
-     ARCompact is considered obsolete, so there is not much reason to support
-     that.  */
-  const struct tdesc_feature *feature
-    = tdesc_find_feature (tdesc_loc, core_v2_feature_name);
-  if (feature != NULL)
-    {
-      /* Confirm that register and architecture match, to prevent accidents in
-	 some situations.  This code will trigger an error if:
+}
 
-	 1. XML tdesc doesn't specify arch explicitly, registers are for arch
-	 X, but ELF specifies arch Y.
+/* At the moment, there is only 1 auxiliary register features set.
+   This is a place holder for future extendability.  */
 
-	 2. XML tdesc specifies arch X, but contains registers for arch Y.
+static const arc_register_feature *
+determine_aux_reg_feature_set ()
+{
+  return &arc_common_aux_reg_feature;
+}
 
-	 It will not protect from case where XML or ELF specify arch X,
-	 registers are for the same arch X, but the real target is arch Y.  To
-	 detect this case we need to check IDENTITY register.  */
-      if (!is_arcv2)
-	{
-	  arc_print (_("Error: ARC v2 target description supplied for "
-		       "non-ARCv2 target.\n"));
-	  return false;
-	}
+/* Update accumulator register names (ACCH/ACCL) for r58 and r59 in the
+   register sets.  The endianness determines the assignment:
 
-      is_reduced_rf = false;
-      core_feature_name = core_v2_feature_name;
-      core_regs = core_v2_register_names;
-    }
-  else
+        ,------.------.
+        | acch | accl |
+   ,----|------+------|
+   | LE | r59  | r58  |
+   | BE | r58  | r59  |
+   `----^------^------'  */
+
+static void
+arc_update_acc_reg_names (const int byte_order)
+{
+  const char *r58_alias
+    = byte_order == BFD_ENDIAN_LITTLE ? "accl" : "acch";
+  const char *r59_alias
+    = byte_order == BFD_ENDIAN_LITTLE ? "acch" : "accl";
+
+  /* Subscript 1 must be OK because those registers have 2 names.  */
+  arc_v1_core_reg_feature.registers[ARC_R58_REGNUM].names[1] = r58_alias;
+  arc_v1_core_reg_feature.registers[ARC_R59_REGNUM].names[1] = r59_alias;
+  arc_v2_core_reg_feature.registers[ARC_R58_REGNUM].names[1] = r58_alias;
+  arc_v2_core_reg_feature.registers[ARC_R59_REGNUM].names[1] = r59_alias;
+}
+
+/* Go through all the registers in REG_SET and check if they exist
+   in FEATURE.  The TDESC_DATA is updated with the register number
+   in REG_SET if it is found in the feature.  If a required register
+   is not found, this function returns false.  */
+
+static bool
+arc_check_tdesc_feature (struct tdesc_arch_data *tdesc_data,
+			 const struct tdesc_feature *feature,
+			 const struct arc_register_feature *reg_set)
+{
+  for (const auto &reg : reg_set->registers)
     {
-      feature = tdesc_find_feature (tdesc_loc, core_reduced_v2_feature_name);
-      if (feature != NULL)
+      bool found = false;
+
+      for (const char *name : reg.names)
 	{
-	  if (!is_arcv2)
-	    {
-	      arc_print (_("Error: ARC v2 target description supplied for "
-			   "non-ARCv2 target.\n"));
-	      return false;
-	    }
+	  found
+	    = tdesc_numbered_register (feature, tdesc_data, reg.regnum, name);
 
-	  is_reduced_rf = true;
-	  core_feature_name = core_reduced_v2_feature_name;
-	  core_regs = core_v2_register_names;
+	  if (found)
+	    break;
 	}
-      else
+
+      if (!found && reg.required_p)
 	{
-	  feature = tdesc_find_feature (tdesc_loc,
-					core_arcompact_feature_name);
-	  if (feature != NULL)
-	    {
-	      if (is_arcv2)
-		{
-		  arc_print (_("Error: ARCompact target description supplied "
-			       "for non-ARCompact target.\n"));
-		  return false;
-		}
-
-	      is_reduced_rf = false;
-	      core_feature_name = core_arcompact_feature_name;
-	      core_regs = core_arcompact_register_names;
-	    }
-	  else
+	  std::ostringstream reg_names;
+	  for (std::size_t i = 0; i < reg.names.size(); ++i)
 	    {
-	      arc_print (_("Error: Couldn't find core register feature in "
-			   "supplied target description."));
-	      return false;
+	      if (i == 0)
+		reg_names << "'" << reg.names[0] << "'";
+	      else
+		reg_names << " or '" << reg.names[0] << "'";
 	    }
+	  arc_print (_("Error: Cannot find required register(s) %s "
+		       "in feature '%s'.\n"), reg_names.str ().c_str (),
+		       feature->name.c_str ());
+	  return false;
 	}
     }
 
-  struct tdesc_arch_data *tdesc_data_loc = tdesc_data_alloc ();
+  return true;
+}
 
-  gdb_assert (feature != NULL);
-  int valid_p = 1;
+/* Initialize target description for the ARC.
 
-  for (int i = 0; i <= ARC_LAST_CORE_REGNUM; i++)
+   Returns true if input TDESC was valid and in this case it will assign TDESC
+   and TDESC_DATA output parameters.  */
+
+static bool
+arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
+		struct tdesc_arch_data **tdesc_data)
+{
+  const struct target_desc *tdesc_loc = info.target_desc;
+  if (arc_debug)
+    debug_printf ("arc: Target description initialization.\n");
+
+  /* If target doesn't provide a description, use the default ones.  */
+  if (!tdesc_has_registers (tdesc_loc))
     {
-      /* If rf16, then skip extra registers.  */
-      if (is_reduced_rf && ((i >= ARC_R4_REGNUM && i <= ARC_R9_REGNUM)
-			    || (i >= ARC_R16_REGNUM && i <= ARC_R25_REGNUM)))
-	continue;
-
-      valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i,
-					 core_regs[i]);
-
-      /* - Ignore errors in extension registers - they are optional.
-	 - Ignore missing ILINK because it doesn't make sense for Linux.
-	 - Ignore missing ILINK2 when architecture is ARCompact, because it
-	 doesn't make sense for Linux targets.
-
-	 In theory those optional registers should be in separate features, but
-	 that would create numerous but tiny features, which looks like an
-	 overengineering of a rather simple task.  */
-      if (!valid_p && (i <= ARC_SP_REGNUM || i == ARC_BLINK_REGNUM
-		       || i == ARC_LP_COUNT_REGNUM || i == ARC_PCL_REGNUM
-		       || (i == ARC_R30_REGNUM && is_arcv2)))
-	{
-	  arc_print (_("Error: Cannot find required register `%s' in "
-		       "feature `%s'.\n"), core_regs[i], core_feature_name);
-	  tdesc_data_cleanup (tdesc_data_loc);
-	  return false;
-	}
+      arc_gdbarch_features features
+	= arc_gdbarch_features_create (info.abfd,
+				       info.bfd_arch_info->mach);
+      tdesc_loc = arc_lookup_target_description (features);
     }
+  gdb_assert (tdesc_loc != nullptr);
 
-  /* Mandatory AUX registers are intentionally few and are common between
-     ARCompact and ARC v2, so same code can be used for both.  */
-  feature = tdesc_find_feature (tdesc_loc, aux_minimal_feature_name);
-  if (feature == NULL)
+  if (arc_debug)
+    debug_printf ("arc: Have got a target description\n");
+
+  const struct tdesc_feature *feature_core
+    = tdesc_find_feature (tdesc_loc, ARC_CORE_FEATURE_NAME);
+  const struct tdesc_feature *feature_aux
+    = tdesc_find_feature (tdesc_loc, ARC_AUX_FEATURE_NAME);
+
+  if (feature_core == nullptr)
     {
-      arc_print (_("Error: Cannot find required feature `%s' in supplied "
-		   "target description.\n"), aux_minimal_feature_name);
-      tdesc_data_cleanup (tdesc_data_loc);
+      arc_print (_("Error: Cannot find required feature '%s' in supplied "
+		   "target description.\n"), ARC_CORE_FEATURE_NAME);
       return false;
     }
 
-  for (int i = ARC_FIRST_AUX_REGNUM; i <= ARC_LAST_AUX_REGNUM; i++)
+  if (feature_aux == nullptr)
     {
-      const char *name = aux_minimal_register_names[i - ARC_FIRST_AUX_REGNUM];
-      valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i, name);
-      if (!valid_p)
-	{
-	  arc_print (_("Error: Cannot find required register `%s' "
-		       "in feature `%s'.\n"),
-		     name, tdesc_feature_name (feature));
-	  tdesc_data_cleanup (tdesc_data_loc);
-	  return false;
-	}
+      arc_print (_("Error: Cannot find required feature '%s' in supplied "
+		   "target description.\n"), ARC_AUX_FEATURE_NAME);
+      return false;
+    }
+
+  const auto arc_core_reg_feature
+    = determine_core_reg_feature_set (info.bfd_arch_info->mach);
+  const auto arc_aux_reg_feature
+    = determine_aux_reg_feature_set ();
+
+  struct tdesc_arch_data *tdesc_data_loc = tdesc_data_alloc ();
+
+  arc_update_acc_reg_names (info.byte_order);
+
+  bool valid_p = arc_check_tdesc_feature (tdesc_data_loc,
+					  feature_core,
+					  arc_core_reg_feature);
+
+  valid_p &= arc_check_tdesc_feature (tdesc_data_loc,
+				      feature_aux,
+				      arc_aux_reg_feature);
+
+  if (!valid_p)
+    {
+      if (arc_debug)
+        debug_printf ("arc: Target description is not valid\n");
+      tdesc_data_cleanup (tdesc_data_loc);
+      return false;
     }
 
   *tdesc = tdesc_loc;
@@ -2131,38 +2300,6 @@ dump_arc_instruction_command (const char *args, int from_tty)
   arc_insn_dump (insn);
 }
 
-/* See arc-tdep.h.  */
-
-const target_desc *
-arc_read_description (arc_sys_type sys_type)
-{
-  if (arc_debug)
-    debug_printf ("arc: Reading target description for \"%s\".\n",
-		  arc_sys_type_to_str (sys_type));
-
-  gdb_assert ((sys_type >= 0) && (sys_type < ARC_SYS_TYPE_NUM));
-  struct target_desc *tdesc = tdesc_arc_list[sys_type];
-
-  if (tdesc == nullptr)
-    {
-      tdesc = arc_create_target_description (sys_type);
-      tdesc_arc_list[sys_type] = tdesc;
-
-      if (arc_debug)
-	{
-	  const char *arch = tdesc_architecture_name (tdesc);
-	  const char *abi = tdesc_osabi_name (tdesc);
-	  arch = arch != NULL ? arch : "";
-	  abi = abi != NULL ? abi : "";
-	  debug_printf ("arc: Created target description for "
-			"\"%s\": arch=\"%s\", ABI=\"%s\"\n",
-			arc_sys_type_to_str (sys_type), arch, abi);
-	}
-    }
-
-  return tdesc;
-}
-
 void _initialize_arc_tdep ();
 void
 _initialize_arc_tdep ()
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index d72332c7638..6ca759a661d 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -35,7 +35,6 @@ enum arc_regnum
   {
     /* Core registers.  */
     ARC_R0_REGNUM = 0,
-    ARC_FIRST_CORE_REGNUM = ARC_R0_REGNUM,
     ARC_R1_REGNUM = 1,
     ARC_R4_REGNUM = 4,
     ARC_R7_REGNUM = 7,
@@ -54,6 +53,9 @@ enum arc_regnum
     ARC_R30_REGNUM,
     /* Return address from function.  */
     ARC_BLINK_REGNUM,
+    /* Accumulator registers.  */
+    ARC_R58_REGNUM = 58,
+    ARC_R59_REGNUM,
     /* Zero-delay loop counter.  */
     ARC_LP_COUNT_REGNUM = 60,
     /* Reserved register number.  There should never be a register with such
@@ -69,14 +71,21 @@ enum arc_regnum
     /* Program counter, aligned to 4-bytes, read-only.  */
     ARC_PCL_REGNUM,
     ARC_LAST_CORE_REGNUM = ARC_PCL_REGNUM,
+
     /* AUX registers.  */
     /* Actual program counter.  */
     ARC_PC_REGNUM,
     ARC_FIRST_AUX_REGNUM = ARC_PC_REGNUM,
     /* Status register.  */
     ARC_STATUS32_REGNUM,
-    ARC_LAST_REGNUM = ARC_STATUS32_REGNUM,
-    ARC_LAST_AUX_REGNUM = ARC_STATUS32_REGNUM,
+    /* Zero-delay loop start instruction.  */
+    ARC_LP_START_REGNUM,
+    /* Zero-delay loop next-after-last instruction.  */
+    ARC_LP_END_REGNUM,
+    /* Branch target address.  */
+    ARC_BTA_REGNUM,
+    ARC_LAST_AUX_REGNUM = ARC_BTA_REGNUM,
+    ARC_LAST_REGNUM = ARC_LAST_AUX_REGNUM,
 
     /* Additional ABI constants.  */
     ARC_FIRST_ARG_REGNUM = ARC_R0_REGNUM,
@@ -164,7 +173,4 @@ CORE_ADDR arc_insn_get_branch_target (const struct arc_instruction &insn);
 
 CORE_ADDR arc_insn_get_linear_next_pc (const struct arc_instruction &insn);
 
-/* Get the correct ARC target description for the given system type.  */
-const target_desc *arc_read_description (arc_sys_type sys_type);
-
 #endif /* ARC_TDEP_H */
diff --git a/gdb/arch/arc.c b/gdb/arch/arc.c
index 9552b4aff97..8e126ca5a82 100644
--- a/gdb/arch/arc.c
+++ b/gdb/arch/arc.c
@@ -17,42 +17,106 @@
 
 
 #include "gdbsupport/common-defs.h"
-#include <stdlib.h>
-
 #include "arc.h"
+#include <stdlib.h>
+#include <unordered_map>
+#include <string>
 
 /* Target description features.  */
-#include "features/arc/core-v2.c"
-#include "features/arc/aux-v2.c"
-#include "features/arc/core-arcompact.c"
-#include "features/arc/aux-arcompact.c"
+#include "features/arc/v1-core.c"
+#include "features/arc/v1-aux.c"
+#include "features/arc/v2-core.c"
+#include "features/arc/v2-aux.c"
 
-/* See arc.h.  */
+#ifndef GDBSERVER
+#define STATIC_IN_GDB static
+#else
+#define STATIC_IN_GDB
+#endif
 
-target_desc *
-arc_create_target_description (arc_sys_type sys_type)
+STATIC_IN_GDB target_desc *
+arc_create_target_description (const struct arc_gdbarch_features &features)
 {
+  /* Create a new target description.  */
   target_desc *tdesc = allocate_target_description ();
 
-  long regnum = 0;
-
 #ifndef IN_PROCESS_AGENT
-  if (sys_type == ARC_SYS_TYPE_ARCV2)
-    set_tdesc_architecture (tdesc, "arc:ARCv2");
-  else
-    set_tdesc_architecture (tdesc, "arc:ARC700");
-#endif
+  std::string arch_name;
 
-  if (sys_type == ARC_SYS_TYPE_ARCV2)
+  /* Architecture names here must match the ones in
+     ARCH_INFO_STRUCT in bfd/cpu-arc.c.  */
+  if (features.isa == ARC_ISA_ARCV1 && features.reg_size == 4)
+      arch_name = "arc:ARC700";
+  else if (features.isa == ARC_ISA_ARCV2 && features.reg_size == 4)
+      arch_name = "arc:ARCv2";
+  else
     {
-      regnum = create_feature_arc_core_v2 (tdesc, regnum);
-      regnum = create_feature_arc_aux_v2 (tdesc, regnum);
+      std::string msg = string_printf
+	("Cannot determine architecture: ISA=%d; bitness=%d",
+	 features.isa, 8 * features.reg_size);
+      gdb_assert_not_reached (msg.c_str ());
     }
-  else
+
+  set_tdesc_architecture (tdesc, arch_name.c_str ());
+#endif
+
+  long regnum = 0;
+
+  switch (features.isa)
     {
-      regnum = create_feature_arc_core_arcompact (tdesc, regnum);
-      regnum = create_feature_arc_aux_arcompact (tdesc, regnum);
+    case ARC_ISA_ARCV1:
+      regnum = create_feature_arc_v1_core (tdesc, regnum);
+      regnum = create_feature_arc_v1_aux (tdesc, regnum);
+      break;
+    case ARC_ISA_ARCV2:
+      regnum = create_feature_arc_v2_core (tdesc, regnum);
+      regnum = create_feature_arc_v2_aux (tdesc, regnum);
+      break;
+    default:
+      std::string msg = string_printf
+	("Cannot choose target description XML: %d", features.isa);
+      gdb_assert_not_reached (msg.c_str ());
     }
 
   return tdesc;
 }
+
+#ifndef GDBSERVER
+
+/* Wrapper used by std::unordered_map to generate hash for features set.  */
+struct arc_gdbarch_features_hasher
+{
+  std::size_t
+  operator() (const arc_gdbarch_features &features) const noexcept
+  {
+    return features.hash ();
+  }
+};
+
+/* Cache of previously created target descriptions, indexed by the hash
+   of the features set used to create them.  */
+static std::unordered_map<arc_gdbarch_features,
+			  const target_desc_up,
+			  arc_gdbarch_features_hasher> arc_tdesc_cache;
+
+/* See arch/arc.h.  */
+
+const target_desc *
+arc_lookup_target_description (const struct arc_gdbarch_features &features)
+{
+  /* Lookup in the cache first.  If found, return the pointer from the
+     "target_desc_up" type which is a "unique_ptr".  This should be fine
+     as the "arc_tdesc_cache" will persist until GDB terminates.  */
+  const auto it = arc_tdesc_cache.find (features);
+  if (it != arc_tdesc_cache.end ())
+    return it->second.get ();
+
+  target_desc *tdesc = arc_create_target_description (features);
+
+  /* Add the newly created target description to the repertoire.  */
+  arc_tdesc_cache.emplace (features, tdesc);
+
+  return tdesc;
+}
+
+#endif /* !GDBSERVER */
diff --git a/gdb/arch/arc.h b/gdb/arch/arc.h
index fd806ae7d34..a5313b1fee6 100644
--- a/gdb/arch/arc.h
+++ b/gdb/arch/arc.h
@@ -20,29 +20,68 @@
 
 #include "gdbsupport/tdesc.h"
 
-/* Supported ARC system hardware types.  */
-enum arc_sys_type
+/* Supported ARC ISAs.  */
+enum arc_isa
 {
-  ARC_SYS_TYPE_ARCOMPACT = 0,	  /* ARC600 or ARC700 */
-  ARC_SYS_TYPE_ARCV2,		  /* ARC EM or ARC HS */
-  ARC_SYS_TYPE_NUM
+  ARC_ISA_ARCV1 = 1,  /* a.k.a. ARCompact (ARC600, ARC700)  */
+  ARC_ISA_ARCV2	      /* such as ARC EM and ARC HS  */
 };
 
-static inline const char *
-arc_sys_type_to_str (const arc_sys_type type)
+struct arc_gdbarch_features
 {
-  switch (type)
-    {
-    case ARC_SYS_TYPE_ARCOMPACT:
-      return "ARC_SYS_TYPE_ARCOMPACT";
-    case ARC_SYS_TYPE_ARCV2:
-      return "ARC_SYS_TYPE_ARCV2";
-    default:
-      return "Invalid";
-    }
-}
-
-/* Create target description for the specified system type.  */
-target_desc *arc_create_target_description (arc_sys_type sys_type);
+  arc_gdbarch_features (int reg_size, arc_isa isa)
+    : reg_size (reg_size), isa (isa)
+  {}
+
+  /* Register size in bytes.  Possible values are 4, and 8.  A 0 indicates
+     an uninitialised value.  */
+  const int reg_size;
+
+  /* See ARC_ISA enum.  */
+  const arc_isa isa;
+
+  /* Equality operator.  */
+  bool operator== (const struct arc_gdbarch_features &rhs) const
+  {
+    return (reg_size == rhs.reg_size && isa == rhs.isa);
+  }
+
+  /* Inequality operator.  */
+  bool operator!= (const struct arc_gdbarch_features &rhs) const
+  {
+    return !(*this == rhs);
+  }
+
+  /* Used by std::unordered_map to hash the feature sets.  The hash is
+     calculated in the manner below:
+     REG_SIZE |  ISA
+      5-bits  | 4-bits  */
+
+  std::size_t hash () const noexcept
+  {
+    std::size_t val = ((reg_size & 0x1f) << 8 | (isa & 0xf) << 0);
+    return val;
+  }
+};
+
+#ifdef GDBSERVER
+
+/* Create and return a target description that is compatible with FEATURES.
+   The only external client of this must be the gdbserver which manipulates
+   the returned data.  */
+
+target_desc *arc_create_target_description
+	(const struct arc_gdbarch_features &features);
+
+#else
+
+/* Lookup the cache for a target description matching the FEATURES.
+   If nothing is found, then create one and return it.  */
+
+const target_desc *arc_lookup_target_description
+	(const struct arc_gdbarch_features &features);
+
+#endif /* GDBSERVER */
+
 
 #endif /* ARCH_ARC_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index a002084d5b9..8cfdb8ccc92 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -45205,40 +45205,41 @@ it should contain registers @samp{pauth_dmask} and @samp{pauth_cmask}.
 @subsection ARC Features
 @cindex target descriptions, ARC Features
 
-ARC processors are highly configurable, so even core registers and their number
-are not completely predetermined.  In addition flags and PC registers which are
-important to @value{GDBN} are not ``core'' registers in ARC.  It is required
-that one of the core registers features is present.
-@samp{org.gnu.gdb.arc.aux-minimal} feature is mandatory.
-
-The @samp{org.gnu.gdb.arc.core.v2} feature is required for ARC EM and ARC HS
-targets with a normal register file.  It should contain registers @samp{r0}
-through @samp{r25}, @samp{gp}, @samp{fp}, @samp{sp}, @samp{r30}, @samp{blink},
-@samp{lp_count} and @samp{pcl}.  This feature may contain register @samp{ilink}
-and any of extension core registers @samp{r32} through @samp{r59/acch}.
-@samp{ilink} and extension core registers are not available to read/write, when
-debugging GNU/Linux applications, thus @samp{ilink} is made optional.
-
-The @samp{org.gnu.gdb.arc.core-reduced.v2} feature is required for ARC EM and
-ARC HS targets with a reduced register file.  It should contain registers
-@samp{r0} through @samp{r3}, @samp{r10} through @samp{r15}, @samp{gp},
-@samp{fp}, @samp{sp}, @samp{r30}, @samp{blink}, @samp{lp_count} and @samp{pcl}.
-This feature may contain register @samp{ilink} and any of extension core
-registers @samp{r32} through @samp{r59/acch}.
-
-The @samp{org.gnu.gdb.arc.core.arcompact} feature is required for ARCompact
-targets with a normal register file.  It should contain registers @samp{r0}
-through @samp{r25}, @samp{gp}, @samp{fp}, @samp{sp}, @samp{r30}, @samp{blink},
-@samp{lp_count} and @samp{pcl}.  This feature may contain registers
-@samp{ilink1}, @samp{ilink2} and any of extension core registers @samp{r32}
-through @samp{r59/acch}.  @samp{ilink1} and @samp{ilink2} and extension core
-registers are not available when debugging GNU/Linux applications.  The only
-difference with @samp{org.gnu.gdb.arc.core.v2} feature is in the names of
-@samp{ilink1} and @samp{ilink2} registers and that @samp{r30} is mandatory in
-ARC v2, but @samp{ilink2} is optional on ARCompact.
-
-The @samp{org.gnu.gdb.arc.aux-minimal} feature is required for all ARC
-targets.  It should contain registers @samp{pc} and @samp{status32}.
+ARC processors are so configurable that even core registers and their numbers
+are not predetermined completely.  Moreover, @emph{flags} and @emph{PC}
+registers, which are important to @value{GDBN}, are not ``core'' registers in
+ARC.  Therefore, there are two features that their presence is mandatory:
+@samp{org.gnu.gdb.arc.core} and @samp{org.gnu.gdb.arc.aux}.
+
+The @samp{org.gnu.gdb.arc.core} feature is required for all targets.  It must
+contain registers:
+
+@itemize @minus
+@item
+@samp{r0} through @samp{r25} for normal register file targets.
+@item
+@samp{r0} through @samp{r3}, and @samp{r10} through @samp{r15} for reduced
+register file targets.
+@item
+@samp{gp}, @samp{fp}, @samp{sp}, @samp{r30}@footnote{Not necessary for ARCv1.},
+@samp{blink}, @samp{lp_count}, @samp{pcl}.
+@end itemize
+
+In case of an ARCompact target (ARCv1 ISA), the @samp{org.gnu.gdb.arc.core}
+feature may contain registers @samp{ilink1} and @samp{ilink2}.  While in case
+of ARC EM and ARC HS targets (ARCv2 ISA), register @samp{ilink} may be present.
+The difference between ARCv1 and ARCv2 is the naming of registers @emph{29th}
+and @emph{30th}.  They are called @samp{ilink1} and @samp{ilink2} for ARCv1 and
+are optional.  For ARCv2, they are called @samp{ilink} and @samp{r30} and only
+@samp{ilink} is optional.  The optionality of @samp{ilink*} registers is
+because of their inaccessibility during user space debugging sessions.
+
+Extension core registers @samp{r32} through @samp{r59} are optional and their
+existence depends on the configuration.  When debugging GNU/Linux applications,
+i.e. user space debugging, these core registers are not available.
+
+The @samp{org.gnu.gdb.arc.aux} feature is required for all ARC targets.  It
+should at least contain @samp{pc} and @samp{status32} registers.
 
 @node ARM Features
 @subsection ARM Features
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index d0af9a47b48..689603847a0 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -201,10 +201,10 @@ $(outdir)/%.dat: %.xml number-regs.xsl sort-regs.xsl gdbserver-regs.xsl
 FEATURE_XMLFILES = aarch64-core.xml \
 	aarch64-fpu.xml \
 	aarch64-pauth.xml \
-	arc/core-v2.xml \
-	arc/aux-v2.xml \
-	arc/core-arcompact.xml \
-	arc/aux-arcompact.xml \
+	arc/v1-core.xml \
+	arc/v1-aux.xml \
+	arc/v2-core.xml \
+	arc/v2-aux.xml \
 	arm/arm-core.xml \
 	arm/arm-fpa.xml \
 	arm/arm-m-profile.xml \
diff --git a/gdb/features/arc/aux-arcompact.c b/gdb/features/arc/v1-aux.c
similarity index 73%
rename from gdb/features/arc/aux-arcompact.c
rename to gdb/features/arc/v1-aux.c
index d8e8c74e639..d1540763433 100644
--- a/gdb/features/arc/aux-arcompact.c
+++ b/gdb/features/arc/v1-aux.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: aux-arcompact.xml */
+  Original: v1-aux.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_aux_arcompact (struct target_desc *result, long regnum)
+create_feature_arc_v1_aux (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux-minimal");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux");
   tdesc_type_with_fields *type_with_fields;
   type_with_fields = tdesc_create_flags (feature, "status32_type", 4);
   tdesc_add_flag (type_with_fields, 0, "H");
@@ -27,5 +27,8 @@ create_feature_arc_aux_arcompact (struct target_desc *result, long regnum)
 
   tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "status32", regnum++, 1, NULL, 32, "status32_type");
+  tdesc_create_reg (feature, "lp_start", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "lp_end", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "bta", regnum++, 1, NULL, 32, "code_ptr");
   return regnum;
 }
diff --git a/gdb/features/arc/aux-arcompact.xml b/gdb/features/arc/v1-aux.xml
similarity index 80%
rename from gdb/features/arc/aux-arcompact.xml
rename to gdb/features/arc/v1-aux.xml
index bf68112f5db..091808b1e29 100644
--- a/gdb/features/arc/aux-arcompact.xml
+++ b/gdb/features/arc/v1-aux.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.aux-minimal">
+<feature name="org.gnu.gdb.arc.aux">
   <flags id="status32_type" size="4">
       <field name="H"   start="0" end="0"/>
       <field name="E"   start="1" end="2"/>
@@ -19,10 +19,13 @@
       <field name="N"   start="10" end="10"/>
       <field name="Z"   start="11" end="11"/>
       <field name="L"   start="12" end="12"/>
-      <field name="R"  start="13" end="13"/>
+      <field name="R"   start="13" end="13"/>
       <field name="SE"  start="14" end="14"/>
   </flags>
 
   <reg name="pc"       bitsize="32" type="code_ptr"/>
   <reg name="status32" bitsize="32" type="status32_type"/>
+  <reg name="lp_start" bitsize="32" type="code_ptr"/>
+  <reg name="lp_end"   bitsize="32" type="code_ptr"/>
+  <reg name="bta"      bitsize="32" type="code_ptr"/>
 </feature>
diff --git a/gdb/features/arc/core-arcompact.c b/gdb/features/arc/v1-core.c
similarity index 87%
rename from gdb/features/arc/core-arcompact.c
rename to gdb/features/arc/v1-core.c
index 7d9a4b23c21..df51d4788df 100644
--- a/gdb/features/arc/core-arcompact.c
+++ b/gdb/features/arc/v1-core.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: core-arcompact.xml */
+  Original: v1-core.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_core_arcompact (struct target_desc *result, long regnum)
+create_feature_arc_v1_core (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core.arcompact");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core");
   tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
@@ -38,8 +38,6 @@ create_feature_arc_core_arcompact (struct target_desc *result, long regnum)
   tdesc_create_reg (feature, "gp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "fp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
-  tdesc_create_reg (feature, "ilink1", regnum++, 1, NULL, 32, "code_ptr");
-  tdesc_create_reg (feature, "ilink2", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "blink", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "lp_count", regnum++, 1, NULL, 32, "uint32");
   tdesc_create_reg (feature, "pcl", regnum++, 1, NULL, 32, "code_ptr");
diff --git a/gdb/features/arc/core-arcompact.xml b/gdb/features/arc/v1-core.xml
similarity index 92%
rename from gdb/features/arc/core-arcompact.xml
rename to gdb/features/arc/v1-core.xml
index 9209891b41a..68d04bdf9d0 100644
--- a/gdb/features/arc/core-arcompact.xml
+++ b/gdb/features/arc/v1-core.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.core.arcompact">
+<feature name="org.gnu.gdb.arc.core">
   <reg name="r0"  bitsize="32"/>
   <reg name="r1"  bitsize="32"/>
   <reg name="r2"  bitsize="32"/>
@@ -40,8 +40,6 @@
   <reg name="sp"  bitsize="32" type="data_ptr"/>
 
   <!-- Code pointers.  -->
-  <reg name="ilink1" bitsize="32" type="code_ptr"/>
-  <reg name="ilink2" bitsize="32" type="code_ptr"/>
   <reg name="blink"  bitsize="32" type="code_ptr"/>
 
   <!-- Here goes extension core registers: r32 - r59 -->
diff --git a/gdb/features/arc/aux-v2.c b/gdb/features/arc/v2-aux.c
similarity index 76%
rename from gdb/features/arc/aux-v2.c
rename to gdb/features/arc/v2-aux.c
index 6290b9b1a7f..7b38e377fe1 100644
--- a/gdb/features/arc/aux-v2.c
+++ b/gdb/features/arc/v2-aux.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: aux-v2.xml */
+  Original: v2-aux.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_aux_v2 (struct target_desc *result, long regnum)
+create_feature_arc_v2_aux (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux-minimal");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux");
   tdesc_type_with_fields *type_with_fields;
   type_with_fields = tdesc_create_flags (feature, "status32_type", 4);
   tdesc_add_flag (type_with_fields, 0, "H");
@@ -31,5 +31,8 @@ create_feature_arc_aux_v2 (struct target_desc *result, long regnum)
 
   tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "status32", regnum++, 1, NULL, 32, "status32_type");
+  tdesc_create_reg (feature, "lp_start", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "lp_end", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "bta", regnum++, 1, NULL, 32, "code_ptr");
   return regnum;
 }
diff --git a/gdb/features/arc/aux-v2.xml b/gdb/features/arc/v2-aux.xml
similarity index 86%
rename from gdb/features/arc/aux-v2.xml
rename to gdb/features/arc/v2-aux.xml
index 2701fad72dc..5d81e248088 100644
--- a/gdb/features/arc/aux-v2.xml
+++ b/gdb/features/arc/v2-aux.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.aux-minimal">
+<feature name="org.gnu.gdb.arc.aux">
   <flags id="status32_type" size="4">
       <field name="H"   start="0" end="0"/>
       <field name="E"   start="1" end="4"/>
@@ -29,4 +29,7 @@
 
   <reg name="pc"       bitsize="32" type="code_ptr"/>
   <reg name="status32" bitsize="32" type="status32_type"/>
+  <reg name="lp_start" bitsize="32" type="code_ptr"/>
+  <reg name="lp_end"   bitsize="32" type="code_ptr"/>
+  <reg name="bta"      bitsize="32" type="code_ptr"/>
 </feature>
diff --git a/gdb/features/arc/core-v2.c b/gdb/features/arc/v2-core.c
similarity index 91%
rename from gdb/features/arc/core-v2.c
rename to gdb/features/arc/v2-core.c
index d37da990457..1c3ef1a91df 100644
--- a/gdb/features/arc/core-v2.c
+++ b/gdb/features/arc/v2-core.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: core-v2.xml */
+  Original: v2-core.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_core_v2 (struct target_desc *result, long regnum)
+create_feature_arc_v2_core (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core.v2");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core");
   tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
@@ -38,7 +38,6 @@ create_feature_arc_core_v2 (struct target_desc *result, long regnum)
   tdesc_create_reg (feature, "gp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "fp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
-  tdesc_create_reg (feature, "ilink", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "r30", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "blink", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "lp_count", regnum++, 1, NULL, 32, "uint32");
diff --git a/gdb/features/arc/core-v2.xml b/gdb/features/arc/v2-core.xml
similarity index 90%
rename from gdb/features/arc/core-v2.xml
rename to gdb/features/arc/v2-core.xml
index 1b17968fb2e..2a2561eab16 100644
--- a/gdb/features/arc/core-v2.xml
+++ b/gdb/features/arc/v2-core.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.core.v2">
+<feature name="org.gnu.gdb.arc.core">
   <reg name="r0"  bitsize="32"/>
   <reg name="r1"  bitsize="32"/>
   <reg name="r2"  bitsize="32"/>
@@ -42,12 +42,11 @@
   <!-- Code pointers.  R30 is general purpose, but it used to be ILINK2 in
   ARCompact, thus its odd position in between of special purpose registers.
   GCC does't use this register, so it isn't a member of a general group. -->
-  <reg name="ilink" bitsize="32" type="code_ptr"/>
   <reg name="r30"   bitsize="32" group=""/>
   <reg name="blink" bitsize="32" type="code_ptr"/>
 
-  <!-- Here goes extension core registers: r32 - r57.  -->
-  <!-- Here goes ACCL/ACCH registers, r58, r59.  -->
+  <!-- Extension core registers: r32 - r57.  -->
+  <!-- ACCL/ACCH registers: r58, r59.  -->
 
   <!-- Loop counter.  -->
   <reg name="lp_count" bitsize="32" type="uint32"/>
diff --git a/gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml b/gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml
index 09689b8a44b..0ae2190c511 100644
--- a/gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml
+++ b/gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml
@@ -9,7 +9,7 @@
 <target>
   <architecture>arc:HS</architecture>
 
-  <feature name="org.gnu.gdb.arc.core.v2">
+  <feature name="org.gnu.gdb.arc.core">
     <reg name="r0"  bitsize="32"/>
     <reg name="r1"  bitsize="32"/>
     <reg name="r2"  bitsize="32"/>
@@ -46,7 +46,7 @@
     <reg name="pcl" bitsize="32"/>
   </feature>
 
-  <feature name="org.gnu.gdb.arc.aux-minimal">
+  <feature name="org.gnu.gdb.arc.aux">
     <reg name="pc"       bitsize="32"/>
     <reg name="status32" bitsize="32"/>
   </feature>
-- 
2.28.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v5 2/4] arc: Add inclusion of "gdbarch.h" in "arc-tdep.h"
  2020-08-04  8:57 ` [PATCH v5 0/4] " Shahab Vahedi
  2020-08-04  8:57   ` [PATCH v5 1/4] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
@ 2020-08-04  8:57   ` Shahab Vahedi
  2020-08-04  8:57   ` [PATCH v5 3/4] arc: Add hardware loop detection Shahab Vahedi
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-04  8:57 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Eli Zaretskii, Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

The "arc-tdep.h" makes use of definitions in "gdbarch.h", but it
does not include it explicitly.  I have piggy backed this fix
in another commit [1], but I was asked to do it separately [2].

[1] arc: Add hardware loop detection
https://sourceware.org/pipermail/gdb-patches/2020-July/170800.html

[2] Simon's remarks to "arc: Add hardware loop detection"
https://sourceware.org/pipermail/gdb-patches/2020-August/170993.html

gdb/ChangeLog:

	* arc-tdep.h: Include "gdbarch.h".
---
 gdb/arc-tdep.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index 6ca759a661d..5968abd4600 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -23,6 +23,7 @@
 
 /* Need disassemble_info.  */
 #include "dis-asm.h"
+#include "gdbarch.h"
 #include "arch/arc.h"
 
 /* To simplify GDB code this enum assumes that internal regnums should be same
-- 
2.28.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v5 3/4] arc: Add hardware loop detection
  2020-08-04  8:57 ` [PATCH v5 0/4] " Shahab Vahedi
  2020-08-04  8:57   ` [PATCH v5 1/4] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
  2020-08-04  8:57   ` [PATCH v5 2/4] arc: Add inclusion of "gdbarch.h" in "arc-tdep.h" Shahab Vahedi
@ 2020-08-04  8:57   ` Shahab Vahedi
  2020-08-04 14:28     ` Eli Zaretskii
  2020-08-04  8:57   ` [PATCH v5 4/4] arc: Add GNU/Linux support for ARC Shahab Vahedi
  2020-08-04 12:49   ` [PATCH v5 0/4] arc: Add GNU/Linux support Simon Marchi
  4 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-04  8:57 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Eli Zaretskii, Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

For ARC there are registers that are not part of a required set in XML
target descriptions by default, but are almost always present on ARC
targets and are universally exposed by the ptrace interface.  Hardware
loop registers being one of them.

LP_START and LP_END auxiliary registers are hardware loop start and end.
Formally, they are optional, but it is hard to find an ARC configuration
that doesn't have them.  They are always present in processors that can
run GNU/Linux.  GDB needs to know about those registers to implement
proper software single stepping, since they affect  what instruction
will be next.

This commit adds the code to check for the existance of "lp_start" and
"lp_end" in XML target descriptions. If they exist, then the function
reports that the target supports hardware loops.

gdb/ChangeLog:

	* arc-tdep.c (arc_check_for_hardware_loop): New.
	* arc-tdep.h (gdbarch_tdep): New field has_hw_loops.

gdb/doc/ChangeLog:

	* gdb.texinfo (Synopsys ARC): Document LP_START, LP_END and BTA.
---
 gdb/arc-tdep.c      | 39 +++++++++++++++++++++++++++++++++++----
 gdb/arc-tdep.h      |  3 +++
 gdb/doc/gdb.texinfo | 11 +++++++++--
 3 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 3b79e0ee685..154df291872 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -2004,6 +2004,35 @@ arc_check_tdesc_feature (struct tdesc_arch_data *tdesc_data,
   return true;
 }
 
+/* Check for the existance of "lp_start" and "lp_end" in target description.
+   If both are present, assume there is hardware loop support in the target.
+   This can be improved by looking into "lpc_size" field of "isa_config"
+   auxiliary register.  */
+
+static bool
+arc_check_for_hw_loops (const struct target_desc *tdesc,
+			struct tdesc_arch_data *data)
+{
+  const auto feature_aux = tdesc_find_feature (tdesc, ARC_AUX_FEATURE_NAME);
+  const auto aux_regset = determine_aux_reg_feature_set ();
+
+  if (feature_aux == nullptr)
+    return false;
+
+  bool hw_loop_p = false;
+  const auto lp_start_name =
+    aux_regset->registers[ARC_LP_START_REGNUM - ARC_FIRST_AUX_REGNUM].names[0];
+  const auto lp_end_name =
+    aux_regset->registers[ARC_LP_END_REGNUM - ARC_FIRST_AUX_REGNUM].names[0];
+
+  hw_loop_p = tdesc_numbered_register (feature_aux, data,
+				       ARC_LP_START_REGNUM, lp_start_name);
+  hw_loop_p &= tdesc_numbered_register (feature_aux, data,
+				       ARC_LP_END_REGNUM, lp_end_name);
+
+  return hw_loop_p;
+}
+
 /* Initialize target description for the ARC.
 
    Returns true if input TDESC was valid and in this case it will assign TDESC
@@ -2120,13 +2149,15 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     debug_printf ("arc: Architecture initialization.\n");
 
   if (!arc_tdesc_init (info, &tdesc, &tdesc_data))
-    return NULL;
+    return nullptr;
 
   /* Allocate the ARC-private target-dependent information structure, and the
      GDB target-independent information structure.  */
-  struct gdbarch_tdep *tdep = XCNEW (struct gdbarch_tdep);
+  gdb::unique_xmalloc_ptr<struct gdbarch_tdep> tdep
+    (XCNEW (struct gdbarch_tdep));
   tdep->jb_pc = -1; /* No longjmp support by default.  */
-  struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep);
+  tdep->has_hw_loops = arc_check_for_hw_loops (tdesc, tdesc_data);
+  struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep.release ());
 
   /* Data types.  */
   set_gdbarch_short_bit (gdbarch, 16);
@@ -2207,7 +2238,7 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      It can override functions set earlier.  */
   gdbarch_init_osabi (info, gdbarch);
 
-  if (tdep->jb_pc >= 0)
+  if (gdbarch_tdep (gdbarch)->jb_pc >= 0)
     set_gdbarch_get_longjmp_target (gdbarch, arc_get_longjmp_target);
 
   /* Disassembler options.  Enforce CPU if it was specified in XML target
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index 5968abd4600..e752348a262 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -111,6 +111,9 @@ struct gdbarch_tdep
   /* Offset to PC value in jump buffer.  If this is negative, longjmp
      support will be disabled.  */
   int jb_pc;
+
+  /* Whether target has hardware (aka zero-delay) loops.  */
+  bool has_hw_loops;
 };
 
 /* Utility functions used by other ARC-specific modules.  */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 8cfdb8ccc92..2578f730cbc 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -45238,8 +45238,15 @@ Extension core registers @samp{r32} through @samp{r59} are optional and their
 existence depends on the configuration.  When debugging GNU/Linux applications,
 i.e. user space debugging, these core registers are not available.
 
-The @samp{org.gnu.gdb.arc.aux} feature is required for all ARC targets.  It
-should at least contain @samp{pc} and @samp{status32} registers.
+The @samp{org.gnu.gdb.arc.aux} feature is required for all ARC targets.  Below
+comes a list of pertinent registers for this feature:
+
+@itemize @minus
+@item
+mandatory: @samp{pc} and @samp{status32}.
+@item
+optional: @samp{lp_start}, @samp{lp_end}, and @samp{bta}.
+@end itemize
 
 @node ARM Features
 @subsection ARM Features
-- 
2.28.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v5 4/4] arc: Add GNU/Linux support for ARC
  2020-08-04  8:57 ` [PATCH v5 0/4] " Shahab Vahedi
                     ` (2 preceding siblings ...)
  2020-08-04  8:57   ` [PATCH v5 3/4] arc: Add hardware loop detection Shahab Vahedi
@ 2020-08-04  8:57   ` Shahab Vahedi
  2020-08-04 12:49   ` [PATCH v5 0/4] arc: Add GNU/Linux support Simon Marchi
  4 siblings, 0 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-04  8:57 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Eli Zaretskii, Anton Kolesov, Francois Bedard, Anton Kolesov

From: Anton Kolesov <Anton.Kolesov@synopsys.com>

ARC Linux targets differences from baremetal:

- No support for hardware single instruction stepping.
- Different access rules to registers.
- Use of another instruction for breakpoints.

v2: Changes after Tom's remarks [1]
 arc-linux-tdep.c
  - Use true/false instead of TRUE/FALSE.
  - arc_linux_sw_breakpoint_from_kind (): Break long lines into two.
  - arc_linux_sw_breakpoint_from_kind (): Remove starting blank line.
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 arc-tdep.c
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 gdb/configure.tgt
  - arc*-*-linux*): Remove "build_gdbserver=yes".

v3: Changes after Simon's remarks [2]
  arc-linux-tdep.c
  - Use "return trap_size" instead of cryptic "return 2".
  - Removed unnecessary curly braces.
  - Removed "void" from "_initialize_arc_linux_tdep (void)".

v5: Changes after Simon's remarks [3]
- Remove unnecessary empty lines.
- Replace "breakpoint uses" with "breakpoints use" in a comment.
- "return condition;" i.s.o. "if (condition) return true; else return false;"

[1] Tom's remarks
https://sourceware.org/pipermail/gdb-patches/2020-April/167887.html

[2] Simon's remarks on v2
https://sourceware.org/pipermail/gdb-patches/2020-May/168513.html

[3] Simon's remarks on v4
https://sourceware.org/pipermail/gdb-patches/2020-August/170994.html

2020-08-03  Anton Kolesov  <anton.kolesov@synopsys.com>

	* configure.tgt: ARC support for GNU/Linux.
	* Makefile.in (ALL_TARGET_OBJS): Likewise.
	* arc-linux-tdep.c: New file.
	* arc-tdep.h (ARC_STATUS32_L_MASK, ARC_STATUS32_DE_MASK): Declare.
	* arc-tdep.c (arc_write_pc): Use it.
---
 gdb/Makefile.in      |   1 +
 gdb/arc-linux-tdep.c | 278 +++++++++++++++++++++++++++++++++++++++++++
 gdb/arc-tdep.c       |   3 +-
 gdb/arc-tdep.h       |   5 +
 gdb/configure.tgt    |   5 +
 5 files changed, 290 insertions(+), 2 deletions(-)
 create mode 100644 gdb/arc-linux-tdep.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 9d484457397..85304b9f549 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -697,6 +697,7 @@ ALL_64_TARGET_OBS = \
 # All other target-dependent objects files (used with --enable-targets=all).
 ALL_TARGET_OBS = \
 	aarch32-tdep.o \
+	arc-linux-tdep.o \
 	arc-tdep.o \
 	arch/aarch32.o \
 	arch/arc.o \
diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
new file mode 100644
index 00000000000..36f32459bbe
--- /dev/null
+++ b/gdb/arc-linux-tdep.c
@@ -0,0 +1,278 @@
+/* Target dependent code for GNU/Linux ARC.
+
+   Copyright 2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* GDB header files.  */
+#include "defs.h"
+#include "linux-tdep.h"
+#include "objfiles.h"
+#include "opcode/arc.h"
+#include "osabi.h"
+#include "solib-svr4.h"
+
+/* ARC header files.  */
+#include "opcodes/arc-dis.h"
+#include "arc-tdep.h"
+
+/* Implement the "cannot_fetch_register" gdbarch method.  */
+
+static int
+arc_linux_cannot_fetch_register (struct gdbarch *gdbarch, int regnum)
+{
+  /* Assume that register is readable if it is unknown.  */
+  switch (regnum)
+    {
+    case ARC_ILINK_REGNUM:
+    case ARC_RESERVED_REGNUM:
+    case ARC_LIMM_REGNUM:
+      return true;
+    case ARC_R30_REGNUM:
+    case ARC_R58_REGNUM:
+    case ARC_R59_REGNUM:
+      return !arc_mach_is_arcv2 (gdbarch);
+    }
+  return (regnum > ARC_BLINK_REGNUM) && (regnum < ARC_LP_COUNT_REGNUM);
+}
+
+/* Implement the "cannot_store_register" gdbarch method.  */
+
+static int
+arc_linux_cannot_store_register (struct gdbarch *gdbarch, int regnum)
+{
+  /* Assume that register is writable if it is unknown.  */
+  switch (regnum)
+    {
+    case ARC_ILINK_REGNUM:
+    case ARC_RESERVED_REGNUM:
+    case ARC_LIMM_REGNUM:
+    case ARC_PCL_REGNUM:
+      return true;
+    case ARC_R30_REGNUM:
+    case ARC_R58_REGNUM:
+    case ARC_R59_REGNUM:
+      return !arc_mach_is_arcv2 (gdbarch);
+    }
+  return (regnum > ARC_BLINK_REGNUM) && (regnum < ARC_LP_COUNT_REGNUM);
+}
+
+/* For ARC Linux, breakpoints use the 16-bit TRAP_S 1 instruction, which
+   is 0x3e78 (little endian) or 0x783e (big endian).  */
+
+static const gdb_byte arc_linux_trap_s_be[] = { 0x78, 0x3e };
+static const gdb_byte arc_linux_trap_s_le[] = { 0x3e, 0x78 };
+static const int trap_size = 2;   /* Number of bytes to insert "trap".  */
+
+/* Implement the "breakpoint_kind_from_pc" gdbarch method.  */
+
+static int
+arc_linux_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+  return trap_size;
+}
+
+/* Implement the "sw_breakpoint_from_kind" gdbarch method.  */
+
+static const gdb_byte *
+arc_linux_sw_breakpoint_from_kind (struct gdbarch *gdbarch,
+				   int kind, int *size)
+{
+  *size = kind;
+  return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+	  ? arc_linux_trap_s_be
+	  : arc_linux_trap_s_le);
+}
+
+/* Implement the "software_single_step" gdbarch method.  */
+
+static std::vector<CORE_ADDR>
+arc_linux_software_single_step (struct regcache *regcache)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct disassemble_info di = arc_disassemble_info (gdbarch);
+
+  /* Read current instruction.  */
+  struct arc_instruction curr_insn;
+  arc_insn_decode (regcache_read_pc (regcache), &di, arc_delayed_print_insn,
+		   &curr_insn);
+  CORE_ADDR next_pc = arc_insn_get_linear_next_pc (curr_insn);
+
+  std::vector<CORE_ADDR> next_pcs;
+
+  /* For instructions with delay slots, the fall thru is not the
+     instruction immediately after the current instruction, but the one
+     after that.  */
+  if (curr_insn.has_delay_slot)
+    {
+      struct arc_instruction next_insn;
+      arc_insn_decode (next_pc, &di, arc_delayed_print_insn, &next_insn);
+      next_pcs.push_back (arc_insn_get_linear_next_pc (next_insn));
+    }
+  else
+    next_pcs.push_back (next_pc);
+
+  ULONGEST status32;
+  regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
+				 &status32);
+
+  if (curr_insn.is_control_flow)
+    {
+      CORE_ADDR branch_pc = arc_insn_get_branch_target (curr_insn);
+      if (branch_pc != next_pc)
+	next_pcs.push_back (branch_pc);
+    }
+  /* Is current instruction the last in a loop body?  */
+  else if (tdep->has_hw_loops)
+    {
+      /* If STATUS32.L is 1, then ZD-loops are disabled.  */
+      if ((status32 & ARC_STATUS32_L_MASK) == 0)
+	{
+	  ULONGEST lp_end, lp_start, lp_count;
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_START_REGNUM,
+					 &lp_start);
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_END_REGNUM, &lp_end);
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_COUNT_REGNUM,
+					 &lp_count);
+
+	  if (arc_debug)
+	    {
+	      debug_printf ("arc-linux: lp_start = %s, lp_end = %s, "
+			    "lp_count = %s, next_pc = %s\n",
+			    paddress (gdbarch, lp_start),
+			    paddress (gdbarch, lp_end),
+			    pulongest (lp_count),
+			    paddress (gdbarch, next_pc));
+	    }
+
+	  if (next_pc == lp_end && lp_count > 1)
+	    {
+	      /* The instruction is in effect a jump back to the start of
+		 the loop.  */
+	      next_pcs.push_back (lp_start);
+	    }
+	}
+    }
+
+  /* Is this a delay slot?  Then next PC is in BTA register.  */
+  if ((status32 & ARC_STATUS32_DE_MASK) != 0)
+    {
+      ULONGEST bta;
+      regcache_cooked_read_unsigned (regcache, ARC_BTA_REGNUM, &bta);
+      next_pcs.push_back (bta);
+    }
+
+  return next_pcs;
+}
+
+/* Implement the "skip_solib_resolver" gdbarch method.
+
+   See glibc_skip_solib_resolver for details.  */
+
+static CORE_ADDR
+arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  /* For uClibc 0.9.26+.
+
+     An unresolved PLT entry points to "__dl_linux_resolve", which calls
+     "_dl_linux_resolver" to do the resolving and then eventually jumps to
+     the function.
+
+     So we look for the symbol `_dl_linux_resolver', and if we are there,
+     gdb sets a breakpoint at the return address, and continues.  */
+  struct bound_minimal_symbol resolver
+    = lookup_minimal_symbol ("_dl_linux_resolver", NULL, NULL);
+
+  if (arc_debug)
+    {
+      if (resolver.minsym != nullptr)
+	{
+	  CORE_ADDR res_addr = BMSYMBOL_VALUE_ADDRESS (resolver);
+	  debug_printf ("arc-linux: skip_solib_resolver (): "
+			"pc = %s, resolver at %s\n",
+			print_core_address (gdbarch, pc),
+			print_core_address (gdbarch, res_addr));
+	}
+      else
+	{
+	  debug_printf ("arc-linux: skip_solib_resolver (): "
+			"pc = %s, no resolver found\n",
+			print_core_address (gdbarch, pc));
+	}
+    }
+
+  if (resolver.minsym != nullptr && BMSYMBOL_VALUE_ADDRESS (resolver) == pc)
+    {
+      /* Find the return address.  */
+      return frame_unwind_caller_pc (get_current_frame ());
+    }
+  else
+    {
+      /* No breakpoint required.  */
+      return 0;
+    }
+}
+
+/* Initialization specific to Linux environment.  */
+
+static void
+arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (arc_debug)
+    debug_printf ("arc-linux: GNU/Linux OS/ABI initialization.\n");
+
+  /* If we are using Linux, we have in uClibc
+     (libc/sysdeps/linux/arc/bits/setjmp.h):
+
+     typedef int __jmp_buf[13+1+1+1];    //r13-r25, fp, sp, blink
+
+     Where "blink" is a stored PC of a caller function.
+   */
+  tdep->jb_pc = 15;
+
+  linux_init_abi (info, gdbarch);
+
+  /* Set up target dependent GDB architecture entries.  */
+  set_gdbarch_cannot_fetch_register (gdbarch, arc_linux_cannot_fetch_register);
+  set_gdbarch_cannot_store_register (gdbarch, arc_linux_cannot_store_register);
+  set_gdbarch_breakpoint_kind_from_pc (gdbarch,
+				       arc_linux_breakpoint_kind_from_pc);
+  set_gdbarch_sw_breakpoint_from_kind (gdbarch,
+				       arc_linux_sw_breakpoint_from_kind);
+  set_gdbarch_fetch_tls_load_module_address (gdbarch,
+					     svr4_fetch_objfile_link_map);
+  set_gdbarch_software_single_step (gdbarch, arc_linux_software_single_step);
+  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+  set_gdbarch_skip_solib_resolver (gdbarch, arc_linux_skip_solib_resolver);
+
+  /* GNU/Linux uses SVR4-style shared libraries, with 32-bit ints, longs
+     and pointers (ILP32).  */
+  set_solib_svr4_fetch_link_map_offsets (gdbarch,
+					 svr4_ilp32_fetch_link_map_offsets);
+}
+
+/* Suppress warning from -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_arc_linux_tdep;
+
+void
+_initialize_arc_linux_tdep ()
+{
+  gdbarch_register_osabi (bfd_arch_arc, 0, GDB_OSABI_LINUX,
+			  arc_linux_init_osabi);
+}
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 154df291872..fed3cd543bc 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -602,8 +602,7 @@ arc_write_pc (struct regcache *regcache, CORE_ADDR new_pc)
   regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
 				 &status32);
 
-  /* Mask for DE bit is 0x40.  */
-  if (status32 & 0x40)
+  if ((status32 & ARC_STATUS32_DE_MASK) != 0)
     {
       if (arc_debug)
 	{
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index e752348a262..6331d29f402 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -100,6 +100,11 @@ enum arc_regnum
    Longer registers are represented as pairs of 32-bit registers.  */
 #define ARC_REGISTER_SIZE  4
 
+/* STATUS32 register: hardware loops disabled bit.  */
+#define ARC_STATUS32_L_MASK (1 << 12)
+/* STATUS32 register: current instruction is a delay slot.  */
+#define ARC_STATUS32_DE_MASK (1 << 6)
+
 #define arc_print(fmt, args...) fprintf_unfiltered (gdb_stdlog, fmt, ##args)
 
 extern int arc_debug;
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index d66f01bb9f7..4178eb4e773 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -157,6 +157,11 @@ arc*-*-elf32)
 	gdb_target_obs="arc-newlib-tdep.o"
 	;;
 
+arc*-*-linux*)
+	# Target: ARC machine running Linux
+	gdb_target_obs="arc-linux-tdep.o linux-tdep.o solib-svr4.o"
+	;;
+
 arm*-wince-pe | arm*-*-mingw32ce*)
 	# Target: ARM based machine running Windows CE (win32)
 	gdb_target_obs="arm-wince-tdep.o windows-tdep.o"
-- 
2.28.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v4 0/3] arc: Add GNU/Linux support
  2020-08-04  7:59         ` Shahab Vahedi
@ 2020-08-04 12:42           ` Simon Marchi
  0 siblings, 0 replies; 86+ messages in thread
From: Simon Marchi @ 2020-08-04 12:42 UTC (permalink / raw)
  To: Shahab Vahedi
  Cc: gdb-patches, Anton Kolesov, Francois Bedard, Shahab Vahedi, Tom Tromey

On 2020-08-04 3:59 a.m., Shahab Vahedi wrote:
> Hi Simon,
> 
> On Sat, Aug 01, 2020 at 07:31:12PM -0400, Simon Marchi wrote:
>> Btw, I think it would make sense to add an entry in the arch section of
>> the MAINTAINERS file for ARC, don't you think?  If you plan on sticking
>> around, I think it would make sense to have you there.
> 
> I already have added my info to "gdb/MAINTAINERS" file.  Is that what
> you mean?

No, there is a section "Target Instruction Set Architectures".  It says who
is responsible for which architecture.  In other words, if there is a change
local to arc-tdep.c, fixing some arc-specific thing, you could approve it to
be merged.

Simon

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v5 0/4] arc: Add GNU/Linux support
  2020-08-04  8:57 ` [PATCH v5 0/4] " Shahab Vahedi
                     ` (3 preceding siblings ...)
  2020-08-04  8:57   ` [PATCH v5 4/4] arc: Add GNU/Linux support for ARC Shahab Vahedi
@ 2020-08-04 12:49   ` Simon Marchi
  2020-08-04 13:05     ` Shahab Vahedi
  4 siblings, 1 reply; 86+ messages in thread
From: Simon Marchi @ 2020-08-04 12:49 UTC (permalink / raw)
  To: Shahab Vahedi, gdb-patches
  Cc: Anton Kolesov, Francois Bedard, Shahab Vahedi, Tom Tromey

On 2020-08-04 4:57 a.m., Shahab Vahedi via Gdb-patches wrote:
> This is a series of changes to enable debugging ARC targets that are
> running on a native ARC GNU/Linux system.  Since this heavily relies
> on XML target descriptions provided for different targets, that piece
> of code has been refactored to accommodate flexible register support.
> 
> After this series, there will come patches that add support for
> native ARC gdb/gdbserver.

Hi Shahab,

The previous version was "LGTM with the pointed out nits fixed", so if you didn't
make other changes than that, you can consider the series ok to merge.

Simon

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v5 0/4] arc: Add GNU/Linux support
  2020-08-04 12:49   ` [PATCH v5 0/4] arc: Add GNU/Linux support Simon Marchi
@ 2020-08-04 13:05     ` Shahab Vahedi
  0 siblings, 0 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-04 13:05 UTC (permalink / raw)
  To: Simon Marchi
  Cc: gdb-patches, Anton Kolesov, Francois Bedard, Shahab Vahedi, Tom Tromey

On Tue, Aug 04, 2020 at 08:49:31AM -0400, Simon Marchi wrote:
> The previous version was "LGTM with the pointed out nits fixed", so if you didn't
> make other changes than that, you can consider the series ok to merge.

Hi Simon,

In the files that you have reviewed, I only applied fixes according to your
remarks.  However, I noticed that the documentation (gdb/doc/gdb.texinfo)
and one test (gdb.arch/arc-tdesc-cpu.xml) need updating.  They're not that
big of a deal of changes, but they reflect that the features name have
changed in this series of patch.  I plan to update the softwares involved,
like OpenOCD, QEMU, etc.


Cheers,
Shahab

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v5 1/4] arc: Add ARCv2 XML target along with refactoring
  2020-08-04  8:57   ` [PATCH v5 1/4] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
@ 2020-08-04 13:08     ` Simon Marchi
  2020-08-04 13:18       ` Shahab Vahedi
  0 siblings, 1 reply; 86+ messages in thread
From: Simon Marchi @ 2020-08-04 13:08 UTC (permalink / raw)
  To: Shahab Vahedi, gdb-patches
  Cc: Shahab Vahedi, Tom Tromey, Eli Zaretskii, Anton Kolesov, Francois Bedard

On 2020-08-04 4:57 a.m., Shahab Vahedi wrote:
> diff --git a/gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml b/gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml
> index 09689b8a44b..0ae2190c511 100644
> --- a/gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml
> +++ b/gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml
> @@ -9,7 +9,7 @@
>  <target>
>    <architecture>arc:HS</architecture>
>  
> -  <feature name="org.gnu.gdb.arc.core.v2">
> +  <feature name="org.gnu.gdb.arc.core">
>      <reg name="r0"  bitsize="32"/>
>      <reg name="r1"  bitsize="32"/>
>      <reg name="r2"  bitsize="32"/>
> @@ -46,7 +46,7 @@
>      <reg name="pcl" bitsize="32"/>
>    </feature>
>  
> -  <feature name="org.gnu.gdb.arc.aux-minimal">
> +  <feature name="org.gnu.gdb.arc.aux">
>      <reg name="pc"       bitsize="32"/>
>      <reg name="status32" bitsize="32"/>
>    </feature>

Does that cause backwards compatibility issues?  Could someone have written a gdb stub
returning an XML target description containing the old feature names, which will now not
work due to these name changes?

Simon

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v5 1/4] arc: Add ARCv2 XML target along with refactoring
  2020-08-04 13:08     ` Simon Marchi
@ 2020-08-04 13:18       ` Shahab Vahedi
  2020-08-04 13:20         ` Simon Marchi
  0 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-04 13:18 UTC (permalink / raw)
  To: Simon Marchi
  Cc: gdb-patches, Shahab Vahedi, Tom Tromey, Eli Zaretskii,
	Anton Kolesov, Francois Bedard

On Tue, Aug 04, 2020 at 09:08:39AM -0400, Simon Marchi wrote:
> Does that cause backwards compatibility issues?  Could someone have written a gdb stub
> returning an XML target description containing the old feature names, which will now not
> work due to these name changes?

Yes!

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v5 1/4] arc: Add ARCv2 XML target along with refactoring
  2020-08-04 13:18       ` Shahab Vahedi
@ 2020-08-04 13:20         ` Simon Marchi
  2020-08-04 14:12           ` Shahab Vahedi
  0 siblings, 1 reply; 86+ messages in thread
From: Simon Marchi @ 2020-08-04 13:20 UTC (permalink / raw)
  To: Shahab Vahedi
  Cc: Francois Bedard, Anton Kolesov, Shahab Vahedi, Tom Tromey, gdb-patches

On 2020-08-04 9:18 a.m., Shahab Vahedi via Gdb-patches wrote:
> On Tue, Aug 04, 2020 at 09:08:39AM -0400, Simon Marchi wrote:
>> Does that cause backwards compatibility issues?  Could someone have written a gdb stub
>> returning an XML target description containing the old feature names, which will now not
>> work due to these name changes?
> 
> Yes!
> 

Do you see a way we could keep backwards compatibility?  Like a way to introduce the new
names, but still make the old names work?

Simon

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v5 1/4] arc: Add ARCv2 XML target along with refactoring
  2020-08-04 13:20         ` Simon Marchi
@ 2020-08-04 14:12           ` Shahab Vahedi
  0 siblings, 0 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-04 14:12 UTC (permalink / raw)
  To: Simon Marchi
  Cc: Francois Bedard, Anton Kolesov, Shahab Vahedi, Tom Tromey, gdb-patches

On Tue, Aug 04, 2020 at 09:20:57AM -0400, Simon Marchi wrote:
> Do you see a way we could keep backwards compatibility?  Like a way to introduce the new
> names, but still make the old names work?

From what it looks like, it should be possible to add a
"backward_compatibility" function layer to search for old
names when the current feature names are not found.  To do
so, I have to pass around the "abfd" data.

I can try implementing it and see if I run into any serious
problem.

Nevertheless, I suggest keeping the test and documentation
in par with the new naming.


Cheers,
Shahab

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v5 3/4] arc: Add hardware loop detection
  2020-08-04  8:57   ` [PATCH v5 3/4] arc: Add hardware loop detection Shahab Vahedi
@ 2020-08-04 14:28     ` Eli Zaretskii
  2020-08-04 16:17       ` Shahab Vahedi
  0 siblings, 1 reply; 86+ messages in thread
From: Eli Zaretskii @ 2020-08-04 14:28 UTC (permalink / raw)
  To: Shahab Vahedi
  Cc: gdb-patches, shahab.vahedi, shahab, simark, tom, anton.kolesov, fbedard

> From: Shahab Vahedi <shahab.vahedi@gmail.com>
> Cc: Shahab Vahedi <shahab.vahedi@gmail.com>,
> 	Shahab Vahedi <shahab@synopsys.com>,
> 	Simon Marchi <simark@simark.ca>,
> 	Tom Tromey <tom@tromey.com>,
> 	Eli Zaretskii <eliz@gnu.org>,
> 	Anton Kolesov <anton.kolesov@synopsys.com>,
> 	Francois Bedard <fbedard@synopsys.com>
> Date: Tue,  4 Aug 2020 10:57:41 +0200
> 
> +The @samp{org.gnu.gdb.arc.aux} feature is required for all ARC targets.  Below
> +comes a list of pertinent registers for this feature:

Suggest to reword the last sentence as follows:

  "Here is the list of the pertinent registers for this feature:"

The documentation part is OK with this nit fixed.

Thanks.

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v5 3/4] arc: Add hardware loop detection
  2020-08-04 14:28     ` Eli Zaretskii
@ 2020-08-04 16:17       ` Shahab Vahedi
  2020-08-04 16:42         ` Eli Zaretskii
  0 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-04 16:17 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, shahab, simark, tom, anton.kolesov, fbedard

On Tue, Aug 04, 2020 at 05:28:05PM +0300, Eli Zaretskii wrote:
> Suggest to reword the last sentence as follows:
> 
>   "Here is the list of the pertinent registers for this feature:"

Hi Eli,

In next patch, I will have it replaced with:

  "Here is a list of registers pertinent to this feature:"

I mentioned "_a_ list of registers", because that list does not
cover all auxiliary registers.


Cheers,
Shahab


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v5 3/4] arc: Add hardware loop detection
  2020-08-04 16:17       ` Shahab Vahedi
@ 2020-08-04 16:42         ` Eli Zaretskii
  2020-08-04 18:15           ` Shahab Vahedi
  0 siblings, 1 reply; 86+ messages in thread
From: Eli Zaretskii @ 2020-08-04 16:42 UTC (permalink / raw)
  To: Shahab Vahedi; +Cc: gdb-patches, shahab, simark, tom, anton.kolesov, fbedard

> Date: Tue, 4 Aug 2020 18:17:12 +0200
> From: Shahab Vahedi <shahab.vahedi@gmail.com>
> Cc: gdb-patches@sourceware.org, shahab@synopsys.com, simark@simark.ca,
> 	tom@tromey.com, anton.kolesov@synopsys.com, fbedard@synopsys.com
> 
> On Tue, Aug 04, 2020 at 05:28:05PM +0300, Eli Zaretskii wrote:
> > Suggest to reword the last sentence as follows:
> > 
> >   "Here is the list of the pertinent registers for this feature:"
> 
> Hi Eli,
> 
> In next patch, I will have it replaced with:
> 
>   "Here is a list of registers pertinent to this feature:"
> 
> I mentioned "_a_ list of registers", because that list does not
> cover all auxiliary registers.

But it does cover _all_ the _pertinent_ registers, doesn't it?  If it
does, then "the" is more correct English, AFAIU.

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v5 3/4] arc: Add hardware loop detection
  2020-08-04 16:42         ` Eli Zaretskii
@ 2020-08-04 18:15           ` Shahab Vahedi
  0 siblings, 0 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-04 18:15 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, shahab, simark, tom, anton.kolesov, fbedard

"the" it is then.
-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.

^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v6 0/4] arc: Add GNU/Linux support
  2020-03-26 12:52 [PATCH 0/4] arc: Add GNU/Linux support Shahab Vahedi
                   ` (7 preceding siblings ...)
  2020-08-04  8:57 ` [PATCH v5 0/4] " Shahab Vahedi
@ 2020-08-05 11:09 ` Shahab Vahedi
  2020-08-05 11:09   ` [PATCH v6 1/4] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
                     ` (4 more replies)
  2020-08-25 15:47 ` [PUSHED " Shahab Vahedi
  9 siblings, 5 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-05 11:09 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Eli Zaretskii, Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

This is a series of changes to enable debugging ARC targets that are
running on a native ARC GNU/Linux system.  Since this heavily relies
on XML target descriptions provided for different targets, that piece
of code has been refactored to accommodate flexible register support.

After this series, there will come patches that add support for
native ARC gdb/gdbserver.

v6: Add backward compatibility for obsolete feature names
 arc-tdep.c:
  - "find_obsolete_[core,aux]_names()" implemented
 gdb/NEWS:
  - Updated with information about these feature name changes.

v5: Changes per remarks of Simon [1] and on my own (documentation and tests)
 arc.h:
  - Made "reg_size" and "isa" constant in "arc_gdbarch_features".
 arc.c:
  - Fix some malformed indentations.
 arc-tdep.h:
  - Inclusion of "gdbarch.h" has its own patch now.
 arc-tdep.c
  - Use "nullptr" instead of "NULL".
  - Remove unnecessary "break"s after "return"s.
  - "determine_core_reg_feature_set" will assert if wrong input is given.
  - Removed dangling comment.
  - Replaced "const auto *" with "const auto" to be consistent.
  - in "arc_check_for_hw_loops()": No "nullptr" check for "aux_regset".
 arc-linux-tdep.c
  - Remove unnecessary empty lines.
  - Replace "breakpoint uses" with "breakpoints use" in a comment.
  - "return condition;" i.s.o. "if (condition) return true; else return false;"
 gdb.texinfo
  - Update documentation regarding the new feature files.
 arc-tdesc-cpu.xml
  - Use new feature names.

[1] Simon's remarks to v4 of the patches
https://sourceware.org/pipermail/gdb-patches/2020-July/170975.html
https://sourceware.org/pipermail/gdb-patches/2020-August/170993.html
https://sourceware.org/pipermail/gdb-patches/2020-August/170994.html

v4: Latest changes per remarks of Simon [2]
 arc-tdep.c
  - Surround "=" in 2 assignments with space.
  - Put the return type of "mach_type_to_arc_isa ()" on the first line.
  - Remove "inline" from "mach_type_to_arc_isa ()".
  - Add space between the "if" conditions for readability.
  - Use "featues.isa" instead of "features.reg_size" in one occurrence.
  - Make "arc_gdbarch_features_init" static
  - Rename "arc_gdbarch_features_init" to "arc_gdbarch_features_create".
  - Adapt "arc_gdbarch_features_create" to act as a constructor.
 arch/arc.c
  - Add a constructor for "arc_gdbarch_features".
  - Get rid of "ARC_ISA_NONE" now that there is a constructor.
 arch/arc.c
  - Use simple assignments (instead of append) for "architecture".
  - Use "string_sprintf ()".
  - Use "target_desc_up" in "arc_tdesc_cache" to avoid memory leakage.
 arc-linux-tdep.c
  - Two occurrences: compare "resolver.minsym" against "nullptr".
  

[2] [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring
https://sourceware.org/pipermail/gdb-patches/2020-July/170427.html

v3: Changes after Simon's remarks:
The XML files have reduced to minimal comprehensible set.
The code is adjusted to work with new reg sets and be platform agnostic.

v2: Changes after Tom's remarks:
 arc-tdep.c
  - arc_tdesc_init(): Use "ARC_{R58,R59}_REGNUM" to index "core_regs[]".
  - arc_gdbarch_init(): Use "xfree ()" instead of "XDELETE ()"
  - arc_gdbarch_init(): return "nullptr" instead of "NULL".
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 arc-linux-tdep.c
  - Use true/false instead of TRUE/FALSE.
  - arc_linux_sw_breakpoint_from_kind (): Break long lines into two.
  - arc_linux_sw_breakpoint_from_kind (): Remove starting blank line.
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 gdb/configure.tgt
  - arc*-*-linux*): Remove "build_gdbserver=yes".

Anton Kolesov (1):
  arc: Add GNU/Linux support for ARC

Shahab Vahedi (3):
  arc: Add ARCv2 XML target along with refactoring
  arc: Add inclusion of "gdbarch.h" in "arc-tdep.h"
  arc: Add hardware loop detection

 gdb/Makefile.in                               |   1 +
 gdb/NEWS                                      |   5 +
 gdb/arc-linux-tdep.c                          | 278 +++++++
 gdb/arc-tdep.c                                | 694 ++++++++++++------
 gdb/arc-tdep.h                                |  27 +-
 gdb/arch/arc.c                                | 108 ++-
 gdb/arch/arc.h                                |  79 +-
 gdb/configure.tgt                             |   5 +
 gdb/doc/gdb.texinfo                           |  76 +-
 gdb/features/Makefile                         |   8 +-
 .../arc/{aux-arcompact.c => v1-aux.c}         |   9 +-
 .../arc/{aux-arcompact.xml => v1-aux.xml}     |   7 +-
 .../arc/{core-arcompact.c => v1-core.c}       |   8 +-
 .../arc/{core-arcompact.xml => v1-core.xml}   |   4 +-
 gdb/features/arc/{aux-v2.c => v2-aux.c}       |   9 +-
 gdb/features/arc/{aux-v2.xml => v2-aux.xml}   |   5 +-
 gdb/features/arc/{core-v2.c => v2-core.c}     |   7 +-
 gdb/features/arc/{core-v2.xml => v2-core.xml} |   7 +-
 gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml      |   4 +-
 19 files changed, 986 insertions(+), 355 deletions(-)
 create mode 100644 gdb/arc-linux-tdep.c
 rename gdb/features/arc/{aux-arcompact.c => v1-aux.c} (73%)
 rename gdb/features/arc/{aux-arcompact.xml => v1-aux.xml} (80%)
 rename gdb/features/arc/{core-arcompact.c => v1-core.c} (87%)
 rename gdb/features/arc/{core-arcompact.xml => v1-core.xml} (92%)
 rename gdb/features/arc/{aux-v2.c => v2-aux.c} (76%)
 rename gdb/features/arc/{aux-v2.xml => v2-aux.xml} (86%)
 rename gdb/features/arc/{core-v2.c => v2-core.c} (91%)
 rename gdb/features/arc/{core-v2.xml => v2-core.xml} (90%)

-- 
2.28.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v6 1/4] arc: Add ARCv2 XML target along with refactoring
  2020-08-05 11:09 ` [PATCH v6 " Shahab Vahedi
@ 2020-08-05 11:09   ` Shahab Vahedi
  2020-08-05 14:31     ` Eli Zaretskii
  2020-08-21 16:16     ` Simon Marchi
  2020-08-05 11:09   ` [PATCH v6 2/4] arc: Add inclusion of "gdbarch.h" in "arc-tdep.h" Shahab Vahedi
                     ` (3 subsequent siblings)
  4 siblings, 2 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-05 11:09 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Eli Zaretskii, Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

A few changes have been made to make the register support simpler,
more flexible and extendible.  The trigger for most of these changes
are the remarks [1] made earlier for v2 of this patch.  The noticeable
improvements are:

- The arc XML target features are placed under gdb/features/arc
- There are two cores (based on ISA) and one auxiliary feature:
  v1-core: ARC600, ARC601, ARC700
  v2-core: ARC EM, ARC HS
  aux: common in both
- The XML target features represent a minimalistic sane set of
  registers irrespective of application (baremetal or linux).
- A concept of "feature" class has been introduced in the code.
  The "feature" object is constructed from BFD and GDBARCH data.
  It contains necessary information (ISA and register size) to
  determine which XML target feature to use.
- A new structure (ARC_REGISTER_FEATURE) is added that allows
  providing index, names, and the necessity of registers. This
  simplifies the sanity checks and future extendibility.
- Documnetation has been updated to reflect ARC features better.
- Although the feature names has changed, there still exists
  backward compatibility with older names through
  find_obsolete_[core,aux]_names() functions.

The last two points were inspired from RiscV port.

[1]
https://sourceware.org/pipermail/gdb-patches/2020-May/168511.html

gdb/ChangeLog:

	* arch/arc.h
	  (arc_gdbarch_features): New class to stir the selection of target XML.
	  (arc_create_target_description): Use FEATURES to choose XML target.
	  (arc_lookup_target_description): Use arc_create_target_description
	  to create _new_ target descriptions or return the already created
	  ones if the FEATURES is the same.
	* arch/arc.c: Implementation of prototypes described above.
	* gdb/arc-tdep.h (arc_regnum enum): Add more registers.
	  (arc_gdbarch_features_init): Initialize the FEATURES struct.
	* arc-tdep.c (*_feature_name): Make feature names consistent.
	  (arc_register_feature): A new struct to hold information about
	  registers of a particular target/feature.
	  (arc_check_tdesc_feature): Check if XML provides registers in
	  compliance with ARC_REGISTER_FEATURE structs.
	  (arc_update_acc_reg_names): Add aliases for r58 and r59.
	  (determine_*_reg_feature_set): Which feature name to look for.
	  (arc_gdbarch_features_init): Given MACH and ABFD, initialize FEATURES.
	  (mach_type_to_arc_isa): Convert from a set of binutils machine types
	  to expected ISA enums to be used in arc_gdbarch_features structs.
	* features/Makefile (FEATURE_XMLFILES): Add new files.
	* gdb/features/arc/v1-aux.c: New file.
	* gdb/features/arc/v1-aux.xml: Likewise.
	* gdb/features/arc/v1-core.c: Likewise.
	* gdb/features/arc/v1-core.xml: Likewise.
	* gdb/features/arc/v2-aux.c: Likewise.
	* gdb/features/arc/v2-aux.xml: Likewise.
	* gdb/features/arc/v2-core.c: Likewise.
	* gdb/features/arc/v2-core.xml: Likewise.
	* NEWS (Changes since GDB 9): Announce obsolence of old feature names.

gdb/doc/ChangeLog:

	* gdb.texinfo (Synopsys ARC): Update the documentation for ARC Features.

gdb/testsuite/ChangeLog:

	* gdb.arch/arc-tdesc-cpu.xml: Use new feature names.
---
 gdb/NEWS                                      |   5 +
 gdb/arc-tdep.c                                | 652 +++++++++++-------
 gdb/arc-tdep.h                                |  18 +-
 gdb/arch/arc.c                                | 108 ++-
 gdb/arch/arc.h                                |  79 ++-
 gdb/doc/gdb.texinfo                           |  69 +-
 gdb/features/Makefile                         |   8 +-
 .../arc/{aux-arcompact.c => v1-aux.c}         |   9 +-
 .../arc/{aux-arcompact.xml => v1-aux.xml}     |   7 +-
 .../arc/{core-arcompact.c => v1-core.c}       |   8 +-
 .../arc/{core-arcompact.xml => v1-core.xml}   |   4 +-
 gdb/features/arc/{aux-v2.c => v2-aux.c}       |   9 +-
 gdb/features/arc/{aux-v2.xml => v2-aux.xml}   |   5 +-
 gdb/features/arc/{core-v2.c => v2-core.c}     |   7 +-
 gdb/features/arc/{core-v2.xml => v2-core.xml} |   7 +-
 gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml      |   4 +-
 16 files changed, 650 insertions(+), 349 deletions(-)
 rename gdb/features/arc/{aux-arcompact.c => v1-aux.c} (73%)
 rename gdb/features/arc/{aux-arcompact.xml => v1-aux.xml} (80%)
 rename gdb/features/arc/{core-arcompact.c => v1-core.c} (87%)
 rename gdb/features/arc/{core-arcompact.xml => v1-core.xml} (92%)
 rename gdb/features/arc/{aux-v2.c => v2-aux.c} (76%)
 rename gdb/features/arc/{aux-v2.xml => v2-aux.xml} (86%)
 rename gdb/features/arc/{core-v2.c => v2-core.c} (91%)
 rename gdb/features/arc/{core-v2.xml => v2-core.xml} (90%)

diff --git a/gdb/NEWS b/gdb/NEWS
index 001dc5e4683..982f3a9cb47 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,11 @@
 
 *** Changes since GDB 9
 
+* There are new feature names for ARC targets: "org.gnu.gdb.arc.core"
+  and "org.gnu.gdb.arc.aux".  The old names are still supported but
+  must be considered obsolete.  They will be deprecated after some
+  grace period.
+
 * Help and apropos commands will now show the documentation of a
   command only once, even if that command has one or more aliases.
   These commands now show the command name, then all of its aliases,
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 7e6d29c334b..9ef929191de 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -21,6 +21,7 @@
 /* GDB header files.  */
 #include "defs.h"
 #include "arch-utils.h"
+#include "elf-bfd.h"
 #include "disasm.h"
 #include "dwarf2/frame.h"
 #include "frame-base.h"
@@ -41,6 +42,7 @@
 
 /* Standard headers.  */
 #include <algorithm>
+#include <sstream>
 
 /* The frame unwind cache for ARC.  */
 
@@ -91,63 +93,211 @@ int arc_debug;
 
 static struct cmd_list_element *maintenance_print_arc_list = NULL;
 
-/* XML target description features.  */
-
-static const char core_v2_feature_name[] = "org.gnu.gdb.arc.core.v2";
-static const char
-  core_reduced_v2_feature_name[] = "org.gnu.gdb.arc.core-reduced.v2";
-static const char
-  core_arcompact_feature_name[] = "org.gnu.gdb.arc.core.arcompact";
-static const char aux_minimal_feature_name[] = "org.gnu.gdb.arc.aux-minimal";
-
-/* XML target description known registers.  */
-
-static const char *const core_v2_register_names[] = {
-  "r0", "r1", "r2", "r3",
-  "r4", "r5", "r6", "r7",
-  "r8", "r9", "r10", "r11",
-  "r12", "r13", "r14", "r15",
-  "r16", "r17", "r18", "r19",
-  "r20", "r21", "r22", "r23",
-  "r24", "r25", "gp", "fp",
-  "sp", "ilink", "r30", "blink",
-  "r32", "r33", "r34", "r35",
-  "r36", "r37", "r38", "r39",
-  "r40", "r41", "r42", "r43",
-  "r44", "r45", "r46", "r47",
-  "r48", "r49", "r50", "r51",
-  "r52", "r53", "r54", "r55",
-  "r56", "r57", "accl", "acch",
-  "lp_count", "reserved", "limm", "pcl",
+/* A set of registers that we expect to find in a tdesc_feature.  These
+   are used in ARC_TDESC_INIT when processing the target description.  */
+
+struct arc_register_feature
+{
+  /* Information for a single register.  */
+  struct register_info
+  {
+    /* The GDB register number for this register.  */
+    int regnum;
+
+    /* List of names for this register.  The first name in this list is the
+       preferred name, the name GDB will use when describing this register.  */
+    std::vector<const char *> names;
+
+    /* When true, this register must be present in this feature set.  */
+    bool required_p;
+  };
+
+  /* The name for this feature.  This is the name used to find this feature
+     within the target description.  */
+  const char *name;
+
+  /* List of all the registers that we expect to encounter in this register
+     set.  */
+  std::vector<struct register_info> registers;
 };
 
-static const char *const aux_minimal_register_names[] = {
-  "pc", "status32",
+/* Obsolete feature names for backward compatibility.  */
+static const char *ARC_CORE_V1_OBSOLETE_FEATURE_NAME
+    = "org.gnu.gdb.arc.core.arcompact";
+static const char *ARC_CORE_V2_OBSOLETE_FEATURE_NAME
+    = "org.gnu.gdb.arc.core.v2";
+static const char *ARC_CORE_V2_REDUCED_OBSOLETE_FEATURE_NAME
+    = "org.gnu.gdb.arc.core-reduced.v2";
+static const char *ARC_AUX_OBSOLETE_FEATURE_NAME
+    = "org.gnu.gdb.arc.aux-minimal";
+/* Modern feature names.  */
+static const char *ARC_CORE_FEATURE_NAME = "org.gnu.gdb.arc.core";
+static const char *ARC_AUX_FEATURE_NAME = "org.gnu.gdb.arc.aux";
+
+/* ARCv1 (ARC600, ARC601, ARC700) general core registers feature set.
+   See also arc_update_acc_reg_names() for "accl/acch" names.  */
+
+static struct arc_register_feature arc_v1_core_reg_feature =
+{
+  ARC_CORE_FEATURE_NAME,
+  {
+    { ARC_R0_REGNUM + 0, { "r0" }, true },
+    { ARC_R0_REGNUM + 1, { "r1" }, true },
+    { ARC_R0_REGNUM + 2, { "r2" }, true },
+    { ARC_R0_REGNUM + 3, { "r3" }, true },
+    { ARC_R0_REGNUM + 4, { "r4" }, false },
+    { ARC_R0_REGNUM + 5, { "r5" }, false },
+    { ARC_R0_REGNUM + 6, { "r6" }, false },
+    { ARC_R0_REGNUM + 7, { "r7" }, false },
+    { ARC_R0_REGNUM + 8, { "r8" }, false },
+    { ARC_R0_REGNUM + 9, { "r9" }, false },
+    { ARC_R0_REGNUM + 10, { "r10" }, true },
+    { ARC_R0_REGNUM + 11, { "r11" }, true },
+    { ARC_R0_REGNUM + 12, { "r12" }, true },
+    { ARC_R0_REGNUM + 13, { "r13" }, true },
+    { ARC_R0_REGNUM + 14, { "r14" }, true },
+    { ARC_R0_REGNUM + 15, { "r15" }, true },
+    { ARC_R0_REGNUM + 16, { "r16" }, false },
+    { ARC_R0_REGNUM + 17, { "r17" }, false },
+    { ARC_R0_REGNUM + 18, { "r18" }, false },
+    { ARC_R0_REGNUM + 19, { "r19" }, false },
+    { ARC_R0_REGNUM + 20, { "r20" }, false },
+    { ARC_R0_REGNUM + 21, { "r21" }, false },
+    { ARC_R0_REGNUM + 22, { "r22" }, false },
+    { ARC_R0_REGNUM + 23, { "r23" }, false },
+    { ARC_R0_REGNUM + 24, { "r24" }, false },
+    { ARC_R0_REGNUM + 25, { "r25" }, false },
+    { ARC_R0_REGNUM + 26, { "gp" }, true },
+    { ARC_R0_REGNUM + 27, { "fp" }, true },
+    { ARC_R0_REGNUM + 28, { "sp" }, true },
+    { ARC_R0_REGNUM + 29, { "ilink1" }, false },
+    { ARC_R0_REGNUM + 30, { "ilink2" }, false },
+    { ARC_R0_REGNUM + 31, { "blink" }, true },
+    { ARC_R0_REGNUM + 32, { "r32" }, false },
+    { ARC_R0_REGNUM + 33, { "r33" }, false },
+    { ARC_R0_REGNUM + 34, { "r34" }, false },
+    { ARC_R0_REGNUM + 35, { "r35" }, false },
+    { ARC_R0_REGNUM + 36, { "r36" }, false },
+    { ARC_R0_REGNUM + 37, { "r37" }, false },
+    { ARC_R0_REGNUM + 38, { "r38" }, false },
+    { ARC_R0_REGNUM + 39, { "r39" }, false },
+    { ARC_R0_REGNUM + 40, { "r40" }, false },
+    { ARC_R0_REGNUM + 41, { "r41" }, false },
+    { ARC_R0_REGNUM + 42, { "r42" }, false },
+    { ARC_R0_REGNUM + 43, { "r43" }, false },
+    { ARC_R0_REGNUM + 44, { "r44" }, false },
+    { ARC_R0_REGNUM + 45, { "r45" }, false },
+    { ARC_R0_REGNUM + 46, { "r46" }, false },
+    { ARC_R0_REGNUM + 47, { "r47" }, false },
+    { ARC_R0_REGNUM + 48, { "r48" }, false },
+    { ARC_R0_REGNUM + 49, { "r49" }, false },
+    { ARC_R0_REGNUM + 50, { "r50" }, false },
+    { ARC_R0_REGNUM + 51, { "r51" }, false },
+    { ARC_R0_REGNUM + 52, { "r52" }, false },
+    { ARC_R0_REGNUM + 53, { "r53" }, false },
+    { ARC_R0_REGNUM + 54, { "r54" }, false },
+    { ARC_R0_REGNUM + 55, { "r55" }, false },
+    { ARC_R0_REGNUM + 56, { "r56" }, false },
+    { ARC_R0_REGNUM + 57, { "r57" }, false },
+    { ARC_R0_REGNUM + 58, { "r58", "accl" }, false },
+    { ARC_R0_REGNUM + 59, { "r59", "acch" }, false },
+    { ARC_R0_REGNUM + 60, { "lp_count" }, false },
+    { ARC_R0_REGNUM + 61, { "reserved" }, false },
+    { ARC_R0_REGNUM + 62, { "limm" }, false },
+    { ARC_R0_REGNUM + 63, { "pcl" }, true }
+  }
 };
 
-static const char *const core_arcompact_register_names[] = {
-  "r0", "r1", "r2", "r3",
-  "r4", "r5", "r6", "r7",
-  "r8", "r9", "r10", "r11",
-  "r12", "r13", "r14", "r15",
-  "r16", "r17", "r18", "r19",
-  "r20", "r21", "r22", "r23",
-  "r24", "r25", "gp", "fp",
-  "sp", "ilink1", "ilink2", "blink",
-  "r32", "r33", "r34", "r35",
-  "r36", "r37", "r38", "r39",
-  "r40", "r41", "r42", "r43",
-  "r44", "r45", "r46", "r47",
-  "r48", "r49", "r50", "r51",
-  "r52", "r53", "r54", "r55",
-  "r56", "r57", "r58", "r59",
-  "lp_count", "reserved", "limm", "pcl",
+/* ARCv2 (ARCHS) general core registers feature set.  See also
+   arc_update_acc_reg_names() for "accl/acch" names.  */
+
+static struct arc_register_feature arc_v2_core_reg_feature =
+{
+  ARC_CORE_FEATURE_NAME,
+  {
+    { ARC_R0_REGNUM + 0, { "r0" }, true },
+    { ARC_R0_REGNUM + 1, { "r1" }, true },
+    { ARC_R0_REGNUM + 2, { "r2" }, true },
+    { ARC_R0_REGNUM + 3, { "r3" }, true },
+    { ARC_R0_REGNUM + 4, { "r4" }, false },
+    { ARC_R0_REGNUM + 5, { "r5" }, false },
+    { ARC_R0_REGNUM + 6, { "r6" }, false },
+    { ARC_R0_REGNUM + 7, { "r7" }, false },
+    { ARC_R0_REGNUM + 8, { "r8" }, false },
+    { ARC_R0_REGNUM + 9, { "r9" }, false },
+    { ARC_R0_REGNUM + 10, { "r10" }, true },
+    { ARC_R0_REGNUM + 11, { "r11" }, true },
+    { ARC_R0_REGNUM + 12, { "r12" }, true },
+    { ARC_R0_REGNUM + 13, { "r13" }, true },
+    { ARC_R0_REGNUM + 14, { "r14" }, true },
+    { ARC_R0_REGNUM + 15, { "r15" }, true },
+    { ARC_R0_REGNUM + 16, { "r16" }, false },
+    { ARC_R0_REGNUM + 17, { "r17" }, false },
+    { ARC_R0_REGNUM + 18, { "r18" }, false },
+    { ARC_R0_REGNUM + 19, { "r19" }, false },
+    { ARC_R0_REGNUM + 20, { "r20" }, false },
+    { ARC_R0_REGNUM + 21, { "r21" }, false },
+    { ARC_R0_REGNUM + 22, { "r22" }, false },
+    { ARC_R0_REGNUM + 23, { "r23" }, false },
+    { ARC_R0_REGNUM + 24, { "r24" }, false },
+    { ARC_R0_REGNUM + 25, { "r25" }, false },
+    { ARC_R0_REGNUM + 26, { "gp" }, true },
+    { ARC_R0_REGNUM + 27, { "fp" }, true },
+    { ARC_R0_REGNUM + 28, { "sp" }, true },
+    { ARC_R0_REGNUM + 29, { "ilink" }, false },
+    { ARC_R0_REGNUM + 30, { "r30" }, true },
+    { ARC_R0_REGNUM + 31, { "blink" }, true },
+    { ARC_R0_REGNUM + 32, { "r32" }, false },
+    { ARC_R0_REGNUM + 33, { "r33" }, false },
+    { ARC_R0_REGNUM + 34, { "r34" }, false },
+    { ARC_R0_REGNUM + 35, { "r35" }, false },
+    { ARC_R0_REGNUM + 36, { "r36" }, false },
+    { ARC_R0_REGNUM + 37, { "r37" }, false },
+    { ARC_R0_REGNUM + 38, { "r38" }, false },
+    { ARC_R0_REGNUM + 39, { "r39" }, false },
+    { ARC_R0_REGNUM + 40, { "r40" }, false },
+    { ARC_R0_REGNUM + 41, { "r41" }, false },
+    { ARC_R0_REGNUM + 42, { "r42" }, false },
+    { ARC_R0_REGNUM + 43, { "r43" }, false },
+    { ARC_R0_REGNUM + 44, { "r44" }, false },
+    { ARC_R0_REGNUM + 45, { "r45" }, false },
+    { ARC_R0_REGNUM + 46, { "r46" }, false },
+    { ARC_R0_REGNUM + 47, { "r47" }, false },
+    { ARC_R0_REGNUM + 48, { "r48" }, false },
+    { ARC_R0_REGNUM + 49, { "r49" }, false },
+    { ARC_R0_REGNUM + 50, { "r50" }, false },
+    { ARC_R0_REGNUM + 51, { "r51" }, false },
+    { ARC_R0_REGNUM + 52, { "r52" }, false },
+    { ARC_R0_REGNUM + 53, { "r53" }, false },
+    { ARC_R0_REGNUM + 54, { "r54" }, false },
+    { ARC_R0_REGNUM + 55, { "r55" }, false },
+    { ARC_R0_REGNUM + 56, { "r56" }, false },
+    { ARC_R0_REGNUM + 57, { "r57" }, false },
+    { ARC_R0_REGNUM + 58, { "r58", "accl" }, false },
+    { ARC_R0_REGNUM + 59, { "r59", "acch" }, false },
+    { ARC_R0_REGNUM + 60, { "lp_count" }, false },
+    { ARC_R0_REGNUM + 61, { "reserved" }, false },
+    { ARC_R0_REGNUM + 62, { "limm" }, false },
+    { ARC_R0_REGNUM + 63, { "pcl" }, true }
+  }
 };
 
-static char *arc_disassembler_options = NULL;
+/* The common auxiliary registers feature set.  The REGNUM field
+   must match the ARC_REGNUM enum in arc-tdep.h.  */
 
-/* Possible arc target descriptors.  */
-static struct target_desc *tdesc_arc_list[ARC_SYS_TYPE_NUM];
+static const struct arc_register_feature arc_common_aux_reg_feature =
+{
+  ARC_AUX_FEATURE_NAME,
+  {
+    { ARC_FIRST_AUX_REGNUM + 0, { "pc" }, true },
+    { ARC_FIRST_AUX_REGNUM + 1, { "status32" }, true },
+    { ARC_FIRST_AUX_REGNUM + 2, { "lp_start" }, false },
+    { ARC_FIRST_AUX_REGNUM + 3, { "lp_end" }, false },
+    { ARC_FIRST_AUX_REGNUM + 4, { "bta" }, false }
+  }
+};
+
+static char *arc_disassembler_options = NULL;
 
 /* Functions are sorted in the order as they are used in the
    _initialize_arc_tdep (), which uses the same order as gdbarch.h.  Static
@@ -1717,192 +1867,254 @@ static const struct frame_base arc_normal_base = {
   arc_frame_base_address
 };
 
-/* Initialize target description for the ARC.
-
-   Returns TRUE if input tdesc was valid and in this case it will assign TDESC
-   and TDESC_DATA output parameters.  */
-
-static bool
-arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
-		struct tdesc_arch_data **tdesc_data)
+static enum arc_isa
+mach_type_to_arc_isa (const unsigned long mach)
 {
-  if (arc_debug)
-    debug_printf ("arc: Target description initialization.\n");
-
-  const struct target_desc *tdesc_loc = info.target_desc;
+  switch (mach)
+    {
+    case bfd_mach_arc_arc600:
+    case bfd_mach_arc_arc601:
+    case bfd_mach_arc_arc700:
+      return ARC_ISA_ARCV1;
+    case bfd_mach_arc_arcv2:
+      return ARC_ISA_ARCV2;
+    default:
+	internal_error (__FILE__, __LINE__,
+			_("unknown machine id %lu"), mach);
+    }
+}
 
-  /* Depending on whether this is ARCompact or ARCv2 we will assign
-     different default registers sets (which will differ in exactly two core
-     registers).  GDB will also refuse to accept register feature from invalid
-     ISA - v2 features can be used only with v2 ARChitecture.  We read
-     bfd_arch_info, which looks like to be a safe bet here, as it looks like it
-     is always initialized even when we don't pass any elf file to GDB at all
-     (it uses default arch in this case).  Also GDB will call this function
-     multiple times, and if XML target description file contains architecture
-     specifications, then GDB will set this architecture to info.bfd_arch_info,
-     overriding value from ELF file if they are different.  That means that,
-     where matters, this value is always our best guess on what CPU we are
-     debugging.  It has been noted that architecture specified in tdesc file
-     has higher precedence over ELF and even "set architecture" - that is,
-     using "set architecture" command will have no effect when tdesc has "arch"
-     tag.  */
-  /* Cannot use arc_mach_is_arcv2 (), because gdbarch is not created yet.  */
-  const int is_arcv2 = (info.bfd_arch_info->mach == bfd_mach_arc_arcv2);
-  bool is_reduced_rf;
-  const char *const *core_regs;
-  const char *core_feature_name;
+/* Common construction code for ARC_GDBARCH_FEATURES struct.  If there
+   is no ABFD, then a FEATURE with default values is returned.  */
 
-  /* If target doesn't provide a description, use the default ones.  */
-  if (!tdesc_has_registers (tdesc_loc))
+static arc_gdbarch_features
+arc_gdbarch_features_create (const bfd *abfd, const unsigned long mach)
+{
+  /* Use 4 as a fallback value.  */
+  int reg_size = 4;
+
+  /* Try to guess the features parameters by looking at the binary to be
+     executed.  If the user is providing a binary that does not match the
+     target, then tough luck.  This is the last effort to makes sense of
+     what's going on.  */
+  if (abfd != nullptr && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
     {
-      if (is_arcv2)
-	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCV2);
+      unsigned char eclass = elf_elfheader (abfd)->e_ident[EI_CLASS];
+
+      if (eclass == ELFCLASS32)
+	reg_size = 4;
+      else if (eclass == ELFCLASS64)
+	reg_size = 8;
       else
-	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCOMPACT);
+	internal_error (__FILE__, __LINE__,
+			_("unknown ELF header class %d"), eclass);
     }
-  else
+
+  /* MACH from a bfd_arch_info struct is used here.  It should be a safe
+     bet, as it looks like the struct is always initialized even when we
+     don't pass any elf file to GDB at all (it uses default arch in that
+     case).  */
+  arc_isa isa = mach_type_to_arc_isa (mach);
+
+  return arc_gdbarch_features (reg_size, isa);
+}
+
+/* Look for obsolete core feature names in TDESC_DATA.  */
+
+static const struct tdesc_feature *
+find_obsolete_core_names (const struct target_desc *tdesc)
+{
+  const struct tdesc_feature *feat = nullptr;
+
+  feat = tdesc_find_feature (tdesc, ARC_CORE_V1_OBSOLETE_FEATURE_NAME);
+
+  if (feat == nullptr)
+    feat = tdesc_find_feature (tdesc, ARC_CORE_V2_OBSOLETE_FEATURE_NAME);
+
+  if (feat == nullptr)
+    feat = tdesc_find_feature
+      (tdesc, ARC_CORE_V2_REDUCED_OBSOLETE_FEATURE_NAME);
+
+  return feat;
+}
+
+/* Look for obsolete aux feature names in TDESC_DATA.  */
+
+static const struct tdesc_feature *
+find_obsolete_aux_names (const struct target_desc *tdesc)
+{
+  return tdesc_find_feature (tdesc, ARC_AUX_OBSOLETE_FEATURE_NAME);
+}
+
+/* Based on the MACH value, determines which core register features set
+   must be used.  */
+
+static arc_register_feature *
+determine_core_reg_feature_set (const unsigned long mach)
+{
+  switch (mach_type_to_arc_isa (mach))
     {
-      if (arc_debug)
-	debug_printf ("arc: Using provided register set.\n");
+    case ARC_ISA_ARCV1:
+      return &arc_v1_core_reg_feature;
+    case ARC_ISA_ARCV2:
+      return &arc_v2_core_reg_feature;
+    default:
+      gdb_assert_not_reached
+        ("Unknown machine type to determine the core feature set.");
     }
-  gdb_assert (tdesc_loc != NULL);
-
-  /* Now we can search for base registers.  Core registers can be either full
-     or reduced.  Summary:
-
-     - core.v2 + aux-minimal
-     - core-reduced.v2 + aux-minimal
-     - core.arcompact + aux-minimal
-
-     NB: It is entirely feasible to have ARCompact with reduced core regs, but
-     we ignore that because GCC doesn't support that and at the same time
-     ARCompact is considered obsolete, so there is not much reason to support
-     that.  */
-  const struct tdesc_feature *feature
-    = tdesc_find_feature (tdesc_loc, core_v2_feature_name);
-  if (feature != NULL)
-    {
-      /* Confirm that register and architecture match, to prevent accidents in
-	 some situations.  This code will trigger an error if:
+}
 
-	 1. XML tdesc doesn't specify arch explicitly, registers are for arch
-	 X, but ELF specifies arch Y.
+/* At the moment, there is only 1 auxiliary register features set.
+   This is a place holder for future extendability.  */
 
-	 2. XML tdesc specifies arch X, but contains registers for arch Y.
+static const arc_register_feature *
+determine_aux_reg_feature_set ()
+{
+  return &arc_common_aux_reg_feature;
+}
 
-	 It will not protect from case where XML or ELF specify arch X,
-	 registers are for the same arch X, but the real target is arch Y.  To
-	 detect this case we need to check IDENTITY register.  */
-      if (!is_arcv2)
-	{
-	  arc_print (_("Error: ARC v2 target description supplied for "
-		       "non-ARCv2 target.\n"));
-	  return false;
-	}
+/* Update accumulator register names (ACCH/ACCL) for r58 and r59 in the
+   register sets.  The endianness determines the assignment:
 
-      is_reduced_rf = false;
-      core_feature_name = core_v2_feature_name;
-      core_regs = core_v2_register_names;
-    }
-  else
+        ,------.------.
+        | acch | accl |
+   ,----|------+------|
+   | LE | r59  | r58  |
+   | BE | r58  | r59  |
+   `----^------^------'  */
+
+static void
+arc_update_acc_reg_names (const int byte_order)
+{
+  const char *r58_alias
+    = byte_order == BFD_ENDIAN_LITTLE ? "accl" : "acch";
+  const char *r59_alias
+    = byte_order == BFD_ENDIAN_LITTLE ? "acch" : "accl";
+
+  /* Subscript 1 must be OK because those registers have 2 names.  */
+  arc_v1_core_reg_feature.registers[ARC_R58_REGNUM].names[1] = r58_alias;
+  arc_v1_core_reg_feature.registers[ARC_R59_REGNUM].names[1] = r59_alias;
+  arc_v2_core_reg_feature.registers[ARC_R58_REGNUM].names[1] = r58_alias;
+  arc_v2_core_reg_feature.registers[ARC_R59_REGNUM].names[1] = r59_alias;
+}
+
+/* Go through all the registers in REG_SET and check if they exist
+   in FEATURE.  The TDESC_DATA is updated with the register number
+   in REG_SET if it is found in the feature.  If a required register
+   is not found, this function returns false.  */
+
+static bool
+arc_check_tdesc_feature (struct tdesc_arch_data *tdesc_data,
+			 const struct tdesc_feature *feature,
+			 const struct arc_register_feature *reg_set)
+{
+  for (const auto &reg : reg_set->registers)
     {
-      feature = tdesc_find_feature (tdesc_loc, core_reduced_v2_feature_name);
-      if (feature != NULL)
+      bool found = false;
+
+      for (const char *name : reg.names)
 	{
-	  if (!is_arcv2)
-	    {
-	      arc_print (_("Error: ARC v2 target description supplied for "
-			   "non-ARCv2 target.\n"));
-	      return false;
-	    }
+	  found
+	    = tdesc_numbered_register (feature, tdesc_data, reg.regnum, name);
 
-	  is_reduced_rf = true;
-	  core_feature_name = core_reduced_v2_feature_name;
-	  core_regs = core_v2_register_names;
+	  if (found)
+	    break;
 	}
-      else
+
+      if (!found && reg.required_p)
 	{
-	  feature = tdesc_find_feature (tdesc_loc,
-					core_arcompact_feature_name);
-	  if (feature != NULL)
-	    {
-	      if (is_arcv2)
-		{
-		  arc_print (_("Error: ARCompact target description supplied "
-			       "for non-ARCompact target.\n"));
-		  return false;
-		}
-
-	      is_reduced_rf = false;
-	      core_feature_name = core_arcompact_feature_name;
-	      core_regs = core_arcompact_register_names;
-	    }
-	  else
+	  std::ostringstream reg_names;
+	  for (std::size_t i = 0; i < reg.names.size(); ++i)
 	    {
-	      arc_print (_("Error: Couldn't find core register feature in "
-			   "supplied target description."));
-	      return false;
+	      if (i == 0)
+		reg_names << "'" << reg.names[0] << "'";
+	      else
+		reg_names << " or '" << reg.names[0] << "'";
 	    }
+	  arc_print (_("Error: Cannot find required register(s) %s "
+		       "in feature '%s'.\n"), reg_names.str ().c_str (),
+		       feature->name.c_str ());
+	  return false;
 	}
     }
 
-  struct tdesc_arch_data *tdesc_data_loc = tdesc_data_alloc ();
+  return true;
+}
 
-  gdb_assert (feature != NULL);
-  int valid_p = 1;
+/* Initialize target description for the ARC.
 
-  for (int i = 0; i <= ARC_LAST_CORE_REGNUM; i++)
+   Returns true if input TDESC was valid and in this case it will assign TDESC
+   and TDESC_DATA output parameters.  */
+
+static bool
+arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
+		struct tdesc_arch_data **tdesc_data)
+{
+  const struct target_desc *tdesc_loc = info.target_desc;
+  if (arc_debug)
+    debug_printf ("arc: Target description initialization.\n");
+
+  /* If target doesn't provide a description, use the default ones.  */
+  if (!tdesc_has_registers (tdesc_loc))
     {
-      /* If rf16, then skip extra registers.  */
-      if (is_reduced_rf && ((i >= ARC_R4_REGNUM && i <= ARC_R9_REGNUM)
-			    || (i >= ARC_R16_REGNUM && i <= ARC_R25_REGNUM)))
-	continue;
-
-      valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i,
-					 core_regs[i]);
-
-      /* - Ignore errors in extension registers - they are optional.
-	 - Ignore missing ILINK because it doesn't make sense for Linux.
-	 - Ignore missing ILINK2 when architecture is ARCompact, because it
-	 doesn't make sense for Linux targets.
-
-	 In theory those optional registers should be in separate features, but
-	 that would create numerous but tiny features, which looks like an
-	 overengineering of a rather simple task.  */
-      if (!valid_p && (i <= ARC_SP_REGNUM || i == ARC_BLINK_REGNUM
-		       || i == ARC_LP_COUNT_REGNUM || i == ARC_PCL_REGNUM
-		       || (i == ARC_R30_REGNUM && is_arcv2)))
-	{
-	  arc_print (_("Error: Cannot find required register `%s' in "
-		       "feature `%s'.\n"), core_regs[i], core_feature_name);
-	  tdesc_data_cleanup (tdesc_data_loc);
-	  return false;
-	}
+      arc_gdbarch_features features
+	= arc_gdbarch_features_create (info.abfd,
+				       info.bfd_arch_info->mach);
+      tdesc_loc = arc_lookup_target_description (features);
+    }
+  gdb_assert (tdesc_loc != nullptr);
+
+  if (arc_debug)
+    debug_printf ("arc: Have got a target description\n");
+
+  const struct tdesc_feature *feature_core
+    = tdesc_find_feature (tdesc_loc, ARC_CORE_FEATURE_NAME);
+  const struct tdesc_feature *feature_aux
+    = tdesc_find_feature (tdesc_loc, ARC_AUX_FEATURE_NAME);
+
+  /* Maybe there still is a chance to salvage the input.  */
+  if (feature_core == nullptr)
+    feature_core = find_obsolete_core_names (tdesc_loc);
+  if (feature_aux == nullptr)
+    feature_aux = find_obsolete_aux_names (tdesc_loc);
+
+  if (feature_core == nullptr)
+    {
+      arc_print (_("Error: Cannot find required feature '%s' in supplied "
+		   "target description.\n"), ARC_CORE_FEATURE_NAME);
+      return false;
     }
 
-  /* Mandatory AUX registers are intentionally few and are common between
-     ARCompact and ARC v2, so same code can be used for both.  */
-  feature = tdesc_find_feature (tdesc_loc, aux_minimal_feature_name);
-  if (feature == NULL)
+  if (feature_aux == nullptr)
     {
-      arc_print (_("Error: Cannot find required feature `%s' in supplied "
-		   "target description.\n"), aux_minimal_feature_name);
-      tdesc_data_cleanup (tdesc_data_loc);
+      arc_print (_("Error: Cannot find required feature '%s' in supplied "
+		   "target description.\n"), ARC_AUX_FEATURE_NAME);
       return false;
     }
 
-  for (int i = ARC_FIRST_AUX_REGNUM; i <= ARC_LAST_AUX_REGNUM; i++)
+  const auto arc_core_reg_feature
+    = determine_core_reg_feature_set (info.bfd_arch_info->mach);
+  const auto arc_aux_reg_feature
+    = determine_aux_reg_feature_set ();
+
+  struct tdesc_arch_data *tdesc_data_loc = tdesc_data_alloc ();
+
+  arc_update_acc_reg_names (info.byte_order);
+
+  bool valid_p = arc_check_tdesc_feature (tdesc_data_loc,
+					  feature_core,
+					  arc_core_reg_feature);
+
+  valid_p &= arc_check_tdesc_feature (tdesc_data_loc,
+				      feature_aux,
+				      arc_aux_reg_feature);
+
+  if (!valid_p)
     {
-      const char *name = aux_minimal_register_names[i - ARC_FIRST_AUX_REGNUM];
-      valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i, name);
-      if (!valid_p)
-	{
-	  arc_print (_("Error: Cannot find required register `%s' "
-		       "in feature `%s'.\n"),
-		     name, tdesc_feature_name (feature));
-	  tdesc_data_cleanup (tdesc_data_loc);
-	  return false;
-	}
+      if (arc_debug)
+        debug_printf ("arc: Target description is not valid\n");
+      tdesc_data_cleanup (tdesc_data_loc);
+      return false;
     }
 
   *tdesc = tdesc_loc;
@@ -2131,38 +2343,6 @@ dump_arc_instruction_command (const char *args, int from_tty)
   arc_insn_dump (insn);
 }
 
-/* See arc-tdep.h.  */
-
-const target_desc *
-arc_read_description (arc_sys_type sys_type)
-{
-  if (arc_debug)
-    debug_printf ("arc: Reading target description for \"%s\".\n",
-		  arc_sys_type_to_str (sys_type));
-
-  gdb_assert ((sys_type >= 0) && (sys_type < ARC_SYS_TYPE_NUM));
-  struct target_desc *tdesc = tdesc_arc_list[sys_type];
-
-  if (tdesc == nullptr)
-    {
-      tdesc = arc_create_target_description (sys_type);
-      tdesc_arc_list[sys_type] = tdesc;
-
-      if (arc_debug)
-	{
-	  const char *arch = tdesc_architecture_name (tdesc);
-	  const char *abi = tdesc_osabi_name (tdesc);
-	  arch = arch != NULL ? arch : "";
-	  abi = abi != NULL ? abi : "";
-	  debug_printf ("arc: Created target description for "
-			"\"%s\": arch=\"%s\", ABI=\"%s\"\n",
-			arc_sys_type_to_str (sys_type), arch, abi);
-	}
-    }
-
-  return tdesc;
-}
-
 void _initialize_arc_tdep ();
 void
 _initialize_arc_tdep ()
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index d72332c7638..6ca759a661d 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -35,7 +35,6 @@ enum arc_regnum
   {
     /* Core registers.  */
     ARC_R0_REGNUM = 0,
-    ARC_FIRST_CORE_REGNUM = ARC_R0_REGNUM,
     ARC_R1_REGNUM = 1,
     ARC_R4_REGNUM = 4,
     ARC_R7_REGNUM = 7,
@@ -54,6 +53,9 @@ enum arc_regnum
     ARC_R30_REGNUM,
     /* Return address from function.  */
     ARC_BLINK_REGNUM,
+    /* Accumulator registers.  */
+    ARC_R58_REGNUM = 58,
+    ARC_R59_REGNUM,
     /* Zero-delay loop counter.  */
     ARC_LP_COUNT_REGNUM = 60,
     /* Reserved register number.  There should never be a register with such
@@ -69,14 +71,21 @@ enum arc_regnum
     /* Program counter, aligned to 4-bytes, read-only.  */
     ARC_PCL_REGNUM,
     ARC_LAST_CORE_REGNUM = ARC_PCL_REGNUM,
+
     /* AUX registers.  */
     /* Actual program counter.  */
     ARC_PC_REGNUM,
     ARC_FIRST_AUX_REGNUM = ARC_PC_REGNUM,
     /* Status register.  */
     ARC_STATUS32_REGNUM,
-    ARC_LAST_REGNUM = ARC_STATUS32_REGNUM,
-    ARC_LAST_AUX_REGNUM = ARC_STATUS32_REGNUM,
+    /* Zero-delay loop start instruction.  */
+    ARC_LP_START_REGNUM,
+    /* Zero-delay loop next-after-last instruction.  */
+    ARC_LP_END_REGNUM,
+    /* Branch target address.  */
+    ARC_BTA_REGNUM,
+    ARC_LAST_AUX_REGNUM = ARC_BTA_REGNUM,
+    ARC_LAST_REGNUM = ARC_LAST_AUX_REGNUM,
 
     /* Additional ABI constants.  */
     ARC_FIRST_ARG_REGNUM = ARC_R0_REGNUM,
@@ -164,7 +173,4 @@ CORE_ADDR arc_insn_get_branch_target (const struct arc_instruction &insn);
 
 CORE_ADDR arc_insn_get_linear_next_pc (const struct arc_instruction &insn);
 
-/* Get the correct ARC target description for the given system type.  */
-const target_desc *arc_read_description (arc_sys_type sys_type);
-
 #endif /* ARC_TDEP_H */
diff --git a/gdb/arch/arc.c b/gdb/arch/arc.c
index 9552b4aff97..8e126ca5a82 100644
--- a/gdb/arch/arc.c
+++ b/gdb/arch/arc.c
@@ -17,42 +17,106 @@
 
 
 #include "gdbsupport/common-defs.h"
-#include <stdlib.h>
-
 #include "arc.h"
+#include <stdlib.h>
+#include <unordered_map>
+#include <string>
 
 /* Target description features.  */
-#include "features/arc/core-v2.c"
-#include "features/arc/aux-v2.c"
-#include "features/arc/core-arcompact.c"
-#include "features/arc/aux-arcompact.c"
+#include "features/arc/v1-core.c"
+#include "features/arc/v1-aux.c"
+#include "features/arc/v2-core.c"
+#include "features/arc/v2-aux.c"
 
-/* See arc.h.  */
+#ifndef GDBSERVER
+#define STATIC_IN_GDB static
+#else
+#define STATIC_IN_GDB
+#endif
 
-target_desc *
-arc_create_target_description (arc_sys_type sys_type)
+STATIC_IN_GDB target_desc *
+arc_create_target_description (const struct arc_gdbarch_features &features)
 {
+  /* Create a new target description.  */
   target_desc *tdesc = allocate_target_description ();
 
-  long regnum = 0;
-
 #ifndef IN_PROCESS_AGENT
-  if (sys_type == ARC_SYS_TYPE_ARCV2)
-    set_tdesc_architecture (tdesc, "arc:ARCv2");
-  else
-    set_tdesc_architecture (tdesc, "arc:ARC700");
-#endif
+  std::string arch_name;
 
-  if (sys_type == ARC_SYS_TYPE_ARCV2)
+  /* Architecture names here must match the ones in
+     ARCH_INFO_STRUCT in bfd/cpu-arc.c.  */
+  if (features.isa == ARC_ISA_ARCV1 && features.reg_size == 4)
+      arch_name = "arc:ARC700";
+  else if (features.isa == ARC_ISA_ARCV2 && features.reg_size == 4)
+      arch_name = "arc:ARCv2";
+  else
     {
-      regnum = create_feature_arc_core_v2 (tdesc, regnum);
-      regnum = create_feature_arc_aux_v2 (tdesc, regnum);
+      std::string msg = string_printf
+	("Cannot determine architecture: ISA=%d; bitness=%d",
+	 features.isa, 8 * features.reg_size);
+      gdb_assert_not_reached (msg.c_str ());
     }
-  else
+
+  set_tdesc_architecture (tdesc, arch_name.c_str ());
+#endif
+
+  long regnum = 0;
+
+  switch (features.isa)
     {
-      regnum = create_feature_arc_core_arcompact (tdesc, regnum);
-      regnum = create_feature_arc_aux_arcompact (tdesc, regnum);
+    case ARC_ISA_ARCV1:
+      regnum = create_feature_arc_v1_core (tdesc, regnum);
+      regnum = create_feature_arc_v1_aux (tdesc, regnum);
+      break;
+    case ARC_ISA_ARCV2:
+      regnum = create_feature_arc_v2_core (tdesc, regnum);
+      regnum = create_feature_arc_v2_aux (tdesc, regnum);
+      break;
+    default:
+      std::string msg = string_printf
+	("Cannot choose target description XML: %d", features.isa);
+      gdb_assert_not_reached (msg.c_str ());
     }
 
   return tdesc;
 }
+
+#ifndef GDBSERVER
+
+/* Wrapper used by std::unordered_map to generate hash for features set.  */
+struct arc_gdbarch_features_hasher
+{
+  std::size_t
+  operator() (const arc_gdbarch_features &features) const noexcept
+  {
+    return features.hash ();
+  }
+};
+
+/* Cache of previously created target descriptions, indexed by the hash
+   of the features set used to create them.  */
+static std::unordered_map<arc_gdbarch_features,
+			  const target_desc_up,
+			  arc_gdbarch_features_hasher> arc_tdesc_cache;
+
+/* See arch/arc.h.  */
+
+const target_desc *
+arc_lookup_target_description (const struct arc_gdbarch_features &features)
+{
+  /* Lookup in the cache first.  If found, return the pointer from the
+     "target_desc_up" type which is a "unique_ptr".  This should be fine
+     as the "arc_tdesc_cache" will persist until GDB terminates.  */
+  const auto it = arc_tdesc_cache.find (features);
+  if (it != arc_tdesc_cache.end ())
+    return it->second.get ();
+
+  target_desc *tdesc = arc_create_target_description (features);
+
+  /* Add the newly created target description to the repertoire.  */
+  arc_tdesc_cache.emplace (features, tdesc);
+
+  return tdesc;
+}
+
+#endif /* !GDBSERVER */
diff --git a/gdb/arch/arc.h b/gdb/arch/arc.h
index fd806ae7d34..a5313b1fee6 100644
--- a/gdb/arch/arc.h
+++ b/gdb/arch/arc.h
@@ -20,29 +20,68 @@
 
 #include "gdbsupport/tdesc.h"
 
-/* Supported ARC system hardware types.  */
-enum arc_sys_type
+/* Supported ARC ISAs.  */
+enum arc_isa
 {
-  ARC_SYS_TYPE_ARCOMPACT = 0,	  /* ARC600 or ARC700 */
-  ARC_SYS_TYPE_ARCV2,		  /* ARC EM or ARC HS */
-  ARC_SYS_TYPE_NUM
+  ARC_ISA_ARCV1 = 1,  /* a.k.a. ARCompact (ARC600, ARC700)  */
+  ARC_ISA_ARCV2	      /* such as ARC EM and ARC HS  */
 };
 
-static inline const char *
-arc_sys_type_to_str (const arc_sys_type type)
+struct arc_gdbarch_features
 {
-  switch (type)
-    {
-    case ARC_SYS_TYPE_ARCOMPACT:
-      return "ARC_SYS_TYPE_ARCOMPACT";
-    case ARC_SYS_TYPE_ARCV2:
-      return "ARC_SYS_TYPE_ARCV2";
-    default:
-      return "Invalid";
-    }
-}
-
-/* Create target description for the specified system type.  */
-target_desc *arc_create_target_description (arc_sys_type sys_type);
+  arc_gdbarch_features (int reg_size, arc_isa isa)
+    : reg_size (reg_size), isa (isa)
+  {}
+
+  /* Register size in bytes.  Possible values are 4, and 8.  A 0 indicates
+     an uninitialised value.  */
+  const int reg_size;
+
+  /* See ARC_ISA enum.  */
+  const arc_isa isa;
+
+  /* Equality operator.  */
+  bool operator== (const struct arc_gdbarch_features &rhs) const
+  {
+    return (reg_size == rhs.reg_size && isa == rhs.isa);
+  }
+
+  /* Inequality operator.  */
+  bool operator!= (const struct arc_gdbarch_features &rhs) const
+  {
+    return !(*this == rhs);
+  }
+
+  /* Used by std::unordered_map to hash the feature sets.  The hash is
+     calculated in the manner below:
+     REG_SIZE |  ISA
+      5-bits  | 4-bits  */
+
+  std::size_t hash () const noexcept
+  {
+    std::size_t val = ((reg_size & 0x1f) << 8 | (isa & 0xf) << 0);
+    return val;
+  }
+};
+
+#ifdef GDBSERVER
+
+/* Create and return a target description that is compatible with FEATURES.
+   The only external client of this must be the gdbserver which manipulates
+   the returned data.  */
+
+target_desc *arc_create_target_description
+	(const struct arc_gdbarch_features &features);
+
+#else
+
+/* Lookup the cache for a target description matching the FEATURES.
+   If nothing is found, then create one and return it.  */
+
+const target_desc *arc_lookup_target_description
+	(const struct arc_gdbarch_features &features);
+
+#endif /* GDBSERVER */
+
 
 #endif /* ARCH_ARC_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index a002084d5b9..8cfdb8ccc92 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -45205,40 +45205,41 @@ it should contain registers @samp{pauth_dmask} and @samp{pauth_cmask}.
 @subsection ARC Features
 @cindex target descriptions, ARC Features
 
-ARC processors are highly configurable, so even core registers and their number
-are not completely predetermined.  In addition flags and PC registers which are
-important to @value{GDBN} are not ``core'' registers in ARC.  It is required
-that one of the core registers features is present.
-@samp{org.gnu.gdb.arc.aux-minimal} feature is mandatory.
-
-The @samp{org.gnu.gdb.arc.core.v2} feature is required for ARC EM and ARC HS
-targets with a normal register file.  It should contain registers @samp{r0}
-through @samp{r25}, @samp{gp}, @samp{fp}, @samp{sp}, @samp{r30}, @samp{blink},
-@samp{lp_count} and @samp{pcl}.  This feature may contain register @samp{ilink}
-and any of extension core registers @samp{r32} through @samp{r59/acch}.
-@samp{ilink} and extension core registers are not available to read/write, when
-debugging GNU/Linux applications, thus @samp{ilink} is made optional.
-
-The @samp{org.gnu.gdb.arc.core-reduced.v2} feature is required for ARC EM and
-ARC HS targets with a reduced register file.  It should contain registers
-@samp{r0} through @samp{r3}, @samp{r10} through @samp{r15}, @samp{gp},
-@samp{fp}, @samp{sp}, @samp{r30}, @samp{blink}, @samp{lp_count} and @samp{pcl}.
-This feature may contain register @samp{ilink} and any of extension core
-registers @samp{r32} through @samp{r59/acch}.
-
-The @samp{org.gnu.gdb.arc.core.arcompact} feature is required for ARCompact
-targets with a normal register file.  It should contain registers @samp{r0}
-through @samp{r25}, @samp{gp}, @samp{fp}, @samp{sp}, @samp{r30}, @samp{blink},
-@samp{lp_count} and @samp{pcl}.  This feature may contain registers
-@samp{ilink1}, @samp{ilink2} and any of extension core registers @samp{r32}
-through @samp{r59/acch}.  @samp{ilink1} and @samp{ilink2} and extension core
-registers are not available when debugging GNU/Linux applications.  The only
-difference with @samp{org.gnu.gdb.arc.core.v2} feature is in the names of
-@samp{ilink1} and @samp{ilink2} registers and that @samp{r30} is mandatory in
-ARC v2, but @samp{ilink2} is optional on ARCompact.
-
-The @samp{org.gnu.gdb.arc.aux-minimal} feature is required for all ARC
-targets.  It should contain registers @samp{pc} and @samp{status32}.
+ARC processors are so configurable that even core registers and their numbers
+are not predetermined completely.  Moreover, @emph{flags} and @emph{PC}
+registers, which are important to @value{GDBN}, are not ``core'' registers in
+ARC.  Therefore, there are two features that their presence is mandatory:
+@samp{org.gnu.gdb.arc.core} and @samp{org.gnu.gdb.arc.aux}.
+
+The @samp{org.gnu.gdb.arc.core} feature is required for all targets.  It must
+contain registers:
+
+@itemize @minus
+@item
+@samp{r0} through @samp{r25} for normal register file targets.
+@item
+@samp{r0} through @samp{r3}, and @samp{r10} through @samp{r15} for reduced
+register file targets.
+@item
+@samp{gp}, @samp{fp}, @samp{sp}, @samp{r30}@footnote{Not necessary for ARCv1.},
+@samp{blink}, @samp{lp_count}, @samp{pcl}.
+@end itemize
+
+In case of an ARCompact target (ARCv1 ISA), the @samp{org.gnu.gdb.arc.core}
+feature may contain registers @samp{ilink1} and @samp{ilink2}.  While in case
+of ARC EM and ARC HS targets (ARCv2 ISA), register @samp{ilink} may be present.
+The difference between ARCv1 and ARCv2 is the naming of registers @emph{29th}
+and @emph{30th}.  They are called @samp{ilink1} and @samp{ilink2} for ARCv1 and
+are optional.  For ARCv2, they are called @samp{ilink} and @samp{r30} and only
+@samp{ilink} is optional.  The optionality of @samp{ilink*} registers is
+because of their inaccessibility during user space debugging sessions.
+
+Extension core registers @samp{r32} through @samp{r59} are optional and their
+existence depends on the configuration.  When debugging GNU/Linux applications,
+i.e. user space debugging, these core registers are not available.
+
+The @samp{org.gnu.gdb.arc.aux} feature is required for all ARC targets.  It
+should at least contain @samp{pc} and @samp{status32} registers.
 
 @node ARM Features
 @subsection ARM Features
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index d0af9a47b48..689603847a0 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -201,10 +201,10 @@ $(outdir)/%.dat: %.xml number-regs.xsl sort-regs.xsl gdbserver-regs.xsl
 FEATURE_XMLFILES = aarch64-core.xml \
 	aarch64-fpu.xml \
 	aarch64-pauth.xml \
-	arc/core-v2.xml \
-	arc/aux-v2.xml \
-	arc/core-arcompact.xml \
-	arc/aux-arcompact.xml \
+	arc/v1-core.xml \
+	arc/v1-aux.xml \
+	arc/v2-core.xml \
+	arc/v2-aux.xml \
 	arm/arm-core.xml \
 	arm/arm-fpa.xml \
 	arm/arm-m-profile.xml \
diff --git a/gdb/features/arc/aux-arcompact.c b/gdb/features/arc/v1-aux.c
similarity index 73%
rename from gdb/features/arc/aux-arcompact.c
rename to gdb/features/arc/v1-aux.c
index d8e8c74e639..d1540763433 100644
--- a/gdb/features/arc/aux-arcompact.c
+++ b/gdb/features/arc/v1-aux.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: aux-arcompact.xml */
+  Original: v1-aux.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_aux_arcompact (struct target_desc *result, long regnum)
+create_feature_arc_v1_aux (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux-minimal");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux");
   tdesc_type_with_fields *type_with_fields;
   type_with_fields = tdesc_create_flags (feature, "status32_type", 4);
   tdesc_add_flag (type_with_fields, 0, "H");
@@ -27,5 +27,8 @@ create_feature_arc_aux_arcompact (struct target_desc *result, long regnum)
 
   tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "status32", regnum++, 1, NULL, 32, "status32_type");
+  tdesc_create_reg (feature, "lp_start", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "lp_end", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "bta", regnum++, 1, NULL, 32, "code_ptr");
   return regnum;
 }
diff --git a/gdb/features/arc/aux-arcompact.xml b/gdb/features/arc/v1-aux.xml
similarity index 80%
rename from gdb/features/arc/aux-arcompact.xml
rename to gdb/features/arc/v1-aux.xml
index bf68112f5db..091808b1e29 100644
--- a/gdb/features/arc/aux-arcompact.xml
+++ b/gdb/features/arc/v1-aux.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.aux-minimal">
+<feature name="org.gnu.gdb.arc.aux">
   <flags id="status32_type" size="4">
       <field name="H"   start="0" end="0"/>
       <field name="E"   start="1" end="2"/>
@@ -19,10 +19,13 @@
       <field name="N"   start="10" end="10"/>
       <field name="Z"   start="11" end="11"/>
       <field name="L"   start="12" end="12"/>
-      <field name="R"  start="13" end="13"/>
+      <field name="R"   start="13" end="13"/>
       <field name="SE"  start="14" end="14"/>
   </flags>
 
   <reg name="pc"       bitsize="32" type="code_ptr"/>
   <reg name="status32" bitsize="32" type="status32_type"/>
+  <reg name="lp_start" bitsize="32" type="code_ptr"/>
+  <reg name="lp_end"   bitsize="32" type="code_ptr"/>
+  <reg name="bta"      bitsize="32" type="code_ptr"/>
 </feature>
diff --git a/gdb/features/arc/core-arcompact.c b/gdb/features/arc/v1-core.c
similarity index 87%
rename from gdb/features/arc/core-arcompact.c
rename to gdb/features/arc/v1-core.c
index 7d9a4b23c21..df51d4788df 100644
--- a/gdb/features/arc/core-arcompact.c
+++ b/gdb/features/arc/v1-core.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: core-arcompact.xml */
+  Original: v1-core.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_core_arcompact (struct target_desc *result, long regnum)
+create_feature_arc_v1_core (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core.arcompact");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core");
   tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
@@ -38,8 +38,6 @@ create_feature_arc_core_arcompact (struct target_desc *result, long regnum)
   tdesc_create_reg (feature, "gp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "fp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
-  tdesc_create_reg (feature, "ilink1", regnum++, 1, NULL, 32, "code_ptr");
-  tdesc_create_reg (feature, "ilink2", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "blink", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "lp_count", regnum++, 1, NULL, 32, "uint32");
   tdesc_create_reg (feature, "pcl", regnum++, 1, NULL, 32, "code_ptr");
diff --git a/gdb/features/arc/core-arcompact.xml b/gdb/features/arc/v1-core.xml
similarity index 92%
rename from gdb/features/arc/core-arcompact.xml
rename to gdb/features/arc/v1-core.xml
index 9209891b41a..68d04bdf9d0 100644
--- a/gdb/features/arc/core-arcompact.xml
+++ b/gdb/features/arc/v1-core.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.core.arcompact">
+<feature name="org.gnu.gdb.arc.core">
   <reg name="r0"  bitsize="32"/>
   <reg name="r1"  bitsize="32"/>
   <reg name="r2"  bitsize="32"/>
@@ -40,8 +40,6 @@
   <reg name="sp"  bitsize="32" type="data_ptr"/>
 
   <!-- Code pointers.  -->
-  <reg name="ilink1" bitsize="32" type="code_ptr"/>
-  <reg name="ilink2" bitsize="32" type="code_ptr"/>
   <reg name="blink"  bitsize="32" type="code_ptr"/>
 
   <!-- Here goes extension core registers: r32 - r59 -->
diff --git a/gdb/features/arc/aux-v2.c b/gdb/features/arc/v2-aux.c
similarity index 76%
rename from gdb/features/arc/aux-v2.c
rename to gdb/features/arc/v2-aux.c
index 6290b9b1a7f..7b38e377fe1 100644
--- a/gdb/features/arc/aux-v2.c
+++ b/gdb/features/arc/v2-aux.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: aux-v2.xml */
+  Original: v2-aux.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_aux_v2 (struct target_desc *result, long regnum)
+create_feature_arc_v2_aux (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux-minimal");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux");
   tdesc_type_with_fields *type_with_fields;
   type_with_fields = tdesc_create_flags (feature, "status32_type", 4);
   tdesc_add_flag (type_with_fields, 0, "H");
@@ -31,5 +31,8 @@ create_feature_arc_aux_v2 (struct target_desc *result, long regnum)
 
   tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "status32", regnum++, 1, NULL, 32, "status32_type");
+  tdesc_create_reg (feature, "lp_start", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "lp_end", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "bta", regnum++, 1, NULL, 32, "code_ptr");
   return regnum;
 }
diff --git a/gdb/features/arc/aux-v2.xml b/gdb/features/arc/v2-aux.xml
similarity index 86%
rename from gdb/features/arc/aux-v2.xml
rename to gdb/features/arc/v2-aux.xml
index 2701fad72dc..5d81e248088 100644
--- a/gdb/features/arc/aux-v2.xml
+++ b/gdb/features/arc/v2-aux.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.aux-minimal">
+<feature name="org.gnu.gdb.arc.aux">
   <flags id="status32_type" size="4">
       <field name="H"   start="0" end="0"/>
       <field name="E"   start="1" end="4"/>
@@ -29,4 +29,7 @@
 
   <reg name="pc"       bitsize="32" type="code_ptr"/>
   <reg name="status32" bitsize="32" type="status32_type"/>
+  <reg name="lp_start" bitsize="32" type="code_ptr"/>
+  <reg name="lp_end"   bitsize="32" type="code_ptr"/>
+  <reg name="bta"      bitsize="32" type="code_ptr"/>
 </feature>
diff --git a/gdb/features/arc/core-v2.c b/gdb/features/arc/v2-core.c
similarity index 91%
rename from gdb/features/arc/core-v2.c
rename to gdb/features/arc/v2-core.c
index d37da990457..1c3ef1a91df 100644
--- a/gdb/features/arc/core-v2.c
+++ b/gdb/features/arc/v2-core.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: core-v2.xml */
+  Original: v2-core.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_core_v2 (struct target_desc *result, long regnum)
+create_feature_arc_v2_core (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core.v2");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core");
   tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
@@ -38,7 +38,6 @@ create_feature_arc_core_v2 (struct target_desc *result, long regnum)
   tdesc_create_reg (feature, "gp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "fp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
-  tdesc_create_reg (feature, "ilink", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "r30", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "blink", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "lp_count", regnum++, 1, NULL, 32, "uint32");
diff --git a/gdb/features/arc/core-v2.xml b/gdb/features/arc/v2-core.xml
similarity index 90%
rename from gdb/features/arc/core-v2.xml
rename to gdb/features/arc/v2-core.xml
index 1b17968fb2e..2a2561eab16 100644
--- a/gdb/features/arc/core-v2.xml
+++ b/gdb/features/arc/v2-core.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.core.v2">
+<feature name="org.gnu.gdb.arc.core">
   <reg name="r0"  bitsize="32"/>
   <reg name="r1"  bitsize="32"/>
   <reg name="r2"  bitsize="32"/>
@@ -42,12 +42,11 @@
   <!-- Code pointers.  R30 is general purpose, but it used to be ILINK2 in
   ARCompact, thus its odd position in between of special purpose registers.
   GCC does't use this register, so it isn't a member of a general group. -->
-  <reg name="ilink" bitsize="32" type="code_ptr"/>
   <reg name="r30"   bitsize="32" group=""/>
   <reg name="blink" bitsize="32" type="code_ptr"/>
 
-  <!-- Here goes extension core registers: r32 - r57.  -->
-  <!-- Here goes ACCL/ACCH registers, r58, r59.  -->
+  <!-- Extension core registers: r32 - r57.  -->
+  <!-- ACCL/ACCH registers: r58, r59.  -->
 
   <!-- Loop counter.  -->
   <reg name="lp_count" bitsize="32" type="uint32"/>
diff --git a/gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml b/gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml
index 09689b8a44b..0ae2190c511 100644
--- a/gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml
+++ b/gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml
@@ -9,7 +9,7 @@
 <target>
   <architecture>arc:HS</architecture>
 
-  <feature name="org.gnu.gdb.arc.core.v2">
+  <feature name="org.gnu.gdb.arc.core">
     <reg name="r0"  bitsize="32"/>
     <reg name="r1"  bitsize="32"/>
     <reg name="r2"  bitsize="32"/>
@@ -46,7 +46,7 @@
     <reg name="pcl" bitsize="32"/>
   </feature>
 
-  <feature name="org.gnu.gdb.arc.aux-minimal">
+  <feature name="org.gnu.gdb.arc.aux">
     <reg name="pc"       bitsize="32"/>
     <reg name="status32" bitsize="32"/>
   </feature>
-- 
2.28.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v6 2/4] arc: Add inclusion of "gdbarch.h" in "arc-tdep.h"
  2020-08-05 11:09 ` [PATCH v6 " Shahab Vahedi
  2020-08-05 11:09   ` [PATCH v6 1/4] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
@ 2020-08-05 11:09   ` Shahab Vahedi
  2020-08-05 11:09   ` [PATCH v6 3/4] arc: Add hardware loop detection Shahab Vahedi
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-05 11:09 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Eli Zaretskii, Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

The "arc-tdep.h" makes use of definitions in "gdbarch.h", but it
does not include it explicitly.  I have piggy backed this fix
in another commit [1], but I was asked to do it separately [2].

[1] arc: Add hardware loop detection
https://sourceware.org/pipermail/gdb-patches/2020-July/170800.html

[2] Simon's remarks to "arc: Add hardware loop detection"
https://sourceware.org/pipermail/gdb-patches/2020-August/170993.html

gdb/ChangeLog:

	* arc-tdep.h: Include "gdbarch.h".
---
 gdb/arc-tdep.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index 6ca759a661d..5968abd4600 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -23,6 +23,7 @@
 
 /* Need disassemble_info.  */
 #include "dis-asm.h"
+#include "gdbarch.h"
 #include "arch/arc.h"
 
 /* To simplify GDB code this enum assumes that internal regnums should be same
-- 
2.28.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v6 3/4] arc: Add hardware loop detection
  2020-08-05 11:09 ` [PATCH v6 " Shahab Vahedi
  2020-08-05 11:09   ` [PATCH v6 1/4] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
  2020-08-05 11:09   ` [PATCH v6 2/4] arc: Add inclusion of "gdbarch.h" in "arc-tdep.h" Shahab Vahedi
@ 2020-08-05 11:09   ` Shahab Vahedi
  2020-08-05 11:09   ` [PATCH v6 4/4] arc: Add GNU/Linux support for ARC Shahab Vahedi
  2020-08-17  8:07   ` [PATCH v6 0/4] arc: Add GNU/Linux support Shahab Vahedi
  4 siblings, 0 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-05 11:09 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Eli Zaretskii, Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

For ARC there are registers that are not part of a required set in XML
target descriptions by default, but are almost always present on ARC
targets and are universally exposed by the ptrace interface.  Hardware
loop registers being one of them.

LP_START and LP_END auxiliary registers are hardware loop start and end.
Formally, they are optional, but it is hard to find an ARC configuration
that doesn't have them.  They are always present in processors that can
run GNU/Linux.  GDB needs to know about those registers to implement
proper software single stepping, since they affect  what instruction
will be next.

This commit adds the code to check for the existance of "lp_start" and
"lp_end" in XML target descriptions. If they exist, then the function
reports that the target supports hardware loops.

gdb/ChangeLog:

	* arc-tdep.c (arc_check_for_hardware_loop): New.
	* arc-tdep.h (gdbarch_tdep): New field has_hw_loops.

gdb/doc/ChangeLog:

	* gdb.texinfo (Synopsys ARC): Document LP_START, LP_END and BTA.
---
 gdb/arc-tdep.c      | 39 +++++++++++++++++++++++++++++++++++----
 gdb/arc-tdep.h      |  3 +++
 gdb/doc/gdb.texinfo | 11 +++++++++--
 3 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 9ef929191de..54f67a03818 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -2041,6 +2041,35 @@ arc_check_tdesc_feature (struct tdesc_arch_data *tdesc_data,
   return true;
 }
 
+/* Check for the existance of "lp_start" and "lp_end" in target description.
+   If both are present, assume there is hardware loop support in the target.
+   This can be improved by looking into "lpc_size" field of "isa_config"
+   auxiliary register.  */
+
+static bool
+arc_check_for_hw_loops (const struct target_desc *tdesc,
+			struct tdesc_arch_data *data)
+{
+  const auto feature_aux = tdesc_find_feature (tdesc, ARC_AUX_FEATURE_NAME);
+  const auto aux_regset = determine_aux_reg_feature_set ();
+
+  if (feature_aux == nullptr)
+    return false;
+
+  bool hw_loop_p = false;
+  const auto lp_start_name =
+    aux_regset->registers[ARC_LP_START_REGNUM - ARC_FIRST_AUX_REGNUM].names[0];
+  const auto lp_end_name =
+    aux_regset->registers[ARC_LP_END_REGNUM - ARC_FIRST_AUX_REGNUM].names[0];
+
+  hw_loop_p = tdesc_numbered_register (feature_aux, data,
+				       ARC_LP_START_REGNUM, lp_start_name);
+  hw_loop_p &= tdesc_numbered_register (feature_aux, data,
+				       ARC_LP_END_REGNUM, lp_end_name);
+
+  return hw_loop_p;
+}
+
 /* Initialize target description for the ARC.
 
    Returns true if input TDESC was valid and in this case it will assign TDESC
@@ -2163,13 +2192,15 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     debug_printf ("arc: Architecture initialization.\n");
 
   if (!arc_tdesc_init (info, &tdesc, &tdesc_data))
-    return NULL;
+    return nullptr;
 
   /* Allocate the ARC-private target-dependent information structure, and the
      GDB target-independent information structure.  */
-  struct gdbarch_tdep *tdep = XCNEW (struct gdbarch_tdep);
+  gdb::unique_xmalloc_ptr<struct gdbarch_tdep> tdep
+    (XCNEW (struct gdbarch_tdep));
   tdep->jb_pc = -1; /* No longjmp support by default.  */
-  struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep);
+  tdep->has_hw_loops = arc_check_for_hw_loops (tdesc, tdesc_data);
+  struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep.release ());
 
   /* Data types.  */
   set_gdbarch_short_bit (gdbarch, 16);
@@ -2250,7 +2281,7 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      It can override functions set earlier.  */
   gdbarch_init_osabi (info, gdbarch);
 
-  if (tdep->jb_pc >= 0)
+  if (gdbarch_tdep (gdbarch)->jb_pc >= 0)
     set_gdbarch_get_longjmp_target (gdbarch, arc_get_longjmp_target);
 
   /* Disassembler options.  Enforce CPU if it was specified in XML target
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index 5968abd4600..e752348a262 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -111,6 +111,9 @@ struct gdbarch_tdep
   /* Offset to PC value in jump buffer.  If this is negative, longjmp
      support will be disabled.  */
   int jb_pc;
+
+  /* Whether target has hardware (aka zero-delay) loops.  */
+  bool has_hw_loops;
 };
 
 /* Utility functions used by other ARC-specific modules.  */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 8cfdb8ccc92..106f0306bbf 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -45238,8 +45238,15 @@ Extension core registers @samp{r32} through @samp{r59} are optional and their
 existence depends on the configuration.  When debugging GNU/Linux applications,
 i.e. user space debugging, these core registers are not available.
 
-The @samp{org.gnu.gdb.arc.aux} feature is required for all ARC targets.  It
-should at least contain @samp{pc} and @samp{status32} registers.
+The @samp{org.gnu.gdb.arc.aux} feature is required for all ARC targets.  Here
+is the list of registers pertinent to this feature:
+
+@itemize @minus
+@item
+mandatory: @samp{pc} and @samp{status32}.
+@item
+optional: @samp{lp_start}, @samp{lp_end}, and @samp{bta}.
+@end itemize
 
 @node ARM Features
 @subsection ARM Features
-- 
2.28.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PATCH v6 4/4] arc: Add GNU/Linux support for ARC
  2020-08-05 11:09 ` [PATCH v6 " Shahab Vahedi
                     ` (2 preceding siblings ...)
  2020-08-05 11:09   ` [PATCH v6 3/4] arc: Add hardware loop detection Shahab Vahedi
@ 2020-08-05 11:09   ` Shahab Vahedi
  2020-08-17  8:07   ` [PATCH v6 0/4] arc: Add GNU/Linux support Shahab Vahedi
  4 siblings, 0 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-05 11:09 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Eli Zaretskii, Anton Kolesov, Francois Bedard, Anton Kolesov

From: Anton Kolesov <Anton.Kolesov@synopsys.com>

ARC Linux targets differences from baremetal:

- No support for hardware single instruction stepping.
- Different access rules to registers.
- Use of another instruction for breakpoints.

v2: Changes after Tom's remarks [1]
 arc-linux-tdep.c
  - Use true/false instead of TRUE/FALSE.
  - arc_linux_sw_breakpoint_from_kind (): Break long lines into two.
  - arc_linux_sw_breakpoint_from_kind (): Remove starting blank line.
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 arc-tdep.c
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 gdb/configure.tgt
  - arc*-*-linux*): Remove "build_gdbserver=yes".

v3: Changes after Simon's remarks [2]
  arc-linux-tdep.c
  - Use "return trap_size" instead of cryptic "return 2".
  - Removed unnecessary curly braces.
  - Removed "void" from "_initialize_arc_linux_tdep (void)".

v5: Changes after Simon's remarks [3]
- Remove unnecessary empty lines.
- Replace "breakpoint uses" with "breakpoints use" in a comment.
- "return condition;" i.s.o. "if (condition) return true; else return false;"

[1] Tom's remarks
https://sourceware.org/pipermail/gdb-patches/2020-April/167887.html

[2] Simon's remarks on v2
https://sourceware.org/pipermail/gdb-patches/2020-May/168513.html

[3] Simon's remarks on v4
https://sourceware.org/pipermail/gdb-patches/2020-August/170994.html

2020-08-03  Anton Kolesov  <anton.kolesov@synopsys.com>

	* configure.tgt: ARC support for GNU/Linux.
	* Makefile.in (ALL_TARGET_OBJS): Likewise.
	* arc-linux-tdep.c: New file.
	* arc-tdep.h (ARC_STATUS32_L_MASK, ARC_STATUS32_DE_MASK): Declare.
	* arc-tdep.c (arc_write_pc): Use it.
---
 gdb/Makefile.in      |   1 +
 gdb/arc-linux-tdep.c | 278 +++++++++++++++++++++++++++++++++++++++++++
 gdb/arc-tdep.c       |   3 +-
 gdb/arc-tdep.h       |   5 +
 gdb/configure.tgt    |   5 +
 5 files changed, 290 insertions(+), 2 deletions(-)
 create mode 100644 gdb/arc-linux-tdep.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 9d484457397..85304b9f549 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -697,6 +697,7 @@ ALL_64_TARGET_OBS = \
 # All other target-dependent objects files (used with --enable-targets=all).
 ALL_TARGET_OBS = \
 	aarch32-tdep.o \
+	arc-linux-tdep.o \
 	arc-tdep.o \
 	arch/aarch32.o \
 	arch/arc.o \
diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
new file mode 100644
index 00000000000..36f32459bbe
--- /dev/null
+++ b/gdb/arc-linux-tdep.c
@@ -0,0 +1,278 @@
+/* Target dependent code for GNU/Linux ARC.
+
+   Copyright 2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* GDB header files.  */
+#include "defs.h"
+#include "linux-tdep.h"
+#include "objfiles.h"
+#include "opcode/arc.h"
+#include "osabi.h"
+#include "solib-svr4.h"
+
+/* ARC header files.  */
+#include "opcodes/arc-dis.h"
+#include "arc-tdep.h"
+
+/* Implement the "cannot_fetch_register" gdbarch method.  */
+
+static int
+arc_linux_cannot_fetch_register (struct gdbarch *gdbarch, int regnum)
+{
+  /* Assume that register is readable if it is unknown.  */
+  switch (regnum)
+    {
+    case ARC_ILINK_REGNUM:
+    case ARC_RESERVED_REGNUM:
+    case ARC_LIMM_REGNUM:
+      return true;
+    case ARC_R30_REGNUM:
+    case ARC_R58_REGNUM:
+    case ARC_R59_REGNUM:
+      return !arc_mach_is_arcv2 (gdbarch);
+    }
+  return (regnum > ARC_BLINK_REGNUM) && (regnum < ARC_LP_COUNT_REGNUM);
+}
+
+/* Implement the "cannot_store_register" gdbarch method.  */
+
+static int
+arc_linux_cannot_store_register (struct gdbarch *gdbarch, int regnum)
+{
+  /* Assume that register is writable if it is unknown.  */
+  switch (regnum)
+    {
+    case ARC_ILINK_REGNUM:
+    case ARC_RESERVED_REGNUM:
+    case ARC_LIMM_REGNUM:
+    case ARC_PCL_REGNUM:
+      return true;
+    case ARC_R30_REGNUM:
+    case ARC_R58_REGNUM:
+    case ARC_R59_REGNUM:
+      return !arc_mach_is_arcv2 (gdbarch);
+    }
+  return (regnum > ARC_BLINK_REGNUM) && (regnum < ARC_LP_COUNT_REGNUM);
+}
+
+/* For ARC Linux, breakpoints use the 16-bit TRAP_S 1 instruction, which
+   is 0x3e78 (little endian) or 0x783e (big endian).  */
+
+static const gdb_byte arc_linux_trap_s_be[] = { 0x78, 0x3e };
+static const gdb_byte arc_linux_trap_s_le[] = { 0x3e, 0x78 };
+static const int trap_size = 2;   /* Number of bytes to insert "trap".  */
+
+/* Implement the "breakpoint_kind_from_pc" gdbarch method.  */
+
+static int
+arc_linux_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+  return trap_size;
+}
+
+/* Implement the "sw_breakpoint_from_kind" gdbarch method.  */
+
+static const gdb_byte *
+arc_linux_sw_breakpoint_from_kind (struct gdbarch *gdbarch,
+				   int kind, int *size)
+{
+  *size = kind;
+  return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+	  ? arc_linux_trap_s_be
+	  : arc_linux_trap_s_le);
+}
+
+/* Implement the "software_single_step" gdbarch method.  */
+
+static std::vector<CORE_ADDR>
+arc_linux_software_single_step (struct regcache *regcache)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct disassemble_info di = arc_disassemble_info (gdbarch);
+
+  /* Read current instruction.  */
+  struct arc_instruction curr_insn;
+  arc_insn_decode (regcache_read_pc (regcache), &di, arc_delayed_print_insn,
+		   &curr_insn);
+  CORE_ADDR next_pc = arc_insn_get_linear_next_pc (curr_insn);
+
+  std::vector<CORE_ADDR> next_pcs;
+
+  /* For instructions with delay slots, the fall thru is not the
+     instruction immediately after the current instruction, but the one
+     after that.  */
+  if (curr_insn.has_delay_slot)
+    {
+      struct arc_instruction next_insn;
+      arc_insn_decode (next_pc, &di, arc_delayed_print_insn, &next_insn);
+      next_pcs.push_back (arc_insn_get_linear_next_pc (next_insn));
+    }
+  else
+    next_pcs.push_back (next_pc);
+
+  ULONGEST status32;
+  regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
+				 &status32);
+
+  if (curr_insn.is_control_flow)
+    {
+      CORE_ADDR branch_pc = arc_insn_get_branch_target (curr_insn);
+      if (branch_pc != next_pc)
+	next_pcs.push_back (branch_pc);
+    }
+  /* Is current instruction the last in a loop body?  */
+  else if (tdep->has_hw_loops)
+    {
+      /* If STATUS32.L is 1, then ZD-loops are disabled.  */
+      if ((status32 & ARC_STATUS32_L_MASK) == 0)
+	{
+	  ULONGEST lp_end, lp_start, lp_count;
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_START_REGNUM,
+					 &lp_start);
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_END_REGNUM, &lp_end);
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_COUNT_REGNUM,
+					 &lp_count);
+
+	  if (arc_debug)
+	    {
+	      debug_printf ("arc-linux: lp_start = %s, lp_end = %s, "
+			    "lp_count = %s, next_pc = %s\n",
+			    paddress (gdbarch, lp_start),
+			    paddress (gdbarch, lp_end),
+			    pulongest (lp_count),
+			    paddress (gdbarch, next_pc));
+	    }
+
+	  if (next_pc == lp_end && lp_count > 1)
+	    {
+	      /* The instruction is in effect a jump back to the start of
+		 the loop.  */
+	      next_pcs.push_back (lp_start);
+	    }
+	}
+    }
+
+  /* Is this a delay slot?  Then next PC is in BTA register.  */
+  if ((status32 & ARC_STATUS32_DE_MASK) != 0)
+    {
+      ULONGEST bta;
+      regcache_cooked_read_unsigned (regcache, ARC_BTA_REGNUM, &bta);
+      next_pcs.push_back (bta);
+    }
+
+  return next_pcs;
+}
+
+/* Implement the "skip_solib_resolver" gdbarch method.
+
+   See glibc_skip_solib_resolver for details.  */
+
+static CORE_ADDR
+arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  /* For uClibc 0.9.26+.
+
+     An unresolved PLT entry points to "__dl_linux_resolve", which calls
+     "_dl_linux_resolver" to do the resolving and then eventually jumps to
+     the function.
+
+     So we look for the symbol `_dl_linux_resolver', and if we are there,
+     gdb sets a breakpoint at the return address, and continues.  */
+  struct bound_minimal_symbol resolver
+    = lookup_minimal_symbol ("_dl_linux_resolver", NULL, NULL);
+
+  if (arc_debug)
+    {
+      if (resolver.minsym != nullptr)
+	{
+	  CORE_ADDR res_addr = BMSYMBOL_VALUE_ADDRESS (resolver);
+	  debug_printf ("arc-linux: skip_solib_resolver (): "
+			"pc = %s, resolver at %s\n",
+			print_core_address (gdbarch, pc),
+			print_core_address (gdbarch, res_addr));
+	}
+      else
+	{
+	  debug_printf ("arc-linux: skip_solib_resolver (): "
+			"pc = %s, no resolver found\n",
+			print_core_address (gdbarch, pc));
+	}
+    }
+
+  if (resolver.minsym != nullptr && BMSYMBOL_VALUE_ADDRESS (resolver) == pc)
+    {
+      /* Find the return address.  */
+      return frame_unwind_caller_pc (get_current_frame ());
+    }
+  else
+    {
+      /* No breakpoint required.  */
+      return 0;
+    }
+}
+
+/* Initialization specific to Linux environment.  */
+
+static void
+arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (arc_debug)
+    debug_printf ("arc-linux: GNU/Linux OS/ABI initialization.\n");
+
+  /* If we are using Linux, we have in uClibc
+     (libc/sysdeps/linux/arc/bits/setjmp.h):
+
+     typedef int __jmp_buf[13+1+1+1];    //r13-r25, fp, sp, blink
+
+     Where "blink" is a stored PC of a caller function.
+   */
+  tdep->jb_pc = 15;
+
+  linux_init_abi (info, gdbarch);
+
+  /* Set up target dependent GDB architecture entries.  */
+  set_gdbarch_cannot_fetch_register (gdbarch, arc_linux_cannot_fetch_register);
+  set_gdbarch_cannot_store_register (gdbarch, arc_linux_cannot_store_register);
+  set_gdbarch_breakpoint_kind_from_pc (gdbarch,
+				       arc_linux_breakpoint_kind_from_pc);
+  set_gdbarch_sw_breakpoint_from_kind (gdbarch,
+				       arc_linux_sw_breakpoint_from_kind);
+  set_gdbarch_fetch_tls_load_module_address (gdbarch,
+					     svr4_fetch_objfile_link_map);
+  set_gdbarch_software_single_step (gdbarch, arc_linux_software_single_step);
+  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+  set_gdbarch_skip_solib_resolver (gdbarch, arc_linux_skip_solib_resolver);
+
+  /* GNU/Linux uses SVR4-style shared libraries, with 32-bit ints, longs
+     and pointers (ILP32).  */
+  set_solib_svr4_fetch_link_map_offsets (gdbarch,
+					 svr4_ilp32_fetch_link_map_offsets);
+}
+
+/* Suppress warning from -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_arc_linux_tdep;
+
+void
+_initialize_arc_linux_tdep ()
+{
+  gdbarch_register_osabi (bfd_arch_arc, 0, GDB_OSABI_LINUX,
+			  arc_linux_init_osabi);
+}
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 54f67a03818..8f1379c0555 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -612,8 +612,7 @@ arc_write_pc (struct regcache *regcache, CORE_ADDR new_pc)
   regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
 				 &status32);
 
-  /* Mask for DE bit is 0x40.  */
-  if (status32 & 0x40)
+  if ((status32 & ARC_STATUS32_DE_MASK) != 0)
     {
       if (arc_debug)
 	{
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index e752348a262..6331d29f402 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -100,6 +100,11 @@ enum arc_regnum
    Longer registers are represented as pairs of 32-bit registers.  */
 #define ARC_REGISTER_SIZE  4
 
+/* STATUS32 register: hardware loops disabled bit.  */
+#define ARC_STATUS32_L_MASK (1 << 12)
+/* STATUS32 register: current instruction is a delay slot.  */
+#define ARC_STATUS32_DE_MASK (1 << 6)
+
 #define arc_print(fmt, args...) fprintf_unfiltered (gdb_stdlog, fmt, ##args)
 
 extern int arc_debug;
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index d66f01bb9f7..4178eb4e773 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -157,6 +157,11 @@ arc*-*-elf32)
 	gdb_target_obs="arc-newlib-tdep.o"
 	;;
 
+arc*-*-linux*)
+	# Target: ARC machine running Linux
+	gdb_target_obs="arc-linux-tdep.o linux-tdep.o solib-svr4.o"
+	;;
+
 arm*-wince-pe | arm*-*-mingw32ce*)
 	# Target: ARM based machine running Windows CE (win32)
 	gdb_target_obs="arm-wince-tdep.o windows-tdep.o"
-- 
2.28.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v6 1/4] arc: Add ARCv2 XML target along with refactoring
  2020-08-05 11:09   ` [PATCH v6 1/4] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
@ 2020-08-05 14:31     ` Eli Zaretskii
  2020-08-21 16:16     ` Simon Marchi
  1 sibling, 0 replies; 86+ messages in thread
From: Eli Zaretskii @ 2020-08-05 14:31 UTC (permalink / raw)
  To: Shahab Vahedi; +Cc: gdb-patches, shahab, simark, tom, anton.kolesov, fbedard

> From: Shahab Vahedi <shahab.vahedi@gmail.com>
> Cc: Shahab Vahedi <shahab.vahedi@gmail.com>,
> 	Shahab Vahedi <shahab@synopsys.com>,
> 	Simon Marchi <simark@simark.ca>,
> 	Tom Tromey <tom@tromey.com>,
> 	Eli Zaretskii <eliz@gnu.org>,
> 	Anton Kolesov <anton.kolesov@synopsys.com>,
> 	Francois Bedard <fbedard@synopsys.com>
> Date: Wed,  5 Aug 2020 13:09:31 +0200
> 
> gdb/ChangeLog:
> 
> 	* arch/arc.h
> 	  (arc_gdbarch_features): New class to stir the selection of target XML.
> 	  (arc_create_target_description): Use FEATURES to choose XML target.
> 	  (arc_lookup_target_description): Use arc_create_target_description
> 	  to create _new_ target descriptions or return the already created
> 	  ones if the FEATURES is the same.
> 	* arch/arc.c: Implementation of prototypes described above.
> 	* gdb/arc-tdep.h (arc_regnum enum): Add more registers.
> 	  (arc_gdbarch_features_init): Initialize the FEATURES struct.
> 	* arc-tdep.c (*_feature_name): Make feature names consistent.
> 	  (arc_register_feature): A new struct to hold information about
> 	  registers of a particular target/feature.
> 	  (arc_check_tdesc_feature): Check if XML provides registers in
> 	  compliance with ARC_REGISTER_FEATURE structs.
> 	  (arc_update_acc_reg_names): Add aliases for r58 and r59.
> 	  (determine_*_reg_feature_set): Which feature name to look for.
> 	  (arc_gdbarch_features_init): Given MACH and ABFD, initialize FEATURES.
> 	  (mach_type_to_arc_isa): Convert from a set of binutils machine types
> 	  to expected ISA enums to be used in arc_gdbarch_features structs.
> 	* features/Makefile (FEATURE_XMLFILES): Add new files.
> 	* gdb/features/arc/v1-aux.c: New file.
> 	* gdb/features/arc/v1-aux.xml: Likewise.
> 	* gdb/features/arc/v1-core.c: Likewise.
> 	* gdb/features/arc/v1-core.xml: Likewise.
> 	* gdb/features/arc/v2-aux.c: Likewise.
> 	* gdb/features/arc/v2-aux.xml: Likewise.
> 	* gdb/features/arc/v2-core.c: Likewise.
> 	* gdb/features/arc/v2-core.xml: Likewise.
> 	* NEWS (Changes since GDB 9): Announce obsolence of old feature names.
> 
> gdb/doc/ChangeLog:
> 
> 	* gdb.texinfo (Synopsys ARC): Update the documentation for ARC Features.
> 
> gdb/testsuite/ChangeLog:
> 
> 	* gdb.arch/arc-tdesc-cpu.xml: Use new feature names.

The documentation parts are OK, with this single nit:

> +existence depends on the configuration.  When debugging GNU/Linux applications,
> +i.e. user space debugging, these core registers are not available.

Please use "i.e.@:", so that the second period is not taken as ending
the sentence (which makes a difference in the printed version of the
manual).

Thanks.

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v6 0/4] arc: Add GNU/Linux support
  2020-08-05 11:09 ` [PATCH v6 " Shahab Vahedi
                     ` (3 preceding siblings ...)
  2020-08-05 11:09   ` [PATCH v6 4/4] arc: Add GNU/Linux support for ARC Shahab Vahedi
@ 2020-08-17  8:07   ` Shahab Vahedi
  2020-08-17 14:12     ` Eli Zaretskii
  4 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-17  8:07 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Simon Marchi, Tom Tromey, Eli Zaretskii,
	Anton Kolesov, Francois Bedard

Friendly reminder for reviewing v6 of the patch series [1].

In general, backward compatibility has been added. Therefore,
previous reviewers only need to take a look at new changes:

gdb/NEWS:
- Added an entry for deprecating the old feature names.

arc-tdep.c:
- Added "ARC_{CORE,AUX}_V{1,2}_OBSOLETE_*" name variables.
- Introduced "find_obsolete_{core,aux}_names()" functions.
- Usage of those functions in "arc_tdesc_init()".


Cheers,
Shahab

[1] [PATCH v6 0/4] arc: Add GNU/Linux support
https://sourceware.org/pipermail/gdb-patches/2020-August/171080.html

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v6 0/4] arc: Add GNU/Linux support
  2020-08-17  8:07   ` [PATCH v6 0/4] arc: Add GNU/Linux support Shahab Vahedi
@ 2020-08-17 14:12     ` Eli Zaretskii
  0 siblings, 0 replies; 86+ messages in thread
From: Eli Zaretskii @ 2020-08-17 14:12 UTC (permalink / raw)
  To: Shahab Vahedi; +Cc: gdb-patches, shahab, simark, tom, anton.kolesov, fbedard

> Date: Mon, 17 Aug 2020 10:07:57 +0200
> From: Shahab Vahedi <shahab.vahedi@gmail.com>
> Cc: Shahab Vahedi <shahab@synopsys.com>, Simon Marchi <simark@simark.ca>,
> 	Tom Tromey <tom@tromey.com>, Eli Zaretskii <eliz@gnu.org>,
> 	Anton Kolesov <anton.kolesov@synopsys.com>,
> 	Francois Bedard <fbedard@synopsys.com>
> 
> Friendly reminder for reviewing v6 of the patch series [1].

Thanks, the documentation parts are OK.

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v6 1/4] arc: Add ARCv2 XML target along with refactoring
  2020-08-05 11:09   ` [PATCH v6 1/4] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
  2020-08-05 14:31     ` Eli Zaretskii
@ 2020-08-21 16:16     ` Simon Marchi
  2020-08-24 20:14       ` Shahab Vahedi
  1 sibling, 1 reply; 86+ messages in thread
From: Simon Marchi @ 2020-08-21 16:16 UTC (permalink / raw)
  To: Shahab Vahedi, gdb-patches
  Cc: Shahab Vahedi, Tom Tromey, Eli Zaretskii, Anton Kolesov, Francois Bedard

Hi Shahab,

The only thing code-wise that changed between v5 and v6 is looking for obsolete features names?

If so, that LGTM (I didn't re-read the whole patch, just checked that and it looks reasonable)
with these nits fixed:

> -static const char *const aux_minimal_register_names[] = {
> -  "pc", "status32",
> +/* Obsolete feature names for backward compatibility.  */
> +static const char *ARC_CORE_V1_OBSOLETE_FEATURE_NAME
> +    = "org.gnu.gdb.arc.core.arcompact";
> +static const char *ARC_CORE_V2_OBSOLETE_FEATURE_NAME
> +    = "org.gnu.gdb.arc.core.v2";
> +static const char *ARC_CORE_V2_REDUCED_OBSOLETE_FEATURE_NAME
> +    = "org.gnu.gdb.arc.core-reduced.v2";
> +static const char *ARC_AUX_OBSOLETE_FEATURE_NAME
> +    = "org.gnu.gdb.arc.aux-minimal";

Should probably be two spaces for indentation here.

> +/* Look for obsolete core feature names in TDESC_DATA.  */
> +
> +static const struct tdesc_feature *
> +find_obsolete_core_names (const struct target_desc *tdesc)

The parameter name doesn't match the doc, TDESC_DATA -> TDESC.

> +{
> +  const struct tdesc_feature *feat = nullptr;
> +
> +  feat = tdesc_find_feature (tdesc, ARC_CORE_V1_OBSOLETE_FEATURE_NAME);
> +
> +  if (feat == nullptr)
> +    feat = tdesc_find_feature (tdesc, ARC_CORE_V2_OBSOLETE_FEATURE_NAME);
> +
> +  if (feat == nullptr)
> +    feat = tdesc_find_feature
> +      (tdesc, ARC_CORE_V2_REDUCED_OBSOLETE_FEATURE_NAME);
> +
> +  return feat;
> +}
> +
> +/* Look for obsolete aux feature names in TDESC_DATA.  */
> +
> +static const struct tdesc_feature *
> +find_obsolete_aux_names (const struct target_desc *tdesc)

Same here.

Simon

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PATCH v6 1/4] arc: Add ARCv2 XML target along with refactoring
  2020-08-21 16:16     ` Simon Marchi
@ 2020-08-24 20:14       ` Shahab Vahedi
  0 siblings, 0 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-24 20:14 UTC (permalink / raw)
  To: Simon Marchi
  Cc: gdb-patches, Shahab Vahedi, Tom Tromey, Eli Zaretskii,
	Anton Kolesov, Francois Bedard

Hi Simon,

On Fri, Aug 21, 2020 at 12:16:10PM -0400, Simon Marchi wrote:
> The only thing code-wise that changed between v5 and v6 is looking for obsolete features names?

That is correct. I will take your remarks [1] (and Eli's [2]) in and push the changes.


Cheers,
Shahab

[1] Simon's remarks on v6
https://sourceware.org/pipermail/gdb-patches/2020-August/171400.html

[2] Eli's remarks on v6
https://sourceware.org/pipermail/gdb-patches/2020-August/171089.html


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PUSHED 0/4] arc: Add GNU/Linux support
  2020-03-26 12:52 [PATCH 0/4] arc: Add GNU/Linux support Shahab Vahedi
                   ` (8 preceding siblings ...)
  2020-08-05 11:09 ` [PATCH v6 " Shahab Vahedi
@ 2020-08-25 15:47 ` Shahab Vahedi
  2020-08-25 15:47   ` [PUSHED 1/4] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
                     ` (3 more replies)
  9 siblings, 4 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-25 15:47 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Eli Zaretskii, Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

This is a series of changes to enable debugging ARC targets that are
running on a native ARC GNU/Linux system.  Since this heavily relies
on XML target descriptions provided for different targets, that piece
of code has been refactored to accommodate flexible register support.

After this series, there will come patches that add support for
native ARC gdb/gdbserver.

v6: Add backward compatibility for obsolete feature names
 arc-tdep.c:
  - "find_obsolete_[core,aux]_names()" implemented
 gdb/NEWS:
  - Updated with information about these feature name changes.

v5: Changes per remarks of Simon [1] and on my own (documentation and tests)
 arc.h:
  - Made "reg_size" and "isa" constant in "arc_gdbarch_features".
 arc.c:
  - Fix some malformed indentations.
 arc-tdep.h:
  - Inclusion of "gdbarch.h" has its own patch now.
 arc-tdep.c
  - Use "nullptr" instead of "NULL".
  - Remove unnecessary "break"s after "return"s.
  - "determine_core_reg_feature_set" will assert if wrong input is given.
  - Removed dangling comment.
  - Replaced "const auto *" with "const auto" to be consistent.
  - in "arc_check_for_hw_loops()": No "nullptr" check for "aux_regset".
 arc-linux-tdep.c
  - Remove unnecessary empty lines.
  - Replace "breakpoint uses" with "breakpoints use" in a comment.
  - "return condition;" i.s.o. "if (condition) return true; else return false;"
 gdb.texinfo
  - Update documentation regarding the new feature files.
 arc-tdesc-cpu.xml
  - Use new feature names.

[1] Simon's remarks to v4 of the patches
https://sourceware.org/pipermail/gdb-patches/2020-July/170975.html
https://sourceware.org/pipermail/gdb-patches/2020-August/170993.html
https://sourceware.org/pipermail/gdb-patches/2020-August/170994.html

v4: Latest changes per remarks of Simon [2]
 arc-tdep.c
  - Surround "=" in 2 assignments with space.
  - Put the return type of "mach_type_to_arc_isa ()" on the first line.
  - Remove "inline" from "mach_type_to_arc_isa ()".
  - Add space between the "if" conditions for readability.
  - Use "featues.isa" instead of "features.reg_size" in one occurrence.
  - Make "arc_gdbarch_features_init" static
  - Rename "arc_gdbarch_features_init" to "arc_gdbarch_features_create".
  - Adapt "arc_gdbarch_features_create" to act as a constructor.
 arch/arc.c
  - Add a constructor for "arc_gdbarch_features".
  - Get rid of "ARC_ISA_NONE" now that there is a constructor.
 arch/arc.c
  - Use simple assignments (instead of append) for "architecture".
  - Use "string_sprintf ()".
  - Use "target_desc_up" in "arc_tdesc_cache" to avoid memory leakage.
 arc-linux-tdep.c
  - Two occurrences: compare "resolver.minsym" against "nullptr".
  

[2] [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring
https://sourceware.org/pipermail/gdb-patches/2020-July/170427.html

v3: Changes after Simon's remarks:
The XML files have reduced to minimal comprehensible set.
The code is adjusted to work with new reg sets and be platform agnostic.

v2: Changes after Tom's remarks:
 arc-tdep.c
  - arc_tdesc_init(): Use "ARC_{R58,R59}_REGNUM" to index "core_regs[]".
  - arc_gdbarch_init(): Use "xfree ()" instead of "XDELETE ()"
  - arc_gdbarch_init(): return "nullptr" instead of "NULL".
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 arc-linux-tdep.c
  - Use true/false instead of TRUE/FALSE.
  - arc_linux_sw_breakpoint_from_kind (): Break long lines into two.
  - arc_linux_sw_breakpoint_from_kind (): Remove starting blank line.
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 gdb/configure.tgt
  - arc*-*-linux*): Remove "build_gdbserver=yes".

Anton Kolesov (1):
  arc: Add GNU/Linux support for ARC

Shahab Vahedi (3):
  arc: Add ARCv2 XML target along with refactoring
  arc: Add inclusion of "gdbarch.h" in "arc-tdep.h"
  arc: Add hardware loop detection

 gdb/ChangeLog                                 |  49 ++
 gdb/Makefile.in                               |   1 +
 gdb/NEWS                                      |   5 +
 gdb/arc-linux-tdep.c                          | 278 +++++++
 gdb/arc-tdep.c                                | 694 ++++++++++++------
 gdb/arc-tdep.h                                |  27 +-
 gdb/arch/arc.c                                | 108 ++-
 gdb/arch/arc.h                                |  79 +-
 gdb/configure.tgt                             |   5 +
 gdb/doc/ChangeLog                             |   9 +
 gdb/doc/gdb.texinfo                           |  76 +-
 gdb/features/Makefile                         |   8 +-
 .../arc/{aux-arcompact.c => v1-aux.c}         |   9 +-
 .../arc/{aux-arcompact.xml => v1-aux.xml}     |   7 +-
 .../arc/{core-arcompact.c => v1-core.c}       |   8 +-
 .../arc/{core-arcompact.xml => v1-core.xml}   |   4 +-
 gdb/features/arc/{aux-v2.c => v2-aux.c}       |   9 +-
 gdb/features/arc/{aux-v2.xml => v2-aux.xml}   |   5 +-
 gdb/features/arc/{core-v2.c => v2-core.c}     |   7 +-
 gdb/features/arc/{core-v2.xml => v2-core.xml} |   7 +-
 gdb/testsuite/ChangeLog                       |   4 +
 gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml      |   4 +-
 22 files changed, 1048 insertions(+), 355 deletions(-)
 create mode 100644 gdb/arc-linux-tdep.c
 rename gdb/features/arc/{aux-arcompact.c => v1-aux.c} (73%)
 rename gdb/features/arc/{aux-arcompact.xml => v1-aux.xml} (80%)
 rename gdb/features/arc/{core-arcompact.c => v1-core.c} (87%)
 rename gdb/features/arc/{core-arcompact.xml => v1-core.xml} (92%)
 rename gdb/features/arc/{aux-v2.c => v2-aux.c} (76%)
 rename gdb/features/arc/{aux-v2.xml => v2-aux.xml} (86%)
 rename gdb/features/arc/{core-v2.c => v2-core.c} (91%)
 rename gdb/features/arc/{core-v2.xml => v2-core.xml} (90%)

-- 
2.28.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PUSHED 1/4] arc: Add ARCv2 XML target along with refactoring
  2020-08-25 15:47 ` [PUSHED " Shahab Vahedi
@ 2020-08-25 15:47   ` Shahab Vahedi
  2020-08-25 16:00     ` Eli Zaretskii
  2020-08-25 15:47   ` [PUSHED 2/4] arc: Add inclusion of "gdbarch.h" in "arc-tdep.h" Shahab Vahedi
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-25 15:47 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Eli Zaretskii, Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

A few changes have been made to make the register support simpler,
more flexible and extendible.  The trigger for most of these changes
are the remarks [1] made earlier for v2 of this patch.  The noticeable
improvements are:

- The arc XML target features are placed under gdb/features/arc
- There are two cores (based on ISA) and one auxiliary feature:
  v1-core: ARC600, ARC601, ARC700
  v2-core: ARC EM, ARC HS
  aux: common in both
- The XML target features represent a minimalistic sane set of
  registers irrespective of application (baremetal or linux).
- A concept of "feature" class has been introduced in the code.
  The "feature" object is constructed from BFD and GDBARCH data.
  It contains necessary information (ISA and register size) to
  determine which XML target feature to use.
- A new structure (ARC_REGISTER_FEATURE) is added that allows
  providing index, names, and the necessity of registers. This
  simplifies the sanity checks and future extendibility.
- Documnetation has been updated to reflect ARC features better.
- Although the feature names has changed, there still exists
  backward compatibility with older names through
  find_obsolete_[core,aux]_names() functions.

The last two points were inspired from RiscV port.

[1]
https://sourceware.org/pipermail/gdb-patches/2020-May/168511.html

gdb/ChangeLog:

	* arch/arc.h
	  (arc_gdbarch_features): New class to stir the selection of target XML.
	  (arc_create_target_description): Use FEATURES to choose XML target.
	  (arc_lookup_target_description): Use arc_create_target_description
	  to create _new_ target descriptions or return the already created
	  ones if the FEATURES is the same.
	* arch/arc.c: Implementation of prototypes described above.
	* gdb/arc-tdep.h (arc_regnum enum): Add more registers.
	  (arc_gdbarch_features_init): Initialize the FEATURES struct.
	* arc-tdep.c (*_feature_name): Make feature names consistent.
	  (arc_register_feature): A new struct to hold information about
	  registers of a particular target/feature.
	  (arc_check_tdesc_feature): Check if XML provides registers in
	  compliance with ARC_REGISTER_FEATURE structs.
	  (arc_update_acc_reg_names): Add aliases for r58 and r59.
	  (determine_*_reg_feature_set): Which feature name to look for.
	  (arc_gdbarch_features_init): Given MACH and ABFD, initialize FEATURES.
	  (mach_type_to_arc_isa): Convert from a set of binutils machine types
	  to expected ISA enums to be used in arc_gdbarch_features structs.
	* features/Makefile (FEATURE_XMLFILES): Add new files.
	* gdb/features/arc/v1-aux.c: New file.
	* gdb/features/arc/v1-aux.xml: Likewise.
	* gdb/features/arc/v1-core.c: Likewise.
	* gdb/features/arc/v1-core.xml: Likewise.
	* gdb/features/arc/v2-aux.c: Likewise.
	* gdb/features/arc/v2-aux.xml: Likewise.
	* gdb/features/arc/v2-core.c: Likewise.
	* gdb/features/arc/v2-core.xml: Likewise.
	* NEWS (Changes since GDB 9): Announce obsolence of old feature names.

gdb/doc/ChangeLog:

	* gdb.texinfo (Synopsys ARC): Update the documentation for ARC
	Features.

gdb/testsuite/ChangeLog:

	* gdb.arch/arc-tdesc-cpu.xml: Use new feature names.
---
 gdb/ChangeLog                                 |  32 +
 gdb/NEWS                                      |   5 +
 gdb/arc-tdep.c                                | 652 +++++++++++-------
 gdb/arc-tdep.h                                |  18 +-
 gdb/arch/arc.c                                | 108 ++-
 gdb/arch/arc.h                                |  79 ++-
 gdb/doc/ChangeLog                             |   5 +
 gdb/doc/gdb.texinfo                           |  69 +-
 gdb/features/Makefile                         |   8 +-
 .../arc/{aux-arcompact.c => v1-aux.c}         |   9 +-
 .../arc/{aux-arcompact.xml => v1-aux.xml}     |   7 +-
 .../arc/{core-arcompact.c => v1-core.c}       |   8 +-
 .../arc/{core-arcompact.xml => v1-core.xml}   |   4 +-
 gdb/features/arc/{aux-v2.c => v2-aux.c}       |   9 +-
 gdb/features/arc/{aux-v2.xml => v2-aux.xml}   |   5 +-
 gdb/features/arc/{core-v2.c => v2-core.c}     |   7 +-
 gdb/features/arc/{core-v2.xml => v2-core.xml} |   7 +-
 gdb/testsuite/ChangeLog                       |   4 +
 gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml      |   4 +-
 19 files changed, 691 insertions(+), 349 deletions(-)
 rename gdb/features/arc/{aux-arcompact.c => v1-aux.c} (73%)
 rename gdb/features/arc/{aux-arcompact.xml => v1-aux.xml} (80%)
 rename gdb/features/arc/{core-arcompact.c => v1-core.c} (87%)
 rename gdb/features/arc/{core-arcompact.xml => v1-core.xml} (92%)
 rename gdb/features/arc/{aux-v2.c => v2-aux.c} (76%)
 rename gdb/features/arc/{aux-v2.xml => v2-aux.xml} (86%)
 rename gdb/features/arc/{core-v2.c => v2-core.c} (91%)
 rename gdb/features/arc/{core-v2.xml => v2-core.xml} (90%)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 4592b84a495..ec936d7ccd4 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,35 @@
+2020-08-25  Shahab Vahedi  <shahab@synopsys.com>
+
+	* arch/arc.h
+	(arc_gdbarch_features): New class to stir the selection of target XML.
+	(arc_create_target_description): Use FEATURES to choose XML target.
+	(arc_lookup_target_description): Use arc_create_target_description
+	to create _new_ target descriptions or return the already created
+	ones if the FEATURES is the same.
+	* arch/arc.c: Implementation of prototypes described above.
+	* gdb/arc-tdep.h (arc_regnum enum): Add more registers.
+	(arc_gdbarch_features_init): Initialize the FEATURES struct.
+	* arc-tdep.c (*_feature_name): Make feature names consistent.
+	(arc_register_feature): A new struct to hold information about
+	registers of a particular target/feature.
+	(arc_check_tdesc_feature): Check if XML provides registers in
+	compliance with ARC_REGISTER_FEATURE structs.
+	(arc_update_acc_reg_names): Add aliases for r58 and r59.
+	(determine_*_reg_feature_set): Which feature name to look for.
+	(arc_gdbarch_features_init): Given MACH and ABFD, initialize FEATURES.
+	(mach_type_to_arc_isa): Convert from a set of binutils machine types
+	to expected ISA enums to be used in arc_gdbarch_features structs.
+	* features/Makefile (FEATURE_XMLFILES): Add new files.
+	* gdb/features/arc/v1-aux.c: New file.
+	* gdb/features/arc/v1-aux.xml: Likewise.
+	* gdb/features/arc/v1-core.c: Likewise.
+	* gdb/features/arc/v1-core.xml: Likewise.
+	* gdb/features/arc/v2-aux.c: Likewise.
+	* gdb/features/arc/v2-aux.xml: Likewise.
+	* gdb/features/arc/v2-core.c: Likewise.
+	* gdb/features/arc/v2-core.xml: Likewise.
+	* NEWS (Changes since GDB 9): Announce obsolence of old feature names.
+
 2020-08-25  Gaius Mulley  <gaiusmod2@gmail.com>
 	    Andrew Burgess  <andrew.burgess@embecosm.com>
 
diff --git a/gdb/NEWS b/gdb/NEWS
index 3f57eb93d1d..45bd23526d6 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,11 @@
 
 *** Changes since GDB 9
 
+* There are new feature names for ARC targets: "org.gnu.gdb.arc.core"
+  and "org.gnu.gdb.arc.aux".  The old names are still supported but
+  must be considered obsolete.  They will be deprecated after some
+  grace period.
+
 * Help and apropos commands will now show the documentation of a
   command only once, even if that command has one or more aliases.
   These commands now show the command name, then all of its aliases,
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 7e6d29c334b..cb4941dec02 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -21,6 +21,7 @@
 /* GDB header files.  */
 #include "defs.h"
 #include "arch-utils.h"
+#include "elf-bfd.h"
 #include "disasm.h"
 #include "dwarf2/frame.h"
 #include "frame-base.h"
@@ -41,6 +42,7 @@
 
 /* Standard headers.  */
 #include <algorithm>
+#include <sstream>
 
 /* The frame unwind cache for ARC.  */
 
@@ -91,63 +93,211 @@ int arc_debug;
 
 static struct cmd_list_element *maintenance_print_arc_list = NULL;
 
-/* XML target description features.  */
-
-static const char core_v2_feature_name[] = "org.gnu.gdb.arc.core.v2";
-static const char
-  core_reduced_v2_feature_name[] = "org.gnu.gdb.arc.core-reduced.v2";
-static const char
-  core_arcompact_feature_name[] = "org.gnu.gdb.arc.core.arcompact";
-static const char aux_minimal_feature_name[] = "org.gnu.gdb.arc.aux-minimal";
-
-/* XML target description known registers.  */
-
-static const char *const core_v2_register_names[] = {
-  "r0", "r1", "r2", "r3",
-  "r4", "r5", "r6", "r7",
-  "r8", "r9", "r10", "r11",
-  "r12", "r13", "r14", "r15",
-  "r16", "r17", "r18", "r19",
-  "r20", "r21", "r22", "r23",
-  "r24", "r25", "gp", "fp",
-  "sp", "ilink", "r30", "blink",
-  "r32", "r33", "r34", "r35",
-  "r36", "r37", "r38", "r39",
-  "r40", "r41", "r42", "r43",
-  "r44", "r45", "r46", "r47",
-  "r48", "r49", "r50", "r51",
-  "r52", "r53", "r54", "r55",
-  "r56", "r57", "accl", "acch",
-  "lp_count", "reserved", "limm", "pcl",
+/* A set of registers that we expect to find in a tdesc_feature.  These
+   are used in ARC_TDESC_INIT when processing the target description.  */
+
+struct arc_register_feature
+{
+  /* Information for a single register.  */
+  struct register_info
+  {
+    /* The GDB register number for this register.  */
+    int regnum;
+
+    /* List of names for this register.  The first name in this list is the
+       preferred name, the name GDB will use when describing this register.  */
+    std::vector<const char *> names;
+
+    /* When true, this register must be present in this feature set.  */
+    bool required_p;
+  };
+
+  /* The name for this feature.  This is the name used to find this feature
+     within the target description.  */
+  const char *name;
+
+  /* List of all the registers that we expect to encounter in this register
+     set.  */
+  std::vector<struct register_info> registers;
 };
 
-static const char *const aux_minimal_register_names[] = {
-  "pc", "status32",
+/* Obsolete feature names for backward compatibility.  */
+static const char *ARC_CORE_V1_OBSOLETE_FEATURE_NAME
+  = "org.gnu.gdb.arc.core.arcompact";
+static const char *ARC_CORE_V2_OBSOLETE_FEATURE_NAME
+  = "org.gnu.gdb.arc.core.v2";
+static const char *ARC_CORE_V2_REDUCED_OBSOLETE_FEATURE_NAME
+  = "org.gnu.gdb.arc.core-reduced.v2";
+static const char *ARC_AUX_OBSOLETE_FEATURE_NAME
+  = "org.gnu.gdb.arc.aux-minimal";
+/* Modern feature names.  */
+static const char *ARC_CORE_FEATURE_NAME = "org.gnu.gdb.arc.core";
+static const char *ARC_AUX_FEATURE_NAME = "org.gnu.gdb.arc.aux";
+
+/* ARCv1 (ARC600, ARC601, ARC700) general core registers feature set.
+   See also arc_update_acc_reg_names() for "accl/acch" names.  */
+
+static struct arc_register_feature arc_v1_core_reg_feature =
+{
+  ARC_CORE_FEATURE_NAME,
+  {
+    { ARC_R0_REGNUM + 0, { "r0" }, true },
+    { ARC_R0_REGNUM + 1, { "r1" }, true },
+    { ARC_R0_REGNUM + 2, { "r2" }, true },
+    { ARC_R0_REGNUM + 3, { "r3" }, true },
+    { ARC_R0_REGNUM + 4, { "r4" }, false },
+    { ARC_R0_REGNUM + 5, { "r5" }, false },
+    { ARC_R0_REGNUM + 6, { "r6" }, false },
+    { ARC_R0_REGNUM + 7, { "r7" }, false },
+    { ARC_R0_REGNUM + 8, { "r8" }, false },
+    { ARC_R0_REGNUM + 9, { "r9" }, false },
+    { ARC_R0_REGNUM + 10, { "r10" }, true },
+    { ARC_R0_REGNUM + 11, { "r11" }, true },
+    { ARC_R0_REGNUM + 12, { "r12" }, true },
+    { ARC_R0_REGNUM + 13, { "r13" }, true },
+    { ARC_R0_REGNUM + 14, { "r14" }, true },
+    { ARC_R0_REGNUM + 15, { "r15" }, true },
+    { ARC_R0_REGNUM + 16, { "r16" }, false },
+    { ARC_R0_REGNUM + 17, { "r17" }, false },
+    { ARC_R0_REGNUM + 18, { "r18" }, false },
+    { ARC_R0_REGNUM + 19, { "r19" }, false },
+    { ARC_R0_REGNUM + 20, { "r20" }, false },
+    { ARC_R0_REGNUM + 21, { "r21" }, false },
+    { ARC_R0_REGNUM + 22, { "r22" }, false },
+    { ARC_R0_REGNUM + 23, { "r23" }, false },
+    { ARC_R0_REGNUM + 24, { "r24" }, false },
+    { ARC_R0_REGNUM + 25, { "r25" }, false },
+    { ARC_R0_REGNUM + 26, { "gp" }, true },
+    { ARC_R0_REGNUM + 27, { "fp" }, true },
+    { ARC_R0_REGNUM + 28, { "sp" }, true },
+    { ARC_R0_REGNUM + 29, { "ilink1" }, false },
+    { ARC_R0_REGNUM + 30, { "ilink2" }, false },
+    { ARC_R0_REGNUM + 31, { "blink" }, true },
+    { ARC_R0_REGNUM + 32, { "r32" }, false },
+    { ARC_R0_REGNUM + 33, { "r33" }, false },
+    { ARC_R0_REGNUM + 34, { "r34" }, false },
+    { ARC_R0_REGNUM + 35, { "r35" }, false },
+    { ARC_R0_REGNUM + 36, { "r36" }, false },
+    { ARC_R0_REGNUM + 37, { "r37" }, false },
+    { ARC_R0_REGNUM + 38, { "r38" }, false },
+    { ARC_R0_REGNUM + 39, { "r39" }, false },
+    { ARC_R0_REGNUM + 40, { "r40" }, false },
+    { ARC_R0_REGNUM + 41, { "r41" }, false },
+    { ARC_R0_REGNUM + 42, { "r42" }, false },
+    { ARC_R0_REGNUM + 43, { "r43" }, false },
+    { ARC_R0_REGNUM + 44, { "r44" }, false },
+    { ARC_R0_REGNUM + 45, { "r45" }, false },
+    { ARC_R0_REGNUM + 46, { "r46" }, false },
+    { ARC_R0_REGNUM + 47, { "r47" }, false },
+    { ARC_R0_REGNUM + 48, { "r48" }, false },
+    { ARC_R0_REGNUM + 49, { "r49" }, false },
+    { ARC_R0_REGNUM + 50, { "r50" }, false },
+    { ARC_R0_REGNUM + 51, { "r51" }, false },
+    { ARC_R0_REGNUM + 52, { "r52" }, false },
+    { ARC_R0_REGNUM + 53, { "r53" }, false },
+    { ARC_R0_REGNUM + 54, { "r54" }, false },
+    { ARC_R0_REGNUM + 55, { "r55" }, false },
+    { ARC_R0_REGNUM + 56, { "r56" }, false },
+    { ARC_R0_REGNUM + 57, { "r57" }, false },
+    { ARC_R0_REGNUM + 58, { "r58", "accl" }, false },
+    { ARC_R0_REGNUM + 59, { "r59", "acch" }, false },
+    { ARC_R0_REGNUM + 60, { "lp_count" }, false },
+    { ARC_R0_REGNUM + 61, { "reserved" }, false },
+    { ARC_R0_REGNUM + 62, { "limm" }, false },
+    { ARC_R0_REGNUM + 63, { "pcl" }, true }
+  }
 };
 
-static const char *const core_arcompact_register_names[] = {
-  "r0", "r1", "r2", "r3",
-  "r4", "r5", "r6", "r7",
-  "r8", "r9", "r10", "r11",
-  "r12", "r13", "r14", "r15",
-  "r16", "r17", "r18", "r19",
-  "r20", "r21", "r22", "r23",
-  "r24", "r25", "gp", "fp",
-  "sp", "ilink1", "ilink2", "blink",
-  "r32", "r33", "r34", "r35",
-  "r36", "r37", "r38", "r39",
-  "r40", "r41", "r42", "r43",
-  "r44", "r45", "r46", "r47",
-  "r48", "r49", "r50", "r51",
-  "r52", "r53", "r54", "r55",
-  "r56", "r57", "r58", "r59",
-  "lp_count", "reserved", "limm", "pcl",
+/* ARCv2 (ARCHS) general core registers feature set.  See also
+   arc_update_acc_reg_names() for "accl/acch" names.  */
+
+static struct arc_register_feature arc_v2_core_reg_feature =
+{
+  ARC_CORE_FEATURE_NAME,
+  {
+    { ARC_R0_REGNUM + 0, { "r0" }, true },
+    { ARC_R0_REGNUM + 1, { "r1" }, true },
+    { ARC_R0_REGNUM + 2, { "r2" }, true },
+    { ARC_R0_REGNUM + 3, { "r3" }, true },
+    { ARC_R0_REGNUM + 4, { "r4" }, false },
+    { ARC_R0_REGNUM + 5, { "r5" }, false },
+    { ARC_R0_REGNUM + 6, { "r6" }, false },
+    { ARC_R0_REGNUM + 7, { "r7" }, false },
+    { ARC_R0_REGNUM + 8, { "r8" }, false },
+    { ARC_R0_REGNUM + 9, { "r9" }, false },
+    { ARC_R0_REGNUM + 10, { "r10" }, true },
+    { ARC_R0_REGNUM + 11, { "r11" }, true },
+    { ARC_R0_REGNUM + 12, { "r12" }, true },
+    { ARC_R0_REGNUM + 13, { "r13" }, true },
+    { ARC_R0_REGNUM + 14, { "r14" }, true },
+    { ARC_R0_REGNUM + 15, { "r15" }, true },
+    { ARC_R0_REGNUM + 16, { "r16" }, false },
+    { ARC_R0_REGNUM + 17, { "r17" }, false },
+    { ARC_R0_REGNUM + 18, { "r18" }, false },
+    { ARC_R0_REGNUM + 19, { "r19" }, false },
+    { ARC_R0_REGNUM + 20, { "r20" }, false },
+    { ARC_R0_REGNUM + 21, { "r21" }, false },
+    { ARC_R0_REGNUM + 22, { "r22" }, false },
+    { ARC_R0_REGNUM + 23, { "r23" }, false },
+    { ARC_R0_REGNUM + 24, { "r24" }, false },
+    { ARC_R0_REGNUM + 25, { "r25" }, false },
+    { ARC_R0_REGNUM + 26, { "gp" }, true },
+    { ARC_R0_REGNUM + 27, { "fp" }, true },
+    { ARC_R0_REGNUM + 28, { "sp" }, true },
+    { ARC_R0_REGNUM + 29, { "ilink" }, false },
+    { ARC_R0_REGNUM + 30, { "r30" }, true },
+    { ARC_R0_REGNUM + 31, { "blink" }, true },
+    { ARC_R0_REGNUM + 32, { "r32" }, false },
+    { ARC_R0_REGNUM + 33, { "r33" }, false },
+    { ARC_R0_REGNUM + 34, { "r34" }, false },
+    { ARC_R0_REGNUM + 35, { "r35" }, false },
+    { ARC_R0_REGNUM + 36, { "r36" }, false },
+    { ARC_R0_REGNUM + 37, { "r37" }, false },
+    { ARC_R0_REGNUM + 38, { "r38" }, false },
+    { ARC_R0_REGNUM + 39, { "r39" }, false },
+    { ARC_R0_REGNUM + 40, { "r40" }, false },
+    { ARC_R0_REGNUM + 41, { "r41" }, false },
+    { ARC_R0_REGNUM + 42, { "r42" }, false },
+    { ARC_R0_REGNUM + 43, { "r43" }, false },
+    { ARC_R0_REGNUM + 44, { "r44" }, false },
+    { ARC_R0_REGNUM + 45, { "r45" }, false },
+    { ARC_R0_REGNUM + 46, { "r46" }, false },
+    { ARC_R0_REGNUM + 47, { "r47" }, false },
+    { ARC_R0_REGNUM + 48, { "r48" }, false },
+    { ARC_R0_REGNUM + 49, { "r49" }, false },
+    { ARC_R0_REGNUM + 50, { "r50" }, false },
+    { ARC_R0_REGNUM + 51, { "r51" }, false },
+    { ARC_R0_REGNUM + 52, { "r52" }, false },
+    { ARC_R0_REGNUM + 53, { "r53" }, false },
+    { ARC_R0_REGNUM + 54, { "r54" }, false },
+    { ARC_R0_REGNUM + 55, { "r55" }, false },
+    { ARC_R0_REGNUM + 56, { "r56" }, false },
+    { ARC_R0_REGNUM + 57, { "r57" }, false },
+    { ARC_R0_REGNUM + 58, { "r58", "accl" }, false },
+    { ARC_R0_REGNUM + 59, { "r59", "acch" }, false },
+    { ARC_R0_REGNUM + 60, { "lp_count" }, false },
+    { ARC_R0_REGNUM + 61, { "reserved" }, false },
+    { ARC_R0_REGNUM + 62, { "limm" }, false },
+    { ARC_R0_REGNUM + 63, { "pcl" }, true }
+  }
 };
 
-static char *arc_disassembler_options = NULL;
+/* The common auxiliary registers feature set.  The REGNUM field
+   must match the ARC_REGNUM enum in arc-tdep.h.  */
 
-/* Possible arc target descriptors.  */
-static struct target_desc *tdesc_arc_list[ARC_SYS_TYPE_NUM];
+static const struct arc_register_feature arc_common_aux_reg_feature =
+{
+  ARC_AUX_FEATURE_NAME,
+  {
+    { ARC_FIRST_AUX_REGNUM + 0, { "pc" }, true },
+    { ARC_FIRST_AUX_REGNUM + 1, { "status32" }, true },
+    { ARC_FIRST_AUX_REGNUM + 2, { "lp_start" }, false },
+    { ARC_FIRST_AUX_REGNUM + 3, { "lp_end" }, false },
+    { ARC_FIRST_AUX_REGNUM + 4, { "bta" }, false }
+  }
+};
+
+static char *arc_disassembler_options = NULL;
 
 /* Functions are sorted in the order as they are used in the
    _initialize_arc_tdep (), which uses the same order as gdbarch.h.  Static
@@ -1717,192 +1867,254 @@ static const struct frame_base arc_normal_base = {
   arc_frame_base_address
 };
 
-/* Initialize target description for the ARC.
-
-   Returns TRUE if input tdesc was valid and in this case it will assign TDESC
-   and TDESC_DATA output parameters.  */
-
-static bool
-arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
-		struct tdesc_arch_data **tdesc_data)
+static enum arc_isa
+mach_type_to_arc_isa (const unsigned long mach)
 {
-  if (arc_debug)
-    debug_printf ("arc: Target description initialization.\n");
-
-  const struct target_desc *tdesc_loc = info.target_desc;
+  switch (mach)
+    {
+    case bfd_mach_arc_arc600:
+    case bfd_mach_arc_arc601:
+    case bfd_mach_arc_arc700:
+      return ARC_ISA_ARCV1;
+    case bfd_mach_arc_arcv2:
+      return ARC_ISA_ARCV2;
+    default:
+	internal_error (__FILE__, __LINE__,
+			_("unknown machine id %lu"), mach);
+    }
+}
 
-  /* Depending on whether this is ARCompact or ARCv2 we will assign
-     different default registers sets (which will differ in exactly two core
-     registers).  GDB will also refuse to accept register feature from invalid
-     ISA - v2 features can be used only with v2 ARChitecture.  We read
-     bfd_arch_info, which looks like to be a safe bet here, as it looks like it
-     is always initialized even when we don't pass any elf file to GDB at all
-     (it uses default arch in this case).  Also GDB will call this function
-     multiple times, and if XML target description file contains architecture
-     specifications, then GDB will set this architecture to info.bfd_arch_info,
-     overriding value from ELF file if they are different.  That means that,
-     where matters, this value is always our best guess on what CPU we are
-     debugging.  It has been noted that architecture specified in tdesc file
-     has higher precedence over ELF and even "set architecture" - that is,
-     using "set architecture" command will have no effect when tdesc has "arch"
-     tag.  */
-  /* Cannot use arc_mach_is_arcv2 (), because gdbarch is not created yet.  */
-  const int is_arcv2 = (info.bfd_arch_info->mach == bfd_mach_arc_arcv2);
-  bool is_reduced_rf;
-  const char *const *core_regs;
-  const char *core_feature_name;
+/* Common construction code for ARC_GDBARCH_FEATURES struct.  If there
+   is no ABFD, then a FEATURE with default values is returned.  */
 
-  /* If target doesn't provide a description, use the default ones.  */
-  if (!tdesc_has_registers (tdesc_loc))
+static arc_gdbarch_features
+arc_gdbarch_features_create (const bfd *abfd, const unsigned long mach)
+{
+  /* Use 4 as a fallback value.  */
+  int reg_size = 4;
+
+  /* Try to guess the features parameters by looking at the binary to be
+     executed.  If the user is providing a binary that does not match the
+     target, then tough luck.  This is the last effort to makes sense of
+     what's going on.  */
+  if (abfd != nullptr && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
     {
-      if (is_arcv2)
-	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCV2);
+      unsigned char eclass = elf_elfheader (abfd)->e_ident[EI_CLASS];
+
+      if (eclass == ELFCLASS32)
+	reg_size = 4;
+      else if (eclass == ELFCLASS64)
+	reg_size = 8;
       else
-	tdesc_loc = arc_read_description (ARC_SYS_TYPE_ARCOMPACT);
+	internal_error (__FILE__, __LINE__,
+			_("unknown ELF header class %d"), eclass);
     }
-  else
+
+  /* MACH from a bfd_arch_info struct is used here.  It should be a safe
+     bet, as it looks like the struct is always initialized even when we
+     don't pass any elf file to GDB at all (it uses default arch in that
+     case).  */
+  arc_isa isa = mach_type_to_arc_isa (mach);
+
+  return arc_gdbarch_features (reg_size, isa);
+}
+
+/* Look for obsolete core feature names in TDESC.  */
+
+static const struct tdesc_feature *
+find_obsolete_core_names (const struct target_desc *tdesc)
+{
+  const struct tdesc_feature *feat = nullptr;
+
+  feat = tdesc_find_feature (tdesc, ARC_CORE_V1_OBSOLETE_FEATURE_NAME);
+
+  if (feat == nullptr)
+    feat = tdesc_find_feature (tdesc, ARC_CORE_V2_OBSOLETE_FEATURE_NAME);
+
+  if (feat == nullptr)
+    feat = tdesc_find_feature
+      (tdesc, ARC_CORE_V2_REDUCED_OBSOLETE_FEATURE_NAME);
+
+  return feat;
+}
+
+/* Look for obsolete aux feature names in TDESC.  */
+
+static const struct tdesc_feature *
+find_obsolete_aux_names (const struct target_desc *tdesc)
+{
+  return tdesc_find_feature (tdesc, ARC_AUX_OBSOLETE_FEATURE_NAME);
+}
+
+/* Based on the MACH value, determines which core register features set
+   must be used.  */
+
+static arc_register_feature *
+determine_core_reg_feature_set (const unsigned long mach)
+{
+  switch (mach_type_to_arc_isa (mach))
     {
-      if (arc_debug)
-	debug_printf ("arc: Using provided register set.\n");
+    case ARC_ISA_ARCV1:
+      return &arc_v1_core_reg_feature;
+    case ARC_ISA_ARCV2:
+      return &arc_v2_core_reg_feature;
+    default:
+      gdb_assert_not_reached
+        ("Unknown machine type to determine the core feature set.");
     }
-  gdb_assert (tdesc_loc != NULL);
-
-  /* Now we can search for base registers.  Core registers can be either full
-     or reduced.  Summary:
-
-     - core.v2 + aux-minimal
-     - core-reduced.v2 + aux-minimal
-     - core.arcompact + aux-minimal
-
-     NB: It is entirely feasible to have ARCompact with reduced core regs, but
-     we ignore that because GCC doesn't support that and at the same time
-     ARCompact is considered obsolete, so there is not much reason to support
-     that.  */
-  const struct tdesc_feature *feature
-    = tdesc_find_feature (tdesc_loc, core_v2_feature_name);
-  if (feature != NULL)
-    {
-      /* Confirm that register and architecture match, to prevent accidents in
-	 some situations.  This code will trigger an error if:
+}
 
-	 1. XML tdesc doesn't specify arch explicitly, registers are for arch
-	 X, but ELF specifies arch Y.
+/* At the moment, there is only 1 auxiliary register features set.
+   This is a place holder for future extendability.  */
 
-	 2. XML tdesc specifies arch X, but contains registers for arch Y.
+static const arc_register_feature *
+determine_aux_reg_feature_set ()
+{
+  return &arc_common_aux_reg_feature;
+}
 
-	 It will not protect from case where XML or ELF specify arch X,
-	 registers are for the same arch X, but the real target is arch Y.  To
-	 detect this case we need to check IDENTITY register.  */
-      if (!is_arcv2)
-	{
-	  arc_print (_("Error: ARC v2 target description supplied for "
-		       "non-ARCv2 target.\n"));
-	  return false;
-	}
+/* Update accumulator register names (ACCH/ACCL) for r58 and r59 in the
+   register sets.  The endianness determines the assignment:
 
-      is_reduced_rf = false;
-      core_feature_name = core_v2_feature_name;
-      core_regs = core_v2_register_names;
-    }
-  else
+        ,------.------.
+        | acch | accl |
+   ,----|------+------|
+   | LE | r59  | r58  |
+   | BE | r58  | r59  |
+   `----^------^------'  */
+
+static void
+arc_update_acc_reg_names (const int byte_order)
+{
+  const char *r58_alias
+    = byte_order == BFD_ENDIAN_LITTLE ? "accl" : "acch";
+  const char *r59_alias
+    = byte_order == BFD_ENDIAN_LITTLE ? "acch" : "accl";
+
+  /* Subscript 1 must be OK because those registers have 2 names.  */
+  arc_v1_core_reg_feature.registers[ARC_R58_REGNUM].names[1] = r58_alias;
+  arc_v1_core_reg_feature.registers[ARC_R59_REGNUM].names[1] = r59_alias;
+  arc_v2_core_reg_feature.registers[ARC_R58_REGNUM].names[1] = r58_alias;
+  arc_v2_core_reg_feature.registers[ARC_R59_REGNUM].names[1] = r59_alias;
+}
+
+/* Go through all the registers in REG_SET and check if they exist
+   in FEATURE.  The TDESC_DATA is updated with the register number
+   in REG_SET if it is found in the feature.  If a required register
+   is not found, this function returns false.  */
+
+static bool
+arc_check_tdesc_feature (struct tdesc_arch_data *tdesc_data,
+			 const struct tdesc_feature *feature,
+			 const struct arc_register_feature *reg_set)
+{
+  for (const auto &reg : reg_set->registers)
     {
-      feature = tdesc_find_feature (tdesc_loc, core_reduced_v2_feature_name);
-      if (feature != NULL)
+      bool found = false;
+
+      for (const char *name : reg.names)
 	{
-	  if (!is_arcv2)
-	    {
-	      arc_print (_("Error: ARC v2 target description supplied for "
-			   "non-ARCv2 target.\n"));
-	      return false;
-	    }
+	  found
+	    = tdesc_numbered_register (feature, tdesc_data, reg.regnum, name);
 
-	  is_reduced_rf = true;
-	  core_feature_name = core_reduced_v2_feature_name;
-	  core_regs = core_v2_register_names;
+	  if (found)
+	    break;
 	}
-      else
+
+      if (!found && reg.required_p)
 	{
-	  feature = tdesc_find_feature (tdesc_loc,
-					core_arcompact_feature_name);
-	  if (feature != NULL)
-	    {
-	      if (is_arcv2)
-		{
-		  arc_print (_("Error: ARCompact target description supplied "
-			       "for non-ARCompact target.\n"));
-		  return false;
-		}
-
-	      is_reduced_rf = false;
-	      core_feature_name = core_arcompact_feature_name;
-	      core_regs = core_arcompact_register_names;
-	    }
-	  else
+	  std::ostringstream reg_names;
+	  for (std::size_t i = 0; i < reg.names.size(); ++i)
 	    {
-	      arc_print (_("Error: Couldn't find core register feature in "
-			   "supplied target description."));
-	      return false;
+	      if (i == 0)
+		reg_names << "'" << reg.names[0] << "'";
+	      else
+		reg_names << " or '" << reg.names[0] << "'";
 	    }
+	  arc_print (_("Error: Cannot find required register(s) %s "
+		       "in feature '%s'.\n"), reg_names.str ().c_str (),
+		       feature->name.c_str ());
+	  return false;
 	}
     }
 
-  struct tdesc_arch_data *tdesc_data_loc = tdesc_data_alloc ();
+  return true;
+}
 
-  gdb_assert (feature != NULL);
-  int valid_p = 1;
+/* Initialize target description for the ARC.
 
-  for (int i = 0; i <= ARC_LAST_CORE_REGNUM; i++)
+   Returns true if input TDESC was valid and in this case it will assign TDESC
+   and TDESC_DATA output parameters.  */
+
+static bool
+arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
+		struct tdesc_arch_data **tdesc_data)
+{
+  const struct target_desc *tdesc_loc = info.target_desc;
+  if (arc_debug)
+    debug_printf ("arc: Target description initialization.\n");
+
+  /* If target doesn't provide a description, use the default ones.  */
+  if (!tdesc_has_registers (tdesc_loc))
     {
-      /* If rf16, then skip extra registers.  */
-      if (is_reduced_rf && ((i >= ARC_R4_REGNUM && i <= ARC_R9_REGNUM)
-			    || (i >= ARC_R16_REGNUM && i <= ARC_R25_REGNUM)))
-	continue;
-
-      valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i,
-					 core_regs[i]);
-
-      /* - Ignore errors in extension registers - they are optional.
-	 - Ignore missing ILINK because it doesn't make sense for Linux.
-	 - Ignore missing ILINK2 when architecture is ARCompact, because it
-	 doesn't make sense for Linux targets.
-
-	 In theory those optional registers should be in separate features, but
-	 that would create numerous but tiny features, which looks like an
-	 overengineering of a rather simple task.  */
-      if (!valid_p && (i <= ARC_SP_REGNUM || i == ARC_BLINK_REGNUM
-		       || i == ARC_LP_COUNT_REGNUM || i == ARC_PCL_REGNUM
-		       || (i == ARC_R30_REGNUM && is_arcv2)))
-	{
-	  arc_print (_("Error: Cannot find required register `%s' in "
-		       "feature `%s'.\n"), core_regs[i], core_feature_name);
-	  tdesc_data_cleanup (tdesc_data_loc);
-	  return false;
-	}
+      arc_gdbarch_features features
+	= arc_gdbarch_features_create (info.abfd,
+				       info.bfd_arch_info->mach);
+      tdesc_loc = arc_lookup_target_description (features);
+    }
+  gdb_assert (tdesc_loc != nullptr);
+
+  if (arc_debug)
+    debug_printf ("arc: Have got a target description\n");
+
+  const struct tdesc_feature *feature_core
+    = tdesc_find_feature (tdesc_loc, ARC_CORE_FEATURE_NAME);
+  const struct tdesc_feature *feature_aux
+    = tdesc_find_feature (tdesc_loc, ARC_AUX_FEATURE_NAME);
+
+  /* Maybe there still is a chance to salvage the input.  */
+  if (feature_core == nullptr)
+    feature_core = find_obsolete_core_names (tdesc_loc);
+  if (feature_aux == nullptr)
+    feature_aux = find_obsolete_aux_names (tdesc_loc);
+
+  if (feature_core == nullptr)
+    {
+      arc_print (_("Error: Cannot find required feature '%s' in supplied "
+		   "target description.\n"), ARC_CORE_FEATURE_NAME);
+      return false;
     }
 
-  /* Mandatory AUX registers are intentionally few and are common between
-     ARCompact and ARC v2, so same code can be used for both.  */
-  feature = tdesc_find_feature (tdesc_loc, aux_minimal_feature_name);
-  if (feature == NULL)
+  if (feature_aux == nullptr)
     {
-      arc_print (_("Error: Cannot find required feature `%s' in supplied "
-		   "target description.\n"), aux_minimal_feature_name);
-      tdesc_data_cleanup (tdesc_data_loc);
+      arc_print (_("Error: Cannot find required feature '%s' in supplied "
+		   "target description.\n"), ARC_AUX_FEATURE_NAME);
       return false;
     }
 
-  for (int i = ARC_FIRST_AUX_REGNUM; i <= ARC_LAST_AUX_REGNUM; i++)
+  const arc_register_feature *arc_core_reg_feature
+    = determine_core_reg_feature_set (info.bfd_arch_info->mach);
+  const arc_register_feature *arc_aux_reg_feature
+    = determine_aux_reg_feature_set ();
+
+  struct tdesc_arch_data *tdesc_data_loc = tdesc_data_alloc ();
+
+  arc_update_acc_reg_names (info.byte_order);
+
+  bool valid_p = arc_check_tdesc_feature (tdesc_data_loc,
+					  feature_core,
+					  arc_core_reg_feature);
+
+  valid_p &= arc_check_tdesc_feature (tdesc_data_loc,
+				      feature_aux,
+				      arc_aux_reg_feature);
+
+  if (!valid_p)
     {
-      const char *name = aux_minimal_register_names[i - ARC_FIRST_AUX_REGNUM];
-      valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i, name);
-      if (!valid_p)
-	{
-	  arc_print (_("Error: Cannot find required register `%s' "
-		       "in feature `%s'.\n"),
-		     name, tdesc_feature_name (feature));
-	  tdesc_data_cleanup (tdesc_data_loc);
-	  return false;
-	}
+      if (arc_debug)
+        debug_printf ("arc: Target description is not valid\n");
+      tdesc_data_cleanup (tdesc_data_loc);
+      return false;
     }
 
   *tdesc = tdesc_loc;
@@ -2131,38 +2343,6 @@ dump_arc_instruction_command (const char *args, int from_tty)
   arc_insn_dump (insn);
 }
 
-/* See arc-tdep.h.  */
-
-const target_desc *
-arc_read_description (arc_sys_type sys_type)
-{
-  if (arc_debug)
-    debug_printf ("arc: Reading target description for \"%s\".\n",
-		  arc_sys_type_to_str (sys_type));
-
-  gdb_assert ((sys_type >= 0) && (sys_type < ARC_SYS_TYPE_NUM));
-  struct target_desc *tdesc = tdesc_arc_list[sys_type];
-
-  if (tdesc == nullptr)
-    {
-      tdesc = arc_create_target_description (sys_type);
-      tdesc_arc_list[sys_type] = tdesc;
-
-      if (arc_debug)
-	{
-	  const char *arch = tdesc_architecture_name (tdesc);
-	  const char *abi = tdesc_osabi_name (tdesc);
-	  arch = arch != NULL ? arch : "";
-	  abi = abi != NULL ? abi : "";
-	  debug_printf ("arc: Created target description for "
-			"\"%s\": arch=\"%s\", ABI=\"%s\"\n",
-			arc_sys_type_to_str (sys_type), arch, abi);
-	}
-    }
-
-  return tdesc;
-}
-
 void _initialize_arc_tdep ();
 void
 _initialize_arc_tdep ()
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index d72332c7638..6ca759a661d 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -35,7 +35,6 @@ enum arc_regnum
   {
     /* Core registers.  */
     ARC_R0_REGNUM = 0,
-    ARC_FIRST_CORE_REGNUM = ARC_R0_REGNUM,
     ARC_R1_REGNUM = 1,
     ARC_R4_REGNUM = 4,
     ARC_R7_REGNUM = 7,
@@ -54,6 +53,9 @@ enum arc_regnum
     ARC_R30_REGNUM,
     /* Return address from function.  */
     ARC_BLINK_REGNUM,
+    /* Accumulator registers.  */
+    ARC_R58_REGNUM = 58,
+    ARC_R59_REGNUM,
     /* Zero-delay loop counter.  */
     ARC_LP_COUNT_REGNUM = 60,
     /* Reserved register number.  There should never be a register with such
@@ -69,14 +71,21 @@ enum arc_regnum
     /* Program counter, aligned to 4-bytes, read-only.  */
     ARC_PCL_REGNUM,
     ARC_LAST_CORE_REGNUM = ARC_PCL_REGNUM,
+
     /* AUX registers.  */
     /* Actual program counter.  */
     ARC_PC_REGNUM,
     ARC_FIRST_AUX_REGNUM = ARC_PC_REGNUM,
     /* Status register.  */
     ARC_STATUS32_REGNUM,
-    ARC_LAST_REGNUM = ARC_STATUS32_REGNUM,
-    ARC_LAST_AUX_REGNUM = ARC_STATUS32_REGNUM,
+    /* Zero-delay loop start instruction.  */
+    ARC_LP_START_REGNUM,
+    /* Zero-delay loop next-after-last instruction.  */
+    ARC_LP_END_REGNUM,
+    /* Branch target address.  */
+    ARC_BTA_REGNUM,
+    ARC_LAST_AUX_REGNUM = ARC_BTA_REGNUM,
+    ARC_LAST_REGNUM = ARC_LAST_AUX_REGNUM,
 
     /* Additional ABI constants.  */
     ARC_FIRST_ARG_REGNUM = ARC_R0_REGNUM,
@@ -164,7 +173,4 @@ CORE_ADDR arc_insn_get_branch_target (const struct arc_instruction &insn);
 
 CORE_ADDR arc_insn_get_linear_next_pc (const struct arc_instruction &insn);
 
-/* Get the correct ARC target description for the given system type.  */
-const target_desc *arc_read_description (arc_sys_type sys_type);
-
 #endif /* ARC_TDEP_H */
diff --git a/gdb/arch/arc.c b/gdb/arch/arc.c
index 9552b4aff97..8e126ca5a82 100644
--- a/gdb/arch/arc.c
+++ b/gdb/arch/arc.c
@@ -17,42 +17,106 @@
 
 
 #include "gdbsupport/common-defs.h"
-#include <stdlib.h>
-
 #include "arc.h"
+#include <stdlib.h>
+#include <unordered_map>
+#include <string>
 
 /* Target description features.  */
-#include "features/arc/core-v2.c"
-#include "features/arc/aux-v2.c"
-#include "features/arc/core-arcompact.c"
-#include "features/arc/aux-arcompact.c"
+#include "features/arc/v1-core.c"
+#include "features/arc/v1-aux.c"
+#include "features/arc/v2-core.c"
+#include "features/arc/v2-aux.c"
 
-/* See arc.h.  */
+#ifndef GDBSERVER
+#define STATIC_IN_GDB static
+#else
+#define STATIC_IN_GDB
+#endif
 
-target_desc *
-arc_create_target_description (arc_sys_type sys_type)
+STATIC_IN_GDB target_desc *
+arc_create_target_description (const struct arc_gdbarch_features &features)
 {
+  /* Create a new target description.  */
   target_desc *tdesc = allocate_target_description ();
 
-  long regnum = 0;
-
 #ifndef IN_PROCESS_AGENT
-  if (sys_type == ARC_SYS_TYPE_ARCV2)
-    set_tdesc_architecture (tdesc, "arc:ARCv2");
-  else
-    set_tdesc_architecture (tdesc, "arc:ARC700");
-#endif
+  std::string arch_name;
 
-  if (sys_type == ARC_SYS_TYPE_ARCV2)
+  /* Architecture names here must match the ones in
+     ARCH_INFO_STRUCT in bfd/cpu-arc.c.  */
+  if (features.isa == ARC_ISA_ARCV1 && features.reg_size == 4)
+      arch_name = "arc:ARC700";
+  else if (features.isa == ARC_ISA_ARCV2 && features.reg_size == 4)
+      arch_name = "arc:ARCv2";
+  else
     {
-      regnum = create_feature_arc_core_v2 (tdesc, regnum);
-      regnum = create_feature_arc_aux_v2 (tdesc, regnum);
+      std::string msg = string_printf
+	("Cannot determine architecture: ISA=%d; bitness=%d",
+	 features.isa, 8 * features.reg_size);
+      gdb_assert_not_reached (msg.c_str ());
     }
-  else
+
+  set_tdesc_architecture (tdesc, arch_name.c_str ());
+#endif
+
+  long regnum = 0;
+
+  switch (features.isa)
     {
-      regnum = create_feature_arc_core_arcompact (tdesc, regnum);
-      regnum = create_feature_arc_aux_arcompact (tdesc, regnum);
+    case ARC_ISA_ARCV1:
+      regnum = create_feature_arc_v1_core (tdesc, regnum);
+      regnum = create_feature_arc_v1_aux (tdesc, regnum);
+      break;
+    case ARC_ISA_ARCV2:
+      regnum = create_feature_arc_v2_core (tdesc, regnum);
+      regnum = create_feature_arc_v2_aux (tdesc, regnum);
+      break;
+    default:
+      std::string msg = string_printf
+	("Cannot choose target description XML: %d", features.isa);
+      gdb_assert_not_reached (msg.c_str ());
     }
 
   return tdesc;
 }
+
+#ifndef GDBSERVER
+
+/* Wrapper used by std::unordered_map to generate hash for features set.  */
+struct arc_gdbarch_features_hasher
+{
+  std::size_t
+  operator() (const arc_gdbarch_features &features) const noexcept
+  {
+    return features.hash ();
+  }
+};
+
+/* Cache of previously created target descriptions, indexed by the hash
+   of the features set used to create them.  */
+static std::unordered_map<arc_gdbarch_features,
+			  const target_desc_up,
+			  arc_gdbarch_features_hasher> arc_tdesc_cache;
+
+/* See arch/arc.h.  */
+
+const target_desc *
+arc_lookup_target_description (const struct arc_gdbarch_features &features)
+{
+  /* Lookup in the cache first.  If found, return the pointer from the
+     "target_desc_up" type which is a "unique_ptr".  This should be fine
+     as the "arc_tdesc_cache" will persist until GDB terminates.  */
+  const auto it = arc_tdesc_cache.find (features);
+  if (it != arc_tdesc_cache.end ())
+    return it->second.get ();
+
+  target_desc *tdesc = arc_create_target_description (features);
+
+  /* Add the newly created target description to the repertoire.  */
+  arc_tdesc_cache.emplace (features, tdesc);
+
+  return tdesc;
+}
+
+#endif /* !GDBSERVER */
diff --git a/gdb/arch/arc.h b/gdb/arch/arc.h
index fd806ae7d34..a5313b1fee6 100644
--- a/gdb/arch/arc.h
+++ b/gdb/arch/arc.h
@@ -20,29 +20,68 @@
 
 #include "gdbsupport/tdesc.h"
 
-/* Supported ARC system hardware types.  */
-enum arc_sys_type
+/* Supported ARC ISAs.  */
+enum arc_isa
 {
-  ARC_SYS_TYPE_ARCOMPACT = 0,	  /* ARC600 or ARC700 */
-  ARC_SYS_TYPE_ARCV2,		  /* ARC EM or ARC HS */
-  ARC_SYS_TYPE_NUM
+  ARC_ISA_ARCV1 = 1,  /* a.k.a. ARCompact (ARC600, ARC700)  */
+  ARC_ISA_ARCV2	      /* such as ARC EM and ARC HS  */
 };
 
-static inline const char *
-arc_sys_type_to_str (const arc_sys_type type)
+struct arc_gdbarch_features
 {
-  switch (type)
-    {
-    case ARC_SYS_TYPE_ARCOMPACT:
-      return "ARC_SYS_TYPE_ARCOMPACT";
-    case ARC_SYS_TYPE_ARCV2:
-      return "ARC_SYS_TYPE_ARCV2";
-    default:
-      return "Invalid";
-    }
-}
-
-/* Create target description for the specified system type.  */
-target_desc *arc_create_target_description (arc_sys_type sys_type);
+  arc_gdbarch_features (int reg_size, arc_isa isa)
+    : reg_size (reg_size), isa (isa)
+  {}
+
+  /* Register size in bytes.  Possible values are 4, and 8.  A 0 indicates
+     an uninitialised value.  */
+  const int reg_size;
+
+  /* See ARC_ISA enum.  */
+  const arc_isa isa;
+
+  /* Equality operator.  */
+  bool operator== (const struct arc_gdbarch_features &rhs) const
+  {
+    return (reg_size == rhs.reg_size && isa == rhs.isa);
+  }
+
+  /* Inequality operator.  */
+  bool operator!= (const struct arc_gdbarch_features &rhs) const
+  {
+    return !(*this == rhs);
+  }
+
+  /* Used by std::unordered_map to hash the feature sets.  The hash is
+     calculated in the manner below:
+     REG_SIZE |  ISA
+      5-bits  | 4-bits  */
+
+  std::size_t hash () const noexcept
+  {
+    std::size_t val = ((reg_size & 0x1f) << 8 | (isa & 0xf) << 0);
+    return val;
+  }
+};
+
+#ifdef GDBSERVER
+
+/* Create and return a target description that is compatible with FEATURES.
+   The only external client of this must be the gdbserver which manipulates
+   the returned data.  */
+
+target_desc *arc_create_target_description
+	(const struct arc_gdbarch_features &features);
+
+#else
+
+/* Lookup the cache for a target description matching the FEATURES.
+   If nothing is found, then create one and return it.  */
+
+const target_desc *arc_lookup_target_description
+	(const struct arc_gdbarch_features &features);
+
+#endif /* GDBSERVER */
+
 
 #endif /* ARCH_ARC_H */
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index cddcdaab2c8..6a81351282f 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,8 @@
+2020-08-25  Shahab Vahedi  <shahab@synopsys.com>
+
+	* gdb.texinfo (Synopsys ARC): Update the documentation for ARC
+	Features.
+
 2020-08-07  Tom Tromey  <tromey@adacore.com>
 
 	* gdb.texinfo (Ravenscar Profile): Add examples.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 77013648b2f..a4f5b787503 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -45265,40 +45265,41 @@ it should contain registers @samp{pauth_dmask} and @samp{pauth_cmask}.
 @subsection ARC Features
 @cindex target descriptions, ARC Features
 
-ARC processors are highly configurable, so even core registers and their number
-are not completely predetermined.  In addition flags and PC registers which are
-important to @value{GDBN} are not ``core'' registers in ARC.  It is required
-that one of the core registers features is present.
-@samp{org.gnu.gdb.arc.aux-minimal} feature is mandatory.
-
-The @samp{org.gnu.gdb.arc.core.v2} feature is required for ARC EM and ARC HS
-targets with a normal register file.  It should contain registers @samp{r0}
-through @samp{r25}, @samp{gp}, @samp{fp}, @samp{sp}, @samp{r30}, @samp{blink},
-@samp{lp_count} and @samp{pcl}.  This feature may contain register @samp{ilink}
-and any of extension core registers @samp{r32} through @samp{r59/acch}.
-@samp{ilink} and extension core registers are not available to read/write, when
-debugging GNU/Linux applications, thus @samp{ilink} is made optional.
-
-The @samp{org.gnu.gdb.arc.core-reduced.v2} feature is required for ARC EM and
-ARC HS targets with a reduced register file.  It should contain registers
-@samp{r0} through @samp{r3}, @samp{r10} through @samp{r15}, @samp{gp},
-@samp{fp}, @samp{sp}, @samp{r30}, @samp{blink}, @samp{lp_count} and @samp{pcl}.
-This feature may contain register @samp{ilink} and any of extension core
-registers @samp{r32} through @samp{r59/acch}.
-
-The @samp{org.gnu.gdb.arc.core.arcompact} feature is required for ARCompact
-targets with a normal register file.  It should contain registers @samp{r0}
-through @samp{r25}, @samp{gp}, @samp{fp}, @samp{sp}, @samp{r30}, @samp{blink},
-@samp{lp_count} and @samp{pcl}.  This feature may contain registers
-@samp{ilink1}, @samp{ilink2} and any of extension core registers @samp{r32}
-through @samp{r59/acch}.  @samp{ilink1} and @samp{ilink2} and extension core
-registers are not available when debugging GNU/Linux applications.  The only
-difference with @samp{org.gnu.gdb.arc.core.v2} feature is in the names of
-@samp{ilink1} and @samp{ilink2} registers and that @samp{r30} is mandatory in
-ARC v2, but @samp{ilink2} is optional on ARCompact.
-
-The @samp{org.gnu.gdb.arc.aux-minimal} feature is required for all ARC
-targets.  It should contain registers @samp{pc} and @samp{status32}.
+ARC processors are so configurable that even core registers and their numbers
+are not predetermined completely.  Moreover, @emph{flags} and @emph{PC}
+registers, which are important to @value{GDBN}, are not ``core'' registers in
+ARC.  Therefore, there are two features that their presence is mandatory:
+@samp{org.gnu.gdb.arc.core} and @samp{org.gnu.gdb.arc.aux}.
+
+The @samp{org.gnu.gdb.arc.core} feature is required for all targets.  It must
+contain registers:
+
+@itemize @minus
+@item
+@samp{r0} through @samp{r25} for normal register file targets.
+@item
+@samp{r0} through @samp{r3}, and @samp{r10} through @samp{r15} for reduced
+register file targets.
+@item
+@samp{gp}, @samp{fp}, @samp{sp}, @samp{r30}@footnote{Not necessary for ARCv1.},
+@samp{blink}, @samp{lp_count}, @samp{pcl}.
+@end itemize
+
+In case of an ARCompact target (ARCv1 ISA), the @samp{org.gnu.gdb.arc.core}
+feature may contain registers @samp{ilink1} and @samp{ilink2}.  While in case
+of ARC EM and ARC HS targets (ARCv2 ISA), register @samp{ilink} may be present.
+The difference between ARCv1 and ARCv2 is the naming of registers @emph{29th}
+and @emph{30th}.  They are called @samp{ilink1} and @samp{ilink2} for ARCv1 and
+are optional.  For ARCv2, they are called @samp{ilink} and @samp{r30} and only
+@samp{ilink} is optional.  The optionality of @samp{ilink*} registers is
+because of their inaccessibility during user space debugging sessions.
+
+Extension core registers @samp{r32} through @samp{r59} are optional and their
+existence depends on the configuration.  When debugging GNU/Linux applications,
+i.e.@: user space debugging, these core registers are not available.
+
+The @samp{org.gnu.gdb.arc.aux} feature is required for all ARC targets.  It
+should at least contain @samp{pc} and @samp{status32} registers.
 
 @node ARM Features
 @subsection ARM Features
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index d0af9a47b48..689603847a0 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -201,10 +201,10 @@ $(outdir)/%.dat: %.xml number-regs.xsl sort-regs.xsl gdbserver-regs.xsl
 FEATURE_XMLFILES = aarch64-core.xml \
 	aarch64-fpu.xml \
 	aarch64-pauth.xml \
-	arc/core-v2.xml \
-	arc/aux-v2.xml \
-	arc/core-arcompact.xml \
-	arc/aux-arcompact.xml \
+	arc/v1-core.xml \
+	arc/v1-aux.xml \
+	arc/v2-core.xml \
+	arc/v2-aux.xml \
 	arm/arm-core.xml \
 	arm/arm-fpa.xml \
 	arm/arm-m-profile.xml \
diff --git a/gdb/features/arc/aux-arcompact.c b/gdb/features/arc/v1-aux.c
similarity index 73%
rename from gdb/features/arc/aux-arcompact.c
rename to gdb/features/arc/v1-aux.c
index d8e8c74e639..d1540763433 100644
--- a/gdb/features/arc/aux-arcompact.c
+++ b/gdb/features/arc/v1-aux.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: aux-arcompact.xml */
+  Original: v1-aux.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_aux_arcompact (struct target_desc *result, long regnum)
+create_feature_arc_v1_aux (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux-minimal");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux");
   tdesc_type_with_fields *type_with_fields;
   type_with_fields = tdesc_create_flags (feature, "status32_type", 4);
   tdesc_add_flag (type_with_fields, 0, "H");
@@ -27,5 +27,8 @@ create_feature_arc_aux_arcompact (struct target_desc *result, long regnum)
 
   tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "status32", regnum++, 1, NULL, 32, "status32_type");
+  tdesc_create_reg (feature, "lp_start", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "lp_end", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "bta", regnum++, 1, NULL, 32, "code_ptr");
   return regnum;
 }
diff --git a/gdb/features/arc/aux-arcompact.xml b/gdb/features/arc/v1-aux.xml
similarity index 80%
rename from gdb/features/arc/aux-arcompact.xml
rename to gdb/features/arc/v1-aux.xml
index bf68112f5db..091808b1e29 100644
--- a/gdb/features/arc/aux-arcompact.xml
+++ b/gdb/features/arc/v1-aux.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.aux-minimal">
+<feature name="org.gnu.gdb.arc.aux">
   <flags id="status32_type" size="4">
       <field name="H"   start="0" end="0"/>
       <field name="E"   start="1" end="2"/>
@@ -19,10 +19,13 @@
       <field name="N"   start="10" end="10"/>
       <field name="Z"   start="11" end="11"/>
       <field name="L"   start="12" end="12"/>
-      <field name="R"  start="13" end="13"/>
+      <field name="R"   start="13" end="13"/>
       <field name="SE"  start="14" end="14"/>
   </flags>
 
   <reg name="pc"       bitsize="32" type="code_ptr"/>
   <reg name="status32" bitsize="32" type="status32_type"/>
+  <reg name="lp_start" bitsize="32" type="code_ptr"/>
+  <reg name="lp_end"   bitsize="32" type="code_ptr"/>
+  <reg name="bta"      bitsize="32" type="code_ptr"/>
 </feature>
diff --git a/gdb/features/arc/core-arcompact.c b/gdb/features/arc/v1-core.c
similarity index 87%
rename from gdb/features/arc/core-arcompact.c
rename to gdb/features/arc/v1-core.c
index 7d9a4b23c21..df51d4788df 100644
--- a/gdb/features/arc/core-arcompact.c
+++ b/gdb/features/arc/v1-core.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: core-arcompact.xml */
+  Original: v1-core.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_core_arcompact (struct target_desc *result, long regnum)
+create_feature_arc_v1_core (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core.arcompact");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core");
   tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
@@ -38,8 +38,6 @@ create_feature_arc_core_arcompact (struct target_desc *result, long regnum)
   tdesc_create_reg (feature, "gp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "fp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
-  tdesc_create_reg (feature, "ilink1", regnum++, 1, NULL, 32, "code_ptr");
-  tdesc_create_reg (feature, "ilink2", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "blink", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "lp_count", regnum++, 1, NULL, 32, "uint32");
   tdesc_create_reg (feature, "pcl", regnum++, 1, NULL, 32, "code_ptr");
diff --git a/gdb/features/arc/core-arcompact.xml b/gdb/features/arc/v1-core.xml
similarity index 92%
rename from gdb/features/arc/core-arcompact.xml
rename to gdb/features/arc/v1-core.xml
index 9209891b41a..68d04bdf9d0 100644
--- a/gdb/features/arc/core-arcompact.xml
+++ b/gdb/features/arc/v1-core.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.core.arcompact">
+<feature name="org.gnu.gdb.arc.core">
   <reg name="r0"  bitsize="32"/>
   <reg name="r1"  bitsize="32"/>
   <reg name="r2"  bitsize="32"/>
@@ -40,8 +40,6 @@
   <reg name="sp"  bitsize="32" type="data_ptr"/>
 
   <!-- Code pointers.  -->
-  <reg name="ilink1" bitsize="32" type="code_ptr"/>
-  <reg name="ilink2" bitsize="32" type="code_ptr"/>
   <reg name="blink"  bitsize="32" type="code_ptr"/>
 
   <!-- Here goes extension core registers: r32 - r59 -->
diff --git a/gdb/features/arc/aux-v2.c b/gdb/features/arc/v2-aux.c
similarity index 76%
rename from gdb/features/arc/aux-v2.c
rename to gdb/features/arc/v2-aux.c
index 6290b9b1a7f..7b38e377fe1 100644
--- a/gdb/features/arc/aux-v2.c
+++ b/gdb/features/arc/v2-aux.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: aux-v2.xml */
+  Original: v2-aux.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_aux_v2 (struct target_desc *result, long regnum)
+create_feature_arc_v2_aux (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux-minimal");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux");
   tdesc_type_with_fields *type_with_fields;
   type_with_fields = tdesc_create_flags (feature, "status32_type", 4);
   tdesc_add_flag (type_with_fields, 0, "H");
@@ -31,5 +31,8 @@ create_feature_arc_aux_v2 (struct target_desc *result, long regnum)
 
   tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "status32", regnum++, 1, NULL, 32, "status32_type");
+  tdesc_create_reg (feature, "lp_start", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "lp_end", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "bta", regnum++, 1, NULL, 32, "code_ptr");
   return regnum;
 }
diff --git a/gdb/features/arc/aux-v2.xml b/gdb/features/arc/v2-aux.xml
similarity index 86%
rename from gdb/features/arc/aux-v2.xml
rename to gdb/features/arc/v2-aux.xml
index 2701fad72dc..5d81e248088 100644
--- a/gdb/features/arc/aux-v2.xml
+++ b/gdb/features/arc/v2-aux.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.aux-minimal">
+<feature name="org.gnu.gdb.arc.aux">
   <flags id="status32_type" size="4">
       <field name="H"   start="0" end="0"/>
       <field name="E"   start="1" end="4"/>
@@ -29,4 +29,7 @@
 
   <reg name="pc"       bitsize="32" type="code_ptr"/>
   <reg name="status32" bitsize="32" type="status32_type"/>
+  <reg name="lp_start" bitsize="32" type="code_ptr"/>
+  <reg name="lp_end"   bitsize="32" type="code_ptr"/>
+  <reg name="bta"      bitsize="32" type="code_ptr"/>
 </feature>
diff --git a/gdb/features/arc/core-v2.c b/gdb/features/arc/v2-core.c
similarity index 91%
rename from gdb/features/arc/core-v2.c
rename to gdb/features/arc/v2-core.c
index d37da990457..1c3ef1a91df 100644
--- a/gdb/features/arc/core-v2.c
+++ b/gdb/features/arc/v2-core.c
@@ -1,14 +1,14 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
-  Original: core-v2.xml */
+  Original: v2-core.xml */
 
 #include "gdbsupport/tdesc.h"
 
 static int
-create_feature_arc_core_v2 (struct target_desc *result, long regnum)
+create_feature_arc_v2_core (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
 
-  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core.v2");
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core");
   tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "int");
@@ -38,7 +38,6 @@ create_feature_arc_core_v2 (struct target_desc *result, long regnum)
   tdesc_create_reg (feature, "gp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "fp", regnum++, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
-  tdesc_create_reg (feature, "ilink", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "r30", regnum++, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "blink", regnum++, 1, NULL, 32, "code_ptr");
   tdesc_create_reg (feature, "lp_count", regnum++, 1, NULL, 32, "uint32");
diff --git a/gdb/features/arc/core-v2.xml b/gdb/features/arc/v2-core.xml
similarity index 90%
rename from gdb/features/arc/core-v2.xml
rename to gdb/features/arc/v2-core.xml
index 1b17968fb2e..2a2561eab16 100644
--- a/gdb/features/arc/core-v2.xml
+++ b/gdb/features/arc/v2-core.xml
@@ -6,7 +6,7 @@
      notice and this notice are preserved.  -->
 
 <!DOCTYPE target SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.arc.core.v2">
+<feature name="org.gnu.gdb.arc.core">
   <reg name="r0"  bitsize="32"/>
   <reg name="r1"  bitsize="32"/>
   <reg name="r2"  bitsize="32"/>
@@ -42,12 +42,11 @@
   <!-- Code pointers.  R30 is general purpose, but it used to be ILINK2 in
   ARCompact, thus its odd position in between of special purpose registers.
   GCC does't use this register, so it isn't a member of a general group. -->
-  <reg name="ilink" bitsize="32" type="code_ptr"/>
   <reg name="r30"   bitsize="32" group=""/>
   <reg name="blink" bitsize="32" type="code_ptr"/>
 
-  <!-- Here goes extension core registers: r32 - r57.  -->
-  <!-- Here goes ACCL/ACCH registers, r58, r59.  -->
+  <!-- Extension core registers: r32 - r57.  -->
+  <!-- ACCL/ACCH registers: r58, r59.  -->
 
   <!-- Loop counter.  -->
   <reg name="lp_count" bitsize="32" type="uint32"/>
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index deab76474cf..cb2945697ad 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2020-08-25  Shahab Vahedi  <shahab@synopsys.com>
+
+	* gdb.arch/arc-tdesc-cpu.xml: Use new feature names.
+
 2020-08-25  Simon Marchi  <simon.marchi@polymtl.ca>
 
 	PR gdb/26532
diff --git a/gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml b/gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml
index 09689b8a44b..0ae2190c511 100644
--- a/gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml
+++ b/gdb/testsuite/gdb.arch/arc-tdesc-cpu.xml
@@ -9,7 +9,7 @@
 <target>
   <architecture>arc:HS</architecture>
 
-  <feature name="org.gnu.gdb.arc.core.v2">
+  <feature name="org.gnu.gdb.arc.core">
     <reg name="r0"  bitsize="32"/>
     <reg name="r1"  bitsize="32"/>
     <reg name="r2"  bitsize="32"/>
@@ -46,7 +46,7 @@
     <reg name="pcl" bitsize="32"/>
   </feature>
 
-  <feature name="org.gnu.gdb.arc.aux-minimal">
+  <feature name="org.gnu.gdb.arc.aux">
     <reg name="pc"       bitsize="32"/>
     <reg name="status32" bitsize="32"/>
   </feature>
-- 
2.28.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PUSHED 2/4] arc: Add inclusion of "gdbarch.h" in "arc-tdep.h"
  2020-08-25 15:47 ` [PUSHED " Shahab Vahedi
  2020-08-25 15:47   ` [PUSHED 1/4] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
@ 2020-08-25 15:47   ` Shahab Vahedi
  2020-08-25 15:47   ` [PUSHED 3/4] arc: Add hardware loop detection Shahab Vahedi
  2020-08-25 15:47   ` [PUSHED 4/4] arc: Add GNU/Linux support for ARC Shahab Vahedi
  3 siblings, 0 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-25 15:47 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Eli Zaretskii, Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

The "arc-tdep.h" makes use of definitions in "gdbarch.h", but it
does not include it explicitly.  I have piggy backed this fix
in another commit [1], but I was asked to do it separately [2].

[1] arc: Add hardware loop detection
https://sourceware.org/pipermail/gdb-patches/2020-July/170800.html

[2] Simon's remarks to "arc: Add hardware loop detection"
https://sourceware.org/pipermail/gdb-patches/2020-August/170993.html

gdb/ChangeLog:

	* arc-tdep.h: Include "gdbarch.h".
---
 gdb/ChangeLog  | 4 ++++
 gdb/arc-tdep.h | 1 +
 2 files changed, 5 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ec936d7ccd4..c7e8cfd3bf6 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,7 @@
+2020-08-25  Shahab Vahedi  <shahab@synopsys.com>
+
+	* arc-tdep.h: Include "gdbarch.h".
+
 2020-08-25  Shahab Vahedi  <shahab@synopsys.com>
 
 	* arch/arc.h
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index 6ca759a661d..5968abd4600 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -23,6 +23,7 @@
 
 /* Need disassemble_info.  */
 #include "dis-asm.h"
+#include "gdbarch.h"
 #include "arch/arc.h"
 
 /* To simplify GDB code this enum assumes that internal regnums should be same
-- 
2.28.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PUSHED 3/4] arc: Add hardware loop detection
  2020-08-25 15:47 ` [PUSHED " Shahab Vahedi
  2020-08-25 15:47   ` [PUSHED 1/4] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
  2020-08-25 15:47   ` [PUSHED 2/4] arc: Add inclusion of "gdbarch.h" in "arc-tdep.h" Shahab Vahedi
@ 2020-08-25 15:47   ` Shahab Vahedi
  2020-08-25 15:58     ` Eli Zaretskii
  2020-08-25 15:47   ` [PUSHED 4/4] arc: Add GNU/Linux support for ARC Shahab Vahedi
  3 siblings, 1 reply; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-25 15:47 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Eli Zaretskii, Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

For ARC there are registers that are not part of a required set in XML
target descriptions by default, but are almost always present on ARC
targets and are universally exposed by the ptrace interface.  Hardware
loop registers being one of them.

LP_START and LP_END auxiliary registers are hardware loop start and end.
Formally, they are optional, but it is hard to find an ARC configuration
that doesn't have them.  They are always present in processors that can
run GNU/Linux.  GDB needs to know about those registers to implement
proper software single stepping, since they affect  what instruction
will be next.

This commit adds the code to check for the existance of "lp_start" and
"lp_end" in XML target descriptions. If they exist, then the function
reports that the target supports hardware loops.

gdb/ChangeLog:

	* arc-tdep.c (arc_check_for_hardware_loop): New.
	* arc-tdep.h (gdbarch_tdep): New field has_hw_loops.

gdb/doc/ChangeLog:

	* gdb.texinfo (Synopsys ARC): Document LP_START, LP_END and BTA.
---
 gdb/ChangeLog       |  5 +++++
 gdb/arc-tdep.c      | 39 +++++++++++++++++++++++++++++++++++----
 gdb/arc-tdep.h      |  3 +++
 gdb/doc/ChangeLog   |  4 ++++
 gdb/doc/gdb.texinfo | 11 +++++++++--
 5 files changed, 56 insertions(+), 6 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c7e8cfd3bf6..2e97cdc061c 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2020-08-25  Shahab Vahedi  <shahab@synopsys.com>
+
+	* arc-tdep.c (arc_check_for_hardware_loop): New.
+	* arc-tdep.h (gdbarch_tdep): New field has_hw_loops.
+
 2020-08-25  Shahab Vahedi  <shahab@synopsys.com>
 
 	* arc-tdep.h: Include "gdbarch.h".
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index cb4941dec02..8b4e2857fb9 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -2041,6 +2041,35 @@ arc_check_tdesc_feature (struct tdesc_arch_data *tdesc_data,
   return true;
 }
 
+/* Check for the existance of "lp_start" and "lp_end" in target description.
+   If both are present, assume there is hardware loop support in the target.
+   This can be improved by looking into "lpc_size" field of "isa_config"
+   auxiliary register.  */
+
+static bool
+arc_check_for_hw_loops (const struct target_desc *tdesc,
+			struct tdesc_arch_data *data)
+{
+  const auto feature_aux = tdesc_find_feature (tdesc, ARC_AUX_FEATURE_NAME);
+  const auto aux_regset = determine_aux_reg_feature_set ();
+
+  if (feature_aux == nullptr)
+    return false;
+
+  bool hw_loop_p = false;
+  const auto lp_start_name =
+    aux_regset->registers[ARC_LP_START_REGNUM - ARC_FIRST_AUX_REGNUM].names[0];
+  const auto lp_end_name =
+    aux_regset->registers[ARC_LP_END_REGNUM - ARC_FIRST_AUX_REGNUM].names[0];
+
+  hw_loop_p = tdesc_numbered_register (feature_aux, data,
+				       ARC_LP_START_REGNUM, lp_start_name);
+  hw_loop_p &= tdesc_numbered_register (feature_aux, data,
+				       ARC_LP_END_REGNUM, lp_end_name);
+
+  return hw_loop_p;
+}
+
 /* Initialize target description for the ARC.
 
    Returns true if input TDESC was valid and in this case it will assign TDESC
@@ -2163,13 +2192,15 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     debug_printf ("arc: Architecture initialization.\n");
 
   if (!arc_tdesc_init (info, &tdesc, &tdesc_data))
-    return NULL;
+    return nullptr;
 
   /* Allocate the ARC-private target-dependent information structure, and the
      GDB target-independent information structure.  */
-  struct gdbarch_tdep *tdep = XCNEW (struct gdbarch_tdep);
+  gdb::unique_xmalloc_ptr<struct gdbarch_tdep> tdep
+    (XCNEW (struct gdbarch_tdep));
   tdep->jb_pc = -1; /* No longjmp support by default.  */
-  struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep);
+  tdep->has_hw_loops = arc_check_for_hw_loops (tdesc, tdesc_data);
+  struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep.release ());
 
   /* Data types.  */
   set_gdbarch_short_bit (gdbarch, 16);
@@ -2250,7 +2281,7 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      It can override functions set earlier.  */
   gdbarch_init_osabi (info, gdbarch);
 
-  if (tdep->jb_pc >= 0)
+  if (gdbarch_tdep (gdbarch)->jb_pc >= 0)
     set_gdbarch_get_longjmp_target (gdbarch, arc_get_longjmp_target);
 
   /* Disassembler options.  Enforce CPU if it was specified in XML target
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index 5968abd4600..e752348a262 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -111,6 +111,9 @@ struct gdbarch_tdep
   /* Offset to PC value in jump buffer.  If this is negative, longjmp
      support will be disabled.  */
   int jb_pc;
+
+  /* Whether target has hardware (aka zero-delay) loops.  */
+  bool has_hw_loops;
 };
 
 /* Utility functions used by other ARC-specific modules.  */
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 6a81351282f..badf7ae10b5 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,7 @@
+2020-08-25  Shahab Vahedi  <shahab@synopsys.com>
+
+	* gdb.texinfo (Synopsys ARC): Document LP_START, LP_END and BTA.
+
 2020-08-25  Shahab Vahedi  <shahab@synopsys.com>
 
 	* gdb.texinfo (Synopsys ARC): Update the documentation for ARC
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index a4f5b787503..77c5d895053 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -45298,8 +45298,15 @@ Extension core registers @samp{r32} through @samp{r59} are optional and their
 existence depends on the configuration.  When debugging GNU/Linux applications,
 i.e.@: user space debugging, these core registers are not available.
 
-The @samp{org.gnu.gdb.arc.aux} feature is required for all ARC targets.  It
-should at least contain @samp{pc} and @samp{status32} registers.
+The @samp{org.gnu.gdb.arc.aux} feature is required for all ARC targets.  Here
+is the list of registers pertinent to this feature:
+
+@itemize @minus
+@item
+mandatory: @samp{pc} and @samp{status32}.
+@item
+optional: @samp{lp_start}, @samp{lp_end}, and @samp{bta}.
+@end itemize
 
 @node ARM Features
 @subsection ARM Features
-- 
2.28.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* [PUSHED 4/4] arc: Add GNU/Linux support for ARC
  2020-08-25 15:47 ` [PUSHED " Shahab Vahedi
                     ` (2 preceding siblings ...)
  2020-08-25 15:47   ` [PUSHED 3/4] arc: Add hardware loop detection Shahab Vahedi
@ 2020-08-25 15:47   ` Shahab Vahedi
  3 siblings, 0 replies; 86+ messages in thread
From: Shahab Vahedi @ 2020-08-25 15:47 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Simon Marchi, Tom Tromey,
	Eli Zaretskii, Anton Kolesov, Francois Bedard, Anton Kolesov

From: Anton Kolesov <Anton.Kolesov@synopsys.com>

ARC Linux targets differences from baremetal:

- No support for hardware single instruction stepping.
- Different access rules to registers.
- Use of another instruction for breakpoints.

v2: Changes after Tom's remarks [1]
 arc-linux-tdep.c
  - Use true/false instead of TRUE/FALSE.
  - arc_linux_sw_breakpoint_from_kind (): Break long lines into two.
  - arc_linux_sw_breakpoint_from_kind (): Remove starting blank line.
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 arc-tdep.c
  - Use explicit number evaluation, e.g: if (a & b) -> if ((a & b) != 0)
 gdb/configure.tgt
  - arc*-*-linux*): Remove "build_gdbserver=yes".

v3: Changes after Simon's remarks [2]
  arc-linux-tdep.c
  - Use "return trap_size" instead of cryptic "return 2".
  - Removed unnecessary curly braces.
  - Removed "void" from "_initialize_arc_linux_tdep (void)".

v5: Changes after Simon's remarks [3]
- Remove unnecessary empty lines.
- Replace "breakpoint uses" with "breakpoints use" in a comment.
- "return condition;" i.s.o. "if (condition) return true; else return false;"

[1] Tom's remarks
https://sourceware.org/pipermail/gdb-patches/2020-April/167887.html

[2] Simon's remarks on v2
https://sourceware.org/pipermail/gdb-patches/2020-May/168513.html

[3] Simon's remarks on v4
https://sourceware.org/pipermail/gdb-patches/2020-August/170994.html

gdb/ChangeLog:

2020-08-25  Anton Kolesov  <anton.kolesov@synopsys.com>

	* configure.tgt: ARC support for GNU/Linux.
	* Makefile.in (ALL_TARGET_OBJS): Likewise.
	* arc-linux-tdep.c: New file.
	* arc-tdep.h (ARC_STATUS32_L_MASK, ARC_STATUS32_DE_MASK): Declare.
	* arc-tdep.c (arc_write_pc): Use it.
---
 gdb/ChangeLog        |   8 ++
 gdb/Makefile.in      |   1 +
 gdb/arc-linux-tdep.c | 278 +++++++++++++++++++++++++++++++++++++++++++
 gdb/arc-tdep.c       |   3 +-
 gdb/arc-tdep.h       |   5 +
 gdb/configure.tgt    |   5 +
 6 files changed, 298 insertions(+), 2 deletions(-)
 create mode 100644 gdb/arc-linux-tdep.c

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2e97cdc061c..150a7afc581 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@
+2020-08-25  Anton Kolesov  <anton.kolesov@synopsys.com>
+
+	* configure.tgt: ARC support for GNU/Linux.
+	* Makefile.in (ALL_TARGET_OBJS): Likewise.
+	* arc-linux-tdep.c: New file.
+	* arc-tdep.h (ARC_STATUS32_L_MASK, ARC_STATUS32_DE_MASK): Declare.
+	* arc-tdep.c (arc_write_pc): Use it.
+
 2020-08-25  Shahab Vahedi  <shahab@synopsys.com>
 
 	* arc-tdep.c (arc_check_for_hardware_loop): New.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 66abac4b15a..4808357e651 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -702,6 +702,7 @@ ALL_64_TARGET_OBS = \
 # All other target-dependent objects files (used with --enable-targets=all).
 ALL_TARGET_OBS = \
 	aarch32-tdep.o \
+	arc-linux-tdep.o \
 	arc-tdep.o \
 	arch/aarch32.o \
 	arch/arc.o \
diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
new file mode 100644
index 00000000000..36f32459bbe
--- /dev/null
+++ b/gdb/arc-linux-tdep.c
@@ -0,0 +1,278 @@
+/* Target dependent code for GNU/Linux ARC.
+
+   Copyright 2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* GDB header files.  */
+#include "defs.h"
+#include "linux-tdep.h"
+#include "objfiles.h"
+#include "opcode/arc.h"
+#include "osabi.h"
+#include "solib-svr4.h"
+
+/* ARC header files.  */
+#include "opcodes/arc-dis.h"
+#include "arc-tdep.h"
+
+/* Implement the "cannot_fetch_register" gdbarch method.  */
+
+static int
+arc_linux_cannot_fetch_register (struct gdbarch *gdbarch, int regnum)
+{
+  /* Assume that register is readable if it is unknown.  */
+  switch (regnum)
+    {
+    case ARC_ILINK_REGNUM:
+    case ARC_RESERVED_REGNUM:
+    case ARC_LIMM_REGNUM:
+      return true;
+    case ARC_R30_REGNUM:
+    case ARC_R58_REGNUM:
+    case ARC_R59_REGNUM:
+      return !arc_mach_is_arcv2 (gdbarch);
+    }
+  return (regnum > ARC_BLINK_REGNUM) && (regnum < ARC_LP_COUNT_REGNUM);
+}
+
+/* Implement the "cannot_store_register" gdbarch method.  */
+
+static int
+arc_linux_cannot_store_register (struct gdbarch *gdbarch, int regnum)
+{
+  /* Assume that register is writable if it is unknown.  */
+  switch (regnum)
+    {
+    case ARC_ILINK_REGNUM:
+    case ARC_RESERVED_REGNUM:
+    case ARC_LIMM_REGNUM:
+    case ARC_PCL_REGNUM:
+      return true;
+    case ARC_R30_REGNUM:
+    case ARC_R58_REGNUM:
+    case ARC_R59_REGNUM:
+      return !arc_mach_is_arcv2 (gdbarch);
+    }
+  return (regnum > ARC_BLINK_REGNUM) && (regnum < ARC_LP_COUNT_REGNUM);
+}
+
+/* For ARC Linux, breakpoints use the 16-bit TRAP_S 1 instruction, which
+   is 0x3e78 (little endian) or 0x783e (big endian).  */
+
+static const gdb_byte arc_linux_trap_s_be[] = { 0x78, 0x3e };
+static const gdb_byte arc_linux_trap_s_le[] = { 0x3e, 0x78 };
+static const int trap_size = 2;   /* Number of bytes to insert "trap".  */
+
+/* Implement the "breakpoint_kind_from_pc" gdbarch method.  */
+
+static int
+arc_linux_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+  return trap_size;
+}
+
+/* Implement the "sw_breakpoint_from_kind" gdbarch method.  */
+
+static const gdb_byte *
+arc_linux_sw_breakpoint_from_kind (struct gdbarch *gdbarch,
+				   int kind, int *size)
+{
+  *size = kind;
+  return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+	  ? arc_linux_trap_s_be
+	  : arc_linux_trap_s_le);
+}
+
+/* Implement the "software_single_step" gdbarch method.  */
+
+static std::vector<CORE_ADDR>
+arc_linux_software_single_step (struct regcache *regcache)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct disassemble_info di = arc_disassemble_info (gdbarch);
+
+  /* Read current instruction.  */
+  struct arc_instruction curr_insn;
+  arc_insn_decode (regcache_read_pc (regcache), &di, arc_delayed_print_insn,
+		   &curr_insn);
+  CORE_ADDR next_pc = arc_insn_get_linear_next_pc (curr_insn);
+
+  std::vector<CORE_ADDR> next_pcs;
+
+  /* For instructions with delay slots, the fall thru is not the
+     instruction immediately after the current instruction, but the one
+     after that.  */
+  if (curr_insn.has_delay_slot)
+    {
+      struct arc_instruction next_insn;
+      arc_insn_decode (next_pc, &di, arc_delayed_print_insn, &next_insn);
+      next_pcs.push_back (arc_insn_get_linear_next_pc (next_insn));
+    }
+  else
+    next_pcs.push_back (next_pc);
+
+  ULONGEST status32;
+  regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
+				 &status32);
+
+  if (curr_insn.is_control_flow)
+    {
+      CORE_ADDR branch_pc = arc_insn_get_branch_target (curr_insn);
+      if (branch_pc != next_pc)
+	next_pcs.push_back (branch_pc);
+    }
+  /* Is current instruction the last in a loop body?  */
+  else if (tdep->has_hw_loops)
+    {
+      /* If STATUS32.L is 1, then ZD-loops are disabled.  */
+      if ((status32 & ARC_STATUS32_L_MASK) == 0)
+	{
+	  ULONGEST lp_end, lp_start, lp_count;
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_START_REGNUM,
+					 &lp_start);
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_END_REGNUM, &lp_end);
+	  regcache_cooked_read_unsigned (regcache, ARC_LP_COUNT_REGNUM,
+					 &lp_count);
+
+	  if (arc_debug)
+	    {
+	      debug_printf ("arc-linux: lp_start = %s, lp_end = %s, "
+			    "lp_count = %s, next_pc = %s\n",
+			    paddress (gdbarch, lp_start),
+			    paddress (gdbarch, lp_end),
+			    pulongest (lp_count),
+			    paddress (gdbarch, next_pc));
+	    }
+
+	  if (next_pc == lp_end && lp_count > 1)
+	    {
+	      /* The instruction is in effect a jump back to the start of
+		 the loop.  */
+	      next_pcs.push_back (lp_start);
+	    }
+	}
+    }
+
+  /* Is this a delay slot?  Then next PC is in BTA register.  */
+  if ((status32 & ARC_STATUS32_DE_MASK) != 0)
+    {
+      ULONGEST bta;
+      regcache_cooked_read_unsigned (regcache, ARC_BTA_REGNUM, &bta);
+      next_pcs.push_back (bta);
+    }
+
+  return next_pcs;
+}
+
+/* Implement the "skip_solib_resolver" gdbarch method.
+
+   See glibc_skip_solib_resolver for details.  */
+
+static CORE_ADDR
+arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  /* For uClibc 0.9.26+.
+
+     An unresolved PLT entry points to "__dl_linux_resolve", which calls
+     "_dl_linux_resolver" to do the resolving and then eventually jumps to
+     the function.
+
+     So we look for the symbol `_dl_linux_resolver', and if we are there,
+     gdb sets a breakpoint at the return address, and continues.  */
+  struct bound_minimal_symbol resolver
+    = lookup_minimal_symbol ("_dl_linux_resolver", NULL, NULL);
+
+  if (arc_debug)
+    {
+      if (resolver.minsym != nullptr)
+	{
+	  CORE_ADDR res_addr = BMSYMBOL_VALUE_ADDRESS (resolver);
+	  debug_printf ("arc-linux: skip_solib_resolver (): "
+			"pc = %s, resolver at %s\n",
+			print_core_address (gdbarch, pc),
+			print_core_address (gdbarch, res_addr));
+	}
+      else
+	{
+	  debug_printf ("arc-linux: skip_solib_resolver (): "
+			"pc = %s, no resolver found\n",
+			print_core_address (gdbarch, pc));
+	}
+    }
+
+  if (resolver.minsym != nullptr && BMSYMBOL_VALUE_ADDRESS (resolver) == pc)
+    {
+      /* Find the return address.  */
+      return frame_unwind_caller_pc (get_current_frame ());
+    }
+  else
+    {
+      /* No breakpoint required.  */
+      return 0;
+    }
+}
+
+/* Initialization specific to Linux environment.  */
+
+static void
+arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (arc_debug)
+    debug_printf ("arc-linux: GNU/Linux OS/ABI initialization.\n");
+
+  /* If we are using Linux, we have in uClibc
+     (libc/sysdeps/linux/arc/bits/setjmp.h):
+
+     typedef int __jmp_buf[13+1+1+1];    //r13-r25, fp, sp, blink
+
+     Where "blink" is a stored PC of a caller function.
+   */
+  tdep->jb_pc = 15;
+
+  linux_init_abi (info, gdbarch);
+
+  /* Set up target dependent GDB architecture entries.  */
+  set_gdbarch_cannot_fetch_register (gdbarch, arc_linux_cannot_fetch_register);
+  set_gdbarch_cannot_store_register (gdbarch, arc_linux_cannot_store_register);
+  set_gdbarch_breakpoint_kind_from_pc (gdbarch,
+				       arc_linux_breakpoint_kind_from_pc);
+  set_gdbarch_sw_breakpoint_from_kind (gdbarch,
+				       arc_linux_sw_breakpoint_from_kind);
+  set_gdbarch_fetch_tls_load_module_address (gdbarch,
+					     svr4_fetch_objfile_link_map);
+  set_gdbarch_software_single_step (gdbarch, arc_linux_software_single_step);
+  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+  set_gdbarch_skip_solib_resolver (gdbarch, arc_linux_skip_solib_resolver);
+
+  /* GNU/Linux uses SVR4-style shared libraries, with 32-bit ints, longs
+     and pointers (ILP32).  */
+  set_solib_svr4_fetch_link_map_offsets (gdbarch,
+					 svr4_ilp32_fetch_link_map_offsets);
+}
+
+/* Suppress warning from -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_arc_linux_tdep;
+
+void
+_initialize_arc_linux_tdep ()
+{
+  gdbarch_register_osabi (bfd_arch_arc, 0, GDB_OSABI_LINUX,
+			  arc_linux_init_osabi);
+}
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 8b4e2857fb9..6f544bff78d 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -612,8 +612,7 @@ arc_write_pc (struct regcache *regcache, CORE_ADDR new_pc)
   regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
 				 &status32);
 
-  /* Mask for DE bit is 0x40.  */
-  if (status32 & 0x40)
+  if ((status32 & ARC_STATUS32_DE_MASK) != 0)
     {
       if (arc_debug)
 	{
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index e752348a262..6331d29f402 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -100,6 +100,11 @@ enum arc_regnum
    Longer registers are represented as pairs of 32-bit registers.  */
 #define ARC_REGISTER_SIZE  4
 
+/* STATUS32 register: hardware loops disabled bit.  */
+#define ARC_STATUS32_L_MASK (1 << 12)
+/* STATUS32 register: current instruction is a delay slot.  */
+#define ARC_STATUS32_DE_MASK (1 << 6)
+
 #define arc_print(fmt, args...) fprintf_unfiltered (gdb_stdlog, fmt, ##args)
 
 extern int arc_debug;
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 8a26bdeb873..a3e11c4b9b8 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -157,6 +157,11 @@ arc*-*-elf32)
 	gdb_target_obs="arc-newlib-tdep.o"
 	;;
 
+arc*-*-linux*)
+	# Target: ARC machine running Linux
+	gdb_target_obs="arc-linux-tdep.o linux-tdep.o solib-svr4.o"
+	;;
+
 arm*-wince-pe | arm*-*-mingw32ce*)
 	# Target: ARM based machine running Windows CE (win32)
 	gdb_target_obs="arm-wince-tdep.o windows-tdep.o"
-- 
2.28.0


^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PUSHED 3/4] arc: Add hardware loop detection
  2020-08-25 15:47   ` [PUSHED 3/4] arc: Add hardware loop detection Shahab Vahedi
@ 2020-08-25 15:58     ` Eli Zaretskii
  0 siblings, 0 replies; 86+ messages in thread
From: Eli Zaretskii @ 2020-08-25 15:58 UTC (permalink / raw)
  To: Shahab Vahedi; +Cc: gdb-patches, shahab, simark, tom, anton.kolesov, fbedard

> From: Shahab Vahedi <shahab.vahedi@gmail.com>
> Cc: Shahab Vahedi <shahab.vahedi@gmail.com>,
> 	Shahab Vahedi <shahab@synopsys.com>,
> 	Simon Marchi <simark@simark.ca>,
> 	Tom Tromey <tom@tromey.com>,
> 	Eli Zaretskii <eliz@gnu.org>,
> 	Anton Kolesov <anton.kolesov@synopsys.com>,
> 	Francois Bedard <fbedard@synopsys.com>
> Date: Tue, 25 Aug 2020 17:47:03 +0200
> 
> diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
> index 6a81351282f..badf7ae10b5 100644
> --- a/gdb/doc/ChangeLog
> +++ b/gdb/doc/ChangeLog
> @@ -1,3 +1,7 @@
> +2020-08-25  Shahab Vahedi  <shahab@synopsys.com>
> +
> +	* gdb.texinfo (Synopsys ARC): Document LP_START, LP_END and BTA.
> +
>  2020-08-25  Shahab Vahedi  <shahab@synopsys.com>
>  
>  	* gdb.texinfo (Synopsys ARC): Update the documentation for ARC
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index a4f5b787503..77c5d895053 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -45298,8 +45298,15 @@ Extension core registers @samp{r32} through @samp{r59} are optional and their
>  existence depends on the configuration.  When debugging GNU/Linux applications,
>  i.e.@: user space debugging, these core registers are not available.
>  
> -The @samp{org.gnu.gdb.arc.aux} feature is required for all ARC targets.  It
> -should at least contain @samp{pc} and @samp{status32} registers.
> +The @samp{org.gnu.gdb.arc.aux} feature is required for all ARC targets.  Here
> +is the list of registers pertinent to this feature:
> +
> +@itemize @minus
> +@item
> +mandatory: @samp{pc} and @samp{status32}.
> +@item
> +optional: @samp{lp_start}, @samp{lp_end}, and @samp{bta}.
> +@end itemize

This part is okay, thanks.

^ permalink raw reply	[flat|nested] 86+ messages in thread

* Re: [PUSHED 1/4] arc: Add ARCv2 XML target along with refactoring
  2020-08-25 15:47   ` [PUSHED 1/4] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
@ 2020-08-25 16:00     ` Eli Zaretskii
  0 siblings, 0 replies; 86+ messages in thread
From: Eli Zaretskii @ 2020-08-25 16:00 UTC (permalink / raw)
  To: Shahab Vahedi; +Cc: gdb-patches, shahab, simark, tom, anton.kolesov, fbedard

> From: Shahab Vahedi <shahab.vahedi@gmail.com>
> Cc: Shahab Vahedi <shahab.vahedi@gmail.com>,
> 	Shahab Vahedi <shahab@synopsys.com>,
> 	Simon Marchi <simark@simark.ca>,
> 	Tom Tromey <tom@tromey.com>,
> 	Eli Zaretskii <eliz@gnu.org>,
> 	Anton Kolesov <anton.kolesov@synopsys.com>,
> 	Francois Bedard <fbedard@synopsys.com>
> Date: Tue, 25 Aug 2020 17:47:01 +0200
> 
> gdb/ChangeLog:
> 
> 	* arch/arc.h
> 	  (arc_gdbarch_features): New class to stir the selection of target XML.
> 	  (arc_create_target_description): Use FEATURES to choose XML target.
> 	  (arc_lookup_target_description): Use arc_create_target_description
> 	  to create _new_ target descriptions or return the already created
> 	  ones if the FEATURES is the same.
> 	* arch/arc.c: Implementation of prototypes described above.
> 	* gdb/arc-tdep.h (arc_regnum enum): Add more registers.
> 	  (arc_gdbarch_features_init): Initialize the FEATURES struct.
> 	* arc-tdep.c (*_feature_name): Make feature names consistent.
> 	  (arc_register_feature): A new struct to hold information about
> 	  registers of a particular target/feature.
> 	  (arc_check_tdesc_feature): Check if XML provides registers in
> 	  compliance with ARC_REGISTER_FEATURE structs.
> 	  (arc_update_acc_reg_names): Add aliases for r58 and r59.
> 	  (determine_*_reg_feature_set): Which feature name to look for.
> 	  (arc_gdbarch_features_init): Given MACH and ABFD, initialize FEATURES.
> 	  (mach_type_to_arc_isa): Convert from a set of binutils machine types
> 	  to expected ISA enums to be used in arc_gdbarch_features structs.
> 	* features/Makefile (FEATURE_XMLFILES): Add new files.
> 	* gdb/features/arc/v1-aux.c: New file.
> 	* gdb/features/arc/v1-aux.xml: Likewise.
> 	* gdb/features/arc/v1-core.c: Likewise.
> 	* gdb/features/arc/v1-core.xml: Likewise.
> 	* gdb/features/arc/v2-aux.c: Likewise.
> 	* gdb/features/arc/v2-aux.xml: Likewise.
> 	* gdb/features/arc/v2-core.c: Likewise.
> 	* gdb/features/arc/v2-core.xml: Likewise.
> 	* NEWS (Changes since GDB 9): Announce obsolence of old feature names.
> 
> gdb/doc/ChangeLog:
> 
> 	* gdb.texinfo (Synopsys ARC): Update the documentation for ARC
> 	Features.
> 
> gdb/testsuite/ChangeLog:
> 
> 	* gdb.arch/arc-tdesc-cpu.xml: Use new feature names.

Thanks, the documentation parts are OK.

^ permalink raw reply	[flat|nested] 86+ messages in thread

end of thread, other threads:[~2020-08-25 16:00 UTC | newest]

Thread overview: 86+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-26 12:52 [PATCH 0/4] arc: Add GNU/Linux support Shahab Vahedi
2020-03-26 12:52 ` [PATCH 1/4] arc: Add XML target features for Linux targets Shahab Vahedi
2020-04-24 13:46   ` Tom Tromey
2020-03-26 12:52 ` [PATCH 2/4] arc: Recognize registers available on " Shahab Vahedi
2020-04-24 13:50   ` Tom Tromey
2020-03-26 12:52 ` [PATCH 3/4] arc: Add GNU/Linux support for ARC Shahab Vahedi
2020-04-24 14:00   ` Tom Tromey
2020-03-26 12:52 ` [PATCH 4/4] arc: Add arc-*-linux regformats Shahab Vahedi
2020-04-24 14:01   ` Tom Tromey
2020-04-06  9:13 ` [PING][PATCH 0/4] arc: Add GNU/Linux support Shahab Vahedi
2020-04-20 16:51 ` [PING^2][PATCH " Shahab Vahedi
2020-04-28 16:04 ` [PATCH v2 " Shahab Vahedi
2020-04-28 16:04   ` [PATCH v2 1/4] arc: Add XML target features for Linux targets Shahab Vahedi
2020-05-14 14:49     ` Simon Marchi
2020-04-28 16:04   ` [PATCH v2 2/4] arc: Recognize registers available on " Shahab Vahedi
2020-04-28 16:56     ` Eli Zaretskii
2020-05-14 15:01     ` Simon Marchi
2020-06-17 15:46       ` Shahab Vahedi
2020-07-13 15:48         ` Simon Marchi
2020-07-14  9:05           ` Shahab Vahedi
2020-04-28 16:04   ` [PATCH v2 3/4] arc: Add GNU/Linux support for ARC Shahab Vahedi
2020-05-14 15:09     ` Simon Marchi
2020-06-15 23:13       ` Shahab Vahedi
2020-06-16  0:58         ` Simon Marchi
2020-04-28 16:04   ` [PATCH v2 4/4] arc: Add arc-*-linux regformats Shahab Vahedi
2020-05-14 15:12     ` Simon Marchi
2020-06-15 23:37       ` Shahab Vahedi
2020-06-16  2:08         ` Simon Marchi
2020-05-14 11:43   ` [PATCH v2 0/4] arc: Add GNU/Linux support Shahab Vahedi
2020-07-13 15:45   ` [PATCH v3 0/3] " Shahab Vahedi
2020-07-13 15:45     ` [PATCH v3 1/3] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
2020-07-15  2:52       ` Simon Marchi
2020-07-15 20:35         ` Shahab Vahedi
2020-07-15 21:23           ` Christian Biesinger
2020-07-16  1:59             ` Simon Marchi
2020-07-16 13:28           ` Simon Marchi
2020-07-22 13:36             ` Shahab Vahedi
2020-07-22 13:49               ` Simon Marchi
2020-07-22 14:33                 ` Shahab Vahedi
2020-07-22 14:54                   ` Simon Marchi
2020-07-13 15:45     ` [PATCH v3 2/3] arc: Add hardware loop detection Shahab Vahedi
2020-07-15  2:55       ` Simon Marchi
2020-07-13 15:45     ` [PATCH v3 3/3] arc: Add GNU/Linux support for ARC Shahab Vahedi
2020-07-15  3:03       ` Simon Marchi
2020-07-23 19:35     ` [PATCH v4 0/3] arc: Add GNU/Linux support Shahab Vahedi
2020-07-23 19:35       ` [PATCH v4 1/3] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
2020-07-30 23:34         ` Simon Marchi
2020-07-23 19:35       ` [PATCH v4 2/3] arc: Add hardware loop detection Shahab Vahedi
2020-08-01 14:53         ` Simon Marchi
2020-07-23 19:35       ` [PATCH v4 3/3] arc: Add GNU/Linux support for ARC Shahab Vahedi
2020-08-01 15:01         ` Simon Marchi
2020-08-01 23:31       ` [PATCH v4 0/3] arc: Add GNU/Linux support Simon Marchi
2020-08-04  7:59         ` Shahab Vahedi
2020-08-04 12:42           ` Simon Marchi
2020-08-04  8:57 ` [PATCH v5 0/4] " Shahab Vahedi
2020-08-04  8:57   ` [PATCH v5 1/4] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
2020-08-04 13:08     ` Simon Marchi
2020-08-04 13:18       ` Shahab Vahedi
2020-08-04 13:20         ` Simon Marchi
2020-08-04 14:12           ` Shahab Vahedi
2020-08-04  8:57   ` [PATCH v5 2/4] arc: Add inclusion of "gdbarch.h" in "arc-tdep.h" Shahab Vahedi
2020-08-04  8:57   ` [PATCH v5 3/4] arc: Add hardware loop detection Shahab Vahedi
2020-08-04 14:28     ` Eli Zaretskii
2020-08-04 16:17       ` Shahab Vahedi
2020-08-04 16:42         ` Eli Zaretskii
2020-08-04 18:15           ` Shahab Vahedi
2020-08-04  8:57   ` [PATCH v5 4/4] arc: Add GNU/Linux support for ARC Shahab Vahedi
2020-08-04 12:49   ` [PATCH v5 0/4] arc: Add GNU/Linux support Simon Marchi
2020-08-04 13:05     ` Shahab Vahedi
2020-08-05 11:09 ` [PATCH v6 " Shahab Vahedi
2020-08-05 11:09   ` [PATCH v6 1/4] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
2020-08-05 14:31     ` Eli Zaretskii
2020-08-21 16:16     ` Simon Marchi
2020-08-24 20:14       ` Shahab Vahedi
2020-08-05 11:09   ` [PATCH v6 2/4] arc: Add inclusion of "gdbarch.h" in "arc-tdep.h" Shahab Vahedi
2020-08-05 11:09   ` [PATCH v6 3/4] arc: Add hardware loop detection Shahab Vahedi
2020-08-05 11:09   ` [PATCH v6 4/4] arc: Add GNU/Linux support for ARC Shahab Vahedi
2020-08-17  8:07   ` [PATCH v6 0/4] arc: Add GNU/Linux support Shahab Vahedi
2020-08-17 14:12     ` Eli Zaretskii
2020-08-25 15:47 ` [PUSHED " Shahab Vahedi
2020-08-25 15:47   ` [PUSHED 1/4] arc: Add ARCv2 XML target along with refactoring Shahab Vahedi
2020-08-25 16:00     ` Eli Zaretskii
2020-08-25 15:47   ` [PUSHED 2/4] arc: Add inclusion of "gdbarch.h" in "arc-tdep.h" Shahab Vahedi
2020-08-25 15:47   ` [PUSHED 3/4] arc: Add hardware loop detection Shahab Vahedi
2020-08-25 15:58     ` Eli Zaretskii
2020-08-25 15:47   ` [PUSHED 4/4] arc: Add GNU/Linux support for ARC Shahab Vahedi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).