diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2011-11-30 16:06:55 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@de.ibm.com> | 2011-11-30 16:06:55 +0000 |
commit | d6db1fabccd61cdc0527cf7c701ae5cf7f277281 (patch) | |
tree | 1ee15269e26f8d23a2a607df2b02f2aff461bbad /gdb/s390-nat.c | |
parent | 1dd635acb8bfcf517fae1d3e21d312828efdb2b1 (diff) | |
download | gdb-d6db1fabccd61cdc0527cf7c701ae5cf7f277281.zip gdb-d6db1fabccd61cdc0527cf7c701ae5cf7f277281.tar.gz gdb-d6db1fabccd61cdc0527cf7c701ae5cf7f277281.tar.bz2 |
ChangeLog:
* s390-nat.c (SUBOFF): Remove.
(s390_native_supply, s390_native_collect): New functions.
(supply_gregset, supply_fpregset): Use s390_native_supply.
(fill_gregset, fill_fpregset): Use s390_native_collect.
* s390-tdep.c (s390_pseudo_register_reggroup_p): Update comment.
(s390_unwind_pseudo_register): New function.
(s390_prologue_frame_unwind_cache): Unwind PSW address and mask
registers instead of PC and CC.
(s390_backchain_frame_unwind_cache): Likewise.
(s390_sigtramp_frame_unwind_cache): Do not unwind PC, CC, or
full GPR pseudos.
(s390_trad_frame_prev_register): New function.
(s390_frame_prev_register): Use it.
(s390_sigtramp_frame_prev_register): Likewise.
(s390_dwarf2_prev_register): Use s390_unwind_pseudo_register.
(s390_dwarf2_frame_init_reg): Unwind PSW address and mask. Use
special callback to unwind any pseudo.
* features/s390-core32.xml: Add pswm/pswa to save/restore group.
* features/s390-core64.xml: Likewise.
* features/s390x-core64.xml: Likewise.
* features/s390-linux32.c: Regenerate.
* features/s390-linux64.c: Likewise.
* features/s390x-linux64.c: Likewise.
gdbserver/ChangeLog:
* linux-s390-low.c (s390_collect_ptrace_register): Fully convert
PSW address/mask between 8-byte and 16-byte formats.
(s390_supply_ptrace_register): Likewise.
(s390_get_pc, s390_set_pc): 4-byte PSW address always includes
basic addressing mode bit.
Diffstat (limited to 'gdb/s390-nat.c')
-rw-r--r-- | gdb/s390-nat.c | 134 |
1 files changed, 110 insertions, 24 deletions
diff --git a/gdb/s390-nat.c b/gdb/s390-nat.c index 5bc88a9..c1eec1c 100644 --- a/gdb/s390-nat.c +++ b/gdb/s390-nat.c @@ -55,28 +55,122 @@ /* When debugging a 32-bit executable running under a 64-bit kernel, we have to fix up the 64-bit registers we get from the kernel to make them look like 32-bit registers. */ + +static void +s390_native_supply (struct regcache *regcache, int regno, + const gdb_byte *regp, int *regmap) +{ + int offset = regmap[regno]; + #ifdef __s390x__ -#define SUBOFF(gdbarch, i) \ - ((gdbarch_ptr_bit (gdbarch) == 32 \ - && ((i) == S390_PSWA_REGNUM \ - || ((i) >= S390_R0_REGNUM && (i) <= S390_R15_REGNUM)))? 4 : 0) -#else -#define SUBOFF(gdbarch, i) 0 + struct gdbarch *gdbarch = get_regcache_arch (regcache); + if (offset != -1 && gdbarch_ptr_bit (gdbarch) == 32) + { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + + if (regno == S390_PSWM_REGNUM) + { + ULONGEST pswm; + gdb_byte buf[4]; + + pswm = extract_unsigned_integer (regp + regmap[S390_PSWM_REGNUM], + 8, byte_order); + + store_unsigned_integer (buf, 4, byte_order, (pswm >> 32) | 0x80000); + regcache_raw_supply (regcache, regno, buf); + return; + } + + if (regno == S390_PSWA_REGNUM) + { + ULONGEST pswm, pswa; + gdb_byte buf[4]; + + pswa = extract_unsigned_integer (regp + regmap[S390_PSWA_REGNUM], + 8, byte_order); + pswm = extract_unsigned_integer (regp + regmap[S390_PSWM_REGNUM], + 8, byte_order); + + store_unsigned_integer (buf, 4, byte_order, + (pswa & 0x7fffffff) | (pswm & 0x80000000)); + regcache_raw_supply (regcache, regno, buf); + return; + } + + if (regno >= S390_R0_REGNUM && regno <= S390_R15_REGNUM) + offset += 4; + } +#endif + + if (offset != -1) + regcache_raw_supply (regcache, regno, regp + offset); +} + +static void +s390_native_collect (const struct regcache *regcache, int regno, + gdb_byte *regp, int *regmap) +{ + int offset = regmap[regno]; + +#ifdef __s390x__ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + if (offset != -1 && gdbarch_ptr_bit (gdbarch) == 32) + { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + + if (regno == S390_PSWM_REGNUM) + { + ULONGEST pswm; + gdb_byte buf[4]; + + regcache_raw_collect (regcache, regno, buf); + pswm = extract_unsigned_integer (buf, 4, byte_order); + + /* We don't know the final addressing mode until the PSW address + is known, so leave it as-is. When the PSW address is collected + (below), the addressing mode will be updated. */ + store_unsigned_integer (regp + regmap[S390_PSWM_REGNUM], + 4, byte_order, pswm & 0xfff7ffff); + return; + } + + if (regno == S390_PSWA_REGNUM) + { + ULONGEST pswa; + gdb_byte buf[4]; + + regcache_raw_collect (regcache, regno, buf); + pswa = extract_unsigned_integer (buf, 4, byte_order); + + store_unsigned_integer (regp + regmap[S390_PSWA_REGNUM], + 8, byte_order, pswa & 0x7fffffff); + + /* Update basic addressing mode bit in PSW mask, see above. */ + store_unsigned_integer (regp + regmap[S390_PSWM_REGNUM] + 4, + 4, byte_order, pswa & 0x80000000); + return; + } + + if (regno >= S390_R0_REGNUM && regno <= S390_R15_REGNUM) + { + memset (regp + offset, 0, 4); + offset += 4; + } + } #endif + if (offset != -1) + regcache_raw_collect (regcache, regno, regp + offset); +} /* Fill GDB's register array with the general-purpose register values in *REGP. */ void supply_gregset (struct regcache *regcache, const gregset_t *regp) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); int i; for (i = 0; i < S390_NUM_REGS; i++) - if (regmap_gregset[i] != -1) - regcache_raw_supply (regcache, i, - (const char *)regp + regmap_gregset[i] - + SUBOFF (gdbarch, i)); + s390_native_supply (regcache, i, (const gdb_byte *) regp, regmap_gregset); } /* Fill register REGNO (if it is a general-purpose register) in @@ -85,14 +179,10 @@ supply_gregset (struct regcache *regcache, const gregset_t *regp) void fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); int i; for (i = 0; i < S390_NUM_REGS; i++) - if (regmap_gregset[i] != -1) - if (regno == -1 || regno == i) - regcache_raw_collect (regcache, i, - (char *)regp + regmap_gregset[i] - + SUBOFF (gdbarch, i)); + if (regno == -1 || regno == i) + s390_native_collect (regcache, i, (gdb_byte *) regp, regmap_gregset); } /* Fill GDB's register array with the floating-point register values @@ -102,9 +192,7 @@ supply_fpregset (struct regcache *regcache, const fpregset_t *regp) { int i; for (i = 0; i < S390_NUM_REGS; i++) - if (regmap_fpregset[i] != -1) - regcache_raw_supply (regcache, i, - (const char *)regp + regmap_fpregset[i]); + s390_native_supply (regcache, i, (const gdb_byte *) regp, regmap_fpregset); } /* Fill register REGNO (if it is a general-purpose register) in @@ -115,10 +203,8 @@ fill_fpregset (const struct regcache *regcache, fpregset_t *regp, int regno) { int i; for (i = 0; i < S390_NUM_REGS; i++) - if (regmap_fpregset[i] != -1) - if (regno == -1 || regno == i) - regcache_raw_collect (regcache, i, - (char *)regp + regmap_fpregset[i]); + if (regno == -1 || regno == i) + s390_native_collect (regcache, i, (gdb_byte *) regp, regmap_fpregset); } /* Find the TID for the current inferior thread to use with ptrace. */ |