summaryrefslogtreecommitdiff
path: root/gdb/gdbserver/linux-s390-low.c
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2011-11-30 16:06:55 +0000
committerUlrich Weigand <uweigand@de.ibm.com>2011-11-30 16:06:55 +0000
commitd6db1fabccd61cdc0527cf7c701ae5cf7f277281 (patch)
tree1ee15269e26f8d23a2a607df2b02f2aff461bbad /gdb/gdbserver/linux-s390-low.c
parent1dd635acb8bfcf517fae1d3e21d312828efdb2b1 (diff)
downloadbinutils-gdb-d6db1fabccd61cdc0527cf7c701ae5cf7f277281.tar.gz
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.c74
1 files changed, 54 insertions, 20 deletions
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
index 5c38e434c11..898b7576843 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
{