[gdb/testsuite] Add target board cc-with-gnu-debuglink.exp
[deliverable/binutils-gdb.git] / gdb / arc-tdep.c
index 286a289a06c7a600e51f17024a4c8743193a921d..ece802545c040ef1b49dd7433695e2ddb56de097 100644 (file)
@@ -1,6 +1,6 @@
-/* Target dependent code for ARC arhitecture, for GDB.
+/* Target dependent code for ARC architecture, for GDB.
 
-   Copyright 2005-2018 Free Software Foundation, Inc.
+   Copyright 2005-2021 Free Software Foundation, Inc.
    Contributed by Synopsys Inc.
 
    This file is part of GDB.
 /* GDB header files.  */
 #include "defs.h"
 #include "arch-utils.h"
+#include "elf-bfd.h"
 #include "disasm.h"
-#include "dwarf2-frame.h"
+#include "dwarf2/frame.h"
 #include "frame-base.h"
 #include "frame-unwind.h"
 #include "gdbcore.h"
+#include "reggroups.h"
 #include "gdbcmd.h"
 #include "objfiles.h"
+#include "osabi.h"
 #include "prologue-value.h"
+#include "target-descriptions.h"
 #include "trad-frame.h"
 
 /* ARC header files.  */
 #include "opcode/arc.h"
 #include "opcodes/arc-dis.h"
 #include "arc-tdep.h"
+#include "arch/arc.h"
 
 /* Standard headers.  */
 #include <algorithm>
-
-/* Default target descriptions.  */
-#include "features/arc-v2.c"
-#include "features/arc-arcompact.c"
+#include <sstream>
 
 /* The frame unwind cache for ARC.  */
 
@@ -81,68 +83,219 @@ struct arc_frame_cache
   /* Store addresses for registers saved in prologue.  During prologue analysis
      GDB stores offsets relatively to "old SP", then after old SP is evaluated,
      offsets are replaced with absolute addresses.  */
-  struct trad_frame_saved_reg *saved_regs;
+  trad_frame_saved_reg *saved_regs;
 };
 
 /* Global debug flag.  */
 
-int arc_debug;
+bool arc_debug;
 
 /* List of "maintenance print arc" commands.  */
 
 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 }
+  }
+};
+
+/* The common auxiliary registers feature set.  The REGNUM field
+   must match the ARC_REGNUM enum in arc-tdep.h.  */
+
+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;
@@ -208,7 +361,7 @@ arc_insn_get_operand_value_signed (const struct arc_instruction &insn,
 
 /* Get register with base address of memory operation.  */
 
-int
+static int
 arc_insn_get_memory_base_reg (const struct arc_instruction &insn)
 {
   /* POP_S and PUSH_S have SP as an implicit argument in a disassembler.  */
@@ -227,7 +380,7 @@ arc_insn_get_memory_base_reg (const struct arc_instruction &insn)
 
 /* Get offset of a memory operation INSN.  */
 
-CORE_ADDR
+static CORE_ADDR
 arc_insn_get_memory_offset (const struct arc_instruction &insn)
 {
   /* POP_S and PUSH_S have offset as an implicit argument in a
@@ -334,7 +487,7 @@ arc_insn_get_branch_target (const struct arc_instruction &insn)
 
 /* Dump INSN into gdb_stdlog.  */
 
-void
+static void
 arc_insn_dump (const struct arc_instruction &insn)
 {
   struct gdbarch *gdbarch = target_gdbarch ();
@@ -449,9 +602,8 @@ arc_write_pc (struct regcache *regcache, CORE_ADDR new_pc)
 {
   struct gdbarch *gdbarch = regcache->arch ();
 
-  if (arc_debug)
-    debug_printf ("arc: Writing PC, new value=%s\n",
-                 paddress (gdbarch, new_pc));
+  arc_debug_printf ("Writing PC, new value=%s",
+                   paddress (gdbarch, new_pc));
 
   regcache_cooked_write_unsigned (regcache, gdbarch_pc_regnum (gdbarch),
                                  new_pc);
@@ -460,16 +612,12 @@ 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)
-       {
-         debug_printf ("arc: Changing PC while in delay slot.  Will "
+      arc_debug_printf ("Changing PC while in delay slot.  Will "
                        "reset STATUS32.DE bit to zero.  Value of STATUS32 "
-                       "register is 0x%s\n",
+                       "register is 0x%s",
                        phex (status32, ARC_REGISTER_SIZE));
-       }
 
       /* Reset bit and write to the cache.  */
       status32 &= ~0x40;
@@ -509,19 +657,6 @@ arc_virtual_frame_pointer (struct gdbarch *gdbarch, CORE_ADDR pc,
   *offset_ptr = 0;
 }
 
-/* Implement the "dummy_id" gdbarch method.
-
-   Tear down a dummy frame created by arc_push_dummy_call ().  This data has
-   to be constructed manually from the data in our hand.  The stack pointer
-   and program counter can be obtained from the frame info.  */
-
-static struct frame_id
-arc_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
-  return frame_id_build (get_frame_sp (this_frame),
-                        get_frame_pc (this_frame));
-}
-
 /* Implement the "push_dummy_call" gdbarch method.
 
    Stack Frame Layout
@@ -537,35 +672,35 @@ arc_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
    The stack grows downward, so SP points below FP in memory; SP always
    points to the last used word on the stack, not the first one.
 
-                      |                       |   |
-                      |      arg word N       |   | caller's
-                      |           :           |   | frame
-                      |      arg word 10      |   |
-                      |      arg word 9       |   |
-          old SP ---> +-----------------------+ --+
-                      |                       |   |
-                      |      callee-saved     |   |
-                      |       registers       |   |
-                      |  including fp, blink  |   |
-                      |                       |   | callee's
-          new FP ---> +-----------------------+   | frame
-                      |                       |   |
-                      |         local         |   |
-                      |       variables       |   |
-                      |                       |   |
-                      |       register        |   |
-                      |      spill area       |   |
-                      |                       |   |
-                      |     outgoing args     |   |
-                      |                       |   |
-          new SP ---> +-----------------------+ --+
-                      |                       |
-                      |         unused        |
-                      |                       |
-                                  |
-                                  |
-                                  V
-                              downwards
+                     |                       |   |
+                     |      arg word N       |   | caller's
+                     |           :           |   | frame
+                     |      arg word 10      |   |
+                     |      arg word 9       |   |
+         old SP ---> +-----------------------+ --+
+                     |                       |   |
+                     |      callee-saved     |   |
+                     |       registers       |   |
+                     |  including fp, blink  |   |
+                     |                       |   | callee's
+         new FP ---> +-----------------------+   | frame
+                     |                       |   |
+                     |         local         |   |
+                     |       variables       |   |
+                     |                       |   |
+                     |       register        |   |
+                     |      spill area       |   |
+                     |                       |   |
+                     |     outgoing args     |   |
+                     |                       |   |
+         new SP ---> +-----------------------+ --+
+                     |                       |
+                     |         unused        |
+                     |                       |
+                                 |
+                                 |
+                                 V
+                             downwards
 
    The list of arguments to be passed to a function is considered to be a
    sequence of _N_ words (as though all the parameters were stored in order in
@@ -592,11 +727,11 @@ arc_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
 static CORE_ADDR
 arc_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                     struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
-                    struct value **args, CORE_ADDR sp, int struct_return,
+                    struct value **args, CORE_ADDR sp,
+                    function_call_return_method return_method,
                     CORE_ADDR struct_addr)
 {
-  if (arc_debug)
-    debug_printf ("arc: push_dummy_call (nargs = %d)\n", nargs);
+  arc_debug_printf ("nargs = %d", nargs);
 
   int arg_reg = ARC_FIRST_ARG_REGNUM;
 
@@ -607,14 +742,13 @@ arc_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
      value return?  If so, struct_addr is the address of the reserved space for
      the return structure to be written on the stack, and that address is
      passed to that function as a hidden first argument.  */
-  if (struct_return)
+  if (return_method == return_method_struct)
     {
       /* Pass the return address in the first argument register.  */
       regcache_cooked_write_unsigned (regcache, arg_reg, struct_addr);
 
-      if (arc_debug)
-       debug_printf ("arc: struct return address %s passed in R%d",
-                     print_core_address (gdbarch, struct_addr), arg_reg);
+      arc_debug_printf ("struct return address %s passed in R%d",
+                       print_core_address (gdbarch, struct_addr), arg_reg);
 
       arg_reg++;
     }
@@ -632,8 +766,7 @@ arc_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
          total_space += space;
 
-         if (arc_debug)
-           debug_printf ("arc: arg %d: %u bytes -> %u\n", i, len, space);
+         arc_debug_printf ("arg %d: %u bytes -> %u", i, len, space);
        }
 
       /* Allocate a buffer to hold a memory image of the arguments.  */
@@ -647,9 +780,8 @@ arc_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
          unsigned int space = align_up (len, 4);
 
          memcpy (data, value_contents (args[i]), (size_t) len);
-         if (arc_debug)
-           debug_printf ("arc: copying arg %d, val 0x%08x, len %d to mem\n",
-                         i, *((int *) value_contents (args[i])), len);
+         arc_debug_printf ("copying arg %d, val 0x%08x, len %d to mem",
+                           i, *((int *) value_contents (args[i])), len);
 
          data += space;
        }
@@ -658,13 +790,12 @@ arc_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
       data = memory_image;
       while (arg_reg <= ARC_LAST_ARG_REGNUM)
        {
-         if (arc_debug)
-           debug_printf ("arc: passing 0x%02x%02x%02x%02x in register R%d\n",
-                         data[0], data[1], data[2], data[3], arg_reg);
+         arc_debug_printf ("passing 0x%02x%02x%02x%02x in register R%d",
+                           data[0], data[1], data[2], data[3], arg_reg);
 
          /* Note we don't use write_unsigned here, since that would convert
             the byte order, but we are already in the correct byte order.  */
-         regcache_cooked_write (regcache, arg_reg, data);
+         regcache->cooked_write (arg_reg, data);
 
          data += ARC_REGISTER_SIZE;
          total_space -= ARC_REGISTER_SIZE;
@@ -680,8 +811,7 @@ arc_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
         operation).  */
       if (total_space > 0)
        {
-         if (arc_debug)
-           debug_printf ("arc: passing %d bytes on stack\n", total_space);
+         arc_debug_printf ("passing %d bytes on stack\n", total_space);
 
          sp -= total_space;
          write_memory (sp, data, (int) total_space);
@@ -777,8 +907,7 @@ arc_extract_return_value (struct gdbarch *gdbarch, struct type *type,
 {
   unsigned int len = TYPE_LENGTH (type);
 
-  if (arc_debug)
-    debug_printf ("arc: extract_return_value\n");
+  arc_debug_printf ("called");
 
   if (len <= ARC_REGISTER_SIZE)
     {
@@ -789,8 +918,7 @@ arc_extract_return_value (struct gdbarch *gdbarch, struct type *type,
       store_unsigned_integer (valbuf, (int) len,
                              gdbarch_byte_order (gdbarch), val);
 
-      if (arc_debug)
-       debug_printf ("arc: returning 0x%s\n", phex (val, ARC_REGISTER_SIZE));
+      arc_debug_printf ("returning 0x%s", phex (val, ARC_REGISTER_SIZE));
     }
   else if (len <= ARC_REGISTER_SIZE * 2)
     {
@@ -806,10 +934,9 @@ arc_extract_return_value (struct gdbarch *gdbarch, struct type *type,
                              (int) len - ARC_REGISTER_SIZE,
                              gdbarch_byte_order (gdbarch), high);
 
-      if (arc_debug)
-       debug_printf ("arc: returning 0x%s%s\n",
-                     phex (high, ARC_REGISTER_SIZE),
-                     phex (low, ARC_REGISTER_SIZE));
+      arc_debug_printf ("returning 0x%s%s",
+                       phex (high, ARC_REGISTER_SIZE),
+                       phex (low, ARC_REGISTER_SIZE));
     }
   else
     error (_("arc: extract_return_value: type length %u too large"), len);
@@ -831,8 +958,7 @@ arc_store_return_value (struct gdbarch *gdbarch, struct type *type,
 {
   unsigned int len = TYPE_LENGTH (type);
 
-  if (arc_debug)
-    debug_printf ("arc: store_return_value\n");
+  arc_debug_printf ("called");
 
   if (len <= ARC_REGISTER_SIZE)
     {
@@ -843,8 +969,7 @@ arc_store_return_value (struct gdbarch *gdbarch, struct type *type,
                                      gdbarch_byte_order (gdbarch));
       regcache_cooked_write_unsigned (regcache, ARC_R0_REGNUM, val);
 
-      if (arc_debug)
-       debug_printf ("arc: storing 0x%s\n", phex (val, ARC_REGISTER_SIZE));
+      arc_debug_printf ("storing 0x%s", phex (val, ARC_REGISTER_SIZE));
     }
   else if (len <= ARC_REGISTER_SIZE * 2)
     {
@@ -860,10 +985,9 @@ arc_store_return_value (struct gdbarch *gdbarch, struct type *type,
       regcache_cooked_write_unsigned (regcache, ARC_R0_REGNUM, low);
       regcache_cooked_write_unsigned (regcache, ARC_R1_REGNUM, high);
 
-      if (arc_debug)
-       debug_printf ("arc: storing 0x%s%s\n",
-                     phex (high, ARC_REGISTER_SIZE),
-                     phex (low, ARC_REGISTER_SIZE));
+      arc_debug_printf ("storing 0x%s%s",
+                       phex (high, ARC_REGISTER_SIZE),
+                       phex (low, ARC_REGISTER_SIZE));
     }
   else
     error (_("arc_store_return_value: type length too large."));
@@ -874,8 +998,7 @@ arc_store_return_value (struct gdbarch *gdbarch, struct type *type,
 static int
 arc_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
 {
-  if (arc_debug)
-    debug_printf ("arc: get_longjmp_target\n");
+  arc_debug_printf ("called");
 
   struct gdbarch *gdbarch = get_frame_arch (frame);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
@@ -903,14 +1026,13 @@ arc_return_value (struct gdbarch *gdbarch, struct value *function,
      function passes a hidden first parameter to the callee (in R0).  That
      parameter is the address at which the value being returned should be
      stored.  Otherwise, the result is returned in registers.  */
-  int is_struct_return = (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
-                         || TYPE_CODE (valtype) == TYPE_CODE_UNION
+  int is_struct_return = (valtype->code () == TYPE_CODE_STRUCT
+                         || valtype->code () == TYPE_CODE_UNION
                          || TYPE_LENGTH (valtype) > 2 * ARC_REGISTER_SIZE);
 
-  if (arc_debug)
-    debug_printf ("arc: return_value (readbuf = %s, writebuf = %s)\n",
-                 host_address_to_string (readbuf),
-                 host_address_to_string (writebuf));
+  arc_debug_printf ("readbuf = %s, writebuf = %s",
+                   host_address_to_string (readbuf),
+                   host_address_to_string (writebuf));
 
   if (writebuf != NULL)
     {
@@ -981,7 +1103,7 @@ arc_is_in_prologue (struct gdbarch *gdbarch, const struct arc_instruction &insn,
   /* Store of some register.  May or may not update base address register.  */
   if (insn.insn_class == STORE || insn.insn_class == PUSH)
     {
-      /* There is definetely at least one operand - register/value being
+      /* There is definitely at least one operand - register/value being
         stored.  */
       gdb_assert (insn.operands_count > 0);
 
@@ -1215,7 +1337,7 @@ arc_disassemble_info (struct gdbarch *gdbarch)
    If CACHE is not NULL, then it will be filled with information about saved
    registers.
 
-   There are several variations of prologue which GDB may encouter.  "Full"
+   There are several variations of prologue which GDB may encounter.  "Full"
    prologue looks like this:
 
        sub     sp,sp,<imm>   ; Space for variadic arguments.
@@ -1236,7 +1358,7 @@ arc_disassemble_info (struct gdbarch *gdbarch)
     store, that doesn't update SP.  Like this:
 
 
-       sub     sp,sp,8         ; Create space for calee-saved registers.
+       sub     sp,sp,8         ; Create space for callee-saved registers.
        st      r13,[sp,4]      ; Store callee saved registers (up to R26/GP).
        st      r14,[sp,0]
 
@@ -1261,10 +1383,9 @@ static CORE_ADDR
 arc_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR entrypoint,
                      const CORE_ADDR limit_pc, struct arc_frame_cache *cache)
 {
-  if (arc_debug)
-    debug_printf ("arc: analyze_prologue (entrypoint=%s, limit_pc=%s)\n",
-                 paddress (gdbarch, entrypoint),
-                 paddress (gdbarch, limit_pc));
+  arc_debug_printf ("entrypoint=%s, limit_pc=%s",
+                   paddress (gdbarch, entrypoint),
+                   paddress (gdbarch, limit_pc));
 
   /* Prologue values.  Only core registers can be stored.  */
   pv_t regs[ARC_LAST_CORE_REGNUM + 1];
@@ -1282,7 +1403,7 @@ arc_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR entrypoint,
       arc_insn_decode (current_prologue_end, &di, arc_delayed_print_insn,
                       &insn);
 
-      if (arc_debug >= 2)
+      if (arc_debug)
        arc_insn_dump (insn);
 
       /* If this instruction is in the prologue, fields in the cache will be
@@ -1290,9 +1411,8 @@ arc_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR entrypoint,
       if (!arc_is_in_prologue (gdbarch, insn, regs, &stack))
        {
          /* Found an instruction that is not in the prologue.  */
-         if (arc_debug)
-           debug_printf ("arc: End of prologue reached at address %s\n",
-                         paddress (gdbarch, insn.address));
+         arc_debug_printf ("End of prologue reached at address %s",
+                           paddress (gdbarch, insn.address));
          break;
        }
 
@@ -1318,7 +1438,7 @@ arc_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR entrypoint,
        {
          CORE_ADDR offset;
          if (stack.find_reg (gdbarch, i, &offset))
-           cache->saved_regs[i].addr = offset;
+           cache->saved_regs[i].set_addr (offset);
        }
     }
 
@@ -1353,8 +1473,7 @@ const static int MAX_PROLOGUE_LENGTH
 static CORE_ADDR
 arc_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
-  if (arc_debug)
-    debug_printf ("arc: skip_prologue\n");
+  arc_debug_printf ("pc = %s", paddress (gdbarch, pc));
 
   CORE_ADDR func_addr;
   const char *func_name;
@@ -1403,7 +1522,7 @@ arc_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 int
 arc_delayed_print_insn (bfd_vma addr, struct disassemble_info *info)
 {
-  /* Standard BFD "machine number" field allows libocodes disassembler to
+  /* Standard BFD "machine number" field allows libopcodes disassembler to
      distinguish ARC 600, 700 and v2 cores, however v2 encompasses both ARC EM
      and HS, which have some difference between.  There are two ways to specify
      what is the target core:
@@ -1495,6 +1614,7 @@ arc_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 static const gdb_byte *
 arc_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
 {
+  gdb_assert (kind == 2 || kind == 4);
   *size = kind;
 
   if (kind == sizeof (arc_brk_le))
@@ -1511,34 +1631,6 @@ arc_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
     }
 }
 
-/* Implement the "unwind_pc" gdbarch method.  */
-
-static CORE_ADDR
-arc_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  int pc_regnum = gdbarch_pc_regnum (gdbarch);
-  CORE_ADDR pc = frame_unwind_register_unsigned (next_frame, pc_regnum);
-
-  if (arc_debug)
-    debug_printf ("arc: unwind PC: %s\n", paddress (gdbarch, pc));
-
-  return pc;
-}
-
-/* Implement the "unwind_sp" gdbarch method.  */
-
-static CORE_ADDR
-arc_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  int sp_regnum = gdbarch_sp_regnum (gdbarch);
-  CORE_ADDR sp = frame_unwind_register_unsigned (next_frame, sp_regnum);
-
-  if (arc_debug)
-    debug_printf ("arc: unwind SP: %s\n", paddress (gdbarch, sp));
-
-  return sp;
-}
-
 /* Implement the "frame_align" gdbarch method.  */
 
 static CORE_ADDR
@@ -1553,19 +1645,19 @@ static void
 arc_print_frame_cache (struct gdbarch *gdbarch, const char *message,
                       struct arc_frame_cache *cache, int addresses_known)
 {
-  debug_printf ("arc: frame_info %s\n", message);
-  debug_printf ("arc: prev_sp = %s\n", paddress (gdbarch, cache->prev_sp));
-  debug_printf ("arc: frame_base_reg = %i\n", cache->frame_base_reg);
-  debug_printf ("arc: frame_base_offset = %s\n",
-               plongest (cache->frame_base_offset));
+  arc_debug_printf ("frame_info %s", message);
+  arc_debug_printf ("prev_sp = %s", paddress (gdbarch, cache->prev_sp));
+  arc_debug_printf ("frame_base_reg = %i", cache->frame_base_reg);
+  arc_debug_printf ("frame_base_offset = %s",
+                   plongest (cache->frame_base_offset));
 
   for (int i = 0; i <= ARC_BLINK_REGNUM; i++)
     {
-      if (trad_frame_addr_p (cache->saved_regs, i))
-       debug_printf ("arc: saved register %s at %s %s\n",
-                     gdbarch_register_name (gdbarch, i),
-                     (addresses_known) ? "address" : "offset",
-                     paddress (gdbarch, cache->saved_regs[i].addr));
+      if (cache->saved_regs[i].is_addr ())
+       arc_debug_printf ("saved register %s at %s %s",
+                         gdbarch_register_name (gdbarch, i),
+                         (addresses_known) ? "address" : "offset",
+                             paddress (gdbarch, cache->saved_regs[i].addr ()));
     }
 }
 
@@ -1574,8 +1666,7 @@ arc_print_frame_cache (struct gdbarch *gdbarch, const char *message,
 static struct arc_frame_cache *
 arc_make_frame_cache (struct frame_info *this_frame)
 {
-  if (arc_debug)
-    debug_printf ("arc: frame_cache\n");
+  arc_debug_printf ("called");
 
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
 
@@ -1626,8 +1717,9 @@ arc_make_frame_cache (struct frame_info *this_frame)
 
   for (int i = 0; i <= ARC_LAST_CORE_REGNUM; i++)
     {
-      if (trad_frame_addr_p (cache->saved_regs, i))
-       cache->saved_regs[i].addr += cache->prev_sp;
+      if (cache->saved_regs[i].is_addr ())
+       cache->saved_regs[i].set_addr (cache->saved_regs[i].addr ()
+                                      + cache->prev_sp);
     }
 
   if (arc_debug)
@@ -1642,8 +1734,7 @@ static void
 arc_frame_this_id (struct frame_info *this_frame, void **this_cache,
                   struct frame_id *this_id)
 {
-  if (arc_debug)
-    debug_printf ("arc: frame_this_id\n");
+  arc_debug_printf ("called");
 
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
 
@@ -1732,6 +1823,100 @@ arc_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
     reg->how = DWARF2_FRAME_REG_CFA;
 }
 
+/*  Signal trampoline frame unwinder.  Allows frame unwinding to happen
+    from within signal handlers.  */
+
+static struct arc_frame_cache *
+arc_make_sigtramp_frame_cache (struct frame_info *this_frame)
+{
+  arc_debug_printf ("called");
+
+  struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (this_frame));
+
+  /* Allocate new frame cache instance and space for saved register info.  */
+  struct arc_frame_cache *cache = FRAME_OBSTACK_ZALLOC (struct arc_frame_cache);
+  cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+
+  /* Get the stack pointer and use it as the frame base.  */
+  cache->prev_sp = arc_frame_base_address (this_frame, NULL);
+
+  /* If the ARC-private target-dependent info doesn't have a table of
+     offsets of saved register contents within an OS signal context
+     structure, then there is nothing to analyze.  */
+  if (tdep->sc_reg_offset == NULL)
+    return cache;
+
+  /* Find the address of the sigcontext structure.  */
+  CORE_ADDR addr = tdep->sigcontext_addr (this_frame);
+
+  /* For each register, if its contents have been saved within the
+     sigcontext structure, determine the address of those contents.  */
+  gdb_assert (tdep->sc_num_regs <= (ARC_LAST_REGNUM + 1));
+  for (int i = 0; i < tdep->sc_num_regs; i++)
+    {
+      if (tdep->sc_reg_offset[i] != ARC_OFFSET_NO_REGISTER)
+       cache->saved_regs[i].set_addr (addr + tdep->sc_reg_offset[i]);
+    }
+
+  return cache;
+}
+
+/* Implement the "this_id" frame_unwind method for signal trampoline
+   frames.  */
+
+static void
+arc_sigtramp_frame_this_id (struct frame_info *this_frame,
+                           void **this_cache, struct frame_id *this_id)
+{
+  arc_debug_printf ("called");
+
+  if (*this_cache == NULL)
+    *this_cache = arc_make_sigtramp_frame_cache (this_frame);
+
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  struct arc_frame_cache *cache = (struct arc_frame_cache *) *this_cache;
+  CORE_ADDR stack_addr = cache->prev_sp;
+  CORE_ADDR code_addr
+    = get_frame_register_unsigned (this_frame, gdbarch_pc_regnum (gdbarch));
+  *this_id = frame_id_build (stack_addr, code_addr);
+}
+
+/* Get a register from a signal handler frame.  */
+
+static struct value *
+arc_sigtramp_frame_prev_register (struct frame_info *this_frame,
+                                 void **this_cache, int regnum)
+{
+  arc_debug_printf ("regnum = %d", regnum);
+
+  /* Make sure we've initialized the cache.  */
+  if (*this_cache == NULL)
+    *this_cache = arc_make_sigtramp_frame_cache (this_frame);
+
+  struct arc_frame_cache *cache = (struct arc_frame_cache *) *this_cache;
+  return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
+}
+
+/* Frame sniffer for signal handler frame.  Only recognize a frame if we
+   have a sigcontext_addr handler in the target dependency.  */
+
+static int
+arc_sigtramp_frame_sniffer (const struct frame_unwind *self,
+                           struct frame_info *this_frame,
+                           void **this_cache)
+{
+  struct gdbarch_tdep *tdep;
+
+  arc_debug_printf ("called");
+
+  tdep = gdbarch_tdep (get_frame_arch (this_frame));
+
+  /* If we have a sigcontext_addr handler, then just return 1 (same as the
+     "default_frame_sniffer ()").  */
+  return (tdep->sigcontext_addr != NULL && tdep->is_sigtramp != NULL
+         && tdep->is_sigtramp (this_frame));
+}
+
 /* Structure defining the ARC ordinary frame unwind functions.  Since we are
    the fallback unwinder, we use the default frame sniffer, which always
    accepts the frame.  */
@@ -1747,6 +1932,21 @@ static const struct frame_unwind arc_frame_unwind = {
   NULL
 };
 
+/* Structure defining the ARC signal frame unwind functions.  Custom
+   sniffer is used, because this frame must be accepted only in the right
+   context.  */
+
+static const struct frame_unwind arc_sigtramp_frame_unwind = {
+  SIGTRAMP_FRAME,
+  default_frame_unwind_stop_reason,
+  arc_sigtramp_frame_this_id,
+  arc_sigtramp_frame_prev_register,
+  NULL,
+  arc_sigtramp_frame_sniffer,
+  NULL,
+  NULL
+};
+
 
 static const struct frame_base arc_normal_base = {
   &arc_frame_unwind,
@@ -1755,206 +1955,298 @@ static const struct frame_base arc_normal_base = {
   arc_frame_base_address
 };
 
-/* Initialize target description for the ARC.
+/* Add all the expected register sets into GDBARCH.  */
 
-   Returns TRUE if input tdesc was valid and in this case it will assign TDESC
-   and TDESC_DATA output parameters.  */
+static void
+arc_add_reggroups (struct gdbarch *gdbarch)
+{
+  reggroup_add (gdbarch, general_reggroup);
+  reggroup_add (gdbarch, float_reggroup);
+  reggroup_add (gdbarch, system_reggroup);
+  reggroup_add (gdbarch, vector_reggroup);
+  reggroup_add (gdbarch, all_reggroup);
+  reggroup_add (gdbarch, save_reggroup);
+  reggroup_add (gdbarch, restore_reggroup);
+}
 
-static int
-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");
+  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);
+    }
+}
 
-  const struct target_desc *tdesc_loc = info.target_desc;
+/* See arc-tdep.h.  */
 
-  /* 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);
-  int is_reduced_rf;
-  const char *const *core_regs;
-  const char *core_feature_name;
-
-  /* If target doesn't provide a description - use default one.  */
-  if (!tdesc_has_registers (tdesc_loc))
+arc_arch_features
+arc_arch_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 = tdesc_arc_v2;
-         if (arc_debug)
-           debug_printf ("arc: Using default register set for ARC v2.\n");
-       }
+      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 = tdesc_arc_arcompact;
-         if (arc_debug)
-           debug_printf ("arc: Using default register set for ARCompact.\n");
-       }
+       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_arch_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;
+/* 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.  */
 
-  for (int i = 0; i <= ARC_LAST_CORE_REGNUM; i++)
+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
+   and TDESC_DATA output parameters.  */
+
+static bool
+arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
+               tdesc_arch_data_up *tdesc_data)
+{
+  const struct target_desc *tdesc_loc = info.target_desc;
+  arc_debug_printf ("Target description initialization.");
+
+  /* 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_arch_features features
+       = arc_arch_features_create (info.abfd,
+                                   info.bfd_arch_info->mach);
+      tdesc_loc = arc_lookup_target_description (features);
     }
+  gdb_assert (tdesc_loc != nullptr);
 
-  /* Mandatory AUX registeres 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)
+  arc_debug_printf ("Have got a target description");
+
+  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"), aux_minimal_feature_name);
-      tdesc_data_cleanup (tdesc_data_loc);
-      return FALSE;
+      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 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 ();
+
+  tdesc_arch_data_up tdesc_data_loc = tdesc_data_alloc ();
+
+  arc_update_acc_reg_names (info.byte_order);
+
+  bool valid_p = arc_check_tdesc_feature (tdesc_data_loc.get (),
+                                         feature_core,
+                                         arc_core_reg_feature);
+
+  valid_p &= arc_check_tdesc_feature (tdesc_data_loc.get (),
+                                     feature_aux,
+                                     arc_aux_reg_feature);
+
+  if (!valid_p)
+    {
+      arc_debug_printf ("Target description is not valid");
+      return false;
     }
 
   *tdesc = tdesc_loc;
-  *tdesc_data = tdesc_data_loc;
+  *tdesc_data = std::move (tdesc_data_loc);
 
-  return TRUE;
+  return true;
 }
 
 /* Implement the type_align gdbarch function.  */
@@ -1962,8 +2254,27 @@ arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
 static ULONGEST
 arc_type_align (struct gdbarch *gdbarch, struct type *type)
 {
-  type = check_typedef (type);
-  return std::min<ULONGEST> (4, TYPE_LENGTH (type));
+  switch (type->code ())
+    {
+    case TYPE_CODE_PTR:
+    case TYPE_CODE_FUNC:
+    case TYPE_CODE_FLAGS:
+    case TYPE_CODE_INT:
+    case TYPE_CODE_RANGE:
+    case TYPE_CODE_FLT:
+    case TYPE_CODE_ENUM:
+    case TYPE_CODE_REF:
+    case TYPE_CODE_RVALUE_REF:
+    case TYPE_CODE_CHAR:
+    case TYPE_CODE_BOOL:
+    case TYPE_CODE_DECFLOAT:
+    case TYPE_CODE_METHODPTR:
+    case TYPE_CODE_MEMBERPTR:
+      type = check_typedef (type);
+      return std::min<ULONGEST> (4, TYPE_LENGTH (type));
+    default:
+      return 0;
+    }
 }
 
 /* Implement the "init" gdbarch method.  */
@@ -1972,19 +2283,20 @@ static struct gdbarch *
 arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
   const struct target_desc *tdesc;
-  struct tdesc_arch_data *tdesc_data;
+  tdesc_arch_data_up tdesc_data;
 
-  if (arc_debug)
-    debug_printf ("arc: Architecture initialization.\n");
+  arc_debug_printf ("Architecture initialization.");
 
   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.get ());
+  struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep.release ());
 
   /* Data types.  */
   set_gdbarch_short_bit (gdbarch, 16);
@@ -2014,7 +2326,6 @@ 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.  */
 
-  set_gdbarch_dummy_id (gdbarch, arc_dummy_id);
   set_gdbarch_push_dummy_call (gdbarch, arc_push_dummy_call);
   set_gdbarch_push_dummy_code (gdbarch, arc_push_dummy_code);
 
@@ -2037,9 +2348,6 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   else
     set_gdbarch_decr_pc_after_break (gdbarch, 2);
 
-  set_gdbarch_unwind_pc (gdbarch, arc_unwind_pc);
-  set_gdbarch_unwind_sp (gdbarch, arc_unwind_sp);
-
   set_gdbarch_frame_align (gdbarch, arc_frame_align);
 
   set_gdbarch_print_insn (gdbarch, arc_delayed_print_insn);
@@ -2059,9 +2367,13 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* This doesn't include possible long-immediate value.  */
   set_gdbarch_max_insn_length (gdbarch, 4);
 
+  /* Add default register groups.  */
+  arc_add_reggroups (gdbarch);
+
   /* Frame unwinders and sniffers.  */
   dwarf2_frame_set_init_reg (gdbarch, arc_dwarf2_frame_init_reg);
   dwarf2_append_unwinders (gdbarch);
+  frame_unwind_append_unwinder (gdbarch, &arc_sigtramp_frame_unwind);
   frame_unwind_append_unwinder (gdbarch, &arc_frame_unwind);
   frame_base_set_default (gdbarch, &arc_normal_base);
 
@@ -2069,7 +2381,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
@@ -2127,7 +2439,7 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        }
     }
 
-  tdesc_use_registers (gdbarch, tdesc, tdesc_data);
+  tdesc_use_registers (gdbarch, tdesc, std::move (tdesc_data));
 
   return gdbarch;
 }
@@ -2140,14 +2452,15 @@ arc_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   fprintf_unfiltered (file, "arc_dump_tdep: jb_pc = %i\n", tdep->jb_pc);
-}
-
-/* Wrapper for "maintenance print arc" list of commands.  */
 
-static void
-maintenance_print_arc_command (const char *args, int from_tty)
-{
-  cmd_show_list (maintenance_print_arc_list, from_tty, "");
+  fprintf_unfiltered (file, "arc_dump_tdep: is_sigtramp = <%s>\n",
+                     host_address_to_string (tdep->is_sigtramp));
+  fprintf_unfiltered (file, "arc_dump_tdep: sigcontext_addr = <%s>\n",
+                     host_address_to_string (tdep->sigcontext_addr));
+  fprintf_unfiltered (file, "arc_dump_tdep: sc_reg_offset = <%s>\n",
+                     host_address_to_string (tdep->sc_reg_offset));
+  fprintf_unfiltered (file, "arc_dump_tdep: sc_num_regs = %d\n",
+                     tdep->sc_num_regs);
 }
 
 /* This command accepts single argument - address of instruction to
@@ -2170,22 +2483,20 @@ dump_arc_instruction_command (const char *args, int from_tty)
   arc_insn_dump (insn);
 }
 
+void _initialize_arc_tdep ();
 void
-_initialize_arc_tdep (void)
+_initialize_arc_tdep ()
 {
   gdbarch_register (bfd_arch_arc, arc_gdbarch_init, arc_dump_tdep);
 
-  initialize_tdesc_arc_v2 ();
-  initialize_tdesc_arc_arcompact ();
-
   /* Register ARC-specific commands with gdb.  */
 
   /* Add root prefix command for "maintenance print arc" commands.  */
-  add_prefix_cmd ("arc", class_maintenance, maintenance_print_arc_command,
-                 _("ARC-specific maintenance commands for printing GDB "
-                   "internal state."),
-                 &maintenance_print_arc_list, "maintenance print arc ", 0,
-                 &maintenanceprintlist);
+  add_show_prefix_cmd ("arc", class_maintenance,
+                      _("ARC-specific maintenance commands for printing GDB "
+                        "internal state."),
+                      &maintenance_print_arc_list,
+                      0, &maintenanceprintlist);
 
   add_cmd ("arc-instruction", class_maintenance,
           dump_arc_instruction_command,
@@ -2193,10 +2504,10 @@ _initialize_arc_tdep (void)
           &maintenance_print_arc_list);
 
   /* Debug internals for ARC GDB.  */
-  add_setshow_zinteger_cmd ("arc", class_maintenance,
-                           &arc_debug,
-                           _("Set ARC specific debugging."),
-                           _("Show ARC specific debugging."),
-                           _("Non-zero enables ARC specific debugging."),
-                           NULL, NULL, &setdebuglist, &showdebuglist);
+  add_setshow_boolean_cmd ("arc", class_maintenance,
+                          &arc_debug,
+                          _("Set ARC specific debugging."),
+                          _("Show ARC specific debugging."),
+                          _("When set, ARC specific debugging is enabled."),
+                          NULL, NULL, &setdebuglist, &showdebuglist);
 }
This page took 0.075744 seconds and 4 git commands to generate.