25120014 gdb does not support target descriptions layered on top of native one
authorIvo Raisr <ivo.raisr@oracle.com>
Tue, 06 Dec 2016 15:59:27 -0800
changeset 7461 fae95a5b122f
parent 7460 ce0a4dac8adb
child 7462 b70b1d023c26
25120014 gdb does not support target descriptions layered on top of native one
components/gdb/patches/gdb.features.sparc64-fpu.xml.patch
components/gdb/patches/gdb.gdb.sparc-tdep.c.patch
components/gdb/patches/gdb.gdb.sparc-tdep.h-2.patch
components/gdb/patches/gdb.gdb.sparc64-tdep.c-2.patch
components/gdb/patches/gdb.gdb.sparc64-tdep.h.patch
components/gdb/patches/gdb.testsuite.tdesc-regs.exp.patch
components/gdb/test/results-sparc-64.master
--- a/components/gdb/patches/gdb.features.sparc64-fpu.xml.patch	Mon Dec 05 15:47:44 2016 -0800
+++ b/components/gdb/patches/gdb.features.sparc64-fpu.xml.patch	Tue Dec 06 15:59:27 2016 -0800
@@ -3,7 +3,7 @@
 +++ gdb-7.6/gdb/features/sparc64-fpu.xml	2013-08-28 00:21:33.000000000 -0700
 @@ -0,0 +1,60 @@
 +<?xml version="1.0"?>
-+<!-- Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
++<!-- Copyright (C) 2007-2013 Free Software Foundation, Inc.
 +
 +     Copying and distribution of this file, with or without modification,
 +     are permitted in any medium without royalty provided the copyright
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/gdb/patches/gdb.gdb.sparc-tdep.c.patch	Tue Dec 06 15:59:27 2016 -0800
@@ -0,0 +1,239 @@
+Support for target descriptions layered on top of sparc32/sparc64
+which describe more registers than native ones.
+Pseudo registers always come after the real registers.
+One more step forward to modernize sparc tdep's.
+Submitted to upstream as:
+https://sourceware.org/bugzilla/show_bug.cgi?id=20936
+
+--- gdb-7.11/gdb/sparc-tdep.c.orig	2016-11-18 06:00:18.299687730 -0800
++++ gdb-7.11/gdb/sparc-tdep.c	2016-11-18 06:01:36.293409472 -0800
[email protected]@ -33,6 +33,7 @@
+ #include "osabi.h"
+ #include "regcache.h"
+ #include "target.h"
++#include "target-descriptions.h"
+ #include "value.h"
+ 
+ #include "sparc-tdep.h"
[email protected]@ -295,20 +296,23 @@
+ }
+ 
+ /* Register information.  */
++#define SPARC32_FPU_REGISTERS                             \
++  "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",         \
++  "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",   \
++  "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", \
++  "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
++#define SPARC32_CP0_REGISTERS \
++  "y", "psr", "wim", "tbr", "pc", "npc", "fsr", "csr"
+ 
++static const char *sparc_core_register_names[] = { SPARC_CORE_REGISTERS };
++static const char *sparc32_fpu_register_names[] = { SPARC32_FPU_REGISTERS };
++static const char *sparc32_cp0_register_names[] = { SPARC32_CP0_REGISTERS };
++
+ static const char *sparc32_register_names[] =
+ {
+-  "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
+-  "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
+-  "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
+-  "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7",
+-
+-  "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+-  "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+-  "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+-  "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+-
+-  "y", "psr", "wim", "tbr", "pc", "npc", "fsr", "csr"
++  SPARC_CORE_REGISTERS,
++  SPARC32_FPU_REGISTERS,
++  SPARC32_CP0_REGISTERS
+ };
+ 
+ /* Total number of registers.  */
[email protected]@ -327,7 +331,19 @@
+ #define SPARC32_NUM_PSEUDO_REGS ARRAY_SIZE (sparc32_pseudo_register_names)
+ 
+ /* Return the name of register REGNUM.  */
++static const char *
++sparc32_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
++{
++  regnum -= gdbarch_num_regs (gdbarch);
+ 
++  if (regnum < SPARC32_NUM_PSEUDO_REGS)
++    return sparc32_pseudo_register_names[regnum];
++
++  internal_error (__FILE__, __LINE__,
++                  _("sparc32_pseudo_register_name: bad register number %d"),
++                  regnum);
++}
++
+ static const char *
+ sparc32_register_name (struct gdbarch *gdbarch, int regnum)
+ {
[email protected]@ -334,10 +350,10 @@
+   if (regnum >= 0 && regnum < SPARC32_NUM_REGS)
+     return sparc32_register_names[regnum];
+ 
+-  if (regnum < SPARC32_NUM_REGS + SPARC32_NUM_PSEUDO_REGS)
+-    return sparc32_pseudo_register_names[regnum - SPARC32_NUM_REGS];
++  if (regnum >= gdbarch_num_regs (gdbarch))
++    return sparc32_pseudo_register_name (gdbarch, regnum);
+ 
+-  return NULL;
++  return tdesc_register_name (gdbarch, regnum);
+ }
+ 
+ /* Construct types for ISA-specific registers.  */
[email protected]@ -399,7 +415,19 @@
+ 
+ /* Return the GDB type object for the "standard" data type of data in
+    register REGNUM.  */
++static struct type *
++sparc32_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
++{
++  regnum -= gdbarch_num_regs (gdbarch);
+ 
++  if (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM)
++    return builtin_type (gdbarch)->builtin_double;
++
++  internal_error (__FILE__, __LINE__,
++                  _("sparc32_pseudo_register_type: bad register number %d"),
++                  regnum);
++}
++
+ static struct type *
+ sparc32_register_type (struct gdbarch *gdbarch, int regnum)
+ {
[email protected]@ -406,9 +434,6 @@
+   if (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM)
+     return builtin_type (gdbarch)->builtin_float;
+ 
+-  if (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM)
+-    return builtin_type (gdbarch)->builtin_double;
+-
+   if (regnum == SPARC_SP_REGNUM || regnum == SPARC_FP_REGNUM)
+     return builtin_type (gdbarch)->builtin_data_ptr;
+ 
[email protected]@ -421,6 +446,9 @@
+   if (regnum == SPARC32_FSR_REGNUM)
+     return sparc_fsr_type (gdbarch);
+ 
++  if (regnum >= gdbarch_num_regs (gdbarch))
++    return sparc32_pseudo_register_type (gdbarch, regnum);
++
+   return builtin_type (gdbarch)->builtin_int32;
+ }
+ 
[email protected]@ -431,6 +459,7 @@
+ {
+   enum register_status status;
+ 
++  regnum -= gdbarch_num_regs (gdbarch);
+   gdb_assert (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM);
+ 
+   regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC32_D0_REGNUM);
[email protected]@ -445,6 +474,7 @@
+ 			       struct regcache *regcache,
+ 			       int regnum, const gdb_byte *buf)
+ {
++  regnum -= gdbarch_num_regs (gdbarch);
+   gdb_assert (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM);
+ 
+   regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC32_D0_REGNUM);
[email protected]@ -1660,11 +1690,36 @@
+ }
+ 
+ 
++static int
++validate_tdesc_registers (const struct target_desc *tdesc,
++                          struct tdesc_arch_data *tdesc_data,
++                          const char *feature_name,
++                          const char *register_names[],
++                          unsigned int registers_num,
++                          unsigned int reg_start)
++{
++  int valid_p = 1;
++  const struct tdesc_feature *feature;
++
++  feature = tdesc_find_feature (tdesc, feature_name);
++  if (feature == NULL)
++    return 0;
++
++  for (unsigned int i = 0; i < registers_num; i++)
++    valid_p &= tdesc_numbered_register (feature, tdesc_data,
++                                        reg_start + i,
++                                        register_names[i]);
++
++  return valid_p;
++}
++
+ static struct gdbarch *
+ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+ {
+   struct gdbarch_tdep *tdep;
++  const struct target_desc *tdesc = info.target_desc;
+   struct gdbarch *gdbarch;
++  int valid_p = 1;
+ 
+   /* If there is already a candidate, use it.  */
+   arches = gdbarch_list_lookup_by_info (arches, &info);
[email protected]@ -1678,6 +1733,10 @@
+   tdep->pc_regnum = SPARC32_PC_REGNUM;
+   tdep->npc_regnum = SPARC32_NPC_REGNUM;
+   tdep->step_trap = sparc_step_trap;
++  tdep->fpu_register_names = sparc32_fpu_register_names;
++  tdep->fpu_registers_num = ARRAY_SIZE (sparc32_fpu_register_names);
++  tdep->cp0_register_names = sparc32_cp0_register_names;
++  tdep->cp0_registers_num = ARRAY_SIZE (sparc32_cp0_register_names);
+ 
+   set_gdbarch_long_double_bit (gdbarch, 128);
+   set_gdbarch_long_double_format (gdbarch, floatformats_sparc_quad);
[email protected]@ -1686,6 +1745,8 @@
+   set_gdbarch_register_name (gdbarch, sparc32_register_name);
+   set_gdbarch_register_type (gdbarch, sparc32_register_type);
+   set_gdbarch_num_pseudo_regs (gdbarch, SPARC32_NUM_PSEUDO_REGS);
++  set_tdesc_pseudo_register_name (gdbarch, sparc32_pseudo_register_name);
++  set_tdesc_pseudo_register_type (gdbarch, sparc32_pseudo_register_type);
+   set_gdbarch_pseudo_register_read (gdbarch, sparc32_pseudo_register_read);
+   set_gdbarch_pseudo_register_write (gdbarch, sparc32_pseudo_register_write);
+ 
[email protected]@ -1734,6 +1795,39 @@
+ 
+   frame_unwind_append_unwinder (gdbarch, &sparc32_frame_unwind);
+ 
++  if (tdesc_has_registers (tdesc))
++    {
++      struct tdesc_arch_data *tdesc_data = tdesc_data_alloc ();
++
++      /* Validate that the descriptor provides the mandatory registers
++         and allocate their numbers. */
++      valid_p &= validate_tdesc_registers (tdesc, tdesc_data,
++                                           "org.gnu.gdb.sparc.cpu",
++                                           sparc_core_register_names,
++                                           ARRAY_SIZE (sparc_core_register_names),
++                                           SPARC_G0_REGNUM);
++      valid_p &= validate_tdesc_registers (tdesc, tdesc_data,
++                                           "org.gnu.gdb.sparc.fpu",
++                                           tdep->fpu_register_names,
++                                           tdep->fpu_registers_num,
++                                           SPARC_F0_REGNUM);
++      valid_p &= validate_tdesc_registers (tdesc, tdesc_data,
++                                           "org.gnu.gdb.sparc.cp0",
++                                           tdep->cp0_register_names,
++                                           tdep->cp0_registers_num,
++                                           SPARC_F0_REGNUM + 
++                                           tdep->fpu_registers_num);
++      if (!valid_p)
++        {
++          tdesc_data_cleanup (tdesc_data);
++          return NULL;
++        }
++
++      /* Target description may have changed. */
++      info.tdep_info = tdesc_data;
++      tdesc_use_registers (gdbarch, tdesc, tdesc_data);
++    }
++
+   /* If we have register sets, enable the generic core file support.  */
+   if (tdep->gregset)
+     set_gdbarch_iterate_over_regset_sections
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/gdb/patches/gdb.gdb.sparc-tdep.h-2.patch	Tue Dec 06 15:59:27 2016 -0800
@@ -0,0 +1,48 @@
+Support for target descriptions layered on top of sparc32/sparc64
+which describe more registers than native ones.
+Pseudo registers always come after the real registers.
+One more step forward to modernize sparc tdep's.
+Submitted to upstream as:
+https://sourceware.org/bugzilla/show_bug.cgi?id=20936
+
+--- gdb-7.11/gdb/sparc-tdep.h.orig	2016-11-13 21:25:35.998594039 -0800
++++ gdb-7.11/gdb/sparc-tdep.h	2016-11-13 21:26:09.714151047 -0800
[email protected]@ -20,6 +20,12 @@
+ #ifndef SPARC_TDEP_H
+ #define SPARC_TDEP_H 1
+ 
++#define SPARC_CORE_REGISTERS                      \
++  "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", \
++  "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7", \
++  "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", \
++  "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
++
+ struct frame_info;
+ struct gdbarch;
+ struct regcache;
[email protected]@ -57,6 +63,12 @@
+   int pc_regnum;
+   int npc_regnum;
+ 
++  /* Register names specific for architecture (sparc32 vs. sparc64) */
++  const char **fpu_register_names;
++  size_t fpu_registers_num;
++  const char **cp0_register_names;
++  size_t cp0_registers_num;
++
+   /* Register sets.  */
+   const struct regset *gregset;
+   size_t sizeof_gregset;
[email protected]@ -141,8 +153,11 @@
+   SPARC32_NPC_REGNUM,		/* %npc */
+   SPARC32_FSR_REGNUM,		/* %fsr */
+   SPARC32_CSR_REGNUM,		/* %csr */
++};
+ 
+-  /* Pseudo registers.  */
++/* Pseudo registers.  */
++enum sparc32_pseudo_regnum
++{
+   SPARC32_D0_REGNUM,		/* %d0 */
+   SPARC32_D30_REGNUM		/* %d30 */
+   = SPARC32_D0_REGNUM + 15
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/gdb/patches/gdb.gdb.sparc64-tdep.c-2.patch	Tue Dec 06 15:59:27 2016 -0800
@@ -0,0 +1,328 @@
+Support for target descriptions layered on top of sparc32/sparc64
+which describe more registers than native ones.
+Pseudo registers always come after the real registers.
+One more step forward to modernize sparc tdep's.
+Submitted to upstream as:
+https://sourceware.org/bugzilla/show_bug.cgi?id=20936
+
+--- gdb-7.11/gdb/sparc64-tdep.c.orig	2016-11-13 22:23:36.747445049 -0800
++++ gdb-7.11/gdb/sparc64-tdep.c	2016-11-13 22:23:47.678340579 -0800
[email protected]@ -31,6 +31,7 @@
+ #include "objfiles.h"
+ #include "osabi.h"
+ #include "regcache.h"
++#include "target-descriptions.h"
+ #include "target.h"
+ #include "value.h"
+ 
[email protected]@ -251,28 +252,29 @@
+ 
+ 
+ /* Register information.  */
++#define SPARC64_FPU_REGISTERS                             \
++  "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",         \
++  "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",   \
++  "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", \
++  "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", \
++  "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46", \
++  "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62"
++#define SPARC64_CP0_REGISTERS                                             \
++  "pc", "npc",                                                            \
++  /* FIXME: Give "state" a name until we start using register groups.  */ \
++  "state",                                                                \
++  "fsr",                                                                  \
++  "fprs",                                                                 \
++  "y"
+ 
++static const char *sparc64_fpu_register_names[] = { SPARC64_FPU_REGISTERS };
++static const char *sparc64_cp0_register_names[] = { SPARC64_CP0_REGISTERS };
++
+ static const char *sparc64_register_names[] =
+ {
+-  "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
+-  "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
+-  "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
+-  "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7",
+-
+-  "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+-  "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+-  "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+-  "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+-  "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
+-  "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
+-
+-  "pc", "npc",
+-  
+-  /* FIXME: Give "state" a name until we start using register groups.  */
+-  "state",
+-  "fsr",
+-  "fprs",
+-  "y",
++  SPARC_CORE_REGISTERS,
++  SPARC64_FPU_REGISTERS,
++  SPARC64_CP0_REGISTERS
+ };
+ 
+ /* Total number of registers.  */
[email protected]@ -298,7 +300,19 @@
+ #define SPARC64_NUM_PSEUDO_REGS ARRAY_SIZE (sparc64_pseudo_register_names)
+ 
+ /* Return the name of register REGNUM.  */
++static const char *
++sparc64_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
++{
++  regnum -= gdbarch_num_regs (gdbarch);
+ 
++  if (regnum < SPARC64_NUM_PSEUDO_REGS)
++    return sparc64_pseudo_register_names[regnum];
++
++  internal_error (__FILE__, __LINE__,
++                  _("sparc64_pseudo_register_name: bad register number %d"),
++                  regnum);
++}
++
+ static const char *
+ sparc64_register_name (struct gdbarch *gdbarch, int regnum)
+ {
[email protected]@ -305,9 +319,8 @@
+   if (regnum >= 0 && regnum < SPARC64_NUM_REGS)
+     return sparc64_register_names[regnum];
+ 
+-  if (regnum >= SPARC64_NUM_REGS
+-      && regnum < SPARC64_NUM_REGS + SPARC64_NUM_PSEUDO_REGS)
+-    return sparc64_pseudo_register_names[regnum - SPARC64_NUM_REGS];
++  if (regnum >= gdbarch_num_regs (gdbarch))
++    return sparc64_pseudo_register_name (gdbarch, regnum);
+ 
+   return NULL;
+ }
[email protected]@ -314,7 +327,29 @@
+ 
+ /* Return the GDB type object for the "standard" data type of data in
+    register REGNUM.  */
++static struct type *
++sparc64_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
++{
++  regnum -= gdbarch_num_regs (gdbarch);
+ 
++  if (regnum == SPARC64_CWP_REGNUM)
++    return builtin_type (gdbarch)->builtin_int64;
++  if (regnum == SPARC64_PSTATE_REGNUM)
++    return sparc64_pstate_type (gdbarch);
++  if (regnum == SPARC64_ASI_REGNUM)
++    return builtin_type (gdbarch)->builtin_int64;
++  if (regnum == SPARC64_CCR_REGNUM)
++    return sparc64_ccr_type (gdbarch);
++  if (regnum >= SPARC64_D0_REGNUM && regnum <= SPARC64_D62_REGNUM)
++    return builtin_type (gdbarch)->builtin_double;
++  if (regnum >= SPARC64_Q0_REGNUM && regnum <= SPARC64_Q60_REGNUM)
++    return builtin_type (gdbarch)->builtin_long_double;
++
++  internal_error (__FILE__, __LINE__,
++                  _("sparc64_pseudo_register_type: bad register number %d"),
++                  regnum);
++}
++
+ static struct type *
+ sparc64_register_type (struct gdbarch *gdbarch, int regnum)
+ {
[email protected]@ -344,20 +379,9 @@
+     return builtin_type (gdbarch)->builtin_int64;
+ 
+   /* Pseudo registers.  */
++  if (regnum >= gdbarch_num_regs (gdbarch))
++    return sparc64_pseudo_register_type (gdbarch, regnum);
+ 
+-  if (regnum == SPARC64_CWP_REGNUM)
+-    return builtin_type (gdbarch)->builtin_int64;
+-  if (regnum == SPARC64_PSTATE_REGNUM)
+-    return sparc64_pstate_type (gdbarch);
+-  if (regnum == SPARC64_ASI_REGNUM)
+-    return builtin_type (gdbarch)->builtin_int64;
+-  if (regnum == SPARC64_CCR_REGNUM)
+-    return sparc64_ccr_type (gdbarch);
+-  if (regnum >= SPARC64_D0_REGNUM && regnum <= SPARC64_D62_REGNUM)
+-    return builtin_type (gdbarch)->builtin_double;
+-  if (regnum >= SPARC64_Q0_REGNUM && regnum <= SPARC64_Q60_REGNUM)
+-    return builtin_type (gdbarch)->builtin_long_double;
+-
+   internal_error (__FILE__, __LINE__, _("invalid regnum"));
+ }
+ 
[email protected]@ -369,7 +393,7 @@
+   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+   enum register_status status;
+ 
+-  gdb_assert (regnum >= SPARC64_NUM_REGS);
++  regnum -= gdbarch_num_regs (gdbarch);
+ 
+   if (regnum >= SPARC64_D0_REGNUM && regnum <= SPARC64_D30_REGNUM)
+     {
[email protected]@ -446,8 +470,9 @@
+ 			       int regnum, const gdb_byte *buf)
+ {
+   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+-  gdb_assert (regnum >= SPARC64_NUM_REGS);
+ 
++  regnum -= gdbarch_num_regs (gdbarch);
++
+   if (regnum >= SPARC64_D0_REGNUM && regnum <= SPARC64_D30_REGNUM)
+     {
+       regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC64_D0_REGNUM);
[email protected]@ -663,6 +688,7 @@
+ sparc64_store_floating_fields (struct regcache *regcache, struct type *type,
+ 			       const gdb_byte *valbuf, int element, int bitpos)
+ {
++  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+   int len = TYPE_LENGTH (type);
+ 
+   gdb_assert (element < 16);
[email protected]@ -677,7 +703,7 @@
+ 	  gdb_assert (bitpos == 0);
+ 	  gdb_assert ((element % 2) == 0);
+ 
+-	  regnum = SPARC64_Q0_REGNUM + element / 2;
++	  regnum = gdbarch_num_regs (gdbarch) + SPARC64_Q0_REGNUM + element / 2;
+ 	  regcache_cooked_write (regcache, regnum, valbuf);
+ 	}
+       else if (len == 8)
[email protected]@ -684,7 +710,8 @@
+ 	{
+ 	  gdb_assert (bitpos == 0 || bitpos == 64);
+ 
+-	  regnum = SPARC64_D0_REGNUM + element + bitpos / 64;
++	  regnum = gdbarch_num_regs (gdbarch) + SPARC64_D0_REGNUM
++                   + element + bitpos / 64;
+ 	  regcache_cooked_write (regcache, regnum, valbuf + (bitpos / 8));
+ 	}
+       else
[email protected]@ -737,6 +764,8 @@
+ sparc64_extract_floating_fields (struct regcache *regcache, struct type *type,
+ 				 gdb_byte *valbuf, int bitpos)
+ {
++  struct gdbarch *gdbarch = get_regcache_arch (regcache);
++
+   if (sparc64_floating_p (type))
+     {
+       int len = TYPE_LENGTH (type);
[email protected]@ -746,7 +775,8 @@
+ 	{
+ 	  gdb_assert (bitpos == 0 || bitpos == 128);
+ 
+-	  regnum = SPARC64_Q0_REGNUM + bitpos / 128;
++	  regnum = gdbarch_num_regs (gdbarch) + SPARC64_Q0_REGNUM
++                   + bitpos / 128;
+ 	  regcache_cooked_read (regcache, regnum, valbuf + (bitpos / 8));
+ 	}
+       else if (len == 8)
[email protected]@ -753,7 +783,7 @@
+ 	{
+ 	  gdb_assert (bitpos % 64 == 0 && bitpos >= 0 && bitpos < 256);
+ 
+-	  regnum = SPARC64_D0_REGNUM + bitpos / 64;
++	  regnum = gdbarch_num_regs (gdbarch) + SPARC64_D0_REGNUM + bitpos / 64;
+ 	  regcache_cooked_read (regcache, regnum, valbuf + (bitpos / 8));
+ 	}
+       else
[email protected]@ -936,13 +966,13 @@
+ 	  /* Float Complex or double Complex arguments.  */
+ 	  if (element < 16)
+ 	    {
+-	      regnum = SPARC64_D0_REGNUM + element;
++	      regnum = gdbarch_num_regs (gdbarch) + SPARC64_D0_REGNUM + element;
+ 
+ 	      if (len == 16)
+ 		{
+-		  if (regnum < SPARC64_D30_REGNUM)
++		  if (regnum < gdbarch_num_regs (gdbarch) + SPARC64_D30_REGNUM)
+ 		    regcache_cooked_write (regcache, regnum + 1, valbuf + 8);
+-		  if (regnum < SPARC64_D10_REGNUM)
++		  if (regnum < gdbarch_num_regs (gdbarch) + SPARC64_D10_REGNUM)
+ 		    regcache_cooked_write (regcache,
+ 					   SPARC_O0_REGNUM + element + 1,
+ 					   valbuf + 8);
[email protected]@ -957,12 +987,14 @@
+ 	      if (element % 2)
+ 		element++;
+ 	      if (element < 16)
+-		regnum = SPARC64_Q0_REGNUM + element / 2;
++		regnum = gdbarch_num_regs (gdbarch) + SPARC64_Q0_REGNUM
++                         + element / 2;
+ 	    }
+ 	  else if (len == 8)
+ 	    {
+ 	      if (element < 16)
+-		regnum = SPARC64_D0_REGNUM + element;
++		regnum = gdbarch_num_regs (gdbarch) + SPARC64_D0_REGNUM
++                         + element;
+ 	    }
+ 	  else if (len == 4)
+ 	    {
[email protected]@ -977,7 +1009,8 @@
+ 	      valbuf = buf;
+ 	      len = 8;
+ 	      if (element < 16)
+-		regnum = SPARC64_D0_REGNUM + element;
++		regnum = gdbarch_num_regs (gdbarch) + SPARC64_D0_REGNUM
++                         + element;
+ 	    }
+ 	}
+       else
[email protected]@ -994,19 +1027,24 @@
+ 
+ 	  /* If we're storing the value in a floating-point register,
+              also store it in the corresponding %0 register(s).  */
+-	  if (regnum >= SPARC64_D0_REGNUM && regnum <= SPARC64_D10_REGNUM)
+-	    {
+-	      gdb_assert (element < 6);
+-	      regnum = SPARC_O0_REGNUM + element;
+-	      regcache_cooked_write (regcache, regnum, valbuf);
+-	    }
+-	  else if (regnum >= SPARC64_Q0_REGNUM && regnum <= SPARC64_Q8_REGNUM)
+-	    {
+-	      gdb_assert (element < 5);
+-	      regnum = SPARC_O0_REGNUM + element;
+-	      regcache_cooked_write (regcache, regnum, valbuf);
+-	      regcache_cooked_write (regcache, regnum + 1, valbuf + 8);
+-	    }
++	  if (regnum >= gdbarch_num_regs (gdbarch))
++            {
++              regnum -= gdbarch_num_regs (gdbarch);
++
++              if (regnum >= SPARC64_D0_REGNUM && regnum <= SPARC64_D10_REGNUM)
++	        {
++	          gdb_assert (element < 6);
++	          regnum = SPARC_O0_REGNUM + element;
++	          regcache_cooked_write (regcache, regnum, valbuf);
++                }
++              else if (regnum >= SPARC64_Q0_REGNUM && regnum <= SPARC64_Q8_REGNUM)
++                {
++                  gdb_assert (element < 5);
++                  regnum = SPARC_O0_REGNUM + element;
++                  regcache_cooked_write (regcache, regnum, valbuf);
++                  regcache_cooked_write (regcache, regnum + 1, valbuf + 8);
++	        }
++            }
+ 	}
+ 
+       /* Always store the argument in memory.  */
[email protected]@ -1210,6 +1248,10 @@
+ 
+   tdep->pc_regnum = SPARC64_PC_REGNUM;
+   tdep->npc_regnum = SPARC64_NPC_REGNUM;
++  tdep->fpu_register_names = sparc64_fpu_register_names;
++  tdep->fpu_registers_num = ARRAY_SIZE (sparc64_fpu_register_names);
++  tdep->cp0_register_names = sparc64_cp0_register_names;
++  tdep->cp0_registers_num = ARRAY_SIZE (sparc64_cp0_register_names);
+ 
+   /* This is what all the fuss is about.  */
+   set_gdbarch_long_bit (gdbarch, 64);
[email protected]@ -1220,6 +1262,8 @@
+   set_gdbarch_register_name (gdbarch, sparc64_register_name);
+   set_gdbarch_register_type (gdbarch, sparc64_register_type);
+   set_gdbarch_num_pseudo_regs (gdbarch, SPARC64_NUM_PSEUDO_REGS);
++  set_tdesc_pseudo_register_name (gdbarch, sparc64_pseudo_register_name);
++  set_tdesc_pseudo_register_type (gdbarch, sparc64_pseudo_register_type);
+   set_gdbarch_pseudo_register_read (gdbarch, sparc64_pseudo_register_read);
+   set_gdbarch_pseudo_register_write (gdbarch, sparc64_pseudo_register_write);
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/gdb/patches/gdb.gdb.sparc64-tdep.h.patch	Tue Dec 06 15:59:27 2016 -0800
@@ -0,0 +1,22 @@
+Support for target descriptions layered on top of sparc32/sparc64
+which describe more registers than native ones.
+Pseudo registers always come after the real registers.
+One more step forward to modernize sparc tdep's.
+Submitted to upstream as:
+https://sourceware.org/bugzilla/show_bug.cgi?id=20936
+
+--- gdb-7.11/gdb/sparc64-tdep.h.orig	2016-11-13 21:26:01.870566687 -0800
++++ gdb-7.11/gdb/sparc64-tdep.h	2016-11-13 21:26:21.157185579 -0800
[email protected]@ -56,8 +56,11 @@
+   SPARC64_FSR_REGNUM,		/* %fsr */
+   SPARC64_FPRS_REGNUM,		/* %fprs */
+   SPARC64_Y_REGNUM,		/* %y */
++};
+ 
+-  /* Pseudo registers.  */
++/* Pseudo registers.  */
++enum sparc64_pseudo_regnum
++{
+   SPARC64_CWP_REGNUM,		/* %cwp */
+   SPARC64_PSTATE_REGNUM,	/* %pstate */
+   SPARC64_ASI_REGNUM,		/* %asi */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/gdb/patches/gdb.testsuite.tdesc-regs.exp.patch	Tue Dec 06 15:59:27 2016 -0800
@@ -0,0 +1,22 @@
+Support for target descriptions layered on top of sparc32/sparc64
+which describe more registers than native ones.
+Pseudo registers always come after the real registers.
+One more step forward to modernize sparc tdep's.
+Submitted to upstream as:
+https://sourceware.org/bugzilla/show_bug.cgi?id=20936
+
+--- gdb-7.11/gdb/testsuite/gdb.xml/tdesc-regs.exp.orig	2016-11-19 07:32:42.820444427 -0800
++++ gdb-7.11/gdb/testsuite/gdb.xml/tdesc-regs.exp	2016-11-19 07:35:44.085215333 -0800
[email protected]@ -49,6 +49,12 @@
+     "s390*-*-*" {
+ 	set core-regs {s390-core32.xml s390-acr.xml s390-fpr.xml}
+     }
++    "sparc-*-*" {
++        set core-regs {sparc-cpu.xml sparc-fpu.xml sparc-cp0.xml}
++    }
++    "sparc64-*-*" {
++        set core-regs {sparc64-cpu.xml sparc64-fpu.xml sparc64-cp0.xml}
++    }
+     "spu*-*-*" {
+ 	# This may be either the spu-linux-nat target, or the Cell/B.E.
+ 	# multi-architecture debugger in SPU standalone executable mode.
--- a/components/gdb/test/results-sparc-64.master	Mon Dec 05 15:47:44 2016 -0800
+++ b/components/gdb/test/results-sparc-64.master	Tue Dec 06 15:59:27 2016 -0800
@@ -24370,14 +24370,25 @@
 PASS: gdb.xml/tdesc-errors.exp: set tdesc filename gdb.xml/tdesc-bogus.xml
 PASS: gdb.xml/tdesc-errors.exp: set tdesc filename gdb.xml/tdesc-unknown.xml
 PASS: gdb.xml/tdesc-regs.exp: set tdesc file single-reg.xml
-UNSUPPORTED: gdb.xml/tdesc-regs.exp: register tests
+PASS: gdb.xml/tdesc-regs.exp: cd to directory holding xml
+PASS: gdb.xml/tdesc-regs.exp: set tdesc filename regs.xml - from extra-regs.xml
+PASS: gdb.xml/tdesc-regs.exp: ptype $extrareg
+PASS: gdb.xml/tdesc-regs.exp: ptype $uintreg
+PASS: gdb.xml/tdesc-regs.exp: ptype $vecreg
+PASS: gdb.xml/tdesc-regs.exp: ptype $unionreg
+PASS: gdb.xml/tdesc-regs.exp: ptype $unionreg.v4
+PASS: gdb.xml/tdesc-regs.exp: ptype $structreg
+PASS: gdb.xml/tdesc-regs.exp: ptype $structreg.v4
+PASS: gdb.xml/tdesc-regs.exp: ptype $bitfields
+PASS: gdb.xml/tdesc-regs.exp: set tdesc filename regs.xml - from core-only.xml
+PASS: gdb.xml/tdesc-regs.exp: ptype $extrareg
 PASS: gdb.xml/tdesc-xinclude.exp: set tdesc filename gdb.xml/includes.xml
 PASS: gdb.xml/tdesc-xinclude.exp: set tdesc filename gdb.xml/bad-include.xml
 PASS: gdb.xml/tdesc-xinclude.exp: set tdesc filename gdb.xml/loop.xml
-# of expected passes		22561
+# of expected passes		22574
 # of unexpected failures	1228
 # of expected failures		36
 # of known failures		51
 # of unresolved testcases	177
 # of untested testcases		104
-# of unsupported tests		219
+# of unsupported tests		218