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 + * 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 + * dwarf2expr.c (execute_stack_op) : 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; }