public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* RFC: partially available registers
@ 2011-07-13 20:17 Tom Tromey
  2011-07-14  4:24 ` Daniel Jacobowitz
  0 siblings, 1 reply; 28+ messages in thread
From: Tom Tromey @ 2011-07-13 20:17 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 2243 bytes --]

I have a test case (I've attached the C source) which exhibits bad
behavior in gdb on x86-64:

(gdb) b 30
Breakpoint 1 at 0x400463: file typeddwarf.c, line 30.
(gdb) r
Starting program: /tmp/t 

Breakpoint 1, f1 (a=<unavailable>, b=<unavailable>, c=<unavailable>, 
    d=<unavailable>, e=<unavailable>, f=6, g=7, h=8, i=9) at typeddwarf.c:30
30	}
(gdb) p s
$1 = <unavailable>


However, 's' is not really unavailable:

(gdb) info addr s
Symbol "s" is a complex DWARF expression:
     0: DW_OP_GNU_regval_type<double [0x2d]> [$xmm2]
     3: DW_OP_GNU_convert<long int [0x42]>
     5: DW_OP_GNU_convert<0>
     7: DW_OP_stack_value
.
(gdb) p (long) $xmm2.v2_double[0]
$3 = 3


The issue here is that DWARF uses the same register numbers for the XMM
and YMM registers, and in this case the high parts of the YMM registers
are unavailable.  This causes the special code in
i386_pseudo_register_read for YMM to return REG_UNAVAILABLE.


This patch fixes the problem by letting an arch register a new
pseudo_register_read_value method, which is responsible for constructing 
a struct value for the register.  This gives us a chance to mark
just some bits unavailable.

With the modified gdb, the test works:

(gdb) b 30
Breakpoint 1 at 0x400463: file typeddwarf.c, line 30.
(gdb) r
Starting program: /tmp/t 

Breakpoint 1, f1 (a=1, b=2, c=3, d=4, e=5, f=6, g=7, h=8, i=9)
    at typeddwarf.c:30
30	}
(gdb) p s
$1 = 3


I would appreciate feedback on this patch.

I considered several other approaches:

* Put the XCR0 bits into the regcache.  This would let us dynamically
  decide whether to return the XMM or YMM register.  This seemed to mean
  treating XCR0 as a real register (which AFAICT it is not, right now),
  which meant also gdbserver changes.

* Rather than a way to return values, have a different API, say one
  where gdb requests the first N bytes of a register.  This may still be
  cleaner, I am not sure.  Optionally this could be the only way,
  meaning a patch touching most existing callers.


I don't think this patch yet hits all the spots I would need to change.
E.g., "print $ymm2" shows all fields as <unavailable>, but that is
incorrect.

I'll turn the test case into part of the patch when I finalize this
change.

Tom


[-- Attachment #2: typeddwarf.c --]
[-- Type: text/plain, Size: 3763 bytes --]

/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
/* { dg-options "-g" } */

typedef __SIZE_TYPE__ size_t;
volatile int vv;
extern void *memcpy (void *, const void *, size_t);

__attribute__((noinline, noclone)) void
f1 (double a, double b, double c, float d, float e, int f, unsigned int g, long long h, unsigned long long i)
{
  double j = d;			/* { dg-final { gdb-test 29 "j" "4" } } */
  long long l;			/* { dg-final { gdb-test 29 "l" "4616189618054758400" } } */
  memcpy (&l, &j, sizeof (l));
  long long m;			/* { dg-final { gdb-test 29 "m" "4613937818241073152" } } */
  memcpy (&m, &c, sizeof (l));
  float n = i;			/* { dg-final { gdb-test 29 "n" "9" } } */
  double o = h;			/* { dg-final { gdb-test 29 "o" "8" } } */
  float p = g;			/* { dg-final { gdb-test 29 "p" "7" } } */
  double q = f;			/* { dg-final { gdb-test 29 "q" "6" } } */
  unsigned long long r = a;	/* { dg-final { gdb-test 29 "r" "1" } } */
  long long s = c;		/* { dg-final { gdb-test 29 "s" "3" } } */
  unsigned t = d;		/* { dg-final { gdb-test 29 "t" "4" } } */
  int u = b;			/* { dg-final { gdb-test 29 "u" "2" } } */
  float v = a;			/* { dg-final { gdb-test 29 "v" "1" } } */
  double w = d / 4.0;		/* { dg-final { gdb-test 29 "w" "1" } } */
  double x = a + b + 1.0;	/* { dg-final { gdb-test 29 "x" "4" } } */
  double y = b + c + 2.0;	/* { dg-final { gdb-test 29 "y" "7" } } */
  float z = d + e + 3.0f;	/* { dg-final { gdb-test 29 "z" "12" } } */
  vv++;
}

__attribute__((noinline, noclone)) void
f2 (double a, double b, double c, float d, float e, int f, unsigned int g, long long h, unsigned long long i)
{
  double j = d;			/* { dg-final { gdb-test 53 "j" "4" } } */
  long long l;			/* { dg-final { gdb-test 53 "l" "4616189618054758400" } } */
  memcpy (&l, &j, sizeof (l));
  long long m;			/* { dg-final { gdb-test 53 "m" "4613937818241073152" } } */
  memcpy (&m, &c, sizeof (l));
  float n = i;			/* { dg-final { gdb-test 53 "n" "9" } } */
  double o = h;			/* { dg-final { gdb-test 53 "o" "8" } } */
  float p = g;			/* { dg-final { gdb-test 53 "p" "7" } } */
  double q = f;			/* { dg-final { gdb-test 53 "q" "6" } } */
  unsigned long long r = a;	/* { dg-final { gdb-test 53 "r" "1" } } */
  long long s = c;		/* { dg-final { gdb-test 53 "s" "3" } } */
  unsigned t = d;		/* { dg-final { gdb-test 53 "t" "4" } } */
  int u = b;			/* { dg-final { gdb-test 53 "u" "2" } } */
  float v = a;			/* { dg-final { gdb-test 53 "v" "1" } } */
  double w = d / 4.0;		/* { dg-final { gdb-test 53 "w" "1" } } */
  double x = a + b - 3 + 1.0e20;/* { dg-final { gdb-test 53 "x" "1e+20" } } */
  double y = b + c * 7.0;	/* { dg-final { gdb-test 53 "y" "23" } } */
  float z = d + e + 3.0f;	/* { dg-final { gdb-test 53 "z" "12" } } */
  vv++;
  vv = a;
  vv = b;
  vv = c;
  vv = d;
  vv = e;
  vv = f;
  vv = g;
  vv = h;
  vv = i;
  vv = j;
}

__attribute__((noinline, noclone)) void
f3 (long long a, int b, long long c, unsigned d)
{
  long long w = (a > d) ? a : d;/* { dg-final { gdb-test 73 "w" "4" } } */
  long long x = a + b + 7;	/* { dg-final { gdb-test 73 "x" "10" } } */
  long long y = c + d + 0x912345678LL;/* { dg-final { gdb-test 73 "y" "38960125567" } } */
  int z = (x + y);		/* { dg-final { gdb-test 73 "z" "305419913" } } */
  vv++;
}

__attribute__((noinline, noclone)) void
f4 (_Decimal32 a, _Decimal64 b, _Decimal128 c)
{
  _Decimal32 w = a * 8.0DF + 6.0DF;/* { dg-final { gdb-test 82 "(int)w" "70" } } */
  _Decimal64 x = b / 8.0DD - 6.0DD;/* { dg-final { gdb-test 82 "(int)x" "-4" } } */
  _Decimal128 y = -c / 8.0DL;	/* { dg-final { gdb-test 82 "(int)y" "-8" } } */
  vv++;
}

int
main ()
{
  f1 (1.0, 2.0, 3.0, 4.0f, 5.0f, 6, 7, 8, 9);
  f2 (1.0, 2.0, 3.0, 4.0f, 5.0f, 6, 7, 8, 9);
  f3 (1, 2, 3, 4);
  f4 (8.0DF, 16.0DD, 64.0DL);
  return 0;
}

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: the patch --]
[-- Type: text/x-patch, Size: 11893 bytes --]

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 4062bf9..b404878 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,20 @@
 2011-07-13  Tom Tromey  <tromey@redhat.com>
 
+	* sentinel-frame.c (sentinel_frame_prev_register): Use
+	regcache_cooked_read_into_value.
+	* regcache.h (regcache_cooked_read_into_value): Declare.
+	* regcache.c (regcache_cooked_read_into_value): New function.
+	* i386-tdep.h (i386_pseudo_register_read_value): Declare.
+	* i386-tdep.c (i386_pseudo_register_read_value): New function.
+	(i386_gdbarch_init): Call set_gdbarch_pseudo_register_read_value.
+	* gdbarch.sh (pseudo_register_read_value): New method.
+	* gdbarch.c, gdbarch.h: Rebuild.
+	* findvar.c (value_from_register): Call get_frame_register_value.
+	* amd64-tdep.c (amd64_init_abi): Call
+	set_gdbarch_pseudo_register_read_value.
+
+2011-07-13  Tom Tromey  <tromey@redhat.com>
+
 	* dwarf2expr.c (execute_stack_op) <DW_OP_GNU_regval_type>: Use
 	value_from_contents for final conversion.
 
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index de62ac7..c728b53 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -2496,6 +2496,8 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   set_gdbarch_pseudo_register_read (gdbarch,
 				    amd64_pseudo_register_read);
+  set_gdbarch_pseudo_register_read_value (gdbarch,
+					  i386_pseudo_register_read_value);
   set_gdbarch_pseudo_register_write (gdbarch,
 				     amd64_pseudo_register_write);
 
diff --git a/gdb/findvar.c b/gdb/findvar.c
index a700c02..59e86ef 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -647,14 +647,16 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
   else
     {
       int len = TYPE_LENGTH (type);
+      struct value *v2;
 
       /* Construct the value.  */
       v = gdbarch_value_from_register (gdbarch, type, regnum, frame);
 
       /* Get the data.  */
-      ok = get_frame_register_bytes (frame, regnum, value_offset (v), len,
-				     value_contents_raw (v),
-				     &optim, &unavail);
+      v2 = get_frame_register_value (frame, regnum);
+
+      value_contents_copy (v, 0, v2, 0, len);
+      ok = 1;
     }
 
   if (!ok)
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 1e65c17..0c1bcf0 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -161,6 +161,7 @@ struct gdbarch
   gdbarch_write_pc_ftype *write_pc;
   gdbarch_virtual_frame_pointer_ftype *virtual_frame_pointer;
   gdbarch_pseudo_register_read_ftype *pseudo_register_read;
+  gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value;
   gdbarch_pseudo_register_write_ftype *pseudo_register_write;
   int num_regs;
   int num_pseudo_regs;
@@ -313,6 +314,7 @@ struct gdbarch startup_gdbarch =
   0,  /* write_pc */
   legacy_virtual_frame_pointer,  /* virtual_frame_pointer */
   0,  /* pseudo_register_read */
+  0,  /* pseudo_register_read_value */
   0,  /* pseudo_register_write */
   0,  /* num_regs */
   0,  /* num_pseudo_regs */
@@ -594,6 +596,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of write_pc, has predicate.  */
   /* Skip verify of virtual_frame_pointer, invalid_p == 0 */
   /* Skip verify of pseudo_register_read, has predicate.  */
+  /* Skip verify of pseudo_register_read_value, has predicate.  */
   /* Skip verify of pseudo_register_write, has predicate.  */
   if (gdbarch->num_regs == -1)
     fprintf_unfiltered (log, "\n\tnum_regs");
@@ -1085,6 +1088,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: pseudo_register_read = <%s>\n",
                       host_address_to_string (gdbarch->pseudo_register_read));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_pseudo_register_read_value_p() = %d\n",
+                      gdbarch_pseudo_register_read_value_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: pseudo_register_read_value = <%s>\n",
+                      host_address_to_string (gdbarch->pseudo_register_read_value));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: gdbarch_pseudo_register_write_p() = %d\n",
                       gdbarch_pseudo_register_write_p (gdbarch));
   fprintf_unfiltered (file,
@@ -1700,6 +1709,30 @@ set_gdbarch_pseudo_register_read (struct gdbarch *gdbarch,
 }
 
 int
+gdbarch_pseudo_register_read_value_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->pseudo_register_read_value != NULL;
+}
+
+int
+gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, struct value *result)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->pseudo_register_read_value != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_pseudo_register_read_value called\n");
+  return gdbarch->pseudo_register_read_value (gdbarch, regcache, cookednum, result);
+}
+
+void
+set_gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch,
+                                        gdbarch_pseudo_register_read_value_ftype pseudo_register_read_value)
+{
+  gdbarch->pseudo_register_read_value = pseudo_register_read_value;
+}
+
+int
 gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 50221d7..5f99ded 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -216,6 +216,12 @@ typedef enum register_status (gdbarch_pseudo_register_read_ftype) (struct gdbarc
 extern enum register_status gdbarch_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, gdb_byte *buf);
 extern void set_gdbarch_pseudo_register_read (struct gdbarch *gdbarch, gdbarch_pseudo_register_read_ftype *pseudo_register_read);
 
+extern int gdbarch_pseudo_register_read_value_p (struct gdbarch *gdbarch);
+
+typedef int (gdbarch_pseudo_register_read_value_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, struct value *result);
+extern int gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, struct value *result);
+extern void set_gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value);
+
 extern int gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch);
 
 typedef void (gdbarch_pseudo_register_write_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, const gdb_byte *buf);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index a628f8c..1e2ad53 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -418,6 +418,7 @@ F:void:write_pc:struct regcache *regcache, CORE_ADDR val:regcache, val
 m:void:virtual_frame_pointer:CORE_ADDR pc, int *frame_regnum, LONGEST *frame_offset:pc, frame_regnum, frame_offset:0:legacy_virtual_frame_pointer::0
 #
 M:enum register_status:pseudo_register_read:struct regcache *regcache, int cookednum, gdb_byte *buf:regcache, cookednum, buf
+M:int:pseudo_register_read_value:struct regcache *regcache, int cookednum, struct value *result:regcache, cookednum, result
 M:void:pseudo_register_write:struct regcache *regcache, int cookednum, const gdb_byte *buf:regcache, cookednum, buf
 #
 v:int:num_regs:::0:-1
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 366d0fa..7a16b4a 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -2854,6 +2854,47 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
   return REG_VALID;
 }
 
+int
+i386_pseudo_register_read_value (struct gdbarch *gdbarch,
+				 struct regcache *regcache,
+				 int regnum,
+				 struct value *result)
+{
+  gdb_byte raw_buf[MAX_REGISTER_SIZE];
+  gdb_byte *buf;
+  struct gdbarch_tdep *tdep;
+  enum register_status status;
+
+  if (!i386_ymm_regnum_p (gdbarch, regnum))
+    return 0;
+
+  tdep = gdbarch_tdep (gdbarch);
+  buf = value_contents_raw (result);
+
+  regnum -= tdep->ymm0_regnum;
+
+  /* Extract (always little endian).  Read lower 128bits.  */
+  status = regcache_raw_read (regcache,
+			      I387_XMM0_REGNUM (tdep) + regnum,
+			      raw_buf);
+
+  if (status != REG_VALID)
+    mark_value_bytes_unavailable (result, 0, 16);
+  else
+    memcpy (buf, raw_buf, 16);
+
+  /* Read upper 128bits.  */
+  status = regcache_raw_read (regcache,
+			      tdep->ymm0h_regnum + regnum,
+			      raw_buf);
+  if (status != REG_VALID)
+    mark_value_bytes_unavailable (result, 16, 32);
+  else
+    memcpy (buf + 16, raw_buf, 16);
+
+  return 1;
+}
+
 void
 i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
 			    int regnum, const gdb_byte *buf)
@@ -7334,6 +7375,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* Pseudo registers may be changed by amd64_init_abi.  */
   set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read);
+  set_gdbarch_pseudo_register_read_value (gdbarch,
+					  i386_pseudo_register_read_value);
   set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write);
 
   set_tdesc_pseudo_register_type (gdbarch, i386_pseudo_register_type);
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 7fc719c..97fa258 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -315,6 +315,12 @@ extern enum register_status i386_pseudo_register_read (struct gdbarch *gdbarch,
 						       struct regcache *regcache,
 						       int regnum,
 						       gdb_byte *buf);
+
+extern int i386_pseudo_register_read_value (struct gdbarch *gdbarch,
+					    struct regcache *regcache,
+					    int regnum,
+					    struct value *result);
+
 extern void i386_pseudo_register_write (struct gdbarch *gdbarch,
 					struct regcache *regcache,
 					int regnum, const gdb_byte *buf);
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 41f218d..2ddcd4c 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -714,6 +714,23 @@ regcache_cooked_read (struct regcache *regcache, int regnum, gdb_byte *buf)
 					 regnum, buf);
 }
 
+void
+regcache_cooked_read_into_value (struct regcache *regcache, int regnum,
+				 struct value *result)
+{
+  gdb_assert (regnum >= 0);
+  gdb_assert (regnum < regcache->descr->nr_cooked_registers);
+  if (!gdbarch_pseudo_register_read_value_p (regcache->descr->gdbarch)
+      || !gdbarch_pseudo_register_read_value (regcache->descr->gdbarch,
+					      regcache, regnum, result))
+    {
+      if (regcache_cooked_read (regcache, regnum,
+				value_contents_raw (result)) == REG_UNAVAILABLE)
+	mark_value_bytes_unavailable (result, 0,
+				      TYPE_LENGTH (value_type (result)));
+    }
+}
+
 enum register_status
 regcache_cooked_read_signed (struct regcache *regcache, int regnum,
 			     LONGEST *val)
diff --git a/gdb/regcache.h b/gdb/regcache.h
index 3708c86..01ee30b 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -104,6 +104,9 @@ enum register_status regcache_cooked_read (struct regcache *regcache,
 void regcache_cooked_write (struct regcache *regcache, int rawnum,
 			    const gdb_byte *buf);
 
+void regcache_cooked_read_into_value (struct regcache *regcache, int regnum,
+				      struct value *result);
+
 /* Read a register as a signed/unsigned quantity.  */
 extern enum register_status
   regcache_cooked_read_signed (struct regcache *regcache,
diff --git a/gdb/sentinel-frame.c b/gdb/sentinel-frame.c
index 6c2f3e0..53d82ba 100644
--- a/gdb/sentinel-frame.c
+++ b/gdb/sentinel-frame.c
@@ -62,10 +62,7 @@ sentinel_frame_prev_register (struct frame_info *this_frame,
   /* Use the regcache_cooked_read() method so that it, on the fly,
      constructs either a raw or pseudo register from the raw
      register cache.  */
-  if (regcache_cooked_read (cache->regcache,
-			    regnum,
-			    value_contents_raw (value)) == REG_UNAVAILABLE)
-    mark_value_bytes_unavailable (value, 0, TYPE_LENGTH (regtype));
+  regcache_cooked_read_into_value (cache->regcache, regnum, value);
 
   return value;
 }

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

* Re: RFC: partially available registers
  2011-07-13 20:17 RFC: partially available registers Tom Tromey
@ 2011-07-14  4:24 ` Daniel Jacobowitz
  2011-07-15 20:52   ` Tom Tromey
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Jacobowitz @ 2011-07-14  4:24 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

I'm too stale to properly review this patch, but I have some comments.

On Wed, Jul 13, 2011 at 1:44 PM, Tom Tromey <tromey@redhat.com> wrote:
> This patch fixes the problem by letting an arch register a new
> pseudo_register_read_value method, which is responsible for constructing
> a struct value for the register.  This gives us a chance to mark
> just some bits unavailable.

I think this is the right approach.  We should move more towards
values, not away; in particular, I do not prefer this alternative:

> * Rather than a way to return values, have a different API, say one
>  where gdb requests the first N bytes of a register.

As for the patch itself:

* Some documentation on the gdbarch method would be nice, in
particular, the return value.  Does 0 mean "not a pseudo"?

* Stale comment in sentinel_frame_prev_register.

* I am not happy about having to implement both
gdbarch_pseudo_register_read and gdbarch_pseudo_register_read_value,
depending on which regcache read function was called.  So for a final
version, is it practical to push this down and only call the value
version if it is registered?  That means implementing the existing
regcache read in terms of the new one, instead of the other way
around.

--
Thanks,
Daniel

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

* Re: RFC: partially available registers
  2011-07-14  4:24 ` Daniel Jacobowitz
@ 2011-07-15 20:52   ` Tom Tromey
  2011-07-18  4:15     ` Daniel Jacobowitz
                       ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: Tom Tromey @ 2011-07-15 20:52 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches

>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:

Daniel> As for the patch itself:
Daniel> * Some documentation on the gdbarch method would be nice, in
Daniel> particular, the return value.  Does 0 mean "not a pseudo"?

Yeah, I left that out for the initial change, but I think I shouldn't
have.

I find gdbarch.sh very hard to read.  Does anybody else?

Daniel> * I am not happy about having to implement both
Daniel> gdbarch_pseudo_register_read and gdbarch_pseudo_register_read_value,
Daniel> depending on which regcache read function was called.  So for a final
Daniel> version, is it practical to push this down and only call the value
Daniel> version if it is registered?  That means implementing the existing
Daniel> regcache read in terms of the new one, instead of the other way
Daniel> around.

I will look at it.  Thanks for looking at this.

Tom

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

* Re: RFC: partially available registers
  2011-07-15 20:52   ` Tom Tromey
@ 2011-07-18  4:15     ` Daniel Jacobowitz
  2011-07-20 20:14       ` Pedro Alves
  2011-07-20 18:49     ` Sergio Durigan Junior
  2011-07-20 20:46     ` Tom Tromey
  2 siblings, 1 reply; 28+ messages in thread
From: Daniel Jacobowitz @ 2011-07-18  4:15 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Fri, Jul 15, 2011 at 4:48 PM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
>
> Daniel> As for the patch itself:
> Daniel> * Some documentation on the gdbarch method would be nice, in
> Daniel> particular, the return value.  Does 0 mean "not a pseudo"?
>
> Yeah, I left that out for the initial change, but I think I shouldn't
> have.
>
> I find gdbarch.sh very hard to read.  Does anybody else?

Incredibly.  Someone please flip us to C++ and use a normal construct
for this...

-- 
Thanks,
Daniel

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

* Re: RFC: partially available registers
  2011-07-15 20:52   ` Tom Tromey
  2011-07-18  4:15     ` Daniel Jacobowitz
@ 2011-07-20 18:49     ` Sergio Durigan Junior
  2011-07-20 20:46     ` Tom Tromey
  2 siblings, 0 replies; 28+ messages in thread
From: Sergio Durigan Junior @ 2011-07-20 18:49 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Daniel Jacobowitz, gdb-patches

Tom Tromey <tromey@redhat.com> writes:

> I find gdbarch.sh very hard to read.  Does anybody else?

FWIW, me too (remembering the `catch syscall' days...).

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

* Re: RFC: partially available registers
  2011-07-18  4:15     ` Daniel Jacobowitz
@ 2011-07-20 20:14       ` Pedro Alves
  0 siblings, 0 replies; 28+ messages in thread
From: Pedro Alves @ 2011-07-20 20:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Daniel Jacobowitz, Tom Tromey

On Sunday 17 July 2011 21:26:17, Daniel Jacobowitz wrote:
> On Fri, Jul 15, 2011 at 4:48 PM, Tom Tromey <tromey@redhat.com> wrote:
> >>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
> >
> > Daniel> As for the patch itself:
> > Daniel> * Some documentation on the gdbarch method would be nice, in
> > Daniel> particular, the return value.  Does 0 mean "not a pseudo"?
> >
> > Yeah, I left that out for the initial change, but I think I shouldn't
> > have.
> >
> > I find gdbarch.sh very hard to read.  Does anybody else?
> 
> Incredibly.  Someone please flip us to C++ and use a normal construct
> for this...

Hey, gcc flipped this week.  We're running behind already.  :-)

-- 
Pedro Alves

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

* Re: RFC: partially available registers
  2011-07-15 20:52   ` Tom Tromey
  2011-07-18  4:15     ` Daniel Jacobowitz
  2011-07-20 18:49     ` Sergio Durigan Junior
@ 2011-07-20 20:46     ` Tom Tromey
  2011-07-20 20:53       ` Tom Tromey
                         ` (2 more replies)
  2 siblings, 3 replies; 28+ messages in thread
From: Tom Tromey @ 2011-07-20 20:46 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches

Daniel> * I am not happy about having to implement both
Daniel> gdbarch_pseudo_register_read and gdbarch_pseudo_register_read_value,
Daniel> depending on which regcache read function was called.  So for a final
Daniel> version, is it practical to push this down and only call the value
Daniel> version if it is registered?  That means implementing the existing
Daniel> regcache read in terms of the new one, instead of the other way
Daniel> around.

Tom> I will look at it.  Thanks for looking at this.

I looked into this, and I changed some things, but I did not change it
completely.

One thing I did change is that I made pseudo_register_read_into_value a
full replacement for pseudo_register_read.  A target should either
define one or the other.  I switched i386 and amd64 to the _value form.

I didn't rewrite regcache_cooked_read in terms of
regcache_cooked_read_into_value, because that is less efficient than
the reverse.

Tom

2011-07-20  Tom Tromey  <tromey@redhat.com>

	* amd64-tdep.c (amd64_pseudo_register_read_into_value): Rename
	from amd64_pseudo_register_read.  Change arguments.  Call
	mark_value_bytes_unavailable when needed.
	(amd64_init_abi): Use set_gdbarch_pseudo_register_read_value, not
	set_gdbarch_pseudo_register_read.
	* sentinel-frame.c (sentinel_frame_prev_register): Use
	regcache_cooked_read_into_value.
	* regcache.h (regcache_cooked_read_into_value): Declare.
	* regcache.c (regcache_cooked_read_into_value): New function.
	(regcache_cooked_read): Call
	gdbarch_pseudo_register_read_into_value if available.
	* i386-tdep.h (i386_pseudo_register_read_into_value): Declare.
	(i386_pseudo_register_read): Remove.
	* i386-tdep.c (i386_pseudo_register_read_into_value): Rename from
	i386_pseudo_register_read.  Change arguments.  Call
	mark_value_bytes_unavailable when needed.
	(i386_gdbarch_init): Call
	set_gdbarch_pseudo_register_read_into_value, not
	set_gdbarch_pseudo_register_read.
	* gdbarch.sh (pseudo_register_read_into_value): New method.
	* gdbarch.c, gdbarch.h: Rebuild.
	* findvar.c (value_from_register): Call get_frame_register_value.

2011-07-20  Tom Tromey  <tromey@redhat.com>

	* gdb.dwarf2/typeddwarf.c: XFAIL 'z' on x86-64.
	* gdb.dwarf2/typeddwarf.exp (xfail-gdb-test): Add arch_pattern
	argument.
	* gdb.dwarf2/typeddwarf-amd64.S: New file.

diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index de62ac7..9a55f01 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -275,11 +275,13 @@ amd64_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
     return i386_pseudo_register_name (gdbarch, regnum);
 }
 
-static enum register_status
-amd64_pseudo_register_read (struct gdbarch *gdbarch,
-			    struct regcache *regcache,
-			    int regnum, gdb_byte *buf)
+static void
+amd64_pseudo_register_read_into_value (struct gdbarch *gdbarch,
+				       struct regcache *regcache,
+				       int regnum,
+				       struct value *result_value)
 {
+  gdb_byte *buf = value_contents_raw (result_value);
   gdb_byte raw_buf[MAX_REGISTER_SIZE];
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum register_status status;
@@ -297,15 +299,19 @@ amd64_pseudo_register_read (struct gdbarch *gdbarch,
 				      raw_buf);
 	  if (status == REG_VALID)
 	    memcpy (buf, raw_buf + 1, 1);
+	  else
+	    mark_value_bytes_unavailable (result_value, 0,
+					  TYPE_LENGTH (value_type (result_value)));
 	}
       else
 	{
 	  status = regcache_raw_read (regcache, gpnum, raw_buf);
 	  if (status == REG_VALID)
 	    memcpy (buf, raw_buf, 1);
+	  else
+	    mark_value_bytes_unavailable (result_value, 0,
+					  TYPE_LENGTH (value_type (result_value)));
 	}
-
-      return status;
     }
   else if (i386_dword_regnum_p (gdbarch, regnum))
     {
@@ -314,11 +320,13 @@ amd64_pseudo_register_read (struct gdbarch *gdbarch,
       status = regcache_raw_read (regcache, gpnum, raw_buf);
       if (status == REG_VALID)
 	memcpy (buf, raw_buf, 4);
-
-      return status;
+      else
+	mark_value_bytes_unavailable (result_value, 0,
+				      TYPE_LENGTH (value_type (result_value)));
     }
   else
-    return i386_pseudo_register_read (gdbarch, regcache, regnum, buf);
+    i386_pseudo_register_read_into_value (gdbarch, regcache, regnum,
+					  result_value);
 }
 
 static void
@@ -2494,8 +2502,8 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* Avoid wiring in the MMX registers for now.  */
   tdep->num_mmx_regs = 0;
 
-  set_gdbarch_pseudo_register_read (gdbarch,
-				    amd64_pseudo_register_read);
+  set_gdbarch_pseudo_register_read_into_value (gdbarch,
+					       amd64_pseudo_register_read_into_value);
   set_gdbarch_pseudo_register_write (gdbarch,
 				     amd64_pseudo_register_write);
 
diff --git a/gdb/findvar.c b/gdb/findvar.c
index a700c02..59e86ef 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -647,14 +647,16 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
   else
     {
       int len = TYPE_LENGTH (type);
+      struct value *v2;
 
       /* Construct the value.  */
       v = gdbarch_value_from_register (gdbarch, type, regnum, frame);
 
       /* Get the data.  */
-      ok = get_frame_register_bytes (frame, regnum, value_offset (v), len,
-				     value_contents_raw (v),
-				     &optim, &unavail);
+      v2 = get_frame_register_value (frame, regnum);
+
+      value_contents_copy (v, 0, v2, 0, len);
+      ok = 1;
     }
 
   if (!ok)
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 1e65c17..31b341a 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -161,6 +161,7 @@ struct gdbarch
   gdbarch_write_pc_ftype *write_pc;
   gdbarch_virtual_frame_pointer_ftype *virtual_frame_pointer;
   gdbarch_pseudo_register_read_ftype *pseudo_register_read;
+  gdbarch_pseudo_register_read_into_value_ftype *pseudo_register_read_into_value;
   gdbarch_pseudo_register_write_ftype *pseudo_register_write;
   int num_regs;
   int num_pseudo_regs;
@@ -313,6 +314,7 @@ struct gdbarch startup_gdbarch =
   0,  /* write_pc */
   legacy_virtual_frame_pointer,  /* virtual_frame_pointer */
   0,  /* pseudo_register_read */
+  0,  /* pseudo_register_read_into_value */
   0,  /* pseudo_register_write */
   0,  /* num_regs */
   0,  /* num_pseudo_regs */
@@ -594,6 +596,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of write_pc, has predicate.  */
   /* Skip verify of virtual_frame_pointer, invalid_p == 0 */
   /* Skip verify of pseudo_register_read, has predicate.  */
+  /* Skip verify of pseudo_register_read_into_value, has predicate.  */
   /* Skip verify of pseudo_register_write, has predicate.  */
   if (gdbarch->num_regs == -1)
     fprintf_unfiltered (log, "\n\tnum_regs");
@@ -1085,6 +1088,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: pseudo_register_read = <%s>\n",
                       host_address_to_string (gdbarch->pseudo_register_read));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_pseudo_register_read_into_value_p() = %d\n",
+                      gdbarch_pseudo_register_read_into_value_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: pseudo_register_read_into_value = <%s>\n",
+                      host_address_to_string (gdbarch->pseudo_register_read_into_value));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: gdbarch_pseudo_register_write_p() = %d\n",
                       gdbarch_pseudo_register_write_p (gdbarch));
   fprintf_unfiltered (file,
@@ -1700,6 +1709,30 @@ set_gdbarch_pseudo_register_read (struct gdbarch *gdbarch,
 }
 
 int
+gdbarch_pseudo_register_read_into_value_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->pseudo_register_read_into_value != NULL;
+}
+
+void
+gdbarch_pseudo_register_read_into_value (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, struct value *result)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->pseudo_register_read_into_value != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_pseudo_register_read_into_value called\n");
+  gdbarch->pseudo_register_read_into_value (gdbarch, regcache, cookednum, result);
+}
+
+void
+set_gdbarch_pseudo_register_read_into_value (struct gdbarch *gdbarch,
+                                             gdbarch_pseudo_register_read_into_value_ftype pseudo_register_read_into_value)
+{
+  gdbarch->pseudo_register_read_into_value = pseudo_register_read_into_value;
+}
+
+int
 gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 50221d7..bf4f03d 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -216,6 +216,18 @@ typedef enum register_status (gdbarch_pseudo_register_read_ftype) (struct gdbarc
 extern enum register_status gdbarch_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, gdb_byte *buf);
 extern void set_gdbarch_pseudo_register_read (struct gdbarch *gdbarch, gdbarch_pseudo_register_read_ftype *pseudo_register_read);
 
+/* Read a register into a struct value.  The value is already
+   allocated, only its contents must be updated.  If the register is
+   wholly or partly unavailable, this should call
+   mark_value_bytes_unavailable as appropriate.  If this is defined,
+   then pseudo_register_read will never be called. */
+
+extern int gdbarch_pseudo_register_read_into_value_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_pseudo_register_read_into_value_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, struct value *result);
+extern void gdbarch_pseudo_register_read_into_value (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, struct value *result);
+extern void set_gdbarch_pseudo_register_read_into_value (struct gdbarch *gdbarch, gdbarch_pseudo_register_read_into_value_ftype *pseudo_register_read_into_value);
+
 extern int gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch);
 
 typedef void (gdbarch_pseudo_register_write_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, const gdb_byte *buf);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index a628f8c..b8d2de8 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -418,6 +418,12 @@ F:void:write_pc:struct regcache *regcache, CORE_ADDR val:regcache, val
 m:void:virtual_frame_pointer:CORE_ADDR pc, int *frame_regnum, LONGEST *frame_offset:pc, frame_regnum, frame_offset:0:legacy_virtual_frame_pointer::0
 #
 M:enum register_status:pseudo_register_read:struct regcache *regcache, int cookednum, gdb_byte *buf:regcache, cookednum, buf
+# Read a register into a struct value.  The value is already
+# allocated, only its contents must be updated.  If the register is
+# wholly or partly unavailable, this should call
+# mark_value_bytes_unavailable as appropriate.  If this is defined,
+# then pseudo_register_read will never be called.
+M:void:pseudo_register_read_into_value:struct regcache *regcache, int cookednum, struct value *result:regcache, cookednum, result
 M:void:pseudo_register_write:struct regcache *regcache, int cookednum, const gdb_byte *buf:regcache, cookednum, buf
 #
 v:int:num_regs:::0:-1
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 366d0fa..aa81303 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -2780,12 +2780,15 @@ i386_mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum)
   return (I387_ST0_REGNUM (tdep) + fpreg);
 }
 
-enum register_status
-i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
-			   int regnum, gdb_byte *buf)
+void
+i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
+				      struct regcache *regcache,
+				      int regnum,
+				      struct value *result_value)
 {
   gdb_byte raw_buf[MAX_REGISTER_SIZE];
   enum register_status status;
+  gdb_byte *buf = value_contents_raw (result_value);
 
   if (i386_mmx_regnum_p (gdbarch, regnum))
     {
@@ -2794,8 +2797,10 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
       /* Extract (always little endian).  */
       status = regcache_raw_read (regcache, fpnum, raw_buf);
       if (status != REG_VALID)
-	return status;
-      memcpy (buf, raw_buf, register_size (gdbarch, regnum));
+	mark_value_bytes_unavailable (result_value, 0,
+				      TYPE_LENGTH (value_type (result_value)));
+      else
+	memcpy (buf, raw_buf, register_size (gdbarch, regnum));
     }
   else
     {
@@ -2810,15 +2815,17 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 				      I387_XMM0_REGNUM (tdep) + regnum,
 				      raw_buf);
 	  if (status != REG_VALID)
-	    return status;
-	  memcpy (buf, raw_buf, 16);
+	    mark_value_bytes_unavailable (result_value, 0, 16);
+	  else
+	    memcpy (buf, raw_buf, 16);
 	  /* Read upper 128bits.  */
 	  status = regcache_raw_read (regcache,
 				      tdep->ymm0h_regnum + regnum,
 				      raw_buf);
 	  if (status != REG_VALID)
-	    return status;
-	  memcpy (buf + 16, raw_buf, 16);
+	    mark_value_bytes_unavailable (result_value, 16, 32);
+	  else
+	    memcpy (buf + 16, raw_buf, 16);
 	}
       else if (i386_word_regnum_p (gdbarch, regnum))
 	{
@@ -2827,8 +2834,10 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 	  /* Extract (always little endian).  */
 	  status = regcache_raw_read (regcache, gpnum, raw_buf);
 	  if (status != REG_VALID)
-	    return status;
-	  memcpy (buf, raw_buf, 2);
+	    mark_value_bytes_unavailable (result_value, 0,
+					  TYPE_LENGTH (value_type (result_value)));
+	  else
+	    memcpy (buf, raw_buf, 2);
 	}
       else if (i386_byte_regnum_p (gdbarch, regnum))
 	{
@@ -2841,8 +2850,9 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 	     upper registers.  */
 	  status = regcache_raw_read (regcache, gpnum % 4, raw_buf);
 	  if (status != REG_VALID)
-	    return status;
-	  if (gpnum >= 4)
+	    mark_value_bytes_unavailable (result_value, 0,
+					  TYPE_LENGTH (value_type (result_value)));
+	  else if (gpnum >= 4)
 	    memcpy (buf, raw_buf + 1, 1);
 	  else
 	    memcpy (buf, raw_buf, 1);
@@ -2850,8 +2860,6 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
       else
 	internal_error (__FILE__, __LINE__, _("invalid regnum"));
     }
-
-  return REG_VALID;
 }
 
 void
@@ -7333,7 +7341,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   frame_base_set_default (gdbarch, &i386_frame_base);
 
   /* Pseudo registers may be changed by amd64_init_abi.  */
-  set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read);
+  set_gdbarch_pseudo_register_read_into_value (gdbarch,
+					       i386_pseudo_register_read_into_value);
   set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write);
 
   set_tdesc_pseudo_register_type (gdbarch, i386_pseudo_register_type);
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 7fc719c..de11f68 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -311,10 +311,11 @@ extern int i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum);
 extern const char *i386_pseudo_register_name (struct gdbarch *gdbarch,
 					      int regnum);
 
-extern enum register_status i386_pseudo_register_read (struct gdbarch *gdbarch,
-						       struct regcache *regcache,
-						       int regnum,
-						       gdb_byte *buf);
+extern void i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
+						  struct regcache *regcache,
+						  int regnum,
+						  struct value *result);
+
 extern void i386_pseudo_register_write (struct gdbarch *gdbarch,
 					struct regcache *regcache,
 					int regnum, const gdb_byte *buf);
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 41f218d..258e8a6 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -709,11 +709,62 @@ regcache_cooked_read (struct regcache *regcache, int regnum, gdb_byte *buf)
 
       return regcache->register_status[regnum];
     }
+  else if (gdbarch_pseudo_register_read_into_value_p (regcache->descr->gdbarch))
+    {
+      struct value *mark, *computed;
+      enum register_status result = REG_VALID;
+
+      mark = value_mark ();
+      computed = allocate_value (register_type (regcache->descr->gdbarch,
+						regnum));
+      VALUE_LVAL (computed) = lval_register;
+      VALUE_REGNUM (computed) = regnum;
+
+      gdbarch_pseudo_register_read_into_value (regcache->descr->gdbarch,
+					       regcache, regnum, computed);
+      if (value_entirely_available (computed))
+	memcpy (buf, value_contents_raw (computed),
+		regcache->descr->sizeof_register[regnum]);
+      else
+	{
+	  memset (buf, 0, regcache->descr->sizeof_register[regnum]);
+	  result = REG_UNAVAILABLE;
+	}
+
+      value_free_to_mark (mark);
+
+      return result;
+    }
   else
     return gdbarch_pseudo_register_read (regcache->descr->gdbarch, regcache,
 					 regnum, buf);
 }
 
+void
+regcache_cooked_read_into_value (struct regcache *regcache, int regnum,
+				 struct value *result)
+{
+  gdb_assert (regnum >= 0);
+  gdb_assert (regnum < regcache->descr->nr_cooked_registers);
+
+  if (regnum < regcache->descr->nr_raw_registers
+      || (regcache->readonly_p
+	  && regcache->register_status[regnum] != REG_UNKNOWN)
+      || !gdbarch_pseudo_register_read_into_value_p (regcache->descr->gdbarch))
+    {
+      /* It is more efficient in general to do this delegation in this
+	 direction than in the other one, even though the value-based
+	 API is preferred.  */
+      if (regcache_cooked_read (regcache, regnum,
+				value_contents_raw (result)) == REG_UNAVAILABLE)
+	mark_value_bytes_unavailable (result, 0,
+				      TYPE_LENGTH (value_type (result)));
+    }
+  else
+    gdbarch_pseudo_register_read_into_value (regcache->descr->gdbarch,
+					     regcache, regnum, result);
+}
+
 enum register_status
 regcache_cooked_read_signed (struct regcache *regcache, int regnum,
 			     LONGEST *val)
diff --git a/gdb/regcache.h b/gdb/regcache.h
index 3708c86..417575c 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -104,6 +104,13 @@ enum register_status regcache_cooked_read (struct regcache *regcache,
 void regcache_cooked_write (struct regcache *regcache, int rawnum,
 			    const gdb_byte *buf);
 
+/* Read register REGNUM from REGCACHE into an already-allocated value,
+   RESULT.  This will fill in the contents of RESULT and, if
+   necessary, call mark_value_bytes_unavailable as appropriate.  */
+
+void regcache_cooked_read_into_value (struct regcache *regcache, int regnum,
+				      struct value *result);
+
 /* Read a register as a signed/unsigned quantity.  */
 extern enum register_status
   regcache_cooked_read_signed (struct regcache *regcache,
diff --git a/gdb/sentinel-frame.c b/gdb/sentinel-frame.c
index 6c2f3e0..86814af 100644
--- a/gdb/sentinel-frame.c
+++ b/gdb/sentinel-frame.c
@@ -59,13 +59,7 @@ sentinel_frame_prev_register (struct frame_info *this_frame,
   VALUE_REGNUM (value) = regnum;
   VALUE_FRAME_ID (value) = get_frame_id (this_frame);
 
-  /* Use the regcache_cooked_read() method so that it, on the fly,
-     constructs either a raw or pseudo register from the raw
-     register cache.  */
-  if (regcache_cooked_read (cache->regcache,
-			    regnum,
-			    value_contents_raw (value)) == REG_UNAVAILABLE)
-    mark_value_bytes_unavailable (value, 0, TYPE_LENGTH (regtype));
+  regcache_cooked_read_into_value (cache->regcache, regnum, value);
 
   return value;
 }
diff --git a/gdb/testsuite/gdb.dwarf2/typeddwarf-amd64.S b/gdb/testsuite/gdb.dwarf2/typeddwarf-amd64.S
new file mode 100644
index 0000000..f97357a
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/typeddwarf-amd64.S
@@ -0,0 +1,1568 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* This source file was generated from typeddwarf.c using the following
+   command line:
+
+   gcc -S -g -O2 typeddwarf.c -o typeddwarf-amd64.S
+
+*/
+
+
+	.file	"typeddwarf.c"
+	.text
+.Ltext0:
+	.globl	f1
+	.type	f1, @function
+f1:
+.LFB0:
+	.file 1 "typeddwarf.c"
+	.loc 1 10 0
+	.cfi_startproc
+.LVL0:
+	.loc 1 29 0
+	movl	vv(%rip), %eax
+	addl	$1, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 30 0
+	ret
+	.cfi_endproc
+.LFE0:
+	.size	f1, .-f1
+	.globl	f2
+	.type	f2, @function
+f2:
+.LFB1:
+	.loc 1 34 0
+	.cfi_startproc
+.LVL1:
+	.loc 1 53 0
+	movl	vv(%rip), %eax
+	addl	$1, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 54 0
+	cvttsd2si	%xmm0, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 55 0
+	cvttsd2si	%xmm1, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 56 0
+	cvttsd2si	%xmm2, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 57 0
+	cvttss2si	%xmm3, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 58 0
+	cvttss2si	%xmm4, %r8d
+	movl	%r8d, vv(%rip)
+	.loc 1 59 0
+	movl	%edi, vv(%rip)
+	.loc 1 60 0
+	movl	%esi, vv(%rip)
+	.loc 1 61 0
+	movl	%edx, vv(%rip)
+	.loc 1 62 0
+	movl	%ecx, vv(%rip)
+	.loc 1 63 0
+	movl	%eax, vv(%rip)
+	.loc 1 64 0
+	ret
+	.cfi_endproc
+.LFE1:
+	.size	f2, .-f2
+	.globl	f3
+	.type	f3, @function
+f3:
+.LFB2:
+	.loc 1 68 0
+	.cfi_startproc
+.LVL2:
+	.loc 1 73 0
+	movl	vv(%rip), %eax
+	addl	$1, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 74 0
+	ret
+	.cfi_endproc
+.LFE2:
+	.size	f3, .-f3
+	.globl	f4
+	.type	f4, @function
+f4:
+.LFB3:
+	.loc 1 78 0
+	.cfi_startproc
+.LVL3:
+	.loc 1 82 0
+	movl	vv(%rip), %eax
+	addl	$1, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 83 0
+	ret
+	.cfi_endproc
+.LFE3:
+	.size	f4, .-f4
+	.globl	_start
+	.type	_start, @function
+_start:
+.LFB4:
+	.loc 1 87 0
+	.cfi_startproc
+	subq	$8, %rsp
+.LCFI0:
+	.cfi_def_cfa_offset 16
+	.loc 1 88 0
+	movl	$9, %ecx
+	movl	$8, %edx
+	movl	$7, %esi
+	movl	$6, %edi
+	movss	.LC2(%rip), %xmm4
+	movss	.LC3(%rip), %xmm3
+	movsd	.LC0(%rip), %xmm2
+	movsd	.LC1(%rip), %xmm1
+	movsd	.LC4(%rip), %xmm0
+	call	f1
+.LVL4:
+	.loc 1 89 0
+	movl	$9, %ecx
+	movl	$8, %edx
+	movl	$7, %esi
+	movl	$6, %edi
+	movss	.LC2(%rip), %xmm4
+	movss	.LC3(%rip), %xmm3
+	movsd	.LC0(%rip), %xmm2
+	movsd	.LC1(%rip), %xmm1
+	movsd	.LC4(%rip), %xmm0
+	call	f2
+.LVL5:
+	.loc 1 90 0
+	movl	$4, %ecx
+	movl	$3, %edx
+	movl	$2, %esi
+	movl	$1, %edi
+	call	f3
+.LVL6:
+	.loc 1 91 0
+	movdqa	.LC5(%rip), %xmm2
+	movq	.LC6(%rip), %xmm1
+	movd	.LC7(%rip), %xmm0
+	call	f4
+.LVL7:
+	.loc 1 93 0
+	movl	$0, %eax
+	addq	$8, %rsp
+.LCFI1:
+	.cfi_def_cfa_offset 8
+	ret
+	.cfi_endproc
+.LFE4:
+	.size	_start, .-_start
+	.comm	vv,4,4
+	.section	.rodata.cst8,"aM",@progbits,8
+	.align 8
+.LC0:
+	.long	0
+	.long	1074266112
+	.align 8
+.LC1:
+	.long	0
+	.long	1073741824
+	.section	.rodata.cst4,"aM",@progbits,4
+	.align 4
+.LC2:
+	.long	1084227584
+	.align 4
+.LC3:
+	.long	1082130432
+	.section	.rodata.cst8
+	.align 8
+.LC4:
+	.long	0
+	.long	1072693248
+	.section	.rodata.cst16,"aM",@progbits,16
+	.align 16
+.LC5:
+	.quad	640
+	.quad	3476215962376601600
+	.section	.rodata.cst8
+	.align 8
+.LC6:
+	.quad	3575858104132173984
+	.section	.rodata.cst4
+	.align 4
+.LC7:
+	.long	838860880
+	.text
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	0x6c4
+	.value	0x2
+	.long	.Ldebug_abbrev0
+	.byte	0x8
+	.uleb128 0x1
+	.long	.LASF8
+	.byte	0x1
+	.long	.LASF9
+	.long	.LASF10
+	.quad	.Ltext0
+	.quad	.Letext0
+	.long	.Ldebug_line0
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0x4
+	.long	.LASF0
+	.uleb128 0x2
+	.byte	0x4
+	.byte	0x4
+	.long	.LASF1
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0x7
+	.long	.LASF2
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0x5
+	.long	.LASF3
+	.uleb128 0x2
+	.byte	0x4
+	.byte	0x7
+	.long	.LASF4
+	.uleb128 0x3
+	.byte	0x4
+	.byte	0x5
+	.string	"int"
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0xf
+	.long	.LASF5
+	.uleb128 0x2
+	.byte	0x4
+	.byte	0xf
+	.long	.LASF6
+	.uleb128 0x2
+	.byte	0x10
+	.byte	0xf
+	.long	.LASF7
+	.uleb128 0x4
+	.byte	0x1
+	.string	"f1"
+	.byte	0x1
+	.byte	0x9
+	.byte	0x1
+	.quad	.LFB0
+	.quad	.LFE0
+	.byte	0x2
+	.byte	0x77
+	.sleb128 8
+	.byte	0x1
+	.long	0x22b
+	.uleb128 0x5
+	.string	"a"
+	.byte	0x1
+	.byte	0x9
+	.long	0x2d
+	.byte	0x1
+	.byte	0x61
+	.uleb128 0x5
+	.string	"b"
+	.byte	0x1
+	.byte	0x9
+	.long	0x2d
+	.byte	0x1
+	.byte	0x62
+	.uleb128 0x5
+	.string	"c"
+	.byte	0x1
+	.byte	0x9
+	.long	0x2d
+	.byte	0x1
+	.byte	0x63
+	.uleb128 0x5
+	.string	"d"
+	.byte	0x1
+	.byte	0x9
+	.long	0x34
+	.byte	0x1
+	.byte	0x64
+	.uleb128 0x5
+	.string	"e"
+	.byte	0x1
+	.byte	0x9
+	.long	0x34
+	.byte	0x1
+	.byte	0x65
+	.uleb128 0x5
+	.string	"f"
+	.byte	0x1
+	.byte	0x9
+	.long	0x50
+	.byte	0x1
+	.byte	0x55
+	.uleb128 0x5
+	.string	"g"
+	.byte	0x1
+	.byte	0x9
+	.long	0x49
+	.byte	0x1
+	.byte	0x54
+	.uleb128 0x5
+	.string	"h"
+	.byte	0x1
+	.byte	0x9
+	.long	0x22b
+	.byte	0x1
+	.byte	0x51
+	.uleb128 0x5
+	.string	"i"
+	.byte	0x1
+	.byte	0x9
+	.long	0x232
+	.byte	0x1
+	.byte	0x52
+	.uleb128 0x6
+	.string	"j"
+	.byte	0x1
+	.byte	0xb
+	.long	0x2d
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"l"
+	.byte	0x1
+	.byte	0xc
+	.long	0x22b
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0xf9
+	.uleb128 0x3b
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"m"
+	.byte	0x1
+	.byte	0xe
+	.long	0x22b
+	.byte	0x1
+	.byte	0x63
+	.uleb128 0x6
+	.string	"n"
+	.byte	0x1
+	.byte	0x10
+	.long	0x34
+	.byte	0x7
+	.byte	0x72
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x3b
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"o"
+	.byte	0x1
+	.byte	0x11
+	.long	0x2d
+	.byte	0x7
+	.byte	0x71
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x42
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"p"
+	.byte	0x1
+	.byte	0x12
+	.long	0x34
+	.byte	0x7
+	.byte	0x74
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x49
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"q"
+	.byte	0x1
+	.byte	0x13
+	.long	0x2d
+	.byte	0x7
+	.byte	0x75
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x50
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"r"
+	.byte	0x1
+	.byte	0x14
+	.long	0x232
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x3b
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"s"
+	.byte	0x1
+	.byte	0x15
+	.long	0x22b
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x13
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x42
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"t"
+	.byte	0x1
+	.byte	0x16
+	.long	0x49
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x49
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"u"
+	.byte	0x1
+	.byte	0x17
+	.long	0x50
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x50
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"v"
+	.byte	0x1
+	.byte	0x18
+	.long	0x34
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"w"
+	.byte	0x1
+	.byte	0x19
+	.long	0x2d
+	.byte	0x12
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x3fd00000
+	.byte	0x1e
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"x"
+	.byte	0x1
+	.byte	0x1a
+	.long	0x2d
+	.byte	0x14
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0x22
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x3ff00000
+	.byte	0x22
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"y"
+	.byte	0x1
+	.byte	0x1b
+	.long	0x2d
+	.byte	0x14
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0xf5
+	.uleb128 0x13
+	.uleb128 0x2d
+	.byte	0x22
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40000000
+	.byte	0x22
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"z"
+	.byte	0x1
+	.byte	0x1c
+	.long	0x34
+	.byte	0x12
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf3
+	.uleb128 0x3
+	.byte	0xf5
+	.uleb128 0x15
+	.uleb128 0x34
+	.byte	0x22
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40400000
+	.byte	0x22
+	.byte	0x9f
+	.byte	0
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0x5
+	.long	.LASF11
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0x7
+	.long	.LASF12
+	.uleb128 0x4
+	.byte	0x1
+	.string	"f2"
+	.byte	0x1
+	.byte	0x21
+	.byte	0x1
+	.quad	.LFB1
+	.quad	.LFE1
+	.byte	0x2
+	.byte	0x77
+	.sleb128 8
+	.byte	0x1
+	.long	0x402
+	.uleb128 0x5
+	.string	"a"
+	.byte	0x1
+	.byte	0x21
+	.long	0x2d
+	.byte	0x1
+	.byte	0x61
+	.uleb128 0x5
+	.string	"b"
+	.byte	0x1
+	.byte	0x21
+	.long	0x2d
+	.byte	0x1
+	.byte	0x62
+	.uleb128 0x5
+	.string	"c"
+	.byte	0x1
+	.byte	0x21
+	.long	0x2d
+	.byte	0x1
+	.byte	0x63
+	.uleb128 0x5
+	.string	"d"
+	.byte	0x1
+	.byte	0x21
+	.long	0x34
+	.byte	0x1
+	.byte	0x64
+	.uleb128 0x5
+	.string	"e"
+	.byte	0x1
+	.byte	0x21
+	.long	0x34
+	.byte	0x1
+	.byte	0x65
+	.uleb128 0x5
+	.string	"f"
+	.byte	0x1
+	.byte	0x21
+	.long	0x50
+	.byte	0x1
+	.byte	0x55
+	.uleb128 0x5
+	.string	"g"
+	.byte	0x1
+	.byte	0x21
+	.long	0x49
+	.byte	0x1
+	.byte	0x54
+	.uleb128 0x5
+	.string	"h"
+	.byte	0x1
+	.byte	0x21
+	.long	0x22b
+	.byte	0x1
+	.byte	0x51
+	.uleb128 0x5
+	.string	"i"
+	.byte	0x1
+	.byte	0x21
+	.long	0x232
+	.byte	0x1
+	.byte	0x52
+	.uleb128 0x6
+	.string	"j"
+	.byte	0x1
+	.byte	0x23
+	.long	0x2d
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"l"
+	.byte	0x1
+	.byte	0x24
+	.long	0x22b
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0xf9
+	.uleb128 0x3b
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"m"
+	.byte	0x1
+	.byte	0x26
+	.long	0x22b
+	.byte	0x1
+	.byte	0x63
+	.uleb128 0x6
+	.string	"n"
+	.byte	0x1
+	.byte	0x28
+	.long	0x34
+	.byte	0x7
+	.byte	0x72
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x3b
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"o"
+	.byte	0x1
+	.byte	0x29
+	.long	0x2d
+	.byte	0x7
+	.byte	0x71
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x42
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"p"
+	.byte	0x1
+	.byte	0x2a
+	.long	0x34
+	.byte	0x7
+	.byte	0x74
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x49
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"q"
+	.byte	0x1
+	.byte	0x2b
+	.long	0x2d
+	.byte	0x7
+	.byte	0x75
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x50
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"r"
+	.byte	0x1
+	.byte	0x2c
+	.long	0x232
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x3b
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"s"
+	.byte	0x1
+	.byte	0x2d
+	.long	0x22b
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x13
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x42
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"t"
+	.byte	0x1
+	.byte	0x2e
+	.long	0x49
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x49
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"u"
+	.byte	0x1
+	.byte	0x2f
+	.long	0x50
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x50
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"v"
+	.byte	0x1
+	.byte	0x30
+	.long	0x34
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"w"
+	.byte	0x1
+	.byte	0x31
+	.long	0x2d
+	.byte	0x12
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x3fd00000
+	.byte	0x1e
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"x"
+	.byte	0x1
+	.byte	0x32
+	.long	0x2d
+	.byte	0x20
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0x22
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40080000
+	.byte	0x1c
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0x78b58c40
+	.long	0x4415af1d
+	.byte	0x22
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"y"
+	.byte	0x1
+	.byte	0x33
+	.long	0x2d
+	.byte	0x14
+	.byte	0xf5
+	.uleb128 0x13
+	.uleb128 0x2d
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x401c0000
+	.byte	0x1e
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0x22
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"z"
+	.byte	0x1
+	.byte	0x34
+	.long	0x34
+	.byte	0x10
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf5
+	.uleb128 0x15
+	.uleb128 0x34
+	.byte	0x22
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40400000
+	.byte	0x22
+	.byte	0x9f
+	.byte	0
+	.uleb128 0x4
+	.byte	0x1
+	.string	"f3"
+	.byte	0x1
+	.byte	0x43
+	.byte	0x1
+	.quad	.LFB2
+	.quad	.LFE2
+	.byte	0x2
+	.byte	0x77
+	.sleb128 8
+	.byte	0x1
+	.long	0x4cd
+	.uleb128 0x5
+	.string	"a"
+	.byte	0x1
+	.byte	0x43
+	.long	0x22b
+	.byte	0x1
+	.byte	0x55
+	.uleb128 0x5
+	.string	"b"
+	.byte	0x1
+	.byte	0x43
+	.long	0x50
+	.byte	0x1
+	.byte	0x54
+	.uleb128 0x5
+	.string	"c"
+	.byte	0x1
+	.byte	0x43
+	.long	0x22b
+	.byte	0x1
+	.byte	0x51
+	.uleb128 0x5
+	.string	"d"
+	.byte	0x1
+	.byte	0x43
+	.long	0x49
+	.byte	0x1
+	.byte	0x52
+	.uleb128 0x6
+	.string	"w"
+	.byte	0x1
+	.byte	0x45
+	.long	0x22b
+	.byte	0x14
+	.byte	0x72
+	.sleb128 0
+	.byte	0xc
+	.long	0xffffffff
+	.byte	0x1a
+	.byte	0x12
+	.byte	0x75
+	.sleb128 0
+	.byte	0x16
+	.byte	0x14
+	.byte	0x2b
+	.byte	0x28
+	.value	0x1
+	.byte	0x16
+	.byte	0x13
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"x"
+	.byte	0x1
+	.byte	0x46
+	.long	0x22b
+	.byte	0xe
+	.byte	0x74
+	.sleb128 0
+	.byte	0x8
+	.byte	0x20
+	.byte	0x24
+	.byte	0x8
+	.byte	0x20
+	.byte	0x26
+	.byte	0x75
+	.sleb128 0
+	.byte	0x22
+	.byte	0x23
+	.uleb128 0x7
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"y"
+	.byte	0x1
+	.byte	0x47
+	.long	0x22b
+	.byte	0x13
+	.byte	0x72
+	.sleb128 0
+	.byte	0xc
+	.long	0xffffffff
+	.byte	0x1a
+	.byte	0x71
+	.sleb128 0
+	.byte	0x22
+	.byte	0x23
+	.uleb128 0x912345678
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"z"
+	.byte	0x1
+	.byte	0x48
+	.long	0x50
+	.byte	0x21
+	.byte	0x74
+	.sleb128 0
+	.byte	0x8
+	.byte	0x20
+	.byte	0x24
+	.byte	0x8
+	.byte	0x20
+	.byte	0x26
+	.byte	0x75
+	.sleb128 0
+	.byte	0x22
+	.byte	0x23
+	.uleb128 0x7
+	.byte	0x72
+	.sleb128 0
+	.byte	0xc
+	.long	0xffffffff
+	.byte	0x1a
+	.byte	0x71
+	.sleb128 0
+	.byte	0x22
+	.byte	0x23
+	.uleb128 0x912345678
+	.byte	0x22
+	.byte	0x9f
+	.byte	0
+	.uleb128 0x4
+	.byte	0x1
+	.string	"f4"
+	.byte	0x1
+	.byte	0x4d
+	.byte	0x1
+	.quad	.LFB3
+	.quad	.LFE3
+	.byte	0x2
+	.byte	0x77
+	.sleb128 8
+	.byte	0x1
+	.long	0x576
+	.uleb128 0x5
+	.string	"a"
+	.byte	0x1
+	.byte	0x4d
+	.long	0x5e
+	.byte	0x1
+	.byte	0x61
+	.uleb128 0x5
+	.string	"b"
+	.byte	0x1
+	.byte	0x4d
+	.long	0x57
+	.byte	0x1
+	.byte	0x62
+	.uleb128 0x5
+	.string	"c"
+	.byte	0x1
+	.byte	0x4d
+	.long	0x65
+	.byte	0x1
+	.byte	0x63
+	.uleb128 0x6
+	.string	"w"
+	.byte	0x1
+	.byte	0x4f
+	.long	0x5e
+	.byte	0x14
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x5e
+	.byte	0xf4
+	.uleb128 0x5e
+	.byte	0x4
+	.long	0x32000050
+	.byte	0x1e
+	.byte	0xf4
+	.uleb128 0x5e
+	.byte	0x4
+	.long	0x3200003c
+	.byte	0x22
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"x"
+	.byte	0x1
+	.byte	0x50
+	.long	0x57
+	.byte	0x1c
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x57
+	.byte	0xf4
+	.uleb128 0x57
+	.byte	0x8
+	.long	0x50
+	.long	0x31a00000
+	.byte	0x1b
+	.byte	0xf4
+	.uleb128 0x57
+	.byte	0x8
+	.long	0x3c
+	.long	0x31a00000
+	.byte	0x1c
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"y"
+	.byte	0x1
+	.byte	0x51
+	.long	0x65
+	.byte	0x19
+	.byte	0xf5
+	.uleb128 0x13
+	.uleb128 0x65
+	.byte	0x1f
+	.byte	0xf4
+	.uleb128 0x65
+	.byte	0x10
+	.long	0x50
+	.long	0
+	.long	0
+	.long	0x303e0000
+	.byte	0x1b
+	.byte	0x9f
+	.byte	0
+	.uleb128 0x7
+	.byte	0x1
+	.long	.LASF13
+	.byte	0x1
+	.byte	0x56
+	.long	0x50
+	.quad	.LFB4
+	.quad	.LFE4
+	.long	.LLST0
+	.byte	0x1
+	.long	0x6a1
+	.uleb128 0x8
+	.quad	.LVL4
+	.long	0x6c
+	.long	0x604
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x61
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x3ff00000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x62
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40000000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x63
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40080000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x64
+	.byte	0x7
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40800000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x65
+	.byte	0x7
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40a00000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x55
+	.byte	0x1
+	.byte	0x36
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x54
+	.byte	0x1
+	.byte	0x37
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x51
+	.byte	0x1
+	.byte	0x38
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x52
+	.byte	0x1
+	.byte	0x39
+	.byte	0
+	.uleb128 0x8
+	.quad	.LVL5
+	.long	0x239
+	.long	0x66d
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x61
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x3ff00000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x62
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40000000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x63
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40080000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x64
+	.byte	0x7
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40800000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x65
+	.byte	0x7
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40a00000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x55
+	.byte	0x1
+	.byte	0x36
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x54
+	.byte	0x1
+	.byte	0x37
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x51
+	.byte	0x1
+	.byte	0x38
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x52
+	.byte	0x1
+	.byte	0x39
+	.byte	0
+	.uleb128 0x8
+	.quad	.LVL6
+	.long	0x402
+	.long	0x693
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x55
+	.byte	0x1
+	.byte	0x31
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x54
+	.byte	0x1
+	.byte	0x32
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x51
+	.byte	0x1
+	.byte	0x33
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x52
+	.byte	0x1
+	.byte	0x34
+	.byte	0
+	.uleb128 0xa
+	.quad	.LVL7
+	.long	0x4cd
+	.byte	0
+	.uleb128 0xb
+	.string	"vv"
+	.byte	0x1
+	.byte	0x5
+	.long	0x6ad
+	.byte	0x1
+	.byte	0x1
+	.uleb128 0xc
+	.long	0x50
+	.uleb128 0xd
+	.string	"vv"
+	.byte	0x1
+	.byte	0x5
+	.long	0x6ad
+	.byte	0x1
+	.byte	0x9
+	.byte	0x3
+	.quad	vv
+	.byte	0
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1
+	.uleb128 0x11
+	.byte	0x1
+	.uleb128 0x25
+	.uleb128 0xe
+	.uleb128 0x13
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x1b
+	.uleb128 0xe
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x1
+	.uleb128 0x10
+	.uleb128 0x6
+	.byte	0
+	.byte	0
+	.uleb128 0x2
+	.uleb128 0x24
+	.byte	0
+	.uleb128 0xb
+	.uleb128 0xb
+	.uleb128 0x3e
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0xe
+	.byte	0
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x24
+	.byte	0
+	.uleb128 0xb
+	.uleb128 0xb
+	.uleb128 0x3e
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0x8
+	.byte	0
+	.byte	0
+	.uleb128 0x4
+	.uleb128 0x2e
+	.byte	0x1
+	.uleb128 0x3f
+	.uleb128 0xc
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x27
+	.uleb128 0xc
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x1
+	.uleb128 0x40
+	.uleb128 0xa
+	.uleb128 0x2117
+	.uleb128 0xc
+	.uleb128 0x1
+	.uleb128 0x13
+	.byte	0
+	.byte	0
+	.uleb128 0x5
+	.uleb128 0x5
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x2
+	.uleb128 0xa
+	.byte	0
+	.byte	0
+	.uleb128 0x6
+	.uleb128 0x34
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x2
+	.uleb128 0xa
+	.byte	0
+	.byte	0
+	.uleb128 0x7
+	.uleb128 0x2e
+	.byte	0x1
+	.uleb128 0x3f
+	.uleb128 0xc
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x1
+	.uleb128 0x40
+	.uleb128 0x6
+	.uleb128 0x2117
+	.uleb128 0xc
+	.uleb128 0x1
+	.uleb128 0x13
+	.byte	0
+	.byte	0
+	.uleb128 0x8
+	.uleb128 0x4109
+	.byte	0x1
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x31
+	.uleb128 0x13
+	.uleb128 0x1
+	.uleb128 0x13
+	.byte	0
+	.byte	0
+	.uleb128 0x9
+	.uleb128 0x410a
+	.byte	0
+	.uleb128 0x2
+	.uleb128 0xa
+	.uleb128 0x2111
+	.uleb128 0xa
+	.byte	0
+	.byte	0
+	.uleb128 0xa
+	.uleb128 0x4109
+	.byte	0
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x31
+	.uleb128 0x13
+	.byte	0
+	.byte	0
+	.uleb128 0xb
+	.uleb128 0x34
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x3f
+	.uleb128 0xc
+	.uleb128 0x3c
+	.uleb128 0xc
+	.byte	0
+	.byte	0
+	.uleb128 0xc
+	.uleb128 0x35
+	.byte	0
+	.uleb128 0x49
+	.uleb128 0x13
+	.byte	0
+	.byte	0
+	.uleb128 0xd
+	.uleb128 0x34
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x3f
+	.uleb128 0xc
+	.uleb128 0x2
+	.uleb128 0xa
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_loc,"",@progbits
+.Ldebug_loc0:
+.LLST0:
+	.quad	.LFB4-.Ltext0
+	.quad	.LCFI0-.Ltext0
+	.value	0x2
+	.byte	0x77
+	.sleb128 8
+	.quad	.LCFI0-.Ltext0
+	.quad	.LCFI1-.Ltext0
+	.value	0x2
+	.byte	0x77
+	.sleb128 16
+	.quad	.LCFI1-.Ltext0
+	.quad	.LFE4-.Ltext0
+	.value	0x2
+	.byte	0x77
+	.sleb128 8
+	.quad	0
+	.quad	0
+	.section	.debug_aranges,"",@progbits
+	.long	0x2c
+	.value	0x2
+	.long	.Ldebug_info0
+	.byte	0x8
+	.byte	0
+	.value	0
+	.value	0
+	.quad	.Ltext0
+	.quad	.Letext0-.Ltext0
+	.quad	0
+	.quad	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF4:
+	.string	"unsigned int"
+.LASF6:
+	.string	"_Decimal32"
+.LASF7:
+	.string	"_Decimal128"
+.LASF2:
+	.string	"long unsigned int"
+.LASF12:
+	.string	"long long unsigned int"
+.LASF5:
+	.string	"_Decimal64"
+.LASF13:
+	.string	"main"
+.LASF3:
+	.string	"long int"
+.LASF10:
+	.string	"/tmp"
+.LASF0:
+	.string	"double"
+.LASF11:
+	.string	"long long int"
+.LASF1:
+	.string	"float"
+.LASF8:
+	.string	"GNU C 4.7.0 20110708 (experimental) [trunk revision 176048]"
+.LASF9:
+	.string	"typeddwarf.c"
+	.ident	"GCC: (GNU) 4.7.0 20110708 (experimental) [trunk revision 176048]"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.dwarf2/typeddwarf.c b/gdb/testsuite/gdb.dwarf2/typeddwarf.c
index e5f7d67..40497da 100644
--- a/gdb/testsuite/gdb.dwarf2/typeddwarf.c
+++ b/gdb/testsuite/gdb.dwarf2/typeddwarf.c
@@ -25,7 +25,7 @@ f1 (double a, double b, double c, float d, float e, int f, unsigned int g, long
   double w = d / 4.0;		/* { dg-final { gdb-test 29 "w" "1" } } */
   double x = a + b + 1.0;	/* { dg-final { gdb-test 29 "x" "4" } } */
   double y = b + c + 2.0;	/* { dg-final { gdb-test 29 "y" "7" } } */
-  float z = d + e + 3.0f;	/* { dg-final { gdb-test 29 "z" "12" } } */
+  float z = d + e + 3.0f;	/* { dg-final { xfail-gdb-test 29 "z" "12" "x86_64-*-*"} } */
   vv++;
 }
 
diff --git a/gdb/testsuite/gdb.dwarf2/typeddwarf.exp b/gdb/testsuite/gdb.dwarf2/typeddwarf.exp
index e6a420a..36a17e5 100644
--- a/gdb/testsuite/gdb.dwarf2/typeddwarf.exp
+++ b/gdb/testsuite/gdb.dwarf2/typeddwarf.exp
@@ -22,12 +22,16 @@ if ![dwarf2_support] {
     return 0  
 }
 
-# This test can only be run on x86 targets.
-if { ![is_x86_like_target] } {
+# This test can only be run on x86 and amd64 targets.
+if { [is_x86_like_target] } {
+    set sfile ${test}.S
+} elseif {[istarget "x86_64-*-*"]} {
+    set sfile ${test}-amd64.S
+} else {
     return 0
 }
 
-if { [prepare_for_testing "${test}.exp" "${test}" ${test}.S {nodebug additional_flags=-nostdlib}] } {
+if { [prepare_for_testing "${test}.exp" "${test}" ${sfile} {nodebug additional_flags=-nostdlib}] } {
     return -1
 }
 
@@ -45,10 +49,19 @@ proc gdb-test {line var value} {
     lappend tests($line) [list $var $value 0]
 }
 
-proc xfail-gdb-test {line var value} {
+# Add an XFAIL'd test.  If ARCH_PATTERN is given, and does not match
+# the target, then the test is simply added and not XFAIL'd.
+proc xfail-gdb-test {line var value {arch_pattern ""}} {
     global tests
 
-    lappend tests($line) [list $var $value 1]
+    set flag 1
+    if {$arch_pattern != ""} {
+	if {! [istarget $arch_pattern]} {
+	    set flag 0
+	}
+    }
+
+    lappend tests($line) [list $var $value $flag]
 }
 
 proc scan_gdb_tests {} {

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

* Re: RFC: partially available registers
  2011-07-20 20:46     ` Tom Tromey
@ 2011-07-20 20:53       ` Tom Tromey
  2011-07-24 13:48         ` Mark Kettenis
  2011-07-21  5:23       ` Ulrich Weigand
  2011-07-22 14:30       ` Pedro Alves
  2 siblings, 1 reply; 28+ messages in thread
From: Tom Tromey @ 2011-07-20 20:53 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches

Tom> I looked into this, and I changed some things, but I did not change it
Tom> completely.

I forgot to mention -- please comment.  In the absence of comments I
will commit this version.

Tom

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

* Re: RFC: partially available registers
  2011-07-20 20:46     ` Tom Tromey
  2011-07-20 20:53       ` Tom Tromey
@ 2011-07-21  5:23       ` Ulrich Weigand
  2011-07-21 20:27         ` Tom Tromey
  2011-07-22 14:30       ` Pedro Alves
  2 siblings, 1 reply; 28+ messages in thread
From: Ulrich Weigand @ 2011-07-21  5:23 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Daniel Jacobowitz, gdb-patches

Tom Tromey wrote:

> 2011-07-20  Tom Tromey  <tromey@redhat.com>
> 
> 	* amd64-tdep.c (amd64_pseudo_register_read_into_value): Rename
> 	from amd64_pseudo_register_read.  Change arguments.  Call
> 	mark_value_bytes_unavailable when needed.
> 	(amd64_init_abi): Use set_gdbarch_pseudo_register_read_value, not
> 	set_gdbarch_pseudo_register_read.
> 	* sentinel-frame.c (sentinel_frame_prev_register): Use
> 	regcache_cooked_read_into_value.
> 	* regcache.h (regcache_cooked_read_into_value): Declare.
> 	* regcache.c (regcache_cooked_read_into_value): New function.
> 	(regcache_cooked_read): Call
> 	gdbarch_pseudo_register_read_into_value if available.
> 	* i386-tdep.h (i386_pseudo_register_read_into_value): Declare.
> 	(i386_pseudo_register_read): Remove.
> 	* i386-tdep.c (i386_pseudo_register_read_into_value): Rename from
> 	i386_pseudo_register_read.  Change arguments.  Call
> 	mark_value_bytes_unavailable when needed.
> 	(i386_gdbarch_init): Call
> 	set_gdbarch_pseudo_register_read_into_value, not
> 	set_gdbarch_pseudo_register_read.
> 	* gdbarch.sh (pseudo_register_read_into_value): New method.
> 	* gdbarch.c, gdbarch.h: Rebuild.
> 	* findvar.c (value_from_register): Call get_frame_register_value.

I'm not completely happy about the "read into value" style interface;
this leaves unclear just how the value passed into that interface is
supposed to have been set up.  Should the callback have to cope with
different types (or even lengths), value offset, or more complex
value properties like enclosing type?  Apparently not -- the actual
callback implementations of your don't attempt to with (or even
check for!) any of that, they just blindly assume the value has been
set up as they expect.

I'd prefer an interface that simply *returns* a value, which then the
callback would be free to set up as desired.  This would also be much
more in line with all the other interfaces that produce values ...

> @@ -647,14 +647,16 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
>    else
>      {
>        int len = TYPE_LENGTH (type);
> +      struct value *v2;
>  
>        /* Construct the value.  */
>        v = gdbarch_value_from_register (gdbarch, type, regnum, frame);
>  
>        /* Get the data.  */
> -      ok = get_frame_register_bytes (frame, regnum, value_offset (v), len,
> -				     value_contents_raw (v),
> -				     &optim, &unavail);
> +      v2 = get_frame_register_value (frame, regnum);
> +
> +      value_contents_copy (v, 0, v2, 0, len);
> +      ok = 1;
>      }

This seems to introduce a bug by ignoring value_offset (v).
If v is of a smaller type than the full register width, only
the appropriate bytes of v2 (which do not always start at the
beginning, in particular on big-endian machines) ought to be
copied over to v.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

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

* Re: RFC: partially available registers
  2011-07-21  5:23       ` Ulrich Weigand
@ 2011-07-21 20:27         ` Tom Tromey
  2011-07-22 13:48           ` Ulrich Weigand
  0 siblings, 1 reply; 28+ messages in thread
From: Tom Tromey @ 2011-07-21 20:27 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: Daniel Jacobowitz, gdb-patches

>>>>> "Ulrich" == Ulrich Weigand <uweigand@de.ibm.com> writes:

Ulrich> I'd prefer an interface that simply *returns* a value, which then the
Ulrich> callback would be free to set up as desired.  This would also be much
Ulrich> more in line with all the other interfaces that produce values ...

No problem.

FWIW, I was mostly following the existing code and existing gdbarch
methods, like gdbarch_value_from_register.

I think a decent project would be to consolidate this new method,
gdbarch_convert_register, and gdbarch_value_from_register into a single
approach.

Ulrich> This seems to introduce a bug by ignoring value_offset (v).
Ulrich> If v is of a smaller type than the full register width, only
Ulrich> the appropriate bytes of v2 (which do not always start at the
Ulrich> beginning, in particular on big-endian machines) ought to be
Ulrich> copied over to v.

Thanks.

What do you think of the appended?

Tom

2011-07-21  Tom Tromey  <tromey@redhat.com>

	* amd64-tdep.c (amd64_pseudo_register_read_value): Rename
	from amd64_pseudo_register_read.  Change arguments.  Call
	mark_value_bytes_unavailable when needed.
	(amd64_init_abi): Use set_gdbarch_pseudo_register_read_value, not
	set_gdbarch_pseudo_register_read.
	* sentinel-frame.c (sentinel_frame_prev_register): Use
	regcache_cooked_read_value.
	* regcache.h (regcache_cooked_read_value): Declare.
	* regcache.c (regcache_cooked_read_value): New function.
	(regcache_cooked_read): Call
	gdbarch_pseudo_register_read_value if available.
	* i386-tdep.h (i386_pseudo_register_read_value): Declare.
	(i386_pseudo_register_read): Remove.
	* i386-tdep.c (i386_pseudo_register_read_into_value): Rename from
	i386_pseudo_register_read.  Change arguments.  Call
	mark_value_bytes_unavailable when needed.
	(i386_pseudo_register_read_value): New function.
	(i386_gdbarch_init): Call set_gdbarch_pseudo_register_read_value,
	not set_gdbarch_pseudo_register_read.
	* gdbarch.sh (pseudo_register_read_value): New method.
	* gdbarch.c, gdbarch.h: Rebuild.
	* findvar.c (value_from_register): Call get_frame_register_value.

2011-07-21  Tom Tromey  <tromey@redhat.com>

	* gdb.dwarf2/typeddwarf.c: XFAIL 'z' on x86-64.
	* gdb.dwarf2/typeddwarf.exp (xfail-gdb-test): Add arch_pattern
	argument.
	* gdb.dwarf2/typeddwarf-amd64.S: New file.

diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index de62ac7..051fb13 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -275,14 +275,21 @@ amd64_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
     return i386_pseudo_register_name (gdbarch, regnum);
 }
 
-static enum register_status
-amd64_pseudo_register_read (struct gdbarch *gdbarch,
-			    struct regcache *regcache,
-			    int regnum, gdb_byte *buf)
+static struct value *
+amd64_pseudo_register_read_value (struct gdbarch *gdbarch,
+				  struct regcache *regcache,
+				  int regnum)
 {
   gdb_byte raw_buf[MAX_REGISTER_SIZE];
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum register_status status;
+  struct value *result_value;
+  gdb_byte *buf;
+
+  result_value = allocate_value (register_type (gdbarch, regnum));
+  VALUE_LVAL (result_value) = lval_register;
+  VALUE_REGNUM (result_value) = regnum;
+  buf = value_contents_raw (result_value);
 
   if (i386_byte_regnum_p (gdbarch, regnum))
     {
@@ -297,15 +304,19 @@ amd64_pseudo_register_read (struct gdbarch *gdbarch,
 				      raw_buf);
 	  if (status == REG_VALID)
 	    memcpy (buf, raw_buf + 1, 1);
+	  else
+	    mark_value_bytes_unavailable (result_value, 0,
+					  TYPE_LENGTH (value_type (result_value)));
 	}
       else
 	{
 	  status = regcache_raw_read (regcache, gpnum, raw_buf);
 	  if (status == REG_VALID)
 	    memcpy (buf, raw_buf, 1);
+	  else
+	    mark_value_bytes_unavailable (result_value, 0,
+					  TYPE_LENGTH (value_type (result_value)));
 	}
-
-      return status;
     }
   else if (i386_dword_regnum_p (gdbarch, regnum))
     {
@@ -314,11 +325,15 @@ amd64_pseudo_register_read (struct gdbarch *gdbarch,
       status = regcache_raw_read (regcache, gpnum, raw_buf);
       if (status == REG_VALID)
 	memcpy (buf, raw_buf, 4);
-
-      return status;
+      else
+	mark_value_bytes_unavailable (result_value, 0,
+				      TYPE_LENGTH (value_type (result_value)));
     }
   else
-    return i386_pseudo_register_read (gdbarch, regcache, regnum, buf);
+    i386_pseudo_register_read_into_value (gdbarch, regcache, regnum,
+					  result_value);
+
+  return result_value;
 }
 
 static void
@@ -2494,8 +2509,8 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* Avoid wiring in the MMX registers for now.  */
   tdep->num_mmx_regs = 0;
 
-  set_gdbarch_pseudo_register_read (gdbarch,
-				    amd64_pseudo_register_read);
+  set_gdbarch_pseudo_register_read_value (gdbarch,
+					  amd64_pseudo_register_read_value);
   set_gdbarch_pseudo_register_write (gdbarch,
 				     amd64_pseudo_register_write);
 
diff --git a/gdb/findvar.c b/gdb/findvar.c
index a700c02..af22a01 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -625,10 +625,11 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
   struct gdbarch *gdbarch = get_frame_arch (frame);
   struct type *type1 = check_typedef (type);
   struct value *v;
-  int optim, unavail, ok;
 
   if (gdbarch_convert_register_p (gdbarch, regnum, type1))
     {
+      int optim, unavail, ok;
+
       /* The ISA/ABI need to something weird when obtaining the
          specified value from this register.  It might need to
          re-order non-adjacent, starting with REGNUM (see MIPS and
@@ -643,26 +644,27 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
       ok = gdbarch_register_to_value (gdbarch, frame, regnum, type1,
 				      value_contents_raw (v), &optim,
 				      &unavail);
+
+      if (!ok)
+	{
+	  if (optim)
+	    set_value_optimized_out (v, 1);
+	  if (unavail)
+	    mark_value_bytes_unavailable (v, 0, TYPE_LENGTH (type));
+	}
     }
   else
     {
       int len = TYPE_LENGTH (type);
+      struct value *v2;
 
       /* Construct the value.  */
       v = gdbarch_value_from_register (gdbarch, type, regnum, frame);
 
       /* Get the data.  */
-      ok = get_frame_register_bytes (frame, regnum, value_offset (v), len,
-				     value_contents_raw (v),
-				     &optim, &unavail);
-    }
+      v2 = get_frame_register_value (frame, regnum);
 
-  if (!ok)
-    {
-      if (optim)
-	set_value_optimized_out (v, 1);
-      if (unavail)
-	mark_value_bytes_unavailable (v, 0, TYPE_LENGTH (type));
+      value_contents_copy (v, value_offset (v), v2, 0, len);
     }
 
   return v;
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 1e65c17..600cce6 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -161,6 +161,7 @@ struct gdbarch
   gdbarch_write_pc_ftype *write_pc;
   gdbarch_virtual_frame_pointer_ftype *virtual_frame_pointer;
   gdbarch_pseudo_register_read_ftype *pseudo_register_read;
+  gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value;
   gdbarch_pseudo_register_write_ftype *pseudo_register_write;
   int num_regs;
   int num_pseudo_regs;
@@ -313,6 +314,7 @@ struct gdbarch startup_gdbarch =
   0,  /* write_pc */
   legacy_virtual_frame_pointer,  /* virtual_frame_pointer */
   0,  /* pseudo_register_read */
+  0,  /* pseudo_register_read_value */
   0,  /* pseudo_register_write */
   0,  /* num_regs */
   0,  /* num_pseudo_regs */
@@ -594,6 +596,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of write_pc, has predicate.  */
   /* Skip verify of virtual_frame_pointer, invalid_p == 0 */
   /* Skip verify of pseudo_register_read, has predicate.  */
+  /* Skip verify of pseudo_register_read_value, has predicate.  */
   /* Skip verify of pseudo_register_write, has predicate.  */
   if (gdbarch->num_regs == -1)
     fprintf_unfiltered (log, "\n\tnum_regs");
@@ -1085,6 +1088,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: pseudo_register_read = <%s>\n",
                       host_address_to_string (gdbarch->pseudo_register_read));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_pseudo_register_read_value_p() = %d\n",
+                      gdbarch_pseudo_register_read_value_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: pseudo_register_read_value = <%s>\n",
+                      host_address_to_string (gdbarch->pseudo_register_read_value));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: gdbarch_pseudo_register_write_p() = %d\n",
                       gdbarch_pseudo_register_write_p (gdbarch));
   fprintf_unfiltered (file,
@@ -1700,6 +1709,30 @@ set_gdbarch_pseudo_register_read (struct gdbarch *gdbarch,
 }
 
 int
+gdbarch_pseudo_register_read_value_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->pseudo_register_read_value != NULL;
+}
+
+struct value *
+gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->pseudo_register_read_value != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_pseudo_register_read_value called\n");
+  return gdbarch->pseudo_register_read_value (gdbarch, regcache, cookednum);
+}
+
+void
+set_gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch,
+                                        gdbarch_pseudo_register_read_value_ftype pseudo_register_read_value)
+{
+  gdbarch->pseudo_register_read_value = pseudo_register_read_value;
+}
+
+int
 gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 50221d7..7619581 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -216,6 +216,17 @@ typedef enum register_status (gdbarch_pseudo_register_read_ftype) (struct gdbarc
 extern enum register_status gdbarch_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, gdb_byte *buf);
 extern void set_gdbarch_pseudo_register_read (struct gdbarch *gdbarch, gdbarch_pseudo_register_read_ftype *pseudo_register_read);
 
+/* Read a register into a new struct value.  If the register is wholly
+   or partly unavailable, this should call mark_value_bytes_unavailable
+   as appropriate.  If this is defined, then pseudo_register_read will
+   never be called. */
+
+extern int gdbarch_pseudo_register_read_value_p (struct gdbarch *gdbarch);
+
+typedef struct value * (gdbarch_pseudo_register_read_value_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum);
+extern struct value * gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum);
+extern void set_gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value);
+
 extern int gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch);
 
 typedef void (gdbarch_pseudo_register_write_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, const gdb_byte *buf);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index a628f8c..61094fb 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -418,6 +418,11 @@ F:void:write_pc:struct regcache *regcache, CORE_ADDR val:regcache, val
 m:void:virtual_frame_pointer:CORE_ADDR pc, int *frame_regnum, LONGEST *frame_offset:pc, frame_regnum, frame_offset:0:legacy_virtual_frame_pointer::0
 #
 M:enum register_status:pseudo_register_read:struct regcache *regcache, int cookednum, gdb_byte *buf:regcache, cookednum, buf
+# Read a register into a new struct value.  If the register is wholly
+# or partly unavailable, this should call mark_value_bytes_unavailable
+# as appropriate.  If this is defined, then pseudo_register_read will
+# never be called.
+M:struct value *:pseudo_register_read_value:struct regcache *regcache, int cookednum:regcache, cookednum
 M:void:pseudo_register_write:struct regcache *regcache, int cookednum, const gdb_byte *buf:regcache, cookednum, buf
 #
 v:int:num_regs:::0:-1
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 366d0fa..5fb2efb 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -2780,12 +2780,19 @@ i386_mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum)
   return (I387_ST0_REGNUM (tdep) + fpreg);
 }
 
-enum register_status
-i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
-			   int regnum, gdb_byte *buf)
+/* A helper function for us by i386_pseudo_register_read_value and
+   amd64_pseudo_register_read_value.  It does all the work but reads
+   the data into an already-allocated value.  */
+
+void
+i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
+				      struct regcache *regcache,
+				      int regnum,
+				      struct value *result_value)
 {
   gdb_byte raw_buf[MAX_REGISTER_SIZE];
   enum register_status status;
+  gdb_byte *buf = value_contents_raw (result_value);
 
   if (i386_mmx_regnum_p (gdbarch, regnum))
     {
@@ -2794,8 +2801,10 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
       /* Extract (always little endian).  */
       status = regcache_raw_read (regcache, fpnum, raw_buf);
       if (status != REG_VALID)
-	return status;
-      memcpy (buf, raw_buf, register_size (gdbarch, regnum));
+	mark_value_bytes_unavailable (result_value, 0,
+				      TYPE_LENGTH (value_type (result_value)));
+      else
+	memcpy (buf, raw_buf, register_size (gdbarch, regnum));
     }
   else
     {
@@ -2810,15 +2819,17 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 				      I387_XMM0_REGNUM (tdep) + regnum,
 				      raw_buf);
 	  if (status != REG_VALID)
-	    return status;
-	  memcpy (buf, raw_buf, 16);
+	    mark_value_bytes_unavailable (result_value, 0, 16);
+	  else
+	    memcpy (buf, raw_buf, 16);
 	  /* Read upper 128bits.  */
 	  status = regcache_raw_read (regcache,
 				      tdep->ymm0h_regnum + regnum,
 				      raw_buf);
 	  if (status != REG_VALID)
-	    return status;
-	  memcpy (buf + 16, raw_buf, 16);
+	    mark_value_bytes_unavailable (result_value, 16, 32);
+	  else
+	    memcpy (buf + 16, raw_buf, 16);
 	}
       else if (i386_word_regnum_p (gdbarch, regnum))
 	{
@@ -2827,8 +2838,10 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 	  /* Extract (always little endian).  */
 	  status = regcache_raw_read (regcache, gpnum, raw_buf);
 	  if (status != REG_VALID)
-	    return status;
-	  memcpy (buf, raw_buf, 2);
+	    mark_value_bytes_unavailable (result_value, 0,
+					  TYPE_LENGTH (value_type (result_value)));
+	  else
+	    memcpy (buf, raw_buf, 2);
 	}
       else if (i386_byte_regnum_p (gdbarch, regnum))
 	{
@@ -2841,8 +2854,9 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 	     upper registers.  */
 	  status = regcache_raw_read (regcache, gpnum % 4, raw_buf);
 	  if (status != REG_VALID)
-	    return status;
-	  if (gpnum >= 4)
+	    mark_value_bytes_unavailable (result_value, 0,
+					  TYPE_LENGTH (value_type (result_value)));
+	  else if (gpnum >= 4)
 	    memcpy (buf, raw_buf + 1, 1);
 	  else
 	    memcpy (buf, raw_buf, 1);
@@ -2850,8 +2864,22 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
       else
 	internal_error (__FILE__, __LINE__, _("invalid regnum"));
     }
+}
+
+static struct value *
+i386_pseudo_register_read_value (struct gdbarch *gdbarch,
+				 struct regcache *regcache,
+				 int regnum)
+{
+  struct value *result;
+
+  result = allocate_value (register_type (gdbarch, regnum));
+  VALUE_LVAL (result) = lval_register;
+  VALUE_REGNUM (result) = regnum;
+
+  i386_pseudo_register_read_into_value (gdbarch, regcache, regnum, result);
 
-  return REG_VALID;
+  return result;
 }
 
 void
@@ -7333,7 +7361,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   frame_base_set_default (gdbarch, &i386_frame_base);
 
   /* Pseudo registers may be changed by amd64_init_abi.  */
-  set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read);
+  set_gdbarch_pseudo_register_read_value (gdbarch,
+					  i386_pseudo_register_read_value);
   set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write);
 
   set_tdesc_pseudo_register_type (gdbarch, i386_pseudo_register_type);
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 7fc719c..de11f68 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -311,10 +311,11 @@ extern int i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum);
 extern const char *i386_pseudo_register_name (struct gdbarch *gdbarch,
 					      int regnum);
 
-extern enum register_status i386_pseudo_register_read (struct gdbarch *gdbarch,
-						       struct regcache *regcache,
-						       int regnum,
-						       gdb_byte *buf);
+extern void i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
+						  struct regcache *regcache,
+						  int regnum,
+						  struct value *result);
+
 extern void i386_pseudo_register_write (struct gdbarch *gdbarch,
 					struct regcache *regcache,
 					int regnum, const gdb_byte *buf);
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 41f218d..0af93e8 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -709,11 +709,66 @@ regcache_cooked_read (struct regcache *regcache, int regnum, gdb_byte *buf)
 
       return regcache->register_status[regnum];
     }
+  else if (gdbarch_pseudo_register_read_value_p (regcache->descr->gdbarch))
+    {
+      struct value *mark, *computed;
+      enum register_status result = REG_VALID;
+
+      mark = value_mark ();
+
+      computed = gdbarch_pseudo_register_read_value (regcache->descr->gdbarch,
+						     regcache, regnum);
+      if (value_entirely_available (computed))
+	memcpy (buf, value_contents_raw (computed),
+		regcache->descr->sizeof_register[regnum]);
+      else
+	{
+	  memset (buf, 0, regcache->descr->sizeof_register[regnum]);
+	  result = REG_UNAVAILABLE;
+	}
+
+      value_free_to_mark (mark);
+
+      return result;
+    }
   else
     return gdbarch_pseudo_register_read (regcache->descr->gdbarch, regcache,
 					 regnum, buf);
 }
 
+struct value *
+regcache_cooked_read_value (struct regcache *regcache, int regnum)
+{
+  gdb_assert (regnum >= 0);
+  gdb_assert (regnum < regcache->descr->nr_cooked_registers);
+
+  if (regnum < regcache->descr->nr_raw_registers
+      || (regcache->readonly_p
+	  && regcache->register_status[regnum] != REG_UNKNOWN)
+      || !gdbarch_pseudo_register_read_value_p (regcache->descr->gdbarch))
+    {
+      struct value *result;
+
+      result = allocate_value (register_type (regcache->descr->gdbarch,
+					      regnum));
+      VALUE_LVAL (result) = lval_register;
+      VALUE_REGNUM (result) = regnum;
+
+      /* It is more efficient in general to do this delegation in this
+	 direction than in the other one, even though the value-based
+	 API is preferred.  */
+      if (regcache_cooked_read (regcache, regnum,
+				value_contents_raw (result)) == REG_UNAVAILABLE)
+	mark_value_bytes_unavailable (result, 0,
+				      TYPE_LENGTH (value_type (result)));
+
+      return result;
+    }
+  else
+    return gdbarch_pseudo_register_read_value (regcache->descr->gdbarch,
+					       regcache, regnum);
+}
+
 enum register_status
 regcache_cooked_read_signed (struct regcache *regcache, int regnum,
 			     LONGEST *val)
diff --git a/gdb/regcache.h b/gdb/regcache.h
index 3708c86..7f7dc10 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -104,6 +104,12 @@ enum register_status regcache_cooked_read (struct regcache *regcache,
 void regcache_cooked_write (struct regcache *regcache, int rawnum,
 			    const gdb_byte *buf);
 
+/* Read register REGNUM from REGCACHE and return a new value.  This
+   will call mark_value_bytes_unavailable as appropriate.  */
+
+struct value *regcache_cooked_read_value (struct regcache *regcache,
+					  int regnum);
+
 /* Read a register as a signed/unsigned quantity.  */
 extern enum register_status
   regcache_cooked_read_signed (struct regcache *regcache,
diff --git a/gdb/sentinel-frame.c b/gdb/sentinel-frame.c
index 6c2f3e0..5d018bd 100644
--- a/gdb/sentinel-frame.c
+++ b/gdb/sentinel-frame.c
@@ -48,25 +48,12 @@ sentinel_frame_prev_register (struct frame_info *this_frame,
 			      void **this_prologue_cache,
 			      int regnum)
 {
-  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct frame_unwind_cache *cache = *this_prologue_cache;
   struct value *value;
-  struct type *regtype = register_type (gdbarch, regnum);
 
-  /* Return the actual value.  */
-  value = allocate_value (regtype);
-  VALUE_LVAL (value) = lval_register;
-  VALUE_REGNUM (value) = regnum;
+  value = regcache_cooked_read_value (cache->regcache, regnum);
   VALUE_FRAME_ID (value) = get_frame_id (this_frame);
 
-  /* Use the regcache_cooked_read() method so that it, on the fly,
-     constructs either a raw or pseudo register from the raw
-     register cache.  */
-  if (regcache_cooked_read (cache->regcache,
-			    regnum,
-			    value_contents_raw (value)) == REG_UNAVAILABLE)
-    mark_value_bytes_unavailable (value, 0, TYPE_LENGTH (regtype));
-
   return value;
 }
 
diff --git a/gdb/testsuite/gdb.dwarf2/typeddwarf-amd64.S b/gdb/testsuite/gdb.dwarf2/typeddwarf-amd64.S
new file mode 100644
index 0000000..f97357a
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/typeddwarf-amd64.S
@@ -0,0 +1,1568 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* This source file was generated from typeddwarf.c using the following
+   command line:
+
+   gcc -S -g -O2 typeddwarf.c -o typeddwarf-amd64.S
+
+*/
+
+
+	.file	"typeddwarf.c"
+	.text
+.Ltext0:
+	.globl	f1
+	.type	f1, @function
+f1:
+.LFB0:
+	.file 1 "typeddwarf.c"
+	.loc 1 10 0
+	.cfi_startproc
+.LVL0:
+	.loc 1 29 0
+	movl	vv(%rip), %eax
+	addl	$1, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 30 0
+	ret
+	.cfi_endproc
+.LFE0:
+	.size	f1, .-f1
+	.globl	f2
+	.type	f2, @function
+f2:
+.LFB1:
+	.loc 1 34 0
+	.cfi_startproc
+.LVL1:
+	.loc 1 53 0
+	movl	vv(%rip), %eax
+	addl	$1, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 54 0
+	cvttsd2si	%xmm0, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 55 0
+	cvttsd2si	%xmm1, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 56 0
+	cvttsd2si	%xmm2, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 57 0
+	cvttss2si	%xmm3, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 58 0
+	cvttss2si	%xmm4, %r8d
+	movl	%r8d, vv(%rip)
+	.loc 1 59 0
+	movl	%edi, vv(%rip)
+	.loc 1 60 0
+	movl	%esi, vv(%rip)
+	.loc 1 61 0
+	movl	%edx, vv(%rip)
+	.loc 1 62 0
+	movl	%ecx, vv(%rip)
+	.loc 1 63 0
+	movl	%eax, vv(%rip)
+	.loc 1 64 0
+	ret
+	.cfi_endproc
+.LFE1:
+	.size	f2, .-f2
+	.globl	f3
+	.type	f3, @function
+f3:
+.LFB2:
+	.loc 1 68 0
+	.cfi_startproc
+.LVL2:
+	.loc 1 73 0
+	movl	vv(%rip), %eax
+	addl	$1, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 74 0
+	ret
+	.cfi_endproc
+.LFE2:
+	.size	f3, .-f3
+	.globl	f4
+	.type	f4, @function
+f4:
+.LFB3:
+	.loc 1 78 0
+	.cfi_startproc
+.LVL3:
+	.loc 1 82 0
+	movl	vv(%rip), %eax
+	addl	$1, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 83 0
+	ret
+	.cfi_endproc
+.LFE3:
+	.size	f4, .-f4
+	.globl	_start
+	.type	_start, @function
+_start:
+.LFB4:
+	.loc 1 87 0
+	.cfi_startproc
+	subq	$8, %rsp
+.LCFI0:
+	.cfi_def_cfa_offset 16
+	.loc 1 88 0
+	movl	$9, %ecx
+	movl	$8, %edx
+	movl	$7, %esi
+	movl	$6, %edi
+	movss	.LC2(%rip), %xmm4
+	movss	.LC3(%rip), %xmm3
+	movsd	.LC0(%rip), %xmm2
+	movsd	.LC1(%rip), %xmm1
+	movsd	.LC4(%rip), %xmm0
+	call	f1
+.LVL4:
+	.loc 1 89 0
+	movl	$9, %ecx
+	movl	$8, %edx
+	movl	$7, %esi
+	movl	$6, %edi
+	movss	.LC2(%rip), %xmm4
+	movss	.LC3(%rip), %xmm3
+	movsd	.LC0(%rip), %xmm2
+	movsd	.LC1(%rip), %xmm1
+	movsd	.LC4(%rip), %xmm0
+	call	f2
+.LVL5:
+	.loc 1 90 0
+	movl	$4, %ecx
+	movl	$3, %edx
+	movl	$2, %esi
+	movl	$1, %edi
+	call	f3
+.LVL6:
+	.loc 1 91 0
+	movdqa	.LC5(%rip), %xmm2
+	movq	.LC6(%rip), %xmm1
+	movd	.LC7(%rip), %xmm0
+	call	f4
+.LVL7:
+	.loc 1 93 0
+	movl	$0, %eax
+	addq	$8, %rsp
+.LCFI1:
+	.cfi_def_cfa_offset 8
+	ret
+	.cfi_endproc
+.LFE4:
+	.size	_start, .-_start
+	.comm	vv,4,4
+	.section	.rodata.cst8,"aM",@progbits,8
+	.align 8
+.LC0:
+	.long	0
+	.long	1074266112
+	.align 8
+.LC1:
+	.long	0
+	.long	1073741824
+	.section	.rodata.cst4,"aM",@progbits,4
+	.align 4
+.LC2:
+	.long	1084227584
+	.align 4
+.LC3:
+	.long	1082130432
+	.section	.rodata.cst8
+	.align 8
+.LC4:
+	.long	0
+	.long	1072693248
+	.section	.rodata.cst16,"aM",@progbits,16
+	.align 16
+.LC5:
+	.quad	640
+	.quad	3476215962376601600
+	.section	.rodata.cst8
+	.align 8
+.LC6:
+	.quad	3575858104132173984
+	.section	.rodata.cst4
+	.align 4
+.LC7:
+	.long	838860880
+	.text
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	0x6c4
+	.value	0x2
+	.long	.Ldebug_abbrev0
+	.byte	0x8
+	.uleb128 0x1
+	.long	.LASF8
+	.byte	0x1
+	.long	.LASF9
+	.long	.LASF10
+	.quad	.Ltext0
+	.quad	.Letext0
+	.long	.Ldebug_line0
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0x4
+	.long	.LASF0
+	.uleb128 0x2
+	.byte	0x4
+	.byte	0x4
+	.long	.LASF1
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0x7
+	.long	.LASF2
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0x5
+	.long	.LASF3
+	.uleb128 0x2
+	.byte	0x4
+	.byte	0x7
+	.long	.LASF4
+	.uleb128 0x3
+	.byte	0x4
+	.byte	0x5
+	.string	"int"
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0xf
+	.long	.LASF5
+	.uleb128 0x2
+	.byte	0x4
+	.byte	0xf
+	.long	.LASF6
+	.uleb128 0x2
+	.byte	0x10
+	.byte	0xf
+	.long	.LASF7
+	.uleb128 0x4
+	.byte	0x1
+	.string	"f1"
+	.byte	0x1
+	.byte	0x9
+	.byte	0x1
+	.quad	.LFB0
+	.quad	.LFE0
+	.byte	0x2
+	.byte	0x77
+	.sleb128 8
+	.byte	0x1
+	.long	0x22b
+	.uleb128 0x5
+	.string	"a"
+	.byte	0x1
+	.byte	0x9
+	.long	0x2d
+	.byte	0x1
+	.byte	0x61
+	.uleb128 0x5
+	.string	"b"
+	.byte	0x1
+	.byte	0x9
+	.long	0x2d
+	.byte	0x1
+	.byte	0x62
+	.uleb128 0x5
+	.string	"c"
+	.byte	0x1
+	.byte	0x9
+	.long	0x2d
+	.byte	0x1
+	.byte	0x63
+	.uleb128 0x5
+	.string	"d"
+	.byte	0x1
+	.byte	0x9
+	.long	0x34
+	.byte	0x1
+	.byte	0x64
+	.uleb128 0x5
+	.string	"e"
+	.byte	0x1
+	.byte	0x9
+	.long	0x34
+	.byte	0x1
+	.byte	0x65
+	.uleb128 0x5
+	.string	"f"
+	.byte	0x1
+	.byte	0x9
+	.long	0x50
+	.byte	0x1
+	.byte	0x55
+	.uleb128 0x5
+	.string	"g"
+	.byte	0x1
+	.byte	0x9
+	.long	0x49
+	.byte	0x1
+	.byte	0x54
+	.uleb128 0x5
+	.string	"h"
+	.byte	0x1
+	.byte	0x9
+	.long	0x22b
+	.byte	0x1
+	.byte	0x51
+	.uleb128 0x5
+	.string	"i"
+	.byte	0x1
+	.byte	0x9
+	.long	0x232
+	.byte	0x1
+	.byte	0x52
+	.uleb128 0x6
+	.string	"j"
+	.byte	0x1
+	.byte	0xb
+	.long	0x2d
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"l"
+	.byte	0x1
+	.byte	0xc
+	.long	0x22b
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0xf9
+	.uleb128 0x3b
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"m"
+	.byte	0x1
+	.byte	0xe
+	.long	0x22b
+	.byte	0x1
+	.byte	0x63
+	.uleb128 0x6
+	.string	"n"
+	.byte	0x1
+	.byte	0x10
+	.long	0x34
+	.byte	0x7
+	.byte	0x72
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x3b
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"o"
+	.byte	0x1
+	.byte	0x11
+	.long	0x2d
+	.byte	0x7
+	.byte	0x71
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x42
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"p"
+	.byte	0x1
+	.byte	0x12
+	.long	0x34
+	.byte	0x7
+	.byte	0x74
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x49
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"q"
+	.byte	0x1
+	.byte	0x13
+	.long	0x2d
+	.byte	0x7
+	.byte	0x75
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x50
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"r"
+	.byte	0x1
+	.byte	0x14
+	.long	0x232
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x3b
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"s"
+	.byte	0x1
+	.byte	0x15
+	.long	0x22b
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x13
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x42
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"t"
+	.byte	0x1
+	.byte	0x16
+	.long	0x49
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x49
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"u"
+	.byte	0x1
+	.byte	0x17
+	.long	0x50
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x50
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"v"
+	.byte	0x1
+	.byte	0x18
+	.long	0x34
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"w"
+	.byte	0x1
+	.byte	0x19
+	.long	0x2d
+	.byte	0x12
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x3fd00000
+	.byte	0x1e
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"x"
+	.byte	0x1
+	.byte	0x1a
+	.long	0x2d
+	.byte	0x14
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0x22
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x3ff00000
+	.byte	0x22
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"y"
+	.byte	0x1
+	.byte	0x1b
+	.long	0x2d
+	.byte	0x14
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0xf5
+	.uleb128 0x13
+	.uleb128 0x2d
+	.byte	0x22
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40000000
+	.byte	0x22
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"z"
+	.byte	0x1
+	.byte	0x1c
+	.long	0x34
+	.byte	0x12
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf3
+	.uleb128 0x3
+	.byte	0xf5
+	.uleb128 0x15
+	.uleb128 0x34
+	.byte	0x22
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40400000
+	.byte	0x22
+	.byte	0x9f
+	.byte	0
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0x5
+	.long	.LASF11
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0x7
+	.long	.LASF12
+	.uleb128 0x4
+	.byte	0x1
+	.string	"f2"
+	.byte	0x1
+	.byte	0x21
+	.byte	0x1
+	.quad	.LFB1
+	.quad	.LFE1
+	.byte	0x2
+	.byte	0x77
+	.sleb128 8
+	.byte	0x1
+	.long	0x402
+	.uleb128 0x5
+	.string	"a"
+	.byte	0x1
+	.byte	0x21
+	.long	0x2d
+	.byte	0x1
+	.byte	0x61
+	.uleb128 0x5
+	.string	"b"
+	.byte	0x1
+	.byte	0x21
+	.long	0x2d
+	.byte	0x1
+	.byte	0x62
+	.uleb128 0x5
+	.string	"c"
+	.byte	0x1
+	.byte	0x21
+	.long	0x2d
+	.byte	0x1
+	.byte	0x63
+	.uleb128 0x5
+	.string	"d"
+	.byte	0x1
+	.byte	0x21
+	.long	0x34
+	.byte	0x1
+	.byte	0x64
+	.uleb128 0x5
+	.string	"e"
+	.byte	0x1
+	.byte	0x21
+	.long	0x34
+	.byte	0x1
+	.byte	0x65
+	.uleb128 0x5
+	.string	"f"
+	.byte	0x1
+	.byte	0x21
+	.long	0x50
+	.byte	0x1
+	.byte	0x55
+	.uleb128 0x5
+	.string	"g"
+	.byte	0x1
+	.byte	0x21
+	.long	0x49
+	.byte	0x1
+	.byte	0x54
+	.uleb128 0x5
+	.string	"h"
+	.byte	0x1
+	.byte	0x21
+	.long	0x22b
+	.byte	0x1
+	.byte	0x51
+	.uleb128 0x5
+	.string	"i"
+	.byte	0x1
+	.byte	0x21
+	.long	0x232
+	.byte	0x1
+	.byte	0x52
+	.uleb128 0x6
+	.string	"j"
+	.byte	0x1
+	.byte	0x23
+	.long	0x2d
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"l"
+	.byte	0x1
+	.byte	0x24
+	.long	0x22b
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0xf9
+	.uleb128 0x3b
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"m"
+	.byte	0x1
+	.byte	0x26
+	.long	0x22b
+	.byte	0x1
+	.byte	0x63
+	.uleb128 0x6
+	.string	"n"
+	.byte	0x1
+	.byte	0x28
+	.long	0x34
+	.byte	0x7
+	.byte	0x72
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x3b
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"o"
+	.byte	0x1
+	.byte	0x29
+	.long	0x2d
+	.byte	0x7
+	.byte	0x71
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x42
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"p"
+	.byte	0x1
+	.byte	0x2a
+	.long	0x34
+	.byte	0x7
+	.byte	0x74
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x49
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"q"
+	.byte	0x1
+	.byte	0x2b
+	.long	0x2d
+	.byte	0x7
+	.byte	0x75
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x50
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"r"
+	.byte	0x1
+	.byte	0x2c
+	.long	0x232
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x3b
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"s"
+	.byte	0x1
+	.byte	0x2d
+	.long	0x22b
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x13
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x42
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"t"
+	.byte	0x1
+	.byte	0x2e
+	.long	0x49
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x49
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"u"
+	.byte	0x1
+	.byte	0x2f
+	.long	0x50
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x50
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"v"
+	.byte	0x1
+	.byte	0x30
+	.long	0x34
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"w"
+	.byte	0x1
+	.byte	0x31
+	.long	0x2d
+	.byte	0x12
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x3fd00000
+	.byte	0x1e
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"x"
+	.byte	0x1
+	.byte	0x32
+	.long	0x2d
+	.byte	0x20
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0x22
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40080000
+	.byte	0x1c
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0x78b58c40
+	.long	0x4415af1d
+	.byte	0x22
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"y"
+	.byte	0x1
+	.byte	0x33
+	.long	0x2d
+	.byte	0x14
+	.byte	0xf5
+	.uleb128 0x13
+	.uleb128 0x2d
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x401c0000
+	.byte	0x1e
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0x22
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"z"
+	.byte	0x1
+	.byte	0x34
+	.long	0x34
+	.byte	0x10
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf5
+	.uleb128 0x15
+	.uleb128 0x34
+	.byte	0x22
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40400000
+	.byte	0x22
+	.byte	0x9f
+	.byte	0
+	.uleb128 0x4
+	.byte	0x1
+	.string	"f3"
+	.byte	0x1
+	.byte	0x43
+	.byte	0x1
+	.quad	.LFB2
+	.quad	.LFE2
+	.byte	0x2
+	.byte	0x77
+	.sleb128 8
+	.byte	0x1
+	.long	0x4cd
+	.uleb128 0x5
+	.string	"a"
+	.byte	0x1
+	.byte	0x43
+	.long	0x22b
+	.byte	0x1
+	.byte	0x55
+	.uleb128 0x5
+	.string	"b"
+	.byte	0x1
+	.byte	0x43
+	.long	0x50
+	.byte	0x1
+	.byte	0x54
+	.uleb128 0x5
+	.string	"c"
+	.byte	0x1
+	.byte	0x43
+	.long	0x22b
+	.byte	0x1
+	.byte	0x51
+	.uleb128 0x5
+	.string	"d"
+	.byte	0x1
+	.byte	0x43
+	.long	0x49
+	.byte	0x1
+	.byte	0x52
+	.uleb128 0x6
+	.string	"w"
+	.byte	0x1
+	.byte	0x45
+	.long	0x22b
+	.byte	0x14
+	.byte	0x72
+	.sleb128 0
+	.byte	0xc
+	.long	0xffffffff
+	.byte	0x1a
+	.byte	0x12
+	.byte	0x75
+	.sleb128 0
+	.byte	0x16
+	.byte	0x14
+	.byte	0x2b
+	.byte	0x28
+	.value	0x1
+	.byte	0x16
+	.byte	0x13
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"x"
+	.byte	0x1
+	.byte	0x46
+	.long	0x22b
+	.byte	0xe
+	.byte	0x74
+	.sleb128 0
+	.byte	0x8
+	.byte	0x20
+	.byte	0x24
+	.byte	0x8
+	.byte	0x20
+	.byte	0x26
+	.byte	0x75
+	.sleb128 0
+	.byte	0x22
+	.byte	0x23
+	.uleb128 0x7
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"y"
+	.byte	0x1
+	.byte	0x47
+	.long	0x22b
+	.byte	0x13
+	.byte	0x72
+	.sleb128 0
+	.byte	0xc
+	.long	0xffffffff
+	.byte	0x1a
+	.byte	0x71
+	.sleb128 0
+	.byte	0x22
+	.byte	0x23
+	.uleb128 0x912345678
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"z"
+	.byte	0x1
+	.byte	0x48
+	.long	0x50
+	.byte	0x21
+	.byte	0x74
+	.sleb128 0
+	.byte	0x8
+	.byte	0x20
+	.byte	0x24
+	.byte	0x8
+	.byte	0x20
+	.byte	0x26
+	.byte	0x75
+	.sleb128 0
+	.byte	0x22
+	.byte	0x23
+	.uleb128 0x7
+	.byte	0x72
+	.sleb128 0
+	.byte	0xc
+	.long	0xffffffff
+	.byte	0x1a
+	.byte	0x71
+	.sleb128 0
+	.byte	0x22
+	.byte	0x23
+	.uleb128 0x912345678
+	.byte	0x22
+	.byte	0x9f
+	.byte	0
+	.uleb128 0x4
+	.byte	0x1
+	.string	"f4"
+	.byte	0x1
+	.byte	0x4d
+	.byte	0x1
+	.quad	.LFB3
+	.quad	.LFE3
+	.byte	0x2
+	.byte	0x77
+	.sleb128 8
+	.byte	0x1
+	.long	0x576
+	.uleb128 0x5
+	.string	"a"
+	.byte	0x1
+	.byte	0x4d
+	.long	0x5e
+	.byte	0x1
+	.byte	0x61
+	.uleb128 0x5
+	.string	"b"
+	.byte	0x1
+	.byte	0x4d
+	.long	0x57
+	.byte	0x1
+	.byte	0x62
+	.uleb128 0x5
+	.string	"c"
+	.byte	0x1
+	.byte	0x4d
+	.long	0x65
+	.byte	0x1
+	.byte	0x63
+	.uleb128 0x6
+	.string	"w"
+	.byte	0x1
+	.byte	0x4f
+	.long	0x5e
+	.byte	0x14
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x5e
+	.byte	0xf4
+	.uleb128 0x5e
+	.byte	0x4
+	.long	0x32000050
+	.byte	0x1e
+	.byte	0xf4
+	.uleb128 0x5e
+	.byte	0x4
+	.long	0x3200003c
+	.byte	0x22
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"x"
+	.byte	0x1
+	.byte	0x50
+	.long	0x57
+	.byte	0x1c
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x57
+	.byte	0xf4
+	.uleb128 0x57
+	.byte	0x8
+	.long	0x50
+	.long	0x31a00000
+	.byte	0x1b
+	.byte	0xf4
+	.uleb128 0x57
+	.byte	0x8
+	.long	0x3c
+	.long	0x31a00000
+	.byte	0x1c
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"y"
+	.byte	0x1
+	.byte	0x51
+	.long	0x65
+	.byte	0x19
+	.byte	0xf5
+	.uleb128 0x13
+	.uleb128 0x65
+	.byte	0x1f
+	.byte	0xf4
+	.uleb128 0x65
+	.byte	0x10
+	.long	0x50
+	.long	0
+	.long	0
+	.long	0x303e0000
+	.byte	0x1b
+	.byte	0x9f
+	.byte	0
+	.uleb128 0x7
+	.byte	0x1
+	.long	.LASF13
+	.byte	0x1
+	.byte	0x56
+	.long	0x50
+	.quad	.LFB4
+	.quad	.LFE4
+	.long	.LLST0
+	.byte	0x1
+	.long	0x6a1
+	.uleb128 0x8
+	.quad	.LVL4
+	.long	0x6c
+	.long	0x604
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x61
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x3ff00000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x62
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40000000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x63
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40080000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x64
+	.byte	0x7
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40800000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x65
+	.byte	0x7
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40a00000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x55
+	.byte	0x1
+	.byte	0x36
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x54
+	.byte	0x1
+	.byte	0x37
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x51
+	.byte	0x1
+	.byte	0x38
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x52
+	.byte	0x1
+	.byte	0x39
+	.byte	0
+	.uleb128 0x8
+	.quad	.LVL5
+	.long	0x239
+	.long	0x66d
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x61
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x3ff00000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x62
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40000000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x63
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40080000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x64
+	.byte	0x7
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40800000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x65
+	.byte	0x7
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40a00000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x55
+	.byte	0x1
+	.byte	0x36
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x54
+	.byte	0x1
+	.byte	0x37
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x51
+	.byte	0x1
+	.byte	0x38
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x52
+	.byte	0x1
+	.byte	0x39
+	.byte	0
+	.uleb128 0x8
+	.quad	.LVL6
+	.long	0x402
+	.long	0x693
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x55
+	.byte	0x1
+	.byte	0x31
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x54
+	.byte	0x1
+	.byte	0x32
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x51
+	.byte	0x1
+	.byte	0x33
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x52
+	.byte	0x1
+	.byte	0x34
+	.byte	0
+	.uleb128 0xa
+	.quad	.LVL7
+	.long	0x4cd
+	.byte	0
+	.uleb128 0xb
+	.string	"vv"
+	.byte	0x1
+	.byte	0x5
+	.long	0x6ad
+	.byte	0x1
+	.byte	0x1
+	.uleb128 0xc
+	.long	0x50
+	.uleb128 0xd
+	.string	"vv"
+	.byte	0x1
+	.byte	0x5
+	.long	0x6ad
+	.byte	0x1
+	.byte	0x9
+	.byte	0x3
+	.quad	vv
+	.byte	0
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1
+	.uleb128 0x11
+	.byte	0x1
+	.uleb128 0x25
+	.uleb128 0xe
+	.uleb128 0x13
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x1b
+	.uleb128 0xe
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x1
+	.uleb128 0x10
+	.uleb128 0x6
+	.byte	0
+	.byte	0
+	.uleb128 0x2
+	.uleb128 0x24
+	.byte	0
+	.uleb128 0xb
+	.uleb128 0xb
+	.uleb128 0x3e
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0xe
+	.byte	0
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x24
+	.byte	0
+	.uleb128 0xb
+	.uleb128 0xb
+	.uleb128 0x3e
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0x8
+	.byte	0
+	.byte	0
+	.uleb128 0x4
+	.uleb128 0x2e
+	.byte	0x1
+	.uleb128 0x3f
+	.uleb128 0xc
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x27
+	.uleb128 0xc
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x1
+	.uleb128 0x40
+	.uleb128 0xa
+	.uleb128 0x2117
+	.uleb128 0xc
+	.uleb128 0x1
+	.uleb128 0x13
+	.byte	0
+	.byte	0
+	.uleb128 0x5
+	.uleb128 0x5
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x2
+	.uleb128 0xa
+	.byte	0
+	.byte	0
+	.uleb128 0x6
+	.uleb128 0x34
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x2
+	.uleb128 0xa
+	.byte	0
+	.byte	0
+	.uleb128 0x7
+	.uleb128 0x2e
+	.byte	0x1
+	.uleb128 0x3f
+	.uleb128 0xc
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x1
+	.uleb128 0x40
+	.uleb128 0x6
+	.uleb128 0x2117
+	.uleb128 0xc
+	.uleb128 0x1
+	.uleb128 0x13
+	.byte	0
+	.byte	0
+	.uleb128 0x8
+	.uleb128 0x4109
+	.byte	0x1
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x31
+	.uleb128 0x13
+	.uleb128 0x1
+	.uleb128 0x13
+	.byte	0
+	.byte	0
+	.uleb128 0x9
+	.uleb128 0x410a
+	.byte	0
+	.uleb128 0x2
+	.uleb128 0xa
+	.uleb128 0x2111
+	.uleb128 0xa
+	.byte	0
+	.byte	0
+	.uleb128 0xa
+	.uleb128 0x4109
+	.byte	0
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x31
+	.uleb128 0x13
+	.byte	0
+	.byte	0
+	.uleb128 0xb
+	.uleb128 0x34
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x3f
+	.uleb128 0xc
+	.uleb128 0x3c
+	.uleb128 0xc
+	.byte	0
+	.byte	0
+	.uleb128 0xc
+	.uleb128 0x35
+	.byte	0
+	.uleb128 0x49
+	.uleb128 0x13
+	.byte	0
+	.byte	0
+	.uleb128 0xd
+	.uleb128 0x34
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x3f
+	.uleb128 0xc
+	.uleb128 0x2
+	.uleb128 0xa
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_loc,"",@progbits
+.Ldebug_loc0:
+.LLST0:
+	.quad	.LFB4-.Ltext0
+	.quad	.LCFI0-.Ltext0
+	.value	0x2
+	.byte	0x77
+	.sleb128 8
+	.quad	.LCFI0-.Ltext0
+	.quad	.LCFI1-.Ltext0
+	.value	0x2
+	.byte	0x77
+	.sleb128 16
+	.quad	.LCFI1-.Ltext0
+	.quad	.LFE4-.Ltext0
+	.value	0x2
+	.byte	0x77
+	.sleb128 8
+	.quad	0
+	.quad	0
+	.section	.debug_aranges,"",@progbits
+	.long	0x2c
+	.value	0x2
+	.long	.Ldebug_info0
+	.byte	0x8
+	.byte	0
+	.value	0
+	.value	0
+	.quad	.Ltext0
+	.quad	.Letext0-.Ltext0
+	.quad	0
+	.quad	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF4:
+	.string	"unsigned int"
+.LASF6:
+	.string	"_Decimal32"
+.LASF7:
+	.string	"_Decimal128"
+.LASF2:
+	.string	"long unsigned int"
+.LASF12:
+	.string	"long long unsigned int"
+.LASF5:
+	.string	"_Decimal64"
+.LASF13:
+	.string	"main"
+.LASF3:
+	.string	"long int"
+.LASF10:
+	.string	"/tmp"
+.LASF0:
+	.string	"double"
+.LASF11:
+	.string	"long long int"
+.LASF1:
+	.string	"float"
+.LASF8:
+	.string	"GNU C 4.7.0 20110708 (experimental) [trunk revision 176048]"
+.LASF9:
+	.string	"typeddwarf.c"
+	.ident	"GCC: (GNU) 4.7.0 20110708 (experimental) [trunk revision 176048]"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.dwarf2/typeddwarf.c b/gdb/testsuite/gdb.dwarf2/typeddwarf.c
index e5f7d67..40497da 100644
--- a/gdb/testsuite/gdb.dwarf2/typeddwarf.c
+++ b/gdb/testsuite/gdb.dwarf2/typeddwarf.c
@@ -25,7 +25,7 @@ f1 (double a, double b, double c, float d, float e, int f, unsigned int g, long
   double w = d / 4.0;		/* { dg-final { gdb-test 29 "w" "1" } } */
   double x = a + b + 1.0;	/* { dg-final { gdb-test 29 "x" "4" } } */
   double y = b + c + 2.0;	/* { dg-final { gdb-test 29 "y" "7" } } */
-  float z = d + e + 3.0f;	/* { dg-final { gdb-test 29 "z" "12" } } */
+  float z = d + e + 3.0f;	/* { dg-final { xfail-gdb-test 29 "z" "12" "x86_64-*-*"} } */
   vv++;
 }
 
diff --git a/gdb/testsuite/gdb.dwarf2/typeddwarf.exp b/gdb/testsuite/gdb.dwarf2/typeddwarf.exp
index e6a420a..36a17e5 100644
--- a/gdb/testsuite/gdb.dwarf2/typeddwarf.exp
+++ b/gdb/testsuite/gdb.dwarf2/typeddwarf.exp
@@ -22,12 +22,16 @@ if ![dwarf2_support] {
     return 0  
 }
 
-# This test can only be run on x86 targets.
-if { ![is_x86_like_target] } {
+# This test can only be run on x86 and amd64 targets.
+if { [is_x86_like_target] } {
+    set sfile ${test}.S
+} elseif {[istarget "x86_64-*-*"]} {
+    set sfile ${test}-amd64.S
+} else {
     return 0
 }
 
-if { [prepare_for_testing "${test}.exp" "${test}" ${test}.S {nodebug additional_flags=-nostdlib}] } {
+if { [prepare_for_testing "${test}.exp" "${test}" ${sfile} {nodebug additional_flags=-nostdlib}] } {
     return -1
 }
 
@@ -45,10 +49,19 @@ proc gdb-test {line var value} {
     lappend tests($line) [list $var $value 0]
 }
 
-proc xfail-gdb-test {line var value} {
+# Add an XFAIL'd test.  If ARCH_PATTERN is given, and does not match
+# the target, then the test is simply added and not XFAIL'd.
+proc xfail-gdb-test {line var value {arch_pattern ""}} {
     global tests
 
-    lappend tests($line) [list $var $value 1]
+    set flag 1
+    if {$arch_pattern != ""} {
+	if {! [istarget $arch_pattern]} {
+	    set flag 0
+	}
+    }
+
+    lappend tests($line) [list $var $value $flag]
 }
 
 proc scan_gdb_tests {} {

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

* Re: RFC: partially available registers
  2011-07-21 20:27         ` Tom Tromey
@ 2011-07-22 13:48           ` Ulrich Weigand
  2011-07-22 15:42             ` Tom Tromey
  0 siblings, 1 reply; 28+ messages in thread
From: Ulrich Weigand @ 2011-07-22 13:48 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Daniel Jacobowitz, gdb-patches

Tom Tromey wrote:

> FWIW, I was mostly following the existing code and existing gdbarch
> methods, like gdbarch_value_from_register.

This looks good to me, thanks.

> I think a decent project would be to consolidate this new method,
> gdbarch_convert_register, and gdbarch_value_from_register into a single
> approach.

Agreed.  I actually had a patchset a while ago that would get rid of
gdbarch_convert_register, but that was never quite completed ...
I'll have to see to get this done at some point.

>        int len = TYPE_LENGTH (type);
> +      struct value *v2;
>  
>        /* Construct the value.  */
>        v = gdbarch_value_from_register (gdbarch, type, regnum, frame);
>  
>        /* Get the data.  */
> -      ok = get_frame_register_bytes (frame, regnum, value_offset (v), len,
> -				     value_contents_raw (v),
> -				     &optim, &unavail);
> -    }
> +      v2 = get_frame_register_value (frame, regnum);
>  
> -  if (!ok)
> -    {
> -      if (optim)
> -	set_value_optimized_out (v, 1);
> -      if (unavail)
> -	mark_value_bytes_unavailable (v, 0, TYPE_LENGTH (type));
> +      value_contents_copy (v, value_offset (v), v2, 0, len);

This still looks wrong, I think.  It should be:

    value_contents_copy (v, 0, v2, value_offset (v), len);

(v2 is the full register.  value_offset (v) specifies at which byte of
that full register contents the contents of v start ...)

The rest looks good to me.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

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

* Re: RFC: partially available registers
  2011-07-20 20:46     ` Tom Tromey
  2011-07-20 20:53       ` Tom Tromey
  2011-07-21  5:23       ` Ulrich Weigand
@ 2011-07-22 14:30       ` Pedro Alves
  2011-07-22 15:40         ` Tom Tromey
  2 siblings, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2011-07-22 14:30 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey, Daniel Jacobowitz

Hi Tom,

On Wednesday 20 July 2011 21:14:08, Tom Tromey wrote:

> 2011-07-20  Tom Tromey  <tromey@redhat.com>
> 
> 	* gdb.dwarf2/typeddwarf.c: XFAIL 'z' on x86-64.
> 	* gdb.dwarf2/typeddwarf.exp (xfail-gdb-test): Add arch_pattern
> 	argument.
> 	* gdb.dwarf2/typeddwarf-amd64.S: New file.

I get:

# of expected passes            39

with an unpatched gdb (x86-64-linux), same as with patched gdb.
Is that expected?

-- 
Pedro Alves

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

* Re: RFC: partially available registers
  2011-07-22 14:30       ` Pedro Alves
@ 2011-07-22 15:40         ` Tom Tromey
  2011-07-22 19:10           ` Pedro Alves
  0 siblings, 1 reply; 28+ messages in thread
From: Tom Tromey @ 2011-07-22 15:40 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches, Daniel Jacobowitz

>>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes:

Pedro> # of expected passes            39
Pedro> with an unpatched gdb (x86-64-linux), same as with patched gdb.
Pedro> Is that expected?

It definitely fails for me with unpatched gdb.

Does your machine have AVX?  I believe it will only fail on an
AVX-capable machine.

Tom

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

* Re: RFC: partially available registers
  2011-07-22 13:48           ` Ulrich Weigand
@ 2011-07-22 15:42             ` Tom Tromey
  0 siblings, 0 replies; 28+ messages in thread
From: Tom Tromey @ 2011-07-22 15:42 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: Daniel Jacobowitz, gdb-patches

>>>>> "Ulrich" == Ulrich Weigand <uweigand@de.ibm.com> writes:

Ulrich> This still looks wrong, I think.  It should be:
Ulrich>     value_contents_copy (v, 0, v2, value_offset (v), len);
Ulrich> (v2 is the full register.  value_offset (v) specifies at which byte of
Ulrich> that full register contents the contents of v start ...)

Thanks again.
I'm checking in the appended, which has this change.

Tom

2011-07-21  Tom Tromey  <tromey@redhat.com>

	* amd64-tdep.c (amd64_pseudo_register_read_value): Rename
	from amd64_pseudo_register_read.  Change arguments.  Call
	mark_value_bytes_unavailable when needed.
	(amd64_init_abi): Use set_gdbarch_pseudo_register_read_value, not
	set_gdbarch_pseudo_register_read.
	* sentinel-frame.c (sentinel_frame_prev_register): Use
	regcache_cooked_read_value.
	* regcache.h (regcache_cooked_read_value): Declare.
	* regcache.c (regcache_cooked_read_value): New function.
	(regcache_cooked_read): Call
	gdbarch_pseudo_register_read_value if available.
	* i386-tdep.h (i386_pseudo_register_read_value): Declare.
	(i386_pseudo_register_read): Remove.
	* i386-tdep.c (i386_pseudo_register_read_into_value): Rename from
	i386_pseudo_register_read.  Change arguments.  Call
	mark_value_bytes_unavailable when needed.
	(i386_pseudo_register_read_value): New function.
	(i386_gdbarch_init): Call set_gdbarch_pseudo_register_read_value,
	not set_gdbarch_pseudo_register_read.
	* gdbarch.sh (pseudo_register_read_value): New method.
	* gdbarch.c, gdbarch.h: Rebuild.
	* findvar.c (value_from_register): Call get_frame_register_value.

2011-07-21  Tom Tromey  <tromey@redhat.com>

	* gdb.dwarf2/typeddwarf.c: XFAIL 'z' on x86-64.
	* gdb.dwarf2/typeddwarf.exp (xfail-gdb-test): Add arch_pattern
	argument.
	* gdb.dwarf2/typeddwarf-amd64.S: New file.

diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index de62ac7..051fb13 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -275,14 +275,21 @@ amd64_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
     return i386_pseudo_register_name (gdbarch, regnum);
 }
 
-static enum register_status
-amd64_pseudo_register_read (struct gdbarch *gdbarch,
-			    struct regcache *regcache,
-			    int regnum, gdb_byte *buf)
+static struct value *
+amd64_pseudo_register_read_value (struct gdbarch *gdbarch,
+				  struct regcache *regcache,
+				  int regnum)
 {
   gdb_byte raw_buf[MAX_REGISTER_SIZE];
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum register_status status;
+  struct value *result_value;
+  gdb_byte *buf;
+
+  result_value = allocate_value (register_type (gdbarch, regnum));
+  VALUE_LVAL (result_value) = lval_register;
+  VALUE_REGNUM (result_value) = regnum;
+  buf = value_contents_raw (result_value);
 
   if (i386_byte_regnum_p (gdbarch, regnum))
     {
@@ -297,15 +304,19 @@ amd64_pseudo_register_read (struct gdbarch *gdbarch,
 				      raw_buf);
 	  if (status == REG_VALID)
 	    memcpy (buf, raw_buf + 1, 1);
+	  else
+	    mark_value_bytes_unavailable (result_value, 0,
+					  TYPE_LENGTH (value_type (result_value)));
 	}
       else
 	{
 	  status = regcache_raw_read (regcache, gpnum, raw_buf);
 	  if (status == REG_VALID)
 	    memcpy (buf, raw_buf, 1);
+	  else
+	    mark_value_bytes_unavailable (result_value, 0,
+					  TYPE_LENGTH (value_type (result_value)));
 	}
-
-      return status;
     }
   else if (i386_dword_regnum_p (gdbarch, regnum))
     {
@@ -314,11 +325,15 @@ amd64_pseudo_register_read (struct gdbarch *gdbarch,
       status = regcache_raw_read (regcache, gpnum, raw_buf);
       if (status == REG_VALID)
 	memcpy (buf, raw_buf, 4);
-
-      return status;
+      else
+	mark_value_bytes_unavailable (result_value, 0,
+				      TYPE_LENGTH (value_type (result_value)));
     }
   else
-    return i386_pseudo_register_read (gdbarch, regcache, regnum, buf);
+    i386_pseudo_register_read_into_value (gdbarch, regcache, regnum,
+					  result_value);
+
+  return result_value;
 }
 
 static void
@@ -2494,8 +2509,8 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* Avoid wiring in the MMX registers for now.  */
   tdep->num_mmx_regs = 0;
 
-  set_gdbarch_pseudo_register_read (gdbarch,
-				    amd64_pseudo_register_read);
+  set_gdbarch_pseudo_register_read_value (gdbarch,
+					  amd64_pseudo_register_read_value);
   set_gdbarch_pseudo_register_write (gdbarch,
 				     amd64_pseudo_register_write);
 
diff --git a/gdb/findvar.c b/gdb/findvar.c
index a700c02..69dc5a0 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -625,10 +625,11 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
   struct gdbarch *gdbarch = get_frame_arch (frame);
   struct type *type1 = check_typedef (type);
   struct value *v;
-  int optim, unavail, ok;
 
   if (gdbarch_convert_register_p (gdbarch, regnum, type1))
     {
+      int optim, unavail, ok;
+
       /* The ISA/ABI need to something weird when obtaining the
          specified value from this register.  It might need to
          re-order non-adjacent, starting with REGNUM (see MIPS and
@@ -643,26 +644,27 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
       ok = gdbarch_register_to_value (gdbarch, frame, regnum, type1,
 				      value_contents_raw (v), &optim,
 				      &unavail);
+
+      if (!ok)
+	{
+	  if (optim)
+	    set_value_optimized_out (v, 1);
+	  if (unavail)
+	    mark_value_bytes_unavailable (v, 0, TYPE_LENGTH (type));
+	}
     }
   else
     {
       int len = TYPE_LENGTH (type);
+      struct value *v2;
 
       /* Construct the value.  */
       v = gdbarch_value_from_register (gdbarch, type, regnum, frame);
 
       /* Get the data.  */
-      ok = get_frame_register_bytes (frame, regnum, value_offset (v), len,
-				     value_contents_raw (v),
-				     &optim, &unavail);
-    }
+      v2 = get_frame_register_value (frame, regnum);
 
-  if (!ok)
-    {
-      if (optim)
-	set_value_optimized_out (v, 1);
-      if (unavail)
-	mark_value_bytes_unavailable (v, 0, TYPE_LENGTH (type));
+      value_contents_copy (v, 0, v2, value_offset (v), len);
     }
 
   return v;
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 1e65c17..600cce6 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -161,6 +161,7 @@ struct gdbarch
   gdbarch_write_pc_ftype *write_pc;
   gdbarch_virtual_frame_pointer_ftype *virtual_frame_pointer;
   gdbarch_pseudo_register_read_ftype *pseudo_register_read;
+  gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value;
   gdbarch_pseudo_register_write_ftype *pseudo_register_write;
   int num_regs;
   int num_pseudo_regs;
@@ -313,6 +314,7 @@ struct gdbarch startup_gdbarch =
   0,  /* write_pc */
   legacy_virtual_frame_pointer,  /* virtual_frame_pointer */
   0,  /* pseudo_register_read */
+  0,  /* pseudo_register_read_value */
   0,  /* pseudo_register_write */
   0,  /* num_regs */
   0,  /* num_pseudo_regs */
@@ -594,6 +596,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of write_pc, has predicate.  */
   /* Skip verify of virtual_frame_pointer, invalid_p == 0 */
   /* Skip verify of pseudo_register_read, has predicate.  */
+  /* Skip verify of pseudo_register_read_value, has predicate.  */
   /* Skip verify of pseudo_register_write, has predicate.  */
   if (gdbarch->num_regs == -1)
     fprintf_unfiltered (log, "\n\tnum_regs");
@@ -1085,6 +1088,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: pseudo_register_read = <%s>\n",
                       host_address_to_string (gdbarch->pseudo_register_read));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_pseudo_register_read_value_p() = %d\n",
+                      gdbarch_pseudo_register_read_value_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: pseudo_register_read_value = <%s>\n",
+                      host_address_to_string (gdbarch->pseudo_register_read_value));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: gdbarch_pseudo_register_write_p() = %d\n",
                       gdbarch_pseudo_register_write_p (gdbarch));
   fprintf_unfiltered (file,
@@ -1700,6 +1709,30 @@ set_gdbarch_pseudo_register_read (struct gdbarch *gdbarch,
 }
 
 int
+gdbarch_pseudo_register_read_value_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->pseudo_register_read_value != NULL;
+}
+
+struct value *
+gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->pseudo_register_read_value != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_pseudo_register_read_value called\n");
+  return gdbarch->pseudo_register_read_value (gdbarch, regcache, cookednum);
+}
+
+void
+set_gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch,
+                                        gdbarch_pseudo_register_read_value_ftype pseudo_register_read_value)
+{
+  gdbarch->pseudo_register_read_value = pseudo_register_read_value;
+}
+
+int
 gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 50221d7..7619581 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -216,6 +216,17 @@ typedef enum register_status (gdbarch_pseudo_register_read_ftype) (struct gdbarc
 extern enum register_status gdbarch_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, gdb_byte *buf);
 extern void set_gdbarch_pseudo_register_read (struct gdbarch *gdbarch, gdbarch_pseudo_register_read_ftype *pseudo_register_read);
 
+/* Read a register into a new struct value.  If the register is wholly
+   or partly unavailable, this should call mark_value_bytes_unavailable
+   as appropriate.  If this is defined, then pseudo_register_read will
+   never be called. */
+
+extern int gdbarch_pseudo_register_read_value_p (struct gdbarch *gdbarch);
+
+typedef struct value * (gdbarch_pseudo_register_read_value_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum);
+extern struct value * gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum);
+extern void set_gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value);
+
 extern int gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch);
 
 typedef void (gdbarch_pseudo_register_write_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, const gdb_byte *buf);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index a628f8c..61094fb 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -418,6 +418,11 @@ F:void:write_pc:struct regcache *regcache, CORE_ADDR val:regcache, val
 m:void:virtual_frame_pointer:CORE_ADDR pc, int *frame_regnum, LONGEST *frame_offset:pc, frame_regnum, frame_offset:0:legacy_virtual_frame_pointer::0
 #
 M:enum register_status:pseudo_register_read:struct regcache *regcache, int cookednum, gdb_byte *buf:regcache, cookednum, buf
+# Read a register into a new struct value.  If the register is wholly
+# or partly unavailable, this should call mark_value_bytes_unavailable
+# as appropriate.  If this is defined, then pseudo_register_read will
+# never be called.
+M:struct value *:pseudo_register_read_value:struct regcache *regcache, int cookednum:regcache, cookednum
 M:void:pseudo_register_write:struct regcache *regcache, int cookednum, const gdb_byte *buf:regcache, cookednum, buf
 #
 v:int:num_regs:::0:-1
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 366d0fa..5fb2efb 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -2780,12 +2780,19 @@ i386_mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum)
   return (I387_ST0_REGNUM (tdep) + fpreg);
 }
 
-enum register_status
-i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
-			   int regnum, gdb_byte *buf)
+/* A helper function for us by i386_pseudo_register_read_value and
+   amd64_pseudo_register_read_value.  It does all the work but reads
+   the data into an already-allocated value.  */
+
+void
+i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
+				      struct regcache *regcache,
+				      int regnum,
+				      struct value *result_value)
 {
   gdb_byte raw_buf[MAX_REGISTER_SIZE];
   enum register_status status;
+  gdb_byte *buf = value_contents_raw (result_value);
 
   if (i386_mmx_regnum_p (gdbarch, regnum))
     {
@@ -2794,8 +2801,10 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
       /* Extract (always little endian).  */
       status = regcache_raw_read (regcache, fpnum, raw_buf);
       if (status != REG_VALID)
-	return status;
-      memcpy (buf, raw_buf, register_size (gdbarch, regnum));
+	mark_value_bytes_unavailable (result_value, 0,
+				      TYPE_LENGTH (value_type (result_value)));
+      else
+	memcpy (buf, raw_buf, register_size (gdbarch, regnum));
     }
   else
     {
@@ -2810,15 +2819,17 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 				      I387_XMM0_REGNUM (tdep) + regnum,
 				      raw_buf);
 	  if (status != REG_VALID)
-	    return status;
-	  memcpy (buf, raw_buf, 16);
+	    mark_value_bytes_unavailable (result_value, 0, 16);
+	  else
+	    memcpy (buf, raw_buf, 16);
 	  /* Read upper 128bits.  */
 	  status = regcache_raw_read (regcache,
 				      tdep->ymm0h_regnum + regnum,
 				      raw_buf);
 	  if (status != REG_VALID)
-	    return status;
-	  memcpy (buf + 16, raw_buf, 16);
+	    mark_value_bytes_unavailable (result_value, 16, 32);
+	  else
+	    memcpy (buf + 16, raw_buf, 16);
 	}
       else if (i386_word_regnum_p (gdbarch, regnum))
 	{
@@ -2827,8 +2838,10 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 	  /* Extract (always little endian).  */
 	  status = regcache_raw_read (regcache, gpnum, raw_buf);
 	  if (status != REG_VALID)
-	    return status;
-	  memcpy (buf, raw_buf, 2);
+	    mark_value_bytes_unavailable (result_value, 0,
+					  TYPE_LENGTH (value_type (result_value)));
+	  else
+	    memcpy (buf, raw_buf, 2);
 	}
       else if (i386_byte_regnum_p (gdbarch, regnum))
 	{
@@ -2841,8 +2854,9 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 	     upper registers.  */
 	  status = regcache_raw_read (regcache, gpnum % 4, raw_buf);
 	  if (status != REG_VALID)
-	    return status;
-	  if (gpnum >= 4)
+	    mark_value_bytes_unavailable (result_value, 0,
+					  TYPE_LENGTH (value_type (result_value)));
+	  else if (gpnum >= 4)
 	    memcpy (buf, raw_buf + 1, 1);
 	  else
 	    memcpy (buf, raw_buf, 1);
@@ -2850,8 +2864,22 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
       else
 	internal_error (__FILE__, __LINE__, _("invalid regnum"));
     }
+}
+
+static struct value *
+i386_pseudo_register_read_value (struct gdbarch *gdbarch,
+				 struct regcache *regcache,
+				 int regnum)
+{
+  struct value *result;
+
+  result = allocate_value (register_type (gdbarch, regnum));
+  VALUE_LVAL (result) = lval_register;
+  VALUE_REGNUM (result) = regnum;
+
+  i386_pseudo_register_read_into_value (gdbarch, regcache, regnum, result);
 
-  return REG_VALID;
+  return result;
 }
 
 void
@@ -7333,7 +7361,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   frame_base_set_default (gdbarch, &i386_frame_base);
 
   /* Pseudo registers may be changed by amd64_init_abi.  */
-  set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read);
+  set_gdbarch_pseudo_register_read_value (gdbarch,
+					  i386_pseudo_register_read_value);
   set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write);
 
   set_tdesc_pseudo_register_type (gdbarch, i386_pseudo_register_type);
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 7fc719c..de11f68 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -311,10 +311,11 @@ extern int i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum);
 extern const char *i386_pseudo_register_name (struct gdbarch *gdbarch,
 					      int regnum);
 
-extern enum register_status i386_pseudo_register_read (struct gdbarch *gdbarch,
-						       struct regcache *regcache,
-						       int regnum,
-						       gdb_byte *buf);
+extern void i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
+						  struct regcache *regcache,
+						  int regnum,
+						  struct value *result);
+
 extern void i386_pseudo_register_write (struct gdbarch *gdbarch,
 					struct regcache *regcache,
 					int regnum, const gdb_byte *buf);
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 41f218d..0af93e8 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -709,11 +709,66 @@ regcache_cooked_read (struct regcache *regcache, int regnum, gdb_byte *buf)
 
       return regcache->register_status[regnum];
     }
+  else if (gdbarch_pseudo_register_read_value_p (regcache->descr->gdbarch))
+    {
+      struct value *mark, *computed;
+      enum register_status result = REG_VALID;
+
+      mark = value_mark ();
+
+      computed = gdbarch_pseudo_register_read_value (regcache->descr->gdbarch,
+						     regcache, regnum);
+      if (value_entirely_available (computed))
+	memcpy (buf, value_contents_raw (computed),
+		regcache->descr->sizeof_register[regnum]);
+      else
+	{
+	  memset (buf, 0, regcache->descr->sizeof_register[regnum]);
+	  result = REG_UNAVAILABLE;
+	}
+
+      value_free_to_mark (mark);
+
+      return result;
+    }
   else
     return gdbarch_pseudo_register_read (regcache->descr->gdbarch, regcache,
 					 regnum, buf);
 }
 
+struct value *
+regcache_cooked_read_value (struct regcache *regcache, int regnum)
+{
+  gdb_assert (regnum >= 0);
+  gdb_assert (regnum < regcache->descr->nr_cooked_registers);
+
+  if (regnum < regcache->descr->nr_raw_registers
+      || (regcache->readonly_p
+	  && regcache->register_status[regnum] != REG_UNKNOWN)
+      || !gdbarch_pseudo_register_read_value_p (regcache->descr->gdbarch))
+    {
+      struct value *result;
+
+      result = allocate_value (register_type (regcache->descr->gdbarch,
+					      regnum));
+      VALUE_LVAL (result) = lval_register;
+      VALUE_REGNUM (result) = regnum;
+
+      /* It is more efficient in general to do this delegation in this
+	 direction than in the other one, even though the value-based
+	 API is preferred.  */
+      if (regcache_cooked_read (regcache, regnum,
+				value_contents_raw (result)) == REG_UNAVAILABLE)
+	mark_value_bytes_unavailable (result, 0,
+				      TYPE_LENGTH (value_type (result)));
+
+      return result;
+    }
+  else
+    return gdbarch_pseudo_register_read_value (regcache->descr->gdbarch,
+					       regcache, regnum);
+}
+
 enum register_status
 regcache_cooked_read_signed (struct regcache *regcache, int regnum,
 			     LONGEST *val)
diff --git a/gdb/regcache.h b/gdb/regcache.h
index 3708c86..7f7dc10 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -104,6 +104,12 @@ enum register_status regcache_cooked_read (struct regcache *regcache,
 void regcache_cooked_write (struct regcache *regcache, int rawnum,
 			    const gdb_byte *buf);
 
+/* Read register REGNUM from REGCACHE and return a new value.  This
+   will call mark_value_bytes_unavailable as appropriate.  */
+
+struct value *regcache_cooked_read_value (struct regcache *regcache,
+					  int regnum);
+
 /* Read a register as a signed/unsigned quantity.  */
 extern enum register_status
   regcache_cooked_read_signed (struct regcache *regcache,
diff --git a/gdb/sentinel-frame.c b/gdb/sentinel-frame.c
index 6c2f3e0..5d018bd 100644
--- a/gdb/sentinel-frame.c
+++ b/gdb/sentinel-frame.c
@@ -48,25 +48,12 @@ sentinel_frame_prev_register (struct frame_info *this_frame,
 			      void **this_prologue_cache,
 			      int regnum)
 {
-  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct frame_unwind_cache *cache = *this_prologue_cache;
   struct value *value;
-  struct type *regtype = register_type (gdbarch, regnum);
 
-  /* Return the actual value.  */
-  value = allocate_value (regtype);
-  VALUE_LVAL (value) = lval_register;
-  VALUE_REGNUM (value) = regnum;
+  value = regcache_cooked_read_value (cache->regcache, regnum);
   VALUE_FRAME_ID (value) = get_frame_id (this_frame);
 
-  /* Use the regcache_cooked_read() method so that it, on the fly,
-     constructs either a raw or pseudo register from the raw
-     register cache.  */
-  if (regcache_cooked_read (cache->regcache,
-			    regnum,
-			    value_contents_raw (value)) == REG_UNAVAILABLE)
-    mark_value_bytes_unavailable (value, 0, TYPE_LENGTH (regtype));
-
   return value;
 }
 
diff --git a/gdb/testsuite/gdb.dwarf2/typeddwarf-amd64.S b/gdb/testsuite/gdb.dwarf2/typeddwarf-amd64.S
new file mode 100644
index 0000000..f97357a
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/typeddwarf-amd64.S
@@ -0,0 +1,1568 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* This source file was generated from typeddwarf.c using the following
+   command line:
+
+   gcc -S -g -O2 typeddwarf.c -o typeddwarf-amd64.S
+
+*/
+
+
+	.file	"typeddwarf.c"
+	.text
+.Ltext0:
+	.globl	f1
+	.type	f1, @function
+f1:
+.LFB0:
+	.file 1 "typeddwarf.c"
+	.loc 1 10 0
+	.cfi_startproc
+.LVL0:
+	.loc 1 29 0
+	movl	vv(%rip), %eax
+	addl	$1, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 30 0
+	ret
+	.cfi_endproc
+.LFE0:
+	.size	f1, .-f1
+	.globl	f2
+	.type	f2, @function
+f2:
+.LFB1:
+	.loc 1 34 0
+	.cfi_startproc
+.LVL1:
+	.loc 1 53 0
+	movl	vv(%rip), %eax
+	addl	$1, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 54 0
+	cvttsd2si	%xmm0, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 55 0
+	cvttsd2si	%xmm1, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 56 0
+	cvttsd2si	%xmm2, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 57 0
+	cvttss2si	%xmm3, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 58 0
+	cvttss2si	%xmm4, %r8d
+	movl	%r8d, vv(%rip)
+	.loc 1 59 0
+	movl	%edi, vv(%rip)
+	.loc 1 60 0
+	movl	%esi, vv(%rip)
+	.loc 1 61 0
+	movl	%edx, vv(%rip)
+	.loc 1 62 0
+	movl	%ecx, vv(%rip)
+	.loc 1 63 0
+	movl	%eax, vv(%rip)
+	.loc 1 64 0
+	ret
+	.cfi_endproc
+.LFE1:
+	.size	f2, .-f2
+	.globl	f3
+	.type	f3, @function
+f3:
+.LFB2:
+	.loc 1 68 0
+	.cfi_startproc
+.LVL2:
+	.loc 1 73 0
+	movl	vv(%rip), %eax
+	addl	$1, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 74 0
+	ret
+	.cfi_endproc
+.LFE2:
+	.size	f3, .-f3
+	.globl	f4
+	.type	f4, @function
+f4:
+.LFB3:
+	.loc 1 78 0
+	.cfi_startproc
+.LVL3:
+	.loc 1 82 0
+	movl	vv(%rip), %eax
+	addl	$1, %eax
+	movl	%eax, vv(%rip)
+	.loc 1 83 0
+	ret
+	.cfi_endproc
+.LFE3:
+	.size	f4, .-f4
+	.globl	_start
+	.type	_start, @function
+_start:
+.LFB4:
+	.loc 1 87 0
+	.cfi_startproc
+	subq	$8, %rsp
+.LCFI0:
+	.cfi_def_cfa_offset 16
+	.loc 1 88 0
+	movl	$9, %ecx
+	movl	$8, %edx
+	movl	$7, %esi
+	movl	$6, %edi
+	movss	.LC2(%rip), %xmm4
+	movss	.LC3(%rip), %xmm3
+	movsd	.LC0(%rip), %xmm2
+	movsd	.LC1(%rip), %xmm1
+	movsd	.LC4(%rip), %xmm0
+	call	f1
+.LVL4:
+	.loc 1 89 0
+	movl	$9, %ecx
+	movl	$8, %edx
+	movl	$7, %esi
+	movl	$6, %edi
+	movss	.LC2(%rip), %xmm4
+	movss	.LC3(%rip), %xmm3
+	movsd	.LC0(%rip), %xmm2
+	movsd	.LC1(%rip), %xmm1
+	movsd	.LC4(%rip), %xmm0
+	call	f2
+.LVL5:
+	.loc 1 90 0
+	movl	$4, %ecx
+	movl	$3, %edx
+	movl	$2, %esi
+	movl	$1, %edi
+	call	f3
+.LVL6:
+	.loc 1 91 0
+	movdqa	.LC5(%rip), %xmm2
+	movq	.LC6(%rip), %xmm1
+	movd	.LC7(%rip), %xmm0
+	call	f4
+.LVL7:
+	.loc 1 93 0
+	movl	$0, %eax
+	addq	$8, %rsp
+.LCFI1:
+	.cfi_def_cfa_offset 8
+	ret
+	.cfi_endproc
+.LFE4:
+	.size	_start, .-_start
+	.comm	vv,4,4
+	.section	.rodata.cst8,"aM",@progbits,8
+	.align 8
+.LC0:
+	.long	0
+	.long	1074266112
+	.align 8
+.LC1:
+	.long	0
+	.long	1073741824
+	.section	.rodata.cst4,"aM",@progbits,4
+	.align 4
+.LC2:
+	.long	1084227584
+	.align 4
+.LC3:
+	.long	1082130432
+	.section	.rodata.cst8
+	.align 8
+.LC4:
+	.long	0
+	.long	1072693248
+	.section	.rodata.cst16,"aM",@progbits,16
+	.align 16
+.LC5:
+	.quad	640
+	.quad	3476215962376601600
+	.section	.rodata.cst8
+	.align 8
+.LC6:
+	.quad	3575858104132173984
+	.section	.rodata.cst4
+	.align 4
+.LC7:
+	.long	838860880
+	.text
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	0x6c4
+	.value	0x2
+	.long	.Ldebug_abbrev0
+	.byte	0x8
+	.uleb128 0x1
+	.long	.LASF8
+	.byte	0x1
+	.long	.LASF9
+	.long	.LASF10
+	.quad	.Ltext0
+	.quad	.Letext0
+	.long	.Ldebug_line0
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0x4
+	.long	.LASF0
+	.uleb128 0x2
+	.byte	0x4
+	.byte	0x4
+	.long	.LASF1
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0x7
+	.long	.LASF2
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0x5
+	.long	.LASF3
+	.uleb128 0x2
+	.byte	0x4
+	.byte	0x7
+	.long	.LASF4
+	.uleb128 0x3
+	.byte	0x4
+	.byte	0x5
+	.string	"int"
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0xf
+	.long	.LASF5
+	.uleb128 0x2
+	.byte	0x4
+	.byte	0xf
+	.long	.LASF6
+	.uleb128 0x2
+	.byte	0x10
+	.byte	0xf
+	.long	.LASF7
+	.uleb128 0x4
+	.byte	0x1
+	.string	"f1"
+	.byte	0x1
+	.byte	0x9
+	.byte	0x1
+	.quad	.LFB0
+	.quad	.LFE0
+	.byte	0x2
+	.byte	0x77
+	.sleb128 8
+	.byte	0x1
+	.long	0x22b
+	.uleb128 0x5
+	.string	"a"
+	.byte	0x1
+	.byte	0x9
+	.long	0x2d
+	.byte	0x1
+	.byte	0x61
+	.uleb128 0x5
+	.string	"b"
+	.byte	0x1
+	.byte	0x9
+	.long	0x2d
+	.byte	0x1
+	.byte	0x62
+	.uleb128 0x5
+	.string	"c"
+	.byte	0x1
+	.byte	0x9
+	.long	0x2d
+	.byte	0x1
+	.byte	0x63
+	.uleb128 0x5
+	.string	"d"
+	.byte	0x1
+	.byte	0x9
+	.long	0x34
+	.byte	0x1
+	.byte	0x64
+	.uleb128 0x5
+	.string	"e"
+	.byte	0x1
+	.byte	0x9
+	.long	0x34
+	.byte	0x1
+	.byte	0x65
+	.uleb128 0x5
+	.string	"f"
+	.byte	0x1
+	.byte	0x9
+	.long	0x50
+	.byte	0x1
+	.byte	0x55
+	.uleb128 0x5
+	.string	"g"
+	.byte	0x1
+	.byte	0x9
+	.long	0x49
+	.byte	0x1
+	.byte	0x54
+	.uleb128 0x5
+	.string	"h"
+	.byte	0x1
+	.byte	0x9
+	.long	0x22b
+	.byte	0x1
+	.byte	0x51
+	.uleb128 0x5
+	.string	"i"
+	.byte	0x1
+	.byte	0x9
+	.long	0x232
+	.byte	0x1
+	.byte	0x52
+	.uleb128 0x6
+	.string	"j"
+	.byte	0x1
+	.byte	0xb
+	.long	0x2d
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"l"
+	.byte	0x1
+	.byte	0xc
+	.long	0x22b
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0xf9
+	.uleb128 0x3b
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"m"
+	.byte	0x1
+	.byte	0xe
+	.long	0x22b
+	.byte	0x1
+	.byte	0x63
+	.uleb128 0x6
+	.string	"n"
+	.byte	0x1
+	.byte	0x10
+	.long	0x34
+	.byte	0x7
+	.byte	0x72
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x3b
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"o"
+	.byte	0x1
+	.byte	0x11
+	.long	0x2d
+	.byte	0x7
+	.byte	0x71
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x42
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"p"
+	.byte	0x1
+	.byte	0x12
+	.long	0x34
+	.byte	0x7
+	.byte	0x74
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x49
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"q"
+	.byte	0x1
+	.byte	0x13
+	.long	0x2d
+	.byte	0x7
+	.byte	0x75
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x50
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"r"
+	.byte	0x1
+	.byte	0x14
+	.long	0x232
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x3b
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"s"
+	.byte	0x1
+	.byte	0x15
+	.long	0x22b
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x13
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x42
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"t"
+	.byte	0x1
+	.byte	0x16
+	.long	0x49
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x49
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"u"
+	.byte	0x1
+	.byte	0x17
+	.long	0x50
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x50
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"v"
+	.byte	0x1
+	.byte	0x18
+	.long	0x34
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"w"
+	.byte	0x1
+	.byte	0x19
+	.long	0x2d
+	.byte	0x12
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x3fd00000
+	.byte	0x1e
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"x"
+	.byte	0x1
+	.byte	0x1a
+	.long	0x2d
+	.byte	0x14
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0x22
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x3ff00000
+	.byte	0x22
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"y"
+	.byte	0x1
+	.byte	0x1b
+	.long	0x2d
+	.byte	0x14
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0xf5
+	.uleb128 0x13
+	.uleb128 0x2d
+	.byte	0x22
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40000000
+	.byte	0x22
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"z"
+	.byte	0x1
+	.byte	0x1c
+	.long	0x34
+	.byte	0x12
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf3
+	.uleb128 0x3
+	.byte	0xf5
+	.uleb128 0x15
+	.uleb128 0x34
+	.byte	0x22
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40400000
+	.byte	0x22
+	.byte	0x9f
+	.byte	0
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0x5
+	.long	.LASF11
+	.uleb128 0x2
+	.byte	0x8
+	.byte	0x7
+	.long	.LASF12
+	.uleb128 0x4
+	.byte	0x1
+	.string	"f2"
+	.byte	0x1
+	.byte	0x21
+	.byte	0x1
+	.quad	.LFB1
+	.quad	.LFE1
+	.byte	0x2
+	.byte	0x77
+	.sleb128 8
+	.byte	0x1
+	.long	0x402
+	.uleb128 0x5
+	.string	"a"
+	.byte	0x1
+	.byte	0x21
+	.long	0x2d
+	.byte	0x1
+	.byte	0x61
+	.uleb128 0x5
+	.string	"b"
+	.byte	0x1
+	.byte	0x21
+	.long	0x2d
+	.byte	0x1
+	.byte	0x62
+	.uleb128 0x5
+	.string	"c"
+	.byte	0x1
+	.byte	0x21
+	.long	0x2d
+	.byte	0x1
+	.byte	0x63
+	.uleb128 0x5
+	.string	"d"
+	.byte	0x1
+	.byte	0x21
+	.long	0x34
+	.byte	0x1
+	.byte	0x64
+	.uleb128 0x5
+	.string	"e"
+	.byte	0x1
+	.byte	0x21
+	.long	0x34
+	.byte	0x1
+	.byte	0x65
+	.uleb128 0x5
+	.string	"f"
+	.byte	0x1
+	.byte	0x21
+	.long	0x50
+	.byte	0x1
+	.byte	0x55
+	.uleb128 0x5
+	.string	"g"
+	.byte	0x1
+	.byte	0x21
+	.long	0x49
+	.byte	0x1
+	.byte	0x54
+	.uleb128 0x5
+	.string	"h"
+	.byte	0x1
+	.byte	0x21
+	.long	0x22b
+	.byte	0x1
+	.byte	0x51
+	.uleb128 0x5
+	.string	"i"
+	.byte	0x1
+	.byte	0x21
+	.long	0x232
+	.byte	0x1
+	.byte	0x52
+	.uleb128 0x6
+	.string	"j"
+	.byte	0x1
+	.byte	0x23
+	.long	0x2d
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"l"
+	.byte	0x1
+	.byte	0x24
+	.long	0x22b
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0xf9
+	.uleb128 0x3b
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"m"
+	.byte	0x1
+	.byte	0x26
+	.long	0x22b
+	.byte	0x1
+	.byte	0x63
+	.uleb128 0x6
+	.string	"n"
+	.byte	0x1
+	.byte	0x28
+	.long	0x34
+	.byte	0x7
+	.byte	0x72
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x3b
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"o"
+	.byte	0x1
+	.byte	0x29
+	.long	0x2d
+	.byte	0x7
+	.byte	0x71
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x42
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"p"
+	.byte	0x1
+	.byte	0x2a
+	.long	0x34
+	.byte	0x7
+	.byte	0x74
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x49
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"q"
+	.byte	0x1
+	.byte	0x2b
+	.long	0x2d
+	.byte	0x7
+	.byte	0x75
+	.sleb128 0
+	.byte	0xf7
+	.uleb128 0x50
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"r"
+	.byte	0x1
+	.byte	0x2c
+	.long	0x232
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x3b
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"s"
+	.byte	0x1
+	.byte	0x2d
+	.long	0x22b
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x13
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x42
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"t"
+	.byte	0x1
+	.byte	0x2e
+	.long	0x49
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x49
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"u"
+	.byte	0x1
+	.byte	0x2f
+	.long	0x50
+	.byte	0x8
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x50
+	.byte	0xf7
+	.uleb128 0
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"v"
+	.byte	0x1
+	.byte	0x30
+	.long	0x34
+	.byte	0x6
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf7
+	.uleb128 0x34
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"w"
+	.byte	0x1
+	.byte	0x31
+	.long	0x2d
+	.byte	0x12
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf7
+	.uleb128 0x2d
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x3fd00000
+	.byte	0x1e
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"x"
+	.byte	0x1
+	.byte	0x32
+	.long	0x2d
+	.byte	0x20
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x2d
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0x22
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40080000
+	.byte	0x1c
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0x78b58c40
+	.long	0x4415af1d
+	.byte	0x22
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"y"
+	.byte	0x1
+	.byte	0x33
+	.long	0x2d
+	.byte	0x14
+	.byte	0xf5
+	.uleb128 0x13
+	.uleb128 0x2d
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x401c0000
+	.byte	0x1e
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x2d
+	.byte	0x22
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"z"
+	.byte	0x1
+	.byte	0x34
+	.long	0x34
+	.byte	0x10
+	.byte	0xf5
+	.uleb128 0x14
+	.uleb128 0x34
+	.byte	0xf5
+	.uleb128 0x15
+	.uleb128 0x34
+	.byte	0x22
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40400000
+	.byte	0x22
+	.byte	0x9f
+	.byte	0
+	.uleb128 0x4
+	.byte	0x1
+	.string	"f3"
+	.byte	0x1
+	.byte	0x43
+	.byte	0x1
+	.quad	.LFB2
+	.quad	.LFE2
+	.byte	0x2
+	.byte	0x77
+	.sleb128 8
+	.byte	0x1
+	.long	0x4cd
+	.uleb128 0x5
+	.string	"a"
+	.byte	0x1
+	.byte	0x43
+	.long	0x22b
+	.byte	0x1
+	.byte	0x55
+	.uleb128 0x5
+	.string	"b"
+	.byte	0x1
+	.byte	0x43
+	.long	0x50
+	.byte	0x1
+	.byte	0x54
+	.uleb128 0x5
+	.string	"c"
+	.byte	0x1
+	.byte	0x43
+	.long	0x22b
+	.byte	0x1
+	.byte	0x51
+	.uleb128 0x5
+	.string	"d"
+	.byte	0x1
+	.byte	0x43
+	.long	0x49
+	.byte	0x1
+	.byte	0x52
+	.uleb128 0x6
+	.string	"w"
+	.byte	0x1
+	.byte	0x45
+	.long	0x22b
+	.byte	0x14
+	.byte	0x72
+	.sleb128 0
+	.byte	0xc
+	.long	0xffffffff
+	.byte	0x1a
+	.byte	0x12
+	.byte	0x75
+	.sleb128 0
+	.byte	0x16
+	.byte	0x14
+	.byte	0x2b
+	.byte	0x28
+	.value	0x1
+	.byte	0x16
+	.byte	0x13
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"x"
+	.byte	0x1
+	.byte	0x46
+	.long	0x22b
+	.byte	0xe
+	.byte	0x74
+	.sleb128 0
+	.byte	0x8
+	.byte	0x20
+	.byte	0x24
+	.byte	0x8
+	.byte	0x20
+	.byte	0x26
+	.byte	0x75
+	.sleb128 0
+	.byte	0x22
+	.byte	0x23
+	.uleb128 0x7
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"y"
+	.byte	0x1
+	.byte	0x47
+	.long	0x22b
+	.byte	0x13
+	.byte	0x72
+	.sleb128 0
+	.byte	0xc
+	.long	0xffffffff
+	.byte	0x1a
+	.byte	0x71
+	.sleb128 0
+	.byte	0x22
+	.byte	0x23
+	.uleb128 0x912345678
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"z"
+	.byte	0x1
+	.byte	0x48
+	.long	0x50
+	.byte	0x21
+	.byte	0x74
+	.sleb128 0
+	.byte	0x8
+	.byte	0x20
+	.byte	0x24
+	.byte	0x8
+	.byte	0x20
+	.byte	0x26
+	.byte	0x75
+	.sleb128 0
+	.byte	0x22
+	.byte	0x23
+	.uleb128 0x7
+	.byte	0x72
+	.sleb128 0
+	.byte	0xc
+	.long	0xffffffff
+	.byte	0x1a
+	.byte	0x71
+	.sleb128 0
+	.byte	0x22
+	.byte	0x23
+	.uleb128 0x912345678
+	.byte	0x22
+	.byte	0x9f
+	.byte	0
+	.uleb128 0x4
+	.byte	0x1
+	.string	"f4"
+	.byte	0x1
+	.byte	0x4d
+	.byte	0x1
+	.quad	.LFB3
+	.quad	.LFE3
+	.byte	0x2
+	.byte	0x77
+	.sleb128 8
+	.byte	0x1
+	.long	0x576
+	.uleb128 0x5
+	.string	"a"
+	.byte	0x1
+	.byte	0x4d
+	.long	0x5e
+	.byte	0x1
+	.byte	0x61
+	.uleb128 0x5
+	.string	"b"
+	.byte	0x1
+	.byte	0x4d
+	.long	0x57
+	.byte	0x1
+	.byte	0x62
+	.uleb128 0x5
+	.string	"c"
+	.byte	0x1
+	.byte	0x4d
+	.long	0x65
+	.byte	0x1
+	.byte	0x63
+	.uleb128 0x6
+	.string	"w"
+	.byte	0x1
+	.byte	0x4f
+	.long	0x5e
+	.byte	0x14
+	.byte	0xf5
+	.uleb128 0x11
+	.uleb128 0x5e
+	.byte	0xf4
+	.uleb128 0x5e
+	.byte	0x4
+	.long	0x32000050
+	.byte	0x1e
+	.byte	0xf4
+	.uleb128 0x5e
+	.byte	0x4
+	.long	0x3200003c
+	.byte	0x22
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"x"
+	.byte	0x1
+	.byte	0x50
+	.long	0x57
+	.byte	0x1c
+	.byte	0xf5
+	.uleb128 0x12
+	.uleb128 0x57
+	.byte	0xf4
+	.uleb128 0x57
+	.byte	0x8
+	.long	0x50
+	.long	0x31a00000
+	.byte	0x1b
+	.byte	0xf4
+	.uleb128 0x57
+	.byte	0x8
+	.long	0x3c
+	.long	0x31a00000
+	.byte	0x1c
+	.byte	0x9f
+	.uleb128 0x6
+	.string	"y"
+	.byte	0x1
+	.byte	0x51
+	.long	0x65
+	.byte	0x19
+	.byte	0xf5
+	.uleb128 0x13
+	.uleb128 0x65
+	.byte	0x1f
+	.byte	0xf4
+	.uleb128 0x65
+	.byte	0x10
+	.long	0x50
+	.long	0
+	.long	0
+	.long	0x303e0000
+	.byte	0x1b
+	.byte	0x9f
+	.byte	0
+	.uleb128 0x7
+	.byte	0x1
+	.long	.LASF13
+	.byte	0x1
+	.byte	0x56
+	.long	0x50
+	.quad	.LFB4
+	.quad	.LFE4
+	.long	.LLST0
+	.byte	0x1
+	.long	0x6a1
+	.uleb128 0x8
+	.quad	.LVL4
+	.long	0x6c
+	.long	0x604
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x61
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x3ff00000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x62
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40000000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x63
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40080000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x64
+	.byte	0x7
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40800000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x65
+	.byte	0x7
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40a00000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x55
+	.byte	0x1
+	.byte	0x36
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x54
+	.byte	0x1
+	.byte	0x37
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x51
+	.byte	0x1
+	.byte	0x38
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x52
+	.byte	0x1
+	.byte	0x39
+	.byte	0
+	.uleb128 0x8
+	.quad	.LVL5
+	.long	0x239
+	.long	0x66d
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x61
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x3ff00000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x62
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40000000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x63
+	.byte	0xb
+	.byte	0xf4
+	.uleb128 0x2d
+	.byte	0x8
+	.long	0
+	.long	0x40080000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x64
+	.byte	0x7
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40800000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x65
+	.byte	0x7
+	.byte	0xf4
+	.uleb128 0x34
+	.byte	0x4
+	.long	0x40a00000
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x55
+	.byte	0x1
+	.byte	0x36
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x54
+	.byte	0x1
+	.byte	0x37
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x51
+	.byte	0x1
+	.byte	0x38
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x52
+	.byte	0x1
+	.byte	0x39
+	.byte	0
+	.uleb128 0x8
+	.quad	.LVL6
+	.long	0x402
+	.long	0x693
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x55
+	.byte	0x1
+	.byte	0x31
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x54
+	.byte	0x1
+	.byte	0x32
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x51
+	.byte	0x1
+	.byte	0x33
+	.uleb128 0x9
+	.byte	0x1
+	.byte	0x52
+	.byte	0x1
+	.byte	0x34
+	.byte	0
+	.uleb128 0xa
+	.quad	.LVL7
+	.long	0x4cd
+	.byte	0
+	.uleb128 0xb
+	.string	"vv"
+	.byte	0x1
+	.byte	0x5
+	.long	0x6ad
+	.byte	0x1
+	.byte	0x1
+	.uleb128 0xc
+	.long	0x50
+	.uleb128 0xd
+	.string	"vv"
+	.byte	0x1
+	.byte	0x5
+	.long	0x6ad
+	.byte	0x1
+	.byte	0x9
+	.byte	0x3
+	.quad	vv
+	.byte	0
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1
+	.uleb128 0x11
+	.byte	0x1
+	.uleb128 0x25
+	.uleb128 0xe
+	.uleb128 0x13
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x1b
+	.uleb128 0xe
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x1
+	.uleb128 0x10
+	.uleb128 0x6
+	.byte	0
+	.byte	0
+	.uleb128 0x2
+	.uleb128 0x24
+	.byte	0
+	.uleb128 0xb
+	.uleb128 0xb
+	.uleb128 0x3e
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0xe
+	.byte	0
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x24
+	.byte	0
+	.uleb128 0xb
+	.uleb128 0xb
+	.uleb128 0x3e
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0x8
+	.byte	0
+	.byte	0
+	.uleb128 0x4
+	.uleb128 0x2e
+	.byte	0x1
+	.uleb128 0x3f
+	.uleb128 0xc
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x27
+	.uleb128 0xc
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x1
+	.uleb128 0x40
+	.uleb128 0xa
+	.uleb128 0x2117
+	.uleb128 0xc
+	.uleb128 0x1
+	.uleb128 0x13
+	.byte	0
+	.byte	0
+	.uleb128 0x5
+	.uleb128 0x5
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x2
+	.uleb128 0xa
+	.byte	0
+	.byte	0
+	.uleb128 0x6
+	.uleb128 0x34
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x2
+	.uleb128 0xa
+	.byte	0
+	.byte	0
+	.uleb128 0x7
+	.uleb128 0x2e
+	.byte	0x1
+	.uleb128 0x3f
+	.uleb128 0xc
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x1
+	.uleb128 0x40
+	.uleb128 0x6
+	.uleb128 0x2117
+	.uleb128 0xc
+	.uleb128 0x1
+	.uleb128 0x13
+	.byte	0
+	.byte	0
+	.uleb128 0x8
+	.uleb128 0x4109
+	.byte	0x1
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x31
+	.uleb128 0x13
+	.uleb128 0x1
+	.uleb128 0x13
+	.byte	0
+	.byte	0
+	.uleb128 0x9
+	.uleb128 0x410a
+	.byte	0
+	.uleb128 0x2
+	.uleb128 0xa
+	.uleb128 0x2111
+	.uleb128 0xa
+	.byte	0
+	.byte	0
+	.uleb128 0xa
+	.uleb128 0x4109
+	.byte	0
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x31
+	.uleb128 0x13
+	.byte	0
+	.byte	0
+	.uleb128 0xb
+	.uleb128 0x34
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x3f
+	.uleb128 0xc
+	.uleb128 0x3c
+	.uleb128 0xc
+	.byte	0
+	.byte	0
+	.uleb128 0xc
+	.uleb128 0x35
+	.byte	0
+	.uleb128 0x49
+	.uleb128 0x13
+	.byte	0
+	.byte	0
+	.uleb128 0xd
+	.uleb128 0x34
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x3f
+	.uleb128 0xc
+	.uleb128 0x2
+	.uleb128 0xa
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_loc,"",@progbits
+.Ldebug_loc0:
+.LLST0:
+	.quad	.LFB4-.Ltext0
+	.quad	.LCFI0-.Ltext0
+	.value	0x2
+	.byte	0x77
+	.sleb128 8
+	.quad	.LCFI0-.Ltext0
+	.quad	.LCFI1-.Ltext0
+	.value	0x2
+	.byte	0x77
+	.sleb128 16
+	.quad	.LCFI1-.Ltext0
+	.quad	.LFE4-.Ltext0
+	.value	0x2
+	.byte	0x77
+	.sleb128 8
+	.quad	0
+	.quad	0
+	.section	.debug_aranges,"",@progbits
+	.long	0x2c
+	.value	0x2
+	.long	.Ldebug_info0
+	.byte	0x8
+	.byte	0
+	.value	0
+	.value	0
+	.quad	.Ltext0
+	.quad	.Letext0-.Ltext0
+	.quad	0
+	.quad	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF4:
+	.string	"unsigned int"
+.LASF6:
+	.string	"_Decimal32"
+.LASF7:
+	.string	"_Decimal128"
+.LASF2:
+	.string	"long unsigned int"
+.LASF12:
+	.string	"long long unsigned int"
+.LASF5:
+	.string	"_Decimal64"
+.LASF13:
+	.string	"main"
+.LASF3:
+	.string	"long int"
+.LASF10:
+	.string	"/tmp"
+.LASF0:
+	.string	"double"
+.LASF11:
+	.string	"long long int"
+.LASF1:
+	.string	"float"
+.LASF8:
+	.string	"GNU C 4.7.0 20110708 (experimental) [trunk revision 176048]"
+.LASF9:
+	.string	"typeddwarf.c"
+	.ident	"GCC: (GNU) 4.7.0 20110708 (experimental) [trunk revision 176048]"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.dwarf2/typeddwarf.c b/gdb/testsuite/gdb.dwarf2/typeddwarf.c
index e5f7d67..40497da 100644
--- a/gdb/testsuite/gdb.dwarf2/typeddwarf.c
+++ b/gdb/testsuite/gdb.dwarf2/typeddwarf.c
@@ -25,7 +25,7 @@ f1 (double a, double b, double c, float d, float e, int f, unsigned int g, long
   double w = d / 4.0;		/* { dg-final { gdb-test 29 "w" "1" } } */
   double x = a + b + 1.0;	/* { dg-final { gdb-test 29 "x" "4" } } */
   double y = b + c + 2.0;	/* { dg-final { gdb-test 29 "y" "7" } } */
-  float z = d + e + 3.0f;	/* { dg-final { gdb-test 29 "z" "12" } } */
+  float z = d + e + 3.0f;	/* { dg-final { xfail-gdb-test 29 "z" "12" "x86_64-*-*"} } */
   vv++;
 }
 
diff --git a/gdb/testsuite/gdb.dwarf2/typeddwarf.exp b/gdb/testsuite/gdb.dwarf2/typeddwarf.exp
index e6a420a..36a17e5 100644
--- a/gdb/testsuite/gdb.dwarf2/typeddwarf.exp
+++ b/gdb/testsuite/gdb.dwarf2/typeddwarf.exp
@@ -22,12 +22,16 @@ if ![dwarf2_support] {
     return 0  
 }
 
-# This test can only be run on x86 targets.
-if { ![is_x86_like_target] } {
+# This test can only be run on x86 and amd64 targets.
+if { [is_x86_like_target] } {
+    set sfile ${test}.S
+} elseif {[istarget "x86_64-*-*"]} {
+    set sfile ${test}-amd64.S
+} else {
     return 0
 }
 
-if { [prepare_for_testing "${test}.exp" "${test}" ${test}.S {nodebug additional_flags=-nostdlib}] } {
+if { [prepare_for_testing "${test}.exp" "${test}" ${sfile} {nodebug additional_flags=-nostdlib}] } {
     return -1
 }
 
@@ -45,10 +49,19 @@ proc gdb-test {line var value} {
     lappend tests($line) [list $var $value 0]
 }
 
-proc xfail-gdb-test {line var value} {
+# Add an XFAIL'd test.  If ARCH_PATTERN is given, and does not match
+# the target, then the test is simply added and not XFAIL'd.
+proc xfail-gdb-test {line var value {arch_pattern ""}} {
     global tests
 
-    lappend tests($line) [list $var $value 1]
+    set flag 1
+    if {$arch_pattern != ""} {
+	if {! [istarget $arch_pattern]} {
+	    set flag 0
+	}
+    }
+
+    lappend tests($line) [list $var $value $flag]
 }
 
 proc scan_gdb_tests {} {

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

* Re: RFC: partially available registers
  2011-07-22 15:40         ` Tom Tromey
@ 2011-07-22 19:10           ` Pedro Alves
  2011-07-22 19:19             ` Tom Tromey
  0 siblings, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2011-07-22 19:10 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey, Daniel Jacobowitz

On Friday 22 July 2011 16:19:38, Tom Tromey wrote:
> >>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes:
> 
> Pedro> # of expected passes            39
> Pedro> with an unpatched gdb (x86-64-linux), same as with patched gdb.
> Pedro> Is that expected?
> 
> It definitely fails for me with unpatched gdb.
> 
> Does your machine have AVX?  I believe it will only fail on an
> AVX-capable machine.

Ah, that's it then.  I was curious to know why were the
upper parts of the ymm unavailable.

Are you hitting:

regcache_raw_read ()
{
...
      /* A number of targets can't access the whole set of raw
	 registers (because the debug API provides no means to get at
	 them).  */
      if (regcache->register_status[regnum] == REG_UNKNOWN)
	regcache->register_status[regnum] = REG_UNAVAILABLE;
    }

?

-- 
Pedro Alves

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

* Re: RFC: partially available registers
  2011-07-22 19:10           ` Pedro Alves
@ 2011-07-22 19:19             ` Tom Tromey
  2011-07-22 19:31               ` Pedro Alves
  0 siblings, 1 reply; 28+ messages in thread
From: Tom Tromey @ 2011-07-22 19:19 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches, Daniel Jacobowitz

>>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes:

Pedro> Ah, that's it then.  I was curious to know why were the
Pedro> upper parts of the ymm unavailable.

amd64_linux_fetch_inferior_registers calls ptrace(PTRACE_GETREGSET)
to fetch the registers.  Then it passes this to amd64_supply_xsave,
which calls i387_supply_xsave.  This function then decodes the "XCR0"
flag and determines that the upper parts were not supplied by the
kernel; that is, we take the true branch here:

	  if ((clear_bv & I386_XSTATE_AVX))
	    p = NULL;
	  else
	    p = regs;

Tom

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

* Re: RFC: partially available registers
  2011-07-22 19:19             ` Tom Tromey
@ 2011-07-22 19:31               ` Pedro Alves
  2011-07-22 21:58                 ` Pedro Alves
  2011-07-22 22:20                 ` Tom Tromey
  0 siblings, 2 replies; 28+ messages in thread
From: Pedro Alves @ 2011-07-22 19:31 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches, Daniel Jacobowitz

On Friday 22 July 2011 19:55:31, Tom Tromey wrote:
> >>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes:
> 
> Pedro> Ah, that's it then.  I was curious to know why were the
> Pedro> upper parts of the ymm unavailable.
> 
> amd64_linux_fetch_inferior_registers calls ptrace(PTRACE_GETREGSET)
> to fetch the registers.  Then it passes this to amd64_supply_xsave,
> which calls i387_supply_xsave.  This function then decodes the "XCR0"
> flag and determines that the upper parts were not supplied by the
> kernel; that is, we take the true branch here:
> 
> 	  if ((clear_bv & I386_XSTATE_AVX))
> 	    p = NULL;
> 	  else
> 	    p = regs;

Ah, thanks.  With a bit more context:

    case avxh:
      if ((clear_bv & I386_XSTATE_AVX))
        p = NULL;
      else
        p = XSAVE_AVXH_ADDR (tdep, regs, regnum);
      regcache_raw_supply (regcache, regnum, p);
      return;

regcache_raw_supply with p=NULL means the register
is unavailable.  But before the <unavailable> stuff,
it meant "supply the register as 0".  I seem to remember
discussing this AVX stuff with H.J., and coming to the
conclusion that what want is really 0, but maybe not.
gdbserver is explicitly zeroing in this case, instead
of returning unavailable, see
gdbserver/i387-fp.c:i387_xsave_to_cache.  

What does it really mean when you have an AVX
capable machine, but I386_XSTATE_AVX is clear?

Whatever the answer, we need to fix one of native
gdb or gdbserver for consistency.

-- 
Pedro Alves

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

* Re: RFC: partially available registers
  2011-07-22 19:31               ` Pedro Alves
@ 2011-07-22 21:58                 ` Pedro Alves
  2011-07-22 22:20                 ` Tom Tromey
  1 sibling, 0 replies; 28+ messages in thread
From: Pedro Alves @ 2011-07-22 21:58 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey, Daniel Jacobowitz

On Friday 22 July 2011 20:10:23, Pedro Alves wrote:
> On Friday 22 July 2011 19:55:31, Tom Tromey wrote:
> > >>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes:
> > 
> > Pedro> Ah, that's it then.  I was curious to know why were the
> > Pedro> upper parts of the ymm unavailable.
> > 
> > amd64_linux_fetch_inferior_registers calls ptrace(PTRACE_GETREGSET)
> > to fetch the registers.  Then it passes this to amd64_supply_xsave,
> > which calls i387_supply_xsave.  This function then decodes the "XCR0"
> > flag and determines that the upper parts were not supplied by the
> > kernel; that is, we take the true branch here:
> > 
> > 	  if ((clear_bv & I386_XSTATE_AVX))
> > 	    p = NULL;
> > 	  else
> > 	    p = regs;
> 
> Ah, thanks.  With a bit more context:
> 
>     case avxh:
>       if ((clear_bv & I386_XSTATE_AVX))
>         p = NULL;
>       else
>         p = XSAVE_AVXH_ADDR (tdep, regs, regnum);
>       regcache_raw_supply (regcache, regnum, p);
>       return;
> 
> regcache_raw_supply with p=NULL means the register
> is unavailable.  But before the <unavailable> stuff,
> it meant "supply the register as 0".  I seem to remember
> discussing this AVX stuff with H.J., and coming to the
> conclusion that what want is really 0, but maybe not.

Found it:

<http://sourceware.org/ml/gdb-patches/2010-10/msg00268.html>

(and follow up)

> gdbserver is explicitly zeroing in this case, instead
> of returning unavailable, see
> gdbserver/i387-fp.c:i387_xsave_to_cache.  
> 
> What does it really mean when you have an AVX
> capable machine, but I386_XSTATE_AVX is clear?
> 
> Whatever the answer, we need to fix one of native
> gdb or gdbserver for consistency.

-- 
Pedro Alves

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

* Re: RFC: partially available registers
  2011-07-22 19:31               ` Pedro Alves
  2011-07-22 21:58                 ` Pedro Alves
@ 2011-07-22 22:20                 ` Tom Tromey
  2011-07-26 17:08                   ` Pedro Alves
  1 sibling, 1 reply; 28+ messages in thread
From: Tom Tromey @ 2011-07-22 22:20 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches, Daniel Jacobowitz, hjl

>>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes:

CC'ing H.J.

Pedro> But before the <unavailable> stuff, it meant "supply the register
Pedro> as 0".  I seem to remember discussing this AVX stuff with H.J.,
Pedro> and coming to the conclusion that what want is really 0, but
Pedro> maybe not.

I am far from being an expert in this area, but from the Intel
Architecture manual, section 13.5.1:

    Saving the x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 state using FXSAVE
    requires processor overhead. If the new task does not access x87 FPU,
    MMX, XMM, and MXCSR registers, avoid overhead by not automatically
    saving the state on a task switch.

    The TS flag in control register CR0 is provided to allow the operating
    system to delay saving the x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 state
    until an instruction that actually accesses this state is encountered in
    a new task.

So I think what is going on here is that the upper bits of these
registers are truly unavailable, because the inferior has never executed
an instruction referencing them.

Pedro> Whatever the answer, we need to fix one of native
Pedro> gdb or gdbserver for consistency.

If you agree with what I have checked in, I will update gdbserver.
Otherwise, let me know what you think would be correct and I will
implement that, instead, for both.

thanks,
Tom

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

* Re: RFC: partially available registers
  2011-07-20 20:53       ` Tom Tromey
@ 2011-07-24 13:48         ` Mark Kettenis
  2011-07-25 15:50           ` Tom Tromey
  0 siblings, 1 reply; 28+ messages in thread
From: Mark Kettenis @ 2011-07-24 13:48 UTC (permalink / raw)
  To: tromey; +Cc: drow, gdb-patches

> From: Tom Tromey <tromey@redhat.com>
> Date: Wed, 20 Jul 2011 14:29:03 -0600
> 
> Tom> I looked into this, and I changed some things, but I did not change it
> Tom> completely.
> 
> I forgot to mention -- please comment.  In the absence of comments I
> will commit this version.

Not sure if you already did so, but I'd like to have a proper look at
this before you do so.  Just returned from vacation, so it may take a
few days before I've cleared my backlog of things and get to it.

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

* Re: RFC: partially available registers
  2011-07-24 13:48         ` Mark Kettenis
@ 2011-07-25 15:50           ` Tom Tromey
  0 siblings, 0 replies; 28+ messages in thread
From: Tom Tromey @ 2011-07-25 15:50 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: drow, gdb-patches

>>>>> "Mark" == Mark Kettenis <mark.kettenis@xs4all.nl> writes:

Tom> I forgot to mention -- please comment.  In the absence of comments I
Tom> will commit this version.

Mark> Not sure if you already did so, but I'd like to have a proper look at
Mark> this before you do so.  Just returned from vacation, so it may take a
Mark> few days before I've cleared my backlog of things and get to it.

It is in, but I will change it if need be.

Tom

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

* Re: RFC: partially available registers
  2011-07-22 22:20                 ` Tom Tromey
@ 2011-07-26 17:08                   ` Pedro Alves
  2011-07-26 17:13                     ` Pedro Alves
  2011-07-27 18:25                     ` Tom Tromey
  0 siblings, 2 replies; 28+ messages in thread
From: Pedro Alves @ 2011-07-26 17:08 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches, Daniel Jacobowitz, hjl

On Friday 22 July 2011 20:30:53, Tom Tromey wrote:
> >>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes:

> Pedro> But before the <unavailable> stuff, it meant "supply the register
> Pedro> as 0".  I seem to remember discussing this AVX stuff with H.J.,
> Pedro> and coming to the conclusion that what want is really 0, but
> Pedro> maybe not.
> 
> I am far from being an expert in this area,

Same here...

> but from the Intel Architecture manual, section 13.5.1:

Thanks.  I finally took a bit to read that too.

>     Saving the x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 state using FXSAVE
>     requires processor overhead. If the new task does not access x87 FPU,
>     MMX, XMM, and MXCSR registers, avoid overhead by not automatically
>     saving the state on a task switch.
> 
>     The TS flag in control register CR0 is provided to allow the operating
>     system to delay saving the x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 state
>     until an instruction that actually accesses this state is encountered in
>     a new task.
> 
> So I think what is going on here is that the upper bits of these
> registers are truly unavailable, because the inferior has never executed
> an instruction referencing them.

My mental model of <unavailable> is:

<unavailable> means the object exists, and its value exists,
but we have no means to fetch it.  This corresponds to trying
to print the value of a register while inspecting a traceframe,
while that register had not been collected by the corresponding
tracepoint -- the register exists in the architecture/machine, but we
can't know what value it had when the tracepoint hit.  It also
corresponds to a (trimmed/partial) core dump file not containing a
dump of all the machine's registers, or a dump of all the process'es
mapped memory (due to ulimit, perhaps).  And corresponds to not
being able to get at some register's current value because the
debug API exposes no means to get at the current value.  Along
with other similar scenarios.

Let me brain dump what I think is happening in this avx case,
to make sure we're on the same page:

In this case, IIUC, with the delayed xsave mechanism active,
if a task has already accessed the x87 states, but hasn't triggered
a delayed x87 states' save/restore since the last context switch, the
current value of the x87 states of that task should be in the
save area (and valie), which is what ptrace gives us when we read
registers.  For a task that did access (and change) the x87 state
since the last x87 state save, (I hope!) a ptrace stopped task's
save area is up to date with the real x87 states.

That is, at runtime, the from ptrace's perpective, the delay/lazy
scheme should be transparent, save for one case...

... that is the case of gdb/ptrace reading an x87 state
before the program had first accessed the state itself for the
first time.

H.J.Lu wrote:

> Values in vector registers are invalid, not unavailable. OS
> initializes them to zero when they are set the firs time in
> a program. I prefer *value not valid".

That is, in between the program starting, and the program 
acessing the vector registers, the register's values are
invalid.  But, given that the kernel will fill them 
in with zero's on first access (meaning, from userspace's
perspective, it's the same as if the registers have always
been zero from the start of the program), I think it's best
that a debugger provides the same illusion to the user.

As H.J. wrote:

> GDB may update vector registers before they are set by program.
> GDB sets proper bits in XSAVE area to tell OS/hardware that vector
> registers now have valid values.

... and indeed this is what i387-tdep.c:i387_collect_xsave
appears to be doing.

Am I making sense?

> Pedro> Whatever the answer, we need to fix one of native
> Pedro> gdb or gdbserver for consistency.
> 
> If you agree with what I have checked in, I will update gdbserver.

I think your patch implements the right interface for partial
registers support.  I like it...

> Otherwise, let me know what you think would be correct and I will
> implement that, instead, for both.

... but I think that we should go with 0, instead of <unavailable>,
meaning changing x87-tdep.c:i387_supply_xsave to supply
explicity zeroed buffer, instead of a NULL pointer, like
gdbserver does.

-- 
Pedro Alves

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

* Re: RFC: partially available registers
  2011-07-26 17:08                   ` Pedro Alves
@ 2011-07-26 17:13                     ` Pedro Alves
  2011-07-26 19:46                       ` Tom Tromey
  2011-07-27 18:25                     ` Tom Tromey
  1 sibling, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2011-07-26 17:13 UTC (permalink / raw)
  To: gdb-patches, H.J. Lu; +Cc: Tom Tromey, Daniel Jacobowitz

On Tuesday 26 July 2011 16:31:18, Pedro Alves wrote:
> On Friday 22 July 2011 20:30:53, Tom Tromey wrote:
> > >>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes:
> 
> > Pedro> But before the <unavailable> stuff, it meant "supply the register
> > Pedro> as 0".  I seem to remember discussing this AVX stuff with H.J.,
> > Pedro> and coming to the conclusion that what want is really 0, but
> > Pedro> maybe not.
> > 
> > I am far from being an expert in this area,
> 
> Same here...
> 
> > but from the Intel Architecture manual, section 13.5.1:
> 
> Thanks.  I finally took a bit to read that too.
> 
> >     Saving the x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 state using FXSAVE
> >     requires processor overhead. If the new task does not access x87 FPU,
> >     MMX, XMM, and MXCSR registers, avoid overhead by not automatically
> >     saving the state on a task switch.
> > 
> >     The TS flag in control register CR0 is provided to allow the operating
> >     system to delay saving the x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 state
> >     until an instruction that actually accesses this state is encountered in
> >     a new task.
> > 
> > So I think what is going on here is that the upper bits of these
> > registers are truly unavailable, because the inferior has never executed
> > an instruction referencing them.
> 
> My mental model of <unavailable> is:
> 
> <unavailable> means the object exists, and its value exists,
> but we have no means to fetch it.  This corresponds to trying
> to print the value of a register while inspecting a traceframe,
> while that register had not been collected by the corresponding
> tracepoint -- the register exists in the architecture/machine, but we
> can't know what value it had when the tracepoint hit.  It also
> corresponds to a (trimmed/partial) core dump file not containing a
> dump of all the machine's registers, or a dump of all the process'es
> mapped memory (due to ulimit, perhaps).  And corresponds to not
> being able to get at some register's current value because the
> debug API exposes no means to get at the current value.  Along
> with other similar scenarios.
> 
> Let me brain dump what I think is happening in this avx case,
> to make sure we're on the same page:
> 
> In this case, IIUC, with the delayed xsave mechanism active,
> if a task has already accessed the x87 states, but hasn't triggered
> a delayed x87 states' save/restore since the last context switch, the
> current value of the x87 states of that task should be in the
> save area (and valie), which is what ptrace gives us when we read
> registers.  For a task that did access (and change) the x87 state
> since the last x87 state save, (I hope!) a ptrace stopped task's
> save area is up to date with the real x87 states.

I glanced at:

 <http://kerneltrap.org/mailarchive/linux-kernel/2010/2/10/4537101/thread>

and now I'm not sure my last assumption with ptrace stopped tasks
holds.  If not, then we have two distinct cases to handle -- x87 state
has never been accessed; and x87 state in the xsave memory area is
not up to date.  Is that true?  Is there a way to distinguish them?
Is that what linux puts in the SW usable bytes [464..511]?

> 
> That is, at runtime, the from ptrace's perpective, the delay/lazy
> scheme should be transparent, save for one case...
> 
> ... that is the case of gdb/ptrace reading an x87 state
> before the program had first accessed the state itself for the
> first time.
> 
> H.J.Lu wrote:
> 
> > Values in vector registers are invalid, not unavailable. OS
> > initializes them to zero when they are set the firs time in
> > a program. I prefer *value not valid".
> 
> That is, in between the program starting, and the program 
> acessing the vector registers, the register's values are
> invalid.  But, given that the kernel will fill them 
> in with zero's on first access (meaning, from userspace's
> perspective, it's the same as if the registers have always
> been zero from the start of the program), I think it's best
> that a debugger provides the same illusion to the user.
> 
> As H.J. wrote:
> 
> > GDB may update vector registers before they are set by program.
> > GDB sets proper bits in XSAVE area to tell OS/hardware that vector
> > registers now have valid values.
> 
> ... and indeed this is what i387-tdep.c:i387_collect_xsave
> appears to be doing.
> 
> Am I making sense?
> 
> > Pedro> Whatever the answer, we need to fix one of native
> > Pedro> gdb or gdbserver for consistency.
> > 
> > If you agree with what I have checked in, I will update gdbserver.
> 
> I think your patch implements the right interface for partial
> registers support.  I like it...
> 
> > Otherwise, let me know what you think would be correct and I will
> > implement that, instead, for both.
> 
> ... but I think that we should go with 0, instead of <unavailable>,
> meaning changing x87-tdep.c:i387_supply_xsave to supply
> explicity zeroed buffer, instead of a NULL pointer, like
> gdbserver does.
> 
> 

-- 
Pedro Alves

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

* Re: RFC: partially available registers
  2011-07-26 17:13                     ` Pedro Alves
@ 2011-07-26 19:46                       ` Tom Tromey
  0 siblings, 0 replies; 28+ messages in thread
From: Tom Tromey @ 2011-07-26 19:46 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches, H.J. Lu, Daniel Jacobowitz

>>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes:

Pedro> I glanced at:
Pedro>  <http://kerneltrap.org/mailarchive/linux-kernel/2010/2/10/4537101/thread>

Pedro> and now I'm not sure my last assumption with ptrace stopped tasks
Pedro> holds.  If not, then we have two distinct cases to handle -- x87 state
Pedro> has never been accessed; and x87 state in the xsave memory area is
Pedro> not up to date.  Is that true?  Is there a way to distinguish them?
Pedro> Is that what linux puts in the SW usable bytes [464..511]?

I do not know.  I think it would be best if H.J. weighed in on this.

Tom

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

* Re: RFC: partially available registers
  2011-07-26 17:08                   ` Pedro Alves
  2011-07-26 17:13                     ` Pedro Alves
@ 2011-07-27 18:25                     ` Tom Tromey
  2011-07-27 19:30                       ` Tom Tromey
  1 sibling, 1 reply; 28+ messages in thread
From: Tom Tromey @ 2011-07-27 18:25 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches, Daniel Jacobowitz, hjl

>>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes:

Pedro> <unavailable> means the object exists, and its value exists,
Pedro> but we have no means to fetch it.

[...]

After re-reading this reply a couple of times and thinking about the
issue, I think you are right, and we should supply 0 instead of
<unavailable> here.

Tom> If you agree with what I have checked in, I will update gdbserver.

Pedro> I think your patch implements the right interface for partial
Pedro> registers support.  I like it...

Great.

Pedro> ... but I think that we should go with 0, instead of <unavailable>,
Pedro> meaning changing x87-tdep.c:i387_supply_xsave to supply
Pedro> explicity zeroed buffer, instead of a NULL pointer, like
Pedro> gdbserver does.

I will do this.

Tom

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

* Re: RFC: partially available registers
  2011-07-27 18:25                     ` Tom Tromey
@ 2011-07-27 19:30                       ` Tom Tromey
  2011-07-27 19:33                         ` Pedro Alves
  2011-07-28  5:19                         ` Mark Kettenis
  0 siblings, 2 replies; 28+ messages in thread
From: Tom Tromey @ 2011-07-27 19:30 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches, Daniel Jacobowitz, hjl

Pedro> ... but I think that we should go with 0, instead of <unavailable>,
Pedro> meaning changing x87-tdep.c:i387_supply_xsave to supply
Pedro> explicity zeroed buffer, instead of a NULL pointer, like
Pedro> gdbserver does.

Tom> I will do this.

Here's the patch.

In absence of comment I will check it in, in a couple of days.

Built and regtested by the buildbot.

Tom

2011-07-27  Tom Tromey  <tromey@redhat.com>

	* i387-tdep.c (i387_supply_xsave): Supply zero for high bits of
	AVX registers.

diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
index c4ace82..332d491 100644
--- a/gdb/i387-tdep.c
+++ b/gdb/i387-tdep.c
@@ -798,17 +798,26 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
       /* Handle the upper YMM registers.  */
       if ((tdep->xcr0 & I386_XSTATE_AVX))
 	{
+	  gdb_byte buf[MAX_REGISTER_SIZE];
+
 	  if ((clear_bv & I386_XSTATE_AVX))
-	    p = NULL;
+	    {
+	      memset (buf, 0, sizeof (buf));
+	      p = NULL;
+	    }
 	  else
 	    p = regs;
 
 	  for (i = I387_YMM0H_REGNUM (tdep);
 	       i < I387_YMMENDH_REGNUM (tdep); i++)
 	    {
+	      const void *arg;
+
 	      if (p != NULL)
-		p = XSAVE_AVXH_ADDR (tdep, regs, i);
-	      regcache_raw_supply (regcache, i, p);
+		arg = XSAVE_AVXH_ADDR (tdep, regs, i);
+	      else
+		arg = buf;
+	      regcache_raw_supply (regcache, i, arg);
 	    }
 	}
 

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

* Re: RFC: partially available registers
  2011-07-27 19:30                       ` Tom Tromey
@ 2011-07-27 19:33                         ` Pedro Alves
  2011-07-28  5:19                         ` Mark Kettenis
  1 sibling, 0 replies; 28+ messages in thread
From: Pedro Alves @ 2011-07-27 19:33 UTC (permalink / raw)
  To: Tom Tromey, H.J. Lu; +Cc: gdb-patches, Daniel Jacobowitz

On Wednesday 27 July 2011 20:08:26, Tom Tromey wrote:
> Pedro> ... but I think that we should go with 0, instead of <unavailable>,
> Pedro> meaning changing x87-tdep.c:i387_supply_xsave to supply
> Pedro> explicity zeroed buffer, instead of a NULL pointer, like
> Pedro> gdbserver does.
> 
> Tom> I will do this.
> 
> Here's the patch.

Thanks.  Why only the AVX state though?  There are
several other places in the same function that
pass NULL to regcache_raw_supply that I think
should get the same treatment.

i387_supply_xsave accepts and handles a NULL XSAVE
argument.  I suppose it's for cores that miss the
xsave section?  I can't quite tell what path ends 
up calling i387_supply_xsave with NULL.  Maybe it's
dead code (I remember this code having changed a bit
the design throughout the review iterations; this bit may
have been left behind).  If not dead, that may be a genuine
case for <unavailable>.

> 
> In absence of comment I will check it in, in a couple of days.
> 
> Built and regtested by the buildbot.
> 
> Tom
> 
> 2011-07-27  Tom Tromey  <tromey@redhat.com>
> 
> 	* i387-tdep.c (i387_supply_xsave): Supply zero for high bits of
> 	AVX registers.
> 
> diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
> index c4ace82..332d491 100644
> --- a/gdb/i387-tdep.c
> +++ b/gdb/i387-tdep.c
> @@ -798,17 +798,26 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
>        /* Handle the upper YMM registers.  */
>        if ((tdep->xcr0 & I386_XSTATE_AVX))
>  	{
> +	  gdb_byte buf[MAX_REGISTER_SIZE];
> +
>  	  if ((clear_bv & I386_XSTATE_AVX))
> -	    p = NULL;
> +	    {
> +	      memset (buf, 0, sizeof (buf));
> +	      p = NULL;
> +	    }
>  	  else
>  	    p = regs;
>  
>  	  for (i = I387_YMM0H_REGNUM (tdep);
>  	       i < I387_YMMENDH_REGNUM (tdep); i++)
>  	    {
> +	      const void *arg;
> +
>  	      if (p != NULL)
> -		p = XSAVE_AVXH_ADDR (tdep, regs, i);
> -	      regcache_raw_supply (regcache, i, p);
> +		arg = XSAVE_AVXH_ADDR (tdep, regs, i);
> +	      else
> +		arg = buf;
> +	      regcache_raw_supply (regcache, i, arg);
>  	    }
>  	}
>  
> 

-- 
Pedro Alves

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

* Re: RFC: partially available registers
  2011-07-27 19:30                       ` Tom Tromey
  2011-07-27 19:33                         ` Pedro Alves
@ 2011-07-28  5:19                         ` Mark Kettenis
  1 sibling, 0 replies; 28+ messages in thread
From: Mark Kettenis @ 2011-07-28  5:19 UTC (permalink / raw)
  To: tromey; +Cc: pedro, gdb-patches, drow, hjl

> From: Tom Tromey <tromey@redhat.com>
> Date: Wed, 27 Jul 2011 13:08:26 -0600
> 
> Pedro> ... but I think that we should go with 0, instead of <unavailable>,
> Pedro> meaning changing x87-tdep.c:i387_supply_xsave to supply
> Pedro> explicity zeroed buffer, instead of a NULL pointer, like
> Pedro> gdbserver does.
> 
> Tom> I will do this.
> 
> Here's the patch.
> 
> In absence of comment I will check it in, in a couple of days.

Please hold off for a moment.

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

end of thread, other threads:[~2011-07-27 19:57 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-13 20:17 RFC: partially available registers Tom Tromey
2011-07-14  4:24 ` Daniel Jacobowitz
2011-07-15 20:52   ` Tom Tromey
2011-07-18  4:15     ` Daniel Jacobowitz
2011-07-20 20:14       ` Pedro Alves
2011-07-20 18:49     ` Sergio Durigan Junior
2011-07-20 20:46     ` Tom Tromey
2011-07-20 20:53       ` Tom Tromey
2011-07-24 13:48         ` Mark Kettenis
2011-07-25 15:50           ` Tom Tromey
2011-07-21  5:23       ` Ulrich Weigand
2011-07-21 20:27         ` Tom Tromey
2011-07-22 13:48           ` Ulrich Weigand
2011-07-22 15:42             ` Tom Tromey
2011-07-22 14:30       ` Pedro Alves
2011-07-22 15:40         ` Tom Tromey
2011-07-22 19:10           ` Pedro Alves
2011-07-22 19:19             ` Tom Tromey
2011-07-22 19:31               ` Pedro Alves
2011-07-22 21:58                 ` Pedro Alves
2011-07-22 22:20                 ` Tom Tromey
2011-07-26 17:08                   ` Pedro Alves
2011-07-26 17:13                     ` Pedro Alves
2011-07-26 19:46                       ` Tom Tromey
2011-07-27 18:25                     ` Tom Tromey
2011-07-27 19:30                       ` Tom Tromey
2011-07-27 19:33                         ` Pedro Alves
2011-07-28  5:19                         ` Mark Kettenis

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