Bug 20936 - provide sparc and sparcv9 target description XML files

Message ID e6065f2e-f76d-0190-dc34-d04da1a33e84@oracle.com
State New
Headers show

Commit Message

Ivo Raisr Jan. 6, 2017, 3:12 p.m.
On 5.1.2017 15:31, Yao Qi wrote:
> On 17-01-04 18:42:27, Ivo Raisr wrote:

>> On 12.12.2016 13:53, Yao Qi wrote:

>>

>>> Hi Ivo,

>>> Your patch does two orthogonal things IMO,

>>>

>>>   - Pseudo register support enhancement, patch #1

>>>   - XML target description support and sparc*-tdep.c updates, patch #2,

>>>

>>> Can you split them to two patches?

>> Hi Yao,

>>

>> Thank you for looking into my changes.

>> I think I can see your motivation behind splitting the patch into two,

>> for better readability and manageability.

>> However my intention was only to provide support for registers

>> supplied by target description (Valgrind shadow registers in addition

>> to sparc real hardware ones).

>> Pseudo register changes were just a necessity to get this done

>> because Valgrind shadow registers are considered as "real" registers

>> and thus they are numbered before any pseudo registers.

>> This also means I cannot draw a clear line between your suggested

>> patch #1 and #2. Can you take my whole patch as is?

>>

> The line is clear to me.  I split your patch, and show the patch #1 here.

> Does it work for you?  Note you still need to add comments to new functions

> in the patch below.


I think I see the line now as well. Please find patch #1 together with a 
ChangeLog entry.
The patch was successfully built and tested on Solaris sparc.
After you find it ok, I will prepare patch #2.
I.
ChangeLog entry:
2017-01-06  Ivo Raisr  <ivo.raisr@oracle.com>

	Split real and pseudo registers in preparation for registers provided
	by a target. Registers provided by target description can have more real
	registers and pseudo registers need to be positioned after them.
	* sparc-tdep.h: Separate real and pseudo registers.
	* sparc64-tdep.h: Separate real and pseudo registers.
	* sparc-tdep.c (sparc32_pseudo_register_name): New function returning
	pseudo register names on sparc 32-bit.
	(sparc32_register_name): Use sparc32_pseudo_register_name().
	(sparc32_pseudo_register_type): New function returning pseudo register
	types on sparc 32-bit.
	(sparc32_register_type): Use sparc32_pseudo_register_type().
	(sparc32_pseudo_register_read, sparc32_pseudo_register_write): Pseudo
	registers may have different numbers.
	(sparc32_gdbarch_init): Initialize properly sparc 32-bit register names.
	* sparc64-tdep.c (sparc64_pseudo_register_name): New function returning
	pseudo register names on sparc 64-bit.
	(sparc64_register_name): Use sparc64_pseudo_register_name().
	(sparc64_pseudo_register_type): New function returning pseudo register
	types on sparc 64-bit.
	(sparc64_register_type): Use sparc64_pseudo_register_type().
	(sparc64_pseudo_register_read, sparc64_pseudo_register_write): Pseudo
	registers may have different numbers.
	(sparc64_store_floating_fields, sparc64_extract_floating_fields,
	sparc64_store_arguments): Pseudo registers may have different numbers;
	deal with it.
	(sparc64_init_abi): Initialize properly sparc 64-bit register names.

Comments

Yao Qi Jan. 9, 2017, 5:35 p.m. | #1
On 17-01-06 16:12:09, Ivo Raisr wrote:
> 

> I think I see the line now as well. Please find patch #1 together

> with a ChangeLog entry.

> The patch was successfully built and tested on Solaris sparc.

> After you find it ok, I will prepare patch #2.

> I.


> ChangeLog entry:

> 2017-01-06  Ivo Raisr  <ivo.raisr@oracle.com>

> 

> 	Split real and pseudo registers in preparation for registers provided

> 	by a target. Registers provided by target description can have more real

> 	registers and pseudo registers need to be positioned after them.


We don't document "changes" in this way.  If you think it is important
to mention them, put them in the commit log.

> @@ -57,6 +63,12 @@ struct gdbarch_tdep

>    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;

> +


These four fields are added, but not used at all, so could you move
them to patch #2?

-- 
Yao (齐尧)
Yao Qi Jan. 10, 2017, 9:29 a.m. | #2
On 17-01-09 22:18:22, Ivo Raisr wrote:

> ChangeLog entry:

> 2017-01-09  Ivo Raisr  <ivo.raisr@oracle.com>

> 

> 	Split real and pseudo registers.

> 	* sparc-tdep.h: Separate real and pseudo registers.


We describe the changes in the ChangeLog, so the change can be described
like this:

	* sparc-tdep.h (SPARC_CORE_REGISTERS): New macro.
	(sparc32_pseudo_regnum): New enum.

> 	* sparc64-tdep.h: Separate real and pseudo registers.


	* sparc64-tdep.h (sparc64_pseudo_regnum): New enum.

> 	* sparc-tdep.c (sparc32_pseudo_register_name): New function returning

> 	pseudo register names on sparc 32-bit.


	"New function" should be enough to describe the change.

> 	(sparc32_register_name): Use sparc32_pseudo_register_name().

> 	(sparc32_pseudo_register_type): New function returning pseudo register

> 	types on sparc 32-bit.

> 	(sparc32_register_type): Use sparc32_pseudo_register_type().

> 	(sparc32_pseudo_register_read, sparc32_pseudo_register_write): Pseudo

> 	registers may have different numbers.

> 	* sparc64-tdep.c (sparc64_pseudo_register_name): New function returning

> 	pseudo register names on sparc 64-bit.

> 	(sparc64_register_name): Use sparc64_pseudo_register_name().

> 	(sparc64_pseudo_register_type): New function returning pseudo register

> 	types on sparc 64-bit.

> 	(sparc64_register_type): Use sparc64_pseudo_register_type().

> 	(sparc64_pseudo_register_read, sparc64_pseudo_register_write): Pseudo

> 	registers may have different numbers.

> 	(sparc64_store_floating_fields, sparc64_extract_floating_fields,

> 	sparc64_store_arguments): Pseudo registers may have different numbers;

> 	deal with it.


> --- a/gdb/sparc-tdep.c	2016-02-09 19:19:39.000000000 +0000

> +++ gdb-7.11/gdb/sparc-tdep.c	2017-01-09 13:11:30.421265402 +0000

> @@ -295,20 +295,23 @@ sparc_structure_or_union_p (const struct

>  }

>  

>  /* 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 };


They are not used in this patch at all.  Should be moved to patch #2.

>  

>  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.  */

> @@ -327,17 +330,26 @@ static const char *sparc32_pseudo_regist

>  #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)


Don't insert the new function between sparc32_register_name and its
comments.  We also need comments to sparc32_pseudo_register_name.

/* Return the name of pseudo register REGNUM.  */

static const char *
sparc32_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
....

/* Return the name of register REGNUM.  */

static const char *
sparc32_register_name (struct gdbarch *gdbarch, int regnum)

>  /* 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)


Likewise, don't insert sparc32_pseudo_register_type between
sparc32_register_type and its type.

> --- a/gdb/sparc64-tdep.c	2016-02-09 19:19:39.000000000 +0000

> +++ gdb-7.11/gdb/sparc64-tdep.c	2017-01-09 13:11:51.858903807 +0000

> @@ -226,28 +226,29 @@ sparc64_fprs_type (struct gdbarch *gdbar

>  

>  

>  /* 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 };


They are not used, should be moved to patch #2.

> @@ -273,28 +274,57 @@ static const char *sparc64_pseudo_regist

>  #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)


sparc64_pseudo_register_name is added between sparc64_register_name and
its comments.

> +{

> +  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)

>  {

> -  if (regnum >= 0 && regnum < SPARC64_NUM_REGS)

> +  if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch))

>      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];

> -

> -  return NULL;

> +  return sparc64_pseudo_register_name (gdbarch, regnum);

>  }

>  

>  /* 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)


Likewise.

> +{

> +  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 builtin_type (gdbarch)->builtin_int64;

> +  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);

> +}

>  


-- 
Yao (齐尧)
Yao Qi Jan. 11, 2017, 3:46 p.m. | #3
On 17-01-11 14:14:10, Ivo Raisr wrote:

Patch is good to me, some nits below.  Fix these nits, and then you
can push it in!

> ChangeLog entry:

> 2017-01-11  Ivo Raisr  <ivo.raisr@oracle.com>

> 

> 	Split real and pseudo registers.

> 	* sparc-tdep.h (SPARC_CORE_REGISTERS): New macro.

> 	(sparc32_pseudo_regnum): New enum.

> 	* sparc64-tdep.h (sparc64_pseudo_regnum): New enum.

> 	* sparc-tdep.c (SPARC32_FPU_REGISTERS): New macro.

> 	(SPARC32_CP0_REGISTERS): New macro.

> 	(sparc32_pseudo_register_name): New function.

> 	(sparc32_register_name): Use sparc32_pseudo_register_name().

	
	(sparc32_register_name): Use sparc32_pseudo_register_name.

> 	(sparc32_pseudo_register_type): New function.

> 	(sparc32_register_type): Use sparc32_pseudo_register_type().


	Likewise.

> 	(sparc32_pseudo_register_read, sparc32_pseudo_register_write): Pseudo

> 	registers may have different numbers.

	
	(sparc32_pseudo_register_read, sparc32_pseudo_register_write): Handle
	pseudo register numbers.

> 	* sparc64-tdep.c SPARC64_FPU_REGISTERS): New macro.

> 	(SPARC64_CP0_REGISTERS): New macro.

> 	(sparc64_pseudo_register_name): New function.

> 	(sparc64_register_name): Use sparc64_pseudo_register_name().

> 	(sparc64_pseudo_register_type): New function.

> 	(sparc64_register_type): Use sparc64_pseudo_register_type().

> 	(sparc64_pseudo_register_read, sparc64_pseudo_register_write): Pseudo

> 	registers may have different numbers.

> 	(sparc64_store_floating_fields, sparc64_extract_floating_fields,

> 	sparc64_store_arguments): Pseudo registers may have different numbers;

> 	deal with it.


> --- a/gdb/sparc-tdep.h	2016-02-09 19:19:39.000000000 +0000

> +++ gdb-7.11/gdb/sparc-tdep.h	2017-01-09 13:26:11.749929515 +0000

> @@ -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;

> @@ -85,7 +91,7 @@ struct gdbarch_tdep

>  

>  enum sparc_regnum

>  {

> -  SPARC_G0_REGNUM,		/* %g0 */

> +  SPARC_G0_REGNUM = 0,		/* %g0 */

>    SPARC_G1_REGNUM,

>    SPARC_G2_REGNUM,

>    SPARC_G3_REGNUM,

> @@ -140,9 +146,12 @@ enum sparc32_regnum

>    SPARC32_NPC_REGNUM,		/* %npc */

>    SPARC32_FSR_REGNUM,		/* %fsr */

>    SPARC32_CSR_REGNUM,		/* %csr */

> +};

>  

> -  /* Pseudo registers.  */

> -  SPARC32_D0_REGNUM,		/* %d0 */

> +/* Pseudo registers.  */

> +enum sparc32_pseudo_regnum

> +{

> +  SPARC32_D0_REGNUM = 0,	/* %d0 */

>    SPARC32_D30_REGNUM		/* %d30 */

>    = SPARC32_D0_REGNUM + 15

>  };

> --- a/gdb/sparc-tdep.c	2016-02-09 19:19:39.000000000 +0000

> +++ gdb-7.11/gdb/sparc-tdep.c	2017-01-11 04:23:28.543904210 +0000

> @@ -295,20 +295,19 @@ sparc_structure_or_union_p (const struct

>  }

>  

>  /* 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 *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.  */

> @@ -326,18 +325,28 @@ static const char *sparc32_pseudo_regist

>  /* Total number of pseudo registers.  */

>  #define SPARC32_NUM_PSEUDO_REGS ARRAY_SIZE (sparc32_pseudo_register_names)

>  

> -/* Return the name of register REGNUM.  */

> +/* Return the name of pseudo register REGNUM.  */


Add a blank line between function and its comment.

> +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);

> +}

> +

> +/* Return the name of register REGNUM.  */


Likewise.

>  static const char *

>  sparc32_register_name (struct gdbarch *gdbarch, int regnum)

>  {

> -  if (regnum >= 0 && regnum < SPARC32_NUM_REGS)

> +  if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch))

>      return sparc32_register_names[regnum];

>  

> -  if (regnum < SPARC32_NUM_REGS + SPARC32_NUM_PSEUDO_REGS)

> -    return sparc32_pseudo_register_names[regnum - SPARC32_NUM_REGS];

> -

> -  return NULL;

> +  return sparc32_pseudo_register_name (gdbarch, regnum);

>  }

>  

>  /* Construct types for ISA-specific registers.  */

> @@ -398,17 +407,28 @@ sparc_fsr_type (struct gdbarch *gdbarch)

>  }

>  

>  /* Return the GDB type object for the "standard" data type of data in

> -   register REGNUM.  */

> +   pseudo register REGNUM.  */


Likewise.

> +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);

> +}

>  

> +/* Return the GDB type object for the "standard" data type of data in

> +   register REGNUM.  */


Likewise.

>  static struct type *

>  sparc32_register_type (struct gdbarch *gdbarch, int regnum)

>  {

>    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;

>  


-- 
Yao (齐尧)
Jose E. Marchesi Jan. 16, 2017, 4:50 p.m. | #4
> On 17-01-11 14:14:10, Ivo Raisr wrote:

    >

    > Patch is good to me, some nits below.  Fix these nits, and then you

    > can push it in!

    I fixed all the nits (see attached).
    Thank you for your review!
    
    However I assume I don't have write access to gdb's git repository [1]
    as the ssh authentication would surely ask for some credentials which
    I don't posses.

I just pushed this patch in your behalf.
Salud!
Pedro Alves Jan. 25, 2017, 3:46 p.m. | #5
(I know I'm quite behind this thread.)

On 01/06/2017 03:12 PM, Ivo Raisr wrote:
> 

> ChangeLog entry:

> 2017-01-06  Ivo Raisr  <ivo.raisr@oracle.com>

> 

> 	Split real and pseudo registers in preparation for registers provided

> 	by a target. Registers provided by target description can have more real

> 	registers and pseudo registers need to be positioned after them.


I don't quite understand this rationale, and I'm wondering if there's
a misunderstanding of register numbering somewhere (maybe mine!).

What exactly would go wrong if you just added the new registers
between the existing raw and pseudo registers?  Other ports do
that routinely.

Thanks,
Pedro Alves
Ivo Raisr Jan. 25, 2017, 4:05 p.m. | #6
On 25.1.2017 16:46, Pedro Alves wrote:
> (I know I'm quite behind this thread.)

>

> On 01/06/2017 03:12 PM, Ivo Raisr wrote:

>>

>> ChangeLog entry:

>> 2017-01-06  Ivo Raisr  <ivo.raisr@oracle.com>

>>

>> 	Split real and pseudo registers in preparation for registers provided

>> 	by a target. Registers provided by target description can have more real

>> 	registers and pseudo registers need to be positioned after them.

>

> I don't quite understand this rationale, and I'm wondering if there's

> a misunderstanding of register numbering somewhere (maybe mine!).

>

> What exactly would go wrong if you just added the new registers

> between the existing raw and pseudo registers?  Other ports do

> that routinely.


Good question.
The rationale is target provided registers.
Consider a typical Valgrind use case where target (gdbserver stub 
implemented inside Valgrind) supplies 3 times more raw registers than 
the architecture normally supports.
One set mimics the "normal" registers, the other two sets are shadow 
copies used internally by Memcheck tool to keep track of 
defined/undefined bits and their origins.

So when gdb'ing ordinary process, you have:
- raw registers (one set)
- pseudo registers

However when gdb'ing Valgrind'ed process over gdb remote protocol
with --vgdb-shadow-registers=yes, target provides:
- first set of raw registers (describes guest state)
- second set of raw registers (describes the first shadow copy)
- third set of raw registers (describes the second shadow copy)
- pseudo registers (actually provided by gdb)

So this means pseudo registers numbering must be flexible.
Other targets (such as s390x, aarch64, amd64) do it in similar ways.

Kind regards,
I.
Pedro Alves Jan. 25, 2017, 4:23 p.m. | #7
On 01/25/2017 04:05 PM, Ivo Raisr wrote:
> 

> 

> On 25.1.2017 16:46, Pedro Alves wrote:

>> (I know I'm quite behind this thread.)

>>

>> On 01/06/2017 03:12 PM, Ivo Raisr wrote:

>>>

>>> ChangeLog entry:

>>> 2017-01-06  Ivo Raisr  <ivo.raisr@oracle.com>

>>>

>>>     Split real and pseudo registers in preparation for registers

>>> provided

>>>     by a target. Registers provided by target description can have

>>> more real

>>>     registers and pseudo registers need to be positioned after them.

>>

>> I don't quite understand this rationale, and I'm wondering if there's

>> a misunderstanding of register numbering somewhere (maybe mine!).

>>

>> What exactly would go wrong if you just added the new registers

>> between the existing raw and pseudo registers?  Other ports do

>> that routinely.

> 

> Good question.

> The rationale is target provided registers.

> Consider a typical Valgrind use case where target (gdbserver stub

> implemented inside Valgrind) supplies 3 times more raw registers than

> the architecture normally supports.

> One set mimics the "normal" registers, the other two sets are shadow

> copies used internally by Memcheck tool to keep track of

> defined/undefined bits and their origins.

> 

> So when gdb'ing ordinary process, you have:

> - raw registers (one set)

> - pseudo registers

> 

> However when gdb'ing Valgrind'ed process over gdb remote protocol

> with --vgdb-shadow-registers=yes, target provides:

> - first set of raw registers (describes guest state)

> - second set of raw registers (describes the first shadow copy)

> - third set of raw registers (describes the second shadow copy)

> - pseudo registers (actually provided by gdb)

> 

> So this means pseudo registers numbering must be flexible.

> Other targets (such as s390x, aarch64, amd64) do it in similar ways.


Ah, OK.  I see what you're doing now.  Thanks for clarifying!

Thanks,
Pedro Alves
Ivo Raisr Jan. 25, 2017, 4:25 p.m. | #8
On 25.1.2017 17:23, Pedro Alves wrote:
> Ah, OK.  I see what you're doing now.  Thanks for clarifying!


You are welcome.
Would you mind letting me know if the second patch for this series
is ok to commit? All the issues and nits reported by Yao have been fixed.
Thank you,
I.
Yao Qi Jan. 25, 2017, 4:44 p.m. | #9
On Wed, Jan 25, 2017 at 4:25 PM, Ivo Raisr <ivo.raisr@oracle.com> wrote:
>

> You are welcome.

> Would you mind letting me know if the second patch for this series

> is ok to commit? All the issues and nits reported by Yao have been fixed.

> Thank you,


I am reviewing it now.

-- 
Yao (齐尧)

Patch

--- a/gdb/sparc-tdep.h	2016-02-09 19:19:39.000000000 +0000
+++ b/gdb/sparc-tdep.h	2017-01-06 04:12:14.291269940 +0000
@@ -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;
@@ -57,6 +63,12 @@  struct gdbarch_tdep
   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;
@@ -85,7 +97,7 @@  struct gdbarch_tdep
 
 enum sparc_regnum
 {
-  SPARC_G0_REGNUM,		/* %g0 */
+  SPARC_G0_REGNUM = 0,		/* %g0 */
   SPARC_G1_REGNUM,
   SPARC_G2_REGNUM,
   SPARC_G3_REGNUM,
@@ -140,9 +152,12 @@  enum sparc32_regnum
   SPARC32_NPC_REGNUM,		/* %npc */
   SPARC32_FSR_REGNUM,		/* %fsr */
   SPARC32_CSR_REGNUM,		/* %csr */
+};
 
-  /* Pseudo registers.  */
-  SPARC32_D0_REGNUM,		/* %d0 */
+/* Pseudo registers.  */
+enum sparc32_pseudo_regnum
+{
+  SPARC32_D0_REGNUM = 0,	/* %d0 */
   SPARC32_D30_REGNUM		/* %d30 */
   = SPARC32_D0_REGNUM + 15
 };
--- a/gdb/sparc-tdep.c	2016-02-09 19:19:39.000000000 +0000
+++ b/gdb/sparc-tdep.c	2017-01-06 04:12:14.293179005 +0000
@@ -295,20 +295,23 @@  sparc_structure_or_union_p (const struct
 }
 
 /* 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.  */
@@ -327,17 +330,26 @@  static const char *sparc32_pseudo_regist
 #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)
 {
-  if (regnum >= 0 && regnum < SPARC32_NUM_REGS)
+  if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch))
     return sparc32_register_names[regnum];
 
-  if (regnum < SPARC32_NUM_REGS + SPARC32_NUM_PSEUDO_REGS)
-    return sparc32_pseudo_register_names[regnum - SPARC32_NUM_REGS];
-
-  return NULL;
+  return sparc32_pseudo_register_name (gdbarch, regnum);
 }
 
 /* Construct types for ISA-specific registers.  */
@@ -399,6 +411,18 @@  sparc_fsr_type (struct gdbarch *gdbarch)
 
 /* 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)
@@ -406,9 +430,6 @@  sparc32_register_type (struct gdbarch *g
   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;
 
@@ -421,6 +442,9 @@  sparc32_register_type (struct gdbarch *g
   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;
 }
 
@@ -431,6 +455,7 @@  sparc32_pseudo_register_read (struct gdb
 {
   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);
@@ -445,6 +470,7 @@  sparc32_pseudo_register_write (struct gd
 			       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);
@@ -1678,6 +1704,10 @@  sparc32_gdbarch_init (struct gdbarch_inf
   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);
--- a/gdb/sparc64-tdep.h	2016-02-09 19:19:39.000000000 +0000
+++ b/gdb/sparc64-tdep.h	2017-01-06 04:12:14.294032452 +0000
@@ -56,9 +56,12 @@  enum sparc64_regnum
   SPARC64_FSR_REGNUM,		/* %fsr */
   SPARC64_FPRS_REGNUM,		/* %fprs */
   SPARC64_Y_REGNUM,		/* %y */
+};
 
-  /* Pseudo registers.  */
-  SPARC64_CWP_REGNUM,		/* %cwp */
+/* Pseudo registers.  */
+enum sparc64_pseudo_regnum
+{
+  SPARC64_CWP_REGNUM = 0,	/* %cwp */
   SPARC64_PSTATE_REGNUM,	/* %pstate */
   SPARC64_ASI_REGNUM,		/* %asi */
   SPARC64_CCR_REGNUM,		/* %ccr */
--- a/gdb/sparc64-tdep.c	2016-02-09 19:19:39.000000000 +0000
+++ b/gdb/sparc64-tdep.c	2017-01-06 04:12:14.295659262 +0000
@@ -226,28 +226,29 @@  sparc64_fprs_type (struct gdbarch *gdbar
 
 
 /* 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.  */
@@ -273,28 +274,57 @@  static const char *sparc64_pseudo_regist
 #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)
 {
-  if (regnum >= 0 && regnum < SPARC64_NUM_REGS)
+  if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch))
     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];
-
-  return NULL;
+  return sparc64_pseudo_register_name (gdbarch, regnum);
 }
 
 /* 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 builtin_type (gdbarch)->builtin_int64;
+  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)
 {
   /* Raw registers.  */
-
   if (regnum == SPARC_SP_REGNUM || regnum == SPARC_FP_REGNUM)
     return builtin_type (gdbarch)->builtin_data_ptr;
   if (regnum >= SPARC_G0_REGNUM && regnum <= SPARC_I7_REGNUM)
@@ -319,19 +349,8 @@  sparc64_register_type (struct gdbarch *g
     return builtin_type (gdbarch)->builtin_int64;
 
   /* Pseudo registers.  */
-
-  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 builtin_type (gdbarch)->builtin_int64;
-  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;
+  if (regnum >= gdbarch_num_regs (gdbarch))
+    return sparc64_pseudo_register_type (gdbarch, regnum);
 
   internal_error (__FILE__, __LINE__, _("invalid regnum"));
 }
@@ -344,7 +363,7 @@  sparc64_pseudo_register_read (struct gdb
   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)
     {
@@ -421,7 +440,8 @@  sparc64_pseudo_register_write (struct gd
 			       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)
     {
@@ -638,6 +658,7 @@  static void
 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);
@@ -652,14 +673,15 @@  sparc64_store_floating_fields (struct re
 	  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)
 	{
 	  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
@@ -712,6 +734,8 @@  static void
 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);
@@ -721,14 +745,15 @@  sparc64_extract_floating_fields (struct
 	{
 	  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)
 	{
 	  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
@@ -911,13 +936,13 @@  sparc64_store_arguments (struct regcache
 	  /* 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);
@@ -932,12 +957,14 @@  sparc64_store_arguments (struct regcache
 	      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)
 	    {
@@ -952,7 +979,8 @@  sparc64_store_arguments (struct regcache
 	      valbuf = buf;
 	      len = 8;
 	      if (element < 16)
-		regnum = SPARC64_D0_REGNUM + element;
+		regnum = gdbarch_num_regs (gdbarch) + SPARC64_D0_REGNUM
+                         + element;
 	    }
 	}
       else
@@ -969,19 +997,24 @@  sparc64_store_arguments (struct regcache
 
 	  /* 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.  */
@@ -1185,6 +1218,10 @@  sparc64_init_abi (struct gdbarch_info in
 
   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);