aboutsummaryrefslogtreecommitdiff
path: root/gdb/hppa-tdep.c
diff options
context:
space:
mode:
authorJim Kingdon <jkingdon@engr.sgi.com>1993-07-30 20:49:52 +0000
committerJim Kingdon <jkingdon@engr.sgi.com>1993-07-30 20:49:52 +0000
commit6cfec92912878589b836fc275d02070f5b8c23d2 (patch)
tree59baf34968fc5d17229be07612e81f1e3186d873 /gdb/hppa-tdep.c
parenta4fbb03e2da5efd227faaa04a8a9b16a58253870 (diff)
downloadgdb-6cfec92912878589b836fc275d02070f5b8c23d2.zip
gdb-6cfec92912878589b836fc275d02070f5b8c23d2.tar.gz
gdb-6cfec92912878589b836fc275d02070f5b8c23d2.tar.bz2
From Jeffrey Law:
* tm-hppa.h (TARGET_WRITE_PC): Define. * hppa-tdep.c (hppa_fix_call_dummy): If in a syscall, then return the address of the dummy itself rather than the address of $$dyncall. (target_write_pc): New function to store a new PC.
Diffstat (limited to 'gdb/hppa-tdep.c')
-rw-r--r--gdb/hppa-tdep.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c
index 24701b1..c3842cf 100644
--- a/gdb/hppa-tdep.c
+++ b/gdb/hppa-tdep.c
@@ -817,6 +817,7 @@ hppa_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p)
{
CORE_ADDR dyncall_addr, sr4export_addr;
struct minimal_symbol *msymbol;
+ int flags = read_register (FLAGS_REGNUM);
msymbol = lookup_minimal_symbol ("$$dyncall", (struct objfile *) NULL);
if (msymbol == NULL)
@@ -837,7 +838,16 @@ hppa_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p)
write_register (22, pc);
- return dyncall_addr;
+ /* If we are in a syscall, then we should call the stack dummy
+ directly. $$dyncall is not needed as the kernel sets up the
+ space id registers properly based on the value in %r31. In
+ fact calling $$dyncall will not work because the value in %r22
+ will be clobbered on the syscall exit path. */
+ if (flags & 2)
+ return pc;
+ else
+ return dyncall_addr;
+
}
/* Get the PC from %r31 if currently in a syscall. Also mask out privilege
@@ -852,6 +862,23 @@ target_read_pc ()
return read_register (PC_REGNUM) & ~0x3;
}
+/* Write out the PC. If currently in a syscall, then also write the new
+ PC value into %r31. */
+void
+target_write_pc (v)
+ CORE_ADDR v;
+{
+ int flags = read_register (FLAGS_REGNUM);
+
+ /* If in a syscall, then set %r31. Also make sure to get the
+ privilege bits set correctly. */
+ if (flags & 2)
+ write_register (31, (long) (v | 0x3));
+
+ write_register (PC_REGNUM, (long) v);
+ write_register (NPC_REGNUM, (long) v + 4);
+}
+
/* return the alignment of a type in bytes. Structures have the maximum
alignment required by their fields. */