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/gdbserver/linux-s390-low.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/gdbserver/linux-s390-low.c')
-rw-r--r-- | gdb/gdbserver/linux-s390-low.c | 74 |
1 files changed, 54 insertions, 20 deletions
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c index 5c38e43..898b757 100644 --- a/gdb/gdbserver/linux-s390-low.c +++ b/gdb/gdbserver/linux-s390-low.c @@ -126,16 +126,27 @@ s390_collect_ptrace_register (struct regcache *regcache, int regno, char *buf) collect_register (regcache, (regno & ~1) + 1, buf + sizeof (long) - size); } - else if (regaddr == PT_PSWADDR - || (regaddr >= PT_GPR0 && regaddr <= PT_GPR15)) + else if (regaddr == PT_PSWMASK) + { + /* Convert 4-byte PSW mask to 8 bytes by clearing bit 12 and copying + the basic addressing mode bit from the PSW address. */ + char *addr = alloca (register_size (regno ^ 1)); + collect_register (regcache, regno, buf); + collect_register (regcache, regno ^ 1, addr); + buf[1] &= ~0x8; + buf[size] |= (addr[0] & 0x80); + } + else if (regaddr == PT_PSWADDR) + { + /* Convert 4-byte PSW address to 8 bytes by clearing the addressing + mode bit (which gets copied to the PSW mask instead). */ + collect_register (regcache, regno, buf + sizeof (long) - size); + buf[sizeof (long) - size] &= ~0x80; + } + else if (regaddr >= PT_GPR0 && regaddr <= PT_GPR15) collect_register (regcache, regno, buf + sizeof (long) - size); else collect_register (regcache, regno, buf); - - /* When debugging a 32-bit inferior on a 64-bit host, make sure - the 31-bit addressing mode bit is set in the PSW mask. */ - if (regaddr == PT_PSWMASK) - buf[size] |= 0x80; } else collect_register (regcache, regno, buf); @@ -157,8 +168,35 @@ s390_supply_ptrace_register (struct regcache *regcache, supply_register (regcache, (regno & ~1) + 1, buf + sizeof (long) - size); } - else if (regaddr == PT_PSWADDR - || (regaddr >= PT_GPR0 && regaddr <= PT_GPR15)) + else if (regaddr == PT_PSWMASK) + { + /* Convert 8-byte PSW mask to 4 bytes by setting bit 12 and copying + the basic addressing mode into the PSW address. */ + char *mask = alloca (size); + char *addr = alloca (register_size (regno ^ 1)); + memcpy (mask, buf, size); + mask[1] |= 0x8; + supply_register (regcache, regno, mask); + + collect_register (regcache, regno ^ 1, addr); + addr[0] &= ~0x80; + addr[0] |= (buf[size] & 0x80); + supply_register (regcache, regno ^ 1, addr); + } + else if (regaddr == PT_PSWADDR) + { + /* Convert 8-byte PSW address to 4 bytes by truncating, but + keeping the addressing mode bit (which was set from the mask). */ + char *addr = alloca (size); + char amode; + collect_register (regcache, regno, addr); + amode = addr[0] & 0x80; + memcpy (addr, buf + sizeof (long) - size, size); + addr[0] &= ~0x80; + addr[0] |= amode; + supply_register (regcache, regno, addr); + } + else if (regaddr >= PT_GPR0 && regaddr <= PT_GPR15) supply_register (regcache, regno, buf + sizeof (long) - size); else supply_register (regcache, regno, buf); @@ -199,12 +237,9 @@ s390_get_pc (struct regcache *regcache) { if (register_size (0) == 4) { - unsigned int pc; - collect_register_by_name (regcache, "pswa", &pc); -#ifndef __s390x__ - pc &= 0x7fffffff; -#endif - return pc; + unsigned int pswa; + collect_register_by_name (regcache, "pswa", &pswa); + return pswa & 0x7fffffff; } else { @@ -219,11 +254,10 @@ s390_set_pc (struct regcache *regcache, CORE_ADDR newpc) { if (register_size (0) == 4) { - unsigned int pc = newpc; -#ifndef __s390x__ - pc |= 0x80000000; -#endif - supply_register_by_name (regcache, "pswa", &pc); + unsigned int pswa; + collect_register_by_name (regcache, "pswa", &pswa); + pswa = (pswa & 0x80000000) | (newpc & 0x7fffffff); + supply_register_by_name (regcache, "pswa", &pswa); } else { |